/*++ Copyright (c) 1998-2001 Klaus P. Gerlicher Module Name: hardware.c Abstract: output to console Environment: Kernel mode only Author: Klaus P. Gerlicher Revision History: 04-Aug-1998: created 15-Nov-2000: general cleanup of source files Copyright notice: This file may be distributed under the terms of the GNU Public License. --*/ //////////////////////////////////////////////////// // INCLUDES //// #include "remods.h" #include "precomp.h" //////////////////////////////////////////////////// // PROTOTYPES //// //////////////////////////////////////////////////// // DEFINES //// //////////////////////////////////////////////////// // GLOBALS //// // flagging stuff BOOLEAN bCursorEnabled = FALSE; BOOLEAN bConsoleIsInitialized = FALSE; // terminal emulation ETERMINALMODE eTerminalMode = TERMINAL_MODE_NONE; // window stuff WINDOW wWindow[4]; // screen parameter ULONG GLOBAL_SCREEN_WIDTH,GLOBAL_SCREEN_HEIGHT; // jump table to real output functions OUTPUT_HANDLERS ohandlers; INPUT_HANDLERS ihandlers; // ring buffer stuff ULONG ulInPos = 0,ulLastPos = 0; ULONG ulOldInPos = 0,ulOldDelta = 0; BOOLEAN bSuspendPrintRingBuffer = FALSE; char aBuffers[LINES_IN_BUFFER][1024]; // output lock ULONG ulOutputLock; // color of windows pane separation bars USHORT usCaptionColor = BLUE; USHORT usCaptionText = WHITE; USHORT usForegroundColor = LTGRAY; USHORT usBackgroundColor = BLACK; USHORT usHiLiteColor = WHITE; //////////////////////////////////////////////////// // FUNCTIONS //// //************************************************************************* // SuspendPrintRingBuffer() // //************************************************************************* void SuspendPrintRingBuffer(BOOLEAN bSuspend) { ENTER_FUNC(); bSuspendPrintRingBuffer = bSuspend; LEAVE_FUNC(); } //************************************************************************* // EmptyRingBuffer() // //************************************************************************* void EmptyRingBuffer(void) { //ENTER_FUNC(); ulLastPos = ulInPos = ulOldInPos = ulOldDelta = 0; PICE_memset(aBuffers,0,sizeof(aBuffers)); //LEAVE_FUNC(); } //************************************************************************* // LinesInRingBuffer() // //************************************************************************* ULONG LinesInRingBuffer(void) { ULONG ulResult; // ENTER_FUNC(); ulResult = (ulInPos-ulLastPos)%LINES_IN_BUFFER; // LEAVE_FUNC(); return ulResult; } //************************************************************************* // CheckRingBuffer() // //************************************************************************* void CheckRingBuffer(void) { // ENTER_FUNC(); Acquire_Output_Lock(); if(ulInPos != ulOldInPos ) { ulOldInPos = ulInPos; PrintRingBuffer(wWindow[OUTPUT_WINDOW].cy-1); } Release_Output_Lock(); // LEAVE_FUNC(); } //************************************************************************* // AddToRingBuffer() // //************************************************************************* BOOLEAN AddToRingBuffer(LPSTR p) { ULONG i,j,len; BOOLEAN bHadReturn = FALSE; char temp[sizeof(aBuffers[0])]; // ENTER_FUNC(); // size of current string j=PICE_strlen(aBuffers[ulInPos]); // start with ':' and current has ':' in front if(aBuffers[ulInPos][0]==':' && *p==':') { if(j==1) { //LEAVE_FUNC(); return FALSE; } aBuffers[ulInPos][j++]='\n'; aBuffers[ulInPos][j]=0; ulInPos = (ulInPos+1)%LINES_IN_BUFFER; // wrap around if(ulInPos == ulLastPos) { ulLastPos = (ulLastPos+1)%LINES_IN_BUFFER; PICE_memset(aBuffers[ulInPos],0,sizeof(aBuffers[0])); } // reset to start of buffer j = 0; } // it's an internal print ("pICE: ...") else if(aBuffers[ulInPos][0]==':' && PICE_strncmpi(p,"pICE:",5)==0) { if(j==1) { PICE_memset(aBuffers[ulInPos],0,sizeof(aBuffers[0])); } else { aBuffers[ulInPos][j++]='\n'; aBuffers[ulInPos][j]=0; ulInPos = (ulInPos+1)%LINES_IN_BUFFER; // wrap around if(ulInPos == ulLastPos) { ulLastPos = (ulLastPos+1)%LINES_IN_BUFFER; PICE_memset(aBuffers[ulInPos],0,sizeof(aBuffers[0])); } } // reset to start of buffer j = 0; } // it's a debug print and the current line is starting with ':' else if(aBuffers[ulInPos][0]==':' && ( (*p=='<' && PICE_isdigit(*(p+1)) && *(p+2)=='>') || bIsDebugPrint) ) { if(j==1) { PICE_memset(aBuffers[ulInPos],0,sizeof(aBuffers[0])); } else { aBuffers[ulInPos][j++]='\n'; aBuffers[ulInPos][j]=0; ulInPos = (ulInPos+1)%LINES_IN_BUFFER; // wrap around if(ulInPos == ulLastPos) { ulLastPos = (ulLastPos+1)%LINES_IN_BUFFER; PICE_memset(aBuffers[ulInPos],0,sizeof(aBuffers[0])); } } // reset to start of buffer j = 0; } // it's a debug print else if(( (*p=='<' && PICE_isdigit(*(p+1)) && *(p+2)=='>') || bIsDebugPrint) ) { p += 3; } // size of new string len=PICE_strlen(p); // if combined string length too big // reduce to maximum if( (len+j) > sizeof(aBuffers[0])-2 ) { PICE_memcpy(temp,p,sizeof(aBuffers[0])-2); p = temp; // assume we end in NEWLINE p[sizeof(aBuffers[0])-2]='\n'; p[sizeof(aBuffers[0])-1]=0; } for(i=0;p[i]!=0;i++) { // newline if(p[i]=='\n') { aBuffers[ulInPos][j++]='\n'; aBuffers[ulInPos][j]=0; ulInPos = (ulInPos+1)%LINES_IN_BUFFER; // wrap around if(ulInPos == ulLastPos) { ulLastPos = (ulLastPos+1)%LINES_IN_BUFFER; PICE_memset(aBuffers[ulInPos],0,sizeof(aBuffers[0])); } // reset to start of buffer j = 0; // notify that we had a NEWLINE bHadReturn = TRUE; } // backspace else if(p[i]=='\b') { if(j!=0) { j--; aBuffers[ulInPos][j] = 0; } } // TAB else if(p[i]=='\t') { // copy TAB aBuffers[ulInPos][j++] = p[i]; } else { if((UCHAR)p[i]<0x20 && (UCHAR)p[i]>0x7f) p[i]=0x20; aBuffers[ulInPos][j++] = p[i]; } } // LEAVE_FUNC(); return bHadReturn; } //************************************************************************* // ReplaceRingBufferCurrent() // //************************************************************************* void ReplaceRingBufferCurrent(LPSTR s) { // ENTER_FUNC(); PICE_memset(aBuffers[ulInPos],0,sizeof(aBuffers[0])); PICE_strcpy(aBuffers[ulInPos],s); // LEAVE_FUNC(); } //************************************************************************* // PrintRingBuffer() // //************************************************************************* void PrintRingBuffer(ULONG ulLines) { ULONG ulDelta = LinesInRingBuffer(); ULONG ulOutPos,i=0; // ENTER_FUNC(); if(bSuspendPrintRingBuffer) { DPRINT((0,"PrintRingBuffer(): suspended\n")); LEAVE_FUNC(); return; } if(!ulDelta) { DPRINT((0,"PrintRingBuffer(): no lines in ring buffer\n")); LEAVE_FUNC(); return; } if(ulDelta=0x20 && (UCHAR)p[i]<0x80) { PrintGraf(x+i,y,p[i]); } } Flush(); Release_Output_Lock(); // LEAVE_FUNC(); } //************************************************************************* // CopyLineTo() // // copy a line from src to dest //************************************************************************* void CopyLineTo(USHORT dest,USHORT src) { ohandlers.CopyLineTo(dest,src); } //************************************************************************* // InvertLine() // // invert a line on the screen //************************************************************************* void InvertLine(ULONG line) { ohandlers.InvertLine(line); } //************************************************************************* // HatchLine() // // hatches a line on the screen //************************************************************************* void HatchLine(ULONG line) { ohandlers.HatchLine(line); } //************************************************************************* // ClrLine() // // clear a line on the screen //************************************************************************* void ClrLine(ULONG line) { ohandlers.ClrLine(line); } //************************************************************************* // ScrollUp() // // Scroll a specific window up one line //************************************************************************* void ScrollUp(USHORT Window) { USHORT i; return; if(!wWindow[Window].bScrollDisabled) { for(i=1;i (GLOBAL_SCREEN_WIDTH-1)) bOutput = FALSE; // newline if(p[i]=='\n') { wWindow[Window].usCurX = 0; wWindow[Window].usCurY++; if(wWindow[Window].usCurY>=wWindow[Window].cy) { wWindow[Window].usCurY=wWindow[Window].cy-1; ScrollUp(Window); } if(wWindow[Window].bScrollDisabled==TRUE)break; } // backspace else if(p[i]=='\b') { if(wWindow[Window].usCurX>0) { wWindow[Window].usCurX--; if(bOutput) PrintGraf(wWindow[Window].usCurX,wWindow[Window].y+wWindow[Window].usCurY,0x20); } } // TAB else if(p[i]=='\t') { if((wWindow[Window].usCurX + 4) < (GLOBAL_SCREEN_WIDTH-1)) { wWindow[Window].usCurX += 4; } } else { if((UCHAR)p[i]<0x20 && (UCHAR)p[i]>0x7f) p[i]=0x20; if(bOutput) PrintGraf(wWindow[Window].usCurX,wWindow[Window].y+wWindow[Window].usCurY,p[i]); wWindow[Window].usCurX++; } } // flush Flush(); } //LEAVE_FUNC(); } //************************************************************************* // SaveGraphicsState() // //************************************************************************* void SaveGraphicsState(void) { ohandlers.SaveGraphicsState(); } //************************************************************************* // RestoreGraphicsState() // //************************************************************************* void RestoreGraphicsState(void) { ohandlers.RestoreGraphicsState(); } //************************************************************************* // SetWindowGeometry() // //************************************************************************* void SetWindowGeometry(PVOID pWindow) { PICE_memcpy(wWindow,pWindow,sizeof(wWindow)); } // INPUT handlers //************************************************************************* // GetKeyPolled() // //************************************************************************* UCHAR GetKeyPolled(void) { return ihandlers.GetKeyPolled(); } //************************************************************************* // FlushKeyboardQueue() // //************************************************************************* void FlushKeyboardQueue(void) { ihandlers.FlushKeyboardQueue(); } //************************************************************************* // ConsoleInit() // // init terminal screen //************************************************************************* BOOLEAN ConsoleInit(void) { BOOLEAN bResult = FALSE; ENTER_FUNC(); // preset ohandlers and ihandler to NULL PICE_memset((void*)&ohandlers,0,sizeof(ohandlers)); PICE_memset((void*)&ihandlers,0,sizeof(ihandlers)); switch(eTerminalMode) { case TERMINAL_MODE_HERCULES_GRAPHICS: bResult = ConsoleInitHercules(); break; case TERMINAL_MODE_HERCULES_TEXT: break; case TERMINAL_MODE_VGA_TEXT: bResult = ConsoleInitVga(); break; case TERMINAL_MODE_SERIAL: bResult = ConsoleInitSerial(); break; case TERMINAL_MODE_NONE: default: // fail break; } // check that outputhandlers have all been set // ohandlers.Flush may be zero on return if( !ohandlers.ClrLine || !ohandlers.CopyLineTo || !ohandlers.HatchLine || !ohandlers.HideCursor || !ohandlers.InvertLine || !ohandlers.PrintCursor || !ohandlers.PrintGraf || !ohandlers.PrintLogo || !ohandlers.RestoreGraphicsState || !ohandlers.SaveGraphicsState || !ohandlers.SetBackgroundColor || !ohandlers.SetForegroundColor || !ohandlers.ShowCursor) { bResult = FALSE; } // check that inputhandlers were installed if( !ihandlers.GetKeyPolled || !ihandlers.FlushKeyboardQueue) { bResult = FALSE; } LEAVE_FUNC(); bConsoleIsInitialized = bResult; return bResult; } //************************************************************************* // ConsoleShutdown() // // exit terminal screen //************************************************************************* void ConsoleShutdown(void) { ENTER_FUNC(); // sleep for a few seconds KeStallExecutionProcessor(1000*5000); switch(eTerminalMode) { case TERMINAL_MODE_HERCULES_GRAPHICS: ConsoleShutdownHercules(); break; case TERMINAL_MODE_HERCULES_TEXT: break; case TERMINAL_MODE_VGA_TEXT: ConsoleShutdownVga(); break; case TERMINAL_MODE_SERIAL: ConsoleShutdownSerial(); break; case TERMINAL_MODE_NONE: default: // fail break; } LEAVE_FUNC(); } // EOF