2 Implements filebuffer interface functions.
4 Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved. <BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "TextEditor.h"
16 #include <Guid/FileSystemInfo.h>
17 #include <Library/FileHandleLib.h>
19 EFI_EDITOR_FILE_BUFFER FileBuffer
;
20 EFI_EDITOR_FILE_BUFFER FileBufferBackupVar
;
23 // for basic initialization of FileBuffer
25 EFI_EDITOR_FILE_BUFFER FileBufferConst
= {
54 // the whole edit area needs to be refreshed
56 BOOLEAN FileBufferNeedRefresh
;
59 // only the current line in edit area needs to be refresh
61 BOOLEAN FileBufferOnlyLineNeedRefresh
;
63 BOOLEAN FileBufferMouseNeedRefresh
;
65 extern BOOLEAN EditorMouseAction
;
68 Initialization function for FileBuffer.
70 @param EFI_SUCCESS The initialization was successful.
71 @param EFI_LOAD_ERROR A default name could not be created.
72 @param EFI_OUT_OF_RESOURCES A memory allocation failed.
81 // basically initialize the FileBuffer
83 CopyMem (&FileBuffer
, &FileBufferConst
, sizeof (EFI_EDITOR_FILE_BUFFER
));
84 CopyMem (&FileBufferBackupVar
, &FileBufferConst
, sizeof (EFI_EDITOR_FILE_BUFFER
));
87 // set default FileName
89 FileBuffer
.FileName
= EditGetDefaultFileName (L
"txt");
90 if (FileBuffer
.FileName
== NULL
) {
91 return EFI_LOAD_ERROR
;
94 FileBuffer
.ListHead
= AllocateZeroPool (sizeof (LIST_ENTRY
));
95 if (FileBuffer
.ListHead
== NULL
) {
96 return EFI_OUT_OF_RESOURCES
;
99 InitializeListHead (FileBuffer
.ListHead
);
101 FileBuffer
.DisplayPosition
.Row
= 2;
102 FileBuffer
.DisplayPosition
.Column
= 1;
103 FileBuffer
.LowVisibleRange
.Row
= 2;
104 FileBuffer
.LowVisibleRange
.Column
= 1;
106 FileBufferNeedRefresh
= FALSE
;
107 FileBufferMouseNeedRefresh
= FALSE
;
108 FileBufferOnlyLineNeedRefresh
= FALSE
;
114 Backup function for FileBuffer. Only backup the following items:
115 Mouse/Cursor position
116 File Name, Type, ReadOnly, Modified
119 This is for making the file buffer refresh as few as possible.
121 @retval EFI_SUCCESS The backup operation was successful.
129 FileBufferBackupVar
.MousePosition
= FileBuffer
.MousePosition
;
131 SHELL_FREE_NON_NULL (FileBufferBackupVar
.FileName
);
132 FileBufferBackupVar
.FileName
= NULL
;
133 FileBufferBackupVar
.FileName
= StrnCatGrow (&FileBufferBackupVar
.FileName
, NULL
, FileBuffer
.FileName
, 0);
135 FileBufferBackupVar
.ModeInsert
= FileBuffer
.ModeInsert
;
136 FileBufferBackupVar
.FileType
= FileBuffer
.FileType
;
138 FileBufferBackupVar
.FilePosition
= FileBuffer
.FilePosition
;
139 FileBufferBackupVar
.LowVisibleRange
= FileBuffer
.LowVisibleRange
;
141 FileBufferBackupVar
.FileModified
= FileBuffer
.FileModified
;
142 FileBufferBackupVar
.ReadOnly
= FileBuffer
.ReadOnly
;
148 Advance to the next Count lines
150 @param[in] Count The line number to advance by.
151 @param[in] CurrentLine The pointer to the current line structure.
152 @param[in] LineList The pointer to the linked list of lines.
154 @retval NULL There was an error.
155 @return The line structure after the advance.
159 InternalEditorMiscLineAdvance (
160 IN CONST UINTN Count
,
161 IN CONST EFI_EDITOR_LINE
*CurrentLine
,
162 IN CONST LIST_ENTRY
*LineList
167 CONST EFI_EDITOR_LINE
*Line
;
169 if (CurrentLine
== NULL
|| LineList
== NULL
) {
173 for (Line
= CurrentLine
, Index
= 0; Index
< Count
; Index
++) {
175 // if already last line
177 if (Line
->Link
.ForwardLink
== LineList
) {
181 Line
= CR (Line
->Link
.ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
184 return ((EFI_EDITOR_LINE
*)Line
);
188 Retreat to the previous Count lines.
190 @param[in] Count The line number to retreat by.
191 @param[in] CurrentLine The pointer to the current line structure.
192 @param[in] LineList The pointer to the linked list of lines.
194 @retval NULL There was an error.
195 @return The line structure after the retreat.
199 InternalEditorMiscLineRetreat (
200 IN CONST UINTN Count
,
201 IN CONST EFI_EDITOR_LINE
*CurrentLine
,
202 IN CONST LIST_ENTRY
*LineList
207 CONST EFI_EDITOR_LINE
*Line
;
209 if (CurrentLine
== NULL
|| LineList
== NULL
) {
213 for (Line
= CurrentLine
, Index
= 0; Index
< Count
; Index
++) {
215 // already the first line
217 if (Line
->Link
.BackLink
== LineList
) {
221 Line
= CR (Line
->Link
.BackLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
224 return ((EFI_EDITOR_LINE
*)Line
);
228 Advance/Retreat lines
230 @param[in] Count line number to advance/retreat
234 @retval NULL An error occured.
235 @return The line after advance/retreat.
242 EFI_EDITOR_LINE
*Line
;
246 // if < 0, then retreat
247 // if > 0, the advance
250 AbsCount
= (UINTN
)ABS(Count
);
251 Line
= InternalEditorMiscLineRetreat (AbsCount
,MainEditor
.FileBuffer
->CurrentLine
,MainEditor
.FileBuffer
->ListHead
);
253 Line
= InternalEditorMiscLineAdvance ((UINTN
)Count
,MainEditor
.FileBuffer
->CurrentLine
,MainEditor
.FileBuffer
->ListHead
);
260 Function to update the 'screen' to display the mouse position.
262 @retval EFI_SUCCESS The backup operation was successful.
266 FileBufferRestoreMousePosition (
270 EFI_EDITOR_COLOR_UNION Orig
;
271 EFI_EDITOR_COLOR_UNION New
;
274 BOOLEAN HasCharacter
;
275 EFI_EDITOR_LINE
*CurrentLine
;
276 EFI_EDITOR_LINE
*Line
;
280 // variable initialization
284 if (MainEditor
.MouseSupported
) {
286 if (FileBufferMouseNeedRefresh
) {
288 FileBufferMouseNeedRefresh
= FALSE
;
291 // if mouse position not moved and only mouse action
292 // so do not need to refresh mouse position
294 if ((FileBuffer
.MousePosition
.Row
== FileBufferBackupVar
.MousePosition
.Row
&&
295 FileBuffer
.MousePosition
.Column
== FileBufferBackupVar
.MousePosition
.Column
)
296 && EditorMouseAction
) {
300 // backup the old screen attributes
302 Orig
= MainEditor
.ColorAttributes
;
304 New
.Colors
.Foreground
= Orig
.Colors
.Background
;
305 New
.Colors
.Background
= Orig
.Colors
.Foreground
;
308 // clear the old mouse position
310 FRow
= FileBuffer
.LowVisibleRange
.Row
+ FileBufferBackupVar
.MousePosition
.Row
- 2;
312 FColumn
= FileBuffer
.LowVisibleRange
.Column
+ FileBufferBackupVar
.MousePosition
.Column
- 1;
315 if (FRow
> FileBuffer
.NumLines
) {
316 HasCharacter
= FALSE
;
318 CurrentLine
= FileBuffer
.CurrentLine
;
319 Line
= MoveLine (FRow
- FileBuffer
.FilePosition
.Row
);
321 if (Line
== NULL
|| FColumn
> Line
->Size
) {
322 HasCharacter
= FALSE
;
325 FileBuffer
.CurrentLine
= CurrentLine
;
329 (INT32
)FileBufferBackupVar
.MousePosition
.Column
- 1,
330 (INT32
)FileBufferBackupVar
.MousePosition
.Row
- 1,
335 Value
= (Line
->Buffer
[FColumn
- 1]);
337 (INT32
)FileBufferBackupVar
.MousePosition
.Column
- 1,
338 (INT32
)FileBufferBackupVar
.MousePosition
.Row
- 1,
344 // set the new mouse position
346 gST
->ConOut
->SetAttribute (gST
->ConOut
, New
.Data
);
349 // clear the old mouse position
351 FRow
= FileBuffer
.LowVisibleRange
.Row
+ FileBuffer
.MousePosition
.Row
- 2;
352 FColumn
= FileBuffer
.LowVisibleRange
.Column
+ FileBuffer
.MousePosition
.Column
- 1;
355 if (FRow
> FileBuffer
.NumLines
) {
356 HasCharacter
= FALSE
;
358 CurrentLine
= FileBuffer
.CurrentLine
;
359 Line
= MoveLine (FRow
- FileBuffer
.FilePosition
.Row
);
361 if (Line
== NULL
|| FColumn
> Line
->Size
) {
362 HasCharacter
= FALSE
;
365 FileBuffer
.CurrentLine
= CurrentLine
;
369 (INT32
)FileBuffer
.MousePosition
.Column
- 1,
370 (INT32
)FileBuffer
.MousePosition
.Row
- 1,
375 Value
= Line
->Buffer
[FColumn
- 1];
377 (INT32
)FileBuffer
.MousePosition
.Column
- 1,
378 (INT32
)FileBuffer
.MousePosition
.Row
- 1,
384 // end of HasCharacter
386 gST
->ConOut
->SetAttribute (gST
->ConOut
, Orig
.Data
);
389 // end of MouseNeedRefresh
393 // end of MouseSupported
399 Free all the lines in FileBuffer
406 @retval EFI_SUCCESS The operation was successful.
410 FileBufferFreeLines (
415 EFI_EDITOR_LINE
*Line
;
418 // free all the lines
420 if (FileBuffer
.Lines
!= NULL
) {
422 Line
= FileBuffer
.Lines
;
423 Link
= &(Line
->Link
);
425 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
426 Link
= Link
->ForwardLink
;
429 // free line's buffer and line itself
432 } while (Link
!= FileBuffer
.ListHead
);
435 // clean the line list related structure
437 FileBuffer
.Lines
= NULL
;
438 FileBuffer
.CurrentLine
= NULL
;
439 FileBuffer
.NumLines
= 0;
441 FileBuffer
.ListHead
->ForwardLink
= FileBuffer
.ListHead
;
442 FileBuffer
.ListHead
->BackLink
= FileBuffer
.ListHead
;
448 Cleanup function for FileBuffer.
450 @retval EFI_SUCCESS The cleanup was successful.
460 SHELL_FREE_NON_NULL (FileBuffer
.FileName
);
463 // free all the lines
465 Status
= FileBufferFreeLines ();
467 SHELL_FREE_NON_NULL (FileBuffer
.ListHead
);
468 FileBuffer
.ListHead
= NULL
;
470 SHELL_FREE_NON_NULL (FileBufferBackupVar
.FileName
);
476 Print a line specified by Line on a row specified by Row of the screen.
478 @param[in] Line The line to print.
479 @param[in] Row The row on the screen to print onto (begin from 1).
481 @retval EFI_SUCCESS The printing was successful.
484 FileBufferPrintLine (
485 IN CONST EFI_EDITOR_LINE
*Line
,
492 CHAR16 PrintLine
[200];
493 CHAR16 PrintLine2
[250];
496 // print start from correct character
498 Buffer
= Line
->Buffer
+ FileBuffer
.LowVisibleRange
.Column
- 1;
500 Limit
= Line
->Size
- FileBuffer
.LowVisibleRange
.Column
+ 1;
501 if (Limit
> Line
->Size
) {
505 StrnCpy (PrintLine
, Buffer
, MIN(MIN(Limit
,MainEditor
.ScreenSize
.Column
), 200));
506 for (; Limit
< MainEditor
.ScreenSize
.Column
; Limit
++) {
507 PrintLine
[Limit
] = L
' ';
510 PrintLine
[MainEditor
.ScreenSize
.Column
] = CHAR_NULL
;
511 ShellCopySearchAndReplace(PrintLine
, PrintLine2
, 250, L
"%", L
"^%", FALSE
, FALSE
);
524 Set the cursor position according to FileBuffer.DisplayPosition.
526 @retval EFI_SUCCESS The operation was successful.
530 FileBufferRestorePosition (
535 // set cursor position
537 return (gST
->ConOut
->SetCursorPosition (
539 FileBuffer
.DisplayPosition
.Column
- 1,
540 FileBuffer
.DisplayPosition
.Row
- 1
545 Refresh the screen with whats in the buffer.
547 @retval EFI_SUCCESS The refresh was successful.
548 @retval EFI_LOAD_ERROR There was an error finding what to write.
557 EFI_EDITOR_LINE
*Line
;
561 // if it's the first time after editor launch, so should refresh
565 // no definite required refresh
566 // and file position displayed on screen has not been changed
568 if (!FileBufferNeedRefresh
&&
569 !FileBufferOnlyLineNeedRefresh
&&
570 FileBufferBackupVar
.LowVisibleRange
.Row
== FileBuffer
.LowVisibleRange
.Row
&&
571 FileBufferBackupVar
.LowVisibleRange
.Column
== FileBuffer
.LowVisibleRange
.Column
574 FileBufferRestoreMousePosition ();
575 FileBufferRestorePosition ();
581 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
584 // only need to refresh current line
586 if (FileBufferOnlyLineNeedRefresh
&&
587 FileBufferBackupVar
.LowVisibleRange
.Row
== FileBuffer
.LowVisibleRange
.Row
&&
588 FileBufferBackupVar
.LowVisibleRange
.Column
== FileBuffer
.LowVisibleRange
.Column
591 EditorClearLine (FileBuffer
.DisplayPosition
.Row
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
);
592 FileBufferPrintLine (
593 FileBuffer
.CurrentLine
,
594 FileBuffer
.DisplayPosition
.Row
598 // the whole edit area need refresh
604 if (FileBuffer
.Lines
== NULL
) {
605 FileBufferRestoreMousePosition ();
606 FileBufferRestorePosition ();
607 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
612 // get the first line that will be displayed
614 Line
= MoveLine (FileBuffer
.LowVisibleRange
.Row
- FileBuffer
.FilePosition
.Row
);
616 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
618 return EFI_LOAD_ERROR
;
621 Link
= &(Line
->Link
);
624 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
629 FileBufferPrintLine (Line
, Row
);
631 Link
= Link
->ForwardLink
;
633 } while (Link
!= FileBuffer
.ListHead
&& Row
<= (MainEditor
.ScreenSize
.Row
- 1));
635 // while not file end and not screen full
637 while (Row
<= (MainEditor
.ScreenSize
.Row
- 1)) {
638 EditorClearLine (Row
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
);
643 FileBufferRestoreMousePosition ();
644 FileBufferRestorePosition ();
646 FileBufferNeedRefresh
= FALSE
;
647 FileBufferOnlyLineNeedRefresh
= FALSE
;
649 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
654 Create a new line and append it to the line list.
659 @retval NULL The create line failed.
660 @return The line created.
664 FileBufferCreateLine (
668 EFI_EDITOR_LINE
*Line
;
671 // allocate a line structure
673 Line
= AllocateZeroPool (sizeof (EFI_EDITOR_LINE
));
678 // initialize the structure
680 Line
->Signature
= LINE_LIST_SIGNATURE
;
683 Line
->Type
= NewLineTypeDefault
;
686 // initial buffer of the line is "\0"
688 ASSERT(CHAR_NULL
== CHAR_NULL
);
689 Line
->Buffer
= CatSPrint (NULL
, L
"\0");
690 if (Line
->Buffer
== NULL
) {
694 FileBuffer
.NumLines
++;
697 // insert the line into line list
699 InsertTailList (FileBuffer
.ListHead
, &Line
->Link
);
701 if (FileBuffer
.Lines
== NULL
) {
702 FileBuffer
.Lines
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
709 Set FileName field in FileBuffer.
711 @param Str The file name to set.
713 @retval EFI_SUCCESS The filename was successfully set.
714 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
715 @retval EFI_INVALID_PARAMETER Str is not a valid filename.
719 FileBufferSetFileName (
724 // Verify the parameters
726 if (!IsValidFileName(Str
)) {
727 return (EFI_INVALID_PARAMETER
);
730 // free the old file name
732 SHELL_FREE_NON_NULL (FileBuffer
.FileName
);
735 // Allocate and set the new name
737 FileBuffer
.FileName
= CatSPrint (NULL
, L
"%s", Str
);
738 if (FileBuffer
.FileName
== NULL
) {
739 return EFI_OUT_OF_RESOURCES
;
745 Free the existing file lines and reset the modified flag.
747 @retval EFI_SUCCESS The operation was successful.
756 // free all the lines
758 FileBufferFreeLines ();
759 FileBuffer
.FileModified
= FALSE
;
766 Read a file from disk into the FileBuffer.
768 @param[in] FileName The filename to read.
769 @param[in] Recover TRUE if is for recover mode, no information printouts.
771 @retval EFI_SUCCESS The load was successful.
772 @retval EFI_LOAD_ERROR The load failed.
773 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
774 @retval EFI_INVALID_PARAMETER FileName is a directory.
779 IN CONST CHAR16
*FileName
,
780 IN CONST BOOLEAN Recover
783 EFI_EDITOR_LINE
*Line
;
784 EE_NEWLINE_TYPE Type
;
789 CHAR16
*UnicodeBuffer
;
792 SHELL_FILE_HANDLE FileHandle
;
795 UINTN LineSizeBackup
;
801 UnicodeBuffer
= NULL
;
802 Type
= NewLineTypeDefault
;
807 // in this function, when you return error ( except EFI_OUT_OF_RESOURCES )
808 // you should set status string via StatusBarSetStatusString(L"blah")
809 // since this function maybe called before the editorhandleinput loop
810 // so any error will cause editor return
811 // so if you want to print the error status
812 // you should set the status string
816 // try to open the file
818 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
, 0);
820 if (!EFI_ERROR(Status
)) {
822 if (FileHandle
== NULL
) {
823 StatusBarSetStatusString (L
"Disk Error");
824 return EFI_LOAD_ERROR
;
827 Info
= ShellGetFileInfo(FileHandle
);
829 if (Info
->Attribute
& EFI_FILE_DIRECTORY
) {
830 StatusBarSetStatusString (L
"Directory Can Not Be Edited");
832 return EFI_INVALID_PARAMETER
;
835 if (Info
->Attribute
& EFI_FILE_READ_ONLY
) {
836 FileBuffer
.ReadOnly
= TRUE
;
838 FileBuffer
.ReadOnly
= FALSE
;
843 FileSize
= (UINTN
) Info
->FileSize
;
846 } else if (Status
== EFI_NOT_FOUND
) {
848 // file not exists. add create and try again
850 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
|EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_CREATE
, 0);
851 if (EFI_ERROR (Status
)) {
852 if (Status
== EFI_WRITE_PROTECTED
||
853 Status
== EFI_ACCESS_DENIED
||
854 Status
== EFI_NO_MEDIA
||
855 Status
== EFI_MEDIA_CHANGED
857 StatusBarSetStatusString (L
"Access Denied");
858 } else if (Status
== EFI_DEVICE_ERROR
|| Status
== EFI_VOLUME_CORRUPTED
|| Status
== EFI_VOLUME_FULL
) {
859 StatusBarSetStatusString (L
"Disk Error");
861 StatusBarSetStatusString (L
"Invalid File Name or Current-working-directory");
867 // it worked. now delete it and move on with the name (now validated)
869 Status
= ShellDeleteFile (&FileHandle
);
870 if (Status
== EFI_WARN_DELETE_FAILURE
) {
871 Status
= EFI_ACCESS_DENIED
;
874 if (EFI_ERROR (Status
)) {
875 StatusBarSetStatusString (L
"Access Denied");
880 // file doesn't exist, so set CreateFile to TRUE
883 FileBuffer
.ReadOnly
= FALSE
;
886 // all the check ends
887 // so now begin to set file name, free lines
889 if (StrCmp (FileName
, FileBuffer
.FileName
) != 0) {
890 FileBufferSetFileName (FileName
);
893 // free the old lines
903 // allocate buffer to read file
905 Buffer
= AllocateZeroPool (FileSize
);
906 if (Buffer
== NULL
) {
907 return EFI_OUT_OF_RESOURCES
;
910 // read file into Buffer
912 Status
= ShellReadFile (FileHandle
, &FileSize
, Buffer
);
913 ShellCloseFile(&FileHandle
);
915 if (EFI_ERROR (Status
)) {
916 StatusBarSetStatusString (L
"Read File Failed");
917 SHELL_FREE_NON_NULL (Buffer
);
918 return EFI_LOAD_ERROR
;
921 // nothing in this file
924 SHELL_FREE_NON_NULL (Buffer
);
926 // since has no head, so only can be an ASCII file
928 FileBuffer
.FileType
= FileTypeAscii
;
933 AsciiBuffer
= Buffer
;
937 // size < Unicode file header, so only can be ASCII file
939 FileBuffer
.FileType
= FileTypeAscii
;
944 if (*(UINT16
*) Buffer
== EFI_UNICODE_BYTE_ORDER_MARK
) {
946 // Unicode file's size should be even
948 if ((FileSize
% 2) != 0) {
949 StatusBarSetStatusString (L
"File Format Wrong");
950 SHELL_FREE_NON_NULL (Buffer
);
951 return EFI_LOAD_ERROR
;
956 FileBuffer
.FileType
= FileTypeUnicode
;
957 UnicodeBuffer
= Buffer
;
960 // pass this 0xff and 0xfe
965 FileBuffer
.FileType
= FileTypeAscii
;
968 // end of AsciiBuffer ==
972 // end of FileSize < 2
973 // all the check ends
974 // so now begin to set file name, free lines
976 if (StrCmp (FileName
, FileBuffer
.FileName
) != 0) {
977 FileBufferSetFileName (FileName
);
981 // free the old lines
986 // parse file content line by line
988 for (LoopVar1
= 0; LoopVar1
< FileSize
; LoopVar1
++) {
989 Type
= NewLineTypeUnknown
;
991 for (LineSize
= LoopVar1
; LineSize
< FileSize
; LineSize
++) {
992 if (FileBuffer
.FileType
== FileTypeAscii
) {
993 if (AsciiBuffer
[LineSize
] == CHAR_CARRIAGE_RETURN
) {
994 Type
= NewLineTypeCarriageReturn
;
999 if (LineSize
< FileSize
- 1) {
1000 if (AsciiBuffer
[LineSize
+ 1] == CHAR_LINEFEED
) {
1001 Type
= NewLineTypeCarriageReturnLineFeed
;
1006 } else if (AsciiBuffer
[LineSize
] == CHAR_LINEFEED
) {
1007 Type
= NewLineTypeLineFeed
;
1012 if (LineSize
< FileSize
- 1) {
1013 if (AsciiBuffer
[LineSize
+ 1] == CHAR_CARRIAGE_RETURN
) {
1014 Type
= NewLineTypeLineFeedCarriageReturn
;
1021 if (UnicodeBuffer
[LineSize
] == CHAR_CARRIAGE_RETURN
) {
1022 Type
= NewLineTypeCarriageReturn
;
1027 if (LineSize
< FileSize
- 1) {
1028 if (UnicodeBuffer
[LineSize
+ 1] == CHAR_LINEFEED
) {
1029 Type
= NewLineTypeCarriageReturnLineFeed
;
1034 } else if (UnicodeBuffer
[LineSize
] == CHAR_LINEFEED
) {
1035 Type
= NewLineTypeLineFeed
;
1040 if (LineSize
< FileSize
- 1) {
1041 if (UnicodeBuffer
[LineSize
+ 1] == CHAR_CARRIAGE_RETURN
) {
1042 Type
= NewLineTypeLineFeedCarriageReturn
;
1054 // end of for LineSize
1056 // if the type is wrong, then exit
1058 if (Type
== NewLineTypeUnknown
) {
1060 // Now if Type is NewLineTypeUnknown, it should be file end
1062 Type
= NewLineTypeDefault
;
1065 LineSizeBackup
= LineSize
;
1068 // create a new line
1070 Line
= FileBufferCreateLine ();
1072 SHELL_FREE_NON_NULL (Buffer
);
1073 return EFI_OUT_OF_RESOURCES
;
1076 // calculate file length
1078 LineSize
-= LoopVar1
;
1081 // Unicode and one CHAR_NULL
1083 SHELL_FREE_NON_NULL (Line
->Buffer
);
1084 Line
->Buffer
= AllocateZeroPool (LineSize
* 2 + 2);
1086 if (Line
->Buffer
== NULL
) {
1087 RemoveEntryList (&Line
->Link
);
1088 return EFI_OUT_OF_RESOURCES
;
1091 // copy this line to Line->Buffer
1093 for (LoopVar2
= 0; LoopVar2
< LineSize
; LoopVar2
++) {
1094 if (FileBuffer
.FileType
== FileTypeAscii
) {
1095 Line
->Buffer
[LoopVar2
] = (CHAR16
) AsciiBuffer
[LoopVar1
];
1097 Line
->Buffer
[LoopVar2
] = UnicodeBuffer
[LoopVar1
];
1103 // LoopVar1 now points to where CHAR_CARRIAGE_RETURN or CHAR_LINEFEED;
1105 Line
->Buffer
[LineSize
] = 0;
1107 Line
->Size
= LineSize
;
1108 Line
->TotalSize
= LineSize
;
1111 if (Type
== NewLineTypeCarriageReturnLineFeed
|| Type
== NewLineTypeLineFeedCarriageReturn
) {
1116 // last character is a return, SO create a new line
1118 if (((Type
== NewLineTypeCarriageReturnLineFeed
|| Type
== NewLineTypeLineFeedCarriageReturn
) && LineSizeBackup
== FileSize
- 2) ||
1119 ((Type
== NewLineTypeLineFeed
|| Type
== NewLineTypeCarriageReturn
) && LineSizeBackup
== FileSize
- 1)
1121 Line
= FileBufferCreateLine ();
1123 SHELL_FREE_NON_NULL (Buffer
);
1124 return EFI_OUT_OF_RESOURCES
;
1134 SHELL_FREE_NON_NULL (Buffer
);
1138 // end of if CreateFile
1142 FileBuffer
.DisplayPosition
.Row
= 2;
1143 FileBuffer
.DisplayPosition
.Column
= 1;
1144 FileBuffer
.LowVisibleRange
.Row
= 1;
1145 FileBuffer
.LowVisibleRange
.Column
= 1;
1146 FileBuffer
.FilePosition
.Row
= 1;
1147 FileBuffer
.FilePosition
.Column
= 1;
1148 FileBuffer
.MousePosition
.Row
= 2;
1149 FileBuffer
.MousePosition
.Column
= 1;
1152 UnicodeBuffer
= CatSPrint (NULL
, L
"%d Lines Read", FileBuffer
.NumLines
);
1153 if (UnicodeBuffer
== NULL
) {
1154 return EFI_OUT_OF_RESOURCES
;
1157 StatusBarSetStatusString (UnicodeBuffer
);
1158 FreePool (UnicodeBuffer
);
1162 // check whether we have fs?: in filename
1165 FSMappingPtr = NULL;
1166 while (FileName[LoopVar1] != 0) {
1167 if (FileName[LoopVar1] == L':') {
1168 FSMappingPtr = &FileName[LoopVar1];
1175 if (FSMappingPtr == NULL) {
1176 CurDir = ShellGetCurrentDir (NULL);
1180 while (FileName[LoopVar1] != 0) {
1181 if (FileName[LoopVar1] == L':') {
1185 FSMapping[LoopVar2++] = FileName[LoopVar1];
1190 FSMapping[LoopVar2] = 0;
1191 CurDir = ShellGetCurrentDir (FSMapping);
1194 if (CurDir != NULL) {
1195 for (LoopVar1 = 0; LoopVar1 < StrLen (CurDir) && CurDir[LoopVar1] != ':'; LoopVar1++);
1197 CurDir[LoopVar1] = 0;
1198 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) ShellGetMap (CurDir);
1201 return EFI_LOAD_ERROR;
1204 Status = LibDevicePathToInterface (
1205 &gEfiSimpleFileSystemProtocolGuid,
1209 if (EFI_ERROR (Status)) {
1210 return EFI_LOAD_ERROR;
1213 Status = Vol->OpenVolume (Vol, &RootFs);
1214 if (EFI_ERROR (Status)) {
1215 return EFI_LOAD_ERROR;
1218 // Get volume information of file system
1220 Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + 100;
1221 VolumeInfo = (EFI_FILE_SYSTEM_INFO *) AllocateZeroPool (Size);
1222 Status = RootFs->GetInfo (RootFs, &gEfiFileSystemInfoGuid, &Size, VolumeInfo);
1223 if (EFI_ERROR (Status)) {
1224 RootFs->Close (RootFs);
1225 return EFI_LOAD_ERROR;
1228 if (VolumeInfo->ReadOnly) {
1229 StatusBarSetStatusString (L"WARNING: Volume Read Only");
1232 FreePool (VolumeInfo);
1233 RootFs->Close (RootFs);
1240 if (FileBuffer
.Lines
!= 0) {
1241 FileBuffer
.CurrentLine
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1244 // create a dummy line
1246 Line
= FileBufferCreateLine ();
1248 return EFI_OUT_OF_RESOURCES
;
1251 FileBuffer
.CurrentLine
= Line
;
1254 FileBuffer
.FileModified
= FALSE
;
1255 FileBufferNeedRefresh
= TRUE
;
1256 FileBufferOnlyLineNeedRefresh
= FALSE
;
1257 FileBufferMouseNeedRefresh
= TRUE
;
1264 According to FileBuffer.NewLineType & FileBuffer.FileType,
1265 get the return buffer and size.
1267 @param[in] Type The type of line.
1268 @param[out] Buffer The buffer to fill.
1269 @param[out] Size The amount of the buffer used on return.
1274 IN CONST EE_NEWLINE_TYPE Type
,
1282 // give new line buffer,
1283 // and will judge unicode or ascii
1288 // not legal new line type
1290 if (Type
!= NewLineTypeLineFeed
&& Type
!= NewLineTypeCarriageReturn
&& Type
!= NewLineTypeCarriageReturnLineFeed
&& Type
!= NewLineTypeLineFeedCarriageReturn
) {
1295 // use_cr: give 0x0d
1297 if (Type
== NewLineTypeCarriageReturn
) {
1298 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1307 *Size
= NewLineSize
;
1311 // use_lf: give 0x0a
1313 if (Type
== NewLineTypeLineFeed
) {
1314 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1323 *Size
= NewLineSize
;
1327 // use_crlf: give 0x0d 0x0a
1329 if (Type
== NewLineTypeCarriageReturnLineFeed
) {
1330 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1343 *Size
= NewLineSize
;
1347 // use_lfcr: give 0x0a 0x0d
1349 if (Type
== NewLineTypeLineFeedCarriageReturn
) {
1350 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1363 *Size
= NewLineSize
;
1370 Change a Unicode string to an ASCII string.
1372 @param[in] UStr The Unicode string.
1373 @param[in] Length The maximum size of AStr.
1374 @param[out] AStr ASCII string to pass out.
1376 @return The actuall length.
1381 IN CONST CHAR16
*UStr
,
1382 IN CONST UINTN Length
,
1389 // just buffer copy, not character copy
1391 for (Index
= 0; Index
< Length
; Index
++) {
1392 *AStr
++ = (CHAR8
) *UStr
++;
1399 Save lines in FileBuffer to disk
1401 @param[in] FileName The file name for writing.
1403 @retval EFI_SUCCESS Data was written.
1404 @retval EFI_LOAD_ERROR
1405 @retval EFI_OUT_OF_RESOURCES There were not enough resources to write the file.
1410 IN CONST CHAR16
*FileName
1413 SHELL_FILE_HANDLE FileHandle
;
1415 EFI_EDITOR_LINE
*Line
;
1421 CHAR8 NewLineBuffer
[4];
1424 EFI_FILE_INFO
*Info
;
1428 EE_NEWLINE_TYPE Type
;
1443 TotalSize
= 0x200000;
1450 // if is the old file
1452 if (FileBuffer
.FileName
!= NULL
&& StrCmp (FileName
, FileBuffer
.FileName
) == 0) {
1454 // file has not been modified
1456 if (!FileBuffer
.FileModified
) {
1461 // if file is read-only, set error
1463 if (FileBuffer
.ReadOnly
) {
1464 StatusBarSetStatusString (L
"Read Only File Can Not Be Saved");
1469 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
|EFI_FILE_MODE_WRITE
, 0);
1471 if (!EFI_ERROR (Status
)) {
1472 Info
= ShellGetFileInfo(FileHandle
);
1474 if (Info
!= NULL
&& Info
->Attribute
& EFI_FILE_DIRECTORY
) {
1475 StatusBarSetStatusString (L
"Directory Can Not Be Saved");
1476 ShellCloseFile(FileHandle
);
1478 return EFI_LOAD_ERROR
;
1482 Attribute
= Info
->Attribute
& ~EFI_FILE_READ_ONLY
;
1487 // if file exits, so delete it
1489 Status
= ShellDeleteFile (&FileHandle
);
1490 if (EFI_ERROR (Status
) || Status
== EFI_WARN_DELETE_FAILURE
) {
1491 StatusBarSetStatusString (L
"Write File Failed");
1492 return EFI_LOAD_ERROR
;
1496 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
|EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_CREATE
, Attribute
);
1498 if (EFI_ERROR (Status
)) {
1499 StatusBarSetStatusString (L
"Create File Failed");
1500 return EFI_LOAD_ERROR
;
1504 // if file is Unicode file, write Unicode header to it.
1506 if (FileBuffer
.FileType
== FileTypeUnicode
) {
1508 Status
= ShellWriteFile (FileHandle
, &Length
, (VOID
*)&gUnicodeFileTag
);
1509 if (EFI_ERROR (Status
)) {
1510 ShellDeleteFile (&FileHandle
);
1511 return EFI_LOAD_ERROR
;
1515 Cache
= AllocateZeroPool (TotalSize
);
1516 if (Cache
== NULL
) {
1517 ShellDeleteFile (&FileHandle
);
1518 return EFI_OUT_OF_RESOURCES
;
1522 // write all the lines back to disk
1525 Type
= NewLineTypeCarriageReturnLineFeed
;
1528 LeftSize
= TotalSize
;
1530 for (Link
= FileBuffer
.ListHead
->ForwardLink
; Link
!= FileBuffer
.ListHead
; Link
= Link
->ForwardLink
) {
1531 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1533 if (Line
->Type
!= NewLineTypeDefault
) {
1537 // newline character is at most 4 bytes ( two Unicode characters )
1540 if (Line
->Buffer
!= NULL
&& Line
->Size
!= 0) {
1541 if (FileBuffer
.FileType
== FileTypeAscii
) {
1542 Length
+= Line
->Size
;
1544 Length
+= (Line
->Size
* 2);
1547 // end if FileTypeAscii
1552 // no cache room left, so write cache to disk
1554 if (LeftSize
< Length
) {
1555 Size
= TotalSize
- LeftSize
;
1556 Status
= ShellWriteFile (FileHandle
, &Size
, Cache
);
1557 if (EFI_ERROR (Status
)) {
1558 ShellDeleteFile (&FileHandle
);
1560 return EFI_LOAD_ERROR
;
1563 LeftSize
= TotalSize
;
1566 if (Line
->Buffer
!= NULL
&& Line
->Size
!= 0) {
1567 if (FileBuffer
.FileType
== FileTypeAscii
) {
1568 UnicodeToAscii (Line
->Buffer
, Line
->Size
, Ptr
);
1569 Length
= Line
->Size
;
1571 Length
= (Line
->Size
* 2);
1572 CopyMem (Ptr
, (CHAR8
*) Line
->Buffer
, Length
);
1575 // end if FileTypeAscii
1582 // end of if Line -> Buffer != NULL && Line -> Size != 0
1584 // if not the last line , write return buffer to disk
1586 if (Link
->ForwardLink
!= FileBuffer
.ListHead
) {
1587 GetNewLine (Type
, NewLineBuffer
, &NewLineSize
);
1588 CopyMem (Ptr
, (CHAR8
*) NewLineBuffer
, NewLineSize
);
1591 LeftSize
-= NewLineSize
;
1597 if (TotalSize
!= LeftSize
) {
1598 Size
= TotalSize
- LeftSize
;
1599 Status
= ShellWriteFile (FileHandle
, &Size
, Cache
);
1600 if (EFI_ERROR (Status
)) {
1601 ShellDeleteFile (&FileHandle
);
1603 return EFI_LOAD_ERROR
;
1609 ShellCloseFile(&FileHandle
);
1611 FileBuffer
.FileModified
= FALSE
;
1614 // set status string
1616 Str
= CatSPrint (NULL
, L
"%d Lines Wrote", NumLines
);
1618 return EFI_OUT_OF_RESOURCES
;
1621 StatusBarSetStatusString (Str
);
1622 SHELL_FREE_NON_NULL (Str
);
1625 // now everything is ready , you can set the new file name to filebuffer
1627 if (FileName
!= NULL
&& FileBuffer
.FileName
!= NULL
&& StrCmp (FileName
, FileBuffer
.FileName
) != 0) {
1631 FileBufferSetFileName (FileName
);
1632 if (FileBuffer
.FileName
== NULL
) {
1633 ShellDeleteFile (&FileHandle
);
1634 return EFI_OUT_OF_RESOURCES
;
1638 FileBuffer
.ReadOnly
= FALSE
;
1643 Scroll cursor to left 1 character position.
1645 @retval EFI_SUCCESS The operation was successful.
1649 FileBufferScrollLeft (
1653 EFI_EDITOR_LINE
*Line
;
1657 Line
= FileBuffer
.CurrentLine
;
1659 FRow
= FileBuffer
.FilePosition
.Row
;
1660 FCol
= FileBuffer
.FilePosition
.Column
;
1663 // if already at start of this line, so move to the end of previous line
1667 // has previous line
1669 if (Line
->Link
.BackLink
!= FileBuffer
.ListHead
) {
1671 Line
= CR (Line
->Link
.BackLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1672 FCol
= Line
->Size
+ 1;
1678 // if not at start of this line, just move to previous column
1683 FileBufferMovePosition (FRow
, FCol
);
1689 Delete a char in line
1691 @param[in, out] Line The line to delete in.
1692 @param[in] Pos Position to delete the char at ( start from 0 ).
1697 IN OUT EFI_EDITOR_LINE
*Line
,
1704 // move the latter characters front
1706 for (Index
= Pos
- 1; Index
< Line
->Size
; Index
++) {
1707 Line
->Buffer
[Index
] = Line
->Buffer
[Index
+ 1];
1714 Concatenate Src into Dest.
1716 @param[in, out] Dest Destination string
1717 @param[in] Src Src String.
1722 IN OUT EFI_EDITOR_LINE
*Dest
,
1723 IN EFI_EDITOR_LINE
*Src
1731 Dest
->Buffer
[Size
] = 0;
1734 // concatenate the two strings
1736 Str
= CatSPrint (NULL
, L
"%s%s", Dest
->Buffer
, Src
->Buffer
);
1738 Dest
->Buffer
= NULL
;
1742 Dest
->Size
= Size
+ Src
->Size
;
1743 Dest
->TotalSize
= Dest
->Size
;
1745 FreePool (Dest
->Buffer
);
1746 FreePool (Src
->Buffer
);
1749 // put str to dest->buffer
1755 Delete the previous character.
1757 @retval EFI_SUCCESS The delete was successful.
1758 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1762 FileBufferDoBackspace (
1766 EFI_EDITOR_LINE
*Line
;
1767 EFI_EDITOR_LINE
*End
;
1771 FileColumn
= FileBuffer
.FilePosition
.Column
;
1773 Line
= FileBuffer
.CurrentLine
;
1778 if (FileColumn
== 1) {
1782 if (FileBuffer
.FilePosition
.Row
== 1) {
1786 FileBufferScrollLeft ();
1788 Line
= FileBuffer
.CurrentLine
;
1789 Link
= Line
->Link
.ForwardLink
;
1790 End
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1793 // concatenate this line with previous line
1795 LineCat (Line
, End
);
1796 if (Line
->Buffer
== NULL
) {
1797 return EFI_OUT_OF_RESOURCES
;
1800 // remove End from line list
1802 RemoveEntryList (&End
->Link
);
1805 FileBuffer
.NumLines
--;
1807 FileBufferNeedRefresh
= TRUE
;
1808 FileBufferOnlyLineNeedRefresh
= FALSE
;
1812 // just delete the previous character
1814 LineDeleteAt (Line
, FileColumn
- 1);
1815 FileBufferScrollLeft ();
1816 FileBufferOnlyLineNeedRefresh
= TRUE
;
1819 if (!FileBuffer
.FileModified
) {
1820 FileBuffer
.FileModified
= TRUE
;
1827 Add a return into line at current position.
1829 @retval EFI_SUCCESS The insetrion of the character was successful.
1830 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1834 FileBufferDoReturn (
1838 EFI_EDITOR_LINE
*Line
;
1839 EFI_EDITOR_LINE
*NewLine
;
1846 FileBufferNeedRefresh
= TRUE
;
1847 FileBufferOnlyLineNeedRefresh
= FALSE
;
1849 Line
= FileBuffer
.CurrentLine
;
1851 FileColumn
= FileBuffer
.FilePosition
.Column
;
1853 NewLine
= AllocateZeroPool (sizeof (EFI_EDITOR_LINE
));
1854 if (NewLine
== NULL
) {
1855 return EFI_OUT_OF_RESOURCES
;
1858 NewLine
->Signature
= LINE_LIST_SIGNATURE
;
1859 NewLine
->Size
= Line
->Size
- FileColumn
+ 1;
1860 NewLine
->TotalSize
= NewLine
->Size
;
1861 NewLine
->Buffer
= CatSPrint (NULL
, L
"\0");
1862 if (NewLine
->Buffer
== NULL
) {
1863 return EFI_OUT_OF_RESOURCES
;
1866 NewLine
->Type
= NewLineTypeDefault
;
1868 if (NewLine
->Size
> 0) {
1870 // UNICODE + CHAR_NULL
1872 Buffer
= AllocateZeroPool (2 * (NewLine
->Size
+ 1));
1873 if (Buffer
== NULL
) {
1874 FreePool (NewLine
->Buffer
);
1876 return EFI_OUT_OF_RESOURCES
;
1879 FreePool (NewLine
->Buffer
);
1881 NewLine
->Buffer
= Buffer
;
1883 for (Index
= 0; Index
< NewLine
->Size
; Index
++) {
1884 NewLine
->Buffer
[Index
] = Line
->Buffer
[Index
+ FileColumn
- 1];
1887 NewLine
->Buffer
[NewLine
->Size
] = CHAR_NULL
;
1889 Line
->Buffer
[FileColumn
- 1] = CHAR_NULL
;
1890 Line
->Size
= FileColumn
- 1;
1893 // increase NumLines
1895 FileBuffer
.NumLines
++;
1898 // insert it into the correct position of line list
1900 NewLine
->Link
.BackLink
= &(Line
->Link
);
1901 NewLine
->Link
.ForwardLink
= Line
->Link
.ForwardLink
;
1902 Line
->Link
.ForwardLink
->BackLink
= &(NewLine
->Link
);
1903 Line
->Link
.ForwardLink
= &(NewLine
->Link
);
1906 // move cursor to the start of next line
1908 Row
= FileBuffer
.FilePosition
.Row
+ 1;
1911 FileBufferMovePosition (Row
, Col
);
1914 // set file is modified
1916 if (!FileBuffer
.FileModified
) {
1917 FileBuffer
.FileModified
= TRUE
;
1924 Delete current character from current line. This is the effect caused
1931 FileBufferDoDelete (
1935 EFI_EDITOR_LINE
*Line
;
1936 EFI_EDITOR_LINE
*Next
;
1940 Line
= FileBuffer
.CurrentLine
;
1941 FileColumn
= FileBuffer
.FilePosition
.Column
;
1946 if (FileColumn
>= Line
->Size
+ 1) {
1950 if (Line
->Link
.ForwardLink
== FileBuffer
.ListHead
) {
1954 // since last character,
1955 // so will add the next line to this line
1957 Link
= Line
->Link
.ForwardLink
;
1958 Next
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1959 LineCat (Line
, Next
);
1960 if (Line
->Buffer
== NULL
) {
1961 return EFI_OUT_OF_RESOURCES
;
1964 RemoveEntryList (&Next
->Link
);
1967 FileBuffer
.NumLines
--;
1969 FileBufferNeedRefresh
= TRUE
;
1970 FileBufferOnlyLineNeedRefresh
= FALSE
;
1974 // just delete current character
1976 LineDeleteAt (Line
, FileColumn
);
1977 FileBufferOnlyLineNeedRefresh
= TRUE
;
1980 if (!FileBuffer
.FileModified
) {
1981 FileBuffer
.FileModified
= TRUE
;
1988 Scroll cursor to right 1 character.
1990 @retval EFI_SUCCESS The operation was successful.
1994 FileBufferScrollRight (
1998 EFI_EDITOR_LINE
*Line
;
2002 Line
= FileBuffer
.CurrentLine
;
2003 if (Line
->Buffer
== NULL
) {
2007 FRow
= FileBuffer
.FilePosition
.Row
;
2008 FCol
= FileBuffer
.FilePosition
.Column
;
2011 // if already at end of this line, scroll it to the start of next line
2013 if (FCol
> Line
->Size
) {
2017 if (Line
->Link
.ForwardLink
!= FileBuffer
.ListHead
) {
2025 // if not at end of this line, just move to next column
2030 FileBufferMovePosition (FRow
, FCol
);
2036 Insert a char into line
2039 @param[in] Line The line to insert into.
2040 @param[in] Char The char to insert.
2041 @param[in] Pos The position to insert the char at ( start from 0 ).
2042 @param[in] StrSize The current string size ( include CHAR_NULL ),unit is Unicode character.
2044 @return The new string size ( include CHAR_NULL ) ( unit is Unicode character ).
2049 IN EFI_EDITOR_LINE
*Line
,
2056 CHAR16
*TempStringPtr
;
2059 Index
= (StrSize
) * 2;
2064 // do not have free space
2066 if (Line
->TotalSize
<= Line
->Size
) {
2067 Str
= ReallocatePool (Index
, Index
+ 16, Str
);
2072 Line
->TotalSize
+= 8;
2075 // move the later part of the string one character right
2077 TempStringPtr
= Str
;
2078 for (Index
= StrSize
; Index
> Pos
; Index
--) {
2079 TempStringPtr
[Index
] = TempStringPtr
[Index
- 1];
2082 // insert char into it.
2084 TempStringPtr
[Index
] = Char
;
2093 Add a character to the current line.
2095 @param[in] Char The Character to input.
2097 @retval EFI_SUCCESS The input was succesful.
2105 EFI_EDITOR_LINE
*Line
;
2108 Line
= FileBuffer
.CurrentLine
;
2111 // only needs to refresh current line
2113 FileBufferOnlyLineNeedRefresh
= TRUE
;
2116 // when is insert mode, or cursor is at end of this line,
2117 // so insert this character
2118 // or replace the character.
2120 FilePos
= FileBuffer
.FilePosition
.Column
- 1;
2121 if (FileBuffer
.ModeInsert
|| FilePos
+ 1 > Line
->Size
) {
2122 LineStrInsert (Line
, Char
, FilePos
, Line
->Size
+ 1);
2124 Line
->Buffer
[FilePos
] = Char
;
2127 // move cursor to right
2129 FileBufferScrollRight ();
2131 if (!FileBuffer
.FileModified
) {
2132 FileBuffer
.FileModified
= TRUE
;
2139 Handles inputs from characters (ASCII key + Backspace + return)
2141 @param[in] Char The input character.
2143 @retval EFI_SUCCESS The operation was successful.
2144 @retval EFI_LOAD_ERROR There was an error.
2145 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2149 FileBufferDoCharInput (
2150 IN CONST CHAR16 Char
2155 Status
= EFI_SUCCESS
;
2161 case CHAR_BACKSPACE
:
2162 Status
= FileBufferDoBackspace ();
2172 case CHAR_CARRIAGE_RETURN
:
2173 Status
= FileBufferDoReturn ();
2178 // DEAL WITH ASCII CHAR, filter out thing like ctrl+f
2180 if (Char
> 127 || Char
< 32) {
2181 Status
= StatusBarSetStatusString (L
"Unknown Command");
2183 Status
= FileBufferAddChar (Char
);
2194 Scroll cursor to the next line.
2196 @retval EFI_SUCCESS The operation was successful.
2200 FileBufferScrollDown (
2204 EFI_EDITOR_LINE
*Line
;
2208 Line
= FileBuffer
.CurrentLine
;
2209 if (Line
->Buffer
== NULL
) {
2213 FRow
= FileBuffer
.FilePosition
.Row
;
2214 FCol
= FileBuffer
.FilePosition
.Column
;
2219 if (Line
->Link
.ForwardLink
!= FileBuffer
.ListHead
) {
2221 Line
= CR (Line
->Link
.ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2224 // if the next line is not that long, so move to end of next line
2226 if (FCol
> Line
->Size
) {
2227 FCol
= Line
->Size
+ 1;
2234 FileBufferMovePosition (FRow
, FCol
);
2240 Scroll the cursor to previous line.
2242 @retval EFI_SUCCESS The operation was successful.
2246 FileBufferScrollUp (
2250 EFI_EDITOR_LINE
*Line
;
2254 Line
= FileBuffer
.CurrentLine
;
2256 FRow
= FileBuffer
.FilePosition
.Row
;
2257 FCol
= FileBuffer
.FilePosition
.Column
;
2260 // has previous line
2262 if (Line
->Link
.BackLink
!= FileBuffer
.ListHead
) {
2264 Line
= CR (Line
->Link
.BackLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2267 // if previous line is not that long, so move to the end of previous line
2269 if (FCol
> Line
->Size
) {
2270 FCol
= Line
->Size
+ 1;
2277 FileBufferMovePosition (FRow
, FCol
);
2283 Scroll cursor to next page.
2285 @retval EFI_SUCCESS The operation wa successful.
2289 FileBufferPageDown (
2293 EFI_EDITOR_LINE
*Line
;
2298 Line
= FileBuffer
.CurrentLine
;
2300 FRow
= FileBuffer
.FilePosition
.Row
;
2301 FCol
= FileBuffer
.FilePosition
.Column
;
2306 if (FileBuffer
.NumLines
>= FRow
+ (MainEditor
.ScreenSize
.Row
- 2)) {
2307 Gap
= (MainEditor
.ScreenSize
.Row
- 2);
2310 // MOVE CURSOR TO LAST LINE
2312 Gap
= FileBuffer
.NumLines
- FRow
;
2317 Line
= MoveLine (Gap
);
2320 // if that line, is not that long, so move to the end of that line
2322 if (Line
!= NULL
&& FCol
> Line
->Size
) {
2323 FCol
= Line
->Size
+ 1;
2328 FileBufferMovePosition (FRow
, FCol
);
2334 Scroll cursor to previous screen.
2336 @retval EFI_SUCCESS The operation was successful.
2344 EFI_EDITOR_LINE
*Line
;
2350 Line
= FileBuffer
.CurrentLine
;
2352 FRow
= FileBuffer
.FilePosition
.Row
;
2353 FCol
= FileBuffer
.FilePosition
.Column
;
2356 // has previous page
2358 if (FRow
> (MainEditor
.ScreenSize
.Row
- 2)) {
2359 Gap
= (MainEditor
.ScreenSize
.Row
- 2);
2362 // the first line of file will displayed on the first line of screen
2373 Line
= MoveLine (Retreat
);
2376 // if that line is not that long, so move to the end of that line
2378 if (Line
!= NULL
&& FCol
> Line
->Size
) {
2379 FCol
= Line
->Size
+ 1;
2384 FileBufferMovePosition (FRow
, FCol
);
2390 Scroll cursor to end of the current line.
2392 @retval EFI_SUCCESS The operation was successful.
2400 EFI_EDITOR_LINE
*Line
;
2404 Line
= FileBuffer
.CurrentLine
;
2406 FRow
= FileBuffer
.FilePosition
.Row
;
2409 // goto the last column of the line
2411 FCol
= Line
->Size
+ 1;
2413 FileBufferMovePosition (FRow
, FCol
);
2419 Dispatch input to different handler
2420 @param[in] Key The input key. One of:
2424 Direction key: up/down/left/right/pgup/pgdn
2428 @retval EFI_SUCCESS The dispatch was done successfully.
2429 @retval EFI_LOAD_ERROR The dispatch was not successful.
2430 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2434 FileBufferHandleInput (
2435 IN CONST EFI_INPUT_KEY
*Key
2440 Status
= EFI_SUCCESS
;
2442 switch (Key
->ScanCode
) {
2444 // ordinary key input
2447 if (!FileBuffer
.ReadOnly
) {
2448 Status
= FileBufferDoCharInput (Key
->UnicodeChar
);
2450 Status
= StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2459 Status
= FileBufferScrollUp ();
2466 Status
= FileBufferScrollDown ();
2473 Status
= FileBufferScrollRight ();
2480 Status
= FileBufferScrollLeft ();
2487 Status
= FileBufferPageUp ();
2493 case SCAN_PAGE_DOWN
:
2494 Status
= FileBufferPageDown ();
2501 if (!FileBuffer
.ReadOnly
) {
2502 Status
= FileBufferDoDelete ();
2504 Status
= StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2513 FileBufferMovePosition (FileBuffer
.FilePosition
.Row
, 1);
2514 Status
= EFI_SUCCESS
;
2521 Status
= FileBufferEnd ();
2528 FileBuffer
.ModeInsert
= (BOOLEAN
)!FileBuffer
.ModeInsert
;
2529 Status
= EFI_SUCCESS
;
2533 Status
= StatusBarSetStatusString (L
"Unknown Command");
2541 Check user specified FileRow is above current screen.
2543 @param[in] FileRow The row of file position ( start from 1 ).
2545 @retval TRUE It is above the current screen.
2546 @retval FALSE It is not above the current screen.
2550 AboveCurrentScreen (
2555 // if is to the above of the screen
2557 if (FileRow
< FileBuffer
.LowVisibleRange
.Row
) {
2565 Check user specified FileRow is under current screen.
2567 @param[in] FileRow The row of file position ( start from 1 ).
2569 @retval TRUE It is under the current screen.
2570 @retval FALSE It is not under the current screen.
2574 UnderCurrentScreen (
2579 // if is to the under of the screen
2581 if (FileRow
> FileBuffer
.LowVisibleRange
.Row
+ (MainEditor
.ScreenSize
.Row
- 2) - 1) {
2589 Check user specified FileCol is left to current screen.
2591 @param[in] FileCol The column of file position ( start from 1 ).
2593 @retval TRUE It is to the left.
2594 @retval FALSE It is not to the left.
2603 // if is to the left of the screen
2605 if (FileCol
< FileBuffer
.LowVisibleRange
.Column
) {
2613 Check user specified FileCol is right to current screen.
2615 @param[in] FileCol The column of file position ( start from 1 ).
2617 @retval TRUE It is to the right.
2618 @retval FALSE It is not to the right.
2622 RightCurrentScreen (
2627 // if is to the right of the screen
2629 if (FileCol
> FileBuffer
.LowVisibleRange
.Column
+ MainEditor
.ScreenSize
.Column
- 1) {
2637 Advance/Retreat lines and set CurrentLine in FileBuffer to it
2639 @param[in] Count The line number to advance/retreat
2643 @retval NULL An error occured.
2644 @return The line after advance/retreat.
2652 EFI_EDITOR_LINE
*Line
;
2656 AbsCount
= (UINTN
)ABS(Count
);
2657 Line
= InternalEditorMiscLineRetreat (AbsCount
,MainEditor
.FileBuffer
->CurrentLine
,MainEditor
.FileBuffer
->ListHead
);
2659 Line
= InternalEditorMiscLineAdvance ((UINTN
)Count
,MainEditor
.FileBuffer
->CurrentLine
,MainEditor
.FileBuffer
->ListHead
);
2666 MainEditor
.FileBuffer
->CurrentLine
= Line
;
2672 According to cursor's file position, adjust screen display
2674 @param[in] NewFilePosRow The row of file position ( start from 1 ).
2675 @param[in] NewFilePosCol The column of file position ( start from 1 ).
2679 FileBufferMovePosition (
2680 IN CONST UINTN NewFilePosRow
,
2681 IN CONST UINTN NewFilePosCol
2693 // CALCULATE gap between current file position and new file position
2695 RowGap
= NewFilePosRow
- FileBuffer
.FilePosition
.Row
;
2696 ColGap
= NewFilePosCol
- FileBuffer
.FilePosition
.Column
;
2698 Under
= UnderCurrentScreen (NewFilePosRow
);
2699 Above
= AboveCurrentScreen (NewFilePosRow
);
2701 // if is below current screen
2705 // display row will be unchanged
2707 FileBuffer
.FilePosition
.Row
= NewFilePosRow
;
2711 // has enough above line, so display row unchanged
2712 // not has enough above lines, so the first line is at the
2713 // first display line
2715 if (NewFilePosRow
< (FileBuffer
.DisplayPosition
.Row
- 1)) {
2716 FileBuffer
.DisplayPosition
.Row
= NewFilePosRow
+ 1;
2719 FileBuffer
.FilePosition
.Row
= NewFilePosRow
;
2722 // in current screen
2724 FileBuffer
.FilePosition
.Row
= NewFilePosRow
;
2726 Abs
= (UINTN
)ABS(RowGap
);
2727 FileBuffer
.DisplayPosition
.Row
-= Abs
;
2729 FileBuffer
.DisplayPosition
.Row
+= RowGap
;
2734 FileBuffer
.LowVisibleRange
.Row
= FileBuffer
.FilePosition
.Row
- (FileBuffer
.DisplayPosition
.Row
- 2);
2736 Right
= RightCurrentScreen (NewFilePosCol
);
2737 Left
= LeftCurrentScreen (NewFilePosCol
);
2740 // if right to current screen
2744 // display column will be changed to end
2746 FileBuffer
.DisplayPosition
.Column
= MainEditor
.ScreenSize
.Column
;
2747 FileBuffer
.FilePosition
.Column
= NewFilePosCol
;
2751 // has enough left characters , so display row unchanged
2752 // not has enough left characters,
2753 // so the first character is at the first display column
2755 if (NewFilePosCol
< (FileBuffer
.DisplayPosition
.Column
)) {
2756 FileBuffer
.DisplayPosition
.Column
= NewFilePosCol
;
2759 FileBuffer
.FilePosition
.Column
= NewFilePosCol
;
2762 // in current screen
2764 FileBuffer
.FilePosition
.Column
= NewFilePosCol
;
2766 Abs
= (UINTN
)(-ColGap
);
2767 FileBuffer
.DisplayPosition
.Column
-= Abs
;
2769 FileBuffer
.DisplayPosition
.Column
+= ColGap
;
2774 FileBuffer
.LowVisibleRange
.Column
= FileBuffer
.FilePosition
.Column
- (FileBuffer
.DisplayPosition
.Column
- 1);
2777 // let CurrentLine point to correct line;
2779 FileBuffer
.CurrentLine
= MoveCurrentLine (RowGap
);
2784 Cut current line out and return a pointer to it.
2786 @param[out] CutLine Upon a successful return pointer to the pointer to
2787 the allocated cut line.
2789 @retval EFI_SUCCESS The cut was successful.
2790 @retval EFI_NOT_FOUND There was no selection to cut.
2791 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2796 OUT EFI_EDITOR_LINE
**CutLine
2799 EFI_EDITOR_LINE
*Line
;
2800 EFI_EDITOR_LINE
*NewLine
;
2804 if (FileBuffer
.ReadOnly
) {
2805 StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2809 Line
= FileBuffer
.CurrentLine
;
2812 // if is the last dummy line, SO CAN not cut
2814 if (StrCmp (Line
->Buffer
, L
"\0") == 0 && Line
->Link
.ForwardLink
== FileBuffer
.ListHead
2820 // LAST LINE AND NOTHING ON THIS LINE, SO CUT NOTHING
2822 StatusBarSetStatusString (L
"Nothing to Cut");
2823 return EFI_NOT_FOUND
;
2826 // if is the last line, so create a dummy line
2828 if (Line
->Link
.ForwardLink
== FileBuffer
.ListHead
) {
2831 // create a new line
2833 NewLine
= FileBufferCreateLine ();
2834 if (NewLine
== NULL
) {
2835 return EFI_OUT_OF_RESOURCES
;
2839 FileBuffer
.NumLines
--;
2840 Row
= FileBuffer
.FilePosition
.Row
;
2845 FileBuffer
.CurrentLine
= CR (
2846 FileBuffer
.CurrentLine
->Link
.ForwardLink
,
2852 RemoveEntryList (&Line
->Link
);
2854 FileBuffer
.Lines
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2856 FileBufferMovePosition (Row
, Col
);
2858 FileBuffer
.FileModified
= TRUE
;
2859 FileBufferNeedRefresh
= TRUE
;
2860 FileBufferOnlyLineNeedRefresh
= FALSE
;
2868 Paste a line into line list.
2870 @retval EFI_SUCCESS The paste was successful.
2871 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2875 FileBufferPasteLine (
2879 EFI_EDITOR_LINE
*Line
;
2880 EFI_EDITOR_LINE
*NewLine
;
2885 // if nothing is on clip board
2888 if (MainEditor
.CutLine
== NULL
) {
2892 // read only file can not be pasted on
2894 if (FileBuffer
.ReadOnly
) {
2895 StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2899 NewLine
= LineDup (MainEditor
.CutLine
);
2900 if (NewLine
== NULL
) {
2901 return EFI_OUT_OF_RESOURCES
;
2904 // insert it above current line
2906 Line
= FileBuffer
.CurrentLine
;
2907 NewLine
->Link
.BackLink
= Line
->Link
.BackLink
;
2908 NewLine
->Link
.ForwardLink
= &Line
->Link
;
2910 Line
->Link
.BackLink
->ForwardLink
= &NewLine
->Link
;
2911 Line
->Link
.BackLink
= &NewLine
->Link
;
2913 FileBuffer
.NumLines
++;
2914 FileBuffer
.CurrentLine
= NewLine
;
2916 FileBuffer
.Lines
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2922 Row
= FileBuffer
.FilePosition
.Row
;
2924 FileBufferMovePosition (Row
, Col
);
2927 // after paste, set some value so that refresh knows to do something
2929 FileBuffer
.FileModified
= TRUE
;
2930 FileBufferNeedRefresh
= TRUE
;
2931 FileBufferOnlyLineNeedRefresh
= FALSE
;
2937 Search string from current position on in file
2939 @param[in] Str The search string.
2940 @param[in] Offset The offset from current position.
2942 @retval EFI_SUCCESS The operation was successful.
2943 @retval EFI_NOT_FOUND The string Str was not found.
2948 IN CONST CHAR16
*Str
,
2949 IN CONST UINTN Offset
2956 EFI_EDITOR_LINE
*Line
;
2965 // search if in current line
2967 Current
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1 + Offset
;
2969 if (Current
>= (FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.CurrentLine
->Size
)) {
2973 Current
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.CurrentLine
->Size
;
2978 CharPos
= StrStr (Current
, Str
);
2979 if (CharPos
!= NULL
) {
2980 Position
= CharPos
- Current
+ 1;
2988 Column
= (Position
- 1) + FileBuffer
.FilePosition
.Column
+ Offset
;
2989 Row
= FileBuffer
.FilePosition
.Row
;
2992 // not found so find through next lines
2994 Link
= FileBuffer
.CurrentLine
->Link
.ForwardLink
;
2996 Row
= FileBuffer
.FilePosition
.Row
+ 1;
2997 while (Link
!= FileBuffer
.ListHead
) {
2998 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2999 // Position = StrStr (Line->Buffer, Str);
3000 CharPos
= StrStr (Line
->Buffer
, Str
);
3001 if (CharPos
!= NULL
) {
3002 Position
= CharPos
- Line
->Buffer
+ 1;
3015 Link
= Link
->ForwardLink
;
3018 if (Link
== FileBuffer
.ListHead
) {
3026 return EFI_NOT_FOUND
;
3029 FileBufferMovePosition (Row
, Column
);
3032 // call refresh to fresh edit area,
3033 // because the outer may loop to find multiply occurrence of this string
3035 FileBufferRefresh ();
3041 Replace SearchLen characters from current position on with Replace.
3043 This will modify the current buffer at the current position.
3045 @param[in] Replace The string to replace.
3046 @param[in] SearchLen Search string's length.
3048 @retval EFI_SUCCESS The operation was successful.
3049 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3054 IN CONST CHAR16
*Replace
,
3055 IN CONST UINTN SearchLen
3065 ReplaceLen
= StrLen (Replace
);
3067 OldSize
= FileBuffer
.CurrentLine
->Size
+ 1;
3069 // include CHAR_NULL
3071 NewSize
= OldSize
+ (ReplaceLen
- SearchLen
);
3073 if (ReplaceLen
> SearchLen
) {
3075 // do not have the enough space
3077 if (FileBuffer
.CurrentLine
->TotalSize
+ 1 <= NewSize
) {
3078 FileBuffer
.CurrentLine
->Buffer
= ReallocatePool (
3081 FileBuffer
.CurrentLine
->Buffer
3083 FileBuffer
.CurrentLine
->TotalSize
= NewSize
- 1;
3086 if (FileBuffer
.CurrentLine
->Buffer
== NULL
) {
3087 return EFI_OUT_OF_RESOURCES
;
3090 // the end CHAR_NULL character;
3092 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ (NewSize
- 1);
3093 Gap
= ReplaceLen
- SearchLen
;
3096 // keep the latter part
3098 for (Index
= 0; Index
< (FileBuffer
.CurrentLine
->Size
- FileBuffer
.FilePosition
.Column
- SearchLen
+ 2); Index
++) {
3099 *Buffer
= *(Buffer
- Gap
);
3103 // set replace into it
3105 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1;
3106 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3107 Buffer
[Index
] = Replace
[Index
];
3111 if (ReplaceLen
< SearchLen
) {
3112 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1;
3114 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3115 Buffer
[Index
] = Replace
[Index
];
3118 Buffer
+= ReplaceLen
;
3119 Gap
= SearchLen
- ReplaceLen
;
3122 // set replace into it
3124 for (Index
= 0; Index
< (FileBuffer
.CurrentLine
->Size
- FileBuffer
.FilePosition
.Column
- ReplaceLen
+ 2); Index
++) {
3125 *Buffer
= *(Buffer
+ Gap
);
3130 if (ReplaceLen
== SearchLen
) {
3131 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1;
3132 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3133 Buffer
[Index
] = Replace
[Index
];
3137 FileBuffer
.CurrentLine
->Size
+= (ReplaceLen
- SearchLen
);
3139 FileBufferOnlyLineNeedRefresh
= TRUE
;
3141 FileBuffer
.FileModified
= TRUE
;
3143 MainTitleBarRefresh (MainEditor
.FileBuffer
->FileName
, MainEditor
.FileBuffer
->FileType
, MainEditor
.FileBuffer
->ReadOnly
, MainEditor
.FileBuffer
->FileModified
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
, 0, 0);
3144 FileBufferRestorePosition ();
3145 FileBufferRefresh ();
3151 Move the mouse cursor position.
3153 @param[in] TextX The new x-coordinate.
3154 @param[in] TextY The new y-coordinate.
3158 FileBufferAdjustMousePosition (
3159 IN CONST INT32 TextX
,
3160 IN CONST INT32 TextY
3169 // TextX and TextY is mouse movement data returned by mouse driver
3170 // This function will change it to MousePosition
3173 // get absolute value
3179 CoordinateX
= FileBuffer
.MousePosition
.Column
;
3180 CoordinateY
= FileBuffer
.MousePosition
.Row
;
3183 CoordinateX
+= TextX
;
3185 if (CoordinateX
>= AbsX
) {
3186 CoordinateX
-= AbsX
;
3193 CoordinateY
+= TextY
;
3195 if (CoordinateY
>= AbsY
) {
3196 CoordinateY
-= AbsY
;
3202 // check whether new mouse column position is beyond screen
3203 // if not, adjust it
3205 if (CoordinateX
>= 1 && CoordinateX
<= MainEditor
.ScreenSize
.Column
) {
3206 FileBuffer
.MousePosition
.Column
= CoordinateX
;
3207 } else if (CoordinateX
< 1) {
3208 FileBuffer
.MousePosition
.Column
= 1;
3209 } else if (CoordinateX
> MainEditor
.ScreenSize
.Column
) {
3210 FileBuffer
.MousePosition
.Column
= MainEditor
.ScreenSize
.Column
;
3213 // check whether new mouse row position is beyond screen
3214 // if not, adjust it
3216 if (CoordinateY
>= 2 && CoordinateY
<= (MainEditor
.ScreenSize
.Row
- 1)) {
3217 FileBuffer
.MousePosition
.Row
= CoordinateY
;
3218 } else if (CoordinateY
< 2) {
3219 FileBuffer
.MousePosition
.Row
= 2;
3220 } else if (CoordinateY
> (MainEditor
.ScreenSize
.Row
- 1)) {
3221 FileBuffer
.MousePosition
.Row
= (MainEditor
.ScreenSize
.Row
- 1);
3227 Search and replace operation.
3229 @param[in] SearchStr The string to search for.
3230 @param[in] ReplaceStr The string to replace with.
3231 @param[in] Offset The column to start at.
3235 FileBufferReplaceAll (
3236 IN CHAR16
*SearchStr
,
3237 IN CHAR16
*ReplaceStr
,
3250 EFI_EDITOR_LINE
*Line
;
3254 SearchLen
= StrLen (SearchStr
);
3255 ReplaceLen
= StrLen (ReplaceStr
);
3257 Column
= FileBuffer
.FilePosition
.Column
+ Offset
- 1;
3259 if (Column
> FileBuffer
.CurrentLine
->Size
) {
3260 Column
= FileBuffer
.CurrentLine
->Size
;
3263 Link
= &(FileBuffer
.CurrentLine
->Link
);
3265 while (Link
!= FileBuffer
.ListHead
) {
3266 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
3267 CharPos
= StrStr (Line
->Buffer
+ Column
, SearchStr
);
3268 if (CharPos
!= NULL
) {
3269 Position
= CharPos
- Line
->Buffer
;// + Column;
3273 if (ReplaceLen
> SearchLen
) {
3274 OldSize
= Line
->Size
+ 1;
3276 // include CHAR_NULL
3278 NewSize
= OldSize
+ (ReplaceLen
- SearchLen
);
3281 // do not have the enough space
3283 if (Line
->TotalSize
+ 1 <= NewSize
) {
3284 Line
->Buffer
= ReallocatePool (
3289 Line
->TotalSize
= NewSize
- 1;
3292 if (Line
->Buffer
== NULL
) {
3293 return EFI_OUT_OF_RESOURCES
;
3296 // the end CHAR_NULL character;
3298 Buffer
= Line
->Buffer
+ (NewSize
- 1);
3299 Gap
= ReplaceLen
- SearchLen
;
3302 // keep the latter part
3304 for (Index
= 0; Index
< (Line
->Size
- Position
- SearchLen
+ 1); Index
++) {
3305 *Buffer
= *(Buffer
- Gap
);
3309 } else if (ReplaceLen
< SearchLen
){
3310 Buffer
= Line
->Buffer
+ Position
+ ReplaceLen
;
3311 Gap
= SearchLen
- ReplaceLen
;
3313 for (Index
= 0; Index
< (Line
->Size
- Position
- ReplaceLen
+ 1); Index
++) {
3314 *Buffer
= *(Buffer
+ Gap
);
3318 ASSERT(ReplaceLen
== SearchLen
);
3321 // set replace into it
3323 Buffer
= Line
->Buffer
+ Position
;
3324 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3325 Buffer
[Index
] = ReplaceStr
[Index
];
3328 Line
->Size
+= (ReplaceLen
- SearchLen
);
3329 Column
+= ReplaceLen
;
3335 Link
= Link
->ForwardLink
;
3339 // call refresh to fresh edit area
3341 FileBuffer
.FileModified
= TRUE
;
3342 FileBufferNeedRefresh
= TRUE
;
3343 FileBufferRefresh ();
3349 Set the modified state to TRUE.
3353 FileBufferSetModified (
3357 FileBuffer
.FileModified
= TRUE
;