~mirabilos/jupp/trunk

576 by tg
merge fixes from gitlab branch; highlights:
1
#define JUPP_IS_COPYRIGHT_C_BY "2018 mirabilos"
177 by tg
bump
2
207 by tg
use less (slightly different) copies of licences, and allow (even static) linking with an {,L}GPLv[23]{,+} libc/libtermcap/libselinux/…
3
/*-
4
 * Copyright (c) 2004ff. Thorsten Glaser
5
 * Copyright (C) 1992 Joseph H. Allen
6
 *
7
 * This file is part of "jupp", a variant of Joe's Own Editor "JOE".
8
 *
9
 * jupp is free software; you can redistribute and/or modify it, deal
10
 * in the work, etc. under the terms of the GNU General Public Licen-
11
 * se, version 1 (of February 1989) as published by the Free Software
12
 * Foundation, reproduced in the file COPYING in the jupp source code
13
 * distribution. If jupp is combined with other independent work, for
14
 * example libraries or when using crunchgen, into a combined binary,
15
 * that may be conveyed under any version of the GPL, as published by
16
 * the Free Software Foundation, and any compatible licence permitted
328 by tg
document better the library exception for later GPL versions
17
 * by any version of the GPL, as above.
207 by tg
use less (slightly different) copies of licences, and allow (even static) linking with an {,L}GPLv[23]{,+} libc/libtermcap/libselinux/…
18
 *
19
 * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
20
 * the utmost extent permitted by applicable law, neither express nor
21
 * implied; without malicious intent or gross negligence. In no event
22
 * may a licensor, author or contributor be held liable for indirect,
23
 * direct, other damage, loss, or other issues arising in any way out
24
 * of dealing in the work, even if advised of the possibility of such
25
 * damage or existence of a defect, except proven that it results out
26
 * of said person's immediate fault when using the work as intended.
27
 *-
28
 * Editor startup and main edit loop
1 by tg
Initial revision
29
 */
207 by tg
use less (slightly different) copies of licences, and allow (even static) linking with an {,L}GPLv[23]{,+} libc/libtermcap/libselinux/…
30
473 by tg
overhaul the way includes work; give jupp proper RCS IDs
31
#define EXTERN
1 by tg
Initial revision
32
#include "config.h"
33
#include "types.h"
34
591 by tg
redo dynamic string memory foo to get rid of those ugly casts
35
__RCSID("$MirOS: contrib/code/jupp/main.c,v 1.43 2018/01/07 20:32:46 tg Exp $");
473 by tg
overhaul the way includes work; give jupp proper RCS IDs
36
1 by tg
Initial revision
37
#include <fcntl.h>
38
#include <string.h>
39
#include <stdlib.h>
443 by tg
make “find … | xargs jupp” work in the absence of BSD xargs -o (e.g. GNU)
40
#include <unistd.h>
1 by tg
Initial revision
41
42
#include "b.h"
43
#include "help.h"
44
#include "kbd.h"
45
#include "macro.h"
521 by tg
lots of fixes related to prototyping
46
#include "main.h"
1 by tg
Initial revision
47
#include "path.h"
48
#include "rc.h"
49
#include "scrn.h"
50
#include "termcap.h"
51
#include "tw.h"
52
#include "vfile.h"
53
#include "vs.h"
54
#include "w.h"
55
#include "charmap.h"
56
#include "syntax.h"
502 by tg
missing header
57
#include "utils.h"
1 by tg
Initial revision
58
521 by tg
lots of fixes related to prototyping
59
extern int mid, dspasis, pgamnt, nobackups, lightoff, exask, lines, columns, dopadding, marking, dobeep;
1 by tg
Initial revision
60
61
extern int idleout;		/* Clear to use /dev/tty for screen */
62
extern unsigned char *joeterm;
63
int help = 0;			/* Set to have help on when starting */
64
int nonotice = 0;		/* Set to prevent copyright notice */
65
int orphan = 0;
66
unsigned char *exmsg = NULL;		/* Message to display when exiting the editor */
67
68
SCREEN *maint;			/* Main edit screen */
69
251 by tg
some clang-3.2/scan-build work; also checked against gcc-4.7, gcc-4.8 and
70
const char null[] = "";
71
408 by tg
add -CYGhack command line option; use it in right-click menu…
72
#ifdef __CYGWIN__
411 by tg
consolidate anything using <windows.h> into one .c file existing precisely for that purpose
73
extern unsigned char *cygwin32_cmdline(void);
408 by tg
add -CYGhack command line option; use it in right-click menu…
74
#endif
75
1 by tg
Initial revision
76
/* Make windows follow cursor */
77
78
void dofollows(void)
79
{
80
	W *w = maint->curwin;
81
82
	do {
532 by tg
feeble first attempt at using a union to break up the UB in the polymorphism
83
		if (w->y != -1 && w->watom->follow && w->object.base)
1 by tg
Initial revision
84
			w->watom->follow(w->object);
85
		w = (W *) (w->link.next);
86
	} while (w != maint->curwin);
87
}
88
89
/* Update screen */
90
91
int dostaupd = 1;
92
extern int staupd;
93
94
void edupd(int flg)
95
{
96
	W *w;
97
	int wid, hei;
98
99
	if (dostaupd) {
100
		staupd = 1;
101
		dostaupd = 0;
102
	}
103
	ttgtsz(&wid, &hei);
104
	if ((wid >= 2 && wid != maint->w) || (hei >= 1 && hei != maint->h)) {
105
		nresize(maint->t, wid, hei);
106
		sresize(maint);
107
	}
108
	dofollows();
109
	ttflsh();
110
	nscroll(maint->t);
111
	help_display(maint);
112
	w = maint->curwin;
113
	do {
114
		if (w->y != -1) {
532 by tg
feeble first attempt at using a union to break up the UB in the polymorphism
115
			if (w->object.base && w->watom->disp)
1 by tg
Initial revision
116
				w->watom->disp(w->object, flg);
117
			msgout(w);
118
		}
119
		w = (W *) (w->link.next);
120
	} while (w != maint->curwin);
121
	cpos(maint->t, maint->curwin->x + maint->curwin->curx, maint->curwin->y + maint->curwin->cury);
122
	staupd = 0;
123
}
124
125
static int ahead = 0;
126
static int ungot = 0;
127
static int ungotc = 0;
128
129
void nungetc(int c)
130
{
131
	if (c != 'C' - '@' && c != 'M' - '@') {
132
		chmac();
133
		ungot = 1;
134
		ungotc = c;
135
	}
136
}
137
138
int edloop(int flg)
139
{
140
	int term = 0;
141
	int ret = 0;
142
143
	if (flg) {
144
		if (maint->curwin->watom->what == TYPETW)
145
			return 0;
146
		else
147
			maint->curwin->notify = &term;
148
	}
149
	while (!leave && (!flg || !term)) {
150
		MACRO *m;
151
		int c;
152
153
		if (exmsg && !flg) {
154
			vsrm(exmsg);
155
			exmsg = NULL;
156
		}
157
		edupd(1);
158
		if (!ahead && !have)
159
			ahead = 1;
160
		if (ungot) {
161
			c = ungotc;
162
			ungot = 0;
163
		} else
164
			c = ttgetc();
165
166
		if (!ahead && c == 10)
167
			c = 13;
168
		m = dokey(maint->curwin->kbd, c);
169
		if (maint->curwin->main && maint->curwin->main != maint->curwin) {
170
			int x = maint->curwin->kbd->x;
171
172
			maint->curwin->main->kbd->x = x;
173
			if (x)
174
				maint->curwin->main->kbd->seq[x - 1] = maint->curwin->kbd->seq[x - 1];
175
		}
176
		if (m)
177
			ret = exemac(m);
178
	}
179
180
	if (term == -1)
181
		return -1;
182
	else
183
		return ret;
184
}
185
186
unsigned char **mainenv;
187
442 by tg
small code reorganisation to reduce total stack (etc.) size
188
static int
189
main_init(int argc, char **argv, char **envp, SCRN **np)
1 by tg
Initial revision
190
{
191
	CAP *cap;
192
	unsigned char *s;
193
	unsigned char *run;
194
	SCRN *n;
288 by tg
fix -mold etc. when passing multiple files on the cmdline
195
	W *opened = NULL;
1 by tg
Initial revision
196
	int omid;
197
	int backopt;
198
	int c;
199
591 by tg
redo dynamic string memory foo to get rid of those ugly casts
200
	jalloc_init();
370 by tg
first cut at win32 self-relocation
201
	init_JOERC();
1 by tg
Initial revision
202
	joe_locale();
203
2 by tg
Update the non-generated files to joe-3.1jupp2
204
	mainenv = (unsigned char **)envp;
1 by tg
Initial revision
205
	run = namprt(argv[0]);
206
207
	if ((s = (unsigned char *)getenv("LINES")) != NULL)
501 by tg
first cut at getting rid of stdio: scanf half
208
		lines = ustol(s, NULL, USTOL_DEC | USTOL_EOS);
1 by tg
Initial revision
209
	if ((s = (unsigned char *)getenv("COLUMNS")) != NULL)
501 by tg
first cut at getting rid of stdio: scanf half
210
		columns = ustol(s, NULL, USTOL_DEC | USTOL_EOS);
1 by tg
Initial revision
211
	if ((s = (unsigned char *)getenv("BAUD")) != NULL)
501 by tg
first cut at getting rid of stdio: scanf half
212
		Baud = ustol(s, NULL, USTOL_DEC | USTOL_EOS);
1 by tg
Initial revision
213
	if (getenv("DOPADDING"))
214
		dopadding = 1;
215
	if (getenv("NOXON"))
216
		noxon = 1;
217
	if ((s = (unsigned char *)getenv("JOETERM")) != NULL)
218
		joeterm = s;
219
220
	if (!(cap = getcap(NULL, 9600, NULL, NULL))) {
221
		fprintf(stderr, "Couldn't load termcap/terminfo entry\n");
222
		return 1;
223
	}
224
225
	s = (unsigned char *)getenv("HOME");
226
	if (s) {
227
		s = vsncpy(NULL, 0, sz(s));
228
		s = vsncpy(sv(s), sc("/."));
229
		s = vsncpy(sv(s), sv(run));
230
		s = vsncpy(sv(s), sc("rc"));
231
		c = procrc(cap, s);
232
		if (c == 0)
233
			goto donerc;
234
		if (c == 1) {
235
			unsigned char buf[8];
236
237
			fprintf(stderr, "There were errors in '%s'.  Use it anyway?", s);
238
			fflush(stderr);
176 by tg
fixes from packages.debian.org/joe are merged; now do a warning cleanup
239
			if (fgets((char *)buf, 8, stdin) != NULL &&
545 by tg
more upper/lower tweak (single ones, ranges yet to follow)
240
			    (buf[0] | 0x20) == 'y')
1 by tg
Initial revision
241
				goto donerc;
242
		}
243
	}
244
370 by tg
first cut at win32 self-relocation
245
	if (has_JOERC) {
246
		vsrm(s);
247
		s = vsncpy(NULL, 0, sz(get_JOERC));
248
		s = vsncpy(sv(s), sv(run));
249
		s = vsncpy(sv(s), sc("rc"));
250
		c = procrc(cap, s);
251
		if (c == 0)
1 by tg
Initial revision
252
			goto donerc;
370 by tg
first cut at win32 self-relocation
253
		if (c == 1) {
254
			unsigned char buf[8];
255
256
			fprintf(stderr, "There were errors in '%s'.  Use it anyway?", s);
257
			fflush(stderr);
258
			if (fgets((char *)buf, 8, stdin) != NULL &&
545 by tg
more upper/lower tweak (single ones, ranges yet to follow)
259
			    (buf[0] | 0x20) == 'y')
370 by tg
first cut at win32 self-relocation
260
				goto donerc;
261
		}
1 by tg
Initial revision
262
	}
120 by tg
add built-in (minimal) jupprc, for stand-alone things
263
264
	/* Try built-in joerc */
265
	vsrm(s);
266
	s = vsncpy(NULL, 0, sc("*"));
267
	s = vsncpy(sv(s), sv(run));
268
	s = vsncpy(sv(s), sc("rc"));
269
	c = procrc(cap, s);
270
	if (c == 0)
271
		goto donerc;
272
	if (c == 1) {
273
		unsigned char buf[8];
274
275
		fprintf(stderr, "There were errors in '%s'.  Use it anyway?", s);
276
		fflush(stderr);
176 by tg
fixes from packages.debian.org/joe are merged; now do a warning cleanup
277
		if (fgets((char *)buf, 8, stdin) != NULL &&
545 by tg
more upper/lower tweak (single ones, ranges yet to follow)
278
		    (buf[0] | 0x20) == 'y')
120 by tg
add built-in (minimal) jupprc, for stand-alone things
279
			goto donerc;
280
	}
1 by tg
Initial revision
281
282
	fprintf(stderr, "Couldn't open '%s'\n", s);
283
	return 1;
284
542 by tg
label indent; small tweaks while here
285
 donerc:
1 by tg
Initial revision
286
	help_init(s);
287
	for (c = 1; argv[c]; ++c) {
288
		if (argv[c][0] == '-') {
408 by tg
add -CYGhack command line option; use it in right-click menu…
289
#ifdef __CYGWIN__
290
			if (!strcmp(argv[c], "-CYGhack")) {
291
				s = cygwin32_cmdline();
292
				s = strstr(s, "-CYGhack");
293
				if (s) {
294
					s += /* strlen("-CYGhack") */ 8;
295
					while (*s == ' ' || *s == '\t')
296
						++s;
297
					argv[c] = s;
298
					argv[c + 1] = NULL;
299
					break;
300
				}
301
			}
302
#endif
1 by tg
Initial revision
303
			if (argv[c][1])
304
				switch (glopt(argv[c] + 1, argv[c + 1], NULL, 1)) {
305
				case 0:
306
					fprintf(stderr, "Unknown option '%s'\n", argv[c]);
307
					break;
308
				case 1:
309
					break;
310
				case 2:
311
					++c;
312
					break;
313
			} else
314
				idleout = 0;
315
		}
316
	}
317
443 by tg
make “find … | xargs jupp” work in the absence of BSD xargs -o (e.g. GNU)
318
#if HAVE_ISATTY
319
	if (idleout && (!isatty(0) || !isatty(1)))
320
		idleout = 0;
321
#endif
322
1 by tg
Initial revision
323
	if (!(n = nopen(cap)))
324
		return 1;
325
	maint = screate(n);
326
	vmem = vtmp();
327
328
	for (c = 1, backopt = 0; argv[c]; ++c)
329
		if (argv[c][0] == '+' && argv[c][1]) {
330
			if (!backopt)
331
				backopt = c;
332
		} else if (argv[c][0] == '-' && argv[c][1]) {
333
			if (!backopt)
334
				backopt = c;
335
			if (glopt(argv[c] + 1, argv[c + 1], NULL, 0) == 2)
336
				++c;
337
		} else {
338
			B *b = bfind(argv[c]);
339
			BW *bw = NULL;
340
			int er = error;
341
342
			if (!orphan || !opened) {
343
				bw = wmktw(maint, b);
344
				if (er)
345
					msgnwt(bw->parent, msgs[-er]);
346
			} else
347
				b->orphan = 1;
348
			if (bw) {
349
				long lnum = 0;
350
351
				bw->o.readonly = bw->b->rdonly;
352
				if (backopt) {
189 by tg
Unbreak passing -keymap on the command line
353
					unsigned char *old_context;
354
355
					old_context = bw->o.context;
1 by tg
Initial revision
356
					while (backopt != c) {
357
						if (argv[backopt][0] == '+') {
501 by tg
first cut at getting rid of stdio: scanf half
358
							lnum = ustol(argv[backopt] + 1, NULL, USTOL_TRIM | USTOL_EOS);
1 by tg
Initial revision
359
							++backopt;
360
						} else {
361
							if (glopt(argv[backopt] + 1, argv[backopt + 1], &bw->o, 0) == 2)
362
								backopt += 2;
363
							else
364
								backopt += 1;
365
							lazy_opts(&bw->o);
366
						}
367
					}
189 by tg
Unbreak passing -keymap on the command line
368
					if (old_context != bw->o.context) {
369
						/* update keymap */
370
						rmkbd(bw->parent->kbd);
371
						bw->parent->kbd =
263 by tg
the long-awaited bracketed paste mode, auto-enabled for TERM=xterm-xfree86 even (but not within GNU screen, see TODO for explanation)
372
						    mkkbd(kmap_getcontext(bw->o.context, 1));
189 by tg
Unbreak passing -keymap on the command line
373
					}
1 by tg
Initial revision
374
				}
375
				bw->b->o = bw->o;
376
				bw->b->rdonly = bw->o.readonly;
288 by tg
fix -mold etc. when passing multiple files on the cmdline
377
				if (!opened || opened == (void *)&opened)
378
					opened = bw->parent;
379
				maint->curwin = bw->parent;
1 by tg
Initial revision
380
				if (er == -1 && bw->o.mnew)
381
					exemac(bw->o.mnew);
382
				if (er == 0 && bw->o.mold)
383
					exemac(bw->o.mold);
288 by tg
fix -mold etc. when passing multiple files on the cmdline
384
				maint->curwin = opened;
1 by tg
Initial revision
385
				if (lnum > 0)
386
					pline(bw->cursor, lnum - 1);
387
			}
288 by tg
fix -mold etc. when passing multiple files on the cmdline
388
			if (!opened)
389
				opened = (void *)&opened;
1 by tg
Initial revision
390
			backopt = 0;
391
		}
392
288 by tg
fix -mold etc. when passing multiple files on the cmdline
393
	maint->curwin = opened == (void *)&opened ? NULL : opened;
1 by tg
Initial revision
394
	if (opened) {
395
		wshowall(maint);
396
		omid = mid;
397
		mid = 1;
398
		dofollows();
399
		mid = omid;
400
	} else {
576 by tg
merge fixes from gitlab branch; highlights:
401
		BW *bw = wmktw(maint, bfind(UC ""));
1 by tg
Initial revision
402
403
		if (bw->o.mnew)
404
			exemac(bw->o.mnew);
405
	}
406
	maint->curwin = maint->topwin;
407
408
	if (help) {
409
		help_on(maint);
410
	}
411
	if (!nonotice) {
579 by tg
if -hmsg begins with exactly \i, do not invert it and the preceding space
412
		int uninvert = fdefault.hmsg &&
413
		    fdefault.hmsg[0] == '\\' &&
414
		    fdefault.hmsg[1] == 'i';
415
416
		joe_snprintf_5((char *)msgbuf, JOE_MSGBUFSIZE,
169 by tg
dynamic help string needed, e.g. jpico has ^G for help…
417
		    "\\i[ Joe's Own Editor v" VERSION
579 by tg
if -hmsg begins with exactly \i, do not invert it and the preceding space
418
		    " | %s | %s " JUPP_IS_COPYRIGHT_C_BY " ]%s%s%s",
169 by tg
dynamic help string needed, e.g. jpico has ^G for help…
419
		    locale_map->name, locale_map->type ? "©" : "(c)",
579 by tg
if -hmsg begins with exactly \i, do not invert it and the preceding space
420
		    uninvert ? "\\i " : fdefault.hmsg ? " " : "",
421
		    uninvert ? fdefault.hmsg + 2 : fdefault.hmsg ?
422
		    fdefault.hmsg : "", uninvert ? "" : "\\i");
532 by tg
feeble first attempt at using a union to break up the UB in the polymorphism
423
		msgnw(lastw(maint)->object.base->parent, msgbuf);
1 by tg
Initial revision
424
	}
425
442 by tg
small code reorganisation to reduce total stack (etc.) size
426
	*np = n;
427
	return 0;
428
}
429
445 by tg
new command abendjoe to exit 1
430
int main_rv;
431
442 by tg
small code reorganisation to reduce total stack (etc.) size
432
int
433
main(int argc, char **argv, char **envp)
434
{
435
	SCRN *n;
436
445 by tg
new command abendjoe to exit 1
437
	if ((main_rv = main_init(argc, argv, envp, &n)))
438
		return (main_rv);
442 by tg
small code reorganisation to reduce total stack (etc.) size
439
1 by tg
Initial revision
440
	edloop(0);
441
	vclose(vmem);
442
	nclose(n);
443
	if (exmsg)
444
		fprintf(stderr, "\n%s\n", exmsg);
445 by tg
new command abendjoe to exit 1
445
	return (main_rv);
1 by tg
Initial revision
446
}