2 Implements filebuffer interface functions.
4 Copyright (c) 2005 - 2014, Intel Corporation. All rights reserved. <BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "TextEditor.h"
16 #include <Guid/FileSystemInfo.h>
17 #include <Library/FileHandleLib.h>
19 EFI_EDITOR_FILE_BUFFER FileBuffer
;
20 EFI_EDITOR_FILE_BUFFER FileBufferBackupVar
;
23 // for basic initialization of FileBuffer
25 EFI_EDITOR_FILE_BUFFER FileBufferConst
= {
54 // the whole edit area needs to be refreshed
56 BOOLEAN FileBufferNeedRefresh
;
59 // only the current line in edit area needs to be refresh
61 BOOLEAN FileBufferOnlyLineNeedRefresh
;
63 BOOLEAN FileBufferMouseNeedRefresh
;
65 extern BOOLEAN EditorMouseAction
;
68 Initialization function for FileBuffer.
70 @param EFI_SUCCESS The initialization was successful.
71 @param EFI_LOAD_ERROR A default name could not be created.
72 @param EFI_OUT_OF_RESOURCES A memory allocation failed.
81 // basically initialize the FileBuffer
83 CopyMem (&FileBuffer
, &FileBufferConst
, sizeof (EFI_EDITOR_FILE_BUFFER
));
84 CopyMem (&FileBufferBackupVar
, &FileBufferConst
, sizeof (EFI_EDITOR_FILE_BUFFER
));
87 // set default FileName
89 FileBuffer
.FileName
= EditGetDefaultFileName (L
"txt");
90 if (FileBuffer
.FileName
== NULL
) {
91 return EFI_LOAD_ERROR
;
94 FileBuffer
.ListHead
= AllocateZeroPool (sizeof (LIST_ENTRY
));
95 if (FileBuffer
.ListHead
== NULL
) {
96 return EFI_OUT_OF_RESOURCES
;
99 InitializeListHead (FileBuffer
.ListHead
);
101 FileBuffer
.DisplayPosition
.Row
= 2;
102 FileBuffer
.DisplayPosition
.Column
= 1;
103 FileBuffer
.LowVisibleRange
.Row
= 2;
104 FileBuffer
.LowVisibleRange
.Column
= 1;
106 FileBufferNeedRefresh
= FALSE
;
107 FileBufferMouseNeedRefresh
= FALSE
;
108 FileBufferOnlyLineNeedRefresh
= FALSE
;
114 Backup function for FileBuffer. Only backup the following items:
115 Mouse/Cursor position
116 File Name, Type, ReadOnly, Modified
119 This is for making the file buffer refresh as few as possible.
121 @retval EFI_SUCCESS The backup operation was successful.
129 FileBufferBackupVar
.MousePosition
= FileBuffer
.MousePosition
;
131 SHELL_FREE_NON_NULL (FileBufferBackupVar
.FileName
);
132 FileBufferBackupVar
.FileName
= NULL
;
133 FileBufferBackupVar
.FileName
= StrnCatGrow (&FileBufferBackupVar
.FileName
, NULL
, FileBuffer
.FileName
, 0);
135 FileBufferBackupVar
.ModeInsert
= FileBuffer
.ModeInsert
;
136 FileBufferBackupVar
.FileType
= FileBuffer
.FileType
;
138 FileBufferBackupVar
.FilePosition
= FileBuffer
.FilePosition
;
139 FileBufferBackupVar
.LowVisibleRange
= FileBuffer
.LowVisibleRange
;
141 FileBufferBackupVar
.FileModified
= FileBuffer
.FileModified
;
142 FileBufferBackupVar
.ReadOnly
= FileBuffer
.ReadOnly
;
148 Advance to the next Count lines
150 @param[in] Count The line number to advance by.
151 @param[in] CurrentLine The pointer to the current line structure.
152 @param[in] LineList The pointer to the linked list of lines.
154 @retval NULL There was an error.
155 @return The line structure after the advance.
159 InternalEditorMiscLineAdvance (
160 IN CONST UINTN Count
,
161 IN CONST EFI_EDITOR_LINE
*CurrentLine
,
162 IN CONST LIST_ENTRY
*LineList
167 CONST EFI_EDITOR_LINE
*Line
;
169 if (CurrentLine
== NULL
|| LineList
== NULL
) {
173 for (Line
= CurrentLine
, Index
= 0; Index
< Count
; Index
++) {
175 // if already last line
177 if (Line
->Link
.ForwardLink
== LineList
) {
181 Line
= CR (Line
->Link
.ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
184 return ((EFI_EDITOR_LINE
*)Line
);
188 Retreat to the previous Count lines.
190 @param[in] Count The line number to retreat by.
191 @param[in] CurrentLine The pointer to the current line structure.
192 @param[in] LineList The pointer to the linked list of lines.
194 @retval NULL There was an error.
195 @return The line structure after the retreat.
199 InternalEditorMiscLineRetreat (
200 IN CONST UINTN Count
,
201 IN CONST EFI_EDITOR_LINE
*CurrentLine
,
202 IN CONST LIST_ENTRY
*LineList
207 CONST EFI_EDITOR_LINE
*Line
;
209 if (CurrentLine
== NULL
|| LineList
== NULL
) {
213 for (Line
= CurrentLine
, Index
= 0; Index
< Count
; Index
++) {
215 // already the first line
217 if (Line
->Link
.BackLink
== LineList
) {
221 Line
= CR (Line
->Link
.BackLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
224 return ((EFI_EDITOR_LINE
*)Line
);
228 Advance/Retreat lines
230 @param[in] Count line number to advance/retreat
234 @retval NULL An error occured.
235 @return The line after advance/retreat.
242 EFI_EDITOR_LINE
*Line
;
246 // if < 0, then retreat
247 // if > 0, the advance
250 AbsCount
= (UINTN
)ABS(Count
);
251 Line
= InternalEditorMiscLineRetreat (AbsCount
,MainEditor
.FileBuffer
->CurrentLine
,MainEditor
.FileBuffer
->ListHead
);
253 Line
= InternalEditorMiscLineAdvance ((UINTN
)Count
,MainEditor
.FileBuffer
->CurrentLine
,MainEditor
.FileBuffer
->ListHead
);
260 Function to update the 'screen' to display the mouse position.
262 @retval EFI_SUCCESS The backup operation was successful.
266 FileBufferRestoreMousePosition (
270 EFI_EDITOR_COLOR_UNION Orig
;
271 EFI_EDITOR_COLOR_UNION New
;
274 BOOLEAN HasCharacter
;
275 EFI_EDITOR_LINE
*CurrentLine
;
276 EFI_EDITOR_LINE
*Line
;
280 // variable initialization
284 if (MainEditor
.MouseSupported
) {
286 if (FileBufferMouseNeedRefresh
) {
288 FileBufferMouseNeedRefresh
= FALSE
;
291 // if mouse position not moved and only mouse action
292 // so do not need to refresh mouse position
294 if ((FileBuffer
.MousePosition
.Row
== FileBufferBackupVar
.MousePosition
.Row
&&
295 FileBuffer
.MousePosition
.Column
== FileBufferBackupVar
.MousePosition
.Column
)
296 && EditorMouseAction
) {
300 // backup the old screen attributes
302 Orig
= MainEditor
.ColorAttributes
;
304 New
.Colors
.Foreground
= Orig
.Colors
.Background
& 0xF;
305 New
.Colors
.Background
= Orig
.Colors
.Foreground
& 0x7;
308 // clear the old mouse position
310 FRow
= FileBuffer
.LowVisibleRange
.Row
+ FileBufferBackupVar
.MousePosition
.Row
- 2;
312 FColumn
= FileBuffer
.LowVisibleRange
.Column
+ FileBufferBackupVar
.MousePosition
.Column
- 1;
315 if (FRow
> FileBuffer
.NumLines
) {
316 HasCharacter
= FALSE
;
318 CurrentLine
= FileBuffer
.CurrentLine
;
319 Line
= MoveLine (FRow
- FileBuffer
.FilePosition
.Row
);
321 if (Line
== NULL
|| FColumn
> Line
->Size
) {
322 HasCharacter
= FALSE
;
325 FileBuffer
.CurrentLine
= CurrentLine
;
329 (INT32
)FileBufferBackupVar
.MousePosition
.Column
- 1,
330 (INT32
)FileBufferBackupVar
.MousePosition
.Row
- 1,
335 Value
= (Line
->Buffer
[FColumn
- 1]);
337 (INT32
)FileBufferBackupVar
.MousePosition
.Column
- 1,
338 (INT32
)FileBufferBackupVar
.MousePosition
.Row
- 1,
344 // set the new mouse position
346 gST
->ConOut
->SetAttribute (gST
->ConOut
, New
.Data
& 0x7F);
349 // clear the old mouse position
351 FRow
= FileBuffer
.LowVisibleRange
.Row
+ FileBuffer
.MousePosition
.Row
- 2;
352 FColumn
= FileBuffer
.LowVisibleRange
.Column
+ FileBuffer
.MousePosition
.Column
- 1;
355 if (FRow
> FileBuffer
.NumLines
) {
356 HasCharacter
= FALSE
;
358 CurrentLine
= FileBuffer
.CurrentLine
;
359 Line
= MoveLine (FRow
- FileBuffer
.FilePosition
.Row
);
361 if (Line
== NULL
|| FColumn
> Line
->Size
) {
362 HasCharacter
= FALSE
;
365 FileBuffer
.CurrentLine
= CurrentLine
;
369 (INT32
)FileBuffer
.MousePosition
.Column
- 1,
370 (INT32
)FileBuffer
.MousePosition
.Row
- 1,
375 Value
= Line
->Buffer
[FColumn
- 1];
377 (INT32
)FileBuffer
.MousePosition
.Column
- 1,
378 (INT32
)FileBuffer
.MousePosition
.Row
- 1,
384 // end of HasCharacter
386 gST
->ConOut
->SetAttribute (gST
->ConOut
, Orig
.Data
);
389 // end of MouseNeedRefresh
393 // end of MouseSupported
399 Free all the lines in FileBuffer
406 @retval EFI_SUCCESS The operation was successful.
410 FileBufferFreeLines (
415 EFI_EDITOR_LINE
*Line
;
418 // free all the lines
420 if (FileBuffer
.Lines
!= NULL
) {
422 Line
= FileBuffer
.Lines
;
423 Link
= &(Line
->Link
);
425 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
426 Link
= Link
->ForwardLink
;
429 // free line's buffer and line itself
432 } while (Link
!= FileBuffer
.ListHead
);
435 // clean the line list related structure
437 FileBuffer
.Lines
= NULL
;
438 FileBuffer
.CurrentLine
= NULL
;
439 FileBuffer
.NumLines
= 0;
441 FileBuffer
.ListHead
->ForwardLink
= FileBuffer
.ListHead
;
442 FileBuffer
.ListHead
->BackLink
= FileBuffer
.ListHead
;
448 Cleanup function for FileBuffer.
450 @retval EFI_SUCCESS The cleanup was successful.
460 SHELL_FREE_NON_NULL (FileBuffer
.FileName
);
463 // free all the lines
465 Status
= FileBufferFreeLines ();
467 SHELL_FREE_NON_NULL (FileBuffer
.ListHead
);
468 FileBuffer
.ListHead
= NULL
;
470 SHELL_FREE_NON_NULL (FileBufferBackupVar
.FileName
);
476 Print a line specified by Line on a row specified by Row of the screen.
478 @param[in] Line The line to print.
479 @param[in] Row The row on the screen to print onto (begin from 1).
481 @retval EFI_SUCCESS The printing was successful.
484 FileBufferPrintLine (
485 IN CONST EFI_EDITOR_LINE
*Line
,
497 // print start from correct character
499 Buffer
= Line
->Buffer
+ FileBuffer
.LowVisibleRange
.Column
- 1;
501 Limit
= Line
->Size
- FileBuffer
.LowVisibleRange
.Column
+ 1;
502 if (Limit
> Line
->Size
) {
506 BufLen
= (MainEditor
.ScreenSize
.Column
+ 1) * sizeof (CHAR16
);
507 PrintLine
= AllocatePool (BufLen
);
508 ASSERT (PrintLine
!= NULL
);
510 StrnCpy (PrintLine
, Buffer
, MIN(Limit
, MainEditor
.ScreenSize
.Column
));
511 for (; Limit
< MainEditor
.ScreenSize
.Column
; Limit
++) {
512 PrintLine
[Limit
] = L
' ';
515 PrintLine
[MainEditor
.ScreenSize
.Column
] = CHAR_NULL
;
517 PrintLine2
= AllocatePool (BufLen
* 2);
518 ASSERT (PrintLine2
!= NULL
);
520 ShellCopySearchAndReplace(PrintLine
, PrintLine2
, BufLen
* 2, L
"%", L
"^%", FALSE
, FALSE
);
529 FreePool (PrintLine
);
530 FreePool (PrintLine2
);
536 Set the cursor position according to FileBuffer.DisplayPosition.
538 @retval EFI_SUCCESS The operation was successful.
542 FileBufferRestorePosition (
547 // set cursor position
549 return (gST
->ConOut
->SetCursorPosition (
551 FileBuffer
.DisplayPosition
.Column
- 1,
552 FileBuffer
.DisplayPosition
.Row
- 1
557 Refresh the screen with whats in the buffer.
559 @retval EFI_SUCCESS The refresh was successful.
560 @retval EFI_LOAD_ERROR There was an error finding what to write.
569 EFI_EDITOR_LINE
*Line
;
573 // if it's the first time after editor launch, so should refresh
577 // no definite required refresh
578 // and file position displayed on screen has not been changed
580 if (!FileBufferNeedRefresh
&&
581 !FileBufferOnlyLineNeedRefresh
&&
582 FileBufferBackupVar
.LowVisibleRange
.Row
== FileBuffer
.LowVisibleRange
.Row
&&
583 FileBufferBackupVar
.LowVisibleRange
.Column
== FileBuffer
.LowVisibleRange
.Column
586 FileBufferRestoreMousePosition ();
587 FileBufferRestorePosition ();
593 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
596 // only need to refresh current line
598 if (FileBufferOnlyLineNeedRefresh
&&
599 FileBufferBackupVar
.LowVisibleRange
.Row
== FileBuffer
.LowVisibleRange
.Row
&&
600 FileBufferBackupVar
.LowVisibleRange
.Column
== FileBuffer
.LowVisibleRange
.Column
603 EditorClearLine (FileBuffer
.DisplayPosition
.Row
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
);
604 FileBufferPrintLine (
605 FileBuffer
.CurrentLine
,
606 FileBuffer
.DisplayPosition
.Row
610 // the whole edit area need refresh
616 if (FileBuffer
.Lines
== NULL
) {
617 FileBufferRestoreMousePosition ();
618 FileBufferRestorePosition ();
619 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
624 // get the first line that will be displayed
626 Line
= MoveLine (FileBuffer
.LowVisibleRange
.Row
- FileBuffer
.FilePosition
.Row
);
628 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
630 return EFI_LOAD_ERROR
;
633 Link
= &(Line
->Link
);
636 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
641 FileBufferPrintLine (Line
, Row
);
643 Link
= Link
->ForwardLink
;
645 } while (Link
!= FileBuffer
.ListHead
&& Row
<= (MainEditor
.ScreenSize
.Row
- 1));
647 // while not file end and not screen full
649 while (Row
<= (MainEditor
.ScreenSize
.Row
- 1)) {
650 EditorClearLine (Row
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
);
655 FileBufferRestoreMousePosition ();
656 FileBufferRestorePosition ();
658 FileBufferNeedRefresh
= FALSE
;
659 FileBufferOnlyLineNeedRefresh
= FALSE
;
661 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
666 Create a new line and append it to the line list.
671 @retval NULL The create line failed.
672 @return The line created.
676 FileBufferCreateLine (
680 EFI_EDITOR_LINE
*Line
;
683 // allocate a line structure
685 Line
= AllocateZeroPool (sizeof (EFI_EDITOR_LINE
));
690 // initialize the structure
692 Line
->Signature
= LINE_LIST_SIGNATURE
;
695 Line
->Type
= NewLineTypeDefault
;
698 // initial buffer of the line is "\0"
700 ASSERT(CHAR_NULL
== CHAR_NULL
);
701 Line
->Buffer
= CatSPrint (NULL
, L
"\0");
702 if (Line
->Buffer
== NULL
) {
706 FileBuffer
.NumLines
++;
709 // insert the line into line list
711 InsertTailList (FileBuffer
.ListHead
, &Line
->Link
);
713 if (FileBuffer
.Lines
== NULL
) {
714 FileBuffer
.Lines
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
721 Set FileName field in FileBuffer.
723 @param Str The file name to set.
725 @retval EFI_SUCCESS The filename was successfully set.
726 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
727 @retval EFI_INVALID_PARAMETER Str is not a valid filename.
731 FileBufferSetFileName (
736 // Verify the parameters
738 if (!IsValidFileName(Str
)) {
739 return (EFI_INVALID_PARAMETER
);
742 // free the old file name
744 SHELL_FREE_NON_NULL (FileBuffer
.FileName
);
747 // Allocate and set the new name
749 FileBuffer
.FileName
= CatSPrint (NULL
, L
"%s", Str
);
750 if (FileBuffer
.FileName
== NULL
) {
751 return EFI_OUT_OF_RESOURCES
;
757 Free the existing file lines and reset the modified flag.
759 @retval EFI_SUCCESS The operation was successful.
768 // free all the lines
770 FileBufferFreeLines ();
771 FileBuffer
.FileModified
= FALSE
;
778 Read a file from disk into the FileBuffer.
780 @param[in] FileName The filename to read.
781 @param[in] Recover TRUE if is for recover mode, no information printouts.
783 @retval EFI_SUCCESS The load was successful.
784 @retval EFI_LOAD_ERROR The load failed.
785 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
786 @retval EFI_INVALID_PARAMETER FileName is a directory.
791 IN CONST CHAR16
*FileName
,
792 IN CONST BOOLEAN Recover
795 EFI_EDITOR_LINE
*Line
;
796 EE_NEWLINE_TYPE Type
;
801 CHAR16
*UnicodeBuffer
;
804 SHELL_FILE_HANDLE FileHandle
;
807 UINTN LineSizeBackup
;
813 UnicodeBuffer
= NULL
;
814 Type
= NewLineTypeDefault
;
819 // in this function, when you return error ( except EFI_OUT_OF_RESOURCES )
820 // you should set status string via StatusBarSetStatusString(L"blah")
821 // since this function maybe called before the editorhandleinput loop
822 // so any error will cause editor return
823 // so if you want to print the error status
824 // you should set the status string
828 // try to open the file
830 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
, 0);
832 if (!EFI_ERROR(Status
)) {
834 if (FileHandle
== NULL
) {
835 StatusBarSetStatusString (L
"Disk Error");
836 return EFI_LOAD_ERROR
;
839 Info
= ShellGetFileInfo(FileHandle
);
841 if (Info
->Attribute
& EFI_FILE_DIRECTORY
) {
842 StatusBarSetStatusString (L
"Directory Can Not Be Edited");
844 return EFI_INVALID_PARAMETER
;
847 if (Info
->Attribute
& EFI_FILE_READ_ONLY
) {
848 FileBuffer
.ReadOnly
= TRUE
;
850 FileBuffer
.ReadOnly
= FALSE
;
855 FileSize
= (UINTN
) Info
->FileSize
;
858 } else if (Status
== EFI_NOT_FOUND
) {
860 // file not exists. add create and try again
862 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
|EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_CREATE
, 0);
863 if (EFI_ERROR (Status
)) {
864 if (Status
== EFI_WRITE_PROTECTED
||
865 Status
== EFI_ACCESS_DENIED
||
866 Status
== EFI_NO_MEDIA
||
867 Status
== EFI_MEDIA_CHANGED
869 StatusBarSetStatusString (L
"Access Denied");
870 } else if (Status
== EFI_DEVICE_ERROR
|| Status
== EFI_VOLUME_CORRUPTED
|| Status
== EFI_VOLUME_FULL
) {
871 StatusBarSetStatusString (L
"Disk Error");
873 StatusBarSetStatusString (L
"Invalid File Name or Current-working-directory");
879 // it worked. now delete it and move on with the name (now validated)
881 Status
= ShellDeleteFile (&FileHandle
);
882 if (Status
== EFI_WARN_DELETE_FAILURE
) {
883 Status
= EFI_ACCESS_DENIED
;
886 if (EFI_ERROR (Status
)) {
887 StatusBarSetStatusString (L
"Access Denied");
892 // file doesn't exist, so set CreateFile to TRUE
895 FileBuffer
.ReadOnly
= FALSE
;
898 // all the check ends
899 // so now begin to set file name, free lines
901 if (StrCmp (FileName
, FileBuffer
.FileName
) != 0) {
902 FileBufferSetFileName (FileName
);
905 // free the old lines
915 // allocate buffer to read file
917 Buffer
= AllocateZeroPool (FileSize
);
918 if (Buffer
== NULL
) {
919 return EFI_OUT_OF_RESOURCES
;
922 // read file into Buffer
924 Status
= ShellReadFile (FileHandle
, &FileSize
, Buffer
);
925 ShellCloseFile(&FileHandle
);
927 if (EFI_ERROR (Status
)) {
928 StatusBarSetStatusString (L
"Read File Failed");
929 SHELL_FREE_NON_NULL (Buffer
);
930 return EFI_LOAD_ERROR
;
933 // nothing in this file
936 SHELL_FREE_NON_NULL (Buffer
);
938 // since has no head, so only can be an ASCII file
940 FileBuffer
.FileType
= FileTypeAscii
;
945 AsciiBuffer
= Buffer
;
949 // size < Unicode file header, so only can be ASCII file
951 FileBuffer
.FileType
= FileTypeAscii
;
956 if (*(UINT16
*) Buffer
== EFI_UNICODE_BYTE_ORDER_MARK
) {
958 // Unicode file's size should be even
960 if ((FileSize
% 2) != 0) {
961 StatusBarSetStatusString (L
"File Format Wrong");
962 SHELL_FREE_NON_NULL (Buffer
);
963 return EFI_LOAD_ERROR
;
968 FileBuffer
.FileType
= FileTypeUnicode
;
969 UnicodeBuffer
= Buffer
;
972 // pass this 0xff and 0xfe
977 FileBuffer
.FileType
= FileTypeAscii
;
980 // end of AsciiBuffer ==
984 // end of FileSize < 2
985 // all the check ends
986 // so now begin to set file name, free lines
988 if (StrCmp (FileName
, FileBuffer
.FileName
) != 0) {
989 FileBufferSetFileName (FileName
);
993 // free the old lines
998 // parse file content line by line
1000 for (LoopVar1
= 0; LoopVar1
< FileSize
; LoopVar1
++) {
1001 Type
= NewLineTypeUnknown
;
1003 for (LineSize
= LoopVar1
; LineSize
< FileSize
; LineSize
++) {
1004 if (FileBuffer
.FileType
== FileTypeAscii
) {
1005 if (AsciiBuffer
[LineSize
] == CHAR_CARRIAGE_RETURN
) {
1006 Type
= NewLineTypeCarriageReturn
;
1011 if (LineSize
< FileSize
- 1) {
1012 if (AsciiBuffer
[LineSize
+ 1] == CHAR_LINEFEED
) {
1013 Type
= NewLineTypeCarriageReturnLineFeed
;
1018 } else if (AsciiBuffer
[LineSize
] == CHAR_LINEFEED
) {
1019 Type
= NewLineTypeLineFeed
;
1024 if (LineSize
< FileSize
- 1) {
1025 if (AsciiBuffer
[LineSize
+ 1] == CHAR_CARRIAGE_RETURN
) {
1026 Type
= NewLineTypeLineFeedCarriageReturn
;
1033 if (UnicodeBuffer
[LineSize
] == CHAR_CARRIAGE_RETURN
) {
1034 Type
= NewLineTypeCarriageReturn
;
1039 if (LineSize
< FileSize
- 1) {
1040 if (UnicodeBuffer
[LineSize
+ 1] == CHAR_LINEFEED
) {
1041 Type
= NewLineTypeCarriageReturnLineFeed
;
1046 } else if (UnicodeBuffer
[LineSize
] == CHAR_LINEFEED
) {
1047 Type
= NewLineTypeLineFeed
;
1052 if (LineSize
< FileSize
- 1) {
1053 if (UnicodeBuffer
[LineSize
+ 1] == CHAR_CARRIAGE_RETURN
) {
1054 Type
= NewLineTypeLineFeedCarriageReturn
;
1066 // end of for LineSize
1068 // if the type is wrong, then exit
1070 if (Type
== NewLineTypeUnknown
) {
1072 // Now if Type is NewLineTypeUnknown, it should be file end
1074 Type
= NewLineTypeDefault
;
1077 LineSizeBackup
= LineSize
;
1080 // create a new line
1082 Line
= FileBufferCreateLine ();
1084 SHELL_FREE_NON_NULL (Buffer
);
1085 return EFI_OUT_OF_RESOURCES
;
1088 // calculate file length
1090 LineSize
-= LoopVar1
;
1093 // Unicode and one CHAR_NULL
1095 SHELL_FREE_NON_NULL (Line
->Buffer
);
1096 Line
->Buffer
= AllocateZeroPool (LineSize
* 2 + 2);
1098 if (Line
->Buffer
== NULL
) {
1099 RemoveEntryList (&Line
->Link
);
1100 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
];
1115 // LoopVar1 now points to where CHAR_CARRIAGE_RETURN or CHAR_LINEFEED;
1117 Line
->Buffer
[LineSize
] = 0;
1119 Line
->Size
= LineSize
;
1120 Line
->TotalSize
= LineSize
;
1123 if (Type
== NewLineTypeCarriageReturnLineFeed
|| Type
== NewLineTypeLineFeedCarriageReturn
) {
1128 // last character is a return, SO create a new line
1130 if (((Type
== NewLineTypeCarriageReturnLineFeed
|| Type
== NewLineTypeLineFeedCarriageReturn
) && LineSizeBackup
== FileSize
- 2) ||
1131 ((Type
== NewLineTypeLineFeed
|| Type
== NewLineTypeCarriageReturn
) && LineSizeBackup
== FileSize
- 1)
1133 Line
= FileBufferCreateLine ();
1135 SHELL_FREE_NON_NULL (Buffer
);
1136 return EFI_OUT_OF_RESOURCES
;
1146 SHELL_FREE_NON_NULL (Buffer
);
1150 // end of if CreateFile
1154 FileBuffer
.DisplayPosition
.Row
= 2;
1155 FileBuffer
.DisplayPosition
.Column
= 1;
1156 FileBuffer
.LowVisibleRange
.Row
= 1;
1157 FileBuffer
.LowVisibleRange
.Column
= 1;
1158 FileBuffer
.FilePosition
.Row
= 1;
1159 FileBuffer
.FilePosition
.Column
= 1;
1160 FileBuffer
.MousePosition
.Row
= 2;
1161 FileBuffer
.MousePosition
.Column
= 1;
1164 UnicodeBuffer
= CatSPrint (NULL
, L
"%d Lines Read", FileBuffer
.NumLines
);
1165 if (UnicodeBuffer
== NULL
) {
1166 return EFI_OUT_OF_RESOURCES
;
1169 StatusBarSetStatusString (UnicodeBuffer
);
1170 FreePool (UnicodeBuffer
);
1174 // check whether we have fs?: in filename
1177 FSMappingPtr = NULL;
1178 while (FileName[LoopVar1] != 0) {
1179 if (FileName[LoopVar1] == L':') {
1180 FSMappingPtr = &FileName[LoopVar1];
1187 if (FSMappingPtr == NULL) {
1188 CurDir = ShellGetCurrentDir (NULL);
1192 while (FileName[LoopVar1] != 0) {
1193 if (FileName[LoopVar1] == L':') {
1197 FSMapping[LoopVar2++] = FileName[LoopVar1];
1202 FSMapping[LoopVar2] = 0;
1203 CurDir = ShellGetCurrentDir (FSMapping);
1206 if (CurDir != NULL) {
1207 for (LoopVar1 = 0; LoopVar1 < StrLen (CurDir) && CurDir[LoopVar1] != ':'; LoopVar1++);
1209 CurDir[LoopVar1] = 0;
1210 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) ShellGetMap (CurDir);
1213 return EFI_LOAD_ERROR;
1216 Status = LibDevicePathToInterface (
1217 &gEfiSimpleFileSystemProtocolGuid,
1221 if (EFI_ERROR (Status)) {
1222 return EFI_LOAD_ERROR;
1225 Status = Vol->OpenVolume (Vol, &RootFs);
1226 if (EFI_ERROR (Status)) {
1227 return EFI_LOAD_ERROR;
1230 // Get volume information of file system
1232 Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + 100;
1233 VolumeInfo = (EFI_FILE_SYSTEM_INFO *) AllocateZeroPool (Size);
1234 Status = RootFs->GetInfo (RootFs, &gEfiFileSystemInfoGuid, &Size, VolumeInfo);
1235 if (EFI_ERROR (Status)) {
1236 RootFs->Close (RootFs);
1237 return EFI_LOAD_ERROR;
1240 if (VolumeInfo->ReadOnly) {
1241 StatusBarSetStatusString (L"WARNING: Volume Read Only");
1244 FreePool (VolumeInfo);
1245 RootFs->Close (RootFs);
1252 if (FileBuffer
.Lines
!= 0) {
1253 FileBuffer
.CurrentLine
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1256 // create a dummy line
1258 Line
= FileBufferCreateLine ();
1260 return EFI_OUT_OF_RESOURCES
;
1263 FileBuffer
.CurrentLine
= Line
;
1266 FileBuffer
.FileModified
= FALSE
;
1267 FileBufferNeedRefresh
= TRUE
;
1268 FileBufferOnlyLineNeedRefresh
= FALSE
;
1269 FileBufferMouseNeedRefresh
= TRUE
;
1276 According to FileBuffer.NewLineType & FileBuffer.FileType,
1277 get the return buffer and size.
1279 @param[in] Type The type of line.
1280 @param[out] Buffer The buffer to fill.
1281 @param[out] Size The amount of the buffer used on return.
1286 IN CONST EE_NEWLINE_TYPE Type
,
1294 // give new line buffer,
1295 // and will judge unicode or ascii
1300 // not legal new line type
1302 if (Type
!= NewLineTypeLineFeed
&& Type
!= NewLineTypeCarriageReturn
&& Type
!= NewLineTypeCarriageReturnLineFeed
&& Type
!= NewLineTypeLineFeedCarriageReturn
) {
1307 // use_cr: give 0x0d
1309 if (Type
== NewLineTypeCarriageReturn
) {
1310 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1319 *Size
= NewLineSize
;
1323 // use_lf: give 0x0a
1325 if (Type
== NewLineTypeLineFeed
) {
1326 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1335 *Size
= NewLineSize
;
1339 // use_crlf: give 0x0d 0x0a
1341 if (Type
== NewLineTypeCarriageReturnLineFeed
) {
1342 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1355 *Size
= NewLineSize
;
1359 // use_lfcr: give 0x0a 0x0d
1361 if (Type
== NewLineTypeLineFeedCarriageReturn
) {
1362 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1375 *Size
= NewLineSize
;
1382 Change a Unicode string to an ASCII string.
1384 @param[in] UStr The Unicode string.
1385 @param[in] Length The maximum size of AStr.
1386 @param[out] AStr ASCII string to pass out.
1388 @return The actuall length.
1393 IN CONST CHAR16
*UStr
,
1394 IN CONST UINTN Length
,
1401 // just buffer copy, not character copy
1403 for (Index
= 0; Index
< Length
; Index
++) {
1404 *AStr
++ = (CHAR8
) *UStr
++;
1411 Save lines in FileBuffer to disk
1413 @param[in] FileName The file name for writing.
1415 @retval EFI_SUCCESS Data was written.
1416 @retval EFI_LOAD_ERROR
1417 @retval EFI_OUT_OF_RESOURCES There were not enough resources to write the file.
1422 IN CONST CHAR16
*FileName
1425 SHELL_FILE_HANDLE FileHandle
;
1427 EFI_EDITOR_LINE
*Line
;
1433 CHAR8 NewLineBuffer
[4];
1436 EFI_FILE_INFO
*Info
;
1440 EE_NEWLINE_TYPE Type
;
1455 TotalSize
= 0x200000;
1462 // if is the old file
1464 if (FileBuffer
.FileName
!= NULL
&& StrCmp (FileName
, FileBuffer
.FileName
) == 0) {
1466 // file has not been modified
1468 if (!FileBuffer
.FileModified
) {
1473 // if file is read-only, set error
1475 if (FileBuffer
.ReadOnly
) {
1476 StatusBarSetStatusString (L
"Read Only File Can Not Be Saved");
1481 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
|EFI_FILE_MODE_WRITE
, 0);
1483 if (!EFI_ERROR (Status
)) {
1484 Info
= ShellGetFileInfo(FileHandle
);
1486 if (Info
!= NULL
&& Info
->Attribute
& EFI_FILE_DIRECTORY
) {
1487 StatusBarSetStatusString (L
"Directory Can Not Be Saved");
1488 ShellCloseFile(FileHandle
);
1490 return EFI_LOAD_ERROR
;
1494 Attribute
= Info
->Attribute
& ~EFI_FILE_READ_ONLY
;
1499 // if file exits, so delete it
1501 Status
= ShellDeleteFile (&FileHandle
);
1502 if (EFI_ERROR (Status
) || Status
== EFI_WARN_DELETE_FAILURE
) {
1503 StatusBarSetStatusString (L
"Write File Failed");
1504 return EFI_LOAD_ERROR
;
1508 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
|EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_CREATE
, Attribute
);
1510 if (EFI_ERROR (Status
)) {
1511 StatusBarSetStatusString (L
"Create File Failed");
1512 return EFI_LOAD_ERROR
;
1516 // if file is Unicode file, write Unicode header to it.
1518 if (FileBuffer
.FileType
== FileTypeUnicode
) {
1520 Status
= ShellWriteFile (FileHandle
, &Length
, (VOID
*)&gUnicodeFileTag
);
1521 if (EFI_ERROR (Status
)) {
1522 ShellDeleteFile (&FileHandle
);
1523 return EFI_LOAD_ERROR
;
1527 Cache
= AllocateZeroPool (TotalSize
);
1528 if (Cache
== NULL
) {
1529 ShellDeleteFile (&FileHandle
);
1530 return EFI_OUT_OF_RESOURCES
;
1534 // write all the lines back to disk
1537 Type
= NewLineTypeCarriageReturnLineFeed
;
1540 LeftSize
= TotalSize
;
1542 for (Link
= FileBuffer
.ListHead
->ForwardLink
; Link
!= FileBuffer
.ListHead
; Link
= Link
->ForwardLink
) {
1543 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1545 if (Line
->Type
!= NewLineTypeDefault
) {
1549 // newline character is at most 4 bytes ( two Unicode characters )
1552 if (Line
->Buffer
!= NULL
&& Line
->Size
!= 0) {
1553 if (FileBuffer
.FileType
== FileTypeAscii
) {
1554 Length
+= Line
->Size
;
1556 Length
+= (Line
->Size
* 2);
1559 // end if FileTypeAscii
1564 // no cache room left, so write cache to disk
1566 if (LeftSize
< Length
) {
1567 Size
= TotalSize
- LeftSize
;
1568 Status
= ShellWriteFile (FileHandle
, &Size
, Cache
);
1569 if (EFI_ERROR (Status
)) {
1570 ShellDeleteFile (&FileHandle
);
1572 return EFI_LOAD_ERROR
;
1575 LeftSize
= TotalSize
;
1578 if (Line
->Buffer
!= NULL
&& Line
->Size
!= 0) {
1579 if (FileBuffer
.FileType
== FileTypeAscii
) {
1580 UnicodeToAscii (Line
->Buffer
, Line
->Size
, Ptr
);
1581 Length
= Line
->Size
;
1583 Length
= (Line
->Size
* 2);
1584 CopyMem (Ptr
, (CHAR8
*) Line
->Buffer
, Length
);
1587 // end if FileTypeAscii
1594 // end of if Line -> Buffer != NULL && Line -> Size != 0
1596 // if not the last line , write return buffer to disk
1598 if (Link
->ForwardLink
!= FileBuffer
.ListHead
) {
1599 GetNewLine (Type
, NewLineBuffer
, &NewLineSize
);
1600 CopyMem (Ptr
, (CHAR8
*) NewLineBuffer
, NewLineSize
);
1603 LeftSize
-= NewLineSize
;
1609 if (TotalSize
!= LeftSize
) {
1610 Size
= TotalSize
- LeftSize
;
1611 Status
= ShellWriteFile (FileHandle
, &Size
, Cache
);
1612 if (EFI_ERROR (Status
)) {
1613 ShellDeleteFile (&FileHandle
);
1615 return EFI_LOAD_ERROR
;
1621 ShellCloseFile(&FileHandle
);
1623 FileBuffer
.FileModified
= FALSE
;
1626 // set status string
1628 Str
= CatSPrint (NULL
, L
"%d Lines Wrote", NumLines
);
1630 return EFI_OUT_OF_RESOURCES
;
1633 StatusBarSetStatusString (Str
);
1634 SHELL_FREE_NON_NULL (Str
);
1637 // now everything is ready , you can set the new file name to filebuffer
1639 if (FileName
!= NULL
&& FileBuffer
.FileName
!= NULL
&& StrCmp (FileName
, FileBuffer
.FileName
) != 0) {
1643 FileBufferSetFileName (FileName
);
1644 if (FileBuffer
.FileName
== NULL
) {
1645 ShellDeleteFile (&FileHandle
);
1646 return EFI_OUT_OF_RESOURCES
;
1650 FileBuffer
.ReadOnly
= FALSE
;
1655 Scroll cursor to left 1 character position.
1657 @retval EFI_SUCCESS The operation was successful.
1661 FileBufferScrollLeft (
1665 EFI_EDITOR_LINE
*Line
;
1669 Line
= FileBuffer
.CurrentLine
;
1671 FRow
= FileBuffer
.FilePosition
.Row
;
1672 FCol
= FileBuffer
.FilePosition
.Column
;
1675 // if already at start of this line, so move to the end of previous line
1679 // has previous line
1681 if (Line
->Link
.BackLink
!= FileBuffer
.ListHead
) {
1683 Line
= CR (Line
->Link
.BackLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1684 FCol
= Line
->Size
+ 1;
1690 // if not at start of this line, just move to previous column
1695 FileBufferMovePosition (FRow
, FCol
);
1701 Delete a char in line
1703 @param[in, out] Line The line to delete in.
1704 @param[in] Pos Position to delete the char at ( start from 0 ).
1709 IN OUT EFI_EDITOR_LINE
*Line
,
1716 // move the latter characters front
1718 for (Index
= Pos
- 1; Index
< Line
->Size
; Index
++) {
1719 Line
->Buffer
[Index
] = Line
->Buffer
[Index
+ 1];
1726 Concatenate Src into Dest.
1728 @param[in, out] Dest Destination string
1729 @param[in] Src Src String.
1734 IN OUT EFI_EDITOR_LINE
*Dest
,
1735 IN EFI_EDITOR_LINE
*Src
1743 Dest
->Buffer
[Size
] = 0;
1746 // concatenate the two strings
1748 Str
= CatSPrint (NULL
, L
"%s%s", Dest
->Buffer
, Src
->Buffer
);
1750 Dest
->Buffer
= NULL
;
1754 Dest
->Size
= Size
+ Src
->Size
;
1755 Dest
->TotalSize
= Dest
->Size
;
1757 FreePool (Dest
->Buffer
);
1758 FreePool (Src
->Buffer
);
1761 // put str to dest->buffer
1767 Delete the previous character.
1769 @retval EFI_SUCCESS The delete was successful.
1770 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1774 FileBufferDoBackspace (
1778 EFI_EDITOR_LINE
*Line
;
1779 EFI_EDITOR_LINE
*End
;
1783 FileColumn
= FileBuffer
.FilePosition
.Column
;
1785 Line
= FileBuffer
.CurrentLine
;
1790 if (FileColumn
== 1) {
1794 if (FileBuffer
.FilePosition
.Row
== 1) {
1798 FileBufferScrollLeft ();
1800 Line
= FileBuffer
.CurrentLine
;
1801 Link
= Line
->Link
.ForwardLink
;
1802 End
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1805 // concatenate this line with previous line
1807 LineCat (Line
, End
);
1808 if (Line
->Buffer
== NULL
) {
1809 return EFI_OUT_OF_RESOURCES
;
1812 // remove End from line list
1814 RemoveEntryList (&End
->Link
);
1817 FileBuffer
.NumLines
--;
1819 FileBufferNeedRefresh
= TRUE
;
1820 FileBufferOnlyLineNeedRefresh
= FALSE
;
1824 // just delete the previous character
1826 LineDeleteAt (Line
, FileColumn
- 1);
1827 FileBufferScrollLeft ();
1828 FileBufferOnlyLineNeedRefresh
= TRUE
;
1831 if (!FileBuffer
.FileModified
) {
1832 FileBuffer
.FileModified
= TRUE
;
1839 Add a return into line at current position.
1841 @retval EFI_SUCCESS The insetrion of the character was successful.
1842 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1846 FileBufferDoReturn (
1850 EFI_EDITOR_LINE
*Line
;
1851 EFI_EDITOR_LINE
*NewLine
;
1858 FileBufferNeedRefresh
= TRUE
;
1859 FileBufferOnlyLineNeedRefresh
= FALSE
;
1861 Line
= FileBuffer
.CurrentLine
;
1863 FileColumn
= FileBuffer
.FilePosition
.Column
;
1865 NewLine
= AllocateZeroPool (sizeof (EFI_EDITOR_LINE
));
1866 if (NewLine
== NULL
) {
1867 return EFI_OUT_OF_RESOURCES
;
1870 NewLine
->Signature
= LINE_LIST_SIGNATURE
;
1871 NewLine
->Size
= Line
->Size
- FileColumn
+ 1;
1872 NewLine
->TotalSize
= NewLine
->Size
;
1873 NewLine
->Buffer
= CatSPrint (NULL
, L
"\0");
1874 if (NewLine
->Buffer
== NULL
) {
1875 return EFI_OUT_OF_RESOURCES
;
1878 NewLine
->Type
= NewLineTypeDefault
;
1880 if (NewLine
->Size
> 0) {
1882 // UNICODE + CHAR_NULL
1884 Buffer
= AllocateZeroPool (2 * (NewLine
->Size
+ 1));
1885 if (Buffer
== NULL
) {
1886 FreePool (NewLine
->Buffer
);
1888 return EFI_OUT_OF_RESOURCES
;
1891 FreePool (NewLine
->Buffer
);
1893 NewLine
->Buffer
= Buffer
;
1895 for (Index
= 0; Index
< NewLine
->Size
; Index
++) {
1896 NewLine
->Buffer
[Index
] = Line
->Buffer
[Index
+ FileColumn
- 1];
1899 NewLine
->Buffer
[NewLine
->Size
] = CHAR_NULL
;
1901 Line
->Buffer
[FileColumn
- 1] = CHAR_NULL
;
1902 Line
->Size
= FileColumn
- 1;
1905 // increase NumLines
1907 FileBuffer
.NumLines
++;
1910 // insert it into the correct position of line list
1912 NewLine
->Link
.BackLink
= &(Line
->Link
);
1913 NewLine
->Link
.ForwardLink
= Line
->Link
.ForwardLink
;
1914 Line
->Link
.ForwardLink
->BackLink
= &(NewLine
->Link
);
1915 Line
->Link
.ForwardLink
= &(NewLine
->Link
);
1918 // move cursor to the start of next line
1920 Row
= FileBuffer
.FilePosition
.Row
+ 1;
1923 FileBufferMovePosition (Row
, Col
);
1926 // set file is modified
1928 if (!FileBuffer
.FileModified
) {
1929 FileBuffer
.FileModified
= TRUE
;
1936 Delete current character from current line. This is the effect caused
1943 FileBufferDoDelete (
1947 EFI_EDITOR_LINE
*Line
;
1948 EFI_EDITOR_LINE
*Next
;
1952 Line
= FileBuffer
.CurrentLine
;
1953 FileColumn
= FileBuffer
.FilePosition
.Column
;
1958 if (FileColumn
>= Line
->Size
+ 1) {
1962 if (Line
->Link
.ForwardLink
== FileBuffer
.ListHead
) {
1966 // since last character,
1967 // so will add the next line to this line
1969 Link
= Line
->Link
.ForwardLink
;
1970 Next
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1971 LineCat (Line
, Next
);
1972 if (Line
->Buffer
== NULL
) {
1973 return EFI_OUT_OF_RESOURCES
;
1976 RemoveEntryList (&Next
->Link
);
1979 FileBuffer
.NumLines
--;
1981 FileBufferNeedRefresh
= TRUE
;
1982 FileBufferOnlyLineNeedRefresh
= FALSE
;
1986 // just delete current character
1988 LineDeleteAt (Line
, FileColumn
);
1989 FileBufferOnlyLineNeedRefresh
= TRUE
;
1992 if (!FileBuffer
.FileModified
) {
1993 FileBuffer
.FileModified
= TRUE
;
2000 Scroll cursor to right 1 character.
2002 @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 ).
2061 IN EFI_EDITOR_LINE
*Line
,
2068 CHAR16
*TempStringPtr
;
2071 Index
= (StrSize
) * 2;
2076 // do not have free space
2078 if (Line
->TotalSize
<= Line
->Size
) {
2079 Str
= ReallocatePool (Index
, Index
+ 16, Str
);
2084 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];
2094 // insert char into it.
2096 TempStringPtr
[Index
] = Char
;
2105 Add a character to the current line.
2107 @param[in] Char The Character to input.
2109 @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
;
2139 // move cursor to right
2141 FileBufferScrollRight ();
2143 if (!FileBuffer
.FileModified
) {
2144 FileBuffer
.FileModified
= TRUE
;
2151 Handles inputs from characters (ASCII key + Backspace + return)
2153 @param[in] Char The input character.
2155 @retval EFI_SUCCESS The operation was successful.
2156 @retval EFI_LOAD_ERROR There was an error.
2157 @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
);
2206 Scroll cursor to the next line.
2208 @retval EFI_SUCCESS The operation was successful.
2212 FileBufferScrollDown (
2216 EFI_EDITOR_LINE
*Line
;
2220 Line
= FileBuffer
.CurrentLine
;
2221 if (Line
->Buffer
== NULL
) {
2225 FRow
= FileBuffer
.FilePosition
.Row
;
2226 FCol
= FileBuffer
.FilePosition
.Column
;
2231 if (Line
->Link
.ForwardLink
!= FileBuffer
.ListHead
) {
2233 Line
= CR (Line
->Link
.ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2236 // if the next line is not that long, so move to end of next line
2238 if (FCol
> Line
->Size
) {
2239 FCol
= Line
->Size
+ 1;
2246 FileBufferMovePosition (FRow
, FCol
);
2252 Scroll the cursor to previous line.
2254 @retval EFI_SUCCESS The operation was successful.
2258 FileBufferScrollUp (
2262 EFI_EDITOR_LINE
*Line
;
2266 Line
= FileBuffer
.CurrentLine
;
2268 FRow
= FileBuffer
.FilePosition
.Row
;
2269 FCol
= FileBuffer
.FilePosition
.Column
;
2272 // has previous line
2274 if (Line
->Link
.BackLink
!= FileBuffer
.ListHead
) {
2276 Line
= CR (Line
->Link
.BackLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2279 // if previous line is not that long, so move to the end of previous line
2281 if (FCol
> Line
->Size
) {
2282 FCol
= Line
->Size
+ 1;
2289 FileBufferMovePosition (FRow
, FCol
);
2295 Scroll cursor to next page.
2297 @retval EFI_SUCCESS The operation wa successful.
2301 FileBufferPageDown (
2305 EFI_EDITOR_LINE
*Line
;
2310 Line
= FileBuffer
.CurrentLine
;
2312 FRow
= FileBuffer
.FilePosition
.Row
;
2313 FCol
= FileBuffer
.FilePosition
.Column
;
2318 if (FileBuffer
.NumLines
>= FRow
+ (MainEditor
.ScreenSize
.Row
- 2)) {
2319 Gap
= (MainEditor
.ScreenSize
.Row
- 2);
2322 // MOVE CURSOR TO LAST LINE
2324 Gap
= FileBuffer
.NumLines
- FRow
;
2329 Line
= MoveLine (Gap
);
2332 // if that line, is not that long, so move to the end of that line
2334 if (Line
!= NULL
&& FCol
> Line
->Size
) {
2335 FCol
= Line
->Size
+ 1;
2340 FileBufferMovePosition (FRow
, FCol
);
2346 Scroll cursor to previous screen.
2348 @retval EFI_SUCCESS The operation was successful.
2356 EFI_EDITOR_LINE
*Line
;
2362 Line
= FileBuffer
.CurrentLine
;
2364 FRow
= FileBuffer
.FilePosition
.Row
;
2365 FCol
= FileBuffer
.FilePosition
.Column
;
2368 // has previous page
2370 if (FRow
> (MainEditor
.ScreenSize
.Row
- 2)) {
2371 Gap
= (MainEditor
.ScreenSize
.Row
- 2);
2374 // the first line of file will displayed on the first line of screen
2385 Line
= MoveLine (Retreat
);
2388 // if that line is not that long, so move to the end of that line
2390 if (Line
!= NULL
&& FCol
> Line
->Size
) {
2391 FCol
= Line
->Size
+ 1;
2396 FileBufferMovePosition (FRow
, FCol
);
2402 Scroll cursor to end of the current line.
2404 @retval EFI_SUCCESS The operation was successful.
2412 EFI_EDITOR_LINE
*Line
;
2416 Line
= FileBuffer
.CurrentLine
;
2418 FRow
= FileBuffer
.FilePosition
.Row
;
2421 // goto the last column of the line
2423 FCol
= Line
->Size
+ 1;
2425 FileBufferMovePosition (FRow
, FCol
);
2431 Dispatch input to different handler
2432 @param[in] Key The input key. One of:
2436 Direction key: up/down/left/right/pgup/pgdn
2440 @retval EFI_SUCCESS The dispatch was done successfully.
2441 @retval EFI_LOAD_ERROR The dispatch was not successful.
2442 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2446 FileBufferHandleInput (
2447 IN CONST EFI_INPUT_KEY
*Key
2452 Status
= EFI_SUCCESS
;
2454 switch (Key
->ScanCode
) {
2456 // ordinary key input
2459 if (!FileBuffer
.ReadOnly
) {
2460 Status
= FileBufferDoCharInput (Key
->UnicodeChar
);
2462 Status
= StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2471 Status
= FileBufferScrollUp ();
2478 Status
= FileBufferScrollDown ();
2485 Status
= FileBufferScrollRight ();
2492 Status
= FileBufferScrollLeft ();
2499 Status
= FileBufferPageUp ();
2505 case SCAN_PAGE_DOWN
:
2506 Status
= FileBufferPageDown ();
2513 if (!FileBuffer
.ReadOnly
) {
2514 Status
= FileBufferDoDelete ();
2516 Status
= StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2525 FileBufferMovePosition (FileBuffer
.FilePosition
.Row
, 1);
2526 Status
= EFI_SUCCESS
;
2533 Status
= FileBufferEnd ();
2540 FileBuffer
.ModeInsert
= (BOOLEAN
)!FileBuffer
.ModeInsert
;
2541 Status
= EFI_SUCCESS
;
2545 Status
= StatusBarSetStatusString (L
"Unknown Command");
2553 Check user specified FileRow is above current screen.
2555 @param[in] FileRow The row of file position ( start from 1 ).
2557 @retval TRUE It is above the current screen.
2558 @retval FALSE It is not above the current screen.
2562 AboveCurrentScreen (
2567 // if is to the above of the screen
2569 if (FileRow
< FileBuffer
.LowVisibleRange
.Row
) {
2577 Check user specified FileRow is under current screen.
2579 @param[in] FileRow The row of file position ( start from 1 ).
2581 @retval TRUE It is under the current screen.
2582 @retval FALSE It is not under the current screen.
2586 UnderCurrentScreen (
2591 // if is to the under of the screen
2593 if (FileRow
> FileBuffer
.LowVisibleRange
.Row
+ (MainEditor
.ScreenSize
.Row
- 2) - 1) {
2601 Check user specified FileCol is left to current screen.
2603 @param[in] FileCol The column of file position ( start from 1 ).
2605 @retval TRUE It is to the left.
2606 @retval FALSE It is not to the left.
2615 // if is to the left of the screen
2617 if (FileCol
< FileBuffer
.LowVisibleRange
.Column
) {
2625 Check user specified FileCol is right to current screen.
2627 @param[in] FileCol The column of file position ( start from 1 ).
2629 @retval TRUE It is to the right.
2630 @retval FALSE It is not to the right.
2634 RightCurrentScreen (
2639 // if is to the right of the screen
2641 if (FileCol
> FileBuffer
.LowVisibleRange
.Column
+ MainEditor
.ScreenSize
.Column
- 1) {
2649 Advance/Retreat lines and set CurrentLine in FileBuffer to it
2651 @param[in] Count The line number to advance/retreat
2655 @retval NULL An error occured.
2656 @return The line after advance/retreat.
2664 EFI_EDITOR_LINE
*Line
;
2668 AbsCount
= (UINTN
)ABS(Count
);
2669 Line
= InternalEditorMiscLineRetreat (AbsCount
,MainEditor
.FileBuffer
->CurrentLine
,MainEditor
.FileBuffer
->ListHead
);
2671 Line
= InternalEditorMiscLineAdvance ((UINTN
)Count
,MainEditor
.FileBuffer
->CurrentLine
,MainEditor
.FileBuffer
->ListHead
);
2678 MainEditor
.FileBuffer
->CurrentLine
= Line
;
2684 According to cursor's file position, adjust screen display
2686 @param[in] NewFilePosRow The row of file position ( start from 1 ).
2687 @param[in] NewFilePosCol The column of file position ( start from 1 ).
2691 FileBufferMovePosition (
2692 IN CONST UINTN NewFilePosRow
,
2693 IN CONST UINTN NewFilePosCol
2705 // CALCULATE gap between current file position and new file position
2707 RowGap
= NewFilePosRow
- FileBuffer
.FilePosition
.Row
;
2708 ColGap
= NewFilePosCol
- FileBuffer
.FilePosition
.Column
;
2710 Under
= UnderCurrentScreen (NewFilePosRow
);
2711 Above
= AboveCurrentScreen (NewFilePosRow
);
2713 // if is below current screen
2717 // display row will be unchanged
2719 FileBuffer
.FilePosition
.Row
= NewFilePosRow
;
2723 // has enough above line, so display row unchanged
2724 // not has enough above lines, so the first line is at the
2725 // first display line
2727 if (NewFilePosRow
< (FileBuffer
.DisplayPosition
.Row
- 1)) {
2728 FileBuffer
.DisplayPosition
.Row
= NewFilePosRow
+ 1;
2731 FileBuffer
.FilePosition
.Row
= NewFilePosRow
;
2734 // in current screen
2736 FileBuffer
.FilePosition
.Row
= NewFilePosRow
;
2738 Abs
= (UINTN
)ABS(RowGap
);
2739 FileBuffer
.DisplayPosition
.Row
-= Abs
;
2741 FileBuffer
.DisplayPosition
.Row
+= RowGap
;
2746 FileBuffer
.LowVisibleRange
.Row
= FileBuffer
.FilePosition
.Row
- (FileBuffer
.DisplayPosition
.Row
- 2);
2748 Right
= RightCurrentScreen (NewFilePosCol
);
2749 Left
= LeftCurrentScreen (NewFilePosCol
);
2752 // if right to current screen
2756 // display column will be changed to end
2758 FileBuffer
.DisplayPosition
.Column
= MainEditor
.ScreenSize
.Column
;
2759 FileBuffer
.FilePosition
.Column
= NewFilePosCol
;
2763 // has enough left characters , so display row unchanged
2764 // not has enough left characters,
2765 // so the first character is at the first display column
2767 if (NewFilePosCol
< (FileBuffer
.DisplayPosition
.Column
)) {
2768 FileBuffer
.DisplayPosition
.Column
= NewFilePosCol
;
2771 FileBuffer
.FilePosition
.Column
= NewFilePosCol
;
2774 // in current screen
2776 FileBuffer
.FilePosition
.Column
= NewFilePosCol
;
2778 Abs
= (UINTN
)(-ColGap
);
2779 FileBuffer
.DisplayPosition
.Column
-= Abs
;
2781 FileBuffer
.DisplayPosition
.Column
+= ColGap
;
2786 FileBuffer
.LowVisibleRange
.Column
= FileBuffer
.FilePosition
.Column
- (FileBuffer
.DisplayPosition
.Column
- 1);
2789 // let CurrentLine point to correct line;
2791 FileBuffer
.CurrentLine
= MoveCurrentLine (RowGap
);
2796 Cut current line out and return a pointer to it.
2798 @param[out] CutLine Upon a successful return pointer to the pointer to
2799 the allocated cut line.
2801 @retval EFI_SUCCESS The cut was successful.
2802 @retval EFI_NOT_FOUND There was no selection to cut.
2803 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2808 OUT EFI_EDITOR_LINE
**CutLine
2811 EFI_EDITOR_LINE
*Line
;
2812 EFI_EDITOR_LINE
*NewLine
;
2816 if (FileBuffer
.ReadOnly
) {
2817 StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2821 Line
= FileBuffer
.CurrentLine
;
2824 // if is the last dummy line, SO CAN not cut
2826 if (StrCmp (Line
->Buffer
, L
"\0") == 0 && Line
->Link
.ForwardLink
== FileBuffer
.ListHead
2832 // LAST LINE AND NOTHING ON THIS LINE, SO CUT NOTHING
2834 StatusBarSetStatusString (L
"Nothing to Cut");
2835 return EFI_NOT_FOUND
;
2838 // if is the last line, so create a dummy line
2840 if (Line
->Link
.ForwardLink
== FileBuffer
.ListHead
) {
2843 // create a new line
2845 NewLine
= FileBufferCreateLine ();
2846 if (NewLine
== NULL
) {
2847 return EFI_OUT_OF_RESOURCES
;
2851 FileBuffer
.NumLines
--;
2852 Row
= FileBuffer
.FilePosition
.Row
;
2857 FileBuffer
.CurrentLine
= CR (
2858 FileBuffer
.CurrentLine
->Link
.ForwardLink
,
2864 RemoveEntryList (&Line
->Link
);
2866 FileBuffer
.Lines
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2868 FileBufferMovePosition (Row
, Col
);
2870 FileBuffer
.FileModified
= TRUE
;
2871 FileBufferNeedRefresh
= TRUE
;
2872 FileBufferOnlyLineNeedRefresh
= FALSE
;
2880 Paste a line into line list.
2882 @retval EFI_SUCCESS The paste was successful.
2883 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2887 FileBufferPasteLine (
2891 EFI_EDITOR_LINE
*Line
;
2892 EFI_EDITOR_LINE
*NewLine
;
2897 // if nothing is on clip board
2900 if (MainEditor
.CutLine
== NULL
) {
2904 // read only file can not be pasted on
2906 if (FileBuffer
.ReadOnly
) {
2907 StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2911 NewLine
= LineDup (MainEditor
.CutLine
);
2912 if (NewLine
== NULL
) {
2913 return EFI_OUT_OF_RESOURCES
;
2916 // insert it above current line
2918 Line
= FileBuffer
.CurrentLine
;
2919 NewLine
->Link
.BackLink
= Line
->Link
.BackLink
;
2920 NewLine
->Link
.ForwardLink
= &Line
->Link
;
2922 Line
->Link
.BackLink
->ForwardLink
= &NewLine
->Link
;
2923 Line
->Link
.BackLink
= &NewLine
->Link
;
2925 FileBuffer
.NumLines
++;
2926 FileBuffer
.CurrentLine
= NewLine
;
2928 FileBuffer
.Lines
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2934 Row
= FileBuffer
.FilePosition
.Row
;
2936 FileBufferMovePosition (Row
, Col
);
2939 // after paste, set some value so that refresh knows to do something
2941 FileBuffer
.FileModified
= TRUE
;
2942 FileBufferNeedRefresh
= TRUE
;
2943 FileBufferOnlyLineNeedRefresh
= FALSE
;
2949 Search string from current position on in file
2951 @param[in] Str The search string.
2952 @param[in] Offset The offset from current position.
2954 @retval EFI_SUCCESS The operation was successful.
2955 @retval EFI_NOT_FOUND The string Str was not found.
2960 IN CONST CHAR16
*Str
,
2961 IN CONST UINTN Offset
2968 EFI_EDITOR_LINE
*Line
;
2977 // search if in current line
2979 Current
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1 + Offset
;
2981 if (Current
>= (FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.CurrentLine
->Size
)) {
2985 Current
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.CurrentLine
->Size
;
2990 CharPos
= StrStr (Current
, Str
);
2991 if (CharPos
!= NULL
) {
2992 Position
= CharPos
- Current
+ 1;
3000 Column
= (Position
- 1) + FileBuffer
.FilePosition
.Column
+ Offset
;
3001 Row
= FileBuffer
.FilePosition
.Row
;
3004 // not found so find through next lines
3006 Link
= FileBuffer
.CurrentLine
->Link
.ForwardLink
;
3008 Row
= FileBuffer
.FilePosition
.Row
+ 1;
3009 while (Link
!= FileBuffer
.ListHead
) {
3010 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
3011 // Position = StrStr (Line->Buffer, Str);
3012 CharPos
= StrStr (Line
->Buffer
, Str
);
3013 if (CharPos
!= NULL
) {
3014 Position
= CharPos
- Line
->Buffer
+ 1;
3027 Link
= Link
->ForwardLink
;
3030 if (Link
== FileBuffer
.ListHead
) {
3038 return EFI_NOT_FOUND
;
3041 FileBufferMovePosition (Row
, Column
);
3044 // call refresh to fresh edit area,
3045 // because the outer may loop to find multiply occurrence of this string
3047 FileBufferRefresh ();
3053 Replace SearchLen characters from current position on with Replace.
3055 This will modify the current buffer at the current position.
3057 @param[in] Replace The string to replace.
3058 @param[in] SearchLen Search string's length.
3060 @retval EFI_SUCCESS The operation was successful.
3061 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3066 IN CONST CHAR16
*Replace
,
3067 IN CONST UINTN SearchLen
3077 ReplaceLen
= StrLen (Replace
);
3079 OldSize
= FileBuffer
.CurrentLine
->Size
+ 1;
3081 // include CHAR_NULL
3083 NewSize
= OldSize
+ (ReplaceLen
- SearchLen
);
3085 if (ReplaceLen
> SearchLen
) {
3087 // do not have the enough space
3089 if (FileBuffer
.CurrentLine
->TotalSize
+ 1 <= NewSize
) {
3090 FileBuffer
.CurrentLine
->Buffer
= ReallocatePool (
3093 FileBuffer
.CurrentLine
->Buffer
3095 FileBuffer
.CurrentLine
->TotalSize
= NewSize
- 1;
3098 if (FileBuffer
.CurrentLine
->Buffer
== NULL
) {
3099 return EFI_OUT_OF_RESOURCES
;
3102 // the end CHAR_NULL character;
3104 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ (NewSize
- 1);
3105 Gap
= ReplaceLen
- SearchLen
;
3108 // keep the latter part
3110 for (Index
= 0; Index
< (FileBuffer
.CurrentLine
->Size
- FileBuffer
.FilePosition
.Column
- SearchLen
+ 2); Index
++) {
3111 *Buffer
= *(Buffer
- Gap
);
3115 // set replace into it
3117 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1;
3118 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3119 Buffer
[Index
] = Replace
[Index
];
3123 if (ReplaceLen
< SearchLen
) {
3124 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1;
3126 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3127 Buffer
[Index
] = Replace
[Index
];
3130 Buffer
+= ReplaceLen
;
3131 Gap
= SearchLen
- ReplaceLen
;
3134 // set replace into it
3136 for (Index
= 0; Index
< (FileBuffer
.CurrentLine
->Size
- FileBuffer
.FilePosition
.Column
- ReplaceLen
+ 2); Index
++) {
3137 *Buffer
= *(Buffer
+ Gap
);
3142 if (ReplaceLen
== SearchLen
) {
3143 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1;
3144 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3145 Buffer
[Index
] = Replace
[Index
];
3149 FileBuffer
.CurrentLine
->Size
+= (ReplaceLen
- SearchLen
);
3151 FileBufferOnlyLineNeedRefresh
= TRUE
;
3153 FileBuffer
.FileModified
= TRUE
;
3155 MainTitleBarRefresh (MainEditor
.FileBuffer
->FileName
, MainEditor
.FileBuffer
->FileType
, MainEditor
.FileBuffer
->ReadOnly
, MainEditor
.FileBuffer
->FileModified
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
, 0, 0);
3156 FileBufferRestorePosition ();
3157 FileBufferRefresh ();
3163 Move the mouse cursor position.
3165 @param[in] TextX The new x-coordinate.
3166 @param[in] TextY The new y-coordinate.
3170 FileBufferAdjustMousePosition (
3171 IN CONST INT32 TextX
,
3172 IN CONST INT32 TextY
3181 // TextX and TextY is mouse movement data returned by mouse driver
3182 // This function will change it to MousePosition
3185 // get absolute value
3191 CoordinateX
= FileBuffer
.MousePosition
.Column
;
3192 CoordinateY
= FileBuffer
.MousePosition
.Row
;
3195 CoordinateX
+= TextX
;
3197 if (CoordinateX
>= AbsX
) {
3198 CoordinateX
-= AbsX
;
3205 CoordinateY
+= TextY
;
3207 if (CoordinateY
>= AbsY
) {
3208 CoordinateY
-= AbsY
;
3214 // check whether new mouse column position is beyond screen
3215 // if not, adjust it
3217 if (CoordinateX
>= 1 && CoordinateX
<= MainEditor
.ScreenSize
.Column
) {
3218 FileBuffer
.MousePosition
.Column
= CoordinateX
;
3219 } else if (CoordinateX
< 1) {
3220 FileBuffer
.MousePosition
.Column
= 1;
3221 } else if (CoordinateX
> MainEditor
.ScreenSize
.Column
) {
3222 FileBuffer
.MousePosition
.Column
= MainEditor
.ScreenSize
.Column
;
3225 // check whether new mouse row position is beyond screen
3226 // if not, adjust it
3228 if (CoordinateY
>= 2 && CoordinateY
<= (MainEditor
.ScreenSize
.Row
- 1)) {
3229 FileBuffer
.MousePosition
.Row
= CoordinateY
;
3230 } else if (CoordinateY
< 2) {
3231 FileBuffer
.MousePosition
.Row
= 2;
3232 } else if (CoordinateY
> (MainEditor
.ScreenSize
.Row
- 1)) {
3233 FileBuffer
.MousePosition
.Row
= (MainEditor
.ScreenSize
.Row
- 1);
3239 Search and replace operation.
3241 @param[in] SearchStr The string to search for.
3242 @param[in] ReplaceStr The string to replace with.
3243 @param[in] Offset The column to start at.
3247 FileBufferReplaceAll (
3248 IN CHAR16
*SearchStr
,
3249 IN CHAR16
*ReplaceStr
,
3262 EFI_EDITOR_LINE
*Line
;
3266 SearchLen
= StrLen (SearchStr
);
3267 ReplaceLen
= StrLen (ReplaceStr
);
3269 Column
= FileBuffer
.FilePosition
.Column
+ Offset
- 1;
3271 if (Column
> FileBuffer
.CurrentLine
->Size
) {
3272 Column
= FileBuffer
.CurrentLine
->Size
;
3275 Link
= &(FileBuffer
.CurrentLine
->Link
);
3277 while (Link
!= FileBuffer
.ListHead
) {
3278 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
3279 CharPos
= StrStr (Line
->Buffer
+ Column
, SearchStr
);
3280 if (CharPos
!= NULL
) {
3281 Position
= CharPos
- Line
->Buffer
;// + Column;
3285 if (ReplaceLen
> SearchLen
) {
3286 OldSize
= Line
->Size
+ 1;
3288 // include CHAR_NULL
3290 NewSize
= OldSize
+ (ReplaceLen
- SearchLen
);
3293 // do not have the enough space
3295 if (Line
->TotalSize
+ 1 <= NewSize
) {
3296 Line
->Buffer
= ReallocatePool (
3301 Line
->TotalSize
= NewSize
- 1;
3304 if (Line
->Buffer
== NULL
) {
3305 return EFI_OUT_OF_RESOURCES
;
3308 // the end CHAR_NULL character;
3310 Buffer
= Line
->Buffer
+ (NewSize
- 1);
3311 Gap
= ReplaceLen
- SearchLen
;
3314 // keep the latter part
3316 for (Index
= 0; Index
< (Line
->Size
- Position
- SearchLen
+ 1); Index
++) {
3317 *Buffer
= *(Buffer
- Gap
);
3321 } else if (ReplaceLen
< SearchLen
){
3322 Buffer
= Line
->Buffer
+ Position
+ ReplaceLen
;
3323 Gap
= SearchLen
- ReplaceLen
;
3325 for (Index
= 0; Index
< (Line
->Size
- Position
- ReplaceLen
+ 1); Index
++) {
3326 *Buffer
= *(Buffer
+ Gap
);
3330 ASSERT(ReplaceLen
== SearchLen
);
3333 // set replace into it
3335 Buffer
= Line
->Buffer
+ Position
;
3336 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3337 Buffer
[Index
] = ReplaceStr
[Index
];
3340 Line
->Size
+= (ReplaceLen
- SearchLen
);
3341 Column
+= ReplaceLen
;
3347 Link
= Link
->ForwardLink
;
3351 // call refresh to fresh edit area
3353 FileBuffer
.FileModified
= TRUE
;
3354 FileBufferNeedRefresh
= TRUE
;
3355 FileBufferRefresh ();
3361 Set the modified state to TRUE.
3365 FileBufferSetModified (
3369 FileBuffer
.FileModified
= TRUE
;