|
|
1.1 root 1: /*
2: * The routines in this file
3: * implement commands that work word at
4: * a time. There are all sorts of word mode
5: * commands. If I do any sentence and/or paragraph
6: * mode commands, they are likely to be put in
7: * this file.
8: */
9: #include <stdio.h>
10: #if NORMAL_CHARS
11: #include <ctype.h>
12: #endif
13: #include "ed.h"
14:
15: /*
16: * Word wrap on input.
17: * called when data is typed in checks that we are at an
18: * end of line. And then trys to wrap the line.
19: */
20: void
21: wrapword()
22: {
23: register LINE *clp;
24:
25: if (llength(clp = curwp->w_dotp) == curwp->w_doto)
26: wrapblock(clp, 0, llength(clp), 0);
27: }
28:
29: /*
30: * Refill region between mark and cursor.
31: */
32: fillregion(f, n)
33: {
34: REGION region;
35:
36: if (getregion(®ion) != TRUE)
37: return (FALSE);
38:
39: if (!bind.fillcol) {
40: mlwrite("Use <ctl-x> f to set fill collumn first");
41: return (FALSE);
42: }
43: return (wrapblock(region.r_linep, region.r_offset, region.r_size,
44: truecol(region.r_linep, region.r_offset)));
45: }
46:
47: /*
48: * wrap a block of data. Gets the start address, size and
49: * true collum of the start. Triggers when printable chars
50: * are over wrap length and there is white space before them.
51: */
52: wrapblock(lineP, offset, size, trueCol)
53: register LINE *lineP;
54: short offset, size, trueCol;
55: {
56: int blackCt, whiteCt;
57:
58: for (blackCt = whiteCt = 0; size-- > 0; offset++) {
59: if (offset == llength(lineP)) {
60: if (!size)
61: break;
62: whiteCt = blackCt = 0;
63: while (!llength(lineP = lforw(lineP))) {
64: size--;
65: trueCol = 0;
66: offset = -1;
67: }
68: if (-1 == offset)
69: continue;
70: curwp->w_doto = offset;
71: curwp->w_dotp = lineP = lback(lineP);
72: ldelete(1, FALSE);
73: linsert(whiteCt = 1, ' ');
74: trueCol++;
75: offset = curwp->w_doto - 1;
76: lineP = curwp->w_dotp;
77: continue;
78: }
79: switch (lgetc(lineP, offset)) {
80: case '\t':
81: taber(trueCol);
82: case ' ':
83: if (!blackCt)
84: whiteCt++;
85: else {
86: whiteCt = 1;
87: blackCt = 0;
88: }
89: break;
90: default:
91: if (!blackCt)
92: blackCt = 1;
93: else
94: blackCt++;
95: }
96: if ((trueCol++ > bind.fillcol) && whiteCt && blackCt) {
97: curwp->w_dotp = lineP;
98: curwp->w_doto = offset -= whiteCt + blackCt - 1;
99: lnewline();
100: ldelete(whiteCt, FALSE);
101: whiteCt = 0;
102: offset = (trueCol = blackCt) - 1;
103: lineP = curwp->w_dotp;
104: }
105: }
106: curwp->w_doto = llength(curwp->w_dotp);
107: return (TRUE);
108: }
109:
110: /*
111: * Return TRUE if the character at dot is a character that is considered
112: * to be white space. Used in wordwrap.
113: * The whitespace character list is hard coded. Should be setable.
114: */
115: inwhite()
116: {
117: register int c;
118:
119: if (curwp->w_doto == llength(curwp->w_dotp))
120: return (FALSE);
121: c = lgetc(curwp->w_dotp, curwp->w_doto);
122: if (c == ' ' || c == '\t' )
123: return (TRUE);
124: return (FALSE);
125: }
126:
127: /*
128: * Move the cursor backward to the last bit of whitespace...
129: * All of the details of motion are performed by the "backchar" and "forwchar"
130: * routines. Error if you try to move beyond the buffers.
131: */
132: backwhite()
133: {
134: if (backchar(FALSE, 1) == FALSE)
135: return (FALSE);
136: while (!inwhite()) {
137: if (backchar(FALSE, 1) == FALSE)
138: return (FALSE);
139: }
140: return (forwchar(FALSE, 1));
141: }
142:
143: /*
144: * Move the cursor backward by "n" words. All of the details of motion
145: * are performed by the "backchar" and "forwchar" routines. Error if you
146: * try to move beyond the buffers.
147: */
148: backword(f, n)
149: {
150: if (n < 0)
151: return (forwword(f, -n));
152: if (backchar(FALSE, 1) == FALSE)
153: return (FALSE);
154: while (n--) {
155: while (inword() == FALSE) {
156: if (backchar(FALSE, 1) == FALSE)
157: return (FALSE);
158: }
159: while (inword() != FALSE) {
160: if (backchar(FALSE, 1) == FALSE)
161: return (FALSE);
162: }
163: }
164: return (forwchar(FALSE, 1));
165: }
166:
167: /*
168: * Move the cursor forward by the specified number of words. All of the
169: * motion is done by "forwchar". Error if you try and move beyond the
170: * buffer's end.
171: */
172: forwword(f, n)
173: {
174: if (n < 0)
175: return (backword(f, -n));
176: while (n--) {
177: while (inword() == FALSE) {
178: if (forwchar(FALSE, 1) == FALSE)
179: return (FALSE);
180: }
181: while (inword() != FALSE) {
182: if (forwchar(FALSE, 1) == FALSE)
183: return (FALSE);
184: }
185: }
186: return (TRUE);
187: }
188:
189: /*
190: * There is no pattern I can discover to the upper and lower case
191: * of the wierd umlauts etc tacked on to ascii. These tables are the
192: * convertable wierd characters upFor has the upper case and loFor
193: * the corresponding lower case.
194: */
195: static uchar upFor[8] = { 0x80, 0x9A, 0x90, 0x8E, 0x8F, 0x92, 0x99, 0 };
196: static uchar loFor[8] = { 0x87, 0x81, 0x82, 0x84, 0x86, 0x91, 0x94, 0 };
197:
198: /*
199: * Turn a char to upper case.
200: */
201: capChar()
202: {
203: register int c;
204:
205: if (c = islow(lgetc(curwp->w_dotp, curwp->w_doto))) {
206: lputc(curwp->w_dotp, curwp->w_doto, c);
207: lchange(WFHARD);
208: }
209: return (forwchar(FALSE, 1));
210: }
211:
212: /*
213: * If character is lower case return upper case version.
214: * else return 0
215: */
216: islow(c)
217: register int c;
218: {
219: #if NORMAL_CHARS
220: return (islower(c) ? toupper(c) : 0);
221: #else
222: int i, d;
223:
224: if (c>='a' && c<='z')
225: return (c - ('a'-'A'));
226:
227: if (c & 0x80)
228: for (i = 0; d = loFor[i]; i++)
229: if (d == c)
230: return (upFor[i]);
231: return (0);
232: #endif
233: }
234:
235: /*
236: * Turn a char to lower case.
237: */
238: lowChar()
239: {
240: register int c;
241:
242: if (c = ishi(lgetc(curwp->w_dotp, curwp->w_doto))) {
243: lputc(curwp->w_dotp, curwp->w_doto, c);
244: lchange(WFHARD);
245: }
246: return (forwchar(FALSE, 1));
247: }
248:
249: /*
250: * If character is upper case return lower case version.
251: * else return 0
252: */
253: ishi(c)
254: register int c;
255: {
256: #if NORMAL_CHARS
257: return (isupper(c) ? tolower(c) : 0);
258: #else
259: int i, d;
260:
261: if (c>='A' && c<='Z')
262: return (c - ('A'-'a'));
263:
264: if (c & 0x80)
265: for (i = 0; d = upFor[i]; i++)
266: if (d == c)
267: return (loFor[i]);
268: return (0);
269: #endif
270: }
271:
272: /*
273: * Move the cursor forward by the specified number of words. As you move,
274: * convert any characters to upper case. Error if you try and move beyond
275: * the end of the buffer.
276: * Bound to "M-U".
277: */
278: upperword(f, n)
279: {
280: if (n < 0)
281: return (FALSE);
282: while (n--) {
283: while (inword() == FALSE)
284: if (forwchar(FALSE, 1) == FALSE)
285: return (FALSE);
286:
287: while (inword() != FALSE)
288: if (capChar() == FALSE)
289: return (FALSE);
290: }
291: return (TRUE);
292: }
293:
294: /*
295: * Move the cursor forward by the specified number of words. As you move
296: * convert characters to lower case. Error if you try and move over the
297: * end of the buffer.
298: * Bound to "M-L".
299: */
300: lowerword(f, n)
301: {
302: register int c;
303:
304: if (n < 0)
305: return (FALSE);
306: while (n--) {
307: while (inword() == FALSE)
308: if (forwchar(FALSE, 1) == FALSE)
309: return (FALSE);
310:
311: while (inword() != FALSE)
312: if (lowChar() == FALSE)
313: return (FALSE);
314: }
315: return (TRUE);
316: }
317:
318: /*
319: * Move the cursor forward by
320: * the specified number of words. As you move
321: * convert the first character of the word to upper
322: * case, and subsequent characters to lower case. Error
323: * if you try and move past the end of the buffer.
324: * Bound to "M-C".
325: */
326: capword(f, n)
327: {
328: register int c;
329:
330: if (n < 0)
331: return (FALSE);
332: while (n--) {
333: while (inword() == FALSE)
334: if (forwchar(FALSE, 1) == FALSE)
335: return (FALSE);
336:
337: if (inword() != FALSE) {
338: if (capChar() == FALSE)
339: return (FALSE);
340: while (inword() != FALSE)
341: if (lowChar() == FALSE)
342: return (FALSE);
343: }
344: }
345: return (TRUE);
346: }
347:
348: /*
349: * Kill forward by "n" words.
350: * Remember the location of dot. Move forward
351: * by the right number of words. Put dot back where
352: * it was and issue the kill command for the
353: * right number of characters. Bound to "M-D".
354: */
355: delfword(f, n)
356: {
357: register int size;
358: register LINE *dotp;
359: register int doto;
360:
361: if (n < 0)
362: return (FALSE);
363: dotp = curwp->w_dotp;
364: doto = curwp->w_doto;
365: size = 0;
366: if ((lastflag&CFKILL) == 0) /* Clear kill buffer if */
367: kdelete(); /* last wasn't a kill. */
368: thisflag |= CFKILL;
369: while (n--) {
370: while (inword() == FALSE) {
371: if (forwchar(FALSE, 1) == FALSE)
372: return (FALSE);
373: ++size;
374: }
375: while (inword() != FALSE) {
376: if (forwchar(FALSE, 1) == FALSE)
377: return (FALSE);
378: ++size;
379: }
380: }
381: curwp->w_dotp = dotp;
382: curwp->w_doto = doto;
383: return (ldelete(size, TRUE));
384: }
385:
386: /*
387: * Kill backwards by "n" words.
388: * Move backwards by the desired number of
389: * words, counting the characters. When dot is
390: * finally moved to its resting place, fire off
391: * the kill command. Bound to "M-Rubout" and
392: * to "M-Backspace".
393: */
394: delbword(f, n)
395: {
396: register int size;
397:
398: if (n < 0)
399: return (FALSE);
400: if (backchar(FALSE, 1) == FALSE)
401: return (FALSE);
402: size = 0;
403: if ((lastflag&CFKILL) == 0) /* Clear kill buffer if */
404: kdelete(); /* last wasn't a kill. */
405: thisflag |= CFKILL;
406: while (n--) {
407: while (inword() == FALSE) {
408: if (backchar(FALSE, 1) == FALSE)
409: return (FALSE);
410: ++size;
411: }
412: while (inword() != FALSE) {
413: if (backchar(FALSE, 1) == FALSE)
414: return (FALSE);
415: ++size;
416: }
417: }
418: if (forwchar(FALSE, 1) == FALSE)
419: return (FALSE);
420: return (ldelete(size, TRUE));
421: }
422:
423: /*
424: * Return TRUE if the character at dot
425: * is a character that is considered to be
426: * part of a word. The word character list is hard
427: * coded. Should be setable.
428: */
429: inword()
430: {
431: register int c;
432:
433: if (curwp->w_doto == llength(curwp->w_dotp))
434: return (FALSE);
435: c = lgetc(curwp->w_dotp, curwp->w_doto);
436: if (c>='a' && c<='z')
437: return (TRUE);
438: if (c>='A' && c<='Z')
439: return (TRUE);
440: if (c>='0' && c<='9')
441: return (TRUE);
442: if (c=='$' || c=='_' || c=='\\') /* For identifiers */
443: return (TRUE);
444: if (c & 0x80)
445: return (TRUE);
446: return (FALSE);
447: }
448:
449: #if LIBHELP
450: /*
451: * Lookup the current word.
452: * Error if you try and move past the end of the buffer.
453: * Bound to "M-M-". Count is passed to lookup routine.
454: */
455: lookupword(f, n)
456: {
457: static uchar wordplace[128];
458: register uchar *cp;
459:
460: while (inword() != FALSE) /* Get to beginning of word */
461: if (backchar(FALSE, 1) == FALSE)
462: break;
463:
464: while (inword() == FALSE) { /* Advance to next word */
465: if (forwchar(FALSE, 1) == FALSE)
466: return (FALSE);
467: }
468:
469: cp = wordplace;
470: while (inword() != FALSE) {
471: *cp++ = lgetc(curwp->w_dotp, curwp->w_doto);
472: if (forwchar(FALSE, 1) == FALSE)
473: break;
474: }
475: *cp = '\0';
476: return do_lookup(wordplace, f, n);
477: }
478: #endif
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.