Category : Files from Magazines
Archive   : DDJ-LIB.ZIP
Filename : WINDOWS.CPP

 
Output of file : WINDOWS.CPP contained in archive : DDJ-LIB.ZIP
_C PROGRAMMING COLUMN_
by Al Stevens

[LISTING ONE]



// -------------- window.h

#ifndef WINDOWS
#define WINDOWS

// ---------- screen dimensions
#define SCREENWIDTH 80
#define SCREENHEIGHT 25

// --------- atrribute values for colors
enum color {
BLACK, BLUE, GREEN, CYAN, RED, MAGENTA, BROWN, LIGHTGRAY,
GRAY, LIGHTBLUE, LIGHTGREEN, LIGHTCYAN, LIGHTRED,
LIGHTMAGENTA, YELLOW, WHITE, BLINK = 128
};

// ------------ spaces per tab stop (text displays)
#define TABS 4
// ------------ color assignments for window types
#define YESNOFG WHITE
#define YESNOBG GREEN
#define NOTICEFG BLACK
#define NOTICEBG CYAN
#define ERRORFG (YELLOW | BLINK)
#define ERRORBG RED

// ------------ a video window
class Window {
unsigned bg, fg; // window colors
unsigned lf,tp,rt,bt; // window position
unsigned *wsave; // video memory save buffer
unsigned *hsave; // hide window save buffer
unsigned row, col; // current cursor row and column
int tabs; // tab stops, this window
char **text; // window text content
public:
Window(unsigned left, unsigned top,
unsigned right, unsigned bottom,
color wfg, color wbg);
~Window(void);
void title(char *ttl);
Window& operator<<(char **btext);
Window& operator<<(char *ltext);
Window& operator<<(char ch);
void cursor(unsigned x, unsigned y);
void cursor(unsigned *x, unsigned *y)
{ *y = row, *x = col; }
void clear_window(void);
void clreos(void); // clear to end of screen
void clreol(void); // clear to end of line
void hidewindow(void); // hide an in-scope window
void restorewindow(void); // unhide a hidden window
void page(void); // page through the text
void scroll(int d); // scroll the window up, down
void set_colors(int cfg, int cbg) // change the colors
{ fg = cfg, bg = cbg; }
void set_tabs(int t) // change the tab stops
{ if (t > 1 && t < 8) tabs = t; }
};

// ---------- utility notice window
class Notice : Window {
public:
Notice(char *text);
~Notice(){}
};

// ---------- utility yes/no window
class YesNo : Window {
public:
YesNo(char *text);
~YesNo(){}
int answer;
};

// ---------- utility error window
class Error : Window {
public:
Error(char *text);
~Error(){}
};

#define max(x,y) (((x) > (y)) ? (x) : (y))
#define min(x,y) (((x) > (y)) ? (y) : (x))

#endif


[LISTING TWO]

// -------------- window.c

// A C++ window library

#include
#include
#include
#include "window.h"
#include "console.h"

#define HEIGHT (bt - tp + 1)
#define WIDTH (rt - lf + 1)

// ------- constructor for a Window
Window::Window(unsigned left, unsigned top, // 0 - 79, 0 - 24
unsigned right, unsigned bottom,
color wfg, color wbg)
{
savecursor();
initconsole();
hidecursor();
// ----- adjust for windows beyond the screen dimensions
if (right > SCREENWIDTH-1) {
left -= right-(SCREENWIDTH-1);
right = SCREENWIDTH-1;
}
if (bottom > SCREENHEIGHT-1) {
top -= bottom-(SCREENHEIGHT-1);
bottom = SCREENHEIGHT-1;
}
// ------- initialize window dimensions
lf = left;
tp = top;
rt = right;
bt = bottom;
// ------- initialize window colors
fg = wfg;
bg = wbg;
// ------- initialize window cursor and tab stops
row = col = 0;
tabs = TABS;
// ---------- save the video rectangle under the new window
wsave = new unsigned[HEIGHT * WIDTH];
hsave = NULL;
savevideo(wsave, tp, lf, bt, rt);
// --------- draw the window frame
box(tp, lf, bt, rt, fg, bg);
// -------- clear the window text area
clear_window();
unhidecursor();
}

// ------- destructor for a Window
Window::~Window(void)
{
// ----- restore the video RAM covered by the window
restorevideo(wsave, tp, lf, bt, rt);
delete wsave;
if (hsave != NULL)
delete hsave;
restorecursor();
}

// ------- hide a window without destroying it
void Window::hidewindow(void)
{
if (hsave == NULL) {
hsave = new unsigned[HEIGHT * WIDTH];
savevideo(hsave, tp, lf, bt, rt);
restorevideo(wsave, tp, lf, bt, rt);
}
}

// --------- restore a hidden window
void Window::restorewindow(void)
{
if (hsave != NULL) {
savevideo(wsave, tp, lf, bt, rt);
restorevideo(hsave, tp, lf, bt, rt);
delete hsave;
hsave = NULL;
colors(fg,bg);
}
}

// -------- add a title to a window
void Window::title(char *ttl)
{
setcursor(lf + (WIDTH - strlen(ttl) - 1) / 2, tp);
colors(fg, bg);
window_printf(" %s ", ttl);
cursor(col, row);
}

// ------- write text body to a window
Window& Window::operator<<(char **btext)
{
cursor(0, 0);
text = btext;
if (*btext != NULL)
*this << *btext++;
while (*btext != NULL && row < HEIGHT-3)
*this << '\n' << *btext++;
}

// -------- write a line of text to a window
Window& Window::operator<<(char *ltext)
{
while (*ltext && col < WIDTH - 2 && row < HEIGHT - 2)
*this << *ltext++;
return *this;
}

// -------- write a character to a window
Window& Window::operator<<(char ch)
{
cursor(col, row);
switch (ch) {
case '\n':
clreol();
if (row == HEIGHT-3)
scroll(1);
else
row++;
case '\r':
col = 0;
break;
case '\b':
if (col)
--col;
break;
case '\t':
do
*this << ' ';
while (col % tabs);
break;
default:
if (col == WIDTH - 2)
*this << '\n';
colors(fg,bg);
window_putc(ch);
col++;
return *this;
}
cursor(col, row);
return *this;
}

// ----- position the window cursor
void Window::cursor(unsigned x, unsigned y)
{
if (x < WIDTH-2 && y < HEIGHT-2) {
setcursor(lf+1+x, tp+1+y);
row = y;
col = x;
}
}

// ------ clear a window to all blamks
void Window::clear_window(void)
{
cursor(0,0);
clreos();
}

// --- clear from current cursor position to end of window
void Window::clreos(void)
{
unsigned rw = row, cl = col;
clreol();
col = 0;
while (++row < HEIGHT-2)
clreol();
row = rw;
col = cl;
}

// --- clear from current cursor position to end of line
void Window::clreol(void)
{
unsigned cl = col;
colors(fg,bg);
while (col < WIDTH-2)
*this << ' ';
col = cl;
}

// ----- page and scroll through the text file
void Window::page(void)
{
int c = 0, lines = 0;
char **tx = text;

hidecursor();
// ------ count the lines of text
while (*(tx + lines) != NULL)
lines++;
while (c != ESC) {
c = getkey();
char **htext = text;
switch (c) {
case UP:
if (tx != text) {
--tx;
scroll(-1);
unsigned x, y;
cursor(&x, &y);
cursor(0, 0);
*this << *tx;
cursor(x, y);
}
continue;
case DN:
if (tx+HEIGHT-3 < text+lines-1) {
tx++;
scroll(1);
unsigned x, y;
cursor(&x, &y);
cursor(0, HEIGHT-3);
*this << *(tx + HEIGHT - 3);
cursor(x, y);
}
continue;
case PGUP:
tx -= HEIGHT-2;
if (tx < text)
tx = text;
break;
case PGDN:
tx += HEIGHT-2;
if (tx+HEIGHT-3 < text+lines-1)
break;
case END:
tx = text+lines-(HEIGHT-2);
if (tx > text)
break;
case HOME:
tx = text;
break;
default:
continue;
}
*this << tx;
text = htext;
clreos();
}
unhidecursor();
}

// --------- scroll a window
void Window::scroll(int d)
{
videoscroll(d, tp+1, lf+1, bt-1, rt-1, fg, bg);
}

// ------ utility notice window
Notice::Notice(char *text)
: ((SCREENWIDTH-(strlen(text)+2)) / 2, 11,
((SCREENWIDTH-(strlen(text)+2)) / 2) + strlen(text)+2,
14, NOTICEFG, NOTICEBG)
{
*this << text << "\n Any key ...";
hidecursor();
getkey();
unhidecursor();
hidewindow();
}

// ------ utility error window
Error::Error(char *text)
: ( (SCREENWIDTH-(strlen(text)+2)) / 2, 11,
((SCREENWIDTH-(strlen(text)+2)) / 2) + strlen(text)+2,
14, ERRORFG, ERRORBG)
{
*this << text << "\n Any key ...";
hidecursor();
getkey();
unhidecursor();
hidewindow();
}

// ------ utility yes/no window
YesNo::YesNo(char *text)
: ( (SCREENWIDTH-(strlen(text)+10)) / 2, 11,
((SCREENWIDTH-(strlen(text)+10)) / 2) + strlen(text)+10,
13, YESNOFG, YESNOBG)
{
*this << text << "? (Y/N) ";
int c = 0;
hidecursor();
while (tolower(c) != 'y' && tolower(c) != 'n')
c = getkey();
unhidecursor();
hidewindow();
answer = tolower(c) == 'y';
}



[LISTING THREE]

/* ----------- console.h -------- */

#ifndef CONSOLE
#define CONSOLE

#include

// -------- cursor and keyboard functions (via BIOS)
void hidecursor(void);
void unhidecursor(void);
void savecursor(void);
void restorecursor(void);
int getkey(void);

// -------- key values returned by getkey()
#define BELL 7
#define ESC 27
#define UP 200
#define BS 203
#define FWD 205
#define DN 208
#define HOME 199
#define END 207
#define PGUP 201
#define PGDN 209

#define attr(fg,bg) ((fg)+(((bg)&7)<<4))

// --------- video functions (defined as Zortech C++ equivalents)
#define initconsole() disp_open()
#define closeconsole() disp_flush()
#define savevideo(bf,t,l,b,r) disp_peekbox(bf,t,l,b,r)
#define restorevideo(bf,t,l,b,r) disp_pokebox(bf,t,l,b,r)
#define box(t,l,b,r,fg,bg) disp_box(1,attr(fg,bg),t,l,b,r)
#define colors(fg,bg) disp_setattr(attr(fg,bg))
#define setcursor(x,y) disp_move(y,x)
#define window_printf disp_printf
#define window_putc disp_putc
#define videoscroll(d,t,l,b,r,fg,bg) \
disp_scroll(d,t,l,b,r,attr(fg,bg));


#endif



[LISTING FOUR]

/* ----------- console.c --------- */

/* PC-specific console functions */

#include
#include
#include "console.h"

/* ------- video BIOS (0x10) functions --------- */
#define VIDEO 0x10
#define SETCURSORTYPE 1
#define SETCURSOR 2
#define READCURSOR 3
#define HIDECURSOR 0x20

#define SAVEDEPTH 20 /* depth to which cursors are saved */

static int cursorpos[SAVEDEPTH];
static int cursorshape[SAVEDEPTH];
static int sd;

union REGS rg;

/* ---- Low-level get cursor shape and position ---- */
static void getcursor(void)
{
rg.h.ah = READCURSOR;
rg.h.bh = 0;
int86(VIDEO,&rg,&rg);
}

/* ---- Save the current cursor configuration ---- */
void savecursor(void)
{
getcursor();
if (sd < SAVEDEPTH) {
cursorshape[sd] = rg.x.cx;
cursorpos[sd++] = rg.x.dx;
}
}

/* ---- Restore the saved cursor configuration ---- */
void restorecursor(void)
{
if (sd) {
rg.h.ah = SETCURSOR;
rg.h.bh = 0;
rg.x.dx = cursorpos[--sd];
int86(VIDEO,&rg,&rg);
rg.h.ah = SETCURSORTYPE;
rg.x.cx = cursorshape[sd];
int86(VIDEO,&rg,&rg);
}
}

/* ---- Hide the cursor ---- */
void hidecursor(void)
{
getcursor();
rg.h.ch |= HIDECURSOR;
rg.h.ah = SETCURSORTYPE;
int86(VIDEO,&rg,&rg);
}

/* ---- Unhide the cursor ---- */
void unhidecursor(void)
{
getcursor();
rg.h.ch &= ~HIDECURSOR;
rg.h.ah = SETCURSORTYPE;
int86(VIDEO,&rg,&rg);
}

/* ---- Read a keystroke ---- */
int getkey(void)
{
rg.h.ah = 0;
int86(0x16,&rg,&rg);
if (rg.h.al == 0)
return (rg.h.ah | 0x80) & 255;
return rg.h.al & 255;
}

[LISTING FIVE]

// ---------- look.c

// A C++ program to demonstrate the use of the window library.
// This program lets you view a text file

#include
#include
#include
#include
#include "window.h"

#define MAXLINES 200 // maximum number of text lines

static char *wtext[MAXLINES+1]; // pointers to text lines

// --- taken from BS; handles all free store (heap) exhaustions
void out_of_store(void);
typedef void (*PF)();
extern PF set_new_handler(PF);

main(int argc, char *argv[])
{
set_new_handler(&out_of_store);
if (argc > 1) {
// ---- open a full-screen window
Window wnd(0,0,79,24,CYAN,BLUE);
char ttl[80];
// ------ put the file name in the title
sprintf(ttl, "Viewing %s", argv[1]);
wnd.title(ttl);
filebuf buf;
if (buf.open(argv[1], input)) {
istream infile(&buf);
int t = 0;
// --- read the file and load the pointer array
char bf[120], *cp = bf;
while (t < MAXLINES && !infile.eof()) {
infile.get(*cp);
if (*cp != '\r') {
if (*cp == '\n') {
*cp = '\0';
wtext[t] = new char [strlen(bf)+1];
strcpy(wtext[t++], bf);
cp = bf;
}
else
cp++;
}
}
wtext[t] = NULL;
// ---- write all the text to the window
wnd << wtext;
// ---- a YesNo window
YesNo yn("Continue");
if (yn.answer)
wnd.page();
// ------ a Notice window
Notice nt("All done.");
}
else
// ------ error windows
Error err("No such file");
}
else
Error err("No file name specified");
}

// ----- the BS free-store exhaustion handler
void out_of_store(void)
{
cerr << "operator new failed: out of store\n";
exit(1);
}



  3 Responses to “Category : Files from Magazines
Archive   : DDJ-LIB.ZIP
Filename : WINDOWS.CPP

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/