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

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