📄 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#ifdef DEBUG_VERBOSE# define DEBUG_LEVEL 1# define DEBUG_X#else # define DEBUG_LEVEL 0#endif#if DEBUG_LEVEL# define DBG_MSG(d,x) if(d <= DEBUG_LEVEL) fprintf x#else# define DBG_MSG(d,x)#endif/*--------------------------------------------------------------------* * BEGIN `INTERNAL' ROUTINE PROTOTYPES * *--------------------------------------------------------------------*/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 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;/*----------------------------------------------------------------------*//* 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) { 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_create_show_windows(r, argc, argv);#ifdef TRANSPARENT if (r->Options & 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, cmd_argv); 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 < 0 || profile >= MAX_PAGES ? 0 : profile ), NULL, NULL ); s = STRCHR( s, ',' ); } while( s++ != NULL ); } /* Backward compatibility: Open profiles 0 .. n-1 if tnum=n. */ else if( r->h->rs[Rs_init_term_num] ) { rxvt_print_error( "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))){ int pid, page, save_errno = errno; rxvt_t* r; /* enable signal reentry, it's ok here */ signal(SIGCHLD, rxvt_Child_signal); DBG_MSG( 1, ( stderr, "rxvt_Child_signal()\n")); r = rxvt_get_r(); /* * 2006-02-17 gi1242: If a child process exits BEFORE we had a chance to * initialize it's PID, then we should not wait for the child here. This * will be done in rxvt_getc. */ for( page=0; page <= LTAB(r); page++) if( PVTS( r, page)->cmd_pid <=0 ) { DBG_MSG( 1, ( stderr, "Tab %d not initialized. Dropping signal\n", page)); return; } ;#if 0 /* * 2006-02-17 gi1242: If we do a while loop, then more than one child could * die when we call wait. This might be the cause of the error we sometimes * get when more than one child dies at the same time ... */ do { errno = 0; } while ( (pid = waitpid(-1, NULL, WNOHANG)) == -1 && errno == EINTR );#endif pid = waitpid( -1, NULL, WNOHANG ); if (pid > 0) { int i; for (i = 0; i <= LTAB(r); i ++) { DBG_MSG( 3, ( stderr, "Tab %d child pid: %d\n", i+1, PVTS( r, i)->cmd_pid)); if (pid == PVTS(r, i)->cmd_pid) break; } if (i <= LTAB(r)) { DBG_MSG(1,(stderr, "Dead child %d is tab %d\n", (int) pid, i)); /* one more vt died */ r->vt_died ++; /* update child members */ PVTS(r, i)->dead = 1; if (r->Options2 & Opt2_holdExit) PVTS(r, i)->hold = 1; } else { /* * PID of child process was not on any tab. We should never get * here. * * 2006-04-28 gi1242: Maybe we can get here if a printPipe dies? */#if 0 assert(0);#endif } } else { /* * Restore errno for other functions. */ DBG_MSG( 1, ( stderr, "No children died.\n")); errno = save_errno; }}/* * 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; DBG_MSG( 1, ( stderr, "Received signal %d\n", (int) sig)); signal( sig, SIG_DFL ); 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_clean_exit( r );}/* INTPROTO */voidrxvt_free_hidden( rxvt_t* r ){#ifdef DEBUG if (None != r->h->bar_pointer) { XFreeCursor( r->Xdisplay, r->h->bar_pointer ); r->h->bar_pointer = None; }# ifdef POINTER_BLANK if( None != r->h->blank_pointer ) { XFreeCursor( r->Xdisplay, r->h->blank_pointer ); r->h->blank_pointer = None; }# endif#endif /* DEBUG */#ifdef USE_XIM if( r->h->Input_Context ) { XDestroyIC( r->h->Input_Context ); r->h->Input_Context = NULL; }#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( r->Options2 & 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_clean_exit(r);}/* EXTPROTO */voidrxvt_clean_exit (rxvt_t* r){ register int i; /* restore default SIGCHLD signal handler */ signal (SIGCHLD, SIG_DFL); rxvt_free_hidden (r);#ifdef HAVE_X11_SM_SMLIB_H if (r->Options2 & Opt2_enableSessionMgt) rxvt_session_exit (r);#endif /* now kill all child processes, zsh puts them into background ** if we do not do so */ for (i = 0; i <= LTAB(r); i ++) kill (PVTS(r, i)->cmd_pid, SIGHUP); /* * 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 */ /* Destroy windows before other X resources */ if (None != r->TermWin.parent) { XDestroySubwindows (r->Xdisplay, r->TermWin.parent); XDestroyWindow (r->Xdisplay, r->TermWin.parent); r->TermWin.parent = None; }# ifdef HAVE_SCROLLBARS rxvt_scrollbar_clean_exit (r);# endif# ifdef HAVE_MENUBAR rxvt_menubar_clean_exit (r);# endif rxvt_tabbar_clean_exit (r); if (NULL != r->TermWin.font) XFreeFont (r->Xdisplay, r->TermWin.font);# ifndef NO_BOLDFONT if (NULL != r->TermWin.bfont && r->TermWin.font != r->TermWin.bfont) { XFreeFont (r->Xdisplay, r->TermWin.bfont); r->TermWin.bfont = NULL; }# endif# ifdef MULTICHAR_SET if (NULL != r->TermWin.mfont && r->TermWin.font != r->TermWin.mfont) { XFreeFont (r->Xdisplay, r->TermWin.mfont); r->TermWin.mfont = NULL; }# endif r->TermWin.font = NULL; /* clear font */# ifdef XFT_SUPPORT if (NULL != r->TermWin.xftfont) { XftFont *fn; XftFontClose (r->Xdisplay, r->TermWin.xftfont); xftCloseACS (r->Xdisplay); if( (fn = r->TermWin.xftpfont) ) { r->TermWin.xftpfont = NULL; xftFreeUnusedFont( r, fn); } if( (fn = r->TermWin.xftPfont) ) { r->TermWin.xftPfont = NULL; xftFreeUnusedFont( r, fn); }# ifndef NO_BOLDFONT fn = r->TermWin.xftbfont; r->TermWin.xftbfont = NULL; xftFreeUnusedFont( r, fn);# endif# ifdef MULTICHAR_SET fn = r->TermWin.xftmfont; r->TermWin.xftmfont = NULL; xftFreeUnusedFont( r, fn);# endif } r->TermWin.xftfont = NULL; /* clear font */ /* * XXX gi1242 2006-01-27: Xft bug. Patterns passed to XftFontOpenPattern * can't always be safely freed. */# if 0 if( r->TermWin.xftpattern ) XftPatternDestroy( r->TermWin.xftpattern);# ifndef NO_BOLDFONT if( r->TermWin.xftbpattern ) XftPatternDestroy( r->TermWin.xftbpattern );# endif# ifdef MULTICHAR_SET if( r->TermWin.xftmpattern ) XftPatternDestroy( r->TermWin.xftmpattern );# endif# endif# endif if (None != r->term_pointer) { XFreeCursor (r->Xdisplay, r->term_pointer); r->term_pointer = None; } if (None != r->TermWin.gc) { XFreeGC (r->Xdisplay, r->TermWin.gc); r->TermWin.gc = None; } XCloseDisplay (r->Xdisplay); r->Xdisplay = NULL; free (r->tabstop); r->tabstop = NULL; free (r->PixColors); r->PixColors = NULL;# ifdef OFF_FOCUS_FADING free (r->PixColorsUnfocus); r->PixColorsUnfocus = NULL;# endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -