]> pd.if.org Git - pd_readline/blob - mg/main.c
Added mg from an OpenBSD mirror site. Many thanks to the OpenBSD team and the mg...
[pd_readline] / mg / main.c
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 }