[BACK]Return to region.c CVS log [TXT][DIR] Up to [local] / src / usr.bin / mg

Annotation of src/usr.bin/mg/region.c, Revision 1.4

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