2 Implements filebuffer interface functions.
4 Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved. <BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "TextEditor.h"
16 #include <Guid/FileSystemInfo.h>
17 #include <Library/FileHandleLib.h>
19 EFI_EDITOR_FILE_BUFFER FileBuffer
;
20 EFI_EDITOR_FILE_BUFFER FileBufferBackupVar
;
23 // for basic initialization of FileBuffer
25 EFI_EDITOR_FILE_BUFFER FileBufferConst
= {
54 // the whole edit area needs to be refreshed
56 BOOLEAN FileBufferNeedRefresh
;
59 // only the current line in edit area needs to be refresh
61 BOOLEAN FileBufferOnlyLineNeedRefresh
;
63 BOOLEAN FileBufferMouseNeedRefresh
;
65 extern BOOLEAN EditorMouseAction
;
68 Initialization function for FileBuffer.
70 @param EFI_SUCCESS The initialization was successful.
71 @param EFI_LOAD_ERROR A default name could not be created.
72 @param EFI_OUT_OF_RESOURCES A memory allocation failed.
80 // basically initialize the FileBuffer
82 CopyMem (&FileBuffer
, &FileBufferConst
, sizeof (EFI_EDITOR_FILE_BUFFER
));
83 CopyMem (&FileBufferBackupVar
, &FileBufferConst
, sizeof (EFI_EDITOR_FILE_BUFFER
));
86 // set default FileName
88 FileBuffer
.FileName
= EditGetDefaultFileName (L
"txt");
89 if (FileBuffer
.FileName
== NULL
) {
90 return EFI_LOAD_ERROR
;
93 FileBuffer
.ListHead
= AllocateZeroPool (sizeof (LIST_ENTRY
));
94 if (FileBuffer
.ListHead
== NULL
) {
95 return EFI_OUT_OF_RESOURCES
;
98 InitializeListHead (FileBuffer
.ListHead
);
100 FileBuffer
.DisplayPosition
.Row
= 2;
101 FileBuffer
.DisplayPosition
.Column
= 1;
102 FileBuffer
.LowVisibleRange
.Row
= 2;
103 FileBuffer
.LowVisibleRange
.Column
= 1;
105 FileBufferNeedRefresh
= FALSE
;
106 FileBufferMouseNeedRefresh
= FALSE
;
107 FileBufferOnlyLineNeedRefresh
= FALSE
;
113 Backup function for FileBuffer. Only backup the following items:
114 Mouse/Cursor position
115 File Name, Type, ReadOnly, Modified
118 This is for making the file buffer refresh as few as possible.
120 @retval EFI_SUCCESS The backup operation was successful.
127 FileBufferBackupVar
.MousePosition
= FileBuffer
.MousePosition
;
129 SHELL_FREE_NON_NULL (FileBufferBackupVar
.FileName
);
130 FileBufferBackupVar
.FileName
= NULL
;
131 FileBufferBackupVar
.FileName
= StrnCatGrow (&FileBufferBackupVar
.FileName
, NULL
, FileBuffer
.FileName
, 0);
133 FileBufferBackupVar
.ModeInsert
= FileBuffer
.ModeInsert
;
134 FileBufferBackupVar
.FileType
= FileBuffer
.FileType
;
136 FileBufferBackupVar
.FilePosition
= FileBuffer
.FilePosition
;
137 FileBufferBackupVar
.LowVisibleRange
= FileBuffer
.LowVisibleRange
;
139 FileBufferBackupVar
.FileModified
= FileBuffer
.FileModified
;
140 FileBufferBackupVar
.ReadOnly
= FileBuffer
.ReadOnly
;
146 Advance to the next Count lines
148 @param[in] Count The line number to advance by.
149 @param[in] CurrentLine The pointer to the current line structure.
150 @param[in] LineList The pointer to the linked list of lines.
152 @retval NULL There was an error.
153 @return The line structure after the advance.
156 InternalEditorMiscLineAdvance (
157 IN CONST UINTN Count
,
158 IN CONST EFI_EDITOR_LINE
*CurrentLine
,
159 IN CONST LIST_ENTRY
*LineList
164 CONST EFI_EDITOR_LINE
*Line
;
166 if (CurrentLine
== NULL
|| LineList
== NULL
) {
170 for (Line
= CurrentLine
, Index
= 0; Index
< Count
; Index
++) {
172 // if already last line
174 if (Line
->Link
.ForwardLink
== LineList
) {
178 Line
= CR (Line
->Link
.ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
181 return ((EFI_EDITOR_LINE
*)Line
);
185 Retreat to the previous Count lines.
187 @param[in] Count The line number to retreat by.
188 @param[in] CurrentLine The pointer to the current line structure.
189 @param[in] LineList The pointer to the linked list of lines.
191 @retval NULL There was an error.
192 @return The line structure after the retreat.
195 InternalEditorMiscLineRetreat (
196 IN CONST UINTN Count
,
197 IN CONST EFI_EDITOR_LINE
*CurrentLine
,
198 IN CONST LIST_ENTRY
*LineList
203 CONST EFI_EDITOR_LINE
*Line
;
205 if (CurrentLine
== NULL
|| LineList
== NULL
) {
209 for (Line
= CurrentLine
, Index
= 0; Index
< Count
; Index
++) {
211 // already the first line
213 if (Line
->Link
.BackLink
== LineList
) {
217 Line
= CR (Line
->Link
.BackLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
220 return ((EFI_EDITOR_LINE
*)Line
);
224 Advance/Retreat lines
226 @param[in] Count line number to advance/retreat
230 @retval NULL An error occured.
231 @return The line after advance/retreat.
238 EFI_EDITOR_LINE
*Line
;
242 // if < 0, then retreat
243 // if > 0, the advance
246 AbsCount
= (UINTN
)ABS(Count
);
247 Line
= InternalEditorMiscLineRetreat (AbsCount
,MainEditor
.FileBuffer
->CurrentLine
,MainEditor
.FileBuffer
->ListHead
);
249 Line
= InternalEditorMiscLineAdvance ((UINTN
)Count
,MainEditor
.FileBuffer
->CurrentLine
,MainEditor
.FileBuffer
->ListHead
);
256 Function to update the 'screen' to display the mouse position.
258 @retval EFI_SUCCESS The backup operation was successful.
261 FileBufferRestoreMousePosition (
265 EFI_EDITOR_COLOR_UNION Orig
;
266 EFI_EDITOR_COLOR_UNION New
;
269 BOOLEAN HasCharacter
;
270 EFI_EDITOR_LINE
*CurrentLine
;
271 EFI_EDITOR_LINE
*Line
;
275 // variable initialization
279 if (MainEditor
.MouseSupported
) {
281 if (FileBufferMouseNeedRefresh
) {
283 FileBufferMouseNeedRefresh
= FALSE
;
286 // if mouse position not moved and only mouse action
287 // so do not need to refresh mouse position
289 if ((FileBuffer
.MousePosition
.Row
== FileBufferBackupVar
.MousePosition
.Row
&&
290 FileBuffer
.MousePosition
.Column
== FileBufferBackupVar
.MousePosition
.Column
)
291 && EditorMouseAction
) {
295 // backup the old screen attributes
297 Orig
= MainEditor
.ColorAttributes
;
299 New
.Colors
.Foreground
= Orig
.Colors
.Background
& 0xF;
300 New
.Colors
.Background
= Orig
.Colors
.Foreground
& 0x7;
303 // clear the old mouse position
305 FRow
= FileBuffer
.LowVisibleRange
.Row
+ FileBufferBackupVar
.MousePosition
.Row
- 2;
307 FColumn
= FileBuffer
.LowVisibleRange
.Column
+ FileBufferBackupVar
.MousePosition
.Column
- 1;
310 if (FRow
> FileBuffer
.NumLines
) {
311 HasCharacter
= FALSE
;
313 CurrentLine
= FileBuffer
.CurrentLine
;
314 Line
= MoveLine (FRow
- FileBuffer
.FilePosition
.Row
);
316 if (Line
== NULL
|| FColumn
> Line
->Size
) {
317 HasCharacter
= FALSE
;
320 FileBuffer
.CurrentLine
= CurrentLine
;
324 (INT32
)FileBufferBackupVar
.MousePosition
.Column
- 1,
325 (INT32
)FileBufferBackupVar
.MousePosition
.Row
- 1,
330 Value
= (Line
->Buffer
[FColumn
- 1]);
332 (INT32
)FileBufferBackupVar
.MousePosition
.Column
- 1,
333 (INT32
)FileBufferBackupVar
.MousePosition
.Row
- 1,
339 // set the new mouse position
341 gST
->ConOut
->SetAttribute (gST
->ConOut
, New
.Data
& 0x7F);
344 // clear the old mouse position
346 FRow
= FileBuffer
.LowVisibleRange
.Row
+ FileBuffer
.MousePosition
.Row
- 2;
347 FColumn
= FileBuffer
.LowVisibleRange
.Column
+ FileBuffer
.MousePosition
.Column
- 1;
350 if (FRow
> FileBuffer
.NumLines
) {
351 HasCharacter
= FALSE
;
353 CurrentLine
= FileBuffer
.CurrentLine
;
354 Line
= MoveLine (FRow
- FileBuffer
.FilePosition
.Row
);
356 if (Line
== NULL
|| FColumn
> Line
->Size
) {
357 HasCharacter
= FALSE
;
360 FileBuffer
.CurrentLine
= CurrentLine
;
364 (INT32
)FileBuffer
.MousePosition
.Column
- 1,
365 (INT32
)FileBuffer
.MousePosition
.Row
- 1,
370 Value
= Line
->Buffer
[FColumn
- 1];
372 (INT32
)FileBuffer
.MousePosition
.Column
- 1,
373 (INT32
)FileBuffer
.MousePosition
.Row
- 1,
379 // end of HasCharacter
381 gST
->ConOut
->SetAttribute (gST
->ConOut
, Orig
.Data
);
384 // end of MouseNeedRefresh
388 // end of MouseSupported
394 Free all the lines in FileBuffer
401 @retval EFI_SUCCESS The operation was successful.
404 FileBufferFreeLines (
409 EFI_EDITOR_LINE
*Line
;
412 // free all the lines
414 if (FileBuffer
.Lines
!= NULL
) {
416 Line
= FileBuffer
.Lines
;
417 Link
= &(Line
->Link
);
419 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
420 Link
= Link
->ForwardLink
;
423 // free line's buffer and line itself
426 } while (Link
!= FileBuffer
.ListHead
);
429 // clean the line list related structure
431 FileBuffer
.Lines
= NULL
;
432 FileBuffer
.CurrentLine
= NULL
;
433 FileBuffer
.NumLines
= 0;
435 FileBuffer
.ListHead
->ForwardLink
= FileBuffer
.ListHead
;
436 FileBuffer
.ListHead
->BackLink
= FileBuffer
.ListHead
;
442 Cleanup function for FileBuffer.
444 @retval EFI_SUCCESS The cleanup was successful.
453 SHELL_FREE_NON_NULL (FileBuffer
.FileName
);
456 // free all the lines
458 Status
= FileBufferFreeLines ();
460 SHELL_FREE_NON_NULL (FileBuffer
.ListHead
);
461 FileBuffer
.ListHead
= NULL
;
463 SHELL_FREE_NON_NULL (FileBufferBackupVar
.FileName
);
469 Print a line specified by Line on a row specified by Row of the screen.
471 @param[in] Line The line to print.
472 @param[in] Row The row on the screen to print onto (begin from 1).
474 @retval EFI_SUCCESS The printing was successful.
477 FileBufferPrintLine (
478 IN CONST EFI_EDITOR_LINE
*Line
,
490 // print start from correct character
492 Buffer
= Line
->Buffer
+ FileBuffer
.LowVisibleRange
.Column
- 1;
494 Limit
= Line
->Size
- FileBuffer
.LowVisibleRange
.Column
+ 1;
495 if (Limit
> Line
->Size
) {
499 BufLen
= (MainEditor
.ScreenSize
.Column
+ 1) * sizeof (CHAR16
);
500 PrintLine
= AllocatePool (BufLen
);
501 if (PrintLine
!= NULL
) {
502 StrnCpyS (PrintLine
, BufLen
/sizeof(CHAR16
), Buffer
, MIN(Limit
, MainEditor
.ScreenSize
.Column
));
503 for (; Limit
< MainEditor
.ScreenSize
.Column
; Limit
++) {
504 PrintLine
[Limit
] = L
' ';
507 PrintLine
[MainEditor
.ScreenSize
.Column
] = CHAR_NULL
;
509 PrintLine2
= AllocatePool (BufLen
* 2);
510 if (PrintLine2
!= NULL
) {
511 ShellCopySearchAndReplace(PrintLine
, PrintLine2
, BufLen
* 2, L
"%", L
"^%", FALSE
, FALSE
);
519 FreePool (PrintLine2
);
521 FreePool (PrintLine
);
528 Set the cursor position according to FileBuffer.DisplayPosition.
530 @retval EFI_SUCCESS The operation was successful.
533 FileBufferRestorePosition (
538 // set cursor position
540 return (gST
->ConOut
->SetCursorPosition (
542 FileBuffer
.DisplayPosition
.Column
- 1,
543 FileBuffer
.DisplayPosition
.Row
- 1
548 Refresh the screen with whats in the buffer.
550 @retval EFI_SUCCESS The refresh was successful.
551 @retval EFI_LOAD_ERROR There was an error finding what to write.
559 EFI_EDITOR_LINE
*Line
;
563 // if it's the first time after editor launch, so should refresh
567 // no definite required refresh
568 // and file position displayed on screen has not been changed
570 if (!FileBufferNeedRefresh
&&
571 !FileBufferOnlyLineNeedRefresh
&&
572 FileBufferBackupVar
.LowVisibleRange
.Row
== FileBuffer
.LowVisibleRange
.Row
&&
573 FileBufferBackupVar
.LowVisibleRange
.Column
== FileBuffer
.LowVisibleRange
.Column
576 FileBufferRestoreMousePosition ();
577 FileBufferRestorePosition ();
583 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
586 // only need to refresh current line
588 if (FileBufferOnlyLineNeedRefresh
&&
589 FileBufferBackupVar
.LowVisibleRange
.Row
== FileBuffer
.LowVisibleRange
.Row
&&
590 FileBufferBackupVar
.LowVisibleRange
.Column
== FileBuffer
.LowVisibleRange
.Column
593 EditorClearLine (FileBuffer
.DisplayPosition
.Row
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
);
594 FileBufferPrintLine (
595 FileBuffer
.CurrentLine
,
596 FileBuffer
.DisplayPosition
.Row
600 // the whole edit area need refresh
606 if (FileBuffer
.Lines
== NULL
) {
607 FileBufferRestoreMousePosition ();
608 FileBufferRestorePosition ();
609 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
614 // get the first line that will be displayed
616 Line
= MoveLine (FileBuffer
.LowVisibleRange
.Row
- FileBuffer
.FilePosition
.Row
);
618 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
620 return EFI_LOAD_ERROR
;
623 Link
= &(Line
->Link
);
626 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
631 FileBufferPrintLine (Line
, Row
);
633 Link
= Link
->ForwardLink
;
635 } while (Link
!= FileBuffer
.ListHead
&& Row
<= (MainEditor
.ScreenSize
.Row
- 1));
637 // while not file end and not screen full
639 while (Row
<= (MainEditor
.ScreenSize
.Row
- 1)) {
640 EditorClearLine (Row
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
);
645 FileBufferRestoreMousePosition ();
646 FileBufferRestorePosition ();
648 FileBufferNeedRefresh
= FALSE
;
649 FileBufferOnlyLineNeedRefresh
= FALSE
;
651 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
656 Create a new line and append it to the line list.
661 @retval NULL The create line failed.
662 @return The line created.
665 FileBufferCreateLine (
669 EFI_EDITOR_LINE
*Line
;
672 // allocate a line structure
674 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
);
730 // free the old file name
732 SHELL_FREE_NON_NULL (FileBuffer
.FileName
);
735 // Allocate and set the new name
737 FileBuffer
.FileName
= CatSPrint (NULL
, L
"%s", Str
);
738 if (FileBuffer
.FileName
== NULL
) {
739 return EFI_OUT_OF_RESOURCES
;
745 Free the existing file lines and reset the modified flag.
747 @retval EFI_SUCCESS The operation was successful.
755 // free all the lines
757 FileBufferFreeLines ();
758 FileBuffer
.FileModified
= FALSE
;
765 Read a file from disk into the FileBuffer.
767 @param[in] FileName The filename to read.
768 @param[in] Recover TRUE if is for recover mode, no information printouts.
770 @retval EFI_SUCCESS The load was successful.
771 @retval EFI_LOAD_ERROR The load failed.
772 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
773 @retval EFI_INVALID_PARAMETER FileName is a directory.
777 IN CONST CHAR16
*FileName
,
778 IN CONST BOOLEAN Recover
781 EFI_EDITOR_LINE
*Line
;
782 EE_NEWLINE_TYPE Type
;
787 CHAR16
*UnicodeBuffer
;
790 SHELL_FILE_HANDLE FileHandle
;
793 UINTN LineSizeBackup
;
799 UnicodeBuffer
= NULL
;
800 Type
= NewLineTypeDefault
;
805 // in this function, when you return error ( except EFI_OUT_OF_RESOURCES )
806 // you should set status string via StatusBarSetStatusString(L"blah")
807 // since this function maybe called before the editorhandleinput loop
808 // so any error will cause editor return
809 // so if you want to print the error status
810 // you should set the status string
814 // try to open the file
816 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
, 0);
818 if (!EFI_ERROR(Status
)) {
820 if (FileHandle
== NULL
) {
821 StatusBarSetStatusString (L
"Disk Error");
822 return EFI_LOAD_ERROR
;
825 Info
= ShellGetFileInfo(FileHandle
);
827 if (Info
->Attribute
& EFI_FILE_DIRECTORY
) {
828 StatusBarSetStatusString (L
"Directory Can Not Be Edited");
830 return EFI_INVALID_PARAMETER
;
833 if (Info
->Attribute
& EFI_FILE_READ_ONLY
) {
834 FileBuffer
.ReadOnly
= TRUE
;
836 FileBuffer
.ReadOnly
= FALSE
;
841 FileSize
= (UINTN
) Info
->FileSize
;
844 } else if (Status
== EFI_NOT_FOUND
) {
846 // file not exists. add create and try again
848 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
|EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_CREATE
, 0);
849 if (EFI_ERROR (Status
)) {
850 if (Status
== EFI_WRITE_PROTECTED
||
851 Status
== EFI_ACCESS_DENIED
||
852 Status
== EFI_NO_MEDIA
||
853 Status
== EFI_MEDIA_CHANGED
855 StatusBarSetStatusString (L
"Access Denied");
856 } else if (Status
== EFI_DEVICE_ERROR
|| Status
== EFI_VOLUME_CORRUPTED
|| Status
== EFI_VOLUME_FULL
) {
857 StatusBarSetStatusString (L
"Disk Error");
859 StatusBarSetStatusString (L
"Invalid File Name or Current-working-directory");
865 // it worked. now delete it and move on with the name (now validated)
867 Status
= ShellDeleteFile (&FileHandle
);
868 if (Status
== EFI_WARN_DELETE_FAILURE
) {
869 Status
= EFI_ACCESS_DENIED
;
872 if (EFI_ERROR (Status
)) {
873 StatusBarSetStatusString (L
"Access Denied");
878 // file doesn't exist, so set CreateFile to TRUE
881 FileBuffer
.ReadOnly
= FALSE
;
884 // all the check ends
885 // so now begin to set file name, free lines
887 if (StrCmp (FileName
, FileBuffer
.FileName
) != 0) {
888 FileBufferSetFileName (FileName
);
891 // free the old lines
901 // allocate buffer to read file
903 Buffer
= AllocateZeroPool (FileSize
);
904 if (Buffer
== NULL
) {
905 return EFI_OUT_OF_RESOURCES
;
908 // read file into Buffer
910 Status
= ShellReadFile (FileHandle
, &FileSize
, Buffer
);
911 ShellCloseFile(&FileHandle
);
913 if (EFI_ERROR (Status
)) {
914 StatusBarSetStatusString (L
"Read File Failed");
915 SHELL_FREE_NON_NULL (Buffer
);
916 return EFI_LOAD_ERROR
;
919 // nothing in this file
922 SHELL_FREE_NON_NULL (Buffer
);
924 // since has no head, so only can be an ASCII file
926 FileBuffer
.FileType
= FileTypeAscii
;
931 AsciiBuffer
= Buffer
;
935 // size < Unicode file header, so only can be ASCII file
937 FileBuffer
.FileType
= FileTypeAscii
;
942 if (*(UINT16
*) Buffer
== EFI_UNICODE_BYTE_ORDER_MARK
) {
944 // Unicode file's size should be even
946 if ((FileSize
% 2) != 0) {
947 StatusBarSetStatusString (L
"File Format Wrong");
948 SHELL_FREE_NON_NULL (Buffer
);
949 return EFI_LOAD_ERROR
;
954 FileBuffer
.FileType
= FileTypeUnicode
;
955 UnicodeBuffer
= Buffer
;
958 // pass this 0xff and 0xfe
963 FileBuffer
.FileType
= FileTypeAscii
;
966 // end of AsciiBuffer ==
970 // end of FileSize < 2
971 // all the check ends
972 // so now begin to set file name, free lines
974 if (StrCmp (FileName
, FileBuffer
.FileName
) != 0) {
975 FileBufferSetFileName (FileName
);
979 // free the old lines
984 // parse file content line by line
986 for (LoopVar1
= 0; LoopVar1
< FileSize
; LoopVar1
++) {
987 Type
= NewLineTypeUnknown
;
989 for (LineSize
= LoopVar1
; LineSize
< FileSize
; LineSize
++) {
990 if (FileBuffer
.FileType
== FileTypeAscii
) {
991 if (AsciiBuffer
[LineSize
] == CHAR_CARRIAGE_RETURN
) {
992 Type
= NewLineTypeCarriageReturn
;
997 if (LineSize
< FileSize
- 1) {
998 if (AsciiBuffer
[LineSize
+ 1] == CHAR_LINEFEED
) {
999 Type
= NewLineTypeCarriageReturnLineFeed
;
1004 } else if (AsciiBuffer
[LineSize
] == CHAR_LINEFEED
) {
1005 Type
= NewLineTypeLineFeed
;
1010 if (LineSize
< FileSize
- 1) {
1011 if (AsciiBuffer
[LineSize
+ 1] == CHAR_CARRIAGE_RETURN
) {
1012 Type
= NewLineTypeLineFeedCarriageReturn
;
1019 if (UnicodeBuffer
[LineSize
] == CHAR_CARRIAGE_RETURN
) {
1020 Type
= NewLineTypeCarriageReturn
;
1025 if (LineSize
< FileSize
- 1) {
1026 if (UnicodeBuffer
[LineSize
+ 1] == CHAR_LINEFEED
) {
1027 Type
= NewLineTypeCarriageReturnLineFeed
;
1032 } else if (UnicodeBuffer
[LineSize
] == CHAR_LINEFEED
) {
1033 Type
= NewLineTypeLineFeed
;
1038 if (LineSize
< FileSize
- 1) {
1039 if (UnicodeBuffer
[LineSize
+ 1] == CHAR_CARRIAGE_RETURN
) {
1040 Type
= NewLineTypeLineFeedCarriageReturn
;
1052 // end of for LineSize
1054 // if the type is wrong, then exit
1056 if (Type
== NewLineTypeUnknown
) {
1058 // Now if Type is NewLineTypeUnknown, it should be file end
1060 Type
= NewLineTypeDefault
;
1063 LineSizeBackup
= LineSize
;
1066 // create a new line
1068 Line
= FileBufferCreateLine ();
1070 SHELL_FREE_NON_NULL (Buffer
);
1071 return EFI_OUT_OF_RESOURCES
;
1074 // calculate file length
1076 LineSize
-= LoopVar1
;
1079 // Unicode and one CHAR_NULL
1081 SHELL_FREE_NON_NULL (Line
->Buffer
);
1082 Line
->Buffer
= AllocateZeroPool (LineSize
* 2 + 2);
1084 if (Line
->Buffer
== NULL
) {
1085 RemoveEntryList (&Line
->Link
);
1086 return EFI_OUT_OF_RESOURCES
;
1089 // copy this line to Line->Buffer
1091 for (LoopVar2
= 0; LoopVar2
< LineSize
; LoopVar2
++) {
1092 if (FileBuffer
.FileType
== FileTypeAscii
) {
1093 Line
->Buffer
[LoopVar2
] = (CHAR16
) AsciiBuffer
[LoopVar1
];
1095 Line
->Buffer
[LoopVar2
] = UnicodeBuffer
[LoopVar1
];
1101 // LoopVar1 now points to where CHAR_CARRIAGE_RETURN or CHAR_LINEFEED;
1103 Line
->Buffer
[LineSize
] = 0;
1105 Line
->Size
= LineSize
;
1106 Line
->TotalSize
= LineSize
;
1109 if (Type
== NewLineTypeCarriageReturnLineFeed
|| Type
== NewLineTypeLineFeedCarriageReturn
) {
1114 // last character is a return, SO create a new line
1116 if (((Type
== NewLineTypeCarriageReturnLineFeed
|| Type
== NewLineTypeLineFeedCarriageReturn
) && LineSizeBackup
== FileSize
- 2) ||
1117 ((Type
== NewLineTypeLineFeed
|| Type
== NewLineTypeCarriageReturn
) && LineSizeBackup
== FileSize
- 1)
1119 Line
= FileBufferCreateLine ();
1121 SHELL_FREE_NON_NULL (Buffer
);
1122 return EFI_OUT_OF_RESOURCES
;
1132 SHELL_FREE_NON_NULL (Buffer
);
1136 // end of if CreateFile
1140 FileBuffer
.DisplayPosition
.Row
= 2;
1141 FileBuffer
.DisplayPosition
.Column
= 1;
1142 FileBuffer
.LowVisibleRange
.Row
= 1;
1143 FileBuffer
.LowVisibleRange
.Column
= 1;
1144 FileBuffer
.FilePosition
.Row
= 1;
1145 FileBuffer
.FilePosition
.Column
= 1;
1146 FileBuffer
.MousePosition
.Row
= 2;
1147 FileBuffer
.MousePosition
.Column
= 1;
1150 UnicodeBuffer
= CatSPrint (NULL
, L
"%d Lines Read", FileBuffer
.NumLines
);
1151 if (UnicodeBuffer
== NULL
) {
1152 return EFI_OUT_OF_RESOURCES
;
1155 StatusBarSetStatusString (UnicodeBuffer
);
1156 FreePool (UnicodeBuffer
);
1160 // check whether we have fs?: in filename
1163 FSMappingPtr = NULL;
1164 while (FileName[LoopVar1] != 0) {
1165 if (FileName[LoopVar1] == L':') {
1166 FSMappingPtr = &FileName[LoopVar1];
1173 if (FSMappingPtr == NULL) {
1174 CurDir = ShellGetCurrentDir (NULL);
1178 while (FileName[LoopVar1] != 0) {
1179 if (FileName[LoopVar1] == L':') {
1183 FSMapping[LoopVar2++] = FileName[LoopVar1];
1188 FSMapping[LoopVar2] = 0;
1189 CurDir = ShellGetCurrentDir (FSMapping);
1192 if (CurDir != NULL) {
1193 for (LoopVar1 = 0; LoopVar1 < StrLen (CurDir) && CurDir[LoopVar1] != ':'; LoopVar1++);
1195 CurDir[LoopVar1] = 0;
1196 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) ShellGetMap (CurDir);
1199 return EFI_LOAD_ERROR;
1202 Status = LibDevicePathToInterface (
1203 &gEfiSimpleFileSystemProtocolGuid,
1207 if (EFI_ERROR (Status)) {
1208 return EFI_LOAD_ERROR;
1211 Status = Vol->OpenVolume (Vol, &RootFs);
1212 if (EFI_ERROR (Status)) {
1213 return EFI_LOAD_ERROR;
1216 // Get volume information of file system
1218 Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + 100;
1219 VolumeInfo = (EFI_FILE_SYSTEM_INFO *) AllocateZeroPool (Size);
1220 Status = RootFs->GetInfo (RootFs, &gEfiFileSystemInfoGuid, &Size, VolumeInfo);
1221 if (EFI_ERROR (Status)) {
1222 RootFs->Close (RootFs);
1223 return EFI_LOAD_ERROR;
1226 if (VolumeInfo->ReadOnly) {
1227 StatusBarSetStatusString (L"WARNING: Volume Read Only");
1230 FreePool (VolumeInfo);
1231 RootFs->Close (RootFs);
1238 if (FileBuffer
.Lines
!= 0) {
1239 FileBuffer
.CurrentLine
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1242 // create a dummy line
1244 Line
= FileBufferCreateLine ();
1246 return EFI_OUT_OF_RESOURCES
;
1249 FileBuffer
.CurrentLine
= Line
;
1252 FileBuffer
.FileModified
= FALSE
;
1253 FileBufferNeedRefresh
= TRUE
;
1254 FileBufferOnlyLineNeedRefresh
= FALSE
;
1255 FileBufferMouseNeedRefresh
= TRUE
;
1262 According to FileBuffer.NewLineType & FileBuffer.FileType,
1263 get the return buffer and size.
1265 @param[in] Type The type of line.
1266 @param[out] Buffer The buffer to fill.
1267 @param[out] Size The amount of the buffer used on return.
1271 IN CONST EE_NEWLINE_TYPE Type
,
1279 // give new line buffer,
1280 // and will judge unicode or ascii
1285 // not legal new line type
1287 if (Type
!= NewLineTypeLineFeed
&& Type
!= NewLineTypeCarriageReturn
&& Type
!= NewLineTypeCarriageReturnLineFeed
&& Type
!= NewLineTypeLineFeedCarriageReturn
) {
1292 // use_cr: give 0x0d
1294 if (Type
== NewLineTypeCarriageReturn
) {
1295 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1304 *Size
= NewLineSize
;
1308 // use_lf: give 0x0a
1310 if (Type
== NewLineTypeLineFeed
) {
1311 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1320 *Size
= NewLineSize
;
1324 // use_crlf: give 0x0d 0x0a
1326 if (Type
== NewLineTypeCarriageReturnLineFeed
) {
1327 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1340 *Size
= NewLineSize
;
1344 // use_lfcr: give 0x0a 0x0d
1346 if (Type
== NewLineTypeLineFeedCarriageReturn
) {
1347 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1360 *Size
= NewLineSize
;
1367 Change a Unicode string to an ASCII string.
1369 @param[in] UStr The Unicode string.
1370 @param[in] Length The maximum size of AStr.
1371 @param[out] AStr ASCII string to pass out.
1373 @return The actuall length.
1377 IN CONST CHAR16
*UStr
,
1378 IN CONST UINTN Length
,
1385 // just buffer copy, not character copy
1387 for (Index
= 0; Index
< Length
; Index
++) {
1388 *AStr
++ = (CHAR8
) *UStr
++;
1395 Save lines in FileBuffer to disk
1397 @param[in] FileName The file name for writing.
1399 @retval EFI_SUCCESS Data was written.
1400 @retval EFI_LOAD_ERROR
1401 @retval EFI_OUT_OF_RESOURCES There were not enough resources to write the file.
1405 IN CONST CHAR16
*FileName
1408 SHELL_FILE_HANDLE FileHandle
;
1410 EFI_EDITOR_LINE
*Line
;
1416 CHAR8 NewLineBuffer
[4];
1419 EFI_FILE_INFO
*Info
;
1423 EE_NEWLINE_TYPE Type
;
1438 TotalSize
= 0x200000;
1445 // if is the old file
1447 if (FileBuffer
.FileName
!= NULL
&& StrCmp (FileName
, FileBuffer
.FileName
) == 0) {
1449 // file has not been modified
1451 if (!FileBuffer
.FileModified
) {
1456 // if file is read-only, set error
1458 if (FileBuffer
.ReadOnly
) {
1459 StatusBarSetStatusString (L
"Read Only File Can Not Be Saved");
1464 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
|EFI_FILE_MODE_WRITE
, 0);
1466 if (!EFI_ERROR (Status
)) {
1467 Info
= ShellGetFileInfo(FileHandle
);
1469 if (Info
!= NULL
&& Info
->Attribute
& EFI_FILE_DIRECTORY
) {
1470 StatusBarSetStatusString (L
"Directory Can Not Be Saved");
1471 ShellCloseFile(FileHandle
);
1473 return EFI_LOAD_ERROR
;
1477 Attribute
= Info
->Attribute
& ~EFI_FILE_READ_ONLY
;
1482 // if file exits, so delete it
1484 Status
= ShellDeleteFile (&FileHandle
);
1485 if (EFI_ERROR (Status
) || Status
== EFI_WARN_DELETE_FAILURE
) {
1486 StatusBarSetStatusString (L
"Write File Failed");
1487 return EFI_LOAD_ERROR
;
1491 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
|EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_CREATE
, Attribute
);
1493 if (EFI_ERROR (Status
)) {
1494 StatusBarSetStatusString (L
"Create File Failed");
1495 return EFI_LOAD_ERROR
;
1499 // if file is Unicode file, write Unicode header to it.
1501 if (FileBuffer
.FileType
== FileTypeUnicode
) {
1503 Status
= ShellWriteFile (FileHandle
, &Length
, (VOID
*)&gUnicodeFileTag
);
1504 if (EFI_ERROR (Status
)) {
1505 ShellDeleteFile (&FileHandle
);
1506 return EFI_LOAD_ERROR
;
1510 Cache
= AllocateZeroPool (TotalSize
);
1511 if (Cache
== NULL
) {
1512 ShellDeleteFile (&FileHandle
);
1513 return EFI_OUT_OF_RESOURCES
;
1517 // write all the lines back to disk
1520 Type
= NewLineTypeCarriageReturnLineFeed
;
1523 LeftSize
= TotalSize
;
1525 for (Link
= FileBuffer
.ListHead
->ForwardLink
; Link
!= FileBuffer
.ListHead
; Link
= Link
->ForwardLink
) {
1526 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1528 if (Line
->Type
!= NewLineTypeDefault
) {
1532 // newline character is at most 4 bytes ( two Unicode characters )
1535 if (Line
->Buffer
!= NULL
&& Line
->Size
!= 0) {
1536 if (FileBuffer
.FileType
== FileTypeAscii
) {
1537 Length
+= Line
->Size
;
1539 Length
+= (Line
->Size
* 2);
1542 // end if FileTypeAscii
1547 // no cache room left, so write cache to disk
1549 if (LeftSize
< Length
) {
1550 Size
= TotalSize
- LeftSize
;
1551 Status
= ShellWriteFile (FileHandle
, &Size
, Cache
);
1552 if (EFI_ERROR (Status
)) {
1553 ShellDeleteFile (&FileHandle
);
1555 return EFI_LOAD_ERROR
;
1558 LeftSize
= TotalSize
;
1561 if (Line
->Buffer
!= NULL
&& Line
->Size
!= 0) {
1562 if (FileBuffer
.FileType
== FileTypeAscii
) {
1563 UnicodeToAscii (Line
->Buffer
, Line
->Size
, Ptr
);
1564 Length
= Line
->Size
;
1566 Length
= (Line
->Size
* 2);
1567 CopyMem (Ptr
, (CHAR8
*) Line
->Buffer
, Length
);
1570 // end if FileTypeAscii
1577 // end of if Line -> Buffer != NULL && Line -> Size != 0
1579 // if not the last line , write return buffer to disk
1581 if (Link
->ForwardLink
!= FileBuffer
.ListHead
) {
1582 GetNewLine (Type
, NewLineBuffer
, &NewLineSize
);
1583 CopyMem (Ptr
, (CHAR8
*) NewLineBuffer
, NewLineSize
);
1586 LeftSize
-= NewLineSize
;
1592 if (TotalSize
!= LeftSize
) {
1593 Size
= TotalSize
- LeftSize
;
1594 Status
= ShellWriteFile (FileHandle
, &Size
, Cache
);
1595 if (EFI_ERROR (Status
)) {
1596 ShellDeleteFile (&FileHandle
);
1598 return EFI_LOAD_ERROR
;
1604 ShellCloseFile(&FileHandle
);
1606 FileBuffer
.FileModified
= FALSE
;
1609 // set status string
1611 Str
= CatSPrint (NULL
, L
"%d Lines Wrote", NumLines
);
1613 return EFI_OUT_OF_RESOURCES
;
1616 StatusBarSetStatusString (Str
);
1617 SHELL_FREE_NON_NULL (Str
);
1620 // now everything is ready , you can set the new file name to filebuffer
1622 if (FileName
!= NULL
&& FileBuffer
.FileName
!= NULL
&& StrCmp (FileName
, FileBuffer
.FileName
) != 0) {
1626 FileBufferSetFileName (FileName
);
1627 if (FileBuffer
.FileName
== NULL
) {
1628 ShellDeleteFile (&FileHandle
);
1629 return EFI_OUT_OF_RESOURCES
;
1633 FileBuffer
.ReadOnly
= FALSE
;
1638 Scroll cursor to left 1 character position.
1640 @retval EFI_SUCCESS The operation was successful.
1643 FileBufferScrollLeft (
1647 EFI_EDITOR_LINE
*Line
;
1651 Line
= FileBuffer
.CurrentLine
;
1653 FRow
= FileBuffer
.FilePosition
.Row
;
1654 FCol
= FileBuffer
.FilePosition
.Column
;
1657 // if already at start of this line, so move to the end of previous line
1661 // has previous line
1663 if (Line
->Link
.BackLink
!= FileBuffer
.ListHead
) {
1665 Line
= CR (Line
->Link
.BackLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1666 FCol
= Line
->Size
+ 1;
1672 // if not at start of this line, just move to previous column
1677 FileBufferMovePosition (FRow
, FCol
);
1683 Delete a char in line
1685 @param[in, out] Line The line to delete in.
1686 @param[in] Pos Position to delete the char at ( start from 0 ).
1690 IN OUT EFI_EDITOR_LINE
*Line
,
1697 // move the latter characters front
1699 for (Index
= Pos
- 1; Index
< Line
->Size
; Index
++) {
1700 Line
->Buffer
[Index
] = Line
->Buffer
[Index
+ 1];
1707 Concatenate Src into Dest.
1709 @param[in, out] Dest Destination string
1710 @param[in] Src Src String.
1714 IN OUT EFI_EDITOR_LINE
*Dest
,
1715 IN EFI_EDITOR_LINE
*Src
1723 Dest
->Buffer
[Size
] = 0;
1726 // concatenate the two strings
1728 Str
= CatSPrint (NULL
, L
"%s%s", Dest
->Buffer
, Src
->Buffer
);
1730 Dest
->Buffer
= NULL
;
1734 Dest
->Size
= Size
+ Src
->Size
;
1735 Dest
->TotalSize
= Dest
->Size
;
1737 FreePool (Dest
->Buffer
);
1738 FreePool (Src
->Buffer
);
1741 // put str to dest->buffer
1747 Delete the previous character.
1749 @retval EFI_SUCCESS The delete was successful.
1750 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1753 FileBufferDoBackspace (
1757 EFI_EDITOR_LINE
*Line
;
1758 EFI_EDITOR_LINE
*End
;
1762 FileColumn
= FileBuffer
.FilePosition
.Column
;
1764 Line
= FileBuffer
.CurrentLine
;
1769 if (FileColumn
== 1) {
1773 if (FileBuffer
.FilePosition
.Row
== 1) {
1777 FileBufferScrollLeft ();
1779 Line
= FileBuffer
.CurrentLine
;
1780 Link
= Line
->Link
.ForwardLink
;
1781 End
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1784 // concatenate this line with previous line
1786 LineCat (Line
, End
);
1787 if (Line
->Buffer
== NULL
) {
1788 return EFI_OUT_OF_RESOURCES
;
1791 // remove End from line list
1793 RemoveEntryList (&End
->Link
);
1796 FileBuffer
.NumLines
--;
1798 FileBufferNeedRefresh
= TRUE
;
1799 FileBufferOnlyLineNeedRefresh
= FALSE
;
1803 // just delete the previous character
1805 LineDeleteAt (Line
, FileColumn
- 1);
1806 FileBufferScrollLeft ();
1807 FileBufferOnlyLineNeedRefresh
= TRUE
;
1810 if (!FileBuffer
.FileModified
) {
1811 FileBuffer
.FileModified
= TRUE
;
1818 Add a return into line at current position.
1820 @retval EFI_SUCCESS The insetrion of the character was successful.
1821 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1824 FileBufferDoReturn (
1828 EFI_EDITOR_LINE
*Line
;
1829 EFI_EDITOR_LINE
*NewLine
;
1836 FileBufferNeedRefresh
= TRUE
;
1837 FileBufferOnlyLineNeedRefresh
= FALSE
;
1839 Line
= FileBuffer
.CurrentLine
;
1841 FileColumn
= FileBuffer
.FilePosition
.Column
;
1843 NewLine
= AllocateZeroPool (sizeof (EFI_EDITOR_LINE
));
1844 if (NewLine
== NULL
) {
1845 return EFI_OUT_OF_RESOURCES
;
1848 NewLine
->Signature
= LINE_LIST_SIGNATURE
;
1849 NewLine
->Size
= Line
->Size
- FileColumn
+ 1;
1850 NewLine
->TotalSize
= NewLine
->Size
;
1851 NewLine
->Buffer
= CatSPrint (NULL
, L
"\0");
1852 if (NewLine
->Buffer
== NULL
) {
1853 return EFI_OUT_OF_RESOURCES
;
1856 NewLine
->Type
= NewLineTypeDefault
;
1858 if (NewLine
->Size
> 0) {
1860 // UNICODE + CHAR_NULL
1862 Buffer
= AllocateZeroPool (2 * (NewLine
->Size
+ 1));
1863 if (Buffer
== NULL
) {
1864 FreePool (NewLine
->Buffer
);
1866 return EFI_OUT_OF_RESOURCES
;
1869 FreePool (NewLine
->Buffer
);
1871 NewLine
->Buffer
= Buffer
;
1873 for (Index
= 0; Index
< NewLine
->Size
; Index
++) {
1874 NewLine
->Buffer
[Index
] = Line
->Buffer
[Index
+ FileColumn
- 1];
1877 NewLine
->Buffer
[NewLine
->Size
] = CHAR_NULL
;
1879 Line
->Buffer
[FileColumn
- 1] = CHAR_NULL
;
1880 Line
->Size
= FileColumn
- 1;
1883 // increase NumLines
1885 FileBuffer
.NumLines
++;
1888 // insert it into the correct position of line list
1890 NewLine
->Link
.BackLink
= &(Line
->Link
);
1891 NewLine
->Link
.ForwardLink
= Line
->Link
.ForwardLink
;
1892 Line
->Link
.ForwardLink
->BackLink
= &(NewLine
->Link
);
1893 Line
->Link
.ForwardLink
= &(NewLine
->Link
);
1896 // move cursor to the start of next line
1898 Row
= FileBuffer
.FilePosition
.Row
+ 1;
1901 FileBufferMovePosition (Row
, Col
);
1904 // set file is modified
1906 if (!FileBuffer
.FileModified
) {
1907 FileBuffer
.FileModified
= TRUE
;
1914 Delete current character from current line. This is the effect caused
1920 FileBufferDoDelete (
1924 EFI_EDITOR_LINE
*Line
;
1925 EFI_EDITOR_LINE
*Next
;
1929 Line
= FileBuffer
.CurrentLine
;
1930 FileColumn
= FileBuffer
.FilePosition
.Column
;
1935 if (FileColumn
>= Line
->Size
+ 1) {
1939 if (Line
->Link
.ForwardLink
== FileBuffer
.ListHead
) {
1943 // since last character,
1944 // so will add the next line to this line
1946 Link
= Line
->Link
.ForwardLink
;
1947 Next
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1948 LineCat (Line
, Next
);
1949 if (Line
->Buffer
== NULL
) {
1950 return EFI_OUT_OF_RESOURCES
;
1953 RemoveEntryList (&Next
->Link
);
1956 FileBuffer
.NumLines
--;
1958 FileBufferNeedRefresh
= TRUE
;
1959 FileBufferOnlyLineNeedRefresh
= FALSE
;
1963 // just delete current character
1965 LineDeleteAt (Line
, FileColumn
);
1966 FileBufferOnlyLineNeedRefresh
= TRUE
;
1969 if (!FileBuffer
.FileModified
) {
1970 FileBuffer
.FileModified
= TRUE
;
1977 Scroll cursor to right 1 character.
1979 @retval EFI_SUCCESS The operation was successful.
1982 FileBufferScrollRight (
1986 EFI_EDITOR_LINE
*Line
;
1990 Line
= FileBuffer
.CurrentLine
;
1991 if (Line
->Buffer
== NULL
) {
1995 FRow
= FileBuffer
.FilePosition
.Row
;
1996 FCol
= FileBuffer
.FilePosition
.Column
;
1999 // if already at end of this line, scroll it to the start of next line
2001 if (FCol
> Line
->Size
) {
2005 if (Line
->Link
.ForwardLink
!= FileBuffer
.ListHead
) {
2013 // if not at end of this line, just move to next column
2018 FileBufferMovePosition (FRow
, FCol
);
2024 Insert a char into line
2027 @param[in] Line The line to insert into.
2028 @param[in] Char The char to insert.
2029 @param[in] Pos The position to insert the char at ( start from 0 ).
2030 @param[in] StrSize The current string size ( include CHAR_NULL ),unit is Unicode character.
2032 @return The new string size ( include CHAR_NULL ) ( unit is Unicode character ).
2036 IN EFI_EDITOR_LINE
*Line
,
2043 CHAR16
*TempStringPtr
;
2046 Index
= (StrSize
) * 2;
2051 // do not have free space
2053 if (Line
->TotalSize
<= Line
->Size
) {
2054 Str
= ReallocatePool (Index
, Index
+ 16, Str
);
2059 Line
->TotalSize
+= 8;
2062 // move the later part of the string one character right
2064 TempStringPtr
= Str
;
2065 for (Index
= StrSize
; Index
> Pos
; Index
--) {
2066 TempStringPtr
[Index
] = TempStringPtr
[Index
- 1];
2069 // insert char into it.
2071 TempStringPtr
[Index
] = Char
;
2080 Add a character to the current line.
2082 @param[in] Char The Character to input.
2084 @retval EFI_SUCCESS The input was succesful.
2091 EFI_EDITOR_LINE
*Line
;
2094 Line
= FileBuffer
.CurrentLine
;
2097 // only needs to refresh current line
2099 FileBufferOnlyLineNeedRefresh
= TRUE
;
2102 // when is insert mode, or cursor is at end of this line,
2103 // so insert this character
2104 // or replace the character.
2106 FilePos
= FileBuffer
.FilePosition
.Column
- 1;
2107 if (FileBuffer
.ModeInsert
|| FilePos
+ 1 > Line
->Size
) {
2108 LineStrInsert (Line
, Char
, FilePos
, Line
->Size
+ 1);
2110 Line
->Buffer
[FilePos
] = Char
;
2113 // move cursor to right
2115 FileBufferScrollRight ();
2117 if (!FileBuffer
.FileModified
) {
2118 FileBuffer
.FileModified
= TRUE
;
2125 Handles inputs from characters (ASCII key + Backspace + return)
2127 @param[in] Char The input character.
2129 @retval EFI_SUCCESS The operation was successful.
2130 @retval EFI_LOAD_ERROR There was an error.
2131 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2134 FileBufferDoCharInput (
2135 IN CONST CHAR16 Char
2140 Status
= EFI_SUCCESS
;
2146 case CHAR_BACKSPACE
:
2147 Status
= FileBufferDoBackspace ();
2157 case CHAR_CARRIAGE_RETURN
:
2158 Status
= FileBufferDoReturn ();
2163 // DEAL WITH ASCII CHAR, filter out thing like ctrl+f
2165 if (Char
> 127 || Char
< 32) {
2166 Status
= StatusBarSetStatusString (L
"Unknown Command");
2168 Status
= FileBufferAddChar (Char
);
2179 Scroll cursor to the next line.
2181 @retval EFI_SUCCESS The operation was successful.
2184 FileBufferScrollDown (
2188 EFI_EDITOR_LINE
*Line
;
2192 Line
= FileBuffer
.CurrentLine
;
2193 if (Line
->Buffer
== NULL
) {
2197 FRow
= FileBuffer
.FilePosition
.Row
;
2198 FCol
= FileBuffer
.FilePosition
.Column
;
2203 if (Line
->Link
.ForwardLink
!= FileBuffer
.ListHead
) {
2205 Line
= CR (Line
->Link
.ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2208 // if the next line is not that long, so move to end of next line
2210 if (FCol
> Line
->Size
) {
2211 FCol
= Line
->Size
+ 1;
2218 FileBufferMovePosition (FRow
, FCol
);
2224 Scroll the cursor to previous line.
2226 @retval EFI_SUCCESS The operation was successful.
2229 FileBufferScrollUp (
2233 EFI_EDITOR_LINE
*Line
;
2237 Line
= FileBuffer
.CurrentLine
;
2239 FRow
= FileBuffer
.FilePosition
.Row
;
2240 FCol
= FileBuffer
.FilePosition
.Column
;
2243 // has previous line
2245 if (Line
->Link
.BackLink
!= FileBuffer
.ListHead
) {
2247 Line
= CR (Line
->Link
.BackLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2250 // if previous line is not that long, so move to the end of previous line
2252 if (FCol
> Line
->Size
) {
2253 FCol
= Line
->Size
+ 1;
2260 FileBufferMovePosition (FRow
, FCol
);
2266 Scroll cursor to next page.
2268 @retval EFI_SUCCESS The operation wa successful.
2271 FileBufferPageDown (
2275 EFI_EDITOR_LINE
*Line
;
2280 Line
= FileBuffer
.CurrentLine
;
2282 FRow
= FileBuffer
.FilePosition
.Row
;
2283 FCol
= FileBuffer
.FilePosition
.Column
;
2288 if (FileBuffer
.NumLines
>= FRow
+ (MainEditor
.ScreenSize
.Row
- 2)) {
2289 Gap
= (MainEditor
.ScreenSize
.Row
- 2);
2292 // MOVE CURSOR TO LAST LINE
2294 Gap
= FileBuffer
.NumLines
- FRow
;
2299 Line
= MoveLine (Gap
);
2302 // if that line, is not that long, so move to the end of that line
2304 if (Line
!= NULL
&& FCol
> Line
->Size
) {
2305 FCol
= Line
->Size
+ 1;
2310 FileBufferMovePosition (FRow
, FCol
);
2316 Scroll cursor to previous screen.
2318 @retval EFI_SUCCESS The operation was successful.
2325 EFI_EDITOR_LINE
*Line
;
2331 Line
= FileBuffer
.CurrentLine
;
2333 FRow
= FileBuffer
.FilePosition
.Row
;
2334 FCol
= FileBuffer
.FilePosition
.Column
;
2337 // has previous page
2339 if (FRow
> (MainEditor
.ScreenSize
.Row
- 2)) {
2340 Gap
= (MainEditor
.ScreenSize
.Row
- 2);
2343 // the first line of file will displayed on the first line of screen
2354 Line
= MoveLine (Retreat
);
2357 // if that line is not that long, so move to the end of that line
2359 if (Line
!= NULL
&& FCol
> Line
->Size
) {
2360 FCol
= Line
->Size
+ 1;
2365 FileBufferMovePosition (FRow
, FCol
);
2371 Scroll cursor to end of the current line.
2373 @retval EFI_SUCCESS The operation was successful.
2380 EFI_EDITOR_LINE
*Line
;
2384 Line
= FileBuffer
.CurrentLine
;
2386 FRow
= FileBuffer
.FilePosition
.Row
;
2389 // goto the last column of the line
2391 FCol
= Line
->Size
+ 1;
2393 FileBufferMovePosition (FRow
, FCol
);
2399 Dispatch input to different handler
2400 @param[in] Key The input key. One of:
2404 Direction key: up/down/left/right/pgup/pgdn
2408 @retval EFI_SUCCESS The dispatch was done successfully.
2409 @retval EFI_LOAD_ERROR The dispatch was not successful.
2410 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2413 FileBufferHandleInput (
2414 IN CONST EFI_INPUT_KEY
*Key
2419 Status
= EFI_SUCCESS
;
2421 switch (Key
->ScanCode
) {
2423 // ordinary key input
2426 if (!FileBuffer
.ReadOnly
) {
2427 Status
= FileBufferDoCharInput (Key
->UnicodeChar
);
2429 Status
= StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2438 Status
= FileBufferScrollUp ();
2445 Status
= FileBufferScrollDown ();
2452 Status
= FileBufferScrollRight ();
2459 Status
= FileBufferScrollLeft ();
2466 Status
= FileBufferPageUp ();
2472 case SCAN_PAGE_DOWN
:
2473 Status
= FileBufferPageDown ();
2480 if (!FileBuffer
.ReadOnly
) {
2481 Status
= FileBufferDoDelete ();
2483 Status
= StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2492 FileBufferMovePosition (FileBuffer
.FilePosition
.Row
, 1);
2493 Status
= EFI_SUCCESS
;
2500 Status
= FileBufferEnd ();
2507 FileBuffer
.ModeInsert
= (BOOLEAN
)!FileBuffer
.ModeInsert
;
2508 Status
= EFI_SUCCESS
;
2512 Status
= StatusBarSetStatusString (L
"Unknown Command");
2520 Check user specified FileRow is above current screen.
2522 @param[in] FileRow The row of file position ( start from 1 ).
2524 @retval TRUE It is above the current screen.
2525 @retval FALSE It is not above the current screen.
2528 AboveCurrentScreen (
2533 // if is to the above of the screen
2535 if (FileRow
< FileBuffer
.LowVisibleRange
.Row
) {
2543 Check user specified FileRow is under current screen.
2545 @param[in] FileRow The row of file position ( start from 1 ).
2547 @retval TRUE It is under the current screen.
2548 @retval FALSE It is not under the current screen.
2551 UnderCurrentScreen (
2556 // if is to the under of the screen
2558 if (FileRow
> FileBuffer
.LowVisibleRange
.Row
+ (MainEditor
.ScreenSize
.Row
- 2) - 1) {
2566 Check user specified FileCol is left to current screen.
2568 @param[in] FileCol The column of file position ( start from 1 ).
2570 @retval TRUE It is to the left.
2571 @retval FALSE It is not to the left.
2579 // if is to the left of the screen
2581 if (FileCol
< FileBuffer
.LowVisibleRange
.Column
) {
2589 Check user specified FileCol is right to current screen.
2591 @param[in] FileCol The column of file position ( start from 1 ).
2593 @retval TRUE It is to the right.
2594 @retval FALSE It is not to the right.
2597 RightCurrentScreen (
2602 // if is to the right of the screen
2604 if (FileCol
> FileBuffer
.LowVisibleRange
.Column
+ MainEditor
.ScreenSize
.Column
- 1) {
2612 Advance/Retreat lines and set CurrentLine in FileBuffer to it
2614 @param[in] Count The line number to advance/retreat
2618 @retval NULL An error occured.
2619 @return The line after advance/retreat.
2626 EFI_EDITOR_LINE
*Line
;
2630 AbsCount
= (UINTN
)ABS(Count
);
2631 Line
= InternalEditorMiscLineRetreat (AbsCount
,MainEditor
.FileBuffer
->CurrentLine
,MainEditor
.FileBuffer
->ListHead
);
2633 Line
= InternalEditorMiscLineAdvance ((UINTN
)Count
,MainEditor
.FileBuffer
->CurrentLine
,MainEditor
.FileBuffer
->ListHead
);
2640 MainEditor
.FileBuffer
->CurrentLine
= Line
;
2646 According to cursor's file position, adjust screen display
2648 @param[in] NewFilePosRow The row of file position ( start from 1 ).
2649 @param[in] NewFilePosCol The column of file position ( start from 1 ).
2652 FileBufferMovePosition (
2653 IN CONST UINTN NewFilePosRow
,
2654 IN CONST UINTN NewFilePosCol
2666 // CALCULATE gap between current file position and new file position
2668 RowGap
= NewFilePosRow
- FileBuffer
.FilePosition
.Row
;
2669 ColGap
= NewFilePosCol
- FileBuffer
.FilePosition
.Column
;
2671 Under
= UnderCurrentScreen (NewFilePosRow
);
2672 Above
= AboveCurrentScreen (NewFilePosRow
);
2674 // if is below current screen
2678 // display row will be unchanged
2680 FileBuffer
.FilePosition
.Row
= NewFilePosRow
;
2684 // has enough above line, so display row unchanged
2685 // not has enough above lines, so the first line is at the
2686 // first display line
2688 if (NewFilePosRow
< (FileBuffer
.DisplayPosition
.Row
- 1)) {
2689 FileBuffer
.DisplayPosition
.Row
= NewFilePosRow
+ 1;
2692 FileBuffer
.FilePosition
.Row
= NewFilePosRow
;
2695 // in current screen
2697 FileBuffer
.FilePosition
.Row
= NewFilePosRow
;
2699 Abs
= (UINTN
)ABS(RowGap
);
2700 FileBuffer
.DisplayPosition
.Row
-= Abs
;
2702 FileBuffer
.DisplayPosition
.Row
+= RowGap
;
2707 FileBuffer
.LowVisibleRange
.Row
= FileBuffer
.FilePosition
.Row
- (FileBuffer
.DisplayPosition
.Row
- 2);
2709 Right
= RightCurrentScreen (NewFilePosCol
);
2710 Left
= LeftCurrentScreen (NewFilePosCol
);
2713 // if right to current screen
2717 // display column will be changed to end
2719 FileBuffer
.DisplayPosition
.Column
= MainEditor
.ScreenSize
.Column
;
2720 FileBuffer
.FilePosition
.Column
= NewFilePosCol
;
2724 // has enough left characters , so display row unchanged
2725 // not has enough left characters,
2726 // so the first character is at the first display column
2728 if (NewFilePosCol
< (FileBuffer
.DisplayPosition
.Column
)) {
2729 FileBuffer
.DisplayPosition
.Column
= NewFilePosCol
;
2732 FileBuffer
.FilePosition
.Column
= NewFilePosCol
;
2735 // in current screen
2737 FileBuffer
.FilePosition
.Column
= NewFilePosCol
;
2739 Abs
= (UINTN
)(-ColGap
);
2740 FileBuffer
.DisplayPosition
.Column
-= Abs
;
2742 FileBuffer
.DisplayPosition
.Column
+= ColGap
;
2747 FileBuffer
.LowVisibleRange
.Column
= FileBuffer
.FilePosition
.Column
- (FileBuffer
.DisplayPosition
.Column
- 1);
2750 // let CurrentLine point to correct line;
2752 FileBuffer
.CurrentLine
= MoveCurrentLine (RowGap
);
2757 Cut current line out and return a pointer to it.
2759 @param[out] CutLine Upon a successful return pointer to the pointer to
2760 the allocated cut line.
2762 @retval EFI_SUCCESS The cut was successful.
2763 @retval EFI_NOT_FOUND There was no selection to cut.
2764 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2768 OUT EFI_EDITOR_LINE
**CutLine
2771 EFI_EDITOR_LINE
*Line
;
2772 EFI_EDITOR_LINE
*NewLine
;
2776 if (FileBuffer
.ReadOnly
) {
2777 StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2781 Line
= FileBuffer
.CurrentLine
;
2784 // if is the last dummy line, SO CAN not cut
2786 if (StrCmp (Line
->Buffer
, L
"\0") == 0 && Line
->Link
.ForwardLink
== FileBuffer
.ListHead
2792 // LAST LINE AND NOTHING ON THIS LINE, SO CUT NOTHING
2794 StatusBarSetStatusString (L
"Nothing to Cut");
2795 return EFI_NOT_FOUND
;
2798 // if is the last line, so create a dummy line
2800 if (Line
->Link
.ForwardLink
== FileBuffer
.ListHead
) {
2803 // create a new line
2805 NewLine
= FileBufferCreateLine ();
2806 if (NewLine
== NULL
) {
2807 return EFI_OUT_OF_RESOURCES
;
2811 FileBuffer
.NumLines
--;
2812 Row
= FileBuffer
.FilePosition
.Row
;
2817 FileBuffer
.CurrentLine
= CR (
2818 FileBuffer
.CurrentLine
->Link
.ForwardLink
,
2824 RemoveEntryList (&Line
->Link
);
2826 FileBuffer
.Lines
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2828 FileBufferMovePosition (Row
, Col
);
2830 FileBuffer
.FileModified
= TRUE
;
2831 FileBufferNeedRefresh
= TRUE
;
2832 FileBufferOnlyLineNeedRefresh
= FALSE
;
2840 Paste a line into line list.
2842 @retval EFI_SUCCESS The paste was successful.
2843 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2846 FileBufferPasteLine (
2850 EFI_EDITOR_LINE
*Line
;
2851 EFI_EDITOR_LINE
*NewLine
;
2856 // if nothing is on clip board
2859 if (MainEditor
.CutLine
== NULL
) {
2863 // read only file can not be pasted on
2865 if (FileBuffer
.ReadOnly
) {
2866 StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2870 NewLine
= LineDup (MainEditor
.CutLine
);
2871 if (NewLine
== NULL
) {
2872 return EFI_OUT_OF_RESOURCES
;
2875 // insert it above current line
2877 Line
= FileBuffer
.CurrentLine
;
2878 NewLine
->Link
.BackLink
= Line
->Link
.BackLink
;
2879 NewLine
->Link
.ForwardLink
= &Line
->Link
;
2881 Line
->Link
.BackLink
->ForwardLink
= &NewLine
->Link
;
2882 Line
->Link
.BackLink
= &NewLine
->Link
;
2884 FileBuffer
.NumLines
++;
2885 FileBuffer
.CurrentLine
= NewLine
;
2887 FileBuffer
.Lines
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2893 Row
= FileBuffer
.FilePosition
.Row
;
2895 FileBufferMovePosition (Row
, Col
);
2898 // after paste, set some value so that refresh knows to do something
2900 FileBuffer
.FileModified
= TRUE
;
2901 FileBufferNeedRefresh
= TRUE
;
2902 FileBufferOnlyLineNeedRefresh
= FALSE
;
2908 Search string from current position on in file
2910 @param[in] Str The search string.
2911 @param[in] Offset The offset from current position.
2913 @retval EFI_SUCCESS The operation was successful.
2914 @retval EFI_NOT_FOUND The string Str was not found.
2918 IN CONST CHAR16
*Str
,
2919 IN CONST UINTN Offset
2926 EFI_EDITOR_LINE
*Line
;
2935 // search if in current line
2937 Current
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1 + Offset
;
2939 if (Current
>= (FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.CurrentLine
->Size
)) {
2943 Current
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.CurrentLine
->Size
;
2948 CharPos
= StrStr (Current
, Str
);
2949 if (CharPos
!= NULL
) {
2950 Position
= CharPos
- Current
+ 1;
2958 Column
= (Position
- 1) + FileBuffer
.FilePosition
.Column
+ Offset
;
2959 Row
= FileBuffer
.FilePosition
.Row
;
2962 // not found so find through next lines
2964 Link
= FileBuffer
.CurrentLine
->Link
.ForwardLink
;
2966 Row
= FileBuffer
.FilePosition
.Row
+ 1;
2967 while (Link
!= FileBuffer
.ListHead
) {
2968 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2969 // Position = StrStr (Line->Buffer, Str);
2970 CharPos
= StrStr (Line
->Buffer
, Str
);
2971 if (CharPos
!= NULL
) {
2972 Position
= CharPos
- Line
->Buffer
+ 1;
2985 Link
= Link
->ForwardLink
;
2988 if (Link
== FileBuffer
.ListHead
) {
2996 return EFI_NOT_FOUND
;
2999 FileBufferMovePosition (Row
, Column
);
3002 // call refresh to fresh edit area,
3003 // because the outer may loop to find multiply occurrence of this string
3005 FileBufferRefresh ();
3011 Replace SearchLen characters from current position on with Replace.
3013 This will modify the current buffer at the current position.
3015 @param[in] Replace The string to replace.
3016 @param[in] SearchLen Search string's length.
3018 @retval EFI_SUCCESS The operation was successful.
3019 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3023 IN CONST CHAR16
*Replace
,
3024 IN CONST UINTN SearchLen
3034 ReplaceLen
= StrLen (Replace
);
3036 OldSize
= FileBuffer
.CurrentLine
->Size
+ 1;
3038 // include CHAR_NULL
3040 NewSize
= OldSize
+ (ReplaceLen
- SearchLen
);
3042 if (ReplaceLen
> SearchLen
) {
3044 // do not have the enough space
3046 if (FileBuffer
.CurrentLine
->TotalSize
+ 1 <= NewSize
) {
3047 FileBuffer
.CurrentLine
->Buffer
= ReallocatePool (
3050 FileBuffer
.CurrentLine
->Buffer
3052 FileBuffer
.CurrentLine
->TotalSize
= NewSize
- 1;
3055 if (FileBuffer
.CurrentLine
->Buffer
== NULL
) {
3056 return EFI_OUT_OF_RESOURCES
;
3059 // the end CHAR_NULL character;
3061 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ (NewSize
- 1);
3062 Gap
= ReplaceLen
- SearchLen
;
3065 // keep the latter part
3067 for (Index
= 0; Index
< (FileBuffer
.CurrentLine
->Size
- FileBuffer
.FilePosition
.Column
- SearchLen
+ 2); Index
++) {
3068 *Buffer
= *(Buffer
- Gap
);
3072 // set replace into it
3074 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1;
3075 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3076 Buffer
[Index
] = Replace
[Index
];
3080 if (ReplaceLen
< SearchLen
) {
3081 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1;
3083 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3084 Buffer
[Index
] = Replace
[Index
];
3087 Buffer
+= ReplaceLen
;
3088 Gap
= SearchLen
- ReplaceLen
;
3091 // set replace into it
3093 for (Index
= 0; Index
< (FileBuffer
.CurrentLine
->Size
- FileBuffer
.FilePosition
.Column
- ReplaceLen
+ 2); Index
++) {
3094 *Buffer
= *(Buffer
+ Gap
);
3099 if (ReplaceLen
== SearchLen
) {
3100 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1;
3101 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3102 Buffer
[Index
] = Replace
[Index
];
3106 FileBuffer
.CurrentLine
->Size
+= (ReplaceLen
- SearchLen
);
3108 FileBufferOnlyLineNeedRefresh
= TRUE
;
3110 FileBuffer
.FileModified
= TRUE
;
3112 MainTitleBarRefresh (MainEditor
.FileBuffer
->FileName
, MainEditor
.FileBuffer
->FileType
, MainEditor
.FileBuffer
->ReadOnly
, MainEditor
.FileBuffer
->FileModified
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
, 0, 0);
3113 FileBufferRestorePosition ();
3114 FileBufferRefresh ();
3120 Move the mouse cursor position.
3122 @param[in] TextX The new x-coordinate.
3123 @param[in] TextY The new y-coordinate.
3126 FileBufferAdjustMousePosition (
3127 IN CONST INT32 TextX
,
3128 IN CONST INT32 TextY
3137 // TextX and TextY is mouse movement data returned by mouse driver
3138 // This function will change it to MousePosition
3141 // get absolute value
3147 CoordinateX
= FileBuffer
.MousePosition
.Column
;
3148 CoordinateY
= FileBuffer
.MousePosition
.Row
;
3151 CoordinateX
+= TextX
;
3153 if (CoordinateX
>= AbsX
) {
3154 CoordinateX
-= AbsX
;
3161 CoordinateY
+= TextY
;
3163 if (CoordinateY
>= AbsY
) {
3164 CoordinateY
-= AbsY
;
3170 // check whether new mouse column position is beyond screen
3171 // if not, adjust it
3173 if (CoordinateX
>= 1 && CoordinateX
<= MainEditor
.ScreenSize
.Column
) {
3174 FileBuffer
.MousePosition
.Column
= CoordinateX
;
3175 } else if (CoordinateX
< 1) {
3176 FileBuffer
.MousePosition
.Column
= 1;
3177 } else if (CoordinateX
> MainEditor
.ScreenSize
.Column
) {
3178 FileBuffer
.MousePosition
.Column
= MainEditor
.ScreenSize
.Column
;
3181 // check whether new mouse row position is beyond screen
3182 // if not, adjust it
3184 if (CoordinateY
>= 2 && CoordinateY
<= (MainEditor
.ScreenSize
.Row
- 1)) {
3185 FileBuffer
.MousePosition
.Row
= CoordinateY
;
3186 } else if (CoordinateY
< 2) {
3187 FileBuffer
.MousePosition
.Row
= 2;
3188 } else if (CoordinateY
> (MainEditor
.ScreenSize
.Row
- 1)) {
3189 FileBuffer
.MousePosition
.Row
= (MainEditor
.ScreenSize
.Row
- 1);
3195 Search and replace operation.
3197 @param[in] SearchStr The string to search for.
3198 @param[in] ReplaceStr The string to replace with.
3199 @param[in] Offset The column to start at.
3202 FileBufferReplaceAll (
3203 IN CHAR16
*SearchStr
,
3204 IN CHAR16
*ReplaceStr
,
3217 EFI_EDITOR_LINE
*Line
;
3221 SearchLen
= StrLen (SearchStr
);
3222 ReplaceLen
= StrLen (ReplaceStr
);
3224 Column
= FileBuffer
.FilePosition
.Column
+ Offset
- 1;
3226 if (Column
> FileBuffer
.CurrentLine
->Size
) {
3227 Column
= FileBuffer
.CurrentLine
->Size
;
3230 Link
= &(FileBuffer
.CurrentLine
->Link
);
3232 while (Link
!= FileBuffer
.ListHead
) {
3233 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
3234 CharPos
= StrStr (Line
->Buffer
+ Column
, SearchStr
);
3235 if (CharPos
!= NULL
) {
3236 Position
= CharPos
- Line
->Buffer
;// + Column;
3240 if (ReplaceLen
> SearchLen
) {
3241 OldSize
= Line
->Size
+ 1;
3243 // include CHAR_NULL
3245 NewSize
= OldSize
+ (ReplaceLen
- SearchLen
);
3248 // do not have the enough space
3250 if (Line
->TotalSize
+ 1 <= NewSize
) {
3251 Line
->Buffer
= ReallocatePool (
3256 Line
->TotalSize
= NewSize
- 1;
3259 if (Line
->Buffer
== NULL
) {
3260 return EFI_OUT_OF_RESOURCES
;
3263 // the end CHAR_NULL character;
3265 Buffer
= Line
->Buffer
+ (NewSize
- 1);
3266 Gap
= ReplaceLen
- SearchLen
;
3269 // keep the latter part
3271 for (Index
= 0; Index
< (Line
->Size
- Position
- SearchLen
+ 1); Index
++) {
3272 *Buffer
= *(Buffer
- Gap
);
3276 } else if (ReplaceLen
< SearchLen
){
3277 Buffer
= Line
->Buffer
+ Position
+ ReplaceLen
;
3278 Gap
= SearchLen
- ReplaceLen
;
3280 for (Index
= 0; Index
< (Line
->Size
- Position
- ReplaceLen
+ 1); Index
++) {
3281 *Buffer
= *(Buffer
+ Gap
);
3285 ASSERT(ReplaceLen
== SearchLen
);
3288 // set replace into it
3290 Buffer
= Line
->Buffer
+ Position
;
3291 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3292 Buffer
[Index
] = ReplaceStr
[Index
];
3295 Line
->Size
+= (ReplaceLen
- SearchLen
);
3296 Column
+= ReplaceLen
;
3302 Link
= Link
->ForwardLink
;
3306 // call refresh to fresh edit area
3308 FileBuffer
.FileModified
= TRUE
;
3309 FileBufferNeedRefresh
= TRUE
;
3310 FileBufferRefresh ();
3316 Set the modified state to TRUE.
3319 FileBufferSetModified (
3323 FileBuffer
.FileModified
= TRUE
;