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-2006  Jingmin Zhou <jimmyzhou@users.sourceforge.net>
14  * Copyright (c) 2005-2006  Gautam Iyer <gi1242@users.sourceforge.net>
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 #include "../config.h"
32 #include "rxvt.h"
33 
34 #ifdef XFT_SUPPORT
35 # include "xftacs.h"
36 #endif
37 
38 
39 /* #define XTERM_REVERSE_VIDEO 1 */
40 
41 
42 /*--------------------------------------------------------------------*
43  *         BEGIN `INTERNAL' ROUTINE PROTOTYPES                        *
44  *--------------------------------------------------------------------*/
45 #if defined(OS_SVR4) && !defined(_POSIX_VERSION)
46 int    rxvt_getdtablesize     ();
47 #endif
48 int    rxvt_xerror_handler    (const Display*, const XErrorEvent*);
49 void   rxvt_init_colors       (rxvt_t*);
50 void   rxvt_init_win_size     (rxvt_t*);
51 void   rxvt_color_aliases     (rxvt_t*, int);
52 void   rxvt_get_ourmods       (rxvt_t*);
53 int    rxvt_run_child         (rxvt_t*, int, const char**);
54 void   rxvt_get_ttymode       (ttymode_t*, int);
55 /*--------------------------------------------------------------------*
56  *         END   `INTERNAL' ROUTINE PROTOTYPES                        *
57  *--------------------------------------------------------------------*/
58 
59 
60 
61 const char *const def_colorName[] = {
62     COLOR_FOREGROUND,
63     COLOR_BACKGROUND,
64 /* low-intensity colors */
65     "black",		/* 0: black	    (#000000) */
66 #ifndef NO_BRIGHTCOLOR
67     "red3",	    /* 1: red		    (#CD0000) */
68     "green3",		/* 2: green	    (#00CD00) */
69     "yellow3",		/* 3: yellow		(#CDCD00) */
70     "blue3",		/* 4: blue		(#0000CD) */
71     "magenta3",		/* 5: magenta		(#CD00CD) */
72     "cyan3",		/* 6: cyan		(#00CDCD) */
73 # ifdef XTERM_COLORS
74     "grey90",		/* 7: white	    (#E5E5E5) */
75 # else
76     "antiquewhite",	/* 7: white	    (#FAEBD7) */
77 # endif
78 /* high-intensity colors */
79 # ifdef XTERM_COLORS
80     "grey30",		/* 8: bright black	(#4D4D4D) */
81 # else
82     "grey25",		/* 8: bright black	(#404040) */
83 # endif
84 #endif		    /* NO_BRIGHTCOLOR */
85     "red",	    /* 1/9: bright red	    (#FF0000) */
86     "green",		/* 2/10: bright green   (#00FF00) */
87     "yellow",		/* 3/11: bright yellow  (#FFFF00) */
88     "blue",	    /* 4/12: bright blue    (#0000FF) */
89     "magenta",		/* 5/13: bright magenta (#FF00FF) */
90     "cyan",	    /* 6/14: bright cyan    (#00FFFF) */
91     "white",		/* 7/15: bright white   (#FFFFFF) */
92 #ifdef TTY_256COLOR
93 # ifdef XTERM_COLORS
94     /* use the same color cube as xterm. 16-231 is a more or less uniform
95      * rgb ramp, and 231-255 is a greyscale ramp */
96     "rgb:00/00/00",	/* default 16-255 color table	    */
97     "rgb:00/00/5f",	/* consists of 6x6x6 colour cub	    */
98     "rgb:00/00/87",	/* and a 24 greyscale ramp w/o	    */
99     "rgb:00/00/af",	/* black or white		    */
100     "rgb:00/00/d7",
101     "rgb:00/00/ff",
102     "rgb:00/5f/00",
103     "rgb:00/5f/5f",
104     "rgb:00/5f/87",
105     "rgb:00/5f/af",
106     "rgb:00/5f/d7",
107     "rgb:00/5f/ff",
108     "rgb:00/87/00",
109     "rgb:00/87/5f",
110     "rgb:00/87/87",
111     "rgb:00/87/af",
112     "rgb:00/87/d7",
113     "rgb:00/87/ff",
114     "rgb:00/af/00",
115     "rgb:00/af/5f",
116     "rgb:00/af/87",
117     "rgb:00/af/af",
118     "rgb:00/af/d7",
119     "rgb:00/af/ff",
120     "rgb:00/d7/00",
121     "rgb:00/d7/5f",
122     "rgb:00/d7/87",
123     "rgb:00/d7/af",
124     "rgb:00/d7/d7",
125     "rgb:00/d7/ff",
126     "rgb:00/ff/00",
127     "rgb:00/ff/5f",
128     "rgb:00/ff/87",
129     "rgb:00/ff/af",
130     "rgb:00/ff/d7",
131     "rgb:00/ff/ff",
132     "rgb:5f/00/00",
133     "rgb:5f/00/5f",
134     "rgb:5f/00/87",
135     "rgb:5f/00/af",
136     "rgb:5f/00/d7",
137     "rgb:5f/00/ff",
138     "rgb:5f/5f/00",
139     "rgb:5f/5f/5f",
140     "rgb:5f/5f/87",
141     "rgb:5f/5f/af",
142     "rgb:5f/5f/d7",
143     "rgb:5f/5f/ff",
144     "rgb:5f/87/00",
145     "rgb:5f/87/5f",
146     "rgb:5f/87/87",
147     "rgb:5f/87/af",
148     "rgb:5f/87/d7",
149     "rgb:5f/87/ff",
150     "rgb:5f/af/00",
151     "rgb:5f/af/5f",
152     "rgb:5f/af/87",
153     "rgb:5f/af/af",
154     "rgb:5f/af/d7",
155     "rgb:5f/af/ff",
156     "rgb:5f/d7/00",
157     "rgb:5f/d7/5f",
158     "rgb:5f/d7/87",
159     "rgb:5f/d7/af",
160     "rgb:5f/d7/d7",
161     "rgb:5f/d7/ff",
162     "rgb:5f/ff/00",
163     "rgb:5f/ff/5f",
164     "rgb:5f/ff/87",
165     "rgb:5f/ff/af",
166     "rgb:5f/ff/d7",
167     "rgb:5f/ff/ff",
168     "rgb:87/00/00",
169     "rgb:87/00/5f",
170     "rgb:87/00/87",
171     "rgb:87/00/af",
172     "rgb:87/00/d7",
173     "rgb:87/00/ff",
174     "rgb:87/5f/00",
175     "rgb:87/5f/5f",
176     "rgb:87/5f/87",
177     "rgb:87/5f/af",
178     "rgb:87/5f/d7",
179     "rgb:87/5f/ff",
180     "rgb:87/87/00",
181     "rgb:87/87/5f",
182     "rgb:87/87/87",
183     "rgb:87/87/af",
184     "rgb:87/87/d7",
185     "rgb:87/87/ff",
186     "rgb:87/af/00",
187     "rgb:87/af/5f",
188     "rgb:87/af/87",
189     "rgb:87/af/af",
190     "rgb:87/af/d7",
191     "rgb:87/af/ff",
192     "rgb:87/d7/00",
193     "rgb:87/d7/5f",
194     "rgb:87/d7/87",
195     "rgb:87/d7/af",
196     "rgb:87/d7/d7",
197     "rgb:87/d7/ff",
198     "rgb:87/ff/00",
199     "rgb:87/ff/5f",
200     "rgb:87/ff/87",
201     "rgb:87/ff/af",
202     "rgb:87/ff/d7",
203     "rgb:87/ff/ff",
204     "rgb:af/00/00",
205     "rgb:af/00/5f",
206     "rgb:af/00/87",
207     "rgb:af/00/af",
208     "rgb:af/00/d7",
209     "rgb:af/00/ff",
210     "rgb:af/5f/00",
211     "rgb:af/5f/5f",
212     "rgb:af/5f/87",
213     "rgb:af/5f/af",
214     "rgb:af/5f/d7",
215     "rgb:af/5f/ff",
216     "rgb:af/87/00",
217     "rgb:af/87/5f",
218     "rgb:af/87/87",
219     "rgb:af/87/af",
220     "rgb:af/87/d7",
221     "rgb:af/87/ff",
222     "rgb:af/af/00",
223     "rgb:af/af/5f",
224     "rgb:af/af/87",
225     "rgb:af/af/af",
226     "rgb:af/af/d7",
227     "rgb:af/af/ff",
228     "rgb:af/d7/00",
229     "rgb:af/d7/5f",
230     "rgb:af/d7/87",
231     "rgb:af/d7/af",
232     "rgb:af/d7/d7",
233     "rgb:af/d7/ff",
234     "rgb:af/ff/00",
235     "rgb:af/ff/5f",
236     "rgb:af/ff/87",
237     "rgb:af/ff/af",
238     "rgb:af/ff/d7",
239     "rgb:af/ff/ff",
240     "rgb:d7/00/00",
241     "rgb:d7/00/5f",
242     "rgb:d7/00/87",
243     "rgb:d7/00/af",
244     "rgb:d7/00/d7",
245     "rgb:d7/00/ff",
246     "rgb:d7/5f/00",
247     "rgb:d7/5f/5f",
248     "rgb:d7/5f/87",
249     "rgb:d7/5f/af",
250     "rgb:d7/5f/d7",
251     "rgb:d7/5f/ff",
252     "rgb:d7/87/00",
253     "rgb:d7/87/5f",
254     "rgb:d7/87/87",
255     "rgb:d7/87/af",
256     "rgb:d7/87/d7",
257     "rgb:d7/87/ff",
258     "rgb:d7/af/00",
259     "rgb:d7/af/5f",
260     "rgb:d7/af/87",
261     "rgb:d7/af/af",
262     "rgb:d7/af/d7",
263     "rgb:d7/af/ff",
264     "rgb:d7/d7/00",
265     "rgb:d7/d7/5f",
266     "rgb:d7/d7/87",
267     "rgb:d7/d7/af",
268     "rgb:d7/d7/d7",
269     "rgb:d7/d7/ff",
270     "rgb:d7/ff/00",
271     "rgb:d7/ff/5f",
272     "rgb:d7/ff/87",
273     "rgb:d7/ff/af",
274     "rgb:d7/ff/d7",
275     "rgb:d7/ff/ff",
276     "rgb:ff/00/00",
277     "rgb:ff/00/5f",
278     "rgb:ff/00/87",
279     "rgb:ff/00/af",
280     "rgb:ff/00/d7",
281     "rgb:ff/00/ff",
282     "rgb:ff/5f/00",
283     "rgb:ff/5f/5f",
284     "rgb:ff/5f/87",
285     "rgb:ff/5f/af",
286     "rgb:ff/5f/d7",
287     "rgb:ff/5f/ff",
288     "rgb:ff/87/00",
289     "rgb:ff/87/5f",
290     "rgb:ff/87/87",
291     "rgb:ff/87/af",
292     "rgb:ff/87/d7",
293     "rgb:ff/87/ff",
294     "rgb:ff/af/00",
295     "rgb:ff/af/5f",
296     "rgb:ff/af/87",
297     "rgb:ff/af/af",
298     "rgb:ff/af/d7",
299     "rgb:ff/af/ff",
300     "rgb:ff/d7/00",
301     "rgb:ff/d7/5f",
302     "rgb:ff/d7/87",
303     "rgb:ff/d7/af",
304     "rgb:ff/d7/d7",
305     "rgb:ff/d7/ff",
306     "rgb:ff/ff/00",
307     "rgb:ff/ff/5f",
308     "rgb:ff/ff/87",
309     "rgb:ff/ff/af",
310     "rgb:ff/ff/d7",
311     "rgb:ff/ff/ff",
312 # else	/* !XTERM_COLORS */
313     "rgbi:0/0/0",	/* default 16-255 color table	    */
314     "rgbi:0/0/.2",	/* consists of 6x6x6 colour cubes   */
315     "rgbi:0/0/.4",	/* and a 24 greyscale ramp w/o	    */
316     "rgbi:0/0/.6",	/* black or white		    */
317     "rgbi:0/0/.8",
318     "rgbi:0/0/1",
319     "rgbi:0/.2/0",
320     "rgbi:0/.2/.2",
321     "rgbi:0/.2/.4",
322     "rgbi:0/.2/.6",
323     "rgbi:0/.2/.8",
324     "rgbi:0/.2/1",
325     "rgbi:0/.4/0",
326     "rgbi:0/.4/.2",
327     "rgbi:0/.4/.4",
328     "rgbi:0/.4/.6",
329     "rgbi:0/.4/.8",
330     "rgbi:0/.4/1",
331     "rgbi:0/.6/0",
332     "rgbi:0/.6/.2",
333     "rgbi:0/.6/.4",
334     "rgbi:0/.6/.6",
335     "rgbi:0/.6/.8",
336     "rgbi:0/.6/1",
337     "rgbi:0/.8/0",
338     "rgbi:0/.8/.2",
339     "rgbi:0/.8/.4",
340     "rgbi:0/.8/.6",
341     "rgbi:0/.8/.8",
342     "rgbi:0/.8/1",
343     "rgbi:0/1/0",
344     "rgbi:0/1/.2",
345     "rgbi:0/1/.4",
346     "rgbi:0/1/.6",
347     "rgbi:0/1/.8",
348     "rgbi:0/1/1",
349     "rgbi:.2/0/0",
350     "rgbi:.2/0/.2",
351     "rgbi:.2/0/.4",
352     "rgbi:.2/0/.6",
353     "rgbi:.2/0/.8",
354     "rgbi:.2/0/1",
355     "rgbi:.2/.2/0",
356     "rgbi:.2/.2/.2",
357     "rgbi:.2/.2/.4",
358     "rgbi:.2/.2/.6",
359     "rgbi:.2/.2/.8",
360     "rgbi:.2/.2/1",
361     "rgbi:.2/.4/0",
362     "rgbi:.2/.4/.2",
363     "rgbi:.2/.4/.4",
364     "rgbi:.2/.4/.6",
365     "rgbi:.2/.4/.8",
366     "rgbi:.2/.4/1",
367     "rgbi:.2/.6/0",
368     "rgbi:.2/.6/.2",
369     "rgbi:.2/.6/.4",
370     "rgbi:.2/.6/.6",
371     "rgbi:.2/.6/.8",
372     "rgbi:.2/.6/1",
373     "rgbi:.2/.8/0",
374     "rgbi:.2/.8/.2",
375     "rgbi:.2/.8/.4",
376     "rgbi:.2/.8/.6",
377     "rgbi:.2/.8/.8",
378     "rgbi:.2/.8/1",
379     "rgbi:.2/1/0",
380     "rgbi:.2/1/.2",
381     "rgbi:.2/1/.4",
382     "rgbi:.2/1/.6",
383     "rgbi:.2/1/.8",
384     "rgbi:.2/1/1",
385     "rgbi:.4/0/0",
386     "rgbi:.4/0/.2",
387     "rgbi:.4/0/.4",
388     "rgbi:.4/0/.6",
389     "rgbi:.4/0/.8",
390     "rgbi:.4/0/1",
391     "rgbi:.4/.2/0",
392     "rgbi:.4/.2/.2",
393     "rgbi:.4/.2/.4",
394     "rgbi:.4/.2/.6",
395     "rgbi:.4/.2/.8",
396     "rgbi:.4/.2/1",
397     "rgbi:.4/.4/0",
398     "rgbi:.4/.4/.2",
399     "rgbi:.4/.4/.4",
400     "rgbi:.4/.4/.6",
401     "rgbi:.4/.4/.8",
402     "rgbi:.4/.4/1",
403     "rgbi:.4/.6/0",
404     "rgbi:.4/.6/.2",
405     "rgbi:.4/.6/.4",
406     "rgbi:.4/.6/.6",
407     "rgbi:.4/.6/.8",
408     "rgbi:.4/.6/1",
409     "rgbi:.4/.8/0",
410     "rgbi:.4/.8/.2",
411     "rgbi:.4/.8/.4",
412     "rgbi:.4/.8/.6",
413     "rgbi:.4/.8/.8",
414     "rgbi:.4/.8/1",
415     "rgbi:.4/1/0",
416     "rgbi:.4/1/.2",
417     "rgbi:.4/1/.4",
418     "rgbi:.4/1/.6",
419     "rgbi:.4/1/.8",
420     "rgbi:.4/1/1",
421     "rgbi:.6/0/0",
422     "rgbi:.6/0/.2",
423     "rgbi:.6/0/.4",
424     "rgbi:.6/0/.6",
425     "rgbi:.6/0/.8",
426     "rgbi:.6/0/1",
427     "rgbi:.6/.2/0",
428     "rgbi:.6/.2/.2",
429     "rgbi:.6/.2/.4",
430     "rgbi:.6/.2/.6",
431     "rgbi:.6/.2/.8",
432     "rgbi:.6/.2/1",
433     "rgbi:.6/.4/0",
434     "rgbi:.6/.4/.2",
435     "rgbi:.6/.4/.4",
436     "rgbi:.6/.4/.6",
437     "rgbi:.6/.4/.8",
438     "rgbi:.6/.4/1",
439     "rgbi:.6/.6/0",
440     "rgbi:.6/.6/.2",
441     "rgbi:.6/.6/.4",
442     "rgbi:.6/.6/.6",
443     "rgbi:.6/.6/.8",
444     "rgbi:.6/.6/1",
445     "rgbi:.6/.8/0",
446     "rgbi:.6/.8/.2",
447     "rgbi:.6/.8/.4",
448     "rgbi:.6/.8/.6",
449     "rgbi:.6/.8/.8",
450     "rgbi:.6/.8/1",
451     "rgbi:.6/1/0",
452     "rgbi:.6/1/.2",
453     "rgbi:.6/1/.4",
454     "rgbi:.6/1/.6",
455     "rgbi:.6/1/.8",
456     "rgbi:.6/1/1",
457     "rgbi:.8/0/0",
458     "rgbi:.8/0/.2",
459     "rgbi:.8/0/.4",
460     "rgbi:.8/0/.6",
461     "rgbi:.8/0/.8",
462     "rgbi:.8/0/1",
463     "rgbi:.8/.2/0",
464     "rgbi:.8/.2/.2",
465     "rgbi:.8/.2/.4",
466     "rgbi:.8/.2/.6",
467     "rgbi:.8/.2/.8",
468     "rgbi:.8/.2/1",
469     "rgbi:.8/.4/0",
470     "rgbi:.8/.4/.2",
471     "rgbi:.8/.4/.4",
472     "rgbi:.8/.4/.6",
473     "rgbi:.8/.4/.8",
474     "rgbi:.8/.4/1",
475     "rgbi:.8/.6/0",
476     "rgbi:.8/.6/.2",
477     "rgbi:.8/.6/.4",
478     "rgbi:.8/.6/.6",
479     "rgbi:.8/.6/.8",
480     "rgbi:.8/.6/1",
481     "rgbi:.8/.8/0",
482     "rgbi:.8/.8/.2",
483     "rgbi:.8/.8/.4",
484     "rgbi:.8/.8/.6",
485     "rgbi:.8/.8/.8",
486     "rgbi:.8/.8/1",
487     "rgbi:.8/1/0",
488     "rgbi:.8/1/.2",
489     "rgbi:.8/1/.4",
490     "rgbi:.8/1/.6",
491     "rgbi:.8/1/.8",
492     "rgbi:.8/1/1",
493     "rgbi:1/0/0",
494     "rgbi:1/0/.2",
495     "rgbi:1/0/.4",
496     "rgbi:1/0/.6",
497     "rgbi:1/0/.8",
498     "rgbi:1/0/1",
499     "rgbi:1/.2/0",
500     "rgbi:1/.2/.2",
501     "rgbi:1/.2/.4",
502     "rgbi:1/.2/.6",
503     "rgbi:1/.2/.8",
504     "rgbi:1/.2/1",
505     "rgbi:1/.4/0",
506     "rgbi:1/.4/.2",
507     "rgbi:1/.4/.4",
508     "rgbi:1/.4/.6",
509     "rgbi:1/.4/.8",
510     "rgbi:1/.4/1",
511     "rgbi:1/.6/0",
512     "rgbi:1/.6/.2",
513     "rgbi:1/.6/.4",
514     "rgbi:1/.6/.6",
515     "rgbi:1/.6/.8",
516     "rgbi:1/.6/1",
517     "rgbi:1/.8/0",
518     "rgbi:1/.8/.2",
519     "rgbi:1/.8/.4",
520     "rgbi:1/.8/.6",
521     "rgbi:1/.8/.8",
522     "rgbi:1/.8/1",
523     "rgbi:1/1/0",
524     "rgbi:1/1/.2",
525     "rgbi:1/1/.4",
526     "rgbi:1/1/.6",
527     "rgbi:1/1/.8",
528     "rgbi:1/1/1",
529 # endif	/* XTERM_COLORS */
530     "rgb:08/08/08", /* xterm, rxvt, mrxvt use the same greyscale ramp */
531     "rgb:12/12/12",
532     "rgb:1c/1c/1c",
533     "rgb:26/26/26",
534     "rgb:30/30/30",
535     "rgb:3a/3a/3a",
536     "rgb:44/44/44",
537     "rgb:4e/4e/4e",
538     "rgb:58/58/58",
539     "rgb:62/62/62",
540     "rgb:6c/6c/6c",
541     "rgb:76/76/76",
542     "rgb:80/80/80",
543     "rgb:8a/8a/8a",
544     "rgb:94/94/94",
545     "rgb:9e/9e/9e",
546     "rgb:a8/a8/a8",
547     "rgb:b2/b2/b2",
548     "rgb:bc/bc/bc",
549     "rgb:c6/c6/c6",
550     "rgb:d0/d0/d0",
551     "rgb:da/da/da",
552     "rgb:e4/e4/e4",
553     "rgb:ee/ee/ee",
554 #endif	/* TTY_256COLOR */
555 #ifndef NO_CURSORCOLOR
556     COLOR_CURSOR_BACKGROUND,
557     COLOR_CURSOR_FOREGROUND,
558 #endif		    /* ! NO_CURSORCOLOR */
559     NULL,	    /* Color_pointer		    */
560     NULL,	    /* Color_border		    */
561     NULL,	    /* Color_ufbg		    */
562 #ifndef NO_BOLD_UNDERLINE_REVERSE
563     NULL,	    /* Color_BD			    */
564     NULL,	    /* Color_UL			    */
565     NULL,	    /* Color_RV			    */
566 #endif		    /* ! NO_BOLD_UNDERLINE_REVERSE  */
567 #ifdef OPTION_HC
568     NULL,	    /* Color_HL			    */
569 #endif
570 #ifdef KEEP_SCROLLCOLOR
571     COLOR_SCROLLBAR,
572     COLOR_SCROLLTROUGH,
573 #endif		    /* KEEP_SCROLLCOLOR */
574 #ifdef TINTING_SUPPORT
575 # ifdef HAVE_LIBXRENDER
576     "rgb:00/00/00",
577 # else
578     "rgb:ff/ff/ff",
579 # endif
580 #endif
581 };
582 
583 
584 /*
585 ** MUST sync with rxvt.h:enum XA_XXXX
586 */
587 const char *const xa_names[NUM_XA] = {
588     "COMPOUND_TEXT",
589     "UTF8_STRING",
590     "TEXT",
591     "MULTIPLE",
592     "TARGETS",
593     "TIMESTAMP",
594     "VT_SELECTION",
595     "INCR",
596     "WM_DELETE_WINDOW",
597     "_NET_WM_DESKTOP",
598     "_WIN_WORKSPACE",
599     "_NET_WM_NAME",
600     "_NET_WM_ICON_NAME",
601     "WM_CLIENT_LEADER",
602     "_NET_WM_WINDOW_OPACITY",
603 #ifndef NO_FRILLS
604     "_NET_WM_PID",
605 #endif
606 #ifdef HAVE_X11_SM_SMLIB_H
607     "SM_CLIENT_ID",
608 #endif
609 #ifdef USE_XIM
610     "WM_LOCALE_NAME",
611 #endif
612 #ifdef TRANSPARENT
613     "_XROOTPMAP_ID",
614     "_XSETROOT_ID",
615 #endif
616 #ifdef OFFIX_DND
617     "DndProtocol",
618     "DndSelection",
619 #endif
620     "CLIPBOARD"
621 };
622 
623 /* substitute system functions */
624 #if defined(OS_SVR4) && ! defined(_POSIX_VERSION)
625 /* INTPROTO */
626 int
rxvt_getdtablesize(void)627 rxvt_getdtablesize(void)
628 {
629     struct rlimit   rlim;
630 
631     getrlimit(RLIMIT_NOFILE, &rlim);
632     return rlim.rlim_cur;
633 }
634 #endif
635 
636 
637 /* EXTPROTO */
638 int
rxvt_init_vars(rxvt_t * r)639 rxvt_init_vars(rxvt_t *r)
640 {
641     register int	i;
642     struct rxvt_hidden*	h;
643 
644 
645     MEMSET(r, 0, sizeof(rxvt_t));
646 
647     h = r->h = (struct rxvt_hidden *)rxvt_calloc(1, sizeof(struct rxvt_hidden));
648 
649     for (i = 0; i < MAX_PAGES; i ++)
650     {
651 	/* Initialize vts_idx for each term_t structure */
652 	r->vterm[i].vts_idx = -1;
653 	/* Initialize each vts pointer */
654 	SET_NULL(r->vts[i]);
655     }
656 
657     SET_NULL(r->Xdisplay);
658 #ifdef USE_XIM
659     SET_NULL(r->TermWin.fontset);
660 #endif
661     SET_NULL(r->TermWin.font);
662 #ifdef MULTICHAR_SET
663     SET_NULL(r->TermWin.mfont);
664 #endif
665 #ifndef NO_BOLDFONT
666     SET_NULL(r->TermWin.bfont);
667 #endif
668 
669 #ifdef XFT_SUPPORT
670     SET_NULL(r->TermWin.xftpattern);
671     SET_NULL(r->TermWin.xftfont);
672     SET_NULL(r->TermWin.xftpfont);
673     SET_NULL(r->TermWin.xftPfont);
674 # ifndef NO_BOLDFONT
675     SET_NULL(r->TermWin.xftbfont);
676 # endif	/* NO_BOLDFONT */
677 # ifdef MULTICHAR_SET
678 #  ifdef HAVE_ICONV_H
679     r->TermWin.xfticonv = (iconv_t) -1;
680 #  endif
681     SET_NULL(r->TermWin.xftmpattern);
682     SET_NULL(r->TermWin.xftmfont);
683 # endif	/* MULTICHAR_SET */
684 #endif	/* XFT_SUPPORT */
685 
686     UNSET_ATOM(h->xa[XA_COMPOUND_TEXT]);
687     UNSET_ATOM(h->xa[XA_MULTIPLE]);
688     UNSET_ATOM(h->xa[XA_TARGETS]);
689     UNSET_ATOM(h->xa[XA_TEXT]);
690     UNSET_ATOM(h->xa[XA_TIMESTAMP]);
691     UNSET_ATOM(h->xa[XA_VT_SELECTION]);
692     UNSET_ATOM(h->xa[XA_INCR]);
693     h->locale = NULL;
694 
695 # ifdef HAVE_MENUBAR
696     SET_NULL(h->BuildMenu);
697     SET_NULL(h->ActiveMenu);
698     SET_NULL(h->popupMenu[0]);
699     SET_NULL(h->popupMenu[1]);
700     SET_NULL(h->popupMenu[2]);
701     h->showingMenu = 0;
702 
703     /* Set the current menubar to empty defaults */
704     SET_NULL(h->MenuBar.head);
705     SET_NULL(h->MenuBar.tail);
706     SET_NULL(h->MenuBar.title);
707 # endif
708 
709 # ifdef USE_XIM
710     SET_NULL(h->Input_Context);
711 # endif
712     /* SET_NULL(h->v_bufstr); */
713     SET_NULL(h->buffer);
714 
715 # ifdef TRANSPARENT
716     h->am_pixmap_trans = 0;
717     h->am_transparent  = 0;
718     UNSET_PIXMAP(h->rootPixmap);
719     h->bgRefreshInterval = DEFAULT_BG_REFRESH_INTERVAL;
720     h->lastCNotify.tv_sec = 0;	    /* No BG update pending */
721 # endif
722 
723     /* Initialize timeouts to 0 */
724     for( i=NUM_TIMEOUTS; i--;)
725         h->timeout[i].tv_sec = 0;
726 
727 
728     /* Back to undocumented code :) */
729     h->MEvent.time = CurrentTime;
730     h->MEvent.button = AnyButton;
731     r->Options[0] = DEFAULT_OPTIONS;
732     r->Options[1] = DEFAULT_OPTIONS2;
733     r->Options[2] = DEFAULT_OPTIONS3;
734     r->Options[3] = DEFAULT_OPTIONS4;
735     h->want_clip_refresh = 0;
736     /*
737      * We only want to set want_resize when we call XResizeWindow. In that
738      * case if XResizeWindow fails, we know that we called it, and can run
739      * our internal resize routines anyway (e.g. put the tabbar in place)
740      */
741     h->want_resize = 0;
742     h->ttygid = -1;
743     r->Xfd = -1;
744 #ifdef USE_FIFO
745     r->fifo_fd = -1;
746 #endif
747     r->ndead_childs = 0;
748 
749     r->nAsyncChilds = 0;
750 
751     /* default values */
752 #ifdef NO_FRILLS
753     r->TermWin.int_bwidth = DEFAULT_INTERNALBORDERWIDTH;
754     r->TermWin.ext_bwidth = DEFAULT_EXTERNALBORDERWIDTH;
755 #else
756     r->TermWin.int_bwidth = (INTERNALBORDERWIDTH >= 0 && INTERNALBORDERWIDTH <= MAX_INTERNALBORDERWIDTH) ? INTERNALBORDERWIDTH : DEFAULT_INTERNALBORDERWIDTH;
757     r->TermWin.ext_bwidth = (EXTERNALBORDERWIDTH >= 0 && EXTERNALBORDERWIDTH <= MAX_EXTERNALBORDERWIDTH) ? EXTERNALBORDERWIDTH : DEFAULT_EXTERNALBORDERWIDTH;
758 #endif
759 
760 #ifndef NO_LINESPACE
761     r->TermWin.lineSpace = (LINESPACE >= 0 && LINESPACE <= MAX_LINESPACE) ? LINESPACE : DEFAULT_LINESPACE;
762 #endif
763 
764 #ifdef CURSOR_BLINK
765     r->h->blinkInterval = DEFAULT_BLINK_TIME;
766 #endif
767 #ifdef POINTER_BLANK
768     r->h->pointerBlankDelay = DEFAULT_BLANKDELAY;
769 #endif
770 
771     /* Initialize selection data */
772 #ifndef NO_NEW_SELECTION
773     r->selection_style = NEW_SELECT;
774 #else
775     r->selection_style = OLD_SELECT;
776 #endif
777     r->selection.vt = -1;
778     r->selection.op = SELECTION_CLEAR;
779     r->selection.screen = PRIMARY;
780     r->selection.clicks = 0;
781     SET_NULL(r->selection.text);
782     r->selection.len = 0;
783     r->selection.beg.row = 0;
784     r->selection.beg.col = 0;
785     r->selection.end.row = 0;
786     r->selection.end.col = 0;
787 
788 #ifndef NO_BRIGHTCOLOR
789     h->colorfgbg = DEFAULT_RSTYLE;
790 #endif
791 #ifdef GREEK_SUPPORT
792     h->ks_greekmodeswith = GREEK_KEYBOARD_MODESWITCH;
793 #endif
794     h->refresh_type = SLOW_REFRESH;
795     UNSET_REGION(h->refreshRegion);	    /* Will be created when needed */
796     h->prev_nrow = h->prev_ncol = 0;
797 
798     r->encoding_method = ENC_NOENC;
799     h->multichar_decode = rxvt_decode_dummy;
800 
801     h->oldcursor.row = h->oldcursor.col = -1;
802     h->last_bot = h->last_state = -1;
803 
804 #ifdef HAVE_X11_SM_SMLIB_H
805     SET_NULL(r->TermWin.sm_conn);
806     SET_NULL(r->TermWin.ice_conn);
807     r->TermWin.ice_fd = -1;
808     SET_NULL(r->TermWin.sm_client_id);
809 #endif
810 
811 #ifdef USE_FIFO
812     {
813 	char fifo_name[FILENAME_MAX];
814 
815 	sprintf( fifo_name, "/tmp/.mrxvt-%d", getpid() );
816 	r->fbuf_ptr = r->fifo_buf;
817 	r->fifo_name = STRDUP( fifo_name );
818     }
819 #endif/*USE_FIFO*/
820 
821     r->tabClicked = -1; /* No tab has been clicked by user */
822 
823     h->allowedxerror = 0;
824     h->xerror_return = Success;
825     return 0;
826 }
827 
828 
829 /* EXTPROTO */
830 void
rxvt_init_secondary(rxvt_t * r)831 rxvt_init_secondary(rxvt_t *r)
832 {
833     int		i, num_fds;
834 #ifdef TTY_GID_SUPPORT
835     struct group   *gr = getgrnam("tty");
836 
837     if (gr)	    /* change group ownership of tty to "tty" */
838     {
839 	r->h->ttygid = gr->gr_gid;
840     }
841     else
842 #endif		    /* TTY_GID_SUPPORT */
843     {
844 	r->h->ttygid = getgid();
845     }
846 
847     rxvt_set_default_locale (r);
848 
849     /* get number of available file descriptors */
850 #if defined(_POSIX_VERSION) || ! defined(OS_SVR4)
851     num_fds = (int)sysconf(_SC_OPEN_MAX);
852 #else
853     num_fds = rxvt_getdtablesize();
854 #endif
855 
856     /*
857     ** Close all unused file descriptors
858     ** We don't want them, we don't need them.
859     */
860     if ((i = open("/dev/null", O_RDONLY)) < 0)
861     {
862 	/* TODO: BOO HISS */
863 	dup2(STDERR_FILENO, STDIN_FILENO);
864     }
865     else if (i > STDIN_FILENO)
866     {
867 	dup2(i, STDIN_FILENO);
868 	close(i);
869     }
870     dup2(STDERR_FILENO, STDOUT_FILENO);
871     for (i = STDERR_FILENO + 1; i < num_fds; i++)
872     {
873     /* #ifdef __sgi */
874 #ifdef OS_IRIX
875 	/* Alex Coventry says we need 4 & 7 too */
876 	if (i == 4 || i == 7)
877 	    continue;
878 #endif
879 	close(i);
880     }
881 
882     /* Now set the correct num_fds */
883     r->num_fds = STDERR_FILENO + 1;
884 #ifdef OS_IRIX
885     r->num_fds = 7 + 1;
886 #endif
887 }
888 
889 
890 /* INTPROTO */
891 int
rxvt_xerror_handler(const Display * display,const XErrorEvent * event)892 rxvt_xerror_handler(const Display *display __attribute__((unused)), const XErrorEvent *event)
893 {
894     rxvt_t*	r = rxvt_get_r();
895     char    error_msg[1024];
896 
897     XGetErrorText (r->Xdisplay, event->error_code, error_msg, 1023);
898     r->h->xerror_return = event->error_code;
899 
900     if( !r->h->allowedxerror )
901     {
902 	rxvt_msg (DBG_ERROR, DBG_INIT, "%s", error_msg);
903 
904 #ifdef DEBUG_X
905 	abort();
906 #endif
907     }
908 
909     return 0;	    /* ignored anyway */
910 }
911 
912 
913 #ifdef TEXT_SHADOW
914 /* INTPROTO */
915 void
rxvt_init_shadow_mode(rxvt_t * r,const char * shadow_mode)916 rxvt_init_shadow_mode (rxvt_t* r, const char* shadow_mode)
917 {
918     if (
919 	  !shadow_mode || !STRCASECMP ("botright", shadow_mode)
920 	  || !STRCASECMP ("default", shadow_mode))
921     {
922 	r->TermWin.shadow_mode = SHADOW_BOTRIGHT;
923     }
924     else if (!STRCASECMP ("botleft", shadow_mode))
925     {
926 	r->TermWin.shadow_mode = SHADOW_BOTLEFT;
927     }
928     else if (!STRCASECMP ("topright", shadow_mode))
929     {
930 	r->TermWin.shadow_mode = SHADOW_TOPRIGHT;
931     }
932     else if (!STRCASECMP ("topleft", shadow_mode))
933     {
934 	r->TermWin.shadow_mode = SHADOW_TOPLEFT;
935     }
936     else if (!STRCASECMP ("top", shadow_mode))
937     {
938 	r->TermWin.shadow_mode = SHADOW_TOP;
939     }
940     else if (!STRCASECMP ("bottom", shadow_mode))
941     {
942 	r->TermWin.shadow_mode = SHADOW_BOTTOM;
943     }
944     else if (!STRCASECMP ("left", shadow_mode))
945     {
946 	r->TermWin.shadow_mode = SHADOW_LEFT;
947     }
948     else if (!STRCASECMP ("right", shadow_mode))
949     {
950 	r->TermWin.shadow_mode = SHADOW_RIGHT;
951     }
952     else if (!STRCASECMP ("none", shadow_mode))
953     {
954 	r->TermWin.shadow_mode = SHADOW_NONE;
955     }
956     else	/* no match == default */
957     {
958 	r->TermWin.shadow_mode = SHADOW_NONE;
959     }
960 }
961 #endif
962 
963 
964 /*----------------------------------------------------------------------*/
965 /* EXTPROTO */
966 void
rxvt_set_jumpscroll(rxvt_t * r)967 rxvt_set_jumpscroll( rxvt_t *r )
968 {
969     if( r->h->rs[Rs_refreshLimit] )
970     {
971 	r->h->refresh_limit = atol( r->h->rs[Rs_refreshLimit] );
972 	if( r->h->refresh_limit < 0 )
973 	    r->h->refresh_limit = 0;
974     }
975     else
976 	r->h->refresh_limit = DEFAULT_REFRESH_LIMIT;
977 
978     if( r->h->rs[Rs_skipPages] )
979     {
980 	r->h->skip_pages = atol( r->h->rs[Rs_skipPages] );
981 	if( r->h->skip_pages <= 0 )
982 	    r->h->skip_pages = 1;
983     }
984     else
985 	r->h->skip_pages = DEFAULT_SKIP_PAGES;
986 }
987 
988 
989 /* EXTPROTO */
990 const char**
rxvt_init_resources(rxvt_t * r,int argc,const char * const * argv)991 rxvt_init_resources(rxvt_t* r, int argc, const char *const *argv)
992 {
993     register int    i, r_argc;
994     const char**    cmd_argv;
995     const char**    r_argv;
996     const char**    rs;
997 
998 
999     /*
1000      * Look for -exec option.  Find => split and make cmd_argv[] of command args
1001      */
1002     for( r_argc = 0; r_argc < argc; r_argc++ )
1003 	if( !STRCMP(argv[r_argc], "-e") || !STRCMP(argv[r_argc], "-exec") )
1004 	    break;
1005 
1006     r_argv = (const char**) rxvt_malloc( sizeof(char*) * (r_argc + 1) );
1007 
1008     for( i = 0; i < r_argc; i++ )
1009 	r_argv[i] = (const char*) argv[i];
1010     SET_NULL(r_argv[i]);
1011 
1012     if (r_argc == argc)
1013 	SET_NULL(cmd_argv);
1014     else
1015     {
1016 	cmd_argv = (const char **)rxvt_malloc(sizeof(char*) * (argc - r_argc));
1017 
1018 	for (i = 0; i < argc - r_argc - 1; i++)
1019 	    cmd_argv[i] = (const char *)argv[i + r_argc + 1];
1020 	SET_NULL(cmd_argv[i]);
1021     }
1022 
1023     /* clear all resources */
1024     rs = r->h->rs;
1025     for (i = 0; i < NUM_RESOURCES;)
1026 	SET_NULL(rs[i++]);
1027 
1028     rs[Rs_name] = rxvt_r_basename( argv[0] );
1029 
1030     /*
1031      * Open display, get options/resources and create the window
1032      */
1033     rxvt_get_options( r, r_argc, r_argv );
1034     rxvt_free( r_argv ); /* XXX memory leak? */
1035 
1036 #ifdef LOCAL_X_IS_UNIX
1037     /*
1038      * 2008-04-29 gi1242: Force UNIX sockets for security (Gentoo Bug #219750)
1039      */
1040     if( IS_NULL( rs[Rs_display_name] ) )
1041 	rs[Rs_display_name] = getenv( "DISPLAY" );
1042 
1043     if( rs[Rs_display_name] && rs[Rs_display_name][0] == ':' )
1044     {
1045 	char *val;
1046 	int l = 5 + STRLEN(rs[Rs_display_name]);
1047 	if (l <= 0 || l > 1024) /* possible integer overflow */
1048 	    l = 1024;
1049 
1050 	val = rxvt_malloc(l);
1051 	STRCPY( val, "unix");
1052 	STRNCAT( val, rs[Rs_display_name], l-5);
1053 
1054 	rs[Rs_display_name] = val;
1055     }
1056 #endif /* LOCAL_X_IS_UNIX */
1057 
1058     rxvt_msg( DBG_INFO, DBG_INIT, "Open X display %s\n", rs[Rs_display_name] );
1059     r->Xdisplay = XOpenDisplay( rs[Rs_display_name] );
1060     if( IS_NULL(r->Xdisplay) )
1061     {
1062 	rxvt_msg( DBG_ERROR, DBG_INIT, "Error opening display %s\n",
1063 		rs[Rs_display_name] );
1064 	exit( EXIT_FAILURE );
1065     }
1066 
1067 
1068 #ifdef DEBUG_X
1069     /*
1070      * Makes life a lot simpler when handling X events, as they are not cached,
1071      * but processed immediately.
1072      */
1073     XSynchronize( r->Xdisplay, True );
1074 #endif
1075 
1076     /*
1077      * Always set XErrorHandler to our own error handler because sometimes
1078      * errors are legal! Our error handler will abort when errors are not
1079      * allowed.
1080      */
1081     XSetErrorHandler( (XErrorHandler) rxvt_xerror_handler );
1082 
1083     /* Initialize all atoms after establishing connection to X */
1084     for (i = 0; i < NUM_XA; i++)
1085 	r->h->xa[i] = XInternAtom( r->Xdisplay, xa_names[i], False );
1086 
1087     rxvt_extract_resources( r, r->Xdisplay, rs[Rs_name] );
1088 
1089     /*
1090      * set any defaults not already set
1091      */
1092     if( cmd_argv && cmd_argv[0] )
1093     {
1094 	if( !rs[Rs_title] )
1095 	    rs[Rs_title] = rxvt_r_basename( cmd_argv[0] );
1096 	if( !rs[Rs_iconName] )
1097 	    rs[Rs_iconName] = rs[Rs_title];
1098     }
1099     else
1100     {
1101 	if( !rs[Rs_title] )
1102 	    rs[Rs_title] = rs[Rs_name];
1103 	if( !rs[Rs_iconName] )
1104 	    rs[Rs_iconName] = rs[Rs_name];
1105     }
1106 
1107     if( rs[Rs_maxTabWidth] )
1108     {
1109 	register int	tmp = atoi( rs[ Rs_maxTabWidth]);
1110 	r->TermWin.maxTabWidth = ( tmp >=1 && tmp <= MAX_DISPLAY_TAB_TXT ) ?
1111 					tmp : MAX_DISPLAY_TAB_TXT;
1112     }
1113     else
1114 	/*
1115 	 * If we're using Xft, then we will probably also use a PFont. So we
1116 	 * should set this to the maximum possible.
1117 	 */
1118 	r->TermWin.maxTabWidth =
1119 #ifdef XFT_SUPPORT
1120 	    ISSET_OPTION(r, Opt_xft) ? MAX_DISPLAY_TAB_TXT :
1121 #endif
1122 	    DEFAULT_DISPLAY_TAB_TXT;
1123 
1124 
1125     if( rs[Rs_minVisibleTabs] )
1126     {
1127 	register int	n = atoi( rs[Rs_minVisibleTabs] );
1128 	r->TermWin.minVisibleTabs = (n >= 2 && n <= MAX_PAGES) ?
1129 	    n : DEFAULT_MIN_VISIBLE_TABS;
1130     }
1131     else r->TermWin.minVisibleTabs = DEFAULT_MIN_VISIBLE_TABS;
1132 
1133 #ifndef NO_FRILLS
1134     if (rs[Rs_int_bwidth])
1135     {
1136 	register int	tmp = atoi( rs[Rs_int_bwidth] );
1137 	r->TermWin.int_bwidth =( tmp >= 0 && tmp <= MAX_INTERNALBORDERWIDTH ) ?
1138 					tmp : DEFAULT_INTERNALBORDERWIDTH;
1139     }
1140 
1141     if (rs[Rs_ext_bwidth])
1142     {
1143 	register int	tmp = atoi( rs[Rs_ext_bwidth] );
1144 	r->TermWin.ext_bwidth = (tmp >= 0 && tmp <= MAX_EXTERNALBORDERWIDTH) ?
1145 					tmp : DEFAULT_EXTERNALBORDERWIDTH;
1146     }
1147 #endif
1148 
1149 #ifndef NO_LINESPACE
1150     if (rs[Rs_lineSpace])
1151     {
1152 	register int	tmp = atoi( rs[Rs_lineSpace] );
1153 	r->TermWin.lineSpace = (tmp >= 0 && tmp <= MAX_LINESPACE) ?
1154 					tmp : DEFAULT_LINESPACE;
1155     }
1156 #endif
1157 
1158 #ifdef POINTER_BLANK
1159     if (rs[Rs_pointerBlankDelay])
1160     {
1161 	register int	tmp = atoi( rs[Rs_pointerBlankDelay] );
1162 	r->h->pointerBlankDelay = (tmp >= 0 && tmp <= MAX_BLANKDELAY) ?
1163 					tmp : DEFAULT_BLANKDELAY;
1164     }
1165 #endif
1166 
1167     /* Handle opacity of translucent window */
1168     if (rs[Rs_opacity])
1169     {
1170 	register int	tmp = atoi( rs[Rs_opacity] );
1171 	r->TermWin.opacity = (tmp >= 0 && tmp <= 100) ? 100 - tmp : 0;
1172 
1173 #ifdef TRANSPARENT
1174 	if (
1175 	      IS_ATOM(r->h->xa[XA_NET_WM_WINDOW_OPACITY]) &&
1176 	      ISSET_OPTION(r, Opt_transparent)
1177 	   )
1178 	{
1179 	    /* Override pseudo-transparent */
1180 	    UNSET_OPTION(r, Opt_transparent);
1181 	}
1182 #endif
1183     }
1184     if (rs[Rs_opacityDegree])
1185     {
1186 	register int	tmp = atoi (rs[Rs_opacityDegree]);
1187 	r->TermWin.opacity_degree = (tmp > 0 && tmp <= 100) ? tmp : 1;
1188     }
1189 
1190 #ifdef TINTING_SUPPORT
1191     if (rs[Rs_shade])
1192     {
1193 	register int	shade;
1194 	shade = atoi( rs[Rs_shade] );
1195 	if (shade < 0 || shade > 100)
1196 	    shade = 100;
1197 	r->TermWin.shade = 100 - shade;
1198     }
1199 #endif
1200 
1201     rxvt_set_jumpscroll(r);
1202 
1203 #ifdef TRANSPARENT
1204     if (rs[Rs_bgRefreshInterval])
1205     {
1206 	register unsigned long interval = atol( rs[Rs_bgRefreshInterval] );
1207 
1208 	if( interval > 1000 ) interval = 1000;
1209 	r->h->bgRefreshInterval = interval * 1000L; /* convert to micro-sec */
1210     }
1211 #endif
1212 
1213     if (rs[Rs_fade])
1214     {
1215 	register int	fade;
1216 	fade = atoi( rs[Rs_fade] );
1217 
1218 	/*
1219 	 * Fade levels of 0 will make the text completely black, so let's ignore
1220 	 * it.
1221 	 */
1222 	if( fade <= 0 || fade > 100 )
1223 	    fade = 100;
1224 	r->TermWin.fade = 100 - fade;
1225     }
1226     /* else r->TermWin.fade is 0 */
1227 
1228 #ifdef CURSOR_BLINK
1229     if (rs[Rs_cursorBlinkInterval])
1230     {
1231 	register long	tmp = atol( rs[Rs_cursorBlinkInterval] );
1232 	r->h->blinkInterval = (tmp >= MIN_BLINK_TIME && tmp <= MAX_BLINK_TIME) ? tmp : DEFAULT_BLINK_TIME;
1233     }
1234     /* convert msec to usec */
1235     r->h->blinkInterval *= 1000;
1236 #endif
1237 
1238 #ifdef PRINTPIPE
1239     if (!rs[Rs_print_pipe])
1240 	rs[Rs_print_pipe] = PRINTPIPE;
1241 #endif
1242     if (!rs[Rs_cutchars])
1243 	rs[Rs_cutchars] = CUTCHARS;
1244 
1245 #ifdef ACS_ASCII
1246     if( !rs[Rs_acs_chars] )
1247 	rs[Rs_acs_chars] = ACS_CHARS;
1248     if( (i = STRLEN(rs[Rs_acs_chars])) < 0x20 )
1249     {
1250 	char *val = rxvt_realloc( (void*) rs[Rs_acs_chars], 0x20 );
1251 	for( ; i < 0x20; )
1252 	    val[i++] = ' ';
1253 	rs[Rs_acs_chars] = val;
1254     }
1255 #endif
1256 
1257 #ifndef NO_BACKSPACE_KEY
1258     if( !rs[Rs_backspace_key] )
1259 # ifdef DEFAULT_BACKSPACE
1260 	r->h->key_backspace = DEFAULT_BACKSPACE;
1261 # else
1262 	r->h->key_backspace = "DEC";	/* can toggle between \010 or \177 */
1263 # endif
1264     else
1265     {
1266 	char*	val = STRDUP(rs[Rs_backspace_key]);
1267 	rxvt_str_trim( val );
1268 	rxvt_str_escaped( val );
1269 	r->h->key_backspace = val;
1270     }
1271 #endif
1272 #ifndef NO_DELETE_KEY
1273     if( !rs[Rs_delete_key] )
1274 # ifdef DEFAULT_DELETE
1275 	r->h->key_delete = DEFAULT_DELETE;
1276 # else
1277 	r->h->key_delete = "\033[3~";
1278 # endif
1279     else
1280     {
1281 	char *val = STRDUP( rs[Rs_delete_key] );
1282 	rxvt_str_trim( val );
1283 	rxvt_str_escaped( val );
1284 	r->h->key_delete = val;
1285     }
1286 #endif
1287     if( rs[Rs_answerbackstring] )
1288     {
1289 	rxvt_str_trim( (char*) rs[Rs_answerbackstring] );
1290 	rxvt_str_escaped( (char*) rs[Rs_answerbackstring] );
1291     }
1292 
1293     if( rs[Rs_selectstyle] )
1294     {
1295 	if( STRNCASECMP( rs[Rs_selectstyle], "oldword", 7 ) == 0 )
1296 	    r->selection_style = OLD_WORD_SELECT;
1297 #ifndef NO_OLD_SELECTION
1298 	else if( STRNCASECMP( rs[Rs_selectstyle], "old", 3 ) == 0 )
1299 	    r->selection_style = OLD_SELECT;
1300 #endif
1301     }
1302 
1303 
1304     /* Set default X11 fonts */
1305     rxvt_set_default_font_x11( r );
1306 #ifdef XFT_SUPPORT
1307     if( rs[Rs_xftsz] )
1308     {
1309 	int	sz = atoi( rs[Rs_xftsz] );
1310 	r->TermWin.xftsize = (sz >= MIN_XFT_FONT_SIZE) ? sz : MIN_XFT_FONT_SIZE;
1311     }
1312     else /* default xft font size */
1313 	r->TermWin.xftsize = DEFAULT_XFT_FONT_SIZE;
1314 
1315     if (rs[Rs_xftpsz])
1316     {
1317 	int	sz = atoi (rs[Rs_xftpsz]);
1318 	r->TermWin.xftpsize  =  (sz >= MIN_XFT_FONT_SIZE) ?
1319 					sz : MIN_XFT_FONT_SIZE;
1320     }
1321     else /* default xft Pfont size */
1322 	r->TermWin.xftpsize = DEFAULT_XFT_PFONT_SIZE;
1323 
1324 # ifdef MULTICHAR_SET
1325     if (rs[Rs_xftmsz])
1326     {
1327 	int	sz = (int) atof (rs[Rs_xftmsz]);
1328 	r->TermWin.xftmsize = (sz >= MIN_XFT_FONT_SIZE) ?
1329 					sz : MIN_XFT_FONT_SIZE;
1330     }
1331     else /* default xft font size */
1332 	r->TermWin.xftmsize = DEFAULT_XFT_FONT_SIZE;
1333 # endif	/* MULTICHAR_SET */
1334 
1335     /* Set default Freetype fonts */
1336     rxvt_set_default_font_xft (r);
1337 #endif	/* XFT_SUPPORT */
1338 
1339 
1340 #ifdef TEXT_SHADOW
1341     rxvt_init_shadow_mode (r, rs[Rs_textShadowMode]);
1342 #endif
1343 
1344 #ifdef XTERM_REVERSE_VIDEO
1345     /* this is how xterm implements reverseVideo */
1346     if (ISSET_OPTION(r, Opt_reverseVideo))
1347     {
1348 	if (!rs[Rs_color + Color_fg])
1349 	    rs[Rs_color + Color_fg] = def_colorName[Color_bg];
1350 	if (!rs[Rs_color + Color_bg])
1351 	    rs[Rs_color + Color_bg] = def_colorName[Color_fg];
1352 
1353 	for (i = 0; i < MAX_PROFILES; i++)
1354 	{
1355 	    int	    vtfg = Rs_foreground + i;
1356 	    int	    vtbg = Rs_background + i;
1357 
1358 	    char*   fg = (char*) rs[vtfg];
1359 	    char*   bg = (char*) rs[vtbg];
1360 
1361 	    /* foreground color of i terminal */
1362 	    if (ISSET_VTFG(r, i))
1363 		rs[vtfg] = ISSET_VTBG(r, i) ? bg :
1364 				def_colorName[Color_bg];
1365 	    /* background color of i terminal */
1366 	    if (ISSET_VTBG(r, i))
1367 		rs[vtbg] = ISSET_VTFG(r, i) ? fg :
1368 			    def_colorName[Color_fg];
1369 	}
1370     }
1371 #endif
1372 
1373     for (i = 0; i < NRS_COLORS; i++)
1374 	if (!rs[Rs_color + i])
1375 	    rs[Rs_color + i] = def_colorName[i];
1376 
1377 #ifndef XTERM_REVERSE_VIDEO
1378     /* this is how we implement reverseVideo */
1379     if (ISSET_OPTION(r, Opt_reverseVideo))
1380     {
1381 	if (!rs[Rs_color + Color_fg])
1382 	    rs[Rs_color + Color_fg] = def_colorName[Color_fg];
1383 	if (!rs[Rs_color + Color_bg])
1384 	    rs[Rs_color + Color_bg] = def_colorName[Color_bg];
1385 
1386 	SWAP_IT(rs[Rs_color + Color_fg], rs[Rs_color + Color_bg], const char *);
1387 
1388 	for (i = 0; i < MAX_PROFILES; i++)
1389 	{
1390 	    int	    vtfg = Rs_foreground + i;
1391 	    int	    vtbg = Rs_background + i;
1392 	    if (!rs[vtfg])
1393 		rs[vtfg] = def_colorName[Color_fg];
1394 	    if (!rs[vtbg])
1395 		rs[vtbg] = def_colorName[Color_bg];
1396 
1397 	    SWAP_IT(rs[vtfg], rs[vtbg], const char*);
1398 	}
1399     }
1400 #endif
1401 
1402     /* convenient aliases for setting fg/bg to colors */
1403     rxvt_color_aliases(r, Color_fg);
1404     rxvt_color_aliases(r, Color_bg);
1405 #ifndef NO_CURSORCOLOR
1406     rxvt_color_aliases(r, Color_cursor);
1407     rxvt_color_aliases(r, Color_cursor2);
1408 #endif		    /* NO_CURSORCOLOR */
1409     rxvt_color_aliases(r, Color_pointer);
1410     rxvt_color_aliases(r, Color_border);
1411 #ifndef NO_BOLD_UNDERLINE_REVERSE
1412     rxvt_color_aliases(r, Color_BD);
1413     rxvt_color_aliases(r, Color_UL);
1414     rxvt_color_aliases(r, Color_RV);
1415 #endif		    /* ! NO_BOLD_UNDERLINE_REVERSE */
1416 
1417     /*
1418      * On startup, use autohideTabbar to override hideTabbar. Thus on startup,
1419      * using autohideTabbar will only display the tabbar if there are multiple
1420      * tabs. The user can hide / show the tabbar using a macro at will.
1421      */
1422     if(ISSET_OPTION(r, Opt2_autohideTabbar))
1423 	SET_OPTION(r, Opt2_hideTabbar);
1424 
1425     /* Cleanup the macro list */
1426     rxvt_cleanup_macros( r );
1427 
1428 
1429     /*
1430      * Profile settings.
1431      */
1432     for( i=0; i < MAX_PROFILES; i++ )
1433     {
1434 	/* Set saveLines */
1435 	if( r->h->rs[Rs_saveLines + i] )
1436 	{
1437 	    int tmp = atoi( r->h->rs[Rs_saveLines + i] );
1438 
1439 	    r->profile[i].saveLines = ( tmp >= 0 && tmp <= MAX_SAVELINES ) ?
1440 		    tmp : DEFAULT_SAVELINES;
1441 	}
1442 	else
1443 	    r->profile[i].saveLines = ( i > 0 ) ? r->profile[0].saveLines :
1444 							    DEFAULT_SAVELINES;
1445 
1446 	/* Set holdOption */
1447 	if( r->h->rs[Rs_holdExit + i] )
1448 	{
1449 	    const char *s = r->h->rs[Rs_holdExit + i];
1450 
1451 	    /* Backward compatibility hack */
1452 	    if(
1453 		 !STRCASECMP( s, "true" )	    ||
1454 		 !STRCASECMP( s, "yes" )	    ||
1455 		 !STRCASECMP( s, "on" )
1456 	      )
1457 		r->profile[i].holdOption = HOLD_ALWAYSBIT;
1458 	    else
1459 		r->profile[i].holdOption = strtoul( s, NULL, 0 );
1460 	}
1461 	else
1462 	    r->profile[i].holdOption = (i > 0) ? r->profile[0].holdOption :
1463 					    (HOLD_STATUSBIT|HOLD_NORMALBIT);
1464     } /* for(i) */
1465 
1466     if( !r->h->rs[Rs_holdExitTtl] )
1467 	r->h->rs[Rs_holdExitTtl] = "(Done) %t";
1468 
1469     if( !r->h->rs[Rs_holdExitTxt] )
1470 	r->h->rs[Rs_holdExitTxt] = "\n\n\r\e[31m"
1471 				   "Process exited %N with status %S. "
1472 				   "Press any key to close tab.\e[0m";
1473 
1474 #ifdef OS_LINUX
1475     if( !r->h->rs[Rs_cwd] )
1476 	r->h->rs[Rs_cwd] = ".";
1477 #endif
1478 
1479 #ifndef NO_BEEP
1480     if( r->h->rs[Rs_vBellDuration] )
1481 	r->TermWin.vBellDuration =
1482 	    1000000ul * strtoul( r->h->rs[Rs_vBellDuration], NULL, 0 );
1483     else
1484 	r->TermWin.vBellDuration = 0;
1485 #endif
1486 
1487 
1488     return cmd_argv;
1489 }
1490 
1491 /*----------------------------------------------------------------------*/
1492 /* EXTPROTO */
1493 void
rxvt_init_env(rxvt_t * r)1494 rxvt_init_env(rxvt_t *r)
1495 {
1496     int		    i;
1497     unsigned int    u;
1498     char*	    val;
1499 
1500 
1501 #ifdef DISPLAY_IS_IP
1502     /* Fixup display_name for export over pty to any interested
1503     ** terminal clients via "ESC[7n" (e.g. shells).  Note we use
1504     ** the pure IP number (for the first non-loopback interface)
1505     ** that we get from rxvt_network_display(). This is more
1506     ** "name-resolution-portable", if you will, and probably allows
1507     ** for faster x-client startup if your name server is beyond
1508     ** a slow link or overloaded at client startup. Of course that
1509     ** only helps the shell's child processes, not us.
1510     **
1511     ** Giving out the display_name also affords a potential
1512     ** security hole
1513     */
1514     val = rxvt_network_display(r->h->rs[Rs_display_name]);
1515     r->h->rs[Rs_display_name] = (const char *)val;
1516     if (IS_NULL(val))
1517 #endif		    /* DISPLAY_IS_IP */
1518     val = XDisplayString(r->Xdisplay);
1519     if (IS_NULL(r->h->rs[Rs_display_name]))
1520 	r->h->rs[Rs_display_name] = val;    /* use broken `:0' value */
1521 
1522     i = STRLEN(val) + 9;
1523     if (i <= 0 || i > 1024) /* possible integer overflow */
1524 	i = 1024;
1525     r->h->env_display = rxvt_malloc(i * sizeof(char));
1526     STRCPY (r->h->env_display, "DISPLAY=");
1527     STRNCAT (r->h->env_display, val, i-9);
1528     r->h->env_display[i-1] = (char) 0;
1529 
1530     /* avoiding the math library:
1531      * i = (int)(ceil(log10((unsigned int)r->TermWin.parent))) */
1532     for (i = 0, u = (unsigned int)r->TermWin.parent; u; u /= 10, i++)
1533 	;
1534     MAX_IT(i, 1);
1535     r->h->env_windowid = rxvt_malloc((i + 10) * sizeof(char));
1536 
1537     sprintf(r->h->env_windowid, "WINDOWID=%u",
1538 	(unsigned int)r->TermWin.parent);
1539 
1540     /*
1541     ** add entries to the environment:
1542     ** @ DISPLAY:   in case we started with -display
1543     ** @ WINDOWID:  X window id number of the window
1544     ** @ COLORTERM: terminal sub-name and also indicates its color
1545     ** @ TERM:	    terminal name
1546     ** @ TERMINFO:  path to terminfo directory
1547     */
1548 #ifdef HAVE_PUTENV
1549     putenv(r->h->env_display);
1550     putenv(r->h->env_windowid);
1551 
1552 # ifdef RXVT_TERMINFO
1553     putenv("TERMINFO=" RXVT_TERMINFO);
1554 # endif
1555     if (XDEPTH <= 2)
1556 	putenv("COLORTERM=" COLORTERMENV "-mono");
1557     else
1558 	putenv("COLORTERM=" COLORTERMENVFULL);
1559     if (NOT_NULL(r->h->rs[Rs_term_name]))
1560     {
1561 	int	l = 6 + STRLEN(r->h->rs[Rs_term_name]);
1562 	if (l <= 0 || l > 1024)	/* possible integer overflow */
1563 	    l = 1024;
1564 	r->h->env_term = rxvt_malloc(l * sizeof(char));
1565 	STRCPY (r->h->env_term, "TERM=");
1566 	STRNCAT (r->h->env_term, r->h->rs[Rs_term_name], l-6);
1567 	r->h->env_term[l-1] = (char) 0;
1568 	putenv(r->h->env_term);
1569     }
1570     else
1571 	putenv("TERM=" TERMENV);
1572 #endif	/* HAVE_PUTENV */
1573 
1574 #ifdef HAVE_UNSETENV
1575     /* avoid passing old settings and confusing term size */
1576     unsetenv("LINES");
1577     unsetenv("COLUMNS");
1578     unsetenv("TERMCAP");    /* terminfo should be okay */
1579 #endif		    /* HAVE_UNSETENV */
1580 
1581     /*
1582     ** allocate environment variable for MRXVT_TABTITLE, we will
1583     ** use it in rxvt_create_termwin later for each tab terminal
1584     */
1585     r->h->env_tabtitle = rxvt_malloc(sizeof(TABTITLEENV) + MAX_TAB_TXT + 1);
1586 }
1587 
1588 /*----------------------------------------------------------------------*/
1589 /*
1590  * This is more or less stolen straight from XFree86 xterm.
1591  * This should support all European type languages.
1592  */
1593 /* EXTPROTO */
1594 void
rxvt_init_xlocale(rxvt_t * r)1595 rxvt_init_xlocale(rxvt_t *r)
1596 {
1597 #ifdef USE_XIM
1598     if (IS_NULL(r->h->locale))
1599 	rxvt_msg (DBG_ERROR, DBG_INIT, "Setting locale failed.");
1600     else
1601     {
1602 	XChangeProperty(r->Xdisplay, r->TermWin.parent,
1603 	    r->h->xa[XA_WM_LOCALE_NAME], XA_STRING, 8, PropModeReplace,
1604 	    (unsigned char *)r->h->locale, STRLEN(r->h->locale));
1605 
1606 	if (XSupportsLocale() != True)
1607 	{
1608 	    rxvt_msg (DBG_ERROR, DBG_INIT, "The locale is not supported by Xlib");
1609 	    return;
1610 	}
1611 	rxvt_IM_set_fontset (r, 0);
1612 
1613 	/* see if we can connect yet */
1614 	rxvt_IM_init_callback (r->Xdisplay, NULL, NULL);
1615 
1616 	/* To avoid Segmentation Fault in C locale: Solaris only? */
1617 	if (STRCMP(r->h->locale, "C"))
1618 	    XRegisterIMInstantiateCallback(r->Xdisplay, NULL, NULL,
1619 		NULL, rxvt_IM_init_callback, NULL);
1620     }
1621 #endif
1622 }
1623 
1624 /*----------------------------------------------------------------------*/
1625 
1626 /* EXTPROTO */
1627 #ifdef USE_FIFO
1628 void
rxvt_init_fifo(rxvt_t * r)1629 rxvt_init_fifo( rxvt_t *r )
1630 {
1631     unlink( r->fifo_name );
1632     mkfifo( r->fifo_name, 0600 );
1633 
1634     /*
1635      * Create the fifo in read write mode. If not, when no clients have the
1636      * fifo open, select() will claim our fifo has data pending and return.
1637      */
1638     r->fifo_fd = open( r->fifo_name, O_RDONLY|O_NDELAY );
1639     if( r->fifo_fd == -1 )
1640 	UNSET_OPTION( r, Opt_useFifo );
1641     else
1642 	MAX_IT( r->num_fds, r->fifo_fd + 1);
1643 
1644     /* Reset the fifo buffer */
1645     r->fbuf_ptr = r->fifo_buf;
1646 }
1647 #endif
1648 
1649 /* EXTPROTO */
1650 void
rxvt_init_command(rxvt_t * r)1651 rxvt_init_command(rxvt_t* r)
1652 {
1653     /*
1654      * Initialize the command connection. This should be called after the X
1655      * server connection is established.
1656      */
1657     struct sigaction	act;
1658 
1659     rxvt_dbgmsg ((DBG_DEBUG, DBG_INIT, "%s()\n", __func__));
1660 
1661 
1662     /*
1663      * Enable delete window protocol so that if the top-level window of the
1664      * terminal is destroyed by the Session Manager, we can receive a
1665      * ClientMessage event and do something gracefully.
1666      */
1667     XSetWMProtocols (r->Xdisplay, r->TermWin.parent,
1668 	    &(r->h->xa[XA_WMDELETEWINDOW]), 1);
1669 
1670 #ifdef META8_OPTION
1671     r->h->meta_char = (ISSET_OPTION(r, Opt_meta8) ? 0x80 : C0_ESC);
1672 #endif
1673     rxvt_get_ourmods(r);
1674 
1675 #ifdef GREEK_SUPPORT
1676     greek_init();
1677 #endif
1678 
1679     r->Xfd = XConnectionNumber(r->Xdisplay);
1680 #ifdef USE_FIFO
1681     if( ISSET_OPTION( r, Opt_useFifo ) )
1682 	rxvt_init_fifo( r );
1683     else
1684 	r->fifo_fd = -1;
1685 #endif
1686 
1687 #ifdef CURSOR_BLINK
1688     if (ISSET_OPTION(r, Opt_cursorBlink))
1689 	(void)gettimeofday(&r->h->lastcursorchange, NULL);
1690 #endif
1691 
1692     /*
1693      * Gracefully exit on term signals.
1694      */
1695     act.sa_handler  = rxvt_Exit_signal;
1696     act.sa_flags    = 0;
1697     sigemptyset (&act.sa_mask);
1698 
1699 #ifndef OS_SVR4
1700     sigaction( SIGINT , &act, NULL);
1701 #endif
1702     sigaction( SIGQUIT, &act, NULL);
1703     sigaction( SIGTERM, &act, NULL);
1704 
1705     /*
1706      * 2006-04-28 gi1242: Ignore HUP signals. We sometimes receive this if bash
1707      * is killed. Chances are that we don't have to exit ...
1708      */
1709     act.sa_handler  = SIG_IGN;
1710     sigaction( SIGHUP, &act, NULL);
1711 
1712 #ifdef PRINTPIPE
1713     /*
1714      * 2006-04-28 gi1242: If there is an error opening the printer command, then
1715      * we'll get SIGPIPE. If not handled, mrxvt will exit.
1716      *
1717      * There's nothing we really need to do on broken pipes, so just ignore
1718      * SIGPIPE for now.
1719      */
1720     sigaction( SIGPIPE, &act, NULL);
1721 #endif
1722 
1723     act.sa_handler  = rxvt_Child_signal;
1724     sigaction (SIGCHLD, &act, NULL);
1725 }
1726 
1727 
1728 /* EXTPROTO */
1729 void
rxvt_fade_color(rxvt_t * r,const XColor * xcol,unsigned long * pix_return,XftColor * xft_return)1730 rxvt_fade_color( rxvt_t* r, const XColor *xcol,
1731 	unsigned long	*pix_return,
1732 # ifdef XFT_SUPPORT
1733 	XftColor	*xft_return
1734 # else
1735 	void		*xft_return
1736 # endif
1737 	)
1738 {
1739     if( r->TermWin.fade )
1740     {
1741 	XColor	faded_xcol;
1742 
1743 	faded_xcol.red   = (xcol->red	/ 100) * r->TermWin.fade;
1744 	faded_xcol.green = (xcol->green	/ 100) * r->TermWin.fade;
1745 	faded_xcol.blue  = (xcol->blue	/ 100) * r->TermWin.fade;
1746 
1747 	rxvt_alloc_color( r, &faded_xcol, "Faded" );
1748 
1749 	*pix_return = faded_xcol.pixel;
1750 # ifdef XFT_SUPPORT
1751 	if( NOT_NULL( xft_return ) )
1752 	    rxvt_alloc_xft_color( r, &faded_xcol, xft_return );
1753 
1754 # endif
1755     }
1756 }
1757 
1758 
1759 #define setChanged( a, b )  \
1760     if( (a) != (b) ) {(a) = (b); changed = 1;}
1761 #define setChangedXft( a, b ) \
1762     if( (a).pixel != (b).pixel ) { (a) = (b); changed = 1;}
1763 /*
1764  * Sets r->pixColors[Color_fg] / etc to the correct color (depending on the ufbg
1765  * color, off focus fading and weather we have focus or not).
1766  */
1767 /* EXTPROTO */
1768 int
rxvt_set_fgbg_colors(rxvt_t * r,int page)1769 rxvt_set_fgbg_colors( rxvt_t *r, int page )
1770 {
1771     int changed = 0;
1772 
1773     rxvt_dbgmsg(( DBG_DEBUG, DBG_INIT, "%s(r, page=%d)"
1774 		": fgbg_tabnum=%d, globalTabNum=%d\n", __func__, page,
1775 		r->fgbg_tabnum, PVTS(r, page)->globalTabNum));
1776 
1777     if(
1778 	 r->fgbg_tabnum == PVTS(r, page)->globalTabNum &&
1779 	 (
1780 	   r->TermWin.fade			||
1781 	   !ISSET_PIXCOLOR( r->h, Color_ufbg )	||
1782 	   (
1783 	     /*
1784 	      * If we dont have fading, but have ufbg, then make sure that
1785 	      * Color_bg points to the correct color.
1786 	      */
1787 	     r->TermWin.focus						?
1788 		( r->pixColors[Color_bg] == PVTS(r, page)->p_bg )	:
1789 		( r->pixColors[Color_bg] == r->pixColors[Color_ufbg] )
1790 	   )
1791 	 )
1792       )
1793 	return 0;   /* No change */
1794 
1795     setChanged( r->pixColorsFocus[Color_fg], PVTS( r, page)->p_fg );
1796 #ifdef XFT_SUPPORT
1797     if( ISSET_OPTION( r, Opt_xft ) )
1798 	setChangedXft( r->xftColorsFocus[Color_fg], PVTS(r, page)->p_xftfg );
1799 #endif
1800 
1801     if( r->TermWin.fade )
1802     {
1803 	/* Ignore ufbg, and use faded colors */
1804 	setChanged( r->pixColorsFocus[Color_bg], PVTS(r, page)->p_bg );
1805 
1806 	setChanged( r->pixColorsUnfocus[Color_fg], PVTS(r, page)->p_fgfade );
1807 	setChanged( r->pixColorsUnfocus[Color_bg], PVTS(r, page)->p_bgfade );
1808 
1809 #ifdef XFT_SUPPORT
1810 	if( ISSET_OPTION( r, Opt_xft ) )
1811 	{
1812 	    setChangedXft( r->xftColorsFocus[Color_bg],
1813 		    PVTS(r, page)->p_xftbg );
1814 
1815 	    setChangedXft( r->xftColorsUnfocus[Color_fg],
1816 		    PVTS(r, page)->p_xftfgfade );
1817 	    setChangedXft( r->xftColorsUnfocus[Color_bg],
1818 		    PVTS(r, page)->p_xftbgfade );
1819 	}
1820 #endif
1821     }
1822 
1823     else if( ISSET_PIXCOLOR( r->h, Color_ufbg ) && !r->TermWin.focus )
1824     {
1825 	/* No fading. But use Color_ufbg */
1826 	setChanged( r->pixColorsFocus[Color_bg],
1827 		r->pixColorsFocus[Color_ufbg] );
1828 #ifdef XFT_SUPPORT
1829 	if( ISSET_OPTION( r, Opt_xft ) )
1830 	    setChangedXft( r->xftColorsFocus[Color_bg],
1831 		    r->xftColorsFocus[Color_ufbg] );
1832 #endif
1833     }
1834 
1835     else
1836     {
1837 	/* Use fgbg from profile */
1838 	setChanged( r->pixColorsFocus[Color_bg],
1839 		PVTS(r, page)->p_bg );
1840 #ifdef XFT_SUPPORT
1841 	if( ISSET_OPTION( r, Opt_xft ) )
1842 	    setChangedXft( r->xftColorsFocus[Color_bg],
1843 		    PVTS(r, page)->p_xftbg );
1844 #endif
1845     }
1846 
1847     r->fgbg_tabnum = PVTS( r, page )->globalTabNum;
1848 
1849     rxvt_dbgmsg(( DBG_DEBUG, DBG_INIT, "%s(r, page=%d) returning %d\n",
1850 	    __func__, page, changed ));
1851     return changed; /* Changed */
1852 }
1853 #undef setChanged
1854 #undef setChangedXft
1855 
1856 
1857 void
rxvt_copy_color(rxvt_t * r,int dst_index,int src_index)1858 rxvt_copy_color( rxvt_t *r, int dst_index, int src_index )
1859 {
1860     r->pixColorsFocus[ dst_index ] = r->pixColorsFocus[ src_index ];
1861 
1862     if( r->TermWin.fade )
1863 	r->pixColorsUnfocus[ dst_index ] = r->pixColorsUnfocus[ src_index ];
1864 
1865 #ifdef XFT_SUPPORT
1866     if( ISSET_OPTION( r, Opt_xft ) )
1867     {
1868 	r->xftColorsFocus[ dst_index ] = r->xftColorsFocus[ src_index ];
1869 
1870 	if( r->TermWin.fade )
1871 	    r->xftColorsUnfocus[ dst_index ] = r->xftColorsUnfocus[ src_index ];
1872     }
1873 #endif
1874 
1875     SET_PIXCOLOR( r->h, dst_index );
1876 }
1877 
1878 
1879 void
rxvt_set_color(rxvt_t * r,int cIndex,const XColor * xcol)1880 rxvt_set_color( rxvt_t *r, int cIndex, const XColor *xcol )
1881 {
1882     /* xcol must contain an ALLOCATED color */
1883     r->pixColorsFocus[cIndex] = xcol->pixel;
1884 #ifdef XFT_SUPPORT
1885     if( ISSET_OPTION( r, Opt_xft ) )
1886 	rxvt_alloc_xft_color( r, xcol, &r->xftColorsFocus[cIndex] );
1887 #endif
1888 
1889     if( r->TermWin.fade )
1890     {
1891 	if( cIndex == Color_pointer )
1892 	{
1893 	    /* Don't fade these colors */
1894 	    r->pixColorsUnfocus[cIndex] = r->pixColorsFocus[cIndex];
1895 #ifdef XFT_SUPPORT
1896 	    if( ISSET_OPTION( r, Opt_xft ) )
1897 		r->xftColorsUnfocus[cIndex] = r->xftColorsFocus[cIndex];
1898 #endif
1899 	}
1900 
1901 	else
1902 	    rxvt_fade_color( r, xcol, &r->pixColorsUnfocus[cIndex],
1903 #ifdef XFT_SUPPORT
1904 		ISSET_OPTION(r, Opt_xft) ? &r->xftColorsUnfocus[cIndex] : NULL
1905 #else
1906 		NULL
1907 #endif
1908 		);
1909     }
1910 
1911     SET_PIXCOLOR( r->h, cIndex );
1912 }
1913 
1914 
1915 /*
1916  * XXX 2006-05-24 gi1242: Should allocate Xft colors only if Opt_xft is set. In
1917  * that case we should avoid allocating XColors, since we can always access them
1918  * through xftcolor.pixel.
1919  */
1920 /* INTPROTO */
1921 void
rxvt_init_colors(rxvt_t * r)1922 rxvt_init_colors( rxvt_t *r )
1923 {
1924     register int    i;
1925 
1926     rxvt_dbgmsg ((DBG_DEBUG, DBG_INIT, "%s()\n", __func__));
1927 
1928     /* Initialize fg/bg colors for each profile */
1929     for (i = 0; i < MAX_PROFILES; i++)
1930     {
1931 	XColor	    xcol;
1932 	int	    vtfg = Rs_foreground + i;
1933 	int	    vtbg = Rs_background + i;
1934 
1935 	if( !ISSET_VTFG( r, i ) )
1936 	    r->h->rs[vtfg] =  ISSET_VTFG( r, 0 ) ?
1937 		    r->h->rs[Rs_foreground] : def_colorName[ Color_fg ];
1938 	if( !ISSET_VTBG( r, i ) )
1939 	    r->h->rs[vtbg] = ISSET_VTBG( r, 0 ) ?
1940 		    r->h->rs[Rs_background] : def_colorName[ Color_bg ];
1941 
1942 	/* foreground color of i terminal */
1943 	if( rxvt_parse_alloc_color(r, &xcol, r->h->rs[vtfg]) )
1944 	{
1945 	    VTFG(r, i) = xcol.pixel;
1946 
1947 #ifdef XFT_SUPPORT
1948 	    rxvt_alloc_xft_color( r, &xcol, &(VTXFTFG(r, i)) );
1949 	    rxvt_fade_color( r, &xcol, &VTFG_FADE(r, i), &VTXFTFG_FADE(r, i) );
1950 #else
1951 	    rxvt_fade_color( r, &xcol, &VTFG_FADE(r, i), NULL );
1952 #endif /* XFT_SUPPORT */
1953 	}
1954 
1955 	else
1956 	{
1957 	    rxvt_msg (DBG_ERROR, DBG_INIT,  "Could not alloc foreground color of profile %d",
1958 		    i );
1959 	    if( i == 0 )
1960 		/* Need default fg/bg */
1961 		exit( EXIT_FAILURE );
1962 
1963 	    /* Use foreground from profie 0 */
1964 	    VTFG( r, i ) = VTFG( r, 0 );
1965 	    VTFG_FADE( r, i ) = VTFG_FADE( r, 0 );
1966 
1967 #ifdef XFT_SUPPORT
1968 	    VTXFTFG( r, i ) = VTXFTFG( r, 0 );
1969 	    VTXFTFG_FADE( r, i ) = VTXFTFG_FADE( r, 0 );
1970 #endif
1971 	}
1972 
1973 	/* background color of i terminal */
1974 	if( rxvt_parse_alloc_color(r, &xcol, r->h->rs[vtbg]) )
1975 	{
1976 	    VTBG(r, i) = xcol.pixel;
1977 
1978 #ifdef XFT_SUPPORT
1979 	    rxvt_alloc_xft_color( r, &xcol, &(VTXFTBG(r, i)) );
1980 	    rxvt_fade_color( r, &xcol, &VTBG_FADE(r, i), &VTXFTBG_FADE(r, i) );
1981 #else
1982 	    rxvt_fade_color( r, &xcol, &VTBG_FADE(r, i), NULL );
1983 #endif /* XFT_SUPPORT */
1984 	}
1985 
1986 	else
1987 	{
1988 	    rxvt_msg (DBG_ERROR, DBG_INIT,  "Could not alloc background color of profile %d",
1989 		    i );
1990 	    if( i == 0 )
1991 		/* Need default fg/bg */
1992 		exit( EXIT_FAILURE );
1993 
1994 	    /* Use background from profie 0 */
1995 	    VTBG( r, i ) = VTBG( r, 0 );
1996 	    VTBG_FADE( r, i ) = VTBG_FADE( r, 0 );
1997 
1998 #ifdef XFT_SUPPORT
1999 	    VTXFTBG( r, i ) = VTXFTBG( r, 0 );
2000 	    VTXFTBG_FADE( r, i ) = VTXFTBG_FADE( r, 0 );
2001 #endif
2002 	}
2003     }
2004 
2005     /* Set foreground / background colors */
2006     r->pixColorsFocus[ Color_fg ] = VTFG( r, 0 );
2007     r->pixColorsFocus[ Color_bg ] = VTBG( r, 0 );
2008 
2009     if( r->TermWin.fade )
2010     {
2011 	r->pixColorsUnfocus[ Color_fg ] = VTFG_FADE( r, 0 );
2012 	r->pixColorsUnfocus[ Color_bg ] = VTBG_FADE( r, 0 );
2013     }
2014 
2015 #ifdef XFT_SUPPORT
2016     if( ISSET_OPTION( r, Opt_xft ) )
2017     {
2018 	r->xftColorsFocus[ Color_fg ] = VTXFTFG( r, 0 );
2019 	r->xftColorsFocus[ Color_bg ] = VTXFTBG( r, 0 );
2020 
2021 	if( r->TermWin.fade )
2022 	{
2023 	    r->xftColorsUnfocus[ Color_fg ] = VTXFTFG( r, 0 );
2024 	    r->xftColorsUnfocus[ Color_bg ] = VTXFTBG( r, 0 );
2025 	}
2026     }
2027 #endif
2028 
2029     r->fgbg_tabnum = -1;    /* fg/bg corresponds to profile 0, not any
2030 			       particular tab during initialization. */
2031 
2032 
2033     /*
2034      * Allocate generic colors.
2035      */
2036     for (i = minCOLOR; i < (XDEPTH <= 2 ? 2 : NRS_COLORS); i++)
2037     {
2038 	XColor		xcol;
2039 
2040 	if( IS_NULL(r->h->rs[Rs_color + i]) )
2041 	    continue;
2042 
2043 	if( !rxvt_parse_alloc_color(r, &xcol, r->h->rs[Rs_color + i]) )
2044 	{
2045 	    if( r->h->rs[Rs_color+i] != def_colorName[i] )
2046 	    {
2047 		rxvt_msg (DBG_ERROR, DBG_INIT,  "Could not allocate color '%s'\n",
2048 			r->h->rs[Rs_color + i] );
2049 
2050 		/* Try again with default color */
2051 		r->h->rs[Rs_color + i] = def_colorName[i];
2052 		i--;
2053 		continue;
2054 	    }
2055 
2056 	    /*
2057 	     * Unable to alloc even the default color. Fall back to fg/bg.
2058 	     */
2059 	    switch( i )
2060 	    {
2061 #ifndef NO_CURSORCOLOR
2062 		case Color_cursor2:
2063 #endif /* !NO_CURSORCOLOR */
2064 		case Color_pointer:
2065 		    rxvt_copy_color( r, i, Color_fg );
2066 		    break;
2067 
2068 		default:
2069 		    rxvt_copy_color( r, i, Color_bg );
2070 		    break;
2071 	    }
2072 	}
2073 
2074 	else
2075 	{
2076 	    /*
2077 	     * Succeeded allocating the color. Store it in pixColors.
2078 	     */
2079 	    rxvt_set_color( r, i, &xcol );
2080 	}
2081     } /* for(i) */
2082 
2083 
2084     /*
2085      * Allocate colors which are essential if they have not been allocated.
2086      */
2087     if( XDEPTH <= 2 || !ISSET_PIXCOLOR( r->h, Color_pointer ) )
2088     {
2089 	/*
2090 	 * NOTE: Fading should be disabled for low depths. And the pointer color
2091 	 * should not be faded.
2092 	 */
2093 	r->pixColorsFocus[Color_pointer]    = VTFG(r, 0);
2094 	if( r->TermWin.fade )
2095 	    r->pixColorsUnfocus[Color_pointer]  = VTFG(r, 0);
2096 #ifdef XFT_SUPPORT
2097 	if( ISSET_OPTION( r, Opt_xft ) )
2098 	{
2099 	    r->xftColorsFocus[Color_pointer]	= VTXFTFG(r, 0);
2100 	    if( r->TermWin.fade )
2101 		r->xftColorsUnfocus[Color_pointer]  = VTXFTFG(r, 0);
2102 	}
2103 #endif
2104 	SET_PIXCOLOR( r->h, Color_pointer );
2105     }
2106 
2107     if( XDEPTH <= 2 || !ISSET_PIXCOLOR( r->h, Color_border ) )
2108 	rxvt_copy_color( r, Color_border, Color_fg );
2109 
2110 
2111     /*
2112      * get scrollBar/menuBar shadow colors
2113      *
2114      * The calculations of topShadow/bottomShadow values are adapted from the
2115      * fvwm window manager.
2116      */
2117 #ifdef KEEP_SCROLLCOLOR
2118     if (XDEPTH <= 2)	    /* Monochrome */
2119     {
2120 	rxvt_copy_color( r, Color_scroll,	Color_fg );
2121 	rxvt_copy_color( r, Color_topShadow,	Color_bg );
2122 	rxvt_copy_color( r, Color_bottomShadow, Color_bg );
2123     }
2124 
2125     else
2126     {
2127 	XColor		xcol[3];
2128 	/*
2129 	 * xcol[0] == white
2130 	 * xcol[1] == top shadow
2131 	 * xcol[2] == bot shadow
2132 	 */
2133 
2134 	xcol[1].pixel = r->pixColorsFocus[Color_scroll];
2135 # ifdef PREFER_24BIT
2136 	xcol[0].red = xcol[0].green = xcol[0].blue = 0xffffu;
2137 	rxvt_alloc_color( r, &(xcol[0]), "White" );
2138 	XQueryColors(r->Xdisplay, XCMAP, &(xcol[1]), 1);
2139 # else
2140 	xcol[0].pixel = WhitePixel(r->Xdisplay, XSCREEN);
2141 	XQueryColors(r->Xdisplay, XCMAP, xcol, 2);
2142 # endif
2143 
2144 	/* bottomShadowColor */
2145 	xcol[2].red	= xcol[1].red	/ 2;
2146 	xcol[2].green	= xcol[1].green / 2;
2147 	xcol[2].blue	= xcol[1].blue	/ 2;
2148 	if( !rxvt_alloc_color( r, &(xcol[2]), "Color_bottomShadow" ) )
2149 	    rxvt_copy_color( r, Color_bottomShadow, Color_Black );
2150 
2151 	else
2152 	    rxvt_set_color( r, Color_bottomShadow, &xcol[2] );
2153 
2154 
2155 	/* topShadowColor */
2156 	xcol[1].red	= max((xcol[0].red   / 5), xcol[1].red	);
2157 	xcol[1].green	= max((xcol[0].green / 5), xcol[1].green);
2158 	xcol[1].blue	= max((xcol[0].blue  / 5), xcol[1].blue	);
2159 	xcol[1].red	= min(xcol[0].red,   (xcol[1].red   * 7) / 5);
2160 	xcol[1].green	= min(xcol[0].green, (xcol[1].green * 7) / 5);
2161 	xcol[1].blue	= min(xcol[0].blue,  (xcol[1].blue  * 7) / 5);
2162 
2163 	if( !rxvt_alloc_color(r, &(xcol[1]), "Color_topShadow") )
2164 	    rxvt_copy_color( r, Color_topShadow, Color_White );
2165 	else
2166 	    rxvt_set_color( r, Color_topShadow, &xcol[1] );
2167 
2168     }
2169 #endif	/* KEEP_SCROLLCOLOR */
2170 
2171 
2172 #ifdef TEXT_SHADOW
2173     if (r->h->rs[Rs_textShadow])
2174     {
2175 	XColor	xcol;
2176 	if( rxvt_parse_alloc_color( r, &xcol, r->h->rs[Rs_textShadow] ) )
2177 	{
2178 	    r->TermWin.shadow = xcol.pixel;
2179 # ifdef XFT_SUPPORT
2180 	    rxvt_alloc_xft_color( r, &xcol, &(r->TermWin.xftshadow));
2181 # endif
2182 	}
2183 	else
2184 	{
2185 	    r->TermWin.shadow = r->pixColorsFocus[Color_Black];
2186 # ifdef XFT_SUPPORT
2187 	    r->TermWin.xftshadow = r->xftColorsFocus[Color_Black];
2188 # endif
2189 	}
2190     }
2191 #endif
2192 }
2193 
2194 
2195 /*----------------------------------------------------------------------*/
2196 /* color aliases, fg/bg bright-bold */
2197 /* INTPROTO */
2198 void
rxvt_color_aliases(rxvt_t * r,int idx)2199 rxvt_color_aliases( rxvt_t *r, int idx )
2200 {
2201     if (r->h->rs[Rs_color + idx] && isdigit((int) *(r->h->rs[Rs_color + idx])))
2202     {
2203 	int	    i = atoi(r->h->rs[Rs_color + idx]);
2204 
2205 	if (i >= 8 && i <= 15)		/* bright colors */
2206 	{
2207 	    i -= 8;
2208 #ifndef NO_BRIGHTCOLOR
2209 	    r->h->rs[Rs_color + idx] = r->h->rs[Rs_color + minBrightCOLOR + i];
2210 	    return;
2211 #endif
2212 	}
2213 	if (i >= 0 && i <= 7)	/* normal colors */
2214 	    r->h->rs[Rs_color + idx] = r->h->rs[Rs_color + minCOLOR +i];
2215     }
2216 }
2217 
2218 
2219 /* INTPROTO */
2220 void
rxvt_init_win_size(rxvt_t * r)2221 rxvt_init_win_size( rxvt_t *r )
2222 {
2223     int		    flags = 0;	/* must initialize to 0!!! */
2224     short	    recalc_x = 0, recalc_y = 0,
2225 		    recalc_width = 1, recalc_height = 1;
2226     int		    x, y;
2227     unsigned int    w, h;
2228 
2229 
2230     r->szHint.flags = PMinSize | PResizeInc | PBaseSize | PWinGravity;
2231     r->szHint.win_gravity = NorthWestGravity;
2232 
2233     /* Set default terminal columns and rows */
2234     r->TermWin.ncol = 80;
2235     r->TermWin.nrow = 24;
2236     r->szHint.x = 0;
2237     r->szHint.y = 0;
2238 
2239 #ifdef TRANSPARENT
2240     refreshRootBGVars( r );
2241 #endif
2242 
2243     /* Get geometry in x, y, w, h */
2244     if (r->h->rs[Rs_geometry])
2245 	flags = XParseGeometry(r->h->rs[Rs_geometry], &x, &y, &w, &h);
2246 
2247     /* Calculate the terminal increment width and height */
2248 #ifndef NO_FRILLS
2249     if( ISSET_OPTION(r, Opt2_smoothResize))
2250     {
2251 	r->szHint.width_inc = 1;
2252 	r->szHint.height_inc = 1;
2253     }
2254     else
2255 #endif
2256     {
2257 	r->szHint.width_inc = r->TermWin.fwidth;
2258 	r->szHint.height_inc = r->TermWin.fheight;
2259     }
2260 
2261     /* Calculate the base width and height */
2262     r->szHint.base_width = 2 * r->TermWin.int_bwidth;
2263     r->szHint.base_height = 2 * r->TermWin.int_bwidth;
2264 #ifdef HAVE_SCROLLBARS
2265     if (ISSET_OPTION(r, Opt_scrollBar))
2266 	r->szHint.base_width += rxvt_scrollbar_rwidth (r);
2267 #endif
2268 #ifdef HAVE_MENUBAR
2269     if (ISSET_OPTION(r, Opt_showMenu))
2270 	r->szHint.base_height += rxvt_menubar_rheight (r);
2271 #endif
2272     if (NOTSET_OPTION(r, Opt2_hideTabbar))
2273 	r->szHint.base_height += rxvt_tabbar_rheight (r);
2274 
2275     /* Set the terminal minimal width and height */
2276     r->szHint.min_width = r->szHint.base_width + r->TermWin.fwidth;
2277     r->szHint.min_height = r->szHint.base_height + r->TermWin.fheight;
2278 
2279     /* Parse Geometry */
2280     if (flags & WidthValue)
2281     {
2282 	r->TermWin.ncol = BOUND_POSITIVE_INT16(w);
2283 #ifndef NO_FRILLS
2284 	if( ISSET_OPTION(r, Opt2_smoothResize) )
2285 	{
2286 	    /* For smoothResize, w as a pixel width (if large enough) */
2287 	    if(r->TermWin.ncol > r->szHint.base_width + r->TermWin.fwidth)
2288 	    {
2289 		r->szHint.width = r->TermWin.ncol;
2290 		r->TermWin.ncol = (r->TermWin.ncol - r->szHint.base_width) /
2291 							r->TermWin.fwidth;
2292 		recalc_width = 0;
2293 	    }
2294 	    else r->TermWin.ncol = 1;
2295 	}
2296 #endif
2297 	r->szHint.flags |= USSize;
2298     }
2299     if (flags & HeightValue)
2300     {
2301 	r->TermWin.nrow = BOUND_POSITIVE_INT16(h);
2302 #ifndef NO_FRILLS
2303 	if(ISSET_OPTION(r, Opt2_smoothResize))
2304 	{
2305 	    /* For smoothResize, w as a pixel height (if large enough) */
2306 	    if(r->TermWin.nrow > r->szHint.base_height + r->TermWin.fheight)
2307 	    {
2308 		r->szHint.height = r->TermWin.nrow;
2309 		r->TermWin.nrow =
2310 		    (r->TermWin.nrow - r->szHint.base_height) / r->TermWin.fheight;
2311 		recalc_height = 0;
2312 	    }
2313 	    else r->TermWin.nrow = 1;
2314 	}
2315 #endif
2316 	r->szHint.flags |= USSize;
2317     }
2318     if (flags & XValue)
2319     {
2320 	r->szHint.x = x;
2321 	r->szHint.flags |= USPosition;
2322 	if (flags & XNegative)
2323 	{
2324 	    recalc_x = 1;
2325 	    r->szHint.win_gravity = NorthEastGravity;
2326 	}
2327     }
2328     if (flags & YValue)
2329     {
2330 	r->szHint.y = y;
2331 	r->szHint.flags |= USPosition;
2332 	if (flags & YNegative)
2333 	{
2334 	    recalc_y = 1;
2335 	    if (r->szHint.win_gravity == NorthEastGravity)
2336 		r->szHint.win_gravity = SouthEastGravity;
2337 	    else
2338 		r->szHint.win_gravity = SouthWestGravity;
2339 	}
2340     }
2341 
2342     /* Set the terminal width and height */
2343     if( recalc_width)
2344 	r->szHint.width = r->szHint.base_width + Width2Pixel (r->TermWin.ncol);
2345     if( recalc_height)
2346 	r->szHint.height = r->szHint.base_height + Height2Pixel (r->TermWin.nrow);
2347 
2348     /* Recalculate the starting position */
2349     if (recalc_x)
2350 	r->szHint.x += (DisplayWidth(r->Xdisplay, XSCREEN)
2351 	    - r->szHint.width - 2 * r->TermWin.ext_bwidth);
2352     if (recalc_y)
2353 	r->szHint.y += (DisplayHeight(r->Xdisplay, XSCREEN)
2354 	    - r->szHint.height - 2 * r->TermWin.ext_bwidth);
2355 
2356     /* Set the terminal window starting position */
2357     r->h->window_vt_x = (ISSET_OPTION(r, Opt_scrollBar_right)) ?
2358 	    0 : r->szHint.base_width - 2*r->TermWin.int_bwidth;
2359     r->h->window_vt_y = r->szHint.base_height - 2*r->TermWin.int_bwidth;
2360     if (ISSET_OPTION(r, Opt2_bottomTabbar) && NOTSET_OPTION(r, Opt2_hideTabbar))
2361 	r->h->window_vt_y -= rxvt_tabbar_rheight (r);
2362 }
2363 
2364 
2365 /*----------------------------------------------------------------------*/
2366 /*
2367  * Probe the modifier keymap to get the Meta (Alt) and Num_Lock settings
2368  * Use resource ``modifier'' to override the Meta modifier
2369  */
2370 /* INTPROTO */
2371 void
rxvt_get_ourmods(rxvt_t * r)2372 rxvt_get_ourmods( rxvt_t *r )
2373 {
2374     int			i, j, k;
2375     int			requestedmeta, realmeta, realalt;
2376     const char*		cm;
2377     const char*		rsmod;
2378     XModifierKeymap*	map;
2379     KeyCode*		kc;
2380     const unsigned int	modmasks[] =
2381     {
2382 	Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
2383     };
2384 
2385 
2386     requestedmeta = realmeta = realalt = 0;
2387 
2388     rsmod = r->h->rs[Rs_modifier];
2389     if (rsmod &&
2390 	STRCASECMP(rsmod, "mod1") >= 0 &&
2391 	STRCASECMP(rsmod, "mod5") <= 0)
2392 	requestedmeta = rsmod[3] - '0';
2393 
2394     map = XGetModifierMapping(r->Xdisplay);
2395     kc = map->modifiermap;
2396     for (i = 1; i < 6; i++)
2397     {
2398 	k = (i + 2) * map->max_keypermod;   /* skip shift/lock/control */
2399 	for (j = map->max_keypermod; j--; k++)
2400 	{
2401 	    if (kc[k] == 0)
2402 		break;
2403 
2404 	    switch (XKeycodeToKeysym(r->Xdisplay, kc[k], 0))
2405 	    {
2406 		case XK_Num_Lock:
2407 		    r->h->ModNumLockMask = modmasks[i - 1];
2408 		    /* FALLTHROUGH */
2409 		default:
2410 		    continue;	/* for(;;) */
2411 		case XK_Meta_L:
2412 		case XK_Meta_R:
2413 		    cm = "meta";
2414 		    realmeta = i;
2415 		    break;
2416 		case XK_Alt_L:
2417 		case XK_Alt_R:
2418 		    cm = "alt";
2419 		    realalt = i;
2420 		    break;
2421 		case XK_Super_L:
2422 		case XK_Super_R:
2423 		    cm = "super";
2424 		    break;
2425 		case XK_Hyper_L:
2426 		case XK_Hyper_R:
2427 		    cm = "hyper";
2428 		    break;
2429 	    }
2430 
2431 	    if (rsmod && STRNCASECMP(rsmod, cm, STRLEN(cm)) == 0)
2432 		requestedmeta = i;
2433 	}
2434     }
2435     XFreeModifiermap(map);
2436 
2437     i = (requestedmeta ? requestedmeta : (
2438 	    realmeta ? realmeta : (
2439 	    realalt ? realalt : 0)));
2440 
2441     if (i)
2442 	r->h->ModMetaMask = modmasks[i - 1];
2443 }
2444 
2445 
2446 
2447 /* EXTPROTO */
2448 char**
rxvt_string_to_argv(const char * string,int * argc)2449 rxvt_string_to_argv( const char *string, int *argc )
2450 {
2451     int		    i = 0;
2452     char**	    pret;
2453     const char*	    pcur;
2454 #ifdef INTERNAL_ARGV_SPLIT
2455     const char*	    pbeg;
2456 #endif
2457 
2458     *argc = 0;
2459     if( IS_NULL(string) || *string == '\0' )
2460     {
2461 	*argc = 0;
2462 	return NULL;
2463     }
2464 
2465 #define MAX_ARGV    (1024)
2466     /* Up to 64 argv.
2467      *
2468      * 2006-02-23 gi1242: Use calloc instead of malloc. Thus when freeing pret,
2469      * we can safely free all elements till we encounter a NULL pointer.
2470      */
2471     pret = (char**) rxvt_calloc (MAX_ARGV, sizeof (char*));
2472 
2473     rxvt_dbgmsg ((DBG_DEBUG, DBG_INIT, "fetch command argv for the tab\n"));
2474 #ifdef INTERNAL_ARGV_SPLIT
2475     /*{{{*/
2476     /*
2477      * 2006-02-23 gi1242: Remember to leave space for a NULL terminated pointer
2478      * at the end
2479      */
2480     pbeg = pcur = string;
2481     for (i = 0; i < MAX_ARGV-2; i ++)
2482     {
2483 	int	dq = 0;	/* double quote */
2484 	int	sq = 0;	/* single quote */
2485 	/* set default argument to NULL */
2486 	SET_NULL(pret[i]);
2487 
2488 	/* skip any spaces and non-printable */
2489 	while (*pcur &&
2490 	    (isspace ((int) *pcur) || !isprint ((int) *pcur)))
2491 	    pcur ++;
2492 	/* stop if reach end of string */
2493 	if (!*pcur)
2494 	    break;
2495 
2496 	/* beginning of the token */
2497 	if (isalnum ((int) *pcur) || ispunct ((int) *pcur))
2498 	{
2499 	    if ('\"' == *pcur)
2500 	    {
2501 		/* beginning of double quote */
2502 		dq = 1;	pbeg = pcur + 1; pcur ++;
2503 	    }
2504 	    else if ('\'' == *pcur)
2505 	    {
2506 		/* beginning of single quote */
2507 		sq = 1;	pbeg = pcur + 1; pcur ++;
2508 	    }
2509 	    else /* normal characters */
2510 		pbeg = pcur;
2511 	}
2512 #ifdef DEBUG
2513 	else	/* shouldn't happen */
2514 	    assert (0);
2515 #endif
2516 
2517 	/* move forward one character */
2518 	pcur ++;
2519 
2520 	/* now fetch the new token */
2521 	while(
2522 		*pcur &&			/* not end of string */
2523 		(
2524 		  (dq && *pcur != '\"') ||	/* not end of double quote */
2525 		  (sq && *pcur != '\'') ||	/* not end of single quote */
2526 		  (!dq && !sq && !isspace ((int) *pcur))
2527 		)
2528 	     )
2529 	{
2530 	    pcur ++;
2531 	}
2532 
2533 	if (!*pcur &&	/* end of string */
2534 	    (dq || sq))	/* no match of quote is found */
2535 	    goto NotMatch;
2536 
2537 	if (!*pcur)	/* end of string */
2538 	{
2539 	    pret[i] = STRDUP (pbeg);
2540 	    rxvt_dbgmsg ((DBG_DEBUG, DBG_INIT, "   argv[%d] = %s\n", i, pret[i]));
2541 	    break;	/* ready to return */
2542 	}
2543 
2544 	if (
2545 	      (dq && *pcur == '\"')		    /* end of double quote */
2546 	      || (sq && *pcur == '\'')		    /* end of single quote */
2547 	      || (!dq && !sq && isspace ((int) *pcur))	    /* space */
2548 	   )
2549 	{
2550 	    int	    len = sizeof (char) * (pcur - pbeg) + 1;
2551 
2552 	    assert (len > 0);	/* possible integer overflow? */
2553 	    pret[i] = (char*) rxvt_malloc (len * sizeof(char));
2554 	    MEMCPY (pret[i], pbeg, len-1);
2555 	    pret[i][len-1] = (char) 0;
2556 	    rxvt_dbgmsg ((DBG_DEBUG, DBG_INIT, "   argv[%d] = %s\n", i, pret[i]));
2557 
2558 	    /* forward to next character */
2559 	    pcur ++;
2560 
2561 	    /* fetch next token */
2562 	    continue;
2563 	}
2564 
2565 	/* shouldn't get here */
2566 	assert (0);
2567     }
2568     /*}}}*/
2569 #else /* !INTERNAL_ARGV_SPLIT */
2570 
2571     /*
2572      * Pass strings beginning with "!" but not "!!" to /bin/sh -c
2573      */
2574     if( *string == '!' && *(++string) != '!' )
2575     {
2576 	/* Pass command to the shell for word splitting */
2577 	pret[i++] = STRDUP( "/bin/sh" );
2578 	pret[i++] = STRDUP( "-c" );
2579 	pret[i++] = STRDUP( string );
2580     }
2581 
2582     else
2583     {
2584 	/*
2585 	 * Split command into words at spaces. White spaces can be quoted with
2586 	 * a backslash. However we don't processes chains of "\\" which don't
2587 	 * end in a space or tab. That is "\\a" expands to "\\a" however "\\ "
2588 	 * expands to "\ ", and "\ " expands to a " " which does not split
2589 	 * words.
2590 	 */
2591 	pcur = string;
2592 	for( ; i < MAX_ARGV && *pcur; i++ )
2593 	{
2594 	    const int	max_argv_len = 1024;
2595 	    char	argval[max_argv_len];
2596 	    int		j = 0;
2597 
2598 	    /* Skip leading spaces */
2599 	    while( *pcur == ' ' || *pcur == '\t' ) pcur++;
2600 
2601 	    while(
2602 		    *pcur && *pcur != ' ' && *pcur != '\t' &&
2603 		    j < max_argv_len - 1
2604 		 )
2605 	    {
2606 		if( *pcur == '\\' )
2607 		{
2608 		    const char *s = pcur + 1;
2609 
2610 		    /* Count backslashes */
2611 		    while( *s == '\\' )
2612 			s++;
2613 
2614 		    if( *s == ' ' || *s == '\t' )
2615 		    {
2616 			int nbslashs = s - pcur;
2617 			int nbytes = min( nbslashs / 2, max_argv_len - j - 1);
2618 
2619 			/* Halve # backslashes */
2620 			MEMSET( &argval[j], '\\', nbytes );
2621 			pcur	=  s;
2622 			j	+= nbytes;
2623 
2624 			if( nbslashs % 2 == 0 )
2625 			    break;  /* Split word here */
2626 		    }
2627 
2628 		    else
2629 		    {
2630 			/* Copy backslashes over verbatim */
2631 			int nbytes = min( s - pcur, max_argv_len -j -1 );
2632 
2633 			MEMCPY( &argval[j], pcur, nbytes );
2634 			j	+= nbytes;
2635 			pcur	=  s;
2636 		    }
2637 		} /* if( pcur = '\\' ) */
2638 
2639 		argval[j++] = *pcur++;
2640 	    } /* while( *pcur ... ) */
2641 
2642 	    if( j )
2643 	    {
2644 		argval[j] = '\0';
2645 		pret[i] = STRDUP( argval );
2646 	    }
2647 	    else
2648 		break;
2649 	}
2650     } /* else [ if( *string != '!' ) ] */
2651 #endif /* !INTERNAL_ARGV_SPLIT */
2652 
2653 #undef MAX_ARGV
2654     /* set the end of argv */
2655     if (pret[i])
2656     {
2657 	*argc = i+1;
2658 	SET_NULL(pret[i+1]);
2659     }
2660     else if (i)	    /* non-empty argv */
2661     {
2662 	*argc = i;
2663     }
2664     else	    /* empty argv */
2665     {
2666 #if 0
2667 	/* 2006-02-23 gi1242: Also need to free the char* pointers in pret? */
2668 	rxvt_free (pret);
2669 	return NULL;
2670 #endif
2671 	goto NotMatch;
2672     }
2673 
2674     /* 2006-02-23  gi1242: Can now reduce the size of pret. */
2675     pret = (char **) rxvt_realloc( pret, (*argc + 1) * sizeof(char*) );
2676     return pret;
2677 
2678 NotMatch:
2679     *argc = 0;
2680     {
2681 	char **s;
2682 	for( s = pret; NOT_NULL(*s); s++) rxvt_free(*s);
2683     }
2684 
2685     rxvt_free (pret);
2686     return NULL;
2687 }
2688 
2689 
2690 /*
2691  * Sets up the fg/bg correctly in pixColorsFocus/unfocus, the fg/bg of
2692  * TermWin.gc, and the fg/bg of the window (if active).
2693  */
2694 /* EXTPROTO */
2695 int
rxvt_set_vt_colors(rxvt_t * r,int page)2696 rxvt_set_vt_colors( rxvt_t *r, int page )
2697 {
2698     int		    changed = 0;
2699     int		    useFocusColors;
2700     unsigned long   *pix_colors;
2701 
2702     rxvt_dbgmsg(( DBG_DEBUG, DBG_INIT, "%s(r, page=%d). ", __func__, page ));
2703 
2704     useFocusColors = ( r->TermWin.focus || !r->TermWin.fade );
2705     pix_colors = (useFocusColors ? r->pixColorsFocus : r->pixColorsUnfocus);
2706     if( r->pixColors != pix_colors )
2707     {
2708 	changed		= 1;
2709 	r->pixColors	= pix_colors;
2710     }
2711 
2712 #ifdef XFT_SUPPORT
2713     if( ISSET_OPTION( r, Opt_xft ) )
2714 	r->xftColors = useFocusColors ? r->xftColorsFocus : r->xftColorsUnfocus;
2715 #endif
2716 
2717     if( rxvt_set_fgbg_colors( r, page ) )
2718 	changed = 1;
2719 
2720     if( changed )
2721     {
2722 	/*
2723 	 * Set foreground/background color for GC. This is necessary. Since all
2724 	 * VTs share the same GC, if we do not set the color here, color from
2725 	 * other VTs will be used to draw the following text till there is a
2726 	 * color change.
2727 	 */
2728 	XSetForeground( r->Xdisplay, r->TermWin.gc, r->pixColors[Color_fg] );
2729 	XSetBackground( r->Xdisplay, r->TermWin.gc, r->pixColors[Color_bg] );
2730 
2731 	if( IS_WIN( PVTS(r, page)->vt ) )
2732 # ifdef TRANSPARENT
2733 	    if (NOTSET_OPTION(r, Opt_transparent))
2734 # endif	/* TRANSPARENT */
2735 #ifdef BACKGROUND_IMAGE
2736 		if (NOT_PIXMAP(PVTS(r, page)->pixmap))
2737 #endif	/* BACKGROUND_IMAGE */
2738 		    XSetWindowBackground(r->Xdisplay, PVTS(r, page)->vt,
2739 			r->pixColors[Color_bg]);
2740     }
2741 
2742     rxvt_dbgmsg(( DBG_DEBUG, DBG_INIT, "Returning %d\n", changed ));
2743     return changed;
2744 }
2745 
2746 
2747 /* INTPROTO */
2748 termenv_t
rxvt_get_termenv(const char * env)2749 rxvt_get_termenv( const char *env )
2750 {
2751     if (IS_NULL(env))
2752 	return (TERMENV_XTERM);
2753     else if (0 == STRCASECMP (env, "xterm"))
2754 	return (TERMENV_XTERM);
2755     else if (0 == STRCASECMP (env, "rxvt"))
2756 	return (TERMENV_RXVT);
2757     else if (0 == STRCASECMP (env, "vt102"))
2758 	return (TERMENV_VT102);
2759     else if (0 == STRCASECMP (env, "vt100"))
2760 	return (TERMENV_VT100);
2761     else if (0 == STRCASECMP (env, "ansi"))
2762 	return (TERMENV_ANSI);
2763     else if (0 == STRCASECMP (env, "dumb"))
2764 	return (TERMENV_DUMB);
2765     else
2766 	return (TERMENV_XTERM);
2767 }
2768 
2769 
2770 /* INTPROTO */
2771 void
rxvt_init_vts(rxvt_t * r,int page,int profile)2772 rxvt_init_vts( rxvt_t *r, int page, int profile )
2773 {
2774 #ifdef TTY_GID_SUPPORT
2775     struct group*   gr = getgrnam( "tty" );
2776 #endif
2777     register int    i;
2778 
2779 
2780     assert( page < MAX_PAGES );
2781 
2782     /* look for an unused term_t structure */
2783     for( i = 0; i < MAX_PAGES; i ++ )
2784 	if( -1 == r->vterm[i].vts_idx )
2785 	    break;
2786     assert( i != MAX_PAGES );
2787     rxvt_dbgmsg ((DBG_DEBUG, DBG_INIT, "Find vterm[%d] for pointer vts[%d]\n", i, page));
2788 
2789     /* clear the term_t structure */
2790     r->vts[page] = &(r->vterm[i]);
2791     MEMSET( r->vts[page], 0, sizeof( r->vterm[0] ) );
2792 
2793     /* set vts_idx for the vterm */
2794     PVTS(r, page)->vts_idx = i;
2795 
2796     /* Set the profile number */
2797     PVTS(r, page)->profileNum	= profile;
2798 
2799     /* Save the "static" number of this tab */
2800     PVTS(r, page)->globalTabNum	= r->ntabs++;
2801 
2802 #ifdef TTY_GID_SUPPORT
2803     /* change group ownership of tty to "tty" */
2804     if (gr)
2805     {
2806 	PVTS(r, page)->ttymode = S_IRUSR | S_IWUSR | S_IWGRP;
2807     }
2808     else
2809 #endif	    /* TTY_GID_SUPPORT */
2810     {
2811 	PVTS(r, page)->ttymode = S_IRUSR | S_IWUSR | S_IWGRP | S_IWOTH;
2812     }
2813 
2814     /* Initialize term_t (vts) structure */
2815     PVTS( r, page )->saveLines = r->profile[profile].saveLines;
2816 
2817     /* will be set in rxvt_create_termwin */
2818     UNSET_WIN(PVTS(r, page)->vt);
2819 
2820 #ifdef XFT_SUPPORT
2821     SET_NULL(PVTS(r, page)->xftvt);
2822 #endif
2823     SET_NULL(PVTS(r, page)->tab_title);
2824 
2825     /*
2826      * Set the tab title format, and window title format. getProfileOption
2827      * returns a static string, so duplicate it here
2828      */
2829     {
2830 	const char *stf = getProfileOption( r, profile, Rs_titleFormat );
2831 	PVTS(r, page)->title_format = NOT_NULL(stf) ? STRDUP(stf) : NULL;
2832     }
2833 
2834     {
2835 	const char *wtf = getProfileOption( r, profile, Rs_winTitleFormat );
2836 	PVTS(r, page)->winTitleFormat = NOT_NULL(wtf) ? STRDUP(wtf) : NULL;
2837     }
2838 
2839 #ifdef BACKGROUND_IMAGE
2840     UNSET_PIXMAP(PVTS(r, page)->pixmap);
2841     UNSET_PIXMAP(PVTS(r, page)->bg.pixmap);
2842     PVTS(r, page)->bg.x = PVTS(r, page)->bg.y = 50;
2843 #endif
2844     PVTS(r, page)->cmd_pid = -1;
2845     PVTS(r, page)->cmd_fd = PVTS(r, page)->tty_fd = -1;
2846 #ifdef UTMP_SUPPORT
2847     PVTS(r, page)->next_utmp_action = SAVE;
2848 #endif
2849 #ifndef NO_SETOWNER_TTYDEV
2850     PVTS(r, page)->next_tty_action = SAVE;
2851 #endif
2852 
2853     PVTS(r, page)->holdOption = r->profile[profile].holdOption;
2854 
2855     PVTS(r, page)->status = 0;
2856     PVTS(r, page)->hold = 0;	    /* clear hold flag */
2857     PVTS(r, page)->dead = 0;	    /* clear dead flag */
2858     PVTS(r, page)->highlight = 0;   /* clear highlight flag */
2859 
2860     /* Get term_env type */
2861     PVTS(r, page)->termenv = rxvt_get_termenv (
2862 	r->h->rs[Rs_term_name] ? r->h->rs[Rs_term_name] : TERMENV);
2863 
2864     /* Initialize PrivateModes and SavedModes */
2865     PVTS(r, page)->PrivateModes = PVTS(r, page)->SavedModes =
2866 	PrivMode_Default;
2867     if (ISSET_OPTION(r, Opt_scrollTtyOutputInhibit))
2868 	SET_PMODE(r, page, PrivMode_TtyOutputInh);
2869     if (ISSET_OPTION(r, Opt_scrollTtyKeypress))
2870 	SET_PMODE(r, page, PrivMode_Keypress);
2871     if( r->h->skip_pages > 1 /* jump scroll is unset */ )
2872 	SET_PMODE(r, page, PrivMode_smoothScroll);
2873 #ifndef NO_BACKSPACE_KEY
2874     if (STRCMP(r->h->key_backspace, "DEC") == 0)
2875 	SET_PMODE(r, page, PrivMode_HaveBackSpace);
2876 #endif
2877 #ifdef HAVE_SCROLLBARS
2878     if (rxvt_scrollbar_visible(r))
2879     {
2880 	SET_PMODE(r, page, PrivMode_scrollBar);
2881 	SET_SMODE(r, page, PrivMode_scrollBar);
2882     }
2883 #endif
2884 #ifdef HAVE_MENUBAR
2885     if (rxvt_menubar_visible(r))
2886     {
2887 	SET_PMODE(r, page, PrivMode_menuBar);
2888 	SET_SMODE(r, page, PrivMode_menuBar);
2889     }
2890 #endif
2891 
2892     /* Now set VT fg/bg color */
2893     PVTS(r, page)->p_fg = VTFG(r, profile);
2894     PVTS(r, page)->p_bg = VTBG(r, profile);
2895 
2896     if( r->TermWin.fade )
2897     {
2898 	PVTS(r, page)->p_fgfade = VTFG_FADE(r, profile);
2899 	PVTS(r, page)->p_bgfade = VTBG_FADE(r, profile);
2900     }
2901 
2902 #ifdef XFT_SUPPORT
2903     if( ISSET_OPTION( r, Opt_xft ) )
2904     {
2905 	PVTS(r, page)->p_xftfg = VTXFTFG(r, profile);
2906 	PVTS(r, page)->p_xftbg = VTXFTBG(r, profile);
2907 
2908 	if( r->TermWin.fade )
2909 	{
2910 	    PVTS(r, page)->p_xftfgfade = VTXFTFG_FADE(r, profile);
2911 	    PVTS(r, page)->p_xftbgfade = VTXFTBG_FADE(r, profile);
2912 	}
2913     }
2914 #endif
2915 
2916     /* Initialize input buffer */
2917     PVTS(r, page)->cmdbuf_ptr	= PVTS(r, page)->cmdbuf_endp
2918 				= PVTS(r, page)->cmdbuf_base;
2919 
2920     /* Initialize write out buffer */
2921     SET_NULL(PVTS(r, page)->v_buffer);
2922     SET_NULL(PVTS(r, page)->v_bufstr);
2923     SET_NULL(PVTS(r, page)->v_bufptr);
2924     SET_NULL(PVTS(r, page)->v_bufend);
2925 
2926     /* Set screen structure initialization flag */
2927     PVTS(r, page)->init_screen = 0;
2928 
2929     /* Request a refresh */
2930     PVTS(r, page)->want_refresh = 1;
2931 }
2932 
2933 
2934 /*----------------------------------------------------------------------*/
2935 /* rxvt_destroy_termwin() - destroy a terminal window */
2936 /* EXTPROTO */
2937 void
rxvt_destroy_termwin(rxvt_t * r,int page)2938 rxvt_destroy_termwin( rxvt_t *r, int page )
2939 {
2940     assert (page < MAX_PAGES);
2941     assert (PVTS(r, page)->tab_title);
2942 
2943     rxvt_free (PVTS(r, page)->tab_title);
2944     SET_NULL(PVTS(r, page)->tab_title);
2945 
2946     rxvt_free( PVTS(r, page)->title_format );
2947     SET_NULL( PVTS(r, page)->title_format );
2948 
2949 #ifdef XFT_SUPPORT
2950     if (ISSET_OPTION(r, Opt_xft))
2951     {
2952 	if (PVTS(r, page)->xftvt)
2953 	    XftDrawDestroy (PVTS(r, page)->xftvt);
2954 	SET_NULL(PVTS(r, page)->xftvt);
2955     }
2956 #endif
2957     assert (IS_WIN(PVTS(r, page)->vt));
2958     XDestroyWindow (r->Xdisplay, PVTS(r, page)->vt);
2959     UNSET_WIN(PVTS(r, page)->vt);
2960 
2961 #ifdef BACKGROUND_IMAGE
2962     if (IS_PIXMAP(PVTS(r, page)->pixmap))
2963     {
2964 	XFreePixmap (r->Xdisplay, PVTS(r, page)->pixmap);
2965 	UNSET_PIXMAP(PVTS(r, page)->pixmap);
2966     }
2967     if (IS_PIXMAP(PVTS(r, page)->bg.pixmap))
2968     {
2969 	XFreePixmap (r->Xdisplay, PVTS(r, page)->bg.pixmap);
2970 	UNSET_PIXMAP(PVTS(r, page)->bg.pixmap);
2971     }
2972 #endif
2973 
2974     /* Set vterm index to -1, so that we know it's unused */
2975     PVTS(r, page)->vts_idx = -1;
2976 }
2977 
2978 
2979 
2980 /* rxvt_create_termwin() - create a terminal window */
2981 /* EXTPROTO */
2982 void
rxvt_create_termwin(rxvt_t * r,int page,int profile,const char TAINTED * title)2983 rxvt_create_termwin( rxvt_t *r, int page, int profile,
2984 	const char TAINTED *title )
2985 {
2986     long	    vt_emask;
2987 
2988 
2989     assert( page < MAX_PAGES );
2990 
2991     rxvt_init_vts( r, page, profile );
2992 
2993     /*
2994      * Set the tab title
2995      */
2996     if (IS_NULL(title))
2997 	title = DEFAULT_TAB_TITLE;
2998     PVTS(r, page)->tab_title = (char UNTAINTED *) STRNDUP( title, MAX_TAB_TXT );
2999 
3000 #ifdef HAVE_PUTENV
3001     /* Set environment variable of tab title */
3002     sprintf (r->h->env_tabtitle, TABTITLEENV "%s", PVTS(r, page)->tab_title);
3003     putenv (r->h->env_tabtitle);
3004 #endif
3005 
3006     PVTS(r, page)->tab_width = rxvt_tab_width (r, PVTS(r, page)->tab_title);
3007 
3008     /*
3009      * Now switch fg/bg colors before creating VT because this will use the
3010      * fg/bg colors
3011      */
3012     rxvt_set_vt_colors( r, page );
3013 
3014     /* create the terminal window */
3015     rxvt_dbgmsg ((DBG_DEBUG, DBG_INIT, "Create VT %d (%dx%d+%dx%d) fg=%06lx, bg=%06lx\n", page, r->h->window_vt_x, r->h->window_vt_y, VT_WIDTH(r), VT_HEIGHT(r), r->pixColors[Color_fg], r->pixColors[Color_bg]));
3016 
3017     PVTS(r, page)->vt = XCreateSimpleWindow (r->Xdisplay, r->TermWin.parent,
3018 				r->h->window_vt_x, r->h->window_vt_y,
3019 				VT_WIDTH(r), VT_HEIGHT(r),
3020 				0,
3021 				r->pixColors[Color_fg],
3022 				r->pixColors[Color_bg]);
3023     assert (IS_WIN(PVTS(r, page)->vt));
3024 #ifdef XFT_SUPPORT
3025     if (ISSET_OPTION(r, Opt_xft))
3026     {
3027 	PVTS(r, page)->xftvt = XftDrawCreate (r->Xdisplay,
3028 	    PVTS(r, page)->vt, XVISUAL, XCMAP);
3029 	assert (NOT_NULL(PVTS(r, page)->xftvt));
3030     }
3031 #endif
3032 
3033 
3034     /* define cursor for the terminal window */
3035     rxvt_pointer_unblank(r, page);
3036 
3037     /* define event mask fo the terminal window */
3038     vt_emask = (ExposureMask | ButtonPressMask | ButtonReleaseMask
3039 	| PropertyChangeMask);
3040 #ifdef POINTER_BLANK
3041     if (ISSET_OPTION(r, Opt_pointerBlank))
3042 	vt_emask |= PointerMotionMask;
3043     else
3044 #endif
3045 	vt_emask |= (Button1MotionMask | Button3MotionMask);
3046     XSelectInput(r->Xdisplay, PVTS(r, page)->vt, vt_emask);
3047 
3048 #ifdef TRANSPARENT
3049     /* Set transparent background */
3050     if (ISSET_OPTION(r, Opt_transparent))
3051     {
3052 	XSetWindowBackgroundPixmap (r->Xdisplay, PVTS(r, page)->vt,
3053 	    ParentRelative);
3054     }
3055 #endif
3056 
3057     /*
3058      * Load the background image for terminal window when not transparent
3059      */
3060 #ifdef BACKGROUND_IMAGE
3061 # ifdef TRANSPARENT
3062     if( NOTSET_OPTION(r,  Opt_transparent) )
3063 # endif
3064     {
3065 	const char *pf = getProfileOption( r, profile, Rs_backgroundPixmap );
3066 	if (NOT_NULL(pf))
3067 	{
3068 	    /* Load pixmap for each individual tab */
3069 	    const char *p = pf;
3070 
3071 	    if (NOT_NULL(p = STRCHR(p, ';')))
3072 	    {
3073 		p++;
3074 		rxvt_scale_pixmap(r, page, p);
3075 	    }
3076 	    rxvt_load_bg_pixmap(r, page, pf);
3077 	    /* rxvt_scr_touch(r, page, True); */
3078 	}
3079     } /* if( NOTSET_OPTION(r,  Opt_transparent) ) */
3080 #endif
3081 
3082     XMapWindow (r->Xdisplay, PVTS(r, page)->vt);
3083 }
3084 
3085 
3086 /*
3087  * Return the value of an option with profile number "profile". This function
3088  * should only be called for profile options.
3089  *
3090  * The string returned is one of r->h->rs[], so should not be freed.
3091  */
3092 /* EXTPROTO */
3093 const char *
getProfileOption(rxvt_t * r,int profile,int resource)3094 getProfileOption( rxvt_t *r, int profile, int resource )
3095 {
3096     assert( profile >= 0 || profile < MAX_PROFILES );
3097 
3098     /*
3099      * Profile 0 is default, so if the profile option is unset, fall back to
3100      * profile 0.
3101      */
3102     return NOT_NULL(r->h->rs[resource + profile]) ?
3103 	r->h->rs[resource + profile] : r->h->rs[resource];
3104 }
3105 
3106 /* INTPROTO */
3107 void
rxvt_set_borderless(rxvt_t * r)3108 rxvt_set_borderless( rxvt_t *r )
3109 {
3110     Atom	prop;
3111     CARD32	hints;	    /* KDE/GNOME hints */
3112     MWMHints	mwmhints;   /* Motif hints */
3113 
3114     hints = (CARD32) 0;
3115     mwmhints.flags = MWM_HINTS_DECORATIONS;
3116     mwmhints.decorations = 0;
3117 
3118     /* Motif compatible WM */
3119     prop = XInternAtom (r->Xdisplay, "_MOTIF_WM_HINTS", True);
3120     if (IS_ATOM(prop))
3121 	XChangeProperty (r->Xdisplay, r->TermWin.parent, prop, prop,
3122 	    32, PropModeReplace, (unsigned char*) &mwmhints,
3123 	    PROP_MWM_HINTS_ELEMENTS);
3124 
3125     /* GNOME compatible WM */
3126     prop = XInternAtom (r->Xdisplay, "_WIN_HINTS", True);
3127     if (IS_ATOM(prop))
3128 	XChangeProperty (r->Xdisplay, r->TermWin.parent, prop, prop,
3129 	    32, PropModeReplace, (unsigned char*) &hints, 1);
3130 
3131     /* KDE compatible WM */
3132     prop = XInternAtom (r->Xdisplay, "KWM_WIN_DECORATION", True);
3133     if (IS_ATOM(prop))
3134 	XChangeProperty (r->Xdisplay, r->TermWin.parent, prop, prop,
3135 	    32, PropModeReplace, (unsigned char*) &hints, 1);
3136 }
3137 
3138 /*
3139  * Send a message to an EWMH compatible window manager.
3140  */
3141 /* EXTPROTO */
3142 Status
ewmh_message(Display * dpy,Window root_win,Window client_win,Atom msgAtom,long d0,long d1,long d2,long d3,long d4)3143 ewmh_message( Display *dpy, Window root_win, Window client_win,
3144 	Atom msgAtom, long d0, long d1, long d2, long d3, long d4)
3145 {
3146 
3147     XEvent event;
3148 
3149     if (NOT_ATOM(msgAtom))
3150 	return 1;
3151 
3152     event.xclient.type = ClientMessage;
3153     event.xclient.serial = 0;
3154     event.xclient.send_event = True;
3155     event.xclient.message_type = msgAtom;
3156     event.xclient.window = client_win;
3157     event.xclient.format = 32;
3158 
3159     event.xclient.data.l[0] = d0;
3160     event.xclient.data.l[1] = d1;
3161     event.xclient.data.l[2] = d2;
3162     event.xclient.data.l[3] = d3;
3163     event.xclient.data.l[4] = d4;
3164 
3165     return XSendEvent( dpy, root_win, False,
3166 	    SubstructureRedirectMask | SubstructureNotifyMask,
3167 	    &event);
3168 }
3169 
3170 
3171 /* INTPROTO */
3172 void
rxvt_set_desktop(rxvt_t * r,CARD32 desktop)3173 rxvt_set_desktop( rxvt_t* r, CARD32 desktop )
3174 {
3175     /* GNOME compatible WM */
3176     if (desktop >= 0 && desktop <= 64 &&
3177 	IS_ATOM(r->h->xa[XA_WIN_WORKSPACE]))
3178 	XChangeProperty(r->Xdisplay, r->TermWin.parent,
3179 	    r->h->xa[XA_WIN_WORKSPACE], XA_CARDINAL, 32,
3180 	    PropModeReplace, (unsigned char*) &desktop, 1L);
3181 
3182     /* WindowMaker/FreeDesktop.org compatible WM */
3183     if (desktop >= 0 && desktop <= 64 &&
3184 	IS_ATOM(r->h->xa[XA_NET_WM_DESKTOP]))
3185 	XChangeProperty(r->Xdisplay, r->TermWin.parent,
3186 	    r->h->xa[XA_NET_WM_DESKTOP], XA_CARDINAL, 32,
3187 	    PropModeReplace, (unsigned char*) &desktop, 1L);
3188 }
3189 
3190 
3191 /* EXTPROTO */
3192 CARD32
rxvt_get_desktop(rxvt_t * r)3193 rxvt_get_desktop( rxvt_t* r )
3194 {
3195     Atom    ret_type;
3196     int	    format;
3197     unsigned long   nitems;
3198     unsigned long   bytes_after;
3199     unsigned char   *prop;
3200     CARD32  desktop;
3201 
3202     if (NOT_ATOM(r->h->xa[XA_NET_WM_DESKTOP]))
3203 	return 0;
3204 
3205     if(
3206 	  XGetWindowProperty( r->Xdisplay, r->TermWin.parent,
3207 	      r->h->xa[XA_NET_WM_DESKTOP], 0L, LONG_MAX, False, XA_CARDINAL,
3208 	      &ret_type, &format, &nitems, &bytes_after, &prop)
3209 	    != Success
3210       )
3211 	return 0;
3212 
3213     if( ret_type == XA_CARDINAL && format == 32 )
3214     {
3215 	desktop = ((CARD32*) prop)[0];
3216 	if (desktop < 0 || desktop > 64)
3217 	    desktop = 0;
3218     }
3219     else
3220 	desktop = 0;
3221 
3222     XFree( prop);
3223 
3224     rxvt_dbgmsg(( DBG_DEBUG, DBG_INIT, "Desktop: %lu\n", desktop ));
3225     return desktop;
3226 }
3227 
3228 
3229 /*----------------------------------------------------------------------*/
3230 /* rxvt_create_show_windows() - Open and map the window */
3231 /* EXTPROTO */
3232 void
rxvt_create_show_windows(rxvt_t * r,int argc,const char * const * argv)3233 rxvt_create_show_windows( rxvt_t *r, int argc, const char *const *argv )
3234 {
3235     XClassHint		    class_hint;
3236     XWMHints		    wm_hint;
3237     XTextProperty	    win_prop;
3238     XTextProperty	    icon_prop;
3239     XGCValues		    gcvalue;
3240     unsigned long	    gcmask;
3241 #ifndef NO_FRILLS
3242     CARD32		    pid = (CARD32) getpid ();
3243 #endif
3244 #ifdef TRANSPARENT
3245     register int	    i;
3246 #endif
3247 #ifdef POINTER_BLANK
3248     static const XColor	    blackcolour = { 0, 0, 0, 0, 0, 0 };
3249 #endif
3250 
3251     Window		    parent;	/* WinID to use for parent window */
3252 
3253 #ifdef PREFER_24BIT
3254     XSetWindowAttributes    attributes;
3255     XWindowAttributes	    gattr;
3256 
3257 
3258     XCMAP = DefaultColormap(r->Xdisplay, XSCREEN);
3259     XVISUAL = DefaultVisual(r->Xdisplay, XSCREEN);
3260 
3261     if (ISSET_OPTION(r, Opt_transparent))
3262     {
3263 	XGetWindowAttributes(r->Xdisplay,
3264 	    RootWindow(r->Xdisplay, XSCREEN), &gattr);
3265 	XDEPTH = gattr.depth;
3266     }
3267     else
3268     {
3269 	XDEPTH = DefaultDepth(r->Xdisplay, XSCREEN);
3270 	/*
3271 	 * If depth is not 24, look for a 24bit visual.
3272 	 */
3273 	if (XDEPTH != 24)
3274 	{
3275 	    XVisualInfo	 vinfo;
3276 
3277 	    if (XMatchVisualInfo(r->Xdisplay, XSCREEN, 24, TrueColor, &vinfo))
3278 	    {
3279 		XDEPTH = 24;
3280 		XVISUAL = vinfo.visual;
3281 		XCMAP = XCreateColormap(r->Xdisplay,
3282 			    RootWindow(r->Xdisplay, XSCREEN),
3283 			    XVISUAL, AllocNone);
3284 	    }
3285 	}
3286     }
3287 #endif
3288 
3289 
3290     /* grab colors before netscape does */
3291     rxvt_init_colors (r);
3292 
3293     /*
3294      * Initialize fonts.
3295      * . Always load X11 fonts since pointer_blank uses it
3296      * . Load XFT font after X11 fonts. If succeeds, XFT font will
3297      * update font width/height and be used by default
3298      *
3299      * 03/09/2006 gi1242: TODO Don't load the X11 font unless absolutely
3300      * necessary. It will speed up startup (minimaly), and reduce resource
3301      * usage (minimaly).
3302      */
3303 #ifdef XFT_SUPPORT
3304     if (ISSET_OPTION(r, Opt_xft))
3305     {
3306 	if (!rxvt_init_font_xft (r))
3307 	{
3308 	    rxvt_msg (DBG_INFO, DBG_INIT,
3309 		    "Failed to load FreeType font, fallback to X11 font\n");
3310 	    /* disable xft */
3311 	    UNSET_OPTION(r, Opt_xft);
3312 	}
3313 	else
3314 	    xftInitACS (r->Xdisplay, XROOT, XDEPTH);
3315     }
3316 #endif
3317     /* init fallback X11 font */
3318     rxvt_init_font_x11( r );
3319 
3320 
3321     /*
3322      * must initialize scrollbar before initialize window size and
3323      * create windows.
3324      */
3325 #ifdef HAVE_SCROLLBARS
3326     rxvt_scrollbar_init (r);
3327 #endif
3328     rxvt_init_win_size (r);
3329 
3330     /*
3331      * Use window specified by -into option as the parent window.
3332      */
3333     if( r->h->rs[Rs_container_window] )
3334     {
3335 	XWindowAttributes   attrs;
3336 
3337 	r->h->allowedxerror = 1;    /* Enable Xerror reporting */
3338 	r->h->xerror_return = Success;
3339 
3340         parent = strtoul( r->h->rs[Rs_container_window], NULL, 0 );
3341 
3342 	XGetWindowAttributes( r->Xdisplay, parent, &attrs );
3343 
3344 	/* Check if we have valid attributes */
3345 	if( r->h->xerror_return != Success || attrs.class == InputOnly )
3346 	{
3347 	    rxvt_msg (DBG_ERROR, DBG_INIT,  "Unable to embed into Win 0x%lx", parent );
3348 	    parent = XROOT;
3349 	}
3350 
3351 	r->h->allowedxerror = 0;    /* Disable Xerror reporting */
3352     }
3353     else
3354         parent = XROOT;
3355 
3356     /*
3357      * parent window - reverse video so we can see placement errors sub-window
3358      * placement & size in rxvt_resize_subwindows()
3359      */
3360 
3361 #ifdef PREFER_24BIT
3362     attributes.background_pixel = r->pixColorsFocus[Color_bg];
3363     attributes.border_pixel = r->pixColorsFocus[Color_border];
3364     attributes.colormap = XCMAP;
3365     r->TermWin.parent = XCreateWindow(r->Xdisplay, parent,
3366 		    r->szHint.x, r->szHint.y,
3367 		    r->szHint.width, r->szHint.height,
3368 		    r->TermWin.ext_bwidth,
3369 		    XDEPTH, InputOutput,
3370 		    XVISUAL,
3371 		    CWBackPixel | CWBorderPixel
3372 		    | CWColormap, &attributes);
3373 #else
3374     r->TermWin.parent = XCreateSimpleWindow(r->Xdisplay, parent,
3375 			r->szHint.x, r->szHint.y,
3376 			r->szHint.width,
3377 			r->szHint.height,
3378 			r->TermWin.ext_bwidth,
3379 			r->pixColorsFocus[Color_border],
3380 			r->pixColorsFocus[Color_bg]);
3381 #endif
3382 
3383 #ifdef XFT_SUPPORT
3384     if (ISSET_OPTION(r, Opt_xft))
3385     {
3386 	/* create XFT draw, test only */
3387 	XftDraw*	xftdraw = XftDrawCreate( r->Xdisplay,
3388 						 r->TermWin.parent, XVISUAL,
3389 						 XCMAP);
3390 	if (xftdraw)
3391 	{
3392 	    XftDrawDestroy (xftdraw);
3393 	    /* some cleanup work if successfully create xft window */
3394 # ifdef POINTER_BLANK
3395 	    /*
3396 	     * 2006-01-21 gi1242: I'm not sure why pointer blank is disabled
3397 	     * with xft. It works fine for me, so I re-enabled it.
3398 	     */
3399 #  if 0
3400 	    /* disable pointer blank */
3401 	    UNSET_OPTION(r, Opt_pointerBlank);
3402 #  endif
3403 # endif
3404 	}
3405     }
3406 #endif
3407 
3408 
3409 # ifdef HAVE_X11_SM_SMLIB_H
3410     if (ISSET_OPTION(r, Opt2_enableSessionMgt))
3411 	rxvt_session_init (r);
3412 # endif
3413 
3414 
3415     /*
3416      * Now set window properties, like title, icon name and hints
3417      */
3418     /* window title name */
3419     win_prop.value = (unsigned char*) r->h->rs[Rs_title];
3420     win_prop.nitems = STRLEN (win_prop.value);
3421     win_prop.encoding = XA_STRING;
3422     win_prop.format = 8;
3423     /* icon name */
3424     icon_prop.value = (unsigned char*) r->h->rs[Rs_iconName];
3425     icon_prop.nitems = STRLEN (icon_prop.value);
3426     icon_prop.encoding = XA_STRING;
3427     icon_prop.format = 8;
3428     /* window manager hints */
3429     wm_hint.flags = (InputHint | StateHint | WindowGroupHint);
3430     wm_hint.input = True;
3431     wm_hint.initial_state = ISSET_OPTION(r, Opt_iconic) ? IconicState
3432 			    : NormalState;
3433     wm_hint.window_group = r->TermWin.parent;
3434     /* window icon hint */
3435 #ifdef HAVE_LIBXPM
3436     if( r->h->rs[Rs_appIcon] )
3437     {
3438 	Pixmap appIcon, appIconMask;
3439 
3440         XpmReadFileToPixmap( r->Xdisplay, r->TermWin.parent,
3441 		(char*) r->h->rs[Rs_appIcon], &appIcon, &appIconMask, 0);
3442 
3443 	if( appIcon != None &&  appIconMask != None ) {
3444 	    wm_hint.icon_pixmap = appIcon;
3445 	    wm_hint.icon_mask = appIconMask;
3446 	    wm_hint.flags |= IconPixmapHint | IconMaskHint;
3447 	}
3448     }
3449 #endif /* HAVE_LIBXPM */
3450     /* class hints */
3451     class_hint.res_name = (char*) r->h->rs[Rs_name];
3452     class_hint.res_class = (char*) APL_CLASS;
3453     XSetWMProperties (r->Xdisplay, r->TermWin.parent,
3454 	&win_prop, &icon_prop, (char**)argv, argc,
3455 	&r->szHint, &wm_hint, &class_hint);
3456 
3457 #if 0 /* If the pixmap's are free'ed, then the WM will not display them. */
3458     if( wm_hint.flags & IconPixmapHint )
3459     {
3460 	XFreePixmap( r->Xdisplay, wm_hint.icon_pixmap );
3461 	XFreePixmap( r->Xdisplay, wm_hint.icon_mask );
3462     }
3463 #endif
3464 
3465     /* set terminal title */
3466     rxvt_set_term_title (r, win_prop.value);
3467     /* set icon title */
3468     rxvt_set_icon_name (r, icon_prop.value);
3469     /* command line */
3470     XSetCommand (r->Xdisplay, r->TermWin.parent, (char**) argv, argc);
3471 
3472     /* override redirect */
3473     if (ISSET_OPTION(r, Opt2_overrideRedirect))
3474     {
3475 	XSetWindowAttributes	attrib;
3476 	attrib.override_redirect = True;
3477 	XChangeWindowAttributes(r->Xdisplay, r->TermWin.parent,
3478 	    CWOverrideRedirect, &attrib);
3479     }
3480 
3481 #ifndef NO_FRILLS
3482     XChangeProperty (r->Xdisplay, r->TermWin.parent,
3483 	r->h->xa[XA_NET_WM_PID], XA_CARDINAL, 32,
3484 	PropModeReplace, (unsigned char*) &pid, 1);
3485 #endif
3486 
3487     if (ISSET_OPTION(r, Opt2_borderLess))
3488     {
3489 	rxvt_set_borderless (r);
3490     }
3491     if (r->h->rs[Rs_desktop])
3492     {
3493 	CARD32	desktop = (CARD32) atoi (r->h->rs[Rs_desktop]);
3494 	rxvt_set_desktop (r, desktop);
3495     }
3496 
3497     /*
3498      * set WM_CLIENT_LEADER property so that session management proxy can handle
3499      * us even session management is not enabled.
3500      */
3501     if (IS_ATOM(r->h->xa[XA_WM_CLIENT_LEADER]))
3502 	XChangeProperty( r->Xdisplay, r->TermWin.parent,
3503 	    r->h->xa[XA_WM_CLIENT_LEADER], XA_WINDOW, 32,
3504 	    PropModeReplace, (unsigned char*) &(r->TermWin.parent), 1L );
3505 
3506 # ifdef HAVE_X11_SM_SMLIB_H
3507     if (NOT_NULL(r->TermWin.sm_conn) &&
3508 	NOT_NULL(r->TermWin.sm_client_id) &&
3509 	STRCMP (r->TermWin.sm_client_id, "")
3510        )
3511     {
3512 	if (IS_ATOM(r->h->xa[XA_SM_CLIENT_ID]))
3513 	    XChangeProperty(r->Xdisplay, r->TermWin.parent,
3514 		r->h->xa[XA_SM_CLIENT_ID], XA_STRING, 8,
3515 		PropModeReplace,
3516 		(unsigned char*) r->TermWin.sm_client_id,
3517 		STRLEN(r->TermWin.sm_client_id));
3518     }
3519 # endif	/* HAVE_X11_SM_SMLIB_H */
3520 
3521 
3522 #ifdef TRANSPARENT
3523     r->TermWin.parenttree[0] = r->TermWin.parent;
3524     for (i = 1; i < PARENT_NUMBER; i ++)
3525 	UNSET_WIN(r->TermWin.parenttree[i]);
3526 
3527     /*
3528      * XXX 2006-01-02 gi1242: This is inefficient. If window is pseudo
3529      * transparent, then the background pixmap will be reset later to something
3530      * else.
3531      */
3532 #if 0
3533     if (ISSET_OPTION(r, Opt_transparent))
3534     {
3535 	XSetWindowBackgroundPixmap (r->Xdisplay, r->TermWin.parent,
3536 	    ParentRelative);
3537     }
3538 #endif
3539 #endif	/* TRANSPARENT */
3540 
3541 
3542     XSelectInput(r->Xdisplay, r->TermWin.parent,
3543 	    (KeyPressMask
3544 #if defined(MOUSE_WHEEL) && defined(MOUSE_SLIP_WHEELING)
3545 	    | KeyReleaseMask
3546 #endif
3547 	    | FocusChangeMask
3548 #ifdef MONITOR_ENTER_LEAVE
3549 	    | EnterWindowMask | LeaveWindowMask
3550 #endif
3551 	    | VisibilityChangeMask
3552 	    | StructureNotifyMask));
3553 
3554 
3555     /*
3556     ** vt cursor: Black-on-White is standard, but this is more
3557     ** popular
3558     */
3559     r->term_pointer = XCreateFontCursor(r->Xdisplay, XC_xterm);
3560     /* scrollbar/menubar/tabbar window pointer */
3561     r->h->bar_pointer = XCreateFontCursor(r->Xdisplay, XC_left_ptr);
3562 
3563 #ifdef POINTER_BLANK
3564     if (NOTSET_OPTION(r, Opt_pointerBlank))
3565 	UNSET_CURSOR(r->h->blank_pointer);
3566     else
3567 	r->h->blank_pointer = XCreateGlyphCursor(r->Xdisplay,
3568 	    r->TermWin.font->fid, r->TermWin.font->fid, ' ', ' ',
3569 	    (XColor*) &blackcolour, (XColor*) &blackcolour);
3570 #endif
3571 
3572 
3573     /* graphics context for the vt window */
3574 #ifdef XFT_SUPPORT
3575     if (NOTSET_OPTION(r, Opt_xft))
3576 #endif
3577     gcvalue.font = r->TermWin.font->fid;
3578     gcvalue.foreground = r->pixColorsFocus[Color_fg];
3579     gcvalue.background = r->pixColorsFocus[Color_bg];
3580     gcvalue.graphics_exposures = 1;
3581     gcmask = GCForeground | GCBackground | GCGraphicsExposures;
3582 #ifdef XFT_SUPPORT
3583     if (NOTSET_OPTION(r, Opt_xft))
3584 #endif
3585     gcmask |= GCFont;
3586     r->TermWin.gc = XCreateGC(r->Xdisplay, r->TermWin.parent,
3587 		    gcmask, &gcvalue);
3588 
3589 #ifdef HAVE_SCROLLBARS
3590     rxvt_scrollbar_create (r);
3591     if (ISSET_OPTION(r, Opt_scrollBar))
3592     {
3593 	rxvt_scrollbar_show (r);
3594     }
3595 #endif
3596 #ifdef HAVE_MENUBAR
3597     if (r->h->rs[Rs_menu] && STRCASECMP( r->h->rs[Rs_menu], "none"))
3598     {
3599 	/*
3600 	 * Only load menubar if arg of -menu option is not none
3601 	 */
3602 	rxvt_menubar_load_file (r, (unsigned char*) r->h->rs[Rs_menu]);
3603     }
3604     else rxvt_menubar_load_file( r, (unsigned char*) "default.menu");
3605 
3606     rxvt_menubar_create (r);
3607     if (ISSET_OPTION(r, Opt_showMenu))
3608 	rxvt_menubar_show (r);
3609 
3610     /*
3611      * 2006-05-28 gi1242: If popup menu 1 is not defined, set it to an empty
3612      * menu (so that the tab list will be popped up on control clicks and right
3613      * clicks on the tabbar).
3614      */
3615     if (IS_NULL(r->h->popupMenu[0]))
3616     {
3617 	rxvt_dbgmsg ((DBG_DEBUG, DBG_INIT, "Setting popup menu 1 to a tab list\n"));
3618 	r->h->popupMenu[0] = (menu_t *) rxvt_calloc( 1, sizeof(menu_t) );
3619 
3620 	r->h->popupMenu[0]->len	    = sizeof( "Switch to tab" );
3621 	r->h->popupMenu[0]->name    = (unsigned char*) STRDUP ("Switch to tab");
3622     }
3623 # endif
3624 
3625     rxvt_tabbar_create (r);
3626     if (NOTSET_OPTION(r, Opt2_hideTabbar))
3627 	rxvt_tabbar_show (r);
3628 
3629     XMapWindow (r->Xdisplay, r->TermWin.parent);
3630 
3631     /*
3632      * We have to wait till our window is mapped before we can set the maximized
3633      * or fullscreen options.
3634      */
3635     if( ISSET_OPTION(r, Opt2_maximized))
3636 	ewmh_message( r->Xdisplay, XROOT, r->TermWin.parent,
3637 	    XInternAtom( r->Xdisplay, "_NET_WM_STATE", True),
3638 	    _NET_WM_STATE_ADD,
3639 	    XInternAtom( r->Xdisplay, "_NET_WM_STATE_MAXIMIZED_HORZ", True),
3640 	    XInternAtom( r->Xdisplay, "_NET_WM_STATE_MAXIMIZED_VERT", True),
3641 	    0, 0);
3642     else if (ISSET_OPTION (r, Opt2_fullscreen))
3643 	ewmh_message( r->Xdisplay, XROOT, r->TermWin.parent,
3644 	    XInternAtom( r->Xdisplay, "_NET_WM_STATE", True),
3645 	    _NET_WM_STATE_ADD,
3646 	    XInternAtom( r->Xdisplay, "_NET_WM_STATE_FULLSCREEN", True),
3647 	    0, 0, 0);
3648 }
3649 
3650 /*----------------------------------------------------------------------*/
3651 /*
3652  * Executes a command in the background, and returns immediately. Returns 1 on
3653  * success, 0 otherwise.
3654  */
3655 int
rxvt_async_exec(rxvt_t * r,const char * cmd)3656 rxvt_async_exec( rxvt_t *r, const char *cmd)
3657 {
3658     int	    pid;
3659     int	    argc;
3660     char    **argv;
3661 
3662     if( r->nAsyncChilds >= MAX_CHILDS )
3663     {
3664 	rxvt_msg (DBG_ERROR, DBG_INIT,  "Too many childs."
3665 		" Increase MAX_CHILDS in src/feature.h" );
3666 	return 0;
3667     }
3668 
3669     pid = fork();
3670     switch( pid )
3671     {
3672 	case -1:
3673 	    rxvt_msg (DBG_ERROR, DBG_INIT,  "Unable to fork" );
3674 	    return 0;	/* Failure */
3675 	    /* NOT REACHED */
3676 
3677 	case 0:
3678 	    /*
3679 	     * Close all file descriptors, and reset signal masks to their
3680 	     * default values before exec'ing the child process.
3681 	     */
3682 	    clean_sigmasks_and_fds( r, ATAB(r) );
3683 
3684 	    argv = rxvt_string_to_argv( cmd, &argc );
3685 
3686 	    execvp( argv[0], argv );
3687 
3688 	    rxvt_msg (DBG_ERROR, DBG_INIT,  "Failed to exec %s", argv[0] );
3689 	    exit(1);
3690 	    /* NOT REACHED */
3691 
3692 	default:
3693 	    rxvt_dbgmsg ((DBG_VERBOSE, DBG_INIT, "Forked %s", cmd));
3694 	    r->asyncChilds[ r->nAsyncChilds++ ] = pid;
3695 	    return 1;
3696     }
3697 }
3698 
3699 
3700 /*
3701  * Run the command in a subprocess and return a file descriptor for the
3702  * master end of the pseudo-teletype pair with the command talking to
3703  * the slave.
3704  */
3705 /* EXTPROTO */
3706 int
rxvt_run_command(rxvt_t * r,int page,const char ** argv)3707 rxvt_run_command(rxvt_t *r, int page, const char **argv)
3708 {
3709     int		cfd, er;
3710 
3711     rxvt_dbgmsg ((DBG_DEBUG, DBG_INIT, "%s(%d, argv)", __func__, page));
3712 
3713     /* get master (pty) */
3714     if ((cfd = rxvt_get_pty(&(PVTS(r, page)->tty_fd),
3715 	(char**) &(PVTS(r, page)->ttydev))) < 0)
3716     {
3717 	rxvt_msg (DBG_ERROR, DBG_INIT, "can't open pseudo-tty");
3718 	return -1;
3719     }
3720 #ifdef FD_SETSIZE
3721     if (r->Xfd > FD_SETSIZE || cfd > FD_SETSIZE)
3722     {
3723 	rxvt_msg (DBG_ERROR, DBG_INIT, "fd too high: %d max", FD_SETSIZE);
3724 	return -1;
3725     }
3726 #endif
3727     fcntl(cfd, F_SETFL, O_NDELAY);
3728 
3729     /* get slave (tty) */
3730     if (PVTS(r, page)->tty_fd < 0)
3731     {
3732 #if !defined(NO_SETOWNER_TTYDEV) && !defined(OS_CYGWIN)
3733 	rxvt_privileged_ttydev(r, page, SAVE);
3734 #endif
3735 	if ((PVTS(r, page)->tty_fd = rxvt_get_tty(PVTS(r, page)->ttydev)) < 0)
3736 	{
3737 	    close(cfd);
3738 	    rxvt_msg (DBG_ERROR, DBG_INIT, "can't open slave tty %s", PVTS(r, page)->ttydev);
3739 	    return -1;
3740 	}
3741     }
3742 
3743     /* Get tty mode before fork */
3744 #ifndef NO_BACKSPACE_KEY
3745     if (r->h->key_backspace[0] && !r->h->key_backspace[1])
3746 	er = r->h->key_backspace[0];
3747     else if (STRCMP(r->h->key_backspace, "DEC") == 0)
3748 	er = '\177';	/* the initial state anyway */
3749     else
3750 #endif
3751 	er = -1;
3752     rxvt_get_ttymode(&(PVTS(r, page)->tio), er);
3753 
3754 
3755     rxvt_dbgmsg ((DBG_DEBUG, DBG_INIT, "argv = 0x%x\n", (unsigned int) argv));
3756 #ifndef __QNX__
3757     /*
3758      * Spin off the command interpreter
3759      */
3760     switch (PVTS(r, page)->cmd_pid = fork())
3761     {
3762 	case -1:
3763 	    rxvt_msg (DBG_ERROR, DBG_INIT, "can't fork");
3764 	    close (cfd);
3765 	    return -1;
3766 
3767 	case 0:
3768 	    /*
3769 	     * To debug the child, follow these steps:
3770 	     *
3771 	     * 	    - enable sleep in the following
3772 	     * 	    - launch gdb, set breakpoint before fork
3773 	     * 	    - run the program, step over fork, then get child pid
3774 	     * 	    - launch another gdb, attach to child process via pid
3775 	     * 	    - in child's gdb, set breakpoint after sleep
3776 	     * 	    - run 'continue' in child's gdb, debug child process
3777 	     */
3778 #if 0
3779 	    sleep(10);
3780 #endif
3781 
3782 
3783 	    if(
3784 		 rxvt_control_tty( PVTS(r, page)->tty_fd,
3785 				    PVTS(r, page)->ttydev ) < 0
3786 	      )
3787 	    {
3788 		rxvt_msg (DBG_ERROR, DBG_INIT, "Could not obtain control of tty");
3789 	    }
3790 	    else
3791 	    {
3792 		/*
3793 		 * Reopen stdin, stdout and stderr over the tty file
3794 		 * descriptor
3795 		 */
3796 		dup2( PVTS(r, page)->tty_fd, STDIN_FILENO  );
3797 		dup2( PVTS(r, page)->tty_fd, STDOUT_FILENO );
3798 		dup2( PVTS(r, page)->tty_fd, STDERR_FILENO );
3799 
3800 		clean_sigmasks_and_fds( r, page );
3801 
3802 		/*
3803 		 * Spin off command interpreter.
3804 		 */
3805 		rxvt_run_child(r, page, argv);
3806 
3807 		/*
3808 		 * If we got here, then we failed to exec the child process.
3809 		 */
3810 		rxvt_msg (DBG_ERROR, DBG_INIT, "Could not execute %s.\n", (argv && argv[0]) ? argv[0] : "shell");
3811 	    }
3812 
3813 	    /* Something went wrong. Kill the child. */
3814 	    if(
3815 		 !(PVTS(r,page)->holdOption & HOLD_STATUSBIT) &&
3816 		 !(PVTS(r,page)->holdOption & HOLD_ALWAYSBIT)
3817 	      )
3818 		/* If tab won't be held open, wait a little */
3819 		sleep(5);
3820 	    exit( EXIT_FAILURE );
3821 
3822 	    /* NOT REACHED */
3823 
3824 	default:
3825 	    {
3826 #if defined(HAVE_STRUCT_UTMP) && defined(HAVE_TTYSLOT)
3827 		int	    fdstdin;
3828 
3829 		fdstdin = dup(STDIN_FILENO);
3830 		dup2(PVTS(r, page)->tty_fd, STDIN_FILENO);
3831 #endif
3832 #ifdef UTMP_SUPPORT
3833 # ifdef UTEMPTER_SUPPORT
3834 		/* utempter hack, it needs cmd_fd */
3835 		PVTS(r, page)->cmd_fd = cfd;
3836 # endif
3837 		rxvt_privileged_utmp(r, page, SAVE);
3838 # ifdef UTEMPTER_SUPPORT
3839 		/* utempter hack, restore cmd_fd */
3840 		PVTS(r, page)->cmd_fd = -1;
3841 # endif
3842 #endif
3843 #if defined(HAVE_STRUCT_UTMP) && defined(HAVE_TTYSLOT)
3844 		dup2(fdstdin, STDIN_FILENO);
3845 		close(fdstdin);
3846 #endif
3847 	    }
3848 
3849 	    /*
3850 	     * keep STDERR_FILENO, PVTS(r, page)->cmd_fd, r->Xfd open
3851 	     */
3852 	    close(PVTS(r, page)->tty_fd);
3853 	    PVTS(r, page)->tty_fd = -1;
3854 	    break;
3855     }
3856 #else		    /* __QNX__ uses qnxspawn() */
3857     fchmod(PVTS(r, page)->tty_fd, 0622);
3858     fcntl(PVTS(r, page)->tty_fd, F_SETFD, FD_CLOEXEC);
3859     fcntl(cfd, F_SETFD, FD_CLOEXEC);
3860     PVTS(r, page)->cmd_fd = cfd;
3861 
3862     if (rxvt_run_child(r, page, argv) == -1)
3863 	/*exit(EXIT_FAILURE);*/
3864 	return -1;
3865 #endif
3866 
3867     return cfd;
3868 }
3869 
3870 
3871 /* ------------------------------------------------------------------------- *
3872  *			    CHILD PROCESS OPERATIONS			     *
3873  * ------------------------------------------------------------------------- */
3874 
3875 /*
3876  * Reset signal masks to their default values, and close all open file
3877  * descriptors.
3878  */
3879 /* EXTPROTO */
3880 void
clean_sigmasks_and_fds(rxvt_t * r,int page)3881 clean_sigmasks_and_fds( rxvt_t* r, int page )
3882 {
3883 #ifdef SIGTSTP
3884     struct sigaction	ignore;
3885 #endif
3886     struct sigaction	deflt;
3887     register int	i;
3888 
3889     /* Close all file descriptors except STDXXX */
3890     for (i = STDERR_FILENO + 1; i < r->num_fds; i ++)
3891 	close (i);
3892     if (PVTS(r, page)->tty_fd > 2)
3893     {
3894 	close (PVTS(r, page)->tty_fd);
3895 	PVTS(r, page)->tty_fd = -1;
3896     }
3897 
3898     /* reset signal handlers */
3899     deflt.sa_handler = SIG_DFL;
3900     deflt.sa_flags = 0;
3901     sigemptyset( &deflt.sa_mask );
3902 
3903     sigaction( SIGINT,	&deflt, NULL );
3904     sigaction( SIGQUIT, &deflt, NULL );
3905     sigaction( SIGTERM, &deflt, NULL );
3906     sigaction( SIGHUP,	&deflt, NULL );
3907     sigaction( SIGPIPE,	&deflt, NULL );
3908     sigaction( SIGCHLD, &deflt, NULL );
3909 
3910     /*
3911      * Mimick login's behavior by disabling the job control signals a shell that
3912      * wants them can turn them back on
3913      */
3914 #ifdef SIGTSTP
3915     ignore.sa_handler	= SIG_IGN;
3916     ignore.sa_flags	= 0;
3917     sigemptyset( &ignore.sa_mask );
3918 
3919     sigaction( SIGTSTP, &ignore, NULL );
3920     sigaction( SIGTTIN, &ignore, NULL );
3921     sigaction( SIGTTOU, &ignore, NULL );
3922 #endif	/* SIGTSTP */
3923 }
3924 
3925 
3926 /*
3927  * The only open file descriptor is the slave tty - so no error messages.
3928  * returns are fatal
3929  */
3930 /* INTPROTO */
3931 int
rxvt_run_child(rxvt_t * r,int page,const char ** argv)3932 rxvt_run_child(rxvt_t* r, int page, const char **argv)
3933 {
3934     char*		login;
3935 
3936 
3937     /* rxvt_dbgmsg ((DBG_DEBUG, DBG_INIT, "argv = %x\n", argv)); */
3938 
3939     /* init terminal attributes */
3940     SET_TTYMODE( STDIN_FILENO, &(PVTS(r, page)->tio) );
3941 
3942     if (ISSET_OPTION(r, Opt_console))	/* be virtual console, fail
3943 					 * silently */
3944     {
3945 #ifdef TIOCCONS
3946 	unsigned int	on = 1;
3947 	ioctl(STDIN_FILENO, TIOCCONS, &on);
3948 #elif defined (SRIOCSREDIR)
3949 	int	    fd;
3950 	fd = open( CONSOLE, O_WRONLY, 0 );
3951 	if (fd >= 0)
3952 	{
3953 	    if( ioctl( fd, SRIOCSREDIR, NULL ) < 0 )
3954 	    close( fd );
3955 	}
3956 #endif	/* SRIOCSREDIR */
3957     }
3958 
3959     /* set window size */
3960     rxvt_tt_winsize( STDIN_FILENO, r->TermWin.ncol, r->TermWin.nrow, 0 );
3961 
3962 #ifndef __QNX__
3963     /* command interpreter path */
3964     if (NOT_NULL(argv))
3965     {
3966 	int	    i;
3967 	for (i = 0; argv[i]; i++)
3968 	    rxvt_dbgmsg ((DBG_DEBUG, DBG_INIT, "argv [%d] = \"%s\"\n", i, argv[i]));
3969 	execvp(argv[0], (char *const *)argv);
3970 	/* no error message: STDERR is closed! */
3971     }
3972     else
3973     {
3974 	const char   *argv0, *shell;
3975 
3976 	if (IS_NULL(shell = getenv("SHELL")) || ((char) 0 == *shell) )
3977 	{
3978 # ifdef HAVE_GETPWUID
3979 	    struct passwd* pwent = getpwuid( getuid () );
3980 
3981 	    if (IS_NULL(pwent) ||
3982 		IS_NULL(shell = pwent->pw_shell) ||
3983 		(char) 0 == *shell
3984 	      )
3985 # endif	/* HAVE_GETPWUID */
3986 		shell = "/bin/sh";
3987 	}
3988 
3989 	argv0 = (const char *) rxvt_r_basename( shell);
3990 	if (ISSET_OPTION(r, Opt_loginShell))
3991 	{
3992 	    int	    l = STRLEN(argv0) + 2;
3993 	    if (l <= 0 || l > 4096) /* possible integer overflow */
3994 		l = 4096;
3995 	    login = rxvt_malloc(l * sizeof(char));
3996 
3997 	    login[0] = '-';
3998 	    STRNCPY(&login[1], argv0, l-2);
3999 	    login[l-1] = (char) 0;
4000 	    argv0 = login;
4001 	}
4002 	execlp( shell, argv0, NULL );
4003 	/* no error message: STDERR is closed! */
4004     }
4005 #else		    /* __QNX__ uses qnxspawn() */
4006     {
4007 	char	iov_a[10] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 };
4008 	char*	command = NULL, fullcommand[_MAX_PATH];
4009 	char**	arg_v, *arg_a[2] = { NULL, NULL };
4010 
4011 	if (argv != NULL)
4012 	{
4013 	    if (access(argv[0], X_OK) == -1)
4014 	    {
4015 		if (IS_NULL(STRCHR(argv[0], '/')))
4016 		{
4017 		    searchenv(argv[0], "PATH", fullcommand);
4018 		    if (fullcommand[0] != '\0')
4019 			command = fullcommand;
4020 		}
4021 		if (access(command, X_OK) == -1)
4022 		    return -1;
4023 	    }
4024 	    else
4025 		command = argv[0];
4026 	    arg_v = argv;
4027 	}
4028 	else
4029 	{
4030 	    if (IS_NULL(command = getenv("SHELL")) ||
4031 		(char) 0 == *command)
4032 		command = "/bin/sh";
4033 
4034 	    arg_a[0] = my_basename(command);
4035 	    if (ISSET_OPTION(r, Opt_loginShell))
4036 	    {
4037 		int	l = STRLEN(arg_a[0]) + 2;
4038 		if (l <= 0 || l > 4096)	/* possible integer overflow */
4039 		    l = 4096;
4040 		login = rxvt_malloc(l * sizeof(char));
4041 
4042 		login[0] = '-';
4043 		STRNCPY(&login[1], arg_a[0], l-2);
4044 		login[l-1] = (char) 0;
4045 		arg_a[0] = login;
4046 	    }
4047 	    arg_v = arg_a;
4048 	}
4049 	iov_a[0] = iov_a[1] = iov_a[2] = PVTS(r, page)->tty_fd;
4050 	PVTS(r, page)->cmd_pid = qnx_spawn(0, 0, 0, -1, -1,
4051 		    _SPAWN_SETSID | _SPAWN_TCSETPGRP,
4052 		    command, arg_v, environ, iov_a, 0);
4053 	if (login)
4054 	    rxvt_free(login);
4055 	close(PVTS(r, page)->tty_fd);
4056 	PVTS(r, page)->tty_fd = -1;
4057 	return PVTS(r, page)->cmd_fd;
4058     }
4059 #endif
4060     return -1;
4061 }
4062 
4063 /* ------------------------------------------------------------------------- *
4064  *			    GET TTY CURRENT STATE			     *
4065  * ------------------------------------------------------------------------- */
4066 /* rxvt_get_ttymode() */
4067 /* INTPROTO */
4068 void
rxvt_get_ttymode(ttymode_t * tio,int erase)4069 rxvt_get_ttymode(ttymode_t *tio, int erase)
4070 {
4071 #ifdef HAVE_TERMIOS_H
4072     /*
4073      * standard System V termios interface
4074      */
4075     if (GET_TERMIOS(STDIN_FILENO, tio) < 0)
4076     {
4077 	/* return error - use system defaults */
4078 	tio->c_cc[VINTR] = CINTR;
4079 	tio->c_cc[VQUIT] = CQUIT;
4080 	tio->c_cc[VERASE] = CERASE;
4081 	tio->c_cc[VKILL] = CKILL;
4082 	tio->c_cc[VSTART] = CSTART;
4083 	tio->c_cc[VSTOP] = CSTOP;
4084 	tio->c_cc[VSUSP] = CSUSP;
4085 # ifdef VDSUSP
4086 	tio->c_cc[VDSUSP] = CDSUSP;
4087 # endif
4088 # ifdef VREPRINT
4089 	tio->c_cc[VREPRINT] = CRPRNT;
4090 # endif
4091 # ifdef VDISCRD
4092 	tio->c_cc[VDISCRD] = CFLUSH;
4093 # endif
4094 # ifdef VWERSE
4095 	tio->c_cc[VWERSE] = CWERASE;
4096 # endif
4097 # ifdef VLNEXT
4098 	tio->c_cc[VLNEXT] = CLNEXT;
4099 # endif
4100     }
4101     tio->c_cc[VEOF] = CEOF;
4102     tio->c_cc[VEOL] = VDISABLE;
4103 # ifdef VEOL2
4104     tio->c_cc[VEOL2] = VDISABLE;
4105 # endif
4106 # ifdef VSWTC
4107     tio->c_cc[VSWTC] = VDISABLE;
4108 # endif
4109 # ifdef VSWTCH
4110     tio->c_cc[VSWTCH] = VDISABLE;
4111 # endif
4112 # if VMIN != VEOF
4113     tio->c_cc[VMIN] = 1;
4114 # endif
4115 # if VTIME != VEOL
4116     tio->c_cc[VTIME] = 0;
4117 # endif
4118     if (erase != -1)
4119     tio->c_cc[VERASE] = (char)erase;
4120 
4121 /* input modes */
4122     tio->c_iflag = (BRKINT | IGNPAR | ICRNL
4123 # ifdef IMAXBEL
4124 		    | IMAXBEL
4125 # endif
4126 		    | IXON);
4127 
4128 /* output modes */
4129     tio->c_oflag = (OPOST | ONLCR);
4130 
4131 /* control modes */
4132     tio->c_cflag = (CS8 | CREAD);
4133 
4134 /* line discipline modes */
4135     tio->c_lflag = (ISIG | ICANON | IEXTEN | ECHO
4136 # if defined (ECHOCTL) && defined (ECHOKE)
4137 		    | ECHOCTL | ECHOKE
4138 # endif
4139 		    | ECHOE | ECHOK);
4140 # else		    /* HAVE_TERMIOS_H */
4141 
4142     /*
4143      * sgtty interface
4144      */
4145 
4146     /* get parameters -- gtty */
4147     if (ioctl(STDIN_FILENO, TIOCGETP, &(tio->sg)) < 0)
4148     {
4149 	tio->sg.sg_erase = CERASE;  /* ^H */
4150 	tio->sg.sg_kill = CKILL;    /* ^U */
4151     }
4152     if (erase != -1)
4153 	tio->sg.sg_erase = (char)erase;
4154 
4155     tio->sg.sg_flags = (CRMOD | ECHO | EVENP | ODDP);
4156 
4157     /* get special characters */
4158     if (ioctl(STDIN_FILENO, TIOCGETC, &(tio->tc)) < 0)
4159     {
4160 	tio->tc.t_intrc = CINTR;    /* ^C */
4161 	tio->tc.t_quitc = CQUIT;    /* ^\ */
4162 	tio->tc.t_startc = CSTART;  /* ^Q */
4163 	tio->tc.t_stopc = CSTOP;    /* ^S */
4164 	tio->tc.t_eofc = CEOF;	/* ^D */
4165 	tio->tc.t_brkc = -1;
4166     }
4167 
4168     /* get local special chars */
4169     if (ioctl(STDIN_FILENO, TIOCGLTC, &(tio->lc)) < 0)
4170     {
4171 	tio->lc.t_suspc = CSUSP;    /* ^Z */
4172 	tio->lc.t_dsuspc = CDSUSP;  /* ^Y */
4173 	tio->lc.t_rprntc = CRPRNT;  /* ^R */
4174 	tio->lc.t_flushc = CFLUSH;  /* ^O */
4175 	tio->lc.t_werasc = CWERASE; /* ^W */
4176 	tio->lc.t_lnextc = CLNEXT;  /* ^V */
4177     }
4178 
4179     /* get line discipline */
4180     ioctl(STDIN_FILENO, TIOCGETD, &(tio->line));
4181 # ifdef NTTYDISC
4182     tio->line = NTTYDISC;
4183 # endif		    /* NTTYDISC */
4184     tio->local = (LCRTBS | LCRTERA | LCTLECH | LPASS8 | LCRTKIL);
4185 #endif		    /* HAVE_TERMIOS_H */
4186 
4187 /*
4188  * Debugging
4189  */
4190 #ifdef DEBUG
4191 #ifdef HAVE_TERMIOS_H
4192 /* c_iflag bits */
4193     rxvt_dbgmsg ((DBG_DEBUG, DBG_INIT, "Input flags\n"));
4194 
4195 /* cpp token stringize doesn't work on all machines <sigh> */
4196 # define FOO(flag,name)		    \
4197     if ((tio->c_iflag) & flag)	    \
4198         rxvt_msg (DBG_DEBUG, DBG_INIT, "%s ", name)
4199 
4200 /* c_iflag bits */
4201     FOO(IGNBRK, "IGNBRK");
4202     FOO(BRKINT, "BRKINT");
4203     FOO(IGNPAR, "IGNPAR");
4204     FOO(PARMRK, "PARMRK");
4205     FOO(INPCK, "INPCK");
4206     FOO(ISTRIP, "ISTRIP");
4207     FOO(INLCR, "INLCR");
4208     FOO(IGNCR, "IGNCR");
4209     FOO(ICRNL, "ICRNL");
4210     FOO(IXON, "IXON");
4211     FOO(IXOFF, "IXOFF");
4212 # ifdef IUCLC
4213     FOO(IUCLC, "IUCLC");
4214 # endif
4215 # ifdef IXANY
4216     FOO(IXANY, "IXANY");
4217 # endif
4218 # ifdef IMAXBEL
4219     FOO(IMAXBEL, "IMAXBEL");
4220 # endif
4221     rxvt_dbgmsg ((DBG_DEBUG, DBG_INIT, "\n"));
4222 
4223 # undef FOO
4224 # define FOO(entry, name)		    \
4225     rxvt_dbgmsg ((DBG_DEBUG, DBG_INIT, "%-8s = %#04o\n", name, tio->c_cc [entry]))
4226 
4227     FOO(VINTR, "VINTR");
4228     FOO(VQUIT, "VQUIT");
4229     FOO(VERASE, "VERASE");
4230     FOO(VKILL, "VKILL");
4231     FOO(VEOF, "VEOF");
4232     FOO(VEOL, "VEOL");
4233 # ifdef VEOL2
4234     FOO(VEOL2, "VEOL2");
4235 # endif
4236 # ifdef VSWTC
4237     FOO(VSWTC, "VSWTC");
4238 # endif
4239 # ifdef VSWTCH
4240     FOO(VSWTCH, "VSWTCH");
4241 # endif
4242     FOO(VSTART, "VSTART");
4243     FOO(VSTOP, "VSTOP");
4244     FOO(VSUSP, "VSUSP");
4245 # ifdef VDSUSP
4246     FOO(VDSUSP, "VDSUSP");
4247 # endif
4248 # ifdef VREPRINT
4249     FOO(VREPRINT, "VREPRINT");
4250 # endif
4251 # ifdef VDISCRD
4252     FOO(VDISCRD, "VDISCRD");
4253 # endif
4254 # ifdef VWERSE
4255     FOO(VWERSE, "VWERSE");
4256 # endif
4257 # ifdef VLNEXT
4258     FOO(VLNEXT, "VLNEXT");
4259 # endif
4260     rxvt_dbgmsg ((DBG_DEBUG, DBG_INIT, "\n"));
4261 # undef FOO
4262 # endif		    /* HAVE_TERMIOS_H */
4263 #endif		    /* DEBUG */
4264 }
4265 
4266 /*----------------------- end-of-file (C source) -----------------------*/
4267