source: libcaca/trunk/caca/driver_win32.c @ 548

Last change on this file since 548 was 548, checked in by Sam Hocevar, 14 years ago
  • Split event.c into the appropriate driver_*.c files.
  • Property svn:keywords set to Id
File size: 9.2 KB
Line 
1/*
2 *  libcaca       ASCII-Art library
3 *  Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
4 *                All Rights Reserved
5 *
6 *  This library is free software; you can redistribute it and/or
7 *  modify it under the terms of the Do What The Fuck You Want To
8 *  Public License, Version 2, as published by Sam Hocevar. See
9 *  http://sam.zoy.org/wtfpl/COPYING for more details.
10 */
11
12/** \file driver_win32.c
13 *  \version \$Id: driver_win32.c 548 2006-03-08 09:28:41Z sam $
14 *  \author Sam Hocevar <sam@zoy.org>
15 *  \brief Win32 driver
16 *
17 *  This file contains the libcaca Win32 input and output driver
18 */
19
20#include "config.h"
21
22#if defined(USE_WIN32)
23
24#include <windows.h>
25
26#include <stdio.h> /* BUFSIZ */
27#include <string.h>
28#include <stdlib.h>
29#if defined(HAVE_UNISTD_H)
30#   include <unistd.h>
31#endif
32#include <stdarg.h>
33
34#include "caca.h"
35#include "caca_internals.h"
36#include "cucul.h"
37#include "cucul_internals.h"
38
39/*
40 * Global variables
41 */
42
43static int const win32_fg_palette[] =
44{
45    0,
46    FOREGROUND_BLUE,
47    FOREGROUND_GREEN,
48    FOREGROUND_GREEN | FOREGROUND_BLUE,
49    FOREGROUND_RED,
50    FOREGROUND_RED | FOREGROUND_BLUE,
51    FOREGROUND_RED | FOREGROUND_GREEN,
52    FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
53    FOREGROUND_INTENSITY,
54    FOREGROUND_INTENSITY | FOREGROUND_BLUE,
55    FOREGROUND_INTENSITY | FOREGROUND_GREEN,
56    FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE,
57    FOREGROUND_INTENSITY | FOREGROUND_RED,
58    FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE,
59    FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN,
60    FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
61};
62
63static int const win32_bg_palette[] =
64{
65    0,
66    BACKGROUND_BLUE,
67    BACKGROUND_GREEN,
68    BACKGROUND_GREEN | BACKGROUND_BLUE,
69    BACKGROUND_RED,
70    BACKGROUND_RED | BACKGROUND_BLUE,
71    BACKGROUND_RED | BACKGROUND_GREEN,
72    BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE,
73    BACKGROUND_INTENSITY,
74    BACKGROUND_INTENSITY | BACKGROUND_BLUE,
75    BACKGROUND_INTENSITY | BACKGROUND_GREEN,
76    BACKGROUND_INTENSITY | BACKGROUND_GREEN | BACKGROUND_BLUE,
77    BACKGROUND_INTENSITY | BACKGROUND_RED,
78    BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_BLUE,
79    BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN,
80    BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
81};
82
83static int win32_init_graphics(caca_t *kk)
84{
85    CONSOLE_SCREEN_BUFFER_INFO csbi;
86    COORD size;
87
88    /* This call is allowed to fail in case we already have a console */
89    AllocConsole();
90
91    kk->win32.hin = GetStdHandle(STD_INPUT_HANDLE);
92    kk->win32.hout = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE,
93                                FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
94                                OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
95    if(kk->win32.hout == INVALID_HANDLE_VALUE)
96        return -1;
97
98    GetConsoleCursorInfo(kk->win32.hout, &kk->win32.cci);
99    kk->win32.cci.bVisible = FALSE;
100    SetConsoleCursorInfo(kk->win32.hout, &kk->win32.cci);
101
102    SetConsoleMode(kk->win32.hout, ENABLE_MOUSE_INPUT);
103
104    kk->win32.front =
105        CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
106                                  0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
107    if(!kk->win32.front || kk->win32.front == INVALID_HANDLE_VALUE)
108        return -1;
109
110    kk->win32.back =
111        CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
112                                  0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
113    if(!kk->win32.back || kk->win32.back == INVALID_HANDLE_VALUE)
114        return -1;
115
116    if(!GetConsoleScreenBufferInfo(kk->win32.hout, &csbi))
117        return -1;
118
119    /* Sample code to get the biggest possible window */
120    //size = GetLargestConsoleWindowSize(kk->win32.hout);
121    cucul_set_size(kk->qq, csbi.srWindow.Right - csbi.srWindow.Left + 1,
122                           csbi.srWindow.Bottom - csbi.srWindow.Top + 1);
123    size.X = kk->qq->width;
124    size.Y = kk->qq->height;
125    SetConsoleScreenBufferSize(kk->win32.front, size);
126    SetConsoleScreenBufferSize(kk->win32.back, size);
127
128    SetConsoleMode(kk->win32.front, 0);
129    SetConsoleMode(kk->win32.back, 0);
130
131    GetConsoleCursorInfo(kk->win32.front, &kk->win32.cci);
132    kk->win32.cci.dwSize = 0;
133    kk->win32.cci.bVisible = FALSE;
134    SetConsoleCursorInfo(kk->win32.front, &kk->win32.cci);
135    SetConsoleCursorInfo(kk->win32.back, &kk->win32.cci);
136
137    SetConsoleActiveScreenBuffer(kk->win32.front);
138
139    kk->win32.buffer = malloc(kk->qq->width * kk->qq->height
140                               * sizeof(CHAR_INFO));
141    if(kk->win32.buffer == NULL)
142        return -1;
143
144    return 0;
145}
146
147static int win32_end_graphics(caca_t *kk)
148{
149    SetConsoleActiveScreenBuffer(kk->win32.hout);
150    CloseHandle(kk->win32.back);
151    CloseHandle(kk->win32.front);
152
153    SetConsoleTextAttribute(kk->win32.hout, FOREGROUND_INTENSITY
154                                             | FOREGROUND_RED
155                                             | FOREGROUND_GREEN
156                                             | FOREGROUND_BLUE);
157    kk->win32.cci.bVisible = TRUE;
158    SetConsoleCursorInfo(kk->win32.hout, &kk->win32.cci);
159    CloseHandle(kk->win32.hout);
160
161    return 0;
162}
163
164static int win32_set_window_title(caca_t *kk, char const *title)
165{
166    SetConsoleTitle(title);
167    return 0;
168}
169
170static unsigned int win32_get_window_width(caca_t *kk)
171{
172    /* FIXME */
173
174    /* Fallback to a 6x10 font */
175    return kk->qq->width * 6;
176}
177
178static unsigned int win32_get_window_height(caca_t *kk)
179{
180    /* FIXME */
181
182    /* Fallback to a 6x10 font */
183    return kk->qq->height * 10;
184}
185
186static void win32_display(caca_t *kk)
187{
188    COORD size, pos;
189    SMALL_RECT rect;
190    unsigned int i;
191
192    /* Render everything to our back buffer */
193    for(i = 0; i < kk->qq->width * kk->qq->height; i++)
194    {
195        kk->win32.buffer[i].Char.AsciiChar = kk->qq->chars[i] & 0x7f;
196        kk->win32.buffer[i].Attributes =
197                win32_fg_palette[kk->qq->attr[i] & 0xf]
198                 | win32_bg_palette[kk->qq->attr[i] >> 4];
199    }
200
201    /* Blit the back buffer to the front buffer */
202    size.X = kk->qq->width;
203    size.Y = kk->qq->height;
204    pos.X = pos.Y = 0;
205    rect.Left = rect.Top = 0;
206    rect.Right = kk->qq->width - 1;
207    rect.Bottom = kk->qq->height - 1;
208    WriteConsoleOutput(kk->win32.front, kk->win32.buffer, size, pos, &rect);
209}
210
211static void win32_handle_resize(caca_t *kk, unsigned int *new_width,
212                                            unsigned int *new_height)
213{
214    /* Nothing to do here. */
215    *new_width = kk->qq->width;
216    *new_height = kk->qq->height;
217}
218
219static unsigned int win32_get_event(caca_t *kk)
220{
221    INPUT_RECORD rec;
222    DWORD num;
223
224    for( ; ; )
225    {
226        GetNumberOfConsoleInputEvents(kk->win32.hin, &num);
227        if(num == 0)
228            break;
229
230        ReadConsoleInput(kk->win32.hin, &rec, 1, &num);
231        if(rec.EventType == KEY_EVENT)
232        {
233            unsigned int event;
234
235            if(rec.Event.KeyEvent.bKeyDown)
236                event = CACA_EVENT_KEY_PRESS;
237            else
238                event = CACA_EVENT_KEY_RELEASE;
239
240            if(rec.Event.KeyEvent.uChar.AsciiChar)
241                return event | rec.Event.KeyEvent.uChar.AsciiChar;
242        }
243
244        if(rec.EventType == MOUSE_EVENT)
245        {
246            if(rec.Event.MouseEvent.dwEventFlags == 0)
247            {
248                if(rec.Event.MouseEvent.dwButtonState & 0x01)
249                    return CACA_EVENT_MOUSE_PRESS | 0x000001;
250
251                if(rec.Event.MouseEvent.dwButtonState & 0x02)
252                    return CACA_EVENT_MOUSE_PRESS | 0x000002;
253            }
254            else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_MOVED)
255            {
256                COORD pos = rec.Event.MouseEvent.dwMousePosition;
257
258                if(kk->mouse_x == (unsigned int)pos.X &&
259                   kk->mouse_y == (unsigned int)pos.Y)
260                    continue;
261
262                kk->mouse_x = pos.X;
263                kk->mouse_y = pos.Y;
264
265                return CACA_EVENT_MOUSE_MOTION | (kk->mouse_x << 12) | kk->mouse_y;
266            }
267#if 0
268            else if(rec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK)
269            {
270                cout << rec.Event.MouseEvent.dwMousePosition.X << "," <<
271                        rec.Event.MouseEvent.dwMousePosition.Y << "  " << flush;
272            }
273            else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_WHEELED)
274            {
275                SetConsoleCursorPosition(hOut,
276                                         WheelWhere);
277                if(rec.Event.MouseEvent.dwButtonState & 0xFF000000)
278                    cout << "Down" << flush;
279                else
280                    cout << "Up  " << flush;
281            }
282#endif
283        }
284
285        /* Unknown event */
286        return CACA_EVENT_NONE;
287    }
288
289    /* No event */
290    return CACA_EVENT_NONE;
291}
292
293/*
294 * Driver initialisation
295 */
296
297void win32_init_driver(caca_t *kk)
298{
299    kk->driver.driver = CACA_DRIVER_WIN32;
300
301    kk->driver.init_graphics = win32_init_graphics;
302    kk->driver.end_graphics = win32_end_graphics;
303    kk->driver.set_window_title = win32_set_window_title;
304    kk->driver.get_window_width = win32_get_window_width;
305    kk->driver.get_window_height = win32_get_window_height;
306    kk->driver.display = win32_display;
307    kk->driver.handle_resize = win32_handle_resize;
308    kk->driver.get_event = win32_get_event;
309}
310
311#endif /* USE_WIN32 */
312
Note: See TracBrowser for help on using the repository browser.