4 class NumberLink : struct
10 struct SearchStackFrame
13 char path[MAX_LOCATION];
19 FileSystemNode result;
20 FileSystemNode browse;
23 public class FileSystemSearch : Thread
26 bool active, terminate, hasNameSearch, hasSizeSearch, hasContentSearch, listLines;
27 int count, matchCount;
28 char location[MAX_LOCATION], nameSearch[1024], contentSearch[1024];
29 bool optionTree, optionBrowser, optionSubdirs;
30 bool optionNameMatchCase, optionNameMatchWord;
31 bool optionContentMatchCase, optionContentMatchWord;
33 //DataField resultsNameField;
34 //DataField browserNameField;
36 // TEMPORARY // ExplorerSearch searchPanel;
47 virtual bool Window::NotifyUpdateSearchLocation(FileSystemSearch search, char * location);
48 virtual bool Window::NotifySearchSortResults(FileSystemSearch search);
49 virtual bool Window::NotifySearchSortBrowser(FileSystemSearch search);
50 virtual bool Window::NotifySearchTerminated(FileSystemSearch search);
52 bool SearchFileContent(String path)
55 File file = FileOpen(path, read);
60 // char * find = null;
61 // for( ; !find && file.GetLine(line, 65536) ; )
62 // find = SearchString(line, 0, contentSearch, optionContentMatchCase, optionContentMatchWord);
63 // // find = strstr(line, contentSearch);
66 uint readCount = 16383;
69 int seekBack = 0 - strlen(contentSearch) - 2;
73 while(readCount == 16383)
75 uint start = 0, len = 0;
76 readCount = file.Read(buffer, 1, 16383);
77 buffer[readCount] = '\0';
78 for( ; start < readCount; start += len ? len : 1)
80 if( (len = strlen(&buffer[start])) )
82 char * newLine = buffer;
84 find = SearchString(buffer, start, contentSearch, optionContentMatchCase, optionContentMatchWord);
86 // todo add a maximum line length possibility as param
88 bstart < readCount && newLine && (!find || newLine < find);
89 bstart += (newLine - &buffer[bstart]) / sizeof(char))
91 newLine = strstr(&buffer[bstart], "\n");
93 if(bstart + (newLine - &buffer[bstart]) / sizeof(char) < readCount && newLine && (!find || newLine < find))
99 len = (find - &buffer[start]) / sizeof(char) + strlen(contentSearch);
101 if(!lines.first || ((NumberLink)lines.last).num != line)
102 lines.Add(NumberLink { num = line });
107 file.Seek(seekBack, current);
112 for( ; !find && readCount == 16383; )
114 uint start = 0, len = 0;
115 readCount = file.Read(buffer, 1, 16383);
116 buffer[readCount] = '\0';
117 for( ; !find && start < readCount; start += len + 1)
118 if( (len = strlen(&buffer[start])) )
119 find = SearchString(buffer, start, contentSearch, optionContentMatchCase, optionContentMatchWord);
120 file.Seek(seekBack, current);
129 // I wonder if this is optimized at the c level to be compiled inline
130 // and to use in-place in-stack memory for both the return value and the parameters
131 // if not, c should be more optimized...
132 // would the const have any impact on optimization?
136 int frame, stackTop = 0, treeTop = 0;
137 double lastTime = GetTime();
138 SearchStackFrame stack[1024];
139 //to be used for content replace... EditBox edit { multiLine = true, textHorzScroll = true, textVertScroll = true, maxLineSize = 65536 };
142 // This won't give drive attribs for c: or c:\ and other drives as well
143 // \\Nateus\data\ is not remote, etc...
151 hasNameSearch = (strlen(nameSearch) != 0);
152 hasSizeSearch = false; // this is temporary
153 hasContentSearch = (strlen(contentSearch) != 0);
158 //SearchDir(location);
160 FileGetStats(location, stats);
162 strcpy(stack[0].path, location);
163 stack[0].listing = FileListing { stack[0].path }; // there should be a sorted = true/false
166 // Binary Search sorting...
168 stack[0].branched = false;
173 //stack[0].browse = searchPanel.AddBrowserRow();
174 //node = MakeFileSystemNode(attribs, stack[0].path,
175 // stack[0].path, fsb.bits.previewPictures, fsb.displaySystem);
176 //stack[0].browse.SetData(browserNameField, node);
177 //stack[0].browse.SetData(typeField, null);
178 //stack[0].browse.SetData(sizeField, null);
180 stack[0].browse = MakeFileSystemNode(stats, stack[0].path, stack[0].path,
181 fsb.bits.previewPictures, fsb.displaySystem);
182 fsb.AddTreeNode(stack[0].browse, true, false, null); // TEMPORARY // searchPanel.AddBrowse(stack[0].browse, null);
187 for(frame = 0; frame >= 0 && !terminate; )
189 if(stack[frame].listing.Find())
193 //match = (strcmp(stack[frame].listing.name, nameSearch) == 0);
194 //match = (stack[frame].listing.name[0] == nameSearch[0]);
195 //match = (bool)strstr(stack[frame].listing.name, nameSearch);
198 match = (bool)SearchString(stack[frame].listing.name, 0, nameSearch, optionNameMatchCase, optionNameMatchWord);
202 if(match && hasContentSearch && !stack[frame].listing.stats.attribs.isDirectory)
203 if(!SearchFileContent(stack[frame].listing.path))
211 for(frame = treeTop; frame <= stackTop; frame++)
213 if(!stack[frame].branched)
218 stack[frame].result = MakeFileSystemNode(stack[frame - 1].listing.stats,
219 stack[frame - 1].listing.name, stack[frame - 1].path,
220 fsb.bits.previewPictures, fsb.displaySystem);
221 fsb.AddTreeNode(stack[frame].result, true, false, stack[frame - 1].result); // TEMPORARY // searchPanel.AddResult(stack[frame].result, stack[frame - 1].result);
222 stack[frame].result.row.collapsed = false;
226 stack[0].result = MakeFileSystemNode(stats, stack[0].path, stack[0].path,
227 fsb.bits.previewPictures, fsb.displaySystem);
228 fsb.AddTreeNode(stack[0].result, true, false, null); // TEMPORARY // searchPanel.AddResult(stack[0].result, null);
229 stack[0].result.row.collapsed = false;
231 stack[frame].branched = true;
239 if(optionSubdirs && stack[frame].listing.stats.attribs.isDirectory)
243 double thisTime = GetTime();
244 if(thisTime - lastTime > 0.25)
246 NotifyUpdateSearchLocation(owner, this, stack[stackTop].listing.path); // TEMPORARY // searchPanel.SearchUpdateLabel(stack[stackTop].listing.path);
250 //searchPanel.SearchUpdateLabel(stack[stackTop].listing.path);
254 stack[frame].browse = MakeFileSystemNode(stack[stackTop].listing.stats,
255 stack[stackTop].listing.name, stack[stackTop].path,
256 fsb.bits.previewPictures, fsb.displaySystem);
257 fsb.AddTreeNode(stack[frame].browse, true, false, stack[stackTop].browse); // TEMPORARY // searchPanel.AddBrowse(stack[frame].browse, stack[stackTop].browse);
260 stack[frame].browse.row.collapsed = true;
262 //searchPanel.SortBrowser(); // this can be very bad for performance in some situations
263 // there should be a way to sort the nodes as they are added
264 // BinarySearch sorting implementation in listBox's Sort?
267 strcpy(stack[frame].path, stack[stackTop].listing.path);
268 stack[frame].listing = FileListing { stack[frame].path };
270 stack[frame].branched = false;
274 stack[frame].result = MakeFileSystemNode(stack[stackTop].listing.stats,
275 stack[stackTop].listing.name, stack[stackTop].path,
276 fsb.bits.previewPictures, fsb.displaySystem);
279 fsb.AddTreeNode(stack[frame].result, true, false, stack[stackTop].result); // TEMPORARY // searchPanel.AddResult(stack[frame].result, stack[stackTop].result);
280 stack[frame].result.row.collapsed = false;
281 //searchPanel.SortResults(); // this can be very bad for performance in some situations
282 // there should be a way to sort the nodes as they are added
283 // BinarySearch sorting implementation in listBox's Sort?
284 stack[frame].branched = true;
288 fsb.AddNode(stack[frame].result); //searchPanel.SearchAddResultsItem(stack[stackTop].listing.name, stack[stackTop].listing.path);
300 item = MakeFileSystemNode(stack[frame].listing.stats,
301 stack[frame].listing.name, stack[frame].path,
302 fsb.bits.previewPictures, fsb.displaySystem);
303 fsb.AddTreeNode(item, true, false, stack[frame].browse); // TEMPORARY // searchPanel.AddBrowse(item, stack[frame].browse);
305 //searchPanel.SortBrowser(); // this can be very bad for performance in some situations
306 // there should be a way to sort the nodes as they are added
307 // BinarySearch sorting implementation in listBox's Sort?
312 item = MakeFileSystemNode(stack[frame].listing.stats,
313 stack[frame].listing.name, stack[frame].path,
314 fsb.bits.previewPictures, fsb.displaySystem);
317 fsb.AddTreeNode(item, true, false, stack[frame].result); // TEMPORARY // searchPanel.AddResult(item, stack[frame].result);
318 item.row.collapsed = false;
319 //searchPanel.SortResults(); // this can be very bad for performance in some situations
320 // there should be a way to sort the nodes as they are added
321 // BinarySearch sorting implementation in listBox's Sort?
323 if(listLines && lines.first)
325 NumberLink lin = lines.first;
326 char temp[MAX_F_STRING];
327 sprintf(temp, "lines %d", lin.num);
328 for(lin = lin.next; lin && strlen(temp) < MAX_F_STRING; lin = lin.next)
329 strcatf(temp, ", %d", lin.num);
330 node = FileSystemNode { name = CopyString(temp), type = lineNumbers };
331 fsb.AddTreeNode(node, true, false, item); // TEMPORARY // searchPanel.AddResult(node, item);
332 //row.AddRow().SetData(resultsNameField, node);
337 fsb.AddNode(item); //searchPanel.SearchAddResultsItem(stack[frame].listing.name, stack[frame].listing.path);
344 if(optionTree && stack[frame].branched && frame == treeTop)
346 stack[frame].branched = false;
354 for( ; frame >= 0 ; frame--)
355 stack[frame].listing.Stop();
359 NotifySearchSortResults(owner, this); // TEMPORARY // searchPanel.SortResults();
361 NotifySearchSortBrowser(owner, this); // TEMPORARY // searchPanel.SortBrowser();
367 NotifySearchTerminated(owner, this); // TEMPORARY // searchPanel.SearchTerminate();