Annotation of src/usr.bin/mg/paragraph.c, Revision 1.8
1.8 ! cloder 1: /* $OpenBSD: paragraph.c,v 1.7 2002/02/14 14:24:21 deraadt Exp $ */
1.4 niklas 2:
1.1 deraadt 3: /*
4: * Code for dealing with paragraphs and filling. Adapted from MicroEMACS 3.6
5: * and GNU-ified by mwm@ucbvax. Several bug fixes by blarson@usc-oberon.
6: */
1.3 millert 7:
1.1 deraadt 8: #include "def.h"
9:
1.3 millert 10: static int fillcol = 70;
11:
1.1 deraadt 12: #define MAXWORD 256
13:
14: /*
1.6 mickey 15: * Move to start of paragraph. Go back to the begining of the current
16: * paragraph here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE>
1.3 millert 17: * combination to delimit the begining of a paragraph.
1.1 deraadt 18: */
1.2 millert 19: /* ARGSUSED */
1.3 millert 20: int
1.8 ! cloder 21: gotobop(int f, int n)
1.1 deraadt 22: {
1.3 millert 23: /* the other way... */
24: if (n < 0)
1.1 deraadt 25: return gotoeop(f, -n);
26:
1.3 millert 27: while (n-- > 0) {
1.1 deraadt 28: /* first scan back until we are in a word */
1.3 millert 29: while (backchar(FFRAND, 1) && inword() == NULL);
1.2 millert 30:
1.3 millert 31: /* and go to the B-O-Line */
32: curwp->w_doto = 0;
1.1 deraadt 33:
1.2 millert 34: /*
35: * and scan back until we hit a <NL><SP> <NL><TAB> or
36: * <NL><NL>
37: */
1.1 deraadt 38: while (lback(curwp->w_dotp) != curbp->b_linep)
1.7 deraadt 39: if (llength(lback(curwp->w_dotp)) &&
40: lgetc(curwp->w_dotp, 0) != ' ' &&
41: lgetc(curwp->w_dotp, 0) != '.' &&
42: lgetc(curwp->w_dotp, 0) != '\t')
1.1 deraadt 43: curwp->w_dotp = lback(curwp->w_dotp);
44: else {
1.7 deraadt 45: if (llength(lback(curwp->w_dotp)) &&
46: lgetc(curwp->w_dotp, 0) == '.') {
1.2 millert 47: curwp->w_dotp = lforw(curwp->w_dotp);
48: if (curwp->w_dotp == curbp->b_linep) {
49: /*
50: * beond end of buffer,
51: * cleanup time
52: */
1.6 mickey 53: curwp->w_dotp =
1.3 millert 54: lback(curwp->w_dotp);
1.6 mickey 55: curwp->w_doto =
1.3 millert 56: llength(curwp->w_dotp);
1.2 millert 57: }
58: }
59: break;
60: }
1.1 deraadt 61: }
1.3 millert 62: /* force screen update */
63: curwp->w_flag |= WFMOVE;
1.1 deraadt 64: return TRUE;
65: }
66:
67: /*
1.6 mickey 68: * Move to end of paragraph. Go forword to the end of the current paragraph
69: * here we look for a <NL><NL> or <NL><TAB> or <NL><SPACE> combination to
1.3 millert 70: * delimit the begining of a paragraph.
1.1 deraadt 71: */
1.2 millert 72: /* ARGSUSED */
1.3 millert 73: int
1.8 ! cloder 74: gotoeop(int f, int n)
1.1 deraadt 75: {
1.3 millert 76: /* the other way... */
77: if (n < 0)
1.1 deraadt 78: return gotobop(f, -n);
79:
1.3 millert 80: /* for each one asked for */
81: while (n-- > 0) {
1.1 deraadt 82: /* Find the first word on/after the current line */
83: curwp->w_doto = 0;
1.3 millert 84: while (forwchar(FFRAND, 1) && inword() == NULL);
85:
1.1 deraadt 86: curwp->w_doto = 0;
87: curwp->w_dotp = lforw(curwp->w_dotp);
1.3 millert 88:
1.1 deraadt 89: /* and scan forword until we hit a <NL><SP> or ... */
90: while (curwp->w_dotp != curbp->b_linep) {
1.7 deraadt 91: if (llength(curwp->w_dotp) &&
92: lgetc(curwp->w_dotp, 0) != ' ' &&
93: lgetc(curwp->w_dotp, 0) != '.' &&
94: lgetc(curwp->w_dotp, 0) != '\t')
1.1 deraadt 95: curwp->w_dotp = lforw(curwp->w_dotp);
96: else
97: break;
98: }
1.2 millert 99: if (curwp->w_dotp == curbp->b_linep) {
1.1 deraadt 100: /* beond end of buffer, cleanup time */
101: curwp->w_dotp = lback(curwp->w_dotp);
102: curwp->w_doto = llength(curwp->w_dotp);
1.2 millert 103: break;
1.1 deraadt 104: }
105: }
1.3 millert 106: /* force screen update */
107: curwp->w_flag |= WFMOVE;
1.1 deraadt 108: return TRUE;
109: }
110:
111: /*
1.6 mickey 112: * Justify a paragraph. Fill the current paragraph according to the current
1.3 millert 113: * fill column.
1.1 deraadt 114: */
1.2 millert 115: /* ARGSUSED */
1.3 millert 116: int
1.8 ! cloder 117: fillpara(int f, int n)
1.1 deraadt 118: {
1.3 millert 119: int c; /* current char durring scan */
120: int wordlen; /* length of current word */
121: int clength; /* position on line during fill */
122: int i; /* index during word copy */
123: int eopflag; /* Are we at the End-Of-Paragraph? */
124: int firstflag; /* first word? (needs no space) */
125: int newlength; /* tentative new line length */
126: int eolflag; /* was at end of line */
127: LINE *eopline; /* pointer to line just past EOP */
128: char wbuf[MAXWORD]; /* buffer for current word */
1.1 deraadt 129:
130: /* record the pointer to the line just past the EOP */
1.5 art 131: (void)gotoeop(FFRAND, 1);
1.2 millert 132: if (curwp->w_doto != 0) {
1.1 deraadt 133: /* paragraph ends at end of buffer */
1.5 art 134: (void)lnewline();
1.1 deraadt 135: eopline = lforw(curwp->w_dotp);
1.2 millert 136: } else
137: eopline = curwp->w_dotp;
1.1 deraadt 138:
139: /* and back top the begining of the paragraph */
1.5 art 140: (void)gotobop(FFRAND, 1);
1.1 deraadt 141:
142: /* initialize various info */
1.3 millert 143: while (inword() == NULL && forwchar(FFRAND, 1));
144:
1.1 deraadt 145: clength = curwp->w_doto;
146: wordlen = 0;
147:
148: /* scan through lines, filling words */
149: firstflag = TRUE;
150: eopflag = FALSE;
151: while (!eopflag) {
1.3 millert 152:
1.1 deraadt 153: /* get the next character in the paragraph */
1.3 millert 154: if ((eolflag = (curwp->w_doto == llength(curwp->w_dotp)))) {
1.1 deraadt 155: c = ' ';
156: if (lforw(curwp->w_dotp) == eopline)
157: eopflag = TRUE;
158: } else
159: c = lgetc(curwp->w_dotp, curwp->w_doto);
160:
161: /* and then delete it */
162: if (ldelete((RSIZE) 1, KNONE) == FALSE && !eopflag)
163: return FALSE;
164:
165: /* if not a separator, just add it in */
166: if (c != ' ' && c != '\t') {
167: if (wordlen < MAXWORD - 1)
168: wbuf[wordlen++] = c;
169: else {
1.2 millert 170: /*
171: * You loose chars beyond MAXWORD if the word
1.1 deraadt 172: * is to long. I'm to lazy to fix it now; it
1.2 millert 173: * just silently truncated the word before,
174: * so I get to feel smug.
1.1 deraadt 175: */
176: ewprintf("Word too long!");
177: }
178: } else if (wordlen) {
1.3 millert 179:
1.1 deraadt 180: /* calculate tenatitive new length with word added */
181: newlength = clength + 1 + wordlen;
1.3 millert 182:
1.2 millert 183: /*
184: * if at end of line or at doublespace and previous
1.1 deraadt 185: * character was one of '.','?','!' doublespace here.
186: */
1.6 mickey 187: if ((eolflag ||
188: curwp->w_doto == llength(curwp->w_dotp) ||
1.3 millert 189: (c = lgetc(curwp->w_dotp, curwp->w_doto)) == ' '
1.6 mickey 190: || c == '\t') && ISEOSP(wbuf[wordlen - 1]) &&
1.3 millert 191: wordlen < MAXWORD - 1)
1.1 deraadt 192: wbuf[wordlen++] = ' ';
1.3 millert 193:
1.1 deraadt 194: /* at a word break with a word waiting */
195: if (newlength <= fillcol) {
196: /* add word to current line */
197: if (!firstflag) {
1.5 art 198: (void)linsert(1, ' ');
1.1 deraadt 199: ++clength;
200: }
201: firstflag = FALSE;
202: } else {
1.2 millert 203: if (curwp->w_doto > 0 &&
204: lgetc(curwp->w_dotp, curwp->w_doto - 1) == ' ') {
1.1 deraadt 205: curwp->w_doto -= 1;
1.5 art 206: (void)ldelete((RSIZE) 1, KNONE);
1.1 deraadt 207: }
208: /* start a new line */
1.5 art 209: (void)lnewline();
1.1 deraadt 210: clength = 0;
211: }
212:
213: /* and add the word in in either case */
1.2 millert 214: for (i = 0; i < wordlen; i++) {
1.5 art 215: (void)linsert(1, wbuf[i]);
1.1 deraadt 216: ++clength;
217: }
218: wordlen = 0;
219: }
220: }
221: /* and add a last newline for the end of our new paragraph */
1.5 art 222: (void)lnewline();
1.3 millert 223:
1.2 millert 224: /*
225: * we realy should wind up where we started, (which is hard to keep
1.1 deraadt 226: * track of) but I think the end of the last line is better than the
1.2 millert 227: * begining of the blank line.
228: */
1.5 art 229: (void)backchar(FFRAND, 1);
1.1 deraadt 230: return TRUE;
231: }
232:
1.6 mickey 233: /*
1.3 millert 234: * Delete a paragraph. Delete n paragraphs starting with the current one.
235: */
1.2 millert 236: /* ARGSUSED */
1.3 millert 237: int
1.8 ! cloder 238: killpara(int f, int n)
1.1 deraadt 239: {
1.3 millert 240: int status; /* returned status of functions */
1.1 deraadt 241:
1.3 millert 242: /* for each paragraph to delete */
243: while (n--) {
1.1 deraadt 244:
245: /* mark out the end and begining of the para to delete */
1.5 art 246: (void)gotoeop(FFRAND, 1);
1.1 deraadt 247:
248: /* set the mark here */
249: curwp->w_markp = curwp->w_dotp;
250: curwp->w_marko = curwp->w_doto;
251:
252: /* go to the begining of the paragraph */
1.5 art 253: (void)gotobop(FFRAND, 1);
1.3 millert 254:
255: /* force us to the beginning of line */
256: curwp->w_doto = 0;
1.1 deraadt 257:
258: /* and delete it */
259: if ((status = killregion(FFRAND, 1)) != TRUE)
260: return status;
261:
262: /* and clean up the 2 extra lines */
1.5 art 263: (void)ldelete((RSIZE) 1, KFORW);
1.1 deraadt 264: }
265: return TRUE;
266: }
267:
268: /*
1.3 millert 269: * Insert char with work wrap. Check to see if we're past fillcol, and if so,
270: * justify this line. As a last step, justify the line.
1.1 deraadt 271: */
1.2 millert 272: /* ARGSUSED */
1.3 millert 273: int
1.8 ! cloder 274: fillword(int f, int n)
1.1 deraadt 275: {
1.3 millert 276: char c;
277: int col, i, nce;
1.1 deraadt 278:
279: for (i = col = 0; col <= fillcol; ++i, ++col) {
1.2 millert 280: if (i == curwp->w_doto)
281: return selfinsert(f, n);
1.1 deraadt 282: c = lgetc(curwp->w_dotp, i);
283: if (c == '\t'
1.3 millert 284: #ifdef NOTAB
1.2 millert 285: && !(curbp->b_flag & BFNOTAB)
1.1 deraadt 286: #endif
1.2 millert 287: )
288: col |= 0x07;
289: else if (ISCTRL(c) != FALSE)
290: ++col;
1.1 deraadt 291: }
292: if (curwp->w_doto != llength(curwp->w_dotp)) {
1.5 art 293: (void)selfinsert(f, n);
1.1 deraadt 294: nce = llength(curwp->w_dotp) - curwp->w_doto;
1.2 millert 295: } else
296: nce = 0;
1.1 deraadt 297: curwp->w_doto = i;
298:
299: if ((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ' && c != '\t')
300: do {
1.5 art 301: (void)backchar(FFRAND, 1);
1.7 deraadt 302: } while ((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ' &&
303: c != '\t' && curwp->w_doto > 0);
1.1 deraadt 304:
305: if (curwp->w_doto == 0)
306: do {
1.5 art 307: (void)forwchar(FFRAND, 1);
1.7 deraadt 308: } while ((c = lgetc(curwp->w_dotp, curwp->w_doto)) != ' ' &&
309: c != '\t' && curwp->w_doto < llength(curwp->w_dotp));
1.1 deraadt 310:
1.5 art 311: (void)delwhite(FFRAND, 1);
312: (void)lnewline();
1.1 deraadt 313: i = llength(curwp->w_dotp) - nce;
1.2 millert 314: curwp->w_doto = i > 0 ? i : 0;
1.1 deraadt 315: curwp->w_flag |= WFMOVE;
1.2 millert 316: if (nce == 0 && curwp->w_doto != 0)
317: return fillword(f, n);
1.1 deraadt 318: return TRUE;
319: }
320:
1.3 millert 321: /*
322: * Set fill column to n for justify.
323: */
324: int
1.8 ! cloder 325: setfillcol(int f, int n)
1.2 millert 326: {
1.1 deraadt 327: fillcol = ((f & FFARG) ? n : getcolpos());
328: ewprintf("Fill column set to %d", fillcol);
329: return TRUE;
330: }