BSD 4_3_Tahoe release
[unix-history] / usr / src / new / X / xterm / resize.c
CommitLineData
ca67e7b4
C
1/*
2 * $Source: /u1/X/xterm/RCS/resize.c,v $
3 * $Header: resize.c,v 10.101 86/12/02 10:35:30 swick Exp $
4 */
5
6#ifndef lint
7static char *rcsid_resize_c = "$Header: resize.c,v 10.101 86/12/02 10:35:30 swick Exp $";
8#endif lint
9
10#include <X/mit-copyright.h>
11
12/* Copyright Massachusetts Institute of Technology 1984 */
13
14/* resize.c */
15
16#include <stdio.h>
17#include <sgtty.h>
18#include <strings.h>
19#include <ctype.h>
20#include <sys/ioctl.h>
21#include <signal.h>
22#include <sys/time.h>
23
24#ifndef lint
25static char sccs_id[] = "@(#)resize.c\tX10/6.6B\t12/26/86";
26#endif
27
28#define EMULATIONS 2
29#define SUN 1
30#define TIMEOUT 10
31#define VT100 0
32
33char *emuname[EMULATIONS] = {
34 "VT100",
35 "Sun",
36};
37char *myname;
38int stdsh;
39char *getsize[EMULATIONS] = {
40 "\0337\033[r\033[999;999H\033[6n",
41 "\033[18t",
42};
43#ifndef sun
44#ifdef TIOCSWINSZ
45char *getwsize[EMULATIONS] = {
46 0,
47 "\033[14t",
48};
49#endif TIOCSWINSZ
50#endif sun
51char *restore[EMULATIONS] = {
52 "\0338",
53 0,
54};
55char *setname = "";
56char *setsize[EMULATIONS] = {
57 0,
58 "\033[8;%s;%st",
59};
60struct sgttyb sgorig;
61char *size[EMULATIONS] = {
62 "\033[%d;%dR",
63 "\033[8;%d;%dt",
64};
65char sunname[] = "sunsize";
66int tty;
67FILE *ttyfp;
68#ifndef sun
69#ifdef TIOCSWINSZ
70char *wsize[EMULATIONS] = {
71 0,
72 "\033[4;%hd;%hdt",
73};
74#endif TIOCSWINSZ
75#endif sun
76
77char *strindex (), *index (), *rindex();
78
79main (argc, argv)
80char **argv;
81/*
82 resets termcap string to reflect current screen size
83 */
84{
85 register char *ptr, *env;
86 register int emu = VT100;
87 int rows, cols;
88 struct sgttyb sg;
89 char termcap [1024];
90 char newtc [1024];
91 char buf[BUFSIZ];
92#ifdef sun
93#ifdef TIOCSSIZE
94 struct ttysize ts;
95#endif TIOCSSIZE
96#else sun
97#ifdef TIOCSWINSZ
98 struct winsize ws;
99#endif TIOCSWINSZ
100#endif sun
101 char *getenv();
102 int onintr();
103
104 if(ptr = rindex(myname = argv[0], '/'))
105 myname = ptr + 1;
106 if(strcmp(myname, sunname) == 0)
107 emu = SUN;
108 for(argv++, argc-- ; argc > 0 && **argv == '-' ; argv++, argc--) {
109 switch((*argv)[1]) {
110 case 's': /* Sun emulation */
111 if(emu == SUN)
112 Usage(); /* Never returns */
113 emu = SUN;
114 break;
115 case 'u': /* Bourne (Unix) shell */
116 stdsh++;
117 break;
118 default:
119 Usage(); /* Never returns */
120 }
121 }
122 if(argc == 2) {
123 if(!setsize[emu]) {
124 fprintf(stderr,
125 "%s: Can't set window size under %s emulation\n",
126 myname, emuname[emu]);
127 exit(1);
128 }
129 if(!checkdigits(argv[0]) || !checkdigits(argv[1]))
130 Usage(); /* Never returns */
131 } else if(argc != 0)
132 Usage(); /* Never returns */
133 if((ttyfp = fopen("/dev/tty", "r+")) == NULL) {
134 fprintf(stderr, "%s: Can't open /dev/tty\n", myname);
135 exit(1);
136 }
137 tty = fileno(ttyfp);
138 if((env = getenv("TERMCAP")) && *env)
139 strcpy(termcap, env);
140 else {
141 if(!(env = getenv("TERM")) || !*env) {
142 env = "xterm";
143 if(stdsh)
144 setname = "TERM=xterm;\n";
145 else setname = "setenv TERM xterm;\n";
146 }
147 if(tgetent (termcap, env) <= 0) {
148 fprintf(stderr, "%s: Can't get entry \"%s\"\n",
149 myname, env);
150 exit(1);
151 }
152 }
153
154 ioctl (tty, TIOCGETP, &sgorig);
155 sg = sgorig;
156 sg.sg_flags |= RAW;
157 sg.sg_flags &= ~ECHO;
158 signal(SIGINT, onintr);
159 signal(SIGQUIT, onintr);
160 signal(SIGTERM, onintr);
161 ioctl (tty, TIOCSETP, &sg);
162
163 if (argc == 2) {
164 sprintf (buf, setsize[emu], argv[0], argv[1]);
165 write(tty, buf, strlen(buf));
166 }
167 write(tty, getsize[emu], strlen(getsize[emu]));
168 readstring(ttyfp, buf, size[emu]);
169 if(sscanf (buf, size[emu], &rows, &cols) != 2) {
170 fprintf(stderr, "%s: Can't get rows and columns\r\n", myname);
171 onintr();
172 }
173 if(restore[emu])
174 write(tty, restore[emu], strlen(restore[emu]));
175#ifdef sun
176#ifdef TIOCGSIZE
177 /* finally, set the tty's window size */
178 if (ioctl (tty, TIOCGSIZE, &ts) != -1) {
179 ts.ts_lines = rows;
180 ts.ts_cols = cols;
181 ioctl (tty, TIOCSSIZE, &ts);
182 }
183#endif TIOCGSIZE
184#else sun
185#ifdef TIOCGWINSZ
186 /* finally, set the tty's window size */
187 if(getwsize[emu]) {
188 /* get the window size in pixels */
189 write (tty, getwsize[emu], strlen (getwsize[emu]));
190 readstring(ttyfp, buf, wsize[emu]);
191 if(sscanf (buf, wsize[emu], &ws.ws_xpixel, &ws.ws_ypixel) != 2) {
192 fprintf(stderr, "%s: Can't get window size\r\n", myname);
193 onintr();
194 }
195 ws.ws_row = rows;
196 ws.ws_col = cols;
197 ioctl (tty, TIOCSWINSZ, &ws);
198 } else if (ioctl (tty, TIOCGWINSZ, &ws) != -1) {
199 /* we don't have any way of directly finding out
200 the current height & width of the window in pixels. We try
201 our best by computing the font height and width from the "old"
202 struct winsize values, and multiplying by these ratios...*/
203 if (ws.ws_xpixel != 0)
204 ws.ws_xpixel = cols * (ws.ws_xpixel / ws.ws_col);
205 if (ws.ws_ypixel != 0)
206 ws.ws_ypixel = rows * (ws.ws_ypixel / ws.ws_row);
207 ws.ws_row = rows;
208 ws.ws_col = cols;
209 ioctl (tty, TIOCSWINSZ, &ws);
210 }
211#endif TIOCGWINSZ
212#endif sun
213
214 ioctl (tty, TIOCSETP, &sgorig);
215 signal(SIGINT, SIG_DFL);
216 signal(SIGQUIT, SIG_DFL);
217 signal(SIGTERM, SIG_DFL);
218
219 /* update termcap string */
220 /* first do columns */
221 if ((ptr = strindex (termcap, "co#")) == NULL) {
222 fprintf(stderr, "%s: No `co#'\n", myname);
223 exit (1);
224 }
225 strncpy (newtc, termcap, ptr - termcap + 3);
226 sprintf (newtc + strlen (newtc), "%d", cols);
227 ptr = index (ptr, ':');
228 strcat (newtc, ptr);
229
230 /* now do lines */
231 if ((ptr = strindex (newtc, "li#")) == NULL) {
232 fprintf(stderr, "%s: No `li#'\n", myname);
233 exit (1);
234 }
235 strncpy (termcap, newtc, ptr - newtc + 3);
236 sprintf (termcap + ((int) ptr - (int) newtc + 3), "%d", rows);
237 ptr = index (ptr, ':');
238 strcat (termcap, ptr);
239
240 if(stdsh)
241 printf ("%sTERMCAP='%s'\n",
242 setname, termcap);
243 else printf ("set noglob;\n%ssetenv TERMCAP '%s';\nunset noglob;\n",
244 setname, termcap);
245 exit(0);
246}
247
248char *strindex (s1, s2)
249/*
250 returns a pointer to the first occurrence of s2 in s1, or NULL if there are
251 none.
252 */
253register char *s1, *s2;
254{
255 register char *s3;
256
257 while ((s3 = index (s1, *s2)) != NULL)
258 {
259 if (strncmp (s3, s2, strlen (s2)) == 0) return (s3);
260 s1 = ++s3;
261 }
262 return (NULL);
263}
264
265checkdigits(str)
266register char *str;
267{
268 while(*str) {
269 if(!isdigit(*str))
270 return(0);
271 str++;
272 }
273 return(1);
274}
275
276readstring(fp, buf, str)
277register FILE *fp;
278register char *buf;
279char *str;
280{
281 register int i, last;
282 struct itimerval it;
283 int timeout();
284
285 signal(SIGALRM, timeout);
286 bzero((char *)&it, sizeof(struct itimerval));
287 it.it_value.tv_sec = TIMEOUT;
288 setitimer(ITIMER_REAL, &it, (struct itimerval *)NULL);
289 if((*buf++ = getc(fp)) != *str) {
290 fprintf(stderr, "%s: unknown character, exiting.\r\n", myname);
291 onintr();
292 }
293 last = str[i = strlen(str) - 1];
294 while((*buf++ = getc(fp)) != last);
295 bzero((char *)&it, sizeof(struct itimerval));
296 setitimer(ITIMER_REAL, &it, (struct itimerval *)NULL);
297 *buf = 0;
298}
299
300Usage()
301{
302 fprintf(stderr, strcmp(myname, sunname) == 0 ?
303 "Usage: %s [rows cols]\n" :
304 "Usage: %s [-u] [-s [rows cols]]\n", myname);
305 exit(1);
306}
307
308timeout()
309{
310 fprintf(stderr, "%s: Time out occurred\r\n", myname);
311 onintr();
312}
313
314onintr()
315{
316 ioctl (tty, TIOCSETP, &sgorig);
317 exit(1);
318}