xref: /openbsd-src/usr.bin/mg/main.c (revision 4c1e55dc91edd6e69ccc60ce855900fbc12cf34f)
1 /*	$OpenBSD: main.c,v 1.67 2012/05/29 06:08:48 lum Exp $	*/
2 
3 /* This file is in the public domain. */
4 
5 /*
6  *	Mainline.
7  */
8 
9 #include "def.h"
10 #include "kbd.h"
11 #include "funmap.h"
12 #include "macro.h"
13 
14 #include <err.h>
15 
16 int		 thisflag;			/* flags, this command	*/
17 int		 lastflag;			/* flags, last command	*/
18 int		 curgoal;			/* goal column		*/
19 int		 startrow;			/* row to start		*/
20 struct buffer	*curbp;				/* current buffer	*/
21 struct buffer	*bheadp;			/* BUFFER list head	*/
22 struct mgwin	*curwp;				/* current window	*/
23 struct mgwin	*wheadp;			/* MGWIN listhead	*/
24 char		 pat[NPAT];			/* pattern		*/
25 
26 static void	 edinit(struct buffer *);
27 static __dead void usage(void);
28 
29 extern char	*__progname;
30 extern void     closetags(void);
31 
32 static __dead void
33 usage()
34 {
35 	fprintf(stderr, "usage: %s [-n] [-f mode] [+number] [file ...]\n",
36 	    __progname);
37 	exit(1);
38 }
39 
40 int
41 main(int argc, char **argv)
42 {
43 	char		*cp, *init_fcn_name = NULL;
44 	PF		 init_fcn = NULL;
45 	int	 	 o, i, nfiles;
46 	int	  	 nobackups = 0;
47 	struct buffer	*bp = NULL;
48 
49 	while ((o = getopt(argc, argv, "nf:")) != -1)
50 		switch (o) {
51 		case 'n':
52 			nobackups = 1;
53 			break;
54 		case 'f':
55 			if (init_fcn_name != NULL)
56 				errx(1, "cannot specify more than one "
57 				    "initial function");
58 			init_fcn_name = optarg;
59 			break;
60 		default:
61 			usage();
62 		}
63 	argc -= optind;
64 	argv += optind;
65 
66 	maps_init();		/* Keymaps and modes.		*/
67 	funmap_init();		/* Functions.			*/
68 
69 	/*
70 	 * This is where we initialize standalone extensions that should
71 	 * be loaded dynamically sometime in the future.
72 	 */
73 	{
74 		extern void grep_init(void);
75 		extern void theo_init(void);
76 		extern void cmode_init(void);
77 		extern void dired_init(void);
78 
79 		dired_init();
80 		grep_init();
81 		theo_init();
82 		cmode_init();
83 	}
84 
85 	if (init_fcn_name &&
86 	    (init_fcn = name_function(init_fcn_name)) == NULL)
87 		errx(1, "Unknown function `%s'", init_fcn_name);
88 
89 	vtinit();		/* Virtual terminal.		*/
90 	dirinit();		/* Get current directory.	*/
91 	edinit(bp);		/* Buffers, windows.		*/
92 	ttykeymapinit();	/* Symbols, bindings.		*/
93 
94 	/*
95 	 * doing update() before reading files causes the error messages from
96 	 * the file I/O show up on the screen.	(and also an extra display of
97 	 * the mode line if there are files specified on the command line.)
98 	 */
99 	update();
100 
101 	/* user startup file. */
102 	if ((cp = startupfile(NULL)) != NULL)
103 		(void)load(cp);
104 
105 	/*
106 	 * Now ensure any default buffer modes from the startup file are
107 	 * given to any files opened when parsing the startup file.
108 	 * Note *scratch* will also be updated.
109 	 */
110 	for (bp = bheadp; bp != NULL; bp = bp->b_bufp) {
111 		bp->b_flag = defb_flag;
112 		for (i = 0; i <= defb_nmodes; i++) {
113                 	bp->b_modes[i] = defb_modes[i];
114         	}
115 	}
116 
117 	/* Force FFOTHARG=1 so that this mode is enabled, not simply toggled */
118 	if (init_fcn)
119 		init_fcn(FFOTHARG, 1);
120 
121 	if (nobackups)
122 		makebkfile(FFARG, 0);
123 
124 	for (nfiles = 0, i = 0; i < argc; i++) {
125 		if (argv[i][0] == '+' && strlen(argv[i]) >= 2) {
126 			long long lval;
127 			const char *errstr;
128 
129 			lval = strtonum(&argv[i][1], INT_MIN, INT_MAX, &errstr);
130 			if (argv[i][1] == '\0' || errstr != NULL)
131 				goto notnum;
132 			startrow = lval;
133 		} else {
134 notnum:
135 			cp = adjustname(argv[i], FALSE);
136 			if (cp != NULL) {
137 				if (nfiles == 1)
138 					splitwind(0, 1);
139 
140 				if ((curbp = findbuffer(cp)) == NULL) {
141 					vttidy();
142 					errx(1, "Can't find current buffer!");
143 				}
144 				(void)showbuffer(curbp, curwp, 0);
145 				if (readin(cp) != TRUE)
146 					killbuffer(curbp);
147 				else {
148 					/* Ensure enabled, not just toggled */
149 					if (init_fcn_name)
150 						init_fcn(FFOTHARG, 1);
151 					nfiles++;
152 				}
153 			}
154 		}
155 	}
156 
157 	if (nfiles > 2)
158 		listbuffers(0, 1);
159 
160 	/* fake last flags */
161 	thisflag = 0;
162 	for (;;) {
163 		if (epresf == KCLEAR)
164 			eerase();
165 		if (epresf == TRUE)
166 			epresf = KCLEAR;
167 		if (winch_flag) {
168 			do_redraw(0, 0, TRUE);
169 			winch_flag = 0;
170 		}
171 		update();
172 		lastflag = thisflag;
173 		thisflag = 0;
174 
175 		switch (doin()) {
176 		case TRUE:
177 			break;
178 		case ABORT:
179 			ewprintf("Quit");
180 			/* FALLTHRU */
181 		case FALSE:
182 		default:
183 			ttbeep();
184 			macrodef = FALSE;
185 		}
186 	}
187 }
188 
189 /*
190  * Initialize default buffer and window. Default buffer is called *scratch*.
191  */
192 static void
193 edinit(struct buffer *bp)
194 {
195 	struct mgwin	*wp;
196 
197 	bheadp = NULL;
198 	bp = bfind("*scratch*", TRUE);		/* Text buffer.          */
199 	if (bp == NULL)
200 		panic("edinit");
201 
202 	wp = new_window(bp);
203 	if (wp == NULL)
204 		panic("edinit: Out of memory");
205 
206 	curbp = bp;				/* Current buffer.	 */
207 	wheadp = wp;
208 	curwp = wp;
209 	wp->w_wndp = NULL;			/* Initialize window.	 */
210 	wp->w_linep = wp->w_dotp = bp->b_headp;
211 	wp->w_ntrows = nrow - 2;		/* 2 = mode, echo.	 */
212 	wp->w_rflag = WFMODE | WFFULL;		/* Full.		 */
213 }
214 
215 /*
216  * Quit command.  If an argument, always quit.  Otherwise confirm if a buffer
217  * has been changed and not written out.  Normally bound to "C-X C-C".
218  */
219 /* ARGSUSED */
220 int
221 quit(int f, int n)
222 {
223 	int	 s;
224 
225 	if ((s = anycb(FALSE)) == ABORT)
226 		return (ABORT);
227 	if (s == FALSE
228 	    || eyesno("Modified buffers exist; really exit") == TRUE) {
229 		vttidy();
230 		closetags();
231 		exit(GOOD);
232 	}
233 	return (TRUE);
234 }
235 
236 /*
237  * User abort.  Should be called by any input routine that sees a C-g to abort
238  * whatever C-g is aborting these days. Currently does nothing.
239  */
240 /* ARGSUSED */
241 int
242 ctrlg(int f, int n)
243 {
244 	return (ABORT);
245 }
246