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: tconsole.cpp
30 // Contents: screen functions
35 // Revisions: Mar. 29, 2000 pbranna@clemson (Paul Brannan)
36 // June 15, 1998 pbranna@clemson.edu
37 // May 16, 1998 pbranna@clemson.edu
38 // 05. Sep.1997 roryt@hol.gr (I.Ioannou)
39 // 11.May,1997 roryt@hol.gr
40 // 06.April,1997 roryt@hol.gr
41 // 30.M\84rz.1997 Titus_Boxberg@public.uni-hamburg.de
42 // 5.Dec.1996 jbj@nounname.com
44 // 02.Apr.1995 igor.milavec@uni-lj.si
47 ///////////////////////////////////////////////////////////////////////////////
51 // argsused doesn't work on MSVC++
56 TConsole::TConsole(HANDLE h
) {
59 GetConsoleScreenBufferInfo(hConsole
, &ConsoleInfo
);
61 // Start with correct colors
62 int color_fg
= ini
.get_normal_fg();
63 int color_bg
= ini
.get_normal_bg();
65 color_fg
= defaultfg
= origfg
= ConsoleInfo
.wAttributes
& 0xF;
67 defaultfg
= origfg
= color_fg
;
69 color_bg
= defaultbg
= origbg
= (ConsoleInfo
.wAttributes
>> 4) & 0xF;
71 defaultbg
= origbg
= color_bg
;
72 wAttributes
= color_fg
| (color_bg
<< 4);
73 reverse
= blink
= underline
= false;
74 SetConsoleTextAttribute(hConsole
, wAttributes
);
78 // Set the screen size
79 SetWindowSize(ini
.get_term_width(), ini
.get_term_height());
85 TConsole::~TConsole() {
86 wAttributes
= origfg
| (origbg
<< 4);
87 SetCursorPosition(0, CON_HEIGHT
);
88 SetConsoleTextAttribute(hConsole
, wAttributes
);
89 WriteCtrlChar('\x0a');
92 // Paul Brannan 8/2/98
93 void TConsole::SetWindowSize(int width
, int height
) {
97 (width
== -1) ? CON_RIGHT
: CON_LEFT
+ width
- 1,
98 (height
== -1) ? CON_BOTTOM
: CON_TOP
+ height
- 1
100 ConsoleInfo
.dwSize
.X
= width
;
101 if(ConsoleInfo
.dwSize
.Y
< height
) ConsoleInfo
.dwSize
.Y
= height
;
102 SetConsoleScreenBufferSize(hConsole
, ConsoleInfo
.dwSize
);
103 SetConsoleWindowInfo(hConsole
, TRUE
, &sr
);
104 SetConsoleScreenBufferSize(hConsole
, ConsoleInfo
.dwSize
);
108 // Paul Brannan 5/15/98
109 void TConsole::sync() {
110 GetConsoleScreenBufferInfo(hConsole
, &ConsoleInfo
);
113 void TConsole::HighVideo() {
114 wAttributes
= wAttributes
| (unsigned char) 8;
117 void TConsole::LowVideo() {
118 wAttributes
= wAttributes
& (unsigned char) (0xff-8);
121 void TConsole::Normal() {
122 // I.Ioannou 11 May 1997
123 // Color 7 is correct on some systems (for example Linux)
124 // but not with others (for example SCO)
125 // we must preserve the colors :
126 // 06/04/98 thanks to Paul a .ini parameter from now on
130 if(ini
.get_preserve_colors()) {
136 wAttributes
= (unsigned char)fg
| (bg
<< 4);
141 void TConsole::SetForeground(unsigned char wAttrib
) {
142 if(reverse
) bg
= wAttrib
; else fg
= wAttrib
;
143 wAttributes
= (wAttributes
& (unsigned char)0x88) |
144 (unsigned char)fg
| (bg
<< 4);
147 void TConsole::SetBackground(unsigned char wAttrib
) {
148 if(reverse
) fg
= wAttrib
; else bg
= wAttrib
;
149 wAttributes
= (wAttributes
& (unsigned char)0x88) |
150 (unsigned char)fg
| (bg
<< 4);
153 // As far as I can tell, there's no such thing as blink in Windows Console.
154 // I tried using some inline asm to turn off high-intensity backgrounds,
155 // but I got a BSOD. Perhaps there is an undocumented function?
156 // (Paul Brannan 6/27/98)
157 void TConsole::BlinkOn() {
162 if(ini
.get_blink_bg() != -1) {
163 wAttributes
&= 0x8f; // turn off bg
164 wAttributes
|= ini
.get_blink_bg() << 4;
166 if(ini
.get_blink_fg() != -1) {
167 wAttributes
&= 0xf8; // turn off fg
168 wAttributes
|= ini
.get_blink_fg();
170 if(ini
.get_blink_bg() == -1 && ini
.get_blink_fg() == -1)
175 // Added by I.Ioannou 06 April, 1997
176 void TConsole::BlinkOff() {
181 if(ini
.get_blink_bg() != -1) {
182 wAttributes
&= 0x8f; // turn off bg
183 wAttributes
|= defaultbg
<< 4;
185 if(ini
.get_blink_fg() != -1) {
186 wAttributes
&= 0xf8; // turn off fg
187 wAttributes
|= defaultfg
;
189 if(ini
.get_blink_bg() == -1 && ini
.get_blink_fg() == -1)
194 // Paul Brannan 6/27/98
195 void TConsole::UnderlineOn() {
200 if(ini
.get_underline_bg() != -1) {
201 wAttributes
&= 0x8f; // turn off bg
202 wAttributes
|= ini
.get_underline_bg() << 4;
204 if(ini
.get_underline_fg() != -1) {
205 wAttributes
&= 0xf8; // turn off fg
206 wAttributes
|= ini
.get_underline_fg();
208 if(ini
.get_underline_bg() == -1 && ini
.get_underline_fg() == -1)
213 // Paul Brannan 6/27/98
214 void TConsole::UnderlineOff() {
219 if(ini
.get_blink_bg() != -1) {
220 wAttributes
&= 0x8f; // turn off bg
221 wAttributes
|= defaultbg
<< 4;
223 if(ini
.get_blink_fg() != -1) {
224 wAttributes
&= 0xf8; // turn off fg
225 wAttributes
|= defaultfg
;
227 if(ini
.get_blink_bg() == -1 && ini
.get_blink_fg() == -1)
232 // Paul Brannan 6/27/98
233 void TConsole::UlBlinkOn() {
234 if(ini
.get_ulblink_bg() != -1) {
235 wAttributes
&= 0x8f; // turn off bg
236 wAttributes
|= ini
.get_ulblink_bg() << 4;
238 if(ini
.get_ulblink_fg() != -1) {
239 wAttributes
&= 0xf8; // turn off fg
240 wAttributes
|= ini
.get_ulblink_fg();
242 if(ini
.get_ulblink_bg() == -1 && ini
.get_ulblink_fg() == -1)
246 // Paul Brannan 6/27/98
247 void TConsole::UlBlinkOff() {
250 } else if(underline
) {
257 // Paul Brannan 6/26/98
258 void TConsole::Lightbg() {
259 WORD
*pAttributes
= new WORD
[CON_COLS
];
262 // Paul Brannan 8/5/98
263 // Correction: processing more than one line at a time causes a segfault
264 // if the screen width != 80
265 for(int i
= CON_TOP
; i
<= CON_BOTTOM
; i
++) {
266 COORD Coord
= {CON_LEFT
, i
};
268 ReadConsoleOutputAttribute(hConsole
, pAttributes
, (DWORD
)(CON_COLS
),
271 for(DWORD j
= 0; j
< Result
; j
++) pAttributes
[j
] |= 0x80;
273 WriteConsoleOutputAttribute(hConsole
, pAttributes
, Result
, Coord
,
277 delete[] pAttributes
; // clean up
279 wAttributes
|= (unsigned char)0x80;
283 // Paul Brannan 6/26/98
284 void TConsole::Darkbg() {
285 WORD
*pAttributes
= new WORD
[CON_COLS
];
288 // Paul Brannan 8/5/98
289 // Correction: processing more than one line at a time causes a segfault
290 // if the screen width != 80
291 for(int i
= CON_TOP
; i
<= CON_BOTTOM
; i
++) {
292 COORD Coord
= {CON_LEFT
, i
};
294 ReadConsoleOutputAttribute(hConsole
, pAttributes
, (DWORD
)(CON_COLS
),
297 for(DWORD j
= 0; j
< Result
; j
++) pAttributes
[j
] &= 0x7f;
299 WriteConsoleOutputAttribute(hConsole
, pAttributes
, Result
, Coord
,
303 delete[] pAttributes
; // clean up
306 wAttributes
&= (unsigned char)0x7f;
310 // Added by I.Ioannou 11.May,1997
311 void TConsole::ReverseOn() {
315 // atl : forground attributes without the intensity
316 // ath : backgound attributes without the blink
317 // bl : the blink state
318 // ints : the intensity
319 unsigned char atl
= wAttributes
& (unsigned char) 0x07;
320 unsigned char ath
= wAttributes
& (unsigned char) 0x70;
321 unsigned char bl
= wAttributes
& (unsigned char) 0x80;
322 unsigned char ints
= wAttributes
& (unsigned char) 0x08;
323 wAttributes
= bl
| (atl
<< 4) | ints
| (ath
>> 4);
327 // Added by I.Ioannou 11.May,1997
328 void TConsole::ReverseOff() {
331 wAttributes
= fg
| (bg
<< 4);
335 unsigned long TConsole::WriteText(const char *pszString
, unsigned long cbString
) {
339 InsertCharacter(cbString
);
342 WriteConsoleOutputCharacter(hConsole
, (char *)pszString
, cbString
,
343 ConsoleInfo
.dwCursorPosition
, &Result
);
344 FillConsoleOutputAttribute(hConsole
, wAttributes
, cbString
,
345 ConsoleInfo
.dwCursorPosition
, &Result
);
349 // Formerly ConWriteString (Paul Brannan 6/28/98)
350 unsigned long TConsole::WriteStringFast(const char* pszString
, unsigned long cbString
) {
353 SetConsoleTextAttribute(hConsole
, wAttributes
);
355 //check to see if the line is longer than the display
356 if (!getLineWrap() && ((unsigned)CON_CUR_X
+ cbString
) >= (unsigned)CON_COLS
) {
357 // Take care of the last line last colum exception...
358 // The display scrolls up if you use the normal char out
359 // function even if you only write to the last place
361 if ((unsigned)CON_CUR_Y
>= (unsigned)CON_HEIGHT
) {
362 unsigned long iFakeResult
= cbString
;
363 cbString
= CON_COLS
- CON_CUR_X
- 1;
365 // FIX ME !!! This will avoid the exception when cbString
366 // is <= 0 but still doesn't work :-(
368 WriteConsole(hConsole
, pszString
, cbString
, &Result
, 0);
375 ciBuffer
.Char
.AsciiChar
= *(pszString
+cbString
);
376 ciBuffer
.Attributes
= wAttributes
;
377 SMALL_RECT srWriteRegion
;
378 srWriteRegion
.Top
= (SHORT
) CON_BOTTOM
;
379 srWriteRegion
.Bottom
= (SHORT
) CON_BOTTOM
;
380 srWriteRegion
.Left
= (SHORT
) CON_RIGHT
;
381 srWriteRegion
.Right
= (SHORT
) CON_RIGHT
;
383 COORD bufSize
= {1,1};
385 WriteConsoleOutput(hConsole
, &ciBuffer
, bufSize
,
386 dwBufferCoord
, &srWriteRegion
);
388 // We need to update the ConsoleInfo struct now (Paul Brannan 5/9/98)
389 ConsoleInfo
.dwCursorPosition
.X
= CON_RIGHT
;
391 return iFakeResult
; // Skip the chars that did not fit
393 // just write the line up to the end
395 int iFakeResult
= cbString
;
396 cbString
= CON_COLS
- CON_CUR_X
;
399 WriteConsole(hConsole
, pszString
, cbString
, &Result
, 0);
401 // We need to update the ConsoleInfo struct now (Paul Brannan 5/9/98)
402 ConsoleInfo
.dwCursorPosition
.X
+= (unsigned short)Result
;
405 return iFakeResult
; // Skip the chars that did not fit
408 // If custom scrolling is enabled we must take care of it
409 if(iScrollStart
!= -1 || iScrollEnd
!= -1) {
410 return WriteString(pszString
, cbString
);
413 // Apparently VT100 terminals have an invisible "81st" column that
414 // can hold a cursor until another character is printed. I'm not sure
415 // exactly how to handle this, but here's a hack (Paul Brannan 5/28/98)
416 if(ini
.get_vt100_mode() && cbString
+ (unsigned)CON_CUR_X
== (unsigned)CON_COLS
) {
419 if((long)cbString
>= 0) WriteConsole(hConsole
, pszString
, cbString
, &Result
, 0);
426 ciBuffer
.Char
.AsciiChar
= *(pszString
+cbString
);
427 ciBuffer
.Attributes
= wAttributes
;
428 SMALL_RECT srWriteRegion
;
429 srWriteRegion
.Top
= (SHORT
) ConsoleInfo
.dwCursorPosition
.Y
;
430 srWriteRegion
.Bottom
= (SHORT
) ConsoleInfo
.dwCursorPosition
.Y
;
431 srWriteRegion
.Left
= (SHORT
) CON_RIGHT
;
432 srWriteRegion
.Right
= (SHORT
) CON_RIGHT
;
434 COORD bufSize
= {1,1};
436 WriteConsoleOutput(hConsole
, &ciBuffer
, bufSize
,
437 dwBufferCoord
, &srWriteRegion
);
439 // Update the ConsoleInfo struct
440 ConsoleInfo
.dwCursorPosition
.X
= CON_RIGHT
+ 1;
445 // normal line will wrap normally or not to the end of buffer
446 WriteConsole(hConsole
, pszString
, cbString
, &Result
, 0);
448 // We need to update the ConsoleInfo struct now (Paul Brannan 5/9/98)
449 // FIX ME!!! This is susceptible to the same problem as above.
450 // (e.g. we write out 160 characters)
451 ConsoleInfo
.dwCursorPosition
.X
+= (unsigned short)Result
;
452 while(CON_CUR_X
> CON_WIDTH
) {
453 ConsoleInfo
.dwCursorPosition
.X
-= ConsoleInfo
.dwSize
.X
;
454 if((unsigned)CON_CUR_Y
< (unsigned)CON_HEIGHT
) {
455 ConsoleInfo
.dwCursorPosition
.Y
++;
457 // If we aren't at the bottom of the window, then we need to
458 // scroll down (Paul Brannan 4/14/2000)
459 if(ConsoleInfo
.srWindow
.Bottom
< ConsoleInfo
.dwSize
.Y
- 1) {
460 ConsoleInfo
.srWindow
.Top
++;
461 ConsoleInfo
.srWindow
.Bottom
++;
462 ConsoleInfo
.dwCursorPosition
.Y
++;
463 SetConsoleWindowInfo(hConsole
, TRUE
, &ConsoleInfo
.srWindow
);
473 unsigned long TConsole::WriteString(const char* pszString
, unsigned long cbString
) {
476 SetConsoleTextAttribute(hConsole
, wAttributes
);
478 //check to see if the line is longer than the display
480 unsigned long iFakeResult
= cbString
;
481 if((CON_CUR_X
+ cbString
) >= (unsigned int)CON_COLS
)
482 cbString
= CON_COLS
- CON_CUR_X
;
484 Result
= WriteText(pszString
, cbString
);
486 // We need to update the ConsoleInfo struct now (Paul Brannan 5/9/98)
487 ConsoleInfo
.dwCursorPosition
.X
+= (unsigned short)Result
;
488 SetConsoleCursorPosition(hConsole
, ConsoleInfo
.dwCursorPosition
);
490 return iFakeResult
; // Skip the chars that did not fit
492 // Write up to the end of the line
493 unsigned long temp
= cbString
;
494 if((CON_CUR_X
+ temp
) > (unsigned int)CON_COLS
) {
495 temp
= CON_COLS
- CON_CUR_X
;
497 Result
= WriteText(pszString
, temp
);
498 ConsoleInfo
.dwCursorPosition
.X
+= (unsigned short)Result
;
499 SetConsoleCursorPosition(hConsole
, ConsoleInfo
.dwCursorPosition
);
503 Result
= WriteText(pszString
, temp
);
504 ConsoleInfo
.dwCursorPosition
.X
+= (unsigned short)Result
;
505 temp
= (unsigned short)Result
;
508 // keep writing lines until we get to less than 80 chars left
509 while((temp
+ (unsigned int)CON_COLS
) < cbString
) {
511 ConsoleInfo
.dwCursorPosition
.X
= 0; // CR
512 Result
= WriteText(&pszString
[temp
], CON_COLS
);
513 temp
+= (unsigned short)Result
;
516 // write out the last bit
517 if(temp
< cbString
) {
519 ConsoleInfo
.dwCursorPosition
.X
= 0;
520 Result
= WriteText(&pszString
[temp
], cbString
- temp
);
521 temp
+= (unsigned short)Result
;
524 // Apparently VT100 terminals have an invisible "81st" column that
525 // can hold a cursor until another character is printed. I'm not sure
526 // exactly how to handle this, but here's a hack (Paul Brannan 5/28/98)
527 if(!ini
.get_vt100_mode() && cbString
+ (unsigned)ConsoleInfo
.dwCursorPosition
.X
528 == (unsigned int)CON_COLS
) {
530 ConsoleInfo
.dwCursorPosition
.X
= 0;
533 SetConsoleCursorPosition(hConsole
, ConsoleInfo
.dwCursorPosition
);
541 // This is for multi-character control strings (Paul Brannan 6/26/98)
542 unsigned long TConsole::WriteCtrlString(const char *pszString
, unsigned long cbString
) {
543 unsigned long total
= 0;
544 while(total
< cbString
) {
545 unsigned long Result
= WriteCtrlChar(*(pszString
+ total
));
547 Result
= WriteStringFast(pszString
+ total
, 1);
548 if(Result
== 0) return total
;
555 // This is for printing single control characters
556 // WriteCtrlString uses this (Paul Brannan 6/26/98)
557 unsigned long TConsole::WriteCtrlChar(char c
) {
558 // The console does not handel the CR/LF chars as we might expect
559 // when using color. The attributes are not set correctly, so we
560 // must interpret them manualy to preserve the colors on the screen.
562 unsigned long Result
= 0; // just in case (Paul Brannan 6/26/98)
564 case '\x09': // horizontal tab
565 SetCursorPosition((((CON_CUR_X
/8)+1)*8), CON_CUR_Y
);
569 case '\x0a': // line feed
573 case '\x0d': // carrage return
574 SetCursorPosition(CON_LEFT
, CON_CUR_Y
); // move to beginning of line
577 case '\b': // backspace
578 // Added support for backspace so the cursor position can be changed
579 // (Paul Brannan 5/25/98)
580 MoveCursorPosition(-1, 0);
582 default : // else just write it like normal
589 void TConsole::index() {
590 // if on the last line scroll up
591 // This must work with scrolling (Paul Brannan 5/13/98)
592 if(iScrollEnd
!= -1 && (signed)CON_CUR_Y
>= iScrollEnd
) {
593 ScrollDown(iScrollStart
, iScrollEnd
, -1);
594 } else if ((iScrollEnd
== -1 && (signed)CON_CUR_Y
>= (signed)CON_HEIGHT
)) {
596 WriteConsole(hConsole
, "\n", 1, &Result
, NULL
);
598 // If we aren't at the bottom of the buffer, then we need to
599 // scroll down (Paul Brannan 4/14/2000)
600 if(iScrollEnd
== -1 && ConsoleInfo
.srWindow
.Bottom
< ConsoleInfo
.dwSize
.Y
- 1) {
601 ConsoleInfo
.srWindow
.Top
++;
602 ConsoleInfo
.srWindow
.Bottom
++;
603 ConsoleInfo
.dwCursorPosition
.Y
++;
604 // SetConsoleWindowInfo(hConsole, TRUE, &ConsoleInfo.srWindow);
608 } else { // else move cursor down to the next line
609 SetCursorPosition(CON_CUR_X
, CON_CUR_Y
+ 1);
613 void TConsole::reverse_index() {
614 // if on the top line scroll down
615 // This must work with scrolling (Paul Brannan 5/13/98)
616 // We should be comparing against iScrollStart, not iScrollEnd (PB 12/2/98)
617 if (iScrollStart
== -1 && (signed)CON_CUR_Y
<= 0) {
618 ScrollDown(iScrollStart
, -1, 1);
619 } else if (iScrollStart
!= -1 && (signed)CON_CUR_Y
<= iScrollStart
) {
620 ScrollDown(iScrollStart
, iScrollEnd
, 1);
621 } else // else move cursor up to the previous line
622 SetCursorPosition(CON_CUR_X
,CON_CUR_Y
- 1);
625 void TConsole::ScrollDown( int iStartRow
, int iEndRow
, int bUp
){
627 SMALL_RECT srScrollWindow
;
629 // Correction from I.Ioannou 11 May 1997
630 // check the scroll region
631 if (iStartRow
< iScrollStart
) iStartRow
= iScrollStart
;
633 // Correction from I.Ioannou 11 May 1997
634 // this will make Top the CON_TOP
635 if ( iStartRow
== -1) iStartRow
= 0;
637 // Correction from I.Ioannou 18 Aug 97
638 if ( iEndRow
== -1) {
639 if ( iScrollEnd
== -1 )
640 iEndRow
= CON_HEIGHT
;
642 iEndRow
= ((CON_HEIGHT
<= iScrollEnd
) ? CON_HEIGHT
: iScrollEnd
);
646 if ( iStartRow
> CON_HEIGHT
) iStartRow
= CON_HEIGHT
;
647 if ( iEndRow
> CON_HEIGHT
) iEndRow
= CON_HEIGHT
;
649 srScrollWindow
.Left
= (CON_LEFT
);
650 srScrollWindow
.Right
= (SHORT
) (CON_RIGHT
);
651 srScrollWindow
.Top
= (SHORT
) (CON_TOP
+ iStartRow
);
652 srScrollWindow
.Bottom
= (SHORT
) (CON_TOP
+ iEndRow
); // don't subtract 1 (PB 5/28)
654 ciChar
.Char
.AsciiChar
= ' '; // fill with spaces
655 ciChar
.Attributes
= wAttributes
; // fill with current attrib
657 // This should speed things up (Paul Brannan 9/2/98)
658 COORD dwDestOrg
= {srScrollWindow
.Left
, srScrollWindow
.Top
+ bUp
};
660 // Note that iEndRow and iStartRow had better not be equal to -1 at this
661 // point. There are four cases to consider for out of bounds. Two of
662 // these cause the scroll window to be cleared; the others cause the
663 // scroll region to be modified. (Paul Brannan 12/3/98)
664 if(dwDestOrg
.Y
> CON_TOP
+ iEndRow
) {
665 // We are scrolling past the end of the scroll region, so just
666 // clear the window instead (Paul Brannan 12/3/98)
667 ClearWindow(CON_TOP
+ iStartRow
, CON_TOP
+ iEndRow
);
669 } else if(dwDestOrg
.Y
+ (iEndRow
-iStartRow
+1) < CON_TOP
+ iStartRow
) {
670 // We are scrolling past the end of the scroll region, so just
671 // clear the window instead (Paul Brannan 12/3/98)
672 ClearWindow(CON_TOP
+ iStartRow
, CON_TOP
+ iEndRow
);
674 } else if(dwDestOrg
.Y
< CON_TOP
+ iStartRow
) {
675 // Modify the scroll region (Paul Brannan 12/3/98)
676 dwDestOrg
.Y
= CON_TOP
+ iStartRow
;
677 srScrollWindow
.Top
-= bUp
;
678 } else if(dwDestOrg
.Y
+ (iEndRow
-iStartRow
+1) > CON_TOP
+ iEndRow
) {
679 // Modify the scroll region (Paul Brannan 12/3/98)
680 srScrollWindow
.Bottom
-= bUp
;
683 ScrollConsoleScreenBuffer(hConsole
, &srScrollWindow
,
684 0, dwDestOrg
, &ciChar
);
687 // This allows us to clear the screen with an arbitrary character
688 // (Paul Brannan 6/26/98)
689 void TConsole::ClearScreen(char c
) {
691 COORD Coord
= {CON_LEFT
, CON_TOP
};
692 FillConsoleOutputCharacter(hConsole
, c
, (DWORD
)(CON_COLS
)*
693 (DWORD
)(CON_LINES
), Coord
, &dwWritten
);
694 FillConsoleOutputAttribute(hConsole
, wAttributes
, (DWORD
)(CON_COLS
)*
695 (DWORD
)(CON_LINES
), Coord
, &dwWritten
);
698 // Same as clear screen, but only affects the scroll region
699 void TConsole::ClearWindow(int iStartRow
, int iEndRow
, char c
) {
701 COORD Coord
= {CON_LEFT
, CON_TOP
+ iStartRow
};
702 FillConsoleOutputCharacter(hConsole
, c
, (DWORD
)(CON_COLS
)*
703 (DWORD
)(iEndRow
-iStartRow
+1), Coord
, &dwWritten
);
704 FillConsoleOutputAttribute(hConsole
, wAttributes
, (DWORD
)(CON_COLS
)*
705 (DWORD
)(CON_LINES
), Coord
, &dwWritten
);
708 // Clear from cursor to end of screen
709 void TConsole::ClearEOScreen(char c
)
712 COORD Coord
= {CON_LEFT
, CON_TOP
+ CON_CUR_Y
+ 1};
713 FillConsoleOutputCharacter(hConsole
, c
, (DWORD
)(CON_COLS
)*
714 (DWORD
)(CON_HEIGHT
- CON_CUR_Y
), Coord
, &dwWritten
);
715 FillConsoleOutputAttribute(hConsole
, wAttributes
, (DWORD
)(CON_COLS
)*
716 (DWORD
)(CON_LINES
- CON_CUR_Y
), Coord
, &dwWritten
);
720 // Clear from beginning of screen to cursor
721 void TConsole::ClearBOScreen(char c
)
724 COORD Coord
= {CON_LEFT
, CON_TOP
};
725 FillConsoleOutputCharacter(hConsole
, c
, (DWORD
)(CON_COLS
)*
726 (DWORD
)(CON_CUR_Y
), Coord
, &dwWritten
);
727 FillConsoleOutputAttribute(hConsole
, wAttributes
, (DWORD
)(CON_COLS
)*
728 (DWORD
)(CON_CUR_Y
), Coord
, &dwWritten
);
732 void TConsole::ClearLine(char c
)
735 COORD Coord
= {CON_LEFT
, CON_TOP
+ CON_CUR_Y
};
736 FillConsoleOutputCharacter(hConsole
, c
, (DWORD
)(CON_COLS
),
738 FillConsoleOutputAttribute(hConsole
, wAttributes
, (DWORD
)(CON_COLS
),
740 GetConsoleScreenBufferInfo(hConsole
, &ConsoleInfo
);
743 void TConsole::ClearEOLine(char c
)
746 COORD Coord
= {CON_LEFT
+ CON_CUR_X
, CON_TOP
+ CON_CUR_Y
};
747 FillConsoleOutputAttribute(hConsole
, wAttributes
,
748 (DWORD
)(CON_RIGHT
- CON_CUR_X
) +1, Coord
, &dwWritten
);
749 FillConsoleOutputCharacter(hConsole
, c
, (DWORD
)(CON_RIGHT
- CON_CUR_X
) +1,
751 GetConsoleScreenBufferInfo(hConsole
, &ConsoleInfo
);
754 void TConsole::ClearBOLine(char c
)
757 COORD Coord
= {CON_LEFT
, CON_TOP
+ CON_CUR_Y
};
758 FillConsoleOutputCharacter(hConsole
, c
, (DWORD
)(CON_CUR_X
) + 1, Coord
,
760 FillConsoleOutputAttribute(hConsole
, wAttributes
, (DWORD
)(CON_CUR_X
) + 1,
762 GetConsoleScreenBufferInfo(hConsole
, &ConsoleInfo
);
766 // Inserts blank lines to the cursor-y-position
767 // scrolls down the rest. CURSOR MOVEMENT (to Col#1) ???
768 void TConsole::InsertLine(int numlines
)
776 // Rest of screen would be deleted
777 if ( (acty
= GetCursorY()) >= CON_LINES
- numlines
) {
778 ClearEOScreen(); // delete rest of screen
782 // Else scroll down the part of the screen which is below the
784 from
.Left
= CON_LEFT
;
785 from
.Top
= CON_TOP
+ (SHORT
)acty
;
786 from
.Right
= CON_LEFT
+ (SHORT
)CON_COLS
;
787 from
.Bottom
= CON_TOP
+ (SHORT
)CON_LINES
;
791 to
.Y
= (SHORT
)(from
.Top
+ numlines
);
793 fill
.Char
.AsciiChar
= ' ';
794 fill
.Attributes
= 7; // WHICH ATTRIBUTES TO TAKE FOR BLANK LINE ??
796 ScrollConsoleScreenBuffer(hConsole
, &from
, &clip
, to
, &fill
);
799 // Inserts blank characters under the cursor
800 void TConsole::InsertCharacter(int numchar
)
808 if ( (actx
= GetCursorX()) >= CON_COLS
- numchar
) {
813 from
.Left
= CON_LEFT
+ (SHORT
)actx
;
814 from
.Top
= CON_TOP
+ (SHORT
)GetCursorY();
815 from
.Right
= CON_LEFT
+ (SHORT
)CON_COLS
;
816 from
.Bottom
= CON_TOP
+ (SHORT
)from
.Top
;
819 to
.X
= (SHORT
)(actx
+ numchar
);
822 fill
.Char
.AsciiChar
= ' ';
823 fill
.Attributes
= wAttributes
; // WHICH ATTRIBUTES TO TAKE FOR BLANK CHAR ??
825 ScrollConsoleScreenBuffer(hConsole
, &from
, &clip
, to
, &fill
);
826 } /* InsertCharacter */
828 // Deletes characters under the cursor
829 // Note that there are cases in which all the following lines should shift by
830 // a character, but we don't handle these. This could break some
831 // VT102-applications, but it shouldn't be too much of an issue.
832 void TConsole::DeleteCharacter(int numchar
)
840 if ( (actx
= GetCursorX()) >= CON_COLS
- numchar
) {
845 from
.Left
= CON_LEFT
+ (SHORT
)actx
;
846 from
.Top
= CON_TOP
+ (SHORT
)GetCursorY();
847 from
.Right
= CON_LEFT
+ (SHORT
)CON_COLS
;
848 from
.Bottom
= CON_TOP
+ from
.Top
;
851 to
.X
= (SHORT
)(actx
- numchar
);
854 fill
.Char
.AsciiChar
= ' ';
855 fill
.Attributes
= wAttributes
; // WHICH ATTRIBUTES TO TAKE FOR BLANK CHAR ??
857 ScrollConsoleScreenBuffer(hConsole
, &from
, &clip
, to
, &fill
);
858 } /* DeleteCharacter */
860 void TConsole::SetRawCursorPosition(int x
, int y
) {
861 if (x
> CON_WIDTH
) x
= CON_WIDTH
;
863 if (y
> CON_HEIGHT
) y
= CON_HEIGHT
;
865 COORD Coord
= {(short)(CON_LEFT
+ x
), (short)(CON_TOP
+ y
)};
866 SetConsoleCursorPosition(hConsole
, Coord
);
868 // Update the ConsoleInfo struct (Paul Brannan 5/9/98)
869 ConsoleInfo
.dwCursorPosition
.Y
= Coord
.Y
;
870 ConsoleInfo
.dwCursorPosition
.X
= Coord
.X
;
872 // bug fix in case we went too far (Paul Brannan 5/25/98)
873 if(ConsoleInfo
.dwCursorPosition
.X
< CON_LEFT
)
874 ConsoleInfo
.dwCursorPosition
.X
= CON_LEFT
;
875 if(ConsoleInfo
.dwCursorPosition
.X
> CON_RIGHT
)
876 ConsoleInfo
.dwCursorPosition
.X
= CON_RIGHT
;
877 if(ConsoleInfo
.dwCursorPosition
.Y
< CON_TOP
)
878 ConsoleInfo
.dwCursorPosition
.Y
= CON_TOP
;
879 if(ConsoleInfo
.dwCursorPosition
.Y
> CON_BOTTOM
)
880 ConsoleInfo
.dwCursorPosition
.Y
= CON_BOTTOM
;
883 // The new SetCursorPosition takes scroll regions into consideration
884 // (Paul Brannan 6/27/98)
885 void TConsole::SetCursorPosition(int x
, int y
) {
886 if (x
> CON_WIDTH
) x
= CON_WIDTH
;
888 if(iScrollEnd
!= -1) {
889 if(y
> iScrollEnd
) y
= iScrollEnd
;
891 if(y
> CON_HEIGHT
) y
= CON_HEIGHT
;
893 if(iScrollStart
!= -1) {
894 if(y
< iScrollStart
) y
= iScrollStart
;
899 COORD Coord
= {(short)(CON_LEFT
+ x
), (short)(CON_TOP
+ y
)};
900 SetConsoleCursorPosition(hConsole
, Coord
);
902 // Update the ConsoleInfo struct
903 ConsoleInfo
.dwCursorPosition
.Y
= Coord
.Y
;
904 ConsoleInfo
.dwCursorPosition
.X
= Coord
.X
;
907 void TConsole::MoveCursorPosition(int x
, int y
) {
908 SetCursorPosition(CON_CUR_X
+ x
, CON_CUR_Y
+ y
);
911 void TConsole::SetExtendedMode(int iFunction
, BOOL bEnable
)
913 // Probably should do something here...
914 // Should change the screen mode, but do we need this?
917 void TConsole::SetScroll(int start
, int end
) {
918 iScrollStart
= start
;
922 void TConsole::Beep() {
923 if(ini
.get_do_beep()) {
924 if(!ini
.get_speaker_beep()) printit("\a");
925 else ::Beep(400, 100);
929 void TConsole::SetCursorSize(int pct
) {
930 CONSOLE_CURSOR_INFO ci
= {(pct
!= 0)?pct
:1, pct
!= 0};
931 SetConsoleCursorInfo(hConsole
, &ci
);
934 void saveScreen(CHAR_INFO
*chiBuffer
) {
936 CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo
;
937 SMALL_RECT srctReadRect
;
941 hStdout
= GetStdHandle(STD_OUTPUT_HANDLE
);
942 GetConsoleScreenBufferInfo(hStdout
, &ConsoleInfo
);
944 srctReadRect
.Top
= CON_TOP
; /* top left: row 0, col 0 */
945 srctReadRect
.Left
= CON_LEFT
;
946 srctReadRect
.Bottom
= CON_BOTTOM
; /* bot. right: row 1, col 79 */
947 srctReadRect
.Right
= CON_RIGHT
;
949 coordBufSize
.Y
= CON_BOTTOM
-CON_TOP
+1;
950 coordBufSize
.X
= CON_RIGHT
-CON_LEFT
+1;
952 coordBufCoord
.X
= CON_TOP
;
953 coordBufCoord
.Y
= CON_LEFT
;
956 hStdout
, /* screen buffer to read from */
957 chiBuffer
, /* buffer to copy into */
958 coordBufSize
, /* col-row size of chiBuffer */
960 coordBufCoord
, /* top left dest. cell in chiBuffer */
961 &srctReadRect
); /* screen buffer source rectangle */
964 void restoreScreen(CHAR_INFO
*chiBuffer
) {
966 CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo
;
967 SMALL_RECT srctReadRect
;
971 hStdout
= GetStdHandle(STD_OUTPUT_HANDLE
);
972 GetConsoleScreenBufferInfo(hStdout
, &ConsoleInfo
);
975 srctReadRect
.Top
= CON_TOP
; /* top left: row 0, col 0 */
976 srctReadRect
.Left
= CON_LEFT
;
977 srctReadRect
.Bottom
= CON_BOTTOM
; /* bot. right: row 1, col 79 */
978 srctReadRect
.Right
= CON_RIGHT
;
980 coordBufSize
.Y
= CON_BOTTOM
-CON_TOP
+1;
981 coordBufSize
.X
= CON_RIGHT
-CON_LEFT
+1;
983 coordBufCoord
.X
= CON_TOP
;
984 coordBufCoord
.Y
= CON_LEFT
;
986 hStdout
, /* screen buffer to write to */
987 chiBuffer
, /* buffer to copy from */
988 coordBufSize
, /* col-row size of chiBuffer */
989 coordBufCoord
, /* top left src cell in chiBuffer */
990 &srctReadRect
); /* dest. screen buffer rectangle */
991 // end restore screen
995 CHAR_INFO
* newBuffer() {
996 CONSOLE_SCREEN_BUFFER_INFO ConsoleInfo
;
997 HANDLE hStdout
= GetStdHandle(STD_OUTPUT_HANDLE
);
998 GetConsoleScreenBufferInfo(hStdout
, &ConsoleInfo
);
999 CHAR_INFO
* chiBuffer
;
1000 chiBuffer
= new CHAR_INFO
[(CON_BOTTOM
-CON_TOP
+1)*(CON_RIGHT
-CON_LEFT
+1)];
1004 void deleteBuffer(CHAR_INFO
* chiBuffer
) {