1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319 |
- /** @file
- Implements filebuffer interface functions.
- Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved. <BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
- **/
- #include "TextEditor.h"
- #include <Guid/FileSystemInfo.h>
- #include <Library/FileHandleLib.h>
- EFI_EDITOR_FILE_BUFFER FileBuffer;
- EFI_EDITOR_FILE_BUFFER FileBufferBackupVar;
- //
- // for basic initialization of FileBuffer
- //
- EFI_EDITOR_FILE_BUFFER FileBufferConst = {
- NULL,
- FileTypeUnicode,
- NULL,
- NULL,
- 0,
- {
- 0,
- 0
- },
- {
- 0,
- 0
- },
- {
- 0,
- 0
- },
- {
- 0,
- 0
- },
- FALSE,
- TRUE,
- FALSE,
- NULL
- };
- //
- // the whole edit area needs to be refreshed
- //
- BOOLEAN FileBufferNeedRefresh;
- //
- // only the current line in edit area needs to be refresh
- //
- BOOLEAN FileBufferOnlyLineNeedRefresh;
- BOOLEAN FileBufferMouseNeedRefresh;
- extern BOOLEAN EditorMouseAction;
- /**
- Initialization function for FileBuffer.
- @param EFI_SUCCESS The initialization was successful.
- @param EFI_LOAD_ERROR A default name could not be created.
- @param EFI_OUT_OF_RESOURCES A memory allocation failed.
- **/
- EFI_STATUS
- FileBufferInit (
- VOID
- )
- {
- //
- // basically initialize the FileBuffer
- //
- CopyMem (&FileBuffer , &FileBufferConst, sizeof (EFI_EDITOR_FILE_BUFFER));
- CopyMem (&FileBufferBackupVar, &FileBufferConst, sizeof (EFI_EDITOR_FILE_BUFFER));
- //
- // set default FileName
- //
- FileBuffer.FileName = EditGetDefaultFileName (L"txt");
- if (FileBuffer.FileName == NULL) {
- return EFI_LOAD_ERROR;
- }
- FileBuffer.ListHead = AllocateZeroPool (sizeof (LIST_ENTRY));
- if (FileBuffer.ListHead == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- InitializeListHead (FileBuffer.ListHead);
- FileBuffer.DisplayPosition.Row = 2;
- FileBuffer.DisplayPosition.Column = 1;
- FileBuffer.LowVisibleRange.Row = 2;
- FileBuffer.LowVisibleRange.Column = 1;
- FileBufferNeedRefresh = FALSE;
- FileBufferMouseNeedRefresh = FALSE;
- FileBufferOnlyLineNeedRefresh = FALSE;
- return EFI_SUCCESS;
- }
- /**
- Backup function for FileBuffer. Only backup the following items:
- Mouse/Cursor position
- File Name, Type, ReadOnly, Modified
- Insert Mode
- This is for making the file buffer refresh as few as possible.
- @retval EFI_SUCCESS The backup operation was successful.
- **/
- EFI_STATUS
- FileBufferBackup (
- VOID
- )
- {
- FileBufferBackupVar.MousePosition = FileBuffer.MousePosition;
- SHELL_FREE_NON_NULL (FileBufferBackupVar.FileName);
- FileBufferBackupVar.FileName = NULL;
- FileBufferBackupVar.FileName = StrnCatGrow (&FileBufferBackupVar.FileName, NULL, FileBuffer.FileName, 0);
- FileBufferBackupVar.ModeInsert = FileBuffer.ModeInsert;
- FileBufferBackupVar.FileType = FileBuffer.FileType;
- FileBufferBackupVar.FilePosition = FileBuffer.FilePosition;
- FileBufferBackupVar.LowVisibleRange = FileBuffer.LowVisibleRange;
- FileBufferBackupVar.FileModified = FileBuffer.FileModified;
- FileBufferBackupVar.ReadOnly = FileBuffer.ReadOnly;
- return EFI_SUCCESS;
- }
- /**
- Advance to the next Count lines
- @param[in] Count The line number to advance by.
- @param[in] CurrentLine The pointer to the current line structure.
- @param[in] LineList The pointer to the linked list of lines.
- @retval NULL There was an error.
- @return The line structure after the advance.
- **/
- EFI_EDITOR_LINE *
- InternalEditorMiscLineAdvance (
- IN CONST UINTN Count,
- IN CONST EFI_EDITOR_LINE *CurrentLine,
- IN CONST LIST_ENTRY *LineList
- )
- {
- UINTN Index;
- CONST EFI_EDITOR_LINE *Line;
- if (CurrentLine == NULL || LineList == NULL) {
- return NULL;
- }
- for (Line = CurrentLine, Index = 0; Index < Count; Index++) {
- //
- // if already last line
- //
- if (Line->Link.ForwardLink == LineList) {
- return NULL;
- }
- Line = CR (Line->Link.ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- }
- return ((EFI_EDITOR_LINE *)Line);
- }
- /**
- Retreat to the previous Count lines.
- @param[in] Count The line number to retreat by.
- @param[in] CurrentLine The pointer to the current line structure.
- @param[in] LineList The pointer to the linked list of lines.
- @retval NULL There was an error.
- @return The line structure after the retreat.
- **/
- EFI_EDITOR_LINE *
- InternalEditorMiscLineRetreat (
- IN CONST UINTN Count,
- IN CONST EFI_EDITOR_LINE *CurrentLine,
- IN CONST LIST_ENTRY *LineList
- )
- {
- UINTN Index;
- CONST EFI_EDITOR_LINE *Line;
- if (CurrentLine == NULL || LineList == NULL) {
- return NULL;
- }
- for (Line = CurrentLine, Index = 0; Index < Count; Index++) {
- //
- // already the first line
- //
- if (Line->Link.BackLink == LineList) {
- return NULL;
- }
- Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- }
- return ((EFI_EDITOR_LINE *)Line);
- }
- /**
- Advance/Retreat lines
- @param[in] Count line number to advance/retreat
- >0 : advance
- <0 : retreat
- @retval NULL An error occurred.
- @return The line after advance/retreat.
- **/
- EFI_EDITOR_LINE *
- MoveLine (
- IN CONST INTN Count
- )
- {
- EFI_EDITOR_LINE *Line;
- UINTN AbsCount;
- //
- // if < 0, then retreat
- // if > 0, the advance
- //
- if (Count <= 0) {
- AbsCount = (UINTN)ABS(Count);
- Line = InternalEditorMiscLineRetreat (AbsCount,MainEditor.FileBuffer->CurrentLine,MainEditor.FileBuffer->ListHead);
- } else {
- Line = InternalEditorMiscLineAdvance ((UINTN)Count,MainEditor.FileBuffer->CurrentLine,MainEditor.FileBuffer->ListHead);
- }
- return Line;
- }
- /**
- Function to update the 'screen' to display the mouse position.
- @retval EFI_SUCCESS The backup operation was successful.
- **/
- EFI_STATUS
- FileBufferRestoreMousePosition (
- VOID
- )
- {
- EFI_EDITOR_COLOR_UNION Orig;
- EFI_EDITOR_COLOR_UNION New;
- UINTN FRow;
- UINTN FColumn;
- BOOLEAN HasCharacter;
- EFI_EDITOR_LINE *CurrentLine;
- EFI_EDITOR_LINE *Line;
- CHAR16 Value;
- //
- // variable initialization
- //
- Line = NULL;
- if (MainEditor.MouseSupported) {
- if (FileBufferMouseNeedRefresh) {
- FileBufferMouseNeedRefresh = FALSE;
- //
- // if mouse position not moved and only mouse action
- // so do not need to refresh mouse position
- //
- if ((FileBuffer.MousePosition.Row == FileBufferBackupVar.MousePosition.Row &&
- FileBuffer.MousePosition.Column == FileBufferBackupVar.MousePosition.Column)
- && EditorMouseAction) {
- return EFI_SUCCESS;
- }
- //
- // backup the old screen attributes
- //
- Orig = MainEditor.ColorAttributes;
- New.Data = 0;
- New.Colors.Foreground = Orig.Colors.Background & 0xF;
- New.Colors.Background = Orig.Colors.Foreground & 0x7;
- //
- // clear the old mouse position
- //
- FRow = FileBuffer.LowVisibleRange.Row + FileBufferBackupVar.MousePosition.Row - 2;
- FColumn = FileBuffer.LowVisibleRange.Column + FileBufferBackupVar.MousePosition.Column - 1;
- HasCharacter = TRUE;
- if (FRow > FileBuffer.NumLines) {
- HasCharacter = FALSE;
- } else {
- CurrentLine = FileBuffer.CurrentLine;
- Line = MoveLine (FRow - FileBuffer.FilePosition.Row);
- if (Line == NULL || FColumn > Line->Size) {
- HasCharacter = FALSE;
- }
- FileBuffer.CurrentLine = CurrentLine;
- }
- ShellPrintEx (
- (INT32)FileBufferBackupVar.MousePosition.Column - 1,
- (INT32)FileBufferBackupVar.MousePosition.Row - 1,
- L" "
- );
- if (HasCharacter) {
- Value = (Line->Buffer[FColumn - 1]);
- ShellPrintEx (
- (INT32)FileBufferBackupVar.MousePosition.Column - 1,
- (INT32)FileBufferBackupVar.MousePosition.Row - 1,
- L"%c",
- Value
- );
- }
- //
- // set the new mouse position
- //
- gST->ConOut->SetAttribute (gST->ConOut, New.Data & 0x7F);
- //
- // clear the old mouse position
- //
- FRow = FileBuffer.LowVisibleRange.Row + FileBuffer.MousePosition.Row - 2;
- FColumn = FileBuffer.LowVisibleRange.Column + FileBuffer.MousePosition.Column - 1;
- HasCharacter = TRUE;
- if (FRow > FileBuffer.NumLines) {
- HasCharacter = FALSE;
- } else {
- CurrentLine = FileBuffer.CurrentLine;
- Line = MoveLine (FRow - FileBuffer.FilePosition.Row);
- if (Line == NULL || FColumn > Line->Size) {
- HasCharacter = FALSE;
- }
- FileBuffer.CurrentLine = CurrentLine;
- }
- ShellPrintEx (
- (INT32)FileBuffer.MousePosition.Column - 1,
- (INT32)FileBuffer.MousePosition.Row - 1,
- L" "
- );
- if (HasCharacter) {
- Value = Line->Buffer[FColumn - 1];
- ShellPrintEx (
- (INT32)FileBuffer.MousePosition.Column - 1,
- (INT32)FileBuffer.MousePosition.Row - 1,
- L"%c",
- Value
- );
- }
- //
- // end of HasCharacter
- //
- gST->ConOut->SetAttribute (gST->ConOut, Orig.Data);
- }
- //
- // end of MouseNeedRefresh
- //
- }
- //
- // end of MouseSupported
- //
- return EFI_SUCCESS;
- }
- /**
- Free all the lines in FileBuffer
- Fields affected:
- Lines
- CurrentLine
- NumLines
- ListHead
- @retval EFI_SUCCESS The operation was successful.
- **/
- EFI_STATUS
- FileBufferFreeLines (
- VOID
- )
- {
- LIST_ENTRY *Link;
- EFI_EDITOR_LINE *Line;
- //
- // free all the lines
- //
- if (FileBuffer.Lines != NULL) {
- Line = FileBuffer.Lines;
- Link = &(Line->Link);
- do {
- Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- Link = Link->ForwardLink;
- //
- // free line's buffer and line itself
- //
- LineFree (Line);
- } while (Link != FileBuffer.ListHead);
- }
- //
- // clean the line list related structure
- //
- FileBuffer.Lines = NULL;
- FileBuffer.CurrentLine = NULL;
- FileBuffer.NumLines = 0;
- FileBuffer.ListHead->ForwardLink = FileBuffer.ListHead;
- FileBuffer.ListHead->BackLink = FileBuffer.ListHead;
- return EFI_SUCCESS;
- }
- /**
- Cleanup function for FileBuffer.
- @retval EFI_SUCCESS The cleanup was successful.
- **/
- EFI_STATUS
- FileBufferCleanup (
- VOID
- )
- {
- EFI_STATUS Status;
- SHELL_FREE_NON_NULL (FileBuffer.FileName);
- //
- // free all the lines
- //
- Status = FileBufferFreeLines ();
- SHELL_FREE_NON_NULL (FileBuffer.ListHead);
- FileBuffer.ListHead = NULL;
- SHELL_FREE_NON_NULL (FileBufferBackupVar.FileName);
- return Status;
- }
- /**
- Print a line specified by Line on a row specified by Row of the screen.
- @param[in] Line The line to print.
- @param[in] Row The row on the screen to print onto (begin from 1).
- @retval EFI_SUCCESS The printing was successful.
- **/
- EFI_STATUS
- FileBufferPrintLine (
- IN CONST EFI_EDITOR_LINE *Line,
- IN CONST UINTN Row
- )
- {
- CHAR16 *Buffer;
- UINTN Limit;
- CHAR16 *PrintLine;
- CHAR16 *PrintLine2;
- UINTN BufLen;
- //
- // print start from correct character
- //
- Buffer = Line->Buffer + FileBuffer.LowVisibleRange.Column - 1;
- Limit = Line->Size - FileBuffer.LowVisibleRange.Column + 1;
- if (Limit > Line->Size) {
- Limit = 0;
- }
- BufLen = (MainEditor.ScreenSize.Column + 1) * sizeof (CHAR16);
- PrintLine = AllocatePool (BufLen);
- if (PrintLine != NULL) {
- StrnCpyS (PrintLine, BufLen/sizeof(CHAR16), Buffer, MIN(Limit, MainEditor.ScreenSize.Column));
- for (Limit = StrLen (PrintLine); Limit < MainEditor.ScreenSize.Column; Limit++) {
- PrintLine[Limit] = L' ';
- }
- PrintLine[MainEditor.ScreenSize.Column] = CHAR_NULL;
- PrintLine2 = AllocatePool (BufLen * 2);
- if (PrintLine2 != NULL) {
- ShellCopySearchAndReplace(PrintLine, PrintLine2, BufLen * 2, L"%", L"^%", FALSE, FALSE);
- ShellPrintEx (
- 0,
- (INT32)Row - 1,
- L"%s",
- PrintLine2
- );
- FreePool (PrintLine2);
- }
- FreePool (PrintLine);
- }
- return EFI_SUCCESS;
- }
- /**
- Set the cursor position according to FileBuffer.DisplayPosition.
- @retval EFI_SUCCESS The operation was successful.
- **/
- EFI_STATUS
- FileBufferRestorePosition (
- VOID
- )
- {
- //
- // set cursor position
- //
- return (gST->ConOut->SetCursorPosition (
- gST->ConOut,
- FileBuffer.DisplayPosition.Column - 1,
- FileBuffer.DisplayPosition.Row - 1
- ));
- }
- /**
- Refresh the screen with whats in the buffer.
- @retval EFI_SUCCESS The refresh was successful.
- @retval EFI_LOAD_ERROR There was an error finding what to write.
- **/
- EFI_STATUS
- FileBufferRefresh (
- VOID
- )
- {
- LIST_ENTRY *Link;
- EFI_EDITOR_LINE *Line;
- UINTN Row;
- //
- // if it's the first time after editor launch, so should refresh
- //
- if (!EditorFirst) {
- //
- // no definite required refresh
- // and file position displayed on screen has not been changed
- //
- if (!FileBufferNeedRefresh &&
- !FileBufferOnlyLineNeedRefresh &&
- FileBufferBackupVar.LowVisibleRange.Row == FileBuffer.LowVisibleRange.Row &&
- FileBufferBackupVar.LowVisibleRange.Column == FileBuffer.LowVisibleRange.Column
- ) {
- FileBufferRestoreMousePosition ();
- FileBufferRestorePosition ();
- return EFI_SUCCESS;
- }
- }
- gST->ConOut->EnableCursor (gST->ConOut, FALSE);
- //
- // only need to refresh current line
- //
- if (FileBufferOnlyLineNeedRefresh &&
- FileBufferBackupVar.LowVisibleRange.Row == FileBuffer.LowVisibleRange.Row &&
- FileBufferBackupVar.LowVisibleRange.Column == FileBuffer.LowVisibleRange.Column
- ) {
- EditorClearLine (FileBuffer.DisplayPosition.Row, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row);
- FileBufferPrintLine (
- FileBuffer.CurrentLine,
- FileBuffer.DisplayPosition.Row
- );
- } else {
- //
- // the whole edit area need refresh
- //
- //
- // no line
- //
- if (FileBuffer.Lines == NULL) {
- FileBufferRestoreMousePosition ();
- FileBufferRestorePosition ();
- gST->ConOut->EnableCursor (gST->ConOut, TRUE);
- return EFI_SUCCESS;
- }
- //
- // get the first line that will be displayed
- //
- Line = MoveLine (FileBuffer.LowVisibleRange.Row - FileBuffer.FilePosition.Row);
- if (Line == NULL) {
- gST->ConOut->EnableCursor (gST->ConOut, TRUE);
- return EFI_LOAD_ERROR;
- }
- Link = &(Line->Link);
- Row = 2;
- do {
- Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- //
- // print line at row
- //
- FileBufferPrintLine (Line, Row);
- Link = Link->ForwardLink;
- Row++;
- } while (Link != FileBuffer.ListHead && Row <= (MainEditor.ScreenSize.Row - 1));
- //
- // while not file end and not screen full
- //
- while (Row <= (MainEditor.ScreenSize.Row - 1)) {
- EditorClearLine (Row, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row);
- Row++;
- }
- }
- FileBufferRestoreMousePosition ();
- FileBufferRestorePosition ();
- FileBufferNeedRefresh = FALSE;
- FileBufferOnlyLineNeedRefresh = FALSE;
- gST->ConOut->EnableCursor (gST->ConOut, TRUE);
- return EFI_SUCCESS;
- }
- /**
- Create a new line and append it to the line list.
- Fields affected:
- NumLines
- Lines
- @retval NULL The create line failed.
- @return The line created.
- **/
- EFI_EDITOR_LINE *
- FileBufferCreateLine (
- VOID
- )
- {
- EFI_EDITOR_LINE *Line;
- //
- // allocate a line structure
- //
- Line = AllocateZeroPool (sizeof (EFI_EDITOR_LINE));
- if (Line == NULL) {
- return NULL;
- }
- //
- // initialize the structure
- //
- Line->Signature = LINE_LIST_SIGNATURE;
- Line->Size = 0;
- Line->TotalSize = 0;
- Line->Type = NewLineTypeDefault;
- //
- // initial buffer of the line is "\0"
- //
- ASSERT(CHAR_NULL == CHAR_NULL);
- Line->Buffer = CatSPrint (NULL, L"\0");
- if (Line->Buffer == NULL) {
- return NULL;
- }
- FileBuffer.NumLines++;
- //
- // insert the line into line list
- //
- InsertTailList (FileBuffer.ListHead, &Line->Link);
- if (FileBuffer.Lines == NULL) {
- FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- }
- return Line;
- }
- /**
- Set FileName field in FileBuffer.
- @param Str The file name to set.
- @retval EFI_SUCCESS The filename was successfully set.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_INVALID_PARAMETER Str is not a valid filename.
- **/
- EFI_STATUS
- FileBufferSetFileName (
- IN CONST CHAR16 *Str
- )
- {
- //
- // Verify the parameters
- //
- if (!IsValidFileName(Str)) {
- return (EFI_INVALID_PARAMETER);
- }
- //
- // free the old file name
- //
- SHELL_FREE_NON_NULL (FileBuffer.FileName);
- //
- // Allocate and set the new name
- //
- FileBuffer.FileName = CatSPrint (NULL, L"%s", Str);
- if (FileBuffer.FileName == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- return EFI_SUCCESS;
- }
- /**
- Free the existing file lines and reset the modified flag.
- @retval EFI_SUCCESS The operation was successful.
- **/
- EFI_STATUS
- FileBufferFree (
- VOID
- )
- {
- //
- // free all the lines
- //
- FileBufferFreeLines ();
- FileBuffer.FileModified = FALSE;
- return EFI_SUCCESS;
- }
- /**
- Read a file from disk into the FileBuffer.
- @param[in] FileName The filename to read.
- @param[in] Recover TRUE if is for recover mode, no information printouts.
- @retval EFI_SUCCESS The load was successful.
- @retval EFI_LOAD_ERROR The load failed.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- @retval EFI_INVALID_PARAMETER FileName is a directory.
- **/
- EFI_STATUS
- FileBufferRead (
- IN CONST CHAR16 *FileName,
- IN CONST BOOLEAN Recover
- )
- {
- EFI_EDITOR_LINE *Line;
- EE_NEWLINE_TYPE Type;
- UINTN LoopVar1;
- UINTN LoopVar2;
- UINTN LineSize;
- VOID *Buffer;
- CHAR16 *UnicodeBuffer;
- UINT8 *AsciiBuffer;
- UINTN FileSize;
- SHELL_FILE_HANDLE FileHandle;
- BOOLEAN CreateFile;
- EFI_STATUS Status;
- UINTN LineSizeBackup;
- EFI_FILE_INFO *Info;
- Line = NULL;
- LoopVar1 = 0;
- FileSize = 0;
- UnicodeBuffer = NULL;
- Type = NewLineTypeDefault;
- FileHandle = NULL;
- CreateFile = FALSE;
- //
- // in this function, when you return error ( except EFI_OUT_OF_RESOURCES )
- // you should set status string via StatusBarSetStatusString(L"blah")
- // since this function maybe called before the editorhandleinput loop
- // so any error will cause editor return
- // so if you want to print the error status
- // you should set the status string
- //
- //
- // try to open the file
- //
- Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ, 0);
- if (!EFI_ERROR(Status)) {
- CreateFile = FALSE;
- if (FileHandle == NULL) {
- StatusBarSetStatusString (L"Disk Error");
- return EFI_LOAD_ERROR;
- }
- Info = ShellGetFileInfo(FileHandle);
- if (Info->Attribute & EFI_FILE_DIRECTORY) {
- StatusBarSetStatusString (L"Directory Can Not Be Edited");
- FreePool (Info);
- return EFI_INVALID_PARAMETER;
- }
- if (Info->Attribute & EFI_FILE_READ_ONLY) {
- FileBuffer.ReadOnly = TRUE;
- } else {
- FileBuffer.ReadOnly = FALSE;
- }
- //
- // get file size
- //
- FileSize = (UINTN) Info->FileSize;
- FreePool (Info);
- } else if (Status == EFI_NOT_FOUND) {
- //
- // file not exists. add create and try again
- //
- Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, 0);
- if (EFI_ERROR (Status)) {
- if (Status == EFI_WRITE_PROTECTED ||
- Status == EFI_ACCESS_DENIED ||
- Status == EFI_NO_MEDIA ||
- Status == EFI_MEDIA_CHANGED
- ) {
- StatusBarSetStatusString (L"Access Denied");
- } else if (Status == EFI_DEVICE_ERROR || Status == EFI_VOLUME_CORRUPTED || Status == EFI_VOLUME_FULL) {
- StatusBarSetStatusString (L"Disk Error");
- } else {
- StatusBarSetStatusString (L"Invalid File Name or Current-working-directory");
- }
- return Status;
- } else {
- //
- // it worked. now delete it and move on with the name (now validated)
- //
- Status = ShellDeleteFile (&FileHandle);
- if (Status == EFI_WARN_DELETE_FAILURE) {
- Status = EFI_ACCESS_DENIED;
- }
- FileHandle = NULL;
- if (EFI_ERROR (Status)) {
- StatusBarSetStatusString (L"Access Denied");
- return Status;
- }
- }
- //
- // file doesn't exist, so set CreateFile to TRUE
- //
- CreateFile = TRUE;
- FileBuffer.ReadOnly = FALSE;
- //
- // all the check ends
- // so now begin to set file name, free lines
- //
- if (StrCmp (FileName, FileBuffer.FileName) != 0) {
- FileBufferSetFileName (FileName);
- }
- //
- // free the old lines
- //
- FileBufferFree ();
- }
- //
- // the file exists
- //
- if (!CreateFile) {
- //
- // allocate buffer to read file
- //
- Buffer = AllocateZeroPool (FileSize);
- if (Buffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // read file into Buffer
- //
- Status = ShellReadFile (FileHandle, &FileSize, Buffer);
- ShellCloseFile(&FileHandle);
- FileHandle = NULL;
- if (EFI_ERROR (Status)) {
- StatusBarSetStatusString (L"Read File Failed");
- SHELL_FREE_NON_NULL (Buffer);
- return EFI_LOAD_ERROR;
- }
- //
- // nothing in this file
- //
- if (FileSize == 0) {
- SHELL_FREE_NON_NULL (Buffer);
- //
- // since has no head, so only can be an ASCII file
- //
- FileBuffer.FileType = FileTypeAscii;
- goto Done;
- }
- AsciiBuffer = Buffer;
- if (FileSize < 2) {
- //
- // size < Unicode file header, so only can be ASCII file
- //
- FileBuffer.FileType = FileTypeAscii;
- } else {
- //
- // Unicode file
- //
- if (*(UINT16 *) Buffer == EFI_UNICODE_BYTE_ORDER_MARK) {
- //
- // Unicode file's size should be even
- //
- if ((FileSize % 2) != 0) {
- StatusBarSetStatusString (L"File Format Wrong");
- SHELL_FREE_NON_NULL (Buffer);
- return EFI_LOAD_ERROR;
- }
- FileSize /= 2;
- FileBuffer.FileType = FileTypeUnicode;
- UnicodeBuffer = Buffer;
- //
- // pass this 0xff and 0xfe
- //
- UnicodeBuffer++;
- FileSize--;
- } else {
- FileBuffer.FileType = FileTypeAscii;
- }
- //
- // end of AsciiBuffer ==
- //
- }
- //
- // end of FileSize < 2
- // all the check ends
- // so now begin to set file name, free lines
- //
- if (StrCmp (FileName, FileBuffer.FileName) != 0) {
- FileBufferSetFileName (FileName);
- }
- //
- // free the old lines
- //
- FileBufferFree ();
- //
- // parse file content line by line
- //
- for (LoopVar1 = 0; LoopVar1 < FileSize; LoopVar1++) {
- Type = NewLineTypeUnknown;
- for (LineSize = LoopVar1; LineSize < FileSize; LineSize++) {
- if (FileBuffer.FileType == FileTypeAscii) {
- if (AsciiBuffer[LineSize] == CHAR_CARRIAGE_RETURN) {
- Type = NewLineTypeCarriageReturn;
- //
- // has LF following
- //
- if (LineSize < FileSize - 1) {
- if (AsciiBuffer[LineSize + 1] == CHAR_LINEFEED) {
- Type = NewLineTypeCarriageReturnLineFeed;
- }
- }
- break;
- } else if (AsciiBuffer[LineSize] == CHAR_LINEFEED) {
- Type = NewLineTypeLineFeed;
- //
- // has CR following
- //
- if (LineSize < FileSize - 1) {
- if (AsciiBuffer[LineSize + 1] == CHAR_CARRIAGE_RETURN) {
- Type = NewLineTypeLineFeedCarriageReturn;
- }
- }
- break;
- }
- } else {
- if (UnicodeBuffer[LineSize] == CHAR_CARRIAGE_RETURN) {
- Type = NewLineTypeCarriageReturn;
- //
- // has LF following
- //
- if (LineSize < FileSize - 1) {
- if (UnicodeBuffer[LineSize + 1] == CHAR_LINEFEED) {
- Type = NewLineTypeCarriageReturnLineFeed;
- }
- }
- break;
- } else if (UnicodeBuffer[LineSize] == CHAR_LINEFEED) {
- Type = NewLineTypeLineFeed;
- //
- // has CR following
- //
- if (LineSize < FileSize - 1) {
- if (UnicodeBuffer[LineSize + 1] == CHAR_CARRIAGE_RETURN) {
- Type = NewLineTypeLineFeedCarriageReturn;
- }
- }
- break;
- }
- }
- //
- // endif == ASCII
- //
- }
- //
- // end of for LineSize
- //
- // if the type is wrong, then exit
- //
- if (Type == NewLineTypeUnknown) {
- //
- // Now if Type is NewLineTypeUnknown, it should be file end
- //
- Type = NewLineTypeDefault;
- }
- LineSizeBackup = LineSize;
- //
- // create a new line
- //
- Line = FileBufferCreateLine ();
- if (Line == NULL) {
- SHELL_FREE_NON_NULL (Buffer);
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // calculate file length
- //
- LineSize -= LoopVar1;
- //
- // Unicode and one CHAR_NULL
- //
- SHELL_FREE_NON_NULL (Line->Buffer);
- Line->Buffer = AllocateZeroPool (LineSize * 2 + 2);
- if (Line->Buffer == NULL) {
- RemoveEntryList (&Line->Link);
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // copy this line to Line->Buffer
- //
- for (LoopVar2 = 0; LoopVar2 < LineSize; LoopVar2++) {
- if (FileBuffer.FileType == FileTypeAscii) {
- Line->Buffer[LoopVar2] = (CHAR16) AsciiBuffer[LoopVar1];
- } else {
- Line->Buffer[LoopVar2] = UnicodeBuffer[LoopVar1];
- }
- LoopVar1++;
- }
- //
- // LoopVar1 now points to where CHAR_CARRIAGE_RETURN or CHAR_LINEFEED;
- //
- Line->Buffer[LineSize] = 0;
- Line->Size = LineSize;
- Line->TotalSize = LineSize;
- Line->Type = Type;
- if (Type == NewLineTypeCarriageReturnLineFeed || Type == NewLineTypeLineFeedCarriageReturn) {
- LoopVar1++;
- }
- //
- // last character is a return, SO create a new line
- //
- if (((Type == NewLineTypeCarriageReturnLineFeed || Type == NewLineTypeLineFeedCarriageReturn) && LineSizeBackup == FileSize - 2) ||
- ((Type == NewLineTypeLineFeed || Type == NewLineTypeCarriageReturn) && LineSizeBackup == FileSize - 1)
- ) {
- Line = FileBufferCreateLine ();
- if (Line == NULL) {
- SHELL_FREE_NON_NULL (Buffer);
- return EFI_OUT_OF_RESOURCES;
- }
- }
- //
- // end of if
- //
- }
- //
- // end of LoopVar1
- //
- SHELL_FREE_NON_NULL (Buffer);
- }
- //
- // end of if CreateFile
- //
- Done:
- FileBuffer.DisplayPosition.Row = 2;
- FileBuffer.DisplayPosition.Column = 1;
- FileBuffer.LowVisibleRange.Row = 1;
- FileBuffer.LowVisibleRange.Column = 1;
- FileBuffer.FilePosition.Row = 1;
- FileBuffer.FilePosition.Column = 1;
- FileBuffer.MousePosition.Row = 2;
- FileBuffer.MousePosition.Column = 1;
- if (!Recover) {
- UnicodeBuffer = CatSPrint (NULL, L"%d Lines Read", FileBuffer.NumLines);
- if (UnicodeBuffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- StatusBarSetStatusString (UnicodeBuffer);
- FreePool (UnicodeBuffer);
- }
- /*
- //
- // check whether we have fs?: in filename
- //
- LoopVar1 = 0;
- FSMappingPtr = NULL;
- while (FileName[LoopVar1] != 0) {
- if (FileName[LoopVar1] == L':') {
- FSMappingPtr = &FileName[LoopVar1];
- break;
- }
- LoopVar1++;
- }
- if (FSMappingPtr == NULL) {
- CurDir = ShellGetCurrentDir (NULL);
- } else {
- LoopVar1 = 0;
- LoopVar2 = 0;
- while (FileName[LoopVar1] != 0) {
- if (FileName[LoopVar1] == L':') {
- break;
- }
- FSMapping[LoopVar2++] = FileName[LoopVar1];
- LoopVar1++;
- }
- FSMapping[LoopVar2] = 0;
- CurDir = ShellGetCurrentDir (FSMapping);
- }
- if (CurDir != NULL) {
- for (LoopVar1 = 0; LoopVar1 < StrLen (CurDir) && CurDir[LoopVar1] != ':'; LoopVar1++);
- CurDir[LoopVar1] = 0;
- DevicePath = (EFI_DEVICE_PATH_PROTOCOL *) ShellGetMap (CurDir);
- FreePool (CurDir);
- } else {
- return EFI_LOAD_ERROR;
- }
- Status = LibDevicePathToInterface (
- &gEfiSimpleFileSystemProtocolGuid,
- DevicePath,
- (VOID **) &Vol
- );
- if (EFI_ERROR (Status)) {
- return EFI_LOAD_ERROR;
- }
- Status = Vol->OpenVolume (Vol, &RootFs);
- if (EFI_ERROR (Status)) {
- return EFI_LOAD_ERROR;
- }
- //
- // Get volume information of file system
- //
- Size = SIZE_OF_EFI_FILE_SYSTEM_INFO + 100;
- VolumeInfo = (EFI_FILE_SYSTEM_INFO *) AllocateZeroPool (Size);
- Status = RootFs->GetInfo (RootFs, &gEfiFileSystemInfoGuid, &Size, VolumeInfo);
- if (EFI_ERROR (Status)) {
- RootFs->Close (RootFs);
- return EFI_LOAD_ERROR;
- }
- if (VolumeInfo->ReadOnly) {
- StatusBarSetStatusString (L"WARNING: Volume Read Only");
- }
- FreePool (VolumeInfo);
- RootFs->Close (RootFs);
- }
- //
- */
- //
- // has line
- //
- if (FileBuffer.Lines != 0) {
- FileBuffer.CurrentLine = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- } else {
- //
- // create a dummy line
- //
- Line = FileBufferCreateLine ();
- if (Line == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- FileBuffer.CurrentLine = Line;
- }
- FileBuffer.FileModified = FALSE;
- FileBufferNeedRefresh = TRUE;
- FileBufferOnlyLineNeedRefresh = FALSE;
- FileBufferMouseNeedRefresh = TRUE;
- return EFI_SUCCESS;
- }
- /**
- According to FileBuffer.NewLineType & FileBuffer.FileType,
- get the return buffer and size.
- @param[in] Type The type of line.
- @param[out] Buffer The buffer to fill.
- @param[out] Size The amount of the buffer used on return.
- **/
- VOID
- GetNewLine (
- IN CONST EE_NEWLINE_TYPE Type,
- OUT CHAR8 *Buffer,
- OUT UINT8 *Size
- )
- {
- UINT8 NewLineSize;
- //
- // give new line buffer,
- // and will judge unicode or ascii
- //
- NewLineSize = 0;
- //
- // not legal new line type
- //
- if (Type != NewLineTypeLineFeed && Type != NewLineTypeCarriageReturn && Type != NewLineTypeCarriageReturnLineFeed && Type != NewLineTypeLineFeedCarriageReturn) {
- *Size = 0;
- return ;
- }
- //
- // use_cr: give 0x0d
- //
- if (Type == NewLineTypeCarriageReturn) {
- if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
- Buffer[0] = 0x0d;
- Buffer[1] = 0;
- NewLineSize = 2;
- } else {
- Buffer[0] = 0x0d;
- NewLineSize = 1;
- }
- *Size = NewLineSize;
- return ;
- }
- //
- // use_lf: give 0x0a
- //
- if (Type == NewLineTypeLineFeed) {
- if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
- Buffer[0] = 0x0a;
- Buffer[1] = 0;
- NewLineSize = 2;
- } else {
- Buffer[0] = 0x0a;
- NewLineSize = 1;
- }
- *Size = NewLineSize;
- return ;
- }
- //
- // use_crlf: give 0x0d 0x0a
- //
- if (Type == NewLineTypeCarriageReturnLineFeed) {
- if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
- Buffer[0] = 0x0d;
- Buffer[1] = 0;
- Buffer[2] = 0x0a;
- Buffer[3] = 0;
- NewLineSize = 4;
- } else {
- Buffer[0] = 0x0d;
- Buffer[1] = 0x0a;
- NewLineSize = 2;
- }
- *Size = NewLineSize;
- return ;
- }
- //
- // use_lfcr: give 0x0a 0x0d
- //
- if (Type == NewLineTypeLineFeedCarriageReturn) {
- if (MainEditor.FileBuffer->FileType == FileTypeUnicode) {
- Buffer[0] = 0x0a;
- Buffer[1] = 0;
- Buffer[2] = 0x0d;
- Buffer[3] = 0;
- NewLineSize = 4;
- } else {
- Buffer[0] = 0x0a;
- Buffer[1] = 0x0d;
- NewLineSize = 2;
- }
- *Size = NewLineSize;
- return ;
- }
- }
- /**
- Change a Unicode string to an ASCII string.
- @param[in] UStr The Unicode string.
- @param[in] Length The maximum size of AStr.
- @param[out] AStr ASCII string to pass out.
- @return The actuall length.
- **/
- UINTN
- UnicodeToAscii (
- IN CONST CHAR16 *UStr,
- IN CONST UINTN Length,
- OUT CHAR8 *AStr
- )
- {
- UINTN Index;
- //
- // just buffer copy, not character copy
- //
- for (Index = 0; Index < Length; Index++) {
- *AStr++ = (CHAR8) *UStr++;
- }
- return Index;
- }
- /**
- Save lines in FileBuffer to disk
- @param[in] FileName The file name for writing.
- @retval EFI_SUCCESS Data was written.
- @retval EFI_LOAD_ERROR
- @retval EFI_OUT_OF_RESOURCES There were not enough resources to write the file.
- **/
- EFI_STATUS
- FileBufferSave (
- IN CONST CHAR16 *FileName
- )
- {
- SHELL_FILE_HANDLE FileHandle;
- LIST_ENTRY *Link;
- EFI_EDITOR_LINE *Line;
- CHAR16 *Str;
- EFI_STATUS Status;
- UINTN Length;
- UINTN NumLines;
- CHAR8 NewLineBuffer[4];
- UINT8 NewLineSize;
- EFI_FILE_INFO *Info;
- UINT64 Attribute;
- EE_NEWLINE_TYPE Type;
- UINTN TotalSize;
- //
- // 2M
- //
- CHAR8 *Cache;
- UINTN LeftSize;
- UINTN Size;
- CHAR8 *Ptr;
- Length = 0;
- //
- // 2M
- //
- TotalSize = 0x200000;
- Attribute = 0;
- //
- // if is the old file
- //
- if (FileBuffer.FileName != NULL && StrCmp (FileName, FileBuffer.FileName) == 0) {
- //
- // file has not been modified
- //
- if (!FileBuffer.FileModified) {
- return EFI_SUCCESS;
- }
- //
- // if file is read-only, set error
- //
- if (FileBuffer.ReadOnly) {
- StatusBarSetStatusString (L"Read Only File Can Not Be Saved");
- return EFI_SUCCESS;
- }
- }
- Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE, 0);
- if (!EFI_ERROR (Status)) {
- Info = ShellGetFileInfo(FileHandle);
- if (Info != NULL && Info->Attribute & EFI_FILE_DIRECTORY) {
- StatusBarSetStatusString (L"Directory Can Not Be Saved");
- ShellCloseFile (&FileHandle);
- FreePool(Info);
- return EFI_LOAD_ERROR;
- }
- if (Info != NULL) {
- Attribute = Info->Attribute & ~EFI_FILE_READ_ONLY;
- FreePool(Info);
- }
- //
- // if file exits, so delete it
- //
- Status = ShellDeleteFile (&FileHandle);
- if (EFI_ERROR (Status) || Status == EFI_WARN_DELETE_FAILURE) {
- StatusBarSetStatusString (L"Write File Failed");
- return EFI_LOAD_ERROR;
- }
- }
- Status = ShellOpenFileByName (FileName, &FileHandle, EFI_FILE_MODE_READ|EFI_FILE_MODE_WRITE|EFI_FILE_MODE_CREATE, Attribute);
- if (EFI_ERROR (Status)) {
- StatusBarSetStatusString (L"Create File Failed");
- return EFI_LOAD_ERROR;
- }
- //
- // if file is Unicode file, write Unicode header to it.
- //
- if (FileBuffer.FileType == FileTypeUnicode) {
- Length = 2;
- Status = ShellWriteFile (FileHandle, &Length, (VOID*)&gUnicodeFileTag);
- if (EFI_ERROR (Status)) {
- ShellDeleteFile (&FileHandle);
- return EFI_LOAD_ERROR;
- }
- }
- Cache = AllocateZeroPool (TotalSize);
- if (Cache == NULL) {
- ShellDeleteFile (&FileHandle);
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // write all the lines back to disk
- //
- NumLines = 0;
- Type = NewLineTypeCarriageReturnLineFeed;
- Ptr = Cache;
- LeftSize = TotalSize;
- for (Link = FileBuffer.ListHead->ForwardLink; Link != FileBuffer.ListHead; Link = Link->ForwardLink) {
- Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- if (Line->Type != NewLineTypeDefault) {
- Type = Line->Type;
- }
- //
- // newline character is at most 4 bytes ( two Unicode characters )
- //
- Length = 4;
- if (Line->Buffer != NULL && Line->Size != 0) {
- if (FileBuffer.FileType == FileTypeAscii) {
- Length += Line->Size;
- } else {
- Length += (Line->Size * 2);
- }
- //
- // end if FileTypeAscii
- //
- }
- //
- // no cache room left, so write cache to disk
- //
- if (LeftSize < Length) {
- Size = TotalSize - LeftSize;
- Status = ShellWriteFile (FileHandle, &Size, Cache);
- if (EFI_ERROR (Status)) {
- ShellDeleteFile (&FileHandle);
- FreePool (Cache);
- return EFI_LOAD_ERROR;
- }
- Ptr = Cache;
- LeftSize = TotalSize;
- }
- if (Line->Buffer != NULL && Line->Size != 0) {
- if (FileBuffer.FileType == FileTypeAscii) {
- UnicodeToAscii (Line->Buffer, Line->Size, Ptr);
- Length = Line->Size;
- } else {
- Length = (Line->Size * 2);
- CopyMem (Ptr, (CHAR8 *) Line->Buffer, Length);
- }
- //
- // end if FileTypeAscii
- //
- Ptr += Length;
- LeftSize -= Length;
- }
- //
- // end of if Line -> Buffer != NULL && Line -> Size != 0
- //
- // if not the last line , write return buffer to disk
- //
- if (Link->ForwardLink != FileBuffer.ListHead) {
- GetNewLine (Type, NewLineBuffer, &NewLineSize);
- CopyMem (Ptr, (CHAR8 *) NewLineBuffer, NewLineSize);
- Ptr += NewLineSize;
- LeftSize -= NewLineSize;
- }
- NumLines++;
- }
- if (TotalSize != LeftSize) {
- Size = TotalSize - LeftSize;
- Status = ShellWriteFile (FileHandle, &Size, Cache);
- if (EFI_ERROR (Status)) {
- ShellDeleteFile (&FileHandle);
- FreePool (Cache);
- return EFI_LOAD_ERROR;
- }
- }
- FreePool (Cache);
- ShellCloseFile(&FileHandle);
- FileBuffer.FileModified = FALSE;
- //
- // set status string
- //
- Str = CatSPrint (NULL, L"%d Lines Written", NumLines);
- if (Str == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- StatusBarSetStatusString (Str);
- SHELL_FREE_NON_NULL (Str);
- //
- // now everything is ready , you can set the new file name to filebuffer
- //
- if (FileName != NULL && FileBuffer.FileName != NULL && StrCmp (FileName, FileBuffer.FileName) != 0) {
- //
- // not the same
- //
- FileBufferSetFileName (FileName);
- if (FileBuffer.FileName == NULL) {
- ShellDeleteFile (&FileHandle);
- return EFI_OUT_OF_RESOURCES;
- }
- }
- FileBuffer.ReadOnly = FALSE;
- return EFI_SUCCESS;
- }
- /**
- Scroll cursor to left 1 character position.
- @retval EFI_SUCCESS The operation was successful.
- **/
- EFI_STATUS
- FileBufferScrollLeft (
- VOID
- )
- {
- EFI_EDITOR_LINE *Line;
- UINTN FRow;
- UINTN FCol;
- Line = FileBuffer.CurrentLine;
- FRow = FileBuffer.FilePosition.Row;
- FCol = FileBuffer.FilePosition.Column;
- //
- // if already at start of this line, so move to the end of previous line
- //
- if (FCol <= 1) {
- //
- // has previous line
- //
- if (Line->Link.BackLink != FileBuffer.ListHead) {
- FRow--;
- Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- FCol = Line->Size + 1;
- } else {
- return EFI_SUCCESS;
- }
- } else {
- //
- // if not at start of this line, just move to previous column
- //
- FCol--;
- }
- FileBufferMovePosition (FRow, FCol);
- return EFI_SUCCESS;
- }
- /**
- Delete a char in line
- @param[in, out] Line The line to delete in.
- @param[in] Pos Position to delete the char at ( start from 0 ).
- **/
- VOID
- LineDeleteAt (
- IN OUT EFI_EDITOR_LINE *Line,
- IN UINTN Pos
- )
- {
- UINTN Index;
- //
- // move the latter characters front
- //
- for (Index = Pos - 1; Index < Line->Size; Index++) {
- Line->Buffer[Index] = Line->Buffer[Index + 1];
- }
- Line->Size--;
- }
- /**
- Concatenate Src into Dest.
- @param[in, out] Dest Destination string
- @param[in] Src Src String.
- **/
- VOID
- LineCat (
- IN OUT EFI_EDITOR_LINE *Dest,
- IN EFI_EDITOR_LINE *Src
- )
- {
- CHAR16 *Str;
- UINTN Size;
- Size = Dest->Size;
- Dest->Buffer[Size] = 0;
- //
- // concatenate the two strings
- //
- Str = CatSPrint (NULL, L"%s%s", Dest->Buffer, Src->Buffer);
- if (Str == NULL) {
- Dest->Buffer = NULL;
- return ;
- }
- Dest->Size = Size + Src->Size;
- Dest->TotalSize = Dest->Size;
- FreePool (Dest->Buffer);
- FreePool (Src->Buffer);
- //
- // put str to dest->buffer
- //
- Dest->Buffer = Str;
- }
- /**
- Delete the previous character.
- @retval EFI_SUCCESS The delete was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- **/
- EFI_STATUS
- FileBufferDoBackspace (
- VOID
- )
- {
- EFI_EDITOR_LINE *Line;
- EFI_EDITOR_LINE *End;
- LIST_ENTRY *Link;
- UINTN FileColumn;
- FileColumn = FileBuffer.FilePosition.Column;
- Line = FileBuffer.CurrentLine;
- //
- // the first column
- //
- if (FileColumn == 1) {
- //
- // the first row
- //
- if (FileBuffer.FilePosition.Row == 1) {
- return EFI_SUCCESS;
- }
- FileBufferScrollLeft ();
- Line = FileBuffer.CurrentLine;
- Link = Line->Link.ForwardLink;
- End = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- //
- // concatenate this line with previous line
- //
- LineCat (Line, End);
- if (Line->Buffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // remove End from line list
- //
- RemoveEntryList (&End->Link);
- FreePool (End);
- FileBuffer.NumLines--;
- FileBufferNeedRefresh = TRUE;
- FileBufferOnlyLineNeedRefresh = FALSE;
- } else {
- //
- // just delete the previous character
- //
- LineDeleteAt (Line, FileColumn - 1);
- FileBufferScrollLeft ();
- FileBufferOnlyLineNeedRefresh = TRUE;
- }
- if (!FileBuffer.FileModified) {
- FileBuffer.FileModified = TRUE;
- }
- return EFI_SUCCESS;
- }
- /**
- Add a return into line at current position.
- @retval EFI_SUCCESS The insetrion of the character was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- **/
- EFI_STATUS
- FileBufferDoReturn (
- VOID
- )
- {
- EFI_EDITOR_LINE *Line;
- EFI_EDITOR_LINE *NewLine;
- UINTN FileColumn;
- UINTN Index;
- CHAR16 *Buffer;
- UINTN Row;
- UINTN Col;
- FileBufferNeedRefresh = TRUE;
- FileBufferOnlyLineNeedRefresh = FALSE;
- Line = FileBuffer.CurrentLine;
- FileColumn = FileBuffer.FilePosition.Column;
- NewLine = AllocateZeroPool (sizeof (EFI_EDITOR_LINE));
- if (NewLine == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- NewLine->Signature = LINE_LIST_SIGNATURE;
- NewLine->Size = Line->Size - FileColumn + 1;
- NewLine->TotalSize = NewLine->Size;
- NewLine->Buffer = CatSPrint (NULL, L"\0");
- if (NewLine->Buffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- NewLine->Type = NewLineTypeDefault;
- if (NewLine->Size > 0) {
- //
- // UNICODE + CHAR_NULL
- //
- Buffer = AllocateZeroPool (2 * (NewLine->Size + 1));
- if (Buffer == NULL) {
- FreePool (NewLine->Buffer);
- FreePool (NewLine);
- return EFI_OUT_OF_RESOURCES;
- }
- FreePool (NewLine->Buffer);
- NewLine->Buffer = Buffer;
- for (Index = 0; Index < NewLine->Size; Index++) {
- NewLine->Buffer[Index] = Line->Buffer[Index + FileColumn - 1];
- }
- NewLine->Buffer[NewLine->Size] = CHAR_NULL;
- Line->Buffer[FileColumn - 1] = CHAR_NULL;
- Line->Size = FileColumn - 1;
- }
- //
- // increase NumLines
- //
- FileBuffer.NumLines++;
- //
- // insert it into the correct position of line list
- //
- NewLine->Link.BackLink = &(Line->Link);
- NewLine->Link.ForwardLink = Line->Link.ForwardLink;
- Line->Link.ForwardLink->BackLink = &(NewLine->Link);
- Line->Link.ForwardLink = &(NewLine->Link);
- //
- // move cursor to the start of next line
- //
- Row = FileBuffer.FilePosition.Row + 1;
- Col = 1;
- FileBufferMovePosition (Row, Col);
- //
- // set file is modified
- //
- if (!FileBuffer.FileModified) {
- FileBuffer.FileModified = TRUE;
- }
- return EFI_SUCCESS;
- }
- /**
- Delete current character from current line. This is the effect caused
- by the 'del' key.
- @retval EFI_SUCCESS
- **/
- EFI_STATUS
- FileBufferDoDelete (
- VOID
- )
- {
- EFI_EDITOR_LINE *Line;
- EFI_EDITOR_LINE *Next;
- LIST_ENTRY *Link;
- UINTN FileColumn;
- Line = FileBuffer.CurrentLine;
- FileColumn = FileBuffer.FilePosition.Column;
- //
- // the last column
- //
- if (FileColumn >= Line->Size + 1) {
- //
- // the last line
- //
- if (Line->Link.ForwardLink == FileBuffer.ListHead) {
- return EFI_SUCCESS;
- }
- //
- // since last character,
- // so will add the next line to this line
- //
- Link = Line->Link.ForwardLink;
- Next = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- LineCat (Line, Next);
- if (Line->Buffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- RemoveEntryList (&Next->Link);
- FreePool (Next);
- FileBuffer.NumLines--;
- FileBufferNeedRefresh = TRUE;
- FileBufferOnlyLineNeedRefresh = FALSE;
- } else {
- //
- // just delete current character
- //
- LineDeleteAt (Line, FileColumn);
- FileBufferOnlyLineNeedRefresh = TRUE;
- }
- if (!FileBuffer.FileModified) {
- FileBuffer.FileModified = TRUE;
- }
- return EFI_SUCCESS;
- }
- /**
- Scroll cursor to right 1 character.
- @retval EFI_SUCCESS The operation was successful.
- **/
- EFI_STATUS
- FileBufferScrollRight (
- VOID
- )
- {
- EFI_EDITOR_LINE *Line;
- UINTN FRow;
- UINTN FCol;
- Line = FileBuffer.CurrentLine;
- if (Line->Buffer == NULL) {
- return EFI_SUCCESS;
- }
- FRow = FileBuffer.FilePosition.Row;
- FCol = FileBuffer.FilePosition.Column;
- //
- // if already at end of this line, scroll it to the start of next line
- //
- if (FCol > Line->Size) {
- //
- // has next line
- //
- if (Line->Link.ForwardLink != FileBuffer.ListHead) {
- FRow++;
- FCol = 1;
- } else {
- return EFI_SUCCESS;
- }
- } else {
- //
- // if not at end of this line, just move to next column
- //
- FCol++;
- }
- FileBufferMovePosition (FRow, FCol);
- return EFI_SUCCESS;
- }
- /**
- Insert a char into line
- @param[in] Line The line to insert into.
- @param[in] Char The char to insert.
- @param[in] Pos The position to insert the char at ( start from 0 ).
- @param[in] StrSize The current string size ( include CHAR_NULL ),unit is Unicode character.
- @return The new string size ( include CHAR_NULL ) ( unit is Unicode character ).
- **/
- UINTN
- LineStrInsert (
- IN EFI_EDITOR_LINE *Line,
- IN CHAR16 Char,
- IN UINTN Pos,
- IN UINTN StrSize
- )
- {
- UINTN Index;
- CHAR16 *TempStringPtr;
- CHAR16 *Str;
- Index = (StrSize) * 2;
- Str = Line->Buffer;
- //
- // do not have free space
- //
- if (Line->TotalSize <= Line->Size) {
- Str = ReallocatePool (Index, Index + 16, Str);
- if (Str == NULL) {
- return 0;
- }
- Line->TotalSize += 8;
- }
- //
- // move the later part of the string one character right
- //
- TempStringPtr = Str;
- for (Index = StrSize; Index > Pos; Index--) {
- TempStringPtr[Index] = TempStringPtr[Index - 1];
- }
- //
- // insert char into it.
- //
- TempStringPtr[Index] = Char;
- Line->Buffer = Str;
- Line->Size++;
- return StrSize + 1;
- }
- /**
- Add a character to the current line.
- @param[in] Char The Character to input.
- @retval EFI_SUCCESS The input was succesful.
- **/
- EFI_STATUS
- FileBufferAddChar (
- IN CHAR16 Char
- )
- {
- EFI_EDITOR_LINE *Line;
- UINTN FilePos;
- Line = FileBuffer.CurrentLine;
- //
- // only needs to refresh current line
- //
- FileBufferOnlyLineNeedRefresh = TRUE;
- //
- // when is insert mode, or cursor is at end of this line,
- // so insert this character
- // or replace the character.
- //
- FilePos = FileBuffer.FilePosition.Column - 1;
- if (FileBuffer.ModeInsert || FilePos + 1 > Line->Size) {
- LineStrInsert (Line, Char, FilePos, Line->Size + 1);
- } else {
- Line->Buffer[FilePos] = Char;
- }
- //
- // move cursor to right
- //
- FileBufferScrollRight ();
- if (!FileBuffer.FileModified) {
- FileBuffer.FileModified = TRUE;
- }
- return EFI_SUCCESS;
- }
- /**
- Handles inputs from characters (ASCII key + Backspace + return)
- @param[in] Char The input character.
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_LOAD_ERROR There was an error.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- **/
- EFI_STATUS
- FileBufferDoCharInput (
- IN CONST CHAR16 Char
- )
- {
- EFI_STATUS Status;
- Status = EFI_SUCCESS;
- switch (Char) {
- case CHAR_NULL:
- break;
- case CHAR_BACKSPACE:
- Status = FileBufferDoBackspace ();
- break;
- case CHAR_TAB:
- //
- // Tabs are ignored
- //
- break;
- case CHAR_LINEFEED:
- case CHAR_CARRIAGE_RETURN:
- Status = FileBufferDoReturn ();
- break;
- default:
- //
- // DEAL WITH ASCII CHAR, filter out thing like ctrl+f
- //
- if (Char > 127 || Char < 32) {
- Status = StatusBarSetStatusString (L"Unknown Command");
- } else {
- Status = FileBufferAddChar (Char);
- }
- break;
- }
- return Status;
- }
- /**
- Scroll cursor to the next line.
- @retval EFI_SUCCESS The operation was successful.
- **/
- EFI_STATUS
- FileBufferScrollDown (
- VOID
- )
- {
- EFI_EDITOR_LINE *Line;
- UINTN FRow;
- UINTN FCol;
- Line = FileBuffer.CurrentLine;
- if (Line->Buffer == NULL) {
- return EFI_SUCCESS;
- }
- FRow = FileBuffer.FilePosition.Row;
- FCol = FileBuffer.FilePosition.Column;
- //
- // has next line
- //
- if (Line->Link.ForwardLink != FileBuffer.ListHead) {
- FRow++;
- Line = CR (Line->Link.ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- //
- // if the next line is not that long, so move to end of next line
- //
- if (FCol > Line->Size) {
- FCol = Line->Size + 1;
- }
- } else {
- return EFI_SUCCESS;
- }
- FileBufferMovePosition (FRow, FCol);
- return EFI_SUCCESS;
- }
- /**
- Scroll the cursor to previous line.
- @retval EFI_SUCCESS The operation was successful.
- **/
- EFI_STATUS
- FileBufferScrollUp (
- VOID
- )
- {
- EFI_EDITOR_LINE *Line;
- UINTN FRow;
- UINTN FCol;
- Line = FileBuffer.CurrentLine;
- FRow = FileBuffer.FilePosition.Row;
- FCol = FileBuffer.FilePosition.Column;
- //
- // has previous line
- //
- if (Line->Link.BackLink != FileBuffer.ListHead) {
- FRow--;
- Line = CR (Line->Link.BackLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- //
- // if previous line is not that long, so move to the end of previous line
- //
- if (FCol > Line->Size) {
- FCol = Line->Size + 1;
- }
- } else {
- return EFI_SUCCESS;
- }
- FileBufferMovePosition (FRow, FCol);
- return EFI_SUCCESS;
- }
- /**
- Scroll cursor to next page.
- @retval EFI_SUCCESS The operation wa successful.
- **/
- EFI_STATUS
- FileBufferPageDown (
- VOID
- )
- {
- EFI_EDITOR_LINE *Line;
- UINTN FRow;
- UINTN FCol;
- UINTN Gap;
- Line = FileBuffer.CurrentLine;
- FRow = FileBuffer.FilePosition.Row;
- FCol = FileBuffer.FilePosition.Column;
- //
- // has next page
- //
- if (FileBuffer.NumLines >= FRow + (MainEditor.ScreenSize.Row - 2)) {
- Gap = (MainEditor.ScreenSize.Row - 2);
- } else {
- //
- // MOVE CURSOR TO LAST LINE
- //
- Gap = FileBuffer.NumLines - FRow;
- }
- //
- // get correct line
- //
- Line = MoveLine (Gap);
- //
- // if that line, is not that long, so move to the end of that line
- //
- if (Line != NULL && FCol > Line->Size) {
- FCol = Line->Size + 1;
- }
- FRow += Gap;
- FileBufferMovePosition (FRow, FCol);
- return EFI_SUCCESS;
- }
- /**
- Scroll cursor to previous screen.
- @retval EFI_SUCCESS The operation was successful.
- **/
- EFI_STATUS
- FileBufferPageUp (
- VOID
- )
- {
- EFI_EDITOR_LINE *Line;
- UINTN FRow;
- UINTN FCol;
- UINTN Gap;
- INTN Retreat;
- Line = FileBuffer.CurrentLine;
- FRow = FileBuffer.FilePosition.Row;
- FCol = FileBuffer.FilePosition.Column;
- //
- // has previous page
- //
- if (FRow > (MainEditor.ScreenSize.Row - 2)) {
- Gap = (MainEditor.ScreenSize.Row - 2);
- } else {
- //
- // the first line of file will displayed on the first line of screen
- //
- Gap = FRow - 1;
- }
- Retreat = Gap;
- Retreat = -Retreat;
- //
- // get correct line
- //
- Line = MoveLine (Retreat);
- //
- // if that line is not that long, so move to the end of that line
- //
- if (Line != NULL && FCol > Line->Size) {
- FCol = Line->Size + 1;
- }
- FRow -= Gap;
- FileBufferMovePosition (FRow, FCol);
- return EFI_SUCCESS;
- }
- /**
- Scroll cursor to end of the current line.
- @retval EFI_SUCCESS The operation was successful.
- **/
- EFI_STATUS
- FileBufferEnd (
- VOID
- )
- {
- EFI_EDITOR_LINE *Line;
- UINTN FRow;
- UINTN FCol;
- Line = FileBuffer.CurrentLine;
- FRow = FileBuffer.FilePosition.Row;
- //
- // goto the last column of the line
- //
- FCol = Line->Size + 1;
- FileBufferMovePosition (FRow, FCol);
- return EFI_SUCCESS;
- }
- /**
- Dispatch input to different handler
- @param[in] Key The input key. One of:
- ASCII KEY
- Backspace/Delete
- Return
- Direction key: up/down/left/right/pgup/pgdn
- Home/End
- INS
- @retval EFI_SUCCESS The dispatch was done successfully.
- @retval EFI_LOAD_ERROR The dispatch was not successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- **/
- EFI_STATUS
- FileBufferHandleInput (
- IN CONST EFI_INPUT_KEY *Key
- )
- {
- EFI_STATUS Status;
- Status = EFI_SUCCESS;
- switch (Key->ScanCode) {
- //
- // ordinary key input
- //
- case SCAN_NULL:
- if (!FileBuffer.ReadOnly) {
- Status = FileBufferDoCharInput (Key->UnicodeChar);
- } else {
- Status = StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
- }
- break;
- //
- // up arrow
- //
- case SCAN_UP:
- Status = FileBufferScrollUp ();
- break;
- //
- // down arrow
- //
- case SCAN_DOWN:
- Status = FileBufferScrollDown ();
- break;
- //
- // right arrow
- //
- case SCAN_RIGHT:
- Status = FileBufferScrollRight ();
- break;
- //
- // left arrow
- //
- case SCAN_LEFT:
- Status = FileBufferScrollLeft ();
- break;
- //
- // page up
- //
- case SCAN_PAGE_UP:
- Status = FileBufferPageUp ();
- break;
- //
- // page down
- //
- case SCAN_PAGE_DOWN:
- Status = FileBufferPageDown ();
- break;
- //
- // delete
- //
- case SCAN_DELETE:
- if (!FileBuffer.ReadOnly) {
- Status = FileBufferDoDelete ();
- } else {
- Status = StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
- }
- break;
- //
- // home
- //
- case SCAN_HOME:
- FileBufferMovePosition (FileBuffer.FilePosition.Row, 1);
- Status = EFI_SUCCESS;
- break;
- //
- // end
- //
- case SCAN_END:
- Status = FileBufferEnd ();
- break;
- //
- // insert
- //
- case SCAN_INSERT:
- FileBuffer.ModeInsert = (BOOLEAN)!FileBuffer.ModeInsert;
- Status = EFI_SUCCESS;
- break;
- default:
- Status = StatusBarSetStatusString (L"Unknown Command");
- break;
- }
- return Status;
- }
- /**
- Check user specified FileRow is above current screen.
- @param[in] FileRow The row of file position ( start from 1 ).
- @retval TRUE It is above the current screen.
- @retval FALSE It is not above the current screen.
- **/
- BOOLEAN
- AboveCurrentScreen (
- IN UINTN FileRow
- )
- {
- //
- // if is to the above of the screen
- //
- if (FileRow < FileBuffer.LowVisibleRange.Row) {
- return TRUE;
- }
- return FALSE;
- }
- /**
- Check user specified FileRow is under current screen.
- @param[in] FileRow The row of file position ( start from 1 ).
- @retval TRUE It is under the current screen.
- @retval FALSE It is not under the current screen.
- **/
- BOOLEAN
- UnderCurrentScreen (
- IN UINTN FileRow
- )
- {
- //
- // if is to the under of the screen
- //
- if (FileRow > FileBuffer.LowVisibleRange.Row + (MainEditor.ScreenSize.Row - 2) - 1) {
- return TRUE;
- }
- return FALSE;
- }
- /**
- Check user specified FileCol is left to current screen.
- @param[in] FileCol The column of file position ( start from 1 ).
- @retval TRUE It is to the left.
- @retval FALSE It is not to the left.
- **/
- BOOLEAN
- LeftCurrentScreen (
- IN UINTN FileCol
- )
- {
- //
- // if is to the left of the screen
- //
- if (FileCol < FileBuffer.LowVisibleRange.Column) {
- return TRUE;
- }
- return FALSE;
- }
- /**
- Check user specified FileCol is right to current screen.
- @param[in] FileCol The column of file position ( start from 1 ).
- @retval TRUE It is to the right.
- @retval FALSE It is not to the right.
- **/
- BOOLEAN
- RightCurrentScreen (
- IN UINTN FileCol
- )
- {
- //
- // if is to the right of the screen
- //
- if (FileCol > FileBuffer.LowVisibleRange.Column + MainEditor.ScreenSize.Column - 1) {
- return TRUE;
- }
- return FALSE;
- }
- /**
- Advance/Retreat lines and set CurrentLine in FileBuffer to it
- @param[in] Count The line number to advance/retreat
- >0 : advance
- <0: retreat
- @retval NULL An error occurred.
- @return The line after advance/retreat.
- **/
- EFI_EDITOR_LINE *
- MoveCurrentLine (
- IN INTN Count
- )
- {
- EFI_EDITOR_LINE *Line;
- UINTN AbsCount;
- if (Count <= 0) {
- AbsCount = (UINTN)ABS(Count);
- Line = InternalEditorMiscLineRetreat (AbsCount,MainEditor.FileBuffer->CurrentLine,MainEditor.FileBuffer->ListHead);
- } else {
- Line = InternalEditorMiscLineAdvance ((UINTN)Count,MainEditor.FileBuffer->CurrentLine,MainEditor.FileBuffer->ListHead);
- }
- if (Line == NULL) {
- return NULL;
- }
- MainEditor.FileBuffer->CurrentLine = Line;
- return Line;
- }
- /**
- According to cursor's file position, adjust screen display
- @param[in] NewFilePosRow The row of file position ( start from 1 ).
- @param[in] NewFilePosCol The column of file position ( start from 1 ).
- **/
- VOID
- FileBufferMovePosition (
- IN CONST UINTN NewFilePosRow,
- IN CONST UINTN NewFilePosCol
- )
- {
- INTN RowGap;
- INTN ColGap;
- UINTN Abs;
- BOOLEAN Above;
- BOOLEAN Under;
- BOOLEAN Right;
- BOOLEAN Left;
- //
- // CALCULATE gap between current file position and new file position
- //
- RowGap = NewFilePosRow - FileBuffer.FilePosition.Row;
- ColGap = NewFilePosCol - FileBuffer.FilePosition.Column;
- Under = UnderCurrentScreen (NewFilePosRow);
- Above = AboveCurrentScreen (NewFilePosRow);
- //
- // if is below current screen
- //
- if (Under) {
- //
- // display row will be unchanged
- //
- FileBuffer.FilePosition.Row = NewFilePosRow;
- } else {
- if (Above) {
- //
- // has enough above line, so display row unchanged
- // not has enough above lines, so the first line is at the
- // first display line
- //
- if (NewFilePosRow < (FileBuffer.DisplayPosition.Row - 1)) {
- FileBuffer.DisplayPosition.Row = NewFilePosRow + 1;
- }
- FileBuffer.FilePosition.Row = NewFilePosRow;
- } else {
- //
- // in current screen
- //
- FileBuffer.FilePosition.Row = NewFilePosRow;
- if (RowGap < 0) {
- Abs = (UINTN)ABS(RowGap);
- FileBuffer.DisplayPosition.Row -= Abs;
- } else {
- FileBuffer.DisplayPosition.Row += RowGap;
- }
- }
- }
- FileBuffer.LowVisibleRange.Row = FileBuffer.FilePosition.Row - (FileBuffer.DisplayPosition.Row - 2);
- Right = RightCurrentScreen (NewFilePosCol);
- Left = LeftCurrentScreen (NewFilePosCol);
- //
- // if right to current screen
- //
- if (Right) {
- //
- // display column will be changed to end
- //
- FileBuffer.DisplayPosition.Column = MainEditor.ScreenSize.Column;
- FileBuffer.FilePosition.Column = NewFilePosCol;
- } else {
- if (Left) {
- //
- // has enough left characters , so display row unchanged
- // not has enough left characters,
- // so the first character is at the first display column
- //
- if (NewFilePosCol < (FileBuffer.DisplayPosition.Column)) {
- FileBuffer.DisplayPosition.Column = NewFilePosCol;
- }
- FileBuffer.FilePosition.Column = NewFilePosCol;
- } else {
- //
- // in current screen
- //
- FileBuffer.FilePosition.Column = NewFilePosCol;
- if (ColGap < 0) {
- Abs = (UINTN)(-ColGap);
- FileBuffer.DisplayPosition.Column -= Abs;
- } else {
- FileBuffer.DisplayPosition.Column += ColGap;
- }
- }
- }
- FileBuffer.LowVisibleRange.Column = FileBuffer.FilePosition.Column - (FileBuffer.DisplayPosition.Column - 1);
- //
- // let CurrentLine point to correct line;
- //
- FileBuffer.CurrentLine = MoveCurrentLine (RowGap);
- }
- /**
- Cut current line out and return a pointer to it.
- @param[out] CutLine Upon a successful return pointer to the pointer to
- the allocated cut line.
- @retval EFI_SUCCESS The cut was successful.
- @retval EFI_NOT_FOUND There was no selection to cut.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- **/
- EFI_STATUS
- FileBufferCutLine (
- OUT EFI_EDITOR_LINE **CutLine
- )
- {
- EFI_EDITOR_LINE *Line;
- EFI_EDITOR_LINE *NewLine;
- UINTN Row;
- UINTN Col;
- if (FileBuffer.ReadOnly) {
- StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
- return EFI_SUCCESS;
- }
- Line = FileBuffer.CurrentLine;
- //
- // if is the last dummy line, SO CAN not cut
- //
- if (StrCmp (Line->Buffer, L"\0") == 0 && Line->Link.ForwardLink == FileBuffer.ListHead
- //
- // last line
- //
- ) {
- //
- // LAST LINE AND NOTHING ON THIS LINE, SO CUT NOTHING
- //
- StatusBarSetStatusString (L"Nothing to Cut");
- return EFI_NOT_FOUND;
- }
- //
- // if is the last line, so create a dummy line
- //
- if (Line->Link.ForwardLink == FileBuffer.ListHead) {
- //
- // last line
- // create a new line
- //
- NewLine = FileBufferCreateLine ();
- if (NewLine == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- }
- FileBuffer.NumLines--;
- Row = FileBuffer.FilePosition.Row;
- Col = 1;
- //
- // move home
- //
- FileBuffer.CurrentLine = CR (
- FileBuffer.CurrentLine->Link.ForwardLink,
- EFI_EDITOR_LINE,
- Link,
- LINE_LIST_SIGNATURE
- );
- RemoveEntryList (&Line->Link);
- FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- FileBufferMovePosition (Row, Col);
- FileBuffer.FileModified = TRUE;
- FileBufferNeedRefresh = TRUE;
- FileBufferOnlyLineNeedRefresh = FALSE;
- *CutLine = Line;
- return EFI_SUCCESS;
- }
- /**
- Paste a line into line list.
- @retval EFI_SUCCESS The paste was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- **/
- EFI_STATUS
- FileBufferPasteLine (
- VOID
- )
- {
- EFI_EDITOR_LINE *Line;
- EFI_EDITOR_LINE *NewLine;
- UINTN Row;
- UINTN Col;
- //
- // if nothing is on clip board
- // then do nothing
- //
- if (MainEditor.CutLine == NULL) {
- return EFI_SUCCESS;
- }
- //
- // read only file can not be pasted on
- //
- if (FileBuffer.ReadOnly) {
- StatusBarSetStatusString (L"Read Only File Can Not Be Modified");
- return EFI_SUCCESS;
- }
- NewLine = LineDup (MainEditor.CutLine);
- if (NewLine == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // insert it above current line
- //
- Line = FileBuffer.CurrentLine;
- NewLine->Link.BackLink = Line->Link.BackLink;
- NewLine->Link.ForwardLink = &Line->Link;
- Line->Link.BackLink->ForwardLink = &NewLine->Link;
- Line->Link.BackLink = &NewLine->Link;
- FileBuffer.NumLines++;
- FileBuffer.CurrentLine = NewLine;
- FileBuffer.Lines = CR (FileBuffer.ListHead->ForwardLink, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- Col = 1;
- //
- // move home
- //
- Row = FileBuffer.FilePosition.Row;
- FileBufferMovePosition (Row, Col);
- //
- // after paste, set some value so that refresh knows to do something
- //
- FileBuffer.FileModified = TRUE;
- FileBufferNeedRefresh = TRUE;
- FileBufferOnlyLineNeedRefresh = FALSE;
- return EFI_SUCCESS;
- }
- /**
- Search string from current position on in file
- @param[in] Str The search string.
- @param[in] Offset The offset from current position.
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_NOT_FOUND The string Str was not found.
- **/
- EFI_STATUS
- FileBufferSearch (
- IN CONST CHAR16 *Str,
- IN CONST UINTN Offset
- )
- {
- CHAR16 *Current;
- UINTN Position;
- UINTN Row;
- UINTN Column;
- EFI_EDITOR_LINE *Line;
- CHAR16 *CharPos;
- LIST_ENTRY *Link;
- BOOLEAN Found;
- Column = 0;
- Position = 0;
- //
- // search if in current line
- //
- Current = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1 + Offset;
- if (Current >= (FileBuffer.CurrentLine->Buffer + FileBuffer.CurrentLine->Size)) {
- //
- // the end
- //
- Current = FileBuffer.CurrentLine->Buffer + FileBuffer.CurrentLine->Size;
- }
- Found = FALSE;
- CharPos = StrStr (Current, Str);
- if (CharPos != NULL) {
- Position = CharPos - Current + 1;
- Found = TRUE;
- }
- //
- // found
- //
- if (Found) {
- Column = (Position - 1) + FileBuffer.FilePosition.Column + Offset;
- Row = FileBuffer.FilePosition.Row;
- } else {
- //
- // not found so find through next lines
- //
- Link = FileBuffer.CurrentLine->Link.ForwardLink;
- Row = FileBuffer.FilePosition.Row + 1;
- while (Link != FileBuffer.ListHead) {
- Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- // Position = StrStr (Line->Buffer, Str);
- CharPos = StrStr (Line->Buffer, Str);
- if (CharPos != NULL) {
- Position = CharPos - Line->Buffer + 1;
- Found = TRUE;
- }
- if (Found) {
- //
- // found
- //
- Column = Position;
- break;
- }
- Row++;
- Link = Link->ForwardLink;
- }
- if (Link == FileBuffer.ListHead) {
- Found = FALSE;
- } else {
- Found = TRUE;
- }
- }
- if (!Found) {
- return EFI_NOT_FOUND;
- }
- FileBufferMovePosition (Row, Column);
- //
- // call refresh to fresh edit area,
- // because the outer may loop to find multiply occurrence of this string
- //
- FileBufferRefresh ();
- return EFI_SUCCESS;
- }
- /**
- Replace SearchLen characters from current position on with Replace.
- This will modify the current buffer at the current position.
- @param[in] Replace The string to replace.
- @param[in] SearchLen Search string's length.
- @retval EFI_SUCCESS The operation was successful.
- @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
- **/
- EFI_STATUS
- FileBufferReplace (
- IN CONST CHAR16 *Replace,
- IN CONST UINTN SearchLen
- )
- {
- UINTN ReplaceLen;
- UINTN Index;
- CHAR16 *Buffer;
- UINTN NewSize;
- UINTN OldSize;
- UINTN Gap;
- ReplaceLen = StrLen (Replace);
- OldSize = FileBuffer.CurrentLine->Size + 1;
- //
- // include CHAR_NULL
- //
- NewSize = OldSize + (ReplaceLen - SearchLen);
- if (ReplaceLen > SearchLen) {
- //
- // do not have the enough space
- //
- if (FileBuffer.CurrentLine->TotalSize + 1 <= NewSize) {
- FileBuffer.CurrentLine->Buffer = ReallocatePool (
- 2 * OldSize,
- 2 * NewSize,
- FileBuffer.CurrentLine->Buffer
- );
- FileBuffer.CurrentLine->TotalSize = NewSize - 1;
- }
- if (FileBuffer.CurrentLine->Buffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // the end CHAR_NULL character;
- //
- Buffer = FileBuffer.CurrentLine->Buffer + (NewSize - 1);
- Gap = ReplaceLen - SearchLen;
- //
- // keep the latter part
- //
- for (Index = 0; Index < (FileBuffer.CurrentLine->Size - FileBuffer.FilePosition.Column - SearchLen + 2); Index++) {
- *Buffer = *(Buffer - Gap);
- Buffer--;
- }
- //
- // set replace into it
- //
- Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1;
- for (Index = 0; Index < ReplaceLen; Index++) {
- Buffer[Index] = Replace[Index];
- }
- }
- if (ReplaceLen < SearchLen) {
- Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1;
- for (Index = 0; Index < ReplaceLen; Index++) {
- Buffer[Index] = Replace[Index];
- }
- Buffer += ReplaceLen;
- Gap = SearchLen - ReplaceLen;
- //
- // set replace into it
- //
- for (Index = 0; Index < (FileBuffer.CurrentLine->Size - FileBuffer.FilePosition.Column - ReplaceLen + 2); Index++) {
- *Buffer = *(Buffer + Gap);
- Buffer++;
- }
- }
- if (ReplaceLen == SearchLen) {
- Buffer = FileBuffer.CurrentLine->Buffer + FileBuffer.FilePosition.Column - 1;
- for (Index = 0; Index < ReplaceLen; Index++) {
- Buffer[Index] = Replace[Index];
- }
- }
- FileBuffer.CurrentLine->Size += (ReplaceLen - SearchLen);
- FileBufferOnlyLineNeedRefresh = TRUE;
- FileBuffer.FileModified = TRUE;
- MainTitleBarRefresh (MainEditor.FileBuffer->FileName, MainEditor.FileBuffer->FileType, MainEditor.FileBuffer->ReadOnly, MainEditor.FileBuffer->FileModified, MainEditor.ScreenSize.Column, MainEditor.ScreenSize.Row, 0, 0);
- FileBufferRestorePosition ();
- FileBufferRefresh ();
- return EFI_SUCCESS;
- }
- /**
- Move the mouse cursor position.
- @param[in] TextX The new x-coordinate.
- @param[in] TextY The new y-coordinate.
- **/
- VOID
- FileBufferAdjustMousePosition (
- IN CONST INT32 TextX,
- IN CONST INT32 TextY
- )
- {
- UINTN CoordinateX;
- UINTN CoordinateY;
- UINTN AbsX;
- UINTN AbsY;
- //
- // TextX and TextY is mouse movement data returned by mouse driver
- // This function will change it to MousePosition
- //
- //
- // get absolute value
- //
- AbsX = ABS(TextX);
- AbsY = ABS(TextY);
- CoordinateX = FileBuffer.MousePosition.Column;
- CoordinateY = FileBuffer.MousePosition.Row;
- if (TextX >= 0) {
- CoordinateX += TextX;
- } else {
- if (CoordinateX >= AbsX) {
- CoordinateX -= AbsX;
- } else {
- CoordinateX = 0;
- }
- }
- if (TextY >= 0) {
- CoordinateY += TextY;
- } else {
- if (CoordinateY >= AbsY) {
- CoordinateY -= AbsY;
- } else {
- CoordinateY = 0;
- }
- }
- //
- // check whether new mouse column position is beyond screen
- // if not, adjust it
- //
- if (CoordinateX >= 1 && CoordinateX <= MainEditor.ScreenSize.Column) {
- FileBuffer.MousePosition.Column = CoordinateX;
- } else if (CoordinateX < 1) {
- FileBuffer.MousePosition.Column = 1;
- } else if (CoordinateX > MainEditor.ScreenSize.Column) {
- FileBuffer.MousePosition.Column = MainEditor.ScreenSize.Column;
- }
- //
- // check whether new mouse row position is beyond screen
- // if not, adjust it
- //
- if (CoordinateY >= 2 && CoordinateY <= (MainEditor.ScreenSize.Row - 1)) {
- FileBuffer.MousePosition.Row = CoordinateY;
- } else if (CoordinateY < 2) {
- FileBuffer.MousePosition.Row = 2;
- } else if (CoordinateY > (MainEditor.ScreenSize.Row - 1)) {
- FileBuffer.MousePosition.Row = (MainEditor.ScreenSize.Row - 1);
- }
- }
- /**
- Search and replace operation.
- @param[in] SearchStr The string to search for.
- @param[in] ReplaceStr The string to replace with.
- @param[in] Offset The column to start at.
- **/
- EFI_STATUS
- FileBufferReplaceAll (
- IN CHAR16 *SearchStr,
- IN CHAR16 *ReplaceStr,
- IN UINTN Offset
- )
- {
- CHAR16 *Buffer;
- UINTN Position;
- UINTN Column;
- UINTN ReplaceLen;
- UINTN SearchLen;
- UINTN Index;
- UINTN NewSize;
- UINTN OldSize;
- UINTN Gap;
- EFI_EDITOR_LINE *Line;
- LIST_ENTRY *Link;
- CHAR16 *CharPos;
- SearchLen = StrLen (SearchStr);
- ReplaceLen = StrLen (ReplaceStr);
- Column = FileBuffer.FilePosition.Column + Offset - 1;
- if (Column > FileBuffer.CurrentLine->Size) {
- Column = FileBuffer.CurrentLine->Size;
- }
- Link = &(FileBuffer.CurrentLine->Link);
- while (Link != FileBuffer.ListHead) {
- Line = CR (Link, EFI_EDITOR_LINE, Link, LINE_LIST_SIGNATURE);
- CharPos = StrStr (Line->Buffer + Column, SearchStr);
- if (CharPos != NULL) {
- Position = CharPos - Line->Buffer;// + Column;
- //
- // found
- //
- if (ReplaceLen > SearchLen) {
- OldSize = Line->Size + 1;
- //
- // include CHAR_NULL
- //
- NewSize = OldSize + (ReplaceLen - SearchLen);
- //
- // do not have the enough space
- //
- if (Line->TotalSize + 1 <= NewSize) {
- Line->Buffer = ReallocatePool (
- 2 * OldSize,
- 2 * NewSize,
- Line->Buffer
- );
- Line->TotalSize = NewSize - 1;
- }
- if (Line->Buffer == NULL) {
- return EFI_OUT_OF_RESOURCES;
- }
- //
- // the end CHAR_NULL character;
- //
- Buffer = Line->Buffer + (NewSize - 1);
- Gap = ReplaceLen - SearchLen;
- //
- // keep the latter part
- //
- for (Index = 0; Index < (Line->Size - Position - SearchLen + 1); Index++) {
- *Buffer = *(Buffer - Gap);
- Buffer--;
- }
- } else if (ReplaceLen < SearchLen){
- Buffer = Line->Buffer + Position + ReplaceLen;
- Gap = SearchLen - ReplaceLen;
- for (Index = 0; Index < (Line->Size - Position - ReplaceLen + 1); Index++) {
- *Buffer = *(Buffer + Gap);
- Buffer++;
- }
- } else {
- ASSERT(ReplaceLen == SearchLen);
- }
- //
- // set replace into it
- //
- Buffer = Line->Buffer + Position;
- for (Index = 0; Index < ReplaceLen; Index++) {
- Buffer[Index] = ReplaceStr[Index];
- }
- Line->Size += (ReplaceLen - SearchLen);
- Column += ReplaceLen;
- } else {
- //
- // not found
- //
- Column = 0;
- Link = Link->ForwardLink;
- }
- }
- //
- // call refresh to fresh edit area
- //
- FileBuffer.FileModified = TRUE;
- FileBufferNeedRefresh = TRUE;
- FileBufferRefresh ();
- return EFI_SUCCESS;
- }
- /**
- Set the modified state to TRUE.
- **/
- VOID
- FileBufferSetModified (
- VOID
- )
- {
- FileBuffer.FileModified = TRUE;
- }
|