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