Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.
 
 
 
 
 
 

365 rindas
10 KiB

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