ViewVC Help
View File | Revision Log | Show Annotations | Download File
/cvs/rxvt-unicode/src/init.C
Revision: 1.346
Committed: Tue Jun 21 12:03:56 2016 UTC (7 years, 11 months ago) by sf-exg
Content type: text/plain
Branch: MAIN
Changes since 1.345: +35 -0 lines
Log Message:
24-bit direct color support (patch by Fengguang Wu)

Support directly setting RGB fg/bg colors via ISO-8613-3 24-bit
ANSI color escapes:

  ESC[38;2;<r>;<g>;<b>m Select RGB foreground color
  ESC[48;2;<r>;<g>;<b>m Select RGB background color

The killer applications for me are vim in tmux. It'll not only modernize
their look and feeling, but also bring more eye friendly color schemes.
Very helpful for long time programmers.

To avoid memory overheads and keep the patch non-intrusive, it takes the
approach to adapt the nearest color in an hidden 6x6x4 (88-color mode)
or 7x7x5 (256-color mode) color cube to the new 24-bit RGB color.

The pros/cons are:

+) least memory footprint (close to 0)
   comparing to konsole, gnome-terminal etc. real 24-bit arrays

+) exact colors and excellent user feelings
   comparing to xterm, mlterm, etc. approximating to 256 palette

+) usable in both the existing 88/256-color modes

   Most vim GUI color schemes show up the same as gvim in rxvt-unicode's
   88-color mode, not to mention the 256-color mode. Typical applications
   only use one or two dozens of colors at the same time.

-) may not be able to show 2+ close 24-bit colors

   RGB colors close to each other will likely fall into the same slot in
   the 6x6x4 or 7x7x5 color cube. If necessary, it could be improved
   effectively by implementing some collision avoidance logic, trying to
   find empty/eldest slot in the +1/-1 r/g/b indices (ie. 3-8 neighbors).

The CPU overheads of map_rgb24_color() look ignorable: I feel no
perceptible slow down when doing vim operations in 24-bit color mode.

A micro benchmark running a test script from [1]:

% time (for i in {1..100}; do 24-bit-color.sh; done)

vanilla rxvt-unicode
====================
  2.42s user 1.88s system 31% cpu 13.555 total
  2.59s user 1.74s system 31% cpu 13.615 total
  2.46s user 1.85s system 31% cpu 13.631 total

THIS PATCH (adapt hidden color cube to 24-bit)
==============================================
  2.33s user 1.97s system 31% cpu 13.598 total
  2.46s user 1.89s system 31% cpu 13.613 total
  2.51s user 1.82s system 31% cpu 13.556 total

https://github.com/spudowiar/rxvt-unicode (real 24-bit array)
=============================================================
  2.61s user 1.75s system 31% cpu 13.721 total
  2.48s user 1.82s system 31% cpu 13.566 total
  2.60s user 1.76s system 31% cpu 13.631 total

USE_256_COLORS is defined in all the above rxvt-unicode builds.

References:

[1] True Colour (16 million colours) support in various terminal
    applications and terminals
    https://gist.github.com/XVilka/8346728

[2] https://en.wikipedia.org/wiki/ANSI_escape_code#Colors

File Contents

# User Rev Content
1 ayin 1.195 /*----------------------------------------------------------------------*
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 ayin 1.214 * Copyright (c) 1996 Chuck Blake <cblake@BBN.COM>
11     * Copyright (c) 1997 mj olesen <olesen@me.queensu.ca>
12     * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
13 pcg 1.1 * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com>
14 pcg 1.4 * - extensive modifications
15 root 1.293 * Copyright (c) 2003-2008 Marc Lehmann <schmorp@schmorp.de>
16 sf-exg 1.345 * Copyright (c) 2015 Emanuele Giaquinta <e.giaquinta@glauco.it>
17 pcg 1.1 *
18     * This program is free software; you can redistribute it and/or modify
19     * it under the terms of the GNU General Public License as published by
20 root 1.332 * the Free Software Foundation; either version 3 of the License, or
21 pcg 1.1 * (at your option) any later version.
22     *
23     * This program is distributed in the hope that it will be useful,
24     * but WITHOUT ANY WARRANTY; without even the implied warranty of
25     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
26     * GNU General Public License for more details.
27     *
28     * You should have received a copy of the GNU General Public License
29     * along with this program; if not, write to the Free Software
30     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31     *---------------------------------------------------------------------*/
32     /*
33     * Initialisation routines.
34     */
35    
36 pcg 1.4 #include "../config.h" /* NECESSARY */
37     #include "rxvt.h" /* NECESSARY */
38 root 1.105 #include "rxvtutil.h"
39 pcg 1.1 #include "init.h"
40 ayin 1.239 #include "keyboard.h"
41 pcg 1.1
42 root 1.125 #include <limits>
43    
44 sf-exg 1.319 #include <signal.h>
45 pcg 1.1
46 ayin 1.226 #include <fcntl.h>
47    
48 sf-exg 1.344 #ifdef HAVE_XMU
49     # include <X11/Xmu/CurUtil.h>
50     #endif
51    
52 ayin 1.218 #ifdef HAVE_XSETLOCALE
53     # define X_LOCALE
54     # include <X11/Xlocale.h>
55     #else
56 sf-exg 1.320 # include <locale.h>
57 ayin 1.218 #endif
58    
59     #ifdef HAVE_NL_LANGINFO
60     # include <langinfo.h>
61     #endif
62    
63 mikachu 1.301 #ifdef HAVE_STARTUP_NOTIFICATION
64     # define SN_API_NOT_YET_FROZEN
65     # include <libsn/sn-launchee.h>
66     #endif
67    
68 ayin 1.214 #ifdef DISPLAY_IS_IP
69     /* On Solaris link with -lsocket and -lnsl */
70     #include <sys/types.h>
71     #include <sys/socket.h>
72    
73 sf-exg 1.290 /* these next two are probably only on Sun (not Solaris) */
74 ayin 1.214 #ifdef HAVE_SYS_SOCKIO_H
75     #include <sys/sockio.h>
76     #endif
77 sf-exg 1.290 #ifdef HAVE_SYS_BYTEORDER_H
78     #include <sys/byteorder.h>
79     #endif
80 ayin 1.214
81     #include <netinet/in.h>
82     #include <arpa/inet.h>
83     #include <net/if.h>
84     #include <net/if_arp.h>
85    
86 root 1.324 static char * ecb_cold
87 ayin 1.214 rxvt_network_display (const char *display)
88     {
89     char buffer[1024], *rval = NULL;
90     struct ifconf ifc;
91     struct ifreq *ifr;
92     int i, skfd;
93    
94     if (display[0] != ':' && strncmp (display, "unix:", 5))
95     return (char *) display; /* nothing to do */
96    
97     ifc.ifc_len = sizeof (buffer); /* Get names of all ifaces */
98     ifc.ifc_buf = buffer;
99    
100     if ((skfd = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
101     {
102     perror ("socket");
103     return NULL;
104     }
105    
106     if (ioctl (skfd, SIOCGIFCONF, &ifc) < 0)
107     {
108     perror ("SIOCGIFCONF");
109     close (skfd);
110     return NULL;
111     }
112    
113     for (i = 0, ifr = ifc.ifc_req;
114     i < (ifc.ifc_len / sizeof (struct ifreq));
115     i++, ifr++)
116     {
117     struct ifreq ifr2;
118    
119     strcpy (ifr2.ifr_name, ifr->ifr_name);
120    
121     if (ioctl (skfd, SIOCGIFADDR, &ifr2) >= 0)
122     {
123     unsigned long addr;
124     struct sockaddr_in *p_addr;
125    
126     p_addr = (struct sockaddr_in *) &ifr2.ifr_addr;
127     addr = htonl ((unsigned long)p_addr->sin_addr.s_addr);
128    
129     /*
130     * not "0.0.0.0" or "127.0.0.1" - so format the address
131     */
132     if (addr && addr != 0x7F000001)
133     {
134     char *colon = strchr (display, ':');
135    
136     if (colon == NULL)
137     colon = ":0.0";
138    
139     rval = rxvt_malloc (strlen (colon) + 16);
140     sprintf (rval, "%d.%d.%d.%d%s",
141     (int) ((addr >> 030) & 0xFF),
142     (int) ((addr >> 020) & 0xFF),
143     (int) ((addr >> 010) & 0xFF),
144     (int) (addr & 0xFF), colon);
145     break;
146     }
147     }
148     }
149    
150     close (skfd);
151    
152     return rval;
153     }
154     #endif
155    
156 sf-exg 1.346 #define NULL_5 \
157     NULL, \
158     NULL, \
159     NULL, \
160     NULL, \
161     NULL,
162    
163     #define NULL_10 \
164     NULL_5 \
165     NULL_5
166    
167     #define NULL_40 \
168     NULL_10 \
169     NULL_10 \
170     NULL_10 \
171     NULL_10
172    
173     #define NULL_50 \
174     NULL_40 \
175     NULL_10
176    
177     #define NULL_100 \
178     NULL_50 \
179     NULL_50
180    
181 sf-exg 1.286 static const char *const def_colorName[] =
182 pcg 1.9 {
183 pcg 1.1 COLOR_FOREGROUND,
184     COLOR_BACKGROUND,
185 pcg 1.9 /* low-intensity colors */
186 root 1.159 "rgb:00/00/00", // 0: black (Black)
187     "rgb:cd/00/00", // 1: red (Red3)
188     "rgb:00/cd/00", // 2: green (Green3)
189 root 1.183 "rgb:cd/cd/00", // 3: yellow (Yellow3)
190 root 1.159 "rgb:00/00/cd", // 4: blue (Blue3)
191     "rgb:cd/00/cd", // 5: magenta (Magenta3)
192     "rgb:00/cd/cd", // 6: cyan (Cyan3)
193 ayin 1.221 # ifdef XTERM_COLORS
194 root 1.159 "rgb:e5/e5/e5", // 7: white (Grey90)
195 ayin 1.221 # else
196 root 1.159 "rgb:fa/eb/d7", // 7: white (AntiqueWhite)
197 pcg 1.1 # endif
198 pcg 1.9 /* high-intensity colors */
199 pcg 1.1 # ifdef XTERM_COLORS
200 root 1.159 "rgb:4d/4d/4d", // 8: bright black (Grey30)
201 pcg 1.1 # else
202 root 1.159 "rgb:40/40/40", // 8: bright black (Grey25)
203 pcg 1.1 # endif
204 root 1.159 "rgb:ff/00/00", // 1/9: bright red (Reed)
205     "rgb:00/ff/00", // 2/10: bright green (Green)
206     "rgb:ff/ff/00", // 3/11: bright yellow (Yellow)
207     "rgb:00/00/ff", // 4/12: bright blue (Blue)
208     "rgb:ff/00/ff", // 5/13: bright magenta (Magenta)
209     "rgb:00/ff/ff", // 6/14: bright cyan (Cyan)
210     "rgb:ff/ff/ff", // 7/15: bright white (White)
211 root 1.90
212 root 1.265 #if !USE_256_COLORS
213 root 1.90 // 88 xterm colours
214     "rgb:00/00/00",
215     "rgb:00/00/8b",
216     "rgb:00/00/cd",
217     "rgb:00/00/ff",
218     "rgb:00/8b/00",
219     "rgb:00/8b/8b",
220     "rgb:00/8b/cd",
221     "rgb:00/8b/ff",
222     "rgb:00/cd/00",
223     "rgb:00/cd/8b",
224     "rgb:00/cd/cd",
225     "rgb:00/cd/ff",
226     "rgb:00/ff/00",
227     "rgb:00/ff/8b",
228     "rgb:00/ff/cd",
229     "rgb:00/ff/ff",
230     "rgb:8b/00/00",
231     "rgb:8b/00/8b",
232     "rgb:8b/00/cd",
233     "rgb:8b/00/ff",
234     "rgb:8b/8b/00",
235     "rgb:8b/8b/8b",
236     "rgb:8b/8b/cd",
237     "rgb:8b/8b/ff",
238     "rgb:8b/cd/00",
239     "rgb:8b/cd/8b",
240     "rgb:8b/cd/cd",
241     "rgb:8b/cd/ff",
242     "rgb:8b/ff/00",
243     "rgb:8b/ff/8b",
244     "rgb:8b/ff/cd",
245     "rgb:8b/ff/ff",
246     "rgb:cd/00/00",
247     "rgb:cd/00/8b",
248     "rgb:cd/00/cd",
249     "rgb:cd/00/ff",
250     "rgb:cd/8b/00",
251     "rgb:cd/8b/8b",
252     "rgb:cd/8b/cd",
253     "rgb:cd/8b/ff",
254     "rgb:cd/cd/00",
255     "rgb:cd/cd/8b",
256     "rgb:cd/cd/cd",
257     "rgb:cd/cd/ff",
258     "rgb:cd/ff/00",
259     "rgb:cd/ff/8b",
260     "rgb:cd/ff/cd",
261     "rgb:cd/ff/ff",
262     "rgb:ff/00/00",
263     "rgb:ff/00/8b",
264     "rgb:ff/00/cd",
265     "rgb:ff/00/ff",
266     "rgb:ff/8b/00",
267     "rgb:ff/8b/8b",
268     "rgb:ff/8b/cd",
269     "rgb:ff/8b/ff",
270     "rgb:ff/cd/00",
271     "rgb:ff/cd/8b",
272     "rgb:ff/cd/cd",
273     "rgb:ff/cd/ff",
274     "rgb:ff/ff/00",
275     "rgb:ff/ff/8b",
276     "rgb:ff/ff/cd",
277     "rgb:ff/ff/ff",
278     "rgb:2e/2e/2e",
279     "rgb:5c/5c/5c",
280     "rgb:73/73/73",
281     "rgb:8b/8b/8b",
282     "rgb:a2/a2/a2",
283     "rgb:b9/b9/b9",
284 pcg 1.1 "rgb:d0/d0/d0",
285 root 1.90 "rgb:e7/e7/e7",
286 sf-exg 1.346 NULL_100
287     NULL_40
288     NULL,
289     NULL,
290     NULL,
291     NULL,
292 sf-exg 1.263 #else
293     // 256 xterm colours
294     "rgb:00/00/00",
295     "rgb:00/00/5f",
296     "rgb:00/00/87",
297     "rgb:00/00/af",
298     "rgb:00/00/d7",
299     "rgb:00/00/ff",
300     "rgb:00/5f/00",
301     "rgb:00/5f/5f",
302     "rgb:00/5f/87",
303     "rgb:00/5f/af",
304     "rgb:00/5f/d7",
305     "rgb:00/5f/ff",
306     "rgb:00/87/00",
307     "rgb:00/87/5f",
308     "rgb:00/87/87",
309     "rgb:00/87/af",
310     "rgb:00/87/d7",
311     "rgb:00/87/ff",
312     "rgb:00/af/00",
313     "rgb:00/af/5f",
314     "rgb:00/af/87",
315     "rgb:00/af/af",
316     "rgb:00/af/d7",
317     "rgb:00/af/ff",
318     "rgb:00/d7/00",
319     "rgb:00/d7/5f",
320     "rgb:00/d7/87",
321     "rgb:00/d7/af",
322     "rgb:00/d7/d7",
323     "rgb:00/d7/ff",
324     "rgb:00/ff/00",
325     "rgb:00/ff/5f",
326     "rgb:00/ff/87",
327     "rgb:00/ff/af",
328     "rgb:00/ff/d7",
329     "rgb:00/ff/ff",
330     "rgb:5f/00/00",
331     "rgb:5f/00/5f",
332     "rgb:5f/00/87",
333     "rgb:5f/00/af",
334     "rgb:5f/00/d7",
335     "rgb:5f/00/ff",
336     "rgb:5f/5f/00",
337     "rgb:5f/5f/5f",
338     "rgb:5f/5f/87",
339     "rgb:5f/5f/af",
340     "rgb:5f/5f/d7",
341     "rgb:5f/5f/ff",
342     "rgb:5f/87/00",
343     "rgb:5f/87/5f",
344     "rgb:5f/87/87",
345     "rgb:5f/87/af",
346     "rgb:5f/87/d7",
347     "rgb:5f/87/ff",
348     "rgb:5f/af/00",
349     "rgb:5f/af/5f",
350     "rgb:5f/af/87",
351     "rgb:5f/af/af",
352     "rgb:5f/af/d7",
353     "rgb:5f/af/ff",
354     "rgb:5f/d7/00",
355     "rgb:5f/d7/5f",
356     "rgb:5f/d7/87",
357     "rgb:5f/d7/af",
358     "rgb:5f/d7/d7",
359     "rgb:5f/d7/ff",
360     "rgb:5f/ff/00",
361     "rgb:5f/ff/5f",
362     "rgb:5f/ff/87",
363     "rgb:5f/ff/af",
364     "rgb:5f/ff/d7",
365     "rgb:5f/ff/ff",
366     "rgb:87/00/00",
367     "rgb:87/00/5f",
368     "rgb:87/00/87",
369     "rgb:87/00/af",
370     "rgb:87/00/d7",
371     "rgb:87/00/ff",
372     "rgb:87/5f/00",
373     "rgb:87/5f/5f",
374     "rgb:87/5f/87",
375     "rgb:87/5f/af",
376     "rgb:87/5f/d7",
377     "rgb:87/5f/ff",
378     "rgb:87/87/00",
379     "rgb:87/87/5f",
380     "rgb:87/87/87",
381     "rgb:87/87/af",
382     "rgb:87/87/d7",
383     "rgb:87/87/ff",
384     "rgb:87/af/00",
385     "rgb:87/af/5f",
386     "rgb:87/af/87",
387     "rgb:87/af/af",
388     "rgb:87/af/d7",
389     "rgb:87/af/ff",
390     "rgb:87/d7/00",
391     "rgb:87/d7/5f",
392     "rgb:87/d7/87",
393     "rgb:87/d7/af",
394     "rgb:87/d7/d7",
395     "rgb:87/d7/ff",
396     "rgb:87/ff/00",
397     "rgb:87/ff/5f",
398     "rgb:87/ff/87",
399     "rgb:87/ff/af",
400     "rgb:87/ff/d7",
401     "rgb:87/ff/ff",
402     "rgb:af/00/00",
403     "rgb:af/00/5f",
404     "rgb:af/00/87",
405     "rgb:af/00/af",
406     "rgb:af/00/d7",
407     "rgb:af/00/ff",
408     "rgb:af/5f/00",
409     "rgb:af/5f/5f",
410     "rgb:af/5f/87",
411     "rgb:af/5f/af",
412     "rgb:af/5f/d7",
413     "rgb:af/5f/ff",
414     "rgb:af/87/00",
415     "rgb:af/87/5f",
416     "rgb:af/87/87",
417     "rgb:af/87/af",
418     "rgb:af/87/d7",
419     "rgb:af/87/ff",
420     "rgb:af/af/00",
421     "rgb:af/af/5f",
422     "rgb:af/af/87",
423     "rgb:af/af/af",
424     "rgb:af/af/d7",
425     "rgb:af/af/ff",
426     "rgb:af/d7/00",
427     "rgb:af/d7/5f",
428     "rgb:af/d7/87",
429     "rgb:af/d7/af",
430     "rgb:af/d7/d7",
431     "rgb:af/d7/ff",
432     "rgb:af/ff/00",
433     "rgb:af/ff/5f",
434     "rgb:af/ff/87",
435     "rgb:af/ff/af",
436     "rgb:af/ff/d7",
437     "rgb:af/ff/ff",
438     "rgb:d7/00/00",
439     "rgb:d7/00/5f",
440     "rgb:d7/00/87",
441     "rgb:d7/00/af",
442     "rgb:d7/00/d7",
443     "rgb:d7/00/ff",
444     "rgb:d7/5f/00",
445     "rgb:d7/5f/5f",
446     "rgb:d7/5f/87",
447     "rgb:d7/5f/af",
448     "rgb:d7/5f/d7",
449     "rgb:d7/5f/ff",
450     "rgb:d7/87/00",
451     "rgb:d7/87/5f",
452     "rgb:d7/87/87",
453     "rgb:d7/87/af",
454     "rgb:d7/87/d7",
455     "rgb:d7/87/ff",
456     "rgb:d7/af/00",
457     "rgb:d7/af/5f",
458     "rgb:d7/af/87",
459     "rgb:d7/af/af",
460     "rgb:d7/af/d7",
461     "rgb:d7/af/ff",
462     "rgb:d7/d7/00",
463     "rgb:d7/d7/5f",
464     "rgb:d7/d7/87",
465     "rgb:d7/d7/af",
466     "rgb:d7/d7/d7",
467     "rgb:d7/d7/ff",
468     "rgb:d7/ff/00",
469     "rgb:d7/ff/5f",
470     "rgb:d7/ff/87",
471     "rgb:d7/ff/af",
472     "rgb:d7/ff/d7",
473     "rgb:d7/ff/ff",
474     "rgb:ff/00/00",
475     "rgb:ff/00/5f",
476     "rgb:ff/00/87",
477     "rgb:ff/00/af",
478     "rgb:ff/00/d7",
479     "rgb:ff/00/ff",
480     "rgb:ff/5f/00",
481     "rgb:ff/5f/5f",
482     "rgb:ff/5f/87",
483     "rgb:ff/5f/af",
484     "rgb:ff/5f/d7",
485     "rgb:ff/5f/ff",
486     "rgb:ff/87/00",
487     "rgb:ff/87/5f",
488     "rgb:ff/87/87",
489     "rgb:ff/87/af",
490     "rgb:ff/87/d7",
491     "rgb:ff/87/ff",
492     "rgb:ff/af/00",
493     "rgb:ff/af/5f",
494     "rgb:ff/af/87",
495     "rgb:ff/af/af",
496     "rgb:ff/af/d7",
497     "rgb:ff/af/ff",
498     "rgb:ff/d7/00",
499     "rgb:ff/d7/5f",
500     "rgb:ff/d7/87",
501     "rgb:ff/d7/af",
502     "rgb:ff/d7/d7",
503     "rgb:ff/d7/ff",
504     "rgb:ff/ff/00",
505     "rgb:ff/ff/5f",
506     "rgb:ff/ff/87",
507     "rgb:ff/ff/af",
508     "rgb:ff/ff/d7",
509     "rgb:ff/ff/ff",
510     "rgb:08/08/08",
511     "rgb:12/12/12",
512     "rgb:1c/1c/1c",
513     "rgb:26/26/26",
514     "rgb:30/30/30",
515     "rgb:3a/3a/3a",
516     "rgb:44/44/44",
517     "rgb:4e/4e/4e",
518     "rgb:58/58/58",
519     "rgb:62/62/62",
520     "rgb:6c/6c/6c",
521     "rgb:76/76/76",
522     "rgb:80/80/80",
523     "rgb:8a/8a/8a",
524     "rgb:94/94/94",
525     "rgb:9e/9e/9e",
526     "rgb:a8/a8/a8",
527     "rgb:b2/b2/b2",
528     "rgb:bc/bc/bc",
529     "rgb:c6/c6/c6",
530     "rgb:d0/d0/d0",
531     "rgb:da/da/da",
532     "rgb:e4/e4/e4",
533     "rgb:ee/ee/ee",
534 sf-exg 1.346 NULL_100
535     NULL_100
536     NULL_40
537     NULL_5
538 sf-exg 1.263 #endif
539 root 1.90
540 pcg 1.1 #ifndef NO_CURSORCOLOR
541     COLOR_CURSOR_BACKGROUND,
542     COLOR_CURSOR_FOREGROUND,
543 ayin 1.222 #endif /* ! NO_CURSORCOLOR */
544 pcg 1.49 NULL, /* Color_pointer_fg */
545     NULL, /* Color_pointer_bg */
546 pcg 1.4 NULL, /* Color_border */
547 pcg 1.1 #ifndef NO_BOLD_UNDERLINE_REVERSE
548 pcg 1.4 NULL, /* Color_BD */
549 root 1.90 NULL, /* Color_IT */
550 pcg 1.4 NULL, /* Color_UL */
551     NULL, /* Color_RV */
552 ayin 1.222 #endif /* ! NO_BOLD_UNDERLINE_REVERSE */
553 root 1.98 #if ENABLE_FRILLS
554     NULL, // Color_underline
555     #endif
556 pcg 1.1 #ifdef OPTION_HC
557     NULL,
558 sf-exg 1.264 NULL,
559 pcg 1.1 #endif
560     COLOR_SCROLLBAR,
561 ayin 1.245 #ifdef RXVT_SCROLLBAR
562 pcg 1.1 COLOR_SCROLLTROUGH,
563 ayin 1.245 #endif
564 sf-exg 1.330 #if BG_IMAGE_FROM_ROOT
565 root 1.57 NULL,
566     #endif
567 root 1.119 #if OFF_FOCUS_FADING
568 root 1.159 "rgb:00/00/00",
569 root 1.119 #endif
570 pcg 1.9 };
571 pcg 1.1
572 ayin 1.227 void
573 pcg 1.14 rxvt_term::init_vars ()
574 pcg 1.1 {
575 ayin 1.234 pix_colors = pix_colors_focused;
576 pcg 1.1
577 pcg 1.9 MEvent.time = CurrentTime;
578     MEvent.button = AnyButton;
579     want_refresh = 1;
580 root 1.79 priv_modes = SavedModes = PrivMode_Default;
581 root 1.122 ncol = 80;
582     nrow = 24;
583     int_bwidth = INTERNALBORDERWIDTH;
584     ext_bwidth = EXTERNALBORDERWIDTH;
585     lineSpace = LINESPACE;
586 root 1.259 letterSpace = LETTERSPACE;
587 root 1.122 saveLines = SAVELINES;
588 pcg 1.14
589 pcg 1.9 refresh_type = SLOW_REFRESH;
590    
591     oldcursor.row = oldcursor.col = -1;
592 pcg 1.14
593 root 1.182 set_option (Opt_scrollBar);
594     set_option (Opt_scrollTtyOutput);
595     set_option (Opt_jumpScroll);
596 root 1.188 set_option (Opt_skipScroll);
597 root 1.182 set_option (Opt_secondaryScreen);
598     set_option (Opt_secondaryScroll);
599     set_option (Opt_pastableTabs);
600     set_option (Opt_intensityStyles);
601 sf-exg 1.260 set_option (Opt_iso14755);
602 ayin 1.186 set_option (Opt_iso14755_52);
603 ayin 1.244 set_option (Opt_buffered);
604 pcg 1.1 }
605    
606     /*----------------------------------------------------------------------*/
607 pcg 1.14 const char **
608     rxvt_term::init_resources (int argc, const char *const *argv)
609 pcg 1.1 {
610 sf-exg 1.308 int i;
611 sf-exg 1.304 const char **cmd_argv;
612 pcg 1.9
613 ayin 1.210 rs[Rs_name] = rxvt_basename (argv[0]);
614 pcg 1.14
615 pcg 1.9 /*
616     * Open display, get options/resources and create the window
617     */
618 pcg 1.1
619 root 1.140 if ((rs[Rs_display_name] = getenv ("DISPLAY")) == NULL)
620     rs[Rs_display_name] = ":0";
621 pcg 1.1
622 sf-exg 1.308 cmd_argv = get_options (argc, argv);
623 root 1.137
624 root 1.140 if (!(display = displays.get (rs[Rs_display_name])))
625 sf-exg 1.303 rxvt_fatal ("can't open display %s, aborting.\n", rs[Rs_display_name]);
626 root 1.139
627 root 1.166 // using a local pointer decreases code size a lot
628 root 1.157 xa = display->xa;
629    
630 root 1.173 set (display);
631     extract_resources ();
632    
633 root 1.328 #if ENABLE_FRILLS
634     if (rs[Rs_visual])
635     select_visual (strtol (rs[Rs_visual], 0, 0));
636     else if (rs[Rs_depth])
637     select_depth (strtol (rs[Rs_depth], 0, 0));
638 root 1.157 #endif
639 pcg 1.1
640 root 1.166 for (int i = NUM_RESOURCES; i--; )
641     if (rs [i] == resval_undef)
642     rs [i] = 0;
643    
644 root 1.151 #if ENABLE_PERL
645     if (!rs[Rs_perl_ext_1])
646     rs[Rs_perl_ext_1] = "default";
647    
648     if ((rs[Rs_perl_ext_1] && *rs[Rs_perl_ext_1])
649     || (rs[Rs_perl_ext_2] && *rs[Rs_perl_ext_2])
650     || (rs[Rs_perl_eval] && *rs[Rs_perl_eval]))
651     {
652     rxvt_perl.init (this);
653     HOOK_INVOKE ((this, HOOK_INIT, DT_END));
654     }
655     #endif
656    
657 sf-exg 1.339 // must be called after initialising the perl interpreter as it
658     // may invoke the `on_register_command' hook
659 sf-exg 1.302 extract_keysym_resources ();
660    
661 pcg 1.9 /*
662     * set any defaults not already set
663     */
664     if (cmd_argv && cmd_argv[0])
665     {
666     if (!rs[Rs_title])
667 ayin 1.210 rs[Rs_title] = rxvt_basename (cmd_argv[0]);
668 root 1.255
669 pcg 1.9 if (!rs[Rs_iconName])
670     rs[Rs_iconName] = rs[Rs_title];
671     }
672     else
673     {
674     if (!rs[Rs_title])
675     rs[Rs_title] = rs[Rs_name];
676 root 1.255
677 pcg 1.9 if (!rs[Rs_iconName])
678     rs[Rs_iconName] = rs[Rs_name];
679 pcg 1.1 }
680 pcg 1.14
681 pcg 1.26 if (rs[Rs_saveLines] && (i = atoi (rs[Rs_saveLines])) >= 0)
682 root 1.126 saveLines = min (i, MAX_SAVELINES);
683 pcg 1.14
684 root 1.79 #if ENABLE_FRILLS
685 pcg 1.26 if (rs[Rs_int_bwidth] && (i = atoi (rs[Rs_int_bwidth])) >= 0)
686 root 1.125 int_bwidth = min (i, std::numeric_limits<int16_t>::max ());
687 root 1.124
688 pcg 1.26 if (rs[Rs_ext_bwidth] && (i = atoi (rs[Rs_ext_bwidth])) >= 0)
689 root 1.125 ext_bwidth = min (i, std::numeric_limits<int16_t>::max ());
690 root 1.124
691 pcg 1.26 if (rs[Rs_lineSpace] && (i = atoi (rs[Rs_lineSpace])) >= 0)
692 root 1.125 lineSpace = min (i, std::numeric_limits<int16_t>::max ());
693 root 1.259
694     if (rs[Rs_letterSpace])
695     letterSpace = atoi (rs[Rs_letterSpace]);
696 pcg 1.1 #endif
697    
698     #ifdef POINTER_BLANK
699 pcg 1.26 if (rs[Rs_pointerBlankDelay] && (i = atoi (rs[Rs_pointerBlankDelay])) >= 0)
700 pcg 1.14 pointerBlankDelay = i;
701 pcg 1.9 else
702 pcg 1.14 pointerBlankDelay = 2;
703 pcg 1.1 #endif
704    
705 sf-exg 1.334 if (rs[Rs_multiClickTime] && (i = atoi (rs[Rs_multiClickTime])) >= 0)
706     multiClickTime = i;
707     else
708     multiClickTime = 500;
709    
710 sf-exg 1.335 cursor_type = option (Opt_cursorUnderline) ? 1 : 0;
711    
712 pcg 1.9 /* no point having a scrollbar without having any scrollback! */
713 root 1.122 if (!saveLines)
714 root 1.136 set_option (Opt_scrollBar, 0);
715 pcg 1.1
716 pcg 1.9 if (!rs[Rs_cutchars])
717     rs[Rs_cutchars] = CUTCHARS;
718 pcg 1.14
719 pcg 1.1 #ifndef NO_BACKSPACE_KEY
720 pcg 1.9 if (!rs[Rs_backspace_key])
721 pcg 1.1 # ifdef DEFAULT_BACKSPACE
722 ayin 1.211 rs[Rs_backspace_key] = DEFAULT_BACKSPACE;
723 pcg 1.1 # else
724 ayin 1.211 rs[Rs_backspace_key] = "DEC"; /* can toggle between \010 or \177 */
725 pcg 1.1 # endif
726     #endif
727 pcg 1.14
728 pcg 1.1 #ifndef NO_DELETE_KEY
729 pcg 1.9 if (!rs[Rs_delete_key])
730 pcg 1.1 # ifdef DEFAULT_DELETE
731 ayin 1.211 rs[Rs_delete_key] = DEFAULT_DELETE;
732 pcg 1.1 # else
733 ayin 1.211 rs[Rs_delete_key] = "\033[3~";
734 pcg 1.1 # endif
735     #endif
736    
737 ayin 1.248 scrollBar.setup (this);
738 pcg 1.1
739     #ifdef XTERM_REVERSE_VIDEO
740 pcg 1.9 /* this is how xterm implements reverseVideo */
741 root 1.182 if (option (Opt_reverseVideo))
742 pcg 1.9 {
743     if (!rs[Rs_color + Color_fg])
744     rs[Rs_color + Color_fg] = def_colorName[Color_bg];
745 root 1.165
746 pcg 1.9 if (!rs[Rs_color + Color_bg])
747     rs[Rs_color + Color_bg] = def_colorName[Color_fg];
748 pcg 1.1 }
749     #endif
750    
751 pcg 1.9 for (i = 0; i < NRS_COLORS; i++)
752     if (!rs[Rs_color + i])
753     rs[Rs_color + i] = def_colorName[i];
754 pcg 1.1
755     #ifndef XTERM_REVERSE_VIDEO
756 pcg 1.9 /* this is how we implement reverseVideo */
757 root 1.182 if (option (Opt_reverseVideo))
758 root 1.123 ::swap (rs[Rs_color + Color_fg], rs[Rs_color + Color_bg]);
759 pcg 1.1 #endif
760    
761 pcg 1.9 /* convenient aliases for setting fg/bg to colors */
762 pcg 1.14 color_aliases (Color_fg);
763     color_aliases (Color_bg);
764 pcg 1.1 #ifndef NO_CURSORCOLOR
765 pcg 1.14 color_aliases (Color_cursor);
766     color_aliases (Color_cursor2);
767 ayin 1.222 #endif /* NO_CURSORCOLOR */
768 pcg 1.49 color_aliases (Color_pointer_fg);
769     color_aliases (Color_pointer_bg);
770 pcg 1.14 color_aliases (Color_border);
771 pcg 1.1 #ifndef NO_BOLD_UNDERLINE_REVERSE
772 pcg 1.14 color_aliases (Color_BD);
773     color_aliases (Color_UL);
774     color_aliases (Color_RV);
775 ayin 1.222 #endif /* ! NO_BOLD_UNDERLINE_REVERSE */
776 pcg 1.1
777 root 1.90 if (!rs[Rs_color + Color_border])
778     rs[Rs_color + Color_border] = rs[Rs_color + Color_bg];
779    
780 pcg 1.9 return cmd_argv;
781 pcg 1.1 }
782    
783     /*----------------------------------------------------------------------*/
784     void
785 root 1.307 rxvt_term::init (stringvec *argv, stringvec *envv)
786     {
787     argv->push_back (0);
788     envv->push_back (0);
789    
790     this->argv = argv;
791     this->envv = envv;
792    
793 sf-exg 1.338 env = new char *[this->envv->size ()];
794     for (int i = 0; i < this->envv->size (); i++)
795     env[i] = this->envv->at (i);
796    
797 root 1.307 init2 (argv->size () - 1, argv->begin ());
798     }
799    
800     void
801     rxvt_term::init (int argc, const char *const *argv, const char *const *envv)
802     {
803     #if ENABLE_PERL
804     // perl might want to access the stringvecs later, so we need to copy them
805     stringvec *args = new stringvec;
806     for (int i = 0; i < argc; i++)
807     args->push_back (strdup (argv [i]));
808    
809     stringvec *envs = new stringvec;
810     for (const char *const *var = envv; *var; var++)
811     envs->push_back (strdup (*var));
812    
813     init (args, envs);
814     #else
815     init2 (argc, argv);
816     #endif
817     }
818    
819     void
820     rxvt_term::init2 (int argc, const char *const *argv)
821 ayin 1.239 {
822     SET_R (this);
823     set_locale ("");
824 sf-exg 1.338 set_environ (env); // a few things in X do not call setlocale :(
825 ayin 1.239
826     init_vars ();
827    
828     const char **cmd_argv = init_resources (argc, argv);
829    
830     #ifdef KEYSYM_RESOURCE
831     keyboard->register_done ();
832     #endif
833    
834 root 1.252 if (const char *path = rs[Rs_chdir])
835     if (*path) // ignored if empty
836     {
837     if (*path != '/')
838     rxvt_fatal ("specified shell working directory must start with a slash, aborting.\n");
839    
840     if (chdir (path))
841     rxvt_fatal ("unable to change into specified shell working directory, aborting.\n");
842     }
843    
844 ayin 1.239 if (option (Opt_scrollBar))
845 sf-exg 1.300 scrollBar.state = SB_STATE_IDLE; /* set existence for size calculations */
846 ayin 1.239
847     pty = ptytty::create ();
848    
849     create_windows (argc, argv);
850    
851     init_xlocale ();
852    
853 root 1.256 scr_poweron (); // initialize screen
854 ayin 1.239
855     #if 0
856     XSynchronize (dpy, True);
857     #endif
858    
859     if (option (Opt_scrollBar))
860 ayin 1.249 scrollBar.resize (); /* create and map scrollbar */
861 sf-exg 1.329
862 ayin 1.239 #ifdef HAVE_BG_PIXMAP
863 sf-exg 1.329 bg_init ();
864 ayin 1.239 #endif
865    
866     #if ENABLE_PERL
867     rootwin_ev.start (display, display->root);
868     #endif
869    
870 sf-exg 1.315 init_done = 1;
871 ayin 1.239
872     init_command (cmd_argv);
873    
874     if (pty->pty >= 0)
875     pty_ev.start (pty->pty, ev::READ);
876    
877     HOOK_INVOKE ((this, HOOK_START, DT_END));
878    
879     #if ENABLE_XEMBED
880     if (rs[Rs_embed])
881     {
882     long info[2] = { 0, XEMBED_MAPPED };
883    
884 sf-exg 1.294 XChangeProperty (dpy, parent, xa[XA_XEMBED_INFO], xa[XA_XEMBED_INFO],
885 ayin 1.239 32, PropModeReplace, (unsigned char *)&info, 2);
886     }
887     #endif
888    
889 mikachu 1.301 #if HAVE_STARTUP_NOTIFICATION
890     SnDisplay *snDisplay;
891     SnLauncheeContext *snContext;
892    
893     snDisplay = sn_display_new (dpy, NULL, NULL);
894     snContext = sn_launchee_context_new_from_environment (snDisplay, DefaultScreen (dpy));
895    
896     /* Tell the window manager that this window is part of the startup context */
897     if (snContext)
898     sn_launchee_context_setup_window (snContext, parent);
899     #endif
900    
901 ayin 1.239 XMapWindow (dpy, vt);
902 sf-exg 1.294 XMapWindow (dpy, parent);
903 ayin 1.239
904 mikachu 1.301 #if HAVE_STARTUP_NOTIFICATION
905     if (snContext)
906     {
907     /* Mark the startup process as complete */
908     sn_launchee_context_complete (snContext);
909    
910     sn_launchee_context_unref (snContext);
911     }
912    
913     sn_display_unref (snDisplay);
914     #endif
915    
916 ayin 1.239 refresh_check ();
917     }
918    
919     /*----------------------------------------------------------------------*/
920     void
921 pcg 1.14 rxvt_term::init_env ()
922 pcg 1.1 {
923 pcg 1.14 char *val;
924 sf-exg 1.314 char *env_display;
925 sf-exg 1.316 char *env_windowid;
926     char *env_colorfgbg;
927 sf-exg 1.314 char *env_term;
928 pcg 1.1
929     #ifdef DISPLAY_IS_IP
930 pcg 1.9 /* Fixup display_name for export over pty to any interested terminal
931     * clients via "ESC[7n" (e.g. shells). Note we use the pure IP number
932     * (for the first non-loopback interface) that we get from
933 pcg 1.26 * rxvt_network_display (). This is more "name-resolution-portable", if you
934 pcg 1.9 * will, and probably allows for faster x-client startup if your name
935     * server is beyond a slow link or overloaded at client startup. Of
936     * course that only helps the shell's child processes, not us.
937     *
938     * Giving out the display_name also affords a potential security hole
939     */
940 pcg 1.14 val = rxvt_network_display (rs[Rs_display_name]);
941     rs[Rs_display_name] = (const char *)val;
942    
943 pcg 1.9 if (val == NULL)
944 ayin 1.222 #endif /* DISPLAY_IS_IP */
945 root 1.169 val = XDisplayString (dpy);
946 pcg 1.9
947 pcg 1.14 if (rs[Rs_display_name] == NULL)
948     rs[Rs_display_name] = val; /* use broken `:0' value */
949 pcg 1.9
950 sf-exg 1.287 env_display = (char *)rxvt_malloc (strlen (val) + 9);
951 pcg 1.9
952 pcg 1.14 sprintf (env_display, "DISPLAY=%s", val);
953 pcg 1.9
954 sf-exg 1.316 env_windowid = (char *)rxvt_malloc (21);
955 sf-exg 1.294 sprintf (env_windowid, "WINDOWID=%lu", (unsigned long)parent);
956 pcg 1.9
957     /* add entries to the environment:
958     * @ DISPLAY: in case we started with -display
959     * @ WINDOWID: X window id number of the window
960     * @ COLORTERM: terminal sub-name and also indicates its color
961     * @ TERM: terminal name
962     * @ TERMINFO: path to terminfo directory
963 pcg 1.27 * @ COLORFGBG: fg;bg color codes
964 pcg 1.9 */
965 pcg 1.14 putenv (env_display);
966     putenv (env_windowid);
967 root 1.155
968 sf-exg 1.316 env_colorfgbg = get_colorfgbg ();
969     putenv (env_colorfgbg);
970 pcg 1.14
971 pcg 1.1 #ifdef RXVT_TERMINFO
972 pcg 1.14 putenv ("TERMINFO=" RXVT_TERMINFO);
973 pcg 1.1 #endif
974 pcg 1.9
975 root 1.156 if (depth <= 2)
976 pcg 1.14 putenv ("COLORTERM=" COLORTERMENV "-mono");
977 pcg 1.9 else
978 pcg 1.14 putenv ("COLORTERM=" COLORTERMENVFULL);
979    
980     if (rs[Rs_term_name] != NULL)
981 pcg 1.9 {
982 ayin 1.208 env_term = (char *)rxvt_malloc (strlen (rs[Rs_term_name]) + 6);
983 pcg 1.14 sprintf (env_term, "TERM=%s", rs[Rs_term_name]);
984     putenv (env_term);
985 pcg 1.9 }
986     else
987 pcg 1.14 putenv ("TERM=" TERMENV);
988 pcg 1.1
989     #ifdef HAVE_UNSETENV
990 pcg 1.9 /* avoid passing old settings and confusing term size */
991 pcg 1.14 unsetenv ("LINES");
992     unsetenv ("COLUMNS");
993     unsetenv ("TERMCAP"); /* terminfo should be okay */
994 ayin 1.222 #endif /* HAVE_UNSETENV */
995 pcg 1.1 }
996    
997     /*----------------------------------------------------------------------*/
998     void
999 pcg 1.15 rxvt_term::set_locale (const char *locale)
1000     {
1001 sf-exg 1.338 set_environ (env);
1002 root 1.137
1003 pcg 1.15 free (this->locale);
1004 root 1.57 this->locale = setlocale (LC_CTYPE, locale);
1005    
1006     if (!this->locale)
1007     {
1008 root 1.79 if (*locale)
1009     {
1010 root 1.137 rxvt_warn ("unable to set locale \"%s\", using C locale instead.\n", locale);
1011     setlocale (LC_CTYPE, "C");
1012 root 1.79 }
1013     else
1014     rxvt_warn ("default locale unavailable, check LC_* and LANG variables. Continuing.\n");
1015    
1016 root 1.137 this->locale = "C";
1017 root 1.57 }
1018    
1019 root 1.79
1020 ayin 1.220 this->locale = strdup (this->locale);
1021 pcg 1.29 SET_LOCALE (this->locale);
1022 pcg 1.28 mbstate.reset ();
1023 root 1.96
1024 pcg 1.15 #if HAVE_NL_LANGINFO
1025 root 1.307 char *codeset = nl_langinfo (CODESET);
1026 root 1.105 // /^UTF.?8/i
1027     enc_utf8 = (codeset[0] == 'U' || codeset[0] == 'u')
1028     && (codeset[1] == 'T' || codeset[1] == 't')
1029     && (codeset[2] == 'F' || codeset[2] == 'f')
1030     && (codeset[3] == '8' || codeset[4] == '8');
1031 pcg 1.15 #else
1032 root 1.96 enc_utf8 = 0;
1033 pcg 1.15 #endif
1034     }
1035    
1036     void
1037 pcg 1.14 rxvt_term::init_xlocale ()
1038 pcg 1.1 {
1039 sf-exg 1.338 set_environ (env);
1040 root 1.137
1041 root 1.327 #if USE_XIM
1042 pcg 1.14 if (!locale)
1043 root 1.307 rxvt_warn ("setting locale failed, continuing without locale support.\n");
1044 pcg 1.9 else
1045     {
1046 root 1.97 set_string_property (xa[XA_WM_LOCALE_NAME], locale);
1047 pcg 1.9
1048 pcg 1.14 if (!XSupportsLocale ())
1049 pcg 1.9 {
1050 root 1.307 rxvt_warn ("the locale is not supported by Xlib, continuing without locale support.\n");
1051 pcg 1.9 return;
1052 pcg 1.4 }
1053 pcg 1.10
1054 pcg 1.25 im_ev.start (display);
1055 pcg 1.4
1056 pcg 1.25 /* see if we can connect already */
1057     im_cb ();
1058 pcg 1.1 }
1059     #endif
1060     }
1061    
1062     /*----------------------------------------------------------------------*/
1063     void
1064 pcg 1.26 rxvt_term::init_command (const char *const *argv)
1065 pcg 1.1 {
1066 pcg 1.4 /*
1067     * Initialize the command connection.
1068     * This should be called after the X server connection is established.
1069     */
1070 pcg 1.1
1071     #ifdef META8_OPTION
1072 root 1.182 meta_char = option (Opt_meta8) ? 0x80 : C0_ESC;
1073 pcg 1.14 #endif
1074 pcg 1.9
1075 pcg 1.20 get_ourmods ();
1076 pcg 1.4
1077 root 1.182 if (!option (Opt_scrollTtyOutput))
1078 root 1.79 priv_modes |= PrivMode_TtyOutputInh;
1079 root 1.182 if (option (Opt_scrollTtyKeypress))
1080 root 1.79 priv_modes |= PrivMode_Keypress;
1081 root 1.182 if (!option (Opt_jumpScroll))
1082 root 1.79 priv_modes |= PrivMode_smoothScroll;
1083 pcg 1.4
1084 pcg 1.1 #ifndef NO_BACKSPACE_KEY
1085 ayin 1.211 if (strcmp (rs[Rs_backspace_key], "DEC") == 0)
1086 root 1.79 priv_modes |= PrivMode_HaveBackSpace;
1087 pcg 1.14 #endif
1088 pcg 1.9
1089     /* add value for scrollBar */
1090 root 1.143 if (scrollBar.state)
1091 pcg 1.4 {
1092 root 1.79 priv_modes |= PrivMode_scrollBar;
1093 pcg 1.14 SavedModes |= PrivMode_scrollBar;
1094 pcg 1.4 }
1095 root 1.110
1096 root 1.70 run_command (argv);
1097 pcg 1.1 }
1098    
1099     /*----------------------------------------------------------------------*/
1100     void
1101 root 1.340 rxvt_term::get_colors ()
1102 pcg 1.1 {
1103 pcg 1.14 int i;
1104 pcg 1.1
1105 root 1.65 #ifdef OFF_FOCUS_FADING
1106 root 1.79 pix_colors = pix_colors_focused;
1107 root 1.65 #endif
1108 ayin 1.221
1109 root 1.340 for (i = 0; i < NRS_COLORS; i++)
1110 root 1.342 if (const char *name = rs[Rs_color + i])
1111 root 1.341 set_color (pix_colors [i], name);
1112 root 1.119
1113 pcg 1.9 /*
1114 root 1.143 * get scrollBar shadow colors
1115 pcg 1.9 *
1116     * The calculations of topShadow/bottomShadow values are adapted
1117     * from the fvwm window manager.
1118     */
1119 ayin 1.245 #ifdef RXVT_SCROLLBAR
1120 root 1.340 pix_colors [Color_scroll].fade (this, 50, pix_colors [Color_bottomShadow]);
1121 pcg 1.1
1122 root 1.340 rgba cscroll;
1123     pix_colors [Color_scroll].get (cscroll);
1124 pcg 1.1
1125 root 1.340 /* topShadowColor */
1126     if (!pix_colors[Color_topShadow].set (this,
1127     rgba (
1128     min ((int)rgba::MAX_CC, max (cscroll.r / 5, cscroll.r) * 7 / 5),
1129     min ((int)rgba::MAX_CC, max (cscroll.g / 5, cscroll.g) * 7 / 5),
1130     min ((int)rgba::MAX_CC, max (cscroll.b / 5, cscroll.b) * 7 / 5),
1131     cscroll.a)
1132     ))
1133     alias_color (Color_topShadow, Color_White);
1134 ayin 1.245 #endif
1135 root 1.168
1136     #ifdef OFF_FOCUS_FADING
1137 root 1.340 for (i = 0; i < NRS_COLORS; i++)
1138     update_fade_color (i, true);
1139 root 1.168 #endif
1140 pcg 1.1 }
1141    
1142     /*----------------------------------------------------------------------*/
1143     /* color aliases, fg/bg bright-bold */
1144     void
1145 pcg 1.26 rxvt_term::color_aliases (int idx)
1146 pcg 1.1 {
1147 sf-exg 1.318 if (rs[Rs_color + idx] && isdigit (*rs[Rs_color + idx]))
1148 pcg 1.9 {
1149 pcg 1.14 int i = atoi (rs[Rs_color + idx]);
1150 pcg 1.1
1151 pcg 1.9 if (i >= 8 && i <= 15)
1152 ayin 1.223 /* bright colors */
1153     rs[Rs_color + idx] = rs[Rs_color + minBrightCOLOR + i - 8];
1154     else if (i >= 0 && i <= 7)
1155     /* normal colors */
1156 pcg 1.14 rs[Rs_color + idx] = rs[Rs_color + minCOLOR + i];
1157 pcg 1.1 }
1158     }
1159    
1160     /*----------------------------------------------------------------------*/
1161     /*
1162     * Probe the modifier keymap to get the Meta (Alt) and Num_Lock settings
1163     * Use resource ``modifier'' to override the Meta modifier
1164     */
1165     void
1166 pcg 1.20 rxvt_term::get_ourmods ()
1167 pcg 1.1 {
1168 root 1.108 int i, j, k;
1169     int requestedmeta, realmeta, realalt;
1170     const char *cm, *rsmod;
1171 pcg 1.9 XModifierKeymap *map;
1172 root 1.108 KeyCode *kc;
1173 pcg 1.9 const unsigned int modmasks[] =
1174     {
1175     Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
1176     };
1177    
1178     requestedmeta = realmeta = realalt = 0;
1179 pcg 1.20 rsmod = rs[Rs_modifier];
1180 root 1.105
1181 pcg 1.9 if (rsmod
1182 root 1.79 && strcasecmp (rsmod, "mod1") >= 0 && strcasecmp (rsmod, "mod5") <= 0)
1183 pcg 1.9 requestedmeta = rsmod[3] - '0';
1184    
1185 root 1.169 map = XGetModifierMapping (dpy);
1186 pcg 1.9 kc = map->modifiermap;
1187 root 1.105
1188 pcg 1.9 for (i = 1; i < 6; i++)
1189     {
1190     k = (i + 2) * map->max_keypermod; /* skip shift/lock/control */
1191 root 1.105
1192 pcg 1.9 for (j = map->max_keypermod; j--; k++)
1193     {
1194     if (kc[k] == 0)
1195     break;
1196 root 1.105
1197 sf-exg 1.337 switch (rxvt_XKeycodeToKeysym (dpy, kc[k], 0))
1198 pcg 1.9 {
1199 pcg 1.23 case XK_Num_Lock:
1200     ModNumLockMask = modmasks[i - 1];
1201 root 1.105 continue;
1202    
1203     case XK_ISO_Level3_Shift:
1204     ModLevel3Mask = modmasks[i - 1];
1205     continue;
1206    
1207 pcg 1.23 case XK_Meta_L:
1208     case XK_Meta_R:
1209     cm = "meta";
1210     realmeta = i;
1211     break;
1212 root 1.105
1213 pcg 1.23 case XK_Alt_L:
1214     case XK_Alt_R:
1215     cm = "alt";
1216     realalt = i;
1217     break;
1218 root 1.105
1219 pcg 1.23 case XK_Super_L:
1220     case XK_Super_R:
1221     cm = "super";
1222     break;
1223 root 1.105
1224 pcg 1.23 case XK_Hyper_L:
1225     case XK_Hyper_R:
1226     cm = "hyper";
1227     break;
1228 root 1.105
1229     default:
1230     continue;
1231 pcg 1.4 }
1232 root 1.105
1233 root 1.79 if (rsmod && strncasecmp (rsmod, cm, strlen (cm)) == 0)
1234 pcg 1.9 requestedmeta = i;
1235 pcg 1.4 }
1236 pcg 1.1 }
1237 root 1.105
1238 pcg 1.26 XFreeModifiermap (map);
1239 root 1.105
1240     i = requestedmeta ? requestedmeta
1241     : realmeta ? realmeta
1242     : realalt ? realalt
1243     : 0;
1244    
1245 pcg 1.9 if (i)
1246 pcg 1.20 ModMetaMask = modmasks[i - 1];
1247 pcg 1.1 }
1248    
1249 sf-exg 1.278 void
1250     rxvt_term::set_icon (const char *file)
1251     {
1252 sf-exg 1.343 #if HAVE_PIXBUF && ENABLE_EWMH
1253 sf-exg 1.282 GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (file, NULL);
1254     if (!pixbuf)
1255     {
1256     rxvt_warn ("Loading image icon failed, continuing without.\n");
1257     return;
1258     }
1259    
1260     unsigned int w = gdk_pixbuf_get_width (pixbuf);
1261     unsigned int h = gdk_pixbuf_get_height (pixbuf);
1262    
1263     if (!IN_RANGE_INC (w, 1, 16383) || !IN_RANGE_INC (h, 1, 16383))
1264     {
1265     rxvt_warn ("Icon image too big, continuing without.\n");
1266     g_object_unref (pixbuf);
1267     return;
1268     }
1269    
1270     if (long *buffer = (long *)malloc ((2 + w * h) * sizeof (long)))
1271     {
1272     int rowstride = gdk_pixbuf_get_rowstride (pixbuf);
1273     unsigned char *row = gdk_pixbuf_get_pixels (pixbuf);
1274     int channels = gdk_pixbuf_get_n_channels (pixbuf);
1275    
1276     buffer [0] = w;
1277     buffer [1] = h;
1278     for (int i = 0; i < h; i++)
1279     {
1280     for (int j = 0; j < w; j++)
1281     {
1282     unsigned char *pixel = row + j * channels;
1283     long value;
1284    
1285     if (channels == 4)
1286     value = pixel[3];
1287     else
1288     value = (unsigned char)0x00ff;
1289    
1290     value = (value << 8) + pixel[0];
1291     value = (value << 8) + pixel[1];
1292     value = (value << 8) + pixel[2];
1293     buffer[(i * w + j) + 2] = value;
1294     }
1295    
1296     row += rowstride;
1297     }
1298    
1299 sf-exg 1.294 XChangeProperty (dpy, parent, xa[XA_NET_WM_ICON], XA_CARDINAL, 32,
1300 sf-exg 1.282 PropModeReplace, (const unsigned char *) buffer, 2 + w * h);
1301     free (buffer);
1302     }
1303     else
1304     rxvt_warn ("Memory allocation for icon hint failed, continuing without.\n");
1305    
1306     g_object_unref (pixbuf);
1307     #endif
1308 sf-exg 1.278 }
1309    
1310 pcg 1.1 /*----------------------------------------------------------------------*/
1311 sf-exg 1.295 /* Open and map the window */
1312 pcg 1.1 void
1313 pcg 1.16 rxvt_term::create_windows (int argc, const char *const *argv)
1314 pcg 1.1 {
1315 pcg 1.51 XClassHint classHint;
1316     XWMHints wmHint;
1317 root 1.79 #if ENABLE_FRILLS
1318 root 1.196 MWMHints mwmhints = { };
1319 root 1.67 #endif
1320 pcg 1.51 XGCValues gcvalue;
1321     XSetWindowAttributes attributes;
1322 root 1.114 Window top, parent;
1323 pcg 1.1
1324 root 1.169 dLocal (Display *, dpy);
1325 pcg 1.1
1326 root 1.148 /* grab colors before netscape does */
1327 root 1.340 get_colors ();
1328 root 1.148
1329     if (!set_fonts ())
1330     rxvt_fatal ("unable to load base fontset, please specify a valid one using -fn, aborting.\n");
1331    
1332 root 1.153 parent = display->root;
1333 root 1.148
1334 root 1.182 attributes.override_redirect = !!option (Opt_override_redirect);
1335 root 1.148
1336 root 1.79 #if ENABLE_FRILLS
1337 root 1.182 if (option (Opt_borderLess))
1338 root 1.67 {
1339 root 1.169 if (XInternAtom (dpy, "_MOTIF_WM_INFO", True) == None)
1340 root 1.67 {
1341 ayin 1.206 // rxvt_warn("Window Manager does not support MWM hints. Bypassing window manager control for borderless window.\n");
1342 root 1.158 attributes.override_redirect = true;
1343 root 1.67 }
1344     else
1345     {
1346     mwmhints.flags = MWM_HINTS_DECORATIONS;
1347     }
1348     }
1349     #endif
1350    
1351 root 1.112 #if ENABLE_XEMBED
1352 root 1.109 if (rs[Rs_embed])
1353     {
1354 root 1.111 XWindowAttributes wattr;
1355    
1356 root 1.114 parent = strtol (rs[Rs_embed], 0, 0);
1357 root 1.109
1358 root 1.169 if (!XGetWindowAttributes (dpy, parent, &wattr))
1359 root 1.111 rxvt_fatal ("invalid window-id specified with -embed, aborting.\n");
1360 pcg 1.1
1361 root 1.109 window_calc (wattr.width, wattr.height);
1362 root 1.114 }
1363 root 1.122 #endif
1364 pcg 1.1
1365 root 1.114 window_calc (0, 0);
1366 root 1.109
1367 sf-exg 1.295 /* sub-window placement & size in rxvt_term::resize_all_windows () */
1368 root 1.156 attributes.background_pixel = pix_colors_focused [Color_border];
1369     attributes.border_pixel = pix_colors_focused [Color_border];
1370     attributes.colormap = cmap;
1371 root 1.153
1372 root 1.169 top = XCreateWindow (dpy, parent,
1373 root 1.114 szHint.x, szHint.y,
1374     szHint.width, szHint.height,
1375 root 1.122 ext_bwidth,
1376 root 1.156 depth, InputOutput, visual,
1377 root 1.148 CWColormap | CWBackPixel | CWBorderPixel | CWOverrideRedirect,
1378     &attributes);
1379 root 1.109
1380 sf-exg 1.294 this->parent = top;
1381 root 1.109
1382 root 1.257 set_title (rs [Rs_title]);
1383     set_icon_name (rs [Rs_iconName]);
1384 pcg 1.9
1385 root 1.153 classHint.res_name = (char *)rs[Rs_name];
1386 pcg 1.38 classHint.res_class = (char *)RESCLASS;
1387 pcg 1.9
1388 root 1.153 wmHint.flags = InputHint | StateHint | WindowGroupHint;
1389     wmHint.input = True;
1390 mikachu 1.333 wmHint.initial_state = option (Opt_iconic) ? IconicState
1391     : option (Opt_dockapp) ? WithdrawnState
1392     : NormalState;
1393 root 1.153 wmHint.window_group = top;
1394 pcg 1.9
1395 root 1.169 XmbSetWMProperties (dpy, top, NULL, NULL, (char **)argv, argc,
1396 root 1.115 &szHint, &wmHint, &classHint);
1397 sf-exg 1.262 #if ENABLE_EWMH
1398 root 1.254 /*
1399     * set up icon hint
1400 sf-exg 1.275 * rs [Rs_iconfile] is path to icon
1401 root 1.254 */
1402 root 1.255
1403     if (rs [Rs_iconfile])
1404 root 1.331 set_icon (rs [Rs_iconfile]);
1405 root 1.254 #endif
1406 pcg 1.49
1407 root 1.153 #if ENABLE_FRILLS
1408     if (mwmhints.flags)
1409 root 1.169 XChangeProperty (dpy, top, xa[XA_MOTIF_WM_HINTS], xa[XA_MOTIF_WM_HINTS], 32,
1410 root 1.153 PropModeReplace, (unsigned char *)&mwmhints, PROP_MWM_HINTS_ELEMENTS);
1411     #endif
1412    
1413 root 1.116 Atom protocols[] = {
1414     xa[XA_WM_DELETE_WINDOW],
1415     #if ENABLE_EWMH
1416     xa[XA_NET_WM_PING],
1417     #endif
1418     };
1419    
1420 sf-exg 1.296 XSetWMProtocols (dpy, top, protocols, ecb_array_length (protocols));
1421 root 1.96
1422 root 1.133 #if ENABLE_FRILLS
1423     if (rs[Rs_transient_for])
1424 root 1.169 XSetTransientForHint (dpy, top, (Window)strtol (rs[Rs_transient_for], 0, 0));
1425 root 1.133 #endif
1426    
1427 root 1.116 #if ENABLE_EWMH
1428 pcg 1.49 long pid = getpid ();
1429 root 1.93
1430 root 1.169 XChangeProperty (dpy, top,
1431 root 1.97 xa[XA_NET_WM_PID], XA_CARDINAL, 32,
1432 pcg 1.49 PropModeReplace, (unsigned char *)&pid, 1);
1433 root 1.116
1434     // _NET_WM_WINDOW_TYPE is NORMAL, which is the default
1435 pcg 1.49 #endif
1436 pcg 1.24
1437 root 1.169 XSelectInput (dpy, top,
1438 root 1.65 KeyPressMask
1439 root 1.90 #if (MOUSE_WHEEL && MOUSE_SLIP_WHEELING) || ENABLE_FRILLS || ISO_14755
1440 root 1.65 | KeyReleaseMask
1441 pcg 1.1 #endif
1442 root 1.65 | FocusChangeMask | VisibilityChangeMask
1443 root 1.112 | ExposureMask | StructureNotifyMask);
1444    
1445 root 1.109 termwin_ev.start (display, top);
1446 pcg 1.1
1447 pcg 1.9 /* vt cursor: Black-on-White is standard, but this is more popular */
1448 sf-exg 1.344 unsigned int shape = XC_xterm;
1449    
1450     #ifdef HAVE_XMU
1451     if (rs[Rs_pointerShape])
1452     {
1453     int stmp = XmuCursorNameToIndex (rs[Rs_pointerShape]);
1454     if (stmp >= 0)
1455     shape = stmp;
1456     }
1457     #endif
1458    
1459     TermWin_cursor = XCreateFontCursor (dpy, shape);
1460 pcg 1.1
1461 pcg 1.9 /* the vt window */
1462 root 1.169 vt = XCreateSimpleWindow (dpy, top,
1463 root 1.153 window_vt_x, window_vt_y,
1464 sf-exg 1.317 vt_width, vt_height,
1465 root 1.153 0,
1466     pix_colors_focused[Color_fg],
1467     pix_colors_focused[Color_bg]);
1468 pcg 1.6
1469 pcg 1.51 attributes.bit_gravity = NorthWestGravity;
1470 root 1.169 XChangeWindowAttributes (dpy, vt, CWBitGravity, &attributes);
1471 pcg 1.51
1472     vt_emask = ExposureMask | ButtonPressMask | ButtonReleaseMask | PropertyChangeMask;
1473 pcg 1.17
1474 root 1.182 if (option (Opt_pointerBlank))
1475 pcg 1.9 vt_emask |= PointerMotionMask;
1476     else
1477 pcg 1.51 vt_emask |= Button1MotionMask | Button3MotionMask;
1478 pcg 1.9
1479 root 1.142 vt_select_input ();
1480    
1481 root 1.122 vt_ev.start (display, vt);
1482 pcg 1.1
1483 pcg 1.9 /* graphics context for the vt window */
1484 root 1.153 gcvalue.foreground = pix_colors[Color_fg];
1485     gcvalue.background = pix_colors[Color_bg];
1486 root 1.170 gcvalue.graphics_exposures = 0;
1487 root 1.153
1488 root 1.169 gc = XCreateGC (dpy, vt,
1489 root 1.153 GCForeground | GCBackground | GCGraphicsExposures,
1490     &gcvalue);
1491 pcg 1.1
1492 root 1.156 drawable = new rxvt_drawable (this, vt);
1493 pcg 1.35
1494 root 1.65 #ifdef OFF_FOCUS_FADING
1495     // initially we are in unfocused state
1496     if (rs[Rs_fade])
1497 root 1.79 pix_colors = pix_colors_unfocused;
1498 pcg 1.1 #endif
1499 root 1.90
1500 root 1.113 pointer_unblank ();
1501 root 1.340 scr_recolor ();
1502 pcg 1.1 }
1503    
1504 root 1.79 /*----------------------------------------------------------------------*/
1505     /*
1506     * Run the command in a subprocess and return a file descriptor for the
1507     * master end of the pseudo-teletype pair with the command talking to
1508     * the slave.
1509     */
1510     void
1511     rxvt_term::run_command (const char *const *argv)
1512     {
1513 root 1.110 #if ENABLE_FRILLS
1514     if (rs[Rs_pty_fd])
1515     {
1516 root 1.145 pty->pty = atoi (rs[Rs_pty_fd]);
1517 root 1.127
1518 root 1.145 if (pty->pty >= 0)
1519 root 1.132 {
1520     if (getfd_hook)
1521 root 1.145 pty->pty = (*getfd_hook) (pty->pty);
1522 root 1.127
1523 sf-exg 1.309 if (pty->pty < 0)
1524 root 1.132 rxvt_fatal ("unusable pty-fd filehandle, aborting.\n");
1525     }
1526 root 1.110 }
1527     else
1528     #endif
1529 root 1.145 if (!pty->get ())
1530 root 1.110 rxvt_fatal ("can't initialize pseudo-tty, aborting.\n");
1531 root 1.79
1532 sf-exg 1.309 fcntl (pty->pty, F_SETFL, O_NONBLOCK);
1533    
1534 sf-exg 1.274 struct termios tio = def_tio;
1535 root 1.105
1536 root 1.79 #ifndef NO_BACKSPACE_KEY
1537 ayin 1.211 if (rs[Rs_backspace_key][0] && !rs[Rs_backspace_key][1])
1538 sf-exg 1.270 tio.c_cc[VERASE] = rs[Rs_backspace_key][0];
1539 ayin 1.211 else if (strcmp (rs[Rs_backspace_key], "DEC") == 0)
1540 sf-exg 1.270 tio.c_cc[VERASE] = '\177'; /* the initial state anyway */
1541 root 1.79 #endif
1542    
1543 ayin 1.233 /* init terminal attributes */
1544     cfsetospeed (&tio, BAUDRATE);
1545     cfsetispeed (&tio, BAUDRATE);
1546     tcsetattr (pty->tty, TCSANOW, &tio);
1547 root 1.175 pty->set_utf8_mode (enc_utf8);
1548    
1549     /* set initial window size */
1550     tt_winch ();
1551 root 1.79
1552 root 1.110 #if ENABLE_FRILLS
1553     if (rs[Rs_pty_fd])
1554     return;
1555     #endif
1556    
1557 root 1.79 /* spin off the command interpreter */
1558     switch (cmd_pid = fork ())
1559     {
1560     case -1:
1561 root 1.110 {
1562     cmd_pid = 0;
1563     rxvt_fatal ("can't fork, aborting.\n");
1564     }
1565 root 1.79 case 0:
1566     init_env ();
1567    
1568 root 1.145 if (!pty->make_controlling_tty ())
1569 root 1.79 fprintf (stderr, "%s: could not obtain control of tty.", RESNAME);
1570     else
1571     {
1572     /* Reopen stdin, stdout and stderr over the tty file descriptor */
1573 root 1.145 dup2 (pty->tty, STDIN_FILENO);
1574     dup2 (pty->tty, STDOUT_FILENO);
1575     dup2 (pty->tty, STDERR_FILENO);
1576 root 1.79
1577     // close all our file handles that we do no longer need
1578     for (rxvt_term **t = termlist.begin (); t < termlist.end (); t++)
1579     {
1580 root 1.145 if ((*t)->pty->pty > 2) close ((*t)->pty->pty);
1581     if ((*t)->pty->tty > 2) close ((*t)->pty->tty);
1582 root 1.79 }
1583    
1584     run_child (argv);
1585     fprintf (stderr, "%s: unable to exec child.", RESNAME);
1586     }
1587    
1588     _exit (EXIT_FAILURE);
1589    
1590     default:
1591 root 1.182 if (!option (Opt_utmpInhibit))
1592 sf-exg 1.310 {
1593     #ifdef LOG_ONLY_ON_LOGIN
1594     bool login_shell = option (Opt_loginShell);
1595     #else
1596     bool login_shell = true;
1597     #endif
1598     pty->login (cmd_pid, login_shell, rs[Rs_display_name]);
1599     }
1600 root 1.79
1601 root 1.145 pty->close_tty ();
1602 root 1.149
1603     child_ev.start (cmd_pid);
1604    
1605     HOOK_INVOKE ((this, HOOK_CHILD_START, DT_INT, cmd_pid, DT_END));
1606 root 1.79 break;
1607     }
1608     }
1609    
1610     /* ------------------------------------------------------------------------- *
1611     * CHILD PROCESS OPERATIONS *
1612     * ------------------------------------------------------------------------- */
1613     /*
1614     * The only open file descriptor is the slave tty - so no error messages.
1615     * returns are fatal
1616     */
1617     int
1618     rxvt_term::run_child (const char *const *argv)
1619     {
1620     char *login;
1621    
1622 root 1.182 if (option (Opt_console))
1623 ayin 1.224 {
1624     /* be virtual console, fail silently */
1625 root 1.79 #ifdef TIOCCONS
1626     unsigned int on = 1;
1627    
1628     ioctl (STDIN_FILENO, TIOCCONS, &on);
1629     #elif defined (SRIOCSREDIR)
1630     int fd;
1631    
1632     fd = open (CONSOLE, O_WRONLY, 0);
1633     if (fd >= 0)
1634 sf-exg 1.311 {
1635 sf-exg 1.312 ioctl (fd, SRIOCSREDIR, STDIN_FILENO);
1636 root 1.79 close (fd);
1637 sf-exg 1.311 }
1638 ayin 1.222 #endif /* SRIOCSREDIR */
1639 root 1.79 }
1640    
1641     /* reset signals and spin off the command interpreter */
1642     signal (SIGINT, SIG_DFL);
1643     signal (SIGQUIT, SIG_DFL);
1644     signal (SIGCHLD, SIG_DFL);
1645     signal (SIGHUP, SIG_DFL);
1646     signal (SIGPIPE, SIG_DFL);
1647     /*
1648 sf-exg 1.272 * mimic login's behavior by disabling the job control signals
1649 root 1.79 * a shell that wants them can turn them back on
1650     */
1651     #ifdef SIGTSTP
1652     signal (SIGTSTP, SIG_IGN);
1653     signal (SIGTTIN, SIG_IGN);
1654     signal (SIGTTOU, SIG_IGN);
1655 ayin 1.222 #endif /* SIGTSTP */
1656 root 1.79
1657     /* command interpreter path */
1658 root 1.213 if (argv)
1659 root 1.79 {
1660     # ifdef DEBUG_CMD
1661     int i;
1662    
1663     for (i = 0; argv[i]; i++)
1664     fprintf (stderr, "argv [%d] = \"%s\"\n", i, argv[i]);
1665     # endif
1666    
1667     execvp (argv[0], (char *const *)argv);
1668     /* no error message: STDERR is closed! */
1669     }
1670     else
1671     {
1672 root 1.137 const char *argv0, *shell;
1673 root 1.79
1674     if ((shell = getenv ("SHELL")) == NULL || *shell == '\0')
1675     shell = "/bin/sh";
1676    
1677 root 1.258 argv0 = rxvt_basename (shell);
1678 root 1.79
1679 root 1.182 if (option (Opt_loginShell))
1680 root 1.79 {
1681 ayin 1.208 login = (char *)rxvt_malloc (strlen (argv0) + 2);
1682 root 1.79
1683     login[0] = '-';
1684     strcpy (&login[1], argv0);
1685     argv0 = login;
1686     }
1687 root 1.137
1688 root 1.213 execlp (shell, argv0, (char *)0);
1689 root 1.79 /* no error message: STDERR is closed! */
1690     }
1691    
1692     return -1;
1693     }
1694    
1695 pcg 1.1 /*----------------------- end-of-file (C source) -----------------------*/