Annotation of src/usr.bin/mg/main.c, Revision 1.87
1.87 ! lum 1: /* $OpenBSD: main.c,v 1.86 2019/06/10 06:52:44 lum Exp $ */
1.40 kjell 2:
3: /* This file is in the public domain. */
1.6 niklas 4:
1.1 deraadt 5: /*
1.5 millert 6: * Mainline.
1.1 deraadt 7: */
1.5 millert 8:
1.75 bcallah 9: #include <sys/queue.h>
10: #include <err.h>
11: #include <limits.h>
12: #include <locale.h>
13: #include <signal.h>
14: #include <stdio.h>
15: #include <stdlib.h>
16: #include <string.h>
17: #include <unistd.h>
18:
1.38 db 19: #include "def.h"
20: #include "kbd.h"
21: #include "funmap.h"
22: #include "macro.h"
1.24 vincent 23:
1.86 lum 24: #ifdef MGLOG
25: #include "log.h"
26: #endif
27:
1.5 millert 28: int thisflag; /* flags, this command */
29: int lastflag; /* flags, last command */
30: int curgoal; /* goal column */
1.36 deraadt 31: int startrow; /* row to start */
1.71 lum 32: int doaudiblebell; /* audible bell toggle */
33: int dovisiblebell; /* visible bell toggle */
1.82 lum 34: int dblspace; /* sentence end #spaces */
1.85 lum 35: int allbro; /* all buffs read-only */
1.55 deraadt 36: struct buffer *curbp; /* current buffer */
1.53 kjell 37: struct buffer *bheadp; /* BUFFER list head */
38: struct mgwin *curwp; /* current window */
39: struct mgwin *wheadp; /* MGWIN listhead */
1.5 millert 40: char pat[NPAT]; /* pattern */
1.1 deraadt 41:
1.66 lum 42: static void edinit(struct buffer *);
1.53 kjell 43: static __dead void usage(void);
44:
45: extern char *__progname;
1.62 lum 46: extern void closetags(void);
1.53 kjell 47:
48: static __dead void
49: usage()
50: {
1.81 lum 51: fprintf(stderr, "usage: %s [-nR] [-f mode] [+number] [file ...]\n",
1.53 kjell 52: __progname);
53: exit(1);
54: }
1.1 deraadt 55:
1.2 deraadt 56: int
1.19 vincent 57: main(int argc, char **argv)
1.1 deraadt 58: {
1.66 lum 59: char *cp, *init_fcn_name = NULL;
60: PF init_fcn = NULL;
61: int o, i, nfiles;
1.85 lum 62: int nobackups = 0;
1.66 lum 63: struct buffer *bp = NULL;
1.78 deraadt 64:
1.83 semarie 65: if (pledge("stdio rpath wpath cpath fattr chown getpw tty proc exec",
66: NULL) == -1)
1.78 deraadt 67: err(1, "pledge");
1.24 vincent 68:
1.81 lum 69: while ((o = getopt(argc, argv, "nRf:")) != -1)
1.24 vincent 70: switch (o) {
1.81 lum 71: case 'R':
1.85 lum 72: allbro = 1;
1.81 lum 73: break;
1.35 henning 74: case 'n':
75: nobackups = 1;
76: break;
1.24 vincent 77: case 'f':
78: if (init_fcn_name != NULL)
79: errx(1, "cannot specify more than one "
80: "initial function");
81: init_fcn_name = optarg;
82: break;
83: default:
1.53 kjell 84: usage();
1.24 vincent 85: }
86: argc -= optind;
87: argv += optind;
1.70 naddy 88:
89: setlocale(LC_CTYPE, "");
1.1 deraadt 90:
1.12 art 91: maps_init(); /* Keymaps and modes. */
1.11 art 92: funmap_init(); /* Functions. */
1.86 lum 93:
94: #ifdef MGLOG
95: if (!mgloginit())
96: errx(1, "Unable to create logging environment.");
97: #endif
1.19 vincent 98:
1.13 art 99: /*
100: * This is where we initialize standalone extensions that should
101: * be loaded dynamically sometime in the future.
102: */
103: {
104: extern void grep_init(void);
1.58 kjell 105: extern void cmode_init(void);
1.42 kjell 106: extern void dired_init(void);
1.13 art 107:
1.42 kjell 108: dired_init();
1.13 art 109: grep_init();
1.58 kjell 110: cmode_init();
1.13 art 111: }
1.5 millert 112:
1.24 vincent 113: if (init_fcn_name &&
114: (init_fcn = name_function(init_fcn_name)) == NULL)
115: errx(1, "Unknown function `%s'", init_fcn_name);
116:
117: vtinit(); /* Virtual terminal. */
118: dirinit(); /* Get current directory. */
1.66 lum 119: edinit(bp); /* Buffers, windows. */
1.24 vincent 120: ttykeymapinit(); /* Symbols, bindings. */
1.71 lum 121: bellinit(); /* Audible and visible bell. */
1.82 lum 122: dblspace = 1; /* two spaces for sentence end. */
1.24 vincent 123:
1.4 millert 124: /*
125: * doing update() before reading files causes the error messages from
126: * the file I/O show up on the screen. (and also an extra display of
127: * the mode line if there are files specified on the command line.)
1.1 deraadt 128: */
1.71 lum 129: update(CMODE);
1.5 millert 130:
1.65 lum 131: /* user startup file. */
132: if ((cp = startupfile(NULL)) != NULL)
133: (void)load(cp);
134:
1.77 jasper 135: /*
1.65 lum 136: * Now ensure any default buffer modes from the startup file are
137: * given to any files opened when parsing the startup file.
138: * Note *scratch* will also be updated.
139: */
140: for (bp = bheadp; bp != NULL; bp = bp->b_bufp) {
141: bp->b_flag = defb_flag;
142: for (i = 0; i <= defb_nmodes; i++) {
143: bp->b_modes[i] = defb_modes[i];
144: }
145: }
1.59 kjell 146:
147: /* Force FFOTHARG=1 so that this mode is enabled, not simply toggled */
148: if (init_fcn)
149: init_fcn(FFOTHARG, 1);
150:
1.35 henning 151: if (nobackups)
152: makebkfile(FFARG, 0);
1.27 vincent 153:
154: for (nfiles = 0, i = 0; i < argc; i++) {
155: if (argv[i][0] == '+' && strlen(argv[i]) >= 2) {
1.43 deraadt 156: long long lval;
1.30 pvalchev 157: const char *errstr;
1.23 deraadt 158:
1.32 vincent 159: lval = strtonum(&argv[i][1], INT_MIN, INT_MAX, &errstr);
1.33 vincent 160: if (argv[i][1] == '\0' || errstr != NULL)
1.23 deraadt 161: goto notnum;
1.30 pvalchev 162: startrow = lval;
1.24 vincent 163: } else {
1.23 deraadt 164: notnum:
1.52 jason 165: cp = adjustname(argv[i], FALSE);
1.24 vincent 166: if (cp != NULL) {
1.38 db 167: if (nfiles == 1)
1.27 vincent 168: splitwind(0, 1);
1.38 db 169:
1.76 lum 170: if (fisdir(cp) == TRUE) {
171: (void)do_dired(cp);
1.77 jasper 172: continue;
1.76 lum 173: }
1.39 beck 174: if ((curbp = findbuffer(cp)) == NULL) {
175: vttidy();
176: errx(1, "Can't find current buffer!");
177: }
1.24 vincent 178: (void)showbuffer(curbp, curwp, 0);
1.44 deraadt 179: if (readin(cp) != TRUE)
1.34 jfb 180: killbuffer(curbp);
1.38 db 181: else {
1.59 kjell 182: /* Ensure enabled, not just toggled */
1.34 jfb 183: if (init_fcn_name)
1.59 kjell 184: init_fcn(FFOTHARG, 1);
1.34 jfb 185: nfiles++;
186: }
1.85 lum 187: if (allbro)
1.81 lum 188: curbp->b_flag |= BFREADONLY;
1.24 vincent 189: }
1.22 vincent 190: }
1.1 deraadt 191: }
1.29 vincent 192:
193: if (nfiles > 2)
194: listbuffers(0, 1);
1.5 millert 195:
196: /* fake last flags */
197: thisflag = 0;
1.4 millert 198: for (;;) {
1.50 kjell 199: if (epresf == KCLEAR)
1.4 millert 200: eerase();
1.50 kjell 201: if (epresf == TRUE)
202: epresf = KCLEAR;
1.17 deraadt 203: if (winch_flag) {
1.49 otto 204: do_redraw(0, 0, TRUE);
1.17 deraadt 205: winch_flag = 0;
206: }
1.71 lum 207: update(CMODE);
1.4 millert 208: lastflag = thisflag;
209: thisflag = 0;
1.5 millert 210:
1.4 millert 211: switch (doin()) {
212: case TRUE:
213: break;
1.1 deraadt 214: case ABORT:
1.5 millert 215: ewprintf("Quit");
1.48 kjell 216: /* FALLTHRU */
1.1 deraadt 217: case FALSE:
218: default:
1.4 millert 219: macrodef = FALSE;
220: }
1.1 deraadt 221: }
222: }
223:
224: /*
1.66 lum 225: * Initialize default buffer and window. Default buffer is called *scratch*.
1.1 deraadt 226: */
1.7 art 227: static void
1.66 lum 228: edinit(struct buffer *bp)
1.4 millert 229: {
1.45 deraadt 230: struct mgwin *wp;
1.1 deraadt 231:
232: bheadp = NULL;
1.66 lum 233: bp = bfind("*scratch*", TRUE); /* Text buffer. */
1.63 lum 234: if (bp == NULL)
235: panic("edinit");
236:
1.26 vincent 237: wp = new_window(bp);
1.21 vincent 238: if (wp == NULL)
1.66 lum 239: panic("edinit: Out of memory");
1.63 lum 240:
1.66 lum 241: curbp = bp; /* Current buffer. */
1.1 deraadt 242: wheadp = wp;
1.4 millert 243: curwp = wp;
1.5 millert 244: wp->w_wndp = NULL; /* Initialize window. */
1.54 kjell 245: wp->w_linep = wp->w_dotp = bp->b_headp;
1.38 db 246: wp->w_ntrows = nrow - 2; /* 2 = mode, echo. */
1.61 kjell 247: wp->w_rflag = WFMODE | WFFULL; /* Full. */
1.1 deraadt 248: }
249:
250: /*
1.5 millert 251: * Quit command. If an argument, always quit. Otherwise confirm if a buffer
1.87 ! lum 252: * has been changed and not written out. Normally bound to "C-x C-c".
1.1 deraadt 253: */
1.4 millert 254: /* ARGSUSED */
1.5 millert 255: int
1.20 vincent 256: quit(int f, int n)
1.1 deraadt 257: {
1.5 millert 258: int s;
1.1 deraadt 259:
1.4 millert 260: if ((s = anycb(FALSE)) == ABORT)
1.38 db 261: return (ABORT);
1.69 lum 262: if (s == FIOERR || s == UERROR)
1.68 lum 263: return (FALSE);
1.1 deraadt 264: if (s == FALSE
1.41 kjell 265: || eyesno("Modified buffers exist; really exit") == TRUE) {
1.1 deraadt 266: vttidy();
1.62 lum 267: closetags();
1.73 florian 268: exit(0);
1.1 deraadt 269: }
1.38 db 270: return (TRUE);
1.1 deraadt 271: }
272:
273: /*
1.10 mickey 274: * User abort. Should be called by any input routine that sees a C-g to abort
1.5 millert 275: * whatever C-g is aborting these days. Currently does nothing.
1.1 deraadt 276: */
1.4 millert 277: /* ARGSUSED */
278: int
1.20 vincent 279: ctrlg(int f, int n)
1.1 deraadt 280: {
1.24 vincent 281: return (ABORT);
1.1 deraadt 282: }