home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / telecomm / uemlsrc / random.c < prev    next >
C/C++ Source or Header  |  1987-08-24  |  17KB  |  562 lines

  1. /*
  2.  * This file contains the
  3.  * command processing functions for
  4.  * a number of random commands. There is
  5.  * no functional grouping here, for
  6.  * sure.
  7.  */
  8. #include        <stdio.h>
  9. #include        "ed.h"
  10.  
  11. int     tabsize;                        /* Tab size (0: use real tabs)  */
  12. char    fillprefix[80];                 /* rather large but who knows   */
  13. int     yankcflag = FALSE;
  14.  
  15. /*
  16.  * Set fill column to n.  The fill column is global, but the individual
  17.  * buffer can be filled or not depending on its mode.
  18.  */
  19. setfillcol(f, n)
  20. register int f, n;
  21. {
  22.         register WINDOW *wp;
  23.         register BUFFER *bp;
  24.  
  25.         fillcol = (n == 1) ? (getccol(FALSE) + 1) : n;
  26.         n = fillcol;
  27.         wp =  wheadp;
  28.         bp =  curwp->w_bufp;
  29.         if (n > 1)
  30.                 {
  31.                 bp->b_bmode |= BMWRAP;
  32.                 bp->b_bmode &= ~BMNWRAP;
  33.                 }
  34.         else
  35.                 {
  36.                 bp->b_bmode |= BMNWRAP;
  37.                 bp->b_bmode &= ~BMWRAP;
  38.                 }
  39.         upmode();
  40.         mlwrite("Fill column is %d", n);
  41.         return(TRUE);
  42. }
  43.  
  44. /*
  45.  * Set indent column to n or set fill prefix to string.
  46.  */
  47. setindcol(f, n)
  48. register int f, n;
  49. {
  50.         short curdo;    /* current dot offset */
  51.         register short tdo;     /* moveable dot offset */
  52.         register short i;
  53.         char tstring[80];       /* temporary store for prefix string */
  54.         i = 0;
  55.         tdo = 0;
  56.         curdo = curwp->w_doto;
  57.  
  58.         if (n>1)        /* called with argument, so just set the indcol */
  59.                 {
  60.                 if (n >= 80)
  61.                         n=79;
  62.                 indcol = n;
  63.                 /* copy the correct number of tabs and spaces into string */
  64.                 if ((tdo=indcol/8)!=0)
  65.                         while (tdo--)
  66.                                 tstring[i++] = '\t';
  67.                 if ((tdo=indcol%8)!=0)
  68.                         while (tdo--)
  69.                                 tstring[i++] =  ' ';
  70.                 tstring[i] = '\0';
  71.                 strncpy(fillprefix,tstring,79);
  72.                 mlwrite("Indent column is %d", indcol);
  73.                 return(TRUE);
  74.                 }
  75.         indcol = getccol(FALSE) +1;
  76.         /* now fabricate fill prefix string */
  77.         do {
  78.                 curwp->w_doto = tdo;
  79.                 tstring[tdo] = lgetc(curwp->w_dotp,tdo);
  80.         } while (++tdo < curdo && tdo < 80);
  81.         tstring[curdo] = '\0';
  82.         curwp->w_doto = curdo;
  83.         strncpy(fillprefix,tstring,79);
  84.         mlwrite("Fill prefix is '%s'",fillprefix);
  85.         return(TRUE);
  86. }
  87.  
  88. /*
  89.  * Display the current position of the cursor,
  90.  * in origin 1 X-Y coordinates, the character that is
  91.  * under the cursor (in hex), and the fraction of the
  92.  * text that is before the cursor. The displayed column
  93.  * is not the current column, but the column that would
  94.  * be used on an infinite width display. Normally this
  95.  * is bound to "C-X =".
  96.  */
  97. showcpos(f,n)
  98. int f, n;
  99. {
  100.         register LINE   *clp;
  101.         register long   nch;
  102.         register long   nbc;
  103.         register long   nmc;
  104.         register int    cbo;
  105.         register int    cac;
  106.         register int    page;
  107.         register int    col;
  108.         register int    i;
  109.         register int    row;
  110.         register long   tl1;
  111.         float    ratio, tf1, tf2;
  112.         char     buf[12], *ftoa();
  113.  
  114.         i = 0;
  115.         clp = lforw(curbp->b_linep);            /* Grovel the data.     */
  116.         cbo = 0;
  117.         nch = 0;
  118.         for (;;) {
  119.                 if (clp==curwp->w_markp && cbo==curwp->w_marko)
  120.                         nmc = nch;
  121.                 if (clp==curwp->w_dotp && cbo==curwp->w_doto) {
  122.                         nbc = nch;
  123.                         row = i;
  124.                         if (cbo == llength(clp))
  125.                                 cac = '\n';
  126.                         else
  127.                                 cac = lgetc(clp, cbo);
  128.                 }
  129.                 if (cbo == llength(clp)) {
  130.                         if (clp == curbp->b_linep)
  131.                                 break;
  132.                         clp = lforw(clp);
  133.                         ++i;
  134.                         cbo = 0;
  135.                 } else
  136.                         ++cbo;
  137.                 ++nch;
  138.         }
  139.         col = getccol(FALSE) + 1;               /* Get real column.     */
  140.         if (nch != 0L)
  141.                 {
  142.                 tl1 = nbc * 100L;
  143.                 tf1 = (float)tl1;
  144.                 tf2 = (float)nch;
  145.                 ratio = tf1/tf2;
  146.                 }
  147.         (void)ftoa(ratio,buf,4);
  148.         buf[strlen(buf)-2] = '\0';      /* fool precision error */
  149.         if (curwp->w_dotp == curbp->b_linep)
  150.                 row = i;
  151.         page = row / pagelen + 1;
  152. mlwrite("page:=%d col:=%d line:=%d CH:=0x%x mark:=%D point:=%D (%s%% of %D)",
  153.                  page, col, row, cac, nmc, nbc, buf, nch);
  154.         return (TRUE);
  155. }
  156.  
  157. /*
  158.  * Return current column.  Stop at first non-blank given TRUE argument.
  159.  */
  160. getccol(bflg)
  161. int bflg;
  162. {
  163.         register int c, i, col;
  164.         col = 0;
  165.         for (i=0; i<curwp->w_doto; ++i) {
  166.                 c = lgetc(curwp->w_dotp, i);
  167.                 if (c!=' ' && c!='\t' && bflg)
  168.                         break;
  169.                 if (c == '\t')
  170.                         col |= 0x07;
  171.                 else if (c<0x20 || c==0x7F)
  172.                         ++col;
  173.                 ++col;
  174.         }
  175.         return(col);
  176. }
  177.  
  178. /*
  179.  * Twiddle the two characters on either side of
  180.  * dot. If dot is at the end of the line twiddle the
  181.  * two characters before it. Return with an error if dot
  182.  * is at the beginning of line; it seems to be a bit
  183.  * pointless to make this work. This fixes up a very
  184.  * common typo with a single stroke. Normally bound
  185.  * to "C-T". This always works within a line, so
  186.  * "WFEDIT" is good enough.
  187.  */
  188. twiddle(f, n)
  189. register int f, n;
  190. {
  191.         register LINE   *dotp;
  192.         register int    doto;
  193.         register int    cl;
  194.         register int    cr;
  195.  
  196.         dotp = curwp->w_dotp;
  197.         doto = curwp->w_doto;
  198.         if (doto==llength(dotp) && --doto<0)
  199.                 return (FALSE);
  200.         cr = lgetc(dotp, doto);
  201.         if (--doto < 0)
  202.                 return (FALSE);
  203.         cl = lgetc(dotp, doto);
  204.         lputc(dotp, doto+0, cr);
  205.         lputc(dotp, doto+1, cl);
  206.         lchange(WFEDIT);
  207.         return (TRUE);
  208. }
  209.  
  210. /*
  211.  * Quote the next character, and
  212.  * insert it into the buffer. All the characters
  213.  * are taken literally, with the exception of the newline,
  214.  * which always has its line splitting meaning. The character
  215.  * is always read, even if it is inserted 0 times, for
  216.  * regularity. Bound to "M-Q" (for me) and "C-Q" (for Rich,
  217.  * and only on terminals that don't need XON-XOFF).
  218.  */
  219. quote(f, n)
  220. register int f, n;
  221. {
  222.         register int    s;
  223.         register int    c;
  224.  
  225.         c = (*term.t_getchar)();
  226.         if (n < 0)
  227.                 return (FALSE);
  228.         if (n == 0)
  229.                 return (TRUE);
  230.         if (c == '\n') {
  231.                 do {
  232.                         s = lnewline();
  233.                 } while (s==TRUE && --n);
  234.                 return (s);
  235.         }
  236.         return (linsert(n, c));
  237. }
  238.  
  239. /*
  240.  * Set tab size if given non-default argument (n <> 1).  Otherwise, insert a
  241.  * tab into file.  If given argument, n, of zero, change to true tabs.
  242.  * If n > 1, simulate tab stop every n-characters using spaces.
  243.  * This has to be done in this slightly funny way because the
  244.  * tab (in ASCII) has been turned into "C-I" (in 10
  245.  * bit code) already. Bound to "C-I".
  246.  */
  247. tab(f, n)
  248. register int f, n;
  249. {
  250.         if (n < 0)
  251.                 return (FALSE);
  252.         if (n == 0 || n > 1) {
  253.                 tabsize = n;
  254.                 return(TRUE);
  255.         }
  256.         if (! tabsize)
  257.                 return(linsert(1, '\t'));
  258.         return(linsert(tabsize - (getccol(FALSE) % tabsize), ' '));
  259. }
  260.  
  261. /*
  262.  * Open up some blank space. The basic plan
  263.  * is to insert a bunch of newlines, and then back
  264.  * up over them. Everything is done by the subcommand
  265.  * processors. They even handle the looping. Normally
  266.  * this is bound to "C-O".
  267.  */
  268. openline(f, n)
  269. register int f, n;
  270. {
  271.         register int    i;
  272.         register int    s;
  273.  
  274.         if (n < 0)
  275.                 return (FALSE);
  276.         if (n == 0)
  277.                 return (TRUE);
  278.         i = n;                                  /* Insert newlines.     */
  279.         do {
  280.                 s = lnewline();
  281.         } while (s==TRUE && --i);
  282.         if (s == TRUE)                          /* Then back up overtop */
  283.                 s = backchar(f, n);             /* of them all.         */
  284.         return (s);
  285. }
  286.  
  287. /*
  288.  * Insert a newline. Bound to "C-M".
  289.  * If you are at the end of the line and the
  290.  * next line is a blank line, just move into the
  291.  * blank line. This makes "C-O" and "C-X C-O" work
  292.  * nicely, and reduces the ammount of screen
  293.  * update that has to be done. This would not be
  294.  * as critical if screen update were a lot
  295.  * more efficient.
  296.  */
  297. newline(f, n)
  298. register int f, n;
  299. {
  300.         register LINE   *lp;
  301.         register int    s;
  302.         extern unsigned char insflag;
  303.  
  304.         if (n < 0)
  305.                 return (FALSE);
  306.         if (yankcflag == TRUE || insflag == TRUE)
  307.                 goto around;
  308.         if (n == 1 && (curbp->b_bmode&BMCMODE) != 0
  309.                 && curwp->w_dotp != curbp->b_linep)
  310.                 return(indent(TRUE,n));
  311.         if (indcol > 0)
  312.                 return(indent(MAYBE,1));
  313. around: while (n--) {
  314.                 lp = curwp->w_dotp;
  315.                 if (llength(lp) == curwp->w_doto
  316.                 && lp != curbp->b_linep
  317.                 && llength(lforw(lp)) == 0) {
  318.                         if ((s=forwchar(FALSE, 1)) != TRUE)
  319.                                 return (s);
  320.                 } else if ((s=lnewline()) != TRUE)
  321.                         return (s);
  322.         }
  323.         return (TRUE);
  324. }
  325.  
  326. /*
  327.  * Delete blank lines around dot.
  328.  * What this command does depends if dot is
  329.  * sitting on a blank line. If dot is sitting on a
  330.  * blank line, this command deletes all the blank lines
  331.  * above and below the current line. If it is sitting
  332.  * on a non blank line then it deletes all of the
  333.  * blank lines after the line. Normally this command
  334.  * is bound to "C-X C-O". Any argument is ignored.
  335.  */
  336. deblank(f, n)
  337. register int f, n;
  338. {
  339.         register LINE   *lp1;
  340.         register LINE   *lp2;
  341.         register int    nld;
  342.  
  343.         lp1 = curwp->w_dotp;
  344.         while (llength(lp1)==0 && (lp2=lback(lp1))!=curbp->b_linep)
  345.                 lp1 = lp2;
  346.         lp2 = lp1;
  347.         nld = 0;
  348.         while ((lp2=lforw(lp2))!=curbp->b_linep && llength(lp2)==0)
  349.                 ++nld;
  350.         if (nld == 0)
  351.                 return (TRUE);
  352.         curwp->w_dotp = lforw(lp1);
  353.         curwp->w_doto = 0;
  354.         return (ldelete(nld));
  355. }
  356.  
  357. /*
  358.  * Insert a newline, then enough
  359.  * tabs and spaces to duplicate the indentation
  360.  * of the previous line. Assumes tabs are every eight
  361.  * characters. Quite simple. Figure out the indentation
  362.  * of the current line. Insert a newline by calling
  363.  * the standard routine. Insert the indentation by
  364.  * inserting the right number of tabs and spaces.
  365.  * Return TRUE if all ok. Return FALSE if one
  366.  * of the subcomands failed. Normally bound
  367.  * to "C-J".
  368.  */
  369. indent(f, n)
  370. register int f, n;
  371. {
  372.         register int    nicol;
  373.         register int    c;
  374.         register int    i;
  375.  
  376.         if (n < 0)
  377.                 return (FALSE);
  378.         if (f == MAYBE) /* This call is to fill a paragraph or wrap an */
  379.                 {       /* indented line */
  380.                 if (lnewline() == FALSE || putlin(fillprefix) == FALSE)
  381.                         return(FALSE);
  382.                 return(TRUE);
  383.                 }
  384.         while (n--) {
  385.                 nicol = 0;
  386.                 for (i=0; i<llength(curwp->w_dotp); ++i) {
  387.                         c = lgetc(curwp->w_dotp, i);
  388.                         if (c!=' ' && c!='\t')
  389.                                 break;
  390.                         if (c == '\t')
  391.                                 nicol |= 0x07;
  392.                         ++nicol;
  393.                 }
  394.         if (lnewline() == FALSE
  395.                 || ((i=nicol/8)!=0 && linsert(i, '\t')==FALSE)
  396.                 || ((i=nicol%8)!=0 && linsert(i,  ' ')==FALSE))
  397.                         return (FALSE);
  398.         }
  399.         return (TRUE);
  400. }
  401.  
  402. /* MDROPLN : META command to drop the current line and indent the same
  403.  * as the current line.  Bound to M-O.
  404.  */
  405.  
  406. mdropln(f, n)
  407. register int f, n;
  408. {
  409.         register int    nicol;
  410.         register int    c;
  411.         register int    i;
  412.  
  413.         if (n < 0)
  414.                 return (FALSE);
  415.         curwp->w_doto = 0;
  416.         while (n--) {
  417.                 nicol = 0;
  418.                 for (i=0; i<llength(curwp->w_dotp); ++i) {
  419.                         c = lgetc(curwp->w_dotp, i);
  420.                         if (c!=' ' && c!='\t')
  421.                                 break;
  422.                         if (c == '\t')
  423.                                 nicol |= 0x07;
  424.                         ++nicol;
  425.                 }
  426.                 if (openline(NULL, 1) == FALSE
  427.                 || ((i=nicol/8)!=0 && linsert(i, '\t')==FALSE)
  428.                 || ((i=nicol%8)!=0 && linsert(i,  ' ')==FALSE))
  429.                         return (FALSE);
  430.         }
  431.         return (TRUE);
  432. }
  433.  
  434. /*
  435.  * Delete forward. This is real
  436.  * easy, because the basic delete routine does
  437.  * all of the work. Watches for negative arguments,
  438.  * and does the right thing. If any argument is
  439.  * present, it kills rather than deletes, to prevent
  440.  * loss of text if typed with a big argument.
  441.  * Normally bound to "C-D".
  442.  */
  443. forwdel(f, n)
  444. register int f, n;
  445. {
  446.         if (n < 0)
  447.                 return (backdel(f, -n));
  448.         if (f != FALSE) {                       /* Really a kill.       */
  449.                 if ((lastflag&CFKILL) == 0)
  450.                         kdelete();
  451.                 thisflag |= CFKILL;
  452.         }
  453.         return (ldelete(n, f));
  454. }
  455.  
  456. /*
  457.  * Delete backwards. This is quite easy too,
  458.  * because it's all done with other functions. Just
  459.  * move the cursor back, and delete forwards.
  460.  * Like delete forward, this actually does a kill
  461.  * if presented with an argument. Bound to both
  462.  * "RUBOUT" and "C-H".
  463.  */
  464. backdel(f, n)
  465. register int f, n;
  466. {
  467.         register int    s;
  468.  
  469.         if (n < 0)
  470.                 return (forwdel(f, -n));
  471.         if (f != FALSE) {                       /* Really a kill.       */
  472.                 if ((lastflag&CFKILL) == 0)
  473.                         kdelete();
  474.                 thisflag |= CFKILL;
  475.         }
  476.         if ((s=backchar(f, n)) == TRUE)
  477.                 s = ldelete(n, f);
  478.         return (s);
  479. }
  480.  
  481. /*
  482.  * Kill text. If called without an argument,
  483.  * it kills from dot to the end of the line, unless it
  484.  * is at the end of the line, when it kills the newline.
  485.  * If called with an argument of 0, it kills from the
  486.  * start of the line to dot. If called with a positive
  487.  * argument, it kills from dot forward over that number
  488.  * of newlines. If called with a negative argument it
  489.  * kills backwards that number of newlines. Normally
  490.  * bound to "C-K".
  491.  */
  492. kill(f, n)
  493. register int f, n;
  494. {
  495.         register int    chunk;
  496.         register LINE   *nextp;
  497.  
  498.         if ((lastflag&CFKILL) == 0)             /* Clear kill buffer if */
  499.                 kdelete();                      /* last wasn't a kill.  */
  500.         thisflag |= CFKILL;
  501.         if (f == FALSE) {
  502.                 chunk = llength(curwp->w_dotp)-curwp->w_doto;
  503.                 if (chunk == 0)
  504.                         chunk = 1;
  505.         } else if (n == 0) {
  506.                 chunk = curwp->w_doto;
  507.                 curwp->w_doto = 0;
  508.         } else if (n > 0) {
  509.                 chunk = llength(curwp->w_dotp)-curwp->w_doto+1;
  510.                 nextp = lforw(curwp->w_dotp);
  511.                 while (--n) {
  512.                         if (nextp == curbp->b_linep)
  513.                                 return (FALSE);
  514.                         chunk += llength(nextp)+1;
  515.                         nextp = lforw(nextp);
  516.                 }
  517.         } else {
  518.                 mlwrite("neg kill");
  519.                 return (FALSE);
  520.         }
  521.         return (ldelete(chunk, TRUE));
  522. }
  523.  
  524. /*
  525.  * Yank text back from the kill buffer. This
  526.  * is really easy. All of the work is done by the
  527.  * standard insert routines. All you do is run the loop,
  528.  * and check for errors. Bound to "C-Y". The blank
  529.  * lines are inserted with a call to "newline"
  530.  * instead of a call to "lnewline" so that the magic
  531.  * stuff that happens when you type a carriage
  532.  * return also happens when a carriage return is
  533.  * yanked back from the kill buffer.
  534.  */
  535. yank(f, n)
  536. register int f, n;
  537. {
  538.         register int    c;
  539.         register int    i;
  540.         extern   int    kused;
  541.  
  542.         if (n < 0)
  543.                 return (FALSE);
  544.         if (curbp->b_bmode&BMCMODE)
  545.                 yankcflag = TRUE;       /* don't reindent yanked text */
  546.         while (n--) {
  547.                 i = 0;
  548.                 while ((c=kremove(i)) >= 0) {
  549.                         if (c == '\n') {
  550.                                 if (newline(FALSE, 1) == FALSE)
  551.                                         return (FALSE);
  552.                         } else {
  553.                                 if (linsert(1, c) == FALSE)
  554.                                         return (FALSE);
  555.                         }
  556.                         ++i;
  557.                 }
  558.         }
  559.         yankcflag = FALSE;
  560.         return (TRUE);
  561. }
  562.