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 + -
显示快捷键?