📄 terminalcontrol.cpp
字号:
/* terminalcontrol.cpp * * A terminal UI control class * * Copyright 2002-2005 Petteri Kangaslampi * * See license.txt for full copyright and license information.*/#include <e32std.h>#include <gdi.h>#include <eikenv.h>#include <e32svr.h>#include "terminalcontrol.h"#ifdef PUTTY_S60#include "termfepext1.h"#include <aknedsts.h>#endif#include "logfile.h"_LIT(KPanic, "TerminalControl");const TUint KNewline = 0x2028; // unicode forced line break_LIT(KTerminalControl, "tc");#ifdef LOGFILE_ENABLEDstatic void AssertFail(TInt aLine) { LFPRINT((_L("ASSERT FAIL: terminalcontrol.cpp %d"), aLine)); User::Panic(KTerminalControl, aLine);}#define assert(x) __ASSERT_ALWAYS(x, AssertFail(__LINE__))#else#define assert(x) __ASSERT_ALWAYS(x, User::Panic(KTerminalControl, __LINE__))#endif#define TRACE LFPRINT((_L("terminalcontrol.cpp %d"), __LINE__))// Cursor and selection color XOR bit masks// 0x00bbggrr#define KCursorFgXor TRgb(0x00ffffff)#define KCursorBgXor TRgb(0x00ffffff)#define KSelectionFgXor TRgb(0x0000ffff)#define KSelectionBgXor TRgb(0x0000ffff)#define KFepEditFgXor TRgb(0x00ffffff)#define KFepEditBgXor TRgb(0x00ffffff)CTerminalControl::CTerminalControl(MTerminalObserver &aObserver) : iObserver(aObserver) { iGrayed = EFalse; iCursorX = -1; iCursorY = -1;}CTerminalControl::~CTerminalControl() { delete [] iChars; delete [] iAttributes;#ifdef PUTTY_S60 delete iFepExt1;#endif}void CTerminalControl::ConstructL(const TRect &aRect, RWindow &aContainerWindow) { SetContainerWindowL(aContainerWindow); SetRect(aRect); Resize(); AllocateBuffersL(); Clear();#ifdef PUTTY_S60 iFepExt1 = CTermFepExt1::NewL(*this);#endif}void CTerminalControl::SetGrayed(TBool aGrayed) { iGrayed = aGrayed; DrawDeferred();}// Resizes the terminal in response to size or font changevoid CTerminalControl::Resize() { TRect rect = Rect(); TInt width = rect.iBr.iX - rect.iTl.iX; TInt height = rect.iBr.iY - rect.iTl.iY; assert((iFontWidth > 0) && (iFontHeight > 0)); assert((width >= iFontWidth) && (height >= iFontHeight)); iCharWidth = width / iFontWidth; iCharHeight = height / iFontHeight; TRAPD(error, AllocateBuffersL()); iObserver.TerminalSizeChanged(iCharWidth, iCharHeight); if ( error != KErrNone ) { User::Panic(KPanic, error); } if ( iCursorX >= iCharWidth ) { iCursorX = iCharWidth - 1; } if ( iCursorY >= iCharHeight ) { iCursorY = iCharHeight - 1; } if ( iSelectX >= iCharWidth ) { iSelectX = iCharWidth - 1; } if ( iSelectY >= iCharHeight ) { iSelectY = iCharHeight - 1; } if ( iMarkX >= iCharWidth ) { iMarkX = iCharWidth - 1; } if ( iMarkY >= iCharHeight ) { iMarkY = iCharHeight - 1; }}// (re)allocate character and attribute buffersvoid CTerminalControl::AllocateBuffersL() { delete [] iChars; iChars = NULL; delete [] iAttributes; iAttributes = NULL; iChars = new (ELeave) TText[iCharWidth*iCharHeight]; iAttributes = new (ELeave) TTerminalAttribute[iCharWidth*iCharHeight]; Clear();}// Clear the buffersvoid CTerminalControl::Clear() { TText *c = iChars; TTerminalAttribute *a = iAttributes; TInt num = iCharWidth * iCharHeight; while ( num-- ) { *c++ = ' '; a->iFgColor = KRgbBlack; a->iBgColor = KRgbWhite; a->iBold = EFalse; a->iUnderline = EFalse; a++; }}// Draws text on the terminal window. The coordinates are zero-based// character coordinates inside the terminal.void CTerminalControl::DrawText(TInt aX, TInt aY, const TDesC &aText, TBool aBold, TBool aUnderline, TRgb aForeground, TRgb aBackground) { // Don't draw text while grayed out if ( iGrayed ) { return; } // Check that we are at least partially on screen if ( (aX < 0) || (aY < 0) || (aX >= iCharWidth) || (aY >= iCharHeight) ) { return; } // Write the text to our character and attribute buffers TInt numChars = aText.Length(); if ( numChars > (iCharWidth - aX) ) { numChars = iCharWidth - aX; } TText *c = &iChars[aX + aY*iCharWidth]; TTerminalAttribute *a = &iAttributes[aX + aY * iCharWidth]; for ( TInt i = 0; i < numChars; i++ ) { *c++ = aText[i]; a->iFgColor = aForeground; a->iBgColor = aBackground; a->iBold = aBold; a->iUnderline = aUnderline; a++; } // Actually draw the text on screen UpdateDisplay(aX, aY, numChars);}// Set cursor positionvoid CTerminalControl::SetCursor(TInt aX, TInt aY) { // Remember old position, set new TInt oldCursorX = iCursorX; TInt oldCursorY = iCursorY; iCursorX = aX; iCursorY = aY; if ( iGrayed ) { return; } // Redraw the affected character cells if they are inside the terminal if ( (oldCursorX >= 0) && (oldCursorX < iCharWidth) && (oldCursorY >= 0) && (oldCursorY < iCharHeight) ) { UpdateDisplay(oldCursorX, oldCursorY, 1); } if ( (iCursorX >= 0) && (iCursorX < iCharWidth) && (iCursorY >= 0) && (iCursorY < iCharHeight) ) { UpdateDisplay(iCursorX, iCursorY, 1); }}// Set modifiers for next key eventvoid CTerminalControl::SetNextKeyModifiers(TUint aModifiers) { iNextKeyModifiers = aModifiers;}// Set select modevoid CTerminalControl::SetSelectMode(TBool aSelectMode) { iSelectMode = aSelectMode; iHaveSelection = EFalse; iSelectX = iCursorX; iSelectY = iCursorY; if ( iSelectX < 0 ) { iSelectX = 0; } if ( iSelectX >= iCharWidth ) { iSelectX = iCharWidth - 1; } if ( iSelectY < 0 ) { iSelectY = 0; } if ( iSelectY >= iCharHeight ) { iSelectY = iCharHeight - 1; } DrawDeferred();}// Set markvoid CTerminalControl::SetMark() { if ( !iSelectMode ) { return; } iHaveSelection = ETrue; iMarkX = iSelectX; iMarkY = iSelectY; DrawDeferred();}// Remove selectionvoid CTerminalControl::RemoveMark() { iHaveSelection = EFalse; if ( iSelectX >= iCharWidth ) { iSelectX = iCharWidth - 1; } DrawDeferred();}// Copy current selectionconst HBufC *CTerminalControl::CopySelectionLC() { if ( !iHaveSelection ) { return HBufC::NewLC(0); } TInt x1, y1, x2, y2; GetSelectionInScanOrder(x1, y1, x2, y2); // Calculate a (fairly accurate) upper bound on the output text size. // The final text size may be less as the algorithm removes trailing // whitespace from lines. TInt maxTextLen = 0; if ( y1 == y2 ) { maxTextLen = x2 - x1; assert(maxTextLen >= 0); } else { assert(y2 > y1); // Note that we need to add one character per linefeed maxTextLen = (iCharWidth - x1 + 1 + (iCharWidth+1) * (y2 - y1 - 1) + x2); } // Allocate the buffer HBufC *buf = HBufC::NewLC(maxTextLen); if ( maxTextLen == 0 ) { return buf; } TPtr16 des = buf->Des(); // Copy text to the buffer, appending a newline after each line and // removing trailing whitespace. One exception: If the selection is on // a single line and contains nothing but spaces, we'll copy it as such, // since we can only assume the user wanted to copy spaces. if ( y1 == y2 ) { // Single-line selection TInt len = x2-x1; TText *chars = &iChars[y1*iCharWidth + x1]; while ( (chars[len-1] == ' ') && (len > 0) ) { len--; } if ( len == 0 ) { // Nothing but spaces -- let's copy them all len = x2-x1; } des.Append(TPtrC(chars, len)); } else { // Multi-line selection. // Start of the selection to the end of the first line TInt len = iCharWidth - x1; TText *chars = &iChars[y1*iCharWidth + x1]; while ( (chars[len-1] == ' ') && (len > 0) ) { len--; } des.Append(TPtrC(chars, len)); des.Append(KNewline); // Full lines for ( TInt y = (y1+1); y < y2; y++ ) { len = iCharWidth; chars = &iChars[y*iCharWidth]; while ( (chars[len-1] == ' ') && (len > 0) ) { len--; } des.Append(TPtrC(chars, len)); des.Append(KNewline); } // Start of the last line to the end of the selection len = x2; chars = &iChars[y2*iCharWidth]; while ( (chars[len-1] == ' ') && (len > 0) ) { len--; } des.Append(TPtrC(chars, len)); } return buf;}// Gets the current selection in raster scan ordervoid CTerminalControl::GetSelectionInScanOrder( TInt &aStartX, TInt &aStartY, TInt &aEndX, TInt &aEndY) const { // Flip mark and selection cursor coordinates as necessary so that we // have the selection in raster scan order aStartY = iSelectY; aStartX = iSelectX; if ( iMarkY < aStartY ) { aStartY = iMarkY; aStartX = iMarkX; } aEndY = iMarkY; aEndX = iMarkX; if ( iSelectY > aEndY ) { aEndY = iSelectY; aEndX = iSelectX; } if ( (aEndY == aStartY) && (aStartX > aEndX) ) { TInt tmp = aEndX; aEndX = aStartX; aStartX = tmp; }}// Calculate the final colors for a character cellvoid CTerminalControl::GetFinalColors(TInt aX, TInt aY, TRgb &aForeground, TRgb &aBackground) const { assert((aX >= 0) && (aX < iCharWidth)); assert((aY >= 0) && (aY < iCharHeight)); // Basic character colors TTerminalAttribute *attribs = &iAttributes[aY * iCharWidth + aX]; TRgb fg = attribs->iFgColor; TRgb bg = attribs->iBgColor; // FEP editor if ( iFepEditActive && (aY == iFepEditY) && (aX >= iFepEditX) && (aX < (iFepEditX + iFepEditDisplayLen)) ) { // Note that we use the FEP edit start position as a reference for the // whole FEP editor display. This way the color stays constant // regardless of the underlying content attribs = &iAttributes[iFepEditOrigY * iCharWidth + iFepEditOrigX]; // Selection and cursor are not visible in the FEP editor aForeground = attribs->iFgColor ^ KFepEditFgXor; aBackground = attribs->iBgColor ^ KFepEditBgXor; return; } // Selection if ( iHaveSelection ) { TInt selStartX, firstSelLine, selEndX, lastSelLine; GetSelectionInScanOrder(selStartX, firstSelLine, selEndX, lastSelLine); TBool inSelection = EFalse; if ( aY == firstSelLine ) { // On the first selected line if ( aY == lastSelLine ) { // This line is both the first and the last selected line if ( (aX >= selStartX) && (aX < selEndX) ) { inSelection = ETrue; } } else { if ( aX >= selStartX ) { inSelection = ETrue; } } } else if ( aY == lastSelLine ) { // Last selected line if ( aX < selEndX ) { inSelection = ETrue; } } else if ( (aY > firstSelLine) && (aY < lastSelLine) ) { // On a fully selected line inSelection = ETrue; } if ( inSelection ) { fg = fg ^ KSelectionFgXor; bg = bg ^ KSelectionBgXor; } } // Cursor if ( (aX == iCursorX) && (aY == iCursorY) ) { fg = fg ^ KCursorFgXor; bg = bg ^ KCursorBgXor; } aForeground = fg; aBackground = bg;}// Get the final character for a character cellTText CTerminalControl::FinalChar(TInt aX, TInt aY) const { assert((aX >= 0) && (aX < iCharWidth)); assert((aY >= 0) && (aY < iCharHeight)); // FEP editor
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -