macro.c

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

C
1,752
字号
    macroCmdInfo *cmdData = window->macroCmdData;    int closeOnCompletion = cmdData->closeOnCompletion;    XmString s;    XClientMessageEvent event;    /* Cancel pending timeout and work proc */    if (cmdData->bannerTimeoutID != 0)    	XtRemoveTimeOut(cmdData->bannerTimeoutID);    if (cmdData->continueWorkProcID != 0)    	XtRemoveWorkProc(cmdData->continueWorkProcID);        /* Clean up waiting-for-macro-command-to-complete mode */    EndWait(window->shell);    XtVaSetValues(window->cancelMacroItem, XmNlabelString,    	    s=XmStringCreateSimple("Cancel Learn"), NULL);    XmStringFree(s);    XtSetSensitive(window->cancelMacroItem, False);    if (cmdData->bannerIsUp)    	ClearModeMessage(window);    /* If a dialog was up, get rid of it */    if (cmdData->dialog != NULL)    	XtDestroyWidget(XtParent(cmdData->dialog));    /* Free execution information */    FreeProgram(cmdData->program);    XtFree((char *)cmdData);    window->macroCmdData = NULL;        /* If macro closed its own window, window was made empty and untitled,       but close was deferred until completion.  This is completion, so if       the window is still empty, do the close */    if (closeOnCompletion && !window->filenameSet && !window->fileChanged) {    	CloseWindow(window);	window = NULL;    }    /* If no other macros are executing, do garbage collection */    SafeGC();        /* In processing the .neditmacro file (and possibly elsewhere), there       is an event loop which waits for macro completion.  Send an event       to wake up that loop, otherwise execution will stall until the user       does something to the window. */    if (!closeOnCompletion) {	event.format = 8;	event.type = ClientMessage;	XSendEvent(XtDisplay(window->shell), XtWindow(window->shell), False,		NoEventMask, (XEvent *)&event);    }}/*** Do garbage collection of strings if there are no macros currently** executing.  NEdit's macro language GC strategy is to call this routine** whenever a macro completes.  If other macros are still running (preempted** or waiting for a shell command or dialog), this does nothing and therefore** defers GC to the completion of the last macro out.*/void SafeGC(void){    WindowInfo *win;        for (win=WindowList; win!=NULL; win=win->next)	if (win->macroCmdData != NULL || InSmartIndentMacros(win))	    return;    GarbageCollectStrings();}/*** Executes macro string "macro" using the lastFocus pane in "window".** Reports errors via a dialog posted over "window", integrating the name** "errInName" into the message to help identify the source of the error.*/void DoMacro(WindowInfo *window, const char *macro, const char *errInName){    Program *prog;    char *errMsg, *stoppedAt, *tMacro;    int macroLen;        /* Add a terminating newline (which command line users are likely to omit       since they are typically invoking a single routine) */    macroLen = strlen(macro);    tMacro = XtMalloc(strlen(macro)+2);    strncpy(tMacro, macro, macroLen);    tMacro[macroLen] = '\n';    tMacro[macroLen+1] = '\0';        /* Parse the macro and report errors if it fails */    prog = ParseMacro(tMacro, &errMsg, &stoppedAt);    if (prog == NULL) {    	ParseError(window->shell, tMacro, stoppedAt, errInName, errMsg);	XtFree(tMacro);    	return;    }    XtFree(tMacro);    /* run the executable program (prog is freed upon completion) */    runMacro(window, prog);}/*** Get the current Learn/Replay macro in text form.  Returned string is a** pointer to the stored macro and should not be freed by the caller (and** will cease to exist when the next replay macro is installed)*/char *GetReplayMacro(void){    return ReplayMacro;}/*** Present the user a dialog for "Repeat" command*/void RepeatDialog(WindowInfo *window){    Widget form, selBox, radioBox, timesForm;    repeatDialog *rd;    Arg selBoxArgs[1];    char *lastCmdLabel, *parenChar;    XmString s1;    int cmdNameLen;    if (LastCommand == NULL)    {        DialogF(DF_WARN, window->shell, 1, "Repeat Macro",                "No previous commands or learn/\nreplay sequences to repeat",                "Dismiss");        return;    }        /* Remeber the last command, since the user is allowed to work in the       window while the dialog is up */    rd = (repeatDialog *)XtMalloc(sizeof(repeatDialog));    rd->lastCommand = XtNewString(LastCommand);        /* make a label for the Last command item of the dialog, which includes       the last executed action name */    parenChar = strchr(LastCommand, '(');    if (parenChar == NULL)	return;    cmdNameLen = parenChar-LastCommand;    lastCmdLabel = XtMalloc(16 + cmdNameLen);    strcpy(lastCmdLabel, "Last Command (");    strncpy(&lastCmdLabel[14], LastCommand, cmdNameLen);    strcpy(&lastCmdLabel[14 + cmdNameLen], ")");        XtSetArg(selBoxArgs[0], XmNautoUnmanage, False);    selBox = CreatePromptDialog(window->shell, "repeat", selBoxArgs, 1);    rd->shell = XtParent(selBox);    XtAddCallback(rd->shell, XmNdestroyCallback, repeatDestroyCB, rd);    XtAddCallback(selBox, XmNokCallback, repeatOKCB, rd);    XtAddCallback(selBox, XmNapplyCallback, repeatApplyCB, rd);    XtAddCallback(selBox, XmNcancelCallback, repeatCancelCB, rd);    XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_TEXT));    XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_SELECTION_LABEL));    XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_HELP_BUTTON));    XtUnmanageChild(XmSelectionBoxGetChild(selBox, XmDIALOG_APPLY_BUTTON));    XtVaSetValues(XtParent(selBox), XmNtitle, "Repeat Macro", NULL);    AddMotifCloseCallback(XtParent(selBox), repeatCancelCB, rd);        form = XtVaCreateManagedWidget("form", xmFormWidgetClass, selBox, NULL);    radioBox = XtVaCreateManagedWidget("cmdSrc", xmRowColumnWidgetClass, form,    	    XmNradioBehavior, True,	    XmNorientation, XmHORIZONTAL,	    XmNpacking, XmPACK_TIGHT,	    XmNtopAttachment, XmATTACH_FORM,    	    XmNleftAttachment, XmATTACH_FORM, NULL);    rd->lastCmdToggle = XtVaCreateManagedWidget("lastCmdToggle",    	    xmToggleButtonWidgetClass, radioBox, XmNset, True,	    XmNlabelString, s1=XmStringCreateSimple(lastCmdLabel),	    XmNmnemonic, 'C', NULL);    XmStringFree(s1);    XtFree(lastCmdLabel);    XtVaCreateManagedWidget("learnReplayToggle",    	    xmToggleButtonWidgetClass, radioBox, XmNset, False,	    XmNlabelString,	    	s1=XmStringCreateSimple("Learn/Replay"),	    XmNmnemonic, 'L',	    XmNsensitive, ReplayMacro != NULL, NULL);    XmStringFree(s1);    timesForm = XtVaCreateManagedWidget("form", xmFormWidgetClass, form,	    XmNtopAttachment, XmATTACH_WIDGET,    	    XmNtopWidget, radioBox,	    XmNtopOffset, 10,    	    XmNleftAttachment, XmATTACH_FORM, NULL);    radioBox = XtVaCreateManagedWidget("method", xmRowColumnWidgetClass,	    timesForm,    	    XmNradioBehavior, True,	    XmNorientation, XmHORIZONTAL,	    XmNpacking, XmPACK_TIGHT,	    XmNtopAttachment, XmATTACH_FORM,    	    XmNbottomAttachment, XmATTACH_FORM,     	    XmNleftAttachment, XmATTACH_FORM, NULL);    rd->inSelToggle = XtVaCreateManagedWidget("inSelToggle",    	    xmToggleButtonWidgetClass, radioBox, XmNset, False,	    XmNlabelString, s1=XmStringCreateSimple("In Selection"),	    XmNmnemonic, 'I', NULL);    XmStringFree(s1);    rd->toEndToggle = XtVaCreateManagedWidget("toEndToggle",    	    xmToggleButtonWidgetClass, radioBox, XmNset, False,	    XmNlabelString, s1=XmStringCreateSimple("To End"),	    XmNmnemonic, 'T', NULL);    XmStringFree(s1);    XtVaCreateManagedWidget("nTimesToggle",    	    xmToggleButtonWidgetClass, radioBox, XmNset, True,	    XmNlabelString, s1=XmStringCreateSimple("N Times"),	    XmNmnemonic, 'N',	    XmNset, True, NULL);    XmStringFree(s1);    rd->repeatText = XtVaCreateManagedWidget("repeatText", xmTextWidgetClass,	    timesForm,    	    XmNcolumns, 5,    	    XmNtopAttachment, XmATTACH_FORM,	    XmNbottomAttachment, XmATTACH_FORM,    	    XmNleftAttachment, XmATTACH_WIDGET,    	    XmNleftWidget, radioBox, NULL);    RemapDeleteKey(rd->repeatText);    /* Handle mnemonic selection of buttons and focus to dialog */    AddDialogMnemonicHandler(form, FALSE);    /* Set initial focus */#if XmVersion >= 1002    XtVaSetValues(form, XmNinitialFocus, timesForm, NULL);    XtVaSetValues(timesForm, XmNinitialFocus, rd->repeatText, NULL);#endif        /* put up dialog */    rd->forWindow = window;    ManageDialogCenteredOnPointer(selBox);}static void repeatOKCB(Widget w, XtPointer clientData, XtPointer callData){    repeatDialog *rd = (repeatDialog *)clientData;    if (doRepeatDialogAction(rd, ((XmAnyCallbackStruct *)callData)->event))    	XtDestroyWidget(rd->shell);}/* Note that the apply button is not managed in the repeat dialog.  The dialog   itself is capable of non-modal operation, but to be complete, it needs   to dynamically update last command, dimming of learn/replay, possibly a   stop button for the macro, and possibly in-selection with selection */static void repeatApplyCB(Widget w, XtPointer clientData, XtPointer callData){    doRepeatDialogAction((repeatDialog *)clientData,	    ((XmAnyCallbackStruct *)callData)->event);}static int doRepeatDialogAction(repeatDialog *rd, XEvent *event){    int nTimes;    char nTimesStr[TYPE_INT_STR_SIZE(int)];    char *params[2];        /* Find out from the dialog how to repeat the command */    if (XmToggleButtonGetState(rd->inSelToggle))    {        if (!rd->forWindow->buffer->primary.selected)        {            DialogF(DF_WARN, rd->shell, 1, "Repeat Macro",                    "No selection in window to repeat within", "Dismiss");            XmProcessTraversal(rd->inSelToggle, XmTRAVERSE_CURRENT);            return False;        }        params[0] = "in_selection";    } else if (XmToggleButtonGetState(rd->toEndToggle))    {        params[0] = "to_end";    } else    {        if (GetIntTextWarn(rd->repeatText, &nTimes, "number of times", True)                != TEXT_READ_OK)        {            XmProcessTraversal(rd->repeatText, XmTRAVERSE_CURRENT);            return False;        }        sprintf(nTimesStr, "%d", nTimes);        params[0] = nTimesStr;    }        /* Figure out which command user wants to repeat */    if (XmToggleButtonGetState(rd->lastCmdToggle))	params[1] = XtNewString(rd->lastCommand);    else {	if (ReplayMacro == NULL)	    return False;	params[1] = XtNewString(ReplayMacro);    }    /* call the action routine repeat_macro to do the work */    XtCallActionProc(rd->forWindow->lastFocus, "repeat_macro", event, params,2);    XtFree(params[1]);    return True;}static void repeatCancelCB(Widget w, XtPointer clientData, XtPointer callData){    repeatDialog *rd = (repeatDialog *)clientData;    XtDestroyWidget(rd->shell);}static void repeatDestroyCB(Widget w, XtPointer clientData, XtPointer callData){    repeatDialog *rd = (repeatDialog *)clientData;        XtFree(rd->lastCommand);    XtFree((char *)rd);}/*** Dispatches a macro to which repeats macro command in "command", either** an integer number of times ("how" == positive integer), or within a** selected range ("how" == REPEAT_IN_SEL), or to the end of the window** ("how == REPEAT_TO_END).**** Note that as with most macro routines, this returns BEFORE the macro is** finished executing*/void RepeatMacro(WindowInfo *window, const char *command, int how){    Program *prog;    char *errMsg, *stoppedAt, *loopMacro, *loopedCmd;    if (command == NULL)	return;        /* Wrap a for loop and counter/tests around the command */    if (how == REPEAT_TO_END)	loopMacro = "lastCursor=-1\nstartPos=$cursor\n\while($cursor>=startPos&&$cursor!=lastCursor){\nlastCursor=$cursor\n%s\n}\n";    else if (how == REPEAT_IN_SEL)	loopMacro = "selStart = $selection_start\nif (selStart == -1)\nreturn\n\selEnd = $selection_end\nset_cursor_pos(selStart)\nselect(0,0)\n\boundText = get_range(selEnd, selEnd+10)\n\while($cursor >= selStart && $cursor < selEnd && \\\n\get_range(selEnd, selEnd+10) == boundText) {\n\startLength = $text_length\n%s\n\selEnd += $text_length - startLength\n}\n";    else    	loopMacro = "for(i=0;i<%d;i++){\n%s\n}\n";    loopedCmd = XtMalloc(strlen(command) + strlen(loopMacro) + 25);    if (how == REPEAT_TO_END || how == REPEAT_IN_SEL)	sprintf(loopedCmd, loopMacro, command);    else	sprintf(loopedCmd, loopMacro, how, command);

⌨️ 快捷键说明

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