home *** CD-ROM | disk | FTP | other *** search
/ The Fred Fish Collection 1.5 / ffcollection-1-5-1992-11.iso / ff_disks / 100-199 / ff147.lzh / src / basic.c next >
C/C++ Source or Header  |  1988-08-15  |  9KB  |  445 lines

  1. /*
  2.  *        Basic cursor motion commands.
  3.  *
  4.  * The routines in this file are the basic
  5.  * command functions for moving the cursor around on
  6.  * the screen, setting mark, and swapping dot with
  7.  * mark. Only moves between lines, which might make the
  8.  * current buffer framing bad, are hard.
  9.  */
  10. #include    "def.h"
  11.  
  12. VOID    setgoal();
  13.  
  14. /*
  15.  * Go to beginning of line.
  16.  */
  17. /*ARGSUSED*/
  18. gotobol(f, n)
  19. {
  20.     curwp->w_doto  = 0;
  21.     return (TRUE);
  22. }
  23.  
  24. /*
  25.  * Move cursor backwards. Do the
  26.  * right thing if the count is less than
  27.  * 0. Error if you try to move back from
  28.  * the beginning of the buffer.
  29.  */
  30. /*ARGSUSED*/
  31. backchar(f, n)
  32. register int n;
  33. {
  34.     register LINE    *lp;
  35.  
  36.     if (n < 0) return forwchar(f, -n);
  37.     while (n--) {
  38.         if (curwp->w_doto == 0) {
  39.             if ((lp=lback(curwp->w_dotp)) == curbp->b_linep) {
  40.                 if (!(f & FFRAND))
  41.                     ewprintf("Beginning of buffer");
  42.                 return (FALSE);
  43.             }
  44.             curwp->w_dotp  = lp;
  45.             curwp->w_doto  = llength(lp);
  46.             curwp->w_flag |= WFMOVE;
  47.         } else
  48.             curwp->w_doto--;
  49.     }
  50.     return TRUE;
  51. }
  52.  
  53. /*
  54.  * Go to end of line.
  55.  */
  56. /*ARGSUSED*/
  57. gotoeol(f, n)
  58. {
  59.     curwp->w_doto  = llength(curwp->w_dotp);
  60.     return (TRUE);
  61. }
  62.  
  63. /*
  64.  * Move cursor forwards. Do the
  65.  * right thing if the count is less than
  66.  * 0. Error if you try to move forward
  67.  * from the end of the buffer.
  68.  */
  69. /*ARGSUSED*/
  70. forwchar(f, n)
  71. register int n;
  72. {
  73.     if (n < 0) return backchar(f, -n);
  74.     while (n--) {
  75.         if (curwp->w_doto == llength(curwp->w_dotp)) {
  76.             curwp->w_dotp  = lforw(curwp->w_dotp);
  77.             if (curwp->w_dotp == curbp->b_linep) {
  78.                 curwp->w_dotp = lback(curwp->w_dotp);
  79.                 if (!(f & FFRAND))
  80.                     ewprintf("End of buffer");
  81.                 return FALSE;
  82.             }
  83.             curwp->w_doto  = 0;
  84.             curwp->w_flag |= WFMOVE;
  85.         } else
  86.             curwp->w_doto++;
  87.     }
  88.     return TRUE;
  89. }
  90.  
  91. /*
  92.  * Go to the beginning of the
  93.  * buffer. Setting WFHARD is conservative,
  94.  * but almost always the case.
  95.  */
  96. gotobob(f, n)
  97. {
  98.     (VOID) setmark(f, n) ;
  99.     curwp->w_dotp  = lforw(curbp->b_linep);
  100.     curwp->w_doto  = 0;
  101.     curwp->w_flag |= WFHARD;
  102.     return TRUE;
  103. }
  104.  
  105. /*
  106.  * Go to the end of the buffer.
  107.  * Setting WFHARD is conservative, but
  108.  * almost always the case.
  109.  */
  110. gotoeob(f, n)
  111. {
  112.     (VOID) setmark(f, n) ;
  113.     curwp->w_dotp  = lback(curbp->b_linep);
  114.     curwp->w_doto  = llength(curwp->w_dotp);
  115.     curwp->w_flag |= WFHARD;
  116.     return TRUE;
  117. }
  118.  
  119. /*
  120.  * Move forward by full lines.
  121.  * If the number of lines to move is less
  122.  * than zero, call the backward line function to
  123.  * actually do it. The last command controls how
  124.  * the goal column is set.
  125.  */
  126. /*ARGSUSED*/
  127. forwline(f, n)
  128. {
  129.     register LINE    *dlp;
  130.  
  131.     if (n < 0)
  132.         return backline(f|FFRAND, -n);
  133.     if ((lastflag&CFCPCN) == 0)        /* Fix goal.        */
  134.         setgoal();
  135.     thisflag |= CFCPCN;
  136.     if (n == 0) return TRUE;
  137.     dlp = curwp->w_dotp;
  138.     while (dlp!=curbp->b_linep && n--)
  139.         dlp = lforw(dlp);
  140.     curwp->w_flag |= WFMOVE;
  141.     if(dlp==curbp->b_linep) {    /* ^N at end of buffer creates lines (like gnu) */
  142.         if(!(curbp->b_flag&BFCHG)) {    /* first change */
  143.             curbp->b_flag |= BFCHG;
  144.             curwp->w_flag |= WFMODE;
  145.         }
  146.         curwp->w_doto = 0;
  147.         while(n-- >= 0) {
  148.             if((dlp = lallocx(0)) == NULL) return FALSE;
  149.             dlp->l_fp = curbp->b_linep;
  150.             dlp->l_bp = lback(dlp->l_fp);
  151.             dlp->l_bp->l_fp = dlp->l_fp->l_bp = dlp;
  152.         }
  153.         curwp->w_dotp = lback(curbp->b_linep);
  154.     } else {
  155.         curwp->w_dotp  = dlp;
  156.         curwp->w_doto  = getgoal(dlp);
  157.     }
  158.     return TRUE;
  159. }
  160.  
  161. /*
  162.  * This function is like "forwline", but
  163.  * goes backwards. The scheme is exactly the same.
  164.  * Check for arguments that are less than zero and
  165.  * call your alternate. Figure out the new line and
  166.  * call "movedot" to perform the motion.
  167.  */
  168. /*ARGSUSED*/
  169. backline(f, n)
  170. {
  171.     register LINE    *dlp;
  172.  
  173.     if (n < 0) return forwline(f|FFRAND, -n);
  174.     if ((lastflag&CFCPCN) == 0)        /* Fix goal.        */
  175.         setgoal();
  176.     thisflag |= CFCPCN;
  177.     dlp = curwp->w_dotp;
  178.     while (n-- && lback(dlp)!=curbp->b_linep)
  179.         dlp = lback(dlp);
  180.     curwp->w_dotp  = dlp;
  181.     curwp->w_doto  = getgoal(dlp);
  182.     curwp->w_flag |= WFMOVE;
  183.     return TRUE;
  184. }
  185.  
  186. /*
  187.  * Set the current goal column,
  188.  * which is saved in the external variable "curgoal",
  189.  * to the current cursor column. The column is never off
  190.  * the edge of the screen; it's more like display then
  191.  * show position.
  192.  */
  193. VOID
  194. setgoal() {
  195.  
  196.     curgoal = getcolpos() - 1;        /* Get the position.    */
  197. /* we can now display past end of display, don't chop! */
  198. }
  199.  
  200. /*
  201.  * This routine looks at a line (pointed
  202.  * to by the LINE pointer "dlp") and the current
  203.  * vertical motion goal column (set by the "setgoal"
  204.  * routine above) and returns the best offset to use
  205.  * when a vertical motion is made into the line.
  206.  */
  207. getgoal(dlp) register LINE *dlp; {
  208.     register int    c;
  209.     register int    col;
  210.     register int    newcol;
  211.     register int    dbo;
  212.  
  213.     col = 0;
  214.     dbo = 0;
  215.     while (dbo != llength(dlp)) {
  216.         c = lgetc(dlp, dbo);
  217.         newcol = col;
  218.         if (c == '\t'
  219. #ifdef    NOTAB
  220.                 && !(curbp->b_flag & BFNOTAB)
  221. #endif
  222.             )
  223.             newcol |= 0x07;
  224.         else if (ISCTRL(c) != FALSE)
  225.             ++newcol;
  226.         ++newcol;
  227.         if (newcol > curgoal)
  228.             break;
  229.         col = newcol;
  230.         ++dbo;
  231.     }
  232.     return (dbo);
  233. }
  234.  
  235. /*
  236.  * Scroll forward by a specified number
  237.  * of lines, or by a full page if no argument.
  238.  * The "2" is the window overlap (this is the default
  239.  * value from ITS EMACS). Because the top line in
  240.  * the window is zapped, we have to do a hard
  241.  * update and get it back.
  242.  */
  243. /*ARGSUSED*/
  244. forwpage(f, n)
  245. register int n;
  246. {
  247.     register LINE    *lp;
  248.  
  249.     if (!(f & FFARG)) {
  250.         n = curwp->w_ntrows - 2;    /* Default scroll.    */
  251.         if (n <= 0)            /* Forget the overlap    */
  252.             n = 1;            /* if tiny window.    */
  253.     } else if (n < 0)
  254.         return backpage(f|FFRAND, -n);
  255. #ifdef    CVMVAS
  256.     else                    /* Convert from pages    */
  257.         n *= curwp->w_ntrows;        /* to lines.        */
  258. #endif
  259.     lp = curwp->w_linep;
  260.     while (n-- && lforw(lp)!=curbp->b_linep)
  261.         lp = lforw(lp);
  262.     curwp->w_linep = lp;
  263.     curwp->w_flag |= WFHARD;
  264.     /* if in current window, don't move dot */
  265.     for(n = curwp->w_ntrows; n-- && lp!=curbp->b_linep; lp = lforw(lp))
  266.         if(lp==curwp->w_dotp) return TRUE;
  267.     curwp->w_dotp  = curwp->w_linep;
  268.     curwp->w_doto  = 0;
  269.     return TRUE;
  270. }
  271.  
  272. /*
  273.  * This command is like "forwpage",
  274.  * but it goes backwards. The "2", like above,
  275.  * is the overlap between the two windows. The
  276.  * value is from the ITS EMACS manual. The
  277.  * hard update is done because the top line in
  278.  * the window is zapped.
  279.  */
  280. /*ARGSUSED*/
  281. backpage(f, n)
  282. register int n;
  283. {
  284.     register LINE    *lp;
  285.  
  286.     if (!(f & FFARG)) {
  287.         n = curwp->w_ntrows - 2;    /* Default scroll.    */
  288.         if (n <= 0)            /* Don't blow up if the */
  289.             n = 1;            /* window is tiny.    */
  290.     } else if (n < 0)
  291.         return forwpage(f|FFRAND, -n);
  292. #ifdef    CVMVAS
  293.     else                    /* Convert from pages    */
  294.         n *= curwp->w_ntrows;        /* to lines.        */
  295. #endif
  296.     lp = curwp->w_linep;
  297.     while (n-- && lback(lp)!=curbp->b_linep)
  298.         lp = lback(lp);
  299.     curwp->w_linep = lp;
  300.     curwp->w_flag |= WFHARD;
  301.     /* if in current window, don't move dot */
  302.     for(n = curwp->w_ntrows; n-- && lp!=curbp->b_linep; lp = lforw(lp))
  303.         if(lp==curwp->w_dotp) return TRUE;
  304.     curwp->w_dotp = curwp->w_linep;
  305.     curwp->w_doto = 0;
  306.     return TRUE;
  307. }
  308.  
  309. /* These functions are provided for compatibility with Gosling's Emacs.
  310.  *    They are used to scroll the display up (or down) one line at a time.
  311.  */
  312.  
  313. #ifdef GOSMACS
  314. forw1page(f, n)
  315. int f, n;
  316. {
  317.     if (!(f & FFARG))  {
  318.             n = 1;
  319.         f = FFUNIV;
  320.     }
  321.     forwpage(f|FFRAND, n);
  322. }
  323.  
  324. back1page(f, n)
  325. int f, n;
  326. {
  327.     if (!(f & FFARG)) {
  328.             n = 1;
  329.         f = FFUNIV;
  330.     }
  331.     backpage(f|FFRAND, n);
  332. }
  333. #endif
  334.  
  335. /*
  336.  * Page the other window. Check to make sure it exists, then
  337.  * nextwind, forwpage and restore window pointers.
  338.  */
  339. pagenext(f, n)
  340. {
  341.     register WINDOW *wp;
  342.  
  343.     if (wheadp->w_wndp == NULL) {
  344.         ewprintf("No other window");
  345.         return FALSE;
  346.     }
  347.     wp = curwp;
  348.     (VOID) nextwind(f, n);
  349.     (VOID) forwpage(f, n);
  350.     curwp = wp;
  351.     curbp = wp->w_bufp;
  352.     return TRUE;
  353. }
  354.  
  355. /*
  356.  * Internal set mark routine, used by other functions (daveb).
  357.  */
  358. VOID
  359. isetmark()
  360. {
  361.     curwp->w_markp = curwp->w_dotp;
  362.     curwp->w_marko = curwp->w_doto;
  363. }
  364.  
  365. /*
  366.  * Set the mark in the current window
  367.  * to the value of dot. A message is written to
  368.  * the echo line.  (ewprintf knows about macros)
  369.  */
  370. /*ARGSUSED*/
  371. setmark(f, n)
  372. {
  373.     isetmark();
  374.     ewprintf("Mark set");
  375.     return TRUE;
  376. }
  377.  
  378. /*
  379.  * Swap the values of "dot" and "mark" in
  380.  * the current window. This is pretty easy, because
  381.  * all of the hard work gets done by the standard routine
  382.  * that moves the mark about. The only possible
  383.  * error is "no mark".
  384.  */
  385. /*ARGSUSED*/
  386. swapmark(f, n)
  387. {
  388.     register LINE    *odotp;
  389.     register int    odoto;
  390.  
  391.     if (curwp->w_markp == NULL) {
  392.         ewprintf("No mark in this window");
  393.         return FALSE;
  394.     }
  395.     odotp = curwp->w_dotp;
  396.     odoto = curwp->w_doto;
  397.     curwp->w_dotp  = curwp->w_markp;
  398.     curwp->w_doto  = curwp->w_marko;
  399.     curwp->w_markp = odotp;
  400.     curwp->w_marko = odoto;
  401.     curwp->w_flag |= WFMOVE;
  402.     return TRUE;
  403. }
  404.  
  405. /*
  406.  * Go to a specific line, mostly for
  407.  * looking up errors in C programs, which give the
  408.  * error a line number. If an argument is present, then
  409.  * it is the line number, else prompt for a line number
  410.  * to use.
  411.  */
  412. /*ARGSUSED*/
  413. gotoline(f, n)
  414. register int n;
  415. {
  416.     register LINE    *clp;
  417.     register int    s;
  418.     char        buf[32];
  419.  
  420.     if (!(f & FFARG)) {
  421.         if ((s=ereply("Goto line: ", buf, sizeof(buf))) != TRUE)
  422.             return s;
  423.         n = atoi(buf);
  424.     }
  425.  
  426.     if (n > 0) {
  427.         clp = lforw(curbp->b_linep);    /* "clp" is first line    */
  428.         while (--n > 0) {
  429.             if (lforw(clp) == curbp->b_linep) break;
  430.             clp = lforw(clp);
  431.         }
  432.     } else {
  433.         clp = lback(curbp->b_linep);    /* clp is last line */
  434.         while (n < 0) {
  435.             if (lback(clp) == curbp->b_linep) break;
  436.             clp = lback(clp);
  437.             n++;
  438.         }
  439.     }
  440.     curwp->w_dotp = clp;
  441.     curwp->w_doto = 0;
  442.     curwp->w_flag |= WFMOVE;
  443.     return TRUE;
  444. }
  445.