home *** CD-ROM | disk | FTP | other *** search
/ Fresh Fish 5 / FreshFish_July-August1994.bin / bbs / util / mg-3b.lha / mg-3b / src.LZH / mg / random.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-05-23  |  11.3 KB  |  466 lines

  1. /*
  2.  * Assorted commands. The file contains the command processors for a large
  3.  * assortment of unrelated commands. The only thing they have in common is
  4.  * that they are all command processors.
  5.  */
  6. #include    "notab.h"
  7.  
  8. #include    "def.h"
  9. #include    "line.h"
  10. #include    "buffer.h"
  11. #include    "window.h"
  12.  
  13. static int isblank 
  14. PROTO((register struct line *));
  15.  
  16. #ifdef    ANSI
  17. #include <string.h>
  18. #endif
  19.  
  20. /*
  21.  * Display a bunch of useful information about the current location of dot.
  22.  * The character under the cursor (in octal), the current line, row, and
  23.  * column, and approximate position of the cursor in the file (as a
  24.  * percentage) is displayed. The column position assumes an infinite position
  25.  * display; it does not truncate just because the screen does. This is
  26.  * normally bound to "C-X =".
  27.  */
  28. /* ARGSUSED */
  29. showcpos(f, n)
  30. {
  31.     register struct line *clp;
  32.     register long   nchar;
  33.     long            cchar;
  34.     register int    nline, row;
  35.     int             cline, cbyte;    /* Current line/char/byte */
  36.     int             ratio;
  37.  
  38.     clp = lforw(curbp->b_linep);    /* Collect the data.     */
  39.     nchar = 0;
  40.     cline = nline = 0;
  41.     for (;;) {
  42.         ++nline;    /* Count this line     */
  43.         if (clp == curwp->w_dotp) {
  44.             cline = nline;    /* Mark line         */
  45.             cchar = nchar + curwp->w_doto;
  46.             if (curwp->w_doto == llength(clp))
  47.                 cbyte = '\n';
  48.             else
  49.                 cbyte = lgetc(clp, curwp->w_doto);
  50.         }
  51.         nchar += llength(clp);    /* Now count the chars     */
  52.         clp = lforw(clp);
  53.         if (clp == curbp->b_linep) {
  54.             if (cline == 0)
  55.                 cline = nline + 1;
  56.             break;
  57.         }
  58.         nchar++;    /* count the newline     */
  59.     }
  60.     row = curwp->w_toprow + 1;    /* Determine row.     */
  61.     clp = curwp->w_linep;
  62.     while (clp != curbp->b_linep && clp != curwp->w_dotp) {
  63.         ++row;
  64.         clp = lforw(clp);
  65.     }
  66.     /* NOSTRICT */
  67.     ratio = nchar ? (100L * cchar) / nchar : 100;
  68.     ewprintf("Char: %c (0%o)  point=%ld(%d%%)  line=%d  row=%d  col=%d",
  69.          cbyte, cbyte, cchar, ratio, cline, row, getcolpos());
  70.     return TRUE;
  71. }
  72.  
  73. getcolpos()
  74. {
  75.     register int    col, i, c;
  76.  
  77.     col = 1;        /* Determine column.     */
  78.     for (i = 0; i < curwp->w_doto; ++i) {
  79.         c = lgetc(curwp->w_dotp, i);
  80.         if (c == '\t'
  81. #ifdef    NOTAB
  82.             && !(curbp->b_flag & BFNOTAB)
  83. #endif
  84.             ) {
  85.             col |= 0x07;
  86.             ++col;
  87.         } else if (ISCTRL(c) != FALSE)
  88.             ++col;
  89.         ++col;
  90.     }
  91.     return col;
  92. }
  93. /*
  94.  * Twiddle the two characters on either side of dot. If dot is at the end of
  95.  * the line twiddle the two characters before it. Return with an error if dot
  96.  * is at the beginning of line; it seems to be a bit pointless to make this
  97.  * work. This fixes up a very common typo with a single stroke. Normally
  98.  * bound to "C-T". This always works within a line, so "WFEDIT" is good
  99.  * enough.
  100.  */
  101. /* ARGSUSED */
  102. twiddle(f, n)
  103. {
  104.     register struct line *dotp;
  105.     register int    doto;
  106.     register int    cr;
  107.     VOID            lchange();
  108.  
  109.     dotp = curwp->w_dotp;
  110.     doto = curwp->w_doto;
  111.     if (doto == llength(dotp)) {
  112.         if (--doto <= 0)
  113.             return FALSE;
  114.     } else {
  115.         if (doto == 0)
  116.             return FALSE;
  117.         ++curwp->w_doto;
  118.     }
  119.     cr = lgetc(dotp, doto--);
  120.     lputc(dotp, doto + 1, lgetc(dotp, doto));
  121.     lputc(dotp, doto, cr);
  122.     lchange(WFEDIT);
  123.     return TRUE;
  124. }
  125.  
  126. /*
  127.  * Open up some blank space. The basic plan is to insert a bunch of newlines,
  128.  * and then back up over them. Everything is done by the subcommand
  129.  * procerssors. They even handle the looping. Normally this is bound to
  130.  * "C-O".
  131.  */
  132. /* ARGSUSED */
  133. openline(f, n)
  134. {
  135.     register int    i;
  136.     register int    s;
  137.  
  138.     if (n < 0)
  139.         return FALSE;
  140.     if (n == 0)
  141.         return TRUE;
  142.     i = n;            /* Insert newlines.     */
  143.     do {
  144.         s = lnewline();
  145.     } while (s == TRUE && --i);
  146.     if (s == TRUE)        /* Then back up overtop */
  147.         s = backchar(f | FFRAND, n);    /* of them all.         */
  148.     return s;
  149. }
  150.  
  151. /*
  152.  * Insert a newline.
  153.  */
  154. /* ARGSUSED */
  155. newline(f, n)
  156. {
  157.     register int    s;
  158.  
  159.     if (n < 0)
  160.         return FALSE;
  161.     while (n--)
  162.         if ((s = lnewline()) != TRUE)
  163.             return s;
  164.     return TRUE;
  165. }
  166.  
  167. /*
  168.  * Delete blank lines around dot. What this command does depends if dot is
  169.  * sitting on a blank line. If dot is sitting on a blank line, this command
  170.  * deletes all the blank lines above and below the current line. If it is
  171.  * sitting on a non blank line then it deletes all of the blank lines after
  172.  * the line. Normally this command is bound to "C-X C-O". Any argument is
  173.  * ignored.
  174.  * 
  175.  * Hacked by phr Thu Dec 22 09:03:19 1988 to leave a blank line if executed in
  176.  * part of a sequence of blank lines (despite previous comment, it used to
  177.  * delete them all).
  178.  */
  179. /* ARGSUSED */
  180. deblank(f, n)
  181. {
  182.     register struct line *lp1;
  183.     register struct line *lp2;
  184.     register RSIZE  nld;
  185.     int             nonblank, tof;
  186.  
  187.     lp1 = curwp->w_dotp;
  188.     nonblank = !isblank(lp1);
  189.     while (isblank(lp1) && (lp2 = lback(lp1)) != curbp->b_linep)
  190.         lp1 = lp2;
  191.     tof = (lp2 == curbp->b_linep);
  192.     lp2 = lp1;
  193.     nld = (RSIZE) 0;
  194.     while ((lp2 = lforw(lp2)) != curbp->b_linep && isblank(lp2))
  195.         ++nld;
  196.     if (nld == 0)
  197.         return (TRUE);
  198.     if (!nonblank && !tof && nld > 1)
  199.         nld -= 1;
  200.     curwp->w_dotp = lforw(lp1);
  201.     curwp->w_doto = 0;
  202.     return fdelete((RSIZE) nld, FALSE);
  203. }
  204. /*
  205.  * isblank - just decide if it's a blank line.
  206.  */
  207. static int
  208. isblank(lp)
  209.     register struct line *lp;
  210. {
  211.     register char  *s;
  212.     register int    i;
  213.  
  214.     for (s = ltext(lp), i = 0; i < llength(lp); i += 1)
  215.         if (s[i] != ' ' || s[i] != '\t')
  216.             return FALSE;
  217.     return TRUE;
  218. }
  219.  
  220. /*
  221.  * Delete any whitespace around dot, then insert a space.
  222.  */
  223. justone(f, n)
  224. {
  225.     (VOID) delwhite(f, n);
  226.     return linsert(1, ' ');
  227. }
  228. /*
  229.  * Delete any whitespace around dot.
  230.  */
  231. /* ARGSUSED */
  232. delwhite(f, n)
  233. {
  234.     register int    col, c, s;
  235.  
  236.     col = curwp->w_doto;
  237.     while (((c = lgetc(curwp->w_dotp, col)) == ' ' || c == '\t')
  238.            && col < llength(curwp->w_dotp))
  239.         ++col;
  240.     do {
  241.         if (curwp->w_doto == 0) {
  242.             s = FALSE;
  243.             break;
  244.         }
  245.         if ((s = backchar(FFRAND, 1)) != TRUE)
  246.             break;
  247.     } while ((c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' ' || c == '\t');
  248.  
  249.     if (s == TRUE)
  250.         (VOID) forwchar(FFRAND, 1);
  251.     (VOID) fdelete((RSIZE) (col - curwp->w_doto), FALSE);
  252.     return TRUE;
  253. }
  254. /*
  255.  * Insert a newline, then enough tabs and spaces to duplicate the indentation
  256.  * of the previous line. Assumes tabs are every eight characters. Quite
  257.  * simple. Figure out the indentation of the current line. Insert a newline
  258.  * by calling the standard routine. Insert the indentation by inserting the
  259.  * right number of tabs and spaces. Return TRUE if all ok. Return FALSE if
  260.  * one of the subcomands failed. Normally bound to "C-J".
  261.  */
  262. /* ARGSUSED */
  263. indent(f, n)
  264. {
  265.     register int    nicol;
  266.     register int    c;
  267.     register int    i;
  268.  
  269.     if (n < 0)
  270.         return (FALSE);
  271.     while (n--) {
  272.         nicol = 0;
  273.         for (i = 0; i < llength(curwp->w_dotp); ++i) {
  274.             c = lgetc(curwp->w_dotp, i);
  275.             if (c != ' ' && c != '\t')
  276.                 break;
  277.             if (c == '\t')
  278.                 nicol |= 0x07;
  279.             ++nicol;
  280.         }
  281.         if (lnewline() == FALSE || ((
  282. #ifdef    NOTAB
  283.                          curbp->b_flag & BFNOTAB) ?
  284.                         linsert(nicol, ' ') == FALSE : (
  285. #endif
  286.               ((i = nicol / 8) != 0 && linsert(i, '\t') == FALSE) ||
  287.                ((i = nicol % 8) != 0 && linsert(i, ' ') == FALSE))))
  288.             return FALSE;
  289.     }
  290.     return TRUE;
  291. }
  292.  
  293. /*
  294.  * Delete forward. This is real easy, because the basic delete routine does
  295.  * all of the work. Watches for negative arguments, and does the right thing.
  296.  * If any argument is present, it kills rather than deletes, to prevent loss
  297.  * of text if typed with a big argument. Normally bound to "C-D".
  298.  */
  299. /* ARGSUSED */
  300. forwdel(f, n)
  301. {
  302.     if (n < 0)
  303.         return backdel(f | FFRAND, -n);
  304.     if (f & FFARG) {    /* Really a kill.     */
  305.         if ((lastflag & CFKILL) == 0)
  306.             kdelete();
  307.         thisflag |= CFKILL;
  308.     }
  309.     return fdelete((RSIZE) n, f & FFARG);
  310. }
  311.  
  312. /*
  313.  * Delete backwards. This is no harder than the above, because we get to use
  314.  * the same code. Like delete forward, this actually does a kill if presented
  315.  * with an argument.
  316.  */
  317. /* ARGSUSED */
  318. backdel(f, n)
  319. {
  320.  
  321.     if (n < 0)
  322.         return forwdel(f | FFRAND, -n);
  323.     if (f & FFARG) {    /* Really a kill.     */
  324.         if ((lastflag & CFKILL) == 0)
  325.             kdelete();
  326.         thisflag |= CFKILL;
  327.     }
  328.     return bdelete((RSIZE) n, f & FFARG);
  329. }
  330.  
  331. /*
  332.  * Kill line. If called without an argument, it kills from dot to the end of
  333.  * the line, unless it is at the end of the line, when it kills the newline.
  334.  * If called with an argument of 0, it kills from the start of the line to
  335.  * dot. If called with a positive argument, it kills from dot forward over
  336.  * that number of newlines. If called with a negative argument it kills any
  337.  * text before dot on the current line, then it kills back abs(arg) lines.
  338.  */
  339. /* ARGSUSED */
  340. killline(f, n)
  341. {
  342.     register RSIZE  chunk;
  343.     register struct line *nextp;
  344.     register int    i, c;
  345.  
  346.     if ((lastflag & CFKILL) == 0)    /* Clear kill buffer if */
  347.         kdelete();    /* last wasn't a kill.     */
  348.     thisflag |= CFKILL;
  349.     if (!(f & FFARG)) {
  350.         for (i = curwp->w_doto; i < llength(curwp->w_dotp); ++i)
  351.             if ((c = lgetc(curwp->w_dotp, i)) != ' ' && c != '\t')
  352.                 break;
  353.         if (i == llength(curwp->w_dotp)) {
  354.             chunk = llength(curwp->w_dotp) - curwp->w_doto;
  355.             if (lforw(curwp->w_dotp) != curbp->b_linep || !chunk)
  356.                 chunk += 1;
  357.         } else {
  358.             chunk = llength(curwp->w_dotp) - curwp->w_doto;
  359.             if (chunk == 0)
  360.                 chunk = 1;
  361.         }
  362.         i = fdelete(chunk, TRUE);
  363.     } else if (n > 0) {
  364.         chunk = llength(curwp->w_dotp) - curwp->w_doto + 1;
  365.         nextp = lforw(curwp->w_dotp);
  366.         i = n;
  367.         while (--i) {
  368.             if (nextp == curbp->b_linep)
  369.                 break;
  370.             chunk += llength(nextp) + 1;
  371.             nextp = lforw(nextp);
  372.         }
  373.         i = fdelete(chunk, TRUE);
  374.     } else {        /* n <= 0         */
  375.         chunk = curwp->w_doto;
  376.         nextp = lback(curwp->w_dotp);
  377.         i = n;
  378.         while (i++) {
  379.             if (nextp == curbp->b_linep)
  380.                 break;
  381.             chunk += llength(nextp) + 1;
  382.             nextp = lback(nextp);
  383.         }
  384.         i = bdelete(chunk, TRUE);
  385.     }
  386.     return i;
  387. }
  388.  
  389. /*
  390.  * Yank text back from the kill buffer. This is really easy. All of the work
  391.  * is done by the standard insert routines. All you do is run the loop, and
  392.  * check for errors. The blank lines are inserted with a call to "newline"
  393.  * instead of a call to "lnewline" so that the magic stuff that happens when
  394.  * you type a carriage return also happens when a carriage return is yanked
  395.  * back from the kill buffer. An attempt has been made to fix the cosmetic
  396.  * bug associated with a yank when dot is on the top line of the window
  397.  * (nothing moves, because all of the new text landed off screen).
  398.  */
  399. /* ARGSUSED */
  400. yank(f, n)
  401. {
  402.     register int    c;
  403.     register int    linsiz;
  404.     char            lin[NLINE];
  405.     RSIZE           i;
  406.  
  407.     register struct line *lp;
  408.     register int    nline;
  409.     VOID            isetmark();
  410.  
  411.     if (n < 0)
  412.         return FALSE;
  413.     nline = 0;        /* Newline counting.     */
  414.     while (n--) {
  415.         isetmark();    /* mark around last yank */
  416.         i = 0;
  417.         while (((c = kremove(i)) >= 0) && (c != '\n'))
  418.             if (linsert(1, c) == FALSE)
  419.                 return (FALSE);
  420.             else
  421.                 i++;
  422.         if (kremove(i++) == '\n') {
  423.             while ((linsiz = klremove(lin, &i)) >= 0) {
  424.                 if (newline(FFRAND, 1) == FALSE)
  425.                     return (FALSE);
  426.                 if (linsert(linsiz, 0) == FALSE)
  427.                     return (FALSE);
  428.                 lp = curwp->w_dotp;
  429.                 bcopy(lin, &lp->l_text[0], linsiz);
  430.                 i++;
  431.                 nline++;
  432.             }
  433.             if (newline(FFRAND, 1) == FALSE)
  434.                 return (FALSE);
  435.             nline++;
  436.         }
  437.         while (((c = kremove(i)) >= 0))
  438.             if (linsert(1, c) == FALSE)
  439.                 return (FALSE);
  440.             else
  441.                 i++;
  442.     }
  443.  
  444.     lp = curwp->w_linep;    /* Cosmetic adjustment     */
  445.     if (curwp->w_dotp == lp) {    /* if offscreen insert. */
  446.         while (nline-- && lback(lp) != curbp->b_linep)
  447.             lp = lback(lp);
  448.         curwp->w_linep = lp;    /* Adjust framing.     */
  449.         curwp->w_flag |= WFHARD;
  450.     }
  451.     return TRUE;
  452. }
  453.  
  454. #ifdef    NOTAB
  455. /* ARGSUSED */
  456. space_to_tabstop(f, n)
  457.     int             f, n;
  458. {
  459.     if (n < 0)
  460.         return FALSE;
  461.     if (n == 0)
  462.         return TRUE;
  463.     return linsert((n << 3) - (curwp->w_doto & 7), ' ');
  464. }
  465. #endif
  466.