add a CVS snapshot, to thoroughly test on the Debian side
[alioth/jupp.git] / main.c
1 /* $MirOS: contrib/code/jupp/main.c,v 1.27 2017/01/11 19:26:54 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
43 #include "b.h"
44 #include "help.h"
45 #include "kbd.h"
46 #include "macro.h"
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 "utf8.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 static 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 int main(int argc, char **argv, char **envp)
189 {
190         CAP *cap;
191         unsigned char *s;
192         unsigned char *run;
193         SCRN *n;
194         W *opened = NULL;
195         int omid;
196         int backopt;
197         int c;
198
199         init_JOERC();
200         joe_locale();
201
202         mainenv = (unsigned char **)envp;
203         run = namprt(argv[0]);
204
205         if ((s = (unsigned char *)getenv("LINES")) != NULL)
206                 sscanf((char *)s, "%d", &lines);
207         if ((s = (unsigned char *)getenv("COLUMNS")) != NULL)
208                 sscanf((char *)s, "%d", &columns);
209         if ((s = (unsigned char *)getenv("BAUD")) != NULL)
210                 sscanf((char *)s, "%u", &Baud);
211         if (getenv("DOPADDING"))
212                 dopadding = 1;
213         if (getenv("NOXON"))
214                 noxon = 1;
215         if ((s = (unsigned char *)getenv("JOETERM")) != NULL)
216                 joeterm = s;
217
218         if (!(cap = getcap(NULL, 9600, NULL, NULL))) {
219                 fprintf(stderr, "Couldn't load termcap/terminfo entry\n");
220                 return 1;
221         }
222
223         s = (unsigned char *)getenv("HOME");
224         if (s) {
225                 s = vsncpy(NULL, 0, sz(s));
226                 s = vsncpy(sv(s), sc("/."));
227                 s = vsncpy(sv(s), sv(run));
228                 s = vsncpy(sv(s), sc("rc"));
229                 c = procrc(cap, s);
230                 if (c == 0)
231                         goto donerc;
232                 if (c == 1) {
233                         unsigned char buf[8];
234
235                         fprintf(stderr, "There were errors in '%s'.  Use it anyway?", s);
236                         fflush(stderr);
237                         if (fgets((char *)buf, 8, stdin) != NULL &&
238                             (buf[0] == 'y' || buf[0] == 'Y'))
239                                 goto donerc;
240                 }
241         }
242
243         if (has_JOERC) {
244                 vsrm(s);
245                 s = vsncpy(NULL, 0, sz(get_JOERC));
246                 s = vsncpy(sv(s), sv(run));
247                 s = vsncpy(sv(s), sc("rc"));
248                 c = procrc(cap, s);
249                 if (c == 0)
250                         goto donerc;
251                 if (c == 1) {
252                         unsigned char buf[8];
253
254                         fprintf(stderr, "There were errors in '%s'.  Use it anyway?", s);
255                         fflush(stderr);
256                         if (fgets((char *)buf, 8, stdin) != NULL &&
257                             (buf[0] == 'y' || buf[0] == 'Y'))
258                                 goto donerc;
259                 }
260         }
261
262         /* Try built-in joerc */
263         vsrm(s);
264         s = vsncpy(NULL, 0, sc("*"));
265         s = vsncpy(sv(s), sv(run));
266         s = vsncpy(sv(s), sc("rc"));
267         c = procrc(cap, s);
268         if (c == 0)
269                 goto donerc;
270         if (c == 1) {
271                 unsigned char buf[8];
272
273                 fprintf(stderr, "There were errors in '%s'.  Use it anyway?", s);
274                 fflush(stderr);
275                 if (fgets((char *)buf, 8, stdin) != NULL &&
276                     (buf[0] == 'y' || buf[0] == 'Y'))
277                         goto donerc;
278         }
279
280         fprintf(stderr, "Couldn't open '%s'\n", s);
281         return 1;
282
283       donerc:
284         help_init(s);
285         for (c = 1; argv[c]; ++c) {
286                 if (argv[c][0] == '-') {
287 #ifdef __CYGWIN__
288                         if (!strcmp(argv[c], "-CYGhack")) {
289                                 s = cygwin32_cmdline();
290                                 s = strstr(s, "-CYGhack");
291                                 if (s) {
292                                         s += /* strlen("-CYGhack") */ 8;
293                                         while (*s == ' ' || *s == '\t')
294                                                 ++s;
295                                         argv[c] = s;
296                                         argv[c + 1] = NULL;
297                                         break;
298                                 }
299                         }
300 #endif
301                         if (argv[c][1])
302                                 switch (glopt(argv[c] + 1, argv[c + 1], NULL, 1)) {
303                                 case 0:
304                                         fprintf(stderr, "Unknown option '%s'\n", argv[c]);
305                                         break;
306                                 case 1:
307                                         break;
308                                 case 2:
309                                         ++c;
310                                         break;
311                         } else
312                                 idleout = 0;
313                 }
314         }
315
316         if (!(n = nopen(cap)))
317                 return 1;
318         maint = screate(n);
319         vmem = vtmp();
320
321         for (c = 1, backopt = 0; argv[c]; ++c)
322                 if (argv[c][0] == '+' && argv[c][1]) {
323                         if (!backopt)
324                                 backopt = c;
325                 } else if (argv[c][0] == '-' && argv[c][1]) {
326                         if (!backopt)
327                                 backopt = c;
328                         if (glopt(argv[c] + 1, argv[c + 1], NULL, 0) == 2)
329                                 ++c;
330                 } else {
331                         B *b = bfind(argv[c]);
332                         BW *bw = NULL;
333                         int er = error;
334
335                         if (!orphan || !opened) {
336                                 bw = wmktw(maint, b);
337                                 if (er)
338                                         msgnwt(bw->parent, msgs[-er]);
339                         } else
340                                 b->orphan = 1;
341                         if (bw) {
342                                 long lnum = 0;
343
344                                 bw->o.readonly = bw->b->rdonly;
345                                 if (backopt) {
346                                         unsigned char *old_context;
347
348                                         old_context = bw->o.context;
349                                         while (backopt != c) {
350                                                 if (argv[backopt][0] == '+') {
351                                                         sscanf((char *)(argv[backopt] + 1), "%ld", &lnum);
352                                                         ++backopt;
353                                                 } else {
354                                                         if (glopt(argv[backopt] + 1, argv[backopt + 1], &bw->o, 0) == 2)
355                                                                 backopt += 2;
356                                                         else
357                                                                 backopt += 1;
358                                                         lazy_opts(&bw->o);
359                                                 }
360                                         }
361                                         if (old_context != bw->o.context) {
362                                                 /* update keymap */
363                                                 rmkbd(bw->parent->kbd);
364                                                 bw->parent->kbd =
365                                                     mkkbd(kmap_getcontext(bw->o.context, 1));
366                                         }
367                                 }
368                                 bw->b->o = bw->o;
369                                 bw->b->rdonly = bw->o.readonly;
370                                 if (!opened || opened == (void *)&opened)
371                                         opened = bw->parent;
372                                 maint->curwin = bw->parent;
373                                 if (er == -1 && bw->o.mnew)
374                                         exemac(bw->o.mnew);
375                                 if (er == 0 && bw->o.mold)
376                                         exemac(bw->o.mold);
377                                 maint->curwin = opened;
378                                 if (lnum > 0)
379                                         pline(bw->cursor, lnum - 1);
380                         }
381                         if (!opened)
382                                 opened = (void *)&opened;
383                         backopt = 0;
384                 }
385
386         maint->curwin = opened == (void *)&opened ? NULL : opened;
387         if (opened) {
388                 wshowall(maint);
389                 omid = mid;
390                 mid = 1;
391                 dofollows();
392                 mid = omid;
393         } else {
394                 BW *bw = wmktw(maint, bfind(US ""));
395
396                 if (bw->o.mnew)
397                         exemac(bw->o.mnew);
398         }
399         maint->curwin = maint->topwin;
400
401         if (help) {
402                 help_on(maint);
403         }
404         if (!nonotice) {
405                 joe_snprintf_4((char *)msgbuf,JOE_MSGBUFSIZE,
406                     "\\i[ Joe's Own Editor v" VERSION
407                     " | %s | %s " JUPP_IS_COPYRIGHT_C_BY " ]%s%s\\i",
408                     locale_map->name, locale_map->type ? "©" : "(c)",
409                     fdefault.hmsg ? " " : "",
410                     fdefault.hmsg ? fdefault.hmsg : "");
411                 msgnw(((BASE *)lastw(maint)->object)->parent, msgbuf);
412         }
413
414         edloop(0);
415         vclose(vmem);
416         nclose(n);
417         if (exmsg)
418                 fprintf(stderr, "\n%s\n", exmsg);
419         return 0;
420 }
421
422 #ifdef __CYGWIN__
423 #include <windows.h>
424
425 /* return command line as passed to the .EXE (just like cygwin32’s dcrt0.cc) */
426 static unsigned char *
427 cygwin32_cmdline(void)
428 {
429         char *cp;
430
431         cp = strdup(GetCommandLineA());
432         if (!AreFileApisANSI())
433                 CharToOemA(cp, cp);
434         return ((unsigned char *)cp);
435 }
436 #endif