1
2 #include "formatindent.h"
3
4 #ifndef CB_PRECOMP
5 #include <wx/tokenzr.h>
6
7 #include <projectmanager.h>
8 #include <cbproject.h>
9 #include <editormanager.h>
10 #include <configmanager.h>
11 #include "cbeditor.h"
12 #endif
13 #include <vector>
14
15 #include "formatindentdlg.h"
16 #include "fortranfileext.h"
17
18 extern FortranFileExt g_FortranFileExt;
19
20 // constructor
FormatIndent()21 FormatIndent::FormatIndent()
22 {
23 }
24
25 // destructor
~FormatIndent()26 FormatIndent::~FormatIndent()
27 {
28 }
29
Format()30 void FormatIndent::Format()
31 {
32 FormatIndentDlg fidlg(Manager::Get()->GetAppWindow());
33 if (fidlg.ShowModal() == wxID_OK)
34 {
35 FormatIndentDlg::FormatIndentScope scope;
36 scope = fidlg.GetFormatScope();
37 if (scope == FormatIndentDlg::fisProject)
38 FormatProject();
39 else if (scope == FormatIndentDlg::fisCurrentFile)
40 FormatActiveFile();
41 else
42 FormatSelection();
43 }
44 }
45
FormatProject()46 void FormatIndent::FormatProject()
47 {
48 cbProject* project = Manager::Get()->GetProjectManager()->GetActiveProject();
49 if (!project)
50 {
51 cbMessageBox(_("No active project was found!"), _("Error"), wxICON_ERROR);
52 return;
53 }
54
55 wxArrayString nonFFiles;
56 for (FilesList::iterator it = project->GetFilesList().begin(); it != project->GetFilesList().end(); ++it)
57 {
58 ProjectFile* pf = *it;
59 FortranSourceForm fsForm;
60 bool isF = g_FortranFileExt.IsFileFortran(pf->file.GetFullPath(), fsForm);
61 if (isF && fsForm == fsfFree)
62 FormatFile(pf->file.GetFullPath());
63 else
64 nonFFiles.Add(pf->file.GetFullName());
65 }
66
67 if (nonFFiles.size() > 0)
68 {
69 wxString mstr;
70 if (nonFFiles.size() == 1)
71 {
72 mstr = _("File \"") + nonFFiles[0] + _("\" was not recognized as a free-form Fortran file.");
73 mstr << _(" The indent formating was not applied for it.");
74 }
75 else
76 {
77 mstr = _("Files");
78 size_t i=0;
79 size_t imax=5;
80 while (i < nonFFiles.size() && i < imax)
81 {
82 mstr << _("\n\"") << nonFFiles[i] << _T("\"");
83 i++;
84 }
85 if (nonFFiles.size() > imax)
86 mstr << _T("...\n");
87 else
88 mstr << _T("\n");
89 mstr << wxString::Format(_T("(%d "), int(nonFFiles.size())) << _("files) ");
90 mstr << _("were not recognized as the free-form Fortran files.");
91 mstr << _(" The indent formating was not applied for them.");
92 cbMessageBox(mstr, _("Info"), wxICON_INFORMATION);
93 }
94 }
95 }
96
FormatActiveFile()97 void FormatIndent::FormatActiveFile()
98 {
99 if (!Manager::Get()->GetEditorManager())
100 return;
101 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
102 if (!ed)
103 return;
104 cbStyledTextCtrl* control = ed->GetControl();
105 if( wxSCI_LEX_FORTRAN != control->GetLexer() )
106 {
107 if( cbMessageBox( wxT("Are you sure \n") + ed->GetFilename() +
108 wxT("\nis a Fortran Free Format Source File?\nContinue to Format the Indent?"), _("Error Message"),
109 wxICON_QUESTION | wxYES_NO | wxNO_DEFAULT ) != wxID_YES )
110 return;
111 }
112
113 FormatFile(ed->GetFilename());
114 }
115
FormatFile(const wxString & filename)116 void FormatIndent::FormatFile(const wxString &filename)
117 {
118 cbEditor* ed = Manager::Get()->GetEditorManager()->IsBuiltinOpen(filename);
119 bool wasOpened = true;
120
121 if (!ed)
122 {
123 // File is not open. We must open it.
124 ed = Manager::Get()->GetEditorManager()->Open(filename);
125 if (!ed)
126 return;
127 wasOpened = false;
128 }
129
130 cbStyledTextCtrl* control = ed->GetControl();
131 if (control->GetReadOnly())
132 {
133 cbMessageBox(_("The file is read-only!"), _("Error"), wxICON_ERROR);
134 return;
135 }
136
137 wxString eolChars = GetEOLChars(control);
138
139 ReadConfig();
140 const int pos_cur = control->GetCurrentPos();
141 wxString text = control->GetText();
142 wxString formattedText;
143 FormatText(text, 0, eolChars, formattedText);
144
145 bool changed = m_IndentEstimator.BuffersDiffer(formattedText, text);
146 if (changed)
147 {
148 ReplaceTextInEditor(formattedText, false, control);
149 control->GotoPos(pos_cur);
150 }
151 else if (!changed && !wasOpened)
152 Manager::Get()->GetEditorManager()->Close(filename);
153
154 }
155
FormatSelection()156 void FormatIndent::FormatSelection()
157 {
158 if (!Manager::Get()->GetEditorManager())
159 return;
160 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
161 if (!ed)
162 return;
163 cbStyledTextCtrl* control = ed->GetControl();
164 if (control->GetReadOnly())
165 {
166 cbMessageBox(_("The file is read-only!"), _("Error"), wxICON_ERROR);
167 return;
168 }
169
170 ReadConfig();
171 int pos_selStart = control->GetSelectionStart();
172 int pos_selEnd = control->GetSelectionEnd();
173 int indexLineStart = 0, indexLineEnd = 0;
174 int nLines = control->GetLineCount();
175
176 if( pos_selStart != pos_selEnd )
177 {
178 indexLineStart = control->LineFromPosition( pos_selStart );
179 control->GotoLine( indexLineStart );
180 pos_selStart = control->GetCurrentPos();
181 indexLineEnd = control->LineFromPosition( pos_selEnd );
182 if( indexLineEnd == nLines )
183 {
184 control->GotoLine(indexLineEnd);
185 control->LineEnd();
186 }
187 else
188 {
189 control->GotoLine(indexLineEnd + 1);
190 }
191 pos_selEnd = control->GetCurrentPos();
192 control->SetSelectionStart(pos_selStart);
193 control->SetSelectionEnd(pos_selEnd);
194 wxString text = control->GetTextRange(pos_selStart, pos_selEnd);
195 wxString eolChars = GetEOLChars(control);
196
197 nLines = indexLineEnd + 1;
198 int indentW = ed->GetLineIndentInSpaces( indexLineStart );
199 int tabW = control->GetTabWidth();
200 int indentNum = indentW / tabW;
201 if( (indentW % tabW) > 0 )
202 indentNum++;
203
204 wxString formattedText;
205 FormatText(text, indentNum, eolChars, formattedText);
206
207 bool changed = m_IndentEstimator.BuffersDiffer(formattedText, text);
208 if (changed)
209 {
210 ReplaceTextInEditor(formattedText, true, control);
211 }
212 }
213 }
214
ReadConfig()215 void FormatIndent::ReadConfig()
216 {
217 ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("fortran_project"));
218 if (cfg->ReadBool(_T("/indent_same_as_editor"), true))
219 {
220 cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
221 if (!ed)
222 return;
223 cbStyledTextCtrl* control = ed->GetControl();
224 if (!control)
225 return;
226 if (control->GetUseTabs())
227 m_IndentStr = _T("\t");
228 else
229 {
230 int tabWidth = control->GetTabWidth();
231 m_IndentStr = wxString(_T(' '), tabWidth);
232 }
233 }
234 else
235 {
236 if (cfg->ReadBool(_T("/indent_use_tabs"), false))
237 m_IndentStr = _T("\t");
238 else
239 {
240 int tabWidth = cfg->ReadInt(_T("/indent_tab_width"), 4);
241 m_IndentStr = wxString(_T(' '), tabWidth);
242 }
243 }
244 m_TrimFromRight = cfg->ReadBool(_T("/indent_trim_right"), true);
245
246 m_IndentEstimator.ReadConfig();
247 }
248
FormatText(const wxString & textIn,int indentStart,const wxString & eolChars,wxString & formattedText)249 void FormatIndent::FormatText(const wxString& textIn, int indentStart, const wxString& eolChars, wxString& formattedText)
250 {
251 wxString str = textIn;
252 str.Replace(_T("\r\n"), _T("\n"));
253 str.Replace(_T("\r"), _T("\n"));
254 wxStringTokenizer tokenizer(str, _T("\n"), wxTOKEN_RET_EMPTY_ALL);
255 std::vector<wxString> textLines;
256 while (tokenizer.HasMoreTokens())
257 textLines.push_back(tokenizer.GetNextToken());
258
259 int indentNum = indentStart;
260 int nLines = textLines.size();
261
262
263 m_IndentEstimator.Initialize(indentNum);
264
265 IsMultiLines isMultiLines;
266 wxString tmpLine;
267 wxString tmpMultiLines;
268
269 int indentNumNext;
270
271 ///formattedText
272 for(int i=0; i < nLines; ++i)
273 {
274 tmpLine = textLines[i];
275
276 if(m_IndentEstimator.GetIsHasPreprocessor(tmpLine))
277 {
278 if (!isMultiLines.haveMultiLines)
279 {
280 if(m_TrimFromRight)
281 tmpLine.Trim(); //trim from right
282 if( i < nLines-1 )
283 tmpLine += eolChars;
284 formattedText += tmpLine;
285 }
286 continue;
287 }
288
289 tmpLine = tmpLine.Trim(false); // trim from left
290 if(m_IndentEstimator.GetIsHasLineContinuation(tmpLine))
291 {
292 wxString tempLine = tmpLine;
293
294 if(!isMultiLines.haveMultiLines)
295 {
296 isMultiLines.haveMultiLines = true;
297 isMultiLines.iFirstLineNo = i;
298 tmpMultiLines.Empty();
299 }
300
301 m_IndentEstimator.CutStringAndComment(tempLine);
302 m_IndentEstimator.DelLineContinuation(tempLine);
303
304 if(tempLine.Len() > 0)
305 {
306 if(wxT('&') == tempLine[0])
307 tempLine = tempLine.Mid(1);
308 }
309 tmpMultiLines += tempLine;
310 continue ;
311 }
312
313 indentNumNext = indentNum;
314
315 if(isMultiLines.haveMultiLines)
316 {
317 isMultiLines.iEndLineNo = i;
318
319 wxString tempLine = tmpLine;
320
321 if(tempLine.Len() > 0)
322 {
323 if(wxT('&') == tempLine[0])
324 tempLine = tempLine.Mid(1);
325 }
326
327 tmpMultiLines += tempLine;
328 m_IndentEstimator.GetFortranIndentLine(tmpMultiLines, indentNum, indentNumNext);
329
330 for(int j = isMultiLines.iFirstLineNo; j <= isMultiLines.iEndLineNo; ++j)
331 {
332 if(m_IndentEstimator.GetIsHasPreprocessor(textLines[j]))
333 {
334 tempLine = textLines[j];
335 if(m_TrimFromRight)
336 tempLine.Trim(); //trim from right
337 if(j < nLines-1)
338 tempLine += eolChars;
339 formattedText += tempLine;
340 }
341 else
342 {
343 tempLine = textLines[j].Trim(false); // trim from left
344
345 if(m_TrimFromRight)
346 tempLine.Trim(); //trim from right
347 if(j < nLines-1)
348 tempLine += eolChars;
349
350 if(j != isMultiLines.iFirstLineNo)
351 indentNum += 1;
352
353 for(int k=0; k < indentNum; ++k)
354 formattedText += m_IndentStr;
355
356 formattedText += tempLine;
357 indentNum = indentNumNext;
358 }
359 }
360
361 isMultiLines.reset();
362 }
363 else
364 {
365 if(tmpLine.Len() == 0 && i < nLines-1)
366 tmpLine += eolChars;
367 else
368 {
369 if(m_TrimFromRight)
370 {
371 tmpLine.Trim(); //trim from right
372 }
373 if(i < nLines-1)
374 tmpLine += eolChars;
375 m_IndentEstimator.GetFortranIndentLine(tmpLine, indentNum, indentNumNext);
376
377 for(int k = 0; k < indentNum; ++k)
378 formattedText += m_IndentStr;
379 }
380
381 formattedText += tmpLine;
382 indentNum = indentNumNext;
383 }
384 }
385 }
386
ReplaceTextInEditor(const wxString & text,bool isSelection,cbStyledTextCtrl * control)387 void FormatIndent::ReplaceTextInEditor(const wxString& text, bool isSelection, cbStyledTextCtrl* control)
388 {
389 if (isSelection)
390 control->ReplaceSelection(text);
391 else
392 control->SetText(text);
393 }
394
GetEOLChars(cbStyledTextCtrl * control)395 wxString FormatIndent::GetEOLChars(cbStyledTextCtrl* control)
396 {
397 wxString eolChars;
398 switch (control->GetEOLMode())
399 {
400 case wxSCI_EOL_CRLF:
401 eolChars = _T("\r\n");
402 break;
403
404 case wxSCI_EOL_CR:
405 eolChars = _T("\r");
406 break;
407
408 case wxSCI_EOL_LF:
409 eolChars = _T("\n");
410 break;
411 }
412 return eolChars;
413 }
414