|
|
1.1 root 1: /* main.c */
2:
3: /* Author:
4: * Steve Kirkendall
5: * 14407 SW Teal Blvd. #C
6: * Beaverton, OR 97005
7: * [email protected]
8: */
9:
10:
11: /* This file contains the main() function of vi */
12:
13: /* HACK! bcc needs to disable use of precompiled headers for this file,
14: or else command line args will not be passed to elvis */
15: #if __BORLANDC__
16: #include "borland.h"
17: #endif
18:
19: #include "config.h"
20: #include <setjmp.h>
21: #include "vi.h"
22:
23: extern trapint(); /* defined below */
24: extern char *getenv();
25: jmp_buf jmpenv;
26:
27: #ifndef NO_DIGRAPH
28: static init_digraphs();
29: #endif
30:
31: /*---------------------------------------------------------------------*/
32:
33: #if AMIGA
34: # include "amiwild.c"
35: main (argc, argv)
36: #else
37: # if VMS
38: # include "vmswild.c"
39: main (argc, argv)
40: # else
41: void main(argc, argv)
42: # endif
43: #endif
44: int argc;
45: char *argv[];
46: {
47: int i;
48: char *cmd = (char *)0;
49: char *err = (char *)0;
50: char *str;
51: char *tag = (char *)0;
52:
53: /* set mode to MODE_VI or MODE_EX depending on program name */
54: switch (argv[0][strlen(argv[0]) - 1])
55: {
56: case 'x': /* "ex" */
57: mode = MODE_EX;
58: break;
59:
60: case 'w': /* "view" */
61: mode = MODE_VI;
62: *o_readonly = TRUE;
63: break;
64: #ifndef NO_EXTENSIONS
65: case 't': /* "edit" or "input" */
66: mode = MODE_VI;
67: *o_inputmode = TRUE;
68: break;
69: #endif
70: default: /* "vi" or "elvis" */
71: mode = MODE_VI;
72: }
73:
74: #ifndef DEBUG
75: # ifdef SIGQUIT
76: /* normally, we ignore SIGQUIT. SIGINT is trapped later */
77: signal(SIGQUIT, SIG_IGN);
78: # endif
79: #endif
80:
81: /* temporarily ignore SIGINT */
82: signal(SIGINT, SIG_IGN);
83:
84: /* start curses */
85: initscr();
86: cbreak();
87: noecho();
88: scrollok(stdscr, TRUE);
89:
90: /* arrange for deadly signals to be caught */
91: # ifdef SIGHUP
92: signal(SIGHUP, (void(*)()) deathtrap);
93: # endif
94: # ifndef DEBUG
95: # ifdef SIGILL
96: signal(SIGILL, (void(*)()) deathtrap);
97: # endif
98: # ifdef SIGBUS
99: signal(SIGBUS, (void(*)()) deathtrap);
100: # endif
101: # ifdef SIGSEGV
102: signal(SIGSEGV, (void(*)()) deathtrap);
103: # endif
104: # ifdef SIGSYS
105: signal(SIGSYS, (void(*)()) deathtrap);
106: # endif
107: # endif /* !DEBUG */
108: # ifdef SIGPIPE
109: signal(SIGPIPE, (void(*)()) deathtrap);
110: # endif
111: # ifdef SIGTERM
112: signal(SIGTERM, (void(*)()) deathtrap);
113: # endif
114: # ifdef SIGUSR1
115: signal(SIGUSR1, (void(*)()) deathtrap);
116: # endif
117: # ifdef SIGUSR2
118: signal(SIGUSR2, (void(*)()) deathtrap);
119: # endif
120:
121: /* initialize the options - must be done after initscr(), so that
122: * we can alter LINES and COLS if necessary.
123: */
124: initopts();
125:
126: /* map the arrow keys. The KU,KD,KL,and KR variables correspond to
127: * the :ku=: (etc.) termcap capabilities. The variables are defined
128: * as part of the curses package.
129: */
130: if (has_KU) mapkey(has_KU, "k", WHEN_VICMD|WHEN_INMV, "<Up>");
131: if (has_KD) mapkey(has_KD, "j", WHEN_VICMD|WHEN_INMV, "<Down>");
132: if (has_KL) mapkey(has_KL, "h", WHEN_VICMD|WHEN_INMV, "<Left>");
133: if (has_KR) mapkey(has_KR, "l", WHEN_VICMD|WHEN_INMV, "<Right>");
134: if (has_HM) mapkey(has_HM, "^", WHEN_VICMD|WHEN_INMV, "<Home>");
135: if (has_EN) mapkey(has_EN, "$", WHEN_VICMD|WHEN_INMV, "<End>");
136: if (has_PU) mapkey(has_PU, "\002", WHEN_VICMD|WHEN_INMV, "<PageUp>");
137: if (has_PD) mapkey(has_PD, "\006", WHEN_VICMD|WHEN_INMV, "<PageDn>");
138: if (has_KI) mapkey(has_KI, "i", WHEN_VICMD|WHEN_INMV, "<Insert>");
139: #if MSDOS
140: # if RAINBOW
141: if (!strcmp("rainbow", o_term))
142: {
143: mapkey("\033[1~", "/", WHEN_VICMD, "<Find>");
144: mapkey("\033[3~", "x", WHEN_VICMD|WHEN_INMV, "<Remove>");
145: mapkey("\033[4~", "v", WHEN_VICMD|WHEN_INMV, "<Select>");
146: mapkey("\033[17~", ":sh\n", WHEN_VICMD, "<Intrpt>");
147: mapkey("\033[19~", ":q\n", WHEN_VICMD, "<Cancel>");
148: mapkey("\033[21~", "ZZ", WHEN_VICMD, "<Exit>");
149: mapkey("\033[26~", "V", WHEN_VICMD|WHEN_INMV, "<AddlOp>");
150: mapkey("\033[28~", "\\", WHEN_VICMD|WHEN_INMV, "<Help>");
151: mapkey("\033[29~", "K", WHEN_VICMD|WHEN_INMV, "<Do>");
152: }
153: else
154: # endif /* RAINBOW */
155: {
156: mapkey("#S", "x", WHEN_VICMD|WHEN_INMV, "<Delete>");
157: mapkey("#s", "B", WHEN_VICMD|WHEN_INMV, "^<Left>");
158: mapkey("#t", "W", WHEN_VICMD|WHEN_INMV, "^<Right>");
159: }
160: #else /* not MSDOS */
161: # if COHERENT
162: mapkey("\033[P", "x", WHEN_VICMD|WHEN_INMV, "<Del>");
163: # else
164: #if AMIGA
165: mapkey("\233?~", "\\", WHEN_VICMD|WHEN_INMV, "<Help>");
166: #endif
167:
168: if (ERASEKEY != '\177')
169: {
170: mapkey("\177", "x", WHEN_VICMD|WHEN_INMV, "<Del>");
171: }
172: # endif
173: #endif
174:
175: #ifndef NO_DIGRAPH
176: init_digraphs();
177: #endif /* NO_DIGRAPH */
178:
179: /* process any flags */
180: for (i = 1; i < argc && *argv[i] == '-'; i++)
181: {
182: switch (argv[i][1])
183: {
184: case 'R': /* readonly */
185: *o_readonly = TRUE;
186: break;
187:
188: case 'L':
189: case 'r': /* recover */
190: msg("Use the `elvrec` program to recover lost files");
191: endmsgs();
192: refresh();
193: endwin();
194: exit(0);
195: break;
196:
197: case 't': /* tag */
198: if (argv[i][2])
199: {
200: tag = argv[i] + 2;
201: }
202: else
203: {
204: tag = argv[++i];
205: }
206: break;
207:
208: case 'v': /* vi mode */
209: mode = MODE_VI;
210: break;
211:
212: case 'e': /* ex mode */
213: mode = MODE_EX;
214: break;
215: #ifndef NO_EXTENSIONS
216: case 'i': /* input mode */
217: *o_inputmode = TRUE;
218: break;
219: #endif
220: #ifndef NO_ERRLIST
221: case 'm': /* use "errlist" as the errlist */
222: if (argv[i][2])
223: {
224: err = argv[i] + 2;
225: }
226: else if (i + 1 < argc)
227: {
228: err = argv[++i];
229: }
230: else
231: {
232: err = "";
233: }
234: break;
235: #endif
236: #ifndef CRUNCH
237: case 'c': /* run the following command, later */
238: if (argv[i][2])
239: {
240: cmd = argv[i] + 2;
241: }
242: else
243: {
244: cmd = argv[++i];
245: }
246: break;
247:
248: case 'w': /* set the window size */
249: if (argv[i][2])
250: {
251: *o_window = atoi(argv[i] + 2);
252: wset = TRUE;
253: }
254: else
255: {
256: *o_window = atoi(argv[++i]);
257: wset = TRUE;
258: }
259: break;
260: #endif
261: default:
262: msg("Ignoring unknown flag \"%s\"", argv[i]);
263: }
264: }
265:
266: /* if we were given an initial ex command, save it... */
267: if (i < argc && *argv[i] == '+')
268: {
269: if (argv[i][1])
270: {
271: cmd = argv[i++] + 1;
272: }
273: else
274: {
275: cmd = "$"; /* "vi + file" means start at EOF */
276: i++;
277: }
278: }
279:
280: /* the remaining args are file names. */
281: if (i < argc)
282: {
283: strcpy(args, argv[i]);
284: while (++i < argc && strlen(args) + 1 + strlen(argv[i]) < sizeof args)
285: {
286: strcat(args, " ");
287: strcat(args, argv[i]);
288: }
289: #if MSDOS || TOS
290: /* expand wildcard characters, if necessary */
291: if (strchr(args, '*') || strchr(args, '?'))
292: {
293: strcpy(args, wildcard(args));
294: }
295: #endif
296: strcpy(tmpblk.c, args);
297: cmd_args(MARK_UNSET, MARK_UNSET, CMD_ARGS, TRUE, tmpblk.c);
298: }
299: else
300: {
301: /* empty args list */
302: args[0] = '\0';
303: nargs = 1;
304: argno = -1;
305: }
306:
307: /* perform the .exrc files and EXINIT environment variable */
308: #ifdef SYSEXRC
309: doexrc(SYSEXRC);
310: #endif
311: #ifdef HMEXRC
312: str = getenv("HOME");
313: if (str && *str)
314: {
315: strcpy(tmpblk.c, str);
316: str = tmpblk.c + strlen(tmpblk.c);
317: #if !VMS
318: # if AMIGA /* Don't SLASH a device. "Elvis:.exrc" */
319: if (str[-1] != COLON && str[-1] != SLASH)
320: # else
321: if (str[-1] != SLASH)
322: # endif
323: {
324: *str++ = SLASH;
325: }
326: #endif
327: strcpy(str, HMEXRC);
328: doexrc(tmpblk.c);
329: }
330: #endif
331: #ifndef CRUNCH
332: if (*o_exrc)
333: #endif
334: {
335: doexrc(EXRC);
336: }
337: #ifdef EXINIT
338: str = getenv(EXINIT);
339: if (str)
340: {
341: exstring(str, strlen(str), ctrl('V'));
342: }
343: #endif
344:
345: /* search for a tag (or an error) now, if desired */
346: blkinit();
347: if (tag)
348: {
349: cmd_tag(MARK_FIRST, MARK_FIRST, CMD_TAG, 0, tag);
350: }
351: #ifndef NO_ERRLIST
352: else if (err)
353: {
354: cmd_errlist(MARK_FIRST, MARK_FIRST, CMD_ERRLIST, 0, err);
355: }
356: #endif
357:
358: /* if no tag/err, or tag failed, then start with first arg */
359: if (tmpfd < 0)
360: {
361: /* start with first arg */
362: cmd_next(MARK_UNSET, MARK_UNSET, CMD_NEXT, FALSE, "");
363:
364: /* pretend to do something, just to force a recoverable
365: * version of the file out to disk
366: */
367: ChangeText
368: {
369: }
370: clrflag(file, MODIFIED);
371: }
372:
373: /* now we do the immediate ex command that we noticed before */
374: if (cmd)
375: {
376: doexcmd(cmd);
377: }
378:
379: /* repeatedly call ex() or vi() (depending on the mode) until the
380: * mode is set to MODE_QUIT
381: */
382: while (mode != MODE_QUIT)
383: {
384: if (setjmp(jmpenv))
385: {
386: /* Maybe we just aborted a change? */
387: abortdo();
388: }
389: signal(SIGINT, (void(*)()) trapint);
390:
391: switch (mode)
392: {
393: case MODE_VI:
394: vi();
395: break;
396:
397: case MODE_EX:
398: ex();
399: break;
400: #ifdef DEBUG
401: default:
402: msg("mode = %d?", mode);
403: mode = MODE_QUIT;
404: #endif
405: }
406: }
407:
408: /* free up the cut buffers */
409: cutend();
410:
411: /* end curses */
412: #ifndef NO_CURSORSHAPE
413: if (has_CQ)
414: do_CQ();
415: #endif
416: endmsgs();
417: move(LINES - 1, 0);
418: clrtoeol();
419: refresh();
420: endwin();
421:
422: exit(exitcode);
423: /*NOTREACHED*/
424: }
425:
426:
427: /*ARGSUSED*/
428: int trapint(signo)
429: int signo;
430: {
431: beep();
432: resume_curses(FALSE);
433: abortdo();
434: #if OSK
435: sigmask(-1);
436: #endif
437: #if TURBOC || __GNUC__
438: signal(signo, (void (*)())trapint);
439: #else
440: signal(signo, trapint);
441: #endif
442: doingglobal = FALSE;
443:
444: longjmp(jmpenv, 1);
445:
446: return 0;
447: }
448:
449:
450:
451: #ifndef NO_DIGRAPH
452:
453: /* This stuff us used to build the default digraphs table. */
454: static char digtable[][4] =
455: {
456: # ifdef CS_IBMPC
457: "C,\200", "u\"\1", "e'\2", "a^\3",
458: "a\"\4", "a`\5", "a@\6", "c,\7",
459: "e^\10", "e\"\211", "e`\12", "i\"\13",
460: "i^\14", "i`\15", "A\"\16", "A@\17",
461: "E'\20", "ae\21", "AE\22", "o^\23",
462: "o\"\24", "o`\25", "u^\26", "u`\27",
463: "y\"\30", "O\"\31", "U\"\32", "a'\240",
464: "i'!", "o'\"", "u'#", "n~$",
465: "N~%", "a-&", "o-'", "~?(",
466: "~!-", "\"<.", "\">/",
467: # ifdef CS_SPECIAL
468: "2/+", "4/,", "^+;", "^q<",
469: "^c=", "^r>", "^t?", "pp]",
470: "^^^", "oo_", "*a`", "*ba",
471: "*pc", "*Sd", "*se", "*uf",
472: "*tg", "*Ph", "*Ti", "*Oj",
473: "*dk", "*Hl", "*hm", "*En",
474: "*No", "eqp", "pmq", "ger",
475: "les", "*It", "*iu", "*/v",
476: "*=w", "sq{", "^n|", "^2}",
477: "^3~", "^_\377",
478: # endif /* CS_SPECIAL */
479: # endif /* CS_IBMPC */
480: # ifdef CS_LATIN1
481: "~!!", "a-*", "\">+", "o-:",
482: "\"<>", "~??",
483:
484: "A`@", "A'A", "A^B", "A~C",
485: "A\"D", "A@E", "AEF", "C,G",
486: "E`H", "E'I", "E^J", "E\"K",
487: "I`L", "I'M", "I^N", "I\"O",
488: "-DP", "N~Q", "O`R", "O'S",
489: "O^T", "O~U", "O\"V", "O/X",
490: "U`Y", "U'Z", "U^[", "U\"\\",
491: "Y'_",
492:
493: "a``", "a'a", "a^b", "a~c",
494: "a\"d", "a@e", "aef", "c,g",
495: "e`h", "e'i", "e^j", "e\"k",
496: "i`l", "i'm", "i^n", "i\"o",
497: "-dp", "n~q", "o`r", "o's",
498: "o^t", "o~u", "o\"v", "o/x",
499: "u`y", "u'z", "u^{", "u\"|",
500: "y'~",
501: # endif /* CS_LATIN1 */
502: ""
503: };
504:
505: static int init_digraphs()
506: {
507: int i;
508:
509: for (i = 0; *digtable[i]; i++)
510: {
511: do_digraph(FALSE, digtable[i]);
512: }
513: do_digraph(FALSE, (char *)0);
514: return 0;
515: }
516: #endif /* NO_DIGRAPH */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.