ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/init.C
Revision: 1.184
Committed: Fri Jun 8 20:04:12 2007 UTC (16 years, 11 months ago) by sasha
Content type: text/plain
Branch: MAIN
Changes since 1.183: +4 -1 lines
Log Message:
added preliminary support to use libAfterImage for background pixmap loading and rendering of transparency effects including blending of pixmap over background using several methods, and gaussian blurr of the transparency background

File Contents

# User Rev Content
1 root 1.172 /*----------------------------------------------------------------------*
2 pcg 1.50 * File: init.C
3 pcg 1.1 *----------------------------------------------------------------------*
4     *
5     * All portions of code are copyright by their respective author/s.
6     * Copyright (c) 1992 John Bovey, University of Kent at Canterbury <jdb@ukc.ac.uk>
7 pcg 1.4 * - original version
8 pcg 1.1 * Copyright (c) 1994 Robert Nation <nation@rocket.sanders.lockheed.com>
9 pcg 1.4 * - extensive modifications
10 pcg 1.1 * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com>
11 pcg 1.4 * - extensive modifications
12 pcg 1.1 * Copyright (c) 1999 D J Hawkey Jr <hawkeyd@visi.com>
13 pcg 1.4 * - QNX support
14 root 1.134 * Copyright (c) 2003-2006 Marc Lehmann <pcg@goof.com>
15 pcg 1.1 *
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     * Initialisation routines.
32     */
33    
34 pcg 1.4 #include "../config.h" /* NECESSARY */
35     #include "rxvt.h" /* NECESSARY */
36 root 1.105 #include "rxvtutil.h"
37 pcg 1.1 #include "init.h"
38    
39 root 1.125 #include <limits>
40    
41 root 1.99 #include <csignal>
42 pcg 1.1
43 pcg 1.9 const char *const def_colorName[] =
44     {
45 pcg 1.1 COLOR_FOREGROUND,
46     COLOR_BACKGROUND,
47 pcg 1.9 /* low-intensity colors */
48 root 1.159 "rgb:00/00/00", // 0: black (Black)
49     "rgb:cd/00/00", // 1: red (Red3)
50     "rgb:00/cd/00", // 2: green (Green3)
51 root 1.183 "rgb:cd/cd/00", // 3: yellow (Yellow3)
52 root 1.159 "rgb:00/00/cd", // 4: blue (Blue3)
53     "rgb:cd/00/cd", // 5: magenta (Magenta3)
54     "rgb:00/cd/cd", // 6: cyan (Cyan3)
55     # ifdef XTERM_COLORS
56     "rgb:e5/e5/e5", // 7: white (Grey90)
57     # else
58     "rgb:fa/eb/d7", // 7: white (AntiqueWhite)
59 pcg 1.1 # endif
60 pcg 1.9 /* high-intensity colors */
61 pcg 1.1 # ifdef XTERM_COLORS
62 root 1.159 "rgb:4d/4d/4d", // 8: bright black (Grey30)
63 pcg 1.1 # else
64 root 1.159 "rgb:40/40/40", // 8: bright black (Grey25)
65 pcg 1.1 # endif
66 root 1.159 "rgb:ff/00/00", // 1/9: bright red (Reed)
67     "rgb:00/ff/00", // 2/10: bright green (Green)
68     "rgb:ff/ff/00", // 3/11: bright yellow (Yellow)
69     "rgb:00/00/ff", // 4/12: bright blue (Blue)
70     "rgb:ff/00/ff", // 5/13: bright magenta (Magenta)
71     "rgb:00/ff/ff", // 6/14: bright cyan (Cyan)
72     "rgb:ff/ff/ff", // 7/15: bright white (White)
73 root 1.90
74     // 88 xterm colours
75     "rgb:00/00/00",
76     "rgb:00/00/8b",
77     "rgb:00/00/cd",
78     "rgb:00/00/ff",
79     "rgb:00/8b/00",
80     "rgb:00/8b/8b",
81     "rgb:00/8b/cd",
82     "rgb:00/8b/ff",
83     "rgb:00/cd/00",
84     "rgb:00/cd/8b",
85     "rgb:00/cd/cd",
86     "rgb:00/cd/ff",
87     "rgb:00/ff/00",
88     "rgb:00/ff/8b",
89     "rgb:00/ff/cd",
90     "rgb:00/ff/ff",
91     "rgb:8b/00/00",
92     "rgb:8b/00/8b",
93     "rgb:8b/00/cd",
94     "rgb:8b/00/ff",
95     "rgb:8b/8b/00",
96     "rgb:8b/8b/8b",
97     "rgb:8b/8b/cd",
98     "rgb:8b/8b/ff",
99     "rgb:8b/cd/00",
100     "rgb:8b/cd/8b",
101     "rgb:8b/cd/cd",
102     "rgb:8b/cd/ff",
103     "rgb:8b/ff/00",
104     "rgb:8b/ff/8b",
105     "rgb:8b/ff/cd",
106     "rgb:8b/ff/ff",
107     "rgb:cd/00/00",
108     "rgb:cd/00/8b",
109     "rgb:cd/00/cd",
110     "rgb:cd/00/ff",
111     "rgb:cd/8b/00",
112     "rgb:cd/8b/8b",
113     "rgb:cd/8b/cd",
114     "rgb:cd/8b/ff",
115     "rgb:cd/cd/00",
116     "rgb:cd/cd/8b",
117     "rgb:cd/cd/cd",
118     "rgb:cd/cd/ff",
119     "rgb:cd/ff/00",
120     "rgb:cd/ff/8b",
121     "rgb:cd/ff/cd",
122     "rgb:cd/ff/ff",
123     "rgb:ff/00/00",
124     "rgb:ff/00/8b",
125     "rgb:ff/00/cd",
126     "rgb:ff/00/ff",
127     "rgb:ff/8b/00",
128     "rgb:ff/8b/8b",
129     "rgb:ff/8b/cd",
130     "rgb:ff/8b/ff",
131     "rgb:ff/cd/00",
132     "rgb:ff/cd/8b",
133     "rgb:ff/cd/cd",
134     "rgb:ff/cd/ff",
135     "rgb:ff/ff/00",
136     "rgb:ff/ff/8b",
137     "rgb:ff/ff/cd",
138     "rgb:ff/ff/ff",
139     "rgb:2e/2e/2e",
140     "rgb:5c/5c/5c",
141     "rgb:73/73/73",
142     "rgb:8b/8b/8b",
143     "rgb:a2/a2/a2",
144     "rgb:b9/b9/b9",
145 pcg 1.1 "rgb:d0/d0/d0",
146 root 1.90 "rgb:e7/e7/e7",
147    
148 pcg 1.1 #ifndef NO_CURSORCOLOR
149     COLOR_CURSOR_BACKGROUND,
150     COLOR_CURSOR_FOREGROUND,
151 pcg 1.4 #endif /* ! NO_CURSORCOLOR */
152 pcg 1.49 NULL, /* Color_pointer_fg */
153     NULL, /* Color_pointer_bg */
154 pcg 1.4 NULL, /* Color_border */
155 pcg 1.1 #ifndef NO_BOLD_UNDERLINE_REVERSE
156 pcg 1.4 NULL, /* Color_BD */
157 root 1.90 NULL, /* Color_IT */
158 pcg 1.4 NULL, /* Color_UL */
159     NULL, /* Color_RV */
160     #endif /* ! NO_BOLD_UNDERLINE_REVERSE */
161 root 1.98 #if ENABLE_FRILLS
162     NULL, // Color_underline
163     #endif
164 pcg 1.1 #ifdef OPTION_HC
165     NULL,
166     #endif
167     #ifdef KEEP_SCROLLCOLOR
168     COLOR_SCROLLBAR,
169     COLOR_SCROLLTROUGH,
170 pcg 1.4 #endif /* KEEP_SCROLLCOLOR */
171 root 1.57 #if TINTING
172     NULL,
173     #endif
174 root 1.119 #if OFF_FOCUS_FADING
175 root 1.159 "rgb:00/00/00",
176 root 1.119 #endif
177 pcg 1.9 };
178 pcg 1.1
179 pcg 1.4 bool
180 pcg 1.14 rxvt_term::init_vars ()
181 pcg 1.1 {
182 root 1.154 pix_colors = //
183     pix_colors_focused = new rxvt_color [TOTAL_COLORS];
184 root 1.65 #ifdef OFF_FOCUS_FADING
185 root 1.79 pix_colors_unfocused = new rxvt_color [TOTAL_COLORS];
186 root 1.65 #endif
187 pcg 1.1
188     #if defined(XPM_BACKGROUND) || defined(TRANSPARENT)
189 root 1.122 pixmap = None;
190 pcg 1.1 #endif
191 pcg 1.9
192     MEvent.time = CurrentTime;
193     MEvent.button = AnyButton;
194     want_refresh = 1;
195 root 1.79 priv_modes = SavedModes = PrivMode_Default;
196 root 1.122 ncol = 80;
197     nrow = 24;
198     int_bwidth = INTERNALBORDERWIDTH;
199     ext_bwidth = EXTERNALBORDERWIDTH;
200     lineSpace = LINESPACE;
201     saveLines = SAVELINES;
202 root 1.79 numpix_colors = TOTAL_COLORS;
203 pcg 1.14
204 pcg 1.9 refresh_limit = 1;
205     refresh_type = SLOW_REFRESH;
206    
207     oldcursor.row = oldcursor.col = -1;
208 pcg 1.1 #ifdef XPM_BACKGROUND
209 pcg 1.9 /* bgPixmap.w = bgPixmap.h = 0; */
210 ayin 1.180 bgPixmap.x = bgPixmap.y = 0;
211 pcg 1.9 bgPixmap.pixmap = None;
212 pcg 1.1 #endif
213 pcg 1.9
214     last_bot = last_state = -1;
215 pcg 1.14
216 root 1.182 set_option (Opt_scrollBar);
217     set_option (Opt_scrollTtyOutput);
218     set_option (Opt_jumpScroll);
219     set_option (Opt_secondaryScreen);
220     set_option (Opt_secondaryScroll);
221     set_option (Opt_pastableTabs);
222     set_option (Opt_intensityStyles);
223 ayin 1.181
224 pcg 1.9 return true;
225 pcg 1.1 }
226    
227     void
228 pcg 1.14 rxvt_term::init_secondary ()
229 pcg 1.1 {
230 pcg 1.14 int i;
231 pcg 1.9
232     /*
233     * Close all unused file descriptors
234     * We don't want them, we don't need them.
235     */
236     if ((i = open ("/dev/null", O_RDONLY)) < 0)
237     {
238     /* TODO: BOO HISS */
239     dup2 (STDERR_FILENO, STDIN_FILENO);
240     }
241     else if (i > STDIN_FILENO)
242     {
243     dup2 (i, STDIN_FILENO);
244     close (i);
245     }
246 pcg 1.1
247 pcg 1.9 dup2 (STDERR_FILENO, STDOUT_FILENO);
248 pcg 1.14
249 pcg 1.7 #if 0 // schmorp sayz closing filies is murder
250 pcg 1.14 for (i = STDERR_FILENO + 1; i < num_fds; i++)
251 pcg 1.9 {
252 pcg 1.4 #ifdef __sgi /* Alex Coventry says we need 4 & 7 too */
253 pcg 1.9 if (i == 4 || i == 7)
254     continue;
255 pcg 1.1 #endif
256 pcg 1.26 close (i);
257 pcg 1.1 }
258 pcg 1.7 #endif
259 pcg 1.1 }
260    
261     /*----------------------------------------------------------------------*/
262 pcg 1.14 const char **
263     rxvt_term::init_resources (int argc, const char *const *argv)
264 pcg 1.1 {
265 pcg 1.9 int i, r_argc;
266     char *val;
267     const char **cmd_argv, **r_argv;
268    
269     /*
270 root 1.171 * Look for -e option. Find => split and make cmd_argv[] of command args
271 pcg 1.9 */
272     for (r_argc = 0; r_argc < argc; r_argc++)
273 root 1.171 if (!strcmp (argv[r_argc], "-e"))
274 pcg 1.9 break;
275 pcg 1.14
276 pcg 1.26 r_argv = (const char **)rxvt_malloc (sizeof (char *) * (r_argc + 1));
277 pcg 1.9
278     for (i = 0; i < r_argc; i++)
279     r_argv[i] = (const char *)argv[i];
280 pcg 1.14
281 pcg 1.9 r_argv[i] = NULL;
282 pcg 1.14
283 pcg 1.9 if (r_argc == argc)
284     cmd_argv = NULL;
285     else
286     {
287 pcg 1.26 cmd_argv = (const char **)rxvt_malloc (sizeof (char *) * (argc - r_argc));
288 pcg 1.1
289 pcg 1.9 for (i = 0; i < argc - r_argc - 1; i++)
290     cmd_argv[i] = (const char *)argv[i + r_argc + 1];
291 pcg 1.14
292 pcg 1.9 cmd_argv[i] = NULL;
293     }
294 pcg 1.1
295 pcg 1.26 rs[Rs_name] = rxvt_r_basename (argv[0]);
296 pcg 1.14
297 pcg 1.9 /*
298     * Open display, get options/resources and create the window
299     */
300 pcg 1.1
301 root 1.140 if ((rs[Rs_display_name] = getenv ("DISPLAY")) == NULL)
302     rs[Rs_display_name] = ":0";
303 pcg 1.1
304 root 1.140 get_options (r_argc, r_argv);
305 root 1.137
306 root 1.140 if (!(display = displays.get (rs[Rs_display_name])))
307     rxvt_fatal ("can't open display %s, aborting.\n", rs[Rs_display_name]);
308 root 1.139
309 root 1.166 // using a local pointer decreases code size a lot
310 root 1.157 xa = display->xa;
311    
312 root 1.173 set (display);
313     extract_resources ();
314    
315 root 1.161 #if XFT
316 root 1.157 if (rs[Rs_depth])
317 root 1.173 select_visual (strtol (rs[Rs_depth], 0, 0));
318 root 1.157 #endif
319 pcg 1.1
320 root 1.167 free (r_argv);
321    
322 root 1.166 for (int i = NUM_RESOURCES; i--; )
323     if (rs [i] == resval_undef)
324     rs [i] = 0;
325    
326 root 1.151 #if ENABLE_PERL
327     if (!rs[Rs_perl_ext_1])
328     rs[Rs_perl_ext_1] = "default";
329    
330     if ((rs[Rs_perl_ext_1] && *rs[Rs_perl_ext_1])
331     || (rs[Rs_perl_ext_2] && *rs[Rs_perl_ext_2])
332     || (rs[Rs_perl_eval] && *rs[Rs_perl_eval]))
333     {
334     rxvt_perl.init (this);
335     HOOK_INVOKE ((this, HOOK_INIT, DT_END));
336     }
337     #endif
338    
339 pcg 1.9 /*
340     * set any defaults not already set
341     */
342     if (cmd_argv && cmd_argv[0])
343     {
344     if (!rs[Rs_title])
345 pcg 1.26 rs[Rs_title] = rxvt_r_basename (cmd_argv[0]);
346 pcg 1.9 if (!rs[Rs_iconName])
347     rs[Rs_iconName] = rs[Rs_title];
348     }
349     else
350     {
351     if (!rs[Rs_title])
352     rs[Rs_title] = rs[Rs_name];
353     if (!rs[Rs_iconName])
354     rs[Rs_iconName] = rs[Rs_name];
355 pcg 1.1 }
356 pcg 1.14
357 pcg 1.26 if (rs[Rs_saveLines] && (i = atoi (rs[Rs_saveLines])) >= 0)
358 root 1.126 saveLines = min (i, MAX_SAVELINES);
359 pcg 1.14
360 root 1.79 #if ENABLE_FRILLS
361 pcg 1.26 if (rs[Rs_int_bwidth] && (i = atoi (rs[Rs_int_bwidth])) >= 0)
362 root 1.125 int_bwidth = min (i, std::numeric_limits<int16_t>::max ());
363 root 1.124
364 pcg 1.26 if (rs[Rs_ext_bwidth] && (i = atoi (rs[Rs_ext_bwidth])) >= 0)
365 root 1.125 ext_bwidth = min (i, std::numeric_limits<int16_t>::max ());
366 root 1.124
367 pcg 1.26 if (rs[Rs_lineSpace] && (i = atoi (rs[Rs_lineSpace])) >= 0)
368 root 1.125 lineSpace = min (i, std::numeric_limits<int16_t>::max ());
369 pcg 1.1 #endif
370    
371     #ifdef POINTER_BLANK
372 pcg 1.26 if (rs[Rs_pointerBlankDelay] && (i = atoi (rs[Rs_pointerBlankDelay])) >= 0)
373 pcg 1.14 pointerBlankDelay = i;
374 pcg 1.9 else
375 pcg 1.14 pointerBlankDelay = 2;
376 pcg 1.1 #endif
377    
378 pcg 1.9 /* no point having a scrollbar without having any scrollback! */
379 root 1.122 if (!saveLines)
380 root 1.136 set_option (Opt_scrollBar, 0);
381 pcg 1.1
382     #ifdef PRINTPIPE
383 pcg 1.9 if (!rs[Rs_print_pipe])
384     rs[Rs_print_pipe] = PRINTPIPE;
385 pcg 1.1 #endif
386 pcg 1.9
387     if (!rs[Rs_cutchars])
388     rs[Rs_cutchars] = CUTCHARS;
389 pcg 1.14
390 pcg 1.1 #ifndef NO_BACKSPACE_KEY
391 pcg 1.9 if (!rs[Rs_backspace_key])
392 pcg 1.1 # ifdef DEFAULT_BACKSPACE
393 pcg 1.14 key_backspace = DEFAULT_BACKSPACE;
394 pcg 1.1 # else
395 pcg 1.14 key_backspace = "DEC"; /* can toggle between \010 or \177 */
396 pcg 1.1 # endif
397 pcg 1.9 else
398     {
399 root 1.79 val = strdup (rs[Rs_backspace_key]);
400 pcg 1.26 rxvt_Str_trim (val);
401     rxvt_Str_escaped (val);
402 pcg 1.14 key_backspace = val;
403 pcg 1.1 }
404     #endif
405 pcg 1.14
406 pcg 1.1 #ifndef NO_DELETE_KEY
407 pcg 1.9 if (!rs[Rs_delete_key])
408 pcg 1.1 # ifdef DEFAULT_DELETE
409 pcg 1.14 key_delete = DEFAULT_DELETE;
410 pcg 1.1 # else
411 pcg 1.14 key_delete = "\033[3~";
412 pcg 1.1 # endif
413 pcg 1.9 else
414     {
415 root 1.79 val = strdup (rs[Rs_delete_key]);
416 pcg 1.26 rxvt_Str_trim (val);
417     rxvt_Str_escaped (val);
418 pcg 1.14 key_delete = val;
419 pcg 1.1 }
420     #endif
421 pcg 1.9 if (rs[Rs_answerbackstring])
422     {
423 pcg 1.26 rxvt_Str_trim ((char *)rs[Rs_answerbackstring]);
424     rxvt_Str_escaped ((char *)rs[Rs_answerbackstring]);
425 pcg 1.1 }
426    
427     #ifdef HAVE_SCROLLBARS
428 root 1.90 setup_scrollbar (rs[Rs_scrollBar_align], rs[Rs_scrollstyle], rs[Rs_scrollBar_thickness]);
429 pcg 1.1 #endif
430    
431     #ifdef XTERM_REVERSE_VIDEO
432 pcg 1.9 /* this is how xterm implements reverseVideo */
433 root 1.182 if (option (Opt_reverseVideo))
434 pcg 1.9 {
435     if (!rs[Rs_color + Color_fg])
436     rs[Rs_color + Color_fg] = def_colorName[Color_bg];
437 root 1.165
438 pcg 1.9 if (!rs[Rs_color + Color_bg])
439     rs[Rs_color + Color_bg] = def_colorName[Color_fg];
440 pcg 1.1 }
441     #endif
442    
443 pcg 1.9 for (i = 0; i < NRS_COLORS; i++)
444     if (!rs[Rs_color + i])
445     rs[Rs_color + i] = def_colorName[i];
446 pcg 1.1
447     #ifndef XTERM_REVERSE_VIDEO
448 pcg 1.9 /* this is how we implement reverseVideo */
449 root 1.182 if (option (Opt_reverseVideo))
450 root 1.123 ::swap (rs[Rs_color + Color_fg], rs[Rs_color + Color_bg]);
451 pcg 1.1 #endif
452    
453 pcg 1.9 /* convenient aliases for setting fg/bg to colors */
454 pcg 1.14 color_aliases (Color_fg);
455     color_aliases (Color_bg);
456 pcg 1.1 #ifndef NO_CURSORCOLOR
457 pcg 1.14 color_aliases (Color_cursor);
458     color_aliases (Color_cursor2);
459 pcg 1.4 #endif /* NO_CURSORCOLOR */
460 pcg 1.49 color_aliases (Color_pointer_fg);
461     color_aliases (Color_pointer_bg);
462 pcg 1.14 color_aliases (Color_border);
463 pcg 1.1 #ifndef NO_BOLD_UNDERLINE_REVERSE
464 pcg 1.14 color_aliases (Color_BD);
465     color_aliases (Color_UL);
466     color_aliases (Color_RV);
467 pcg 1.4 #endif /* ! NO_BOLD_UNDERLINE_REVERSE */
468 pcg 1.1
469 root 1.90 if (!rs[Rs_color + Color_border])
470     rs[Rs_color + Color_border] = rs[Rs_color + Color_bg];
471    
472 pcg 1.9 return cmd_argv;
473 pcg 1.1 }
474    
475     /*----------------------------------------------------------------------*/
476     void
477 pcg 1.14 rxvt_term::init_env ()
478 pcg 1.1 {
479 pcg 1.14 int i;
480     unsigned int u;
481     char *val;
482 pcg 1.1
483     #ifdef DISPLAY_IS_IP
484 pcg 1.9 /* Fixup display_name for export over pty to any interested terminal
485     * clients via "ESC[7n" (e.g. shells). Note we use the pure IP number
486     * (for the first non-loopback interface) that we get from
487 pcg 1.26 * rxvt_network_display (). This is more "name-resolution-portable", if you
488 pcg 1.9 * will, and probably allows for faster x-client startup if your name
489     * server is beyond a slow link or overloaded at client startup. Of
490     * course that only helps the shell's child processes, not us.
491     *
492     * Giving out the display_name also affords a potential security hole
493     */
494 pcg 1.14 val = rxvt_network_display (rs[Rs_display_name]);
495     rs[Rs_display_name] = (const char *)val;
496    
497 pcg 1.9 if (val == NULL)
498 pcg 1.4 #endif /* DISPLAY_IS_IP */
499 root 1.169 val = XDisplayString (dpy);
500 pcg 1.9
501 pcg 1.14 if (rs[Rs_display_name] == NULL)
502     rs[Rs_display_name] = val; /* use broken `:0' value */
503 pcg 1.9
504 root 1.79 i = strlen (val);
505 pcg 1.26 env_display = (char *)rxvt_malloc ((i + 9) * sizeof (char));
506 pcg 1.9
507 pcg 1.14 sprintf (env_display, "DISPLAY=%s", val);
508 pcg 1.9
509 root 1.155 sprintf (env_windowid, "WINDOWID=%lu", (unsigned long)parent[0]);
510 pcg 1.9
511     /* add entries to the environment:
512     * @ DISPLAY: in case we started with -display
513     * @ WINDOWID: X window id number of the window
514     * @ COLORTERM: terminal sub-name and also indicates its color
515     * @ TERM: terminal name
516     * @ TERMINFO: path to terminfo directory
517 pcg 1.27 * @ COLORFGBG: fg;bg color codes
518 pcg 1.9 */
519 pcg 1.14 putenv (env_display);
520     putenv (env_windowid);
521 root 1.155
522 pcg 1.27 if (env_colorfgbg)
523     putenv (env_colorfgbg);
524 pcg 1.14
525 pcg 1.1 #ifdef RXVT_TERMINFO
526 pcg 1.14 putenv ("TERMINFO=" RXVT_TERMINFO);
527 pcg 1.1 #endif
528 pcg 1.9
529 root 1.156 if (depth <= 2)
530 pcg 1.14 putenv ("COLORTERM=" COLORTERMENV "-mono");
531 pcg 1.9 else
532 pcg 1.14 putenv ("COLORTERM=" COLORTERMENVFULL);
533    
534     if (rs[Rs_term_name] != NULL)
535 pcg 1.9 {
536 root 1.79 env_term = (char *)rxvt_malloc ((strlen (rs[Rs_term_name]) + 6) * sizeof (char));
537 pcg 1.14 sprintf (env_term, "TERM=%s", rs[Rs_term_name]);
538     putenv (env_term);
539 pcg 1.9 }
540     else
541 pcg 1.14 putenv ("TERM=" TERMENV);
542 pcg 1.1
543     #ifdef HAVE_UNSETENV
544 pcg 1.9 /* avoid passing old settings and confusing term size */
545 pcg 1.14 unsetenv ("LINES");
546     unsetenv ("COLUMNS");
547     unsetenv ("TERMCAP"); /* terminfo should be okay */
548 pcg 1.4 #endif /* HAVE_UNSETENV */
549 pcg 1.1 }
550    
551     /*----------------------------------------------------------------------*/
552     /*
553     * This is more or less stolen straight from XFree86 xterm.
554     * This should support all European type languages.
555     */
556     void
557 pcg 1.15 rxvt_term::set_locale (const char *locale)
558     {
559 root 1.140 set_environ (envv);
560 root 1.137
561 pcg 1.15 #if HAVE_XSETLOCALE || HAVE_SETLOCALE
562     free (this->locale);
563 root 1.57 this->locale = setlocale (LC_CTYPE, locale);
564    
565     if (!this->locale)
566     {
567 root 1.79 if (*locale)
568     {
569 root 1.137 rxvt_warn ("unable to set locale \"%s\", using C locale instead.\n", locale);
570     setlocale (LC_CTYPE, "C");
571 root 1.79 }
572     else
573     rxvt_warn ("default locale unavailable, check LC_* and LANG variables. Continuing.\n");
574    
575 root 1.137 this->locale = "C";
576 root 1.57 }
577    
578 root 1.79
579 root 1.57 this->locale = rxvt_strdup (this->locale);
580 pcg 1.29 SET_LOCALE (this->locale);
581 pcg 1.28 mbstate.reset ();
582 pcg 1.15 #endif
583 root 1.96
584 pcg 1.15 #if HAVE_NL_LANGINFO
585 root 1.96 char *codeset = strdup (nl_langinfo (CODESET));
586 root 1.105 // /^UTF.?8/i
587     enc_utf8 = (codeset[0] == 'U' || codeset[0] == 'u')
588     && (codeset[1] == 'T' || codeset[1] == 't')
589     && (codeset[2] == 'F' || codeset[2] == 'f')
590     && (codeset[3] == '8' || codeset[4] == '8');
591 root 1.96 free (codeset);
592 pcg 1.15 #else
593 root 1.96 enc_utf8 = 0;
594 pcg 1.15 #endif
595     }
596    
597     void
598 pcg 1.14 rxvt_term::init_xlocale ()
599 pcg 1.1 {
600 root 1.140 set_environ (envv);
601 root 1.137
602 pcg 1.1 #ifdef USE_XIM
603 pcg 1.14 if (!locale)
604 pcg 1.45 rxvt_warn ("setting locale failed, working without locale support.\n");
605 pcg 1.9 else
606     {
607 root 1.97 set_string_property (xa[XA_WM_LOCALE_NAME], locale);
608 pcg 1.9
609 pcg 1.14 if (!XSupportsLocale ())
610 pcg 1.9 {
611 root 1.92 rxvt_warn ("the locale is not supported by Xlib, working without locale support.\n");
612 pcg 1.9 return;
613 pcg 1.4 }
614 pcg 1.10
615 pcg 1.25 im_ev.start (display);
616 pcg 1.4
617 pcg 1.25 /* see if we can connect already */
618     im_cb ();
619 pcg 1.1 }
620     #endif
621     }
622    
623     /*----------------------------------------------------------------------*/
624     void
625 pcg 1.26 rxvt_term::init_command (const char *const *argv)
626 pcg 1.1 {
627 pcg 1.4 /*
628     * Initialize the command connection.
629     * This should be called after the X server connection is established.
630     */
631 pcg 1.1
632     #ifdef META8_OPTION
633 root 1.182 meta_char = option (Opt_meta8) ? 0x80 : C0_ESC;
634 pcg 1.14 #endif
635 pcg 1.9
636 pcg 1.20 get_ourmods ();
637 pcg 1.4
638 root 1.182 if (!option (Opt_scrollTtyOutput))
639 root 1.79 priv_modes |= PrivMode_TtyOutputInh;
640 root 1.182 if (option (Opt_scrollTtyKeypress))
641 root 1.79 priv_modes |= PrivMode_Keypress;
642 root 1.182 if (!option (Opt_jumpScroll))
643 root 1.79 priv_modes |= PrivMode_smoothScroll;
644 pcg 1.4
645 pcg 1.1 #ifndef NO_BACKSPACE_KEY
646 root 1.79 if (strcmp (key_backspace, "DEC") == 0)
647     priv_modes |= PrivMode_HaveBackSpace;
648 pcg 1.14 #endif
649 pcg 1.9
650     /* add value for scrollBar */
651 root 1.143 if (scrollBar.state)
652 pcg 1.4 {
653 root 1.79 priv_modes |= PrivMode_scrollBar;
654 pcg 1.14 SavedModes |= PrivMode_scrollBar;
655 pcg 1.4 }
656 root 1.110
657 root 1.70 run_command (argv);
658 pcg 1.1 }
659    
660     /*----------------------------------------------------------------------*/
661     void
662 pcg 1.20 rxvt_term::Get_Colours ()
663 pcg 1.1 {
664 pcg 1.14 int i;
665 pcg 1.1
666 root 1.65 #ifdef OFF_FOCUS_FADING
667 root 1.79 pix_colors = pix_colors_focused;
668 root 1.65 #endif
669    
670 root 1.156 for (i = 0; i < (depth <= 2 ? 2 : NRS_COLORS); i++)
671 pcg 1.9 {
672 root 1.164 const char *name = rs[Rs_color + i];
673 pcg 1.1
674 root 1.164 if (!name)
675 pcg 1.9 continue;
676 pcg 1.1
677 root 1.164 rxvt_color xcol;
678    
679     if (!set_color (xcol, name))
680 pcg 1.9 {
681 pcg 1.1 #ifndef XTERM_REVERSE_VIDEO
682 root 1.182 if (i < 2 && option (Opt_reverseVideo))
683 root 1.164 name = def_colorName [1 - i];
684 pcg 1.9 else
685     #endif
686 root 1.164 name = def_colorName [i];
687 pcg 1.9
688 root 1.164 if (!name)
689 pcg 1.9 continue;
690 pcg 1.14
691 root 1.164 if (!set_color (xcol, name))
692 pcg 1.9 {
693     switch (i)
694     {
695 pcg 1.23 case Color_fg:
696     case Color_bg:
697 root 1.160 rxvt_warn ("unable to get foreground/background colour, continuing.\n");
698 root 1.164 name = "";
699 pcg 1.23 break;
700 pcg 1.1 #ifndef NO_CURSORCOLOR
701 pcg 1.23 case Color_cursor2:
702 root 1.164 #endif
703 pcg 1.49 case Color_pointer_fg:
704 root 1.164 name = rs[Rs_color + Color_fg];
705 root 1.168 xcol.set (this, name);
706 pcg 1.23 break;
707     default:
708 root 1.164 name = rs[Rs_color + Color_bg];
709 root 1.168 xcol.set (this, name);
710 pcg 1.23 break;
711 pcg 1.4 }
712     }
713     }
714 pcg 1.14
715 root 1.79 pix_colors[i] = xcol;
716 root 1.164 rs[Rs_color + i] = name;
717 root 1.119 }
718    
719 root 1.156 if (depth <= 2)
720 pcg 1.49 {
721 root 1.168 if (!rs[Rs_color + Color_pointer_fg]) alias_color (Color_pointer_fg, Color_fg);
722     if (!rs[Rs_color + Color_pointer_bg]) alias_color (Color_pointer_bg, Color_bg);
723     if (!rs[Rs_color + Color_border] ) alias_color (Color_border, Color_fg);
724 pcg 1.49 }
725 pcg 1.1
726 pcg 1.9 /*
727 root 1.143 * get scrollBar shadow colors
728 pcg 1.9 *
729     * The calculations of topShadow/bottomShadow values are adapted
730     * from the fvwm window manager.
731     */
732 pcg 1.1 #ifdef KEEP_SCROLLCOLOR
733 root 1.156 if (depth <= 2)
734 root 1.118 {
735     /* Monochrome */
736 root 1.168 alias_color (Color_scroll, Color_fg);
737     alias_color (Color_topShadow, Color_bg);
738     alias_color (Color_bottomShadow, Color_bg);
739 pcg 1.9 }
740     else
741     {
742 root 1.168 pix_colors [Color_scroll].fade (this, 50, pix_colors [Color_bottomShadow]);
743 pcg 1.1
744 root 1.168 rgba cscroll;
745     pix_colors [Color_scroll].get (cscroll);
746 pcg 1.1
747 pcg 1.9 /* topShadowColor */
748 root 1.168 if (!pix_colors[Color_topShadow].set (this,
749     rgba (
750     min ((int)rgba::MAX_CC, max (cscroll.r / 5, cscroll.r) * 7 / 5),
751     min ((int)rgba::MAX_CC, max (cscroll.g / 5, cscroll.g) * 7 / 5),
752     min ((int)rgba::MAX_CC, max (cscroll.b / 5, cscroll.b) * 7 / 5),
753     cscroll.a)
754     ))
755     alias_color (Color_topShadow, Color_White);
756 pcg 1.1 }
757 pcg 1.4 #endif /* KEEP_SCROLLCOLOR */
758 root 1.168
759     #ifdef OFF_FOCUS_FADING
760 root 1.174 for (i = 0; i < (depth <= 2 ? 2 : NRS_COLORS); i++)
761     update_fade_color (i);
762 root 1.168 #endif
763 pcg 1.1 }
764    
765     /*----------------------------------------------------------------------*/
766     /* color aliases, fg/bg bright-bold */
767     void
768 pcg 1.26 rxvt_term::color_aliases (int idx)
769 pcg 1.1 {
770 pcg 1.26 if (rs[Rs_color + idx] && isdigit (* (rs[Rs_color + idx])))
771 pcg 1.9 {
772 pcg 1.14 int i = atoi (rs[Rs_color + idx]);
773 pcg 1.1
774 pcg 1.9 if (i >= 8 && i <= 15)
775     { /* bright colors */
776     i -= 8;
777 pcg 1.14 rs[Rs_color + idx] = rs[Rs_color + minBrightCOLOR + i];
778 pcg 1.9 return;
779 pcg 1.17 }
780 pcg 1.9
781     if (i >= 0 && i <= 7) /* normal colors */
782 pcg 1.14 rs[Rs_color + idx] = rs[Rs_color + minCOLOR + i];
783 pcg 1.1 }
784     }
785    
786     /*----------------------------------------------------------------------*/
787     /*
788     * Probe the modifier keymap to get the Meta (Alt) and Num_Lock settings
789     * Use resource ``modifier'' to override the Meta modifier
790     */
791     void
792 pcg 1.20 rxvt_term::get_ourmods ()
793 pcg 1.1 {
794 root 1.108 int i, j, k;
795     int requestedmeta, realmeta, realalt;
796     const char *cm, *rsmod;
797 pcg 1.9 XModifierKeymap *map;
798 root 1.108 KeyCode *kc;
799 pcg 1.9 const unsigned int modmasks[] =
800     {
801     Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
802     };
803    
804     requestedmeta = realmeta = realalt = 0;
805 pcg 1.20 rsmod = rs[Rs_modifier];
806 root 1.105
807 pcg 1.9 if (rsmod
808 root 1.79 && strcasecmp (rsmod, "mod1") >= 0 && strcasecmp (rsmod, "mod5") <= 0)
809 pcg 1.9 requestedmeta = rsmod[3] - '0';
810    
811 root 1.169 map = XGetModifierMapping (dpy);
812 pcg 1.9 kc = map->modifiermap;
813 root 1.105
814 pcg 1.9 for (i = 1; i < 6; i++)
815     {
816     k = (i + 2) * map->max_keypermod; /* skip shift/lock/control */
817 root 1.105
818 pcg 1.9 for (j = map->max_keypermod; j--; k++)
819     {
820     if (kc[k] == 0)
821     break;
822 root 1.105
823 root 1.169 switch (XKeycodeToKeysym (dpy, kc[k], 0))
824 pcg 1.9 {
825 pcg 1.23 case XK_Num_Lock:
826     ModNumLockMask = modmasks[i - 1];
827 root 1.105 continue;
828    
829     case XK_ISO_Level3_Shift:
830     ModLevel3Mask = modmasks[i - 1];
831     continue;
832    
833 pcg 1.23 case XK_Meta_L:
834     case XK_Meta_R:
835     cm = "meta";
836     realmeta = i;
837     break;
838 root 1.105
839 pcg 1.23 case XK_Alt_L:
840     case XK_Alt_R:
841     cm = "alt";
842     realalt = i;
843     break;
844 root 1.105
845 pcg 1.23 case XK_Super_L:
846     case XK_Super_R:
847     cm = "super";
848     break;
849 root 1.105
850 pcg 1.23 case XK_Hyper_L:
851     case XK_Hyper_R:
852     cm = "hyper";
853     break;
854 root 1.105
855     default:
856     continue;
857 pcg 1.4 }
858 root 1.105
859 root 1.79 if (rsmod && strncasecmp (rsmod, cm, strlen (cm)) == 0)
860 pcg 1.9 requestedmeta = i;
861 pcg 1.4 }
862 pcg 1.1 }
863 root 1.105
864 pcg 1.26 XFreeModifiermap (map);
865 root 1.105
866     i = requestedmeta ? requestedmeta
867     : realmeta ? realmeta
868     : realalt ? realalt
869     : 0;
870    
871 pcg 1.9 if (i)
872 pcg 1.20 ModMetaMask = modmasks[i - 1];
873 pcg 1.1 }
874    
875     /*----------------------------------------------------------------------*/
876 pcg 1.26 /* rxvt_Create_Windows () - Open and map the window */
877 pcg 1.1 void
878 pcg 1.16 rxvt_term::create_windows (int argc, const char *const *argv)
879 pcg 1.1 {
880 pcg 1.51 XClassHint classHint;
881     XWMHints wmHint;
882 root 1.79 #if ENABLE_FRILLS
883 root 1.67 MWMHints mwmhints;
884     #endif
885 pcg 1.51 XGCValues gcvalue;
886     XSetWindowAttributes attributes;
887 root 1.114 Window top, parent;
888 pcg 1.1
889 root 1.169 dLocal (Display *, dpy);
890 pcg 1.1
891 root 1.148 /* grab colors before netscape does */
892     Get_Colours ();
893    
894     if (!set_fonts ())
895     rxvt_fatal ("unable to load base fontset, please specify a valid one using -fn, aborting.\n");
896    
897 root 1.153 parent = display->root;
898 root 1.148
899 root 1.182 attributes.override_redirect = !!option (Opt_override_redirect);
900 root 1.148
901 root 1.79 #if ENABLE_FRILLS
902 root 1.182 if (option (Opt_borderLess))
903 root 1.67 {
904 root 1.169 if (XInternAtom (dpy, "_MOTIF_WM_INFO", True) == None)
905 root 1.67 {
906     /* print_warning("Window Manager does not support MWM hints. Bypassing window manager control for borderless window.\n");*/
907 root 1.158 attributes.override_redirect = true;
908 root 1.67 mwmhints.flags = 0;
909     }
910     else
911     {
912     mwmhints.flags = MWM_HINTS_DECORATIONS;
913     mwmhints.decorations = 0;
914     }
915     }
916     else
917 root 1.116 mwmhints.flags = 0;
918 root 1.67 #endif
919    
920 root 1.112 #if ENABLE_XEMBED
921 root 1.109 if (rs[Rs_embed])
922     {
923 root 1.111 XWindowAttributes wattr;
924    
925 root 1.114 parent = strtol (rs[Rs_embed], 0, 0);
926 root 1.109
927 root 1.169 if (!XGetWindowAttributes (dpy, parent, &wattr))
928 root 1.111 rxvt_fatal ("invalid window-id specified with -embed, aborting.\n");
929 pcg 1.1
930 root 1.109 window_calc (wattr.width, wattr.height);
931 root 1.114 }
932 root 1.122 #endif
933 pcg 1.1
934 root 1.114 window_calc (0, 0);
935 root 1.109
936 root 1.114 /* sub-window placement & size in rxvt_resize_subwindows () */
937 root 1.156 attributes.background_pixel = pix_colors_focused [Color_border];
938     attributes.border_pixel = pix_colors_focused [Color_border];
939     attributes.colormap = cmap;
940 root 1.153
941 root 1.169 top = XCreateWindow (dpy, parent,
942 root 1.114 szHint.x, szHint.y,
943     szHint.width, szHint.height,
944 root 1.122 ext_bwidth,
945 root 1.156 depth, InputOutput, visual,
946 root 1.148 CWColormap | CWBackPixel | CWBorderPixel | CWOverrideRedirect,
947     &attributes);
948 root 1.109
949 root 1.122 this->parent[0] = top;
950 root 1.109
951     old_width = szHint.width;
952     old_height = szHint.height;
953 pcg 1.9
954 root 1.153 process_xterm_seq (XTerm_title, rs[Rs_title], CHAR_ST);
955 pcg 1.49 process_xterm_seq (XTerm_iconName, rs[Rs_iconName], CHAR_ST);
956 pcg 1.9
957 root 1.153 classHint.res_name = (char *)rs[Rs_name];
958 pcg 1.38 classHint.res_class = (char *)RESCLASS;
959 pcg 1.9
960 root 1.153 wmHint.flags = InputHint | StateHint | WindowGroupHint;
961     wmHint.input = True;
962 root 1.182 wmHint.initial_state = option (Opt_iconic) ? IconicState : NormalState;
963 root 1.153 wmHint.window_group = top;
964 pcg 1.9
965 root 1.169 XmbSetWMProperties (dpy, top, NULL, NULL, (char **)argv, argc,
966 root 1.115 &szHint, &wmHint, &classHint);
967 pcg 1.49
968 root 1.153 #if ENABLE_FRILLS
969     if (mwmhints.flags)
970 root 1.169 XChangeProperty (dpy, top, xa[XA_MOTIF_WM_HINTS], xa[XA_MOTIF_WM_HINTS], 32,
971 root 1.153 PropModeReplace, (unsigned char *)&mwmhints, PROP_MWM_HINTS_ELEMENTS);
972     #endif
973    
974 root 1.116 Atom protocols[] = {
975     xa[XA_WM_DELETE_WINDOW],
976     #if ENABLE_EWMH
977     xa[XA_NET_WM_PING],
978     #endif
979     };
980    
981 root 1.169 XSetWMProtocols (dpy, top, protocols, sizeof (protocols) / sizeof (protocols[0]));
982 root 1.96
983 root 1.133 #if ENABLE_FRILLS
984     if (rs[Rs_transient_for])
985 root 1.169 XSetTransientForHint (dpy, top, (Window)strtol (rs[Rs_transient_for], 0, 0));
986 root 1.133 #endif
987    
988 root 1.116 #if ENABLE_EWMH
989 pcg 1.49 long pid = getpid ();
990 root 1.93
991 root 1.169 XChangeProperty (dpy, top,
992 root 1.97 xa[XA_NET_WM_PID], XA_CARDINAL, 32,
993 pcg 1.49 PropModeReplace, (unsigned char *)&pid, 1);
994 root 1.116
995     // _NET_WM_WINDOW_TYPE is NORMAL, which is the default
996 pcg 1.49 #endif
997 pcg 1.24
998 root 1.169 XSelectInput (dpy, top,
999 root 1.65 KeyPressMask
1000 root 1.90 #if (MOUSE_WHEEL && MOUSE_SLIP_WHEELING) || ENABLE_FRILLS || ISO_14755
1001 root 1.65 | KeyReleaseMask
1002 pcg 1.1 #endif
1003 root 1.65 | FocusChangeMask | VisibilityChangeMask
1004 root 1.112 | ExposureMask | StructureNotifyMask);
1005    
1006 root 1.109 termwin_ev.start (display, top);
1007 pcg 1.1
1008 pcg 1.9 /* vt cursor: Black-on-White is standard, but this is more popular */
1009 root 1.169 TermWin_cursor = XCreateFontCursor (dpy, XC_xterm);
1010 pcg 1.1
1011 root 1.143 #ifdef HAVE_SCROLLBARS
1012     /* cursor scrollBar: Black-on-White */
1013 root 1.169 leftptr_cursor = XCreateFontCursor (dpy, XC_left_ptr);
1014 pcg 1.1 #endif
1015    
1016 pcg 1.9 /* the vt window */
1017 root 1.169 vt = XCreateSimpleWindow (dpy, top,
1018 root 1.153 window_vt_x, window_vt_y,
1019     width, height,
1020     0,
1021     pix_colors_focused[Color_fg],
1022     pix_colors_focused[Color_bg]);
1023 pcg 1.6
1024 pcg 1.51 attributes.bit_gravity = NorthWestGravity;
1025 root 1.169 XChangeWindowAttributes (dpy, vt, CWBitGravity, &attributes);
1026 pcg 1.51
1027     vt_emask = ExposureMask | ButtonPressMask | ButtonReleaseMask | PropertyChangeMask;
1028 pcg 1.17
1029 root 1.182 if (option (Opt_pointerBlank))
1030 pcg 1.9 vt_emask |= PointerMotionMask;
1031     else
1032 pcg 1.51 vt_emask |= Button1MotionMask | Button3MotionMask;
1033 pcg 1.9
1034 root 1.142 vt_select_input ();
1035    
1036 root 1.122 vt_ev.start (display, vt);
1037 pcg 1.1
1038     #ifdef XPM_BACKGROUND
1039 pcg 1.16 if (rs[Rs_backgroundPixmap] != NULL
1040 sasha 1.184 #ifndef HAVE_AFTERIMAGE
1041     && !OPTION (Opt_transparent)
1042     #endif
1043     )
1044 pcg 1.9 {
1045 root 1.65 const char *p = rs[Rs_backgroundPixmap];
1046 pcg 1.9
1047 root 1.79 if ((p = strchr (p, ';')) != NULL)
1048 pcg 1.9 {
1049     p++;
1050 pcg 1.20 scale_pixmap (p);
1051 pcg 1.4 }
1052 root 1.90
1053 pcg 1.20 set_bgPixmap (rs[Rs_backgroundPixmap]);
1054 root 1.90 scr_touch (true);
1055 pcg 1.1 }
1056     #endif
1057    
1058 pcg 1.9 /* graphics context for the vt window */
1059 root 1.153 gcvalue.foreground = pix_colors[Color_fg];
1060     gcvalue.background = pix_colors[Color_bg];
1061 root 1.170 gcvalue.graphics_exposures = 0;
1062 root 1.153
1063 root 1.169 gc = XCreateGC (dpy, vt,
1064 root 1.153 GCForeground | GCBackground | GCGraphicsExposures,
1065     &gcvalue);
1066 pcg 1.1
1067 root 1.156 drawable = new rxvt_drawable (this, vt);
1068 pcg 1.35
1069 root 1.143 #ifdef RXVT_SCROLLBAR
1070 root 1.79 gcvalue.foreground = pix_colors[Color_topShadow];
1071 root 1.169 topShadowGC = XCreateGC (dpy, vt, GCForeground, &gcvalue);
1072 root 1.79 gcvalue.foreground = pix_colors[Color_bottomShadow];
1073 root 1.169 botShadowGC = XCreateGC (dpy, vt, GCForeground, &gcvalue);
1074 root 1.156 gcvalue.foreground = pix_colors[ (depth <= 2 ? Color_fg : Color_scroll)];
1075 root 1.169 scrollbarGC = XCreateGC (dpy, vt, GCForeground, &gcvalue);
1076 pcg 1.1 #endif
1077 root 1.65
1078     #ifdef OFF_FOCUS_FADING
1079     // initially we are in unfocused state
1080     if (rs[Rs_fade])
1081 root 1.79 pix_colors = pix_colors_unfocused;
1082 pcg 1.1 #endif
1083 root 1.90
1084 root 1.113 pointer_unblank ();
1085 root 1.90 scr_recolour ();
1086 pcg 1.1 }
1087    
1088     /* ------------------------------------------------------------------------- *
1089     * GET TTY CURRENT STATE *
1090     * ------------------------------------------------------------------------- */
1091     void
1092 pcg 1.26 rxvt_get_ttymode (ttymode_t *tio, int erase)
1093 pcg 1.1 {
1094 pcg 1.9 /*
1095     * standard System V termios interface
1096     */
1097 pcg 1.26 if (GET_TERMIOS (STDIN_FILENO, tio) < 0)
1098 pcg 1.9 {
1099 root 1.126 // return error - use system defaults,
1100     // where possible, and zero elsewhere
1101     memset (tio, 0, sizeof (ttymode_t));
1102    
1103 pcg 1.9 tio->c_cc[VINTR] = CINTR;
1104     tio->c_cc[VQUIT] = CQUIT;
1105     tio->c_cc[VERASE] = CERASE;
1106 root 1.126 #ifdef VERASE2
1107     tio->c_cc[VERASE2] = CERASE2;
1108     #endif
1109 pcg 1.9 tio->c_cc[VKILL] = CKILL;
1110     tio->c_cc[VSTART] = CSTART;
1111     tio->c_cc[VSTOP] = CSTOP;
1112     tio->c_cc[VSUSP] = CSUSP;
1113 pcg 1.1 # ifdef VDSUSP
1114 pcg 1.9 tio->c_cc[VDSUSP] = CDSUSP;
1115 pcg 1.1 # endif
1116     # ifdef VREPRINT
1117 pcg 1.9 tio->c_cc[VREPRINT] = CRPRNT;
1118 pcg 1.1 # endif
1119     # ifdef VDISCRD
1120 pcg 1.9 tio->c_cc[VDISCRD] = CFLUSH;
1121 pcg 1.1 # endif
1122     # ifdef VWERSE
1123 pcg 1.9 tio->c_cc[VWERSE] = CWERASE;
1124 pcg 1.1 # endif
1125     # ifdef VLNEXT
1126 pcg 1.9 tio->c_cc[VLNEXT] = CLNEXT;
1127 pcg 1.1 # endif
1128 root 1.120 }
1129 pcg 1.9
1130     tio->c_cc[VEOF] = CEOF;
1131     tio->c_cc[VEOL] = VDISABLE;
1132 pcg 1.1 # ifdef VEOL2
1133 pcg 1.9 tio->c_cc[VEOL2] = VDISABLE;
1134 pcg 1.1 # endif
1135     # ifdef VSWTC
1136 pcg 1.9 tio->c_cc[VSWTC] = VDISABLE;
1137 pcg 1.1 # endif
1138     # ifdef VSWTCH
1139 pcg 1.9 tio->c_cc[VSWTCH] = VDISABLE;
1140 pcg 1.1 # endif
1141     # if VMIN != VEOF
1142 pcg 1.9 tio->c_cc[VMIN] = 1;
1143 pcg 1.1 # endif
1144     # if VTIME != VEOL
1145 pcg 1.9 tio->c_cc[VTIME] = 0;
1146 pcg 1.1 # endif
1147    
1148 pcg 1.9 if (erase != -1)
1149     tio->c_cc[VERASE] = (char)erase;
1150    
1151     /* input modes */
1152     tio->c_iflag = (BRKINT | IGNPAR | ICRNL
1153 pcg 1.1 # ifdef IMAXBEL
1154 pcg 1.9 | IMAXBEL
1155 pcg 1.1 # endif
1156 pcg 1.9 | IXON);
1157 pcg 1.1
1158 pcg 1.9 /* output modes */
1159     tio->c_oflag = (OPOST | ONLCR);
1160 pcg 1.1
1161 pcg 1.9 /* control modes */
1162     tio->c_cflag = (CS8 | CREAD);
1163 pcg 1.1
1164 pcg 1.9 /* line discipline modes */
1165     tio->c_lflag = (ISIG | ICANON | IEXTEN | ECHO
1166 pcg 1.1 # if defined (ECHOCTL) && defined (ECHOKE)
1167 pcg 1.9 | ECHOCTL | ECHOKE
1168 pcg 1.1 # endif
1169 pcg 1.9 | ECHOE | ECHOK);
1170 pcg 1.1
1171 pcg 1.9 /*
1172     * Debugging
1173     */
1174 pcg 1.1 #ifdef DEBUG_TTYMODE
1175     #ifdef HAVE_TERMIOS_H
1176 pcg 1.9 /* c_iflag bits */
1177 pcg 1.26 fprintf (stderr, "Input flags\n");
1178 pcg 1.1
1179 pcg 1.9 /* cpp token stringize doesn't work on all machines <sigh> */
1180 pcg 1.4 # define FOO(flag,name) \
1181     if ((tio->c_iflag) & flag) \
1182     fprintf (stderr, "%s ", name)
1183 pcg 1.1
1184 pcg 1.9 /* c_iflag bits */
1185 pcg 1.26 FOO (IGNBRK, "IGNBRK");
1186     FOO (BRKINT, "BRKINT");
1187     FOO (IGNPAR, "IGNPAR");
1188     FOO (PARMRK, "PARMRK");
1189     FOO (INPCK, "INPCK");
1190     FOO (ISTRIP, "ISTRIP");
1191     FOO (INLCR, "INLCR");
1192     FOO (IGNCR, "IGNCR");
1193     FOO (ICRNL, "ICRNL");
1194     FOO (IXON, "IXON");
1195     FOO (IXOFF, "IXOFF");
1196 pcg 1.1 # ifdef IUCLC
1197 pcg 1.26 FOO (IUCLC, "IUCLC");
1198 pcg 1.1 # endif
1199     # ifdef IXANY
1200 pcg 1.26 FOO (IXANY, "IXANY");
1201 pcg 1.1 # endif
1202     # ifdef IMAXBEL
1203 pcg 1.26 FOO (IMAXBEL, "IMAXBEL");
1204 pcg 1.1 # endif
1205 pcg 1.9
1206 pcg 1.26 fprintf (stderr, "\n");
1207 pcg 1.1
1208     # undef FOO
1209 pcg 1.4 # define FOO(entry, name) \
1210 pcg 1.26 fprintf (stderr, "%-8s = %#04o\n", name, tio->c_cc [entry])
1211 pcg 1.1
1212 pcg 1.26 FOO (VINTR, "VINTR");
1213     FOO (VQUIT, "VQUIT");
1214     FOO (VERASE, "VERASE");
1215     FOO (VKILL, "VKILL");
1216     FOO (VEOF, "VEOF");
1217     FOO (VEOL, "VEOL");
1218 pcg 1.1 # ifdef VEOL2
1219 pcg 1.26 FOO (VEOL2, "VEOL2");
1220 pcg 1.1 # endif
1221     # ifdef VSWTC
1222 pcg 1.26 FOO (VSWTC, "VSWTC");
1223 pcg 1.1 # endif
1224     # ifdef VSWTCH
1225 pcg 1.26 FOO (VSWTCH, "VSWTCH");
1226 pcg 1.1 # endif
1227 pcg 1.26 FOO (VSTART, "VSTART");
1228     FOO (VSTOP, "VSTOP");
1229     FOO (VSUSP, "VSUSP");
1230 pcg 1.1 # ifdef VDSUSP
1231 pcg 1.26 FOO (VDSUSP, "VDSUSP");
1232 pcg 1.1 # endif
1233     # ifdef VREPRINT
1234 pcg 1.26 FOO (VREPRINT, "VREPRINT");
1235 pcg 1.1 # endif
1236     # ifdef VDISCRD
1237 pcg 1.26 FOO (VDISCRD, "VDISCRD");
1238 pcg 1.1 # endif
1239     # ifdef VWERSE
1240 pcg 1.26 FOO (VWERSE, "VWERSE");
1241 pcg 1.1 # endif
1242     # ifdef VLNEXT
1243 pcg 1.26 FOO (VLNEXT, "VLNEXT");
1244 pcg 1.1 # endif
1245 pcg 1.9
1246 pcg 1.26 fprintf (stderr, "\n");
1247 pcg 1.1 # undef FOO
1248 pcg 1.4 # endif /* HAVE_TERMIOS_H */
1249     #endif /* DEBUG_TTYMODE */
1250 pcg 1.1 }
1251    
1252 root 1.79 /*----------------------------------------------------------------------*/
1253     /*
1254     * Run the command in a subprocess and return a file descriptor for the
1255     * master end of the pseudo-teletype pair with the command talking to
1256     * the slave.
1257     */
1258     void
1259     rxvt_term::run_command (const char *const *argv)
1260     {
1261 root 1.110 #if ENABLE_FRILLS
1262     if (rs[Rs_pty_fd])
1263     {
1264 root 1.145 pty->pty = atoi (rs[Rs_pty_fd]);
1265 root 1.127
1266 root 1.145 if (pty->pty >= 0)
1267 root 1.132 {
1268     if (getfd_hook)
1269 root 1.145 pty->pty = (*getfd_hook) (pty->pty);
1270 root 1.127
1271 root 1.145 if (pty->pty < 0 || fcntl (pty->pty, F_SETFL, O_NONBLOCK))
1272 root 1.132 rxvt_fatal ("unusable pty-fd filehandle, aborting.\n");
1273     }
1274 root 1.110 }
1275     else
1276     #endif
1277 root 1.145 if (!pty->get ())
1278 root 1.110 rxvt_fatal ("can't initialize pseudo-tty, aborting.\n");
1279 root 1.79
1280 root 1.105 int er;
1281    
1282 root 1.79 #ifndef NO_BACKSPACE_KEY
1283     if (key_backspace[0] && !key_backspace[1])
1284     er = key_backspace[0];
1285     else if (strcmp (key_backspace, "DEC") == 0)
1286     er = '\177'; /* the initial state anyway */
1287     else
1288     #endif
1289     er = -1;
1290    
1291     rxvt_get_ttymode (&tio, er);
1292 root 1.179 SET_TERMIOS (pty->tty, &tio); /* init terminal attributes */
1293 root 1.175 pty->set_utf8_mode (enc_utf8);
1294    
1295     /* set initial window size */
1296     tt_winch ();
1297 root 1.79
1298 root 1.110 #if ENABLE_FRILLS
1299     if (rs[Rs_pty_fd])
1300     return;
1301     #endif
1302    
1303 root 1.79 /* spin off the command interpreter */
1304     switch (cmd_pid = fork ())
1305     {
1306     case -1:
1307 root 1.110 {
1308     cmd_pid = 0;
1309     rxvt_fatal ("can't fork, aborting.\n");
1310     }
1311 root 1.79 case 0:
1312     init_env ();
1313    
1314 root 1.145 if (!pty->make_controlling_tty ())
1315 root 1.79 fprintf (stderr, "%s: could not obtain control of tty.", RESNAME);
1316     else
1317     {
1318     /* Reopen stdin, stdout and stderr over the tty file descriptor */
1319 root 1.145 dup2 (pty->tty, STDIN_FILENO);
1320     dup2 (pty->tty, STDOUT_FILENO);
1321     dup2 (pty->tty, STDERR_FILENO);
1322 root 1.79
1323     // close all our file handles that we do no longer need
1324     for (rxvt_term **t = termlist.begin (); t < termlist.end (); t++)
1325     {
1326 root 1.145 if ((*t)->pty->pty > 2) close ((*t)->pty->pty);
1327     if ((*t)->pty->tty > 2) close ((*t)->pty->tty);
1328 root 1.79 }
1329    
1330     run_child (argv);
1331     fprintf (stderr, "%s: unable to exec child.", RESNAME);
1332     }
1333    
1334     _exit (EXIT_FAILURE);
1335    
1336     default:
1337 root 1.182 if (!option (Opt_utmpInhibit))
1338     pty->login (cmd_pid, option (Opt_loginShell), rs[Rs_display_name]);
1339 root 1.79
1340 root 1.145 pty->close_tty ();
1341 root 1.149
1342     child_ev.start (cmd_pid);
1343    
1344     HOOK_INVOKE ((this, HOOK_CHILD_START, DT_INT, cmd_pid, DT_END));
1345 root 1.79 break;
1346     }
1347     }
1348    
1349     /* ------------------------------------------------------------------------- *
1350     * CHILD PROCESS OPERATIONS *
1351     * ------------------------------------------------------------------------- */
1352     /*
1353     * The only open file descriptor is the slave tty - so no error messages.
1354     * returns are fatal
1355     */
1356     int
1357     rxvt_term::run_child (const char *const *argv)
1358     {
1359     char *login;
1360    
1361 root 1.182 if (option (Opt_console))
1362 root 1.79 { /* be virtual console, fail silently */
1363     #ifdef TIOCCONS
1364     unsigned int on = 1;
1365    
1366     ioctl (STDIN_FILENO, TIOCCONS, &on);
1367     #elif defined (SRIOCSREDIR)
1368     int fd;
1369    
1370     fd = open (CONSOLE, O_WRONLY, 0);
1371     if (fd >= 0)
1372     if (ioctl (fd, SRIOCSREDIR, NULL) < 0)
1373     close (fd);
1374     #endif /* SRIOCSREDIR */
1375     }
1376    
1377     /* reset signals and spin off the command interpreter */
1378     signal (SIGINT, SIG_DFL);
1379     signal (SIGQUIT, SIG_DFL);
1380     signal (SIGCHLD, SIG_DFL);
1381     signal (SIGHUP, SIG_DFL);
1382     signal (SIGPIPE, SIG_DFL);
1383     /*
1384     * mimick login's behavior by disabling the job control signals
1385     * a shell that wants them can turn them back on
1386     */
1387     #ifdef SIGTSTP
1388     signal (SIGTSTP, SIG_IGN);
1389     signal (SIGTTIN, SIG_IGN);
1390     signal (SIGTTOU, SIG_IGN);
1391     #endif /* SIGTSTP */
1392    
1393     // unblock signals (signals are blocked by iom.C
1394     sigset_t ss;
1395     sigemptyset (&ss);
1396     sigprocmask (SIG_SETMASK, &ss, 0);
1397    
1398     /* command interpreter path */
1399     if (argv != NULL)
1400     {
1401     # ifdef DEBUG_CMD
1402     int i;
1403    
1404     for (i = 0; argv[i]; i++)
1405     fprintf (stderr, "argv [%d] = \"%s\"\n", i, argv[i]);
1406     # endif
1407    
1408     execvp (argv[0], (char *const *)argv);
1409     /* no error message: STDERR is closed! */
1410     }
1411     else
1412     {
1413 root 1.137 const char *argv0, *shell;
1414 root 1.79
1415     if ((shell = getenv ("SHELL")) == NULL || *shell == '\0')
1416     shell = "/bin/sh";
1417    
1418     argv0 = (const char *)rxvt_r_basename (shell);
1419    
1420 root 1.182 if (option (Opt_loginShell))
1421 root 1.79 {
1422     login = (char *)rxvt_malloc ((strlen (argv0) + 2) * sizeof (char));
1423    
1424     login[0] = '-';
1425     strcpy (&login[1], argv0);
1426     argv0 = login;
1427     }
1428 root 1.137
1429 root 1.79 execlp (shell, argv0, NULL);
1430     /* no error message: STDERR is closed! */
1431     }
1432    
1433     return -1;
1434     }
1435    
1436 pcg 1.1 /*----------------------- end-of-file (C source) -----------------------*/