📄 smartindent.c
字号:
winData->newlineMacro = ParseMacro(indentMacros->newlineMacro, &errMsg, &stoppedAt); if (winData->newlineMacro == NULL) { ParseError(window->shell, indentMacros->newlineMacro, stoppedAt, "newline macro", errMsg); return; } if (indentMacros->modMacro == NULL) winData->modMacro = NULL; else { winData->modMacro = ParseMacro(indentMacros->modMacro, &errMsg, &stoppedAt); if (winData->modMacro == NULL) { ParseError(window->shell, indentMacros->modMacro, stoppedAt, "smart indent modify macro", errMsg); return; } } window->smartIndentData = (void *)winData;}void EndSmartIndent(WindowInfo *window){ windowSmartIndentData *winData = (windowSmartIndentData *)window->smartIndentData; if (winData == NULL) return; /* Free programs and allocated data */ if (winData->modMacro != NULL) FreeProgram(winData->modMacro); FreeProgram(winData->newlineMacro); XtFree((char *)winData); window->smartIndentData = NULL;}/*** Returns true if there are smart indent macros for a named language*/int SmartIndentMacrosAvailable(char *languageModeName){ return findIndentSpec(languageModeName) != NULL;}/*** Attaches to the text widget's smart-indent callback to invoke a user** defined macro when the text widget requires an indent (not just when the** user types a newline, but also when the widget does an auto-wrap with** auto-indent on), or the user types some other character.*/void SmartIndentCB(Widget w, XtPointer clientData, XtPointer callData) { WindowInfo *window = (WindowInfo *)clientData; smartIndentCBStruct *cbInfo = (smartIndentCBStruct *)callData; if (window->smartIndentData == NULL) return; if (cbInfo->reason == CHAR_TYPED) executeModMacro(window, cbInfo); else if (cbInfo->reason == NEWLINE_INDENT_NEEDED) executeNewlineMacro(window, cbInfo);}/*** Run the newline macro with information from the smart-indent callback** structure passed by the widget*/static void executeNewlineMacro(WindowInfo *window, smartIndentCBStruct *cbInfo){ windowSmartIndentData *winData = (windowSmartIndentData *)window->smartIndentData; /* posValue probably shouldn't be static due to re-entrance issues <slobasso> */ static DataValue posValue = {INT_TAG, {0}}; DataValue result; RestartData *continuation; char *errMsg; int stat; /* Beware of recursion: the newline macro may insert a string which triggers the newline macro to be called again and so on. Newline macros shouldn't insert strings, but nedit must not crash either if they do. */ if (winData->inNewLineMacro) return; /* Call newline macro with the position at which to add newline/indent */ posValue.val.n = cbInfo->pos; ++(winData->inNewLineMacro); stat = ExecuteMacro(window, winData->newlineMacro, 1, &posValue, &result, &continuation, &errMsg); /* Don't allow preemption or time limit. Must get return value */ while (stat == MACRO_TIME_LIMIT) stat = ContinueMacro(continuation, &result, &errMsg); --(winData->inNewLineMacro); /* Collect Garbage. Note that the mod macro does not collect garbage, (because collecting per-line is more efficient than per-character) but GC now depends on the newline macro being mandatory */ SafeGC(); /* Process errors in macro execution */ if (stat == MACRO_PREEMPT || stat == MACRO_ERROR) { DialogF(DF_ERR, window->shell, 1, "Smart Indent", "Error in smart indent macro:\n%s", "Dismiss", stat == MACRO_ERROR ? errMsg : "dialogs and shell commands not permitted"); EndSmartIndent(window); return; } /* Validate and return the result */ if (result.tag != INT_TAG || result.val.n < -1 || result.val.n > 1000) { DialogF(DF_ERR, window->shell, 1, "Smart Indent", "Smart indent macros must return\ninteger indent distance", "Dismiss"); EndSmartIndent(window); return; } cbInfo->indentRequest = result.val.n;}Boolean InSmartIndentMacros(WindowInfo *window) { windowSmartIndentData *winData = (windowSmartIndentData *)window->smartIndentData; return((winData && (winData->inModMacro || winData->inNewLineMacro)));}/*** Run the modification macro with information from the smart-indent callback** structure passed by the widget*/static void executeModMacro(WindowInfo *window,smartIndentCBStruct *cbInfo){ windowSmartIndentData *winData = (windowSmartIndentData *)window->smartIndentData; /* args probably shouldn't be static due to future re-entrance issues <slobasso> */ static DataValue args[2] = {{INT_TAG, {0}}, {STRING_TAG, {0}}}; /* after 5.2 release remove inModCB and use new winData->inModMacro value */ static int inModCB = False; DataValue result; RestartData *continuation; char *errMsg; int stat; /* Check for inappropriate calls and prevent re-entering if the macro makes a buffer modification */ if (winData == NULL || winData->modMacro == NULL || inModCB) return; /* Call modification macro with the position of the modification, and the character(s) inserted. Don't allow preemption or time limit. Execution must not overlap or re-enter */ args[0].val.n = cbInfo->pos; args[1].val.str = AllocString(strlen(cbInfo->charsTyped) + 1); strcpy(args[1].val.str, cbInfo->charsTyped); inModCB = True; ++(winData->inModMacro); stat = ExecuteMacro(window, winData->modMacro, 3, args, &result, &continuation, &errMsg); while (stat == MACRO_TIME_LIMIT) stat = ContinueMacro(continuation, &result, &errMsg); --(winData->inModMacro); inModCB = False; /* Process errors in macro execution */ if (stat == MACRO_PREEMPT || stat == MACRO_ERROR) { DialogF(DF_ERR, window->shell, 1, "Smart Indent", "Error in smart indent modification macro:\n%s", "Dismiss", stat == MACRO_ERROR ? errMsg : "dialogs and shell commands not permitted"); EndSmartIndent(window); return; }}void EditSmartIndentMacros(WindowInfo *window){#define BORDER 4 Widget form, lmOptMenu, lmForm, lmBtn; Widget okBtn, applyBtn, checkBtn, deleteBtn, commonBtn; Widget dismissBtn, helpBtn, restoreBtn, pane; Widget initForm, newlineForm, modifyForm; Widget initLbl, newlineLbl, modifyLbl; XmString s1; char *lmName; Arg args[20]; int n; /* if the dialog is already displayed, just pop it to the top and return */ if (SmartIndentDialog.shell != NULL) { RaiseShellWindow(SmartIndentDialog.shell); return; } if (LanguageModeName(0) == NULL) { DialogF(DF_WARN, window->shell, 1, "Language Mode", "No Language Modes defined", "Dismiss"); return; } /* Decide on an initial language mode */ lmName = LanguageModeName(window->languageMode == PLAIN_LANGUAGE_MODE ? 0 : window->languageMode); SmartIndentDialog.langModeName = XtNewString(lmName); /* Create a form widget in an application shell */ n = 0; XtSetArg(args[n], XmNdeleteResponse, XmDO_NOTHING); n++; XtSetArg(args[n], XmNiconName, "NEdit Smart Indent Macros"); n++; XtSetArg(args[n], XmNtitle, "Program Smart Indent Macros"); n++; SmartIndentDialog.shell = CreateShellWithBestVis(APP_NAME, APP_CLASS, applicationShellWidgetClass, TheDisplay, args, n); AddSmallIcon(SmartIndentDialog.shell); form = XtVaCreateManagedWidget("editSmartIndentMacros", xmFormWidgetClass, SmartIndentDialog.shell, XmNautoUnmanage, False, XmNresizePolicy, XmRESIZE_NONE, NULL); XtAddCallback(form, XmNdestroyCallback, destroyCB, NULL); AddMotifCloseCallback(SmartIndentDialog.shell, dismissCB, NULL); lmForm = XtVaCreateManagedWidget("lmForm", xmFormWidgetClass, form, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 1, XmNtopAttachment, XmATTACH_POSITION, XmNtopPosition, 1, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 99, NULL); SmartIndentDialog.lmPulldown = CreateLanguageModeMenu(lmForm, langModeCB, NULL); n = 0; XtSetArg(args[n], XmNspacing, 0); n++; XtSetArg(args[n], XmNmarginWidth, 0); n++; XtSetArg(args[n], XmNtopAttachment, XmATTACH_FORM); n++; XtSetArg(args[n], XmNleftAttachment, XmATTACH_POSITION); n++; XtSetArg(args[n], XmNleftPosition, 50); n++; XtSetArg(args[n], XmNsubMenuId, SmartIndentDialog.lmPulldown); n++; lmOptMenu = XmCreateOptionMenu(lmForm, "langModeOptMenu", args, n); XtManageChild(lmOptMenu); SmartIndentDialog.lmOptMenu = lmOptMenu; XtVaCreateManagedWidget("lmLbl", xmLabelGadgetClass, lmForm, XmNlabelString, s1=XmStringCreateSimple("Language Mode:"), XmNmnemonic, 'L', XmNuserData, XtParent(SmartIndentDialog.lmOptMenu), XmNalignment, XmALIGNMENT_END, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 50, XmNtopAttachment, XmATTACH_FORM, XmNbottomAttachment, XmATTACH_OPPOSITE_WIDGET, XmNbottomWidget, lmOptMenu, NULL); XmStringFree(s1); lmBtn = XtVaCreateManagedWidget("lmBtn", xmPushButtonWidgetClass, lmForm, XmNlabelString, s1=MKSTRING("Add / Modify\nLanguage Mode..."), XmNmnemonic, 'A', XmNrightAttachment, XmATTACH_FORM, XmNtopAttachment, XmATTACH_FORM, NULL); XtAddCallback(lmBtn, XmNactivateCallback, lmDialogCB, NULL); XmStringFree(s1); commonBtn = XtVaCreateManagedWidget("commonBtn", xmPushButtonWidgetClass, lmForm, XmNlabelString, s1=MKSTRING("Common / Shared\nInitialization..."), XmNmnemonic, 'C', XmNleftAttachment, XmATTACH_FORM, XmNtopAttachment, XmATTACH_FORM, NULL); XtAddCallback(commonBtn, XmNactivateCallback, commonDialogCB, NULL); XmStringFree(s1); okBtn = XtVaCreateManagedWidget("ok", xmPushButtonWidgetClass, form, XmNlabelString, s1=XmStringCreateSimple("OK"), XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 1, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 13, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, BORDER, NULL); XtAddCallback(okBtn, XmNactivateCallback, okCB, NULL); XmStringFree(s1); applyBtn = XtVaCreateManagedWidget("apply", xmPushButtonWidgetClass, form, XmNlabelString, s1=XmStringCreateSimple("Apply"), XmNmnemonic, 'y', XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 13, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 26, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, BORDER, NULL); XtAddCallback(applyBtn, XmNactivateCallback, applyCB, NULL); XmStringFree(s1); checkBtn = XtVaCreateManagedWidget("check", xmPushButtonWidgetClass, form, XmNlabelString, s1=XmStringCreateSimple("Check"), XmNmnemonic, 'k', XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 26, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 39, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, BORDER, NULL); XtAddCallback(checkBtn, XmNactivateCallback, checkCB, NULL); XmStringFree(s1); deleteBtn = XtVaCreateManagedWidget("delete", xmPushButtonWidgetClass, form, XmNlabelString, s1=XmStringCreateSimple("Delete"), XmNmnemonic, 'D', XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 39, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 52, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, BORDER, NULL); XtAddCallback(deleteBtn, XmNactivateCallback, deleteCB, NULL); XmStringFree(s1); restoreBtn = XtVaCreateManagedWidget("restore", xmPushButtonWidgetClass, form, XmNlabelString, s1=XmStringCreateSimple("Restore Defaults"), XmNmnemonic, 'f', XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 52, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 73, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, BORDER, NULL); XtAddCallback(restoreBtn, XmNactivateCallback, restoreCB, NULL); XmStringFree(s1); dismissBtn = XtVaCreateManagedWidget("dismiss", xmPushButtonWidgetClass, form, XmNlabelString, s1=XmStringCreateSimple("Dismiss"), XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 73, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 86, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, BORDER, NULL); XtAddCallback(dismissBtn, XmNactivateCallback, dismissCB, NULL); XmStringFree(s1); helpBtn = XtVaCreateManagedWidget("help", xmPushButtonWidgetClass, form, XmNlabelString, s1=XmStringCreateSimple("Help"), XmNmnemonic, 'H', XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 86, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 99, XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, BORDER, NULL); XtAddCallback(helpBtn, XmNactivateCallback, helpCB, NULL); XmStringFree(s1); pane = XtVaCreateManagedWidget("pane", xmPanedWindowWidgetClass, form, XmNleftAttachment, XmATTACH_POSITION, XmNleftPosition, 1, XmNrightAttachment, XmATTACH_POSITION, XmNrightPosition, 99,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -