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