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 >
C/C++ Source or Header  |  1992-04-23  |  22KB  |  1,181 lines

  1. #include    <stdio.h>
  2. #include    <stdlib.h>
  3. #include    <string.h>
  4. #include    <dos.h>
  5. #include    "video.h"
  6. #include    "files.h"
  7.  
  8. #define    background        0        /* Background colour */
  9. #define    foreground        7        /* Foreground colour */
  10.  
  11. #define    attr                (((background << 4) | foreground) << 8)
  12.  
  13. #define    seg(p)            *((unsigned *)&(p) + 1)
  14. #define    off(p)            *((unsigned *)&(p))
  15.  
  16. static char datemaxday[] =
  17. {
  18.     0,
  19.     31,
  20.     28,
  21.     31,
  22.     30,
  23.     31,
  24.     30,
  25.     31,
  26.     31,
  27.     30,
  28.     31,
  29.     30,
  30.     31,
  31. };
  32.  
  33. int dir;                    /* Cursor direction */
  34. int fieldno;            /* Current field number for scroll edit */
  35. static videopage;        /* Segment part of pointer to video memory */
  36. static currenty;        /* Current Y coordinate for scrolling screens */
  37.  
  38.         /* Check if last keystroke is an allowed cursor key, and if so, set
  39.             dir variable accordingly */
  40.  
  41. static setdir (int k,int directions)
  42. {
  43.     dir = -1;
  44.     switch (k)
  45.     {
  46.         case '\r':
  47.             if (directions & DF_RETURN)
  48.                 dir = DIR_RETURN;
  49.             break;
  50.         case 27:
  51.             if (directions & DF_ESC)
  52.                 dir = DIR_ESC;
  53.             break;
  54.         case 18432:
  55.             if (directions & DF_UP)
  56.                 dir = DIR_UP;
  57.             break;
  58.         case 20480:
  59.             if (directions & DF_DOWN)
  60.                 dir = DIR_DOWN;
  61.             break;
  62.         case 19200:
  63.             if (directions & DF_LEFT)
  64.                 dir = DIR_LEFT;
  65.             break;
  66.         case 19712:
  67.             if (directions & DF_RIGHT)
  68.                 dir = DIR_RIGHT;
  69.             break;
  70.         case 18688:
  71.             if (directions & DF_PGUP)
  72.                 dir = DIR_PGUP;
  73.             break;
  74.         case 20736:
  75.             if (directions & DF_PGDN)
  76.                 dir = DIR_PGDN;
  77.             break;
  78.         case 18176:
  79.             if (directions & DF_HOME)
  80.                 dir = DIR_HOME;
  81.             break;
  82.         case 20224:
  83.             if (directions & DF_END)
  84.                 dir = DIR_END;
  85.             break;
  86.         case 20992:
  87.             if (directions & DF_INS)
  88.                 dir = DIR_INS;
  89.             break;
  90.         case 21248:
  91.             if (directions & DF_DEL)
  92.                 dir = DIR_DEL;
  93.             break;
  94.     }
  95.     return dir >= 0;
  96. }
  97.  
  98.         /* Return pointer into video memory for given X,Y coordinates */
  99.  
  100. static int far *calcptr (int x,int y)
  101. {
  102.     int far *p;
  103.  
  104.     if (y < 0)
  105.         y = currenty;
  106.     currenty = y;
  107.     seg (p) = videopage;
  108.     off (p) = y*2*80 + x*2;
  109.     return p;
  110. }
  111.  
  112.         /* Display a null-terminated ASCII string */
  113.  
  114. static void printzstr (int x,int y,char *s)
  115. {
  116.     int far *p;
  117.  
  118.     p = calcptr (x,y);
  119.     while (*s)
  120.         *p++ = *s++ + attr;
  121. }
  122.  
  123.         /* Convert an integer to ASCII representation */
  124.  
  125. static void zsprintint (char *s,long n,int l)
  126. {
  127.     char buf[20];
  128.  
  129.     sprintf (buf,"%%%dld",l);
  130.     sprintf (s,buf,n);
  131. }
  132.  
  133.         /* Convert a floating point number to ASCII representation */
  134.  
  135. static void zsprintfloat (char *s,double n,int l,int dec)
  136. {
  137.     char buf[20];
  138.  
  139.     if (dec <= 0)
  140.         sprintf (buf,"%%%d.0lf",l);
  141.     else
  142.         sprintf (buf,"%%%d.%dlf",l + dec + 1,dec);
  143.     sprintf (s,buf,n);
  144. }
  145.  
  146.         /* Convert a date to ASCII representation */
  147.  
  148. static void zsprintdate (char *s,unsigned short d)
  149. {
  150.     sprintf (s,"%02d.%02d.%02d",dateday (d),datemonth (d),dateyear (d));
  151. }
  152.  
  153.         /* Display a character a given number of times */
  154.  
  155. static void printchars (int x,int y,int n,int c)
  156. {
  157.     int far *p;
  158.  
  159.     p = calcptr (x,y);
  160.     while (--n >= 0)
  161.         *p++ = c + attr;
  162. }
  163.  
  164.         /* Display a character */
  165.  
  166. static void printchar (int x,int y,int c)
  167. {
  168.     printchars (x,y,1,c);
  169. }
  170.  
  171.         /* Draw an outline border using IBM graphics characters */
  172.  
  173. static void border (int x,int y,int width,int height)
  174. {
  175.     int i;
  176.  
  177.     printchar (x,y,0xda);
  178.     printchars (x + 1,y,width - 2,0xc4);
  179.     printchar (x + width - 1,y,0xbf);
  180.     for (i=height-2; i; i--)
  181.     {
  182.         printchar (x,y + i,0xb3);
  183.         printchar (x + width - 1,y + i,0xb3);
  184.     }
  185.     printchar (x,y + height - 1,0xc0);
  186.     printchars (x + 1,y + height - 1,width - 2,0xc4);
  187.     printchar (x + width - 1,y + height - 1,0xd9);
  188. }
  189.  
  190.         /* Allocate memory with error checking */
  191.  
  192. static void *alloc (int n)
  193. {
  194.     void *p;
  195.  
  196.     p = malloc (n);
  197.     if (p == 0)
  198.     {
  199.         printf ("Out of memory");
  200.         exit (1);
  201.     }
  202.     return p;
  203. }
  204.  
  205.         /* Save a portion of the screen in a buffer allocated for the purpose */
  206.  
  207. static void *stashvideo (int x,int y,int width,int height)
  208. {
  209.     int *result,*dest;
  210.     int far *src,far *q;
  211.     int i;
  212.  
  213.     src = calcptr (x,y);
  214.     result = dest = alloc (width*height*2);
  215.     do
  216.     {
  217.         q = src;
  218.         i = width;
  219.         do
  220.             *dest++ = *q++;
  221.         while (--i);
  222.         src += 80;
  223.     }
  224.     while (--height);
  225.     return result;
  226. }
  227.  
  228.         /* Restore a portion of the screen from a buffer and free the buffer */
  229.  
  230. static void fetchvideo (int x,int y,int width,int height,void *data)
  231. {
  232.     int far *dest,far *p;
  233.     int *src;
  234.     int i;
  235.  
  236.     dest = calcptr (x,y);
  237.     src = data;
  238.     do
  239.     {
  240.         p = dest;
  241.         i = width;
  242.         do
  243.             *p++ = *src++;
  244.         while (--i);
  245.         dest += 80;
  246.     }
  247.     while (--height);
  248.     free (data);
  249. }
  250.  
  251. void beep (void)
  252. {
  253.     putchar (7);
  254.     fflush (stdout);
  255. }
  256.  
  257.         /* Initialize variables and clear the screen */
  258.  
  259. void initvideo (void)
  260. {
  261.     union REGS r;
  262.     int far *p,far *q;
  263.     int i,j;
  264.  
  265.     r.x.ax = 0x0f00;
  266.     int86 (0x10,&r,&r);
  267.     videopage = 0xb800;
  268.     if (r.h.al == 7)
  269.         videopage = 0xb000;
  270.     seg (p) = videopage;
  271.     off (p) = 0;
  272.     i = 25;
  273.     do
  274.     {
  275.         q = p;
  276.         p += 80;
  277.         j = 80;
  278.         do
  279.             *q++ = attr;
  280.         while (--j != 0);
  281.     }
  282.     while (--i != 0);
  283. }
  284.  
  285.         /* Put hardware cursor at given coordinates */
  286.  
  287. void cursor (int x,int y)
  288. {
  289.     union REGS r;
  290.  
  291.     if (y < 0)
  292.         y = currenty;
  293.     r.h.ah = 2;
  294.     r.h.dh = y;
  295.     r.h.dl = x;
  296.     r.h.bh = 0;
  297.     int86 (0x10,&r,&r);
  298. }
  299.  
  300.         /* Get a keystroke from the user */
  301.  
  302. getkey (void)
  303. {
  304.     int k;
  305.  
  306.     k = bioskey (0);
  307.     if (k & 0xff)
  308.         k &= 0xff;
  309.     return k;
  310. }
  311.  
  312.         /* Display a string with given number of characters */
  313.  
  314. void printstr (int x,int y,char *s,int l)
  315. {
  316.     int far *p;
  317.  
  318.     p = calcptr (x,y);
  319.     while (--l >= 0)
  320.         *p++ = *s++ + attr;
  321. }
  322.  
  323.         /* Display an integer using given number of digits */
  324.  
  325. void printint (int x,int y,long n,int l)
  326. {
  327.     char s[20];
  328.     zsprintint (s,n,l);
  329.     printzstr (x,y,s);
  330. }
  331.  
  332.         /* Display a floating point number using given number of digits */
  333.  
  334. void printfloat (int x,int y,double n,int l,int dec)
  335. {
  336.     char s[20];
  337.  
  338.     zsprintfloat (s,n,l,dec);
  339.     printzstr (x,y,s);
  340. }
  341.  
  342.         /* Display a date */
  343.  
  344. void printdate (int x,int y,unsigned short d)
  345. {
  346.     char s[20];
  347.  
  348.     zsprintdate (s,d);
  349.     printzstr (x,y,s);
  350. }
  351.  
  352.         /* Input integer value from user */
  353.  
  354. void editlong (long *n,int l,int x,int y,int directions)
  355. {
  356.     int _l;
  357.     int k;
  358.     int changed;
  359.     char s[20];
  360.  
  361.     cursor (x,y);
  362. LOOP:
  363.     changed = 0;
  364.     zsprintint (s,*n,l);
  365.     _l = 0;
  366.     for (;;)
  367.     {
  368.         printzstr (x,y,s);
  369.         k = getkey ();
  370.         if (setdir (k,directions))
  371.         {
  372.             *n = atol (s);
  373.             printint (x,y,*n,l);
  374.             return;
  375.         }
  376.         if (k == 8)
  377.         {
  378.             if (_l > 0)
  379.             {
  380.                 memmove (s + 1,s,l - 1);
  381.                 s[0] = ' ';
  382.                 _l--;
  383.                 continue;
  384.             }
  385.             goto LOOP;
  386.         }
  387.         if (k >= '0' && k <= '9' && _l != l)
  388.         {
  389.             if (!changed)
  390.             {
  391.                 changed = 1;
  392.                 strset (s,' ');
  393.             }
  394.             memmove (s,s + 1,l - 1);
  395.             s[l - 1] = k;
  396.             _l++;
  397.         }
  398.     }
  399. }
  400.  
  401. void editbyte (signed char *n,int l,int x,int y,int directions)
  402. {
  403.     long t;
  404.  
  405.     t = *n;
  406.     editlong (&t,l,x,y,directions);
  407.     *n = t;
  408. }
  409.  
  410. void editshort (short *n,int l,int x,int y,int directions)
  411. {
  412.     long t;
  413.  
  414.     t = *n;
  415.     editlong (&t,l,x,y,directions);
  416.     *n = t;
  417. }
  418.  
  419.         /* Input floating point value from user */
  420.  
  421. void editfloat (double *n,int l,int dec,int x,int y,int directions)
  422. {
  423.     int _l,_dec;
  424.     int k;
  425.     int changed;
  426.     char s[20];
  427.  
  428.     if (dec == 0)
  429.         dec = -1;
  430.     cursor (x,y);
  431. LOOP:
  432.     changed = 0;
  433.     zsprintfloat (s,*n,l,dec);
  434.     _l = 0;
  435.     _dec = -1;
  436.     for (;;)
  437.     {
  438.         printzstr (x,y,s);
  439.         k = getkey ();
  440.         if (setdir (k,directions))
  441.         {
  442.             *n = atof (s);
  443.             printfloat (x,y,*n,l,dec);
  444.             return;
  445.         }
  446.         if (k == 8)
  447.         {
  448.             if (_dec > 0)
  449.             {
  450.                 s[l + _dec] = ' ';
  451.                 _dec--;
  452.                 continue;
  453.             }
  454.             if (_dec == 0)
  455.             {
  456.                 _dec = -1;
  457.                 continue;
  458.             }
  459.             if (_l > 0)
  460.             {
  461.                 memmove (s + 1,s,l - 1);
  462.                 s[0] = ' ';
  463.                 _l--;
  464.                 continue;
  465.             }
  466.             goto LOOP;
  467.         }
  468.         if (k >= '0' && k <= '9')
  469.         {
  470.             if (!changed)
  471.             {
  472.                 changed = 1;
  473.                 strset (s,' ');
  474.                 if (dec >= 0)
  475.                     s[l] = '.';
  476.             }
  477.             if (_dec < 0)
  478.             {
  479.                 if (_l == l)
  480.                     continue;
  481.                 memmove (s,s + 1,l - 1);
  482.                 s[l - 1] = k;
  483.                 _l++;
  484.             }
  485.             else
  486.             {
  487.                 if (_dec == dec)
  488.                     continue;
  489.                 _dec++;
  490.                 s[l + _dec] = k;
  491.             }
  492.         }
  493.         if (k == '.' && _dec < 0 && dec > 0)
  494.         {
  495.             if (!changed)
  496.             {
  497.                 zsprintfloat (s,0,l,dec);
  498.                 changed = 1;
  499.             }
  500.             _dec = 0;
  501.         }
  502.     }
  503. }
  504.  
  505.         /* Create a date from ASCII representation */
  506.  
  507. unsigned short atodate (char *s)
  508. {
  509.     int day,month,year;
  510.  
  511.     day = atoi (s);
  512.     month = atoi (s + 3);
  513.     year = atoi (s + 6);
  514.     return makedate (day,month,year);
  515. }
  516.  
  517.         /* Check whether a date is valid */
  518.  
  519. validdate (unsigned short d)
  520. {
  521.     int day,month,year;
  522.  
  523.     day = dateday (d);
  524.     month = datemonth (d);
  525.     year = dateyear (d);
  526.  
  527.     if (month < 1 || month > 12)
  528.         return 0;
  529.  
  530.     datemaxday[2] = 28;
  531.     if ((year % 4) == 0 && year != 0)
  532.         datemaxday[2] = 29;
  533.     if (day < 1 || day > datemaxday[month])
  534.         return 0;
  535.  
  536.     return 1;
  537. }
  538.  
  539.         /* Input date from user */
  540.  
  541. void editdate (unsigned short *d,int x,int y,int directions)
  542. {
  543.     int k,i;
  544.     int changed;
  545.     char s[20];
  546.  
  547.     cursor (x,y);
  548. LOOP:
  549.     i = 0;
  550.     changed = 0;
  551.     zsprintdate (s,*d);
  552.     for (;;)
  553.     {
  554.         printzstr (x,y,s);
  555.         k = getkey ();
  556.         if (setdir (k,directions))
  557.         {
  558.             if (!validdate (atodate (s)))
  559.             {
  560.                 beep ();
  561.                 goto LOOP;
  562.             }
  563.             *d = atodate (s);
  564.             printdate (x,y,*d);
  565.             return;
  566.         }
  567.         if (k == 8)
  568.         {
  569.             if (i == 0)
  570.                 goto LOOP;
  571.             if (i == 3 || i == 6)
  572.                 i--;
  573.             s[--i] = ' ';
  574.         }
  575.         if (k >= '0' && k <= '9' && i != 8)
  576.         {
  577.             if (!changed)
  578.             {
  579.                 strcpy (s,"  .  .  ");
  580.                 changed = 1;
  581.             }
  582.             s[i++] = k;
  583.             if (i == 2 || i == 5)
  584.                 i++;
  585.         }
  586.         if (k == '.')
  587.             switch (i)
  588.             {
  589.                 case 0:
  590.                     if (!changed)
  591.                     {
  592.                         strcpy (s,"  .  .  ");
  593.                         changed = 1;
  594.                     }
  595.                     memcpy (s,"01",2);
  596.                     i = 3;
  597.                     break;
  598.                 case 1:
  599.                     s[1] = s[0];
  600.                     s[0] = '0';
  601.                     i = 3;
  602.                     break;
  603.                 case 3:
  604.                     memcpy (s + 3,"01",2);
  605.                     i = 6;
  606.                     break;
  607.                 case 4:
  608.                     s[4] = s[3];
  609.                     s[3] = '0';
  610.                     i = 6;
  611.                     break;
  612.             }
  613.     }
  614. }
  615.  
  616.         /* Input string from user */
  617.  
  618. void editstr (char *s,int l,int x,int y,int directions)
  619. {
  620.     char olds[256];
  621.     int i;
  622.     int k;
  623.     int changed;
  624.  
  625.     cursor (x,y);
  626.     memcpy (olds,s,l);
  627.     i = 0;
  628.     changed = 0;
  629.     for (;;)
  630.     {
  631.         k = getkey ();
  632.         if (setdir (k,directions))
  633.         {
  634.             if (changed)
  635.                 printchars (x,y,i - l,' ');
  636.             return;
  637.         }
  638.         if (k >= 0x20 && k <= 0x7e && i != l)
  639.         {
  640.             if (!changed)
  641.             {
  642.                 changed = 1;
  643.                 printchars (x,y,l,' ');
  644.                 memset (s,' ',l);
  645.             }
  646.             printchar (x + i,y,k);
  647.             s[i++] = k;
  648.         }
  649.         if (k == 8)
  650.         {
  651.             if (i)
  652.             {
  653.                 s[--i] = ' ';
  654.                 printchar (x + i,y,' ');
  655.             }
  656.             else
  657.             {
  658.                 memcpy (s,olds,l);
  659.                 printstr (x,y,s,l);
  660.                 changed = 0;
  661.             }
  662.         }
  663.     }
  664. }
  665.  
  666. static void printexecmenuitem (int x,int y,int i,execmenuitem *m,int maxwidth,
  667.         int reverse)
  668. {
  669.     int far *p;
  670.     int a;
  671.     char *s;
  672.  
  673.     p = calcptr (x + 1,y + i + 1);
  674.     a = attr;
  675.     if (reverse)
  676.         a = ((foreground << 4) | background) << 8;
  677.     *p++ = ' ' + a;
  678.     s = m->text;
  679.     while (*s)
  680.     {
  681.         *p++ = *s++ + a;
  682.         maxwidth--;
  683.     }
  684.     while (maxwidth-- >= 0)
  685.         *p++ = ' ' + a;
  686. }
  687.  
  688.         /* Display menu on screen, allow user to select an item, and take
  689.             appropriate action: if the selected item points to a function, call
  690.             the function, otherwise display the submenu */
  691.  
  692. void execmenu (execmenuitem *m,int mx,int my,int prevwidth,int prevheight)
  693. {
  694.     int nitems;
  695.     int maxwidth;
  696.     int i,j,k,x,y;
  697.     execmenuitem *n,*o;
  698.     void *oldvideo,*menuscreen;
  699.     char *s;
  700.  
  701.     cursor (0,25);
  702.     nitems = 0;
  703.     maxwidth = 0;
  704.     for (n=m; n->text; n++)
  705.     {
  706.         nitems++;
  707.         if (strlen (n->text) > maxwidth)
  708.             maxwidth = strlen (n->text);
  709.     }
  710.     x = 10;
  711.     y = 5;
  712.     if (mx == -2)
  713.     {
  714.         x = 38 - maxwidth/2;
  715.         y = 12 - nitems/2;
  716.     }
  717.     if (mx >= 0)
  718.     {
  719.         x = mx + 8;
  720.         if (x < mx + prevwidth - maxwidth - 3)
  721.             x = mx + prevwidth - maxwidth - 3;
  722.         if (x > mx + prevwidth - 1)
  723.             x = mx + prevwidth - 1;
  724.         y = my + 4;
  725.         if (y < my + prevheight - nitems - 1)
  726.             y = my + prevheight - nitems - 1;
  727.         if (y > my + prevheight - 1)
  728.             y = my + prevheight - 1;
  729.     }
  730.     if (x > 76 - maxwidth)
  731.         x = 76 - maxwidth;
  732.     if (y > 23 - nitems)
  733.         y = 23 - nitems;
  734.     oldvideo = stashvideo (x,y,maxwidth + 4,nitems + 2);
  735.     border (x,y,maxwidth + 4,nitems + 2);
  736.     n = m;
  737.     for (i=0; i!=nitems; i++)
  738.     {
  739.         printzstr (x + 2,y + 1 + i,n->text);
  740.         n++;
  741.     }
  742.     n = m;
  743.     i = 0;
  744.     for (;;)
  745.     {
  746.         printexecmenuitem (x,y,i,n,maxwidth,1);
  747.         k = getkey ();
  748.         setdir (k,~0);
  749.         switch (dir)
  750.         {
  751.             case DIR_ESC:
  752.                 fetchvideo (x,y,maxwidth + 4,nitems + 2,oldvideo);
  753.                 return;
  754.             case DIR_UP:
  755.                 if (i)
  756.                 {
  757.                     printexecmenuitem (x,y,i,n,maxwidth,0);
  758.                     i--;
  759.                     n--;
  760.                 }
  761.                 break;
  762.             case DIR_DOWN:
  763.                 if (i != nitems - 1)
  764.                 {
  765.                     printexecmenuitem (x,y,i,n,maxwidth,0);
  766.                     i++;
  767.                     n++;
  768.                 }
  769.                 break;
  770.             case DIR_PGUP:
  771.             case DIR_HOME:
  772.                 if (i)
  773.                     printexecmenuitem (x,y,i,n,maxwidth,0);
  774.                 i = 0;
  775.                 n = m;
  776.                 break;
  777.             case DIR_PGDN:
  778.             case DIR_END:
  779.                 if (i != nitems - 1)
  780.                     printexecmenuitem (x,y,i,n,maxwidth,0);
  781.                 i = nitems - 1;
  782.                 n = m + i;
  783.                 break;
  784.             case DIR_RETURN:
  785.                 o = n;
  786.                 goto DO_OPTION;
  787.         }
  788.         if (k == '0')
  789.         {
  790.             j = 9;
  791. SELECT_NUMBER:
  792.             if (j >= nitems)
  793.                 continue;
  794.             o = m + j;
  795.             goto DO_OPTION_1;
  796.         }
  797.         if (k >= '1' && k <= '9')
  798.         {
  799.             j = k - '1';
  800.             goto SELECT_NUMBER;
  801.         }
  802.         if (k >= 0x3b00 && k <= 0x4400)
  803.         {
  804.             j = (k - 0x3b00) / 0x100;
  805.             goto SELECT_NUMBER;
  806.         }
  807.         k = toupper (k);
  808.         j = 0;
  809.         for (o=m; o->text; o++)
  810.         {
  811.             s = o->text;
  812.             while (*s >= 'a' && *s <= 'z')
  813.                 s++;
  814.             if (*s == k)
  815.             {
  816. DO_OPTION_1:
  817.                 printexecmenuitem (x,y,i,n,maxwidth,0);
  818.                 i = j;
  819.                 n = o;
  820.                 printexecmenuitem (x,y,i,n,maxwidth,1);
  821. DO_OPTION:
  822.                 if (o->submenu)
  823.                     execmenu (o->submenu,x,y,maxwidth + 4,nitems + 2);
  824.                 else
  825.                 {
  826.                     menuscreen = stashvideo (0,0,80,25);
  827.                     printchars (0,0,80*25,' ');
  828.                     (o->function)();
  829.                     fetchvideo (0,0,80,25,menuscreen);
  830.                     cursor (0,25);
  831.                 }
  832.                 break;
  833.             }
  834.             j++;
  835.         }
  836.     }
  837. }
  838.  
  839. static void scrollup (int x,int y,int width,int height)
  840. {
  841.     int far *scr,far *p,far *q;
  842.     int i,j;
  843.  
  844.     scr = calcptr (x,y);
  845.     j = height;
  846.     while (--j)
  847.     {
  848.         p = scr;
  849.         q = scr + 80;
  850.         i = width;
  851.         do
  852.             *p++ = *q++;
  853.         while (--i);
  854.         scr += 80;
  855.     }
  856.     if (height)
  857.         printchars (x,y + height - 1,width,' ');
  858. }
  859.  
  860. static void scrolldown (int x,int y,int width,int height)
  861. {
  862.     int far *scr,far *p,far *q;
  863.     int i,j;
  864.  
  865.     scr = calcptr (x,y + height);
  866.     j = height;
  867.     while (--j)
  868.     {
  869.         scr -= 80;
  870.         p = scr;
  871.         q = scr - 80;
  872.         i = width;
  873.         do
  874.             *p++ = *q++;
  875.         while (--i);
  876.     }
  877.     if (height)
  878.         printchars (x,y,width,' ');
  879. }
  880.  
  881.         /* Function to display linked list of records in scrolling format, using
  882.             supplied functions to show and (optionally) edit records */
  883.  
  884. void scrolledit (
  885.         int fromfile,long *fromptr,void *fromrec,int fromoffset,int fromsize,
  886.         int tofile,long toptr,void *torec,int tooffset,int tosize,
  887.         void *blankrec,int miscoff,int nfields,void (*show)(),void (*edit)(),
  888.         int x,int y,int width,int height)
  889. {
  890.     long *fromptrs;
  891.     long *toptrs;
  892.     long p,q;
  893.     int n;
  894.     long pv[25];
  895.     int i,j;
  896.  
  897.     fromptrs = (long *)(((char *)fromrec) + fromoffset);
  898.     toptrs = (long *)(((char *)torec) + tooffset);
  899.     p = toptrs[0];
  900.     if (p < 0)
  901.     {
  902.         if (!edit)
  903.         {
  904.             printzstr (30,23,"No records to display");
  905.             cursor (53,23);
  906.             beep ();
  907.             getkey ();
  908.             return;
  909.         }
  910.         memcpy (fromrec,blankrec,fromsize);
  911.         create (fromfile,fromptr,fromrec,fromsize,miscoff);
  912.         reclink (fromfile,*fromptr,fromptrs,fromoffset,tofile,toptr,toptrs,tooffset);
  913.         p = toptrs[0];
  914.     }
  915.     n = 0;
  916.     do
  917.     {
  918.         *fromptr = pv[n] = p;
  919.         Read (fromfile,p,fromrec,fromsize);
  920.         currenty = y + n;
  921.         show ();
  922.         p = fromptrs[1];
  923.         n++;
  924.     }
  925.     while (n != height && p >= 0);
  926.     *fromptr = pv[0];
  927.     Read (fromfile,pv[0],fromrec,fromsize);
  928.     fieldno = 0;
  929.     i = 0;
  930.     for (;;)
  931.     {
  932.         currenty = y + i;
  933.         if (edit)
  934.             edit ();
  935.         else
  936.         {
  937.             cursor (x,currenty);
  938.             do
  939.                 i = getkey ();
  940.             while (!setdir (i,DF_ESC | DF_UP | DF_DOWN | DF_PGUP | DF_PGDN | DF_HOME | DF_END));
  941.         }
  942.         switch (dir)
  943.         {
  944.             case DIR_RETURN:
  945.                 if (fieldno == nfields - 1)
  946.                 {
  947.                     Write (fromfile,*fromptr,fromrec,fromsize);
  948.                     fieldno = 0;
  949.                     if (fromptrs[1] >= 0)
  950.                         goto DOWN;
  951.                     memcpy (fromrec,blankrec,fromsize);
  952.                     create (fromfile,fromptr,fromrec,fromsize,miscoff);
  953.                     toptrs[1] = *fromptr;
  954.                     fromptrs[0] = toptr;
  955.                     fromptrs[2] = pv[i];
  956.                     Write (fromfile,pv[i] + fromoffset + sizeof (long),fromptr,sizeof (long));
  957.                     if (n != height - 1)
  958.                     {
  959.                         n++;
  960.                         i++;
  961.                         currenty++;
  962.                     }
  963.                     else
  964.                     {
  965.                         memmove (pv,pv + 1,sizeof pv - sizeof (long));
  966.                         scrollup (x,y,width,height);
  967.                     }
  968.                     pv[i] = *fromptr;
  969.                     show ();
  970.                 }
  971.                 else
  972.                     fieldno++;
  973.                 break;
  974.             case DIR_ESC:
  975.                 if (edit)
  976.                 {
  977.                     Write (fromfile,*fromptr,fromrec,fromsize);
  978.                     Write (tofile,toptr,torec,tosize);
  979.                 }
  980.                 return;
  981.             case DIR_UP:
  982.                 if (i)
  983.                 {
  984.                     if (edit)
  985.                         Write (fromfile,*fromptr,fromrec,fromsize);
  986.                     i--;
  987.                     *fromptr = pv[i];
  988.                     Read (fromfile,*fromptr,fromrec,fromsize);
  989.                 }
  990.                 else
  991.                     if (fromptrs[2] >= 0)
  992.                     {
  993.                         if (edit)
  994.                             Write (fromfile,*fromptr,fromrec,fromsize);
  995.                         memmove (pv + 1,pv,sizeof pv - sizeof (long));
  996.                         *fromptr = pv[0] = fromptrs[2];
  997.                         Read (fromfile,pv[0],fromrec,fromsize);
  998.                         scrolldown (x,y,width,height);
  999.                         show ();
  1000.                     }
  1001.                 break;
  1002.             case DIR_DOWN:
  1003. DOWN:
  1004.                 if (i != n - 1)
  1005.                 {
  1006.                     if (edit)
  1007.                         Write (fromfile,*fromptr,fromrec,fromsize);
  1008.                     i++;
  1009.                     *fromptr = pv[i];
  1010.                     Read (fromfile,*fromptr,fromrec,fromsize);
  1011.                 }
  1012.                 else
  1013.                     if (fromptrs[1] >= 0)
  1014.                     {
  1015.                         if (edit)
  1016.                             Write (fromfile,*fromptr,fromrec,fromsize);
  1017.                         memmove (pv,pv + 1,sizeof pv - sizeof (long));
  1018.                         *fromptr = pv[i] = fromptrs[1];
  1019.                         Read (fromfile,*fromptr,fromrec,fromsize);
  1020.                         scrollup (x,y,width,height);
  1021.                         show ();
  1022.                     }
  1023.                 break;
  1024.             case DIR_LEFT:
  1025.                 fieldno--;
  1026.                 break;
  1027.             case DIR_RIGHT:
  1028.                 fieldno++;
  1029.                 break;
  1030.             case DIR_PGUP:
  1031.                 if (edit)
  1032.                     Write (fromfile,*fromptr,fromrec,fromsize);
  1033.                 if (i)
  1034.                 {
  1035.                     *fromptr = pv[0];
  1036.                     Read (fromfile,pv[0],fromrec,fromsize);
  1037.                     currenty = y;
  1038.                 }
  1039.                 for (j=0; j!=height && fromptrs[2] >= 0; j++)
  1040.                 {
  1041.                     memmove (pv + 1,pv,sizeof pv - sizeof (long));
  1042.                     *fromptr = pv[0] = fromptrs[2];
  1043.                     Read (fromfile,pv[0],fromrec,fromsize);
  1044.                     scrolldown (x,y,width,height);
  1045.                     show ();
  1046.                 }
  1047.                 if (i)
  1048.                 {
  1049.                     *fromptr = pv[i];
  1050.                     Read (fromfile,*fromptr,fromrec,fromsize);
  1051.                 }
  1052.                 break;
  1053.             case DIR_PGDN:
  1054.                 if (edit)
  1055.                     Write (fromfile,*fromptr,fromrec,fromsize);
  1056.                 if (i != n - 1)
  1057.                 {
  1058.                     *fromptr = pv[n - 1];
  1059.                     Read (fromfile,*fromptr,fromrec,fromsize);
  1060.                     currenty = y + n - 1;
  1061.                 }
  1062.                 for (j=0; j!=height && fromptrs[1] >= 0; j++)
  1063.                 {
  1064.                     memmove (pv,pv + 1,sizeof pv - sizeof (long));
  1065.                     *fromptr = pv[n - 1] = fromptrs[1];
  1066.                     Read (fromfile,*fromptr,fromrec,fromsize);
  1067.                     scrollup (x,y,width,height);
  1068.                     show ();
  1069.                 }
  1070.                 if (i != n - 1)
  1071.                 {
  1072.                     *fromptr = pv[i];
  1073.                     Read (fromfile,*fromptr,fromrec,fromsize);
  1074.                 }
  1075.                 break;
  1076.             case DIR_HOME:
  1077.                 if (fromptrs[2] >= 0)
  1078.                 {
  1079.                     if (edit)
  1080.                         Write (fromfile,*fromptr,fromrec,fromsize);
  1081.                     p = toptrs[0];
  1082.                     n = 0;
  1083.                     do
  1084.                     {
  1085.                         *fromptr = pv[n] = p;
  1086.                         Read (fromfile,p,fromrec,fromsize);
  1087.                         currenty = y + n;
  1088.                         show ();
  1089.                         p = fromptrs[1];
  1090.                         n++;
  1091.                     }
  1092.                     while (n != height && p >= 0);
  1093.                     *fromptr = pv[0];
  1094.                     Read (fromfile,pv[0],fromrec,fromsize);
  1095.                     i = 0;
  1096.                 }
  1097.                 break;
  1098.             case DIR_END:
  1099.                 if (fromptrs[1] >= 0)
  1100.                 {
  1101.                     if (edit)
  1102.                         Write (fromfile,*fromptr,fromrec,fromsize);
  1103.                     i = n - 1;
  1104.                     *fromptr = pv[i];
  1105.                     Read (fromfile,*fromptr,fromrec,fromsize);
  1106.                     while (fromptrs[1] >= 0)
  1107.                     {
  1108.                         memmove (pv,pv + 1,sizeof pv - sizeof (long));
  1109.                         *fromptr = pv[i] = fromptrs[1];
  1110.                         Read (fromfile,*fromptr,fromrec,fromsize);
  1111.                     }
  1112.                     for (i=0; i!=n; i++)
  1113.                     {
  1114.                         *fromptr = pv[i];
  1115.                         Read (fromfile,*fromptr,fromrec,fromsize);
  1116.                         currenty = y + i;
  1117.                         show ();
  1118.                     }
  1119.                     i = n - 1;
  1120.                 }
  1121.                 break;
  1122.             case DIR_INS:
  1123.                 Write (fromfile,*fromptr,fromrec,fromsize);
  1124.                 p = fromptrs[2];
  1125.                 memcpy (fromrec,blankrec,fromsize);
  1126.                 create (fromfile,fromptr,fromrec,fromsize,miscoff);
  1127.                 fromptrs[0] = toptr;
  1128.                 fromptrs[1] = pv[i];
  1129.                 fromptrs[2] = p;
  1130.                 if (p < 0)
  1131.                     toptrs[0] = *fromptr;
  1132.                 else
  1133.                     Write (fromfile,p + fromoffset + sizeof (long),fromptr,sizeof (long));
  1134.                 Write (fromfile,pv[i] + fromoffset + 2*sizeof (long),fromptr,sizeof (long));
  1135.                 if (n != height - 1)
  1136.                     n++;
  1137.                 memmove (pv + i + 1,pv + i,(n - i - 1)*sizeof (long));
  1138.                 pv[i] = *fromptr;
  1139.                 scrolldown (x,currenty,width,height + y - currenty);
  1140.                 show ();
  1141.                 break;
  1142.             case DIR_DEL:
  1143.                 if (n != 1)
  1144.                 {
  1145.                     p = fromptrs[1];
  1146.                     q = fromptrs[2];
  1147.                     recunlink (fromfile,*fromptr,fromptrs,fromoffset,tofile,toptr,toptrs,tooffset);
  1148.                     delete (fromfile,*fromptr,fromrec,miscoff);
  1149.                     scrollup (x,y + currenty,width,height + y - currenty);
  1150.                     if (n == height && p >= 0)
  1151.                     {
  1152.                         *fromptr = pv[n - 1] = p;
  1153.                         Read (fromfile,p,fromrec,fromsize);
  1154.                         currenty = y + height - 1;
  1155.                         show ();
  1156.                     }
  1157.                     else
  1158.                         if (i == n - 1)
  1159.                         {
  1160.                             if (i)
  1161.                             {
  1162.                                 printchars (x,y + i,width,' ');
  1163.                                 i--;
  1164.                                 n--;
  1165.                             }
  1166.                             else
  1167.                             {
  1168.                                 *fromptr = pv[0] = q;
  1169.                                 Read (fromfile,q,fromrec,fromsize);
  1170.                                 printchars (x,y,width,' ');
  1171.                                 show ();
  1172.                             }
  1173.                         }
  1174.                         else
  1175.                             n--;
  1176.                 }
  1177.                 break;
  1178.         }
  1179.     }
  1180. }
  1181.