📄 main.c
字号:
/*--------------------------------*-C-*---------------------------------* * File: main.c *----------------------------------------------------------------------* * * All portions of code are copyright by their respective author/s. * Copyright (c) 1992 John Bovey <jdb@ukc.ac.uk> * Copyright (c) 1994 Robert Nation <nation@rocket.sanders.lockheed.com> * Copyright (c) 1995 Garrett D'Amore <garrett@netcom.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> * Copyright (c) 2000 Xianping Ge <xge@ics.uci.edu> * Copyright (c) 2003-2004 Marc Lehmann <pcg@goof.com> * Copyright (c) 2005 Burgers A.R. <burgers@ecn.nl> * Copyright (c) 2004-2006 Jingmin Zhou <jimmyzhou@users.sourceforge.net> * Copyright (c) 2005-2006 Gautam Iyer <gi1242@users.sourceforge.net> * * 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 2 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. *----------------------------------------------------------------------*/#include "../config.h"#include "rxvt.h"#ifdef XFT_SUPPORT# include "xftacs.h"#endif/*--------------------------------------------------------------------* * BEGIN `INTERNAL' ROUTINE PROTOTYPES * *--------------------------------------------------------------------*/void rxvt_alarm_signal ( __attribute__((unused)) int sig );void rxvt_pre_show_init (rxvt_t* r);void rxvt_clean_commands (rxvt_t* r, int command_number);void rxvt_free_hidden (rxvt_t*);void rxvt_font_up_down (rxvt_t*, int, int);int rxvt_get_font_widest (XFontStruct*);void rxvt_set_colorfgbg (rxvt_t*);void rxvt_resize_sub_windows (rxvt_t*);#ifdef USE_XIMvoid rxvt_IM_set_size (rxvt_t*, XRectangle*);void rxvt_IM_set_position (rxvt_t*, XPoint*);void rxvt_IM_set_color (rxvt_t*, unsigned long*, unsigned long*);Bool rxvt_IM_is_running (rxvt_t*);void rxvt_IM_change_fontset (rxvt_t*, int);void rxvt_IM_set_preedit_area (rxvt_t*, XRectangle*, XRectangle*, XRectangle*);void rxvt_IM_destroy_callback (XIM, XPointer, XPointer);Bool rxvt_IM_get_IC (rxvt_t*);void rxvt_IM_send_size (rxvt_t*);void rxvt_IM_set_status_pos (rxvt_t*);#endifvoid rxvt_set_r (rxvt_t*);#ifdef XFT_SUPPORTvoid xftFreeUnusedFont (rxvt_t*, XftFont*);void setXftWeight (XftPattern *, const char *, int);void rxvt_init_font_fixed (rxvt_t*);# ifndef NO_BOLDFONTvoid rxvt_init_bfont_xft (rxvt_t*, XftPattern*);# endif# ifdef MULTICHAR_SETint rxvt_init_mfont_xft (rxvt_t*, XftPattern*, const char*);int isDoubleWidthFont (Display *dpy, XftFont *font);# endif#endif /* XFT_SUPPORT *//*--------------------------------------------------------------------* * END `INTERNAL' ROUTINE PROTOTYPES * *--------------------------------------------------------------------*//*----------------------------------------------------------------------*/const char** cmd_argv;/*----------------------------------------------------------------------*//* * Initialization done after reading command line options, and before calling * rxvt_create_show_windows(). *//* INTPROTO */voidrxvt_pre_show_init( rxvt_t *r ){ /* * 2006-08-18 gi1242 TODO: If we're using Xft, then we don't need to * initialize this array. */ r->pixColorsFocus = rxvt_malloc( sizeof(unsigned long) * (TOTAL_COLORS)); r->pixColors = r->pixColorsFocus;#ifdef XFT_SUPPORT if( ISSET_OPTION( r, Opt_xft ) ) { r->xftColorsFocus = rxvt_malloc( sizeof(XftColor) * (TOTAL_COLORS) ); r->xftColors = r->xftColorsFocus; } else { SET_NULL( r->xftColors ); SET_NULL( r->xftColorsFocus ); }#endif if( r->TermWin.fade ) { rxvt_dbgmsg ((DBG_DEBUG, DBG_MAIN, "Allocating space for fade colors\n")); r->pixColorsUnfocus = rxvt_malloc( sizeof(unsigned long) * (TOTAL_COLORS) );# ifdef XFT_SUPPORT if( ISSET_OPTION( r, Opt_xft ) ) r->xftColorsUnfocus = rxvt_malloc( sizeof(XftColor) * TOTAL_COLORS ); else SET_NULL( r->xftColorsUnfocus );# endif /* XFT_SUPPORT */ } else { SET_NULL( r->pixColorsUnfocus );# ifdef XFT_SUPPORT SET_NULL( r->xftColorsUnfocus );# endif }}/* rxvt_init() *//* LIBPROTO */rxvt_t *rxvt_init(int argc, const char *const *argv){ register int i; register int itnum; /* initial terminal number */ rxvt_t* r; /* Allocate memory for "r" and initialize contents to 0 */ r = (rxvt_t *) rxvt_calloc(1, sizeof(rxvt_t)); /* Save "r" in _rxvt_vars. This is the only assignment to _rxvt_vars */ rxvt_set_r(r); /* Initialize vars in "r" */ if (rxvt_init_vars(r) < 0) { rxvt_msg (DBG_ERROR, DBG_MAIN, "Could not initialize." ); rxvt_free(r); return NULL; } /* save global argc and argv */ r->global_argc = argc; r->global_argv = (char**) argv; rxvt_init_secondary(r); cmd_argv = rxvt_init_resources(r, argc, argv); rxvt_pre_show_init( r ); rxvt_create_show_windows(r, argc, argv);#ifdef TRANSPARENT if (ISSET_OPTION(r, Opt_transparent)) { XSelectInput(r->Xdisplay, XROOT, PropertyChangeMask); /* * Our "parents" will automatically be checked on the first expose and * ConfigureNotify event respectively. Forcefully calling it is just a * waste of time. */# if 0 rxvt_check_our_parents(r);# endif }#endif rxvt_init_env(r); rxvt_init_command(r); rxvt_init_screen (r); /* * Initialize the pages */ if( r->h->rs[Rs_initProfiles] ) { /* Split into a comma separated string */ char *s = (char *) r->h->rs[Rs_initProfiles]; do { int profile = atoi( s ); rxvt_append_page( r, profile, NULL, NULL ); s = STRCHR( s, ',' ); } while (NULL != s++); } /* Backward compatibility: Open profiles 0 .. n-1 if tnum=n. */ else if( r->h->rs[Rs_init_term_num] ) { rxvt_msg (DBG_ERROR, DBG_MAIN, "Option tnum is obsolete." " Use --initProfileList instead" ); itnum = atoi( r->h->rs[Rs_init_term_num] ); itnum = max( 1, itnum ); itnum = min( itnum, MAX_PAGES ); for (i = 0; i < itnum; i ++) rxvt_append_page( r, (i < MAX_PROFILES) ? i : 0 , NULL, NULL ); } /* Just open the default tab */ else rxvt_append_page( r, 0, NULL, NULL ); /* Activate the tab */ rxvt_activate_page (r, 0); /* Initialize xlocale after VT is created */ rxvt_init_xlocale(r); return r;}/* ------------------------------------------------------------------------- * * SIGNAL HANDLING & EXIT HANDLER * * ------------------------------------------------------------------------- *//* * Catch a SIGCHLD signal and exit if the direct child has died *//* ARGSUSED *//* EXTPROTO */RETSIGTYPErxvt_Child_signal(int sig __attribute__((unused))){ /* * Sometimes the child process could exit before we have a chance to * initialize the term structure. So we just count the number of calls to * this function here. We will wait for our dead children later. */ rxvt_t *r; rxvt_dbgmsg ((DBG_VERBOSE, DBG_MAIN, "\e[31mrxvt_Child_signal()\e[0m\n")); r = rxvt_get_r(); r->ndead_childs++; rxvt_dbgmsg ((DBG_VERBOSE, DBG_MAIN, "done rxvt_Child_signal()\n"));}/* * Catch a fatal signal and tidy up before quitting *//* EXTPROTO */RETSIGTYPErxvt_Exit_signal(int sig){#ifdef UTMP_SUPPORT register int i;#endif rxvt_t* r; rxvt_msg (DBG_INFO, DBG_MAIN, "Received signal %d\n", (int) sig); r = rxvt_get_r();#ifdef UTMP_SUPPORT for (i = 0; i <= LTAB(r); i ++) { rxvt_privileges( RESTORE ); rxvt_cleanutent( r, i ); rxvt_privileges( IGNORE ); }#endif /* resend signal to default handler */ /* kill (getpid (), sig); */ rxvt_close_all_tabs( r );}voidrxvt_alarm_signal( __attribute__((unused)) int sig ){ int i; rxvt_t *r = rxvt_get_r(); if( LTAB(r) >= 0 ) { rxvt_msg (DBG_WARN, DBG_MAIN, APL_NAME ": WARNING Processes "); for( i=0; i <= LTAB(r); i ++ ) rxvt_msg (DBG_WARN, DBG_MAIN, "%d%c", PVTS(r, i)->cmd_pid, i == LTAB(r) ? ' ' : ',' ); rxvt_msg (DBG_WARN, DBG_MAIN, " have not responded to SIGHUP, and are still " "running. Either 'kill -9' these processes or close the " APL_NAME " window again within 3 seconds.\n"); }}/* INTPROTO */voidrxvt_free_hidden( rxvt_t* r ){#ifdef DEBUG if (IS_CURSOR(r->h->bar_pointer)) { XFreeCursor( r->Xdisplay, r->h->bar_pointer ); UNSET_CURSOR(r->h->bar_pointer); }# ifdef POINTER_BLANK if (IS_CURSOR(r->h->blank_pointer)) { XFreeCursor( r->Xdisplay, r->h->blank_pointer ); UNSET_CURSOR(r->h->blank_pointer); }# endif#endif /* DEBUG */#ifdef USE_XIM if( r->h->Input_Context ) { XDestroyIC( r->h->Input_Context ); SET_NULL(r->h->Input_Context); }#endif}/* * If we're protecting the secondary screen, or have multiple tabs with a hidden * tabbar, then avoid exiting. *//* EXTPROTO */voidrxvt_exit_request( rxvt_t *r ){ /* Avoid exiting if there are multiple tabs with hidden tabbar */ if( LTAB(r) > 0 && !rxvt_tabbar_visible( r ) ) { XBell( r->Xdisplay, 0 ); if( rxvt_tabbar_show(r) ) rxvt_resize_on_subwin (r, SHOW_TABBAR); return; } /* Avoid exiting if some tab is in the secondary screen */ if(ISSET_OPTION(r, Opt2_protectSecondary)) { int i, dontExit = 0; for( i=0; i <= LTAB(r); i++) { if( PVTS(r, i)->current_screen == SECONDARY ) { dontExit = 1; if( i != ATAB(r) ) rxvt_tabbar_highlight_tab( r, i, False); } } if( dontExit ) { XBell( r->Xdisplay, 0); return; } } rxvt_close_all_tabs(r);}/* * Remove all held tabs, and send SIGHUP to processes in all live tabs * * 2006-09-22 gi1242: In mrxvt-0.5.1 and before, we would exit mrxvt by calling * rxvt_clean_exit(). This would send SIGHUP to all child processes, and then * call exit(). This however is flawed! If some processes do not exit on SIGHUP, * then they will remain in the background and the user will not know. * * To fix this issue, we call rxvt_close_all_tabs() instead of rxvt_clean_exit() * when we want to exit mrxvt. rxvt_close_all_tabs() will send SIGHUP's to all * child processes, and remove all held tabs. If mrxvt does not exit within two * seconds, then it will sound an alarm warning the user of the offending * processes which ignored SIGHUP. The user can either kill -9 those processes * manually, or request another exit of mrxvt within the next 3 seconds to have * mrxvt forcefully exit (but leaving the child processes running). *//* EXTPROTO */voidrxvt_close_all_tabs( rxvt_t *r){ static struct timeval lastRequest = {0, 0}; struct timeval now; int i; for( i=LTAB(r); i >=0; i-- ) { if( PVTS(r, i)->dead ) rxvt_remove_page( r, i ); else { PVTS(r, i)->holdOption = 0; kill( PVTS(r, i)->cmd_pid, SIGHUP ); } } gettimeofday( &now, NULL ); if( lastRequest.tv_sec != 0 && now.tv_sec - lastRequest.tv_sec < 5 ) /* Second request within 5 seconds. Kill mrxvt */ rxvt_clean_exit(r); else { lastRequest = now; /* Just in case the processes don't exit on SIGHUP, warn the user */ signal( SIGALRM, rxvt_alarm_signal ); alarm( 2 ); }}/* EXTPROTO */voidrxvt_clean_exit (rxvt_t* r){#ifdef HAVE_X11_SM_SMLIB_H if (ISSET_OPTION(r, Opt2_enableSessionMgt)) rxvt_session_exit (r);#endif#if 0 /* * Now kill all child processes, zsh puts them into background if we do not * do so. * * 2006-09-22 gi1242: No! See comments before rxvt_close_all_tabs(). */ for (i = 0; i <= LTAB(r); i ++) kill (PVTS(r, i)->cmd_pid, SIGHUP);#endif /* * 2006-01-27 gi1242: Free all used resources. This used to be done only in * debug mode, but I think it's good practice to do it always. It can't hurt * anything. *//* #ifdef DEBUG */ rxvt_free_hidden (r); /* Destroy windows before other X resources */ if (IS_WIN(r->TermWin.parent)) { XDestroySubwindows (r->Xdisplay, r->TermWin.parent); XDestroyWindow (r->Xdisplay, r->TermWin.parent); UNSET_WIN(r->TermWin.parent); }# ifdef HAVE_SCROLLBARS rxvt_scrollbar_clean_exit (r);# endif# ifdef HAVE_MENUBAR rxvt_menubar_clean_exit (r);# endif rxvt_tabbar_clean_exit (r); if (NOT_NULL(r->TermWin.font)) XFreeFont (r->Xdisplay, r->TermWin.font);# ifndef NO_BOLDFONT if (NOT_NULL(r->TermWin.bfont) && r->TermWin.font != r->TermWin.bfont) { XFreeFont (r->Xdisplay, r->TermWin.bfont); SET_NULL(r->TermWin.bfont); }# endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -