📄 search.c
字号:
case SEARCH_LITERAL: *lastLiteralCase = False; *lastRegexCase = True; XmToggleButtonSetState(regexToggle, False, False); XmToggleButtonSetState(caseToggle, False, False); if (wordToggle) { XmToggleButtonSetState(*wordToggle, False, False); XtSetSensitive(*wordToggle, True); } break; case SEARCH_CASE_SENSE: *lastLiteralCase = True; *lastRegexCase = True; XmToggleButtonSetState(regexToggle, False, False); XmToggleButtonSetState(caseToggle, True, False); if (wordToggle) { XmToggleButtonSetState(*wordToggle, False, False); XtSetSensitive(*wordToggle, True); } break; case SEARCH_LITERAL_WORD: *lastLiteralCase = False; *lastRegexCase = True; XmToggleButtonSetState(regexToggle, False, False); XmToggleButtonSetState(caseToggle, False, False); if (wordToggle) { XmToggleButtonSetState(*wordToggle, True, False); XtSetSensitive(*wordToggle, True); } break; case SEARCH_CASE_SENSE_WORD: *lastLiteralCase = True; *lastRegexCase = True; XmToggleButtonSetState(regexToggle, False, False); XmToggleButtonSetState(caseToggle, True, False); if (wordToggle) { XmToggleButtonSetState(*wordToggle, True, False); XtSetSensitive(*wordToggle, True); } break; case SEARCH_REGEX: *lastLiteralCase = False; *lastRegexCase = True; XmToggleButtonSetState(regexToggle, True, False); XmToggleButtonSetState(caseToggle, True, False); if (wordToggle) { XmToggleButtonSetState(*wordToggle, False, False); XtSetSensitive(*wordToggle, False); } break; case SEARCH_REGEX_NOCASE: *lastLiteralCase = False; *lastRegexCase = False; XmToggleButtonSetState(regexToggle, True, False); XmToggleButtonSetState(caseToggle, False, False); if (wordToggle) { XmToggleButtonSetState(*wordToggle, False, False); XtSetSensitive(*wordToggle, False); } break; }}#ifdef REPLACE_SCOPE/*** Checks whether a selection spans multiple lines. Used to decide on the** default scope for replace dialogs. ** This routine introduces a dependency on textDisp.h, which is not so nice,** but I currently don't have a cleaner solution.*/static int selectionSpansMultipleLines(WindowInfo *window){ int selStart, selEnd, isRect, rectStart, rectEnd, lineStartStart, lineStartEnd; int lineWidth; textDisp *textD; if (!BufGetSelectionPos(window->buffer, &selStart, &selEnd, &isRect, &rectStart, &rectEnd)) return FALSE; /* This is kind of tricky. The perception of a line depends on the line wrap mode being used. So in theory, we should take into account the layout of the text on the screen. However, the routine to calculate a line number for a given character position (TextDPosToLineAndCol) only works for displayed lines, so we cannot use it. Therefore, we use this simple heuristic: - If a newline is found between the start and end of the selection, we obviously have a multi-line selection. - If no newline is found, but the distance between the start and the end of the selection is larger than the number of characters displayed on a line, and we're in continuous wrap mode, we also assume a multi-line selection. */ lineStartStart = BufStartOfLine(window->buffer, selStart); lineStartEnd = BufStartOfLine(window->buffer, selEnd); /* If the line starts differ, we have a "\n" in between. */ if (lineStartStart != lineStartEnd ) return TRUE; if (window->wrapMode != CONTINUOUS_WRAP) return FALSE; /* Same line */ /* Estimate the number of characters on a line */ textD = ((TextWidget)window->textArea)->text.textD; if (textD->fontStruct->max_bounds.width > 0) lineWidth = textD->width / textD->fontStruct->max_bounds.width; else lineWidth = 1; if (lineWidth < 1) lineWidth = 1; /* Just in case */ /* Estimate the numbers of line breaks from the start of the line to the start and ending positions of the selection and compare.*/ if ((selStart-lineStartStart)/lineWidth != (selEnd-lineStartStart)/lineWidth ) return TRUE; /* Spans multiple lines */ return FALSE; /* Small selection; probably doesn't span lines */}#endifvoid DoFindReplaceDlog(WindowInfo *window, int direction, int keepDialogs, int searchType, Time time){ /* Create the dialog if it doesn't already exist */ if (window->replaceDlog == NULL) createReplaceDlog(window->shell, window); setTextField(window, time, window->replaceText); /* If the window is already up, just pop it to the top */ if (XtIsManaged(window->replaceDlog)) { RaiseShellWindow(XtParent(window->replaceDlog)); return; } /* Blank the Replace with field */ XmTextSetString(window->replaceWithText, ""); /* Set the initial search type */ initToggleButtons(searchType, window->replaceRegexToggle, window->replaceCaseToggle, &window->replaceWordToggle, &window->replaceLastLiteralCase, &window->replaceLastRegexCase); /* Set the initial direction based on the direction argument */ XmToggleButtonSetState(window->replaceRevToggle, direction == SEARCH_FORWARD ? False: True, True); /* Set the state of the Keep Dialog Up button */ XmToggleButtonSetState(window->replaceKeepBtn, keepDialogs, True); #ifdef REPLACE_SCOPE /* Set the state of the scope radio buttons to "In Window". Notify to make sure that callbacks are called. NOTE: due to an apparent bug in OpenMotif, the radio buttons may get stuck after resetting the scope to "In Window". Therefore we must use RadioButtonChangeStateNotified(), which contains a workaround. */ if (window->wasSelected) { /* If a selection exists, the default scope depends on the preference of the user. */ switch(GetPrefReplaceDefScope()) { case REPL_DEF_SCOPE_SELECTION: /* The user prefers selection scope, no matter what the size of the selection is. */ RadioButtonChangeStateNotified(window->replaceScopeSelToggle, True); break; case REPL_DEF_SCOPE_SMART: if (selectionSpansMultipleLines(window)) { /* If the selection spans multiple lines, the user most likely wants to perform a replacement in the selection */ RadioButtonChangeStateNotified(window->replaceScopeSelToggle, True); } else { /* It's unlikely that the user wants a replacement in a tiny selection only. */ RadioButtonChangeStateNotified(window->replaceScopeWinToggle, True); } break; default: /* The user always wants window scope as default. */ RadioButtonChangeStateNotified(window->replaceScopeWinToggle, True); break; } } else { /* No selection -> always choose "In Window" as default. */ RadioButtonChangeStateNotified(window->replaceScopeWinToggle, True); }#endif UpdateReplaceActionButtons(window); /* Start the search history mechanism at the current history item */ window->rHistIndex = 0; /* Display the dialog */ ManageDialogCenteredOnPointer(window->replaceDlog); /* Workaround: LessTif (as of version 0.89) needs reminding of who had the focus when the dialog was unmanaged. When re-managed, focus is lost and events fall through to the window below. */ XmProcessTraversal(window->replaceText, XmTRAVERSE_CURRENT);}static void setTextField(WindowInfo *window, Time time, Widget textField){ XEvent nextEvent; char *primary_selection = 0; SelectionInfo *selectionInfo = XtNew(SelectionInfo); if (GetPrefFindReplaceUsesSelection()) { selectionInfo->done = 0; selectionInfo->window = window; selectionInfo->selection = 0; XtGetSelectionValue(window->textArea, XA_PRIMARY, XA_STRING, (XtSelectionCallbackProc)getSelectionCB, selectionInfo, time); while (selectionInfo->done == 0) { XtAppNextEvent(XtWidgetToApplicationContext(window->textArea), &nextEvent); ServerDispatchEvent(&nextEvent); } primary_selection = selectionInfo->selection; } if (primary_selection == 0) { primary_selection = XtNewString(""); } /* Update the field */ XmTextSetString(textField, primary_selection); XtFree(primary_selection); XtFree((char*)selectionInfo);} static void getSelectionCB(Widget w, SelectionInfo *selectionInfo, Atom *selection, Atom *type, char *value, int *length, int *format){ WindowInfo *window = selectionInfo->window; /* return an empty string if we can't get the selection data */ if (*type == XT_CONVERT_FAIL || *type != XA_STRING || value == NULL || *length == 0) { XtFree(value); selectionInfo->selection = 0; selectionInfo->done = 1; return; } /* return an empty string if the data is not of the correct format. */ if (*format != 8) { DialogF(DF_WARN, window->shell, 1, "Invalid Format", "NEdit can't handle non 8-bit text", "OK"); XtFree(value); selectionInfo->selection = 0; selectionInfo->done = 1; return; } selectionInfo->selection = XtMalloc(*length+1); memcpy(selectionInfo->selection, value, *length); selectionInfo->selection[*length] = 0; XtFree(value); selectionInfo->done = 1;}void DoFindDlog(WindowInfo *window, int direction, int keepDialogs, int searchType, Time time){ /* Create the dialog if it doesn't already exist */ if (window->findDlog == NULL) createFindDlog(window->shell, window); setTextField(window, time, window->findText); /* If the window is already up, just pop it to the top */ if (XtIsManaged(window->findDlog)) { RaiseShellWindow(XtParent(window->findDlog)); return; } /* Set the initial search type */ initToggleButtons(searchType, window->findRegexToggle, window->findCaseToggle, &window->findWordToggle, &window->findLastLiteralCase, &window->findLastRegexCase); /* Set the initial direction based on the direction argument */ XmToggleButtonSetState(window->findRevToggle, direction == SEARCH_FORWARD ? False : True, True);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -