home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
ddjmag
/
ddj8809.arc
/
STEVENS.LIS
< prev
next >
Wrap
File List
|
1988-08-22
|
12KB
|
502 lines
_C PROGRAMMING_
by
Al Stevens
Listing One
/* ---------- window.h ----------- */
void establish_window(int,int,int,int,int,int,int);
void window_title(char *);
void clear_window(void);
void delete_window(void);
void scroll_window(int);
void text_window(char **, int);
int select_window(int, int, int, int (*func)(int,int));
int getkey(void);
void hidecursor(void);
void set_cursor_type(unsigned);
void clear_screen(void);
void writeline(int, int, char *);
void current_window(void);
void error_message(char *);
#define MAX_WINDOWS 10 /* maximum windows open at once */
#define TRUE 1
#define FALSE 0
#define ERROR -1
#define BELL 7
#define ESC 27
#define SHIFT_HT 143
#define CTRL_T 20
#define CTRL_B 2
#define CTRL_D 4
#define ALT_D 160
#define ALT_F 161
#define ALT_E 146
#define ALT_O 152
#define ALT_S 159
#define F1 187
#define F2 188
#define F3 189
#define F4 190
#define F5 191
#define F6 192
#define F7 193
#define F8 194
#define F9 195
#define F10 196
#define ALT_F7 238
#define HOME 199
#define UP 200
#define PGUP 201
#define BS 203
#define FWD 205
#define END 207
#define DN 208
#define PGDN 209
#define INS 210
#define DEL 211
#define CTRL_HOME 247
#define CTRL_BS 243
#define CTRL_FWD 244
#define CTRL_END 245
/* --------- window definition structure ------------ */
struct wn {
int lf,tp,rt,bt; /* window position */
int ht,wd; /* window dimensions */
int wx, wy; /* window cursor */
int wtop; /* top text line */
int wlines; /* total text lines */
int fg,bg; /* window colors */
char *wsave; /* video memory save buffer */
char **wtext; /* pointer to text */
};
/* ------ internal Turbo C stuff ------- */
void far * pascal __vptr(int, int);
void pascal __vram(void far *, void far *, int);
extern struct {
char filler1[4];
char attribute;
char filler2[5];
char snow;
} _video;
/* ------------ window colors --------------- */
#define TEXTFG WHITE /* data display screen */
#define TEXTBG BLACK
#define BLOCKFG BLACK /* data blocks */
#define BLOCKBG WHITE
#define HELPBG WHITE /* help windows */
#define HELPFG BLACK
#define MENUBG WHITE /* menus */
#define MENUFG BLACK
#define SELECTBG BLACK /* menu selector bars */
#define SELECTFG WHITE
#define ENTRYFG WHITE /* data entry windows */
#define ENTRYBG BLACK
#define FIELDFG BLACK /* data entry fields */
#define FIELDBG WHITE
#define ERRORFG BLACK /* error messages */
#define ERRORBG WHITE
Listing Two
/* ----------------------- window.c --------------------- */
#include <stdio.h>
#include <alloc.h>
#include <string.h>
#include <conio.h>
#include <mem.h>
#include <dos.h>
#include <stdlib.h>
#include "window.h"
/* --------- window border characters ---------------- */
#define NW '\332'
#define NE '\277'
#define SE '\331'
#define SW '\300'
#define SIDE '\263'
#define LINE '\304'
int editing;
static union REGS rg;
/* --------- window definition structure ------------ */
struct wn wdo [MAX_WINDOWS];
int curr_wnd; /* current window */
struct wn wkw; /* a working window structure */
static void upline(void);
static void downline(void);
static void firstline(void);
static void lastline(void);
static void dline(int, int, int);
/* ----------- establish a new window -------------- */
void establish_window(left,top,right,bottom,foreg,backg,save)
{
if (curr_wnd < MAX_WINDOWS) {
if (curr_wnd)
wdo[curr_wnd-1] = wkw;
setmem(&wkw, sizeof(wkw), 0);
wkw.lf = left;
wkw.tp = top;
wkw.rt = right;
wkw.bt = bottom;
wkw.fg = foreg;
wkw.bg = backg;
wkw.wd = right+1-left;
wkw.ht = bottom-top-1;
if (save) {
if ((wkw.wsave=malloc((wkw.ht+2)*wkw.wd*2)) == NULL)
return;
gettext(left, top, right, bottom, wkw.wsave);
}
wdo[curr_wnd++] = wkw;
current_window();
clear_window();
}
}
/* ------- initialize the working window as current -------- */
void current_window()
{
window(wkw.lf,wkw.tp,wkw.rt,wkw.bt);
hidecursor();
if (wkw.fg || wkw.bg) {
textcolor(wkw.fg);
textbackground(wkw.bg);
}
}
/* ----------- set a window's title -------------- */
void window_title(char *ttl)
{
writeline((wkw.wd-strlen(ttl)) / 2, 1, ttl);
}
/* ------------ remove a window ------------------ */
void delete_window()
{
if (curr_wnd) {
if (wkw.wsave) {
puttext(wkw.lf,wkw.tp,wkw.rt,wkw.bt,wkw.wsave);
free(wkw.wsave);
}
setmem(wdo+curr_wnd-1, sizeof (struct wn), 0);
--curr_wnd;
if (curr_wnd) {
wkw = wdo[curr_wnd-1];
current_window();
}
}
}
/* ---- clear the window area and display the border ----- */
void clear_window()
{
int height, width, y = 1;
char line1[81], line2[81];
height = wkw.ht;
width = wkw.wd;
setmem(line1 + 1, width-1, LINE);
setmem(line2 + 1, width-1, ' ');
*line1 = NW;
line1[width-1] = NE;
line1[width] = '\0';
*line2 = SIDE;
line2[width-1] = SIDE;
line2[width] = '\0';
line1[width] = line2[width] = '\0';
writeline(1, y++, line1);
while (height--)
writeline(1, y++, line2);
*line1 = SW;
line1[width-1] = SE;
writeline(1, y, line1);
}
/* --------- scroll the window. d: 1 = up, 0 = dn ---------- */
void scroll_window(d)
{
if (_video.snow == 0)
movetext(wkw.lf+1, wkw.tp+1+d,
wkw.rt-1, wkw.bt-2+d,
wkw.lf+1, wkw.tp+2-d);
else {
rg.h.ah = d ? 6 : 7;
rg.h.al = 1;
rg.h.bh = _video.attribute;
rg.h.cl = wkw.lf;
rg.h.ch = wkw.tp;
rg.h.dl = wkw.rt-2;
rg.h.dh = wkw.bt-2;
int86(16, &rg, &rg);
}
}
/* ---------- display text in a window --------------- */
void text_window(char *txt[], int ln)
{
int height = wkw.ht;
wkw.wtext = txt;
wkw.wtop = ln;
wkw.wy = 1;
while (height-- && txt[ln-1])
dline(ln++, wkw.fg, wkw.bg);
wkw.wlines = 0;
while (*txt++)
wkw.wlines++;
}
static int lineno;
/* -------- page and scroll through a window of text -------- */
int
select_window(int ln,int foreg,int backg,int (*func)(int,int))
{
int c = 0;
int frtn;
int height, dln, ptop;
if (ln > wkw.wtop + wkw.ht-1 || ln < wkw.wtop)
text_window(wkw.wtext, ln);
else
wkw.wy = ln - wkw.wtop + 1;
while (TRUE) {
lineno = wkw.wtop + wkw.wy - 1;
ptop = wkw.wtop;
dline(lineno, foreg, backg);
if (wkw.wx == 0)
hidecursor();
else
gotoxy(wkw.wx, wkw.wy+1);
c = getkey();
if (c == '\r' || c == ESC)
break;
switch (c) {
case CTRL_HOME:
firstline();
break;
case CTRL_END:
lastline();
break;
case PGUP:
wkw.wtop -= wkw.ht;
if (wkw.wtop < 1)
wkw.wtop = 1;
break;
case PGDN:
wkw.wtop += wkw.ht;
if (wkw.wtop > wkw.wlines - (wkw.ht-1)) {
wkw.wtop = wkw.wlines - (wkw.ht-1);
if (wkw.wtop < 1)
wkw.wtop = 1;
}
break;
case UP:
upline();
break;
case DN:
downline();
break;
default:
if (!editing && wkw.wlines <= wkw.ht) {
if (c == HOME) {
firstline();
break;
}
if (c == END) {
lastline();
break;
}
}
if (func) {
frtn = (*func)(c, lineno);
if (frtn == ERROR)
putch(BELL);
else if (frtn) {
wkw.wy = frtn;
return frtn;
}
c = 0;
}
break;
}
switch (c) {
case HOME:
case CTRL_HOME:
case END:
case CTRL_END:
case PGUP:
case PGDN: if (wkw.wtop != ptop) {
height = wkw.ht;
dln = wkw.wtop;
while (height-- && wkw.wtext[dln-1])
dline(dln++, wkw.fg, wkw.bg);
break;
}
default: dline(lineno, wkw.fg, wkw.bg);
break;
}
}
return c == ESC ? 0 : lineno;
}
/* ---------- move up one line --------------- */
static void upline()
{
if (lineno > 1) {
if (wkw.wy == 1) {
if (wkw.wtop > 1) {
--wkw.wtop;
scroll_window(0);
}
}
else
--wkw.wy;
}
else if (wkw.wlines <= wkw.ht)
lastline();
}
/* ----------- move down one line ------------- */
static void downline()
{
if (lineno < wkw.wlines) {
if (wkw.wy == wkw.ht) {
scroll_window(1);
wkw.wtop++;
}
else
wkw.wy++;
}
else if (wkw.wlines <= wkw.ht)
firstline();
}
/* -------- move to the first line --------- */
static void firstline()
{
wkw.wtop = wkw.wy = 1;
}
/* -------- move to the last line --------- */
static void lastline()
{
wkw.wtop = wkw.wlines - (wkw.ht-1);
if (wkw.wtop < 1)
wkw.wtop = 1;
wkw.wy = wkw.ht;
if (wkw.wy > wkw.wlines)
wkw.wy = wkw.wlines;
}
char spaces[80] =
" ";
/* ------- display a line of text, highlight or normal ------ */
static void dline(ln, foreg, backg)
{
if (foreg || backg) {
textcolor(foreg);
textbackground(backg);
--ln;
writeline(2, ln-wkw.wtop+3, *(wkw.wtext + ln));
if (strlen(*(wkw.wtext + ln)) < wkw.wd-2)
writeline(2+strlen(*(wkw.wtext + ln)),
ln-wkw.wtop+3,
spaces + 79 - wkw.wd +
strlen(*(wkw.wtext + ln)) + 2 );
}
}
/* --------- write a line of text to video window ----------- */
void writeline(int x, int y, char *str)
{
int cl[80], *cp = cl;
while (*str)
*cp++ = (*str++ & 255) | (_video.attribute << 8);
__vram(__vptr(x+wkw.lf-1,y+wkw.tp-1),MK_FP(_DS,cl),cp-cl);
}
/* ------- use BIOS to hide the cursor ---------- */
void hidecursor()
{
rg.h.ah = 2;
rg.x.dx = 0x1900;
rg.h.bh = 0;
int86(0x10, &rg, &rg);
}
/* ----------- use BIOS to set the cursor type -------------- */
void set_cursor_type(unsigned t)
{
rg.x.ax = 0x0100;
rg.x.bx = 0;
rg.x.cx = t;
int86(0x10, &rg, &rg);
}
/* ----------- use BIOS to clear the screen ---------------- */
void clear_screen()
{
window(1,1,80,25);
gotoxy(1,1);
rg.h.al = ' ';
rg.h.ah = 9;
rg.x.bx = 7;
rg.x.cx = 2000;
int86(0x10, &rg, &rg);
}
void (*helpfunc)(void);
int helpkey;
/* ------------- read the keyboard ---------------- */
int getkey()
{
int c;
if ((c = getch()) == 0)
c = getch() | 128;
if (c == helpkey && helpfunc) {
(*helpfunc)();
c = getkey();
}
return c;
}
/* ------- write an error message ------------- */
void error_message(char *ermsg)
{
int lf = (80-strlen(ermsg)+2)/2;
int rt = lf+max(strlen(ermsg)+2,15);
establish_window(lf, 11, rt, 14, ERRORFG, ERRORBG, TRUE);
gotoxy(2,2);
cputs(ermsg);
gotoxy(2,3);
cputs("(Press [Esc])");
hidecursor();
do
putch(BELL);
while (getkey() != ESC);
delete_window();
}