tcursesport.c - vaccinewars - be a doctor and try to vaccinate the world
HTML git clone git://src.adamsgaard.dk/vaccinewars
DIR Log
DIR Files
DIR Refs
DIR README
DIR LICENSE
---
tcursesport.c (7418B)
---
1 /************************************************************************
2 * cursesport.c Portability functions to enable curses applications *
3 * to be built on Win32 systems *
4 * Copyright (C) 1998-2021 Ben Webb *
5 * Email: benwebb@users.sf.net *
6 * WWW: https://dopewars.sourceforge.io/ *
7 * *
8 * This program is free software; you can redistribute it and/or *
9 * modify it under the terms of the GNU General Public License *
10 * as published by the Free Software Foundation; either version 2 *
11 * of the License, or (at your option) any later version. *
12 * *
13 * This program is distributed in the hope that it will be useful, *
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
16 * GNU General Public License for more details. *
17 * *
18 * You should have received a copy of the GNU General Public License *
19 * along with this program; if not, write to the Free Software *
20 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, *
21 * MA 02111-1307, USA. *
22 ************************************************************************/
23
24 #ifdef HAVE_CONFIG_H
25 #include <config.h>
26 #endif
27
28 #include "cursesport.h"
29 #include "dopewars.h"
30 #include <glib.h>
31
32 #ifdef CYGWIN /* Code for native Win32 build under Cygwin */
33
34 int COLS, LINES;
35
36 static int Width, Depth;
37 static CHAR_INFO RealScreen[25][80], VirtualScreen[25][80];
38 static HANDLE hOut, hIn;
39 static int CurAttr = 0;
40 static int CurX, CurY;
41 static WORD Attr[10];
42
43 void refresh(void)
44 {
45 int y;
46 COORD size, offset;
47 SMALL_RECT screenpos;
48
49 move(CurY, CurX);
50 for (y = 0; y < Depth; y++) {
51 if (memcmp(&RealScreen[y][0], &VirtualScreen[y][0],
52 sizeof(CHAR_INFO) * Width) != 0) {
53 memcpy(&RealScreen[y][0], &VirtualScreen[y][0],
54 Width * sizeof(CHAR_INFO));
55 size.X = Width;
56 size.Y = 1;
57 offset.X = offset.Y = 0;
58 screenpos.Left = 0;
59 screenpos.Top = y;
60 screenpos.Right = Width - 1;
61 screenpos.Bottom = y;
62 WriteConsoleOutputW(hOut, &VirtualScreen[y][0], size,
63 offset, &screenpos);
64 }
65 }
66 }
67
68 static HANDLE WINAPI GetConHandle(TCHAR *pszName)
69 {
70 SECURITY_ATTRIBUTES sa;
71
72 sa.nLength = sizeof(sa);
73 sa.lpSecurityDescriptor = NULL;
74 sa.bInheritHandle = TRUE;
75 return CreateFile(pszName, GENERIC_READ | GENERIC_WRITE,
76 FILE_SHARE_READ | FILE_SHARE_WRITE,
77 &sa, OPEN_EXISTING, (DWORD)0, (HANDLE)0);
78 }
79
80 SCREEN *newterm(void *a, void *b, void *c)
81 {
82 int i;
83
84 Width = COLS = 80;
85 Depth = LINES = 25;
86 CurAttr = 1 << 16;
87 CurX = 0;
88 CurY = 0;
89 for (i = 0; i < 10; i++)
90 Attr[i] = FOREGROUND_RED | FOREGROUND_BLUE | FOREGROUND_GREEN;
91 hOut = GetConHandle("CONOUT$");
92 hIn = GetConHandle("CONIN$");
93 SetConsoleMode(hIn, 0);
94 SetConsoleMode(hOut, 0);
95 return NULL;
96 }
97
98 void start_color(void)
99 {
100 }
101
102 void init_pair(int index, WORD fg, WORD bg)
103 {
104 if (index >= 0 && index < 10) {
105 Attr[index] = 0;
106 switch (fg) {
107 case COLOR_MAGENTA:
108 Attr[index] |= (FOREGROUND_RED + FOREGROUND_BLUE);
109 break;
110 case COLOR_BLUE:
111 Attr[index] |= FOREGROUND_BLUE;
112 break;
113 case COLOR_RED:
114 Attr[index] |= FOREGROUND_RED;
115 break;
116 case COLOR_WHITE:
117 Attr[index] |= (FOREGROUND_RED + FOREGROUND_BLUE + FOREGROUND_GREEN);
118 break;
119 }
120 switch (bg) {
121 case COLOR_MAGENTA:
122 Attr[index] |= (BACKGROUND_RED + BACKGROUND_BLUE);
123 break;
124 case COLOR_BLUE:
125 Attr[index] |= BACKGROUND_BLUE;
126 break;
127 case COLOR_RED:
128 Attr[index] |= BACKGROUND_RED;
129 break;
130 case COLOR_WHITE:
131 Attr[index] |= (BACKGROUND_RED + BACKGROUND_BLUE + BACKGROUND_GREEN);
132 break;
133 }
134 }
135 }
136
137 void cbreak(void)
138 {
139 }
140
141 void noecho(void)
142 {
143 }
144
145 void nodelay(void *a, char b)
146 {
147 }
148
149 void keypad(void *a, char b)
150 {
151 }
152
153 void curs_set(BOOL visible)
154 {
155 CONSOLE_CURSOR_INFO ConCurInfo;
156
157 ConCurInfo.dwSize = 10;
158 ConCurInfo.bVisible = visible;
159 SetConsoleCursorInfo(hOut, &ConCurInfo);
160 }
161
162 void endwin(void)
163 {
164 CurAttr = 0;
165 refresh();
166 curs_set(1);
167 }
168
169 void move(int y, int x)
170 {
171 COORD coord;
172
173 if (x >= Width) {
174 x = 0;
175 }
176 if (y >= Depth) {
177 y = 0;
178 }
179 CurX = x;
180 CurY = y;
181 coord.X = x;
182 coord.Y = y;
183 SetConsoleCursorPosition(hOut, coord);
184 }
185
186 void attrset(int newAttr)
187 {
188 CurAttr = newAttr;
189 }
190
191 void addstr(const char *str)
192 {
193 int i;
194 for (i = 0; i < strlen(str); i++)
195 addch((guchar)str[i]);
196 }
197
198 void addch(unsigned ch_and_attr)
199 {
200 int attr;
201 unsigned int ch;
202 gunichar gch;
203 /* Keep track of a UTF-8-encoded character */
204 static char utf8_str[4];
205 static int utf8_width = 0;
206 static int utf8_pos = 0;
207
208 ch = ch_and_attr & 0xFFFF;
209
210 if (ch > 0xFF || ch <= 0x7F) {
211 /* Already Unicode (e.g. box-drawing character), or ASCII */
212 VirtualScreen[CurY][CurX].Char.UnicodeChar = ch;
213 } else if (ch & 64) {
214 /* UTF-8 encoded; first byte (get the width) */
215 utf8_width = ch & 16 ? 4 : ch & 32 ? 3 : 2;
216 utf8_pos = 0;
217 utf8_str[utf8_pos++] = ch;
218 return;
219 } else {
220 /* UTF-8 encoded; intermediate or last byte */
221 utf8_str[utf8_pos++] = ch;
222 if (utf8_pos < utf8_width) return;
223 gch = g_utf8_get_char(utf8_str);
224 /* Windows console can only handle 2-byte Unicode */
225 VirtualScreen[CurY][CurX].Char.UnicodeChar = gch > 0xFFFF ? '?' : gch;
226 }
227
228 attr = ch_and_attr >> 16;
229 if (attr > 0)
230 VirtualScreen[CurY][CurX].Attributes = Attr[attr];
231 else
232 VirtualScreen[CurY][CurX].Attributes = Attr[CurAttr >> 16];
233 if (++CurX >= Width) {
234 CurX = 0;
235 if (++CurY >= Depth)
236 CurY = 0;
237 }
238 }
239
240 void mvaddstr(int y, int x, const char *str)
241 {
242 move(y, x);
243 addstr(str);
244 }
245
246 void mvaddch(int y, int x, int ch)
247 {
248 move(y, x);
249 addch(ch);
250 }
251
252 /*
253 * Waits for the user to press a key.
254 */
255 gunichar bgetch(void)
256 {
257 DWORD NumRead;
258 WCHAR Buffer[10];
259
260 refresh();
261 ReadConsoleW(hIn, Buffer, 1, &NumRead, NULL);
262 return (int)(Buffer[0]);
263 }
264
265 void standout(void)
266 {
267 }
268
269 void standend(void)
270 {
271 }
272
273 #else /* Code for Unix build */
274
275 /*
276 * Calls the curses getch() function; if the key pressed is Ctrl-L
277 * then automatically clears and redraws the screen, otherwise just
278 * passes the key back to the calling routine.
279 */
280 gunichar bgetch()
281 {
282 int c;
283
284 c = getch();
285 while (c == '\f') {
286 wrefresh(curscr);
287 c = getch();
288 }
289 /* Ignore special keys (e.g arrow keys) so we don't confuse them with
290 * Unicode characters */
291 if (c > 255) {
292 return 0;
293 }
294 /* In UTF-8 locales we may need to read multiple bytes to assemble a
295 complete Unicode character */
296 if (LocaleIsUTF8 && (c & 192) == 192) { /* First UTF-8 byte */
297 char utf8_str[10];
298 int i, utf8_width = c & 16 ? 4 : c & 32 ? 3 : 2;
299 utf8_str[0] = (guchar)c;
300 for (i = 1; i < utf8_width; ++i) {
301 utf8_str[i] = (guchar)getch();
302 }
303 return g_utf8_get_char(utf8_str);
304 }
305 return c;
306 }
307
308 #endif /* CYGWIN */