source: branches/2.20_branch/NewView/TextSearchQuery.pas@ 448

Last change on this file since 448 was 228, checked in by RBRi, 18 years ago

refactoring for language handling

  • Property svn:eol-style set to native
File size: 5.1 KB
Line 
1Unit TextSearchQuery;
2
3// NewView - a new OS/2 Help Viewer
4// Copyright 2003 Aaron Lawrence (aaronl at consultant dot com)
5// This software is released under the Gnu Public License - see readme.txt
6
7Interface
8
9// Encapsulates a parsed search query.
10
11uses
12 Classes,
13 SysUtils;
14
15Type
16 ESearchSyntaxError = class( Exception )
17 end;
18
19 TSearchTermCombineMethod =
20 (
21 cmOptional,
22 cmRequired,
23 cmExcluded
24 );
25
26 TSearchTerm = class
27 Text: string;
28 Parts: TStringList;
29 CombineMethod: TSearchTermCombineMethod;
30
31 constructor Create( const TheText: string;
32 const TheCombineMethod: TSearchTermCombineMethod );
33 destructor Destroy; override;
34 end;
35
36 TTextSearchQuery = class
37 protected
38 Terms: TList;
39 function GetTerm( Index: longint ): TSearchTerm;
40 function GetTermCount: longint;
41 public
42 constructor Create( const SearchString: string );
43 destructor Destroy; override;
44
45 property Term[ Index: longint ]: TSearchTerm read GetTerm;
46 property TermCount: longint read GetTermCount;
47 end;
48
49Implementation
50
51uses
52 ACLUtility,
53 ACLLanguageUnit,
54 CharUtilsUnit,
55 StringUtilsUnit,
56 DebugUnit;
57
58var
59 QueryErrorMissingWord1: string;
60 QueryErrorMissingWord2: string;
61
62Procedure OnLanguageEvent( Language: TLanguageFile;
63 const Apply: boolean );
64var
65 tmpPrefix : String;
66begin
67 tmpPrefix := 'SearchQuery' + LANGUAGE_LABEL_DELIMITER;
68 Language.LL( Apply, QueryErrorMissingWord1, tmpPrefix + 'QueryErrorMissingWord1', 'No search word given after ' );
69 Language.LL( Apply, QueryErrorMissingWord2, tmpPrefix + 'QueryErrorMissingWord2', ' before ' );
70end;
71
72constructor TTextSearchQuery.Create( const SearchString: string );
73var
74 TermText: string;
75 CombineMethod: TSearchTermCombineMethod;
76 Term: TSearchTerm;
77 tmpTerms : TStringList;
78 i : integer;
79begin
80 Terms := TList.Create;
81 try
82 tmpTerms := TStringList.Create;
83 StrExtractStringsQuoted(tmpTerms, SearchString);
84
85 for i := 0 to tmpTerms.count-1 do
86 begin
87 TermText := tmpTerms[i];
88
89 // Check for modifiers:
90 // + word must be matched
91 // - word must not be matched
92 case TermText[ 1 ] of
93 '+':
94 CombineMethod := cmRequired;
95 '-':
96 CombineMethod := cmExcluded;
97 else
98 CombineMethod := cmOptional;
99 end;
100
101 if CombineMethod <> cmOptional then
102 begin
103 // delete + or -
104 if Length( TermText ) = 1 then
105 if (i < tmpTerms.count-1) then
106 raise ESearchSyntaxError.Create( QueryErrorMissingWord1
107 + StrInDoubleQuotes(TermText)
108 + QueryErrorMissingWord2
109 + StrInDoubleQuotes(tmpTerms[i+1]) )
110 else
111 raise ESearchSyntaxError.Create( QueryErrorMissingWord1
112 + StrInDoubleQuotes(TermText));
113 Delete( TermText, 1, 1 );
114 end;
115
116 Term := TSearchTerm.Create( TermText,
117 CombineMethod );
118 Terms.Add( Term );
119 end;
120 tmpTerms.Destroy;
121 except
122 tmpTerms.Destroy;
123 Destroy; // clean up
124 raise; // reraise exception
125 end;
126end;
127
128destructor TTextSearchQuery.Destroy;
129begin
130 DestroyListObjects( Terms );
131 Terms.Destroy;
132end;
133
134function TTextSearchQuery.GetTerm( index: longint ): TSearchTerm;
135begin
136 Result := Terms[ Index ];
137end;
138
139function TTextSearchQuery.GetTermCount: longint;
140begin
141 Result := Terms.Count;
142end;
143
144constructor TSearchTerm.Create( const TheText: string;
145 const TheCombineMethod: TSearchTermCombineMethod );
146var
147 TermParseIndex: longint;
148 TermChar: char;
149 TermPart: string;
150begin
151 Parts := TStringList.Create;
152
153 Text := TheText;
154 CombineMethod := TheCombineMethod;
155
156 // Break out each part of the term as IPF does:
157 // consecutive alphanumeric chars become a "word"
158 // but each symbol is a separate word, and symbols break
159 // up alphanumerics into multiple words. e.g.
160 // CAKE_SAUSAGE becomes three words in IPF,
161 // one each for "CAKE" "_" and "SAUSAGE"
162
163 TermParseIndex := 1;
164 while TermParseIndex <= Length( Text ) do
165 begin
166 // collect alphanumeric chars
167 TermPart := '';
168 while TermParseIndex <= Length( Text ) do
169 begin
170 TermChar := Text[ TermParseIndex ];
171 if ( CharIsAlpha( TermChar )
172 or CharIsDigit( TermChar ) ) then
173 begin
174 // alpha numeric, collect it
175 TermPart := TermPart + TermChar;
176 inc( TermParseIndex );
177 end
178 else
179 begin
180 // not alpha numeric, so stop
181 break;
182 end;
183 end;
184 if Length( TermPart ) > 0 then
185 begin
186 Parts.Add( TermPart ); // add collected alphanumeric part
187 end;
188
189 if TermParseIndex <= Length( Text ) then
190 begin
191 // must be a symbol,
192 // each symbol (excluding space) is an individual item
193 if Text[ TermParseIndex ] <> ' ' then
194 Parts.Add( Text[ TermParseIndex ] );
195 inc( TermParseIndex );
196 end;
197
198 end;
199
200end;
201
202destructor TSearchTerm.Destroy;
203begin
204 Parts.Destroy;
205end;
206
207Initialization
208 RegisterProcForLanguages( OnLanguageEvent );
209End.
Note: See TracBrowser for help on using the repository browser.