This patch adds a clear button to the interactive search bar (labelled " Date: 2003-08-25 14:13:44 [Download message RAW] Much as I like the ISearch bar, I am an inveterate mouse user, and find that the ISearch could support mouse use better. In particular: - I want to paste selected words from the main window into the search bar, replacing text already there - I want to invoke a search without having to hit return To this end I patched NEdit so that the Find: label becomes a button which invokes the "activate" action of the text widget, and I added a clear button (labelled "iSearchText, table); + static XtTranslations tableClear = NULL; + static char *translationsClear = + ":Arm()\n: isearch_clear_and_paste() Disarm()\n"; + + static XtActionsRec actions[] = { + { "isearch_clear_and_paste", iSearchTextClearAndPasteAP } + }; + + if (tableText == NULL) + tableText = XtParseTranslationTable(translationsText); + XtOverrideTranslations(window->iSearchText, tableText); + + if (tableClear == NULL) { + /* make sure actions are loaded */ + XtAppAddActions(XtWidgetToApplicationContext(window->iSearchText), + actions, XtNumber(actions)); + tableClear = XtParseTranslationTable(translationsClear); + } + XtOverrideTranslations(window->iSearchClearButton, tableClear); XtAddCallback(window->iSearchText, XmNactivateCallback, (XtCallbackProc)iSearchTextActivateCB, window); XtAddCallback(window->iSearchText, XmNvalueChangedCallback, (XtCallbackProc)iSearchTextValueChangedCB, window); @@ -3011,10 +3032,72 @@ (XtCallbackProc)iSearchTextValueChangedCB, window); XtAddCallback(window->iSearchRegexToggle, XmNvalueChangedCallback, (XtCallbackProc)iSearchTextValueChangedCB, window); XtAddCallback(window->iSearchRevToggle, XmNvalueChangedCallback, (XtCallbackProc)iSearchTextValueChangedCB, window); + + /* find button: just like pressing return */ + XtAddCallback(window->iSearchFindButton, XmNactivateCallback, + (XtCallbackProc)iSearchTextActivateCB, window); + /* clear button: empty the search text widget */ + XtAddCallback(window->iSearchClearButton, XmNactivateCallback, + (XtCallbackProc)iSearchTextClearCB, window); +} + +/* +** Remove callbacks before resetting the incremental search text to avoid any +** cursor movement and/or clearing of selections. +*/ +static void iSearchTextSetString(Widget w, WindowInfo *window, + char *str) +{ + /* remove callbacks which would be activated by emptying the text */ + XtRemoveAllCallbacks(window->iSearchText, XmNvalueChangedCallback); + XtRemoveAllCallbacks(window->iSearchText, XmNactivateCallback); + /* empty the text */ + XmTextSetString(window->iSearchText, str ? str : ""); + /* put back the callbacks */ + XtAddCallback(window->iSearchText, XmNactivateCallback, + (XtCallbackProc)iSearchTextActivateCB, window); + XtAddCallback(window->iSearchText, XmNvalueChangedCallback, + (XtCallbackProc)iSearchTextValueChangedCB, window); +} + +/* +** Action routine for Mouse Button 2 on the iSearchClearButton: resets the +** string then calls the activate callback for the text directly. +*/ +static void iSearchTextClearAndPasteAP(Widget w, XEvent *event, String *args, + Cardinal *nArg) +{ + WindowInfo *window; + char *selText; + XmAnyCallbackStruct cbdata; + + memset(&cbdata, 0, sizeof (cbdata)); + cbdata.event = event; + + window = WidgetToWindow(w); + + selText = GetAnySelection(window); + iSearchTextSetString(w, window, selText); + if (selText) { + XmTextSetInsertionPosition(window->iSearchText, strlen(selText)); + XtFree(selText); + } + iSearchTextActivateCB(w, window, &cbdata); +} + +/* +** User pressed the clear incremental search bar button. Remove callbacks +** before resetting the text to avoid any cursor movement and/or clearing +** of selections. +*/ +static void iSearchTextClearCB(Widget w, WindowInfo *window, + XmAnyCallbackStruct *callData) +{ + iSearchTextSetString(w, window, NULL); } /* ** User pressed return in the incremental search bar. Do a new search with ** the search string displayed. The direction of the search is toggled if diff -rb -U5 nedit_official/source/window.c nedit_mod/source/window.c --- nedit_official/source/window.c 2004-03-19 04:53:21.000000000 -0500 +++ nedit_mod/source/window.c 2004-03-30 00:04:47.324612000 -0500 @@ -210,10 +210,13 @@ unsigned char* invalidBindings = NULL; XmFontList fontList; int fontWidth, tabWidth, state; XFontStruct *fs; + static Pixmap isrcFind = 0; + static Pixmap isrcClear = 0; + if (firstTime) { invalidBindings = sanitizeVirtualKeyBindings(); firstTime = False; } @@ -413,29 +416,55 @@ XmNrightAttachment, XmATTACH_FORM, XmNrightOffset, STAT_SHADOW_THICKNESS, XmNbottomOffset, STAT_SHADOW_THICKNESS, NULL); if(window->showISearchLine) XtManageChild(window->iSearchForm); - iSearchLabel = XtVaCreateManagedWidget("iSearchLabel", - xmLabelWidgetClass, window->iSearchForm, - XmNlabelString, s1=XmStringCreateSimple("Find:"), - XmNmarginHeight, 0, - XmNleftAttachment, XmATTACH_FORM, - XmNleftOffset, 5, - XmNtopAttachment, XmATTACH_FORM, - XmNtopOffset, 1, /* see openmotif note above, for aligment - with toggle buttons below */ - XmNbottomAttachment, XmATTACH_FORM, NULL); - XmStringFree(s1); - /* Disable keyboard traversal of the toggle buttons. We were doing - this previously by forcing the keyboard focus back to the text - widget whenever a toggle changed. That causes an ugly focus flash + /* Disable keyboard traversal of the find, clear and toggle buttons. We + were doing this previously by forcing the keyboard focus back to the + text widget whenever a toggle changed. That causes an ugly focus flash on screen. It's better just not to go there in the first place. Plus, if the user really wants traversal, it's an X resource so it can be enabled without too much pain and suffering. */ + if (isrcFind == 0) { + int isrcFind_width = 11; + int isrcFind_height = 11; + static unsigned char isrcFind_bits[] = { + 0xe0, 0x01, 0x30, 0x03, 0x58, 0x06, 0x68, 0x04, 0x08, 0x04, 0x18, + 0x06, 0x30, 0x03, 0xec, 0x01, 0x0e, 0x00, 0x07, 0x00, 0x03, 0x00 + }; + Pixel fg, bg; + int depth; + /* cf setTabCloseButtonImage() for technique */ + XtVaGetValues (window->iSearchForm, + XmNforeground, &fg, + XmNbackground, &bg, + XmNdepth, &depth, NULL); + isrcFind = XCreatePixmapFromBitmapData(TheDisplay, + RootWindowOfScreen(XtScreen(window->iSearchForm)), + (char *)isrcFind_bits, + isrcFind_width, isrcFind_height, fg, bg, depth); + } + window->iSearchFindButton = XtVaCreateManagedWidget("iSearchFindButton", + xmPushButtonWidgetClass, window->iSearchForm, + XmNlabelString, s1=XmStringCreateSimple("Find"), + XmNlabelType, XmPIXMAP, + XmNlabelPixmap, isrcFind, + XmNtraversalOn, False, + XmNmarginHeight, 1, + XmNmarginWidth, 1, + XmNleftAttachment, XmATTACH_FORM, + /* XmNleftOffset, 3, */ + XmNleftOffset, 0, + XmNtopAttachment, XmATTACH_FORM, + XmNtopOffset, 1, + XmNbottomAttachment, XmATTACH_FORM, + XmNbottomOffset, 1, + NULL); + XmStringFree(s1); + window->iSearchCaseToggle = XtVaCreateManagedWidget("iSearchCaseToggle", xmToggleButtonWidgetClass, window->iSearchForm, XmNlabelString, s1=XmStringCreateSimple("Case"), XmNset, GetPrefSearch() == SEARCH_CASE_SENSE || GetPrefSearch() == SEARCH_REGEX @@ -476,19 +505,56 @@ XmNmarginHeight, 0, XmNtraversalOn, False, NULL); XmStringFree(s1); + if (isrcClear == 0) { + int isrcClear_width = 11; + int isrcClear_height = 11; + static unsigned char isrcClear_bits[] = { + 0x00, 0x00, 0x00, 0x00, 0x0c, 0x03, 0x8c, 0x03, 0xcc, 0x01, 0xec, + 0x00, 0xcc, 0x01, 0x8c, 0x03, 0x0c, 0x03, 0x00, 0x00, 0x00, 0x00 + }; + Pixel fg, bg; + int depth; + /* cf setTabCloseButtonImage() for technique */ + XtVaGetValues (window->iSearchForm, + XmNforeground, &fg, + XmNbackground, &bg, + XmNdepth, &depth, NULL); + isrcClear = XCreatePixmapFromBitmapData(TheDisplay, + RootWindowOfScreen(XtScreen(window->iSearchForm)), + (char *)isrcClear_bits, + isrcClear_width, isrcClear_height, fg, bg, depth); + } + window->iSearchClearButton = XtVaCreateManagedWidget("iSearchClearButton", + xmPushButtonWidgetClass, window->iSearchForm, + XmNlabelString, s1=XmStringCreateSimple("iSearchRevToggle, + XmNrightOffset, 2, + XmNtopAttachment, XmATTACH_FORM, + XmNtopOffset, 1, + XmNbottomAttachment, XmATTACH_FORM, + XmNbottomOffset, 1, + NULL); + XmStringFree(s1); + window->iSearchText = XtVaCreateManagedWidget("iSearchText", xmTextWidgetClass, window->iSearchForm, XmNmarginHeight, 1, XmNnavigationType, XmEXCLUSIVE_TAB_GROUP, XmNleftAttachment, XmATTACH_WIDGET, - XmNleftWidget, iSearchLabel, + XmNleftWidget, window->iSearchFindButton, XmNrightAttachment, XmATTACH_WIDGET, - XmNrightWidget, window->iSearchRevToggle, - XmNrightOffset, 5, + XmNrightWidget, window->iSearchClearButton, + /* XmNrightOffset, 5, */ XmNtopAttachment, XmATTACH_FORM, XmNtopOffset, 0, /* see openmotif note above */ XmNbottomAttachment, XmATTACH_FORM, XmNbottomOffset, 0, NULL); RemapDeleteKey(window->iSearchText);