// MSTREAM.CPP
// Defines the classes required to
// access a secondary monitor for
// debugging.
#ifdef_Windows
#include <windows.h>
extern WORD _BOOOH; // pointer to global selector
#else
#include <dos.h>
#endif
#include "mstream.h"
#define CPL 80 // Characters Per Line
#define LPP 25 // Lines Per Page
#define ATTR 0x700 // white on black character attribute
mstreambuf::mstreambuf(char* s, int n) : streambuf(s,n)
{
setp(base(),ebuf))); // Initialize the put pointers
if ( screen == 0 ) { // screen pointer needs to be initialized
#ifdef _Windows // Windows will use the predefined global selector
screen = (unsigned int far*) MAKELONG( O, &_BOOOH );
#else // DOS will point directly to the MDA memory area
screen = (unsigned int far*) MK_FP( OxBOO0, 0 );
#endif
// first time thru we clear the screen
for ( int i = O; i < (CPL*LPP); i++ )
screen[i] = ' ' + ATTR;
column = row = 0; // reset the current screen character position
}
}
mstreambuf::-mstreambuf()
{
sync(); // flush the put buffer before we leave.
}
void
mstreambuf::newline()
// This routine generates a new line on the mda monitor. It will scroll all of the lines on
// the screen up one line and erases the bottom line if it needs it.
{
column = 0; // reset the current column position
row++; // increment the current row pointer
if ( row == LPP ) { // are we at the bottom of the screen?
// move lines 2 thru 25 (LPP) up one line
_fmovmem( &screen[CPL], &screen[O], (CPL*(LPP-1))*2);
// clear the last line
for ( int i = CPL*(LPP-1); i < (CPL*LPP); i++ )
screen[i] - ATTR + ' ';
row--; // decrement the current row pointer
}
}
int
mstreambuf::overflow( int nChar )
// This routine empties the put area and consumes the "nChar" character if it is not EDF.
{
sync(); // flush the buffer
if ( nChar != EOF ) // is there a character to consume?
return sputc( nChar ); // store it in the put area, returning the results
else
return 0; // return success otherwise
}
int
mstreambuf::sync()
// This routine flushes the put area.
{
int count = out_waiting(); // get the number of characters in the put area
if ( count ) {
for ( int i=O; i< count; i++ ) {
char c = pbase()[i]; // get each character and send to mda
if ( column == CPL ) // are we at the end of the line?
newline(); // then generate a CR/LF
if ( c == '\n' ) // is the character a CR/LF?
newline(); // then generate a CR/LF here as well
else // send character and attribute to monitor
screen[(CPL*row) + column++] = c + ATTR;
}
setp(base(),ebuf()); // reset the put area pointers
}
return 0;
}
mstream::mstream(): ostream()
// The class constructor. It will create a new streambuf using the classes character buffer.
{
strbuf = new mstreambuf(msgs,bsize);
// do the actual initialization and associate strbuf with ostream
ostream::init(strbuf);
// set flag so that the stream to be flushed after each insertion
setf(ios::unitbuf);
}
mstream::-mstream()
// The class destructor.
{
delete strbuf; // delete the streambuf used by the class.
}
// static class member allocation. This allocates space and initializes.
unsigned int far* mstreambuf::screen=0; // mda screen memory area
int mtreambuf::column=0; // current screen column position
int mstreambuf::row=0; // current screen line position
#ifndef _DLL__
mstream mout; // create a global instance of mstream for everyone to use.
#endif
/* End of File */