home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Simtel MSDOS 1992 September
/
Simtel20_Sept92.cdr
/
msdos
/
ddjmag
/
ddj8810.arc
/
C_COLU.ARC
/
WINDOW.C
< prev
Wrap
Text File
|
1988-08-30
|
8KB
|
388 lines
/* ----------------------- 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),(int far *) cl,
(unsigned) ((int far *) cp - (int far *) 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();
}