joe-3.1jupp31.tgz (die zweite Klappe…)
[alioth/jupp.git] / main.c
1 /* $MirOS: contrib/code/jupp/main.c,v 1.31 2017/08/08 21:39:28 tg Exp $ */
2
3 #define JUPP_IS_COPYRIGHT_C_BY "2017 mirabilos"
4
5 /*-
6  * Copyright (c) 2004ff. Thorsten Glaser
7  * Copyright (C) 1992 Joseph H. Allen
8  *
9  * This file is part of "jupp", a variant of Joe's Own Editor "JOE".
10  *
11  * jupp is free software; you can redistribute and/or modify it, deal
12  * in the work, etc. under the terms of the GNU General Public Licen-
13  * se, version 1 (of February 1989) as published by the Free Software
14  * Foundation, reproduced in the file COPYING in the jupp source code
15  * distribution. If jupp is combined with other independent work, for
16  * example libraries or when using crunchgen, into a combined binary,
17  * that may be conveyed under any version of the GPL, as published by
18  * the Free Software Foundation, and any compatible licence permitted
19  * by any version of the GPL, as above.
20  *
21  * This work is provided "AS IS" and WITHOUT WARRANTY of any kind, to
22  * the utmost extent permitted by applicable law, neither express nor
23  * implied; without malicious intent or gross negligence. In no event
24  * may a licensor, author or contributor be held liable for indirect,
25  * direct, other damage, loss, or other issues arising in any way out
26  * of dealing in the work, even if advised of the possibility of such
27  * damage or existence of a defect, except proven that it results out
28  * of said person's immediate fault when using the work as intended.
29  *-
30  * Editor startup and main edit loop
31  */
32
33 #include "config.h"
34 #include "types.h"
35
36 #include <stdio.h>
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 "utf8.h"
57 #include "charmap.h"
58 #include "syntax.h"
59
60 extern int mid, dspasis, help, pgamnt, nobackups, lightoff, exask, lines, columns, dopadding, marking, dobeep;
61
62 extern int idleout;             /* Clear to use /dev/tty for screen */
63 extern unsigned char *joeterm;
64 int help = 0;                   /* Set to have help on when starting */
65 int nonotice = 0;               /* Set to prevent copyright notice */
66 int orphan = 0;
67 unsigned char *exmsg = NULL;            /* Message to display when exiting the editor */
68
69 SCREEN *maint;                  /* Main edit screen */
70
71 const char null[] = "";
72
73 #ifdef __CYGWIN__
74 extern unsigned char *cygwin32_cmdline(void);
75 #endif
76
77 /* Make windows follow cursor */
78
79 void dofollows(void)
80 {
81         W *w = maint->curwin;
82
83         do {
84                 if (w->y != -1 && w->watom->follow && w->object)
85                         w->watom->follow(w->object);
86                 w = (W *) (w->link.next);
87         } while (w != maint->curwin);
88 }
89
90 /* Update screen */
91
92 int dostaupd = 1;
93 extern int staupd;
94
95 void edupd(int flg)
96 {
97         W *w;
98         int wid, hei;
99
100         if (dostaupd) {
101                 staupd = 1;
102                 dostaupd = 0;
103         }
104         ttgtsz(&wid, &hei);
105         if ((wid >= 2 && wid != maint->w) || (hei >= 1 && hei != maint->h)) {
106                 nresize(maint->t, wid, hei);
107                 sresize(maint);
108         }
109         dofollows();
110         ttflsh();
111         nscroll(maint->t);
112         help_display(maint);
113         w = maint->curwin;
114         do {
115                 if (w->y != -1) {
116                         if (w->object && w->watom->disp)
117                                 w->watom->disp(w->object, flg);
118                         msgout(w);
119                 }
120                 w = (W *) (w->link.next);
121         } while (w != maint->curwin);
122         cpos(maint->t, maint->curwin->x + maint->curwin->curx, maint->curwin->y + maint->curwin->cury);
123         staupd = 0;
124 }
125
126 static int ahead = 0;
127 static int ungot = 0;
128 static int ungotc = 0;
129
130 void nungetc(int c)
131 {
132         if (c != 'C' - '@' && c != 'M' - '@') {
133                 chmac();
134                 ungot = 1;
135                 ungotc = c;
136         }
137 }
138
139 int edloop(int flg)
140 {
141         int term = 0;
142         int ret = 0;
143
144         if (flg) {
145                 if (maint->curwin->watom->what == TYPETW)
146                         return 0;
147                 else
148                         maint->curwin->notify = &term;
149         }
150         while (!leave && (!flg || !term)) {
151                 MACRO *m;
152                 int c;
153
154                 if (exmsg && !flg) {
155                         vsrm(exmsg);
156                         exmsg = NULL;
157                 }
158                 edupd(1);
159                 if (!ahead && !have)
160                         ahead = 1;
161                 if (ungot) {
162                         c = ungotc;
163                         ungot = 0;
164                 } else
165                         c = ttgetc();
166
167                 if (!ahead && c == 10)
168                         c = 13;
169                 m = dokey(maint->curwin->kbd, c);
170                 if (maint->curwin->main && maint->curwin->main != maint->curwin) {
171                         int x = maint->curwin->kbd->x;
172
173                         maint->curwin->main->kbd->x = x;
174                         if (x)
175                                 maint->curwin->main->kbd->seq[x - 1] = maint->curwin->kbd->seq[x - 1];
176                 }
177                 if (m)
178                         ret = exemac(m);
179         }
180
181         if (term == -1)
182                 return -1;
183         else
184                 return ret;
185 }
186
187 unsigned char **mainenv;
188
189 static int
190 main_init(int argc, char **argv, char **envp, SCRN **np)
191 {
192         CAP *cap;
193         unsigned char *s;
194         unsigned char *run;
195         SCRN *n;
196         W *opened = NULL;
197         int omid;
198         int backopt;
199         int c;
200
201         init_JOERC();
202         joe_locale();
203
204         mainenv = (unsigned char **)envp;
205         run = namprt(argv[0]);
206
207         if ((s = (unsigned char *)getenv("LINES")) != NULL)
208                 sscanf((char *)s, "%d", &lines);
209         if ((s = (unsigned char *)getenv("COLUMNS")) != NULL)
210                 sscanf((char *)s, "%d", &columns);
211         if ((s = (unsigned char *)getenv("BAUD")) != NULL)
212                 sscanf((char *)s, "%u", &Baud);
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);
239                         if (fgets((char *)buf, 8, stdin) != NULL &&
240                             (buf[0] == 'y' || buf[0] == 'Y'))
241                                 goto donerc;
242                 }
243         }
244
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)
252                         goto donerc;
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 &&
259                             (buf[0] == 'y' || buf[0] == 'Y'))
260                                 goto donerc;
261                 }
262         }
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);
277                 if (fgets((char *)buf, 8, stdin) != NULL &&
278                     (buf[0] == 'y' || buf[0] == 'Y'))
279                         goto donerc;
280         }
281
282         fprintf(stderr, "Couldn't open '%s'\n", s);
283         return 1;
284
285       donerc:
286         help_init(s);
287         for (c = 1; argv[c]; ++c) {
288                 if (argv[c][0] == '-') {
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
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
318 #if HAVE_ISATTY
319         if (idleout && (!isatty(0) || !isatty(1)))
320                 idleout = 0;
321 #endif
322
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) {
353                                         unsigned char *old_context;
354
355                                         old_context = bw->o.context;
356                                         while (backopt != c) {
357                                                 if (argv[backopt][0] == '+') {
358                                                         sscanf((char *)(argv[backopt] + 1), "%ld", &lnum);
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                                         }
368                                         if (old_context != bw->o.context) {
369                                                 /* update keymap */
370                                                 rmkbd(bw->parent->kbd);
371                                                 bw->parent->kbd =
372                                                     mkkbd(kmap_getcontext(bw->o.context, 1));
373                                         }
374                                 }
375                                 bw->b->o = bw->o;
376                                 bw->b->rdonly = bw->o.readonly;
377                                 if (!opened || opened == (void *)&opened)
378                                         opened = bw->parent;
379                                 maint->curwin = bw->parent;
380                                 if (er == -1 && bw->o.mnew)
381                                         exemac(bw->o.mnew);
382                                 if (er == 0 && bw->o.mold)
383                                         exemac(bw->o.mold);
384                                 maint->curwin = opened;
385                                 if (lnum > 0)
386                                         pline(bw->cursor, lnum - 1);
387                         }
388                         if (!opened)
389                                 opened = (void *)&opened;
390                         backopt = 0;
391                 }
392
393         maint->curwin = opened == (void *)&opened ? NULL : opened;
394         if (opened) {
395                 wshowall(maint);
396                 omid = mid;
397                 mid = 1;
398                 dofollows();
399                 mid = omid;
400         } else {
401                 BW *bw = wmktw(maint, bfind(US ""));
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) {
412                 joe_snprintf_4((char *)msgbuf,JOE_MSGBUFSIZE,
413                     "\\i[ Joe's Own Editor v" VERSION
414                     " | %s | %s " JUPP_IS_COPYRIGHT_C_BY " ]%s%s\\i",
415                     locale_map->name, locale_map->type ? "©" : "(c)",
416                     fdefault.hmsg ? " " : "",
417                     fdefault.hmsg ? fdefault.hmsg : "");
418                 msgnw(((BASE *)lastw(maint)->object)->parent, msgbuf);
419         }
420
421         *np = n;
422         return 0;
423 }
424
425 int main_rv;
426
427 int
428 main(int argc, char **argv, char **envp)
429 {
430         SCRN *n;
431
432         if ((main_rv = main_init(argc, argv, envp, &n)))
433                 return (main_rv);
434
435         edloop(0);
436         vclose(vmem);
437         nclose(n);
438         if (exmsg)
439                 fprintf(stderr, "\n%s\n", exmsg);
440         return (main_rv);
441 }