update .gitignore
[nedit-bw.git] / SmartCaseSearch.patch
blob3055856d9c1fca624f8940a46cd7ad3b618d3cd7
1 ---
3 doc/help.etx | 23 ++++++++++++------
4 source/menu.c | 36 +++++++++++++++++++++++++++++
5 source/nedit.h | 1
6 source/preferences.c | 17 +++++++------
7 source/search.c | 63 ++++++++++++++++++++++++++++++++++++++++++++++-----
8 source/search.h | 1
9 source/window.c | 3 +-
10 7 files changed, 122 insertions(+), 22 deletions(-)
12 diff --quilt old/doc/help.etx new/doc/help.etx
13 --- old/doc/help.etx
14 +++ new/doc/help.etx
15 @@ -260,10 +260,15 @@ Finding and Replacing Text
16 button with an icon resembling "|<". Clicking on it empties the search text widget
17 without disturbing selections. A middle click on the clear button copies the
18 content of any existing selection into the search text widget and triggers a new
19 search.
21 + All searches will default to the search mode selected in the preference menu.
22 + (Default Setting -> Searching -> Default Search Style). You can choose a smart
23 + case sensitivity here; this let all searches start insensitive, but changes to
24 + case sensitive as soon as you enter an upper-case letter.
26 3>Searching Backwards
28 Holding down the shift key while choosing any of the search or replace
29 commands from the menu (or using the keyboard shortcut), will search in the
30 reverse direction. Users who have set the search direction using the buttons
31 @@ -2765,23 +2770,24 @@ Macro Subroutines
32 Searches silently in a window without dialogs, beeps, or changes to the
33 selection. Arguments are: 1: string to search for, 2: starting position.
34 Optional arguments may include the strings: "wrap" to make the search wrap
35 around the beginning or end of the string, "backward" or "forward" to change
36 the search direction ("forward" is the default), "literal", "case", "word",
37 - "caseWord", "regex", or "regexNoCase" to change the search type (default is
38 - "literal"). Returns the starting position of the match, or -1 if nothing
39 - matched. Also returns the ending position of the match in $search_end.
40 + "caseWord", "regex", "regexNoCase", or "regexSmartCase" to change the search
41 + type (default is "literal"). Returns the starting position of the match, or
42 + -1 if nothing matched. Also returns the ending position of the match in
43 + $search_end.
45 **search_string( string, search_for, start [, search_type, direction] )**
46 Built-in macro subroutine for searching a string. Arguments are 1: string to
47 search in, 2: string to search for, 3: starting position. Optional arguments
48 may include the strings: "wrap" to make the search wrap around the beginning
49 or end of the string, "backward" or "forward" to change the search direction
50 ("forward" is the default), "literal", "case", "word", "caseWord", "regex",
51 - or "regexNoCase" to change the search type (default is "literal"). Returns
52 - the starting position of the match, or -1 if nothing matched. Also returns
53 - the ending position of the match in $search_end.
54 + "regexNoCase", or "regexSmartCase" to change the search type (default is
55 + "literal"). Returns the starting position of the match, or -1 if nothing
56 + matched. Also returns the ending position of the match in $search_end.
58 **select( start, end )**
59 Selects (with the primary selection) text in the current buffer between a
60 starting and ending position.
62 @@ -3320,12 +3326,13 @@ Action Routines
63 "caseWord".
65 ~search-direction~
66 Either "forward" or "backward".
68 - ~search-type~ Either "literal", "case", "word",
69 - "caseWord", "regex", or "regexNoCase".
70 + ~search-type~ Either "literal", "case", "word",
71 + "caseWord", "regex", "regexNoCase",
72 + or "regexSmartCase".
74 ~search-wrap~ Either "wrap" or "nowrap".
76 ~shell-menu-item-name~
77 Name of the command exactly as specified in
78 diff --quilt old/source/menu.c new/source/menu.c
79 --- old/source/menu.c
80 +++ new/source/menu.c
81 @@ -191,10 +191,12 @@ static void exitWarnDefCB(Widget w, Wind
82 static void searchLiteralCB(Widget w, WindowInfo *window, caddr_t callData);
83 static void searchCaseSenseCB(Widget w, WindowInfo *window, caddr_t callData);
84 static void searchLiteralWordCB(Widget w, WindowInfo *window, caddr_t callData);
85 static void searchCaseSenseWordCB(Widget w, WindowInfo *window, caddr_t callData);
86 static void searchRegexNoCaseCB(Widget w, WindowInfo *window, caddr_t callData);
87 +static void searchRegexSmartCaseCB(Widget toggleButton, WindowInfo *windowInfo,
88 + caddr_t callData);
89 static void searchRegexCB(Widget w, WindowInfo *window, caddr_t callData);
90 #ifdef REPLACE_SCOPE
91 static void replaceScopeWindowCB(Widget w, WindowInfo *window, caddr_t callData);
92 static void replaceScopeSelectionCB(Widget w, WindowInfo *window, caddr_t callData);
93 static void replaceScopeSmartCB(Widget w, WindowInfo *window, caddr_t callData);
94 @@ -933,10 +935,14 @@ Widget CreateMenuBar(Widget parent, Wind
95 "regularExpression", "Regular Expression", 'R', searchRegexCB,
96 window, GetPrefSearch() == SEARCH_REGEX, FULL);
97 window->searchRegexNoCaseDefItem = createMenuToggle(subSubSubPane,
98 "regularExpressionNoCase", "Regular Expression, Case Insensitive", 'I', searchRegexNoCaseCB, window,
99 GetPrefSearch() == SEARCH_REGEX_NOCASE, FULL);
100 + window->searchRegexSmartCaseDefItem = createMenuToggle(subSubSubPane,
101 + "regularExpressionSmartCase", "Regular Expression, Smart Case",
102 + 'S', searchRegexSmartCaseCB, window,
103 + GetPrefSearch() == SEARCH_REGEX_SMARTCASE, FULL);
104 #ifdef REPLACE_SCOPE
105 subSubSubPane = createMenu(subSubPane, "defaultReplaceScope",
106 "Default Replace Scope", 'R', NULL, FULL);
107 XtVaSetValues(subSubSubPane, XmNradioBehavior, True, NULL);
108 window->replScopeWinDefItem = createMenuToggle(subSubSubPane, "window",
109 @@ -2566,10 +2572,40 @@ static void searchRegexNoCaseCB(Widget w
110 XmToggleButtonSetState(win->searchRegexNoCaseDefItem, True, False);
115 +static void searchRegexSmartCaseCB(Widget toggleButton, WindowInfo *window,
116 + caddr_t callData)
118 + WindowInfo *windowInfo;
120 + /* Set the preference and make the other windows' menus agree */
121 + if (XmToggleButtonGetState(toggleButton)) {
122 + SetPrefSearch(SEARCH_REGEX_SMARTCASE);
124 + for (windowInfo = WindowList;
125 + windowInfo != NULL;
126 + windowInfo = windowInfo->next) {
127 + XmToggleButtonSetState(windowInfo->searchLiteralDefItem,
128 + False, False);
129 + XmToggleButtonSetState(windowInfo->searchCaseSenseDefItem,
130 + False, False);
131 + XmToggleButtonSetState(windowInfo->searchLiteralWordDefItem,
132 + False, False);
133 + XmToggleButtonSetState(windowInfo->searchCaseSenseWordDefItem,
134 + False, False);
135 + XmToggleButtonSetState(windowInfo->searchRegexDefItem,
136 + False, False);
137 + XmToggleButtonSetState(windowInfo->searchRegexNoCaseDefItem,
138 + False, False);
139 + XmToggleButtonSetState(windowInfo->searchRegexSmartCaseDefItem,
140 + True, False);
145 #ifdef REPLACE_SCOPE
146 static void replaceScopeWindowCB(Widget w, WindowInfo *window, caddr_t callData)
148 WindowInfo *win;
150 diff --quilt old/source/nedit.h new/source/nedit.h
151 --- old/source/nedit.h
152 +++ new/source/nedit.h
153 @@ -423,10 +423,11 @@ typedef struct _WindowInfo {
154 Widget searchLiteralDefItem;
155 Widget searchCaseSenseDefItem;
156 Widget searchLiteralWordDefItem;
157 Widget searchCaseSenseWordDefItem;
158 Widget searchRegexNoCaseDefItem;
159 + Widget searchRegexSmartCaseDefItem;
160 Widget searchRegexDefItem;
161 #ifdef REPLACE_SCOPE
162 Widget replScopeWinDefItem;
163 Widget replScopeSelDefItem;
164 Widget replScopeSmartDefItem;
165 diff --quilt old/source/preferences.c new/source/preferences.c
166 --- old/source/preferences.c
167 +++ new/source/preferences.c
168 @@ -117,10 +117,11 @@ enum fontStatus {GOOD_FONT, BAD_PRIMARY,
169 ** defined in search.h (!!)
171 static char *SearchMethodStrings[] = {
172 "Literal", "CaseSense", "RegExp",
173 "LiteralWord", "CaseSenseWord", "RegExpNoCase",
174 + "RegExpSmartCase",
175 NULL
178 #ifdef REPLACE_SCOPE
179 /* enumerated default scope for replace dialog if a selection exists when
180 @@ -2218,18 +2219,10 @@ int GetPrefOverrideVirtKeyBindings(void)
181 int GetPrefTruncSubstitution(void)
183 return PrefData.truncSubstitution;
187 -** If preferences don't get saved, ask the user on exit whether to save
189 -void MarkPrefsChanged(void)
191 - PrefsHaveChanged = True;
194 void SetPrefShowCursorline(Boolean value)
196 setIntPref(&PrefData.showCursorline, (int)value);
199 @@ -2237,10 +2230,18 @@ Boolean GetPrefShowCursorline(void)
201 return PrefData.showCursorline;
205 +** If preferences don't get saved, ask the user on exit whether to save
207 +void MarkPrefsChanged(void)
209 + PrefsHaveChanged = True;
213 ** Check if preferences have changed, and if so, ask the user if he wants
214 ** to re-save. Returns False if user requests cancelation of Exit (or whatever
215 ** operation triggered this call to be made).
217 int CheckPrefsChangesSaved(Widget dialogParent)
218 diff --quilt old/source/search.c new/source/search.c
219 --- old/source/search.c
220 +++ new/source/search.c
221 @@ -243,10 +243,11 @@ static void iSearchTryBeepOnWrap(WindowI
222 int beginPos, int startPos);
223 static void iSearchRecordLastBeginPos(WindowInfo *window, int direction,
224 int initPos);
225 static Boolean prefOrUserCancelsSubst(const Widget parent,
226 const Display* display);
227 +static void smartCaseToggle(const char *searchString, Widget toggleButton);
229 typedef struct _charMatchTable {
230 char c;
231 char match;
232 char direction;
233 @@ -279,10 +280,11 @@ static char *searchTypeStrings[] = {
234 "case", /* SEARCH_CASE_SENSE */
235 "regex", /* SEARCH_REGEX */
236 "word", /* SEARCH_LITERAL_WORD */
237 "caseWord", /* SEARCH_CASE_SENSE_WORD */
238 "regexNoCase", /* SEARCH_REGEX_NOCASE */
239 + "regexSmartCase", /* SEARCH_REGEX_SMARTCASE */
240 NULL
244 ** Window for which a search dialog callback is currently active. That window
245 @@ -368,10 +370,12 @@ static void initToggleButtons(int search
246 XmToggleButtonSetState(*wordToggle, False, False);
247 XtSetSensitive(*wordToggle, False);
249 break;
250 case SEARCH_REGEX_NOCASE:
251 + case SEARCH_REGEX_SMARTCASE:
252 + /* Smart case is no case for default setting */
253 *lastLiteralCase = False;
254 *lastRegexCase = False;
255 XmToggleButtonSetState(regexToggle, True, False);
256 XmToggleButtonSetState(caseToggle, False, False);
257 if (wordToggle) {
258 @@ -2406,12 +2410,20 @@ static int textFieldNonEmpty(Widget w)
259 return(nonEmpty);
262 static void rFindTextValueChangedCB(Widget w, WindowInfo *window, XKeyEvent *event)
264 + char *searchString = XmTextGetString(w);
266 window = WidgetToWindow(w);
267 UpdateReplaceActionButtons(window);
269 + /* Switch to case-sensitive as soon as the user enters an upper-case
270 + letter. We have check the whole string each time to catch clipboard
271 + or selection inserts. */
272 + smartCaseToggle(searchString, window->replaceCaseToggle);
273 + XtFree(searchString);
276 static void rFindArrowKeyCB(Widget w, WindowInfo *window, XKeyEvent *event)
278 KeySym keysym = XLookupKeysym(event, 0);
279 @@ -2501,12 +2513,20 @@ static void fUpdateActionButtons(WindowI
280 XtSetSensitive(window->findBtn, buttonState);
283 static void findTextValueChangedCB(Widget w, WindowInfo *window, XKeyEvent *event)
285 + char *searchString = XmTextGetString(w);
287 window = WidgetToWindow(w);
288 fUpdateActionButtons(window);
290 + /* Switch to case-sensitive as soon as the user enters an upper-case
291 + letter. We have check the whole string each time to catch clipboard
292 + or selection inserts. */
293 + smartCaseToggle(searchString, window->findCaseToggle);
294 + XtFree(searchString);
297 static void findArrowKeyCB(Widget w, WindowInfo *window, XKeyEvent *event)
299 KeySym keysym = XLookupKeysym(event, 0);
300 @@ -2874,14 +2894,17 @@ static void selectedSearchCB(Widget w, X
301 XtFree(value);
303 /* Use the passed method for searching, unless it is regex, since this
304 kind of search is by definition a literal search */
305 searchType = callDataItems->searchType;
306 - if (searchType == SEARCH_REGEX )
307 - searchType = SEARCH_CASE_SENSE;
308 - else if (searchType == SEARCH_REGEX_NOCASE)
309 - searchType = SEARCH_LITERAL;
310 + if (searchType == SEARCH_REGEX || searchType == SEARCH_REGEX_SMARTCASE) {
311 + /* Here smart case must be sensitive, because the user
312 + cannot modify the string to search for. */
313 + searchType = SEARCH_CASE_SENSE;
314 + } else if (searchType == SEARCH_REGEX_NOCASE) {
315 + searchType = SEARCH_LITERAL;
318 /* search for it in the window */
319 SearchAndSelect(window, callDataItems->direction, searchString,
320 searchType, callDataItems->searchWrap);
321 XtFree(callData);
322 @@ -2900,10 +2923,15 @@ void BeginISearch(WindowInfo *window, in
323 case toggles are not reset to their default state when the incremental
324 search bar is redisplayed. I'm not sure whether this is the best
325 choice. If not, an initToggleButtons() call should be inserted
326 here. But in that case, it might be appropriate to have different
327 default search modes for i-search and replace/find. */
329 + /* The 'Case' toggle button must be deactivated for smart cases. */
330 + if (GetPrefSearch() == SEARCH_REGEX_SMARTCASE) {
331 + XmToggleButtonSetState(window->iSearchCaseToggle, False, False);
333 TempShowISearch(window, TRUE);
334 XmProcessTraversal(window->iSearchText, XmTRAVERSE_CURRENT);
338 @@ -3193,10 +3221,16 @@ static void iSearchTextValueChangedCB(Wi
339 window = WidgetToWindow(w);
341 /* Fetch the string, search type and direction from the incremental
342 search bar widgets at the top of the window */
343 searchString = XmTextGetString(window->iSearchText);
345 + /* Switch to case-sensitive as soon as the user enters an upper-case
346 + letter. We have check the whole string each time to catch clipboard
347 + or selection inserts. */
348 + smartCaseToggle(searchString, window->iSearchCaseToggle);
350 if(XmToggleButtonGetState(window->iSearchCaseToggle)) {
351 if(XmToggleButtonGetState(window->iSearchRegexToggle))
352 searchType = SEARCH_REGEX;
353 else
354 searchType = SEARCH_CASE_SENSE;
355 @@ -4872,11 +4906,13 @@ static char *directionArg(int direction)
357 ** Checks whether a search mode in one of the regular expression modes.
359 static int isRegexType(int searchType)
361 - return searchType == SEARCH_REGEX || searchType == SEARCH_REGEX_NOCASE;
362 + return searchType == SEARCH_REGEX
363 + || searchType == SEARCH_REGEX_NOCASE
364 + || searchType == SEARCH_REGEX_SMARTCASE;
368 ** Returns the default flags for regular expression matching, given a
369 ** regular expression search mode.
370 @@ -5015,5 +5051,22 @@ static void iSearchCaseToggleCB(Widget w
371 if(XmToggleButtonGetState(window->iSearchRegexToggle))
372 window->iSearchLastRegexCase = searchCaseSense;
373 else
374 window->iSearchLastLiteralCase = searchCaseSense;
378 +** Will search a string for uppercase characters. If there is one,
379 +** The toggleButton will be set to True.
381 +static void smartCaseToggle(const char *searchString, Widget toggleButton)
383 + if (GetPrefSearch() == SEARCH_REGEX_SMARTCASE) {
384 + int i;
385 + for (i = 0; i < strlen(searchString); i++) {
386 + if (isupper(*(searchString + i))) {
387 + XmToggleButtonSetState(toggleButton, True, False);
388 + break;
393 diff --quilt old/source/search.h new/source/search.h
394 --- old/source/search.h
395 +++ new/source/search.h
396 @@ -88,10 +88,11 @@ Boolean WindowCanBeClosed(WindowInfo *wi
399 enum SearchType {
400 SEARCH_LITERAL, SEARCH_CASE_SENSE, SEARCH_REGEX,
401 SEARCH_LITERAL_WORD, SEARCH_CASE_SENSE_WORD, SEARCH_REGEX_NOCASE,
402 + SEARCH_REGEX_SMARTCASE,
403 N_SEARCH_TYPES /* must be last in enum SearchType */ };
405 #ifdef REPLACE_SCOPE
406 /* Scope on which the replace operations apply */
407 enum ReplaceScope { REPL_SCOPE_WIN, REPL_SCOPE_SEL, REPL_SCOPE_MULTI };
408 diff --quilt old/source/window.c new/source/window.c
409 --- old/source/window.c
410 +++ new/source/window.c
411 @@ -467,11 +467,12 @@ WindowInfo *CreateWindow(const char *nam
413 window->iSearchRegexToggle = XtVaCreateManagedWidget("iSearchREToggle",
414 xmToggleButtonWidgetClass, window->iSearchForm,
415 XmNlabelString, s1=XmStringCreateSimple("RegExp"),
416 XmNset, GetPrefSearch() == SEARCH_REGEX_NOCASE
417 - || GetPrefSearch() == SEARCH_REGEX,
418 + || GetPrefSearch() == SEARCH_REGEX
419 + || GetPrefSearch() == SEARCH_REGEX_SMARTCASE,
420 XmNtopAttachment, XmATTACH_FORM,
421 XmNbottomAttachment, XmATTACH_FORM,
422 XmNtopOffset, 1, /* see openmotif note above */
423 XmNrightAttachment, XmATTACH_WIDGET,
424 XmNrightWidget, window->iSearchCaseToggle,