⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 macros.c

📁 multi-tabed terminal based on rxvt
💻 C
📖 第 1 页 / 共 3 页
字号:
/*--------------------------------*-C-*----------------------------------------* * File:    macros.c (used to be hotkeys.c) *-----------------------------------------------------------------------------* * * All portions of code are copyright by their respective author/s. * *  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"/* * Must sync these to macroFnNames in rxvtlib.h. */static const char *const macroNames[] ={    "Dummy",		    /* Delete macro */    "Esc",		    /* Escape sequence to send to mrxvt */    "Str",		    /* String to send to child process */    "NewTab",		    /* Open a new tab, and exec a program in it. */    "Exec",		    /* Exec a program asynchronusly */    "Close",		    /* Close tab(s) */    "GotoTab",		    /* Switch to tab */    "MoveTab",		    /* Move tab */    "Scroll",		    /* Scroll up/down */    "Copy",		    /* Copy selection */    "Paste",		    /* Paste selection */    "PasteFile",	    /* Paste the content of a file */    "MonitorTab",	    /* Monitor tab for activity/inactivity */    "ToggleSubwin",	    /* Toggle subwindows (scroll / menu / tabbar) */    "ResizeFont",	    /* Resize terminal font */    "ToggleVeryBold",	    /* Toggle use of bold font for colored text */    "ToggleBoldColors",	    /* Toggle option boldColors */    "ToggleVeryBright",	    /* Toggle option veryBright */    "ToggleTransparency",   /* Toggle pseudo transparency */    "ToggleBroadcast",	    /* Toggle broadcasting of input */    "ToggleHold",	    /* Toggle holding of completed tabs */    "ToggleFullscreen",	    /* Toggle full screen mode */    "Raise",		    /* Raise the terminal window */    "SetTitle",		    /* Set title of active tab to selection */    "UseFifo",		    /* Enable / disable using fifo */    "PrintScreen",	    /* Dump screen to file / printer */    "SaveConfig",	    /* Save config to file */    "ToggleMacros"	    /* Toggle using keyboard macros */};/******************************************************************************\* 		       BEGIN INTERNAL ROUTINE PROTOTYPES		       *\******************************************************************************/int		macro_cmp	    ( const void*, const void*);int		rxvt_add_macro	    ( rxvt_t*, KeySym, unsigned char, char*, Bool, macro_priority_t);unsigned char	macro_set_number    ( unsigned char, unsigned char);/******************************************************************************\*			END INTERNAL ROUTINE PROTOTYPES			       *\******************************************************************************//* * 2006-02-23 gi1242: New macro code. This should extend the hotkey aproach * without causing code bloat. The idea is that defining "macros" can also * enable the user to communicate with mrxvt using escape sequences! *//* * str = [+-][s|t|m|b] * *	'+' means show. '-' means hide. Neither means toggle. * *	s, t, m, b are the scroll tab and menubars respectively. 'b' is tabbar *	buttons. * * 2006-02-23 gi1242 TODO: Permit hiding / showing more than one sub window at * one time. Currently calls to resize_on_subwin must be followed by * ConfigureNotify event (which we process) to correct the sizeHint (otherwise * we end up having the wrong size). *//* EXTPROTO */voidrxvt_toggle_subwin( rxvt_t *r, const unsigned char *str){    if (IS_NULL(str) || (char) 0 == *str ||	    STRCHR( str, 't') || STRCHR( str, 'T' ) )    {	/*	 * Backward compatibility -- If str is NULL or empty, then toggle the	 * tabbar visibility.	 */	if (rxvt_tabbar_visible (r) &&	    (IS_NULL(str) || '+' != *str))	{	    /*	     * If the tabbar is visible, and we are not forced to show it then	     * hide it.	     */	    if( rxvt_tabbar_hide(r) ) rxvt_resize_on_subwin (r, HIDE_TABBAR);	}	else if (!rxvt_tabbar_visible (r) &&	    (IS_NULL(str) || '-' != *str))	{	    /*	     * If the tabbar is hidden, and we are not forced to hide it, then	     * show the tabbar.	     */	    if( rxvt_tabbar_show(r)) rxvt_resize_on_subwin (r, SHOW_TABBAR);	}	return;    }    /*     * The remainder of this function assumes a non-empty string.     */    if( STRCHR( str, 'b') || STRCHR( str, 'B') )    {	/* Toggle tabbar buttons */	switch( *str )	{	    case '+':		/* Show buttons */		UNSET_OPTION(r, Opt2_hideButtons);		break;	    case '-':		/* Hide buttons */		SET_OPTION(r, Opt2_hideButtons);		break;	    default:		/* Toggle buttons */		TOGGLE_OPTION(r, Opt2_hideButtons);	}	/* Refresh tabbar */	rxvt_tabbar_set_visible_tabs (r, False);	if (IS_WIN(r->tabBar.win))	    XClearArea( r->Xdisplay, r->tabBar.win, 0, 0, 0, 0, True);	return;    }#ifdef HAVE_SCROLLBARS    if( STRCHR( str, 's') || STRCHR( str, 'S' ) )    {	if( rxvt_scrollbar_visible (r) && *str != '+' )	{	    if( rxvt_scrollbar_hide(r) )		rxvt_resize_on_subwin (r, HIDE_SCROLLBAR);	}	else if( !rxvt_scrollbar_visible( r ) && *str != '-' )	{	    if( rxvt_scrollbar_show(r) )		rxvt_resize_on_subwin (r, SHOW_SCROLLBAR);	}	return;    }#endif#ifdef HAVE_MENUBAR    if( STRCHR( str, 'm') || STRCHR( str, 'M' ) )    {	if( rxvt_menubar_visible (r) && *str != '+' )	{	    if( rxvt_menubar_hide(r) )		rxvt_resize_on_subwin (r, HIDE_MENUBAR);	}	else if( !rxvt_menubar_visible( r ) && *str != '-' )	{	    if( rxvt_menubar_show(r) )		rxvt_resize_on_subwin (r, SHOW_MENUBAR);	}	return;    }#endif}/* }}} *//* * Functions to parse macros (add them to our list), and exec actions. *//* {{{1 macro_cmp() * * Used by bsearch and qsort for macro comparison. */intmacro_cmp( const void *p1, const void *p2){    const macros_t  *macro1 = p1,	     	    *macro2 = p2;    /* First compare keysyms, then modflags. Ignore the "Primary" modifier */    if( macro1->keysym == macro2->keysym )    {	if(	     (macro1->modFlags & ~MACRO_PRIMARY & MACRO_MODMASK)		== (macro2->modFlags & ~MACRO_PRIMARY & MACRO_MODMASK)	  )	    return MACRO_GET_NUMBER( macro1->modFlags )			- MACRO_GET_NUMBER( macro2->modFlags );	else	    return (macro1->modFlags & ~MACRO_PRIMARY & MACRO_MODMASK)			- (macro2->modFlags & ~MACRO_PRIMARY & MACRO_MODMASK);    }    else	return macro1->keysym - macro2->keysym;}/* {{{1 macro_set_number( flag, num ) *//* INTPROTO */unsigned charmacro_set_number( unsigned char flag, unsigned char num ){    flag &= MACRO_MODMASK;    flag |= (num << MACRO_N_MOD_BITS);    return flag;}/* {{{1 rxvt_parse_macros(str, arg): Parse macro from arguments * * str and arg can be as follows: * * 	1. str = keyname,		    arg = argument. * 	2. str = macro.keyname: argument,   arg = NULL * * If a valid macro is found, it is added to our list (r->macros) of macros. * Returns 1 if the macro is added to r->macros, 0 if it is not a macro (i.e. * does not begin with "macro."), and -1 if invalid syntax / error adding / etc. *//* EXTPROTO */#define NEWARGLIM   500	/* `reasonable' size */intrxvt_parse_macros( rxvt_t *r, const char *str, const char *arg,	macro_priority_t priority){    char	    newarg[NEWARGLIM],		    keyname[ NEWARGLIM],		    *keyname_nomods;    unsigned char   modFlags = 0;    KeySym	    keysym;    Bool	    addmacro = False;    if (IS_NULL(arg))    {	char *keyend;	int	n;	/*	 * Need to split str into keyname and argument.	 */	if( (n = rxvt_str_match(str, "macro.")) == 0 )	    return 0;	str += n;	/* skip `macro.' */	if (IS_NULL(keyend = STRCHR( str, ':' )))	    return -1;	n = min( keyend - str, NEWARGLIM - 1 );	STRNCPY( keyname, str, n );	keyname[n] = 0;	STRNCPY( newarg, keyend + 1, NEWARGLIM - 1 );    }    else    {	/*	 * Keyname is already in str. Copy arg into newarg.	 */	STRNCPY( keyname, str, NEWARGLIM - 1 );	keyname[ NEWARGLIM - 1] = '\0';	STRNCPY( newarg, arg, NEWARGLIM - 1 );    }    /* Null terminate and strip leading / trailing spaces */    newarg[NEWARGLIM - 1] = '\0';    rxvt_str_trim( newarg );    rxvt_msg( DBG_INFO, DBG_MACROS,	    "Got macro '%s' -- '%s'\n", keyname, newarg );    /*     * Breakup keyname into a keysym and modifier flags.     */    if (IS_NULL(keyname_nomods = STRRCHR( keyname, '+' )))    {	/* No modifiers specified */#ifdef UNSHIFTED_MACROS	keyname_nomods = keyname;#else	return -1;#endif    }    else    {	*(keyname_nomods++) = 0;	/*	 * keyname is now a null terminated string containing only the	 * modifiers, and keyname_nomods is a null terminated string	 * containing only the key name.	 */	if( STRCASESTR( keyname, "ctrl" ) )	    modFlags |= MACRO_CTRL;	if( STRCASESTR( keyname, "meta" ) || STRCASESTR( keyname, "alt"))	    modFlags |= MACRO_META;	if( STRCASESTR( keyname, "shift") )	    modFlags |= MACRO_SHIFT;	if( STRCASESTR( keyname, "primary"))	    modFlags |= MACRO_PRIMARY;	if( STRCASESTR( keyname, "add" ) )	    addmacro = True;    }    /*     * Always store the keysym as upper case. That way we can treat shift     * correctly even when Caps Lock is pressed.     */    {        KeySym upper;        XConvertCase(XStringToKeysym(keyname_nomods), &keysym, &upper);    }    if (NOT_KEYSYM(keysym))    {	rxvt_msg (DBG_ERROR, DBG_MACROS,  "Invalid keysym %s. Skipping macro.",		keyname_nomods);	return -1;    }    return rxvt_add_macro( r, keysym, modFlags, newarg, addmacro, priority)		? 1 : -1;}/* {{{1 rxvt_add_macro( keysym, modFlags, astring, priority) * * Add a macro to our list of macros (r->macros) if astring describes a valid * macro. * * priority is the priority with which the macro should be added. A macro should * never overwrite a macro with lower priority (yes, I know that's backwards). A * macro should be added to a chain ONLY IF it's priority is the same as the * previous macro's priority. *//* INTPROTO */intrxvt_add_macro( rxvt_t *r, KeySym keysym, unsigned char modFlags, char *astring,	Bool addmacro, macro_priority_t priority){    const unsigned nmacros_increment = 64;  /* # extra macros to alloc space for					       when we need to enlarge our list					       of macros. A large number here is					       not wasteful as we clean it up					       after initialization */    unsigned short  i,		    replaceIndex = r->nmacros,		    dummyIndex = r->nmacros;    unsigned char   macroNum = 0;    action_t	    action;    rxvt_dbgmsg(( DBG_DEBUG, DBG_MACROS, "%s(%08lx, %2hhx, '%s', %d, %d)\n",		__func__, keysym, modFlags, astring, addmacro, priority ));    /*     * Check to see if macro already exists.     */    for( i=0; i < r->nmacros; i++ )    {	if(	    r->macros[i].keysym == keysym	    && (r->macros[i].modFlags & MACRO_MODMASK & ~MACRO_PRIMARY)		    == (modFlags & MACRO_MODMASK & ~MACRO_PRIMARY)	  )	{	    if( addmacro && r->macros[i].priority == priority )	    {		/*		 * Find the last macro in the macro chain (the macro with the		 * largest number).		 */		unsigned char num;		num	 = MACRO_GET_NUMBER( r->macros[i].modFlags );		if( num > macroNum )		    macroNum = num;		if( macroNum == MACRO_MAX_CHAINLEN )		{		    rxvt_msg (DBG_ERROR, DBG_MACROS,  "Macro chain too long" );		    return 0;		}		replaceIndex = i;	    }	    /*	     * Macro for key already exists. Only replace it if we have a	     * *lower* priority (which in theory should never happen).	     */	    else if( priority > r->macros[i].priority )		return 1; /* Claim to have succeded so that caller will not			     complain about "Failing to add a ... macro". */	    	    /*	     * 2006-03-06 gi1242: Don't delete "Dummy" macros here. If we do	     * that then the user will have no way to delete macros defined in	     * the system /etc/mrxvt/mrxvtrc file. "Dummy" macros will be	     * deleted after init.	     */	    else	    {		if( replaceIndex < r->nmacros )		{		    /*		     * replaceIndex points to a macro with keysym == the keysym		     * of the macro to be added. Set keysym to 0 so that it will		     * be cleaned up by rxvt_cleanup_macros().		     */		    r->macros[replaceIndex].keysym = 0;		}		replaceIndex = i;	    }	}	else if( r->macros[i].keysym == 0 )	    /*	     * Macros with keysym 0 are dummies, and can be safely replaced.	     */	    dummyIndex = i;    } /* for */    /*     * Now dummyIndex will point to a macro that can safely be replaced.     * replaceIndex (if less than r->nmacros) will be the index of a macro in     * r->macros which has the same keysym / modflags as the macro we wish to     * add. We will either replace this macro with the new one, or add to it if     * the "Add" flag was specified.     */    if( addmacro )    {	if( replaceIndex == r->nmacros )	{	    rxvt_msg( DBG_ERROR, DBG_MACROS,		    "No previous macro to add to (key %s%s%s%s)",		    (modFlags & MACRO_CTRL) ? "Ctrl+" : "",		    (modFlags & MACRO_META) ? "Meta+" : "",		    (modFlags & MACRO_SHIFT) ? "Shift+" : "",		    XKeysymToString( keysym ) );

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -