--- rxvt-unicode/src/main.C 2004/02/22 08:09:38 1.40 +++ rxvt-unicode/src/main.C 2004/04/02 15:15:26 1.65 @@ -46,17 +46,84 @@ #include +vector rxvt_term::termlist; + static char curlocale[128]; -void +bool rxvt_set_locale (const char *locale) { - if (locale && STRNCMP (locale, curlocale, 128)) + if (!locale || !STRNCMP (locale, curlocale, 128)) + return false; + + STRNCPY (curlocale, locale, 128); + setlocale (LC_CTYPE, curlocale); + return true; +} + +#if ENABLE_COMBINING +class rxvt_composite_vec rxvt_composite; + +text_t rxvt_composite_vec::compose (unicode_t c1, unicode_t c2) +{ + compose_char *cc; + + // break compose chains, as stupid readline really likes to duplicate + // composing characters for some reason near the end of a line. + cc = (*this)[c1]; + while (cc) + { + if (cc->c2 == c2) return c1; + cc = (*this)[cc->c1]; + } + + // check to see wether this combination already exists otherwise + for (cc = v.end (); cc-- > v.begin (); ) + { + if (cc->c1 == c1 && cc->c2 == c2) + return COMPOSE_LO + (cc - v.begin ()); + } + + // allocate a new combination + if (v.size () == COMPOSE_HI - COMPOSE_LO + 1) + { + static int seen; + + if (!seen++) + fprintf (stderr, "too many unrepresentable composite characters, try --enable-unicode3\n"); + + return REPLACEMENT_CHAR; + } + + v.push_back (compose_char (c1, c2)); + + return v.size () - 1 + COMPOSE_LO; +} + +int rxvt_composite_vec::expand (unicode_t c, wchar_t *r) +{ + compose_char *cc = (*this)[c]; + + if (!cc) { - STRNCPY (curlocale, locale, 128); - setlocale (LC_CTYPE, curlocale); + if (r) *r = c; + return 1; } + + int len = expand (cc->c1, r); + + if (r) r += len; + + if (cc->c2 != NOCHAR) + { + len++; + if (r) *r++ = cc->c2; + } + + return len; + } +#endif void * rxvt_term::operator new (size_t s) @@ -82,7 +149,7 @@ scrollbar_ev (this, &rxvt_term::x_cb), #endif #ifdef MENUBAR - menubar_ev (this, &rxvt_term::x_cb), fixme + menubar_ev (this, &rxvt_term::x_cb), #endif #ifdef CURSOR_BLINK cursor_blink_ev (this, &rxvt_term::cursor_blink_cb), @@ -102,10 +169,14 @@ incr_ev (this, &rxvt_term::incr_cb) { cmdbuf_ptr = cmdbuf_endp = cmdbuf_base; + + termlist.push_back (this); } rxvt_term::~rxvt_term () { + termlist.erase (find (termlist.begin (), termlist.end(), this)); + if (cmd_fd >= 0) close (cmd_fd); @@ -119,8 +190,48 @@ delete TermWin.fontset; if (display) - if (TermWin.parent[0]) - XDestroyWindow (display->display, TermWin.parent[0]); + { + selection_clear (); + +#ifdef MENUBAR + if (menubarGC) XFreeGC (display->display, menubarGC); +#endif +#ifdef XTERM_SCROLLBAR + if (xscrollbarGC) XFreeGC (display->display, xscrollbarGC); + if (ShadowGC) XFreeGC (display->display, ShadowGC); +#endif +#ifdef PLAIN_SCROLLBAR + if (pscrollbarGC) XFreeGC (display->display, pscrollbarGC); +#endif +#ifdef NEXT_SCROLLBAR + if (blackGC) XFreeGC (display->display, blackGC); + if (whiteGC) XFreeGC (display->display, whiteGC); + if (grayGC) XFreeGC (display->display, grayGC); + if (darkGC) XFreeGC (display->display, darkGC); + if (stippleGC) XFreeGC (display->display, stippleGC); + if (dimple) XFreePixmap (display->display, dimple); + if (upArrow) XFreePixmap (display->display, upArrow); + if (downArrow) XFreePixmap (display->display, downArrow); + if (upArrowHi) XFreePixmap (display->display, upArrowHi); + if (downArrowHi) XFreePixmap (display->display, downArrowHi); +#endif +#if defined(MENUBAR) || defined(RXVT_SCROLLBAR) + if (topShadowGC) XFreeGC (display->display, topShadowGC); + if (botShadowGC) XFreeGC (display->display, botShadowGC); + if (scrollbarGC) XFreeGC (display->display, scrollbarGC); +#endif + if (TermWin.gc) XFreeGC (display->display, TermWin.gc); + +#if defined(MENUBAR) && (MENUBAR_MAX > 1) + delete menuBar.drawable; + //if (menuBar.win) + // XDestroyWindow (display->display, menuBar.win); +#endif + delete TermWin.drawable; + // destroy all windows + if (TermWin.parent[0]) + XDestroyWindow (display->display, TermWin.parent[0]); + } // TODO: free pixcolours, colours should become part of rxvt_display @@ -130,12 +241,20 @@ scr_release (); + /* clear all resources */ + for (int i = 0; i < allocated.size (); i++) + free (allocated[i]); + + free (selection.text); + // TODO: manage env vars in child only(!) free (env_windowid); free (env_display); free (env_term); free (env_colorfgbg); free (locale); +#if 0 free (codeset); +#endif delete envv; delete argv; @@ -186,55 +305,14 @@ /*----------------------------------------------------------------------*/ /* rxvt_init () */ -/* LIBPROTO */ -rxvt_t -rxvt_init (int argc, const char *const *argv) -{ - SET_R (new rxvt_term); - - if (!GET_R->init_vars () || !GET_R->init (argc, argv)) - { - delete GET_R; - SET_R (0); - } - - return GET_R; -} - -static int (*old_xerror_handler) (Display *dpy, XErrorEvent *event); - -void -rxvt_init_signals () -{ - /* install exit handler for cleanup */ -#if 0 -#ifdef HAVE_ATEXIT - atexit (rxvt_clean_exit); -#else -#endif -#endif - - struct sigaction sa; - - sigfillset (&sa.sa_mask); - sa.sa_flags = SA_NOCLDSTOP | SA_RESTART; - sa.sa_handler = SIG_IGN; sigaction (SIGHUP , &sa, 0); - sa.sa_handler = SIG_IGN; sigaction (SIGPIPE, &sa, 0); - sa.sa_handler = rxvt_Exit_signal; sigaction (SIGINT , &sa, 0); - sa.sa_handler = rxvt_Exit_signal; sigaction (SIGQUIT, &sa, 0); - sa.sa_handler = rxvt_Exit_signal; sigaction (SIGTERM, &sa, 0); - sa.sa_handler = rxvt_Child_signal; sigaction (SIGCHLD, &sa, 0); - - /* need to trap SIGURG for SVR4 (Unixware) rlogin */ - /* signal (SIGURG, SIG_DFL); */ - - old_xerror_handler = XSetErrorHandler ((XErrorHandler) rxvt_xerror_handler); - //XSetIOErrorHandler ((XErrorHandler) rxvt_xioerror_handler); -} - bool rxvt_term::init (int argc, const char *const *argv) { + SET_R (this); + + if (!init_vars ()) + return false; + /* * Save and then give up any super-user privileges * If we need privileges in any area then we must specifically request it. @@ -251,7 +329,7 @@ set_locale (""); -#if (MENUBAR_MAX) +#if MENUBAR_MAX menubar_read (rs[Rs_menu]); #endif #ifdef HAVE_SCROLLBARS @@ -274,7 +352,7 @@ resize_scrollbar (); /* create and map scrollbar */ #endif #if (MENUBAR_MAX) - if (menubar_visible (r)) + if (menubar_visible ()) XMapWindow (display->display, menuBar.win); #endif #ifdef TRANSPARENT @@ -299,26 +377,65 @@ return true; } +static int (*old_xerror_handler) (Display *dpy, XErrorEvent *event); + +void +rxvt_init_signals () +{ + /* install exit handler for cleanup */ +#if 0 +#ifdef HAVE_ATEXIT + atexit (rxvt_clean_exit); +#else +#endif +#endif + + struct sigaction sa; + + sigfillset (&sa.sa_mask); + sa.sa_flags = SA_NOCLDSTOP | SA_RESTART; + sa.sa_handler = SIG_IGN; sigaction (SIGHUP , &sa, 0); + sa.sa_handler = SIG_IGN; sigaction (SIGPIPE, &sa, 0); + sa.sa_handler = rxvt_Exit_signal; sigaction (SIGINT , &sa, 0); + sa.sa_handler = rxvt_Exit_signal; sigaction (SIGQUIT, &sa, 0); + sa.sa_handler = rxvt_Exit_signal; sigaction (SIGTERM, &sa, 0); + sa.sa_handler = rxvt_Child_signal; sigaction (SIGCHLD, &sa, 0); + + /* need to trap SIGURG for SVR4 (Unixware) rlogin */ + /* signal (SIGURG, SIG_DFL); */ + + old_xerror_handler = XSetErrorHandler ((XErrorHandler) rxvt_xerror_handler); + //XSetIOErrorHandler ((XErrorHandler) rxvt_xioerror_handler); +} + /* ------------------------------------------------------------------------- * * SIGNAL HANDLING & EXIT HANDLER * * ------------------------------------------------------------------------- */ /* * Catch a SIGCHLD signal and exit if the direct child has died */ + +void rxvt_term::child_exited (int pid) +{ + for (rxvt_term **t = termlist.begin (); t < termlist.end (); t++) + if (pid == (*t)->cmd_pid) + { + (*t)->destroy (); + break; + } +} + /* ARGSUSED */ /* EXTPROTO */ RETSIGTYPE rxvt_Child_signal (int sig __attribute__ ((unused))) { int pid, save_errno = errno; - while ((pid = waitpid (-1, NULL, WNOHANG)) == -1 && errno == EINTR) - ; - errno = save_errno; -#if 0 - if (pid == cmd_pid) - exit (EXIT_SUCCESS); -#endif + while ((pid = waitpid (-1, NULL, WNOHANG)) > 0) + rxvt_term::child_exited (pid); + + errno = save_errno; } /* @@ -330,7 +447,7 @@ { signal (sig, SIG_DFL); #ifdef DEBUG_CMD - rxvt_print_error ("signal %d", sig); + rxvt_warn ("caught signal %d, exiting.\n", sig); #endif rxvt_clean_exit (); kill (getpid (), sig); @@ -378,7 +495,7 @@ if (p) return p; - fprintf (stderr, APL_NAME ": memory allocation failure. Aborting"); + fprintf (stderr, RESNAME ": memory allocation failure. Aborting"); rxvt_clean_exit (); exit (EXIT_FAILURE); /* NOTREACHED */ @@ -394,7 +511,7 @@ if (p) return p; - fprintf (stderr, APL_NAME ": memory allocation failure. Aborting"); + fprintf (stderr, RESNAME ": memory allocation failure. Aborting"); rxvt_clean_exit (); exit (EXIT_FAILURE); /* NOTREACHED */ @@ -413,7 +530,7 @@ if (p) return p; - fprintf (stderr, APL_NAME ": memory allocation failure. Aborting"); + fprintf (stderr, RESNAME ": memory allocation failure. Aborting"); rxvt_clean_exit (); exit (EXIT_FAILURE); /* NOTREACHED */ @@ -615,6 +732,7 @@ } } } + /* TODO: BOUNDS */ TermWin.width = TermWin.ncol * TermWin.fwidth; TermWin.height = TermWin.nrow * TermWin.fheight; @@ -717,13 +835,48 @@ * fontname == FONT_UP - switch to bigger font * fontname == FONT_DN - switch to smaller font */ -void -rxvt_term::change_font (int init, const char *fontname) -{} +bool +rxvt_term::change_font (const char *fontname) +{ + if (fontname == FONT_UP) + { + // TODO + } + else if (fontname == FONT_DN) + { + // TODO + } + else + { + rxvt_fontset *fs = new rxvt_fontset (this); -void + if (fs && fs->populate (fontname ? fontname : "fixed")) + { + delete TermWin.fontset; + TermWin.fontset = fs; + TermWin.fwidth = fs->base_font ()->width; + TermWin.fheight = fs->base_font ()->height; + TermWin.fbase = fs->base_font ()->ascent; + + if (TermWin.parent[0]) + { + resize_all_windows (0, 0, 0); + scr_remap_chars (); + scr_touch (true); + } + + return true; + } + } + + return false; +} + +bool rxvt_term::font_up_down (int n, int direction) -{} +{ + return false; +} /*----------------------------------------------------------------------*/ /*----------------------------------------------------------------------*/ @@ -731,32 +884,36 @@ void rxvt_term::set_title (const char *str) { -#ifndef SMART_WINDOW_TITLE - XStoreName (display->display, TermWin.parent[0], str); -#else - char *name; +#ifdef SMART_WINDOW_TITLE + char *name; - if (XFetchName (display->display, TermWin.parent[0], &name) == 0) + if (!XFetchName (display->display, TermWin.parent[0], &name)) name = NULL; + if (name == NULL || STRCMP (name, str)) +#endif XStoreName (display->display, TermWin.parent[0], str); + +#ifdef SMART_WINDOW_TITLE if (name) XFree (name); #endif } void -rxvt_term::set_iconName (const char *str) +rxvt_term::set_icon_name (const char *str) { -#ifndef SMART_WINDOW_TITLE - XSetIconName (display->display, TermWin.parent[0], str); -#else - char *name; +#ifdef SMART_WINDOW_TITLE + char *name; - if (XGetIconName (display->display, TermWin.parent[0], &name)) + if (!XGetIconName (display->display, TermWin.parent[0], &name)) name = NULL; + if (name == NULL || STRCMP (name, str)) +#endif XSetIconName (display->display, TermWin.parent[0], str); + +#ifdef SMART_WINDOW_TITLE if (name) XFree (name); #endif @@ -766,8 +923,8 @@ void rxvt_term::set_window_color (int idx, const char *color) { - rxvt_color xcol; - int i; + rxvt_color xcol; + int i; if (color == NULL || *color == '\0') return; @@ -793,8 +950,10 @@ goto Done; } } + if (!rXParseAllocColor (& xcol, color)) return; + /* XStoreColor (display->display, XCMAP, XColor*); */ /* @@ -827,8 +986,7 @@ set_colorfgbg (); recolour_cursor (); - /* the only reasonable way to enforce a clean update */ - scr_poweron (); + scr_touch (true); } #else @@ -838,14 +996,12 @@ void rxvt_term::recolour_cursor () { -#if TODO - rxvt_color xcol[2]; + XColor xcol[2]; - xcol[0] = PixColors[Color_pointer]; - xcol[1] = PixColors[Color_bg]; + xcol[0].pixel = ISSET_PIXCOLOR (Color_pointer_fg) ? PixColors[Color_pointer_fg] : PixColors[Color_fg]; + xcol[1].pixel = ISSET_PIXCOLOR (Color_pointer_bg) ? PixColors[Color_pointer_bg] : PixColors[Color_bg]; XQueryColors (display->display, XCMAP, xcol, 2); - XRecolorCursor (display->display, TermWin_cursor, & (xcol[0]), & (xcol[1])); -#endif + XRecolorCursor (display->display, TermWin_cursor, xcol + 0, xcol + 1); } /*----------------------------------------------------------------------*/ @@ -904,7 +1060,7 @@ { if (!screen_in_out->set (display, colour)) { - rxvt_print_error ("can't allocate colour: %s", colour); + rxvt_warn ("can't get colour '%s', continuing without.\n", colour); return false; } @@ -994,7 +1150,7 @@ XMoveResizeWindow (display->display, TermWin.vt, window_vt_x, window_vt_y, TermWin_TotalWidth (), TermWin_TotalHeight ()); - scr_clear (); + scr_clear (height != old_height); #ifdef XPM_BACKGROUND resize_pixmap (); #endif @@ -1281,7 +1437,7 @@ if (Input_Context == NULL) { - rxvt_print_error ("failed to create input context"); + rxvt_warn ("failed to create input context, continuing without XIM.\n"); display->put_xim (input_method); return false; }