home *** CD-ROM | disk | FTP | other *** search
- /*
- *
- * Windows source implementation
- *
- * (C) 1990 Vision Software
- *
- * $Id: windows.c 1.2001 91/04/25 15:07:55 pcalvin release $
- *
- * Comments:
- *
- * Used by nearly every class that performs any screen I/O. These interfaces
- * will (hopefully) aid in porting any application under this system.
- *
- * Bugs:
- *
- * Not fully implemented. Right now there is no window information storage
- * for re-drawing a window moved to the top.
- *
- * No clipping of output should the window be written to when not on top..
- *
- * Some torture testing should be done to determine how stable this system
- * is. If we crash here, there isn't much hope for the rest of the library
- *
- * CODE DOCUMENTATION!!!!!!
- *
- */
- #include <string.h>
- #include <dos.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <conio.h>
- #include <math.h>
- #include <ctype.h>
-
- #include <stdhdr.h>
- #include <adl.h>
-
- #include "lowlevel.h"
-
- /*
- * Windows may be constructed without arguements, in that case,
- * they default to the entire screen with no border.
- */
- WINDOW::WINDOW(ROW r1,COL c1,ROW r2,COL c2,CO coFore,CO coBack,SZ sz,BOOL fScroll)
- {
- rowTop = r1;
- colLeft = c1;
- rowBottom = r2;
- colRight = c2;
- coForeground = coFore;
- coBackground = coBack;
- fOpen = fFalse;
- szTitle = sz;
- fAutomaticScroll = fScroll;
-
- /*
- * Assert the window will fit, attempts to move it if the window doesn't fit.
- */
- VerifySz(FValidWindow(),"Window to large to fit on screen");
- SetScrollRow(rowTop,rowBottom);
- SetScrollCol(colLeft,colRight);
- }
-
- WINDOW::WINDOW(VOID)
- {
- rowTop = 2;
- colLeft = 5;
- rowBottom = 22;
- colRight = 75;
- coForeground = coBlack;
- coBackground = coCyan;
- fOpen = fFalse;
- szTitle = szNil;
- fAutomaticScroll = fFalse;
-
- SetScrollRow(rowTop,rowBottom);
- SetScrollCol(colLeft,colRight);
- }
-
- WINDOW::~WINDOW()
- {
- if (fOpen)
- Close();
- }
-
- ROW WINDOW::RowQuery()
- {
- return (rowTop);
- }
-
- COL WINDOW::ColQuery()
- {
- return (colLeft);
- }
-
- VOID WINDOW::Open(VOID)
- {
- if (!fOpen)
- {
- /*
- * Save screen below window.
- * puchBuffer == Original screen contents
- */
- puchBuffer = new UCHAR[(6+rowBottom-rowTop) * (6+colRight-colLeft) * 2];
- MemoryAssert(puchBuffer);
-
- Save(puchBuffer);
- fOpen = fTrue;
- }
-
- SetRowCol(0,0);
- Draw();
- }
-
- VOID WINDOW::Draw(VOID)
- {
- if (fOpen)
- {
- ClearWindow(rowTop,colLeft,rowBottom,colRight,coForeground,coBackground);
- DrawBorder(rowTop-1,colLeft-1,rowBottom+1,colRight+1,bdDouble,coForeground,coBackground);
-
- if (szTitle != szNil)
- DisplayCenter(rowTop-1,(colRight+colLeft)/2,szTitle,coForeground,coBackground);
- }
- }
-
- VOID WINDOW::Close(VOID)
- {
- if (fOpen)
- {
- Restore(puchBuffer);
- delete puchBuffer;
- fOpen = fFalse;
- }
- }
-
- VOID WINDOW::Restore(PUCH puch)
- {
- Assert(puch != puchNil);
-
- puttext(colLeft-1,rowTop-1,colRight+2,rowBottom+2,puch);
- }
-
- VOID WINDOW::Save(PUCH puch)
- {
- Assert(puch != puchNil);
-
- gettext(colLeft-1,rowTop-1,colRight+2,rowBottom+2,puch);
- }
-
- VOID WINDOW::Move(ROW row,COL col)
- {
- ROW drow = rowBottom-rowTop;
- COL dcol = colRight-colLeft;
-
- Restore(puchBuffer);
- rowTop = row;
- colLeft = col;
- rowBottom = row+drow;
- colRight = col+dcol;
- Save(puchBuffer);
- Draw();
- }
-
- /*
- * Updates the internal record of cursor position and sets position on
- * the viewscreen..
- */
- VOID WINDOW::SetRowCol(ROW row,COL col)
- {
- if (fOpen)
- {
- /*
- * Before setting cursor, assert cursor is within screen.
- */
- if (rowTop + row > rowBottom)
- row = rowBottom;
-
- if (colLeft + col > colRight)
- col = colRight;
-
- /*
- * Now, set internal/external cursor
- */
- rowCurrent = row;
- colCurrent = col;
- SetGlobalRowCol(RowAbs(row),ColAbs(col));
- }
- }
-
- /*
- * Clears the entire window..
- */
- VOID WINDOW::Cls(VOID)
- {
- if (fOpen)
- {
- ClearWindow(rowTop,colLeft,rowBottom,colRight,coForeground,coBackground);
- SetRowCol(0,0);
- }
- }
-
- /*
- * Clear a specific row, does not adjust cursor..
- */
- VOID WINDOW::ClearRow(ROW rowClear)
- {
- if (fOpen)
- {
- ROW row = RowAbs(rowClear);
-
- ClearWindow(row,colLeft,row,colRight,coForeground,coBackground);
- }
- }
-
- /*
- * Clear a specific column, also does not touch the cursor..
- */
- VOID WINDOW::ClearCol(COL colClear)
- {
- if (fOpen)
- {
- COL col = ColAbs(colClear);
-
- ClearWindow(rowTop,col,rowBottom,col,coForeground,coBackground);
- }
- }
-
- /*
- * String output routines..
- */
- VOID WINDOW::Say(SZ sz,CO coFore,CO coBack)
- {
- Assert(sz != szNil);
-
- /*
- * Set up color if default arguments are used..
- */
- coFore = CoFromCoCo(coFore,coForeground);
- coBack = CoFromCoCo(coBack,coBackground);
-
- if (fOpen)
- {
- REGISTER CHAR ch;
-
- /*
- * Draw, keep text from going outside window
- */
- SetRowCol(rowCurrent,colCurrent);
- CursorColor(coFore,coBack);
-
- while ((ch = *sz++) != chNil)
- {
- if (ch == chReturn)
- AdvanceRow();
- else if (isprint(ch))
- putch(ch);
-
- AdvanceCol();
- }
- }
- }
-
- /*
- * Sets new cursor position..
- */
- VOID WINDOW::SayAt(ROW row,COL col,SZ sz,CO coFore,CO coBack)
- {
- SetRowCol(row,col);
- Say(sz,coFore,coBack);
- }
-
- /*
- * Displays a "Hot" string. The CCH'th letter is highlighted
- */
- VOID WINDOW::SayHot(ROW row,COL col,SZ sz,CCH cch,CO coFore,CO coBack)
- {
- ROW rowDisplay = RowAbs(row);
- COL colDisplay = ColAbs(col);
-
- /*
- * Normalize colours..
- */
- coFore = CoFromCoCo(coFore,coForeground);
- coBack = CoFromCoCo(coBack,coBackground);
-
- HotString(rowDisplay,colDisplay,cch,sz,coFore,coBack);
- }
-
- /*
- * Centers the text on the desired row
- */
- VOID WINDOW::SayCentered(ROW row,SZ sz,CO coFore,CO coBack)
- {
- ROW rowDisplay = RowAbs(row);
- COL colDisplay = ColAbs((colRight-colLeft) >> 1);
-
- /*
- * Normalize colours..
- */
- coFore = CoFromCoCo(coFore,coForeground);
- coBack = CoFromCoCo(coBack,coBackground);
-
- DisplayCenter(rowDisplay,colDisplay,sz,coFore,coBack);
- }
-
- /*
- * Outputs a single character at the current location..
- */
- VOID WINDOW::PutCh(CHAR ch,CO coFore,CO coBack)
- {
- /*
- * Normalize colours..
- */
- coFore = CoFromCoCo(coFore,coForeground);
- coBack = CoFromCoCo(coBack,coBackground);
-
- if (fOpen)
- {
- SetRowCol(rowCurrent,colCurrent);
- CursorColor(coFore,coBack);
- if (isprint(ch))
- {
- putch(ch);
- AdvanceCol();
- }
- else if (ch == chReturn)
- {
- AdvanceRow();
- }
- }
- }
-
- /*
- *
- * Windows internal operation
- *
- */
-
- /*
- * Advances the cursor position..
- */
- VOID WINDOW::AdvanceCol()
- {
- COL colLast = colRight - colLeft;
-
- if (++colCurrent > colLast)
- {
- colCurrent = 0;
- AdvanceRow();
- }
-
- SetRowCol(rowCurrent,colCurrent);
- }
-
- VOID WINDOW::AdvanceRow()
- {
- ROW rowLast = rowBottom - rowTop;
-
- /*
- * Be sure to before a return with the linefeed.
- */
- colCurrent = 0;
-
- /*
- * The window is only scrolled up if automatic cursor
- * addressing is to be observed.
- */
- if (++rowCurrent > rowLast)
- {
- rowCurrent--;
- if (fAutomaticScroll)
- ScrollDrow(1);
- }
-
- SetRowCol(rowCurrent,colCurrent);
- }
-
- /*
- * Allows normalizing of the colors. coDefault is used if co==coError
- */
- CO WINDOW::CoFromCoCo(CO co,CO coDefault)
- {
- return ((co == coError) ? coDefault : co);
- }
-
- /*
- * Functions to answer with the ABSOLUTE screen position. Will keep
- * cursor within the window
- */
- ROW WINDOW::RowAbs(ROW row)
- {
- ROW rowAbs = rowTop + row;
-
- return ((rowAbs < rowBottom) ? rowAbs : rowBottom);
- }
-
- ROW WINDOW::ColAbs(COL col)
- {
- COL colAbs = colLeft + col;
-
- return ((colAbs < colRight) ? colAbs : colRight);
- }
-
- VOID WINDOW::SetScrollRow(ROW rowFirst,ROW rowLast)
- {
- rowScrollTop = (rowFirst >= rowTop) ? rowFirst : rowTop;
- rowScrollBottom = (rowLast <= rowBottom) ? rowLast : rowBottom;
- }
-
- VOID WINDOW::SetScrollCol(COL colFirst,COL colLast)
- {
- colScrollLeft = (colFirst >= colLeft) ? colFirst : colLeft;
- colScrollRight = (colLast <= colRight) ? colLast : colRight;
- }
-
- VOID WINDOW::ScrollDrow(ROW drow)
- {
- if (drow > 0)
- {
- movetext(colScrollLeft,rowScrollTop+drow,colScrollRight,rowScrollBottom,colScrollLeft,rowScrollTop);
- ClearRow(rowScrollBottom-rowTop);
- }
- else if (drow < 0)
- {
- movetext(colScrollLeft,rowScrollTop,colScrollRight,rowScrollBottom+drow,colScrollLeft,rowScrollTop-drow);
- ClearRow(0);
- }
- }
-
- /*
- * Asserts that window is small enough to fit on the screen. Also makes sure
- * the window does not travel off the screen.
- * Must leave 2 columns at right edge for border + shadow
- * Also, must leave 3 rows at bottom for border/shadow and help
- */
- BOOL WINDOW::FValidWindow()
- {
- /*
- * First, assert the horizontal measurements..
- */
- if (colRight+2 >= colGlobalWindowRight)
- {
- COL dcol = 2 + colRight - colGlobalWindowRight;
-
- colRight -= dcol;
- colLeft -= dcol;
- }
-
- /*
- * Now the vertical measurements..
- */
- if (rowBottom+3 >= rowGlobalWindowBottom)
- {
- ROW drow = 3 + rowBottom - rowGlobalWindowBottom;
-
- rowBottom -= drow;
- rowTop -= drow;
- }
-
- return (fTrue);
- }
-