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