/* * HT Editor * sysdisplay.cc - screen access functions for Win32 * * Copyright (C) 1999-2005 Sebastian Biallas (sb@biallas.net) * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as * published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ #include "io/display.h" #include "io/types.h" #include #include #include #define WIN32_LEAN_AND_MEAN #include uint mapToGraphical(char chr) { switch (chr) { case GC_1VLINE: return 0x2502; case GC_1HLINE: return 0x2500; case GC_1CORNER0: return 0x2510; case GC_1CORNER1: return 0x2518; case GC_1CORNER2: return 0x2514; case GC_1CORNER3: return 0x250c; case GC_1UTEE: return 0x252c; case GC_1LTEE: return 0x251c; case GC_1DTEE: return 0x2534; case GC_1RTEE: return 0x2524; case GC_2VLINE: return 0x2551; case GC_2HLINE: return 0x2550; case GC_2CORNER0: return 0x2557; case GC_2CORNER1: return 0x255c; case GC_2CORNER2: return 0x255a; case GC_2CORNER3: return 0x2554; case GC_LOW: return 0x2591; case GC_MEDIUM: return 0x2592; case GC_HIGH: return 0x2593; case GC_FULL: return 0x2588; case GC_ARROW_UP: return 0x25b2; case GC_ARROW_DOWN: return 0x25bc; case GC_ARROW_LEFT: return 0x25c4; case GC_ARROW_RIGHT: return 0x25ba; case GC_SMALL_ARROW_UP: return 0x2191; case GC_SMALL_ARROW_DOWN: return 0x2193; case GC_FILLED_CIRCLE: return 0x25cf; case GC_FILLED_QUAD: return 0x25a0; case GC_FILLED_UPPER: return 0x2580; case GC_FILLED_LOWER: return 0x2584; } return '?'; } uint mapCharToSystemCP(char chr, Codepage codepage) { switch (codepage) { case CP_WINDOWS: case CP_UNICODE: return chr; case CP_DEVICE: if (byte(chr) > 127) { char in[2] = {chr, 0}; WCHAR out[2]; OemToCharW(in, out); return out[0]; } else { return chr; } case CP_GRAPHICAL: return mapToGraphical(chr); case CP_INVALID: return '?'; } return chr; } bool sys_get_screen_size(int &w, int &h) { CONSOLE_SCREEN_BUFFER_INFO screen_info; GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &screen_info); w = screen_info.srWindow.Right - screen_info.srWindow.Left + 1; h = screen_info.srWindow.Bottom - screen_info.srWindow.Top + 1; return true; } /* * Class Win32SystemDisplay */ class Win32SystemDisplay: public SystemDisplay { public: CHAR_INFO *buf; vcp *colorbuf; HANDLE output; CursorMode cursor_mode; CursorMode last_cursor_mode; int cursorx, cursory; int dx, dy; void cursorBold(); void cursorHide(); void cursorNormal(); bool initConsole(); public: Win32SystemDisplay(const char *title); virtual ~Win32SystemDisplay(); /* extends Display */ virtual void copyFromDisplay(const Display &display, int x, int y, const Bounds &clipping); virtual void fill(int x, int y, int w, int h, vcp color, char chr, Codepage cp = CP_DEVICE); virtual void getCursor(int &x, int &y) const; virtual CursorMode getCursorMode() const; virtual int nprint(int x, int y, vcp color, const char *str, int maxstrlen, Codepage codepage = CP_DEVICE); virtual bool read(uint &rawchar, vcp &color, int x, int y) const; virtual void setBounds(const Bounds &b); virtual void setCursor(int x, int y, CursorMode mode = CURSOR_NORMAL); virtual void setCursorMode(CursorMode mode = CURSOR_NORMAL); /* extends SystemDisplay */ virtual void show(); /* new */ void putChar(int dest, uint rawchar, vcp vc); uint vcpToSystem(vcp color); }; Win32SystemDisplay::Win32SystemDisplay(const char *title) : SystemDisplay() { CONSOLE_SCREEN_BUFFER_INFO screen_info; buf = NULL; colorbuf = NULL; if (!initConsole()) ;//throw sys_exception("unable to init console"); GetConsoleScreenBufferInfo(output, &screen_info); SetConsoleTitleA(title); assign(0, 0, screen_info.srWindow.Right - screen_info.srWindow.Left + 1, screen_info.srWindow.Bottom - screen_info.srWindow.Top + 1); dx = screen_info.srWindow.Left; dy = screen_info.srWindow.Top; setCursor(dx, dy, CURSOR_OFF); last_cursor_mode = CURSOR_NORMAL; /* COORD xy; xy.X = dx; xy.Y = dy; SetConsoleCursorPosition(output, xy); xy.X = dx+w-1; xy.Y = dy+h-1; SetConsoleCursorPosition(output, xy); xy.X = dx; xy.Y = dy; SetConsoleCursorPosition(output, xy); ScrollConsoleScreenBuffer(output, );*/ show(); } Win32SystemDisplay::~Win32SystemDisplay() { COORD xy; printChar(w-1, h-1, VCP(VC_WHITE, VC_BLACK), ' '); xy.X = dx; xy.Y = dy+h-1; SetConsoleCursorPosition(output, xy); free(buf); free(colorbuf); cursorNormal(); } bool Win32SystemDisplay::initConsole() { CONSOLE_SCREEN_BUFFER_INFO csbiInfo; SMALL_RECT windowRect; output = GetStdHandle(STD_OUTPUT_HANDLE); if (output == INVALID_HANDLE_VALUE) return false; /* if (!SetConsoleActiveScreenBuffer(output)) return false; if (!GetConsoleScreenBufferInfo(output, &csbiInfo)) return false; windowRect.Left = 0; windowRect.Top = 0; windowRect.Right = csbiInfo.dwSize.X - 1; windowRect.Bottom = csbiInfo.dwSize.Y - 1; if (!SetConsoleWindowInfo(output, TRUE, &windowRect)) return false;*/ if (!SetConsoleMode(output, 0)) return false; return true; } void Win32SystemDisplay::fill(int x, int y, int w, int h, vcp color, char chr, Codepage codepage) { uint rawchar = mapCharToSystemCP(chr, codepage); for (int i=0; i < h; i++) { if (y+i >= this->h) break; if (y+i < 0) continue; int dest = x + (y+i)*this->w; for (int j=0; j < w; j++) { if (x+j >= this->w) break; if (x+j >= 0) putChar(dest, rawchar, color); dest++; } } } int Win32SystemDisplay::nprint(int x, int y, vcp color, const char *str, int maxstrlen, Codepage codepage) { int n = 0; int dest = x + y*w; while (*str && n < maxstrlen && x+n < w) { if (x+n >= 0) putChar(dest, mapCharToSystemCP(*str, codepage), color); dest++; str++; n++; } return n; } bool Win32SystemDisplay::read(uint &rawchar, vcp &color, int x, int y) const { rawchar = buf[x+y*w].Char.AsciiChar; color = colorbuf[x+y*w]; return true; } void Win32SystemDisplay::setBounds(const Bounds &b) { SystemDisplay::setBounds(b); free(buf); free(colorbuf); buf = ht_malloc(w * h * sizeof(CHAR_INFO)); colorbuf = ht_malloc(w * h * sizeof(vcp)); fill(x, y, w, h, VCP(VC_WHITE, VC_BLACK), ' '); } void Win32SystemDisplay::copyFromDisplay(const Display &d, int x, int y, const Bounds &clipping) { for (int iy=0; iy < d.h; iy++) { if (y+iy >= clipping.y+clipping.h) break; if (y+iy < clipping.y) break; int dest = x+(iy+y)*w; for (int ix=0; ix < d.w; ix++) { uint rawchar; vcp color; d.read(rawchar, color, ix, iy); if ((x+ix < clipping.x+clipping.w) && (x+ix >= clipping.x)) putChar(dest, rawchar, color); dest++; } } } void Win32SystemDisplay::getCursor(int &x, int &y) const { x = cursorx; y = cursory; } CursorMode Win32SystemDisplay::getCursorMode() const { return cursor_mode; } void Win32SystemDisplay::putChar(int dest, uint rawchar, vcp vc) { if (dest >= w*h || dest < 0) return; buf[dest].Char.UnicodeChar = rawchar ? rawchar : ' '; colorbuf[dest] = mixColors(colorbuf[dest], vc); buf[dest].Attributes = vcpToSystem(colorbuf[dest]); } void Win32SystemDisplay::setCursor(int x, int y, CursorMode mode) { cursorx = x; cursory = y; if (cursorx < 0) cursorx = 0; if (cursory < 0) cursory = 0; if (cursorx >= w) cursorx = w-1; if (cursory >= h) cursory = h-1; setCursorMode(mode); } void Win32SystemDisplay::setCursorMode(CursorMode mode) { cursor_mode = mode; } void Win32SystemDisplay::show() { COORD xy, xy2; if (cursor_mode != CURSOR_OFF) { xy.X = cursorx + dx; xy.Y = cursory + dy; } else { xy.X = dx; xy.Y = dy; } SetConsoleCursorPosition(output, xy); if (last_cursor_mode != cursor_mode) { switch (cursor_mode) { case CURSOR_OFF: cursorHide(); break; case CURSOR_NORMAL: cursorNormal(); break; case CURSOR_BOLD: cursorBold(); break; } last_cursor_mode = cursor_mode; } /* char s[1024]; sprintf(s, "%d, %d ", xy.X, xy.Y); nprint(0, 0, VCP(VC_WHITE, VC_BLACK), s, 10);*/ xy.X = 0; xy.Y = 0; xy2.X = w; xy2.Y = h; SMALL_RECT sr; sr.Left = dx; sr.Top = dy; sr.Right = dx+w-1; sr.Bottom = dy+h-1; // for (xy.Y=0; xy.Y