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.

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