1 /* Unix screen update functions for regutil
2  *
3  * The contents of this file are subject to the Mozilla Public License
4  * Version 1.0 (the "License"); you may not use this file except in
5  * compliance with the License. You may obtain a copy of the License at
6  * http://www.mozilla.org/MPL/
7  *
8  * Software distributed under the License is distributed on an "AS IS"
9  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the
10  * License for the specific language governing rights and limitations
11  * under the License.
12  *
13  * The Original Code is regutil.
14  *
15  * The Initial Developer of the Original Code is Patrick TJ McPhee.
16  * Portions created by Patrick McPhee are Copyright � 1998, 2001
17  * Patrick TJ McPhee. All Rights Reserved.
18  *
19  * Contributors:
20  *
21  * $Header: C:/ptjm/rexx/regutil/RCS/regscreenux.c 1.15 2003/04/02 03:38:48 ptjm Rel $
22  */
23 #include "regutil.h"
24 #ifdef USE_TERMCAP_DB
25 # ifdef USE_TERM_H
26 #  include <sys/ioctl.h>
27 #  include <curses.h>
28 #  include <term.h>
29 # else
30 #  include <termcap.h>
31 # endif
32 #endif
33 #include <unistd.h>
34 #include <termios.h>
35 #include <sys/time.h>
36 #include <sys/types.h>
37 
38 /* sys/select.h is not present on hp-ux */
39 #ifndef __hpux
40 # include <sys/select.h>
41 #endif
42 
43 /* ******************************************************************** */
44 /* ************************** Screen Update *************************** */
45 /* ******************************************************************** */
46 
47 /* using termcap */
48 
49 static const char notimp[] = "not implemented";
50 #define what() memcpy(result->strptr, notimp, sizeof(notimp)-1), result->strlength = sizeof(notimp)-1
51 
52 
53 /* load the termcap info */
54 #ifdef USE_TERMCAP_DB
sethandles(void)55 static void sethandles(void)
56 {
57     static char tcent[1024];
58 
59     if (!*tcent)
60       tgetent(tcent, getenv("TERM"));
61 }
62 #endif
63 
64 
65 /* syscls() */
rxfunc(syscls)66 rxfunc(syscls)
67 {
68 #ifdef USE_TERMCAP_DB
69    static char clrbuf[100], * clr = clrbuf;
70 
71    if (!*clr) {
72       sethandles();
73       clr = tgetstr("cl", &clr);
74    }
75 #else
76    /* ansi terminal control for clearing the screen should work with any
77     * terminal these days... */
78    static const char clr[] = "\033[2J";
79 #endif
80 
81    if (clr) {
82       fputs(clr, stdout);
83       fflush(stdout);
84       result_zero();
85    }
86    else {
87        result_one();
88    }
89 
90    return 0;
91 }
92 
93 
94 /* syscurpos([row],[column]) -- returns current position, but I don't know
95  * how to get that */
rxfunc(syscurpos)96 rxfunc(syscurpos)
97 {
98 #ifdef USE_TERMCAP_DB
99    static char cposbuf[100], * cpos = cposbuf;
100 #else
101    static const char cpos[] = "\033[%d;%dH";
102 #endif
103 
104    if (argc != 0 && argc != 2)
105        return BADARGS;
106 
107 #ifdef USE_TERMCAP_DB
108    if (!*cpos) {
109       sethandles();
110       cpos = tgetstr("cm", &cpos);
111    }
112 #endif
113 
114    if (cpos) {
115       int x, y;
116       char * ex, *why;
117 
118       rxstrdup(ex, argv[1]);
119       rxstrdup(why, argv[0]);
120       x = atoi(ex)-1;
121       y = atoi(why)-1;
122 
123 #ifdef USE_TERMCAP_DB
124       fputs(tgoto(cpos, x, y), stdout);
125 #else
126       fprintf(stdout, cpos, y+1, x+1);
127 #endif
128       fflush(stdout);
129       strcpy(result->strptr, "0 0");
130       result->strlength = 3;
131    }
132    else {
133       strcpy(result->strptr, "0 0");
134       result->strlength = 3;
135    }
136 
137    return 0;
138 }
139 
140 
141 /* syscurstate(state) */
rxfunc(syscurstate)142 rxfunc(syscurstate)
143 {
144 #ifdef USE_TERMCAP_DB
145    static char css[100], *pcsson, *pcssoff;
146 #else
147    /* these work for vt-series terminals */
148    static char pcsson[] = "\033[?25h", pcssoff[] = "\033[?25l";
149 #endif
150    char * onoff;
151 
152    checkparam(1, 1);
153 
154    rxstrdup(onoff, argv[0]);
155    strupr(onoff);
156 
157 #ifdef USE_TERMCAP_DB
158    if (!*css) {
159       char *pcss = css;
160       sethandles();
161       pcsson = tgetstr("ve", &pcss);
162       pcssoff = tgetstr("vi", &pcss);
163    }
164 #endif
165 
166    if (pcsson && pcssoff) {
167        if (!strcasecmp(onoff, "OFF"))
168           onoff = pcssoff;
169        else
170           onoff = pcsson;
171    }
172 
173    fputs(onoff, stdout);
174    fflush(stdout);
175 
176    return 0;
177 }
178 
179 
180 /* sysgetkey([opt],[timeout]) */
rxfunc(sysgetkey)181 rxfunc(sysgetkey)
182 {
183    static struct termios oterm, nterm;
184    static int init = 1;
185    register rxbool doecho = true;
186    fd_set readfds;
187    struct timeval select_tv;
188    struct timeval *pselect_tv = NULL;
189 
190    checkparam(0,2);
191 
192    if (argc > 0 && argv[0].strptr && (argv[0].strptr[0] == 'N' || argv[0].strptr[0] == 'n'))
193       doecho = false;
194 
195    if (argc > 1 && argv[1].strptr) {
196       select_tv.tv_sec = rxint(argv+1);
197       select_tv.tv_usec = rxuint(argv+1);
198 
199       if (select_tv.tv_sec || select_tv.tv_usec) {
200          pselect_tv = &select_tv;
201       }
202    }
203 
204    if (init) {
205       init = 0;
206       tcgetattr(0, &oterm);			/* save oterm state */
207       nterm = oterm;				/* get base of nterm state */
208       nterm.c_lflag &= ~(ICANON | ISIG | IEXTEN);
209       nterm.c_iflag &= ~(ICRNL | INLCR | IXON | IXOFF | IXANY | BRKINT);
210       nterm.c_cc[VMIN]  = 1;
211       nterm.c_cc[VTIME] = 0;
212    }
213 
214    if (!doecho)
215        nterm.c_lflag &= ~(ECHO|ECHOE|ECHOK);
216    else
217        nterm.c_lflag |= ECHO|ECHOE|ECHOK;
218 
219    tcsetattr(0, TCSANOW, &nterm);			/* set mode */
220    /*
221     * Wait for specified timeout
222     */
223    FD_ZERO(&readfds);
224    FD_SET(0, &readfds);
225    if (select(1,&readfds,NULL,0,pselect_tv) > 0) {
226       result->strlength = sprintf(result->strptr, "%c", getchar());
227    }
228    else
229       result->strlength = 0;
230    tcsetattr(0, TCSANOW, &oterm);			/* restore mode */
231 
232    return 0;
233 }
234 
235 /* systextscreenread(row,column, len) */
rxfunc(systextscreenread)236 rxfunc(systextscreenread)
237 {
238    what();
239    return 0;
240 }
241 
242 /* systextscreensize() -- don't use termcap because the termcap
243  * result comes from the database, not the screen  */
rxfunc(systextscreensize)244 rxfunc(systextscreensize)
245 {
246 #  ifdef TIOCGWINSZ
247    struct winsize ws;
248 
249    /* Get the terminal size */
250    if (ioctl(0, TIOCGWINSZ, &ws) || 0 == ws.ws_row)
251       return 80;
252 
253    result->strlength = sprintf(result->strptr, "%d %d", ws.ws_row, ws.ws_col);
254 #  else
255    /* if the window-size ioctl is not avaiable, use the COLUMNS and LINES
256     * environment variables. These are specified by POSIX, but some systems
257     * don't set them correctly. */
258    char * columns = getenv("COLUMNS"), * lines = getenv("LINES");
259 
260    if (columns && lines) {
261       result->strlength = sprintf(result->strptr, "%s %s", lines, columns);
262    }
263    else {
264       static const char commonsize[] = "24 80"; /* a common size... */
265       result->strlength = sizeof(commonsize) - 1;
266       memcpy(result->strptr, commonsize, sizeof(commonsize) - 1);
267    }
268 #  endif
269 
270    return 0;
271 }
272