2
* libcaca Colour ASCII-Art library
3
* Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
6
* $Id: driver_win32.c 1011 2006-11-11 08:44:14Z sam $
8
* This library is free software; you can redistribute it and/or
9
* modify it under the terms of the Do What The Fuck You Want To
10
* Public License, Version 2, as published by Sam Hocevar. See
11
* http://sam.zoy.org/wtfpl/COPYING for more details.
15
* This file contains the libcaca Win32 input and output driver
21
#if defined(USE_WIN32)
29
#include "caca_internals.h"
31
#include "cucul_internals.h"
37
static int const win32_fg_palette[] =
42
FOREGROUND_GREEN | FOREGROUND_BLUE,
44
FOREGROUND_RED | FOREGROUND_BLUE,
45
FOREGROUND_RED | FOREGROUND_GREEN,
46
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
48
FOREGROUND_INTENSITY | FOREGROUND_BLUE,
49
FOREGROUND_INTENSITY | FOREGROUND_GREEN,
50
FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE,
51
FOREGROUND_INTENSITY | FOREGROUND_RED,
52
FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE,
53
FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN,
54
FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
57
static int const win32_bg_palette[] =
62
BACKGROUND_GREEN | BACKGROUND_BLUE,
64
BACKGROUND_RED | BACKGROUND_BLUE,
65
BACKGROUND_RED | BACKGROUND_GREEN,
66
BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE,
68
BACKGROUND_INTENSITY | BACKGROUND_BLUE,
69
BACKGROUND_INTENSITY | BACKGROUND_GREEN,
70
BACKGROUND_INTENSITY | BACKGROUND_GREEN | BACKGROUND_BLUE,
71
BACKGROUND_INTENSITY | BACKGROUND_RED,
72
BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_BLUE,
73
BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN,
74
BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
79
HANDLE hin, hout, screen;
81
CONSOLE_CURSOR_INFO cci;
84
static int win32_init_graphics(caca_display_t *dp)
86
CONSOLE_SCREEN_BUFFER_INFO csbi;
90
dp->drv.p = malloc(sizeof(struct driver_private));
92
/* This call is allowed to fail in case we already have a console */
95
dp->drv.p->hin = GetStdHandle(STD_INPUT_HANDLE);
96
dp->drv.p->hout = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE,
97
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
98
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
99
if(dp->drv.p->hout == INVALID_HANDLE_VALUE)
102
GetConsoleCursorInfo(dp->drv.p->hout, &dp->drv.p->cci);
103
dp->drv.p->cci.bVisible = FALSE;
104
SetConsoleCursorInfo(dp->drv.p->hout, &dp->drv.p->cci);
106
SetConsoleMode(dp->drv.p->hout, ENABLE_MOUSE_INPUT);
109
CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
110
0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
111
if(!dp->drv.p->screen || dp->drv.p->screen == INVALID_HANDLE_VALUE)
114
/* Set the new console size */
115
size.X = dp->cv->width ? dp->cv->width : 80;
116
size.Y = dp->cv->height ? dp->cv->height : 25;
117
SetConsoleScreenBufferSize(dp->drv.p->screen, size);
119
rect.Left = rect.Top = 0;
120
rect.Right = dp->cv->width - 1;
121
rect.Bottom = dp->cv->height - 1;
122
SetConsoleWindowInfo(dp->drv.p->screen, TRUE, &rect);
124
/* Report our new size to libcucul */
125
if(!GetConsoleScreenBufferInfo(dp->drv.p->screen, &csbi))
128
_cucul_set_canvas_size(dp->cv, csbi.srWindow.Right - csbi.srWindow.Left + 1,
129
csbi.srWindow.Bottom - csbi.srWindow.Top + 1);
131
SetConsoleMode(dp->drv.p->screen, 0);
133
GetConsoleCursorInfo(dp->drv.p->screen, &dp->drv.p->cci);
134
dp->drv.p->cci.dwSize = 0;
135
dp->drv.p->cci.bVisible = FALSE;
136
SetConsoleCursorInfo(dp->drv.p->screen, &dp->drv.p->cci);
138
SetConsoleActiveScreenBuffer(dp->drv.p->screen);
140
dp->drv.p->buffer = malloc(dp->cv->width * dp->cv->height
141
* sizeof(CHAR_INFO));
142
if(dp->drv.p->buffer == NULL)
148
static int win32_end_graphics(caca_display_t *dp)
150
SetConsoleActiveScreenBuffer(dp->drv.p->hout);
151
CloseHandle(dp->drv.p->screen);
153
SetConsoleTextAttribute(dp->drv.p->hout, FOREGROUND_INTENSITY
157
dp->drv.p->cci.bVisible = TRUE;
158
SetConsoleCursorInfo(dp->drv.p->hout, &dp->drv.p->cci);
159
CloseHandle(dp->drv.p->hout);
166
static int win32_set_display_title(caca_display_t *dp, char const *title)
168
SetConsoleTitle(title);
172
static unsigned int win32_get_display_width(caca_display_t *dp)
176
/* Fallback to a 6x10 font */
177
return dp->cv->width * 6;
180
static unsigned int win32_get_display_height(caca_display_t *dp)
184
/* Fallback to a 6x10 font */
185
return dp->cv->height * 10;
188
static void win32_display(caca_display_t *dp)
192
CHAR_INFO *buffer = dp->drv.p->buffer;
193
uint32_t *attrs = dp->cv->attrs;
194
uint32_t *chars = dp->cv->chars;
197
/* Render everything to our screen buffer */
198
for(n = dp->cv->height * dp->cv->width; n--; )
200
uint32_t ch = *chars++;
201
uint8_t fg = cucul_attr_to_ansi_fg(*attrs);
202
uint8_t bg = cucul_attr_to_ansi_bg(*attrs);
205
if(ch > 0x00000020 && ch < 0x00000080)
206
dp->drv.p->buffer[i].Char.AsciiChar = (uint8_t)ch;
208
dp->drv.p->buffer[i].Char.AsciiChar = ' ';
210
if(n && *chars == CUCUL_MAGIC_FULLWIDTH)
212
else if(ch > 0x00000020 && ch < 0x00010000)
213
buffer->Char.UnicodeChar = (uint16_t)ch;
215
buffer->Char.UnicodeChar = (uint16_t)' ';
218
buffer->Attributes = win32_fg_palette[fg < 0x10 ? fg : CUCUL_LIGHTGRAY]
219
| win32_bg_palette[bg < 0x10 ? bg : CUCUL_BLACK];
224
/* Blit the screen buffer */
225
size.X = dp->cv->width;
226
size.Y = dp->cv->height;
228
rect.Left = rect.Top = 0;
229
rect.Right = dp->cv->width - 1;
230
rect.Bottom = dp->cv->height - 1;
232
WriteConsoleOutput(dp->drv.p->screen, dp->drv.p->buffer, size, pos, &rect);
234
WriteConsoleOutputW(dp->drv.p->screen, dp->drv.p->buffer, size, pos, &rect);
238
static void win32_handle_resize(caca_display_t *dp)
240
/* FIXME: I don't know what to do here. */
241
dp->resize.w = dp->cv->width;
242
dp->resize.h = dp->cv->height;
245
static int win32_get_event(caca_display_t *dp, caca_event_t *ev)
252
GetNumberOfConsoleInputEvents(dp->drv.p->hin, &num);
256
ReadConsoleInput(dp->drv.p->hin, &rec, 1, &num);
257
if(rec.EventType == KEY_EVENT)
259
if(rec.Event.KeyEvent.bKeyDown)
260
ev->type = CACA_EVENT_KEY_PRESS;
262
ev->type = CACA_EVENT_KEY_RELEASE;
264
if(rec.Event.KeyEvent.uChar.AsciiChar)
266
ev->data.key.ch = rec.Event.KeyEvent.uChar.AsciiChar;
267
ev->data.key.utf32 = (uint32_t)ev->data.key.ch;
268
ev->data.key.utf8[0] = ev->data.key.ch;
269
ev->data.key.utf8[1] = '\0';
275
if(rec.EventType == MOUSE_EVENT)
277
if(rec.Event.MouseEvent.dwEventFlags == 0)
279
if(rec.Event.MouseEvent.dwButtonState & 0x01)
281
ev->type = CACA_EVENT_MOUSE_PRESS;
282
ev->data.mouse.button = 1;
286
if(rec.Event.MouseEvent.dwButtonState & 0x02)
288
ev->type = CACA_EVENT_MOUSE_PRESS;
289
ev->data.mouse.button = 2;
293
else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_MOVED)
295
COORD pos = rec.Event.MouseEvent.dwMousePosition;
297
if(dp->mouse.x == (unsigned int)pos.X &&
298
dp->mouse.y == (unsigned int)pos.Y)
304
ev->type = CACA_EVENT_MOUSE_MOTION;
305
ev->data.mouse.x = dp->mouse.x;
306
ev->data.mouse.y = dp->mouse.y;
310
else if(rec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK)
312
cout << rec.Event.MouseEvent.dwMousePosition.X << "," <<
313
rec.Event.MouseEvent.dwMousePosition.Y << " " << flush;
315
else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_WHEELED)
317
SetConsoleCursorPosition(hOut,
319
if(rec.Event.MouseEvent.dwButtonState & 0xFF000000)
320
cout << "Down" << flush;
322
cout << "Up " << flush;
328
ev->type = CACA_EVENT_NONE;
333
ev->type = CACA_EVENT_NONE;
338
* Driver initialisation
341
int win32_install(caca_display_t *dp)
343
dp->drv.driver = CACA_DRIVER_WIN32;
345
dp->drv.init_graphics = win32_init_graphics;
346
dp->drv.end_graphics = win32_end_graphics;
347
dp->drv.set_display_title = win32_set_display_title;
348
dp->drv.get_display_width = win32_get_display_width;
349
dp->drv.get_display_height = win32_get_display_height;
350
dp->drv.display = win32_display;
351
dp->drv.handle_resize = win32_handle_resize;
352
dp->drv.get_event = win32_get_event;
353
dp->drv.set_mouse = NULL;
358
#endif /* USE_WIN32 */