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

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