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 occurred.
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
) {
274 if (FileBufferMouseNeedRefresh
) {
275 FileBufferMouseNeedRefresh
= FALSE
;
278 // if mouse position not moved and only mouse action
279 // so do not need to refresh mouse position
281 if ( ((FileBuffer
.MousePosition
.Row
== FileBufferBackupVar
.MousePosition
.Row
) &&
282 (FileBuffer
.MousePosition
.Column
== FileBufferBackupVar
.MousePosition
.Column
))
283 && 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,
334 // set the new mouse position
336 gST
->ConOut
->SetAttribute (gST
->ConOut
, New
.Data
& 0x7F);
339 // clear the old mouse position
341 FRow
= FileBuffer
.LowVisibleRange
.Row
+ FileBuffer
.MousePosition
.Row
- 2;
342 FColumn
= FileBuffer
.LowVisibleRange
.Column
+ FileBuffer
.MousePosition
.Column
- 1;
345 if (FRow
> FileBuffer
.NumLines
) {
346 HasCharacter
= FALSE
;
348 CurrentLine
= FileBuffer
.CurrentLine
;
349 Line
= MoveLine (FRow
- FileBuffer
.FilePosition
.Row
);
351 if ((Line
== NULL
) || (FColumn
> Line
->Size
)) {
352 HasCharacter
= FALSE
;
355 FileBuffer
.CurrentLine
= CurrentLine
;
359 (INT32
)FileBuffer
.MousePosition
.Column
- 1,
360 (INT32
)FileBuffer
.MousePosition
.Row
- 1,
365 Value
= Line
->Buffer
[FColumn
- 1];
367 (INT32
)FileBuffer
.MousePosition
.Column
- 1,
368 (INT32
)FileBuffer
.MousePosition
.Row
- 1,
375 // end of HasCharacter
377 gST
->ConOut
->SetAttribute (gST
->ConOut
, Orig
.Data
);
381 // end of MouseNeedRefresh
386 // end of MouseSupported
392 Free all the lines in FileBuffer
399 @retval EFI_SUCCESS The operation was successful.
402 FileBufferFreeLines (
407 EFI_EDITOR_LINE
*Line
;
410 // free all the lines
412 if (FileBuffer
.Lines
!= NULL
) {
413 Line
= FileBuffer
.Lines
;
414 Link
= &(Line
->Link
);
416 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
417 Link
= Link
->ForwardLink
;
420 // free line's buffer and line itself
423 } while (Link
!= FileBuffer
.ListHead
);
427 // clean the line list related structure
429 FileBuffer
.Lines
= NULL
;
430 FileBuffer
.CurrentLine
= NULL
;
431 FileBuffer
.NumLines
= 0;
433 FileBuffer
.ListHead
->ForwardLink
= FileBuffer
.ListHead
;
434 FileBuffer
.ListHead
->BackLink
= FileBuffer
.ListHead
;
440 Cleanup function for FileBuffer.
442 @retval EFI_SUCCESS The cleanup was successful.
451 SHELL_FREE_NON_NULL (FileBuffer
.FileName
);
454 // free all the lines
456 Status
= FileBufferFreeLines ();
458 SHELL_FREE_NON_NULL (FileBuffer
.ListHead
);
459 FileBuffer
.ListHead
= NULL
;
461 SHELL_FREE_NON_NULL (FileBufferBackupVar
.FileName
);
466 Print a line specified by Line on a row specified by Row of the screen.
468 @param[in] Line The line to print.
469 @param[in] Row The row on the screen to print onto (begin from 1).
471 @retval EFI_SUCCESS The printing was successful.
474 FileBufferPrintLine (
475 IN CONST EFI_EDITOR_LINE
*Line
,
486 // print start from correct character
488 Buffer
= Line
->Buffer
+ FileBuffer
.LowVisibleRange
.Column
- 1;
490 Limit
= Line
->Size
- FileBuffer
.LowVisibleRange
.Column
+ 1;
491 if (Limit
> Line
->Size
) {
495 BufLen
= (MainEditor
.ScreenSize
.Column
+ 1) * sizeof (CHAR16
);
496 PrintLine
= AllocatePool (BufLen
);
497 if (PrintLine
!= NULL
) {
498 StrnCpyS (PrintLine
, BufLen
/sizeof (CHAR16
), Buffer
, MIN (Limit
, MainEditor
.ScreenSize
.Column
));
499 for (Limit
= StrLen (PrintLine
); Limit
< MainEditor
.ScreenSize
.Column
; Limit
++) {
500 PrintLine
[Limit
] = L
' ';
503 PrintLine
[MainEditor
.ScreenSize
.Column
] = CHAR_NULL
;
505 PrintLine2
= AllocatePool (BufLen
* 2);
506 if (PrintLine2
!= NULL
) {
507 ShellCopySearchAndReplace (PrintLine
, PrintLine2
, BufLen
* 2, L
"%", L
"^%", FALSE
, FALSE
);
515 FreePool (PrintLine2
);
518 FreePool (PrintLine
);
525 Set the cursor position according to FileBuffer.DisplayPosition.
527 @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.
556 EFI_EDITOR_LINE
*Line
;
560 // if it's the first time after editor launch, so should refresh
564 // no definite required refresh
565 // and file position displayed on screen has not been changed
567 if (!FileBufferNeedRefresh
&&
568 !FileBufferOnlyLineNeedRefresh
&&
569 (FileBufferBackupVar
.LowVisibleRange
.Row
== FileBuffer
.LowVisibleRange
.Row
) &&
570 (FileBufferBackupVar
.LowVisibleRange
.Column
== FileBuffer
.LowVisibleRange
.Column
)
573 FileBufferRestoreMousePosition ();
574 FileBufferRestorePosition ();
580 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
583 // only need to refresh current line
585 if (FileBufferOnlyLineNeedRefresh
&&
586 (FileBufferBackupVar
.LowVisibleRange
.Row
== FileBuffer
.LowVisibleRange
.Row
) &&
587 (FileBufferBackupVar
.LowVisibleRange
.Column
== FileBuffer
.LowVisibleRange
.Column
)
590 EditorClearLine (FileBuffer
.DisplayPosition
.Row
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
);
591 FileBufferPrintLine (
592 FileBuffer
.CurrentLine
,
593 FileBuffer
.DisplayPosition
.Row
597 // the whole edit area need refresh
603 if (FileBuffer
.Lines
== NULL
) {
604 FileBufferRestoreMousePosition ();
605 FileBufferRestorePosition ();
606 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));
636 // while not file end and not screen full
638 while (Row
<= (MainEditor
.ScreenSize
.Row
- 1)) {
639 EditorClearLine (Row
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
);
644 FileBufferRestoreMousePosition ();
645 FileBufferRestorePosition ();
647 FileBufferNeedRefresh
= FALSE
;
648 FileBufferOnlyLineNeedRefresh
= FALSE
;
650 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
655 Create a new line and append it to the line list.
660 @retval NULL The create line failed.
661 @return The line created.
664 FileBufferCreateLine (
668 EFI_EDITOR_LINE
*Line
;
671 // allocate a line structure
673 Line
= AllocateZeroPool (sizeof (EFI_EDITOR_LINE
));
679 // initialize the structure
681 Line
->Signature
= LINE_LIST_SIGNATURE
;
684 Line
->Type
= NewLineTypeDefault
;
687 // initial buffer of the line is "\0"
689 ASSERT (CHAR_NULL
== CHAR_NULL
);
690 Line
->Buffer
= CatSPrint (NULL
, L
"\0");
691 if (Line
->Buffer
== NULL
) {
695 FileBuffer
.NumLines
++;
698 // insert the line into line list
700 InsertTailList (FileBuffer
.ListHead
, &Line
->Link
);
702 if (FileBuffer
.Lines
== NULL
) {
703 FileBuffer
.Lines
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
710 Set FileName field in FileBuffer.
712 @param Str The file name to set.
714 @retval EFI_SUCCESS The filename was successfully set.
715 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
716 @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
);
731 // free the old file name
733 SHELL_FREE_NON_NULL (FileBuffer
.FileName
);
736 // Allocate and set the new name
738 FileBuffer
.FileName
= CatSPrint (NULL
, L
"%s", Str
);
739 if (FileBuffer
.FileName
== NULL
) {
740 return EFI_OUT_OF_RESOURCES
;
747 Free the existing file lines and reset the modified flag.
749 @retval EFI_SUCCESS The operation was successful.
757 // free all the lines
759 FileBufferFreeLines ();
760 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.
778 IN CONST CHAR16
*FileName
,
779 IN CONST BOOLEAN Recover
782 EFI_EDITOR_LINE
*Line
;
783 EE_NEWLINE_TYPE Type
;
788 CHAR16
*UnicodeBuffer
;
791 SHELL_FILE_HANDLE FileHandle
;
794 UINTN LineSizeBackup
;
800 UnicodeBuffer
= NULL
;
801 Type
= NewLineTypeDefault
;
806 // in this function, when you return error ( except EFI_OUT_OF_RESOURCES )
807 // you should set status string via StatusBarSetStatusString(L"blah")
808 // since this function maybe called before the editorhandleinput loop
809 // so any error will cause editor return
810 // so if you want to print the error status
811 // you should set the status string
815 // try to open the file
817 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
, 0);
819 if (!EFI_ERROR (Status
)) {
821 if (FileHandle
== NULL
) {
822 StatusBarSetStatusString (L
"Disk Error");
823 return EFI_LOAD_ERROR
;
826 Info
= ShellGetFileInfo (FileHandle
);
828 if (Info
->Attribute
& EFI_FILE_DIRECTORY
) {
829 StatusBarSetStatusString (L
"Directory Can Not Be Edited");
831 return EFI_INVALID_PARAMETER
;
834 if (Info
->Attribute
& EFI_FILE_READ_ONLY
) {
835 FileBuffer
.ReadOnly
= TRUE
;
837 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
)
858 StatusBarSetStatusString (L
"Access Denied");
859 } else if ((Status
== EFI_DEVICE_ERROR
) || (Status
== EFI_VOLUME_CORRUPTED
) || (Status
== EFI_VOLUME_FULL
)) {
860 StatusBarSetStatusString (L
"Disk Error");
862 StatusBarSetStatusString (L
"Invalid File Name or Current-working-directory");
868 // it worked. now delete it and move on with the name (now validated)
870 Status
= ShellDeleteFile (&FileHandle
);
871 if (Status
== EFI_WARN_DELETE_FAILURE
) {
872 Status
= EFI_ACCESS_DENIED
;
876 if (EFI_ERROR (Status
)) {
877 StatusBarSetStatusString (L
"Access Denied");
883 // file doesn't exist, so set CreateFile to TRUE
886 FileBuffer
.ReadOnly
= FALSE
;
889 // all the check ends
890 // so now begin to set file name, free lines
892 if (StrCmp (FileName
, FileBuffer
.FileName
) != 0) {
893 FileBufferSetFileName (FileName
);
897 // free the old lines
907 // allocate buffer to read file
909 Buffer
= AllocateZeroPool (FileSize
);
910 if (Buffer
== NULL
) {
911 return EFI_OUT_OF_RESOURCES
;
915 // read file into Buffer
917 Status
= ShellReadFile (FileHandle
, &FileSize
, Buffer
);
918 ShellCloseFile (&FileHandle
);
920 if (EFI_ERROR (Status
)) {
921 StatusBarSetStatusString (L
"Read File Failed");
922 SHELL_FREE_NON_NULL (Buffer
);
923 return EFI_LOAD_ERROR
;
927 // nothing in this file
930 SHELL_FREE_NON_NULL (Buffer
);
932 // since has no head, so only can be an ASCII file
934 FileBuffer
.FileType
= FileTypeAscii
;
939 AsciiBuffer
= Buffer
;
943 // size < Unicode file header, so only can be ASCII file
945 FileBuffer
.FileType
= FileTypeAscii
;
950 if (*(UINT16
*)Buffer
== EFI_UNICODE_BYTE_ORDER_MARK
) {
952 // Unicode file's size should be even
954 if ((FileSize
% 2) != 0) {
955 StatusBarSetStatusString (L
"File Format Wrong");
956 SHELL_FREE_NON_NULL (Buffer
);
957 return EFI_LOAD_ERROR
;
962 FileBuffer
.FileType
= FileTypeUnicode
;
963 UnicodeBuffer
= Buffer
;
966 // pass this 0xff and 0xfe
971 FileBuffer
.FileType
= FileTypeAscii
;
975 // end of AsciiBuffer ==
980 // end of FileSize < 2
981 // all the check ends
982 // so now begin to set file name, free lines
984 if (StrCmp (FileName
, FileBuffer
.FileName
) != 0) {
985 FileBufferSetFileName (FileName
);
989 // free the old lines
994 // parse file content line by line
996 for (LoopVar1
= 0; LoopVar1
< FileSize
; LoopVar1
++) {
997 Type
= NewLineTypeUnknown
;
999 for (LineSize
= LoopVar1
; LineSize
< FileSize
; LineSize
++) {
1000 if (FileBuffer
.FileType
== FileTypeAscii
) {
1001 if (AsciiBuffer
[LineSize
] == CHAR_CARRIAGE_RETURN
) {
1002 Type
= NewLineTypeCarriageReturn
;
1007 if (LineSize
< FileSize
- 1) {
1008 if (AsciiBuffer
[LineSize
+ 1] == CHAR_LINEFEED
) {
1009 Type
= NewLineTypeCarriageReturnLineFeed
;
1014 } else if (AsciiBuffer
[LineSize
] == CHAR_LINEFEED
) {
1015 Type
= NewLineTypeLineFeed
;
1020 if (LineSize
< FileSize
- 1) {
1021 if (AsciiBuffer
[LineSize
+ 1] == CHAR_CARRIAGE_RETURN
) {
1022 Type
= NewLineTypeLineFeedCarriageReturn
;
1029 if (UnicodeBuffer
[LineSize
] == CHAR_CARRIAGE_RETURN
) {
1030 Type
= NewLineTypeCarriageReturn
;
1035 if (LineSize
< FileSize
- 1) {
1036 if (UnicodeBuffer
[LineSize
+ 1] == CHAR_LINEFEED
) {
1037 Type
= NewLineTypeCarriageReturnLineFeed
;
1042 } else if (UnicodeBuffer
[LineSize
] == CHAR_LINEFEED
) {
1043 Type
= NewLineTypeLineFeed
;
1048 if (LineSize
< FileSize
- 1) {
1049 if (UnicodeBuffer
[LineSize
+ 1] == CHAR_CARRIAGE_RETURN
) {
1050 Type
= NewLineTypeLineFeedCarriageReturn
;
1064 // end of for LineSize
1066 // if the type is wrong, then exit
1068 if (Type
== NewLineTypeUnknown
) {
1070 // Now if Type is NewLineTypeUnknown, it should be file end
1072 Type
= NewLineTypeDefault
;
1075 LineSizeBackup
= LineSize
;
1078 // create a new line
1080 Line
= FileBufferCreateLine ();
1082 SHELL_FREE_NON_NULL (Buffer
);
1083 return EFI_OUT_OF_RESOURCES
;
1087 // calculate file length
1089 LineSize
-= LoopVar1
;
1092 // Unicode and one CHAR_NULL
1094 SHELL_FREE_NON_NULL (Line
->Buffer
);
1095 Line
->Buffer
= AllocateZeroPool (LineSize
* 2 + 2);
1097 if (Line
->Buffer
== NULL
) {
1098 RemoveEntryList (&Line
->Link
);
1099 return EFI_OUT_OF_RESOURCES
;
1103 // copy this line to Line->Buffer
1105 for (LoopVar2
= 0; LoopVar2
< LineSize
; LoopVar2
++) {
1106 if (FileBuffer
.FileType
== FileTypeAscii
) {
1107 Line
->Buffer
[LoopVar2
] = (CHAR16
)AsciiBuffer
[LoopVar1
];
1109 Line
->Buffer
[LoopVar2
] = UnicodeBuffer
[LoopVar1
];
1116 // LoopVar1 now points to where CHAR_CARRIAGE_RETURN or CHAR_LINEFEED;
1118 Line
->Buffer
[LineSize
] = 0;
1120 Line
->Size
= LineSize
;
1121 Line
->TotalSize
= LineSize
;
1124 if ((Type
== NewLineTypeCarriageReturnLineFeed
) || (Type
== NewLineTypeLineFeedCarriageReturn
)) {
1129 // last character is a return, SO create a new line
1131 if ((((Type
== NewLineTypeCarriageReturnLineFeed
) || (Type
== NewLineTypeLineFeedCarriageReturn
)) && (LineSizeBackup
== FileSize
- 2)) ||
1132 (((Type
== NewLineTypeLineFeed
) || (Type
== NewLineTypeCarriageReturn
)) && (LineSizeBackup
== FileSize
- 1))
1135 Line
= FileBufferCreateLine ();
1137 SHELL_FREE_NON_NULL (Buffer
);
1138 return EFI_OUT_OF_RESOURCES
;
1150 SHELL_FREE_NON_NULL (Buffer
);
1154 // end of if CreateFile
1158 FileBuffer
.DisplayPosition
.Row
= 2;
1159 FileBuffer
.DisplayPosition
.Column
= 1;
1160 FileBuffer
.LowVisibleRange
.Row
= 1;
1161 FileBuffer
.LowVisibleRange
.Column
= 1;
1162 FileBuffer
.FilePosition
.Row
= 1;
1163 FileBuffer
.FilePosition
.Column
= 1;
1164 FileBuffer
.MousePosition
.Row
= 2;
1165 FileBuffer
.MousePosition
.Column
= 1;
1168 UnicodeBuffer
= CatSPrint (NULL
, L
"%d Lines Read", FileBuffer
.NumLines
);
1169 if (UnicodeBuffer
== NULL
) {
1170 return EFI_OUT_OF_RESOURCES
;
1173 StatusBarSetStatusString (UnicodeBuffer
);
1174 FreePool (UnicodeBuffer
);
1179 // check whether we have fs?: in filename
1182 FSMappingPtr = NULL;
1183 while (FileName[LoopVar1] != 0) {
1184 if (FileName[LoopVar1] == L':') {
1185 FSMappingPtr = &FileName[LoopVar1];
1192 if (FSMappingPtr == NULL) {
1193 CurDir = ShellGetCurrentDir (NULL);
1197 while (FileName[LoopVar1] != 0) {
1198 if (FileName[LoopVar1] == L':') {
1202 FSMapping[LoopVar2++] = FileName[LoopVar1];
1207 FSMapping[LoopVar2] = 0;
1208 CurDir = ShellGetCurrentDir (FSMapping);
1211 if (CurDir != NULL) {
1212 for (LoopVar1 = 0; LoopVar1 < StrLen (CurDir) && CurDir[LoopVar1] != ':'; LoopVar1++);
1214 CurDir[LoopVar1] = 0;
1215 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) ShellGetMap (CurDir);
1218 return EFI_LOAD_ERROR;
1221 Status = LibDevicePathToInterface (
1222 &gEfiSimpleFileSystemProtocolGuid,
1226 if (EFI_ERROR (Status)) {
1227 return EFI_LOAD_ERROR;
1230 Status = Vol->OpenVolume (Vol, &RootFs);
1231 if (EFI_ERROR (Status)) {
1232 return EFI_LOAD_ERROR;
1235 // Get volume information of file system
1237 Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + 100;
1238 VolumeInfo = (EFI_FILE_SYSTEM_INFO *) AllocateZeroPool (Size);
1239 Status = RootFs->GetInfo (RootFs, &gEfiFileSystemInfoGuid, &Size, VolumeInfo);
1240 if (EFI_ERROR (Status)) {
1241 RootFs->Close (RootFs);
1242 return EFI_LOAD_ERROR;
1245 if (VolumeInfo->ReadOnly) {
1246 StatusBarSetStatusString (L"WARNING: Volume Read Only");
1249 FreePool (VolumeInfo);
1250 RootFs->Close (RootFs);
1257 if (FileBuffer
.Lines
!= 0) {
1258 FileBuffer
.CurrentLine
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1261 // create a dummy line
1263 Line
= FileBufferCreateLine ();
1265 return EFI_OUT_OF_RESOURCES
;
1268 FileBuffer
.CurrentLine
= Line
;
1271 FileBuffer
.FileModified
= FALSE
;
1272 FileBufferNeedRefresh
= TRUE
;
1273 FileBufferOnlyLineNeedRefresh
= FALSE
;
1274 FileBufferMouseNeedRefresh
= TRUE
;
1280 According to FileBuffer.NewLineType & FileBuffer.FileType,
1281 get the return buffer and size.
1283 @param[in] Type The type of line.
1284 @param[out] Buffer The buffer to fill.
1285 @param[out] Size The amount of the buffer used on return.
1289 IN CONST EE_NEWLINE_TYPE Type
,
1297 // give new line buffer,
1298 // and will judge unicode or ascii
1303 // not legal new line type
1305 if ((Type
!= NewLineTypeLineFeed
) && (Type
!= NewLineTypeCarriageReturn
) && (Type
!= NewLineTypeCarriageReturnLineFeed
) && (Type
!= NewLineTypeLineFeedCarriageReturn
)) {
1311 // use_cr: give 0x0d
1313 if (Type
== NewLineTypeCarriageReturn
) {
1314 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1323 *Size
= NewLineSize
;
1328 // use_lf: give 0x0a
1330 if (Type
== NewLineTypeLineFeed
) {
1331 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1340 *Size
= NewLineSize
;
1345 // use_crlf: give 0x0d 0x0a
1347 if (Type
== NewLineTypeCarriageReturnLineFeed
) {
1348 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1361 *Size
= NewLineSize
;
1366 // use_lfcr: give 0x0a 0x0d
1368 if (Type
== NewLineTypeLineFeedCarriageReturn
) {
1369 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1382 *Size
= NewLineSize
;
1388 Change a Unicode string to an ASCII string.
1390 @param[in] UStr The Unicode string.
1391 @param[in] Length The maximum size of AStr.
1392 @param[out] AStr ASCII string to pass out.
1394 @return The actuall length.
1398 IN CONST CHAR16
*UStr
,
1399 IN CONST UINTN Length
,
1406 // just buffer copy, not character copy
1408 for (Index
= 0; Index
< Length
; Index
++) {
1409 *AStr
++ = (CHAR8
)*UStr
++;
1416 Save lines in FileBuffer to disk
1418 @param[in] FileName The file name for writing.
1420 @retval EFI_SUCCESS Data was written.
1421 @retval EFI_LOAD_ERROR
1422 @retval EFI_OUT_OF_RESOURCES There were not enough resources to write the file.
1426 IN CONST CHAR16
*FileName
1429 SHELL_FILE_HANDLE FileHandle
;
1431 EFI_EDITOR_LINE
*Line
;
1437 CHAR8 NewLineBuffer
[4];
1440 EFI_FILE_INFO
*Info
;
1444 EE_NEWLINE_TYPE Type
;
1459 TotalSize
= 0x200000;
1464 // if is the old file
1466 if ((FileBuffer
.FileName
!= NULL
) && (StrCmp (FileName
, FileBuffer
.FileName
) == 0)) {
1468 // file has not been modified
1470 if (!FileBuffer
.FileModified
) {
1475 // if file is read-only, set error
1477 if (FileBuffer
.ReadOnly
) {
1478 StatusBarSetStatusString (L
"Read Only File Can Not Be Saved");
1483 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
|EFI_FILE_MODE_WRITE
, 0);
1485 if (!EFI_ERROR (Status
)) {
1486 Info
= ShellGetFileInfo (FileHandle
);
1488 if ((Info
!= NULL
) && Info
->Attribute
& EFI_FILE_DIRECTORY
) {
1489 StatusBarSetStatusString (L
"Directory Can Not Be Saved");
1490 ShellCloseFile (&FileHandle
);
1492 return EFI_LOAD_ERROR
;
1496 Attribute
= Info
->Attribute
& ~EFI_FILE_READ_ONLY
;
1501 // if file exits, so delete it
1503 Status
= ShellDeleteFile (&FileHandle
);
1504 if (EFI_ERROR (Status
) || (Status
== EFI_WARN_DELETE_FAILURE
)) {
1505 StatusBarSetStatusString (L
"Write File Failed");
1506 return EFI_LOAD_ERROR
;
1510 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
|EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_CREATE
, Attribute
);
1512 if (EFI_ERROR (Status
)) {
1513 StatusBarSetStatusString (L
"Create File Failed");
1514 return EFI_LOAD_ERROR
;
1518 // if file is Unicode file, write Unicode header to it.
1520 if (FileBuffer
.FileType
== FileTypeUnicode
) {
1522 Status
= ShellWriteFile (FileHandle
, &Length
, (VOID
*)&gUnicodeFileTag
);
1523 if (EFI_ERROR (Status
)) {
1524 ShellDeleteFile (&FileHandle
);
1525 return EFI_LOAD_ERROR
;
1529 Cache
= AllocateZeroPool (TotalSize
);
1530 if (Cache
== NULL
) {
1531 ShellDeleteFile (&FileHandle
);
1532 return EFI_OUT_OF_RESOURCES
;
1536 // write all the lines back to disk
1539 Type
= NewLineTypeCarriageReturnLineFeed
;
1542 LeftSize
= TotalSize
;
1544 for (Link
= FileBuffer
.ListHead
->ForwardLink
; Link
!= FileBuffer
.ListHead
; Link
= Link
->ForwardLink
) {
1545 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1547 if (Line
->Type
!= NewLineTypeDefault
) {
1552 // newline character is at most 4 bytes ( two Unicode characters )
1555 if ((Line
->Buffer
!= NULL
) && (Line
->Size
!= 0)) {
1556 if (FileBuffer
.FileType
== FileTypeAscii
) {
1557 Length
+= Line
->Size
;
1559 Length
+= (Line
->Size
* 2);
1563 // end if FileTypeAscii
1568 // no cache room left, so write cache to disk
1570 if (LeftSize
< Length
) {
1571 Size
= TotalSize
- LeftSize
;
1572 Status
= ShellWriteFile (FileHandle
, &Size
, Cache
);
1573 if (EFI_ERROR (Status
)) {
1574 ShellDeleteFile (&FileHandle
);
1576 return EFI_LOAD_ERROR
;
1580 LeftSize
= TotalSize
;
1583 if ((Line
->Buffer
!= NULL
) && (Line
->Size
!= 0)) {
1584 if (FileBuffer
.FileType
== FileTypeAscii
) {
1585 UnicodeToAscii (Line
->Buffer
, Line
->Size
, Ptr
);
1586 Length
= Line
->Size
;
1588 Length
= (Line
->Size
* 2);
1589 CopyMem (Ptr
, (CHAR8
*)Line
->Buffer
, Length
);
1593 // end if FileTypeAscii
1600 // end of if Line -> Buffer != NULL && Line -> Size != 0
1602 // if not the last line , write return buffer to disk
1604 if (Link
->ForwardLink
!= FileBuffer
.ListHead
) {
1605 GetNewLine (Type
, NewLineBuffer
, &NewLineSize
);
1606 CopyMem (Ptr
, (CHAR8
*)NewLineBuffer
, NewLineSize
);
1609 LeftSize
-= NewLineSize
;
1615 if (TotalSize
!= LeftSize
) {
1616 Size
= TotalSize
- LeftSize
;
1617 Status
= ShellWriteFile (FileHandle
, &Size
, Cache
);
1618 if (EFI_ERROR (Status
)) {
1619 ShellDeleteFile (&FileHandle
);
1621 return EFI_LOAD_ERROR
;
1627 ShellCloseFile (&FileHandle
);
1629 FileBuffer
.FileModified
= FALSE
;
1632 // set status string
1634 Str
= CatSPrint (NULL
, L
"%d Lines Written", NumLines
);
1636 return EFI_OUT_OF_RESOURCES
;
1639 StatusBarSetStatusString (Str
);
1640 SHELL_FREE_NON_NULL (Str
);
1643 // now everything is ready , you can set the new file name to filebuffer
1645 if ((FileName
!= NULL
) && (FileBuffer
.FileName
!= NULL
) && (StrCmp (FileName
, FileBuffer
.FileName
) != 0)) {
1649 FileBufferSetFileName (FileName
);
1650 if (FileBuffer
.FileName
== NULL
) {
1651 ShellDeleteFile (&FileHandle
);
1652 return EFI_OUT_OF_RESOURCES
;
1656 FileBuffer
.ReadOnly
= FALSE
;
1661 Scroll cursor to left 1 character position.
1663 @retval EFI_SUCCESS The operation was successful.
1666 FileBufferScrollLeft (
1670 EFI_EDITOR_LINE
*Line
;
1674 Line
= FileBuffer
.CurrentLine
;
1676 FRow
= FileBuffer
.FilePosition
.Row
;
1677 FCol
= FileBuffer
.FilePosition
.Column
;
1680 // if already at start of this line, so move to the end of previous line
1684 // has previous line
1686 if (Line
->Link
.BackLink
!= FileBuffer
.ListHead
) {
1688 Line
= CR (Line
->Link
.BackLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1689 FCol
= Line
->Size
+ 1;
1695 // if not at start of this line, just move to previous column
1700 FileBufferMovePosition (FRow
, FCol
);
1706 Delete a char in line
1708 @param[in, out] Line The line to delete in.
1709 @param[in] Pos Position to delete the char at ( start from 0 ).
1713 IN OUT EFI_EDITOR_LINE
*Line
,
1720 // move the latter characters front
1722 for (Index
= Pos
- 1; Index
< Line
->Size
; Index
++) {
1723 Line
->Buffer
[Index
] = Line
->Buffer
[Index
+ 1];
1730 Concatenate Src into Dest.
1732 @param[in, out] Dest Destination string
1733 @param[in] Src Src String.
1737 IN OUT EFI_EDITOR_LINE
*Dest
,
1738 IN EFI_EDITOR_LINE
*Src
1746 Dest
->Buffer
[Size
] = 0;
1749 // concatenate the two strings
1751 Str
= CatSPrint (NULL
, L
"%s%s", Dest
->Buffer
, Src
->Buffer
);
1753 Dest
->Buffer
= NULL
;
1757 Dest
->Size
= Size
+ Src
->Size
;
1758 Dest
->TotalSize
= Dest
->Size
;
1760 FreePool (Dest
->Buffer
);
1761 FreePool (Src
->Buffer
);
1764 // put str to dest->buffer
1770 Delete the previous character.
1772 @retval EFI_SUCCESS The delete was successful.
1773 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1776 FileBufferDoBackspace (
1780 EFI_EDITOR_LINE
*Line
;
1781 EFI_EDITOR_LINE
*End
;
1785 FileColumn
= FileBuffer
.FilePosition
.Column
;
1787 Line
= FileBuffer
.CurrentLine
;
1792 if (FileColumn
== 1) {
1796 if (FileBuffer
.FilePosition
.Row
== 1) {
1800 FileBufferScrollLeft ();
1802 Line
= FileBuffer
.CurrentLine
;
1803 Link
= Line
->Link
.ForwardLink
;
1804 End
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1807 // concatenate this line with previous line
1809 LineCat (Line
, End
);
1810 if (Line
->Buffer
== NULL
) {
1811 return EFI_OUT_OF_RESOURCES
;
1815 // remove End from line list
1817 RemoveEntryList (&End
->Link
);
1820 FileBuffer
.NumLines
--;
1822 FileBufferNeedRefresh
= TRUE
;
1823 FileBufferOnlyLineNeedRefresh
= FALSE
;
1826 // just delete the previous character
1828 LineDeleteAt (Line
, FileColumn
- 1);
1829 FileBufferScrollLeft ();
1830 FileBufferOnlyLineNeedRefresh
= TRUE
;
1833 if (!FileBuffer
.FileModified
) {
1834 FileBuffer
.FileModified
= TRUE
;
1841 Add a return into line at current position.
1843 @retval EFI_SUCCESS The insetrion of the character was successful.
1844 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1847 FileBufferDoReturn (
1851 EFI_EDITOR_LINE
*Line
;
1852 EFI_EDITOR_LINE
*NewLine
;
1859 FileBufferNeedRefresh
= TRUE
;
1860 FileBufferOnlyLineNeedRefresh
= FALSE
;
1862 Line
= FileBuffer
.CurrentLine
;
1864 FileColumn
= FileBuffer
.FilePosition
.Column
;
1866 NewLine
= AllocateZeroPool (sizeof (EFI_EDITOR_LINE
));
1867 if (NewLine
== NULL
) {
1868 return EFI_OUT_OF_RESOURCES
;
1871 NewLine
->Signature
= LINE_LIST_SIGNATURE
;
1872 NewLine
->Size
= Line
->Size
- FileColumn
+ 1;
1873 NewLine
->TotalSize
= NewLine
->Size
;
1874 NewLine
->Buffer
= CatSPrint (NULL
, L
"\0");
1875 if (NewLine
->Buffer
== NULL
) {
1876 return EFI_OUT_OF_RESOURCES
;
1879 NewLine
->Type
= NewLineTypeDefault
;
1881 if (NewLine
->Size
> 0) {
1883 // UNICODE + CHAR_NULL
1885 Buffer
= AllocateZeroPool (2 * (NewLine
->Size
+ 1));
1886 if (Buffer
== NULL
) {
1887 FreePool (NewLine
->Buffer
);
1889 return EFI_OUT_OF_RESOURCES
;
1892 FreePool (NewLine
->Buffer
);
1894 NewLine
->Buffer
= Buffer
;
1896 for (Index
= 0; Index
< NewLine
->Size
; Index
++) {
1897 NewLine
->Buffer
[Index
] = Line
->Buffer
[Index
+ FileColumn
- 1];
1900 NewLine
->Buffer
[NewLine
->Size
] = CHAR_NULL
;
1902 Line
->Buffer
[FileColumn
- 1] = CHAR_NULL
;
1903 Line
->Size
= FileColumn
- 1;
1907 // increase NumLines
1909 FileBuffer
.NumLines
++;
1912 // insert it into the correct position of line list
1914 NewLine
->Link
.BackLink
= &(Line
->Link
);
1915 NewLine
->Link
.ForwardLink
= Line
->Link
.ForwardLink
;
1916 Line
->Link
.ForwardLink
->BackLink
= &(NewLine
->Link
);
1917 Line
->Link
.ForwardLink
= &(NewLine
->Link
);
1920 // move cursor to the start of next line
1922 Row
= FileBuffer
.FilePosition
.Row
+ 1;
1925 FileBufferMovePosition (Row
, Col
);
1928 // set file is modified
1930 if (!FileBuffer
.FileModified
) {
1931 FileBuffer
.FileModified
= TRUE
;
1938 Delete current character from current line. This is the effect caused
1944 FileBufferDoDelete (
1948 EFI_EDITOR_LINE
*Line
;
1949 EFI_EDITOR_LINE
*Next
;
1953 Line
= FileBuffer
.CurrentLine
;
1954 FileColumn
= FileBuffer
.FilePosition
.Column
;
1959 if (FileColumn
>= Line
->Size
+ 1) {
1963 if (Line
->Link
.ForwardLink
== FileBuffer
.ListHead
) {
1968 // since last character,
1969 // so will add the next line to this line
1971 Link
= Line
->Link
.ForwardLink
;
1972 Next
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1973 LineCat (Line
, Next
);
1974 if (Line
->Buffer
== NULL
) {
1975 return EFI_OUT_OF_RESOURCES
;
1978 RemoveEntryList (&Next
->Link
);
1981 FileBuffer
.NumLines
--;
1983 FileBufferNeedRefresh
= TRUE
;
1984 FileBufferOnlyLineNeedRefresh
= FALSE
;
1987 // just delete current character
1989 LineDeleteAt (Line
, FileColumn
);
1990 FileBufferOnlyLineNeedRefresh
= TRUE
;
1993 if (!FileBuffer
.FileModified
) {
1994 FileBuffer
.FileModified
= TRUE
;
2001 Scroll cursor to right 1 character.
2003 @retval EFI_SUCCESS The operation was successful.
2006 FileBufferScrollRight (
2010 EFI_EDITOR_LINE
*Line
;
2014 Line
= FileBuffer
.CurrentLine
;
2015 if (Line
->Buffer
== NULL
) {
2019 FRow
= FileBuffer
.FilePosition
.Row
;
2020 FCol
= FileBuffer
.FilePosition
.Column
;
2023 // if already at end of this line, scroll it to the start of next line
2025 if (FCol
> Line
->Size
) {
2029 if (Line
->Link
.ForwardLink
!= FileBuffer
.ListHead
) {
2037 // if not at end of this line, just move to next column
2042 FileBufferMovePosition (FRow
, FCol
);
2048 Insert a char into line
2051 @param[in] Line The line to insert into.
2052 @param[in] Char The char to insert.
2053 @param[in] Pos The position to insert the char at ( start from 0 ).
2054 @param[in] StrSize The current string size ( include CHAR_NULL ),unit is Unicode character.
2056 @return The new string size ( include CHAR_NULL ) ( unit is Unicode character ).
2060 IN EFI_EDITOR_LINE
*Line
,
2067 CHAR16
*TempStringPtr
;
2070 Index
= (StrSize
) * 2;
2075 // do not have free space
2077 if (Line
->TotalSize
<= Line
->Size
) {
2078 Str
= ReallocatePool (Index
, Index
+ 16, Str
);
2083 Line
->TotalSize
+= 8;
2087 // move the later part of the string one character right
2089 TempStringPtr
= Str
;
2090 for (Index
= StrSize
; Index
> Pos
; Index
--) {
2091 TempStringPtr
[Index
] = TempStringPtr
[Index
- 1];
2095 // insert char into it.
2097 TempStringPtr
[Index
] = Char
;
2106 Add a character to the current line.
2108 @param[in] Char The Character to input.
2110 @retval EFI_SUCCESS The input was succesful.
2117 EFI_EDITOR_LINE
*Line
;
2120 Line
= FileBuffer
.CurrentLine
;
2123 // only needs to refresh current line
2125 FileBufferOnlyLineNeedRefresh
= TRUE
;
2128 // when is insert mode, or cursor is at end of this line,
2129 // so insert this character
2130 // or replace the character.
2132 FilePos
= FileBuffer
.FilePosition
.Column
- 1;
2133 if (FileBuffer
.ModeInsert
|| (FilePos
+ 1 > Line
->Size
)) {
2134 LineStrInsert (Line
, Char
, FilePos
, Line
->Size
+ 1);
2136 Line
->Buffer
[FilePos
] = Char
;
2140 // move cursor to right
2142 FileBufferScrollRight ();
2144 if (!FileBuffer
.FileModified
) {
2145 FileBuffer
.FileModified
= TRUE
;
2152 Handles inputs from characters (ASCII key + Backspace + return)
2154 @param[in] Char The input character.
2156 @retval EFI_SUCCESS The operation was successful.
2157 @retval EFI_LOAD_ERROR There was an error.
2158 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2161 FileBufferDoCharInput (
2162 IN CONST CHAR16 Char
2167 Status
= EFI_SUCCESS
;
2173 case CHAR_BACKSPACE
:
2174 Status
= FileBufferDoBackspace ();
2184 case CHAR_CARRIAGE_RETURN
:
2185 Status
= FileBufferDoReturn ();
2190 // DEAL WITH ASCII CHAR, filter out thing like ctrl+f
2192 if ((Char
> 127) || (Char
< 32)) {
2193 Status
= StatusBarSetStatusString (L
"Unknown Command");
2195 Status
= FileBufferAddChar (Char
);
2205 Scroll cursor to the next line.
2207 @retval EFI_SUCCESS The operation was successful.
2210 FileBufferScrollDown (
2214 EFI_EDITOR_LINE
*Line
;
2218 Line
= FileBuffer
.CurrentLine
;
2219 if (Line
->Buffer
== NULL
) {
2223 FRow
= FileBuffer
.FilePosition
.Row
;
2224 FCol
= FileBuffer
.FilePosition
.Column
;
2229 if (Line
->Link
.ForwardLink
!= FileBuffer
.ListHead
) {
2231 Line
= CR (Line
->Link
.ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2234 // if the next line is not that long, so move to end of next line
2236 if (FCol
> Line
->Size
) {
2237 FCol
= Line
->Size
+ 1;
2243 FileBufferMovePosition (FRow
, FCol
);
2249 Scroll the cursor to previous line.
2251 @retval EFI_SUCCESS The operation was successful.
2254 FileBufferScrollUp (
2258 EFI_EDITOR_LINE
*Line
;
2262 Line
= FileBuffer
.CurrentLine
;
2264 FRow
= FileBuffer
.FilePosition
.Row
;
2265 FCol
= FileBuffer
.FilePosition
.Column
;
2268 // has previous line
2270 if (Line
->Link
.BackLink
!= FileBuffer
.ListHead
) {
2272 Line
= CR (Line
->Link
.BackLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2275 // if previous line is not that long, so move to the end of previous line
2277 if (FCol
> Line
->Size
) {
2278 FCol
= Line
->Size
+ 1;
2284 FileBufferMovePosition (FRow
, FCol
);
2290 Scroll cursor to next page.
2292 @retval EFI_SUCCESS The operation wa successful.
2295 FileBufferPageDown (
2299 EFI_EDITOR_LINE
*Line
;
2304 Line
= FileBuffer
.CurrentLine
;
2306 FRow
= FileBuffer
.FilePosition
.Row
;
2307 FCol
= FileBuffer
.FilePosition
.Column
;
2312 if (FileBuffer
.NumLines
>= FRow
+ (MainEditor
.ScreenSize
.Row
- 2)) {
2313 Gap
= (MainEditor
.ScreenSize
.Row
- 2);
2316 // MOVE CURSOR TO LAST LINE
2318 Gap
= FileBuffer
.NumLines
- FRow
;
2324 Line
= MoveLine (Gap
);
2327 // if that line, is not that long, so move to the end of that line
2329 if ((Line
!= NULL
) && (FCol
> Line
->Size
)) {
2330 FCol
= Line
->Size
+ 1;
2335 FileBufferMovePosition (FRow
, FCol
);
2341 Scroll cursor to previous screen.
2343 @retval EFI_SUCCESS The operation was successful.
2350 EFI_EDITOR_LINE
*Line
;
2356 Line
= FileBuffer
.CurrentLine
;
2358 FRow
= FileBuffer
.FilePosition
.Row
;
2359 FCol
= FileBuffer
.FilePosition
.Column
;
2362 // has previous page
2364 if (FRow
> (MainEditor
.ScreenSize
.Row
- 2)) {
2365 Gap
= (MainEditor
.ScreenSize
.Row
- 2);
2368 // the first line of file will displayed on the first line of screen
2379 Line
= MoveLine (Retreat
);
2382 // if that line is not that long, so move to the end of that line
2384 if ((Line
!= NULL
) && (FCol
> Line
->Size
)) {
2385 FCol
= Line
->Size
+ 1;
2390 FileBufferMovePosition (FRow
, FCol
);
2396 Scroll cursor to end of the current line.
2398 @retval EFI_SUCCESS The operation was successful.
2405 EFI_EDITOR_LINE
*Line
;
2409 Line
= FileBuffer
.CurrentLine
;
2411 FRow
= FileBuffer
.FilePosition
.Row
;
2414 // goto the last column of the line
2416 FCol
= Line
->Size
+ 1;
2418 FileBufferMovePosition (FRow
, FCol
);
2424 Dispatch input to different handler
2425 @param[in] Key The input key. One of:
2429 Direction key: up/down/left/right/pgup/pgdn
2433 @retval EFI_SUCCESS The dispatch was done successfully.
2434 @retval EFI_LOAD_ERROR The dispatch was not successful.
2435 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2438 FileBufferHandleInput (
2439 IN CONST EFI_INPUT_KEY
*Key
2444 Status
= EFI_SUCCESS
;
2446 switch (Key
->ScanCode
) {
2448 // ordinary key input
2451 if (!FileBuffer
.ReadOnly
) {
2452 Status
= FileBufferDoCharInput (Key
->UnicodeChar
);
2454 Status
= StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2463 Status
= FileBufferScrollUp ();
2470 Status
= FileBufferScrollDown ();
2477 Status
= FileBufferScrollRight ();
2484 Status
= FileBufferScrollLeft ();
2491 Status
= FileBufferPageUp ();
2497 case SCAN_PAGE_DOWN
:
2498 Status
= FileBufferPageDown ();
2505 if (!FileBuffer
.ReadOnly
) {
2506 Status
= FileBufferDoDelete ();
2508 Status
= StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2517 FileBufferMovePosition (FileBuffer
.FilePosition
.Row
, 1);
2518 Status
= EFI_SUCCESS
;
2525 Status
= FileBufferEnd ();
2532 FileBuffer
.ModeInsert
= (BOOLEAN
) !FileBuffer
.ModeInsert
;
2533 Status
= EFI_SUCCESS
;
2537 Status
= StatusBarSetStatusString (L
"Unknown Command");
2545 Check user specified FileRow is above current screen.
2547 @param[in] FileRow The row of file position ( start from 1 ).
2549 @retval TRUE It is above the current screen.
2550 @retval FALSE It is not above the current screen.
2553 AboveCurrentScreen (
2558 // if is to the above of the screen
2560 if (FileRow
< FileBuffer
.LowVisibleRange
.Row
) {
2568 Check user specified FileRow is under current screen.
2570 @param[in] FileRow The row of file position ( start from 1 ).
2572 @retval TRUE It is under the current screen.
2573 @retval FALSE It is not under the current screen.
2576 UnderCurrentScreen (
2581 // if is to the under of the screen
2583 if (FileRow
> FileBuffer
.LowVisibleRange
.Row
+ (MainEditor
.ScreenSize
.Row
- 2) - 1) {
2591 Check user specified FileCol is left to current screen.
2593 @param[in] FileCol The column of file position ( start from 1 ).
2595 @retval TRUE It is to the left.
2596 @retval FALSE It is not to the left.
2604 // if is to the left of the screen
2606 if (FileCol
< FileBuffer
.LowVisibleRange
.Column
) {
2614 Check user specified FileCol is right to current screen.
2616 @param[in] FileCol The column of file position ( start from 1 ).
2618 @retval TRUE It is to the right.
2619 @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 occurred.
2644 @return The line after advance/retreat.
2651 EFI_EDITOR_LINE
*Line
;
2655 AbsCount
= (UINTN
)ABS (Count
);
2656 Line
= InternalEditorMiscLineRetreat (AbsCount
, MainEditor
.FileBuffer
->CurrentLine
, MainEditor
.FileBuffer
->ListHead
);
2658 Line
= InternalEditorMiscLineAdvance ((UINTN
)Count
, MainEditor
.FileBuffer
->CurrentLine
, MainEditor
.FileBuffer
->ListHead
);
2665 MainEditor
.FileBuffer
->CurrentLine
= Line
;
2671 According to cursor's file position, adjust screen display
2673 @param[in] NewFilePosRow The row of file position ( start from 1 ).
2674 @param[in] NewFilePosCol The column of file position ( start from 1 ).
2677 FileBufferMovePosition (
2678 IN CONST UINTN NewFilePosRow
,
2679 IN CONST UINTN NewFilePosCol
2691 // CALCULATE gap between current file position and new file position
2693 RowGap
= NewFilePosRow
- FileBuffer
.FilePosition
.Row
;
2694 ColGap
= NewFilePosCol
- FileBuffer
.FilePosition
.Column
;
2696 Under
= UnderCurrentScreen (NewFilePosRow
);
2697 Above
= AboveCurrentScreen (NewFilePosRow
);
2699 // if is below current screen
2703 // display row will be unchanged
2705 FileBuffer
.FilePosition
.Row
= NewFilePosRow
;
2709 // has enough above line, so display row unchanged
2710 // not has enough above lines, so the first line is at the
2711 // first display line
2713 if (NewFilePosRow
< (FileBuffer
.DisplayPosition
.Row
- 1)) {
2714 FileBuffer
.DisplayPosition
.Row
= NewFilePosRow
+ 1;
2717 FileBuffer
.FilePosition
.Row
= NewFilePosRow
;
2720 // in current screen
2722 FileBuffer
.FilePosition
.Row
= NewFilePosRow
;
2724 Abs
= (UINTN
)ABS (RowGap
);
2725 FileBuffer
.DisplayPosition
.Row
-= Abs
;
2727 FileBuffer
.DisplayPosition
.Row
+= RowGap
;
2732 FileBuffer
.LowVisibleRange
.Row
= FileBuffer
.FilePosition
.Row
- (FileBuffer
.DisplayPosition
.Row
- 2);
2734 Right
= RightCurrentScreen (NewFilePosCol
);
2735 Left
= LeftCurrentScreen (NewFilePosCol
);
2738 // if right to current screen
2742 // display column will be changed to end
2744 FileBuffer
.DisplayPosition
.Column
= MainEditor
.ScreenSize
.Column
;
2745 FileBuffer
.FilePosition
.Column
= NewFilePosCol
;
2749 // has enough left characters , so display row unchanged
2750 // not has enough left characters,
2751 // so the first character is at the first display column
2753 if (NewFilePosCol
< (FileBuffer
.DisplayPosition
.Column
)) {
2754 FileBuffer
.DisplayPosition
.Column
= NewFilePosCol
;
2757 FileBuffer
.FilePosition
.Column
= NewFilePosCol
;
2760 // in current screen
2762 FileBuffer
.FilePosition
.Column
= NewFilePosCol
;
2764 Abs
= (UINTN
)(-ColGap
);
2765 FileBuffer
.DisplayPosition
.Column
-= Abs
;
2767 FileBuffer
.DisplayPosition
.Column
+= ColGap
;
2772 FileBuffer
.LowVisibleRange
.Column
= FileBuffer
.FilePosition
.Column
- (FileBuffer
.DisplayPosition
.Column
- 1);
2775 // let CurrentLine point to correct line;
2777 FileBuffer
.CurrentLine
= MoveCurrentLine (RowGap
);
2781 Cut current line out and return a pointer to it.
2783 @param[out] CutLine Upon a successful return pointer to the pointer to
2784 the allocated cut line.
2786 @retval EFI_SUCCESS The cut was successful.
2787 @retval EFI_NOT_FOUND There was no selection to cut.
2788 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2792 OUT EFI_EDITOR_LINE
**CutLine
2795 EFI_EDITOR_LINE
*Line
;
2796 EFI_EDITOR_LINE
*NewLine
;
2802 if (FileBuffer
.ReadOnly
) {
2803 StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2807 Line
= FileBuffer
.CurrentLine
;
2810 // if is the last dummy line, SO CAN not cut
2812 if ((StrCmp (Line
->Buffer
, L
"\0") == 0) && (Line
->Link
.ForwardLink
== FileBuffer
.ListHead
)
2819 // LAST LINE AND NOTHING ON THIS LINE, SO CUT NOTHING
2821 StatusBarSetStatusString (L
"Nothing to Cut");
2822 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.
2874 FileBufferPasteLine (
2878 EFI_EDITOR_LINE
*Line
;
2879 EFI_EDITOR_LINE
*NewLine
;
2884 // if nothing is on clip board
2887 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
;
2905 // insert it above current line
2907 Line
= FileBuffer
.CurrentLine
;
2908 NewLine
->Link
.BackLink
= Line
->Link
.BackLink
;
2909 NewLine
->Link
.ForwardLink
= &Line
->Link
;
2911 Line
->Link
.BackLink
->ForwardLink
= &NewLine
->Link
;
2912 Line
->Link
.BackLink
= &NewLine
->Link
;
2914 FileBuffer
.NumLines
++;
2915 FileBuffer
.CurrentLine
= NewLine
;
2917 FileBuffer
.Lines
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2923 Row
= FileBuffer
.FilePosition
.Row
;
2925 FileBufferMovePosition (Row
, Col
);
2928 // after paste, set some value so that refresh knows to do something
2930 FileBuffer
.FileModified
= TRUE
;
2931 FileBufferNeedRefresh
= TRUE
;
2932 FileBufferOnlyLineNeedRefresh
= FALSE
;
2938 Search string from current position on in file
2940 @param[in] Str The search string.
2941 @param[in] Offset The offset from current position.
2943 @retval EFI_SUCCESS The operation was successful.
2944 @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.
3053 IN CONST CHAR16
*Replace
,
3054 IN CONST UINTN SearchLen
3064 ReplaceLen
= StrLen (Replace
);
3066 OldSize
= FileBuffer
.CurrentLine
->Size
+ 1;
3068 // include CHAR_NULL
3070 NewSize
= OldSize
+ (ReplaceLen
- SearchLen
);
3072 if (ReplaceLen
> SearchLen
) {
3074 // do not have the enough space
3076 if (FileBuffer
.CurrentLine
->TotalSize
+ 1 <= NewSize
) {
3077 FileBuffer
.CurrentLine
->Buffer
= ReallocatePool (
3080 FileBuffer
.CurrentLine
->Buffer
3082 FileBuffer
.CurrentLine
->TotalSize
= NewSize
- 1;
3085 if (FileBuffer
.CurrentLine
->Buffer
== NULL
) {
3086 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
);
3104 // set replace into it
3106 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1;
3107 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3108 Buffer
[Index
] = Replace
[Index
];
3112 if (ReplaceLen
< SearchLen
) {
3113 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1;
3115 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3116 Buffer
[Index
] = Replace
[Index
];
3119 Buffer
+= ReplaceLen
;
3120 Gap
= SearchLen
- ReplaceLen
;
3123 // set replace into it
3125 for (Index
= 0; Index
< (FileBuffer
.CurrentLine
->Size
- FileBuffer
.FilePosition
.Column
- ReplaceLen
+ 2); Index
++) {
3126 *Buffer
= *(Buffer
+ Gap
);
3131 if (ReplaceLen
== SearchLen
) {
3132 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1;
3133 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3134 Buffer
[Index
] = Replace
[Index
];
3138 FileBuffer
.CurrentLine
->Size
+= (ReplaceLen
- SearchLen
);
3140 FileBufferOnlyLineNeedRefresh
= TRUE
;
3142 FileBuffer
.FileModified
= TRUE
;
3144 MainTitleBarRefresh (MainEditor
.FileBuffer
->FileName
, MainEditor
.FileBuffer
->FileType
, MainEditor
.FileBuffer
->ReadOnly
, MainEditor
.FileBuffer
->FileModified
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
, 0, 0);
3145 FileBufferRestorePosition ();
3146 FileBufferRefresh ();
3152 Move the mouse cursor position.
3154 @param[in] TextX The new x-coordinate.
3155 @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
;
3203 // check whether new mouse column position is beyond screen
3204 // if not, adjust it
3206 if ((CoordinateX
>= 1) && (CoordinateX
<= MainEditor
.ScreenSize
.Column
)) {
3207 FileBuffer
.MousePosition
.Column
= CoordinateX
;
3208 } else if (CoordinateX
< 1) {
3209 FileBuffer
.MousePosition
.Column
= 1;
3210 } else if (CoordinateX
> MainEditor
.ScreenSize
.Column
) {
3211 FileBuffer
.MousePosition
.Column
= MainEditor
.ScreenSize
.Column
;
3215 // check whether new mouse row position is beyond screen
3216 // if not, adjust it
3218 if ((CoordinateY
>= 2) && (CoordinateY
<= (MainEditor
.ScreenSize
.Row
- 1))) {
3219 FileBuffer
.MousePosition
.Row
= CoordinateY
;
3220 } else if (CoordinateY
< 2) {
3221 FileBuffer
.MousePosition
.Row
= 2;
3222 } else if (CoordinateY
> (MainEditor
.ScreenSize
.Row
- 1)) {
3223 FileBuffer
.MousePosition
.Row
= (MainEditor
.ScreenSize
.Row
- 1);
3228 Search and replace operation.
3230 @param[in] SearchStr The string to search for.
3231 @param[in] ReplaceStr The string to replace with.
3232 @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
;
3297 // the end CHAR_NULL character;
3299 Buffer
= Line
->Buffer
+ (NewSize
- 1);
3300 Gap
= ReplaceLen
- SearchLen
;
3303 // keep the latter part
3305 for (Index
= 0; Index
< (Line
->Size
- Position
- SearchLen
+ 1); Index
++) {
3306 *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
);
3322 // set replace into it
3324 Buffer
= Line
->Buffer
+ Position
;
3325 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3326 Buffer
[Index
] = ReplaceStr
[Index
];
3329 Line
->Size
+= (ReplaceLen
- SearchLen
);
3330 Column
+= ReplaceLen
;
3336 Link
= Link
->ForwardLink
;
3341 // call refresh to fresh edit area
3343 FileBuffer
.FileModified
= TRUE
;
3344 FileBufferNeedRefresh
= TRUE
;
3345 FileBufferRefresh ();
3351 Set the modified state to TRUE.
3354 FileBufferSetModified (
3358 FileBuffer
.FileModified
= TRUE
;