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