update for HEAD-2003091401
[reactos.git] / subsys / system / explorer / Seashell / SeaShellExt / TextParse.cpp
1 //*******************************************************************************
2 // COPYRIGHT NOTES
3 // ---------------
4 // You may use this source code, compile or redistribute it as part of your application 
5 // for free. You cannot redistribute it as a part of a software development 
6 // library without the agreement of the author. If the sources are 
7 // distributed along with the application, you should leave the original 
8 // copyright notes in the source code without any changes.
9 // This code can be used WITHOUT ANY WARRANTIES at your own risk.
10 // 
11 // For the latest updates to this code, check this site:
12 // http://www.masmex.com 
13 // after Sept 2000
14 // 
15 // Copyright(C) 2000 Philip Oldaker <email: philip@masmex.com>
16 //*******************************************************************************
17
18 #include "stdafx.h"
19 #include "TextParse.h"
20
21 CTextParse::CTextParse()
22 {
23         m_szBuffer[0] = '\0';
24         m_pStartLine = m_szBuffer;
25         m_pLine = m_szBuffer;
26         m_pSavePos = m_szBuffer;
27 }
28
29 CTextParse::CTextParse(LPCTSTR pszLine)
30 {
31         m_szBuffer[0] = '\0';
32         Set(pszLine);
33 }
34
35 CTextParse::~CTextParse()
36 {
37 }
38
39 CTextParse::CTextParse(const CTextParse &tp)
40 {
41         m_pLine = tp.m_pLine;
42         m_pStartLine = tp.m_pStartLine;
43         m_pSavePos = tp.m_pSavePos;
44         m_szCopyBuf[0] = '\0';
45         m_szBuffer[0] = '\0';
46         _tcscpy(m_szCopyBuf,tp.m_szCopyBuf);
47         _tcscpy(m_szBuffer,tp.m_szBuffer);
48 }
49
50 const CTextParse& CTextParse::operator=(LPCTSTR lpsz)
51 {
52         Set(lpsz);
53         m_szCopyBuf[0] = '\0';
54         m_szBuffer[0] = '\0';
55         return *this;
56 }
57
58 const CTextParse& CTextParse::operator=(const CTextParse &tp)
59 {
60         if (*this == tp)
61                 return *this;
62         m_pLine = tp.m_pLine;
63         m_pStartLine = tp.m_pStartLine;
64         m_pSavePos = tp.m_pSavePos;
65         _tcscpy(m_szCopyBuf,tp.m_szCopyBuf);
66         _tcscpy(m_szBuffer,tp.m_szBuffer);
67         return *this;
68 }
69
70 BOOL CTextParse::CharExistFromCurPos(int c,BOOL bForward)
71 {
72         LPCTSTR p = m_pLine;
73         if (bForward) 
74         {
75                 while (*p && *p != c)
76                            p = _tcsinc(p);
77         }
78         else
79         {
80                 while (p > m_pStartLine && *p != c)
81                            p = _tcsdec(m_pLine,p);
82         }
83         return *p == c;
84 }
85
86 BOOL CTextParse::ValidCppCharExist(int c,BOOL bForward)
87 {
88         LPCTSTR p = m_pLine;
89         while (*p && *p != c && *p != '/')
90                    p = _tcsinc(p);
91         return *p == c;
92 }
93
94 BOOL CTextParse::CharExist(LPCTSTR str)
95 {
96         LPCTSTR p = m_pStartLine;
97         while (*p && !IsToken(str,p))
98                    p = _tcsinc(p);
99         return *p != '\0';
100 }
101
102 BOOL CTextParse::FindString(LPCTSTR str)
103 {
104         LPCTSTR p = _tcsstr(m_pLine,str);
105         if (p)
106                 m_pLine = p;
107         return p ? TRUE : FALSE;
108 }
109
110 BOOL CTextParse::FindChar(int c)
111 {
112         LPCTSTR p = _tcschr(m_pLine,c);
113         if (p)
114                 m_pLine = p;
115         return p ? TRUE : FALSE;
116 }
117
118 BOOL CTextParse::MoveUntilChar(int c,BOOL bForward)
119 {
120         if (bForward) 
121         {
122                 while(*m_pLine && *m_pLine != c)
123                            m_pLine = _tcsinc(m_pLine);
124                 return *m_pLine != '\0';
125         }
126         else 
127         {
128                 while(m_pLine > m_pStartLine && *m_pLine != c)
129                            m_pLine = _tcsdec(m_pStartLine,m_pLine);
130                 return *m_pLine == c;
131         }
132 }
133
134 BOOL CTextParse::MoveUntilChar(LPCTSTR strTok,BOOL bForward)
135 {
136         if (bForward) 
137         {
138                 while(*m_pLine && !IsToken(strTok,m_pLine))
139                            m_pLine = _tcsinc(m_pLine);
140                 return *m_pLine != '\0';
141         }
142         else 
143         {
144                 while(m_pLine > m_pStartLine && !IsToken(strTok,m_pLine))
145                            m_pLine = _tcsdec(m_pStartLine,m_pLine);
146                 return IsToken(strTok,m_pLine);
147         }
148 }
149
150 BOOL CTextParse::MoveUntilString(LPCTSTR str,BOOL bForward)
151 {
152         if (bForward) 
153         {
154                 while(*m_pLine && !IsString(str))
155                            m_pLine = _tcsinc(m_pLine);
156                 return *m_pLine != '\0';
157         }
158         else
159         {
160                 while(m_pLine > m_pStartLine && !IsString(str))
161                            m_pLine = _tcsdec(m_pStartLine,m_pLine);
162                 return IsString(str);
163         }
164 }
165
166 BOOL CTextParse::MoveWhileChar(int c,BOOL bForward)
167 {
168         if (bForward) 
169         {
170                 while(*m_pLine && *m_pLine == c)
171                            m_pLine = _tcsinc(m_pLine);
172                 return *m_pLine != '\0';
173         }
174         else
175         {
176                 while(m_pLine > m_pStartLine && *m_pLine == c)
177                            m_pLine = _tcsdec(m_pStartLine,m_pLine);
178                 return *m_pLine == c;
179         }
180 }
181
182 BOOL CTextParse::MoveWhileChar(LPCTSTR strTok,BOOL bForward)
183 {
184         if (bForward) 
185         {
186                 while(*m_pLine && IsToken(strTok,m_pLine))
187                            m_pLine = _tcsinc(m_pLine);
188                 return *m_pLine != '\0';
189         }
190         else
191         {
192                 while(m_pLine > m_pStartLine && IsToken(strTok,m_pLine))
193                            m_pLine = _tcsdec(m_pStartLine,m_pLine);
194                 return IsToken(strTok,m_pLine);
195         }
196 }
197
198 LPCTSTR CTextParse::CopyWhileChar(int c)
199 {
200         for(int i=0;i < MAX_BUF && *m_pLine != '\0' && *m_pLine == c;i++)
201         {
202                 m_szCopyBuf[i] = *m_pLine;
203                 m_pLine = _tcsinc(m_pLine);
204         }
205         m_szCopyBuf[i] = '\0';
206         return m_szCopyBuf;
207 }
208
209 LPCTSTR CTextParse::CopyUntilString(LPCTSTR pszText)
210 {
211         int nLen = _tcslen(pszText);
212         for(int i=0;i < MAX_BUF && *m_pLine != '\0' && _tcsncmp(m_pLine,pszText,nLen) != 0;i++)
213         {
214                 m_szCopyBuf[i] = *m_pLine;
215                 m_pLine = _tcsinc(m_pLine);
216         }
217         m_szCopyBuf[i] = '\0';
218         return m_szCopyBuf;
219 }
220
221 LPCTSTR CTextParse::CopyUntilChar(int c)
222 {
223         for(int i=0;i < MAX_BUF && *m_pLine != '\0' && *m_pLine != c;i++)
224         {
225                 m_szCopyBuf[i] = *m_pLine;
226                 m_pLine = _tcsinc(m_pLine);
227         }
228         m_szCopyBuf[i] = '\0';
229         return m_szCopyBuf;
230 }
231
232 LPCTSTR CTextParse::CopyWhileChar(LPCTSTR strTok)
233 {
234         for(int i=0;i < MAX_BUF && *m_pLine != '\0' && IsToken(strTok,m_pLine);i++)
235         {
236                 m_szCopyBuf[i] = *m_pLine;
237                 m_pLine = _tcsinc(m_pLine);
238         }
239         m_szCopyBuf[i] = '\0';
240         return m_szCopyBuf;
241 }
242
243 LPCTSTR CTextParse::CopyUntilChar(LPCTSTR strTok)
244 {
245         for(int i=0;i < MAX_BUF && *m_pLine != '\0' && !IsToken(strTok,m_pLine);i++)
246         {
247                 m_szCopyBuf[i] = *m_pLine;
248                 m_pLine = _tcsinc(m_pLine);
249         }
250         m_szCopyBuf[i] = '\0';
251         return m_szCopyBuf;
252 }
253
254 LPCTSTR CTextParse::CopyFuncUntilChar(LPCTSTR strTok)
255 {
256         for(int i=0;i < MAX_BUF && !IsEnd() && !IsToken(strTok,m_pLine);i++) 
257         {
258 /*              if (*m_pLine == '=') {
259                         MoveUntilChar(",)");
260                         if (m_szCopyBuf[i-1] == ' ') {
261                                 i--;
262                         }
263                 }*/
264                 if (CharAtCurrent('/')) 
265                 {
266                         MoveForward();
267                         MoveUntilChar(_T("/"));
268                         if (m_szCopyBuf[i-1] == ' ') 
269                         {
270                                 i--;
271                             MoveForward();
272                         }
273                 }
274                 m_szCopyBuf[i] = *m_pLine;
275                 MoveForward();
276         }
277         m_szCopyBuf[i] = '\0';
278         return m_szCopyBuf;
279 }
280
281 BOOL CTextParse::IsToken(LPCTSTR strTok,LPCTSTR p)
282 {
283         while(*strTok) 
284         {
285                   if (*p == *strTok)
286                           break;
287                    strTok = _tcsinc(strTok);
288         }
289         return *strTok != '\0';
290 }
291
292 LPCTSTR CTextParse::ExtractConstructor()
293 {
294         MoveUntilChar('(');
295         CopyUntilChar(')');
296         _tcscat(m_szCopyBuf,_T(")"));
297         return m_szCopyBuf;
298 }
299
300 LPCTSTR CTextParse::ExtractDeclareMacro()
301 {
302         return CopyUntilChar('(');
303 }
304
305 LPCTSTR CTextParse::ExtractFuncName()
306 {
307         Reset();
308         // skip keywords
309         if (_tcsncmp(m_pLine,_T("const"),5) == 0 || _tcsncmp(m_pLine,_T("afx_msg"),7) == 0 || _tcsncmp(m_pLine,_T("virtual"),7) == 0) 
310         {
311                 CopyUntilWhiteSpace();
312                 MoveWhileWhiteSpace();
313         }
314         MoveUntilChar(_T("("));
315         MoveUntilWhiteSpace(FALSE);
316         if (*m_pLine == CPP_SPACE) // regular function
317                 MoveWhileWhiteSpace();
318         else
319         { // else constructor or destructor
320                 // allow for virtual destructors
321                 if (_tcsncmp(m_pLine,_T("virtual"),7) == 0)
322                 {
323                         CopyUntilWhiteSpace();
324                         MoveWhileWhiteSpace();
325                 }
326                 Reset();
327         }
328         // returning pointer or reference
329         if (*m_pLine == '*' || *m_pLine == '&')
330            m_pLine = _tcsinc(m_pLine);
331         return CopyUntilChar('(');      
332 }
333
334 LPCTSTR CTextParse::ExtractClassName()
335 {
336         MoveWhileWhiteSpace();
337         if (_tcsncmp(m_pLine,_T("class"),5) != 0)
338         {
339                 m_szCopyBuf[0] = 0;
340                 return m_szCopyBuf;
341         }
342         Reset();
343         // check if derived class
344         if (!CharExistFromCurPos(':'))
345         {
346                 if (!CharExistFromCurPos('{'))
347                 {
348                         MoveToLastChar();
349                         MoveWhileWhiteSpace(FALSE);
350                         MoveUntilWhiteSpace(FALSE);
351                         MoveWhileWhiteSpace();
352                 }
353                 else
354                 {
355                         MoveUntilChar('{');
356                         MoveUntilWhiteSpace(FALSE);
357                         MoveWhileWhiteSpace(FALSE);                     
358                         MoveUntilWhiteSpace(FALSE);
359                         MoveWhileWhiteSpace();                  
360                 }
361         }
362         else
363         {
364                 MoveUntilChar(':');
365                 // go back and skip colon
366                 MoveUntilWhiteSpace(FALSE);
367                 MoveWhileWhiteSpace(FALSE);
368                 if (CharAtCurrent('>'))
369                 {
370                         MoveUntilChar('<',FALSE);
371                         MoveUntilWhiteSpace(FALSE);
372                         MoveWhileWhiteSpace(FALSE);
373                 }
374                 MoveUntilWhiteSpace(FALSE);
375                 MoveWhileWhiteSpace();
376         }
377         return CopyUntilChar(_T(" \t<"));       
378 }
379
380 LPCTSTR CTextParse::ExtractBaseClassName()
381 {
382         Reset();
383         MoveWhileWhiteSpace();
384         if (_tcsncmp(m_pLine,_T("class"),5) != 0)
385         {
386                 m_szCopyBuf[0] = 0;
387                 return m_szCopyBuf;
388         }
389         Reset();
390         // check if derived class
391         if (CharExistFromCurPos(':'))
392         {
393                 MoveUntilChar(':');
394                 // go back
395                 MoveWhileChar(':');             
396                 MoveWhileWhiteSpace();
397                 MoveUntilWhiteSpace();
398                 MoveWhileWhiteSpace();
399         }
400         else
401         {
402                 m_szCopyBuf[0] = 0;
403                 return m_szCopyBuf;
404         }
405         return CopyUntilChar(_T(" \t<"));       
406 }
407
408 BOOL CTextParse::IsCommentBlock(LPCTSTR strStart,LPCTSTR strEnd)
409 {
410         LPCTSTR p = _tcsstr(m_pLine,strStart);
411         if (p)
412         {
413                 if (p == m_pStartLine && *(p+sizeof(TCHAR)*2) == '+')
414                         return FALSE;
415                 if (p == m_pStartLine || (p != m_pStartLine && *(p-sizeof(TCHAR)) != '/') ) 
416                 {
417                         if (_tcsstr(m_pLine,strEnd) == NULL)
418                                 return TRUE;
419                 }
420         }
421         return FALSE;
422 }
423
424 LPCTSTR CTextParse::CopyWholeWord()
425 {
426         bool bQuote=false;
427         for(int i=0;i < MAX_BUF && *m_pLine != '\0';i++) 
428         {
429                 if (*m_pLine == '"') 
430                 {
431                         bQuote = !bQuote;
432                 }
433                 else if (*m_pLine == ' ' && bQuote == false)
434                 {
435                         break;
436                 }
437                 m_szCopyBuf[i] = *m_pLine;
438                 m_pLine = _tcsinc(m_pLine);
439         }
440         SkipWhiteSpace();
441         m_szCopyBuf[i] = '\0';
442         return m_szCopyBuf;
443 }
444
445 LPCTSTR CTextParse::CopyUntilEnd()
446 {
447         for(int i=0;i < MAX_BUF && *m_pLine != '\0';i++) 
448         {
449                 m_szCopyBuf[i] = *m_pLine;
450                 m_pLine = _tcsinc(m_pLine);
451         }
452         m_szCopyBuf[i] = '\0';
453         return m_szCopyBuf;
454 }
455
456 bool CTextParse::FindWholeWord(LPCTSTR pszText)
457 {
458         bool bQuote = _tcsstr(pszText,_T("\"")) != NULL;
459         if (*pszText == '+' || *pszText == '-')
460                 pszText = _tcsinc(pszText);
461         int nLen = _tcslen(pszText);
462         int nRet=-1;
463         for(int i=0;i < MAX_BUF && *m_pLine != '\0';i++) 
464         {
465                 SkipWhiteSpace();
466                 if (*m_pLine == '"')
467                 {
468                         if (bQuote == true) 
469                         {
470                                 nRet = _tcsncmp(m_pLine,pszText,nLen);
471                                 if (nRet == 0)
472                                         break;
473                         }
474                         MoveWhileChar('"');
475                         MoveUntilChar('"');
476                         MoveWhileChar('"');
477                 }
478                 else
479                 {
480                         nRet = _tcsncmp(m_pLine,pszText,GetWordLen());
481                         if (nRet == 0)
482                                 break;
483                         SkipWord();
484                 }
485         }
486         return nRet == 0;
487 }
488
489 int CTextParse::GetWordLen()
490 {
491         LPCTSTR p = m_pLine;
492         for (int i=0;*p && !IsToken(CPP_WHITE_SPACE,p);i++)
493         {
494                 p++;
495         }
496         return i;
497 }
498
499 bool CTextParse::SkipHTMLCommand(bool bSkipCRLF)
500 {
501         if (CharAtCurrent('&'))
502         {
503                 MoveUntilChar(';');
504                 if (CharAtCurrent(';'))
505                         MoveForward();
506                 return true;
507         }
508         LPCTSTR p = m_pLine;
509         if (bSkipCRLF)
510         {
511                 while (*p == '\r' || *p == '\n')
512                         p = _tcsinc(p);
513         }
514         if (*p != '<')
515                 return false;
516         while (*p != '>' && *p != '\0')
517                         p = _tcsinc(p);
518         if (*p == '>')
519                 p = _tcsinc(p);
520         m_pLine = p;
521         return true;
522 }
523
524 void CTextParse::SkipHTMLCommands(bool bSkipCRLF)
525 {
526         while (SkipHTMLCommand(bSkipCRLF))
527                 ;
528 }
529
530 BOOL CTextParse::IsValidCPP(LPCTSTR pszText)
531 {
532         BOOL bRet=FALSE;
533         if (FindString(pszText))
534         {
535                 // check if a comment
536                 SaveCurPos();
537                 if (!MoveUntilString(_T("//"),FALSE))
538                 {
539                         RestorePos();
540                         if (!MoveUntilString(_T("/*"),FALSE))
541                                 bRet = TRUE;
542                 }
543         }
544         Reset();
545         return bRet;
546 }
547
548 BOOL CTextParse::IsPrivate()
549 {
550         return IsValidCPP(_T("private"));
551 }
552
553 BOOL CTextParse::IsPublic()
554 {
555         return IsValidCPP(_T("public"));
556 }
557
558 BOOL CTextParse::IsProtected()
559 {
560         return IsValidCPP(_T("protected"));
561 }
562
563 BOOL CTextParse::IsVirtualFunc()
564 {
565         return IsValidCPP(_T("virtual"));
566 }
567
568 BOOL CTextParse::IsStartBrace()
569 {
570         return IsValidCPP(_T("{"));
571 }
572
573 BOOL CTextParse::IsEndBrace()
574 {
575         return IsValidCPP(_T("}"));
576 }
577
578 BOOL CTextParse::IsAccessSpecifier()
579 {
580         return IsValidCPP(_T(":"));
581 }
582
583 BOOL CTextParse::IsConstructor(LPCTSTR pszClassName)
584 {
585         CString sTest(pszClassName);
586         sTest += _T("(");
587         if (FindChar('~'))
588         {
589                 Reset();
590                 return FALSE;
591         }
592         return IsValidCPP(sTest);
593 }
594
595 BOOL CTextParse::IsMsgMap()
596 {
597         return FindString(_T("{{AFX_MSG"));
598 }
599
600 BOOL CTextParse::IsDeclareMacro()
601 {
602         BOOL bRet = FALSE;
603         if (IsValidCPP(_T("DECLARE_")))
604         {
605                 if (!FindString(_T("()")))
606                         bRet = TRUE;
607                 Reset();
608         }
609         return bRet;
610 }
611
612 BOOL CTextParse::IsStartCommentBlock()
613 {
614         if (!FindString(_T("//")))
615                 return FindString(_T("/*"));
616         return FALSE;
617 }
618
619 BOOL CTextParse::IsEndCommentBlock()
620 {
621         return FindString(_T("*/"));
622 }
623
624 BOOL CTextParse::IsClass()
625 {
626         BOOL bRet=TRUE;
627         if (FindString(_T("template")))
628         {
629                 bRet = FALSE;
630         }
631         if (!StringAtCurrent(_T("class ")))
632         {
633                 bRet = FALSE;
634         }
635         Reset();
636         // any line comments before 'class '
637         MoveUntilString(_T("class "));
638         if (MoveUntilString(_T("//"),FALSE))
639         {
640                 bRet = FALSE;           
641         }
642         Reset();
643         if (FindChar(_T(';')))
644         {
645                 bRet = FALSE;
646         }
647         if (FindChar(_T('#')))
648         {
649                 bRet = FALSE;
650         }
651         Reset();
652         return bRet;
653 }
654
655 BOOL CTextParse::ExtractArgs(CString &sRet,CStringArray &asArgs)
656 {
657         asArgs.RemoveAll();
658         SaveCurPos();
659         if (!CharAtCurrent('(') && FindChar('('))
660         {
661                 RestorePos();
662                 SkipWhiteSpace();
663                 if (StringAtCurrent(_T("const")))
664                 {
665                         MoveUntilWhiteSpace();                  
666                         SkipWhiteSpace();
667                 }
668                 sRet = CopyUntilWhiteSpace();
669                 if (MoveUntilChar('('))
670                 {
671                         MoveForward();
672                 }
673                 else
674                 {
675                         RestorePos();
676                 }
677         }
678         while (!CharAtCurrent(')') && !IsEnd())
679         {
680                 SkipWhiteSpace();
681                 if (StringAtCurrent(_T("const")))
682                 {
683                         MoveUntilWhiteSpace();                  
684                         SkipWhiteSpace();
685                 }
686                 MoveUntilWhiteSpace();
687                 SkipWhiteSpace();
688                 if (StringAtCurrent(_T("void")))
689                         break;
690                 if (CharAtCurrent('*') || CharAtCurrent('&'))
691                         MoveForward();
692                 asArgs.Add(CopyUntilChar(_T(",)\t ")));
693                 if (CharAtCurrent(','))
694                         MoveForward();
695                 else
696                         SkipWhiteSpace();
697         }
698         return TRUE;
699 }
700
701 LPCTSTR CTextParse::ExtractHTMLText(bool bRemoveCRLF)
702 {
703         return ExtractHTMLText(_T("<"),bRemoveCRLF);
704 }
705
706 LPCTSTR CTextParse::ExtractHTMLText(LPCTSTR pszUntil,bool bRemoveCRLF)
707 {
708         int nLen=_tcslen(pszUntil);
709         int i=0;
710         bool bEnd = false;
711         while(i < MAX_BUF && *m_pLine != '\0' && _tcsncmp(m_pLine,pszUntil,nLen) != 0)
712         {
713                 if (*m_pLine == '<' || *m_pLine == '&')
714                 {
715                         while (SkipHTMLCommand(false))
716                         {
717                                 if (_tcsncmp(m_pLine,pszUntil,nLen) == 0)
718                                 {
719                                         bEnd = true;
720                                         break;
721                                 }
722                         }
723                 }
724                 if (bEnd)
725                         break;
726                 if (bRemoveCRLF && (*m_pLine == '\n' || *m_pLine == '\r'))
727                 {
728                         m_pLine = _tcsinc(m_pLine);
729                 }
730                 else
731                 {
732                         m_szCopyBuf[i++] = *m_pLine;
733                         m_pLine = _tcsinc(m_pLine);
734                 }
735         }
736         m_szCopyBuf[i] = '\0';
737         return m_szCopyBuf;
738 }
739
740 LPCTSTR CTextParse::ExtractHTMLLink()
741 {
742         m_szCopyBuf[0] = '\0';
743         if (!FindString(_T("href=")))
744                 return m_szCopyBuf;
745         MoveUntilChar('"');
746         LPCTSTR p = m_pLine;
747         if (*p == '"')
748         {
749                 p = _tcsinc(p);
750                 m_pLine = p;
751                 LPCTSTR pRet = CopyUntilChar('"');
752                 MoveUntilChar('>');
753                 MoveWhileChar('>');
754                 return pRet;
755         }
756         return m_szCopyBuf;
757 }
758