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

📄 macros.c

📁 multi-tabed terminal based on rxvt
💻 C
📖 第 1 页 / 共 3 页
字号:
	    return 0;	/* Failure */	}	else if( r->macros[replaceIndex].priority != priority )	{	    rxvt_msg( DBG_ERROR, DBG_MACROS,		    "Can not add to a macro defined at a different location "		    "(key %s%s%s%s)",		    (modFlags & MACRO_CTRL) ? "Ctrl+" : "",		    (modFlags & MACRO_META) ? "Meta+" : "",		    (modFlags & MACRO_SHIFT) ? "Shift+" : "",		    XKeysymToString( keysym ) );	    return 0;	/* Failure */	}	else if( r->macros[replaceIndex].action.type == MacroFnDummy )	{	    /* Do not add to a dummy macro */	    rxvt_msg (DBG_ERROR, DBG_MACROS,		    "Can not add actions to a Dummy macro"		    "(key %s%s%s%s)",		    (modFlags & MACRO_CTRL) ? "Ctrl+" : "",		    (modFlags & MACRO_META) ? "Meta+" : "",		    (modFlags & MACRO_SHIFT) ? "Shift+" : "",		    XKeysymToString( keysym ) );	    return 0;	/* Failure */	}	/*	 * We're going to add to this macro chain, so don't replace this macro.	 */	replaceIndex = dummyIndex;	/*	 * Make the number of this macro one higher than the last in the macro	 * chain.	 */	modFlags = macro_set_number( modFlags, macroNum+1 );    }    else    {	modFlags = macro_set_number( modFlags, 0 );	/* Set replaceIndex to the index of a macro we can replace */	if( dummyIndex < replaceIndex )	    replaceIndex = dummyIndex;    }    /*     * Add action to the list of macros (making it bigger if necessary).     */    if( replaceIndex == r->nmacros )    {	if( r->nmacros == r->maxMacros )	{	    /* Get space for more macros*/	    r->maxMacros += nmacros_increment;	    r->macros = (macros_t *) rxvt_realloc( r->macros,					r->maxMacros * sizeof(macros_t));	}	r->nmacros++;    }    else    {	/* Macro action string needs to be freed (as it will be replaced) */	if( r->macros[replaceIndex].action.str )	    rxvt_free( r->macros[replaceIndex].action.str );    }    /*     * Set the action string. This malloc's memory so any returns after this     * should either save action in to a global variable, or free it.     */    assert( astring );    SET_NULL(action.str);   /* Make sure rxvt_set_action won't free non-existent			       memory */    if( !rxvt_set_action( &action, astring) )	return 0; /* Failure: Probably unrecognized action type */    /*     * Save macro values in our global macro list.     */    r->macros[replaceIndex].keysym	= keysym;    r->macros[replaceIndex].modFlags	= modFlags;    r->macros[replaceIndex].action	= action;    r->macros[replaceIndex].priority	= priority;    rxvt_dbgmsg(( DBG_DEBUG, DBG_MACROS,		"Added macro %hu of %hu. Type %s, len %hu, args '%s'.\n",		replaceIndex, r->maxMacros, macroNames[ action.type ],		action.len,		(action.type == MacroFnStr || action.type == MacroFnEsc) ?		    "(escaped string)" :		    (IS_NULL(action.str) ?			"(nil)" : (char*) action.str)));    return 1;	/* Success */}/* {{{1 rxvt_cleanup_macros() * * Delete all "Dummy" macros from our list of macros, and free space alloced for * extra macros */voidrxvt_cleanup_macros( rxvt_t *r ){    unsigned i, nDummyMacros = 0;    if( r->nmacros == 0 ) return; /* Nothing to be done */    for( i = 0; i < r->nmacros; i++)    {	if(	     r->macros[i].action.type == MacroFnDummy ||	     NOT_KEYSYM(r->macros[i].keysym)	  )	{	    /*	     * Dummy macro needs to be deleted. Make sure this macro comes first	     * in the macro list.	     *	     * 2006-03-06 gi1242: Would be more efficient if we made sure that	     * this macro was last in the list, however that would involve	     * knowing what the max keysym value is. Could be different on	     * different architectures.	     */	    r->macros[i].keysym	    = 0;	    r->macros[i].modFlags   = 0;	    if (NOT_NULL(r->macros[i].action.str))	    {	        rxvt_free( r->macros[i].action.str );	        SET_NULL(r->macros[i].action.str); /* Probably unnecessary */	    }	    nDummyMacros++;	}    } /* for */    /*     * The macro list now needs to be sorted on keysym. When we look for macros,     * we assume the macro list is sorted, so we can use a binary search to     * lookup macros quickly.     */    qsort( r->macros, r->nmacros, sizeof( macros_t ), macro_cmp);    /* Remove dummy macros from our list */    MEMMOVE( r->macros, r->macros + nDummyMacros,	    (r->nmacros - nDummyMacros) * sizeof( macros_t ) );    r->nmacros -= nDummyMacros;    /* Shrink our macros list */    if( r->nmacros < r->maxMacros )    {	r->macros = rxvt_realloc( r->macros, r->nmacros * sizeof( macros_t ));	r->maxMacros = r->nmacros;    }    rxvt_dbgmsg(( DBG_DEBUG, DBG_MACROS,		"Read %d macros. (Have space for %d macros)\n",		r->nmacros, r->maxMacros));}/* {{{1 rxvt_set_action( action, astring) * * Check what action is specified by astring, and assign respective values in * action. *  * The string astring might be modified, but can be freed immediately after * calling this function (regardless of wether it succeeds or not). *//* EXTPROTO */Boolrxvt_set_action	    (action_t *action, char *astring){    unsigned short type, len;    rxvt_dbgmsg ((DBG_DEBUG, DBG_MACROS, "Setting action '%s'\n", astring));    /*     * Match head of "astring" to a name in macroNames to figure out the macro     * type.     */    for( type = 0; type < NMACRO_FUNCS; type++)    {	if( (len = rxvt_str_match( astring, macroNames[type])) )	{	    /* Matched a macroName at the start of astring */	    if( astring[len] && !isspace( astring[len] ) )		/* Not delimited by a space */		continue;	    /* Skip macroName and delimiting spaces */	    astring += len;	    while( *astring && isspace( *astring ) ) astring++;	    /* Exit for loop early */	    break;	}    }    if( type == NMACRO_FUNCS )    {	rxvt_msg (DBG_ERROR, DBG_MACROS,  "Action %s is not of known type", astring);	return False; /* Failure: No matching macro name */    }    /*     * Setup values in action     */    action->type	= type;    /*     * Interpolate escape sequences into action. XXX: Should we only do this for     * MacroFnStr and MacroFnEsc?.     */    len	= rxvt_str_escaped( astring );    /* All macros exept MacroFnStr and MacroFnEsc have null terminated string */    if( type != MacroFnStr && type != MacroFnEsc && len > 0 && astring[len-1] )	astring[ len++ ] = 0;	/* Since astring was null terminated,				   astring[len] is certainly part of the memory				   in astring. */    action->len	    = len;    /* Set action->str. If any data is previously there, realloc it. */    if( len > 0 )    {	action->str = (unsigned char *) rxvt_realloc( action->str,						len * sizeof(unsigned char));	MEMCPY( action->str, astring, len);    }    else    if (NOT_NULL(action->str))    {	rxvt_free( action->str );	SET_NULL(action->str);    }    return True;}/* {{{1 rxvt_process_macros( keysym, ev) * * Check to see if a macro key was pressed. If yes, exec the action and return * 1. Else return 0. * * 2006-02-24 gi1242: Take both a keysym, and a XKeyEvent argument because, the * caller might have modified keysym based on XIM. *//* EXTPROTO */intrxvt_process_macros( rxvt_t *r, KeySym keysym, XKeyEvent *ev){    macros_t	ck,		/* Storing the keysym and mods of the current				   key that's pressed. */		*macro;		/* Macro we find in our saved list corresponding				   to the current key press */    int		status;    if( r->nmacros == 0 )	return 0;   /* No macro processed */    /* Copy the modifier mask and keysym into ck */    ck.modFlags = 0;    if (ev->state & ShiftMask)		    ck.modFlags |= MACRO_SHIFT;    if (ev->state & ControlMask)	    ck.modFlags |= MACRO_CTRL;    if (ev->state & r->h->ModMetaMask)	    ck.modFlags |= MACRO_META;    /* Use uppercase version so we can ignore caps lock */    {        KeySym upper;        XConvertCase(keysym, &ck.keysym, &upper);    }    /* Check if macro ck is in our list of macros. */    macro = bsearch( &ck, r->macros, r->nmacros, sizeof( macros_t ),		macro_cmp);    if (         /*          * No macro found.          */         IS_NULL(macro)         || (              /*               * Primary only macro in secondary screen.               */              (macro->modFlags & MACRO_PRIMARY)              && AVTS(r)->current_screen != PRIMARY            )         || (              /*               * When macros are disabled, only the toggle macros macro should               * work.               */              ISSET_OPTION(r, Opt2_disableMacros)              && macro->action.type != MacroFnToggleMacros            )       )	return 0;   /* No macro processed */    do      {	rxvt_dbgmsg ((DBG_DEBUG, DBG_MACROS, "Processing macro #%d mods %02hhx\n", macro - r->macros, macro->modFlags));	status = rxvt_dispatch_action( r, &(macro->action), (XEvent*) ev );      }    while(	   status == 1	   && (++macro - r->macros) < r->nmacros	   && MACRO_GET_NUMBER( macro->modFlags ) 	 );    return status;}/* {{{1 rxvt_dispatch_action( action, ev) * * Exec the macro / menu action with type "type" and action "action". Returns 1 * on success, -1 on failure. *//* EXTPROTO */intrxvt_dispatch_action( rxvt_t *r, action_t *action, XEvent *ev){    const int	maxLen = 1024;    char	expstr[ maxLen ];    char	*astr;    int		alen,		retval = 1;	    /* Succeed by default */    if( IS_NULL( action->str ) )    {	SET_NULL( astr );	alen = 0;    }    else    {	/* % interpolate the action string */	astr = expstr;	alen = rxvt_percent_interpolate( r, ATAB(r), (char *) action->str,		action->len, astr, maxLen );    }    switch( action->type )    {	case MacroFnEsc:	    /* Send action to rxvt */	    if( NOT_NULL( astr ) && alen > 1 )		rxvt_cmd_write( r, ATAB(r), (unsigned char*) astr, alen - 1);	    else	    {		rxvt_msg (DBG_ERROR, DBG_MACROS,  "Macro %s requires argument.",			macroNames[action->type] );		retval = -1;	    }	    break;	case MacroFnStr:	    /* Send action to child process */	    if( NOT_NULL( astr ) && alen > 1 )		rxvt_tt_write( r, ATAB(r), (unsigned char*) astr, alen - 1);	    else	    {		rxvt_msg (DBG_ERROR, DBG_MACROS,  "Macro %s requires argument.",			macroNames[action->type] );		retval = -1;	    }	    break;	case MacroFnNewTab:	    if (NOT_NULL(astr))	    {		/*		 * If the first word is quoted, use that as the title. Don't be		 * fancy and check for nested quotes. That's probably		 * unnecessary.		 *		 * Everything after the first quoted word is the command. If		 * command starts with "!", then the shell is exec'ed before		 * running command.		 */		const int   MaxMacroTitle = 80;	/* Longest title we will have */		char	    titlestring[MaxMacroTitle];		char	    *command = (char *) astr;		char	    *title = NULL;		int	    profile = 0;		/* See if a profile is specified */		if( *command == '-' )		{		    char *pnum_end;		    profile = strtoul( ++command, &pnum_end, 0 );		    if( profile < 0 || profile >= MAX_PROFILES )			profile = AVTS(r)->profileNum;		    /* Skip spaces */		    command = pnum_end;		    while( isspace( *command ) ) command++;		}		/* See if a title is specified */		if( *command == '"' )		{		    int i;		    /* Copy everything until first " into title */		    for(			  i=0, command++;			  i < MaxMacroTitle - 2 && *command && *command != '"';			  i++, command++		       )			titlestring[i] = *command;		    titlestring[i] = '\0'; /* Null terminate title */		    title = titlestring;		    /* Skip spaces after title */		    if( *command ) command++;		    while( isspace( *command ) ) command++;		}		/* Add page */		rxvt_append_page( r, profile, title,				    *command ? command : NULL );	    }	    else		rxvt_append_page( r, 0, NULL, NULL );	    break;	case MacroFnExec:	    if( NOT_NULL( astr ) )		retval = rxvt_async_exec( r, astr ) ? 1 : -1;	    else	    {		rxvt_msg (DBG_ERROR, DBG_MACROS,  "Macro %s requires argument.",			macroNames[action->type] );		retval = -1;	    }	    break;	case MacroFnClose:	    if( alen > 0 && *(astr) )	    {		/* Close tab specified by str */		int tabno = atoi( (char*) astr) - 1;		if( tabno == -1 ) tabno = ATAB(r);		if (		      tabno >=0 && tabno <=LTAB(r)		      && (			   NOTSET_OPTION(r, Opt2_protectSecondary)			   || PVTS(r, tabno)->current_screen == PRIMARY			 )		   )		{		    rxvt_kill_page (r, tabno);		}		else		    retval = -1;

⌨️ 快捷键说明

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