xref: /openbsd-src/usr.bin/mg/main.c (revision db3296cf5c1dd9058ceecc3a29fe4aaa0bd26000)
1 /*	$OpenBSD: main.c,v 1.25 2003/06/26 23:04:10 vincent Exp $	*/
2 
3 /*
4  *	Mainline.
5  */
6 
7 #include	"def.h"
8 #include	"kbd.h"
9 #include	"funmap.h"
10 
11 #ifndef NO_MACRO
12 #include	"macro.h"
13 #endif	/* NO_MACRO */
14 
15 #include <err.h>
16 
17 int		 thisflag;			/* flags, this command	*/
18 int		 lastflag;			/* flags, last command	*/
19 int		 curgoal;			/* goal column		*/
20 int		 startrow;			/* row to start         */
21 BUFFER		*curbp;				/* current buffer	*/
22 BUFFER		*bheadp;			/* BUFFER listhead	*/
23 MGWIN		*curwp;				/* current window	*/
24 MGWIN		*wheadp;			/* MGWIN listhead	*/
25 char		 pat[NPAT];			/* pattern		*/
26 
27 static void	 edinit(PF);
28 
29 int
30 main(int argc, char **argv)
31 {
32 	char	*cp, *init_fcn_name = NULL;
33 	PF init_fcn = NULL;
34 	int o;
35 
36 	while ((o = getopt(argc, argv, "f:")) != -1)
37 		switch (o) {
38 		case 'f':
39 			if (init_fcn_name != NULL)
40 				errx(1, "cannot specify more than one "
41 				    "initial function");
42 			init_fcn_name = optarg;
43 			break;
44 		default:
45 			errx(1, "usage: mg [-f <mode>] [files...]");
46 		}
47 	argc -= optind;
48 	argv += optind;
49 
50 	maps_init();		/* Keymaps and modes.		*/
51 	funmap_init();		/* Functions.			*/
52 
53 	/*
54 	 * This is where we initialize standalone extensions that should
55 	 * be loaded dynamically sometime in the future.
56 	 */
57 	{
58 		extern void grep_init(void);
59 		extern void theo_init(void);
60 
61 		grep_init();
62 		theo_init();
63 		mail_init();
64 	}
65 
66 	if (init_fcn_name &&
67 	    (init_fcn = name_function(init_fcn_name)) == NULL)
68 		errx(1, "Unknown function `%s'", init_fcn_name);
69 
70 	vtinit();		/* Virtual terminal.		*/
71 #ifndef NO_DIR
72 	dirinit();		/* Get current directory.	*/
73 #endif	/* !NO_DIR */
74 	edinit(init_fcn);	/* Buffers, windows.		*/
75 	ttykeymapinit();	/* Symbols, bindings.		*/
76 
77 	/*
78 	 * doing update() before reading files causes the error messages from
79 	 * the file I/O show up on the screen.	(and also an extra display of
80 	 * the mode line if there are files specified on the command line.)
81 	 */
82 	update();
83 
84 #ifndef NO_STARTUP
85 	/* user startup file */
86 	if ((cp = startupfile(NULL)) != NULL)
87 		(void)load(cp);
88 #endif	/* !NO_STARTUP */
89 	while (argc > 0) {
90 		if (argv[0][0] == '+' && strlen(argv[0]) >= 2) {
91 			long lval;
92 			char *ep;
93 
94 			errno = 0;
95 			lval = strtoul(&argv[0][1], &ep, 10);
96 			if (argv[0][1] == '\0' || *ep != '\0')
97 				goto notnum;
98 			if ((errno == ERANGE &&
99 			    (lval == LONG_MAX || lval == LONG_MIN)) ||
100 			    (lval > INT_MAX || lval < INT_MIN))
101 				goto notnum;
102 			startrow = (int)lval;
103 		} else {
104 notnum:
105 			cp = adjustname(*argv);
106 			if (cp != NULL) {
107 				curbp = findbuffer(cp);
108 				(void)showbuffer(curbp, curwp, 0);
109 				(void)readin(cp);
110 				if (init_fcn_name)
111 					init_fcn(0, 1);
112 			}
113 		}
114 		argc--;
115 		argv++;
116 	}
117 
118 	/* fake last flags */
119 	thisflag = 0;
120 	for (;;) {
121 #ifndef NO_DPROMPT
122 		if (epresf == KPROMPT)
123 			eerase();
124 #endif	/* !NO_DPROMPT */
125 		if (winch_flag) {
126 			refresh(0, 0);
127 			winch_flag = 0;
128 		}
129 		update();
130 		lastflag = thisflag;
131 		thisflag = 0;
132 
133 		switch (doin()) {
134 		case TRUE:
135 			break;
136 		case ABORT:
137 			ewprintf("Quit");
138 			/* and fall through */
139 		case FALSE:
140 		default:
141 			ttbeep();
142 #ifndef NO_MACRO
143 			macrodef = FALSE;
144 #endif	/* !NO_MACRO */
145 		}
146 	}
147 }
148 
149 /*
150  * Initialize default buffer and window.
151  */
152 static void
153 edinit(PF init_fcn)
154 {
155 	BUFFER	*bp;
156 	MGWIN	*wp;
157 
158 	bheadp = NULL;
159 	bp = bfind("*scratch*", TRUE);		/* Text buffer.		 */
160 	wp = (MGWIN *)malloc(sizeof(MGWIN));	/* Initial window.	 */
161 	if (wp == NULL)
162 		panic("Out of memory");
163 	if (bp == NULL || wp == NULL)
164 		panic("edinit");
165 	curbp = bp;				/* Current ones.	 */
166 	wheadp = wp;
167 	curwp = wp;
168 	wp->w_wndp = NULL;			/* Initialize window.	 */
169 	wp->w_bufp = bp;
170 	bp->b_nwnd = 1;				/* Displayed.		 */
171 	wp->w_linep = wp->w_dotp = bp->b_linep;
172 	wp->w_doto = 0;
173 	wp->w_markp = NULL;
174 	wp->w_marko = 0;
175 	wp->w_toprow = 0;
176 	wp->w_ntrows = nrow - 2;		/* 2 = mode, echo.	 */
177 	wp->w_force = 0;
178 	wp->w_flag = WFMODE | WFHARD;		/* Full.		 */
179 
180 	if (init_fcn)
181 		init_fcn(0, 1);
182 }
183 
184 /*
185  * Quit command.  If an argument, always quit.  Otherwise confirm if a buffer
186  * has been changed and not written out.  Normally bound to "C-X C-C".
187  */
188 /* ARGSUSED */
189 int
190 quit(int f, int n)
191 {
192 	int	 s;
193 
194 	if ((s = anycb(FALSE)) == ABORT)
195 		return ABORT;
196 	if (s == FALSE
197 	    || eyesno("Some modified buffers exist, really exit") == TRUE) {
198 		vttidy();
199 #ifdef SYSCLEANUP
200 		SYSCLEANUP;
201 #endif	/* SYSCLEANUP */
202 		exit(GOOD);
203 	}
204 	return TRUE;
205 }
206 
207 /*
208  * User abort.  Should be called by any input routine that sees a C-g to abort
209  * whatever C-g is aborting these days. Currently does nothing.
210  */
211 /* ARGSUSED */
212 int
213 ctrlg(int f, int n)
214 {
215 	return (ABORT);
216 }
217