📄 window.cpp
字号:
// vi:ts=4:shiftwidth=4:expandtab/*************************************************************************** window.cpp - description ------------------- begin : Sun Mar 18 2001 copyright : (C) 2001 by huyong email : ccpaging@online.sh.cn ***************************************************************************//*************************************************************************** * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * ***************************************************************************/#include <cassert>#include <algorithm>#include <sys/time.h>#include <algorithm>#include "global.h"#include "debug.h"#include "window.h"//static members for all the windowsWindow* Window::mpConsole = NULL;char* Window::mpOverlaps = NULL;Window::Window(int x1, int y1, int x2, int y2, int type): mCol(0), mRow(0),mCursorEnabled(false), mCursorVisible(false), mCursorIntevel(350000),mFgColor(7), mBgColor(0) { mX1 = x1; mX2 = x2; mY1 = y1; mY2 = y2; mType = type; mpText = NULL; mpAttr = NULL; mpFlag = NULL; SetBuf(); if (!(type & WS_CHILD)) { // can only be called once! if (mpConsole != NULL) { throw "Window() can not called more than once!"; } int size = mMaxCols * mMaxRows; mpConsole = this; mpOverlaps = new char[size]; memset(mpOverlaps, 0, size); } SetCursorType(CUR_DEF); mVisible = false;}void Window::SetBuf() { int FramePixs = 0; if (mType & WS_FRAMETHIN) { FramePixs = 2; } else if (mType & WS_FRAMETHICK) { FramePixs = 3; } else; mTextX0 = mTextY0 = 0; if (FramePixs > 0) { mTextX0 = FramePixs + ((Width() - 2 * FramePixs) % gpScreen->BlockWidth()) / 2; mTextY0 = FramePixs + ((Height() - 2 * FramePixs) % gpScreen->BlockHeight()) / 2; } mMaxCols = (Width() - 2 * FramePixs) / gpScreen->BlockWidth(); mMaxRows = (Height() - 2 * FramePixs) / gpScreen->BlockHeight(); mEndCol = mMaxCols - 1; mEndRow = mMaxRows - 1; int size = mMaxCols * mMaxRows; delete[] mpText; delete[] mpAttr; delete[] mpFlag; mpText = new char[size]; mpAttr = new char[size]; mpFlag = new char[size];}Window::~Window() { if (this == mpConsole) { delete[] mpOverlaps; mpConsole = NULL; } delete[] mpText; delete[] mpAttr; delete[] mpFlag;}void Window::SetCursorType(int CurType) { this->CursorRestore(); switch (CurType) { case CUR_NONE: mCursorStart = gpScreen->BlockHeight() - 1; mCursorEnd = gpScreen->BlockHeight() - 1; case CUR_UNDERLINE: if (gpScreen->mBlankLineHeight > 0) mCursorStart = gpScreen->BlockHeight() - gpScreen->mBlankLineHeight; else mCursorStart = gpScreen->BlockHeight() - gpScreen->mBlankLineHeight - 1; mCursorEnd = gpScreen->BlockHeight() - 1; break; case CUR_LOWER_THIRD: mCursorStart = gpScreen->BlockHeight()/3; mCursorEnd = gpScreen->BlockHeight() - 1; break; case CUR_LOWER_HALF: mCursorStart = gpScreen->BlockHeight()/2; mCursorEnd = gpScreen->BlockHeight() - 1; break; case CUR_TWO_THIRDS: mCursorStart = gpScreen->BlockHeight()*2/3; mCursorEnd = gpScreen->BlockHeight() - 1; break; default: // CUR_DEF, CUR_BLOCK mCursorStart = 0; mCursorEnd = gpScreen->BlockHeight() - 1; break; }}int Window::ColsOvered() { int cols = Width() / gpScreen->BlockWidth(); if (Width() % gpScreen->BlockWidth()) cols++; return cols;}int Window::RowsOvered() { int rows = Height() / gpScreen->BlockHeight(); if (Height() % gpScreen->BlockHeight()) rows++; return rows;}void Window::OutChar(int col, int row, int fg, int bg, char c) { if (!mVisible) return; if (this == mpConsole && mpOverlaps[Index(col, row)] > 0) return; gpScreen->OutChar(mX1 + mTextX0 + col * gpScreen->BlockWidth(), mY1 + mTextY0 + row * gpScreen->BlockHeight(), fg, bg, c);}void Window::OutChar(int col, int row, int fg, int bg, char c1, char c2) { if (!mVisible) return; if (this != mpConsole) { gpScreen->OutChar(mX1 + mTextX0 + col * gpScreen->BlockWidth(), mY1 + mTextY0 + row * gpScreen->BlockHeight(), fg, bg, c1, c2); return; } int idx = Index(col, row); if (mpOverlaps[idx] == 0 && mpOverlaps[idx+1] == 0 ) { gpScreen->OutChar(mX1 + mTextX0 + col * gpScreen->BlockWidth(), mY1 + mTextY0 + row * gpScreen->BlockHeight(), fg, bg, c1, c2); return; } if (mpOverlaps[idx] > 0) { if (mpOverlaps[idx+1] == 0) { // left is overlapped, draw right gpScreen->OutChar(mX1 + mTextX0 + (col+1) * gpScreen->BlockWidth(), mY1 + mTextY0 + row * gpScreen->BlockHeight(), fg, bg, c2); } // whole chinese is in overlaped return; } // left is not overlaped if (mpOverlaps[idx+1] > 0) { // right is overlapped, draw left gpScreen->OutChar(mX1 + mTextX0 + col * gpScreen->BlockWidth(), mY1 + mTextY0 + row * gpScreen->BlockHeight(), fg, bg, c1); } // both left & right are not overlapped}//put c into inner text buffer col and row are relative positionvoid Window::PutChar(char attr,char flag,char c){ int i = Index(mCol, mRow); mpText[i] = c; mpAttr[i] = attr; mpFlag[i] = flag;}//put a dbl charvoid Window::PutChar(char attr,char flag,char c1,char c2){ int i = Index(mCol, mRow); mpText[i] = c1; mpAttr[i] = attr; mpFlag[i++] = flag; mpText[i] = c2; mpAttr[i] = attr; mpFlag[i] = flag;}//return index of (r,c) in mpText,mpAttr,mpFlagint Window::Index(int c, int r) { return c + r * mMaxCols;}//do Hanzi recognize then update screen//if isUpdateAll is true then update all screenvoid Window::Redraw(bool isUpdateAll) { CursorRestore(); //then we update console int row, indexCol; for (row = 0, indexCol = 0; row < mMaxRows; row++) { RedrawRow(row, mpText + indexCol, mpAttr + indexCol, mpFlag + indexCol, isUpdateAll); indexCol += mMaxCols; } CursorSet();}//DrawRow for Consolevoid Window::RedrawRow(int row, char *pText, char *pAttr, char *pFlag, bool isUpdateAll) { for (int col = 0; col < mMaxCols; pText++, pAttr++, pFlag++, col++) { if (isUpdateAll == false && !(*pFlag & txtUpdated)) continue; *pFlag &= ~txtUpdated; if ((!(*pFlag & txtPrimary) || (*pFlag & txtASCII))) { OutChar(col, row, FgColor(*pAttr), BgColor(*pAttr), *pText); continue; } if (*pFlag & txtDblCode) { *pFlag &= ~txtDblCode; if (col == 0) { if (gpDecoder->IsCode1(*pText)) { *pFlag |= txtDblCode1; } else { *pFlag |= txtASCII; } } else if (*(pFlag - 1) & txtDblCode1) { *pFlag |= txtDblCode2; } // prev char is ASCII or double code2 else { if (gpDecoder->IsCode1(*pText)) { *pFlag |= txtDblCode1; } else { *pFlag |= txtASCII; } } // txtDblCode may convert to txtASCII, special in BIG5 if (*pFlag & txtASCII) { OutChar(col, row, FgColor(*pAttr), BgColor(*pAttr), *pText); continue; } } if (*pFlag & txtDblCode1) { // absolate double code 1 at last col if (col >= mMaxCols - 1) { OutChar(col, row, FgColor(*pAttr), BgColor(*pAttr), *pText); continue; } if ( (*(pFlag + 1) & txtASCII) || !(*(pFlag + 1) & txtPrimary) || (*(pFlag + 1) & txtDblCode1) || !gpDecoder->IsCode2(*(pText + 1)) ) { // absolate double code 1 OutChar(col, row, FgColor(*pAttr), BgColor(*pAttr), *pText); continue; } // if next char is not set to txtDblCode if (*(pFlag + 1) & txtDblCode) { *(pFlag + 1) &= ~txtDblCode; *(pFlag + 1) |= txtDblCode2; } // next char is or was txtDblCode2 OutChar(col, row, FgColor(*pAttr), BgColor(*pAttr), *pText, *(pText + 1)); pText++; pAttr++; pFlag++; col++; continue; } if ( (*pFlag & txtDblCode2) && isUpdateAll == false && col != 0 && (*(pFlag-1) & txtDblCode1) ) { OutChar(col - 1, row, FgColor(*pAttr), BgColor(*pAttr), *(pText-1), *pText); } }}void Window::RedrawChar(int col, int row) { assert(col >= 0 && col <= mEndCol && row >= 0 && row <= mEndRow); int idx = Index(col, row); mpFlag[idx] &= ~txtUpdated; if ((mpFlag[idx] & txtDblCode1) && col < mpConsole->MaxCols() - 1 && (mpFlag[idx + 1] & txtDblCode2) ) { //full hz out OutChar(col, row, FgColor(mpAttr[idx]), BgColor(mpAttr[idx]), mpText[idx], mpText[idx + 1]); return; } if ((mpFlag[idx] & txtDblCode2) && col > 0 && (mpFlag[idx - 1] & txtDblCode1) ) { //full hz out OutChar(col-1, row, FgColor(mpAttr[idx]), BgColor(mpAttr[idx]), mpText[idx-1], mpText[idx]); return; } //ascii or single double code OutChar(col, row, FgColor(mpAttr[idx]), BgColor(mpAttr[idx]), mpText[idx]);}//implement blink attribute on consolevoid Window::UpdateBlinkAttr(bool show) { int size = mpConsole->MaxCols() * mpConsole->MaxRows(); char *pFlag = mpConsole->mpFlag; char *pAttr = mpConsole->mpAttr; char *pText = mpConsole->mpText; int r, c; for (int i = 0; i < size; i++) { if (mpOverlaps[i] == 0 && pAttr[i] & 0x80) continue; r = i / mpConsole->MaxCols(); c = i % mpConsole->MaxCols(); if (show) { if ((pFlag[i] & txtDblCode1) && c < mpConsole->MaxCols() - 1 && (pFlag[i + 1] & txtDblCode2) ) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -