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