pdcdisp.c 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329
  1. /* PDCurses */
  2. #include "pdcwin.h"
  3. #include <stdlib.h>
  4. #include <string.h>
  5. #ifdef PDC_WIDE
  6. # include "../common/acsuni.h"
  7. #else
  8. # include "../common/acs437.h"
  9. #endif
  10. DWORD pdc_last_blink;
  11. static bool blinked_off = FALSE;
  12. static bool in_italic = FALSE;
  13. /* position hardware cursor at (y, x) */
  14. void PDC_gotoyx(int row, int col)
  15. {
  16. COORD coord;
  17. PDC_LOG(("PDC_gotoyx() - called: row %d col %d from row %d col %d\n",
  18. row, col, SP->cursrow, SP->curscol));
  19. coord.X = col;
  20. coord.Y = row;
  21. SetConsoleCursorPosition(pdc_con_out, coord);
  22. }
  23. void _set_ansi_color(short f, short b, attr_t attr)
  24. {
  25. char esc[64], *p;
  26. short tmp, underline;
  27. bool italic;
  28. if (f < 16 && !pdc_color[f].mapped)
  29. f = pdc_curstoansi[f];
  30. if (b < 16 && !pdc_color[b].mapped)
  31. b = pdc_curstoansi[b];
  32. if (attr & A_REVERSE)
  33. {
  34. tmp = f;
  35. f = b;
  36. b = tmp;
  37. }
  38. attr &= SP->termattrs;
  39. italic = !!(attr & A_ITALIC);
  40. underline = !!(attr & A_UNDERLINE);
  41. p = esc + sprintf(esc, "\x1b[");
  42. if (f != pdc_oldf)
  43. {
  44. if (f < 8 && !pdc_color[f].mapped)
  45. p += sprintf(p, "%d", f + 30);
  46. else if (f < 16 && !pdc_color[f].mapped)
  47. p += sprintf(p, "%d", f + 82);
  48. else if (f < 256 && !pdc_color[f].mapped)
  49. p += sprintf(p, "38;5;%d", f);
  50. else
  51. {
  52. short red = DIVROUND(pdc_color[f].r * 255, 1000);
  53. short green = DIVROUND(pdc_color[f].g * 255, 1000);
  54. short blue = DIVROUND(pdc_color[f].b * 255, 1000);
  55. p += sprintf(p, "38;2;%d;%d;%d", red, green, blue);
  56. }
  57. pdc_oldf = f;
  58. }
  59. if (b != pdc_oldb)
  60. {
  61. if (strlen(esc) > 2)
  62. p += sprintf(p, ";");
  63. if (b < 8 && !pdc_color[b].mapped)
  64. p += sprintf(p, "%d", b + 40);
  65. else if (b < 16 && !pdc_color[b].mapped)
  66. p += sprintf(p, "%d", b + 92);
  67. else if (b < 256 && !pdc_color[b].mapped)
  68. p += sprintf(p, "48;5;%d", b);
  69. else
  70. {
  71. short red = DIVROUND(pdc_color[b].r * 255, 1000);
  72. short green = DIVROUND(pdc_color[b].g * 255, 1000);
  73. short blue = DIVROUND(pdc_color[b].b * 255, 1000);
  74. p += sprintf(p, "48;2;%d;%d;%d", red, green, blue);
  75. }
  76. pdc_oldb = b;
  77. }
  78. if (italic != in_italic)
  79. {
  80. if (strlen(esc) > 2)
  81. p += sprintf(p, ";");
  82. if (italic)
  83. p += sprintf(p, "3");
  84. else
  85. p += sprintf(p, "23");
  86. in_italic = italic;
  87. }
  88. if (underline != pdc_oldu)
  89. {
  90. if (strlen(esc) > 2)
  91. p += sprintf(p, ";");
  92. if (underline)
  93. p += sprintf(p, "4");
  94. else
  95. p += sprintf(p, "24");
  96. pdc_oldu = underline;
  97. }
  98. if (strlen(esc) > 2)
  99. {
  100. sprintf(p, "m");
  101. if (!pdc_conemu)
  102. SetConsoleMode(pdc_con_out, 0x0015);
  103. WriteConsoleA(pdc_con_out, esc, strlen(esc), NULL, NULL);
  104. if (!pdc_conemu)
  105. SetConsoleMode(pdc_con_out, 0x0010);
  106. }
  107. }
  108. void _new_packet(attr_t attr, int lineno, int x, int len, const chtype *srcp)
  109. {
  110. int j;
  111. short fore, back;
  112. bool blink, ansi;
  113. if (pdc_ansi && (lineno == (SP->lines - 1)) && ((x + len) == SP->cols))
  114. {
  115. len--;
  116. if (len)
  117. _new_packet(attr, lineno, x, len, srcp);
  118. pdc_ansi = FALSE;
  119. _new_packet(attr, lineno, x + len, 1, srcp + len);
  120. pdc_ansi = TRUE;
  121. return;
  122. }
  123. pair_content(PAIR_NUMBER(attr), &fore, &back);
  124. ansi = pdc_ansi || (fore >= 16 || back >= 16);
  125. blink = (SP->termattrs & A_BLINK) && (attr & A_BLINK);
  126. if (blink)
  127. {
  128. attr &= ~A_BLINK;
  129. if (blinked_off)
  130. attr &= ~(A_UNDERLINE | A_RIGHT | A_LEFT);
  131. }
  132. if (attr & A_BOLD)
  133. fore |= 8;
  134. if (attr & A_BLINK)
  135. back |= 8;
  136. if (ansi)
  137. {
  138. #ifdef PDC_WIDE
  139. WCHAR buffer[512];
  140. #else
  141. char buffer[512];
  142. #endif
  143. for (j = 0; j < len; j++)
  144. {
  145. chtype ch = srcp[j];
  146. if (ch & A_ALTCHARSET && !(ch & 0xff80))
  147. {
  148. ch = acs_map[ch & 0x7f];
  149. if (pdc_wt && (ch & A_CHARTEXT) < ' ')
  150. goto NONANSI;
  151. }
  152. if (blink && blinked_off)
  153. ch = ' ';
  154. buffer[j] = ch & A_CHARTEXT;
  155. }
  156. PDC_gotoyx(lineno, x);
  157. _set_ansi_color(fore, back, attr);
  158. #ifdef PDC_WIDE
  159. WriteConsoleW(pdc_con_out, buffer, len, NULL, NULL);
  160. #else
  161. WriteConsoleA(pdc_con_out, buffer, len, NULL, NULL);
  162. #endif
  163. }
  164. else
  165. NONANSI:
  166. {
  167. CHAR_INFO buffer[512];
  168. COORD bufSize, bufPos;
  169. SMALL_RECT sr;
  170. WORD mapped_attr;
  171. fore = pdc_curstoreal[fore];
  172. back = pdc_curstoreal[back];
  173. if (attr & A_REVERSE)
  174. mapped_attr = back | (fore << 4);
  175. else
  176. mapped_attr = fore | (back << 4);
  177. if (attr & A_UNDERLINE)
  178. mapped_attr |= 0x8000; /* COMMON_LVB_UNDERSCORE */
  179. if (attr & A_LEFT)
  180. mapped_attr |= 0x0800; /* COMMON_LVB_GRID_LVERTICAL */
  181. if (attr & A_RIGHT)
  182. mapped_attr |= 0x1000; /* COMMON_LVB_GRID_RVERTICAL */
  183. for (j = 0; j < len; j++)
  184. {
  185. chtype ch = srcp[j];
  186. if (ch & A_ALTCHARSET && !(ch & 0xff80))
  187. ch = acs_map[ch & 0x7f];
  188. if (blink && blinked_off)
  189. ch = ' ';
  190. buffer[j].Attributes = mapped_attr;
  191. buffer[j].Char.UnicodeChar = ch & A_CHARTEXT;
  192. }
  193. bufPos.X = bufPos.Y = 0;
  194. bufSize.X = len;
  195. bufSize.Y = 1;
  196. sr.Top = sr.Bottom = lineno;
  197. sr.Left = x;
  198. sr.Right = x + len - 1;
  199. WriteConsoleOutput(pdc_con_out, buffer, bufSize, bufPos, &sr);
  200. }
  201. }
  202. /* update the given physical line to look like the corresponding line in
  203. curscr */
  204. void PDC_transform_line(int lineno, int x, int len, const chtype *srcp)
  205. {
  206. attr_t old_attr, attr;
  207. int i, j;
  208. PDC_LOG(("PDC_transform_line() - called: lineno=%d\n", lineno));
  209. old_attr = *srcp & (A_ATTRIBUTES ^ A_ALTCHARSET);
  210. for (i = 1, j = 1; j < len; i++, j++)
  211. {
  212. attr = srcp[i] & (A_ATTRIBUTES ^ A_ALTCHARSET);
  213. if (attr != old_attr)
  214. {
  215. _new_packet(old_attr, lineno, x, i, srcp);
  216. old_attr = attr;
  217. srcp += i;
  218. x += i;
  219. i = 0;
  220. }
  221. }
  222. _new_packet(old_attr, lineno, x, i, srcp);
  223. }
  224. void PDC_blink_text(void)
  225. {
  226. CONSOLE_CURSOR_INFO cci;
  227. int i, j, k;
  228. bool oldvis;
  229. GetConsoleCursorInfo(pdc_con_out, &cci);
  230. oldvis = cci.bVisible;
  231. if (oldvis)
  232. {
  233. cci.bVisible = FALSE;
  234. SetConsoleCursorInfo(pdc_con_out, &cci);
  235. }
  236. if (!(SP->termattrs & A_BLINK))
  237. blinked_off = FALSE;
  238. else
  239. blinked_off = !blinked_off;
  240. for (i = 0; i < SP->lines; i++)
  241. {
  242. const chtype *srcp = curscr->_y[i];
  243. for (j = 0; j < SP->cols; j++)
  244. if (srcp[j] & A_BLINK)
  245. {
  246. k = j;
  247. while (k < SP->cols && (srcp[k] & A_BLINK))
  248. k++;
  249. PDC_transform_line(i, j, k - j, srcp + j);
  250. j = k;
  251. }
  252. }
  253. PDC_gotoyx(SP->cursrow, SP->curscol);
  254. if (oldvis)
  255. {
  256. cci.bVisible = TRUE;
  257. SetConsoleCursorInfo(pdc_con_out, &cci);
  258. }
  259. pdc_last_blink = GetTickCount();
  260. }
  261. void PDC_doupdate(void)
  262. {
  263. }