[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.24

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