|  | /* generic.c */ | 
|  | /* Copyright 1999 - Joseph Pranevich */ | 
|  |  | 
|  | /* This is a driver to implement, when possible, "high-level" | 
|  | routines using only low level calls. This is to make it possible | 
|  | to have accelerated functions for the individual drivers... | 
|  | or to simply not bother with them. */ | 
|  |  | 
|  | /* When creating new drivers, you need to assign all the functions that | 
|  | that driver supports into the driver struct. If it is a supplementary | 
|  | driver, it should make sure to perserve the old values. */ | 
|  |  | 
|  | #include <stdio.h> | 
|  |  | 
|  | #include "console.h" | 
|  | #include "config.h" | 
|  | #include "debugtools.h" | 
|  |  | 
|  | DEFAULT_DEBUG_CHANNEL(console) | 
|  |  | 
|  | static void GENERIC_MoveLine(char row1, char row2, char col1, char col2); | 
|  | static void GENERIC_ClearLine(char row, char col1, char col2, int bgcolor, | 
|  | int attribute); | 
|  | void GENERIC_Start(void) | 
|  | { | 
|  | /* Here, we only want to add a driver if there is not one already | 
|  | defined. */ | 
|  |  | 
|  | TRACE("GENERIC_Start\n"); | 
|  |  | 
|  | if (!driver.clearWindow) | 
|  | driver.clearWindow = GENERIC_ClearWindow; | 
|  |  | 
|  | if (!driver.scrollUpWindow) | 
|  | driver.scrollUpWindow = GENERIC_ScrollUpWindow; | 
|  |  | 
|  | if (!driver.scrollDownWindow) | 
|  | driver.scrollDownWindow = GENERIC_ScrollDownWindow; | 
|  |  | 
|  | if (!driver.getCharacter) | 
|  | driver.getCharacter = GENERIC_GetCharacter; | 
|  | } | 
|  |  | 
|  | void GENERIC_ClearWindow(char row1, char col1, char row2, char col2, | 
|  | int bg_color, int attribute) | 
|  | { | 
|  | char trow, tcol, x; | 
|  | int old_refresh; | 
|  |  | 
|  | /* Abort if we have only partial functionality */ | 
|  | if (!(driver.getCursorPosition && driver.moveCursor && driver.write)) | 
|  | return; | 
|  |  | 
|  | old_refresh = CONSOLE_GetRefresh(); | 
|  | CONSOLE_SetRefresh(FALSE); | 
|  |  | 
|  | CONSOLE_GetCursorPosition(&trow, &tcol); | 
|  |  | 
|  | for (x = row1; x <= row2; x++) | 
|  | GENERIC_ClearLine(x, col1, col2, bg_color, attribute); | 
|  |  | 
|  | CONSOLE_MoveCursor(trow, tcol); | 
|  |  | 
|  | CONSOLE_SetRefresh(old_refresh); | 
|  | } | 
|  |  | 
|  | void GENERIC_ScrollUpWindow(char row1, char col1, char row2, char col2, | 
|  | char lines, int bg_color, int attribute) | 
|  | { | 
|  | /* Scroll Up Window: Characters go down */ | 
|  |  | 
|  | char trow, tcol, x; | 
|  | int old_refresh; | 
|  |  | 
|  | TRACE("Scroll Up %d lines from %d to %d.\n", lines, row1, | 
|  | row2); | 
|  |  | 
|  | /* Abort if we have only partial functionality */ | 
|  | if (!(driver.getCursorPosition && driver.moveCursor && driver.write | 
|  | && driver.getCharacterAtCursor && driver.clearWindow)) | 
|  | return; | 
|  |  | 
|  | /* Save initial state... */ | 
|  | old_refresh = CONSOLE_GetRefresh(); | 
|  | CONSOLE_SetRefresh(FALSE); | 
|  | CONSOLE_GetCursorPosition(&trow, &tcol); | 
|  |  | 
|  | for (x = row1 + lines; x <= row2; x++) | 
|  | { | 
|  | GENERIC_MoveLine(x, x - lines, col1, col2); | 
|  | GENERIC_ClearLine(x, col1, col2, bg_color, attribute); | 
|  | } | 
|  |  | 
|  | /* Restore State */ | 
|  | CONSOLE_MoveCursor(trow, tcol); | 
|  | CONSOLE_SetRefresh(old_refresh); | 
|  | } | 
|  |  | 
|  | void GENERIC_ScrollDownWindow(char row1, char col1, char row2, char col2, | 
|  | char lines, int bg_color, int attribute) | 
|  | { | 
|  | /* Scroll Down Window: Characters go up */ | 
|  |  | 
|  | char trow, tcol, x; | 
|  | int old_refresh; | 
|  |  | 
|  | /* Abort if we have only partial functionality */ | 
|  | if (!(driver.getCursorPosition && driver.moveCursor && driver.write | 
|  | && driver.getCharacterAtCursor && driver.clearWindow)) | 
|  | return; | 
|  |  | 
|  | /* Save initial state... */ | 
|  | old_refresh = CONSOLE_GetRefresh(); | 
|  | CONSOLE_SetRefresh(FALSE); | 
|  | CONSOLE_GetCursorPosition(&trow, &tcol); | 
|  |  | 
|  | for (x = row2; x >= row1 + lines; x--) | 
|  | { | 
|  | GENERIC_MoveLine(x, x + lines, col1, col2); | 
|  | GENERIC_ClearLine(x, col1, col1, bg_color, attribute); | 
|  | } | 
|  |  | 
|  | /* Restore State */ | 
|  | CONSOLE_MoveCursor(trow, tcol); | 
|  | CONSOLE_SetRefresh(old_refresh); | 
|  | } | 
|  |  | 
|  | char GENERIC_GetCharacter() | 
|  | { | 
|  | /* Keep getting keys until we get one with a char value */ | 
|  | char ch = (char) 0, scan; | 
|  |  | 
|  | while (!ch) | 
|  | { | 
|  | CONSOLE_GetKeystroke(&scan, &ch); | 
|  | } | 
|  | return ch; | 
|  | } | 
|  |  | 
|  | static void GENERIC_ClearLine(char row, char col1, char col2, int bgcolor, | 
|  | int attribute) | 
|  | { | 
|  | /* This function is here to simplify the logic of the scroll and clear | 
|  | functions but may be useful elsewhere. If it can be used from | 
|  | outside here, it should be made non-static */ | 
|  |  | 
|  | char x; | 
|  |  | 
|  | TRACE("Clear Line: %d from %d to %d.\n", row, col1, col2); | 
|  |  | 
|  | for (x = col1; x <= col2; x++) | 
|  | { | 
|  | CONSOLE_MoveCursor(row, x); | 
|  | CONSOLE_Write(' ', 0, 0, 0); | 
|  | } | 
|  |  | 
|  | /* Assume that the calling function will make sure that the cursor is | 
|  | repositioned properly. If this becomes non-static, that will need to be | 
|  | changed. */ | 
|  | } | 
|  |  | 
|  | static void GENERIC_MoveLine(char row1, char row2, char col1, char col2) | 
|  | { | 
|  | /* This function is here to simplify the logic of the scroll and clear | 
|  | functions but may be useful elsewhere. If it can be used from | 
|  | outside here, it should be made non-static */ | 
|  |  | 
|  | char x; | 
|  | int bg_color, fg_color, attribute; | 
|  | char ch; | 
|  |  | 
|  | TRACE("Move Line: Move %d to %d.\n", row1, row2); | 
|  |  | 
|  | for (x = col1; x <= col2; x++) | 
|  | { | 
|  | CONSOLE_MoveCursor(row1, x); | 
|  | CONSOLE_GetCharacterAtCursor(&ch, &fg_color, &bg_color, &attribute); | 
|  | CONSOLE_MoveCursor(row2, x); | 
|  | CONSOLE_Write(ch, fg_color, bg_color, attribute); | 
|  | } | 
|  |  | 
|  | /* Assume that the calling function will make sure that the cursor is | 
|  | repositioned properly. If this becomes non-static, that will need to be | 
|  | changed. */ | 
|  | } |