+ Native win32 port.tags/v0.99.beta14
@@ -193,5 +193,6 @@ $Id$ | |||||
o MS-DOS: all bright colours, bright backgrounds, and bright combinations | o MS-DOS: all bright colours, bright backgrounds, and bright combinations | ||||
work using <conio.h>. No need to kludge anything. | work using <conio.h>. No need to kludge anything. | ||||
o Win32: we use GetConsoleScreenBufferInfo etc. | |||||
o Win32: we use GetConsoleScreenBufferInfo etc. There is an interesting | |||||
tutorial here: http://www.adrianxw.dk/SoftwareSite/index.html | |||||
@@ -34,6 +34,10 @@ | |||||
# include <stdio.h> | # include <stdio.h> | ||||
#endif | #endif | ||||
#if defined(HAVE_SLEEP) | |||||
# include <windows.h> | |||||
#endif | |||||
#include "caca.h" | #include "caca.h" | ||||
/* Local macros */ | /* Local macros */ | ||||
@@ -256,7 +260,11 @@ int main(int argc, char **argv) | |||||
if(!update) | if(!update) | ||||
{ | { | ||||
#if defined(HAVE_USLEEP) | |||||
usleep(10000); | usleep(10000); | ||||
#elif defined(HAVE_SLEEP) | |||||
Sleep(10); | |||||
#endif | |||||
continue; | continue; | ||||
} | } | ||||
@@ -70,6 +70,10 @@ enum caca_driver _caca_driver; | |||||
static mmask_t oldmask; | static mmask_t oldmask; | ||||
#endif | #endif | ||||
#if defined(USE_WIN32) | |||||
static CONSOLE_CURSOR_INFO cci; | |||||
#endif | |||||
/** \brief Initialise \e libcaca. | /** \brief Initialise \e libcaca. | ||||
* | * | ||||
* This function initialises internal \e libcaca structures and the backend | * This function initialises internal \e libcaca structures and the backend | ||||
@@ -168,8 +172,19 @@ int caca_init(void) | |||||
#if defined(USE_WIN32) | #if defined(USE_WIN32) | ||||
if(_caca_driver == CACA_DRIVER_WIN32) | if(_caca_driver == CACA_DRIVER_WIN32) | ||||
{ | { | ||||
/* Nothing to do */ | |||||
printf("initialising win32 driver\n"); | |||||
win32_hin = GetStdHandle(STD_INPUT_HANDLE); | |||||
win32_hout = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE, | |||||
FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, | |||||
OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); | |||||
if(win32_hout == INVALID_HANDLE_VALUE) | |||||
return -1; | |||||
GetConsoleCursorInfo(win32_hout, &cci); | |||||
cci.bVisible = FALSE; | |||||
SetConsoleCursorInfo(win32_hout, &cci); | |||||
SetConsoleMode(win32_hout, ENABLE_MOUSE_INPUT); | |||||
} | } | ||||
else | else | ||||
#endif | #endif | ||||
@@ -391,7 +406,13 @@ void caca_end(void) | |||||
#if defined(USE_WIN32) | #if defined(USE_WIN32) | ||||
if(_caca_driver == CACA_DRIVER_WIN32) | if(_caca_driver == CACA_DRIVER_WIN32) | ||||
{ | { | ||||
/* Nothing to do */ | |||||
SetConsoleTextAttribute(win32_hout, FOREGROUND_INTENSITY | |||||
| FOREGROUND_RED | |||||
| FOREGROUND_GREEN | |||||
| FOREGROUND_BLUE); | |||||
cci.bVisible = TRUE; | |||||
SetConsoleCursorInfo(win32_hout, &cci); | |||||
CloseHandle(win32_hout); | |||||
} | } | ||||
else | else | ||||
#endif | #endif | ||||
@@ -86,4 +86,9 @@ extern Window x11_window; | |||||
extern int x11_font_width, x11_font_height; | extern int x11_font_width, x11_font_height; | ||||
#endif | #endif | ||||
#if defined(USE_WIN32) | |||||
#include <windows.h> | |||||
extern HANDLE win32_hin, win32_hout; | |||||
#endif | |||||
#endif /* __CACA_INTERNALS_H__ */ | #endif /* __CACA_INTERNALS_H__ */ |
@@ -51,6 +51,9 @@ | |||||
# include <X11/XKBlib.h> | # include <X11/XKBlib.h> | ||||
# endif | # endif | ||||
#endif | #endif | ||||
#if defined(USE_WIN32) | |||||
# include <windows.h> | |||||
#endif | |||||
#if defined(HAVE_INTTYPES_H) || defined(_DOXYGEN_SKIP_ME) | #if defined(HAVE_INTTYPES_H) || defined(_DOXYGEN_SKIP_ME) | ||||
# include <inttypes.h> | # include <inttypes.h> | ||||
@@ -61,6 +64,7 @@ typedef unsigned char uint8_t; | |||||
#include <stdio.h> /* BUFSIZ */ | #include <stdio.h> /* BUFSIZ */ | ||||
#include <string.h> | #include <string.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <unistd.h> | |||||
#include <stdarg.h> | #include <stdarg.h> | ||||
#include "caca.h" | #include "caca.h" | ||||
@@ -161,6 +165,53 @@ static Bool x11_detect_autorepeat; | |||||
#endif | #endif | ||||
#endif | #endif | ||||
#if defined(USE_WIN32) | |||||
static uint8_t *win32_char, *win32_attr; | |||||
HANDLE win32_hin, win32_hout; | |||||
static HANDLE win32_front, win32_back; | |||||
static CHAR_INFO *win32_buffer; | |||||
static int const win32_fg_palette[] = | |||||
{ | |||||
0, | |||||
FOREGROUND_BLUE, | |||||
FOREGROUND_GREEN, | |||||
FOREGROUND_GREEN | FOREGROUND_BLUE, | |||||
FOREGROUND_RED, | |||||
FOREGROUND_RED | FOREGROUND_BLUE, | |||||
FOREGROUND_RED | FOREGROUND_GREEN, | |||||
FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE, | |||||
FOREGROUND_INTENSITY, | |||||
FOREGROUND_INTENSITY | FOREGROUND_BLUE, | |||||
FOREGROUND_INTENSITY | FOREGROUND_GREEN, | |||||
FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE, | |||||
FOREGROUND_INTENSITY | FOREGROUND_RED, | |||||
FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE, | |||||
FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN, | |||||
FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | |||||
}; | |||||
static int const win32_bg_palette[] = | |||||
{ | |||||
0, | |||||
BACKGROUND_BLUE, | |||||
BACKGROUND_GREEN, | |||||
BACKGROUND_GREEN | BACKGROUND_BLUE, | |||||
BACKGROUND_RED, | |||||
BACKGROUND_RED | BACKGROUND_BLUE, | |||||
BACKGROUND_RED | BACKGROUND_GREEN, | |||||
BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE, | |||||
BACKGROUND_INTENSITY, | |||||
BACKGROUND_INTENSITY | BACKGROUND_BLUE, | |||||
BACKGROUND_INTENSITY | BACKGROUND_GREEN, | |||||
BACKGROUND_INTENSITY | BACKGROUND_GREEN | BACKGROUND_BLUE, | |||||
BACKGROUND_INTENSITY | BACKGROUND_RED, | |||||
BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_BLUE, | |||||
BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN, | |||||
BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE | |||||
}; | |||||
#endif | |||||
static char *_caca_empty_line; | static char *_caca_empty_line; | ||||
static char *_caca_scratch_line; | static char *_caca_scratch_line; | ||||
@@ -244,7 +295,12 @@ void caca_set_color(enum caca_color fgcolor, enum caca_color bgcolor) | |||||
#endif | #endif | ||||
#if defined(USE_X11) | #if defined(USE_X11) | ||||
case CACA_DRIVER_X11: | case CACA_DRIVER_X11: | ||||
/* FIXME */ | |||||
/* Nothing to do */ | |||||
break; | |||||
#endif | |||||
#if defined(USE_WIN32) | |||||
case CACA_DRIVER_WIN32: | |||||
/* Nothing to do */ | |||||
break; | break; | ||||
#endif | #endif | ||||
default: | default: | ||||
@@ -326,6 +382,12 @@ void caca_putchar(int x, int y, char c) | |||||
x11_char[x + y * _caca_width] = c; | x11_char[x + y * _caca_width] = c; | ||||
x11_attr[x + y * _caca_width] = (_caca_bgcolor << 4) | _caca_fgcolor; | x11_attr[x + y * _caca_width] = (_caca_bgcolor << 4) | _caca_fgcolor; | ||||
break; | break; | ||||
#endif | |||||
#if defined(USE_WIN32) | |||||
case CACA_DRIVER_WIN32: | |||||
win32_char[x + y * _caca_width] = c; | |||||
win32_attr[x + y * _caca_width] = (_caca_bgcolor << 4) | _caca_fgcolor; | |||||
break; | |||||
#endif | #endif | ||||
default: | default: | ||||
break; | break; | ||||
@@ -345,10 +407,10 @@ void caca_putchar(int x, int y, char c) | |||||
*/ | */ | ||||
void caca_putstr(int x, int y, char const *s) | void caca_putstr(int x, int y, char const *s) | ||||
{ | { | ||||
#if defined(USE_CONIO) | defined(USE_X11) | |||||
#if defined(USE_CONIO) | defined(USE_X11) | defined(USE_WIN32) | |||||
char *charbuf; | char *charbuf; | ||||
#endif | #endif | ||||
#if defined(USE_X11) | |||||
#if defined(USE_X11) | defined(USE_WIN32) | |||||
char *attrbuf; | char *attrbuf; | ||||
#endif | #endif | ||||
unsigned int len; | unsigned int len; | ||||
@@ -414,6 +476,17 @@ void caca_putstr(int x, int y, char const *s) | |||||
*attrbuf++ = (_caca_bgcolor << 4) | _caca_fgcolor; | *attrbuf++ = (_caca_bgcolor << 4) | _caca_fgcolor; | ||||
} | } | ||||
break; | break; | ||||
#endif | |||||
#if defined(USE_WIN32) | |||||
case CACA_DRIVER_WIN32: | |||||
charbuf = win32_char + x + y * _caca_width; | |||||
attrbuf = win32_attr + x + y * _caca_width; | |||||
while(*s) | |||||
{ | |||||
*charbuf++ = *s++; | |||||
*attrbuf++ = (_caca_bgcolor << 4) | _caca_fgcolor; | |||||
} | |||||
break; | |||||
#endif | #endif | ||||
default: | default: | ||||
break; | break; | ||||
@@ -734,6 +807,64 @@ int _caca_init_graphics(void) | |||||
DefaultScreen(x11_dpy))); | DefaultScreen(x11_dpy))); | ||||
} | } | ||||
else | else | ||||
#endif | |||||
#if defined(USE_WIN32) | |||||
if(_caca_driver == CACA_DRIVER_WIN32) | |||||
{ | |||||
CONSOLE_CURSOR_INFO cci; | |||||
CONSOLE_SCREEN_BUFFER_INFO csbi; | |||||
COORD size; | |||||
win32_front = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, | |||||
0, NULL, | |||||
CONSOLE_TEXTMODE_BUFFER, NULL); | |||||
if(!win32_front) | |||||
return -1; | |||||
win32_back = CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE, | |||||
0, NULL, | |||||
CONSOLE_TEXTMODE_BUFFER, NULL); | |||||
if(!win32_back) | |||||
return -1; | |||||
if(!GetConsoleScreenBufferInfo(win32_hout, &csbi)) | |||||
return -1; | |||||
_caca_width = csbi.srWindow.Right - csbi.srWindow.Left + 1; | |||||
_caca_height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1; | |||||
size.X = _caca_width; | |||||
size.Y = _caca_height; | |||||
SetConsoleScreenBufferSize(win32_front, size); | |||||
SetConsoleScreenBufferSize(win32_back, size); | |||||
SetConsoleMode(win32_front, 0); | |||||
SetConsoleMode(win32_back, 0); | |||||
GetConsoleCursorInfo(win32_front, &cci); | |||||
cci.bVisible = FALSE; | |||||
SetConsoleCursorInfo(win32_front, &cci); | |||||
SetConsoleCursorInfo(win32_back, &cci); | |||||
SetConsoleActiveScreenBuffer(win32_front); | |||||
win32_char = malloc(_caca_width * _caca_height * sizeof(int)); | |||||
if(win32_char == NULL) | |||||
return -1; | |||||
win32_attr = malloc(_caca_width * _caca_height * sizeof(int)); | |||||
if(win32_attr == NULL) | |||||
{ | |||||
free(win32_char); | |||||
return -1; | |||||
} | |||||
win32_buffer = malloc(sizeof(CHAR_INFO) * _caca_width * _caca_height); | |||||
memset(win32_char, 0, _caca_width * _caca_height * sizeof(int)); | |||||
memset(win32_attr, 0, _caca_width * _caca_height * sizeof(int)); | |||||
} | |||||
else | |||||
#endif | #endif | ||||
{ | { | ||||
/* Dummy */ | /* Dummy */ | ||||
@@ -784,6 +915,17 @@ int _caca_end_graphics(void) | |||||
free(x11_attr); | free(x11_attr); | ||||
} | } | ||||
else | else | ||||
#endif | |||||
#if defined(USE_WIN32) | |||||
if(_caca_driver == CACA_DRIVER_WIN32) | |||||
{ | |||||
SetConsoleActiveScreenBuffer(win32_hout); | |||||
CloseHandle(win32_back); | |||||
CloseHandle(win32_front); | |||||
free(win32_char); | |||||
free(win32_attr); | |||||
} | |||||
else | |||||
#endif | #endif | ||||
{ | { | ||||
/* Dummy */ | /* Dummy */ | ||||
@@ -926,7 +1068,55 @@ void caca_refresh(void) | |||||
0, 0); | 0, 0); | ||||
XFlush(x11_dpy); | XFlush(x11_dpy); | ||||
} | } | ||||
else | |||||
#endif | #endif | ||||
#if defined(USE_WIN32) | |||||
if(_caca_driver == CACA_DRIVER_WIN32) | |||||
{ | |||||
COORD size, pos; | |||||
SMALL_RECT rect; | |||||
DWORD dummy; | |||||
unsigned int x, y, len; | |||||
/* Render everything to our back buffer */ | |||||
for(y = 0; y < _caca_height; y++) | |||||
{ | |||||
pos.X = 0; | |||||
pos.Y = y; | |||||
SetConsoleCursorPosition(win32_back, pos); | |||||
for(x = 0; x < _caca_width; x += len) | |||||
{ | |||||
unsigned char *attr = win32_attr + x + y * _caca_width; | |||||
len = 1; | |||||
while(x + len < _caca_width && attr[len] == attr[0]) | |||||
len++; | |||||
SetConsoleTextAttribute(win32_back, | |||||
win32_fg_palette[attr[0] & 0xf] | |||||
| win32_bg_palette[attr[0] >> 4]); | |||||
WriteConsole(win32_back, win32_char + x + y * _caca_width, | |||||
len, &dummy, NULL); | |||||
} | |||||
} | |||||
/* Blit the back buffer to the front buffer */ | |||||
size.X = _caca_width; | |||||
size.Y = _caca_height; | |||||
pos.X = pos.Y = 0; | |||||
rect.Left = rect.Top = 0; | |||||
rect.Right = _caca_width - 1; | |||||
rect.Bottom = _caca_height - 1; | |||||
ReadConsoleOutput(win32_back, win32_buffer, size, pos, &rect); | |||||
WriteConsoleOutput(win32_front, win32_buffer, size, pos, &rect); | |||||
} | |||||
else | |||||
#endif | |||||
{ | |||||
/* Dummy */ | |||||
} | |||||
/* Wait until _caca_delay + time of last call */ | /* Wait until _caca_delay + time of last call */ | ||||
ticks += _caca_getticks(&timer); | ticks += _caca_getticks(&timer); | ||||
@@ -56,14 +56,18 @@ | |||||
static unsigned int _get_next_event(void); | static unsigned int _get_next_event(void); | ||||
static unsigned int _lowlevel_event(void); | static unsigned int _lowlevel_event(void); | ||||
#if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO) | |||||
static void _push_event(unsigned int); | static void _push_event(unsigned int); | ||||
static unsigned int _pop_event(void); | static unsigned int _pop_event(void); | ||||
#endif | |||||
#if !defined(_DOXYGEN_SKIP_ME) | #if !defined(_DOXYGEN_SKIP_ME) | ||||
#define EVENTBUF_LEN 10 | #define EVENTBUF_LEN 10 | ||||
#endif | #endif | ||||
#if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO) | |||||
static unsigned int eventbuf[EVENTBUF_LEN]; | static unsigned int eventbuf[EVENTBUF_LEN]; | ||||
static int events = 0; | static int events = 0; | ||||
#endif | |||||
#if !defined(_DOXYGEN_SKIP_ME) | #if !defined(_DOXYGEN_SKIP_ME) | ||||
/* If no new key was pressed after AUTOREPEAT_THRESHOLD usec, assume the | /* If no new key was pressed after AUTOREPEAT_THRESHOLD usec, assume the | ||||
@@ -198,10 +202,14 @@ static unsigned int _get_next_event(void) | |||||
static unsigned int _lowlevel_event(void) | static unsigned int _lowlevel_event(void) | ||||
{ | { | ||||
unsigned int event = _pop_event(); | |||||
unsigned int event; | |||||
#if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO) | |||||
event = _pop_event(); | |||||
if(event) | if(event) | ||||
return event; | return event; | ||||
#endif | |||||
#if defined(USE_X11) | #if defined(USE_X11) | ||||
/* The X11 event check routine */ | /* The X11 event check routine */ | ||||
@@ -540,6 +548,58 @@ static unsigned int _lowlevel_event(void) | |||||
#if defined(USE_WIN32) | #if defined(USE_WIN32) | ||||
if(_caca_driver == CACA_DRIVER_WIN32) | if(_caca_driver == CACA_DRIVER_WIN32) | ||||
{ | { | ||||
INPUT_RECORD rec; | |||||
DWORD num; | |||||
GetNumberOfConsoleInputEvents(win32_hin, &num); | |||||
if(num == 0) | |||||
return CACA_EVENT_NONE; | |||||
ReadConsoleInput(win32_hin, &rec, 1, &num); | |||||
if(rec.EventType == KEY_EVENT) | |||||
{ | |||||
if(rec.Event.KeyEvent.bKeyDown) | |||||
event = CACA_EVENT_KEY_PRESS; | |||||
else | |||||
event = CACA_EVENT_KEY_RELEASE; | |||||
if(rec.Event.KeyEvent.uChar.AsciiChar) | |||||
return event | rec.Event.KeyEvent.uChar.AsciiChar; | |||||
} | |||||
else if(rec.EventType == MOUSE_EVENT) | |||||
{ | |||||
if(rec.Event.MouseEvent.dwEventFlags == 0) | |||||
{ | |||||
if(rec.Event.MouseEvent.dwButtonState & 0x01) | |||||
return CACA_EVENT_MOUSE_PRESS | 0x000001; | |||||
if(rec.Event.MouseEvent.dwButtonState & 0x02) | |||||
return CACA_EVENT_MOUSE_PRESS | 0x000002; | |||||
} | |||||
else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_MOVED) | |||||
{ | |||||
return CACA_EVENT_MOUSE_MOTION | |||||
| (rec.Event.MouseEvent.dwMousePosition.X << 12) | |||||
| (rec.Event.MouseEvent.dwMousePosition.Y); | |||||
} | |||||
#if 0 | |||||
else if(rec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK) | |||||
{ | |||||
cout << rec.Event.MouseEvent.dwMousePosition.X << "," << | |||||
rec.Event.MouseEvent.dwMousePosition.Y << " " << flush; | |||||
} | |||||
else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_WHEELED) | |||||
{ | |||||
SetConsoleCursorPosition(hOut, | |||||
WheelWhere); | |||||
if(rec.Event.MouseEvent.dwButtonState & 0xFF000000) | |||||
cout << "Down" << flush; | |||||
else | |||||
cout << "Up " << flush; | |||||
} | |||||
#endif | |||||
} | |||||
return CACA_EVENT_NONE; | return CACA_EVENT_NONE; | ||||
} | } | ||||
else | else | ||||
@@ -551,6 +611,7 @@ static unsigned int _lowlevel_event(void) | |||||
return CACA_EVENT_NONE; | return CACA_EVENT_NONE; | ||||
} | } | ||||
#if defined(USE_SLANG) || defined(USE_NCURSES) || defined(USE_CONIO) | |||||
static void _push_event(unsigned int event) | static void _push_event(unsigned int event) | ||||
{ | { | ||||
if(events == EVENTBUF_LEN) | if(events == EVENTBUF_LEN) | ||||
@@ -574,4 +635,5 @@ static unsigned int _pop_event(void) | |||||
return event; | return event; | ||||
} | } | ||||
#endif | |||||
@@ -58,8 +58,8 @@ unsigned int _caca_getticks(struct caca_timer *timer) | |||||
#if defined(HAVE_GETTIMEOFDAY) | #if defined(HAVE_GETTIMEOFDAY) | ||||
struct timeval tv; | struct timeval tv; | ||||
#elif defined(USE_WIN32) | #elif defined(USE_WIN32) | ||||
static long long int freq = -1LL; | |||||
long long int usec; | |||||
static long long int freq = -1; | |||||
unsigned long long int usec; | |||||
#endif | #endif | ||||
unsigned int ticks = 0; | unsigned int ticks = 0; | ||||
int new_sec, new_usec; | int new_sec, new_usec; | ||||
@@ -69,15 +69,15 @@ unsigned int _caca_getticks(struct caca_timer *timer) | |||||
new_sec = tv.tv_sec; | new_sec = tv.tv_sec; | ||||
new_usec = tv.tv_usec; | new_usec = tv.tv_usec; | ||||
#elif defined(USE_WIN32) | #elif defined(USE_WIN32) | ||||
if(freq == -1LL) | |||||
if(freq == -1) | |||||
{ | { | ||||
if(!QueryPerformanceFrequency((LARGE_INTEGER *)&freq)) | if(!QueryPerformanceFrequency((LARGE_INTEGER *)&freq)) | ||||
freq = 0; | freq = 0; | ||||
} | } | ||||
QueryPerformanceCounter((LARGE_INTEGER *)&usec); | QueryPerformanceCounter((LARGE_INTEGER *)&usec); | ||||
new_sec = usec / freq; | |||||
new_usec = usec % freq; | |||||
new_sec = usec * 1000000 / freq / 1000000; | |||||
new_usec = (usec * 1000000 / freq) % 1000000; | |||||
#endif | #endif | ||||
if(timer->last_sec != 0) | if(timer->last_sec != 0) | ||||