add newTabTab.patch
[nedit-bw.git] / saveSearchHistory.patch
blob4037104bfe0d040d83f24f1b068044a474a57d84
1 ---
3 source/menu.c | 17 +++
4 source/nedit.c | 5 +
5 source/nedit.h | 1
6 source/preferences.c | 13 ++
7 source/preferences.h | 2
8 source/search.c | 238 ++++++++++++++++++++++++++++++++++++++++++++++++---
9 source/search.h | 2
10 util/utils.c | 8 -
11 util/utils.h | 3
12 9 files changed, 273 insertions(+), 16 deletions(-)
14 diff --quilt old/source/menu.c new/source/menu.c
15 --- old/source/menu.c
16 +++ new/source/menu.c
17 @@ -188,6 +188,7 @@ static void searchDlogsDefCB(Widget w, W
18 static void beepOnSearchWrapDefCB(Widget w, WindowInfo *window, caddr_t callData);
19 static void keepSearchDlogsDefCB(Widget w, WindowInfo *window,
20 caddr_t callData);
21 +static void saveSearchHistoryDefCB(Widget w, WindowInfo *window, caddr_t callData);
22 static void searchWrapsDefCB(Widget w, WindowInfo *window, caddr_t callData);
23 static void showCursorlineCB(Widget widget, WindowInfo *window,
24 caddr_t callData);
25 @@ -941,6 +942,9 @@ Widget CreateMenuBar(Widget parent, Wind
26 window->keepSearchDlogsDefItem = createMenuToggle(subSubPane,
27 "keepDialogsUp", "Keep Dialogs Up", 'K',
28 keepSearchDlogsDefCB, window, GetPrefKeepSearchDlogs(), SHORT);
29 + window->saveSearchHistoryDefItem = createMenuToggle(subSubPane,
30 + "saveSearchHistory", "Save History", 'S',
31 + saveSearchHistoryDefCB, window, GetPrefSaveSearchHistory(), SHORT);
32 subSubSubPane = createMenu(subSubPane, "defaultSearchStyle",
33 "Default Search Style", 'D', NULL, FULL);
34 XtVaSetValues(subSubSubPane, XmNradioBehavior, True, NULL);
35 @@ -2297,6 +2301,19 @@ static void keepSearchDlogsDefCB(Widget
39 +static void saveSearchHistoryDefCB(Widget w, WindowInfo *window, caddr_t callData)
41 + WindowInfo *win;
42 + int state = XmToggleButtonGetState(w);
44 + /* Set the preference and make the other windows' menus agree */
45 + SetPrefSaveSearchHistory(state);
46 + for (win=WindowList; win!=NULL; win=win->next) {
47 + if (IsTopDocument(win))
48 + XmToggleButtonSetState(win->saveSearchHistoryDefItem, state, False);
49 + }
52 static void searchWrapsDefCB(Widget w, WindowInfo *window, caddr_t callData)
54 WindowInfo *win;
55 diff --quilt old/source/nedit.c new/source/nedit.c
56 --- old/source/nedit.c
57 +++ new/source/nedit.c
58 @@ -44,6 +44,7 @@ static const char CVSID[] = "$Id: nedit.
59 #include "tags.h"
60 #include "menu.h"
61 #include "macro.h"
62 +#include "search.h"
63 #include "server.h"
64 #include "interpret.h"
65 #include "parse.h"
66 @@ -559,6 +560,10 @@ int main(int argc, char **argv)
67 command (and eventually other information as well) */
68 ReadNEditDB();
70 + /* Read database of search/replace history. It's called here
71 + for enabling the Find/Replace Again menu items. */
72 + ReadSearchHistory();
74 /* Process -import command line argument before others which might
75 open windows (loading preferences doesn't update menu settings,
76 which would then be out of sync with the real preference settings) */
77 diff --quilt old/source/nedit.h new/source/nedit.h
78 --- old/source/nedit.h
79 +++ new/source/nedit.h
80 @@ -406,6 +406,7 @@ typedef struct _WindowInfo {
81 Widget searchDlogsDefItem;
82 Widget beepOnSearchWrapDefItem;
83 Widget keepSearchDlogsDefItem;
84 + Widget saveSearchHistoryDefItem;
85 Widget searchWrapsDefItem;
86 Widget showCursorlineItem;
87 Widget appendLFItem;
88 diff --quilt old/source/preferences.c new/source/preferences.c
89 --- old/source/preferences.c
90 +++ new/source/preferences.c
91 @@ -276,6 +276,7 @@ static struct prefData {
92 int autoIndent; /* style for auto-indent */
93 int autoSave; /* whether automatic backup feature is on */
94 int saveOldVersion; /* whether to preserve a copy of last version */
95 + int saveSearchHistory; /* whether to store search/replace history */
96 int searchDlogs; /* whether to show explanatory search dialogs */
97 int searchWrapBeep; /* 1=beep when search restarts at begin/end */
98 int keepSearchDlogs; /* whether to retain find and replace dialogs */
99 @@ -985,6 +986,8 @@ static PrefDescripRec PrefDescrip[] = {
100 "0-8,10-31,127:red;9:#dedede;32,160-255:#f0f0f0;128-159:orange",
101 /* gray87 gray94 */
102 &PrefData.backlightCharTypes, NULL, False},
103 + {"saveSearchHistory", "SaveSearchHistory", PREF_BOOLEAN, "False",
104 + &PrefData.saveSearchHistory, NULL, True},
105 {"searchDialogs", "SearchDialogs", PREF_BOOLEAN, "False",
106 &PrefData.searchDlogs, NULL, True},
107 {"beepOnSearchWrap", "BeepOnSearchWrap", PREF_BOOLEAN, "False",
108 @@ -1797,6 +1800,16 @@ int GetPrefSaveOldVersion(void)
109 return PrefData.saveOldVersion;
112 +void SetPrefSaveSearchHistory(int state)
114 + setIntPref(&PrefData.saveSearchHistory, state);
117 +int GetPrefSaveSearchHistory(void)
119 + return PrefData.saveSearchHistory;
122 void SetPrefSearchDlogs(int state)
124 setIntPref(&PrefData.searchDlogs, state);
125 diff --quilt old/source/preferences.h new/source/preferences.h
126 --- old/source/preferences.h
127 +++ new/source/preferences.h
128 @@ -59,6 +59,8 @@ void SetPrefWrap(int state);
129 int GetPrefWrap(int langMode);
130 void SetPrefWrapMargin(int margin);
131 int GetPrefWrapMargin(void);
132 +void SetPrefSaveSearchHistory(int state);
133 +int GetPrefSaveSearchHistory(void);
134 void SetPrefShowWrapMargin(int state);
135 int GetPrefShowWrapMargin(void);
136 void SetPrefSearchDlogs(int state);
137 diff --quilt old/source/search.c new/source/search.c
138 --- old/source/search.c
139 +++ new/source/search.c
140 @@ -49,11 +49,15 @@ static const char CVSID[] = "$Id: search
141 #endif
142 #include "../util/DialogF.h"
143 #include "../util/misc.h"
144 +#include "../util/utils.h"
146 #include <stdlib.h>
147 #include <stdio.h>
148 #include <string.h>
149 #include <ctype.h>
150 +#include <errno.h>
151 +#include <sys/stat.h>
153 #ifdef VMS
154 #include "../util/VMSparam.h"
155 #else
156 @@ -88,6 +92,7 @@ static const char CVSID[] = "$Id: search
157 #include "patternMatch.h"
159 int NHist = 0;
160 +time_t lastSearchdbModTime = 0;
162 typedef struct _SelectionInfo {
163 int done;
164 @@ -218,6 +223,7 @@ static int searchMatchesSelection(Window
165 static Boolean replaceUsingRE(const char* searchStr, const char* replaceStr,
166 const char* sourceStr, int beginPos, char* destStr, int maxDestLen,
167 int prevChar, const char* delimiters, int defaultFlags);
168 +static void enableFindAgainCmds(void);
169 static void saveSearchHistory(const char *searchString,
170 const char *replaceString, int searchType, int isIncremental);
171 static int historyIndex(int nCycles);
172 @@ -503,6 +509,10 @@ void DoFindReplaceDlog(WindowInfo *windo
174 UpdateReplaceActionButtons(window);
176 + /* Refresh search/replace history where two sessions overwrite each
177 + other's changes in the history file. */
178 + ReadSearchHistory();
180 /* Start the search history mechanism at the current history item */
181 window->rHistIndex = 0;
183 @@ -604,6 +614,10 @@ void DoFindDlog(WindowInfo *window, int
184 /* Set the state of the Find button */
185 fUpdateActionButtons(window);
187 + /* Refresh search/replace history where two sessions overwrite each
188 + other's changes in the history file. */
189 + ReadSearchHistory();
191 /* start the search history mechanism at the current history item */
192 window->fHistIndex = 0;
194 @@ -4686,6 +4700,205 @@ static Boolean replaceUsingRE(const char
198 +** Enable commands for repeating the last search/replace
200 +static void enableFindAgainCmds(void)
202 + WindowInfo *w;
204 + for (w=WindowList; w!=NULL; w=w->next) {
205 + if (!IsTopDocument(w))
206 + continue;
207 + XtSetSensitive(w->findAgainItem, True);
208 + XtSetSensitive(w->replaceFindAgainItem, True);
209 + XtSetSensitive(w->replaceAgainItem, True);
214 +** Write dynamic database of search/replace history.
216 +** Format:
217 +** type:search-len:replace-len\nsearch-string\nreplace-string\n
219 +** type ............ search flags (int as string)
220 +** search-len ...... length of search-string (int as string)
221 +** replace-len ..... length of replace-string (int as string)
222 +** search-string ... binary data of search string
223 +** replace-string .. binary data of replace string
226 +void WriteSearchHistory(void)
228 + const char *fullName = GetRCFileName(SEARCH_HISTORY);
229 + const char *searchStr, *replaceStr;
230 + struct stat attribute;
231 + FILE *fp;
232 + int i;
234 + /* If the Save Search-History option is disabled, just return */
235 + if (!GetPrefSaveSearchHistory())
236 + return;
238 + /* open the file */
239 + if ((fp = fopen(fullName, "w")) == NULL) {
240 +#ifdef VMS
241 + /* When the version number, ";1" is specified as part of the file
242 + name, fopen(fullName, "w"), will only open for writing if the
243 + file does not exist. Using, fopen(fullName, "r+"), opens an
244 + existing file for "update" - read/write pointer is placed at the
245 + beginning of file.
246 + By calling ftruncate(), we discard the old contents and avoid
247 + trailing garbage in the file if the new contents is shorter. */
248 + if ((fp = fopen(fullName, "r+")) == NULL)
249 + return;
250 + if (ftruncate(fileno(fp), 0) != 0) {
251 + fclose(fp);
252 + return;
254 +#else
255 + return;
256 +#endif
259 + /* Write list of search-/replace-strings and types to the file */
260 + for (i = NHist; i >= 1; i--) {
261 + searchStr = SearchHistory[historyIndex(i)];
262 + replaceStr = ReplaceHistory[historyIndex(i)];
263 + fprintf(fp, "%d:%u:%u\n%s\n%s\n",
264 + SearchTypeHistory[historyIndex(i)],
265 + (unsigned)strlen(searchStr), (unsigned)strlen(replaceStr),
266 + searchStr, replaceStr);
268 + fclose(fp);
270 + /* Stat history file to store our own write time. */
271 + if (0 == stat(fullName, &attribute)) {
272 + /* Memorize modtime to compare to next time. */
273 + lastSearchdbModTime = attribute.st_mtime;
278 +** Read database of search/replace history.
280 +** For more information see WriteSearchHistory().
283 +void ReadSearchHistory(void)
285 + const char *fullName = GetRCFileName(SEARCH_HISTORY);
286 + struct stat attribute;
287 + char line[16];
288 + size_t lineLen;
289 + int type;
290 + unsigned srchLen, replLen;
291 + FILE *fp;
293 + /* If the save search history option is disabled, just return */
294 + if (!GetPrefSaveSearchHistory())
295 + return;
297 + /* Stat history file to see whether someone touched it after this
298 + session last changed it. */
299 + if (0 == stat(fullName, &attribute)) {
300 + if (lastSearchdbModTime >= attribute.st_mtime) {
301 + /* Do nothing, history file is unchanged. */
302 + return;
303 + } else {
304 + /* Memorize modtime to compare to next time. */
305 + lastSearchdbModTime = attribute.st_mtime;
307 + } else {
308 + /* stat() failed, probably for non-exiting history database. */
309 + if (ENOENT != errno)
310 + fprintf(stderr, "NEdit: Error reading file %s (%s)\n",
311 + fullName, strerror(errno));
312 + return;
315 + /* open the file */
316 + if ((fp = fopen(fullName, "r")) == NULL)
317 + return;
319 + /* Clear previous list */
320 + while (0 != NHist) {
321 + XtFree(SearchHistory[historyIndex(NHist)]);
322 + XtFree(ReplaceHistory[historyIndex(NHist)]);
323 + NHist--;
325 + HistStart = 0;
327 + /* read lines of the file */
328 + while (fgets(line, sizeof(line), fp) != NULL) {
329 + lineLen = strlen(line);
330 + if (lineLen == 0 || line[0] == '\n' || line[0] == '#') {
331 + /* blank line or comment */
332 + continue;
334 + if (line[lineLen - 1] != '\n') {
335 + /* no newline, probably truncated */
336 + fprintf(stderr, "NEdit: Line too long in file %s\n", fullName);
337 + break;
339 + line[--lineLen] = '\0';
341 + if (sscanf(line, "%d:%u:%u", &type, &srchLen, &replLen) != 3) {
342 + fprintf(stderr, "NEdit: Invalid line in file %s\n", fullName);
343 + break;
346 + SearchTypeHistory[HistStart]=type;
347 + if (type < 0 || type >= N_SEARCH_TYPES
348 + || srchLen > SEARCHMAX || replLen > SEARCHMAX) {
349 + fprintf(stderr, "NEdit: Invalid values in file %s\n", fullName);
350 + break;
353 + /* If there are more than MAX_SEARCH_HISTORY strings saved, recycle
354 + some space, free the entry that's about to be overwritten */
355 + if (NHist == MAX_SEARCH_HISTORY) {
356 + XtFree(SearchHistory[HistStart]);
357 + XtFree(ReplaceHistory[HistStart]);
358 + } else
359 + NHist++;
361 + /* read and store search-string */
362 + SearchHistory[HistStart] = XtMalloc(srchLen+1);
363 + if (fread(SearchHistory[HistStart], 1, srchLen + 1, fp) != srchLen + 1
364 + || SearchHistory[HistStart][srchLen] != '\n') {
365 + fprintf(stderr, "NEdit: Error reading file %s (%s)\n",
366 + fullName, strerror(errno));
367 + XtFree(SearchHistory[HistStart]);
368 + NHist--;
369 + break;
371 + SearchHistory[HistStart][srchLen]='\0';
373 + /* read and store replace-string */
374 + ReplaceHistory[HistStart] = XtMalloc(replLen+1);
375 + if (fread(ReplaceHistory[HistStart], 1, replLen + 1, fp) != replLen + 1
376 + || ReplaceHistory[HistStart][replLen] != '\n') {
377 + fprintf(stderr, "NEdit: Error reading file %s (%s)\n",
378 + fullName, strerror(errno));
379 + XtFree(SearchHistory[HistStart]);
380 + XtFree(ReplaceHistory[HistStart]);
381 + NHist--;
382 + break;
384 + ReplaceHistory[HistStart][replLen]='\0';
386 + if (++HistStart >= MAX_SEARCH_HISTORY)
387 + HistStart = 0;
389 + fclose(fp);
391 + /* If there are history items, enable Find/Replace Again commands */
392 + if (NHist)
393 + enableFindAgainCmds();
397 ** Store the search and replace strings, and search type for later recall.
398 ** If replaceString is NULL, duplicate the last replaceString used.
399 ** Contiguous incremental searches share the same history entry (each new
400 @@ -4698,7 +4911,6 @@ static void saveSearchHistory(const char
402 char *sStr, *rStr;
403 static int currentItemIsIncremental = FALSE;
404 - WindowInfo *w;
406 /* Cancel accumulation of contiguous incremental searches (even if the
407 information is not worthy of saving) if search is not incremental */
408 @@ -4727,19 +4939,20 @@ static void saveSearchHistory(const char
409 XtFree(SearchHistory[historyIndex(1)]);
410 SearchHistory[historyIndex(1)] = XtNewString(searchString);
411 SearchTypeHistory[historyIndex(1)] = searchType;
413 + /* Save history to file */
414 + WriteSearchHistory();
415 return;
417 currentItemIsIncremental = isIncremental;
419 - if (NHist==0) {
420 - for (w=WindowList; w!=NULL; w=w->next) {
421 - if (!IsTopDocument(w))
422 - continue;
423 - XtSetSensitive(w->findAgainItem, True);
424 - XtSetSensitive(w->replaceFindAgainItem, True);
425 - XtSetSensitive(w->replaceAgainItem, True);
429 + /* Enable Find/Replace Again commands on first call */
430 + if (NHist == 0)
431 + enableFindAgainCmds();
433 + /* Refresh search/replace history where two sessions overwrite each
434 + other's changes in the history file. */
435 + ReadSearchHistory();
437 /* If there are more than MAX_SEARCH_HISTORY strings saved, recycle
438 some space, free the entry that's about to be overwritten */
439 @@ -4761,6 +4974,9 @@ static void saveSearchHistory(const char
440 HistStart++;
441 if (HistStart >= MAX_SEARCH_HISTORY)
442 HistStart = 0;
444 + /* Save history to file */
445 + WriteSearchHistory();
449 diff --quilt old/source/search.h new/source/search.h
450 --- old/source/search.h
451 +++ new/source/search.h
452 @@ -78,6 +78,8 @@ void SelectToMatchingCharacter(WindowInf
453 void GotoMatchingCharacter(WindowInfo *window);
454 void RemoveFromMultiReplaceDialog(WindowInfo *window);
455 Boolean WindowCanBeClosed(WindowInfo *window);
456 +void WriteSearchHistory(void);
457 +void ReadSearchHistory(void);
460 ** Schwarzenberg: added SEARCH_LITERAL_WORD .. SEARCH_REGEX_NOCASE
461 diff --quilt old/util/utils.c new/util/utils.c
462 --- old/util/utils.c
463 +++ new/util/utils.c
464 @@ -53,11 +53,11 @@ static const char CVSID[] = "$Id: utils.
466 #define DEFAULT_NEDIT_HOME ".nedit"
467 #ifdef VMS
468 - static char* hiddenFileNames[N_FILE_TYPES] = {".nedit", ".neditmacro", ".neditdb;1", ".neditdict"};
469 - static char* plainFileNames[N_FILE_TYPES] = {"nedit.rc", "autoload.nm", "nedit.history;1", "nedit.dict"};
470 + static char* hiddenFileNames[N_FILE_TYPES] = {".nedit", ".neditmacro", ".neditdb;1", ".neditdict", ".neditsearch;1"};
471 + static char* plainFileNames[N_FILE_TYPES] = {"nedit.rc", "autoload.nm", "nedit.history;1", "nedit.dict", "search.history;1"};
472 #else
473 - static char* hiddenFileNames[N_FILE_TYPES] = {".nedit", ".neditmacro", ".neditdb", ".neditdict"};
474 - static char* plainFileNames[N_FILE_TYPES] = {"nedit.rc", "autoload.nm", "nedit.history", "nedit.dict"};
475 + static char* hiddenFileNames[N_FILE_TYPES] = {".nedit", ".neditmacro", ".neditdb", ".neditdict", ".neditsearch"};
476 + static char* plainFileNames[N_FILE_TYPES] = {"nedit.rc", "autoload.nm", "nedit.history", "nedit.dict", "search.history"};
477 #endif
479 static void buildFilePath(char* fullPath, const char* dir, const char* file);
480 diff --quilt old/util/utils.h new/util/utils.h
481 --- old/util/utils.h
482 +++ new/util/utils.h
483 @@ -74,7 +74,8 @@ void Push(Stack* stack, const void* valu
484 void* Pop(Stack* stack);
486 /* N_FILE_TYPES must be the last entry!! This saves us from counting. */
487 -enum {NEDIT_RC, AUTOLOAD_NM, NEDIT_HISTORY, NEDIT_DICT, N_FILE_TYPES};
488 +enum {NEDIT_RC, AUTOLOAD_NM, NEDIT_HISTORY, NEDIT_DICT, SEARCH_HISTORY,
489 + N_FILE_TYPES};
491 /* If anyone knows where to get this from system include files (in a machine
492 independent way), please change this (L_cuserid is apparently not ANSI) */