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

Last change on this file since 700 was 689, checked in by Sam Hocevar, 15 years ago
  • Merged caca_show_cursor() and caca_hide_cursor() into caca_set_mouse() so that we have one function less.
  • Fixed coding style.
  • Removed FUCKING TABS. .------._

_.----' -.

_.--' `.

_.-' ' ' `. _

.- H A H A H A ' M A I S \/.)

. . .-' / `

|-.(-. ' ` |\
. '\\ V I E U X ' ' - -|

/'') - - ` ' '.' |\_)

|'_._ '' P O R C . . /
@) \ ''' . '/

/ | \)..'-. _ _ . ` '/

.'- -'. . )-- '/'' ,._`' ' /

.' - ` ' .' / ' /,;;;, ,_.---' \ / \
(. .'
',`'.--'/ ' /'-----' | ' / ))

'-'/ _.---' \;;'/ , | |`- |

'--'---' |;| / ,,,,;;;;;;;;;;,,,,, |-' / |

|;'| ,;;;;;;;;;;;;;;;; ;;;/ /|`

,,' /

'

  • Property svn:keywords set to Id
File size: 10.0 KB
RevLine 
[35]1/*
[672]2 *  libcaca       Colour ASCII-Art library
[527]3 *  Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
[268]4 *                All Rights Reserved
[35]5 *
[268]6 *  This library is free software; you can redistribute it and/or
[522]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.
[35]10 */
[17]11
[540]12/** \file driver_win32.c
[268]13 *  \version \$Id: driver_win32.c 689 2006-03-24 16:51:59Z sam $
14 *  \author Sam Hocevar <sam@zoy.org>
[540]15 *  \brief Win32 driver
[205]16 *
[540]17 *  This file contains the libcaca Win32 input and output driver
[205]18 */
19
[63]20#include "config.h"
21
[539]22#if defined(USE_WIN32)
23
24#include <windows.h>
25
[550]26#include <stdlib.h>
[632]27#include <stdio.h>
[550]28
[185]29#include "caca.h"
30#include "caca_internals.h"
[524]31#include "cucul.h"
32#include "cucul_internals.h"
[17]33
[247]34/*
35 * Global variables
36 */
37
[336]38static int const win32_fg_palette[] =
39{
40    0,
41    FOREGROUND_BLUE,
42    FOREGROUND_GREEN,
43    FOREGROUND_GREEN | FOREGROUND_BLUE,
44    FOREGROUND_RED,
45    FOREGROUND_RED | FOREGROUND_BLUE,
46    FOREGROUND_RED | FOREGROUND_GREEN,
47    FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
48    FOREGROUND_INTENSITY,
49    FOREGROUND_INTENSITY | FOREGROUND_BLUE,
50    FOREGROUND_INTENSITY | FOREGROUND_GREEN,
51    FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE,
52    FOREGROUND_INTENSITY | FOREGROUND_RED,
53    FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE,
54    FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN,
55    FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
56};
57
58static int const win32_bg_palette[] =
59{
60    0,
61    BACKGROUND_BLUE,
62    BACKGROUND_GREEN,
63    BACKGROUND_GREEN | BACKGROUND_BLUE,
64    BACKGROUND_RED,
65    BACKGROUND_RED | BACKGROUND_BLUE,
66    BACKGROUND_RED | BACKGROUND_GREEN,
67    BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE,
68    BACKGROUND_INTENSITY,
69    BACKGROUND_INTENSITY | BACKGROUND_BLUE,
70    BACKGROUND_INTENSITY | BACKGROUND_GREEN,
71    BACKGROUND_INTENSITY | BACKGROUND_GREEN | BACKGROUND_BLUE,
72    BACKGROUND_INTENSITY | BACKGROUND_RED,
73    BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_BLUE,
74    BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN,
75    BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
76};
[527]77
[550]78struct driver_private
79{
[632]80    HANDLE hin, hout, screen;
[550]81    CHAR_INFO *buffer;
82    CONSOLE_CURSOR_INFO cci;
83};
84
[540]85static int win32_init_graphics(caca_t *kk)
[227]86{
[539]87    CONSOLE_SCREEN_BUFFER_INFO csbi;
[632]88    SMALL_RECT rect;
[539]89    COORD size;
[348]90
[550]91    kk->drv.p = malloc(sizeof(struct driver_private));
92
[539]93    /* This call is allowed to fail in case we already have a console */
94    AllocConsole();
[227]95
[550]96    kk->drv.p->hin = GetStdHandle(STD_INPUT_HANDLE);
97    kk->drv.p->hout = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE,
98                                 FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
99                                 OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
100    if(kk->drv.p->hout == INVALID_HANDLE_VALUE)
[539]101        return -1;
[231]102
[550]103    GetConsoleCursorInfo(kk->drv.p->hout, &kk->drv.p->cci);
104    kk->drv.p->cci.bVisible = FALSE;
105    SetConsoleCursorInfo(kk->drv.p->hout, &kk->drv.p->cci);
[227]106
[550]107    SetConsoleMode(kk->drv.p->hout, ENABLE_MOUSE_INPUT);
[227]108
[632]109    kk->drv.p->screen =
[539]110        CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
111                                  0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
[632]112    if(!kk->drv.p->screen || kk->drv.p->screen == INVALID_HANDLE_VALUE)
[539]113        return -1;
[227]114
[632]115    /* Set the new console size */
116    size.X = kk->qq->width;
117    size.Y = kk->qq->height;
118    SetConsoleScreenBufferSize(kk->drv.p->screen, size);
[227]119
[632]120    rect.Left = rect.Top = 0;
121    rect.Right = kk->qq->width - 1;
122    rect.Bottom = kk->qq->height - 1;
123    SetConsoleWindowInfo(kk->drv.p->screen, TRUE, &rect);
124
125    /* Report our new size to libcucul */
126    if(!GetConsoleScreenBufferInfo(kk->drv.p->screen, &csbi))
[539]127        return -1;
[227]128
[582]129    _cucul_set_size(kk->qq, csbi.srWindow.Right - csbi.srWindow.Left + 1,
130                            csbi.srWindow.Bottom - csbi.srWindow.Top + 1);
[227]131
[632]132    SetConsoleMode(kk->drv.p->screen, 0);
[251]133
[632]134    GetConsoleCursorInfo(kk->drv.p->screen, &kk->drv.p->cci);
[550]135    kk->drv.p->cci.dwSize = 0;
136    kk->drv.p->cci.bVisible = FALSE;
[632]137    SetConsoleCursorInfo(kk->drv.p->screen, &kk->drv.p->cci);
[261]138
[632]139    SetConsoleActiveScreenBuffer(kk->drv.p->screen);
[274]140
[550]141    kk->drv.p->buffer = malloc(kk->qq->width * kk->qq->height
[539]142                               * sizeof(CHAR_INFO));
[550]143    if(kk->drv.p->buffer == NULL)
[539]144        return -1;
[263]145
[227]146    return 0;
147}
148
[540]149static int win32_end_graphics(caca_t *kk)
[251]150{
[550]151    SetConsoleActiveScreenBuffer(kk->drv.p->hout);
[632]152    CloseHandle(kk->drv.p->screen);
[300]153
[550]154    SetConsoleTextAttribute(kk->drv.p->hout, FOREGROUND_INTENSITY
[539]155                                             | FOREGROUND_RED
156                                             | FOREGROUND_GREEN
157                                             | FOREGROUND_BLUE);
[550]158    kk->drv.p->cci.bVisible = TRUE;
159    SetConsoleCursorInfo(kk->drv.p->hout, &kk->drv.p->cci);
160    CloseHandle(kk->drv.p->hout);
[539]161
[550]162    free(kk->drv.p);
163
[251]164    return 0;
165}
166
[540]167static int win32_set_window_title(caca_t *kk, char const *title)
[343]168{
[539]169    SetConsoleTitle(title);
[343]170    return 0;
171}
172
[540]173static unsigned int win32_get_window_width(caca_t *kk)
[352]174{
[539]175    /* FIXME */
[352]176
177    /* Fallback to a 6x10 font */
[524]178    return kk->qq->width * 6;
[352]179}
180
[540]181static unsigned int win32_get_window_height(caca_t *kk)
[352]182{
[539]183    /* FIXME */
[352]184
185    /* Fallback to a 6x10 font */
[524]186    return kk->qq->height * 10;
[352]187}
188
[540]189static void win32_display(caca_t *kk)
[227]190{
[539]191    COORD size, pos;
192    SMALL_RECT rect;
193    unsigned int i;
[227]194
[632]195    /* Render everything to our screen buffer */
[539]196    for(i = 0; i < kk->qq->width * kk->qq->height; i++)
[265]197    {
[557]198        uint32_t c = kk->qq->chars[i];
199
[612]200#if 0
[557]201        if(c > 0x00000020 && c < 0x00000080)
[612]202            kk->drv.p->buffer[i].Char.AsciiChar = (uint8_t)c;
[557]203        else
204            kk->drv.p->buffer[i].Char.AsciiChar = ' ';
[612]205#else
206        if(c > 0x00000020 && c < 0x00010000)
207            kk->drv.p->buffer[i].Char.UnicodeChar = (uint16_t)c;
208        else
209            kk->drv.p->buffer[i].Char.UnicodeChar = (uint16_t)' ';
210#endif
[557]211
[550]212        kk->drv.p->buffer[i].Attributes =
[539]213                win32_fg_palette[kk->qq->attr[i] & 0xf]
214                 | win32_bg_palette[kk->qq->attr[i] >> 4];
[265]215    }
[261]216
[632]217    /* Blit the screen buffer */
[539]218    size.X = kk->qq->width;
219    size.Y = kk->qq->height;
220    pos.X = pos.Y = 0;
221    rect.Left = rect.Top = 0;
222    rect.Right = kk->qq->width - 1;
223    rect.Bottom = kk->qq->height - 1;
[612]224#if 0
[632]225    WriteConsoleOutput(kk->drv.p->screen, kk->drv.p->buffer, size, pos, &rect);
[612]226#else
[632]227    WriteConsoleOutputW(kk->drv.p->screen, kk->drv.p->buffer, size, pos, &rect);
[612]228#endif
[227]229}
230
[553]231static void win32_handle_resize(caca_t *kk)
[347]232{
[553]233    /* FIXME: I don't know what to do here. */
234    kk->resize.w = kk->qq->width;
235    kk->resize.h = kk->qq->height;
[347]236}
237
[681]238static int win32_get_event(caca_t *kk, struct caca_event *ev)
[548]239{
240    INPUT_RECORD rec;
241    DWORD num;
242
243    for( ; ; )
244    {
[550]245        GetNumberOfConsoleInputEvents(kk->drv.p->hin, &num);
[548]246        if(num == 0)
247            break;
248
[550]249        ReadConsoleInput(kk->drv.p->hin, &rec, 1, &num);
[548]250        if(rec.EventType == KEY_EVENT)
251        {
252            unsigned int event;
253
254            if(rec.Event.KeyEvent.bKeyDown)
[681]255                ev->type = CACA_EVENT_KEY_PRESS;
[548]256            else
[681]257                ev->type = CACA_EVENT_KEY_RELEASE;
[548]258
259            if(rec.Event.KeyEvent.uChar.AsciiChar)
[681]260            {
261                ev->data.key.c = rec.Event.KeyEvent.uChar.AsciiChar;
262                ev->data.key.ucs4 = (uint32_t)ev->data.key.c;
263                ev->data.key.utf8[0] = ev->data.key.c;
264                ev->data.key.utf8[1] = '\0';
265
266                return 1;
267            }
[548]268        }
269
270        if(rec.EventType == MOUSE_EVENT)
271        {
272            if(rec.Event.MouseEvent.dwEventFlags == 0)
273            {
274                if(rec.Event.MouseEvent.dwButtonState & 0x01)
[681]275                {
276                    ev->type = CACA_EVENT_MOUSE_PRESS;
277                    ev->data.mouse.button = 1;
278                    return 1;
279                }
[548]280
281                if(rec.Event.MouseEvent.dwButtonState & 0x02)
[681]282                {
283                    ev->type = CACA_EVENT_MOUSE_PRESS;
284                    ev->data.mouse.button = 2;
285                    return 1;
286                }
[548]287            }
288            else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_MOVED)
289            {
290                COORD pos = rec.Event.MouseEvent.dwMousePosition;
291
[551]292                if(kk->mouse.x == (unsigned int)pos.X &&
293                   kk->mouse.y == (unsigned int)pos.Y)
[548]294                    continue;
295
[551]296                kk->mouse.x = pos.X;
297                kk->mouse.y = pos.Y;
[548]298
[681]299                ev->type = CACA_EVENT_MOUSE_MOTION;
300                ev->data.mouse.x = kk->mouse.x;
301                ev->data.mouse.y = kk->mouse.y;
302                return 1;
[548]303            }
304#if 0
305            else if(rec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK)
306            {
307                cout << rec.Event.MouseEvent.dwMousePosition.X << "," <<
308                        rec.Event.MouseEvent.dwMousePosition.Y << "  " << flush;
309            }
310            else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_WHEELED)
311            {
312                SetConsoleCursorPosition(hOut,
313                                         WheelWhere);
314                if(rec.Event.MouseEvent.dwButtonState & 0xFF000000)
315                    cout << "Down" << flush;
316                else
317                    cout << "Up  " << flush;
318            }
319#endif
320        }
321
322        /* Unknown event */
[681]323        ev->type = CACA_EVENT_NONE;
324        return 0;
[548]325    }
326
327    /* No event */
[681]328    ev->type = CACA_EVENT_NONE;
329    return 0;
[548]330}
331
[539]332/*
333 * Driver initialisation
334 */
[281]335
[684]336int win32_install(caca_t *kk)
[300]337{
[550]338    kk->drv.driver = CACA_DRIVER_WIN32;
[300]339
[550]340    kk->drv.init_graphics = win32_init_graphics;
341    kk->drv.end_graphics = win32_end_graphics;
342    kk->drv.set_window_title = win32_set_window_title;
343    kk->drv.get_window_width = win32_get_window_width;
344    kk->drv.get_window_height = win32_get_window_height;
345    kk->drv.display = win32_display;
346    kk->drv.handle_resize = win32_handle_resize;
347    kk->drv.get_event = win32_get_event;
[689]348    kk->drv.set_mouse = NULL;
[684]349
350    return 0;
[348]351}
352
[539]353#endif /* USE_WIN32 */
[527]354
Note: See TracBrowser for help on using the repository browser.