home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 June
/
SIMTEL_0692.cdr
/
msdos
/
turbo_c
/
turbbook.arc
/
TWINDOW.C
< prev
next >
Wrap
Text File
|
1987-10-22
|
14KB
|
641 lines
/* ----------------------- twindow.c --------------------- */
#include <stdio.h>
#include <ctype.h>
#include <stdarg.h>
#include <dos.h>
#include <alloc.h>
#include <stdlib.h>
#include <string.h>
#include "twindow.h"
#include "keys.h"
#define TABS 4
#define SCRNHT 25
#define SCRNWIDTH 80
#define ON 1
#define OFF 0
#define ERROR -1
/* -------- local prototypes ---------- */
redraw(WINDOW *wnd);
wframe(WINDOW *wnd);
dtitle(WINDOW *wnd);
int *waddr(WINDOW *wnd, int x, int y);
vswap(WINDOW *wnd);
vsave(WINDOW *wnd);
vrstr(WINDOW *wnd);
add_list(WINDOW *wnd);
beg_list(WINDOW *wnd);
remove_list(WINDOW *wnd);
insert_list(WINDOW *w1, WINDOW *w2);
#ifndef FASTWINDOWS
int dget(WINDOW *wnd, int x, int y);
verify_wnd(WINDOW **w1);
#endif
/*page*/
/* ---- array of border character sets ------ */
struct {
int nw, ne, se, sw, side, line;
} wcs[] = {
{218,191,217,192,179,196}, /* single line */
{201,187,188,200,186,205}, /* double line */
{214,183,189,211,186,196}, /* single top, double side */
{213,184,190,212,179,205}, /* double top, single side */
{194,194,217,192,179,196} /* pop-down menu */
};
/* ---- window structure linked list head & tail ---- */
WINDOW *listhead = NULL;
WINDOW *listtail = NULL;
int VSG; /* video segment address */
/* ----------- establish a new window -------------- */
WINDOW *establish_window(x, y, h, w)
{
WINDOW *wnd;
VSG = (vmode() == 7 ? 0xb000 : 0xb800);
if ((wnd = (WINDOW *) malloc(sizeof (WINDOW))) == NULL)
return NULL;
/* ------- adjust for out-of bounds parameters ------- */
WTITLE = "";
HEIGHT = min(h, SCRNHT);
WIDTH = min(w, SCRNWIDTH);
COL = max(0, min(x, SCRNWIDTH-WIDTH));
ROW = max(0, min(y, SCRNHT-HEIGHT));
WCURS = 0;
SCROLL = 0;
SELECT = 1;
BTYPE = 0;
VISIBLE = HIDDEN = 0;
PREV = NEXT = NULL;
FHEAD = FTAIL = NULL;
WBORDER=WNORMAL=PNORMAL=WTITLEC =
clr(BLACK, WHITE, BRIGHT);
WACCENT = clr(WHITE, BLACK, DIM);
if ((SAV = malloc(WIDTH * HEIGHT * 2)) == (char *) 0)
return NULL;
add_list(wnd);
#ifndef FASTWINDOWS
clear_window(wnd);
wframe(wnd);
#endif
return wnd;
}
/* ------ set the window's border --------- */
void set_border(WINDOW *wnd, int btype)
{
if (verify_wnd(&wnd)) {
BTYPE = btype;
redraw(wnd);
}
}
/* ------- set colors ----------- */
void set_colors(WINDOW *wnd,int area,int bg,int fg,int inten)
{
if (vmode() == 7) {
if (bg != WHITE && bg != BLACK)
return;
if (fg != WHITE && fg != BLACK)
return;
}
if (verify_wnd(&wnd)) {
if (area == ALL)
while (area)
WCOLOR [--area] = clr(bg, fg, inten);
else
WCOLOR [area] = clr(bg, fg, inten);
redraw(wnd);
}
}
/*page*/
/* ----- set the intensity of a window ------ */
void set_intensity(WINDOW *wnd, int inten)
{
int area = ALL;
if (verify_wnd(&wnd)) {
while (area) {
WCOLOR [--area] &= ~BRIGHT;
WCOLOR [area] |= inten;
}
redraw(wnd);
}
}
/* -------- set title ------------- */
void set_title(WINDOW *wnd, char *title)
{
if (verify_wnd(&wnd)) {
WTITLE = title;
redraw(wnd);
}
}
/* ------ redraw a window when an attribute changes ----- */
static redraw(WINDOW *wnd)
{
#ifndef FASTWINDOWS
int x, y, chat, atr;
for (y = 1; y < HEIGHT-1; y++)
for (x = 1; x < WIDTH-1; x++) {
chat = dget(wnd, x, y);
atr = (((chat>>8)&255) ==
PNORMAL ? WNORMAL : WACCENT);
displ(wnd, x, y, chat&255, atr);
}
wframe(wnd);
#endif
PNORMAL = WNORMAL;
}
/* ------------ display an established window ------------ */
void display_window(WINDOW *wnd)
{
if (verify_wnd(&wnd) && !VISIBLE) {
VISIBLE = 1;
#ifdef FASTWINDOWS
if (HIDDEN) {
HIDDEN = 0;
vrstr(wnd);
}
else {
vsave(wnd);
clear_window(wnd);
wframe(wnd);
}
#else
vswap(wnd);
#endif
}
}
/* ---------- close all windows -------------- */
void close_all()
{
WINDOW *sav, *wnd = listtail;
while (wnd) {
sav = PREV;
delete_window(wnd);
wnd = sav;
}
}
/*page*/
/* ------------ remove a window ------------------ */
void delete_window(WINDOW *wnd)
{
if (verify_wnd(&wnd)) {
hide_window(wnd);
free(SAV);
remove_list(wnd); /* remove window from list */
free(wnd);
}
}
/* ----------- hide a window --------------- */
void hide_window(WINDOW *wnd)
{
if (verify_wnd(&wnd) && VISIBLE) {
#ifndef FASTWINDOWS
vswap(wnd);
#else
vrstr(wnd);
#endif
HIDDEN = 1;
VISIBLE = 0;
}
}
/*page*/
#ifndef FASTWINDOWS
/* ------ reposition the window in its 3-axis plane ------ */
void repos_wnd(WINDOW *wnd, int x, int y, int z)
{
WINDOW *twnd;
int x1, y1, chat;
if (!verify_wnd(&wnd))
return;
twnd = establish_window(x+COL, y+ROW, HEIGHT, WIDTH);
twnd->_tl = WTITLE;
twnd->btype = BTYPE;
twnd->wcolor[BORDER] = WBORDER;
twnd->wcolor[TITLE] = WTITLEC;
twnd->wcolor[ACCENT] = WACCENT;
twnd->wcolor[NORMAL] = WNORMAL;
twnd->_wsp = SCROLL;
twnd->_cr = WCURS;
if (z != 1) {
remove_list(twnd);
if (z == 0)
insert_list(twnd, wnd);
else
beg_list(twnd);
}
for (y1 = 0; y1 < twnd->_wh; y1++)
for (x1 = 0; x1 < twnd->_ww; x1++) {
chat = dget(wnd, x1, y1);
displ(twnd, x1, y1, chat&255, (chat>>8)&255);
}
twnd->_wv = 1;
vswap(twnd);
hide_window(wnd);
free(SAV);
remove_list(wnd);
*wnd = *twnd;
insert_list(wnd, twnd);
remove_list(twnd);
free(twnd);
}
#endif
/* ----------- clear the window area -------------- */
void clear_window(WINDOW *wnd)
{
register int x1, y1;
if (verify_wnd(&wnd))
for (y1 = 1; y1 < HEIGHT-1; y1++)
for (x1 = 1; x1 < WIDTH-1; x1++)
displ(wnd,x1, y1, ' ', WNORMAL);
}
/* ------------ draw the window frame --------------- */
static wframe(WINDOW *wnd)
{
register int x1, y1;
if (!verify_wnd(&wnd))
return;
/* --------- window title -------------- */
displ(wnd,0, 0, NW, WBORDER);
dtitle(wnd);
displ(wnd,WIDTH-1, 0, NE, WBORDER);
/* ------------ window sides ----------------- */
for (y1 = 1; y1 < HEIGHT-1; y1++) {
displ(wnd,0, y1, SIDE, WBORDER);
displ(wnd,WIDTH-1, y1, SIDE, WBORDER);
}
/* --------------- bottom of frame ---------------- */
displ(wnd,0, y1, SW, WBORDER);
for (x1 = 1; x1 < WIDTH-1; x1++)
displ(wnd,x1, y1, LINE, WBORDER);
displ(wnd,x1, y1, SE, WBORDER);
}
/*page*/
/* ------------- displ the window title -------------------- */
static dtitle(WINDOW *wnd)
{
int x1 = 1, i, ln;
char *s = WTITLE;
if (!verify_wnd(&wnd))
return;
if (s) {
ln = strlen(s);
if (ln > WIDTH-2)
i = 0;
else
i = ((WIDTH-2-ln) / 2);
if (i > 0)
while (i--)
displ(wnd, x1++, 0, LINE, WBORDER);
while (*s && x1 < WIDTH-1)
displ(wnd, x1++, 0, *s++, WTITLEC);
}
while (x1 < WIDTH-1)
displ(wnd, x1++, 0, LINE, WBORDER);
}
/* ------------- window-oriented printf ---------------- */
void wprintf(WINDOW *wnd, char *ln, ...)
{
char dlin [100], *dl = dlin;
if (verify_wnd(&wnd)) {
va_list ap;
va_start(ap, ln);
vsprintf(dlin, ln, ap);
va_end(ap);
while (*dl)
wputchar(wnd, *dl++);
}
}
/*page*/
/* ------------ write a character to the window ---------- */
void wputchar(WINDOW *wnd, int c)
{
if (!verify_wnd(&wnd))
return;
switch (c) {
case '\n':
if (SCROLL == HEIGHT-3)
scroll(wnd, UP);
else
SCROLL++;
WCURS = 0;
break;
case '\t':
do displ(wnd,(WCURS++)+3,SCROLL+1,' ',WNORMAL);
while ((WCURS%TABS) && (WCURS+1) < WIDTH-1);
break;
default:
if ((WCURS+1) < WIDTH-1) {
displ(wnd, WCURS+1, SCROLL+1, c, WNORMAL);
WCURS++;
}
break;
}
}
/* ------- set window cursor --------- */
void wcursor(WINDOW *wnd, int x, int y)
{
if (verify_wnd(&wnd) && x < WIDTH-1 && y < HEIGHT-1) {
WCURS = x;
SCROLL = y;
cursor(COL+x+1, ROW+y+1);
}
}
/*page*/
/* ------ allow the user to make a window selection ------ */
int get_selection(WINDOW *wnd, int s, char *keys)
{
int c = 0, ky;
if (!verify_wnd(&wnd))
return 0;
SELECT = s;
while (c != ESC && c != '\r' && c != BS && c != FWD) {
accent(wnd);
c = get_char();
deaccent(wnd);
switch (c) {
case UP: if (SELECT > 1)
SELECT--;
else
SELECT = SCROLL+1;
break;
case DN: if (SELECT < SCROLL+1)
SELECT++;
else
SELECT = 1;
break;
case '\r':
case ESC:
case FWD:
case BS: break;
default: if (keys) {
ky = 0;
while (*(keys + ky)) {
if (*(keys+ky)==toupper(c) ||
*(keys+ky)==tolower(c))
return ky + 1;
ky++;
}
}
break;
}
}
return c == '\r' ? SELECT : c == ESC ? 0 : c;
}
union REGS rg;
/* ------- scroll a window's contents up or down --------- */
void scroll(WINDOW *wnd, int dir)
{
int row = HEIGHT-1, col, chat;
if (!verify_wnd(&wnd))
return;
if (NEXT == NULL && HEIGHT > 3 && VISIBLE) {
rg.h.ah = dir == UP ? 6 : 7;
rg.h.al = 1;
rg.h.bh = WNORMAL;
rg.h.cl = COL + 1;
rg.h.ch = ROW + 1;
rg.h.dl = COL + WIDTH - 2;
rg.h.dh = ROW + HEIGHT - 2;
int86(16, &rg, &rg);
return;
}
if (dir == UP) {
for (row = 2; row < HEIGHT-1; row++)
for (col = 1; col < WIDTH-1; col++) {
chat = dget(wnd, col, row);
displ(wnd,col,row-1,chat&255,(chat>>8)&255);
}
for (col = 1; col < WIDTH-1; col++)
displ(wnd, col, row-1, ' ', WNORMAL);
}
else {
for (row = HEIGHT-2; row > 1; --row)
for (col = 1; col < WIDTH-1; col++) {
chat = dget(wnd, col, row);
displ(wnd,col,row+1,chat&255,(chat>>8)&255);
}
for (col = 1; col < WIDTH-1; col++)
displ(wnd, col, row+1, ' ', WNORMAL);
}
}
/*page*/
#ifndef FASTWINDOWS
/* --- compute address of a window's display character --- */
static int *waddr(WINDOW *wnd, int x, int y)
{
WINDOW *nxt = NEXT;
int *vp;
if (!VISIBLE)
return (int *) (SAV+y*(WIDTH*2)+x*2);
x += COL;
y += ROW;
while (nxt) {
if (nxt->_wv)
if (x >= nxt->_wx && x <= nxt->_wx + nxt->_ww-1)
if (y >= nxt->_wy &&
y <= nxt->_wy + nxt->_wh-1) {
x -= nxt->_wx;
y -= nxt->_wy;
vp = (int *)
((nxt->_ws) +y*(nxt->_ww*2)+x*2);
return vp;
}
nxt = nxt->_nx;
}
return NULL;
}
/* ---------- display a character to a window --------- */
void displ(WINDOW *wnd, int x, int y, int ch, int at)
{
int *vp;
int vch = (ch&255)|(at<<8);
if ((vp = waddr(wnd, x, y)) != NULL)
*vp = vch;
else
vpoke(VSG,vad(x+COL,y+ROW),vch);
}
/*page*/
/* ----- get a displayed character from a window ----- */
static int dget(WINDOW *wnd, int x, int y)
{
int *vp;
if ((vp = waddr(wnd, x, y)) != NULL)
return *vp;
return vpeek(VSG,vad(x+COL,y+ROW));
}
/* ------------- low-level video functions --------------- */
/* ------- swap the video image with the save buffer ----- */
static vswap(WINDOW *wnd)
{
int x, y, chat;
int *bf = (int *) SAV;
for (y = 0; y < HEIGHT; y++)
for (x = 0; x < WIDTH; x++) {
chat = *bf;
*bf++ = dget(wnd, x, y);
displ(wnd, x, y, chat&255, (chat>>8)&255);
}
}
#else
/* -------- save video memory into the save buffer ---- */
static vsave(WINDOW *wnd)
{
int x, y;
int *bf = (int *) SAV;
for (y = 0; y < HEIGHT; y++)
for (x = 0; x < WIDTH; x++)
*bf++ = vpeek(VSG, vad(x+COL, y+ROW));
}
/*page*/
/* ----- restore video memory from the save buffer ----- */
static vrstr(WINDOW *wnd)
{
int x, y;
int *bf = (int *) SAV;
for (y = 0; y < HEIGHT; y++)
for (x = 0; x < WIDTH; x++)
vpoke(VSG,vad(x+COL,y+ROW), *bf++);
}
#endif
/* ----- (de)accent the line where SELECT points ------- */
void acline(WINDOW *wnd, int set)
{
int x, ch;
if (!verify_wnd(&wnd))
return;
for (x = 1; x < WIDTH - 1; x++) {
ch = dget(wnd, x, SELECT) & 255;
displ(wnd, x, SELECT, ch, set);
}
}
/* ---------- linked list functions --------- */
/* ----- add a window to the end of the list ------ */
static add_list(WINDOW *wnd)
{
if (listtail) {
PREV = listtail;
listtail->_nx = wnd;
}
listtail = wnd;
if (!listhead)
listhead = wnd;
}
/*page*/
/* ----- add a window to the beginning of the list ------ */
static beg_list(WINDOW *wnd)
{
if (listhead) {
NEXT = listhead;
listhead->_pv = wnd;
}
listhead = wnd;
if (!listtail)
listtail = wnd;
}
/* --------- remove a window from the list -------- */
static remove_list(WINDOW *wnd)
{
if (NEXT)
NEXT->_pv = PREV;
if (PREV)
PREV->_nx = NEXT;
if (listhead == wnd)
listhead = NEXT;
if (listtail == wnd)
listtail = PREV;
NEXT = PREV = NULL;
}
/* ----- insert w1 after w2 ------ */
static insert_list(WINDOW *w1, WINDOW *w2)
{
w1->_pv = w2;
w1->_nx = w2->_nx;
w2->_nx = w1;
if (w1->_nx == NULL)
listtail = w1;
else
w1->_nx->_pv = w1;
}
/*page*/
#ifndef FASTWINDOWS
/* ---- verify the presence of a window in the list ----- */
static verify_wnd(WINDOW **w1)
{
WINDOW *wnd;
if (*w1 == NULL)
*w1 = listtail;
else {
wnd = listhead;
while (wnd != NULL) {
if (*w1 == wnd)
break;
wnd = NEXT;
}
}
return *w1 != NULL;
}
#endif
WINDOW *ewnd = NULL;
/* ------- error messages ------- */
void error_message(char *s)
{
ewnd = establish_window(50, 22, 3, max(10, strlen(s)+2));
set_colors(ewnd, ALL, RED, YELLOW, BRIGHT);
set_title(ewnd, " ERROR! ");
display_window(ewnd);
wprintf(ewnd, s);
putchar(BELL);
}
void clear_message()
{
if (ewnd)
delete_window(ewnd);
ewnd = NULL;
}