2 Implements filebuffer interface functions.
4 Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
5 SPDX-License-Identifier: BSD-2-Clause-Patent
9 #include "TextEditor.h"
10 #include <Guid/FileSystemInfo.h>
11 #include <Library/FileHandleLib.h>
13 EFI_EDITOR_FILE_BUFFER FileBuffer
;
14 EFI_EDITOR_FILE_BUFFER FileBufferBackupVar
;
17 // for basic initialization of FileBuffer
19 EFI_EDITOR_FILE_BUFFER FileBufferConst
= {
48 // the whole edit area needs to be refreshed
50 BOOLEAN FileBufferNeedRefresh
;
53 // only the current line in edit area needs to be refresh
55 BOOLEAN FileBufferOnlyLineNeedRefresh
;
57 BOOLEAN FileBufferMouseNeedRefresh
;
59 extern BOOLEAN EditorMouseAction
;
62 Initialization function for FileBuffer.
64 @param EFI_SUCCESS The initialization was successful.
65 @param EFI_LOAD_ERROR A default name could not be created.
66 @param EFI_OUT_OF_RESOURCES A memory allocation failed.
74 // basically initialize the FileBuffer
76 CopyMem (&FileBuffer
, &FileBufferConst
, sizeof (EFI_EDITOR_FILE_BUFFER
));
77 CopyMem (&FileBufferBackupVar
, &FileBufferConst
, sizeof (EFI_EDITOR_FILE_BUFFER
));
80 // set default FileName
82 FileBuffer
.FileName
= EditGetDefaultFileName (L
"txt");
83 if (FileBuffer
.FileName
== NULL
) {
84 return EFI_LOAD_ERROR
;
87 FileBuffer
.ListHead
= AllocateZeroPool (sizeof (LIST_ENTRY
));
88 if (FileBuffer
.ListHead
== NULL
) {
89 return EFI_OUT_OF_RESOURCES
;
92 InitializeListHead (FileBuffer
.ListHead
);
94 FileBuffer
.DisplayPosition
.Row
= 2;
95 FileBuffer
.DisplayPosition
.Column
= 1;
96 FileBuffer
.LowVisibleRange
.Row
= 2;
97 FileBuffer
.LowVisibleRange
.Column
= 1;
99 FileBufferNeedRefresh
= FALSE
;
100 FileBufferMouseNeedRefresh
= FALSE
;
101 FileBufferOnlyLineNeedRefresh
= FALSE
;
107 Backup function for FileBuffer. Only backup the following items:
108 Mouse/Cursor position
109 File Name, Type, ReadOnly, Modified
112 This is for making the file buffer refresh as few as possible.
114 @retval EFI_SUCCESS The backup operation was successful.
121 FileBufferBackupVar
.MousePosition
= FileBuffer
.MousePosition
;
123 SHELL_FREE_NON_NULL (FileBufferBackupVar
.FileName
);
124 FileBufferBackupVar
.FileName
= NULL
;
125 FileBufferBackupVar
.FileName
= StrnCatGrow (&FileBufferBackupVar
.FileName
, NULL
, FileBuffer
.FileName
, 0);
127 FileBufferBackupVar
.ModeInsert
= FileBuffer
.ModeInsert
;
128 FileBufferBackupVar
.FileType
= FileBuffer
.FileType
;
130 FileBufferBackupVar
.FilePosition
= FileBuffer
.FilePosition
;
131 FileBufferBackupVar
.LowVisibleRange
= FileBuffer
.LowVisibleRange
;
133 FileBufferBackupVar
.FileModified
= FileBuffer
.FileModified
;
134 FileBufferBackupVar
.ReadOnly
= FileBuffer
.ReadOnly
;
140 Advance to the next Count lines
142 @param[in] Count The line number to advance by.
143 @param[in] CurrentLine The pointer to the current line structure.
144 @param[in] LineList The pointer to the linked list of lines.
146 @retval NULL There was an error.
147 @return The line structure after the advance.
150 InternalEditorMiscLineAdvance (
151 IN CONST UINTN Count
,
152 IN CONST EFI_EDITOR_LINE
*CurrentLine
,
153 IN CONST LIST_ENTRY
*LineList
158 CONST EFI_EDITOR_LINE
*Line
;
160 if (CurrentLine
== NULL
|| LineList
== NULL
) {
164 for (Line
= CurrentLine
, Index
= 0; Index
< Count
; Index
++) {
166 // if already last line
168 if (Line
->Link
.ForwardLink
== LineList
) {
172 Line
= CR (Line
->Link
.ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
175 return ((EFI_EDITOR_LINE
*)Line
);
179 Retreat to the previous Count lines.
181 @param[in] Count The line number to retreat by.
182 @param[in] CurrentLine The pointer to the current line structure.
183 @param[in] LineList The pointer to the linked list of lines.
185 @retval NULL There was an error.
186 @return The line structure after the retreat.
189 InternalEditorMiscLineRetreat (
190 IN CONST UINTN Count
,
191 IN CONST EFI_EDITOR_LINE
*CurrentLine
,
192 IN CONST LIST_ENTRY
*LineList
197 CONST EFI_EDITOR_LINE
*Line
;
199 if (CurrentLine
== NULL
|| LineList
== NULL
) {
203 for (Line
= CurrentLine
, Index
= 0; Index
< Count
; Index
++) {
205 // already the first line
207 if (Line
->Link
.BackLink
== LineList
) {
211 Line
= CR (Line
->Link
.BackLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
214 return ((EFI_EDITOR_LINE
*)Line
);
218 Advance/Retreat lines
220 @param[in] Count line number to advance/retreat
224 @retval NULL An error occured.
225 @return The line after advance/retreat.
232 EFI_EDITOR_LINE
*Line
;
236 // if < 0, then retreat
237 // if > 0, the advance
240 AbsCount
= (UINTN
)ABS(Count
);
241 Line
= InternalEditorMiscLineRetreat (AbsCount
,MainEditor
.FileBuffer
->CurrentLine
,MainEditor
.FileBuffer
->ListHead
);
243 Line
= InternalEditorMiscLineAdvance ((UINTN
)Count
,MainEditor
.FileBuffer
->CurrentLine
,MainEditor
.FileBuffer
->ListHead
);
250 Function to update the 'screen' to display the mouse position.
252 @retval EFI_SUCCESS The backup operation was successful.
255 FileBufferRestoreMousePosition (
259 EFI_EDITOR_COLOR_UNION Orig
;
260 EFI_EDITOR_COLOR_UNION New
;
263 BOOLEAN HasCharacter
;
264 EFI_EDITOR_LINE
*CurrentLine
;
265 EFI_EDITOR_LINE
*Line
;
269 // variable initialization
273 if (MainEditor
.MouseSupported
) {
275 if (FileBufferMouseNeedRefresh
) {
277 FileBufferMouseNeedRefresh
= FALSE
;
280 // if mouse position not moved and only mouse action
281 // so do not need to refresh mouse position
283 if ((FileBuffer
.MousePosition
.Row
== FileBufferBackupVar
.MousePosition
.Row
&&
284 FileBuffer
.MousePosition
.Column
== FileBufferBackupVar
.MousePosition
.Column
)
285 && EditorMouseAction
) {
289 // backup the old screen attributes
291 Orig
= MainEditor
.ColorAttributes
;
293 New
.Colors
.Foreground
= Orig
.Colors
.Background
& 0xF;
294 New
.Colors
.Background
= Orig
.Colors
.Foreground
& 0x7;
297 // clear the old mouse position
299 FRow
= FileBuffer
.LowVisibleRange
.Row
+ FileBufferBackupVar
.MousePosition
.Row
- 2;
301 FColumn
= FileBuffer
.LowVisibleRange
.Column
+ FileBufferBackupVar
.MousePosition
.Column
- 1;
304 if (FRow
> FileBuffer
.NumLines
) {
305 HasCharacter
= FALSE
;
307 CurrentLine
= FileBuffer
.CurrentLine
;
308 Line
= MoveLine (FRow
- FileBuffer
.FilePosition
.Row
);
310 if (Line
== NULL
|| FColumn
> Line
->Size
) {
311 HasCharacter
= FALSE
;
314 FileBuffer
.CurrentLine
= CurrentLine
;
318 (INT32
)FileBufferBackupVar
.MousePosition
.Column
- 1,
319 (INT32
)FileBufferBackupVar
.MousePosition
.Row
- 1,
324 Value
= (Line
->Buffer
[FColumn
- 1]);
326 (INT32
)FileBufferBackupVar
.MousePosition
.Column
- 1,
327 (INT32
)FileBufferBackupVar
.MousePosition
.Row
- 1,
333 // set the new mouse position
335 gST
->ConOut
->SetAttribute (gST
->ConOut
, New
.Data
& 0x7F);
338 // clear the old mouse position
340 FRow
= FileBuffer
.LowVisibleRange
.Row
+ FileBuffer
.MousePosition
.Row
- 2;
341 FColumn
= FileBuffer
.LowVisibleRange
.Column
+ FileBuffer
.MousePosition
.Column
- 1;
344 if (FRow
> FileBuffer
.NumLines
) {
345 HasCharacter
= FALSE
;
347 CurrentLine
= FileBuffer
.CurrentLine
;
348 Line
= MoveLine (FRow
- FileBuffer
.FilePosition
.Row
);
350 if (Line
== NULL
|| FColumn
> Line
->Size
) {
351 HasCharacter
= FALSE
;
354 FileBuffer
.CurrentLine
= CurrentLine
;
358 (INT32
)FileBuffer
.MousePosition
.Column
- 1,
359 (INT32
)FileBuffer
.MousePosition
.Row
- 1,
364 Value
= Line
->Buffer
[FColumn
- 1];
366 (INT32
)FileBuffer
.MousePosition
.Column
- 1,
367 (INT32
)FileBuffer
.MousePosition
.Row
- 1,
373 // end of HasCharacter
375 gST
->ConOut
->SetAttribute (gST
->ConOut
, Orig
.Data
);
378 // end of MouseNeedRefresh
382 // end of MouseSupported
388 Free all the lines in FileBuffer
395 @retval EFI_SUCCESS The operation was successful.
398 FileBufferFreeLines (
403 EFI_EDITOR_LINE
*Line
;
406 // free all the lines
408 if (FileBuffer
.Lines
!= NULL
) {
410 Line
= FileBuffer
.Lines
;
411 Link
= &(Line
->Link
);
413 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
414 Link
= Link
->ForwardLink
;
417 // free line's buffer and line itself
420 } while (Link
!= FileBuffer
.ListHead
);
423 // clean the line list related structure
425 FileBuffer
.Lines
= NULL
;
426 FileBuffer
.CurrentLine
= NULL
;
427 FileBuffer
.NumLines
= 0;
429 FileBuffer
.ListHead
->ForwardLink
= FileBuffer
.ListHead
;
430 FileBuffer
.ListHead
->BackLink
= FileBuffer
.ListHead
;
436 Cleanup function for FileBuffer.
438 @retval EFI_SUCCESS The cleanup was successful.
447 SHELL_FREE_NON_NULL (FileBuffer
.FileName
);
450 // free all the lines
452 Status
= FileBufferFreeLines ();
454 SHELL_FREE_NON_NULL (FileBuffer
.ListHead
);
455 FileBuffer
.ListHead
= NULL
;
457 SHELL_FREE_NON_NULL (FileBufferBackupVar
.FileName
);
463 Print a line specified by Line on a row specified by Row of the screen.
465 @param[in] Line The line to print.
466 @param[in] Row The row on the screen to print onto (begin from 1).
468 @retval EFI_SUCCESS The printing was successful.
471 FileBufferPrintLine (
472 IN CONST EFI_EDITOR_LINE
*Line
,
484 // print start from correct character
486 Buffer
= Line
->Buffer
+ FileBuffer
.LowVisibleRange
.Column
- 1;
488 Limit
= Line
->Size
- FileBuffer
.LowVisibleRange
.Column
+ 1;
489 if (Limit
> Line
->Size
) {
493 BufLen
= (MainEditor
.ScreenSize
.Column
+ 1) * sizeof (CHAR16
);
494 PrintLine
= AllocatePool (BufLen
);
495 if (PrintLine
!= NULL
) {
496 StrnCpyS (PrintLine
, BufLen
/sizeof(CHAR16
), Buffer
, MIN(Limit
, MainEditor
.ScreenSize
.Column
));
497 for (Limit
= StrLen (PrintLine
); Limit
< MainEditor
.ScreenSize
.Column
; Limit
++) {
498 PrintLine
[Limit
] = L
' ';
501 PrintLine
[MainEditor
.ScreenSize
.Column
] = CHAR_NULL
;
503 PrintLine2
= AllocatePool (BufLen
* 2);
504 if (PrintLine2
!= NULL
) {
505 ShellCopySearchAndReplace(PrintLine
, PrintLine2
, BufLen
* 2, L
"%", L
"^%", FALSE
, FALSE
);
513 FreePool (PrintLine2
);
515 FreePool (PrintLine
);
522 Set the cursor position according to FileBuffer.DisplayPosition.
524 @retval EFI_SUCCESS The operation was successful.
527 FileBufferRestorePosition (
532 // set cursor position
534 return (gST
->ConOut
->SetCursorPosition (
536 FileBuffer
.DisplayPosition
.Column
- 1,
537 FileBuffer
.DisplayPosition
.Row
- 1
542 Refresh the screen with whats in the buffer.
544 @retval EFI_SUCCESS The refresh was successful.
545 @retval EFI_LOAD_ERROR There was an error finding what to write.
553 EFI_EDITOR_LINE
*Line
;
557 // if it's the first time after editor launch, so should refresh
561 // no definite required refresh
562 // and file position displayed on screen has not been changed
564 if (!FileBufferNeedRefresh
&&
565 !FileBufferOnlyLineNeedRefresh
&&
566 FileBufferBackupVar
.LowVisibleRange
.Row
== FileBuffer
.LowVisibleRange
.Row
&&
567 FileBufferBackupVar
.LowVisibleRange
.Column
== FileBuffer
.LowVisibleRange
.Column
570 FileBufferRestoreMousePosition ();
571 FileBufferRestorePosition ();
577 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
580 // only need to refresh current line
582 if (FileBufferOnlyLineNeedRefresh
&&
583 FileBufferBackupVar
.LowVisibleRange
.Row
== FileBuffer
.LowVisibleRange
.Row
&&
584 FileBufferBackupVar
.LowVisibleRange
.Column
== FileBuffer
.LowVisibleRange
.Column
587 EditorClearLine (FileBuffer
.DisplayPosition
.Row
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
);
588 FileBufferPrintLine (
589 FileBuffer
.CurrentLine
,
590 FileBuffer
.DisplayPosition
.Row
594 // the whole edit area need refresh
600 if (FileBuffer
.Lines
== NULL
) {
601 FileBufferRestoreMousePosition ();
602 FileBufferRestorePosition ();
603 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
608 // get the first line that will be displayed
610 Line
= MoveLine (FileBuffer
.LowVisibleRange
.Row
- FileBuffer
.FilePosition
.Row
);
612 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
614 return EFI_LOAD_ERROR
;
617 Link
= &(Line
->Link
);
620 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
625 FileBufferPrintLine (Line
, Row
);
627 Link
= Link
->ForwardLink
;
629 } while (Link
!= FileBuffer
.ListHead
&& Row
<= (MainEditor
.ScreenSize
.Row
- 1));
631 // while not file end and not screen full
633 while (Row
<= (MainEditor
.ScreenSize
.Row
- 1)) {
634 EditorClearLine (Row
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
);
639 FileBufferRestoreMousePosition ();
640 FileBufferRestorePosition ();
642 FileBufferNeedRefresh
= FALSE
;
643 FileBufferOnlyLineNeedRefresh
= FALSE
;
645 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
650 Create a new line and append it to the line list.
655 @retval NULL The create line failed.
656 @return The line created.
659 FileBufferCreateLine (
663 EFI_EDITOR_LINE
*Line
;
666 // allocate a line structure
668 Line
= AllocateZeroPool (sizeof (EFI_EDITOR_LINE
));
673 // initialize the structure
675 Line
->Signature
= LINE_LIST_SIGNATURE
;
678 Line
->Type
= NewLineTypeDefault
;
681 // initial buffer of the line is "\0"
683 ASSERT(CHAR_NULL
== CHAR_NULL
);
684 Line
->Buffer
= CatSPrint (NULL
, L
"\0");
685 if (Line
->Buffer
== NULL
) {
689 FileBuffer
.NumLines
++;
692 // insert the line into line list
694 InsertTailList (FileBuffer
.ListHead
, &Line
->Link
);
696 if (FileBuffer
.Lines
== NULL
) {
697 FileBuffer
.Lines
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
704 Set FileName field in FileBuffer.
706 @param Str The file name to set.
708 @retval EFI_SUCCESS The filename was successfully set.
709 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
710 @retval EFI_INVALID_PARAMETER Str is not a valid filename.
713 FileBufferSetFileName (
718 // Verify the parameters
720 if (!IsValidFileName(Str
)) {
721 return (EFI_INVALID_PARAMETER
);
724 // free the old file name
726 SHELL_FREE_NON_NULL (FileBuffer
.FileName
);
729 // Allocate and set the new name
731 FileBuffer
.FileName
= CatSPrint (NULL
, L
"%s", Str
);
732 if (FileBuffer
.FileName
== NULL
) {
733 return EFI_OUT_OF_RESOURCES
;
739 Free the existing file lines and reset the modified flag.
741 @retval EFI_SUCCESS The operation was successful.
749 // free all the lines
751 FileBufferFreeLines ();
752 FileBuffer
.FileModified
= FALSE
;
759 Read a file from disk into the FileBuffer.
761 @param[in] FileName The filename to read.
762 @param[in] Recover TRUE if is for recover mode, no information printouts.
764 @retval EFI_SUCCESS The load was successful.
765 @retval EFI_LOAD_ERROR The load failed.
766 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
767 @retval EFI_INVALID_PARAMETER FileName is a directory.
771 IN CONST CHAR16
*FileName
,
772 IN CONST BOOLEAN Recover
775 EFI_EDITOR_LINE
*Line
;
776 EE_NEWLINE_TYPE Type
;
781 CHAR16
*UnicodeBuffer
;
784 SHELL_FILE_HANDLE FileHandle
;
787 UINTN LineSizeBackup
;
793 UnicodeBuffer
= NULL
;
794 Type
= NewLineTypeDefault
;
799 // in this function, when you return error ( except EFI_OUT_OF_RESOURCES )
800 // you should set status string via StatusBarSetStatusString(L"blah")
801 // since this function maybe called before the editorhandleinput loop
802 // so any error will cause editor return
803 // so if you want to print the error status
804 // you should set the status string
808 // try to open the file
810 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
, 0);
812 if (!EFI_ERROR(Status
)) {
814 if (FileHandle
== NULL
) {
815 StatusBarSetStatusString (L
"Disk Error");
816 return EFI_LOAD_ERROR
;
819 Info
= ShellGetFileInfo(FileHandle
);
821 if (Info
->Attribute
& EFI_FILE_DIRECTORY
) {
822 StatusBarSetStatusString (L
"Directory Can Not Be Edited");
824 return EFI_INVALID_PARAMETER
;
827 if (Info
->Attribute
& EFI_FILE_READ_ONLY
) {
828 FileBuffer
.ReadOnly
= TRUE
;
830 FileBuffer
.ReadOnly
= FALSE
;
835 FileSize
= (UINTN
) Info
->FileSize
;
838 } else if (Status
== EFI_NOT_FOUND
) {
840 // file not exists. add create and try again
842 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
|EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_CREATE
, 0);
843 if (EFI_ERROR (Status
)) {
844 if (Status
== EFI_WRITE_PROTECTED
||
845 Status
== EFI_ACCESS_DENIED
||
846 Status
== EFI_NO_MEDIA
||
847 Status
== EFI_MEDIA_CHANGED
849 StatusBarSetStatusString (L
"Access Denied");
850 } else if (Status
== EFI_DEVICE_ERROR
|| Status
== EFI_VOLUME_CORRUPTED
|| Status
== EFI_VOLUME_FULL
) {
851 StatusBarSetStatusString (L
"Disk Error");
853 StatusBarSetStatusString (L
"Invalid File Name or Current-working-directory");
859 // it worked. now delete it and move on with the name (now validated)
861 Status
= ShellDeleteFile (&FileHandle
);
862 if (Status
== EFI_WARN_DELETE_FAILURE
) {
863 Status
= EFI_ACCESS_DENIED
;
866 if (EFI_ERROR (Status
)) {
867 StatusBarSetStatusString (L
"Access Denied");
872 // file doesn't exist, so set CreateFile to TRUE
875 FileBuffer
.ReadOnly
= FALSE
;
878 // all the check ends
879 // so now begin to set file name, free lines
881 if (StrCmp (FileName
, FileBuffer
.FileName
) != 0) {
882 FileBufferSetFileName (FileName
);
885 // free the old lines
895 // allocate buffer to read file
897 Buffer
= AllocateZeroPool (FileSize
);
898 if (Buffer
== NULL
) {
899 return EFI_OUT_OF_RESOURCES
;
902 // read file into Buffer
904 Status
= ShellReadFile (FileHandle
, &FileSize
, Buffer
);
905 ShellCloseFile(&FileHandle
);
907 if (EFI_ERROR (Status
)) {
908 StatusBarSetStatusString (L
"Read File Failed");
909 SHELL_FREE_NON_NULL (Buffer
);
910 return EFI_LOAD_ERROR
;
913 // nothing in this file
916 SHELL_FREE_NON_NULL (Buffer
);
918 // since has no head, so only can be an ASCII file
920 FileBuffer
.FileType
= FileTypeAscii
;
925 AsciiBuffer
= Buffer
;
929 // size < Unicode file header, so only can be ASCII file
931 FileBuffer
.FileType
= FileTypeAscii
;
936 if (*(UINT16
*) Buffer
== EFI_UNICODE_BYTE_ORDER_MARK
) {
938 // Unicode file's size should be even
940 if ((FileSize
% 2) != 0) {
941 StatusBarSetStatusString (L
"File Format Wrong");
942 SHELL_FREE_NON_NULL (Buffer
);
943 return EFI_LOAD_ERROR
;
948 FileBuffer
.FileType
= FileTypeUnicode
;
949 UnicodeBuffer
= Buffer
;
952 // pass this 0xff and 0xfe
957 FileBuffer
.FileType
= FileTypeAscii
;
960 // end of AsciiBuffer ==
964 // end of FileSize < 2
965 // all the check ends
966 // so now begin to set file name, free lines
968 if (StrCmp (FileName
, FileBuffer
.FileName
) != 0) {
969 FileBufferSetFileName (FileName
);
973 // free the old lines
978 // parse file content line by line
980 for (LoopVar1
= 0; LoopVar1
< FileSize
; LoopVar1
++) {
981 Type
= NewLineTypeUnknown
;
983 for (LineSize
= LoopVar1
; LineSize
< FileSize
; LineSize
++) {
984 if (FileBuffer
.FileType
== FileTypeAscii
) {
985 if (AsciiBuffer
[LineSize
] == CHAR_CARRIAGE_RETURN
) {
986 Type
= NewLineTypeCarriageReturn
;
991 if (LineSize
< FileSize
- 1) {
992 if (AsciiBuffer
[LineSize
+ 1] == CHAR_LINEFEED
) {
993 Type
= NewLineTypeCarriageReturnLineFeed
;
998 } else if (AsciiBuffer
[LineSize
] == CHAR_LINEFEED
) {
999 Type
= NewLineTypeLineFeed
;
1004 if (LineSize
< FileSize
- 1) {
1005 if (AsciiBuffer
[LineSize
+ 1] == CHAR_CARRIAGE_RETURN
) {
1006 Type
= NewLineTypeLineFeedCarriageReturn
;
1013 if (UnicodeBuffer
[LineSize
] == CHAR_CARRIAGE_RETURN
) {
1014 Type
= NewLineTypeCarriageReturn
;
1019 if (LineSize
< FileSize
- 1) {
1020 if (UnicodeBuffer
[LineSize
+ 1] == CHAR_LINEFEED
) {
1021 Type
= NewLineTypeCarriageReturnLineFeed
;
1026 } else if (UnicodeBuffer
[LineSize
] == CHAR_LINEFEED
) {
1027 Type
= NewLineTypeLineFeed
;
1032 if (LineSize
< FileSize
- 1) {
1033 if (UnicodeBuffer
[LineSize
+ 1] == CHAR_CARRIAGE_RETURN
) {
1034 Type
= NewLineTypeLineFeedCarriageReturn
;
1046 // end of for LineSize
1048 // if the type is wrong, then exit
1050 if (Type
== NewLineTypeUnknown
) {
1052 // Now if Type is NewLineTypeUnknown, it should be file end
1054 Type
= NewLineTypeDefault
;
1057 LineSizeBackup
= LineSize
;
1060 // create a new line
1062 Line
= FileBufferCreateLine ();
1064 SHELL_FREE_NON_NULL (Buffer
);
1065 return EFI_OUT_OF_RESOURCES
;
1068 // calculate file length
1070 LineSize
-= LoopVar1
;
1073 // Unicode and one CHAR_NULL
1075 SHELL_FREE_NON_NULL (Line
->Buffer
);
1076 Line
->Buffer
= AllocateZeroPool (LineSize
* 2 + 2);
1078 if (Line
->Buffer
== NULL
) {
1079 RemoveEntryList (&Line
->Link
);
1080 return EFI_OUT_OF_RESOURCES
;
1083 // copy this line to Line->Buffer
1085 for (LoopVar2
= 0; LoopVar2
< LineSize
; LoopVar2
++) {
1086 if (FileBuffer
.FileType
== FileTypeAscii
) {
1087 Line
->Buffer
[LoopVar2
] = (CHAR16
) AsciiBuffer
[LoopVar1
];
1089 Line
->Buffer
[LoopVar2
] = UnicodeBuffer
[LoopVar1
];
1095 // LoopVar1 now points to where CHAR_CARRIAGE_RETURN or CHAR_LINEFEED;
1097 Line
->Buffer
[LineSize
] = 0;
1099 Line
->Size
= LineSize
;
1100 Line
->TotalSize
= LineSize
;
1103 if (Type
== NewLineTypeCarriageReturnLineFeed
|| Type
== NewLineTypeLineFeedCarriageReturn
) {
1108 // last character is a return, SO create a new line
1110 if (((Type
== NewLineTypeCarriageReturnLineFeed
|| Type
== NewLineTypeLineFeedCarriageReturn
) && LineSizeBackup
== FileSize
- 2) ||
1111 ((Type
== NewLineTypeLineFeed
|| Type
== NewLineTypeCarriageReturn
) && LineSizeBackup
== FileSize
- 1)
1113 Line
= FileBufferCreateLine ();
1115 SHELL_FREE_NON_NULL (Buffer
);
1116 return EFI_OUT_OF_RESOURCES
;
1126 SHELL_FREE_NON_NULL (Buffer
);
1130 // end of if CreateFile
1134 FileBuffer
.DisplayPosition
.Row
= 2;
1135 FileBuffer
.DisplayPosition
.Column
= 1;
1136 FileBuffer
.LowVisibleRange
.Row
= 1;
1137 FileBuffer
.LowVisibleRange
.Column
= 1;
1138 FileBuffer
.FilePosition
.Row
= 1;
1139 FileBuffer
.FilePosition
.Column
= 1;
1140 FileBuffer
.MousePosition
.Row
= 2;
1141 FileBuffer
.MousePosition
.Column
= 1;
1144 UnicodeBuffer
= CatSPrint (NULL
, L
"%d Lines Read", FileBuffer
.NumLines
);
1145 if (UnicodeBuffer
== NULL
) {
1146 return EFI_OUT_OF_RESOURCES
;
1149 StatusBarSetStatusString (UnicodeBuffer
);
1150 FreePool (UnicodeBuffer
);
1154 // check whether we have fs?: in filename
1157 FSMappingPtr = NULL;
1158 while (FileName[LoopVar1] != 0) {
1159 if (FileName[LoopVar1] == L':') {
1160 FSMappingPtr = &FileName[LoopVar1];
1167 if (FSMappingPtr == NULL) {
1168 CurDir = ShellGetCurrentDir (NULL);
1172 while (FileName[LoopVar1] != 0) {
1173 if (FileName[LoopVar1] == L':') {
1177 FSMapping[LoopVar2++] = FileName[LoopVar1];
1182 FSMapping[LoopVar2] = 0;
1183 CurDir = ShellGetCurrentDir (FSMapping);
1186 if (CurDir != NULL) {
1187 for (LoopVar1 = 0; LoopVar1 < StrLen (CurDir) && CurDir[LoopVar1] != ':'; LoopVar1++);
1189 CurDir[LoopVar1] = 0;
1190 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) ShellGetMap (CurDir);
1193 return EFI_LOAD_ERROR;
1196 Status = LibDevicePathToInterface (
1197 &gEfiSimpleFileSystemProtocolGuid,
1201 if (EFI_ERROR (Status)) {
1202 return EFI_LOAD_ERROR;
1205 Status = Vol->OpenVolume (Vol, &RootFs);
1206 if (EFI_ERROR (Status)) {
1207 return EFI_LOAD_ERROR;
1210 // Get volume information of file system
1212 Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + 100;
1213 VolumeInfo = (EFI_FILE_SYSTEM_INFO *) AllocateZeroPool (Size);
1214 Status = RootFs->GetInfo (RootFs, &gEfiFileSystemInfoGuid, &Size, VolumeInfo);
1215 if (EFI_ERROR (Status)) {
1216 RootFs->Close (RootFs);
1217 return EFI_LOAD_ERROR;
1220 if (VolumeInfo->ReadOnly) {
1221 StatusBarSetStatusString (L"WARNING: Volume Read Only");
1224 FreePool (VolumeInfo);
1225 RootFs->Close (RootFs);
1232 if (FileBuffer
.Lines
!= 0) {
1233 FileBuffer
.CurrentLine
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1236 // create a dummy line
1238 Line
= FileBufferCreateLine ();
1240 return EFI_OUT_OF_RESOURCES
;
1243 FileBuffer
.CurrentLine
= Line
;
1246 FileBuffer
.FileModified
= FALSE
;
1247 FileBufferNeedRefresh
= TRUE
;
1248 FileBufferOnlyLineNeedRefresh
= FALSE
;
1249 FileBufferMouseNeedRefresh
= TRUE
;
1256 According to FileBuffer.NewLineType & FileBuffer.FileType,
1257 get the return buffer and size.
1259 @param[in] Type The type of line.
1260 @param[out] Buffer The buffer to fill.
1261 @param[out] Size The amount of the buffer used on return.
1265 IN CONST EE_NEWLINE_TYPE Type
,
1273 // give new line buffer,
1274 // and will judge unicode or ascii
1279 // not legal new line type
1281 if (Type
!= NewLineTypeLineFeed
&& Type
!= NewLineTypeCarriageReturn
&& Type
!= NewLineTypeCarriageReturnLineFeed
&& Type
!= NewLineTypeLineFeedCarriageReturn
) {
1286 // use_cr: give 0x0d
1288 if (Type
== NewLineTypeCarriageReturn
) {
1289 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1298 *Size
= NewLineSize
;
1302 // use_lf: give 0x0a
1304 if (Type
== NewLineTypeLineFeed
) {
1305 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1314 *Size
= NewLineSize
;
1318 // use_crlf: give 0x0d 0x0a
1320 if (Type
== NewLineTypeCarriageReturnLineFeed
) {
1321 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1334 *Size
= NewLineSize
;
1338 // use_lfcr: give 0x0a 0x0d
1340 if (Type
== NewLineTypeLineFeedCarriageReturn
) {
1341 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1354 *Size
= NewLineSize
;
1361 Change a Unicode string to an ASCII string.
1363 @param[in] UStr The Unicode string.
1364 @param[in] Length The maximum size of AStr.
1365 @param[out] AStr ASCII string to pass out.
1367 @return The actuall length.
1371 IN CONST CHAR16
*UStr
,
1372 IN CONST UINTN Length
,
1379 // just buffer copy, not character copy
1381 for (Index
= 0; Index
< Length
; Index
++) {
1382 *AStr
++ = (CHAR8
) *UStr
++;
1389 Save lines in FileBuffer to disk
1391 @param[in] FileName The file name for writing.
1393 @retval EFI_SUCCESS Data was written.
1394 @retval EFI_LOAD_ERROR
1395 @retval EFI_OUT_OF_RESOURCES There were not enough resources to write the file.
1399 IN CONST CHAR16
*FileName
1402 SHELL_FILE_HANDLE FileHandle
;
1404 EFI_EDITOR_LINE
*Line
;
1410 CHAR8 NewLineBuffer
[4];
1413 EFI_FILE_INFO
*Info
;
1417 EE_NEWLINE_TYPE Type
;
1432 TotalSize
= 0x200000;
1439 // if is the old file
1441 if (FileBuffer
.FileName
!= NULL
&& StrCmp (FileName
, FileBuffer
.FileName
) == 0) {
1443 // file has not been modified
1445 if (!FileBuffer
.FileModified
) {
1450 // if file is read-only, set error
1452 if (FileBuffer
.ReadOnly
) {
1453 StatusBarSetStatusString (L
"Read Only File Can Not Be Saved");
1458 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
|EFI_FILE_MODE_WRITE
, 0);
1460 if (!EFI_ERROR (Status
)) {
1461 Info
= ShellGetFileInfo(FileHandle
);
1463 if (Info
!= NULL
&& Info
->Attribute
& EFI_FILE_DIRECTORY
) {
1464 StatusBarSetStatusString (L
"Directory Can Not Be Saved");
1465 ShellCloseFile (&FileHandle
);
1467 return EFI_LOAD_ERROR
;
1471 Attribute
= Info
->Attribute
& ~EFI_FILE_READ_ONLY
;
1476 // if file exits, so delete it
1478 Status
= ShellDeleteFile (&FileHandle
);
1479 if (EFI_ERROR (Status
) || Status
== EFI_WARN_DELETE_FAILURE
) {
1480 StatusBarSetStatusString (L
"Write File Failed");
1481 return EFI_LOAD_ERROR
;
1485 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
|EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_CREATE
, Attribute
);
1487 if (EFI_ERROR (Status
)) {
1488 StatusBarSetStatusString (L
"Create File Failed");
1489 return EFI_LOAD_ERROR
;
1493 // if file is Unicode file, write Unicode header to it.
1495 if (FileBuffer
.FileType
== FileTypeUnicode
) {
1497 Status
= ShellWriteFile (FileHandle
, &Length
, (VOID
*)&gUnicodeFileTag
);
1498 if (EFI_ERROR (Status
)) {
1499 ShellDeleteFile (&FileHandle
);
1500 return EFI_LOAD_ERROR
;
1504 Cache
= AllocateZeroPool (TotalSize
);
1505 if (Cache
== NULL
) {
1506 ShellDeleteFile (&FileHandle
);
1507 return EFI_OUT_OF_RESOURCES
;
1511 // write all the lines back to disk
1514 Type
= NewLineTypeCarriageReturnLineFeed
;
1517 LeftSize
= TotalSize
;
1519 for (Link
= FileBuffer
.ListHead
->ForwardLink
; Link
!= FileBuffer
.ListHead
; Link
= Link
->ForwardLink
) {
1520 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1522 if (Line
->Type
!= NewLineTypeDefault
) {
1526 // newline character is at most 4 bytes ( two Unicode characters )
1529 if (Line
->Buffer
!= NULL
&& Line
->Size
!= 0) {
1530 if (FileBuffer
.FileType
== FileTypeAscii
) {
1531 Length
+= Line
->Size
;
1533 Length
+= (Line
->Size
* 2);
1536 // end if FileTypeAscii
1541 // no cache room left, so write cache to disk
1543 if (LeftSize
< Length
) {
1544 Size
= TotalSize
- LeftSize
;
1545 Status
= ShellWriteFile (FileHandle
, &Size
, Cache
);
1546 if (EFI_ERROR (Status
)) {
1547 ShellDeleteFile (&FileHandle
);
1549 return EFI_LOAD_ERROR
;
1552 LeftSize
= TotalSize
;
1555 if (Line
->Buffer
!= NULL
&& Line
->Size
!= 0) {
1556 if (FileBuffer
.FileType
== FileTypeAscii
) {
1557 UnicodeToAscii (Line
->Buffer
, Line
->Size
, Ptr
);
1558 Length
= Line
->Size
;
1560 Length
= (Line
->Size
* 2);
1561 CopyMem (Ptr
, (CHAR8
*) Line
->Buffer
, Length
);
1564 // end if FileTypeAscii
1571 // end of if Line -> Buffer != NULL && Line -> Size != 0
1573 // if not the last line , write return buffer to disk
1575 if (Link
->ForwardLink
!= FileBuffer
.ListHead
) {
1576 GetNewLine (Type
, NewLineBuffer
, &NewLineSize
);
1577 CopyMem (Ptr
, (CHAR8
*) NewLineBuffer
, NewLineSize
);
1580 LeftSize
-= NewLineSize
;
1586 if (TotalSize
!= LeftSize
) {
1587 Size
= TotalSize
- LeftSize
;
1588 Status
= ShellWriteFile (FileHandle
, &Size
, Cache
);
1589 if (EFI_ERROR (Status
)) {
1590 ShellDeleteFile (&FileHandle
);
1592 return EFI_LOAD_ERROR
;
1598 ShellCloseFile(&FileHandle
);
1600 FileBuffer
.FileModified
= FALSE
;
1603 // set status string
1605 Str
= CatSPrint (NULL
, L
"%d Lines Wrote", NumLines
);
1607 return EFI_OUT_OF_RESOURCES
;
1610 StatusBarSetStatusString (Str
);
1611 SHELL_FREE_NON_NULL (Str
);
1614 // now everything is ready , you can set the new file name to filebuffer
1616 if (FileName
!= NULL
&& FileBuffer
.FileName
!= NULL
&& StrCmp (FileName
, FileBuffer
.FileName
) != 0) {
1620 FileBufferSetFileName (FileName
);
1621 if (FileBuffer
.FileName
== NULL
) {
1622 ShellDeleteFile (&FileHandle
);
1623 return EFI_OUT_OF_RESOURCES
;
1627 FileBuffer
.ReadOnly
= FALSE
;
1632 Scroll cursor to left 1 character position.
1634 @retval EFI_SUCCESS The operation was successful.
1637 FileBufferScrollLeft (
1641 EFI_EDITOR_LINE
*Line
;
1645 Line
= FileBuffer
.CurrentLine
;
1647 FRow
= FileBuffer
.FilePosition
.Row
;
1648 FCol
= FileBuffer
.FilePosition
.Column
;
1651 // if already at start of this line, so move to the end of previous line
1655 // has previous line
1657 if (Line
->Link
.BackLink
!= FileBuffer
.ListHead
) {
1659 Line
= CR (Line
->Link
.BackLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1660 FCol
= Line
->Size
+ 1;
1666 // if not at start of this line, just move to previous column
1671 FileBufferMovePosition (FRow
, FCol
);
1677 Delete a char in line
1679 @param[in, out] Line The line to delete in.
1680 @param[in] Pos Position to delete the char at ( start from 0 ).
1684 IN OUT EFI_EDITOR_LINE
*Line
,
1691 // move the latter characters front
1693 for (Index
= Pos
- 1; Index
< Line
->Size
; Index
++) {
1694 Line
->Buffer
[Index
] = Line
->Buffer
[Index
+ 1];
1701 Concatenate Src into Dest.
1703 @param[in, out] Dest Destination string
1704 @param[in] Src Src String.
1708 IN OUT EFI_EDITOR_LINE
*Dest
,
1709 IN EFI_EDITOR_LINE
*Src
1717 Dest
->Buffer
[Size
] = 0;
1720 // concatenate the two strings
1722 Str
= CatSPrint (NULL
, L
"%s%s", Dest
->Buffer
, Src
->Buffer
);
1724 Dest
->Buffer
= NULL
;
1728 Dest
->Size
= Size
+ Src
->Size
;
1729 Dest
->TotalSize
= Dest
->Size
;
1731 FreePool (Dest
->Buffer
);
1732 FreePool (Src
->Buffer
);
1735 // put str to dest->buffer
1741 Delete the previous character.
1743 @retval EFI_SUCCESS The delete was successful.
1744 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1747 FileBufferDoBackspace (
1751 EFI_EDITOR_LINE
*Line
;
1752 EFI_EDITOR_LINE
*End
;
1756 FileColumn
= FileBuffer
.FilePosition
.Column
;
1758 Line
= FileBuffer
.CurrentLine
;
1763 if (FileColumn
== 1) {
1767 if (FileBuffer
.FilePosition
.Row
== 1) {
1771 FileBufferScrollLeft ();
1773 Line
= FileBuffer
.CurrentLine
;
1774 Link
= Line
->Link
.ForwardLink
;
1775 End
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1778 // concatenate this line with previous line
1780 LineCat (Line
, End
);
1781 if (Line
->Buffer
== NULL
) {
1782 return EFI_OUT_OF_RESOURCES
;
1785 // remove End from line list
1787 RemoveEntryList (&End
->Link
);
1790 FileBuffer
.NumLines
--;
1792 FileBufferNeedRefresh
= TRUE
;
1793 FileBufferOnlyLineNeedRefresh
= FALSE
;
1797 // just delete the previous character
1799 LineDeleteAt (Line
, FileColumn
- 1);
1800 FileBufferScrollLeft ();
1801 FileBufferOnlyLineNeedRefresh
= TRUE
;
1804 if (!FileBuffer
.FileModified
) {
1805 FileBuffer
.FileModified
= TRUE
;
1812 Add a return into line at current position.
1814 @retval EFI_SUCCESS The insetrion of the character was successful.
1815 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1818 FileBufferDoReturn (
1822 EFI_EDITOR_LINE
*Line
;
1823 EFI_EDITOR_LINE
*NewLine
;
1830 FileBufferNeedRefresh
= TRUE
;
1831 FileBufferOnlyLineNeedRefresh
= FALSE
;
1833 Line
= FileBuffer
.CurrentLine
;
1835 FileColumn
= FileBuffer
.FilePosition
.Column
;
1837 NewLine
= AllocateZeroPool (sizeof (EFI_EDITOR_LINE
));
1838 if (NewLine
== NULL
) {
1839 return EFI_OUT_OF_RESOURCES
;
1842 NewLine
->Signature
= LINE_LIST_SIGNATURE
;
1843 NewLine
->Size
= Line
->Size
- FileColumn
+ 1;
1844 NewLine
->TotalSize
= NewLine
->Size
;
1845 NewLine
->Buffer
= CatSPrint (NULL
, L
"\0");
1846 if (NewLine
->Buffer
== NULL
) {
1847 return EFI_OUT_OF_RESOURCES
;
1850 NewLine
->Type
= NewLineTypeDefault
;
1852 if (NewLine
->Size
> 0) {
1854 // UNICODE + CHAR_NULL
1856 Buffer
= AllocateZeroPool (2 * (NewLine
->Size
+ 1));
1857 if (Buffer
== NULL
) {
1858 FreePool (NewLine
->Buffer
);
1860 return EFI_OUT_OF_RESOURCES
;
1863 FreePool (NewLine
->Buffer
);
1865 NewLine
->Buffer
= Buffer
;
1867 for (Index
= 0; Index
< NewLine
->Size
; Index
++) {
1868 NewLine
->Buffer
[Index
] = Line
->Buffer
[Index
+ FileColumn
- 1];
1871 NewLine
->Buffer
[NewLine
->Size
] = CHAR_NULL
;
1873 Line
->Buffer
[FileColumn
- 1] = CHAR_NULL
;
1874 Line
->Size
= FileColumn
- 1;
1877 // increase NumLines
1879 FileBuffer
.NumLines
++;
1882 // insert it into the correct position of line list
1884 NewLine
->Link
.BackLink
= &(Line
->Link
);
1885 NewLine
->Link
.ForwardLink
= Line
->Link
.ForwardLink
;
1886 Line
->Link
.ForwardLink
->BackLink
= &(NewLine
->Link
);
1887 Line
->Link
.ForwardLink
= &(NewLine
->Link
);
1890 // move cursor to the start of next line
1892 Row
= FileBuffer
.FilePosition
.Row
+ 1;
1895 FileBufferMovePosition (Row
, Col
);
1898 // set file is modified
1900 if (!FileBuffer
.FileModified
) {
1901 FileBuffer
.FileModified
= TRUE
;
1908 Delete current character from current line. This is the effect caused
1914 FileBufferDoDelete (
1918 EFI_EDITOR_LINE
*Line
;
1919 EFI_EDITOR_LINE
*Next
;
1923 Line
= FileBuffer
.CurrentLine
;
1924 FileColumn
= FileBuffer
.FilePosition
.Column
;
1929 if (FileColumn
>= Line
->Size
+ 1) {
1933 if (Line
->Link
.ForwardLink
== FileBuffer
.ListHead
) {
1937 // since last character,
1938 // so will add the next line to this line
1940 Link
= Line
->Link
.ForwardLink
;
1941 Next
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1942 LineCat (Line
, Next
);
1943 if (Line
->Buffer
== NULL
) {
1944 return EFI_OUT_OF_RESOURCES
;
1947 RemoveEntryList (&Next
->Link
);
1950 FileBuffer
.NumLines
--;
1952 FileBufferNeedRefresh
= TRUE
;
1953 FileBufferOnlyLineNeedRefresh
= FALSE
;
1957 // just delete current character
1959 LineDeleteAt (Line
, FileColumn
);
1960 FileBufferOnlyLineNeedRefresh
= TRUE
;
1963 if (!FileBuffer
.FileModified
) {
1964 FileBuffer
.FileModified
= TRUE
;
1971 Scroll cursor to right 1 character.
1973 @retval EFI_SUCCESS The operation was successful.
1976 FileBufferScrollRight (
1980 EFI_EDITOR_LINE
*Line
;
1984 Line
= FileBuffer
.CurrentLine
;
1985 if (Line
->Buffer
== NULL
) {
1989 FRow
= FileBuffer
.FilePosition
.Row
;
1990 FCol
= FileBuffer
.FilePosition
.Column
;
1993 // if already at end of this line, scroll it to the start of next line
1995 if (FCol
> Line
->Size
) {
1999 if (Line
->Link
.ForwardLink
!= FileBuffer
.ListHead
) {
2007 // if not at end of this line, just move to next column
2012 FileBufferMovePosition (FRow
, FCol
);
2018 Insert a char into line
2021 @param[in] Line The line to insert into.
2022 @param[in] Char The char to insert.
2023 @param[in] Pos The position to insert the char at ( start from 0 ).
2024 @param[in] StrSize The current string size ( include CHAR_NULL ),unit is Unicode character.
2026 @return The new string size ( include CHAR_NULL ) ( unit is Unicode character ).
2030 IN EFI_EDITOR_LINE
*Line
,
2037 CHAR16
*TempStringPtr
;
2040 Index
= (StrSize
) * 2;
2045 // do not have free space
2047 if (Line
->TotalSize
<= Line
->Size
) {
2048 Str
= ReallocatePool (Index
, Index
+ 16, Str
);
2053 Line
->TotalSize
+= 8;
2056 // move the later part of the string one character right
2058 TempStringPtr
= Str
;
2059 for (Index
= StrSize
; Index
> Pos
; Index
--) {
2060 TempStringPtr
[Index
] = TempStringPtr
[Index
- 1];
2063 // insert char into it.
2065 TempStringPtr
[Index
] = Char
;
2074 Add a character to the current line.
2076 @param[in] Char The Character to input.
2078 @retval EFI_SUCCESS The input was succesful.
2085 EFI_EDITOR_LINE
*Line
;
2088 Line
= FileBuffer
.CurrentLine
;
2091 // only needs to refresh current line
2093 FileBufferOnlyLineNeedRefresh
= TRUE
;
2096 // when is insert mode, or cursor is at end of this line,
2097 // so insert this character
2098 // or replace the character.
2100 FilePos
= FileBuffer
.FilePosition
.Column
- 1;
2101 if (FileBuffer
.ModeInsert
|| FilePos
+ 1 > Line
->Size
) {
2102 LineStrInsert (Line
, Char
, FilePos
, Line
->Size
+ 1);
2104 Line
->Buffer
[FilePos
] = Char
;
2107 // move cursor to right
2109 FileBufferScrollRight ();
2111 if (!FileBuffer
.FileModified
) {
2112 FileBuffer
.FileModified
= TRUE
;
2119 Handles inputs from characters (ASCII key + Backspace + return)
2121 @param[in] Char The input character.
2123 @retval EFI_SUCCESS The operation was successful.
2124 @retval EFI_LOAD_ERROR There was an error.
2125 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2128 FileBufferDoCharInput (
2129 IN CONST CHAR16 Char
2134 Status
= EFI_SUCCESS
;
2140 case CHAR_BACKSPACE
:
2141 Status
= FileBufferDoBackspace ();
2151 case CHAR_CARRIAGE_RETURN
:
2152 Status
= FileBufferDoReturn ();
2157 // DEAL WITH ASCII CHAR, filter out thing like ctrl+f
2159 if (Char
> 127 || Char
< 32) {
2160 Status
= StatusBarSetStatusString (L
"Unknown Command");
2162 Status
= FileBufferAddChar (Char
);
2173 Scroll cursor to the next line.
2175 @retval EFI_SUCCESS The operation was successful.
2178 FileBufferScrollDown (
2182 EFI_EDITOR_LINE
*Line
;
2186 Line
= FileBuffer
.CurrentLine
;
2187 if (Line
->Buffer
== NULL
) {
2191 FRow
= FileBuffer
.FilePosition
.Row
;
2192 FCol
= FileBuffer
.FilePosition
.Column
;
2197 if (Line
->Link
.ForwardLink
!= FileBuffer
.ListHead
) {
2199 Line
= CR (Line
->Link
.ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2202 // if the next line is not that long, so move to end of next line
2204 if (FCol
> Line
->Size
) {
2205 FCol
= Line
->Size
+ 1;
2212 FileBufferMovePosition (FRow
, FCol
);
2218 Scroll the cursor to previous line.
2220 @retval EFI_SUCCESS The operation was successful.
2223 FileBufferScrollUp (
2227 EFI_EDITOR_LINE
*Line
;
2231 Line
= FileBuffer
.CurrentLine
;
2233 FRow
= FileBuffer
.FilePosition
.Row
;
2234 FCol
= FileBuffer
.FilePosition
.Column
;
2237 // has previous line
2239 if (Line
->Link
.BackLink
!= FileBuffer
.ListHead
) {
2241 Line
= CR (Line
->Link
.BackLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2244 // if previous line is not that long, so move to the end of previous line
2246 if (FCol
> Line
->Size
) {
2247 FCol
= Line
->Size
+ 1;
2254 FileBufferMovePosition (FRow
, FCol
);
2260 Scroll cursor to next page.
2262 @retval EFI_SUCCESS The operation wa successful.
2265 FileBufferPageDown (
2269 EFI_EDITOR_LINE
*Line
;
2274 Line
= FileBuffer
.CurrentLine
;
2276 FRow
= FileBuffer
.FilePosition
.Row
;
2277 FCol
= FileBuffer
.FilePosition
.Column
;
2282 if (FileBuffer
.NumLines
>= FRow
+ (MainEditor
.ScreenSize
.Row
- 2)) {
2283 Gap
= (MainEditor
.ScreenSize
.Row
- 2);
2286 // MOVE CURSOR TO LAST LINE
2288 Gap
= FileBuffer
.NumLines
- FRow
;
2293 Line
= MoveLine (Gap
);
2296 // if that line, is not that long, so move to the end of that line
2298 if (Line
!= NULL
&& FCol
> Line
->Size
) {
2299 FCol
= Line
->Size
+ 1;
2304 FileBufferMovePosition (FRow
, FCol
);
2310 Scroll cursor to previous screen.
2312 @retval EFI_SUCCESS The operation was successful.
2319 EFI_EDITOR_LINE
*Line
;
2325 Line
= FileBuffer
.CurrentLine
;
2327 FRow
= FileBuffer
.FilePosition
.Row
;
2328 FCol
= FileBuffer
.FilePosition
.Column
;
2331 // has previous page
2333 if (FRow
> (MainEditor
.ScreenSize
.Row
- 2)) {
2334 Gap
= (MainEditor
.ScreenSize
.Row
- 2);
2337 // the first line of file will displayed on the first line of screen
2348 Line
= MoveLine (Retreat
);
2351 // if that line is not that long, so move to the end of that line
2353 if (Line
!= NULL
&& FCol
> Line
->Size
) {
2354 FCol
= Line
->Size
+ 1;
2359 FileBufferMovePosition (FRow
, FCol
);
2365 Scroll cursor to end of the current line.
2367 @retval EFI_SUCCESS The operation was successful.
2374 EFI_EDITOR_LINE
*Line
;
2378 Line
= FileBuffer
.CurrentLine
;
2380 FRow
= FileBuffer
.FilePosition
.Row
;
2383 // goto the last column of the line
2385 FCol
= Line
->Size
+ 1;
2387 FileBufferMovePosition (FRow
, FCol
);
2393 Dispatch input to different handler
2394 @param[in] Key The input key. One of:
2398 Direction key: up/down/left/right/pgup/pgdn
2402 @retval EFI_SUCCESS The dispatch was done successfully.
2403 @retval EFI_LOAD_ERROR The dispatch was not successful.
2404 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2407 FileBufferHandleInput (
2408 IN CONST EFI_INPUT_KEY
*Key
2413 Status
= EFI_SUCCESS
;
2415 switch (Key
->ScanCode
) {
2417 // ordinary key input
2420 if (!FileBuffer
.ReadOnly
) {
2421 Status
= FileBufferDoCharInput (Key
->UnicodeChar
);
2423 Status
= StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2432 Status
= FileBufferScrollUp ();
2439 Status
= FileBufferScrollDown ();
2446 Status
= FileBufferScrollRight ();
2453 Status
= FileBufferScrollLeft ();
2460 Status
= FileBufferPageUp ();
2466 case SCAN_PAGE_DOWN
:
2467 Status
= FileBufferPageDown ();
2474 if (!FileBuffer
.ReadOnly
) {
2475 Status
= FileBufferDoDelete ();
2477 Status
= StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2486 FileBufferMovePosition (FileBuffer
.FilePosition
.Row
, 1);
2487 Status
= EFI_SUCCESS
;
2494 Status
= FileBufferEnd ();
2501 FileBuffer
.ModeInsert
= (BOOLEAN
)!FileBuffer
.ModeInsert
;
2502 Status
= EFI_SUCCESS
;
2506 Status
= StatusBarSetStatusString (L
"Unknown Command");
2514 Check user specified FileRow is above current screen.
2516 @param[in] FileRow The row of file position ( start from 1 ).
2518 @retval TRUE It is above the current screen.
2519 @retval FALSE It is not above the current screen.
2522 AboveCurrentScreen (
2527 // if is to the above of the screen
2529 if (FileRow
< FileBuffer
.LowVisibleRange
.Row
) {
2537 Check user specified FileRow is under current screen.
2539 @param[in] FileRow The row of file position ( start from 1 ).
2541 @retval TRUE It is under the current screen.
2542 @retval FALSE It is not under the current screen.
2545 UnderCurrentScreen (
2550 // if is to the under of the screen
2552 if (FileRow
> FileBuffer
.LowVisibleRange
.Row
+ (MainEditor
.ScreenSize
.Row
- 2) - 1) {
2560 Check user specified FileCol is left to current screen.
2562 @param[in] FileCol The column of file position ( start from 1 ).
2564 @retval TRUE It is to the left.
2565 @retval FALSE It is not to the left.
2573 // if is to the left of the screen
2575 if (FileCol
< FileBuffer
.LowVisibleRange
.Column
) {
2583 Check user specified FileCol is right to current screen.
2585 @param[in] FileCol The column of file position ( start from 1 ).
2587 @retval TRUE It is to the right.
2588 @retval FALSE It is not to the right.
2591 RightCurrentScreen (
2596 // if is to the right of the screen
2598 if (FileCol
> FileBuffer
.LowVisibleRange
.Column
+ MainEditor
.ScreenSize
.Column
- 1) {
2606 Advance/Retreat lines and set CurrentLine in FileBuffer to it
2608 @param[in] Count The line number to advance/retreat
2612 @retval NULL An error occured.
2613 @return The line after advance/retreat.
2620 EFI_EDITOR_LINE
*Line
;
2624 AbsCount
= (UINTN
)ABS(Count
);
2625 Line
= InternalEditorMiscLineRetreat (AbsCount
,MainEditor
.FileBuffer
->CurrentLine
,MainEditor
.FileBuffer
->ListHead
);
2627 Line
= InternalEditorMiscLineAdvance ((UINTN
)Count
,MainEditor
.FileBuffer
->CurrentLine
,MainEditor
.FileBuffer
->ListHead
);
2634 MainEditor
.FileBuffer
->CurrentLine
= Line
;
2640 According to cursor's file position, adjust screen display
2642 @param[in] NewFilePosRow The row of file position ( start from 1 ).
2643 @param[in] NewFilePosCol The column of file position ( start from 1 ).
2646 FileBufferMovePosition (
2647 IN CONST UINTN NewFilePosRow
,
2648 IN CONST UINTN NewFilePosCol
2660 // CALCULATE gap between current file position and new file position
2662 RowGap
= NewFilePosRow
- FileBuffer
.FilePosition
.Row
;
2663 ColGap
= NewFilePosCol
- FileBuffer
.FilePosition
.Column
;
2665 Under
= UnderCurrentScreen (NewFilePosRow
);
2666 Above
= AboveCurrentScreen (NewFilePosRow
);
2668 // if is below current screen
2672 // display row will be unchanged
2674 FileBuffer
.FilePosition
.Row
= NewFilePosRow
;
2678 // has enough above line, so display row unchanged
2679 // not has enough above lines, so the first line is at the
2680 // first display line
2682 if (NewFilePosRow
< (FileBuffer
.DisplayPosition
.Row
- 1)) {
2683 FileBuffer
.DisplayPosition
.Row
= NewFilePosRow
+ 1;
2686 FileBuffer
.FilePosition
.Row
= NewFilePosRow
;
2689 // in current screen
2691 FileBuffer
.FilePosition
.Row
= NewFilePosRow
;
2693 Abs
= (UINTN
)ABS(RowGap
);
2694 FileBuffer
.DisplayPosition
.Row
-= Abs
;
2696 FileBuffer
.DisplayPosition
.Row
+= RowGap
;
2701 FileBuffer
.LowVisibleRange
.Row
= FileBuffer
.FilePosition
.Row
- (FileBuffer
.DisplayPosition
.Row
- 2);
2703 Right
= RightCurrentScreen (NewFilePosCol
);
2704 Left
= LeftCurrentScreen (NewFilePosCol
);
2707 // if right to current screen
2711 // display column will be changed to end
2713 FileBuffer
.DisplayPosition
.Column
= MainEditor
.ScreenSize
.Column
;
2714 FileBuffer
.FilePosition
.Column
= NewFilePosCol
;
2718 // has enough left characters , so display row unchanged
2719 // not has enough left characters,
2720 // so the first character is at the first display column
2722 if (NewFilePosCol
< (FileBuffer
.DisplayPosition
.Column
)) {
2723 FileBuffer
.DisplayPosition
.Column
= NewFilePosCol
;
2726 FileBuffer
.FilePosition
.Column
= NewFilePosCol
;
2729 // in current screen
2731 FileBuffer
.FilePosition
.Column
= NewFilePosCol
;
2733 Abs
= (UINTN
)(-ColGap
);
2734 FileBuffer
.DisplayPosition
.Column
-= Abs
;
2736 FileBuffer
.DisplayPosition
.Column
+= ColGap
;
2741 FileBuffer
.LowVisibleRange
.Column
= FileBuffer
.FilePosition
.Column
- (FileBuffer
.DisplayPosition
.Column
- 1);
2744 // let CurrentLine point to correct line;
2746 FileBuffer
.CurrentLine
= MoveCurrentLine (RowGap
);
2751 Cut current line out and return a pointer to it.
2753 @param[out] CutLine Upon a successful return pointer to the pointer to
2754 the allocated cut line.
2756 @retval EFI_SUCCESS The cut was successful.
2757 @retval EFI_NOT_FOUND There was no selection to cut.
2758 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2762 OUT EFI_EDITOR_LINE
**CutLine
2765 EFI_EDITOR_LINE
*Line
;
2766 EFI_EDITOR_LINE
*NewLine
;
2770 if (FileBuffer
.ReadOnly
) {
2771 StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2775 Line
= FileBuffer
.CurrentLine
;
2778 // if is the last dummy line, SO CAN not cut
2780 if (StrCmp (Line
->Buffer
, L
"\0") == 0 && Line
->Link
.ForwardLink
== FileBuffer
.ListHead
2786 // LAST LINE AND NOTHING ON THIS LINE, SO CUT NOTHING
2788 StatusBarSetStatusString (L
"Nothing to Cut");
2789 return EFI_NOT_FOUND
;
2792 // if is the last line, so create a dummy line
2794 if (Line
->Link
.ForwardLink
== FileBuffer
.ListHead
) {
2797 // create a new line
2799 NewLine
= FileBufferCreateLine ();
2800 if (NewLine
== NULL
) {
2801 return EFI_OUT_OF_RESOURCES
;
2805 FileBuffer
.NumLines
--;
2806 Row
= FileBuffer
.FilePosition
.Row
;
2811 FileBuffer
.CurrentLine
= CR (
2812 FileBuffer
.CurrentLine
->Link
.ForwardLink
,
2818 RemoveEntryList (&Line
->Link
);
2820 FileBuffer
.Lines
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2822 FileBufferMovePosition (Row
, Col
);
2824 FileBuffer
.FileModified
= TRUE
;
2825 FileBufferNeedRefresh
= TRUE
;
2826 FileBufferOnlyLineNeedRefresh
= FALSE
;
2834 Paste a line into line list.
2836 @retval EFI_SUCCESS The paste was successful.
2837 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2840 FileBufferPasteLine (
2844 EFI_EDITOR_LINE
*Line
;
2845 EFI_EDITOR_LINE
*NewLine
;
2850 // if nothing is on clip board
2853 if (MainEditor
.CutLine
== NULL
) {
2857 // read only file can not be pasted on
2859 if (FileBuffer
.ReadOnly
) {
2860 StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2864 NewLine
= LineDup (MainEditor
.CutLine
);
2865 if (NewLine
== NULL
) {
2866 return EFI_OUT_OF_RESOURCES
;
2869 // insert it above current line
2871 Line
= FileBuffer
.CurrentLine
;
2872 NewLine
->Link
.BackLink
= Line
->Link
.BackLink
;
2873 NewLine
->Link
.ForwardLink
= &Line
->Link
;
2875 Line
->Link
.BackLink
->ForwardLink
= &NewLine
->Link
;
2876 Line
->Link
.BackLink
= &NewLine
->Link
;
2878 FileBuffer
.NumLines
++;
2879 FileBuffer
.CurrentLine
= NewLine
;
2881 FileBuffer
.Lines
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2887 Row
= FileBuffer
.FilePosition
.Row
;
2889 FileBufferMovePosition (Row
, Col
);
2892 // after paste, set some value so that refresh knows to do something
2894 FileBuffer
.FileModified
= TRUE
;
2895 FileBufferNeedRefresh
= TRUE
;
2896 FileBufferOnlyLineNeedRefresh
= FALSE
;
2902 Search string from current position on in file
2904 @param[in] Str The search string.
2905 @param[in] Offset The offset from current position.
2907 @retval EFI_SUCCESS The operation was successful.
2908 @retval EFI_NOT_FOUND The string Str was not found.
2912 IN CONST CHAR16
*Str
,
2913 IN CONST UINTN Offset
2920 EFI_EDITOR_LINE
*Line
;
2929 // search if in current line
2931 Current
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1 + Offset
;
2933 if (Current
>= (FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.CurrentLine
->Size
)) {
2937 Current
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.CurrentLine
->Size
;
2942 CharPos
= StrStr (Current
, Str
);
2943 if (CharPos
!= NULL
) {
2944 Position
= CharPos
- Current
+ 1;
2952 Column
= (Position
- 1) + FileBuffer
.FilePosition
.Column
+ Offset
;
2953 Row
= FileBuffer
.FilePosition
.Row
;
2956 // not found so find through next lines
2958 Link
= FileBuffer
.CurrentLine
->Link
.ForwardLink
;
2960 Row
= FileBuffer
.FilePosition
.Row
+ 1;
2961 while (Link
!= FileBuffer
.ListHead
) {
2962 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2963 // Position = StrStr (Line->Buffer, Str);
2964 CharPos
= StrStr (Line
->Buffer
, Str
);
2965 if (CharPos
!= NULL
) {
2966 Position
= CharPos
- Line
->Buffer
+ 1;
2979 Link
= Link
->ForwardLink
;
2982 if (Link
== FileBuffer
.ListHead
) {
2990 return EFI_NOT_FOUND
;
2993 FileBufferMovePosition (Row
, Column
);
2996 // call refresh to fresh edit area,
2997 // because the outer may loop to find multiply occurrence of this string
2999 FileBufferRefresh ();
3005 Replace SearchLen characters from current position on with Replace.
3007 This will modify the current buffer at the current position.
3009 @param[in] Replace The string to replace.
3010 @param[in] SearchLen Search string's length.
3012 @retval EFI_SUCCESS The operation was successful.
3013 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3017 IN CONST CHAR16
*Replace
,
3018 IN CONST UINTN SearchLen
3028 ReplaceLen
= StrLen (Replace
);
3030 OldSize
= FileBuffer
.CurrentLine
->Size
+ 1;
3032 // include CHAR_NULL
3034 NewSize
= OldSize
+ (ReplaceLen
- SearchLen
);
3036 if (ReplaceLen
> SearchLen
) {
3038 // do not have the enough space
3040 if (FileBuffer
.CurrentLine
->TotalSize
+ 1 <= NewSize
) {
3041 FileBuffer
.CurrentLine
->Buffer
= ReallocatePool (
3044 FileBuffer
.CurrentLine
->Buffer
3046 FileBuffer
.CurrentLine
->TotalSize
= NewSize
- 1;
3049 if (FileBuffer
.CurrentLine
->Buffer
== NULL
) {
3050 return EFI_OUT_OF_RESOURCES
;
3053 // the end CHAR_NULL character;
3055 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ (NewSize
- 1);
3056 Gap
= ReplaceLen
- SearchLen
;
3059 // keep the latter part
3061 for (Index
= 0; Index
< (FileBuffer
.CurrentLine
->Size
- FileBuffer
.FilePosition
.Column
- SearchLen
+ 2); Index
++) {
3062 *Buffer
= *(Buffer
- Gap
);
3066 // set replace into it
3068 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1;
3069 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3070 Buffer
[Index
] = Replace
[Index
];
3074 if (ReplaceLen
< SearchLen
) {
3075 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1;
3077 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3078 Buffer
[Index
] = Replace
[Index
];
3081 Buffer
+= ReplaceLen
;
3082 Gap
= SearchLen
- ReplaceLen
;
3085 // set replace into it
3087 for (Index
= 0; Index
< (FileBuffer
.CurrentLine
->Size
- FileBuffer
.FilePosition
.Column
- ReplaceLen
+ 2); Index
++) {
3088 *Buffer
= *(Buffer
+ Gap
);
3093 if (ReplaceLen
== SearchLen
) {
3094 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1;
3095 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3096 Buffer
[Index
] = Replace
[Index
];
3100 FileBuffer
.CurrentLine
->Size
+= (ReplaceLen
- SearchLen
);
3102 FileBufferOnlyLineNeedRefresh
= TRUE
;
3104 FileBuffer
.FileModified
= TRUE
;
3106 MainTitleBarRefresh (MainEditor
.FileBuffer
->FileName
, MainEditor
.FileBuffer
->FileType
, MainEditor
.FileBuffer
->ReadOnly
, MainEditor
.FileBuffer
->FileModified
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
, 0, 0);
3107 FileBufferRestorePosition ();
3108 FileBufferRefresh ();
3114 Move the mouse cursor position.
3116 @param[in] TextX The new x-coordinate.
3117 @param[in] TextY The new y-coordinate.
3120 FileBufferAdjustMousePosition (
3121 IN CONST INT32 TextX
,
3122 IN CONST INT32 TextY
3131 // TextX and TextY is mouse movement data returned by mouse driver
3132 // This function will change it to MousePosition
3135 // get absolute value
3141 CoordinateX
= FileBuffer
.MousePosition
.Column
;
3142 CoordinateY
= FileBuffer
.MousePosition
.Row
;
3145 CoordinateX
+= TextX
;
3147 if (CoordinateX
>= AbsX
) {
3148 CoordinateX
-= AbsX
;
3155 CoordinateY
+= TextY
;
3157 if (CoordinateY
>= AbsY
) {
3158 CoordinateY
-= AbsY
;
3164 // check whether new mouse column position is beyond screen
3165 // if not, adjust it
3167 if (CoordinateX
>= 1 && CoordinateX
<= MainEditor
.ScreenSize
.Column
) {
3168 FileBuffer
.MousePosition
.Column
= CoordinateX
;
3169 } else if (CoordinateX
< 1) {
3170 FileBuffer
.MousePosition
.Column
= 1;
3171 } else if (CoordinateX
> MainEditor
.ScreenSize
.Column
) {
3172 FileBuffer
.MousePosition
.Column
= MainEditor
.ScreenSize
.Column
;
3175 // check whether new mouse row position is beyond screen
3176 // if not, adjust it
3178 if (CoordinateY
>= 2 && CoordinateY
<= (MainEditor
.ScreenSize
.Row
- 1)) {
3179 FileBuffer
.MousePosition
.Row
= CoordinateY
;
3180 } else if (CoordinateY
< 2) {
3181 FileBuffer
.MousePosition
.Row
= 2;
3182 } else if (CoordinateY
> (MainEditor
.ScreenSize
.Row
- 1)) {
3183 FileBuffer
.MousePosition
.Row
= (MainEditor
.ScreenSize
.Row
- 1);
3189 Search and replace operation.
3191 @param[in] SearchStr The string to search for.
3192 @param[in] ReplaceStr The string to replace with.
3193 @param[in] Offset The column to start at.
3196 FileBufferReplaceAll (
3197 IN CHAR16
*SearchStr
,
3198 IN CHAR16
*ReplaceStr
,
3211 EFI_EDITOR_LINE
*Line
;
3215 SearchLen
= StrLen (SearchStr
);
3216 ReplaceLen
= StrLen (ReplaceStr
);
3218 Column
= FileBuffer
.FilePosition
.Column
+ Offset
- 1;
3220 if (Column
> FileBuffer
.CurrentLine
->Size
) {
3221 Column
= FileBuffer
.CurrentLine
->Size
;
3224 Link
= &(FileBuffer
.CurrentLine
->Link
);
3226 while (Link
!= FileBuffer
.ListHead
) {
3227 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
3228 CharPos
= StrStr (Line
->Buffer
+ Column
, SearchStr
);
3229 if (CharPos
!= NULL
) {
3230 Position
= CharPos
- Line
->Buffer
;// + Column;
3234 if (ReplaceLen
> SearchLen
) {
3235 OldSize
= Line
->Size
+ 1;
3237 // include CHAR_NULL
3239 NewSize
= OldSize
+ (ReplaceLen
- SearchLen
);
3242 // do not have the enough space
3244 if (Line
->TotalSize
+ 1 <= NewSize
) {
3245 Line
->Buffer
= ReallocatePool (
3250 Line
->TotalSize
= NewSize
- 1;
3253 if (Line
->Buffer
== NULL
) {
3254 return EFI_OUT_OF_RESOURCES
;
3257 // the end CHAR_NULL character;
3259 Buffer
= Line
->Buffer
+ (NewSize
- 1);
3260 Gap
= ReplaceLen
- SearchLen
;
3263 // keep the latter part
3265 for (Index
= 0; Index
< (Line
->Size
- Position
- SearchLen
+ 1); Index
++) {
3266 *Buffer
= *(Buffer
- Gap
);
3270 } else if (ReplaceLen
< SearchLen
){
3271 Buffer
= Line
->Buffer
+ Position
+ ReplaceLen
;
3272 Gap
= SearchLen
- ReplaceLen
;
3274 for (Index
= 0; Index
< (Line
->Size
- Position
- ReplaceLen
+ 1); Index
++) {
3275 *Buffer
= *(Buffer
+ Gap
);
3279 ASSERT(ReplaceLen
== SearchLen
);
3282 // set replace into it
3284 Buffer
= Line
->Buffer
+ Position
;
3285 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3286 Buffer
[Index
] = ReplaceStr
[Index
];
3289 Line
->Size
+= (ReplaceLen
- SearchLen
);
3290 Column
+= ReplaceLen
;
3296 Link
= Link
->ForwardLink
;
3300 // call refresh to fresh edit area
3302 FileBuffer
.FileModified
= TRUE
;
3303 FileBufferNeedRefresh
= TRUE
;
3304 FileBufferRefresh ();
3310 Set the modified state to TRUE.
3313 FileBufferSetModified (
3317 FileBuffer
.FileModified
= TRUE
;