blob: 5d1edc9a2b7da892bf68d8c0bfd31d607bfa6a75 [file] [log] [blame]
Joseph Pranevich791cd6a1998-12-02 19:58:08 +00001/* ncurses.c */
Joseph Pranevichebc0e5e1999-02-14 11:15:47 +00002/* Copyright 1999 - Joseph Pranevich */
Joseph Pranevich791cd6a1998-12-02 19:58:08 +00003
Marcus Meissner317af321999-02-17 13:51:06 +00004#include <stdio.h>
Joseph Pranevich791cd6a1998-12-02 19:58:08 +00005#include "config.h"
Joseph Pranevichf0e0df31999-02-20 16:43:40 +00006#include "console.h" /* Must define WINE_NCURSES */
Joseph Pranevich791cd6a1998-12-02 19:58:08 +00007
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 Julliard9fe7a251999-05-14 08:17:14 +000024#include "debugtools.h"
Joseph Pranevichf0e0df31999-02-20 16:43:40 +000025#include "options.h"
26
Dimitrie O. Paun529da542000-11-27 23:54:25 +000027DEFAULT_DEBUG_CHANNEL(console);
Patrik Stridvallb4b9fae1999-04-19 14:56:29 +000028
Joseph Pranevich791cd6a1998-12-02 19:58:08 +000029#undef ERR /* Use ncurses's err() */
Marcus Meissnerf0a35451999-01-28 09:09:03 +000030#ifdef HAVE_NCURSES_H
31# include <ncurses.h>
Marcus Meissner592ba101999-01-20 14:18:55 +000032#else
Marcus Meissnerf0a35451999-01-28 09:09:03 +000033# ifdef HAVE_CURSES_H
34# include <curses.h>
Marcus Meissner592ba101999-01-20 14:18:55 +000035# endif
36#endif
Joseph Pranevich791cd6a1998-12-02 19:58:08 +000037
Joseph Pranevich55768381998-12-09 15:43:03 +000038SCREEN *ncurses_screen;
39
Joseph Pranevich9c77b471999-01-30 12:51:09 +000040static int get_color_pair(int fg_color, int bg_color);
41
Joseph Pranevichf0e0df31999-02-20 16:43:40 +000042const 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 Pranevich791cd6a1998-12-02 19:58:08 +000047void 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 Pranevich9c77b471999-01-30 12:51:09 +000061 driver.allocColor = NCURSES_AllocColor;
Michael Vekslerf5445071999-02-25 17:11:05 +000062#ifdef HAVE_GETBKGD
Joseph Pranevich9c77b471999-01-30 12:51:09 +000063 driver.setBackgroundColor = NCURSES_SetBackgroundColor;
Michael Vekslerf5445071999-02-25 17:11:05 +000064#endif
Alexandre Julliard638f1691999-01-17 16:32:32 +000065#ifdef HAVE_RESIZETERM
Joseph Praneviche884f9c1999-01-03 16:14:34 +000066 driver.notifyResizeScreen = NCURSES_NotifyResizeScreen;
Joseph Pranevichf0e0df31999-02-20 16:43:40 +000067#endif /* HAVE_RESIZETERM */
Joseph Pranevich791cd6a1998-12-02 19:58:08 +000068
69 driver.checkForKeystroke = NCURSES_CheckForKeystroke;
70 driver.getKeystroke = NCURSES_GetKeystroke;
71
72 driver.refresh = NCURSES_Refresh;
73}
74
75void NCURSES_Init()
76{
Joseph Pranevichf0e0df31999-02-20 16:43:40 +000077 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 Pranevich55768381998-12-09 15:43:03 +000083 driver.console_in);
84 set_term(ncurses_screen);
Joseph Pranevich9c77b471999-01-30 12:51:09 +000085 start_color();
86 raw();
Joseph Pranevich791cd6a1998-12-02 19:58:08 +000087 noecho();
88 nonl();
Joseph Pranevichf0e0df31999-02-20 16:43:40 +000089 intrflush(stdscr, FALSE);
Joseph Pranevich791cd6a1998-12-02 19:58:08 +000090 keypad(stdscr, TRUE);
91 nodelay(stdscr, TRUE);
92}
93
94void NCURSES_Write(char output, int fg, int bg, int attribute)
95{
Alexandre Julliard638f1691999-01-17 16:32:32 +000096 char row, col;
Joseph Pranevich9c77b471999-01-30 12:51:09 +000097 int pair;
98
99 if (!fg)
100 fg = COLOR_WHITE; /* Default */
Alexandre Julliard638f1691999-01-17 16:32:32 +0000101
Joseph Pranevich9c77b471999-01-30 12:51:09 +0000102 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 Julliard638f1691999-01-17 16:32:32 +0000108 {
109 NCURSES_GetCursorPosition(&row, &col);
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000110 FIXME("NCURSES: waddch() failed at %d, %d.\n", row, col);
Alexandre Julliard638f1691999-01-17 16:32:32 +0000111 }
Joseph Pranevich791cd6a1998-12-02 19:58:08 +0000112}
113
114void NCURSES_Close()
115{
116 endwin();
117}
118
119void 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 Pranevich55768381998-12-09 15:43:03 +0000127 wgetch(stdscr);
Joseph Pranevich791cd6a1998-12-02 19:58:08 +0000128}
129
130int NCURSES_CheckForKeystroke(char *scan, char *ascii)
131{
132 /* We don't currently support scan codes here */
133 /* FIXME */
134 int temp;
Joseph Pranevich55768381998-12-09 15:43:03 +0000135 temp = wgetch(stdscr);
Joseph Pranevich791cd6a1998-12-02 19:58:08 +0000136 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
148void NCURSES_MoveCursor(char row, char col)
149{
Joseph Praneviche884f9c1999-01-03 16:14:34 +0000150 if (wmove(stdscr, row, col) == ERR)
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000151 FIXME("NCURSES: wmove() failed to %d, %d.\n", row, col);
Joseph Pranevich791cd6a1998-12-02 19:58:08 +0000152}
153
154void 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
164void NCURSES_GetCharacterAtCursor(char *ch, int *fg_color, int
165 *bg_color, int *attribute)
166{
Joseph Pranevichebc0e5e1999-02-14 11:15:47 +0000167 /* If any of the pointers are NULL, ignore them */
Joseph Pranevich791cd6a1998-12-02 19:58:08 +0000168 /* We will eventually have to convert the color data */
Joseph Pranevichebc0e5e1999-02-14 11:15:47 +0000169 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 Pouechd57f7d12000-04-09 18:40:32 +0000177}
Joseph Pranevich791cd6a1998-12-02 19:58:08 +0000178
179void NCURSES_Refresh()
180{
Joseph Pranevich55768381998-12-09 15:43:03 +0000181 wrefresh(stdscr);
Joseph Pranevich791cd6a1998-12-02 19:58:08 +0000182}
183
184void NCURSES_ClearScreen()
185{
Joseph Pranevich55768381998-12-09 15:43:03 +0000186 werase(stdscr);
Joseph Pranevich791cd6a1998-12-02 19:58:08 +0000187}
188
Joseph Pranevich9c77b471999-01-30 12:51:09 +0000189int 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 Julliard9fe7a251999-05-14 08:17:14 +0000204 FIXME("Unable to allocate color %d (%s)\n", color,
Joseph Pranevichf0e0df31999-02-20 16:43:40 +0000205 color_names[color]);
Joseph Pranevich9c77b471999-01-30 12:51:09 +0000206
207 /* Don't allocate a color... yet */
208 return 0;
209}
210
211void NCURSES_SetBackgroundColor(int fg, int bg)
212{
213 int pair;
214
215 pair = get_color_pair(fg, bg);
216
Joseph Pranevich93a2ce61999-02-24 11:08:29 +0000217 wbkgd(stdscr, COLOR_PAIR(pair));
218}
219
Michael Vekslerf5445071999-02-25 17:11:05 +0000220#ifdef HAVE_GETBKGD
Joseph Pranevich93a2ce61999-02-24 11:08:29 +0000221void 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 Pranevich9c77b471999-01-30 12:51:09 +0000234}
Michael Vekslerf5445071999-02-25 17:11:05 +0000235#endif /* HAVE_GETBKGD */
Joseph Pranevich9c77b471999-01-30 12:51:09 +0000236
Alexandre Julliard638f1691999-01-17 16:32:32 +0000237#ifdef HAVE_RESIZETERM
238
Joseph Praneviche884f9c1999-01-03 16:14:34 +0000239void 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 Julliard9fe7a251999-05-14 08:17:14 +0000245 TRACE("Terminal resized to y: %d, x: %d\n", y, x);
Joseph Pranevichf0e0df31999-02-20 16:43:40 +0000246
Joseph Praneviche884f9c1999-01-03 16:14:34 +0000247 resizeterm(y, x);
248}
249
Joseph Pranevich9c77b471999-01-30 12:51:09 +0000250#endif /* HAVE_RESIZETERM */
251
252static 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 Julliard9fe7a251999-05-14 08:17:14 +0000270 TRACE("Color pair: already allocated\n");
Joseph Pranevich9c77b471999-01-30 12:51:09 +0000271 return x;
272 }
273 }
274
275 /* Need to allocate new color */
276 current++;
277 fg[current] = fg_color;
278 bg[current] = bg_color;
Alexandre Julliard9fe7a251999-05-14 08:17:14 +0000279 TRACE("Color pair: allocated.\n");
Joseph Pranevich9c77b471999-01-30 12:51:09 +0000280 return init_pair(current, fg_color, bg_color);
281}
Alexandre Julliard638f1691999-01-17 16:32:32 +0000282
Joseph Pranevich791cd6a1998-12-02 19:58:08 +0000283#endif /* WINE_NCURSES */