tscroll.cpp
来自「一个类似windows」· C++ 代码 · 共 370 行
CPP
370 行
///////////////////////////////////////////////////////////////////////////////
//Telnet Win32 : an ANSI telnet client.
//Copyright (C) 1998-2000 Paul Brannan
//Copyright (C) 1998 I.Ioannou
//Copyright (C) 1997 Brad Johnson
//
//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.
//
//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.
//
//I.Ioannou
//roryt@hol.gr
//
///////////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////
//
// Module: tscroll.cpp
//
// Contents: Telnet Handler
//
// Product: telnet
//
// Revisions: Dec. 5, 1998 Paul Brannan <pbranna@clemson.edu>
// June 15, 1998 Paul Brannan
//
// This is code originally from tnclass.cpp and ansiprsr.cpp
//
///////////////////////////////////////////////////////////////////////////////
#include <windows.h>
#include <string.h>
#include <ctype.h>
#include "tscroll.h"
#include "tncon.h"
#include "tconsole.h"
#include "tnconfig.h"
enum {
HEX,
DUMP,
DUMPB,
TEXTB,
};
int DummyStripBuffer(char *start, char *end, int width) {return 0;}
TScroller::TScroller(TMouse &M, int size) : Mouse(M) {
iScrollSize = size;
pcScrollData = new char[iScrollSize];
iScrollEnd = 0;
iPastEnd = 0;
memset(pcScrollData, ' ', iScrollSize);
if(stricmp(ini.get_scroll_mode(), "hex") == 0) iDisplay = HEX;
else if(stricmp(ini.get_scroll_mode(), "dump") == 0) iDisplay = DUMP;
else if(stricmp(ini.get_scroll_mode(), "dumpb") == 0) iDisplay = DUMPB;
else if(stricmp(ini.get_scroll_mode(), "text") == 0) iDisplay = TEXTB;
else iDisplay = DUMP;
strip = &DummyStripBuffer;
}
TScroller::~TScroller() {
delete[] pcScrollData;
}
void TScroller::init(stripfunc *s) {
strip = s;
}
// Fixed update of circular buffer (Paul Brannan 12/4/98)
// Note: iScrollEnd is one character beyond the end
void TScroller::update(const char *pszHead, const char *pszTail) {
if ((iScrollEnd)+(pszTail-pszHead) < iScrollSize) {
memcpy(&pcScrollData[iScrollEnd], pszHead, pszTail-pszHead);
} else if (pszTail-pszHead > iScrollSize) {
memcpy(pcScrollData, pszTail-iScrollSize, iScrollSize);
iScrollEnd = 0;
} else {
memcpy(&pcScrollData[iScrollEnd], pszHead, iScrollSize-iScrollEnd);
memcpy(&pcScrollData[0], pszHead + (iScrollSize-iScrollEnd),
pszTail-pszHead-(iScrollSize-iScrollEnd));
}
// This could probably be optimized better, but it's probably not worth it
int temp = iScrollEnd;
iScrollEnd = ((iScrollEnd)+(pszTail-pszHead))%iScrollSize;
if(iScrollEnd < temp) iPastEnd = 1;
}
// Perhaps this should be moved to Tconsole.cpp? (Paul Brannan 6/12/98)
static BOOL WriteConsoleOutputCharAndAttribute(
HANDLE hConsoleOutput, // handle of a console screen buffer
CHAR * lpWriteBuffer,
WORD wAttrib,
SHORT sX,
SHORT sY ){
// we ought to allocate memory before writing to an address (PB 5/12/98)
DWORD cWritten;
const LPDWORD lpcWritten = &cWritten;
DWORD cWriteCells = strlen(lpWriteBuffer);
COORD coordWrite = {sX,sY};
LPWORD lpwAttribute = new WORD[cWriteCells];
for (unsigned int i = 0; i < cWriteCells; i++)
lpwAttribute[i] = wAttrib;
WriteConsoleOutputAttribute(
hConsoleOutput, // handle of a console screen buffer
lpwAttribute, // address of buffer to write attributes from
cWriteCells, // number of character cells to write to
coordWrite, // coordinates of first cell to write to
lpcWritten // address of number of cells written to
);
WriteConsoleOutputCharacter(
hConsoleOutput, // handle of a console screen buffer
lpWriteBuffer, // address of buffer to write characters from
cWriteCells, // number of character cells to write to
coordWrite, // coordinates of first cell to write to
lpcWritten // address of number of cells written to
);
delete [] lpwAttribute;
return 1;
}
static void hexify(int x, char *str, int len) {
for(int j = len - 1; j >= 0; j--) {
str[j] = x % 16;
if(str[j] > 9) str[j] += 'A' - 10;
else str[j] += '0';
x /= 16;
}
}
static int setmaxlines(int iDisplay, int iScrollSize, int strippedlines,
int con_width) {
switch(iDisplay) {
case HEX: return(iScrollSize / 16); break;
case DUMP:
case DUMPB: return(iScrollSize / con_width); break;
case TEXTB: return(strippedlines); break;
}
return 0;
}
static void setstatusline(char *szStatusLine, int len, int iDisplay) {
memset(szStatusLine, ' ', len);
memcpy(&szStatusLine[1], "Scrollback Mode", 15);
switch(iDisplay) {
case HEX: memcpy(&szStatusLine[len / 2 - 1], "HEX", 3); break;
case DUMP: memcpy(&szStatusLine[len / 2 - 2], "DUMP", 4); break;
case DUMPB: memcpy(&szStatusLine[len / 2 - 5], "BINARY DUMP", 11); break;
case TEXTB: memcpy(&szStatusLine[len / 2 - 2], "TEXT", 4); break;
}
memcpy(&szStatusLine[len - 6], "READY", 5);
szStatusLine[len] = 0;
}
void TScroller::ScrollBack(){
char p;
int r,c;
// define colors (Paul Brannan 7/5/98)
int normal = (ini.get_scroll_bg() << 4) | ini.get_scroll_fg();
// int inverse = (ini.get_scroll_fg() << 4) | ini.get_scroll_bg();
int status = (ini.get_status_bg() << 4) | ini.get_status_fg();
CHAR_INFO* chiBuffer;
chiBuffer = newBuffer();
saveScreen(chiBuffer);
HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo;
GetConsoleScreenBufferInfo(hStdout, &ConsoleInfo);
// Update iScrollBegin -- necessary in case the buffer isn't full yet
long iScrollBegin, iScrollLast;
if(iPastEnd == 0) {
iScrollBegin = 0;
iScrollLast = iScrollEnd - 1;
} else {
iScrollBegin = iScrollEnd;
iScrollLast = iScrollSize - 1;
}
// Create buffer with ANSI codes stripped
// Fixed this to work properly with a circular buffer (PB 12/4/98)
char *stripped = new char[iScrollSize];
memcpy(stripped, pcScrollData + iScrollBegin, iScrollSize -
iScrollBegin);
if(iScrollBegin != 0) memcpy(stripped + (iScrollSize - iScrollBegin),
pcScrollData, iScrollBegin - 1);
int strippedlines = (*strip)(stripped, stripped + iScrollLast,
CON_COLS);
// Calculate the last line of the scroll buffer (Paul Brannan 12/4/98)
int maxlines = setmaxlines(iDisplay, iScrollLast + 1, strippedlines,
CON_COLS);
// init scroll position
int current = maxlines - CON_HEIGHT + 1;
if(current < 0) current = 0;
// paint border and info
// paint last two lines black on white
char * szStatusLine;
szStatusLine = new char[CON_WIDTH+2];
setstatusline(szStatusLine, CON_COLS, iDisplay);
WriteConsoleOutputCharAndAttribute(hStdout, szStatusLine, status,
CON_LEFT, CON_BOTTOM);
// loop while not done
BOOL done = FALSE;
while (!done){
switch (iDisplay){
case HEX:
memset(szStatusLine, ' ', CON_COLS);
szStatusLine[8] = ':';
szStatusLine[34] = '-';
for (r = 0; r < CON_HEIGHT; r++) {
hexify((r + current) * 16, &szStatusLine[2], 6);
for (c = 0; c < 16; c++){
if (c+(16*(r+current)) >= iScrollLast)
p = 0;
else
p = pcScrollData[(c+16*(r+current) + iScrollBegin) %
iScrollSize];
hexify((char)p, &szStatusLine[11 + 3*c], 2);
if (!iscntrl(p)) {
szStatusLine[60 + c] = (char)p;
} else {
szStatusLine[60 + c] = '.';
}
}
for(int j = 0; j < 16; j++) {
}
szStatusLine[CON_COLS] = '\0';
WriteConsoleOutputCharAndAttribute(hStdout, szStatusLine,
normal, CON_LEFT, r+CON_TOP);
}
break;
case DUMP:
for (r = 0; r < CON_HEIGHT; r++) {
for (c = 0; c <= CON_WIDTH; c++) {
if (c+((CON_COLS)*(r+current)) >= iScrollLast) p = ' ';
else p = pcScrollData[(c+((CON_COLS)*(r+current))
+ iScrollBegin) % iScrollSize];
if (!iscntrl(p))
szStatusLine[c] = p;
else
szStatusLine[c] = '.';
}
szStatusLine[c] = '\0';
WriteConsoleOutputCharAndAttribute(hStdout, szStatusLine,
normal, CON_LEFT, r+CON_TOP);
}
break;
case DUMPB:
for (r = 0; r < CON_HEIGHT; r++) {
for (c = 0; c <= CON_WIDTH; c++) {
if (c+((CON_COLS)*(r+current)) >= iScrollLast) p = ' ';
else p = pcScrollData[ (c+((CON_COLS)*(r+current))
+ iScrollBegin) % iScrollSize];
if (p != 0)
szStatusLine[c] = p;
else
szStatusLine[c] = ' ';
}
szStatusLine[c] = '\0';
WriteConsoleOutputCharAndAttribute(hStdout, szStatusLine,
normal, CON_LEFT, r+CON_TOP);
}
break;
case TEXTB: {
int ch, lines, x;
// Find the starting position
for(ch = 0, lines = 0, x = 1; ch < iScrollSize &&
lines < current; ch++, x++) {
if(stripped[ch] == '\n') lines++;
if(stripped[ch] == '\r') x = 1;
}
for (r = 0; r < CON_HEIGHT; r++) {
memset(szStatusLine, ' ', CON_COLS);
for(c = 0; c <= CON_WIDTH; c++) {
done = FALSE;
if (ch >= iScrollSize) p = ' ';
else p = stripped[ch];
switch(p) {
case 10: done = TRUE; break;
case 13: c = 0; break;
default: szStatusLine[c] = p;
}
ch++;
if(done) break;
}
szStatusLine[CON_COLS] = '\0';
WriteConsoleOutputCharAndAttribute(hStdout, szStatusLine,
normal, CON_LEFT, r+CON_TOP);
}
}
break;
}
setstatusline(szStatusLine, CON_COLS, iDisplay);
WriteConsoleOutputCharAndAttribute(hStdout, szStatusLine, status,
CON_LEFT, CON_BOTTOM);
// paint scroll back data
// get key input
switch(scrollkeys()){
case VK_ESCAPE:
done = TRUE;
break;
case VK_PRIOR:
if ( current > CON_HEIGHT)
current-= CON_HEIGHT;
else
current = 0;
break;
case VK_NEXT:
if ( current < maxlines - 2*CON_HEIGHT + 2)
current += CON_HEIGHT;
else
current = maxlines - CON_HEIGHT + 1;
break;
case VK_DOWN:
if (current <= maxlines - CON_HEIGHT) current++;
break;
case VK_UP:
if ( current > 0) current--;
break;
case VK_TAB:
iDisplay = (iDisplay+1)%4;
maxlines = setmaxlines(iDisplay, iScrollLast + 1, strippedlines,
CON_COLS);
if(current > maxlines) current = maxlines - 1;
if(current < 0) current = 0;
break;
case VK_END:
current = maxlines - CON_HEIGHT + 1;
if(current < 0) current = 0;
break;
case VK_HOME:
current = 0;
break;
case SC_MOUSE:
Mouse.scrollMouse();
break;
}
}
// Clean up
restoreScreen(chiBuffer);
delete[] szStatusLine;
delete[] chiBuffer;
delete[] stripped;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?