Você não pode selecionar mais de 25 tópicos Os tópicos devem começar com uma letra ou um número, podem incluir traços ('-') e podem ter até 35 caracteres.

driver_win32.c 10 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /*
  2. * libcaca Colour ASCII-Art library
  3. * Copyright (c) 2002-2006 Sam Hocevar <sam@zoy.org>
  4. * All Rights Reserved
  5. *
  6. * $Id$
  7. *
  8. * This library is free software; you can redistribute it and/or
  9. * modify it under the terms of the Do What The Fuck You Want To
  10. * Public License, Version 2, as published by Sam Hocevar. See
  11. * http://sam.zoy.org/wtfpl/COPYING for more details.
  12. */
  13. /*
  14. * This file contains the libcaca Win32 input and output driver
  15. */
  16. #include "config.h"
  17. #include "common.h"
  18. #if defined(USE_WIN32)
  19. #include <windows.h>
  20. #include <stdlib.h>
  21. #include <stdio.h>
  22. #include "caca.h"
  23. #include "caca_internals.h"
  24. #include "cucul.h"
  25. #include "cucul_internals.h"
  26. /*
  27. * Global variables
  28. */
  29. static int const win32_fg_palette[] =
  30. {
  31. 0,
  32. FOREGROUND_BLUE,
  33. FOREGROUND_GREEN,
  34. FOREGROUND_GREEN | FOREGROUND_BLUE,
  35. FOREGROUND_RED,
  36. FOREGROUND_RED | FOREGROUND_BLUE,
  37. FOREGROUND_RED | FOREGROUND_GREEN,
  38. FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE,
  39. FOREGROUND_INTENSITY,
  40. FOREGROUND_INTENSITY | FOREGROUND_BLUE,
  41. FOREGROUND_INTENSITY | FOREGROUND_GREEN,
  42. FOREGROUND_INTENSITY | FOREGROUND_GREEN | FOREGROUND_BLUE,
  43. FOREGROUND_INTENSITY | FOREGROUND_RED,
  44. FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_BLUE,
  45. FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN,
  46. FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE
  47. };
  48. static int const win32_bg_palette[] =
  49. {
  50. 0,
  51. BACKGROUND_BLUE,
  52. BACKGROUND_GREEN,
  53. BACKGROUND_GREEN | BACKGROUND_BLUE,
  54. BACKGROUND_RED,
  55. BACKGROUND_RED | BACKGROUND_BLUE,
  56. BACKGROUND_RED | BACKGROUND_GREEN,
  57. BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE,
  58. BACKGROUND_INTENSITY,
  59. BACKGROUND_INTENSITY | BACKGROUND_BLUE,
  60. BACKGROUND_INTENSITY | BACKGROUND_GREEN,
  61. BACKGROUND_INTENSITY | BACKGROUND_GREEN | BACKGROUND_BLUE,
  62. BACKGROUND_INTENSITY | BACKGROUND_RED,
  63. BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_BLUE,
  64. BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN,
  65. BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN | BACKGROUND_BLUE
  66. };
  67. struct driver_private
  68. {
  69. HANDLE hin, hout, screen;
  70. CHAR_INFO *buffer;
  71. CONSOLE_CURSOR_INFO cci;
  72. };
  73. static int win32_init_graphics(caca_display_t *dp)
  74. {
  75. CONSOLE_SCREEN_BUFFER_INFO csbi;
  76. SMALL_RECT rect;
  77. COORD size;
  78. dp->drv.p = malloc(sizeof(struct driver_private));
  79. /* This call is allowed to fail in case we already have a console */
  80. AllocConsole();
  81. dp->drv.p->hin = GetStdHandle(STD_INPUT_HANDLE);
  82. dp->drv.p->hout = CreateFile("CONOUT$", GENERIC_READ | GENERIC_WRITE,
  83. FILE_SHARE_READ | FILE_SHARE_WRITE, NULL,
  84. OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  85. if(dp->drv.p->hout == INVALID_HANDLE_VALUE)
  86. return -1;
  87. GetConsoleCursorInfo(dp->drv.p->hout, &dp->drv.p->cci);
  88. dp->drv.p->cci.bVisible = FALSE;
  89. SetConsoleCursorInfo(dp->drv.p->hout, &dp->drv.p->cci);
  90. SetConsoleMode(dp->drv.p->hout, ENABLE_MOUSE_INPUT);
  91. dp->drv.p->screen =
  92. CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
  93. 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
  94. if(!dp->drv.p->screen || dp->drv.p->screen == INVALID_HANDLE_VALUE)
  95. return -1;
  96. /* Set the new console size */
  97. size.X = dp->cv->width ? dp->cv->width : 80;
  98. size.Y = dp->cv->height ? dp->cv->height : 25;
  99. SetConsoleScreenBufferSize(dp->drv.p->screen, size);
  100. rect.Left = rect.Top = 0;
  101. rect.Right = dp->cv->width - 1;
  102. rect.Bottom = dp->cv->height - 1;
  103. SetConsoleWindowInfo(dp->drv.p->screen, TRUE, &rect);
  104. /* Report our new size to libcucul */
  105. if(!GetConsoleScreenBufferInfo(dp->drv.p->screen, &csbi))
  106. return -1;
  107. _cucul_set_canvas_size(dp->cv, csbi.srWindow.Right - csbi.srWindow.Left + 1,
  108. csbi.srWindow.Bottom - csbi.srWindow.Top + 1);
  109. SetConsoleMode(dp->drv.p->screen, 0);
  110. GetConsoleCursorInfo(dp->drv.p->screen, &dp->drv.p->cci);
  111. dp->drv.p->cci.dwSize = 0;
  112. dp->drv.p->cci.bVisible = FALSE;
  113. SetConsoleCursorInfo(dp->drv.p->screen, &dp->drv.p->cci);
  114. SetConsoleActiveScreenBuffer(dp->drv.p->screen);
  115. dp->drv.p->buffer = malloc(dp->cv->width * dp->cv->height
  116. * sizeof(CHAR_INFO));
  117. if(dp->drv.p->buffer == NULL)
  118. return -1;
  119. return 0;
  120. }
  121. static int win32_end_graphics(caca_display_t *dp)
  122. {
  123. SetConsoleActiveScreenBuffer(dp->drv.p->hout);
  124. CloseHandle(dp->drv.p->screen);
  125. SetConsoleTextAttribute(dp->drv.p->hout, FOREGROUND_INTENSITY
  126. | FOREGROUND_RED
  127. | FOREGROUND_GREEN
  128. | FOREGROUND_BLUE);
  129. dp->drv.p->cci.bVisible = TRUE;
  130. SetConsoleCursorInfo(dp->drv.p->hout, &dp->drv.p->cci);
  131. CloseHandle(dp->drv.p->hout);
  132. free(dp->drv.p);
  133. return 0;
  134. }
  135. static int win32_set_display_title(caca_display_t *dp, char const *title)
  136. {
  137. SetConsoleTitle(title);
  138. return 0;
  139. }
  140. static unsigned int win32_get_display_width(caca_display_t *dp)
  141. {
  142. /* FIXME */
  143. /* Fallback to a 6x10 font */
  144. return dp->cv->width * 6;
  145. }
  146. static unsigned int win32_get_display_height(caca_display_t *dp)
  147. {
  148. /* FIXME */
  149. /* Fallback to a 6x10 font */
  150. return dp->cv->height * 10;
  151. }
  152. static void win32_display(caca_display_t *dp)
  153. {
  154. COORD size, pos;
  155. SMALL_RECT rect;
  156. CHAR_INFO *buffer = dp->drv.p->buffer;
  157. uint32_t *attrs = dp->cv->attrs;
  158. uint32_t *chars = dp->cv->chars;
  159. unsigned int n;
  160. /* Render everything to our screen buffer */
  161. for(n = dp->cv->height * dp->cv->width; n--; )
  162. {
  163. uint32_t ch = *chars++;
  164. #if 0
  165. if(ch > 0x00000020 && ch < 0x00000080)
  166. dp->drv.p->buffer[i].Char.AsciiChar = (uint8_t)ch;
  167. else
  168. dp->drv.p->buffer[i].Char.AsciiChar = ' ';
  169. #else
  170. if(n && *chars == CUCUL_MAGIC_FULLWIDTH)
  171. ;
  172. else if(ch > 0x00000020 && ch < 0x00010000)
  173. buffer->Char.UnicodeChar = (uint16_t)ch;
  174. else
  175. buffer->Char.UnicodeChar = (uint16_t)' ';
  176. #endif
  177. buffer->Attributes =
  178. win32_fg_palette[_cucul_attr_to_ansi4fg(*attrs)]
  179. | win32_bg_palette[_cucul_attr_to_ansi4bg(*attrs)];
  180. attrs++;
  181. buffer++;
  182. }
  183. /* Blit the screen buffer */
  184. size.X = dp->cv->width;
  185. size.Y = dp->cv->height;
  186. pos.X = pos.Y = 0;
  187. rect.Left = rect.Top = 0;
  188. rect.Right = dp->cv->width - 1;
  189. rect.Bottom = dp->cv->height - 1;
  190. #if 0
  191. WriteConsoleOutput(dp->drv.p->screen, dp->drv.p->buffer, size, pos, &rect);
  192. #else
  193. WriteConsoleOutputW(dp->drv.p->screen, dp->drv.p->buffer, size, pos, &rect);
  194. #endif
  195. }
  196. static void win32_handle_resize(caca_display_t *dp)
  197. {
  198. /* FIXME: I don't know what to do here. */
  199. dp->resize.w = dp->cv->width;
  200. dp->resize.h = dp->cv->height;
  201. }
  202. static int win32_get_event(caca_display_t *dp, caca_event_t *ev)
  203. {
  204. INPUT_RECORD rec;
  205. DWORD num;
  206. for( ; ; )
  207. {
  208. GetNumberOfConsoleInputEvents(dp->drv.p->hin, &num);
  209. if(num == 0)
  210. break;
  211. ReadConsoleInput(dp->drv.p->hin, &rec, 1, &num);
  212. if(rec.EventType == KEY_EVENT)
  213. {
  214. if(rec.Event.KeyEvent.bKeyDown)
  215. ev->type = CACA_EVENT_KEY_PRESS;
  216. else
  217. ev->type = CACA_EVENT_KEY_RELEASE;
  218. if(rec.Event.KeyEvent.uChar.AsciiChar)
  219. {
  220. ev->data.key.ch = rec.Event.KeyEvent.uChar.AsciiChar;
  221. ev->data.key.utf32 = (uint32_t)ev->data.key.ch;
  222. ev->data.key.utf8[0] = ev->data.key.ch;
  223. ev->data.key.utf8[1] = '\0';
  224. return 1;
  225. }
  226. }
  227. if(rec.EventType == MOUSE_EVENT)
  228. {
  229. if(rec.Event.MouseEvent.dwEventFlags == 0)
  230. {
  231. if(rec.Event.MouseEvent.dwButtonState & 0x01)
  232. {
  233. ev->type = CACA_EVENT_MOUSE_PRESS;
  234. ev->data.mouse.button = 1;
  235. return 1;
  236. }
  237. if(rec.Event.MouseEvent.dwButtonState & 0x02)
  238. {
  239. ev->type = CACA_EVENT_MOUSE_PRESS;
  240. ev->data.mouse.button = 2;
  241. return 1;
  242. }
  243. }
  244. else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_MOVED)
  245. {
  246. COORD pos = rec.Event.MouseEvent.dwMousePosition;
  247. if(dp->mouse.x == (unsigned int)pos.X &&
  248. dp->mouse.y == (unsigned int)pos.Y)
  249. continue;
  250. dp->mouse.x = pos.X;
  251. dp->mouse.y = pos.Y;
  252. ev->type = CACA_EVENT_MOUSE_MOTION;
  253. ev->data.mouse.x = dp->mouse.x;
  254. ev->data.mouse.y = dp->mouse.y;
  255. return 1;
  256. }
  257. #if 0
  258. else if(rec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK)
  259. {
  260. cout << rec.Event.MouseEvent.dwMousePosition.X << "," <<
  261. rec.Event.MouseEvent.dwMousePosition.Y << " " << flush;
  262. }
  263. else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_WHEELED)
  264. {
  265. SetConsoleCursorPosition(hOut,
  266. WheelWhere);
  267. if(rec.Event.MouseEvent.dwButtonState & 0xFF000000)
  268. cout << "Down" << flush;
  269. else
  270. cout << "Up " << flush;
  271. }
  272. #endif
  273. }
  274. /* Unknown event */
  275. ev->type = CACA_EVENT_NONE;
  276. return 0;
  277. }
  278. /* No event */
  279. ev->type = CACA_EVENT_NONE;
  280. return 0;
  281. }
  282. /*
  283. * Driver initialisation
  284. */
  285. int win32_install(caca_display_t *dp)
  286. {
  287. dp->drv.driver = CACA_DRIVER_WIN32;
  288. dp->drv.init_graphics = win32_init_graphics;
  289. dp->drv.end_graphics = win32_end_graphics;
  290. dp->drv.set_display_title = win32_set_display_title;
  291. dp->drv.get_display_width = win32_get_display_width;
  292. dp->drv.get_display_height = win32_get_display_height;
  293. dp->drv.display = win32_display;
  294. dp->drv.handle_resize = win32_handle_resize;
  295. dp->drv.get_event = win32_get_event;
  296. dp->drv.set_mouse = NULL;
  297. return 0;
  298. }
  299. #endif /* USE_WIN32 */