1 /* @(#)cmds.c	1.46 21/07/05 Copyright 1984-2021 J. Schilling */
2 #include <schily/mconfig.h>
3 #ifndef lint
4 static	UConst char sccsid[] =
5 	"@(#)cmds.c	1.46 21/07/05 Copyright 1984-2021 J. Schilling";
6 #endif
7 /*
8  *	Commands that deal with various things that do not apply to other
9  *	systematic categories.
10  *
11  *	Copyright (c) 1984-2021 J. Schilling
12  */
13 /*
14  * The contents of this file are subject to the terms of the
15  * Common Development and Distribution License, Version 1.0 only
16  * (the "License").  You may not use this file except in compliance
17  * with the License.
18  *
19  * See the file CDDL.Schily.txt in this distribution for details.
20  * A copy of the CDDL is also available via the Internet at
21  * http://www.opensource.org/licenses/cddl1.txt
22  *
23  * When distributing Covered Code, include this CDDL HEADER in each
24  * file and include the License file CDDL.Schily.txt from this distribution.
25  */
26 
27 #include "ved.h"
28 #include "terminal.h"
29 #include <schily/signal.h>
30 
31 LOCAL	BOOL	rawinput;
32 
33 EXPORT 	void	vnorm		__PR((ewin_t *wp));
34 EXPORT	void	vsnorm		__PR((ewin_t *wp));
35 EXPORT	void	vnl		__PR((ewin_t *wp));
36 EXPORT	void	vsnl		__PR((ewin_t *wp));
37 EXPORT	void	verror		__PR((ewin_t *wp));
38 EXPORT	void	modified	__PR((ewin_t *wp));
39 EXPORT	void	vmode		__PR((ewin_t *wp));
40 LOCAL	void	modemsg		__PR((ewin_t *wp, char *msg, BOOL flag));
41 LOCAL	void	modeprint	__PR((ewin_t *wp, char *msg, BOOL flag));
42 EXPORT	void	vwhere		__PR((ewin_t *wp));
43 EXPORT	void	vewhere		__PR((ewin_t *wp));
44 EXPORT	void	vswhere		__PR((ewin_t *wp));
45 EXPORT	void	vsewhere	__PR((ewin_t *wp));
46 LOCAL	epos_t	where		__PR((ewin_t *wp, epos_t loc));
47 EXPORT	void	vquote		__PR((ewin_t *wp));
48 EXPORT	void	v8cntlq		__PR((ewin_t *wp));
49 EXPORT	void	v8quote		__PR((ewin_t *wp));
50 LOCAL	int	tocntrl		__PR((int c));
51 EXPORT	void	vhex		__PR((ewin_t *wp));
52 EXPORT	void	vopen		__PR((ewin_t *wp));
53 EXPORT	void	vsopen		__PR((ewin_t *wp));
54 EXPORT	void	vhelp		__PR((ewin_t *wp));
55 LOCAL	BOOL	dowrap		__PR((ewin_t *wp, int hp));
56 
57 LOCAL BOOL
dowrap(wp,hp)58 dowrap(wp, hp)
59 	ewin_t	*wp;
60 	int	hp;
61 {
62 	register epos_t save;
63 	register ecnt_t	n;
64 		epos_t	diff = (epos_t)0;
65 
66 	if (((wp->wrapmargin && hp > (wp->llen - wp->wrapmargin)) ||
67 	    (wp->maxlinelen && hp > wp->maxlinelen))) {
68 		save = wp->dot;
69 		if ((wp->dot = revword(wp, save, (ecnt_t)1)) > revline(wp, save, (ecnt_t)1)) {
70 			update(wp);		/* update screen/cursor position */
71 			diff += wp->dot;
72 			n = wp->curnum;
73 			wp->curnum = 1;
74 			vnl(wp);
75 			wp->curnum = n;
76 			diff -= wp->dot;
77 		}
78 		wp->dot = save - diff;
79 		return (TRUE);
80 	}
81 	return (FALSE);
82 }
83 
84 /*
85  * Insert a regular character 'curnum' times, handle overstrike and autowrap
86  */
87 EXPORT void
vnorm(wp)88 vnorm(wp)
89 	ewin_t	*wp;
90 {
91 	register epos_t save;
92 	register epos_t dels;
93 	register ecnt_t	n = wp->curnum;
94 		int	hp;
95 
96 	if (wp->overstrikemode) {
97 		if ((dels = min(n, wp->eof-wp->dot)) > 0) {
98 			dispup(wp, wp->dot, wp->dot+dels);
99 			delete(wp, dels);
100 			setpos(wp);
101 			setcursor(wp);
102 		}
103 	}
104 	if (wp->lastch == '\n' && dowrap(wp, cursor.hp))
105 		update(wp);			/* update screen/cursor position */
106 
107 	save = wp->dot;
108 	if (wp->lastch == '\n' && wp->dosmode && !rawinput) {
109 		while (--n >= 0)
110 			insert(wp, UC "\r\n", 2L);	/* insert the chars into the file*/
111 	} else {
112 		while (--n >= 0)
113 			insert(wp, &wp->lastch, 1L);	/* insert the char into the file*/
114 	}
115 	dispup(wp, wp->dot, save);		/* update display with inserted chars*/
116 	hp = cursor.hp;
117 	if (wp->lastch != '\n') {		/* Cheap estimation of hp    */
118 		extern	Uchar	csize[];	/* The character sizes table */
119 
120 		if (wp->lastch == TAB) {
121 			n = wp->curnum;
122 
123 			while (--n >= 0)
124 				hp = (hp / wp->tabstop) * wp->tabstop +
125 					wp->tabstop;
126 		} else {
127 			hp += wp->curnum * csize[wp->lastch];
128 		}
129 		dowrap(wp, hp);
130 	}
131 	modified(wp);				/* display '*' in info field */
132 }
133 
134 /*
135  * Set mark, then insert a regular character 'curnum' times
136  */
137 EXPORT void
vsnorm(wp)138 vsnorm(wp)
139 	ewin_t	*wp;
140 {
141 	setmark(wp, wp->dot);
142 	vnorm(wp);
143 }
144 
145 /*
146  * Insert a linefeed character 'curnum' times, handle autoindent if necessary
147  */
148 EXPORT void
vnl(wp)149 vnl(wp)
150 	ewin_t	*wp;
151 {
152 	cpos_t		c;
153 	BOOL		save;
154 	epos_t		lbeg;
155 	epos_t		textbeg;
156 	long		indent;
157 	extern Uchar	notwhitespace[];
158 
159 	if (wp->autoindent) {
160 		c.vp = 1;
161 		c.hp = 0;
162 		lbeg = revline(wp, wp->dot, (ecnt_t)1);	/* an den Anfang der Zeile */
163 		save = wp->magic;
164 		wp->magic = TRUE;
165 		textbeg =
166 		    search(wp, lbeg, notwhitespace, strlen(C notwhitespace), 0) - 1;
167 		wp->magic = save;
168 		if (textbeg >= wp->dot) {
169 			textbeg = wp->dot;
170 			wp->dot = lbeg;
171 			update(wp);
172 			wp->lastch = '\n';
173 			vnorm(wp);
174 			wp->dot = textbeg + wp->curnum;
175 			return;
176 		}
177 /*		writeerr(wp, "%d %d %d", lbeg, textbeg, wp->dot);*/
178 		countpos(wp, lbeg, textbeg, &c);
179 		indent = c.hp;
180 		wp->lastch = '\n';
181 		vnorm(wp);
182 		update(wp);
183 		wp->lastch = '\t';
184 		wp->curnum = indent / wp->tabstop;
185 		vnorm(wp);
186 		update(wp);
187 		wp->lastch = ' ';
188 		wp->curnum = indent % wp->tabstop;
189 		vnorm(wp);
190 	} else {
191 		wp->lastch = '\n';
192 		vnorm(wp);
193 	}
194 }
195 
196 /*
197  * Set mark, then insert a linefeed character 'curnum times',
198  * handle autoindent if necessary
199  */
200 EXPORT void
vsnl(wp)201 vsnl(wp)
202 	ewin_t	*wp;
203 {
204 	setmark(wp, wp->dot);
205 	vnl(wp);
206 }
207 
208 /*
209  * Non-existant function or error condition
210  */
211 /* ARGSUSED */
212 EXPORT void
verror(wp)213 verror(wp)
214 	ewin_t	*wp;
215 {
216 	ringbell();
217 }
218 
219 /*
220  * Increment modified flag, set defaultinfo on first modification
221  */
222 EXPORT void
modified(wp)223 modified(wp)
224 	ewin_t	*wp;
225 {
226 	if (wp->modflg++ == 0)
227 		defaultinfo(wp, UC "*");
228 }
229 
230 /*
231  * Change the current modes of ved.
232  *
233  * Known modes are:
234  *	v:	Visible mode
235  *	d:	DOS mode
236  *	8:	raw8 mode
237  *	o:	Overstrike mode
238  *	r:	Reset to default mode
239  */
240 EXPORT void
vmode(wp)241 vmode(wp)
242 	ewin_t	*wp;
243 {
244 	Uchar ch;
245 
246 	writemsg(wp, "Mode?(DORV8)"); MOVE_CURSOR(wp, 0, 12); flush();
247 	ch = nigchar(wp);
248 
249 	switch (ch) {
250 
251 	case 'v':
252 	case 'V':
253 		wp->visible = !wp->visible;
254 		vredisp(wp);
255 		modemsg(wp, "Visible", wp->visible);
256 		break;
257 	case 'd':
258 	case 'D':
259 		wp->dosmode = !wp->dosmode;
260 		vredisp(wp);
261 		modemsg(wp, "DOS", wp->dosmode);
262 		break;
263 	case '8':
264 		wp->raw8 = !wp->raw8;
265 		vredisp(wp);
266 		modemsg(wp, "Raw8", wp->raw8);
267 		break;
268 	case 'o':
269 	case 'O':
270 		wp->overstrikemode = !wp->overstrikemode;
271 		modemsg(wp, "Overstrike", wp->overstrikemode);
272 		break;
273 	case 'r':
274 	case 'R':
275 		if (wp->visible) {
276 			wp->visible = FALSE;
277 			vredisp(wp);
278 		}
279 		wp->overstrikemode = FALSE;
280 		writemsg(wp, "Modes Reset");
281 		break;
282 	case '\r':
283 	case '\n':
284 		MOVE_CURSOR_ABS(wp, 1, 0);
285 		modeprint(wp, "Visible", wp->visible);
286 		modeprint(wp, "DOS", wp->dosmode);
287 		modeprint(wp, "Raw8", wp->raw8);
288 		modeprint(wp, "Overstrike", wp->overstrikemode);
289 		wait_for_confirm(wp);
290 		vredisp(wp);
291 		break;
292 	default:
293 		abortmsg(wp);
294 		break;
295 	}
296 }
297 
298 LOCAL void
modemsg(wp,msg,flag)299 modemsg(wp, msg, flag)
300 	ewin_t	*wp;
301 	char	*msg;
302 	BOOL	flag;
303 {
304 	writemsg(wp, "%s mode %s", msg, flag?"on":"off");
305 }
306 
307 LOCAL void
modeprint(wp,msg,flag)308 modeprint(wp, msg, flag)
309 	ewin_t	*wp;
310 	char	*msg;
311 	BOOL	flag;
312 {
313 	printscreen(wp, "%s mode %s\n", msg, flag?"on":"off");
314 }
315 
316 /*
317  * Count and print the number of lines from top of file to cursor
318  */
319 EXPORT void
vwhere(wp)320 vwhere(wp)
321 	ewin_t	*wp;
322 {
323 	writemsg(wp, "+Line: %lld", (Llong)where(wp, wp->dot));
324 }
325 
326 /*
327  * Count and print the number of lines from end of file to cursor
328  */
329 EXPORT void
vewhere(wp)330 vewhere(wp)
331 	ewin_t	*wp;
332 {
333 	writemsg(wp, "-Line: %lld", (Llong)(where(wp, wp->eof) - where(wp, wp->dot) + 1));
334 }
335 
336 /*
337  * Count and print the number of lines from top of file to mark
338  */
339 EXPORT void
vswhere(wp)340 vswhere(wp)
341 	ewin_t	*wp;
342 {
343 	if (wp->markvalid)
344 		writemsg(wp, "+Line: %lld", (Llong)where(wp, wp->mark));
345 	else
346 		nomarkmsg(wp);
347 }
348 
349 /*
350  * Count and print the number of lines from end of file to mark
351  */
352 EXPORT void
vsewhere(wp)353 vsewhere(wp)
354 	ewin_t	*wp;
355 {
356 	if (wp->markvalid)
357 		writemsg(wp, "-Line: %lld", (Llong)(where(wp, wp->eof) - where(wp, wp->mark) + 1));
358 	else
359 		nomarkmsg(wp);
360 }
361 
362 /*
363  * Count the number of lines from top of file to location
364  */
365 LOCAL epos_t
where(wp,loc)366 where(wp, loc)
367 		ewin_t	*wp;
368 	register epos_t loc;
369 {
370 	register epos_t newdot = (epos_t)0;
371 	register epos_t	line = 0;
372 
373 	while (newdot <= loc) {
374 		line++;
375 		if ((newdot = search(wp, newdot, UC "\n", 1, 0)) > wp->eof) {
376 			newdot = wp->eof;
377 			break;
378 		}
379 	}
380 	return (line);
381 }
382 
383 /*
384  * Quote next character to control character and insert it 'curnum' times
385  */
386 EXPORT void
vquote(wp)387 vquote(wp)
388 	ewin_t	*wp;
389 {
390 	writemsg(wp, "^ Quote:");
391 	flush();
392 	wp->lastch = nigchar(wp);
393 	wp->lastch = tocntrl(wp->lastch);
394 	rawinput = TRUE;
395 	vnorm(wp);
396 	rawinput = FALSE;
397 	writemsg(wp, C NULL);
398 }
399 
400 /*
401  * Quote next character to 8 bit control character and insert it 'curnum' times
402  */
403 EXPORT void
v8cntlq(wp)404 v8cntlq(wp)
405 	ewin_t	*wp;
406 {
407 	writemsg(wp, "~^ Quote:");
408 	flush();
409 	wp->lastch = nigchar(wp);
410 	wp->lastch = tocntrl(wp->lastch);
411 	wp->lastch ^= 0200;
412 	vnorm(wp);
413 	writemsg(wp, C NULL);
414 }
415 
416 /*
417  * Quote next character to 8 bit character and insert it 'curnum' times
418  */
419 EXPORT void
v8quote(wp)420 v8quote(wp)
421 	ewin_t	*wp;
422 {
423 	writemsg(wp, "~ Quote:");
424 	flush();
425 	wp->lastch = nigchar(wp);
426 	wp->lastch ^= 0200;
427 	vnorm(wp);
428 	writemsg(wp, C NULL);
429 }
430 
431 /*
432  * Change a character into a control character
433  * XXX with the curent bindings, ved would only work in an ASCII world
434  * XXX or on a world where the low 7 bits are ASCII compatible.
435  */
436 LOCAL int
tocntrl(c)437 tocntrl(c)
438 	register Uchar c;
439 {
440 	if (c == '?')
441 		return (DEL);
442 
443 	/*
444 	 * Convert into capital letters
445 	 */
446 	if (c >= 'a' && c <= 'z')
447 		c += 'A' - 'a';
448 
449 	/*
450 	 * Change only the valid range into a control character.
451 	 */
452 	if (c >= (unsigned)'@' && c <= (unsigned)('@' + 0x1F))
453 		c &= 0x1F;
454 
455 	return (c);
456 }
457 
458 /*
459  * Quote next character from hex input and insert it 'curnum' times
460  */
461 EXPORT void
vhex(wp)462 vhex(wp)
463 	ewin_t	*wp;
464 {
465 	int	i;
466 	char	hbuf[5];
467 
468 	hbuf[0] = '0';
469 	hbuf[1] = 'x';
470 	if (getcmdline(wp, UC &hbuf[2], sizeof (hbuf) - 2, "Quote: 0x")) {
471 		if (*astoi(hbuf, &i) != '\0')
472 			writeerr(wp, "BAD ARG");
473 		else {
474 			wp->lastch = (Uchar)i;
475 			vnorm(wp);
476 		}
477 	}
478 }
479 
480 /*
481  * Insert 'curnum' newlines after the cursor, leave cursor at current position
482  * XXX is this the right way ? It is in the manual ?!?
483  */
484 EXPORT void
vopen(wp)485 vopen(wp)
486 	ewin_t	*wp;
487 {
488 	wp->lastch = '\n';
489 	vnorm(wp);
490 	wp->dot -= wp->curnum;
491 }
492 
493 /*
494  * Insert 'curnum' newlines after the cursor, leave cursor at current position,
495  * then set mark at old corsor position.
496  * XXX is this the right way ? It is in the manual ?!?
497  */
498 EXPORT void
vsopen(wp)499 vsopen(wp)
500 	ewin_t	*wp;
501 {
502 	vopen(wp);
503 	setmark(wp, wp->dot+wp->curnum);
504 }
505 
506 /*
507  * Edit vedhelp file
508  */
509 EXPORT void
vhelp(wp)510 vhelp(wp)
511 	ewin_t	*wp;
512 {
513 	if (! getcmdchar(wp, "yY", "HELP?(Y/N) "))
514 		return;
515 	if (spawncmd(wp, "ved", "-vhelp") != 0) {
516 		wait_for_confirm(wp);
517 		vredisp(wp);
518 	} else {
519 		vredisp(wp);
520 		writemsg(wp, "BACK AGAIN");
521 	}
522 }
523