1e0b8e63eSJohn Marino /*-
2e0b8e63eSJohn Marino * Copyright (c) 1993, 1994
3e0b8e63eSJohn Marino * The Regents of the University of California. All rights reserved.
4e0b8e63eSJohn Marino * Copyright (c) 1993, 1994, 1995, 1996
5e0b8e63eSJohn Marino * Keith Bostic. All rights reserved.
6e0b8e63eSJohn Marino *
7e0b8e63eSJohn Marino * See the LICENSE file for redistribution information.
8e0b8e63eSJohn Marino */
9e0b8e63eSJohn Marino
10e0b8e63eSJohn Marino #include "config.h"
11e0b8e63eSJohn Marino
12e0b8e63eSJohn Marino #include <sys/types.h>
13e0b8e63eSJohn Marino #include <sys/ioctl.h>
14e0b8e63eSJohn Marino #include <sys/queue.h>
15e0b8e63eSJohn Marino #include <sys/stat.h>
16e0b8e63eSJohn Marino
17e0b8e63eSJohn Marino #include <bitstring.h>
18e0b8e63eSJohn Marino #include <errno.h>
19e0b8e63eSJohn Marino #include <limits.h>
20e0b8e63eSJohn Marino #include <signal.h>
21e0b8e63eSJohn Marino #include <stdio.h>
22e0b8e63eSJohn Marino #include <stdlib.h>
23e0b8e63eSJohn Marino #include <string.h>
24e0b8e63eSJohn Marino #ifdef HAVE_TERM_H
25e0b8e63eSJohn Marino #include <term.h>
26e0b8e63eSJohn Marino #endif
27e0b8e63eSJohn Marino #include <termios.h>
28e0b8e63eSJohn Marino #include <unistd.h>
29e0b8e63eSJohn Marino
30e0b8e63eSJohn Marino #include "../common/common.h"
31e0b8e63eSJohn Marino #include "cl.h"
32e0b8e63eSJohn Marino
33e0b8e63eSJohn Marino static int cl_pfmap(SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t);
34*b1ac2ebbSDaniel Fojt static size_t atoz_or(const char *, size_t);
35e0b8e63eSJohn Marino
36e0b8e63eSJohn Marino /*
37e0b8e63eSJohn Marino * XXX
38e0b8e63eSJohn Marino * THIS REQUIRES THAT ALL SCREENS SHARE A TERMINAL TYPE.
39e0b8e63eSJohn Marino */
40e0b8e63eSJohn Marino typedef struct _tklist {
41e0b8e63eSJohn Marino char *ts; /* Key's termcap string. */
42e0b8e63eSJohn Marino char *output; /* Corresponding vi command. */
43e0b8e63eSJohn Marino char *name; /* Name. */
44e0b8e63eSJohn Marino u_char value; /* Special value (for lookup). */
45e0b8e63eSJohn Marino } TKLIST;
46e0b8e63eSJohn Marino static TKLIST const c_tklist[] = { /* Command mappings. */
47e0b8e63eSJohn Marino {"kil1", "O", "insert line"},
48e0b8e63eSJohn Marino {"kdch1", "x", "delete character"},
49e0b8e63eSJohn Marino {"kcud1", "j", "cursor down"},
50e0b8e63eSJohn Marino {"kel", "D", "delete to eol"},
51e0b8e63eSJohn Marino {"kind", "\004", "scroll down"}, /* ^D */
52e0b8e63eSJohn Marino {"kll", "$", "go to eol"},
53e0b8e63eSJohn Marino {"kend", "$", "go to eol"},
54e0b8e63eSJohn Marino {"khome", "^", "go to sol"},
55e0b8e63eSJohn Marino {"kich1", "i", "insert at cursor"},
56e0b8e63eSJohn Marino {"kdl1", "dd", "delete line"},
57e0b8e63eSJohn Marino {"kcub1", "h", "cursor left"},
58e0b8e63eSJohn Marino {"knp", "\006", "page down"}, /* ^F */
59e0b8e63eSJohn Marino {"kpp", "\002", "page up"}, /* ^B */
60e0b8e63eSJohn Marino {"kri", "\025", "scroll up"}, /* ^U */
61e0b8e63eSJohn Marino {"ked", "dG", "delete to end of screen"},
62e0b8e63eSJohn Marino {"kcuf1", "l", "cursor right"},
63e0b8e63eSJohn Marino {"kcuu1", "k", "cursor up"},
64e0b8e63eSJohn Marino {NULL},
65e0b8e63eSJohn Marino };
66e0b8e63eSJohn Marino static TKLIST const m1_tklist[] = { /* Input mappings (lookup). */
67e0b8e63eSJohn Marino {NULL},
68e0b8e63eSJohn Marino };
69e0b8e63eSJohn Marino static TKLIST const m2_tklist[] = { /* Input mappings (set or delete). */
70e0b8e63eSJohn Marino {"kcud1", "\033ja", "cursor down"}, /* ^[ja */
71e0b8e63eSJohn Marino {"kcub1", "\033ha", "cursor left"}, /* ^[ha */
72e0b8e63eSJohn Marino {"kcuu1", "\033ka", "cursor up"}, /* ^[ka */
73e0b8e63eSJohn Marino {"kcuf1", "\033la", "cursor right"}, /* ^[la */
74e0b8e63eSJohn Marino {NULL},
75e0b8e63eSJohn Marino };
76e0b8e63eSJohn Marino
77e0b8e63eSJohn Marino /*
78e0b8e63eSJohn Marino * cl_term_init --
79e0b8e63eSJohn Marino * Initialize the special keys defined by the termcap/terminfo entry.
80e0b8e63eSJohn Marino *
81e0b8e63eSJohn Marino * PUBLIC: int cl_term_init(SCR *);
82e0b8e63eSJohn Marino */
83e0b8e63eSJohn Marino int
cl_term_init(SCR * sp)84e0b8e63eSJohn Marino cl_term_init(SCR *sp)
85e0b8e63eSJohn Marino {
86e0b8e63eSJohn Marino KEYLIST *kp;
87e0b8e63eSJohn Marino SEQ *qp;
88e0b8e63eSJohn Marino TKLIST const *tkp;
89e0b8e63eSJohn Marino char *t;
90e0b8e63eSJohn Marino CHAR_T name[60];
91e0b8e63eSJohn Marino CHAR_T output[5];
92e0b8e63eSJohn Marino CHAR_T ts[20];
93e0b8e63eSJohn Marino CHAR_T *wp;
94e0b8e63eSJohn Marino size_t wlen;
95e0b8e63eSJohn Marino
96e0b8e63eSJohn Marino /* Command mappings. */
97e0b8e63eSJohn Marino for (tkp = c_tklist; tkp->name != NULL; ++tkp) {
98e0b8e63eSJohn Marino if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1)
99e0b8e63eSJohn Marino continue;
100e0b8e63eSJohn Marino CHAR2INT(sp, tkp->name, strlen(tkp->name), wp, wlen);
101e0b8e63eSJohn Marino MEMCPY(name, wp, wlen);
102e0b8e63eSJohn Marino CHAR2INT(sp, t, strlen(t), wp, wlen);
103e0b8e63eSJohn Marino MEMCPY(ts, wp, wlen);
104e0b8e63eSJohn Marino CHAR2INT(sp, tkp->output, strlen(tkp->output), wp, wlen);
105e0b8e63eSJohn Marino MEMCPY(output, wp, wlen);
106e0b8e63eSJohn Marino if (seq_set(sp, name, strlen(tkp->name), ts, strlen(t),
107e0b8e63eSJohn Marino output, strlen(tkp->output), SEQ_COMMAND,
108e0b8e63eSJohn Marino SEQ_NOOVERWRITE | SEQ_SCREEN))
109e0b8e63eSJohn Marino return (1);
110e0b8e63eSJohn Marino }
111e0b8e63eSJohn Marino
112e0b8e63eSJohn Marino /* Input mappings needing to be looked up. */
113e0b8e63eSJohn Marino for (tkp = m1_tklist; tkp->name != NULL; ++tkp) {
114e0b8e63eSJohn Marino if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1)
115e0b8e63eSJohn Marino continue;
116e0b8e63eSJohn Marino for (kp = keylist;; ++kp)
117e0b8e63eSJohn Marino if (kp->value == tkp->value)
118e0b8e63eSJohn Marino break;
119e0b8e63eSJohn Marino if (kp == NULL)
120e0b8e63eSJohn Marino continue;
121e0b8e63eSJohn Marino CHAR2INT(sp, tkp->name, strlen(tkp->name), wp, wlen);
122e0b8e63eSJohn Marino MEMCPY(name, wp, wlen);
123e0b8e63eSJohn Marino CHAR2INT(sp, t, strlen(t), wp, wlen);
124e0b8e63eSJohn Marino MEMCPY(ts, wp, wlen);
125e0b8e63eSJohn Marino output[0] = (UCHAR_T)kp->ch;
126e0b8e63eSJohn Marino if (seq_set(sp, name, strlen(tkp->name), ts, strlen(t),
127e0b8e63eSJohn Marino output, 1, SEQ_INPUT, SEQ_NOOVERWRITE | SEQ_SCREEN))
128e0b8e63eSJohn Marino return (1);
129e0b8e63eSJohn Marino }
130e0b8e63eSJohn Marino
131e0b8e63eSJohn Marino /* Input mappings that are already set or are text deletions. */
132e0b8e63eSJohn Marino for (tkp = m2_tklist; tkp->name != NULL; ++tkp) {
133e0b8e63eSJohn Marino if ((t = tigetstr(tkp->ts)) == NULL || t == (char *)-1)
134e0b8e63eSJohn Marino continue;
135e0b8e63eSJohn Marino /*
136e0b8e63eSJohn Marino * !!!
137e0b8e63eSJohn Marino * Some terminals' <cursor_left> keys send single <backspace>
138e0b8e63eSJohn Marino * characters. This is okay in command mapping, but not okay
139e0b8e63eSJohn Marino * in input mapping. That combination is the only one we'll
140e0b8e63eSJohn Marino * ever see, hopefully, so kluge it here for now.
141e0b8e63eSJohn Marino */
142e0b8e63eSJohn Marino if (!strcmp(t, "\b"))
143e0b8e63eSJohn Marino continue;
144e0b8e63eSJohn Marino if (tkp->output == NULL) {
145e0b8e63eSJohn Marino CHAR2INT(sp, tkp->name, strlen(tkp->name), wp, wlen);
146e0b8e63eSJohn Marino MEMCPY(name, wp, wlen);
147e0b8e63eSJohn Marino CHAR2INT(sp, t, strlen(t), wp, wlen);
148e0b8e63eSJohn Marino MEMCPY(ts, wp, wlen);
149e0b8e63eSJohn Marino if (seq_set(sp, name, strlen(tkp->name),
150e0b8e63eSJohn Marino ts, strlen(t), NULL, 0,
151e0b8e63eSJohn Marino SEQ_INPUT, SEQ_NOOVERWRITE | SEQ_SCREEN))
152e0b8e63eSJohn Marino return (1);
153e0b8e63eSJohn Marino } else {
154e0b8e63eSJohn Marino CHAR2INT(sp, tkp->name, strlen(tkp->name), wp, wlen);
155e0b8e63eSJohn Marino MEMCPY(name, wp, wlen);
156e0b8e63eSJohn Marino CHAR2INT(sp, t, strlen(t), wp, wlen);
157e0b8e63eSJohn Marino MEMCPY(ts, wp, wlen);
158e0b8e63eSJohn Marino CHAR2INT(sp, tkp->output, strlen(tkp->output), wp, wlen);
159e0b8e63eSJohn Marino MEMCPY(output, wp, wlen);
160e0b8e63eSJohn Marino if (seq_set(sp, name, strlen(tkp->name),
161e0b8e63eSJohn Marino ts, strlen(t), output, strlen(tkp->output),
162e0b8e63eSJohn Marino SEQ_INPUT, SEQ_NOOVERWRITE | SEQ_SCREEN))
163e0b8e63eSJohn Marino return (1);
164e0b8e63eSJohn Marino }
165e0b8e63eSJohn Marino }
166e0b8e63eSJohn Marino
167e0b8e63eSJohn Marino /*
168e0b8e63eSJohn Marino * Rework any function key mappings that were set before the
169e0b8e63eSJohn Marino * screen was initialized.
170e0b8e63eSJohn Marino */
171e0b8e63eSJohn Marino SLIST_FOREACH(qp, sp->gp->seqq, q)
172e0b8e63eSJohn Marino if (F_ISSET(qp, SEQ_FUNCMAP))
173e0b8e63eSJohn Marino (void)cl_pfmap(sp, qp->stype,
174e0b8e63eSJohn Marino qp->input, qp->ilen, qp->output, qp->olen);
175e0b8e63eSJohn Marino return (0);
176e0b8e63eSJohn Marino }
177e0b8e63eSJohn Marino
178e0b8e63eSJohn Marino /*
179e0b8e63eSJohn Marino * cl_term_end --
180e0b8e63eSJohn Marino * End the special keys defined by the termcap/terminfo entry.
181e0b8e63eSJohn Marino *
182e0b8e63eSJohn Marino * PUBLIC: int cl_term_end(GS *);
183e0b8e63eSJohn Marino */
184e0b8e63eSJohn Marino int
cl_term_end(GS * gp)185e0b8e63eSJohn Marino cl_term_end(GS *gp)
186e0b8e63eSJohn Marino {
187e0b8e63eSJohn Marino SEQ *qp, *nqp, *pre_qp = NULL;
188e0b8e63eSJohn Marino
189e0b8e63eSJohn Marino /* Delete screen specific mappings. */
190e0b8e63eSJohn Marino SLIST_FOREACH_MUTABLE(qp, gp->seqq, q, nqp)
191e0b8e63eSJohn Marino if (F_ISSET(qp, SEQ_SCREEN)) {
192e0b8e63eSJohn Marino if (qp == SLIST_FIRST(gp->seqq))
193e0b8e63eSJohn Marino SLIST_REMOVE_HEAD(gp->seqq, q);
194e0b8e63eSJohn Marino else
195e0b8e63eSJohn Marino SLIST_REMOVE_AFTER(pre_qp, q);
196e0b8e63eSJohn Marino (void)seq_free(qp);
197e0b8e63eSJohn Marino } else
198e0b8e63eSJohn Marino pre_qp = qp;
199e0b8e63eSJohn Marino return (0);
200e0b8e63eSJohn Marino }
201e0b8e63eSJohn Marino
202e0b8e63eSJohn Marino /*
203e0b8e63eSJohn Marino * cl_fmap --
204e0b8e63eSJohn Marino * Map a function key.
205e0b8e63eSJohn Marino *
206e0b8e63eSJohn Marino * PUBLIC: int cl_fmap(SCR *, seq_t, CHAR_T *, size_t, CHAR_T *, size_t);
207e0b8e63eSJohn Marino */
208e0b8e63eSJohn Marino int
cl_fmap(SCR * sp,seq_t stype,CHAR_T * from,size_t flen,CHAR_T * to,size_t tlen)209e0b8e63eSJohn Marino cl_fmap(SCR *sp, seq_t stype, CHAR_T *from, size_t flen, CHAR_T *to, size_t tlen)
210e0b8e63eSJohn Marino {
211e0b8e63eSJohn Marino /* Ignore until the screen is running, do the real work then. */
212e0b8e63eSJohn Marino if (F_ISSET(sp, SC_VI) && !F_ISSET(sp, SC_SCR_VI))
213e0b8e63eSJohn Marino return (0);
214e0b8e63eSJohn Marino if (F_ISSET(sp, SC_EX) && !F_ISSET(sp, SC_SCR_EX))
215e0b8e63eSJohn Marino return (0);
216e0b8e63eSJohn Marino
217e0b8e63eSJohn Marino return (cl_pfmap(sp, stype, from, flen, to, tlen));
218e0b8e63eSJohn Marino }
219e0b8e63eSJohn Marino
220e0b8e63eSJohn Marino /*
221e0b8e63eSJohn Marino * cl_pfmap --
222e0b8e63eSJohn Marino * Map a function key (private version).
223e0b8e63eSJohn Marino */
224e0b8e63eSJohn Marino static int
cl_pfmap(SCR * sp,seq_t stype,CHAR_T * from,size_t flen,CHAR_T * to,size_t tlen)225e0b8e63eSJohn Marino cl_pfmap(SCR *sp, seq_t stype, CHAR_T *from, size_t flen, CHAR_T *to, size_t tlen)
226e0b8e63eSJohn Marino {
227e0b8e63eSJohn Marino size_t nlen;
228e0b8e63eSJohn Marino char *p;
229e0b8e63eSJohn Marino char name[64];
230e0b8e63eSJohn Marino CHAR_T keyname[64];
231e0b8e63eSJohn Marino CHAR_T ts[20];
232e0b8e63eSJohn Marino CHAR_T *wp;
233e0b8e63eSJohn Marino size_t wlen;
234e0b8e63eSJohn Marino
235e0b8e63eSJohn Marino (void)snprintf(name, sizeof(name), "kf%d",
236e0b8e63eSJohn Marino (int)STRTOL(from+1,NULL,10));
237e0b8e63eSJohn Marino if ((p = tigetstr(name)) == NULL ||
238e0b8e63eSJohn Marino p == (char *)-1 || strlen(p) == 0)
239e0b8e63eSJohn Marino p = NULL;
240e0b8e63eSJohn Marino if (p == NULL) {
241e0b8e63eSJohn Marino msgq_wstr(sp, M_ERR, from, "233|This terminal has no %s key");
242e0b8e63eSJohn Marino return (1);
243e0b8e63eSJohn Marino }
244e0b8e63eSJohn Marino
245e0b8e63eSJohn Marino nlen = SPRINTF(keyname,
246e0b8e63eSJohn Marino SIZE(keyname), L("function key %d"),
247e0b8e63eSJohn Marino (int)STRTOL(from+1,NULL,10));
248e0b8e63eSJohn Marino CHAR2INT(sp, p, strlen(p), wp, wlen);
249e0b8e63eSJohn Marino MEMCPY(ts, wp, wlen);
250e0b8e63eSJohn Marino return (seq_set(sp, keyname, nlen,
251e0b8e63eSJohn Marino ts, strlen(p), to, tlen, stype, SEQ_NOOVERWRITE | SEQ_SCREEN));
252e0b8e63eSJohn Marino }
253e0b8e63eSJohn Marino
254e0b8e63eSJohn Marino /*
255e0b8e63eSJohn Marino * cl_optchange --
256e0b8e63eSJohn Marino * Curses screen specific "option changed" routine.
257e0b8e63eSJohn Marino *
258e0b8e63eSJohn Marino * PUBLIC: int cl_optchange(SCR *, int, char *, u_long *);
259e0b8e63eSJohn Marino */
260e0b8e63eSJohn Marino int
cl_optchange(SCR * sp,int opt,char * str,u_long * valp)261e0b8e63eSJohn Marino cl_optchange(SCR *sp, int opt, char *str, u_long *valp)
262e0b8e63eSJohn Marino {
263e0b8e63eSJohn Marino CL_PRIVATE *clp;
264e0b8e63eSJohn Marino
265e0b8e63eSJohn Marino clp = CLP(sp);
266e0b8e63eSJohn Marino
267e0b8e63eSJohn Marino switch (opt) {
268e0b8e63eSJohn Marino case O_TERM:
269e0b8e63eSJohn Marino F_CLR(sp, SC_SCR_EX | SC_SCR_VI);
270e0b8e63eSJohn Marino /* FALLTHROUGH */
271e0b8e63eSJohn Marino case O_COLUMNS:
272e0b8e63eSJohn Marino case O_LINES:
273e0b8e63eSJohn Marino /*
274e0b8e63eSJohn Marino * Changing the terminal type requires that we reinitialize
275e0b8e63eSJohn Marino * curses, while resizing does not.
276e0b8e63eSJohn Marino */
277e0b8e63eSJohn Marino F_SET(sp->gp, G_SRESTART);
278e0b8e63eSJohn Marino break;
279e0b8e63eSJohn Marino case O_MESG:
280e0b8e63eSJohn Marino (void)cl_omesg(sp, clp, *valp);
281e0b8e63eSJohn Marino break;
282e0b8e63eSJohn Marino case O_WINDOWNAME:
283e0b8e63eSJohn Marino if (*valp) {
284e0b8e63eSJohn Marino F_SET(clp, CL_RENAME_OK);
285e0b8e63eSJohn Marino
286e0b8e63eSJohn Marino /*
287e0b8e63eSJohn Marino * If the screen is live, i.e. we're not reading the
288e0b8e63eSJohn Marino * .exrc file, update the window.
289e0b8e63eSJohn Marino */
290e0b8e63eSJohn Marino if (sp->frp != NULL && sp->frp->name != NULL)
291e0b8e63eSJohn Marino (void)cl_rename(sp, sp->frp->name, 1);
292e0b8e63eSJohn Marino } else {
293e0b8e63eSJohn Marino F_CLR(clp, CL_RENAME_OK);
294e0b8e63eSJohn Marino
295e0b8e63eSJohn Marino (void)cl_rename(sp, NULL, 0);
296e0b8e63eSJohn Marino }
297e0b8e63eSJohn Marino break;
298e0b8e63eSJohn Marino }
299e0b8e63eSJohn Marino return (0);
300e0b8e63eSJohn Marino }
301e0b8e63eSJohn Marino
302e0b8e63eSJohn Marino /*
303e0b8e63eSJohn Marino * cl_omesg --
304e0b8e63eSJohn Marino * Turn the tty write permission on or off.
305e0b8e63eSJohn Marino *
306e0b8e63eSJohn Marino * PUBLIC: int cl_omesg(SCR *, CL_PRIVATE *, int);
307e0b8e63eSJohn Marino */
308e0b8e63eSJohn Marino int
cl_omesg(SCR * sp,CL_PRIVATE * clp,int on)309e0b8e63eSJohn Marino cl_omesg(SCR *sp, CL_PRIVATE *clp, int on)
310e0b8e63eSJohn Marino {
311e0b8e63eSJohn Marino struct stat sb;
312e0b8e63eSJohn Marino char *tty;
313e0b8e63eSJohn Marino
314e0b8e63eSJohn Marino /* Find the tty, get the current permissions. */
315e0b8e63eSJohn Marino if ((tty = ttyname(STDERR_FILENO)) == NULL) {
316e0b8e63eSJohn Marino if (sp != NULL)
317e0b8e63eSJohn Marino msgq(sp, M_SYSERR, "stderr");
318e0b8e63eSJohn Marino return (1);
319e0b8e63eSJohn Marino }
320e0b8e63eSJohn Marino if (stat(tty, &sb) < 0) {
321e0b8e63eSJohn Marino if (sp != NULL)
322e0b8e63eSJohn Marino msgq(sp, M_SYSERR, "%s", tty);
323e0b8e63eSJohn Marino return (1);
324e0b8e63eSJohn Marino }
325e0b8e63eSJohn Marino
326e0b8e63eSJohn Marino /* Save the original status if it's unknown. */
327e0b8e63eSJohn Marino if (clp->tgw == TGW_UNKNOWN)
328e0b8e63eSJohn Marino clp->tgw = sb.st_mode & S_IWGRP ? TGW_SET : TGW_UNSET;
329e0b8e63eSJohn Marino
330e0b8e63eSJohn Marino /* Toggle the permissions. */
331e0b8e63eSJohn Marino if (on) {
332e0b8e63eSJohn Marino if (chmod(tty, sb.st_mode | S_IWGRP) < 0) {
333e0b8e63eSJohn Marino if (sp != NULL)
334e0b8e63eSJohn Marino msgq(sp, M_SYSERR,
335e0b8e63eSJohn Marino "046|messages not turned on: %s", tty);
336e0b8e63eSJohn Marino return (1);
337e0b8e63eSJohn Marino }
338e0b8e63eSJohn Marino } else
339e0b8e63eSJohn Marino if (chmod(tty, sb.st_mode & ~S_IWGRP) < 0) {
340e0b8e63eSJohn Marino if (sp != NULL)
341e0b8e63eSJohn Marino msgq(sp, M_SYSERR,
342e0b8e63eSJohn Marino "045|messages not turned off: %s", tty);
343e0b8e63eSJohn Marino return (1);
344e0b8e63eSJohn Marino }
345e0b8e63eSJohn Marino return (0);
346e0b8e63eSJohn Marino }
347e0b8e63eSJohn Marino
348e0b8e63eSJohn Marino /*
349e0b8e63eSJohn Marino * cl_ssize --
350e0b8e63eSJohn Marino * Return the terminal size.
351e0b8e63eSJohn Marino *
352e0b8e63eSJohn Marino * PUBLIC: int cl_ssize(SCR *, int, size_t *, size_t *, int *);
353e0b8e63eSJohn Marino */
354e0b8e63eSJohn Marino int
cl_ssize(SCR * sp,int sigwinch,size_t * rowp,size_t * colp,int * changedp)355e0b8e63eSJohn Marino cl_ssize(SCR *sp, int sigwinch, size_t *rowp, size_t *colp, int *changedp)
356e0b8e63eSJohn Marino {
357e0b8e63eSJohn Marino struct winsize win;
358e0b8e63eSJohn Marino size_t col, row;
359e0b8e63eSJohn Marino int rval;
360e0b8e63eSJohn Marino char *p;
361e0b8e63eSJohn Marino
362e0b8e63eSJohn Marino /* Assume it's changed. */
363e0b8e63eSJohn Marino if (changedp != NULL)
364e0b8e63eSJohn Marino *changedp = 1;
365e0b8e63eSJohn Marino
366e0b8e63eSJohn Marino /*
367e0b8e63eSJohn Marino * !!!
368e0b8e63eSJohn Marino * sp may be NULL.
369e0b8e63eSJohn Marino *
370e0b8e63eSJohn Marino * Get the screen rows and columns. If the values are wrong, it's
371e0b8e63eSJohn Marino * not a big deal -- as soon as the user sets them explicitly the
372e0b8e63eSJohn Marino * environment will be set and the screen package will use the new
373e0b8e63eSJohn Marino * values.
374e0b8e63eSJohn Marino *
375e0b8e63eSJohn Marino * Try TIOCGWINSZ.
376e0b8e63eSJohn Marino */
377e0b8e63eSJohn Marino row = col = 0;
378e0b8e63eSJohn Marino if (ioctl(STDERR_FILENO, TIOCGWINSZ, &win) != -1) {
379e0b8e63eSJohn Marino row = win.ws_row;
380e0b8e63eSJohn Marino col = win.ws_col;
381e0b8e63eSJohn Marino }
382e0b8e63eSJohn Marino /* If here because of suspend or a signal, only trust TIOCGWINSZ. */
383e0b8e63eSJohn Marino if (sigwinch) {
384e0b8e63eSJohn Marino /*
385e0b8e63eSJohn Marino * Somebody didn't get TIOCGWINSZ right, or has suspend
386e0b8e63eSJohn Marino * without window resizing support. The user just lost,
387e0b8e63eSJohn Marino * but there's nothing we can do.
388e0b8e63eSJohn Marino */
389e0b8e63eSJohn Marino if (row == 0 || col == 0) {
390e0b8e63eSJohn Marino if (changedp != NULL)
391e0b8e63eSJohn Marino *changedp = 0;
392e0b8e63eSJohn Marino return (0);
393e0b8e63eSJohn Marino }
394e0b8e63eSJohn Marino
395e0b8e63eSJohn Marino /*
396e0b8e63eSJohn Marino * SunOS systems deliver SIGWINCH when windows are uncovered
397e0b8e63eSJohn Marino * as well as when they change size. In addition, we call
398e0b8e63eSJohn Marino * here when continuing after being suspended since the window
399e0b8e63eSJohn Marino * may have changed size. Since we don't want to background
400e0b8e63eSJohn Marino * all of the screens just because the window was uncovered,
401e0b8e63eSJohn Marino * ignore the signal if there's no change.
402e0b8e63eSJohn Marino */
403e0b8e63eSJohn Marino if (sp != NULL &&
404e0b8e63eSJohn Marino row == O_VAL(sp, O_LINES) && col == O_VAL(sp, O_COLUMNS)) {
405e0b8e63eSJohn Marino if (changedp != NULL)
406e0b8e63eSJohn Marino *changedp = 0;
407e0b8e63eSJohn Marino return (0);
408e0b8e63eSJohn Marino }
409e0b8e63eSJohn Marino
410e0b8e63eSJohn Marino if (rowp != NULL)
411e0b8e63eSJohn Marino *rowp = row;
412e0b8e63eSJohn Marino if (colp != NULL)
413e0b8e63eSJohn Marino *colp = col;
414e0b8e63eSJohn Marino return (0);
415e0b8e63eSJohn Marino }
416e0b8e63eSJohn Marino
417e0b8e63eSJohn Marino /*
418e0b8e63eSJohn Marino * !!!
419e0b8e63eSJohn Marino * If TIOCGWINSZ failed, or had entries of 0, try termcap. This
420e0b8e63eSJohn Marino * routine is called before any termcap or terminal information
421e0b8e63eSJohn Marino * has been set up. If there's no TERM environmental variable set,
422e0b8e63eSJohn Marino * let it go, at least ex can run.
423e0b8e63eSJohn Marino */
424e0b8e63eSJohn Marino if (row == 0 || col == 0) {
425e0b8e63eSJohn Marino if ((p = getenv("TERM")) == NULL)
426e0b8e63eSJohn Marino goto noterm;
427e0b8e63eSJohn Marino if (row == 0)
428e0b8e63eSJohn Marino if ((rval = tigetnum("lines")) < 0)
429e0b8e63eSJohn Marino msgq(sp, M_SYSERR, "tigetnum: lines");
430e0b8e63eSJohn Marino else
431e0b8e63eSJohn Marino row = rval;
432e0b8e63eSJohn Marino if (col == 0)
433e0b8e63eSJohn Marino if ((rval = tigetnum("cols")) < 0)
434e0b8e63eSJohn Marino msgq(sp, M_SYSERR, "tigetnum: cols");
435e0b8e63eSJohn Marino else
436e0b8e63eSJohn Marino col = rval;
437e0b8e63eSJohn Marino }
438e0b8e63eSJohn Marino
439e0b8e63eSJohn Marino /* If nothing else, well, it's probably a VT100. */
440e0b8e63eSJohn Marino noterm: if (row == 0)
441e0b8e63eSJohn Marino row = 24;
442e0b8e63eSJohn Marino if (col == 0)
443e0b8e63eSJohn Marino col = 80;
444e0b8e63eSJohn Marino
445e0b8e63eSJohn Marino /*
446e0b8e63eSJohn Marino * !!!
447e0b8e63eSJohn Marino * POSIX 1003.2 requires the environment to override everything.
448e0b8e63eSJohn Marino * Often, people can get nvi to stop messing up their screen by
449e0b8e63eSJohn Marino * deleting the LINES and COLUMNS environment variables from their
450e0b8e63eSJohn Marino * dot-files.
451e0b8e63eSJohn Marino */
452e0b8e63eSJohn Marino if ((p = getenv("LINES")) != NULL)
453*b1ac2ebbSDaniel Fojt row = atoz_or(p, row);
454e0b8e63eSJohn Marino if ((p = getenv("COLUMNS")) != NULL)
455*b1ac2ebbSDaniel Fojt col = atoz_or(p, col);
456e0b8e63eSJohn Marino
457e0b8e63eSJohn Marino if (rowp != NULL)
458e0b8e63eSJohn Marino *rowp = row;
459e0b8e63eSJohn Marino if (colp != NULL)
460e0b8e63eSJohn Marino *colp = col;
461e0b8e63eSJohn Marino return (0);
462e0b8e63eSJohn Marino }
463e0b8e63eSJohn Marino
464e0b8e63eSJohn Marino /*
465*b1ac2ebbSDaniel Fojt * atoz_or --
466*b1ac2ebbSDaniel Fojt * Parse non-zero positive decimal with a fallback.
467*b1ac2ebbSDaniel Fojt */
468*b1ac2ebbSDaniel Fojt static size_t
atoz_or(const char * s,size_t y)469*b1ac2ebbSDaniel Fojt atoz_or(const char *s, size_t y)
470*b1ac2ebbSDaniel Fojt {
471*b1ac2ebbSDaniel Fojt char *ep;
472*b1ac2ebbSDaniel Fojt long x = strtol(s, &ep, 10);
473*b1ac2ebbSDaniel Fojt
474*b1ac2ebbSDaniel Fojt if (*ep == '\0' && (0 < x && x < INT_MAX))
475*b1ac2ebbSDaniel Fojt return (size_t)x;
476*b1ac2ebbSDaniel Fojt else
477*b1ac2ebbSDaniel Fojt return y;
478*b1ac2ebbSDaniel Fojt }
479*b1ac2ebbSDaniel Fojt
480*b1ac2ebbSDaniel Fojt /*
481e0b8e63eSJohn Marino * cl_putchar --
482e0b8e63eSJohn Marino * Function version of putchar, for tputs.
483e0b8e63eSJohn Marino *
484e0b8e63eSJohn Marino * PUBLIC: int cl_putchar(int);
485e0b8e63eSJohn Marino */
486e0b8e63eSJohn Marino int
cl_putchar(int ch)487e0b8e63eSJohn Marino cl_putchar(int ch)
488e0b8e63eSJohn Marino {
489e0b8e63eSJohn Marino return (putchar(ch));
490e0b8e63eSJohn Marino }
491