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(®ion)) != 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(®ion)) != 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(®ion)) != 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(®ion)) != 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(®ion)) != 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 */