2 Implements filebuffer interface functions.
4 Copyright (c) 2005 - 2012, Intel Corporation. All rights reserved. <BR>
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include "TextEditor.h"
16 #include <Guid/FileSystemInfo.h>
17 #include <Library/FileHandleLib.h>
19 EFI_EDITOR_FILE_BUFFER FileBuffer
;
20 EFI_EDITOR_FILE_BUFFER FileBufferBackupVar
;
23 // for basic initialization of FileBuffer
25 EFI_EDITOR_FILE_BUFFER FileBufferConst
= {
54 // the whole edit area needs to be refreshed
56 BOOLEAN FileBufferNeedRefresh
;
59 // only the current line in edit area needs to be refresh
61 BOOLEAN FileBufferOnlyLineNeedRefresh
;
63 BOOLEAN FileBufferMouseNeedRefresh
;
65 extern BOOLEAN EditorMouseAction
;
68 Initialization function for FileBuffer.
70 @param EFI_SUCCESS The initialization was successful.
71 @param EFI_LOAD_ERROR A default name could not be created.
72 @param EFI_OUT_OF_RESOURCES A memory allocation failed.
81 // basically initialize the FileBuffer
83 CopyMem (&FileBuffer
, &FileBufferConst
, sizeof (EFI_EDITOR_FILE_BUFFER
));
84 CopyMem (&FileBufferBackupVar
, &FileBufferConst
, sizeof (EFI_EDITOR_FILE_BUFFER
));
87 // set default FileName
89 FileBuffer
.FileName
= EditGetDefaultFileName (L
"txt");
90 if (FileBuffer
.FileName
== NULL
) {
91 return EFI_LOAD_ERROR
;
94 FileBuffer
.ListHead
= AllocateZeroPool (sizeof (LIST_ENTRY
));
95 if (FileBuffer
.ListHead
== NULL
) {
96 return EFI_OUT_OF_RESOURCES
;
99 InitializeListHead (FileBuffer
.ListHead
);
101 FileBuffer
.DisplayPosition
.Row
= 2;
102 FileBuffer
.DisplayPosition
.Column
= 1;
103 FileBuffer
.LowVisibleRange
.Row
= 2;
104 FileBuffer
.LowVisibleRange
.Column
= 1;
106 FileBufferNeedRefresh
= FALSE
;
107 FileBufferMouseNeedRefresh
= FALSE
;
108 FileBufferOnlyLineNeedRefresh
= FALSE
;
114 Backup function for FileBuffer. Only backup the following items:
115 Mouse/Cursor position
116 File Name, Type, ReadOnly, Modified
119 This is for making the file buffer refresh as few as possible.
121 @retval EFI_SUCCESS The backup operation was successful.
129 FileBufferBackupVar
.MousePosition
= FileBuffer
.MousePosition
;
131 SHELL_FREE_NON_NULL (FileBufferBackupVar
.FileName
);
132 FileBufferBackupVar
.FileName
= NULL
;
133 FileBufferBackupVar
.FileName
= StrnCatGrow (&FileBufferBackupVar
.FileName
, NULL
, FileBuffer
.FileName
, 0);
135 FileBufferBackupVar
.ModeInsert
= FileBuffer
.ModeInsert
;
136 FileBufferBackupVar
.FileType
= FileBuffer
.FileType
;
138 FileBufferBackupVar
.FilePosition
= FileBuffer
.FilePosition
;
139 FileBufferBackupVar
.LowVisibleRange
= FileBuffer
.LowVisibleRange
;
141 FileBufferBackupVar
.FileModified
= FileBuffer
.FileModified
;
142 FileBufferBackupVar
.ReadOnly
= FileBuffer
.ReadOnly
;
148 Advance to the next Count lines
150 @param[in] Count The line number to advance by.
151 @param[in] CurrentLine The pointer to the current line structure.
152 @param[in] LineList The pointer to the linked list of lines.
154 @retval NULL There was an error.
155 @return The line structure after the advance.
159 InternalEditorMiscLineAdvance (
160 IN CONST UINTN Count
,
161 IN CONST EFI_EDITOR_LINE
*CurrentLine
,
162 IN CONST LIST_ENTRY
*LineList
167 CONST EFI_EDITOR_LINE
*Line
;
169 if (CurrentLine
== NULL
|| LineList
== NULL
) {
173 for (Line
= CurrentLine
, Index
= 0; Index
< Count
; Index
++) {
175 // if already last line
177 if (Line
->Link
.ForwardLink
== LineList
) {
181 Line
= CR (Line
->Link
.ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
184 return ((EFI_EDITOR_LINE
*)Line
);
188 Retreat to the previous Count lines.
190 @param[in] Count The line number to retreat by.
191 @param[in] CurrentLine The pointer to the current line structure.
192 @param[in] LineList The pointer to the linked list of lines.
194 @retval NULL There was an error.
195 @return The line structure after the retreat.
199 InternalEditorMiscLineRetreat (
200 IN CONST UINTN Count
,
201 IN CONST EFI_EDITOR_LINE
*CurrentLine
,
202 IN CONST LIST_ENTRY
*LineList
207 CONST EFI_EDITOR_LINE
*Line
;
209 if (CurrentLine
== NULL
|| LineList
== NULL
) {
213 for (Line
= CurrentLine
, Index
= 0; Index
< Count
; Index
++) {
215 // already the first line
217 if (Line
->Link
.BackLink
== LineList
) {
221 Line
= CR (Line
->Link
.BackLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
224 return ((EFI_EDITOR_LINE
*)Line
);
228 Advance/Retreat lines
230 @param[in] Count line number to advance/retreat
234 @retval NULL An error occured.
235 @return The line after advance/retreat.
242 EFI_EDITOR_LINE
*Line
;
246 // if < 0, then retreat
247 // if > 0, the advance
250 AbsCount
= (UINTN
)ABS(Count
);
251 Line
= InternalEditorMiscLineRetreat (AbsCount
,MainEditor
.FileBuffer
->CurrentLine
,MainEditor
.FileBuffer
->ListHead
);
253 Line
= InternalEditorMiscLineAdvance ((UINTN
)Count
,MainEditor
.FileBuffer
->CurrentLine
,MainEditor
.FileBuffer
->ListHead
);
260 Function to update the 'screen' to display the mouse position.
262 @retval EFI_SUCCESS The backup operation was successful.
266 FileBufferRestoreMousePosition (
270 EFI_EDITOR_COLOR_UNION Orig
;
271 EFI_EDITOR_COLOR_UNION New
;
274 BOOLEAN HasCharacter
;
275 EFI_EDITOR_LINE
*CurrentLine
;
276 EFI_EDITOR_LINE
*Line
;
280 // variable initialization
284 if (MainEditor
.MouseSupported
) {
286 if (FileBufferMouseNeedRefresh
) {
288 FileBufferMouseNeedRefresh
= FALSE
;
291 // if mouse position not moved and only mouse action
292 // so do not need to refresh mouse position
294 if ((FileBuffer
.MousePosition
.Row
== FileBufferBackupVar
.MousePosition
.Row
&&
295 FileBuffer
.MousePosition
.Column
== FileBufferBackupVar
.MousePosition
.Column
)
296 && EditorMouseAction
) {
300 // backup the old screen attributes
302 Orig
= MainEditor
.ColorAttributes
;
303 New
.Colors
.Foreground
= Orig
.Colors
.Background
;
304 New
.Colors
.Background
= Orig
.Colors
.Foreground
;
307 // clear the old mouse position
309 FRow
= FileBuffer
.LowVisibleRange
.Row
+ FileBufferBackupVar
.MousePosition
.Row
- 2;
311 FColumn
= FileBuffer
.LowVisibleRange
.Column
+ FileBufferBackupVar
.MousePosition
.Column
- 1;
314 if (FRow
> FileBuffer
.NumLines
) {
315 HasCharacter
= FALSE
;
317 CurrentLine
= FileBuffer
.CurrentLine
;
318 Line
= MoveLine (FRow
- FileBuffer
.FilePosition
.Row
);
320 if (Line
== NULL
|| FColumn
> Line
->Size
) {
321 HasCharacter
= FALSE
;
324 FileBuffer
.CurrentLine
= CurrentLine
;
328 (INT32
)FileBufferBackupVar
.MousePosition
.Column
- 1,
329 (INT32
)FileBufferBackupVar
.MousePosition
.Row
- 1,
334 Value
= (Line
->Buffer
[FColumn
- 1]);
336 (INT32
)FileBufferBackupVar
.MousePosition
.Column
- 1,
337 (INT32
)FileBufferBackupVar
.MousePosition
.Row
- 1,
343 // set the new mouse position
345 gST
->ConOut
->SetAttribute (gST
->ConOut
, New
.Data
);
348 // clear the old mouse position
350 FRow
= FileBuffer
.LowVisibleRange
.Row
+ FileBuffer
.MousePosition
.Row
- 2;
351 FColumn
= FileBuffer
.LowVisibleRange
.Column
+ FileBuffer
.MousePosition
.Column
- 1;
354 if (FRow
> FileBuffer
.NumLines
) {
355 HasCharacter
= FALSE
;
357 CurrentLine
= FileBuffer
.CurrentLine
;
358 Line
= MoveLine (FRow
- FileBuffer
.FilePosition
.Row
);
360 if (Line
== NULL
|| FColumn
> Line
->Size
) {
361 HasCharacter
= FALSE
;
364 FileBuffer
.CurrentLine
= CurrentLine
;
368 (INT32
)FileBuffer
.MousePosition
.Column
- 1,
369 (INT32
)FileBuffer
.MousePosition
.Row
- 1,
374 Value
= Line
->Buffer
[FColumn
- 1];
376 (INT32
)FileBuffer
.MousePosition
.Column
- 1,
377 (INT32
)FileBuffer
.MousePosition
.Row
- 1,
383 // end of HasCharacter
385 gST
->ConOut
->SetAttribute (gST
->ConOut
, Orig
.Data
);
388 // end of MouseNeedRefresh
392 // end of MouseSupported
398 Free all the lines in FileBuffer
405 @retval EFI_SUCCESS The operation was successful.
409 FileBufferFreeLines (
414 EFI_EDITOR_LINE
*Line
;
417 // free all the lines
419 if (FileBuffer
.Lines
!= NULL
) {
421 Line
= FileBuffer
.Lines
;
422 Link
= &(Line
->Link
);
424 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
425 Link
= Link
->ForwardLink
;
428 // free line's buffer and line itself
431 } while (Link
!= FileBuffer
.ListHead
);
434 // clean the line list related structure
436 FileBuffer
.Lines
= NULL
;
437 FileBuffer
.CurrentLine
= NULL
;
438 FileBuffer
.NumLines
= 0;
440 FileBuffer
.ListHead
->ForwardLink
= FileBuffer
.ListHead
;
441 FileBuffer
.ListHead
->BackLink
= FileBuffer
.ListHead
;
447 Cleanup function for FileBuffer.
449 @retval EFI_SUCCESS The cleanup was successful.
459 SHELL_FREE_NON_NULL (FileBuffer
.FileName
);
462 // free all the lines
464 Status
= FileBufferFreeLines ();
466 SHELL_FREE_NON_NULL (FileBuffer
.ListHead
);
467 FileBuffer
.ListHead
= NULL
;
469 SHELL_FREE_NON_NULL (FileBufferBackupVar
.FileName
);
475 Print a line specified by Line on a row specified by Row of the screen.
477 @param[in] Line The line to print.
478 @param[in] Row The row on the screen to print onto (begin from 1).
480 @retval EFI_SUCCESS The printing was successful.
483 FileBufferPrintLine (
484 IN CONST EFI_EDITOR_LINE
*Line
,
491 CHAR16 PrintLine
[200];
492 CHAR16 PrintLine2
[250];
495 // print start from correct character
497 Buffer
= Line
->Buffer
+ FileBuffer
.LowVisibleRange
.Column
- 1;
499 Limit
= Line
->Size
- FileBuffer
.LowVisibleRange
.Column
+ 1;
500 if (Limit
> Line
->Size
) {
504 StrnCpy (PrintLine
, Buffer
, MIN(MIN(Limit
,MainEditor
.ScreenSize
.Column
), 200));
505 for (; Limit
< MainEditor
.ScreenSize
.Column
; Limit
++) {
506 PrintLine
[Limit
] = L
' ';
509 PrintLine
[MainEditor
.ScreenSize
.Column
] = CHAR_NULL
;
510 ShellCopySearchAndReplace(PrintLine
, PrintLine2
, 250, L
"%", L
"^%", FALSE
, FALSE
);
523 Set the cursor position according to FileBuffer.DisplayPosition.
525 @retval EFI_SUCCESS The operation was successful.
529 FileBufferRestorePosition (
534 // set cursor position
536 return (gST
->ConOut
->SetCursorPosition (
538 FileBuffer
.DisplayPosition
.Column
- 1,
539 FileBuffer
.DisplayPosition
.Row
- 1
544 Refresh the screen with whats in the buffer.
546 @retval EFI_SUCCESS The refresh was successful.
547 @retval EFI_LOAD_ERROR There was an error finding what to write.
556 EFI_EDITOR_LINE
*Line
;
560 // if it's the first time after editor launch, so should refresh
564 // no definite required refresh
565 // and file position displayed on screen has not been changed
567 if (!FileBufferNeedRefresh
&&
568 !FileBufferOnlyLineNeedRefresh
&&
569 FileBufferBackupVar
.LowVisibleRange
.Row
== FileBuffer
.LowVisibleRange
.Row
&&
570 FileBufferBackupVar
.LowVisibleRange
.Column
== FileBuffer
.LowVisibleRange
.Column
573 FileBufferRestoreMousePosition ();
574 FileBufferRestorePosition ();
580 gST
->ConOut
->EnableCursor (gST
->ConOut
, FALSE
);
583 // only need to refresh current line
585 if (FileBufferOnlyLineNeedRefresh
&&
586 FileBufferBackupVar
.LowVisibleRange
.Row
== FileBuffer
.LowVisibleRange
.Row
&&
587 FileBufferBackupVar
.LowVisibleRange
.Column
== FileBuffer
.LowVisibleRange
.Column
590 EditorClearLine (FileBuffer
.DisplayPosition
.Row
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
);
591 FileBufferPrintLine (
592 FileBuffer
.CurrentLine
,
593 FileBuffer
.DisplayPosition
.Row
597 // the whole edit area need refresh
603 if (FileBuffer
.Lines
== NULL
) {
604 FileBufferRestoreMousePosition ();
605 FileBufferRestorePosition ();
606 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
611 // get the first line that will be displayed
613 Line
= MoveLine (FileBuffer
.LowVisibleRange
.Row
- FileBuffer
.FilePosition
.Row
);
615 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
617 return EFI_LOAD_ERROR
;
620 Link
= &(Line
->Link
);
623 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
628 FileBufferPrintLine (Line
, Row
);
630 Link
= Link
->ForwardLink
;
632 } while (Link
!= FileBuffer
.ListHead
&& Row
<= (MainEditor
.ScreenSize
.Row
- 1));
634 // while not file end and not screen full
636 while (Row
<= (MainEditor
.ScreenSize
.Row
- 1)) {
637 EditorClearLine (Row
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
);
642 FileBufferRestoreMousePosition ();
643 FileBufferRestorePosition ();
645 FileBufferNeedRefresh
= FALSE
;
646 FileBufferOnlyLineNeedRefresh
= FALSE
;
648 gST
->ConOut
->EnableCursor (gST
->ConOut
, TRUE
);
653 Create a new line and append it to the line list.
658 @retval NULL The create line failed.
659 @return The line created.
663 FileBufferCreateLine (
667 EFI_EDITOR_LINE
*Line
;
670 // allocate a line structure
672 Line
= AllocateZeroPool (sizeof (EFI_EDITOR_LINE
));
677 // initialize the structure
679 Line
->Signature
= LINE_LIST_SIGNATURE
;
682 Line
->Type
= NewLineTypeDefault
;
685 // initial buffer of the line is "\0"
687 ASSERT(CHAR_NULL
== CHAR_NULL
);
688 Line
->Buffer
= CatSPrint (NULL
, L
"\0");
689 if (Line
->Buffer
== NULL
) {
693 FileBuffer
.NumLines
++;
696 // insert the line into line list
698 InsertTailList (FileBuffer
.ListHead
, &Line
->Link
);
700 if (FileBuffer
.Lines
== NULL
) {
701 FileBuffer
.Lines
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
708 Set FileName field in FileBuffer.
710 @param Str The file name to set.
712 @retval EFI_SUCCESS The filename was successfully set.
713 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
714 @retval EFI_INVALID_PARAMETER Str is not a valid filename.
718 FileBufferSetFileName (
723 // Verify the parameters
725 if (!IsValidFileName(Str
)) {
726 return (EFI_INVALID_PARAMETER
);
729 // free the old file name
731 SHELL_FREE_NON_NULL (FileBuffer
.FileName
);
734 // Allocate and set the new name
736 FileBuffer
.FileName
= CatSPrint (NULL
, L
"%s", Str
);
737 if (FileBuffer
.FileName
== NULL
) {
738 return EFI_OUT_OF_RESOURCES
;
744 Free the existing file lines and reset the modified flag.
746 @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.
778 IN CONST CHAR16
*FileName
,
779 IN CONST BOOLEAN Recover
782 EFI_EDITOR_LINE
*Line
;
783 EE_NEWLINE_TYPE Type
;
788 CHAR16
*UnicodeBuffer
;
791 SHELL_FILE_HANDLE FileHandle
;
794 UINTN LineSizeBackup
;
800 UnicodeBuffer
= NULL
;
801 Type
= NewLineTypeDefault
;
806 // in this function, when you return error ( except EFI_OUT_OF_RESOURCES )
807 // you should set status string via StatusBarSetStatusString(L"blah")
808 // since this function maybe called before the editorhandleinput loop
809 // so any error will cause editor return
810 // so if you want to print the error status
811 // you should set the status string
815 // try to open the file
817 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
, 0);
819 if (!EFI_ERROR(Status
)) {
821 if (FileHandle
== NULL
) {
822 StatusBarSetStatusString (L
"Disk Error");
823 return EFI_LOAD_ERROR
;
826 Info
= ShellGetFileInfo(FileHandle
);
828 if (Info
->Attribute
& EFI_FILE_DIRECTORY
) {
829 StatusBarSetStatusString (L
"Directory Can Not Be Edited");
831 return EFI_INVALID_PARAMETER
;
834 if (Info
->Attribute
& EFI_FILE_READ_ONLY
) {
835 FileBuffer
.ReadOnly
= TRUE
;
837 FileBuffer
.ReadOnly
= FALSE
;
842 FileSize
= (UINTN
) Info
->FileSize
;
845 } else if (Status
== EFI_NOT_FOUND
) {
847 // file not exists. add create and try again
849 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
|EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_CREATE
, 0);
850 if (EFI_ERROR (Status
)) {
851 if (Status
== EFI_WRITE_PROTECTED
||
852 Status
== EFI_ACCESS_DENIED
||
853 Status
== EFI_NO_MEDIA
||
854 Status
== EFI_MEDIA_CHANGED
856 StatusBarSetStatusString (L
"Access Denied");
857 } else if (Status
== EFI_DEVICE_ERROR
|| Status
== EFI_VOLUME_CORRUPTED
|| Status
== EFI_VOLUME_FULL
) {
858 StatusBarSetStatusString (L
"Disk Error");
860 StatusBarSetStatusString (L
"Invalid File Name or Current-working-directory");
866 // it worked. now delete it and move on with the name (now validated)
868 Status
= ShellDeleteFile (&FileHandle
);
869 if (Status
== EFI_WARN_DELETE_FAILURE
) {
870 Status
= EFI_ACCESS_DENIED
;
873 if (EFI_ERROR (Status
)) {
874 StatusBarSetStatusString (L
"Access Denied");
879 // file doesn't exist, so set CreateFile to TRUE
882 FileBuffer
.ReadOnly
= FALSE
;
885 // all the check ends
886 // so now begin to set file name, free lines
888 if (StrCmp (FileName
, FileBuffer
.FileName
) != 0) {
889 FileBufferSetFileName (FileName
);
892 // free the old lines
902 // allocate buffer to read file
904 Buffer
= AllocateZeroPool (FileSize
);
905 if (Buffer
== NULL
) {
906 return EFI_OUT_OF_RESOURCES
;
909 // read file into Buffer
911 Status
= ShellReadFile (FileHandle
, &FileSize
, Buffer
);
912 ShellCloseFile(&FileHandle
);
914 if (EFI_ERROR (Status
)) {
915 StatusBarSetStatusString (L
"Read File Failed");
916 SHELL_FREE_NON_NULL (Buffer
);
917 return EFI_LOAD_ERROR
;
920 // nothing in this file
923 SHELL_FREE_NON_NULL (Buffer
);
925 // since has no head, so only can be an ASCII file
927 FileBuffer
.FileType
= FileTypeAscii
;
932 AsciiBuffer
= Buffer
;
936 // size < Unicode file header, so only can be ASCII file
938 FileBuffer
.FileType
= FileTypeAscii
;
943 if (*(UINT16
*) Buffer
== EFI_UNICODE_BYTE_ORDER_MARK
) {
945 // Unicode file's size should be even
947 if ((FileSize
% 2) != 0) {
948 StatusBarSetStatusString (L
"File Format Wrong");
949 SHELL_FREE_NON_NULL (Buffer
);
950 return EFI_LOAD_ERROR
;
955 FileBuffer
.FileType
= FileTypeUnicode
;
956 UnicodeBuffer
= Buffer
;
959 // pass this 0xff and 0xfe
964 FileBuffer
.FileType
= FileTypeAscii
;
967 // end of AsciiBuffer ==
971 // end of FileSize < 2
972 // all the check ends
973 // so now begin to set file name, free lines
975 if (StrCmp (FileName
, FileBuffer
.FileName
) != 0) {
976 FileBufferSetFileName (FileName
);
980 // free the old lines
985 // parse file content line by line
987 for (LoopVar1
= 0; LoopVar1
< FileSize
; LoopVar1
++) {
988 Type
= NewLineTypeUnknown
;
990 for (LineSize
= LoopVar1
; LineSize
< FileSize
; LineSize
++) {
991 if (FileBuffer
.FileType
== FileTypeAscii
) {
992 if (AsciiBuffer
[LineSize
] == CHAR_CARRIAGE_RETURN
) {
993 Type
= NewLineTypeCarriageReturn
;
998 if (LineSize
< FileSize
- 1) {
999 if (AsciiBuffer
[LineSize
+ 1] == CHAR_LINEFEED
) {
1000 Type
= NewLineTypeCarriageReturnLineFeed
;
1005 } else if (AsciiBuffer
[LineSize
] == CHAR_LINEFEED
) {
1006 Type
= NewLineTypeLineFeed
;
1011 if (LineSize
< FileSize
- 1) {
1012 if (AsciiBuffer
[LineSize
+ 1] == CHAR_CARRIAGE_RETURN
) {
1013 Type
= NewLineTypeLineFeedCarriageReturn
;
1020 if (UnicodeBuffer
[LineSize
] == CHAR_CARRIAGE_RETURN
) {
1021 Type
= NewLineTypeCarriageReturn
;
1026 if (LineSize
< FileSize
- 1) {
1027 if (UnicodeBuffer
[LineSize
+ 1] == CHAR_LINEFEED
) {
1028 Type
= NewLineTypeCarriageReturnLineFeed
;
1033 } else if (UnicodeBuffer
[LineSize
] == CHAR_LINEFEED
) {
1034 Type
= NewLineTypeLineFeed
;
1039 if (LineSize
< FileSize
- 1) {
1040 if (UnicodeBuffer
[LineSize
+ 1] == CHAR_CARRIAGE_RETURN
) {
1041 Type
= NewLineTypeLineFeedCarriageReturn
;
1053 // end of for LineSize
1055 // if the type is wrong, then exit
1057 if (Type
== NewLineTypeUnknown
) {
1059 // Now if Type is NewLineTypeUnknown, it should be file end
1061 Type
= NewLineTypeDefault
;
1064 LineSizeBackup
= LineSize
;
1067 // create a new line
1069 Line
= FileBufferCreateLine ();
1071 SHELL_FREE_NON_NULL (Buffer
);
1072 return EFI_OUT_OF_RESOURCES
;
1075 // calculate file length
1077 LineSize
-= LoopVar1
;
1080 // Unicode and one CHAR_NULL
1082 SHELL_FREE_NON_NULL (Line
->Buffer
);
1083 Line
->Buffer
= AllocateZeroPool (LineSize
* 2 + 2);
1085 if (Line
->Buffer
== NULL
) {
1086 RemoveEntryList (&Line
->Link
);
1087 return EFI_OUT_OF_RESOURCES
;
1090 // copy this line to Line->Buffer
1092 for (LoopVar2
= 0; LoopVar2
< LineSize
; LoopVar2
++) {
1093 if (FileBuffer
.FileType
== FileTypeAscii
) {
1094 Line
->Buffer
[LoopVar2
] = (CHAR16
) AsciiBuffer
[LoopVar1
];
1096 Line
->Buffer
[LoopVar2
] = UnicodeBuffer
[LoopVar1
];
1102 // LoopVar1 now points to where CHAR_CARRIAGE_RETURN or CHAR_LINEFEED;
1104 Line
->Buffer
[LineSize
] = 0;
1106 Line
->Size
= LineSize
;
1107 Line
->TotalSize
= LineSize
;
1110 if (Type
== NewLineTypeCarriageReturnLineFeed
|| Type
== NewLineTypeLineFeedCarriageReturn
) {
1115 // last character is a return, SO create a new line
1117 if (((Type
== NewLineTypeCarriageReturnLineFeed
|| Type
== NewLineTypeLineFeedCarriageReturn
) && LineSizeBackup
== FileSize
- 2) ||
1118 ((Type
== NewLineTypeLineFeed
|| Type
== NewLineTypeCarriageReturn
) && LineSizeBackup
== FileSize
- 1)
1120 Line
= FileBufferCreateLine ();
1122 SHELL_FREE_NON_NULL (Buffer
);
1123 return EFI_OUT_OF_RESOURCES
;
1133 SHELL_FREE_NON_NULL (Buffer
);
1137 // end of if CreateFile
1141 FileBuffer
.DisplayPosition
.Row
= 2;
1142 FileBuffer
.DisplayPosition
.Column
= 1;
1143 FileBuffer
.LowVisibleRange
.Row
= 1;
1144 FileBuffer
.LowVisibleRange
.Column
= 1;
1145 FileBuffer
.FilePosition
.Row
= 1;
1146 FileBuffer
.FilePosition
.Column
= 1;
1147 FileBuffer
.MousePosition
.Row
= 2;
1148 FileBuffer
.MousePosition
.Column
= 1;
1151 UnicodeBuffer
= CatSPrint (NULL
, L
"%d Lines Read", FileBuffer
.NumLines
);
1152 if (UnicodeBuffer
== NULL
) {
1153 return EFI_OUT_OF_RESOURCES
;
1156 StatusBarSetStatusString (UnicodeBuffer
);
1157 FreePool (UnicodeBuffer
);
1161 // check whether we have fs?: in filename
1164 FSMappingPtr = NULL;
1165 while (FileName[LoopVar1] != 0) {
1166 if (FileName[LoopVar1] == L':') {
1167 FSMappingPtr = &FileName[LoopVar1];
1174 if (FSMappingPtr == NULL) {
1175 CurDir = ShellGetCurrentDir (NULL);
1179 while (FileName[LoopVar1] != 0) {
1180 if (FileName[LoopVar1] == L':') {
1184 FSMapping[LoopVar2++] = FileName[LoopVar1];
1189 FSMapping[LoopVar2] = 0;
1190 CurDir = ShellGetCurrentDir (FSMapping);
1193 if (CurDir != NULL) {
1194 for (LoopVar1 = 0; LoopVar1 < StrLen (CurDir) && CurDir[LoopVar1] != ':'; LoopVar1++);
1196 CurDir[LoopVar1] = 0;
1197 DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) ShellGetMap (CurDir);
1200 return EFI_LOAD_ERROR;
1203 Status = LibDevicePathToInterface (
1204 &gEfiSimpleFileSystemProtocolGuid,
1208 if (EFI_ERROR (Status)) {
1209 return EFI_LOAD_ERROR;
1212 Status = Vol->OpenVolume (Vol, &RootFs);
1213 if (EFI_ERROR (Status)) {
1214 return EFI_LOAD_ERROR;
1217 // Get volume information of file system
1219 Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + 100;
1220 VolumeInfo = (EFI_FILE_SYSTEM_INFO *) AllocateZeroPool (Size);
1221 Status = RootFs->GetInfo (RootFs, &gEfiFileSystemInfoGuid, &Size, VolumeInfo);
1222 if (EFI_ERROR (Status)) {
1223 RootFs->Close (RootFs);
1224 return EFI_LOAD_ERROR;
1227 if (VolumeInfo->ReadOnly) {
1228 StatusBarSetStatusString (L"WARNING: Volume Read Only");
1231 FreePool (VolumeInfo);
1232 RootFs->Close (RootFs);
1239 if (FileBuffer
.Lines
!= 0) {
1240 FileBuffer
.CurrentLine
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1243 // create a dummy line
1245 Line
= FileBufferCreateLine ();
1247 return EFI_OUT_OF_RESOURCES
;
1250 FileBuffer
.CurrentLine
= Line
;
1253 FileBuffer
.FileModified
= FALSE
;
1254 FileBufferNeedRefresh
= TRUE
;
1255 FileBufferOnlyLineNeedRefresh
= FALSE
;
1256 FileBufferMouseNeedRefresh
= TRUE
;
1263 According to FileBuffer.NewLineType & FileBuffer.FileType,
1264 get the return buffer and size.
1266 @param[in] Type The type of line.
1267 @param[out] Buffer The buffer to fill.
1268 @param[out] Size The amount of the buffer used on return.
1273 IN CONST EE_NEWLINE_TYPE Type
,
1281 // give new line buffer,
1282 // and will judge unicode or ascii
1287 // not legal new line type
1289 if (Type
!= NewLineTypeLineFeed
&& Type
!= NewLineTypeCarriageReturn
&& Type
!= NewLineTypeCarriageReturnLineFeed
&& Type
!= NewLineTypeLineFeedCarriageReturn
) {
1294 // use_cr: give 0x0d
1296 if (Type
== NewLineTypeCarriageReturn
) {
1297 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1306 *Size
= NewLineSize
;
1310 // use_lf: give 0x0a
1312 if (Type
== NewLineTypeLineFeed
) {
1313 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1322 *Size
= NewLineSize
;
1326 // use_crlf: give 0x0d 0x0a
1328 if (Type
== NewLineTypeCarriageReturnLineFeed
) {
1329 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1342 *Size
= NewLineSize
;
1346 // use_lfcr: give 0x0a 0x0d
1348 if (Type
== NewLineTypeLineFeedCarriageReturn
) {
1349 if (MainEditor
.FileBuffer
->FileType
== FileTypeUnicode
) {
1362 *Size
= NewLineSize
;
1369 Change a Unicode string to an ASCII string.
1371 @param[in] UStr The Unicode string.
1372 @param[in] Length The maximum size of AStr.
1373 @param[out] AStr ASCII string to pass out.
1375 @return The actuall length.
1380 IN CONST CHAR16
*UStr
,
1381 IN CONST UINTN Length
,
1388 // just buffer copy, not character copy
1390 for (Index
= 0; Index
< Length
; Index
++) {
1391 *AStr
++ = (CHAR8
) *UStr
++;
1398 Save lines in FileBuffer to disk
1400 @param[in] FileName The file name for writing.
1402 @retval EFI_SUCCESS Data was written.
1403 @retval EFI_LOAD_ERROR
1404 @retval EFI_OUT_OF_RESOURCES There were not enough resources to write the file.
1409 IN CONST CHAR16
*FileName
1412 SHELL_FILE_HANDLE FileHandle
;
1414 EFI_EDITOR_LINE
*Line
;
1420 CHAR8 NewLineBuffer
[4];
1423 EFI_FILE_INFO
*Info
;
1427 EE_NEWLINE_TYPE Type
;
1442 TotalSize
= 0x200000;
1449 // if is the old file
1451 if (FileBuffer
.FileName
!= NULL
&& StrCmp (FileName
, FileBuffer
.FileName
) == 0) {
1453 // file has not been modified
1455 if (!FileBuffer
.FileModified
) {
1460 // if file is read-only, set error
1462 if (FileBuffer
.ReadOnly
) {
1463 StatusBarSetStatusString (L
"Read Only File Can Not Be Saved");
1468 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
|EFI_FILE_MODE_WRITE
, 0);
1470 if (!EFI_ERROR (Status
)) {
1471 Info
= ShellGetFileInfo(FileHandle
);
1473 if (Info
!= NULL
&& Info
->Attribute
& EFI_FILE_DIRECTORY
) {
1474 StatusBarSetStatusString (L
"Directory Can Not Be Saved");
1475 ShellCloseFile(FileHandle
);
1477 return EFI_LOAD_ERROR
;
1481 Attribute
= Info
->Attribute
& ~EFI_FILE_READ_ONLY
;
1486 // if file exits, so delete it
1488 Status
= ShellDeleteFile (&FileHandle
);
1489 if (EFI_ERROR (Status
) || Status
== EFI_WARN_DELETE_FAILURE
) {
1490 StatusBarSetStatusString (L
"Write File Failed");
1491 return EFI_LOAD_ERROR
;
1495 Status
= ShellOpenFileByName (FileName
, &FileHandle
, EFI_FILE_MODE_READ
|EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_CREATE
, Attribute
);
1497 if (EFI_ERROR (Status
)) {
1498 StatusBarSetStatusString (L
"Create File Failed");
1499 return EFI_LOAD_ERROR
;
1503 // if file is Unicode file, write Unicode header to it.
1505 if (FileBuffer
.FileType
== FileTypeUnicode
) {
1507 Status
= ShellWriteFile (FileHandle
, &Length
, (VOID
*)&gUnicodeFileTag
);
1508 if (EFI_ERROR (Status
)) {
1509 ShellDeleteFile (&FileHandle
);
1510 return EFI_LOAD_ERROR
;
1514 Cache
= AllocateZeroPool (TotalSize
);
1515 if (Cache
== NULL
) {
1516 ShellDeleteFile (&FileHandle
);
1517 return EFI_OUT_OF_RESOURCES
;
1521 // write all the lines back to disk
1524 Type
= NewLineTypeCarriageReturnLineFeed
;
1527 LeftSize
= TotalSize
;
1529 for (Link
= FileBuffer
.ListHead
->ForwardLink
; Link
!= FileBuffer
.ListHead
; Link
= Link
->ForwardLink
) {
1530 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1532 if (Line
->Type
!= NewLineTypeDefault
) {
1536 // newline character is at most 4 bytes ( two Unicode characters )
1539 if (Line
->Buffer
!= NULL
&& Line
->Size
!= 0) {
1540 if (FileBuffer
.FileType
== FileTypeAscii
) {
1541 Length
+= Line
->Size
;
1543 Length
+= (Line
->Size
* 2);
1546 // end if FileTypeAscii
1551 // no cache room left, so write cache to disk
1553 if (LeftSize
< Length
) {
1554 Size
= TotalSize
- LeftSize
;
1555 Status
= ShellWriteFile (FileHandle
, &Size
, Cache
);
1556 if (EFI_ERROR (Status
)) {
1557 ShellDeleteFile (&FileHandle
);
1559 return EFI_LOAD_ERROR
;
1562 LeftSize
= TotalSize
;
1565 if (Line
->Buffer
!= NULL
&& Line
->Size
!= 0) {
1566 if (FileBuffer
.FileType
== FileTypeAscii
) {
1567 UnicodeToAscii (Line
->Buffer
, Line
->Size
, Ptr
);
1568 Length
= Line
->Size
;
1570 Length
= (Line
->Size
* 2);
1571 CopyMem (Ptr
, (CHAR8
*) Line
->Buffer
, Length
);
1574 // end if FileTypeAscii
1581 // end of if Line -> Buffer != NULL && Line -> Size != 0
1583 // if not the last line , write return buffer to disk
1585 if (Link
->ForwardLink
!= FileBuffer
.ListHead
) {
1586 GetNewLine (Type
, NewLineBuffer
, &NewLineSize
);
1587 CopyMem (Ptr
, (CHAR8
*) NewLineBuffer
, NewLineSize
);
1590 LeftSize
-= NewLineSize
;
1596 if (TotalSize
!= LeftSize
) {
1597 Size
= TotalSize
- LeftSize
;
1598 Status
= ShellWriteFile (FileHandle
, &Size
, Cache
);
1599 if (EFI_ERROR (Status
)) {
1600 ShellDeleteFile (&FileHandle
);
1602 return EFI_LOAD_ERROR
;
1608 ShellCloseFile(&FileHandle
);
1610 FileBuffer
.FileModified
= FALSE
;
1613 // set status string
1615 Str
= CatSPrint (NULL
, L
"%d Lines Wrote", NumLines
);
1617 return EFI_OUT_OF_RESOURCES
;
1620 StatusBarSetStatusString (Str
);
1621 SHELL_FREE_NON_NULL (Str
);
1624 // now everything is ready , you can set the new file name to filebuffer
1626 if (FileName
!= NULL
&& FileBuffer
.FileName
!= NULL
&& StrCmp (FileName
, FileBuffer
.FileName
) != 0) {
1630 FileBufferSetFileName (FileName
);
1631 if (FileBuffer
.FileName
== NULL
) {
1632 ShellDeleteFile (&FileHandle
);
1633 return EFI_OUT_OF_RESOURCES
;
1637 FileBuffer
.ReadOnly
= FALSE
;
1642 Scroll cursor to left 1 character position.
1644 @retval EFI_SUCCESS The operation was successful.
1648 FileBufferScrollLeft (
1652 EFI_EDITOR_LINE
*Line
;
1656 Line
= FileBuffer
.CurrentLine
;
1658 FRow
= FileBuffer
.FilePosition
.Row
;
1659 FCol
= FileBuffer
.FilePosition
.Column
;
1662 // if already at start of this line, so move to the end of previous line
1666 // has previous line
1668 if (Line
->Link
.BackLink
!= FileBuffer
.ListHead
) {
1670 Line
= CR (Line
->Link
.BackLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1671 FCol
= Line
->Size
+ 1;
1677 // if not at start of this line, just move to previous column
1682 FileBufferMovePosition (FRow
, FCol
);
1688 Delete a char in line
1690 @param[in, out] Line The line to delete in.
1691 @param[in] Pos Position to delete the char at ( start from 0 ).
1696 IN OUT EFI_EDITOR_LINE
*Line
,
1703 // move the latter characters front
1705 for (Index
= Pos
- 1; Index
< Line
->Size
; Index
++) {
1706 Line
->Buffer
[Index
] = Line
->Buffer
[Index
+ 1];
1713 Concatenate Src into Dest.
1715 @param[in, out] Dest Destination string
1716 @param[in] Src Src String.
1721 IN OUT EFI_EDITOR_LINE
*Dest
,
1722 IN EFI_EDITOR_LINE
*Src
1730 Dest
->Buffer
[Size
] = 0;
1733 // concatenate the two strings
1735 Str
= CatSPrint (NULL
, L
"%s%s", Dest
->Buffer
, Src
->Buffer
);
1737 Dest
->Buffer
= NULL
;
1741 Dest
->Size
= Size
+ Src
->Size
;
1742 Dest
->TotalSize
= Dest
->Size
;
1744 FreePool (Dest
->Buffer
);
1745 FreePool (Src
->Buffer
);
1748 // put str to dest->buffer
1754 Delete the previous character.
1756 @retval EFI_SUCCESS The delete was successful.
1757 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1761 FileBufferDoBackspace (
1765 EFI_EDITOR_LINE
*Line
;
1766 EFI_EDITOR_LINE
*End
;
1770 FileColumn
= FileBuffer
.FilePosition
.Column
;
1772 Line
= FileBuffer
.CurrentLine
;
1777 if (FileColumn
== 1) {
1781 if (FileBuffer
.FilePosition
.Row
== 1) {
1785 FileBufferScrollLeft ();
1787 Line
= FileBuffer
.CurrentLine
;
1788 Link
= Line
->Link
.ForwardLink
;
1789 End
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1792 // concatenate this line with previous line
1794 LineCat (Line
, End
);
1795 if (Line
->Buffer
== NULL
) {
1796 return EFI_OUT_OF_RESOURCES
;
1799 // remove End from line list
1801 RemoveEntryList (&End
->Link
);
1804 FileBuffer
.NumLines
--;
1806 FileBufferNeedRefresh
= TRUE
;
1807 FileBufferOnlyLineNeedRefresh
= FALSE
;
1811 // just delete the previous character
1813 LineDeleteAt (Line
, FileColumn
- 1);
1814 FileBufferScrollLeft ();
1815 FileBufferOnlyLineNeedRefresh
= TRUE
;
1818 if (!FileBuffer
.FileModified
) {
1819 FileBuffer
.FileModified
= TRUE
;
1826 Add a return into line at current position.
1828 @retval EFI_SUCCESS The insetrion of the character was successful.
1829 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1833 FileBufferDoReturn (
1837 EFI_EDITOR_LINE
*Line
;
1838 EFI_EDITOR_LINE
*NewLine
;
1845 FileBufferNeedRefresh
= TRUE
;
1846 FileBufferOnlyLineNeedRefresh
= FALSE
;
1848 Line
= FileBuffer
.CurrentLine
;
1850 FileColumn
= FileBuffer
.FilePosition
.Column
;
1852 NewLine
= AllocateZeroPool (sizeof (EFI_EDITOR_LINE
));
1853 if (NewLine
== NULL
) {
1854 return EFI_OUT_OF_RESOURCES
;
1857 NewLine
->Signature
= LINE_LIST_SIGNATURE
;
1858 NewLine
->Size
= Line
->Size
- FileColumn
+ 1;
1859 NewLine
->TotalSize
= NewLine
->Size
;
1860 NewLine
->Buffer
= CatSPrint (NULL
, L
"\0");
1861 if (NewLine
->Buffer
== NULL
) {
1862 return EFI_OUT_OF_RESOURCES
;
1865 NewLine
->Type
= NewLineTypeDefault
;
1867 if (NewLine
->Size
> 0) {
1869 // UNICODE + CHAR_NULL
1871 Buffer
= AllocateZeroPool (2 * (NewLine
->Size
+ 1));
1872 if (Buffer
== NULL
) {
1873 FreePool (NewLine
->Buffer
);
1875 return EFI_OUT_OF_RESOURCES
;
1878 FreePool (NewLine
->Buffer
);
1880 NewLine
->Buffer
= Buffer
;
1882 for (Index
= 0; Index
< NewLine
->Size
; Index
++) {
1883 NewLine
->Buffer
[Index
] = Line
->Buffer
[Index
+ FileColumn
- 1];
1886 NewLine
->Buffer
[NewLine
->Size
] = CHAR_NULL
;
1888 Line
->Buffer
[FileColumn
- 1] = CHAR_NULL
;
1889 Line
->Size
= FileColumn
- 1;
1892 // increase NumLines
1894 FileBuffer
.NumLines
++;
1897 // insert it into the correct position of line list
1899 NewLine
->Link
.BackLink
= &(Line
->Link
);
1900 NewLine
->Link
.ForwardLink
= Line
->Link
.ForwardLink
;
1901 Line
->Link
.ForwardLink
->BackLink
= &(NewLine
->Link
);
1902 Line
->Link
.ForwardLink
= &(NewLine
->Link
);
1905 // move cursor to the start of next line
1907 Row
= FileBuffer
.FilePosition
.Row
+ 1;
1910 FileBufferMovePosition (Row
, Col
);
1913 // set file is modified
1915 if (!FileBuffer
.FileModified
) {
1916 FileBuffer
.FileModified
= TRUE
;
1923 Delete current character from current line. This is the effect caused
1930 FileBufferDoDelete (
1934 EFI_EDITOR_LINE
*Line
;
1935 EFI_EDITOR_LINE
*Next
;
1939 Line
= FileBuffer
.CurrentLine
;
1940 FileColumn
= FileBuffer
.FilePosition
.Column
;
1945 if (FileColumn
>= Line
->Size
+ 1) {
1949 if (Line
->Link
.ForwardLink
== FileBuffer
.ListHead
) {
1953 // since last character,
1954 // so will add the next line to this line
1956 Link
= Line
->Link
.ForwardLink
;
1957 Next
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
1958 LineCat (Line
, Next
);
1959 if (Line
->Buffer
== NULL
) {
1960 return EFI_OUT_OF_RESOURCES
;
1963 RemoveEntryList (&Next
->Link
);
1966 FileBuffer
.NumLines
--;
1968 FileBufferNeedRefresh
= TRUE
;
1969 FileBufferOnlyLineNeedRefresh
= FALSE
;
1973 // just delete current character
1975 LineDeleteAt (Line
, FileColumn
);
1976 FileBufferOnlyLineNeedRefresh
= TRUE
;
1979 if (!FileBuffer
.FileModified
) {
1980 FileBuffer
.FileModified
= TRUE
;
1987 Scroll cursor to right 1 character.
1989 @retval EFI_SUCCESS The operation was successful.
1993 FileBufferScrollRight (
1997 EFI_EDITOR_LINE
*Line
;
2001 Line
= FileBuffer
.CurrentLine
;
2002 if (Line
->Buffer
== NULL
) {
2006 FRow
= FileBuffer
.FilePosition
.Row
;
2007 FCol
= FileBuffer
.FilePosition
.Column
;
2010 // if already at end of this line, scroll it to the start of next line
2012 if (FCol
> Line
->Size
) {
2016 if (Line
->Link
.ForwardLink
!= FileBuffer
.ListHead
) {
2024 // if not at end of this line, just move to next column
2029 FileBufferMovePosition (FRow
, FCol
);
2035 Insert a char into line
2038 @param[in] Line The line to insert into.
2039 @param[in] Char The char to insert.
2040 @param[in] Pos The position to insert the char at ( start from 0 ).
2041 @param[in] StrSize The current string size ( include CHAR_NULL ),unit is Unicode character.
2043 @return The new string size ( include CHAR_NULL ) ( unit is Unicode character ).
2048 IN EFI_EDITOR_LINE
*Line
,
2055 CHAR16
*TempStringPtr
;
2058 Index
= (StrSize
) * 2;
2063 // do not have free space
2065 if (Line
->TotalSize
<= Line
->Size
) {
2066 Str
= ReallocatePool (Index
, Index
+ 16, Str
);
2071 Line
->TotalSize
+= 8;
2074 // move the later part of the string one character right
2076 TempStringPtr
= Str
;
2077 for (Index
= StrSize
; Index
> Pos
; Index
--) {
2078 TempStringPtr
[Index
] = TempStringPtr
[Index
- 1];
2081 // insert char into it.
2083 TempStringPtr
[Index
] = Char
;
2092 Add a character to the current line.
2094 @param[in] Char The Character to input.
2096 @retval EFI_SUCCESS The input was succesful.
2104 EFI_EDITOR_LINE
*Line
;
2107 Line
= FileBuffer
.CurrentLine
;
2110 // only needs to refresh current line
2112 FileBufferOnlyLineNeedRefresh
= TRUE
;
2115 // when is insert mode, or cursor is at end of this line,
2116 // so insert this character
2117 // or replace the character.
2119 FilePos
= FileBuffer
.FilePosition
.Column
- 1;
2120 if (FileBuffer
.ModeInsert
|| FilePos
+ 1 > Line
->Size
) {
2121 LineStrInsert (Line
, Char
, FilePos
, Line
->Size
+ 1);
2123 Line
->Buffer
[FilePos
] = Char
;
2126 // move cursor to right
2128 FileBufferScrollRight ();
2130 if (!FileBuffer
.FileModified
) {
2131 FileBuffer
.FileModified
= TRUE
;
2138 Handles inputs from characters (ASCII key + Backspace + return)
2140 @param[in] Char The input character.
2142 @retval EFI_SUCCESS The operation was successful.
2143 @retval EFI_LOAD_ERROR There was an error.
2144 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2148 FileBufferDoCharInput (
2149 IN CONST CHAR16 Char
2154 Status
= EFI_SUCCESS
;
2160 case CHAR_BACKSPACE
:
2161 Status
= FileBufferDoBackspace ();
2171 case CHAR_CARRIAGE_RETURN
:
2172 Status
= FileBufferDoReturn ();
2177 // DEAL WITH ASCII CHAR, filter out thing like ctrl+f
2179 if (Char
> 127 || Char
< 32) {
2180 Status
= StatusBarSetStatusString (L
"Unknown Command");
2182 Status
= FileBufferAddChar (Char
);
2193 Scroll cursor to the next line.
2195 @retval EFI_SUCCESS The operation was successful.
2199 FileBufferScrollDown (
2203 EFI_EDITOR_LINE
*Line
;
2207 Line
= FileBuffer
.CurrentLine
;
2208 if (Line
->Buffer
== NULL
) {
2212 FRow
= FileBuffer
.FilePosition
.Row
;
2213 FCol
= FileBuffer
.FilePosition
.Column
;
2218 if (Line
->Link
.ForwardLink
!= FileBuffer
.ListHead
) {
2220 Line
= CR (Line
->Link
.ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2223 // if the next line is not that long, so move to end of next line
2225 if (FCol
> Line
->Size
) {
2226 FCol
= Line
->Size
+ 1;
2233 FileBufferMovePosition (FRow
, FCol
);
2239 Scroll the cursor to previous line.
2241 @retval EFI_SUCCESS The operation was successful.
2245 FileBufferScrollUp (
2249 EFI_EDITOR_LINE
*Line
;
2253 Line
= FileBuffer
.CurrentLine
;
2255 FRow
= FileBuffer
.FilePosition
.Row
;
2256 FCol
= FileBuffer
.FilePosition
.Column
;
2259 // has previous line
2261 if (Line
->Link
.BackLink
!= FileBuffer
.ListHead
) {
2263 Line
= CR (Line
->Link
.BackLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2266 // if previous line is not that long, so move to the end of previous line
2268 if (FCol
> Line
->Size
) {
2269 FCol
= Line
->Size
+ 1;
2276 FileBufferMovePosition (FRow
, FCol
);
2282 Scroll cursor to next page.
2284 @retval EFI_SUCCESS The operation wa successful.
2288 FileBufferPageDown (
2292 EFI_EDITOR_LINE
*Line
;
2297 Line
= FileBuffer
.CurrentLine
;
2299 FRow
= FileBuffer
.FilePosition
.Row
;
2300 FCol
= FileBuffer
.FilePosition
.Column
;
2305 if (FileBuffer
.NumLines
>= FRow
+ (MainEditor
.ScreenSize
.Row
- 2)) {
2306 Gap
= (MainEditor
.ScreenSize
.Row
- 2);
2309 // MOVE CURSOR TO LAST LINE
2311 Gap
= FileBuffer
.NumLines
- FRow
;
2316 Line
= MoveLine (Gap
);
2319 // if that line, is not that long, so move to the end of that line
2321 if (Line
!= NULL
&& FCol
> Line
->Size
) {
2322 FCol
= Line
->Size
+ 1;
2327 FileBufferMovePosition (FRow
, FCol
);
2333 Scroll cursor to previous screen.
2335 @retval EFI_SUCCESS The operation was successful.
2343 EFI_EDITOR_LINE
*Line
;
2349 Line
= FileBuffer
.CurrentLine
;
2351 FRow
= FileBuffer
.FilePosition
.Row
;
2352 FCol
= FileBuffer
.FilePosition
.Column
;
2355 // has previous page
2357 if (FRow
> (MainEditor
.ScreenSize
.Row
- 2)) {
2358 Gap
= (MainEditor
.ScreenSize
.Row
- 2);
2361 // the first line of file will displayed on the first line of screen
2372 Line
= MoveLine (Retreat
);
2375 // if that line is not that long, so move to the end of that line
2377 if (Line
!= NULL
&& FCol
> Line
->Size
) {
2378 FCol
= Line
->Size
+ 1;
2383 FileBufferMovePosition (FRow
, FCol
);
2389 Scroll cursor to end of the current line.
2391 @retval EFI_SUCCESS The operation was successful.
2399 EFI_EDITOR_LINE
*Line
;
2403 Line
= FileBuffer
.CurrentLine
;
2405 FRow
= FileBuffer
.FilePosition
.Row
;
2408 // goto the last column of the line
2410 FCol
= Line
->Size
+ 1;
2412 FileBufferMovePosition (FRow
, FCol
);
2418 Dispatch input to different handler
2419 @param[in] Key The input key. One of:
2423 Direction key: up/down/left/right/pgup/pgdn
2427 @retval EFI_SUCCESS The dispatch was done successfully.
2428 @retval EFI_LOAD_ERROR The dispatch was not successful.
2429 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2433 FileBufferHandleInput (
2434 IN CONST EFI_INPUT_KEY
*Key
2439 Status
= EFI_SUCCESS
;
2441 switch (Key
->ScanCode
) {
2443 // ordinary key input
2446 if (!FileBuffer
.ReadOnly
) {
2447 Status
= FileBufferDoCharInput (Key
->UnicodeChar
);
2449 Status
= StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2458 Status
= FileBufferScrollUp ();
2465 Status
= FileBufferScrollDown ();
2472 Status
= FileBufferScrollRight ();
2479 Status
= FileBufferScrollLeft ();
2486 Status
= FileBufferPageUp ();
2492 case SCAN_PAGE_DOWN
:
2493 Status
= FileBufferPageDown ();
2500 if (!FileBuffer
.ReadOnly
) {
2501 Status
= FileBufferDoDelete ();
2503 Status
= StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2512 FileBufferMovePosition (FileBuffer
.FilePosition
.Row
, 1);
2513 Status
= EFI_SUCCESS
;
2520 Status
= FileBufferEnd ();
2527 FileBuffer
.ModeInsert
= (BOOLEAN
)!FileBuffer
.ModeInsert
;
2528 Status
= EFI_SUCCESS
;
2532 Status
= StatusBarSetStatusString (L
"Unknown Command");
2540 Check user specified FileRow is above current screen.
2542 @param[in] FileRow The row of file position ( start from 1 ).
2544 @retval TRUE It is above the current screen.
2545 @retval FALSE It is not above the current screen.
2549 AboveCurrentScreen (
2554 // if is to the above of the screen
2556 if (FileRow
< FileBuffer
.LowVisibleRange
.Row
) {
2564 Check user specified FileRow is under current screen.
2566 @param[in] FileRow The row of file position ( start from 1 ).
2568 @retval TRUE It is under the current screen.
2569 @retval FALSE It is not under the current screen.
2573 UnderCurrentScreen (
2578 // if is to the under of the screen
2580 if (FileRow
> FileBuffer
.LowVisibleRange
.Row
+ (MainEditor
.ScreenSize
.Row
- 2) - 1) {
2588 Check user specified FileCol is left to current screen.
2590 @param[in] FileCol The column of file position ( start from 1 ).
2592 @retval TRUE It is to the left.
2593 @retval FALSE It is not to the left.
2602 // if is to the left of the screen
2604 if (FileCol
< FileBuffer
.LowVisibleRange
.Column
) {
2612 Check user specified FileCol is right to current screen.
2614 @param[in] FileCol The column of file position ( start from 1 ).
2616 @retval TRUE It is to the right.
2617 @retval FALSE It is not to the right.
2621 RightCurrentScreen (
2626 // if is to the right of the screen
2628 if (FileCol
> FileBuffer
.LowVisibleRange
.Column
+ MainEditor
.ScreenSize
.Column
- 1) {
2636 Advance/Retreat lines and set CurrentLine in FileBuffer to it
2638 @param[in] Count The line number to advance/retreat
2642 @retval NULL An error occured.
2643 @return The line after advance/retreat.
2651 EFI_EDITOR_LINE
*Line
;
2655 AbsCount
= (UINTN
)ABS(Count
);
2656 Line
= InternalEditorMiscLineRetreat (AbsCount
,MainEditor
.FileBuffer
->CurrentLine
,MainEditor
.FileBuffer
->ListHead
);
2658 Line
= InternalEditorMiscLineAdvance ((UINTN
)Count
,MainEditor
.FileBuffer
->CurrentLine
,MainEditor
.FileBuffer
->ListHead
);
2665 MainEditor
.FileBuffer
->CurrentLine
= Line
;
2671 According to cursor's file position, adjust screen display
2673 @param[in] NewFilePosRow The row of file position ( start from 1 ).
2674 @param[in] NewFilePosCol The column of file position ( start from 1 ).
2678 FileBufferMovePosition (
2679 IN CONST UINTN NewFilePosRow
,
2680 IN CONST UINTN NewFilePosCol
2692 // CALCULATE gap between current file position and new file position
2694 RowGap
= NewFilePosRow
- FileBuffer
.FilePosition
.Row
;
2695 ColGap
= NewFilePosCol
- FileBuffer
.FilePosition
.Column
;
2697 Under
= UnderCurrentScreen (NewFilePosRow
);
2698 Above
= AboveCurrentScreen (NewFilePosRow
);
2700 // if is below current screen
2704 // display row will be unchanged
2706 FileBuffer
.FilePosition
.Row
= NewFilePosRow
;
2710 // has enough above line, so display row unchanged
2711 // not has enough above lines, so the first line is at the
2712 // first display line
2714 if (NewFilePosRow
< (FileBuffer
.DisplayPosition
.Row
- 1)) {
2715 FileBuffer
.DisplayPosition
.Row
= NewFilePosRow
+ 1;
2718 FileBuffer
.FilePosition
.Row
= NewFilePosRow
;
2721 // in current screen
2723 FileBuffer
.FilePosition
.Row
= NewFilePosRow
;
2725 Abs
= (UINTN
)ABS(RowGap
);
2726 FileBuffer
.DisplayPosition
.Row
-= Abs
;
2728 FileBuffer
.DisplayPosition
.Row
+= RowGap
;
2733 FileBuffer
.LowVisibleRange
.Row
= FileBuffer
.FilePosition
.Row
- (FileBuffer
.DisplayPosition
.Row
- 2);
2735 Right
= RightCurrentScreen (NewFilePosCol
);
2736 Left
= LeftCurrentScreen (NewFilePosCol
);
2739 // if right to current screen
2743 // display column will be changed to end
2745 FileBuffer
.DisplayPosition
.Column
= MainEditor
.ScreenSize
.Column
;
2746 FileBuffer
.FilePosition
.Column
= NewFilePosCol
;
2750 // has enough left characters , so display row unchanged
2751 // not has enough left characters,
2752 // so the first character is at the first display column
2754 if (NewFilePosCol
< (FileBuffer
.DisplayPosition
.Column
)) {
2755 FileBuffer
.DisplayPosition
.Column
= NewFilePosCol
;
2758 FileBuffer
.FilePosition
.Column
= NewFilePosCol
;
2761 // in current screen
2763 FileBuffer
.FilePosition
.Column
= NewFilePosCol
;
2765 Abs
= (UINTN
)(-ColGap
);
2766 FileBuffer
.DisplayPosition
.Column
-= Abs
;
2768 FileBuffer
.DisplayPosition
.Column
+= ColGap
;
2773 FileBuffer
.LowVisibleRange
.Column
= FileBuffer
.FilePosition
.Column
- (FileBuffer
.DisplayPosition
.Column
- 1);
2776 // let CurrentLine point to correct line;
2778 FileBuffer
.CurrentLine
= MoveCurrentLine (RowGap
);
2783 Cut current line out and return a pointer to it.
2785 @param[out] CutLine Upon a successful return pointer to the pointer to
2786 the allocated cut line.
2788 @retval EFI_SUCCESS The cut was successful.
2789 @retval EFI_NOT_FOUND There was no selection to cut.
2790 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2795 OUT EFI_EDITOR_LINE
**CutLine
2798 EFI_EDITOR_LINE
*Line
;
2799 EFI_EDITOR_LINE
*NewLine
;
2803 if (FileBuffer
.ReadOnly
) {
2804 StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2808 Line
= FileBuffer
.CurrentLine
;
2811 // if is the last dummy line, SO CAN not cut
2813 if (StrCmp (Line
->Buffer
, L
"\0") == 0 && Line
->Link
.ForwardLink
== FileBuffer
.ListHead
2819 // LAST LINE AND NOTHING ON THIS LINE, SO CUT NOTHING
2821 StatusBarSetStatusString (L
"Nothing to Cut");
2822 return EFI_NOT_FOUND
;
2825 // if is the last line, so create a dummy line
2827 if (Line
->Link
.ForwardLink
== FileBuffer
.ListHead
) {
2830 // create a new line
2832 NewLine
= FileBufferCreateLine ();
2833 if (NewLine
== NULL
) {
2834 return EFI_OUT_OF_RESOURCES
;
2838 FileBuffer
.NumLines
--;
2839 Row
= FileBuffer
.FilePosition
.Row
;
2844 FileBuffer
.CurrentLine
= CR (
2845 FileBuffer
.CurrentLine
->Link
.ForwardLink
,
2851 RemoveEntryList (&Line
->Link
);
2853 FileBuffer
.Lines
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2855 FileBufferMovePosition (Row
, Col
);
2857 FileBuffer
.FileModified
= TRUE
;
2858 FileBufferNeedRefresh
= TRUE
;
2859 FileBufferOnlyLineNeedRefresh
= FALSE
;
2867 Paste a line into line list.
2869 @retval EFI_SUCCESS The paste was successful.
2870 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
2874 FileBufferPasteLine (
2878 EFI_EDITOR_LINE
*Line
;
2879 EFI_EDITOR_LINE
*NewLine
;
2884 // if nothing is on clip board
2887 if (MainEditor
.CutLine
== NULL
) {
2891 // read only file can not be pasted on
2893 if (FileBuffer
.ReadOnly
) {
2894 StatusBarSetStatusString (L
"Read Only File Can Not Be Modified");
2898 NewLine
= LineDup (MainEditor
.CutLine
);
2899 if (NewLine
== NULL
) {
2900 return EFI_OUT_OF_RESOURCES
;
2903 // insert it above current line
2905 Line
= FileBuffer
.CurrentLine
;
2906 NewLine
->Link
.BackLink
= Line
->Link
.BackLink
;
2907 NewLine
->Link
.ForwardLink
= &Line
->Link
;
2909 Line
->Link
.BackLink
->ForwardLink
= &NewLine
->Link
;
2910 Line
->Link
.BackLink
= &NewLine
->Link
;
2912 FileBuffer
.NumLines
++;
2913 FileBuffer
.CurrentLine
= NewLine
;
2915 FileBuffer
.Lines
= CR (FileBuffer
.ListHead
->ForwardLink
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2921 Row
= FileBuffer
.FilePosition
.Row
;
2923 FileBufferMovePosition (Row
, Col
);
2926 // after paste, set some value so that refresh knows to do something
2928 FileBuffer
.FileModified
= TRUE
;
2929 FileBufferNeedRefresh
= TRUE
;
2930 FileBufferOnlyLineNeedRefresh
= FALSE
;
2936 Search string from current position on in file
2938 @param[in] Str The search string.
2939 @param[in] Offset The offset from current position.
2941 @retval EFI_SUCCESS The operation was successful.
2942 @retval EFI_NOT_FOUND The string Str was not found.
2947 IN CONST CHAR16
*Str
,
2948 IN CONST UINTN Offset
2955 EFI_EDITOR_LINE
*Line
;
2964 // search if in current line
2966 Current
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1 + Offset
;
2968 if (Current
>= (FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.CurrentLine
->Size
)) {
2972 Current
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.CurrentLine
->Size
;
2977 CharPos
= StrStr (Current
, Str
);
2978 if (CharPos
!= NULL
) {
2979 Position
= CharPos
- Current
+ 1;
2987 Column
= (Position
- 1) + FileBuffer
.FilePosition
.Column
+ Offset
;
2988 Row
= FileBuffer
.FilePosition
.Row
;
2991 // not found so find through next lines
2993 Link
= FileBuffer
.CurrentLine
->Link
.ForwardLink
;
2995 Row
= FileBuffer
.FilePosition
.Row
+ 1;
2996 while (Link
!= FileBuffer
.ListHead
) {
2997 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
2998 // Position = StrStr (Line->Buffer, Str);
2999 CharPos
= StrStr (Line
->Buffer
, Str
);
3000 if (CharPos
!= NULL
) {
3001 Position
= CharPos
- Line
->Buffer
+ 1;
3014 Link
= Link
->ForwardLink
;
3017 if (Link
== FileBuffer
.ListHead
) {
3025 return EFI_NOT_FOUND
;
3028 FileBufferMovePosition (Row
, Column
);
3031 // call refresh to fresh edit area,
3032 // because the outer may loop to find multiply occurrence of this string
3034 FileBufferRefresh ();
3040 Replace SearchLen characters from current position on with Replace.
3042 This will modify the current buffer at the current position.
3044 @param[in] Replace The string to replace.
3045 @param[in] SearchLen Search string's length.
3047 @retval EFI_SUCCESS The operation was successful.
3048 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
3053 IN CONST CHAR16
*Replace
,
3054 IN CONST UINTN SearchLen
3064 ReplaceLen
= StrLen (Replace
);
3066 OldSize
= FileBuffer
.CurrentLine
->Size
+ 1;
3068 // include CHAR_NULL
3070 NewSize
= OldSize
+ (ReplaceLen
- SearchLen
);
3072 if (ReplaceLen
> SearchLen
) {
3074 // do not have the enough space
3076 if (FileBuffer
.CurrentLine
->TotalSize
+ 1 <= NewSize
) {
3077 FileBuffer
.CurrentLine
->Buffer
= ReallocatePool (
3080 FileBuffer
.CurrentLine
->Buffer
3082 FileBuffer
.CurrentLine
->TotalSize
= NewSize
- 1;
3085 if (FileBuffer
.CurrentLine
->Buffer
== NULL
) {
3086 return EFI_OUT_OF_RESOURCES
;
3089 // the end CHAR_NULL character;
3091 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ (NewSize
- 1);
3092 Gap
= ReplaceLen
- SearchLen
;
3095 // keep the latter part
3097 for (Index
= 0; Index
< (FileBuffer
.CurrentLine
->Size
- FileBuffer
.FilePosition
.Column
- SearchLen
+ 2); Index
++) {
3098 *Buffer
= *(Buffer
- Gap
);
3102 // set replace into it
3104 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1;
3105 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3106 Buffer
[Index
] = Replace
[Index
];
3110 if (ReplaceLen
< SearchLen
) {
3111 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1;
3113 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3114 Buffer
[Index
] = Replace
[Index
];
3117 Buffer
+= ReplaceLen
;
3118 Gap
= SearchLen
- ReplaceLen
;
3121 // set replace into it
3123 for (Index
= 0; Index
< (FileBuffer
.CurrentLine
->Size
- FileBuffer
.FilePosition
.Column
- ReplaceLen
+ 2); Index
++) {
3124 *Buffer
= *(Buffer
+ Gap
);
3129 if (ReplaceLen
== SearchLen
) {
3130 Buffer
= FileBuffer
.CurrentLine
->Buffer
+ FileBuffer
.FilePosition
.Column
- 1;
3131 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3132 Buffer
[Index
] = Replace
[Index
];
3136 FileBuffer
.CurrentLine
->Size
+= (ReplaceLen
- SearchLen
);
3138 FileBufferOnlyLineNeedRefresh
= TRUE
;
3140 FileBuffer
.FileModified
= TRUE
;
3142 MainTitleBarRefresh (MainEditor
.FileBuffer
->FileName
, MainEditor
.FileBuffer
->FileType
, MainEditor
.FileBuffer
->ReadOnly
, MainEditor
.FileBuffer
->FileModified
, MainEditor
.ScreenSize
.Column
, MainEditor
.ScreenSize
.Row
, 0, 0);
3143 FileBufferRestorePosition ();
3144 FileBufferRefresh ();
3150 Move the mouse cursor position.
3152 @param[in] TextX The new x-coordinate.
3153 @param[in] TextY The new y-coordinate.
3157 FileBufferAdjustMousePosition (
3158 IN CONST INT32 TextX
,
3159 IN CONST INT32 TextY
3168 // TextX and TextY is mouse movement data returned by mouse driver
3169 // This function will change it to MousePosition
3172 // get absolute value
3178 CoordinateX
= FileBuffer
.MousePosition
.Column
;
3179 CoordinateY
= FileBuffer
.MousePosition
.Row
;
3182 CoordinateX
+= TextX
;
3184 if (CoordinateX
>= AbsX
) {
3185 CoordinateX
-= AbsX
;
3192 CoordinateY
+= TextY
;
3194 if (CoordinateY
>= AbsY
) {
3195 CoordinateY
-= AbsY
;
3201 // check whether new mouse column position is beyond screen
3202 // if not, adjust it
3204 if (CoordinateX
>= 1 && CoordinateX
<= MainEditor
.ScreenSize
.Column
) {
3205 FileBuffer
.MousePosition
.Column
= CoordinateX
;
3206 } else if (CoordinateX
< 1) {
3207 FileBuffer
.MousePosition
.Column
= 1;
3208 } else if (CoordinateX
> MainEditor
.ScreenSize
.Column
) {
3209 FileBuffer
.MousePosition
.Column
= MainEditor
.ScreenSize
.Column
;
3212 // check whether new mouse row position is beyond screen
3213 // if not, adjust it
3215 if (CoordinateY
>= 2 && CoordinateY
<= (MainEditor
.ScreenSize
.Row
- 1)) {
3216 FileBuffer
.MousePosition
.Row
= CoordinateY
;
3217 } else if (CoordinateY
< 2) {
3218 FileBuffer
.MousePosition
.Row
= 2;
3219 } else if (CoordinateY
> (MainEditor
.ScreenSize
.Row
- 1)) {
3220 FileBuffer
.MousePosition
.Row
= (MainEditor
.ScreenSize
.Row
- 1);
3226 Search and replace operation.
3228 @param[in] SearchStr The string to search for.
3229 @param[in] ReplaceStr The string to replace with.
3230 @param[in] Offset The column to start at.
3234 FileBufferReplaceAll (
3235 IN CHAR16
*SearchStr
,
3236 IN CHAR16
*ReplaceStr
,
3249 EFI_EDITOR_LINE
*Line
;
3253 SearchLen
= StrLen (SearchStr
);
3254 ReplaceLen
= StrLen (ReplaceStr
);
3256 Column
= FileBuffer
.FilePosition
.Column
+ Offset
- 1;
3258 if (Column
> FileBuffer
.CurrentLine
->Size
) {
3259 Column
= FileBuffer
.CurrentLine
->Size
;
3262 Link
= &(FileBuffer
.CurrentLine
->Link
);
3264 while (Link
!= FileBuffer
.ListHead
) {
3265 Line
= CR (Link
, EFI_EDITOR_LINE
, Link
, LINE_LIST_SIGNATURE
);
3266 CharPos
= StrStr (Line
->Buffer
+ Column
, SearchStr
);
3267 if (CharPos
!= NULL
) {
3268 Position
= CharPos
- Line
->Buffer
;// + Column;
3272 if (ReplaceLen
> SearchLen
) {
3273 OldSize
= Line
->Size
+ 1;
3275 // include CHAR_NULL
3277 NewSize
= OldSize
+ (ReplaceLen
- SearchLen
);
3280 // do not have the enough space
3282 if (Line
->TotalSize
+ 1 <= NewSize
) {
3283 Line
->Buffer
= ReallocatePool (
3288 Line
->TotalSize
= NewSize
- 1;
3291 if (Line
->Buffer
== NULL
) {
3292 return EFI_OUT_OF_RESOURCES
;
3295 // the end CHAR_NULL character;
3297 Buffer
= Line
->Buffer
+ (NewSize
- 1);
3298 Gap
= ReplaceLen
- SearchLen
;
3301 // keep the latter part
3303 for (Index
= 0; Index
< (Line
->Size
- Position
- SearchLen
+ 1); Index
++) {
3304 *Buffer
= *(Buffer
- Gap
);
3308 } else if (ReplaceLen
< SearchLen
){
3309 Buffer
= Line
->Buffer
+ Position
+ ReplaceLen
;
3310 Gap
= SearchLen
- ReplaceLen
;
3312 for (Index
= 0; Index
< (Line
->Size
- Position
- ReplaceLen
+ 1); Index
++) {
3313 *Buffer
= *(Buffer
+ Gap
);
3317 ASSERT(ReplaceLen
== SearchLen
);
3320 // set replace into it
3322 Buffer
= Line
->Buffer
+ Position
;
3323 for (Index
= 0; Index
< ReplaceLen
; Index
++) {
3324 Buffer
[Index
] = ReplaceStr
[Index
];
3327 Line
->Size
+= (ReplaceLen
- SearchLen
);
3328 Column
+= ReplaceLen
;
3334 Link
= Link
->ForwardLink
;
3338 // call refresh to fresh edit area
3340 FileBuffer
.FileModified
= TRUE
;
3341 FileBufferNeedRefresh
= TRUE
;
3342 FileBufferRefresh ();
3348 Set the modified state to TRUE.
3352 FileBufferSetModified (
3356 FileBuffer
.FileModified
= TRUE
;