159243Sobrien/* 259243Sobrien * ed.screen.c: Editor/termcap-curses interface 359243Sobrien */ 459243Sobrien/*- 559243Sobrien * Copyright (c) 1980, 1991 The Regents of the University of California. 659243Sobrien * All rights reserved. 759243Sobrien * 859243Sobrien * Redistribution and use in source and binary forms, with or without 959243Sobrien * modification, are permitted provided that the following conditions 1059243Sobrien * are met: 1159243Sobrien * 1. Redistributions of source code must retain the above copyright 1259243Sobrien * notice, this list of conditions and the following disclaimer. 1359243Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1459243Sobrien * notice, this list of conditions and the following disclaimer in the 1559243Sobrien * documentation and/or other materials provided with the distribution. 16100616Smp * 3. Neither the name of the University nor the names of its contributors 1759243Sobrien * may be used to endorse or promote products derived from this software 1859243Sobrien * without specific prior written permission. 1959243Sobrien * 2059243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2159243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2259243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2359243Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2459243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2559243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2659243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2759243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2859243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2959243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3059243Sobrien * SUCH DAMAGE. 3159243Sobrien */ 3259243Sobrien#include "sh.h" 3359243Sobrien#include "ed.h" 3459243Sobrien#include "tc.h" 3559243Sobrien#include "ed.defns.h" 3659243Sobrien 3759243Sobrien/* #define DEBUG_LITERAL */ 3859243Sobrien 3959243Sobrien/* 4059243Sobrien * IMPORTANT NOTE: these routines are allowed to look at the current screen 4159243Sobrien * and the current possition assuming that it is correct. If this is not 4259243Sobrien * true, then the update will be WRONG! This is (should be) a valid 4359243Sobrien * assumption... 4459243Sobrien */ 4559243Sobrien 4659243Sobrien#define TC_BUFSIZE 2048 4759243Sobrien 4859243Sobrien#define GoodStr(a) (tstr[a].str != NULL && tstr[a].str[0] != '\0') 4959243Sobrien#define Str(a) tstr[a].str 5059243Sobrien#define Val(a) tval[a].val 5159243Sobrien 52167465Smpstatic const struct { 53145479Smp const char *b_name; 54145479Smp speed_t b_rate; 5559243Sobrien} baud_rate[] = { 5659243Sobrien 5759243Sobrien#ifdef B0 5859243Sobrien { "0", B0 }, 5959243Sobrien#endif 6059243Sobrien#ifdef B50 6159243Sobrien { "50", B50 }, 6259243Sobrien#endif 6359243Sobrien#ifdef B75 6459243Sobrien { "75", B75 }, 6559243Sobrien#endif 6659243Sobrien#ifdef B110 6759243Sobrien { "110", B110 }, 6859243Sobrien#endif 6959243Sobrien#ifdef B134 7059243Sobrien { "134", B134 }, 7159243Sobrien#endif 7259243Sobrien#ifdef B150 7359243Sobrien { "150", B150 }, 7459243Sobrien#endif 7559243Sobrien#ifdef B200 7659243Sobrien { "200", B200 }, 7759243Sobrien#endif 7859243Sobrien#ifdef B300 7959243Sobrien { "300", B300 }, 8059243Sobrien#endif 8159243Sobrien#ifdef B600 8259243Sobrien { "600", B600 }, 8359243Sobrien#endif 8459243Sobrien#ifdef B900 8559243Sobrien { "900", B900 }, 8659243Sobrien#endif 8759243Sobrien#ifdef B1200 8859243Sobrien { "1200", B1200 }, 8959243Sobrien#endif 9059243Sobrien#ifdef B1800 9159243Sobrien { "1800", B1800 }, 9259243Sobrien#endif 9359243Sobrien#ifdef B2400 9459243Sobrien { "2400", B2400 }, 9559243Sobrien#endif 9659243Sobrien#ifdef B3600 9759243Sobrien { "3600", B3600 }, 9859243Sobrien#endif 9959243Sobrien#ifdef B4800 10059243Sobrien { "4800", B4800 }, 10159243Sobrien#endif 10259243Sobrien#ifdef B7200 10359243Sobrien { "7200", B7200 }, 10459243Sobrien#endif 10559243Sobrien#ifdef B9600 10659243Sobrien { "9600", B9600 }, 10759243Sobrien#endif 10859243Sobrien#ifdef EXTA 10959243Sobrien { "19200", EXTA }, 11059243Sobrien#endif 11159243Sobrien#ifdef B19200 11259243Sobrien { "19200", B19200 }, 11359243Sobrien#endif 11459243Sobrien#ifdef EXTB 11559243Sobrien { "38400", EXTB }, 11659243Sobrien#endif 11759243Sobrien#ifdef B38400 11859243Sobrien { "38400", B38400 }, 11959243Sobrien#endif 12059243Sobrien { NULL, 0 } 12159243Sobrien}; 12259243Sobrien 123167465Smp#define T_at7 0 124167465Smp#define T_al 1 125167465Smp#define T_bl 2 126167465Smp#define T_cd 3 127167465Smp#define T_ce 4 128167465Smp#define T_ch 5 129167465Smp#define T_cl 6 130167465Smp#define T_dc 7 131167465Smp#define T_dl 8 132167465Smp#define T_dm 9 133167465Smp#define T_ed 10 134167465Smp#define T_ei 11 135167465Smp#define T_fs 12 136167465Smp#define T_ho 13 137167465Smp#define T_ic 14 138167465Smp#define T_im 15 139167465Smp#define T_ip 16 140167465Smp#define T_kd 17 141167465Smp#define T_kh 18 142167465Smp#define T_kl 19 143167465Smp#define T_kr 20 144167465Smp#define T_ku 21 145167465Smp#define T_md 22 146167465Smp#define T_me 23 147167465Smp#define T_mr 24 148167465Smp#define T_nd 25 149167465Smp#define T_se 26 150167465Smp#define T_so 27 151167465Smp#define T_ts 28 152167465Smp#define T_up 29 153167465Smp#define T_us 30 154167465Smp#define T_ue 31 155167465Smp#define T_vb 32 156167465Smp#define T_DC 33 157167465Smp#define T_DO 34 158167465Smp#define T_IC 35 159167465Smp#define T_LE 36 160167465Smp#define T_RI 37 161167465Smp#define T_UP 38 162167465Smp#define T_str 39 163167465Smp 16459243Sobrienstatic struct termcapstr { 165145479Smp const char *name; 166145479Smp const char *long_name; 16759243Sobrien char *str; 16859243Sobrien} tstr[T_str + 1]; 16959243Sobrien 17059243Sobrien 17159243Sobrien#define T_am 0 17259243Sobrien#define T_pt 1 17359243Sobrien#define T_li 2 17459243Sobrien#define T_co 3 17559243Sobrien#define T_km 4 17659243Sobrien#define T_xn 5 17759243Sobrien#define T_val 6 17859243Sobrienstatic struct termcapval { 179145479Smp const char *name; 180145479Smp const char *long_name; 18159243Sobrien int val; 18259243Sobrien} tval[T_val + 1]; 18359243Sobrien 18459243Sobrienvoid 185167465Smpterminit(void) 18659243Sobrien{ 18759243Sobrien#ifdef NLS_CATALOGS 18859243Sobrien int i; 18959243Sobrien 19059243Sobrien for (i = 0; i < T_str + 1; i++) 191167465Smp xfree((ptr_t)(intptr_t)tstr[i].long_name); 19259243Sobrien 19359243Sobrien for (i = 0; i < T_val + 1; i++) 194167465Smp xfree((ptr_t)(intptr_t)tval[i].long_name); 19559243Sobrien#endif 19659243Sobrien 19759243Sobrien tstr[T_al].name = "al"; 19859243Sobrien tstr[T_al].long_name = CSAVS(4, 1, "add new blank line"); 19959243Sobrien 20059243Sobrien tstr[T_bl].name = "bl"; 20159243Sobrien tstr[T_bl].long_name = CSAVS(4, 2, "audible bell"); 20259243Sobrien 20359243Sobrien tstr[T_cd].name = "cd"; 20459243Sobrien tstr[T_cd].long_name = CSAVS(4, 3, "clear to bottom"); 20559243Sobrien 20659243Sobrien tstr[T_ce].name = "ce"; 20759243Sobrien tstr[T_ce].long_name = CSAVS(4, 4, "clear to end of line"); 20859243Sobrien 20959243Sobrien tstr[T_ch].name = "ch"; 21059243Sobrien tstr[T_ch].long_name = CSAVS(4, 5, "cursor to horiz pos"); 21159243Sobrien 21259243Sobrien tstr[T_cl].name = "cl"; 21359243Sobrien tstr[T_cl].long_name = CSAVS(4, 6, "clear screen"); 21459243Sobrien 21559243Sobrien tstr[T_dc].name = "dc"; 21659243Sobrien tstr[T_dc].long_name = CSAVS(4, 7, "delete a character"); 21759243Sobrien 21859243Sobrien tstr[T_dl].name = "dl"; 21959243Sobrien tstr[T_dl].long_name = CSAVS(4, 8, "delete a line"); 22059243Sobrien 22159243Sobrien tstr[T_dm].name = "dm"; 22259243Sobrien tstr[T_dm].long_name = CSAVS(4, 9, "start delete mode"); 22359243Sobrien 22459243Sobrien tstr[T_ed].name = "ed"; 22559243Sobrien tstr[T_ed].long_name = CSAVS(4, 10, "end delete mode"); 22659243Sobrien 22759243Sobrien tstr[T_ei].name = "ei"; 22859243Sobrien tstr[T_ei].long_name = CSAVS(4, 11, "end insert mode"); 22959243Sobrien 23059243Sobrien tstr[T_fs].name = "fs"; 23159243Sobrien tstr[T_fs].long_name = CSAVS(4, 12, "cursor from status line"); 23259243Sobrien 23359243Sobrien tstr[T_ho].name = "ho"; 23459243Sobrien tstr[T_ho].long_name = CSAVS(4, 13, "home cursor"); 23559243Sobrien 23659243Sobrien tstr[T_ic].name = "ic"; 23759243Sobrien tstr[T_ic].long_name = CSAVS(4, 14, "insert character"); 23859243Sobrien 23959243Sobrien tstr[T_im].name = "im"; 24059243Sobrien tstr[T_im].long_name = CSAVS(4, 15, "start insert mode"); 24159243Sobrien 24259243Sobrien tstr[T_ip].name = "ip"; 24359243Sobrien tstr[T_ip].long_name = CSAVS(4, 16, "insert padding"); 24459243Sobrien 24559243Sobrien tstr[T_kd].name = "kd"; 24659243Sobrien tstr[T_kd].long_name = CSAVS(4, 17, "sends cursor down"); 24759243Sobrien 24859243Sobrien tstr[T_kl].name = "kl"; 24959243Sobrien tstr[T_kl].long_name = CSAVS(4, 18, "sends cursor left"); 25059243Sobrien 25159243Sobrien tstr[T_kr].name = "kr"; 25259243Sobrien tstr[T_kr].long_name = CSAVS(4, 19, "sends cursor right"); 25359243Sobrien 25459243Sobrien tstr[T_ku].name = "ku"; 25559243Sobrien tstr[T_ku].long_name = CSAVS(4, 20, "sends cursor up"); 25659243Sobrien 25759243Sobrien tstr[T_md].name = "md"; 25859243Sobrien tstr[T_md].long_name = CSAVS(4, 21, "begin bold"); 25959243Sobrien 26059243Sobrien tstr[T_me].name = "me"; 26159243Sobrien tstr[T_me].long_name = CSAVS(4, 22, "end attributes"); 26259243Sobrien 26359243Sobrien tstr[T_nd].name = "nd"; 26459243Sobrien tstr[T_nd].long_name = CSAVS(4, 23, "non destructive space"); 26559243Sobrien 26659243Sobrien tstr[T_se].name = "se"; 26759243Sobrien tstr[T_se].long_name = CSAVS(4, 24, "end standout"); 26859243Sobrien 26959243Sobrien tstr[T_so].name = "so"; 27059243Sobrien tstr[T_so].long_name = CSAVS(4, 25, "begin standout"); 27159243Sobrien 27259243Sobrien tstr[T_ts].name = "ts"; 27359243Sobrien tstr[T_ts].long_name = CSAVS(4, 26, "cursor to status line"); 27459243Sobrien 27559243Sobrien tstr[T_up].name = "up"; 27659243Sobrien tstr[T_up].long_name = CSAVS(4, 27, "cursor up one"); 27759243Sobrien 27859243Sobrien tstr[T_us].name = "us"; 27959243Sobrien tstr[T_us].long_name = CSAVS(4, 28, "begin underline"); 28059243Sobrien 28159243Sobrien tstr[T_ue].name = "ue"; 28259243Sobrien tstr[T_ue].long_name = CSAVS(4, 29, "end underline"); 28359243Sobrien 28459243Sobrien tstr[T_vb].name = "vb"; 28559243Sobrien tstr[T_vb].long_name = CSAVS(4, 30, "visible bell"); 28659243Sobrien 28759243Sobrien tstr[T_DC].name = "DC"; 28859243Sobrien tstr[T_DC].long_name = CSAVS(4, 31, "delete multiple chars"); 28959243Sobrien 29059243Sobrien tstr[T_DO].name = "DO"; 29159243Sobrien tstr[T_DO].long_name = CSAVS(4, 32, "cursor down multiple"); 29259243Sobrien 29359243Sobrien tstr[T_IC].name = "IC"; 29459243Sobrien tstr[T_IC].long_name = CSAVS(4, 33, "insert multiple chars"); 29559243Sobrien 29659243Sobrien tstr[T_LE].name = "LE"; 29759243Sobrien tstr[T_LE].long_name = CSAVS(4, 34, "cursor left multiple"); 29859243Sobrien 29959243Sobrien tstr[T_RI].name = "RI"; 30059243Sobrien tstr[T_RI].long_name = CSAVS(4, 35, "cursor right multiple"); 30159243Sobrien 30259243Sobrien tstr[T_UP].name = "UP"; 30359243Sobrien tstr[T_UP].long_name = CSAVS(4, 36, "cursor up multiple"); 30459243Sobrien 30569408Sache tstr[T_kh].name = "kh"; 306167465Smp tstr[T_kh].long_name = CSAVS(4, 43, "send cursor home"); 30769408Sache 30869408Sache tstr[T_at7].name = "@7"; 309167465Smp tstr[T_at7].long_name = CSAVS(4, 44, "send cursor end"); 31069408Sache 311167465Smp tstr[T_mr].name = "mr"; 312167465Smp tstr[T_mr].long_name = CSAVS(4, 45, "begin reverse video"); 313167465Smp 31459243Sobrien tstr[T_str].name = NULL; 31559243Sobrien tstr[T_str].long_name = NULL; 31659243Sobrien 31759243Sobrien 31859243Sobrien tval[T_am].name = "am"; 31959243Sobrien tval[T_am].long_name = CSAVS(4, 37, "Has automatic margins"); 32059243Sobrien 32159243Sobrien tval[T_pt].name = "pt"; 32259243Sobrien tval[T_pt].long_name = CSAVS(4, 38, "Can use physical tabs"); 32359243Sobrien 32459243Sobrien tval[T_li].name = "li"; 32559243Sobrien tval[T_li].long_name = CSAVS(4, 39, "Number of lines"); 32659243Sobrien 32759243Sobrien tval[T_co].name = "co"; 32859243Sobrien tval[T_co].long_name = CSAVS(4, 40, "Number of columns"); 32959243Sobrien 33059243Sobrien tval[T_km].name = "km"; 33159243Sobrien tval[T_km].long_name = CSAVS(4, 41, "Has meta key"); 33259243Sobrien 33359243Sobrien tval[T_xn].name = "xn"; 33459243Sobrien tval[T_xn].long_name = CSAVS(4, 42, "Newline ignored at right margin"); 33559243Sobrien 33659243Sobrien tval[T_val].name = NULL; 33759243Sobrien tval[T_val].long_name = NULL; 33859243Sobrien} 33959243Sobrien 34059243Sobrien/* 34159243Sobrien * A very useful table from justin@crim.ca (Justin Bur) :-) 34259243Sobrien * (Modified by per@erix.ericsson.se (Per Hedeland) 34359243Sobrien * - first (and second:-) case fixed) 34459243Sobrien * 34559243Sobrien * Description Termcap variables tcsh behavior 34659243Sobrien * am xn UseRightmost SendCRLF 34759243Sobrien * -------------- ------- ------- ------------ ------------ 34859243Sobrien * Automargins yes no yes no 34959243Sobrien * Magic Margins yes yes yes no 35059243Sobrien * No Wrap no -- yes yes 35159243Sobrien */ 35259243Sobrien 353145479Smpstatic int me_all = 0; /* does two or more of the attributes use me */ 35459243Sobrien 355167465Smpstatic void ReBufferDisplay (void); 356167465Smpstatic void TCset (struct termcapstr *, const char *); 35759243Sobrien 35859243Sobrien 35959243Sobrienstatic void 360167465SmpTCset(struct termcapstr *t, const char *cap) 36159243Sobrien{ 36259243Sobrien if (cap == NULL || *cap == '\0') { 363167465Smp xfree(t->str); 36459243Sobrien t->str = NULL; 365167465Smp } else { 366167465Smp size_t size; 36759243Sobrien 368167465Smp size = strlen(cap) + 1; 369167465Smp t->str = xrealloc(t->str, size); 370167465Smp memcpy(t->str, cap, size); 37159243Sobrien } 37259243Sobrien} 37359243Sobrien 37459243Sobrien 37559243Sobrien/*ARGSUSED*/ 37659243Sobrienvoid 377167465SmpTellTC(void) 37859243Sobrien{ 37959243Sobrien struct termcapstr *t; 380167465Smp char *first, *s; 38159243Sobrien 382195609Smp xprintf("%s", CGETS(7, 1, "\n\tTcsh thinks your terminal has the\n")); 383195609Smp xprintf("%s", CGETS(7, 2, "\tfollowing characteristics:\n\n")); 38459243Sobrien xprintf(CGETS(7, 3, "\tIt has %d columns and %d lines\n"), 38559243Sobrien Val(T_co), Val(T_li)); 386145479Smp s = strsave(T_HasMeta ? CGETS(7, 5, "a") : CGETS(7, 6, "no")); 387167465Smp cleanup_push(s, xfree); 388167465Smp first = s; 389145479Smp xprintf(CGETS(7, 4, "\tIt has %s meta key\n"), s); 390145479Smp s = strsave(T_Tabs ? "" : CGETS(7, 8, " not")); 391167465Smp cleanup_push(s, xfree); 392145479Smp xprintf(CGETS(7, 7, "\tIt can%s use tabs\n"), s); 393145479Smp s = strsave((T_Margin&MARGIN_AUTO) ? 394145479Smp CGETS(7, 10, "has") : CGETS(7, 11, "does not have")); 395167465Smp cleanup_push(s, xfree); 396145479Smp xprintf(CGETS(7, 9, "\tIt %s automatic margins\n"), s); 397145479Smp if (T_Margin & MARGIN_AUTO) { 398145479Smp s = strsave((T_Margin & MARGIN_MAGIC) ? 399145479Smp CGETS(7, 10, "has") : CGETS(7, 11, "does not have")); 400167465Smp cleanup_push(s, xfree); 401145479Smp xprintf(CGETS(7, 12, "\tIt %s magic margins\n"), s); 402145479Smp } 403145479Smp for (t = tstr; t->name != NULL; t++) { 404145479Smp s = strsave(t->str && *t->str ? t->str : CGETS(7, 13, "(empty)")); 405167465Smp cleanup_push(s, xfree); 406145479Smp xprintf("\t%36s (%s) == %s\n", t->long_name, t->name, s); 407167465Smp cleanup_until(s); 408145479Smp } 40959243Sobrien xputchar('\n'); 410167465Smp cleanup_until(first); 41159243Sobrien} 41259243Sobrien 41359243Sobrien 41459243Sobrienstatic void 415167465SmpReBufferDisplay(void) 41659243Sobrien{ 417145479Smp int i; 418145479Smp Char **b; 41959243Sobrien 42059243Sobrien b = Display; 42159243Sobrien Display = NULL; 422167465Smp blkfree(b); 42359243Sobrien b = Vdisplay; 42459243Sobrien Vdisplay = NULL; 425167465Smp blkfree(b); 42659243Sobrien TermH = Val(T_co); 427167465Smp TermV = (INBUFSIZE * 4) / TermH + 1;/*FIXBUF*/ 428167465Smp b = xmalloc(sizeof(*b) * (TermV + 1)); 42959243Sobrien for (i = 0; i < TermV; i++) 430167465Smp b[i] = xmalloc(sizeof(*b[i]) * (TermH + 1)); 43159243Sobrien b[TermV] = NULL; 43259243Sobrien Display = b; 433167465Smp b = xmalloc(sizeof(*b) * (TermV + 1)); 43459243Sobrien for (i = 0; i < TermV; i++) 435167465Smp b[i] = xmalloc(sizeof(*b[i]) * (TermH + 1)); 43659243Sobrien b[TermV] = NULL; 43759243Sobrien Vdisplay = b; 43859243Sobrien} 43959243Sobrien 44059243Sobrienvoid 441167465SmpSetTC(char *what, char *how) 44259243Sobrien{ 44359243Sobrien struct termcapstr *ts; 44459243Sobrien struct termcapval *tv; 44559243Sobrien 44659243Sobrien /* 44759243Sobrien * Do the strings first 44859243Sobrien */ 44959243Sobrien setname("settc"); 45059243Sobrien for (ts = tstr; ts->name != NULL; ts++) 45159243Sobrien if (strcmp(ts->name, what) == 0) 45259243Sobrien break; 45359243Sobrien if (ts->name != NULL) { 454167465Smp TCset(ts, how); 45559243Sobrien /* 45659243Sobrien * Reset variables 45759243Sobrien */ 45859243Sobrien if (GoodStr(T_me) && GoodStr(T_ue)) 45959243Sobrien me_all = (strcmp(Str(T_me), Str(T_ue)) == 0); 46059243Sobrien else 46159243Sobrien me_all = 0; 46259243Sobrien if (GoodStr(T_me) && GoodStr(T_se)) 46359243Sobrien me_all |= (strcmp(Str(T_me), Str(T_se)) == 0); 46459243Sobrien 46559243Sobrien T_CanCEOL = GoodStr(T_ce); 46659243Sobrien T_CanDel = GoodStr(T_dc) || GoodStr(T_DC); 46759243Sobrien T_CanIns = GoodStr(T_im) || GoodStr(T_ic) || GoodStr(T_IC); 46859243Sobrien T_CanUP = GoodStr(T_up) || GoodStr(T_UP); 46959243Sobrien return; 47059243Sobrien } 47159243Sobrien 47259243Sobrien /* 47359243Sobrien * Do the numeric ones second 47459243Sobrien */ 47559243Sobrien for (tv = tval; tv->name != NULL; tv++) 47659243Sobrien if (strcmp(tv->name, what) == 0) 47759243Sobrien break; 47859243Sobrien 47959243Sobrien if (tv->name != NULL) { 48059243Sobrien if (tv == &tval[T_pt] || tv == &tval[T_km] || 48159243Sobrien tv == &tval[T_am] || tv == &tval[T_xn]) { 48259243Sobrien if (strcmp(how, "yes") == 0) 48359243Sobrien tv->val = 1; 48459243Sobrien else if (strcmp(how, "no") == 0) 48559243Sobrien tv->val = 0; 48659243Sobrien else { 48759243Sobrien stderror(ERR_SETTCUS, tv->name); 48859243Sobrien return; 48959243Sobrien } 490167465Smp T_Tabs = Val(T_pt); 491167465Smp T_HasMeta = Val(T_km); 492167465Smp T_Margin = Val(T_am) ? MARGIN_AUTO : 0; 493167465Smp T_Margin |= Val(T_xn) ? MARGIN_MAGIC : 0; 49459243Sobrien if (tv == &tval[T_am] || tv == &tval[T_xn]) 49559243Sobrien ChangeSize(Val(T_li), Val(T_co)); 49659243Sobrien return; 49759243Sobrien } 49859243Sobrien else { 49959243Sobrien tv->val = atoi(how); 50059243Sobrien T_Cols = (Char) Val(T_co); 50159243Sobrien T_Lines = (Char) Val(T_li); 50259243Sobrien if (tv == &tval[T_co] || tv == &tval[T_li]) 50359243Sobrien ChangeSize(Val(T_li), Val(T_co)); 50459243Sobrien return; 50559243Sobrien } 50659243Sobrien } 50759243Sobrien stderror(ERR_NAME | ERR_TCCAP, what); 50859243Sobrien return; 50959243Sobrien} 51059243Sobrien 51159243Sobrien 51259243Sobrien/* 51359243Sobrien * Print the termcap string out with variable substitution 51459243Sobrien */ 51559243Sobrienvoid 516167465SmpEchoTC(Char **v) 51759243Sobrien{ 518167465Smp char *cap, *scap, *cv; 51959243Sobrien int arg_need, arg_cols, arg_rows; 52059243Sobrien int verbose = 0, silent = 0; 52159243Sobrien char *area; 522167465Smp static const char fmts[] = "%s\n", fmtd[] = "%d\n"; 52359243Sobrien struct termcapstr *t; 52459243Sobrien char buf[TC_BUFSIZE]; 525167465Smp Char **globbed; 52659243Sobrien 52759243Sobrien area = buf; 52859243Sobrien 52959243Sobrien setname("echotc"); 53059243Sobrien 531167465Smp v = glob_all_or_error(v); 532167465Smp globbed = v; 533167465Smp cleanup_push(globbed, blk_cleanup); 53459243Sobrien 53559243Sobrien if (!*v || *v[0] == '\0') 536167465Smp goto end; 53759243Sobrien if (v[0][0] == '-') { 53859243Sobrien switch (v[0][1]) { 53959243Sobrien case 'v': 54059243Sobrien verbose = 1; 54159243Sobrien break; 54259243Sobrien case 's': 54359243Sobrien silent = 1; 54459243Sobrien break; 54559243Sobrien default: 54659243Sobrien stderror(ERR_NAME | ERR_TCUSAGE); 54759243Sobrien break; 54859243Sobrien } 54959243Sobrien v++; 55059243Sobrien } 55159243Sobrien if (!*v || *v[0] == '\0') 552167465Smp goto end; 553167465Smp cv = strsave(short2str(*v)); 554167465Smp cleanup_push(cv, xfree); 55559243Sobrien if (strcmp(cv, "tabs") == 0) { 55659243Sobrien xprintf(fmts, T_Tabs ? CGETS(7, 14, "yes") : 55759243Sobrien CGETS(7, 15, "no")); 558167465Smp goto end_flush; 55959243Sobrien } 56059243Sobrien else if (strcmp(cv, "meta") == 0) { 56159243Sobrien xprintf(fmts, Val(T_km) ? CGETS(7, 14, "yes") : 56259243Sobrien CGETS(7, 15, "no")); 563167465Smp goto end_flush; 56459243Sobrien } 56559243Sobrien else if (strcmp(cv, "xn") == 0) { 56659243Sobrien xprintf(fmts, T_Margin & MARGIN_MAGIC ? CGETS(7, 14, "yes") : 56759243Sobrien CGETS(7, 15, "no")); 568167465Smp goto end_flush; 56959243Sobrien } 57059243Sobrien else if (strcmp(cv, "am") == 0) { 57159243Sobrien xprintf(fmts, T_Margin & MARGIN_AUTO ? CGETS(7, 14, "yes") : 57259243Sobrien CGETS(7, 15, "no")); 573167465Smp goto end_flush; 57459243Sobrien } 57559243Sobrien else if (strcmp(cv, "baud") == 0) { 57659243Sobrien int i; 57759243Sobrien 57859243Sobrien for (i = 0; baud_rate[i].b_name != NULL; i++) 57959243Sobrien if (T_Speed == baud_rate[i].b_rate) { 58059243Sobrien xprintf(fmts, baud_rate[i].b_name); 581167465Smp goto end_flush; 58259243Sobrien } 58359243Sobrien xprintf(fmtd, 0); 584167465Smp goto end_flush; 58559243Sobrien } 586167465Smp else if (strcmp(cv, "rows") == 0 || strcmp(cv, "lines") == 0 || 587167465Smp strcmp(cv, "li") == 0) { 58859243Sobrien xprintf(fmtd, Val(T_li)); 589167465Smp goto end_flush; 59059243Sobrien } 591167465Smp else if (strcmp(cv, "cols") == 0 || strcmp(cv, "co") == 0) { 59259243Sobrien xprintf(fmtd, Val(T_co)); 593167465Smp goto end_flush; 59459243Sobrien } 59559243Sobrien 59659243Sobrien /* 59759243Sobrien * Try to use our local definition first 59859243Sobrien */ 59959243Sobrien scap = NULL; 60059243Sobrien for (t = tstr; t->name != NULL; t++) 60159243Sobrien if (strcmp(t->name, cv) == 0) { 60259243Sobrien scap = t->str; 60359243Sobrien break; 60459243Sobrien } 60559243Sobrien if (t->name == NULL) 60659243Sobrien scap = tgetstr(cv, &area); 60759243Sobrien if (!scap || scap[0] == '\0') { 60859243Sobrien if (tgetflag(cv)) { 609195609Smp xprintf("%s", CGETS(7, 14, "yes\n")); 610167465Smp goto end; 61159243Sobrien } 61259243Sobrien if (silent) 613167465Smp goto end; 61459243Sobrien else 61559243Sobrien stderror(ERR_NAME | ERR_TCCAP, cv); 61659243Sobrien } 61759243Sobrien 61859243Sobrien /* 61959243Sobrien * Count home many values we need for this capability. 62059243Sobrien */ 62159243Sobrien for (cap = scap, arg_need = 0; *cap; cap++) 62259243Sobrien if (*cap == '%') 62359243Sobrien switch (*++cap) { 62459243Sobrien case 'd': 62559243Sobrien case '2': 62659243Sobrien case '3': 62759243Sobrien case '.': 62859243Sobrien case '+': 62959243Sobrien arg_need++; 63059243Sobrien break; 63159243Sobrien case '%': 63259243Sobrien case '>': 63359243Sobrien case 'i': 63459243Sobrien case 'r': 63559243Sobrien case 'n': 63659243Sobrien case 'B': 63759243Sobrien case 'D': 63859243Sobrien break; 63959243Sobrien default: 64059243Sobrien /* 64159243Sobrien * hpux has lot's of them... 64259243Sobrien */ 64359243Sobrien if (verbose) 64459243Sobrien stderror(ERR_NAME | ERR_TCPARM, *cap); 64559243Sobrien /* This is bad, but I won't complain */ 64659243Sobrien break; 64759243Sobrien } 64859243Sobrien 64959243Sobrien switch (arg_need) { 65059243Sobrien case 0: 65159243Sobrien v++; 65259243Sobrien if (*v && *v[0]) { 65359243Sobrien if (silent) 654167465Smp goto end; 65559243Sobrien else 65659243Sobrien stderror(ERR_NAME | ERR_TCARGS, cv, arg_need); 65759243Sobrien } 65859243Sobrien (void) tputs(scap, 1, PUTRAW); 65959243Sobrien break; 66059243Sobrien case 1: 66159243Sobrien v++; 66259243Sobrien if (!*v || *v[0] == '\0') 66359243Sobrien stderror(ERR_NAME | ERR_TCNARGS, cv, 1); 66459243Sobrien arg_cols = 0; 66559243Sobrien arg_rows = atoi(short2str(*v)); 66659243Sobrien v++; 66759243Sobrien if (*v && *v[0]) { 66859243Sobrien if (silent) 669167465Smp goto end; 67059243Sobrien else 67159243Sobrien stderror(ERR_NAME | ERR_TCARGS, cv, arg_need); 67259243Sobrien } 67359243Sobrien (void) tputs(tgoto(scap, arg_cols, arg_rows), 1, PUTRAW); 67459243Sobrien break; 67559243Sobrien default: 67659243Sobrien /* This is wrong, but I will ignore it... */ 67759243Sobrien if (verbose) 67859243Sobrien stderror(ERR_NAME | ERR_TCARGS, cv, arg_need); 67959243Sobrien /*FALLTHROUGH*/ 68059243Sobrien case 2: 68159243Sobrien v++; 68259243Sobrien if (!*v || *v[0] == '\0') { 68359243Sobrien if (silent) 684167465Smp goto end; 68559243Sobrien else 68659243Sobrien stderror(ERR_NAME | ERR_TCNARGS, cv, 2); 68759243Sobrien } 68859243Sobrien arg_cols = atoi(short2str(*v)); 68959243Sobrien v++; 69059243Sobrien if (!*v || *v[0] == '\0') { 69159243Sobrien if (silent) 692167465Smp goto end; 69359243Sobrien else 69459243Sobrien stderror(ERR_NAME | ERR_TCNARGS, cv, 2); 69559243Sobrien } 69659243Sobrien arg_rows = atoi(short2str(*v)); 69759243Sobrien v++; 69859243Sobrien if (*v && *v[0]) { 69959243Sobrien if (silent) 700167465Smp goto end; 70159243Sobrien else 70259243Sobrien stderror(ERR_NAME | ERR_TCARGS, cv, arg_need); 70359243Sobrien } 70459243Sobrien (void) tputs(tgoto(scap, arg_cols, arg_rows), arg_rows, PUTRAW); 70559243Sobrien break; 70659243Sobrien } 707167465Smp end_flush: 70859243Sobrien flush(); 709167465Smp end: 710167465Smp cleanup_until(globbed); 71159243Sobrien} 71259243Sobrien 713145479Smpint GotTermCaps = 0; 71459243Sobrien 71559243Sobrienstatic struct { 71659243Sobrien Char *name; 71759243Sobrien int key; 71859243Sobrien XmapVal fun; 71959243Sobrien int type; 72059243Sobrien} arrow[] = { 72159243Sobrien#define A_K_DN 0 722145479Smp { STRdown, T_kd, { 0 }, 0 }, 72359243Sobrien#define A_K_UP 1 724145479Smp { STRup, T_ku, { 0 }, 0 }, 72559243Sobrien#define A_K_LT 2 726145479Smp { STRleft, T_kl, { 0 }, 0 }, 72759243Sobrien#define A_K_RT 3 728145479Smp { STRright, T_kr, { 0 }, 0 }, 72969408Sache#define A_K_HO 4 730145479Smp { STRhome, T_kh, { 0 }, 0 }, 73169408Sache#define A_K_EN 5 732145479Smp { STRend, T_at7, { 0 }, 0} 73359243Sobrien}; 73469408Sache#define A_K_NKEYS 6 73559243Sobrien 73659243Sobrienvoid 737167465SmpResetArrowKeys(void) 73859243Sobrien{ 73959243Sobrien arrow[A_K_DN].fun.cmd = F_DOWN_HIST; 74059243Sobrien arrow[A_K_DN].type = XK_CMD; 74159243Sobrien 74259243Sobrien arrow[A_K_UP].fun.cmd = F_UP_HIST; 74359243Sobrien arrow[A_K_UP].type = XK_CMD; 74459243Sobrien 74559243Sobrien arrow[A_K_LT].fun.cmd = F_CHARBACK; 74659243Sobrien arrow[A_K_LT].type = XK_CMD; 74759243Sobrien 74859243Sobrien arrow[A_K_RT].fun.cmd = F_CHARFWD; 74959243Sobrien arrow[A_K_RT].type = XK_CMD; 75059243Sobrien 75169408Sache arrow[A_K_HO].fun.cmd = F_TOBEG; 75269408Sache arrow[A_K_HO].type = XK_CMD; 75369408Sache 75469408Sache arrow[A_K_EN].fun.cmd = F_TOEND; 75569408Sache arrow[A_K_EN].type = XK_CMD; 75659243Sobrien} 75759243Sobrien 75859243Sobrienvoid 759167465SmpDefaultArrowKeys(void) 76059243Sobrien{ 76159243Sobrien static Char strA[] = {033, '[', 'A', '\0'}; 76259243Sobrien static Char strB[] = {033, '[', 'B', '\0'}; 76359243Sobrien static Char strC[] = {033, '[', 'C', '\0'}; 76459243Sobrien static Char strD[] = {033, '[', 'D', '\0'}; 76569408Sache static Char strH[] = {033, '[', 'H', '\0'}; 76669408Sache static Char strF[] = {033, '[', 'F', '\0'}; 76759243Sobrien static Char stOA[] = {033, 'O', 'A', '\0'}; 76859243Sobrien static Char stOB[] = {033, 'O', 'B', '\0'}; 76959243Sobrien static Char stOC[] = {033, 'O', 'C', '\0'}; 77059243Sobrien static Char stOD[] = {033, 'O', 'D', '\0'}; 77169408Sache static Char stOH[] = {033, 'O', 'H', '\0'}; 77269408Sache static Char stOF[] = {033, 'O', 'F', '\0'}; 77359243Sobrien 77459243Sobrien CStr cs; 77569408Sache#ifndef IS_ASCII 77659243Sobrien if (strA[0] == 033) 77759243Sobrien { 77859243Sobrien strA[0] = CTL_ESC('\033'); 77959243Sobrien strB[0] = CTL_ESC('\033'); 78059243Sobrien strC[0] = CTL_ESC('\033'); 78159243Sobrien strD[0] = CTL_ESC('\033'); 78269408Sache strH[0] = CTL_ESC('\033'); 78369408Sache strF[0] = CTL_ESC('\033'); 78459243Sobrien stOA[0] = CTL_ESC('\033'); 78559243Sobrien stOB[0] = CTL_ESC('\033'); 78659243Sobrien stOC[0] = CTL_ESC('\033'); 78759243Sobrien stOD[0] = CTL_ESC('\033'); 78869408Sache stOH[0] = CTL_ESC('\033'); 78969408Sache stOF[0] = CTL_ESC('\033'); 79059243Sobrien } 79159243Sobrien#endif 79259243Sobrien 79359243Sobrien cs.len = 3; 79459243Sobrien 79559243Sobrien cs.buf = strA; AddXkey(&cs, &arrow[A_K_UP].fun, arrow[A_K_UP].type); 79659243Sobrien cs.buf = strB; AddXkey(&cs, &arrow[A_K_DN].fun, arrow[A_K_DN].type); 79759243Sobrien cs.buf = strC; AddXkey(&cs, &arrow[A_K_RT].fun, arrow[A_K_RT].type); 79859243Sobrien cs.buf = strD; AddXkey(&cs, &arrow[A_K_LT].fun, arrow[A_K_LT].type); 79969408Sache cs.buf = strH; AddXkey(&cs, &arrow[A_K_HO].fun, arrow[A_K_HO].type); 80069408Sache cs.buf = strF; AddXkey(&cs, &arrow[A_K_EN].fun, arrow[A_K_EN].type); 80159243Sobrien cs.buf = stOA; AddXkey(&cs, &arrow[A_K_UP].fun, arrow[A_K_UP].type); 80259243Sobrien cs.buf = stOB; AddXkey(&cs, &arrow[A_K_DN].fun, arrow[A_K_DN].type); 80359243Sobrien cs.buf = stOC; AddXkey(&cs, &arrow[A_K_RT].fun, arrow[A_K_RT].type); 80459243Sobrien cs.buf = stOD; AddXkey(&cs, &arrow[A_K_LT].fun, arrow[A_K_LT].type); 80569408Sache cs.buf = stOH; AddXkey(&cs, &arrow[A_K_HO].fun, arrow[A_K_HO].type); 80669408Sache cs.buf = stOF; AddXkey(&cs, &arrow[A_K_EN].fun, arrow[A_K_EN].type); 80769408Sache 80859243Sobrien if (VImode) { 80959243Sobrien cs.len = 2; 81059243Sobrien cs.buf = &strA[1]; AddXkey(&cs, &arrow[A_K_UP].fun, arrow[A_K_UP].type); 81159243Sobrien cs.buf = &strB[1]; AddXkey(&cs, &arrow[A_K_DN].fun, arrow[A_K_DN].type); 81259243Sobrien cs.buf = &strC[1]; AddXkey(&cs, &arrow[A_K_RT].fun, arrow[A_K_RT].type); 81359243Sobrien cs.buf = &strD[1]; AddXkey(&cs, &arrow[A_K_LT].fun, arrow[A_K_LT].type); 81469408Sache cs.buf = &strH[1]; AddXkey(&cs, &arrow[A_K_HO].fun, arrow[A_K_HO].type); 81569408Sache cs.buf = &strF[1]; AddXkey(&cs, &arrow[A_K_EN].fun, arrow[A_K_EN].type); 81659243Sobrien cs.buf = &stOA[1]; AddXkey(&cs, &arrow[A_K_UP].fun, arrow[A_K_UP].type); 81759243Sobrien cs.buf = &stOB[1]; AddXkey(&cs, &arrow[A_K_DN].fun, arrow[A_K_DN].type); 81859243Sobrien cs.buf = &stOC[1]; AddXkey(&cs, &arrow[A_K_RT].fun, arrow[A_K_RT].type); 81959243Sobrien cs.buf = &stOD[1]; AddXkey(&cs, &arrow[A_K_LT].fun, arrow[A_K_LT].type); 82069408Sache cs.buf = &stOH[1]; AddXkey(&cs, &arrow[A_K_HO].fun, arrow[A_K_HO].type); 82169408Sache cs.buf = &stOF[1]; AddXkey(&cs, &arrow[A_K_EN].fun, arrow[A_K_EN].type); 82259243Sobrien } 82359243Sobrien} 82459243Sobrien 82559243Sobrien 82659243Sobrienint 827167465SmpSetArrowKeys(const CStr *name, XmapVal *fun, int type) 82859243Sobrien{ 82959243Sobrien int i; 83069408Sache for (i = 0; i < A_K_NKEYS; i++) 83159243Sobrien if (Strcmp(name->buf, arrow[i].name) == 0) { 83259243Sobrien arrow[i].fun = *fun; 83359243Sobrien arrow[i].type = type; 83459243Sobrien return 0; 83559243Sobrien } 83659243Sobrien return -1; 83759243Sobrien} 83859243Sobrien 83959243Sobrienint 840167465SmpIsArrowKey(Char *name) 84159243Sobrien{ 84259243Sobrien int i; 84369408Sache for (i = 0; i < A_K_NKEYS; i++) 84459243Sobrien if (Strcmp(name, arrow[i].name) == 0) 84559243Sobrien return 1; 84659243Sobrien return 0; 84759243Sobrien} 84859243Sobrien 84959243Sobrienint 850167465SmpClearArrowKeys(const CStr *name) 85159243Sobrien{ 85259243Sobrien int i; 85369408Sache for (i = 0; i < A_K_NKEYS; i++) 85459243Sobrien if (Strcmp(name->buf, arrow[i].name) == 0) { 85559243Sobrien arrow[i].type = XK_NOD; 85659243Sobrien return 0; 85759243Sobrien } 85859243Sobrien return -1; 85959243Sobrien} 86059243Sobrien 86159243Sobrienvoid 862167465SmpPrintArrowKeys(const CStr *name) 86359243Sobrien{ 86459243Sobrien int i; 86559243Sobrien 86669408Sache for (i = 0; i < A_K_NKEYS; i++) 86759243Sobrien if (name->len == 0 || Strcmp(name->buf, arrow[i].name) == 0) 868167465Smp if (arrow[i].type != XK_NOD) 869167465Smp printOne(arrow[i].name, &arrow[i].fun, arrow[i].type); 87059243Sobrien} 87159243Sobrien 87259243Sobrien 87359243Sobrienvoid 874167465SmpBindArrowKeys(void) 87559243Sobrien{ 87659243Sobrien KEYCMD *map, *dmap; 87759243Sobrien int i, j; 87859243Sobrien char *p; 87959243Sobrien CStr cs; 88059243Sobrien 88159243Sobrien if (!GotTermCaps) 88259243Sobrien return; 88359243Sobrien map = VImode ? CcAltMap : CcKeyMap; 88459243Sobrien dmap = VImode ? CcViCmdMap : CcEmacsMap; 88559243Sobrien 88659243Sobrien DefaultArrowKeys(); 88759243Sobrien 88869408Sache for (i = 0; i < A_K_NKEYS; i++) { 88959243Sobrien p = tstr[arrow[i].key].str; 89059243Sobrien if (p && *p) { 89159243Sobrien j = (unsigned char) *p; 89259243Sobrien cs.buf = str2short(p); 89359243Sobrien cs.len = Strlen(cs.buf); 89459243Sobrien /* 89559243Sobrien * Assign the arrow keys only if: 89659243Sobrien * 89759243Sobrien * 1. They are multi-character arrow keys and the user 89859243Sobrien * has not re-assigned the leading character, or 89959243Sobrien * has re-assigned the leading character to be F_XKEY 90059243Sobrien * 2. They are single arrow keys pointing to an unassigned key. 90159243Sobrien */ 90259243Sobrien if (arrow[i].type == XK_NOD) { 90359243Sobrien ClearXkey(map, &cs); 90459243Sobrien } 90559243Sobrien else { 90659243Sobrien if (p[1] && (dmap[j] == map[j] || map[j] == F_XKEY)) { 90759243Sobrien AddXkey(&cs, &arrow[i].fun, arrow[i].type); 90859243Sobrien map[j] = F_XKEY; 90959243Sobrien } 91059243Sobrien else if (map[j] == F_UNASSIGNED) { 91159243Sobrien ClearXkey(map, &cs); 91259243Sobrien if (arrow[i].type == XK_CMD) 91359243Sobrien map[j] = arrow[i].fun.cmd; 91459243Sobrien else 91559243Sobrien AddXkey(&cs, &arrow[i].fun, arrow[i].type); 91659243Sobrien } 91759243Sobrien } 91859243Sobrien } 91959243Sobrien } 92059243Sobrien} 92159243Sobrien 92259243Sobrienstatic Char cur_atr = 0; /* current attributes */ 92359243Sobrien 92459243Sobrienvoid 925167465SmpSetAttributes(Char atr) 92659243Sobrien{ 92759243Sobrien atr &= ATTRIBUTES; 92859243Sobrien if (atr != cur_atr) { 92959243Sobrien if (me_all && GoodStr(T_me)) { 93059243Sobrien if (((cur_atr & BOLD) && !(atr & BOLD)) || 93159243Sobrien ((cur_atr & UNDER) && !(atr & UNDER)) || 93259243Sobrien ((cur_atr & STANDOUT) && !(atr & STANDOUT))) { 93359243Sobrien (void) tputs(Str(T_me), 1, PUTPURE); 93459243Sobrien cur_atr = 0; 93559243Sobrien } 93659243Sobrien } 93759243Sobrien if ((atr & BOLD) != (cur_atr & BOLD)) { 93859243Sobrien if (atr & BOLD) { 93959243Sobrien if (GoodStr(T_md) && GoodStr(T_me)) { 94059243Sobrien (void) tputs(Str(T_md), 1, PUTPURE); 94159243Sobrien cur_atr |= BOLD; 94259243Sobrien } 94359243Sobrien } 94459243Sobrien else { 94559243Sobrien if (GoodStr(T_md) && GoodStr(T_me)) { 94659243Sobrien (void) tputs(Str(T_me), 1, PUTPURE); 94759243Sobrien if ((cur_atr & STANDOUT) && GoodStr(T_se)) { 94859243Sobrien (void) tputs(Str(T_se), 1, PUTPURE); 94959243Sobrien cur_atr &= ~STANDOUT; 95059243Sobrien } 95159243Sobrien if ((cur_atr & UNDER) && GoodStr(T_ue)) { 95259243Sobrien (void) tputs(Str(T_ue), 1, PUTPURE); 95359243Sobrien cur_atr &= ~UNDER; 95459243Sobrien } 95559243Sobrien cur_atr &= ~BOLD; 95659243Sobrien } 95759243Sobrien } 95859243Sobrien } 95959243Sobrien if ((atr & STANDOUT) != (cur_atr & STANDOUT)) { 96059243Sobrien if (atr & STANDOUT) { 96159243Sobrien if (GoodStr(T_so) && GoodStr(T_se)) { 96259243Sobrien (void) tputs(Str(T_so), 1, PUTPURE); 96359243Sobrien cur_atr |= STANDOUT; 96459243Sobrien } 96559243Sobrien } 96659243Sobrien else { 96759243Sobrien if (GoodStr(T_se)) { 96859243Sobrien (void) tputs(Str(T_se), 1, PUTPURE); 96959243Sobrien cur_atr &= ~STANDOUT; 97059243Sobrien } 97159243Sobrien } 97259243Sobrien } 97359243Sobrien if ((atr & UNDER) != (cur_atr & UNDER)) { 97459243Sobrien if (atr & UNDER) { 97559243Sobrien if (GoodStr(T_us) && GoodStr(T_ue)) { 97659243Sobrien (void) tputs(Str(T_us), 1, PUTPURE); 97759243Sobrien cur_atr |= UNDER; 97859243Sobrien } 97959243Sobrien } 98059243Sobrien else { 98159243Sobrien if (GoodStr(T_ue)) { 98259243Sobrien (void) tputs(Str(T_ue), 1, PUTPURE); 98359243Sobrien cur_atr &= ~UNDER; 98459243Sobrien } 98559243Sobrien } 98659243Sobrien } 98759243Sobrien } 98859243Sobrien} 98959243Sobrien 990167465Smpint highlighting = 0; 991167465Smp 992167465Smpvoid 993316957SdchaginStartHighlight(void) 994167465Smp{ 995167465Smp (void) tputs(Str(T_mr), 1, PUTPURE); 996167465Smp highlighting = 1; 997167465Smp} 998167465Smp 999167465Smpvoid 1000316957SdchaginStopHighlight(void) 1001167465Smp{ 1002167465Smp (void) tputs(Str(T_me), 1, PUTPURE); 1003167465Smp highlighting = 0; 1004167465Smp} 1005167465Smp 100659243Sobrien/* PWP 6-27-88 -- if the tty driver thinks that we can tab, we ask termcap */ 100759243Sobrienint 1008167465SmpCanWeTab(void) 100959243Sobrien{ 101059243Sobrien return (Val(T_pt)); 101159243Sobrien} 101259243Sobrien 1013167465Smp/* move to line <where> (first line == 0) as efficiently as possible; */ 101459243Sobrienvoid 1015167465SmpMoveToLine(int where) 101659243Sobrien{ 101759243Sobrien int del; 101859243Sobrien 101959243Sobrien if (where == CursorV) 102059243Sobrien return; 102159243Sobrien 102259243Sobrien if (where > TermV) { 102359243Sobrien#ifdef DEBUG_SCREEN 102459243Sobrien xprintf("MoveToLine: where is ridiculous: %d\r\n", where); 102559243Sobrien flush(); 102659243Sobrien#endif /* DEBUG_SCREEN */ 102759243Sobrien return; 102859243Sobrien } 102959243Sobrien 103059243Sobrien del = where - CursorV; 103159243Sobrien 103259243Sobrien if (del > 0) { 103359243Sobrien while (del > 0) { 103459243Sobrien if ((T_Margin & MARGIN_AUTO) && Display[CursorV][0] != '\0') { 1035145479Smp size_t h; 1036145479Smp 1037145479Smp for (h = TermH - 1; h > 0 && Display[CursorV][h] == CHAR_DBWIDTH; 1038145479Smp h--) 1039145479Smp ; 104059243Sobrien /* move without newline */ 1041145479Smp MoveToChar(h); 1042145479Smp so_write(&Display[CursorV][CursorH], TermH - CursorH); /* updates CursorH/V*/ 104359243Sobrien del--; 104459243Sobrien } 104559243Sobrien else { 104659243Sobrien if ((del > 1) && GoodStr(T_DO)) { 104759243Sobrien (void) tputs(tgoto(Str(T_DO), del, del), del, PUTPURE); 104859243Sobrien del = 0; 104959243Sobrien } 105059243Sobrien else { 105159243Sobrien for ( ; del > 0; del--) 105259243Sobrien (void) putraw('\n'); 105359243Sobrien CursorH = 0; /* because the \n will become \r\n */ 105459243Sobrien } 105559243Sobrien } 105659243Sobrien } 105759243Sobrien } 105859243Sobrien else { /* del < 0 */ 105959243Sobrien if (GoodStr(T_UP) && (-del > 1 || !GoodStr(T_up))) 106059243Sobrien (void) tputs(tgoto(Str(T_UP), -del, -del), -del, PUTPURE); 106159243Sobrien else { 106259243Sobrien int i; 106359243Sobrien if (GoodStr(T_up)) 106459243Sobrien for (i = 0; i < -del; i++) 106559243Sobrien (void) tputs(Str(T_up), 1, PUTPURE); 106659243Sobrien } 106759243Sobrien } 106859243Sobrien CursorV = where; /* now where is here */ 106959243Sobrien} 107059243Sobrien 107159243Sobrienvoid 1072167465SmpMoveToChar(int where) /* move to character position (where) */ 107359243Sobrien{ /* as efficiently as possible */ 107459243Sobrien int del; 107559243Sobrien 107659243Sobrienmc_again: 107759243Sobrien if (where == CursorH) 107859243Sobrien return; 107959243Sobrien 108059243Sobrien if (where >= TermH) { 108159243Sobrien#ifdef DEBUG_SCREEN 108259243Sobrien xprintf("MoveToChar: where is riduculous: %d\r\n", where); 108359243Sobrien flush(); 108459243Sobrien#endif /* DEBUG_SCREEN */ 108559243Sobrien return; 108659243Sobrien } 108759243Sobrien 108859243Sobrien if (!where) { /* if where is first column */ 108959243Sobrien (void) putraw('\r'); /* do a CR */ 109059243Sobrien CursorH = 0; 109159243Sobrien return; 109259243Sobrien } 109359243Sobrien 109459243Sobrien del = where - CursorH; 109559243Sobrien 109659243Sobrien if ((del < -4 || del > 4) && GoodStr(T_ch)) 109759243Sobrien /* go there directly */ 109859243Sobrien (void) tputs(tgoto(Str(T_ch), where, where), where, PUTPURE); 109959243Sobrien else { 110059243Sobrien int i; 110159243Sobrien if (del > 0) { /* moving forward */ 110259243Sobrien if ((del > 4) && GoodStr(T_RI)) 110359243Sobrien (void) tputs(tgoto(Str(T_RI), del, del), del, PUTPURE); 110459243Sobrien else { 110569408Sache /* if I can do tabs, use them */ 1106145479Smp if (T_Tabs) { 1107145479Smp if ((CursorH & 0370) != (where & ~0x7) 1108145479Smp && Display[CursorV][where & ~0x7] != CHAR_DBWIDTH) { 110959243Sobrien /* if not within tab stop */ 1110145479Smp for (i = (CursorH & 0370); i < (where & ~0x7); i += 8) 111159243Sobrien (void) putraw('\t'); /* then tab over */ 1112145479Smp CursorH = where & ~0x7; 111359243Sobrien /* Note: considering that we often want to go to 111459243Sobrien TermH - 1 for the wrapping, it would be nice to 111559243Sobrien optimize this case by tabbing to the last column 111659243Sobrien - but this doesn't work for all terminals! */ 111759243Sobrien } 111859243Sobrien } 111959243Sobrien /* it's usually cheaper to just write the chars, so we do. */ 112059243Sobrien 112159243Sobrien /* NOTE THAT so_write() WILL CHANGE CursorH!!! */ 112259243Sobrien so_write(&Display[CursorV][CursorH], where - CursorH); 112359243Sobrien 112459243Sobrien } 112559243Sobrien } 112659243Sobrien else { /* del < 0 := moving backward */ 112759243Sobrien if ((-del > 4) && GoodStr(T_LE)) 112859243Sobrien (void) tputs(tgoto(Str(T_LE), -del, -del), -del, PUTPURE); 112959243Sobrien else { /* can't go directly there */ 113059243Sobrien /* if the "cost" is greater than the "cost" from col 0 */ 113159243Sobrien if (T_Tabs ? (-del > ((where >> 3) + (where & 07))) 113259243Sobrien : (-del > where)) { 113359243Sobrien (void) putraw('\r'); /* do a CR */ 113459243Sobrien CursorH = 0; 113559243Sobrien goto mc_again; /* and try again */ 113659243Sobrien } 113759243Sobrien for (i = 0; i < -del; i++) 113859243Sobrien (void) putraw('\b'); 113959243Sobrien } 114059243Sobrien } 114159243Sobrien } 114259243Sobrien CursorH = where; /* now where is here */ 114359243Sobrien} 114459243Sobrien 114559243Sobrienvoid 1146167465Smpso_write(Char *cp, int n) 114759243Sobrien{ 1148167465Smp int cur_pos, prompt_len = 0, region_start = 0, region_end = 0; 1149167465Smp 115059243Sobrien if (n <= 0) 115159243Sobrien return; /* catch bugs */ 115259243Sobrien 115359243Sobrien if (n > TermH) { 115459243Sobrien#ifdef DEBUG_SCREEN 115559243Sobrien xprintf("so_write: n is riduculous: %d\r\n", n); 115659243Sobrien flush(); 115759243Sobrien#endif /* DEBUG_SCREEN */ 115859243Sobrien return; 115959243Sobrien } 116059243Sobrien 1161167465Smp if (adrof(STRhighlight)) { 1162167465Smp /* find length of prompt */ 1163167465Smp Char *promptc; 1164167465Smp for (promptc = Prompt; *promptc; promptc++); 1165167465Smp prompt_len = promptc - Prompt; 1166167465Smp 1167167465Smp /* find region start and end points */ 1168167465Smp if (IncMatchLen) { 1169167465Smp region_start = (Cursor - InputBuf) + prompt_len; 1170167465Smp region_end = region_start + IncMatchLen; 1171167465Smp } else if (MarkIsSet) { 1172167465Smp region_start = (min(Cursor, Mark) - InputBuf) + prompt_len; 1173167465Smp region_end = (max(Cursor, Mark) - InputBuf) + prompt_len; 1174167465Smp } 1175167465Smp } 1176167465Smp 117759243Sobrien do { 1178167465Smp if (adrof(STRhighlight)) { 1179167465Smp cur_pos = CursorV * TermH + CursorH; 1180167465Smp if (!highlighting && 1181167465Smp cur_pos >= region_start && cur_pos < region_end) 1182167465Smp StartHighlight(); 1183167465Smp else if (highlighting && cur_pos >= region_end) 1184167465Smp StopHighlight(); 1185167465Smp 1186167465Smp /* don't highlight over the cursor. the highlighting's reverse 1187167465Smp * video would cancel it out. :P */ 1188167465Smp if (highlighting && cur_pos == (Cursor - InputBuf) + prompt_len) 1189167465Smp StopHighlight(); 1190167465Smp } 1191167465Smp 1192145479Smp if (*cp != CHAR_DBWIDTH) { 1193145479Smp if (*cp & LITERAL) { 1194145479Smp Char *d; 119559243Sobrien#ifdef DEBUG_LITERAL 1196145479Smp xprintf("so: litnum %d\r\n", (int)(*cp & ~LITERAL)); 119759243Sobrien#endif /* DEBUG_LITERAL */ 1198145479Smp for (d = litptr + (*cp & ~LITERAL) * LIT_FACTOR; *d; d++) 1199145479Smp (void) putwraw(*d); 1200145479Smp } 1201145479Smp else 1202145479Smp (void) putwraw(*cp); 120359243Sobrien } 1204145479Smp cp++; 120559243Sobrien CursorH++; 120659243Sobrien } while (--n); 120759243Sobrien 1208167465Smp if (adrof(STRhighlight) && highlighting) 1209167465Smp StopHighlight(); 1210167465Smp 121159243Sobrien if (CursorH >= TermH) { /* wrap? */ 121259243Sobrien if (T_Margin & MARGIN_AUTO) { /* yes */ 121359243Sobrien CursorH = 0; 121459243Sobrien CursorV++; 121559243Sobrien if (T_Margin & MARGIN_MAGIC) { 121659243Sobrien /* force the wrap to avoid the "magic" situation */ 1217167465Smp Char xc; 1218167465Smp if ((xc = Display[CursorV][CursorH]) != '\0') { 1219167465Smp so_write(&xc, 1); 1220145479Smp while(Display[CursorV][CursorH] == CHAR_DBWIDTH) 1221145479Smp CursorH++; 1222145479Smp } 1223145479Smp else { 122459243Sobrien (void) putraw(' '); 1225145479Smp CursorH = 1; 1226145479Smp } 122759243Sobrien } 122859243Sobrien } 122959243Sobrien else /* no wrap, but cursor stays on screen */ 123059243Sobrien CursorH = TermH - 1; 123159243Sobrien } 123259243Sobrien} 123359243Sobrien 123459243Sobrien 123559243Sobrienvoid 1236167465SmpDeleteChars(int num) /* deletes <num> characters */ 123759243Sobrien{ 123859243Sobrien if (num <= 0) 123959243Sobrien return; 124059243Sobrien 124159243Sobrien if (!T_CanDel) { 124259243Sobrien#ifdef DEBUG_EDIT 124359243Sobrien xprintf(CGETS(7, 16, "ERROR: cannot delete\r\n")); 124459243Sobrien#endif /* DEBUG_EDIT */ 124559243Sobrien flush(); 124659243Sobrien return; 124759243Sobrien } 124859243Sobrien 124959243Sobrien if (num > TermH) { 125059243Sobrien#ifdef DEBUG_SCREEN 125159243Sobrien xprintf(CGETS(7, 17, "DeleteChars: num is riduculous: %d\r\n"), num); 125259243Sobrien flush(); 125359243Sobrien#endif /* DEBUG_SCREEN */ 125459243Sobrien return; 125559243Sobrien } 125659243Sobrien 125759243Sobrien if (GoodStr(T_DC)) /* if I have multiple delete */ 125859243Sobrien if ((num > 1) || !GoodStr(T_dc)) { /* if dc would be more expen. */ 125959243Sobrien (void) tputs(tgoto(Str(T_DC), num, num), num, PUTPURE); 126059243Sobrien return; 126159243Sobrien } 126259243Sobrien 126359243Sobrien if (GoodStr(T_dm)) /* if I have delete mode */ 126459243Sobrien (void) tputs(Str(T_dm), 1, PUTPURE); 126559243Sobrien 126659243Sobrien if (GoodStr(T_dc)) /* else do one at a time */ 126759243Sobrien while (num--) 126859243Sobrien (void) tputs(Str(T_dc), 1, PUTPURE); 126959243Sobrien 127059243Sobrien if (GoodStr(T_ed)) /* if I have delete mode */ 127159243Sobrien (void) tputs(Str(T_ed), 1, PUTPURE); 127259243Sobrien} 127359243Sobrien 1274167465Smp/* Puts terminal in insert character mode, or inserts num characters in the 1275167465Smp line */ 127659243Sobrienvoid 1277167465SmpInsert_write(Char *cp, int num) 127859243Sobrien{ 127959243Sobrien if (num <= 0) 128059243Sobrien return; 128159243Sobrien if (!T_CanIns) { 128259243Sobrien#ifdef DEBUG_EDIT 128359243Sobrien xprintf(CGETS(7, 18, "ERROR: cannot insert\r\n")); 128459243Sobrien#endif /* DEBUG_EDIT */ 128559243Sobrien flush(); 128659243Sobrien return; 128759243Sobrien } 128859243Sobrien 128959243Sobrien if (num > TermH) { 129059243Sobrien#ifdef DEBUG_SCREEN 129159243Sobrien xprintf(CGETS(7, 19, "StartInsert: num is riduculous: %d\r\n"), num); 129259243Sobrien flush(); 129359243Sobrien#endif /* DEBUG_SCREEN */ 129459243Sobrien return; 129559243Sobrien } 129659243Sobrien 129759243Sobrien if (GoodStr(T_IC)) /* if I have multiple insert */ 129859243Sobrien if ((num > 1) || !GoodStr(T_ic)) { /* if ic would be more expen. */ 129959243Sobrien (void) tputs(tgoto(Str(T_IC), num, num), num, PUTPURE); 130059243Sobrien so_write(cp, num); /* this updates CursorH/V */ 130159243Sobrien return; 130259243Sobrien } 130359243Sobrien 130459243Sobrien if (GoodStr(T_im) && GoodStr(T_ei)) { /* if I have insert mode */ 130559243Sobrien (void) tputs(Str(T_im), 1, PUTPURE); 130659243Sobrien 1307145479Smp so_write(cp, num); /* this updates CursorH/V */ 130859243Sobrien 130959243Sobrien if (GoodStr(T_ip)) /* have to make num chars insert */ 131059243Sobrien (void) tputs(Str(T_ip), 1, PUTPURE); 131159243Sobrien 131259243Sobrien (void) tputs(Str(T_ei), 1, PUTPURE); 131359243Sobrien return; 131459243Sobrien } 131559243Sobrien 131659243Sobrien do { 131759243Sobrien if (GoodStr(T_ic)) /* have to make num chars insert */ 131859243Sobrien (void) tputs(Str(T_ic), 1, PUTPURE); /* insert a char */ 131959243Sobrien 1320145479Smp so_write(cp++, 1); /* this updates CursorH/V */ 132159243Sobrien 132259243Sobrien if (GoodStr(T_ip)) /* have to make num chars insert */ 132359243Sobrien (void) tputs(Str(T_ip), 1, PUTPURE);/* pad the inserted char */ 132459243Sobrien 132559243Sobrien } while (--num); 132659243Sobrien 132759243Sobrien} 132859243Sobrien 1329167465Smp/* clear to end of line. There are num characters to clear */ 133059243Sobrienvoid 1331167465SmpClearEOL(int num) 133259243Sobrien{ 1333145479Smp int i; 133459243Sobrien 133559243Sobrien if (num <= 0) 133659243Sobrien return; 133759243Sobrien 133859243Sobrien if (T_CanCEOL && GoodStr(T_ce)) 133959243Sobrien (void) tputs(Str(T_ce), 1, PUTPURE); 134059243Sobrien else { 134159243Sobrien for (i = 0; i < num; i++) 134259243Sobrien (void) putraw(' '); 134359243Sobrien CursorH += num; /* have written num spaces */ 134459243Sobrien } 134559243Sobrien} 134659243Sobrien 134759243Sobrienvoid 1348167465SmpClearScreen(void) 134959243Sobrien{ /* clear the whole screen and home */ 135059243Sobrien if (GoodStr(T_cl)) 135159243Sobrien /* send the clear screen code */ 135259243Sobrien (void) tputs(Str(T_cl), Val(T_li), PUTPURE); 135359243Sobrien else if (GoodStr(T_ho) && GoodStr(T_cd)) { 135459243Sobrien (void) tputs(Str(T_ho), Val(T_li), PUTPURE); /* home */ 135559243Sobrien /* clear to bottom of screen */ 135659243Sobrien (void) tputs(Str(T_cd), Val(T_li), PUTPURE); 135759243Sobrien } 135859243Sobrien else { 135959243Sobrien (void) putraw('\r'); 136059243Sobrien (void) putraw('\n'); 136159243Sobrien } 136259243Sobrien} 136359243Sobrien 136459243Sobrienvoid 1365167465SmpSoundBeep(void) 136659243Sobrien{ /* produce a sound */ 136759243Sobrien beep_cmd (); 136859243Sobrien if (adrof(STRnobeep)) 136959243Sobrien return; 137059243Sobrien 137159243Sobrien if (GoodStr(T_vb) && adrof(STRvisiblebell)) 137259243Sobrien (void) tputs(Str(T_vb), 1, PUTPURE); /* visible bell */ 137359243Sobrien else if (GoodStr(T_bl)) 137459243Sobrien /* what termcap says we should use */ 137559243Sobrien (void) tputs(Str(T_bl), 1, PUTPURE); 137659243Sobrien else 137759243Sobrien (void) putraw(CTL_ESC('\007')); /* an ASCII bell; ^G */ 137859243Sobrien} 137959243Sobrien 138059243Sobrienvoid 1381167465SmpClearToBottom(void) 138259243Sobrien{ /* clear to the bottom of the screen */ 138359243Sobrien if (GoodStr(T_cd)) 138459243Sobrien (void) tputs(Str(T_cd), Val(T_li), PUTPURE); 138559243Sobrien else if (GoodStr(T_ce)) 138659243Sobrien (void) tputs(Str(T_ce), Val(T_li), PUTPURE); 138759243Sobrien} 138859243Sobrien 138959243Sobrienvoid 1390167465SmpGetTermCaps(void) 139159243Sobrien{ /* read in the needed terminal capabilites */ 1392145479Smp int i; 1393145479Smp const char *ptr; 139459243Sobrien char buf[TC_BUFSIZE]; 139559243Sobrien static char bp[TC_BUFSIZE]; 139659243Sobrien char *area; 139759243Sobrien struct termcapstr *t; 139859243Sobrien 139959243Sobrien 140059243Sobrien#ifdef SIG_WINDOW 1401167465Smp sigset_t oset, set; 140259243Sobrien int lins, cols; 140359243Sobrien 140459243Sobrien /* don't want to confuse things here */ 1405167465Smp sigemptyset(&set); 1406167465Smp sigaddset(&set, SIG_WINDOW); 1407167465Smp (void)sigprocmask(SIG_BLOCK, &set, &oset); 1408167465Smp cleanup_push(&oset, sigprocmask_cleanup); 140959243Sobrien#endif /* SIG_WINDOW */ 141059243Sobrien area = buf; 141159243Sobrien 141259243Sobrien GotTermCaps = 1; 141359243Sobrien 141459243Sobrien setname("gettermcaps"); 141559243Sobrien ptr = getenv("TERM"); 141659243Sobrien 141759243Sobrien#ifdef apollo 141859243Sobrien /* 141959243Sobrien * If we are on a pad, we pretend that we are dumb. Otherwise the termcap 142059243Sobrien * library will put us in a weird screen mode, thinking that we are going 142159243Sobrien * to use curses 142259243Sobrien */ 142359243Sobrien if (isapad()) 142459243Sobrien ptr = "dumb"; 142559243Sobrien#endif /* apollo */ 142659243Sobrien 142759243Sobrien if (!ptr || !ptr[0] || !strcmp(ptr, "wm") || !strcmp(ptr,"dmx")) 142859243Sobrien ptr = "dumb"; 142959243Sobrien 143059243Sobrien setzero(bp, TC_BUFSIZE); 143159243Sobrien 143259243Sobrien i = tgetent(bp, ptr); 143359243Sobrien if (i <= 0) { 143459243Sobrien if (i == -1) { 143559243Sobrien#if (SYSVREL == 0) || defined(IRIS3D) 1436316957Sdchagin xprintf(CGETS(7, 20, 1437316957Sdchagin "%s: The terminal database could not be opened.\n"), progname); 143859243Sobrien } 143959243Sobrien else if (i == 0) { 144059243Sobrien#endif /* SYSVREL */ 144159243Sobrien xprintf(CGETS(7, 21, 144259243Sobrien "%s: No entry for terminal type \"%s\"\n"), progname, 144359243Sobrien getenv("TERM")); 144459243Sobrien } 144559243Sobrien xprintf(CGETS(7, 22, "%s: using dumb terminal settings.\n"), progname); 144659243Sobrien Val(T_co) = 80; /* do a dumb terminal */ 144759243Sobrien Val(T_pt) = Val(T_km) = Val(T_li) = 0; 144859243Sobrien for (t = tstr; t->name != NULL; t++) 1449167465Smp TCset(t, NULL); 145059243Sobrien } 145159243Sobrien else { 145259243Sobrien /* Can we tab */ 145359243Sobrien Val(T_pt) = tgetflag("pt") && !tgetflag("xt"); 145459243Sobrien /* do we have a meta? */ 145559243Sobrien Val(T_km) = (tgetflag("km") || tgetflag("MT")); 145659243Sobrien Val(T_am) = tgetflag("am"); 145759243Sobrien Val(T_xn) = tgetflag("xn"); 145859243Sobrien Val(T_co) = tgetnum("co"); 145959243Sobrien Val(T_li) = tgetnum("li"); 146059243Sobrien for (t = tstr; t->name != NULL; t++) 1461167465Smp TCset(t, tgetstr(t->name, &area)); 146259243Sobrien } 146359243Sobrien if (Val(T_co) < 2) 146459243Sobrien Val(T_co) = 80; /* just in case */ 146559243Sobrien if (Val(T_li) < 1) 146659243Sobrien Val(T_li) = 24; 146759243Sobrien 146859243Sobrien T_Cols = (Char) Val(T_co); 146959243Sobrien T_Lines = (Char) Val(T_li); 147059243Sobrien if (T_Tabs) 1471167465Smp T_Tabs = Val(T_pt); 1472167465Smp T_HasMeta = Val(T_km); 1473167465Smp T_Margin = Val(T_am) ? MARGIN_AUTO : 0; 1474167465Smp T_Margin |= Val(T_xn) ? MARGIN_MAGIC : 0; 147559243Sobrien T_CanCEOL = GoodStr(T_ce); 147659243Sobrien T_CanDel = GoodStr(T_dc) || GoodStr(T_DC); 147759243Sobrien T_CanIns = GoodStr(T_im) || GoodStr(T_ic) || GoodStr(T_IC); 147859243Sobrien T_CanUP = GoodStr(T_up) || GoodStr(T_UP); 147959243Sobrien if (GoodStr(T_me) && GoodStr(T_ue)) 148059243Sobrien me_all = (strcmp(Str(T_me), Str(T_ue)) == 0); 148159243Sobrien else 148259243Sobrien me_all = 0; 148359243Sobrien if (GoodStr(T_me) && GoodStr(T_se)) 148459243Sobrien me_all |= (strcmp(Str(T_me), Str(T_se)) == 0); 148559243Sobrien 148659243Sobrien 148759243Sobrien#ifdef DEBUG_SCREEN 148859243Sobrien if (!T_CanUP) { 148959243Sobrien xprintf(CGETS(7, 23, "%s: WARNING: Your terminal cannot move up.\n", 149059243Sobrien progname)); 149159243Sobrien xprintf(CGETS(7, 24, "Editing may be odd for long lines.\n")); 149259243Sobrien } 149359243Sobrien if (!T_CanCEOL) 149459243Sobrien xprintf(CGETS(7, 25, "no clear EOL capability.\n")); 149559243Sobrien if (!T_CanDel) 149659243Sobrien xprintf(CGETS(7, 26, "no delete char capability.\n")); 149759243Sobrien if (!T_CanIns) 149859243Sobrien xprintf(CGETS(7, 27, "no insert char capability.\n")); 149959243Sobrien#endif /* DEBUG_SCREEN */ 150059243Sobrien 150159243Sobrien 150259243Sobrien 150359243Sobrien#ifdef SIG_WINDOW 150459243Sobrien (void) GetSize(&lins, &cols); /* get the correct window size */ 150559243Sobrien ChangeSize(lins, cols); 150659243Sobrien 1507167465Smp cleanup_until(&oset); /* can change it again */ 150859243Sobrien#else /* SIG_WINDOW */ 150959243Sobrien ChangeSize(Val(T_li), Val(T_co)); 151059243Sobrien#endif /* SIG_WINDOW */ 151159243Sobrien 151259243Sobrien BindArrowKeys(); 151359243Sobrien} 151459243Sobrien 151559243Sobrien#ifdef SIG_WINDOW 151659243Sobrien/* GetSize(): 151759243Sobrien * Return the new window size in lines and cols, and 151859243Sobrien * true if the size was changed. This can fail if SHIN 151959243Sobrien * is not a tty, but it will work in most cases. 152059243Sobrien */ 152159243Sobrienint 1522167465SmpGetSize(int *lins, int *cols) 152359243Sobrien{ 152459243Sobrien *cols = Val(T_co); 152559243Sobrien *lins = Val(T_li); 152659243Sobrien 152759243Sobrien#ifdef TIOCGWINSZ 152859243Sobrien# define KNOWsize 152959243Sobrien# ifndef lint 153059243Sobrien { 153159243Sobrien struct winsize ws; /* from 4.3 */ 153259243Sobrien 153359243Sobrien if (ioctl(SHIN, TIOCGWINSZ, (ioctl_t) &ws) != -1) { 153459243Sobrien if (ws.ws_col) 153559243Sobrien *cols = ws.ws_col; 153659243Sobrien if (ws.ws_row) 153759243Sobrien *lins = ws.ws_row; 153859243Sobrien } 153959243Sobrien } 154059243Sobrien# endif /* !lint */ 154159243Sobrien#else /* TIOCGWINSZ */ 154259243Sobrien# ifdef TIOCGSIZE 154359243Sobrien# define KNOWsize 154459243Sobrien { 154559243Sobrien struct ttysize ts; /* from Sun */ 154659243Sobrien 154759243Sobrien if (ioctl(SHIN, TIOCGSIZE, (ioctl_t) &ts) != -1) { 154859243Sobrien if (ts.ts_cols) 154959243Sobrien *cols = ts.ts_cols; 155059243Sobrien if (ts.ts_lines) 155159243Sobrien *lins = ts.ts_lines; 155259243Sobrien } 155359243Sobrien } 155459243Sobrien# endif /* TIOCGSIZE */ 155559243Sobrien#endif /* TIOCGWINSZ */ 155659243Sobrien 155759243Sobrien return (Val(T_co) != *cols || Val(T_li) != *lins); 155859243Sobrien} 155959243Sobrien 1560167465Smp#endif /* SIG_WINDOW */ 156159243Sobrien 1562231990Smp#ifdef KNOWsize 1563316957Sdchaginstatic int 1564231990SmpUpdateVal(const Char *tag, int value, Char *termcap, Char *backup) 1565231990Smp{ 1566231990Smp Char *ptr, *p; 1567231990Smp if ((ptr = Strstr(termcap, tag)) == NULL) { 1568231990Smp (void)Strcpy(backup, termcap); 1569316957Sdchagin return 0; 1570231990Smp } else { 1571231990Smp size_t len = (ptr - termcap) + Strlen(tag); 1572231990Smp (void)Strncpy(backup, termcap, len); 1573231990Smp backup[len] = '\0'; 1574231990Smp p = Itoa(value, 0, 0); 1575231990Smp (void) Strcat(backup + len, p); 1576231990Smp xfree(p); 1577231990Smp ptr = Strchr(ptr, ':'); 1578231990Smp if (ptr) 1579231990Smp (void) Strcat(backup, ptr); 1580316957Sdchagin return 1; 1581231990Smp } 1582231990Smp} 1583231990Smp#endif 1584231990Smp 158559243Sobrienvoid 1586167465SmpChangeSize(int lins, int cols) 158759243Sobrien{ 158859243Sobrien /* 158959243Sobrien * Just in case 159059243Sobrien */ 159159243Sobrien Val(T_co) = (cols < 2) ? 80 : cols; 159259243Sobrien Val(T_li) = (lins < 1) ? 24 : lins; 159359243Sobrien 159459243Sobrien#ifdef KNOWsize 159559243Sobrien /* 159659243Sobrien * We want to affect the environment only when we have a valid 159759243Sobrien * setup, not when we get bad settings. Consider the following scenario: 159859243Sobrien * We just logged in, and we have not initialized the editor yet. 159959243Sobrien * We reset termcap with tset, and not $TERMCAP has the right 160059243Sobrien * terminal size. But since the editor is not initialized yet, and 160159243Sobrien * the kernel's notion of the terminal size might be wrong we arrive 160259243Sobrien * here with lines = columns = 0. If we reset the environment we lose 160359243Sobrien * our only chance to get the window size right. 160459243Sobrien */ 160559243Sobrien if (Val(T_co) == cols && Val(T_li) == lins) { 1606167465Smp Char *p; 160759243Sobrien char *tptr; 160859243Sobrien 160959243Sobrien if (getenv("COLUMNS")) { 1610167465Smp p = Itoa(Val(T_co), 0, 0); 1611167465Smp cleanup_push(p, xfree); 1612167465Smp tsetenv(STRCOLUMNS, p); 1613167465Smp cleanup_until(p); 161459243Sobrien } 161559243Sobrien 161659243Sobrien if (getenv("LINES")) { 1617167465Smp p = Itoa(Val(T_li), 0, 0); 1618167465Smp cleanup_push(p, xfree); 1619167465Smp tsetenv(STRLINES, p); 1620167465Smp cleanup_until(p); 162159243Sobrien } 162259243Sobrien 162359243Sobrien if ((tptr = getenv("TERMCAP")) != NULL) { 162459243Sobrien /* Leave 64 characters slop in case we enlarge the termcap string */ 1625167465Smp Char termcap[TC_BUFSIZE+64], backup[TC_BUFSIZE+64], *ptr; 1626316957Sdchagin int changed; 162759243Sobrien 162859243Sobrien ptr = str2short(tptr); 1629167465Smp (void) Strncpy(termcap, ptr, TC_BUFSIZE); 1630167465Smp termcap[TC_BUFSIZE-1] = '\0'; 163159243Sobrien 1632316957Sdchagin changed = UpdateVal(STRco, Val(T_co), termcap, backup); 1633316957Sdchagin changed |= UpdateVal(STRli, Val(T_li), termcap, backup); 163459243Sobrien 1635316957Sdchagin if (changed) { 1636316957Sdchagin /* 1637316957Sdchagin * Chop the termcap string at TC_BUFSIZE-1 characters to avoid 1638316957Sdchagin * core-dumps in the termcap routines 1639316957Sdchagin */ 1640316957Sdchagin termcap[TC_BUFSIZE - 1] = '\0'; 1641316957Sdchagin tsetenv(STRTERMCAP, termcap); 1642316957Sdchagin } 164359243Sobrien } 164459243Sobrien } 164559243Sobrien#endif /* KNOWsize */ 164659243Sobrien 164759243Sobrien ReBufferDisplay(); /* re-make display buffers */ 164859243Sobrien ClearDisp(); 164959243Sobrien} 1650