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

Last change on this file since 540 was 540, checked in by Sam Hocevar, 15 years ago
  • Polished the driver split a bit (still no events, except resize events), properly credited authors and documented a few things.
  • Property svn:keywords set to Id
File size: 6.9 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 540 2006-03-07 09:17:35Z 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
219/*
220 * Driver initialisation
221 */
222
223void win32_init_driver(caca_t *kk)
224{
225    kk->driver.driver = CACA_DRIVER_WIN32;
226
227    kk->driver.init_graphics = win32_init_graphics;
228    kk->driver.end_graphics = win32_end_graphics;
229    kk->driver.set_window_title = win32_set_window_title;
230    kk->driver.get_window_width = win32_get_window_width;
231    kk->driver.get_window_height = win32_get_window_height;
232    kk->driver.display = win32_display;
233    kk->driver.handle_resize = win32_handle_resize;
234}
235
236#endif /* USE_WIN32 */
237
Note: See TracBrowser for help on using the repository browser.