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

  1. /*
  2.  * Region based commands. The routines in this file deal with the region,
  3.  * that magic space between "." and mark. Some functions are commands. Some
  4.  * functions are just for internal use.
  5.  */
  6. #include    "prefixregion.h"
  7.  
  8. #include    "def.h"
  9. #include    "line.h"
  10. #include    "region.h"
  11. #include    "buffer.h"
  12. #include    "window.h"
  13.  
  14. #ifdef    ANSI
  15. #include <string.h>
  16. #endif
  17.  
  18. /*
  19.  * Kill the region. Ask "getregion" to figure out the bounds of the region.
  20.  * Move "." to the start, and kill the characters.
  21.  */
  22. /* ARGSUSED */
  23. killregion(f, n)
  24. {
  25.     register int    s;
  26.     struct region   reg;
  27.  
  28.     if ((s = getregion(®)) != TRUE)
  29.         return (s);
  30.     if ((lastflag & CFKILL) == 0)    /* This is a kill type     */
  31.         kdelete();    /* command, so do magic */
  32.     thisflag |= CFKILL;    /* kill buffer stuff.     */
  33.     curwp->w_dotp = reg.r_linep;
  34.     curwp->w_doto = reg.r_offset;
  35.     return (fdelete(reg.r_size, TRUE));
  36. }
  37.  
  38. /*
  39.  * Copy all of the characters in the region to the kill buffer. Don't move
  40.  * dot at all. This is a bit like a kill region followed by a yank.
  41.  */
  42. /* ARGSUSED */
  43. copyregion(f, n)
  44. {
  45.     register struct line *linep;
  46.     register int    loffs;
  47.     register int    s;
  48.     struct region   reg;
  49.     VOID            kdelete();
  50.  
  51.     if ((s = getregion(®)) != TRUE)
  52.         return s;
  53.     if ((lastflag & CFKILL) == 0)    /* Kill type command.     */
  54.         kdelete();
  55.     thisflag |= CFKILL;
  56.     linep = reg.r_linep;    /* Current line.     */
  57.     loffs = reg.r_offset;    /* Current offset.     */
  58.     while (reg.r_size--) {
  59.         if (loffs == llength(linep)) {    /* End of line.         */
  60.             if ((s = kinsert('\n', KFORW)) != TRUE)
  61.                 return (s);
  62.             linep = lforw(linep);
  63.             loffs = 0;
  64.         } else {    /* Middle of line.     */
  65.             if ((s = kinsert(lgetc(linep, loffs), KFORW)) != TRUE)
  66.                 return s;
  67.             loffs += 1;
  68.         }
  69.     }
  70.     return TRUE;
  71. }
  72.  
  73. /*
  74.  * Lower case region. Zap all of the upper case characters in the region to
  75.  * lower case. Use the region code to set the limits. Scan the buffer, doing
  76.  * the changes. Call "lchange" to ensure that redisplay is done in all
  77.  * buffers.
  78.  */
  79. /* ARGSUSED */
  80. lowerregion(f, n)
  81. {
  82.     register struct line *linep;
  83.     register int    loffs;
  84.     register int    c;
  85.     register int    s;
  86.     struct region   reg;
  87.  
  88.     if ((s = getregion(®)) != TRUE)
  89.         return s;
  90.     lchange(WFHARD);
  91.     linep = reg.r_linep;
  92.     loffs = reg.r_offset;
  93.     while (reg.r_size--) {
  94.         if (loffs == llength(linep)) {
  95.             linep = lforw(linep);
  96.             loffs = 0;
  97.         } else {
  98.             c = lgetc(linep, loffs);
  99.             if (ISUPPER(c) != FALSE)
  100.                 lputc(linep, loffs, TOLOWER(c));
  101.             loffs += 1;
  102.         }
  103.     }
  104.     return TRUE;
  105. }
  106.  
  107. /*
  108.  * Upper case region. Zap all of the lower case characters in the region to
  109.  * upper case. Use the region code to set the limits. Scan the buffer, doing
  110.  * the changes. Call "lchange" to ensure that redisplay is done in all
  111.  * buffers.
  112.  */
  113. /* ARGSUSED */
  114. upperregion(f, n)
  115. {
  116.     register struct line *linep;
  117.     register int    loffs;
  118.     register int    c;
  119.     register int    s;
  120.     struct region   reg;
  121.     VOID            lchange();
  122.  
  123.     if ((s = getregion(®)) != TRUE)
  124.         return s;
  125.     lchange(WFHARD);
  126.     linep = reg.r_linep;
  127.     loffs = reg.r_offset;
  128.     while (reg.r_size--) {
  129.         if (loffs == llength(linep)) {
  130.             linep = lforw(linep);
  131.             loffs = 0;
  132.         } else {
  133.             c = lgetc(linep, loffs);
  134.             if (ISLOWER(c) != FALSE)
  135.                 lputc(linep, loffs, TOUPPER(c));
  136.             loffs += 1;
  137.         }
  138.     }
  139.     return TRUE;
  140. }
  141.  
  142. /*
  143.  * This routine figures out the bound of the region in the current window,
  144.  * and stores the results into the fields of the REGION structure. Dot and
  145.  * mark are usually close together, but I don't know the order, so I scan
  146.  * outward from dot, in both directions, looking for mark. The size is kept
  147.  * in a long. At the end, after the size is figured out, it is assigned to
  148.  * the size field of the region structure. If this assignment loses any bits,
  149.  * then we print an error. This is "type independent" overflow checking. All
  150.  * of the callers of this routine should be ready to get an ABORT status,
  151.  * because I might add a "if regions is big, ask before clobberring" flag.
  152.  */
  153. getregion(rp)
  154.     register struct region *rp;
  155. {
  156.     register struct line *flp;
  157.     register struct line *blp;
  158.     register long   fsize;    /* Long now.         */
  159.     register long   bsize;
  160.  
  161.     if (curwp->w_markp == NULL) {
  162.         ewprintf("No mark set in this window");
  163.         return (FALSE);
  164.     }
  165.     if (curwp->w_dotp == curwp->w_markp) {    /* "r_size" always ok.     */
  166.         rp->r_linep = curwp->w_dotp;
  167.         if (curwp->w_doto < curwp->w_marko) {
  168.             rp->r_offset = curwp->w_doto;
  169.             rp->r_size = (RSIZE) (curwp->w_marko - curwp->w_doto);
  170.         } else {
  171.             rp->r_offset = curwp->w_marko;
  172.             rp->r_size = (RSIZE) (curwp->w_doto - curwp->w_marko);
  173.         }
  174.         return TRUE;
  175.     }
  176.     flp = blp = curwp->w_dotp;    /* Get region size.     */
  177.     bsize = curwp->w_doto;
  178.     fsize = llength(flp) - curwp->w_doto + 1;
  179.     while (lforw(flp) != curbp->b_linep || lback(blp) != curbp->b_linep) {
  180.         if (lforw(flp) != curbp->b_linep) {
  181.             flp = lforw(flp);
  182.             if (flp == curwp->w_markp) {
  183.                 rp->r_linep = curwp->w_dotp;
  184.                 rp->r_offset = curwp->w_doto;
  185.                 return (setsize(rp,
  186.                      (RSIZE) (fsize + curwp->w_marko)));
  187.             }
  188.             fsize += llength(flp) + 1;
  189.         }
  190.         if (lback(blp) != curbp->b_linep) {
  191.             blp = lback(blp);
  192.             bsize += llength(blp) + 1;
  193.             if (blp == curwp->w_markp) {
  194.                 rp->r_linep = blp;
  195.                 rp->r_offset = curwp->w_marko;
  196.                 return (setsize(rp,
  197.                      (RSIZE) (bsize - curwp->w_marko)));
  198.             }
  199.         }
  200.     }
  201.     ewprintf("Bug: lost mark");    /* Gak!             */
  202.     return FALSE;
  203. }
  204.  
  205. /*
  206.  * Set size, and check for overflow.
  207.  */
  208. setsize(rp, size)
  209.     register struct region *rp;
  210.     register RSIZE  size;
  211. {
  212.  
  213.     rp->r_size = size;
  214.     if (rp->r_size != size) {
  215.         ewprintf("Region is too large");
  216.         return FALSE;
  217.     }
  218.     return TRUE;
  219. }
  220.  
  221. #ifdef    PREFIXREGION
  222. /*
  223.  * Implements one of my favorite keyboard macros; put a string at the
  224.  * beginning of a number of lines in a buffer.    The quote string is settable
  225.  * by using set-prefix-string.     Great for quoting mail, which is the real
  226.  * reason I wrote it, but also has uses for creating bar comments (like the
  227.  * one you're reading) in C code.
  228.  */
  229.  
  230. #define PREFIXLENGTH 40
  231. static char     prefix_string[PREFIXLENGTH] = {'>', '\0'};
  232.  
  233. /*
  234.  * Prefix the region with whatever is in prefix_string. Leaves dot at the
  235.  * beginning of the line after the end of the region.  If an argument is
  236.  * given, prompts for the line prefix string.
  237.  */
  238.  
  239. /* ARGSUSED */
  240. prefixregion(f, n)
  241. {
  242.     register int    s;
  243.     register struct line *first, *last;
  244.     register int    nline;
  245.     struct region   reg;
  246.     char           *prefix = prefix_string;
  247.  
  248.     if ((f == TRUE) && ((s = setprefix(FFRAND, 1)) != TRUE))
  249.         return s;
  250.  
  251.     /* get # of lines to affect */
  252.     if ((s = getregion(®)) != TRUE)
  253.         return (s);
  254.     first = reg.r_linep;
  255.     last = (first == curwp->w_dotp) ? curwp->w_markp : curwp->w_dotp;
  256.     for (nline = 1; first != last; nline += 1)
  257.         first = lforw(first);
  258.  
  259.     /* move to beginning of region */
  260.     curwp->w_dotp = reg.r_linep;
  261.     curwp->w_doto = reg.r_offset;
  262.  
  263.     /* for each line, go to beginning and insert the prefix string */
  264.     while (nline--) {
  265.         (VOID) gotobol(FFRAND, 1);
  266.         for (prefix = prefix_string; *prefix; prefix += 1)
  267.             (VOID) linsert(1, *prefix);
  268.         (VOID) forwline(FFRAND, 1);
  269.     }
  270.     (VOID) gotobol(FFRAND, 1);
  271.     return TRUE;
  272. }
  273.  
  274. /*
  275.  * Set prefix string.
  276.  */
  277.  
  278. /* ARGSUSED */
  279. setprefix(f, n)
  280. {
  281.     char            buf[PREFIXLENGTH];
  282.     register int    s;
  283.  
  284.     if (prefix_string[0] == '\0')
  285.         s = ereply("Prefix string: ", buf, sizeof buf);
  286.     else
  287.         s = ereply("Prefix string (default %s): ",
  288.                buf, sizeof buf, prefix_string);
  289.     if (s == TRUE)
  290.         (VOID) strcpy(prefix_string, buf);
  291.     if ((s == FALSE) && (prefix_string[0] != '\0'))    /* CR -- use old one */
  292.         s = TRUE;
  293.     return s;
  294. }
  295. #endif
  296.