Subversion Repositories planix.SVN

Rev

Rev 105 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
105 7u83 1
/*
2
 * Copyright (c) 1980 Regents of the University of California.
3
 * All rights reserved.  The Berkeley software License Agreement
4
 * specifies the terms and conditions for redistribution.
5
 */
6
 
7
#if	!defined(lint) && defined(DOSCCS)
8
static char *sccsid = "@(#)ex_vops3.c	7.3 (Berkeley) 6/7/85";
9
#endif
10
 
11
#include "ex.h"
12
#include "ex_tty.h"
13
#include "ex_vis.h"
14
 
15
/*
16
 * Routines to handle structure.
17
 * Operations supported are:
18
 *	( ) { } [ ]
19
 *
20
 * These cover:		LISP		TEXT
21
 *	( )		s-exprs		sentences
22
 *	{ }		list at same	paragraphs
23
 *	[ ]		defuns		sections
24
 *
25
 * { and } for C used to attempt to do something with matching {}'s, but
26
 * I couldn't find definitions which worked intuitively very well, so I
27
 * scrapped this.
28
 *
29
 * The code here is very hard to understand.
30
 */
31
line	*llimit;
32
int	(*lf)();
33
 
34
#ifdef LISPCODE
35
int	lindent();
36
#endif
37
 
38
bool	wasend;
39
 
40
/*
41
 * Find over structure, repeated count times.
42
 * Don't go past line limit.  F is the operation to
43
 * be performed eventually.  If pastatom then the user said {}
44
 * rather than (), implying past atoms in a list (or a paragraph
45
 * rather than a sentence.
46
 */
47
lfind(pastatom, cnt, f, limit)
48
	bool pastatom;
49
	int cnt, (*f)();
50
	line *limit;
51
{
52
	register int c;
53
	register int rc = 0;
54
	char save[LBSIZE];
55
 
56
	/*
57
	 * Initialize, saving the current line buffer state
58
	 * and computing the limit; a 0 argument means
59
	 * directional end of file.
60
	 */
61
	wasend = 0;
62
	lf = f;
63
	strcpy(save, linebuf);
64
	if (limit == 0)
65
		limit = dir < 0 ? one : dol;
66
	llimit = limit;
67
	wdot = dot;
68
	wcursor = cursor;
69
 
70
	if (pastatom >= 2) {
71
		while (cnt > 0 && word(f, cnt))
72
			cnt--;
73
		if (pastatom == 3)
74
			eend(f);
75
		if (dot == wdot) {
76
			wdot = 0;
77
			if (cursor == wcursor)
78
				rc = -1;
79
		}
80
	}
81
#ifdef LISPCODE
82
	else if (!value(LISP)) {
83
#else
84
	else {
85
#endif
86
		char *icurs;
87
		line *idot;
88
 
89
		if (linebuf[0] == 0) {
90
			do
91
				if (!lnext())
92
					goto ret;
93
			while (linebuf[0] == 0);
94
			if (dir > 0) {
95
				wdot--;
96
				linebuf[0] = 0;
97
				wcursor = linebuf;
98
				/*
99
				 * If looking for sentence, next line
100
				 * starts one.
101
				 */
102
				if (!pastatom) {
103
					icurs = wcursor;
104
					idot = wdot;
105
					goto begin;
106
				}
107
			}
108
		}
109
		icurs = wcursor;
110
		idot = wdot;
111
 
112
		/*
113
		 * Advance so as to not find same thing again.
114
		 */
115
		if (dir > 0) {
116
			if (!lnext()) {
117
				rc = -1;
118
				goto ret;
119
			}
120
		} else
121
			ignore(lskipa1(""));
122
 
123
		/*
124
		 * Count times find end of sentence/paragraph.
125
		 */
126
begin:
127
		for (;;) {
128
			while (!endsent(pastatom))
129
				if (!lnext())
130
					goto ret;
131
			if (!pastatom || wcursor == linebuf && endPS())
132
				if (--cnt <= 0)
133
					break;
134
			if (linebuf[0] == 0) {
135
				do
136
					if (!lnext())
137
						goto ret;
138
				while (linebuf[0] == 0);
139
			} else
140
				if (!lnext())
141
					goto ret;
142
		}
143
 
144
		/*
145
		 * If going backwards, and didn't hit the end of the buffer,
146
		 * then reverse direction.
147
		 */
148
		if (dir < 0 && (wdot != llimit || wcursor != linebuf)) {
149
			dir = 1;
150
			llimit = dot;
151
			/*
152
			 * Empty line needs special treatement.
153
			 * If moved to it from other than begining of next line,
154
			 * then a sentence starts on next line.
155
			 */
156
			if (linebuf[0] == 0 && !pastatom && 
157
			   (wdot != dot - 1 || cursor != linebuf)) {
158
				lnext();
159
				goto ret;
160
			}
161
		}
162
 
163
		/*
164
		 * If we are not at a section/paragraph division,
165
		 * advance to next.
166
		 */
167
		if (wcursor == icurs && wdot == idot || wcursor != linebuf || !endPS())
168
			ignore(lskipa1(""));
169
	}
170
#ifdef LISPCODE
171
	else {
172
		c = *wcursor;
173
		/*
174
		 * Startup by skipping if at a ( going left or a ) going
175
		 * right to keep from getting stuck immediately.
176
		 */
177
		if (dir < 0 && c == '(' || dir > 0 && c == ')') {
178
			if (!lnext()) {
179
				rc = -1;
180
				goto ret;
181
			}
182
		}
183
		/*
184
		 * Now chew up repitition count.  Each time around
185
		 * if at the beginning of an s-exp (going forwards)
186
		 * or the end of an s-exp (going backwards)
187
		 * skip the s-exp.  If not at beg/end resp, then stop
188
		 * if we hit a higher level paren, else skip an atom,
189
		 * counting it unless pastatom.
190
		 */
191
		while (cnt > 0) {
192
			c = *wcursor;
193
			if (dir < 0 && c == ')' || dir > 0 && c == '(') {
194
				if (!lskipbal("()"))
195
					goto ret;
196
				/*
197
 				 * Unless this is the last time going
198
				 * backwards, skip past the matching paren
199
				 * so we don't think it is a higher level paren.
200
				 */
201
				if (dir < 0 && cnt == 1)
202
					goto ret;
203
				if (!lnext() || !ltosolid())
204
					goto ret;
205
				--cnt;
206
			} else if (dir < 0 && c == '(' || dir > 0 && c == ')')
207
				/* Found a higher level paren */
208
				goto ret;
209
			else {
210
				if (!lskipatom())
211
					goto ret;
212
				if (!pastatom)
213
					--cnt;
214
			}
215
		}
216
	}
217
#endif
218
ret:
219
	strcLIN(save);
220
	return (rc);
221
}
222
 
223
/*
224
 * Is this the end of a sentence?
225
 */
226
endsent(pastatom)
227
	bool pastatom;
228
{
229
	register char *cp = wcursor;
230
	register int c, d;
231
 
232
	/*
233
	 * If this is the beginning of a line, then
234
	 * check for the end of a paragraph or section.
235
	 */
236
	if (cp == linebuf)
237
		return (endPS());
238
 
239
	/*
240
	 * Sentences end with . ! ? not at the beginning
241
	 * of the line, and must be either at the end of the line,
242
	 * or followed by 2 spaces.  Any number of intervening ) ] ' "
243
	 * characters are allowed.
244
	 */
245
	if (!any(c = *cp, ".!?"))
246
		goto tryps;
247
	do
248
		if ((d = *++cp) == 0)
249
			return (1);
250
	while (any(d, ")]'"));
251
	if (*cp == 0 || *cp++ == ' ' && *cp == ' ')
252
		return (1);
253
tryps:
254
	if (cp[1] == 0)
255
		return (endPS());
256
	return (0);
257
}
258
 
259
/*
260
 * End of paragraphs/sections are respective
261
 * macros as well as blank lines and form feeds.
262
 */
263
endPS()
264
{
265
 
266
	return (linebuf[0] == 0 ||
267
		isa(svalue(PARAGRAPHS)) || isa(svalue(SECTIONS)));
268
 
269
}
270
 
271
#ifdef LISPCODE
272
lindent(addr)
273
	line *addr;
274
{
275
	register int i;
276
	char *swcurs = wcursor;
277
	line *swdot = wdot;
278
 
279
again:
280
	if (addr > one) {
281
		register char *cp;
282
		register int cnt = 0;
283
 
284
		addr--;
118 7u83 285
		ex_getline(*addr);
105 7u83 286
		for (cp = linebuf; *cp; cp++)
287
			if (*cp == '(')
288
				cnt++;
289
			else if (*cp == ')')
290
				cnt--;
291
		cp = vpastwh(linebuf);
292
		if (*cp == 0)
293
			goto again;
294
		if (cnt == 0)
295
			return (whitecnt(linebuf));
296
		addr++;
297
	}
298
	wcursor = linebuf;
299
	linebuf[0] = 0;
300
	wdot = addr;
301
	dir = -1;
302
	llimit = one;
303
	lf = lindent;
304
	if (!lskipbal("()"))
305
		i = 0;
306
	else if (wcursor == linebuf)
307
		i = 2;
308
	else {
309
		register char *wp = wcursor;
310
 
311
		dir = 1;
312
		llimit = wdot;
313
		if (!lnext() || !ltosolid() || !lskipatom()) {
314
			wcursor = wp;
315
			i = 1;
316
		} else
317
			i = 0;
318
		i += column(wcursor) - 1;
319
		if (!inopen)
320
			i--;
321
	}
322
	wdot = swdot;
323
	wcursor = swcurs;
324
	return (i);
325
}
326
#endif
327
 
328
lmatchp(addr)
329
	line *addr;
330
{
331
	register int i;
332
	register char *parens, *cp;
333
 
334
	for (cp = cursor; !any(*cp, "({[)}]");)
335
		if (*cp++ == 0)
336
			return (0);
337
	lf = 0;
338
	parens = any(*cp, "()") ? "()" : any(*cp, "[]") ? "[]" : "{}";
339
	if (*cp == parens[1]) {
340
		dir = -1;
341
		llimit = one;
342
	} else {
343
		dir = 1;
344
		llimit = dol;
345
	}
346
	if (addr)
347
		llimit = addr;
348
	if (splitw)
349
		llimit = dot;
350
	wcursor = cp;
351
	wdot = dot;
352
	i = lskipbal(parens);
353
	return (i);
354
}
355
 
356
lsmatch(cp)
357
	char *cp;
358
{
359
	char save[LBSIZE];
360
	register char *sp = save;
361
	register char *scurs = cursor;
362
 
363
	wcursor = cp;
364
	strcpy(sp, linebuf);
365
	*wcursor = 0;
366
	strcpy(cursor, genbuf);
367
	cursor = strend(linebuf) - 1;
368
	if (lmatchp(dot - vcline)) {
369
		register int i = insmode;
370
		register int c = outcol;
371
		register int l = outline;
372
 
373
		if (!MI)
374
			endim();
375
		vgoto(splitw ? WECHO : LINE(wdot - llimit), column(wcursor) - 1);
376
		flush();
377
#ifndef	__linux__
378
		sleep(1);
379
#else
380
		usleep(500000);
381
#endif
382
		vgoto(l, c);
383
		if (i)
384
			goim();
385
	}
386
	else {
387
		strcLIN(sp);
388
		strcpy(scurs, genbuf);
389
		if (!lmatchp((line *) 0))
390
			beep();
391
	}
392
	strcLIN(sp);
393
	wdot = 0;
394
	wcursor = 0;
395
	cursor = scurs;
396
}
397
 
398
ltosolid()
399
{
400
 
401
	return (ltosol1("()"));
402
}
403
 
404
ltosol1(parens)
405
	register char *parens;
406
{
407
	register char *cp;
408
 
409
	if (*parens && !*wcursor && !lnext())
410
		return (0);
411
	while (isspace(*wcursor) || (*wcursor == 0 && *parens))
412
		if (!lnext())
413
			return (0);
414
	if (any(*wcursor, parens) || dir > 0)
415
		return (1);
416
	for (cp = wcursor; cp > linebuf; cp--)
417
		if (isspace(cp[-1]) || any(cp[-1], parens))
418
			break;
419
	wcursor = cp;
420
	return (1);
421
}
422
 
423
lskipbal(parens)
424
	register char *parens;
425
{
426
	register int level = dir;
427
	register int c;
428
 
429
	do {
430
		if (!lnext()) {
431
			wdot = NOLINE;
432
			return (0);
433
		}
434
		c = *wcursor;
435
		if (c == parens[1])
436
			level--;
437
		else if (c == parens[0])
438
			level++;
439
	} while (level);
440
	return (1);
441
}
442
 
443
lskipatom()
444
{
445
 
446
	return (lskipa1("()"));
447
}
448
 
449
lskipa1(parens)
450
	register char *parens;
451
{
452
	register int c;
453
 
454
	for (;;) {
455
		if (dir < 0 && wcursor == linebuf) {
456
			if (!lnext())
457
				return (0);
458
			break;
459
		}
460
		c = *wcursor;
461
		if (c && (isspace(c) || any(c, parens)))
462
			break;
463
		if (!lnext())
464
			return (0);
465
		if (dir > 0 && wcursor == linebuf)
466
			break;
467
	}
468
	return (ltosol1(parens));
469
}
470
 
471
lnext()
472
{
473
 
474
	if (dir > 0) {
475
		if (*wcursor)
476
			wcursor++;
477
		if (*wcursor)
478
			return (1);
479
		if (wdot >= llimit) {
480
			if (lf == vmove && wcursor > linebuf)
481
				wcursor--;
482
			return (0);
483
		}
484
		wdot++;
118 7u83 485
		ex_getline(*wdot);
105 7u83 486
		wcursor = linebuf;
487
		return (1);
488
	} else {
489
		--wcursor;
490
		if (wcursor >= linebuf)
491
			return (1);
492
#ifdef LISPCODE
493
		if (lf == lindent && linebuf[0] == '(')
494
			llimit = wdot;
495
#endif
496
		if (wdot <= llimit) {
497
			wcursor = linebuf;
498
			return (0);
499
		}
500
		wdot--;
118 7u83 501
		ex_getline(*wdot);
105 7u83 502
		wcursor = linebuf[0] == 0 ? linebuf : strend(linebuf) - 1;
503
		return (1);
504
	}
505
}
506
 
507
lbrack(c, f)
508
	register int c;
509
	int (*f)();
510
{
511
	register line *addr;
512
 
513
	addr = dot;
514
	for (;;) {
515
		addr += dir;
516
		if (addr < one || addr > dol) {
517
			addr -= dir;
518
			break;
519
		}
118 7u83 520
		ex_getline(*addr);
105 7u83 521
		if (linebuf[0] == '{' ||
522
#ifdef LISPCODE
523
		    value(LISP) && linebuf[0] == '(' ||
524
#endif
525
		    isa(svalue(SECTIONS))) {
526
			if (c == ']' && f != vmove) {
527
				addr--;
118 7u83 528
				ex_getline(*addr);
105 7u83 529
			}
530
			break;
531
		}
532
		if (c == ']' && f != vmove && linebuf[0] == '}')
533
			break;
534
	}
535
	if (addr == dot)
536
		return (0);
537
	if (f != vmove)
538
		wcursor = c == ']' ? strend(linebuf) : linebuf;
539
	else
540
		wcursor = 0;
541
	wdot = addr;
542
	vmoving = 0;
543
	return (1);
544
}
545
 
546
isa(cp)
547
	register char *cp;
548
{
549
 
550
	if (linebuf[0] != '.')
551
		return (0);
552
	for (; cp[0] && cp[1]; cp += 2)
553
		if (linebuf[1] == cp[0]) {
554
			if (linebuf[2] == cp[1])
555
				return (1);
556
			if (linebuf[2] == 0 && cp[1] == ' ')
557
				return (1);
558
		}
559
	return (0);
560
}