1232633Smp/* $Header: /p/tcsh/cvsroot/tcsh/ed.screen.c,v 3.78 2011/02/27 00:14:38 christos Exp $ */ 259243Sobrien/* 359243Sobrien * ed.screen.c: Editor/termcap-curses interface 459243Sobrien */ 559243Sobrien/*- 659243Sobrien * Copyright (c) 1980, 1991 The Regents of the University of California. 759243Sobrien * All rights reserved. 859243Sobrien * 959243Sobrien * Redistribution and use in source and binary forms, with or without 1059243Sobrien * modification, are permitted provided that the following conditions 1159243Sobrien * are met: 1259243Sobrien * 1. Redistributions of source code must retain the above copyright 1359243Sobrien * notice, this list of conditions and the following disclaimer. 1459243Sobrien * 2. Redistributions in binary form must reproduce the above copyright 1559243Sobrien * notice, this list of conditions and the following disclaimer in the 1659243Sobrien * documentation and/or other materials provided with the distribution. 17100616Smp * 3. Neither the name of the University nor the names of its contributors 1859243Sobrien * may be used to endorse or promote products derived from this software 1959243Sobrien * without specific prior written permission. 2059243Sobrien * 2159243Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 2259243Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2359243Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2459243Sobrien * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2559243Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2659243Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2759243Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2859243Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2959243Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 3059243Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 3159243Sobrien * SUCH DAMAGE. 3259243Sobrien */ 3359243Sobrien#include "sh.h" 3459243Sobrien 35232633SmpRCSID("$tcsh: ed.screen.c,v 3.78 2011/02/27 00:14:38 christos Exp $") 3659243Sobrien 3759243Sobrien#include "ed.h" 3859243Sobrien#include "tc.h" 3959243Sobrien#include "ed.defns.h" 4059243Sobrien 4159243Sobrien/* #define DEBUG_LITERAL */ 4259243Sobrien 4359243Sobrien/* 4459243Sobrien * IMPORTANT NOTE: these routines are allowed to look at the current screen 4559243Sobrien * and the current possition assuming that it is correct. If this is not 4659243Sobrien * true, then the update will be WRONG! This is (should be) a valid 4759243Sobrien * assumption... 4859243Sobrien */ 4959243Sobrien 5059243Sobrien#define TC_BUFSIZE 2048 5159243Sobrien 5259243Sobrien#define GoodStr(a) (tstr[a].str != NULL && tstr[a].str[0] != '\0') 5359243Sobrien#define Str(a) tstr[a].str 5459243Sobrien#define Val(a) tval[a].val 5559243Sobrien 56167465Smpstatic const struct { 57145479Smp const char *b_name; 58145479Smp speed_t b_rate; 5959243Sobrien} baud_rate[] = { 6059243Sobrien 6159243Sobrien#ifdef B0 6259243Sobrien { "0", B0 }, 6359243Sobrien#endif 6459243Sobrien#ifdef B50 6559243Sobrien { "50", B50 }, 6659243Sobrien#endif 6759243Sobrien#ifdef B75 6859243Sobrien { "75", B75 }, 6959243Sobrien#endif 7059243Sobrien#ifdef B110 7159243Sobrien { "110", B110 }, 7259243Sobrien#endif 7359243Sobrien#ifdef B134 7459243Sobrien { "134", B134 }, 7559243Sobrien#endif 7659243Sobrien#ifdef B150 7759243Sobrien { "150", B150 }, 7859243Sobrien#endif 7959243Sobrien#ifdef B200 8059243Sobrien { "200", B200 }, 8159243Sobrien#endif 8259243Sobrien#ifdef B300 8359243Sobrien { "300", B300 }, 8459243Sobrien#endif 8559243Sobrien#ifdef B600 8659243Sobrien { "600", B600 }, 8759243Sobrien#endif 8859243Sobrien#ifdef B900 8959243Sobrien { "900", B900 }, 9059243Sobrien#endif 9159243Sobrien#ifdef B1200 9259243Sobrien { "1200", B1200 }, 9359243Sobrien#endif 9459243Sobrien#ifdef B1800 9559243Sobrien { "1800", B1800 }, 9659243Sobrien#endif 9759243Sobrien#ifdef B2400 9859243Sobrien { "2400", B2400 }, 9959243Sobrien#endif 10059243Sobrien#ifdef B3600 10159243Sobrien { "3600", B3600 }, 10259243Sobrien#endif 10359243Sobrien#ifdef B4800 10459243Sobrien { "4800", B4800 }, 10559243Sobrien#endif 10659243Sobrien#ifdef B7200 10759243Sobrien { "7200", B7200 }, 10859243Sobrien#endif 10959243Sobrien#ifdef B9600 11059243Sobrien { "9600", B9600 }, 11159243Sobrien#endif 11259243Sobrien#ifdef EXTA 11359243Sobrien { "19200", EXTA }, 11459243Sobrien#endif 11559243Sobrien#ifdef B19200 11659243Sobrien { "19200", B19200 }, 11759243Sobrien#endif 11859243Sobrien#ifdef EXTB 11959243Sobrien { "38400", EXTB }, 12059243Sobrien#endif 12159243Sobrien#ifdef B38400 12259243Sobrien { "38400", B38400 }, 12359243Sobrien#endif 12459243Sobrien { NULL, 0 } 12559243Sobrien}; 12659243Sobrien 127167465Smp#define T_at7 0 128167465Smp#define T_al 1 129167465Smp#define T_bl 2 130167465Smp#define T_cd 3 131167465Smp#define T_ce 4 132167465Smp#define T_ch 5 133167465Smp#define T_cl 6 134167465Smp#define T_dc 7 135167465Smp#define T_dl 8 136167465Smp#define T_dm 9 137167465Smp#define T_ed 10 138167465Smp#define T_ei 11 139167465Smp#define T_fs 12 140167465Smp#define T_ho 13 141167465Smp#define T_ic 14 142167465Smp#define T_im 15 143167465Smp#define T_ip 16 144167465Smp#define T_kd 17 145167465Smp#define T_kh 18 146167465Smp#define T_kl 19 147167465Smp#define T_kr 20 148167465Smp#define T_ku 21 149167465Smp#define T_md 22 150167465Smp#define T_me 23 151167465Smp#define T_mr 24 152167465Smp#define T_nd 25 153167465Smp#define T_se 26 154167465Smp#define T_so 27 155167465Smp#define T_ts 28 156167465Smp#define T_up 29 157167465Smp#define T_us 30 158167465Smp#define T_ue 31 159167465Smp#define T_vb 32 160167465Smp#define T_DC 33 161167465Smp#define T_DO 34 162167465Smp#define T_IC 35 163167465Smp#define T_LE 36 164167465Smp#define T_RI 37 165167465Smp#define T_UP 38 166167465Smp#define T_str 39 167167465Smp 16859243Sobrienstatic struct termcapstr { 169145479Smp const char *name; 170145479Smp const char *long_name; 17159243Sobrien char *str; 17259243Sobrien} tstr[T_str + 1]; 17359243Sobrien 17459243Sobrien 17559243Sobrien#define T_am 0 17659243Sobrien#define T_pt 1 17759243Sobrien#define T_li 2 17859243Sobrien#define T_co 3 17959243Sobrien#define T_km 4 18059243Sobrien#define T_xn 5 18159243Sobrien#define T_val 6 18259243Sobrienstatic struct termcapval { 183145479Smp const char *name; 184145479Smp const char *long_name; 18559243Sobrien int val; 18659243Sobrien} tval[T_val + 1]; 18759243Sobrien 18859243Sobrienvoid 189167465Smpterminit(void) 19059243Sobrien{ 19159243Sobrien#ifdef NLS_CATALOGS 19259243Sobrien int i; 19359243Sobrien 19459243Sobrien for (i = 0; i < T_str + 1; i++) 195167465Smp xfree((ptr_t)(intptr_t)tstr[i].long_name); 19659243Sobrien 19759243Sobrien for (i = 0; i < T_val + 1; i++) 198167465Smp xfree((ptr_t)(intptr_t)tval[i].long_name); 19959243Sobrien#endif 20059243Sobrien 20159243Sobrien tstr[T_al].name = "al"; 20259243Sobrien tstr[T_al].long_name = CSAVS(4, 1, "add new blank line"); 20359243Sobrien 20459243Sobrien tstr[T_bl].name = "bl"; 20559243Sobrien tstr[T_bl].long_name = CSAVS(4, 2, "audible bell"); 20659243Sobrien 20759243Sobrien tstr[T_cd].name = "cd"; 20859243Sobrien tstr[T_cd].long_name = CSAVS(4, 3, "clear to bottom"); 20959243Sobrien 21059243Sobrien tstr[T_ce].name = "ce"; 21159243Sobrien tstr[T_ce].long_name = CSAVS(4, 4, "clear to end of line"); 21259243Sobrien 21359243Sobrien tstr[T_ch].name = "ch"; 21459243Sobrien tstr[T_ch].long_name = CSAVS(4, 5, "cursor to horiz pos"); 21559243Sobrien 21659243Sobrien tstr[T_cl].name = "cl"; 21759243Sobrien tstr[T_cl].long_name = CSAVS(4, 6, "clear screen"); 21859243Sobrien 21959243Sobrien tstr[T_dc].name = "dc"; 22059243Sobrien tstr[T_dc].long_name = CSAVS(4, 7, "delete a character"); 22159243Sobrien 22259243Sobrien tstr[T_dl].name = "dl"; 22359243Sobrien tstr[T_dl].long_name = CSAVS(4, 8, "delete a line"); 22459243Sobrien 22559243Sobrien tstr[T_dm].name = "dm"; 22659243Sobrien tstr[T_dm].long_name = CSAVS(4, 9, "start delete mode"); 22759243Sobrien 22859243Sobrien tstr[T_ed].name = "ed"; 22959243Sobrien tstr[T_ed].long_name = CSAVS(4, 10, "end delete mode"); 23059243Sobrien 23159243Sobrien tstr[T_ei].name = "ei"; 23259243Sobrien tstr[T_ei].long_name = CSAVS(4, 11, "end insert mode"); 23359243Sobrien 23459243Sobrien tstr[T_fs].name = "fs"; 23559243Sobrien tstr[T_fs].long_name = CSAVS(4, 12, "cursor from status line"); 23659243Sobrien 23759243Sobrien tstr[T_ho].name = "ho"; 23859243Sobrien tstr[T_ho].long_name = CSAVS(4, 13, "home cursor"); 23959243Sobrien 24059243Sobrien tstr[T_ic].name = "ic"; 24159243Sobrien tstr[T_ic].long_name = CSAVS(4, 14, "insert character"); 24259243Sobrien 24359243Sobrien tstr[T_im].name = "im"; 24459243Sobrien tstr[T_im].long_name = CSAVS(4, 15, "start insert mode"); 24559243Sobrien 24659243Sobrien tstr[T_ip].name = "ip"; 24759243Sobrien tstr[T_ip].long_name = CSAVS(4, 16, "insert padding"); 24859243Sobrien 24959243Sobrien tstr[T_kd].name = "kd"; 25059243Sobrien tstr[T_kd].long_name = CSAVS(4, 17, "sends cursor down"); 25159243Sobrien 25259243Sobrien tstr[T_kl].name = "kl"; 25359243Sobrien tstr[T_kl].long_name = CSAVS(4, 18, "sends cursor left"); 25459243Sobrien 25559243Sobrien tstr[T_kr].name = "kr"; 25659243Sobrien tstr[T_kr].long_name = CSAVS(4, 19, "sends cursor right"); 25759243Sobrien 25859243Sobrien tstr[T_ku].name = "ku"; 25959243Sobrien tstr[T_ku].long_name = CSAVS(4, 20, "sends cursor up"); 26059243Sobrien 26159243Sobrien tstr[T_md].name = "md"; 26259243Sobrien tstr[T_md].long_name = CSAVS(4, 21, "begin bold"); 26359243Sobrien 26459243Sobrien tstr[T_me].name = "me"; 26559243Sobrien tstr[T_me].long_name = CSAVS(4, 22, "end attributes"); 26659243Sobrien 26759243Sobrien tstr[T_nd].name = "nd"; 26859243Sobrien tstr[T_nd].long_name = CSAVS(4, 23, "non destructive space"); 26959243Sobrien 27059243Sobrien tstr[T_se].name = "se"; 27159243Sobrien tstr[T_se].long_name = CSAVS(4, 24, "end standout"); 27259243Sobrien 27359243Sobrien tstr[T_so].name = "so"; 27459243Sobrien tstr[T_so].long_name = CSAVS(4, 25, "begin standout"); 27559243Sobrien 27659243Sobrien tstr[T_ts].name = "ts"; 27759243Sobrien tstr[T_ts].long_name = CSAVS(4, 26, "cursor to status line"); 27859243Sobrien 27959243Sobrien tstr[T_up].name = "up"; 28059243Sobrien tstr[T_up].long_name = CSAVS(4, 27, "cursor up one"); 28159243Sobrien 28259243Sobrien tstr[T_us].name = "us"; 28359243Sobrien tstr[T_us].long_name = CSAVS(4, 28, "begin underline"); 28459243Sobrien 28559243Sobrien tstr[T_ue].name = "ue"; 28659243Sobrien tstr[T_ue].long_name = CSAVS(4, 29, "end underline"); 28759243Sobrien 28859243Sobrien tstr[T_vb].name = "vb"; 28959243Sobrien tstr[T_vb].long_name = CSAVS(4, 30, "visible bell"); 29059243Sobrien 29159243Sobrien tstr[T_DC].name = "DC"; 29259243Sobrien tstr[T_DC].long_name = CSAVS(4, 31, "delete multiple chars"); 29359243Sobrien 29459243Sobrien tstr[T_DO].name = "DO"; 29559243Sobrien tstr[T_DO].long_name = CSAVS(4, 32, "cursor down multiple"); 29659243Sobrien 29759243Sobrien tstr[T_IC].name = "IC"; 29859243Sobrien tstr[T_IC].long_name = CSAVS(4, 33, "insert multiple chars"); 29959243Sobrien 30059243Sobrien tstr[T_LE].name = "LE"; 30159243Sobrien tstr[T_LE].long_name = CSAVS(4, 34, "cursor left multiple"); 30259243Sobrien 30359243Sobrien tstr[T_RI].name = "RI"; 30459243Sobrien tstr[T_RI].long_name = CSAVS(4, 35, "cursor right multiple"); 30559243Sobrien 30659243Sobrien tstr[T_UP].name = "UP"; 30759243Sobrien tstr[T_UP].long_name = CSAVS(4, 36, "cursor up multiple"); 30859243Sobrien 30969408Sache tstr[T_kh].name = "kh"; 310167465Smp tstr[T_kh].long_name = CSAVS(4, 43, "send cursor home"); 31169408Sache 31269408Sache tstr[T_at7].name = "@7"; 313167465Smp tstr[T_at7].long_name = CSAVS(4, 44, "send cursor end"); 31469408Sache 315167465Smp tstr[T_mr].name = "mr"; 316167465Smp tstr[T_mr].long_name = CSAVS(4, 45, "begin reverse video"); 317167465Smp 31859243Sobrien tstr[T_str].name = NULL; 31959243Sobrien tstr[T_str].long_name = NULL; 32059243Sobrien 32159243Sobrien 32259243Sobrien tval[T_am].name = "am"; 32359243Sobrien tval[T_am].long_name = CSAVS(4, 37, "Has automatic margins"); 32459243Sobrien 32559243Sobrien tval[T_pt].name = "pt"; 32659243Sobrien tval[T_pt].long_name = CSAVS(4, 38, "Can use physical tabs"); 32759243Sobrien 32859243Sobrien tval[T_li].name = "li"; 32959243Sobrien tval[T_li].long_name = CSAVS(4, 39, "Number of lines"); 33059243Sobrien 33159243Sobrien tval[T_co].name = "co"; 33259243Sobrien tval[T_co].long_name = CSAVS(4, 40, "Number of columns"); 33359243Sobrien 33459243Sobrien tval[T_km].name = "km"; 33559243Sobrien tval[T_km].long_name = CSAVS(4, 41, "Has meta key"); 33659243Sobrien 33759243Sobrien tval[T_xn].name = "xn"; 33859243Sobrien tval[T_xn].long_name = CSAVS(4, 42, "Newline ignored at right margin"); 33959243Sobrien 34059243Sobrien tval[T_val].name = NULL; 34159243Sobrien tval[T_val].long_name = NULL; 34259243Sobrien} 34359243Sobrien 34459243Sobrien/* 34559243Sobrien * A very useful table from justin@crim.ca (Justin Bur) :-) 34659243Sobrien * (Modified by per@erix.ericsson.se (Per Hedeland) 34759243Sobrien * - first (and second:-) case fixed) 34859243Sobrien * 34959243Sobrien * Description Termcap variables tcsh behavior 35059243Sobrien * am xn UseRightmost SendCRLF 35159243Sobrien * -------------- ------- ------- ------------ ------------ 35259243Sobrien * Automargins yes no yes no 35359243Sobrien * Magic Margins yes yes yes no 35459243Sobrien * No Wrap no -- yes yes 35559243Sobrien */ 35659243Sobrien 357145479Smpstatic int me_all = 0; /* does two or more of the attributes use me */ 35859243Sobrien 359167465Smpstatic void ReBufferDisplay (void); 360167465Smpstatic void TCset (struct termcapstr *, const char *); 36159243Sobrien 36259243Sobrien 36359243Sobrienstatic void 364167465SmpTCset(struct termcapstr *t, const char *cap) 36559243Sobrien{ 36659243Sobrien if (cap == NULL || *cap == '\0') { 367167465Smp xfree(t->str); 36859243Sobrien t->str = NULL; 369167465Smp } else { 370167465Smp size_t size; 37159243Sobrien 372167465Smp size = strlen(cap) + 1; 373167465Smp t->str = xrealloc(t->str, size); 374167465Smp memcpy(t->str, cap, size); 37559243Sobrien } 37659243Sobrien} 37759243Sobrien 37859243Sobrien 37959243Sobrien/*ARGSUSED*/ 38059243Sobrienvoid 381167465SmpTellTC(void) 38259243Sobrien{ 38359243Sobrien struct termcapstr *t; 384167465Smp char *first, *s; 38559243Sobrien 386195609Smp xprintf("%s", CGETS(7, 1, "\n\tTcsh thinks your terminal has the\n")); 387195609Smp xprintf("%s", CGETS(7, 2, "\tfollowing characteristics:\n\n")); 38859243Sobrien xprintf(CGETS(7, 3, "\tIt has %d columns and %d lines\n"), 38959243Sobrien Val(T_co), Val(T_li)); 390145479Smp s = strsave(T_HasMeta ? CGETS(7, 5, "a") : CGETS(7, 6, "no")); 391167465Smp cleanup_push(s, xfree); 392167465Smp first = s; 393145479Smp xprintf(CGETS(7, 4, "\tIt has %s meta key\n"), s); 394145479Smp s = strsave(T_Tabs ? "" : CGETS(7, 8, " not")); 395167465Smp cleanup_push(s, xfree); 396145479Smp xprintf(CGETS(7, 7, "\tIt can%s use tabs\n"), s); 397145479Smp s = strsave((T_Margin&MARGIN_AUTO) ? 398145479Smp CGETS(7, 10, "has") : CGETS(7, 11, "does not have")); 399167465Smp cleanup_push(s, xfree); 400145479Smp xprintf(CGETS(7, 9, "\tIt %s automatic margins\n"), s); 401145479Smp if (T_Margin & MARGIN_AUTO) { 402145479Smp s = strsave((T_Margin & MARGIN_MAGIC) ? 403145479Smp CGETS(7, 10, "has") : CGETS(7, 11, "does not have")); 404167465Smp cleanup_push(s, xfree); 405145479Smp xprintf(CGETS(7, 12, "\tIt %s magic margins\n"), s); 406145479Smp } 407145479Smp for (t = tstr; t->name != NULL; t++) { 408145479Smp s = strsave(t->str && *t->str ? t->str : CGETS(7, 13, "(empty)")); 409167465Smp cleanup_push(s, xfree); 410145479Smp xprintf("\t%36s (%s) == %s\n", t->long_name, t->name, s); 411167465Smp cleanup_until(s); 412145479Smp } 41359243Sobrien xputchar('\n'); 414167465Smp cleanup_until(first); 41559243Sobrien} 41659243Sobrien 41759243Sobrien 41859243Sobrienstatic void 419167465SmpReBufferDisplay(void) 42059243Sobrien{ 421145479Smp int i; 422145479Smp Char **b; 42359243Sobrien 42459243Sobrien b = Display; 42559243Sobrien Display = NULL; 426167465Smp blkfree(b); 42759243Sobrien b = Vdisplay; 42859243Sobrien Vdisplay = NULL; 429167465Smp blkfree(b); 43059243Sobrien TermH = Val(T_co); 431167465Smp TermV = (INBUFSIZE * 4) / TermH + 1;/*FIXBUF*/ 432167465Smp b = xmalloc(sizeof(*b) * (TermV + 1)); 43359243Sobrien for (i = 0; i < TermV; i++) 434167465Smp b[i] = xmalloc(sizeof(*b[i]) * (TermH + 1)); 43559243Sobrien b[TermV] = NULL; 43659243Sobrien Display = b; 437167465Smp b = xmalloc(sizeof(*b) * (TermV + 1)); 43859243Sobrien for (i = 0; i < TermV; i++) 439167465Smp b[i] = xmalloc(sizeof(*b[i]) * (TermH + 1)); 44059243Sobrien b[TermV] = NULL; 44159243Sobrien Vdisplay = b; 44259243Sobrien} 44359243Sobrien 44459243Sobrienvoid 445167465SmpSetTC(char *what, char *how) 44659243Sobrien{ 44759243Sobrien struct termcapstr *ts; 44859243Sobrien struct termcapval *tv; 44959243Sobrien 45059243Sobrien /* 45159243Sobrien * Do the strings first 45259243Sobrien */ 45359243Sobrien setname("settc"); 45459243Sobrien for (ts = tstr; ts->name != NULL; ts++) 45559243Sobrien if (strcmp(ts->name, what) == 0) 45659243Sobrien break; 45759243Sobrien if (ts->name != NULL) { 458167465Smp TCset(ts, how); 45959243Sobrien /* 46059243Sobrien * Reset variables 46159243Sobrien */ 46259243Sobrien if (GoodStr(T_me) && GoodStr(T_ue)) 46359243Sobrien me_all = (strcmp(Str(T_me), Str(T_ue)) == 0); 46459243Sobrien else 46559243Sobrien me_all = 0; 46659243Sobrien if (GoodStr(T_me) && GoodStr(T_se)) 46759243Sobrien me_all |= (strcmp(Str(T_me), Str(T_se)) == 0); 46859243Sobrien 46959243Sobrien T_CanCEOL = GoodStr(T_ce); 47059243Sobrien T_CanDel = GoodStr(T_dc) || GoodStr(T_DC); 47159243Sobrien T_CanIns = GoodStr(T_im) || GoodStr(T_ic) || GoodStr(T_IC); 47259243Sobrien T_CanUP = GoodStr(T_up) || GoodStr(T_UP); 47359243Sobrien return; 47459243Sobrien } 47559243Sobrien 47659243Sobrien /* 47759243Sobrien * Do the numeric ones second 47859243Sobrien */ 47959243Sobrien for (tv = tval; tv->name != NULL; tv++) 48059243Sobrien if (strcmp(tv->name, what) == 0) 48159243Sobrien break; 48259243Sobrien 48359243Sobrien if (tv->name != NULL) { 48459243Sobrien if (tv == &tval[T_pt] || tv == &tval[T_km] || 48559243Sobrien tv == &tval[T_am] || tv == &tval[T_xn]) { 48659243Sobrien if (strcmp(how, "yes") == 0) 48759243Sobrien tv->val = 1; 48859243Sobrien else if (strcmp(how, "no") == 0) 48959243Sobrien tv->val = 0; 49059243Sobrien else { 49159243Sobrien stderror(ERR_SETTCUS, tv->name); 49259243Sobrien return; 49359243Sobrien } 494167465Smp T_Tabs = Val(T_pt); 495167465Smp T_HasMeta = Val(T_km); 496167465Smp T_Margin = Val(T_am) ? MARGIN_AUTO : 0; 497167465Smp T_Margin |= Val(T_xn) ? MARGIN_MAGIC : 0; 49859243Sobrien if (tv == &tval[T_am] || tv == &tval[T_xn]) 49959243Sobrien ChangeSize(Val(T_li), Val(T_co)); 50059243Sobrien return; 50159243Sobrien } 50259243Sobrien else { 50359243Sobrien tv->val = atoi(how); 50459243Sobrien T_Cols = (Char) Val(T_co); 50559243Sobrien T_Lines = (Char) Val(T_li); 50659243Sobrien if (tv == &tval[T_co] || tv == &tval[T_li]) 50759243Sobrien ChangeSize(Val(T_li), Val(T_co)); 50859243Sobrien return; 50959243Sobrien } 51059243Sobrien } 51159243Sobrien stderror(ERR_NAME | ERR_TCCAP, what); 51259243Sobrien return; 51359243Sobrien} 51459243Sobrien 51559243Sobrien 51659243Sobrien/* 51759243Sobrien * Print the termcap string out with variable substitution 51859243Sobrien */ 51959243Sobrienvoid 520167465SmpEchoTC(Char **v) 52159243Sobrien{ 522167465Smp char *cap, *scap, *cv; 52359243Sobrien int arg_need, arg_cols, arg_rows; 52459243Sobrien int verbose = 0, silent = 0; 52559243Sobrien char *area; 526167465Smp static const char fmts[] = "%s\n", fmtd[] = "%d\n"; 52759243Sobrien struct termcapstr *t; 52859243Sobrien char buf[TC_BUFSIZE]; 529167465Smp Char **globbed; 53059243Sobrien 53159243Sobrien area = buf; 53259243Sobrien 53359243Sobrien setname("echotc"); 53459243Sobrien 535167465Smp v = glob_all_or_error(v); 536167465Smp globbed = v; 537167465Smp cleanup_push(globbed, blk_cleanup); 53859243Sobrien 53959243Sobrien if (!*v || *v[0] == '\0') 540167465Smp goto end; 54159243Sobrien if (v[0][0] == '-') { 54259243Sobrien switch (v[0][1]) { 54359243Sobrien case 'v': 54459243Sobrien verbose = 1; 54559243Sobrien break; 54659243Sobrien case 's': 54759243Sobrien silent = 1; 54859243Sobrien break; 54959243Sobrien default: 55059243Sobrien stderror(ERR_NAME | ERR_TCUSAGE); 55159243Sobrien break; 55259243Sobrien } 55359243Sobrien v++; 55459243Sobrien } 55559243Sobrien if (!*v || *v[0] == '\0') 556167465Smp goto end; 557167465Smp cv = strsave(short2str(*v)); 558167465Smp cleanup_push(cv, xfree); 55959243Sobrien if (strcmp(cv, "tabs") == 0) { 56059243Sobrien xprintf(fmts, T_Tabs ? CGETS(7, 14, "yes") : 56159243Sobrien CGETS(7, 15, "no")); 562167465Smp goto end_flush; 56359243Sobrien } 56459243Sobrien else if (strcmp(cv, "meta") == 0) { 56559243Sobrien xprintf(fmts, Val(T_km) ? CGETS(7, 14, "yes") : 56659243Sobrien CGETS(7, 15, "no")); 567167465Smp goto end_flush; 56859243Sobrien } 56959243Sobrien else if (strcmp(cv, "xn") == 0) { 57059243Sobrien xprintf(fmts, T_Margin & MARGIN_MAGIC ? CGETS(7, 14, "yes") : 57159243Sobrien CGETS(7, 15, "no")); 572167465Smp goto end_flush; 57359243Sobrien } 57459243Sobrien else if (strcmp(cv, "am") == 0) { 57559243Sobrien xprintf(fmts, T_Margin & MARGIN_AUTO ? CGETS(7, 14, "yes") : 57659243Sobrien CGETS(7, 15, "no")); 577167465Smp goto end_flush; 57859243Sobrien } 57959243Sobrien else if (strcmp(cv, "baud") == 0) { 58059243Sobrien int i; 58159243Sobrien 58259243Sobrien for (i = 0; baud_rate[i].b_name != NULL; i++) 58359243Sobrien if (T_Speed == baud_rate[i].b_rate) { 58459243Sobrien xprintf(fmts, baud_rate[i].b_name); 585167465Smp goto end_flush; 58659243Sobrien } 58759243Sobrien xprintf(fmtd, 0); 588167465Smp goto end_flush; 58959243Sobrien } 590167465Smp else if (strcmp(cv, "rows") == 0 || strcmp(cv, "lines") == 0 || 591167465Smp strcmp(cv, "li") == 0) { 59259243Sobrien xprintf(fmtd, Val(T_li)); 593167465Smp goto end_flush; 59459243Sobrien } 595167465Smp else if (strcmp(cv, "cols") == 0 || strcmp(cv, "co") == 0) { 59659243Sobrien xprintf(fmtd, Val(T_co)); 597167465Smp goto end_flush; 59859243Sobrien } 59959243Sobrien 60059243Sobrien /* 60159243Sobrien * Try to use our local definition first 60259243Sobrien */ 60359243Sobrien scap = NULL; 60459243Sobrien for (t = tstr; t->name != NULL; t++) 60559243Sobrien if (strcmp(t->name, cv) == 0) { 60659243Sobrien scap = t->str; 60759243Sobrien break; 60859243Sobrien } 60959243Sobrien if (t->name == NULL) 61059243Sobrien scap = tgetstr(cv, &area); 61159243Sobrien if (!scap || scap[0] == '\0') { 61259243Sobrien if (tgetflag(cv)) { 613195609Smp xprintf("%s", CGETS(7, 14, "yes\n")); 614167465Smp goto end; 61559243Sobrien } 61659243Sobrien if (silent) 617167465Smp goto end; 61859243Sobrien else 61959243Sobrien stderror(ERR_NAME | ERR_TCCAP, cv); 62059243Sobrien } 62159243Sobrien 62259243Sobrien /* 62359243Sobrien * Count home many values we need for this capability. 62459243Sobrien */ 62559243Sobrien for (cap = scap, arg_need = 0; *cap; cap++) 62659243Sobrien if (*cap == '%') 62759243Sobrien switch (*++cap) { 62859243Sobrien case 'd': 62959243Sobrien case '2': 63059243Sobrien case '3': 63159243Sobrien case '.': 63259243Sobrien case '+': 63359243Sobrien arg_need++; 63459243Sobrien break; 63559243Sobrien case '%': 63659243Sobrien case '>': 63759243Sobrien case 'i': 63859243Sobrien case 'r': 63959243Sobrien case 'n': 64059243Sobrien case 'B': 64159243Sobrien case 'D': 64259243Sobrien break; 64359243Sobrien default: 64459243Sobrien /* 64559243Sobrien * hpux has lot's of them... 64659243Sobrien */ 64759243Sobrien if (verbose) 64859243Sobrien stderror(ERR_NAME | ERR_TCPARM, *cap); 64959243Sobrien /* This is bad, but I won't complain */ 65059243Sobrien break; 65159243Sobrien } 65259243Sobrien 65359243Sobrien switch (arg_need) { 65459243Sobrien case 0: 65559243Sobrien v++; 65659243Sobrien if (*v && *v[0]) { 65759243Sobrien if (silent) 658167465Smp goto end; 65959243Sobrien else 66059243Sobrien stderror(ERR_NAME | ERR_TCARGS, cv, arg_need); 66159243Sobrien } 66259243Sobrien (void) tputs(scap, 1, PUTRAW); 66359243Sobrien break; 66459243Sobrien case 1: 66559243Sobrien v++; 66659243Sobrien if (!*v || *v[0] == '\0') 66759243Sobrien stderror(ERR_NAME | ERR_TCNARGS, cv, 1); 66859243Sobrien arg_cols = 0; 66959243Sobrien arg_rows = atoi(short2str(*v)); 67059243Sobrien v++; 67159243Sobrien if (*v && *v[0]) { 67259243Sobrien if (silent) 673167465Smp goto end; 67459243Sobrien else 67559243Sobrien stderror(ERR_NAME | ERR_TCARGS, cv, arg_need); 67659243Sobrien } 67759243Sobrien (void) tputs(tgoto(scap, arg_cols, arg_rows), 1, PUTRAW); 67859243Sobrien break; 67959243Sobrien default: 68059243Sobrien /* This is wrong, but I will ignore it... */ 68159243Sobrien if (verbose) 68259243Sobrien stderror(ERR_NAME | ERR_TCARGS, cv, arg_need); 68359243Sobrien /*FALLTHROUGH*/ 68459243Sobrien case 2: 68559243Sobrien v++; 68659243Sobrien if (!*v || *v[0] == '\0') { 68759243Sobrien if (silent) 688167465Smp goto end; 68959243Sobrien else 69059243Sobrien stderror(ERR_NAME | ERR_TCNARGS, cv, 2); 69159243Sobrien } 69259243Sobrien arg_cols = atoi(short2str(*v)); 69359243Sobrien v++; 69459243Sobrien if (!*v || *v[0] == '\0') { 69559243Sobrien if (silent) 696167465Smp goto end; 69759243Sobrien else 69859243Sobrien stderror(ERR_NAME | ERR_TCNARGS, cv, 2); 69959243Sobrien } 70059243Sobrien arg_rows = atoi(short2str(*v)); 70159243Sobrien v++; 70259243Sobrien if (*v && *v[0]) { 70359243Sobrien if (silent) 704167465Smp goto end; 70559243Sobrien else 70659243Sobrien stderror(ERR_NAME | ERR_TCARGS, cv, arg_need); 70759243Sobrien } 70859243Sobrien (void) tputs(tgoto(scap, arg_cols, arg_rows), arg_rows, PUTRAW); 70959243Sobrien break; 71059243Sobrien } 711167465Smp end_flush: 71259243Sobrien flush(); 713167465Smp end: 714167465Smp cleanup_until(globbed); 71559243Sobrien} 71659243Sobrien 717145479Smpint GotTermCaps = 0; 71859243Sobrien 71959243Sobrienstatic struct { 72059243Sobrien Char *name; 72159243Sobrien int key; 72259243Sobrien XmapVal fun; 72359243Sobrien int type; 72459243Sobrien} arrow[] = { 72559243Sobrien#define A_K_DN 0 726145479Smp { STRdown, T_kd, { 0 }, 0 }, 72759243Sobrien#define A_K_UP 1 728145479Smp { STRup, T_ku, { 0 }, 0 }, 72959243Sobrien#define A_K_LT 2 730145479Smp { STRleft, T_kl, { 0 }, 0 }, 73159243Sobrien#define A_K_RT 3 732145479Smp { STRright, T_kr, { 0 }, 0 }, 73369408Sache#define A_K_HO 4 734145479Smp { STRhome, T_kh, { 0 }, 0 }, 73569408Sache#define A_K_EN 5 736145479Smp { STRend, T_at7, { 0 }, 0} 73759243Sobrien}; 73869408Sache#define A_K_NKEYS 6 73959243Sobrien 74059243Sobrienvoid 741167465SmpResetArrowKeys(void) 74259243Sobrien{ 74359243Sobrien arrow[A_K_DN].fun.cmd = F_DOWN_HIST; 74459243Sobrien arrow[A_K_DN].type = XK_CMD; 74559243Sobrien 74659243Sobrien arrow[A_K_UP].fun.cmd = F_UP_HIST; 74759243Sobrien arrow[A_K_UP].type = XK_CMD; 74859243Sobrien 74959243Sobrien arrow[A_K_LT].fun.cmd = F_CHARBACK; 75059243Sobrien arrow[A_K_LT].type = XK_CMD; 75159243Sobrien 75259243Sobrien arrow[A_K_RT].fun.cmd = F_CHARFWD; 75359243Sobrien arrow[A_K_RT].type = XK_CMD; 75459243Sobrien 75569408Sache arrow[A_K_HO].fun.cmd = F_TOBEG; 75669408Sache arrow[A_K_HO].type = XK_CMD; 75769408Sache 75869408Sache arrow[A_K_EN].fun.cmd = F_TOEND; 75969408Sache arrow[A_K_EN].type = XK_CMD; 76059243Sobrien} 76159243Sobrien 76259243Sobrienvoid 763167465SmpDefaultArrowKeys(void) 76459243Sobrien{ 76559243Sobrien static Char strA[] = {033, '[', 'A', '\0'}; 76659243Sobrien static Char strB[] = {033, '[', 'B', '\0'}; 76759243Sobrien static Char strC[] = {033, '[', 'C', '\0'}; 76859243Sobrien static Char strD[] = {033, '[', 'D', '\0'}; 76969408Sache static Char strH[] = {033, '[', 'H', '\0'}; 77069408Sache static Char strF[] = {033, '[', 'F', '\0'}; 77159243Sobrien static Char stOA[] = {033, 'O', 'A', '\0'}; 77259243Sobrien static Char stOB[] = {033, 'O', 'B', '\0'}; 77359243Sobrien static Char stOC[] = {033, 'O', 'C', '\0'}; 77459243Sobrien static Char stOD[] = {033, 'O', 'D', '\0'}; 77569408Sache static Char stOH[] = {033, 'O', 'H', '\0'}; 77669408Sache static Char stOF[] = {033, 'O', 'F', '\0'}; 77759243Sobrien 77859243Sobrien CStr cs; 77969408Sache#ifndef IS_ASCII 78059243Sobrien if (strA[0] == 033) 78159243Sobrien { 78259243Sobrien strA[0] = CTL_ESC('\033'); 78359243Sobrien strB[0] = CTL_ESC('\033'); 78459243Sobrien strC[0] = CTL_ESC('\033'); 78559243Sobrien strD[0] = CTL_ESC('\033'); 78669408Sache strH[0] = CTL_ESC('\033'); 78769408Sache strF[0] = CTL_ESC('\033'); 78859243Sobrien stOA[0] = CTL_ESC('\033'); 78959243Sobrien stOB[0] = CTL_ESC('\033'); 79059243Sobrien stOC[0] = CTL_ESC('\033'); 79159243Sobrien stOD[0] = CTL_ESC('\033'); 79269408Sache stOH[0] = CTL_ESC('\033'); 79369408Sache stOF[0] = CTL_ESC('\033'); 79459243Sobrien } 79559243Sobrien#endif 79659243Sobrien 79759243Sobrien cs.len = 3; 79859243Sobrien 79959243Sobrien cs.buf = strA; AddXkey(&cs, &arrow[A_K_UP].fun, arrow[A_K_UP].type); 80059243Sobrien cs.buf = strB; AddXkey(&cs, &arrow[A_K_DN].fun, arrow[A_K_DN].type); 80159243Sobrien cs.buf = strC; AddXkey(&cs, &arrow[A_K_RT].fun, arrow[A_K_RT].type); 80259243Sobrien cs.buf = strD; AddXkey(&cs, &arrow[A_K_LT].fun, arrow[A_K_LT].type); 80369408Sache cs.buf = strH; AddXkey(&cs, &arrow[A_K_HO].fun, arrow[A_K_HO].type); 80469408Sache cs.buf = strF; AddXkey(&cs, &arrow[A_K_EN].fun, arrow[A_K_EN].type); 80559243Sobrien cs.buf = stOA; AddXkey(&cs, &arrow[A_K_UP].fun, arrow[A_K_UP].type); 80659243Sobrien cs.buf = stOB; AddXkey(&cs, &arrow[A_K_DN].fun, arrow[A_K_DN].type); 80759243Sobrien cs.buf = stOC; AddXkey(&cs, &arrow[A_K_RT].fun, arrow[A_K_RT].type); 80859243Sobrien cs.buf = stOD; AddXkey(&cs, &arrow[A_K_LT].fun, arrow[A_K_LT].type); 80969408Sache cs.buf = stOH; AddXkey(&cs, &arrow[A_K_HO].fun, arrow[A_K_HO].type); 81069408Sache cs.buf = stOF; AddXkey(&cs, &arrow[A_K_EN].fun, arrow[A_K_EN].type); 81169408Sache 81259243Sobrien if (VImode) { 81359243Sobrien cs.len = 2; 81459243Sobrien cs.buf = &strA[1]; AddXkey(&cs, &arrow[A_K_UP].fun, arrow[A_K_UP].type); 81559243Sobrien cs.buf = &strB[1]; AddXkey(&cs, &arrow[A_K_DN].fun, arrow[A_K_DN].type); 81659243Sobrien cs.buf = &strC[1]; AddXkey(&cs, &arrow[A_K_RT].fun, arrow[A_K_RT].type); 81759243Sobrien cs.buf = &strD[1]; AddXkey(&cs, &arrow[A_K_LT].fun, arrow[A_K_LT].type); 81869408Sache cs.buf = &strH[1]; AddXkey(&cs, &arrow[A_K_HO].fun, arrow[A_K_HO].type); 81969408Sache cs.buf = &strF[1]; AddXkey(&cs, &arrow[A_K_EN].fun, arrow[A_K_EN].type); 82059243Sobrien cs.buf = &stOA[1]; AddXkey(&cs, &arrow[A_K_UP].fun, arrow[A_K_UP].type); 82159243Sobrien cs.buf = &stOB[1]; AddXkey(&cs, &arrow[A_K_DN].fun, arrow[A_K_DN].type); 82259243Sobrien cs.buf = &stOC[1]; AddXkey(&cs, &arrow[A_K_RT].fun, arrow[A_K_RT].type); 82359243Sobrien cs.buf = &stOD[1]; AddXkey(&cs, &arrow[A_K_LT].fun, arrow[A_K_LT].type); 82469408Sache cs.buf = &stOH[1]; AddXkey(&cs, &arrow[A_K_HO].fun, arrow[A_K_HO].type); 82569408Sache cs.buf = &stOF[1]; AddXkey(&cs, &arrow[A_K_EN].fun, arrow[A_K_EN].type); 82659243Sobrien } 82759243Sobrien} 82859243Sobrien 82959243Sobrien 83059243Sobrienint 831167465SmpSetArrowKeys(const CStr *name, XmapVal *fun, int type) 83259243Sobrien{ 83359243Sobrien int i; 83469408Sache for (i = 0; i < A_K_NKEYS; i++) 83559243Sobrien if (Strcmp(name->buf, arrow[i].name) == 0) { 83659243Sobrien arrow[i].fun = *fun; 83759243Sobrien arrow[i].type = type; 83859243Sobrien return 0; 83959243Sobrien } 84059243Sobrien return -1; 84159243Sobrien} 84259243Sobrien 84359243Sobrienint 844167465SmpIsArrowKey(Char *name) 84559243Sobrien{ 84659243Sobrien int i; 84769408Sache for (i = 0; i < A_K_NKEYS; i++) 84859243Sobrien if (Strcmp(name, arrow[i].name) == 0) 84959243Sobrien return 1; 85059243Sobrien return 0; 85159243Sobrien} 85259243Sobrien 85359243Sobrienint 854167465SmpClearArrowKeys(const CStr *name) 85559243Sobrien{ 85659243Sobrien int i; 85769408Sache for (i = 0; i < A_K_NKEYS; i++) 85859243Sobrien if (Strcmp(name->buf, arrow[i].name) == 0) { 85959243Sobrien arrow[i].type = XK_NOD; 86059243Sobrien return 0; 86159243Sobrien } 86259243Sobrien return -1; 86359243Sobrien} 86459243Sobrien 86559243Sobrienvoid 866167465SmpPrintArrowKeys(const CStr *name) 86759243Sobrien{ 86859243Sobrien int i; 86959243Sobrien 87069408Sache for (i = 0; i < A_K_NKEYS; i++) 87159243Sobrien if (name->len == 0 || Strcmp(name->buf, arrow[i].name) == 0) 872167465Smp if (arrow[i].type != XK_NOD) 873167465Smp printOne(arrow[i].name, &arrow[i].fun, arrow[i].type); 87459243Sobrien} 87559243Sobrien 87659243Sobrien 87759243Sobrienvoid 878167465SmpBindArrowKeys(void) 87959243Sobrien{ 88059243Sobrien KEYCMD *map, *dmap; 88159243Sobrien int i, j; 88259243Sobrien char *p; 88359243Sobrien CStr cs; 88459243Sobrien 88559243Sobrien if (!GotTermCaps) 88659243Sobrien return; 88759243Sobrien map = VImode ? CcAltMap : CcKeyMap; 88859243Sobrien dmap = VImode ? CcViCmdMap : CcEmacsMap; 88959243Sobrien 89059243Sobrien DefaultArrowKeys(); 89159243Sobrien 89269408Sache for (i = 0; i < A_K_NKEYS; i++) { 89359243Sobrien p = tstr[arrow[i].key].str; 89459243Sobrien if (p && *p) { 89559243Sobrien j = (unsigned char) *p; 89659243Sobrien cs.buf = str2short(p); 89759243Sobrien cs.len = Strlen(cs.buf); 89859243Sobrien /* 89959243Sobrien * Assign the arrow keys only if: 90059243Sobrien * 90159243Sobrien * 1. They are multi-character arrow keys and the user 90259243Sobrien * has not re-assigned the leading character, or 90359243Sobrien * has re-assigned the leading character to be F_XKEY 90459243Sobrien * 2. They are single arrow keys pointing to an unassigned key. 90559243Sobrien */ 90659243Sobrien if (arrow[i].type == XK_NOD) { 90759243Sobrien ClearXkey(map, &cs); 90859243Sobrien } 90959243Sobrien else { 91059243Sobrien if (p[1] && (dmap[j] == map[j] || map[j] == F_XKEY)) { 91159243Sobrien AddXkey(&cs, &arrow[i].fun, arrow[i].type); 91259243Sobrien map[j] = F_XKEY; 91359243Sobrien } 91459243Sobrien else if (map[j] == F_UNASSIGNED) { 91559243Sobrien ClearXkey(map, &cs); 91659243Sobrien if (arrow[i].type == XK_CMD) 91759243Sobrien map[j] = arrow[i].fun.cmd; 91859243Sobrien else 91959243Sobrien AddXkey(&cs, &arrow[i].fun, arrow[i].type); 92059243Sobrien } 92159243Sobrien } 92259243Sobrien } 92359243Sobrien } 92459243Sobrien} 92559243Sobrien 92659243Sobrienstatic Char cur_atr = 0; /* current attributes */ 92759243Sobrien 92859243Sobrienvoid 929167465SmpSetAttributes(Char atr) 93059243Sobrien{ 93159243Sobrien atr &= ATTRIBUTES; 93259243Sobrien if (atr != cur_atr) { 93359243Sobrien if (me_all && GoodStr(T_me)) { 93459243Sobrien if (((cur_atr & BOLD) && !(atr & BOLD)) || 93559243Sobrien ((cur_atr & UNDER) && !(atr & UNDER)) || 93659243Sobrien ((cur_atr & STANDOUT) && !(atr & STANDOUT))) { 93759243Sobrien (void) tputs(Str(T_me), 1, PUTPURE); 93859243Sobrien cur_atr = 0; 93959243Sobrien } 94059243Sobrien } 94159243Sobrien if ((atr & BOLD) != (cur_atr & BOLD)) { 94259243Sobrien if (atr & BOLD) { 94359243Sobrien if (GoodStr(T_md) && GoodStr(T_me)) { 94459243Sobrien (void) tputs(Str(T_md), 1, PUTPURE); 94559243Sobrien cur_atr |= BOLD; 94659243Sobrien } 94759243Sobrien } 94859243Sobrien else { 94959243Sobrien if (GoodStr(T_md) && GoodStr(T_me)) { 95059243Sobrien (void) tputs(Str(T_me), 1, PUTPURE); 95159243Sobrien if ((cur_atr & STANDOUT) && GoodStr(T_se)) { 95259243Sobrien (void) tputs(Str(T_se), 1, PUTPURE); 95359243Sobrien cur_atr &= ~STANDOUT; 95459243Sobrien } 95559243Sobrien if ((cur_atr & UNDER) && GoodStr(T_ue)) { 95659243Sobrien (void) tputs(Str(T_ue), 1, PUTPURE); 95759243Sobrien cur_atr &= ~UNDER; 95859243Sobrien } 95959243Sobrien cur_atr &= ~BOLD; 96059243Sobrien } 96159243Sobrien } 96259243Sobrien } 96359243Sobrien if ((atr & STANDOUT) != (cur_atr & STANDOUT)) { 96459243Sobrien if (atr & STANDOUT) { 96559243Sobrien if (GoodStr(T_so) && GoodStr(T_se)) { 96659243Sobrien (void) tputs(Str(T_so), 1, PUTPURE); 96759243Sobrien cur_atr |= STANDOUT; 96859243Sobrien } 96959243Sobrien } 97059243Sobrien else { 97159243Sobrien if (GoodStr(T_se)) { 97259243Sobrien (void) tputs(Str(T_se), 1, PUTPURE); 97359243Sobrien cur_atr &= ~STANDOUT; 97459243Sobrien } 97559243Sobrien } 97659243Sobrien } 97759243Sobrien if ((atr & UNDER) != (cur_atr & UNDER)) { 97859243Sobrien if (atr & UNDER) { 97959243Sobrien if (GoodStr(T_us) && GoodStr(T_ue)) { 98059243Sobrien (void) tputs(Str(T_us), 1, PUTPURE); 98159243Sobrien cur_atr |= UNDER; 98259243Sobrien } 98359243Sobrien } 98459243Sobrien else { 98559243Sobrien if (GoodStr(T_ue)) { 98659243Sobrien (void) tputs(Str(T_ue), 1, PUTPURE); 98759243Sobrien cur_atr &= ~UNDER; 98859243Sobrien } 98959243Sobrien } 99059243Sobrien } 99159243Sobrien } 99259243Sobrien} 99359243Sobrien 994167465Smpint highlighting = 0; 995167465Smp 996167465Smpvoid 997167465SmpStartHighlight() 998167465Smp{ 999167465Smp (void) tputs(Str(T_mr), 1, PUTPURE); 1000167465Smp highlighting = 1; 1001167465Smp} 1002167465Smp 1003167465Smpvoid 1004167465SmpStopHighlight() 1005167465Smp{ 1006167465Smp (void) tputs(Str(T_me), 1, PUTPURE); 1007167465Smp highlighting = 0; 1008167465Smp} 1009167465Smp 101059243Sobrien/* PWP 6-27-88 -- if the tty driver thinks that we can tab, we ask termcap */ 101159243Sobrienint 1012167465SmpCanWeTab(void) 101359243Sobrien{ 101459243Sobrien return (Val(T_pt)); 101559243Sobrien} 101659243Sobrien 1017167465Smp/* move to line <where> (first line == 0) as efficiently as possible; */ 101859243Sobrienvoid 1019167465SmpMoveToLine(int where) 102059243Sobrien{ 102159243Sobrien int del; 102259243Sobrien 102359243Sobrien if (where == CursorV) 102459243Sobrien return; 102559243Sobrien 102659243Sobrien if (where > TermV) { 102759243Sobrien#ifdef DEBUG_SCREEN 102859243Sobrien xprintf("MoveToLine: where is ridiculous: %d\r\n", where); 102959243Sobrien flush(); 103059243Sobrien#endif /* DEBUG_SCREEN */ 103159243Sobrien return; 103259243Sobrien } 103359243Sobrien 103459243Sobrien del = where - CursorV; 103559243Sobrien 103659243Sobrien if (del > 0) { 103759243Sobrien while (del > 0) { 103859243Sobrien if ((T_Margin & MARGIN_AUTO) && Display[CursorV][0] != '\0') { 1039145479Smp size_t h; 1040145479Smp 1041145479Smp for (h = TermH - 1; h > 0 && Display[CursorV][h] == CHAR_DBWIDTH; 1042145479Smp h--) 1043145479Smp ; 104459243Sobrien /* move without newline */ 1045145479Smp MoveToChar(h); 1046145479Smp so_write(&Display[CursorV][CursorH], TermH - CursorH); /* updates CursorH/V*/ 104759243Sobrien del--; 104859243Sobrien } 104959243Sobrien else { 105059243Sobrien if ((del > 1) && GoodStr(T_DO)) { 105159243Sobrien (void) tputs(tgoto(Str(T_DO), del, del), del, PUTPURE); 105259243Sobrien del = 0; 105359243Sobrien } 105459243Sobrien else { 105559243Sobrien for ( ; del > 0; del--) 105659243Sobrien (void) putraw('\n'); 105759243Sobrien CursorH = 0; /* because the \n will become \r\n */ 105859243Sobrien } 105959243Sobrien } 106059243Sobrien } 106159243Sobrien } 106259243Sobrien else { /* del < 0 */ 106359243Sobrien if (GoodStr(T_UP) && (-del > 1 || !GoodStr(T_up))) 106459243Sobrien (void) tputs(tgoto(Str(T_UP), -del, -del), -del, PUTPURE); 106559243Sobrien else { 106659243Sobrien int i; 106759243Sobrien if (GoodStr(T_up)) 106859243Sobrien for (i = 0; i < -del; i++) 106959243Sobrien (void) tputs(Str(T_up), 1, PUTPURE); 107059243Sobrien } 107159243Sobrien } 107259243Sobrien CursorV = where; /* now where is here */ 107359243Sobrien} 107459243Sobrien 107559243Sobrienvoid 1076167465SmpMoveToChar(int where) /* move to character position (where) */ 107759243Sobrien{ /* as efficiently as possible */ 107859243Sobrien int del; 107959243Sobrien 108059243Sobrienmc_again: 108159243Sobrien if (where == CursorH) 108259243Sobrien return; 108359243Sobrien 108459243Sobrien if (where >= TermH) { 108559243Sobrien#ifdef DEBUG_SCREEN 108659243Sobrien xprintf("MoveToChar: where is riduculous: %d\r\n", where); 108759243Sobrien flush(); 108859243Sobrien#endif /* DEBUG_SCREEN */ 108959243Sobrien return; 109059243Sobrien } 109159243Sobrien 109259243Sobrien if (!where) { /* if where is first column */ 109359243Sobrien (void) putraw('\r'); /* do a CR */ 109459243Sobrien CursorH = 0; 109559243Sobrien return; 109659243Sobrien } 109759243Sobrien 109859243Sobrien del = where - CursorH; 109959243Sobrien 110059243Sobrien if ((del < -4 || del > 4) && GoodStr(T_ch)) 110159243Sobrien /* go there directly */ 110259243Sobrien (void) tputs(tgoto(Str(T_ch), where, where), where, PUTPURE); 110359243Sobrien else { 110459243Sobrien int i; 110559243Sobrien if (del > 0) { /* moving forward */ 110659243Sobrien if ((del > 4) && GoodStr(T_RI)) 110759243Sobrien (void) tputs(tgoto(Str(T_RI), del, del), del, PUTPURE); 110859243Sobrien else { 110969408Sache /* if I can do tabs, use them */ 1110145479Smp if (T_Tabs) { 1111145479Smp if ((CursorH & 0370) != (where & ~0x7) 1112145479Smp && Display[CursorV][where & ~0x7] != CHAR_DBWIDTH) { 111359243Sobrien /* if not within tab stop */ 1114145479Smp for (i = (CursorH & 0370); i < (where & ~0x7); i += 8) 111559243Sobrien (void) putraw('\t'); /* then tab over */ 1116145479Smp CursorH = where & ~0x7; 111759243Sobrien /* Note: considering that we often want to go to 111859243Sobrien TermH - 1 for the wrapping, it would be nice to 111959243Sobrien optimize this case by tabbing to the last column 112059243Sobrien - but this doesn't work for all terminals! */ 112159243Sobrien } 112259243Sobrien } 112359243Sobrien /* it's usually cheaper to just write the chars, so we do. */ 112459243Sobrien 112559243Sobrien /* NOTE THAT so_write() WILL CHANGE CursorH!!! */ 112659243Sobrien so_write(&Display[CursorV][CursorH], where - CursorH); 112759243Sobrien 112859243Sobrien } 112959243Sobrien } 113059243Sobrien else { /* del < 0 := moving backward */ 113159243Sobrien if ((-del > 4) && GoodStr(T_LE)) 113259243Sobrien (void) tputs(tgoto(Str(T_LE), -del, -del), -del, PUTPURE); 113359243Sobrien else { /* can't go directly there */ 113459243Sobrien /* if the "cost" is greater than the "cost" from col 0 */ 113559243Sobrien if (T_Tabs ? (-del > ((where >> 3) + (where & 07))) 113659243Sobrien : (-del > where)) { 113759243Sobrien (void) putraw('\r'); /* do a CR */ 113859243Sobrien CursorH = 0; 113959243Sobrien goto mc_again; /* and try again */ 114059243Sobrien } 114159243Sobrien for (i = 0; i < -del; i++) 114259243Sobrien (void) putraw('\b'); 114359243Sobrien } 114459243Sobrien } 114559243Sobrien } 114659243Sobrien CursorH = where; /* now where is here */ 114759243Sobrien} 114859243Sobrien 114959243Sobrienvoid 1150167465Smpso_write(Char *cp, int n) 115159243Sobrien{ 1152167465Smp int cur_pos, prompt_len = 0, region_start = 0, region_end = 0; 1153167465Smp 115459243Sobrien if (n <= 0) 115559243Sobrien return; /* catch bugs */ 115659243Sobrien 115759243Sobrien if (n > TermH) { 115859243Sobrien#ifdef DEBUG_SCREEN 115959243Sobrien xprintf("so_write: n is riduculous: %d\r\n", n); 116059243Sobrien flush(); 116159243Sobrien#endif /* DEBUG_SCREEN */ 116259243Sobrien return; 116359243Sobrien } 116459243Sobrien 1165167465Smp if (adrof(STRhighlight)) { 1166167465Smp /* find length of prompt */ 1167167465Smp Char *promptc; 1168167465Smp for (promptc = Prompt; *promptc; promptc++); 1169167465Smp prompt_len = promptc - Prompt; 1170167465Smp 1171167465Smp /* find region start and end points */ 1172167465Smp if (IncMatchLen) { 1173167465Smp region_start = (Cursor - InputBuf) + prompt_len; 1174167465Smp region_end = region_start + IncMatchLen; 1175167465Smp } else if (MarkIsSet) { 1176167465Smp region_start = (min(Cursor, Mark) - InputBuf) + prompt_len; 1177167465Smp region_end = (max(Cursor, Mark) - InputBuf) + prompt_len; 1178167465Smp } 1179167465Smp } 1180167465Smp 118159243Sobrien do { 1182167465Smp if (adrof(STRhighlight)) { 1183167465Smp cur_pos = CursorV * TermH + CursorH; 1184167465Smp if (!highlighting && 1185167465Smp cur_pos >= region_start && cur_pos < region_end) 1186167465Smp StartHighlight(); 1187167465Smp else if (highlighting && cur_pos >= region_end) 1188167465Smp StopHighlight(); 1189167465Smp 1190167465Smp /* don't highlight over the cursor. the highlighting's reverse 1191167465Smp * video would cancel it out. :P */ 1192167465Smp if (highlighting && cur_pos == (Cursor - InputBuf) + prompt_len) 1193167465Smp StopHighlight(); 1194167465Smp } 1195167465Smp 1196145479Smp if (*cp != CHAR_DBWIDTH) { 1197145479Smp if (*cp & LITERAL) { 1198145479Smp Char *d; 119959243Sobrien#ifdef DEBUG_LITERAL 1200145479Smp xprintf("so: litnum %d\r\n", (int)(*cp & ~LITERAL)); 120159243Sobrien#endif /* DEBUG_LITERAL */ 1202145479Smp for (d = litptr + (*cp & ~LITERAL) * LIT_FACTOR; *d; d++) 1203145479Smp (void) putwraw(*d); 1204145479Smp } 1205145479Smp else 1206145479Smp (void) putwraw(*cp); 120759243Sobrien } 1208145479Smp cp++; 120959243Sobrien CursorH++; 121059243Sobrien } while (--n); 121159243Sobrien 1212167465Smp if (adrof(STRhighlight) && highlighting) 1213167465Smp StopHighlight(); 1214167465Smp 121559243Sobrien if (CursorH >= TermH) { /* wrap? */ 121659243Sobrien if (T_Margin & MARGIN_AUTO) { /* yes */ 121759243Sobrien CursorH = 0; 121859243Sobrien CursorV++; 121959243Sobrien if (T_Margin & MARGIN_MAGIC) { 122059243Sobrien /* force the wrap to avoid the "magic" situation */ 1221167465Smp Char xc; 1222167465Smp if ((xc = Display[CursorV][CursorH]) != '\0') { 1223167465Smp so_write(&xc, 1); 1224145479Smp while(Display[CursorV][CursorH] == CHAR_DBWIDTH) 1225145479Smp CursorH++; 1226145479Smp } 1227145479Smp else { 122859243Sobrien (void) putraw(' '); 1229145479Smp CursorH = 1; 1230145479Smp } 123159243Sobrien } 123259243Sobrien } 123359243Sobrien else /* no wrap, but cursor stays on screen */ 123459243Sobrien CursorH = TermH - 1; 123559243Sobrien } 123659243Sobrien} 123759243Sobrien 123859243Sobrien 123959243Sobrienvoid 1240167465SmpDeleteChars(int num) /* deletes <num> characters */ 124159243Sobrien{ 124259243Sobrien if (num <= 0) 124359243Sobrien return; 124459243Sobrien 124559243Sobrien if (!T_CanDel) { 124659243Sobrien#ifdef DEBUG_EDIT 124759243Sobrien xprintf(CGETS(7, 16, "ERROR: cannot delete\r\n")); 124859243Sobrien#endif /* DEBUG_EDIT */ 124959243Sobrien flush(); 125059243Sobrien return; 125159243Sobrien } 125259243Sobrien 125359243Sobrien if (num > TermH) { 125459243Sobrien#ifdef DEBUG_SCREEN 125559243Sobrien xprintf(CGETS(7, 17, "DeleteChars: num is riduculous: %d\r\n"), num); 125659243Sobrien flush(); 125759243Sobrien#endif /* DEBUG_SCREEN */ 125859243Sobrien return; 125959243Sobrien } 126059243Sobrien 126159243Sobrien if (GoodStr(T_DC)) /* if I have multiple delete */ 126259243Sobrien if ((num > 1) || !GoodStr(T_dc)) { /* if dc would be more expen. */ 126359243Sobrien (void) tputs(tgoto(Str(T_DC), num, num), num, PUTPURE); 126459243Sobrien return; 126559243Sobrien } 126659243Sobrien 126759243Sobrien if (GoodStr(T_dm)) /* if I have delete mode */ 126859243Sobrien (void) tputs(Str(T_dm), 1, PUTPURE); 126959243Sobrien 127059243Sobrien if (GoodStr(T_dc)) /* else do one at a time */ 127159243Sobrien while (num--) 127259243Sobrien (void) tputs(Str(T_dc), 1, PUTPURE); 127359243Sobrien 127459243Sobrien if (GoodStr(T_ed)) /* if I have delete mode */ 127559243Sobrien (void) tputs(Str(T_ed), 1, PUTPURE); 127659243Sobrien} 127759243Sobrien 1278167465Smp/* Puts terminal in insert character mode, or inserts num characters in the 1279167465Smp line */ 128059243Sobrienvoid 1281167465SmpInsert_write(Char *cp, int num) 128259243Sobrien{ 128359243Sobrien if (num <= 0) 128459243Sobrien return; 128559243Sobrien if (!T_CanIns) { 128659243Sobrien#ifdef DEBUG_EDIT 128759243Sobrien xprintf(CGETS(7, 18, "ERROR: cannot insert\r\n")); 128859243Sobrien#endif /* DEBUG_EDIT */ 128959243Sobrien flush(); 129059243Sobrien return; 129159243Sobrien } 129259243Sobrien 129359243Sobrien if (num > TermH) { 129459243Sobrien#ifdef DEBUG_SCREEN 129559243Sobrien xprintf(CGETS(7, 19, "StartInsert: num is riduculous: %d\r\n"), num); 129659243Sobrien flush(); 129759243Sobrien#endif /* DEBUG_SCREEN */ 129859243Sobrien return; 129959243Sobrien } 130059243Sobrien 130159243Sobrien if (GoodStr(T_IC)) /* if I have multiple insert */ 130259243Sobrien if ((num > 1) || !GoodStr(T_ic)) { /* if ic would be more expen. */ 130359243Sobrien (void) tputs(tgoto(Str(T_IC), num, num), num, PUTPURE); 130459243Sobrien so_write(cp, num); /* this updates CursorH/V */ 130559243Sobrien return; 130659243Sobrien } 130759243Sobrien 130859243Sobrien if (GoodStr(T_im) && GoodStr(T_ei)) { /* if I have insert mode */ 130959243Sobrien (void) tputs(Str(T_im), 1, PUTPURE); 131059243Sobrien 1311145479Smp so_write(cp, num); /* this updates CursorH/V */ 131259243Sobrien 131359243Sobrien if (GoodStr(T_ip)) /* have to make num chars insert */ 131459243Sobrien (void) tputs(Str(T_ip), 1, PUTPURE); 131559243Sobrien 131659243Sobrien (void) tputs(Str(T_ei), 1, PUTPURE); 131759243Sobrien return; 131859243Sobrien } 131959243Sobrien 132059243Sobrien do { 132159243Sobrien if (GoodStr(T_ic)) /* have to make num chars insert */ 132259243Sobrien (void) tputs(Str(T_ic), 1, PUTPURE); /* insert a char */ 132359243Sobrien 1324145479Smp so_write(cp++, 1); /* this updates CursorH/V */ 132559243Sobrien 132659243Sobrien if (GoodStr(T_ip)) /* have to make num chars insert */ 132759243Sobrien (void) tputs(Str(T_ip), 1, PUTPURE);/* pad the inserted char */ 132859243Sobrien 132959243Sobrien } while (--num); 133059243Sobrien 133159243Sobrien} 133259243Sobrien 1333167465Smp/* clear to end of line. There are num characters to clear */ 133459243Sobrienvoid 1335167465SmpClearEOL(int num) 133659243Sobrien{ 1337145479Smp int i; 133859243Sobrien 133959243Sobrien if (num <= 0) 134059243Sobrien return; 134159243Sobrien 134259243Sobrien if (T_CanCEOL && GoodStr(T_ce)) 134359243Sobrien (void) tputs(Str(T_ce), 1, PUTPURE); 134459243Sobrien else { 134559243Sobrien for (i = 0; i < num; i++) 134659243Sobrien (void) putraw(' '); 134759243Sobrien CursorH += num; /* have written num spaces */ 134859243Sobrien } 134959243Sobrien} 135059243Sobrien 135159243Sobrienvoid 1352167465SmpClearScreen(void) 135359243Sobrien{ /* clear the whole screen and home */ 135459243Sobrien if (GoodStr(T_cl)) 135559243Sobrien /* send the clear screen code */ 135659243Sobrien (void) tputs(Str(T_cl), Val(T_li), PUTPURE); 135759243Sobrien else if (GoodStr(T_ho) && GoodStr(T_cd)) { 135859243Sobrien (void) tputs(Str(T_ho), Val(T_li), PUTPURE); /* home */ 135959243Sobrien /* clear to bottom of screen */ 136059243Sobrien (void) tputs(Str(T_cd), Val(T_li), PUTPURE); 136159243Sobrien } 136259243Sobrien else { 136359243Sobrien (void) putraw('\r'); 136459243Sobrien (void) putraw('\n'); 136559243Sobrien } 136659243Sobrien} 136759243Sobrien 136859243Sobrienvoid 1369167465SmpSoundBeep(void) 137059243Sobrien{ /* produce a sound */ 137159243Sobrien beep_cmd (); 137259243Sobrien if (adrof(STRnobeep)) 137359243Sobrien return; 137459243Sobrien 137559243Sobrien if (GoodStr(T_vb) && adrof(STRvisiblebell)) 137659243Sobrien (void) tputs(Str(T_vb), 1, PUTPURE); /* visible bell */ 137759243Sobrien else if (GoodStr(T_bl)) 137859243Sobrien /* what termcap says we should use */ 137959243Sobrien (void) tputs(Str(T_bl), 1, PUTPURE); 138059243Sobrien else 138159243Sobrien (void) putraw(CTL_ESC('\007')); /* an ASCII bell; ^G */ 138259243Sobrien} 138359243Sobrien 138459243Sobrienvoid 1385167465SmpClearToBottom(void) 138659243Sobrien{ /* clear to the bottom of the screen */ 138759243Sobrien if (GoodStr(T_cd)) 138859243Sobrien (void) tputs(Str(T_cd), Val(T_li), PUTPURE); 138959243Sobrien else if (GoodStr(T_ce)) 139059243Sobrien (void) tputs(Str(T_ce), Val(T_li), PUTPURE); 139159243Sobrien} 139259243Sobrien 139359243Sobrienvoid 1394167465SmpGetTermCaps(void) 139559243Sobrien{ /* read in the needed terminal capabilites */ 1396145479Smp int i; 1397145479Smp const char *ptr; 139859243Sobrien char buf[TC_BUFSIZE]; 139959243Sobrien static char bp[TC_BUFSIZE]; 140059243Sobrien char *area; 140159243Sobrien struct termcapstr *t; 140259243Sobrien 140359243Sobrien 140459243Sobrien#ifdef SIG_WINDOW 1405167465Smp sigset_t oset, set; 140659243Sobrien int lins, cols; 140759243Sobrien 140859243Sobrien /* don't want to confuse things here */ 1409167465Smp sigemptyset(&set); 1410167465Smp sigaddset(&set, SIG_WINDOW); 1411167465Smp (void)sigprocmask(SIG_BLOCK, &set, &oset); 1412167465Smp cleanup_push(&oset, sigprocmask_cleanup); 141359243Sobrien#endif /* SIG_WINDOW */ 141459243Sobrien area = buf; 141559243Sobrien 141659243Sobrien GotTermCaps = 1; 141759243Sobrien 141859243Sobrien setname("gettermcaps"); 141959243Sobrien ptr = getenv("TERM"); 142059243Sobrien 142159243Sobrien#ifdef apollo 142259243Sobrien /* 142359243Sobrien * If we are on a pad, we pretend that we are dumb. Otherwise the termcap 142459243Sobrien * library will put us in a weird screen mode, thinking that we are going 142559243Sobrien * to use curses 142659243Sobrien */ 142759243Sobrien if (isapad()) 142859243Sobrien ptr = "dumb"; 142959243Sobrien#endif /* apollo */ 143059243Sobrien 143159243Sobrien if (!ptr || !ptr[0] || !strcmp(ptr, "wm") || !strcmp(ptr,"dmx")) 143259243Sobrien ptr = "dumb"; 143359243Sobrien 143459243Sobrien setzero(bp, TC_BUFSIZE); 143559243Sobrien 143659243Sobrien i = tgetent(bp, ptr); 143759243Sobrien if (i <= 0) { 143859243Sobrien if (i == -1) { 143959243Sobrien#if (SYSVREL == 0) || defined(IRIS3D) 144059243Sobrien xprintf(CGETS(7, 20, "%s: Cannot open /etc/termcap.\n"), progname); 144159243Sobrien } 144259243Sobrien else if (i == 0) { 144359243Sobrien#endif /* SYSVREL */ 144459243Sobrien xprintf(CGETS(7, 21, 144559243Sobrien "%s: No entry for terminal type \"%s\"\n"), progname, 144659243Sobrien getenv("TERM")); 144759243Sobrien } 144859243Sobrien xprintf(CGETS(7, 22, "%s: using dumb terminal settings.\n"), progname); 144959243Sobrien Val(T_co) = 80; /* do a dumb terminal */ 145059243Sobrien Val(T_pt) = Val(T_km) = Val(T_li) = 0; 145159243Sobrien for (t = tstr; t->name != NULL; t++) 1452167465Smp TCset(t, NULL); 145359243Sobrien } 145459243Sobrien else { 145559243Sobrien /* Can we tab */ 145659243Sobrien Val(T_pt) = tgetflag("pt") && !tgetflag("xt"); 145759243Sobrien /* do we have a meta? */ 145859243Sobrien Val(T_km) = (tgetflag("km") || tgetflag("MT")); 145959243Sobrien Val(T_am) = tgetflag("am"); 146059243Sobrien Val(T_xn) = tgetflag("xn"); 146159243Sobrien Val(T_co) = tgetnum("co"); 146259243Sobrien Val(T_li) = tgetnum("li"); 146359243Sobrien for (t = tstr; t->name != NULL; t++) 1464167465Smp TCset(t, tgetstr(t->name, &area)); 146559243Sobrien } 146659243Sobrien if (Val(T_co) < 2) 146759243Sobrien Val(T_co) = 80; /* just in case */ 146859243Sobrien if (Val(T_li) < 1) 146959243Sobrien Val(T_li) = 24; 147059243Sobrien 147159243Sobrien T_Cols = (Char) Val(T_co); 147259243Sobrien T_Lines = (Char) Val(T_li); 147359243Sobrien if (T_Tabs) 1474167465Smp T_Tabs = Val(T_pt); 1475167465Smp T_HasMeta = Val(T_km); 1476167465Smp T_Margin = Val(T_am) ? MARGIN_AUTO : 0; 1477167465Smp T_Margin |= Val(T_xn) ? MARGIN_MAGIC : 0; 147859243Sobrien T_CanCEOL = GoodStr(T_ce); 147959243Sobrien T_CanDel = GoodStr(T_dc) || GoodStr(T_DC); 148059243Sobrien T_CanIns = GoodStr(T_im) || GoodStr(T_ic) || GoodStr(T_IC); 148159243Sobrien T_CanUP = GoodStr(T_up) || GoodStr(T_UP); 148259243Sobrien if (GoodStr(T_me) && GoodStr(T_ue)) 148359243Sobrien me_all = (strcmp(Str(T_me), Str(T_ue)) == 0); 148459243Sobrien else 148559243Sobrien me_all = 0; 148659243Sobrien if (GoodStr(T_me) && GoodStr(T_se)) 148759243Sobrien me_all |= (strcmp(Str(T_me), Str(T_se)) == 0); 148859243Sobrien 148959243Sobrien 149059243Sobrien#ifdef DEBUG_SCREEN 149159243Sobrien if (!T_CanUP) { 149259243Sobrien xprintf(CGETS(7, 23, "%s: WARNING: Your terminal cannot move up.\n", 149359243Sobrien progname)); 149459243Sobrien xprintf(CGETS(7, 24, "Editing may be odd for long lines.\n")); 149559243Sobrien } 149659243Sobrien if (!T_CanCEOL) 149759243Sobrien xprintf(CGETS(7, 25, "no clear EOL capability.\n")); 149859243Sobrien if (!T_CanDel) 149959243Sobrien xprintf(CGETS(7, 26, "no delete char capability.\n")); 150059243Sobrien if (!T_CanIns) 150159243Sobrien xprintf(CGETS(7, 27, "no insert char capability.\n")); 150259243Sobrien#endif /* DEBUG_SCREEN */ 150359243Sobrien 150459243Sobrien 150559243Sobrien 150659243Sobrien#ifdef SIG_WINDOW 150759243Sobrien (void) GetSize(&lins, &cols); /* get the correct window size */ 150859243Sobrien ChangeSize(lins, cols); 150959243Sobrien 1510167465Smp cleanup_until(&oset); /* can change it again */ 151159243Sobrien#else /* SIG_WINDOW */ 151259243Sobrien ChangeSize(Val(T_li), Val(T_co)); 151359243Sobrien#endif /* SIG_WINDOW */ 151459243Sobrien 151559243Sobrien BindArrowKeys(); 151659243Sobrien} 151759243Sobrien 151859243Sobrien#ifdef SIG_WINDOW 151959243Sobrien/* GetSize(): 152059243Sobrien * Return the new window size in lines and cols, and 152159243Sobrien * true if the size was changed. This can fail if SHIN 152259243Sobrien * is not a tty, but it will work in most cases. 152359243Sobrien */ 152459243Sobrienint 1525167465SmpGetSize(int *lins, int *cols) 152659243Sobrien{ 152759243Sobrien *cols = Val(T_co); 152859243Sobrien *lins = Val(T_li); 152959243Sobrien 153059243Sobrien#ifdef TIOCGWINSZ 153159243Sobrien# define KNOWsize 153259243Sobrien# ifndef lint 153359243Sobrien { 153459243Sobrien struct winsize ws; /* from 4.3 */ 153559243Sobrien 153659243Sobrien if (ioctl(SHIN, TIOCGWINSZ, (ioctl_t) &ws) != -1) { 153759243Sobrien if (ws.ws_col) 153859243Sobrien *cols = ws.ws_col; 153959243Sobrien if (ws.ws_row) 154059243Sobrien *lins = ws.ws_row; 154159243Sobrien } 154259243Sobrien } 154359243Sobrien# endif /* !lint */ 154459243Sobrien#else /* TIOCGWINSZ */ 154559243Sobrien# ifdef TIOCGSIZE 154659243Sobrien# define KNOWsize 154759243Sobrien { 154859243Sobrien struct ttysize ts; /* from Sun */ 154959243Sobrien 155059243Sobrien if (ioctl(SHIN, TIOCGSIZE, (ioctl_t) &ts) != -1) { 155159243Sobrien if (ts.ts_cols) 155259243Sobrien *cols = ts.ts_cols; 155359243Sobrien if (ts.ts_lines) 155459243Sobrien *lins = ts.ts_lines; 155559243Sobrien } 155659243Sobrien } 155759243Sobrien# endif /* TIOCGSIZE */ 155859243Sobrien#endif /* TIOCGWINSZ */ 155959243Sobrien 156059243Sobrien return (Val(T_co) != *cols || Val(T_li) != *lins); 156159243Sobrien} 156259243Sobrien 1563167465Smp#endif /* SIG_WINDOW */ 156459243Sobrien 1565232633Smp#ifdef KNOWsize 1566232633Smpstatic void 1567232633SmpUpdateVal(const Char *tag, int value, Char *termcap, Char *backup) 1568232633Smp{ 1569232633Smp Char *ptr, *p; 1570232633Smp if ((ptr = Strstr(termcap, tag)) == NULL) { 1571232633Smp (void)Strcpy(backup, termcap); 1572232633Smp return; 1573232633Smp } else { 1574232633Smp size_t len = (ptr - termcap) + Strlen(tag); 1575232633Smp (void)Strncpy(backup, termcap, len); 1576232633Smp backup[len] = '\0'; 1577232633Smp p = Itoa(value, 0, 0); 1578232633Smp (void) Strcat(backup + len, p); 1579232633Smp xfree(p); 1580232633Smp ptr = Strchr(ptr, ':'); 1581232633Smp if (ptr) 1582232633Smp (void) Strcat(backup, ptr); 1583232633Smp } 1584232633Smp} 1585232633Smp#endif 1586232633Smp 158759243Sobrienvoid 1588167465SmpChangeSize(int lins, int cols) 158959243Sobrien{ 159059243Sobrien /* 159159243Sobrien * Just in case 159259243Sobrien */ 159359243Sobrien Val(T_co) = (cols < 2) ? 80 : cols; 159459243Sobrien Val(T_li) = (lins < 1) ? 24 : lins; 159559243Sobrien 159659243Sobrien#ifdef KNOWsize 159759243Sobrien /* 159859243Sobrien * We want to affect the environment only when we have a valid 159959243Sobrien * setup, not when we get bad settings. Consider the following scenario: 160059243Sobrien * We just logged in, and we have not initialized the editor yet. 160159243Sobrien * We reset termcap with tset, and not $TERMCAP has the right 160259243Sobrien * terminal size. But since the editor is not initialized yet, and 160359243Sobrien * the kernel's notion of the terminal size might be wrong we arrive 160459243Sobrien * here with lines = columns = 0. If we reset the environment we lose 160559243Sobrien * our only chance to get the window size right. 160659243Sobrien */ 160759243Sobrien if (Val(T_co) == cols && Val(T_li) == lins) { 1608167465Smp Char *p; 160959243Sobrien char *tptr; 161059243Sobrien 161159243Sobrien if (getenv("COLUMNS")) { 1612167465Smp p = Itoa(Val(T_co), 0, 0); 1613167465Smp cleanup_push(p, xfree); 1614167465Smp tsetenv(STRCOLUMNS, p); 1615167465Smp cleanup_until(p); 161659243Sobrien } 161759243Sobrien 161859243Sobrien if (getenv("LINES")) { 1619167465Smp p = Itoa(Val(T_li), 0, 0); 1620167465Smp cleanup_push(p, xfree); 1621167465Smp tsetenv(STRLINES, p); 1622167465Smp cleanup_until(p); 162359243Sobrien } 162459243Sobrien 162559243Sobrien if ((tptr = getenv("TERMCAP")) != NULL) { 162659243Sobrien /* Leave 64 characters slop in case we enlarge the termcap string */ 1627167465Smp Char termcap[TC_BUFSIZE+64], backup[TC_BUFSIZE+64], *ptr; 1628167465Smp Char buf[4]; 162959243Sobrien 163059243Sobrien ptr = str2short(tptr); 1631167465Smp (void) Strncpy(termcap, ptr, TC_BUFSIZE); 1632167465Smp termcap[TC_BUFSIZE-1] = '\0'; 163359243Sobrien 1634232633Smp UpdateVal(STRco, Val(T_co), termcap, backup); 1635232633Smp UpdateVal(STRli, Val(T_li), termcap, backup); 163659243Sobrien 163759243Sobrien /* 1638167465Smp * Chop the termcap string at TC_BUFSIZE-1 characters to avoid 1639167465Smp * core-dumps in the termcap routines 164059243Sobrien */ 1641167465Smp termcap[TC_BUFSIZE - 1] = '\0'; 164259243Sobrien tsetenv(STRTERMCAP, termcap); 164359243Sobrien } 164459243Sobrien } 164559243Sobrien#endif /* KNOWsize */ 164659243Sobrien 164759243Sobrien ReBufferDisplay(); /* re-make display buffers */ 164859243Sobrien ClearDisp(); 164959243Sobrien} 1650