You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

преди 19 години
преди 19 години
преди 19 години
преди 19 години
преди 19 години
преди 19 години
преди 19 години
преди 19 години
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335
  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. /** \file driver_win32.c
  12. * \version \$Id$
  13. * \author Sam Hocevar <sam@zoy.org>
  14. * \brief Win32 driver
  15. *
  16. * This file contains the libcaca Win32 input and output driver
  17. */
  18. #include "config.h"
  19. #if defined(USE_WIN32)
  20. #include <windows.h>
  21. #include <stdlib.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;
  70. HANDLE front, back;
  71. CHAR_INFO *buffer;
  72. CONSOLE_CURSOR_INFO cci;
  73. };
  74. static int win32_init_graphics(caca_t *kk)
  75. {
  76. CONSOLE_SCREEN_BUFFER_INFO csbi;
  77. COORD size;
  78. kk->drv.p = malloc(sizeof(struct driver_private));
  79. /* This call is allowed to fail in case we already have a console */
  80. AllocConsole();
  81. kk->drv.p->hin = GetStdHandle(STD_INPUT_HANDLE);
  82. kk->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(kk->drv.p->hout == INVALID_HANDLE_VALUE)
  86. return -1;
  87. GetConsoleCursorInfo(kk->drv.p->hout, &kk->drv.p->cci);
  88. kk->drv.p->cci.bVisible = FALSE;
  89. SetConsoleCursorInfo(kk->drv.p->hout, &kk->drv.p->cci);
  90. SetConsoleMode(kk->drv.p->hout, ENABLE_MOUSE_INPUT);
  91. kk->drv.p->front =
  92. CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
  93. 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
  94. if(!kk->drv.p->front || kk->drv.p->front == INVALID_HANDLE_VALUE)
  95. return -1;
  96. kk->drv.p->back =
  97. CreateConsoleScreenBuffer(GENERIC_READ | GENERIC_WRITE,
  98. 0, NULL, CONSOLE_TEXTMODE_BUFFER, NULL);
  99. if(!kk->drv.p->back || kk->drv.p->back == INVALID_HANDLE_VALUE)
  100. return -1;
  101. if(!GetConsoleScreenBufferInfo(kk->drv.p->hout, &csbi))
  102. return -1;
  103. /* Sample code to get the biggest possible window */
  104. //size = GetLargestConsoleWindowSize(kk->drv.p->hout);
  105. _cucul_set_size(kk->qq, csbi.srWindow.Right - csbi.srWindow.Left + 1,
  106. csbi.srWindow.Bottom - csbi.srWindow.Top + 1);
  107. size.X = kk->qq->width;
  108. size.Y = kk->qq->height;
  109. SetConsoleScreenBufferSize(kk->drv.p->front, size);
  110. SetConsoleScreenBufferSize(kk->drv.p->back, size);
  111. SetConsoleMode(kk->drv.p->front, 0);
  112. SetConsoleMode(kk->drv.p->back, 0);
  113. GetConsoleCursorInfo(kk->drv.p->front, &kk->drv.p->cci);
  114. kk->drv.p->cci.dwSize = 0;
  115. kk->drv.p->cci.bVisible = FALSE;
  116. SetConsoleCursorInfo(kk->drv.p->front, &kk->drv.p->cci);
  117. SetConsoleCursorInfo(kk->drv.p->back, &kk->drv.p->cci);
  118. SetConsoleActiveScreenBuffer(kk->drv.p->front);
  119. kk->drv.p->buffer = malloc(kk->qq->width * kk->qq->height
  120. * sizeof(CHAR_INFO));
  121. if(kk->drv.p->buffer == NULL)
  122. return -1;
  123. return 0;
  124. }
  125. static int win32_end_graphics(caca_t *kk)
  126. {
  127. SetConsoleActiveScreenBuffer(kk->drv.p->hout);
  128. CloseHandle(kk->drv.p->back);
  129. CloseHandle(kk->drv.p->front);
  130. SetConsoleTextAttribute(kk->drv.p->hout, FOREGROUND_INTENSITY
  131. | FOREGROUND_RED
  132. | FOREGROUND_GREEN
  133. | FOREGROUND_BLUE);
  134. kk->drv.p->cci.bVisible = TRUE;
  135. SetConsoleCursorInfo(kk->drv.p->hout, &kk->drv.p->cci);
  136. CloseHandle(kk->drv.p->hout);
  137. free(kk->drv.p);
  138. return 0;
  139. }
  140. static int win32_set_window_title(caca_t *kk, char const *title)
  141. {
  142. SetConsoleTitle(title);
  143. return 0;
  144. }
  145. static unsigned int win32_get_window_width(caca_t *kk)
  146. {
  147. /* FIXME */
  148. /* Fallback to a 6x10 font */
  149. return kk->qq->width * 6;
  150. }
  151. static unsigned int win32_get_window_height(caca_t *kk)
  152. {
  153. /* FIXME */
  154. /* Fallback to a 6x10 font */
  155. return kk->qq->height * 10;
  156. }
  157. static void win32_display(caca_t *kk)
  158. {
  159. COORD size, pos;
  160. SMALL_RECT rect;
  161. unsigned int i;
  162. /* Render everything to our back buffer */
  163. for(i = 0; i < kk->qq->width * kk->qq->height; i++)
  164. {
  165. uint32_t c = kk->qq->chars[i];
  166. #if 0
  167. if(c > 0x00000020 && c < 0x00000080)
  168. kk->drv.p->buffer[i].Char.AsciiChar = (uint8_t)c;
  169. else
  170. kk->drv.p->buffer[i].Char.AsciiChar = ' ';
  171. #else
  172. if(c > 0x00000020 && c < 0x00010000)
  173. kk->drv.p->buffer[i].Char.UnicodeChar = (uint16_t)c;
  174. else
  175. kk->drv.p->buffer[i].Char.UnicodeChar = (uint16_t)' ';
  176. #endif
  177. kk->drv.p->buffer[i].Attributes =
  178. win32_fg_palette[kk->qq->attr[i] & 0xf]
  179. | win32_bg_palette[kk->qq->attr[i] >> 4];
  180. }
  181. /* Blit the back buffer to the front buffer */
  182. size.X = kk->qq->width;
  183. size.Y = kk->qq->height;
  184. pos.X = pos.Y = 0;
  185. rect.Left = rect.Top = 0;
  186. rect.Right = kk->qq->width - 1;
  187. rect.Bottom = kk->qq->height - 1;
  188. #if 0
  189. WriteConsoleOutput(kk->drv.p->front, kk->drv.p->buffer, size, pos, &rect);
  190. #else
  191. WriteConsoleOutputW(kk->drv.p->front, kk->drv.p->buffer, size, pos, &rect);
  192. #endif
  193. }
  194. static void win32_handle_resize(caca_t *kk)
  195. {
  196. /* FIXME: I don't know what to do here. */
  197. kk->resize.w = kk->qq->width;
  198. kk->resize.h = kk->qq->height;
  199. }
  200. static unsigned int win32_get_event(caca_t *kk)
  201. {
  202. INPUT_RECORD rec;
  203. DWORD num;
  204. for( ; ; )
  205. {
  206. GetNumberOfConsoleInputEvents(kk->drv.p->hin, &num);
  207. if(num == 0)
  208. break;
  209. ReadConsoleInput(kk->drv.p->hin, &rec, 1, &num);
  210. if(rec.EventType == KEY_EVENT)
  211. {
  212. unsigned int event;
  213. if(rec.Event.KeyEvent.bKeyDown)
  214. event = CACA_EVENT_KEY_PRESS;
  215. else
  216. event = CACA_EVENT_KEY_RELEASE;
  217. if(rec.Event.KeyEvent.uChar.AsciiChar)
  218. return event | rec.Event.KeyEvent.uChar.AsciiChar;
  219. }
  220. if(rec.EventType == MOUSE_EVENT)
  221. {
  222. if(rec.Event.MouseEvent.dwEventFlags == 0)
  223. {
  224. if(rec.Event.MouseEvent.dwButtonState & 0x01)
  225. return CACA_EVENT_MOUSE_PRESS | 0x000001;
  226. if(rec.Event.MouseEvent.dwButtonState & 0x02)
  227. return CACA_EVENT_MOUSE_PRESS | 0x000002;
  228. }
  229. else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_MOVED)
  230. {
  231. COORD pos = rec.Event.MouseEvent.dwMousePosition;
  232. if(kk->mouse.x == (unsigned int)pos.X &&
  233. kk->mouse.y == (unsigned int)pos.Y)
  234. continue;
  235. kk->mouse.x = pos.X;
  236. kk->mouse.y = pos.Y;
  237. return CACA_EVENT_MOUSE_MOTION
  238. | (kk->mouse.x << 12) | kk->mouse.y;
  239. }
  240. #if 0
  241. else if(rec.Event.MouseEvent.dwEventFlags == DOUBLE_CLICK)
  242. {
  243. cout << rec.Event.MouseEvent.dwMousePosition.X << "," <<
  244. rec.Event.MouseEvent.dwMousePosition.Y << " " << flush;
  245. }
  246. else if(rec.Event.MouseEvent.dwEventFlags == MOUSE_WHEELED)
  247. {
  248. SetConsoleCursorPosition(hOut,
  249. WheelWhere);
  250. if(rec.Event.MouseEvent.dwButtonState & 0xFF000000)
  251. cout << "Down" << flush;
  252. else
  253. cout << "Up " << flush;
  254. }
  255. #endif
  256. }
  257. /* Unknown event */
  258. return CACA_EVENT_NONE;
  259. }
  260. /* No event */
  261. return CACA_EVENT_NONE;
  262. }
  263. /*
  264. * Driver initialisation
  265. */
  266. void win32_init_driver(caca_t *kk)
  267. {
  268. kk->drv.driver = CACA_DRIVER_WIN32;
  269. kk->drv.init_graphics = win32_init_graphics;
  270. kk->drv.end_graphics = win32_end_graphics;
  271. kk->drv.set_window_title = win32_set_window_title;
  272. kk->drv.get_window_width = win32_get_window_width;
  273. kk->drv.get_window_height = win32_get_window_height;
  274. kk->drv.display = win32_display;
  275. kk->drv.handle_resize = win32_handle_resize;
  276. kk->drv.get_event = win32_get_event;
  277. }
  278. #endif /* USE_WIN32 */