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

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