Category : Databases and related files
Archive   : DPG.ZIP
Filename : VIDEO.C
Output of file : VIDEO.C contained in archive : DPG.ZIP
#include
#include
#include
#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;
}
}
}
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/