📄 textwind.cpp
字号:
// ****************** START OF TEXTWIND.CPP ******************
//
//
//
// This file contains all of the code needed to support the
// Text Windows used for example programs in this book. These
// are "quick and dirty" text windows, using the BIOS for most of
// the work.
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include <conio.h>
#include <ctype.h>
#include <bios.h>
#include "textwind.h"
// This static data member keeps track of how many windows are
// open. When the count drops to zero, cleanup work can be done.
int TextWindow::count = 0;
// write_char uses the BIOS function to write the current
// character using the window attribute. This function is a
// protected member function, and is used by the << operator.
inline void TextWindow::write_char( unsigned char c )
{
union REGS r;
r.h.ah = 9;
r.h.al = c;
r.h.bl = attribute;
r.h.bh = 0;
r.x.cx = 1;
int86( 0x10, &r, &r );
}
// This protected function uses the BIOS parameter to write a
// single character repeatedly. This is much faster than writing
// individual characters in a loop. It is used when writing the
// border and clearing the screen.
inline void TextWindow::write_repeated_chars( unsigned char c,
int count )
{
union REGS r;
r.h.ah = 9;
r.h.al = c;
r.h.bl = attribute;
r.x.cx = count;
r.h.bh = 0;
int86( 0x10, &r, &r );
}
// This protected member function positions the cursor at the
// desired position relative to the text window. The protected
// function doesn't check for validity of the row and column
// values. It also doesn't set the row and column data
// members.
inline void TextWindow::position( int r, int c )
{
union REGS rin;
r += start_row;
c += start_col;
rin.h.ah = 2;
rin.h.dh = (unsigned char) r;
rin.h.dl = (unsigned char) c;
rin.h.bh = 0;
int86( 0x10, &rin, &rin );
}
// This public member function positions the cursor in a
// window. It also stores the new position in the row and column
// data members.
int TextWindow::SetPosition( int r, int c )
{
union REGS rin;
if ( r < 0 || c < 0 )
return 0;
if ( r >= (int) height || c >= (int) width )
return 0;
row = (unsigned char) r;
col = (unsigned char) c;
r += start_row;
c += start_col;
rin.h.ah = 2;
rin.h.dh = (unsigned char) r;
rin.h.dl = (unsigned char) c;
rin.h.bh = 0;
int86( 0x10, &rin, &rin );
return 1;
}
// This public member function positions the cursor in the current
// location of the window defined by *this.
void TextWindow::Goto( void )
{
union REGS rin;
rin.h.ah = 2;
rin.h.dh = (unsigned char) ( row + start_row );
rin.h.dl = (unsigned char) ( col + start_col );
rin.h.bh = 0;
int86( 0x10, &rin, &rin );
}
// This public function uses the BIOS to scroll a text window.
inline void TextWindow::Scroll( unsigned char line_count )
{
union REGS r;
r.h.ah = 6;
r.h.al = line_count;
r.h.ch = start_row;
r.h.cl = start_col;
r.h.dh = (unsigned char) ( start_row + height - 1 );
r.h.dl = (unsigned char) ( start_col + width - 1 );
r.h.bh = attribute;
int86( 0x10, &r, &r );
}
// This routine writes a formated character to the output
// window. Special processing is performed for the CR, LF, and
// BS keys.
BaseWindow& TextWindow::operator<<( char c )
{
switch ( c ) {
case '\r' :
col = 0;
break;
case '\n' :
col = 0;
row += 1;
break;
case '\b' :
if ( col > 0 )
col--;
break;
default :
position( row, col );
write_char( c );
col++;
if ( col >= width ) {
if ( wrap ) {
col = 0;
row++;
} else
col--;
}
}
if ( row >= height ) {
row = (unsigned char) ( height - 1 );
Scroll( 1 );
}
position( row, col );
return *this;
}
// This routine writes a formated string to the output
// window. Special processing is performed for the CR, LF, and
// BS keys.
BaseWindow& TextWindow::operator<<( char *s )
{
unsigned char c;
while ( ( c = *s++ ) != '\0' ) {
switch ( c ) {
case '\r' :
col = 0;
break;
case '\n' :
col = 0;
row += 1;
break;
case '\b' :
if ( col > 0 )
col--;
break;
default :
position( row, col );
write_char( c );
col++;
if ( col >= width ) {
if ( wrap ) {
col = 0;
row += 1;
} else
col--;
}
break;
}
if ( row >= height ) {
row = (unsigned char) ( height - 1 );
Scroll( 1 );
}
position( row, col );
}
return *this;
}
BaseWindow& TextWindow::operator<<( int c )
{
return operator<<( (char) c );
}
// The only constructor for a text window just defines the
// starting row and column, and the width and height.
// Constructing a window doesn't actually draw anything on the
// screen.
TextWindow::TextWindow( int r, int c, int w, int h )
{
count++;
start_row = (unsigned char ) r;
start_col = (unsigned char ) c;
width = (unsigned char) w;
height = (unsigned char) h;
border = 0;
save_buffer = 0;
row = 0;
col = 0;
}
// The destructor for a text window restores any saved data
// that was under the window. It also repositions the cursor if
// the last window was just closed.
TextWindow::~TextWindow( void )
{
if ( save_buffer ) {
restore_window();
if ( border )
restore_border();
delete[] save_buffer;
}
count--;
if ( count == 0 ) {
start_row = 0;
start_col = 0;
position( 23, 0 );
}
}
// Clearing the window is easy.
void TextWindow::Clear( void )
{
Scroll( 0 );
}
// This function writes the border out around the window. If
// a save buffer has been established, the data under the border
// is saved.
void TextWindow::AddBorder( void )
{
unsigned char r;
SaveCursor a;
if ( save_buffer && border == 0 )
save_border();
border = 1;
position( -1, -1 );
write_char( 218 );
position( -1, width );
write_char( 191 );
position( height, -1 );
write_char( 192 );
position( height, width );
write_char( 217 );
for ( r = 0 ; r < height ; r++ ) {
position( r, -1 );
write_char( 179 );
position( r, width );
write_char( 179 );
}
position( -1, 0 );
write_repeated_chars( 196, width );
position( height, 0 );
write_repeated_chars( 196, width );
}
// The title just gets displayed on top of the border.
void TextWindow::DisplayTitle( char *s )
{
int col = 0;
if ( ( strlen( s ) + 2 ) > width )
return;
if ( !border )
AddBorder();
SaveCursor save_it;
position( -1, col++ );
write_char( 180 );
while ( *s ) {
position( -1, col++ );
write_char( *s++ );
}
position( -1, col );
write_char( 195 );
}
// Popup windows save the area under the window. This
// function saves the main window, another one saves the border
// area.
void TextWindow::save_window( void )
{
union REGS rpos;
union REGS rread;
union REGS rout;
int i;
SaveCursor save_it;
// Allocate enough space for the window plus the border. To
// simplify the storage issues, I treat the save buffer as the
// screen array followed by a border array. The border array
// will have weird indexing, but the screen array won't.
if ( save_buffer == 0 )
save_buffer = new unsigned int[(width+2)*(height+2)];
if ( save_buffer ) {
i = 0;
rpos.h.ah = 2;
rpos.h.bh = 0;
rread.h.ah = 8;
rread.h.bh = 0;
for ( rpos.h.dh = start_row ;
rpos.h.dh < (unsigned char) (start_row+height);
rpos.h.dh++ )
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -