1 ///////////////////////////////////////////////////////////////////////////////
2 //Telnet Win32 : an ANSI telnet client.
3 //Copyright (C) 1998-2000 Paul Brannan
4 //Copyright (C) 1998 I.Ioannou
5 //Copyright (C) 1997 Brad Johnson
7 //This program is free software; you can redistribute it and/or
8 //modify it under the terms of the GNU General Public License
9 //as published by the Free Software Foundation; either version 2
10 //of the License, or (at your option) any later version.
12 //This program is distributed in the hope that it will be useful,
13 //but WITHOUT ANY WARRANTY; without even the implied warranty of
14 //MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 //GNU General Public License for more details.
17 //You should have received a copy of the GNU General Public License
18 //along with this program; if not, write to the Free Software
19 //Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 ///////////////////////////////////////////////////////////////////////////
26 ///////////////////////////////////////////////////////////////////////////////
28 // Module: tscroll.cpp
30 // Contents: Telnet Handler
34 // Revisions: Dec. 5, 1998 Paul Brannan <pbranna@clemson.edu>
35 // June 15, 1998 Paul Brannan
37 // This is code originally from tnclass.cpp and ansiprsr.cpp
39 ///////////////////////////////////////////////////////////////////////////////
56 int DummyStripBuffer(char *start
, char *end
, int width
) {return 0;}
58 TScroller::TScroller(TMouse
&M
, int size
) : Mouse(M
) {
60 pcScrollData
= new char[iScrollSize
];
63 memset(pcScrollData
, ' ', iScrollSize
);
65 if(stricmp(ini
.get_scroll_mode(), "hex") == 0) iDisplay
= HEX
;
66 else if(stricmp(ini
.get_scroll_mode(), "dump") == 0) iDisplay
= DUMP
;
67 else if(stricmp(ini
.get_scroll_mode(), "dumpb") == 0) iDisplay
= DUMPB
;
68 else if(stricmp(ini
.get_scroll_mode(), "text") == 0) iDisplay
= TEXTB
;
71 strip
= &DummyStripBuffer
;
74 TScroller::~TScroller() {
75 delete[] pcScrollData
;
78 void TScroller::init(stripfunc
*s
) {
82 // Fixed update of circular buffer (Paul Brannan 12/4/98)
83 // Note: iScrollEnd is one character beyond the end
84 void TScroller::update(const char *pszHead
, const char *pszTail
) {
85 if ((iScrollEnd
)+(pszTail
-pszHead
) < iScrollSize
) {
86 memcpy(&pcScrollData
[iScrollEnd
], pszHead
, pszTail
-pszHead
);
87 } else if (pszTail
-pszHead
> iScrollSize
) {
88 memcpy(pcScrollData
, pszTail
-iScrollSize
, iScrollSize
);
91 memcpy(&pcScrollData
[iScrollEnd
], pszHead
, iScrollSize
-iScrollEnd
);
92 memcpy(&pcScrollData
[0], pszHead
+ (iScrollSize
-iScrollEnd
),
93 pszTail
-pszHead
-(iScrollSize
-iScrollEnd
));
96 // This could probably be optimized better, but it's probably not worth it
97 int temp
= iScrollEnd
;
98 iScrollEnd
= ((iScrollEnd
)+(pszTail
-pszHead
))%iScrollSize
;
99 if(iScrollEnd
< temp
) iPastEnd
= 1;
102 // Perhaps this should be moved to Tconsole.cpp? (Paul Brannan 6/12/98)
103 static BOOL
WriteConsoleOutputCharAndAttribute(
104 HANDLE hConsoleOutput
, // handle of a console screen buffer
105 CHAR
* lpWriteBuffer
,
109 // we ought to allocate memory before writing to an address (PB 5/12/98)
111 const LPDWORD lpcWritten
= &cWritten
;
113 DWORD cWriteCells
= strlen(lpWriteBuffer
);
114 COORD coordWrite
= {sX
,sY
};
115 LPWORD lpwAttribute
= new WORD
[cWriteCells
];
116 for (unsigned int i
= 0; i
< cWriteCells
; i
++)
117 lpwAttribute
[i
] = wAttrib
;
118 WriteConsoleOutputAttribute(
119 hConsoleOutput
, // handle of a console screen buffer
120 lpwAttribute
, // address of buffer to write attributes from
121 cWriteCells
, // number of character cells to write to
122 coordWrite
, // coordinates of first cell to write to
123 lpcWritten
// address of number of cells written to
125 WriteConsoleOutputCharacter(
126 hConsoleOutput
, // handle of a console screen buffer
127 lpWriteBuffer
, // address of buffer to write characters from
128 cWriteCells
, // number of character cells to write to
129 coordWrite
, // coordinates of first cell to write to
130 lpcWritten
// address of number of cells written to
132 delete [] lpwAttribute
;
136 static void hexify(int x
, char *str
, int len
) {
137 for(int j
= len
- 1; j
>= 0; j
--) {
139 if(str
[j
] > 9) str
[j
] += 'A' - 10;
145 static int setmaxlines(int iDisplay
, int iScrollSize
, int strippedlines
,
148 case HEX
: return(iScrollSize
/ 16); break;
150 case DUMPB
: return(iScrollSize
/ con_width
); break;
151 case TEXTB
: return(strippedlines
); break;
156 static void setstatusline(char *szStatusLine
, int len
, int iDisplay
) {
157 memset(szStatusLine
, ' ', len
);
158 memcpy(&szStatusLine
[1], "Scrollback Mode", 15);
160 case HEX
: memcpy(&szStatusLine
[len
/ 2 - 1], "HEX", 3); break;
161 case DUMP
: memcpy(&szStatusLine
[len
/ 2 - 2], "DUMP", 4); break;
162 case DUMPB
: memcpy(&szStatusLine
[len
/ 2 - 5], "BINARY DUMP", 11); break;
163 case TEXTB
: memcpy(&szStatusLine
[len
/ 2 - 2], "TEXT", 4); break;
165 memcpy(&szStatusLine
[len
- 6], "READY", 5);
166 szStatusLine
[len
] = 0;
169 void TScroller::ScrollBack(){
173 // define colors (Paul Brannan 7/5/98)
174 int normal
= (ini
.get_scroll_bg() << 4) | ini
.get_scroll_fg();
175 // int inverse = (ini.get_scroll_fg() << 4) | ini.get_scroll_bg();
176 int status
= (ini
.get_status_bg() << 4) | ini
.get_status_fg();
178 CHAR_INFO
* chiBuffer
;
179 chiBuffer
= newBuffer();
180 saveScreen(chiBuffer
);
182 HANDLE hStdout
= GetStdHandle(STD_OUTPUT_HANDLE
);
183 CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo
;
184 GetConsoleScreenBufferInfo(hStdout
, &ConsoleInfo
);
186 // Update iScrollBegin -- necessary in case the buffer isn't full yet
187 long iScrollBegin
, iScrollLast
;
190 iScrollLast
= iScrollEnd
- 1;
192 iScrollBegin
= iScrollEnd
;
193 iScrollLast
= iScrollSize
- 1;
196 // Create buffer with ANSI codes stripped
197 // Fixed this to work properly with a circular buffer (PB 12/4/98)
198 char *stripped
= new char[iScrollSize
];
199 memcpy(stripped
, pcScrollData
+ iScrollBegin
, iScrollSize
-
201 if(iScrollBegin
!= 0) memcpy(stripped
+ (iScrollSize
- iScrollBegin
),
202 pcScrollData
, iScrollBegin
- 1);
203 int strippedlines
= (*strip
)(stripped
, stripped
+ iScrollLast
,
206 // Calculate the last line of the scroll buffer (Paul Brannan 12/4/98)
207 int maxlines
= setmaxlines(iDisplay
, iScrollLast
+ 1, strippedlines
,
210 // init scroll position
211 int current
= maxlines
- CON_HEIGHT
+ 1;
212 if(current
< 0) current
= 0;
214 // paint border and info
215 // paint last two lines black on white
217 szStatusLine
= new char[CON_WIDTH
+2];
218 setstatusline(szStatusLine
, CON_COLS
, iDisplay
);
219 WriteConsoleOutputCharAndAttribute(hStdout
, szStatusLine
, status
,
220 CON_LEFT
, CON_BOTTOM
);
222 // loop while not done
227 memset(szStatusLine
, ' ', CON_COLS
);
228 szStatusLine
[8] = ':';
229 szStatusLine
[34] = '-';
230 for (r
= 0; r
< CON_HEIGHT
; r
++) {
231 hexify((r
+ current
) * 16, &szStatusLine
[2], 6);
232 for (c
= 0; c
< 16; c
++){
233 if (c
+(16*(r
+current
)) >= iScrollLast
)
236 p
= pcScrollData
[(c
+16*(r
+current
) + iScrollBegin
) %
238 hexify((char)p
, &szStatusLine
[11 + 3*c
], 2);
240 szStatusLine
[60 + c
] = (char)p
;
242 szStatusLine
[60 + c
] = '.';
245 for(int j
= 0; j
< 16; j
++) {
247 szStatusLine
[CON_COLS
] = '\0';
248 WriteConsoleOutputCharAndAttribute(hStdout
, szStatusLine
,
249 normal
, CON_LEFT
, r
+CON_TOP
);
253 for (r
= 0; r
< CON_HEIGHT
; r
++) {
254 for (c
= 0; c
<= CON_WIDTH
; c
++) {
255 if (c
+((CON_COLS
)*(r
+current
)) >= iScrollLast
) p
= ' ';
256 else p
= pcScrollData
[(c
+((CON_COLS
)*(r
+current
))
257 + iScrollBegin
) % iScrollSize
];
261 szStatusLine
[c
] = '.';
263 szStatusLine
[c
] = '\0';
264 WriteConsoleOutputCharAndAttribute(hStdout
, szStatusLine
,
265 normal
, CON_LEFT
, r
+CON_TOP
);
269 for (r
= 0; r
< CON_HEIGHT
; r
++) {
270 for (c
= 0; c
<= CON_WIDTH
; c
++) {
271 if (c
+((CON_COLS
)*(r
+current
)) >= iScrollLast
) p
= ' ';
272 else p
= pcScrollData
[ (c
+((CON_COLS
)*(r
+current
))
273 + iScrollBegin
) % iScrollSize
];
277 szStatusLine
[c
] = ' ';
279 szStatusLine
[c
] = '\0';
280 WriteConsoleOutputCharAndAttribute(hStdout
, szStatusLine
,
281 normal
, CON_LEFT
, r
+CON_TOP
);
286 // Find the starting position
287 for(ch
= 0, lines
= 0, x
= 1; ch
< iScrollSize
&&
288 lines
< current
; ch
++, x
++) {
290 if(stripped
[ch
] == '\n') lines
++;
291 if(stripped
[ch
] == '\r') x
= 1;
294 for (r
= 0; r
< CON_HEIGHT
; r
++) {
295 memset(szStatusLine
, ' ', CON_COLS
);
296 for(c
= 0; c
<= CON_WIDTH
; c
++) {
298 if (ch
>= iScrollSize
) p
= ' ';
299 else p
= stripped
[ch
];
301 case 10: done
= TRUE
; break;
302 case 13: c
= 0; break;
303 default: szStatusLine
[c
] = p
;
308 szStatusLine
[CON_COLS
] = '\0';
309 WriteConsoleOutputCharAndAttribute(hStdout
, szStatusLine
,
310 normal
, CON_LEFT
, r
+CON_TOP
);
316 setstatusline(szStatusLine
, CON_COLS
, iDisplay
);
317 WriteConsoleOutputCharAndAttribute(hStdout
, szStatusLine
, status
,
318 CON_LEFT
, CON_BOTTOM
);
320 // paint scroll back data
322 switch(scrollkeys()){
327 if ( current
> CON_HEIGHT
)
328 current
-= CON_HEIGHT
;
333 if ( current
< maxlines
- 2*CON_HEIGHT
+ 2)
334 current
+= CON_HEIGHT
;
336 current
= maxlines
- CON_HEIGHT
+ 1;
339 if (current
<= maxlines
- CON_HEIGHT
) current
++;
342 if ( current
> 0) current
--;
345 iDisplay
= (iDisplay
+1)%4;
346 maxlines
= setmaxlines(iDisplay
, iScrollLast
+ 1, strippedlines
,
348 if(current
> maxlines
) current
= maxlines
- 1;
349 if(current
< 0) current
= 0;
352 current
= maxlines
- CON_HEIGHT
+ 1;
353 if(current
< 0) current
= 0;
365 restoreScreen(chiBuffer
);
366 delete[] szStatusLine
;