--- rxvt-unicode/src/main.C 2005/12/18 00:59:42 1.149 +++ rxvt-unicode/src/main.C 2006/01/24 19:40:12 1.199 @@ -13,7 +13,7 @@ * Copyright (c) 1997,1998 Oezguer Kesim * Copyright (c) 1998-2001 Geoff Wing * - extensive modifications - * Copyright (c) 2003-2004 Marc Lehmann + * Copyright (c) 2003-2006 Marc Lehmann * * 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 @@ -32,6 +32,10 @@ #include "../config.h" /* NECESSARY */ #include "rxvt.h" /* NECESSARY */ +#include "keyboard.h" +#include "rxvtperl.h" + +#include #include #include @@ -44,16 +48,15 @@ # include #endif -#ifdef KEYSYM_RESOURCE -# include "keyboard.h" -#endif - vector rxvt_term::termlist; -static char curlocale[128]; +// used to tell global functions which terminal instance is "active" +rxvt_t rxvt_current_term; + +static char curlocale[128], savelocale[128]; bool -rxvt_set_locale (const char *locale) +rxvt_set_locale (const char *locale) NOTHROW { if (!locale || !strncmp (locale, curlocale, 128)) return false; @@ -63,6 +66,19 @@ return true; } +void +rxvt_push_locale (const char *locale) NOTHROW +{ + strcpy (savelocale, curlocale); + rxvt_set_locale (locale); +} + +void +rxvt_pop_locale () NOTHROW +{ + rxvt_set_locale (savelocale); +} + #if ENABLE_COMBINING class rxvt_composite_vec rxvt_composite; @@ -135,9 +151,6 @@ #ifdef HAVE_SCROLLBARS scrollbar_ev (this, &rxvt_term::x_cb), #endif -#ifdef MENUBAR - menubar_ev (this, &rxvt_term::x_cb), -#endif #ifdef CURSOR_BLINK cursor_blink_ev (this, &rxvt_term::cursor_blink_cb), #endif @@ -159,8 +172,12 @@ #ifdef USE_XIM im_ev (this, &rxvt_term::im_cb), #endif +#ifndef NO_BELL + bell_ev (this, &rxvt_term::bell_cb), +#endif termwin_ev (this, &rxvt_term::x_cb), vt_ev (this, &rxvt_term::x_cb), + child_ev (this, &rxvt_term::child_cb), check_ev (this, &rxvt_term::check_cb), flush_ev (this, &rxvt_term::flush_cb), destroy_ev (this, &rxvt_term::destroy_cb), @@ -173,9 +190,6 @@ #ifdef KEYSYM_RESOURCE keyboard = new keyboard_manager; - - if (!keyboard) - rxvt_fatal ("out of memory, aborting.\n"); #endif } @@ -186,11 +200,7 @@ if (cmd_pid) kill (-cmd_pid, SIGHUP); -#ifdef UTMP_SUPPORT - privileged_utmp (RESTORE); -#endif - - pty.put (); + delete pty; pty = 0; } rxvt_term::~rxvt_term () @@ -215,9 +225,6 @@ #ifdef USE_XIM im_destroy (); #endif -#ifdef MENUBAR - if (menubarGC) XFreeGC (disp, menubarGC); -#endif #ifdef XTERM_SCROLLBAR if (xscrollbarGC) XFreeGC (disp, xscrollbarGC); if (ShadowGC) XFreeGC (disp, ShadowGC); @@ -237,18 +244,13 @@ if (upArrowHi) XFreePixmap (disp, upArrowHi); if (downArrowHi) XFreePixmap (disp, downArrowHi); #endif -#if defined(MENUBAR) || defined(RXVT_SCROLLBAR) +#ifdef RXVT_SCROLLBAR if (topShadowGC) XFreeGC (disp, topShadowGC); if (botShadowGC) XFreeGC (disp, botShadowGC); if (scrollbarGC) XFreeGC (disp, scrollbarGC); #endif if (gc) XFreeGC (disp, gc); -#if defined(MENUBAR) && (MENUBAR_MAX > 1) - delete menuBar.drawable; - //if (menuBar.win) - // XDestroyWindow (disp, menuBar.win); -#endif delete drawable; // destroy all windows if (parent[0]) @@ -256,7 +258,6 @@ } // TODO: free pixcolours, colours should become part of rxvt_display - delete pix_colors_focused; #if OFF_FOCUS_FADING delete pix_colors_unfocused; @@ -288,12 +289,27 @@ #endif } +// child has exited, usually destroys +void +rxvt_term::child_cb (child_watcher &w, int status) +{ + HOOK_INVOKE ((this, HOOK_CHILD_EXIT, DT_INT, status, DT_END)); + + cmd_pid = 0; + + if (!OPTION (Opt_hold)) + destroy (); +} + void rxvt_term::destroy () { if (destroy_ev.active) return; + if (HOOK_INVOKE ((this, HOOK_DESTROY, DT_END))) + return; + #if ENABLE_OVERLAY scr_overlay_off (); #endif @@ -306,9 +322,6 @@ #if HAVE_SCROLLBARS scrollbar_ev.stop (display); #endif -#if MENUBAR - menubar_ev.stop (display); -#endif #if TRANSPARENT rootwin_ev.stop (display); #endif @@ -341,7 +354,7 @@ void rxvt_term::destroy_cb (time_watcher &w) { - SET_R (this); + make_current (); delete this; } @@ -439,11 +452,13 @@ /*----------------------------------------------------------------------*/ bool -rxvt_term::init (int argc, const char *const *argv) +rxvt_term::init (int argc, const char *const *argv, stringvec *envv) { - SET_R (this); + this->envv = envv; + SET_R (this); set_locale (""); + set_environ (envv); // few things in X do not call setlocale :( if (!init_vars ()) return false; @@ -456,36 +471,31 @@ keyboard->register_done (); #endif -#if MENUBAR_MAX - menubar_read (rs[Rs_menu]); -#endif #ifdef HAVE_SCROLLBARS - if (options & Opt_scrollBar) + if (OPTION (Opt_scrollBar)) scrollBar.setIdle (); /* set existence for size calculations */ #endif + pty = ptytty::create (); + create_windows (argc, argv); dDisp; init_xlocale (); - scr_reset (); /* initialize screen */ + scr_reset (); // initialize screen #if 0 XSynchronize (disp, True); #endif #ifdef HAVE_SCROLLBARS - if (options & Opt_scrollBar) + if (OPTION (Opt_scrollBar)) resize_scrollbar (); /* create and map scrollbar */ #endif -#if (MENUBAR_MAX) - if (menubar_visible ()) - XMapWindow (disp, menuBar.win); -#endif #ifdef TRANSPARENT - if (options & Opt_transparent) + if (OPTION (Opt_transparent)) { XSelectInput (disp, display->root, PropertyChangeMask); check_our_parents (); @@ -493,79 +503,59 @@ } #endif - XMapWindow (disp, vt); - XMapWindow (disp, parent[0]); - set_colorfgbg (); init_command (cmd_argv); free (cmd_argv); - pty_ev.start (pty.pty, EVENT_READ); + if (pty->pty >= 0) + pty_ev.start (pty->pty, EVENT_READ); check_ev.start (); + HOOK_INVOKE ((this, HOOK_START, DT_END)); + + XMapWindow (disp, vt); + XMapWindow (disp, parent[0]); + return true; } static struct sig_handlers { - sig_watcher sw_chld, sw_term, sw_int; + sig_watcher sw_term, sw_int; - void sig_chld (sig_watcher &w) - { - // we are being called for every SIGCHLD, find the corresponding term - int pid; - - while ((pid = waitpid (-1, NULL, WNOHANG)) > 0) - for (rxvt_term **t = rxvt_term::termlist.begin (); t < rxvt_term::termlist.end (); t++) - if (pid == (*t)->cmd_pid) - { - (*t)->destroy (); - break; - } - } - /* * Catch a fatal signal and tidy up before quitting */ void sig_term (sig_watcher &w) { -#ifdef DEBUG_CMD - rxvt_warn ("caught signal %d, exiting.\n", w.signum); -#endif rxvt_emergency_cleanup (); signal (w.signum, SIG_DFL); kill (getpid (), w.signum); } sig_handlers () - : sw_chld (this, &sig_handlers::sig_chld), - sw_term (this, &sig_handlers::sig_term), + : sw_term (this, &sig_handlers::sig_term), sw_int (this, &sig_handlers::sig_term) { } } sig_handlers; +char **rxvt_environ; // startup environment + void rxvt_init () { - /* - * Save and then give up any super-user privileges - * If we need privileges in any area then we must specifically request it. - * We should only need to be root in these cases: - * 1. write utmp entries on some systems - * 2. chown tty on some systems - */ - rxvt_privileges (SAVE); - rxvt_privileges (IGNORE); + ptytty::init (); + + rxvt_environ = environ; signal (SIGHUP, SIG_IGN); signal (SIGPIPE, SIG_IGN); - sig_handlers.sw_chld.start (SIGCHLD); sig_handlers.sw_term.start (SIGTERM); sig_handlers.sw_int.start (SIGINT); @@ -575,6 +565,8 @@ old_xerror_handler = XSetErrorHandler ((XErrorHandler) rxvt_xerror_handler); // TODO: handle this with exceptions and tolerate the memory loss XSetIOErrorHandler (rxvt_xioerror_handler); + + XrmInitialize (); } /* ------------------------------------------------------------------------- * @@ -602,7 +594,7 @@ return p; } -void * +void * rxvt_realloc (void *ptr, size_t size) { void *p = realloc (ptr, size); @@ -613,80 +605,6 @@ return p; } -/* ------------------------------------------------------------------------- * - * PRIVILEGED OPERATIONS * - * ------------------------------------------------------------------------- */ -/* take care of suid/sgid super-user (root) privileges */ -void -rxvt_privileges (rxvt_privaction action) -{ -#if (defined(HAVE_SETEUID) || defined(HAVE_SETREUID)) && !defined(__CYGWIN32__) - static uid_t euid; - static gid_t egid; -#endif - -#if ! defined(__CYGWIN32__) -# if !defined(HAVE_SETEUID) && defined(HAVE_SETREUID) - /* setreuid () is the poor man's setuid (), seteuid () */ -# define seteuid(a) setreuid(-1, (a)) -# define setegid(a) setregid(-1, (a)) -# define HAVE_SETEUID -# endif -# ifdef HAVE_SETEUID - switch (action) - { - case IGNORE: - /* - * change effective uid/gid - not real uid/gid - so we can switch - * back to root later, as required - */ - seteuid (getuid ()); - setegid (getgid ()); - break; - case SAVE: - euid = geteuid (); - egid = getegid (); - break; - case RESTORE: - seteuid (euid); - setegid (egid); - break; - } -# else - switch (action) - { - case IGNORE: - setuid (getuid ()); - setgid (getgid ()); - /* FALLTHROUGH */ - case SAVE: - /* FALLTHROUGH */ - case RESTORE: - break; - } -# endif -#endif -} - -#ifdef UTMP_SUPPORT -void -rxvt_term::privileged_utmp (rxvt_privaction action) -{ - if ((options & Opt_utmpInhibit) - || !pty.name || !*pty.name) - return; - - rxvt_privileges (RESTORE); - - if (action == SAVE) - makeutent (pty.name, rs[Rs_display_name]); - else - cleanutent (); - - rxvt_privileges (IGNORE); -} -#endif - /*----------------------------------------------------------------------*/ /* * window size/position calculcations for XSizeHint and other storage. @@ -696,14 +614,11 @@ rxvt_term::window_calc (unsigned int newwidth, unsigned int newheight) { short recalc_x, recalc_y; - int x, y, sb_w, mb_h, flags; + int x, y, sb_w, flags; unsigned int w, h; unsigned int max_width, max_height; dDisp; - D_SIZE ((stderr, "< Cols/Rows: %3d x %3d ; Width/Height: %4d x %4d", - ncol, nrow, szHint.width, szHint.height)); - szHint.flags = PMinSize | PResizeInc | PBaseSize | PWinGravity; szHint.win_gravity = NorthWestGravity; /* szHint.min_aspect.x = szHint.min_aspect.y = 1; */ @@ -720,13 +635,13 @@ if (flags & WidthValue) { - ncol = BOUND_POSITIVE_INT16 (w); + ncol = clamp (w, 0, std::numeric_limits::max ()); szHint.flags |= USSize; } if (flags & HeightValue) { - nrow = BOUND_POSITIVE_INT16 (h); + nrow = clamp (h, 0, std::numeric_limits::max ()); szHint.flags |= USSize; } @@ -767,24 +682,17 @@ szHint.base_width = szHint.base_height = 2 * int_bwidth; - sb_w = mb_h = 0; + sb_w = 0; window_vt_x = window_vt_y = int_bwidth; - if (scrollbar_visible ()) + if (scrollBar.state) { sb_w = scrollbar_TotalWidth (); szHint.base_width += sb_w; - if (!(options & Opt_scrollBar_right)) + if (!OPTION (Opt_scrollBar_right)) window_vt_x += sb_w; } - if (menubar_visible ()) - { - mb_h = menuBar_TotalHeight (); - szHint.base_height += mb_h; - window_vt_y += mb_h; - } - szHint.width_inc = fwidth; szHint.height_inc = fheight; szHint.min_width = szHint.base_width + szHint.width_inc; @@ -797,7 +705,7 @@ } else { - MIN_IT (width, max_width); + min_it (width, max_width); szHint.width = szHint.base_width + width; } @@ -808,11 +716,11 @@ } else { - MIN_IT (height, max_height); + min_it (height, max_height); szHint.height = szHint.base_height + height; } - if (scrollbar_visible () && (options & Opt_scrollBar_right)) + if (scrollBar.state && OPTION (Opt_scrollBar_right)) window_sb_x = szHint.width - sb_w; if (recalc_x) @@ -822,10 +730,6 @@ ncol = width / fwidth; nrow = height / fheight; - D_SIZE ((stderr, "> Cols/Rows: %3d x %3d ; Width/Height: %4d x %4d", - ncol, nrow, szHint.width, - szHint.height)); - return; } /*----------------------------------------------------------------------*/ @@ -836,7 +740,7 @@ void rxvt_term::tt_winch () { - if (pty.pty < 0) + if (pty->pty < 0) return; struct winsize ws; @@ -845,7 +749,7 @@ ws.ws_row = nrow; ws.ws_xpixel = width; ws.ws_ypixel = height; - (void)ioctl (pty.pty, TIOCSWINSZ, &ws); + (void)ioctl (pty->pty, TIOCSWINSZ, &ws); #if 0 // TIOCSWINSZ⎈ is supposed to do this automatically and correctly @@ -891,9 +795,7 @@ fwidth = prop.width; fheight = prop.height; - fweight = prop.weight; - fslant = prop.slant; - fbase = (*fs)[1]->ascent; + fbase = prop.ascent; for (int style = 1; style < 4; style++) { @@ -937,7 +839,6 @@ void rxvt_term::set_string_property (Atom prop, const char *str, int len) { - // TODO: SMART_WINDOW_TITLE XChangeProperty (display->display, parent[0], prop, XA_STRING, 8, PropModeReplace, (const unsigned char *)str, len >= 0 ? len : strlen (str)); @@ -945,7 +846,6 @@ void rxvt_term::set_utf8_property (Atom prop, const char *str, int len) { - // TODO: SMART_WINDOW_TITLE wchar_t *ws = rxvt_mbstowcs (str, len); char *s = rxvt_wcstoutf8 (ws); @@ -996,11 +896,9 @@ if (i >= 8 && i <= 15) { /* bright colors */ i -= 8; -# ifndef NO_BRIGHTCOLOR pix_colors_focused[idx] = pix_colors_focused[minBrightCOLOR + i]; SET_PIXCOLOR (idx); goto done; -# endif } if (i >= 0 && i <= 7) @@ -1125,7 +1023,8 @@ rxvt_term::resize_all_windows (unsigned int newwidth, unsigned int newheight, int ignoreparent) { int fix_screen; - int old_width = szHint.width, old_height = szHint.height; + int old_width = szHint.width; + int old_height = szHint.height; dDisp; window_calc (newwidth, newheight); @@ -1157,9 +1056,9 @@ y -= y1; } - x1 = (DisplayWidth (disp, display->screen) - old_width) / 2; + x1 = (DisplayWidth (disp, display->screen) - old_width ) / 2; y1 = (DisplayHeight (disp, display->screen) - old_height) / 2; - dx = old_width - szHint.width; + dx = old_width - szHint.width; dy = old_height - szHint.height; /* Check position of the center of the window */ @@ -1183,7 +1082,7 @@ if (fix_screen || newwidth != old_width || newheight != old_height) { - if (scrollbar_visible ()) + if (scrollBar.state) { XMoveResizeWindow (disp, scrollBar.win, window_sb_x, 0, @@ -1191,14 +1090,9 @@ resize_scrollbar (); } - if (menubar_visible ()) - XMoveResizeWindow (disp, menuBar.win, - window_vt_x, 0, - TermWin_TotalWidth (), menuBar_TotalHeight ()); - XMoveResizeWindow (disp, vt, window_vt_x, window_vt_y, - TermWin_TotalWidth (), TermWin_TotalHeight ()); + width, height); scr_clear (); #ifdef XPM_BACKGROUND @@ -1207,30 +1101,7 @@ } if (fix_screen || old_height == 0) - { - int curr_screen = -1; - int old_ncol = prev_ncol; - - /* scr_reset only works on the primary screen */ - if (old_height) /* this is not the first time through */ - { - unsigned int ocol = ncol; - ncol = prev_ncol; // save b/c scr_blank_screen_mem uses this - curr_screen = scr_change_screen (PRIMARY); - ncol = ocol; - } - - scr_reset (); - - if (curr_screen >= 0) /* this is not the first time through */ - { - scr_change_screen (curr_screen); - selection_check (old_ncol != ncol ? 4 : 0); - } - } - - old_width = szHint.width; - old_height = szHint.height; + scr_reset (); #ifdef XPM_BACKGROUND if (pixmap) @@ -1389,10 +1260,11 @@ char **s; XIMStyles *xim_styles; + set_environ (envv); + if (! ((p = XSetLocaleModifiers (modifiers)) && *p)) return false; - D_MAIN ((stderr, "rxvt_IM_get_IC ()")); input_method = display->get_xim (locale, modifiers); if (input_method == NULL) return false; @@ -1548,10 +1420,12 @@ return false; } + if (!XGetICValues (Input_Context, XNFilterEvents, &vt_emask_xim, NULL)) + vt_select_input (); + if (input_style & XIMPreeditArea) IMSetStatusPosition (); - D_MAIN ((stderr, "rxvt_IM_get_IC () - successful connection")); return true; } @@ -1563,11 +1437,10 @@ char **s; char buf[IMBUFSIZ]; - SET_R (this); + make_current (); im_destroy (); - D_MAIN ((stderr, "rxvt_IMInstantiateCallback ()")); if (Input_Context) return; @@ -1650,7 +1523,4 @@ } #endif /* USE_XIM */ -/*----------------------------------------------------------------------*/ -rxvt_t rxvt_current_term; - /*----------------------- end-of-file (C source) -----------------------*/