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
00049
00050
00051
00052
00053 #include "sys.h"
00054 #include <stdio.h>
00055 #include <signal.h>
00056 #include <string.h>
00057 #include <stdlib.h>
00058 #include <unistd.h>
00059 #include <sys/types.h>
00060 #include <sys/ioctl.h>
00061 #include <string>
00062
00063 #include "el.h"
00064 #include "TTermManip.h"
00065
00066
00067
00068 #include "rlcurses.h"
00069
00070
00071
00072
00073
00074
00075
00076
00077 #define TC_BUFSIZE 2048
00078
00079 #define GoodStr(a) (el->fTerm.fStr[a] != NULL && \
00080 el->fTerm.fStr[a][0] != '\0')
00081 #define Str(a) el->fTerm.fStr[a]
00082 #define Val(a) el->fTerm.fVal[a]
00083
00084 #ifdef notdef
00085 el_private const struct {
00086 const char* b_name;
00087 int b_rate;
00088 } baud_rate[] = {
00089 # ifdef B0
00090 { "0", B0 },
00091 # endif
00092 # ifdef B50
00093 { "50", B50 },
00094 # endif
00095 # ifdef B75
00096 { "75", B75 },
00097 # endif
00098 # ifdef B110
00099 { "110", B110 },
00100 # endif
00101 # ifdef B134
00102 { "134", B134 },
00103 # endif
00104 # ifdef B150
00105 { "150", B150 },
00106 # endif
00107 # ifdef B200
00108 { "200", B200 },
00109 # endif
00110 # ifdef B300
00111 { "300", B300 },
00112 # endif
00113 # ifdef B600
00114 { "600", B600 },
00115 # endif
00116 # ifdef B900
00117 { "900", B900 },
00118 # endif
00119 # ifdef B1200
00120 { "1200", B1200 },
00121 # endif
00122 # ifdef B1800
00123 { "1800", B1800 },
00124 # endif
00125 # ifdef B2400
00126 { "2400", B2400 },
00127 # endif
00128 # ifdef B3600
00129 { "3600", B3600 },
00130 # endif
00131 # ifdef B4800
00132 { "4800", B4800 },
00133 # endif
00134 # ifdef B7200
00135 { "7200", B7200 },
00136 # endif
00137 # ifdef B9600
00138 { "9600", B9600 },
00139 # endif
00140 # ifdef EXTA
00141 { "19200", EXTA },
00142 # endif
00143 # ifdef B19200
00144 { "19200", B19200 },
00145 # endif
00146 # ifdef EXTB
00147 { "38400", EXTB },
00148 # endif
00149 # ifdef B38400
00150 { "38400", B38400 },
00151 # endif
00152 { NULL, 0 }
00153 };
00154 #endif
00155
00156 el_private const struct TermCapStr_t {
00157 const char* fName;
00158 const char* fLongName;
00159 } tstr[] = {
00160 #define T_al 0
00161 { "al", "add new blank line" },
00162 #define T_bl 1
00163 { "bl", "audible bell" },
00164 #define T_cd 2
00165 { "cd", "clear to bottom" },
00166 #define T_ce 3
00167 { "ce", "clear to end of line" },
00168 #define T_ch 4
00169 { "ch", "cursor to horiz pos" },
00170 #define T_cl 5
00171 { "cl", "clear screen" },
00172 #define T_dc 6
00173 { "dc", "delete a character" },
00174 #define T_dl 7
00175 { "dl", "delete a line" },
00176 #define T_dm 8
00177 { "dm", "start delete mode" },
00178 #define T_ed 9
00179 { "ed", "end delete mode" },
00180 #define T_ei 10
00181 { "ei", "end insert mode" },
00182 #define T_fs 11
00183 { "fs", "cursor from status line" },
00184 #define T_ho 12
00185 { "ho", "home cursor" },
00186 #define T_ic 13
00187 { "ic", "insert character" },
00188 #define T_im 14
00189 { "im", "start insert mode" },
00190 #define T_ip 15
00191 { "ip", "insert padding" },
00192 #define T_kd 16
00193 { "kd", "sends cursor down" },
00194 #define T_kl 17
00195 { "kl", "sends cursor left" },
00196 #define T_kr 18
00197 { "kr", "sends cursor right" },
00198 #define T_ku 19
00199 { "ku", "sends cursor up" },
00200 #define T_md 20
00201 { "md", "begin bold" },
00202 #define T_me 21
00203 { "me", "end attributes" },
00204 #define T_nd 22
00205 { "nd", "non destructive space" },
00206 #define T_se 23
00207 { "se", "end standout" },
00208 #define T_so 24
00209 { "so", "begin standout" },
00210 #define T_ts 25
00211 { "ts", "cursor to status line" },
00212 #define T_up 26
00213 { "up", "cursor up one" },
00214 #define T_us 27
00215 { "us", "begin underline" },
00216 #define T_ue 28
00217 { "ue", "end underline" },
00218 #define T_vb 29
00219 { "vb", "visible bell" },
00220 #define T_DC 30
00221 { "DC", "delete multiple chars" },
00222 #define T_DO 31
00223 { "DO", "cursor down multiple" },
00224 #define T_IC 32
00225 { "IC", "insert multiple chars" },
00226 #define T_LE 33
00227 { "LE", "cursor left multiple" },
00228 #define T_RI 34
00229 { "RI", "cursor right multiple" },
00230 #define T_UP 35
00231 { "UP", "cursor up multiple" },
00232 #define T_kh 36
00233 { "kh", "send cursor home" },
00234 #define T_at7 37
00235 { "@7", "send cursor end" },
00236 #define T_kD 38
00237 { "kD", "delete a character" },
00238 #define T_str 39
00239 { NULL, NULL }
00240 };
00241
00242 el_private const struct TermCapVal_t {
00243 const char* fName;
00244 const char* fLongName;
00245 } tval[] = {
00246 #define T_am 0
00247 { "am", "has automatic margins" },
00248 #define T_pt 1
00249 { "pt", "has physical tabs" },
00250 #define T_li 2
00251 { "li", "Number of lines" },
00252 #define T_co 3
00253 { "co", "Number of columns" },
00254 #define T_km 4
00255 { "km", "Has meta key" },
00256 #define T_xt 5
00257 { "xt", "Tab chars destructive" },
00258 #define T_xn 6
00259 { "xn", "newline ignored at right margin" },
00260 #define T_MT 7
00261 { "MT", "Has meta key" },
00262 #define T_val 8
00263 { NULL, NULL, }
00264 };
00265
00266
00267 el_private void term_setflags(EditLine_t*);
00268 el_private int term_rebuffer_display(EditLine_t*);
00269 el_private void term_free_display(EditLine_t*);
00270 el_private int term_alloc_display(EditLine_t*);
00271 el_private void term_alloc(EditLine_t*, const struct TermCapStr_t*, const char*);
00272 el_private void term_init_arrow(EditLine_t*);
00273 el_private void term_reset_arrow(EditLine_t*);
00274 el_private void term_init_color(EditLine_t*);
00275
00276
00277 el_private FILE* term_outfile = NULL;
00278
00279
00280
00281
00282
00283 el_private void
00284 term_setflags(EditLine_t* el) {
00285 EL_FLAGS = 0;
00286
00287 if (el->fTTY.t_tabs) {
00288 EL_FLAGS |= (Val(T_pt) && !Val(T_xt)) ? TERM_CAN_TAB : 0;
00289 }
00290
00291 EL_FLAGS |= (Val(T_km) || Val(T_MT)) ? TERM_HAS_META : 0;
00292 EL_FLAGS |= GoodStr(T_ce) ? TERM_CAN_CEOL : 0;
00293 EL_FLAGS |= (GoodStr(T_dc) || GoodStr(T_DC)) ? TERM_CAN_DELETE : 0;
00294 EL_FLAGS |= (GoodStr(T_im) || GoodStr(T_ic) || GoodStr(T_IC)) ?
00295 TERM_CAN_INSERT : 0;
00296 EL_FLAGS |= (GoodStr(T_up) || GoodStr(T_UP)) ? TERM_CAN_UP : 0;
00297 EL_FLAGS |= Val(T_am) ? TERM_HAS_AUTO_MARGINS : 0;
00298 EL_FLAGS |= Val(T_xn) ? TERM_HAS_MAGIC_MARGINS : 0;
00299
00300 if (GoodStr(T_me) && GoodStr(T_ue)) {
00301 EL_FLAGS |= (strcmp(Str(T_me), Str(T_ue)) == 0) ?
00302 TERM_CAN_ME : 0;
00303 } else {
00304 EL_FLAGS &= ~TERM_CAN_ME;
00305 }
00306
00307 if (GoodStr(T_me) && GoodStr(T_se)) {
00308 EL_FLAGS |= (strcmp(Str(T_me), Str(T_se)) == 0) ?
00309 TERM_CAN_ME : 0;
00310 }
00311
00312
00313 #ifdef DEBUG_SCREEN
00314
00315 if (!EL_CAN_UP) {
00316 (void) fprintf(el->fErrFile,
00317 "WARNING: Your terminal cannot move up.\n");
00318 (void) fprintf(el->fErrFile,
00319 "Editing may be odd for long lines.\n");
00320 }
00321
00322 if (!EL_CAN_CEOL) {
00323 (void) fprintf(el->fErrFile, "no clear EOL capability.\n");
00324 }
00325
00326 if (!EL_CAN_DELETE) {
00327 (void) fprintf(el->fErrFile, "no delete char capability.\n");
00328 }
00329
00330 if (!EL_CAN_INSERT) {
00331 (void) fprintf(el->fErrFile, "no insert char capability.\n");
00332 }
00333 #endif
00334 }
00335
00336
00337
00338
00339
00340 el_protected int
00341 term_init(EditLine_t* el) {
00342 el->fTerm.fBuf = (char*) el_malloc(TC_BUFSIZE);
00343
00344 if (el->fTerm.fBuf == NULL) {
00345 return -1;
00346 }
00347 el->fTerm.fCap = (char*) el_malloc(TC_BUFSIZE);
00348
00349 if (el->fTerm.fCap == NULL) {
00350 return -1;
00351 }
00352 el->fTerm.fFKey = (FKey_t*) el_malloc(A_K_NKEYS * sizeof(FKey_t));
00353
00354 if (el->fTerm.fFKey == NULL) {
00355 return -1;
00356 }
00357 el->fTerm.fLoc = 0;
00358 el->fTerm.fStr = (char**) el_malloc(T_str * sizeof(char*));
00359
00360 if (el->fTerm.fStr == NULL) {
00361 return -1;
00362 }
00363 (void) memset(el->fTerm.fStr, 0, T_str * sizeof(char*));
00364 el->fTerm.fVal = (int*) el_malloc(T_val * sizeof(int));
00365
00366 if (el->fTerm.fVal == NULL) {
00367 return -1;
00368 }
00369 (void) memset(el->fTerm.fVal, 0, T_val * sizeof(int));
00370 term_outfile = el->fOutFile;
00371
00372 if (term_set(el, NULL) == -1) {
00373 return -1;
00374 }
00375 term_init_arrow(el);
00376
00377 term_init_color(el);
00378
00379 return 0;
00380 }
00381
00382
00383
00384
00385
00386 el_protected void
00387 term_end(EditLine_t* el) {
00388 el_free((ptr_t) el->fTerm.fBuf);
00389 el->fTerm.fBuf = NULL;
00390 el_free((ptr_t) el->fTerm.fCap);
00391 el->fTerm.fCap = NULL;
00392 el->fTerm.fLoc = 0;
00393 el_free((ptr_t) el->fTerm.fStr);
00394 el->fTerm.fStr = NULL;
00395 el_free((ptr_t) el->fTerm.fVal);
00396 el->fTerm.fVal = NULL;
00397 term_free_display(el);
00398 }
00399
00400
00401
00402
00403
00404 el_private void
00405 term_alloc(EditLine_t* el, const struct TermCapStr_t* t, const char* cap) {
00406 char termbuf[TC_BUFSIZE];
00407 int tlen, clen;
00408 char** tlist = el->fTerm.fStr;
00409 char** tmp, ** str = &tlist[t - tstr];
00410
00411 if (cap == NULL || *cap == '\0') {
00412 *str = NULL;
00413 return;
00414 } else {
00415 clen = strlen(cap);
00416 }
00417
00418 tlen = *str == NULL ? 0 : strlen(*str);
00419
00420
00421
00422
00423 if (clen <= tlen) {
00424
00425 (void) strcpy(*str, cap);
00426 return;
00427 }
00428
00429
00430
00431
00432 if (el->fTerm.fLoc + 3 < TC_BUFSIZE) {
00433
00434
00435 (void) strcpy(*str = &el->fTerm.fBuf[el->fTerm.fLoc],
00436 cap);
00437 el->fTerm.fLoc += clen + 1;
00438 return;
00439 }
00440
00441
00442
00443
00444
00445 tlen = 0;
00446
00447 for (tmp = tlist; tmp < &tlist[T_str]; tmp++) {
00448 if (*tmp != NULL && *tmp != '\0' && *tmp != *str) {
00449 char* ptr;
00450
00451 for (ptr = *tmp; *ptr != '\0'; termbuf[tlen++] = *ptr++) {
00452 continue;
00453 }
00454 termbuf[tlen++] = '\0';
00455 }
00456 }
00457 memcpy(el->fTerm.fBuf, termbuf, TC_BUFSIZE);
00458 el->fTerm.fLoc = tlen;
00459
00460 if (el->fTerm.fLoc + 3 >= TC_BUFSIZE) {
00461 (void) fprintf(el->fErrFile,
00462 "Out of termcap string space.\n");
00463 return;
00464 }
00465
00466
00467 (void) strcpy(*str = &el->fTerm.fBuf[el->fTerm.fLoc], cap);
00468 el->fTerm.fLoc += clen + 1;
00469 return;
00470 }
00471
00472
00473
00474
00475
00476 el_private int
00477 term_rebuffer_display(EditLine_t* el) {
00478 ElCoord_t* c = &el->fTerm.fSize;
00479
00480 term_free_display(el);
00481
00482 c->fH = Val(T_co);
00483 c->fV = Val(T_li);
00484
00485 if (term_alloc_display(el) == -1) {
00486 return -1;
00487 }
00488 return 0;
00489 }
00490
00491
00492
00493
00494
00495 el_private int
00496 term_alloc_display(EditLine_t* el) {
00497 int i;
00498 char** b;
00499 ElColor_t** col;
00500 ElCoord_t* c = &el->fTerm.fSize;
00501
00502
00503 b = (char**) el_malloc((size_t) (sizeof(char*) * (c->fV + 1)));
00504
00505 if (b == NULL) {
00506 return -1;
00507 }
00508
00509 for (i = 0; i < c->fV; i++) {
00510 b[i] = (char*) el_malloc((size_t) (sizeof(char) * (c->fH + 1)));
00511
00512 if (b[i] == NULL) {
00513 el_free((ptr_t) b);
00514 return -1;
00515 }
00516 }
00517 b[c->fV] = NULL;
00518 el->fDisplay = b;
00519
00520
00521 col = (ElColor_t**) el_malloc((size_t) (sizeof(ElColor_t*) * (c->fV + 1)));
00522
00523 if (col == NULL) {
00524 return -1;
00525 }
00526
00527 for (i = 0; i < c->fV; i++) {
00528 col[i] = (ElColor_t*) el_malloc((size_t) (sizeof(ElColor_t) * (c->fH + 1)));
00529
00530 if (col[i] == NULL) {
00531 el_free((ptr_t) col);
00532 return -1;
00533 }
00534 }
00535 col[c->fV] = NULL;
00536 el->fDispColor = col;
00537
00538
00539 b = (char**) el_malloc((size_t) (sizeof(char*) * (c->fV + 1)));
00540
00541 if (b == NULL) {
00542 return -1;
00543 }
00544
00545 for (i = 0; i < c->fV; i++) {
00546 b[i] = (char*) el_malloc((size_t) (sizeof(char) * (c->fH + 1)));
00547
00548 if (b[i] == NULL) {
00549 for (int ii = 0; ii < i; ++ii) {
00550 el_free((ptr_t) b[ii]);
00551 }
00552 el_free((ptr_t) b);
00553 return -1;
00554 }
00555 }
00556 b[c->fV] = NULL;
00557 el->fVDisplay = b;
00558
00559
00560 col = (ElColor_t**) el_malloc((size_t) (sizeof(ElColor_t*) * (c->fV + 1)));
00561
00562 if (col == NULL) {
00563 return -1;
00564 }
00565
00566 for (i = 0; i < c->fV; i++) {
00567 col[i] = (ElColor_t*) el_malloc((size_t) (sizeof(ElColor_t) * (c->fH + 1)));
00568
00569 if (col[i] == NULL) {
00570 for (int ii = 0; ii < i; ++ii) {
00571 el_free((ptr_t) col[ii]);
00572 }
00573 el_free((ptr_t) col);
00574 return -1;
00575 }
00576 }
00577 col[c->fV] = NULL;
00578 el->fVDispColor = col;
00579
00580 return 0;
00581 }
00582
00583
00584
00585
00586
00587 el_private void
00588 term_free_display(EditLine_t* el) {
00589 char** b;
00590 char** bufp;
00591 ElColor_t** c;
00592 ElColor_t** bufc;
00593
00594
00595 b = el->fDisplay;
00596 el->fDisplay = NULL;
00597
00598 if (b != NULL) {
00599 for (bufp = b; *bufp != NULL; bufp++) {
00600 el_free((ptr_t) *bufp);
00601 }
00602 el_free((ptr_t) b);
00603 }
00604
00605
00606 c = el->fDispColor;
00607 el->fDispColor = NULL;
00608
00609 if (c != NULL) {
00610 for (bufc = c; *bufc != NULL; bufc++) {
00611 el_free((ptr_t) *bufc);
00612 }
00613 el_free((ptr_t) c);
00614 }
00615
00616
00617 b = el->fVDisplay;
00618 el->fVDisplay = NULL;
00619
00620 if (b != NULL) {
00621 for (bufp = b; *bufp != NULL; bufp++) {
00622 el_free((ptr_t) *bufp);
00623 }
00624 el_free((ptr_t) b);
00625 }
00626
00627
00628 c = el->fVDispColor;
00629 el->fVDispColor = NULL;
00630
00631 if (c != NULL) {
00632 for (bufc = c; *bufc != NULL; bufc++) {
00633 el_free((ptr_t) *bufc);
00634 }
00635 el_free((ptr_t) c);
00636 }
00637 }
00638
00639
00640
00641
00642
00643
00644 el_protected void
00645 term_move_to_line(EditLine_t* el, int where) {
00646 int del;
00647
00648 if (where == el->fCursor.fV) {
00649 return;
00650 }
00651
00652 if (where > el->fTerm.fSize.fV) {
00653 #ifdef DEBUG_SCREEN
00654 (void) fprintf(el->fErrFile,
00655 "term_move_to_line: where is ridiculous: %d\r\n", where);
00656 #endif
00657 return;
00658 }
00659
00660 if ((del = where - el->fCursor.fV) > 0) {
00661 while (del > 0) {
00662 if (EL_HAS_AUTO_MARGINS &&
00663 el->fDisplay[el->fCursor.fV][0] != '\0') {
00664
00665 term_move_to_char(el, el->fTerm.fSize.fH - 1);
00666 term_overwrite(el,
00667 &el->fDisplay[el->fCursor.fV][el->fCursor.fH],
00668 &el->fDispColor[el->fCursor.fV][el->fCursor.fH],
00669 1);
00670
00671 del--;
00672 } else {
00673 if ((del > 1) && GoodStr(T_DO)) {
00674 (void) tputs(tgoto(Str(T_DO), del, del), del, term__putc);
00675 del = 0;
00676 } else {
00677 for ( ; del > 0; del--) {
00678 term__putcolorch('\n', NULL);
00679 }
00680
00681 el->fCursor.fH = 0;
00682 }
00683 }
00684 }
00685 } else {
00686 if (GoodStr(T_UP) && (-del > 1 || !GoodStr(T_up))) {
00687 (void) tputs(tgoto(Str(T_UP), -del, -del), -del, term__putc);
00688 } else {
00689 if (GoodStr(T_up)) {
00690 for ( ; del < 0; del++) {
00691 (void) tputs(Str(T_up), 1, term__putc);
00692 }
00693 }
00694 }
00695 }
00696 el->fCursor.fV = where;
00697 }
00698
00699
00700
00701
00702
00703 el_protected void
00704 term_move_to_char(EditLine_t* el, int where) {
00705 int del, i;
00706
00707 mc_again:
00708
00709 if (where == el->fCursor.fH) {
00710 return;
00711 }
00712
00713 if (where > el->fTerm.fSize.fH) {
00714 #ifdef DEBUG_SCREEN
00715 (void) fprintf(el->fErrFile,
00716 "term_move_to_char: where is riduculous: %d\r\n", where);
00717 #endif
00718 return;
00719 }
00720
00721 if (!where) {
00722 term__putcolorch('\r', NULL);
00723 el->fCursor.fH = 0;
00724 return;
00725 }
00726 del = where - el->fCursor.fH;
00727
00728 if ((del < -4 || del > 4) && GoodStr(T_ch)) {
00729
00730 (void) tputs(tgoto(Str(T_ch), where, where), where, term__putc);
00731 } else {
00732 if (del > 0) {
00733 if ((del > 4) && GoodStr(T_RI)) {
00734 (void) tputs(tgoto(Str(T_RI), del, del), del, term__putc);
00735 } else {
00736
00737 if (EL_CAN_TAB) {
00738 if ((el->fCursor.fH & 0370) !=
00739 (where & 0370)) {
00740
00741 for (i =
00742 (el->fCursor.fH & 0370);
00743 i < (where & 0370);
00744 i += 8) {
00745 term__putcolorch('\t', NULL);
00746 }
00747
00748 el->fCursor.fH = where & 0370;
00749 }
00750 }
00751
00752
00753
00754
00755
00756
00757
00758
00759
00760
00761 term_overwrite(el,
00762 &el->fDisplay[el->fCursor.fV][el->fCursor.fH],
00763 &el->fDispColor[el->fCursor.fV][el->fCursor.fH],
00764 where - el->fCursor.fH);
00765
00766 }
00767 } else {
00768 if ((-del > 4) && GoodStr(T_LE)) {
00769 (void) tputs(tgoto(Str(T_LE), -del, -del), -del, term__putc);
00770 } else {
00771
00772
00773
00774
00775 if (EL_CAN_TAB ?
00776 (-del > ((where >> 3) +
00777 (where & 07)))
00778 : (-del > where)) {
00779 term__putcolorch('\r', NULL);
00780 el->fCursor.fH = 0;
00781 goto mc_again;
00782 }
00783
00784 for (i = 0; i < -del; i++) {
00785 term__putcolorch('\b', &el->fDispColor[el->fCursor.fV][el->fCursor.fH]);
00786 }
00787 }
00788 }
00789 }
00790 el->fCursor.fH = where;
00791 }
00792
00793
00794
00795
00796
00797 el_protected void
00798 term_overwrite(EditLine_t* el, const char* cp, ElColor_t* color, int n) {
00799 if (n <= 0) {
00800 return;
00801
00802 }
00803
00804 if (n > el->fTerm.fSize.fH) {
00805 #ifdef DEBUG_SCREEN
00806 (void) fprintf(el->fErrFile,
00807 "term_overwrite: n is riduculous: %d\r\n", n);
00808 #endif
00809 return;
00810 }
00811
00812 do {
00813 if (color) {
00814 el->fDispColor[el->fCursor.fV][el->fCursor.fH] = *color;
00815 }
00816 term__putcolorch(*cp++, color ? color++ : 0);
00817 el->fCursor.fH++;
00818 }
00819 while (--n);
00820
00821 if (el->fCursor.fH >= el->fTerm.fSize.fH) {
00822 if (EL_HAS_AUTO_MARGINS) {
00823 el->fCursor.fH = 0;
00824 el->fCursor.fV++;
00825
00826 if (EL_HAS_MAGIC_MARGINS) {
00827
00828
00829 char c;
00830
00831 if ((c = el->fDisplay[el->fCursor.fV][el->fCursor.fH]) != '\0') {
00832 term_overwrite(el, &c, &el->fDispColor[el->fCursor.fV][el->fCursor.fH], 1);
00833 } else {
00834 term__putcolorch(' ', NULL);
00835 }
00836 el->fCursor.fH = 1;
00837 }
00838 } else {
00839 el->fCursor.fH = el->fTerm.fSize.fH;
00840 }
00841 }
00842 }
00843
00844
00845
00846
00847
00848 el_protected void
00849 term_deletechars(EditLine_t* el, int num) {
00850 if (num <= 0) {
00851 return;
00852 }
00853
00854 if (!EL_CAN_DELETE) {
00855 #ifdef DEBUG_EDIT
00856 (void) fprintf(el->fErrFile, " ERROR: cannot delete \n");
00857 #endif
00858 return;
00859 }
00860
00861 if (num > el->fTerm.fSize.fH) {
00862 #ifdef DEBUG_SCREEN
00863 (void) fprintf(el->fErrFile,
00864 "term_deletechars: num is riduculous: %d\r\n", num);
00865 #endif
00866 return;
00867 }
00868
00869 if (GoodStr(T_DC)) {
00870 if ((num > 1) || !GoodStr(T_dc)) {
00871
00872 (void) tputs(tgoto(Str(T_DC), num, num), num, term__putc);
00873 return;
00874 }
00875 }
00876
00877 if (GoodStr(T_dm)) {
00878 (void) tputs(Str(T_dm), 1, term__putc);
00879 }
00880
00881 if (GoodStr(T_dc)) {
00882 while (num--)
00883 (void) tputs(Str(T_dc), 1, term__putc);
00884 }
00885
00886 if (GoodStr(T_ed)) {
00887 (void) tputs(Str(T_ed), 1, term__putc);
00888 }
00889 }
00890
00891
00892
00893
00894
00895
00896 el_protected void
00897 term_insertwrite(EditLine_t* el, const char* cp, ElColor_t* color, int num) {
00898 if (num <= 0) {
00899 return;
00900 }
00901
00902 if (!EL_CAN_INSERT) {
00903 #ifdef DEBUG_EDIT
00904 (void) fprintf(el->fErrFile, " ERROR: cannot insert \n");
00905 #endif
00906 return;
00907 }
00908
00909 if (num > el->fTerm.fSize.fH) {
00910 #ifdef DEBUG_SCREEN
00911 (void) fprintf(el->fErrFile,
00912 "StartInsert: num is riduculous: %d\r\n", num);
00913 #endif
00914 return;
00915 }
00916
00917 if (GoodStr(T_IC)) {
00918 if ((num > 1) || !GoodStr(T_ic)) {
00919
00920
00921 (void) tputs(tgoto(Str(T_IC), num, num), num, term__putc);
00922 term_overwrite(el, cp, color, num);
00923
00924
00925 return;
00926 }
00927 }
00928
00929 if (GoodStr(T_im) && GoodStr(T_ei)) {
00930 (void) tputs(Str(T_im), 1, term__putc);
00931
00932 el->fCursor.fH += num;
00933
00934 do {
00935
00936 term__putcolorch(*cp++, color ? color++ : 0);
00937 }
00938 while (--num);
00939
00940 if (GoodStr(T_ip)) {
00941 (void) tputs(Str(T_ip), 1, term__putc);
00942 }
00943
00944 (void) tputs(Str(T_ei), 1, term__putc);
00945 return;
00946 }
00947
00948 do {
00949 if (GoodStr(T_ic)) {
00950 (void) tputs(Str(T_ic), 1, term__putc);
00951 }
00952
00953 term__putcolorch(*cp++, color ? color++ : 0);
00954
00955 el->fCursor.fH++;
00956
00957 if (GoodStr(T_ip)) {
00958 (void) tputs(Str(T_ip), 1, term__putc);
00959 }
00960
00961
00962 }
00963 while (--num);
00964 }
00965
00966
00967
00968
00969
00970 el_protected void
00971 term_clear_EOL(EditLine_t* el, int num) {
00972 int i;
00973
00974 if (EL_CAN_CEOL && GoodStr(T_ce)) {
00975 (void) tputs(Str(T_ce), 1, term__putc);
00976 } else {
00977 for (i = 0; i < num; i++) {
00978 term__putcolorch(' ', NULL);
00979 }
00980 el->fCursor.fH += num;
00981 }
00982 }
00983
00984
00985
00986
00987
00988 el_protected void
00989 term_clear_screen(EditLine_t* el) {
00990 if (GoodStr(T_cl)) {
00991
00992 (void) tputs(Str(T_cl), Val(T_li), term__putc);
00993 } else if (GoodStr(T_ho) && GoodStr(T_cd)) {
00994 (void) tputs(Str(T_ho), Val(T_li), term__putc);
00995
00996 (void) tputs(Str(T_cd), Val(T_li), term__putc);
00997 } else {
00998 term__putcolorch('\r', NULL);
00999 term__putcolorch('\n', NULL);
01000 }
01001 }
01002
01003
01004
01005
01006
01007 el_protected void
01008 term_beep(EditLine_t* el) {
01009 if (GoodStr(T_bl)) {
01010
01011 (void) tputs(Str(T_bl), 1, term__putc);
01012 } else {
01013 term__putcolorch('\007', NULL);
01014 }
01015 }
01016
01017
01018 #ifdef notdef
01019
01020
01021
01022
01023 el_protected void
01024 term_clear_to_bottom(EditLine_t* el) {
01025 if (GoodStr(T_cd)) {
01026 (void) tputs(Str(T_cd), Val(T_li), term__putc);
01027 } else if (GoodStr(T_ce)) {
01028 (void) tputs(Str(T_ce), Val(T_li), term__putc);
01029 }
01030 }
01031
01032
01033 #endif
01034
01035
01036
01037
01038
01039 el_protected int
01040 term_set(EditLine_t* el, const char* term) {
01041 int i;
01042 char buf[TC_BUFSIZE];
01043 char* area;
01044 const struct TermCapStr_t* t;
01045 sigset_t oset, nset;
01046 int lins, cols;
01047
01048 (void) sigemptyset(&nset);
01049 (void) sigaddset(&nset, SIGWINCH);
01050 (void) sigprocmask(SIG_BLOCK, &nset, &oset);
01051
01052 area = buf;
01053
01054 if (term == NULL) {
01055 term = getenv("TERM");
01056 }
01057
01058 if (!term || !term[0]
01059 || !isatty(0)
01060 || !isatty(1)) {
01061 term = "dumb";
01062 }
01063
01064 if (strcmp(term, "emacs") == 0
01065 || !isatty(0)) {
01066 el->fFlags |= EDIT_DISABLED;
01067 }
01068
01069 memset(el->fTerm.fCap, 0, TC_BUFSIZE);
01070
01071 i = tgetent(el->fTerm.fCap, term);
01072
01073 if (i <= 0) {
01074 if (i == -1) {
01075 (void) fprintf(el->fErrFile,
01076 "Cannot read termcap database;\n");
01077 } else if (i == 0) {
01078 (void) fprintf(el->fErrFile,
01079 "No entry for terminal type \"%s\";\n", term);
01080 }
01081 (void) fprintf(el->fErrFile,
01082 "using dumb terminal settings.\n");
01083 Val(T_co) = 80;
01084 Val(T_pt) = Val(T_km) = Val(T_li) = 0;
01085 Val(T_xt) = Val(T_MT);
01086
01087 for (t = tstr; t->fName != NULL; t++) {
01088 term_alloc(el, t, NULL);
01089 }
01090 } else {
01091
01092 Val(T_am) = tgetflag((char*)"am");
01093 Val(T_xn) = tgetflag((char*)"xn");
01094
01095 Val(T_pt) = tgetflag((char*)"pt");
01096 Val(T_xt) = tgetflag((char*)"xt");
01097
01098 Val(T_km) = tgetflag((char*)"km");
01099 Val(T_MT) = tgetflag((char*)"MT");
01100
01101 Val(T_co) = tgetnum((char*)"co");
01102 Val(T_li) = tgetnum((char*)"li");
01103
01104 for (t = tstr; t->fName != NULL; t++) {
01105 term_alloc(el, t, tgetstr((char*)t->fName, &area));
01106 }
01107 }
01108
01109 if (Val(T_co) < 2) {
01110 Val(T_co) = 80;
01111 }
01112
01113 if (Val(T_li) < 1) {
01114 Val(T_li) = 24;
01115 }
01116
01117 el->fTerm.fSize.fV = Val(T_co);
01118 el->fTerm.fSize.fH = Val(T_li);
01119
01120 term_setflags(el);
01121
01122
01123 (void) term_get_size(el, &lins, &cols);
01124
01125 if (term_change_size(el, lins, cols) == -1) {
01126 return -1;
01127 }
01128 (void) sigprocmask(SIG_SETMASK, &oset, NULL);
01129 term_bind_arrow(el);
01130 return i <= 0 ? -1 : 0;
01131 }
01132
01133
01134
01135
01136
01137
01138 el_protected int
01139 term_get_size(EditLine_t* el, int* lins, int* cols) {
01140 *cols = Val(T_co);
01141 *lins = Val(T_li);
01142
01143 #ifdef TIOCGWINSZ
01144 {
01145 struct winsize ws;
01146
01147 if (ioctl(el->fInFD, TIOCGWINSZ, (ioctl_t) &ws) != -1) {
01148 if (ws.ws_col) {
01149 *cols = ws.ws_col;
01150 }
01151
01152 if (ws.ws_row) {
01153 *lins = ws.ws_row;
01154 }
01155 }
01156 }
01157 #endif
01158 #ifdef TIOCGSIZE
01159 {
01160 struct ttysize ts;
01161
01162 if (ioctl(el->fInFD, TIOCGSIZE, (ioctl_t) &ts) != -1) {
01163 if (ts.ts_cols) {
01164 *cols = ts.ts_cols;
01165 }
01166
01167 if (ts.ts_lines) {
01168 *lins = ts.ts_lines;
01169 }
01170 }
01171 }
01172 #endif
01173 return Val(T_co) != *cols || Val(T_li) != *lins;
01174 }
01175
01176
01177
01178
01179
01180 el_protected int
01181 term_change_size(EditLine_t* el, int lins, int cols) {
01182
01183
01184
01185 Val(T_co) = (cols < 2) ? 80 : cols;
01186 Val(T_li) = (lins < 1) ? 24 : lins;
01187
01188
01189 if (term_rebuffer_display(el) == -1) {
01190 return -1;
01191 }
01192 re_clear_display(el);
01193 return 0;
01194 }
01195
01196
01197
01198
01199
01200 el_private void
01201 term_init_arrow(EditLine_t* el) {
01202 FKey_t* arrow = el->fTerm.fFKey;
01203
01204 arrow[A_K_DN].fName = "down";
01205 arrow[A_K_DN].fKey = T_kd;
01206 arrow[A_K_DN].fFun.fCmd = ED_NEXT_HISTORY;
01207 arrow[A_K_DN].fType = XK_CMD;
01208
01209 arrow[A_K_UP].fName = "up";
01210 arrow[A_K_UP].fKey = T_ku;
01211 arrow[A_K_UP].fFun.fCmd = ED_PREV_HISTORY;
01212 arrow[A_K_UP].fType = XK_CMD;
01213
01214 arrow[A_K_LT].fName = "left";
01215 arrow[A_K_LT].fKey = T_kl;
01216 arrow[A_K_LT].fFun.fCmd = ED_PREV_CHAR;
01217 arrow[A_K_LT].fType = XK_CMD;
01218
01219 arrow[A_K_RT].fName = "right";
01220 arrow[A_K_RT].fKey = T_kr;
01221 arrow[A_K_RT].fFun.fCmd = ED_NEXT_CHAR;
01222 arrow[A_K_RT].fType = XK_CMD;
01223
01224 arrow[A_K_HO].fName = "home";
01225 arrow[A_K_HO].fKey = T_kh;
01226 arrow[A_K_HO].fFun.fCmd = ED_MOVE_TO_BEG;
01227 arrow[A_K_HO].fType = XK_CMD;
01228
01229 arrow[A_K_EN].fName = "end";
01230 arrow[A_K_EN].fKey = T_at7;
01231 arrow[A_K_EN].fFun.fCmd = ED_MOVE_TO_END;
01232 arrow[A_K_EN].fType = XK_CMD;
01233
01234 arrow[A_K_DE].fName = "del";
01235 arrow[A_K_DE].fKey = T_kD;
01236 arrow[A_K_DE].fFun.fCmd = ED_DELETE_NEXT_CHAR;
01237 arrow[A_K_DE].fType = XK_CMD;
01238 }
01239
01240
01241
01242
01243
01244 el_private void
01245 term_reset_arrow(EditLine_t* el) {
01246 FKey_t* arrow = el->fTerm.fFKey;
01247 static const char strA[] = { 033, '[', 'A', '\0' };
01248 static const char strB[] = { 033, '[', 'B', '\0' };
01249 static const char strC[] = { 033, '[', 'C', '\0' };
01250 static const char strD[] = { 033, '[', 'D', '\0' };
01251 static const char strH[] = { 033, '[', 'H', '\0' };
01252 static const char strF[] = { 033, '[', 'F', '\0' };
01253 static const char stOA[] = { 033, 'O', 'A', '\0' };
01254 static const char stOB[] = { 033, 'O', 'B', '\0' };
01255 static const char stOC[] = { 033, 'O', 'C', '\0' };
01256 static const char stOD[] = { 033, 'O', 'D', '\0' };
01257 static const char stOH[] = { 033, 'O', 'H', '\0' };
01258 static const char stOF[] = { 033, 'O', 'F', '\0' };
01259
01260 key_add(el, strA, &arrow[A_K_UP].fFun, arrow[A_K_UP].fType);
01261 key_add(el, strB, &arrow[A_K_DN].fFun, arrow[A_K_DN].fType);
01262 key_add(el, strC, &arrow[A_K_RT].fFun, arrow[A_K_RT].fType);
01263 key_add(el, strD, &arrow[A_K_LT].fFun, arrow[A_K_LT].fType);
01264 key_add(el, strH, &arrow[A_K_HO].fFun, arrow[A_K_HO].fType);
01265 key_add(el, strF, &arrow[A_K_EN].fFun, arrow[A_K_EN].fType);
01266 key_add(el, stOA, &arrow[A_K_UP].fFun, arrow[A_K_UP].fType);
01267 key_add(el, stOB, &arrow[A_K_DN].fFun, arrow[A_K_DN].fType);
01268 key_add(el, stOC, &arrow[A_K_RT].fFun, arrow[A_K_RT].fType);
01269 key_add(el, stOD, &arrow[A_K_LT].fFun, arrow[A_K_LT].fType);
01270 key_add(el, stOH, &arrow[A_K_HO].fFun, arrow[A_K_HO].fType);
01271 key_add(el, stOF, &arrow[A_K_EN].fFun, arrow[A_K_EN].fType);
01272 key_add(el, stOF, &arrow[A_K_EN].fFun, arrow[A_K_EN].fType);
01273
01274 if (el->fMap.fType == MAP_VI) {
01275 key_add(el, &strA[1], &arrow[A_K_UP].fFun, arrow[A_K_UP].fType);
01276 key_add(el, &strB[1], &arrow[A_K_DN].fFun, arrow[A_K_DN].fType);
01277 key_add(el, &strC[1], &arrow[A_K_RT].fFun, arrow[A_K_RT].fType);
01278 key_add(el, &strD[1], &arrow[A_K_LT].fFun, arrow[A_K_LT].fType);
01279 key_add(el, &strH[1], &arrow[A_K_HO].fFun, arrow[A_K_HO].fType);
01280 key_add(el, &strF[1], &arrow[A_K_EN].fFun, arrow[A_K_EN].fType);
01281 key_add(el, &stOA[1], &arrow[A_K_UP].fFun, arrow[A_K_UP].fType);
01282 key_add(el, &stOB[1], &arrow[A_K_DN].fFun, arrow[A_K_DN].fType);
01283 key_add(el, &stOC[1], &arrow[A_K_RT].fFun, arrow[A_K_RT].fType);
01284 key_add(el, &stOD[1], &arrow[A_K_LT].fFun, arrow[A_K_LT].fType);
01285 key_add(el, &stOH[1], &arrow[A_K_HO].fFun, arrow[A_K_HO].fType);
01286 key_add(el, &stOF[1], &arrow[A_K_EN].fFun, arrow[A_K_EN].fType);
01287 }
01288 }
01289
01290
01291
01292
01293
01294 el_protected int
01295 term_set_arrow(EditLine_t* el, char* name, KeyValue_t* fun, int type) {
01296 FKey_t* arrow = el->fTerm.fFKey;
01297 int i;
01298
01299 for (i = 0; i < A_K_NKEYS; i++) {
01300 if (strcmp(name, arrow[i].fName) == 0) {
01301 arrow[i].fFun = *fun;
01302 arrow[i].fType = type;
01303 return 0;
01304 }
01305 }
01306 return -1;
01307 }
01308
01309
01310
01311
01312
01313 el_protected int
01314 term_clear_arrow(EditLine_t* el, char* name) {
01315 FKey_t* arrow = el->fTerm.fFKey;
01316 int i;
01317
01318 for (i = 0; i < A_K_NKEYS; i++) {
01319 if (strcmp(name, arrow[i].fName) == 0) {
01320 arrow[i].fType = XK_NOD;
01321 return 0;
01322 }
01323 }
01324 return -1;
01325 }
01326
01327
01328
01329
01330
01331 el_protected void
01332 term_print_arrow(EditLine_t* el, const char* name) {
01333 int i;
01334 FKey_t* arrow = el->fTerm.fFKey;
01335
01336 for (i = 0; i < A_K_NKEYS; i++) {
01337 if (*name == '\0' || strcmp(name, arrow[i].fName) == 0) {
01338 if (arrow[i].fType != XK_NOD) {
01339 key_kprint(el, arrow[i].fName, &arrow[i].fFun,
01340 arrow[i].fType);
01341 }
01342 }
01343 }
01344 }
01345
01346
01347
01348
01349
01350 el_protected void
01351 term_bind_arrow(EditLine_t* el) {
01352 ElAction_t* map;
01353 const ElAction_t* dmap;
01354 int i, j;
01355 char* p;
01356 FKey_t* arrow = el->fTerm.fFKey;
01357
01358
01359 if (el->fTerm.fBuf == NULL || el->fMap.fKey == NULL) {
01360 return;
01361 }
01362
01363 map = el->fMap.fType == MAP_VI ? el->fMap.fAlt : el->fMap.fKey;
01364 dmap = el->fMap.fType == MAP_VI ? el->fMap.fVic : el->fMap.fEmacs;
01365
01366 term_reset_arrow(el);
01367
01368 for (i = 0; i < A_K_NKEYS; i++) {
01369 p = el->fTerm.fStr[arrow[i].fKey];
01370
01371 if (p && *p) {
01372 j = (unsigned char) *p;
01373
01374
01375
01376
01377
01378
01379
01380
01381
01382
01383
01384 if (arrow[i].fType == XK_NOD) {
01385 key_clear(el, map, p);
01386 } else {
01387 if (p[1] && (dmap[j] == map[j] ||
01388 map[j] == ED_SEQUENCE_LEAD_IN)) {
01389 key_add(el, p, &arrow[i].fFun,
01390 arrow[i].fType);
01391 map[j] = ED_SEQUENCE_LEAD_IN;
01392 } else if (map[j] == ED_UNASSIGNED) {
01393 key_clear(el, map, p);
01394
01395 if (arrow[i].fType == XK_CMD) {
01396 map[j] = arrow[i].fFun.fCmd;
01397 } else {
01398 key_add(el, p, &arrow[i].fFun,
01399 arrow[i].fType);
01400 }
01401 }
01402 }
01403 }
01404 }
01405 }
01406
01407
01408
01409
01410
01411 el_private void
01412 term_init_color(EditLine_t* el) {
01413 int errcode;
01414
01415 if ((el->fFlags & NO_TTY) || !isatty(1)) {
01416
01417 return;
01418 }
01419
01420 if (ERR == setupterm(0, 1, &errcode)) {
01421 char* eldebug = getenv("EDITLINEDEBUG");
01422 if (eldebug != 0 && eldebug[0]) {
01423 fprintf(stderr, "ERROR initializing the terminal [TERM=%s]:\n", getenv("TERM"));
01424 switch (errcode) {
01425 case 1:
01426 fprintf(stderr,
01427 " Your terminal cannot be used for curses applications [code 1].\n"
01428 " Please reconfigure ROOT with --disable-editline, or get a better terminal.\n\n");
01429 break;
01430 case 0:
01431 fprintf(stderr,
01432 " the terminal could not be found, or it is a generic type [code 0].\n"
01433 " Please reconfigure ROOT with --disable-editline, or get a better terminal.\n\n");
01434 break;
01435 case -1:
01436 fprintf(stderr,
01437 " the terminfo database could not be found [code -1].\n"
01438 " Please make sure that it is accessible.\n\n");
01439 break;
01440 default:
01441 fprintf(stderr,
01442 " unknown curses error while setting up the terminal [code %d].\n\n",
01443 errcode);
01444 }
01445 }
01446 }
01447 }
01448
01449
01450
01451
01452
01453 el_private TTermManip&
01454 term__gettermmanip() {
01455 static TTermManip tm;
01456 return tm;
01457 }
01458
01459
01460
01461
01462
01463 el_protected void
01464 term__resetcolor() {
01465 TTermManip& tm = term__gettermmanip();
01466 tm.ResetTerm();
01467 term__flush();
01468 }
01469
01470
01471
01472
01473
01474 el_protected int
01475 term__putc(int c) {
01476 return term__putcolorch(c, NULL);
01477 }
01478
01479
01480
01481
01482
01483
01484 el_public int
01485 term__atocolor(const char* name) {
01486 int attr = 0;
01487 std::string lowname(name);
01488 size_t lenname = strlen(name);
01489 for (size_t i = 0; i < lenname; ++i)
01490 lowname[i] = tolower(lowname[i]);
01491
01492 if (lowname.find("bold") != std::string::npos
01493 || lowname.find("light") != std::string::npos)
01494 attr |= 0x2000;
01495 if (lowname.find("under") != std::string::npos)
01496 attr |= 0x4000;
01497
01498 TTermManip& tm = term__gettermmanip();
01499 size_t poshash = lowname.find('#');
01500 size_t lenrgb = 0;
01501 if (poshash != std::string::npos) {
01502 int endrgb = poshash + 1;
01503 while ((lowname[endrgb] >= '0' && lowname[endrgb] <= '9')
01504 || (lowname[endrgb] >= 'a' && lowname[endrgb] <= 'f')) {
01505 ++endrgb;
01506 }
01507 lenrgb = endrgb - poshash - 1;
01508 }
01509
01510 if (lenrgb == 3) {
01511 int rgb[3] = {0};
01512 for (int i = 0; i < 3; ++i) {
01513 rgb[i] = lowname[poshash + 1 + i] - '0';
01514 if (rgb[i] > 9) {
01515 rgb[i] = rgb[i] + '0' - 'a' + 10;
01516 }
01517 rgb[i] *= 16;
01518 }
01519 return attr | tm.GetColorIndex(rgb[0], rgb[1], rgb[2]);
01520 } else if (lenrgb == 6) {
01521 int rgb[3] = {0};
01522 for (int i = 0; i < 6; ++i) {
01523 int v = lowname[poshash + 1 + i] - '0';
01524 if (v > 9) {
01525 v = v + '0' - 'a' + 10;
01526 }
01527 if (i % 2 == 0) {
01528 v *= 16;
01529 }
01530 rgb[i / 2] += v;
01531 }
01532 return attr | tm.GetColorIndex(rgb[0], rgb[1], rgb[2]);
01533 } else {
01534 if (lowname.find("default") != std::string::npos) {
01535 return attr | 0xff;
01536 }
01537
01538 static const char* colornames[] = {
01539 "black", "red", "green", "yellow",
01540 "blue", "magenta", "cyan", "white", 0
01541 };
01542 static const unsigned char colorrgb[][3] = {
01543 {0,0,0}, {127,0,0}, {0,127,0}, {127,127,0},
01544 {0,0,127}, {127,0,127}, {0,127,127}, {127,127,127},
01545 {0}
01546 };
01547
01548 for (int i = 0; colornames[i]; ++i) {
01549 if (lowname.find(colornames[i]) != std::string::npos) {
01550 int boldify = 0;
01551 if (attr & 0x2000)
01552 boldify = 64;
01553 return attr | tm.GetColorIndex(colorrgb[i][0] + boldify,
01554 colorrgb[i][1] + boldify,
01555 colorrgb[i][2] + boldify);
01556 }
01557 }
01558 }
01559 fprintf(stderr, "editline / term__atocolor: cannot parse color %s!\n", name);
01560 return -1;
01561 }
01562
01563
01564
01565
01566
01567 el_protected void
01568 term__setcolor(int fgcol) {
01569 TTermManip& tm = term__gettermmanip();
01570
01571 int idx = (fgcol & 0xff);
01572 if (idx == 0xff) {
01573 tm.SetDefaultColor();
01574 } else {
01575 tm.SetColor(idx);
01576 }
01577
01578 if (fgcol != -1) {
01579 if (fgcol & 0x2000) {
01580 tm.StartBold();
01581 } else {
01582 tm.StopBold();
01583 }
01584 if (fgcol & 0x4000) {
01585 tm.StartUnderline();
01586 } else {
01587 tm.StopUnderline();
01588 }
01589 }
01590
01591 }
01592
01593
01594
01595
01596
01597 el_protected int
01598 term__putcolorch(int c, ElColor_t* color) {
01599 if (color != NULL && c != ' ') {
01600 term__setcolor(color->fForeColor);
01601 }
01602
01603 int res = fputc(c, term_outfile);
01604 return res;
01605
01606 }
01607
01608
01609
01610
01611
01612 el_protected void
01613 term__repaint(EditLine_t* el, int index) {
01614
01615 char* cursor = el->fLine.fCursor;
01616
01617 int promptSize = el->fPrompt.fPos.fH;
01618 int oriCursor = el->fCursor.fH;
01619 int oriLine = el->fCursor.fV;
01620
01621
01622 el->fLine.fCursor = el->fLine.fBuffer + index;
01623
01624 int line = (promptSize + index) / el->fTerm.fSize.fH;
01625 int hpos = (promptSize + index) % el->fTerm.fSize.fH;
01626 term_move_to_line(el, line);
01627 term_move_to_char(el, hpos);
01628
01629
01630 term_overwrite(el, el->fLine.fCursor,
01631 el->fLine.fBufColor + index,
01632 1);
01633
01634
01635 el->fLine.fCursor = cursor;
01636 term_move_to_line(el, oriLine);
01637 term_move_to_char(el, oriCursor);
01638
01639 term__flush();
01640 }
01641
01642
01643
01644
01645
01646 el_protected void
01647 term__flush(void) {
01648 (void) fflush(term_outfile);
01649 }
01650
01651
01652
01653
01654
01655 el_protected int
01656
01657 term_telltc(EditLine_t* el, int , const char** ) {
01658 const struct TermCapStr_t* t;
01659 char** ts;
01660 char upbuf[EL_BUFSIZ];
01661
01662 (void) fprintf(el->fOutFile, "\n\tYour terminal has the\n");
01663 (void) fprintf(el->fOutFile, "\tfollowing characteristics:\n\n");
01664 (void) fprintf(el->fOutFile, "\tIt has %d columns and %d lines\n",
01665 Val(T_co), Val(T_li));
01666 (void) fprintf(el->fOutFile,
01667 "\tIt has %s meta key\n", EL_HAS_META ? "a" : "no");
01668 (void) fprintf(el->fOutFile,
01669 "\tIt can%suse tabs\n", EL_CAN_TAB ? " " : "not ");
01670 (void) fprintf(el->fOutFile, "\tIt %s automatic margins\n",
01671 EL_HAS_AUTO_MARGINS ? "has" : "does not have");
01672
01673 if (EL_HAS_AUTO_MARGINS) {
01674 (void) fprintf(el->fOutFile, "\tIt %s magic margins\n",
01675 EL_HAS_MAGIC_MARGINS ? "has" : "does not have");
01676 }
01677
01678 for (t = tstr, ts = el->fTerm.fStr; t->fName != NULL; t++, ts++) {
01679 (void) fprintf(el->fOutFile, "\t%25s (%s) == %s\n",
01680 t->fLongName,
01681 t->fName, *ts && **ts ?
01682 key__decode_str(*ts, upbuf, "") : "(empty)");
01683 }
01684 (void) fputc('\n', el->fOutFile);
01685 return 0;
01686 }
01687
01688
01689
01690
01691
01692 el_protected int
01693
01694 term_settc(EditLine_t* el, int , const char** argv) {
01695 const struct TermCapStr_t* ts;
01696 const struct TermCapVal_t* tv;
01697 const char* what, * how;
01698
01699 if (argv == NULL || argv[1] == NULL || argv[2] == NULL) {
01700 return -1;
01701 }
01702
01703
01704 what = argv[1];
01705 how = argv[2];
01706
01707
01708
01709
01710 for (ts = tstr; ts->fName != NULL; ts++) {
01711 if (strcmp(ts->fName, what) == 0) {
01712 break;
01713 }
01714 }
01715
01716 if (ts->fName != NULL) {
01717 term_alloc(el, ts, how);
01718 term_setflags(el);
01719 return 0;
01720 }
01721
01722
01723
01724
01725 for (tv = tval; tv->fName != NULL; tv++) {
01726 if (strcmp(tv->fName, what) == 0) {
01727 break;
01728 }
01729 }
01730
01731 if (tv->fName != NULL) {
01732 if (tv == &tval[T_pt] || tv == &tval[T_km] ||
01733 tv == &tval[T_am] || tv == &tval[T_xn]) {
01734 if (strcmp(how, "yes") == 0) {
01735 el->fTerm.fVal[tv - tval] = 1;
01736 } else if (strcmp(how, "no") == 0) {
01737 el->fTerm.fVal[tv - tval] = 0;
01738 } else {
01739 (void) fprintf(el->fErrFile,
01740 "settc: Bad value `%s'.\n", how);
01741 return -1;
01742 }
01743 term_setflags(el);
01744
01745 if (term_change_size(el, Val(T_li), Val(T_co)) == -1) {
01746 return -1;
01747 }
01748 return 0;
01749 } else {
01750 long i;
01751 char* ep;
01752
01753 i = strtol(how, &ep, 10);
01754
01755 if (*ep != '\0') {
01756 (void) fprintf(el->fErrFile,
01757 "settc: Bad value `%s'.\n", how);
01758 return -1;
01759 }
01760 el->fTerm.fVal[tv - tval] = (int) i;
01761 el->fTerm.fSize.fV = Val(T_co);
01762 el->fTerm.fSize.fH = Val(T_li);
01763
01764 if (tv == &tval[T_co] || tv == &tval[T_li]) {
01765 if (term_change_size(el, Val(T_li), Val(T_co))
01766 == -1) {
01767 return -1;
01768 }
01769 }
01770 return 0;
01771 }
01772 }
01773 return -1;
01774 }
01775
01776
01777
01778
01779
01780 el_protected int
01781
01782 term_echotc(EditLine_t* el, int , const char** argv) {
01783 char* cap, * scap, * ep;
01784 int arg_need, arg_cols, arg_rows;
01785 int verbose = 0, silent = 0;
01786 char* area;
01787 static const char fmts[] = "%s\n", fmtd[] = "%d\n";
01788 const struct TermCapStr_t* t;
01789 char buf[TC_BUFSIZE];
01790 long i;
01791
01792 area = buf;
01793
01794 if (argv == NULL || argv[1] == NULL) {
01795 return -1;
01796 }
01797 argv++;
01798
01799 if (argv[0][0] == '-') {
01800 switch (argv[0][1]) {
01801 case 'v':
01802 verbose = 1;
01803 break;
01804 case 's':
01805 silent = 1;
01806 break;
01807 default:
01808
01809 break;
01810 }
01811 argv++;
01812 }
01813
01814 if (!*argv || *argv[0] == '\0') {
01815 return 0;
01816 }
01817
01818 if (strcmp(*argv, "tabs") == 0) {
01819 (void) fprintf(el->fOutFile, fmts, EL_CAN_TAB ? "yes" : "no");
01820 return 0;
01821 } else if (strcmp(*argv, "meta") == 0) {
01822 (void) fprintf(el->fOutFile, fmts, Val(T_km) ? "yes" : "no");
01823 return 0;
01824 } else if (strcmp(*argv, "xn") == 0) {
01825 (void) fprintf(el->fOutFile, fmts, EL_HAS_MAGIC_MARGINS ?
01826 "yes" : "no");
01827 return 0;
01828 } else if (strcmp(*argv, "am") == 0) {
01829 (void) fprintf(el->fOutFile, fmts, EL_HAS_AUTO_MARGINS ?
01830 "yes" : "no");
01831 return 0;
01832 } else if (strcmp(*argv, "baud") == 0) {
01833 #ifdef notdef
01834 int i;
01835
01836 for (i = 0; baud_rate[i].b_name != NULL; i++) {
01837 if (el->fTTY.t_speed == baud_rate[i].b_rate) {
01838 (void) fprintf(el->fOutFile, fmts,
01839 baud_rate[i].b_name);
01840 return 0;
01841 }
01842 }
01843 (void) fprintf(el->fOutFile, fmtd, 0);
01844 #else
01845 (void) fprintf(el->fOutFile, fmtd, (int)el->fTTY.t_speed);
01846 #endif
01847 return 0;
01848 } else if (strcmp(*argv, "rows") == 0 || strcmp(*argv, "lines") == 0) {
01849 (void) fprintf(el->fOutFile, fmtd, Val(T_li));
01850 return 0;
01851 } else if (strcmp(*argv, "cols") == 0) {
01852 (void) fprintf(el->fOutFile, fmtd, Val(T_co));
01853 return 0;
01854 }
01855
01856
01857
01858
01859 scap = NULL;
01860
01861 for (t = tstr; t->fName != NULL; t++) {
01862 if (strcmp(t->fName, *argv) == 0) {
01863 scap = el->fTerm.fStr[t - tstr];
01864 break;
01865 }
01866 }
01867
01868 if (t->fName == NULL) {
01869 scap = tgetstr((char*)*argv, &area);
01870 }
01871
01872 if (!scap || scap[0] == '\0') {
01873 if (!silent) {
01874 (void) fprintf(el->fErrFile,
01875 "echotc: Termcap parameter `%s' not found.\n",
01876 *argv);
01877 }
01878 return -1;
01879 }
01880
01881
01882
01883
01884 for (cap = scap, arg_need = 0; *cap; cap++) {
01885 if (*cap == '%') {
01886 switch (*++cap) {
01887 case 'd':
01888 case '2':
01889 case '3':
01890 case '.':
01891 case '+':
01892 arg_need++;
01893 break;
01894 case '%':
01895 case '>':
01896 case 'i':
01897 case 'r':
01898 case 'n':
01899 case 'B':
01900 case 'D':
01901 break;
01902 default:
01903
01904
01905
01906
01907 if (verbose) {
01908 (void) fprintf(el->fErrFile,
01909 "echotc: Warning: unknown termcap %% `%c'.\n",
01910 *cap);
01911 }
01912
01913 break;
01914 }
01915 }
01916 }
01917
01918 switch (arg_need) {
01919 case 0:
01920 argv++;
01921
01922 if (*argv && *argv[0]) {
01923 if (!silent) {
01924 (void) fprintf(el->fErrFile,
01925 "echotc: Warning: Extra argument `%s'.\n",
01926 *argv);
01927 }
01928 return -1;
01929 }
01930 (void) tputs(scap, 1, term__putc);
01931 break;
01932 case 1:
01933 argv++;
01934
01935 if (!*argv || *argv[0] == '\0') {
01936 if (!silent) {
01937 (void) fprintf(el->fErrFile,
01938 "echotc: Warning: Missing argument.\n");
01939 }
01940 return -1;
01941 }
01942 arg_cols = 0;
01943 i = strtol(*argv, &ep, 10);
01944
01945 if (*ep != '\0' || i < 0) {
01946 if (!silent) {
01947 (void) fprintf(el->fErrFile,
01948 "echotc: Bad value `%s' for rows.\n",
01949 *argv);
01950 }
01951 return -1;
01952 }
01953 arg_rows = (int) i;
01954 argv++;
01955
01956 if (*argv && *argv[0]) {
01957 if (!silent) {
01958 (void) fprintf(el->fErrFile,
01959 "echotc: Warning: Extra argument `%s'.\n",
01960 *argv);
01961 }
01962 return -1;
01963 }
01964 (void) tputs(tgoto(scap, arg_cols, arg_rows), 1, term__putc);
01965 break;
01966 default:
01967
01968
01969 if (verbose) {
01970 (void) fprintf(el->fErrFile,
01971 "echotc: Warning: Too many required arguments (%d).\n",
01972 arg_need);
01973 }
01974
01975 case 2:
01976 argv++;
01977
01978 if (!*argv || *argv[0] == '\0') {
01979 if (!silent) {
01980 (void) fprintf(el->fErrFile,
01981 "echotc: Warning: Missing argument.\n");
01982 }
01983 return -1;
01984 }
01985 i = strtol(*argv, &ep, 10);
01986
01987 if (*ep != '\0' || i < 0) {
01988 if (!silent) {
01989 (void) fprintf(el->fErrFile,
01990 "echotc: Bad value `%s' for cols.\n",
01991 *argv);
01992 }
01993 return -1;
01994 }
01995 arg_cols = (int) i;
01996 argv++;
01997
01998 if (!*argv || *argv[0] == '\0') {
01999 if (!silent) {
02000 (void) fprintf(el->fErrFile,
02001 "echotc: Warning: Missing argument.\n");
02002 }
02003 return -1;
02004 }
02005 i = strtol(*argv, &ep, 10);
02006
02007 if (*ep != '\0' || i < 0) {
02008 if (!silent) {
02009 (void) fprintf(el->fErrFile,
02010 "echotc: Bad value `%s' for rows.\n",
02011 *argv);
02012 }
02013 return -1;
02014 }
02015 arg_rows = (int) i;
02016
02017 if (*ep != '\0') {
02018 if (!silent) {
02019 (void) fprintf(el->fErrFile,
02020 "echotc: Bad value `%s'.\n", *argv);
02021 }
02022 return -1;
02023 }
02024 argv++;
02025
02026 if (*argv && *argv[0]) {
02027 if (!silent) {
02028 (void) fprintf(el->fErrFile,
02029 "echotc: Warning: Extra argument `%s'.\n",
02030 *argv);
02031 }
02032 return -1;
02033 }
02034 (void) tputs(tgoto(scap, arg_cols, arg_rows), arg_rows, term__putc);
02035 break;
02036 }
02037 return 0;
02038 }