1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241 |
- /*++
- Copyright (c) 2013 Minoca Corp.
- This file is licensed under the terms of the GNU General Public License
- version 3. Alternative licensing terms are available. Contact
- info@minocacorp.com for details. See the LICENSE file at the root of this
- project for complete licensing information.
- Module Name:
- videocon.c
- Abstract:
- This module implements functionality for a basic console over a video
- frame buffer.
- Author:
- Evan Green 15-Feb-2013
- Environment:
- Kernel
- --*/
- //
- // ------------------------------------------------------------------- Includes
- //
- #include <minoca/kernel/driver.h>
- #include <minoca/kernel/sysres.h>
- #include <minoca/lib/basevid.h>
- #include <minoca/lib/termlib.h>
- //
- // --------------------------------------------------------------------- Macros
- //
- //
- // This routine gets the line structure for the given row.
- //
- #define GET_CONSOLE_LINE(_Console, _Row) \
- (PVIDEO_CONSOLE_LINE)((_Console)->Lines + \
- (CONSOLE_LINE_SIZE(_Console) * \
- CONSOLE_ROW_INDEX(_Console, _Row)))
- //
- // This routine gets the effective console row number, taking into account the
- // rotating nature of the console lines. This verbose conditional avoids
- // divides.
- //
- #define CONSOLE_ROW_INDEX(_Console, _Row) \
- ((((_Console)->TopLine + (_Row)) < (_Console)->BufferRows) ? \
- ((_Console)->TopLine + (_Row)) : \
- ((_Console)->TopLine + (_Row) - (_Console)->BufferRows))
- //
- // This macro determines the size of one console line.
- //
- #define CONSOLE_LINE_SIZE(_Console) \
- (sizeof(VIDEO_CONSOLE_LINE) + \
- ((((_Console)->Columns) + 1 - ANYSIZE_ARRAY) * \
- sizeof(BASE_VIDEO_CHARACTER)))
- //
- // This macro determines if the cursor is within the scroll region.
- //
- #define CURSOR_IN_SCROLL_REGION(_Console) \
- (((_Console)->NextRow >= (_Console)->TopMargin) && \
- ((_Console)->NextRow <= \
- (_Console)->ScreenRows - 1 - (_Console)->BottomMargin))
- //
- // ---------------------------------------------------------------- Definitions
- //
- #define VIDEO_CONSOLE_ALLOCATION_TAG 0x6E6F4356 // 'noCV'
- #define VIDEO_CONSOLE_DEFAULT_TAB_WIDTH 4
- #define VIDEO_CONSOLE_READ_BUFFER_SIZE 2048
- #define VIDEO_CONSOLE_MAX_LINES 10000
- //
- // Define the number of milliseconds between blinks.
- //
- #define VIDEO_CONSOLE_BLINK_RATE 500
- #define VIDEO_CONSOLE_CURSOR_BLINK_COUNT 60
- //
- // Define the number of rows to leave at the top for a banner.
- //
- #define VIDEO_CONSOLE_TOP_BANNER_ROWS 3
- //
- // Define known characters.
- //
- #define VIDEO_CHARACTER_SHIFT_IN 0xF
- #define VIDEO_CHARACTER_SHIFT_OUT 0xE
- //
- // Define pending actions.
- //
- #define VIDEO_ACTION_REDRAW_ENTIRE_SCREEN 0x00000001
- #define VIDEO_ACTION_RESET_SCROLL 0x00000002
- //
- // Define modes.
- //
- //
- // Keyboard action mode locks the keyboard, preventing all further interactions
- // with the user until it is unlocked.
- //
- #define CONSOLE_MODE_KEYBOARD_ACTION 0x00000002
- //
- // Insert mode causes characters to get shifted over. Characters that move
- // past the right margin are lost. If this is not set, it is in replace mode,
- // where characters overwrite the previous ones.
- //
- #define CONSOLE_MODE_INSERT 0x00000004
- //
- // If this bit is set, characters from the keyboard are not automatically
- // echoed to the screen.
- //
- #define CONSOLE_MODE_DISABLE_LOCAL_ECHO 0x00000008
- //
- // If this bit is set then Line Feed, Form Feed, and Vertical Tab characters
- // all reset the column position to zero in addition to incrementing the
- // vertical position.
- //
- #define CONSOLE_MODE_NEW_LINE 0x00000010
- //
- // If this bit is set, then the cursor is visible.
- //
- #define CONSOLE_MODE_CURSOR 0x00000020
- //
- // If this bit is set, the cursor keys send application control functions. If
- // clear, the cursor keys send ANSI cursor control sequences.
- //
- #define CONSOLE_MODE_APPLICATION_CURSOR_KEYS 0x00000040
- //
- // If this bit is set, the console switches to VT52 compatibility mode.
- //
- #define CONSOLE_MODE_VT52 0x00000080
- //
- // If this bit is set, the console has 132 (or more) columns. If clear, the
- // console is set to 80 columns.
- //
- #define CONSOLE_MODE_132_COLUMN 0x00000100
- //
- // If this bit is set, smooth scrolling is performed, a maximum of 6 lines per
- // second is output. If clear, lines are displayed as they come in.
- //
- #define CONSOLE_MODE_SMOOTH_SCROLL 0x00000200
- //
- // If this bit is set, the screen's default foreground and background colors
- // are switched.
- //
- #define CONSOLE_MODE_VIDEO_REVERSED 0x00000400
- //
- // If this bit is set, the home position is set to the top left of the user
- // defined scroll region. The user cannot move out of the scroll region. The
- // erase in display command is an exception to that. If this is clear, the
- // home position is the upper-left corner of the screen.
- //
- #define CONSOLE_MODE_ORIGIN 0x00000800
- //
- // If this bit is set, characters received when the cursor is at the right
- // margin appear on the next line. The display scrolls up if the cursor is at
- // the end of the scrolling region. If this bit is clear, characters that
- // appear at the right replace previously displayed characters.
- //
- #define CONSOLE_MODE_AUTO_WRAP 0x00001000
- //
- // If this bit is set, keypad keys send application control functions. If clear,
- // keypad keys send numeric values (plus comma, period, plus minus, etc.)
- //
- #define CONSOLE_MODE_APPLICATION_KEYPAD 0x00002000
- //
- // If this bit is set, the cursor blinks.
- //
- #define CONSOLE_MODE_CURSOR_BLINK 0x00004000
- //
- // Define the default video mode bits when the console is initialized.
- //
- #define VIDEO_CONSOLE_MODE_DEFAULTS \
- (CONSOLE_MODE_CURSOR | CONSOLE_MODE_CURSOR_BLINK | CONSOLE_MODE_AUTO_WRAP)
- //
- // ------------------------------------------------------ Data Type Definitions
- //
- /*++
- Structure Description:
- This structure defines state associated with a single horizontal line of
- the video console.
- Members:
- Attributes - Stores attributes for the entire line.
- Character - Stores the array of printable characters in this line.
- --*/
- typedef struct _VIDEO_CONSOLE_LINE {
- USHORT Attributes;
- BASE_VIDEO_CHARACTER Character[ANYSIZE_ARRAY];
- } VIDEO_CONSOLE_LINE, *PVIDEO_CONSOLE_LINE;
- /*++
- Structure Description:
- This structure defines state associated with a video console.
- Members:
- PhysicalAddress - Stores the physical address of the frame buffer.
- VideoContext - Stores the base video library context used for low level
- print routines.
- FrameBuffer - Stores the virtual address of the frame buffer.
- Width - Stores the width of the frame buffer, in pixels.
- Height - Stores the height of the frame buffer, in pixels.
- BitsPerPixel - Stores the number of bits that correspond to one pixel.
- Columns - Stores the number of text columns in the console.
- ScreenRows - Stores the number of rows that can be displayed on the screen.
- BufferRows - Stores the number of rows in the buffer. This must be at least
- as large as the number of rows on the screen.
- MaxRows - Stores the maximum number of rows that should be stored in this
- console. Set to 0 for unlimited.
- TopMargin - Stores the top margin of the scroll area in lines. A count of
- zero means the console will scroll with scrollback.
- BottomMargin - Stores the bottom margin of the scroll area in lines. A
- count of zero means the console goes to the bottom of the screen.
- Lines - Stores a pointer to the array of lines representing the contents of
- this console.
- Screen - Stores a pointer to the array of lines that represents what's
- actually on the screen.
- TopLine - Stores the index of the line displaying at the top of the screen.
- TabWidth - Stores the number of spaces that expand to a tab.
- Lock - Stores a pointer to a lock that serializes access to the console.
- NextColumn - Stores the zero-based column number where the next character
- will be printed. This might be equal to the column count in order to
- handle the old VT100 wraparound bug.
- NextRow - Stores the zero-based row number where the next character will be
- printed. This is a screen row, not a buffer row.
- RowViewOffset - Stores the number of lines down from the screen top row to
- display the screen.
- TextAttributes - Stores the current text attributes for printed text.
- Command - Stores the terminal input command data.
- PendingAction - Stores a bitfield of flags containing actions that need to
- be performed.
- Mode - Stores the console mode selections. See VIDEO_*_MODE definitions.
- SavedColumn - Stores the cursor column when a save cursor command occurred.
- SavedRow - Stores the cursor row when a save cursor command occurred.
- SavedAttributes - Stores the next attributes when a save cursor command
- occurred.
- --*/
- typedef struct _VIDEO_CONSOLE_DEVICE {
- PHYSICAL_ADDRESS PhysicalAddress;
- BASE_VIDEO_CONTEXT VideoContext;
- PVOID FrameBuffer;
- LONG Width;
- LONG Height;
- LONG BitsPerPixel;
- LONG Columns;
- LONG ScreenRows;
- LONG BufferRows;
- LONG MaxRows;
- LONG TopMargin;
- LONG BottomMargin;
- PVOID Lines;
- PVOID Screen;
- LONG TopLine;
- ULONG TabWidth;
- PQUEUED_LOCK Lock;
- LONG NextColumn;
- LONG NextRow;
- LONG RowViewOffset;
- USHORT TextAttributes;
- TERMINAL_COMMAND_DATA Command;
- ULONG PendingAction;
- ULONG Mode;
- LONG SavedColumn;
- LONG SavedRow;
- LONG SavedAttributes;
- } VIDEO_CONSOLE_DEVICE, *PVIDEO_CONSOLE_DEVICE;
- //
- // ----------------------------------------------- Internal Function Prototypes
- //
- KSTATUS
- VcAddDevice (
- PVOID Driver,
- PCSTR DeviceId,
- PCSTR ClassId,
- PCSTR CompatibleIds,
- PVOID DeviceToken
- );
- VOID
- VcDispatchStateChange (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- );
- VOID
- VcDispatchOpen (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- );
- VOID
- VcDispatchClose (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- );
- VOID
- VcDispatchIo (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- );
- VOID
- VcDispatchSystemControl (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- );
- VOID
- VcpLocalTerminalRedrawThread (
- PVOID Parameter
- );
- VOID
- VcpWriteToConsole (
- PVIDEO_CONSOLE_DEVICE Console,
- PSTR String,
- UINTN StringLength
- );
- VOID
- VcpProcessCommand (
- PVIDEO_CONSOLE_DEVICE Console,
- PTERMINAL_COMMAND_DATA Command
- );
- VOID
- VcpEraseArea (
- PVIDEO_CONSOLE_DEVICE Console,
- LONG StartColumn,
- LONG StartRow,
- LONG EndColumn,
- LONG EndRow,
- BOOL ResetAttributes
- );
- VOID
- VcpRedrawArea (
- PVIDEO_CONSOLE_DEVICE Console,
- LONG StartColumn,
- LONG StartRow,
- LONG EndColumn,
- LONG EndRow
- );
- VOID
- VcpSetOrClearMode (
- PVIDEO_CONSOLE_DEVICE Console,
- ULONG ModeNumber,
- TERMINAL_COMMAND Command
- );
- VOID
- VcpAdvanceRow (
- PVIDEO_CONSOLE_DEVICE Console
- );
- VOID
- VcpSetColorFromParameters (
- PVIDEO_CONSOLE_DEVICE Console,
- PTERMINAL_COMMAND_DATA Command
- );
- VOID
- VcpSaveRestoreCursor (
- PVIDEO_CONSOLE_DEVICE Console,
- BOOL Save
- );
- VOID
- VcpMoveCursorRelative (
- PVIDEO_CONSOLE_DEVICE Console,
- LONG DistanceX,
- LONG DistanceY
- );
- VOID
- VcpMoveCursorAbsolute (
- PVIDEO_CONSOLE_DEVICE Console,
- LONG Column,
- LONG Row,
- BOOL ProcessOriginMode
- );
- VOID
- VcpDeleteLines (
- PVIDEO_CONSOLE_DEVICE Console,
- LONG Count,
- LONG StartingRow
- );
- VOID
- VcpInsertLines (
- PVIDEO_CONSOLE_DEVICE Console,
- LONG Count,
- LONG StartingRow
- );
- //
- // -------------------------------------------------------------------- Globals
- //
- PDRIVER VcDriver = NULL;
- //
- // Store the next identifier.
- //
- volatile ULONG VcNextIdentifier = 0;
- //
- // Store a pointer to the local terminal.
- //
- PIO_HANDLE VcLocalTerminal;
- //
- // ------------------------------------------------------------------ Functions
- //
- KSTATUS
- DriverEntry (
- PDRIVER Driver
- )
- /*++
- Routine Description:
- This routine is the entry point for the video console driver. It registers
- its other dispatch functions, and performs driver-wide initialization.
- Arguments:
- Driver - Supplies a pointer to the driver object.
- Return Value:
- STATUS_SUCCESS on success.
- Failure code on error.
- --*/
- {
- ULONG AllocationSize;
- LONG Columns;
- PVIDEO_CONSOLE_DEVICE ConsoleDevice;
- volatile ULONG DeviceId;
- CHAR DeviceIdString[15];
- PSYSTEM_RESOURCE_FRAME_BUFFER FrameBufferResource;
- DRIVER_FUNCTION_TABLE FunctionTable;
- PSYSTEM_RESOURCE_HEADER GenericHeader;
- ULONG Height;
- LONG LineSize;
- PHYSICAL_ADDRESS PhysicalAddress;
- LONG Rows;
- ULONG RowSize;
- KSTATUS Status;
- UINTN TopOffset;
- SYSTEM_RESOURCE_FRAME_BUFFER VideoResource;
- PVOID VirtualAddress;
- ULONG Width;
- TERMINAL_WINDOW_SIZE WindowSize;
- ConsoleDevice = NULL;
- VcDriver = Driver;
- RtlZeroMemory(&FunctionTable, sizeof(DRIVER_FUNCTION_TABLE));
- FunctionTable.Version = DRIVER_FUNCTION_TABLE_VERSION;
- FunctionTable.AddDevice = VcAddDevice;
- FunctionTable.DispatchStateChange = VcDispatchStateChange;
- FunctionTable.DispatchOpen = VcDispatchOpen;
- FunctionTable.DispatchClose = VcDispatchClose;
- FunctionTable.DispatchIo = VcDispatchIo;
- FunctionTable.DispatchSystemControl = VcDispatchSystemControl;
- Status = IoRegisterDriverFunctions(Driver, &FunctionTable);
- if (!KSUCCESS(Status)) {
- goto DriverEntryEnd;
- }
- //
- // Get all frame buffers from the boot environment.
- //
- while (TRUE) {
- GenericHeader = KeAcquireSystemResource(SystemResourceFrameBuffer);
- if (GenericHeader == NULL) {
- break;
- }
- //
- // TODO: The base video library can only handle one frame buffer at a
- // time. If multiple frame buffers crop up, retrofit that library to
- // support multiple consoles.
- //
- ASSERT(VcNextIdentifier == 0);
- FrameBufferResource = (PSYSTEM_RESOURCE_FRAME_BUFFER)GenericHeader;
- //
- // Ensure the frame buffer is big enough for at least a character.
- //
- Height = FrameBufferResource->Height;
- Width = FrameBufferResource->Width;
- if (FrameBufferResource->Mode == BaseVideoModeBiosText) {
- if ((Height <= VIDEO_CONSOLE_TOP_BANNER_ROWS) || (Width < 1)) {
- continue;
- }
- Height -= VIDEO_CONSOLE_TOP_BANNER_ROWS;
- RowSize = FrameBufferResource->Width *
- FrameBufferResource->BitsPerPixel / BITS_PER_BYTE;
- TopOffset = RowSize * VIDEO_CONSOLE_TOP_BANNER_ROWS;
- Columns = Width;
- Rows = Height;
- } else {
- ASSERT(FrameBufferResource->Mode == BaseVideoModeFrameBuffer);
- if ((Height <=
- VIDEO_CONSOLE_TOP_BANNER_ROWS * VidDefaultFont->CellHeight) ||
- (Width < VidDefaultFont->CellWidth)) {
- continue;
- }
- Height -= VIDEO_CONSOLE_TOP_BANNER_ROWS *
- VidDefaultFont->CellHeight;
- RowSize = FrameBufferResource->Width *
- FrameBufferResource->BitsPerPixel / BITS_PER_BYTE;
- TopOffset = RowSize * (VIDEO_CONSOLE_TOP_BANNER_ROWS *
- VidDefaultFont->CellHeight);
- Columns = Width / VidDefaultFont->CellWidth;
- Rows = Height / VidDefaultFont->CellHeight;
- }
- VirtualAddress = FrameBufferResource->Header.VirtualAddress + TopOffset;
- PhysicalAddress = FrameBufferResource->Header.PhysicalAddress +
- TopOffset;
- ConsoleDevice = MmAllocatePagedPool(sizeof(VIDEO_CONSOLE_DEVICE),
- VIDEO_CONSOLE_ALLOCATION_TAG);
- if (ConsoleDevice == NULL) {
- goto DriverEntryEnd;
- }
- RtlZeroMemory(ConsoleDevice, sizeof(VIDEO_CONSOLE_DEVICE));
- //
- // Determine the size of the allocation needed for the lines.
- //
- LineSize = sizeof(VIDEO_CONSOLE_LINE) +
- ((Columns + 1 - ANYSIZE_ARRAY) *
- sizeof(BASE_VIDEO_CHARACTER));
- AllocationSize = LineSize * Rows;
- //
- // Allocate the internal data structure.
- //
- ConsoleDevice->Lines = MmAllocatePagedPool(
- AllocationSize,
- VIDEO_CONSOLE_ALLOCATION_TAG);
- if (ConsoleDevice->Lines == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto DriverEntryEnd;
- }
- RtlZeroMemory(ConsoleDevice->Lines, AllocationSize);
- ConsoleDevice->Screen = MmAllocatePagedPool(
- AllocationSize,
- VIDEO_CONSOLE_ALLOCATION_TAG);
- if (ConsoleDevice->Screen == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto DriverEntryEnd;
- }
- RtlZeroMemory(ConsoleDevice->Screen, AllocationSize);
- ConsoleDevice->PhysicalAddress = PhysicalAddress;
- ConsoleDevice->FrameBuffer = VirtualAddress;
- ConsoleDevice->Width = Width;
- ConsoleDevice->Height = Height;
- ConsoleDevice->BitsPerPixel = FrameBufferResource->BitsPerPixel;
- ConsoleDevice->Columns = Columns;
- ConsoleDevice->ScreenRows = Rows;
- ConsoleDevice->BufferRows = Rows;
- ConsoleDevice->MaxRows = VIDEO_CONSOLE_MAX_LINES;
- ConsoleDevice->Mode = VIDEO_CONSOLE_MODE_DEFAULTS;
- ConsoleDevice->Lock = KeCreateQueuedLock();
- ConsoleDevice->TabWidth = VIDEO_CONSOLE_DEFAULT_TAB_WIDTH;
- if (ConsoleDevice->Lock == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto DriverEntryEnd;
- }
- RtlCopyMemory(&VideoResource,
- FrameBufferResource,
- sizeof(SYSTEM_RESOURCE_FRAME_BUFFER));
- VideoResource.Header.VirtualAddress = VirtualAddress;
- VideoResource.Header.PhysicalAddress = PhysicalAddress;
- VideoResource.Width = Width;
- VideoResource.Height = Height;
- Status = VidInitialize(&(ConsoleDevice->VideoContext), &VideoResource);
- if (!KSUCCESS(Status)) {
- goto DriverEntryEnd;
- }
- //
- // Ensure the calculation agrees with the macro. Ideally the macro would
- // have been used directly to calculate the line size, but it attempts
- // to dereference the console object and thus cannot be used.
- //
- ASSERT(LineSize == CONSOLE_LINE_SIZE(ConsoleDevice));
- DeviceId = RtlAtomicAdd32(&VcNextIdentifier, 1);
- RtlPrintToString(DeviceIdString,
- 15,
- CharacterEncodingDefault,
- "VideoConsole%x",
- DeviceId);
- //
- // Get a handle to the master side of the local console terminal and
- // create the local console redraw thread.
- //
- ASSERT(VcLocalTerminal == NULL);
- Status = IoOpenLocalTerminalMaster(&VcLocalTerminal);
- if (KSUCCESS(Status)) {
- Status = PsCreateKernelThread(VcpLocalTerminalRedrawThread,
- ConsoleDevice,
- "VcpLocalTerminalRedrawThread");
- if (!KSUCCESS(Status)) {
- goto DriverEntryEnd;
- }
- }
- //
- // Set the window size in the terminal.
- //
- RtlZeroMemory(&WindowSize, sizeof(TERMINAL_WINDOW_SIZE));
- WindowSize.Rows = Rows;
- WindowSize.Columns = Columns;
- WindowSize.PixelsX = Width;
- WindowSize.PixelsY = Height;
- IoUserControl(VcLocalTerminal,
- TerminalControlSetWindowSize,
- TRUE,
- &WindowSize,
- sizeof(TERMINAL_WINDOW_SIZE));
- //
- // Create the video console device.
- //
- Status = IoCreateDevice(VcDriver,
- ConsoleDevice,
- NULL,
- DeviceIdString,
- CHARACTER_CLASS_ID,
- NULL,
- NULL);
- if (!KSUCCESS(Status)) {
- goto DriverEntryEnd;
- }
- }
- DriverEntryEnd:
- if (!KSUCCESS(Status)) {
- ASSERT(VcNextIdentifier <= 1);
- if (ConsoleDevice != NULL) {
- if (ConsoleDevice->Lock != NULL) {
- KeDestroyQueuedLock(ConsoleDevice->Lock);
- }
- if (ConsoleDevice->Lines != NULL) {
- MmFreePagedPool(ConsoleDevice->Lines);
- }
- if (ConsoleDevice->Screen != NULL) {
- MmFreePagedPool(ConsoleDevice->Screen);
- }
- MmFreePagedPool(ConsoleDevice);
- }
- }
- return Status;
- }
- KSTATUS
- VcAddDevice (
- PVOID Driver,
- PCSTR DeviceId,
- PCSTR ClassId,
- PCSTR CompatibleIds,
- PVOID DeviceToken
- )
- /*++
- Routine Description:
- This routine is called when a device is detected for which the video console
- device acts as the function driver. The driver will attach itself to the
- stack.
- Arguments:
- Driver - Supplies a pointer to the driver being called.
- DeviceId - Supplies a pointer to a string with the device ID.
- ClassId - Supplies a pointer to a string containing the device's class ID.
- CompatibleIds - Supplies a pointer to a string containing device IDs
- that would be compatible with this device.
- DeviceToken - Supplies an opaque token that the driver can use to identify
- the device in the system. This token should be used when attaching to
- the stack.
- Return Value:
- STATUS_SUCCESS on success.
- Failure code if the driver was unsuccessful in attaching itself.
- --*/
- {
- //
- // The Video console is not a real device, so it is not expected to be
- // attaching to emerging stacks.
- //
- return STATUS_NOT_IMPLEMENTED;
- }
- VOID
- VcDispatchStateChange (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- )
- /*++
- Routine Description:
- This routine handles State Change IRPs.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- DeviceContext - Supplies the context pointer supplied by the driver when it
- attached itself to the driver stack. Presumably this pointer contains
- driver-specific device context.
- IrpContext - Supplies the context pointer supplied by the driver when
- the IRP was created.
- Return Value:
- None.
- --*/
- {
- BOOL CompleteIrp;
- KSTATUS Status;
- ASSERT(Irp->MajorCode == IrpMajorStateChange);
- //
- // The IRP is on its way down the stack. Do most processing here.
- //
- if (Irp->Direction == IrpDown) {
- Status = STATUS_NOT_SUPPORTED;
- CompleteIrp = TRUE;
- switch (Irp->MinorCode) {
- case IrpMinorQueryResources:
- Status = STATUS_SUCCESS;
- break;
- case IrpMinorStartDevice:
- Status = STATUS_SUCCESS;
- break;
- case IrpMinorQueryChildren:
- Irp->U.QueryChildren.Children = NULL;
- Irp->U.QueryChildren.ChildCount = 0;
- Status = STATUS_SUCCESS;
- break;
- //
- // Pass all other IRPs down.
- //
- default:
- CompleteIrp = FALSE;
- break;
- }
- //
- // Complete the IRP unless there's a reason not to.
- //
- if (CompleteIrp != FALSE) {
- IoCompleteIrp(VcDriver, Irp, Status);
- }
- //
- // The IRP is completed and is on its way back up.
- //
- } else {
- ASSERT(Irp->Direction == IrpUp);
- }
- return;
- }
- VOID
- VcDispatchOpen (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- )
- /*++
- Routine Description:
- This routine handles Open IRPs.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- DeviceContext - Supplies the context pointer supplied by the driver when it
- attached itself to the driver stack. Presumably this pointer contains
- driver-specific device context.
- IrpContext - Supplies the context pointer supplied by the driver when
- the IRP was created.
- Return Value:
- None.
- --*/
- {
- IoCompleteIrp(VcDriver, Irp, STATUS_SUCCESS);
- return;
- }
- VOID
- VcDispatchClose (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- )
- /*++
- Routine Description:
- This routine handles Close IRPs.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- DeviceContext - Supplies the context pointer supplied by the driver when it
- attached itself to the driver stack. Presumably this pointer contains
- driver-specific device context.
- IrpContext - Supplies the context pointer supplied by the driver when
- the IRP was created.
- Return Value:
- None.
- --*/
- {
- IoCompleteIrp(VcDriver, Irp, STATUS_SUCCESS);
- return;
- }
- VOID
- VcDispatchIo (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- )
- /*++
- Routine Description:
- This routine handles I/O IRPs.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- DeviceContext - Supplies the context pointer supplied by the driver when it
- attached itself to the driver stack. Presumably this pointer contains
- driver-specific device context.
- IrpContext - Supplies the context pointer supplied by the driver when
- the IRP was created.
- Return Value:
- None.
- --*/
- {
- PVIDEO_CONSOLE_DEVICE Console;
- UINTN FragmentIndex;
- UINTN FragmentSize;
- PIO_BUFFER IoBuffer;
- UINTN Size;
- KSTATUS Status;
- ASSERT(Irp->Direction == IrpDown);
- Console = (PVIDEO_CONSOLE_DEVICE)DeviceContext;
- //
- // Fail reads.
- //
- if (Irp->MinorCode != IrpMinorIoWrite) {
- Status = STATUS_NOT_SUPPORTED;
- goto DispatchIoEnd;
- }
- IoBuffer = Irp->U.ReadWrite.IoBuffer;
- Status = MmMapIoBuffer(IoBuffer, FALSE, FALSE, FALSE);
- if (!KSUCCESS(Status)) {
- goto DispatchIoEnd;
- }
- Size = Irp->U.ReadWrite.IoSizeInBytes;
- for (FragmentIndex = 0;
- FragmentIndex < IoBuffer->FragmentCount;
- FragmentIndex += 1) {
- FragmentSize = IoBuffer->Fragment[FragmentIndex].Size;
- if (FragmentSize > Size) {
- FragmentSize = Size;
- }
- VcpWriteToConsole(Console,
- IoBuffer->Fragment[FragmentIndex].VirtualAddress,
- FragmentSize);
- Size -= FragmentSize;
- }
- Irp->U.ReadWrite.IoBytesCompleted = Irp->U.ReadWrite.IoSizeInBytes;
- Status = STATUS_SUCCESS;
- DispatchIoEnd:
- IoCompleteIrp(VcDriver, Irp, Status);
- return;
- }
- VOID
- VcDispatchSystemControl (
- PIRP Irp,
- PVOID DeviceContext,
- PVOID IrpContext
- )
- /*++
- Routine Description:
- This routine handles System Control IRPs.
- Arguments:
- Irp - Supplies a pointer to the I/O request packet.
- DeviceContext - Supplies the context pointer supplied by the driver when it
- attached itself to the driver stack. Presumably this pointer contains
- driver-specific device context.
- IrpContext - Supplies the context pointer supplied by the driver when
- the IRP was created.
- Return Value:
- None.
- --*/
- {
- ASSERT(Irp->MajorCode == IrpMajorSystemControl);
- //
- // Do no processing on any IRPs. Let them flow.
- //
- return;
- }
- //
- // --------------------------------------------------------- Internal Functions
- //
- VOID
- VcpLocalTerminalRedrawThread (
- PVOID Parameter
- )
- /*++
- Routine Description:
- This routine implements the video console redraw thread, which reads from
- the terminal master and draws the output.
- Arguments:
- Parameter - Supplies the thread parameter, in this case a pointer to the
- video console device.
- Return Value:
- None.
- --*/
- {
- ULONG BlinkCount;
- UINTN BytesRead;
- USHORT CursorAttributes;
- LONG CursorColumn;
- LONG CursorRow;
- PVIDEO_CONSOLE_DEVICE Device;
- PIO_BUFFER IoBuffer;
- PVIDEO_CONSOLE_LINE Line;
- PCHAR ReadBuffer;
- KSTATUS Status;
- ULONG Timeout;
- BlinkCount = 0;
- CursorAttributes = 0;
- Device = (PVIDEO_CONSOLE_DEVICE)Parameter;
- ReadBuffer = MmAllocatePagedPool(VIDEO_CONSOLE_READ_BUFFER_SIZE,
- VIDEO_CONSOLE_ALLOCATION_TAG);
- if (ReadBuffer == NULL) {
- Status = STATUS_INSUFFICIENT_RESOURCES;
- goto LocalTerminalRedrawThread;
- }
- Status = MmCreateIoBuffer(ReadBuffer,
- VIDEO_CONSOLE_READ_BUFFER_SIZE,
- IO_BUFFER_FLAG_KERNEL_MODE_DATA,
- &IoBuffer);
- if (!KSUCCESS(Status)) {
- goto LocalTerminalRedrawThread;
- }
- //
- // Loop reading the slave's standard out and printing it to the screen.
- //
- while (TRUE) {
- Timeout = WAIT_TIME_INDEFINITE;
- if (((Device->Mode & CONSOLE_MODE_CURSOR) != 0) &&
- ((Device->Mode & CONSOLE_MODE_CURSOR_BLINK) != 0)) {
- //
- // Stop blinking after a little while to save power, but make sure
- // the blinking stops on having the cursor drawn.
- //
- if ((BlinkCount < VIDEO_CONSOLE_CURSOR_BLINK_COUNT) ||
- ((CursorAttributes & BASE_VIDEO_CURSOR) == 0)) {
- Timeout = VIDEO_CONSOLE_BLINK_RATE;
- }
- }
- Status = IoRead(VcLocalTerminal,
- IoBuffer,
- VIDEO_CONSOLE_READ_BUFFER_SIZE,
- 0,
- Timeout,
- &BytesRead);
- if (Status == STATUS_TIMEOUT) {
- ASSERT(BytesRead == 0);
- CursorRow = Device->NextRow;
- CursorColumn = Device->NextColumn;
- if (CursorColumn == Device->Columns) {
- CursorColumn -= 1;
- }
- Line = GET_CONSOLE_LINE(Device, CursorRow);
- Line->Character[CursorColumn].Data.Attributes ^= BASE_VIDEO_CURSOR;
- CursorAttributes = Line->Character[CursorColumn].Data.Attributes;
- VcpRedrawArea(Device,
- CursorColumn,
- CursorRow,
- CursorColumn + 1,
- CursorRow);
- BlinkCount += 1;
- //
- // Device I/O error probably means there are no slaves connected. Wait
- // a little while and see if one connects.
- //
- } else if (Status == STATUS_DEVICE_IO_ERROR) {
- KeDelayExecution(FALSE, FALSE, 5 * MICROSECONDS_PER_SECOND);
- } else if (!KSUCCESS(Status)) {
- break;
- }
- if (BytesRead != 0) {
- BlinkCount = 0;
- VcpWriteToConsole(Device, ReadBuffer, BytesRead);
- }
- }
- LocalTerminalRedrawThread:
- if (!KSUCCESS(Status)) {
- RtlDebugPrint("VideoCon: TerminalRedrawThread failure: %d\n", Status);
- }
- if (IoBuffer != NULL) {
- MmFreeIoBuffer(IoBuffer);
- }
- if (ReadBuffer != NULL) {
- MmFreePagedPool(ReadBuffer);
- }
- return;
- }
- VOID
- VcpWriteToConsole (
- PVIDEO_CONSOLE_DEVICE Console,
- PSTR String,
- UINTN StringLength
- )
- /*++
- Routine Description:
- This routine writes the given string to the video console.
- Arguments:
- Console - Supplies a pointer to the video console to write to.
- String - Supplies a pointer to the string to print.
- StringLength - Supplies the length of the string buffer, including the null
- terminator.
- Return Value:
- None.
- --*/
- {
- UCHAR Character;
- PBASE_VIDEO_CHARACTER Characters;
- LONG Column;
- LONG CursorColumn;
- LONG CursorRow;
- LONG EndColumn;
- LONG EndRow;
- PVIDEO_CONSOLE_LINE Line;
- TERMINAL_PARSE_RESULT OutputResult;
- LONG StartColumn;
- LONG StartRow;
- ASSERT(KeGetRunLevel() == RunLevelLow);
- KeAcquireQueuedLock(Console->Lock);
- StartRow = Console->NextRow;
- StartColumn = Console->NextColumn;
- if (StartColumn == Console->Columns) {
- StartColumn -= 1;
- }
- EndColumn = StartColumn;
- EndRow = StartRow;
- ASSERT(StartColumn < Console->Columns);
- ASSERT(StartRow < Console->ScreenRows);
- //
- // Clear the cursor flag assuming it's going to move.
- //
- Line = GET_CONSOLE_LINE(Console, StartRow);
- Characters = (PBASE_VIDEO_CHARACTER)(Line->Character);
- Characters[StartColumn].Data.Attributes &= ~BASE_VIDEO_CURSOR;
- //
- // Loop over each character in the string.
- //
- while (TRUE) {
- if (StringLength == 0) {
- break;
- }
- Character = *String;
- if (Character == '\0') {
- String += 1;
- StringLength -= 1;
- continue;
- }
- OutputResult = TermProcessOutput(&(Console->Command), Character);
- switch (OutputResult) {
- //
- // This is just an ordinary joe character.
- //
- case TerminalParseResultNormalCharacter:
- Console->PendingAction |= VIDEO_ACTION_RESET_SCROLL;
- if (Character == '\t') {
- do {
- //
- // Tab never goes over a line, and leaves one character of
- // space as well at the end of the current line.
- //
- if (Console->NextColumn >= Console->Columns - 1) {
- break;
- }
- Console->NextColumn += 1;
- } while ((Console->NextColumn % Console->TabWidth) != 0);
- //
- // A newline, vertical time, or form feed moves to the next line,
- // and potentially resets the column too.
- //
- } else if ((Character == '\n') || (Character == '\v') ||
- (Character == '\f')) {
- if ((Console->NextColumn == Console->Columns) ||
- ((Console->Mode & CONSOLE_MODE_NEW_LINE) != 0)) {
- Console->NextColumn = 0;
- }
- VcpAdvanceRow(Console);
- Line = NULL;
- //
- // Handle a carraige return.
- //
- } else if (Character == '\r') {
- Console->NextColumn = 0;
- //
- // Handle a backspace.
- //
- } else if (Character == '\b') {
- if (Console->NextColumn != 0) {
- Console->NextColumn -= 1;
- } else {
- if (Console->NextRow != 0) {
- Console->NextColumn = Console->Columns - 1;
- Console->NextRow -= 1;
- Line = NULL;
- }
- }
- //
- // Handle a rubout, which moves the cursor back one and erases the
- // character at that new position. It does not go back up lines.
- //
- } else if (Character == TERMINAL_RUBOUT) {
- if (Console->NextColumn != 0) {
- Console->NextColumn -= 1;
- }
- if (Line == NULL) {
- CursorRow = Console->NextRow;
- Line = GET_CONSOLE_LINE(Console, CursorRow);
- Characters = (PBASE_VIDEO_CHARACTER)(Line->Character);
- }
- Characters[Console->NextColumn].Data.Character = ' ';
- } else if ((Character >= ' ') && (Character < 0x80)) {
- if (Line == NULL) {
- CursorRow = Console->NextRow;
- Line = GET_CONSOLE_LINE(Console, CursorRow);
- Characters = (PBASE_VIDEO_CHARACTER)(Line->Character);
- }
- if ((Console->Mode & CONSOLE_MODE_INSERT) != 0) {
- for (Column = Console->Columns - 1;
- Column > Console->NextColumn;
- Column -= 1) {
- Characters[Column].AsUint32 =
- Characters[Column - 1].AsUint32;
- }
- if (EndRow == Console->NextRow) {
- EndColumn = Console->Columns - 1;
- }
- }
- //
- // If the column was actually overhanging, move it down now.
- //
- if (Console->NextColumn == Console->Columns) {
- Console->NextColumn = 0;
- VcpAdvanceRow(Console);
- Line = GET_CONSOLE_LINE(Console, Console->NextRow);
- Characters = (PBASE_VIDEO_CHARACTER)(Line->Character);
- }
- Characters[Console->NextColumn].Data.Attributes =
- Console->TextAttributes;
- Characters[Console->NextColumn].Data.Character = Character;
- //
- // Move the column forward.
- //
- if ((Console->Mode & CONSOLE_MODE_AUTO_WRAP) != 0) {
- if (Console->NextColumn < Console->Columns) {
- Console->NextColumn += 1;
- }
- } else if (Console->NextColumn < Console->Columns - 1) {
- Console->NextColumn += 1;
- }
- } else if (Character == VIDEO_CHARACTER_SHIFT_IN) {
- //
- // TODO: Handle shift in, which invokes the G0 character set.
- //
- } else if (Character == VIDEO_CHARACTER_SHIFT_OUT) {
- //
- // TODO: Handle shift out, which invokes the G1 character set.
- //
- }
- break;
- case TerminalParseResultPartialCommand:
- break;
- case TerminalParseResultCompleteCommand:
- TermNormalizeParameters(&(Console->Command));
- VcpProcessCommand(Console, &(Console->Command));
- Line = NULL;
- break;
- default:
- ASSERT(FALSE);
- break;
- }
- //
- // Potentially widen the redraw area unless a scroll has already
- // occurred, in which case the entire screen will be redrawn anyway.
- //
- if ((Console->PendingAction & VIDEO_ACTION_REDRAW_ENTIRE_SCREEN) == 0) {
- //
- // Potentially move the end region out.
- //
- if (Console->NextRow > EndRow) {
- EndRow = Console->NextRow;
- EndColumn = Console->NextColumn;
- } else if ((Console->NextRow == EndRow) &&
- (Console->NextColumn > EndColumn)) {
- EndColumn = Console->NextColumn;
- }
- //
- // Potentially move the start region.
- //
- if (Console->NextRow < StartRow) {
- StartRow = Console->NextRow;
- StartColumn = Console->NextColumn;
- } else if ((Console->NextRow == StartRow) &&
- (Console->NextColumn < StartColumn)) {
- StartColumn = Console->NextColumn;
- }
- }
- //
- // Move on to the next character.
- //
- String += 1;
- StringLength -= 1;
- }
- //
- // Make the cursor visible on any real events.
- //
- if ((Console->PendingAction & VIDEO_ACTION_RESET_SCROLL) != 0) {
- Console->PendingAction &= ~VIDEO_ACTION_RESET_SCROLL;
- if ((Console->RowViewOffset > Console->NextRow) ||
- (Console->RowViewOffset + Console->ScreenRows < Console->NextRow)) {
- Console->PendingAction |= VIDEO_ACTION_REDRAW_ENTIRE_SCREEN;
- Console->RowViewOffset = 0;
- }
- }
- if ((Console->PendingAction & VIDEO_ACTION_REDRAW_ENTIRE_SCREEN) != 0) {
- Console->PendingAction &= ~VIDEO_ACTION_REDRAW_ENTIRE_SCREEN;
- StartColumn = 0;
- StartRow = 0;
- EndColumn = Console->Columns;
- EndRow = Console->ScreenRows - 1;
- //
- // Add one extra for the cursor, and adjust for the row view offset.
- //
- } else {
- EndColumn += 1;
- if (EndColumn > Console->Columns) {
- EndColumn = Console->Columns;
- }
- StartRow -= Console->RowViewOffset;
- if (StartRow < 0) {
- StartRow = 0;
- } else if (StartRow > Console->ScreenRows - 1) {
- StartRow = Console->ScreenRows - 1;
- }
- EndRow -= Console->RowViewOffset;
- if (EndRow < 0) {
- EndRow = 0;
- } else if (EndRow > Console->ScreenRows - 1) {
- EndRow = Console->ScreenRows - 1;
- }
- if ((EndRow == StartRow) && (EndColumn < StartColumn)) {
- EndColumn = StartColumn;
- }
- }
- //
- // Set the cursor character.
- //
- CursorRow = Console->NextRow;
- CursorColumn = Console->NextColumn;
- if (CursorColumn == Console->Columns) {
- CursorColumn -= 1;
- }
- Line = GET_CONSOLE_LINE(Console, CursorRow);
- Characters = (PBASE_VIDEO_CHARACTER)(Line->Character);
- if ((Console->Mode & CONSOLE_MODE_CURSOR) != 0) {
- Characters[CursorColumn].Data.Attributes |= BASE_VIDEO_CURSOR;
- }
- //
- // Redraw the portion of the screen that was modified.
- //
- VcpRedrawArea(Console, StartColumn, StartRow, EndColumn, EndRow);
- KeReleaseQueuedLock(Console->Lock);
- return;
- }
- VOID
- VcpProcessCommand (
- PVIDEO_CONSOLE_DEVICE Console,
- PTERMINAL_COMMAND_DATA Command
- )
- /*++
- Routine Description:
- This routine processes a terminal control sequence.
- Arguments:
- Console - Supplies a pointer to the video console.
- Command - Supplies a pointer to the command to run.
- Return Value:
- None.
- --*/
- {
- LONG Bottom;
- LONG Column;
- LONG Count;
- PVIDEO_CONSOLE_LINE Line;
- UINTN ParameterIndex;
- BOOL ResetCharacterAttributes;
- LONG Row;
- LONG Top;
- //
- // For the purposes of handling a command, the console cannot be
- // overhanging.
- //
- if (Console->NextColumn == Console->Columns) {
- Console->NextColumn -= 1;
- }
- switch (Command->Command) {
- case TerminalCommandInvalid:
- ASSERT(FALSE);
- break;
- case TerminalCommandCursorUp:
- Count = Command->Parameter[0];
- ASSERT((Command->ParameterCount != 0) && (Count > 0));
- VcpMoveCursorRelative(Console, 0, -Count);
- break;
- case TerminalCommandCursorDown:
- Count = Command->Parameter[0];
- ASSERT((Command->ParameterCount != 0) && (Count > 0) &&
- (Console->NextRow <= Console->ScreenRows - 1));
- VcpMoveCursorRelative(Console, 0, Count);
- break;
- case TerminalCommandCursorLeft:
- Count = Command->Parameter[0];
- ASSERT((Command->ParameterCount != 0) && (Count > 0));
- VcpMoveCursorRelative(Console, -Count, 0);
- break;
- case TerminalCommandCursorRight:
- Count = Command->Parameter[0];
- ASSERT((Command->ParameterCount != 0) && (Count > 0));
- ASSERT(Console->NextColumn < Console->Columns);
- VcpMoveCursorRelative(Console, Count, 0);
- break;
- case TerminalCommandSetCursorRowAbsolute:
- Row = Command->Parameter[0];
- ASSERT((Command->ParameterCount != 0) && (Row > 0));
- Row -= 1;
- VcpMoveCursorAbsolute(Console, Console->NextColumn, Row, TRUE);
- break;
- case TerminalCommandSetCursorColumnAbsolute:
- Column = Command->Parameter[0];
- ASSERT((Command->ParameterCount != 0) && (Column > 0));
- Column -= 1;
- VcpMoveCursorAbsolute(Console, Column, Console->NextRow, FALSE);
- break;
- case TerminalCommandCursorMove:
- Column = Command->Parameter[1];
- Row = Command->Parameter[0];
- ASSERT((Command->ParameterCount == 2) && (Column > 0) && (Row > 0));
- Column -= 1;
- Row -= 1;
- VcpMoveCursorAbsolute(Console, Column, Row, TRUE);
- break;
- case TerminalCommandNextLine:
- Console->NextColumn = 0;
- VcpAdvanceRow(Console);
- break;
- case TerminalCommandReverseLineFeed:
- if (Console->NextRow < Console->TopMargin) {
- if (Console->NextRow != 0) {
- Console->NextRow -= 1;
- }
- } else if (Console->NextRow == Console->TopMargin) {
- VcpInsertLines(Console, 1, Console->NextRow);
- } else {
- ASSERT(Console->NextRow > 0);
- Console->NextRow -= 1;
- }
- break;
- case TerminalCommandSaveCursorAndAttributes:
- VcpSaveRestoreCursor(Console, TRUE);
- break;
- case TerminalCommandRestoreCursorAndAttributes:
- VcpSaveRestoreCursor(Console, FALSE);
- break;
- case TerminalCommandSetHorizontalTab:
- case TerminalCommandClearHorizontalTab:
- break;
- case TerminalCommandSetTopAndBottomMargin:
- Top = 1;
- Bottom = Console->ScreenRows;
- if (Command->ParameterCount > 0) {
- if ((Command->Parameter[0] != 0) &&
- (Command->Parameter[0] <= Console->ScreenRows)) {
- Top = Command->Parameter[0];
- }
- if ((Command->ParameterCount > 1) && (Command->Parameter[1] != 0) &&
- (Command->Parameter[1] <= Console->ScreenRows)) {
- Bottom = Command->Parameter[1];
- }
- }
- if (Top < Bottom) {
- ASSERT((Top > 0) && (Top <= Console->ScreenRows) &&
- (Bottom > Top) && (Bottom <= Console->ScreenRows));
- Console->TopMargin = Top - 1;
- Console->BottomMargin = Console->ScreenRows - Bottom;
- }
- Console->NextColumn = 0;
- Console->NextRow = 0;
- if ((Console->Mode & CONSOLE_MODE_ORIGIN) != 0) {
- Console->NextRow += Console->TopMargin;
- }
- break;
- case TerminalCommandEraseInDisplay:
- case TerminalCommandEraseInDisplaySelective:
- ResetCharacterAttributes = TRUE;
- if (Command->Command == TerminalCommandEraseInDisplaySelective) {
- ResetCharacterAttributes = FALSE;
- }
- //
- // For no parameter or zero, erase from the cursor to the end of the
- // screen, including the cursor.
- //
- if ((Command->ParameterCount == 0) || (Command->Parameter[0] == 0)) {
- VcpEraseArea(Console,
- Console->NextColumn,
- Console->NextRow,
- Console->Columns - 1,
- Console->ScreenRows - 1,
- ResetCharacterAttributes);
- //
- // If the parameter is 1, erase from the top of the screen to the
- // current cursor, including the cursor.
- //
- } else if (Command->Parameter[0] == 1) {
- VcpEraseArea(Console,
- 0,
- 0,
- Console->NextColumn,
- Console->NextRow,
- ResetCharacterAttributes);
- //
- // If the parameter is 2, erase the entire display.
- //
- } else if (Command->Parameter[0] == 2) {
- VcpEraseArea(Console,
- 0,
- 0,
- Console->Columns - 1,
- Console->ScreenRows - 1,
- ResetCharacterAttributes);
- }
- break;
- case TerminalCommandEraseInLine:
- case TerminalCommandEraseInLineSelective:
- ResetCharacterAttributes = TRUE;
- if (Command->Command == TerminalCommandEraseInLineSelective) {
- ResetCharacterAttributes = FALSE;
- }
- //
- // For no parameters or zero, erase from the cursor to the end of the
- // line, including the cursor.
- //
- if ((Command->ParameterCount == 0) || (Command->Parameter[0] == 0)) {
- VcpEraseArea(Console,
- Console->NextColumn,
- Console->NextRow,
- Console->Columns - 1,
- Console->NextRow,
- ResetCharacterAttributes);
- //
- // Erase from the beginning of the line to the cursor, including the
- // cursor.
- //
- } else if (Command->Parameter[0] == 1) {
- VcpEraseArea(Console,
- 0,
- Console->NextRow,
- Console->NextColumn,
- Console->NextRow,
- ResetCharacterAttributes);
- } else if (Command->Parameter[0] == 2) {
- VcpEraseArea(Console,
- 0,
- Console->NextRow,
- Console->Columns - 1,
- Console->NextRow,
- ResetCharacterAttributes);
- }
- break;
- case TerminalCommandInsertLines:
- Count = 1;
- if ((Command->ParameterCount != 0) && (Command->Parameter[0] > 0)) {
- Count = Command->Parameter[0];
- }
- //
- // If the cursor is outside the scroll area.
- //
- if (!CURSOR_IN_SCROLL_REGION(Console)) {
- break;
- }
- Console->NextColumn = 0;
- VcpInsertLines(Console, Count, Console->NextRow);
- break;
- case TerminalCommandDeleteLines:
- Count = 1;
- if ((Command->ParameterCount != 0) && (Command->Parameter[0] > 0)) {
- Count = Command->Parameter[0];
- }
- //
- // If the cursor is outside the scroll area or at the very bottom of it,
- // this command is ignored.
- //
- if (!CURSOR_IN_SCROLL_REGION(Console)) {
- break;
- }
- Console->NextColumn = 0;
- if (Console->NextRow ==
- Console->ScreenRows - 1 - Console->BottomMargin) {
- break;
- }
- VcpDeleteLines(Console, Count, Console->NextRow);
- break;
- case TerminalCommandInsertCharacters:
- Count = 1;
- if ((Command->ParameterCount != 0) && (Command->Parameter[0] != 0)) {
- Count = Command->Parameter[0];
- }
- if (Count > Console->Columns - Console->NextColumn) {
- Count = Console->Columns - Console->NextColumn;
- }
- //
- // If insert mode is set, shift the remaining characters out.
- //
- Line = GET_CONSOLE_LINE(Console, Console->NextRow);
- for (Column = Console->Columns - 1;
- Column >= Console->NextColumn + Count;
- Column -= 1) {
- Line->Character[Column].AsUint32 =
- Line->Character[Column - Count].AsUint32;
- }
- RtlZeroMemory(&(Line->Character[Console->NextColumn]),
- Count * sizeof(BASE_VIDEO_CHARACTER));
- Console->PendingAction |= VIDEO_ACTION_REDRAW_ENTIRE_SCREEN;
- break;
- case TerminalCommandDeleteCharacters:
- Count = 1;
- if ((Command->ParameterCount != 0) && (Command->Parameter[0] != 0)) {
- Count = Command->Parameter[0];
- }
- if (Count > Console->Columns - Console->NextColumn) {
- Count = Console->Columns - Console->NextColumn;
- }
- //
- // Move the remaining characters backwards.
- //
- Line = GET_CONSOLE_LINE(Console, Console->NextRow);
- for (Column = Console->NextColumn;
- Column < Console->Columns - Count;
- Column += 1) {
- Line->Character[Column].AsUint32 =
- Line->Character[Column + Count].AsUint32;
- }
- //
- // Clear out the space at the right.
- //
- RtlZeroMemory(&(Line->Character[Console->Columns - Count]),
- Count * sizeof(BASE_VIDEO_CHARACTER));
- Console->PendingAction |= VIDEO_ACTION_REDRAW_ENTIRE_SCREEN;
- break;
- case TerminalCommandEraseCharacters:
- Count = 1;
- if ((Command->ParameterCount != 0) && (Command->Parameter[0] != 0)) {
- Count = Command->Parameter[0];
- }
- if (Count > Console->Columns - Console->NextColumn) {
- Count = Console->Columns - Console->NextColumn;
- }
- //
- // Erase characters starting at the cursor without shifting the line
- // contents.
- //
- VcpEraseArea(Console,
- Console->NextColumn,
- Console->NextRow,
- Console->NextColumn + Count - 1,
- Console->NextRow,
- TRUE);
- break;
- case TerminalCommandKeypadNumeric:
- case TerminalCommandKeypadApplication:
- break;
- case TerminalCommandSetMode:
- case TerminalCommandClearMode:
- case TerminalCommandSetPrivateMode:
- case TerminalCommandClearPrivateMode:
- for (ParameterIndex = 0;
- ParameterIndex < Command->ParameterCount;
- ParameterIndex += 1) {
- VcpSetOrClearMode(Console,
- Command->Parameter[ParameterIndex],
- Command->Command);
- }
- break;
- case TerminalCommandSelectG0CharacterSet:
- case TerminalCommandSelectG1CharacterSet:
- case TerminalCommandSelectG2CharacterSet:
- case TerminalCommandSelectG3CharacterSet:
- break;
- case TerminalCommandSelectGraphicRendition:
- VcpSetColorFromParameters(Console, Command);
- break;
- case TerminalCommandReset:
- case TerminalCommandSoftReset:
- Console->TextAttributes = 0;
- Console->NextRow = 0;
- Console->NextColumn = 0;
- Console->Mode = VIDEO_CONSOLE_MODE_DEFAULTS;
- Console->TopMargin = 0;
- Console->BottomMargin = 0;
- VcpEraseArea(Console,
- 0,
- 0,
- Console->Columns - 1,
- Console->ScreenRows - 1,
- TRUE);
- break;
- case TerminalCommandDeviceAttributesPrimary:
- case TerminalCommandDeviceAttributesSecondary:
- break;
- case TerminalCommandScrollUp:
- Count = Command->Parameter[0];
- if ((Command->ParameterCount == 0) || (Count <= 0)) {
- Count = 1;
- }
- if (Console->TopMargin == 0) {
- Console->RowViewOffset -= Count;
- } else {
- VcpDeleteLines(Console, Count, Console->TopMargin);
- }
- Console->PendingAction |= VIDEO_ACTION_REDRAW_ENTIRE_SCREEN;
- break;
- case TerminalCommandScrollDown:
- Count = Command->Parameter[0];
- if ((Command->ParameterCount == 0) || (Count <= 0)) {
- Count = 1;
- }
- if (Console->TopMargin == 0) {
- Console->RowViewOffset += Count;
- } else {
- VcpInsertLines(Console, Count, Console->TopMargin);
- }
- Console->PendingAction |= VIDEO_ACTION_REDRAW_ENTIRE_SCREEN;
- break;
- case TerminalCommandDoubleLineHeightTopHalf:
- case TerminalCommandDoubleLineHeightBottomHalf:
- case TerminalCommandSingleWidthLine:
- case TerminalCommandDoubleWidthLine:
- break;
- //
- // Do nothing for unknown commands.
- //
- default:
- break;
- }
- return;
- }
- VOID
- VcpEraseArea (
- PVIDEO_CONSOLE_DEVICE Console,
- LONG StartColumn,
- LONG StartRow,
- LONG EndColumn,
- LONG EndRow,
- BOOL ResetAttributes
- )
- /*++
- Routine Description:
- This routine erases a portion of the screen.
- Arguments:
- Console - Supplies a pointer to the video console to erase.
- StartColumn - Supplies the starting column, inclusive, to erase.
- StartRow - Supplies the starting row, inclusive, to erase.
- EndColumn - Supplies the ending column, inclusive, to erase.
- EndRow - Supplies the ending row, inclusive, to erase.
- ResetAttributes - Supplies a boolean indicating if the attributes should be
- reset to zero as well or left alone.
- Return Value:
- None.
- --*/
- {
- BOOL Blank;
- LONG Column;
- LONG EndColumnThisRow;
- PVIDEO_CONSOLE_LINE Line;
- LONG LineCount;
- LONG Row;
- LONG SavedBottomMargin;
- LONG SavedTopMargin;
- ASSERT((EndColumn < Console->Columns) && (EndRow < Console->ScreenRows));
- Console->RowViewOffset = 0;
- Console->PendingAction |= VIDEO_ACTION_REDRAW_ENTIRE_SCREEN;
- if (StartColumn == Console->Columns) {
- StartColumn -= 1;
- }
- if (EndColumn == Console->Columns) {
- EndColumn -= 1;
- }
- //
- // If erasing the whole screen, then actually scroll up until the screen
- // is blank.
- //
- if ((ResetAttributes != FALSE) && (StartColumn == 0) && (StartRow == 0) &&
- (EndColumn == Console->Columns - 1) &&
- (EndRow == Console->ScreenRows - 1)) {
- //
- // Find the last non-blank line.
- //
- for (Row = Console->ScreenRows - 1; Row >= 0; Row -= 1) {
- Blank = TRUE;
- Line = GET_CONSOLE_LINE(Console, Row);
- for (Column = 0; Column < Console->Columns; Column += 1) {
- if ((Line->Character[Column].Data.Character != 0) &&
- (Line->Character[Column].Data.Character != ' ')) {
- Blank = FALSE;
- break;
- }
- if (Line->Character[Column].Data.Attributes != 0) {
- Blank = FALSE;
- break;
- }
- }
- if (Blank == FALSE) {
- break;
- }
- }
- //
- // Scroll up by the number of non-blank lines.
- //
- LineCount = Row + 1;
- Row = Console->NextRow;
- SavedTopMargin = Console->TopMargin;
- SavedBottomMargin = Console->BottomMargin;
- Console->NextRow = Console->ScreenRows - 1;
- Console->TopMargin = 0;
- Console->BottomMargin = 0;
- while (LineCount != 0) {
- VcpAdvanceRow(Console);
- LineCount -= 1;
- }
- Console->NextRow = Row;
- Console->TopMargin = SavedTopMargin;
- Console->BottomMargin = SavedBottomMargin;
- return;
- }
- //
- // Really erase the given region, rather than just scrolling up.
- //
- for (Row = StartRow; Row <= EndRow; Row += 1) {
- Line = GET_CONSOLE_LINE(Console, Row);
- Column = 0;
- if (Row == StartRow) {
- Column = StartColumn;
- }
- EndColumnThisRow = Console->Columns - 1;
- if (Row == EndRow) {
- EndColumnThisRow = EndColumn;
- }
- ASSERT(Column <= EndColumnThisRow);
- if (ResetAttributes != FALSE) {
- while (Column <= EndColumnThisRow) {
- Line->Character[Column].Data.Character = ' ';
- Line->Character[Column].Data.Attributes =
- Console->TextAttributes;
- Column += 1;
- }
- } else {
- while (Column <= EndColumnThisRow) {
- Line->Character[Column].Data.Character = ' ';
- Column += 1;
- }
- }
- }
- return;
- }
- VOID
- VcpSetOrClearMode (
- PVIDEO_CONSOLE_DEVICE Console,
- ULONG ModeNumber,
- TERMINAL_COMMAND Command
- )
- /*++
- Routine Description:
- This routine sets or clears a console mode setting.
- Arguments:
- Console - Supplies a pointer to the video console to alter.
- ModeNumber - Supplies the mode number to set or clear.
- Command - Supplies the command number.
- Return Value:
- None.
- --*/
- {
- ULONG Mask;
- BOOL Set;
- Mask = 0;
- Set = FALSE;
- if ((Command == TerminalCommandSetMode) ||
- (Command == TerminalCommandSetPrivateMode)) {
- Set = TRUE;
- }
- if ((Command == TerminalCommandSetMode) ||
- (Command == TerminalCommandClearMode)) {
- switch (ModeNumber) {
- case TERMINAL_MODE_KEYBOARD_LOCKED:
- Mask = CONSOLE_MODE_KEYBOARD_ACTION;
- break;
- case TERMINAL_MODE_INSERT:
- Mask = CONSOLE_MODE_INSERT;
- break;
- case TERMINAL_MODE_DISABLE_LOCAL_ECHO:
- Mask = CONSOLE_MODE_DISABLE_LOCAL_ECHO;
- break;
- case TERMINAL_MODE_NEW_LINE:
- Mask = CONSOLE_MODE_NEW_LINE;
- break;
- default:
- break;
- }
- } else {
- ASSERT((Command == TerminalCommandSetPrivateMode) ||
- (Command == TerminalCommandClearPrivateMode));
- switch (ModeNumber) {
- case TERMINAL_PRIVATE_MODE_APPLICATION_CURSOR_KEYS:
- Mask = CONSOLE_MODE_APPLICATION_CURSOR_KEYS;
- break;
- case TERMINAL_PRIVATE_MODE_VT52:
- Mask = CONSOLE_MODE_VT52;
- break;
- case TERMINAL_PRIVATE_MODE_132_COLUMNS:
- Mask = CONSOLE_MODE_132_COLUMN;
- break;
- case TERMINAL_PRIVATE_MODE_SMOOTH_SCROLLING:
- Mask = CONSOLE_MODE_KEYBOARD_ACTION;
- break;
- case TERMINAL_PRIVATE_MODE_REVERSE_VIDEO:
- Mask = CONSOLE_MODE_VIDEO_REVERSED;
- Console->PendingAction = VIDEO_ACTION_REDRAW_ENTIRE_SCREEN;
- break;
- case TERMINAL_PRIVATE_MODE_ORIGIN:
- Mask = CONSOLE_MODE_ORIGIN;
- break;
- case TERMINAL_PRIVATE_MODE_AUTO_WRAP:
- Mask = CONSOLE_MODE_AUTO_WRAP;
- break;
- case TERMINAL_PRIVATE_MODE_BLINKING_CURSOR:
- Mask = CONSOLE_MODE_CURSOR_BLINK;
- break;
- case TERMINAL_PRIVATE_MODE_CURSOR:
- Mask = CONSOLE_MODE_CURSOR;
- break;
- case TERMINAL_PRIVATE_MODE_SAVE_CURSOR:
- VcpSaveRestoreCursor(Console, Set);
- break;
- case TERMINAL_PRIVATE_MODE_ALTERNATE_SCREEN_SAVE_CURSOR:
- VcpSaveRestoreCursor(Console, Set);
- //
- // Erase the screen in lieu of a keeping secondary screen buffer.
- //
- VcpEraseArea(Console,
- 0,
- 0,
- Console->Columns - 1,
- Console->ScreenRows - 1,
- TRUE);
- Console->TopMargin = 0;
- Console->BottomMargin = 0;
- break;
- case TERMINAL_PRIVATE_MODE_AUTO_REPEAT:
- case TERMINAL_PRIVATE_MODE_FORM_FEED:
- case TERMINAL_PRIVATE_MODE_PRINT_FULL_SCREEN:
- case TERMINAL_PRIVATE_MODE_NATIONAL:
- case TERMINAL_PRIVATE_MODE_ALTERNATE_SCREEN:
- break;
- }
- }
- if (Set != FALSE) {
- Console->Mode |= Mask;
- } else {
- Console->Mode &= ~Mask;
- }
- return;
- }
- VOID
- VcpRedrawArea (
- PVIDEO_CONSOLE_DEVICE Console,
- LONG StartColumn,
- LONG StartRow,
- LONG EndColumn,
- LONG EndRow
- )
- /*++
- Routine Description:
- This routine redraws a portion of the screen.
- Arguments:
- Console - Supplies a pointer to the video console to write to.
- StartColumn - Supplies the starting column, inclusive, to redraw at.
- StartRow - Supplies the starting row, inclusive, to redraw at.
- EndColumn - Supplies the ending column, exclusive, to redraw until.
- EndRow - Supplies the ending row, inclusive, to redraw until.
- Return Value:
- None.
- --*/
- {
- BASE_VIDEO_CHARACTER Blank;
- LONG BufferRow;
- PBASE_VIDEO_CHARACTER Characters;
- LONG CurrentColumn;
- LONG CurrentRow;
- LONG EndColumnThisRow;
- PVIDEO_CONSOLE_LINE Line;
- PBASE_VIDEO_CHARACTER ScreenCharacters;
- PVIDEO_CONSOLE_LINE ScreenLine;
- LONG StartDrawColumn;
- LONG Width;
- CurrentColumn = StartColumn;
- CurrentRow = StartRow;
- Width = Console->Columns;
- Blank.Data.Attributes = Console->TextAttributes;
- Blank.Data.Character = ' ';
- ASSERT((StartColumn <= Console->Columns) &&
- (EndColumn <= Console->Columns));
- ASSERT((StartRow < Console->ScreenRows) && (EndRow <= Console->ScreenRows));
- if (StartColumn >= Console->Columns) {
- StartColumn = Console->Columns - 1;
- }
- //
- // Loop through each row on the screen.
- //
- while (TRUE) {
- //
- // Get the line associated with this row. If the offset plus the
- // current row is greater than the screen size, this is an empty row.
- //
- if (CurrentRow + Console->RowViewOffset >= Console->ScreenRows) {
- Line = NULL;
- //
- // The current row plus the offset also needs to be greater than the
- // bottom of the screen (otherwise the bottom of the screen would show
- // up again if scrolled far enough up).
- //
- } else if (CurrentRow + Console->RowViewOffset <
- -(Console->BufferRows - Console->ScreenRows)) {
- Line = NULL;
- //
- // The offset is reasonable enough that there's a line associated with
- // it. Go find that line. The macro can't be used here because of the
- // potential for the buffer row to go negative during the calculation.
- //
- } else {
- BufferRow = Console->TopLine + CurrentRow + Console->RowViewOffset;
- if (BufferRow >= Console->BufferRows) {
- BufferRow -= Console->BufferRows;
- } else if (BufferRow < 0) {
- BufferRow += Console->BufferRows;
- }
- ASSERT((BufferRow >= 0) && (BufferRow < Console->BufferRows));
- Line = (PVIDEO_CONSOLE_LINE)(Console->Lines +
- (CONSOLE_LINE_SIZE(Console) *
- BufferRow));
- }
- //
- // Figure out the ending column for this row.
- //
- if (CurrentRow == EndRow) {
- EndColumnThisRow = EndColumn;
- } else {
- EndColumnThisRow = Width;
- }
- ScreenLine = (PVIDEO_CONSOLE_LINE)(Console->Screen +
- (CONSOLE_LINE_SIZE(Console) *
- CurrentRow));
- ScreenCharacters = ScreenLine->Character;
- if (Line != NULL) {
- Characters = Line->Character;
- //
- // Line attributes need support here if they're implemented.
- //
- ASSERT(ScreenLine->Attributes == Line->Attributes);
- while (CurrentColumn < EndColumnThisRow) {
- //
- // Skip characters that are already drawn correctly.
- //
- if (ScreenCharacters[CurrentColumn].AsUint32 ==
- Characters[CurrentColumn].AsUint32) {
- CurrentColumn += 1;
- continue;
- }
- //
- // Collect characters that need redrawing.
- //
- StartDrawColumn = CurrentColumn;
- while ((CurrentColumn < EndColumnThisRow) &&
- (ScreenCharacters[CurrentColumn].AsUint32 !=
- Characters[CurrentColumn].AsUint32)) {
- ScreenCharacters[CurrentColumn].AsUint32 =
- Characters[CurrentColumn].AsUint32;
- CurrentColumn += 1;
- }
- VidPrintCharacters(&(Console->VideoContext),
- StartDrawColumn,
- CurrentRow,
- &(ScreenCharacters[StartDrawColumn]),
- CurrentColumn - StartDrawColumn);
- }
- } else {
- while (CurrentColumn < EndColumnThisRow) {
- //
- // Skip characters that are already blank.
- //
- if (ScreenCharacters[CurrentColumn].AsUint32 ==
- Blank.AsUint32) {
- CurrentColumn += 1;
- continue;
- }
- //
- // Batch together characters that need redrawing.
- //
- StartDrawColumn = CurrentColumn;
- while ((CurrentColumn < EndColumnThisRow) &&
- (ScreenCharacters[CurrentColumn].AsUint32 !=
- Blank.AsUint32)) {
- ScreenCharacters[CurrentColumn] = Blank;
- CurrentColumn += 1;
- }
- VidPrintCharacters(&(Console->VideoContext),
- StartDrawColumn,
- CurrentRow,
- &(ScreenCharacters[StartDrawColumn]),
- CurrentColumn - StartDrawColumn);
- }
- }
- //
- // Potentially break if this was the last row.
- //
- if (CurrentRow == EndRow) {
- break;
- }
- //
- // On to the next row.
- //
- CurrentColumn = 0;
- CurrentRow += 1;
- }
- return;
- }
- VOID
- VcpAdvanceRow (
- PVIDEO_CONSOLE_DEVICE Console
- )
- /*++
- Routine Description:
- This routine move the console's "next row" up by one (visually down to the
- next row).
- Arguments:
- Console - Supplies a pointer to the video console to write to.
- ScreenRedrawNeeded - Supplies a pointer where a boolean will be returned
- indicating if the entire screen needs to be redrawn. If not, this
- boolean will be left uninitialized. If so, this boolean will be set to
- TRUE.
- Return Value:
- None.
- --*/
- {
- UINTN LineSize;
- ULONG NewAllocationSize;
- PVIDEO_CONSOLE_LINE NewLastLine;
- PVOID NewLines;
- LONG NewRowCount;
- ULONG OriginalSize;
- LONG Row;
- //
- // It's really easy if there are still extra rows on the screen to be
- // used.
- //
- if (Console->NextRow < Console->ScreenRows - 1 - Console->BottomMargin) {
- Console->NextRow += 1;
- return;
- }
- Console->PendingAction |= VIDEO_ACTION_REDRAW_ENTIRE_SCREEN;
- //
- // If the cursor made it beyond the bottom of the scroll area, then allow
- // movement towards the bottom of the screen. Don't scroll beyond that.
- //
- if (Console->NextRow > Console->ScreenRows - 1 - Console->BottomMargin) {
- if (Console->NextRow < Console->ScreenRows - 1) {
- Console->NextRow += 1;
- }
- return;
- }
- //
- // If the bottom console line is also the bottom buffer line, look into
- // expanding the buffer.
- //
- if ((Console->TopLine + Console->ScreenRows == Console->BufferRows) &&
- ((Console->BufferRows < Console->MaxRows) ||
- (Console->MaxRows == 0))) {
- NewRowCount = Console->BufferRows * 2;
- if ((Console->MaxRows != 0) && (NewRowCount > Console->MaxRows)) {
- NewRowCount = Console->MaxRows;
- }
- ASSERT(NewRowCount > Console->BufferRows);
- NewAllocationSize = CONSOLE_LINE_SIZE(Console) * NewRowCount;
- NewLines = MmAllocatePagedPool(NewAllocationSize,
- VIDEO_CONSOLE_ALLOCATION_TAG);
- if (NewLines != NULL) {
- OriginalSize = CONSOLE_LINE_SIZE(Console) * Console->BufferRows;
- RtlCopyMemory(NewLines, Console->Lines, OriginalSize);
- RtlZeroMemory(NewLines + OriginalSize,
- NewAllocationSize - OriginalSize);
- MmFreePagedPool(Console->Lines);
- Console->Lines = NewLines;
- Console->BufferRows = NewRowCount;
- }
- }
- LineSize = CONSOLE_LINE_SIZE(Console);
- //
- // If there's a top margin, then actually perform the scroll by copying
- // the lines up.
- //
- if (Console->TopMargin != 0) {
- for (Row = Console->TopMargin;
- Row < Console->ScreenRows - Console->BottomMargin - 1;
- Row += 1) {
- RtlCopyMemory(GET_CONSOLE_LINE(Console, Row),
- GET_CONSOLE_LINE(Console, Row + 1),
- LineSize);
- }
- RtlZeroMemory(GET_CONSOLE_LINE(Console, Row), LineSize);
- Console->RowViewOffset = 0;
- Console->PendingAction |= VIDEO_ACTION_REDRAW_ENTIRE_SCREEN;
- return;
- }
- //
- // Initialize and reset a fresh line.
- //
- if (Console->BottomMargin == 0) {
- NewLastLine = GET_CONSOLE_LINE(Console, Console->ScreenRows);
- //
- // There's a bottom margin (but not a top one), so move everything below
- // the bottom margin down one and zero out the bottom margin line.
- //
- } else {
- for (Row = Console->ScreenRows;
- Row > Console->ScreenRows - 1 - Console->BottomMargin;
- Row -= 1) {
- RtlCopyMemory(GET_CONSOLE_LINE(Console, Row),
- GET_CONSOLE_LINE(Console, Row - 1),
- LineSize);
- }
- NewLastLine = GET_CONSOLE_LINE(Console, Row + 1);
- Console->RowViewOffset = 0;
- Console->PendingAction |= VIDEO_ACTION_REDRAW_ENTIRE_SCREEN;
- }
- RtlZeroMemory(NewLastLine, LineSize);
- Console->TopLine = Console->TopLine + 1;
- if (Console->TopLine >= Console->BufferRows) {
- Console->TopLine -= Console->BufferRows;
- ASSERT(Console->TopLine < Console->BufferRows);
- }
- //
- // Create the appearance of filling up the space shown because the user
- // scrolled past the end.
- //
- if (Console->RowViewOffset > 0) {
- Console->RowViewOffset -= 1;
- }
- return;
- }
- VOID
- VcpSetColorFromParameters (
- PVIDEO_CONSOLE_DEVICE Console,
- PTERMINAL_COMMAND_DATA Command
- )
- /*++
- Routine Description:
- This routine sets the current text attributes based on the paramters in
- the input parse state.
- Arguments:
- Console - Supplies a pointer to the video console that just got the
- set colors command.
- Command - Supplies a pointer to the command to set attributes from.
- Return Value:
- None.
- --*/
- {
- USHORT Attributes;
- LONG Parameter;
- LONG ParameterIndex;
- Attributes = 0;
- for (ParameterIndex = 0;
- ParameterIndex < Command->ParameterCount;
- ParameterIndex += 1) {
- Parameter = Command->Parameter[ParameterIndex];
- if (Parameter == TERMINAL_GRAPHICS_BOLD) {
- Attributes |= BASE_VIDEO_FOREGROUND_BOLD;
- } else if (Parameter == TERMINAL_GRAPHICS_NEGATIVE) {
- Attributes |= BASE_VIDEO_NEGATIVE;
- } else if ((Parameter >= TERMINAL_GRAPHICS_FOREGROUND) &&
- (Parameter <
- TERMINAL_GRAPHICS_FOREGROUND + AnsiColorCount)) {
- Attributes &= ~BASE_VIDEO_COLOR_MASK;
- Attributes |= Parameter - TERMINAL_GRAPHICS_FOREGROUND +
- AnsiColorBlack;
- } else if ((Parameter >= TERMINAL_GRAPHICS_BACKGROUND) &&
- (Parameter <
- TERMINAL_GRAPHICS_BACKGROUND + AnsiColorCount)) {
- Attributes &= ~(BASE_VIDEO_COLOR_MASK <<
- BASE_VIDEO_BACKGROUND_SHIFT);
- Attributes |= (Parameter - TERMINAL_GRAPHICS_BACKGROUND +
- AnsiColorBlack) << BASE_VIDEO_BACKGROUND_SHIFT;
- }
- }
- Console->TextAttributes = Attributes;
- return;
- }
- VOID
- VcpSaveRestoreCursor (
- PVIDEO_CONSOLE_DEVICE Console,
- BOOL Save
- )
- /*++
- Routine Description:
- This routine saves or restores the cursor position and text attributes.
- Arguments:
- Console - Supplies a pointer to the video console.
- Save - Supplies a boolean indicating whether to save the attributes (TRUE)
- or restore them (FALSE).
- Return Value:
- None.
- --*/
- {
- if (Save != FALSE) {
- Console->SavedColumn = Console->NextColumn;
- Console->SavedRow = Console->NextRow;
- Console->SavedAttributes = Console->TextAttributes;
- } else {
- Console->NextColumn = Console->SavedColumn;
- Console->NextRow = Console->SavedRow;
- Console->TextAttributes = Console->SavedAttributes;
- }
- return;
- }
- VOID
- VcpMoveCursorRelative (
- PVIDEO_CONSOLE_DEVICE Console,
- LONG DistanceX,
- LONG DistanceY
- )
- /*++
- Routine Description:
- This routine moves the cursor relative to its current position.
- Arguments:
- Console - Supplies a pointer to the video console.
- DistanceX - Supplies the distance to move the cursor right. Negative values
- move left.
- DistanceY - Supplies the distance to move the cursor down. Negative values
- move up.
- Return Value:
- None.
- --*/
- {
- LONG NewColumn;
- LONG NewRow;
- NewColumn = Console->NextColumn + DistanceX;
- if (NewColumn < 0) {
- NewColumn = 0;
- } else if (NewColumn >= Console->Columns) {
- NewColumn = Console->Columns - 1;
- }
- NewRow = Console->NextRow + DistanceY;
- if (NewRow < Console->TopMargin) {
- NewRow = Console->TopMargin;
- } else if (NewRow >= Console->ScreenRows - Console->BottomMargin) {
- NewRow = Console->ScreenRows - 1 - Console->BottomMargin;
- }
- Console->NextRow = NewRow;
- Console->NextColumn = NewColumn;
- Console->PendingAction |= VIDEO_ACTION_RESET_SCROLL;
- return;
- }
- VOID
- VcpMoveCursorAbsolute (
- PVIDEO_CONSOLE_DEVICE Console,
- LONG Column,
- LONG Row,
- BOOL ProcessOriginMode
- )
- /*++
- Routine Description:
- This routine moves the cursor to a new absolute position.
- Arguments:
- Console - Supplies a pointer to the video console.
- Column - Supplies the new zero-based column to move to.
- Row - Supplies the new zero-based row to move to.
- ProcessOriginMode - Supplies a boolean indicating if this routine should
- adjust the position if origin mode is set.
- Return Value:
- None.
- --*/
- {
- LONG MaxRow;
- LONG MinRow;
- if (Column < 0) {
- Column = 0;
- } else if (Column >= Console->Columns) {
- Column = Console->Columns - 1;
- }
- MinRow = 0;
- MaxRow = Console->ScreenRows - 1;
- if (((Console->Mode & CONSOLE_MODE_ORIGIN) != 0) &&
- (ProcessOriginMode != FALSE)) {
- MinRow = Console->TopMargin;
- MaxRow -= Console->BottomMargin;
- Row += Console->TopMargin;
- }
- if (Row < MinRow) {
- Row = MinRow;
- }
- if (Row > MaxRow) {
- Row = MaxRow;
- }
- Console->NextRow = Row;
- Console->NextColumn = Column;
- Console->PendingAction |= VIDEO_ACTION_RESET_SCROLL;
- return;
- }
- VOID
- VcpDeleteLines (
- PVIDEO_CONSOLE_DEVICE Console,
- LONG Count,
- LONG StartingRow
- )
- /*++
- Routine Description:
- This routine deletes lines from the console screen, moving following lines
- up.
- Arguments:
- Console - Supplies a pointer to the video console.
- Count - Supplies the number of lines to delete.
- StartingRow - Supplies the first row of the region.
- Return Value:
- None.
- --*/
- {
- UINTN LineSize;
- LONG Row;
- if (StartingRow == Console->ScreenRows - 1 - Console->BottomMargin) {
- return;
- }
- //
- // If more lines are being deleted than can exist in the scroll area,
- // just erase the scroll area.
- //
- if (Count >
- (Console->ScreenRows - Console->BottomMargin -
- StartingRow + 1)) {
- VcpEraseArea(Console,
- 0,
- StartingRow,
- Console->Columns - 1,
- Console->ScreenRows - 1 - Console->BottomMargin,
- TRUE);
- return;
- }
- //
- // Move lines up within the scroll region.
- //
- LineSize = CONSOLE_LINE_SIZE(Console);
- for (Row = StartingRow;
- Row < Console->ScreenRows - Console->BottomMargin - Count;
- Row += 1) {
- RtlCopyMemory(GET_CONSOLE_LINE(Console, Row),
- GET_CONSOLE_LINE(Console, Row + Count),
- LineSize);
- }
- ASSERT(Row <= Console->ScreenRows - 1 - Console->BottomMargin);
- VcpEraseArea(Console,
- 0,
- Row,
- Console->Columns - 1,
- Console->ScreenRows - 1 - Console->BottomMargin,
- TRUE);
- Console->PendingAction |= VIDEO_ACTION_REDRAW_ENTIRE_SCREEN |
- VIDEO_ACTION_RESET_SCROLL;
- return;
- }
- VOID
- VcpInsertLines (
- PVIDEO_CONSOLE_DEVICE Console,
- LONG Count,
- LONG StartingRow
- )
- /*++
- Routine Description:
- This routine inserts lines on the console screen, moving following lines
- down.
- Arguments:
- Console - Supplies a pointer to the video console.
- Count - Supplies the number of lines to delete.
- StartingRow - Supplies the first row of the region.
- Return Value:
- None.
- --*/
- {
- UINTN LineSize;
- LONG Row;
- //
- // If more lines are being inserted than exist in the scroll area, just
- // erase the scroll area.
- //
- if (Count > Console->ScreenRows - Console->BottomMargin - StartingRow) {
- VcpEraseArea(Console,
- 0,
- StartingRow,
- Console->Columns - 1,
- Console->ScreenRows - 1 - Console->BottomMargin,
- TRUE);
- return;
- }
- //
- // Move lines down within the scroll region.
- //
- LineSize = CONSOLE_LINE_SIZE(Console);
- for (Row = Console->ScreenRows - Console->BottomMargin - 1;
- Row >= StartingRow + Count;
- Row -= 1) {
- RtlCopyMemory(GET_CONSOLE_LINE(Console, Row),
- GET_CONSOLE_LINE(Console, Row - Count),
- LineSize);
- }
- VcpEraseArea(Console,
- 0,
- StartingRow,
- Console->Columns - 1,
- StartingRow + Count - 1,
- TRUE);
- Console->PendingAction |= VIDEO_ACTION_REDRAW_ENTIRE_SCREEN |
- VIDEO_ACTION_RESET_SCROLL;
- return;
- }
|