void TextConsoleViewer::view() { #ifdef _WIN32 int topline, leftpos; leftpos = topline = 0; INPUT_RECORD ir; HANDLE hCon = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE hConI = CreateFile("CONIN$", GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0); if (hConI == INVALID_HANDLE_VALUE) return; SetConsoleMode(hConI, ENABLE_MOUSE_INPUT|ENABLE_WINDOW_INPUT); CONSOLE_SCREEN_BUFFER_INFO csbi; hCon = CreateConsoleScreenBuffer(GENERIC_WRITE|GENERIC_READ, 0, 0, CONSOLE_TEXTMODE_BUFFER, 0); SetConsoleActiveScreenBuffer(hCon); GetConsoleScreenBufferInfo(hCon, &csbi); CONSOLE_CURSOR_INFO cci; cci.dwSize = 100; cci.bVisible = FALSE; SetConsoleCursorInfo(hCon, &cci); CHAR_INFO *buffer = new CHAR_INFO[csbi.dwSize.X * csbi.dwSize.Y]; bool unc_fault = false; do { int lline = csbi.dwSize.Y; if (topline+lline > textLinesStore->getLineCount()) lline = textLinesStore->getLineCount()-topline; baseEditor->visibleTextEvent(topline, lline); for(int i = topline; i < topline + csbi.dwSize.Y; i++) { int Y = i-topline; int li; for(li = 0; li < csbi.dwSize.X; li++) { buffer[Y*csbi.dwSize.X + li].Char.UnicodeChar = ' '; buffer[Y*csbi.dwSize.X + li].Attributes = background; }; if (i >= textLinesStore->getLineCount()) continue; DString iLine = textLinesStore->getLine(i); for(li = 0; li < csbi.dwSize.X; li++) { if (leftpos+li >= iLine.length()) break; buffer[Y*csbi.dwSize.X + li].Char.UnicodeChar = iLine[leftpos+li]; if (unc_fault) buffer[Y*csbi.dwSize.X + li].Char.AsciiChar = Encodings::toChar(encoding, iLine[leftpos+li]); }; for(LineRegion *l1 = baseEditor->getLineRegions(i); l1 != null; l1 = l1->next) { if (l1->special || l1->rdef == null) continue; int end = l1->end; if (end == -1) end = iLine.length(); int X = l1->start - leftpos; int len = end - l1->start; if (X < 0) { len += X; X = 0; }; if (len < 0 || X >= csbi.dwSize.X) continue; if (len+X > csbi.dwSize.X) len = csbi.dwSize.X-X; WORD color = (WORD)(l1->styled()->fore + (l1->styled()->back<<4)); if (!l1->styled()->bfore) color = (color&0xF0) + (background&0xF); if (!l1->styled()->bback) color = (color&0xF) + (background&0xF0); for(int li = 0; li < len; li++) buffer[Y*csbi.dwSize.X + X + li].Attributes = color; }; }; COORD coor; coor.X = coor.Y = 0; SMALL_RECT sr; sr.Left = 0; sr.Right = csbi.dwSize.X-1; sr.Top = 0; sr.Bottom = csbi.dwSize.Y-1; if (!unc_fault && !WriteConsoleOutputW(hCon, buffer, csbi.dwSize, coor, &sr)) { unc_fault = true; continue; }; if (unc_fault) WriteConsoleOutputA(hCon, buffer, csbi.dwSize, coor, &sr); // managing the keyboard do { DWORD tmp; ReadConsoleInput(hConI, &ir, 1, &tmp); if (ir.EventType == WINDOW_BUFFER_SIZE_EVENT) { GetConsoleScreenBufferInfo(hCon, &csbi); delete[] buffer; buffer = new CHAR_INFO[csbi.dwSize.X * csbi.dwSize.Y]; break; }; if (ir.EventType == MOUSE_EVENT && ir.Event.MouseEvent.dwEventFlags == 0x4) { switch(ir.Event.MouseEvent.dwButtonState) { case 0x780000: topline-=csbi.dwSize.Y; if (topline < 0) topline = 0; break; case 0xFF880000: topline += csbi.dwSize.Y; if (topline > textLinesStore->getLineCount() - csbi.dwSize.Y) topline = textLinesStore->getLineCount() - csbi.dwSize.Y; if (topline < 0) topline = 0; break; }; break; }; if (ir.EventType == KEY_EVENT && ir.Event.KeyEvent.bKeyDown) { // moving view position switch(ir.Event.KeyEvent.wVirtualKeyCode) { case VK_UP: if (topline) topline--; break; case VK_DOWN: if (topline+csbi.dwSize.Y < textLinesStore->getLineCount()) topline++; break; case VK_LEFT: leftpos--; if (ir.Event.KeyEvent.dwControlKeyState & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)) leftpos -= 15; if (leftpos < 0) leftpos = 0; break; case VK_RIGHT: leftpos++; if (ir.Event.KeyEvent.dwControlKeyState & (RIGHT_CTRL_PRESSED|LEFT_CTRL_PRESSED)) leftpos += 15; break; case VK_PRIOR: topline-=csbi.dwSize.Y; if (topline < 0) topline = 0; break; case VK_NEXT: case VK_SPACE: topline += csbi.dwSize.Y; if (topline > textLinesStore->getLineCount() - csbi.dwSize.Y) topline = textLinesStore->getLineCount() - csbi.dwSize.Y; if (topline < 0) topline = 0; break; case VK_HOME: leftpos = topline = 0; break; case VK_END: topline = textLinesStore->getLineCount()-csbi.dwSize.Y; if (topline < 0) topline = 0; leftpos = 0; break; }; break; }; } while(true); } while(ir.Event.KeyEvent.wVirtualKeyCode != VK_ESCAPE); delete[] buffer; SetConsoleActiveScreenBuffer(GetStdHandle(STD_OUTPUT_HANDLE)); CloseHandle(hCon); #else printf("unix edition doesn't support interactive text viewing\n\n"); for(int i = 0; i < textLinesStore->getLineCount(); i++) { DString line = textLinesStore->getLine(i); printf("%s\n", line.getChars()); }; #endif };
static void win32_display(caca_display_t *dp) { COORD size, pos; SMALL_RECT rect; CHAR_INFO *buffer = dp->drv.p->buffer; uint32_t const *cvchars = caca_get_canvas_chars(dp->cv); uint32_t const *cvattrs = caca_get_canvas_attrs(dp->cv); int width = caca_get_canvas_width(dp->cv); int height = caca_get_canvas_height(dp->cv); int n; /* Render everything to our screen buffer */ for(n = height * width; n--; ) { uint32_t ch = *cvchars++; uint16_t bgfg = caca_attr_to_ansi(*cvattrs); uint8_t fg = bgfg & 0xf; uint8_t bg = bgfg >> 4; #if 0 if(ch > 0x00000020 && ch < 0x00000080) dp->drv.p->buffer[i].Char.AsciiChar = (uint8_t)ch; else dp->drv.p->buffer[i].Char.AsciiChar = ' '; #else if(n && *cvchars == CACA_MAGIC_FULLWIDTH) ; else if(ch > 0x00000020 && ch < 0x00010000) buffer->Char.UnicodeChar = (uint16_t)ch; else buffer->Char.UnicodeChar = (uint16_t)' '; #endif buffer->Attributes = win32_fg_palette[fg < 0x10 ? fg : CACA_LIGHTGRAY] | win32_bg_palette[bg < 0x10 ? bg : CACA_BLACK]; cvattrs++; buffer++; } /* Blit the screen buffer */ size.X = width; size.Y = height; pos.X = pos.Y = 0; rect.Left = rect.Top = 0; rect.Right = width - 1; rect.Bottom = height - 1; #if 0 WriteConsoleOutput(dp->drv.p->screen, dp->drv.p->buffer, size, pos, &rect); #else /* FIXME: would this benefit from dirty rectangles? */ WriteConsoleOutputW(dp->drv.p->screen, dp->drv.p->buffer, size, pos, &rect); #endif }
static void putwchxyattr(int x, int y, wchar_t ch, int attr) { CHAR_INFO buffer; SMALL_RECT r; COORD c = { 0,0 }, s = { 1,1 }; if (!in_window(x, y)) return; r.Left = x - 1; r.Top = y - 1; r.Right = x - 1; r.Bottom = y - 1; buffer.Char.UnicodeChar = ch; buffer.Attributes = attr; WriteConsoleOutputW(GetStdHandle(STD_OUTPUT_HANDLE), &buffer, s, c, &r); }
/* acx1_write ***************************************************************/ ACX1_API unsigned int ACX1_CALL acx1_write (void const * data, size_t len) { uint16_t buf[0x200]; size_t cpc; int c; CHAR_INFO ci[0x200]; size_t i, j, l; SMALL_RECT wr; COORD bs, bc; //uint8_t * b; c = acx1_mutf8_str_decode(data, len, buf, ACX1_ITEM_COUNT(buf), NULL, &cpc); if (c) return ACX1_BAD_DATA; //b = data; cpc = len; l = ACX1_ITEM_COUNT(ci); for (c = 0, i = j = 0; c >= 0 && i < cpc && j < l; ++i, j += c) { c = acx1_term_char_width(buf[i]); if (!c) continue; ci[j].Char.UnicodeChar = buf[i]; ci[j].Attributes = attr; if (c == 2) { ci[j + 1].Char.UnicodeChar = ' '; ci[j + 1].Attributes = attr; } } if (c < 0) return ACX1_BAD_DATA; if (!j) return 0; // nothing to print bs.X = j; bs.Y = 1; bc.X = 0; bc.Y = 0; wr.Left = write_col; wr.Top = write_row; wr.Right = screen_width - 1; wr.Bottom = write_row; if (!WriteConsoleOutputW(hout, ci, bs, bc, &wr)) return ACX1_TERM_IO_FAILED; write_col = wr.Right + 1; return 0; }
int movetext(int __left, int __top, int __right, int __bottom, int __destleft, int __desttop) { CHAR_INFO * buffer; SMALL_RECT r; COORD c = { 0,0 }, s; HANDLE con; init_ti(); s.X = __right - __left + 1; s.Y = __bottom - __top + 1; if (s.X <= 0 || s.Y <= 0) return 0; buffer = (CHAR_INFO*)malloc(s.X * s.Y * sizeof(CHAR_INFO)); con = GetStdHandle(STD_OUTPUT_HANDLE); r.Left = __left - 1; r.Top = __top - 1; r.Right = __right - 1; r.Bottom = __bottom - 1; if (ReadConsoleOutputW(con, buffer, s, c, &r)) WriteConsoleOutputW(con, buffer, s, c, &r); free(buffer); return 0; }
int putwtext(int __left, int __top, int __right, int __bottom, const wchar_info *__source) { int i; SMALL_RECT r; CHAR_INFO* buffer; COORD s, c = { 0,0 }; if (__right<__left || __bottom<__top) return 0; init_ti(); r.Left = __left - 1; r.Top = __top - 1; r.Right = __right - 1; r.Bottom = __bottom - 1; s.X = __right - __left + 1; s.Y = __bottom - __top + 1; buffer = (CHAR_INFO*)malloc(s.X * s.Y * sizeof(CHAR_INFO)); for (i = 0; i < s.X * s.Y; i++) { buffer[i].Char.UnicodeChar = __source[i].letter; buffer[i].Attributes = __source[i].attr; } WriteConsoleOutputW(GetStdHandle(STD_OUTPUT_HANDLE), buffer, s, c, &r); free(buffer); return 0; }
/********************************************************************** * Purpose: Draws all characters in character buffer to the console window. * * Precondition: * None * * Postcondition: * _chbuf drawn. * ************************************************************************/ void ScreenBuffer::Draw() { WriteConsoleOutputW(_hStdout, _chbuf, _chbuf_size, _chbuf_coord, &_write_area); }
/* acx1_rect ****************************************************************/ ACX1_API unsigned int ACX1_CALL acx1_rect ( uint8_t const * const * data, // array of rows of utf8 text with special escapes uint16_t start_row, uint16_t start_col, uint16_t row_num, uint16_t col_num, acx1_attr_t * attrs ) { CHAR_INFO buf[0x2000]; CHAR_INFO * ci; SMALL_RECT wr; COORD bs, bc; uint_t i, j, o, crt_attr, buf_rows; int l, cw; uint16_t a; uint32_t cp; start_row--; start_col--; if (start_row >= screen_height || start_col >= screen_width) return 0; if (row_num > screen_height - start_row) row_num = screen_height - start_row; if (col_num > screen_width - start_col) col_num = screen_width - start_col; buf_rows = ACX1_ITEM_COUNT(buf) / col_num; bs.X = col_num; bc.X = 0; bc.Y = 0; for (; row_num; row_num -= buf_rows, start_row += buf_rows, data += buf_rows) { if (row_num < buf_rows) buf_rows = row_num; for (ci = &buf[0], i = 0; i < buf_rows; ++i) { crt_attr = 0; a = prepare_attr(attrs[crt_attr].bg, attrs[crt_attr].fg, attrs[crt_attr].mode); for (j = o = 0; data[i][o] && j < col_num; o += l, j += cw, ci += cw) { if (data[i][o] >= 0x80) { l = acx1_utf8_char_decode_strict(data[i] + o, SSIZE_MAX, &cp); if (l < 0) return ACX1_BAD_DATA; cw = acx1_term_char_width(cp); if (cw < 0) return ACX1_BAD_DATA; if (!cw) continue; if (cw == 2) { if (j == (uint_t) col_num - 1) break; // finish line if a wide char is in last column ci[1].Attributes = a; ci[1].Char.UnicodeChar = 0; } } else { cp = data[i][o]; if (cp == '\a') { crt_attr = data[i][o + 1]; a = prepare_attr(attrs[crt_attr].bg, attrs[crt_attr].fg, attrs[crt_attr].mode); cw = 0; l = 2; continue; } if (cp < 0x20) return ACX1_BAD_DATA; l = 1; cw = 1; } ci->Char.UnicodeChar = (uint16_t) (cp >= 0x10000 ? 0 : cp); ci->Attributes = a; } if (j < col_num) { // crt_attr = 0; // a = prepare_attr(attrs[crt_attr].bg, attrs[crt_attr].fg, // attrs[crt_attr].mode); for (; j < col_num; ++j, ++ci) { ci->Char.UnicodeChar = ' '; ci->Attributes = a; } } } bs.Y = buf_rows; wr.Left = start_col; wr.Top = start_row; wr.Right = start_col + col_num - 1; wr.Bottom = start_row + buf_rows - 1; if (!WriteConsoleOutputW(hout, buf, bs, bc, &wr)) return ACX1_TERM_IO_FAILED; } return 0; }