we’ll need to distinguish these for sarge/etch as well
[alioth/jupp.git] / main.c
1 #define JUPP_IS_COPYRIGHT_C_BY "2017 mirabilos"
2
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
17  * by any version of the GPL, as above.
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
29  */
30
31 #define EXTERN
32 #include "config.h"
33 #include "types.h"
34
35 __RCSID("$MirOS: contrib/code/jupp/main.c,v 1.33 2017/12/02 04:32:40 tg Exp $");
36
37 #include <fcntl.h>
38 #include <string.h>
39 #ifdef HAVE_STDLIB_H
40 #include <stdlib.h>
41 #endif
42 #include <unistd.h>
43
44 #include "b.h"
45 #include "help.h"
46 #include "kbd.h"
47 #include "macro.h"
48 #include "path.h"
49 #include "rc.h"
50 #include "scrn.h"
51 #include "termcap.h"
52 #include "tw.h"
53 #include "vfile.h"
54 #include "vs.h"
55 #include "w.h"
56 #include "charmap.h"
57 #include "syntax.h"
58
59 extern int mid, dspasis, help, pgamnt, nobackups, lightoff, exask, lines, columns, dopadding, marking, dobeep;
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
70 const char null[] = "";
71
72 #ifdef __CYGWIN__
73 extern unsigned char *cygwin32_cmdline(void);
74 #endif
75
76 /* Make windows follow cursor */
77
78 void dofollows(void)
79 {
80         W *w = maint->curwin;
81
82         do {
83                 if (w->y != -1 && w->watom->follow && w->object)
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) {
115                         if (w->object && w->watom->disp)
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
188 static int
189 main_init(int argc, char **argv, char **envp, SCRN **np)
190 {
191         CAP *cap;
192         unsigned char *s;
193         unsigned char *run;
194         SCRN *n;
195         W *opened = NULL;
196         int omid;
197         int backopt;
198         int c;
199
200         init_JOERC();
201         joe_locale();
202
203         mainenv = (unsigned char **)envp;
204         run = namprt(argv[0]);
205
206         if ((s = (unsigned char *)getenv("LINES")) != NULL)
207                 sscanf((char *)s, "%d", &lines);
208         if ((s = (unsigned char *)getenv("COLUMNS")) != NULL)
209                 sscanf((char *)s, "%d", &columns);
210         if ((s = (unsigned char *)getenv("BAUD")) != NULL)
211                 sscanf((char *)s, "%u", &Baud);
212         if (getenv("DOPADDING"))
213                 dopadding = 1;
214         if (getenv("NOXON"))
215                 noxon = 1;
216         if ((s = (unsigned char *)getenv("JOETERM")) != NULL)
217                 joeterm = s;
218
219         if (!(cap = getcap(NULL, 9600, NULL, NULL))) {
220                 fprintf(stderr, "Couldn't load termcap/terminfo entry\n");
221                 return 1;
222         }
223
224         s = (unsigned char *)getenv("HOME");
225         if (s) {
226                 s = vsncpy(NULL, 0, sz(s));
227                 s = vsncpy(sv(s), sc("/."));
228                 s = vsncpy(sv(s), sv(run));
229                 s = vsncpy(sv(s), sc("rc"));
230                 c = procrc(cap, s);
231                 if (c == 0)
232                         goto donerc;
233                 if (c == 1) {
234                         unsigned char buf[8];
235
236                         fprintf(stderr, "There were errors in '%s'.  Use it anyway?", s);
237                         fflush(stderr);
238                         if (fgets((char *)buf, 8, stdin) != NULL &&
239                             (buf[0] == 'y' || buf[0] == 'Y'))
240                                 goto donerc;
241                 }
242         }
243
244         if (has_JOERC) {
245                 vsrm(s);
246                 s = vsncpy(NULL, 0, sz(get_JOERC));
247                 s = vsncpy(sv(s), sv(run));
248                 s = vsncpy(sv(s), sc("rc"));
249                 c = procrc(cap, s);
250                 if (c == 0)
251                         goto donerc;
252                 if (c == 1) {
253                         unsigned char buf[8];
254
255                         fprintf(stderr, "There were errors in '%s'.  Use it anyway?", s);
256                         fflush(stderr);
257                         if (fgets((char *)buf, 8, stdin) != NULL &&
258                             (buf[0] == 'y' || buf[0] == 'Y'))
259                                 goto donerc;
260                 }
261         }
262
263         /* Try built-in joerc */
264         vsrm(s);
265         s = vsncpy(NULL, 0, sc("*"));
266         s = vsncpy(sv(s), sv(run));
267         s = vsncpy(sv(s), sc("rc"));
268         c = procrc(cap, s);
269         if (c == 0)
270                 goto donerc;
271         if (c == 1) {
272                 unsigned char buf[8];
273
274                 fprintf(stderr, "There were errors in '%s'.  Use it anyway?", s);
275                 fflush(stderr);
276                 if (fgets((char *)buf, 8, stdin) != NULL &&
277                     (buf[0] == 'y' || buf[0] == 'Y'))
278                         goto donerc;
279         }
280
281         fprintf(stderr, "Couldn't open '%s'\n", s);
282         return 1;
283
284       donerc:
285         help_init(s);
286         for (c = 1; argv[c]; ++c) {
287                 if (argv[c][0] == '-') {
288 #ifdef __CYGWIN__
289                         if (!strcmp(argv[c], "-CYGhack")) {
290                                 s = cygwin32_cmdline();
291                                 s = strstr(s, "-CYGhack");
292                                 if (s) {
293                                         s += /* strlen("-CYGhack") */ 8;
294                                         while (*s == ' ' || *s == '\t')
295                                                 ++s;
296                                         argv[c] = s;
297                                         argv[c + 1] = NULL;
298                                         break;
299                                 }
300                         }
301 #endif
302                         if (argv[c][1])
303                                 switch (glopt(argv[c] + 1, argv[c + 1], NULL, 1)) {
304                                 case 0:
305                                         fprintf(stderr, "Unknown option '%s'\n", argv[c]);
306                                         break;
307                                 case 1:
308                                         break;
309                                 case 2:
310                                         ++c;
311                                         break;
312                         } else
313                                 idleout = 0;
314                 }
315         }
316
317 #if HAVE_ISATTY
318         if (idleout && (!isatty(0) || !isatty(1)))
319                 idleout = 0;
320 #endif
321
322         if (!(n = nopen(cap)))
323                 return 1;
324         maint = screate(n);
325         vmem = vtmp();
326
327         for (c = 1, backopt = 0; argv[c]; ++c)
328                 if (argv[c][0] == '+' && argv[c][1]) {
329                         if (!backopt)
330                                 backopt = c;
331                 } else if (argv[c][0] == '-' && argv[c][1]) {
332                         if (!backopt)
333                                 backopt = c;
334                         if (glopt(argv[c] + 1, argv[c + 1], NULL, 0) == 2)
335                                 ++c;
336                 } else {
337                         B *b = bfind(argv[c]);
338                         BW *bw = NULL;
339                         int er = error;
340
341                         if (!orphan || !opened) {
342                                 bw = wmktw(maint, b);
343                                 if (er)
344                                         msgnwt(bw->parent, msgs[-er]);
345                         } else
346                                 b->orphan = 1;
347                         if (bw) {
348                                 long lnum = 0;
349
350                                 bw->o.readonly = bw->b->rdonly;
351                                 if (backopt) {
352                                         unsigned char *old_context;
353
354                                         old_context = bw->o.context;
355                                         while (backopt != c) {
356                                                 if (argv[backopt][0] == '+') {
357                                                         sscanf((char *)(argv[backopt] + 1), "%ld", &lnum);
358                                                         ++backopt;
359                                                 } else {
360                                                         if (glopt(argv[backopt] + 1, argv[backopt + 1], &bw->o, 0) == 2)
361                                                                 backopt += 2;
362                                                         else
363                                                                 backopt += 1;
364                                                         lazy_opts(&bw->o);
365                                                 }
366                                         }
367                                         if (old_context != bw->o.context) {
368                                                 /* update keymap */
369                                                 rmkbd(bw->parent->kbd);
370                                                 bw->parent->kbd =
371                                                     mkkbd(kmap_getcontext(bw->o.context, 1));
372                                         }
373                                 }
374                                 bw->b->o = bw->o;
375                                 bw->b->rdonly = bw->o.readonly;
376                                 if (!opened || opened == (void *)&opened)
377                                         opened = bw->parent;
378                                 maint->curwin = bw->parent;
379                                 if (er == -1 && bw->o.mnew)
380                                         exemac(bw->o.mnew);
381                                 if (er == 0 && bw->o.mold)
382                                         exemac(bw->o.mold);
383                                 maint->curwin = opened;
384                                 if (lnum > 0)
385                                         pline(bw->cursor, lnum - 1);
386                         }
387                         if (!opened)
388                                 opened = (void *)&opened;
389                         backopt = 0;
390                 }
391
392         maint->curwin = opened == (void *)&opened ? NULL : opened;
393         if (opened) {
394                 wshowall(maint);
395                 omid = mid;
396                 mid = 1;
397                 dofollows();
398                 mid = omid;
399         } else {
400                 BW *bw = wmktw(maint, bfind(US ""));
401
402                 if (bw->o.mnew)
403                         exemac(bw->o.mnew);
404         }
405         maint->curwin = maint->topwin;
406
407         if (help) {
408                 help_on(maint);
409         }
410         if (!nonotice) {
411                 joe_snprintf_4((char *)msgbuf,JOE_MSGBUFSIZE,
412                     "\\i[ Joe's Own Editor v" VERSION
413                     " | %s | %s " JUPP_IS_COPYRIGHT_C_BY " ]%s%s\\i",
414                     locale_map->name, locale_map->type ? "©" : "(c)",
415                     fdefault.hmsg ? " " : "",
416                     fdefault.hmsg ? fdefault.hmsg : "");
417                 msgnw(((BASE *)lastw(maint)->object)->parent, msgbuf);
418         }
419
420         *np = n;
421         return 0;
422 }
423
424 int main_rv;
425
426 int
427 main(int argc, char **argv, char **envp)
428 {
429         SCRN *n;
430
431         if ((main_rv = main_init(argc, argv, envp, &n)))
432                 return (main_rv);
433
434         edloop(0);
435         vclose(vmem);
436         nclose(n);
437         if (exmsg)
438                 fprintf(stderr, "\n%s\n", exmsg);
439         return (main_rv);
440 }