1 /*
2  * This file is part of the FortranProject plugin for Code::Blocks IDE
3  * and licensed under the GNU General Public License, version 3
4  * http://www.gnu.org/licenses/gpl-3.0.html
5  *
6  * Author: Darius Markauskas
7  *
8  */
9 #include "ccsmartfilter.h"
10 
11 #ifndef CB_PRECOMP
12     #include <wx/string.h>
13 #endif
14 
15 #include "tokenf.h"
16 
GetTokenKind(wxArrayString & words,int & kindFilter,bool & allowVariables,kindOfCCList & kindCC)17 void CCSmartFilter::GetTokenKind(wxArrayString& words, int& kindFilter, bool& allowVariables, kindOfCCList& kindCC)
18 {
19     kindCC = kccOther;
20     allowVariables = false;
21     wxString wordLw;
22     wxString wordLastLw;
23     int woCount = words.GetCount();
24     if (woCount > 0)
25     {
26         wordLw = words.Item(0);
27         wordLastLw = words.Item(woCount-1);
28     }
29     if (woCount > 1)
30     {
31         if ( (wordLw.IsSameAs('(') && words.Item(1).IsSameAs(_T("type"))) ||
32              (wordLw.IsSameAs('(') && words.Item(1).IsSameAs(_T("extends"))) ||
33              (wordLw.IsSameAs('(') && words.Item(1).IsSameAs(_T("class"))))
34             wordLw.Prepend( words.Item(1) );
35     }
36 
37     if (woCount >= 2 && wordLastLw.IsSameAs(_T("!")) &&
38         words.Item(woCount-2).IsSameAs(_T("$")) )
39     {
40         if (woCount >= 3 &&
41             (words.Item(woCount-3).IsSameAs(_T("omp")) || words.Item(woCount-3).IsSameAs(_T("acc"))))
42         {
43             kindFilter = tkOther;
44             int idxa = words.Index(_T("("));
45             if (idxa != wxNOT_FOUND)
46             {
47                 int idxb = words.Index((_T(")")));
48                 if (idxb == wxNOT_FOUND || idxb > idxa)
49                     allowVariables = true;
50             }
51             return;
52         }
53         else
54         {
55             words.RemoveAt(words.GetCount()-1);
56             words.RemoveAt(words.GetCount()-1);
57             woCount = words.GetCount();
58             if (woCount > 0)
59             {
60                 wordLastLw = words.Item(woCount-1);
61             }
62             else
63             {
64                 wordLw = wxEmptyString;
65                 wordLastLw = wxEmptyString;
66             }
67         }
68     }
69 
70 
71     if (wordLw.IsEmpty())
72     {
73         kindFilter = tkOther;
74         allowVariables = true;
75     }
76     else if (wordLw.IsSameAs(_T("call")))
77     {
78         kindFilter = tkSubroutine | tkInterface;
79     }
80     else if (woCount > 1 &&
81              ( wordLastLw.IsSameAs(_T("generic")) || wordLastLw.IsSameAs(_T("procedure")) ||
82               ( wordLastLw.IsSameAs(_T("module")) && words.Item(woCount-2).IsSameAs(_T("procedure")) ) ))
83     {
84         kindFilter = tkSubroutine | tkFunction | tkInterface;
85         if (words.Index(_T(":")) == wxNOT_FOUND)
86             kindFilter = kindFilter | tkOther;
87     }
88     else if (wordLw.IsSameAs(_T("use")) || wordLw.IsSameAs(_T("module")))
89     {
90         kindFilter = tkModule;
91     }
92     else if (wordLw.IsSameAs(_T("module")))
93     {
94         kindFilter = tkModule | tkSubmodule;
95     }
96     else if (woCount == 1 && wordLw.IsSameAs(_T("endmodule")))
97     {
98         kindFilter = tkModule;
99     }
100     else if (wordLastLw.IsSameAs(_T("submodule")))
101     {
102         kindFilter = tkModule | tkSubmodule;
103     }
104     else if ((woCount == 2 && wordLastLw.IsSameAs(_T("end")) && wordLw.IsSameAs(_T("submodule"))) ||
105              (woCount == 1 && wordLw.IsSameAs(_T("endsubmodule"))))
106     {
107         kindFilter = tkSubmodule;
108     }
109     else if (woCount > 1 && wordLastLw.IsSameAs(_T("use")))
110     {
111         if (woCount > 2 && wordLw.IsSameAs(_T(":")) && words.Item(1).IsSameAs(_T(":")))
112         {
113             kindFilter = tkModule;
114         }
115         else
116         {
117             kindFilter = tkVariable | tkSubroutine | tkFunction | tkInterface | tkOther;
118             allowVariables = true;
119             kindCC = kccUseAssocTokens;
120         }
121     }
122     else if (wordLastLw.IsSameAs(_T("private")) ||
123              wordLastLw.IsSameAs(_T("public")) ||
124              wordLastLw.IsSameAs(_T("protected")) )
125     {
126         kindFilter = tkVariable | tkSubroutine | tkFunction | tkInterface | tkType | tkOther;
127         allowVariables = true;
128         kindCC = kccAccessList;
129     }
130     else if (wordLw.IsSameAs('=') || wordLw.IsSameAs('+') || wordLw.IsSameAs('-') || wordLw.IsSameAs('*') ||
131              wordLw.IsSameAs('/') || wordLw.IsSameAs('>') || wordLw.IsSameAs('<') || wordLw.IsSameAs('.'))
132     {
133         kindFilter = tkFunction | tkInterface;
134         allowVariables = true;
135     }
136     else if (woCount == 3 && wordLw.IsSameAs('(') && words.Item(1).IsSameAs(_T("is"))
137              && (words.Item(2).IsSameAs(_T("type")) || words.Item(2).IsSameAs(_T("class"))) )
138     {
139         kindFilter = tkType;
140     }
141     else if ((woCount == 2 && wordLastLw.IsSameAs(_T("allocate")) && wordLw.IsSameAs('('))
142              || (woCount == 5 && wordLastLw.IsSameAs(_T("allocate")) && wordLw.IsSameAs(':')))
143     {
144         if (woCount == 2 && wordLw.IsSameAs('('))
145         {
146             kindFilter = tkType;
147             allowVariables = true;
148         }
149         else // (woCount == 5 && wordLw.IsSameAs(':'))
150         {
151             kindFilter = tkVariable;
152             allowVariables = true;
153         }
154     }
155     else if (woCount >= 2 && words.Item(1).IsSameAs(_T("c_funloc")) && wordLw.IsSameAs('('))
156     {
157         kindFilter = tkSubroutine | tkFunction | tkInterface;
158     }
159     else if (woCount > 2 && words.Item(1).IsSameAs(_T("intent")) && wordLw.IsSameAs('('))
160     {
161         kindFilter = tkOther;
162         allowVariables = false;
163     }
164     else if (wordLw.IsSameAs('(') || wordLw.IsSameAs(','))
165     {
166         kindFilter = tkFunction | tkInterface | tkOther;
167         allowVariables = true;
168     }
169     else if ( wordLw.IsSameAs(_T("subroutine")) || wordLw.IsSameAs(_T("function")) || wordLw.IsSameAs(_T("interface"))
170              || wordLw.IsSameAs(_T("procedure")) )
171     {
172         kindFilter = tkSubroutine | tkFunction | tkInterface;
173     }
174     else if (woCount == 1 && wordLw.IsSameAs(_T("endsubroutine")))
175     {
176         kindFilter = tkSubroutine | tkInterface;
177     }
178     else if (woCount == 1 && wordLw.IsSameAs(_T("endfunction")))
179     {
180         kindFilter = tkFunction | tkInterface;
181     }
182     else if (wordLw.IsSameAs(_T("type")) || wordLw.IsSameAs(_T("type(")) || wordLw.IsSameAs(_T("extends("))
183              || wordLw.IsSameAs(_T("class(")))
184     {
185         kindFilter = tkType;
186     }
187     else if (wordLw.IsSameAs(';'))
188     {
189         kindFilter = tkOther;
190         allowVariables = true;
191     }
192     else if (woCount >= 3 && wordLw.IsSameAs(':') && words.Item(1).IsSameAs(_T(":")) &&
193               ((words.Item(woCount-1).IsSameAs(_T("type")) && words.Item(woCount-2).IsSameAs('('))  ||
194                (words.Item(woCount-1).IsSameAs(_T("class")) && words.Item(woCount-2).IsSameAs('(')) ||
195                 words.Item(woCount-1).IsSameAs(_T("integer")) ||
196                 words.Item(woCount-1).IsSameAs(_T("real"))    ||
197                 words.Item(woCount-1).IsSameAs(_T("logical")) ||
198                 words.Item(woCount-1).IsSameAs(_T("complex")) ||
199                 words.Item(woCount-1).IsSameAs(_T("character")) ))
200     {
201         kindFilter = tkVariable;
202         allowVariables = true;
203     }
204     else if (wordLw.IsSameAs(':'))
205     {
206         kindFilter = tkSubroutine | tkFunction | tkInterface;
207         allowVariables = true;
208     }
209     else if (wordLw.IsSameAs(_T("do")))
210     {
211         kindFilter = tkOther;
212         allowVariables = true;
213     }
214     else if (woCount > 1 && wordLw.IsSameAs(')') && (
215                 (wordLastLw.IsSameAs(_T("if")))
216              || (wordLastLw.IsSameAs(_T("read")))
217              || (wordLastLw.IsSameAs(_T("write"))) ))
218     {
219         kindFilter = tkOther | tkFunction | tkInterface;
220         allowVariables = true;
221     }
222     else if (wordLw.IsSameAs('['))
223     {
224         kindFilter = tkVariable;
225         allowVariables = true;
226     }
227     else
228     {
229         kindFilter = tkOther;
230     }
231 }
232 
FitsToContext(const wxString & kw,const wxArrayString & firstWords)233 bool CCSmartFilter::FitsToContext(const wxString& kw, const wxArrayString& firstWords)
234 {
235     static std::set<wxString> onlyFirstSet;
236     if (onlyFirstSet.size() == 0)
237     {
238         onlyFirstSet.insert(_T("contains"));
239         onlyFirstSet.insert(_T("double"));
240         onlyFirstSet.insert(_T("doubleprecision"));
241         onlyFirstSet.insert(_T("else"));
242         onlyFirstSet.insert(_T("elseif"));
243         onlyFirstSet.insert(_T("elsewhere"));
244         onlyFirstSet.insert(_T("enum"));
245         onlyFirstSet.insert(_T("end"));
246         onlyFirstSet.insert(_T("endassociate"));
247         onlyFirstSet.insert(_T("endblock"));
248         onlyFirstSet.insert(_T("endblockdata"));
249         onlyFirstSet.insert(_T("endcritical"));
250         onlyFirstSet.insert(_T("endenum"));
251         onlyFirstSet.insert(_T("endfile"));
252         onlyFirstSet.insert(_T("endforall"));
253         onlyFirstSet.insert(_T("endfunction"));
254         onlyFirstSet.insert(_T("endif"));
255         onlyFirstSet.insert(_T("endinterface"));
256         onlyFirstSet.insert(_T("endprocedure"));
257         onlyFirstSet.insert(_T("enddo"));
258         onlyFirstSet.insert(_T("endmodule"));
259         onlyFirstSet.insert(_T("endprogram"));
260         onlyFirstSet.insert(_T("endselect"));
261         onlyFirstSet.insert(_T("endsubmodule"));
262         onlyFirstSet.insert(_T("endsubroutine"));
263         onlyFirstSet.insert(_T("endteam"));
264         onlyFirstSet.insert(_T("endtype"));
265         onlyFirstSet.insert(_T("endwhere"));
266         onlyFirstSet.insert(_T("entry"));
267         onlyFirstSet.insert(_T("error"));
268         onlyFirstSet.insert(_T("equivalence"));
269         onlyFirstSet.insert(_T("final"));
270         onlyFirstSet.insert(_T("flush"));
271         onlyFirstSet.insert(_T("forall"));
272         onlyFirstSet.insert(_T("format"));
273         onlyFirstSet.insert(_T("if"));
274         onlyFirstSet.insert(_T("implicit"));
275         onlyFirstSet.insert(_T("include"));
276         onlyFirstSet.insert(_T("inquire"));
277         onlyFirstSet.insert(_T("module"));
278         onlyFirstSet.insert(_T("namelist"));
279         onlyFirstSet.insert(_T("nullify"));
280         onlyFirstSet.insert(_T("open"));
281         onlyFirstSet.insert(_T("print"));
282         onlyFirstSet.insert(_T("program"));
283     }
284 
285     bool kwFits = true;
286     wxString kwLw = kw.Lower();
287     int lenFW = firstWords.size();
288     wxArrayString fWL;
289     for (int i=0; i<lenFW; ++i) {
290         if (!firstWords[i].IsEmpty())
291             fWL.Add(firstWords[i]);
292     }
293     lenFW = fWL.size();
294 
295     if (lenFW >= 1 && fWL[lenFW-1] == _T("end"))
296     {
297         if (kwLw == _T("associate") || kwLw == _T("block") || kwLw == _T("data") || kwLw == _T("critical") ||
298             kwLw == _T("do") || kwLw == _T("enum") || kwLw == _T("forall") ||
299             kwLw == _T("function") || kwLw == _T("if") || kwLw == _T("interface") || kwLw == _T("module") ||
300             kwLw == _T("procedure") || kwLw == _T("program") || kwLw == _T("select") || kwLw == _T("submodule") ||
301             kwLw == _T("subroutine") || kwLw == _T("team") || kwLw == _T("type") || kwLw == _T("where"))
302         {
303             kwFits = true;
304         }
305         else
306             kwFits = false;
307     }
308     else if (lenFW > 0 && onlyFirstSet.count(kwLw) != 0)
309     {
310         kwFits = false;
311     }
312     else if (kwLw == _T("associate") || kwLw == _T("do") || kwLw == _T("change"))
313     {
314         if (lenFW == 0 || (lenFW > 0 && fWL[0] == _T(":")))
315             kwFits = true;
316         else
317             kwFits = false;
318     }
319     else if (lenFW == 1 && fWL[0] == _T("implicit"))
320     {
321         if (kwLw == _T("none") || kwLw == _T("real") || kwLw == _T("integer") ||
322             kwLw == _T("logical") || kwLw == _T("character") ||kwLw == _T("type"))
323             kwFits = true;
324         else
325             kwFits = false;
326     }
327     else if (lenFW >= 1 && fWL[0] == _T("do"))
328     {
329         if (kwLw == _T("concurrent") || kwLw == _T("while"))
330             kwFits = true;
331         else
332             kwFits = false;
333     }
334     else if (kwLw == _T("do"))
335     {
336         long label;
337         if ((lenFW == 1 && fWL[0].ToLong(&label)) ||
338             (lenFW == 2 && (fWL[0] == _T(":"))) ||
339             lenFW == 0)
340             kwFits = true;
341         else
342             kwFits = false;
343     }
344     else if (kwLw == _T("concurrent"))
345     {
346         if (lenFW >= 1 && fWL[0] == _T("do"))
347             kwFits = true;
348         else
349             kwFits = false;
350     }
351     else if (kwLw == _T("if"))
352     {
353         long label;
354         if ((lenFW == 1 && (fWL[0].ToLong(&label) || fWL[0] == _T("else"))) ||
355             (lenFW == 2 && (fWL[0] == _T(":"))) ||
356             lenFW == 0)
357             kwFits = true;
358         else
359             kwFits = false;
360     }
361     else if (kwLw == _T("allocate") || kwLw == _T("deallocate"))
362     {
363         if (lenFW == 0 || (lenFW > 0 && fWL[lenFW-1] == _T("if") && fWL[0] == _T(")")))
364             kwFits = true;
365         else
366             kwFits = false;
367     }
368     else if (kwLw == _T("apostrophe"))
369     {
370         if (lenFW > 0 && fWL[lenFW-1] == _T("open"))
371             kwFits = true;
372         else
373             kwFits = false;
374     }
375     else if (lenFW > 2 && fWL[0] == _T("(") && fWL[1] == _T("intent"))
376     {
377         if (kwLw == _T("in") || kwLw == _T("inout") || kwLw == _T("out"))
378             kwFits = true;
379         else
380             kwFits = false;
381     }
382     else if (lenFW >= 2 && (fWL[lenFW-1] == _T("real") || fWL[lenFW-1] == _T("integer") || fWL[lenFW-1] == _T("logical") ||
383                             fWL[lenFW-1] == _T("complex") || fWL[lenFW-1] == _T("character") ||
384                             (fWL[lenFW-1] == _T("double") && fWL[lenFW-2] == _T("precision")) || fWL[lenFW-1] == _T("doubleprecision") ||
385                             ((fWL[lenFW-1] == _T("type") || fWL[lenFW-1] == _T("class")) && fWL[lenFW-2] == _T("(")))  &&
386              !CCSmartFilter::hasWord(_T("::"), fWL))
387     {
388         if (kwLw == _T("allocatable") || kwLw == _T("dimension") || kwLw == _T("pointer") || kwLw == _T("target") ||
389             kwLw == _T("contiguous") || kwLw == _T("selected_char_kind") || kwLw == _T("selected_int_kind") ||
390             kwLw == _T("selected_real_kind") || kwLw == _T("codimension") || kwLw == _T("size") || kwLw == _T("shape") ||
391             kwLw == _T("intent") || kwLw == _T("optional") || kwLw == _T("save") || kwLw == _T("parameter") ||
392             kwLw == _T("private") || kwLw == _T("public"))
393         {
394             kwFits = true;
395         }
396         else if (lenFW > 2 && fWL[0] == _T("(") && fWL[1] == _T("intent"))
397         {
398             if (kwLw == _T("in") || kwLw == _T("inout") || kwLw == _T("out"))
399                 kwFits = true;
400             else
401                 kwFits = false;
402         }
403         else
404             kwFits = false;
405     }
406     else if (kwLw == _T("allocatable") || kwLw == _T("dimension") || kwLw == _T("pointer") || kwLw == _T("target") ||
407             kwLw == _T("contiguous") || kwLw == _T("codimension") ||
408             kwLw == _T("intent") || kwLw == _T("contiguous") || kwLw == _T("optional"))
409     {
410         // the above keywords can be only as variable declaration attribute
411         kwFits = false;
412     }
413     else if (kwLw == _T("stop"))
414     {
415         if (lenFW == 0 || (lenFW > 0 && (fWL[0] == _T(")") || fWL[0] == _T("error"))))
416             kwFits = true;
417         else
418             kwFits = false;
419     }
420     else if (kwLw == _T("then"))
421     {
422         if (lenFW >= 3 && fWL[0] == _T(")"))
423             kwFits = true;
424         else
425             kwFits = false;
426     }
427     else if (kwLw == _T("bind"))
428     {
429         if (lenFW >= 2 && (fWL[0] == _T(",") || fWL[0] == _T(")")))
430             kwFits = true;
431         else
432             kwFits = false;
433     }
434     else if (kwLw == _T("only"))
435     {
436         if (lenFW >= 2 && fWL[lenFW-1] == _T("use"))
437             kwFits = true;
438         else
439             kwFits = false;
440     }
441     else if (lenFW >= 4 && (fWL[lenFW-1] == _T("open") || fWL[lenFW-1] == _T("read") || fWL[lenFW-1] == _T("write")) &&
442              fWL[lenFW-2] == _T("(") && fWL[0] == _T("=") && fWL[1] == _T("delim"))
443     {
444         if (kwLw == _T("quote") || kwLw == _T("apostrophe") || kwLw == _T("none"))
445             kwFits = true;
446         else
447             kwFits = false;
448     }
449     else if (kwLw == _T("quote") || kwLw == _T("apostrophe"))
450     {
451         kwFits = false;
452     }
453     else if (lenFW >= 2 && fWL[lenFW-1] == _T("open") && fWL[lenFW-2] == _T("("))
454     {
455         if (kwLw == _T("unit") || kwLw == _T("access") || kwLw == _T("action") || kwLw == _T("asynchronous") ||
456             kwLw == _T("blank") || kwLw == _T("decimal") || kwLw == _T("delim") || kwLw == _T("encoding") ||
457             kwLw == _T("err") || kwLw == _T("file") || kwLw == _T("form") || kwLw == _T("iomsg") || kwLw == _T("iostat") ||
458             kwLw == _T("newunit") || kwLw == _T("pad") || kwLw == _T("position") || kwLw == _T("recl") ||
459             kwLw == _T("round") || kwLw == _T("sign") || kwLw == _T("status"))
460         {
461             kwFits = true;
462         }
463         else
464             kwFits = false;
465     }
466     else if (lenFW >= 2 && fWL[lenFW-1] == _T("inquiry") && fWL[lenFW-2] == _T("("))
467     {
468         if (kwLw == _T("unit") || kwLw == _T("file") || kwLw == _T("access") || kwLw == _T("action") || kwLw == _T("asynchronous") ||
469             kwLw == _T("blank") || kwLw == _T("decimal") || kwLw == _T("delim") || kwLw == _T("direct") || kwLw == _T("encoding") ||
470             kwLw == _T("err") || kwLw == _T("exist") || kwLw == _T("form") || kwLw == _T("formated") || kwLw == _T("id") ||
471             kwLw == _T("iomsg") || kwLw == _T("iostat") || kwLw == _T("name") || kwLw == _T("named") || kwLw == _T("nextrec") ||
472             kwLw == _T("number") || kwLw == _T("opened") || kwLw == _T("pad") || kwLw == _T("pending") || kwLw == _T("pos") ||
473             kwLw == _T("position") || kwLw == _T("read") || kwLw == _T("readwrite") || kwLw == _T("recl") ||
474             kwLw == _T("round") || kwLw == _T("sequential") || kwLw == _T("sign") || kwLw == _T("size") || kwLw == _T("stream") ||
475             kwLw == _T("unformated") || kwLw == _T("write"))
476         {
477             kwFits = true;
478         }
479         else
480             kwFits = false;
481     }
482     else if (lenFW >= 2 && fWL[lenFW-1] == _T("close") && fWL[lenFW-2] == _T("("))
483     {
484         if (kwLw == _T("unit") || kwLw == _T("iomsg") || kwLw == _T("iostat") ||
485             kwLw == _T("err") || kwLw == _T("status"))
486         {
487             kwFits = true;
488         }
489         else
490             kwFits = false;
491     }
492     else if (lenFW >= 2 && (fWL[lenFW-1] == _T("read") || fWL[lenFW-1] == _T("write")) && fWL[lenFW-2] == _T("("))
493     {
494         if (kwLw == _T("unit") || kwLw == _T("fmt") || kwLw == _T("nml") || kwLw == _T("advance") || kwLw == _T("asynchronous") ||
495             kwLw == _T("blank") || kwLw == _T("decimal") || kwLw == _T("delim") || kwLw == _T("end") || kwLw == _T("eor") ||
496             kwLw == _T("err") || kwLw == _T("id") || kwLw == _T("iomsg") || kwLw == _T("iostat") || kwLw == _T("pad") ||
497             kwLw == _T("pos") || kwLw == _T("rec") || kwLw == _T("round") || kwLw == _T("sign") || kwLw == _T("size"))
498         {
499             kwFits = true;
500         }
501         else
502             kwFits = false;
503     }
504     else if (kwLw == _T("access") || kwLw == _T("action") || kwLw == _T("asynchronous") ||
505             kwLw == _T("blank") || kwLw == _T("decimal") || kwLw == _T("delim") || kwLw == _T("encoding") ||
506             kwLw == _T("err") || kwLw == _T("file") || kwLw == _T("form") || kwLw == _T("iomsg") || kwLw == _T("iostat") ||
507             kwLw == _T("newunit") || kwLw == _T("pad") || kwLw == _T("position") || kwLw == _T("recl") ||
508             kwLw == _T("round") || kwLw == _T("status ") || kwLw == _T("unit") || kwLw == _T("file") ||
509             kwLw == _T("direct") || kwLw == _T("exist") || kwLw == _T("formated") || kwLw == _T("id") || kwLw == _T("name") ||
510             kwLw == _T("named") || kwLw == _T("nextrec") ||
511             kwLw == _T("number") || kwLw == _T("opened") || kwLw == _T("pending") || kwLw == _T("pos") || kwLw == _T("readwrite") ||
512             kwLw == _T("sequential") || kwLw == _T("stream") || kwLw == _T("unformated"))
513     {
514         // the above keywords can be only in open, close, inquire, write and read statements.
515         kwFits = false;
516     }
517     else if (kwLw == _T("sequence"))
518     {
519         if (lenFW == 0)
520             kwFits = true;
521         else
522             kwFits = false;
523     }
524     else if (lenFW >= 1 && fWL[lenFW-1] == _T("go"))
525     {
526         if (kwLw == _T("to"))
527             kwFits = true;
528         else
529             kwFits = false;
530     }
531     return kwFits;
532 }
533 
hasWord(const wxString & word,const wxArrayString & wordArr)534 bool CCSmartFilter::hasWord(const wxString& word, const wxArrayString& wordArr)
535 {
536     wxString str;
537     int wCount = wordArr.size();
538     for (int i=0; i<wCount; ++i)
539     {
540         str.Append(wordArr[i]);
541     }
542 
543     return (str.Find(word) != wxNOT_FOUND);
544 }
545