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;
42 FileSystemNode messageNode;
50 virtual bool Window::NotifyUpdateSearchLocation(FileSystemSearch search, const char * location);
51 virtual bool Window::NotifySearchSortResults(FileSystemSearch search);
52 virtual bool Window::NotifySearchSortBrowser(FileSystemSearch search);
53 virtual bool Window::NotifySearchTerminated(FileSystemSearch search);
58 //CreateMessageNode();
59 //messageNode.label = "No results yet!";
64 bool SearchFileContent(const String path)
67 File file = FileOpen(path, read);
72 // char * find = null;
73 // for( ; !find && file.GetLine(line, 65536) ; )
74 // find = SearchString(line, 0, contentSearch, optionContentMatchCase, optionContentMatchWord);
75 // // find = strstr(line, contentSearch);
78 uint readCount = 16383;
81 int seekBack = 0 - strlen(contentSearch) - 2;
85 while(readCount == 16383)
87 uint start = 0, len = 0;
88 readCount = file.Read(buffer, 1, 16383);
89 buffer[readCount] = '\0';
90 for( ; start < readCount; start += len ? len : 1)
92 if( (len = strlen(&buffer[start])) )
94 char * newLine = buffer;
96 find = SearchString(buffer, start, contentSearch, optionContentMatchCase, optionContentMatchWord);
98 // todo add a maximum line length possibility as param
100 bstart < readCount && newLine && (!find || newLine < find);
101 bstart += (newLine - &buffer[bstart]) / sizeof(char))
103 newLine = strstr(&buffer[bstart], "\n");
105 if(bstart + (newLine - &buffer[bstart]) / sizeof(char) < readCount && newLine && (!find || newLine < find))
111 len = (find - &buffer[start]) / sizeof(char) + strlen(contentSearch);
113 if(!lines.first || ((NumberLink)lines.last).num != line)
114 lines.Add(NumberLink { num = line });
119 file.Seek(seekBack, current);
124 for( ; !find && readCount == 16383; )
126 uint start = 0, len = 0;
127 readCount = file.Read(buffer, 1, 16383);
128 buffer[readCount] = '\0';
129 for( ; !find && start < readCount; start += len + 1)
130 if( (len = strlen(&buffer[start])) )
131 find = SearchString(buffer, start, contentSearch, optionContentMatchCase, optionContentMatchWord);
132 file.Seek(seekBack, current);
134 match = find != null;
141 // I wonder if this is optimized at the c level to be compiled inline
142 // and to use in-place in-stack memory for both the return value and the parameters
143 // if not, c should be more optimized...
144 // would the const have any impact on optimization?
148 int frame, stackTop = 0, treeTop = 0;
149 double lastTime = GetTime();
150 SearchStackFrame stack[1024];
151 //to be used for content replace... EditBox edit { multiLine = true, textHorzScroll = true, textVertScroll = true, maxLineSize = 65536 };
154 // This won't give drive attribs for c: or c:\ and other drives as well
155 // \\Nateus\data\ is not remote, etc...
163 hasNameSearch = (strlen(nameSearch) != 0);
164 hasSizeSearch = false; // this is temporary
165 hasContentSearch = (strlen(contentSearch) != 0);
170 //SearchDir(location);
172 FileGetStats(location, stats);
174 strcpy(stack[0].path, location);
175 stack[0].listing = FileListing { stack[0].path }; // there should be a sorted = true/false
178 // Binary Search sorting...
180 stack[0].branched = false;
185 //stack[0].browse = searchPanel.AddBrowserRow();
186 //DeleteMessageNode();
187 //node = MakeFileSystemNode(attribs, stack[0].path, true,
188 // stack[0].path, fsb.bits.previewPictures, fsb.displaySystem);
189 //stack[0].browse.SetData(browserNameField, node);
190 //stack[0].browse.SetData(typeField, null);
191 //stack[0].browse.SetData(sizeField, null);
193 //DeleteMessageNode();
195 stack[0].browse = MakeFileSystemNode(stats, stack[0].path, stack[0].path, false,
196 tree.bits.previewPictures, false, tree.displaySystem);
197 tree.AddTreeNode(stack[0].browse, false, true, true, null); // TEMPORARY // searchPanel.AddBrowse(stack[0].browse, null);
202 for(frame = 0; frame >= 0 && !terminate; )
206 double thisTime = GetTime();
207 if(thisTime - lastTime > 0.25)
209 NotifyUpdateSearchLocation(owner, this, stack[frame].listing.path); // TEMPORARY // searchPanel.SearchUpdateLabel(stack[frame].listing.path);
211 // CreateMessageNode();
212 //delete messageNode.label;
213 //messageNode.label = PrintString("Searching '", stack[frame].listing.path, "'...");
214 //messageNode.EnsureVisible(false);
215 //fsb.Select(messageNode);
217 //guiApp.UpdateDisplay();
222 if(stack[frame].listing.Find())
226 //match = (strcmp(stack[frame].listing.name, nameSearch) == 0);
227 //match = (stack[frame].listing.name[0] == nameSearch[0]);
228 //match = (bool)strstr(stack[frame].listing.name, nameSearch);
231 match = SearchString(stack[frame].listing.name, 0, nameSearch, optionNameMatchCase, optionNameMatchWord) != null;
235 if(match && hasContentSearch && !stack[frame].listing.stats.attribs.isDirectory)
236 if(!SearchFileContent(stack[frame].listing.path))
244 for(frame = treeTop; frame <= stackTop; frame++)
246 if(!stack[frame].branched)
252 stack[frame].result = MakeFileSystemNode(stack[frame - 1].listing.stats,
253 stack[frame - 1].listing.name, stack[frame - 1].path, true,
254 fsb.bits.previewPictures, false, fsb.displaySystem);
255 fsb.AddTreeNode(stack[frame].result, true, true, false, stack[frame - 1].result); // TEMPORARY // searchPanel.AddResult(stack[frame].result, stack[frame - 1].result);
256 stack[frame].result.row.collapsed = false;
261 stack[0].result = MakeFileSystemNode(stats, stack[0].path, stack[0].path, true,
262 fsb.bits.previewPictures, false, fsb.displaySystem);
263 fsb.AddTreeNode(stack[0].result, true, true, false, null); // TEMPORARY // searchPanel.AddResult(stack[0].result, null);
264 stack[0].result.row.collapsed = false;
266 stack[frame].branched = true;
274 if(optionSubdirs && stack[frame].listing.stats.attribs.isDirectory)
278 double thisTime = GetTime();
279 if(thisTime - lastTime > 0.25)
281 NotifyUpdateSearchLocation(owner, this, stack[stackTop].listing.path); // TEMPORARY // searchPanel.SearchUpdateLabel(stack[stackTop].listing.path);
284 //delete messageNode.label;
285 messageNode.label = PrintString("Searching '", stack[stackTop].listing.path, "'...");
286 messageNode.EnsureVisible(false);
288 guiApp.UpdateDisplay();
292 //searchPanel.SearchUpdateLabel(stack[stackTop].listing.path);*/
294 /* /-*if(optionBrowser)
297 stack[frame].browse = MakeFileSystemNode(stack[stackTop].listing.stats,
298 stack[stackTop].listing.name, stack[stackTop].path, true,
299 fsb.bits.previewPictures, fsb.displaySystem);
300 fsb.AddTreeNode(stack[frame].browse, true, true, false, stack[stackTop].browse); // TEMPORARY // searchPanel.AddBrowse(stack[frame].browse, stack[stackTop].browse);
303 stack[frame].browse.row.collapsed = true;
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?
310 strcpy(stack[frame].path, stack[stackTop].listing.path);
311 stack[frame].listing = FileListing { stack[frame].path };
313 stack[frame].branched = false;
318 stack[frame].result = MakeFileSystemNode(stack[stackTop].listing.stats,
319 stack[stackTop].listing.name, stack[stackTop].path, true,
320 fsb.bits.previewPictures, false, fsb.displaySystem);
323 fsb.AddTreeNode(stack[frame].result, true, true, false, stack[stackTop].result); // TEMPORARY // searchPanel.AddResult(stack[frame].result, stack[stackTop].result);
324 stack[frame].result.row.collapsed = false;
325 //searchPanel.SortResults(); // this can be very bad for performance in some situations
326 // there should be a way to sort the nodes as they are added
327 // BinarySearch sorting implementation in listBox's Sort?
328 stack[frame].branched = true;
332 fsb.AddNode(stack[frame].result); //searchPanel.SearchAddResultsItem(stack[stackTop].listing.name, stack[stackTop].listing.path);
345 item = MakeFileSystemNode(stack[frame].listing.stats,
346 stack[frame].listing.name, stack[frame].path, true,
347 fsb.bits.previewPictures, fsb.displaySystem);
348 fsb.AddTreeNode(item, true, true, false, stack[frame].browse); // TEMPORARY // searchPanel.AddBrowse(item, stack[frame].browse);
350 //searchPanel.SortBrowser(); // this can be very bad for performance in some situations
351 // there should be a way to sort the nodes as they are added
352 // BinarySearch sorting implementation in listBox's Sort?
358 item = MakeFileSystemNode(stack[frame].listing.stats,
359 stack[frame].listing.name, stack[frame].path, true,
360 fsb.bits.previewPictures, false, fsb.displaySystem);
363 fsb.AddTreeNode(item, true, true, false, stack[frame].result); // TEMPORARY // searchPanel.AddResult(item, stack[frame].result);
364 item.row.collapsed = false;
365 //searchPanel.SortResults(); // this can be very bad for performance in some situations
366 // there should be a way to sort the nodes as they are added
367 // BinarySearch sorting implementation in listBox's Sort?
369 if(listLines && lines.first)
371 NumberLink lin = lines.first;
372 char temp[MAX_F_STRING];
373 sprintf(temp, "lines %d", lin.num);
374 for(lin = lin.next; lin && strlen(temp) < MAX_F_STRING; lin = lin.next)
375 strcatf(temp, ", %d", lin.num);
376 node = FileSystemNode { name = temp/*CopyString(temp)*/, type = lineNumbers };
377 fsb.AddTreeNode(node, true, true, false, item); // TEMPORARY // searchPanel.AddResult(node, item);
378 //row.AddRow().SetData(resultsNameField, node);
383 fsb.AddNode(item); //searchPanel.SearchAddResultsItem(stack[frame].listing.name, stack[frame].listing.path);
390 if(optionTree && stack[frame].branched && frame == treeTop)
392 stack[frame].branched = false;
400 for( ; frame >= 0 ; frame--)
401 stack[frame].listing.Stop();
405 NotifySearchSortResults(owner, this); // TEMPORARY // searchPanel.SortResults();
407 NotifySearchSortBrowser(owner, this); // TEMPORARY // searchPanel.SortBrowser();
413 NotifySearchTerminated(owner, this); // TEMPORARY // searchPanel.SearchTerminate();
414 //delete messageNode.label;
415 //messageNode.label = PrintString("Searching '", stack[stackTop].listing.path, "'...");
416 //delete the messageNode;
423 void CreateMessageNode()
425 //messageNode = MakeFileSystemNode({ }, " ", " ", false, false, fsb.displaySystem);
426 //messageNode.type = normalFile;
427 //fsb.AddNode(messageNode);
429 void DeleteMessageNode()
432 // fsb.DeleteNode(messageNode);
433 //messageNode = null;