1 | /** @file
|
---|
2 | Implements filebuffer interface functions.
|
---|
3 |
|
---|
4 | Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
|
---|
5 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
6 |
|
---|
7 | **/
|
---|
8 |
|
---|
9 | #include "TextEditor.h"
|
---|
10 | #include <Guid/FileSystemInfo.h>
|
---|
11 | #include <Library/FileHandleLib.h>
|
---|
12 |
|
---|
13 | EFI_EDITOR_FILE_BUFFER FileBuffer;
|
---|
14 | EFI_EDITOR_FILE_BUFFER FileBufferBackupVar;
|
---|
15 |
|
---|
16 | //
|
---|
17 | // for basic initialization of FileBuffer
|
---|
18 | //
|
---|
19 | EFI_EDITOR_FILE_BUFFER FileBufferConst = {
|
---|
20 | NULL,
|
---|
21 | FileTypeUnicode,
|
---|
22 | NULL,
|
---|
23 | NULL,
|
---|
24 | 0,
|
---|
25 | {
|
---|
26 | 0,
|
---|
27 | 0
|
---|
28 | },
|
---|
29 | {
|
---|
30 | 0,
|
---|
31 | 0
|
---|
32 | },
|
---|
33 | {
|
---|
34 | 0,
|
---|
35 | 0
|
---|
36 | },
|
---|
37 | {
|
---|
38 | 0,
|
---|
39 | 0
|
---|
40 | },
|
---|
41 | FALSE,
|
---|
42 | TRUE,
|
---|
43 | FALSE,
|
---|
44 | NULL
|
---|
45 | };
|
---|
46 |
|
---|
47 | //
|
---|
48 | // the whole edit area needs to be refreshed
|
---|
49 | //
|
---|
50 | BOOLEAN FileBufferNeedRefresh;
|
---|
51 |
|
---|
52 | //
|
---|
53 | // only the current line in edit area needs to be refresh
|
---|
54 | //
|
---|
55 | BOOLEAN FileBufferOnlyLineNeedRefresh;
|
---|
56 |
|
---|
57 | BOOLEAN FileBufferMouseNeedRefresh;
|
---|
58 |
|
---|
59 | extern BOOLEAN EditorMouseAction;
|
---|
60 |
|
---|
61 | /**
|
---|
62 | Initialization function for FileBuffer.
|
---|
63 |
|
---|
64 | @param EFI_SUCCESS The initialization was successful.
|
---|
65 | @param EFI_LOAD_ERROR A default name could not be created.
|
---|
66 | @param EFI_OUT_OF_RESOURCES A memory allocation failed.
|
---|
67 | **/
|
---|
68 | EFI_STATUS
|
---|
69 | FileBufferInit (
|
---|
70 | VOID
|
---|
71 | )
|
---|
72 | {
|
---|
73 | //
|
---|
74 | // basically initialize the FileBuffer
|
---|
75 | //
|
---|
76 | CopyMem (&FileBuffer, &FileBufferConst, sizeof (EFI_EDITOR_FILE_BUFFER));
|
---|
77 | CopyMem (&FileBufferBackupVar, &FileBufferConst, sizeof (EFI_EDITOR_FILE_BUFFER));
|
---|
78 |
|
---|
79 | //
|
---|
80 | // set default FileName
|
---|
81 | //
|
---|
82 | FileBuffer.FileName = EditGetDefaultFileName (L"txt");
|
---|
83 | if (FileBuffer.FileName == NULL) {
|
---|
84 | return EFI_LOAD_ERROR;
|
---|
85 | }
|
---|
86 |
|
---|
87 | FileBuffer.ListHead = AllocateZeroPool (sizeof (LIST_ENTRY));
|
---|
88 | if (FileBuffer.ListHead == NULL) {
|
---|
89 | return EFI_OUT_OF_RESOURCES;
|
---|
90 | }
|
---|
91 |
|
---|
92 | InitializeListHead (FileBuffer.ListHead);
|
---|
93 |
|
---|
94 | FileBuffer.DisplayPosition.Row = 2;
|
---|
95 | FileBuffer.DisplayPosition.Column = 1;
|
---|
96 | FileBuffer.LowVisibleRange.Row = 2;
|
---|
97 | FileBuffer.LowVisibleRange.Column = 1;
|
---|
98 |
|
---|
99 | FileBufferNeedRefresh = FALSE;
|
---|
100 | FileBufferMouseNeedRefresh = FALSE;
|
---|
101 | FileBufferOnlyLineNeedRefresh = FALSE;
|
---|
102 |
|
---|
103 | return EFI_SUCCESS;
|
---|
104 | }
|
---|
105 |
|
---|
106 | /**
|
---|
107 | Backup function for FileBuffer. Only backup the following items:
|
---|
108 | Mouse/Cursor position
|
---|
109 | File Name, Type, ReadOnly, Modified
|
---|
110 | Insert Mode
|
---|
111 |
|
---|
112 | This is for making the file buffer refresh as few as possible.
|
---|
113 |
|
---|
114 | @retval EFI_SUCCESS The backup operation was successful.
|
---|
115 | **/
|
---|
116 | EFI_STATUS
|
---|
117 | FileBufferBackup (
|
---|
118 | VOID
|
---|
119 | )
|
---|
120 | {
|
---|
121 | FileBufferBackupVar.MousePosition = FileBuffer.MousePosition;
|
---|
122 |
|
---|
123 | SHELL_FREE_NON_NULL (FileBufferBackupVar.FileName);
|
---|
124 | FileBufferBackupVar.FileName = NULL;
|
---|
125 | FileBufferBackupVar.FileName = StrnCatGrow (&FileBufferBackupVar.FileName, NULL, FileBuffer.FileName, 0);
|
---|
126 |
|
---|
127 | FileBufferBackupVar.ModeInsert = FileBuffer.ModeInsert;
|
---|
128 | FileBufferBackupVar.FileType = FileBuffer.FileType;
|
---|
129 |
|
---|
130 | FileBufferBackupVar.FilePosition = FileBuffer.FilePosition;
|
---|
131 | FileBufferBackupVar.LowVisibleRange = FileBuffer.LowVisibleRange;
|
---|
132 |
|
---|
133 | FileBufferBackupVar.FileModified = FileBuffer.FileModified;
|
---|
134 | FileBufferBackupVar.ReadOnly = FileBuffer.ReadOnly;
|
---|
135 |
|
---|
136 | return EFI_SUCCESS;
|
---|
137 | }
|
---|
138 |
|
---|
139 | /**
|
---|
140 | Advance to the next Count lines
|
---|
141 |
|
---|
142 | @param[in] Count The line number to advance by.
|
---|
143 | @param[in] CurrentLine The pointer to the current line structure.
|
---|
144 | @param[in] LineList The pointer to the linked list of lines.
|
---|
145 |
|
---|
146 | @retval NULL There was an error.
|
---|
147 | @return The line structure after the advance.
|
---|
148 | **/
|
---|
149 | EFI_EDITOR_LINE *
|
---|
150 | InternalEditorMiscLineAdvance (
|
---|
151 | IN CONST UINTN Count,
|
---|
152 | IN CONST EFI_EDITOR_LINE *CurrentLine,
|
---|
153 | IN CONST LIST_ENTRY *LineList
|
---|
154 | )
|
---|
155 |
|
---|
156 | {
|
---|
157 | UINTN Index;
|
---|
158 | CONST EFI_EDITOR_LINE *Line;
|
---|
159 |
|
---|
160 | if ((CurrentLine == NULL) || (LineList == NULL)) {
|
---|
161 | return NULL;
|
---|
162 | }
|
---|
163 |
|
---|
164 | for (Line = CurrentLine, Index = 0; Index < Count; Index++) {
|
---|
165 | //
|
---|
166 | // if already last line
|
---|
167 | //
|
---|
168 | if (Line->Link.ForwardLink == LineList) {
|
---|
169 | return NULL;
|
---|
170 | }
|
---|
171 |
|
---|
172 | Line = CR (Line->Link.ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
|
---|
173 | }
|
---|
174 |
|
---|
175 | return ((EFI_EDITOR_LINE *)Line);
|
---|
176 | }
|
---|
177 |
|
---|
178 | /**
|
---|
179 | Retreat to the previous Count lines.
|
---|
180 |
|
---|
181 | @param[in] Count The line number to retreat by.
|
---|
182 | @param[in] CurrentLine The pointer to the current line structure.
|
---|
183 | @param[in] LineList The pointer to the linked list of lines.
|
---|
184 |
|
---|
185 | @retval NULL There was an error.
|
---|
186 | @return The line structure after the retreat.
|
---|
187 | **/
|
---|
188 | EFI_EDITOR_LINE *
|
---|
189 | InternalEditorMiscLineRetreat (
|
---|
190 | IN CONST UINTN Count,
|
---|
191 | IN CONST EFI_EDITOR_LINE *CurrentLine,
|
---|
192 | IN CONST LIST_ENTRY *LineList
|
---|
193 | )
|
---|
194 |
|
---|
195 | {
|
---|
196 | UINTN Index;
|
---|
197 | CONST EFI_EDITOR_LINE *Line;
|
---|
198 |
|
---|
199 | if ((CurrentLine == NULL) || (LineList == NULL)) {
|
---|
200 | return NULL;
|
---|
201 | }
|
---|
202 |
|
---|
203 | for (Line = CurrentLine, Index = 0; Index < Count; Index++) {
|
---|
204 | //
|
---|
205 | // already the first line
|
---|
206 | //
|
---|
207 | if (Line->Link.BackLink == LineList) {
|
---|
208 | return NULL;
|
---|
209 | }
|
---|
210 |
|
---|
211 | Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
|
---|
212 | }
|
---|
213 |
|
---|
214 | return ((EFI_EDITOR_LINE *)Line);
|
---|
215 | }
|
---|
216 |
|
---|
217 | /**
|
---|
218 | Advance/Retreat lines
|
---|
219 |
|
---|
220 | @param[in] Count line number to advance/retreat
|
---|
221 | >0 : advance
|
---|
222 | <0 : retreat
|
---|
223 |
|
---|
224 | @retval NULL An error occurred.
|
---|
225 | @return The line after advance/retreat.
|
---|
226 | **/
|
---|
227 | EFI_EDITOR_LINE *
|
---|
228 | MoveLine (
|
---|
229 | IN CONST INTN Count
|
---|
230 | )
|
---|
231 | {
|
---|
232 | EFI_EDITOR_LINE *Line;
|
---|
233 | UINTN AbsCount;
|
---|
234 |
|
---|
235 | //
|
---|
236 | // if < 0, then retreat
|
---|
237 | // if > 0, the advance
|
---|
238 | //
|
---|
239 | if (Count <= 0) {
|
---|
240 | AbsCount = (UINTN)ABS (Count);
|
---|
241 | Line = InternalEditorMiscLineRetreat (AbsCount, MainEditor.FileBuffer->CurrentLine, MainEditor.FileBuffer->ListHead);
|
---|
242 | } else {
|
---|
243 | Line = InternalEditorMiscLineAdvance ((UINTN)Count, MainEditor.FileBuffer->CurrentLine, MainEditor.FileBuffer->ListHead);
|
---|
244 | }
|
---|
245 |
|
---|
246 | return Line;
|
---|
247 | }
|
---|
248 |
|
---|
249 | /**
|
---|
250 | Function to update the 'screen' to display the mouse position.
|
---|
251 |
|
---|
252 | @retval EFI_SUCCESS The backup operation was successful.
|
---|
253 | **/
|
---|
254 | EFI_STATUS
|
---|
255 | FileBufferRestoreMousePosition (
|
---|
256 | VOID
|
---|
257 | )
|
---|
258 | {
|
---|
259 | EFI_EDITOR_COLOR_UNION Orig;
|
---|
260 | EFI_EDITOR_COLOR_UNION New;
|
---|
261 | UINTN FRow;
|
---|
262 | UINTN FColumn;
|
---|
263 | BOOLEAN HasCharacter;
|
---|
264 | EFI_EDITOR_LINE *CurrentLine;
|
---|
265 | EFI_EDITOR_LINE *Line;
|
---|
266 | CHAR16 Value;
|
---|
267 |
|
---|
268 | //
|
---|
269 | // variable initialization
|
---|
270 | //
|
---|
271 | Line = NULL;
|
---|
272 |
|
---|
273 | if (MainEditor.MouseSupported) {
|
---|
274 | if (FileBufferMouseNeedRefresh) {
|
---|
275 | FileBufferMouseNeedRefresh = FALSE;
|
---|
276 |
|
---|
277 | //
|
---|
278 | // if mouse position not moved and only mouse action
|
---|
279 | // so do not need to refresh mouse position
|
---|
280 | //
|
---|
281 | if ( ((FileBuffer.MousePosition.Row == FileBufferBackupVar.MousePosition.Row) &&
|
---|
282 | (FileBuffer.MousePosition.Column == FileBufferBackupVar.MousePosition.Column))
|
---|
283 | && EditorMouseAction)
|
---|
284 | {
|
---|
285 | return EFI_SUCCESS;
|
---|
286 | }
|
---|
287 |
|
---|
288 | //
|
---|
289 | // backup the old screen attributes
|
---|
290 | //
|
---|
291 | Orig = MainEditor.ColorAttributes;
|
---|
292 | New.Data = 0;
|
---|
293 | New.Colors.Foreground = Orig.Colors.Background & 0xF;
|
---|
294 | New.Colors.Background = Orig.Colors.Foreground & 0x7;
|
---|
295 |
|
---|
296 | //
|
---|
297 | // clear the old mouse position
|
---|
298 | //
|
---|
299 | FRow = FileBuffer.LowVisibleRange.Row + FileBufferBackupVar.MousePosition.Row - 2;
|
---|
300 |
|
---|
301 | FColumn = FileBuffer.LowVisibleRange.Column + FileBufferBackupVar.MousePosition.Column - 1;
|
---|
302 |
|
---|
303 | HasCharacter = TRUE;
|
---|
304 | if (FRow > FileBuffer.NumLines) {
|
---|
305 | HasCharacter = FALSE;
|
---|
306 | } else {
|
---|
307 | CurrentLine = FileBuffer.CurrentLine;
|
---|
308 | Line = MoveLine (FRow - FileBuffer.FilePosition.Row);
|
---|
309 |
|
---|
310 | if ((Line == NULL) || (FColumn > Line->Size)) {
|
---|
311 | HasCharacter = FALSE;
|
---|
312 | }
|
---|
313 |
|
---|
314 | FileBuffer.CurrentLine = CurrentLine;
|
---|
315 | }
|
---|
316 |
|
---|
317 | ShellPrintEx (
|
---|
318 | (INT32)FileBufferBackupVar.MousePosition.Column - 1,
|
---|
319 | (INT32)FileBufferBackupVar.MousePosition.Row - 1,
|
---|
320 | L" "
|
---|
321 | );
|
---|
322 |
|
---|
323 | if (HasCharacter) {
|
---|
324 | Value = (Line->Buffer[FColumn - 1]);
|
---|
325 | ShellPrintEx (
|
---|
326 | (INT32)FileBufferBackupVar.MousePosition.Column - 1,
|
---|
327 | (INT32)FileBufferBackupVar.MousePosition.Row - 1,
|
---|
328 | L"%c",
|
---|
329 | Value
|
---|
330 | );
|
---|
331 | }
|
---|
332 |
|
---|
333 | //
|
---|
334 | // set the new mouse position
|
---|
335 | //
|
---|
336 | gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);
|
---|
337 |
|
---|
338 | //
|
---|
339 | // clear the old mouse position
|
---|
340 | //
|
---|
341 | FRow = FileBuffer.LowVisibleRange.Row + FileBuffer.MousePosition.Row - 2;
|
---|
342 | FColumn = FileBuffer.LowVisibleRange.Column + FileBuffer.MousePosition.Column - 1;
|
---|
343 |
|
---|
344 | HasCharacter = TRUE;
|
---|
345 | if (FRow > FileBuffer.NumLines) {
|
---|
346 | HasCharacter = FALSE;
|
---|
347 | } else {
|
---|
348 | CurrentLine = FileBuffer.CurrentLine;
|
---|
349 | Line = MoveLine (FRow - FileBuffer.FilePosition.Row);
|
---|
350 |
|
---|
351 | if ((Line == NULL) || (FColumn > Line->Size)) {
|
---|
352 | HasCharacter = FALSE;
|
---|
353 | }
|
---|
354 |
|
---|
355 | FileBuffer.CurrentLine = CurrentLine;
|
---|
356 | }
|
---|
357 |
|
---|
358 | ShellPrintEx (
|
---|
359 | (INT32)FileBuffer.MousePosition.Column - 1,
|
---|
360 | (INT32)FileBuffer.MousePosition.Row - 1,
|
---|
361 | L" "
|
---|
362 | );
|
---|
363 |
|
---|
364 | if (HasCharacter) {
|
---|
365 | Value = Line->Buffer[FColumn - 1];
|
---|
366 | ShellPrintEx (
|
---|
367 | (INT32)FileBuffer.MousePosition.Column - 1,
|
---|
368 | (INT32)FileBuffer.MousePosition.Row - 1,
|
---|
369 | L"%c",
|
---|
370 | Value
|
---|
371 | );
|
---|
372 | }
|
---|
373 |
|
---|
374 | //
|
---|
375 | // end of HasCharacter
|
---|
376 | //
|
---|
377 | gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
|
---|
378 | }
|
---|
379 |
|
---|
380 | //
|
---|
381 | // end of MouseNeedRefresh
|
---|
382 | //
|
---|
383 | }
|
---|
384 |
|
---|
385 | //
|
---|
386 | // end of MouseSupported
|
---|
387 | //
|
---|
388 | return EFI_SUCCESS;
|
---|
389 | }
|
---|
390 |
|
---|
391 | /**
|
---|
392 | Free all the lines in FileBuffer
|
---|
393 | Fields affected:
|
---|
394 | Lines
|
---|
395 | CurrentLine
|
---|
396 | NumLines
|
---|
397 | ListHead
|
---|
398 |
|
---|
399 | @retval EFI_SUCCESS The operation was successful.
|
---|
400 | **/
|
---|
401 | EFI_STATUS
|
---|
402 | FileBufferFreeLines (
|
---|
403 | VOID
|
---|
404 | )
|
---|
405 | {
|
---|
406 | LIST_ENTRY *Link;
|
---|
407 | EFI_EDITOR_LINE *Line;
|
---|
408 |
|
---|
409 | //
|
---|
410 | // free all the lines
|
---|
411 | //
|
---|
412 | if (FileBuffer.Lines != NULL) {
|
---|
413 | Line = FileBuffer.Lines;
|
---|
414 | Link = &(Line->Link);
|
---|
415 | do {
|
---|
416 | Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
|
---|
417 | Link = Link->ForwardLink;
|
---|
418 |
|
---|
419 | //
|
---|
420 | // free line's buffer and line itself
|
---|
421 | //
|
---|
422 | LineFree (Line);
|
---|
423 | } while (Link != FileBuffer.ListHead);
|
---|
424 | }
|
---|
425 |
|
---|
426 | //
|
---|
427 | // clean the line list related structure
|
---|
428 | //
|
---|
429 | FileBuffer.Lines = NULL;
|
---|
430 | FileBuffer.CurrentLine = NULL;
|
---|
431 | FileBuffer.NumLines = 0;
|
---|
432 |
|
---|
433 | FileBuffer.ListHead->ForwardLink = FileBuffer.ListHead;
|
---|
434 | FileBuffer.ListHead->BackLink = FileBuffer.ListHead;
|
---|
435 |
|
---|
436 | return EFI_SUCCESS;
|
---|
437 | }
|
---|
438 |
|
---|
439 | /**
|
---|
440 | Cleanup function for FileBuffer.
|
---|
441 |
|
---|
442 | @retval EFI_SUCCESS The cleanup was successful.
|
---|
443 | **/
|
---|
444 | EFI_STATUS
|
---|
445 | FileBufferCleanup (
|
---|
446 | VOID
|
---|
447 | )
|
---|
448 | {
|
---|
449 | EFI_STATUS Status;
|
---|
450 |
|
---|
451 | SHELL_FREE_NON_NULL (FileBuffer.FileName);
|
---|
452 |
|
---|
453 | //
|
---|
454 | // free all the lines
|
---|
455 | //
|
---|
456 | Status = FileBufferFreeLines ();
|
---|
457 |
|
---|
458 | SHELL_FREE_NON_NULL (FileBuffer.ListHead);
|
---|
459 | FileBuffer.ListHead = NULL;
|
---|
460 |
|
---|
461 | SHELL_FREE_NON_NULL (FileBufferBackupVar.FileName);
|
---|
462 | return Status;
|
---|
463 | }
|
---|
464 |
|
---|
465 | /**
|
---|
466 | Print a line specified by Line on a row specified by Row of the screen.
|
---|
467 |
|
---|
468 | @param[in] Line The line to print.
|
---|
469 | @param[in] Row The row on the screen to print onto (begin from 1).
|
---|
470 |
|
---|
471 | @retval EFI_SUCCESS The printing was successful.
|
---|
472 | **/
|
---|
473 | EFI_STATUS
|
---|
474 | FileBufferPrintLine (
|
---|
475 | IN CONST EFI_EDITOR_LINE *Line,
|
---|
476 | IN CONST UINTN Row
|
---|
477 | )
|
---|
478 | {
|
---|
479 | CHAR16 *Buffer;
|
---|
480 | UINTN Limit;
|
---|
481 | CHAR16 *PrintLine;
|
---|
482 | CHAR16 *PrintLine2;
|
---|
483 | UINTN BufLen;
|
---|
484 |
|
---|
485 | //
|
---|
486 | // print start from correct character
|
---|
487 | //
|
---|
488 | Buffer = Line->Buffer + FileBuffer.LowVisibleRange.Column - 1;
|
---|
489 |
|
---|
490 | Limit = Line->Size - FileBuffer.LowVisibleRange.Column + 1;
|
---|
491 | if (Limit > Line->Size) {
|
---|
492 | Limit = 0;
|
---|
493 | }
|
---|
494 |
|
---|
495 | BufLen = (MainEditor.ScreenSize.Column + 1) * sizeof (CHAR16);
|
---|
496 | PrintLine = AllocatePool (BufLen);
|
---|
497 | if (PrintLine != NULL) {
|
---|
498 | StrnCpyS (PrintLine, BufLen/sizeof (CHAR16), Buffer, MIN (Limit, MainEditor.ScreenSize.Column));
|
---|
499 | for (Limit = StrLen (PrintLine); Limit < MainEditor.ScreenSize.Column; Limit++) {
|
---|
500 | PrintLine[Limit] = L' ';
|
---|
501 | }
|
---|
502 |
|
---|
503 | PrintLine[MainEditor.ScreenSize.Column] = CHAR_NULL;
|
---|
504 |
|
---|
505 | PrintLine2 = AllocatePool (BufLen * 2);
|
---|
506 | if (PrintLine2 != NULL) {
|
---|
507 | ShellCopySearchAndReplace (PrintLine, PrintLine2, BufLen * 2, L"%", L"^%", FALSE, FALSE);
|
---|
508 |
|
---|
509 | ShellPrintEx (
|
---|
510 | 0,
|
---|
511 | (INT32)Row - 1,
|
---|
512 | L"%s",
|
---|
513 | PrintLine2
|
---|
514 | );
|
---|
515 | FreePool (PrintLine2);
|
---|
516 | }
|
---|
517 |
|
---|
518 | FreePool (PrintLine);
|
---|
519 | }
|
---|
520 |
|
---|
521 | return EFI_SUCCESS;
|
---|
522 | }
|
---|
523 |
|
---|
524 | /**
|
---|
525 | Set the cursor position according to FileBuffer.DisplayPosition.
|
---|
526 |
|
---|
527 | @retval EFI_SUCCESS The operation was successful.
|
---|
528 | **/
|
---|
529 | EFI_STATUS
|
---|
530 | FileBufferRestorePosition (
|
---|
531 | VOID
|
---|
532 | )
|
---|
533 | {
|
---|
534 | //
|
---|
535 | // set cursor position
|
---|
536 | //
|
---|
537 | return (gST->ConOut->SetCursorPosition (
|
---|
538 | gST->ConOut,
|
---|
539 | FileBuffer.DisplayPosition.Column - 1,
|
---|
540 | FileBuffer.DisplayPosition.Row - 1
|
---|
541 | ));
|
---|
542 | }
|
---|
543 |
|
---|
544 | /**
|
---|
545 | Refresh the screen with whats in the buffer.
|
---|
546 |
|
---|
547 | @retval EFI_SUCCESS The refresh was successful.
|
---|
548 | @retval EFI_LOAD_ERROR There was an error finding what to write.
|
---|
549 | **/
|
---|
550 | EFI_STATUS
|
---|
551 | FileBufferRefresh (
|
---|
552 | VOID
|
---|
553 | )
|
---|
554 | {
|
---|
555 | LIST_ENTRY *Link;
|
---|
556 | EFI_EDITOR_LINE *Line;
|
---|
557 | UINTN Row;
|
---|
558 |
|
---|
559 | //
|
---|
560 | // if it's the first time after editor launch, so should refresh
|
---|
561 | //
|
---|
562 | if (!EditorFirst) {
|
---|
563 | //
|
---|
564 | // no definite required refresh
|
---|
565 | // and file position displayed on screen has not been changed
|
---|
566 | //
|
---|
567 | if (!FileBufferNeedRefresh &&
|
---|
568 | !FileBufferOnlyLineNeedRefresh &&
|
---|
569 | (FileBufferBackupVar.LowVisibleRange.Row == FileBuffer.LowVisibleRange.Row) &&
|
---|
570 | (FileBufferBackupVar.LowVisibleRange.Column == FileBuffer.LowVisibleRange.Column)
|
---|
571 | )
|
---|
572 | {
|
---|
573 | FileBufferRestoreMousePosition ();
|
---|
574 | FileBufferRestorePosition ();
|
---|
575 |
|
---|
576 | return EFI_SUCCESS;
|
---|
577 | }
|
---|
578 | }
|
---|
579 |
|
---|
580 | gST->ConOut->EnableCursor (gST->ConOut, FALSE);
|
---|
581 |
|
---|
582 | //
|
---|
583 | // only need to refresh current line
|
---|
584 | //
|
---|
585 | if (FileBufferOnlyLineNeedRefresh &&
|
---|
586 | (FileBufferBackupVar.LowVisibleRange.Row == FileBuffer.LowVisibleRange.Row) &&
|
---|
587 | (FileBufferBackupVar.LowVisibleRange.Column == FileBuffer.LowVisibleRange.Column)
|
---|
588 | )
|
---|
589 | {
|
---|
590 | EditorClearLine (FileBuffer.DisplayPosition.Row, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row);
|
---|
591 | FileBufferPrintLine (
|
---|
592 | FileBuffer.CurrentLine,
|
---|
593 | FileBuffer.DisplayPosition.Row
|
---|
594 | );
|
---|
595 | } else {
|
---|
596 | //
|
---|
597 | // the whole edit area need refresh
|
---|
598 | //
|
---|
599 |
|
---|
600 | //
|
---|
601 | // no line
|
---|
602 | //
|
---|
603 | if (FileBuffer.Lines == NULL) {
|
---|
604 | FileBufferRestoreMousePosition ();
|
---|
605 | FileBufferRestorePosition ();
|
---|
606 | gST->ConOut->EnableCursor (gST->ConOut, TRUE);
|
---|
607 |
|
---|
608 | return EFI_SUCCESS;
|
---|
609 | }
|
---|
610 |
|
---|
611 | //
|
---|
612 | // get the first line that will be displayed
|
---|
613 | //
|
---|
614 | Line = MoveLine (FileBuffer.LowVisibleRange.Row - FileBuffer.FilePosition.Row);
|
---|
615 | if (Line == NULL) {
|
---|
616 | gST->ConOut->EnableCursor (gST->ConOut, TRUE);
|
---|
617 |
|
---|
618 | return EFI_LOAD_ERROR;
|
---|
619 | }
|
---|
620 |
|
---|
621 | Link = &(Line->Link);
|
---|
622 | Row = 2;
|
---|
623 | do {
|
---|
624 | Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
|
---|
625 |
|
---|
626 | //
|
---|
627 | // print line at row
|
---|
628 | //
|
---|
629 | FileBufferPrintLine (Line, Row);
|
---|
630 |
|
---|
631 | Link = Link->ForwardLink;
|
---|
632 | Row++;
|
---|
633 | } while (Link != FileBuffer.ListHead && Row <= (MainEditor.ScreenSize.Row - 1));
|
---|
634 |
|
---|
635 | //
|
---|
636 | // while not file end and not screen full
|
---|
637 | //
|
---|
638 | while (Row <= (MainEditor.ScreenSize.Row - 1)) {
|
---|
639 | EditorClearLine (Row, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row);
|
---|
640 | Row++;
|
---|
641 | }
|
---|
642 | }
|
---|
643 |
|
---|
644 | FileBufferRestoreMousePosition ();
|
---|
645 | FileBufferRestorePosition ();
|
---|
646 |
|
---|
647 | FileBufferNeedRefresh = FALSE;
|
---|
648 | FileBufferOnlyLineNeedRefresh = FALSE;
|
---|
649 |
|
---|
650 | gST->ConOut->EnableCursor (gST->ConOut, TRUE);
|
---|
651 | return EFI_SUCCESS;
|
---|
652 | }
|
---|
653 |
|
---|
654 | /**
|
---|
655 | Create a new line and append it to the line list.
|
---|
656 | Fields affected:
|
---|
657 | NumLines
|
---|
658 | Lines
|
---|
659 |
|
---|
660 | @retval NULL The create line failed.
|
---|
661 | @return The line created.
|
---|
662 | **/
|
---|
663 | EFI_EDITOR_LINE *
|
---|
664 | FileBufferCreateLine (
|
---|
665 | VOID
|
---|
666 | )
|
---|
667 | {
|
---|
668 | EFI_EDITOR_LINE *Line;
|
---|
669 |
|
---|
670 | //
|
---|
671 | // allocate a line structure
|
---|
672 | //
|
---|
673 | Line = AllocateZeroPool (sizeof (EFI_EDITOR_LINE));
|
---|
674 | if (Line == NULL) {
|
---|
675 | return NULL;
|
---|
676 | }
|
---|
677 |
|
---|
678 | //
|
---|
679 | // initialize the structure
|
---|
680 | //
|
---|
681 | Line->Signature = LINE_LIST_SIGNATURE;
|
---|
682 | Line->Size = 0;
|
---|
683 | Line->TotalSize = 0;
|
---|
684 | Line->Type = NewLineTypeDefault;
|
---|
685 |
|
---|
686 | //
|
---|
687 | // initial buffer of the line is "\0"
|
---|
688 | //
|
---|
689 | ASSERT (CHAR_NULL == CHAR_NULL);
|
---|
690 | Line->Buffer = CatSPrint (NULL, L"\0");
|
---|
691 | if (Line->Buffer == NULL) {
|
---|
692 | return NULL;
|
---|
693 | }
|
---|
694 |
|
---|
695 | FileBuffer.NumLines++;
|
---|
696 |
|
---|
697 | //
|
---|
698 | // insert the line into line list
|
---|
699 | //
|
---|
700 | InsertTailList (FileBuffer.ListHead, &Line->Link);
|
---|
701 |
|
---|
702 | if (FileBuffer.Lines == NULL) {
|
---|
703 | FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
|
---|
704 | }
|
---|
705 |
|
---|
706 | return Line;
|
---|
707 | }
|
---|
708 |
|
---|
709 | /**
|
---|
710 | Set FileName field in FileBuffer.
|
---|
711 |
|
---|
712 | @param Str The file name to set.
|
---|
713 |
|
---|
714 | @retval EFI_SUCCESS The filename was successfully set.
|
---|
715 | @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
|
---|
716 | @retval EFI_INVALID_PARAMETER Str is not a valid filename.
|
---|
717 | **/
|
---|
718 | EFI_STATUS
|
---|
719 | FileBufferSetFileName (
|
---|
720 | IN CONST CHAR16 *Str
|
---|
721 | )
|
---|
722 | {
|
---|
723 | //
|
---|
724 | // Verify the parameters
|
---|
725 | //
|
---|
726 | if (!IsValidFileName (Str)) {
|
---|
727 | return (EFI_INVALID_PARAMETER);
|
---|
728 | }
|
---|
729 |
|
---|
730 | //
|
---|
731 | // free the old file name
|
---|
732 | //
|
---|
733 | SHELL_FREE_NON_NULL (FileBuffer.FileName);
|
---|
734 |
|
---|
735 | //
|
---|
736 | // Allocate and set the new name
|
---|
737 | //
|
---|
738 | FileBuffer.FileName = CatSPrint (NULL, L"%s", Str);
|
---|
739 | if (FileBuffer.FileName == NULL) {
|
---|
740 | return EFI_OUT_OF_RESOURCES;
|
---|
741 | }
|
---|
742 |
|
---|
743 | return EFI_SUCCESS;
|
---|
744 | }
|
---|
745 |
|
---|
746 | /**
|
---|
747 | Free the existing file lines and reset the modified flag.
|
---|
748 |
|
---|
749 | @retval EFI_SUCCESS The operation was successful.
|
---|
750 | **/
|
---|
751 | EFI_STATUS
|
---|
752 | FileBufferFree (
|
---|
753 | VOID
|
---|
754 | )
|
---|
755 | {
|
---|
756 | //
|
---|
757 | // free all the lines
|
---|
758 | //
|
---|
759 | FileBufferFreeLines ();
|
---|
760 | FileBuffer.FileModified = FALSE;
|
---|
761 |
|
---|
762 | return EFI_SUCCESS;
|
---|
763 | }
|
---|
764 |
|
---|
765 | /**
|
---|
766 | Read a file from disk into the FileBuffer.
|
---|
767 |
|
---|
768 | @param[in] FileName The filename to read.
|
---|
769 | @param[in] Recover TRUE if is for recover mode, no information printouts.
|
---|
770 |
|
---|
771 | @retval EFI_SUCCESS The load was successful.
|
---|
772 | @retval EFI_LOAD_ERROR The load failed.
|
---|
773 | @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
|
---|
774 | @retval EFI_INVALID_PARAMETER FileName is a directory.
|
---|
775 | **/
|
---|
776 | EFI_STATUS
|
---|
777 | FileBufferRead (
|
---|
778 | IN CONST CHAR16 *FileName,
|
---|
779 | IN CONST BOOLEAN Recover
|
---|
780 | )
|
---|
781 | {
|
---|
782 | EFI_EDITOR_LINE *Line;
|
---|
783 | EE_NEWLINE_TYPE Type;
|
---|
784 | UINTN LoopVar1;
|
---|
785 | UINTN LoopVar2;
|
---|
786 | UINTN LineSize;
|
---|
787 | VOID *Buffer;
|
---|
788 | CHAR16 *UnicodeBuffer;
|
---|
789 | UINT8 *AsciiBuffer;
|
---|
790 | UINTN FileSize;
|
---|
791 | SHELL_FILE_HANDLE FileHandle;
|
---|
792 | BOOLEAN CreateFile;
|
---|
793 | EFI_STATUS Status;
|
---|
794 | UINTN LineSizeBackup;
|
---|
795 | EFI_FILE_INFO *Info;
|
---|
796 |
|
---|
797 | Line = NULL;
|
---|
798 | LoopVar1 = 0;
|
---|
799 | FileSize = 0;
|
---|
800 | UnicodeBuffer = NULL;
|
---|
801 | Type = NewLineTypeDefault;
|
---|
802 | FileHandle = NULL;
|
---|
803 | CreateFile = FALSE;
|
---|
804 |
|
---|
805 | //
|
---|
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
|
---|
812 | //
|
---|
813 |
|
---|
814 | //
|
---|
815 | // try to open the file
|
---|
816 | //
|
---|
817 | Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
|
---|
818 |
|
---|
819 | if (!EFI_ERROR (Status)) {
|
---|
820 | CreateFile = FALSE;
|
---|
821 | if (FileHandle == NULL) {
|
---|
822 | StatusBarSetStatusString (L"Disk Error");
|
---|
823 | return EFI_LOAD_ERROR;
|
---|
824 | }
|
---|
825 |
|
---|
826 | Info = ShellGetFileInfo (FileHandle);
|
---|
827 |
|
---|
828 | if (Info->Attribute & EFI_FILE_DIRECTORY) {
|
---|
829 | StatusBarSetStatusString (L"Directory Can Not Be Edited");
|
---|
830 | FreePool (Info);
|
---|
831 | return EFI_INVALID_PARAMETER;
|
---|
832 | }
|
---|
833 |
|
---|
834 | if (Info->Attribute & EFI_FILE_READ_ONLY) {
|
---|
835 | FileBuffer.ReadOnly = TRUE;
|
---|
836 | } else {
|
---|
837 | FileBuffer.ReadOnly = FALSE;
|
---|
838 | }
|
---|
839 |
|
---|
840 | //
|
---|
841 | // get file size
|
---|
842 | //
|
---|
843 | FileSize = (UINTN)Info->FileSize;
|
---|
844 |
|
---|
845 | FreePool (Info);
|
---|
846 | } else if (Status == EFI_NOT_FOUND) {
|
---|
847 | //
|
---|
848 | // file not exists. add create and try again
|
---|
849 | //
|
---|
850 | Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
|
---|
851 | if (EFI_ERROR (Status)) {
|
---|
852 | if ((Status == EFI_WRITE_PROTECTED) ||
|
---|
853 | (Status == EFI_ACCESS_DENIED) ||
|
---|
854 | (Status == EFI_NO_MEDIA) ||
|
---|
855 | (Status == EFI_MEDIA_CHANGED)
|
---|
856 | )
|
---|
857 | {
|
---|
858 | StatusBarSetStatusString (L"Access Denied");
|
---|
859 | } else if ((Status == EFI_DEVICE_ERROR) || (Status == EFI_VOLUME_CORRUPTED) || (Status == EFI_VOLUME_FULL)) {
|
---|
860 | StatusBarSetStatusString (L"Disk Error");
|
---|
861 | } else {
|
---|
862 | StatusBarSetStatusString (L"Invalid File Name or Current-working-directory");
|
---|
863 | }
|
---|
864 |
|
---|
865 | return Status;
|
---|
866 | } else {
|
---|
867 | //
|
---|
868 | // it worked. now delete it and move on with the name (now validated)
|
---|
869 | //
|
---|
870 | Status = ShellDeleteFile (&FileHandle);
|
---|
871 | if (Status == EFI_WARN_DELETE_FAILURE) {
|
---|
872 | Status = EFI_ACCESS_DENIED;
|
---|
873 | }
|
---|
874 |
|
---|
875 | FileHandle = NULL;
|
---|
876 | if (EFI_ERROR (Status)) {
|
---|
877 | StatusBarSetStatusString (L"Access Denied");
|
---|
878 | return Status;
|
---|
879 | }
|
---|
880 | }
|
---|
881 |
|
---|
882 | //
|
---|
883 | // file doesn't exist, so set CreateFile to TRUE
|
---|
884 | //
|
---|
885 | CreateFile = TRUE;
|
---|
886 | FileBuffer.ReadOnly = FALSE;
|
---|
887 |
|
---|
888 | //
|
---|
889 | // all the check ends
|
---|
890 | // so now begin to set file name, free lines
|
---|
891 | //
|
---|
892 | if (StrCmp (FileName, FileBuffer.FileName) != 0) {
|
---|
893 | FileBufferSetFileName (FileName);
|
---|
894 | }
|
---|
895 |
|
---|
896 | //
|
---|
897 | // free the old lines
|
---|
898 | //
|
---|
899 | FileBufferFree ();
|
---|
900 | }
|
---|
901 |
|
---|
902 | //
|
---|
903 | // the file exists
|
---|
904 | //
|
---|
905 | if (!CreateFile) {
|
---|
906 | //
|
---|
907 | // allocate buffer to read file
|
---|
908 | //
|
---|
909 | Buffer = AllocateZeroPool (FileSize);
|
---|
910 | if (Buffer == NULL) {
|
---|
911 | return EFI_OUT_OF_RESOURCES;
|
---|
912 | }
|
---|
913 |
|
---|
914 | //
|
---|
915 | // read file into Buffer
|
---|
916 | //
|
---|
917 | Status = ShellReadFile (FileHandle, &FileSize, Buffer);
|
---|
918 | ShellCloseFile (&FileHandle);
|
---|
919 | FileHandle = NULL;
|
---|
920 | if (EFI_ERROR (Status)) {
|
---|
921 | StatusBarSetStatusString (L"Read File Failed");
|
---|
922 | SHELL_FREE_NON_NULL (Buffer);
|
---|
923 | return EFI_LOAD_ERROR;
|
---|
924 | }
|
---|
925 |
|
---|
926 | //
|
---|
927 | // nothing in this file
|
---|
928 | //
|
---|
929 | if (FileSize == 0) {
|
---|
930 | SHELL_FREE_NON_NULL (Buffer);
|
---|
931 | //
|
---|
932 | // since has no head, so only can be an ASCII file
|
---|
933 | //
|
---|
934 | FileBuffer.FileType = FileTypeAscii;
|
---|
935 |
|
---|
936 | goto Done;
|
---|
937 | }
|
---|
938 |
|
---|
939 | AsciiBuffer = Buffer;
|
---|
940 |
|
---|
941 | if (FileSize < 2) {
|
---|
942 | //
|
---|
943 | // size < Unicode file header, so only can be ASCII file
|
---|
944 | //
|
---|
945 | FileBuffer.FileType = FileTypeAscii;
|
---|
946 | } else {
|
---|
947 | //
|
---|
948 | // Unicode file
|
---|
949 | //
|
---|
950 | if (*(UINT16 *)Buffer == EFI_UNICODE_BYTE_ORDER_MARK) {
|
---|
951 | //
|
---|
952 | // Unicode file's size should be even
|
---|
953 | //
|
---|
954 | if ((FileSize % 2) != 0) {
|
---|
955 | StatusBarSetStatusString (L"File Format Wrong");
|
---|
956 | SHELL_FREE_NON_NULL (Buffer);
|
---|
957 | return EFI_LOAD_ERROR;
|
---|
958 | }
|
---|
959 |
|
---|
960 | FileSize /= 2;
|
---|
961 |
|
---|
962 | FileBuffer.FileType = FileTypeUnicode;
|
---|
963 | UnicodeBuffer = Buffer;
|
---|
964 |
|
---|
965 | //
|
---|
966 | // pass this 0xff and 0xfe
|
---|
967 | //
|
---|
968 | UnicodeBuffer++;
|
---|
969 | FileSize--;
|
---|
970 | } else {
|
---|
971 | FileBuffer.FileType = FileTypeAscii;
|
---|
972 | }
|
---|
973 |
|
---|
974 | //
|
---|
975 | // end of AsciiBuffer ==
|
---|
976 | //
|
---|
977 | }
|
---|
978 |
|
---|
979 | //
|
---|
980 | // end of FileSize < 2
|
---|
981 | // all the check ends
|
---|
982 | // so now begin to set file name, free lines
|
---|
983 | //
|
---|
984 | if (StrCmp (FileName, FileBuffer.FileName) != 0) {
|
---|
985 | FileBufferSetFileName (FileName);
|
---|
986 | }
|
---|
987 |
|
---|
988 | //
|
---|
989 | // free the old lines
|
---|
990 | //
|
---|
991 | FileBufferFree ();
|
---|
992 |
|
---|
993 | //
|
---|
994 | // parse file content line by line
|
---|
995 | //
|
---|
996 | for (LoopVar1 = 0; LoopVar1 < FileSize; LoopVar1++) {
|
---|
997 | Type = NewLineTypeUnknown;
|
---|
998 |
|
---|
999 | for (LineSize = LoopVar1; LineSize < FileSize; LineSize++) {
|
---|
1000 | if (FileBuffer.FileType == FileTypeAscii) {
|
---|
1001 | if (AsciiBuffer[LineSize] == CHAR_CARRIAGE_RETURN) {
|
---|
1002 | Type = NewLineTypeCarriageReturn;
|
---|
1003 |
|
---|
1004 | //
|
---|
1005 | // has LF following
|
---|
1006 | //
|
---|
1007 | if (LineSize < FileSize - 1) {
|
---|
1008 | if (AsciiBuffer[LineSize + 1] == CHAR_LINEFEED) {
|
---|
1009 | Type = NewLineTypeCarriageReturnLineFeed;
|
---|
1010 | }
|
---|
1011 | }
|
---|
1012 |
|
---|
1013 | break;
|
---|
1014 | } else if (AsciiBuffer[LineSize] == CHAR_LINEFEED) {
|
---|
1015 | Type = NewLineTypeLineFeed;
|
---|
1016 |
|
---|
1017 | //
|
---|
1018 | // has CR following
|
---|
1019 | //
|
---|
1020 | if (LineSize < FileSize - 1) {
|
---|
1021 | if (AsciiBuffer[LineSize + 1] == CHAR_CARRIAGE_RETURN) {
|
---|
1022 | Type = NewLineTypeLineFeedCarriageReturn;
|
---|
1023 | }
|
---|
1024 | }
|
---|
1025 |
|
---|
1026 | break;
|
---|
1027 | }
|
---|
1028 | } else {
|
---|
1029 | if (UnicodeBuffer[LineSize] == CHAR_CARRIAGE_RETURN) {
|
---|
1030 | Type = NewLineTypeCarriageReturn;
|
---|
1031 |
|
---|
1032 | //
|
---|
1033 | // has LF following
|
---|
1034 | //
|
---|
1035 | if (LineSize < FileSize - 1) {
|
---|
1036 | if (UnicodeBuffer[LineSize + 1] == CHAR_LINEFEED) {
|
---|
1037 | Type = NewLineTypeCarriageReturnLineFeed;
|
---|
1038 | }
|
---|
1039 | }
|
---|
1040 |
|
---|
1041 | break;
|
---|
1042 | } else if (UnicodeBuffer[LineSize] == CHAR_LINEFEED) {
|
---|
1043 | Type = NewLineTypeLineFeed;
|
---|
1044 |
|
---|
1045 | //
|
---|
1046 | // has CR following
|
---|
1047 | //
|
---|
1048 | if (LineSize < FileSize - 1) {
|
---|
1049 | if (UnicodeBuffer[LineSize + 1] == CHAR_CARRIAGE_RETURN) {
|
---|
1050 | Type = NewLineTypeLineFeedCarriageReturn;
|
---|
1051 | }
|
---|
1052 | }
|
---|
1053 |
|
---|
1054 | break;
|
---|
1055 | }
|
---|
1056 | }
|
---|
1057 |
|
---|
1058 | //
|
---|
1059 | // endif == ASCII
|
---|
1060 | //
|
---|
1061 | }
|
---|
1062 |
|
---|
1063 | //
|
---|
1064 | // end of for LineSize
|
---|
1065 | //
|
---|
1066 | // if the type is wrong, then exit
|
---|
1067 | //
|
---|
1068 | if (Type == NewLineTypeUnknown) {
|
---|
1069 | //
|
---|
1070 | // Now if Type is NewLineTypeUnknown, it should be file end
|
---|
1071 | //
|
---|
1072 | Type = NewLineTypeDefault;
|
---|
1073 | }
|
---|
1074 |
|
---|
1075 | LineSizeBackup = LineSize;
|
---|
1076 |
|
---|
1077 | //
|
---|
1078 | // create a new line
|
---|
1079 | //
|
---|
1080 | Line = FileBufferCreateLine ();
|
---|
1081 | if (Line == NULL) {
|
---|
1082 | SHELL_FREE_NON_NULL (Buffer);
|
---|
1083 | return EFI_OUT_OF_RESOURCES;
|
---|
1084 | }
|
---|
1085 |
|
---|
1086 | //
|
---|
1087 | // calculate file length
|
---|
1088 | //
|
---|
1089 | LineSize -= LoopVar1;
|
---|
1090 |
|
---|
1091 | //
|
---|
1092 | // Unicode and one CHAR_NULL
|
---|
1093 | //
|
---|
1094 | SHELL_FREE_NON_NULL (Line->Buffer);
|
---|
1095 | Line->Buffer = AllocateZeroPool (LineSize * 2 + 2);
|
---|
1096 |
|
---|
1097 | if (Line->Buffer == NULL) {
|
---|
1098 | RemoveEntryList (&Line->Link);
|
---|
1099 | return EFI_OUT_OF_RESOURCES;
|
---|
1100 | }
|
---|
1101 |
|
---|
1102 | //
|
---|
1103 | // copy this line to Line->Buffer
|
---|
1104 | //
|
---|
1105 | for (LoopVar2 = 0; LoopVar2 < LineSize; LoopVar2++) {
|
---|
1106 | if (FileBuffer.FileType == FileTypeAscii) {
|
---|
1107 | Line->Buffer[LoopVar2] = (CHAR16)AsciiBuffer[LoopVar1];
|
---|
1108 | } else {
|
---|
1109 | Line->Buffer[LoopVar2] = UnicodeBuffer[LoopVar1];
|
---|
1110 | }
|
---|
1111 |
|
---|
1112 | LoopVar1++;
|
---|
1113 | }
|
---|
1114 |
|
---|
1115 | //
|
---|
1116 | // LoopVar1 now points to where CHAR_CARRIAGE_RETURN or CHAR_LINEFEED;
|
---|
1117 | //
|
---|
1118 | Line->Buffer[LineSize] = 0;
|
---|
1119 |
|
---|
1120 | Line->Size = LineSize;
|
---|
1121 | Line->TotalSize = LineSize;
|
---|
1122 | Line->Type = Type;
|
---|
1123 |
|
---|
1124 | if ((Type == NewLineTypeCarriageReturnLineFeed) || (Type == NewLineTypeLineFeedCarriageReturn)) {
|
---|
1125 | LoopVar1++;
|
---|
1126 | }
|
---|
1127 |
|
---|
1128 | //
|
---|
1129 | // last character is a return, SO create a new line
|
---|
1130 | //
|
---|
1131 | if ((((Type == NewLineTypeCarriageReturnLineFeed) || (Type == NewLineTypeLineFeedCarriageReturn)) && (LineSizeBackup == FileSize - 2)) ||
|
---|
1132 | (((Type == NewLineTypeLineFeed) || (Type == NewLineTypeCarriageReturn)) && (LineSizeBackup == FileSize - 1))
|
---|
1133 | )
|
---|
1134 | {
|
---|
1135 | Line = FileBufferCreateLine ();
|
---|
1136 | if (Line == NULL) {
|
---|
1137 | SHELL_FREE_NON_NULL (Buffer);
|
---|
1138 | return EFI_OUT_OF_RESOURCES;
|
---|
1139 | }
|
---|
1140 | }
|
---|
1141 |
|
---|
1142 | //
|
---|
1143 | // end of if
|
---|
1144 | //
|
---|
1145 | }
|
---|
1146 |
|
---|
1147 | //
|
---|
1148 | // end of LoopVar1
|
---|
1149 | //
|
---|
1150 | SHELL_FREE_NON_NULL (Buffer);
|
---|
1151 | }
|
---|
1152 |
|
---|
1153 | //
|
---|
1154 | // end of if CreateFile
|
---|
1155 | //
|
---|
1156 | Done:
|
---|
1157 |
|
---|
1158 | FileBuffer.DisplayPosition.Row = 2;
|
---|
1159 | FileBuffer.DisplayPosition.Column = 1;
|
---|
1160 | FileBuffer.LowVisibleRange.Row = 1;
|
---|
1161 | FileBuffer.LowVisibleRange.Column = 1;
|
---|
1162 | FileBuffer.FilePosition.Row = 1;
|
---|
1163 | FileBuffer.FilePosition.Column = 1;
|
---|
1164 | FileBuffer.MousePosition.Row = 2;
|
---|
1165 | FileBuffer.MousePosition.Column = 1;
|
---|
1166 |
|
---|
1167 | if (!Recover) {
|
---|
1168 | UnicodeBuffer = CatSPrint (NULL, L"%d Lines Read", FileBuffer.NumLines);
|
---|
1169 | if (UnicodeBuffer == NULL) {
|
---|
1170 | return EFI_OUT_OF_RESOURCES;
|
---|
1171 | }
|
---|
1172 |
|
---|
1173 | StatusBarSetStatusString (UnicodeBuffer);
|
---|
1174 | FreePool (UnicodeBuffer);
|
---|
1175 | }
|
---|
1176 |
|
---|
1177 | /*
|
---|
1178 | //
|
---|
1179 | // check whether we have fs?: in filename
|
---|
1180 | //
|
---|
1181 | LoopVar1 = 0;
|
---|
1182 | FSMappingPtr = NULL;
|
---|
1183 | while (FileName[LoopVar1] != 0) {
|
---|
1184 | if (FileName[LoopVar1] == L':') {
|
---|
1185 | FSMappingPtr = &FileName[LoopVar1];
|
---|
1186 | break;
|
---|
1187 | }
|
---|
1188 |
|
---|
1189 | LoopVar1++;
|
---|
1190 | }
|
---|
1191 |
|
---|
1192 | if (FSMappingPtr == NULL) {
|
---|
1193 | CurDir = ShellGetCurrentDir (NULL);
|
---|
1194 | } else {
|
---|
1195 | LoopVar1 = 0;
|
---|
1196 | LoopVar2 = 0;
|
---|
1197 | while (FileName[LoopVar1] != 0) {
|
---|
1198 | if (FileName[LoopVar1] == L':') {
|
---|
1199 | break;
|
---|
1200 | }
|
---|
1201 |
|
---|
1202 | FSMapping[LoopVar2++] = FileName[LoopVar1];
|
---|
1203 |
|
---|
1204 | LoopVar1++;
|
---|
1205 | }
|
---|
1206 |
|
---|
1207 | FSMapping[LoopVar2] = 0;
|
---|
1208 | CurDir = ShellGetCurrentDir (FSMapping);
|
---|
1209 | }
|
---|
1210 |
|
---|
1211 | if (CurDir != NULL) {
|
---|
1212 | for (LoopVar1 = 0; LoopVar1 < StrLen (CurDir) && CurDir[LoopVar1] != ':'; LoopVar1++);
|
---|
1213 |
|
---|
1214 | CurDir[LoopVar1] = 0;
|
---|
1215 | DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) ShellGetMap (CurDir);
|
---|
1216 | FreePool (CurDir);
|
---|
1217 | } else {
|
---|
1218 | return EFI_LOAD_ERROR;
|
---|
1219 | }
|
---|
1220 |
|
---|
1221 | Status = LibDevicePathToInterface (
|
---|
1222 | &gEfiSimpleFileSystemProtocolGuid,
|
---|
1223 | DevicePath,
|
---|
1224 | (VOID **) &Vol
|
---|
1225 | );
|
---|
1226 | if (EFI_ERROR (Status)) {
|
---|
1227 | return EFI_LOAD_ERROR;
|
---|
1228 | }
|
---|
1229 |
|
---|
1230 | Status = Vol->OpenVolume (Vol, &RootFs);
|
---|
1231 | if (EFI_ERROR (Status)) {
|
---|
1232 | return EFI_LOAD_ERROR;
|
---|
1233 | }
|
---|
1234 | //
|
---|
1235 | // Get volume information of file system
|
---|
1236 | //
|
---|
1237 | Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + 100;
|
---|
1238 | VolumeInfo = (EFI_FILE_SYSTEM_INFO *) AllocateZeroPool (Size);
|
---|
1239 | Status = RootFs->GetInfo (RootFs, &gEfiFileSystemInfoGuid, &Size, VolumeInfo);
|
---|
1240 | if (EFI_ERROR (Status)) {
|
---|
1241 | RootFs->Close (RootFs);
|
---|
1242 | return EFI_LOAD_ERROR;
|
---|
1243 | }
|
---|
1244 |
|
---|
1245 | if (VolumeInfo->ReadOnly) {
|
---|
1246 | StatusBarSetStatusString (L"WARNING: Volume Read Only");
|
---|
1247 | }
|
---|
1248 |
|
---|
1249 | FreePool (VolumeInfo);
|
---|
1250 | RootFs->Close (RootFs);
|
---|
1251 | }
|
---|
1252 | //
|
---|
1253 | */
|
---|
1254 | //
|
---|
1255 | // has line
|
---|
1256 | //
|
---|
1257 | if (FileBuffer.Lines != 0) {
|
---|
1258 | FileBuffer.CurrentLine = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
|
---|
1259 | } else {
|
---|
1260 | //
|
---|
1261 | // create a dummy line
|
---|
1262 | //
|
---|
1263 | Line = FileBufferCreateLine ();
|
---|
1264 | if (Line == NULL) {
|
---|
1265 | return EFI_OUT_OF_RESOURCES;
|
---|
1266 | }
|
---|
1267 |
|
---|
1268 | FileBuffer.CurrentLine = Line;
|
---|
1269 | }
|
---|
1270 |
|
---|
1271 | FileBuffer.FileModified = FALSE;
|
---|
1272 | FileBufferNeedRefresh = TRUE;
|
---|
1273 | FileBufferOnlyLineNeedRefresh = FALSE;
|
---|
1274 | FileBufferMouseNeedRefresh = TRUE;
|
---|
1275 |
|
---|
1276 | return EFI_SUCCESS;
|
---|
1277 | }
|
---|
1278 |
|
---|
1279 | /**
|
---|
1280 | According to FileBuffer.NewLineType & FileBuffer.FileType,
|
---|
1281 | get the return buffer and size.
|
---|
1282 |
|
---|
1283 | @param[in] Type The type of line.
|
---|
1284 | @param[out] Buffer The buffer to fill.
|
---|
1285 | @param[out] Size The amount of the buffer used on return.
|
---|
1286 | **/
|
---|
1287 | VOID
|
---|
1288 | GetNewLine (
|
---|
1289 | IN CONST EE_NEWLINE_TYPE Type,
|
---|
1290 | OUT CHAR8 *Buffer,
|
---|
1291 | OUT UINT8 *Size
|
---|
1292 | )
|
---|
1293 | {
|
---|
1294 | UINT8 NewLineSize;
|
---|
1295 |
|
---|
1296 | //
|
---|
1297 | // give new line buffer,
|
---|
1298 | // and will judge unicode or ascii
|
---|
1299 | //
|
---|
1300 | NewLineSize = 0;
|
---|
1301 |
|
---|
1302 | //
|
---|
1303 | // not legal new line type
|
---|
1304 | //
|
---|
1305 | if ((Type != NewLineTypeLineFeed) && (Type != NewLineTypeCarriageReturn) && (Type != NewLineTypeCarriageReturnLineFeed) && (Type != NewLineTypeLineFeedCarriageReturn)) {
|
---|
1306 | *Size = 0;
|
---|
1307 | return;
|
---|
1308 | }
|
---|
1309 |
|
---|
1310 | //
|
---|
1311 | // use_cr: give 0x0d
|
---|
1312 | //
|
---|
1313 | if (Type == NewLineTypeCarriageReturn) {
|
---|
1314 | if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
|
---|
1315 | Buffer[0] = 0x0d;
|
---|
1316 | Buffer[1] = 0;
|
---|
1317 | NewLineSize = 2;
|
---|
1318 | } else {
|
---|
1319 | Buffer[0] = 0x0d;
|
---|
1320 | NewLineSize = 1;
|
---|
1321 | }
|
---|
1322 |
|
---|
1323 | *Size = NewLineSize;
|
---|
1324 | return;
|
---|
1325 | }
|
---|
1326 |
|
---|
1327 | //
|
---|
1328 | // use_lf: give 0x0a
|
---|
1329 | //
|
---|
1330 | if (Type == NewLineTypeLineFeed) {
|
---|
1331 | if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
|
---|
1332 | Buffer[0] = 0x0a;
|
---|
1333 | Buffer[1] = 0;
|
---|
1334 | NewLineSize = 2;
|
---|
1335 | } else {
|
---|
1336 | Buffer[0] = 0x0a;
|
---|
1337 | NewLineSize = 1;
|
---|
1338 | }
|
---|
1339 |
|
---|
1340 | *Size = NewLineSize;
|
---|
1341 | return;
|
---|
1342 | }
|
---|
1343 |
|
---|
1344 | //
|
---|
1345 | // use_crlf: give 0x0d 0x0a
|
---|
1346 | //
|
---|
1347 | if (Type == NewLineTypeCarriageReturnLineFeed) {
|
---|
1348 | if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
|
---|
1349 | Buffer[0] = 0x0d;
|
---|
1350 | Buffer[1] = 0;
|
---|
1351 | Buffer[2] = 0x0a;
|
---|
1352 | Buffer[3] = 0;
|
---|
1353 |
|
---|
1354 | NewLineSize = 4;
|
---|
1355 | } else {
|
---|
1356 | Buffer[0] = 0x0d;
|
---|
1357 | Buffer[1] = 0x0a;
|
---|
1358 | NewLineSize = 2;
|
---|
1359 | }
|
---|
1360 |
|
---|
1361 | *Size = NewLineSize;
|
---|
1362 | return;
|
---|
1363 | }
|
---|
1364 |
|
---|
1365 | //
|
---|
1366 | // use_lfcr: give 0x0a 0x0d
|
---|
1367 | //
|
---|
1368 | if (Type == NewLineTypeLineFeedCarriageReturn) {
|
---|
1369 | if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
|
---|
1370 | Buffer[0] = 0x0a;
|
---|
1371 | Buffer[1] = 0;
|
---|
1372 | Buffer[2] = 0x0d;
|
---|
1373 | Buffer[3] = 0;
|
---|
1374 |
|
---|
1375 | NewLineSize = 4;
|
---|
1376 | } else {
|
---|
1377 | Buffer[0] = 0x0a;
|
---|
1378 | Buffer[1] = 0x0d;
|
---|
1379 | NewLineSize = 2;
|
---|
1380 | }
|
---|
1381 |
|
---|
1382 | *Size = NewLineSize;
|
---|
1383 | return;
|
---|
1384 | }
|
---|
1385 | }
|
---|
1386 |
|
---|
1387 | /**
|
---|
1388 | Change a Unicode string to an ASCII string.
|
---|
1389 |
|
---|
1390 | @param[in] UStr The Unicode string.
|
---|
1391 | @param[in] Length The maximum size of AStr.
|
---|
1392 | @param[out] AStr ASCII string to pass out.
|
---|
1393 |
|
---|
1394 | @return The actuall length.
|
---|
1395 | **/
|
---|
1396 | UINTN
|
---|
1397 | UnicodeToAscii (
|
---|
1398 | IN CONST CHAR16 *UStr,
|
---|
1399 | IN CONST UINTN Length,
|
---|
1400 | OUT CHAR8 *AStr
|
---|
1401 | )
|
---|
1402 | {
|
---|
1403 | UINTN Index;
|
---|
1404 |
|
---|
1405 | //
|
---|
1406 | // just buffer copy, not character copy
|
---|
1407 | //
|
---|
1408 | for (Index = 0; Index < Length; Index++) {
|
---|
1409 | *AStr++ = (CHAR8)*UStr++;
|
---|
1410 | }
|
---|
1411 |
|
---|
1412 | return Index;
|
---|
1413 | }
|
---|
1414 |
|
---|
1415 | /**
|
---|
1416 | Save lines in FileBuffer to disk
|
---|
1417 |
|
---|
1418 | @param[in] FileName The file name for writing.
|
---|
1419 |
|
---|
1420 | @retval EFI_SUCCESS Data was written.
|
---|
1421 | @retval EFI_LOAD_ERROR
|
---|
1422 | @retval EFI_OUT_OF_RESOURCES There were not enough resources to write the file.
|
---|
1423 | **/
|
---|
1424 | EFI_STATUS
|
---|
1425 | FileBufferSave (
|
---|
1426 | IN CONST CHAR16 *FileName
|
---|
1427 | )
|
---|
1428 | {
|
---|
1429 | SHELL_FILE_HANDLE FileHandle;
|
---|
1430 | LIST_ENTRY *Link;
|
---|
1431 | EFI_EDITOR_LINE *Line;
|
---|
1432 | CHAR16 *Str;
|
---|
1433 |
|
---|
1434 | EFI_STATUS Status;
|
---|
1435 | UINTN Length;
|
---|
1436 | UINTN NumLines;
|
---|
1437 | CHAR8 NewLineBuffer[4];
|
---|
1438 | UINT8 NewLineSize;
|
---|
1439 |
|
---|
1440 | EFI_FILE_INFO *Info;
|
---|
1441 |
|
---|
1442 | UINT64 Attribute;
|
---|
1443 |
|
---|
1444 | EE_NEWLINE_TYPE Type;
|
---|
1445 |
|
---|
1446 | UINTN TotalSize;
|
---|
1447 | //
|
---|
1448 | // 2M
|
---|
1449 | //
|
---|
1450 | CHAR8 *Cache;
|
---|
1451 | UINTN LeftSize;
|
---|
1452 | UINTN Size;
|
---|
1453 | CHAR8 *Ptr;
|
---|
1454 |
|
---|
1455 | Length = 0;
|
---|
1456 | //
|
---|
1457 | // 2M
|
---|
1458 | //
|
---|
1459 | TotalSize = 0x200000;
|
---|
1460 |
|
---|
1461 | Attribute = 0;
|
---|
1462 |
|
---|
1463 | //
|
---|
1464 | // if is the old file
|
---|
1465 | //
|
---|
1466 | if ((FileBuffer.FileName != NULL) && (StrCmp (FileName, FileBuffer.FileName) == 0)) {
|
---|
1467 | //
|
---|
1468 | // file has not been modified
|
---|
1469 | //
|
---|
1470 | if (!FileBuffer.FileModified) {
|
---|
1471 | return EFI_SUCCESS;
|
---|
1472 | }
|
---|
1473 |
|
---|
1474 | //
|
---|
1475 | // if file is read-only, set error
|
---|
1476 | //
|
---|
1477 | if (FileBuffer.ReadOnly) {
|
---|
1478 | StatusBarSetStatusString (L"Read Only File Can Not Be Saved");
|
---|
1479 | return EFI_SUCCESS;
|
---|
1480 | }
|
---|
1481 | }
|
---|
1482 |
|
---|
1483 | Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);
|
---|
1484 |
|
---|
1485 | if (!EFI_ERROR (Status)) {
|
---|
1486 | Info = ShellGetFileInfo (FileHandle);
|
---|
1487 |
|
---|
1488 | if ((Info != NULL) && Info->Attribute & EFI_FILE_DIRECTORY) {
|
---|
1489 | StatusBarSetStatusString (L"Directory Can Not Be Saved");
|
---|
1490 | ShellCloseFile (&FileHandle);
|
---|
1491 | FreePool (Info);
|
---|
1492 | return EFI_LOAD_ERROR;
|
---|
1493 | }
|
---|
1494 |
|
---|
1495 | if (Info != NULL) {
|
---|
1496 | Attribute = Info->Attribute & ~EFI_FILE_READ_ONLY;
|
---|
1497 | FreePool (Info);
|
---|
1498 | }
|
---|
1499 |
|
---|
1500 | //
|
---|
1501 | // if file exits, so delete it
|
---|
1502 | //
|
---|
1503 | Status = ShellDeleteFile (&FileHandle);
|
---|
1504 | if (EFI_ERROR (Status) || (Status == EFI_WARN_DELETE_FAILURE)) {
|
---|
1505 | StatusBarSetStatusString (L"Write File Failed");
|
---|
1506 | return EFI_LOAD_ERROR;
|
---|
1507 | }
|
---|
1508 | }
|
---|
1509 |
|
---|
1510 | Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, Attribute);
|
---|
1511 |
|
---|
1512 | if (EFI_ERROR (Status)) {
|
---|
1513 | StatusBarSetStatusString (L"Create File Failed");
|
---|
1514 | return EFI_LOAD_ERROR;
|
---|
1515 | }
|
---|
1516 |
|
---|
1517 | //
|
---|
1518 | // if file is Unicode file, write Unicode header to it.
|
---|
1519 | //
|
---|
1520 | if (FileBuffer.FileType == FileTypeUnicode) {
|
---|
1521 | Length = 2;
|
---|
1522 | Status = ShellWriteFile (FileHandle, &Length, (VOID *)&gUnicodeFileTag);
|
---|
1523 | if (EFI_ERROR (Status)) {
|
---|
1524 | ShellDeleteFile (&FileHandle);
|
---|
1525 | return EFI_LOAD_ERROR;
|
---|
1526 | }
|
---|
1527 | }
|
---|
1528 |
|
---|
1529 | Cache = AllocateZeroPool (TotalSize);
|
---|
1530 | if (Cache == NULL) {
|
---|
1531 | ShellDeleteFile (&FileHandle);
|
---|
1532 | return EFI_OUT_OF_RESOURCES;
|
---|
1533 | }
|
---|
1534 |
|
---|
1535 | //
|
---|
1536 | // write all the lines back to disk
|
---|
1537 | //
|
---|
1538 | NumLines = 0;
|
---|
1539 | Type = NewLineTypeCarriageReturnLineFeed;
|
---|
1540 |
|
---|
1541 | Ptr = Cache;
|
---|
1542 | LeftSize = TotalSize;
|
---|
1543 |
|
---|
1544 | for (Link = FileBuffer.ListHead->ForwardLink; Link != FileBuffer.ListHead; Link = Link->ForwardLink) {
|
---|
1545 | Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
|
---|
1546 |
|
---|
1547 | if (Line->Type != NewLineTypeDefault) {
|
---|
1548 | Type = Line->Type;
|
---|
1549 | }
|
---|
1550 |
|
---|
1551 | //
|
---|
1552 | // newline character is at most 4 bytes ( two Unicode characters )
|
---|
1553 | //
|
---|
1554 | Length = 4;
|
---|
1555 | if ((Line->Buffer != NULL) && (Line->Size != 0)) {
|
---|
1556 | if (FileBuffer.FileType == FileTypeAscii) {
|
---|
1557 | Length += Line->Size;
|
---|
1558 | } else {
|
---|
1559 | Length += (Line->Size * 2);
|
---|
1560 | }
|
---|
1561 |
|
---|
1562 | //
|
---|
1563 | // end if FileTypeAscii
|
---|
1564 | //
|
---|
1565 | }
|
---|
1566 |
|
---|
1567 | //
|
---|
1568 | // no cache room left, so write cache to disk
|
---|
1569 | //
|
---|
1570 | if (LeftSize < Length) {
|
---|
1571 | Size = TotalSize - LeftSize;
|
---|
1572 | Status = ShellWriteFile (FileHandle, &Size, Cache);
|
---|
1573 | if (EFI_ERROR (Status)) {
|
---|
1574 | ShellDeleteFile (&FileHandle);
|
---|
1575 | FreePool (Cache);
|
---|
1576 | return EFI_LOAD_ERROR;
|
---|
1577 | }
|
---|
1578 |
|
---|
1579 | Ptr = Cache;
|
---|
1580 | LeftSize = TotalSize;
|
---|
1581 | }
|
---|
1582 |
|
---|
1583 | if ((Line->Buffer != NULL) && (Line->Size != 0)) {
|
---|
1584 | if (FileBuffer.FileType == FileTypeAscii) {
|
---|
1585 | UnicodeToAscii (Line->Buffer, Line->Size, Ptr);
|
---|
1586 | Length = Line->Size;
|
---|
1587 | } else {
|
---|
1588 | Length = (Line->Size * 2);
|
---|
1589 | CopyMem (Ptr, (CHAR8 *)Line->Buffer, Length);
|
---|
1590 | }
|
---|
1591 |
|
---|
1592 | //
|
---|
1593 | // end if FileTypeAscii
|
---|
1594 | //
|
---|
1595 | Ptr += Length;
|
---|
1596 | LeftSize -= Length;
|
---|
1597 | }
|
---|
1598 |
|
---|
1599 | //
|
---|
1600 | // end of if Line -> Buffer != NULL && Line -> Size != 0
|
---|
1601 | //
|
---|
1602 | // if not the last line , write return buffer to disk
|
---|
1603 | //
|
---|
1604 | if (Link->ForwardLink != FileBuffer.ListHead) {
|
---|
1605 | GetNewLine (Type, NewLineBuffer, &NewLineSize);
|
---|
1606 | CopyMem (Ptr, (CHAR8 *)NewLineBuffer, NewLineSize);
|
---|
1607 |
|
---|
1608 | Ptr += NewLineSize;
|
---|
1609 | LeftSize -= NewLineSize;
|
---|
1610 | }
|
---|
1611 |
|
---|
1612 | NumLines++;
|
---|
1613 | }
|
---|
1614 |
|
---|
1615 | if (TotalSize != LeftSize) {
|
---|
1616 | Size = TotalSize - LeftSize;
|
---|
1617 | Status = ShellWriteFile (FileHandle, &Size, Cache);
|
---|
1618 | if (EFI_ERROR (Status)) {
|
---|
1619 | ShellDeleteFile (&FileHandle);
|
---|
1620 | FreePool (Cache);
|
---|
1621 | return EFI_LOAD_ERROR;
|
---|
1622 | }
|
---|
1623 | }
|
---|
1624 |
|
---|
1625 | FreePool (Cache);
|
---|
1626 |
|
---|
1627 | ShellCloseFile (&FileHandle);
|
---|
1628 |
|
---|
1629 | FileBuffer.FileModified = FALSE;
|
---|
1630 |
|
---|
1631 | //
|
---|
1632 | // set status string
|
---|
1633 | //
|
---|
1634 | Str = CatSPrint (NULL, L"%d Lines Written", NumLines);
|
---|
1635 | if (Str == NULL) {
|
---|
1636 | return EFI_OUT_OF_RESOURCES;
|
---|
1637 | }
|
---|
1638 |
|
---|
1639 | StatusBarSetStatusString (Str);
|
---|
1640 | SHELL_FREE_NON_NULL (Str);
|
---|
1641 |
|
---|
1642 | //
|
---|
1643 | // now everything is ready , you can set the new file name to filebuffer
|
---|
1644 | //
|
---|
1645 | if ((FileName != NULL) && (FileBuffer.FileName != NULL) && (StrCmp (FileName, FileBuffer.FileName) != 0)) {
|
---|
1646 | //
|
---|
1647 | // not the same
|
---|
1648 | //
|
---|
1649 | FileBufferSetFileName (FileName);
|
---|
1650 | if (FileBuffer.FileName == NULL) {
|
---|
1651 | ShellDeleteFile (&FileHandle);
|
---|
1652 | return EFI_OUT_OF_RESOURCES;
|
---|
1653 | }
|
---|
1654 | }
|
---|
1655 |
|
---|
1656 | FileBuffer.ReadOnly = FALSE;
|
---|
1657 | return EFI_SUCCESS;
|
---|
1658 | }
|
---|
1659 |
|
---|
1660 | /**
|
---|
1661 | Scroll cursor to left 1 character position.
|
---|
1662 |
|
---|
1663 | @retval EFI_SUCCESS The operation was successful.
|
---|
1664 | **/
|
---|
1665 | EFI_STATUS
|
---|
1666 | FileBufferScrollLeft (
|
---|
1667 | VOID
|
---|
1668 | )
|
---|
1669 | {
|
---|
1670 | EFI_EDITOR_LINE *Line;
|
---|
1671 | UINTN FRow;
|
---|
1672 | UINTN FCol;
|
---|
1673 |
|
---|
1674 | Line = FileBuffer.CurrentLine;
|
---|
1675 |
|
---|
1676 | FRow = FileBuffer.FilePosition.Row;
|
---|
1677 | FCol = FileBuffer.FilePosition.Column;
|
---|
1678 |
|
---|
1679 | //
|
---|
1680 | // if already at start of this line, so move to the end of previous line
|
---|
1681 | //
|
---|
1682 | if (FCol <= 1) {
|
---|
1683 | //
|
---|
1684 | // has previous line
|
---|
1685 | //
|
---|
1686 | if (Line->Link.BackLink != FileBuffer.ListHead) {
|
---|
1687 | FRow--;
|
---|
1688 | Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
|
---|
1689 | FCol = Line->Size + 1;
|
---|
1690 | } else {
|
---|
1691 | return EFI_SUCCESS;
|
---|
1692 | }
|
---|
1693 | } else {
|
---|
1694 | //
|
---|
1695 | // if not at start of this line, just move to previous column
|
---|
1696 | //
|
---|
1697 | FCol--;
|
---|
1698 | }
|
---|
1699 |
|
---|
1700 | FileBufferMovePosition (FRow, FCol);
|
---|
1701 |
|
---|
1702 | return EFI_SUCCESS;
|
---|
1703 | }
|
---|
1704 |
|
---|
1705 | /**
|
---|
1706 | Delete a char in line
|
---|
1707 |
|
---|
1708 | @param[in, out] Line The line to delete in.
|
---|
1709 | @param[in] Pos Position to delete the char at ( start from 0 ).
|
---|
1710 | **/
|
---|
1711 | VOID
|
---|
1712 | LineDeleteAt (
|
---|
1713 | IN OUT EFI_EDITOR_LINE *Line,
|
---|
1714 | IN UINTN Pos
|
---|
1715 | )
|
---|
1716 | {
|
---|
1717 | UINTN Index;
|
---|
1718 |
|
---|
1719 | //
|
---|
1720 | // move the latter characters front
|
---|
1721 | //
|
---|
1722 | for (Index = Pos - 1; Index < Line->Size; Index++) {
|
---|
1723 | Line->Buffer[Index] = Line->Buffer[Index + 1];
|
---|
1724 | }
|
---|
1725 |
|
---|
1726 | Line->Size--;
|
---|
1727 | }
|
---|
1728 |
|
---|
1729 | /**
|
---|
1730 | Concatenate Src into Dest.
|
---|
1731 |
|
---|
1732 | @param[in, out] Dest Destination string
|
---|
1733 | @param[in] Src Src String.
|
---|
1734 | **/
|
---|
1735 | VOID
|
---|
1736 | LineCat (
|
---|
1737 | IN OUT EFI_EDITOR_LINE *Dest,
|
---|
1738 | IN EFI_EDITOR_LINE *Src
|
---|
1739 | )
|
---|
1740 | {
|
---|
1741 | CHAR16 *Str;
|
---|
1742 | UINTN Size;
|
---|
1743 |
|
---|
1744 | Size = Dest->Size;
|
---|
1745 |
|
---|
1746 | Dest->Buffer[Size] = 0;
|
---|
1747 |
|
---|
1748 | //
|
---|
1749 | // concatenate the two strings
|
---|
1750 | //
|
---|
1751 | Str = CatSPrint (NULL, L"%s%s", Dest->Buffer, Src->Buffer);
|
---|
1752 | if (Str == NULL) {
|
---|
1753 | Dest->Buffer = NULL;
|
---|
1754 | return;
|
---|
1755 | }
|
---|
1756 |
|
---|
1757 | Dest->Size = Size + Src->Size;
|
---|
1758 | Dest->TotalSize = Dest->Size;
|
---|
1759 |
|
---|
1760 | FreePool (Dest->Buffer);
|
---|
1761 | FreePool (Src->Buffer);
|
---|
1762 |
|
---|
1763 | //
|
---|
1764 | // put str to dest->buffer
|
---|
1765 | //
|
---|
1766 | Dest->Buffer = Str;
|
---|
1767 | }
|
---|
1768 |
|
---|
1769 | /**
|
---|
1770 | Delete the previous character.
|
---|
1771 |
|
---|
1772 | @retval EFI_SUCCESS The delete was successful.
|
---|
1773 | @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
|
---|
1774 | **/
|
---|
1775 | EFI_STATUS
|
---|
1776 | FileBufferDoBackspace (
|
---|
1777 | VOID
|
---|
1778 | )
|
---|
1779 | {
|
---|
1780 | EFI_EDITOR_LINE *Line;
|
---|
1781 | EFI_EDITOR_LINE *End;
|
---|
1782 | LIST_ENTRY *Link;
|
---|
1783 | UINTN FileColumn;
|
---|
1784 |
|
---|
1785 | FileColumn = FileBuffer.FilePosition.Column;
|
---|
1786 |
|
---|
1787 | Line = FileBuffer.CurrentLine;
|
---|
1788 |
|
---|
1789 | //
|
---|
1790 | // the first column
|
---|
1791 | //
|
---|
1792 | if (FileColumn == 1) {
|
---|
1793 | //
|
---|
1794 | // the first row
|
---|
1795 | //
|
---|
1796 | if (FileBuffer.FilePosition.Row == 1) {
|
---|
1797 | return EFI_SUCCESS;
|
---|
1798 | }
|
---|
1799 |
|
---|
1800 | FileBufferScrollLeft ();
|
---|
1801 |
|
---|
1802 | Line = FileBuffer.CurrentLine;
|
---|
1803 | Link = Line->Link.ForwardLink;
|
---|
1804 | End = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
|
---|
1805 |
|
---|
1806 | //
|
---|
1807 | // concatenate this line with previous line
|
---|
1808 | //
|
---|
1809 | LineCat (Line, End);
|
---|
1810 | if (Line->Buffer == NULL) {
|
---|
1811 | return EFI_OUT_OF_RESOURCES;
|
---|
1812 | }
|
---|
1813 |
|
---|
1814 | //
|
---|
1815 | // remove End from line list
|
---|
1816 | //
|
---|
1817 | RemoveEntryList (&End->Link);
|
---|
1818 | FreePool (End);
|
---|
1819 |
|
---|
1820 | FileBuffer.NumLines--;
|
---|
1821 |
|
---|
1822 | FileBufferNeedRefresh = TRUE;
|
---|
1823 | FileBufferOnlyLineNeedRefresh = FALSE;
|
---|
1824 | } else {
|
---|
1825 | //
|
---|
1826 | // just delete the previous character
|
---|
1827 | //
|
---|
1828 | LineDeleteAt (Line, FileColumn - 1);
|
---|
1829 | FileBufferScrollLeft ();
|
---|
1830 | FileBufferOnlyLineNeedRefresh = TRUE;
|
---|
1831 | }
|
---|
1832 |
|
---|
1833 | if (!FileBuffer.FileModified) {
|
---|
1834 | FileBuffer.FileModified = TRUE;
|
---|
1835 | }
|
---|
1836 |
|
---|
1837 | return EFI_SUCCESS;
|
---|
1838 | }
|
---|
1839 |
|
---|
1840 | /**
|
---|
1841 | Add a return into line at current position.
|
---|
1842 |
|
---|
1843 | @retval EFI_SUCCESS The insetrion of the character was successful.
|
---|
1844 | @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
|
---|
1845 | **/
|
---|
1846 | EFI_STATUS
|
---|
1847 | FileBufferDoReturn (
|
---|
1848 | VOID
|
---|
1849 | )
|
---|
1850 | {
|
---|
1851 | EFI_EDITOR_LINE *Line;
|
---|
1852 | EFI_EDITOR_LINE *NewLine;
|
---|
1853 | UINTN FileColumn;
|
---|
1854 | UINTN Index;
|
---|
1855 | CHAR16 *Buffer;
|
---|
1856 | UINTN Row;
|
---|
1857 | UINTN Col;
|
---|
1858 |
|
---|
1859 | FileBufferNeedRefresh = TRUE;
|
---|
1860 | FileBufferOnlyLineNeedRefresh = FALSE;
|
---|
1861 |
|
---|
1862 | Line = FileBuffer.CurrentLine;
|
---|
1863 |
|
---|
1864 | FileColumn = FileBuffer.FilePosition.Column;
|
---|
1865 |
|
---|
1866 | NewLine = AllocateZeroPool (sizeof (EFI_EDITOR_LINE));
|
---|
1867 | if (NewLine == NULL) {
|
---|
1868 | return EFI_OUT_OF_RESOURCES;
|
---|
1869 | }
|
---|
1870 |
|
---|
1871 | NewLine->Signature = LINE_LIST_SIGNATURE;
|
---|
1872 | NewLine->Size = Line->Size - FileColumn + 1;
|
---|
1873 | NewLine->TotalSize = NewLine->Size;
|
---|
1874 | NewLine->Buffer = CatSPrint (NULL, L"\0");
|
---|
1875 | if (NewLine->Buffer == NULL) {
|
---|
1876 | return EFI_OUT_OF_RESOURCES;
|
---|
1877 | }
|
---|
1878 |
|
---|
1879 | NewLine->Type = NewLineTypeDefault;
|
---|
1880 |
|
---|
1881 | if (NewLine->Size > 0) {
|
---|
1882 | //
|
---|
1883 | // UNICODE + CHAR_NULL
|
---|
1884 | //
|
---|
1885 | Buffer = AllocateZeroPool (2 * (NewLine->Size + 1));
|
---|
1886 | if (Buffer == NULL) {
|
---|
1887 | FreePool (NewLine->Buffer);
|
---|
1888 | FreePool (NewLine);
|
---|
1889 | return EFI_OUT_OF_RESOURCES;
|
---|
1890 | }
|
---|
1891 |
|
---|
1892 | FreePool (NewLine->Buffer);
|
---|
1893 |
|
---|
1894 | NewLine->Buffer = Buffer;
|
---|
1895 |
|
---|
1896 | for (Index = 0; Index < NewLine->Size; Index++) {
|
---|
1897 | NewLine->Buffer[Index] = Line->Buffer[Index + FileColumn - 1];
|
---|
1898 | }
|
---|
1899 |
|
---|
1900 | NewLine->Buffer[NewLine->Size] = CHAR_NULL;
|
---|
1901 |
|
---|
1902 | Line->Buffer[FileColumn - 1] = CHAR_NULL;
|
---|
1903 | Line->Size = FileColumn - 1;
|
---|
1904 | }
|
---|
1905 |
|
---|
1906 | //
|
---|
1907 | // increase NumLines
|
---|
1908 | //
|
---|
1909 | FileBuffer.NumLines++;
|
---|
1910 |
|
---|
1911 | //
|
---|
1912 | // insert it into the correct position of line list
|
---|
1913 | //
|
---|
1914 | NewLine->Link.BackLink = &(Line->Link);
|
---|
1915 | NewLine->Link.ForwardLink = Line->Link.ForwardLink;
|
---|
1916 | Line->Link.ForwardLink->BackLink = &(NewLine->Link);
|
---|
1917 | Line->Link.ForwardLink = &(NewLine->Link);
|
---|
1918 |
|
---|
1919 | //
|
---|
1920 | // move cursor to the start of next line
|
---|
1921 | //
|
---|
1922 | Row = FileBuffer.FilePosition.Row + 1;
|
---|
1923 | Col = 1;
|
---|
1924 |
|
---|
1925 | FileBufferMovePosition (Row, Col);
|
---|
1926 |
|
---|
1927 | //
|
---|
1928 | // set file is modified
|
---|
1929 | //
|
---|
1930 | if (!FileBuffer.FileModified) {
|
---|
1931 | FileBuffer.FileModified = TRUE;
|
---|
1932 | }
|
---|
1933 |
|
---|
1934 | return EFI_SUCCESS;
|
---|
1935 | }
|
---|
1936 |
|
---|
1937 | /**
|
---|
1938 | Delete current character from current line. This is the effect caused
|
---|
1939 | by the 'del' key.
|
---|
1940 |
|
---|
1941 | @retval EFI_SUCCESS
|
---|
1942 | **/
|
---|
1943 | EFI_STATUS
|
---|
1944 | FileBufferDoDelete (
|
---|
1945 | VOID
|
---|
1946 | )
|
---|
1947 | {
|
---|
1948 | EFI_EDITOR_LINE *Line;
|
---|
1949 | EFI_EDITOR_LINE *Next;
|
---|
1950 | LIST_ENTRY *Link;
|
---|
1951 | UINTN FileColumn;
|
---|
1952 |
|
---|
1953 | Line = FileBuffer.CurrentLine;
|
---|
1954 | FileColumn = FileBuffer.FilePosition.Column;
|
---|
1955 |
|
---|
1956 | //
|
---|
1957 | // the last column
|
---|
1958 | //
|
---|
1959 | if (FileColumn >= Line->Size + 1) {
|
---|
1960 | //
|
---|
1961 | // the last line
|
---|
1962 | //
|
---|
1963 | if (Line->Link.ForwardLink == FileBuffer.ListHead) {
|
---|
1964 | return EFI_SUCCESS;
|
---|
1965 | }
|
---|
1966 |
|
---|
1967 | //
|
---|
1968 | // since last character,
|
---|
1969 | // so will add the next line to this line
|
---|
1970 | //
|
---|
1971 | Link = Line->Link.ForwardLink;
|
---|
1972 | Next = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
|
---|
1973 | LineCat (Line, Next);
|
---|
1974 | if (Line->Buffer == NULL) {
|
---|
1975 | return EFI_OUT_OF_RESOURCES;
|
---|
1976 | }
|
---|
1977 |
|
---|
1978 | RemoveEntryList (&Next->Link);
|
---|
1979 | FreePool (Next);
|
---|
1980 |
|
---|
1981 | FileBuffer.NumLines--;
|
---|
1982 |
|
---|
1983 | FileBufferNeedRefresh = TRUE;
|
---|
1984 | FileBufferOnlyLineNeedRefresh = FALSE;
|
---|
1985 | } else {
|
---|
1986 | //
|
---|
1987 | // just delete current character
|
---|
1988 | //
|
---|
1989 | LineDeleteAt (Line, FileColumn);
|
---|
1990 | FileBufferOnlyLineNeedRefresh = TRUE;
|
---|
1991 | }
|
---|
1992 |
|
---|
1993 | if (!FileBuffer.FileModified) {
|
---|
1994 | FileBuffer.FileModified = TRUE;
|
---|
1995 | }
|
---|
1996 |
|
---|
1997 | return EFI_SUCCESS;
|
---|
1998 | }
|
---|
1999 |
|
---|
2000 | /**
|
---|
2001 | Scroll cursor to right 1 character.
|
---|
2002 |
|
---|
2003 | @retval EFI_SUCCESS The operation was successful.
|
---|
2004 | **/
|
---|
2005 | EFI_STATUS
|
---|
2006 | FileBufferScrollRight (
|
---|
2007 | VOID
|
---|
2008 | )
|
---|
2009 | {
|
---|
2010 | EFI_EDITOR_LINE *Line;
|
---|
2011 | UINTN FRow;
|
---|
2012 | UINTN FCol;
|
---|
2013 |
|
---|
2014 | Line = FileBuffer.CurrentLine;
|
---|
2015 | if (Line->Buffer == NULL) {
|
---|
2016 | return EFI_SUCCESS;
|
---|
2017 | }
|
---|
2018 |
|
---|
2019 | FRow = FileBuffer.FilePosition.Row;
|
---|
2020 | FCol = FileBuffer.FilePosition.Column;
|
---|
2021 |
|
---|
2022 | //
|
---|
2023 | // if already at end of this line, scroll it to the start of next line
|
---|
2024 | //
|
---|
2025 | if (FCol > Line->Size) {
|
---|
2026 | //
|
---|
2027 | // has next line
|
---|
2028 | //
|
---|
2029 | if (Line->Link.ForwardLink != FileBuffer.ListHead) {
|
---|
2030 | FRow++;
|
---|
2031 | FCol = 1;
|
---|
2032 | } else {
|
---|
2033 | return EFI_SUCCESS;
|
---|
2034 | }
|
---|
2035 | } else {
|
---|
2036 | //
|
---|
2037 | // if not at end of this line, just move to next column
|
---|
2038 | //
|
---|
2039 | FCol++;
|
---|
2040 | }
|
---|
2041 |
|
---|
2042 | FileBufferMovePosition (FRow, FCol);
|
---|
2043 |
|
---|
2044 | return EFI_SUCCESS;
|
---|
2045 | }
|
---|
2046 |
|
---|
2047 | /**
|
---|
2048 | Insert a char into line
|
---|
2049 |
|
---|
2050 |
|
---|
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.
|
---|
2055 |
|
---|
2056 | @return The new string size ( include CHAR_NULL ) ( unit is Unicode character ).
|
---|
2057 | **/
|
---|
2058 | UINTN
|
---|
2059 | LineStrInsert (
|
---|
2060 | IN EFI_EDITOR_LINE *Line,
|
---|
2061 | IN CHAR16 Char,
|
---|
2062 | IN UINTN Pos,
|
---|
2063 | IN UINTN StrSize
|
---|
2064 | )
|
---|
2065 | {
|
---|
2066 | UINTN Index;
|
---|
2067 | CHAR16 *TempStringPtr;
|
---|
2068 | CHAR16 *Str;
|
---|
2069 |
|
---|
2070 | Index = (StrSize) * 2;
|
---|
2071 |
|
---|
2072 | Str = Line->Buffer;
|
---|
2073 |
|
---|
2074 | //
|
---|
2075 | // do not have free space
|
---|
2076 | //
|
---|
2077 | if (Line->TotalSize <= Line->Size) {
|
---|
2078 | Str = ReallocatePool (Index, Index + 16, Str);
|
---|
2079 | if (Str == NULL) {
|
---|
2080 | return 0;
|
---|
2081 | }
|
---|
2082 |
|
---|
2083 | Line->TotalSize += 8;
|
---|
2084 | }
|
---|
2085 |
|
---|
2086 | //
|
---|
2087 | // move the later part of the string one character right
|
---|
2088 | //
|
---|
2089 | TempStringPtr = Str;
|
---|
2090 | for (Index = StrSize; Index > Pos; Index--) {
|
---|
2091 | TempStringPtr[Index] = TempStringPtr[Index - 1];
|
---|
2092 | }
|
---|
2093 |
|
---|
2094 | //
|
---|
2095 | // insert char into it.
|
---|
2096 | //
|
---|
2097 | TempStringPtr[Index] = Char;
|
---|
2098 |
|
---|
2099 | Line->Buffer = Str;
|
---|
2100 | Line->Size++;
|
---|
2101 |
|
---|
2102 | return StrSize + 1;
|
---|
2103 | }
|
---|
2104 |
|
---|
2105 | /**
|
---|
2106 | Add a character to the current line.
|
---|
2107 |
|
---|
2108 | @param[in] Char The Character to input.
|
---|
2109 |
|
---|
2110 | @retval EFI_SUCCESS The input was succesful.
|
---|
2111 | **/
|
---|
2112 | EFI_STATUS
|
---|
2113 | FileBufferAddChar (
|
---|
2114 | IN CHAR16 Char
|
---|
2115 | )
|
---|
2116 | {
|
---|
2117 | EFI_EDITOR_LINE *Line;
|
---|
2118 | UINTN FilePos;
|
---|
2119 |
|
---|
2120 | Line = FileBuffer.CurrentLine;
|
---|
2121 |
|
---|
2122 | //
|
---|
2123 | // only needs to refresh current line
|
---|
2124 | //
|
---|
2125 | FileBufferOnlyLineNeedRefresh = TRUE;
|
---|
2126 |
|
---|
2127 | //
|
---|
2128 | // when is insert mode, or cursor is at end of this line,
|
---|
2129 | // so insert this character
|
---|
2130 | // or replace the character.
|
---|
2131 | //
|
---|
2132 | FilePos = FileBuffer.FilePosition.Column - 1;
|
---|
2133 | if (FileBuffer.ModeInsert || (FilePos + 1 > Line->Size)) {
|
---|
2134 | LineStrInsert (Line, Char, FilePos, Line->Size + 1);
|
---|
2135 | } else {
|
---|
2136 | Line->Buffer[FilePos] = Char;
|
---|
2137 | }
|
---|
2138 |
|
---|
2139 | //
|
---|
2140 | // move cursor to right
|
---|
2141 | //
|
---|
2142 | FileBufferScrollRight ();
|
---|
2143 |
|
---|
2144 | if (!FileBuffer.FileModified) {
|
---|
2145 | FileBuffer.FileModified = TRUE;
|
---|
2146 | }
|
---|
2147 |
|
---|
2148 | return EFI_SUCCESS;
|
---|
2149 | }
|
---|
2150 |
|
---|
2151 | /**
|
---|
2152 | Handles inputs from characters (ASCII key + Backspace + return)
|
---|
2153 |
|
---|
2154 | @param[in] Char The input character.
|
---|
2155 |
|
---|
2156 | @retval EFI_SUCCESS The operation was successful.
|
---|
2157 | @retval EFI_LOAD_ERROR There was an error.
|
---|
2158 | @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
|
---|
2159 | **/
|
---|
2160 | EFI_STATUS
|
---|
2161 | FileBufferDoCharInput (
|
---|
2162 | IN CONST CHAR16 Char
|
---|
2163 | )
|
---|
2164 | {
|
---|
2165 | EFI_STATUS Status;
|
---|
2166 |
|
---|
2167 | Status = EFI_SUCCESS;
|
---|
2168 |
|
---|
2169 | switch (Char) {
|
---|
2170 | case CHAR_NULL:
|
---|
2171 | break;
|
---|
2172 |
|
---|
2173 | case CHAR_BACKSPACE:
|
---|
2174 | Status = FileBufferDoBackspace ();
|
---|
2175 | break;
|
---|
2176 |
|
---|
2177 | case CHAR_TAB:
|
---|
2178 | //
|
---|
2179 | // Tabs are ignored
|
---|
2180 | //
|
---|
2181 | break;
|
---|
2182 |
|
---|
2183 | case CHAR_LINEFEED:
|
---|
2184 | case CHAR_CARRIAGE_RETURN:
|
---|
2185 | Status = FileBufferDoReturn ();
|
---|
2186 | break;
|
---|
2187 |
|
---|
2188 | default:
|
---|
2189 | //
|
---|
2190 | // DEAL WITH ASCII CHAR, filter out thing like ctrl+f
|
---|
2191 | //
|
---|
2192 | if ((Char > 127) || (Char < 32)) {
|
---|
2193 | Status = StatusBarSetStatusString (L"Unknown Command");
|
---|
2194 | } else {
|
---|
2195 | Status = FileBufferAddChar (Char);
|
---|
2196 | }
|
---|
2197 |
|
---|
2198 | break;
|
---|
2199 | }
|
---|
2200 |
|
---|
2201 | return Status;
|
---|
2202 | }
|
---|
2203 |
|
---|
2204 | /**
|
---|
2205 | Scroll cursor to the next line.
|
---|
2206 |
|
---|
2207 | @retval EFI_SUCCESS The operation was successful.
|
---|
2208 | **/
|
---|
2209 | EFI_STATUS
|
---|
2210 | FileBufferScrollDown (
|
---|
2211 | VOID
|
---|
2212 | )
|
---|
2213 | {
|
---|
2214 | EFI_EDITOR_LINE *Line;
|
---|
2215 | UINTN FRow;
|
---|
2216 | UINTN FCol;
|
---|
2217 |
|
---|
2218 | Line = FileBuffer.CurrentLine;
|
---|
2219 | if (Line->Buffer == NULL) {
|
---|
2220 | return EFI_SUCCESS;
|
---|
2221 | }
|
---|
2222 |
|
---|
2223 | FRow = FileBuffer.FilePosition.Row;
|
---|
2224 | FCol = FileBuffer.FilePosition.Column;
|
---|
2225 |
|
---|
2226 | //
|
---|
2227 | // has next line
|
---|
2228 | //
|
---|
2229 | if (Line->Link.ForwardLink != FileBuffer.ListHead) {
|
---|
2230 | FRow++;
|
---|
2231 | Line = CR (Line->Link.ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
|
---|
2232 |
|
---|
2233 | //
|
---|
2234 | // if the next line is not that long, so move to end of next line
|
---|
2235 | //
|
---|
2236 | if (FCol > Line->Size) {
|
---|
2237 | FCol = Line->Size + 1;
|
---|
2238 | }
|
---|
2239 | } else {
|
---|
2240 | return EFI_SUCCESS;
|
---|
2241 | }
|
---|
2242 |
|
---|
2243 | FileBufferMovePosition (FRow, FCol);
|
---|
2244 |
|
---|
2245 | return EFI_SUCCESS;
|
---|
2246 | }
|
---|
2247 |
|
---|
2248 | /**
|
---|
2249 | Scroll the cursor to previous line.
|
---|
2250 |
|
---|
2251 | @retval EFI_SUCCESS The operation was successful.
|
---|
2252 | **/
|
---|
2253 | EFI_STATUS
|
---|
2254 | FileBufferScrollUp (
|
---|
2255 | VOID
|
---|
2256 | )
|
---|
2257 | {
|
---|
2258 | EFI_EDITOR_LINE *Line;
|
---|
2259 | UINTN FRow;
|
---|
2260 | UINTN FCol;
|
---|
2261 |
|
---|
2262 | Line = FileBuffer.CurrentLine;
|
---|
2263 |
|
---|
2264 | FRow = FileBuffer.FilePosition.Row;
|
---|
2265 | FCol = FileBuffer.FilePosition.Column;
|
---|
2266 |
|
---|
2267 | //
|
---|
2268 | // has previous line
|
---|
2269 | //
|
---|
2270 | if (Line->Link.BackLink != FileBuffer.ListHead) {
|
---|
2271 | FRow--;
|
---|
2272 | Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
|
---|
2273 |
|
---|
2274 | //
|
---|
2275 | // if previous line is not that long, so move to the end of previous line
|
---|
2276 | //
|
---|
2277 | if (FCol > Line->Size) {
|
---|
2278 | FCol = Line->Size + 1;
|
---|
2279 | }
|
---|
2280 | } else {
|
---|
2281 | return EFI_SUCCESS;
|
---|
2282 | }
|
---|
2283 |
|
---|
2284 | FileBufferMovePosition (FRow, FCol);
|
---|
2285 |
|
---|
2286 | return EFI_SUCCESS;
|
---|
2287 | }
|
---|
2288 |
|
---|
2289 | /**
|
---|
2290 | Scroll cursor to next page.
|
---|
2291 |
|
---|
2292 | @retval EFI_SUCCESS The operation wa successful.
|
---|
2293 | **/
|
---|
2294 | EFI_STATUS
|
---|
2295 | FileBufferPageDown (
|
---|
2296 | VOID
|
---|
2297 | )
|
---|
2298 | {
|
---|
2299 | EFI_EDITOR_LINE *Line;
|
---|
2300 | UINTN FRow;
|
---|
2301 | UINTN FCol;
|
---|
2302 | UINTN Gap;
|
---|
2303 |
|
---|
2304 | Line = FileBuffer.CurrentLine;
|
---|
2305 |
|
---|
2306 | FRow = FileBuffer.FilePosition.Row;
|
---|
2307 | FCol = FileBuffer.FilePosition.Column;
|
---|
2308 |
|
---|
2309 | //
|
---|
2310 | // has next page
|
---|
2311 | //
|
---|
2312 | if (FileBuffer.NumLines >= FRow + (MainEditor.ScreenSize.Row - 2)) {
|
---|
2313 | Gap = (MainEditor.ScreenSize.Row - 2);
|
---|
2314 | } else {
|
---|
2315 | //
|
---|
2316 | // MOVE CURSOR TO LAST LINE
|
---|
2317 | //
|
---|
2318 | Gap = FileBuffer.NumLines - FRow;
|
---|
2319 | }
|
---|
2320 |
|
---|
2321 | //
|
---|
2322 | // get correct line
|
---|
2323 | //
|
---|
2324 | Line = MoveLine (Gap);
|
---|
2325 |
|
---|
2326 | //
|
---|
2327 | // if that line, is not that long, so move to the end of that line
|
---|
2328 | //
|
---|
2329 | if ((Line != NULL) && (FCol > Line->Size)) {
|
---|
2330 | FCol = Line->Size + 1;
|
---|
2331 | }
|
---|
2332 |
|
---|
2333 | FRow += Gap;
|
---|
2334 |
|
---|
2335 | FileBufferMovePosition (FRow, FCol);
|
---|
2336 |
|
---|
2337 | return EFI_SUCCESS;
|
---|
2338 | }
|
---|
2339 |
|
---|
2340 | /**
|
---|
2341 | Scroll cursor to previous screen.
|
---|
2342 |
|
---|
2343 | @retval EFI_SUCCESS The operation was successful.
|
---|
2344 | **/
|
---|
2345 | EFI_STATUS
|
---|
2346 | FileBufferPageUp (
|
---|
2347 | VOID
|
---|
2348 | )
|
---|
2349 | {
|
---|
2350 | EFI_EDITOR_LINE *Line;
|
---|
2351 | UINTN FRow;
|
---|
2352 | UINTN FCol;
|
---|
2353 | UINTN Gap;
|
---|
2354 | INTN Retreat;
|
---|
2355 |
|
---|
2356 | Line = FileBuffer.CurrentLine;
|
---|
2357 |
|
---|
2358 | FRow = FileBuffer.FilePosition.Row;
|
---|
2359 | FCol = FileBuffer.FilePosition.Column;
|
---|
2360 |
|
---|
2361 | //
|
---|
2362 | // has previous page
|
---|
2363 | //
|
---|
2364 | if (FRow > (MainEditor.ScreenSize.Row - 2)) {
|
---|
2365 | Gap = (MainEditor.ScreenSize.Row - 2);
|
---|
2366 | } else {
|
---|
2367 | //
|
---|
2368 | // the first line of file will displayed on the first line of screen
|
---|
2369 | //
|
---|
2370 | Gap = FRow - 1;
|
---|
2371 | }
|
---|
2372 |
|
---|
2373 | Retreat = Gap;
|
---|
2374 | Retreat = -Retreat;
|
---|
2375 |
|
---|
2376 | //
|
---|
2377 | // get correct line
|
---|
2378 | //
|
---|
2379 | Line = MoveLine (Retreat);
|
---|
2380 |
|
---|
2381 | //
|
---|
2382 | // if that line is not that long, so move to the end of that line
|
---|
2383 | //
|
---|
2384 | if ((Line != NULL) && (FCol > Line->Size)) {
|
---|
2385 | FCol = Line->Size + 1;
|
---|
2386 | }
|
---|
2387 |
|
---|
2388 | FRow -= Gap;
|
---|
2389 |
|
---|
2390 | FileBufferMovePosition (FRow, FCol);
|
---|
2391 |
|
---|
2392 | return EFI_SUCCESS;
|
---|
2393 | }
|
---|
2394 |
|
---|
2395 | /**
|
---|
2396 | Scroll cursor to end of the current line.
|
---|
2397 |
|
---|
2398 | @retval EFI_SUCCESS The operation was successful.
|
---|
2399 | **/
|
---|
2400 | EFI_STATUS
|
---|
2401 | FileBufferEnd (
|
---|
2402 | VOID
|
---|
2403 | )
|
---|
2404 | {
|
---|
2405 | EFI_EDITOR_LINE *Line;
|
---|
2406 | UINTN FRow;
|
---|
2407 | UINTN FCol;
|
---|
2408 |
|
---|
2409 | Line = FileBuffer.CurrentLine;
|
---|
2410 |
|
---|
2411 | FRow = FileBuffer.FilePosition.Row;
|
---|
2412 |
|
---|
2413 | //
|
---|
2414 | // goto the last column of the line
|
---|
2415 | //
|
---|
2416 | FCol = Line->Size + 1;
|
---|
2417 |
|
---|
2418 | FileBufferMovePosition (FRow, FCol);
|
---|
2419 |
|
---|
2420 | return EFI_SUCCESS;
|
---|
2421 | }
|
---|
2422 |
|
---|
2423 | /**
|
---|
2424 | Dispatch input to different handler
|
---|
2425 | @param[in] Key The input key. One of:
|
---|
2426 | ASCII KEY
|
---|
2427 | Backspace/Delete
|
---|
2428 | Return
|
---|
2429 | Direction key: up/down/left/right/pgup/pgdn
|
---|
2430 | Home/End
|
---|
2431 | INS
|
---|
2432 |
|
---|
2433 | @retval EFI_SUCCESS The dispatch was done successfully.
|
---|
2434 | @retval EFI_LOAD_ERROR The dispatch was not successful.
|
---|
2435 | @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
|
---|
2436 | **/
|
---|
2437 | EFI_STATUS
|
---|
2438 | FileBufferHandleInput (
|
---|
2439 | IN CONST EFI_INPUT_KEY *Key
|
---|
2440 | )
|
---|
2441 | {
|
---|
2442 | EFI_STATUS Status;
|
---|
2443 |
|
---|
2444 | Status = EFI_SUCCESS;
|
---|
2445 |
|
---|
2446 | switch (Key->ScanCode) {
|
---|
2447 | //
|
---|
2448 | // ordinary key input
|
---|
2449 | //
|
---|
2450 | case SCAN_NULL:
|
---|
2451 | if (!FileBuffer.ReadOnly) {
|
---|
2452 | Status = FileBufferDoCharInput (Key->UnicodeChar);
|
---|
2453 | } else {
|
---|
2454 | Status = StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
|
---|
2455 | }
|
---|
2456 |
|
---|
2457 | break;
|
---|
2458 |
|
---|
2459 | //
|
---|
2460 | // up arrow
|
---|
2461 | //
|
---|
2462 | case SCAN_UP:
|
---|
2463 | Status = FileBufferScrollUp ();
|
---|
2464 | break;
|
---|
2465 |
|
---|
2466 | //
|
---|
2467 | // down arrow
|
---|
2468 | //
|
---|
2469 | case SCAN_DOWN:
|
---|
2470 | Status = FileBufferScrollDown ();
|
---|
2471 | break;
|
---|
2472 |
|
---|
2473 | //
|
---|
2474 | // right arrow
|
---|
2475 | //
|
---|
2476 | case SCAN_RIGHT:
|
---|
2477 | Status = FileBufferScrollRight ();
|
---|
2478 | break;
|
---|
2479 |
|
---|
2480 | //
|
---|
2481 | // left arrow
|
---|
2482 | //
|
---|
2483 | case SCAN_LEFT:
|
---|
2484 | Status = FileBufferScrollLeft ();
|
---|
2485 | break;
|
---|
2486 |
|
---|
2487 | //
|
---|
2488 | // page up
|
---|
2489 | //
|
---|
2490 | case SCAN_PAGE_UP:
|
---|
2491 | Status = FileBufferPageUp ();
|
---|
2492 | break;
|
---|
2493 |
|
---|
2494 | //
|
---|
2495 | // page down
|
---|
2496 | //
|
---|
2497 | case SCAN_PAGE_DOWN:
|
---|
2498 | Status = FileBufferPageDown ();
|
---|
2499 | break;
|
---|
2500 |
|
---|
2501 | //
|
---|
2502 | // delete
|
---|
2503 | //
|
---|
2504 | case SCAN_DELETE:
|
---|
2505 | if (!FileBuffer.ReadOnly) {
|
---|
2506 | Status = FileBufferDoDelete ();
|
---|
2507 | } else {
|
---|
2508 | Status = StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
|
---|
2509 | }
|
---|
2510 |
|
---|
2511 | break;
|
---|
2512 |
|
---|
2513 | //
|
---|
2514 | // home
|
---|
2515 | //
|
---|
2516 | case SCAN_HOME:
|
---|
2517 | FileBufferMovePosition (FileBuffer.FilePosition.Row, 1);
|
---|
2518 | Status = EFI_SUCCESS;
|
---|
2519 | break;
|
---|
2520 |
|
---|
2521 | //
|
---|
2522 | // end
|
---|
2523 | //
|
---|
2524 | case SCAN_END:
|
---|
2525 | Status = FileBufferEnd ();
|
---|
2526 | break;
|
---|
2527 |
|
---|
2528 | //
|
---|
2529 | // insert
|
---|
2530 | //
|
---|
2531 | case SCAN_INSERT:
|
---|
2532 | FileBuffer.ModeInsert = (BOOLEAN) !FileBuffer.ModeInsert;
|
---|
2533 | Status = EFI_SUCCESS;
|
---|
2534 | break;
|
---|
2535 |
|
---|
2536 | default:
|
---|
2537 | Status = StatusBarSetStatusString (L"Unknown Command");
|
---|
2538 | break;
|
---|
2539 | }
|
---|
2540 |
|
---|
2541 | return Status;
|
---|
2542 | }
|
---|
2543 |
|
---|
2544 | /**
|
---|
2545 | Check user specified FileRow is above current screen.
|
---|
2546 |
|
---|
2547 | @param[in] FileRow The row of file position ( start from 1 ).
|
---|
2548 |
|
---|
2549 | @retval TRUE It is above the current screen.
|
---|
2550 | @retval FALSE It is not above the current screen.
|
---|
2551 | **/
|
---|
2552 | BOOLEAN
|
---|
2553 | AboveCurrentScreen (
|
---|
2554 | IN UINTN FileRow
|
---|
2555 | )
|
---|
2556 | {
|
---|
2557 | //
|
---|
2558 | // if is to the above of the screen
|
---|
2559 | //
|
---|
2560 | if (FileRow < FileBuffer.LowVisibleRange.Row) {
|
---|
2561 | return TRUE;
|
---|
2562 | }
|
---|
2563 |
|
---|
2564 | return FALSE;
|
---|
2565 | }
|
---|
2566 |
|
---|
2567 | /**
|
---|
2568 | Check user specified FileRow is under current screen.
|
---|
2569 |
|
---|
2570 | @param[in] FileRow The row of file position ( start from 1 ).
|
---|
2571 |
|
---|
2572 | @retval TRUE It is under the current screen.
|
---|
2573 | @retval FALSE It is not under the current screen.
|
---|
2574 | **/
|
---|
2575 | BOOLEAN
|
---|
2576 | UnderCurrentScreen (
|
---|
2577 | IN UINTN FileRow
|
---|
2578 | )
|
---|
2579 | {
|
---|
2580 | //
|
---|
2581 | // if is to the under of the screen
|
---|
2582 | //
|
---|
2583 | if (FileRow > FileBuffer.LowVisibleRange.Row + (MainEditor.ScreenSize.Row - 2) - 1) {
|
---|
2584 | return TRUE;
|
---|
2585 | }
|
---|
2586 |
|
---|
2587 | return FALSE;
|
---|
2588 | }
|
---|
2589 |
|
---|
2590 | /**
|
---|
2591 | Check user specified FileCol is left to current screen.
|
---|
2592 |
|
---|
2593 | @param[in] FileCol The column of file position ( start from 1 ).
|
---|
2594 |
|
---|
2595 | @retval TRUE It is to the left.
|
---|
2596 | @retval FALSE It is not to the left.
|
---|
2597 | **/
|
---|
2598 | BOOLEAN
|
---|
2599 | LeftCurrentScreen (
|
---|
2600 | IN UINTN FileCol
|
---|
2601 | )
|
---|
2602 | {
|
---|
2603 | //
|
---|
2604 | // if is to the left of the screen
|
---|
2605 | //
|
---|
2606 | if (FileCol < FileBuffer.LowVisibleRange.Column) {
|
---|
2607 | return TRUE;
|
---|
2608 | }
|
---|
2609 |
|
---|
2610 | return FALSE;
|
---|
2611 | }
|
---|
2612 |
|
---|
2613 | /**
|
---|
2614 | Check user specified FileCol is right to current screen.
|
---|
2615 |
|
---|
2616 | @param[in] FileCol The column of file position ( start from 1 ).
|
---|
2617 |
|
---|
2618 | @retval TRUE It is to the right.
|
---|
2619 | @retval FALSE It is not to the right.
|
---|
2620 | **/
|
---|
2621 | BOOLEAN
|
---|
2622 | RightCurrentScreen (
|
---|
2623 | IN UINTN FileCol
|
---|
2624 | )
|
---|
2625 | {
|
---|
2626 | //
|
---|
2627 | // if is to the right of the screen
|
---|
2628 | //
|
---|
2629 | if (FileCol > FileBuffer.LowVisibleRange.Column + MainEditor.ScreenSize.Column - 1) {
|
---|
2630 | return TRUE;
|
---|
2631 | }
|
---|
2632 |
|
---|
2633 | return FALSE;
|
---|
2634 | }
|
---|
2635 |
|
---|
2636 | /**
|
---|
2637 | Advance/Retreat lines and set CurrentLine in FileBuffer to it
|
---|
2638 |
|
---|
2639 | @param[in] Count The line number to advance/retreat
|
---|
2640 | >0 : advance
|
---|
2641 | <0: retreat
|
---|
2642 |
|
---|
2643 | @retval NULL An error occurred.
|
---|
2644 | @return The line after advance/retreat.
|
---|
2645 | **/
|
---|
2646 | EFI_EDITOR_LINE *
|
---|
2647 | MoveCurrentLine (
|
---|
2648 | IN INTN Count
|
---|
2649 | )
|
---|
2650 | {
|
---|
2651 | EFI_EDITOR_LINE *Line;
|
---|
2652 | UINTN AbsCount;
|
---|
2653 |
|
---|
2654 | if (Count <= 0) {
|
---|
2655 | AbsCount = (UINTN)ABS (Count);
|
---|
2656 | Line = InternalEditorMiscLineRetreat (AbsCount, MainEditor.FileBuffer->CurrentLine, MainEditor.FileBuffer->ListHead);
|
---|
2657 | } else {
|
---|
2658 | Line = InternalEditorMiscLineAdvance ((UINTN)Count, MainEditor.FileBuffer->CurrentLine, MainEditor.FileBuffer->ListHead);
|
---|
2659 | }
|
---|
2660 |
|
---|
2661 | if (Line == NULL) {
|
---|
2662 | return NULL;
|
---|
2663 | }
|
---|
2664 |
|
---|
2665 | MainEditor.FileBuffer->CurrentLine = Line;
|
---|
2666 |
|
---|
2667 | return Line;
|
---|
2668 | }
|
---|
2669 |
|
---|
2670 | /**
|
---|
2671 | According to cursor's file position, adjust screen display
|
---|
2672 |
|
---|
2673 | @param[in] NewFilePosRow The row of file position ( start from 1 ).
|
---|
2674 | @param[in] NewFilePosCol The column of file position ( start from 1 ).
|
---|
2675 | **/
|
---|
2676 | VOID
|
---|
2677 | FileBufferMovePosition (
|
---|
2678 | IN CONST UINTN NewFilePosRow,
|
---|
2679 | IN CONST UINTN NewFilePosCol
|
---|
2680 | )
|
---|
2681 | {
|
---|
2682 | INTN RowGap;
|
---|
2683 | INTN ColGap;
|
---|
2684 | UINTN Abs;
|
---|
2685 | BOOLEAN Above;
|
---|
2686 | BOOLEAN Under;
|
---|
2687 | BOOLEAN Right;
|
---|
2688 | BOOLEAN Left;
|
---|
2689 |
|
---|
2690 | //
|
---|
2691 | // CALCULATE gap between current file position and new file position
|
---|
2692 | //
|
---|
2693 | RowGap = NewFilePosRow - FileBuffer.FilePosition.Row;
|
---|
2694 | ColGap = NewFilePosCol - FileBuffer.FilePosition.Column;
|
---|
2695 |
|
---|
2696 | Under = UnderCurrentScreen (NewFilePosRow);
|
---|
2697 | Above = AboveCurrentScreen (NewFilePosRow);
|
---|
2698 | //
|
---|
2699 | // if is below current screen
|
---|
2700 | //
|
---|
2701 | if (Under) {
|
---|
2702 | //
|
---|
2703 | // display row will be unchanged
|
---|
2704 | //
|
---|
2705 | FileBuffer.FilePosition.Row = NewFilePosRow;
|
---|
2706 | } else {
|
---|
2707 | if (Above) {
|
---|
2708 | //
|
---|
2709 | // has enough above line, so display row unchanged
|
---|
2710 | // not has enough above lines, so the first line is at the
|
---|
2711 | // first display line
|
---|
2712 | //
|
---|
2713 | if (NewFilePosRow < (FileBuffer.DisplayPosition.Row - 1)) {
|
---|
2714 | FileBuffer.DisplayPosition.Row = NewFilePosRow + 1;
|
---|
2715 | }
|
---|
2716 |
|
---|
2717 | FileBuffer.FilePosition.Row = NewFilePosRow;
|
---|
2718 | } else {
|
---|
2719 | //
|
---|
2720 | // in current screen
|
---|
2721 | //
|
---|
2722 | FileBuffer.FilePosition.Row = NewFilePosRow;
|
---|
2723 | if (RowGap < 0) {
|
---|
2724 | Abs = (UINTN)ABS (RowGap);
|
---|
2725 | FileBuffer.DisplayPosition.Row -= Abs;
|
---|
2726 | } else {
|
---|
2727 | FileBuffer.DisplayPosition.Row += RowGap;
|
---|
2728 | }
|
---|
2729 | }
|
---|
2730 | }
|
---|
2731 |
|
---|
2732 | FileBuffer.LowVisibleRange.Row = FileBuffer.FilePosition.Row - (FileBuffer.DisplayPosition.Row - 2);
|
---|
2733 |
|
---|
2734 | Right = RightCurrentScreen (NewFilePosCol);
|
---|
2735 | Left = LeftCurrentScreen (NewFilePosCol);
|
---|
2736 |
|
---|
2737 | //
|
---|
2738 | // if right to current screen
|
---|
2739 | //
|
---|
2740 | if (Right) {
|
---|
2741 | //
|
---|
2742 | // display column will be changed to end
|
---|
2743 | //
|
---|
2744 | FileBuffer.DisplayPosition.Column = MainEditor.ScreenSize.Column;
|
---|
2745 | FileBuffer.FilePosition.Column = NewFilePosCol;
|
---|
2746 | } else {
|
---|
2747 | if (Left) {
|
---|
2748 | //
|
---|
2749 | // has enough left characters , so display row unchanged
|
---|
2750 | // not has enough left characters,
|
---|
2751 | // so the first character is at the first display column
|
---|
2752 | //
|
---|
2753 | if (NewFilePosCol < (FileBuffer.DisplayPosition.Column)) {
|
---|
2754 | FileBuffer.DisplayPosition.Column = NewFilePosCol;
|
---|
2755 | }
|
---|
2756 |
|
---|
2757 | FileBuffer.FilePosition.Column = NewFilePosCol;
|
---|
2758 | } else {
|
---|
2759 | //
|
---|
2760 | // in current screen
|
---|
2761 | //
|
---|
2762 | FileBuffer.FilePosition.Column = NewFilePosCol;
|
---|
2763 | if (ColGap < 0) {
|
---|
2764 | Abs = (UINTN)(-ColGap);
|
---|
2765 | FileBuffer.DisplayPosition.Column -= Abs;
|
---|
2766 | } else {
|
---|
2767 | FileBuffer.DisplayPosition.Column += ColGap;
|
---|
2768 | }
|
---|
2769 | }
|
---|
2770 | }
|
---|
2771 |
|
---|
2772 | FileBuffer.LowVisibleRange.Column = FileBuffer.FilePosition.Column - (FileBuffer.DisplayPosition.Column - 1);
|
---|
2773 |
|
---|
2774 | //
|
---|
2775 | // let CurrentLine point to correct line;
|
---|
2776 | //
|
---|
2777 | FileBuffer.CurrentLine = MoveCurrentLine (RowGap);
|
---|
2778 | }
|
---|
2779 |
|
---|
2780 | /**
|
---|
2781 | Cut current line out and return a pointer to it.
|
---|
2782 |
|
---|
2783 | @param[out] CutLine Upon a successful return pointer to the pointer to
|
---|
2784 | the allocated cut line.
|
---|
2785 |
|
---|
2786 | @retval EFI_SUCCESS The cut was successful.
|
---|
2787 | @retval EFI_NOT_FOUND There was no selection to cut.
|
---|
2788 | @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
|
---|
2789 | **/
|
---|
2790 | EFI_STATUS
|
---|
2791 | FileBufferCutLine (
|
---|
2792 | OUT EFI_EDITOR_LINE **CutLine
|
---|
2793 | )
|
---|
2794 | {
|
---|
2795 | EFI_EDITOR_LINE *Line;
|
---|
2796 | EFI_EDITOR_LINE *NewLine;
|
---|
2797 | UINTN Row;
|
---|
2798 | UINTN Col;
|
---|
2799 |
|
---|
2800 | *CutLine = NULL;
|
---|
2801 |
|
---|
2802 | if (FileBuffer.ReadOnly) {
|
---|
2803 | StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
|
---|
2804 | return EFI_SUCCESS;
|
---|
2805 | }
|
---|
2806 |
|
---|
2807 | Line = FileBuffer.CurrentLine;
|
---|
2808 |
|
---|
2809 | //
|
---|
2810 | // if is the last dummy line, SO CAN not cut
|
---|
2811 | //
|
---|
2812 | if ((StrCmp (Line->Buffer, L"\0") == 0) && (Line->Link.ForwardLink == FileBuffer.ListHead)
|
---|
2813 | //
|
---|
2814 | // last line
|
---|
2815 | //
|
---|
2816 | )
|
---|
2817 | {
|
---|
2818 | //
|
---|
2819 | // LAST LINE AND NOTHING ON THIS LINE, SO CUT NOTHING
|
---|
2820 | //
|
---|
2821 | StatusBarSetStatusString (L"Nothing to Cut");
|
---|
2822 | return EFI_NOT_FOUND;
|
---|
2823 | }
|
---|
2824 |
|
---|
2825 | //
|
---|
2826 | // if is the last line, so create a dummy line
|
---|
2827 | //
|
---|
2828 | if (Line->Link.ForwardLink == FileBuffer.ListHead) {
|
---|
2829 | //
|
---|
2830 | // last line
|
---|
2831 | // create a new line
|
---|
2832 | //
|
---|
2833 | NewLine = FileBufferCreateLine ();
|
---|
2834 | if (NewLine == NULL) {
|
---|
2835 | return EFI_OUT_OF_RESOURCES;
|
---|
2836 | }
|
---|
2837 | }
|
---|
2838 |
|
---|
2839 | FileBuffer.NumLines--;
|
---|
2840 | Row = FileBuffer.FilePosition.Row;
|
---|
2841 | Col = 1;
|
---|
2842 | //
|
---|
2843 | // move home
|
---|
2844 | //
|
---|
2845 | FileBuffer.CurrentLine = CR (
|
---|
2846 | FileBuffer.CurrentLine->Link.ForwardLink,
|
---|
2847 | EFI_EDITOR_LINE,
|
---|
2848 | Link,
|
---|
2849 | LINE_LIST_SIGNATURE
|
---|
2850 | );
|
---|
2851 |
|
---|
2852 | RemoveEntryList (&Line->Link);
|
---|
2853 |
|
---|
2854 | FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
|
---|
2855 |
|
---|
2856 | FileBufferMovePosition (Row, Col);
|
---|
2857 |
|
---|
2858 | FileBuffer.FileModified = TRUE;
|
---|
2859 | FileBufferNeedRefresh = TRUE;
|
---|
2860 | FileBufferOnlyLineNeedRefresh = FALSE;
|
---|
2861 |
|
---|
2862 | *CutLine = Line;
|
---|
2863 |
|
---|
2864 | return EFI_SUCCESS;
|
---|
2865 | }
|
---|
2866 |
|
---|
2867 | /**
|
---|
2868 | Paste a line into line list.
|
---|
2869 |
|
---|
2870 | @retval EFI_SUCCESS The paste was successful.
|
---|
2871 | @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
|
---|
2872 | **/
|
---|
2873 | EFI_STATUS
|
---|
2874 | FileBufferPasteLine (
|
---|
2875 | VOID
|
---|
2876 | )
|
---|
2877 | {
|
---|
2878 | EFI_EDITOR_LINE *Line;
|
---|
2879 | EFI_EDITOR_LINE *NewLine;
|
---|
2880 | UINTN Row;
|
---|
2881 | UINTN Col;
|
---|
2882 |
|
---|
2883 | //
|
---|
2884 | // if nothing is on clip board
|
---|
2885 | // then do nothing
|
---|
2886 | //
|
---|
2887 | if (MainEditor.CutLine == NULL) {
|
---|
2888 | return EFI_SUCCESS;
|
---|
2889 | }
|
---|
2890 |
|
---|
2891 | //
|
---|
2892 | // read only file can not be pasted on
|
---|
2893 | //
|
---|
2894 | if (FileBuffer.ReadOnly) {
|
---|
2895 | StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
|
---|
2896 | return EFI_SUCCESS;
|
---|
2897 | }
|
---|
2898 |
|
---|
2899 | NewLine = LineDup (MainEditor.CutLine);
|
---|
2900 | if (NewLine == NULL) {
|
---|
2901 | return EFI_OUT_OF_RESOURCES;
|
---|
2902 | }
|
---|
2903 |
|
---|
2904 | //
|
---|
2905 | // insert it above current line
|
---|
2906 | //
|
---|
2907 | Line = FileBuffer.CurrentLine;
|
---|
2908 | NewLine->Link.BackLink = Line->Link.BackLink;
|
---|
2909 | NewLine->Link.ForwardLink = &Line->Link;
|
---|
2910 |
|
---|
2911 | Line->Link.BackLink->ForwardLink = &NewLine->Link;
|
---|
2912 | Line->Link.BackLink = &NewLine->Link;
|
---|
2913 |
|
---|
2914 | FileBuffer.NumLines++;
|
---|
2915 | FileBuffer.CurrentLine = NewLine;
|
---|
2916 |
|
---|
2917 | FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
|
---|
2918 |
|
---|
2919 | Col = 1;
|
---|
2920 | //
|
---|
2921 | // move home
|
---|
2922 | //
|
---|
2923 | Row = FileBuffer.FilePosition.Row;
|
---|
2924 |
|
---|
2925 | FileBufferMovePosition (Row, Col);
|
---|
2926 |
|
---|
2927 | //
|
---|
2928 | // after paste, set some value so that refresh knows to do something
|
---|
2929 | //
|
---|
2930 | FileBuffer.FileModified = TRUE;
|
---|
2931 | FileBufferNeedRefresh = TRUE;
|
---|
2932 | FileBufferOnlyLineNeedRefresh = FALSE;
|
---|
2933 |
|
---|
2934 | return EFI_SUCCESS;
|
---|
2935 | }
|
---|
2936 |
|
---|
2937 | /**
|
---|
2938 | Search string from current position on in file
|
---|
2939 |
|
---|
2940 | @param[in] Str The search string.
|
---|
2941 | @param[in] Offset The offset from current position.
|
---|
2942 |
|
---|
2943 | @retval EFI_SUCCESS The operation was successful.
|
---|
2944 | @retval EFI_NOT_FOUND The string Str was not found.
|
---|
2945 | **/
|
---|
2946 | EFI_STATUS
|
---|
2947 | FileBufferSearch (
|
---|
2948 | IN CONST CHAR16 *Str,
|
---|
2949 | IN CONST UINTN Offset
|
---|
2950 | )
|
---|
2951 | {
|
---|
2952 | CHAR16 *Current;
|
---|
2953 | UINTN Position;
|
---|
2954 | UINTN Row;
|
---|
2955 | UINTN Column;
|
---|
2956 | EFI_EDITOR_LINE *Line;
|
---|
2957 | CHAR16 *CharPos;
|
---|
2958 | LIST_ENTRY *Link;
|
---|
2959 | BOOLEAN Found;
|
---|
2960 |
|
---|
2961 | Column = 0;
|
---|
2962 | Position = 0;
|
---|
2963 |
|
---|
2964 | //
|
---|
2965 | // search if in current line
|
---|
2966 | //
|
---|
2967 | Current = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1 + Offset;
|
---|
2968 |
|
---|
2969 | if (Current >= (FileBuffer.CurrentLine->Buffer + FileBuffer.CurrentLine->Size)) {
|
---|
2970 | //
|
---|
2971 | // the end
|
---|
2972 | //
|
---|
2973 | Current = FileBuffer.CurrentLine->Buffer + FileBuffer.CurrentLine->Size;
|
---|
2974 | }
|
---|
2975 |
|
---|
2976 | Found = FALSE;
|
---|
2977 |
|
---|
2978 | CharPos = StrStr (Current, Str);
|
---|
2979 | if (CharPos != NULL) {
|
---|
2980 | Position = CharPos - Current + 1;
|
---|
2981 | Found = TRUE;
|
---|
2982 | }
|
---|
2983 |
|
---|
2984 | //
|
---|
2985 | // found
|
---|
2986 | //
|
---|
2987 | if (Found) {
|
---|
2988 | Column = (Position - 1) + FileBuffer.FilePosition.Column + Offset;
|
---|
2989 | Row = FileBuffer.FilePosition.Row;
|
---|
2990 | } else {
|
---|
2991 | //
|
---|
2992 | // not found so find through next lines
|
---|
2993 | //
|
---|
2994 | Link = FileBuffer.CurrentLine->Link.ForwardLink;
|
---|
2995 |
|
---|
2996 | Row = FileBuffer.FilePosition.Row + 1;
|
---|
2997 | while (Link != FileBuffer.ListHead) {
|
---|
2998 | Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
|
---|
2999 | // Position = StrStr (Line->Buffer, Str);
|
---|
3000 | CharPos = StrStr (Line->Buffer, Str);
|
---|
3001 | if (CharPos != NULL) {
|
---|
3002 | Position = CharPos - Line->Buffer + 1;
|
---|
3003 | Found = TRUE;
|
---|
3004 | }
|
---|
3005 |
|
---|
3006 | if (Found) {
|
---|
3007 | //
|
---|
3008 | // found
|
---|
3009 | //
|
---|
3010 | Column = Position;
|
---|
3011 | break;
|
---|
3012 | }
|
---|
3013 |
|
---|
3014 | Row++;
|
---|
3015 | Link = Link->ForwardLink;
|
---|
3016 | }
|
---|
3017 |
|
---|
3018 | if (Link == FileBuffer.ListHead) {
|
---|
3019 | Found = FALSE;
|
---|
3020 | } else {
|
---|
3021 | Found = TRUE;
|
---|
3022 | }
|
---|
3023 | }
|
---|
3024 |
|
---|
3025 | if (!Found) {
|
---|
3026 | return EFI_NOT_FOUND;
|
---|
3027 | }
|
---|
3028 |
|
---|
3029 | FileBufferMovePosition (Row, Column);
|
---|
3030 |
|
---|
3031 | //
|
---|
3032 | // call refresh to fresh edit area,
|
---|
3033 | // because the outer may loop to find multiply occurrence of this string
|
---|
3034 | //
|
---|
3035 | FileBufferRefresh ();
|
---|
3036 |
|
---|
3037 | return EFI_SUCCESS;
|
---|
3038 | }
|
---|
3039 |
|
---|
3040 | /**
|
---|
3041 | Replace SearchLen characters from current position on with Replace.
|
---|
3042 |
|
---|
3043 | This will modify the current buffer at the current position.
|
---|
3044 |
|
---|
3045 | @param[in] Replace The string to replace.
|
---|
3046 | @param[in] SearchLen Search string's length.
|
---|
3047 |
|
---|
3048 | @retval EFI_SUCCESS The operation was successful.
|
---|
3049 | @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
|
---|
3050 | **/
|
---|
3051 | EFI_STATUS
|
---|
3052 | FileBufferReplace (
|
---|
3053 | IN CONST CHAR16 *Replace,
|
---|
3054 | IN CONST UINTN SearchLen
|
---|
3055 | )
|
---|
3056 | {
|
---|
3057 | UINTN ReplaceLen;
|
---|
3058 | UINTN Index;
|
---|
3059 | CHAR16 *Buffer;
|
---|
3060 | UINTN NewSize;
|
---|
3061 | UINTN OldSize;
|
---|
3062 | UINTN Gap;
|
---|
3063 |
|
---|
3064 | ReplaceLen = StrLen (Replace);
|
---|
3065 |
|
---|
3066 | OldSize = FileBuffer.CurrentLine->Size + 1;
|
---|
3067 | //
|
---|
3068 | // include CHAR_NULL
|
---|
3069 | //
|
---|
3070 | NewSize = OldSize + (ReplaceLen - SearchLen);
|
---|
3071 |
|
---|
3072 | if (ReplaceLen > SearchLen) {
|
---|
3073 | //
|
---|
3074 | // do not have the enough space
|
---|
3075 | //
|
---|
3076 | if (FileBuffer.CurrentLine->TotalSize + 1 <= NewSize) {
|
---|
3077 | FileBuffer.CurrentLine->Buffer = ReallocatePool (
|
---|
3078 | 2 * OldSize,
|
---|
3079 | 2 * NewSize,
|
---|
3080 | FileBuffer.CurrentLine->Buffer
|
---|
3081 | );
|
---|
3082 | FileBuffer.CurrentLine->TotalSize = NewSize - 1;
|
---|
3083 | }
|
---|
3084 |
|
---|
3085 | if (FileBuffer.CurrentLine->Buffer == NULL) {
|
---|
3086 | return EFI_OUT_OF_RESOURCES;
|
---|
3087 | }
|
---|
3088 |
|
---|
3089 | //
|
---|
3090 | // the end CHAR_NULL character;
|
---|
3091 | //
|
---|
3092 | Buffer = FileBuffer.CurrentLine->Buffer + (NewSize - 1);
|
---|
3093 | Gap = ReplaceLen - SearchLen;
|
---|
3094 |
|
---|
3095 | //
|
---|
3096 | // keep the latter part
|
---|
3097 | //
|
---|
3098 | for (Index = 0; Index < (FileBuffer.CurrentLine->Size - FileBuffer.FilePosition.Column - SearchLen + 2); Index++) {
|
---|
3099 | *Buffer = *(Buffer - Gap);
|
---|
3100 | Buffer--;
|
---|
3101 | }
|
---|
3102 |
|
---|
3103 | //
|
---|
3104 | // set replace into it
|
---|
3105 | //
|
---|
3106 | Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1;
|
---|
3107 | for (Index = 0; Index < ReplaceLen; Index++) {
|
---|
3108 | Buffer[Index] = Replace[Index];
|
---|
3109 | }
|
---|
3110 | }
|
---|
3111 |
|
---|
3112 | if (ReplaceLen < SearchLen) {
|
---|
3113 | Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1;
|
---|
3114 |
|
---|
3115 | for (Index = 0; Index < ReplaceLen; Index++) {
|
---|
3116 | Buffer[Index] = Replace[Index];
|
---|
3117 | }
|
---|
3118 |
|
---|
3119 | Buffer += ReplaceLen;
|
---|
3120 | Gap = SearchLen - ReplaceLen;
|
---|
3121 |
|
---|
3122 | //
|
---|
3123 | // set replace into it
|
---|
3124 | //
|
---|
3125 | for (Index = 0; Index < (FileBuffer.CurrentLine->Size - FileBuffer.FilePosition.Column - ReplaceLen + 2); Index++) {
|
---|
3126 | *Buffer = *(Buffer + Gap);
|
---|
3127 | Buffer++;
|
---|
3128 | }
|
---|
3129 | }
|
---|
3130 |
|
---|
3131 | if (ReplaceLen == SearchLen) {
|
---|
3132 | Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1;
|
---|
3133 | for (Index = 0; Index < ReplaceLen; Index++) {
|
---|
3134 | Buffer[Index] = Replace[Index];
|
---|
3135 | }
|
---|
3136 | }
|
---|
3137 |
|
---|
3138 | FileBuffer.CurrentLine->Size += (ReplaceLen - SearchLen);
|
---|
3139 |
|
---|
3140 | FileBufferOnlyLineNeedRefresh = TRUE;
|
---|
3141 |
|
---|
3142 | FileBuffer.FileModified = TRUE;
|
---|
3143 |
|
---|
3144 | MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row, 0, 0);
|
---|
3145 | FileBufferRestorePosition ();
|
---|
3146 | FileBufferRefresh ();
|
---|
3147 |
|
---|
3148 | return EFI_SUCCESS;
|
---|
3149 | }
|
---|
3150 |
|
---|
3151 | /**
|
---|
3152 | Move the mouse cursor position.
|
---|
3153 |
|
---|
3154 | @param[in] TextX The new x-coordinate.
|
---|
3155 | @param[in] TextY The new y-coordinate.
|
---|
3156 | **/
|
---|
3157 | VOID
|
---|
3158 | FileBufferAdjustMousePosition (
|
---|
3159 | IN CONST INT32 TextX,
|
---|
3160 | IN CONST INT32 TextY
|
---|
3161 | )
|
---|
3162 | {
|
---|
3163 | UINTN CoordinateX;
|
---|
3164 | UINTN CoordinateY;
|
---|
3165 | UINTN AbsX;
|
---|
3166 | UINTN AbsY;
|
---|
3167 |
|
---|
3168 | //
|
---|
3169 | // TextX and TextY is mouse movement data returned by mouse driver
|
---|
3170 | // This function will change it to MousePosition
|
---|
3171 | //
|
---|
3172 | //
|
---|
3173 | // get absolute value
|
---|
3174 | //
|
---|
3175 |
|
---|
3176 | AbsX = ABS (TextX);
|
---|
3177 | AbsY = ABS (TextY);
|
---|
3178 |
|
---|
3179 | CoordinateX = FileBuffer.MousePosition.Column;
|
---|
3180 | CoordinateY = FileBuffer.MousePosition.Row;
|
---|
3181 |
|
---|
3182 | if (TextX >= 0) {
|
---|
3183 | CoordinateX += TextX;
|
---|
3184 | } else {
|
---|
3185 | if (CoordinateX >= AbsX) {
|
---|
3186 | CoordinateX -= AbsX;
|
---|
3187 | } else {
|
---|
3188 | CoordinateX = 0;
|
---|
3189 | }
|
---|
3190 | }
|
---|
3191 |
|
---|
3192 | if (TextY >= 0) {
|
---|
3193 | CoordinateY += TextY;
|
---|
3194 | } else {
|
---|
3195 | if (CoordinateY >= AbsY) {
|
---|
3196 | CoordinateY -= AbsY;
|
---|
3197 | } else {
|
---|
3198 | CoordinateY = 0;
|
---|
3199 | }
|
---|
3200 | }
|
---|
3201 |
|
---|
3202 | //
|
---|
3203 | // check whether new mouse column position is beyond screen
|
---|
3204 | // if not, adjust it
|
---|
3205 | //
|
---|
3206 | if ((CoordinateX >= 1) && (CoordinateX <= MainEditor.ScreenSize.Column)) {
|
---|
3207 | FileBuffer.MousePosition.Column = CoordinateX;
|
---|
3208 | } else if (CoordinateX < 1) {
|
---|
3209 | FileBuffer.MousePosition.Column = 1;
|
---|
3210 | } else if (CoordinateX > MainEditor.ScreenSize.Column) {
|
---|
3211 | FileBuffer.MousePosition.Column = MainEditor.ScreenSize.Column;
|
---|
3212 | }
|
---|
3213 |
|
---|
3214 | //
|
---|
3215 | // check whether new mouse row position is beyond screen
|
---|
3216 | // if not, adjust it
|
---|
3217 | //
|
---|
3218 | if ((CoordinateY >= 2) && (CoordinateY <= (MainEditor.ScreenSize.Row - 1))) {
|
---|
3219 | FileBuffer.MousePosition.Row = CoordinateY;
|
---|
3220 | } else if (CoordinateY < 2) {
|
---|
3221 | FileBuffer.MousePosition.Row = 2;
|
---|
3222 | } else if (CoordinateY > (MainEditor.ScreenSize.Row - 1)) {
|
---|
3223 | FileBuffer.MousePosition.Row = (MainEditor.ScreenSize.Row - 1);
|
---|
3224 | }
|
---|
3225 | }
|
---|
3226 |
|
---|
3227 | /**
|
---|
3228 | Search and replace operation.
|
---|
3229 |
|
---|
3230 | @param[in] SearchStr The string to search for.
|
---|
3231 | @param[in] ReplaceStr The string to replace with.
|
---|
3232 | @param[in] Offset The column to start at.
|
---|
3233 | **/
|
---|
3234 | EFI_STATUS
|
---|
3235 | FileBufferReplaceAll (
|
---|
3236 | IN CHAR16 *SearchStr,
|
---|
3237 | IN CHAR16 *ReplaceStr,
|
---|
3238 | IN UINTN Offset
|
---|
3239 | )
|
---|
3240 | {
|
---|
3241 | CHAR16 *Buffer;
|
---|
3242 | UINTN Position;
|
---|
3243 | UINTN Column;
|
---|
3244 | UINTN ReplaceLen;
|
---|
3245 | UINTN SearchLen;
|
---|
3246 | UINTN Index;
|
---|
3247 | UINTN NewSize;
|
---|
3248 | UINTN OldSize;
|
---|
3249 | UINTN Gap;
|
---|
3250 | EFI_EDITOR_LINE *Line;
|
---|
3251 | LIST_ENTRY *Link;
|
---|
3252 | CHAR16 *CharPos;
|
---|
3253 |
|
---|
3254 | SearchLen = StrLen (SearchStr);
|
---|
3255 | ReplaceLen = StrLen (ReplaceStr);
|
---|
3256 |
|
---|
3257 | Column = FileBuffer.FilePosition.Column + Offset - 1;
|
---|
3258 |
|
---|
3259 | if (Column > FileBuffer.CurrentLine->Size) {
|
---|
3260 | Column = FileBuffer.CurrentLine->Size;
|
---|
3261 | }
|
---|
3262 |
|
---|
3263 | Link = &(FileBuffer.CurrentLine->Link);
|
---|
3264 |
|
---|
3265 | while (Link != FileBuffer.ListHead) {
|
---|
3266 | Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
|
---|
3267 | CharPos = StrStr (Line->Buffer + Column, SearchStr);
|
---|
3268 | if (CharPos != NULL) {
|
---|
3269 | Position = CharPos - Line->Buffer;// + Column;
|
---|
3270 | //
|
---|
3271 | // found
|
---|
3272 | //
|
---|
3273 | if (ReplaceLen > SearchLen) {
|
---|
3274 | OldSize = Line->Size + 1;
|
---|
3275 | //
|
---|
3276 | // include CHAR_NULL
|
---|
3277 | //
|
---|
3278 | NewSize = OldSize + (ReplaceLen - SearchLen);
|
---|
3279 |
|
---|
3280 | //
|
---|
3281 | // do not have the enough space
|
---|
3282 | //
|
---|
3283 | if (Line->TotalSize + 1 <= NewSize) {
|
---|
3284 | Line->Buffer = ReallocatePool (
|
---|
3285 | 2 * OldSize,
|
---|
3286 | 2 * NewSize,
|
---|
3287 | Line->Buffer
|
---|
3288 | );
|
---|
3289 | Line->TotalSize = NewSize - 1;
|
---|
3290 | }
|
---|
3291 |
|
---|
3292 | if (Line->Buffer == NULL) {
|
---|
3293 | return EFI_OUT_OF_RESOURCES;
|
---|
3294 | }
|
---|
3295 |
|
---|
3296 | //
|
---|
3297 | // the end CHAR_NULL character;
|
---|
3298 | //
|
---|
3299 | Buffer = Line->Buffer + (NewSize - 1);
|
---|
3300 | Gap = ReplaceLen - SearchLen;
|
---|
3301 |
|
---|
3302 | //
|
---|
3303 | // keep the latter part
|
---|
3304 | //
|
---|
3305 | for (Index = 0; Index < (Line->Size - Position - SearchLen + 1); Index++) {
|
---|
3306 | *Buffer = *(Buffer - Gap);
|
---|
3307 | Buffer--;
|
---|
3308 | }
|
---|
3309 | } else if (ReplaceLen < SearchLen) {
|
---|
3310 | Buffer = Line->Buffer + Position + ReplaceLen;
|
---|
3311 | Gap = SearchLen - ReplaceLen;
|
---|
3312 |
|
---|
3313 | for (Index = 0; Index < (Line->Size - Position - ReplaceLen + 1); Index++) {
|
---|
3314 | *Buffer = *(Buffer + Gap);
|
---|
3315 | Buffer++;
|
---|
3316 | }
|
---|
3317 | } else {
|
---|
3318 | ASSERT (ReplaceLen == SearchLen);
|
---|
3319 | }
|
---|
3320 |
|
---|
3321 | //
|
---|
3322 | // set replace into it
|
---|
3323 | //
|
---|
3324 | Buffer = Line->Buffer + Position;
|
---|
3325 | for (Index = 0; Index < ReplaceLen; Index++) {
|
---|
3326 | Buffer[Index] = ReplaceStr[Index];
|
---|
3327 | }
|
---|
3328 |
|
---|
3329 | Line->Size += (ReplaceLen - SearchLen);
|
---|
3330 | Column += ReplaceLen;
|
---|
3331 | } else {
|
---|
3332 | //
|
---|
3333 | // not found
|
---|
3334 | //
|
---|
3335 | Column = 0;
|
---|
3336 | Link = Link->ForwardLink;
|
---|
3337 | }
|
---|
3338 | }
|
---|
3339 |
|
---|
3340 | //
|
---|
3341 | // call refresh to fresh edit area
|
---|
3342 | //
|
---|
3343 | FileBuffer.FileModified = TRUE;
|
---|
3344 | FileBufferNeedRefresh = TRUE;
|
---|
3345 | FileBufferRefresh ();
|
---|
3346 |
|
---|
3347 | return EFI_SUCCESS;
|
---|
3348 | }
|
---|
3349 |
|
---|
3350 | /**
|
---|
3351 | Set the modified state to TRUE.
|
---|
3352 | **/
|
---|
3353 | VOID
|
---|
3354 | FileBufferSetModified (
|
---|
3355 | VOID
|
---|
3356 | )
|
---|
3357 | {
|
---|
3358 | FileBuffer.FileModified = TRUE;
|
---|
3359 | }
|
---|