Joseph Pranevich | 791cd6a | 1998-12-02 19:58:08 +0000 | [diff] [blame] | 1 | /* ncurses.c */ |
Joseph Pranevich | ebc0e5e | 1999-02-14 11:15:47 +0000 | [diff] [blame] | 2 | /* Copyright 1999 - Joseph Pranevich */ |
Joseph Pranevich | 791cd6a | 1998-12-02 19:58:08 +0000 | [diff] [blame] | 3 | |
Marcus Meissner | 317af32 | 1999-02-17 13:51:06 +0000 | [diff] [blame] | 4 | #include <stdio.h> |
Joseph Pranevich | 791cd6a | 1998-12-02 19:58:08 +0000 | [diff] [blame] | 5 | #include "config.h" |
Joseph Pranevich | f0e0df3 | 1999-02-20 16:43:40 +0000 | [diff] [blame] | 6 | #include "console.h" /* Must define WINE_NCURSES */ |
Joseph Pranevich | 791cd6a | 1998-12-02 19:58:08 +0000 | [diff] [blame] | 7 | |
| 8 | #ifdef WINE_NCURSES |
| 9 | |
| 10 | /* This is the console driver for systems that support the ncurses |
| 11 | interface. |
| 12 | */ |
| 13 | |
| 14 | /* Actually, this should work for curses, as well. But there may be |
| 15 | individual functions that are unsupported in plain curses or other |
| 16 | variants. Those should be detected and special-cased by autoconf. |
| 17 | */ |
| 18 | |
| 19 | /* When creating new drivers, you need to assign all the functions that |
| 20 | that driver supports into the driver struct. If it is a supplementary |
| 21 | driver, it should make sure to perserve the old values. |
| 22 | */ |
| 23 | |
Alexandre Julliard | 9fe7a25 | 1999-05-14 08:17:14 +0000 | [diff] [blame] | 24 | #include "debugtools.h" |
Joseph Pranevich | f0e0df3 | 1999-02-20 16:43:40 +0000 | [diff] [blame] | 25 | #include "options.h" |
| 26 | |
Dimitrie O. Paun | 529da54 | 2000-11-27 23:54:25 +0000 | [diff] [blame] | 27 | DEFAULT_DEBUG_CHANNEL(console); |
Patrik Stridvall | b4b9fae | 1999-04-19 14:56:29 +0000 | [diff] [blame] | 28 | |
Joseph Pranevich | 791cd6a | 1998-12-02 19:58:08 +0000 | [diff] [blame] | 29 | #undef ERR /* Use ncurses's err() */ |
Marcus Meissner | f0a3545 | 1999-01-28 09:09:03 +0000 | [diff] [blame] | 30 | #ifdef HAVE_NCURSES_H |
| 31 | # include <ncurses.h> |
Marcus Meissner | 592ba10 | 1999-01-20 14:18:55 +0000 | [diff] [blame] | 32 | #else |
Marcus Meissner | f0a3545 | 1999-01-28 09:09:03 +0000 | [diff] [blame] | 33 | # ifdef HAVE_CURSES_H |
| 34 | # include <curses.h> |
Marcus Meissner | 592ba10 | 1999-01-20 14:18:55 +0000 | [diff] [blame] | 35 | # endif |
| 36 | #endif |
Joseph Pranevich | 791cd6a | 1998-12-02 19:58:08 +0000 | [diff] [blame] | 37 | |
Joseph Pranevich | 5576838 | 1998-12-09 15:43:03 +0000 | [diff] [blame] | 38 | SCREEN *ncurses_screen; |
| 39 | |
Joseph Pranevich | 9c77b47 | 1999-01-30 12:51:09 +0000 | [diff] [blame] | 40 | static int get_color_pair(int fg_color, int bg_color); |
| 41 | |
Joseph Pranevich | f0e0df3 | 1999-02-20 16:43:40 +0000 | [diff] [blame] | 42 | const char *color_names[] = {"null", "black", "blue", "green", |
| 43 | "cyan", "magenta", "brown", "red", "light gray", "dark gray", |
| 44 | "light blue", "light green", "light red", "light magenta", |
| 45 | "light cyan", "yellow", "white"}; |
| 46 | |
Joseph Pranevich | 791cd6a | 1998-12-02 19:58:08 +0000 | [diff] [blame] | 47 | void NCURSES_Start() |
| 48 | { |
| 49 | /* This should be the root driver so we can ignore anything |
| 50 | already in the struct. */ |
| 51 | |
| 52 | driver.norefresh = FALSE; |
| 53 | |
| 54 | driver.init = NCURSES_Init; |
| 55 | driver.write = NCURSES_Write; |
| 56 | driver.close = NCURSES_Close; |
| 57 | driver.moveCursor = NCURSES_MoveCursor; |
| 58 | driver.getCursorPosition = NCURSES_GetCursorPosition; |
| 59 | driver.getCharacterAtCursor = NCURSES_GetCharacterAtCursor; |
| 60 | driver.clearScreen = NCURSES_ClearScreen; |
Joseph Pranevich | 9c77b47 | 1999-01-30 12:51:09 +0000 | [diff] [blame] | 61 | driver.allocColor = NCURSES_AllocColor; |
Michael Veksler | f544507 | 1999-02-25 17:11:05 +0000 | [diff] [blame] | 62 | #ifdef HAVE_GETBKGD |
Joseph Pranevich | 9c77b47 | 1999-01-30 12:51:09 +0000 | [diff] [blame] | 63 | driver.setBackgroundColor = NCURSES_SetBackgroundColor; |
Michael Veksler | f544507 | 1999-02-25 17:11:05 +0000 | [diff] [blame] | 64 | #endif |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 65 | #ifdef HAVE_RESIZETERM |
Joseph Pranevich | e884f9c | 1999-01-03 16:14:34 +0000 | [diff] [blame] | 66 | driver.notifyResizeScreen = NCURSES_NotifyResizeScreen; |
Joseph Pranevich | f0e0df3 | 1999-02-20 16:43:40 +0000 | [diff] [blame] | 67 | #endif /* HAVE_RESIZETERM */ |
Joseph Pranevich | 791cd6a | 1998-12-02 19:58:08 +0000 | [diff] [blame] | 68 | |
| 69 | driver.checkForKeystroke = NCURSES_CheckForKeystroke; |
| 70 | driver.getKeystroke = NCURSES_GetKeystroke; |
| 71 | |
| 72 | driver.refresh = NCURSES_Refresh; |
| 73 | } |
| 74 | |
| 75 | void NCURSES_Init() |
| 76 | { |
Joseph Pranevich | f0e0df3 | 1999-02-20 16:43:40 +0000 | [diff] [blame] | 77 | char terminal_type[80]; |
| 78 | |
| 79 | PROFILE_GetWineIniString("console", "TerminalType", |
| 80 | "xterm", terminal_type, 79); |
| 81 | |
| 82 | ncurses_screen = newterm(terminal_type, driver.console_out, |
Joseph Pranevich | 5576838 | 1998-12-09 15:43:03 +0000 | [diff] [blame] | 83 | driver.console_in); |
| 84 | set_term(ncurses_screen); |
Joseph Pranevich | 9c77b47 | 1999-01-30 12:51:09 +0000 | [diff] [blame] | 85 | start_color(); |
| 86 | raw(); |
Joseph Pranevich | 791cd6a | 1998-12-02 19:58:08 +0000 | [diff] [blame] | 87 | noecho(); |
| 88 | nonl(); |
Joseph Pranevich | f0e0df3 | 1999-02-20 16:43:40 +0000 | [diff] [blame] | 89 | intrflush(stdscr, FALSE); |
Joseph Pranevich | 791cd6a | 1998-12-02 19:58:08 +0000 | [diff] [blame] | 90 | keypad(stdscr, TRUE); |
| 91 | nodelay(stdscr, TRUE); |
| 92 | } |
| 93 | |
| 94 | void NCURSES_Write(char output, int fg, int bg, int attribute) |
| 95 | { |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 96 | char row, col; |
Joseph Pranevich | 9c77b47 | 1999-01-30 12:51:09 +0000 | [diff] [blame] | 97 | int pair; |
| 98 | |
| 99 | if (!fg) |
| 100 | fg = COLOR_WHITE; /* Default */ |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 101 | |
Joseph Pranevich | 9c77b47 | 1999-01-30 12:51:09 +0000 | [diff] [blame] | 102 | if (!bg) |
| 103 | bg = COLOR_BLACK; /* Default */ |
| 104 | |
| 105 | pair = get_color_pair(fg, bg); |
| 106 | |
| 107 | if (waddch(stdscr, output | COLOR_PAIR(pair)) == ERR) |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 108 | { |
| 109 | NCURSES_GetCursorPosition(&row, &col); |
Alexandre Julliard | 9fe7a25 | 1999-05-14 08:17:14 +0000 | [diff] [blame] | 110 | FIXME("NCURSES: waddch() failed at %d, %d.\n", row, col); |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 111 | } |
Joseph Pranevich | 791cd6a | 1998-12-02 19:58:08 +0000 | [diff] [blame] | 112 | } |
| 113 | |
| 114 | void NCURSES_Close() |
| 115 | { |
| 116 | endwin(); |
| 117 | } |
| 118 | |
| 119 | void NCURSES_GetKeystroke(char *scan, char *ascii) |
| 120 | { |
| 121 | while (!NCURSES_CheckForKeystroke(scan, ascii)) |
| 122 | {} /* Wait until keystroke is detected */ |
| 123 | |
| 124 | /* When it is detected, we will already have the right value |
| 125 | in scan and ascii, but we need to take this keystroke |
| 126 | out of the buffer. */ |
Joseph Pranevich | 5576838 | 1998-12-09 15:43:03 +0000 | [diff] [blame] | 127 | wgetch(stdscr); |
Joseph Pranevich | 791cd6a | 1998-12-02 19:58:08 +0000 | [diff] [blame] | 128 | } |
| 129 | |
| 130 | int NCURSES_CheckForKeystroke(char *scan, char *ascii) |
| 131 | { |
| 132 | /* We don't currently support scan codes here */ |
| 133 | /* FIXME */ |
| 134 | int temp; |
Joseph Pranevich | 5576838 | 1998-12-09 15:43:03 +0000 | [diff] [blame] | 135 | temp = wgetch(stdscr); |
Joseph Pranevich | 791cd6a | 1998-12-02 19:58:08 +0000 | [diff] [blame] | 136 | if (temp == ERR) |
| 137 | { |
| 138 | return FALSE; |
| 139 | } |
| 140 | else |
| 141 | { |
| 142 | ungetch(temp); /* Keystroke not removed from buffer */ |
| 143 | *ascii = (char) temp; |
| 144 | return TRUE; |
| 145 | } |
| 146 | } |
| 147 | |
| 148 | void NCURSES_MoveCursor(char row, char col) |
| 149 | { |
Joseph Pranevich | e884f9c | 1999-01-03 16:14:34 +0000 | [diff] [blame] | 150 | if (wmove(stdscr, row, col) == ERR) |
Alexandre Julliard | 9fe7a25 | 1999-05-14 08:17:14 +0000 | [diff] [blame] | 151 | FIXME("NCURSES: wmove() failed to %d, %d.\n", row, col); |
Joseph Pranevich | 791cd6a | 1998-12-02 19:58:08 +0000 | [diff] [blame] | 152 | } |
| 153 | |
| 154 | void NCURSES_GetCursorPosition(char *row, char *col) |
| 155 | { |
| 156 | int trow, tcol; |
| 157 | |
| 158 | getyx(stdscr, trow, tcol); /* MACRO, no need to pass pointer */ |
| 159 | |
| 160 | *row = (char) trow; |
| 161 | *col = (char) tcol; |
| 162 | } |
| 163 | |
| 164 | void NCURSES_GetCharacterAtCursor(char *ch, int *fg_color, int |
| 165 | *bg_color, int *attribute) |
| 166 | { |
Joseph Pranevich | ebc0e5e | 1999-02-14 11:15:47 +0000 | [diff] [blame] | 167 | /* If any of the pointers are NULL, ignore them */ |
Joseph Pranevich | 791cd6a | 1998-12-02 19:58:08 +0000 | [diff] [blame] | 168 | /* We will eventually have to convert the color data */ |
Joseph Pranevich | ebc0e5e | 1999-02-14 11:15:47 +0000 | [diff] [blame] | 169 | if (ch) |
| 170 | *ch = (char) winch(stdscr); |
| 171 | if (fg_color) |
| 172 | *fg_color = WINE_WHITE; |
| 173 | if (bg_color) |
| 174 | *bg_color = WINE_BLACK; |
| 175 | if (attribute) |
| 176 | *attribute = 0; |
Eric Pouech | d57f7d1 | 2000-04-09 18:40:32 +0000 | [diff] [blame] | 177 | } |
Joseph Pranevich | 791cd6a | 1998-12-02 19:58:08 +0000 | [diff] [blame] | 178 | |
| 179 | void NCURSES_Refresh() |
| 180 | { |
Joseph Pranevich | 5576838 | 1998-12-09 15:43:03 +0000 | [diff] [blame] | 181 | wrefresh(stdscr); |
Joseph Pranevich | 791cd6a | 1998-12-02 19:58:08 +0000 | [diff] [blame] | 182 | } |
| 183 | |
| 184 | void NCURSES_ClearScreen() |
| 185 | { |
Joseph Pranevich | 5576838 | 1998-12-09 15:43:03 +0000 | [diff] [blame] | 186 | werase(stdscr); |
Joseph Pranevich | 791cd6a | 1998-12-02 19:58:08 +0000 | [diff] [blame] | 187 | } |
| 188 | |
Joseph Pranevich | 9c77b47 | 1999-01-30 12:51:09 +0000 | [diff] [blame] | 189 | int NCURSES_AllocColor(int color) |
| 190 | { |
| 191 | /* Currently support only internal colors */ |
| 192 | switch (color) |
| 193 | { |
| 194 | case WINE_BLACK: return COLOR_BLACK; |
| 195 | case WINE_WHITE: return COLOR_WHITE; |
| 196 | case WINE_RED: return COLOR_RED; |
| 197 | case WINE_GREEN: return COLOR_GREEN; |
| 198 | case WINE_YELLOW: return COLOR_YELLOW; |
| 199 | case WINE_BLUE: return COLOR_BLUE; |
| 200 | case WINE_MAGENTA: return COLOR_MAGENTA; |
| 201 | case WINE_CYAN: return COLOR_CYAN; |
| 202 | } |
| 203 | |
Alexandre Julliard | 9fe7a25 | 1999-05-14 08:17:14 +0000 | [diff] [blame] | 204 | FIXME("Unable to allocate color %d (%s)\n", color, |
Joseph Pranevich | f0e0df3 | 1999-02-20 16:43:40 +0000 | [diff] [blame] | 205 | color_names[color]); |
Joseph Pranevich | 9c77b47 | 1999-01-30 12:51:09 +0000 | [diff] [blame] | 206 | |
| 207 | /* Don't allocate a color... yet */ |
| 208 | return 0; |
| 209 | } |
| 210 | |
| 211 | void NCURSES_SetBackgroundColor(int fg, int bg) |
| 212 | { |
| 213 | int pair; |
| 214 | |
| 215 | pair = get_color_pair(fg, bg); |
| 216 | |
Joseph Pranevich | 93a2ce6 | 1999-02-24 11:08:29 +0000 | [diff] [blame] | 217 | wbkgd(stdscr, COLOR_PAIR(pair)); |
| 218 | } |
| 219 | |
Michael Veksler | f544507 | 1999-02-25 17:11:05 +0000 | [diff] [blame] | 220 | #ifdef HAVE_GETBKGD |
Joseph Pranevich | 93a2ce6 | 1999-02-24 11:08:29 +0000 | [diff] [blame] | 221 | void NCURSES_GetBackgroundColor(int *fg, int *bg) |
| 222 | { |
| 223 | chtype background; |
| 224 | short pair, sfg, sbg; |
| 225 | |
| 226 | background = getbkgd(stdscr); |
| 227 | |
| 228 | pair = (!A_CHARTEXT & background); |
| 229 | |
| 230 | pair_content(pair, &sfg, &sbg); |
| 231 | |
| 232 | *fg = sfg; |
| 233 | *bg = sbg; |
Joseph Pranevich | 9c77b47 | 1999-01-30 12:51:09 +0000 | [diff] [blame] | 234 | } |
Michael Veksler | f544507 | 1999-02-25 17:11:05 +0000 | [diff] [blame] | 235 | #endif /* HAVE_GETBKGD */ |
Joseph Pranevich | 9c77b47 | 1999-01-30 12:51:09 +0000 | [diff] [blame] | 236 | |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 237 | #ifdef HAVE_RESIZETERM |
| 238 | |
Joseph Pranevich | e884f9c | 1999-01-03 16:14:34 +0000 | [diff] [blame] | 239 | void NCURSES_NotifyResizeScreen(int x, int y) |
| 240 | { |
| 241 | /* Note: This function gets called *after* another driver in the chain |
| 242 | calls ResizeScreen(). It is meant to resize the ncurses internal |
| 243 | data structures to know about the new window dimensions. */ |
| 244 | |
Alexandre Julliard | 9fe7a25 | 1999-05-14 08:17:14 +0000 | [diff] [blame] | 245 | TRACE("Terminal resized to y: %d, x: %d\n", y, x); |
Joseph Pranevich | f0e0df3 | 1999-02-20 16:43:40 +0000 | [diff] [blame] | 246 | |
Joseph Pranevich | e884f9c | 1999-01-03 16:14:34 +0000 | [diff] [blame] | 247 | resizeterm(y, x); |
| 248 | } |
| 249 | |
Joseph Pranevich | 9c77b47 | 1999-01-30 12:51:09 +0000 | [diff] [blame] | 250 | #endif /* HAVE_RESIZETERM */ |
| 251 | |
| 252 | static int get_color_pair(int fg_color, int bg_color) |
| 253 | { |
| 254 | /* ncurses internally uses "color pairs" in addition to the "pallet" */ |
| 255 | /* This isn't the best way to do this. Or even close */ |
| 256 | |
| 257 | static int current = 0; |
| 258 | static int fg[255]; /* 16 x 16 is enough */ |
| 259 | static int bg[255]; |
| 260 | int x; |
| 261 | |
| 262 | /* The first pair is hardwired into ncurses */ |
| 263 | fg[0] = COLOR_WHITE; |
| 264 | bg[0] = COLOR_BLACK; |
| 265 | |
| 266 | for (x = 0; x <= current; x++) |
| 267 | { |
| 268 | if ((fg_color == fg[x]) && (bg_color == bg[x])) |
| 269 | { |
Alexandre Julliard | 9fe7a25 | 1999-05-14 08:17:14 +0000 | [diff] [blame] | 270 | TRACE("Color pair: already allocated\n"); |
Joseph Pranevich | 9c77b47 | 1999-01-30 12:51:09 +0000 | [diff] [blame] | 271 | return x; |
| 272 | } |
| 273 | } |
| 274 | |
| 275 | /* Need to allocate new color */ |
| 276 | current++; |
| 277 | fg[current] = fg_color; |
| 278 | bg[current] = bg_color; |
Alexandre Julliard | 9fe7a25 | 1999-05-14 08:17:14 +0000 | [diff] [blame] | 279 | TRACE("Color pair: allocated.\n"); |
Joseph Pranevich | 9c77b47 | 1999-01-30 12:51:09 +0000 | [diff] [blame] | 280 | return init_pair(current, fg_color, bg_color); |
| 281 | } |
Alexandre Julliard | 638f169 | 1999-01-17 16:32:32 +0000 | [diff] [blame] | 282 | |
Joseph Pranevich | 791cd6a | 1998-12-02 19:58:08 +0000 | [diff] [blame] | 283 | #endif /* WINE_NCURSES */ |