| /* interface.c */ | 
 |  | 
 | /* The primary purpose of this function is to provide CONSOLE_* | 
 |    reotines that immediately call the appropiate driver handler. | 
 |    This cleans up code in the individual modules considerably. | 
 |    This could be done using a macro, but additional functionality | 
 |    may be provided here in the future. */ | 
 |  | 
 | #include <stdio.h> | 
 | #include <stdlib.h> | 
 | #include <string.h> | 
 |  | 
 | #include "config.h" | 
 | #include "windef.h" | 
 | #include "console.h" | 
 | #include "options.h" | 
 |  | 
 | static int pop_driver(char **, char **, int *); | 
 |  | 
 | static int console_initialized = FALSE; | 
 |  | 
 | int CONSOLE_Init(char *drivers) | 
 | { | 
 |       /* When this function is called drivers should be a string | 
 |          that consists of driver names followed by plus (+) signs | 
 |          to denote additions.  | 
 |  | 
 |          For example: | 
 |             drivers = tty                Load just the tty driver | 
 |             drivers = ncurses+xterm      Load ncurses then xterm | 
 |  | 
 |          The "default" value is just tty. | 
 |       */ | 
 |        | 
 |       char *single; | 
 |       int length; | 
 |       char initial_rows[5]; | 
 |       char initial_columns[5]; | 
 |  | 
 |       /* Suitable defaults... */ | 
 |       driver.console_out = stdout; | 
 |       driver.console_in = stdin; | 
 |  | 
 |       while (pop_driver(&drivers, &single, &length)) | 
 |       { | 
 |          if (!strncmp(single, "tty", length)) | 
 |             TTY_Start(); | 
 | #ifdef WINE_NCURSES | 
 |          else if (!strncmp(single, "ncurses", length)) | 
 |             NCURSES_Start(); | 
 | #endif /* WINE_NCURSES */ | 
 |          else if (!strncmp(single, "xterm", length)) | 
 |             XTERM_Start(); | 
 |       } | 
 |  | 
 |    /* Read in generic configuration */ | 
 |    /* This is primarily to work around a limitation in nxterm where | 
 |       this information is not correctly passed to the ncurses layer | 
 |       through the terminal. At least, I'm not doing it correctly if there | 
 |       is a way. But this serves as a generic way to do the same anyway. */ | 
 |  | 
 |    /* We are setting this to 80x25 here which is *not* the default for | 
 |       most xterm variants... It is however the standard VGA resolution */ | 
 |  | 
 |    /* FIXME: We need to be able to be able to specify that the window's | 
 |       dimensions should be used. This is required for correct emulation | 
 |       of Win32's console and Win32's DOS emulation */ | 
 |  | 
 |    PROFILE_GetWineIniString("console", "InitialRows", | 
 |       "24", initial_rows, 5); | 
 |    PROFILE_GetWineIniString("console", "InitialColumns", | 
 |       "80", initial_columns, 5); | 
 |  | 
 |    sscanf(initial_rows, "%d", &driver.y_res); | 
 |    sscanf(initial_columns, "%d", &driver.x_res); | 
 |     | 
 |    GENERIC_Start(); | 
 |  | 
 |    if (driver.init) | 
 |       driver.init(); | 
 |  | 
 |    /* Not all terminals let our programs know the proper resolution | 
 |       if the resolution is set on the command-line... */ | 
 |    CONSOLE_NotifyResizeScreen(driver.x_res, driver.y_res); | 
 |  | 
 |    /* For now, always return TRUE */ | 
 |    return TRUE; | 
 | } | 
 |  | 
 | void CONSOLE_Write(char out, int fg_color, int bg_color, int attribute) | 
 | { | 
 |    if (!console_initialized) | 
 |       console_initialized = CONSOLE_Init(driver.driver_list); | 
 |        | 
 |    if (driver.write) | 
 |    { | 
 |       driver.write(out, fg_color, bg_color, attribute); | 
 |       if (!driver.norefresh) | 
 |          CONSOLE_Refresh(); | 
 |    } | 
 | } | 
 |  | 
 | void CONSOLE_Close() | 
 | { | 
 |    if (driver.close) | 
 |       driver.close(); | 
 | } | 
 |  | 
 | void CONSOLE_MoveCursor(char row, char col) | 
 | { | 
 |    if (!console_initialized) | 
 |       console_initialized = CONSOLE_Init(driver.driver_list); | 
 |        | 
 |    if (driver.moveCursor) | 
 |    { | 
 |       driver.moveCursor(row, col); | 
 |       if (!driver.norefresh) | 
 |          CONSOLE_Refresh(); | 
 |    } | 
 | } | 
 |  | 
 | void CONSOLE_ClearWindow(char row1, char col1, char row2, char col2,  | 
 |    int bg_color, int attribute) | 
 | { | 
 |    if (!console_initialized) | 
 |       console_initialized = CONSOLE_Init(driver.driver_list); | 
 |        | 
 |    if (driver.clearWindow) | 
 |    { | 
 |       driver.clearWindow(row1, col1, row2, col2, bg_color, attribute); | 
 |       if (!driver.norefresh) | 
 |          CONSOLE_Refresh(); | 
 |    } | 
 | } | 
 |  | 
 | void CONSOLE_ScrollUpWindow(char row1, char col1, char row2, char col2,  | 
 |    char lines, int bg_color, int attribute) | 
 | { | 
 |    if (!console_initialized) | 
 |       console_initialized = CONSOLE_Init(driver.driver_list); | 
 |        | 
 |    if (driver.scrollUpWindow) | 
 |    { | 
 |       driver.scrollUpWindow(row1, col1, row2, col2, lines, bg_color,  | 
 |          attribute); | 
 |       if (!driver.norefresh) | 
 |          CONSOLE_Refresh(); | 
 |    } | 
 | } | 
 |  | 
 | void CONSOLE_ScrollDownWindow(char row1, char col1, char row2, char col2,  | 
 |    char lines, int bg_color, int attribute) | 
 | { | 
 |    if (!console_initialized) | 
 |       console_initialized = CONSOLE_Init(driver.driver_list); | 
 |        | 
 |    if (driver.scrollDownWindow) | 
 |    { | 
 |       driver.scrollDownWindow(row1, col1, row2, col2, lines, bg_color,  | 
 |          attribute); | 
 |       if (!driver.norefresh) | 
 |          CONSOLE_Refresh(); | 
 |    } | 
 | } | 
 |  | 
 | int CONSOLE_CheckForKeystroke(char *scan, char *ascii) | 
 | /* These functions need to go through a conversion layer. Scancodes | 
 |    should *not* be determined by the driver, rather they should have | 
 |    a conv_* function in int16.c. Yuck. */ | 
 | { | 
 |    if (!console_initialized) | 
 |       console_initialized = CONSOLE_Init(driver.driver_list); | 
 |        | 
 |    if (driver.checkForKeystroke) | 
 |       return driver.checkForKeystroke(scan, ascii); | 
 |    else | 
 |       return FALSE; | 
 | } | 
 |  | 
 | void CONSOLE_GetKeystroke(char *scan, char *ascii) | 
 | { | 
 |    if (!console_initialized) | 
 |       console_initialized = CONSOLE_Init(driver.driver_list); | 
 |        | 
 |    if (driver.getKeystroke) | 
 |       driver.getKeystroke(scan, ascii); | 
 | } | 
 |  | 
 | void CONSOLE_GetCursorPosition(char *row, char *col) | 
 | { | 
 |    if (!console_initialized) | 
 |       console_initialized = CONSOLE_Init(driver.driver_list); | 
 |        | 
 |    if (driver.getCursorPosition) | 
 |       driver.getCursorPosition(row, col); | 
 | } | 
 |  | 
 | void CONSOLE_GetCharacterAtCursor(char *ch, int *fg, int *bg, int *a) | 
 | { | 
 |    if (!console_initialized) | 
 |       console_initialized = CONSOLE_Init(driver.driver_list); | 
 |        | 
 |    if (driver.getCharacterAtCursor) | 
 |       driver.getCharacterAtCursor(ch, fg, bg, a); | 
 | } | 
 |  | 
 | void CONSOLE_Refresh() | 
 | { | 
 |    if (!console_initialized) | 
 |       console_initialized = CONSOLE_Init(driver.driver_list); | 
 |        | 
 |    if (driver.refresh) | 
 |       driver.refresh(); | 
 | } | 
 |  | 
 | int CONSOLE_AllocColor(int color) | 
 | { | 
 |    if (!console_initialized) | 
 |       console_initialized = CONSOLE_Init(driver.driver_list); | 
 |        | 
 |    if (driver.allocColor) | 
 |       return driver.allocColor(color); | 
 |    else  | 
 |       return 0; | 
 | } | 
 |  | 
 | void CONSOLE_ClearScreen() | 
 | { | 
 |    if (!console_initialized) | 
 |       console_initialized = CONSOLE_Init(driver.driver_list); | 
 |        | 
 |    if (driver.clearScreen) | 
 |    { | 
 |       driver.clearScreen(); | 
 |       if (!driver.norefresh) | 
 |          CONSOLE_Refresh(); | 
 |    } | 
 | } | 
 |  | 
 | char CONSOLE_GetCharacter() | 
 | { | 
 |    if (!console_initialized) | 
 |       console_initialized = CONSOLE_Init(driver.driver_list); | 
 |        | 
 |    /* I'm not sure if we need this really. This is a function that can be | 
 |       accelerated that returns the next *non extended* keystroke */ | 
 |    if (driver.getCharacter) | 
 |       return driver.getCharacter(); | 
 |    else | 
 |       return (char) 0; /* Sure, this will probably break programs... */ | 
 | } | 
 |  | 
 | void CONSOLE_ResizeScreen(int x, int y) | 
 | { | 
 |    if (!console_initialized) | 
 |       console_initialized = CONSOLE_Init(driver.driver_list); | 
 |        | 
 |    if (driver.resizeScreen) | 
 |       driver.resizeScreen(x, y); | 
 | } | 
 |  | 
 | void CONSOLE_NotifyResizeScreen(int x, int y) | 
 | { | 
 |    if (driver.notifyResizeScreen) | 
 |       driver.notifyResizeScreen(x, y); | 
 | } | 
 |  | 
 | void CONSOLE_SetBackgroundColor(int fg, int bg) | 
 | { | 
 |    if (!console_initialized) | 
 |       console_initialized = CONSOLE_Init(driver.driver_list); | 
 |        | 
 |    if (driver.setBackgroundColor) | 
 |       driver.setBackgroundColor(fg, bg); | 
 | } | 
 |  | 
 | void CONSOLE_GetBackgroundColor(int *fg, int *bg) | 
 | { | 
 |    if (!console_initialized) | 
 |       console_initialized = CONSOLE_Init(driver.driver_list); | 
 |        | 
 |    if (driver.getBackgroundColor) | 
 |       driver.getBackgroundColor(fg, bg); | 
 | } | 
 |  | 
 | void CONSOLE_WriteRawString(char *str) | 
 | { | 
 |    if (!console_initialized) | 
 |       console_initialized = CONSOLE_Init(driver.driver_list); | 
 |        | 
 |    /* This is a special function that is only for internal use and  | 
 |       does not actually call any of the console drivers. It's  | 
 |       primary purpose is to provide a way for higher-level drivers | 
 |       to write directly to the underlying terminal without worry that | 
 |       there will be any retranslation done by the assorted drivers. Care | 
 |       should be taken to ensure that this only gets called when the thing | 
 |       written does not actually produce any output or a CONSOLE_Redraw() | 
 |       is called immediately afterwards. | 
 |       CONSOLE_Redraw() is not yet implemented. | 
 |    */ | 
 |    fprintf(driver.console_out, "%s", str); | 
 | } | 
 |  | 
 | /* This function is only at the CONSOLE level. */ | 
 | /* Admittably, calling the variable norefresh might be a bit dumb...*/ | 
 | void CONSOLE_SetRefresh(int setting) | 
 | { | 
 |    if (setting) | 
 |       driver.norefresh = FALSE; | 
 |    else | 
 |       driver.norefresh = TRUE; | 
 | } | 
 |  | 
 | /* This function is only at the CONSOLE level. */ | 
 | int CONSOLE_GetRefresh() | 
 | { | 
 |    if (driver.norefresh) | 
 |       return FALSE; | 
 |    else  | 
 |       return TRUE; | 
 | } | 
 |  | 
 |  | 
 | /* Utility functions... */ | 
 |  | 
 | int pop_driver(char **drivers, char **single, int *length) | 
 | { | 
 |    /* Take the string in drivers and extract the first "driver" entry */ | 
 |    /* Advance the pointer in drivers to the next entry, put the origional | 
 |       pointer in single, and put the length in length. */ | 
 |    /* Return TRUE if we found one */ | 
 |  | 
 |    if (!*drivers) | 
 |       return FALSE; | 
 |  | 
 |    *single = *drivers; | 
 |    *length = 0; | 
 |  | 
 |    while ((*drivers[0] != NULL) && (*drivers[0] != '+')) | 
 |    { | 
 |       (*drivers)++; | 
 |       (*length)++; | 
 |    } | 
 |     | 
 |    while (*drivers[0] == '+') | 
 |       (*drivers)++; | 
 |  | 
 |    if (*length) | 
 |       return TRUE; | 
 |    else | 
 |       return FALSE; | 
 |        | 
 | } |