📄 tty.cpp
字号:
//*************************************************************************// MODULE : TTY - Device Driver to emulate a simple teletype emulator *// AUTHOR : Ron Chernich *// PURPOSE: This class used by RCOS to instantiate devices for the *// "Operator's console" and the (two) TTY "user terminals". *// HISTORY: *// 05-APR-93 Second Implementation following previous flawed design *// 08-APR-93 ANSI terminal driver and Error Signals 41, 42 added *// 12-MAY-93 Bugs in WriteBlk and ANSI gotoxy squashed *// 18-MAY-93 Memory leaks plugged (always kill arrays with delete[] !) *// 27-OCT-93 Limit cursor hiding to "screen" region *// 01-APR-94 Allow TTY mode to be changed via an IoCtrl message *// 20-APR-94 YAM - YetAnotherMemoryleak plugged in GetKey/PutKey *//************************************************************************* #include "tty.hpp" #include "kernel.hpp" #define XM 3 // Offset, screen left edge to first character #define BUFLEN 32 // Size for input ring buffer #define FATAL TRUE // Define fatal and simple error conditions #define WARN FALSE//////////////////////////////////////////////////////////////////////////// Class constructor must run base class constructor first. Passed params// specify display size and location (in pixels) in a rect struct, and the// colors to use for the foreground and background. The "screen" size in// chars is determined from the pixel dimensions and a char array allocated// and cleared to all spaces.//tty::tty (UINT16 id, UINT16 cls, Knl *pK, rect &pR, UINT16 nFg, UINT16 nBg) :port(id, cls, pK), RngBuf(BUFLEN), nFgnd(nFg), nBgnd(nBg){ x = pR.ul.x, y = pR.ul.y; dx = pR.lr.x, dy = pR.lr.y; nRows = dy / GfxTextHeight(); nCols = (dx - 2) / GfxTextExtent("w"); ddy = (dy - (GfxTextHeight() * nRows)) >> 1; pVmem = new char[(nRows * nCols)+1]; if (pVmem) { nMode = TTY_Silent; Reset(TRUE); } else { nMode = TTY_Failed; DevError(ET_InitFail, FATAL); }}////////////////////// Destructor must release "video" memory//tty::~tty (void){ if (pVmem) DELETE_ARRAY pVmem;}//////////////////////// Receive and action a message. Like a good driver, TTY opens, closes,// can be read, written (char and vlock modes) and responds to specific// IO control requests..//void tty::RxPort (PMSG pM){ switch (pM->wMsgType & ~MM_Sync) { case KM_Open : if (uDest) DevError(ET_StillOpen, WARN); else { Reset(TRUE); uDest = pM->wSender; } break; case KM_Close : if (uDest) uDest = ID_NULL; else DevError(ET_NotOpen, WARN); break; case KM_Read : if (uDest == pM->wSender) GetKey(pM); else DevError(ET_InvalidReq, WARN); break; case KM_KeyPress : if (nMode & TTY_UConly) pM->wParam = (UINT16)toupper(pM->wParam); PutKey((char)pM->wParam); break; case KM_Write : Display((char*)&pM->wParam, 1); break; case KM_WriteBlk : Display((char*)pM->pBody, pM->wParam); break; case KM_IoCtrl : if (uDest) { UINT16 wStat = 0xffff; switch (pM->wParam) { case DM_Reset: Reset((pM->wSender == ID_Kernel) ? TRUE : FALSE); break; case DM_KeyHit: wStat = (UINT16)RngBuf.RngStat(); break; case DM_GetSize: wStat = (UINT16)((nRows << 8) | nCols); break; case DM_GetPos: wStat = (UINT16)(((idx / nCols) << 8) | (idx % nCols)); break; case DM_GetMode: wStat = (UINT16)nMode; break; case DM_SetMode: nMode = *(INT16*)pM->pBody; wStat = (UINT16)nMode; break; default: DevError(ET_NoSupport, WARN); } if (IS_SYNCH(pM->wMsgType)) pM->wParam = wStat; else { PMSG pM = new message(uID, KM_IoCtrl, wStat); pTx->PostMsg(pM->wSender, pM); } } break; default: DevError(ET_NoSupport, WARN); }}/////////////////// Clear the video RAM and, if the display is active, clear the screen// and home the cursor. If bool param is set, we must also reinitialize// the the keyboard buffer.//void tty::Reset (BOOL bFlush){ if (bFlush) { while (RngBuf.RngStat()) RngBuf.RngGet(); uDest = ID_NULL, uCnt = 0; } idx = jdx = nEscape = 0; ycurr = y + ddy, xcurr = x + XM; memset(pVmem, ' ', (nRows * nCols)); if (nMode & TTY_Active) { GfxRect(x, y, x+dx, y+dy, GFX_Fill, nBgnd); TtyCursor(ON); }}//////////// Refresh the display from the input buffer. For optimum speed,// trailing blanks are truncated - the whole line even, maybe..//void tty::ReFresh (BOOL bClear){ char *pBuf = new char[nCols+1]; if (NULL == pBuf) DevError(41, FATAL); else { char *cp; INT16 i, j; Mickey.AutoPointer(x, y, x+dx, y+dy); if (bClear) GfxRect(x, y, x+dx, y+dy, GFX_Fill, nBgnd); GfxSetClip(x, y, x+dx, y+dy); GfxTextColor(nFgnd); for (i = 0, cp = pVmem; i < nRows; i++, cp += nCols) { strncpy(pBuf, cp, nCols); j = nCols - 1; while ((pBuf[j] == ' ') && (j >= 0)) --j; pBuf[j+1] = '\0'; if (*pBuf) GfxText(x+XM, y+ddy+(i*GfxTextHeight()), pBuf, GFX_Transparent); } GfxClrClip(); TtyCursor(ON); Mickey.ShowPointer(); DELETE_ARRAY pBuf; }}//////////////////////// Provided the thing is not stuffed, change its mode.// RETURNS: previous mode//INT16 tty::SetMode (INT16 nNew){ INT16 nOld = nMode; if (!(nMode & TTY_Failed)) nMode = nNew; return nOld;}/////////////// The ANSI Terminal Driver. This is a subset of the ISO 6429 standard in:// 1. Sequences 'h', 'l', 'p' are NOT implemented.// 2. The 'm' (graphics) sequence implement Fore/Background colors only -// ie, Attributes (Blink etc) are ignored.// The tty class default if line-wrap on. Since 'l' is not implemented,// there is no way to change this at present.//INT16 tty::AnsiDriver (char ch){ static short aColor[8] = {0, 4, 2, 14, 1, 5, 3, 15}; if (nEscape == 1) { n1 = n2 = 0; return ((ch == '[') ? 2 : 0); } else { INT16 i, j; switch (ch) { case 'A': // <--------------------------------- Cursor Up and Down case 'B': if (nEscape == 3) { j = ((ch == 'A') ? MIN((idx/nCols),n1) : MIN((idx/nCols),n1)); if (j) { i = nCols * j; idx += (ch == 'A') ? -i : i; i = GfxTextHeight() * j; ycurr += (ch == 'A') ? -i : i; ch = pVmem[idx], pVmem[idx] = '\0'; i = idx - (idx % nCols); xcurr = x + XM + GfxTextExtent(pVmem + i) * j; pVmem[idx] = ch; } } break; case 'C': case 'D': // <------------------------------ Cursor Right and Left if (nEscape == 3) { j = ((ch == 'C') ? MIN((idx-((idx%nCols)+1)),n1) : MIN(((idx % nCols)+1),n1)); if (j) { idx += (ch == 'C') ? j : -j; i = idx - (idx % nCols); ch = pVmem[idx], pVmem[idx] = '\0'; xcurr = x + XM + GfxTextExtent(pVmem + i); pVmem[idx] = ch; } } break; case 'f': case 'H': // <------------------------------------ Position Cursor if (nEscape >= 3) { n1 = MIN(n1,(nRows-1)), n2 = MIN(n2,(nCols-1)); idx = (nCols * n1) + n2; ycurr = y + ddy + (GfxTextHeight() * n1); ch = pVmem[idx], pVmem[idx] = '\0'; xcurr = x + XM + GfxTextExtent(pVmem + (n1 * nCols)); pVmem[idx] = ch; } break; case 'J': // <----------------------- Clear screen and home cursor if (((char)n1 == '2') && (nEscape == 3)) Reset(FALSE); break; case 'K': // <------------------------------- Erase to end of line
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -