Personal tools
You are here: Home Projects C++ Cfront releases Release 3.0.3 source demo lang Screen.C
Document Actions

Screen.C

by Michael L Powell last modified 2007-01-26 03:20

Click here to get the file

Size 7.0 kB - File type text/plain

File contents

/*ident	"@(#)cls4:demo/lang/Screen.C	1.1" */
/*#########################################################################
#                       Copyright (c) 1989 AT&T
#                         All Rights Reserved   
#
#                THIS IS PROPRIETARY SOURCE CODE OF AT&T
#       
#                     This code has been published in
#                      C++ Primer by Stanley Lippman
#                    Addison_Wesley Publishing Company
#
#########################################################################*/
#include "Screen.h"
#include <stdlib.h>

void Screen::checkRange( int x, int y )
{ // verify range
     if ( x < 1 || x > height ||
          y < 1 || y > width )
     {
       cerr<< "Screen(" << height << "," << width
           << "): value out of range: move("
           << x << "," << y << ")\n";
       exit( -1 );
     }
}

int Screen::col() 
{ // return current column
  int pos = cursor - screen + 1; 
  return ((pos + width - 1) % width ) + 1;
}

int Screen::row() 
{ // return current row
  int pos = cursor - screen + 1; 
  return ( pos + width - 1 ) / width;
} 

int Screen::remainingSpace() 
{ // current position is no longer remaining
  int sz = width*height;
  return( screen + sz - cursor - 1 );
}

Screen& Screen::move( int x, int y )
{ // move cursor absolute position
    checkRange( x, y ); // valid address?
    int row = ( x-1 ) * width; // row location
    cursor = screen + row 
             + y-1; // column location    
    return *this;
}

Screen& Screen::back()
{ // move cursor backward one screen element

    // check for top of screen; wraparound
    if ( cursor == screen )
	bottom();
    else
	--cursor;
    return *this;
}

Screen& Screen::bottom ()
{
    int sz = width*height - 1;
    cursor = screen + sz;
    return *this;
}

enum { BELL = '\007' };
Screen& Screen::up()
{ // move cursor up one row of screen
  // do not wraparound; rather, ring bell
    
    if ( row() == 1 ) // at top?
	cout.put( BELL );
    else
	cursor -= width;
    return *this;
}

Screen& Screen::down()
{
    if ( row() == height ) // at bottom?
	cout.put( BELL );
    else
	cursor += width;
    return *this;
}

Screen& Screen::set( char *s )
{ // write string beginning at screen element

    int space = remainingSpace();
    int len = strlen( s );
    if ( space < len ) {
        cerr << "Screen: warning: truncation: "
             << "space: " << space
	     << "string length: " << len << "\n";
	len = space;
    }

    for ( int i = 0; i < len; ++i ) 
	*cursor++ = *s++;
    return *this;
}

Screen& Screen::set( char ch ) 
{
    if ( ch == '\0' )
        cerr << "Screen: warning: "
             << "null character (ignored).\n";
    else *cursor = ch; 
    return *this;
}

int Screen::isEqual( char *s )
{ // yes? return 1; otherwise, 0

    int len = strlen( s );
    if ( remainingSpace() < len )
	return 0;

    char *p = cursor;
    for ( int i = 0; i < len; ++i )
	if ( *p++ != *s++ )
	    return 0;

    return 1;
}

int Screen::isEqual( Screen& s )
{ 
    // first, are they physically unequal?
    if ( width != s.width || height != s.height )
	return 0;

    // do both share the same screen?
    char *p = screen;
    char *q = s.screen;
    if ( p == q ) return 1;

    // be careful not to walk off the Screens
    while ( *p && *p++ == *q++ );

    if ( *p ) // loop broke on not equal
	return 0;

    return 1;
}

Screen& Screen::clear( char bkground )
{ // reset the cursor and clear the screen
     char *p = cursor = screen;

     while ( *p )
	*p++ = bkground;

    return *this; // return invoking object
}

char Screen::get( int x, int y )
{
    move( x, y ); // position cursor
    return get();
}

Screen& Screen::copy( Screen& s )
{ // copy one Screen object with another

    // free up existing storage, if any
    if ( screen != 0 )
	delete screen;

    height = s.height;
    width = s.width;

    screen = cursor = new char[ height * width + 1 ];
    strcpy( screen, s.screen );
    return *this;
}

Screen::Screen( int _height, int _width, char bkground )
{
    int sz;

    // initialize data members
    height = _height;
    width = _width;
    cursor = screen = new char[ (sz = height*width) + 1 ];

    char *endptr = screen + sz;
    char *ptr = screen;
    while ( ptr != endptr )
	*ptr++ = bkground;
    *ptr ='\0'; 
}

Screen& Screen::forward() 
{ // advance cursor one screen element

    ++cursor;
    if (! (*cursor)) home();
    return *this;
}

Screen& Screen::stats()
{
     cout << "row: " << row()<< "\t";
     cout << "col: " << col()<< "\t";
     cout << "rm: " << remainingSpace()<< "\n";
    return *this;
}

Screen& 
Screen::lineX( int x, int y, // x,y coordinates
               int len, char ch)
{ // provide straight line along x-axis 

    move( x, y ); // move to beginning of line

    // now, draw the line of size len  
    for ( int i = 0; i < len; ++i )
	set( ch ).forward();

    return *this;
}

Screen& 
Screen::lineY( int x, int y,
               int len, char ch)
{ // provide straight line along y-axis 
     move( x, y );
     for ( int i = 0; i < len; ++i )
	 set(ch).down();

     return *this;
}

Screen& Screen::display()
{
    char *p;
    for ( int i = 0; i < height; ++i ) 
    {   // for each row
        cout << "\n"; 
        int offset = width * i; // row position
        for ( int j = 0; j < width; ++j ) 
	{   // for each column, write element
	    p = screen + offset + j;
	    cout.put( *p ); 
	}
    }
    return *this;
}

Screen& Screen::reSize( int h, int w, char bkground )
{ // reSize a screen to height h and width w

    Screen *ps = new Screen( h, w, bkground );
    char *pNew = ps->screen;

    // Is this screen currently allocated?
    // If so, copy old screen contents to new
    if ( screen ) 
    {
	char *pOld = screen;
	while ( *pOld && *pNew )
	     *pNew++ = *pOld++;
	delete screen;
     }

     while ( *pNew )
        *pNew++ = bkground;

     *this = *ps; // replace Screen object
     return *this;
}

ostream& operator<<( ostream& os, Screen& s ) 
{ 
    os << "\n<" << s.height
       << "," << s.width << ">";
    
    char *p = s.screen;
    while ( *p )
       os.put( *p++ );
  
    return os;
}

enum {LBRAC = '<', RBRAC = '>', COMMA = ','};
istream& operator>>( istream& os, Screen& s ) 
{ // read Screen object output by << Screen
    int wid, hi;
    char ch;

    // format verification not shown
    // <hi,wid>screenDump
    os >> ch;  // '>'
    os >> hi;  // get height
    os >> ch;  // ','
    os >> wid; // get width
    os >> ch;  // '<'

    // don't modify s until sure format valid
    if ( s.screen ) // return to free store
         delete s.screen;

    int sz = hi * wid;
    s.height = hi; s.width = wid;
    s.cursor = s.screen = new char[ sz + 1 ];

    char *endptr = s.screen + sz;
    char *ptr = s.screen;
    while ( ptr != endptr )
       os.get( *ptr++ );
    *ptr = '\0';    

    return os;
}

typedef Screen& (Screen::*Action)();
Action Menu[] = {
    &Screen::home,
    &Screen::forward,
    &Screen::back,
    &Screen::up,
    &Screen::down,
    &Screen::bottom
};

Screen& Screen::move( CursorMovements cm ) 
{
    (this->*Menu[ cm ])();
    return *this;
} 
« May 2024 »
Su Mo Tu We Th Fr Sa
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
 

Powered by Plone CMS, the Open Source Content Management System

This site conforms to the following standards: