Listing 2 mstream.cpp — C++ output stream classes

// 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 */