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

  1. /****** KEYFUNCS.C - a collection of routines to service special keys
  2.  *             each routine has the name of the key it services
  3.  */
  4.  
  5. #include <ctype.h>
  6. #include <dos.h>
  7. #include <doscalls.h>
  8. #include <subcalls.h>
  9. #include "ssedefs.h"
  10. #include "keydefs.h"
  11.  
  12.  
  13. /*** insert(c) - inserts the character c at the current cursor position
  14.  *
  15.  *   This routine is called when any regular printable character is hit.
  16.  *
  17.  *   insert(c) checks to see if there is room in EditBuff[] to insert the
  18.  *   character it is passed by seeing if there is already a printable
  19.  *   character in the 80th column. If so, no character can be inserted
  20.  *   so we just call badkey(). If there is room, insert the character
  21.  *   at the position indicated by CurCol and shift everything past that
  22.  *   over one; mark EditBuff[] as dirty.
  23.  *
  24.  *   If there is text that has been marked, insert() will call del() to
  25.  *   remove it before inserting its character where the marked text was.
  26.  *
  27.  *   The character we are passed has already been checked as being a
  28.  *   valid printable characters.
  29.  *
  30.  *   insert(c)
  31.  *
  32.  *   ENTRY:      c  -    the validated character to be inserted
  33.  *
  34.  *   EFFECTS:      EditBuff[]     - changes its contents if successful
  35.  *          EditBuffDirty  - sets this flag if EditBuff changed
  36.  *          LinesMarked     - clears this if set
  37.  *          CharsMarked     - clears this if set
  38.  *          CurCol     - increments this one
  39.  *
  40.  *   The effects of del() should also be considered since it may be
  41.  *   called from this function.
  42.  */
  43.  
  44. insert(c)
  45.     char c;         /* the character we are to insert, already validated */
  46.     {
  47.  
  48.     register short i;                     /* indexing variable */
  49.  
  50.     if (LinesMarked || CharsMarked)       /* if there is marked text around, */
  51.     del();                   /* we first want to delete it      */
  52.  
  53.     if ( EditBuff[LINESIZE - 1] == ' ')  /* can only insert when there's room */
  54.     {
  55.     for ( i = (LINESIZE - 1); i > CurCol; i-- )
  56.         EditBuff[i] = EditBuff[i-1];     /* shift everything over one */
  57.     EditBuff[CurCol] = c;             /* put in the new character  */
  58.     drawline();
  59.     CurCol += 1;                        /* update display */
  60.     VIOSETCURPOS( CurRow, CurCol, 0 );
  61.     EditBuffDirty = 1;             /* mark edit buffer as dirty */
  62.     }
  63.  
  64.     else badkey();               /* if no room, exit as for invalid key */
  65.  
  66.     }
  67.  
  68.  
  69. /*** up() - moves the cursor up one row
  70.  *
  71.  *   up() moves the cursor position up one row. If we are at the top of
  72.  *   the screen already, up() scrolls the screen down one line. If we
  73.  *   are at the top of the file, it does nothing. If there is marked text
  74.  *   around, up() will clear it without deleting. Because the current row
  75.  *   in the file is changed by up(), EditBuff[] is flushed and refilled
  76.  *   and line25() is called to update the line information at the bottom
  77.  *   of the screen.
  78.  *
  79.  *   EFFECTS:      EditBuff[]     - flushes its current contents and reloads
  80.  *          EditBuffDirty  - clears this flag
  81.  *          LinesMarked     - clears this flag
  82.  *          MarkedLine[]     - clears all
  83.  *          CharsMarked     - clears this flag
  84.  *          MarkedChar[]     - clears all
  85.  *          TopRow     - if at top of screen, decrements this one
  86.  *          CurRow     - otherwise, decrements this one
  87.  */
  88.  
  89.  
  90. void up()
  91.     {
  92.  
  93.     register short i;                      /* indexing variable */
  94.  
  95.     char buff[2];          /* local buffer for scrolling fill character */
  96.     buff[0] = 32;          /*         character = 32 = <blank>  */
  97.     buff[1] = ForeNorm;       /*              attribute = normal   */
  98.  
  99.     if (EditBuffDirty) {              /* this call will change */
  100.     EditBuffDirty = 0;              /* cursor line, so flush */
  101.     flushline((TopRow + CurRow), EditBuff);   /* edit buffer if dirty  */
  102.     }
  103.  
  104.     if ( LinesMarked || CharsMarked ) {
  105.     LinesMarked = 0;             /* if there's marked text */
  106.     CharsMarked = 0;             /* around, clear it and   */
  107.     for ( i = 0; i < MAXLINES; i++ )     /* redraw the screen       */
  108.         MarkedLine[i] = 0;
  109.     for ( i = 0; i < LINESIZE; i++ )
  110.         MarkedChar[i] = 0;
  111.     drawscr(TopRow);
  112.     }
  113.  
  114.     if ( (TopRow + CurRow) != 0 ) {         /* if top of file, do nothing */
  115.     if ( CurRow == 0 ) {
  116.         TopRow -= 1;          /* if top of screen, scroll down */
  117.         VIOSCROLLDN( 0, 0, (PageSize - 1), (LINESIZE - 1), 1,
  118.                (char far *)buff, 0);
  119.         getline( (TopRow + CurRow), &EditBuff[0] );
  120.         drawline();
  121.         }
  122.     else {
  123.         CurRow -= 1;          /* otherwise just move cursor up */
  124.         getline( (TopRow + CurRow), &EditBuff[0] );
  125.         VIOSETCURPOS( CurRow, CurCol, 0 );
  126.         }
  127.     }
  128.  
  129.     line25();          /* reset line numbers on 25th line to reflect change */
  130.  
  131.     }
  132.  
  133.  
  134. /*** down() - moves the cursor up one row
  135.  *
  136.  *   down() moves the cursor down one row. If we are at the top of
  137.  *   the screen already, down() scrolls the screen up one line. If we
  138.  *   are at the end of the file, it does nothing. If there is marked text
  139.  *   around, down() will clear it without deleting. Because the current row
  140.  *   in the file is changed by down(), EditBuff[] is flushed and refilled
  141.  *   and line25() is called to update the line information at the bottom
  142.  *   of the screen.
  143.  *
  144.  *   EFFECTS:      EditBuff[]     - flushes its current contents and reloads
  145.  *          EditBuffDirty  - clears this flag
  146.  *          LinesMarked     - clears this flag
  147.  *          MarkedLine[]     - clears all
  148.  *          CharsMarked     - clears this flag
  149.  *          MarkedChar[]     - clears all
  150.  *          TopRow     - if at bottom of screen, increments this one
  151.  *          CurRow     - otherwise, increments this one
  152.  */
  153.  
  154.  
  155. void down()
  156.     {
  157.  
  158.     register short i;                      /* indexing variable */
  159.  
  160.     char buff[2];          /* local buffer for scrolling fill character */
  161.     buff[0] = 32;          /*          character = 32 = <blank> */
  162.     buff[1] = ForeNorm;       /*               attribute = normal  */
  163.  
  164.     if (EditBuffDirty) {              /* this call will change */
  165.     EditBuffDirty = 0;              /* cursor line, so flush */
  166.     flushline((TopRow + CurRow), EditBuff);   /* edit buffer if dirty  */
  167.     }
  168.  
  169.     if ( LinesMarked || CharsMarked ) {
  170.     LinesMarked = 0;             /* if there's marked text */
  171.     CharsMarked = 0;             /* around, clear it and   */
  172.     for ( i = 0; i < MAXLINES; i++ )     /* redraw the screen       */
  173.         MarkedLine[i] = 0;
  174.     for ( i = 0; i < LINESIZE; i++ )
  175.         MarkedChar[i] = 0;
  176.     drawscr(TopRow);
  177.     }
  178.  
  179.     if ( (TopRow + CurRow) < (TotalLines) ) {         /* if EOF, do nothing */
  180.     if ( CurRow == (PageSize - 1) ) {   /* if end of screen, scroll up */
  181.         TopRow += 1;
  182.         VIOSCROLLUP( 0, 0, CurRow, (LINESIZE - 1), 1,
  183.                (char far *)buff, 0);
  184.         getline( (TopRow + CurRow), &EditBuff[0] );
  185.         drawline();
  186.         }
  187.     else {
  188.         CurRow += 1;              /* else move cursor down */
  189.         getline( (TopRow + CurRow), &EditBuff[0] );
  190.         VIOSETCURPOS( CurRow, CurCol, 0 );
  191.         }
  192.     }
  193.  
  194.     line25();          /* reset line numbers on 25th line to reflect change */
  195.  
  196.     }
  197.  
  198.  
  199. /*** home() - moves the cursor to beginning of the line
  200.  *
  201.  *   home() moves the cursor to the position of the first printable character
  202.  *   in the current line. If there is marked text, home() will clear it
  203.  *   without deleting. We need to be able to get correct information about
  204.  *   the length of the current line from LineTable[], so we flush EditBuff[]
  205.  *   on entry; but since the current line does not get changed, we do not
  206.  *   reload it (current contents remain correct) and we do not call line25().
  207.  *
  208.  *   EFFECTS:      EditBuffDirty  - clears this flag
  209.  *          LinesMarked     - clears this flag
  210.  *          MarkedLine[]     - clears all
  211.  *          CharsMarked     - clears this flag
  212.  *          MarkedChar[]     - clears all
  213.  *          CurCol     - set to position of first printable character
  214.  */
  215.  
  216. void home()
  217.     {
  218.  
  219.     register short i, j;                   /* indexing variables */
  220.  
  221.  
  222.     if (EditBuffDirty) {               /* this call will need to */
  223.     EditBuffDirty = 0;               /* get correct info on    */
  224.     flushline((TopRow + CurRow), EditBuff);    /* line length, so flush  */
  225.     }                       /* edit buffer if dirty   */
  226.  
  227.     if ( LinesMarked || CharsMarked ) {
  228.     LinesMarked = 0;               /* if there's marked text */
  229.     CharsMarked = 0;               /* around, clear it and   */
  230.     for ( i = 0; i < MAXLINES; i++ )       /* redraw the screen      */
  231.         MarkedLine[i] = 0;
  232.     for ( i = 0; i < LINESIZE; i++ )
  233.         MarkedChar[i] = 0;
  234.     drawscr(TopRow);
  235.     }
  236.  
  237.     if( (TopRow + CurRow) < TotalLines ) {
  238.     i = LineTable[TopRow + CurRow]->linelength;    /* i is position of  */
  239.     i--;                        /* last char in line */
  240.     }
  241.     else i = 0;         /* if we're off the end of the file, that's 0... */
  242.  
  243.  
  244.     for( j = 0; ( j <= i )  &&    !isgraph(EditBuff[j]); j++ );
  245.  
  246.     CurCol = j;                      /* j is position of */
  247.     VIOSETCURPOS( CurRow, CurCol, 0 );             /* first non-blank  */
  248.  
  249.     }
  250.  
  251.  
  252. /*** end_() - moves the cursor to one position past the end of the current line
  253.  *
  254.  *   end_() moves the cursor to one position beyond the position of the last
  255.  *   printable character in the current line. If the last printable character
  256.  *   is already in column 80, we just go there. If there is marked text,
  257.  *   end_() will clear it without deleting. We need to be able to get correct
  258.  *   information about the length of the current line from LineTable[], so
  259.  *   we flush EditBuff[] on entry; but since the current line does not get
  260.  *   changed, we do not reload it (current contents remain correct) and we
  261.  *   do not call line25(). Note that this routine had to be named end_() not
  262.  *   end() since that is a reserved word under the compiler used.
  263.  *
  264.  *   EFFECTS:      EditBuffDirty  - clears this flag
  265.  *          LinesMarked     - clears this flag
  266.  *          MarkedLine[]     - clears all
  267.  *          CharsMarked     - clears this flag
  268.  *          MarkedChar[]     - clears all
  269.  *          CurCol     - set to position of last printable
  270.  *                   character, plus one if possible
  271.  */
  272.  
  273. void end_()
  274.     {
  275.  
  276.     register short i;                       /* indexing variable */
  277.  
  278.     if (EditBuffDirty) {              /* this call will need to */
  279.     EditBuffDirty = 0;              /* get correct info on    */
  280.     flushline((TopRow + CurRow), EditBuff);   /* line length, so flush  */
  281.     }                      /* edit buffer if dirty   */
  282.  
  283.     if ( LinesMarked || CharsMarked ) {
  284.     LinesMarked = 0;              /* if there's marked text */
  285.     CharsMarked = 0;              /* around, clear it and   */
  286.     for ( i = 0; i < MAXLINES; i++ )      /* redraw the screen        */
  287.         MarkedLine[i] = 0;
  288.     for ( i = 0; i < LINESIZE; i++ )
  289.         MarkedChar[i] = 0;
  290.     drawscr(TopRow);
  291.     }
  292.  
  293.     if( (TopRow + CurRow) < TotalLines ) {
  294.     i = LineTable[TopRow + CurRow]->linelength;    /* i is position of  */
  295.     }                           /* last char in line */
  296.     else i = 0;
  297.  
  298.     CurCol = i;
  299.     VIOSETCURPOS( CurRow, CurCol, 0 );
  300.  
  301.     }
  302.  
  303.  
  304. /*** pgup() - moves up one screen
  305.  *
  306.  *   pgup() subtracts PageSize from the current value of TopRow and then
  307.  *   redraws the screen, effectively moving us up one screen. If TopRow
  308.  *   is less than PageSize, we just go to the start of the file. The
  309.  *   position of the cursor on the screen is not altered. If there is marked
  310.  *   text, pgup() will clear it without deleting. Because this call changes
  311.  *   the current line, we flush and reload EditBuff[].
  312.  *
  313.  *   EFFECTS:      EditBuff[]     - flushes and reloads
  314.  *          EditBuffDirty  - clears this flag
  315.  *          LinesMarked     - clears this flag
  316.  *          MarkedLine[]     - clears all
  317.  *          CharsMarked     - clears this flag
  318.  *          MarkedChar[]     - clears all
  319.  *          TopRow     - gets PageSize subtracted from it
  320.  *                   if possible, otherwise set to 0.
  321.  */
  322.  
  323. void pgup()
  324.     {
  325.  
  326.     register short i;                      /* indexing variable */
  327.  
  328.     if (EditBuffDirty) {              /* this call will change */
  329.     EditBuffDirty = 0;              /* cursor line, so flush */
  330.     flushline((TopRow + CurRow), EditBuff);   /* edit buffer if dirty  */
  331.     }
  332.  
  333.     if ( LinesMarked || CharsMarked ) {
  334.     LinesMarked = 0;             /* if there's marked text */
  335.     CharsMarked = 0;             /* around, clear it and   */
  336.     for ( i = 0; i < MAXLINES; i++ )     /* redraw the screen       */
  337.         MarkedLine[i] = 0;
  338.     for ( i = 0; i < LINESIZE; i++ )
  339.         MarkedChar[i] = 0;
  340.     }
  341.  
  342.     if ( TopRow >= PageSize )         /* go up one page if there's room */
  343.     TopRow -= PageSize;
  344.     else {
  345.     TopRow = 0;               /* otherwise just go to top of file */
  346.     CurRow = 0;
  347.     VIOSETCURPOS( CurRow, CurCol, 0 );
  348.     }
  349.  
  350.     drawscr(TopRow);                     /* redraw screen and  */
  351.     getline( (TopRow + CurRow), &EditBuff[0] );      /* update edit buffer */
  352.     line25();          /* reset line numbers on 25th line to reflect change */
  353.  
  354.     }
  355.  
  356.  
  357. /*** pgdn() - moves down one screen
  358.  *
  359.  *   pgdn() adds PageSize to the current value of TopRow and then
  360.  *   redraws the screen, effectively moving us down one screen. If the
  361.  *   result of adding TopRow and PageSize is greater than TotalLines
  362.  *   (in other words, we would be moving off the end of the file), then
  363.  *   we just move to one beyond the end of the file. The position of the
  364.  *   cursor on the screen is not altered. If there is marked text,
  365.  *   pgdn() will clear it without deleting. Because this call changes
  366.  *   the current line, we flush and reload EditBuff[].
  367.  *
  368.  *   EFFECTS:      EditBuff[]     - flushes and reloads
  369.  *          EditBuffDirty  - clears this flag
  370.  *          LinesMarked     - clears this flag
  371.  *          MarkedLine[]     - clears all
  372.  *          CharsMarked     - clears this flag
  373.  *          MarkedChar[]     - clears all
  374.  *          TopRow     - gets PageSize added to it if possible,
  375.  *                   otherwise set to TotalLines - PageSize - 1.
  376.  */
  377.  
  378. void pgdn()
  379.     {
  380.  
  381.     register short i;                    /* indexing variable */
  382.  
  383.     if (EditBuffDirty) {                /* this call will change */
  384.     EditBuffDirty = 0;                /* cursor line, so flush */
  385.     flushline((TopRow + CurRow), EditBuff);     /* edit buffer if dirty  */
  386.     }
  387.  
  388.     if ( LinesMarked || CharsMarked ) {
  389.     LinesMarked = 0;               /* if there's marked text */
  390.     CharsMarked = 0;               /* around, clear it         */
  391.     for ( i = 0; i < MAXLINES; i++ )
  392.         MarkedLine[i] = 0;
  393.     for ( i = 0; i < LINESIZE; i++ )
  394.         MarkedChar[i] = 0;
  395.     }
  396.  
  397.     TopRow += PageSize;                 /* go down one page  */
  398.     if ( TopRow > (TotalLines - (PageSize -1)) ) {    /* if there's room,  */
  399.     TopRow = (TotalLines - (PageSize -1));        /* else stop at last */
  400.     CurRow = (PageSize -1);             /* full page         */
  401.     VIOSETCURPOS(CurRow, CurCol, 0);
  402.     }
  403.  
  404.     drawscr(TopRow);                       /* redraw screen and  */
  405.     getline( (TopRow + CurRow), &EditBuff[0] );        /* update edit buffer */
  406.     line25();        /* reset line numbers on 25th line to reflect change */
  407.  
  408.     }
  409.  
  410.  
  411. /*** bksp() - deletes character to right of the cursor; moves cursor right one
  412.  *
  413.  *   bksp() clears any marked text without deleting it, flushes EditBuff[],
  414.  *   moves the cursor right one position and calls del(). If we're at the
  415.  *   beginning of a line so there's nothing to our right, calls badkey().
  416.  *
  417.  *   EFFECTS:      EditBuff[]     - flushes and reloads
  418.  *          EditBuffDirty  - clears this flag
  419.  *          LinesMarked     - clears this flag
  420.  *          MarkedLine[]     - clears all
  421.  *          CharsMarked     - clears this flag
  422.  *          MarkedChar[]     - clears all
  423.  *          CurCol     - decrements if possible
  424.  *
  425.  *   The effects of del() should also be considered since it may be
  426.  *   called from this function.
  427.  */
  428.  
  429. void bksp()
  430.     {
  431.  
  432.     register short i;                       /* indexing variable */
  433.  
  434.     if ( LinesMarked || CharsMarked ) {
  435.     LinesMarked = 0;              /* if there's marked text */
  436.     CharsMarked = 0;              /* around, clear it and   */
  437.     for ( i = 0; i < MAXLINES; i++ )      /* redraw the screen        */
  438.         MarkedLine[i] = 0;
  439.     for ( i = 0; i < LINESIZE; i++ )
  440.         MarkedChar[i] = 0;
  441.  
  442.     if (EditBuffDirty) {                 /* flush before redraw */
  443.         EditBuffDirty = 0;                 /* to get any changes  */
  444.         flushline((TopRow + CurRow), EditBuff);
  445.         }
  446.     drawscr(TopRow);
  447.     }
  448.  
  449.     if( CurCol == 0 )         /* can't backspace if already at left edge */
  450.     badkey();
  451.     else {
  452.     CurCol -= 1;            /* otherwise, move left one and del */
  453.     VIOSETCURPOS( CurRow, CurCol, 0 );
  454.     del();
  455.     }
  456.     }
  457.  
  458.  
  459. /*** del() - deletes all indicated text
  460.  *
  461.  *   del() is the function for deleting text. What gets deleted depends on
  462.  *   what is marked. If there are marked lines around (as indicated by the
  463.  *   LinesMarked flag) then we delete the marked lines, clear all the line
  464.  *   marking flags, and adjust LineTable[] to reflect the change. Note that
  465.  *   if there are lines marked, there cannot be characters marked too. If
  466.  *   there are no lines marked, but characters marked, these characters are
  467.  *   deleted and EditBuff[] is adjusted to reflect the change and flagged
  468.  *   as dirty. If there are no lines or characters marked, then the character
  469.  *   under the cursor is deleted and EditBuff[] is adjusted accordingly and
  470.  *   marked as dirty.
  471.  *
  472.  *   EFFECTS:      EditBuff[]     - contents altered if no lines were marked
  473.  *          EditBuffDirty  - set if no lines were marked
  474.  *          LineTable[]     - contents altered if lines were marked
  475.  *          TotalLines     - altered if lines were marked
  476.  *          LinesMarked     - clears this flag
  477.  *          MarkedLine[]     - clears all
  478.  *          CharsMarked     - clears this flag
  479.  *          MarkedChar[]     - clears all
  480.  *          TopRow     - may change, depending on what's marked
  481.  *          CurRow     - may change, depending on what's marked
  482.  *
  483.  */
  484.  
  485. void del()
  486.     {
  487.  
  488.     register short i, j;                /* indexing variables */
  489.  
  490.     if (LinesMarked) {                  /* if lines are marked, do this */
  491.     for( i = 0; !MarkedLine[i]; i++ );
  492.     j = i;                   /* i, j refer to first marked line */
  493.     if( i <= TopRow ) {
  494.         if( i != 0 ) {
  495.         TopRow = i - 1;       /* if first line to be deleted is   */
  496.         CurRow = 1;          /* off the top of the screen, then  */
  497.         }              /* set TopRow to last unmarked line */
  498.         else {
  499.         TopRow = 0;           /* or if there are no unmarked     */
  500.         CurRow = 0;           /* lines ahead of the marked ones, */
  501.         }               /* set TopRow to start of the file */
  502.         }
  503.     else CurRow = i - TopRow;
  504.     for( ; MarkedLine[i]; i++ )           /* delete all marked lines */
  505.         deleteline( i );           /* i refers to first unmarked line */
  506.     for( ; i < TotalLines; i++,j++ )        /* adjust LineTable[] */
  507.         LineTable[j] = LineTable[i];
  508.     TotalLines -= ( i - j );             /* adjust TotalLines */
  509.     LinesMarked = 0;
  510.     for( i = 0; i < MAXLINES; i++ )       /* clear line marking flags */
  511.         MarkedLine[i] = 0;
  512.     drawscr(TopRow);                     /* redraw screen */
  513.     VIOSETCURPOS(CurRow, CurCol, 0);
  514.     getline( (TopRow + CurRow), &EditBuff[0] );     /* reload EditBuff[] */
  515.     }
  516.  
  517.     else if (CharsMarked) {   /* if no lines marked but chars marked, do this */
  518.     for( i = 0; !MarkedChar[i] & ( i < LINESIZE ); i++ );
  519.     j = i;                  /* i, j refer to first marked character */
  520.     CurCol = j;
  521.     VIOSETCURPOS(CurRow, CurCol, 0);        /* adjust cursor position */
  522.     for( ; MarkedChar[i] & (i < LINESIZE); i++ ); /* i now first unmarked */
  523.     for( ; i < LINESIZE; i++, j++ )
  524.         EditBuff[j] = EditBuff[i];     /* remove characters between i and j */
  525.     for( ; j < LINESIZE; j++ )
  526.         EditBuff[j] = ' ';              /* fill end of line with blanks */
  527.     CharsMarked = 0;
  528.     for( i = 0; i < LINESIZE; i++ )  /* clear all character marking flags */
  529.         MarkedChar[i] = 0;
  530.     drawline();                           /* redraw line */
  531.     EditBuffDirty = 1;              /* mark EditBuff[] as dirty */
  532.     }
  533.  
  534.     else {                  /* if no lines or chars marked, do this */
  535.     for( i = (CurCol + 1); i < LINESIZE; i++ )
  536.        EditBuff[i-1] = EditBuff[i];      /* remove character under cursor */
  537.     EditBuff[LINESIZE-1] = ' ';           /* fill end of line with blank */
  538.     drawline();                           /* redraw line */
  539.     EditBuffDirty = 1;              /* mark EditBuff[] as dirty */
  540.     }
  541.  
  542.     line25();        /* reset line numbers on 25th line to reflect changes */
  543.  
  544.     }
  545.  
  546.  
  547. /*** F9() - saves the file being edited and exits
  548.  *
  549.  *   F9() save the file being edited with any changes that have been made
  550.  *   and exits the editor. The user is given a prompt to be sure they want
  551.  *   do quit; hitting carriage return goes ahead with the save-and-quit,
  552.  *   while any other key returns you to the editor.
  553.  *
  554.  *   EFFECTS:      If quit not completed:    EditBuff[]      -  gets flushed
  555.  *                        EditBuffDirty -  gets cleared
  556.  */
  557.  
  558. void F9()
  559.     {
  560.  
  561.     static char message[LINESIZE] = "Save file as:";
  562.     struct  KeyData keydata;
  563.     char attrib = Fore25 + Back25;
  564.     int i;
  565.  
  566.     if (EditBuffDirty) {           /* flush the edit buffer if dirty */
  567.     EditBuffDirty = 0;           /* so all editting will be saved  */
  568.     flushline((TopRow + CurRow), EditBuff);
  569.     }
  570.  
  571.     for( i = 0; (i < 65) && (fname[i] != 0); message[i + 14] = fname[i], i++ );
  572.                     /* copy filename into prompt message */
  573.  
  574.     VIOWRTCHARSTRATT( message, 80, PageSize, 0, &attrib, 0 );
  575.                             /* write out message */
  576.  
  577.     KBDCHARIN( &keydata, 0, 0 );           /* wait for user response */
  578.  
  579.     if( keydata.char_code == CRETURN_CHAR ) {      /* if response was <CR>... */
  580.     if ( !savefile(fhandle)) {
  581.         freesegs();
  582.         VIOSETCURPOS( 24, 0, 0 );            /* ... clean up and quit */
  583.         quit(0);
  584.         }
  585.     else error25(11);
  586.     }
  587.     name25();                 /* ... otherwise restore message on */
  588.                      /* 25th line and return to editor   */
  589.     }
  590.  
  591.  
  592. /*** F10() - exits the editor without saving the file being edited
  593.  *
  594.  *   F10() exits from the editor without saving back the file being edited,
  595.  *   leaving the file as it was before the editor was invoked. A prompt
  596.  *   will be issued to give the user a chance to change their mind before
  597.  *   all editing is lost.
  598.  *
  599.  *   EFFECTS:      If quit not completed:    EditBuff[]      -  gets flushed
  600.  *                        EditBuffDirty -  gets cleared
  601.  */
  602.  
  603.  
  604. void F10()
  605.     {
  606.     static char message[51] = "WARNING: Any edits will be lost   (y/n)?           ";
  607.     struct  KeyData keydata;
  608.     char attrib = Fore25 + Back25;           /* attributes for message */
  609.     int  row, col;              /* to save current cursor position */
  610.     int  done = 0;        /* flag to be set when have a valid response */
  611.  
  612.     if (EditBuffDirty) {            /* flush EditBuff[] if dirty */
  613.     EditBuffDirty = 0;
  614.     flushline((TopRow + CurRow), EditBuff);
  615.     }
  616.  
  617.     VIOWRTCHARSTRATT( message, 51, PageSize, 0, &attrib, 0 );
  618.     VIOGETCURPOS( &row, &col, 0 );            /* print prompt and set  */
  619.     VIOSETCURPOS( PageSize, 42, 0 );            /* cursor to await reply */
  620.  
  621.     while( !done ) {
  622.  
  623.     KBDCHARIN( &keydata, 0, 0 );         /* get a character from KBD */
  624.  
  625.     if( (keydata.char_code == 'y') || (keydata.char_code == 'Y') ) {
  626.         VIOWRTCHARSTRATT( &keydata.char_code, 1, PageSize, 42, &attrib, 0 );
  627.         freesegs();
  628.         quit(0);                /* if Y, quit without saving */
  629.         }
  630.     else if( (keydata.char_code == 'n') || (keydata.char_code == 'N') ) {
  631.         VIOSETCURPOS( row, col, 0 );
  632.         name25();
  633.         done = 1;                   /* if N, return to editor */
  634.         }
  635.     else badkey();               /* otherwise wait for another key */
  636.  
  637.     }
  638.  
  639.     }
  640.  
  641.  
  642. /*** ctrl_home() - repositions cursor to upper left hand corner of screen
  643.  *
  644.  *   ctrl_home() moves the cursor to the upper left hand corner of the
  645.  *   screen, coordinate position (0,0). Since the current cursor line is
  646.  *   probably changed, we flush and reload EditBuff[]. If there is any
  647.  *   text marked, this call will clear the marking without deleting.
  648.  *   Line number information on 25th line is redrawn to reflect changes.
  649.  *   The actual content of the screen - i.e. the value of TopRow - is
  650.  *   unchanged by this call.
  651.  *
  652.  *   EFFECTS:      EditBuff[]     - flushes and reloads
  653.  *          EditBuffDirty  - clears this flag
  654.  *          LinesMarked     - clears this flag
  655.  *          MarkedLine[]     - clears all
  656.  *          CharsMarked     - clears this flag
  657.  *          MarkedChar[]     - clears all
  658.  *          CurRow     - set to 0
  659.  *          CurCol     - set to 0
  660.  */
  661.  
  662. void ctrl_home()
  663.     {
  664.  
  665.     register short i;                      /* indexing variable */
  666.  
  667.     if (EditBuffDirty) {              /* this call will change */
  668.     EditBuffDirty = 0;              /* cursor line, so flush */
  669.     flushline((TopRow + CurRow), EditBuff);   /* edit buffer if dirty  */
  670.     }
  671.  
  672.     if ( LinesMarked || CharsMarked ) {
  673.     LinesMarked = 0;             /* if there's marked text */
  674.     CharsMarked = 0;             /* around, clear it and   */
  675.     for ( i = 0; i < MAXLINES; i++ )     /* redraw the screen       */
  676.         MarkedLine[i] = 0;
  677.     for ( i = 0; i < LINESIZE; i++ )
  678.         MarkedChar[i] = 0;
  679.     drawscr(TopRow);
  680.     }
  681.  
  682.     if ( CurRow != 0  ||  CurCol != 0 ) {
  683.     CurRow = 0;                    /* reposition to (0,0) */
  684.     CurCol = 0;
  685.     VIOSETCURPOS( CurRow, CurCol, 0 );
  686.     getline( (TopRow + CurRow), &EditBuff[0] );
  687.     }
  688.  
  689.     line25();        /* update line numbers on 25th line to reflect changes */
  690.  
  691.     }
  692.  
  693.  
  694. /*** ctrl_end() - repositions cursor to lower left hand corner of screen
  695.  *
  696.  *   ctrl_end() moves the cursor to the lower left hand corner of the
  697.  *   screen. Since the current cursor line is probably changed, we flush
  698.  *   and reload EditBuff[]. If there is any text marked, this call will
  699.  *   clear the marking without deleting. Line number information on 25th
  700.  *   line is redrawn to reflect changes. The actual content of the screen
  701.  *   is unchanged by this call.
  702.  *
  703.  *   EFFECTS:      EditBuff[]     - flushes and reloads
  704.  *          EditBuffDirty  - clears this flag
  705.  *          LinesMarked     - clears this flag
  706.  *          MarkedLine[]     - clears all
  707.  *          CharsMarked     - clears this flag
  708.  *          MarkedChar[]     - clears all
  709.  *          CurRow     - set to PAGESIZE - 1
  710.  *          CurCol     - set to 0
  711.  */
  712.  
  713. void ctrl_end()
  714.     {
  715.  
  716.     register short i;
  717.  
  718.     if (EditBuffDirty) {              /* this call will change */
  719.     EditBuffDirty = 0;              /* cursor line, so flush */
  720.     flushline((TopRow + CurRow), EditBuff);   /* edit buffer if dirty  */
  721.     }
  722.  
  723.     if ( LinesMarked || CharsMarked ) {
  724.     LinesMarked = 0;             /* if there's marked text */
  725.     CharsMarked = 0;             /* around, clear it and   */
  726.     for ( i = 0; i < MAXLINES; i++ )     /* redraw the screen       */
  727.         MarkedLine[i] = 0;
  728.     for ( i = 0; i < LINESIZE; i++ )
  729.         MarkedChar[i] = 0;
  730.     drawscr(TopRow);
  731.     }
  732.  
  733.     if( CurRow != (PageSize - 1) || CurCol != 0 ) {
  734.     CurRow = (PageSize - 1);              /* reposition cursor */
  735.     CurCol = 0;
  736.     VIOSETCURPOS( CurRow, CurCol, 0 );
  737.     getline( (TopRow + CurRow), &EditBuff[0] );
  738.     }
  739.  
  740.     line25();        /* update line numbers on 25th line to reflect changes */
  741.  
  742.     }
  743.  
  744.  
  745. /*** ctrl_pgup() - repositions cursor to beginning of file
  746.  *
  747.  *   ctrl_pgup() redraws the screen with the first screenfull of the file
  748.  *   and moves the cursor to the upper left hand corner of the screen,
  749.  *   coordinate position (0,0). Since the current cursor line is
  750.  *   probably changed, we flush and reload EditBuff[]. If there is any
  751.  *   text marked, this call will clear the marking without deleting.
  752.  *   Line number information on 25th line is redrawn to reflect changes.
  753.  *
  754.  *   EFFECTS:      EditBuff[]     - flushes and reloads
  755.  *          EditBuffDirty  - clears this flag
  756.  *          LinesMarked     - clears this flag
  757.  *          MarkedLine[]     - clears all
  758.  *          CharsMarked     - clears this flag
  759.  *          MarkedChar[]     - clears all
  760.  *          TopRow     - set to 0
  761.  *          CurRow     - set to 0
  762.  *          CurCol     - set to 0
  763.  */
  764.  
  765. void ctrl_pgup()
  766.     {
  767.  
  768.     register short i;                      /* indexing variable */
  769.  
  770.     if (EditBuffDirty) {              /* this call will change */
  771.     EditBuffDirty = 0;              /* cursor line, so flush */
  772.     flushline((TopRow + CurRow), EditBuff);   /* edit buffer if dirty  */
  773.     }
  774.  
  775.     if ( LinesMarked || CharsMarked ) {
  776.     LinesMarked = 0;             /* if there's marked text */
  777.     CharsMarked = 0;             /* around, clear it - no  */
  778.     for ( i = 0; i < MAXLINES; i++ )     /* need to redraw screen  */
  779.         MarkedLine[i] = 0;
  780.     for ( i = 0; i < LINESIZE; i++ )
  781.         MarkedChar[i] = 0;
  782.     }
  783.  
  784.     TopRow = 0;
  785.     CurRow = 0;                   /* reposition and redraw */
  786.     CurCol = 0;
  787.     VIOSETCURPOS( CurRow, CurCol, 0 );
  788.     drawscr(TopRow);
  789.     getline( (TopRow + CurRow), &EditBuff[0] );       /* reload EditBuff[] */
  790.     line25();                           /* update 25th line */
  791.  
  792.     }
  793.  
  794.  
  795. /*** ctrl_pgdn() - repositions cursor to beginning of file
  796.  *
  797.  *   ctrl_pgdn() redraws the screen with the last screenfull of the file
  798.  *   and moves the cursor to the lower left hand corner of the screen,
  799.  *   one line past the end of the file. Since the current cursor line is
  800.  *   probably changed, we flush and reload EditBuff[]. If there is any
  801.  *   text marked, this call will clear the marking without deleting.
  802.  *   Line number information on 25th line is redrawn to reflect changes.
  803.  *
  804.  *   EFFECTS:      EditBuff[]     - flushes and reloads
  805.  *          EditBuffDirty  - clears this flag
  806.  *          LinesMarked     - clears this flag
  807.  *          MarkedLine[]     - clears all
  808.  *          CharsMarked     - clears this flag
  809.  *          MarkedChar[]     - clears all
  810.  *          TopRow     - set to TotalLines - (PageSize - 1)
  811.  *          CurRow     - set to end of file + 1
  812.  *          CurCol     - set to 0
  813.  */
  814.  
  815. void ctrl_pgdn()
  816.     {
  817.     register short i;                      /* indexing variable */
  818.  
  819.     if (EditBuffDirty) {              /* this call will change */
  820.     EditBuffDirty = 0;              /* cursor line, so flush */
  821.     flushline((TopRow + CurRow), EditBuff);   /* edit buffer if dirty  */
  822.     }
  823.  
  824.     if ( LinesMarked || CharsMarked ) {
  825.     LinesMarked = 0;             /* if there's marked text */
  826.     CharsMarked = 0;             /* around, clear it - no  */
  827.     for ( i = 0; i < MAXLINES; i++ )     /* need to redraw screen  */
  828.         MarkedLine[i] = 0;             /* as it gets done later  */
  829.     for ( i = 0; i < LINESIZE; i++ )
  830.         MarkedChar[i] = 0;
  831.     }
  832.     if (TotalLines > (PageSize - 1))
  833.     TopRow = TotalLines - (PageSize - 1);         /* recalculate TopRow */
  834.     else TopRow = 0;
  835.     CurRow = TotalLines - TopRow;          /* set cursor row and column */
  836.     CurCol = 0;
  837.     VIOSETCURPOS( CurRow, CurCol, 0 );
  838.     getline( (TopRow + CurRow), &EditBuff[0] );       /* reload EditBuff[] */
  839.     drawscr(TopRow);                      /* redraw screen */
  840.     line25();                           /* update 25th line */
  841.  
  842.     }
  843.  
  844.  
  845. /*** shift_left() - moves cursor left one and marks that character for deletion.
  846.  *
  847.  *   shift_left() moves the cursor one position to the left. If we are on
  848.  *   a line that is already marked, that's all it does - just like regular
  849.  *   left, but markings are not cleared. If we are not on a marked line,
  850.  *   then the character we just moved to is marked for deletion. Unless it
  851.  *   already was marked for deletion, in which case it gets un-marked.
  852.  *
  853.  *   EFFECTS:      CharsMarked     - sets this flag if LinesMarked not set
  854.  *          MarkedChar[]     - sets this for the character we just moved to
  855.  *          CurCol     - decremented one
  856.  */
  857.  
  858. void shift_left()
  859.     {
  860.  
  861.     if ( LinesMarked ) {       /* if this line is marked, just move left */
  862.     if ( CurCol > 0 ) {
  863.         CurCol -= 1;
  864.         VIOSETCURPOS( CurRow, CurCol, 0 );
  865.         }
  866.     }
  867.     else if( CurCol > 0 ) {        /* otherwise, see if there's room... */
  868.     CurCol -= 1;
  869.     VIOSETCURPOS( CurRow, CurCol, 0 );           /* ...if so move left */
  870.     CharsMarked = 1;
  871.     if (MarkedChar[CurCol])
  872.         MarkedChar[CurCol] = 0;    /* and set marking for that character */
  873.     else MarkedChar[CurCol] = 1;
  874.     drawline();               /* redraw line to update markings */
  875.     }
  876.  
  877.     }
  878.  
  879.  
  880. /*** shift_right() - moves cursor right one and marks the character
  881.  *             we were previously on for deletion.
  882.  *
  883.  *   shift_right() moves the cursor one position to the right. If we are on
  884.  *   a line that is already marked, that's all it does - just like regular
  885.  *   right, but markings are not cleared. If we are not on a marked line,
  886.  *   then the character we just moved from is marked for deletion. Unless it
  887.  *   already was marked for deletion, in which case it gets un-marked.
  888.  *
  889.  *   EFFECTS:      CharsMarked     - sets this flag if LinesMarked not set
  890.  *          MarkedChar[]     - sets this for the character we just left
  891.  *          CurCol     - incremented one
  892.  */
  893.  
  894. void shift_right()
  895.     {
  896.  
  897.     if ( LinesMarked ) {         /* if this line marked, just move right */
  898.     if (CurCol < (LINESIZE - 1)) {
  899.         CurCol += 1;
  900.         VIOSETCURPOS( CurRow, CurCol, 0 );
  901.         }
  902.     }
  903.     else if( CurCol < (LINESIZE - 1)) {  /* otherwise, see if there's room.. */
  904.     CharsMarked = 1;
  905.     if (MarkedChar[CurCol])        /* if so, mark character we're on */
  906.         MarkedChar[CurCol] = 0;
  907.     else MarkedChar[CurCol] = 1;
  908.     CurCol += 1;                      /* then move right one */
  909.     VIOSETCURPOS( CurRow, CurCol, 0 );
  910.     drawline();                      /* and redraw line */
  911.     }
  912.  
  913.     }
  914.  
  915.  
  916. /*** shift_up() - moves cursor up one line and marks lines for deletion
  917.  *
  918.  *   shift_up() moves the cursor one line up. If no lines are marked, then
  919.  *   both the previous line and the line moved to get marked for deletion.
  920.  *   If lines are already marked, and were marked starting with another
  921.  *   shift_up, then only the line we move to gets marked (the one we just
  922.  *   left would already be marked). If there are lines marked but they
  923.  *   were marked starting with a shift_down, then we un-mark the line we
  924.  *   just left and do nothing to the line moved to. Unless the line moved
  925.  *   to is the last one marked, in which case we un-mark it also to clear all
  926.  *   markings. To determine how lines first got marked - by a shift_up or
  927.  *   shift_down - we give the flag LinesMarked two different TRUE values,
  928.  *   1 or 2 respectively.
  929.  *
  930.  *   EFFECTS:      EditBuff[]     - flushes and reloads
  931.  *          EditBuffDirty  - clears
  932.  *          LinesMarked     - sets this flag, unless un-marking only
  933.  *                   marked line present, in which case clears it
  934.  *          MarkedLine[]     - may set or clear this
  935.  *          CharsMarked     - clears this flag as we now have marked lines
  936.  *          MarkedChar[]     - clears all
  937.  *          TopRow     - decremented one if at top of page
  938.  *          CurRow     - decremented one if not at top of page
  939.  */
  940.  
  941. void shift_up()
  942.     {
  943.     register short i;                      /* indexing variable */
  944.  
  945.     char buff[2];          /* local buffer for scrolling fill character */
  946.     buff[0] = 32;                   /* character = 32 = <blank> */
  947.     buff[1] = ForeHilite + BackHilite;           /*  attribute = highlighted */
  948.  
  949.     if (EditBuffDirty) {              /* this call will change */
  950.     EditBuffDirty = 0;              /* cursor line, so flush */
  951.     flushline((TopRow + CurRow), EditBuff);   /* edit buffer if dirty  */
  952.     }
  953.  
  954.     if ( CharsMarked ) {            /* clear CharsMarked flags */
  955.     CharsMarked = 0;            /* since we now will have  */
  956.     for ( i = 0; i < LINESIZE; i++ )    /* the whole line marked.  */
  957.         MarkedChar[i] = 0;
  958.     }
  959.  
  960.   /* if no lines currently marked, do this */
  961.     if( !LinesMarked ) {
  962.     LinesMarked = 1;    /* set flag to indicate marking started UP */
  963.     MarkedLine[ TopRow + CurRow ] = 1;              /* mark line */
  964.     drawline();                          /* redraw it */
  965.     if ( (TopRow + CurRow) != 0 ) {            /* if there's room, */
  966.         MarkedLine[ TopRow + CurRow - 1 ] = 1;    /* mark line above */
  967.         if ( CurRow == 0 ) {
  968.         TopRow -= 1;              /* ...may have to scroll */
  969.         VIOSCROLLDN( 0, 0, (PageSize - 1), (LINESIZE - 1), 1,
  970.                (char far *)buff, 0);
  971.         getline( (TopRow + CurRow), &EditBuff[0] );     /* reload */
  972.         }
  973.         else {               /* ...or may not have to scroll */
  974.         CurRow -= 1;
  975.         getline( (TopRow + CurRow), &EditBuff[0] );     /* reload */
  976.         VIOSETCURPOS( CurRow, CurCol, 0 );
  977.         }
  978.         drawline();                 /* redraw new line */
  979.         }
  980.     }
  981.  
  982.   /* if lines marked, and shift_up started marking, do this */
  983.     else if( LinesMarked == 1 ) {
  984.     if ( (TopRow + CurRow) != 0 ) {        /* if not at top of screen, */
  985.         MarkedLine[ TopRow + CurRow - 1 ] = 1;    /* mark next line up */
  986.         if ( CurRow == 0 ) {
  987.         TopRow -= 1;              /* ...may have to scroll */
  988.         VIOSCROLLDN( 0, 0, (PageSize - 1), (LINESIZE - 1), 1,
  989.                (char far *)buff, 0);
  990.         getline( (TopRow + CurRow), &EditBuff[0] );     /* reload */
  991.         }
  992.         else {
  993.         CurRow -= 1;           /* ...or may not have to scroll */
  994.         getline( (TopRow + CurRow), &EditBuff[0] );     /* reload */
  995.         VIOSETCURPOS( CurRow, CurCol, 0 );
  996.         }
  997.         drawline();                 /* redraw line move to */
  998.         }
  999.     }
  1000.  
  1001.   /* if lines marked, and shift_down started marking, do this */
  1002.     else if( LinesMarked == 2 ) {
  1003.     MarkedLine[ TopRow + CurRow ] = 0;       /* un-mark current line */
  1004.     drawline();                          /* redraw it */
  1005.     if( (TopRow + CurRow) != 0 ) {
  1006.         if( CurRow == 0 ) {          /* ...may have to scroll down */
  1007.         TopRow -= 1;
  1008.         VIOSCROLLDN( 0, 0, (PageSize - 1), (LINESIZE - 1), 1,
  1009.                (char far *)buff, 0);
  1010.         getline( (TopRow + CurRow), &EditBuff[0] );     /* reload */
  1011.         }
  1012.         else {             /* or may not have to scroll down */
  1013.         CurRow -= 1;
  1014.         getline( (TopRow + CurRow), &EditBuff[0] );     /* reload */
  1015.         VIOSETCURPOS( CurRow, CurCol, 0 );
  1016.         }
  1017.         if( !MarkedLine[ TopRow + CurRow - 1 ] ) { /* if line moved to */
  1018.         MarkedLine[ TopRow + CurRow ] = 0;     /* is last marked,  */
  1019.         LinesMarked = 0;               /* clear it too       */
  1020.         drawline();
  1021.         }
  1022.         }
  1023.     }
  1024.  
  1025.     line25();        /* update line numbers on 25th line to reflect changes */
  1026.  
  1027.     }
  1028.  
  1029.  
  1030. /*** shift_down() - moves cursor down one line and marks lines for deletion
  1031.  *
  1032.  *   shift_down() moves the cursor one line down. If no lines are marked, then
  1033.  *   both the previous line and the line moved to get marked for deletion.
  1034.  *   If lines are already marked, and were marked starting with another
  1035.  *   shift_down, then only the line we move to gets marked (the one we just
  1036.  *   left would already be marked). If there are lines marked but they
  1037.  *   were marked starting with a shift_up, then we un-mark the line we
  1038.  *   just left and do nothing to the line moved to. Unless the line moved
  1039.  *   to is the last one marked, in which case we un-mark it also to clear all
  1040.  *   markings. To determine how lines first got marked - by a shift_up or
  1041.  *   shift_down - we give the flag LinesMarked two different TRUE values,
  1042.  *   1 or 2 respectively.
  1043.  *
  1044.  *   EFFECTS:      EditBuff[]     - flushes and reloads
  1045.  *          EditBuffDirty  - clears
  1046.  *          LinesMarked     - sets this flag, unless un-marking only
  1047.  *                   marked line present, in which case clears it
  1048.  *          MarkedLine[]     - may set or clear this
  1049.  *          CharsMarked     - clears this flag as we now have marked lines
  1050.  *          MarkedChar[]     - clears all
  1051.  *          TopRow     - incremented one if at bottom of page
  1052.  *          CurRow     - incremented one if not at bottom of page
  1053.  */
  1054.  
  1055. void shift_down()
  1056.     {
  1057.     register short i;                    /* indexing variable */
  1058.  
  1059.     char buff[2];              /* local buffer for fill character */
  1060.     buff[0] = 32;                 /* character = 32 = <blank> */
  1061.     buff[1] = ForeHilite + BackHilite;         /* attribute =  highlighted */
  1062.  
  1063.     if (EditBuffDirty) {                /* this call will change */
  1064.     EditBuffDirty = 0;                /* cursor line, so flush */
  1065.     flushline((TopRow + CurRow), EditBuff);     /* edit buffer if dirty  */
  1066.     }
  1067.  
  1068.     if ( CharsMarked ) {                 /* clear all character  */
  1069.     CharsMarked = 0;                 /* markings, since line */
  1070.     for ( i = 0; i < LINESIZE; i++ )         /* is now marked.         */
  1071.         MarkedChar[i] = 0;
  1072.     }
  1073.  
  1074.   /* if no lines are currently marked, do this */
  1075.     if( !LinesMarked ) {
  1076.     LinesMarked = 2;       /* set flag to show marking started with DOWN */
  1077.     MarkedLine[ TopRow + CurRow ] = 1;        /* mark current line */
  1078.     drawline();                        /* and redraw it */
  1079.     if( ( TopRow + CurRow ) < TotalLines ) {    /* if room to move down, */
  1080.         MarkedLine[ TopRow + CurRow + 1 ] = 1;      /* mark line below */
  1081.         if ( CurRow == (PageSize - 1) ) {
  1082.         TopRow += 1;                /* ...may have to scroll */
  1083.         VIOSCROLLUP( 0, 0, CurRow, (LINESIZE - 1), 1,
  1084.                (char far *)buff, 0);
  1085.         getline( (TopRow + CurRow), &EditBuff[0] );       /* reload */
  1086.         }
  1087.         else {                 /* ...or may not have to scroll */
  1088.         CurRow += 1;
  1089.         getline( (TopRow + CurRow), &EditBuff[0] );       /* reload */
  1090.         VIOSETCURPOS( CurRow, CurCol, 0 );
  1091.         }
  1092.         drawline();                   /* redraw new line */
  1093.         }
  1094.     }
  1095.  
  1096.   /* if lines are marked, and first marking was another shift_down, do this */
  1097.     else if( LinesMarked == 2 ) {
  1098.     if ( (TopRow + CurRow) < TotalLines ) {     /* if room to move down */
  1099.         MarkedLine[ TopRow + CurRow + 1 ] = 1;     /* mark line below */
  1100.         if ( CurRow == (PageSize - 1) ) {
  1101.         TopRow += 1;               /* ...may have to scroll */
  1102.         VIOSCROLLUP( 0, 0, CurRow, (LINESIZE - 1), 1,
  1103.                (char far *)buff, 0);
  1104.         getline( (TopRow + CurRow), &EditBuff[0] );      /* reload */
  1105.         }
  1106.         else {                /* ...or may not have to scroll */
  1107.         CurRow += 1;
  1108.         getline( (TopRow + CurRow), &EditBuff[0] );      /* reload */
  1109.         VIOSETCURPOS( CurRow, CurCol, 0 );
  1110.         }
  1111.         drawline();     /* redraw the current line to show markings */
  1112.         }
  1113.     }
  1114.  
  1115.   /* if lines are marked, and first marking was a shift_up, do this */
  1116.     else if( LinesMarked == 1 ) {
  1117.     MarkedLine[ TopRow + CurRow ] = 0;        /* un-mark current line */
  1118.     drawline();                       /* and redraw it */
  1119.     if ( (TopRow + CurRow) < TotalLines ) {
  1120.         if ( CurRow == (PageSize - 1) ) {
  1121.         TopRow += 1;               /* ...may have to scroll */
  1122.         VIOSCROLLUP( 0, 0, CurRow, (LINESIZE - 1), 1,
  1123.                (char far *)buff, 0);
  1124.         getline( (TopRow + CurRow), &EditBuff[0] );      /* reload */
  1125.         }
  1126.         else {                /* ...or may not have to scroll */
  1127.         CurRow += 1;
  1128.         getline( (TopRow + CurRow), &EditBuff[0] );      /* reload */
  1129.         VIOSETCURPOS( CurRow, CurCol, 0 );
  1130.         }
  1131.         }
  1132.     if( (TopRow + CurRow) < TotalLines ) {
  1133.         if( !MarkedLine[ TopRow + CurRow + 1 ] ) {
  1134.         MarkedLine[ TopRow + CurRow ] = 0;
  1135.         LinesMarked = 0;             /* if only 1 line left */
  1136.         }                  /* marked, un-mark it too */
  1137.         }
  1138.     drawline();             /* redraw line to reflect markings */
  1139.  
  1140.     }
  1141.  
  1142.     line25();         /* update line info on bottom line to show changes */
  1143.  
  1144.     }
  1145.  
  1146.  
  1147. /*** shift_home() - moves cursor to first character in current line and
  1148.  *            marks all characters in between for deletion
  1149.  *
  1150.  *   shift_down() moves the cursor to the first printable character in the
  1151.  *   current line. If the line is already marked, that's all it does, just
  1152.  *   like a regular home except markings are not cleared. Otherwise, all
  1153.  *   characters between the cursor position when the function is called and
  1154.  *   the first character in the line get their markings toggled - that is, if
  1155.  *   they are not marked they get marked, if they are already marked they
  1156.  *   get un-marked.
  1157.  *
  1158.  *   EFFECTS:      EditBuff[]     - flushes and reloads
  1159.  *          EditBuffDirty  - clears
  1160.  *          CharsMarked     - sets this flag unless line is marked
  1161.  *          MarkedChar[]     - sets for all appropriate characters
  1162.  *          CurCol     - set to position of first printable character
  1163.  */
  1164.  
  1165. void shift_home()
  1166.     {
  1167.  
  1168.     register short i, j;                   /* indexing variables */
  1169.  
  1170.     if (EditBuffDirty) {               /* this call will need to */
  1171.     EditBuffDirty = 0;               /* get correct info on    */
  1172.     flushline((TopRow + CurRow), EditBuff);    /* line length, so flush  */
  1173.     }                       /* edit buffer if dirty   */
  1174.  
  1175.     if( (TopRow + CurRow) < TotalLines ) {
  1176.     i = LineTable[TopRow + CurRow]->linelength;    /* i is position + 1 */
  1177.     }                        /* last char in line */
  1178.     else i = 0;
  1179.  
  1180.     for( j = 0; ( j < i )  &&  !isgraph(EditBuff[j]); j++ );
  1181.                              /* j is position of */
  1182.                              /* first non-blank  */
  1183.     if( !LinesMarked ) {              /* if no lines marked,     */
  1184.     if( j < CurCol ) {              /* flag everything between */
  1185.         CharsMarked = 1;              /* CurCol and j as Marked  */
  1186.         for( i = j; i < CurCol; i++ ) {
  1187.         if( !MarkedChar[i] )
  1188.             MarkedChar[i] = 1;         /* may be moving forward... */
  1189.         else MarkedChar[i] = 0;
  1190.         }
  1191.         }
  1192.     else if( j > CurCol ) {
  1193.         CharsMarked = 1;
  1194.         for( i = CurCol; i < j; i++ ) {          /* ... or backward */
  1195.         if( !MarkedChar[i] )
  1196.             MarkedChar[i] = 1;
  1197.         else MarkedChar[i] = 0;
  1198.         }
  1199.         }
  1200.     }
  1201.  
  1202.     CurCol = j;                /* if lines are marked, just move */
  1203.     VIOSETCURPOS( CurRow, CurCol, 0 );
  1204.     drawline();                  /* redraw line to show markings */
  1205.  
  1206.     }
  1207.  
  1208.  
  1209. /*** shift_end() - moves cursor to one beyond last character in current line
  1210.  *           and marks all characters in between for deletion
  1211.  *
  1212.  *   shift_down() moves the cursor to one position beyond the last printable
  1213.  *   character in the current line. If the line is already marked, that's all
  1214.  *   it does, just like a regular end_ except markings are not cleared.
  1215.  *   Otherwise, all characters between the cursor position when the function
  1216.  *   is called and the final cursor position get their markings toggled - that
  1217.  *   is, if they are not marked they get marked, if they are already marked
  1218.  *   they get un-marked.
  1219.  *
  1220.  *   EFFECTS:      EditBuff[]     - flushes and reloads
  1221.  *          EditBuffDirty  - clears
  1222.  *          CharsMarked     - sets this flag unless line is marked
  1223.  *          MarkedChar[]     - sets for all appropriate characters
  1224.  *          CurCol     - set to one beyond position of
  1225.  *                   last printable character
  1226.  */
  1227.  
  1228. void shift_end()
  1229.     {
  1230.  
  1231.     register short i, j;                  /* indexing variables */
  1232.  
  1233.     if (EditBuffDirty) {              /* this call will need to */
  1234.     EditBuffDirty = 0;              /* get correct info on    */
  1235.     flushline((TopRow + CurRow), EditBuff);   /* line length, so flush  */
  1236.     }                      /* edit buffer if dirty   */
  1237.  
  1238.     if( (TopRow + CurRow) < TotalLines ) {
  1239.     i = LineTable[TopRow + CurRow]->linelength;    /* i is position + 1 */
  1240.     }                           /* last char in line */
  1241.     else i = 0;
  1242.  
  1243.     if( !LinesMarked ) {             /* if no lines marked,     */
  1244.     if( i < CurCol ) {             /* flag everything between */
  1245.         CharsMarked = 1;             /* CurCol and i as Marked  */
  1246.         for( j = i; j < CurCol; j++ ) {
  1247.         if( !MarkedChar[j] )            /* may move forwards... */
  1248.             MarkedChar[j] = 1;
  1249.         else MarkedChar[j] = 0;
  1250.         }
  1251.         }
  1252.     else if( i > CurCol ) {
  1253.         CharsMarked = 1;                /* ... or backwards */
  1254.         for( j = CurCol; j < i; j++ ) {
  1255.         if( !MarkedChar[j] )
  1256.             MarkedChar[j] = 1;
  1257.         else MarkedChar[j] = 0;
  1258.         }
  1259.         }
  1260.     }
  1261.  
  1262.     CurCol = i;                 /* if line is marked, just move */
  1263.     VIOSETCURPOS( CurRow, CurCol, 0 );
  1264.     drawline();                           /* redraw */
  1265.  
  1266.     }
  1267.