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