home *** CD-ROM | disk | FTP | other *** search
/ The C Users' Group Library 1994 August / wc-cdrom-cusersgrouplibrary-1994-08.iso / vol_100 / 198_01 / basic.c < prev    next >
C/C++ Source or Header  |  1990-01-23  |  17KB  |  626 lines

  1. /*
  2.  * The routines in this file move the cursor around on the screen. They
  3.  * compute a new value for the cursor, then adjust ".". The display code
  4.  * always updates the cursor location, so only moves between lines, or
  5.  * functions that adjust the top line in the window and invalidate the
  6.  * framing, are hard.
  7.  */
  8. #include        <stdio.h>
  9. #include    "estruct.h"
  10. #include        "edef.h"
  11.  
  12. /*
  13.  * Move the cursor to the
  14.  * beginning of the current line.
  15.  * Trivial.
  16.  */
  17. gobol(f, n)
  18. {
  19.         curwp->w_doto  = 0;
  20.         return (TRUE);
  21. }
  22.  
  23. /*
  24.  * Move the cursor backwards by "n" characters. If "n" is less than zero call
  25.  * "forwchar" to actually do the move. Otherwise compute the new cursor
  26.  * location. Error if you try and move out of the buffer. Set the flag if the
  27.  * line pointer for dot changes.
  28.  */
  29. backchar(f, n)
  30. register int    n;
  31. {
  32.         register LINE   *lp;
  33.  
  34.         if (n < 0)
  35.                 return (forwchar(f, -n));
  36.         while (n--) {
  37.                 if (curwp->w_doto == 0) {
  38.                         if ((lp=lback(curwp->w_dotp)) == curbp->b_linep)
  39.                                 return (FALSE);
  40.                         curwp->w_dotp  = lp;
  41.                         curwp->w_doto  = llength(lp);
  42.                         curwp->w_flag |= WFMOVE;
  43.                 } else
  44.                         curwp->w_doto--;
  45.         }
  46.         return (TRUE);
  47. }
  48.  
  49. /*
  50.  * Move the cursor to the end of the current line. Trivial. No errors.
  51.  */
  52. goeol(f, n)
  53. {
  54.         curwp->w_doto  = llength(curwp->w_dotp);
  55.         return (TRUE);
  56. }
  57.  
  58. /*
  59.  * Move the cursor forwards by "n" characters. If "n" is less than zero call
  60.  * "backchar" to actually do the move. Otherwise compute the new cursor
  61.  * location, and move ".". Error if you try and move off the end of the
  62.  * buffer. Set the flag if the line pointer for dot changes.
  63.  */
  64. forwchar(f, n)
  65. register int    n;
  66. {
  67.         if (n < 0)
  68.                 return (backchar(f, -n));
  69.         while (n--) {
  70.                 if (curwp->w_doto == llength(curwp->w_dotp)) {
  71.                         if (curwp->w_dotp == curbp->b_linep)
  72.                                 return (FALSE);
  73.                         curwp->w_dotp  = lforw(curwp->w_dotp);
  74.                         curwp->w_doto  = 0;
  75.                         curwp->w_flag |= WFMOVE;
  76.                 } else
  77.                         curwp->w_doto++;
  78.         }
  79.         return (TRUE);
  80. }
  81.  
  82. gotoline(f, n)        /* move to a particular line.
  83.                argument (n) must be a positive integer for
  84.                this to actually do anything        */
  85.  
  86. {
  87.     register int status;    /* status return */
  88.     char arg[NSTRING];    /* buffer to hold argument */
  89.  
  90.     /* get an argument if one doesnt exist */
  91.     if (f == FALSE) {
  92.         if ((status=mlreply("Line to GOTO: ", arg, NSTRING)) != TRUE) {
  93.             mlwrite("[Aborted]");
  94.             return(status);
  95.         }
  96.         n = atoi(arg);
  97.     }
  98.  
  99.     if (n < 1)        /* if a bogus argument...then leave */
  100.         return(FALSE);
  101.  
  102.     /* first, we go to the start of the buffer */
  103.         curwp->w_dotp  = lforw(curbp->b_linep);
  104.         curwp->w_doto  = 0;
  105.     return(forwline(f, n-1));
  106. }
  107.  
  108. /*
  109.  * Goto the beginning of the buffer. Massive adjustment of dot. This is
  110.  * considered to be hard motion; it really isn't if the original value of dot
  111.  * is the same as the new value of dot. Normally bound to "M-<".
  112.  */
  113. gobob(f, n)
  114. {
  115.         curwp->w_dotp  = lforw(curbp->b_linep);
  116.         curwp->w_doto  = 0;
  117.         curwp->w_flag |= WFHARD;
  118.         return (TRUE);
  119. }
  120.  
  121. /*
  122.  * Move to the end of the buffer. Dot is always put at the end of the file
  123.  * (ZJ). The standard screen code does most of the hard parts of update.
  124.  * Bound to "M->".
  125.  */
  126. goeob(f, n)
  127. {
  128.         curwp->w_dotp  = curbp->b_linep;
  129.         curwp->w_doto  = 0;
  130.         curwp->w_flag |= WFHARD;
  131.         return (TRUE);
  132. }
  133.  
  134. /*
  135.  * Move forward by full lines. If the number of lines to move is less than
  136.  * zero, call the backward line function to actually do it. The last command
  137.  * controls how the goal column is set. Bound to "C-N". No errors are
  138.  * possible.
  139.  */
  140. forwline(f, n)
  141. {
  142.         register LINE   *dlp;
  143.  
  144.         if (n < 0)
  145.                 return (backline(f, -n));
  146.  
  147.     /* flag this command as a line move */
  148.         thisflag |= CFCPCN;
  149.  
  150.     /* if we are on the last line as we start....fail the command */
  151.     if (curwp->w_dotp == curbp->b_linep)
  152.         return(FALSE);
  153.  
  154.     /* if the last command was not note a line move,
  155.        reset the goal column */
  156.         if ((lastflag&CFCPCN) == 0)
  157.                 curgoal = getccol(FALSE);
  158.  
  159.     /* and move the point down */
  160.         dlp = curwp->w_dotp;
  161.         while (n-- && dlp!=curbp->b_linep)
  162.                 dlp = lforw(dlp);
  163.  
  164.     /* reseting the current position */
  165.         curwp->w_dotp  = dlp;
  166.         curwp->w_doto  = getgoal(dlp);
  167.         curwp->w_flag |= WFMOVE;
  168.         return (TRUE);
  169. }
  170.  
  171. /*
  172.  * This function is like "forwline", but goes backwards. The scheme is exactly
  173.  * the same. Check for arguments that are less than zero and call your
  174.  * alternate. Figure out the new line and call "movedot" to perform the
  175.  * motion. No errors are possible. Bound to "C-P".
  176.  */
  177. backline(f, n)
  178. {
  179.         register LINE   *dlp;
  180.  
  181.         if (n < 0)
  182.                 return (forwline(f, -n));
  183.  
  184.  
  185.     /* flag this command as a line move */
  186.         thisflag |= CFCPCN;
  187.  
  188.     /* if we are on the last line as we start....fail the command */
  189.     if (lback(curwp->w_dotp) == curbp->b_linep)
  190.         return(FALSE);
  191.  
  192.     /* if the last command was not note a line move,
  193.        reset the goal column */
  194.         if ((lastflag&CFCPCN) == 0)
  195.                 curgoal = getccol(FALSE);
  196.  
  197.     /* and move the point up */
  198.         dlp = curwp->w_dotp;
  199.         while (n-- && lback(dlp)!=curbp->b_linep)
  200.                 dlp = lback(dlp);
  201.  
  202.     /* reseting the current position */
  203.         curwp->w_dotp  = dlp;
  204.         curwp->w_doto  = getgoal(dlp);
  205.         curwp->w_flag |= WFMOVE;
  206.         return (TRUE);
  207. }
  208.  
  209. #if    WORDPRO
  210. gobop(f, n)    /* go back to the beginning of the current paragraph
  211.            here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
  212.            combination to delimit the beginning of a paragraph    */
  213.  
  214. int f, n;    /* default Flag & Numeric argument */
  215.  
  216. {
  217.     register int suc;    /* success of last backchar */
  218.  
  219.     if (n < 0)    /* the other way...*/
  220.         return(goeop(f, -n));
  221.  
  222.     while (n-- > 0) {    /* for each one asked for */
  223.  
  224.         /* first scan back until we are in a word */
  225.         suc = backchar(FALSE, 1);
  226.         while (!inword() && suc)
  227.             suc = backchar(FALSE, 1);
  228.         curwp->w_doto = 0;    /* and go to the B-O-Line */
  229.  
  230.         /* and scan back until we hit a <NL><NL> or <NL><TAB>
  231.            or a <NL><SPACE>                    */
  232.         while (lback(curwp->w_dotp) != curbp->b_linep)
  233.             if (llength(curwp->w_dotp) != 0 &&
  234.                 lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
  235.                 lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
  236.                 curwp->w_dotp = lback(curwp->w_dotp);
  237.             else
  238.                 break;
  239.  
  240.         /* and then forward until we are in a word */
  241.         if (lback(curwp->w_dotp) == curbp->b_linep)
  242.             suc = (curwp->w_dotp != curbp->b_linep);
  243.         else
  244.             suc = forwchar(FALSE, 1);
  245.         while (suc && !inword())
  246.             suc = forwchar(FALSE, 1);
  247.     }
  248.     curwp->w_flag |= WFMOVE;    /* force screen update */
  249.     return(TRUE);
  250. }
  251.  
  252. goeop(f, n)    /* go forword to the end of the current paragraph
  253.            here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
  254.            combination to delimit the beginning of a paragraph    */
  255.  
  256. int f, n;    /* default Flag & Numeric argument */
  257.  
  258. {
  259.     register int suc;    /* success of last backchar */
  260.  
  261.     if (n < 0)    /* the other way...*/
  262.         return(gobop(f, -n));
  263.  
  264.     while (n-- > 0) {    /* for each one asked for */
  265.  
  266.         /* first scan forward until we are in a word */
  267.         suc = TRUE; /* forwchar(FALSE, 1); */
  268.         while (!inword() && suc)
  269.             suc = forwchar(FALSE, 1);
  270.         curwp->w_doto = 0;    /* and go to the B-O-Line */
  271.         if (suc)    /* of next line if not at EOF */
  272.             curwp->w_dotp = lforw(curwp->w_dotp);
  273.  
  274.         /* and scan forword until we hit a <NL><NL> or <NL><TAB>
  275.            or a <NL><SPACE>                    */
  276.         while (curwp->w_dotp != curbp->b_linep) {
  277.             if (llength(curwp->w_dotp) != 0 &&
  278.                 lgetc(curwp->w_dotp, curwp->w_doto) != TAB &&
  279.                 lgetc(curwp->w_dotp, curwp->w_doto) != ' ')
  280.                 curwp->w_dotp = lforw(curwp->w_dotp);
  281.             else
  282.                 break;
  283.         }
  284.  
  285.         /* and then backward until we are in a word */
  286.         suc = backchar(FALSE, 1);
  287.         while (suc && !inword()) {
  288.             suc = backchar(FALSE, 1);
  289.         }
  290.         curwp->w_doto = llength(curwp->w_dotp);    /* and to the EOL */
  291.     }
  292.     curwp->w_flag |= WFMOVE;    /* force screen update */
  293.     return(TRUE);
  294. }
  295. #endif
  296.  
  297. /*
  298.  * This routine, given a pointer to a LINE, and the current cursor goal
  299.  * column, return the best choice for the offset. The offset is returned.
  300.  * Used by "C-N" and "C-P".
  301.  */
  302. getgoal(dlp)
  303. register LINE   *dlp;
  304. {
  305.         register int    c;
  306.         register int    col;
  307.         register int    newcol;
  308.         register int    dbo;
  309.  
  310.         col = 0;
  311.         dbo = 0;
  312.         while (dbo != llength(dlp)) {
  313.                 c = lgetc(dlp, dbo);
  314.                 newcol = col;
  315.                 if (c == '\t')
  316.                         newcol += tabsize - (newcol % tabsize) - 1;
  317.                 else if ((c&0x7F) < 0x20 || (c&0x7F) == 0x7F)
  318.                         ++newcol;
  319.                 ++newcol;
  320.                 if (newcol > curgoal)
  321.                         break;
  322.                 col = newcol;
  323.                 ++dbo;
  324.         }
  325.         return (dbo);
  326. }
  327.  
  328. /*
  329.  * Scroll forward by a specified number of lines, or by a full page if no
  330.  * argument. Bound to "C-V". The "2" in the arithmetic on the window size is
  331.  * the overlap; this value is the default overlap value in ITS EMACS. Because
  332.  * this zaps the top line in the display window, we have to do a hard update.
  333.  */
  334. forwpage(f, n)
  335. register int    n;
  336. {
  337.         register LINE   *lp, *dp;
  338.  
  339.         if (f == FALSE) {
  340.                 n = curwp->w_ntrows - 2;        /* Default scroll.      */
  341.                 if (n <= 0)                     /* Forget the overlap   */
  342.                         n = 1;                  /* if tiny window.      */
  343.         } else if (n < 0)
  344.                 return (backpage(f, -n));
  345. #if     CVMVAS
  346.         else                                    /* Convert from pages   */
  347.                 n *= curwp->w_ntrows;           /* to lines.            */
  348. #endif
  349.  
  350.     lp = curwp->w_linep;
  351.         dp = curwp->w_dotp;
  352.         while (n > 0 && dp != curbp->b_linep)
  353.                 {--n; lp = lforw(lp); dp = lforw(dp);}
  354.         curwp->w_linep = lp;
  355.         curwp->w_dotp  = dp;
  356.         curwp->w_doto  = 0;
  357.         curwp->w_flag |= WFHARD;
  358.         return (TRUE);
  359. }
  360.  
  361. /*
  362.  * This command is like "forwpage", but it goes backwards. The "2", like
  363.  * above, is the overlap between the two windows. The value is from the ITS
  364.  * EMACS manual. Bound to "M-V". We do a hard update for exactly the same
  365.  * reason.
  366.  */
  367. backpage(f, n)
  368. register int    n;
  369. {
  370.         register LINE   *lp, *dp;
  371.  
  372.         if (f == FALSE) {
  373.                 n = curwp->w_ntrows - 2;        /* Default scroll.      */
  374.                 if (n <= 0)                     /* Don't blow up if the */
  375.                         n = 1;                  /* window is tiny.      */
  376.         } else if (n < 0)
  377.                 return (forwpage(f, -n));
  378. #if     CVMVAS
  379.         else                                    /* Convert from pages   */
  380.                 n *= curwp->w_ntrows;           /* to lines.            */
  381. #endif
  382.  
  383.     lp = curwp->w_linep;
  384.     dp = curwp->w_dotp;
  385.         while (n > 0 && lback(lp) != curbp->b_linep)
  386.                 {--n; lp = lback(lp); dp = lback(dp);}
  387.         while (n > 0 && lback(dp) != curbp->b_linep)
  388.                 {--n; dp = lback(dp);}
  389.         curwp->w_linep = lp;
  390.         curwp->w_dotp  = dp;
  391.         curwp->w_doto  = 0;
  392.         curwp->w_flag |= WFHARD;
  393.         return (TRUE);
  394. }
  395.  
  396. /*
  397.  * Set the mark in the current window to the value of "." in the window. No
  398.  * errors are possible. Bound to "M-.".
  399.  */
  400. setmark(f, n)
  401. {
  402.         curwp->w_markp = curwp->w_dotp;
  403.         curwp->w_marko = curwp->w_doto;
  404.         mlwrite("[Mark set]");
  405.         return (TRUE);
  406. }
  407.  
  408. /*
  409.  * Clear the mark in the current window. No errors are possible.
  410.  * Bound to ^X <space>
  411.  */
  412. remmark(f, n)
  413. {
  414.     curwp->w_markp = NULL;
  415.     curwp->w_marko = 0;
  416.     mlwrite("[Mark removed]");
  417.     return (TRUE);
  418. }
  419.  
  420. /*
  421.  * Swap the values of "." and "mark" in the current window. This is pretty
  422.  * easy, bacause all of the hard work gets done by the standard routine
  423.  * that moves the mark about. The only possible error is "no mark". Bound to
  424.  * "C-X C-X".
  425.  */
  426. swapmark(f, n)
  427. {
  428.         register LINE   *odotp;
  429.         register int    odoto;
  430.  
  431.         if (curwp->w_markp == NULL) {
  432.                 mlwrite("No mark in this window");
  433.                 return (FALSE);
  434.         }
  435.         odotp = curwp->w_dotp;
  436.         odoto = curwp->w_doto;
  437.         curwp->w_dotp  = curwp->w_markp;
  438.         curwp->w_doto  = curwp->w_marko;
  439.         curwp->w_markp = odotp;
  440.         curwp->w_marko = odoto;
  441.         curwp->w_flag |= WFMOVE;
  442.         return (TRUE);
  443. }
  444.  
  445. #if    DECEDT
  446.  
  447. int advset = TRUE;
  448.  
  449. /* advance command.  sets advance flag true */
  450. advadv(f, n)
  451. {
  452. advset = TRUE;
  453. return(TRUE);
  454. }
  455.  
  456. /* backup command.  sets backup flag false */
  457. advback(f, n)
  458. {
  459. advset = FALSE;
  460. return(TRUE);
  461. }
  462.  
  463. /* bottom command.  goes to top or bottom of buffer */
  464. advbot(f, n)
  465. {
  466. return( (advset == TRUE)? goeob(f, n): gobob(f, n) );
  467. }
  468.  
  469. /* character command.  goes forward or backward a character */
  470. advchar(f, n)
  471. {
  472. return( (advset == TRUE)? forwchar(f, n): backchar(f, n) );
  473. }
  474.  
  475. /* word command.  goes forward or backward a word */
  476. advword(f, n)
  477. {
  478. return( (advset == TRUE)? forwword(f, n): backword(f, n) );
  479. }
  480.  
  481. /* line command.  goes to beginning of next or previous line */
  482. advline(f, n)
  483. {
  484. int stat;
  485. if (advset != TRUE && curwp->w_doto > 0) stat = TRUE;
  486. else stat = ((advset == TRUE)? scdnwind(f, n): scupwind(f, n));
  487. thisflag &= ~CFCPCN;
  488. return( (stat == TRUE)? gobol(f, n): stat);
  489. }
  490.  
  491. /* end of line command.  goes to end of next or previous line */
  492. adveol(f, n)
  493. {
  494. int stat;
  495.  
  496. if (advset == TRUE && curwp->w_doto < llength(curwp->w_dotp)) stat = TRUE;
  497. else stat = ((advset == TRUE)? forwline(f, n): backline(f, n));
  498. thisflag &= ~CFCPCN;
  499. return( (stat == TRUE)? goeol(f, n): stat);
  500. }
  501.  
  502. /* search command.  searches forward or reverse */
  503. advsearch(f, n)
  504. {
  505. return( (advset == TRUE)? forwsearch(f, n): backsearch(f, n) );
  506. }
  507.  
  508. /* hunt command.  hunts forward or reverse */
  509. advhunt(f, n)
  510. {
  511. return( (advset == TRUE)? forwhunt(f, n): backhunt(f, n) );
  512. }
  513.  
  514. /* smooth next page command.  goes forward page */
  515. scnxpage(f, n)
  516. {
  517. #if    1
  518.     int s, adv;
  519.  
  520.     /* EDT-like paging */
  521.     gobol(f, n);
  522.     if (f == FALSE) n = 1;
  523.     n *= (curwp->w_ntrows * 2 + 1) / 3;
  524.     if (isvt100) {
  525.         s = TRUE;
  526.         adv = (n >= 0);
  527.         if (!adv) n = -n;
  528.         while (n-- > 0 && s == TRUE)    {
  529.             s = (adv? scdnwind(TRUE, 1): scupwind(TRUE, 1) );
  530.             if (s == TRUE && n > 0) update(HOOK);
  531.         }
  532.     }
  533.     else
  534.         s = scdnwind(TRUE, n);
  535.     thisflag &= ~CFCPCN;
  536.     return(s);
  537. #else
  538.     /* Emacs-like paging */
  539.     return(forwpage(f, n));
  540. #endif
  541. }
  542.  
  543. /* smooth previous page command.  goes backward page */
  544. scprpage(f, n)
  545. {
  546.     if (f == FALSE) { f = TRUE; n = 1; }
  547.     return( scnxpage(f, -n) );
  548. }
  549.  
  550. /* page command.  goes forward or backward a page */
  551. advpage(f, n)
  552. {
  553.     return( (advset == TRUE)? scnxpage(f, n): scprpage(f, n) );
  554. }
  555.  
  556. /*
  557.  * Special insertion.  The argument is the ascii value of the character
  558.  * to insert into the buffer. All the characters
  559.  * are taken literally, with the exception of the newline, which always has
  560.  * its line splitting meaning.
  561.  */
  562. specins(f, n)
  563. {
  564.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  565.         return(rdonly());    /* we are in read only mode    */
  566.     n = ((f == TRUE)? (n & 0xFF): 0);
  567.     return( (n == '\n')? lnewline(): linsert(1, n) );
  568. }
  569.  
  570. /*
  571.  * Undelete the last deleted character.
  572.  */
  573. yankchar(f, n)
  574. {
  575.     int s;
  576.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  577.         return(rdonly());    /* we are in read only mode    */
  578.     if (ykchar == -1 || n <= 0) s = FALSE;
  579.     else if (ykchar == '\n') {
  580.         s = TRUE;
  581.         while (s == TRUE && n-- > 0) s = lnewline();
  582.     }
  583.     else s = linsert(n, ykchar);
  584.     return(s);
  585. }
  586.  
  587. /*
  588.  * Octal insertion.
  589.  * Quote next character and insert in C backslash octal format.
  590.  * Unbound
  591.  */
  592. octalins(f, n)
  593. {
  594.     register int    s;
  595.     register int    c;
  596.     int i, len;
  597.     char oct[10];
  598.  
  599.     if (curbp->b_mode&MDVIEW)    /* don't allow this command if    */
  600.         return(rdonly());    /* we are in read only mode    */
  601.     mlwrite(": character to insert ");
  602.         c = tgetc() & 0xFF;
  603.     len = 0;
  604.     while (c > 0)    {
  605.         oct[len++] = '0' + c % 8;
  606.         c /= 8;
  607.         }
  608.     while (len < 3) oct[len++] = '0';
  609.  
  610.     s = TRUE;
  611.     while (n-- > 0 && s == TRUE)    {
  612.         linsert(1, '\\');
  613.         i = len;
  614.         while(i > 0) s = linsert(1, oct[--i]);
  615.         }
  616.  
  617.     return(s);
  618. }
  619.  
  620. /* null commnad.  does nothing */
  621. nullcmd(f, n)
  622. {
  623. return(TRUE);
  624. }
  625. #endif
  626.