1 /*--------------------------------*-C-*---------------------------------*
2  * File:	init.c
3  *----------------------------------------------------------------------*
4  *
5  * All portions of code are copyright by their respective author/s.
6  * Copyright (c) 1992       John Bovey <jdb@ukc.ac.uk>
7  * Copyright (c) 1994       Robert Nation <nation@rocket.sanders.lockheed.com>
8  * Copyright (c) 1998-2001  Geoff Wing <gcw@pobox.com>
9  * Copyright (c) 1999       D J Hawkey Jr <hawkeyd@visi.com>
10  * Copyright (c) 2003       marcus at #fluxbox on freenode.net
11  * Copyright (c) 2004       Mr. Dobalina <losermcloser@users.sourceforge.net>
12  * Copyright (c) 2003-2004	Marc Lehmann <pcg@goof.com>
13  * Copyright (c) 2004-2005  Jingmin Zhou <jimmyzhou@users.sourceforge.net>
14  * Copyright (c) 2005       Gautam Iyer <gautam@math.uchicago.edu>
15  *
16  * This program is free software; you can redistribute it and/or modify
17  * it under the terms of the GNU General Public License as published by
18  * the Free Software Foundation; either version 2 of the License, or
19  * (at your option) any later version.
20  *
21  * This program is distributed in the hope that it will be useful,
22  * but WITHOUT ANY WARRANTY; without even the implied warranty of
23  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
24  * GNU General Public License for more details.
25  *
26  * You should have received a copy of the GNU General Public License
27  * along with this program; if not, write to the Free Software
28  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
29  *----------------------------------------------------------------------*/
30 /*
31 ** $Id: init.c,v 1.165 2005/10/08 01:07:45 cvs Exp $
32 */
33 
34 #include "../config.h"
35 #include "rxvt.h"
36 
37 
38 #ifdef DEBUG_VERBOSE
39 # define DEBUG_LEVEL	1
40 # define DEBUG_X
41 #else
42 # define DEBUG_LEVEL	0
43 # undef DEBUG_X
44 #endif
45 
46 #if DEBUG_LEVEL
47 # define DBG_MSG(d,x) if(d <= DEBUG_LEVEL) fprintf x
48 #else
49 # define DBG_MSG(d,x)
50 #endif
51 
52 /* #define XTERM_REVERSE_VIDEO 1 */
53 
54 
55 /*--------------------------------------------------------------------*
56  *         BEGIN `INTERNAL' ROUTINE PROTOTYPES                        *
57  *--------------------------------------------------------------------*/
58 #if defined(OS_SVR4) && !defined(_POSIX_VERSION)
59 int    rxvt_getdtablesize     ();
60 #endif
61 int    rxvt_xerror_handler    (const Display*, const XErrorEvent*);
62 void   rxvt_init_colors       (rxvt_t*);
63 void   rxvt_init_win_size     (rxvt_t*);
64 char** rxvt_string_to_argv    (char*, int*);
65 void   rxvt_color_aliases     (rxvt_t*, int);
66 void   rxvt_get_ourmods       (rxvt_t*);
67 int    rxvt_run_child         (rxvt_t*, int, const char**);
68 void   rxvt_get_ttymode       (ttymode_t*, int);
69 /*--------------------------------------------------------------------*
70  *         END   `INTERNAL' ROUTINE PROTOTYPES                        *
71  *--------------------------------------------------------------------*/
72 
73 
74 
75 const char *const def_colorName[] = {
76 	COLOR_FOREGROUND,
77 	COLOR_BACKGROUND,
78 /* low-intensity colors */
79 	"black",			/* 0: black			(#000000) */
80 #ifndef NO_BRIGHTCOLOR
81 	"red3",			/* 1: red				(#CD0000) */
82 	"green3",			/* 2: green			(#00CD00) */
83 	"yellow3",			/* 3: yellow			(#CDCD00) */
84 	"blue3",			/* 4: blue				(#0000CD) */
85 	"magenta3",			/* 5: magenta			(#CD00CD) */
86 	"cyan3",			/* 6: cyan				(#00CDCD) */
87 # ifdef XTERM_COLORS
88 	"grey90",			/* 7: white			(#E5E5E5) */
89 # else
90 	"antiquewhite",		/* 7: white			(#FAEBD7) */
91 # endif
92 /* high-intensity colors */
93 # ifdef XTERM_COLORS
94 	"grey30",			/* 8: bright black		(#4D4D4D) */
95 # else
96 	"grey25",			/* 8: bright black		(#404040) */
97 # endif
98 #endif				/* NO_BRIGHTCOLOR */
99 	"red",			/* 1/9: bright red		(#FF0000) */
100 	"green",			/* 2/10: bright green   (#00FF00) */
101 	"yellow",			/* 3/11: bright yellow  (#FFFF00) */
102 	"blue",			/* 4/12: bright blue	(#0000FF) */
103 	"magenta",			/* 5/13: bright magenta (#FF00FF) */
104 	"cyan",			/* 6/14: bright cyan	(#00FFFF) */
105 	"white",			/* 7/15: bright white   (#FFFFFF) */
106 #ifdef TTY_256COLOR
107 # ifdef XTERM_COLORS
108 	/* use the same color cube as xterm. 16-231 is a more or less uniform
109 	 * rgb ramp, and 231-255 is a greyscale ramp */
110 	"rgb:00/00/00",		/* default ff6-255 color table	 */
111 	"rgb:00/00/5f",		/* consists of 6 6x6 colour cubes */
112 	"rgb:00/00/87",		/* and a 24 greyscale ramp w/o	*/
113 	"rgb:00/00/af",		/* black or white			*/
114 	"rgb:00/00/d7",
115 	"rgb:00/00/ff",
116 	"rgb:00/5f/00",
117 	"rgb:00/5f/5f",
118 	"rgb:00/5f/87",
119 	"rgb:00/5f/af",
120 	"rgb:00/5f/d7",
121 	"rgb:00/5f/ff",
122 	"rgb:00/87/00",
123 	"rgb:00/87/5f",
124 	"rgb:00/87/87",
125 	"rgb:00/87/af",
126 	"rgb:00/87/d7",
127 	"rgb:00/87/ff",
128 	"rgb:00/af/00",
129 	"rgb:00/af/5f",
130 	"rgb:00/af/87",
131 	"rgb:00/af/af",
132 	"rgb:00/af/d7",
133 	"rgb:00/af/ff",
134 	"rgb:00/d7/00",
135 	"rgb:00/d7/5f",
136 	"rgb:00/d7/87",
137 	"rgb:00/d7/af",
138 	"rgb:00/d7/d7",
139 	"rgb:00/d7/ff",
140 	"rgb:00/ff/00",
141 	"rgb:00/ff/5f",
142 	"rgb:00/ff/87",
143 	"rgb:00/ff/af",
144 	"rgb:00/ff/d7",
145 	"rgb:00/ff/ff",
146 	"rgb:5f/00/00",
147 	"rgb:5f/00/5f",
148 	"rgb:5f/00/87",
149 	"rgb:5f/00/af",
150 	"rgb:5f/00/d7",
151 	"rgb:5f/00/ff",
152 	"rgb:5f/5f/00",
153 	"rgb:5f/5f/5f",
154 	"rgb:5f/5f/87",
155 	"rgb:5f/5f/af",
156 	"rgb:5f/5f/d7",
157 	"rgb:5f/5f/ff",
158 	"rgb:5f/87/00",
159 	"rgb:5f/87/5f",
160 	"rgb:5f/87/87",
161 	"rgb:5f/87/af",
162 	"rgb:5f/87/d7",
163 	"rgb:5f/87/ff",
164 	"rgb:5f/af/00",
165 	"rgb:5f/af/5f",
166 	"rgb:5f/af/87",
167 	"rgb:5f/af/af",
168 	"rgb:5f/af/d7",
169 	"rgb:5f/af/ff",
170 	"rgb:5f/d7/00",
171 	"rgb:5f/d7/5f",
172 	"rgb:5f/d7/87",
173 	"rgb:5f/d7/af",
174 	"rgb:5f/d7/d7",
175 	"rgb:5f/d7/ff",
176 	"rgb:5f/ff/00",
177 	"rgb:5f/ff/5f",
178 	"rgb:5f/ff/87",
179 	"rgb:5f/ff/af",
180 	"rgb:5f/ff/d7",
181 	"rgb:5f/ff/ff",
182 	"rgb:87/00/00",
183 	"rgb:87/00/5f",
184 	"rgb:87/00/87",
185 	"rgb:87/00/af",
186 	"rgb:87/00/d7",
187 	"rgb:87/00/ff",
188 	"rgb:87/5f/00",
189 	"rgb:87/5f/5f",
190 	"rgb:87/5f/87",
191 	"rgb:87/5f/af",
192 	"rgb:87/5f/d7",
193 	"rgb:87/5f/ff",
194 	"rgb:87/87/00",
195 	"rgb:87/87/5f",
196 	"rgb:87/87/87",
197 	"rgb:87/87/af",
198 	"rgb:87/87/d7",
199 	"rgb:87/87/ff",
200 	"rgb:87/af/00",
201 	"rgb:87/af/5f",
202 	"rgb:87/af/87",
203 	"rgb:87/af/af",
204 	"rgb:87/af/d7",
205 	"rgb:87/af/ff",
206 	"rgb:87/d7/00",
207 	"rgb:87/d7/5f",
208 	"rgb:87/d7/87",
209 	"rgb:87/d7/af",
210 	"rgb:87/d7/d7",
211 	"rgb:87/d7/ff",
212 	"rgb:87/ff/00",
213 	"rgb:87/ff/5f",
214 	"rgb:87/ff/87",
215 	"rgb:87/ff/af",
216 	"rgb:87/ff/d7",
217 	"rgb:87/ff/ff",
218 	"rgb:af/00/00",
219 	"rgb:af/00/5f",
220 	"rgb:af/00/87",
221 	"rgb:af/00/af",
222 	"rgb:af/00/d7",
223 	"rgb:af/00/ff",
224 	"rgb:af/5f/00",
225 	"rgb:af/5f/5f",
226 	"rgb:af/5f/87",
227 	"rgb:af/5f/af",
228 	"rgb:af/5f/d7",
229 	"rgb:af/5f/ff",
230 	"rgb:af/87/00",
231 	"rgb:af/87/5f",
232 	"rgb:af/87/87",
233 	"rgb:af/87/af",
234 	"rgb:af/87/d7",
235 	"rgb:af/87/ff",
236 	"rgb:af/af/00",
237 	"rgb:af/af/5f",
238 	"rgb:af/af/87",
239 	"rgb:af/af/af",
240 	"rgb:af/af/d7",
241 	"rgb:af/af/ff",
242 	"rgb:af/d7/00",
243 	"rgb:af/d7/5f",
244 	"rgb:af/d7/87",
245 	"rgb:af/d7/af",
246 	"rgb:af/d7/d7",
247 	"rgb:af/d7/ff",
248 	"rgb:af/ff/00",
249 	"rgb:af/ff/5f",
250 	"rgb:af/ff/87",
251 	"rgb:af/ff/af",
252 	"rgb:af/ff/d7",
253 	"rgb:af/ff/ff",
254 	"rgb:d7/00/00",
255 	"rgb:d7/00/5f",
256 	"rgb:d7/00/87",
257 	"rgb:d7/00/af",
258 	"rgb:d7/00/d7",
259 	"rgb:d7/00/ff",
260 	"rgb:d7/5f/00",
261 	"rgb:d7/5f/5f",
262 	"rgb:d7/5f/87",
263 	"rgb:d7/5f/af",
264 	"rgb:d7/5f/d7",
265 	"rgb:d7/5f/ff",
266 	"rgb:d7/87/00",
267 	"rgb:d7/87/5f",
268 	"rgb:d7/87/87",
269 	"rgb:d7/87/af",
270 	"rgb:d7/87/d7",
271 	"rgb:d7/87/ff",
272 	"rgb:d7/af/00",
273 	"rgb:d7/af/5f",
274 	"rgb:d7/af/87",
275 	"rgb:d7/af/af",
276 	"rgb:d7/af/d7",
277 	"rgb:d7/af/ff",
278 	"rgb:d7/d7/00",
279 	"rgb:d7/d7/5f",
280 	"rgb:d7/d7/87",
281 	"rgb:d7/d7/af",
282 	"rgb:d7/d7/d7",
283 	"rgb:d7/d7/ff",
284 	"rgb:d7/ff/00",
285 	"rgb:d7/ff/5f",
286 	"rgb:d7/ff/87",
287 	"rgb:d7/ff/af",
288 	"rgb:d7/ff/d7",
289 	"rgb:d7/ff/ff",
290 	"rgb:ff/00/00",
291 	"rgb:ff/00/5f",
292 	"rgb:ff/00/87",
293 	"rgb:ff/00/af",
294 	"rgb:ff/00/d7",
295 	"rgb:ff/00/ff",
296 	"rgb:ff/5f/00",
297 	"rgb:ff/5f/5f",
298 	"rgb:ff/5f/87",
299 	"rgb:ff/5f/af",
300 	"rgb:ff/5f/d7",
301 	"rgb:ff/5f/ff",
302 	"rgb:ff/87/00",
303 	"rgb:ff/87/5f",
304 	"rgb:ff/87/87",
305 	"rgb:ff/87/af",
306 	"rgb:ff/87/d7",
307 	"rgb:ff/87/ff",
308 	"rgb:ff/af/00",
309 	"rgb:ff/af/5f",
310 	"rgb:ff/af/87",
311 	"rgb:ff/af/af",
312 	"rgb:ff/af/d7",
313 	"rgb:ff/af/ff",
314 	"rgb:ff/d7/00",
315 	"rgb:ff/d7/5f",
316 	"rgb:ff/d7/87",
317 	"rgb:ff/d7/af",
318 	"rgb:ff/d7/d7",
319 	"rgb:ff/d7/ff",
320 	"rgb:ff/ff/00",
321 	"rgb:ff/ff/5f",
322 	"rgb:ff/ff/87",
323 	"rgb:ff/ff/af",
324 	"rgb:ff/ff/d7",
325 	"rgb:ff/ff/ff",
326 # else	/* XTERM_COLORS */
327 	"rgbi:0/0/0",		/* default 16-255 color table	 */
328 	"rgbi:0/0/.2",		/* consists of 6 6x6 colour cubes */
329 	"rgbi:0/0/.4",		/* and a 24 greyscale ramp w/o	*/
330 	"rgbi:0/0/.6",		/* black or white			*/
331 	"rgbi:0/0/.8",
332 	"rgbi:0/0/1",
333 	"rgbi:0/.2/0",
334 	"rgbi:0/.2/.2",
335 	"rgbi:0/.2/.4",
336 	"rgbi:0/.2/.6",
337 	"rgbi:0/.2/.8",
338 	"rgbi:0/.2/1",
339 	"rgbi:0/.4/0",
340 	"rgbi:0/.4/.2",
341 	"rgbi:0/.4/.4",
342 	"rgbi:0/.4/.6",
343 	"rgbi:0/.4/.8",
344 	"rgbi:0/.4/1",
345 	"rgbi:0/.6/0",
346 	"rgbi:0/.6/.2",
347 	"rgbi:0/.6/.4",
348 	"rgbi:0/.6/.6",
349 	"rgbi:0/.6/.8",
350 	"rgbi:0/.6/1",
351 	"rgbi:0/.8/0",
352 	"rgbi:0/.8/.2",
353 	"rgbi:0/.8/.4",
354 	"rgbi:0/.8/.6",
355 	"rgbi:0/.8/.8",
356 	"rgbi:0/.8/1",
357 	"rgbi:0/1/0",
358 	"rgbi:0/1/.2",
359 	"rgbi:0/1/.4",
360 	"rgbi:0/1/.6",
361 	"rgbi:0/1/.8",
362 	"rgbi:0/1/1",
363 	"rgbi:.2/0/0",
364 	"rgbi:.2/0/.2",
365 	"rgbi:.2/0/.4",
366 	"rgbi:.2/0/.6",
367 	"rgbi:.2/0/.8",
368 	"rgbi:.2/0/1",
369 	"rgbi:.2/.2/0",
370 	"rgbi:.2/.2/.2",
371 	"rgbi:.2/.2/.4",
372 	"rgbi:.2/.2/.6",
373 	"rgbi:.2/.2/.8",
374 	"rgbi:.2/.2/1",
375 	"rgbi:.2/.4/0",
376 	"rgbi:.2/.4/.2",
377 	"rgbi:.2/.4/.4",
378 	"rgbi:.2/.4/.6",
379 	"rgbi:.2/.4/.8",
380 	"rgbi:.2/.4/1",
381 	"rgbi:.2/.6/0",
382 	"rgbi:.2/.6/.2",
383 	"rgbi:.2/.6/.4",
384 	"rgbi:.2/.6/.6",
385 	"rgbi:.2/.6/.8",
386 	"rgbi:.2/.6/1",
387 	"rgbi:.2/.8/0",
388 	"rgbi:.2/.8/.2",
389 	"rgbi:.2/.8/.4",
390 	"rgbi:.2/.8/.6",
391 	"rgbi:.2/.8/.8",
392 	"rgbi:.2/.8/1",
393 	"rgbi:.2/1/0",
394 	"rgbi:.2/1/.2",
395 	"rgbi:.2/1/.4",
396 	"rgbi:.2/1/.6",
397 	"rgbi:.2/1/.8",
398 	"rgbi:.2/1/1",
399 	"rgbi:.4/0/0",
400 	"rgbi:.4/0/.2",
401 	"rgbi:.4/0/.4",
402 	"rgbi:.4/0/.6",
403 	"rgbi:.4/0/.8",
404 	"rgbi:.4/0/1",
405 	"rgbi:.4/.2/0",
406 	"rgbi:.4/.2/.2",
407 	"rgbi:.4/.2/.4",
408 	"rgbi:.4/.2/.6",
409 	"rgbi:.4/.2/.8",
410 	"rgbi:.4/.2/1",
411 	"rgbi:.4/.4/0",
412 	"rgbi:.4/.4/.2",
413 	"rgbi:.4/.4/.4",
414 	"rgbi:.4/.4/.6",
415 	"rgbi:.4/.4/.8",
416 	"rgbi:.4/.4/1",
417 	"rgbi:.4/.6/0",
418 	"rgbi:.4/.6/.2",
419 	"rgbi:.4/.6/.4",
420 	"rgbi:.4/.6/.6",
421 	"rgbi:.4/.6/.8",
422 	"rgbi:.4/.6/1",
423 	"rgbi:.4/.8/0",
424 	"rgbi:.4/.8/.2",
425 	"rgbi:.4/.8/.4",
426 	"rgbi:.4/.8/.6",
427 	"rgbi:.4/.8/.8",
428 	"rgbi:.4/.8/1",
429 	"rgbi:.4/1/0",
430 	"rgbi:.4/1/.2",
431 	"rgbi:.4/1/.4",
432 	"rgbi:.4/1/.6",
433 	"rgbi:.4/1/.8",
434 	"rgbi:.4/1/1",
435 	"rgbi:.6/0/0",
436 	"rgbi:.6/0/.2",
437 	"rgbi:.6/0/.4",
438 	"rgbi:.6/0/.6",
439 	"rgbi:.6/0/.8",
440 	"rgbi:.6/0/1",
441 	"rgbi:.6/.2/0",
442 	"rgbi:.6/.2/.2",
443 	"rgbi:.6/.2/.4",
444 	"rgbi:.6/.2/.6",
445 	"rgbi:.6/.2/.8",
446 	"rgbi:.6/.2/1",
447 	"rgbi:.6/.4/0",
448 	"rgbi:.6/.4/.2",
449 	"rgbi:.6/.4/.4",
450 	"rgbi:.6/.4/.6",
451 	"rgbi:.6/.4/.8",
452 	"rgbi:.6/.4/1",
453 	"rgbi:.6/.6/0",
454 	"rgbi:.6/.6/.2",
455 	"rgbi:.6/.6/.4",
456 	"rgbi:.6/.6/.6",
457 	"rgbi:.6/.6/.8",
458 	"rgbi:.6/.6/1",
459 	"rgbi:.6/.8/0",
460 	"rgbi:.6/.8/.2",
461 	"rgbi:.6/.8/.4",
462 	"rgbi:.6/.8/.6",
463 	"rgbi:.6/.8/.8",
464 	"rgbi:.6/.8/1",
465 	"rgbi:.6/1/0",
466 	"rgbi:.6/1/.2",
467 	"rgbi:.6/1/.4",
468 	"rgbi:.6/1/.6",
469 	"rgbi:.6/1/.8",
470 	"rgbi:.6/1/1",
471 	"rgbi:.8/0/0",
472 	"rgbi:.8/0/.2",
473 	"rgbi:.8/0/.4",
474 	"rgbi:.8/0/.6",
475 	"rgbi:.8/0/.8",
476 	"rgbi:.8/0/1",
477 	"rgbi:.8/.2/0",
478 	"rgbi:.8/.2/.2",
479 	"rgbi:.8/.2/.4",
480 	"rgbi:.8/.2/.6",
481 	"rgbi:.8/.2/.8",
482 	"rgbi:.8/.2/1",
483 	"rgbi:.8/.4/0",
484 	"rgbi:.8/.4/.2",
485 	"rgbi:.8/.4/.4",
486 	"rgbi:.8/.4/.6",
487 	"rgbi:.8/.4/.8",
488 	"rgbi:.8/.4/1",
489 	"rgbi:.8/.6/0",
490 	"rgbi:.8/.6/.2",
491 	"rgbi:.8/.6/.4",
492 	"rgbi:.8/.6/.6",
493 	"rgbi:.8/.6/.8",
494 	"rgbi:.8/.6/1",
495 	"rgbi:.8/.8/0",
496 	"rgbi:.8/.8/.2",
497 	"rgbi:.8/.8/.4",
498 	"rgbi:.8/.8/.6",
499 	"rgbi:.8/.8/.8",
500 	"rgbi:.8/.8/1",
501 	"rgbi:.8/1/0",
502 	"rgbi:.8/1/.2",
503 	"rgbi:.8/1/.4",
504 	"rgbi:.8/1/.6",
505 	"rgbi:.8/1/.8",
506 	"rgbi:.8/1/1",
507 	"rgbi:1/0/0",
508 	"rgbi:1/0/.2",
509 	"rgbi:1/0/.4",
510 	"rgbi:1/0/.6",
511 	"rgbi:1/0/.8",
512 	"rgbi:1/0/1",
513 	"rgbi:1/.2/0",
514 	"rgbi:1/.2/.2",
515 	"rgbi:1/.2/.4",
516 	"rgbi:1/.2/.6",
517 	"rgbi:1/.2/.8",
518 	"rgbi:1/.2/1",
519 	"rgbi:1/.4/0",
520 	"rgbi:1/.4/.2",
521 	"rgbi:1/.4/.4",
522 	"rgbi:1/.4/.6",
523 	"rgbi:1/.4/.8",
524 	"rgbi:1/.4/1",
525 	"rgbi:1/.6/0",
526 	"rgbi:1/.6/.2",
527 	"rgbi:1/.6/.4",
528 	"rgbi:1/.6/.6",
529 	"rgbi:1/.6/.8",
530 	"rgbi:1/.6/1",
531 	"rgbi:1/.8/0",
532 	"rgbi:1/.8/.2",
533 	"rgbi:1/.8/.4",
534 	"rgbi:1/.8/.6",
535 	"rgbi:1/.8/.8",
536 	"rgbi:1/.8/1",
537 	"rgbi:1/1/0",
538 	"rgbi:1/1/.2",
539 	"rgbi:1/1/.4",
540 	"rgbi:1/1/.6",
541 	"rgbi:1/1/.8",
542 	"rgbi:1/1/1",
543 # endif	/* XTERM_COLORS */
544 	"rgb:08/08/08", /* xterm, rxvt, mrxvt use the same greyscale ramp */
545 	"rgb:12/12/12",
546 	"rgb:1c/1c/1c",
547 	"rgb:26/26/26",
548 	"rgb:30/30/30",
549 	"rgb:3a/3a/3a",
550 	"rgb:44/44/44",
551 	"rgb:4e/4e/4e",
552 	"rgb:58/58/58",
553 	"rgb:62/62/62",
554 	"rgb:6c/6c/6c",
555 	"rgb:76/76/76",
556 	"rgb:80/80/80",
557 	"rgb:8a/8a/8a",
558 	"rgb:94/94/94",
559 	"rgb:9e/9e/9e",
560 	"rgb:a8/a8/a8",
561 	"rgb:b2/b2/b2",
562 	"rgb:bc/bc/bc",
563 	"rgb:c6/c6/c6",
564 	"rgb:d0/d0/d0",
565 	"rgb:da/da/da",
566 	"rgb:e4/e4/e4",
567 	"rgb:ee/ee/ee",
568 #endif	/* TTY_256COLOR */
569 #ifndef NO_CURSORCOLOR
570 	COLOR_CURSOR_BACKGROUND,
571 	COLOR_CURSOR_FOREGROUND,
572 #endif				/* ! NO_CURSORCOLOR */
573 	NULL,			/* Color_pointer					*/
574 	NULL,			/* Color_border					*/
575 	NULL,			/* Color_ufbg					*/
576 #ifndef NO_BOLD_UNDERLINE_REVERSE
577 	NULL,			/* Color_BD						*/
578 	NULL,			/* Color_UL						*/
579 	NULL,			/* Color_RV						*/
580 #endif				/* ! NO_BOLD_UNDERLINE_REVERSE */
581 #ifdef OPTION_HC
582 	NULL,
583 #endif
584 #ifdef KEEP_SCROLLCOLOR
585 	COLOR_SCROLLBAR,
586 	COLOR_SCROLLTROUGH,
587 #endif				/* KEEP_SCROLLCOLOR */
588 #ifdef TINTING_SUPPORT
589 	NULL,
590 #endif
591 };
592 
593 
594 /*
595 ** MUST sync with rxvt.h:enum XA_XXXX
596 */
597 const char *const xa_names[NUM_XA] = {
598 	"COMPOUND_TEXT",
599 	"UTF8_STRING",
600 	"TEXT",
601 	"MULTIPLE",
602 	"TARGETS",
603 	"TIMESTAMP",
604 	"VT_SELECTION",
605 	"INCR",
606 	"WM_DELETE_WINDOW",
607 	"_NET_WM_DESKTOP",
608 	"_WIN_WORKSPACE",
609 	"_NET_WM_NAME",
610 	"_NET_WM_ICON_NAME",
611 	"WM_CLIENT_LEADER",
612 	"_NET_WM_WINDOW_OPACITY",
613 #ifndef NO_FRILLS
614 	"_NET_WM_PID",
615 #endif
616 #ifdef HAVE_X11_SM_SMLIB_H
617 	"SM_CLIENT_ID",
618 #endif
619 #ifdef USE_XIM
620 	"WM_LOCALE_NAME",
621 #endif
622 #ifdef TRANSPARENT
623 	"_XROOTPMAP_ID",
624 #endif
625 #ifdef OFFIX_DND
626 	"DndProtocol",
627 	"DndSelection",
628 #endif
629 	"CLIPBOARD"
630 };
631 
632 /*----------------------------------------------------------------------*/
633 /* substitute system functions */
634 #if defined(OS_SVR4) && ! defined(_POSIX_VERSION)
635 /* INTPROTO */
636 int
rxvt_getdtablesize(void)637 rxvt_getdtablesize(void)
638 {
639 	struct rlimit   rlim;
640 
641 	getrlimit(RLIMIT_NOFILE, &rlim);
642 	return rlim.rlim_cur;
643 }
644 #endif
645 /*----------------------------------------------------------------------*/
646 /* EXTPROTO */
647 int
rxvt_init_vars(rxvt_t * r)648 rxvt_init_vars(rxvt_t *r)
649 {
650 	register int		i;
651 	struct rxvt_hidden*	h;
652 
653 
654 	MEMSET(r, 0, sizeof(rxvt_t));
655 
656 	h = r->h = (struct rxvt_hidden *)rxvt_calloc(1, sizeof(struct rxvt_hidden));
657 
658 	for (i = 0; i < MAX_PAGES; i ++)	{
659 		/* Initialize vts_idx for each term_t structure */
660 		r->vterm[i].vts_idx = -1;
661 		/* Initialize each vts pointer */
662 		r->vts[i] = NULL;
663 	}
664 
665 	/*
666 	** hotkeys[MAX_HOTKEYS] is a valid entry!!! it will be used to
667 	** save the first hotkey entry if we toggle disableHotkeys
668 	*/
669 	r->hotkeys = (hotkeys_t*) rxvt_malloc(
670 		sizeof(hotkeys_t) * (MAX_HOTKEYS + 1));
671 
672 	r->PixColors = (unsigned long*) rxvt_malloc(
673 		sizeof(unsigned long) * (TOTAL_COLORS + 2 * MAX_PAGES));
674 #ifdef OFF_FOCUS_FADING
675 	r->PixColorsUnfocus = (unsigned long*) rxvt_malloc(
676 		sizeof(unsigned long) * (TOTAL_COLORS + 2 * MAX_PAGES));
677 #endif
678 #ifdef XFT_SUPPORT
679 	r->XftColors = (XftColor*) rxvt_malloc (
680 		sizeof (XftColor) * (TOTAL_COLORS + 2 * MAX_PAGES));
681 #endif
682 	if (NULL == r->h ||
683 		NULL == r->hotkeys ||
684 		NULL == r->PixColors
685 #ifdef OFF_FOCUS_FADING
686 		|| NULL == r->PixColorsUnfocus
687 #endif
688 #ifdef XFT_SUPPORT
689 		|| NULL == r->XftColors
690 #endif
691 		)
692 		return -1;
693 
694 
695 	r->Xdisplay = NULL;
696 #ifdef USE_XIM
697 	r->TermWin.fontset = NULL;
698 #endif
699 	r->TermWin.font = NULL;
700 #ifdef MULTICHAR_SET
701 	r->TermWin.mfont = NULL;
702 #endif
703 #ifndef NO_BOLDFONT
704 	r->TermWin.bfont = NULL;
705 #endif
706 
707 #ifdef XFT_SUPPORT
708 	r->TermWin.xftpattern = NULL;
709 	r->TermWin.xftfont = NULL;
710 # ifndef NO_BOLDFONT
711 	r->TermWin.xftbpattern = NULL;
712 	r->TermWin.xftbfont = NULL;
713 	r->TermWin.bf_switched = 0;
714 # endif	/* NO_BOLDFONT */
715 # ifdef MULTICHAR_SET
716 #  ifdef HAVE_ICONV_H
717 	r->TermWin.xfticonv = (iconv_t) -1;
718 #  endif
719 	r->TermWin.xftmpattern = NULL;
720 	r->TermWin.xftmfont = NULL;
721 # endif	/* MULTICHAR_SET */
722 #endif	/* XFT_SUPPORT */
723 
724 #ifdef OFF_FOCUS_FADING
725 	r->color_switched = 0;	/* color is not switched */
726 #endif
727 	h->xa[XA_COMPOUND_TEXT] =
728 	h->xa[XA_MULTIPLE] =
729 	h->xa[XA_TARGETS] =
730 	h->xa[XA_TEXT] =
731 	h->xa[XA_TIMESTAMP] =
732 	h->xa[XA_VT_SELECTION] =
733 	h->xa[XA_INCR] = None;
734 	h->locale = NULL;
735 # ifdef HAVE_MENUBAR
736 	h->BuildMenu = NULL;	/* the menu currently being built */
737 #  if (MENUBAR_MAX > 1)
738 	h->CurrentBar = NULL;
739 #  endif			/* (MENUBAR_MAX > 1) */
740 # endif
741 # ifdef USE_XIM
742 	h->Input_Context = NULL;
743 # endif
744 	/* h->v_bufstr = NULL; */
745 	h->buffer = NULL;
746 	h->compose.compose_ptr = NULL;
747 #ifdef TRANSPARENT
748 	h->am_pixmap_trans = 0;
749 	h->am_transparent = 0;
750 #endif
751 
752 
753 	h->MEvent.time = CurrentTime;
754 	h->MEvent.button = AnyButton;
755 	r->Options = DEFAULT_OPTIONS;
756 	r->Options2 = DEFAULT_OPTIONS2;
757 	h->want_refresh = 1;
758 	h->ttygid = -1;
759 	r->Xfd = -1;
760 	r->vt_died = 0;
761 
762 	/* default values */
763 #ifdef NO_FRILLS
764 	r->TermWin.int_bwidth = DEFAULT_INTERNALBORDERWIDTH;
765 	r->TermWin.ext_bwidth = DEFAULT_EXTERNALBORDERWIDTH;
766 #else
767 	r->TermWin.int_bwidth = (INTERNALBORDERWIDTH >= 0 && INTERNALBORDERWIDTH <= MAX_INTERNALBORDERWIDTH) ? INTERNALBORDERWIDTH : DEFAULT_INTERNALBORDERWIDTH;
768 	r->TermWin.ext_bwidth = (EXTERNALBORDERWIDTH >= 0 && EXTERNALBORDERWIDTH <= MAX_EXTERNALBORDERWIDTH) ? EXTERNALBORDERWIDTH : DEFAULT_EXTERNALBORDERWIDTH;
769 #endif
770 
771 #ifndef NO_LINESPACE
772 	r->TermWin.lineSpace = (LINESPACE >= 0 && LINESPACE <= MAX_LINESPACE) ? LINESPACE : DEFAULT_LINESPACE;
773 #endif
774 
775 #ifdef CURSOR_BLINK
776 	r->h->blinkInterval = DEFAULT_BLINK_TIME;
777 #endif
778 #ifdef POINTER_BLANK
779 	r->h->pointerBlankDelay = DEFAULT_BLANKDELAY;
780 #endif
781 
782 	r->numPixColors = TOTAL_COLORS;
783 
784 	/* Initialize selection data */
785 #ifndef NO_NEW_SELECTION
786 	r->selection_style = NEW_SELECT;
787 #else
788 	r->selection_style = OLD_SELECT;
789 #endif
790 	r->selection.vt = -1;
791 	r->selection.op = SELECTION_CLEAR;
792 	r->selection.screen = PRIMARY;
793 	r->selection.clicks = 0;
794 	r->selection.text = NULL;
795 	r->selection.len = 0;
796 	r->selection.beg.row = 0;
797 	r->selection.beg.col = 0;
798 	r->selection.end.row = 0;
799 	r->selection.end.col = 0;
800 
801 #ifndef NO_BRIGHTCOLOR
802 	h->colorfgbg = DEFAULT_RSTYLE;
803 #endif
804 #if defined (HOTKEY_CTRL) || defined (HOTKEY_META)
805 	h->ks_bigfont = XK_greater;
806 	h->ks_smallfont = XK_less;
807 #endif
808 #ifdef GREEK_SUPPORT
809 	h->ks_greekmodeswith = GREEK_KEYBOARD_MODESWITCH;
810 #endif
811 	h->refresh_limit = 1;
812 	h->refresh_type = SLOW_REFRESH;
813 	h->prev_nrow = h->prev_ncol = 0;
814 
815 	r->encoding_method = ENC_NOENC;
816 	h->multichar_decode = rxvt_decode_dummy;
817 
818 	h->oldcursor.row = h->oldcursor.col = -1;
819 	h->last_bot = h->last_state = -1;
820 #ifdef HAVE_MENUBAR
821 	h->menu_readonly = 1;
822 # if !(MENUBAR_MAX > 1)
823 	h->CurrentBar = &(h->BarList);
824 # endif				/* (MENUBAR_MAX > 1) */
825 #endif
826 
827 #ifdef HAVE_X11_SM_SMLIB_H
828 	r->TermWin.sm_conn = NULL;
829 	r->TermWin.ice_conn = NULL;
830 	r->TermWin.ice_fd = -1;
831 	r->TermWin.sm_client_id = NULL;
832 #endif
833 
834 	return 0;
835 }
836 
837 
838 /* EXTPROTO */
839 void
rxvt_init_secondary(rxvt_t * r)840 rxvt_init_secondary(rxvt_t *r)
841 {
842 	int			i, num_fds;
843 #ifdef TTY_GID_SUPPORT
844 	struct group   *gr = getgrnam("tty");
845 
846 	if (gr) {		/* change group ownership of tty to "tty" */
847 		r->h->ttygid = gr->gr_gid;
848 	}
849 	else
850 #endif				/* TTY_GID_SUPPORT */
851 	{
852 		r->h->ttygid = getgid();
853 	}
854 
855 	rxvt_set_default_locale (r);
856 
857 	/* get number of available file descriptors */
858 #if defined(_POSIX_VERSION) || ! defined(OS_SVR4)
859 	num_fds = (int)sysconf(_SC_OPEN_MAX);
860 #else
861 	num_fds = rxvt_getdtablesize();
862 #endif
863 
864 	/*
865 	** Close all unused file descriptors
866 	** We don't want them, we don't need them.
867 	*/
868 	if ((i = open("/dev/null", O_RDONLY)) < 0) {
869 		/* TODO: BOO HISS */
870 		dup2(STDERR_FILENO, STDIN_FILENO);
871 	}
872 	else if (i > STDIN_FILENO) {
873 		dup2(i, STDIN_FILENO);
874 		close(i);
875 	}
876 	dup2(STDERR_FILENO, STDOUT_FILENO);
877 	for (i = STDERR_FILENO + 1; i < num_fds; i++) {
878 /* #ifdef __sgi */
879 #ifdef OS_IRIX
880 		/* Alex Coventry says we need 4 & 7 too */
881 		if (i == 4 || i == 7)
882 			continue;
883 #endif
884 		close(i);
885 	}
886 
887 	/* Now set the correct num_fds */
888 	r->num_fds = STDERR_FILENO + 1;
889 #ifdef OS_IRIX
890 	r->num_fds = 7 + 1;
891 #endif
892 }
893 
894 
895 /* INTPROTO */
896 hotkeys_t
make_hotkeys_t(unsigned short func,unsigned short flag,KeySym keysym)897 make_hotkeys_t (unsigned short func, unsigned short flag, KeySym keysym)
898 {
899 	hotkeys_t	value;
900 	value.func = func;
901 	value.flag = flag;
902 	value.keysym = keysym;
903 	return (value);
904 }
905 
906 
907 /* EXTPROTO */
908 void
rxvt_init_hotkeys(rxvt_t * r)909 rxvt_init_hotkeys (rxvt_t* r)
910 {
911 	register int	i = 0;
912 	hotkeys_t*		hk;
913 
914 
915 	/* initialize hotkey handlers */
916 	rxvt_init_hotkey_handlers (r);
917 
918 	assert (NULL != r->hotkeys);
919 	hk = r->hotkeys;
920 
921 	/* if shft is 1, keysym must be upper case!!! */
922 
923 	/* gnome-terminal hotkeys */
924 	hk[i++] = make_hotkeys_t (HKF_NEW_TAB,		(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_T);
925 	hk[i++] = make_hotkeys_t (HKF_KILL_TAB,		(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_W);
926 	hk[i++] = make_hotkeys_t (HKF_PREV_TAB,		(HK_INTERNAL|HK_CTRL), XK_Prior);
927 	hk[i++] = make_hotkeys_t (HKF_NEXT_TAB,		(HK_INTERNAL|HK_CTRL), XK_Next);
928 	hk[i++] = make_hotkeys_t (HKF_TAB_1,		(HK_INTERNAL|HK_META), XK_1);
929 	hk[i++] = make_hotkeys_t (HKF_TAB_2,		(HK_INTERNAL|HK_META), XK_2);
930 	hk[i++] = make_hotkeys_t (HKF_TAB_3,		(HK_INTERNAL|HK_META), XK_3);
931 	hk[i++] = make_hotkeys_t (HKF_TAB_4,		(HK_INTERNAL|HK_META), XK_4);
932 	hk[i++] = make_hotkeys_t (HKF_TAB_5,		(HK_INTERNAL|HK_META), XK_5);
933 	hk[i++] = make_hotkeys_t (HKF_TAB_6,		(HK_INTERNAL|HK_META), XK_6);
934 	hk[i++] = make_hotkeys_t (HKF_TAB_7,		(HK_INTERNAL|HK_META), XK_7);
935 	hk[i++] = make_hotkeys_t (HKF_TAB_8,		(HK_INTERNAL|HK_META), XK_8);
936 	hk[i++] = make_hotkeys_t (HKF_TAB_9,		(HK_INTERNAL|HK_META), XK_9);
937 	hk[i++] = make_hotkeys_t (HKF_SMALL_FONT,	(HK_INTERNAL|HK_CTRL), XK_minus);
938 	hk[i++] = make_hotkeys_t (HKF_LARGE_FONT,	(HK_INTERNAL|HK_CTRL), XK_equal);
939 	hk[i++] = make_hotkeys_t (HKF_SMALL_FONT,	(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_underscore);
940 	hk[i++] = make_hotkeys_t (HKF_LARGE_FONT,	(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_plus);
941 
942 	/* konsole hotkeys */
943 	hk[i++] = make_hotkeys_t (HKF_LMOVE_TAB,	(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_Left);
944 	hk[i++] = make_hotkeys_t (HKF_RMOVE_TAB,	(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_Right);
945 	hk[i++] = make_hotkeys_t (HKF_NEW_TAB,		(HK_INTERNAL|HK_CTRL|HK_META), XK_n);
946 	hk[i++] = make_hotkeys_t (HKF_NEW_TAB,		(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_N);
947 	hk[i++] = make_hotkeys_t (HKF_PREV_TAB,		(HK_INTERNAL|HK_SHFT), XK_Left);
948 	hk[i++] = make_hotkeys_t (HKF_NEXT_TAB,		(HK_INTERNAL|HK_SHFT), XK_Right);
949 	hk[i++] = make_hotkeys_t (HKF_CHANGE_TITLE,	(HK_INTERNAL|HK_CTRL|HK_META), XK_s);
950 
951 	/* vi-like hotkeys */
952 	hk[i++] = make_hotkeys_t (HKF_PREV_TAB,		(HK_INTERNAL|HK_CTRL|HK_META), XK_h);
953 	hk[i++] = make_hotkeys_t (HKF_NEXT_TAB,		(HK_INTERNAL|HK_CTRL|HK_META), XK_l);
954 
955 	/* screen-like hotkeys */
956 	hk[i++] = make_hotkeys_t (HKF_PREV_ATAB,	(HK_INTERNAL|HK_CTRL|HK_META), XK_p);
957 
958 	/* our own default hotkeys */
959 	hk[i++] = make_hotkeys_t (HKF_CHANGE_TITLE,	(HK_INTERNAL|HK_SHFT), XK_Delete);
960 	hk[i++] = make_hotkeys_t (HKF_PREV_ATAB,	(HK_INTERNAL|HK_CTRL), XK_Tab);
961 	hk[i++] = make_hotkeys_t (HKF_KILL_TAB,		(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_K);
962 	hk[i++] = make_hotkeys_t (HKF_TAB_1,		(HK_INTERNAL|HK_CTRL|HK_META), XK_1);
963 	hk[i++] = make_hotkeys_t (HKF_TAB_2,		(HK_INTERNAL|HK_CTRL|HK_META), XK_2);
964 	hk[i++] = make_hotkeys_t (HKF_TAB_3,		(HK_INTERNAL|HK_CTRL|HK_META), XK_3);
965 	hk[i++] = make_hotkeys_t (HKF_TAB_4,		(HK_INTERNAL|HK_CTRL|HK_META), XK_4);
966 	hk[i++] = make_hotkeys_t (HKF_TAB_5,		(HK_INTERNAL|HK_CTRL|HK_META), XK_5);
967 	hk[i++] = make_hotkeys_t (HKF_TAB_6,		(HK_INTERNAL|HK_CTRL|HK_META), XK_6);
968 	hk[i++] = make_hotkeys_t (HKF_TAB_7,		(HK_INTERNAL|HK_CTRL|HK_META), XK_7);
969 	hk[i++] = make_hotkeys_t (HKF_TAB_8,		(HK_INTERNAL|HK_CTRL|HK_META), XK_8);
970 	hk[i++] = make_hotkeys_t (HKF_TAB_9,		(HK_INTERNAL|HK_CTRL|HK_META), XK_9);
971 	hk[i++] = make_hotkeys_t (HKF_LMOVE_TAB,	(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_less);
972 	hk[i++] = make_hotkeys_t (HKF_RMOVE_TAB,	(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_greater);
973 	hk[i++] = make_hotkeys_t (HKF_DUMP_SCREEN,	(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_Z);
974 	hk[i++] = make_hotkeys_t (HKF_INC_OPACITY,	(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_O);
975 	hk[i++] = make_hotkeys_t (HKF_DEC_OPACITY,	(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_U);
976 	hk[i++] = make_hotkeys_t (HKF_TRANSPARENCY,	(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_R);
977 	hk[i++] = make_hotkeys_t (HKF_HIDE_TABBAR,	(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_H);
978 	hk[i++] = make_hotkeys_t (HKF_HIDE_SCROLLBAR,(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_S);
979 	hk[i++] = make_hotkeys_t (HKF_HIDE_MENUBAR,	(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_M);
980 	hk[i++] = make_hotkeys_t (HKF_HIDE_BUTTON,	(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_A);
981 	hk[i++] = make_hotkeys_t (HKF_VERYBOLD,		(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_F);
982 	hk[i++] = make_hotkeys_t (HKF_HOLD_EXIT,	(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_E);
983 	hk[i++] = make_hotkeys_t (HKF_BROADCAST,	(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_B);
984 	hk[i++] = make_hotkeys_t (HKF_SAVE_CONFIG,	(HK_INTERNAL|HK_CTRL|HK_SHFT), XK_X);
985 	hk[i++] = make_hotkeys_t (HKF_LARGE_FONT,	(HK_INTERNAL|HK_SHFT), XK_Home);
986 	hk[i++] = make_hotkeys_t (HKF_SMALL_FONT,	(HK_INTERNAL|HK_SHFT), XK_End);
987 	hk[i++] = make_hotkeys_t (HKF_SCROLL_UP,	(HK_INTERNAL|HK_SHFT), XK_Up);
988 	hk[i++] = make_hotkeys_t (HKF_SCROLL_DOWN,	(HK_INTERNAL|HK_SHFT), XK_Down);
989 	hk[i++] = make_hotkeys_t (HKF_SCROLL_PGUP,	(HK_INTERNAL|HK_SHFT), XK_Prior);
990 	hk[i++] = make_hotkeys_t (HKF_SCROLL_PGDOWN,(HK_INTERNAL|HK_SHFT), XK_Next);
991 
992 	/* rxvt/xterm hotkeys */
993 
994 	assert (i <= MAX_HOTKEYS);
995 
996 	/*
997 	** hotkeys[MAX_HOTKEYS] is a valid entry!!! it will be used to
998 	** save the first hotkey entry if we toggle disableHotkeys
999 	*/
1000 	for (; i <= MAX_HOTKEYS; i ++)	{
1001 		hk[i] = make_hotkeys_t (HKF_DUMMY, 0, 0);
1002 	}
1003 }
1004 
1005 
1006 /* EXTPROTO */
1007 void
rxvt_toggle_hotkeys(rxvt_t * r,int enable)1008 rxvt_toggle_hotkeys (rxvt_t* r, int enable)
1009 {
1010 	if (enable)	{
1011 		if (HKF_DUMMY != r->hotkeys[0].func)	/* already enabled */
1012 			return;
1013 
1014 		SWAP_IT (r->hotkeys[0], r->hotkeys[MAX_HOTKEYS], hotkeys_t);
1015 	}
1016 	else	{
1017 		if (HKF_DUMMY == r->hotkeys[0].func)	/* already disabled */
1018 			return;
1019 
1020 		SWAP_IT (r->hotkeys[0], r->hotkeys[MAX_HOTKEYS], hotkeys_t);
1021 	}
1022 }
1023 
1024 
1025 /* INTPROTO */
1026 int
rxvt_xerror_handler(const Display * display,const XErrorEvent * event)1027 rxvt_xerror_handler(const Display *display __attribute__((unused)), const XErrorEvent *event)
1028 {
1029 	char		error_msg[1024];
1030 	rxvt_t*		r = rxvt_get_r();
1031 
1032 	XGetErrorText (r->Xdisplay, event->error_code, error_msg, 1023);
1033 	rxvt_print_error("%s", error_msg);
1034 	if (r->h->allowedxerror == -1) {
1035 		r->h->allowedxerror = event->error_code;
1036 	}
1037 	return 0;		/* ignored anyway */
1038 }
1039 
1040 
1041 
1042 #ifdef TEXT_SHADOW
1043 /* INTPROTO */
1044 void
rxvt_init_shadow_mode(rxvt_t * r,const char * shadow_mode)1045 rxvt_init_shadow_mode (rxvt_t* r, const char* shadow_mode)
1046 {
1047 	if (!shadow_mode ||
1048 		!STRCASECMP ("botright", shadow_mode) ||
1049 		!STRCASECMP ("default", shadow_mode))	{
1050 		r->TermWin.shadow_mode = SHADOW_BOTRIGHT;
1051 	}
1052 	else if (!STRCASECMP ("botleft", shadow_mode))	{
1053 		r->TermWin.shadow_mode = SHADOW_BOTLEFT;
1054 	}
1055 	else if (!STRCASECMP ("topright", shadow_mode))	{
1056 		r->TermWin.shadow_mode = SHADOW_TOPRIGHT;
1057 	}
1058 	else if (!STRCASECMP ("topleft", shadow_mode))	{
1059 		r->TermWin.shadow_mode = SHADOW_TOPLEFT;
1060 	}
1061 	else if (!STRCASECMP ("top", shadow_mode))	{
1062 		r->TermWin.shadow_mode = SHADOW_TOP;
1063 	}
1064 	else if (!STRCASECMP ("bottom", shadow_mode))	{
1065 		r->TermWin.shadow_mode = SHADOW_BOTTOM;
1066 	}
1067 	else if (!STRCASECMP ("left", shadow_mode))	{
1068 		r->TermWin.shadow_mode = SHADOW_LEFT;
1069 	}
1070 	else if (!STRCASECMP ("right", shadow_mode))	{
1071 		r->TermWin.shadow_mode = SHADOW_RIGHT;
1072 	}
1073 	else if (!STRCASECMP ("none", shadow_mode))	{
1074 		r->TermWin.shadow_mode = SHADOW_NONE;
1075 	}
1076 	else	{	/* no match == default */
1077 		r->TermWin.shadow_mode = SHADOW_NONE;
1078 	}
1079 }
1080 #endif
1081 
1082 
1083 /*----------------------------------------------------------------------*/
1084 /* EXTPROTO */
1085 const char**
rxvt_init_resources(rxvt_t * r,int argc,const char * const * argv)1086 rxvt_init_resources(rxvt_t* r, int argc, const char *const *argv)
1087 {
1088 	register int	i, r_argc;
1089 	const char**	cmd_argv;
1090 	const char**	r_argv;
1091 	const char**	rs;
1092 
1093 
1094 /*
1095  * Look for -exec option.  Find => split and make cmd_argv[] of command args
1096  */
1097 	for (r_argc = 0; r_argc < argc; r_argc++)
1098 	if (!STRCMP(argv[r_argc], "-e") || !STRCMP(argv[r_argc], "-exec"))
1099 		break;
1100 	r_argv = (const char **)rxvt_malloc(sizeof(char*) * (r_argc + 1));
1101 
1102 	for (i = 0; i < r_argc; i++)
1103 	r_argv[i] = (const char *)argv[i];
1104 	r_argv[i] = NULL;
1105 	if (r_argc == argc)
1106 		cmd_argv = NULL;
1107 	else {
1108 		cmd_argv = (const char **)rxvt_malloc(sizeof(char*) * (argc - r_argc));
1109 
1110 		for (i = 0; i < argc - r_argc - 1; i++)
1111 			cmd_argv[i] = (const char *)argv[i + r_argc + 1];
1112 		cmd_argv[i] = NULL;
1113 	}
1114 
1115 	/* clear all resources */
1116 	rs = r->h->rs;
1117 	for (i = 0; i < NUM_RESOURCES;)
1118 		rs[i++] = NULL;
1119 
1120 	rs[Rs_name] = rxvt_r_basename(argv[0]);
1121 
1122 	/*
1123 	** Open display, get options/resources and create the window
1124 	*/
1125 	if ((rs[Rs_display_name] = getenv("DISPLAY")) == NULL)
1126 		rs[Rs_display_name] = ":0";
1127 
1128 	rxvt_get_options(r, r_argc, r_argv);
1129 	free(r_argv);
1130 
1131 #ifdef LOCAL_X_IS_UNIX
1132 	if (rs[Rs_display_name][0] == ':') {
1133 		int		l = 5 + STRLEN(rs[Rs_display_name]);
1134 		if (l <= 0 || l > 1024) /* possible integer overflow */
1135 			l = 1024;
1136 		val = rxvt_malloc(l);
1137 		STRCPY(val, "unix");
1138 		STRNCAT(val, rs[Rs_display_name], l-5);
1139 		val[l-1] = (char) 0;
1140 		DBG_MSG(1, (stderr, "Open X display %s\n", val));
1141 		r->Xdisplay = XOpenDisplay(val);
1142 		free(val);
1143 	}
1144 #endif
1145 
1146 	if (r->Xdisplay == NULL)	{
1147 		DBG_MSG(1, (stderr, "Open X display %s\n", rs[Rs_display_name] ? rs[Rs_display_name] : "nil"));
1148 		r->Xdisplay = XOpenDisplay(rs[Rs_display_name]);
1149 		if (NULL == r->Xdisplay)	{
1150 			rxvt_print_error("can't open display %s", rs[Rs_display_name]);
1151 			exit(EXIT_FAILURE);
1152 		}
1153 	}
1154 
1155 
1156 #ifdef DEBUG_X
1157 	XSynchronize(r->Xdisplay, True);
1158 	XSetErrorHandler((XErrorHandler) abort);
1159 	/* XSetErrorHandler((XErrorHandler) rxvt_xerror_handler); */
1160 #else
1161 	XSetErrorHandler((XErrorHandler) rxvt_xerror_handler);
1162 #endif
1163 
1164 	/* Initialize all atoms after establishing connection to X */
1165 	for (i = 0; i < NUM_XA; i++)	{
1166 		r->h->xa[i] = XInternAtom(r->Xdisplay, xa_names[i], False);
1167 	}
1168 
1169 
1170 	rxvt_extract_resources(r, r->Xdisplay, rs[Rs_name]);
1171 
1172 	/*
1173 	** set any defaults not already set
1174 	*/
1175 	if (cmd_argv && cmd_argv[0]) {
1176 		if (!rs[Rs_title])
1177 			rs[Rs_title] = rxvt_r_basename(cmd_argv[0]);
1178 		if (!rs[Rs_iconName])
1179 			rs[Rs_iconName] = rs[Rs_title];
1180 	}
1181 	else {
1182 		if (!rs[Rs_title])
1183 			rs[Rs_title] = rs[Rs_name];
1184 		if (!rs[Rs_iconName])
1185 			rs[Rs_iconName] = rs[Rs_name];
1186 	}
1187 
1188 	if (rs[Rs_saveLinesAll])	{
1189 		register int	tmp = atoi(rs[Rs_saveLinesAll]);
1190 		r->TermWin.saveLines = (tmp >=0 && tmp <= MAX_SAVELINES) ?  tmp : DEFAULT_SAVELINES;
1191 	}
1192 
1193 #ifndef NO_FRILLS
1194 	if (rs[Rs_int_bwidth])	{
1195 		register int	tmp = atoi (rs[Rs_int_bwidth]);
1196 		r->TermWin.int_bwidth = (tmp >= 0 && tmp <= MAX_INTERNALBORDERWIDTH) ? tmp : DEFAULT_INTERNALBORDERWIDTH;
1197 	}
1198 
1199 	if (rs[Rs_ext_bwidth])	{
1200 		register int	tmp = atoi (rs[Rs_ext_bwidth]);
1201 		r->TermWin.ext_bwidth = (tmp >= 0 && tmp <= MAX_EXTERNALBORDERWIDTH) ? tmp : DEFAULT_EXTERNALBORDERWIDTH;
1202 	}
1203 #endif
1204 
1205 #ifndef NO_LINESPACE
1206 	if (rs[Rs_lineSpace])	{
1207 		register int	tmp = atoi (rs[Rs_lineSpace]);
1208 		r->TermWin.lineSpace = (tmp >= 0 && tmp <= MAX_LINESPACE) ? tmp : DEFAULT_LINESPACE;
1209 	}
1210 #endif
1211 
1212 #ifdef POINTER_BLANK
1213 	if (rs[Rs_pointerBlankDelay])	{
1214 		register int	tmp = atoi (rs[Rs_pointerBlankDelay]);
1215 		r->h->pointerBlankDelay = (tmp >= 0 && tmp <= MAX_BLANKDELAY) ? tmp : DEFAULT_BLANKDELAY;
1216 	}
1217 #endif
1218 
1219 	/* Handle opacity of translucent window */
1220 	if (rs[Rs_opacity])		{
1221 		register int	tmp = atoi (rs[Rs_opacity]);
1222 		r->TermWin.opacity = (tmp >= 0 && tmp <= 100) ? 100 - tmp : 0;
1223 
1224 #ifdef TRANSPARENT
1225 		if (None != r->h->xa[XA_NET_WM_WINDOW_OPACITY] &&
1226 			r->Options & Opt_transparent)	{
1227 			/* Override pseudo-transparent */
1228 			r->Options &= ~Opt_transparent;
1229 		}
1230 #endif
1231 	}
1232 	if (rs[Rs_opacityDegree])		{
1233 		register int	tmp = atoi (rs[Rs_opacityDegree]);
1234 		r->TermWin.opacity_degree = (tmp > 0 && tmp <= 100) ? tmp : 1;
1235 	}
1236 
1237 #if defined(BACKGROUND_IMAGE) || defined(TRANSPARENT)
1238 	if (rs[Rs_backgroundFade])	{
1239 		register int	fade;
1240 		fade = atoi (rs[Rs_backgroundFade]);
1241 		if (fade < 0 || fade > 100)
1242 			fade = 100;
1243 		r->TermWin.bgfade = 100 - fade;
1244 	}
1245 
1246 # ifdef TINTING_SUPPORT
1247 	if (rs[Rs_shade])	{
1248 		register int	shade;
1249 		shade = atoi (rs[Rs_shade]);
1250 		if (shade < 0 || shade > 100)
1251 			shade = 100;
1252 		r->TermWin.shade = 100 - shade;
1253 	}
1254 # endif
1255 #endif
1256 
1257 #ifdef OFF_FOCUS_FADING
1258 	if (rs[Rs_fade])	{
1259 		register int	fade;
1260 		fade = atoi (rs[Rs_fade]);
1261 		if (fade < 0 || fade > 100)
1262 			fade = 100;
1263 		r->TermWin.fade = 100 - fade;
1264 	}
1265 #endif
1266 
1267 #ifdef CURSOR_BLINK
1268 	if (rs[Rs_cursorBlinkInterval])	{
1269 		register long	tmp = (long) atoi (rs[Rs_cursorBlinkInterval]);
1270 		r->h->blinkInterval = (tmp >= MIN_BLINK_TIME && tmp <= MAX_BLINK_TIME) ? tmp : DEFAULT_BLINK_TIME;
1271 	}
1272 	/* convert msec to usec */
1273 	r->h->blinkInterval *= 1000;
1274 #endif
1275 
1276 #ifdef PRINTPIPE
1277 	if (!rs[Rs_print_pipe])
1278 		rs[Rs_print_pipe] = PRINTPIPE;
1279 #endif
1280 	if (!rs[Rs_cutchars])
1281 		rs[Rs_cutchars] = CUTCHARS;
1282 #ifdef ACS_ASCII
1283 	if (!rs[Rs_acs_chars])
1284 		rs[Rs_acs_chars] = ACS_CHARS;
1285 	if ((i = STRLEN(rs[Rs_acs_chars])) < 0x20) {
1286 		val = rxvt_realloc((void *)rs[Rs_acs_chars], 0x20);
1287 		for (; i < 0x20; )
1288 			val[i] = ' ';
1289 		rs[Rs_acs_chars] = val;
1290 	}
1291 #endif
1292 #ifndef NO_BACKSPACE_KEY
1293 	if (!rs[Rs_backspace_key])
1294 # ifdef DEFAULT_BACKSPACE
1295 		r->h->key_backspace = DEFAULT_BACKSPACE;
1296 # else
1297 		r->h->key_backspace = "DEC";	/* can toggle between \010 or \177 */
1298 # endif
1299 	else {
1300 		char*	val = STRDUP(rs[Rs_backspace_key]);
1301 		rxvt_str_trim(val);
1302 		rxvt_str_escaped(val);
1303 		r->h->key_backspace = val;
1304 	}
1305 #endif
1306 #ifndef NO_DELETE_KEY
1307 	if (!rs[Rs_delete_key])
1308 # ifdef DEFAULT_DELETE
1309 		r->h->key_delete = DEFAULT_DELETE;
1310 # else
1311 		r->h->key_delete = "\033[3~";
1312 # endif
1313 	else {
1314 		char* val = STRDUP(rs[Rs_delete_key]);
1315 		rxvt_str_trim(val);
1316 		rxvt_str_escaped(val);
1317 		r->h->key_delete = val;
1318 	}
1319 #endif
1320 	if (rs[Rs_answerbackstring]) {
1321 		rxvt_str_trim((char *)rs[Rs_answerbackstring]);
1322 		rxvt_str_escaped((char *)rs[Rs_answerbackstring]);
1323 	}
1324 
1325 	if (rs[Rs_selectstyle]) {
1326 		if (STRNCASECMP(rs[Rs_selectstyle], "oldword", 7) == 0)
1327 			r->selection_style = OLD_WORD_SELECT;
1328 #ifndef NO_OLD_SELECTION
1329 		else if (STRNCASECMP(rs[Rs_selectstyle], "old", 3) == 0)
1330 			r->selection_style = OLD_SELECT;
1331 #endif
1332 	}
1333 
1334 
1335 	/* Set default X11 fonts */
1336 	rxvt_set_default_font_x11 (r);
1337 #ifdef XFT_SUPPORT
1338 	if (rs[Rs_xftsz])	{
1339 		int		sz = (int) atof (rs[Rs_xftsz]);
1340 		r->TermWin.xftsize = (sz >= MIN_XFT_FONT_SIZE) ? sz : MIN_XFT_FONT_SIZE;
1341 	}
1342 	else /* default xft font size */
1343 		r->TermWin.xftsize = DEFAULT_XFT_FONT_SIZE;
1344 # ifdef MULTICHAR_SET
1345 	if (rs[Rs_xftmsz])	{
1346 		int		sz = (int) atof (rs[Rs_xftmsz]);
1347 		r->TermWin.xftmsize = (sz >= MIN_XFT_FONT_SIZE) ? sz : MIN_XFT_FONT_SIZE;
1348 	}
1349 	else /* default xft font size */
1350 		r->TermWin.xftmsize = DEFAULT_XFT_FONT_SIZE;
1351 # endif	/* MULTICHAR_SET */
1352 
1353 	/* Set default Freetype fonts */
1354 	rxvt_set_default_font_xft (r);
1355 #endif	/* XFT_SUPPORT */
1356 
1357 
1358 #ifdef TEXT_SHADOW
1359 	rxvt_init_shadow_mode (r, rs[Rs_textShadowMode]);
1360 #endif
1361 
1362 #ifdef XTERM_REVERSE_VIDEO
1363 	/* this is how xterm implements reverseVideo */
1364 	if (r->Options & Opt_reverseVideo) {
1365 		if (!rs[Rs_color + Color_fg])
1366 			rs[Rs_color + Color_fg] = def_colorName[Color_bg];
1367 		if (!rs[Rs_color + Color_bg])
1368 			rs[Rs_color + Color_bg] = def_colorName[Color_fg];
1369 
1370 		for (i = 0; i < MAX_PAGES; i++) {
1371 			int		vtfg = Rs_color + TOTAL_COLORS + i;
1372 			int		vtbg = Rs_color + TOTAL_COLORS + MAX_PAGES + i;
1373 			char*	fg = (char*) rs[vtfg];
1374 			char*	bg = (char*) rs[vtbg];
1375 			/* foreground color of i terminal */
1376 			if (ISSET_VTFG(r, i))
1377 				rs[vtfg] = ISSET_VTBG(r, i) ? bg :
1378 								def_colorName[Color_bg];
1379 			/* background color of i terminal */
1380 			if (ISSET_VTBG(r, i))
1381 				rs[vtbg] = ISSET_VTFG(r, i) ? fg :
1382 							def_colorName[Color_fg];
1383 		}
1384 	}
1385 #endif
1386 
1387 	for (i = 0; i < NRS_COLORS; i++)
1388 		if (!rs[Rs_color + i])
1389 			rs[Rs_color + i] = def_colorName[i];
1390 
1391 #ifndef XTERM_REVERSE_VIDEO
1392 	/* this is how we implement reverseVideo */
1393 	if (r->Options & Opt_reverseVideo)	{
1394 		SWAP_IT(rs[Rs_color + Color_fg], rs[Rs_color + Color_bg], const char *);
1395 		for (i = 0; i < MAX_PAGES; i++)	{
1396 			int		vtfg = Rs_color + TOTAL_COLORS + i;
1397 			int		vtbg = Rs_color + TOTAL_COLORS + MAX_PAGES + i;
1398 			SWAP_IT(rs[vtfg], rs[vtbg], const char*);
1399 		}
1400 	}
1401 #endif
1402 
1403 /* convenient aliases for setting fg/bg to colors */
1404 	rxvt_color_aliases(r, Color_fg);
1405 	rxvt_color_aliases(r, Color_bg);
1406 #ifndef NO_CURSORCOLOR
1407 	rxvt_color_aliases(r, Color_cursor);
1408 	rxvt_color_aliases(r, Color_cursor2);
1409 #endif				/* NO_CURSORCOLOR */
1410 	rxvt_color_aliases(r, Color_pointer);
1411 	rxvt_color_aliases(r, Color_border);
1412 #ifndef NO_BOLD_UNDERLINE_REVERSE
1413 	rxvt_color_aliases(r, Color_BD);
1414 	rxvt_color_aliases(r, Color_UL);
1415 	rxvt_color_aliases(r, Color_RV);
1416 #endif				/* ! NO_BOLD_UNDERLINE_REVERSE */
1417 
1418 	return cmd_argv;
1419 }
1420 
1421 /*----------------------------------------------------------------------*/
1422 /* EXTPROTO */
1423 void
rxvt_init_env(rxvt_t * r)1424 rxvt_init_env(rxvt_t *r)
1425 {
1426 	int				i;
1427 	unsigned int	u;
1428 	char*			val;
1429 
1430 
1431 #ifdef DISPLAY_IS_IP
1432 	/* Fixup display_name for export over pty to any interested
1433 	** terminal clients via "ESC[7n" (e.g. shells).  Note we use
1434 	** the pure IP number (for the first non-loopback interface)
1435 	** that we get from rxvt_network_display(). This is more
1436 	** "name-resolution-portable", if you will, and probably allows
1437 	** for faster x-client startup if your name server is beyond
1438 	** a slow link or overloaded at client startup. Of course that
1439 	** only helps the shell's child processes, not us.
1440 	**
1441 	** Giving out the display_name also affords a potential
1442 	** security hole
1443 	*/
1444 	val = rxvt_network_display(r->h->rs[Rs_display_name]);
1445 	r->h->rs[Rs_display_name] = (const char *)val;
1446 	if (val == NULL)
1447 #endif				/* DISPLAY_IS_IP */
1448 	val = XDisplayString(r->Xdisplay);
1449 	if (r->h->rs[Rs_display_name] == NULL)
1450 		r->h->rs[Rs_display_name] = val;	/* use broken `:0' value */
1451 
1452 	i = STRLEN(val) + 9;
1453 	if (i <= 0 || i > 1024)	/* possible integer overflow */
1454 		i = 1024;
1455 	r->h->env_display = rxvt_malloc(i * sizeof(char));
1456 	STRCPY (r->h->env_display, "DISPLAY=");
1457 	STRNCAT (r->h->env_display, val, i-9);
1458 	r->h->env_display[i-1] = (char) 0;
1459 
1460 	/* avoiding the math library:
1461 	 * i = (int)(ceil(log10((unsigned int)r->TermWin.parent))) */
1462 	for (i = 0, u = (unsigned int)r->TermWin.parent; u; u /= 10, i++)
1463 		;
1464 	MAX_IT(i, 1);
1465 	r->h->env_windowid = rxvt_malloc((i + 10) * sizeof(char));
1466 
1467 	sprintf(r->h->env_windowid, "WINDOWID=%u",
1468 		(unsigned int)r->TermWin.parent);
1469 
1470 	/*
1471 	** add entries to the environment:
1472 	** @ DISPLAY:   in case we started with -display
1473 	** @ WINDOWID:  X window id number of the window
1474 	** @ COLORTERM: terminal sub-name and also indicates its color
1475 	** @ TERM:		terminal name
1476 	** @ TERMINFO:	path to terminfo directory
1477 	*/
1478 #ifdef HAVE_PUTENV
1479 	putenv(r->h->env_display);
1480 	putenv(r->h->env_windowid);
1481 
1482 # ifdef RXVT_TERMINFO
1483 	putenv("TERMINFO=" RXVT_TERMINFO);
1484 # endif
1485 	if (XDEPTH <= 2)
1486 		putenv("COLORTERM=" COLORTERMENV "-mono");
1487 	else
1488 		putenv("COLORTERM=" COLORTERMENVFULL);
1489 	if (r->h->rs[Rs_term_name] != NULL) {
1490 		int		l = 6 + STRLEN(r->h->rs[Rs_term_name]);
1491 		if (l <= 0 || l > 1024)	/* possible integer overflow */
1492 			l = 1024;
1493 		r->h->env_term = rxvt_malloc(l * sizeof(char));
1494 		STRCPY (r->h->env_term, "TERM=");
1495 		STRNCAT (r->h->env_term, r->h->rs[Rs_term_name], l-6);
1496 		r->h->env_term[l-1] = (char) 0;
1497 		putenv(r->h->env_term);
1498 	}
1499 	else
1500 		putenv("TERM=" TERMENV);
1501 #endif	/* HAVE_PUTENV */
1502 
1503 #ifdef HAVE_UNSETENV
1504 	/* avoid passing old settings and confusing term size */
1505 	unsetenv("LINES");
1506 	unsetenv("COLUMNS");
1507 	unsetenv("TERMCAP");	/* terminfo should be okay */
1508 #endif				/* HAVE_UNSETENV */
1509 
1510 	/*
1511 	** allocate environment variable for MRXVT_TABTITLE, we will
1512 	** use it in rxvt_create_termwin later for each tab terminal
1513 	*/
1514 	r->h->env_tabtitle = rxvt_malloc(sizeof(TABTITLEENV) + MAX_TAB_TXT + 1);
1515 }
1516 
1517 /*----------------------------------------------------------------------*/
1518 /*
1519  * This is more or less stolen straight from XFree86 xterm.
1520  * This should support all European type languages.
1521  */
1522 /* EXTPROTO */
1523 void
rxvt_init_xlocale(rxvt_t * r)1524 rxvt_init_xlocale(rxvt_t *r)
1525 {
1526 #ifdef USE_XIM
1527 	if (r->h->locale == NULL)
1528 		rxvt_print_error("Setting locale failed.");
1529 	else {
1530 		XChangeProperty(r->Xdisplay, r->TermWin.parent,
1531 			r->h->xa[XA_WM_LOCALE_NAME], XA_STRING, 8, PropModeReplace,
1532 			(unsigned char *)r->h->locale, STRLEN(r->h->locale));
1533 
1534 		if (XSupportsLocale() != True) {
1535 			rxvt_print_error("The locale is not supported by Xlib");
1536 			return;
1537 		}
1538 		rxvt_IM_set_fontset (r, 0);
1539 
1540 		/* see if we can connect yet */
1541 		rxvt_IM_init_callback (r->Xdisplay, NULL, NULL);
1542 
1543 		/* To avoid Segmentation Fault in C locale: Solaris only? */
1544 		if (STRCMP(r->h->locale, "C"))
1545 			XRegisterIMInstantiateCallback(r->Xdisplay, NULL, NULL,
1546 				NULL, rxvt_IM_init_callback, NULL);
1547 	}
1548 #endif
1549 }
1550 
1551 /*----------------------------------------------------------------------*/
1552 /* EXTPROTO */
1553 void
rxvt_init_command(rxvt_t * r,const char * const * argv)1554 rxvt_init_command(rxvt_t* r, const char *const *argv)
1555 {
1556 	/*
1557 	** Initialize the command connection. This should be called
1558 	** after the X server connection is established.
1559 	*/
1560 	struct sigaction	act;
1561 
1562 
1563 	/*
1564 	** Enable delete window protocol so that if the top-level window
1565 	** of the terminal is destroyed by the Session Manager, we can
1566 	** receive a ClientMessage event and do something gracefully.
1567 	*/
1568 	XSetWMProtocols (r->Xdisplay, r->TermWin.parent,
1569 			&(r->h->xa[XA_WMDELETEWINDOW]), 1);
1570 
1571 #ifdef META8_OPTION
1572 	r->h->meta_char = (r->Options & Opt_meta8 ? 0x80 : C0_ESC);
1573 #endif
1574 	rxvt_get_ourmods(r);
1575 
1576 #ifdef GREEK_SUPPORT
1577 	greek_init();
1578 #endif
1579 
1580 	r->Xfd = XConnectionNumber(r->Xdisplay);
1581 
1582 #ifdef CURSOR_BLINK
1583 	if (r->Options & Opt_cursorBlink)
1584 		(void)gettimeofday(&r->h->lastcursorchange, NULL);
1585 #endif
1586 
1587 
1588 	act.sa_handler = rxvt_Exit_signal;
1589 	act.sa_flags = 0;
1590 	sigemptyset (&act.sa_mask);
1591 	sigaction (SIGHUP, &act, NULL);
1592 #ifndef OS_SVR4
1593 	sigaction (SIGINT, &act, NULL);
1594 #endif
1595 	sigaction (SIGQUIT, &act, NULL);
1596 	sigaction (SIGTERM, &act, NULL);
1597 
1598 	act.sa_handler = rxvt_Child_signal;
1599 	act.sa_flags = 0;
1600 	sigaction (SIGCHLD, &act, NULL);
1601 
1602 	/*
1603 	signal(SIGHUP, rxvt_Exit_signal);
1604 #ifndef OS_SVR4
1605 	signal(SIGINT, rxvt_Exit_signal);
1606 #endif
1607 	signal(SIGQUIT, rxvt_Exit_signal);
1608 	signal(SIGTERM, rxvt_Exit_signal);
1609 	signal(SIGCHLD, rxvt_Child_signal);
1610 	*/
1611 
1612 	/* need to trap SIGURG for SVR4 (Unixware) rlogin */
1613 	/* signal (SIGURG, SIG_DFL); */
1614 }
1615 
1616 
1617 
1618 #ifdef OFF_FOCUS_FADING
1619 /* EXTPROTO */
1620 unsigned long
rxvt_fade_color(rxvt_t * r,unsigned long pixel)1621 rxvt_fade_color (rxvt_t* r, unsigned long pixel)
1622 {
1623 	if (r->h->rs[Rs_fade])	{
1624 		XColor	faded_xcol;
1625 
1626 		faded_xcol.pixel = pixel;
1627 		XQueryColor (r->Xdisplay, XCMAP, &faded_xcol);
1628 		faded_xcol.red   = (faded_xcol.red / 100) * r->TermWin.fade;
1629 		faded_xcol.green = (faded_xcol.green / 100) * r->TermWin.fade;
1630 		faded_xcol.blue  = (faded_xcol.blue / 100) * r->TermWin.fade;
1631 
1632 		rxvt_alloc_color (r, &faded_xcol, "Faded");
1633 		return faded_xcol.pixel;
1634 	}
1635 
1636 	return pixel;
1637 }
1638 #endif
1639 
1640 
1641 /*
1642 ** rxvt_restore_ufbg_color should always be called before
1643 ** rxvt_restore_pix_color.
1644 */
1645 /* EXTPROTO */
1646 int
rxvt_restore_ufbg_color(rxvt_t * r)1647 rxvt_restore_ufbg_color (rxvt_t* r)
1648 {
1649 	/* Restore bg and ufbg color state now */
1650 	if (ISSET_PIXCOLOR(r->h, Color_ufbg) && r->ufbg_switched)	{
1651 		DBG_MSG(2, (stderr, "switch back to bg color\n"));
1652 		SWAP_IT (r->PixColors[Color_bg], r->PixColors[Color_ufbg],
1653 			unsigned long);
1654 		r->ufbg_switched = 0;
1655 		return (1);	/* switched */
1656 	}
1657 	return (0);	/* no change */
1658 }
1659 
1660 
1661 /*
1662 ** rxvt_switch_pix_color should always be called before
1663 ** rxvt_switch_ufbg_color.
1664 */
1665 /* EXTPROTO */
1666 int
rxvt_switch_ufbg_color(rxvt_t * r)1667 rxvt_switch_ufbg_color (rxvt_t* r)
1668 {
1669 	if (ISSET_PIXCOLOR(r->h, Color_ufbg) && !r->ufbg_switched)	{
1670 		DBG_MSG(2, (stderr, "switch to ufbg color\n"));
1671 		SWAP_IT (r->PixColors[Color_bg], r->PixColors[Color_ufbg],
1672 			unsigned long);
1673 		r->ufbg_switched = 1;
1674 		return (1);	/* switched */
1675 	}
1676 	return (0);	/* no change */
1677 }
1678 
1679 
1680 #ifdef OFF_FOCUS_FADING
1681 /* EXTPROTO */
1682 int
rxvt_restore_pix_color(rxvt_t * r)1683 rxvt_restore_pix_color (rxvt_t* r)
1684 {
1685 	/* Restore off-focus color state now */
1686 	if (r->h->rs[Rs_fade] && r->color_switched)	{
1687 		DBG_MSG(2, (stderr, "switch back to focus color\n"));
1688 		SWAP_IT (r->PixColors, r->PixColorsUnfocus, unsigned long*);
1689 		r->color_switched = 0;
1690 		return (1);	/* switched */
1691 	}
1692 	return (0);	/* no change */
1693 }
1694 
1695 
1696 /* EXTPROTO */
1697 int
rxvt_switch_pix_color(rxvt_t * r)1698 rxvt_switch_pix_color (rxvt_t* r)
1699 {
1700 	if (r->h->rs[Rs_fade] && !r->color_switched)	{
1701 		DBG_MSG(2, (stderr, "switch back to unfocus color\n"));
1702 		SWAP_IT (r->PixColors, r->PixColorsUnfocus, unsigned long*);
1703 		r->color_switched = 1;
1704 		return (1);	/* switched */
1705 	}
1706 	return (0);	/* no change */
1707 }
1708 #endif
1709 
1710 
1711 /* INTPROTO */
1712 void
rxvt_init_colors(rxvt_t * r)1713 rxvt_init_colors (rxvt_t *r)
1714 {
1715 	register int	i;
1716 
1717 
1718 	for (i = 0; i < (XDEPTH <= 2 ? 2 : NRS_COLORS); i++) {
1719 		XColor			xcol;
1720 
1721 		if (!r->h->rs[Rs_color + i])
1722 			continue;
1723 
1724 		if (!rxvt_parse_alloc_color(r, &xcol, r->h->rs[Rs_color + i])) {
1725 #ifndef XTERM_REVERSE_VIDEO
1726 			if (i < 2 && (r->Options & Opt_reverseVideo)) {
1727 				r->h->rs[Rs_color + i] = def_colorName[!i];
1728 			}
1729 			else
1730 #endif
1731 				r->h->rs[Rs_color + i] = def_colorName[i];
1732 
1733 			if (!r->h->rs[Rs_color + i])
1734 				continue;
1735 			if (!rxvt_parse_alloc_color (r, &xcol,
1736 				r->h->rs[Rs_color + i])) {
1737 				switch (i) {
1738 				case Color_fg:
1739 				case Color_bg:
1740 					/* fatal: need bg/fg color */
1741 					rxvt_print_error("aborting");
1742 					exit(EXIT_FAILURE);
1743 					/* NOTREACHED */
1744 					break;
1745 #ifndef NO_CURSORCOLOR
1746 				case Color_cursor2:
1747 					xcol.pixel = r->PixColors[Color_fg];
1748 					break;
1749 #endif				/* ! NO_CURSORCOLOR */
1750 				case Color_pointer:
1751 					xcol.pixel = r->PixColors[Color_fg];
1752 					break;
1753 				default:
1754 					xcol.pixel = r->PixColors[Color_bg];	/* None */
1755 					break;
1756 				}
1757 			}
1758 		}
1759 		r->PixColors[i] = xcol.pixel;
1760 #ifdef OFF_FOCUS_FADING
1761 		r->PixColorsUnfocus[i] = rxvt_fade_color (r, xcol.pixel);
1762 #endif
1763 #ifdef XFT_SUPPORT
1764 		rxvt_alloc_xft_color (r, xcol.pixel, &(r->XftColors[i]));
1765 #endif
1766 		SET_PIXCOLOR(r->h, i);
1767 	}
1768 
1769 	if (XDEPTH <= 2 || !r->h->rs[Rs_color + Color_pointer])	{
1770 		r->PixColors[Color_pointer] = r->PixColors[Color_fg];
1771 #ifdef XFT_SUPPORT
1772 		r->XftColors[Color_pointer] = r->XftColors[Color_fg];
1773 #endif
1774 	}
1775 	if (XDEPTH <= 2 || !r->h->rs[Rs_color + Color_border])	{
1776 		r->PixColors[Color_border] = r->PixColors[Color_fg];
1777 #ifdef XFT_SUPPORT
1778 		r->XftColors[Color_border] = r->XftColors[Color_fg];
1779 #endif
1780 	}
1781 
1782 
1783 	/* we have not switched the bg/ufbg color */
1784 	r->ufbg_switched = 0;
1785 
1786 	/* Save global foreground/background colors */
1787 	r->h->global_fg = r->PixColors[Color_fg];
1788 	r->h->global_bg = r->PixColors[Color_bg];
1789 #ifdef XFT_SUPPORT
1790 	r->h->global_xftfg = r->XftColors[Color_fg];
1791 	r->h->global_xftbg = r->XftColors[Color_bg];
1792 #endif
1793 
1794 
1795 	/* Initialize fg/bg colors for individual terminals */
1796 	for (i = 0; i < MAX_PAGES; i++) {
1797 		XColor		xcol;
1798 		int			vtfg = Rs_color + TOTAL_COLORS + i;
1799 		int			vtbg = Rs_color + TOTAL_COLORS + MAX_PAGES + i;
1800 
1801 		/* foreground color of i terminal */
1802 		if (ISSET_VTFG(r, i) &&
1803 			rxvt_parse_alloc_color(r, &xcol, r->h->rs[vtfg]))	{
1804 			VTFG(r, i) = xcol.pixel;
1805 #ifdef XFT_SUPPORT
1806 			rxvt_alloc_xft_color (r, VTFG(r, i), &(VTXFTFG(r, i)));
1807 #endif
1808 		}
1809 
1810 		/* background color of i terminal */
1811 		if (ISSET_VTBG(r, i) &&
1812 			rxvt_parse_alloc_color(r, &xcol, r->h->rs[vtbg]))	{
1813 			VTBG(r, i) = xcol.pixel;
1814 #ifdef XFT_SUPPORT
1815 			rxvt_alloc_xft_color (r, VTBG(r, i), &(VTXFTBG(r, i)));
1816 #endif
1817 		}
1818 	}
1819 
1820 
1821 	/*
1822 	** get scrollBar/menuBar shadow colors
1823 	**
1824 	** The calculations of topShadow/bottomShadow values are adapted
1825 	** from the fvwm window manager.
1826 	**/
1827 #ifdef KEEP_SCROLLCOLOR
1828 	if (XDEPTH <= 2) {	/* Monochrome */
1829 		r->PixColors[Color_scroll] = r->PixColors[Color_fg];
1830 		r->PixColors[Color_topShadow] = r->PixColors[Color_bg];
1831 		r->PixColors[Color_bottomShadow] = r->PixColors[Color_bg];
1832 	}
1833 	else {
1834 		XColor			xcol[3];
1835 		/* xcol[0] == white
1836 		 * xcol[1] == top shadow
1837 		 * xcol[2] == bot shadow */
1838 
1839 		xcol[1].pixel = r->PixColors[Color_scroll];
1840 # ifdef PREFER_24BIT
1841 		xcol[0].red = xcol[0].green = xcol[0].blue = (unsigned short)~0;
1842 		rxvt_alloc_color(r, &(xcol[0]), "White");
1843 /*		XFreeColors(r->Xdisplay, XCMAP, &(xcol[0].pixel), 1, ~0); */
1844 		XQueryColors(r->Xdisplay, XCMAP, &(xcol[1]), 1);
1845 # else
1846 		xcol[0].pixel = WhitePixel(r->Xdisplay, XSCREEN);
1847 		XQueryColors(r->Xdisplay, XCMAP, xcol, 2);
1848 # endif
1849 
1850 		/* bottomShadowColor */
1851 		xcol[2].red = xcol[1].red / 2;
1852 		xcol[2].green = xcol[1].green / 2;
1853 		xcol[2].blue = xcol[1].blue / 2;
1854 		if (!rxvt_alloc_color(r, &(xcol[2]), "Color_bottomShadow"))
1855 			xcol[2].pixel = r->PixColors[Color_Black];
1856 		r->PixColors[Color_bottomShadow] = xcol[2].pixel;
1857 
1858 		/* topShadowColor */
1859 		xcol[1].red = max((xcol[0].red / 5), xcol[1].red);
1860 		xcol[1].green = max((xcol[0].green / 5), xcol[1].green);
1861 		xcol[1].blue = max((xcol[0].blue / 5), xcol[1].blue);
1862 		xcol[1].red = min(xcol[0].red, (xcol[1].red * 7) / 5);
1863 		xcol[1].green = min(xcol[0].green, (xcol[1].green * 7) / 5);
1864 		xcol[1].blue = min(xcol[0].blue, (xcol[1].blue * 7) / 5);
1865 
1866 		if (!rxvt_alloc_color(r, &(xcol[1]), "Color_topShadow"))
1867 			xcol[1].pixel = r->PixColors[Color_White];
1868 		r->PixColors[Color_topShadow] = xcol[1].pixel;
1869 	}
1870 #endif	/* KEEP_SCROLLCOLOR */
1871 
1872 
1873 #ifdef TEXT_SHADOW
1874 	if (r->h->rs[Rs_textShadow])	{
1875 		XColor	xcol;
1876 		if (rxvt_parse_alloc_color (r, &xcol, r->h->rs[Rs_textShadow]))
1877 			r->TermWin.shadow = xcol.pixel;
1878 		else
1879 			r->TermWin.shadow = r->PixColors[Color_Black];
1880 # ifdef XFT_SUPPORT
1881 		rxvt_alloc_xft_color (r, r->TermWin.shadow, &(r->TermWin.xftshadow));
1882 # endif
1883 	}
1884 #endif
1885 }
1886 
1887 
1888 /*----------------------------------------------------------------------*/
1889 /* color aliases, fg/bg bright-bold */
1890 /* INTPROTO */
1891 void
rxvt_color_aliases(rxvt_t * r,int idx)1892 rxvt_color_aliases(rxvt_t* r, int idx)
1893 {
1894 	if (r->h->rs[Rs_color + idx] &&
1895 		isdigit((int) *(r->h->rs[Rs_color + idx]))) {
1896 		int			i = atoi(r->h->rs[Rs_color + idx]);
1897 
1898 		if (i >= 8 && i <= 15) {	/* bright colors */
1899 			i -= 8;
1900 #ifndef NO_BRIGHTCOLOR
1901 			r->h->rs[Rs_color + idx] = r->h->rs[Rs_color + minBrightCOLOR + i];
1902 			return;
1903 #endif
1904 		}
1905 		if (i >= 0 && i <= 7)	/* normal colors */
1906 			r->h->rs[Rs_color + idx] = r->h->rs[Rs_color + minCOLOR +i];
1907 	}
1908 }
1909 
1910 
1911 /* INTPROTO */
1912 void
rxvt_init_win_size(rxvt_t * r)1913 rxvt_init_win_size (rxvt_t* r)
1914 {
1915 	int				flags = 0;	/* must initialize to 0!!! */
1916 	short			recalc_x = 0, recalc_y = 0;
1917 	int				x, y;
1918 	unsigned int	w, h;
1919 
1920 
1921 	r->szHint.flags = PMinSize | PResizeInc | PBaseSize | PWinGravity;
1922 	r->szHint.win_gravity = NorthWestGravity;
1923 
1924 	/* Set default terminal columns and rows */
1925 	r->TermWin.ncol = 80;
1926 	r->TermWin.nrow = 24;
1927 	r->szHint.x = 0;
1928 	r->szHint.y = 0;
1929 
1930 	/* Parse geometry */
1931 	if (r->h->rs[Rs_geometry])
1932 		flags = XParseGeometry(r->h->rs[Rs_geometry], &x, &y, &w, &h);
1933 	if (flags & WidthValue) {
1934 		r->TermWin.ncol = BOUND_POSITIVE_INT16(w);
1935 		r->szHint.flags |= USSize;
1936 	}
1937 	if (flags & HeightValue) {
1938 		r->TermWin.nrow = BOUND_POSITIVE_INT16(h);
1939 		r->szHint.flags |= USSize;
1940 	}
1941 	if (flags & XValue) {
1942 		r->szHint.x = x;
1943 		r->szHint.flags |= USPosition;
1944 		if (flags & XNegative) {
1945 			recalc_x = 1;
1946 			r->szHint.win_gravity = NorthEastGravity;
1947 		}
1948 	}
1949 	if (flags & YValue) {
1950 		r->szHint.y = y;
1951 		r->szHint.flags |= USPosition;
1952 		if (flags & YNegative) {
1953 			recalc_y = 1;
1954 			if (r->szHint.win_gravity == NorthEastGravity)
1955 				r->szHint.win_gravity = SouthEastGravity;
1956 			else
1957 				r->szHint.win_gravity = SouthWestGravity;
1958 		}
1959 	}
1960 
1961 	/* Calculate the base width and height */
1962 	r->szHint.base_width = 2 * r->TermWin.int_bwidth;
1963 	r->szHint.base_height = 2 * r->TermWin.int_bwidth;
1964 #ifdef HAVE_SCROLLBARS
1965 	if (r->Options & Opt_scrollBar)
1966 		r->szHint.base_width += rxvt_scrollbar_rwidth (r);
1967 #endif
1968 #if defined(HAVE_MENUBAR) && (MENUBAR_MAX > 1)
1969 	if (r->Options & Opt_showMenu)
1970 		r->szHint.base_height += rxvt_menubar_rheight (r);
1971 #endif
1972 	if (!(r->Options2 & Opt2_hideTabbar))
1973 		r->szHint.base_height += rxvt_tabbar_rheight (r);
1974 
1975 	/* Calculate the terminal increment width and height */
1976 	r->szHint.width_inc = r->TermWin.fwidth;
1977 	r->szHint.height_inc = r->TermWin.fheight;
1978 
1979 	/* Set the terminal minimal width and height */
1980 	r->szHint.min_width = r->szHint.base_width + r->szHint.width_inc;
1981 	r->szHint.min_height = r->szHint.base_height + r->szHint.height_inc;
1982 
1983 	/* Set the terminal width and height */
1984 	r->szHint.width = r->szHint.base_width + Width2Pixel (r->TermWin.ncol);
1985 	r->szHint.height = r->szHint.base_height + Height2Pixel (r->TermWin.nrow);
1986 
1987 	/* Recalculate the starting position */
1988 	if (recalc_x)
1989 		r->szHint.x += (DisplayWidth(r->Xdisplay, XSCREEN)
1990 			- r->szHint.width - 2 * r->TermWin.ext_bwidth);
1991 	if (recalc_y)
1992 		r->szHint.y += (DisplayHeight(r->Xdisplay, XSCREEN)
1993 			- r->szHint.height - 2 * r->TermWin.ext_bwidth);
1994 
1995 	/* Set the terminal window starting position */
1996 	r->h->window_vt_x = (r->Options & Opt_scrollBar_right) ?
1997 			0 : r->szHint.base_width - 2*r->TermWin.int_bwidth;
1998 	r->h->window_vt_y = r->szHint.base_height - 2*r->TermWin.int_bwidth;
1999 	if ((r->Options2 & Opt2_bottomTabbar) &&
2000 		!(r->Options2 & Opt2_hideTabbar))
2001 		r->h->window_vt_y -= rxvt_tabbar_rheight (r);
2002 }
2003 
2004 
2005 /*----------------------------------------------------------------------*/
2006 /*
2007  * Probe the modifier keymap to get the Meta (Alt) and Num_Lock settings
2008  * Use resource ``modifier'' to override the Meta modifier
2009  */
2010 /* INTPROTO */
2011 void
rxvt_get_ourmods(rxvt_t * r)2012 rxvt_get_ourmods(rxvt_t *r)
2013 {
2014 	int					i, j, k;
2015 	int					requestedmeta, realmeta, realalt;
2016 	const char*			cm;
2017 	const char*			rsmod;
2018 	XModifierKeymap*	map;
2019 	KeyCode*			kc;
2020 	const unsigned int	modmasks[] = {
2021 			Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
2022 		};
2023 
2024 
2025 	requestedmeta = realmeta = realalt = 0;
2026 
2027 	rsmod = r->h->rs[Rs_modifier];
2028 	if (rsmod &&
2029 		STRCASECMP(rsmod, "mod1") >= 0 &&
2030 		STRCASECMP(rsmod, "mod5") <= 0)
2031 		requestedmeta = rsmod[3] - '0';
2032 
2033 	map = XGetModifierMapping(r->Xdisplay);
2034 	kc = map->modifiermap;
2035 	for (i = 1; i < 6; i++) {
2036 		k = (i + 2) * map->max_keypermod;	/* skip shift/lock/control */
2037 		for (j = map->max_keypermod; j--; k++) {
2038 			if (kc[k] == 0)
2039 				break;
2040 
2041 			switch (XKeycodeToKeysym(r->Xdisplay, kc[k], 0)) {
2042 			case XK_Num_Lock:
2043 				r->h->ModNumLockMask = modmasks[i - 1];
2044 				/* FALLTHROUGH */
2045 			default:
2046 				continue;	/* for(;;) */
2047 			case XK_Meta_L:
2048 			case XK_Meta_R:
2049 				cm = "meta";
2050 				realmeta = i;
2051 				break;
2052 			case XK_Alt_L:
2053 			case XK_Alt_R:
2054 				cm = "alt";
2055 				realalt = i;
2056 				break;
2057 			case XK_Super_L:
2058 			case XK_Super_R:
2059 				cm = "super";
2060 				break;
2061 			case XK_Hyper_L:
2062 			case XK_Hyper_R:
2063 				cm = "hyper";
2064 				break;
2065 			}
2066 
2067 			if (rsmod && STRNCASECMP(rsmod, cm, STRLEN(cm)) == 0)
2068 				requestedmeta = i;
2069 		}
2070 	}
2071 	XFreeModifiermap(map);
2072 
2073 	i = (requestedmeta ? requestedmeta : (
2074 			realmeta ? realmeta : (
2075 			realalt ? realalt : 0)));
2076 
2077 	if (i)
2078 		r->h->ModMetaMask = modmasks[i - 1];
2079 }
2080 
2081 
2082 
2083 /* INTPROTO */
2084 char**
rxvt_string_to_argv(char * string,int * argc)2085 rxvt_string_to_argv (char* string, int* argc)
2086 {
2087 	register int	i;
2088 	char**			pret;
2089 	char*			pbeg;
2090 	char*			pcur;
2091 
2092 	/* not implemented yet */
2093 	*argc = 0;
2094 	if (NULL == string)
2095 		return NULL;
2096 
2097 #define MAX_ARGV	(64)
2098 	/* Up to 64 argv */
2099 	pret = (char**) rxvt_malloc (MAX_ARGV * sizeof (char*));
2100 
2101 	DBG_MSG(1, (stderr, "fetch command argv for the tab\n"));
2102 	pbeg = pcur = string;
2103 	for (i = 0; i < MAX_ARGV-1; i ++)	{
2104 		int		dq = 0;	/* double quote */
2105 		int		sq = 0;	/* single quote */
2106 		/* set default argument to NULL */
2107 		pret[i] = NULL;
2108 
2109 		/* skip any spaces and non-printable */
2110 		while (*pcur &&
2111 			(isspace ((int) *pcur) || !isprint ((int) *pcur)))
2112 			pcur ++;
2113 		/* stop if reach end of string */
2114 		if (!*pcur)
2115 			break;
2116 
2117 		/* beginning of the token */
2118 		if (isalnum ((int) *pcur) || ispunct ((int) *pcur))	{
2119 			if ('\"' == *pcur)	{
2120 				/* beginning of double quote */
2121 				dq = 1;	pbeg = pcur + 1; pcur ++;
2122 			}
2123 			else if ('\'' == *pcur)	{
2124 				/* beginning of single quote */
2125 				sq = 1;	pbeg = pcur + 1; pcur ++;
2126 			}
2127 			else /* normal characters */
2128 				pbeg = pcur;
2129 		}
2130 #ifdef DEBUG
2131 		else	/* shouldn't happen */
2132 			assert (0);
2133 #endif
2134 
2135 		/* move forward one character */
2136 		pcur ++;
2137 
2138 		/* now fetch the new token */
2139 		while (*pcur &&					/* not end of string */
2140 			((dq && *pcur != '\"') ||	/* not end of double quote */
2141 			 (sq && *pcur != '\'') ||	/* not end of single quote */
2142 			 (!dq && !sq && !isspace ((int) *pcur))))
2143 			*pcur ++;
2144 
2145 		if (!*pcur &&	/* end of string */
2146 			(dq || sq))	/* no match of quote is found */
2147 			goto NotMatch;
2148 
2149 		if (!*pcur)	{	/* end of string */
2150 			pret[i] = STRDUP (pbeg);
2151 			DBG_MSG(1, (stderr, "   argv[%d] = %s\n", i, pret[i]));
2152 			break;		/* ready to return */
2153 		}
2154 
2155 		if ((dq && *pcur == '\"') ||	/* end of double quote */
2156 			(sq && *pcur == '\'') ||	/* end of single quote */
2157 			(!dq && !sq && isspace ((int) *pcur)))	{	/* space */
2158 			int		len = sizeof (char) * (pcur - pbeg) + 1;
2159 
2160 			assert (len > 0);	/* possible integer overflow? */
2161 			pret[i] = (char*) rxvt_malloc (len * sizeof(char));
2162 			MEMCPY (pret[i], pbeg, len-1);
2163 			pret[i][len-1] = (char) 0;
2164 			DBG_MSG(1, (stderr, "   argv[%d] = %s\n", i, pret[i]));
2165 
2166 			/* forward to next character */
2167 			pcur ++;
2168 
2169 			/* fetch next token */
2170 			continue;
2171 		}
2172 
2173 		/* shouldn't get here */
2174 		assert (0);
2175 	}
2176 
2177 #undef MAX_ARGV
2178 	/* set the end of argv */
2179 	if (pret[i])	{
2180 		*argc = i+1;
2181 		pret[i+1] = NULL;
2182 	}
2183 	else if (i)	{	/* non-empty argv */
2184 		*argc = i;
2185 	}
2186 	else	{	/* empty argv */
2187 		free (pret);
2188 		return NULL;
2189 	}
2190 	return pret;
2191 
2192 NotMatch:
2193 	free (pret);
2194 	return NULL;
2195 }
2196 
2197 
2198 /* EXTPROTO */
2199 void
rxvt_switch_fgbg_color(rxvt_t * r,int page)2200 rxvt_switch_fgbg_color (rxvt_t* r, int page)
2201 {
2202 	/* Restore bg/ufbg color */
2203 	rxvt_restore_ufbg_color (r);
2204 #ifdef OFF_FOCUS_FADING
2205 	/* Restore off-focus color */
2206 	rxvt_restore_pix_color (r);
2207 #endif
2208 
2209 	/*
2210 	** Set fg/bg color of individual terminal
2211 	*/
2212 	r->PixColors[Color_fg] = *(PVTS(r, page)->p_fg);
2213 	r->PixColors[Color_bg] = *(PVTS(r, page)->p_bg);
2214 #ifdef XFT_SUPPORT
2215 	r->XftColors[Color_fg] = *(PVTS(r, page)->p_xftfg);
2216 	r->XftColors[Color_bg] = *(PVTS(r, page)->p_xftbg);
2217 #endif	/* XFT_SUPPORT */
2218 
2219 	/*
2220 	** Set foreground/background color for GC. This is necessary.
2221 	** Since all VTs share the same GC, if we do not set the color
2222 	** here, color from other VTs will be used to draw the following
2223 	** text till there is a color change.
2224 	*/
2225 	XSetForeground (r->Xdisplay, r->TermWin.gc, r->PixColors[Color_fg]);
2226 	XSetBackground (r->Xdisplay, r->TermWin.gc, r->PixColors[Color_bg]);
2227 }
2228 
2229 
2230 /* INTPROTO */
2231 termenv_t
rxvt_get_termenv(const char * env)2232 rxvt_get_termenv (const char* env)
2233 {
2234 	if (NULL == env)
2235 		return (TERMENV_XTERM);
2236 	else if (0 == STRCASECMP (env, "xterm"))
2237 		return (TERMENV_XTERM);
2238 	else if (0 == STRCASECMP (env, "rxvt"))
2239 		return (TERMENV_RXVT);
2240 	else if (0 == STRCASECMP (env, "vt102"))
2241 		return (TERMENV_VT102);
2242 	else if (0 == STRCASECMP (env, "vt100"))
2243 		return (TERMENV_VT100);
2244 	else if (0 == STRCASECMP (env, "ansi"))
2245 		return (TERMENV_ANSI);
2246 	else if (0 == STRCASECMP (env, "dumb"))
2247 		return (TERMENV_DUMB);
2248 	else
2249 		return (TERMENV_XTERM);
2250 }
2251 
2252 
2253 /* INTPROTO */
2254 void
rxvt_init_vts(rxvt_t * r,int page)2255 rxvt_init_vts (rxvt_t* r, int page)
2256 {
2257 #ifdef TTY_GID_SUPPORT
2258 	struct group*	gr = getgrnam("tty");
2259 #endif
2260 	struct tms		tp;
2261 	register int	i;
2262 
2263 
2264 	assert (page < MAX_PAGES);
2265 
2266 	/* look for an unused term_t structure */
2267 	for (i = 0; i < MAX_PAGES; i ++)
2268 		if (-1 == r->vterm[i].vts_idx)
2269 			break;
2270 	assert (i != MAX_PAGES);
2271 	DBG_MSG(1, (stderr, "Find vterm[%d] for pointer vts[%d]\n", i, page));
2272 
2273 	/* clear the term_t structure */
2274 	r->vts[page] = &(r->vterm[i]);
2275 	MEMSET (r->vts[page], 0, sizeof (r->vterm[0]));
2276 	/* set vts_idx for the vterm */
2277 	PVTS(r, page)->vts_idx = i;
2278 
2279 #ifdef TTY_GID_SUPPORT
2280 	/* change group ownership of tty to "tty" */
2281 	if (gr)	{
2282 		PVTS(r, page)->ttymode = S_IRUSR | S_IWUSR | S_IWGRP;
2283 	}
2284 	else
2285 #endif		/* TTY_GID_SUPPORT */
2286 	{
2287 		PVTS(r, page)->ttymode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH;
2288 	}
2289 
2290 	/* Initialize term_t (vts) structure */
2291 	/*
2292 	** How to get saveLines? Try the following sequence:
2293 	** . individual saveLines in .Xdefaults or command line option
2294 	** . saveLines for all tabs in .Xdefaults or command line option
2295 	** . Default saveLines
2296 	*/
2297 	if (r->h->rs[Rs_saveLines+page])	{
2298 		register int	tmp = atoi(r->h->rs[Rs_saveLines+page]);
2299 		PVTS(r, page)->saveLines = (tmp >=0 && tmp <= MAX_SAVELINES) ?  tmp : DEFAULT_SAVELINES;
2300 	}
2301 	else if (r->h->rs[Rs_saveLinesAll])	{
2302 		PVTS(r, page)->saveLines = r->TermWin.saveLines;
2303 	}
2304 	else
2305 		PVTS(r, page)->saveLines = (SAVELINES >= 0 && SAVELINES <= MAX_SAVELINES) ? SAVELINES : DEFAULT_SAVELINES;
2306 
2307 	/* will be set in rxvt_create_termwin */
2308 	PVTS(r, page)->vt = None;
2309 #ifdef XFT_SUPPORT
2310 	PVTS(r, page)->xftvt = NULL;
2311 #endif
2312 	PVTS(r, page)->tab_title = NULL;
2313 #ifdef BACKGROUND_IMAGE
2314 	PVTS(r, page)->pixmap = None;
2315 	PVTS(r, page)->bg.pixmap = None;
2316 	PVTS(r, page)->bg.x = PVTS(r, page)->bg.y = 50;
2317 #endif
2318 	PVTS(r, page)->cmd_pid = -1;
2319 	PVTS(r, page)->cmd_fd = PVTS(r, page)->tty_fd = -1;
2320 #ifdef UTMP_SUPPORT
2321 	PVTS(r, page)->next_utmp_action = SAVE;
2322 #endif
2323 #ifndef NO_SETOWNER_TTYDEV
2324 	PVTS(r, page)->next_tty_action = SAVE;
2325 #endif
2326 
2327 	PVTS(r, page)->hold = 0;		/* clear hold flag */
2328 	PVTS(r, page)->dead = 0;		/* clear dead flag */
2329 	PVTS(r, page)->highlight = 0;	/* clear highlight flag */
2330 
2331 	/* Get term_env type */
2332 	PVTS(r, page)->termenv = rxvt_get_termenv (
2333 		r->h->rs[Rs_term_name] ? r->h->rs[Rs_term_name] : TERMENV);
2334 
2335 	/* get command argv from resources */
2336 	PVTS(r, page)->command_argv = rxvt_string_to_argv (
2337 				(char*) r->h->rs[Rs_command+i],
2338 				&(PVTS(r, page)->command_argc));
2339 
2340 	/* Initialize PrivateModes and SavedModes */
2341 	PVTS(r, page)->PrivateModes = PVTS(r, page)->SavedModes =
2342 		PrivMode_Default;
2343 	if (r->Options & Opt_scrollTtyOutputInhibit)
2344 		PVTS(r, page)->PrivateModes |= PrivMode_TtyOutputInh;
2345 	if (r->Options & Opt_scrollTtyKeypress)
2346 		PVTS(r, page)->PrivateModes |= PrivMode_Keypress;
2347 	if (!(r->Options & Opt_jumpScroll))
2348 		PVTS(r, page)->PrivateModes |= PrivMode_smoothScroll;
2349 #ifndef NO_BACKSPACE_KEY
2350 	if (STRCMP(r->h->key_backspace, "DEC") == 0)
2351 		PVTS(r, page)->PrivateModes |= PrivMode_HaveBackSpace;
2352 #endif
2353 #ifdef HAVE_SCROLLBARS
2354 	if (rxvt_scrollbar_visible(r)) {
2355 		PVTS(r, page)->PrivateModes |= PrivMode_scrollBar;
2356 		PVTS(r, page)->SavedModes |= PrivMode_scrollBar;
2357 	}
2358 #endif
2359 #ifdef HAVE_MENUBAR
2360 	if (rxvt_menubar_visible(r)) {
2361 		PVTS(r, page)->PrivateModes |= PrivMode_menuBar;
2362 		PVTS(r, page)->SavedModes |= PrivMode_menuBar;
2363 	}
2364 #endif
2365 
2366 	/* Now set VT fg/bg color */
2367 	PVTS(r, page)->p_fg = ISSET_VTFG(r, page) ?
2368 			&(VTFG(r, page)) : &(r->h->global_fg);
2369 	PVTS(r, page)->p_bg = ISSET_VTBG(r, page) ?
2370 			&(VTBG(r, page)) : &(r->h->global_bg);
2371 #ifdef XFT_SUPPORT
2372 	PVTS(r, page)->p_xftfg = ISSET_VTFG(r, page) ?
2373 			&(VTXFTFG(r, page)) : &(r->h->global_xftfg);
2374 	PVTS(r, page)->p_xftbg = ISSET_VTBG(r, page) ?
2375 			&(VTXFTBG(r, page)) : &(r->h->global_xftbg);
2376 #endif
2377 
2378 	/* Initialize input buffer */
2379 	PVTS(r, page)->cmdbuf_ptr =
2380 		PVTS(r, page)->cmdbuf_endp =
2381 		PVTS(r, page)->cmdbuf_base;
2382 
2383 	/* Initialize write out buffer */
2384 	PVTS(r, page)->v_buffer =
2385 		PVTS(r, page)->v_bufstr =
2386 		PVTS(r, page)->v_bufptr =
2387 		PVTS(r, page)->v_bufend = NULL;
2388 
2389 	/* Initialize checksum */
2390 	PVTS(r, page)->checksum = times (&tp);
2391 
2392 	/* Set screen structure initialization flag */
2393 	PVTS(r, page)->init_screen = 0;
2394 }
2395 
2396 
2397 /*----------------------------------------------------------------------*/
2398 /* rxvt_destroy_termwin() - destroy a terminal window */
2399 /* EXTPROTO */
2400 void
rxvt_destroy_termwin(rxvt_t * r,int page)2401 rxvt_destroy_termwin(rxvt_t* r, int page)
2402 {
2403 	assert (page < MAX_PAGES);
2404 
2405 	/* free command argv */
2406 	if (PVTS(r, page)->command_argv && PVTS(r, page)->command_argc)	{
2407 		register int	i;
2408 		for (i = 0; i < PVTS(r, page)->command_argc; i ++)
2409 			free (PVTS(r, page)->command_argv[i]);
2410 		free (PVTS(r, page)->command_argv);
2411 		PVTS(r, page)->command_argv = NULL;
2412 		PVTS(r, page)->command_argc = 0;
2413 	}
2414 
2415 	assert (PVTS(r, page)->tab_title);
2416 	free (PVTS(r, page)->tab_title);
2417 	PVTS(r, page)->tab_title = NULL;
2418 
2419 #ifdef XFT_SUPPORT
2420 	if (r->Options & Opt_xft)	{
2421 		if (PVTS(r, page)->xftvt)
2422 			XftDrawDestroy (PVTS(r, page)->xftvt);
2423 		PVTS(r, page)->xftvt = NULL;
2424 	}
2425 #endif
2426 	assert (None != PVTS(r, page)->vt);
2427 	XDestroyWindow (r->Xdisplay, PVTS(r, page)->vt);
2428 	PVTS(r, page)->vt = None;
2429 
2430 #ifdef BACKGROUND_IMAGE
2431 	if (None != PVTS(r, page)->pixmap)	{
2432 		XFreePixmap (r->Xdisplay, PVTS(r, page)->pixmap);
2433 		PVTS(r, page)->pixmap = None;
2434 	}
2435 	if (None != PVTS(r, page)->bg.pixmap)	{
2436 		XFreePixmap (r->Xdisplay, PVTS(r, page)->bg.pixmap);
2437 		PVTS(r, page)->bg.pixmap = None;
2438 	}
2439 #endif
2440 
2441 	/* Set vterm index to -1, so that we know it's unused */
2442 	PVTS(r, page)->vts_idx = -1;
2443 }
2444 
2445 
2446 
2447 char*	g_default_tab_title = "Terminal";
2448 /* rxvt_create_termwin() - create a terminal window */
2449 /* EXTPROTO */
2450 void
rxvt_create_termwin(rxvt_t * r,int page,const char TAINTED * title)2451 rxvt_create_termwin(rxvt_t* r, int page, const char TAINTED * title)
2452 {
2453 #ifdef DEBUG_X
2454 	char			vt_name[32];
2455 #endif
2456 	long			vt_emask;
2457 	char TAINTED *	t;
2458 
2459 
2460 	assert (page < MAX_PAGES);
2461 
2462 	rxvt_init_vts (r, page);
2463 
2464 	/*
2465 	** How to get the tab title? Try the following steps in sequence:
2466 	** . runtime supplied tab title (e.g., escape sequence)
2467 	** . individual tab title in .Xdefaults or command line option
2468 	** . tab title for all tabs in .Xdefaults or command line option
2469 	** . default tab title
2470 	*/
2471 	t = (char TAINTED *) title;
2472 	if (NULL == t)
2473 		t = (char*) r->h->rs[Rs_tabtitle+page];
2474 	if (NULL == t)
2475 		t = (char*) r->h->rs[Rs_tabtitleAll];
2476 	if (NULL == t)
2477 		t = g_default_tab_title;
2478 	PVTS(r, page)->tab_title = (char UNTAINTED *) STRNDUP(t, MAX_TAB_TXT);
2479 #ifdef HAVE_PUTENV
2480 	/* Set environment variable of tab title */
2481 	sprintf (r->h->env_tabtitle, TABTITLEENV "%s", PVTS(r, page)->tab_title);
2482 	putenv (r->h->env_tabtitle);
2483 #endif
2484 
2485 	PVTS(r, page)->tab_width = rxvt_tab_width (r, PVTS(r, page)->tab_title);
2486 
2487 	/*
2488 	** Now switch fg/bg colors before creating VT because this
2489 	** will use the fg/bg colors
2490 	*/
2491 	rxvt_switch_fgbg_color (r, page);
2492 
2493 	/* create the terminal window */
2494 	DBG_MSG (1, (stderr, "Create VT %d (%dx%d+%dx%d)\n", page, r->h->window_vt_x, r->h->window_vt_y, VT_WIDTH(r), VT_HEIGHT(r)));
2495 	PVTS(r, page)->vt = XCreateSimpleWindow (r->Xdisplay,
2496 						r->TermWin.parent,
2497 						r->h->window_vt_x, r->h->window_vt_y,
2498 						VT_WIDTH(r), VT_HEIGHT(r),
2499 						0,
2500 						r->PixColors[Color_fg],
2501 						r->PixColors[Color_bg]);
2502 	assert (None != PVTS(r, page)->vt);
2503 #ifdef XFT_SUPPORT
2504 	if (r->Options & Opt_xft)	{
2505 		PVTS(r, page)->xftvt = XftDrawCreate (r->Xdisplay,
2506 			PVTS(r, page)->vt, XVISUAL, XCMAP);
2507 		assert (NULL != PVTS(r, page)->xftvt);
2508 	}
2509 #endif
2510 
2511 
2512 #ifdef DEBUG_X
2513 	sprintf (vt_name, "vt %d window", page);
2514 	rxvt_set_win_title (r, PVTS(r, page)->vt, vt_name);
2515 #endif
2516 
2517 
2518 	/* define cursor for the terminal window */
2519 	rxvt_pointer_unblank(r, page);
2520 
2521 	/* define event mask fo the terminal window */
2522 	vt_emask = (ExposureMask | ButtonPressMask | ButtonReleaseMask
2523 		| PropertyChangeMask);
2524 #ifdef POINTER_BLANK
2525 	if ((r->Options & Opt_pointerBlank))
2526 		vt_emask |= PointerMotionMask;
2527 	else
2528 #endif
2529 		vt_emask |= (Button1MotionMask | Button3MotionMask);
2530 	XSelectInput(r->Xdisplay, PVTS(r, page)->vt, vt_emask);
2531 
2532 #ifdef TRANSPARENT
2533 	/* Set transparent background */
2534 	if (r->Options & Opt_transparent)	{
2535 		XSetWindowBackgroundPixmap (r->Xdisplay, PVTS(r, page)->vt,
2536 			ParentRelative);
2537 	}
2538 #endif
2539 
2540 	/*
2541 	** Load the background image for terminal window when not
2542 	** transparent
2543 	*/
2544 #ifdef BACKGROUND_IMAGE
2545 # ifdef TRANSPARENT
2546 	if (!(r->Options & Opt_transparent))
2547 # endif
2548 	if (r->h->rs[Rs_backgroundPixmap+page] ||
2549 		r->h->rs[Rs_backgroundPixmapAll]) {
2550 		/* Load pixmap for each individual tab */
2551 		const char*	pf = r->h->rs[Rs_backgroundPixmap+page];
2552 		const char*	p;
2553 		/*
2554 		** If each individual pixmap is unset, load pixmap for all
2555 		** tabs
2556 		*/
2557 		if (NULL == pf)
2558 			pf = r->h->rs[Rs_backgroundPixmapAll];
2559 
2560 		p = pf;
2561 		if ((p = STRCHR(p, ';')) != NULL) {
2562 			p++;
2563 			rxvt_scale_pixmap(r, page, p);
2564 		}
2565 		rxvt_load_bg_pixmap(r, page, pf);
2566 		/* rxvt_scr_touch(r, page, True); */
2567 	}
2568 #endif
2569 
2570 	XMapWindow (r->Xdisplay, PVTS(r, page)->vt);
2571 }
2572 
2573 
2574 /* INTPROTO */
2575 void
rxvt_set_borderless(rxvt_t * r)2576 rxvt_set_borderless (rxvt_t* r)
2577 {
2578 	Atom		prop;
2579 	CARD32		hints;		/* KDE/GNOME hints */
2580 	MWMHints	mwmhints;	/* Motif hints */
2581 
2582 	hints = (CARD32) 0;
2583 	mwmhints.flags = MWM_HINTS_DECORATIONS;
2584 	mwmhints.decorations = MWM_DECOR_BORDER | MWM_DECOR_RESIZEH;
2585 
2586 	/* Motif compatible WM */
2587 	prop = XInternAtom (r->Xdisplay, "_MOTIF_WM_HINTS", True);
2588 	if (None != prop)
2589 		XChangeProperty (r->Xdisplay, r->TermWin.parent, prop, prop,
2590 			32, PropModeReplace, (unsigned char*) &mwmhints,
2591 			PROP_MWM_HINTS_ELEMENTS);
2592 
2593 	/* GNOME compatible WM */
2594 	prop = XInternAtom (r->Xdisplay, "_WIN_HINTS", True);
2595 	if (None != prop)
2596 		XChangeProperty (r->Xdisplay, r->TermWin.parent, prop, prop,
2597 			32, PropModeReplace, (unsigned char*) &hints, 1);
2598 
2599 	/* KDE compatible WM */
2600 	prop = XInternAtom (r->Xdisplay, "KWM_WIN_DECORATION", True);
2601 	if (None != prop)
2602 		XChangeProperty (r->Xdisplay, r->TermWin.parent, prop, prop,
2603 			32, PropModeReplace, (unsigned char*) &hints, 1);
2604 }
2605 
2606 
2607 /* INTPROTO */
2608 void
rxvt_set_desktop(rxvt_t * r,CARD32 desktop)2609 rxvt_set_desktop (rxvt_t* r, CARD32 desktop)
2610 {
2611 	/* GNOME compatible WM */
2612 	if (desktop >= 0 && desktop <= 64 &&
2613 		None != r->h->xa[XA_WIN_WORKSPACE])
2614 		XChangeProperty(r->Xdisplay, r->TermWin.parent,
2615 			r->h->xa[XA_WIN_WORKSPACE], XA_CARDINAL, 32,
2616 			PropModeReplace, (unsigned char*) &desktop, 1L);
2617 
2618 	/* WindowMaker/FreeDesktop.org compatible WM */
2619 	if (desktop >= 0 && desktop <= 64 &&
2620 		None != r->h->xa[XA_NET_WM_DESKTOP])
2621 		XChangeProperty(r->Xdisplay, r->TermWin.parent,
2622 			r->h->xa[XA_NET_WM_DESKTOP], XA_CARDINAL, 32,
2623 			PropModeReplace, (unsigned char*) &desktop, 1L);
2624 }
2625 
2626 
2627 /* EXTPROTO */
2628 CARD32
rxvt_get_desktop(rxvt_t * r)2629 rxvt_get_desktop (rxvt_t* r)
2630 {
2631 	int		result;
2632 	Atom	ret_type;
2633 	int		format;
2634 	unsigned long	nitems;
2635 	unsigned long	bytes_after;
2636 	long*	cardinals;
2637 	CARD32	desktop;
2638 
2639 	if (None == r->h->xa[XA_NET_WM_DESKTOP])
2640 		return 0;
2641 
2642 	result = XGetWindowProperty (r->Xdisplay, r->TermWin.parent,
2643 				r->h->xa[XA_NET_WM_DESKTOP], 0L, LONG_MAX, False,
2644 				XA_CARDINAL, &ret_type, &format, &nitems,
2645 				&bytes_after, (unsigned char**) &cardinals);
2646 	if (Success != result)
2647 		return 0;
2648 	if (XA_CARDINAL != ret_type || 0 == format)
2649 		return 0;
2650 
2651 	desktop = (CARD32) cardinals[0];
2652 	if (desktop < 0 || desktop > 64)
2653 		desktop = 0;
2654 
2655 	XFree (cardinals);
2656 	return desktop;
2657 }
2658 
2659 
2660 /*----------------------------------------------------------------------*/
2661 /* rxvt_create_show_windows() - Open and map the window */
2662 /* EXTPROTO */
2663 void
rxvt_create_show_windows(rxvt_t * r,int argc,const char * const * argv)2664 rxvt_create_show_windows(rxvt_t* r, int argc, const char *const *argv)
2665 {
2666 	XClassHint				class_hint;
2667 	XWMHints				wm_hint;
2668 	XTextProperty			win_prop;
2669 	XTextProperty			icon_prop;
2670 	XGCValues				gcvalue;
2671 	unsigned long			gcmask;
2672 #ifndef NO_FRILLS
2673 	CARD32					pid = (CARD32) getpid ();
2674 #endif
2675 #ifdef TRANSPARENT
2676 	register int			i;
2677 #endif
2678 #ifdef POINTER_BLANK
2679 	static const XColor		blackcolour = { 0, 0, 0, 0, 0, 0 };
2680 #endif
2681 
2682 #ifdef PREFER_24BIT
2683 	XSetWindowAttributes	attributes;
2684 	XWindowAttributes		gattr;
2685 
2686 
2687 	XCMAP = DefaultColormap(r->Xdisplay, XSCREEN);
2688 	XVISUAL = DefaultVisual(r->Xdisplay, XSCREEN);
2689 
2690 	if (r->Options & Opt_transparent) {
2691 		XGetWindowAttributes(r->Xdisplay,
2692 			RootWindow(r->Xdisplay, XSCREEN), &gattr);
2693 		XDEPTH = gattr.depth;
2694 	}
2695 	else {
2696 		XDEPTH = DefaultDepth(r->Xdisplay, XSCREEN);
2697 		/*
2698 		** If depth is not 24, look for a 24bit visual.
2699 		*/
2700 		if (XDEPTH != 24) {
2701 			XVisualInfo	 vinfo;
2702 
2703 			if (XMatchVisualInfo(r->Xdisplay, XSCREEN, 24, TrueColor,
2704 				&vinfo)) {
2705 				XDEPTH = 24;
2706 				XVISUAL = vinfo.visual;
2707 				XCMAP = XCreateColormap(r->Xdisplay,
2708 							RootWindow(r->Xdisplay, XSCREEN),
2709 							XVISUAL, AllocNone);
2710 			}
2711 		}
2712 	}
2713 #endif
2714 
2715 
2716 	/* grab colors before netscape does */
2717 	rxvt_init_colors (r);
2718 
2719 	/*
2720 	** Initialize fonts.
2721 	** . Always load X11 fonts since pointer_blank uses it
2722 	** . Load XFT font after X11 fonts. If succeeds, XFT font will
2723 	** update font width/height and be used by default
2724 	*/
2725 #ifdef XFT_SUPPORT
2726 	if (r->Options & Opt_xft)	{
2727 		if (!rxvt_init_font_xft (r))	{
2728 			DBG_MSG (1, (stderr, "Failed to load FreeType font, fallback to X11 font\n"));
2729 			/* disable xft */
2730 			r->Options &= ~Opt_xft;
2731 		}
2732 	}
2733 #endif
2734 	/* init fallback X11 font */
2735 	rxvt_init_font_x11 (r);
2736 
2737 
2738 	/*
2739 	** must initialize scrollbar before initialize window size and
2740 	** create windows.
2741 	*/
2742 #ifdef HAVE_SCROLLBARS
2743 	rxvt_scrollbar_init (r);
2744 #endif
2745 	rxvt_init_win_size (r);
2746 
2747 	/*
2748 	** parent window - reverse video so we can see placement errors
2749 	** sub-window placement & size in rxvt_resize_subwindows()
2750 	*/
2751 
2752 #ifdef PREFER_24BIT
2753 	attributes.background_pixel = r->PixColors[Color_bg];
2754 	attributes.border_pixel = r->PixColors[Color_border];
2755 	attributes.colormap = XCMAP;
2756 	r->TermWin.parent = XCreateWindow(r->Xdisplay, XROOT,
2757 					r->szHint.x, r->szHint.y,
2758 					r->szHint.width, r->szHint.height,
2759 					r->TermWin.ext_bwidth,
2760 					XDEPTH, InputOutput,
2761 					XVISUAL,
2762 					CWBackPixel | CWBorderPixel
2763 					| CWColormap, &attributes);
2764 #else
2765 	r->TermWin.parent = XCreateSimpleWindow(r->Xdisplay, XROOT,
2766 						r->szHint.x, r->szHint.y,
2767 						r->szHint.width,
2768 						r->szHint.height,
2769 						r->TermWin.ext_bwidth,
2770 						r->PixColors[Color_border],
2771 						r->PixColors[Color_bg]);
2772 #endif
2773 	assert (None != r->TermWin.parent);
2774 
2775 
2776 #ifdef XFT_SUPPORT
2777 	if (r->Options & Opt_xft)	{
2778 		/* create XFT draw, test only */
2779 		XftDraw*		xftdraw = XftDrawCreate (r->Xdisplay,
2780 			r->TermWin.parent, XVISUAL, XCMAP);
2781 		if (xftdraw)	{
2782 			XftDrawDestroy (xftdraw);
2783 			/* some cleanup work if successfully create xft window */
2784 # ifdef POINTER_BLANK
2785 			/* disable pointer blank */
2786 			r->Options &= ~Opt_pointerBlank;
2787 # endif
2788 		}
2789 	}
2790 #endif
2791 
2792 
2793 # ifdef HAVE_X11_SM_SMLIB_H
2794 	if (r->Options2 & Opt2_enableSessionMgt)
2795 		rxvt_session_init (r);
2796 # endif
2797 
2798 
2799 	/*
2800 	** Now set window properties, like title, icon name and hints
2801 	*/
2802 	/* window title name */
2803 	win_prop.value = (unsigned char*) r->h->rs[Rs_title];
2804 	win_prop.nitems = STRLEN (win_prop.value);
2805 	win_prop.encoding = XA_STRING;
2806 	win_prop.format = 8;
2807 	/* icon name */
2808 	icon_prop.value = (unsigned char*) r->h->rs[Rs_iconName];
2809 	icon_prop.nitems = STRLEN (icon_prop.value);
2810 	icon_prop.encoding = XA_STRING;
2811 	icon_prop.format = 8;
2812 	/* window manager hints */
2813 	wm_hint.flags = (InputHint | StateHint | WindowGroupHint);
2814 	wm_hint.input = True;
2815 	wm_hint.initial_state = (r->Options & Opt_iconic ? IconicState
2816 							: NormalState);
2817 	wm_hint.window_group = r->TermWin.parent;
2818 	/* class hints */
2819 	class_hint.res_name = (char*) r->h->rs[Rs_name];
2820 	class_hint.res_class = (char*) APL_CLASS;
2821 	XSetWMProperties (r->Xdisplay, r->TermWin.parent,
2822 		&win_prop, &icon_prop, (char**)argv, argc,
2823 		&r->szHint, &wm_hint, &class_hint);
2824 
2825 	/* set terminal title */
2826 	rxvt_set_term_title (r, win_prop.value);
2827 	/* set icon title */
2828 	rxvt_set_icon_name (r, icon_prop.value);
2829 	/* command line */
2830 	XSetCommand (r->Xdisplay, r->TermWin.parent, (char**) argv, argc);
2831 
2832 	/* override redirect */
2833 	if (r->Options2 & Opt2_overrideRedirect)	{
2834 		XSetWindowAttributes	attrib;
2835 		attrib.override_redirect = True;
2836 		XChangeWindowAttributes(r->Xdisplay, r->TermWin.parent,
2837 			CWOverrideRedirect, &attrib);
2838 	}
2839 
2840 #ifndef NO_FRILLS
2841 	XChangeProperty (r->Xdisplay, r->TermWin.parent,
2842 		r->h->xa[XA_NET_WM_PID], XA_CARDINAL, 32,
2843 		PropModeReplace, (unsigned char*) &pid, 1);
2844 #endif
2845 
2846 	if (r->Options2 & Opt2_borderLess)	{
2847 		rxvt_set_borderless (r);
2848 	}
2849 	if (r->h->rs[Rs_desktop])	{
2850 		CARD32	desktop = (CARD32) atoi (r->h->rs[Rs_desktop]);
2851 		rxvt_set_desktop (r, desktop);
2852 	}
2853 
2854 	/*
2855 	** set WM_CLIENT_LEADER property so that session management proxy
2856 	** can handle us even session management is not enabled.
2857 	*/
2858 	if (None != r->h->xa[XA_WM_CLIENT_LEADER])
2859 		XChangeProperty(r->Xdisplay, r->TermWin.parent,
2860 			r->h->xa[XA_WM_CLIENT_LEADER], XA_WINDOW, 32,
2861 			PropModeReplace, (unsigned char*) &(r->TermWin.parent), 1L);
2862 
2863 # ifdef HAVE_X11_SM_SMLIB_H
2864 	if (NULL != r->TermWin.sm_conn &&
2865 		NULL != r->TermWin.sm_client_id &&
2866 		STRCMP (r->TermWin.sm_client_id, ""))	{
2867 		if (None != r->h->xa[XA_SM_CLIENT_ID])
2868 			XChangeProperty(r->Xdisplay, r->TermWin.parent,
2869 				r->h->xa[XA_SM_CLIENT_ID], XA_STRING, 8,
2870 				PropModeReplace,
2871 				(unsigned char*) r->TermWin.sm_client_id,
2872 				STRLEN(r->TermWin.sm_client_id));
2873 	}
2874 # endif	/* HAVE_X11_SM_SMLIB_H */
2875 
2876 
2877 #ifdef TRANSPARENT
2878 	r->TermWin.pixmap = None;	/* Initialize it to None */
2879 	r->TermWin.parenttree[0] = r->TermWin.parent;
2880 	for (i = 1; i < PARENT_NUMBER; i ++)
2881 		r->TermWin.parenttree[i] = None;
2882 
2883 	if (r->Options & Opt_transparent)	{
2884 		XSetWindowBackgroundPixmap (r->Xdisplay, r->TermWin.parent,
2885 			ParentRelative);
2886 	}
2887 #endif	/* TRANSPARENT */
2888 
2889 
2890 	XSelectInput(r->Xdisplay, r->TermWin.parent,
2891 			(KeyPressMask
2892 #if defined(MOUSE_WHEEL) && defined(MOUSE_SLIP_WHEELING)
2893 			| KeyReleaseMask
2894 #endif
2895 			| FocusChangeMask
2896 #ifdef MONITOR_ENTER_LEAVE
2897 			| EnterWindowMask | LeaveWindowMask
2898 #endif
2899 			| VisibilityChangeMask
2900 			| StructureNotifyMask));
2901 
2902 
2903 	/*
2904 	** vt cursor: Black-on-White is standard, but this is more
2905 	** popular
2906 	*/
2907 	r->term_pointer = XCreateFontCursor(r->Xdisplay, XC_xterm);
2908 	/* scrollbar/menubar/tabbar window pointer */
2909 	r->h->bar_pointer = XCreateFontCursor(r->Xdisplay, XC_left_ptr);
2910 
2911 #ifdef POINTER_BLANK
2912 	if (!(r->Options & Opt_pointerBlank))
2913 		r->h->blank_pointer = None;
2914 	else
2915 		r->h->blank_pointer = XCreateGlyphCursor(r->Xdisplay,
2916 			r->TermWin.font->fid, r->TermWin.font->fid, ' ', ' ',
2917 			(XColor*) &blackcolour, (XColor*) &blackcolour);
2918 #endif
2919 
2920 
2921 	/* graphics context for the vt window */
2922 #ifdef XFT_SUPPORT
2923 	if (!(r->Options & Opt_xft))
2924 #endif
2925 	gcvalue.font = r->TermWin.font->fid;
2926 	gcvalue.foreground = r->PixColors[Color_fg];
2927 	gcvalue.background = r->PixColors[Color_bg];
2928 	gcvalue.graphics_exposures = 1;
2929 	gcmask = GCForeground | GCBackground | GCGraphicsExposures;
2930 #ifdef XFT_SUPPORT
2931 	if (!(r->Options & Opt_xft))
2932 #endif
2933 	gcmask |= GCFont;
2934 	r->TermWin.gc = XCreateGC(r->Xdisplay, r->TermWin.parent,
2935 					gcmask, &gcvalue);
2936 
2937 #ifdef HAVE_SCROLLBARS
2938 	rxvt_scrollbar_create (r);
2939 	if (r->Options & Opt_scrollBar)	{
2940 		rxvt_scrollbar_show (r);
2941 	}
2942 #endif
2943 #ifdef HAVE_MENUBAR
2944 	rxvt_menubar_create (r);
2945 # if (MENUBAR_MAX)
2946 	if (r->Options & Opt_showMenu)
2947 		rxvt_menubar_show (r);
2948 	if (r->h->rs[Rs_menu])	{
2949 		rxvt_menubar_load_file (r, r->h->rs[Rs_menu]);
2950 	}
2951 # endif
2952 #endif
2953 	rxvt_tabbar_create (r);
2954 	if (!(r->Options2 & Opt2_hideTabbar))
2955 		rxvt_tabbar_show (r);
2956 
2957 	XMapWindow (r->Xdisplay, r->TermWin.parent);
2958 }
2959 
2960 /*----------------------------------------------------------------------*/
2961 /*
2962  * Run the command in a subprocess and return a file descriptor for the
2963  * master end of the pseudo-teletype pair with the command talking to
2964  * the slave.
2965  */
2966 /* EXTPROTO */
2967 int
rxvt_run_command(rxvt_t * r,int page,const char ** argv)2968 rxvt_run_command(rxvt_t* r, int page, const char** argv)
2969 {
2970 	int			cfd, er;
2971 	int			i;
2972 
2973 	/* get master (pty) */
2974 	if ((cfd = rxvt_get_pty(&(PVTS(r, page)->tty_fd),
2975 		(char**) &(PVTS(r, page)->ttydev))) < 0) {
2976 		rxvt_print_error("can't open pseudo-tty");
2977 		return -1;
2978 	}
2979 #ifdef FD_SETSIZE
2980 	if (r->Xfd > FD_SETSIZE || cfd > FD_SETSIZE) {
2981 		rxvt_print_error("fd too high: %d max", FD_SETSIZE);
2982 		return -1;
2983 	}
2984 #endif
2985 	fcntl(cfd, F_SETFL, O_NDELAY);
2986 
2987 	/* get slave (tty) */
2988 	if (PVTS(r, page)->tty_fd < 0) {
2989 #if !defined(NO_SETOWNER_TTYDEV) && !defined(OS_CYGWIN)
2990 		rxvt_privileged_ttydev(r, page, SAVE);
2991 #endif
2992 		if ((PVTS(r, page)->tty_fd = rxvt_get_tty(PVTS(r, page)->ttydev)) < 0) {
2993 			close(cfd);
2994 			rxvt_print_error("can't open slave tty %s", PVTS(r, page)->ttydev);
2995 			return -1;
2996 		}
2997 	}
2998 
2999 	/* Get tty mode before fork */
3000 #ifndef NO_BACKSPACE_KEY
3001 	if (r->h->key_backspace[0] && !r->h->key_backspace[1])
3002 		er = r->h->key_backspace[0];
3003 	else if (STRCMP(r->h->key_backspace, "DEC") == 0)
3004 		er = '\177';	/* the initial state anyway */
3005 	else
3006 #endif
3007 		er = -1;
3008 	rxvt_get_ttymode(&(PVTS(r, page)->tio), er);
3009 
3010 
3011 	DBG_MSG(1,(stderr, "argv = 0x%x\n", (unsigned int) argv));
3012 #ifndef __QNX__
3013 /* spin off the command interpreter */
3014 	switch (PVTS(r, page)->cmd_pid = fork()) {
3015 	case -1:
3016 		rxvt_print_error("can't fork");
3017 		return -1;
3018 	case 0:
3019 		/*
3020 		** To debug the child, follow these steps:
3021 		** . enable sleep in the following
3022 		** . launch gdb, set breakpoint before fork
3023 		** . run the program, step over fork, then get child pid
3024 		** . launch another gdb, attach to child process via pid
3025 		** . in child's gdb, set breakpoint after sleep
3026 		** . run 'continue' in child's gdb, debug child process
3027 		*/
3028 		/* sleep(10);	*/
3029 		/*
3030 		** Close all file descriptors except PVTS(r, page)->tty_fd
3031 		** and STDERR
3032 		*/
3033 		for (i = STDERR_FILENO + 1; i < r->num_fds; i ++)
3034 			if (i != PVTS(r, page)->tty_fd)
3035 				close (i);
3036 
3037 		if (rxvt_control_tty(PVTS(r, page)->tty_fd, PVTS(r, page)->ttydev) < 0)
3038 			rxvt_print_error("could not obtain control of tty");
3039 		else {
3040 		/* Reopen stdin, stdout and stderr over the tty file descriptor */
3041 			dup2(PVTS(r, page)->tty_fd, STDIN_FILENO);
3042 			dup2(PVTS(r, page)->tty_fd, STDOUT_FILENO);
3043 			dup2(PVTS(r, page)->tty_fd, STDERR_FILENO);
3044 			if (PVTS(r, page)->tty_fd > 2)
3045 				close(PVTS(r, page)->tty_fd);
3046 			rxvt_run_child(r, page, argv);
3047 		}
3048 		return -1;
3049 		/* exit(EXIT_FAILURE); */
3050 		/* NOTREACHED */
3051 	default:
3052 		{
3053 #if defined(HAVE_STRUCT_UTMP) && defined(HAVE_TTYSLOT)
3054 			int			fdstdin;
3055 
3056 			fdstdin = dup(STDIN_FILENO);
3057 			dup2(PVTS(r, page)->tty_fd, STDIN_FILENO);
3058 #endif
3059 #ifdef UTMP_SUPPORT
3060 # ifdef UTEMPTER_SUPPORT
3061 			/* utempter hack, it needs cmd_fd */
3062 			PVTS(r, page)->cmd_fd = cfd;
3063 # endif
3064 			rxvt_privileged_utmp(r, page, SAVE);
3065 # ifdef UTEMPTER_SUPPORT
3066 			/* utempter hack, restore cmd_fd */
3067 			PVTS(r, page)->cmd_fd = -1;
3068 # endif
3069 #endif
3070 #if defined(HAVE_STRUCT_UTMP) && defined(HAVE_TTYSLOT)
3071 			dup2(fdstdin, STDIN_FILENO);
3072 			close(fdstdin);
3073 #endif
3074 		}
3075 		/* keep STDERR_FILENO, PVTS(r, page)->cmd_fd, r->Xfd open */
3076 		close(PVTS(r, page)->tty_fd);
3077 		PVTS(r, page)->tty_fd = -1;
3078 		break;
3079 	}
3080 #else				/* __QNX__ uses qnxspawn() */
3081 	fchmod(PVTS(r, page)->tty_fd, 0622);
3082 	fcntl(PVTS(r, page)->tty_fd, F_SETFD, FD_CLOEXEC);
3083 	fcntl(cfd, F_SETFD, FD_CLOEXEC);
3084 
3085 	if (rxvt_run_child(r, page, argv) == -1)
3086 		/*exit(EXIT_FAILURE);*/
3087 		return -1;
3088 #endif
3089 
3090 	return cfd;
3091 }
3092 
3093 /* ------------------------------------------------------------------------- *
3094  *							CHILD PROCESS OPERATIONS						*
3095  * ------------------------------------------------------------------------- */
3096 /*
3097  * The only open file descriptor is the slave tty - so no error messages.
3098  * returns are fatal
3099  */
3100 /* INTPROTO */
3101 int
rxvt_run_child(rxvt_t * r,int page,const char ** argv)3102 rxvt_run_child(rxvt_t* r, int page, const char **argv)
3103 {
3104 #ifdef SIGTSTP
3105 	struct sigaction	ignore;
3106 #endif
3107 	struct sigaction	deflt;
3108 	char*				login;
3109 
3110 
3111 	/* DBG_MSG(1,(stderr, "argv = %x\n", argv)); */
3112 
3113 	/* init terminal attributes */
3114 	SET_TTYMODE(STDIN_FILENO, &(PVTS(r, page)->tio));
3115 
3116 	if (r->Options & Opt_console) {	/* be virtual console, fail silently */
3117 #ifdef TIOCCONS
3118 		unsigned int	on = 1;
3119 		ioctl(STDIN_FILENO, TIOCCONS, &on);
3120 #elif defined (SRIOCSREDIR)
3121 		int			fd;
3122 		fd = open(CONSOLE, O_WRONLY, 0);
3123 		if (fd >= 0) {
3124 			if (ioctl(fd, SRIOCSREDIR, NULL) < 0)
3125 			close(fd);
3126 		}
3127 #endif	/* SRIOCSREDIR */
3128 	}
3129 
3130 	/* reset signals and spin off the command interpreter */
3131 	deflt.sa_handler = SIG_DFL;
3132 	deflt.sa_flags = 0;
3133 	sigemptyset (&deflt.sa_mask);
3134 	sigaction (SIGINT, &deflt, NULL);
3135 	sigaction (SIGQUIT, &deflt, NULL);
3136 	sigaction (SIGCHLD, &deflt, NULL);
3137 	/*
3138 	signal(SIGINT, SIG_DFL);
3139 	signal(SIGQUIT, SIG_DFL);
3140 	signal(SIGCHLD, SIG_DFL);
3141 	*/
3142 
3143 	/*
3144 	** mimick login's behavior by disabling the job control signals
3145 	** a shell that wants them can turn them back on
3146 	*/
3147 #ifdef SIGTSTP
3148 	ignore.sa_handler = SIG_IGN;
3149 	ignore.sa_flags = 0;
3150 	sigemptyset (&ignore.sa_mask);
3151 	sigaction (SIGTSTP, &ignore, NULL);
3152 	sigaction (SIGTTIN, &ignore, NULL);
3153 	sigaction (SIGTTOU, &ignore, NULL);
3154 	/*
3155 	signal(SIGTSTP, SIG_IGN);
3156 	signal(SIGTTIN, SIG_IGN);
3157 	signal(SIGTTOU, SIG_IGN);
3158 	*/
3159 #endif	/* SIGTSTP */
3160 
3161 	/* set window size */
3162 	rxvt_tt_winsize(STDIN_FILENO, r->TermWin.ncol, r->TermWin.nrow, 0);
3163 
3164 #ifndef __QNX__
3165 /* command interpreter path */
3166 	if (argv != NULL) {
3167 # ifdef DEBUG_VERBOSE
3168 		int			i;
3169 		for (i = 0; argv[i]; i++)
3170 			DBG_MSG(2,(stderr, "argv [%d] = \"%s\"\n", i, argv[i]));
3171 # endif
3172 		execvp(argv[0], (char *const *)argv);
3173 		/* no error message: STDERR is closed! */
3174 	}
3175 	else {
3176 		const char	 *argv0, *shell;
3177 
3178 		if (NULL == (shell = getenv("SHELL")) ||
3179 			((char) 0 == *shell))	{
3180 # ifdef HAVE_GETPWUID
3181 			struct passwd* pwent = getpwuid (getuid ());
3182 			if ((NULL == pwent) ||
3183 				(NULL == (shell = pwent->pw_shell)) ||
3184 				((char) 0 == *shell))
3185 # endif	/* HAVE_GETPWUID */
3186 			shell = "/bin/sh";
3187 		}
3188 
3189 		argv0 = (const char *)rxvt_r_basename(shell);
3190 		if (r->Options & Opt_loginShell) {
3191 			int		l = STRLEN(argv0) + 2;
3192 			if (l <= 0 || l > 4096)	/* possible integer overflow */
3193 				l = 4096;
3194 			login = rxvt_malloc(l * sizeof(char));
3195 
3196 			login[0] = '-';
3197 			STRNCPY(&login[1], argv0, l-2);
3198 			login[l-1] = (char) 0;
3199 			argv0 = login;
3200 		}
3201 		execlp(shell, argv0, NULL);
3202 		/* no error message: STDERR is closed! */
3203 	}
3204 #else				/* __QNX__ uses qnxspawn() */
3205 	{
3206 		char	iov_a[10] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
3207 		char*	command = NULL, fullcommand[_MAX_PATH];
3208 		char**	arg_v, *arg_a[2] = { NULL, NULL };
3209 
3210 		if (argv != NULL) {
3211 			if (access(argv[0], X_OK) == -1) {
3212 				if (STRCHR(argv[0], '/') == NULL) {
3213 					searchenv(argv[0], "PATH", fullcommand);
3214 					if (fullcommand[0] != '\0')
3215 						command = fullcommand;
3216 				}
3217 				if (access(command, X_OK) == -1)
3218 					return -1;
3219 			}
3220 			else
3221 				command = argv[0];
3222 			arg_v = argv;
3223 		}
3224 		else {
3225 			if ((command = getenv("SHELL")) == NULL || *command == '\0')
3226 				command = "/bin/sh";
3227 
3228 			arg_a[0] = my_basename(command);
3229 			if (r->Options & Opt_loginShell) {
3230 				int		l = STRLEN(arg_a[0]) + 2;
3231 				if (l <= 0 || l > 4096)	/* possible integer overflow */
3232 					l = 4096;
3233 				login = rxvt_malloc(l * sizeof(char));
3234 
3235 				login[0] = '-';
3236 				STRNCPY(&login[1], arg_a[0], l-2);
3237 				login[l-1] = (char) 0;
3238 				arg_a[0] = login;
3239 			}
3240 			arg_v = arg_a;
3241 		}
3242 		iov_a[0] = iov_a[1] = iov_a[2] = PVTS(r, page)->tty_fd;
3243 		PVTS(r, page)->cmd_pid = qnx_spawn(0, 0, 0, -1, -1,
3244 					_SPAWN_SETSID | _SPAWN_TCSETPGRP,
3245 					command, arg_v, environ, iov_a, 0);
3246 		if (login)
3247 			free(login);
3248 		close(PVTS(r, page)->tty_fd);
3249 		return PVTS(r, page)->cmd_fd;
3250 	}
3251 #endif
3252 	return -1;
3253 }
3254 
3255 /* ------------------------------------------------------------------------- *
3256  *							GET TTY CURRENT STATE							*
3257  * ------------------------------------------------------------------------- */
3258 /* rxvt_get_ttymode() */
3259 /* INTPROTO */
3260 void
rxvt_get_ttymode(ttymode_t * tio,int erase)3261 rxvt_get_ttymode(ttymode_t *tio, int erase)
3262 {
3263 #ifdef HAVE_TERMIOS_H
3264 /*
3265  * standard System V termios interface
3266  */
3267 	if (GET_TERMIOS(STDIN_FILENO, tio) < 0) {
3268 	/* return error - use system defaults */
3269 	tio->c_cc[VINTR] = CINTR;
3270 	tio->c_cc[VQUIT] = CQUIT;
3271 	tio->c_cc[VERASE] = CERASE;
3272 	tio->c_cc[VKILL] = CKILL;
3273 	tio->c_cc[VSTART] = CSTART;
3274 	tio->c_cc[VSTOP] = CSTOP;
3275 	tio->c_cc[VSUSP] = CSUSP;
3276 # ifdef VDSUSP
3277 	tio->c_cc[VDSUSP] = CDSUSP;
3278 # endif
3279 # ifdef VREPRINT
3280 	tio->c_cc[VREPRINT] = CRPRNT;
3281 # endif
3282 # ifdef VDISCRD
3283 	tio->c_cc[VDISCRD] = CFLUSH;
3284 # endif
3285 # ifdef VWERSE
3286 	tio->c_cc[VWERSE] = CWERASE;
3287 # endif
3288 # ifdef VLNEXT
3289 	tio->c_cc[VLNEXT] = CLNEXT;
3290 # endif
3291 	}
3292 	tio->c_cc[VEOF] = CEOF;
3293 	tio->c_cc[VEOL] = VDISABLE;
3294 # ifdef VEOL2
3295 	tio->c_cc[VEOL2] = VDISABLE;
3296 # endif
3297 # ifdef VSWTC
3298 	tio->c_cc[VSWTC] = VDISABLE;
3299 # endif
3300 # ifdef VSWTCH
3301 	tio->c_cc[VSWTCH] = VDISABLE;
3302 # endif
3303 # if VMIN != VEOF
3304 	tio->c_cc[VMIN] = 1;
3305 # endif
3306 # if VTIME != VEOL
3307 	tio->c_cc[VTIME] = 0;
3308 # endif
3309 	if (erase != -1)
3310 	tio->c_cc[VERASE] = (char)erase;
3311 
3312 /* input modes */
3313 	tio->c_iflag = (BRKINT | IGNPAR | ICRNL
3314 # ifdef IMAXBEL
3315 					| IMAXBEL
3316 # endif
3317 					| IXON);
3318 
3319 /* output modes */
3320 	tio->c_oflag = (OPOST | ONLCR);
3321 
3322 /* control modes */
3323 	tio->c_cflag = (CS8 | CREAD);
3324 
3325 /* line discipline modes */
3326 	tio->c_lflag = (ISIG | ICANON | IEXTEN | ECHO
3327 # if defined (ECHOCTL) && defined (ECHOKE)
3328 					| ECHOCTL | ECHOKE
3329 # endif
3330 					| ECHOE | ECHOK);
3331 # else				/* HAVE_TERMIOS_H */
3332 
3333 /*
3334  * sgtty interface
3335  */
3336 
3337 /* get parameters -- gtty */
3338 	if (ioctl(STDIN_FILENO, TIOCGETP, &(tio->sg)) < 0) {
3339 		tio->sg.sg_erase = CERASE;	/* ^H */
3340 		tio->sg.sg_kill = CKILL;	/* ^U */
3341 	}
3342 	if (erase != -1)
3343 		tio->sg.sg_erase = (char)erase;
3344 
3345 	tio->sg.sg_flags = (CRMOD | ECHO | EVENP | ODDP);
3346 
3347 /* get special characters */
3348 	if (ioctl(STDIN_FILENO, TIOCGETC, &(tio->tc)) < 0) {
3349 		tio->tc.t_intrc = CINTR;	/* ^C */
3350 		tio->tc.t_quitc = CQUIT;	/* ^\ */
3351 		tio->tc.t_startc = CSTART;	/* ^Q */
3352 		tio->tc.t_stopc = CSTOP;	/* ^S */
3353 		tio->tc.t_eofc = CEOF;	/* ^D */
3354 		tio->tc.t_brkc = -1;
3355 	}
3356 /* get local special chars */
3357 	if (ioctl(STDIN_FILENO, TIOCGLTC, &(tio->lc)) < 0) {
3358 		tio->lc.t_suspc = CSUSP;	/* ^Z */
3359 		tio->lc.t_dsuspc = CDSUSP;	/* ^Y */
3360 		tio->lc.t_rprntc = CRPRNT;	/* ^R */
3361 		tio->lc.t_flushc = CFLUSH;	/* ^O */
3362 		tio->lc.t_werasc = CWERASE;	/* ^W */
3363 		tio->lc.t_lnextc = CLNEXT;	/* ^V */
3364 	}
3365 /* get line discipline */
3366 	ioctl(STDIN_FILENO, TIOCGETD, &(tio->line));
3367 # ifdef NTTYDISC
3368 	tio->line = NTTYDISC;
3369 # endif				/* NTTYDISC */
3370 	tio->local = (LCRTBS | LCRTERA | LCTLECH | LPASS8 | LCRTKIL);
3371 #endif				/* HAVE_TERMIOS_H */
3372 
3373 /*
3374  * Debugging
3375  */
3376 #ifdef DEBUG_TTYMODE
3377 #ifdef HAVE_TERMIOS_H
3378 /* c_iflag bits */
3379 	fprintf(stderr, "Input flags\n");
3380 
3381 /* cpp token stringize doesn't work on all machines <sigh> */
3382 # define FOO(flag,name)			\
3383 	if ((tio->c_iflag) & flag)		\
3384 	fprintf (stderr, "%s ", name)
3385 
3386 /* c_iflag bits */
3387 	FOO(IGNBRK, "IGNBRK");
3388 	FOO(BRKINT, "BRKINT");
3389 	FOO(IGNPAR, "IGNPAR");
3390 	FOO(PARMRK, "PARMRK");
3391 	FOO(INPCK, "INPCK");
3392 	FOO(ISTRIP, "ISTRIP");
3393 	FOO(INLCR, "INLCR");
3394 	FOO(IGNCR, "IGNCR");
3395 	FOO(ICRNL, "ICRNL");
3396 	FOO(IXON, "IXON");
3397 	FOO(IXOFF, "IXOFF");
3398 # ifdef IUCLC
3399 	FOO(IUCLC, "IUCLC");
3400 # endif
3401 # ifdef IXANY
3402 	FOO(IXANY, "IXANY");
3403 # endif
3404 # ifdef IMAXBEL
3405 	FOO(IMAXBEL, "IMAXBEL");
3406 # endif
3407 	fprintf(stderr, "\n");
3408 
3409 # undef FOO
3410 # define FOO(entry, name)					\
3411 	fprintf(stderr, "%-8s = %#04o\n", name, tio->c_cc [entry])
3412 
3413 	FOO(VINTR, "VINTR");
3414 	FOO(VQUIT, "VQUIT");
3415 	FOO(VERASE, "VERASE");
3416 	FOO(VKILL, "VKILL");
3417 	FOO(VEOF, "VEOF");
3418 	FOO(VEOL, "VEOL");
3419 # ifdef VEOL2
3420 	FOO(VEOL2, "VEOL2");
3421 # endif
3422 # ifdef VSWTC
3423 	FOO(VSWTC, "VSWTC");
3424 # endif
3425 # ifdef VSWTCH
3426 	FOO(VSWTCH, "VSWTCH");
3427 # endif
3428 	FOO(VSTART, "VSTART");
3429 	FOO(VSTOP, "VSTOP");
3430 	FOO(VSUSP, "VSUSP");
3431 # ifdef VDSUSP
3432 	FOO(VDSUSP, "VDSUSP");
3433 # endif
3434 # ifdef VREPRINT
3435 	FOO(VREPRINT, "VREPRINT");
3436 # endif
3437 # ifdef VDISCRD
3438 	FOO(VDISCRD, "VDISCRD");
3439 # endif
3440 # ifdef VWERSE
3441 	FOO(VWERSE, "VWERSE");
3442 # endif
3443 # ifdef VLNEXT
3444 	FOO(VLNEXT, "VLNEXT");
3445 # endif
3446 	fprintf(stderr, "\n");
3447 # undef FOO
3448 # endif				/* HAVE_TERMIOS_H */
3449 #endif				/* DEBUG_TTYMODE */
3450 }
3451 
3452 /*----------------------- end-of-file (C source) -----------------------*/
3453