home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Programmer's Library 1.3 / Microsoft-Programers-Library-v1.3.iso / sampcode / os2sdk / os2sdk10 / apps / sse / dispatch.c next >
Encoding:
C/C++ Source or Header  |  1988-08-11  |  23.5 KB  |  812 lines

  1. /*** dispatch() - accepts keyboard input and dispatches control to
  2.  *          the appropriate function.
  3.  *
  4.  *   Wait in a loop for keyboard input, then dispatch to any of several
  5.  *   functions based on what the character code was. Default is insert()
  6.  *   after validating, otherwise it is one of our control keys. There is
  7.  *   a second dispatch function for special keys - those with zero for a
  8.  *   character value. special_dispatch() works based on the scan code.
  9.  *
  10.  *   EFFECTS:    No global variables are directly effected by this function
  11.  */
  12.  
  13.  
  14. #include <ctype.h>
  15. #include <dos.h>
  16. #include <doscalls.h>
  17. #include <subcalls.h>
  18. #include "ssedefs.h"
  19. #include "keydefs.h"
  20.  
  21.  
  22. void dispatch()
  23.     {
  24.  
  25.     struct    KeyData keydata;      /* data structure from subcalls.h */
  26.     struct    KbdStatus kbdstatus;      /* data structure from subcalls.h */
  27.  
  28.     kbdstatus.length = sizeof( kbdstatus );
  29.     KBDGETSTATUS( &kbdstatus, 0 );               /* set keyboard mode */
  30.     kbdstatus.bit_mask |= 4;
  31.     KBDSETSTATUS( &kbdstatus, 0 );
  32.  
  33.  
  34.     /*    the following section waits for keyboard input      */
  35.     /*    then examines the key received and dispatches us  */
  36.     /*    to the appropriate function for the key pressed.  */
  37.  
  38.  
  39.     while(1) {
  40.  
  41.  
  42.         KBDCHARIN( &keydata, 0, 0 );   /* get a character from KBD */
  43.  
  44.  
  45.         switch( keydata.char_code ) {
  46.  
  47.             default:                     /* default is not */
  48.             if ( isprint( keydata.char_code ) )  /* a control key. */
  49.                   insert( keydata.char_code );   /* check validity */
  50.             else  badkey();              /* and if good,   */
  51.             break;                     /* call insert()  */
  52.  
  53.      /* "special keys", those with character codes of 00, must */
  54.      /*  be sent to another dispatcher that checks scan codes. */
  55.  
  56.             case SPECIAL_KEYS_CHAR:
  57.             special_dispatch( keydata.scan_code,
  58.                       keydata.shift_state );
  59.             break;
  60.  
  61.      /* all others keys we can dispatch from here. some */
  62.      /* are easy, just dispatch based on char code...   */
  63.  
  64.             case CTRL_B_CHAR:
  65.             ctrl_b();
  66.             break;
  67.  
  68.             case BKSP_CHAR:
  69.             bksp();
  70.             break;
  71.  
  72.             case TAB_CHAR:
  73.             tab();
  74.             break;
  75.  
  76.             case CRETURN_CHAR:
  77.             creturn();
  78.             break;
  79.  
  80.             case CTRL_N_CHAR:
  81.             ctrl_n();
  82.             break;
  83.  
  84.             case CTRL_Y_CHAR:
  85.             ctrl_y();
  86.             break;
  87.  
  88.  
  89.      /*  ...for others, we must check the scan code and shift */
  90.      /* also as the char code may be shared with another key. */
  91.  
  92.             case SHIFT_END_CHAR:
  93.             if ( keydata.scan_code == END_SCAN  &&
  94.                  keydata.shift_state < 3 )
  95.                 shift_end();
  96.             else insert( keydata.char_code );
  97.             break;
  98.  
  99.             case SHIFT_DOWN_CHAR:
  100.             if ( keydata.scan_code == DOWN_SCAN  &&
  101.                 keydata.shift_state < 3 )
  102.                 shift_down();
  103.             else insert( keydata.char_code );
  104.             break;
  105.  
  106.             case SHIFT_LEFT_CHAR:
  107.             if ( keydata.scan_code == LEFT_SCAN  &&
  108.                 keydata.shift_state < 3 )
  109.                 shift_left();
  110.             else insert( keydata.char_code );
  111.             break;
  112.  
  113.             case SHIFT_RIGHT_CHAR:
  114.             if ( keydata.scan_code == RIGHT_SCAN  &&
  115.                 keydata.shift_state < 3 )
  116.                 shift_right();
  117.             else insert( keydata.char_code );
  118.             break;
  119.  
  120.             case SHIFT_HOME_CHAR:
  121.             if ( keydata.scan_code == HOME_SCAN  &&
  122.                 keydata.shift_state < 3 )
  123.                 shift_home();
  124.                else insert( keydata.char_code );
  125.             break;
  126.  
  127.             case SHIFT_UP_CHAR:
  128.             if ( keydata.scan_code == UP_SCAN  &&
  129.                 keydata.shift_state < 3 )
  130.                 shift_up();
  131.             else insert( keydata.char_code );
  132.             break;
  133.  
  134.      /*  There's one other possibility, that the char code is 0xE0 */
  135.      /*  which indicates an arrow key on the new AT03 keyboard.    */
  136.      /*  We will treat these in the same manner as special keys.   */
  137.  
  138.           case ARROW_CHAR:
  139.             special_dispatch( keydata.scan_code,
  140.                       keydata.shift_state );
  141.             break;
  142.  
  143.  
  144.         }
  145.  
  146.         }
  147.  
  148.     }
  149.  
  150.  
  151. /*** special_dispatch(c,s) - dispatches control to the appropriate function
  152.  *                 based on character and scan codes received
  153.  *
  154.  *   Characters with zero character codes or character code 0xE0 are sent
  155.  *   here to be dispatched based on their scan code and shift status. These
  156.  *   values are passed to special_dispatch as parameters.
  157.  *
  158.  *   The left and right arrow keys are handled in this routine rather than
  159.  *   dispatched to their own functions in an attempt to gain some speed.
  160.  *
  161.  *   ENTRY:   scan  -     scan code of the key press
  162.  *          shift -     shift state of the key press
  163.  *
  164.  *   EFFECTS:    No global variables are directly effected by this function
  165.  *        unless the key is an unshifted right or left arrow.
  166.  *        In that case, effects are:
  167.  *
  168.  *            LinesMarked    -   this flag is cleared
  169.  *            MarkedLine[]    -   all cleared
  170.  *            CharsMarked    -   this flag is cleared
  171.  *            MarkedChar[]    -   all cleared
  172.  *            EditBuff[]    -   may be flushed if above were set
  173.  *            EditBuffDirty    -   cleared if EditBuff[] flushed
  174.  *            CurCol        -   incremented or decremented
  175.  */
  176.  
  177. special_dispatch(scan,shift)       /* dispatcher for "special keys" based on */
  178.                    /* the scan code and shift code from KBD  */
  179.  
  180.     unsigned char scan;              /* scan code - must be unsigned */
  181.     unsigned shift;                           /* shift code */
  182.  
  183.     {
  184.  
  185.     register short i;                    /* indexing variable */
  186.  
  187.     switch( scan ) {             /* dispatch based on what scan code was */
  188.                     /*    - check the shift state if necessary */
  189.     case LEFT_SCAN:
  190.         if( shift == 0 ) {        /* left arrow handled here for speed */
  191.  
  192.         if ( LinesMarked || CharsMarked ) {
  193.             LinesMarked = 0;            /* if there's marked */
  194.             CharsMarked = 0;            /* text, clear it    */
  195.             for ( i = 0; i < MAXLINES; i++ )
  196.             MarkedLine[i] = 0;
  197.             for ( i = 0; i < LINESIZE; i++ )
  198.             MarkedChar[i] = 0;
  199.             if (EditBuffDirty) {     /* flush EditBuff before redraw */
  200.             EditBuffDirty = 0;
  201.             flushline((TopRow + CurRow), EditBuff);
  202.             }
  203.             drawscr(TopRow);            /* redraw the screen */
  204.             }
  205.  
  206.         if ( CurCol > 0 ) {
  207.             CurCol -= 1;              /* move cursor left 1  */
  208.             VIOSETCURPOS( CurRow, CurCol, 0 );      /* if there's room */
  209.             }
  210.  
  211.         }
  212.  
  213.         else
  214.         shift_left();
  215.         break;
  216.  
  217.     case RIGHT_SCAN:
  218.         if( shift == 0 ) {           /* right arrow handled here for speed */
  219.  
  220.         if ( LinesMarked || CharsMarked ) {
  221.             LinesMarked = 0;            /* if there's marked */
  222.             CharsMarked = 0;            /* text, clear it    */
  223.             for ( i = 0; i < MAXLINES; i++ )
  224.             MarkedLine[i] = 0;
  225.             for ( i = 0; i < LINESIZE; i++ )
  226.             MarkedChar[i] = 0;
  227.             if (EditBuffDirty) {     /* flush EditBuff before redraw */
  228.             EditBuffDirty = 0;
  229.             flushline((TopRow + CurRow), EditBuff);
  230.             }
  231.             drawscr(TopRow);            /* redraw the screen */
  232.             }
  233.  
  234.         if (CurCol < (LINESIZE -1)) {       /* move cursor right one  */
  235.             CurCol += 1;           /* column if there's room */
  236.             VIOSETCURPOS( CurRow, CurCol, 0 );
  237.             }
  238.  
  239.         }
  240.  
  241.         else
  242.         shift_right();
  243.         break;
  244.  
  245.     case UP_SCAN:
  246.         if( shift == 0 )
  247.         up();
  248.         else
  249.         shift_up();
  250.         break;
  251.  
  252.     case DOWN_SCAN:
  253.         if( shift == 0 )
  254.         down();
  255.         else
  256.         shift_down();
  257.         break;
  258.  
  259.     case HOME_SCAN:
  260.         if( shift == 0 )
  261.         home();
  262.         else
  263.         shift_home();
  264.         break;
  265.  
  266.     case END_SCAN:
  267.         if( shift == 0 )
  268.         end_();
  269.         else
  270.         shift_end();
  271.         break;
  272.  
  273.     case PGUP_SCAN:
  274.         pgup();
  275.         break;
  276.  
  277.     case PGDN_SCAN:
  278.         pgdn();
  279.         break;
  280.  
  281.     case CTRL_HOME_SCAN:
  282.         ctrl_home();
  283.         break;
  284.  
  285.     case CTRL_END_SCAN:
  286.         ctrl_end();
  287.         break;
  288.  
  289.     case CTRL_PGUP_SCAN:
  290.         ctrl_pgup();
  291.         break;
  292.  
  293.     case CTRL_PGDN_SCAN:
  294.         ctrl_pgdn();
  295.         break;
  296.  
  297.     case DEL_SCAN:
  298.         del();
  299.         break;
  300.  
  301.     case F9_SCAN:
  302.         F9();
  303.         break;
  304.  
  305.     case F10_SCAN:
  306.         F10();
  307.         break;
  308.  
  309.     default:
  310.         badkey();
  311.  
  312.     }
  313.  
  314.     }
  315.  
  316.  
  317. /*** badkey() - sounds a beep when an invalid or inappropriate key is hit
  318.  *
  319.  *   EFFECTS:    None
  320.  */
  321.  
  322. badkey()
  323.     {
  324.     DOSBEEP (500, 50);             /*     frequency = 500 Hertz */
  325.     }                     /* duration = 50 milliseconds */
  326.  
  327.  
  328. /*** clearscr() - clears the screen by writing blanks over entire screen
  329.  *
  330.  *   clearscr() writes blanks with normal attributes over the entire screen,
  331.  *   effectively clearing it.
  332.  *
  333.  *   EFFECTS:    None
  334.  */
  335.  
  336. void clearscr()
  337.     {
  338.     char buff[2];          /* local buffer for filling cell value */
  339.  
  340.     buff[0] = ' ';             /* cell to replicate is a blank */
  341.     buff[1] = BackNorm + ForeNorm;           /* with normal attributes */
  342.  
  343.     VIOSCROLLUP(0, 0, -1, -1, -1, (char far *)buff, 0);
  344.  
  345.                       /* when the first 5 parameters are */
  346.                       /* set as above, the entire screen */
  347.                       /* is filled with the cell in buff */
  348.     }
  349.  
  350.  
  351. /*** drawscr(startline) - redraws the screen starting at the specified line
  352.  *
  353.  *   drawscr() redraws the screen starting at the line specified in the
  354.  *   parameter it is passed, startline. The screen is drawn with normal
  355.  *   attributes, since this call will never be made with lines marked.
  356.  *   Nothing is done with EditBuff[], that is left to the caller, as is
  357.  *   the value of TopRow.
  358.  *
  359.  *   ENTRY:  startline -  the line in the file which will be at the top of
  360.  *              the screen when redrawn.
  361.  *
  362.  *   EFFECTS:  ScrBuff[][] -  gets reloaded
  363.  */
  364.  
  365. void drawscr(startline)
  366.  
  367.     unsigned short startline;
  368.     {
  369.  
  370.     register unsigned short   i, j;            /* indexing variables */
  371.  
  372.     char normal = BackNorm + ForeNorm;             /* normal attributes */
  373.  
  374.     for ( i = startline, j = 0 ;  j < PageSize ; i++, j++)
  375.     getline( i, &ScrBuff[j][0] );         /* load ScrBuff[][] with the */
  376.                         /* part of the screen we want */
  377.  
  378.     VIOWRTCHARSTRATT ( (char far *)ScrBuff, ( PageSize * LINESIZE ), 0, 0,
  379.               &normal, 0 );
  380.                         /* write it out to the screen */
  381.     }
  382.  
  383.  
  384. /*** drawline() - redraws the current line
  385.  *
  386.  *   drawline() redraws the line the cursor is currently on, using the
  387.  *   contents of EditBuff[]. All marked characters will be drawn with the
  388.  *   appropriate attributes. If the line is marked, all characters are
  389.  *   drawn as marked; if the line is not marked, then the characters marked
  390.  *   flag is checked. If characters are marked, the line is drawn in three
  391.  *   sections - unmarked characters at the front of the line (may be 0),
  392.  *   marked characters in the middle of the line (at least 1), and unmarked
  393.  *   characters at the end of the line (may be 0). If no characters are marked
  394.  *   either, then the line is drawn with all normal attributes.
  395.  *
  396.  *   EFFECTS:  None
  397.  */
  398.  
  399. drawline()
  400.     {
  401.     unsigned short i;                     /* indexing variables */
  402.     unsigned short j;
  403.  
  404.     char hilite = BackHilite + ForeHilite;      /* attributes for marked */
  405.     char normal = BackNorm + ForeNorm;          /* attributes for not marked */
  406.  
  407.     if( MarkedLine[TopRow+CurRow] )
  408.     VIOWRTCHARSTRATT( EditBuff, LINESIZE, CurRow, 0, &hilite, 0);
  409.                          /* if line is marked, do this */
  410.     else if (CharsMarked) {
  411.          for( i = 0; !MarkedChar[i] & (i < LINESIZE); i++ );
  412.          for( j = i; MarkedChar[j] & (j < LINESIZE); j++ );
  413.          VIOWRTCHARSTRATT( &EditBuff[0], i, CurRow, 0, &normal, 0);
  414.          VIOWRTCHARSTRATT( &EditBuff[i], (j - i), CurRow, i, &hilite, 0);
  415.          VIOWRTCHARSTRATT( &EditBuff[j], (LINESIZE - j), CurRow, j,
  416.                    &normal, 0);
  417.          }                 /* else if characters marked, do this */
  418.  
  419.      else VIOWRTCHARSTRATT( EditBuff, LINESIZE, CurRow, 0, &normal, 0);
  420.     }                    /* else if neither marked, do this */
  421.  
  422.  
  423. /*** line25() - updates line number information on last line
  424.  *
  425.  *   line25() updates the line numbers maintained in the lower right hand
  426.  *   corner of the screen - current line of cursor and total lines in file.
  427.  *   These numbers are first converted from their zero-based internal values
  428.  *   to a more friendly one-based number. Lots of standing on our heads is
  429.  *   done to get the numbers into decimal characters without using C runtime
  430.  *   routines or doing divisions.
  431.  *
  432.  *   Note that while the names of these routines refer to the 25th line,
  433.  *   the pagesize is not hardcoded - if we are in 43 line mode, this
  434.  *   information will appear on the 43rd line. However, the spacing within
  435.  *   the line is hardcoded for an 80-column display.
  436.  *
  437.  *   EFFECTS -    None
  438.  */
  439.  
  440. void line25()
  441.     {
  442.  
  443.     int  flag0 = 0;            /* flag to aid in supressing leading 0's */
  444.     int  col = 67;                /* starting column for this info */
  445.     int  i, n;                           /* indexing variables */
  446.     char buff[LINESIZE];            /* buffer to build output string */
  447.     char attrib = Back25 + Fore25;         /* attributes for output string */
  448.  
  449.     n = (TopRow + CurRow + 1);        /* set n to line number cursor is on */
  450.  
  451.     for( i = 0; n > 9999; n -= 10000, i++ );
  452.     if( i > 0 ) {
  453.     flag0 = 1;               /* 10,000's place of current line */
  454.     buff[0] = i + 0x30;
  455.     }
  456.     else buff[0] = ' ';
  457.     VIOWRTCHARSTRATT( buff, 1, PageSize, col, &attrib, 0 );
  458.     col += 1;
  459.  
  460.     for( i = 0; n > 999; n -= 1000, i++ );
  461.     if( i > 0 ) {
  462.     flag0 = 1;                /* 1,000's place of current line */
  463.     buff[0] = i + 0x30;
  464.     }
  465.     else if( flag0 ) buff[0] = '0';
  466.     else buff[0] = ' ';
  467.     VIOWRTCHARSTRATT( buff, 1, PageSize, col, &attrib, 0 );
  468.     col += 1;
  469.  
  470.     for( i = 0; n > 99; n -= 100, i++ );
  471.     if( i > 0 ) {
  472.     flag0 = 1;                  /* 100's place of current line */
  473.     buff[0] = i + 0x30;
  474.     }
  475.     else if( flag0 ) buff[0] = '0';
  476.     else buff[0] = ' ';
  477.     VIOWRTCHARSTRATT( buff, 1, PageSize, col, &attrib, 0 );
  478.     col += 1;
  479.  
  480.     for( i = 0; n > 9; n -= 10, i++ );
  481.     if( i > 0 ) {
  482.     flag0 = 1;                   /* 10's place of current line */
  483.     buff[0] = i + 0x30;
  484.     }
  485.     else if( flag0 ) buff[0] = '0';
  486.     else buff[0] = ' ';
  487.     VIOWRTCHARSTRATT( buff, 1, PageSize, col, &attrib, 0 );
  488.     col += 1;
  489.  
  490.     buff[0] = n + 0x30;             /* 1's place of current line */
  491.     VIOWRTCHARSTRATT( buff, 1, PageSize, col, &attrib, 0 );
  492.     col += 1;
  493.  
  494.     buff[0] = ' ';
  495.     buff[1] = '/';                    /* delimiting characters */
  496.     buff[2] = ' ';
  497.     VIOWRTCHARSTRATT( buff, 3, PageSize, col, &attrib, 0 );
  498.     col += 3;
  499.  
  500.     flag0 = 0;
  501.     n = TotalLines;                 /* n is total lines in file */
  502.  
  503.     for( i = 0; n > 9999; n -= 10000, i++ );
  504.     if( i > 0 ) {
  505.     flag0 = 1;                /* 10,000's place of total lines */
  506.     buff[0] = i + 0x30;
  507.     VIOWRTCHARSTRATT( buff, 1, PageSize, col, &attrib, 0 );
  508.     col += 1;
  509.     }
  510.  
  511.     for( i = 0; n > 999; n -= 1000, i++ );
  512.     if( i > 0 ) {
  513.     flag0 = 1;                 /* 1,000's place of total lines */
  514.     buff[0] = i + 0x30;
  515.     VIOWRTCHARSTRATT( buff, 1, PageSize, col, &attrib, 0 );
  516.     col += 1;
  517.     }
  518.     else if( flag0 ) {
  519.     buff[0] = '0';
  520.     VIOWRTCHARSTRATT( buff, 1, PageSize, col, &attrib, 0 );
  521.     col += 1;
  522.     }
  523.  
  524.     for( i = 0; n > 99; n -= 100, i++ );
  525.     if( i > 0 ) {
  526.     flag0 = 1;                   /* 100's place of total lines */
  527.     buff[0] = i + 0x30;
  528.     VIOWRTCHARSTRATT( buff, 1, PageSize, col, &attrib, 0 );
  529.     col += 1;
  530.     }
  531.     else if( flag0 ) {
  532.     buff[0] = '0';
  533.     VIOWRTCHARSTRATT( buff, 1, PageSize, col, &attrib, 0 );
  534.     col += 1;
  535.     }
  536.  
  537.     for( i = 0; n > 9; n -= 10, i++ );
  538.     if( i > 0 ) {
  539.     flag0 = 1;                /* 10's place of total lines */
  540.     buff[0] = i + 0x30;
  541.     VIOWRTCHARSTRATT( buff, 1, PageSize, col, &attrib, 0 );
  542.     col += 1;
  543.     }
  544.     else if( flag0 ) {
  545.     buff[0] = '0';
  546.     VIOWRTCHARSTRATT( buff, 1, PageSize, col, &attrib, 0 );
  547.     col += 1;
  548.     }
  549.  
  550.     buff[0] = n + 0x30;              /* 1's place of total lines */
  551.     VIOWRTCHARSTRATT( buff, 1, PageSize, col, &attrib, 0 );
  552.  
  553.     col +=1;
  554.     n = LINESIZE - col;      /* fill rest of line with blanks; n is how many */
  555.     for( i = 0; i < LINESIZE; buff[i] = ' ', i++ );
  556.     VIOWRTCHARSTRATT( buff, n, PageSize, col, &attrib, 0 );
  557.  
  558.     }
  559.  
  560. /*** name25() - draws prompt and displays filename on 25th line
  561.  *
  562.  *   This routine draws a prompt line with usage information about some
  563.  *   of the less obvious function keys, and the name of the file currently
  564.  *   being edited. Will be called at the start of execution, and whenever
  565.  *   an error message has been displayed on the 25th line so that we need
  566.  *   to re-draw the usage message after the error is responded to. The
  567.  *   line25() routine takes care of the line numbers at the far right end
  568.  *   of the line.
  569.  *
  570.  *   Note that while the names of these routines refer to the 25th line,
  571.  *   the pagesize is not hardcoded - if we are in 43 line mode, this
  572.  *   information will appear on the 43rd line. Spacing within the line
  573.  *   is hardcoded for an 80-column display.
  574.  *
  575.  *   EFFECTS -    None
  576.  */
  577.  
  578. void name25()
  579.     {
  580.  
  581.     static char message[51] = "^N/^B=insert above/below ^Y=delete F9=save F10=quit";
  582.     char  name[16];                /* for holding name of file */
  583.     char  attrib = Back25 + Fore25;          /* attributes for message */
  584.     int   i, j, k;                      /* indexing variables */
  585.  
  586.  
  587.                           /* first, print usage message */
  588.     VIOWRTCHARSTRATT( message, 51, PageSize, 0, &attrib, 0 );
  589.  
  590.  
  591.     /* build filename string */
  592.  
  593.     name[0] = ' ';
  594.     name[1] = ' ';                /* some blanks at start and end */
  595.     name[2] = ' ';
  596.     name[15] = ' ';
  597.  
  598.     for( i = 0; fname[i] != 0; i++);      /* find null terminator for fname */
  599.  
  600.     if( i > 0 ) i--;             /* point i to last letter in fname */
  601.  
  602.     for( j = i, k = 14;
  603.     (fname[j] != '\\') && (fname[j] != ':') && (j >= 0) && (k >= 0);
  604.     name[k] = fname[j], j--, k-- );
  605.               /* move the file name into name[] backwards until */
  606.               /* we hit a backslash, colon or start of the name */
  607.  
  608.     for( ; k >= 0; name[k] = ' ', k-- );    /* if any room left, blank fill */
  609.  
  610.     VIOWRTCHARSTRATT( name, 16, PageSize, 51, &attrib, 0 );    /* write it */
  611.  
  612.     line25();                    /* call the line number routine */
  613.  
  614.     }
  615.  
  616.  
  617. /*** error25(error) - displays error messages on 25th line, accepts responses
  618.  *
  619.  *   error25() displays an error message on the 25th line when any of several
  620.  *   error conditions are encountered, the type of error being passed as a
  621.  *   parameter. In some cases we just abort; in others we accept input from
  622.  *   the user to determine what to do next.
  623.  *
  624.  *   Note that while the names of these routines refer to the 25th line,
  625.  *   the pagesize is not hardcoded - if we are in 43 line mode, this
  626.  *   information will appear on the 43rd line. Spacing within the line
  627.  *   is hardcoded for an 80-column display.
  628.  *
  629.  *   ENTRY   -    Error - an arbitrary number identifying the error encountered
  630.  *
  631.  *   EFFECTS -    May cause us to end execution; otherwise, none
  632.  */
  633.  
  634. void error25(error)
  635.     unsigned short error;
  636.     {
  637.     static char message1[51] = "ERROR: Out of memory or can't read file            ";
  638.     static char message2[51] = "ERROR: Unable to create backup. Continue?  (y/n)   ";
  639.     static char message3[51] = "File not found. Create?  (y/n)                     ";
  640.     static char message4[51] = "ERROR: Unable to create file                       ";
  641.     static char message5[51] = "ERROR: Unable to open file - denied write access   ";
  642.     static char message6[51] = "ERROR: Unable to open file                         ";
  643.     static char message7[51] = "ERROR: Out of memory.   S = save  Q = quit         ";
  644.     static char message8[51] = "ERROR: No filename given on command line           ";
  645.     static char message9[51] = "ERROR: Invalid argument on command line            ";
  646.     static char message10[51] = "ERROR: Too many parameters on command line         ";
  647.     static char message11[51] = "ERROR: Unable to save file.   C = continue         ";
  648.     static char message99[51] = "ERROR: Unknown error. Continue?  (y/n)             ";
  649.     struct  KeyData keydata;
  650.     char  attrib = Back25 + Fore25;         /* attributes for our messages */
  651.  
  652.  
  653.     switch( error ) {           /* take the appropriate action for the error */
  654.  
  655.     case 1:
  656.         VIOWRTCHARSTRATT( message1, 51, PageSize, 0, &attrib, 0 );
  657.         quit(1);
  658.         break;                 /* 1 -> print message and quit */
  659.  
  660.     case 2:
  661.         VIOWRTCHARSTRATT( message2, 51, PageSize, 0, &attrib, 0 );
  662.         VIOSETCURPOS( PageSize, 50, 0 );
  663.  
  664.         while( 1 ) {           /* 2 -> get a character from KBD */
  665.  
  666.         KBDCHARIN( &keydata, 0, 0 );
  667.  
  668.         if( (keydata.char_code == 'y') || (keydata.char_code == 'Y') ) {
  669.             name25();
  670.             break;                  /* if Y, go ahead */
  671.             }
  672.  
  673.         else if( (keydata.char_code == 'n') || (keydata.char_code == 'N') ) {
  674.             VIOWRTCHARSTRATT( &keydata.char_code, 1, PageSize, 50, &attrib, 0 );
  675.             quit(1);               /* if N, quit with error */
  676.             break;
  677.             }
  678.  
  679.         else badkey();          /* otherwise wait for another key */
  680.  
  681.         }
  682.         break;
  683.  
  684.     case 3:
  685.         VIOWRTCHARSTRATT( message3, 51, PageSize, 0, &attrib, 0 );
  686.         VIOSETCURPOS( PageSize, 32, 0 );
  687.  
  688.         while( 1 ) {           /* 3 -> get a character from KBD */
  689.  
  690.         KBDCHARIN( &keydata, 0, 0 );
  691.  
  692.         if( (keydata.char_code == 'y') || (keydata.char_code == 'Y') ) {
  693.             name25();
  694.             break;                  /* if Y, go ahead */
  695.             }
  696.  
  697.         else if( (keydata.char_code == 'n') || (keydata.char_code == 'N') ) {
  698.             VIOWRTCHARSTRATT( &keydata.char_code, 1, PageSize, 50, &attrib, 0 );
  699.             quit(1);               /* if N, quit with error */
  700.             break;
  701.             }
  702.  
  703.         else badkey();          /* otherwise wait for another key */
  704.  
  705.         }
  706.         break;
  707.  
  708.     case 4:
  709.         VIOWRTCHARSTRATT( message4, 51, PageSize, 0, &attrib, 0 );
  710.         quit(1);
  711.         break;                 /* 4 -> print message and quit */
  712.  
  713.     case 5:
  714.         VIOWRTCHARSTRATT( message5, 51, PageSize, 0, &attrib, 0 );
  715.         quit(1);
  716.         break;                 /* 5 -> print message and quit */
  717.  
  718.     case 6:
  719.         VIOWRTCHARSTRATT( message6, 51, PageSize, 0, &attrib, 0 );
  720.         quit(1);
  721.         break;                 /* 6 -> print message and quit */
  722.  
  723.     case 7:
  724.         VIOWRTCHARSTRATT( message7, 51, PageSize, 0, &attrib, 0 );
  725.         VIOSETCURPOS( PageSize, 44, 0 );
  726.  
  727.         while( 1 ) {           /* 7 -> get a character from KBD */
  728.  
  729.         KBDCHARIN( &keydata, 0, 0 );
  730.  
  731.         if( (keydata.char_code == 's') || (keydata.char_code == 'S') ) {
  732.             VIOWRTCHARSTRATT( &keydata.char_code, 1, PageSize, 50, &attrib, 0 );
  733.             if ( !savefile(fhandle)) {    /* if S, save file and quit */
  734.             freesegs();
  735.             VIOSETCURPOS( PageSize, 0, 0 );
  736.             quit(1);
  737.             }
  738.             else
  739.             error25(11);         /* call error 11 if can't save */
  740.             }
  741.  
  742.         else if( (keydata.char_code == 'q') || (keydata.char_code == 'Q') ) {
  743.             VIOWRTCHARSTRATT( &keydata.char_code, 1, PageSize, 50, &attrib, 0 );
  744.             quit(1);               /* if Q, quit with error */
  745.             break;
  746.             }
  747.  
  748.         else badkey();          /* otherwise wait for another key */
  749.  
  750.         }
  751.         break;
  752.  
  753.     case 8:
  754.         VIOWRTCHARSTRATT( message8, 51, PageSize, 0, &attrib, 0 );
  755.         quit(1);
  756.         break;                 /* 8 -> print message and quit */
  757.  
  758.     case 9:
  759.         VIOWRTCHARSTRATT( message9, 51, PageSize, 0, &attrib, 0 );
  760.         quit(1);
  761.         break;                 /* 9 -> print message and quit */
  762.  
  763.     case 10:
  764.         VIOWRTCHARSTRATT( message10, 51, PageSize, 0, &attrib, 0 );
  765.         quit(1);
  766.         break;                /* 10 -> print message and quit */
  767.  
  768.     case 11:
  769.         VIOWRTCHARSTRATT( message11, 51, PageSize, 0, &attrib, 0 );
  770.         VIOSETCURPOS( PageSize, 45, 0 );
  771.  
  772.         while( 1 ) {          /* 11 -> get a character from KBD */
  773.  
  774.         KBDCHARIN( &keydata, 0, 0 );
  775.  
  776.         if( (keydata.char_code == 'c') || (keydata.char_code == 'C') ) {
  777.             name25();
  778.             break;                /* C means continue */
  779.             }
  780.         else badkey();          /* otherwise wait for another key */
  781.  
  782.         }
  783.         break;
  784.  
  785.     default:
  786.         VIOWRTCHARSTRATT( message99, 51, PageSize, 0, &attrib, 0 );
  787.         VIOSETCURPOS( PageSize, 40, 0 );
  788.  
  789.         while( 1 ) {               /* UNKNOWN error number! */
  790.                         /* get a character from KBD */
  791.         KBDCHARIN( &keydata, 0, 0 );
  792.  
  793.         if( (keydata.char_code == 'y') || (keydata.char_code == 'Y') ) {
  794.             name25();
  795.             break;                  /* if Y, go ahead */
  796.             }
  797.  
  798.         else if( (keydata.char_code == 'n') || (keydata.char_code == 'N') ) {
  799.             VIOWRTCHARSTRATT( &keydata.char_code, 1, PageSize, 50, &attrib, 0 );
  800.             quit(1);               /* if N, quit with error */
  801.             break;
  802.             }
  803.  
  804.         else badkey();          /* otherwise wait for another key */
  805.  
  806.         }
  807.         break;
  808.  
  809.     }
  810.  
  811.     }
  812.