154235Sbostic /*- 254235Sbostic * Copyright (c) 1992 The Regents of the University of California. 354235Sbostic * All rights reserved. 454235Sbostic * 554235Sbostic * This code is derived from software contributed to Berkeley by 654235Sbostic * Christos Zoulas of Cornell University. 754235Sbostic * 854235Sbostic * %sccs.include.redist.c% 954235Sbostic */ 1054235Sbostic 11*54624Schristos #if !defined(lint) && !defined(SCCSID) 12*54624Schristos static char sccsid[] = "@(#)term.c 5.2 (Berkeley) 07/03/92"; 13*54624Schristos #endif /* not lint && not SCCSID */ 1454235Sbostic 1554235Sbostic /* 16*54624Schristos * term.c: Editor/termcap-curses interface 17*54624Schristos * We have to declare a static variable here, since the 18*54624Schristos * termcap putchar routine does not take an argument! 1954235Sbostic */ 2054235Sbostic #include "sys.h" 2154235Sbostic #include <stdio.h> 2254235Sbostic #include <signal.h> 2354235Sbostic #include <string.h> 2454235Sbostic #include <stdlib.h> 2554235Sbostic #include <unistd.h> 2654235Sbostic #include "termcap.h" /* XXX: should be <termcap.h> */ 2754235Sbostic #include <sys/types.h> 2854235Sbostic 2954235Sbostic #include "el.h" 3054235Sbostic 3154235Sbostic /* 3254235Sbostic * IMPORTANT NOTE: these routines are allowed to look at the current screen 3354235Sbostic * and the current possition assuming that it is correct. If this is not 3454235Sbostic * true, then the update will be WRONG! This is (should be) a valid 3554235Sbostic * assumption... 3654235Sbostic */ 3754235Sbostic 3854235Sbostic #define TC_BUFSIZE 2048 3954235Sbostic 4054235Sbostic #define GoodStr(a) (el->el_term.t_str[a] != NULL && \ 4154235Sbostic el->el_term.t_str[a][0] != '\0') 4254235Sbostic #define Str(a) el->el_term.t_str[a] 4354235Sbostic #define Val(a) el->el_term.t_val[a] 4454235Sbostic 4554235Sbostic private struct { 4654235Sbostic char *b_name; 4754235Sbostic int b_rate; 4854235Sbostic } baud_rate[] = { 4954235Sbostic #ifdef B0 5054235Sbostic { "0", B0 }, 5154235Sbostic #endif 5254235Sbostic #ifdef B50 5354235Sbostic { "50", B50 }, 5454235Sbostic #endif 5554235Sbostic #ifdef B75 5654235Sbostic { "75", B75 }, 5754235Sbostic #endif 5854235Sbostic #ifdef B110 5954235Sbostic { "110", B110 }, 6054235Sbostic #endif 6154235Sbostic #ifdef B134 6254235Sbostic { "134", B134 }, 6354235Sbostic #endif 6454235Sbostic #ifdef B150 6554235Sbostic { "150", B150 }, 6654235Sbostic #endif 6754235Sbostic #ifdef B200 6854235Sbostic { "200", B200 }, 6954235Sbostic #endif 7054235Sbostic #ifdef B300 7154235Sbostic { "300", B300 }, 7254235Sbostic #endif 7354235Sbostic #ifdef B600 7454235Sbostic { "600", B600 }, 7554235Sbostic #endif 7654235Sbostic #ifdef B900 7754235Sbostic { "900", B900 }, 7854235Sbostic #endif 7954235Sbostic #ifdef B1200 8054235Sbostic { "1200", B1200 }, 8154235Sbostic #endif 8254235Sbostic #ifdef B1800 8354235Sbostic { "1800", B1800 }, 8454235Sbostic #endif 8554235Sbostic #ifdef B2400 8654235Sbostic { "2400", B2400 }, 8754235Sbostic #endif 8854235Sbostic #ifdef B3600 8954235Sbostic { "3600", B3600 }, 9054235Sbostic #endif 9154235Sbostic #ifdef B4800 9254235Sbostic { "4800", B4800 }, 9354235Sbostic #endif 9454235Sbostic #ifdef B7200 9554235Sbostic { "7200", B7200 }, 9654235Sbostic #endif 9754235Sbostic #ifdef B9600 9854235Sbostic { "9600", B9600 }, 9954235Sbostic #endif 10054235Sbostic #ifdef EXTA 10154235Sbostic { "19200", EXTA }, 10254235Sbostic #endif 10354235Sbostic #ifdef B19200 10454235Sbostic { "19200", B19200 }, 10554235Sbostic #endif 10654235Sbostic #ifdef EXTB 10754235Sbostic { "38400", EXTB }, 10854235Sbostic #endif 10954235Sbostic #ifdef B38400 11054235Sbostic { "38400", B38400 }, 11154235Sbostic #endif 11254235Sbostic { NULL, 0 } 11354235Sbostic }; 11454235Sbostic 11554235Sbostic private struct termcapstr { 11654235Sbostic char *name; 11754235Sbostic char *long_name; 11854235Sbostic } tstr[] = { 11954235Sbostic 12054235Sbostic #define T_al 0 12154235Sbostic { "al", "add new blank line" }, 12254235Sbostic #define T_bl 1 12354235Sbostic { "bl", "audible bell" }, 12454235Sbostic #define T_cd 2 12554235Sbostic { "cd", "clear to bottom" }, 12654235Sbostic #define T_ce 3 12754235Sbostic { "ce", "clear to end of line" }, 12854235Sbostic #define T_ch 4 12954235Sbostic { "ch", "cursor to horiz pos" }, 13054235Sbostic #define T_cl 5 13154235Sbostic { "cl", "clear screen" }, 13254235Sbostic #define T_dc 6 13354235Sbostic { "dc", "delete a character" }, 13454235Sbostic #define T_dl 7 13554235Sbostic { "dl", "delete a line" }, 13654235Sbostic #define T_dm 8 13754235Sbostic { "dm", "start delete mode" }, 13854235Sbostic #define T_ed 9 13954235Sbostic { "ed", "end delete mode" }, 14054235Sbostic #define T_ei 10 14154235Sbostic { "ei", "end insert mode" }, 14254235Sbostic #define T_fs 11 14354235Sbostic { "fs", "cursor from status line" }, 14454235Sbostic #define T_ho 12 14554235Sbostic { "ho", "home cursor" }, 14654235Sbostic #define T_ic 13 14754235Sbostic { "ic", "insert character" }, 14854235Sbostic #define T_im 14 14954235Sbostic { "im", "start insert mode" }, 15054235Sbostic #define T_ip 15 15154235Sbostic { "ip", "insert padding" }, 15254235Sbostic #define T_kd 16 15354235Sbostic { "kd", "sends cursor down" }, 15454235Sbostic #define T_kl 17 15554235Sbostic { "kl", "sends cursor left" }, 15654235Sbostic #define T_kr 18 15754235Sbostic { "kr", "sends cursor right" }, 15854235Sbostic #define T_ku 19 15954235Sbostic { "ku", "sends cursor up" }, 16054235Sbostic #define T_md 20 16154235Sbostic { "md", "begin bold" }, 16254235Sbostic #define T_me 21 16354235Sbostic { "me", "end attributes" }, 16454235Sbostic #define T_nd 22 16554235Sbostic { "nd", "non destructive space" }, 16654235Sbostic #define T_se 23 16754235Sbostic { "se", "end standout" }, 16854235Sbostic #define T_so 24 16954235Sbostic { "so", "begin standout" }, 17054235Sbostic #define T_ts 25 17154235Sbostic { "ts", "cursor to status line" }, 17254235Sbostic #define T_up 26 17354235Sbostic { "up", "cursor up one" }, 17454235Sbostic #define T_us 27 17554235Sbostic { "us", "begin underline" }, 17654235Sbostic #define T_ue 28 17754235Sbostic { "ue", "end underline" }, 17854235Sbostic #define T_vb 29 17954235Sbostic { "vb", "visible bell" }, 18054235Sbostic #define T_DC 30 18154235Sbostic { "DC", "delete multiple chars" }, 18254235Sbostic #define T_DO 31 18354235Sbostic { "DO", "cursor down multiple" }, 18454235Sbostic #define T_IC 32 18554235Sbostic { "IC", "insert multiple chars" }, 18654235Sbostic #define T_LE 33 18754235Sbostic { "LE", "cursor left multiple" }, 18854235Sbostic #define T_RI 34 18954235Sbostic { "RI", "cursor right multiple" }, 19054235Sbostic #define T_UP 35 19154235Sbostic { "UP", "cursor up multiple" }, 19254235Sbostic #define T_str 36 19354235Sbostic { NULL, NULL } 19454235Sbostic }; 19554235Sbostic 19654235Sbostic private struct termcapval { 19754235Sbostic char *name; 19854235Sbostic char *long_name; 19954235Sbostic } tval[] = { 20054235Sbostic #define T_pt 0 20154235Sbostic { "pt", "has physical tabs" }, 20254235Sbostic #define T_li 1 20354235Sbostic { "li", "Number of lines" }, 20454235Sbostic #define T_co 2 20554235Sbostic { "co", "Number of columns" }, 20654235Sbostic #define T_km 3 20754235Sbostic { "km", "Has meta key" }, 20854235Sbostic #define T_xt 4 20954235Sbostic { "xt", "Tab chars destructive" }, 21054235Sbostic #define T_MT 5 21154235Sbostic { "MT", "Has meta key" }, /* XXX? */ 21254235Sbostic #define T_val 6 21354235Sbostic { NULL, NULL, } 21454235Sbostic }; 21554235Sbostic 21654235Sbostic /* do two or more of the attributes use me */ 21754235Sbostic 21854235Sbostic private void term_rebuffer_display __P((EditLine *)); 21954235Sbostic private void term_free_display __P((EditLine *)); 22054235Sbostic private void term_alloc_display __P((EditLine *)); 22154235Sbostic private void term_alloc __P((EditLine *, 22254235Sbostic struct termcapstr *, char *)); 223*54624Schristos private void term_init_arrow __P((EditLine *)); 224*54624Schristos private void term_reset_arrow __P((EditLine *)); 22554235Sbostic 22654235Sbostic 22754235Sbostic private FILE *term_outfile = NULL; /* XXX: How do we fix that? */ 22854235Sbostic 22954235Sbostic 23054235Sbostic /* term_setflags(): 23154235Sbostic * Set the terminal capability flags 23254235Sbostic */ 23354235Sbostic private void 23454235Sbostic term_setflags(el) 23554235Sbostic EditLine *el; 23654235Sbostic { 23754235Sbostic EL_FLAGS = 0; 23854235Sbostic if (el->el_tty.t_tabs) 23954235Sbostic EL_FLAGS |= (Val(T_pt) && !Val(T_xt)) ? TERM_CAN_TAB : 0; 24054235Sbostic 24154235Sbostic EL_FLAGS |= (Val(T_km) || Val(T_MT)) ? TERM_HAS_META : 0; 24254235Sbostic EL_FLAGS |= GoodStr(T_ce) ? TERM_CAN_CEOL : 0; 24354235Sbostic EL_FLAGS |= (GoodStr(T_dc) || GoodStr(T_DC)) ? TERM_CAN_DELETE : 0; 24454235Sbostic EL_FLAGS |= (GoodStr(T_im) || GoodStr(T_ic) || GoodStr(T_IC)) ? 24554235Sbostic TERM_CAN_INSERT : 0; 24654235Sbostic EL_FLAGS |= (GoodStr(T_up) || GoodStr(T_UP)) ? TERM_CAN_UP : 0; 24754235Sbostic 24854235Sbostic if (GoodStr(T_me) && GoodStr(T_ue)) 24954235Sbostic EL_FLAGS |= (strcmp(Str(T_me), Str(T_ue)) == 0) ? TERM_CAN_ME : 0; 25054235Sbostic else 25154235Sbostic EL_FLAGS &= ~TERM_CAN_ME; 25254235Sbostic if (GoodStr(T_me) && GoodStr(T_se)) 25354235Sbostic EL_FLAGS |= (strcmp(Str(T_me), Str(T_se)) == 0) ? TERM_CAN_ME : 0; 25454235Sbostic 25554235Sbostic 25654235Sbostic #ifdef DEBUG_SCREEN 25754235Sbostic if (!EL_CAN_UP) { 25854235Sbostic (void) fprintf(el->el_errfile, "WARNING: Your terminal cannot move up.\n"); 25954235Sbostic (void) fprintf(el->el_errfile, "Editing may be odd for long lines.\n"); 26054235Sbostic } 26154235Sbostic if (!EL_CAN_CEOL) 26254235Sbostic (void) fprintf(el->el_errfile, "no clear EOL capability.\n"); 26354235Sbostic if (!EL_CAN_DELETE) 26454235Sbostic (void) fprintf(el->el_errfile, "no delete char capability.\n"); 26554235Sbostic if (!EL_CAN_INSERT) 26654235Sbostic (void) fprintf(el->el_errfile, "no insert char capability.\n"); 26754235Sbostic #endif /* DEBUG_SCREEN */ 26854235Sbostic } 26954235Sbostic 27054235Sbostic 27154235Sbostic /* term_init(): 27254235Sbostic * Initialize the terminal stuff 27354235Sbostic */ 27454235Sbostic protected int 27554235Sbostic term_init(el) 27654235Sbostic EditLine *el; 27754235Sbostic { 27854235Sbostic el->el_term.t_buf = (char *) el_malloc(TC_BUFSIZE); 27954235Sbostic el->el_term.t_cap = (char *) el_malloc(TC_BUFSIZE); 280*54624Schristos el->el_term.t_fkey = (fkey_t *) el_malloc(4 * sizeof(fkey_t)); 28154235Sbostic el->el_term.t_loc = 0; 28254235Sbostic el->el_term.t_str = (char **) el_malloc(T_str * sizeof(char*)); 28354235Sbostic (void) memset(el->el_term.t_str, 0, T_str * sizeof(char*)); 28454235Sbostic el->el_term.t_val = (int *) el_malloc(T_val * sizeof(int)); 28554235Sbostic (void) memset(el->el_term.t_val, 0, T_val * sizeof(char*)); 28654235Sbostic term_outfile = el->el_outfile; 287*54624Schristos (void) term_set(el, NULL); 288*54624Schristos term_init_arrow(el); 28954235Sbostic return 0; 29054235Sbostic } 29154235Sbostic 29254235Sbostic /* term_end(): 29354235Sbostic * Clean up the terminal stuff 29454235Sbostic */ 29554235Sbostic protected void 29654235Sbostic term_end(el) 29754235Sbostic EditLine *el; 29854235Sbostic { 29954235Sbostic el_free((ptr_t) el->el_term.t_buf); 30054235Sbostic el->el_term.t_buf = NULL; 30154235Sbostic el_free((ptr_t) el->el_term.t_cap); 30254235Sbostic el->el_term.t_cap = NULL; 30354235Sbostic el->el_term.t_loc = 0; 30454235Sbostic el_free((ptr_t) el->el_term.t_str); 30554235Sbostic el->el_term.t_str = NULL; 30654235Sbostic el_free((ptr_t) el->el_term.t_val); 30754235Sbostic el->el_term.t_val = NULL; 30854235Sbostic term_free_display(el); 30954235Sbostic } 31054235Sbostic 31154235Sbostic 31254235Sbostic /* term_alloc(): 31354235Sbostic * Maintain a string pool for termcap strings 31454235Sbostic */ 31554235Sbostic private void 31654235Sbostic term_alloc(el, t, cap) 31754235Sbostic EditLine *el; 31854235Sbostic struct termcapstr *t; 31954235Sbostic char *cap; 32054235Sbostic { 32154235Sbostic char termbuf[TC_BUFSIZE]; 32254235Sbostic int tlen, clen; 32354235Sbostic char **tlist = el->el_term.t_str; 32454235Sbostic char **tmp, **str = &tlist[t - tstr]; 32554235Sbostic 32654235Sbostic if (cap == NULL || *cap == '\0') { 32754235Sbostic *str = NULL; 32854235Sbostic return; 32954235Sbostic } 33054235Sbostic else 33154235Sbostic clen = strlen(cap); 33254235Sbostic 33354235Sbostic tlen = *str == NULL ? 0 : strlen(*str); 33454235Sbostic 33554235Sbostic /* 33654235Sbostic * New string is shorter; no need to allocate space 33754235Sbostic */ 33854235Sbostic if (clen <= tlen) { 33954235Sbostic (void) strcpy(*str, cap); 34054235Sbostic return; 34154235Sbostic } 34254235Sbostic 34354235Sbostic /* 34454235Sbostic * New string is longer; see if we have enough space to append 34554235Sbostic */ 34654235Sbostic if (el->el_term.t_loc + 3 < TC_BUFSIZE) { 34754235Sbostic (void) strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap); 34854235Sbostic el->el_term.t_loc += clen + 1; /* one for \0 */ 34954235Sbostic return; 35054235Sbostic } 35154235Sbostic 35254235Sbostic /* 35354235Sbostic * Compact our buffer; no need to check compaction, cause we know it 35454235Sbostic * fits... 35554235Sbostic */ 35654235Sbostic tlen = 0; 35754235Sbostic for (tmp = tlist; tmp < &tlist[T_str]; tmp++) 35854235Sbostic if (*tmp != NULL && *tmp != '\0' && *tmp != *str) { 35954235Sbostic char *ptr; 36054235Sbostic 36154235Sbostic for (ptr = *tmp; *ptr != '\0'; termbuf[tlen++] = *ptr++) 36254235Sbostic continue; 36354235Sbostic termbuf[tlen++] = '\0'; 36454235Sbostic } 36554235Sbostic memcpy(el->el_term.t_buf, termbuf, TC_BUFSIZE); 36654235Sbostic el->el_term.t_loc = tlen; 36754235Sbostic if (el->el_term.t_loc + 3 >= TC_BUFSIZE) { 36854235Sbostic (void) fprintf(el->el_errfile, "Out of termcap string space.\n"); 36954235Sbostic return; 37054235Sbostic } 37154235Sbostic (void) strcpy(*str = &el->el_term.t_buf[el->el_term.t_loc], cap); 37254235Sbostic el->el_term.t_loc += clen + 1; /* one for \0 */ 37354235Sbostic return; 37454235Sbostic } /* end term_alloc */ 37554235Sbostic 37654235Sbostic 37754235Sbostic /* term_rebuffer_display(): 37854235Sbostic * Rebuffer the display after the screen changed size 37954235Sbostic */ 38054235Sbostic private void 38154235Sbostic term_rebuffer_display(el) 38254235Sbostic EditLine *el; 38354235Sbostic { 38454235Sbostic coord_t *c = &el->el_term.t_size; 38554235Sbostic 38654235Sbostic term_free_display(el); 38754235Sbostic 38854235Sbostic /* make this public, -1 to avoid wraps */ 38954235Sbostic c->h = Val(T_co) - 1; 39054235Sbostic c->v = (EL_BUFSIZ * 4) / c->h + 1; 39154235Sbostic 39254235Sbostic term_alloc_display(el); 39354235Sbostic } /* end term_rebuffer_display */ 39454235Sbostic 39554235Sbostic 39654235Sbostic /* term_alloc_display(): 39754235Sbostic * Allocate a new display. 39854235Sbostic */ 39954235Sbostic private void 40054235Sbostic term_alloc_display(el) 40154235Sbostic EditLine *el; 40254235Sbostic { 40354235Sbostic int i; 40454235Sbostic char **b; 40554235Sbostic coord_t *c = &el->el_term.t_size; 40654235Sbostic 40754235Sbostic b = (char **) el_malloc((size_t) (sizeof(char *) * (c->v + 1))); 40854235Sbostic for (i = 0; i < c->v; i++) 40954235Sbostic b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1))); 41054235Sbostic b[c->v] = NULL; 41154235Sbostic el->el_display = b; 41254235Sbostic 41354235Sbostic b = (char **) el_malloc((size_t) (sizeof(char *) * (c->v + 1))); 41454235Sbostic for (i = 0; i < c->v; i++) 41554235Sbostic b[i] = (char *) el_malloc((size_t) (sizeof(char) * (c->h + 1))); 41654235Sbostic b[c->v] = NULL; 41754235Sbostic el->el_vdisplay = b; 41854235Sbostic 41954235Sbostic } /* end term_alloc_display */ 42054235Sbostic 42154235Sbostic 42254235Sbostic /* term_free_display(): 42354235Sbostic * Free the display buffers 42454235Sbostic */ 42554235Sbostic private void 42654235Sbostic term_free_display(el) 42754235Sbostic EditLine *el; 42854235Sbostic { 42954235Sbostic char **b; 43054235Sbostic char **bufp; 43154235Sbostic 43254235Sbostic b = el->el_display; 43354235Sbostic el->el_display = NULL; 43454235Sbostic if (b != NULL) { 43554235Sbostic for (bufp = b; *bufp != NULL; bufp++) 43654235Sbostic el_free((ptr_t) *bufp); 43754235Sbostic el_free((ptr_t) b); 43854235Sbostic } 43954235Sbostic b = el->el_vdisplay; 44054235Sbostic el->el_vdisplay = NULL; 44154235Sbostic if (b != NULL) { 44254235Sbostic for (bufp = b; *bufp != NULL; bufp++) 44354235Sbostic el_free((ptr_t) * bufp); 44454235Sbostic el_free((ptr_t) b); 44554235Sbostic } 44654235Sbostic } /* end term_free_display */ 44754235Sbostic 44854235Sbostic 44954235Sbostic /* term_move_to_line(): 45054235Sbostic * move to line <where> (first line == 0) 45154235Sbostic * as efficiently as possible 45254235Sbostic */ 45354235Sbostic protected void 45454235Sbostic term_move_to_line(el, where) 45554235Sbostic EditLine *el; 45654235Sbostic int where; 45754235Sbostic { 45854235Sbostic int del, i; 45954235Sbostic 46054235Sbostic if (where == el->el_cursor.v) 46154235Sbostic return; 46254235Sbostic 46354235Sbostic if (where > el->el_term.t_size.v) { 46454235Sbostic #ifdef DEBUG_SCREEN 46554235Sbostic (void) fprintf(el->el_errfile, 46654235Sbostic "term_move_to_line: where is ridiculous: %d\r\n", where); 46754235Sbostic #endif /* DEBUG_SCREEN */ 46854235Sbostic return; 46954235Sbostic } 47054235Sbostic 47154235Sbostic if ((del = where - el->el_cursor.v) > 0) { 47254235Sbostic if ((del > 1) && GoodStr(T_DO)) 47354235Sbostic (void) tputs(tgoto(Str(T_DO), del, del), del, term__putc); 47454235Sbostic else { 47554235Sbostic for (i = 0; i < del; i++) 47654235Sbostic term__putc('\n'); 47754235Sbostic el->el_cursor.h = 0; /* because the \n will become \r\n */ 47854235Sbostic } 47954235Sbostic } 48054235Sbostic else { /* del < 0 */ 48154235Sbostic if (GoodStr(T_UP) && (-del > 1 || !GoodStr(T_up))) 48254235Sbostic (void) tputs(tgoto(Str(T_UP), -del, -del), -del, term__putc); 48354235Sbostic else { 48454235Sbostic if (GoodStr(T_up)) 48554235Sbostic for (i = 0; i < -del; i++) 48654235Sbostic (void) tputs(Str(T_up), 1, term__putc); 48754235Sbostic } 48854235Sbostic } 48954235Sbostic el->el_cursor.v = where; /* now where is here */ 49054235Sbostic } /* end term_move_to_line */ 49154235Sbostic 49254235Sbostic 49354235Sbostic /* term_move_to_char(): 49454235Sbostic * Move to the character position specified 49554235Sbostic */ 49654235Sbostic protected void 49754235Sbostic term_move_to_char(el, where) 49854235Sbostic EditLine *el; 49954235Sbostic int where; 50054235Sbostic { 50154235Sbostic int del, i; 50254235Sbostic 50354235Sbostic mc_again: 50454235Sbostic if (where == el->el_cursor.h) 50554235Sbostic return; 50654235Sbostic 50754235Sbostic if (where > (el->el_term.t_size.h + 1)) { 50854235Sbostic #ifdef DEBUG_SCREEN 50954235Sbostic (void) fprintf(el->el_errfile, 51054235Sbostic "term_move_to_char: where is riduculous: %d\r\n", where); 51154235Sbostic #endif /* DEBUG_SCREEN */ 51254235Sbostic return; 51354235Sbostic } 51454235Sbostic 51554235Sbostic if (!where) { /* if where is first column */ 51654235Sbostic term__putc('\r'); /* do a CR */ 51754235Sbostic el->el_cursor.h = 0; 51854235Sbostic return; 51954235Sbostic } 52054235Sbostic 52154235Sbostic del = where - el->el_cursor.h; 52254235Sbostic 52354235Sbostic if ((del < -4 || del > 4) && GoodStr(T_ch)) 52454235Sbostic /* go there directly */ 52554235Sbostic (void) tputs(tgoto(Str(T_ch), where, where), where, term__putc); 52654235Sbostic else { 52754235Sbostic if (del > 0) { /* moving forward */ 52854235Sbostic if ((del > 4) && GoodStr(T_RI)) 52954235Sbostic (void) tputs(tgoto(Str(T_RI), del, del), del, term__putc); 53054235Sbostic else { 53154235Sbostic if (EL_CAN_TAB) { /* if I can do tabs, use them */ 53254235Sbostic if ((el->el_cursor.h & 0370) != (where & 0370)) { 53354235Sbostic /* if not within tab stop */ 53454235Sbostic for (i = (el->el_cursor.h & 0370); 53554235Sbostic i < (where & 0370); i += 8) 53654235Sbostic term__putc('\t'); /* then tab over */ 53754235Sbostic el->el_cursor.h = where & 0370; 53854235Sbostic } 53954235Sbostic } 54054235Sbostic /* it's usually cheaper to just write the chars, so we do. */ 54154235Sbostic 54254235Sbostic /* NOTE THAT term_overwrite() WILL CHANGE el->el_cursor.h!!! */ 54354235Sbostic term_overwrite(el, 54454235Sbostic &el->el_display[el->el_cursor.v][el->el_cursor.h], 54554235Sbostic where - el->el_cursor.h); 54654235Sbostic 54754235Sbostic } 54854235Sbostic } 54954235Sbostic else { /* del < 0 := moving backward */ 55054235Sbostic if ((-del > 4) && GoodStr(T_LE)) 55154235Sbostic (void) tputs(tgoto(Str(T_LE), -del, -del), -del, term__putc); 55254235Sbostic else { /* can't go directly there */ 55354235Sbostic /* if the "cost" is greater than the "cost" from col 0 */ 55454235Sbostic if (EL_CAN_TAB ? (-del > ((where >> 3) + (where & 07))) 55554235Sbostic : (-del > where)) { 55654235Sbostic term__putc('\r'); /* do a CR */ 55754235Sbostic el->el_cursor.h = 0; 55854235Sbostic goto mc_again; /* and try again */ 55954235Sbostic } 56054235Sbostic for (i = 0; i < -del; i++) 56154235Sbostic term__putc('\b'); 56254235Sbostic } 56354235Sbostic } 56454235Sbostic } 56554235Sbostic el->el_cursor.h = where; /* now where is here */ 56654235Sbostic } /* end term_move_to_char */ 56754235Sbostic 56854235Sbostic 56954235Sbostic /* term_overwrite(): 57054235Sbostic * Overstrike num characters 57154235Sbostic */ 57254235Sbostic protected void 57354235Sbostic term_overwrite(el, cp, n) 57454235Sbostic EditLine *el; 57554235Sbostic char *cp; 57654235Sbostic int n; 57754235Sbostic { 57854235Sbostic if (n <= 0) 57954235Sbostic return; /* catch bugs */ 58054235Sbostic 58154235Sbostic if (n > (el->el_term.t_size.h + 1)) { 58254235Sbostic #ifdef DEBUG_SCREEN 58354235Sbostic (void) fprintf(el->el_errfile, "term_overwrite: n is riduculous: %d\r\n", n); 58454235Sbostic #endif /* DEBUG_SCREEN */ 58554235Sbostic return; 58654235Sbostic } 58754235Sbostic 58854235Sbostic do { 58954235Sbostic term__putc(*cp++); 59054235Sbostic el->el_cursor.h++; 59154235Sbostic } while (--n); 59254235Sbostic } /* end term_overwrite */ 59354235Sbostic 59454235Sbostic 59554235Sbostic /* term_deletechars(): 59654235Sbostic * Delete num characters 59754235Sbostic */ 59854235Sbostic protected void 59954235Sbostic term_deletechars(el, num) 60054235Sbostic EditLine *el; 60154235Sbostic int num; 60254235Sbostic { 60354235Sbostic if (num <= 0) 60454235Sbostic return; 60554235Sbostic 60654235Sbostic if (!EL_CAN_DELETE) { 60754235Sbostic #ifdef DEBUG_EDIT 60854235Sbostic (void) fprintf(el->el_errfile, " ERROR: cannot delete \n"); 60954235Sbostic #endif /* DEBUG_EDIT */ 61054235Sbostic return; 61154235Sbostic } 61254235Sbostic 61354235Sbostic if (num > el->el_term.t_size.h) { 61454235Sbostic #ifdef DEBUG_SCREEN 61554235Sbostic (void) fprintf(el->el_errfile, 61654235Sbostic "term_deletechars: num is riduculous: %d\r\n", num); 61754235Sbostic #endif /* DEBUG_SCREEN */ 61854235Sbostic return; 61954235Sbostic } 62054235Sbostic 62154235Sbostic if (GoodStr(T_DC)) /* if I have multiple delete */ 62254235Sbostic if ((num > 1) || !GoodStr(T_dc)) { /* if dc would be more expen. */ 62354235Sbostic (void) tputs(tgoto(Str(T_DC), num, num), num, term__putc); 62454235Sbostic return; 62554235Sbostic } 62654235Sbostic 62754235Sbostic if (GoodStr(T_dm)) /* if I have delete mode */ 62854235Sbostic (void) tputs(Str(T_dm), 1, term__putc); 62954235Sbostic 63054235Sbostic if (GoodStr(T_dc)) /* else do one at a time */ 63154235Sbostic while (num--) 63254235Sbostic (void) tputs(Str(T_dc), 1, term__putc); 63354235Sbostic 63454235Sbostic if (GoodStr(T_ed)) /* if I have delete mode */ 63554235Sbostic (void) tputs(Str(T_ed), 1, term__putc); 63654235Sbostic } /* end term_deletechars */ 63754235Sbostic 63854235Sbostic 63954235Sbostic /* term_insertwrite(): 64054235Sbostic * Puts terminal in insert character mode or inserts num 64154235Sbostic * characters in the line 64254235Sbostic */ 64354235Sbostic protected void 64454235Sbostic term_insertwrite(el, cp, num) 64554235Sbostic EditLine *el; 64654235Sbostic char *cp; 64754235Sbostic int num; 64854235Sbostic { 64954235Sbostic if (num <= 0) 65054235Sbostic return; 65154235Sbostic if (!EL_CAN_INSERT) { 65254235Sbostic #ifdef DEBUG_EDIT 65354235Sbostic (void) fprintf(el->el_errfile, " ERROR: cannot insert \n"); 65454235Sbostic #endif /* DEBUG_EDIT */ 65554235Sbostic return; 65654235Sbostic } 65754235Sbostic 65854235Sbostic if (num > el->el_term.t_size.h) { 65954235Sbostic #ifdef DEBUG_SCREEN 66054235Sbostic (void) fprintf(el->el_errfile, "StartInsert: num is riduculous: %d\r\n", num); 66154235Sbostic #endif /* DEBUG_SCREEN */ 66254235Sbostic return; 66354235Sbostic } 66454235Sbostic 66554235Sbostic if (GoodStr(T_IC)) /* if I have multiple insert */ 66654235Sbostic if ((num > 1) || !GoodStr(T_ic)) { /* if ic would be more expen. */ 66754235Sbostic (void) tputs(tgoto(Str(T_IC), num, num), num, term__putc); 66854235Sbostic term_overwrite(el, cp, num); /* this updates el_cursor.h */ 66954235Sbostic return; 67054235Sbostic } 67154235Sbostic 67254235Sbostic if (GoodStr(T_im) && GoodStr(T_ei)) { /* if I have insert mode */ 67354235Sbostic (void) tputs(Str(T_im), 1, term__putc); 67454235Sbostic 67554235Sbostic el->el_cursor.h += num; 67654235Sbostic do 67754235Sbostic term__putc(*cp++); 67854235Sbostic while (--num); 67954235Sbostic 68054235Sbostic if (GoodStr(T_ip)) /* have to make num chars insert */ 68154235Sbostic (void) tputs(Str(T_ip), 1, term__putc); 68254235Sbostic 68354235Sbostic (void) tputs(Str(T_ei), 1, term__putc); 68454235Sbostic return; 68554235Sbostic } 68654235Sbostic 68754235Sbostic do { 68854235Sbostic if (GoodStr(T_ic)) /* have to make num chars insert */ 68954235Sbostic (void) tputs(Str(T_ic), 1, term__putc); /* insert a char */ 69054235Sbostic 69154235Sbostic term__putc(*cp++); 69254235Sbostic 69354235Sbostic el->el_cursor.h++; 69454235Sbostic 69554235Sbostic if (GoodStr(T_ip)) /* have to make num chars insert */ 69654235Sbostic (void) tputs(Str(T_ip), 1, term__putc);/* pad the inserted char */ 69754235Sbostic 69854235Sbostic } while (--num); 69954235Sbostic } /* end term_insertwrite */ 70054235Sbostic 70154235Sbostic 70254235Sbostic /* term_clear_EOL(): 70354235Sbostic * clear to end of line. There are num characters to clear 70454235Sbostic */ 70554235Sbostic protected void 70654235Sbostic term_clear_EOL(el, num) 70754235Sbostic EditLine *el; 70854235Sbostic int num; 70954235Sbostic { 71054235Sbostic int i; 71154235Sbostic 71254235Sbostic if (EL_CAN_CEOL && GoodStr(T_ce)) 71354235Sbostic (void) tputs(Str(T_ce), 1, term__putc); 71454235Sbostic else { 71554235Sbostic for (i = 0; i < num; i++) 71654235Sbostic term__putc(' '); 71754235Sbostic el->el_cursor.h += num; /* have written num spaces */ 71854235Sbostic } 71954235Sbostic } /* end term_clear_EOL */ 72054235Sbostic 72154235Sbostic 72254235Sbostic /* term_clear_screen(): 72354235Sbostic * Clear the screen 72454235Sbostic */ 72554235Sbostic protected void 72654235Sbostic term_clear_screen(el) 72754235Sbostic EditLine *el; 72854235Sbostic { /* clear the whole screen and home */ 72954235Sbostic if (GoodStr(T_cl)) 73054235Sbostic /* send the clear screen code */ 73154235Sbostic (void) tputs(Str(T_cl), Val(T_li), term__putc); 73254235Sbostic else if (GoodStr(T_ho) && GoodStr(T_cd)) { 73354235Sbostic (void) tputs(Str(T_ho), Val(T_li), term__putc); /* home */ 73454235Sbostic /* clear to bottom of screen */ 73554235Sbostic (void) tputs(Str(T_cd), Val(T_li), term__putc); 73654235Sbostic } 73754235Sbostic else { 73854235Sbostic term__putc('\r'); 73954235Sbostic term__putc('\n'); 74054235Sbostic } 74154235Sbostic } /* end term_clear_screen */ 74254235Sbostic 74354235Sbostic 74454235Sbostic /* term_beep(): 74554235Sbostic * Beep the way the terminal wants us 74654235Sbostic */ 74754235Sbostic protected void 74854235Sbostic term_beep(el) 74954235Sbostic EditLine *el; 75054235Sbostic { 75154235Sbostic if (GoodStr(T_vb)) 75254235Sbostic (void) tputs(Str(T_vb), 1, term__putc); /* visible bell */ 75354235Sbostic else if (GoodStr(T_bl)) 75454235Sbostic /* what termcap says we should use */ 75554235Sbostic (void) tputs(Str(T_bl), 1, term__putc); 75654235Sbostic else 75754235Sbostic term__putc('\007'); /* an ASCII bell; ^G */ 75854235Sbostic } /* end term_beep */ 75954235Sbostic 76054235Sbostic 76154235Sbostic #ifdef notdef 76254235Sbostic /* term_clear_to_bottom(): 76354235Sbostic * Clear to the bottom of the screen 76454235Sbostic */ 76554235Sbostic protected void 76654235Sbostic term_clear_to_bottom(el) 76754235Sbostic EditLine *el; 76854235Sbostic { 76954235Sbostic if (GoodStr(T_cd)) 77054235Sbostic (void) tputs(Str(T_cd), Val(T_li), term__putc); 77154235Sbostic else if (GoodStr(T_ce)) 77254235Sbostic (void) tputs(Str(T_ce), Val(T_li), term__putc); 77354235Sbostic } /* end term_clear_to_bottom */ 77454235Sbostic #endif 77554235Sbostic 77654235Sbostic 777*54624Schristos /* term_set(): 778*54624Schristos * Read in the terminal capabilities from the requested terminal 77954235Sbostic */ 780*54624Schristos protected int 781*54624Schristos term_set(el, term) 78254235Sbostic EditLine *el; 78354235Sbostic char *term; 78454235Sbostic { 78554235Sbostic int i; 78654235Sbostic char buf[TC_BUFSIZE]; 78754235Sbostic char *area; 78854235Sbostic struct termcapstr *t; 78954235Sbostic sigset_t oset, nset; 79054235Sbostic int lins, cols; 79154235Sbostic 79254235Sbostic (void) sigemptyset(&nset); 79354235Sbostic (void) sigaddset(&nset, SIGWINCH); 79454235Sbostic (void) sigprocmask(SIG_BLOCK, &nset, &oset); 79554235Sbostic 79654235Sbostic area = buf; 79754235Sbostic 79854235Sbostic 79954235Sbostic if (term == NULL) 80054235Sbostic term = getenv("TERM"); 80154235Sbostic 80254235Sbostic if (!term || !term[0]) 80354235Sbostic term = "dumb"; 80454235Sbostic 80554235Sbostic memset(el->el_term.t_cap, 0, TC_BUFSIZE); 80654235Sbostic 80754235Sbostic i = tgetent(el->el_term.t_cap, term); 80854235Sbostic 80954235Sbostic if (i <= 0) { 81054235Sbostic if (i == -1) 81154235Sbostic (void) fprintf(el->el_errfile, "Cannot open /etc/termcap.\n"); 81254235Sbostic else if (i == 0) 81354235Sbostic (void) fprintf(el->el_errfile, 81454235Sbostic "No entry for terminal type \"%s\"\n", term); 81554235Sbostic (void) fprintf(el->el_errfile, "using dumb terminal settings.\n"); 81654235Sbostic Val(T_co) = 80; /* do a dumb terminal */ 81754235Sbostic Val(T_pt) = Val(T_km) = Val(T_li) = 0; 81854235Sbostic Val(T_xt) = Val(T_MT); 81954235Sbostic for (t = tstr; t->name != NULL; t++) 82054235Sbostic term_alloc(el, t, NULL); 82154235Sbostic } 82254235Sbostic else { 82354235Sbostic /* Can we tab */ 82454235Sbostic Val(T_pt) = tgetflag("pt"); 82554235Sbostic Val(T_xt) = tgetflag("xt"); 82654235Sbostic /* do we have a meta? */ 82754235Sbostic Val(T_km) = tgetflag("km"); 82854235Sbostic Val(T_MT) = tgetflag("MT"); 82954235Sbostic /* Get the size */ 83054235Sbostic Val(T_co) = tgetnum("co"); 83154235Sbostic Val(T_li) = tgetnum("li"); 83254235Sbostic for (t = tstr; t->name != NULL; t++) 83354235Sbostic term_alloc(el, t, tgetstr(t->name, &area)); 83454235Sbostic } 83554235Sbostic 83654235Sbostic if (Val(T_co) < 2) 83754235Sbostic Val(T_co) = 80; /* just in case */ 83854235Sbostic if (Val(T_li) < 1) 83954235Sbostic Val(T_li) = 24; 84054235Sbostic 84154235Sbostic el->el_term.t_size.v = Val(T_co); 84254235Sbostic el->el_term.t_size.h = Val(T_li); 84354235Sbostic 84454235Sbostic term_setflags(el); 84554235Sbostic 84654235Sbostic (void) term_get_size(el, &lins, &cols);/* get the correct window size */ 84754235Sbostic term_change_size(el, lins, cols); 84854235Sbostic (void) sigprocmask(SIG_SETMASK, &oset, NULL); 849*54624Schristos term_bind_arrow(el); 850*54624Schristos return 0; 851*54624Schristos } /* end term_set */ 85254235Sbostic 85354235Sbostic 85454235Sbostic /* term_get_size(): 85554235Sbostic * Return the new window size in lines and cols, and 85654235Sbostic * true if the size was changed. 85754235Sbostic */ 85854235Sbostic protected int 85954235Sbostic term_get_size(el, lins, cols) 86054235Sbostic EditLine *el; 86154235Sbostic int *lins, *cols; 86254235Sbostic { 86354235Sbostic 86454235Sbostic *cols = Val(T_co); 86554235Sbostic *lins = Val(T_li); 86654235Sbostic 86754235Sbostic #ifdef TIOCGWINSZ 86854235Sbostic { 86954235Sbostic struct winsize ws; 87054235Sbostic if (ioctl(el->el_infd, TIOCGWINSZ, (ioctl_t) &ws) != -1) { 87154235Sbostic if (ws.ws_col) 87254235Sbostic *cols = ws.ws_col; 87354235Sbostic if (ws.ws_row) 87454235Sbostic *lins = ws.ws_row; 87554235Sbostic } 87654235Sbostic } 87754235Sbostic #endif 87854235Sbostic #ifdef TIOCGSIZE 87954235Sbostic { 88054235Sbostic struct ttysize ts; 88154235Sbostic if (ioctl(el->el_infd, TIOCGSIZE, (ioctl_t) &ts) != -1) { 88254235Sbostic if (ts.ts_cols) 88354235Sbostic *cols = ts.ts_cols; 88454235Sbostic if (ts.ts_lines) 88554235Sbostic *lins = ts.ts_lines; 88654235Sbostic } 88754235Sbostic } 88854235Sbostic #endif 88954235Sbostic return (Val(T_co) != *cols || Val(T_li) != *lins); 89054235Sbostic } /* end term_get_size */ 89154235Sbostic 89254235Sbostic 89354235Sbostic /* term_change_size(): 89454235Sbostic * Change the size of the terminal 89554235Sbostic */ 89654235Sbostic protected void 89754235Sbostic term_change_size(el, lins, cols) 89854235Sbostic EditLine *el; 89954235Sbostic int lins, cols; 90054235Sbostic { 90154235Sbostic /* 90254235Sbostic * Just in case 90354235Sbostic */ 90454235Sbostic Val(T_co) = (cols < 2) ? 80 : cols; 90554235Sbostic Val(T_li) = (lins < 1) ? 24 : lins; 90654235Sbostic 90754235Sbostic term_rebuffer_display(el); /* re-make display buffers */ 90854235Sbostic re_clear_display(el); 90954235Sbostic } /* end term_change_size */ 91054235Sbostic 91154235Sbostic 912*54624Schristos /* term_init_arrow(): 913*54624Schristos * Initialize the arrow key bindings from termcap 914*54624Schristos */ 915*54624Schristos private void 916*54624Schristos term_init_arrow(el) 917*54624Schristos EditLine *el; 918*54624Schristos { 919*54624Schristos fkey_t *arrow = el->el_term.t_fkey; 920*54624Schristos 921*54624Schristos arrow[A_K_DN].name = "down"; 922*54624Schristos arrow[A_K_DN].fun.cmd = ED_NEXT_HISTORY; 923*54624Schristos arrow[A_K_DN].type = XK_CMD; 924*54624Schristos 925*54624Schristos arrow[A_K_UP].name = "up"; 926*54624Schristos arrow[A_K_UP].fun.cmd = ED_PREV_HISTORY; 927*54624Schristos arrow[A_K_UP].type = XK_CMD; 928*54624Schristos 929*54624Schristos arrow[A_K_LT].name = "left"; 930*54624Schristos arrow[A_K_LT].fun.cmd = ED_PREV_CHAR; 931*54624Schristos arrow[A_K_LT].type = XK_CMD; 932*54624Schristos 933*54624Schristos arrow[A_K_RT].name = "right"; 934*54624Schristos arrow[A_K_RT].fun.cmd = ED_NEXT_CHAR; 935*54624Schristos arrow[A_K_RT].type = XK_CMD; 936*54624Schristos 937*54624Schristos } 938*54624Schristos 939*54624Schristos 940*54624Schristos /* term_reset_arrow(): 941*54624Schristos * Reset arrow key bindings 942*54624Schristos */ 943*54624Schristos private void 944*54624Schristos term_reset_arrow(el) 945*54624Schristos EditLine *el; 946*54624Schristos { 947*54624Schristos fkey_t *arrow = el->el_term.t_fkey; 948*54624Schristos static char strA[] = {033, '[', 'A', '\0'}; 949*54624Schristos static char strB[] = {033, '[', 'B', '\0'}; 950*54624Schristos static char strC[] = {033, '[', 'C', '\0'}; 951*54624Schristos static char strD[] = {033, '[', 'D', '\0'}; 952*54624Schristos static char stOA[] = {033, 'O', 'A', '\0'}; 953*54624Schristos static char stOB[] = {033, 'O', 'B', '\0'}; 954*54624Schristos static char stOC[] = {033, 'O', 'C', '\0'}; 955*54624Schristos static char stOD[] = {033, 'O', 'D', '\0'}; 956*54624Schristos 957*54624Schristos key_add(el, strA, &arrow[A_K_UP].fun, arrow[A_K_UP].type); 958*54624Schristos key_add(el, strB, &arrow[A_K_DN].fun, arrow[A_K_DN].type); 959*54624Schristos key_add(el, strC, &arrow[A_K_RT].fun, arrow[A_K_RT].type); 960*54624Schristos key_add(el, strD, &arrow[A_K_LT].fun, arrow[A_K_LT].type); 961*54624Schristos key_add(el, stOA, &arrow[A_K_UP].fun, arrow[A_K_UP].type); 962*54624Schristos key_add(el, stOB, &arrow[A_K_DN].fun, arrow[A_K_DN].type); 963*54624Schristos key_add(el, stOC, &arrow[A_K_RT].fun, arrow[A_K_RT].type); 964*54624Schristos key_add(el, stOD, &arrow[A_K_LT].fun, arrow[A_K_LT].type); 965*54624Schristos 966*54624Schristos if (el->el_map.type == MAP_VI) { 967*54624Schristos key_add(el, &strA[1], &arrow[A_K_UP].fun, arrow[A_K_UP].type); 968*54624Schristos key_add(el, &strB[1], &arrow[A_K_DN].fun, arrow[A_K_DN].type); 969*54624Schristos key_add(el, &strC[1], &arrow[A_K_RT].fun, arrow[A_K_RT].type); 970*54624Schristos key_add(el, &strD[1], &arrow[A_K_LT].fun, arrow[A_K_LT].type); 971*54624Schristos key_add(el, &stOA[1], &arrow[A_K_UP].fun, arrow[A_K_UP].type); 972*54624Schristos key_add(el, &stOB[1], &arrow[A_K_DN].fun, arrow[A_K_DN].type); 973*54624Schristos key_add(el, &stOC[1], &arrow[A_K_RT].fun, arrow[A_K_RT].type); 974*54624Schristos key_add(el, &stOD[1], &arrow[A_K_LT].fun, arrow[A_K_LT].type); 975*54624Schristos } 976*54624Schristos } 977*54624Schristos 978*54624Schristos 979*54624Schristos /* term_set_arrow(): 980*54624Schristos * Set an arrow key binding 981*54624Schristos */ 982*54624Schristos protected int 983*54624Schristos term_set_arrow(el, name, fun, type) 984*54624Schristos EditLine *el; 985*54624Schristos char *name; 986*54624Schristos key_value_t *fun; 987*54624Schristos int type; 988*54624Schristos { 989*54624Schristos fkey_t *arrow = el->el_term.t_fkey; 990*54624Schristos int i; 991*54624Schristos 992*54624Schristos for (i = 0; i < A_K_NKEYS; i++) 993*54624Schristos if (strcmp(name, arrow[i].name) == 0) { 994*54624Schristos arrow[i].fun = *fun; 995*54624Schristos arrow[i].type = type; 996*54624Schristos return 0; 997*54624Schristos } 998*54624Schristos return -1; 999*54624Schristos } 1000*54624Schristos 1001*54624Schristos 1002*54624Schristos /* term_clear_arrow(): 1003*54624Schristos * Clear an arrow key binding 1004*54624Schristos */ 1005*54624Schristos protected int 1006*54624Schristos term_clear_arrow(el, name) 1007*54624Schristos EditLine *el; 1008*54624Schristos char *name; 1009*54624Schristos { 1010*54624Schristos fkey_t *arrow = el->el_term.t_fkey; 1011*54624Schristos int i; 1012*54624Schristos 1013*54624Schristos for (i = 0; i < A_K_NKEYS; i++) 1014*54624Schristos if (strcmp(name, arrow[i].name) == 0) { 1015*54624Schristos arrow[i].type = XK_NOD; 1016*54624Schristos return 0; 1017*54624Schristos } 1018*54624Schristos return -1; 1019*54624Schristos } 1020*54624Schristos 1021*54624Schristos 1022*54624Schristos /* term_print_arrow(): 1023*54624Schristos * Print the arrow key bindings 1024*54624Schristos */ 1025*54624Schristos protected void 1026*54624Schristos term_print_arrow(el, name) 1027*54624Schristos EditLine *el; 1028*54624Schristos char *name; 1029*54624Schristos { 1030*54624Schristos int i; 1031*54624Schristos fkey_t *arrow = el->el_term.t_fkey; 1032*54624Schristos 1033*54624Schristos for (i = 0; i < A_K_NKEYS; i++) 1034*54624Schristos if (*name == '\0' || strcmp(name, arrow[i].name) == 0) 1035*54624Schristos if (arrow[i].type != XK_NOD) 1036*54624Schristos key_kprint(el, arrow[i].name, &arrow[i].fun, arrow[i].type); 1037*54624Schristos } 1038*54624Schristos 1039*54624Schristos 1040*54624Schristos /* term_bind_arrow(): 104154235Sbostic * Bind the arrow keys 104254235Sbostic */ 104354235Sbostic protected void 1044*54624Schristos term_bind_arrow(el) 104554235Sbostic EditLine *el; 104654235Sbostic { 104754235Sbostic el_action_t *map, *dmap; 104854235Sbostic int i, j; 104954235Sbostic char *p; 1050*54624Schristos fkey_t *arrow = el->el_term.t_fkey; 105154235Sbostic 105254235Sbostic /* Check if the components needed are initialized */ 105354235Sbostic if (el->el_term.t_buf == NULL || el->el_map.key == NULL) 105454235Sbostic return; 105554235Sbostic 105654235Sbostic map = el->el_map.type == MAP_VI ? el->el_map.alt : el->el_map.key; 105754235Sbostic dmap = el->el_map.type == MAP_VI ? el->el_map.vic : el->el_map.emacs; 105854235Sbostic 1059*54624Schristos term_reset_arrow(el); 1060*54624Schristos 106154235Sbostic for (i = 0; i < 4; i++) { 1062*54624Schristos p = el->el_term.t_str[arrow[i].key]; 106354235Sbostic if (p && *p) { 106454235Sbostic j = (unsigned char) *p; 106554235Sbostic /* 106654235Sbostic * Assign the arrow keys only if: 106754235Sbostic * 106854235Sbostic * 1. They are multi-character arrow keys and the user 106954235Sbostic * has not re-assigned the leading character, or 107054235Sbostic * has re-assigned the leading character to be 107154235Sbostic * ED_SEQUENCE_LEAD_IN 107254235Sbostic * 2. They are single arrow keys pointing to an unassigned key. 107354235Sbostic */ 1074*54624Schristos if (arrow[i].type == XK_NOD) 107554235Sbostic key_clear(el, map, p); 1076*54624Schristos else { 1077*54624Schristos if (p[1] && (dmap[j] == map[j] || 1078*54624Schristos map[j] == ED_SEQUENCE_LEAD_IN)) { 1079*54624Schristos key_add(el, p, &arrow[i].fun, arrow[i].type); 1080*54624Schristos map[j] = ED_SEQUENCE_LEAD_IN; 1081*54624Schristos } 1082*54624Schristos else if (map[j] == ED_UNASSIGNED) { 1083*54624Schristos key_clear(el, map, p); 1084*54624Schristos if (arrow[i].type == XK_CMD) 1085*54624Schristos map[j] = arrow[i].fun.cmd; 1086*54624Schristos else 1087*54624Schristos key_add(el, p, &arrow[i].fun, arrow[i].type); 1088*54624Schristos } 108954235Sbostic } 109054235Sbostic } 109154235Sbostic } 109254235Sbostic } 109354235Sbostic 109454235Sbostic 109554235Sbostic /* term__putc(): 109654235Sbostic * Add a character 109754235Sbostic */ 109854235Sbostic protected void 109954235Sbostic term__putc(c) 110054235Sbostic int c; 110154235Sbostic { 110254235Sbostic (void) fputc(c, term_outfile); 110354235Sbostic } /* end term__putc */ 110454235Sbostic 110554235Sbostic 110654235Sbostic /* term__flush(): 110754235Sbostic * Flush output 110854235Sbostic */ 110954235Sbostic protected void 111054235Sbostic term__flush() 111154235Sbostic { 111254235Sbostic (void) fflush(term_outfile); 111354235Sbostic } /* end term__flush */ 111454235Sbostic 111554235Sbostic 111654235Sbostic /* term_telltc(): 111754235Sbostic * Print the current termcap characteristics 111854235Sbostic */ 111954235Sbostic protected int 112054235Sbostic /*ARGSUSED*/ 112154235Sbostic term_telltc(el, argc, argv) 112254235Sbostic EditLine *el; 112354235Sbostic int argc; 112454235Sbostic char **argv; 112554235Sbostic { 112654235Sbostic struct termcapstr *t; 112754235Sbostic char **ts; 112854235Sbostic char upbuf[EL_BUFSIZ]; 112954235Sbostic 113054235Sbostic (void) fprintf(el->el_outfile, "\n\tYour terminal has the\n"); 113154235Sbostic (void) fprintf(el->el_outfile, "\tfollowing characteristics:\n\n"); 113254235Sbostic (void) fprintf(el->el_outfile, "\tIt has %d columns and %d lines\n", 113354235Sbostic Val(T_co), Val(T_li)); 113454235Sbostic (void) fprintf(el->el_outfile, 113554235Sbostic "\tIt has %s meta key\n", EL_HAS_META ? "a" : "no"); 113654235Sbostic (void) fprintf(el->el_outfile, 113754235Sbostic "\tIt can%suse tabs\n", EL_CAN_TAB ? " " : "not "); 113854235Sbostic #ifdef notyet 113954235Sbostic (void) fprintf(el->el_outfile, "\tIt %s automatic margins\n", 114054235Sbostic (T_Margin&MARGIN_AUTO)? "has": "does not have"); 114154235Sbostic if (T_Margin & MARGIN_AUTO) 114254235Sbostic (void) fprintf(el->el_outfile, "\tIt %s magic margins\n", 114354235Sbostic (T_Margin&MARGIN_MAGIC)?"has":"does not have"); 114454235Sbostic #endif 114554235Sbostic 114654235Sbostic for (t = tstr, ts = el->el_term.t_str; t->name != NULL; t++, ts++) 114754235Sbostic (void) fprintf(el->el_outfile, "\t%25s (%s) == %s\n", t->long_name, 114854235Sbostic t->name, *ts && **ts ? 114954235Sbostic key__decode_str(*ts, upbuf, "") : "(empty)"); 115054235Sbostic (void) fputc('\n', el->el_outfile); 115154235Sbostic return 0; 115254235Sbostic } 115354235Sbostic 115454235Sbostic 115554235Sbostic /* term_settc(): 115654235Sbostic * Change the current terminal characteristics 115754235Sbostic */ 115854235Sbostic protected int 115954235Sbostic /*ARGSUSED*/ 116054235Sbostic term_settc(el, argc, argv) 116154235Sbostic EditLine *el; 116254235Sbostic int argc; 116354235Sbostic char **argv; 116454235Sbostic { 116554235Sbostic struct termcapstr *ts; 116654235Sbostic struct termcapval *tv; 116754235Sbostic char *what, *how; 116854235Sbostic 116954235Sbostic if (argv == NULL || argv[1] == NULL || argv[2] == NULL) 117054235Sbostic return -1; 117154235Sbostic 117254235Sbostic what = argv[1]; 117354235Sbostic how = argv[2]; 117454235Sbostic 117554235Sbostic /* 117654235Sbostic * Do the strings first 117754235Sbostic */ 117854235Sbostic for (ts = tstr; ts->name != NULL; ts++) 117954235Sbostic if (strcmp(ts->name, what) == 0) 118054235Sbostic break; 118154235Sbostic 118254235Sbostic if (ts->name != NULL) { 118354235Sbostic term_alloc(el, ts, how); 118454235Sbostic term_setflags(el); 118554235Sbostic return 0; 118654235Sbostic } 118754235Sbostic 118854235Sbostic /* 118954235Sbostic * Do the numeric ones second 119054235Sbostic */ 119154235Sbostic for (tv = tval; tv->name != NULL; tv++) 119254235Sbostic if (strcmp(tv->name, what) == 0) 119354235Sbostic break; 119454235Sbostic 119554235Sbostic if (tv->name != NULL) { 119654235Sbostic if (tv == &tval[T_pt] || tv == &tval[T_km] 119754235Sbostic #ifdef notyet 119854235Sbostic || tv == &tval[T_am] || tv == &tval[T_xn] 119954235Sbostic #endif 120054235Sbostic ) { 120154235Sbostic if (strcmp(how, "yes") == 0) 120254235Sbostic el->el_term.t_val[tv - tval] = 1; 120354235Sbostic else if (strcmp(how, "no") == 0) 120454235Sbostic el->el_term.t_val[tv - tval] = 0; 120554235Sbostic else { 120654235Sbostic (void) fprintf(el->el_errfile, "settc: Bad value `%s'.\n", how); 120754235Sbostic return -1; 120854235Sbostic } 120954235Sbostic term_setflags(el); 121054235Sbostic term_change_size(el, Val(T_li), Val(T_co)); 121154235Sbostic return 0; 121254235Sbostic } 121354235Sbostic else { 121454235Sbostic el->el_term.t_val[tv - tval] = atoi(how); 121554235Sbostic el->el_term.t_size.v = Val(T_co); 121654235Sbostic el->el_term.t_size.h = Val(T_li); 121754235Sbostic if (tv == &tval[T_co] || tv == &tval[T_li]) 121854235Sbostic term_change_size(el, Val(T_li), Val(T_co)); 121954235Sbostic return 0; 122054235Sbostic } 122154235Sbostic } 122254235Sbostic return -1; 122354235Sbostic } 122454235Sbostic 122554235Sbostic 122654235Sbostic /* term_echotc(): 122754235Sbostic * Print the termcap string out with variable substitution 122854235Sbostic */ 122954235Sbostic protected int 123054235Sbostic /*ARGSUSED*/ 123154235Sbostic term_echotc(el, argc, argv) 123254235Sbostic EditLine *el; 123354235Sbostic int argc; 123454235Sbostic char **argv; 123554235Sbostic { 123654235Sbostic char *cap, *scap; 123754235Sbostic int arg_need, arg_cols, arg_rows; 123854235Sbostic int verbose = 0, silent = 0; 123954235Sbostic char *area; 124054235Sbostic static char *fmts = "%s\n", *fmtd = "%d\n"; 124154235Sbostic struct termcapstr *t; 124254235Sbostic char buf[TC_BUFSIZE]; 124354235Sbostic 124454235Sbostic area = buf; 124554235Sbostic 124654235Sbostic if (argv == NULL || argv[1] == NULL) 124754235Sbostic return -1; 124854235Sbostic argv++; 124954235Sbostic 125054235Sbostic if (argv[0][0] == '-') { 125154235Sbostic switch (argv[0][1]) { 125254235Sbostic case 'v': 125354235Sbostic verbose = 1; 125454235Sbostic break; 125554235Sbostic case 's': 125654235Sbostic silent = 1; 125754235Sbostic break; 125854235Sbostic default: 125954235Sbostic /* stderror(ERR_NAME | ERR_TCUSAGE); */ 126054235Sbostic break; 126154235Sbostic } 126254235Sbostic argv++; 126354235Sbostic } 126454235Sbostic if (!*argv || *argv[0] == '\0') 126554235Sbostic return 0; 126654235Sbostic if (strcmp(*argv, "tabs") == 0) { 126754235Sbostic (void) fprintf(el->el_outfile, fmts, EL_CAN_TAB ? "yes" : "no"); 126854235Sbostic return 0; 126954235Sbostic } 127054235Sbostic else if (strcmp(*argv, "meta") == 0) { 127154235Sbostic (void) fprintf(el->el_outfile, fmts, Val(T_km) ? "yes" : "no"); 127254235Sbostic return 0; 127354235Sbostic } 127454235Sbostic #ifdef notyet 127554235Sbostic else if (strcmp(*argv, "xn") == 0) { 127654235Sbostic (void) fprintf(el->el_outfile, fmts, T_Margin & MARGIN_MAGIC ? 127754235Sbostic "yes" : "no"); 127854235Sbostic return 0; 127954235Sbostic } 128054235Sbostic else if (strcmp(*argv, "am") == 0) { 128154235Sbostic (void) fprintf(el->el_outfile, fmts, T_Margin & MARGIN_AUTO ? 128254235Sbostic "yes" : "no"); 128354235Sbostic return 0; 128454235Sbostic } 128554235Sbostic #endif 128654235Sbostic else if (strcmp(*argv, "baud") == 0) { 128754235Sbostic int i; 128854235Sbostic 128954235Sbostic for (i = 0; baud_rate[i].b_name != NULL; i++) 129054235Sbostic if (el->el_tty.t_speed == baud_rate[i].b_rate) { 129154235Sbostic (void) fprintf(el->el_outfile, fmts, baud_rate[i].b_name); 129254235Sbostic return 0; 129354235Sbostic } 129454235Sbostic (void) fprintf(el->el_outfile, fmtd, 0); 129554235Sbostic return 0; 129654235Sbostic } 129754235Sbostic else if (strcmp(*argv, "rows") == 0 || strcmp(*argv, "lines") == 0) { 129854235Sbostic (void) fprintf(el->el_outfile, fmtd, Val(T_li)); 129954235Sbostic return 0; 130054235Sbostic } 130154235Sbostic else if (strcmp(*argv, "cols") == 0) { 130254235Sbostic (void) fprintf(el->el_outfile, fmtd, Val(T_co)); 130354235Sbostic return 0; 130454235Sbostic } 130554235Sbostic 130654235Sbostic /* 130754235Sbostic * Try to use our local definition first 130854235Sbostic */ 130954235Sbostic scap = NULL; 131054235Sbostic for (t = tstr; t->name != NULL; t++) 131154235Sbostic if (strcmp(t->name, *argv) == 0) { 131254235Sbostic scap = el->el_term.t_str[t - tstr]; 131354235Sbostic break; 131454235Sbostic } 131554235Sbostic if (t->name == NULL) 131654235Sbostic scap = tgetstr(*argv, &area); 131754235Sbostic if (!scap || scap[0] == '\0') { 131854235Sbostic if (!silent) 131954235Sbostic (void) fprintf(el->el_errfile, 132054235Sbostic "echotc: Termcap parameter `%s' not found.\n", *argv); 132154235Sbostic return -1; 132254235Sbostic } 132354235Sbostic 132454235Sbostic /* 132554235Sbostic * Count home many values we need for this capability. 132654235Sbostic */ 132754235Sbostic for (cap = scap, arg_need = 0; *cap; cap++) 132854235Sbostic if (*cap == '%') 132954235Sbostic switch (*++cap) { 133054235Sbostic case 'd': 133154235Sbostic case '2': 133254235Sbostic case '3': 133354235Sbostic case '.': 133454235Sbostic case '+': 133554235Sbostic arg_need++; 133654235Sbostic break; 133754235Sbostic case '%': 133854235Sbostic case '>': 133954235Sbostic case 'i': 134054235Sbostic case 'r': 134154235Sbostic case 'n': 134254235Sbostic case 'B': 134354235Sbostic case 'D': 134454235Sbostic break; 134554235Sbostic default: 134654235Sbostic /* 134754235Sbostic * hpux has lot's of them... 134854235Sbostic */ 134954235Sbostic if (verbose) 135054235Sbostic (void) fprintf(el->el_errfile, 135154235Sbostic "echotc: Warning: unknown termcap %% `%c'.\n", *cap); 135254235Sbostic /* This is bad, but I won't complain */ 135354235Sbostic break; 135454235Sbostic } 135554235Sbostic 135654235Sbostic switch (arg_need) { 135754235Sbostic case 0: 135854235Sbostic argv++; 135954235Sbostic if (*argv && *argv[0]) { 136054235Sbostic if (!silent) 136154235Sbostic (void) fprintf(el->el_errfile, 136254235Sbostic "echotc: Warning: Extra argument `%s'.\n", *argv); 136354235Sbostic return -1; 136454235Sbostic } 136554235Sbostic (void) tputs(scap, 1, term__putc); 136654235Sbostic break; 136754235Sbostic case 1: 136854235Sbostic argv++; 136954235Sbostic if (!*argv || *argv[0] == '\0') { 137054235Sbostic if (!silent) 137154235Sbostic (void) fprintf(el->el_errfile, 137254235Sbostic "echotc: Warning: Missing argument.\n"); 137354235Sbostic return -1; 137454235Sbostic } 137554235Sbostic arg_cols = 0; 137654235Sbostic arg_rows = atoi(*argv); 137754235Sbostic argv++; 137854235Sbostic if (*argv && *argv[0]) { 137954235Sbostic if (!silent) 138054235Sbostic (void) fprintf(el->el_errfile, 138154235Sbostic "echotc: Warning: Extra argument `%s'.\n", *argv); 138254235Sbostic return -1; 138354235Sbostic } 138454235Sbostic (void) tputs(tgoto(scap, arg_cols, arg_rows), 1, term__putc); 138554235Sbostic break; 138654235Sbostic default: 138754235Sbostic /* This is wrong, but I will ignore it... */ 138854235Sbostic if (verbose) 138954235Sbostic (void) fprintf(el->el_errfile, 139054235Sbostic "echotc: Warning: Too many required arguments (%d).\n", 139154235Sbostic arg_need); 139254235Sbostic /*FALLTHROUGH*/ 139354235Sbostic case 2: 139454235Sbostic argv++; 139554235Sbostic if (!*argv || *argv[0] == '\0') { 139654235Sbostic if (!silent) 139754235Sbostic (void) fprintf(el->el_errfile, 139854235Sbostic "echotc: Warning: Missing argument.\n"); 139954235Sbostic return -1; 140054235Sbostic } 140154235Sbostic arg_cols = atoi(*argv); 140254235Sbostic argv++; 140354235Sbostic if (!*argv || *argv[0] == '\0') { 140454235Sbostic if (!silent) 140554235Sbostic (void) fprintf(el->el_errfile, 140654235Sbostic "echotc: Warning: Missing argument.\n"); 140754235Sbostic return -1; 140854235Sbostic } 140954235Sbostic arg_rows = atoi(*argv); 141054235Sbostic argv++; 141154235Sbostic if (*argv && *argv[0]) { 141254235Sbostic if (!silent) 141354235Sbostic (void) fprintf(el->el_errfile, 141454235Sbostic "echotc: Warning: Extra argument `%s'.\n", *argv); 141554235Sbostic return -1; 141654235Sbostic } 141754235Sbostic (void) tputs(tgoto(scap, arg_cols, arg_rows), arg_rows, term__putc); 141854235Sbostic break; 141954235Sbostic } 142054235Sbostic return 0; 142154235Sbostic } 1422