/* PDCurses */ #include "pdcwin.h" #include #include #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) { }