macro.c

来自「nedit 是一款linux下的开发源码的功能强大的编辑器」· C语言 代码 · 共 1,752 行 · 第 1/5 页

C
1,752
字号
        /* Parse the resulting macro into an executable program "prog" */    prog = ParseMacro(loopedCmd, &errMsg, &stoppedAt);    if (prog == NULL) {	fprintf(stderr, "NEdit internal error, repeat macro syntax wrong: %s\n",    		errMsg);    	return;    }    XtFree(loopedCmd);    /* run the executable program */    runMacro(window, prog);}/*** Macro recording action hook for Learn/Replay, added temporarily during** learn.*/static void learnActionHook(Widget w, XtPointer clientData, String actionName,	XEvent *event, String *params, Cardinal *numParams){    WindowInfo *window;    int i;    char *actionString;        /* Select only actions in text panes in the window for which this       action hook is recording macros (from clientData). */    for (window=WindowList; window!=NULL; window=window->next) {	if (window->textArea == w)	    break;	for (i=0; i<window->nPanes; i++) {    	    if (window->textPanes[i] == w)    	    	break;	}	if (i < window->nPanes)	    break;    }    if (window == NULL || window != (WindowInfo *)clientData)    	return;        /* beep on un-recordable operations which require a mouse position, to       remind the user that the action was not recorded */    if (isMouseAction(actionName)) {    	XBell(XtDisplay(w), 0);    	return;    }        /* Record the action and its parameters */    actionString = actionToString(w, actionName, event, params, *numParams);    if (actionString != NULL) {	BufInsert(MacroRecordBuf, MacroRecordBuf->length, actionString);	XtFree(actionString);    }}/*** Permanent action hook for remembering last action for possible replay*/static void lastActionHook(Widget w, XtPointer clientData, String actionName,	XEvent *event, String *params, Cardinal *numParams){    WindowInfo *window;    int i;    char *actionString;        /* Find the window to which this action belongs */    for (window=WindowList; window!=NULL; window=window->next) {	if (window->textArea == w)	    break;	for (i=0; i<window->nPanes; i++) {    	    if (window->textPanes[i] == w)    	    	break;	}	if (i < window->nPanes)	    break;    }    if (window == NULL)    	return;    /* The last action is recorded for the benefit of repeating the last       action.  Don't record repeat_macro and wipe out the real action */    if (!strcmp(actionName, "repeat_macro"))	return;            /* Record the action and its parameters */    actionString = actionToString(w, actionName, event, params, *numParams);    if (actionString != NULL) {	if (LastCommand != NULL)	    XtFree(LastCommand);	LastCommand = actionString;    }}/*** Create a macro string to represent an invocation of an action routine.** Returns NULL for non-operational or un-recordable actions.*/static char *actionToString(Widget w, char *actionName, XEvent *event,	String *params, Cardinal numParams){    char chars[20], *charList[1], *outStr, *outPtr;    KeySym keysym;    int i, nChars, nParams, length, nameLength;#ifndef NO_XMIM    int status;#endif        if (isIgnoredAction(actionName) || isRedundantAction(actionName) ||	    isMouseAction(actionName))    	return NULL;        /* Convert self_insert actions, to insert_string */    if (!strcmp(actionName, "self_insert") ||    	    !strcmp(actionName, "self-insert")) {    	actionName = "insert_string";#ifdef NO_XMIM	nChars = XLookupString((XKeyEvent *)event, chars, 19, &keysym, NULL);	if (nChars == 0)	    return NULL;#else	nChars = XmImMbLookupString(w, (XKeyEvent *)event,				    chars, 19, &keysym, &status);	if (nChars == 0 || status == XLookupNone ||		status == XLookupKeySym || status == XBufferOverflow)	    return NULL;#endif    	chars[nChars] = '\0';    	charList[0] = chars;    	params = charList;    	nParams = 1;    } else    	nParams = numParams;    	    /* Figure out the length of string required */    nameLength = strlen(actionName);    length = nameLength + 3;    for (i=0; i<nParams; i++)	length += escapedStringLength(params[i]) + 4;        /* Allocate the string and copy the information to it */    outPtr = outStr = XtMalloc(length + 1);    strcpy(outPtr, actionName);    outPtr += nameLength;    *outPtr++ = '(';    for (i=0; i<nParams; i++) {	*outPtr++ = '\"';	outPtr += escapeStringChars(params[i], outPtr);	*outPtr++ = '\"'; *outPtr++ = ','; *outPtr++ = ' ';    }    if (nParams != 0)	outPtr -= 2;    *outPtr++ = ')'; *outPtr++ = '\n'; *outPtr++ = '\0';    return outStr;}static int isMouseAction(const char *action){    int i;        for (i=0; i<(int)XtNumber(MouseActions); i++)    	if (!strcmp(action, MouseActions[i]))    	    return True;    return False;}static int isRedundantAction(const char *action){    int i;        for (i=0; i<(int)XtNumber(RedundantActions); i++)    	if (!strcmp(action, RedundantActions[i]))    	    return True;    return False;}static int isIgnoredAction(const char *action){    int i;        for (i=0; i<(int)XtNumber(IgnoredActions); i++)    	if (!strcmp(action, IgnoredActions[i]))    	    return True;    return False;}/*** Timer proc for putting up the "Macro Command in Progress" banner if** the process is taking too long.*/#define MAX_TIMEOUT_MSG_LEN (MAX_ACCEL_LEN + 60)static void bannerTimeoutProc(XtPointer clientData, XtIntervalId *id){    WindowInfo *window = (WindowInfo *)clientData;    macroCmdInfo *cmdData = window->macroCmdData;    XmString xmCancel;    char *cCancel;    char message[MAX_TIMEOUT_MSG_LEN];        cmdData->bannerIsUp = True;    /* Extract accelerator text from menu PushButtons */    XtVaGetValues(window->cancelMacroItem, XmNacceleratorText, &xmCancel, NULL);    /* Translate Motif string to char* */    cCancel = GetXmStringText(xmCancel);    /* Free Motif String */    XmStringFree(xmCancel);    /* Create message */    if (cCancel[0] == '\0') {        strncpy(message, "Macro Command in Progress", MAX_TIMEOUT_MSG_LEN);        message[MAX_TIMEOUT_MSG_LEN - 1] = '\0';    }    else {        sprintf(message,            "Macro Command in Progress -- Press %s to Cancel",            cCancel);    }    /* Free C-string */    XtFree(cCancel);    SetModeMessage(window, message);    cmdData->bannerTimeoutID = 0;}/*** Work proc for continuing execution of a preempted macro.**** Xt WorkProcs are designed to run first-in first-out, which makes them** very bad at sharing time between competing tasks.  For this reason, it's** usually bad to use work procs anywhere where their execution is likely to** overlap.  Using a work proc instead of a timer proc (which I usually** prefer) here means macros will probably share time badly, but we're more** interested in making the macros cancelable, and in continuing other work** than having users run a bunch of them at once together.*/static Boolean continueWorkProc(XtPointer clientData){    WindowInfo *window = (WindowInfo *)clientData;    macroCmdInfo *cmdData = window->macroCmdData;    char *errMsg;    int stat;    DataValue result;        stat = ContinueMacro(cmdData->context, &result, &errMsg);    if (stat == MACRO_ERROR)    {        finishMacroCmdExecution(window);        DialogF(DF_ERR, window->shell, 1, "Macro Error",                "Error executing macro: %s", "Dismiss", errMsg);        return True;    } else if (stat == MACRO_DONE)    {        finishMacroCmdExecution(window);        return True;    } else if (stat == MACRO_PREEMPT)    {        cmdData->continueWorkProcID = 0;        return True;    }        /* Macro exceeded time slice, re-schedule it */    if (stat != MACRO_TIME_LIMIT)    	return True; /* shouldn't happen */    return False;}/*** Copy fromString to toString replacing special characters in strings, such** that they can be read back by the macro parser's string reader.  i.e. double** quotes are replaced by \", backslashes are replaced with \\, C-std control** characters like \n are replaced with their backslash counterparts.  This** routine should be kept reasonably in sync with yylex in parse.y.  Companion** routine escapedStringLength predicts the length needed to write the string** when it is expanded with the additional characters.  Returns the number** of characters to which the string expanded.*/static int escapeStringChars(char *fromString, char *toString){    char *e, *c, *outPtr = toString;        /* substitute escape sequences */    for (c=fromString; *c!='\0'; c++) {    	for (e=EscapeChars; *e!='\0'; e++) {    	    if (*c == *e) {    		*outPtr++ = '\\';    		*outPtr++ = ReplaceChars[e-EscapeChars];		break;	    }	}	if (*e == '\0')    	   *outPtr++ = *c;    }    *outPtr = '\0';    return outPtr - toString;}/*** Predict the length of a string needed to hold a copy of "string" with** special characters replaced with escape sequences by escapeStringChars.*/static int escapedStringLength(char *string){    char *c, *e;    int length = 0;    /* calculate length and allocate returned string */    for (c=string; *c!='\0'; c++) {    	for (e=EscapeChars; *e!='\0'; e++) {	    if (*c == *e) {    		length++;		break;	    }	}    	length++;    }    return length;}/*** Built-in macro subroutine for getting the length of a string*/static int lengthMS(WindowInfo *window, DataValue *argList, int nArgs,    	DataValue *result, char **errMsg){    char *string, stringStorage[TYPE_INT_STR_SIZE(int)];        if (nArgs != 1)    	return wrongNArgsErr(errMsg);    if (!readStringArg(argList[0], &string, stringStorage, errMsg))	return False;    result->tag = INT_TAG;    result->val.n = strlen(string);    return True;}/*** Built-in macro subroutines for min and max*/static int minMS(WindowInfo *window, DataValue *argList, int nArgs,    	DataValue *result, char **errMsg){    int minVal, value, i;        if (nArgs =

⌨️ 快捷键说明

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