| /* PDCurses */ |
| |
| #include "pdcwin.h" |
| |
| #include <stdlib.h> |
| #include <string.h> |
| |
| #ifdef PDC_WIDE |
| # include "../common/acsuni.h" |
| #else |
| # include "../common/acs437.h" |
| #endif |
| |
| DWORD pdc_last_blink; |
| static bool blinked_off = FALSE; |
| static bool in_italic = FALSE; |
| |
| /* position hardware cursor at (y, x) */ |
| |
| void PDC_gotoyx(int row, int col) |
| { |
| COORD coord; |
| |
| PDC_LOG(("PDC_gotoyx() - called: row %d col %d from row %d col %d\n", |
| row, col, SP->cursrow, SP->curscol)); |
| |
| coord.X = col; |
| coord.Y = row; |
| |
| SetConsoleCursorPosition(pdc_con_out, coord); |
| } |
| |
| void _set_ansi_color(short f, short b, attr_t attr) |
| { |
| char esc[64], *p; |
| short tmp, underline; |
| bool italic; |
| |
| if (f < 16 && !pdc_color[f].mapped) |
| f = pdc_curstoansi[f]; |
| |
| if (b < 16 && !pdc_color[b].mapped) |
| b = pdc_curstoansi[b]; |
| |
| if (attr & A_REVERSE) |
| { |
| tmp = f; |
| f = b; |
| b = tmp; |
| } |
| attr &= SP->termattrs; |
| italic = !!(attr & A_ITALIC); |
| underline = !!(attr & A_UNDERLINE); |
| |
| p = esc + sprintf(esc, "\x1b["); |
| |
| if (f != pdc_oldf) |
| { |
| if (f < 8 && !pdc_color[f].mapped) |
| p += sprintf(p, "%d", f + 30); |
| else if (f < 16 && !pdc_color[f].mapped) |
| p += sprintf(p, "%d", f + 82); |
| else if (f < 256 && !pdc_color[f].mapped) |
| p += sprintf(p, "38;5;%d", f); |
| else |
| { |
| short red = DIVROUND(pdc_color[f].r * 255, 1000); |
| short green = DIVROUND(pdc_color[f].g * 255, 1000); |
| short blue = DIVROUND(pdc_color[f].b * 255, 1000); |
| |
| p += sprintf(p, "38;2;%d;%d;%d", red, green, blue); |
| } |
| |
| pdc_oldf = f; |
| } |
| |
| if (b != pdc_oldb) |
| { |
| if (strlen(esc) > 2) |
| p += sprintf(p, ";"); |
| |
| if (b < 8 && !pdc_color[b].mapped) |
| p += sprintf(p, "%d", b + 40); |
| else if (b < 16 && !pdc_color[b].mapped) |
| p += sprintf(p, "%d", b + 92); |
| else if (b < 256 && !pdc_color[b].mapped) |
| p += sprintf(p, "48;5;%d", b); |
| else |
| { |
| short red = DIVROUND(pdc_color[b].r * 255, 1000); |
| short green = DIVROUND(pdc_color[b].g * 255, 1000); |
| short blue = DIVROUND(pdc_color[b].b * 255, 1000); |
| |
| p += sprintf(p, "48;2;%d;%d;%d", red, green, blue); |
| } |
| |
| pdc_oldb = b; |
| } |
| |
| if (italic != in_italic) |
| { |
| if (strlen(esc) > 2) |
| p += sprintf(p, ";"); |
| |
| if (italic) |
| p += sprintf(p, "3"); |
| else |
| p += sprintf(p, "23"); |
| |
| in_italic = italic; |
| } |
| |
| if (underline != pdc_oldu) |
| { |
| if (strlen(esc) > 2) |
| p += sprintf(p, ";"); |
| |
| if (underline) |
| p += sprintf(p, "4"); |
| else |
| p += sprintf(p, "24"); |
| |
| pdc_oldu = underline; |
| } |
| |
| if (strlen(esc) > 2) |
| { |
| sprintf(p, "m"); |
| if (!pdc_conemu) |
| SetConsoleMode(pdc_con_out, 0x0015); |
| |
| WriteConsoleA(pdc_con_out, esc, strlen(esc), NULL, NULL); |
| |
| if (!pdc_conemu) |
| SetConsoleMode(pdc_con_out, 0x0010); |
| } |
| } |
| |
| void _new_packet(attr_t attr, int lineno, int x, int len, const chtype *srcp) |
| { |
| int j; |
| short fore, back; |
| bool blink, ansi; |
| |
| if (pdc_ansi && (lineno == (SP->lines - 1)) && ((x + len) == SP->cols)) |
| { |
| len--; |
| if (len) |
| _new_packet(attr, lineno, x, len, srcp); |
| pdc_ansi = FALSE; |
| _new_packet(attr, lineno, x + len, 1, srcp + len); |
| pdc_ansi = TRUE; |
| return; |
| } |
| |
| pair_content(PAIR_NUMBER(attr), &fore, &back); |
| ansi = pdc_ansi || (fore >= 16 || back >= 16); |
| blink = (SP->termattrs & A_BLINK) && (attr & A_BLINK); |
| |
| if (blink) |
| { |
| attr &= ~A_BLINK; |
| if (blinked_off) |
| attr &= ~(A_UNDERLINE | A_RIGHT | A_LEFT); |
| } |
| |
| if (attr & A_BOLD) |
| fore |= 8; |
| if (attr & A_BLINK) |
| back |= 8; |
| |
| if (ansi) |
| { |
| #ifdef PDC_WIDE |
| WCHAR buffer[512]; |
| #else |
| char buffer[512]; |
| #endif |
| for (j = 0; j < len; j++) |
| { |
| chtype ch = srcp[j]; |
| |
| if (ch & A_ALTCHARSET && !(ch & 0xff80)) |
| { |
| ch = acs_map[ch & 0x7f]; |
| |
| if (pdc_wt && (ch & A_CHARTEXT) < ' ') |
| goto NONANSI; |
| } |
| |
| if (blink && blinked_off) |
| ch = ' '; |
| |
| buffer[j] = ch & A_CHARTEXT; |
| } |
| |
| PDC_gotoyx(lineno, x); |
| _set_ansi_color(fore, back, attr); |
| #ifdef PDC_WIDE |
| WriteConsoleW(pdc_con_out, buffer, len, NULL, NULL); |
| #else |
| WriteConsoleA(pdc_con_out, buffer, len, NULL, NULL); |
| #endif |
| } |
| else |
| NONANSI: |
| { |
| CHAR_INFO buffer[512]; |
| COORD bufSize, bufPos; |
| SMALL_RECT sr; |
| WORD mapped_attr; |
| |
| fore = pdc_curstoreal[fore]; |
| back = pdc_curstoreal[back]; |
| |
| if (attr & A_REVERSE) |
| mapped_attr = back | (fore << 4); |
| else |
| mapped_attr = fore | (back << 4); |
| |
| if (attr & A_UNDERLINE) |
| mapped_attr |= 0x8000; /* COMMON_LVB_UNDERSCORE */ |
| if (attr & A_LEFT) |
| mapped_attr |= 0x0800; /* COMMON_LVB_GRID_LVERTICAL */ |
| if (attr & A_RIGHT) |
| mapped_attr |= 0x1000; /* COMMON_LVB_GRID_RVERTICAL */ |
| |
| for (j = 0; j < len; j++) |
| { |
| chtype ch = srcp[j]; |
| |
| if (ch & A_ALTCHARSET && !(ch & 0xff80)) |
| ch = acs_map[ch & 0x7f]; |
| |
| if (blink && blinked_off) |
| ch = ' '; |
| |
| buffer[j].Attributes = mapped_attr; |
| buffer[j].Char.UnicodeChar = ch & A_CHARTEXT; |
| } |
| |
| bufPos.X = bufPos.Y = 0; |
| bufSize.X = len; |
| bufSize.Y = 1; |
| |
| sr.Top = sr.Bottom = lineno; |
| sr.Left = x; |
| sr.Right = x + len - 1; |
| |
| WriteConsoleOutput(pdc_con_out, buffer, bufSize, bufPos, &sr); |
| } |
| } |
| |
| /* update the given physical line to look like the corresponding line in |
| curscr */ |
| |
| void PDC_transform_line(int lineno, int x, int len, const chtype *srcp) |
| { |
| attr_t old_attr, attr; |
| int i, j; |
| |
| PDC_LOG(("PDC_transform_line() - called: lineno=%d\n", lineno)); |
| |
| old_attr = *srcp & (A_ATTRIBUTES ^ A_ALTCHARSET); |
| |
| for (i = 1, j = 1; j < len; i++, j++) |
| { |
| attr = srcp[i] & (A_ATTRIBUTES ^ A_ALTCHARSET); |
| |
| if (attr != old_attr) |
| { |
| _new_packet(old_attr, lineno, x, i, srcp); |
| old_attr = attr; |
| srcp += i; |
| x += i; |
| i = 0; |
| } |
| } |
| |
| _new_packet(old_attr, lineno, x, i, srcp); |
| } |
| |
| void PDC_blink_text(void) |
| { |
| CONSOLE_CURSOR_INFO cci; |
| int i, j, k; |
| bool oldvis; |
| |
| GetConsoleCursorInfo(pdc_con_out, &cci); |
| oldvis = cci.bVisible; |
| if (oldvis) |
| { |
| cci.bVisible = FALSE; |
| SetConsoleCursorInfo(pdc_con_out, &cci); |
| } |
| |
| if (!(SP->termattrs & A_BLINK)) |
| blinked_off = FALSE; |
| else |
| blinked_off = !blinked_off; |
| |
| for (i = 0; i < SP->lines; i++) |
| { |
| const chtype *srcp = curscr->_y[i]; |
| |
| for (j = 0; j < SP->cols; j++) |
| if (srcp[j] & A_BLINK) |
| { |
| k = j; |
| while (k < SP->cols && (srcp[k] & A_BLINK)) |
| k++; |
| PDC_transform_line(i, j, k - j, srcp + j); |
| j = k; |
| } |
| } |
| |
| PDC_gotoyx(SP->cursrow, SP->curscol); |
| if (oldvis) |
| { |
| cci.bVisible = TRUE; |
| SetConsoleCursorInfo(pdc_con_out, &cci); |
| } |
| |
| pdc_last_blink = GetTickCount(); |
| } |
| |
| void PDC_doupdate(void) |
| { |
| } |