📄 macros.c
字号:
/*--------------------------------*-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 + -