summaryrefslogtreecommitdiffstats
path: root/src/init.C
diff options
context:
space:
mode:
Diffstat (limited to 'src/init.C')
-rw-r--r--src/init.C1697
1 files changed, 1697 insertions, 0 deletions
diff --git a/src/init.C b/src/init.C
new file mode 100644
index 0000000..7e78358
--- /dev/null
+++ b/src/init.C
@@ -0,0 +1,1697 @@
+/*----------------------------------------------------------------------*
+ * File: init.C
+ *----------------------------------------------------------------------*
+ *
+ * All portions of code are copyright by their respective author/s.
+ * Copyright (c) 1992 John Bovey, University of Kent at Canterbury <jdb@ukc.ac.uk>
+ * - original version
+ * Copyright (c) 1994 Robert Nation <nation@rocket.sanders.lockheed.com>
+ * - extensive modifications
+ * Copyright (c) 1996 Chuck Blake <cblake@BBN.COM>
+ * Copyright (c) 1997 mj olesen <olesen@me.queensu.ca>
+ * Copyright (c) 1997,1998 Oezguer Kesim <kesim@math.fu-berlin.de>
+ * Copyright (c) 1998-2001 Geoff Wing <gcw@pobox.com>
+ * - extensive modifications
+ * Copyright (c) 2003-2008 Marc Lehmann <schmorp@schmorp.de>
+ * Copyright (c) 2015 Emanuele Giaquinta <e.giaquinta@glauco.it>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *---------------------------------------------------------------------*/
+/*
+ * Initialisation routines.
+ */
+
+#include "../config.h" /* NECESSARY */
+#include "rxvt.h" /* NECESSARY */
+#include "rxvtutil.h"
+#include "init.h"
+#include "keyboard.h"
+
+#include <limits>
+
+#include <signal.h>
+
+#include <fcntl.h>
+
+#ifdef HAVE_XMU
+# include <X11/Xmu/CurUtil.h>
+#endif
+
+#ifdef HAVE_XSETLOCALE
+# define X_LOCALE
+# include <X11/Xlocale.h>
+#else
+# include <locale.h>
+#endif
+
+#ifdef HAVE_NL_LANGINFO
+# include <langinfo.h>
+#endif
+
+#ifdef HAVE_STARTUP_NOTIFICATION
+# define SN_API_NOT_YET_FROZEN
+# include <libsn/sn-launchee.h>
+#endif
+
+#ifdef DISPLAY_IS_IP
+/* On Solaris link with -lsocket and -lnsl */
+#include <sys/types.h>
+#include <sys/socket.h>
+
+/* these next two are probably only on Sun (not Solaris) */
+#ifdef HAVE_SYS_SOCKIO_H
+#include <sys/sockio.h>
+#endif
+#ifdef HAVE_SYS_BYTEORDER_H
+#include <sys/byteorder.h>
+#endif
+
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <net/if.h>
+#include <net/if_arp.h>
+
+static char * ecb_cold
+rxvt_network_display (const char *display)
+{
+ char buffer[1024], *rval = NULL;
+ struct ifconf ifc;
+ struct ifreq *ifr;
+ int i, skfd;
+
+ if (display[0] != ':' && strncmp (display, "unix:", 5))
+ return (char *) display; /* nothing to do */
+
+ ifc.ifc_len = sizeof (buffer); /* Get names of all ifaces */
+ ifc.ifc_buf = buffer;
+
+ if ((skfd = socket (AF_INET, SOCK_DGRAM, 0)) < 0)
+ {
+ perror ("socket");
+ return NULL;
+ }
+
+ if (ioctl (skfd, SIOCGIFCONF, &ifc) < 0)
+ {
+ perror ("SIOCGIFCONF");
+ close (skfd);
+ return NULL;
+ }
+
+ for (i = 0, ifr = ifc.ifc_req;
+ i < (ifc.ifc_len / sizeof (struct ifreq));
+ i++, ifr++)
+ {
+ struct ifreq ifr2;
+
+ strcpy (ifr2.ifr_name, ifr->ifr_name);
+
+ if (ioctl (skfd, SIOCGIFADDR, &ifr2) >= 0)
+ {
+ unsigned long addr;
+ struct sockaddr_in *p_addr;
+
+ p_addr = (struct sockaddr_in *) &ifr2.ifr_addr;
+ addr = htonl ((unsigned long)p_addr->sin_addr.s_addr);
+
+ /*
+ * not "0.0.0.0" or "127.0.0.1" - so format the address
+ */
+ if (addr && addr != 0x7F000001)
+ {
+ char *colon = strchr (display, ':');
+
+ if (colon == NULL)
+ colon = ":0.0";
+
+ rval = rxvt_malloc (strlen (colon) + 16);
+ sprintf (rval, "%d.%d.%d.%d%s",
+ (int) ((addr >> 030) & 0xFF),
+ (int) ((addr >> 020) & 0xFF),
+ (int) ((addr >> 010) & 0xFF),
+ (int) (addr & 0xFF), colon);
+ break;
+ }
+ }
+ }
+
+ close (skfd);
+
+ return rval;
+}
+#endif
+
+#define NULL_5 \
+ NULL, \
+ NULL, \
+ NULL, \
+ NULL, \
+ NULL,
+
+#define NULL_10 \
+ NULL_5 \
+ NULL_5
+
+#define NULL_40 \
+ NULL_10 \
+ NULL_10 \
+ NULL_10 \
+ NULL_10
+
+#define NULL_50 \
+ NULL_40 \
+ NULL_10
+
+#define NULL_100 \
+ NULL_50 \
+ NULL_50
+
+static const char *const def_colorName[] =
+ {
+ COLOR_FOREGROUND,
+ COLOR_BACKGROUND,
+ /* low-intensity colors */
+ "rgb:00/00/00", // 0: black (Black)
+ "rgb:cd/00/00", // 1: red (Red3)
+ "rgb:00/cd/00", // 2: green (Green3)
+ "rgb:cd/cd/00", // 3: yellow (Yellow3)
+ "rgb:00/00/cd", // 4: blue (Blue3)
+ "rgb:cd/00/cd", // 5: magenta (Magenta3)
+ "rgb:00/cd/cd", // 6: cyan (Cyan3)
+# ifdef XTERM_COLORS
+ "rgb:e5/e5/e5", // 7: white (Grey90)
+# else
+ "rgb:fa/eb/d7", // 7: white (AntiqueWhite)
+# endif
+ /* high-intensity colors */
+# ifdef XTERM_COLORS
+ "rgb:4d/4d/4d", // 8: bright black (Grey30)
+# else
+ "rgb:40/40/40", // 8: bright black (Grey25)
+# endif
+ "rgb:ff/00/00", // 1/9: bright red (Reed)
+ "rgb:00/ff/00", // 2/10: bright green (Green)
+ "rgb:ff/ff/00", // 3/11: bright yellow (Yellow)
+ "rgb:00/00/ff", // 4/12: bright blue (Blue)
+ "rgb:ff/00/ff", // 5/13: bright magenta (Magenta)
+ "rgb:00/ff/ff", // 6/14: bright cyan (Cyan)
+ "rgb:ff/ff/ff", // 7/15: bright white (White)
+
+#if !USE_256_COLORS
+ // 88 xterm colours
+ "rgb:00/00/00",
+ "rgb:00/00/8b",
+ "rgb:00/00/cd",
+ "rgb:00/00/ff",
+ "rgb:00/8b/00",
+ "rgb:00/8b/8b",
+ "rgb:00/8b/cd",
+ "rgb:00/8b/ff",
+ "rgb:00/cd/00",
+ "rgb:00/cd/8b",
+ "rgb:00/cd/cd",
+ "rgb:00/cd/ff",
+ "rgb:00/ff/00",
+ "rgb:00/ff/8b",
+ "rgb:00/ff/cd",
+ "rgb:00/ff/ff",
+ "rgb:8b/00/00",
+ "rgb:8b/00/8b",
+ "rgb:8b/00/cd",
+ "rgb:8b/00/ff",
+ "rgb:8b/8b/00",
+ "rgb:8b/8b/8b",
+ "rgb:8b/8b/cd",
+ "rgb:8b/8b/ff",
+ "rgb:8b/cd/00",
+ "rgb:8b/cd/8b",
+ "rgb:8b/cd/cd",
+ "rgb:8b/cd/ff",
+ "rgb:8b/ff/00",
+ "rgb:8b/ff/8b",
+ "rgb:8b/ff/cd",
+ "rgb:8b/ff/ff",
+ "rgb:cd/00/00",
+ "rgb:cd/00/8b",
+ "rgb:cd/00/cd",
+ "rgb:cd/00/ff",
+ "rgb:cd/8b/00",
+ "rgb:cd/8b/8b",
+ "rgb:cd/8b/cd",
+ "rgb:cd/8b/ff",
+ "rgb:cd/cd/00",
+ "rgb:cd/cd/8b",
+ "rgb:cd/cd/cd",
+ "rgb:cd/cd/ff",
+ "rgb:cd/ff/00",
+ "rgb:cd/ff/8b",
+ "rgb:cd/ff/cd",
+ "rgb:cd/ff/ff",
+ "rgb:ff/00/00",
+ "rgb:ff/00/8b",
+ "rgb:ff/00/cd",
+ "rgb:ff/00/ff",
+ "rgb:ff/8b/00",
+ "rgb:ff/8b/8b",
+ "rgb:ff/8b/cd",
+ "rgb:ff/8b/ff",
+ "rgb:ff/cd/00",
+ "rgb:ff/cd/8b",
+ "rgb:ff/cd/cd",
+ "rgb:ff/cd/ff",
+ "rgb:ff/ff/00",
+ "rgb:ff/ff/8b",
+ "rgb:ff/ff/cd",
+ "rgb:ff/ff/ff",
+ "rgb:2e/2e/2e",
+ "rgb:5c/5c/5c",
+ "rgb:73/73/73",
+ "rgb:8b/8b/8b",
+ "rgb:a2/a2/a2",
+ "rgb:b9/b9/b9",
+ "rgb:d0/d0/d0",
+ "rgb:e7/e7/e7",
+ NULL_100
+ NULL_40
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+#else
+ // 256 xterm colours
+ "rgb:00/00/00",
+ "rgb:00/00/5f",
+ "rgb:00/00/87",
+ "rgb:00/00/af",
+ "rgb:00/00/d7",
+ "rgb:00/00/ff",
+ "rgb:00/5f/00",
+ "rgb:00/5f/5f",
+ "rgb:00/5f/87",
+ "rgb:00/5f/af",
+ "rgb:00/5f/d7",
+ "rgb:00/5f/ff",
+ "rgb:00/87/00",
+ "rgb:00/87/5f",
+ "rgb:00/87/87",
+ "rgb:00/87/af",
+ "rgb:00/87/d7",
+ "rgb:00/87/ff",
+ "rgb:00/af/00",
+ "rgb:00/af/5f",
+ "rgb:00/af/87",
+ "rgb:00/af/af",
+ "rgb:00/af/d7",
+ "rgb:00/af/ff",
+ "rgb:00/d7/00",
+ "rgb:00/d7/5f",
+ "rgb:00/d7/87",
+ "rgb:00/d7/af",
+ "rgb:00/d7/d7",
+ "rgb:00/d7/ff",
+ "rgb:00/ff/00",
+ "rgb:00/ff/5f",
+ "rgb:00/ff/87",
+ "rgb:00/ff/af",
+ "rgb:00/ff/d7",
+ "rgb:00/ff/ff",
+ "rgb:5f/00/00",
+ "rgb:5f/00/5f",
+ "rgb:5f/00/87",
+ "rgb:5f/00/af",
+ "rgb:5f/00/d7",
+ "rgb:5f/00/ff",
+ "rgb:5f/5f/00",
+ "rgb:5f/5f/5f",
+ "rgb:5f/5f/87",
+ "rgb:5f/5f/af",
+ "rgb:5f/5f/d7",
+ "rgb:5f/5f/ff",
+ "rgb:5f/87/00",
+ "rgb:5f/87/5f",
+ "rgb:5f/87/87",
+ "rgb:5f/87/af",
+ "rgb:5f/87/d7",
+ "rgb:5f/87/ff",
+ "rgb:5f/af/00",
+ "rgb:5f/af/5f",
+ "rgb:5f/af/87",
+ "rgb:5f/af/af",
+ "rgb:5f/af/d7",
+ "rgb:5f/af/ff",
+ "rgb:5f/d7/00",
+ "rgb:5f/d7/5f",
+ "rgb:5f/d7/87",
+ "rgb:5f/d7/af",
+ "rgb:5f/d7/d7",
+ "rgb:5f/d7/ff",
+ "rgb:5f/ff/00",
+ "rgb:5f/ff/5f",
+ "rgb:5f/ff/87",
+ "rgb:5f/ff/af",
+ "rgb:5f/ff/d7",
+ "rgb:5f/ff/ff",
+ "rgb:87/00/00",
+ "rgb:87/00/5f",
+ "rgb:87/00/87",
+ "rgb:87/00/af",
+ "rgb:87/00/d7",
+ "rgb:87/00/ff",
+ "rgb:87/5f/00",
+ "rgb:87/5f/5f",
+ "rgb:87/5f/87",
+ "rgb:87/5f/af",
+ "rgb:87/5f/d7",
+ "rgb:87/5f/ff",
+ "rgb:87/87/00",
+ "rgb:87/87/5f",
+ "rgb:87/87/87",
+ "rgb:87/87/af",
+ "rgb:87/87/d7",
+ "rgb:87/87/ff",
+ "rgb:87/af/00",
+ "rgb:87/af/5f",
+ "rgb:87/af/87",
+ "rgb:87/af/af",
+ "rgb:87/af/d7",
+ "rgb:87/af/ff",
+ "rgb:87/d7/00",
+ "rgb:87/d7/5f",
+ "rgb:87/d7/87",
+ "rgb:87/d7/af",
+ "rgb:87/d7/d7",
+ "rgb:87/d7/ff",
+ "rgb:87/ff/00",
+ "rgb:87/ff/5f",
+ "rgb:87/ff/87",
+ "rgb:87/ff/af",
+ "rgb:87/ff/d7",
+ "rgb:87/ff/ff",
+ "rgb:af/00/00",
+ "rgb:af/00/5f",
+ "rgb:af/00/87",
+ "rgb:af/00/af",
+ "rgb:af/00/d7",
+ "rgb:af/00/ff",
+ "rgb:af/5f/00",
+ "rgb:af/5f/5f",
+ "rgb:af/5f/87",
+ "rgb:af/5f/af",
+ "rgb:af/5f/d7",
+ "rgb:af/5f/ff",
+ "rgb:af/87/00",
+ "rgb:af/87/5f",
+ "rgb:af/87/87",
+ "rgb:af/87/af",
+ "rgb:af/87/d7",
+ "rgb:af/87/ff",
+ "rgb:af/af/00",
+ "rgb:af/af/5f",
+ "rgb:af/af/87",
+ "rgb:af/af/af",
+ "rgb:af/af/d7",
+ "rgb:af/af/ff",
+ "rgb:af/d7/00",
+ "rgb:af/d7/5f",
+ "rgb:af/d7/87",
+ "rgb:af/d7/af",
+ "rgb:af/d7/d7",
+ "rgb:af/d7/ff",
+ "rgb:af/ff/00",
+ "rgb:af/ff/5f",
+ "rgb:af/ff/87",
+ "rgb:af/ff/af",
+ "rgb:af/ff/d7",
+ "rgb:af/ff/ff",
+ "rgb:d7/00/00",
+ "rgb:d7/00/5f",
+ "rgb:d7/00/87",
+ "rgb:d7/00/af",
+ "rgb:d7/00/d7",
+ "rgb:d7/00/ff",
+ "rgb:d7/5f/00",
+ "rgb:d7/5f/5f",
+ "rgb:d7/5f/87",
+ "rgb:d7/5f/af",
+ "rgb:d7/5f/d7",
+ "rgb:d7/5f/ff",
+ "rgb:d7/87/00",
+ "rgb:d7/87/5f",
+ "rgb:d7/87/87",
+ "rgb:d7/87/af",
+ "rgb:d7/87/d7",
+ "rgb:d7/87/ff",
+ "rgb:d7/af/00",
+ "rgb:d7/af/5f",
+ "rgb:d7/af/87",
+ "rgb:d7/af/af",
+ "rgb:d7/af/d7",
+ "rgb:d7/af/ff",
+ "rgb:d7/d7/00",
+ "rgb:d7/d7/5f",
+ "rgb:d7/d7/87",
+ "rgb:d7/d7/af",
+ "rgb:d7/d7/d7",
+ "rgb:d7/d7/ff",
+ "rgb:d7/ff/00",
+ "rgb:d7/ff/5f",
+ "rgb:d7/ff/87",
+ "rgb:d7/ff/af",
+ "rgb:d7/ff/d7",
+ "rgb:d7/ff/ff",
+ "rgb:ff/00/00",
+ "rgb:ff/00/5f",
+ "rgb:ff/00/87",
+ "rgb:ff/00/af",
+ "rgb:ff/00/d7",
+ "rgb:ff/00/ff",
+ "rgb:ff/5f/00",
+ "rgb:ff/5f/5f",
+ "rgb:ff/5f/87",
+ "rgb:ff/5f/af",
+ "rgb:ff/5f/d7",
+ "rgb:ff/5f/ff",
+ "rgb:ff/87/00",
+ "rgb:ff/87/5f",
+ "rgb:ff/87/87",
+ "rgb:ff/87/af",
+ "rgb:ff/87/d7",
+ "rgb:ff/87/ff",
+ "rgb:ff/af/00",
+ "rgb:ff/af/5f",
+ "rgb:ff/af/87",
+ "rgb:ff/af/af",
+ "rgb:ff/af/d7",
+ "rgb:ff/af/ff",
+ "rgb:ff/d7/00",
+ "rgb:ff/d7/5f",
+ "rgb:ff/d7/87",
+ "rgb:ff/d7/af",
+ "rgb:ff/d7/d7",
+ "rgb:ff/d7/ff",
+ "rgb:ff/ff/00",
+ "rgb:ff/ff/5f",
+ "rgb:ff/ff/87",
+ "rgb:ff/ff/af",
+ "rgb:ff/ff/d7",
+ "rgb:ff/ff/ff",
+ "rgb:08/08/08",
+ "rgb:12/12/12",
+ "rgb:1c/1c/1c",
+ "rgb:26/26/26",
+ "rgb:30/30/30",
+ "rgb:3a/3a/3a",
+ "rgb:44/44/44",
+ "rgb:4e/4e/4e",
+ "rgb:58/58/58",
+ "rgb:62/62/62",
+ "rgb:6c/6c/6c",
+ "rgb:76/76/76",
+ "rgb:80/80/80",
+ "rgb:8a/8a/8a",
+ "rgb:94/94/94",
+ "rgb:9e/9e/9e",
+ "rgb:a8/a8/a8",
+ "rgb:b2/b2/b2",
+ "rgb:bc/bc/bc",
+ "rgb:c6/c6/c6",
+ "rgb:d0/d0/d0",
+ "rgb:da/da/da",
+ "rgb:e4/e4/e4",
+ "rgb:ee/ee/ee",
+ NULL_100
+ NULL_100
+ NULL_40
+ NULL_5
+#endif
+
+#ifndef NO_CURSORCOLOR
+ COLOR_CURSOR_BACKGROUND,
+ COLOR_CURSOR_FOREGROUND,
+#endif /* ! NO_CURSORCOLOR */
+ NULL, /* Color_pointer_fg */
+ NULL, /* Color_pointer_bg */
+ NULL, /* Color_border */
+#ifndef NO_BOLD_UNDERLINE_REVERSE
+ NULL, /* Color_BD */
+ NULL, /* Color_IT */
+ NULL, /* Color_UL */
+ NULL, /* Color_RV */
+#endif /* ! NO_BOLD_UNDERLINE_REVERSE */
+#if ENABLE_FRILLS
+ NULL, // Color_underline
+#endif
+#ifdef OPTION_HC
+ NULL,
+ NULL,
+#endif
+ COLOR_SCROLLBAR,
+#ifdef RXVT_SCROLLBAR
+ COLOR_SCROLLTROUGH,
+#endif
+#if OFF_FOCUS_FADING
+ "rgb:00/00/00",
+#endif
+ };
+
+void
+rxvt_term::init_vars ()
+{
+ pix_colors = pix_colors_focused;
+
+ MEvent.time = CurrentTime;
+ MEvent.button = AnyButton;
+ want_refresh = 1;
+ priv_modes = SavedModes = PrivMode_Default;
+ ncol = 80;
+ nrow = 24;
+ int_bwidth = INTERNALBORDERWIDTH;
+ ext_bwidth = EXTERNALBORDERWIDTH;
+ lineSpace = LINESPACE;
+ letterSpace = LETTERSPACE;
+ saveLines = SAVELINES;
+
+ refresh_type = SLOW_REFRESH;
+
+ oldcursor.row = oldcursor.col = -1;
+
+ set_option (Opt_scrollBar);
+ set_option (Opt_scrollTtyOutput);
+ set_option (Opt_jumpScroll);
+ set_option (Opt_skipScroll);
+ set_option (Opt_secondaryScreen);
+ set_option (Opt_secondaryScroll);
+ set_option (Opt_pastableTabs);
+ set_option (Opt_intensityStyles);
+ set_option (Opt_iso14755);
+ set_option (Opt_iso14755_52);
+ set_option (Opt_buffered);
+}
+
+#if ENABLE_PERL
+static void
+rxvt_perl_parse_resource (rxvt_term *term, const char *k, const char *v)
+{
+ rxvt_perl.parse_resource (term, k, false, false, 0, v);
+}
+#endif
+
+/*----------------------------------------------------------------------*/
+const char **
+rxvt_term::init_resources (int argc, const char *const *argv)
+{
+ int i;
+ const char **cmd_argv;
+
+ rs[Rs_name] = rxvt_basename (argv[0]);
+
+ /*
+ * Open display, get options/resources and create the window
+ */
+
+ if ((rs[Rs_display_name] = getenv ("DISPLAY")) == NULL)
+ rs[Rs_display_name] = ":0";
+
+ cmd_argv = get_options (argc, argv);
+
+ if (!(display = displays.get (rs[Rs_display_name])))
+ rxvt_fatal ("can't open display %s, aborting.\n", rs[Rs_display_name]);
+
+ // using a local pointer decreases code size a lot
+ xa = display->xa;
+
+ set (display);
+ extract_resources ();
+
+#if ENABLE_FRILLS
+ if (rs[Rs_visual])
+ select_visual (strtol (rs[Rs_visual], 0, 0));
+ else if (rs[Rs_depth])
+ select_depth (strtol (rs[Rs_depth], 0, 0));
+#endif
+
+ for (int i = NUM_RESOURCES; i--; )
+ if (rs [i] == resval_undef)
+ rs [i] = 0;
+
+#if ENABLE_PERL
+ if (!rs[Rs_perl_ext_1])
+ rs[Rs_perl_ext_1] = "default";
+
+ if ((rs[Rs_perl_ext_1] && *rs[Rs_perl_ext_1])
+ || (rs[Rs_perl_ext_2] && *rs[Rs_perl_ext_2])
+ || (rs[Rs_perl_eval] && *rs[Rs_perl_eval]))
+ {
+ rxvt_perl.init (this);
+ enumerate_resources (rxvt_perl_parse_resource);
+ HOOK_INVOKE ((this, HOOK_INIT, DT_END));
+ }
+#endif
+
+ // must be called after initialising the perl interpreter as it
+ // may invoke the `on_register_command' hook
+ extract_keysym_resources ();
+
+ /*
+ * set any defaults not already set
+ */
+ if (cmd_argv && cmd_argv[0])
+ {
+ if (!rs[Rs_title])
+ rs[Rs_title] = rxvt_basename (cmd_argv[0]);
+
+ if (!rs[Rs_iconName])
+ rs[Rs_iconName] = rs[Rs_title];
+ }
+ else
+ {
+ if (!rs[Rs_title])
+ rs[Rs_title] = rs[Rs_name];
+
+ if (!rs[Rs_iconName])
+ rs[Rs_iconName] = rs[Rs_name];
+ }
+
+ if (rs[Rs_saveLines] && (i = atoi (rs[Rs_saveLines])) >= 0)
+ saveLines = min (i, MAX_SAVELINES);
+
+#if ENABLE_FRILLS
+ if (rs[Rs_int_bwidth] && (i = atoi (rs[Rs_int_bwidth])) >= 0)
+ int_bwidth = min (i, std::numeric_limits<int16_t>::max ());
+
+ if (rs[Rs_ext_bwidth] && (i = atoi (rs[Rs_ext_bwidth])) >= 0)
+ ext_bwidth = min (i, std::numeric_limits<int16_t>::max ());
+
+ if (rs[Rs_lineSpace] && (i = atoi (rs[Rs_lineSpace])) >= 0)
+ lineSpace = min (i, std::numeric_limits<int16_t>::max ());
+
+ if (rs[Rs_letterSpace])
+ letterSpace = atoi (rs[Rs_letterSpace]);
+#endif
+
+#ifdef POINTER_BLANK
+ if (rs[Rs_pointerBlankDelay] && (i = atoi (rs[Rs_pointerBlankDelay])) >= 0)
+ pointerBlankDelay = i;
+ else
+ pointerBlankDelay = 2;
+#endif
+
+ if (rs[Rs_multiClickTime] && (i = atoi (rs[Rs_multiClickTime])) >= 0)
+ multiClickTime = i;
+ else
+ multiClickTime = 500;
+
+ cursor_type = option (Opt_cursorUnderline) ? 1 : 0;
+
+ /* no point having a scrollbar without having any scrollback! */
+ if (!saveLines)
+ set_option (Opt_scrollBar, 0);
+
+ if (!rs[Rs_cutchars])
+ rs[Rs_cutchars] = CUTCHARS;
+
+#ifndef NO_BACKSPACE_KEY
+ if (!rs[Rs_backspace_key])
+# ifdef DEFAULT_BACKSPACE
+ rs[Rs_backspace_key] = DEFAULT_BACKSPACE;
+# else
+ rs[Rs_backspace_key] = "DEC"; /* can toggle between \010 or \177 */
+# endif
+#endif
+
+#ifndef NO_DELETE_KEY
+ if (!rs[Rs_delete_key])
+# ifdef DEFAULT_DELETE
+ rs[Rs_delete_key] = DEFAULT_DELETE;
+# else
+ rs[Rs_delete_key] = "\033[3~";
+# endif
+#endif
+
+ scrollBar.setup (this);
+
+#ifdef XTERM_REVERSE_VIDEO
+ /* this is how xterm implements reverseVideo */
+ if (option (Opt_reverseVideo))
+ {
+ if (!rs[Rs_color + Color_fg])
+ rs[Rs_color + Color_fg] = def_colorName[Color_bg];
+
+ if (!rs[Rs_color + Color_bg])
+ rs[Rs_color + Color_bg] = def_colorName[Color_fg];
+ }
+#endif
+
+ for (i = 0; i < NRS_COLORS; i++)
+ if (!rs[Rs_color + i])
+ rs[Rs_color + i] = def_colorName[i];
+
+#ifndef XTERM_REVERSE_VIDEO
+ /* this is how we implement reverseVideo */
+ if (option (Opt_reverseVideo))
+ ::swap (rs[Rs_color + Color_fg], rs[Rs_color + Color_bg]);
+#endif
+
+ /* convenient aliases for setting fg/bg to colors */
+ color_aliases (Color_fg);
+ color_aliases (Color_bg);
+#ifndef NO_CURSORCOLOR
+ color_aliases (Color_cursor);
+ color_aliases (Color_cursor2);
+#endif /* NO_CURSORCOLOR */
+ color_aliases (Color_pointer_fg);
+ color_aliases (Color_pointer_bg);
+ color_aliases (Color_border);
+#ifndef NO_BOLD_UNDERLINE_REVERSE
+ color_aliases (Color_BD);
+ color_aliases (Color_UL);
+ color_aliases (Color_RV);
+#endif /* ! NO_BOLD_UNDERLINE_REVERSE */
+
+ if (!rs[Rs_color + Color_border])
+ rs[Rs_color + Color_border] = rs[Rs_color + Color_bg];
+
+ return cmd_argv;
+}
+
+/*----------------------------------------------------------------------*/
+void
+rxvt_term::init (stringvec *argv, stringvec *envv)
+{
+ argv->push_back (0);
+ envv->push_back (0);
+
+ this->argv = argv;
+ this->envv = envv;
+
+ env = new char *[this->envv->size ()];
+ for (int i = 0; i < this->envv->size (); i++)
+ env[i] = this->envv->at (i);
+
+ init2 (argv->size () - 1, argv->begin ());
+}
+
+void
+rxvt_term::init (int argc, const char *const *argv, const char *const *envv)
+{
+#if ENABLE_PERL
+ // perl might want to access the stringvecs later, so we need to copy them
+ stringvec *args = new stringvec;
+ for (int i = 0; i < argc; i++)
+ args->push_back (strdup (argv [i]));
+
+ stringvec *envs = new stringvec;
+ for (const char *const *var = envv; *var; var++)
+ envs->push_back (strdup (*var));
+
+ init (args, envs);
+#else
+ init2 (argc, argv);
+#endif
+}
+
+void
+rxvt_term::init2 (int argc, const char *const *argv)
+{
+ SET_R (this);
+ set_locale ("");
+ set_environ (env); // a few things in X do not call setlocale :(
+
+ init_vars ();
+
+ const char **cmd_argv = init_resources (argc, argv);
+
+#ifdef KEYSYM_RESOURCE
+ keyboard->register_done ();
+#endif
+
+ if (const char *path = rs[Rs_chdir])
+ if (*path) // ignored if empty
+ {
+ if (*path != '/')
+ rxvt_fatal ("specified shell working directory must start with a slash, aborting.\n");
+
+ if (chdir (path))
+ rxvt_fatal ("unable to change into specified shell working directory, aborting.\n");
+ }
+
+ if (option (Opt_scrollBar))
+ scrollBar.state = SB_STATE_IDLE; /* set existence for size calculations */
+
+ pty = ptytty::create ();
+
+ create_windows (argc, argv);
+
+ init_xlocale ();
+
+ scr_poweron (); // initialize screen
+
+#if 0
+ XSynchronize (dpy, True);
+#endif
+
+ if (option (Opt_scrollBar))
+ scrollBar.resize (); /* create and map scrollbar */
+
+#if ENABLE_PERL
+ rootwin_ev.start (display, display->root);
+#endif
+
+ init_done = 1;
+
+ init_command (cmd_argv);
+
+ if (pty->pty >= 0)
+ pty_ev.start (pty->pty, ev::READ);
+
+ HOOK_INVOKE ((this, HOOK_START, DT_END));
+
+#if ENABLE_XEMBED
+ if (rs[Rs_embed])
+ {
+ long info[2] = { 0, XEMBED_MAPPED };
+
+ XChangeProperty (dpy, parent, xa[XA_XEMBED_INFO], xa[XA_XEMBED_INFO],
+ 32, PropModeReplace, (unsigned char *)&info, 2);
+ }
+#endif
+
+#if HAVE_STARTUP_NOTIFICATION
+ SnDisplay *snDisplay;
+ SnLauncheeContext *snContext;
+
+ snDisplay = sn_display_new (dpy, NULL, NULL);
+ snContext = sn_launchee_context_new_from_environment (snDisplay, DefaultScreen (dpy));
+
+ /* Tell the window manager that this window is part of the startup context */
+ if (snContext)
+ sn_launchee_context_setup_window (snContext, parent);
+#endif
+
+ XMapWindow (dpy, vt);
+ XMapWindow (dpy, parent);
+
+#if HAVE_STARTUP_NOTIFICATION
+ if (snContext)
+ {
+ /* Mark the startup process as complete */
+ sn_launchee_context_complete (snContext);
+
+ sn_launchee_context_unref (snContext);
+ }
+
+ sn_display_unref (snDisplay);
+#endif
+
+ refresh_check ();
+}
+
+/*----------------------------------------------------------------------*/
+void
+rxvt_term::init_env ()
+{
+ char *val;
+ char *env_display;
+ char *env_windowid;
+ char *env_colorfgbg;
+ char *env_term;
+
+#ifdef DISPLAY_IS_IP
+ /* Fixup display_name for export over pty to any interested terminal
+ * clients via "ESC[7n" (e.g. shells). Note we use the pure IP number
+ * (for the first non-loopback interface) that we get from
+ * rxvt_network_display (). This is more "name-resolution-portable", if you
+ * will, and probably allows for faster x-client startup if your name
+ * server is beyond a slow link or overloaded at client startup. Of
+ * course that only helps the shell's child processes, not us.
+ *
+ * Giving out the display_name also affords a potential security hole
+ */
+ val = rxvt_network_display (rs[Rs_display_name]);
+ rs[Rs_display_name] = (const char *)val;
+
+ if (val == NULL)
+#endif /* DISPLAY_IS_IP */
+ val = XDisplayString (dpy);
+
+ if (rs[Rs_display_name] == NULL)
+ rs[Rs_display_name] = val; /* use broken `:0' value */
+
+ env_display = (char *)rxvt_malloc (strlen (val) + 9);
+
+ sprintf (env_display, "DISPLAY=%s", val);
+
+ env_windowid = (char *)rxvt_malloc (21);
+ sprintf (env_windowid, "WINDOWID=%lu", (unsigned long)parent);
+
+ /* add entries to the environment:
+ * @ DISPLAY: in case we started with -display
+ * @ WINDOWID: X window id number of the window
+ * @ COLORTERM: terminal sub-name and also indicates its color
+ * @ TERM: terminal name
+ * @ TERMINFO: path to terminfo directory
+ * @ COLORFGBG: fg;bg color codes
+ */
+ putenv (env_display);
+ putenv (env_windowid);
+
+ env_colorfgbg = get_colorfgbg ();
+ putenv (env_colorfgbg);
+
+#ifdef RXVT_TERMINFO
+ putenv ("TERMINFO=" RXVT_TERMINFO);
+#endif
+
+ if (depth <= 2)
+ putenv ((char *)"COLORTERM=" COLORTERMENV "-mono");
+ else
+ putenv ((char *)"COLORTERM=" COLORTERMENVFULL);
+
+ if (rs[Rs_term_name] != NULL)
+ {
+ env_term = (char *)rxvt_malloc (strlen (rs[Rs_term_name]) + 6);
+ sprintf (env_term, "TERM=%s", rs[Rs_term_name]);
+ putenv (env_term);
+ }
+ else
+ putenv ((char *)"TERM=" TERMENV);
+
+#ifdef HAVE_UNSETENV
+ /* avoid passing old settings and confusing term size */
+ unsetenv ("LINES");
+ unsetenv ("COLUMNS");
+ unsetenv ("TERMCAP"); /* terminfo should be okay */
+#endif /* HAVE_UNSETENV */
+}
+
+/*----------------------------------------------------------------------*/
+void
+rxvt_term::set_locale (const char *locale)
+{
+ set_environ (env);
+
+ free (this->locale);
+ this->locale = setlocale (LC_CTYPE, locale);
+
+ if (!this->locale)
+ {
+ if (*locale)
+ {
+ rxvt_warn ("unable to set locale \"%s\", using C locale instead.\n", locale);
+ setlocale (LC_CTYPE, "C");
+ }
+ else
+ rxvt_warn ("default locale unavailable, check LC_* and LANG variables. Continuing.\n");
+
+ this->locale = (char *)"C"; /* strdup'ed below */
+ }
+
+
+ this->locale = strdup (this->locale);
+ SET_LOCALE (this->locale);
+ mbstate.reset ();
+
+#if HAVE_NL_LANGINFO
+ char *codeset = nl_langinfo (CODESET);
+ // /^UTF.?8/i
+ enc_utf8 = (codeset[0] == 'U' || codeset[0] == 'u')
+ && (codeset[1] == 'T' || codeset[1] == 't')
+ && (codeset[2] == 'F' || codeset[2] == 'f')
+ && (codeset[3] == '8' || codeset[4] == '8');
+#else
+ enc_utf8 = 0;
+#endif
+}
+
+void
+rxvt_term::init_xlocale ()
+{
+ set_environ (env);
+
+#if USE_XIM
+ if (!locale)
+ rxvt_warn ("setting locale failed, continuing without locale support.\n");
+ else
+ {
+ set_string_property (xa[XA_WM_LOCALE_NAME], locale);
+
+ if (!XSupportsLocale ())
+ {
+ rxvt_warn ("the locale is not supported by Xlib, continuing without locale support.\n");
+ return;
+ }
+
+ im_ev.start (display);
+
+ /* see if we can connect already */
+ im_cb ();
+ }
+#endif
+}
+
+/*----------------------------------------------------------------------*/
+void
+rxvt_term::init_command (const char *const *argv)
+{
+ /*
+ * Initialize the command connection.
+ * This should be called after the X server connection is established.
+ */
+
+#ifdef META8_OPTION
+ meta_char = option (Opt_meta8) ? 0x80 : C0_ESC;
+#endif
+
+ get_ourmods ();
+
+ if (!option (Opt_scrollTtyOutput))
+ priv_modes |= PrivMode_TtyOutputInh;
+ if (option (Opt_scrollTtyKeypress))
+ priv_modes |= PrivMode_Keypress;
+ if (!option (Opt_jumpScroll))
+ priv_modes |= PrivMode_smoothScroll;
+
+#ifndef NO_BACKSPACE_KEY
+ if (strcmp (rs[Rs_backspace_key], "DEC") == 0)
+ priv_modes |= PrivMode_HaveBackSpace;
+#endif
+
+ /* add value for scrollBar */
+ if (scrollBar.state)
+ {
+ priv_modes |= PrivMode_scrollBar;
+ SavedModes |= PrivMode_scrollBar;
+ }
+
+ run_command (argv);
+}
+
+/*----------------------------------------------------------------------*/
+void
+rxvt_term::get_colors ()
+{
+ int i;
+
+#ifdef OFF_FOCUS_FADING
+ pix_colors = pix_colors_focused;
+#endif
+
+ for (i = 0; i < NRS_COLORS; i++)
+ if (const char *name = rs[Rs_color + i])
+ set_color (pix_colors [i], name);
+
+ /*
+ * get scrollBar shadow colors
+ *
+ * The calculations of topShadow/bottomShadow values are adapted
+ * from the fvwm window manager.
+ */
+#ifdef RXVT_SCROLLBAR
+ pix_colors [Color_scroll].fade (this, 50, pix_colors [Color_bottomShadow]);
+
+ rgba cscroll;
+ pix_colors [Color_scroll].get (cscroll);
+
+ /* topShadowColor */
+ if (!pix_colors[Color_topShadow].set (this,
+ rgba (
+ min ((int)rgba::MAX_CC, max (cscroll.r / 5, cscroll.r) * 7 / 5),
+ min ((int)rgba::MAX_CC, max (cscroll.g / 5, cscroll.g) * 7 / 5),
+ min ((int)rgba::MAX_CC, max (cscroll.b / 5, cscroll.b) * 7 / 5),
+ cscroll.a)
+ ))
+ alias_color (Color_topShadow, Color_White);
+#endif
+
+#ifdef OFF_FOCUS_FADING
+ for (i = 0; i < NRS_COLORS; i++)
+ update_fade_color (i, true);
+#endif
+}
+
+/*----------------------------------------------------------------------*/
+/* color aliases, fg/bg bright-bold */
+void
+rxvt_term::color_aliases (int idx)
+{
+ if (rs[Rs_color + idx] && isdigit (*rs[Rs_color + idx]))
+ {
+ int i = atoi (rs[Rs_color + idx]);
+
+ if (i >= 8 && i <= 15)
+ /* bright colors */
+ rs[Rs_color + idx] = rs[Rs_color + minBrightCOLOR + i - 8];
+ else if (i >= 0 && i <= 7)
+ /* normal colors */
+ rs[Rs_color + idx] = rs[Rs_color + minCOLOR + i];
+ }
+}
+
+/*----------------------------------------------------------------------*/
+/*
+ * Probe the modifier keymap to get the Meta (Alt) and Num_Lock settings
+ * Use resource ``modifier'' to override the Meta modifier
+ */
+void
+rxvt_term::get_ourmods ()
+{
+ int i, j, k;
+ int requestedmeta, realmeta, realalt;
+ const char *cm, *rsmod;
+ XModifierKeymap *map;
+ KeyCode *kc;
+ const unsigned int modmasks[] =
+ {
+ Mod1Mask, Mod2Mask, Mod3Mask, Mod4Mask, Mod5Mask
+ };
+
+ requestedmeta = realmeta = realalt = 0;
+ rsmod = rs[Rs_modifier];
+
+ if (rsmod
+ && strcasecmp (rsmod, "mod1") >= 0 && strcasecmp (rsmod, "mod5") <= 0)
+ requestedmeta = rsmod[3] - '0';
+
+ map = XGetModifierMapping (dpy);
+ kc = map->modifiermap;
+
+ for (i = 1; i < 6; i++)
+ {
+ k = (i + 2) * map->max_keypermod; /* skip shift/lock/control */
+
+ for (j = map->max_keypermod; j--; k++)
+ {
+ if (kc[k] == 0)
+ break;
+
+ switch (rxvt_XKeycodeToKeysym (dpy, kc[k], 0))
+ {
+ case XK_Num_Lock:
+ ModNumLockMask = modmasks[i - 1];
+ continue;
+
+ case XK_ISO_Level3_Shift:
+ ModLevel3Mask = modmasks[i - 1];
+ continue;
+
+ case XK_Meta_L:
+ case XK_Meta_R:
+ cm = "meta";
+ realmeta = i;
+ break;
+
+ case XK_Alt_L:
+ case XK_Alt_R:
+ cm = "alt";
+ realalt = i;
+ break;
+
+ case XK_Super_L:
+ case XK_Super_R:
+ cm = "super";
+ break;
+
+ case XK_Hyper_L:
+ case XK_Hyper_R:
+ cm = "hyper";
+ break;
+
+ default:
+ continue;
+ }
+
+ if (rsmod && strncasecmp (rsmod, cm, strlen (cm)) == 0)
+ requestedmeta = i;
+ }
+ }
+
+ XFreeModifiermap (map);
+
+ i = requestedmeta ? requestedmeta
+ : realmeta ? realmeta
+ : realalt ? realalt
+ : 0;
+
+ if (i)
+ ModMetaMask = modmasks[i - 1];
+}
+
+void
+rxvt_term::set_icon (const char *file)
+{
+#if HAVE_PIXBUF && ENABLE_