| /* ncurses.c */ | 
 | /* Copyright 1999 - Joseph Pranevich */ | 
 |  | 
 | #include <stdio.h> | 
 | #include "config.h" | 
 | #include "console.h"	/* Must define WINE_NCURSES */ | 
 |  | 
 | #ifdef WINE_NCURSES | 
 |  | 
 | /* This is the console driver for systems that support the ncurses | 
 |    interface.  | 
 | */ | 
 |  | 
 | /* Actually, this should work for curses, as well. But there may be | 
 |    individual functions that are unsupported in plain curses or other | 
 |    variants. Those should be detected and special-cased by autoconf.  | 
 | */ | 
 |  | 
 | /* 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 "debugtools.h" | 
 | #include "options.h" | 
 |  | 
 | DEFAULT_DEBUG_CHANNEL(console); | 
 |  | 
 | #undef ERR /* Use ncurses's err() */ | 
 | #ifdef HAVE_NCURSES_H | 
 | # include <ncurses.h> | 
 | #else | 
 | # ifdef HAVE_CURSES_H | 
 | #  include <curses.h> | 
 | # endif | 
 | #endif | 
 |  | 
 | SCREEN *ncurses_screen; | 
 |  | 
 | static int get_color_pair(int fg_color, int bg_color); | 
 |  | 
 | const char *color_names[] = {"null", "black", "blue", "green", | 
 |    "cyan", "magenta", "brown", "red", "light gray", "dark gray", | 
 |    "light blue", "light green", "light red", "light magenta", | 
 |    "light cyan", "yellow", "white"}; | 
 |  | 
 | void NCURSES_Start() | 
 | { | 
 |    /* This should be the root driver so we can ignore anything | 
 |       already in the struct. */ | 
 |  | 
 |    driver.norefresh = FALSE; | 
 |  | 
 |    driver.init = NCURSES_Init; | 
 |    driver.write = NCURSES_Write; | 
 |    driver.close = NCURSES_Close; | 
 |    driver.moveCursor = NCURSES_MoveCursor; | 
 |    driver.getCursorPosition = NCURSES_GetCursorPosition; | 
 |    driver.getCharacterAtCursor = NCURSES_GetCharacterAtCursor; | 
 |    driver.clearScreen = NCURSES_ClearScreen; | 
 |    driver.allocColor = NCURSES_AllocColor; | 
 | #ifdef HAVE_GETBKGD | 
 |    driver.setBackgroundColor = NCURSES_SetBackgroundColor; | 
 | #endif    | 
 | #ifdef HAVE_RESIZETERM | 
 |    driver.notifyResizeScreen = NCURSES_NotifyResizeScreen; | 
 | #endif /* HAVE_RESIZETERM */ | 
 |  | 
 |    driver.checkForKeystroke = NCURSES_CheckForKeystroke; | 
 |    driver.getKeystroke = NCURSES_GetKeystroke; | 
 |  | 
 |    driver.refresh = NCURSES_Refresh;  | 
 | } | 
 |  | 
 | void NCURSES_Init() | 
 | { | 
 |    char terminal_type[80]; | 
 |  | 
 |    PROFILE_GetWineIniString("console", "TerminalType", | 
 |       "xterm", terminal_type, 79); | 
 |  | 
 |    ncurses_screen = newterm(terminal_type, driver.console_out, | 
 |       driver.console_in); | 
 |    set_term(ncurses_screen); | 
 |    start_color(); | 
 |    raw(); | 
 |    noecho(); | 
 |    nonl(); | 
 |    intrflush(stdscr, FALSE); | 
 |    keypad(stdscr, TRUE); | 
 |    nodelay(stdscr, TRUE); | 
 | } | 
 |  | 
 | void NCURSES_Write(char output, int fg, int bg, int attribute) | 
 | { | 
 |    char row, col; | 
 |    int pair; | 
 |     | 
 |    if (!fg) | 
 |       fg = COLOR_WHITE; /* Default */ | 
 |  | 
 |    if (!bg) | 
 |       bg = COLOR_BLACK; /* Default */ | 
 |  | 
 |    pair = get_color_pair(fg, bg); | 
 |  | 
 |    if (waddch(stdscr, output | COLOR_PAIR(pair)) == ERR) | 
 |    { | 
 |       NCURSES_GetCursorPosition(&row, &col); | 
 |       FIXME("NCURSES: waddch() failed at %d, %d.\n", row, col); | 
 |    } | 
 | } | 
 |  | 
 | void NCURSES_Close() | 
 | { | 
 |    endwin(); | 
 | } | 
 |  | 
 | void NCURSES_GetKeystroke(char *scan, char *ascii) | 
 | { | 
 |    while (!NCURSES_CheckForKeystroke(scan, ascii)) | 
 |    {} /* Wait until keystroke is detected */ | 
 |     | 
 |    /* When it is detected, we will already have the right value  | 
 |       in scan and ascii, but we need to take this keystroke | 
 |       out of the buffer. */ | 
 |    wgetch(stdscr); | 
 | } | 
 |  | 
 | int NCURSES_CheckForKeystroke(char *scan, char *ascii) | 
 | { | 
 |    /* We don't currently support scan codes here */ | 
 |    /* FIXME */ | 
 |    int temp; | 
 |    temp = wgetch(stdscr); | 
 |    if (temp == ERR) | 
 |    { | 
 |       return FALSE; | 
 |    } | 
 |    else | 
 |    { | 
 |       ungetch(temp);  /* Keystroke not removed from buffer */ | 
 |       *ascii = (char) temp; | 
 |       return TRUE; | 
 |    } | 
 | } | 
 |  | 
 | void NCURSES_MoveCursor(char row, char col) | 
 | { | 
 |    if (wmove(stdscr, row, col) == ERR) | 
 |       FIXME("NCURSES: wmove() failed to %d, %d.\n", row, col); | 
 | } | 
 |  | 
 | void NCURSES_GetCursorPosition(char *row, char *col) | 
 | { | 
 |    int trow, tcol; | 
 |  | 
 |    getyx(stdscr, trow, tcol); /* MACRO, no need to pass pointer */ | 
 |  | 
 |    *row = (char) trow; | 
 |    *col = (char) tcol; | 
 | } | 
 |  | 
 | void NCURSES_GetCharacterAtCursor(char *ch, int *fg_color, int | 
 |    *bg_color, int *attribute) | 
 | { | 
 |    /* If any of the pointers are NULL, ignore them */ | 
 |    /* We will eventually have to convert the color data */ | 
 |    if (ch) | 
 |       *ch = (char) winch(stdscr); | 
 |    if (fg_color) | 
 |       *fg_color = WINE_WHITE; | 
 |    if (bg_color) | 
 |       *bg_color = WINE_BLACK; | 
 |    if (attribute) | 
 |       *attribute = 0; | 
 | } | 
 |  | 
 | void NCURSES_Refresh() | 
 | { | 
 |    wrefresh(stdscr); | 
 | } | 
 |  | 
 | void NCURSES_ClearScreen() | 
 | { | 
 |    werase(stdscr); | 
 | } | 
 |  | 
 | int NCURSES_AllocColor(int color) | 
 | { | 
 |    /* Currently support only internal colors */ | 
 |    switch (color) | 
 |    { | 
 |       case WINE_BLACK:		return COLOR_BLACK; | 
 |       case WINE_WHITE:		return COLOR_WHITE; | 
 |       case WINE_RED:		return COLOR_RED; | 
 |       case WINE_GREEN:		return COLOR_GREEN; | 
 |       case WINE_YELLOW:		return COLOR_YELLOW; | 
 |       case WINE_BLUE:     	return COLOR_BLUE; | 
 |       case WINE_MAGENTA:	return COLOR_MAGENTA; | 
 |       case WINE_CYAN:		return COLOR_CYAN; | 
 |    } | 
 |  | 
 |    FIXME("Unable to allocate color %d (%s)\n", color, | 
 |       color_names[color]); | 
 |  | 
 |    /* Don't allocate a color... yet */ | 
 |    return 0; | 
 | } | 
 |  | 
 | void NCURSES_SetBackgroundColor(int fg, int bg) | 
 | { | 
 |    int pair; | 
 |  | 
 |    pair = get_color_pair(fg, bg); | 
 |  | 
 |    wbkgd(stdscr, COLOR_PAIR(pair)); | 
 | } | 
 |  | 
 | #ifdef HAVE_GETBKGD | 
 | void NCURSES_GetBackgroundColor(int *fg, int *bg) | 
 | { | 
 |    chtype background; | 
 |    short pair, sfg, sbg; | 
 |       | 
 |    background = getbkgd(stdscr); | 
 |  | 
 |    pair = (!A_CHARTEXT & background); | 
 |     | 
 |    pair_content(pair, &sfg, &sbg); | 
 |  | 
 |    *fg = sfg; | 
 |    *bg = sbg; | 
 | } | 
 | #endif /* HAVE_GETBKGD */ | 
 |  | 
 | #ifdef HAVE_RESIZETERM | 
 |  | 
 | void NCURSES_NotifyResizeScreen(int x, int y) | 
 | { | 
 |    /* Note: This function gets called *after* another driver in the chain | 
 |       calls ResizeScreen(). It is meant to resize the ncurses internal | 
 |       data structures to know about the new window dimensions. */ | 
 |   | 
 |    TRACE("Terminal resized to y: %d, x: %d\n", y, x); | 
 |  | 
 |    resizeterm(y, x); | 
 | } | 
 |  | 
 | #endif /* HAVE_RESIZETERM */ | 
 |  | 
 | static int get_color_pair(int fg_color, int bg_color) | 
 | { | 
 |    /* ncurses internally uses "color pairs" in addition to the "pallet" */ | 
 |    /* This isn't the best way to do this. Or even close */ | 
 |  | 
 |    static int current = 0; | 
 |    static int fg[255];     /* 16 x 16 is enough */ | 
 |    static int bg[255]; | 
 |    int x; | 
 |  | 
 |    /* The first pair is hardwired into ncurses */ | 
 |    fg[0] = COLOR_WHITE; | 
 |    bg[0] = COLOR_BLACK; | 
 |  | 
 |    for (x = 0; x <= current; x++) | 
 |    { | 
 |       if ((fg_color == fg[x]) && (bg_color == bg[x])) | 
 |       { | 
 |          TRACE("Color pair: already allocated\n"); | 
 |          return x;   | 
 |       }     | 
 |    } | 
 |  | 
 |    /* Need to allocate new color */ | 
 |    current++; | 
 |    fg[current] = fg_color; | 
 |    bg[current] = bg_color; | 
 |    TRACE("Color pair: allocated.\n"); | 
 |    return init_pair(current, fg_color, bg_color); | 
 | } | 
 |  | 
 | #endif /* WINE_NCURSES */ |