so I slapped this together...
I compiled it, then created a tool "Search Project File"
working dir: %PROJECT
Arguments: "%HOME"
and gave it "ALT-F" short cut.. Now when I need to search all project files, it's relatively easily...
Caveat: Purebasic doesn't write the project file (pbp) to disk until you either close the project or or exit the IDE; so if you add new new files to a project, the project will need to be closed/re-opened before this can search all the files.
Code: Select all
;v3a - Adds menu/options to close search on selecton (dbl click)
; - Add right-click menu on results to open folder of selection.
;v3 - adds search history (note, if using ADS, history will be lost on rebuild)
; - adds seaching all code/c-asm/ignore c-asm
; - fixed regex error
; - added "ignore comments" (basic, has issues)
; - fixed several bugs.
; - added statusbar to results screen
; - save search options & history (per project)
;v2a - Adds an icon to windows
;v2 - Simplified: Reduce code, Remove map & structures
; - fixed stupid programmer code. (aka: very dumb bugs)
;v1b - Windows Only: re-activate window If re-run
;v1a - suggestions by @highend
; - light changs here&there
;v1 - initial
EnableExplicit
; note, 'ignore comments' and those dealing with c/asm (; and !)
; are only considered if they are at the start of the line.
; I'll work on this.
;- ---[ PB Form Generated ]---
;{ Search Window
Enumeration FormWindow
#winSearch
EndEnumeration
Enumeration FormGadget
#txtSearchFor
#cboSearchFor
#chkExact
#chkCaseSpecific
#btnSearch
#chkIgnoreComments
#optEverywhere
#optcASM
#optPBOnly
#chkIgnoreQuotes
EndEnumeration
Procedure OpenwinSearch(x = 0, y = 0, width = 380, height = 100)
OpenWindow(#winSearch, x, y, width, height, "Project Search", #PB_Window_SystemMenu | #PB_Window_ScreenCentered|#PB_Window_Invisible)
HideWindow(#winSearch, 1)
TextGadget(#txtSearchFor, 10, 10, 70, 15, "Search &For")
ComboBoxGadget(#cboSearchFor, 80, 5, 170, 25, #PB_ComboBox_Editable)
CheckBoxGadget(#chkExact, 130, 70, 92, 15, "&Exact Match")
GadgetToolTip(#chkExact, "Match partial words or not")
CheckBoxGadget(#chkCaseSpecific, 130, 50, 96, 15, "&Case Specific")
ButtonGadget(#btnSearch, 260, 5, 100, 25, "&Search")
DisableGadget(#btnSearch, 1)
CheckBoxGadget(#chkIgnoreComments, 230, 50, 127, 15, "&Ignore Comments")
OptionGadget(#optEverywhere, 10, 40, 110, 15, "&All")
SetGadgetState(#optEverywhere, 1)
OptionGadget(#optcASM, 10, 60, 110, 15, "c/AS&M only")
OptionGadget(#optPBOnly, 10, 80, 110, 15, "I&gnore c/ASM")
CheckBoxGadget(#chkIgnoreQuotes, 230, 70, 127, 15, "Ignore &Quotes")
GadgetToolTip(#chkIgnoreQuotes, "Will not match text inside quotes")
EndProcedure
;}
;{ Search results window
;
; This code is automatically generated by the FormDesigner.
; Manual modification is possible to adjust existing commands, but anything else will be dropped when the code is compiled.
; Event procedures needs to be put in another source file.
;
Enumeration FormWindow
#winResults
EndEnumeration
Enumeration FormGadget
#lstResults
#chkCloseOnSelect
EndEnumeration
Procedure OpenwinResults(x = 0, y = 0, width = 1050, height = 350)
OpenWindow(#winResults, x, y, width, height, "Project Search Results", #PB_Window_SystemMenu|#PB_Window_Invisible, WindowID(#winSearch))
HideWindow(#winResults, 1)
CreateStatusBar(0, WindowID(#winResults))
AddStatusBarField(60)
StatusBarText(0, 0, "Total Files", #PB_StatusBar_Raised)
AddStatusBarField(50)
StatusBarText(0, 1, "Label", #PB_StatusBar_Center | #PB_StatusBar_Raised)
AddStatusBarField(80)
StatusBarText(0, 2, "Files Matched", #PB_StatusBar_Raised)
AddStatusBarField(50)
StatusBarText(0, 3, "Label", #PB_StatusBar_Center | #PB_StatusBar_Raised)
AddStatusBarField(80)
StatusBarText(0, 4, "Total Matches", #PB_StatusBar_Raised)
AddStatusBarField(50)
StatusBarText(0, 5, "Label", #PB_StatusBar_Center | #PB_StatusBar_Raised)
ListIconGadget(#lstResults, 5, 4, 1035, 304, "File", 300, #PB_ListIcon_GridLines | #PB_ListIcon_FullRowSelect)
AddGadgetColumn(#lstResults, 1, "Line", 60)
AddGadgetColumn(#lstResults, 2, "Text", 700)
CheckBoxGadget(#chkCloseOnSelect, 890, 310, 150, 17, "Close on Double Click")
EndProcedure
;}
;- ===[ Code... ]===
;- ---[ Structures ]---
Structure SearchItem
len.c
when.q
text.s
EndStructure
Structure winPosition
top.l
left.l
EndStructure
Structure winsPositions
search.winPosition
result.winPosition
EndStructure
;- ---[ Enumerations ]---
Enumeration menus
#menuResultsList
EndEnumeration
Enumeration menuItems ;-Menu/hotkey items
#Menu_CloseWindow
#Menu_Search
#Menu_ExactMatch
#Menu_CaseSpecific
#Menu_IgnoreComment
#Menu_SearchFor
#Menu_SearchEverywhere
#Menu_SearchcASM
#Menu_SearchIgnorecASM
#menu_OpenFile
#menu_OpenFolder
#menu_CloseOnSelect
EndEnumeration
Enumeration ; option group stuff
#s_Everything
#s_cASMonly
#s_PBonly
EndEnumeration
EnumerationBinary 1 ; for flags in saving options
#opxcasespecific
#opxexactmatch
#opxignorecomment
#opxignorequotes
#opxEverywhere
#opxcASM
#opxpbonly
#opxLstCloseOnSelect
EndEnumeration
Enumeration ; xml data
#xml
EndEnumeration
Enumeration ; files
#fileSource
#fileLock
#fileDB
EndEnumeration
Enumeration FormImage ; images/icons
#imgSearchICO
EndEnumeration
Enumeration ; Regular Expressions
#regxSearch
#regxFiles
EndEnumeration
;- ---[ Constants ]---
#useADS = #True ; only valid for windows, just to keep the disk tidy.
#maxSaveSearchItems = 20
#regex_notinquotes$ = ~"(?=(?:[^\"]*\"[^\"]*\")*[^\"]*\\Z)" ; regex for ignoring things in quotes
#regex_ExtractFilenamesFromXML = ~"(?im)(?<=<file name=\\\").*(?=\\\">)"
CompilerIf #PB_Compiler_Unicode ;- maximum path length
#PATH_MAX = 32767
CompilerElse
#PATH_MAX = #MAX_PATH
CompilerEndIf
CompilerSelect #PB_Compiler_OS ;- additional flags for MessageRequester()
CompilerCase #PB_OS_Windows
#MR_flags=#MB_TOPMOST|#MB_SYSTEMMODAL
CompilerCase #PB_OS_Linux ; todo
#MR_flags=0
CompilerWarning("a flag to get message requester to be modal is needed for this OS")
CompilerEndSelect
;- ---[ data section ]---
DataSection ; BOM
bom:
Data.b $EB,$C,$DC,$A1,$02
EndDataSection
;- ---[ Generic Macros ]---
Macro ods( c ) : OutputDebugString_( c ) : Debug c : EndMacro
Macro warning( c ) : ods("*WARNING: " + c ) : DebuggerWarning( c ) : EndMacro
Macro error( c ) : ods("** ERROR: " + c ) : DebuggerWarning( c ) : EndMacro
Macro iifs( b, t, f ) : PeekS( iif(b,@t,@f) ) : EndMacro
Macro moveWindow( w,x,y ) : ResizeWindow( w, x, y, #PB_Ignore,#PB_Ignore ) : EndMacro
CompilerIf #PB_Compiler_Debugger
; non-blocking (ie: in race condition, you can stil pause the app in the debugger.
Macro LockMutex( m ) : While Not TryLockMutex( m ) : Delay( 1 ) : Wend : EndMacro
Macro WaitSemaphore( s ) : While Not TrySemaphore( s ) : Delay( 1 ) : Wend : EndMacro
CompilerEndIf
CompilerSelect #PB_Compiler_OS ;- System wide mutex (lock only 1 instance)
CompilerCase #PB_OS_Windows
Macro createSystemMutex( mutexName ) : CreateMutex_(#NUL,#False,mutexName ) : EndMacro
Macro tryLockSystemMutex( hMutex ) : Bool(WaitForSingleObject_( hMutex,1 ) = #WAIT_OBJECT_0 ) : EndMacro
Macro lockSystemMutex( hMutex ) : Bool(WaitForSingleObject_( hMutex,#INFINITE ) = #WAIT_OBJECT_0 ) : EndMacro
Macro unlockSystemMutex( hMutex ) : ReleaseMutex_( hMutex ) : EndMacro
Macro freeSystemMutex( hMutex ) : CloseHandle_( hMutex ) : EndMacro
CompilerDefault
CompilerWarning("System wide mutex is needed for this OS")
CompilerWarning("These are completely untested, just speculative")
Macro createSystemMutex( mutexName ) : CreateFile(#fileLock, GetTemporaryDirectory()+"\pbProjectSearch.lock",#PB_File_NoBuffering) : EndMacro
Macro tryLockSystemMutex( hMutex ) : Bool(IsFile(#fileLock) Or CreateFile(#fileLock, GetTemporaryDirectory()+"\pbProjectSearch.lock",#PB_File_NoBuffering)) : EndMacro
Macro lockSystemMutex( hMutex ) : While Not tryLockSystemMutex(#NUL) : Delay( 1 ) : Wend : EndMacro
Macro unlockSystemMutex( hMutex ) : CloseFile(#fileLock) : EndMacro
Macro freeSystemMutex( hMutex ) : DeleteFile(GetTemporaryDirectory()+"\pbProjectSearch.lock") : EndMacro
CompilerEndSelect
;- ---[ Generic Procedures ]---
;{
Procedure.s getDirectoryEntry( file.s ) ; Fetches the filename as it appears on disk (capitilzations) - SLOW.
Protected here.s, dir
dir = ExamineDirectory(#PB_Any, GetPathPart(file), GetFilePart(file))
If dir
If NextDirectoryEntry(dir)
here = GetCurrentDirectory()
SetCurrentDirectory( GetPathPart(file))
file = GetCurrentDirectory()+DirectoryEntryName(dir)
SetCurrentDirectory(here)
EndIf
FinishDirectory(dir)
EndIf
ProcedureReturn file
EndProcedure
Procedure.s getFullPathName( cPath.s, bExact = #False ) ; gets fullpath from partial or relative paths
Protected cFullPath.s, *Buffer, nSize, *FilePart
*Buffer = AllocateMemory(#PATH_MAX * SizeOf(Character))
If *Buffer
nSize = GetFullPathName_(@cPath,#PATH_MAX,*Buffer,@*FilePart)
If nSize : cFullPath = PeekS(*Buffer,nSize) : EndIf
FreeMemory(*Buffer)
Else
Error("Alloc failure")
EndIf
If bExact : cFullPath = GetDirectoryEntry( cFullPath ) : EndIf
ProcedureReturn cFullPath
EndProcedure
Procedure restoreWindow( title.s, class.s="" )
Protected hWnd,
bRestored = #False
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
hwnd = FindWindow_( @class, @title )
bRestored = Bool( hWnd And
IsWindowVisible_( hWnd ) And
ShowWindowAsync_( hWnd, #SW_RESTORE ) And
SetForegroundWindow_( hWnd ) )
SetActiveWindow_( hWnd )
CompilerDefault
CompilerWarning("a restoreWindow() method is needed for this OS")
bRestored=#True
CompilerEndSelect
ProcedureReturn bRestored
EndProcedure
Procedure fixTextHK(gadget)
Protected p, c.s, tmp.s
If GadgetType(gadget)=#PB_GadgetType_Text
tmp = GetGadgetText( gadget )
p = FindString( tmp, "&" )
If p
c = Mid( tmp, p+1, 1)
ReplaceString( tmp, "&"+c, c+Chr($332), #PB_String_CaseSensitive|#PB_String_InPlace, p ,1 )
SetGadgetText( gadget, tmp)
EndIf
EndIf
EndProcedure
Procedure setWindowIcon( window, image )
If IsWindow(window) And IsImage(image)
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
SendMessage_( WindowID(window), #WM_SETICON, 0, ImageID(image) )
CompilerCase #PB_OS_Linux
gtk_window_set_icon_( WindowID(window), ImageID(image) )
CompilerEndSelect
EndIf
EndProcedure
Procedure min(a,b)
CompilerIf #PB_Compiler_Backend=#PB_Backend_C
! return( fmin(v_a,v_b) );//(v_a<v_b?v_a:v_b);
CompilerElse
If a<b : ProcedureReturn a
Else : ProcedureReturn b
EndIf
CompilerEndIf
EndProcedure
Procedure iif( b, t, f )
CompilerIf #PB_Compiler_Backend = #PB_Backend_C
! return( (v_b?v_t:v_f) );
CompilerElse
If b : ProcedureReturn t : EndIf
ProcedureReturn f
CompilerEndIf
EndProcedure
Procedure waitForFile(f, waitMS=#INFINITE)
Protected s
If IsFile(f)
If waitMS <> #INFINITE : s = ElapsedMilliseconds() : EndIf
While IsFile(f) And (waitMS=#INFINITE Or waitMS > (ElapsedMilliseconds()-s) )
Delay( 1 )
Wend
EndIf
ProcedureReturn Bool( Not IsFile(f ) )
EndProcedure
;}
;- ---[ Project Search Procedures ]---
;{
Procedure.s readToString( file.s )
Protected fdata.s, s, c.c, encoding
If ReadFile(#fileSource, file, #PB_File_SharedRead)
encoding = ReadStringFormat( #fileSource )
fdata = ReadString(#fileSource, #PB_File_IgnoreEOL|encoding, Lof(#fileSource))
Else
ods("Failed to read file: "+file)
EndIf
ProcedureReturn fdata
EndProcedure
Procedure getLineNo( source.s, instance )
Protected tmp.s, x, l,
encoding, count, lineNo,
caseSpecific = GetGadgetState( #chkCaseSpecific )
source=Trim(source) : l=Len(source)
If Not caseSpecific : source = LCase( source ) : EndIf
FileSeek( 0,0, #PB_Absolute )
encoding =ReadStringFormat(#fileSource)
instance+1
For x = 1 To instance
While Not Eof(#fileSource)
count + 1
tmp = ReadString( #fileSource, encoding )
tmp = Left(Trim(tmp),l)
If (caseSpecific And tmp = source) Or LCase(tmp) = source
lineno = count
Break
EndIf
Wend
Next
ProcedureReturn lineNo
EndProcedure
Procedure searchFile( cFile.s )
Protected Dim results.s(0)
Protected regX.s, fileStr.s,
x, t, p, lineno,
matches.i,
commentPosition,
SearchWhat,
rxFlags = #PB_RegularExpression_AnyNewLine|#PB_RegularExpression_MultiLine,
bCaseSpecific = GetGadgetState( #chkCaseSpecific ),
bExactMatch = GetGadgetState( #chkExact ),
bIgnoreComments = GetGadgetState( #chkIgnoreComments ),
textToFind.s = GetGadgetText( #cboSearchFor ),
bIgnoreQuotes = GetGadgetState( #chkIgnoreQuotes )
If Not bCaseSpecific : rxFlags|#PB_RegularExpression_NoCase : EndIf
#pcre_needsEscaping="\%.*+-()[]{}<>|^$?"
For x = 1 To Len( #pcre_needsEscaping )
textToFind = ReplaceString( textToFind, Mid(#pcre_needsEscaping,x,1),"\"+Mid(#pcre_needsEscaping,x,1) )
Next
If bExactMatch : regx+"^.*(\b"+textToFind+"\b)" ; find the string, as a whole word
Else : regx+"^.*(" +textToFind+ ")" ; find the string, somewhere, in the line
EndIf
If bIgnoreQuotes : regx+#regex_notinquotes$ : EndIf
regx+".*$" ; but only across a line (start-of-line *text* end-of-line)
If Not CreateRegularExpression(#regxSearch, regx, rxFlags)
MessageRequester("Error","Invalid Regex"+#CRLF$+regx+#CRLF$+RegularExpressionError(),#PB_MessageRequester_Error)
End
EndIf
; it got too complicated to handle all the combinations in a single regex.
If GetGadgetState(#optcASM)
SearchWhat=#s_cASMonly ; starts with "!" (outside of quotes)
ElseIf GetGadgetState(#optPBOnly)
SearchWhat=#s_PBonly ; does not start with "!" (outside of quotes)
Else ;If GetGadgetState(#optEverywhere)
SearchWhat=#s_Everything
EndIf
ods("Scanning "+cFile)
fileStr = readToString( cFile )
If Len(fileStr) > 0
t = ExtractRegularExpression(#regxSearch,fileStr,results())
ods("Matches: "+Str(t))
t-1
Protected bAddit
; before comment
For x = 0 To t
bAddit=#True
; This needs updating, right now the matching is super simple, "line starts with..."but this doesn't account for ":"
If bIgnoreComments And Left(Trim(results(x)),1)=";"
;commentPosition=FindString(results(x),";",0,#PB_String_CaseSensitive)
;If commentPosition And (FindString(results(x),textToFind,0,#PB_String_NoCase) > commentPosition)
ods("Comment, not adding: "+results(x))
bAddit=#False
;EndIf
ElseIf SearchWhat=#s_cASMonly And Left(Trim(results(x)),1)<>"!"
ods("PB code, not adding: "+results(x))
bAddit=#False
ElseIf searchwhat=#s_PBonly And Left(Trim(results(x)),1)="!"
ods("ASM/C code, not adding: "+results(x))
bAddit=#False
EndIf
If bAddit
ods("Adding ("+lineno+") "+results(x))
;todo lineno not updating!
lineno = getLineNo(results(x), x+1)
AddGadgetItem(#lstResults,x,cFile + #LF$ + Str(lineno) + #LF$ + Trim( results(x) ) )
matches+1
EndIf
Next
FreeRegularExpression(#regxSearch)
Else
ods("empty file")
EndIf
If IsFile(#fileSource) : CloseFile(#fileSource) : EndIf
ProcedureReturn matches
EndProcedure
Procedure scanProject( cProjectFile.s )
Protected str.s,x,t, matchCount, fileCount, tmp
Dim results.s(0)
str = readToString( cProjectFile ) : CloseFile(#fileSource)
If str<>""
;- Regex to pull out any file names that are included in project file or source.
CreateRegularExpression(#regxFiles,#regex_ExtractFilenamesFromXML)
t = ExtractRegularExpression(#regxFiles, str, results() ) : t-1
For x = 0 To t
results(x) = getFullPathName( results(x), #True )
tmp = searchFile( results(x) )
If tmp
fileCount+1
matchCount+tmp
EndIf
Next
StatusBarText(0, 1, Str(t), #PB_StatusBar_Center )
StatusBarText(0, 3, Str(fileCount), #PB_StatusBar_Center )
StatusBarText(0, 5, Str(matchCount), #PB_StatusBar_Center )
FreeRegularExpression(#regxFiles)
EndIf
ProcedureReturn CountGadgetItems(#lstResults)
EndProcedure
Procedure.s getTitleXML( cProjectFile.s )
Protected cTitle.s, *x
If FileSize(cProjectFile) > 0 And LoadXML(#XML, cProjectFile)
If XMLStatus(#XML) <> #PB_XML_Success
Warning("XML Error: " + XMLError(#XML) + "Line: " + Str(XMLErrorLine(#XML)) + " Character: " + Str(XMLErrorPosition(#XML)))
Else
*x = MainXMLNode(#XML)
*x = XMLNodeFromPath( *x,"/project/section/options")
If ExamineXMLAttributes( *x )
While NextXMLAttribute( *x )
If XMLAttributeName( *x ) = "name"
cTitle=XMLAttributeValue( *x )
Break
EndIf
Wend
EndIf
EndIf
FreeXML(#xml)
EndIf
ProcedureReturn cTitle
EndProcedure
;}
;- ---[ Threaded Procedures ]---
;{
CompilerIf Not #PB_Compiler_Thread
CompilerWarning("Advise: Use ThreadSafe!")
CompilerEndIf
Procedure loadDB(hSemaphore)
Protected *p.SearchItem,
winpos.winsPositions,
i, t, flags.c, dbName.s
waitForFile(#fileDB)
dbName = GetEnvironmentVariable("PB_TOOL_PROJECT")+".search.db"
CompilerIf #useADS And #PB_Compiler_OS=#PB_OS_Windows
ReplaceString(dbname,"\",".",#PB_String_InPlace)
ReplaceString(dbname,":",".",#PB_String_InPlace)
dbname=ProgramFilename()+":"+dbName ; use ads to keep from cluttering disk
CompilerEndIf
If ReadFile(#fileDB, dbName, #PB_Unicode)
*p=AllocateMemory(SizeOf(SearchItem))
ReadData(#fileDB,*p,5)
If CompareMemory(*p,?bom,5)
t = ReadInteger(#fileDB) : flags=ReadCharacter(#fileDB) : ReadData(#fileDB,@winpos,SizeOf(winsPositions))
moveWindow(#winResults,winPos\result\left,winPos\result\top)
moveWindow(#winSearch,winPos\search\left,winPos\search\top)
SignalSemaphore(hSemaphore)
Dim items.SearchItem(t)
i=0
While Not Eof(#fileDB) And i <= t
ReadData(#fileDB,*p,SizeOf(SearchItem))
items(i)\len = *p\len
items(i)\when = *p\when
items(i)\text = ReadString(#fileDB,#PB_Unicode,items(i)\len)
i+1
Wend
SortStructuredArray(items(),#PB_Sort_Descending,OffsetOf(SearchItem\text),#PB_String)
For i = 0 To t
AddGadgetItem(#cboSearchFor,i,Trim(items(i)\text))
SetGadgetItemData(#cboSearchFor,i,items(i)\when)
Next
SetGadgetState( #chkCaseSpecific, flags&#opxcasespecific )
SetGadgetState( #chkExact, flags&#opxexactmatch )
SetGadgetState( #chkIgnoreComments, flags&#opxignorecomment )
SetGadgetState( #chkIgnoreQuotes, flags&#opxignorequotes )
SetGadgetState( #optcASM, flags&#opxcASM )
SetGadgetState( #optEverywhere, flags&#opxEverywhere )
SetGadgetState( #optPBOnly, flags&#opxpbonly )
SetGadgetState( #chkCloseOnSelect, flags&#opxLstCloseOnSelect )
Else
Warning("Invalid BOM")
SignalSemaphore( hSemaphore )
EndIf
FreeMemory(*p)
CloseFile(#fileDB)
Else
ods("No db to open")
SignalSemaphore( hSemaphore )
EndIf
EndProcedure
Procedure saveDB(lock)
Protected bAlready, i, flags.c, dbName.s,
winPos.winsPositions
LockMutex(lock)
Protected t = CountGadgetItems( #cboSearchFor )
Protected Dim items.SearchItem( t )
If GetGadgetState(#chkCaseSpecific) : flags|#opxcasespecific : EndIf
If GetGadgetState(#chkExact) : flags|#opxexactmatch : EndIf
If GetGadgetState(#chkIgnoreComments) : flags|#opxignorecomment : EndIf
If GetGadgetState(#chkIgnoreQuotes) : flags|#opxignorequotes : EndIf
If GetGadgetState(#chkCloseOnSelect) : flags|#opxLstCloseOnSelect : EndIf
If GetGadgetState(#optcASM) : flags|#opxcASM
ElseIf GetGadgetState(#optPBOnly ) : flags|#opxpbonly
Else : flags|#opxEverywhere
EndIf
t-1
For i = 0 To t
items(i)\text = GetGadgetItemText(#cboSearchFor,i)
items(i)\when = GetGadgetItemData(#cboSearchFor,i)
items(i)\len = Len(items(i)\text)
If items(i)\text=GetGadgetText(#cboSearchFor)
SetGadgetState(#cboSearchFor,i)
SetGadgetItemData(#cboSearchFor,i,Date())
bAlready=#True
EndIf
Next
If Not bAlready
t+1
items(t)\text = GetGadgetText(#cboSearchFor)
items(t)\when = Date()
items(t)\len = Len(items(t)\text)
ClearGadgetItems(#cboSearchFor)
SortStructuredArray(items(),#PB_Sort_Descending,OffsetOf(SearchItem\text),#PB_String)
For i = 0 To min(t,#maxSaveSearchItems)
AddGadgetItem(#cboSearchFor,i,items(i)\text)
SetGadgetItemData(#cboSearchFor,i,items(i)\when)
If items(i)\text=GetGadgetText(#cboSearchFor)
SetGadgetState(#cboSearchFor,i)
EndIf
Next
EndIf
SortStructuredArray(items(),#PB_Sort_Descending,OffsetOf(SearchItem\when),#PB_Quad)
waitForFile(#fileDB)
dbName = GetEnvironmentVariable("PB_TOOL_PROJECT") + ".search.db"
CompilerIf #useADS And #PB_Compiler_OS=#PB_OS_Windows
ReplaceString(dbname,"\",".",#PB_String_InPlace)
ReplaceString(dbname,":",".",#PB_String_InPlace)
dbname=ProgramFilename()+":"+dbName ; use ads to keep from cluttering disk
CompilerEndIf
If CreateFile(#fileDB, dbName, #PB_Unicode)
WriteData(#fileDB,?bom,5) : WriteInteger(#fileDB,min(t,#maxSaveSearchItems)) : WriteCharacter(#fileDB,flags)
winPos\search\left=WindowX( #winSearch, #PB_Window_FrameCoordinate )
winPos\search\top=WindowY( #winSearch, #PB_Window_FrameCoordinate )
winPos\result\left=WindowX( #winResults, #PB_Window_FrameCoordinate )
winPos\result\top=WindowY( #winResults, #PB_Window_FrameCoordinate )
WriteData(#fileDB,@winpos,SizeOf(winsPositions))
For i = 0 To min(t,#maxSaveSearchItems)
WriteData( #fileDB, @items(i), SizeOf(SearchItem) )
WriteString( #fileDB, items(i)\text, #PB_Unicode )
Next
CloseFile(#fileDB)
Else
Warning("** Failed to write search db")
EndIf
UnlockMutex(lock)
EndProcedure
;}
;- ---[ Main Processing ]---
Procedure main()
Protected ev,gn, m, s, cFileName.s, cLineNumber.s, cTitle.s,
hSysMutex = createSystemMutex( "pbProjectSearch" ),
pbHome.s = ProgramParameter(0),
project.s = GetEnvironmentVariable("PB_TOOL_PROJECT")
CompilerIf #PB_Compiler_Debugger
project = "c:\pbincludes\josh\test-timer.pbp"
pbHome = #PB_Compiler_Home
CompilerEndIf
If FileSize(pbHome)=-2 And project <> ""
If tryLockSystemMutex( hSysMutex ) ; Suggested by highend to stop double-runs
OpenwinSearch() : OpenwinResults()
s=CreateSemaphore()
CompilerIf #PB_Compiler_Thread
CreateThread( @loadDB(), s )
CompilerElse
loadDB( s )
CompilerEndIf
CatchImage( #imgSearchICO, ?beginSearchico, ?endSearchico-?beginSearchico )
setWindowIcon( #winSearch, #imgSearchICO ) : StickyWindow( #winSearch, #True ) : fixTextHK(#txtSearchFor)
setWindowIcon( #winResults, #imgSearchICO )
If CreatePopupMenu( #menuResultsList )
MenuItem( #menu_CloseOnSelect, "Close Search on Select")
MenuItem( #menu_openFile, "Open File" )
MenuItem( #menu_openFolder, "Open Folder" )
SetMenuItemState( #menuResultsList, #menu_CloseOnSelect, GetGadgetState(#chkCloseOnSelect) )
EndIf
cTitle=getTitleXML(project)
If cTitle
SetWindowTitle( #winSearch, "Search: " + cTitle )
SetWindowTitle( #winResults, "Results: " + cTitle )
EndIf
HideWindow(#winSearch,#False)
SetActiveGadget(#cboSearchFor)
m=CreateMutex()
SetCurrentDirectory( GetPathPart(project))
;{ Add keyboard shortcuts.
AddKeyboardShortcut(#winSearch, #PB_Shortcut_Return, #Menu_Search)
AddKeyboardShortcut(#winSearch, #PB_Shortcut_Escape, #Menu_CloseWindow)
AddKeyboardShortcut(#winSearch, #PB_Shortcut_Alt|#PB_Shortcut_E, #Menu_ExactMatch)
AddKeyboardShortcut(#winSearch, #PB_Shortcut_Alt|#PB_Shortcut_C, #Menu_CaseSpecific)
AddKeyboardShortcut(#winSearch, #PB_Shortcut_Alt|#PB_Shortcut_I, #Menu_IgnoreComment)
AddKeyboardShortcut(#winSearch, #PB_Shortcut_Alt|#PB_Shortcut_S, #Menu_Search)
AddKeyboardShortcut(#winSearch, #PB_Shortcut_Alt|#PB_Shortcut_F, #Menu_SearchFor)
AddKeyboardShortcut(#winSearch, #PB_Shortcut_Alt|#PB_Shortcut_A, #Menu_SearchEverywhere)
AddKeyboardShortcut(#winSearch, #PB_Shortcut_Alt|#PB_Shortcut_M, #Menu_SearchcASM)
AddKeyboardShortcut(#winSearch, #PB_Shortcut_Alt|#PB_Shortcut_G, #Menu_SearchIgnorecASM)
AddKeyboardShortcut(#winResults, #PB_Shortcut_Escape, #Menu_CloseWindow)
AddKeyboardShortcut(#winResults, #PB_Shortcut_Return, #menu_OpenFile)
;}
CompilerIf #PB_Compiler_Thread
; when using a thread to resize a window, it requires there to be an event loop; no thread, no loop needed.
Repeat
WaitWindowEvent(0)
Until TrySemaphore(s)
CompilerEndIf
FreeSemaphore(s)
Repeat
Select WaitWindowEvent(1)
Case #PB_Event_Menu
Select EventMenu()
Case #Menu_Search
PostEvent(#PB_Event_Gadget,#winSearch,#btnSearch,#PB_EventType_LeftClick)
Case #Menu_CloseWindow
Select GetActiveWindow()
Case #winSearch
Break
Case #winResults
HideWindow(#winResults,#True)
HideWindow(#winSearch,#False)
DisableWindow(#winSearch,#False)
EndSelect
Case #Menu_SearchFor : SetActiveGadget(#cboSearchFor)
Case #Menu_ExactMatch : SetGadgetState( #chkExact, Bool(Not GetGadgetState( #chkExact )) )
Case #Menu_CaseSpecific : SetGadgetState( #chkCaseSpecific, Bool(Not GetGadgetState( #chkCaseSpecific )) )
Case #Menu_IgnoreComment : SetGadgetState( #chkIgnoreComments, Bool(Not GetGadgetState( #chkIgnoreComments )) )
Case #Menu_SearchEverywhere : SetGadgetState( #optEverywhere, #True )
Case #Menu_SearchcASM : SetGadgetState( #optcASM, #True )
Case #Menu_SearchIgnorecASM : SetGadgetState( #optPBOnly, #True )
Case #menu_OpenFile
; fix by highend (quote around file name)
cFileName = GetGadgetItemText(#lstResults,GetGadgetState(#lstResults),0)
cLineNumber = GetGadgetItemText(#lstResults,GetGadgetState(#lstResults),1)
RunProgram( pbHome+"PureBasic.exe",~"\""+cFileName+~"\" /L "+cLineNumber,GetPathPart(project))
If GetGadgetState(#chkCloseOnSelect)
PostEvent(#PB_Event_CloseWindow,#winResults,#winResults)
PostEvent(#PB_Event_CloseWindow,#winSearch,#winSearch)
EndIf
Case #menu_OpenFolder
RunProgram("explorer.exe",~"/select,\"" + cFileName + ~"\"","")
If GetGadgetState(#chkCloseOnSelect)
PostEvent(#PB_Event_CloseWindow,#winResults,#winResults)
PostEvent(#PB_Event_CloseWindow,#winSearch,#winSearch)
EndIf
Case #menu_CloseOnSelect
SetMenuItemState(#menuResultsList, #menu_CloseOnSelect, Bool( Not GetMenuItemState( #menuResultsList, #menu_CloseOnSelect ) ) )
SetGadgetState( #chkCloseOnSelect, GetMenuItemState( #menuResultsList, #menu_CloseOnSelect ) )
EndSelect
Case #PB_Event_SizeWindow,#PB_Event_MoveWindow
CompilerIf #PB_Compiler_Thread
CreateThread( @saveDB(),m)
CompilerElse
saveDB(m)
CompilerEndIf
Case #PB_Event_CloseWindow
Select EventWindow()
Case #winSearch
Break
Case #winResults
HideWindow( #winResults, #True )
StickyWindow( #winResults, #False )
HideWindow( #winSearch, #False )
DisableWindow( #winSearch, #False )
StickyWindow( #winSearch, #True )
EndSelect
Case #PB_Event_Gadget
Select EventGadget()
Case #chkCloseOnSelect
SetMenuItemState( #menuResultsList, #menu_CloseOnSelect, GetGadgetState(#chkCloseOnSelect) )
Select EventType()
Case #PB_EventType_Change
CompilerIf #PB_Compiler_Thread
CreateThread( @saveDB(),m)
CompilerElse
saveDB(m)
CompilerEndIf
EndSelect
Case #lstResults
Select EventType()
Case #PB_EventType_RightClick
DisplayPopupMenu(0, WindowID(#winResults)) ; now display the popup-menu
Case #PB_EventType_LeftDoubleClick
PostEvent(#PB_Event_Menu,#winResults,#menu_OpenFile)
EndSelect
Case #btnSearch
DisableWindow(#winSearch,#True)
CompilerIf #PB_Compiler_Thread
CreateThread( @saveDB(),m)
CompilerElse
saveDB(m)
CompilerEndIf
ClearGadgetItems(#lstResults)
If scanProject( project )
HideWindow( #winSearch, #True )
DisableWindow( #winSearch, #True )
StickyWindow( #winSearch, #False )
HideWindow( #winResults, #False )
StickyWindow( #winResults, #True )
Else
MessageRequester("Project Search","No matches found",#PB_MessageRequester_Ok|#MR_flags,WindowID(#winSearch))
HideWindow( #winSearch, #False )
DisableWindow( #winSearch, #False )
StickyWindow( #winSearch, #True )
HideWindow( #winResults, #True )
StickyWindow( #winResults, #False )
EndIf
Case #cboSearchFor
Select EventType()
Case #PB_EventType_Change,#PB_EventType_LostFocus
DisableGadget(#btnSearch, Bool(Len(Trim(GetGadgetText(#cboSearchFor)))=0))
Case #PB_EventType_Focus
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
SendMessage_( GadgetID(#cboSearchFor), #EM_SETSEL, 0, -1)
CompilerDefault
CompilerWarning("a method to select all gadget text is needed for this OS")
CompilerEndSelect
EndSelect
EndSelect
EndSelect
ForEver
unlockSystemMutex(hSysMutex)
Else
MessageRequester("Project Search","Already Running",#PB_MessageRequester_Ok|#MR_flags)
CompilerSelect #PB_Compiler_OS
CompilerCase #PB_OS_Windows
If Not restoreWindow( "Project Search", "WindowClass_0" )
restoreWindow( "Project Search Results", "WindowClass_1" )
EndIf
CompilerDefault
CompilerWarning("a method to restore focus to windows is needed for this OS")
CompilerEndSelect
EndIf
Else
MessageRequester("Project Search","No project active",#PB_MessageRequester_Ok|#MR_flags)
EndIf
freeSystemMutex(hSysMutex)
EndProcedure
main() ;- Run the program
;- ---[ Icon Data Section ]---
DataSection
beginSearchico:
Data.w $0000,$0001,$0001,$3030,$0000,$0001,$0008,$0EA8, $0000,$0016,$0000,$0028,$0000,$0030,$0000,$0060
Data.w $0000,$0001,$0008,$0000,$0000,$0000,$0000,$0EC4, $0000,$0EC4,$0000,$0000,$0000,$0000,$0000,$FFFF
Data.w $00FF,$F3F3,$00F3,$E9E9,$00E9,$E4E4,$00E4,$C9C9, $00C9,$C5C5,$00C5,$DEFB,$00BB,$DCFA,$00B5,$D7FB
Data.w $00AC,$D3FA,$00A4,$D0F9,$009D,$CEF9,$009A,$CCF9, $0094,$C9F8,$008F,$ABAB,$00AB,$A9AB,$00A6,$A6A8
Data.w $00A2,$A1A1,$00A1,$A0A2,$009B,$9EA0,$0099,$9E9E, $009E,$999C,$0093,$9699,$0090,$8383,$0083,$C0F7
Data.w $007B,$BFF7,$0079,$BCF7,$0073,$B8F7,$006A,$B6F6, $0068,$B5F6,$0064,$B1EF,$0064,$A9E0,$0063,$A8DE
Data.w $0063,$A1D1,$0064,$9ECE,$0063,$92B9,$0063,$91B7, $0063,$88A7,$0063,$87A5,$0062,$7482,$0062,$7B7B
Data.w $007B,$7272,$0072,$727E,$0062,$6E79,$0061,$6D77, $0062,$6C6C,$006C,$676B,$0062,$6162,$0061,$6267
Data.w $0058,$6267,$0057,$5F64,$0054,$4F54,$0044,$4850, $0038,$474F,$0038,$474F,$0037,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000
Data.w $0000,$0000,$0000,$0000,$0000,$0000,$0000,$0000, $0000,$0000,$0000,$0000,$0000,$0000,$0000,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3115,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$1537,$3636,$0132,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3616,$3636,$3036,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$1537,$3636,$3636,$1336,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3515,$3636,$3636,$3713,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $1537,$3636,$3636,$1336,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3515,$3636,$3636,$3713,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$1537, $3636,$3636,$1336,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$0401,$1711, $2F2D,$2D2F,$1117,$0104,$3737,$3737,$3737,$3611
Data.w $3636,$3636,$3712,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$1101,$2F2D,$2F2F
Data.w $2F2F,$2F2F,$2F2F,$2D2F,$0211,$3737,$0437,$332F, $3636,$1336,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$0E37,$2F2D,$2F2F,$2F2F, $2F2F,$2F2F,$2F2F,$2F2F,$2F2F,$370E,$2F04,$2F2F
Data.w $3633,$3713,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$0137,$2F17,$2F2F,$2C2F,$2226
Data.w $1E20,$201E,$2622,$2F2C,$2F2F,$282F,$2F2F,$2F2F, $0F2F,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$2903,$2F2F,$2B2F,$1D22,$1D1D, $1D1D,$1D1D,$1D1D,$221D,$2F2A,$2F2F,$2F2F,$2F2F
Data.w $3705,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$0237,$2F29,$2F2F,$1D24,$1D1D,$1D1D
Data.w $1D1D,$1D1D,$1D1D,$1D1D,$241D,$2F2F,$2F2F,$052F, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$1737,$2F2F,$212E,$1D1D,$1D1D,$1D1D, $1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$2E22,$2F2F,$3728
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$2F0E,$2F2F,$1D22,$1D1D,$1D1D,$1D1D
Data.w $1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$211D,$2F2F,$0E2F, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$0337,$2F2F,$232F,$1D1D,$1D1D,$1D1D,$1D1D, $1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$2F24,$2F2F
Data.w $3702,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$1337,$2F2F,$1D2A,$1D1D,$1D1D,$1D1D,$1D1D
Data.w $1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$2A1D,$2F2F, $3711,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$2D01,$2F2F,$1D22,$1D1D,$1D1D,$1D1D,$1D1D, $1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$221D,$2F2F
Data.w $372F,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$2F04,$2C2F,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D
Data.w $1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$2F2C, $042F,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$2F13,$262F,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D, $1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$2F26
Data.w $112F,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$2F17,$222F,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D
Data.w $1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$2F22, $172F,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$2F2D,$202F,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D, $1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$2F20
Data.w $2D2F,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$2F2F,$1E2F,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D
Data.w $1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$2F1E, $2F2F,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$2F2F,$1E2F,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D, $1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$2F1E
Data.w $2F2F,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$2F2D,$202F,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D
Data.w $1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$2F20, $2D2F,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$2F17,$222F,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D, $1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$2F22
Data.w $172F,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$2F13,$262F,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D
Data.w $1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$2F26, $112F,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$2F04,$2B2F,$1D1D,$1D1D,$091D,$1D0C,$1D1D, $1D1D,$1D1D,$1D1D,$0C1D,$1D09,$1D1D,$1D1D,$2F2C
Data.w $042F,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$2F01,$2F2F,$1D22,$1D1D,$071B,$0A06,$1D1C
Data.w $1D1D,$1D1D,$1C1D,$060A,$1D07,$1D1D,$221D,$2F2F, $012D,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$1337,$2F2F,$1D27,$1D1D,$191D,$0607,$0D07, $1D1A,$1A1C,$070D,$0706,$1D19,$1D1D,$2A1D,$2F2F
Data.w $3711,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$0237,$2F2F,$232F,$1D1D,$1D1D,$091A,$0606
Data.w $0606,$0606,$0606,$1A09,$1D1D,$1D1D,$2F24,$2D2F, $3702,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$2F0F,$2F2F,$1D21,$1D1D,$1D1D,$0A19, $0708,$0807,$190A,$1D1D,$1D1D,$211D,$2F2F,$0E2F
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$2837,$2F2F,$222E,$1D1D,$1D1D,$1D1D
Data.w $1D1D,$1D1D,$1D1D,$1D1D,$1D1D,$2E22,$2F2F,$3717, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$0237,$2F2D,$2F2F,$1D23,$1D1D,$1D1D, $1D1D,$1D1D,$1D1D,$1D1D,$241D,$2F2F,$292F,$3702
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$2D03,$2F2F,$2A2F,$1D22,$1D1D
Data.w $1D1D,$1D1D,$1D1D,$211D,$2F27,$2F2F,$0329,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$0237,$2F28,$2F2F,$2C2F,$2226, $1E20,$201E,$2622,$2F2B,$2F2F,$172F,$3702,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$0F37,$2F2F,$2F2F,$2F2F
Data.w $2F2F,$2F2F,$2F2F,$2F2F,$2F2F,$370E,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$1303,$2F2F,$2F2F, $2F2F,$2F2F,$2F2F,$2F2F,$0213,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$0401,$1713
Data.w $2F2D,$2D2F,$1317,$0104,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737
Data.w $3737,$3737,$3737,$3737,$3737,$3737,$3737,$3737, $3737,$3737,$3737,$3737,$3737,$3737,$3737,$FFFF
Data.w $FFFF,$FFFF,$0000,$FFFF,$FFFF,$FFFF,$0000,$FFFF, $FFFF,$FFFF,$0000,$FFFF,$FFFF,$FFFF,$0000,$FFFF
Data.w $FFFF,$3FFF,$0000,$FFFF,$FFFF,$0FFE,$0000,$FFFF, $FFFF,$0FFC,$0000,$FFFF,$FFFF,$0FF8,$0000,$FFFF
Data.w $FFFF,$1FF0,$0000,$FFFF,$FFFF,$3FE0,$0000,$FFFF, $FFFF,$7FC0,$0000,$FFFF,$FFFF,$FF80,$0000,$FCFF
Data.w $3F00,$FF01,$0000,$F0FF,$0E00,$FF03,$0000,$E0FF, $0400,$FF07,$0000,$80FF,$0000,$FF0F,$0000,$00FF
Data.w $0000,$FF1F,$0000,$00FE,$0000,$FF3F,$0000,$00FE, $0000,$FF7F,$0000,$00FC,$0000,$FF3F,$0000,$00F8
Data.w $0000,$FF1F,$0000,$00F8,$0000,$FF1F,$0000,$00F0, $0000,$FF1F,$0000,$00F0,$0000,$FF0F,$0000,$00F0
Data.w $0000,$FF0F,$0000,$00F0,$0000,$FF0F,$0000,$00F0, $0000,$FF0F,$0000,$00F0,$0000,$FF0F,$0000,$00F0
Data.w $0000,$FF0F,$0000,$00F0,$0000,$FF0F,$0000,$00F0, $0000,$FF0F,$0000,$00F0,$0000,$FF0F,$0000,$00F0
Data.w $0000,$FF0F,$0000,$00F0,$0000,$FF0F,$0000,$00F8, $0000,$FF1F,$0000,$00F8,$0000,$FF1F,$0000,$00FC
Data.w $0000,$FF3F,$0000,$00FE,$0000,$FF7F,$0000,$00FE, $0000,$FF7F,$0000,$00FF,$0000,$FFFF,$0000,$80FF
Data.w $0100,$FFFF,$0000,$E0FF,$0700,$FFFF,$0000,$F0FF, $0F00,$FFFF,$0000,$FCFF,$3F00,$FFFF,$0000,$FFFF
Data.w $FFFF,$FFFF,$0000,$FFFF,$FFFF,$FFFF,$0000,$FFFF, $FFFF,$FFFF,$0000,$FFFF,$FFFF,$FFFF,$0000
endSearchico:
EndDataSection