xref: /freebsd-src/contrib/tcsh/ed.screen.c (revision 6560ac57ce879857203bc456cdc3849808dc0700)
1c80476e4SDavid E. O'Brien /*
2c80476e4SDavid E. O'Brien  * ed.screen.c: Editor/termcap-curses interface
3c80476e4SDavid E. O'Brien  */
4c80476e4SDavid E. O'Brien /*-
5c80476e4SDavid E. O'Brien  * Copyright (c) 1980, 1991 The Regents of the University of California.
6c80476e4SDavid E. O'Brien  * All rights reserved.
7c80476e4SDavid E. O'Brien  *
8c80476e4SDavid E. O'Brien  * Redistribution and use in source and binary forms, with or without
9c80476e4SDavid E. O'Brien  * modification, are permitted provided that the following conditions
10c80476e4SDavid E. O'Brien  * are met:
11c80476e4SDavid E. O'Brien  * 1. Redistributions of source code must retain the above copyright
12c80476e4SDavid E. O'Brien  *    notice, this list of conditions and the following disclaimer.
13c80476e4SDavid E. O'Brien  * 2. Redistributions in binary form must reproduce the above copyright
14c80476e4SDavid E. O'Brien  *    notice, this list of conditions and the following disclaimer in the
15c80476e4SDavid E. O'Brien  *    documentation and/or other materials provided with the distribution.
1629301572SMark Peek  * 3. Neither the name of the University nor the names of its contributors
17c80476e4SDavid E. O'Brien  *    may be used to endorse or promote products derived from this software
18c80476e4SDavid E. O'Brien  *    without specific prior written permission.
19c80476e4SDavid E. O'Brien  *
20c80476e4SDavid E. O'Brien  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
21c80476e4SDavid E. O'Brien  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22c80476e4SDavid E. O'Brien  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23c80476e4SDavid E. O'Brien  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
24c80476e4SDavid E. O'Brien  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25c80476e4SDavid E. O'Brien  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26c80476e4SDavid E. O'Brien  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27c80476e4SDavid E. O'Brien  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28c80476e4SDavid E. O'Brien  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29c80476e4SDavid E. O'Brien  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30c80476e4SDavid E. O'Brien  * SUCH DAMAGE.
31c80476e4SDavid E. O'Brien  */
32c80476e4SDavid E. O'Brien #include "sh.h"
33c80476e4SDavid E. O'Brien #include "ed.h"
34c80476e4SDavid E. O'Brien #include "tc.h"
35c80476e4SDavid E. O'Brien #include "ed.defns.h"
36c80476e4SDavid E. O'Brien 
37c80476e4SDavid E. O'Brien /* #define DEBUG_LITERAL */
38c80476e4SDavid E. O'Brien 
39c80476e4SDavid E. O'Brien /*
40c80476e4SDavid E. O'Brien  * IMPORTANT NOTE: these routines are allowed to look at the current screen
41c80476e4SDavid E. O'Brien  * and the current possition assuming that it is correct.  If this is not
42c80476e4SDavid E. O'Brien  * true, then the update will be WRONG!  This is (should be) a valid
43c80476e4SDavid E. O'Brien  * assumption...
44c80476e4SDavid E. O'Brien  */
45c80476e4SDavid E. O'Brien 
46c80476e4SDavid E. O'Brien #define TC_BUFSIZE 2048
47c80476e4SDavid E. O'Brien 
48c80476e4SDavid E. O'Brien #define GoodStr(a) (tstr[a].str != NULL && tstr[a].str[0] != '\0')
49c80476e4SDavid E. O'Brien #define Str(a) tstr[a].str
50c80476e4SDavid E. O'Brien #define Val(a) tval[a].val
51c80476e4SDavid E. O'Brien 
5245e5710bSMark Peek static const struct {
5323338178SMark Peek     const char   *b_name;
5423338178SMark Peek     speed_t b_rate;
55c80476e4SDavid E. O'Brien }       baud_rate[] = {
56c80476e4SDavid E. O'Brien 
57c80476e4SDavid E. O'Brien #ifdef B0
58c80476e4SDavid E. O'Brien     { "0", B0 },
59c80476e4SDavid E. O'Brien #endif
60c80476e4SDavid E. O'Brien #ifdef B50
61c80476e4SDavid E. O'Brien     { "50", B50 },
62c80476e4SDavid E. O'Brien #endif
63c80476e4SDavid E. O'Brien #ifdef B75
64c80476e4SDavid E. O'Brien     { "75", B75 },
65c80476e4SDavid E. O'Brien #endif
66c80476e4SDavid E. O'Brien #ifdef B110
67c80476e4SDavid E. O'Brien     { "110", B110 },
68c80476e4SDavid E. O'Brien #endif
69c80476e4SDavid E. O'Brien #ifdef B134
70c80476e4SDavid E. O'Brien     { "134", B134 },
71c80476e4SDavid E. O'Brien #endif
72c80476e4SDavid E. O'Brien #ifdef B150
73c80476e4SDavid E. O'Brien     { "150", B150 },
74c80476e4SDavid E. O'Brien #endif
75c80476e4SDavid E. O'Brien #ifdef B200
76c80476e4SDavid E. O'Brien     { "200", B200 },
77c80476e4SDavid E. O'Brien #endif
78c80476e4SDavid E. O'Brien #ifdef B300
79c80476e4SDavid E. O'Brien     { "300", B300 },
80c80476e4SDavid E. O'Brien #endif
81c80476e4SDavid E. O'Brien #ifdef B600
82c80476e4SDavid E. O'Brien     { "600", B600 },
83c80476e4SDavid E. O'Brien #endif
84c80476e4SDavid E. O'Brien #ifdef B900
85c80476e4SDavid E. O'Brien     { "900", B900 },
86c80476e4SDavid E. O'Brien #endif
87c80476e4SDavid E. O'Brien #ifdef B1200
88c80476e4SDavid E. O'Brien     { "1200", B1200 },
89c80476e4SDavid E. O'Brien #endif
90c80476e4SDavid E. O'Brien #ifdef B1800
91c80476e4SDavid E. O'Brien     { "1800", B1800 },
92c80476e4SDavid E. O'Brien #endif
93c80476e4SDavid E. O'Brien #ifdef B2400
94c80476e4SDavid E. O'Brien     { "2400", B2400 },
95c80476e4SDavid E. O'Brien #endif
96c80476e4SDavid E. O'Brien #ifdef B3600
97c80476e4SDavid E. O'Brien     { "3600", B3600 },
98c80476e4SDavid E. O'Brien #endif
99c80476e4SDavid E. O'Brien #ifdef B4800
100c80476e4SDavid E. O'Brien     { "4800", B4800 },
101c80476e4SDavid E. O'Brien #endif
102c80476e4SDavid E. O'Brien #ifdef B7200
103c80476e4SDavid E. O'Brien     { "7200", B7200 },
104c80476e4SDavid E. O'Brien #endif
105c80476e4SDavid E. O'Brien #ifdef B9600
106c80476e4SDavid E. O'Brien     { "9600", B9600 },
107c80476e4SDavid E. O'Brien #endif
108c80476e4SDavid E. O'Brien #ifdef EXTA
109c80476e4SDavid E. O'Brien     { "19200", EXTA },
110c80476e4SDavid E. O'Brien #endif
111c80476e4SDavid E. O'Brien #ifdef B19200
112c80476e4SDavid E. O'Brien     { "19200", B19200 },
113c80476e4SDavid E. O'Brien #endif
114c80476e4SDavid E. O'Brien #ifdef EXTB
115c80476e4SDavid E. O'Brien     { "38400", EXTB },
116c80476e4SDavid E. O'Brien #endif
117c80476e4SDavid E. O'Brien #ifdef B38400
118c80476e4SDavid E. O'Brien     { "38400", B38400 },
119c80476e4SDavid E. O'Brien #endif
120c80476e4SDavid E. O'Brien     { NULL, 0 }
121c80476e4SDavid E. O'Brien };
122c80476e4SDavid E. O'Brien 
12345e5710bSMark Peek #define T_at7   0
12445e5710bSMark Peek #define T_al	1
12545e5710bSMark Peek #define T_bl	2
12645e5710bSMark Peek #define T_cd	3
12745e5710bSMark Peek #define T_ce	4
12845e5710bSMark Peek #define T_ch	5
12945e5710bSMark Peek #define T_cl	6
13045e5710bSMark Peek #define	T_dc	7
13145e5710bSMark Peek #define	T_dl	8
13245e5710bSMark Peek #define	T_dm	9
13345e5710bSMark Peek #define	T_ed	10
13445e5710bSMark Peek #define	T_ei	11
13545e5710bSMark Peek #define	T_fs	12
13645e5710bSMark Peek #define	T_ho	13
13745e5710bSMark Peek #define	T_ic	14
13845e5710bSMark Peek #define	T_im	15
13945e5710bSMark Peek #define	T_ip	16
14045e5710bSMark Peek #define	T_kd	17
14145e5710bSMark Peek #define T_kh    18
14245e5710bSMark Peek #define	T_kl	19
14345e5710bSMark Peek #define T_kr	20
14445e5710bSMark Peek #define T_ku	21
14545e5710bSMark Peek #define T_md	22
14645e5710bSMark Peek #define T_me	23
14745e5710bSMark Peek #define T_mr    24
14845e5710bSMark Peek #define T_nd	25
14945e5710bSMark Peek #define T_se	26
15045e5710bSMark Peek #define T_so	27
15145e5710bSMark Peek #define T_ts	28
15245e5710bSMark Peek #define T_up	29
15345e5710bSMark Peek #define T_us	30
15445e5710bSMark Peek #define T_ue	31
15545e5710bSMark Peek #define T_vb	32
15645e5710bSMark Peek #define T_DC	33
15745e5710bSMark Peek #define T_DO	34
15845e5710bSMark Peek #define T_IC	35
15945e5710bSMark Peek #define T_LE	36
16045e5710bSMark Peek #define T_RI	37
16145e5710bSMark Peek #define T_UP	38
16245e5710bSMark Peek #define T_str   39
16345e5710bSMark Peek 
164c80476e4SDavid E. O'Brien static struct termcapstr {
16523338178SMark Peek     const char   *name;
16623338178SMark Peek     const char   *long_name;
167c80476e4SDavid E. O'Brien     char   *str;
168c80476e4SDavid E. O'Brien } tstr[T_str + 1];
169c80476e4SDavid E. O'Brien 
170c80476e4SDavid E. O'Brien 
171c80476e4SDavid E. O'Brien #define T_am	0
172c80476e4SDavid E. O'Brien #define T_pt	1
173c80476e4SDavid E. O'Brien #define T_li	2
174c80476e4SDavid E. O'Brien #define T_co	3
175c80476e4SDavid E. O'Brien #define T_km	4
176c80476e4SDavid E. O'Brien #define T_xn	5
177c80476e4SDavid E. O'Brien #define T_val	6
178c80476e4SDavid E. O'Brien static struct termcapval {
17923338178SMark Peek     const char   *name;
18023338178SMark Peek     const char   *long_name;
181c80476e4SDavid E. O'Brien     int     val;
182c80476e4SDavid E. O'Brien } tval[T_val + 1];
183c80476e4SDavid E. O'Brien 
184c80476e4SDavid E. O'Brien void
terminit(void)18545e5710bSMark Peek terminit(void)
186c80476e4SDavid E. O'Brien {
187c80476e4SDavid E. O'Brien #ifdef NLS_CATALOGS
188c80476e4SDavid E. O'Brien     int i;
189c80476e4SDavid E. O'Brien 
190c80476e4SDavid E. O'Brien     for (i = 0; i < T_str + 1; i++)
19145e5710bSMark Peek 	xfree((ptr_t)(intptr_t)tstr[i].long_name);
192c80476e4SDavid E. O'Brien 
193c80476e4SDavid E. O'Brien     for (i = 0; i < T_val + 1; i++)
19445e5710bSMark Peek 	xfree((ptr_t)(intptr_t)tval[i].long_name);
195c80476e4SDavid E. O'Brien #endif
196c80476e4SDavid E. O'Brien 
197c80476e4SDavid E. O'Brien     tstr[T_al].name = "al";
198c80476e4SDavid E. O'Brien     tstr[T_al].long_name = CSAVS(4, 1, "add new blank line");
199c80476e4SDavid E. O'Brien 
200c80476e4SDavid E. O'Brien     tstr[T_bl].name = "bl";
201c80476e4SDavid E. O'Brien     tstr[T_bl].long_name = CSAVS(4, 2, "audible bell");
202c80476e4SDavid E. O'Brien 
203c80476e4SDavid E. O'Brien     tstr[T_cd].name = "cd";
204c80476e4SDavid E. O'Brien     tstr[T_cd].long_name = CSAVS(4, 3, "clear to bottom");
205c80476e4SDavid E. O'Brien 
206c80476e4SDavid E. O'Brien     tstr[T_ce].name = "ce";
207c80476e4SDavid E. O'Brien     tstr[T_ce].long_name = CSAVS(4, 4, "clear to end of line");
208c80476e4SDavid E. O'Brien 
209c80476e4SDavid E. O'Brien     tstr[T_ch].name = "ch";
210c80476e4SDavid E. O'Brien     tstr[T_ch].long_name = CSAVS(4, 5, "cursor to horiz pos");
211c80476e4SDavid E. O'Brien 
212c80476e4SDavid E. O'Brien     tstr[T_cl].name = "cl";
213c80476e4SDavid E. O'Brien     tstr[T_cl].long_name = CSAVS(4, 6, "clear screen");
214c80476e4SDavid E. O'Brien 
215c80476e4SDavid E. O'Brien     tstr[T_dc].name = "dc";
216c80476e4SDavid E. O'Brien     tstr[T_dc].long_name = CSAVS(4, 7, "delete a character");
217c80476e4SDavid E. O'Brien 
218c80476e4SDavid E. O'Brien     tstr[T_dl].name = "dl";
219c80476e4SDavid E. O'Brien     tstr[T_dl].long_name = CSAVS(4, 8, "delete a line");
220c80476e4SDavid E. O'Brien 
221c80476e4SDavid E. O'Brien     tstr[T_dm].name = "dm";
222c80476e4SDavid E. O'Brien     tstr[T_dm].long_name = CSAVS(4, 9, "start delete mode");
223c80476e4SDavid E. O'Brien 
224c80476e4SDavid E. O'Brien     tstr[T_ed].name = "ed";
225c80476e4SDavid E. O'Brien     tstr[T_ed].long_name = CSAVS(4, 10, "end delete mode");
226c80476e4SDavid E. O'Brien 
227c80476e4SDavid E. O'Brien     tstr[T_ei].name = "ei";
228c80476e4SDavid E. O'Brien     tstr[T_ei].long_name = CSAVS(4, 11, "end insert mode");
229c80476e4SDavid E. O'Brien 
230c80476e4SDavid E. O'Brien     tstr[T_fs].name = "fs";
231c80476e4SDavid E. O'Brien     tstr[T_fs].long_name = CSAVS(4, 12, "cursor from status line");
232c80476e4SDavid E. O'Brien 
233c80476e4SDavid E. O'Brien     tstr[T_ho].name = "ho";
234c80476e4SDavid E. O'Brien     tstr[T_ho].long_name = CSAVS(4, 13, "home cursor");
235c80476e4SDavid E. O'Brien 
236c80476e4SDavid E. O'Brien     tstr[T_ic].name = "ic";
237c80476e4SDavid E. O'Brien     tstr[T_ic].long_name = CSAVS(4, 14, "insert character");
238c80476e4SDavid E. O'Brien 
239c80476e4SDavid E. O'Brien     tstr[T_im].name = "im";
240c80476e4SDavid E. O'Brien     tstr[T_im].long_name = CSAVS(4, 15, "start insert mode");
241c80476e4SDavid E. O'Brien 
242c80476e4SDavid E. O'Brien     tstr[T_ip].name = "ip";
243c80476e4SDavid E. O'Brien     tstr[T_ip].long_name = CSAVS(4, 16, "insert padding");
244c80476e4SDavid E. O'Brien 
245c80476e4SDavid E. O'Brien     tstr[T_kd].name = "kd";
246c80476e4SDavid E. O'Brien     tstr[T_kd].long_name = CSAVS(4, 17, "sends cursor down");
247c80476e4SDavid E. O'Brien 
248c80476e4SDavid E. O'Brien     tstr[T_kl].name = "kl";
249c80476e4SDavid E. O'Brien     tstr[T_kl].long_name = CSAVS(4, 18, "sends cursor left");
250c80476e4SDavid E. O'Brien 
251c80476e4SDavid E. O'Brien     tstr[T_kr].name = "kr";
252c80476e4SDavid E. O'Brien     tstr[T_kr].long_name = CSAVS(4, 19, "sends cursor right");
253c80476e4SDavid E. O'Brien 
254c80476e4SDavid E. O'Brien     tstr[T_ku].name = "ku";
255c80476e4SDavid E. O'Brien     tstr[T_ku].long_name = CSAVS(4, 20, "sends cursor up");
256c80476e4SDavid E. O'Brien 
257c80476e4SDavid E. O'Brien     tstr[T_md].name = "md";
258c80476e4SDavid E. O'Brien     tstr[T_md].long_name = CSAVS(4, 21, "begin bold");
259c80476e4SDavid E. O'Brien 
260c80476e4SDavid E. O'Brien     tstr[T_me].name = "me";
261c80476e4SDavid E. O'Brien     tstr[T_me].long_name = CSAVS(4, 22, "end attributes");
262c80476e4SDavid E. O'Brien 
263c80476e4SDavid E. O'Brien     tstr[T_nd].name = "nd";
264c80476e4SDavid E. O'Brien     tstr[T_nd].long_name = CSAVS(4, 23, "non destructive space");
265c80476e4SDavid E. O'Brien 
266c80476e4SDavid E. O'Brien     tstr[T_se].name = "se";
267c80476e4SDavid E. O'Brien     tstr[T_se].long_name = CSAVS(4, 24, "end standout");
268c80476e4SDavid E. O'Brien 
269c80476e4SDavid E. O'Brien     tstr[T_so].name = "so";
270c80476e4SDavid E. O'Brien     tstr[T_so].long_name = CSAVS(4, 25, "begin standout");
271c80476e4SDavid E. O'Brien 
272c80476e4SDavid E. O'Brien     tstr[T_ts].name = "ts";
273c80476e4SDavid E. O'Brien     tstr[T_ts].long_name = CSAVS(4, 26, "cursor to status line");
274c80476e4SDavid E. O'Brien 
275c80476e4SDavid E. O'Brien     tstr[T_up].name = "up";
276c80476e4SDavid E. O'Brien     tstr[T_up].long_name = CSAVS(4, 27, "cursor up one");
277c80476e4SDavid E. O'Brien 
278c80476e4SDavid E. O'Brien     tstr[T_us].name = "us";
279c80476e4SDavid E. O'Brien     tstr[T_us].long_name = CSAVS(4, 28, "begin underline");
280c80476e4SDavid E. O'Brien 
281c80476e4SDavid E. O'Brien     tstr[T_ue].name = "ue";
282c80476e4SDavid E. O'Brien     tstr[T_ue].long_name = CSAVS(4, 29, "end underline");
283c80476e4SDavid E. O'Brien 
284c80476e4SDavid E. O'Brien     tstr[T_vb].name = "vb";
285c80476e4SDavid E. O'Brien     tstr[T_vb].long_name = CSAVS(4, 30, "visible bell");
286c80476e4SDavid E. O'Brien 
287c80476e4SDavid E. O'Brien     tstr[T_DC].name = "DC";
288c80476e4SDavid E. O'Brien     tstr[T_DC].long_name = CSAVS(4, 31, "delete multiple chars");
289c80476e4SDavid E. O'Brien 
290c80476e4SDavid E. O'Brien     tstr[T_DO].name = "DO";
291c80476e4SDavid E. O'Brien     tstr[T_DO].long_name = CSAVS(4, 32, "cursor down multiple");
292c80476e4SDavid E. O'Brien 
293c80476e4SDavid E. O'Brien     tstr[T_IC].name = "IC";
294c80476e4SDavid E. O'Brien     tstr[T_IC].long_name = CSAVS(4, 33, "insert multiple chars");
295c80476e4SDavid E. O'Brien 
296c80476e4SDavid E. O'Brien     tstr[T_LE].name = "LE";
297c80476e4SDavid E. O'Brien     tstr[T_LE].long_name = CSAVS(4, 34, "cursor left multiple");
298c80476e4SDavid E. O'Brien 
299c80476e4SDavid E. O'Brien     tstr[T_RI].name = "RI";
300c80476e4SDavid E. O'Brien     tstr[T_RI].long_name = CSAVS(4, 35, "cursor right multiple");
301c80476e4SDavid E. O'Brien 
302c80476e4SDavid E. O'Brien     tstr[T_UP].name = "UP";
303c80476e4SDavid E. O'Brien     tstr[T_UP].long_name = CSAVS(4, 36, "cursor up multiple");
304c80476e4SDavid E. O'Brien 
3053b6eaa7bSAndrey A. Chernov     tstr[T_kh].name = "kh";
30645e5710bSMark Peek     tstr[T_kh].long_name = CSAVS(4, 43, "send cursor home");
3073b6eaa7bSAndrey A. Chernov 
3083b6eaa7bSAndrey A. Chernov     tstr[T_at7].name = "@7";
30945e5710bSMark Peek     tstr[T_at7].long_name = CSAVS(4, 44, "send cursor end");
31045e5710bSMark Peek 
31145e5710bSMark Peek     tstr[T_mr].name = "mr";
31245e5710bSMark Peek     tstr[T_mr].long_name = CSAVS(4, 45, "begin reverse video");
3133b6eaa7bSAndrey A. Chernov 
314c80476e4SDavid E. O'Brien     tstr[T_str].name = NULL;
315c80476e4SDavid E. O'Brien     tstr[T_str].long_name = NULL;
316c80476e4SDavid E. O'Brien 
317c80476e4SDavid E. O'Brien 
318c80476e4SDavid E. O'Brien     tval[T_am].name = "am";
319c80476e4SDavid E. O'Brien     tval[T_am].long_name = CSAVS(4, 37, "Has automatic margins");
320c80476e4SDavid E. O'Brien 
321c80476e4SDavid E. O'Brien     tval[T_pt].name = "pt";
322c80476e4SDavid E. O'Brien     tval[T_pt].long_name = CSAVS(4, 38, "Can use physical tabs");
323c80476e4SDavid E. O'Brien 
324c80476e4SDavid E. O'Brien     tval[T_li].name = "li";
325c80476e4SDavid E. O'Brien     tval[T_li].long_name = CSAVS(4, 39, "Number of lines");
326c80476e4SDavid E. O'Brien 
327c80476e4SDavid E. O'Brien     tval[T_co].name = "co";
328c80476e4SDavid E. O'Brien     tval[T_co].long_name = CSAVS(4, 40, "Number of columns");
329c80476e4SDavid E. O'Brien 
330c80476e4SDavid E. O'Brien     tval[T_km].name = "km";
331c80476e4SDavid E. O'Brien     tval[T_km].long_name = CSAVS(4, 41, "Has meta key");
332c80476e4SDavid E. O'Brien 
333c80476e4SDavid E. O'Brien     tval[T_xn].name = "xn";
334c80476e4SDavid E. O'Brien     tval[T_xn].long_name = CSAVS(4, 42, "Newline ignored at right margin");
335c80476e4SDavid E. O'Brien 
336c80476e4SDavid E. O'Brien     tval[T_val].name = NULL;
337c80476e4SDavid E. O'Brien     tval[T_val].long_name = NULL;
338c80476e4SDavid E. O'Brien }
339c80476e4SDavid E. O'Brien 
340c80476e4SDavid E. O'Brien /*
341c80476e4SDavid E. O'Brien  * A very useful table from justin@crim.ca (Justin Bur) :-)
342c80476e4SDavid E. O'Brien  * (Modified by per@erix.ericsson.se (Per Hedeland)
343c80476e4SDavid E. O'Brien  *  - first (and second:-) case fixed)
344c80476e4SDavid E. O'Brien  *
345c80476e4SDavid E. O'Brien  * Description     Termcap variables       tcsh behavior
346c80476e4SDavid E. O'Brien  * 		   am      xn              UseRightmost    SendCRLF
347c80476e4SDavid E. O'Brien  * --------------  ------- -------         ------------    ------------
348c80476e4SDavid E. O'Brien  * Automargins     yes     no              yes             no
349c80476e4SDavid E. O'Brien  * Magic Margins   yes     yes             yes             no
350c80476e4SDavid E. O'Brien  * No Wrap         no      --              yes             yes
351c80476e4SDavid E. O'Brien  */
352c80476e4SDavid E. O'Brien 
35323338178SMark Peek static int me_all = 0;		/* does two or more of the attributes use me */
354c80476e4SDavid E. O'Brien 
35545e5710bSMark Peek static	void	ReBufferDisplay	(void);
35645e5710bSMark Peek static	void	TCset		(struct termcapstr *, const char *);
357c80476e4SDavid E. O'Brien 
358c80476e4SDavid E. O'Brien 
359c80476e4SDavid E. O'Brien static void
TCset(struct termcapstr * t,const char * cap)36045e5710bSMark Peek TCset(struct termcapstr *t, const char *cap)
361c80476e4SDavid E. O'Brien {
362c80476e4SDavid E. O'Brien     if (cap == NULL || *cap == '\0') {
36345e5710bSMark Peek 	xfree(t->str);
364c80476e4SDavid E. O'Brien 	t->str = NULL;
36545e5710bSMark Peek     } else {
36645e5710bSMark Peek 	size_t size;
367c80476e4SDavid E. O'Brien 
36845e5710bSMark Peek 	size = strlen(cap) + 1;
36945e5710bSMark Peek 	t->str = xrealloc(t->str, size);
37045e5710bSMark Peek 	memcpy(t->str, cap, size);
371c80476e4SDavid E. O'Brien     }
372c80476e4SDavid E. O'Brien }
373c80476e4SDavid E. O'Brien 
374c80476e4SDavid E. O'Brien 
375c80476e4SDavid E. O'Brien /*ARGSUSED*/
376c80476e4SDavid E. O'Brien void
TellTC(void)37745e5710bSMark Peek TellTC(void)
378c80476e4SDavid E. O'Brien {
379c80476e4SDavid E. O'Brien     struct termcapstr *t;
38045e5710bSMark Peek     char *first, *s;
381c80476e4SDavid E. O'Brien 
382a15e6f9aSMark Peek     xprintf("%s", CGETS(7, 1, "\n\tTcsh thinks your terminal has the\n"));
383a15e6f9aSMark Peek     xprintf("%s", CGETS(7, 2, "\tfollowing characteristics:\n\n"));
384c80476e4SDavid E. O'Brien     xprintf(CGETS(7, 3, "\tIt has %d columns and %d lines\n"),
385c80476e4SDavid E. O'Brien 	    Val(T_co), Val(T_li));
38623338178SMark Peek     s = strsave(T_HasMeta ? CGETS(7, 5, "a") : CGETS(7, 6, "no"));
38745e5710bSMark Peek     cleanup_push(s, xfree);
38845e5710bSMark Peek     first = s;
38923338178SMark Peek     xprintf(CGETS(7, 4, "\tIt has %s meta key\n"), s);
39023338178SMark Peek     s = strsave(T_Tabs ? "" : CGETS(7, 8, " not"));
39145e5710bSMark Peek     cleanup_push(s, xfree);
39223338178SMark Peek     xprintf(CGETS(7, 7, "\tIt can%s use tabs\n"), s);
39323338178SMark Peek     s = strsave((T_Margin&MARGIN_AUTO) ?
39423338178SMark Peek 		CGETS(7, 10, "has") : CGETS(7, 11, "does not have"));
39545e5710bSMark Peek     cleanup_push(s, xfree);
39623338178SMark Peek     xprintf(CGETS(7, 9, "\tIt %s automatic margins\n"), s);
39723338178SMark Peek     if (T_Margin & MARGIN_AUTO) {
39823338178SMark Peek         s = strsave((T_Margin & MARGIN_MAGIC) ?
39923338178SMark Peek 			CGETS(7, 10, "has") : CGETS(7, 11, "does not have"));
40045e5710bSMark Peek 	cleanup_push(s, xfree);
40123338178SMark Peek 	xprintf(CGETS(7, 12, "\tIt %s magic margins\n"), s);
40223338178SMark Peek     }
40323338178SMark Peek     for (t = tstr; t->name != NULL; t++) {
40423338178SMark Peek         s = strsave(t->str && *t->str ? t->str : CGETS(7, 13, "(empty)"));
40545e5710bSMark Peek 	cleanup_push(s, xfree);
40623338178SMark Peek 	xprintf("\t%36s (%s) == %s\n", t->long_name, t->name, s);
40745e5710bSMark Peek 	cleanup_until(s);
40823338178SMark Peek     }
409c80476e4SDavid E. O'Brien     xputchar('\n');
41045e5710bSMark Peek     cleanup_until(first);
411c80476e4SDavid E. O'Brien }
412c80476e4SDavid E. O'Brien 
413c80476e4SDavid E. O'Brien 
414c80476e4SDavid E. O'Brien static void
ReBufferDisplay(void)41545e5710bSMark Peek ReBufferDisplay(void)
416c80476e4SDavid E. O'Brien {
41723338178SMark Peek     int i;
418c80476e4SDavid E. O'Brien     Char **b;
419c80476e4SDavid E. O'Brien 
420c80476e4SDavid E. O'Brien     b = Display;
421c80476e4SDavid E. O'Brien     Display = NULL;
42245e5710bSMark Peek     blkfree(b);
423c80476e4SDavid E. O'Brien     b = Vdisplay;
424c80476e4SDavid E. O'Brien     Vdisplay = NULL;
42545e5710bSMark Peek     blkfree(b);
426c80476e4SDavid E. O'Brien     TermH = Val(T_co);
42745e5710bSMark Peek     TermV = (INBUFSIZE * 4) / TermH + 1;/*FIXBUF*/
42845e5710bSMark Peek     b = xmalloc(sizeof(*b) * (TermV + 1));
429c80476e4SDavid E. O'Brien     for (i = 0; i < TermV; i++)
43045e5710bSMark Peek 	b[i] = xmalloc(sizeof(*b[i]) * (TermH + 1));
431c80476e4SDavid E. O'Brien     b[TermV] = NULL;
432c80476e4SDavid E. O'Brien     Display = b;
43345e5710bSMark Peek     b = xmalloc(sizeof(*b) * (TermV + 1));
434c80476e4SDavid E. O'Brien     for (i = 0; i < TermV; i++)
43545e5710bSMark Peek 	b[i] = xmalloc(sizeof(*b[i]) * (TermH + 1));
436c80476e4SDavid E. O'Brien     b[TermV] = NULL;
437c80476e4SDavid E. O'Brien     Vdisplay = b;
438c80476e4SDavid E. O'Brien }
439c80476e4SDavid E. O'Brien 
440c80476e4SDavid E. O'Brien void
SetTC(char * what,char * how)44145e5710bSMark Peek SetTC(char *what, char *how)
442c80476e4SDavid E. O'Brien {
443c80476e4SDavid E. O'Brien     struct termcapstr *ts;
444c80476e4SDavid E. O'Brien     struct termcapval *tv;
445c80476e4SDavid E. O'Brien 
446c80476e4SDavid E. O'Brien     /*
447c80476e4SDavid E. O'Brien      * Do the strings first
448c80476e4SDavid E. O'Brien      */
449c80476e4SDavid E. O'Brien     setname("settc");
450c80476e4SDavid E. O'Brien     for (ts = tstr; ts->name != NULL; ts++)
451c80476e4SDavid E. O'Brien 	if (strcmp(ts->name, what) == 0)
452c80476e4SDavid E. O'Brien 	    break;
453c80476e4SDavid E. O'Brien     if (ts->name != NULL) {
45445e5710bSMark Peek 	TCset(ts, how);
455c80476e4SDavid E. O'Brien 	/*
456c80476e4SDavid E. O'Brien 	 * Reset variables
457c80476e4SDavid E. O'Brien 	 */
458c80476e4SDavid E. O'Brien 	if (GoodStr(T_me) && GoodStr(T_ue))
459c80476e4SDavid E. O'Brien 	    me_all = (strcmp(Str(T_me), Str(T_ue)) == 0);
460c80476e4SDavid E. O'Brien 	else
461c80476e4SDavid E. O'Brien 	    me_all = 0;
462c80476e4SDavid E. O'Brien 	if (GoodStr(T_me) && GoodStr(T_se))
463c80476e4SDavid E. O'Brien 	    me_all |= (strcmp(Str(T_me), Str(T_se)) == 0);
464c80476e4SDavid E. O'Brien 
465c80476e4SDavid E. O'Brien 	T_CanCEOL = GoodStr(T_ce);
466c80476e4SDavid E. O'Brien 	T_CanDel = GoodStr(T_dc) || GoodStr(T_DC);
467c80476e4SDavid E. O'Brien 	T_CanIns = GoodStr(T_im) || GoodStr(T_ic) || GoodStr(T_IC);
468c80476e4SDavid E. O'Brien 	T_CanUP = GoodStr(T_up) || GoodStr(T_UP);
469c80476e4SDavid E. O'Brien 	return;
470c80476e4SDavid E. O'Brien     }
471c80476e4SDavid E. O'Brien 
472c80476e4SDavid E. O'Brien     /*
473c80476e4SDavid E. O'Brien      * Do the numeric ones second
474c80476e4SDavid E. O'Brien      */
475c80476e4SDavid E. O'Brien     for (tv = tval; tv->name != NULL; tv++)
476c80476e4SDavid E. O'Brien 	if (strcmp(tv->name, what) == 0)
477c80476e4SDavid E. O'Brien 	    break;
478c80476e4SDavid E. O'Brien 
479c80476e4SDavid E. O'Brien     if (tv->name != NULL) {
480c80476e4SDavid E. O'Brien 	if (tv == &tval[T_pt] || tv == &tval[T_km] ||
481c80476e4SDavid E. O'Brien 	    tv == &tval[T_am] || tv == &tval[T_xn]) {
482c80476e4SDavid E. O'Brien 	    if (strcmp(how, "yes") == 0)
483c80476e4SDavid E. O'Brien 		tv->val = 1;
484c80476e4SDavid E. O'Brien 	    else if (strcmp(how, "no") == 0)
485c80476e4SDavid E. O'Brien 		tv->val = 0;
486c80476e4SDavid E. O'Brien 	    else {
487c80476e4SDavid E. O'Brien 		stderror(ERR_SETTCUS, tv->name);
488c80476e4SDavid E. O'Brien 		return;
489c80476e4SDavid E. O'Brien 	    }
49045e5710bSMark Peek 	    T_Tabs = Val(T_pt);
49145e5710bSMark Peek 	    T_HasMeta = Val(T_km);
49245e5710bSMark Peek 	    T_Margin = Val(T_am) ? MARGIN_AUTO : 0;
49345e5710bSMark Peek 	    T_Margin |= Val(T_xn) ? MARGIN_MAGIC : 0;
494c80476e4SDavid E. O'Brien 	    if (tv == &tval[T_am] || tv == &tval[T_xn])
495c80476e4SDavid E. O'Brien 		ChangeSize(Val(T_li), Val(T_co));
496c80476e4SDavid E. O'Brien 	    return;
497c80476e4SDavid E. O'Brien 	}
498c80476e4SDavid E. O'Brien 	else {
499c80476e4SDavid E. O'Brien 	    tv->val = atoi(how);
500c80476e4SDavid E. O'Brien 	    T_Cols = (Char) Val(T_co);
501c80476e4SDavid E. O'Brien 	    T_Lines = (Char) Val(T_li);
502c80476e4SDavid E. O'Brien 	    if (tv == &tval[T_co] || tv == &tval[T_li])
503c80476e4SDavid E. O'Brien 		ChangeSize(Val(T_li), Val(T_co));
504c80476e4SDavid E. O'Brien 	    return;
505c80476e4SDavid E. O'Brien 	}
506c80476e4SDavid E. O'Brien     }
507c80476e4SDavid E. O'Brien     stderror(ERR_NAME | ERR_TCCAP, what);
508c80476e4SDavid E. O'Brien     return;
509c80476e4SDavid E. O'Brien }
510c80476e4SDavid E. O'Brien 
511c80476e4SDavid E. O'Brien 
512c80476e4SDavid E. O'Brien /*
513c80476e4SDavid E. O'Brien  * Print the termcap string out with variable substitution
514c80476e4SDavid E. O'Brien  */
515c80476e4SDavid E. O'Brien void
EchoTC(Char ** v)51645e5710bSMark Peek EchoTC(Char **v)
517c80476e4SDavid E. O'Brien {
51845e5710bSMark Peek     char   *cap, *scap, *cv;
519c80476e4SDavid E. O'Brien     int     arg_need, arg_cols, arg_rows;
520c80476e4SDavid E. O'Brien     int     verbose = 0, silent = 0;
521c80476e4SDavid E. O'Brien     char   *area;
52245e5710bSMark Peek     static const char fmts[] = "%s\n", fmtd[] = "%d\n";
523c80476e4SDavid E. O'Brien     struct termcapstr *t;
524c80476e4SDavid E. O'Brien     char    buf[TC_BUFSIZE];
52545e5710bSMark Peek     Char **globbed;
526c80476e4SDavid E. O'Brien 
527c80476e4SDavid E. O'Brien     area = buf;
528c80476e4SDavid E. O'Brien 
529c80476e4SDavid E. O'Brien     setname("echotc");
530c80476e4SDavid E. O'Brien 
53145e5710bSMark Peek     v = glob_all_or_error(v);
53245e5710bSMark Peek     globbed = v;
53345e5710bSMark Peek     cleanup_push(globbed, blk_cleanup);
534c80476e4SDavid E. O'Brien 
535c80476e4SDavid E. O'Brien     if (!*v || *v[0] == '\0')
53645e5710bSMark Peek 	goto end;
537c80476e4SDavid E. O'Brien     if (v[0][0] == '-') {
538c80476e4SDavid E. O'Brien 	switch (v[0][1]) {
539c80476e4SDavid E. O'Brien 	case 'v':
540c80476e4SDavid E. O'Brien 	    verbose = 1;
541c80476e4SDavid E. O'Brien 	    break;
542c80476e4SDavid E. O'Brien 	case 's':
543c80476e4SDavid E. O'Brien 	    silent = 1;
544c80476e4SDavid E. O'Brien 	    break;
545c80476e4SDavid E. O'Brien 	default:
546c80476e4SDavid E. O'Brien 	    stderror(ERR_NAME | ERR_TCUSAGE);
547c80476e4SDavid E. O'Brien 	    break;
548c80476e4SDavid E. O'Brien 	}
549c80476e4SDavid E. O'Brien 	v++;
550c80476e4SDavid E. O'Brien     }
551c80476e4SDavid E. O'Brien     if (!*v || *v[0] == '\0')
55245e5710bSMark Peek 	goto end;
55345e5710bSMark Peek     cv = strsave(short2str(*v));
55445e5710bSMark Peek     cleanup_push(cv, xfree);
555c80476e4SDavid E. O'Brien     if (strcmp(cv, "tabs") == 0) {
556c80476e4SDavid E. O'Brien 	xprintf(fmts, T_Tabs ? CGETS(7, 14, "yes") :
557c80476e4SDavid E. O'Brien 		CGETS(7, 15, "no"));
55845e5710bSMark Peek 	goto end_flush;
559c80476e4SDavid E. O'Brien     }
560c80476e4SDavid E. O'Brien     else if (strcmp(cv, "meta") == 0) {
561c80476e4SDavid E. O'Brien 	xprintf(fmts, Val(T_km) ? CGETS(7, 14, "yes") :
562c80476e4SDavid E. O'Brien 		CGETS(7, 15, "no"));
56345e5710bSMark Peek 	goto end_flush;
564c80476e4SDavid E. O'Brien     }
565c80476e4SDavid E. O'Brien     else if (strcmp(cv, "xn") == 0) {
566c80476e4SDavid E. O'Brien 	xprintf(fmts, T_Margin & MARGIN_MAGIC ? CGETS(7, 14, "yes") :
567c80476e4SDavid E. O'Brien 		CGETS(7, 15,  "no"));
56845e5710bSMark Peek 	goto end_flush;
569c80476e4SDavid E. O'Brien     }
570c80476e4SDavid E. O'Brien     else if (strcmp(cv, "am") == 0) {
571c80476e4SDavid E. O'Brien 	xprintf(fmts, T_Margin & MARGIN_AUTO ? CGETS(7, 14, "yes") :
572c80476e4SDavid E. O'Brien 		CGETS(7, 15, "no"));
57345e5710bSMark Peek 	goto end_flush;
574c80476e4SDavid E. O'Brien     }
575c80476e4SDavid E. O'Brien     else if (strcmp(cv, "baud") == 0) {
576c80476e4SDavid E. O'Brien 	int     i;
577c80476e4SDavid E. O'Brien 
578c80476e4SDavid E. O'Brien 	for (i = 0; baud_rate[i].b_name != NULL; i++)
579c80476e4SDavid E. O'Brien 	    if (T_Speed == baud_rate[i].b_rate) {
580c80476e4SDavid E. O'Brien 		xprintf(fmts, baud_rate[i].b_name);
58145e5710bSMark Peek 		goto end_flush;
582c80476e4SDavid E. O'Brien 	    }
583c80476e4SDavid E. O'Brien 	xprintf(fmtd, 0);
58445e5710bSMark Peek 	goto end_flush;
585c80476e4SDavid E. O'Brien     }
58645e5710bSMark Peek     else if (strcmp(cv, "rows") == 0 || strcmp(cv, "lines") == 0 ||
58745e5710bSMark Peek 	strcmp(cv, "li") == 0) {
588c80476e4SDavid E. O'Brien 	xprintf(fmtd, Val(T_li));
58945e5710bSMark Peek 	goto end_flush;
590c80476e4SDavid E. O'Brien     }
59145e5710bSMark Peek     else if (strcmp(cv, "cols") == 0 || strcmp(cv, "co") == 0) {
592c80476e4SDavid E. O'Brien 	xprintf(fmtd, Val(T_co));
59345e5710bSMark Peek 	goto end_flush;
594c80476e4SDavid E. O'Brien     }
595c80476e4SDavid E. O'Brien 
596c80476e4SDavid E. O'Brien     /*
597c80476e4SDavid E. O'Brien      * Try to use our local definition first
598c80476e4SDavid E. O'Brien      */
599c80476e4SDavid E. O'Brien     scap = NULL;
600c80476e4SDavid E. O'Brien     for (t = tstr; t->name != NULL; t++)
601c80476e4SDavid E. O'Brien 	if (strcmp(t->name, cv) == 0) {
602c80476e4SDavid E. O'Brien 	    scap = t->str;
603c80476e4SDavid E. O'Brien 	    break;
604c80476e4SDavid E. O'Brien 	}
605c80476e4SDavid E. O'Brien     if (t->name == NULL)
606c80476e4SDavid E. O'Brien 	scap = tgetstr(cv, &area);
607c80476e4SDavid E. O'Brien     if (!scap || scap[0] == '\0') {
608c80476e4SDavid E. O'Brien 	if (tgetflag(cv)) {
609a15e6f9aSMark Peek 	    xprintf("%s", CGETS(7, 14, "yes\n"));
61045e5710bSMark Peek 	    goto end;
611c80476e4SDavid E. O'Brien 	}
612c80476e4SDavid E. O'Brien 	if (silent)
61345e5710bSMark Peek 	    goto end;
614c80476e4SDavid E. O'Brien 	else
615c80476e4SDavid E. O'Brien 	    stderror(ERR_NAME | ERR_TCCAP, cv);
616c80476e4SDavid E. O'Brien     }
617c80476e4SDavid E. O'Brien 
618c80476e4SDavid E. O'Brien     /*
619c80476e4SDavid E. O'Brien      * Count home many values we need for this capability.
620c80476e4SDavid E. O'Brien      */
621c80476e4SDavid E. O'Brien     for (cap = scap, arg_need = 0; *cap; cap++)
622c80476e4SDavid E. O'Brien 	if (*cap == '%')
623c80476e4SDavid E. O'Brien 	    switch (*++cap) {
624c80476e4SDavid E. O'Brien 	    case 'd':
625c80476e4SDavid E. O'Brien 	    case '2':
626c80476e4SDavid E. O'Brien 	    case '3':
627c80476e4SDavid E. O'Brien 	    case '.':
628c80476e4SDavid E. O'Brien 	    case '+':
629c80476e4SDavid E. O'Brien 		arg_need++;
630c80476e4SDavid E. O'Brien 		break;
631c80476e4SDavid E. O'Brien 	    case '%':
632c80476e4SDavid E. O'Brien 	    case '>':
633c80476e4SDavid E. O'Brien 	    case 'i':
634c80476e4SDavid E. O'Brien 	    case 'r':
635c80476e4SDavid E. O'Brien 	    case 'n':
636c80476e4SDavid E. O'Brien 	    case 'B':
637c80476e4SDavid E. O'Brien 	    case 'D':
638c80476e4SDavid E. O'Brien 		break;
639c80476e4SDavid E. O'Brien 	    default:
640c80476e4SDavid E. O'Brien 		/*
641c80476e4SDavid E. O'Brien 		 * hpux has lot's of them...
642c80476e4SDavid E. O'Brien 		 */
643c80476e4SDavid E. O'Brien 		if (verbose)
644c80476e4SDavid E. O'Brien 		    stderror(ERR_NAME | ERR_TCPARM, *cap);
645c80476e4SDavid E. O'Brien 		/* This is bad, but I won't complain */
646c80476e4SDavid E. O'Brien 		break;
647c80476e4SDavid E. O'Brien 	    }
648c80476e4SDavid E. O'Brien 
649c80476e4SDavid E. O'Brien     switch (arg_need) {
650c80476e4SDavid E. O'Brien     case 0:
651c80476e4SDavid E. O'Brien 	v++;
652c80476e4SDavid E. O'Brien 	if (*v && *v[0]) {
653c80476e4SDavid E. O'Brien 	    if (silent)
65445e5710bSMark Peek 		goto end;
655c80476e4SDavid E. O'Brien 	    else
656c80476e4SDavid E. O'Brien 		stderror(ERR_NAME | ERR_TCARGS, cv, arg_need);
657c80476e4SDavid E. O'Brien 	}
658c80476e4SDavid E. O'Brien 	(void) tputs(scap, 1, PUTRAW);
659c80476e4SDavid E. O'Brien 	break;
660c80476e4SDavid E. O'Brien     case 1:
661c80476e4SDavid E. O'Brien 	v++;
662c80476e4SDavid E. O'Brien 	if (!*v || *v[0] == '\0')
663c80476e4SDavid E. O'Brien 	    stderror(ERR_NAME | ERR_TCNARGS, cv, 1);
664c80476e4SDavid E. O'Brien 	arg_cols = 0;
665c80476e4SDavid E. O'Brien 	arg_rows = atoi(short2str(*v));
666c80476e4SDavid E. O'Brien 	v++;
667c80476e4SDavid E. O'Brien 	if (*v && *v[0]) {
668c80476e4SDavid E. O'Brien 	    if (silent)
66945e5710bSMark Peek 		goto end;
670c80476e4SDavid E. O'Brien 	    else
671c80476e4SDavid E. O'Brien 		stderror(ERR_NAME | ERR_TCARGS, cv, arg_need);
672c80476e4SDavid E. O'Brien 	}
673c80476e4SDavid E. O'Brien 	(void) tputs(tgoto(scap, arg_cols, arg_rows), 1, PUTRAW);
674c80476e4SDavid E. O'Brien 	break;
675c80476e4SDavid E. O'Brien     default:
676c80476e4SDavid E. O'Brien 	/* This is wrong, but I will ignore it... */
677c80476e4SDavid E. O'Brien 	if (verbose)
678c80476e4SDavid E. O'Brien 	    stderror(ERR_NAME | ERR_TCARGS, cv, arg_need);
679c80476e4SDavid E. O'Brien 	/*FALLTHROUGH*/
680c80476e4SDavid E. O'Brien     case 2:
681c80476e4SDavid E. O'Brien 	v++;
682c80476e4SDavid E. O'Brien 	if (!*v || *v[0] == '\0') {
683c80476e4SDavid E. O'Brien 	    if (silent)
68445e5710bSMark Peek 		goto end;
685c80476e4SDavid E. O'Brien 	    else
686c80476e4SDavid E. O'Brien 		stderror(ERR_NAME | ERR_TCNARGS, cv, 2);
687c80476e4SDavid E. O'Brien 	}
688c80476e4SDavid E. O'Brien 	arg_cols = atoi(short2str(*v));
689c80476e4SDavid E. O'Brien 	v++;
690c80476e4SDavid E. O'Brien 	if (!*v || *v[0] == '\0') {
691c80476e4SDavid E. O'Brien 	    if (silent)
69245e5710bSMark Peek 		goto end;
693c80476e4SDavid E. O'Brien 	    else
694c80476e4SDavid E. O'Brien 		stderror(ERR_NAME | ERR_TCNARGS, cv, 2);
695c80476e4SDavid E. O'Brien 	}
696c80476e4SDavid E. O'Brien 	arg_rows = atoi(short2str(*v));
697c80476e4SDavid E. O'Brien 	v++;
698c80476e4SDavid E. O'Brien 	if (*v && *v[0]) {
699c80476e4SDavid E. O'Brien 	    if (silent)
70045e5710bSMark Peek 		goto end;
701c80476e4SDavid E. O'Brien 	    else
702c80476e4SDavid E. O'Brien 		stderror(ERR_NAME | ERR_TCARGS, cv, arg_need);
703c80476e4SDavid E. O'Brien 	}
704c80476e4SDavid E. O'Brien 	(void) tputs(tgoto(scap, arg_cols, arg_rows), arg_rows, PUTRAW);
705c80476e4SDavid E. O'Brien 	break;
706c80476e4SDavid E. O'Brien     }
70745e5710bSMark Peek  end_flush:
708c80476e4SDavid E. O'Brien     flush();
70945e5710bSMark Peek  end:
71045e5710bSMark Peek     cleanup_until(globbed);
711c80476e4SDavid E. O'Brien }
712c80476e4SDavid E. O'Brien 
71323338178SMark Peek int    GotTermCaps = 0;
714c80476e4SDavid E. O'Brien 
715c80476e4SDavid E. O'Brien static struct {
716c80476e4SDavid E. O'Brien     Char   *name;
717c80476e4SDavid E. O'Brien     int     key;
718c80476e4SDavid E. O'Brien     XmapVal fun;
719c80476e4SDavid E. O'Brien     int	    type;
720c80476e4SDavid E. O'Brien } arrow[] = {
721c80476e4SDavid E. O'Brien #define A_K_DN	0
72223338178SMark Peek     { STRdown,	T_kd, { 0 }, 0 },
723c80476e4SDavid E. O'Brien #define A_K_UP	1
72423338178SMark Peek     { STRup,	T_ku, { 0 }, 0 },
725c80476e4SDavid E. O'Brien #define A_K_LT	2
72623338178SMark Peek     { STRleft,	T_kl, { 0 }, 0 },
727c80476e4SDavid E. O'Brien #define A_K_RT	3
72823338178SMark Peek     { STRright, T_kr, { 0 }, 0 },
7293b6eaa7bSAndrey A. Chernov #define A_K_HO  4
73023338178SMark Peek     { STRhome,  T_kh, { 0 }, 0 },
7313b6eaa7bSAndrey A. Chernov #define A_K_EN  5
73223338178SMark Peek     { STRend,   T_at7, { 0 }, 0}
733c80476e4SDavid E. O'Brien };
7343b6eaa7bSAndrey A. Chernov #define A_K_NKEYS 6
735c80476e4SDavid E. O'Brien 
736c80476e4SDavid E. O'Brien void
ResetArrowKeys(void)73745e5710bSMark Peek ResetArrowKeys(void)
738c80476e4SDavid E. O'Brien {
739c80476e4SDavid E. O'Brien     arrow[A_K_DN].fun.cmd = F_DOWN_HIST;
740c80476e4SDavid E. O'Brien     arrow[A_K_DN].type    = XK_CMD;
741c80476e4SDavid E. O'Brien 
742c80476e4SDavid E. O'Brien     arrow[A_K_UP].fun.cmd = F_UP_HIST;
743c80476e4SDavid E. O'Brien     arrow[A_K_UP].type    = XK_CMD;
744c80476e4SDavid E. O'Brien 
745c80476e4SDavid E. O'Brien     arrow[A_K_LT].fun.cmd = F_CHARBACK;
746c80476e4SDavid E. O'Brien     arrow[A_K_LT].type    = XK_CMD;
747c80476e4SDavid E. O'Brien 
748c80476e4SDavid E. O'Brien     arrow[A_K_RT].fun.cmd = F_CHARFWD;
749c80476e4SDavid E. O'Brien     arrow[A_K_RT].type    = XK_CMD;
750c80476e4SDavid E. O'Brien 
7513b6eaa7bSAndrey A. Chernov     arrow[A_K_HO].fun.cmd = F_TOBEG;
7523b6eaa7bSAndrey A. Chernov     arrow[A_K_HO].type    = XK_CMD;
7533b6eaa7bSAndrey A. Chernov 
7543b6eaa7bSAndrey A. Chernov     arrow[A_K_EN].fun.cmd = F_TOEND;
7553b6eaa7bSAndrey A. Chernov     arrow[A_K_EN].type    = XK_CMD;
756c80476e4SDavid E. O'Brien }
757c80476e4SDavid E. O'Brien 
758c80476e4SDavid E. O'Brien void
DefaultArrowKeys(void)75945e5710bSMark Peek DefaultArrowKeys(void)
760c80476e4SDavid E. O'Brien {
761c80476e4SDavid E. O'Brien     static Char strA[] = {033, '[', 'A', '\0'};
762c80476e4SDavid E. O'Brien     static Char strB[] = {033, '[', 'B', '\0'};
763c80476e4SDavid E. O'Brien     static Char strC[] = {033, '[', 'C', '\0'};
764c80476e4SDavid E. O'Brien     static Char strD[] = {033, '[', 'D', '\0'};
7653b6eaa7bSAndrey A. Chernov     static Char strH[] = {033, '[', 'H', '\0'};
7663b6eaa7bSAndrey A. Chernov     static Char strF[] = {033, '[', 'F', '\0'};
767c80476e4SDavid E. O'Brien     static Char stOA[] = {033, 'O', 'A', '\0'};
768c80476e4SDavid E. O'Brien     static Char stOB[] = {033, 'O', 'B', '\0'};
769c80476e4SDavid E. O'Brien     static Char stOC[] = {033, 'O', 'C', '\0'};
770c80476e4SDavid E. O'Brien     static Char stOD[] = {033, 'O', 'D', '\0'};
7713b6eaa7bSAndrey A. Chernov     static Char stOH[] = {033, 'O', 'H', '\0'};
7723b6eaa7bSAndrey A. Chernov     static Char stOF[] = {033, 'O', 'F', '\0'};
773c80476e4SDavid E. O'Brien 
774c80476e4SDavid E. O'Brien     CStr cs;
7753b6eaa7bSAndrey A. Chernov #ifndef IS_ASCII
776c80476e4SDavid E. O'Brien     if (strA[0] == 033)
777c80476e4SDavid E. O'Brien     {
778c80476e4SDavid E. O'Brien 	strA[0] = CTL_ESC('\033');
779c80476e4SDavid E. O'Brien 	strB[0] = CTL_ESC('\033');
780c80476e4SDavid E. O'Brien 	strC[0] = CTL_ESC('\033');
781c80476e4SDavid E. O'Brien 	strD[0] = CTL_ESC('\033');
7823b6eaa7bSAndrey A. Chernov 	strH[0] = CTL_ESC('\033');
7833b6eaa7bSAndrey A. Chernov 	strF[0] = CTL_ESC('\033');
784c80476e4SDavid E. O'Brien 	stOA[0] = CTL_ESC('\033');
785c80476e4SDavid E. O'Brien 	stOB[0] = CTL_ESC('\033');
786c80476e4SDavid E. O'Brien 	stOC[0] = CTL_ESC('\033');
787c80476e4SDavid E. O'Brien 	stOD[0] = CTL_ESC('\033');
7883b6eaa7bSAndrey A. Chernov 	stOH[0] = CTL_ESC('\033');
7893b6eaa7bSAndrey A. Chernov 	stOF[0] = CTL_ESC('\033');
790c80476e4SDavid E. O'Brien     }
791c80476e4SDavid E. O'Brien #endif
792c80476e4SDavid E. O'Brien 
793c80476e4SDavid E. O'Brien     cs.len = 3;
794c80476e4SDavid E. O'Brien 
795c80476e4SDavid E. O'Brien     cs.buf = strA; AddXkey(&cs, &arrow[A_K_UP].fun, arrow[A_K_UP].type);
796c80476e4SDavid E. O'Brien     cs.buf = strB; AddXkey(&cs, &arrow[A_K_DN].fun, arrow[A_K_DN].type);
797c80476e4SDavid E. O'Brien     cs.buf = strC; AddXkey(&cs, &arrow[A_K_RT].fun, arrow[A_K_RT].type);
798c80476e4SDavid E. O'Brien     cs.buf = strD; AddXkey(&cs, &arrow[A_K_LT].fun, arrow[A_K_LT].type);
7993b6eaa7bSAndrey A. Chernov     cs.buf = strH; AddXkey(&cs, &arrow[A_K_HO].fun, arrow[A_K_HO].type);
8003b6eaa7bSAndrey A. Chernov     cs.buf = strF; AddXkey(&cs, &arrow[A_K_EN].fun, arrow[A_K_EN].type);
801c80476e4SDavid E. O'Brien     cs.buf = stOA; AddXkey(&cs, &arrow[A_K_UP].fun, arrow[A_K_UP].type);
802c80476e4SDavid E. O'Brien     cs.buf = stOB; AddXkey(&cs, &arrow[A_K_DN].fun, arrow[A_K_DN].type);
803c80476e4SDavid E. O'Brien     cs.buf = stOC; AddXkey(&cs, &arrow[A_K_RT].fun, arrow[A_K_RT].type);
804c80476e4SDavid E. O'Brien     cs.buf = stOD; AddXkey(&cs, &arrow[A_K_LT].fun, arrow[A_K_LT].type);
8053b6eaa7bSAndrey A. Chernov     cs.buf = stOH; AddXkey(&cs, &arrow[A_K_HO].fun, arrow[A_K_HO].type);
8063b6eaa7bSAndrey A. Chernov     cs.buf = stOF; AddXkey(&cs, &arrow[A_K_EN].fun, arrow[A_K_EN].type);
807c80476e4SDavid E. O'Brien 
808c80476e4SDavid E. O'Brien     if (VImode) {
809c80476e4SDavid E. O'Brien 	cs.len = 2;
810c80476e4SDavid E. O'Brien 	cs.buf = &strA[1]; AddXkey(&cs, &arrow[A_K_UP].fun, arrow[A_K_UP].type);
811c80476e4SDavid E. O'Brien 	cs.buf = &strB[1]; AddXkey(&cs, &arrow[A_K_DN].fun, arrow[A_K_DN].type);
812c80476e4SDavid E. O'Brien 	cs.buf = &strC[1]; AddXkey(&cs, &arrow[A_K_RT].fun, arrow[A_K_RT].type);
813c80476e4SDavid E. O'Brien 	cs.buf = &strD[1]; AddXkey(&cs, &arrow[A_K_LT].fun, arrow[A_K_LT].type);
8143b6eaa7bSAndrey A. Chernov 	cs.buf = &strH[1]; AddXkey(&cs, &arrow[A_K_HO].fun, arrow[A_K_HO].type);
8153b6eaa7bSAndrey A. Chernov 	cs.buf = &strF[1]; AddXkey(&cs, &arrow[A_K_EN].fun, arrow[A_K_EN].type);
816c80476e4SDavid E. O'Brien 	cs.buf = &stOA[1]; AddXkey(&cs, &arrow[A_K_UP].fun, arrow[A_K_UP].type);
817c80476e4SDavid E. O'Brien 	cs.buf = &stOB[1]; AddXkey(&cs, &arrow[A_K_DN].fun, arrow[A_K_DN].type);
818c80476e4SDavid E. O'Brien 	cs.buf = &stOC[1]; AddXkey(&cs, &arrow[A_K_RT].fun, arrow[A_K_RT].type);
819c80476e4SDavid E. O'Brien 	cs.buf = &stOD[1]; AddXkey(&cs, &arrow[A_K_LT].fun, arrow[A_K_LT].type);
8203b6eaa7bSAndrey A. Chernov 	cs.buf = &stOH[1]; AddXkey(&cs, &arrow[A_K_HO].fun, arrow[A_K_HO].type);
8213b6eaa7bSAndrey A. Chernov 	cs.buf = &stOF[1]; AddXkey(&cs, &arrow[A_K_EN].fun, arrow[A_K_EN].type);
822c80476e4SDavid E. O'Brien     }
823c80476e4SDavid E. O'Brien }
824c80476e4SDavid E. O'Brien 
825c80476e4SDavid E. O'Brien 
826c80476e4SDavid E. O'Brien int
SetArrowKeys(const CStr * name,XmapVal * fun,int type)82745e5710bSMark Peek SetArrowKeys(const CStr *name, XmapVal *fun, int type)
828c80476e4SDavid E. O'Brien {
829c80476e4SDavid E. O'Brien     int i;
8303b6eaa7bSAndrey A. Chernov     for (i = 0; i < A_K_NKEYS; i++)
831c80476e4SDavid E. O'Brien 	if (Strcmp(name->buf, arrow[i].name) == 0) {
832c80476e4SDavid E. O'Brien 	    arrow[i].fun  = *fun;
833c80476e4SDavid E. O'Brien 	    arrow[i].type = type;
834c80476e4SDavid E. O'Brien 	    return 0;
835c80476e4SDavid E. O'Brien 	}
836c80476e4SDavid E. O'Brien     return -1;
837c80476e4SDavid E. O'Brien }
838c80476e4SDavid E. O'Brien 
839c80476e4SDavid E. O'Brien int
IsArrowKey(Char * name)84045e5710bSMark Peek IsArrowKey(Char *name)
841c80476e4SDavid E. O'Brien {
842c80476e4SDavid E. O'Brien     int i;
8433b6eaa7bSAndrey A. Chernov     for (i = 0; i < A_K_NKEYS; i++)
844c80476e4SDavid E. O'Brien 	if (Strcmp(name, arrow[i].name) == 0)
845c80476e4SDavid E. O'Brien 	    return 1;
846c80476e4SDavid E. O'Brien     return 0;
847c80476e4SDavid E. O'Brien }
848c80476e4SDavid E. O'Brien 
849c80476e4SDavid E. O'Brien int
ClearArrowKeys(const CStr * name)85045e5710bSMark Peek ClearArrowKeys(const CStr *name)
851c80476e4SDavid E. O'Brien {
852c80476e4SDavid E. O'Brien     int i;
8533b6eaa7bSAndrey A. Chernov     for (i = 0; i < A_K_NKEYS; i++)
854c80476e4SDavid E. O'Brien 	if (Strcmp(name->buf, arrow[i].name) == 0) {
855c80476e4SDavid E. O'Brien 	    arrow[i].type = XK_NOD;
856c80476e4SDavid E. O'Brien 	    return 0;
857c80476e4SDavid E. O'Brien 	}
858c80476e4SDavid E. O'Brien     return -1;
859c80476e4SDavid E. O'Brien }
860c80476e4SDavid E. O'Brien 
861c80476e4SDavid E. O'Brien void
PrintArrowKeys(const CStr * name)86245e5710bSMark Peek PrintArrowKeys(const CStr *name)
863c80476e4SDavid E. O'Brien {
864c80476e4SDavid E. O'Brien     int i;
865c80476e4SDavid E. O'Brien 
8663b6eaa7bSAndrey A. Chernov     for (i = 0; i < A_K_NKEYS; i++)
867c80476e4SDavid E. O'Brien 	if (name->len == 0 || Strcmp(name->buf, arrow[i].name) == 0)
86845e5710bSMark Peek 	    if (arrow[i].type != XK_NOD)
86945e5710bSMark Peek 		printOne(arrow[i].name, &arrow[i].fun, arrow[i].type);
870c80476e4SDavid E. O'Brien }
871c80476e4SDavid E. O'Brien 
872c80476e4SDavid E. O'Brien 
873c80476e4SDavid E. O'Brien void
BindArrowKeys(void)87445e5710bSMark Peek BindArrowKeys(void)
875c80476e4SDavid E. O'Brien {
876c80476e4SDavid E. O'Brien     KEYCMD *map, *dmap;
877c80476e4SDavid E. O'Brien     int     i, j;
878c80476e4SDavid E. O'Brien     char   *p;
879c80476e4SDavid E. O'Brien     CStr    cs;
880c80476e4SDavid E. O'Brien 
881c80476e4SDavid E. O'Brien     if (!GotTermCaps)
882c80476e4SDavid E. O'Brien 	return;
883c80476e4SDavid E. O'Brien     map = VImode ? CcAltMap : CcKeyMap;
884c80476e4SDavid E. O'Brien     dmap = VImode ? CcViCmdMap : CcEmacsMap;
885c80476e4SDavid E. O'Brien 
886c80476e4SDavid E. O'Brien     DefaultArrowKeys();
887c80476e4SDavid E. O'Brien 
8883b6eaa7bSAndrey A. Chernov     for (i = 0; i < A_K_NKEYS; i++) {
889c80476e4SDavid E. O'Brien 	p = tstr[arrow[i].key].str;
890c80476e4SDavid E. O'Brien 	if (p && *p) {
891c80476e4SDavid E. O'Brien 	    j = (unsigned char) *p;
892c80476e4SDavid E. O'Brien 	    cs.buf = str2short(p);
893c80476e4SDavid E. O'Brien 	    cs.len = Strlen(cs.buf);
894c80476e4SDavid E. O'Brien 	    /*
895c80476e4SDavid E. O'Brien 	     * Assign the arrow keys only if:
896c80476e4SDavid E. O'Brien 	     *
897c80476e4SDavid E. O'Brien 	     * 1. They are multi-character arrow keys and the user
898c80476e4SDavid E. O'Brien 	     *    has not re-assigned the leading character, or
899c80476e4SDavid E. O'Brien 	     *    has re-assigned the leading character to be F_XKEY
900c80476e4SDavid E. O'Brien 	     * 2. They are single arrow keys pointing to an unassigned key.
901c80476e4SDavid E. O'Brien 	     */
902c80476e4SDavid E. O'Brien 	    if (arrow[i].type == XK_NOD) {
903c80476e4SDavid E. O'Brien 		ClearXkey(map, &cs);
904c80476e4SDavid E. O'Brien 	    }
905c80476e4SDavid E. O'Brien 	    else {
906c80476e4SDavid E. O'Brien 		if (p[1] && (dmap[j] == map[j] || map[j] == F_XKEY)) {
907c80476e4SDavid E. O'Brien 		    AddXkey(&cs, &arrow[i].fun, arrow[i].type);
908c80476e4SDavid E. O'Brien 		    map[j] = F_XKEY;
909c80476e4SDavid E. O'Brien 		}
910c80476e4SDavid E. O'Brien 		else if (map[j] == F_UNASSIGNED) {
911c80476e4SDavid E. O'Brien 		    ClearXkey(map, &cs);
912c80476e4SDavid E. O'Brien 		    if (arrow[i].type == XK_CMD)
913c80476e4SDavid E. O'Brien 			map[j] = arrow[i].fun.cmd;
914c80476e4SDavid E. O'Brien 		    else
915c80476e4SDavid E. O'Brien 			AddXkey(&cs, &arrow[i].fun, arrow[i].type);
916c80476e4SDavid E. O'Brien 		}
917c80476e4SDavid E. O'Brien 	    }
918c80476e4SDavid E. O'Brien 	}
919c80476e4SDavid E. O'Brien     }
920c80476e4SDavid E. O'Brien }
921c80476e4SDavid E. O'Brien 
922c80476e4SDavid E. O'Brien static Char cur_atr = 0;	/* current attributes */
923c80476e4SDavid E. O'Brien 
924c80476e4SDavid E. O'Brien void
SetAttributes(Char atr)92545e5710bSMark Peek SetAttributes(Char atr)
926c80476e4SDavid E. O'Brien {
927c80476e4SDavid E. O'Brien     atr &= ATTRIBUTES;
928c80476e4SDavid E. O'Brien     if (atr != cur_atr) {
929c80476e4SDavid E. O'Brien 	if (me_all && GoodStr(T_me)) {
930c80476e4SDavid E. O'Brien 	    if (((cur_atr & BOLD) && !(atr & BOLD)) ||
931c80476e4SDavid E. O'Brien 		((cur_atr & UNDER) && !(atr & UNDER)) ||
932c80476e4SDavid E. O'Brien 		((cur_atr & STANDOUT) && !(atr & STANDOUT))) {
933c80476e4SDavid E. O'Brien 		(void) tputs(Str(T_me), 1, PUTPURE);
934c80476e4SDavid E. O'Brien 		cur_atr = 0;
935c80476e4SDavid E. O'Brien 	    }
936c80476e4SDavid E. O'Brien 	}
937c80476e4SDavid E. O'Brien 	if ((atr & BOLD) != (cur_atr & BOLD)) {
938c80476e4SDavid E. O'Brien 	    if (atr & BOLD) {
939c80476e4SDavid E. O'Brien 		if (GoodStr(T_md) && GoodStr(T_me)) {
940c80476e4SDavid E. O'Brien 		    (void) tputs(Str(T_md), 1, PUTPURE);
941c80476e4SDavid E. O'Brien 		    cur_atr |= BOLD;
942c80476e4SDavid E. O'Brien 		}
943c80476e4SDavid E. O'Brien 	    }
944c80476e4SDavid E. O'Brien 	    else {
945c80476e4SDavid E. O'Brien 		if (GoodStr(T_md) && GoodStr(T_me)) {
946c80476e4SDavid E. O'Brien 		    (void) tputs(Str(T_me), 1, PUTPURE);
947c80476e4SDavid E. O'Brien 		    if ((cur_atr & STANDOUT) && GoodStr(T_se)) {
948c80476e4SDavid E. O'Brien 			(void) tputs(Str(T_se), 1, PUTPURE);
949c80476e4SDavid E. O'Brien 			cur_atr &= ~STANDOUT;
950c80476e4SDavid E. O'Brien 		    }
951c80476e4SDavid E. O'Brien 		    if ((cur_atr & UNDER) && GoodStr(T_ue)) {
952c80476e4SDavid E. O'Brien 			(void) tputs(Str(T_ue), 1, PUTPURE);
953c80476e4SDavid E. O'Brien 			cur_atr &= ~UNDER;
954c80476e4SDavid E. O'Brien 		    }
955c80476e4SDavid E. O'Brien 		    cur_atr &= ~BOLD;
956c80476e4SDavid E. O'Brien 		}
957c80476e4SDavid E. O'Brien 	    }
958c80476e4SDavid E. O'Brien 	}
959c80476e4SDavid E. O'Brien 	if ((atr & STANDOUT) != (cur_atr & STANDOUT)) {
960c80476e4SDavid E. O'Brien 	    if (atr & STANDOUT) {
961c80476e4SDavid E. O'Brien 		if (GoodStr(T_so) && GoodStr(T_se)) {
962c80476e4SDavid E. O'Brien 		    (void) tputs(Str(T_so), 1, PUTPURE);
963c80476e4SDavid E. O'Brien 		    cur_atr |= STANDOUT;
964c80476e4SDavid E. O'Brien 		}
965c80476e4SDavid E. O'Brien 	    }
966c80476e4SDavid E. O'Brien 	    else {
967c80476e4SDavid E. O'Brien 		if (GoodStr(T_se)) {
968c80476e4SDavid E. O'Brien 		    (void) tputs(Str(T_se), 1, PUTPURE);
969c80476e4SDavid E. O'Brien 		    cur_atr &= ~STANDOUT;
970c80476e4SDavid E. O'Brien 		}
971c80476e4SDavid E. O'Brien 	    }
972c80476e4SDavid E. O'Brien 	}
973c80476e4SDavid E. O'Brien 	if ((atr & UNDER) != (cur_atr & UNDER)) {
974c80476e4SDavid E. O'Brien 	    if (atr & UNDER) {
975c80476e4SDavid E. O'Brien 		if (GoodStr(T_us) && GoodStr(T_ue)) {
976c80476e4SDavid E. O'Brien 		    (void) tputs(Str(T_us), 1, PUTPURE);
977c80476e4SDavid E. O'Brien 		    cur_atr |= UNDER;
978c80476e4SDavid E. O'Brien 		}
979c80476e4SDavid E. O'Brien 	    }
980c80476e4SDavid E. O'Brien 	    else {
981c80476e4SDavid E. O'Brien 		if (GoodStr(T_ue)) {
982c80476e4SDavid E. O'Brien 		    (void) tputs(Str(T_ue), 1, PUTPURE);
983c80476e4SDavid E. O'Brien 		    cur_atr &= ~UNDER;
984c80476e4SDavid E. O'Brien 		}
985c80476e4SDavid E. O'Brien 	    }
986c80476e4SDavid E. O'Brien 	}
987c80476e4SDavid E. O'Brien     }
988c80476e4SDavid E. O'Brien }
989c80476e4SDavid E. O'Brien 
99045e5710bSMark Peek int highlighting = 0;
99145e5710bSMark Peek 
99245e5710bSMark Peek void
StartHighlight(void)993*19d2e3deSDmitry Chagin StartHighlight(void)
99445e5710bSMark Peek {
99545e5710bSMark Peek     (void) tputs(Str(T_mr), 1, PUTPURE);
99645e5710bSMark Peek     highlighting = 1;
99745e5710bSMark Peek }
99845e5710bSMark Peek 
99945e5710bSMark Peek void
StopHighlight(void)1000*19d2e3deSDmitry Chagin StopHighlight(void)
100145e5710bSMark Peek {
100245e5710bSMark Peek     (void) tputs(Str(T_me), 1, PUTPURE);
100345e5710bSMark Peek     highlighting = 0;
100445e5710bSMark Peek }
100545e5710bSMark Peek 
1006c80476e4SDavid E. O'Brien /* PWP 6-27-88 -- if the tty driver thinks that we can tab, we ask termcap */
1007c80476e4SDavid E. O'Brien int
CanWeTab(void)100845e5710bSMark Peek CanWeTab(void)
1009c80476e4SDavid E. O'Brien {
1010c80476e4SDavid E. O'Brien     return (Val(T_pt));
1011c80476e4SDavid E. O'Brien }
1012c80476e4SDavid E. O'Brien 
101345e5710bSMark Peek /* move to line <where> (first line == 0) as efficiently as possible; */
1014c80476e4SDavid E. O'Brien void
MoveToLine(int where)101545e5710bSMark Peek MoveToLine(int where)
1016c80476e4SDavid E. O'Brien {
1017c80476e4SDavid E. O'Brien     int     del;
1018c80476e4SDavid E. O'Brien 
1019c80476e4SDavid E. O'Brien     if (where == CursorV)
1020c80476e4SDavid E. O'Brien 	return;
1021c80476e4SDavid E. O'Brien 
1022c80476e4SDavid E. O'Brien     if (where > TermV) {
1023c80476e4SDavid E. O'Brien #ifdef DEBUG_SCREEN
1024c80476e4SDavid E. O'Brien 	xprintf("MoveToLine: where is ridiculous: %d\r\n", where);
1025c80476e4SDavid E. O'Brien 	flush();
1026c80476e4SDavid E. O'Brien #endif /* DEBUG_SCREEN */
1027c80476e4SDavid E. O'Brien 	return;
1028c80476e4SDavid E. O'Brien     }
1029c80476e4SDavid E. O'Brien 
1030c80476e4SDavid E. O'Brien     del = where - CursorV;
1031c80476e4SDavid E. O'Brien 
1032c80476e4SDavid E. O'Brien     if (del > 0) {
1033c80476e4SDavid E. O'Brien 	while (del > 0) {
1034c80476e4SDavid E. O'Brien 	    if ((T_Margin & MARGIN_AUTO) && Display[CursorV][0] != '\0') {
103523338178SMark Peek 		size_t h;
103623338178SMark Peek 
103723338178SMark Peek 		for (h = TermH - 1; h > 0 && Display[CursorV][h] == CHAR_DBWIDTH;
103823338178SMark Peek 		     h--)
103923338178SMark Peek 		    ;
1040c80476e4SDavid E. O'Brien 		/* move without newline */
104123338178SMark Peek 		MoveToChar(h);
104223338178SMark Peek 		so_write(&Display[CursorV][CursorH], TermH - CursorH); /* updates CursorH/V*/
1043c80476e4SDavid E. O'Brien 		del--;
1044c80476e4SDavid E. O'Brien 	    }
1045c80476e4SDavid E. O'Brien 	    else {
1046c80476e4SDavid E. O'Brien 		if ((del > 1) && GoodStr(T_DO)) {
1047c80476e4SDavid E. O'Brien 		    (void) tputs(tgoto(Str(T_DO), del, del), del, PUTPURE);
1048c80476e4SDavid E. O'Brien 		    del = 0;
1049c80476e4SDavid E. O'Brien 		}
1050c80476e4SDavid E. O'Brien 		else {
1051c80476e4SDavid E. O'Brien 		    for ( ; del > 0; del--)
1052c80476e4SDavid E. O'Brien 			(void) putraw('\n');
1053c80476e4SDavid E. O'Brien 		    CursorH = 0;	/* because the \n will become \r\n */
1054c80476e4SDavid E. O'Brien 		}
1055c80476e4SDavid E. O'Brien 	    }
1056c80476e4SDavid E. O'Brien 	}
1057c80476e4SDavid E. O'Brien     }
1058c80476e4SDavid E. O'Brien     else {			/* del < 0 */
1059c80476e4SDavid E. O'Brien 	if (GoodStr(T_UP) && (-del > 1 || !GoodStr(T_up)))
1060c80476e4SDavid E. O'Brien 	    (void) tputs(tgoto(Str(T_UP), -del, -del), -del, PUTPURE);
1061c80476e4SDavid E. O'Brien 	else {
1062c80476e4SDavid E. O'Brien 	    int i;
1063c80476e4SDavid E. O'Brien 	    if (GoodStr(T_up))
1064c80476e4SDavid E. O'Brien 		for (i = 0; i < -del; i++)
1065c80476e4SDavid E. O'Brien 		    (void) tputs(Str(T_up), 1, PUTPURE);
1066c80476e4SDavid E. O'Brien 	}
1067c80476e4SDavid E. O'Brien     }
1068c80476e4SDavid E. O'Brien     CursorV = where;		/* now where is here */
1069c80476e4SDavid E. O'Brien }
1070c80476e4SDavid E. O'Brien 
1071c80476e4SDavid E. O'Brien void
MoveToChar(int where)107245e5710bSMark Peek MoveToChar(int where)		/* move to character position (where) */
1073c80476e4SDavid E. O'Brien {				/* as efficiently as possible */
1074c80476e4SDavid E. O'Brien     int     del;
1075c80476e4SDavid E. O'Brien 
1076c80476e4SDavid E. O'Brien mc_again:
1077c80476e4SDavid E. O'Brien     if (where == CursorH)
1078c80476e4SDavid E. O'Brien 	return;
1079c80476e4SDavid E. O'Brien 
1080c80476e4SDavid E. O'Brien     if (where >= TermH) {
1081c80476e4SDavid E. O'Brien #ifdef DEBUG_SCREEN
1082c80476e4SDavid E. O'Brien 	xprintf("MoveToChar: where is riduculous: %d\r\n", where);
1083c80476e4SDavid E. O'Brien 	flush();
1084c80476e4SDavid E. O'Brien #endif /* DEBUG_SCREEN */
1085c80476e4SDavid E. O'Brien 	return;
1086c80476e4SDavid E. O'Brien     }
1087c80476e4SDavid E. O'Brien 
1088c80476e4SDavid E. O'Brien     if (!where) {		/* if where is first column */
1089c80476e4SDavid E. O'Brien 	(void) putraw('\r');	/* do a CR */
1090c80476e4SDavid E. O'Brien 	CursorH = 0;
1091c80476e4SDavid E. O'Brien 	return;
1092c80476e4SDavid E. O'Brien     }
1093c80476e4SDavid E. O'Brien 
1094c80476e4SDavid E. O'Brien     del = where - CursorH;
1095c80476e4SDavid E. O'Brien 
1096c80476e4SDavid E. O'Brien     if ((del < -4 || del > 4) && GoodStr(T_ch))
1097c80476e4SDavid E. O'Brien 	/* go there directly */
1098c80476e4SDavid E. O'Brien 	(void) tputs(tgoto(Str(T_ch), where, where), where, PUTPURE);
1099c80476e4SDavid E. O'Brien     else {
1100c80476e4SDavid E. O'Brien 	int i;
1101c80476e4SDavid E. O'Brien 	if (del > 0) {		/* moving forward */
1102c80476e4SDavid E. O'Brien 	    if ((del > 4) && GoodStr(T_RI))
1103c80476e4SDavid E. O'Brien 		(void) tputs(tgoto(Str(T_RI), del, del), del, PUTPURE);
1104c80476e4SDavid E. O'Brien 	    else {
11053b6eaa7bSAndrey A. Chernov 		/* if I can do tabs, use them */
110623338178SMark Peek 		if (T_Tabs) {
110723338178SMark Peek 		    if ((CursorH & 0370) != (where & ~0x7)
110823338178SMark Peek 			&& Display[CursorV][where & ~0x7] != CHAR_DBWIDTH) {
1109c80476e4SDavid E. O'Brien 			/* if not within tab stop */
111023338178SMark Peek 			for (i = (CursorH & 0370); i < (where & ~0x7); i += 8)
1111c80476e4SDavid E. O'Brien 			    (void) putraw('\t');	/* then tab over */
111223338178SMark Peek 			CursorH = where & ~0x7;
1113c80476e4SDavid E. O'Brien 			/* Note: considering that we often want to go to
1114c80476e4SDavid E. O'Brien 			   TermH - 1 for the wrapping, it would be nice to
1115c80476e4SDavid E. O'Brien 			   optimize this case by tabbing to the last column
1116c80476e4SDavid E. O'Brien 			   - but this doesn't work for all terminals! */
1117c80476e4SDavid E. O'Brien 		    }
1118c80476e4SDavid E. O'Brien 		}
1119c80476e4SDavid E. O'Brien 		/* it's usually cheaper to just write the chars, so we do. */
1120c80476e4SDavid E. O'Brien 
1121c80476e4SDavid E. O'Brien 		/* NOTE THAT so_write() WILL CHANGE CursorH!!! */
1122c80476e4SDavid E. O'Brien 		so_write(&Display[CursorV][CursorH], where - CursorH);
1123c80476e4SDavid E. O'Brien 
1124c80476e4SDavid E. O'Brien 	    }
1125c80476e4SDavid E. O'Brien 	}
1126c80476e4SDavid E. O'Brien 	else {			/* del < 0 := moving backward */
1127c80476e4SDavid E. O'Brien 	    if ((-del > 4) && GoodStr(T_LE))
1128c80476e4SDavid E. O'Brien 		(void) tputs(tgoto(Str(T_LE), -del, -del), -del, PUTPURE);
1129c80476e4SDavid E. O'Brien 	    else {		/* can't go directly there */
1130c80476e4SDavid E. O'Brien 		/* if the "cost" is greater than the "cost" from col 0 */
1131c80476e4SDavid E. O'Brien 		if (T_Tabs ? (-del > ((where >> 3) + (where & 07)))
1132c80476e4SDavid E. O'Brien 		    : (-del > where)) {
1133c80476e4SDavid E. O'Brien 		    (void) putraw('\r');	/* do a CR */
1134c80476e4SDavid E. O'Brien 		    CursorH = 0;
1135c80476e4SDavid E. O'Brien 		    goto mc_again;	/* and try again */
1136c80476e4SDavid E. O'Brien 		}
1137c80476e4SDavid E. O'Brien 		for (i = 0; i < -del; i++)
1138c80476e4SDavid E. O'Brien 		    (void) putraw('\b');
1139c80476e4SDavid E. O'Brien 	    }
1140c80476e4SDavid E. O'Brien 	}
1141c80476e4SDavid E. O'Brien     }
1142c80476e4SDavid E. O'Brien     CursorH = where;		/* now where is here */
1143c80476e4SDavid E. O'Brien }
1144c80476e4SDavid E. O'Brien 
1145c80476e4SDavid E. O'Brien void
so_write(Char * cp,int n)114645e5710bSMark Peek so_write(Char *cp, int n)
1147c80476e4SDavid E. O'Brien {
114845e5710bSMark Peek     int cur_pos, prompt_len = 0, region_start = 0, region_end = 0;
114945e5710bSMark Peek 
1150c80476e4SDavid E. O'Brien     if (n <= 0)
1151c80476e4SDavid E. O'Brien 	return;			/* catch bugs */
1152c80476e4SDavid E. O'Brien 
1153c80476e4SDavid E. O'Brien     if (n > TermH) {
1154c80476e4SDavid E. O'Brien #ifdef DEBUG_SCREEN
1155c80476e4SDavid E. O'Brien 	xprintf("so_write: n is riduculous: %d\r\n", n);
1156c80476e4SDavid E. O'Brien 	flush();
1157c80476e4SDavid E. O'Brien #endif /* DEBUG_SCREEN */
1158c80476e4SDavid E. O'Brien 	return;
1159c80476e4SDavid E. O'Brien     }
1160c80476e4SDavid E. O'Brien 
116145e5710bSMark Peek     if (adrof(STRhighlight)) {
116245e5710bSMark Peek 	/* find length of prompt */
116345e5710bSMark Peek 	Char *promptc;
116445e5710bSMark Peek 	for (promptc = Prompt; *promptc; promptc++);
116545e5710bSMark Peek 	prompt_len = promptc - Prompt;
116645e5710bSMark Peek 
116745e5710bSMark Peek 	/* find region start and end points */
116845e5710bSMark Peek 	if (IncMatchLen) {
116945e5710bSMark Peek 	    region_start = (Cursor - InputBuf) + prompt_len;
117045e5710bSMark Peek 	    region_end = region_start + IncMatchLen;
117145e5710bSMark Peek 	} else if (MarkIsSet) {
117245e5710bSMark Peek 	    region_start = (min(Cursor, Mark) - InputBuf) + prompt_len;
117345e5710bSMark Peek 	    region_end   = (max(Cursor, Mark) - InputBuf) + prompt_len;
117445e5710bSMark Peek 	}
117545e5710bSMark Peek     }
117645e5710bSMark Peek 
1177c80476e4SDavid E. O'Brien     do {
117845e5710bSMark Peek 	if (adrof(STRhighlight)) {
117945e5710bSMark Peek 	    cur_pos = CursorV * TermH + CursorH;
118045e5710bSMark Peek 	    if (!highlighting &&
118145e5710bSMark Peek 		cur_pos >= region_start && cur_pos < region_end)
118245e5710bSMark Peek 		StartHighlight();
118345e5710bSMark Peek 	    else if (highlighting && cur_pos >= region_end)
118445e5710bSMark Peek 		StopHighlight();
118545e5710bSMark Peek 
118645e5710bSMark Peek 	    /* don't highlight over the cursor. the highlighting's reverse
118745e5710bSMark Peek 	     * video would cancel it out. :P */
118845e5710bSMark Peek 	    if (highlighting && cur_pos == (Cursor - InputBuf) + prompt_len)
118945e5710bSMark Peek 		StopHighlight();
119045e5710bSMark Peek 	}
119145e5710bSMark Peek 
119223338178SMark Peek 	if (*cp != CHAR_DBWIDTH) {
1193c80476e4SDavid E. O'Brien 	    if (*cp & LITERAL) {
1194c80476e4SDavid E. O'Brien 		Char   *d;
1195c80476e4SDavid E. O'Brien #ifdef DEBUG_LITERAL
119623338178SMark Peek 		xprintf("so: litnum %d\r\n", (int)(*cp & ~LITERAL));
1197c80476e4SDavid E. O'Brien #endif /* DEBUG_LITERAL */
119823338178SMark Peek 		for (d = litptr + (*cp & ~LITERAL) * LIT_FACTOR; *d; d++)
119923338178SMark Peek 		    (void) putwraw(*d);
1200c80476e4SDavid E. O'Brien 	    }
1201c80476e4SDavid E. O'Brien 	    else
120223338178SMark Peek 		(void) putwraw(*cp);
120323338178SMark Peek 	}
120423338178SMark Peek 	cp++;
1205c80476e4SDavid E. O'Brien 	CursorH++;
1206c80476e4SDavid E. O'Brien     } while (--n);
1207c80476e4SDavid E. O'Brien 
120845e5710bSMark Peek     if (adrof(STRhighlight) && highlighting)
120945e5710bSMark Peek 	StopHighlight();
121045e5710bSMark Peek 
1211c80476e4SDavid E. O'Brien     if (CursorH >= TermH) { /* wrap? */
1212c80476e4SDavid E. O'Brien 	if (T_Margin & MARGIN_AUTO) { /* yes */
1213c80476e4SDavid E. O'Brien 	    CursorH = 0;
1214c80476e4SDavid E. O'Brien 	    CursorV++;
1215c80476e4SDavid E. O'Brien 	    if (T_Margin & MARGIN_MAGIC) {
1216c80476e4SDavid E. O'Brien 		/* force the wrap to avoid the "magic" situation */
121745e5710bSMark Peek 		Char xc;
121845e5710bSMark Peek 		if ((xc = Display[CursorV][CursorH]) != '\0') {
121945e5710bSMark Peek 		    so_write(&xc, 1);
122023338178SMark Peek 		    while (Display[CursorV][CursorH] == CHAR_DBWIDTH)
122123338178SMark Peek 			CursorH++;
122223338178SMark Peek 		}
122323338178SMark Peek 		else {
1224c80476e4SDavid E. O'Brien 		    (void) putraw(' ');
1225c80476e4SDavid E. O'Brien 		    CursorH = 1;
1226c80476e4SDavid E. O'Brien 		}
1227c80476e4SDavid E. O'Brien 	    }
122823338178SMark Peek 	}
1229c80476e4SDavid E. O'Brien 	else			/* no wrap, but cursor stays on screen */
1230c80476e4SDavid E. O'Brien 	    CursorH = TermH - 1;
1231c80476e4SDavid E. O'Brien     }
1232c80476e4SDavid E. O'Brien }
1233c80476e4SDavid E. O'Brien 
1234c80476e4SDavid E. O'Brien 
1235c80476e4SDavid E. O'Brien void
DeleteChars(int num)123645e5710bSMark Peek DeleteChars(int num)		/* deletes <num> characters */
1237c80476e4SDavid E. O'Brien {
1238c80476e4SDavid E. O'Brien     if (num <= 0)
1239c80476e4SDavid E. O'Brien 	return;
1240c80476e4SDavid E. O'Brien 
1241c80476e4SDavid E. O'Brien     if (!T_CanDel) {
1242c80476e4SDavid E. O'Brien #ifdef DEBUG_EDIT
1243c80476e4SDavid E. O'Brien 	xprintf(CGETS(7, 16, "ERROR: cannot delete\r\n"));
1244c80476e4SDavid E. O'Brien #endif /* DEBUG_EDIT */
1245c80476e4SDavid E. O'Brien 	flush();
1246c80476e4SDavid E. O'Brien 	return;
1247c80476e4SDavid E. O'Brien     }
1248c80476e4SDavid E. O'Brien 
1249c80476e4SDavid E. O'Brien     if (num > TermH) {
1250c80476e4SDavid E. O'Brien #ifdef DEBUG_SCREEN
1251c80476e4SDavid E. O'Brien 	xprintf(CGETS(7, 17, "DeleteChars: num is riduculous: %d\r\n"), num);
1252c80476e4SDavid E. O'Brien 	flush();
1253c80476e4SDavid E. O'Brien #endif /* DEBUG_SCREEN */
1254c80476e4SDavid E. O'Brien 	return;
1255c80476e4SDavid E. O'Brien     }
1256c80476e4SDavid E. O'Brien 
1257c80476e4SDavid E. O'Brien     if (GoodStr(T_DC))		/* if I have multiple delete */
1258c80476e4SDavid E. O'Brien 	if ((num > 1) || !GoodStr(T_dc)) {	/* if dc would be more expen. */
1259c80476e4SDavid E. O'Brien 	    (void) tputs(tgoto(Str(T_DC), num, num), num, PUTPURE);
1260c80476e4SDavid E. O'Brien 	    return;
1261c80476e4SDavid E. O'Brien 	}
1262c80476e4SDavid E. O'Brien 
1263c80476e4SDavid E. O'Brien     if (GoodStr(T_dm))		/* if I have delete mode */
1264c80476e4SDavid E. O'Brien 	(void) tputs(Str(T_dm), 1, PUTPURE);
1265c80476e4SDavid E. O'Brien 
1266c80476e4SDavid E. O'Brien     if (GoodStr(T_dc))		/* else do one at a time */
1267c80476e4SDavid E. O'Brien 	while (num--)
1268c80476e4SDavid E. O'Brien 	    (void) tputs(Str(T_dc), 1, PUTPURE);
1269c80476e4SDavid E. O'Brien 
1270c80476e4SDavid E. O'Brien     if (GoodStr(T_ed))		/* if I have delete mode */
1271c80476e4SDavid E. O'Brien 	(void) tputs(Str(T_ed), 1, PUTPURE);
1272c80476e4SDavid E. O'Brien }
1273c80476e4SDavid E. O'Brien 
127445e5710bSMark Peek /* Puts terminal in insert character mode, or inserts num characters in the
127545e5710bSMark Peek    line */
1276c80476e4SDavid E. O'Brien void
Insert_write(Char * cp,int num)127745e5710bSMark Peek Insert_write(Char *cp, int num)
1278c80476e4SDavid E. O'Brien {
1279c80476e4SDavid E. O'Brien     if (num <= 0)
1280c80476e4SDavid E. O'Brien 	return;
1281c80476e4SDavid E. O'Brien     if (!T_CanIns) {
1282c80476e4SDavid E. O'Brien #ifdef DEBUG_EDIT
1283c80476e4SDavid E. O'Brien 	xprintf(CGETS(7, 18, "ERROR: cannot insert\r\n"));
1284c80476e4SDavid E. O'Brien #endif /* DEBUG_EDIT */
1285c80476e4SDavid E. O'Brien 	flush();
1286c80476e4SDavid E. O'Brien 	return;
1287c80476e4SDavid E. O'Brien     }
1288c80476e4SDavid E. O'Brien 
1289c80476e4SDavid E. O'Brien     if (num > TermH) {
1290c80476e4SDavid E. O'Brien #ifdef DEBUG_SCREEN
1291c80476e4SDavid E. O'Brien 	xprintf(CGETS(7, 19, "StartInsert: num is riduculous: %d\r\n"), num);
1292c80476e4SDavid E. O'Brien 	flush();
1293c80476e4SDavid E. O'Brien #endif /* DEBUG_SCREEN */
1294c80476e4SDavid E. O'Brien 	return;
1295c80476e4SDavid E. O'Brien     }
1296c80476e4SDavid E. O'Brien 
1297c80476e4SDavid E. O'Brien     if (GoodStr(T_IC))		/* if I have multiple insert */
1298c80476e4SDavid E. O'Brien 	if ((num > 1) || !GoodStr(T_ic)) {	/* if ic would be more expen. */
1299c80476e4SDavid E. O'Brien 	    (void) tputs(tgoto(Str(T_IC), num, num), num, PUTPURE);
1300c80476e4SDavid E. O'Brien 	    so_write(cp, num);	/* this updates CursorH/V */
1301c80476e4SDavid E. O'Brien 	    return;
1302c80476e4SDavid E. O'Brien 	}
1303c80476e4SDavid E. O'Brien 
1304c80476e4SDavid E. O'Brien     if (GoodStr(T_im) && GoodStr(T_ei)) { /* if I have insert mode */
1305c80476e4SDavid E. O'Brien 	(void) tputs(Str(T_im), 1, PUTPURE);
1306c80476e4SDavid E. O'Brien 
130723338178SMark Peek 	so_write(cp, num);	/* this updates CursorH/V */
1308c80476e4SDavid E. O'Brien 
1309c80476e4SDavid E. O'Brien 	if (GoodStr(T_ip))	/* have to make num chars insert */
1310c80476e4SDavid E. O'Brien 	    (void) tputs(Str(T_ip), 1, PUTPURE);
1311c80476e4SDavid E. O'Brien 
1312c80476e4SDavid E. O'Brien 	(void) tputs(Str(T_ei), 1, PUTPURE);
1313c80476e4SDavid E. O'Brien 	return;
1314c80476e4SDavid E. O'Brien     }
1315c80476e4SDavid E. O'Brien 
1316c80476e4SDavid E. O'Brien     do {
1317c80476e4SDavid E. O'Brien 	if (GoodStr(T_ic))	/* have to make num chars insert */
1318c80476e4SDavid E. O'Brien 	    (void) tputs(Str(T_ic), 1, PUTPURE);	/* insert a char */
1319c80476e4SDavid E. O'Brien 
132023338178SMark Peek 	so_write(cp++, 1);	/* this updates CursorH/V */
1321c80476e4SDavid E. O'Brien 
1322c80476e4SDavid E. O'Brien 	if (GoodStr(T_ip))	/* have to make num chars insert */
1323c80476e4SDavid E. O'Brien 	    (void) tputs(Str(T_ip), 1, PUTPURE);/* pad the inserted char */
1324c80476e4SDavid E. O'Brien 
1325c80476e4SDavid E. O'Brien     } while (--num);
1326c80476e4SDavid E. O'Brien 
1327c80476e4SDavid E. O'Brien }
1328c80476e4SDavid E. O'Brien 
132945e5710bSMark Peek /* clear to end of line.  There are num characters to clear */
1330c80476e4SDavid E. O'Brien void
ClearEOL(int num)133145e5710bSMark Peek ClearEOL(int num)
1332c80476e4SDavid E. O'Brien {
133323338178SMark Peek     int i;
1334c80476e4SDavid E. O'Brien 
1335c80476e4SDavid E. O'Brien     if (num <= 0)
1336c80476e4SDavid E. O'Brien 	return;
1337c80476e4SDavid E. O'Brien 
1338c80476e4SDavid E. O'Brien     if (T_CanCEOL && GoodStr(T_ce))
1339c80476e4SDavid E. O'Brien 	(void) tputs(Str(T_ce), 1, PUTPURE);
1340c80476e4SDavid E. O'Brien     else {
1341c80476e4SDavid E. O'Brien 	for (i = 0; i < num; i++)
1342c80476e4SDavid E. O'Brien 	    (void) putraw(' ');
1343c80476e4SDavid E. O'Brien 	CursorH += num;		/* have written num spaces */
1344c80476e4SDavid E. O'Brien     }
1345c80476e4SDavid E. O'Brien }
1346c80476e4SDavid E. O'Brien 
1347c80476e4SDavid E. O'Brien void
ClearScreen(void)134845e5710bSMark Peek ClearScreen(void)
1349c80476e4SDavid E. O'Brien {				/* clear the whole screen and home */
1350c80476e4SDavid E. O'Brien     if (GoodStr(T_cl))
1351c80476e4SDavid E. O'Brien 	/* send the clear screen code */
1352c80476e4SDavid E. O'Brien 	(void) tputs(Str(T_cl), Val(T_li), PUTPURE);
1353c80476e4SDavid E. O'Brien     else if (GoodStr(T_ho) && GoodStr(T_cd)) {
1354c80476e4SDavid E. O'Brien 	(void) tputs(Str(T_ho), Val(T_li), PUTPURE);	/* home */
1355c80476e4SDavid E. O'Brien 	/* clear to bottom of screen */
1356c80476e4SDavid E. O'Brien 	(void) tputs(Str(T_cd), Val(T_li), PUTPURE);
1357c80476e4SDavid E. O'Brien     }
1358c80476e4SDavid E. O'Brien     else {
1359c80476e4SDavid E. O'Brien 	(void) putraw('\r');
1360c80476e4SDavid E. O'Brien 	(void) putraw('\n');
1361c80476e4SDavid E. O'Brien     }
1362c80476e4SDavid E. O'Brien }
1363c80476e4SDavid E. O'Brien 
1364c80476e4SDavid E. O'Brien void
SoundBeep(void)136545e5710bSMark Peek SoundBeep(void)
1366c80476e4SDavid E. O'Brien {				/* produce a sound */
1367c80476e4SDavid E. O'Brien     beep_cmd ();
1368c80476e4SDavid E. O'Brien     if (adrof(STRnobeep))
1369c80476e4SDavid E. O'Brien 	return;
1370c80476e4SDavid E. O'Brien 
1371c80476e4SDavid E. O'Brien     if (GoodStr(T_vb) && adrof(STRvisiblebell))
1372c80476e4SDavid E. O'Brien 	(void) tputs(Str(T_vb), 1, PUTPURE);	/* visible bell */
1373c80476e4SDavid E. O'Brien     else if (GoodStr(T_bl))
1374c80476e4SDavid E. O'Brien 	/* what termcap says we should use */
1375c80476e4SDavid E. O'Brien 	(void) tputs(Str(T_bl), 1, PUTPURE);
1376c80476e4SDavid E. O'Brien     else
1377c80476e4SDavid E. O'Brien 	(void) putraw(CTL_ESC('\007'));	/* an ASCII bell; ^G */
1378c80476e4SDavid E. O'Brien }
1379c80476e4SDavid E. O'Brien 
1380c80476e4SDavid E. O'Brien void
ClearToBottom(void)138145e5710bSMark Peek ClearToBottom(void)
1382c80476e4SDavid E. O'Brien {				/* clear to the bottom of the screen */
1383c80476e4SDavid E. O'Brien     if (GoodStr(T_cd))
1384c80476e4SDavid E. O'Brien 	(void) tputs(Str(T_cd), Val(T_li), PUTPURE);
1385c80476e4SDavid E. O'Brien     else if (GoodStr(T_ce))
1386c80476e4SDavid E. O'Brien 	(void) tputs(Str(T_ce), Val(T_li), PUTPURE);
1387c80476e4SDavid E. O'Brien }
1388c80476e4SDavid E. O'Brien 
1389c80476e4SDavid E. O'Brien void
GetTermCaps(void)139045e5710bSMark Peek GetTermCaps(void)
1391c80476e4SDavid E. O'Brien {				/* read in the needed terminal capabilites */
139223338178SMark Peek     int i;
139323338178SMark Peek     const char   *ptr;
1394c80476e4SDavid E. O'Brien     char    buf[TC_BUFSIZE];
1395c80476e4SDavid E. O'Brien     static char bp[TC_BUFSIZE];
1396c80476e4SDavid E. O'Brien     char   *area;
1397c80476e4SDavid E. O'Brien     struct termcapstr *t;
1398c80476e4SDavid E. O'Brien 
1399c80476e4SDavid E. O'Brien 
1400c80476e4SDavid E. O'Brien #ifdef SIG_WINDOW
140145e5710bSMark Peek     sigset_t oset, set;
1402c80476e4SDavid E. O'Brien     int     lins, cols;
1403c80476e4SDavid E. O'Brien 
1404c80476e4SDavid E. O'Brien     /* don't want to confuse things here */
140545e5710bSMark Peek     sigemptyset(&set);
140645e5710bSMark Peek     sigaddset(&set, SIG_WINDOW);
140745e5710bSMark Peek     (void)sigprocmask(SIG_BLOCK, &set, &oset);
140845e5710bSMark Peek     cleanup_push(&oset, sigprocmask_cleanup);
1409c80476e4SDavid E. O'Brien #endif /* SIG_WINDOW */
1410c80476e4SDavid E. O'Brien     area = buf;
1411c80476e4SDavid E. O'Brien 
1412c80476e4SDavid E. O'Brien     GotTermCaps = 1;
1413c80476e4SDavid E. O'Brien 
1414c80476e4SDavid E. O'Brien     setname("gettermcaps");
1415c80476e4SDavid E. O'Brien     ptr = getenv("TERM");
1416c80476e4SDavid E. O'Brien 
1417c80476e4SDavid E. O'Brien #ifdef apollo
1418c80476e4SDavid E. O'Brien     /*
1419c80476e4SDavid E. O'Brien      * If we are on a pad, we pretend that we are dumb. Otherwise the termcap
1420c80476e4SDavid E. O'Brien      * library will put us in a weird screen mode, thinking that we are going
1421c80476e4SDavid E. O'Brien      * to use curses
1422c80476e4SDavid E. O'Brien      */
1423c80476e4SDavid E. O'Brien     if (isapad())
1424c80476e4SDavid E. O'Brien 	ptr = "dumb";
1425c80476e4SDavid E. O'Brien #endif /* apollo */
1426c80476e4SDavid E. O'Brien 
1427c80476e4SDavid E. O'Brien     if (!ptr || !ptr[0] || !strcmp(ptr, "wm") || !strcmp(ptr,"dmx"))
1428c80476e4SDavid E. O'Brien 	ptr = "dumb";
1429c80476e4SDavid E. O'Brien 
1430c80476e4SDavid E. O'Brien     setzero(bp, TC_BUFSIZE);
1431c80476e4SDavid E. O'Brien 
1432c80476e4SDavid E. O'Brien     i = tgetent(bp, ptr);
1433c80476e4SDavid E. O'Brien     if (i <= 0) {
1434c80476e4SDavid E. O'Brien 	if (i == -1) {
1435c80476e4SDavid E. O'Brien #if (SYSVREL == 0) || defined(IRIS3D)
1436*19d2e3deSDmitry Chagin 	    xprintf(CGETS(7, 20,
1437*19d2e3deSDmitry Chagin 		"%s: The terminal database could not be opened.\n"), progname);
1438c80476e4SDavid E. O'Brien 	}
1439c80476e4SDavid E. O'Brien 	else if (i == 0) {
1440c80476e4SDavid E. O'Brien #endif /* SYSVREL */
1441c80476e4SDavid E. O'Brien 	    xprintf(CGETS(7, 21,
1442c80476e4SDavid E. O'Brien 			  "%s: No entry for terminal type \"%s\"\n"), progname,
1443c80476e4SDavid E. O'Brien 		    getenv("TERM"));
1444c80476e4SDavid E. O'Brien 	}
1445c80476e4SDavid E. O'Brien 	xprintf(CGETS(7, 22, "%s: using dumb terminal settings.\n"), progname);
1446c80476e4SDavid E. O'Brien 	Val(T_co) = 80;		/* do a dumb terminal */
1447c80476e4SDavid E. O'Brien 	Val(T_pt) = Val(T_km) = Val(T_li) = 0;
1448c80476e4SDavid E. O'Brien 	for (t = tstr; t->name != NULL; t++)
144945e5710bSMark Peek 	    TCset(t, NULL);
1450c80476e4SDavid E. O'Brien     }
1451c80476e4SDavid E. O'Brien     else {
1452c80476e4SDavid E. O'Brien 	/* Can we tab */
1453c80476e4SDavid E. O'Brien 	Val(T_pt) = tgetflag("pt") && !tgetflag("xt");
1454c80476e4SDavid E. O'Brien 	/* do we have a meta? */
1455c80476e4SDavid E. O'Brien 	Val(T_km) = (tgetflag("km") || tgetflag("MT"));
1456c80476e4SDavid E. O'Brien 	Val(T_am) = tgetflag("am");
1457c80476e4SDavid E. O'Brien 	Val(T_xn) = tgetflag("xn");
1458c80476e4SDavid E. O'Brien 	Val(T_co) = tgetnum("co");
1459c80476e4SDavid E. O'Brien 	Val(T_li) = tgetnum("li");
1460c80476e4SDavid E. O'Brien 	for (t = tstr; t->name != NULL; t++)
146145e5710bSMark Peek 	    TCset(t, tgetstr(t->name, &area));
1462c80476e4SDavid E. O'Brien     }
1463c80476e4SDavid E. O'Brien     if (Val(T_co) < 2)
1464c80476e4SDavid E. O'Brien 	Val(T_co) = 80;		/* just in case */
1465c80476e4SDavid E. O'Brien     if (Val(T_li) < 1)
1466c80476e4SDavid E. O'Brien 	Val(T_li) = 24;
1467c80476e4SDavid E. O'Brien 
1468c80476e4SDavid E. O'Brien     T_Cols = (Char) Val(T_co);
1469c80476e4SDavid E. O'Brien     T_Lines = (Char) Val(T_li);
1470c80476e4SDavid E. O'Brien     if (T_Tabs)
147145e5710bSMark Peek 	T_Tabs = Val(T_pt);
147245e5710bSMark Peek     T_HasMeta = Val(T_km);
147345e5710bSMark Peek     T_Margin = Val(T_am) ? MARGIN_AUTO : 0;
147445e5710bSMark Peek     T_Margin |= Val(T_xn) ? MARGIN_MAGIC : 0;
1475c80476e4SDavid E. O'Brien     T_CanCEOL = GoodStr(T_ce);
1476c80476e4SDavid E. O'Brien     T_CanDel = GoodStr(T_dc) || GoodStr(T_DC);
1477c80476e4SDavid E. O'Brien     T_CanIns = GoodStr(T_im) || GoodStr(T_ic) || GoodStr(T_IC);
1478c80476e4SDavid E. O'Brien     T_CanUP = GoodStr(T_up) || GoodStr(T_UP);
1479c80476e4SDavid E. O'Brien     if (GoodStr(T_me) && GoodStr(T_ue))
1480c80476e4SDavid E. O'Brien 	me_all = (strcmp(Str(T_me), Str(T_ue)) == 0);
1481c80476e4SDavid E. O'Brien     else
1482c80476e4SDavid E. O'Brien 	me_all = 0;
1483c80476e4SDavid E. O'Brien     if (GoodStr(T_me) && GoodStr(T_se))
1484c80476e4SDavid E. O'Brien 	me_all |= (strcmp(Str(T_me), Str(T_se)) == 0);
1485c80476e4SDavid E. O'Brien 
1486c80476e4SDavid E. O'Brien 
1487c80476e4SDavid E. O'Brien #ifdef DEBUG_SCREEN
1488c80476e4SDavid E. O'Brien     if (!T_CanUP) {
1489c80476e4SDavid E. O'Brien 	xprintf(CGETS(7, 23, "%s: WARNING: Your terminal cannot move up.\n",
1490c80476e4SDavid E. O'Brien 		progname));
1491c80476e4SDavid E. O'Brien 	xprintf(CGETS(7, 24, "Editing may be odd for long lines.\n"));
1492c80476e4SDavid E. O'Brien     }
1493c80476e4SDavid E. O'Brien     if (!T_CanCEOL)
1494c80476e4SDavid E. O'Brien 	xprintf(CGETS(7, 25, "no clear EOL capability.\n"));
1495c80476e4SDavid E. O'Brien     if (!T_CanDel)
1496c80476e4SDavid E. O'Brien 	xprintf(CGETS(7, 26, "no delete char capability.\n"));
1497c80476e4SDavid E. O'Brien     if (!T_CanIns)
1498c80476e4SDavid E. O'Brien 	xprintf(CGETS(7, 27, "no insert char capability.\n"));
1499c80476e4SDavid E. O'Brien #endif /* DEBUG_SCREEN */
1500c80476e4SDavid E. O'Brien 
1501c80476e4SDavid E. O'Brien 
1502c80476e4SDavid E. O'Brien 
1503c80476e4SDavid E. O'Brien #ifdef SIG_WINDOW
1504c80476e4SDavid E. O'Brien     (void) GetSize(&lins, &cols);	/* get the correct window size */
1505c80476e4SDavid E. O'Brien     ChangeSize(lins, cols);
1506c80476e4SDavid E. O'Brien 
150745e5710bSMark Peek     cleanup_until(&oset);		/* can change it again */
1508c80476e4SDavid E. O'Brien #else /* SIG_WINDOW */
1509c80476e4SDavid E. O'Brien     ChangeSize(Val(T_li), Val(T_co));
1510c80476e4SDavid E. O'Brien #endif /* SIG_WINDOW */
1511c80476e4SDavid E. O'Brien 
1512c80476e4SDavid E. O'Brien     BindArrowKeys();
1513c80476e4SDavid E. O'Brien }
1514c80476e4SDavid E. O'Brien 
1515c80476e4SDavid E. O'Brien #ifdef SIG_WINDOW
1516c80476e4SDavid E. O'Brien /* GetSize():
1517c80476e4SDavid E. O'Brien  *	Return the new window size in lines and cols, and
1518c80476e4SDavid E. O'Brien  *	true if the size was changed. This can fail if SHIN
1519c80476e4SDavid E. O'Brien  *	is not a tty, but it will work in most cases.
1520c80476e4SDavid E. O'Brien  */
1521c80476e4SDavid E. O'Brien int
GetSize(int * lins,int * cols)152245e5710bSMark Peek GetSize(int *lins, int *cols)
1523c80476e4SDavid E. O'Brien {
1524c80476e4SDavid E. O'Brien     *cols = Val(T_co);
1525c80476e4SDavid E. O'Brien     *lins = Val(T_li);
1526c80476e4SDavid E. O'Brien 
1527c80476e4SDavid E. O'Brien #ifdef TIOCGWINSZ
1528c80476e4SDavid E. O'Brien # define KNOWsize
1529c80476e4SDavid E. O'Brien # ifndef lint
1530c80476e4SDavid E. O'Brien     {
1531c80476e4SDavid E. O'Brien 	struct winsize ws;	/* from 4.3 */
1532c80476e4SDavid E. O'Brien 
1533c80476e4SDavid E. O'Brien 	if (ioctl(SHIN, TIOCGWINSZ, (ioctl_t) &ws) != -1) {
1534c80476e4SDavid E. O'Brien 	    if (ws.ws_col)
1535c80476e4SDavid E. O'Brien 		*cols = ws.ws_col;
1536c80476e4SDavid E. O'Brien 	    if (ws.ws_row)
1537c80476e4SDavid E. O'Brien 		*lins = ws.ws_row;
1538c80476e4SDavid E. O'Brien 	}
1539c80476e4SDavid E. O'Brien     }
1540c80476e4SDavid E. O'Brien # endif /* !lint */
1541c80476e4SDavid E. O'Brien #else /* TIOCGWINSZ */
1542c80476e4SDavid E. O'Brien # ifdef TIOCGSIZE
1543c80476e4SDavid E. O'Brien #  define KNOWsize
1544c80476e4SDavid E. O'Brien     {
1545c80476e4SDavid E. O'Brien 	struct ttysize ts;	/* from Sun */
1546c80476e4SDavid E. O'Brien 
1547c80476e4SDavid E. O'Brien 	if (ioctl(SHIN, TIOCGSIZE, (ioctl_t) &ts) != -1) {
1548c80476e4SDavid E. O'Brien 	    if (ts.ts_cols)
1549c80476e4SDavid E. O'Brien 		*cols = ts.ts_cols;
1550c80476e4SDavid E. O'Brien 	    if (ts.ts_lines)
1551c80476e4SDavid E. O'Brien 		*lins = ts.ts_lines;
1552c80476e4SDavid E. O'Brien 	}
1553c80476e4SDavid E. O'Brien     }
1554c80476e4SDavid E. O'Brien # endif /* TIOCGSIZE */
1555c80476e4SDavid E. O'Brien #endif /* TIOCGWINSZ */
1556c80476e4SDavid E. O'Brien 
1557c80476e4SDavid E. O'Brien     return (Val(T_co) != *cols || Val(T_li) != *lins);
1558c80476e4SDavid E. O'Brien }
1559c80476e4SDavid E. O'Brien 
156045e5710bSMark Peek #endif /* SIG_WINDOW */
1561c80476e4SDavid E. O'Brien 
15629ccc37e3SMark Peek #ifdef KNOWsize
1563*19d2e3deSDmitry Chagin static int
UpdateVal(const Char * tag,int value,Char * termcap,Char * backup)15649ccc37e3SMark Peek UpdateVal(const Char *tag, int value, Char *termcap, Char *backup)
15659ccc37e3SMark Peek {
15669ccc37e3SMark Peek     Char *ptr, *p;
15679ccc37e3SMark Peek     if ((ptr = Strstr(termcap, tag)) == NULL) {
15689ccc37e3SMark Peek 	(void)Strcpy(backup, termcap);
1569*19d2e3deSDmitry Chagin 	return 0;
15709ccc37e3SMark Peek     } else {
15719ccc37e3SMark Peek 	size_t len = (ptr - termcap) + Strlen(tag);
15729ccc37e3SMark Peek 	(void)Strncpy(backup, termcap, len);
15739ccc37e3SMark Peek 	backup[len] = '\0';
15749ccc37e3SMark Peek 	p = Itoa(value, 0, 0);
15759ccc37e3SMark Peek 	(void) Strcat(backup + len, p);
15769ccc37e3SMark Peek 	xfree(p);
15779ccc37e3SMark Peek 	ptr = Strchr(ptr, ':');
15789ccc37e3SMark Peek 	if (ptr)
15799ccc37e3SMark Peek 	    (void) Strcat(backup, ptr);
1580*19d2e3deSDmitry Chagin 	return 1;
15819ccc37e3SMark Peek     }
15829ccc37e3SMark Peek }
15839ccc37e3SMark Peek #endif
15849ccc37e3SMark Peek 
1585c80476e4SDavid E. O'Brien void
ChangeSize(int lins,int cols)158645e5710bSMark Peek ChangeSize(int lins, int cols)
1587c80476e4SDavid E. O'Brien {
1588c80476e4SDavid E. O'Brien     /*
1589c80476e4SDavid E. O'Brien      * Just in case
1590c80476e4SDavid E. O'Brien      */
1591c80476e4SDavid E. O'Brien     Val(T_co) = (cols < 2) ? 80 : cols;
1592c80476e4SDavid E. O'Brien     Val(T_li) = (lins < 1) ? 24 : lins;
1593c80476e4SDavid E. O'Brien 
1594c80476e4SDavid E. O'Brien #ifdef KNOWsize
1595c80476e4SDavid E. O'Brien     /*
1596c80476e4SDavid E. O'Brien      * We want to affect the environment only when we have a valid
1597c80476e4SDavid E. O'Brien      * setup, not when we get bad settings. Consider the following scenario:
1598c80476e4SDavid E. O'Brien      * We just logged in, and we have not initialized the editor yet.
1599c80476e4SDavid E. O'Brien      * We reset termcap with tset, and not $TERMCAP has the right
1600c80476e4SDavid E. O'Brien      * terminal size. But since the editor is not initialized yet, and
1601c80476e4SDavid E. O'Brien      * the kernel's notion of the terminal size might be wrong we arrive
1602c80476e4SDavid E. O'Brien      * here with lines = columns = 0. If we reset the environment we lose
1603c80476e4SDavid E. O'Brien      * our only chance to get the window size right.
1604c80476e4SDavid E. O'Brien      */
1605c80476e4SDavid E. O'Brien     if (Val(T_co) == cols && Val(T_li) == lins) {
160645e5710bSMark Peek 	Char   *p;
1607c80476e4SDavid E. O'Brien 	char   *tptr;
1608c80476e4SDavid E. O'Brien 
1609c80476e4SDavid E. O'Brien 	if (getenv("COLUMNS")) {
161045e5710bSMark Peek 	    p = Itoa(Val(T_co), 0, 0);
161145e5710bSMark Peek 	    cleanup_push(p, xfree);
161245e5710bSMark Peek 	    tsetenv(STRCOLUMNS, p);
161345e5710bSMark Peek 	    cleanup_until(p);
1614c80476e4SDavid E. O'Brien 	}
1615c80476e4SDavid E. O'Brien 
1616c80476e4SDavid E. O'Brien 	if (getenv("LINES")) {
161745e5710bSMark Peek 	    p = Itoa(Val(T_li), 0, 0);
161845e5710bSMark Peek 	    cleanup_push(p, xfree);
161945e5710bSMark Peek 	    tsetenv(STRLINES, p);
162045e5710bSMark Peek 	    cleanup_until(p);
1621c80476e4SDavid E. O'Brien 	}
1622c80476e4SDavid E. O'Brien 
1623c80476e4SDavid E. O'Brien 	if ((tptr = getenv("TERMCAP")) != NULL) {
1624c80476e4SDavid E. O'Brien 	    /* Leave 64 characters slop in case we enlarge the termcap string */
162545e5710bSMark Peek 	    Char    termcap[TC_BUFSIZE+64], backup[TC_BUFSIZE+64], *ptr;
1626*19d2e3deSDmitry Chagin 	    int changed;
1627c80476e4SDavid E. O'Brien 
1628c80476e4SDavid E. O'Brien 	    ptr = str2short(tptr);
162945e5710bSMark Peek 	    (void) Strncpy(termcap, ptr, TC_BUFSIZE);
163045e5710bSMark Peek 	    termcap[TC_BUFSIZE-1] = '\0';
1631c80476e4SDavid E. O'Brien 
1632*19d2e3deSDmitry Chagin 	    changed = UpdateVal(STRco, Val(T_co), termcap, backup);
1633*19d2e3deSDmitry Chagin 	    changed |= UpdateVal(STRli, Val(T_li), termcap, backup);
1634c80476e4SDavid E. O'Brien 
1635*19d2e3deSDmitry Chagin 	    if (changed) {
1636c80476e4SDavid E. O'Brien 		/*
163745e5710bSMark Peek 		 * Chop the termcap string at TC_BUFSIZE-1 characters to avoid
163845e5710bSMark Peek 		 * core-dumps in the termcap routines
1639c80476e4SDavid E. O'Brien 		 */
164045e5710bSMark Peek 		termcap[TC_BUFSIZE - 1] = '\0';
1641c80476e4SDavid E. O'Brien 		tsetenv(STRTERMCAP, termcap);
1642c80476e4SDavid E. O'Brien 	    }
1643c80476e4SDavid E. O'Brien 	}
1644*19d2e3deSDmitry Chagin     }
1645c80476e4SDavid E. O'Brien #endif /* KNOWsize */
1646c80476e4SDavid E. O'Brien 
1647c80476e4SDavid E. O'Brien     ReBufferDisplay();		/* re-make display buffers */
1648c80476e4SDavid E. O'Brien     ClearDisp();
1649c80476e4SDavid E. O'Brien }
1650