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(®ion)) != 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(®ion)) != 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(®ion)) != 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(®ion)) != 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(®ion)) != 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: }