1 
2 #include "indentestimator.h"
3 
4 #include <sdk.h>
5 #ifndef CB_PRECOMP
6     #include <wx/tokenzr.h>
7     #include <configmanager.h>
8 #endif
9 
FormatIndentCodeTree()10 FormatIndentCodeTree::FormatIndentCodeTree()
11 {
12     Initialize(0);
13 }
14 
~FormatIndentCodeTree()15 FormatIndentCodeTree::~FormatIndentCodeTree()
16 {
17 
18 }
19 
Initialize(int firstLineIndent)20 void FormatIndentCodeTree::Initialize(int firstLineIndent)
21 {
22     m_Tree.clear();
23     m_RootIndent = firstLineIndent;
24 }
25 
GetCodeTreeIndent(CodeTreeKind iKind,int & myIndent)26 void FormatIndentCodeTree::GetCodeTreeIndent(CodeTreeKind iKind, int& myIndent)
27 {
28     if (iKind == ctcNone)
29         return;
30     else if (iKind == ctcAssociate || iKind == ctcCritical || iKind == ctcDoForall || iKind == ctcEnum ||
31              iKind == ctcFunction || iKind == ctcIfThen || iKind == ctcInterface || iKind == ctcProgramBlock ||
32              iKind == ctcModule || iKind == ctcSeclectCase || iKind == ctcSeclectType ||
33              iKind == ctcSubmodule || iKind == ctcSubroutine || iKind == ctcTypeDefine ||
34              iKind == ctcWhere)
35     {
36         treeNode tn;
37         tn.indent = myIndent;
38         tn.kind = iKind;
39         m_Tree.push_back(tn);
40         return;
41     }
42 
43     CodeTreeKind startKind1 = ctcNone;
44     CodeTreeKind startKind2 = ctcNone;
45     CodeTreeKind startKind3 = ctcNone;
46     CodeTreeKind startKind4 = ctcNone;
47     CodeTreeKind startKind5 = ctcNone;
48     if (iKind == ctcEndAssociate)
49         startKind1 = ctcAssociate;
50     else if (iKind == ctcEndCritical)
51         startKind1 = ctcCritical;
52     else if (iKind == ctcEndDoForall)
53         startKind1 = ctcDoForall;
54     else if (iKind == ctcEndEnum)
55         startKind1 = ctcEnum;
56     else if (iKind == ctcEndInterface)
57         startKind1 = ctcInterface;
58     else if (iKind == ctcEndProgramBlockSubFun)
59     {
60         startKind1 = ctcProgramBlock;
61         startKind2 = ctcSubroutine;
62         startKind3 = ctcFunction;
63     }
64     else if (iKind == ctcEndModule)
65         startKind1 = ctcModule;
66     else if (iKind == ctcEndSeclectCase)
67     {
68         startKind1 = ctcSeclectCase;
69         startKind2 = ctcSeclectType;
70     }
71     else if (iKind == ctcEndSubmodule)
72         startKind1 = ctcSubmodule;
73     else if (iKind == ctcEndTypeDefine)
74         startKind1 = ctcTypeDefine;
75     else if (iKind == ctcEndWhere)
76         startKind1 = ctcWhere;
77     else if (iKind == ctcEndIf)
78         startKind1 = ctcIfThen;
79     else if (iKind == ctcEnd)
80     {
81         startKind1 = ctcProgramBlock;
82         startKind2 = ctcSubroutine;
83         startKind3 = ctcFunction;
84         startKind4 = ctcModule;
85         startKind5 = ctcSubmodule;
86     }
87 
88     for (int i=int(m_Tree.size())-1; i >= 0; i--)
89     {
90         if ((m_Tree[i].kind == startKind1) ||
91             (m_Tree[i].kind == startKind2) ||
92             (m_Tree[i].kind == startKind3) ||
93             (m_Tree[i].kind == startKind4) ||
94             (m_Tree[i].kind == startKind5))
95         {
96             myIndent = m_Tree[i].indent;
97             m_Tree.resize(i);
98             break;
99         }
100     }
101 }
102 
GetParentKind()103 FormatIndentCodeTree::CodeTreeKind FormatIndentCodeTree::GetParentKind()
104 {
105     CodeTreeKind pK = ctcNone;
106     if (m_Tree.size() > 0)
107         pK = m_Tree[m_Tree.size()-1].kind;
108 
109     return pK;
110 }
111 
112 
113 
114 
115 //***************************************************************
116 //*
117 //***************************************************************
118 
DelFormatIndentRegEx()119 void IndentEstimator::DelFormatIndentRegEx()
120 {
121     if( m_RegEx.empty() )
122     {
123         return ;
124     }
125     FormatIndentRegEx::iterator it = m_RegEx.begin();
126     // iterate over all the Hash Map
127     while( it != m_RegEx.end() )
128     {
129         wxRegEx * pIt = it->second;
130         delete pIt;
131         ++it;
132     }
133     m_RegEx.clear();
134 }
135 
136 
CreateFormatIndentRegEx()137 void IndentEstimator::CreateFormatIndentRegEx()
138 {
139 	int options = wxRE_DEFAULT | wxRE_ADVANCED | wxRE_ICASE ;
140 
141 	DelFormatIndentRegEx();
142 
143 	m_RegEx[wxT("regexMultiLines")] = new wxRegEx( wxT("(&)((\r\n)|(\r)|(\n))?$"), options );
144 	m_RegEx[wxT("regexEndProgram")] = new wxRegEx( wxT("^(\\s*)(end)(\\s*)((program)|((block)(\\s*)(data))|(subroutine)|(function))((\\s+)([a-zA-Z0-9_]+))?((\\s*)!(.*))?(\\s*)$"), options );
145 	m_RegEx[wxT("regexProgram")] = new wxRegEx( wxT("^(\\s*)((program)|((block)(\\s*)(data)))((\\s+)([a-zA-Z0-9_]+))?((\\s*)!(.*))?(\\s*)$"), options );
146 	m_RegEx[wxT("regexEndModule")] = new wxRegEx( wxT("^(\\s*)(end)(\\s*)(module)((\\s+)([a-zA-Z0-9_]+))?((\\s*)!(.*))?(\\s*)$"), options );
147 	m_RegEx[wxT("regexModule")] = new wxRegEx( wxT("^(\\s*)(module)((\\s+)([a-zA-Z0-9_]+))?((\\s*)!(.*))?(\\s*)$"), options );
148 	m_RegEx[wxT("regexInterface")] = new wxRegEx( wxT("^(\\s*)((abstract)(\\s+))?(interface)((\\s+)(([a-zA-Z0-9_]+)|((assignment)(\\s*)\\((\\s*)(a+)(\\s*)\\))|((operator)(\\s*)\\((.+)\\))|((write|read)(\\s*)\\((.+)\\))))?((\\s*)!(.*))?(\\s*)$"), options );
149 	m_RegEx[wxT("regexEndInterface")] = new wxRegEx( wxT("^(\\s*)(end)(\\s*)(interface)((\\s+)(([a-zA-Z0-9_]+)|((assignment)(\\s*)\\((\\s*)(a+)(\\s*)\\))|((operator)(\\s*)\\((.+)\\))|((write|read)(\\s*)\\((.+)\\))))?((\\s*)!(.*))?(\\s*)$"), options );
150 	m_RegEx[wxT("regexContains")] = new wxRegEx( wxT("^(\\s*)(contains)((\\s*)!(.*))?(\\s*)$"), options );
151 	m_RegEx[wxT("regexSubroutine")] = new wxRegEx( wxT("^(\\s*)(((pure)|(impure)|(elemental)|(recursive)|(non_recursive)|(module))(\\s+))*((\\s+))?(subroutine)(\\s+)([a-zA-Z0-9_]+)((\\s*)(\\()(\\s*)(([a-zA-Z0-9_]+)((\\s*)(,)(\\s*)([a-zA-Z0-9_]+))*)?(\\s*)(\\))(\\s*))?"), options );
152 	m_RegEx[wxT("regexFunction")] = new wxRegEx( wxT("^(((.*)(\\s+))|(\\s*)){1}(function)(\\s+)([a-zA-Z0-9_]+)(\\s*)\\((\\s*)(([a-zA-Z0-9_]+)((\\s*)(,)(\\s*)([a-zA-Z0-9_]+))*)?(\\s*)\\)"), options );
153 	m_RegEx[wxT("regexType")] = new wxRegEx( wxT("^(\\s*)((type)(\\s*)(\\()(\\s*)([a-zA-Z0-9_]+)(\\s*)(\\)))(\\s*)"), options );
154 	m_RegEx[wxT("regexTypeDefine")] = new wxRegEx( wxT("^(\\s*)((type)\\M((\\s*),(\\s*)((public)|(private)|(protected)))?((\\s*),(\\s*)((abstract)|((extends)(\\s*)\\((\\s*)([a-zA-Z0-9_]+)(\\s*)\\))))?((\\s*),(\\s*)((bind)(\\s*)\\((\\s*)([a-z0-9_]+)(\\s*)\\)))?((\\s*)(::)?(\\s*)([a-zA-Z0-9_]+)))(\\s*)"), options );
155 	m_RegEx[wxT("regexEndType")] = new wxRegEx( wxT("^(\\s*)(end)(\\s*)(type)((\\s+)([a-zA-Z0-9_]+))?(\\s*)"), options );
156 	m_RegEx[wxT("regexEndDo")] = new wxRegEx( wxT("^(\\s*)(end)(\\s*)((do)|(forall))((\\s+)([a-zA-Z0-9_]+))?(\\s*)"), options );
157 	m_RegEx[wxT("regexDo")] = new wxRegEx( wxT("^(\\s*)(([a-zA-Z0-9_]+)(\\s*)(:)(\\s*))?(do)((\\s+)([a-zA-Z0-9_])(.+))?((\\s*)!(.*))?(\\s*)$"), options );
158 	m_RegEx[wxT("regexForall")] = new wxRegEx( wxT("^([\\s\\t]*)([0-9]*)([\\s\\t]*)(([a-z0-9_]+)(\\s*)(:)(\\s*))?((forall)|((do)(\\s+)(while)))(\\s*)(\\([^\\)]+\\))(\\s*)$"), options );
159 	m_RegEx[wxT("regexEndSelect")] = new wxRegEx( wxT("^(\\s*)(end)(\\s*)(select)((\\s+)([a-zA-Z0-9_]+))?(\\s*)"), options );
160 	m_RegEx[wxT("regexSelectCase")] = new wxRegEx( wxT("^(\\s*)(([a-zA-Z0-9_]+)(\\s*)(:)(\\s*))?((select)(\\s*)(case))(\\s*)(\\()(.+)(\\))((\\s*)!(.*))?(\\s*)$"), options );
161 	m_RegEx[wxT("regexSelectType")] = new wxRegEx( wxT("^(\\s*)(([a-zA-Z0-9_]+)(\\s*)(:)(\\s*))?((select)(\\s*)(type))(\\s*)(\\()(.+)(\\))((\\s*)!(.*))?(\\s*)$"), options );
162 	m_RegEx[wxT("regexCase")] = new wxRegEx( wxT("^(\\s*)((((case)|(((type)|(class))(\\s+)(is)))(\\s*)(\\()(.+)(\\))((\\s+)([a-zA-Z0-9_]+))?)|(((case)|(class))(\\s+)(default)((\\s+)([a-zA-Z0-9_]+))?))((\\s*)!(.*))?(\\s*)$"), options );
163 	m_RegEx[wxT("regexIfThen")] = new wxRegEx( wxT("^(\\s*)(([a-zA-Z0-9_]+)(\\s*)(:)(\\s*))?((if)(\\s*)(\\()(.+)(\\))(\\s*)(then))((\\s*)!(.*))?(\\s*)$"), options );
164 	m_RegEx[wxT("regexElse")] = new wxRegEx( wxT("^(\\s*)(else)(\\s*)(((\\s+)([a-zA-Z0-9_]+))|((if)(\\s*)(\\()(.+)(\\))(\\s*)(then)((\\s+)([a-zA-Z0-9_]+))?))?((\\s*)!(.*))?(\\s*)$"), options );
165 	m_RegEx[wxT("regexEndIf")] = new wxRegEx( wxT("^(\\s*)(end)(\\s*)(if)((\\s+)([a-zA-Z0-9_]+))?(\\s*)"), options );
166 	m_RegEx[wxT("regexWhere")] = new wxRegEx( wxT("^([\\s\\t]*)([0-9]*)([\\s\\t]*)(([a-z0-9_]+)(\\s*)(:)(\\s*))?(where)(\\s*)(\\([^\\)]+\\))(\\s*)$"), options );
167 	m_RegEx[wxT("regexElseWhere")] = new wxRegEx( wxT("^(\\s*)(else)(\\s*)(where)(((\\s+)([a-zA-Z0-9_]+))|((\\s*)\\((.+)\\)((\\s+)([a-zA-Z0-9_]+))?))?((\\s*)!(.*))?(\\s*)$"), options );
168 	m_RegEx[wxT("regexEndWhere")] = new wxRegEx( wxT("^(\\s*)(end)(\\s*)(where)((\\s+)([a-zA-Z0-9_]+))?(\\s*)"), options );
169 	m_RegEx[wxT("regexEndOnly")] = new wxRegEx( wxT("^(\\s*)(end)((\\s*)!(.*))?(\\s*)$"), options );
170 
171 	m_RegEx[wxT("regexAssociate")] = new wxRegEx( wxT("^(\\s*)(([a-zA-Z0-9_]+)(\\s*)(:)(\\s*))?(associate)(\\s*)\\((.+)\\)((\\s*)!(.*))?(\\s*)$"), options );
172 	m_RegEx[wxT("regexEndAssociate")] = new wxRegEx( wxT("^(\\s*)(end)(\\s*)(associate)((\\s+)([a-zA-Z0-9_]+))?((\\s*)!(.*))?(\\s*)$"), options );
173 
174 	m_RegEx[wxT("regexCritical")] = new wxRegEx( wxT("^(\\s*)(([a-zA-Z0-9_]+)(\\s*)(:)(\\s*))?((block)|(critical))((\\s*)!(.*))?(\\s*)$"), options );
175 	m_RegEx[wxT("regexEndCritical")] = new wxRegEx( wxT("^(\\s*)(end)(\\s*)((block)|(critical))((\\s+)([a-zA-Z0-9_]+))?((\\s*)!(.*))?(\\s*)$"), options );
176 
177 	m_RegEx[wxT("regexSubmodule")] = new wxRegEx( wxT("^(\\s*)(([a-zA-Z0-9_]+)(\\s*)(:)(\\s*))?((submodule)(\\s*)\\((.+)\\)(\\s*)([a-zA-Z0-9_]+))((\\s*)!(.*))?(\\s*)$"), options );
178 	m_RegEx[wxT("regexEndSubmodule")] = new wxRegEx( wxT("^(\\s*)(end)(\\s*)(submodule)((\\s+)([a-zA-Z0-9_]+))?((\\s*)!(.*))?(\\s*)$"), options );
179 
180 	m_RegEx[wxT("regexModuleProcedure")] = new wxRegEx( wxT("^(\\s*)(module(\\s*)procedure)(\\s*)([a-zA-Z0-9_]+)((\\s*)!(.*))?(\\s*)$"), options );
181 	m_RegEx[wxT("regexEndProcedure")] = new wxRegEx( wxT("^(\\s*)(end)(\\s*)(procedure)((\\s+)([a-zA-Z0-9_]+))?((\\s*)!(.*))?(\\s*)$"), options );
182 
183 	m_RegEx[wxT("regexEnum")] = new wxRegEx( wxT("^(\\s*)(enum)((\\s*),(\\s*)((bind)(\\s*)\\((\\s*)([a-zA-Z0-9_]+)(\\s*)\\)))((\\s*)!(.*))?(\\s*)$"), options );
184 	m_RegEx[wxT("regexEndEnum")] = new wxRegEx( wxT("^(\\s*)(end)(\\s*)(enum)((\\s*)!(.*))?(\\s*)$"), options );
185 
186 	m_RegEx[wxT("regexComment")] = new wxRegEx( wxT("(!(.*))((\r\n)|(\r)|(\n))?$"), options | wxRE_NEWLINE );
187 
188 	m_RegEx[wxT("regexBlankLine")] = new wxRegEx( wxT("([ \t]+)((\r\n)|(\r)|(\n))"), options | wxRE_NEWLINE );
189 
190 	m_RegEx[wxT("regexPreprocessorC")] = new wxRegEx( wxT("^#(define|undef|ifdef|ifndef|if|elif|else|endif|include|error|warning|line)"), options );
191 
192 }
193 
194 
Initialize(int firstLineIndent)195 void IndentEstimator::Initialize(int firstLineIndent)
196 {
197     m_CodeTree.Initialize(firstLineIndent);
198 }
199 
200 
GetFortranIndentLine(const wxString & src1,int & indentNum,int & indentNumNext)201 void IndentEstimator::GetFortranIndentLine(const wxString& src1, int& indentNum, int& indentNumNext)
202 {
203     indentNumNext = indentNum;
204     wxArrayString srcLines;
205     PrepareLine(src1, srcLines); // for case if several statements on one line
206     for (size_t i=0; i<srcLines.size(); i++)
207     {
208         int deltaIndentCur;
209         int deltaIndentNext;
210         FormatIndentCodeTree::CodeTreeKind iKind;
211         CalcFortranIndentLine(srcLines.Item(i), deltaIndentCur, deltaIndentNext, iKind);
212         if (i == 0)
213         {
214             indentNum += deltaIndentCur;
215             m_CodeTree.GetCodeTreeIndent(iKind, indentNum);
216         }
217 
218         if (i+1 == srcLines.size())
219         {
220             m_CodeTree.GetCodeTreeIndent(iKind, indentNum);
221             indentNumNext = indentNum + deltaIndentNext;
222         }
223     }
224 }
225 
226 
CalcFortranIndentLine(const wxString & srcLine,int & deltaIndentCur,int & deltaIndentNext,FormatIndentCodeTree::CodeTreeKind & iKind)227 void IndentEstimator::CalcFortranIndentLine( const wxString & srcLine, int & deltaIndentCur, int & deltaIndentNext, FormatIndentCodeTree::CodeTreeKind & iKind )
228 {
229     // module program subroutine function forall
230     // Add a shiftwidth to statements following module, program, subroutine,
231     // function and forall statements
232     //Manager::Get()->GetLogManager()->Log( src1 );
233 
234     iKind = FormatIndentCodeTree::ctcNone;
235 
236     deltaIndentCur = 0;
237     deltaIndentNext = 0;
238 
239     wxString src = srcLine;
240     src.Trim(true); // trim from right
241 
242     // Program, Interface, Bblock Data, Subroutine, Function
243     if ( m_RegEx[wxT("regexEndProgram")]->Matches( src ) )
244     {
245         iKind = FormatIndentCodeTree::ctcEndProgramBlockSubFun;
246         if (m_IndentProgFunSub)
247             deltaIndentCur = -1;
248         else
249             deltaIndentCur = 0;
250         deltaIndentNext = 0;
251     }
252     else if ( m_RegEx[wxT("regexEndInterface")]->Matches( src ) )
253     {
254         iKind = FormatIndentCodeTree::ctcEndInterface;
255         deltaIndentCur = -1;
256         deltaIndentNext = 0;
257     }
258 	else if ( m_RegEx[wxT("regexInterface")]->Matches( src ) )
259     {
260         iKind = FormatIndentCodeTree::ctcInterface;
261         deltaIndentCur = 0;
262         deltaIndentNext = 1;
263     }
264     else if ( m_RegEx[wxT("regexSubroutine")]->Matches( src ) )
265     {
266         iKind = FormatIndentCodeTree::ctcSubroutine;
267         deltaIndentCur = 0;
268         if (m_IndentProgFunSub)
269             deltaIndentNext = 1;
270         else
271             deltaIndentNext = 0;
272     }
273     else if ( m_RegEx[wxT("regexFunction")]->Matches( src ) )
274     {
275         iKind = FormatIndentCodeTree::ctcFunction;
276         deltaIndentCur = 0;
277         if (m_IndentProgFunSub)
278             deltaIndentNext = 1;
279         else
280             deltaIndentNext = 0;
281     }
282     else if ( m_RegEx[wxT("regexProgram")]->Matches( src ) )
283     {
284         iKind = FormatIndentCodeTree::ctcProgramBlock;
285         deltaIndentCur = 0;
286         if (m_IndentProgFunSub)
287             deltaIndentNext = 1;
288         else
289             deltaIndentNext = 0;
290         return ;
291     }
292     else if ( m_RegEx[wxT("regexEndModule")]->Matches( src ) )
293     {
294         iKind = FormatIndentCodeTree::ctcEndModule;
295         if (m_IndentModule)
296             deltaIndentCur = -1;
297         else
298             deltaIndentCur = 0;
299         deltaIndentNext = 0;
300     }
301     else if ( m_RegEx[wxT("regexModule")]->Matches( src ) )
302     {
303         iKind = FormatIndentCodeTree::ctcModule;
304         deltaIndentCur = 0;
305         if (m_IndentModule)
306             deltaIndentNext = 1;
307         else
308             deltaIndentNext = 0;
309     }
310     else if ( m_RegEx[wxT("regexContains")]->Matches( src ) )
311     {
312         FormatIndentCodeTree::CodeTreeKind pk = m_CodeTree.GetParentKind();
313 
314         if (pk == FormatIndentCodeTree::ctcModule ||
315             pk == FormatIndentCodeTree::ctcSubmodule)
316         {
317             if (m_IndentContainsModule)
318                 deltaIndentCur = -1;
319             if (m_IndentContainsModuleAfter)
320                 deltaIndentNext = 1;
321         }
322         else if (pk == FormatIndentCodeTree::ctcSubroutine ||
323                  pk == FormatIndentCodeTree::ctcFunction ||
324                  pk == FormatIndentCodeTree::ctcProgramBlock)
325         {
326             if (m_IndentContainsProcedure)
327                 deltaIndentCur = -1;
328             if (m_IndentContainsProcedureAfter)
329                 deltaIndentNext = 1;
330         }
331         else if (pk == FormatIndentCodeTree::ctcTypeDefine)
332         {
333             if (m_IndentContainsTypedef)
334                 deltaIndentCur = -1;
335             if (m_IndentContainsTypedefAfter)
336                 deltaIndentNext = 1;
337         }
338         else // could it be?
339         {
340             deltaIndentCur = -1;
341             deltaIndentNext = 1;
342         }
343     }
344     else if ( m_RegEx[wxT("regexEndDo")]->Matches( src ) )
345     {
346         // do while # end do
347         // forall() # end forall
348         // Indent do loops only if they are all guaranteed to be of do/end do type
349         iKind = FormatIndentCodeTree::ctcEndDoForall;
350         deltaIndentCur = -1;
351         deltaIndentNext = 0;
352     }
353     else if ( m_RegEx[wxT("regexDo")]->Matches( src ) )
354     {
355         iKind = FormatIndentCodeTree::ctcDoForall;
356         deltaIndentCur = 0;
357         deltaIndentNext = 1;
358     }
359     else if ( m_RegEx[wxT("regexForall")]->Matches( src ) )
360     {
361         iKind = FormatIndentCodeTree::ctcDoForall;
362         deltaIndentCur = 0;
363         deltaIndentNext = 1;
364     }
365     else if ( m_RegEx[wxT("regexEndSelect")]->Matches( src ) )
366     {
367         // select case # case | case dafault # end select
368         iKind = FormatIndentCodeTree::ctcEndSeclectCase;
369         deltaIndentCur = -2;
370         deltaIndentNext = 0;
371     }
372     else if ( m_RegEx[wxT("regexSelectCase")]->Matches( src ) )
373     {
374         iKind = FormatIndentCodeTree::ctcSeclectCase;
375         deltaIndentCur = 0;
376         if (m_IndentSelectCaseAfter)
377             deltaIndentNext = 2;
378         else
379             deltaIndentNext = 1;
380     }
381     else if ( m_RegEx[wxT("regexSelectType")]->Matches( src ) )
382     {
383         iKind = FormatIndentCodeTree::ctcSeclectType;
384         deltaIndentCur = 0;
385         if (m_IndentSelectTypeAfter)
386             deltaIndentNext = 2;
387         else
388             deltaIndentNext = 1;
389     }
390     else if ( m_RegEx[wxT("regexCase")]->Matches( src ) )
391     {
392         deltaIndentCur = -1;
393         deltaIndentNext = 1;
394     }
395     else if ( m_RegEx[wxT("regexIfThen")]->Matches( src ) )
396     {
397         // if ## if then # else # end if
398         iKind = FormatIndentCodeTree::ctcIfThen;
399         deltaIndentCur = 0;
400         deltaIndentNext = 1;
401     }
402     else if ( m_RegEx[wxT("regexElse")]->Matches( src ) )
403     {
404         deltaIndentCur = -1;
405         deltaIndentNext = 1;
406     }
407     else if ( m_RegEx[wxT("regexEndIf")]->Matches( src ) )
408     {
409         iKind = FormatIndentCodeTree::ctcEndIf;
410         deltaIndentCur = -1;
411         deltaIndentNext = 0;
412     }
413     else if ( m_RegEx[wxT("regexWhere")]->Matches( src ) )
414     {
415         // where elsewhere
416         iKind = FormatIndentCodeTree::ctcWhere;
417         deltaIndentCur = 0;
418         deltaIndentNext = 1;
419     }
420     else if ( m_RegEx[wxT("regexElseWhere")]->Matches( src ) )
421     {
422         deltaIndentCur = -1;
423         deltaIndentNext = 1;
424     }
425     else if ( m_RegEx[wxT("regexEndWhere")]->Matches( src ) )
426     {
427         iKind = FormatIndentCodeTree::ctcEndWhere;
428         deltaIndentCur = -1;
429         deltaIndentNext = 0;
430     }
431     else if ( m_RegEx[wxT("regexEndType")]->Matches( src ) )
432     {
433         iKind = FormatIndentCodeTree::ctcEndTypeDefine;
434         deltaIndentCur = -1;
435         deltaIndentNext = 0;
436     }
437     else if ( ( false == m_RegEx[wxT("regexType")]->Matches( src ) ) &&
438             ( m_RegEx[wxT("regexTypeDefine")]->Matches( src ) ) )
439     {
440         iKind = FormatIndentCodeTree::ctcTypeDefine;
441         deltaIndentCur = 0;
442         deltaIndentNext = 1;
443     }
444     else if ( m_RegEx[wxT("regexEndAssociate")]->Matches( src ) )
445     {
446         iKind = FormatIndentCodeTree::ctcEndAssociate;
447         deltaIndentCur = -1;
448         deltaIndentNext = 0;
449     }
450 	else if ( m_RegEx[wxT("regexAssociate")]->Matches( src ) )
451     {
452         iKind = FormatIndentCodeTree::ctcAssociate;
453         deltaIndentCur = 0;
454         deltaIndentNext = 1;
455     }
456     else if ( m_RegEx[wxT("regexEndCritical")]->Matches( src ) )
457     {
458         iKind = FormatIndentCodeTree::ctcEndCritical;
459         deltaIndentCur = -1;
460         deltaIndentNext = 0;
461     }
462 	else if ( m_RegEx[wxT("regexCritical")]->Matches( src ) )
463     {
464         iKind = FormatIndentCodeTree::ctcCritical;
465         deltaIndentCur = 0;
466         deltaIndentNext = 1;
467     }
468 	else if ( m_RegEx[wxT("regexSubmodule")]->Matches( src ) )
469     {
470         iKind = FormatIndentCodeTree::ctcSubmodule;
471         deltaIndentCur = 0;
472         if (m_IndentModule)
473             deltaIndentNext = 1;
474         else
475             deltaIndentNext = 0;
476     }
477 	else if ( m_RegEx[wxT("regexEndSubmodule")]->Matches( src ) )
478     {
479         iKind = FormatIndentCodeTree::ctcEndSubmodule;
480         if (m_IndentModule)
481             deltaIndentCur = -1;
482         else
483             deltaIndentCur = 0;
484         deltaIndentNext = 0;
485     }
486     else if ( m_RegEx[wxT("regexEndEnum")]->Matches( src ) )
487     {
488         iKind = FormatIndentCodeTree::ctcEndEnum;
489         deltaIndentCur = -1;
490         deltaIndentNext = 0;
491     }
492 	else if ( m_RegEx[wxT("regexEnum")]->Matches( src ) )
493     {
494         iKind = FormatIndentCodeTree::ctcEnum;
495         deltaIndentCur = 0;
496         deltaIndentNext = 1;
497     }
498     else if ( m_RegEx[wxT("regexEndOnly")]->Matches( src ) )
499     {
500         iKind = FormatIndentCodeTree::ctcEnd;
501         deltaIndentCur = -1;
502         deltaIndentNext = 0;
503     }
504     else if ( m_RegEx[wxT("regexModuleProcedure")]->Matches( src ) &&
505               m_CodeTree.GetParentKind() == FormatIndentCodeTree::ctcSubmodule )
506     {
507         iKind = FormatIndentCodeTree::ctcModuleProcedure;
508         deltaIndentCur = 0;
509         if (m_IndentProgFunSub)
510             deltaIndentNext = 1;
511         else
512             deltaIndentNext = 0;
513     }
514     else if ( m_RegEx[wxT("regexEndProcedure")]->Matches( src ) )
515     {
516         iKind = FormatIndentCodeTree::ctcEndProcedure;
517         if (m_IndentProgFunSub)
518             deltaIndentCur = -1;
519         else
520             deltaIndentCur = 0;
521         deltaIndentNext = 0;
522     }
523 
524 
525 
526 }
527 
528 // Special code to compare strings which doesn't care
529 // about spaces leading up to the EOL.
BuffersDiffer(const wxString & a,const wxString & b)530 bool IndentEstimator::BuffersDiffer( const wxString &a, const wxString &b )
531 {
532     wxString acopy = a;
533     acopy.Replace(_T("\r\n"), _T("\n"));
534     acopy.Replace(_T("\r"), _T("\n"));
535     wxStringTokenizer aTokenizer(acopy, _T("\n"), wxTOKEN_RET_EMPTY_ALL);
536     std::vector<wxString> aLines;
537     while (aTokenizer.HasMoreTokens())
538         aLines.push_back(aTokenizer.GetNextToken());
539 
540     wxString bcopy = b;
541     bcopy.Replace(_T("\r\n"), _T("\n"));
542     bcopy.Replace(_T("\r"), _T("\n"));
543     wxStringTokenizer bTokenizer(bcopy, _T("\n"), wxTOKEN_RET_EMPTY_ALL);
544     std::vector<wxString> bLines;
545     while (bTokenizer.HasMoreTokens())
546         bLines.push_back(bTokenizer.GetNextToken());
547 
548     size_t aSize = aLines.size();
549     if(aSize != bLines.size())
550         return true;
551 
552     for (size_t i=0; i<aSize; i++)
553     {
554         wxString aLin = aLines[i];
555         aLin.Trim();
556         wxString bLin = bLines[i];
557         bLin.Trim();
558         if (aLin != bLin)
559             return true;
560     }
561     return false;
562 }
563 
GetIsHasLineContinuation(const wxString & srcLine)564 bool IndentEstimator::GetIsHasLineContinuation( const wxString & srcLine )
565 {
566     wxASSERT( m_RegEx[wxT("regexMultiLines")] );
567     return m_RegEx[wxT("regexMultiLines")]->Matches( srcLine );
568 }
569 
570 
DelLineContinuation(wxString & srcLine)571 void IndentEstimator::DelLineContinuation( wxString & srcLine )
572 {
573     wxASSERT( m_RegEx[wxT("regexMultiLines")] );
574     m_RegEx[wxT("regexMultiLines")]->ReplaceAll( &srcLine, wxT("") );
575 }
576 
577 
DelComment(wxString & srcLine)578 void IndentEstimator::DelComment( wxString & srcLine )
579 {
580     wxASSERT( m_RegEx[wxT("regexComment")] );
581     m_RegEx[wxT("regexComment")]->ReplaceAll( &srcLine, wxT("") );
582 }
583 
GetIsHasPreprocessor(const wxString & srcLine)584 bool IndentEstimator::GetIsHasPreprocessor(const wxString & srcLine)
585 {
586     bool bRet = false;
587     wxASSERT( m_RegEx[wxT("regexPreprocessorC")] );
588     bRet = m_RegEx[wxT("regexPreprocessorC")]->Matches( srcLine );
589 
590     return bRet;
591 }
592 
PrepareLine(const wxString & srcIn,wxArrayString & srcLines)593 void IndentEstimator::PrepareLine(const wxString& srcIn, wxArrayString& srcLines)
594 {
595     wxString src = srcIn;
596     CutStringAndComment(src);
597 
598     wxStringTokenizer tokenizer(src, _T(";"), wxTOKEN_STRTOK);
599     while (tokenizer.HasMoreTokens())
600     {
601         wxString token = tokenizer.GetNextToken();
602         srcLines.Add(token);
603     }
604 
605 }
606 
CutStringAndComment(wxString & src)607 void IndentEstimator::CutStringAndComment(wxString& src)
608 {
609     src.Trim(false);
610 
611     while(true)
612     {
613         int i1 = src.Find('\'');
614         int j1 = src.Find('"');
615         char curChar;
616         if (i1 != wxNOT_FOUND && j1 != wxNOT_FOUND)
617             curChar = i1<j1 ? '\'' : '"';
618         else if (i1 != wxNOT_FOUND)
619             curChar = '\'';
620         else if (j1 != wxNOT_FOUND)
621             curChar = '"';
622         else
623             break;
624 
625         i1 = src.Find(curChar);
626         if (i1 != wxNOT_FOUND)
627         {
628             wxString str2 = src.Mid(i1+1);
629             int i2 = str2.Find(curChar);
630             if (i2 != wxNOT_FOUND)
631                 src = src.Mid(0,i1) + _T("$_$") + str2.Mid(i2+1);
632             else
633                 src = src.Mid(0,i1);
634         }
635         else
636             break;
637     }
638 
639     src.Replace(_T("$_$"), _T("\" \""));
640     src = src.BeforeFirst('!').Trim();
641     if (src.IsEmpty())
642         return;
643 
644     //Replace inside parentheses
645     int istart = -1;
646     int level = 0;
647     for (size_t i=0; i<src.size(); i++)
648     {
649         if (src[i] == '(')
650         {
651             if (level == 0)
652                 istart = i;
653             level++;
654         }
655         else if (src[i] == ')')
656         {
657             level--;
658             if (level == 0)
659             {
660                 for (size_t j=istart+1; j<i; j++)
661                     src.SetChar(j, 'a');
662             }
663         }
664     }
665 }
666 
ReadConfig()667 void IndentEstimator::ReadConfig()
668 {
669     ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("fortran_project"));
670 
671     m_IndentProgFunSub = cfg->ReadBool(_T("/indent_prog_fun_sub_after"), true);
672     m_IndentModule = cfg->ReadBool(_T("/indent_module_after"), true);
673     m_IndentContainsModule = cfg->ReadBool(_T("/indent_contains_module"), true);
674     m_IndentContainsModuleAfter = cfg->ReadBool(_T("/indent_contains_module_after"), true);
675     m_IndentContainsProcedure = cfg->ReadBool(_T("/indent_contains_procedure"), true);
676     m_IndentContainsProcedureAfter = cfg->ReadBool(_T("/indent_contains_procedure_after"), true);
677     m_IndentContainsTypedef = cfg->ReadBool(_T("/indent_contains_typedef"), true);
678     m_IndentContainsTypedefAfter = cfg->ReadBool(_T("/indent_contains_typedef_after"), true);
679     m_IndentSelectCaseAfter = cfg->ReadBool(_T("/indent_selectcase_after"), true);
680     m_IndentSelectTypeAfter = cfg->ReadBool(_T("/indent_selecttype_after"), true);
681 }
682 
683 
684