📄 ansisys.cpp
字号:
// Implements ansi.sys display class// public domain// by David Nugent <davidn@unique.blaze.net.au>// 3:632/348@fidonet#include <iostream.h>#include <ctype.h>#include <string.h>#include "ansisys.hpp"ansisys::ansisys(video & v) : scrinterp(v), dispfunc(0), savx(0), savy(0){}voidansisys::reset(){ dispfunc = 0; savx = savy = 0; scrinterp::reset();} // This is the top level dispatcher. It really only // Looks for special control charactersvoidansisys::putch(int ch){ if (dispfunc) (this->*dispfunc)(ch); else if (ch == '\x1b') { flushbuf(); dispfunc = &ansisys::esc; // Hand over to ESC routine } else scrinterp::putch(ch);} // This parses for the leadin for an escape sequencevoidansisys::esc(int ch){ switch (ch) { case '[': // ANSI lead-in dispfunc = &ansisys::seq; // Now parse the sequences break; default: // Huh? putbuf('?'); dispfunc = 0; break; }}intansisys::evalargs(cell_t * plist){ chrbuf[chridx] = '\0'; char const * s = chrbuf; int idx = 0; while (idx < 32) { cell_t res = 0; while (*s && isdigit(*s)) // Evaluate numeric res = cell_t((res * 10) + (*s++ - '0')); plist[idx++] = res; if (*s == ';') // Skip over ++s; else break; // Not a valid delimiter, quit } return idx;} // Parses esc sequencesvoidansisys::seq(int ch){ if (ch == ';' || isdigit(ch)) // Accumulate parameters { if (chridx < CBUFSZ) chrbuf[chridx++] = char(ch); } else { cell_t plist[32]; cell_t x, y, mx, my; int nx =0, ny =0; int args = evalargs(plist); switch (ch) { default: // Unknown sequences reset(); break; case 'A': // Cursor up ny = -((args < 1 || plist[0] == 0) ? 1 : plist[0]); goto mvxy; case 'B': // Cursor down ny = ((args < 1 || plist[0] == 0) ? 1 : plist[0]); goto mvxy; case 'C': // Cursor right nx = ((args < 1 || plist[0] == 0) ? 1 : plist[0]); goto mvxy; case 'D': // Cursor left nx = -((args < 1 || plist[0] == 0) ? 1 : plist[0]); mvxy: vs.wherexy(x, y); x = cell_t(x + nx); y = cell_t(y + ny); goto goxy; case 'H': // Cursor position y = cell_t(((args < 1 || plist[0] == 0) ? 1 : plist[0]) - 1); x = cell_t(((args < 2 || plist[1] == 0) ? 1 : plist[1]) - 1); goxy: vs.maxxy(mx, my); if (x < mx && y < my) vs.gotoxy(x, y); break; case 'J': // Erase display if (args && plist[0] == 2) vs.gotoxy(0, 0); vs.cls(); break; case 'K': // Erase line vs.wherexy(x, y); vs.maxxy(mx, my); vs.repchr(' ', mx - x); vs.gotoxy(x, y); break; case 'n': // Device status report // Not supported here // Need to send back ESC [ x+1 ; y+1 R break; case 's': // Save cursor position vs.wherexy(savx, savy); break; case 'u': // Restore cursor position vs.gotoxy(savx, savy); break; case 'm': // Set graphics rendition (colour) if (!args) plist[args++] = 0; for (int idx = 0 ; idx < args ; ++idx) { cell_t val = plist[idx]; static cell_t colmap[] = { 0, 4, 2, 6, 1, 5, 3, 7 }; switch (val) { case 0: vs.setattr(7); break; case 1: vs.setfg(cell_t(vs.getfg() | 0x8)); break; case 2: vs.setfg(cell_t(vs.getbg() | 0x8)); break; case 3: vs.setfg(cell_t((vs.getbg() & ~0x8) | 1)); break; case 5: vs.setbg(cell_t(vs.getbg() | 0x8)); break; case 7: vs.setfg(0); vs.setbg(cell_t(7 + (vs.getbg() & 0x8))); break; case 8: vs.setfg(cell_t(vs.getbg() & ~0x8)); break; default: if (val >= 30 && val <= 37) vs.setfg(cell_t(colmap[val-30] | (vs.getfg() & 0x8))); else if (val >= 40 && val <= 47) vs.setbg(cell_t(colmap[val-40] | (vs.getbg() & 0x8))); break; } } break; } chridx = 0; dispfunc = 0; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -