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