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