home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Boldly Go Collection
/
version40.iso
/
TS
/
17A
/
DRWIN101.ZIP
/
WUTIL.C
< prev
next >
Wrap
C/C++ Source or Header
|
1991-08-19
|
60KB
|
1,110 lines
/****************************************************************************/
/* MODULE wutil.c */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This module contains windowing utilities for use in text mode on IBM */
/* PC's. */
/*-----------------------------Constraints/Gotchas--------------------------*/
/* These functions will only work on an IBM PC in text mode. */
/* Function descriptions will NOT list those functions available in both */
/* Turbo C and Microsoft C (such as int86() in [dos.h]). It is assumed */
/* that the reader is familiar with these non-ANSII functions. */
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 (c) D. Rogers initial code */
/****************************************************************************/
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <string.h>
#include <conio.h>
#include <dos.h>
#include "strutil.h"
#include "scrutil.h"
#include "wutil.h"
char winitd=0; /*flag for windows initialization*/
char wupd=1; /*flag for updating*/
char wcga=0; /*don't check for CGA retrace scan*/
WORD wscr_size=0; /*bytes in original screen*/
WORD *vscr; /*pointer to virtual screen*/
WORD far *vidp; /*pointer to video segment*/
WIND *wscr; /*original screen, base window*/
WIND *wact; /*current active window pointer*/
/****************************************************************************/
/* winit */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function initializes the windowing environment. Make sure this */
/* function is not called twice without calling wpurge(). */
/*-----------------------------Arguments------------------------------------*/
/*-----------------------------Return value---------------------------------*/
/* winit() returns 1 if everything checks out ok, 0 otherwise (if no */
/* memory was available for the virtual screen, etc.). */
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
int winit(void)
{
WORD rs,cs; /*rows and columns on original screen*/
if (winitd) return 0; /*if already initialized*/
switch (getsmod()) { /*check the mode*/
case MONO_80_25:
vidp=MONO_POINTER; /*...set mono video pointer*/
break;
case TEXT_40_25_BW:
case TEXT_40_25:
case TEXT_80_25_BW:
case TEXT_80_25:
case TEXT_80_HI:
vidp=COLOR_POINTER; /*...set color video pointer*/
break;
default:
return 0; /*..unknown/nontext video mode*/
} /*switch on video mode*/
rs=getsrows(); /*rows available on screen*/
cs=getscols(); /*columns available on screen*/
wscr_size=rs*cs*2; /*get number of bytes in original scr*/
vscr=(WORD *)malloc(wscr_size); /*set up virtual screen*/
if (vscr==NULL) return 0; /*oops! no room*/
wscr=(WIND *)malloc(sizeof(WIND)+wscr_size);
wact=wscr; /*active is base*/
if (wscr==NULL) { free(vscr); return 0; } /*oops! no room*/
/*set first window to be original screen...*/
wscr->rows=rs; /*set rows as calc'd above*/
wscr->cols=cs; /*set cols as calc'd above*/
wscr->srow=0; /*window starts in row 0 on screen*/
wscr->scol=0; /*window starts in column 0 on screen*/
wscr->row =getcrow(); /*save screen cursor row*/
wscr->col =getccol(); /*save screen cursor column*/
wscr->csiz=getcsiz(); /*save screen cursor size*/
wscr->attr=(BLACK<<4)+LIGHTGRAY; /*default low intensity white on black*/
wscr->fchr=' '; /*default to space as fill char*/
wscr->battr=wscr->attr; /*no border, but set attribute anyway*/
wscr->prompt=NULL; /*set prompt pointer*/
wscr->bord=0; /*no border*/
wscr->fl.wrap=1; /*wrap text at end of line*/
wscr->fl.scroll=1; /*scroll window at bottom*/
wscr->fl.moves=0; /*no window moving allowed*/
wscr->fl.sizes=0; /*no window resizing*/
wscr->fl.alive=1; /*definitely show this window*/
wscr->fl.saved=0; /*not yet saved*/
wscr->fl.showcr=0; /*don't show little note character*/
wscr->fl.showlf=0; /*ditto for LF one*/
wscr->fl.showbs=0; /*ditto for BS one*/
wscr->wprv=NULL; /*previous window is nonexistent*/
wscr->wnxt=NULL; /*next window is also nonexistent*/
#if defined(__TINY__)||defined(__SMALL__)||defined(__MEDIUM__)
memcpynfi(wscr->wtxt,vidp,wscr_size); /*save screen into text buffer*/
#else
memcpyi(wscr->wtxt,vidp,wscr_size); /*save screen into text buffer*/
#endif
memcpyi(vscr,wscr->wtxt,wscr_size); /*update virtual screen*/
winitd=1; /*indicate that now initialized*/
return 1; /*all done!*/
} /*winit*/
/****************************************************************************/
/* wvscr */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function writes the virtual screen into the real screen. */
/*-----------------------------Arguments------------------------------------*/
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
void wvscr(void)
{
if (wcga) ; /*check for CGA retrace scan here*/
#if defined(__TINY__)||defined(__SMALL__)||defined(__MEDIUM__)
memcpyfni(vidp,vscr,wscr_size); /*copy virtual to actual screen*/
#else
memcpyi(vidp,vscr,wscr_size); /*copy virtual to actual screen*/
#endif
} /*wvscr*/
/****************************************************************************/
/* wsetDOSscr, wgetDOSscr */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* These functions allow easy access to DOS system calls. */
/* wsetDOSscr() makes the base window, wscr, the active window and hides */
/* all other windows. It should be called before calling system() or */
/* spawnXXX() (or execXXX()). Upon return, you should call wgetDOSscr(). */
/* wgetDOSscr() copies the screen into the base window, wscr, and unhides */
/* all windows previously hidden. */
/*-----------------------------Arguments------------------------------------*/
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Global constants-----------------------------*/
/*-------------------Mod-------Global variables-----------------------------*/
/*-----------------------------Functions called-----------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 A. Turing initial code */
/****************************************************************************/
void wsetDOSscr(void)
{
WIND *w;
if (!winitd) return; /*return at end*/
wupd=1; /*turn on update*/
w=wscr->wnxt;
while (w!=NULL) {
w->fl.saved=0;
if (w->fl.alive) { /*if not hidden..*/
w->fl.alive=0; /*..hide and*/
w->fl.saved=1; /*..indicate we've done so*/
} /*if not hidden*/
w=w->wnxt;
} /*while*/
wupdate(NULL);
} /*wsetDOSscr*/
void wgetDOSscr(void)
{
WIND *w;
if (!winitd) return; /*return at end*/
wupd=1; /*turn on update*/
wscr->row =getcrow(); /*save screen cursor row*/
wscr->col =getccol(); /*save screen cursor column*/
wscr->csiz=getcsiz(); /*save screen cursor size*/
#if defined(__TINY__)||defined(__SMALL__)||defined(__MEDIUM__)
memcpynfi(wscr->wtxt,vidp,wscr_size); /*save screen into text buffer*/
#else
memcpyi(wscr->wtxt,vidp,wscr_size); /*save screen into text buffer*/
#endif
w=wscr->wnxt;
while (w!=NULL) {
if (w->fl.saved) w->fl.alive=1; /*if hidden by wsetDOSscr, unhide*/
w->fl.saved=0;
w=w->wnxt;
} /*while*/
wupdate(NULL);
} /*wgetDOSscr*/
/****************************************************************************/
/* wvbord */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function writes the border for a window to the virtual screen. */
/*-----------------------------Arguments------------------------------------*/
/* WIND *w window for which border is to be made */
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
void wvbord(WIND *w)
{
#define TOPLEFT 0 /*mneumonics for graphics chars...*/
#define HORIZ 1
#define TOP_T 2
#define TOPRIGHT 3
#define VERT 4
#define LEFT_T 5
#define MIDDLE 6
#define RIGHT_T 7
#define BOTLEFT 8
#define BOT_T 9
#define BOTRIGHT 10
static BYTE *gcs[2]={ /*text mode graphics characters*/
"\xDA\xC4\xC2\xBF\xB3\xC3\xC5\xB4\xC0\xC1\xD9\x00",
"\xC9\xCD\xCB\xBB\xBA\xCC\xCE\xB9\xC8\xCA\xBC\x00"
};
BYTE gc[12]; /*text mode graphics characters copy*/
WORD ac; /*attribute:character*/
WORD *vp; /*pointer into virtual screen*/
BYTE *p; /*pointer to prompt*/
WORD k; /*row/col counter*/
WORD l; /*length*/
if (w->bord) { /*if border around window*/
ac=0; /*clear ac*/
HI(ac)=w->battr; /*get border attribute*/
if (w->bord>2) w->bord=1; /*make sure a legal value*/
memcpyi(gc,gcs[w->bord-1],12); /*copy text graphics characters*/
l=0; /*initialize length to 0*/
p=w->prompt; /*point to prompt*/
if (p!=NULL) l=strlen(p); /*get length of prompt*/
vp=(WORD *)vscr; /*start at top of screen*/
vp+=((w->srow-1)*wscr->cols); /*offset to first border row*/
vp+=(w->scol-1); /*offset to correct column*/
*vp++=ac|gc[TOPLEFT]; /*write top left character*/
for (k=0;k<w->cols;k++) { /*go through each column*/
if (k<l) /*if still writing prompt...*/
*vp++=ac|*p++; /*...write out prompt character*/
else /*otherwise...*/
*vp++=ac|gc[HORIZ]; /*...write out horizontal bar*/
} /*for*/
*vp++=ac|gc[TOPRIGHT]; /*write top right character*/
ac|=gc[VERT];
for (k=0;k<w->rows;k++) { /*write out side walls on each row*/
vp+=(wscr->cols-w->cols-2); /*point to left side wall*/
*vp++=ac; /*write out vertical character*/
vp+=w->cols; /*go to right wall*/
*vp++=ac; /*write out vertical character*/
} /*for*/
ac&=0xFF00; /*clear out the vertical character*/
vp+=(wscr->cols-w->cols-2); /*point to bottom left*/
*vp++=ac|gc[BOTLEFT]; /*write bottom left character*/
for (k=0;k<w->cols;k++) /*go through each column*/
*vp++=ac|gc[HORIZ]; /*write out horizontal*/
*vp++=ac|gc[BOTRIGHT]; /*write bottom right character*/
} /*if border*/
} /*wvbord*/
/****************************************************************************/
/* wupdate */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function updates the screen, starting with the base window and */
/* going up. */
/*-----------------------------Arguments------------------------------------*/
/* WIND *w window at which to start updating (NULL=from base) */
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
void wupdate(WIND *w)
{
WORD *vp; /*pointer into virtual screen*/
WORD *tp; /*window text pointer*/
WORD r; /*row counter*/
if (!winitd) return; /*return at end*/
wupd=1; /*turn on update*/
if (!w) w=wscr; /*if starting at base*/
for (;w!=NULL;w=w->wnxt) { /*go through each window*/
if (!w->fl.alive) continue; /*if not alive, don't update*/
wact=w; /*make active window this window*/
if (w->bord) wvbord(w); /*write out border if there is one*/
vp=(WORD *)vscr; /*start at top of screen*/
vp+=(w->srow*wscr->cols); /*offset to correct row*/
vp+=w->scol; /*offset to correct column*/
tp=w->wtxt; /*start in window*/
for (r=0;r<w->rows;r++) { /*go through each row*/
memcpyi(vp,tp,w->cols<<1); /*copying each line into virt screen*/
vp+=wscr->cols; /*inc virtual screen pointer 1 row*/
tp+=w->cols; /*inc window pointer 1 window row*/
} /*for each row*/
} /*for each window*/
wvscr(); /*write virtual screen to real screen*/
setcsiz(wact->csiz); /*set cursor size*/
setcpos(wact->srow+wact->row,wact->scol+wact->col); /*set curs position*/
} /*wupdate*/
/****************************************************************************/
/* wpurge */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function closes all windows and frees up all memory used by the */
/* windowing environment. After calling wpurge(), you are allowed to */
/* call winit() once again. */
/*-----------------------------Arguments------------------------------------*/
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
void wpurge(void)
{
WIND *wn;
WORD r,c,s; /*cursor row, column, size*/
if (!winitd) return;
memcpyi(vscr,wscr->wtxt,wscr_size); /*first save original screen*/
r=wscr->row; /*save original row*/
c=wscr->col; /*save original column*/
s=wscr->csiz; /*save original cursor size*/
wact=wscr->wnxt; /*start at first window*/
while (wact!=NULL) { /*go through each window from start*/
wn=wact->wnxt; /*get pointer to next window*/
free(wact); /*return memory to system*/
wact=wn; /*update pointer to window*/
} /*while*/
wvscr(); /*write virtual screen to screen*/
free(wscr); /*free up the base window memory*/
free(vscr); /*free memory for virtual screen*/
setcsiz(s); /*restore original cursor size*/
setcpos(r,c); /*restore cursor position*/
wupd=1; /*turn on update*/
winitd=0; /*not initialized anymore*/
} /*wpurge*/
/****************************************************************************/
/* wclose */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function closes a window by its window id. */
/*-----------------------------Arguments------------------------------------*/
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
void wclose(WIND *w)
{
if (!winitd) if (!winit()) return; /*if not initialized, return*/
if (w==NULL) return; /*return if bad pointer*/
(w->wprv)->wnxt=(w->wnxt); /*set previous to point to next*/
if (w->wnxt) (w->wnxt)->wprv=(w->wprv); /*set next to point to previous*/
free(w); /*return memory to system*/
if (wupd) wupdate(NULL); /*update screen*/
} /*wclose*/
/****************************************************************************/
/* wopen */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function opens a window with the given position and dimensions. */
/*-----------------------------Arguments------------------------------------*/
/* WORD bord number of graphic lines in border */
/* char *p pointer to prompt to appear in border */
/* WORD sr absolute screen row of upper left corner of window */
/* WORD sc absolute screen column of up-left corner of window */
/* WORD rows number of rows in window */
/* WORD cols number of columns in window */
/* WORD attr initial character attribute (colors) for window */
/*-----------------------------Return value---------------------------------*/
/* wopen() returns a pointer (WIND *) to the window just opened. This */
/* pointer is then used when calling the other windowing functions. */
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
WIND *wopen(WORD bord,char *p,WORD sr,WORD sc,WORD rows,WORD cols,WORD attr)
{
WORD wsiz; /*size of window*/
WORD ac; /*attribute:character*/
WORD *tp; /*pointer to window's text*/
if (!winitd) if (!winit()) return NULL; /*make sure initialized*/
if (bord>2) bord=0; /*border is 0 (no border), 1 or 2*/
if (!attr) attr=LIGHTGRAY; /*set default attribute*/
if (sr>=wscr->rows) sr=1; /*check screen row*/
if (sc>=wscr->cols) sc=1; /*check screen column*/
if ((sr+rows)>wscr->rows) rows=wscr->rows-sr-1; /*check last row*/
if ((sc+cols)>wscr->cols) cols=wscr->cols-sc-1; /*check last column*/
if ((rows==0)||(cols==0)) return NULL; /*couldn't recover*/
wsiz=(rows*cols)<<1; /*window size in bytes*/
wact->wnxt=(WIND *)malloc(sizeof(WIND)+wsiz); /*get memory*/
if (wact->wnxt==NULL) return NULL; /*no room!*/
(wact->wnxt)->wprv=wact; /*make new window point to old*/
wact=wact->wnxt; /*make active window point to new*/
wact->rows=rows; /*rows as provided*/
wact->cols=cols; /*columns as provided*/
wact->srow=sr; /*window starts in row 0 on screen*/
wact->scol=sc; /*window starts in column 0 on screen*/
wact->row =0; /*normal cursor row*/
wact->col =0; /*normal cursor column*/
wact->csiz=DEF_CSIZE; /*cursor size is default size*/
wact->attr=attr; /*default low intensity white on black*/
wact->fchr=' '; /*fill character for clearing*/
wact->prompt=p; /*set prompt pointer*/
wact->bord=bord; /*border lines as prescribed*/
wact->battr=attr; /*set border attribute*/
wact->fl.wrap=1; /*wrap text at end of line*/
wact->fl.scroll=1; /*scroll window at bottom*/
wact->fl.moves=0; /*no window moving allowed*/
wact->fl.sizes=0; /*no window resizing*/
wact->fl.alive=1; /*show it*/
wact->fl.saved=0; /*not saved yet*/
wact->fl.showcr=0; /*don't show little note character*/
wact->fl.showlf=0; /*ditto for LF one*/
wact->fl.showbs=0; /*ditto for BS one*/
wact->wnxt=NULL; /*next window is nonexistent*/
HI(ac)=wact->attr; /*put attribute for clearing*/
LO(ac)=wact->fchr; /*use clearing fill character*/
wsiz>>=1; /*size goes from bytes to words*/
tp=wact->wtxt; /*point to text of window*/
for (;wsiz>0;wsiz--) *tp++=ac; /*load clearing character into text*/
if (wupd) wupdate(wact); /*update the screen*/
return wact; /*return the window id*/
} /*wopen*/
/****************************************************************************/
/* wgetcrow, wgetccol, wgetcsiz */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* These functions get the cursor row, column and size, respectively, of */
/* the specified window. */
/*-----------------------------Arguments------------------------------------*/
/* WIND *w window from*/
/*-----------------------------Return value---------------------------------*/
/* Returns row, column or size of window. */
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
WORD wgetcrow(WIND *w)
{
if ((w==NULL)||!winitd) return 0; /*returns*/
return (w->row);
} /*wgetcrow*/
WORD wgetccol(WIND *w)
{
if ((w==NULL)||!winitd) return 0; /*returns*/
return (w->col);
} /*wgetccol*/
WORD wgetcsiz(WIND *w)
{
if ((w==NULL)||!winitd) return 0; /*returns*/
return (w->csiz);
} /*wgetccol*/
/****************************************************************************/
/* wsetcpos */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function sets the cursor position within a window. */
/*-----------------------------Arguments------------------------------------*/
/* WIND *w window for which cursor position is to be set */
/* WORD row row to set */
/* WORD col column to set */
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
void wsetcpos(WIND *w,WORD row,WORD col)
{
if ((w==NULL)||!winitd) return; /*if not initialized, hit the road*/
if ((row<w->rows)&&(col<w->cols)) { /*if legal row,column*/
w->row=row; /*set row*/
w->col=col; /*set column*/
if (wupd&&ptrcmp(w,wact)) /*if this is the active window...*/
setcpos(w->srow+w->row,w->scol+w->col); /*...display cursor*/
} /*if r,c ok*/
} /*wsetcpos*/
/****************************************************************************/
/* wsetcsiz */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function sets the cursor size of the specified window. If the */
/* window is the active one, it sets the size immediately on the screen. */
/*-----------------------------Arguments------------------------------------*/
/* WIND *w window for cursor sizing */
/* WORD siz size (start and stop scan lines) of cursor */
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
void wsetcsiz(WIND *w,WORD siz)
{
if ((w==NULL)||!winitd) return; /*return if stupid*/
w->csiz=siz; /*set window cursor size*/
if (wupd&&w->fl.alive&&ptrcmp(w,wact))
setcsiz(w->csiz); /*set on screen if active window*/
} /*wsetcsiz*/
/****************************************************************************/
/* wfcolor, wbcolor, wsetattr, wgetattr */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* These functions set the foreground and background colors of the given */
/* window, respectively. */
/*-----------------------------Arguments------------------------------------*/
/* WIND *w window whose attribute is to change */
/* WORD color color for foreground/background */
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/* Only the first 8 colors may be used as background colors (BLACK up to */
/* LIGHTGRAY). Higher colors which are used as background colors will */
/* result in a blinking attribute (see the BLINK constant in [wutil.h]). */
/* In monochrome mode, some adaptors turn on underscore for various */
/* attribute settings. */
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
void wfcolor(WIND *w,WORD color)
{
if ((w==NULL)||!winitd) return; /*leave*/
w->attr&=0xF0; /*clear foreground portion*/
w->attr|=(color&0x0F); /*insert new foreground color*/
} /*wfcolor*/
void wbcolor(WIND *w,WORD color)
{
if ((w==NULL)||!winitd) return; /*leave*/
w->attr&=0x0F; /*clear out previous background*/
w->attr|=((color<<4)&0xF0); /*insert new background*/
} /*wbcolor*/
WORD wsetattr(WIND* w,WORD attr)
{
WORD a; /*old attribute*/
if ((w==NULL)||!winitd) return 0; /*leave*/
a=w->attr; /*save old attribute*/
w->attr=attr; /*set attribute*/
return a; /*return old attribute*/
} /*wsetattr*/
WORD wgetattr(WIND *w)
{
if ((w==NULL)||!winitd) return 0; /*leave*/
return w->attr;
} /*wgetattr*/
/****************************************************************************/
/* wclr, wclrbor, wclreor, wclrbow, wclreow */
/****************************************************************************/
void wclr(WIND *w)
{
WORD k; /*counter*/
WORD *tp; /*text pointer*/
WORD ac; /*attribute:character*/
if ((w==NULL)||!winitd) return; /*leave if bad*/
k=w->rows*w->cols; /*calculate window size*/
tp=w->wtxt; /*point to window text*/
HI(ac)=(BYTE)w->attr; /*set up attribute*/
LO(ac)=(BYTE)w->fchr; /*set up fill character*/
for (;(k);k--) *tp++=ac; /*fill window with character*/
w->row=0; /*reset row*/
w->col=0; /*and column*/
if (wupd) wupdate(w); /*update window if necessary*/
} /*wclr*/
void wclrbor(WIND *w)
{
WORD c; /*column counter*/
WORD *tp; /*text pointer*/
WORD ac; /*attribute:character*/
if ((w==NULL)||!winitd) return; /*leave if bad*/
if (w->row>=w->rows) w->row=w->rows-1;
if (w->col>=w->cols) w->col=w->cols-1;
tp=w->wtxt; /*point to window text*/
tp+=w->row*w->cols; /*point to start of row*/
HI(ac)=(BYTE)w->attr; /*set up attribute*/
LO(ac)=(BYTE)w->fchr; /*set up fill character*/
for (c=0;c<=w->col;c++) *tp++=ac; /*fill character to cursor*/
if (wupd) wupdate(w); /*update window if necessary*/
} /*wclrbor*/
void wclreor(WIND *w)
{
WORD c; /*column counter*/
WORD *tp; /*text pointer*/
WORD ac; /*attribute:character*/
if ((w==NULL)||!winitd) return; /*leave if bad*/
if (w->row>=w->rows) w->row=w->rows-1;
if (w->col>=w->cols) w->col=w->cols-1;
tp=w->wtxt; /*point to window text*/
tp+=w->row*w->cols; /*point to start of row*/
tp+=w->col; /*point to column of row*/
HI(ac)=(BYTE)w->attr; /*set up attribute*/
LO(ac)=(BYTE)w->fchr; /*set up fill character*/
for (c=w->col;c<w->cols;c++) *tp++=ac; /*fill character from cursor*/
if (wupd) wupdate(w); /*update window if necessary*/
} /*wclreor*/
void wclrbow(WIND *w)
{
WORD k; /*counter*/
WORD *tp; /*text pointer*/
WORD ac; /*attribute:character*/
if ((w==NULL)||!winitd) return; /*leave if bad*/
if (w->row>=w->rows) w->row=w->rows-1;
if (w->col>=w->cols) w->col=w->cols-1;
tp=w->wtxt; /*point to window text*/
k=w->row*w->cols; /*go up to row*/
k+=w->col+1; /*go up to column, inclusive*/
HI(ac)=(BYTE)w->attr; /*set up attribute*/
LO(ac)=(BYTE)w->fchr; /*set up fill character*/
for (;(k);k--) *tp++=ac; /*fill character to cursor*/
if (wupd) wupdate(w); /*update window if necessary*/
} /*wclrbow*/
void wclreow(WIND *w)
{
WORD k; /*counter*/
WORD *tp; /*text pointer*/
WORD ac; /*attribute:character*/
if ((w==NULL)||!winitd) return; /*leave if bad*/
if (w->row>=w->rows) w->row=w->rows-1;
if (w->col>=w->cols) w->col=w->cols-1;
tp=w->wtxt; /*point to window text*/
tp+=w->row*w->cols; /*to row*/
tp+=w->col; /*to column*/
k=(w->rows-w->row-1)*w->cols; /*go up to row*/
k+=(w->cols-w->col); /*go from column, inclusive*/
HI(ac)=(BYTE)w->attr; /*set up attribute*/
LO(ac)=(BYTE)w->fchr; /*set up fill character*/
for (;(k);k--) *tp++=ac; /*fill character from cursor*/
if (wupd) wupdate(w); /*update window if necessary*/
} /*wclreow*/
/****************************************************************************/
/* wfront */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function brings the designated window to the front (makes it the */
/* active window). */
/*-----------------------------Arguments------------------------------------*/
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
void wfront(WIND *w)
{
if (!winitd) return; /*leave if no windows yet*/
if (w==NULL) return; /*leave if bad window*/
if (!ptrcmp(w,wact)&&!ptrcmp(w,wscr)) { /*do nothing if already active*/
(w->wprv)->wnxt=w->wnxt; /*make prev's next be my next*/
(w->wnxt)->wprv=w->wprv; /*make next's prev be my prev*/
wact->wnxt=w; /*make current active point to me*/
w->wprv=wact; /*point back at current active*/
w->wnxt=NULL; /*turn off forward pointer*/
wact=w; /*i'm active now*/
} /*if need to rearrange*/
w->fl.alive=1; /*unhide it*/
if (wupd) wupdate(w); /*update if already active*/
} /*wfront*/
/****************************************************************************/
/* wback */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function pushes the specified window to the back (i.e., just in */
/* front of the base window). */
/*-----------------------------Arguments------------------------------------*/
/* WIND *w window to push back */
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
void wback(WIND *w)
{
if (!winitd) return; /*leave if no windows yet*/
if (w==NULL) return; /*leave if bad window*/
if (!ptrcmp(w,wscr)) { /*do nothing if base window*/
(w->wprv)->wnxt=w->wnxt; /*make prev's next be my next*/
if (w->wnxt!=NULL) (w->wnxt)->wprv=w->wprv; /*make next's prev be prev*/
(wscr->wnxt)->wprv=w; /*have window atop base point to me*/
w->wnxt=wscr->wnxt; /*point to just past base window*/
w->wprv=wscr; /*point back at base*/
wscr->wnxt=w; /*have base point to me*/
} /*if need to rearrange*/
if (wupd) wupdate(NULL); /*update even if already active*/
} /*wback*/
void whide(WIND *w)
{
if (w==NULL) return;
w->fl.alive=0;
wback(w);
} /*whide*/
/****************************************************************************/
/* wdelrow */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function deletes the current row from the given window. It puts */
/* a blank line at the bottom of the window (with the current attribute). */
/*-----------------------------Arguments------------------------------------*/
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
void wdelrow(WIND *w)
{
WORD *tp; /*pointer to window text*/
WORD r; /*local row counter*/
WORD ac; /*atrr:char*/
WORD n; /*number of bytes to copy*/
if (!winitd) return; /*check initialization*/
if (w==NULL) return; /*check window pointer*/
w->col=0; /*resets column*/
if (w->row>=w->rows) { /*make sure row is ok*/
w->row=w->rows-1; /*reset to last row*/
} /*if bad row*/
tp=w->wtxt; /*point to top of text*/
tp+=w->row*w->cols; /*go to current row*/
n=w->cols<<1; /*bytes to copy per row*/
for (r=w->row;r<(w->rows-1);r++) { /*go through each row but last*/
memcpyi(tp,(tp+w->cols),n); /*copy next row of BYTEs*/
tp+=w->cols; /*point to next row of WORDs*/
} /*for*/
HI(ac)=w->attr; /*load attribute*/
LO(ac)=w->fchr; /*load fill char to clear*/
for (r=0;r<w->cols;r++) *tp++=ac; /*clear last line*/
if (wupd) wupdate(w); /*update window*/
} /*wdelrow*/
/****************************************************************************/
/* winsrow */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function inserts a row at the current cursor position. It fills */
/* the row with blanks of the current attribute setting, and deletes the */
/* bottom row of the window. */
/*-----------------------------Arguments------------------------------------*/
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
void winsrow(WIND *w)
{
WORD *tp,*tp2; /*pointer to window text*/
WORD r; /*local row counter*/
WORD ac; /*atrr:char*/
WORD n; /*number of bytes*/
if (!winitd) return; /*check initialization*/
if (w==NULL) return; /*check window pointer*/
w->col=0; /*reset column*/
if (w->row>=w->rows) { /*make sure row is ok*/
w->row=w->rows-1; /*reset to last row*/
} /*if bad row*/
tp=w->wtxt; /*point to top of text*/
tp+=(w->rows-1)*w->cols; /*go to last row*/
n=w->cols<<1; /*number of bytes=2*words*/
for (r=(w->rows-1);r>w->row;r--) { /*go through each row but current*/
tp2=tp;
tp2-=w->cols;
memcpyi(tp,tp2,n); /*copy from prev row of BYTEs*/
tp=tp2; /*point to previous row of WORDs*/
} /*for*/
HI(ac)=w->attr; /*load attribute*/
LO(ac)=w->fchr; /*load fill char since clearing*/
for (r=0;r<w->cols;r++) *tp++=ac; /*clear current row*/
if (wupd) wupdate(w); /*update window*/
} /*winsrow*/
/****************************************************************************/
/* wputc */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function writes a single character out to the window. */
/*-----------------------------Arguments------------------------------------*/
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
void wputc(WIND *w,int c)
{
WORD *tp; /*point to window's text*/
WORD ac=0; /*attribute:character*/
BYTE twupd; /*locally store wupd*/
BYTE show=1;
if ((w==NULL)||!winitd) return; /*return*/
if (w->row>=w->rows) w->row=w->rows-1; /*check row*/
if (w->col>=w->cols) w->col=w->cols-1; /*check column*/
switch (c) { /*check for special chars*/
case 0x0D: /*on CR...*/
if (w->fl.showcr) break;
show=0;
w->col=0; /*...go to beginning of line*/
break;
case 0x0A: /*on LF (newline)...*/
if (w->fl.showlf) break;
show=0;
(w->row)++; /*...go to next row*/
w->col=0; /*...beginning thereof*/
break;
case 0x08: /*if BS...*/
if (w->fl.showbs) break;
show=0;
if (w->col==0) { /*see if first column*/
if (w->fl.wrap&&(w->row>0)) { /*is wrap enabled?*/
w->col=w->cols-1; /*...back one row*/
(w->row)--; /*...at the end*/
} /*if not first row and wrap enabled*/
} /*if first column*/
else
(w->col)--; /*just decrement column*/
break;
default:
;
} /*switch*/
if (show) { /*see if showing after translation*/
HI(ac)=w->attr; /*set up current attribute*/
LO(ac)=(BYTE)c; /*set up passed character*/
tp=w->wtxt; /*point to text*/
tp+=(w->row*w->cols); /*go to row in window's text*/
tp+=w->col; /*go to column in window's text*/
*tp=ac; /*copy character*/
(w->col)++; /*ready for next character*/
} /*if showing character*/
if (w->col>=w->cols) { /*if wrapped*/
if (w->fl.wrap) { /*if wrapping enabled...*/
(w->row)++; /*...go to next row*/
w->col=0; /*...at beginning*/
} /*otherwise...*/
else w->col=w->cols-1; /*...just leave cursor at end*/
} /*if wrapped around end of row*/
if (w->row>=w->rows) { /*if scrolled*/
if (w->fl.scroll) { /*if scrolling enabled...*/
w->row=0; /*...set to first row for delrow call*/
twupd=wupd; /*...save wupd setting*/
wupd=0; /*...don't update when deleting row*/
wdelrow(w); /*...delete top row of window*/
wupd=twupd; /*...restore wupd setting*/
w->row=w->rows-1; /*...set to last row*/
w->col=0; /*...set to first column in row*/
} /*otherwise...*/
else w->row=0; /*...go back to top of window*/
} /*if scrolled at end of screen*/
if (wupd) wupdate(w);
} /*wputc*/
/****************************************************************************/
/* wputs */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function writes a string to a specified window. */
/*-----------------------------Arguments------------------------------------*/
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
void wputs(WIND *w,char *s)
{
BYTE twupd;
if (!winitd) if (!winit()) return; /*return if can't initialize*/
if (w==NULL) return; /*return if can't find window*/
twupd=wupd; /*save update flag*/
wupd=0; /*do wputc's before updating screen*/
while (*s) wputc(w,*s++); /*write out each character*/
wupd=twupd; /*reset internal flag*/
if (wupd) wupdate(w); /*update screen*/
} /*wputs*/
/****************************************************************************/
/* wputns */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function writes n characters to the screen, regardless of the */
/* presence of a NUL character. */
/*-----------------------------Arguments------------------------------------*/
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
void wputns(WIND *w,char *s,int n)
{
BYTE twupd;
if (!winitd) if (!winit()) return; /*return if can't initialize*/
if (w==NULL) return; /*return if can't find window*/
twupd=wupd; /*save update flag*/
wupd=0; /*do wputc's before updating screen*/
while (n--) wputc(w,*s++); /*write out each character*/
wupd=twupd; /*reset internal flag*/
if (wupd) wupdate(w); /*update screen*/
} /*wputs*/
/****************************************************************************/
/* wputrcs */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function positions the cursor in a window, then writes out the */
/* specified string */
/*-----------------------------Arguments------------------------------------*/
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
void wputrcs(WIND *w,WORD r,WORD c,char *s)
{
BYTE twupd;
if ((w==NULL)||!winit) return; /*leave*/
if ((r>=w->rows)||(c>=w->cols)) return;
w->row=r;
w->col=c;
twupd=wupd; /*save update flag*/
wupd=0;
while (*s) wputc(w,*s++); /*write out string*/
wupd=twupd; /*restore update flag*/
if (wupd) wupdate(w); /*update*/
} /*wputrcs*/
/****************************************************************************/
/* wprintf */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function performs a printf to the given window. */
/*-----------------------------Arguments------------------------------------*/
/* WIND *w window for printf */
/* BYTE *fmt format for printf */
/*-----------------------------Return value---------------------------------*/
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
void cdecl wprintf(WIND *w,char *fmt,...)
{
#define MAX_DATUM 256
static BYTE bs[MAX_DATUM]; /*256 bytes max for formatted data*/
va_list va; /*variable argument list*/
va_start(va,fmt); /*point to argument list*/
if ((w==NULL)||!winitd) return; /*leave if bad*/
vsprintf(bs,fmt,va); /*write to string*/
wputs(w,bs); /*write to window*/
va_end(va); /*close variable list pointers*/
} /*wprintf*/
/****************************************************************************/
/* wgetc */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function gets a character from the specified window at the */
/* current cursor position. The given window is first made active. */
/*-----------------------------Arguments------------------------------------*/
/* WIND *w window to use to read the character */
/*-----------------------------Return value---------------------------------*/
/* wgetc() returns the ASCII code of the key pressed. If a special */
/* function key is pressed, it returns the scan code plus 0x100 (256). */
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
int wgetc(WIND *w)
{
int c; /*character*/
if ((w==NULL)||!winitd) return 0; /*return if not initialized*/
w->fl.alive=1; /*make sure it's alive*/
if (!ptrcmp(w,wact)) wfront(w); /*bring window to front if necessary*/
#if 0
while (!kbhit()) {
if (scrollhit()) wmovew(w); /*move window*/
} /*while key not hit*/
#endif
c=(BYTE)getch(); /*get character*/
if (c) /*if normal character...*/
return (c); /*...just return it*/
else /*otherwise...*/
return (0x100+getch()); /*...add 0x100 to next char*/
} /*wgetc*/
int wgetce(WIND *w) /*get char and echo*/
{
int c;
c=wgetc(w); /*get char*/
if ((c>0)&&(c<0x100)) wputc(w,c); /*and echo*/
return (c);
}
/****************************************************************************/
/* wgets */
/****************************************************************************/
/*-----------------------------Description----------------------------------*/
/* This function reads a string in from a window. It ends when CR is */
/* pressed, or when ESC is pressed. The CR is NOT included in the */
/* return string. */
/*-----------------------------Arguments------------------------------------*/
/* WIND *w window */
/* BYTE *s string to receive characters */
/* int n maximum number of characters to read */
/*-----------------------------Return value---------------------------------*/
/* wgets() returns the number of characters actually received. */
/*-----------------------------Constraints/Gotchas--------------------------*/
/*--Date--------Programmer----------Comments--------------------------------*/
/* 1990.01.01 D. Rogers initial code */
/****************************************************************************/
int wgets(WIND *w,char *s,int n)
{
WORD k;
int c;
if (!winitd) return 0; /*leave if not initialized*/
if (w==NULL) return 0; /*leave if bad pointer*/
if (n<2) return 0; /*leave if no chars to get*/
n--; /*leave room for NUL at string's end*/
k=0; /*initialize counter*/
c=0; /*keep loop alive*/
while (c!=0x0D) { /*while not done*/
c=wgetc(w); /*get a character from the window*/
switch (c) {
case 0x0D: /*carriage return*/
break;
case 0x1B: /*escape character*/
k=0; /*reset string to 0*/
c=0x0D; /*tell loop we're done*/
break;
case 0x08:
if (k) {
wupd=0; /*turn off the automatic updates*/
wputc(w,'\x08'); /*write out a backspace*/
wputc(w,w->fchr); /*write out a fill character*/
wupd=1; /*turn updating back on*/
wputc(w,'\x08'); /*write out another backspace*/
k--; /*go back one in string*/
}
break;
default:
if ((k<n)&&(c<0x100)) { /*if not special key*/
s[k++]=(BYTE)c; /*load char and increment position*/
wputc(w,c); /*put out character*/
} /*if printable*/
} /*switch*/
} /*while*/
s[k]=0; /*put end marker in string*/
return (k); /*return number of chars read*/
} /*wgets*/