home *** CD-ROM | disk | FTP | other *** search
/ Frozen Fish 1: Amiga / FrozenFish-Apr94.iso / bbs / alib / d3xx / d352 / mg.lha / MG / src.LZH / mg / basic.c < prev    next >
C/C++ Source or Header  |  1990-05-23  |  10KB  |  456 lines

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