00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046 #include "compat.h"
00047
00048 #include <fstream>
00049 #include <string>
00050
00051
00052
00053
00054 #include "sys.h"
00055
00056 #include <sys/types.h>
00057 #include <sys/param.h>
00058 #include <string.h>
00059 #include <stdlib.h>
00060 #include <stdarg.h>
00061 #include "el.h"
00062
00063
00064
00065
00066 el_public EditLine_t*
00067 el_init(const char* prog, FILE* fin, FILE* fout, FILE* ferr) {
00068 EditLine_t* el = (EditLine_t*) el_malloc(sizeof(EditLine_t));
00069 #ifdef DEBUG
00070 char* tty;
00071 #endif
00072
00073 if (el == NULL) {
00074 return NULL;
00075 }
00076
00077 memset(el, 0, sizeof(EditLine_t));
00078
00079 el->fIn = fin;
00080 el->fInFD = fileno(fin);
00081 if (isatty(el->fInFD))
00082 el->fIn = 0;
00083
00084 el->fOutFile = fout;
00085 el->fErrFile = ferr;
00086 el->fProg = strdup(prog);
00087
00088
00089
00090
00091 el->fFlags = 0;
00092
00093 (void) term_init(el);
00094 (void) key_init(el);
00095 (void) map_init(el);
00096
00097 if (tty_init(el) == -1) {
00098 el->fFlags |= NO_TTY;
00099 }
00100 (void) ch_init(el);
00101 (void) search_init(el);
00102 (void) hist_init(el);
00103 (void) prompt_init(el);
00104 (void) sig_init(el);
00105
00106 return el;
00107 }
00108
00109
00110
00111
00112
00113 el_public void
00114 el_end(EditLine_t* el) {
00115 if (el == NULL) {
00116 return;
00117 }
00118
00119 el_reset(el);
00120
00121 term_end(el);
00122 key_end(el);
00123 map_end(el);
00124 tty_end(el);
00125 ch_end(el);
00126 search_end(el);
00127 hist_end(el);
00128 prompt_end(el);
00129 sig_end(el);
00130
00131 el_free((ptr_t) el->fProg);
00132 el_free((ptr_t) el);
00133 }
00134
00135
00136
00137
00138
00139 el_public void
00140 el_reset(EditLine_t* el) {
00141 tty_cookedmode(el);
00142 ch_reset(el);
00143 }
00144
00145
00146
00147
00148
00149 el_public int
00150 el_set(EditLine_t* el, int op, ...) {
00151 va_list va;
00152 int rv;
00153 va_start(va, op);
00154
00155 if (el == NULL) {
00156 va_end(va);
00157 return -1;
00158 }
00159
00160 switch (op) {
00161 case EL_PROMPT:
00162 case EL_RPROMPT:
00163 rv = prompt_set(el, va_arg(va, ElPFunc_t), op);
00164 break;
00165
00166 case EL_TERMINAL:
00167 rv = term_set(el, va_arg(va, char*));
00168 break;
00169
00170 case EL_EDITOR:
00171 rv = map_set_editor(el, va_arg(va, char*));
00172 break;
00173
00174 case EL_SIGNAL:
00175
00176 if (va_arg(va, int)) {
00177 el->fFlags |= HANDLE_SIGNALS;
00178 } else {
00179 el->fFlags &= ~HANDLE_SIGNALS;
00180 }
00181 rv = 0;
00182 break;
00183
00184 case EL_BIND:
00185 case EL_TELLTC:
00186 case EL_SETTC:
00187 case EL_ECHOTC:
00188 case EL_SETTY:
00189 {
00190 const char* argv[20];
00191 const char** cargv = 0;
00192 int i;
00193
00194 for (i = 1; i < 20; i++) {
00195 if ((argv[i] = va_arg(va, const char*)) == NULL) {
00196 break;
00197 }
00198 }
00199 argv[0] = argv[1];
00200 cargv = argv;
00201
00202 switch (op) {
00203 case EL_BIND:
00204 argv[0] = "bind";
00205 rv = map_bind(el, i, cargv);
00206 break;
00207
00208 case EL_TELLTC:
00209 argv[0] = "telltc";
00210 rv = term_telltc(el, i, cargv);
00211 break;
00212
00213 case EL_SETTC:
00214 argv[0] = "settc";
00215 rv = term_settc(el, i, cargv);
00216 break;
00217
00218 case EL_ECHOTC:
00219 argv[0] = "echotc";
00220 rv = term_echotc(el, i, cargv);
00221 break;
00222
00223 case EL_SETTY:
00224 argv[0] = "setty";
00225 rv = tty_stty(el, i, cargv);
00226 break;
00227
00228 default:
00229 rv = -1;
00230 EL_ABORT((el->fErrFile, "Bad op %d\n", op));
00231 break;
00232 }
00233 break;
00234 }
00235
00236 case EL_ADDFN:
00237 {
00238 char* name = va_arg(va, char*);
00239 char* help = va_arg(va, char*);
00240 ElFunc_t func = va_arg(va, ElFunc_t);
00241
00242 rv = map_addfunc(el, name, help, func);
00243 break;
00244 }
00245
00246 case EL_HIST:
00247 {
00248 HistFun_t func = va_arg(va, HistFun_t);
00249 ptr_t ptr = va_arg(va, char*);
00250
00251 rv = hist_set(el, func, ptr);
00252 break;
00253 }
00254
00255 case EL_EDITMODE:
00256
00257 if (va_arg(va, int)) {
00258 el->fFlags &= ~EDIT_DISABLED;
00259 } else {
00260 el->fFlags |= EDIT_DISABLED;
00261 }
00262 rv = 0;
00263 break;
00264
00265 default:
00266 rv = -1;
00267 }
00268
00269 va_end(va);
00270 return rv;
00271 }
00272
00273
00274
00275
00276
00277 el_public int
00278 el_get(EditLine_t* el, int op, void* ret) {
00279 int rv;
00280
00281 if (el == NULL || ret == NULL) {
00282 return -1;
00283 }
00284
00285 switch (op) {
00286 case EL_PROMPT:
00287 case EL_RPROMPT:
00288 {
00289 ElPFunc_t func;
00290 rv = prompt_get(el, &func, op);
00291 ret = (void*) func;
00292 break;
00293 }
00294
00295 case EL_EDITOR:
00296 {
00297 const char* str;
00298 rv = map_get_editor(el, &str);
00299 ret = (void*)str;
00300 break;
00301 }
00302
00303 case EL_SIGNAL:
00304 *((int*) ret) = (el->fFlags & HANDLE_SIGNALS);
00305 rv = 0;
00306 break;
00307
00308 case EL_EDITMODE:
00309 *((int*) ret) = (!(el->fFlags & EDIT_DISABLED));
00310 rv = 0;
00311 break;
00312
00313 #if 0
00314 case EL_TERMINAL:
00315 rv = term_get(el, (const char*) &ret);
00316 break;
00317
00318 case EL_BIND:
00319 case EL_TELLTC:
00320 case EL_SETTC:
00321 case EL_ECHOTC:
00322 case EL_SETTY:
00323 {
00324 char* argv[20];
00325 int i;
00326
00327 for (i = 1; i < 20; i++) {
00328 if ((argv[i] = va_arg(va, char*)) == NULL) {
00329 break;
00330 }
00331 }
00332
00333 switch (op) {
00334 case EL_BIND:
00335 argv[0] = "bind";
00336 rv = map_bind(el, i, argv);
00337 break;
00338
00339 case EL_TELLTC:
00340 argv[0] = "telltc";
00341 rv = term_telltc(el, i, argv);
00342 break;
00343
00344 case EL_SETTC:
00345 argv[0] = "settc";
00346 rv = term_settc(el, i, argv);
00347 break;
00348
00349 case EL_ECHOTC:
00350 argv[0] = "echotc";
00351 rv = term_echotc(el, i, argv);
00352 break;
00353
00354 case EL_SETTY:
00355 argv[0] = "setty";
00356 rv = tty_stty(el, i, argv);
00357 break;
00358
00359 default:
00360 rv = -1;
00361 EL_ABORT((el->errfile, "Bad op %d\n", op));
00362 break;
00363 }
00364 break;
00365 }
00366
00367 case EL_ADDFN:
00368 {
00369 char* name = va_arg(va, char*);
00370 char* help = va_arg(va, char*);
00371 ElFunc_t func = va_arg(va, ElFunc_t);
00372
00373 rv = map_addfunc(el, name, help, func);
00374 break;
00375 }
00376
00377 case EL_HIST:
00378 {
00379 HistFun_t func = va_arg(va, HistFun_t);
00380 ptr_t ptr = va_arg(va, char*);
00381 rv = hist_set(el, func, ptr);
00382 }
00383 break;
00384 #endif
00385
00386 default:
00387 rv = -1;
00388 }
00389
00390 return rv;
00391 }
00392
00393
00394
00395
00396
00397 el_public const LineInfo_t*
00398 el_line(EditLine_t* el) {
00399 return (const LineInfo_t*) (void*) &el->fLine;
00400 }
00401
00402
00403 static const char elpath[] = "/.editrc";
00404
00405
00406
00407
00408 el_public int
00409 el_source(EditLine_t* el, const char* fname) {
00410 char* ptr, path[MAXPATHLEN];
00411
00412 if (fname == NULL) {
00413 if ((ptr = getenv("HOME")) == NULL) {
00414 return -1;
00415 }
00416
00417 if (strlcpy(path, ptr, sizeof(path)) >= sizeof(path)) {
00418 return -1;
00419 }
00420
00421 if (strlcat(path, elpath, sizeof(path)) >= sizeof(path)) {
00422 return -1;
00423 }
00424 fname = path;
00425 }
00426
00427 std::ifstream in(fname);
00428 std::string line;
00429 while (in) {
00430 std::getline(in, line);
00431 if (parse_line(el, line.c_str()) == -1) {
00432 return -1;
00433 }
00434 }
00435
00436 return 0;
00437 }
00438
00439
00440
00441
00442
00443 el_public void
00444 el_resize(EditLine_t* el) {
00445 int lins, cols;
00446 sigset_t oset, nset;
00447
00448 (void) sigemptyset(&nset);
00449 (void) sigaddset(&nset, SIGWINCH);
00450 (void) sigprocmask(SIG_BLOCK, &nset, &oset);
00451
00452 int curHPos = el->fCursor.fH;
00453 int curVPos = el->fCursor.fV;
00454
00455
00456 int displen = el->fPrompt.fPos.fH;
00457 displen += el->fLine.fLastChar - el->fLine.fBuffer;
00458
00459 int nlines = displen / el->fTerm.fSize.fH;
00460
00461
00462 if (term_get_size(el, &lins, &cols)) {
00463 term_change_size(el, lins, cols);
00464 }
00465
00466
00467 el->fRefresh.r_oldcv = nlines;
00468
00469
00470
00471
00472 el->fCursor.fH = curHPos >= cols ? cols - 1 : curHPos;
00473
00474 el->fCursor.fV = curVPos;
00475 re_clear_lines(el);
00476 re_refresh(el);
00477 term__flush();
00478
00479 (void) sigprocmask(SIG_SETMASK, &oset, NULL);
00480 }
00481
00482
00483
00484
00485
00486 el_public void
00487 el_beep(EditLine_t* el) {
00488 term_beep(el);
00489 }
00490
00491
00492
00493
00494
00495 el_protected int
00496
00497 el_editmode(EditLine_t* el, int argc, const char** argv) {
00498 const char* how;
00499
00500 if (argv == NULL || argc != 2 || argv[1] == NULL) {
00501 (void) fprintf(el->fErrFile, "edit: Usage error. Pass 'on' or 'off' to enable or disable line-editing mode.\n");
00502 return -1;
00503 }
00504
00505 how = argv[1];
00506
00507 if (strcmp(how, "on") == 0) {
00508 el->fFlags &= ~EDIT_DISABLED;
00509 } else if (strcmp(how, "off") == 0) {
00510 el->fFlags |= EDIT_DISABLED;
00511 } else {
00512 (void) fprintf(el->fErrFile, "edit: Bad value `%s'.\n", how);
00513 return -1;
00514 }
00515 return 0;
00516 }