- New implementation of SendMessage, ReceiveMessage, ReplyMessage functions
[wine] / console / ncurses.c
1 /* ncurses.c */
2 /* Copyright 1999 - Joseph Pranevich */
3
4 #include <stdio.h>
5 #include "config.h"
6 #include "console.h"
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
24 #include "debug.h"
25 #undef ERR /* Use ncurses's err() */
26 #ifdef HAVE_NCURSES_H
27 # include <ncurses.h>
28 #else
29 # ifdef HAVE_CURSES_H
30 #  include <curses.h>
31 # endif
32 #endif
33
34 SCREEN *ncurses_screen;
35
36 static int get_color_pair(int fg_color, int bg_color);
37
38 void NCURSES_Start()
39 {
40    /* This should be the root driver so we can ignore anything
41       already in the struct. */
42
43    driver.norefresh = FALSE;
44
45    driver.init = NCURSES_Init;
46    driver.write = NCURSES_Write;
47    driver.close = NCURSES_Close;
48    driver.moveCursor = NCURSES_MoveCursor;
49    driver.getCursorPosition = NCURSES_GetCursorPosition;
50    driver.getCharacterAtCursor = NCURSES_GetCharacterAtCursor;
51    driver.clearScreen = NCURSES_ClearScreen;
52    driver.allocColor = NCURSES_AllocColor;
53    driver.setBackgroundColor = NCURSES_SetBackgroundColor;
54 #ifdef HAVE_RESIZETERM
55    driver.notifyResizeScreen = NCURSES_NotifyResizeScreen;
56 #endif
57
58    driver.checkForKeystroke = NCURSES_CheckForKeystroke;
59    driver.getKeystroke = NCURSES_GetKeystroke;
60
61    driver.refresh = NCURSES_Refresh; 
62 }
63
64 void NCURSES_Init()
65 {
66    ncurses_screen = newterm("xterm", driver.console_out,
67       driver.console_in);
68    set_term(ncurses_screen);
69    start_color();
70    raw();
71    noecho();
72    nonl();
73 /*   intrflush(stdscr, FALSE); */ 
74    keypad(stdscr, TRUE);
75    nodelay(stdscr, TRUE);
76 }
77
78 void NCURSES_Write(char output, int fg, int bg, int attribute)
79 {
80    char row, col;
81    int pair;
82    
83    if (!fg)
84       fg = COLOR_WHITE; /* Default */
85
86    if (!bg)
87       bg = COLOR_BLACK; /* Default */
88
89    pair = get_color_pair(fg, bg);
90
91    if (waddch(stdscr, output | COLOR_PAIR(pair)) == ERR)
92    {
93       NCURSES_GetCursorPosition(&row, &col);
94       FIXME(console, "NCURSES: waddch() failed at %d, %d.\n", row, col);
95    }
96 }
97
98 void NCURSES_Close()
99 {
100    endwin();
101 }
102
103 void NCURSES_GetKeystroke(char *scan, char *ascii)
104 {
105    while (!NCURSES_CheckForKeystroke(scan, ascii))
106    {} /* Wait until keystroke is detected */
107    
108    /* When it is detected, we will already have the right value 
109       in scan and ascii, but we need to take this keystroke
110       out of the buffer. */
111    wgetch(stdscr);
112 }
113
114 int NCURSES_CheckForKeystroke(char *scan, char *ascii)
115 {
116    /* We don't currently support scan codes here */
117    /* FIXME */
118    int temp;
119    temp = wgetch(stdscr);
120    if (temp == ERR)
121    {
122       return FALSE;
123    }
124    else
125    {
126       ungetch(temp);  /* Keystroke not removed from buffer */
127       *ascii = (char) temp;
128       return TRUE;
129    }
130 }
131
132 void NCURSES_MoveCursor(char row, char col)
133 {
134    if (wmove(stdscr, row, col) == ERR)
135       FIXME(console, "NCURSES: wmove() failed to %d, %d.\n", row, col);
136 }
137
138 void NCURSES_GetCursorPosition(char *row, char *col)
139 {
140    int trow, tcol;
141
142    getyx(stdscr, trow, tcol); /* MACRO, no need to pass pointer */
143
144    *row = (char) trow;
145    *col = (char) tcol;
146 }
147
148 void NCURSES_GetCharacterAtCursor(char *ch, int *fg_color, int
149    *bg_color, int *attribute)
150 {
151    /* If any of the pointers are NULL, ignore them */
152    /* We will eventually have to convert the color data */
153    if (ch)
154       *ch = (char) winch(stdscr);
155    if (fg_color)
156       *fg_color = WINE_WHITE;
157    if (bg_color)
158       *bg_color = WINE_BLACK;
159    if (attribute)
160       *attribute = 0;
161 };
162
163 void NCURSES_Refresh()
164 {
165    wrefresh(stdscr);
166 }
167
168 void NCURSES_ClearScreen()
169 {
170    werase(stdscr);
171 }
172
173 int NCURSES_AllocColor(int color)
174 {
175    /* Currently support only internal colors */
176    switch (color)
177    {
178       case WINE_BLACK:          return COLOR_BLACK;
179       case WINE_WHITE:          return COLOR_WHITE;
180       case WINE_RED:            return COLOR_RED;
181       case WINE_GREEN:          return COLOR_GREEN;
182       case WINE_YELLOW:         return COLOR_YELLOW;
183       case WINE_BLUE:           return COLOR_BLUE;
184       case WINE_MAGENTA:        return COLOR_MAGENTA;
185       case WINE_CYAN:           return COLOR_CYAN;
186    }
187
188    FIXME(console, "Unable to allocate color %d\n", color);
189
190    /* Don't allocate a color... yet */
191    return 0;
192 }
193
194 void NCURSES_SetBackgroundColor(int fg, int bg)
195 {
196    int pair;
197
198    pair = get_color_pair(fg, bg);
199
200    bkgdset(COLOR_PAIR(pair));
201 }
202
203 #ifdef HAVE_RESIZETERM
204
205 void NCURSES_NotifyResizeScreen(int x, int y)
206 {
207    /* Note: This function gets called *after* another driver in the chain
208       calls ResizeScreen(). It is meant to resize the ncurses internal
209       data structures to know about the new window dimensions. */
210  
211    resizeterm(y, x);
212 }
213
214 #endif /* HAVE_RESIZETERM */
215
216 static int get_color_pair(int fg_color, int bg_color)
217 {
218    /* ncurses internally uses "color pairs" in addition to the "pallet" */
219    /* This isn't the best way to do this. Or even close */
220
221    static int current = 0;
222    static int fg[255];     /* 16 x 16 is enough */
223    static int bg[255];
224    int x;
225
226    /* The first pair is hardwired into ncurses */
227    fg[0] = COLOR_WHITE;
228    bg[0] = COLOR_BLACK;
229
230    for (x = 0; x <= current; x++)
231    {
232       if ((fg_color == fg[x]) && (bg_color == bg[x]))
233       {
234          TRACE(console, "Color pair: already allocated\n");
235          return x;  
236       }    
237    }
238
239    /* Need to allocate new color */
240    current++;
241    fg[current] = fg_color;
242    bg[current] = bg_color;
243    TRACE(console, "Color pair: allocated.\n");
244    return init_pair(current, fg_color, bg_color);
245 }
246
247 #endif /* WINE_NCURSES */