home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
World of Shareware - Software Farm 2
/
wosw_2.zip
/
wosw_2
/
DATABASE
/
DPG.ZIP
/
VIDEO.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-04-23
|
22KB
|
1,181 lines
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dos.h>
#include "video.h"
#include "files.h"
#define background 0 /* Background colour */
#define foreground 7 /* Foreground colour */
#define attr (((background << 4) | foreground) << 8)
#define seg(p) *((unsigned *)&(p) + 1)
#define off(p) *((unsigned *)&(p))
static char datemaxday[] =
{
0,
31,
28,
31,
30,
31,
30,
31,
31,
30,
31,
30,
31,
};
int dir; /* Cursor direction */
int fieldno; /* Current field number for scroll edit */
static videopage; /* Segment part of pointer to video memory */
static currenty; /* Current Y coordinate for scrolling screens */
/* Check if last keystroke is an allowed cursor key, and if so, set
dir variable accordingly */
static setdir (int k,int directions)
{
dir = -1;
switch (k)
{
case '\r':
if (directions & DF_RETURN)
dir = DIR_RETURN;
break;
case 27:
if (directions & DF_ESC)
dir = DIR_ESC;
break;
case 18432:
if (directions & DF_UP)
dir = DIR_UP;
break;
case 20480:
if (directions & DF_DOWN)
dir = DIR_DOWN;
break;
case 19200:
if (directions & DF_LEFT)
dir = DIR_LEFT;
break;
case 19712:
if (directions & DF_RIGHT)
dir = DIR_RIGHT;
break;
case 18688:
if (directions & DF_PGUP)
dir = DIR_PGUP;
break;
case 20736:
if (directions & DF_PGDN)
dir = DIR_PGDN;
break;
case 18176:
if (directions & DF_HOME)
dir = DIR_HOME;
break;
case 20224:
if (directions & DF_END)
dir = DIR_END;
break;
case 20992:
if (directions & DF_INS)
dir = DIR_INS;
break;
case 21248:
if (directions & DF_DEL)
dir = DIR_DEL;
break;
}
return dir >= 0;
}
/* Return pointer into video memory for given X,Y coordinates */
static int far *calcptr (int x,int y)
{
int far *p;
if (y < 0)
y = currenty;
currenty = y;
seg (p) = videopage;
off (p) = y*2*80 + x*2;
return p;
}
/* Display a null-terminated ASCII string */
static void printzstr (int x,int y,char *s)
{
int far *p;
p = calcptr (x,y);
while (*s)
*p++ = *s++ + attr;
}
/* Convert an integer to ASCII representation */
static void zsprintint (char *s,long n,int l)
{
char buf[20];
sprintf (buf,"%%%dld",l);
sprintf (s,buf,n);
}
/* Convert a floating point number to ASCII representation */
static void zsprintfloat (char *s,double n,int l,int dec)
{
char buf[20];
if (dec <= 0)
sprintf (buf,"%%%d.0lf",l);
else
sprintf (buf,"%%%d.%dlf",l + dec + 1,dec);
sprintf (s,buf,n);
}
/* Convert a date to ASCII representation */
static void zsprintdate (char *s,unsigned short d)
{
sprintf (s,"%02d.%02d.%02d",dateday (d),datemonth (d),dateyear (d));
}
/* Display a character a given number of times */
static void printchars (int x,int y,int n,int c)
{
int far *p;
p = calcptr (x,y);
while (--n >= 0)
*p++ = c + attr;
}
/* Display a character */
static void printchar (int x,int y,int c)
{
printchars (x,y,1,c);
}
/* Draw an outline border using IBM graphics characters */
static void border (int x,int y,int width,int height)
{
int i;
printchar (x,y,0xda);
printchars (x + 1,y,width - 2,0xc4);
printchar (x + width - 1,y,0xbf);
for (i=height-2; i; i--)
{
printchar (x,y + i,0xb3);
printchar (x + width - 1,y + i,0xb3);
}
printchar (x,y + height - 1,0xc0);
printchars (x + 1,y + height - 1,width - 2,0xc4);
printchar (x + width - 1,y + height - 1,0xd9);
}
/* Allocate memory with error checking */
static void *alloc (int n)
{
void *p;
p = malloc (n);
if (p == 0)
{
printf ("Out of memory");
exit (1);
}
return p;
}
/* Save a portion of the screen in a buffer allocated for the purpose */
static void *stashvideo (int x,int y,int width,int height)
{
int *result,*dest;
int far *src,far *q;
int i;
src = calcptr (x,y);
result = dest = alloc (width*height*2);
do
{
q = src;
i = width;
do
*dest++ = *q++;
while (--i);
src += 80;
}
while (--height);
return result;
}
/* Restore a portion of the screen from a buffer and free the buffer */
static void fetchvideo (int x,int y,int width,int height,void *data)
{
int far *dest,far *p;
int *src;
int i;
dest = calcptr (x,y);
src = data;
do
{
p = dest;
i = width;
do
*p++ = *src++;
while (--i);
dest += 80;
}
while (--height);
free (data);
}
void beep (void)
{
putchar (7);
fflush (stdout);
}
/* Initialize variables and clear the screen */
void initvideo (void)
{
union REGS r;
int far *p,far *q;
int i,j;
r.x.ax = 0x0f00;
int86 (0x10,&r,&r);
videopage = 0xb800;
if (r.h.al == 7)
videopage = 0xb000;
seg (p) = videopage;
off (p) = 0;
i = 25;
do
{
q = p;
p += 80;
j = 80;
do
*q++ = attr;
while (--j != 0);
}
while (--i != 0);
}
/* Put hardware cursor at given coordinates */
void cursor (int x,int y)
{
union REGS r;
if (y < 0)
y = currenty;
r.h.ah = 2;
r.h.dh = y;
r.h.dl = x;
r.h.bh = 0;
int86 (0x10,&r,&r);
}
/* Get a keystroke from the user */
getkey (void)
{
int k;
k = bioskey (0);
if (k & 0xff)
k &= 0xff;
return k;
}
/* Display a string with given number of characters */
void printstr (int x,int y,char *s,int l)
{
int far *p;
p = calcptr (x,y);
while (--l >= 0)
*p++ = *s++ + attr;
}
/* Display an integer using given number of digits */
void printint (int x,int y,long n,int l)
{
char s[20];
zsprintint (s,n,l);
printzstr (x,y,s);
}
/* Display a floating point number using given number of digits */
void printfloat (int x,int y,double n,int l,int dec)
{
char s[20];
zsprintfloat (s,n,l,dec);
printzstr (x,y,s);
}
/* Display a date */
void printdate (int x,int y,unsigned short d)
{
char s[20];
zsprintdate (s,d);
printzstr (x,y,s);
}
/* Input integer value from user */
void editlong (long *n,int l,int x,int y,int directions)
{
int _l;
int k;
int changed;
char s[20];
cursor (x,y);
LOOP:
changed = 0;
zsprintint (s,*n,l);
_l = 0;
for (;;)
{
printzstr (x,y,s);
k = getkey ();
if (setdir (k,directions))
{
*n = atol (s);
printint (x,y,*n,l);
return;
}
if (k == 8)
{
if (_l > 0)
{
memmove (s + 1,s,l - 1);
s[0] = ' ';
_l--;
continue;
}
goto LOOP;
}
if (k >= '0' && k <= '9' && _l != l)
{
if (!changed)
{
changed = 1;
strset (s,' ');
}
memmove (s,s + 1,l - 1);
s[l - 1] = k;
_l++;
}
}
}
void editbyte (signed char *n,int l,int x,int y,int directions)
{
long t;
t = *n;
editlong (&t,l,x,y,directions);
*n = t;
}
void editshort (short *n,int l,int x,int y,int directions)
{
long t;
t = *n;
editlong (&t,l,x,y,directions);
*n = t;
}
/* Input floating point value from user */
void editfloat (double *n,int l,int dec,int x,int y,int directions)
{
int _l,_dec;
int k;
int changed;
char s[20];
if (dec == 0)
dec = -1;
cursor (x,y);
LOOP:
changed = 0;
zsprintfloat (s,*n,l,dec);
_l = 0;
_dec = -1;
for (;;)
{
printzstr (x,y,s);
k = getkey ();
if (setdir (k,directions))
{
*n = atof (s);
printfloat (x,y,*n,l,dec);
return;
}
if (k == 8)
{
if (_dec > 0)
{
s[l + _dec] = ' ';
_dec--;
continue;
}
if (_dec == 0)
{
_dec = -1;
continue;
}
if (_l > 0)
{
memmove (s + 1,s,l - 1);
s[0] = ' ';
_l--;
continue;
}
goto LOOP;
}
if (k >= '0' && k <= '9')
{
if (!changed)
{
changed = 1;
strset (s,' ');
if (dec >= 0)
s[l] = '.';
}
if (_dec < 0)
{
if (_l == l)
continue;
memmove (s,s + 1,l - 1);
s[l - 1] = k;
_l++;
}
else
{
if (_dec == dec)
continue;
_dec++;
s[l + _dec] = k;
}
}
if (k == '.' && _dec < 0 && dec > 0)
{
if (!changed)
{
zsprintfloat (s,0,l,dec);
changed = 1;
}
_dec = 0;
}
}
}
/* Create a date from ASCII representation */
unsigned short atodate (char *s)
{
int day,month,year;
day = atoi (s);
month = atoi (s + 3);
year = atoi (s + 6);
return makedate (day,month,year);
}
/* Check whether a date is valid */
validdate (unsigned short d)
{
int day,month,year;
day = dateday (d);
month = datemonth (d);
year = dateyear (d);
if (month < 1 || month > 12)
return 0;
datemaxday[2] = 28;
if ((year % 4) == 0 && year != 0)
datemaxday[2] = 29;
if (day < 1 || day > datemaxday[month])
return 0;
return 1;
}
/* Input date from user */
void editdate (unsigned short *d,int x,int y,int directions)
{
int k,i;
int changed;
char s[20];
cursor (x,y);
LOOP:
i = 0;
changed = 0;
zsprintdate (s,*d);
for (;;)
{
printzstr (x,y,s);
k = getkey ();
if (setdir (k,directions))
{
if (!validdate (atodate (s)))
{
beep ();
goto LOOP;
}
*d = atodate (s);
printdate (x,y,*d);
return;
}
if (k == 8)
{
if (i == 0)
goto LOOP;
if (i == 3 || i == 6)
i--;
s[--i] = ' ';
}
if (k >= '0' && k <= '9' && i != 8)
{
if (!changed)
{
strcpy (s," . . ");
changed = 1;
}
s[i++] = k;
if (i == 2 || i == 5)
i++;
}
if (k == '.')
switch (i)
{
case 0:
if (!changed)
{
strcpy (s," . . ");
changed = 1;
}
memcpy (s,"01",2);
i = 3;
break;
case 1:
s[1] = s[0];
s[0] = '0';
i = 3;
break;
case 3:
memcpy (s + 3,"01",2);
i = 6;
break;
case 4:
s[4] = s[3];
s[3] = '0';
i = 6;
break;
}
}
}
/* Input string from user */
void editstr (char *s,int l,int x,int y,int directions)
{
char olds[256];
int i;
int k;
int changed;
cursor (x,y);
memcpy (olds,s,l);
i = 0;
changed = 0;
for (;;)
{
k = getkey ();
if (setdir (k,directions))
{
if (changed)
printchars (x,y,i - l,' ');
return;
}
if (k >= 0x20 && k <= 0x7e && i != l)
{
if (!changed)
{
changed = 1;
printchars (x,y,l,' ');
memset (s,' ',l);
}
printchar (x + i,y,k);
s[i++] = k;
}
if (k == 8)
{
if (i)
{
s[--i] = ' ';
printchar (x + i,y,' ');
}
else
{
memcpy (s,olds,l);
printstr (x,y,s,l);
changed = 0;
}
}
}
}
static void printexecmenuitem (int x,int y,int i,execmenuitem *m,int maxwidth,
int reverse)
{
int far *p;
int a;
char *s;
p = calcptr (x + 1,y + i + 1);
a = attr;
if (reverse)
a = ((foreground << 4) | background) << 8;
*p++ = ' ' + a;
s = m->text;
while (*s)
{
*p++ = *s++ + a;
maxwidth--;
}
while (maxwidth-- >= 0)
*p++ = ' ' + a;
}
/* Display menu on screen, allow user to select an item, and take
appropriate action: if the selected item points to a function, call
the function, otherwise display the submenu */
void execmenu (execmenuitem *m,int mx,int my,int prevwidth,int prevheight)
{
int nitems;
int maxwidth;
int i,j,k,x,y;
execmenuitem *n,*o;
void *oldvideo,*menuscreen;
char *s;
cursor (0,25);
nitems = 0;
maxwidth = 0;
for (n=m; n->text; n++)
{
nitems++;
if (strlen (n->text) > maxwidth)
maxwidth = strlen (n->text);
}
x = 10;
y = 5;
if (mx == -2)
{
x = 38 - maxwidth/2;
y = 12 - nitems/2;
}
if (mx >= 0)
{
x = mx + 8;
if (x < mx + prevwidth - maxwidth - 3)
x = mx + prevwidth - maxwidth - 3;
if (x > mx + prevwidth - 1)
x = mx + prevwidth - 1;
y = my + 4;
if (y < my + prevheight - nitems - 1)
y = my + prevheight - nitems - 1;
if (y > my + prevheight - 1)
y = my + prevheight - 1;
}
if (x > 76 - maxwidth)
x = 76 - maxwidth;
if (y > 23 - nitems)
y = 23 - nitems;
oldvideo = stashvideo (x,y,maxwidth + 4,nitems + 2);
border (x,y,maxwidth + 4,nitems + 2);
n = m;
for (i=0; i!=nitems; i++)
{
printzstr (x + 2,y + 1 + i,n->text);
n++;
}
n = m;
i = 0;
for (;;)
{
printexecmenuitem (x,y,i,n,maxwidth,1);
k = getkey ();
setdir (k,~0);
switch (dir)
{
case DIR_ESC:
fetchvideo (x,y,maxwidth + 4,nitems + 2,oldvideo);
return;
case DIR_UP:
if (i)
{
printexecmenuitem (x,y,i,n,maxwidth,0);
i--;
n--;
}
break;
case DIR_DOWN:
if (i != nitems - 1)
{
printexecmenuitem (x,y,i,n,maxwidth,0);
i++;
n++;
}
break;
case DIR_PGUP:
case DIR_HOME:
if (i)
printexecmenuitem (x,y,i,n,maxwidth,0);
i = 0;
n = m;
break;
case DIR_PGDN:
case DIR_END:
if (i != nitems - 1)
printexecmenuitem (x,y,i,n,maxwidth,0);
i = nitems - 1;
n = m + i;
break;
case DIR_RETURN:
o = n;
goto DO_OPTION;
}
if (k == '0')
{
j = 9;
SELECT_NUMBER:
if (j >= nitems)
continue;
o = m + j;
goto DO_OPTION_1;
}
if (k >= '1' && k <= '9')
{
j = k - '1';
goto SELECT_NUMBER;
}
if (k >= 0x3b00 && k <= 0x4400)
{
j = (k - 0x3b00) / 0x100;
goto SELECT_NUMBER;
}
k = toupper (k);
j = 0;
for (o=m; o->text; o++)
{
s = o->text;
while (*s >= 'a' && *s <= 'z')
s++;
if (*s == k)
{
DO_OPTION_1:
printexecmenuitem (x,y,i,n,maxwidth,0);
i = j;
n = o;
printexecmenuitem (x,y,i,n,maxwidth,1);
DO_OPTION:
if (o->submenu)
execmenu (o->submenu,x,y,maxwidth + 4,nitems + 2);
else
{
menuscreen = stashvideo (0,0,80,25);
printchars (0,0,80*25,' ');
(o->function)();
fetchvideo (0,0,80,25,menuscreen);
cursor (0,25);
}
break;
}
j++;
}
}
}
static void scrollup (int x,int y,int width,int height)
{
int far *scr,far *p,far *q;
int i,j;
scr = calcptr (x,y);
j = height;
while (--j)
{
p = scr;
q = scr + 80;
i = width;
do
*p++ = *q++;
while (--i);
scr += 80;
}
if (height)
printchars (x,y + height - 1,width,' ');
}
static void scrolldown (int x,int y,int width,int height)
{
int far *scr,far *p,far *q;
int i,j;
scr = calcptr (x,y + height);
j = height;
while (--j)
{
scr -= 80;
p = scr;
q = scr - 80;
i = width;
do
*p++ = *q++;
while (--i);
}
if (height)
printchars (x,y,width,' ');
}
/* Function to display linked list of records in scrolling format, using
supplied functions to show and (optionally) edit records */
void scrolledit (
int fromfile,long *fromptr,void *fromrec,int fromoffset,int fromsize,
int tofile,long toptr,void *torec,int tooffset,int tosize,
void *blankrec,int miscoff,int nfields,void (*show)(),void (*edit)(),
int x,int y,int width,int height)
{
long *fromptrs;
long *toptrs;
long p,q;
int n;
long pv[25];
int i,j;
fromptrs = (long *)(((char *)fromrec) + fromoffset);
toptrs = (long *)(((char *)torec) + tooffset);
p = toptrs[0];
if (p < 0)
{
if (!edit)
{
printzstr (30,23,"No records to display");
cursor (53,23);
beep ();
getkey ();
return;
}
memcpy (fromrec,blankrec,fromsize);
create (fromfile,fromptr,fromrec,fromsize,miscoff);
reclink (fromfile,*fromptr,fromptrs,fromoffset,tofile,toptr,toptrs,tooffset);
p = toptrs[0];
}
n = 0;
do
{
*fromptr = pv[n] = p;
Read (fromfile,p,fromrec,fromsize);
currenty = y + n;
show ();
p = fromptrs[1];
n++;
}
while (n != height && p >= 0);
*fromptr = pv[0];
Read (fromfile,pv[0],fromrec,fromsize);
fieldno = 0;
i = 0;
for (;;)
{
currenty = y + i;
if (edit)
edit ();
else
{
cursor (x,currenty);
do
i = getkey ();
while (!setdir (i,DF_ESC | DF_UP | DF_DOWN | DF_PGUP | DF_PGDN | DF_HOME | DF_END));
}
switch (dir)
{
case DIR_RETURN:
if (fieldno == nfields - 1)
{
Write (fromfile,*fromptr,fromrec,fromsize);
fieldno = 0;
if (fromptrs[1] >= 0)
goto DOWN;
memcpy (fromrec,blankrec,fromsize);
create (fromfile,fromptr,fromrec,fromsize,miscoff);
toptrs[1] = *fromptr;
fromptrs[0] = toptr;
fromptrs[2] = pv[i];
Write (fromfile,pv[i] + fromoffset + sizeof (long),fromptr,sizeof (long));
if (n != height - 1)
{
n++;
i++;
currenty++;
}
else
{
memmove (pv,pv + 1,sizeof pv - sizeof (long));
scrollup (x,y,width,height);
}
pv[i] = *fromptr;
show ();
}
else
fieldno++;
break;
case DIR_ESC:
if (edit)
{
Write (fromfile,*fromptr,fromrec,fromsize);
Write (tofile,toptr,torec,tosize);
}
return;
case DIR_UP:
if (i)
{
if (edit)
Write (fromfile,*fromptr,fromrec,fromsize);
i--;
*fromptr = pv[i];
Read (fromfile,*fromptr,fromrec,fromsize);
}
else
if (fromptrs[2] >= 0)
{
if (edit)
Write (fromfile,*fromptr,fromrec,fromsize);
memmove (pv + 1,pv,sizeof pv - sizeof (long));
*fromptr = pv[0] = fromptrs[2];
Read (fromfile,pv[0],fromrec,fromsize);
scrolldown (x,y,width,height);
show ();
}
break;
case DIR_DOWN:
DOWN:
if (i != n - 1)
{
if (edit)
Write (fromfile,*fromptr,fromrec,fromsize);
i++;
*fromptr = pv[i];
Read (fromfile,*fromptr,fromrec,fromsize);
}
else
if (fromptrs[1] >= 0)
{
if (edit)
Write (fromfile,*fromptr,fromrec,fromsize);
memmove (pv,pv + 1,sizeof pv - sizeof (long));
*fromptr = pv[i] = fromptrs[1];
Read (fromfile,*fromptr,fromrec,fromsize);
scrollup (x,y,width,height);
show ();
}
break;
case DIR_LEFT:
fieldno--;
break;
case DIR_RIGHT:
fieldno++;
break;
case DIR_PGUP:
if (edit)
Write (fromfile,*fromptr,fromrec,fromsize);
if (i)
{
*fromptr = pv[0];
Read (fromfile,pv[0],fromrec,fromsize);
currenty = y;
}
for (j=0; j!=height && fromptrs[2] >= 0; j++)
{
memmove (pv + 1,pv,sizeof pv - sizeof (long));
*fromptr = pv[0] = fromptrs[2];
Read (fromfile,pv[0],fromrec,fromsize);
scrolldown (x,y,width,height);
show ();
}
if (i)
{
*fromptr = pv[i];
Read (fromfile,*fromptr,fromrec,fromsize);
}
break;
case DIR_PGDN:
if (edit)
Write (fromfile,*fromptr,fromrec,fromsize);
if (i != n - 1)
{
*fromptr = pv[n - 1];
Read (fromfile,*fromptr,fromrec,fromsize);
currenty = y + n - 1;
}
for (j=0; j!=height && fromptrs[1] >= 0; j++)
{
memmove (pv,pv + 1,sizeof pv - sizeof (long));
*fromptr = pv[n - 1] = fromptrs[1];
Read (fromfile,*fromptr,fromrec,fromsize);
scrollup (x,y,width,height);
show ();
}
if (i != n - 1)
{
*fromptr = pv[i];
Read (fromfile,*fromptr,fromrec,fromsize);
}
break;
case DIR_HOME:
if (fromptrs[2] >= 0)
{
if (edit)
Write (fromfile,*fromptr,fromrec,fromsize);
p = toptrs[0];
n = 0;
do
{
*fromptr = pv[n] = p;
Read (fromfile,p,fromrec,fromsize);
currenty = y + n;
show ();
p = fromptrs[1];
n++;
}
while (n != height && p >= 0);
*fromptr = pv[0];
Read (fromfile,pv[0],fromrec,fromsize);
i = 0;
}
break;
case DIR_END:
if (fromptrs[1] >= 0)
{
if (edit)
Write (fromfile,*fromptr,fromrec,fromsize);
i = n - 1;
*fromptr = pv[i];
Read (fromfile,*fromptr,fromrec,fromsize);
while (fromptrs[1] >= 0)
{
memmove (pv,pv + 1,sizeof pv - sizeof (long));
*fromptr = pv[i] = fromptrs[1];
Read (fromfile,*fromptr,fromrec,fromsize);
}
for (i=0; i!=n; i++)
{
*fromptr = pv[i];
Read (fromfile,*fromptr,fromrec,fromsize);
currenty = y + i;
show ();
}
i = n - 1;
}
break;
case DIR_INS:
Write (fromfile,*fromptr,fromrec,fromsize);
p = fromptrs[2];
memcpy (fromrec,blankrec,fromsize);
create (fromfile,fromptr,fromrec,fromsize,miscoff);
fromptrs[0] = toptr;
fromptrs[1] = pv[i];
fromptrs[2] = p;
if (p < 0)
toptrs[0] = *fromptr;
else
Write (fromfile,p + fromoffset + sizeof (long),fromptr,sizeof (long));
Write (fromfile,pv[i] + fromoffset + 2*sizeof (long),fromptr,sizeof (long));
if (n != height - 1)
n++;
memmove (pv + i + 1,pv + i,(n - i - 1)*sizeof (long));
pv[i] = *fromptr;
scrolldown (x,currenty,width,height + y - currenty);
show ();
break;
case DIR_DEL:
if (n != 1)
{
p = fromptrs[1];
q = fromptrs[2];
recunlink (fromfile,*fromptr,fromptrs,fromoffset,tofile,toptr,toptrs,tooffset);
delete (fromfile,*fromptr,fromrec,miscoff);
scrollup (x,y + currenty,width,height + y - currenty);
if (n == height && p >= 0)
{
*fromptr = pv[n - 1] = p;
Read (fromfile,p,fromrec,fromsize);
currenty = y + height - 1;
show ();
}
else
if (i == n - 1)
{
if (i)
{
printchars (x,y + i,width,' ');
i--;
n--;
}
else
{
*fromptr = pv[0] = q;
Read (fromfile,q,fromrec,fromsize);
printchars (x,y,width,' ');
show ();
}
}
else
n--;
}
break;
}
}
}