NumeRe v1.1.4
NumeRe: Framework für Numerische Rechnungen
editor.cpp
Go to the documentation of this file.
1/*****************************************************************************
2 NumeRe: Framework fuer Numerische Rechnungen
3 Copyright (C) 2019 Erik Haenel et al.
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17******************************************************************************/
18
19
20
21#define CRTDBG_MAP_ALLOC
22#include <stdlib.h>
23#ifdef _MSC_VER
24#include <crtdbg.h>
25#else
26#define _ASSERT(expr) ((void)0)
27
28#define _ASSERTE(expr) ((void)0)
29#endif
30
31#include "../../common/CommonHeaders.h"
32#include "../../kernel/core/ui/language.hpp"
33#include "../../kernel/core/utils/tools.hpp"
34
35#include <wx/datetime.h>
36#include <wx/stdpaths.h>
37#include <wx/tokenzr.h>
38#include <wx/clipbrd.h>
39#include <vector>
40#include <string>
41#include <set>
42#include <memory>
43
44#include "editor.h"
45#include "../NumeReWindow.h"
46#include "../NumeReNotebook.h"
47#include "codeanalyzer.hpp"
48#include "searchcontroller.hpp"
49#include "codeformatter.hpp"
50
51#include "../../common/datastructures.h"
52#include "../../common/Options.h"
53#include "../../common/vcsmanager.hpp"
54#include "../../common/filerevisions.hpp"
55#include "../dialogs/renamesymbolsdialog.hpp"
56#include "../globals.hpp"
57
58#define MARGIN_FOLD 3
59#define HIGHLIGHT 25
60#define HIGHLIGHT_DBLCLK 26
61#define HIGHLIGHT_MATCHING_BRACE 6
62#define HIGHLIGHT_STRIKETHROUGH 7
63#define HIGHLIGHT_MATCHING_BLOCK 8
64#define HIGHLIGHT_NOT_MATCHING_BLOCK 9
65#define HIGHLIGHT_DIFFERENCES 10
66#define HIGHLIGHT_DIFFERENCE_SOURCE 11
67#define HIGHLIGHT_ANNOTATION 12
68#define HIGHLIGHT_LOCALVARIABLES 13
69#define ANNOTATION_NOTE wxSTC_NSCR_PROCEDURE_COMMANDS+1
70#define ANNOTATION_WARN wxSTC_NSCR_PROCEDURE_COMMANDS+2
71#define ANNOTATION_ERROR wxSTC_NSCR_PROCEDURE_COMMANDS+3
72
73#define SEMANTICS_VAR 1
74#define SEMANTICS_STRING 2
75#define SEMANTICS_NUM 4
76#define SEMANTICS_FUNCTION 8
77
78
79BEGIN_EVENT_TABLE(NumeReEditor, wxStyledTextCtrl)
80 EVT_STC_CHARADDED (-1, NumeReEditor::OnChar)
81 EVT_STC_MODIFIED (-1, NumeReEditor::OnEditorModified)
82 EVT_KEY_DOWN (NumeReEditor::OnKeyDn)
83 EVT_KEY_UP (NumeReEditor::OnKeyRel)
84 EVT_LEFT_DOWN (NumeReEditor::OnMouseDn)
85 EVT_LEFT_UP (NumeReEditor::OnMouseUp)
86 EVT_RIGHT_DOWN (NumeReEditor::OnRightClick)
87 EVT_LEFT_DCLICK (NumeReEditor::OnMouseDblClk)
88 EVT_MOUSE_CAPTURE_LOST(NumeReEditor::OnMouseCaptureLost)
89// EVT_ENTER_WINDOW (NumeReEditor::OnEnter)
90 EVT_LEAVE_WINDOW (NumeReEditor::OnLeave)
91 EVT_KILL_FOCUS (NumeReEditor::OnLoseFocus)
92 EVT_STC_DWELLSTART (-1, NumeReEditor::OnMouseDwell)
93 EVT_STC_MARGINCLICK (-1, NumeReEditor::OnMarginClick)
94 EVT_STC_DRAG_OVER (-1, NumeReEditor::OnDragOver)
95 EVT_STC_SAVEPOINTREACHED (-1, NumeReEditor::OnSavePointReached)
96 EVT_STC_SAVEPOINTLEFT (-1, NumeReEditor::OnSavePointLeft)
97 EVT_STC_AUTOCOMP_SELECTION (-1, NumeReEditor::OnAutoCompletion)
118 EVT_IDLE (NumeReEditor::OnIdle)
121
122int CompareInts(int n1, int n2)
123{
124 return n1 - n2;
125}
126
127
128extern Language _guilang;
129using namespace std;
130
146NumeReEditor::NumeReEditor(NumeReWindow* mframe, Options* options, wxWindow* parent, wxWindowID id,
147 NumeReSyntax* __syntax, NumeReTerminal* __terminal, const wxPoint& pos, const wxSize& size, long style, const wxString& name) :
148 wxStyledTextCtrl(parent, id, pos, size, style, name)
149{
150 defaultPage = false;
151 m_mainFrame = mframe;
152 m_options = options;
153 m_analyzer = new CodeAnalyzer(this, options);
154 m_search = new SearchController(this, __terminal);
155 m_formatter = new CodeFormatter(this);
156 m_duplicateCode = nullptr;
157 m_nCallTipStart = 0;
162
163 m_watchedString = "";
164 m_dblclkString = "";
165
168
169 m_bLoadingFile = false;
171 m_bHasBeenCompiled = false;
172 m_PopUpActive = false;
173
174 m_fileNameAndPath.Assign(wxEmptyString);
175
176 m_lastRightClick.x = -1;
177 m_lastRightClick.y = -1;
178 _syntax = __syntax;
180 m_terminal = __terminal;
181 m_dragging = false;
182
186 m_procedureViewer = nullptr;
187 m_analyzerTimer = new wxTimer(this, ID_ANALYZERTIMER);
188
189 Bind(wxEVT_THREAD, &NumeReEditor::OnThreadUpdate, this);
190
191 SetTabWidth(4);
192 SetIndent(4);
193 SetUseTabs(true);
194
195 AutoCompSetIgnoreCase(true);
196 AutoCompSetCaseInsensitiveBehaviour(wxSTC_CASEINSENSITIVEBEHAVIOUR_RESPECTCASE);
197
198 SetMultipleSelection(true);
199 SetVirtualSpaceOptions(wxSTC_SCVS_RECTANGULARSELECTION);
200 SetAdditionalSelectionTyping(true);
201 SetMultiPaste(wxSTC_MULTIPASTE_EACH);
202
203 SetMarginWidth(0, 40);
204 SetMarginType(0, wxSTC_MARGIN_NUMBER);
205
206 SetMarginWidth(1, 20);
207 SetMarginType(1, wxSTC_MARGIN_SYMBOL);
208
209 SetYCaretPolicy(wxSTC_CARET_SLOP | wxSTC_CARET_STRICT | wxSTC_CARET_EVEN, 1);
210
211 wxFileName f(wxStandardPaths::Get().GetExecutablePath());
212 //wxInitAllImageHandlers();
213 RegisterImage(NumeReSyntax::SYNTAX_COMMAND,
214 wxBitmap(f.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + "icons\\cmd.png", wxBITMAP_TYPE_PNG));
215 RegisterImage(NumeReSyntax::SYNTAX_FUNCTION,
216 wxBitmap(f.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + "icons\\fnc.png", wxBITMAP_TYPE_PNG));
217 RegisterImage(NumeReSyntax::SYNTAX_OPTION,
218 wxBitmap(f.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + "icons\\opt.png", wxBITMAP_TYPE_PNG));
219 RegisterImage(NumeReSyntax::SYNTAX_CONSTANT,
220 wxBitmap(f.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + "icons\\cnst.png", wxBITMAP_TYPE_PNG));
222 wxBitmap(f.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + "icons\\spv.png", wxBITMAP_TYPE_PNG));
223 RegisterImage(NumeReSyntax::SYNTAX_OPERATOR,
224 wxBitmap(f.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + "icons\\opr.png", wxBITMAP_TYPE_PNG));
225 RegisterImage(NumeReSyntax::SYNTAX_METHODS,
226 wxBitmap(f.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + "icons\\mthd.png", wxBITMAP_TYPE_PNG));
227 RegisterImage(NumeReSyntax::SYNTAX_PROCEDURE,
228 wxBitmap(f.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + "icons\\prc.png", wxBITMAP_TYPE_PNG));
229 RegisterImage(NumeReSyntax::SYNTAX_STD,
230 wxBitmap(f.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + "icons\\var.png", wxBITMAP_TYPE_PNG));
231 RegisterImage(NumeReSyntax::SYNTAX_CLUSTER,
232 wxBitmap(f.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + "icons\\cst.png", wxBITMAP_TYPE_PNG));
233 RegisterImage(NumeReSyntax::SYNTAX_TABLE,
234 wxBitmap(f.GetPath(wxPATH_GET_VOLUME | wxPATH_GET_SEPARATOR) + "icons\\tab.png", wxBITMAP_TYPE_PNG));
235
236 wxFont font = m_options->GetEditorFont();
237 StyleSetFont(wxSTC_STYLE_DEFAULT, font);
238
239 // Add the characters for procedures to the word char list
240 // this->SetWordChars("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789_$~");
241
242 StyleClearAll();
243
244 SetMouseDwellTime(500);
245
246 EmptyUndoBuffer();
247 m_bSetUnsaved = false;
248 m_bNewFile = true;
250 m_bNewFile = false;
251
252 MarkerDefine(MARKER_BREAKPOINT, wxSTC_MARK_CIRCLE);
253 MarkerSetBackground(MARKER_BREAKPOINT, wxColour("red"));
254
255 MarkerDefine(MARKER_BOOKMARK, wxSTC_MARK_SMALLRECT);
256 MarkerSetBackground(MARKER_BOOKMARK, wxColour(192, 0, 64));
257
258 MarkerDefine(MARKER_FOCUSEDLINE, wxSTC_MARK_SHORTARROW);
259 MarkerSetBackground(MARKER_FOCUSEDLINE, wxColour("yellow"));
260
261 MarkerDefine(MARKER_MODIFIED, wxSTC_MARK_LEFTRECT);
262 MarkerSetBackground(MARKER_MODIFIED, wxColour(255, 220, 0));
263
264 MarkerDefine(MARKER_SAVED, wxSTC_MARK_LEFTRECT);
265 MarkerSetBackground(MARKER_SAVED, wxColour("green"));
266
267 MarkerDefine(MARKER_SECTION, wxSTC_MARK_ARROWDOWN);
269
270 MarkerDefine(MARKER_HIDDEN, wxSTC_MARK_UNDERLINE);
271 MarkerSetBackground(MARKER_HIDDEN, wxColour(128, 128, 128));
272 MarkerDefine(MARKER_HIDDEN_MARGIN, wxSTC_MARK_DOTDOTDOT);
273 MarkerSetBackground(MARKER_HIDDEN_MARGIN, wxColour(128, 128, 128));
274
275 MarkerDefine(MARKER_DUPLICATEINDICATOR_ONE, wxSTC_MARK_BACKGROUND);
276 MarkerSetBackground(MARKER_DUPLICATEINDICATOR_ONE, wxColour(220, 255, 220));
277
278 MarkerDefine(MARKER_DUPLICATEINDICATOR_TWO, wxSTC_MARK_BACKGROUND);
279 MarkerSetBackground(MARKER_DUPLICATEINDICATOR_TWO, wxColour(255, 220, 220));
280
281 SetMarginSensitive(1, true);
282
283 UsePopUp(false);
284
286
287 SetCaretPeriod(m_options->GetCaretBlinkTime());
288
289 m_refactoringMenu = new wxMenu();
291 _guilang.get("GUI_MENU_EDITOR_RENAME_SYMBOLS"),
292 _guilang.get("GUI_MENU_EDITOR_RENAME_SYMBOLS_TTP"));
294 _guilang.get("GUI_MENU_EDITOR_FIX_TYPE"),
295 _guilang.get("GUI_MENU_EDITOR_FIX_TYPE_TTP"));
297 _guilang.get("GUI_MENU_EDITOR_ABSTRAHIZE_SECTION"),
298 _guilang.get("GUI_MENU_EDITOR_ABSTRAHIZE_SECTION_TTP"));
299
300 m_popupMenu.Append(ID_MENU_CUT, _guilang.get("GUI_MENU_EDITOR_CUT"));
301 m_popupMenu.Append(ID_MENU_COPY, _guilang.get("GUI_MENU_EDITOR_COPY"));
302 m_popupMenu.Append(ID_MENU_PASTE, _guilang.get("GUI_MENU_EDITOR_PASTE"));
303 m_popupMenu.AppendSeparator();
304
305 m_popupMenu.Append(ID_FOLD_CURRENT_BLOCK, _guilang.get("GUI_MENU_EDITOR_FOLDCURRENTBLOCK"));
306 m_popupMenu.Append(ID_HIDE_SELECTION, _guilang.get("GUI_MENU_EDITOR_HIDECURRENTBLOCK"));
307 m_popupMenu.AppendSeparator();
308
309 m_popupMenu.Append(ID_DEBUG_ADD_BREAKPOINT, _guilang.get("GUI_MENU_EDITOR_ADDBP"));
310 m_popupMenu.Append(ID_DEBUG_REMOVE_BREAKPOINT, _guilang.get("GUI_MENU_EDITOR_REMOVEBP"));
311 m_popupMenu.Append(ID_DEBUG_CLEAR_ALL_BREAKPOINTS, _guilang.get("GUI_MENU_EDITOR_CLEARBP"));
312 m_popupMenu.AppendSeparator();
313
314 m_popupMenu.Append(ID_BOOKMARK_ADD, _guilang.get("GUI_MENU_EDITOR_ADDBM"));
315 m_popupMenu.Append(ID_BOOKMARK_REMOVE, _guilang.get("GUI_MENU_EDITOR_REMOVEBM"));
316 m_popupMenu.Append(ID_BOOKMARK_CLEAR, _guilang.get("GUI_MENU_EDITOR_CLEARBM"));
317
318 m_popupMenu.AppendSeparator();
319
320 //m_menuAddWatch = m_popupMenu.Append(ID_DEBUG_WATCH_SELECTION, "Watch selection");
321 m_menuFindProcedure = m_popupMenu.Append(ID_FIND_PROCEDURE, _guilang.get("GUI_MENU_EDITOR_FINDPROC", "$procedure"));
322 m_menuFindInclude = m_popupMenu.Append(ID_FIND_INCLUDE, _guilang.get("GUI_MENU_EDITOR_FINDINCLUDE", "script"));
323 m_menuShowValue = m_popupMenu.Append(ID_DEBUG_DISPLAY_SELECTION, _guilang.get("GUI_MENU_EDITOR_HIGHLIGHT", "selection"), "", wxITEM_CHECK);
324 m_menuHelpOnSelection = m_popupMenu.Append(ID_MENU_HELP_ON_ITEM, _guilang.get("GUI_TREE_PUP_HELPONITEM", "..."));
325 m_menuRefactoring = m_popupMenu.Append(ID_REFACTORING_MENU, _guilang.get("GUI_MENU_EDITOR_REFACTORING"), m_refactoringMenu);
326 m_popupMenu.AppendSeparator();
327 m_popupMenu.Append(ID_UPPERCASE, _guilang.get("GUI_MENU_EDITOR_UPPERCASE"));
328 m_popupMenu.Append(ID_LOWERCASE, _guilang.get("GUI_MENU_EDITOR_LOWERCASE"));
329
330
331 int modmask = wxSTC_MOD_INSERTTEXT
332 | wxSTC_MOD_DELETETEXT
333 //| wxSTC_MOD_CHANGESTYLE
334 | wxSTC_PERFORMED_UNDO
335 | wxSTC_PERFORMED_REDO;
336
337 this->SetModEventMask(modmask);
338 SetScrollWidthTracking(true);
339}
340
341
351{
352 if (m_analyzer)
353 {
354 delete m_analyzer;
355 m_analyzer = nullptr;
356 }
357
358 if (m_search)
359 {
360 delete m_search;
361 m_search = nullptr;
362 }
363
364 if (m_formatter)
365 {
366 delete m_formatter;
367 m_formatter = nullptr;
368 }
369}
370
371
381{
382 return SaveFile(m_fileNameAndPath.GetFullPath());
383}
384
385
396bool NumeReEditor::SaveFile( const wxString& filename )
397{
398 // return if no change
399 if (!Modified() && filename.IsEmpty())
400 {
401 return true;
402 }
403
404 wxFileName fn(filename);
405
406 // save edit in file and clear undo
407 if (!filename.IsEmpty())
408 {
409 m_simpleFileName = fn.GetFullName();
410 }
411
413 std::unique_ptr<FileRevisions> revisions;
414
415 // The history does not need a real revision
416 if (filename.find("numere.history") == string::npos)
417 revisions.reset(manager.getRevisions(filename));
418
419 if (revisions.get())
420 {
421 if (!revisions->getRevisionCount() && wxFileExists(filename))
422 {
423 wxFile tempfile(filename);
424 wxString contents;
425 tempfile.ReadAll(&contents);
426 revisions->addRevision(contents);
427 }
428 }
429 else if (wxFileExists(filename))
430 {
431 wxCopyFile(filename, filename + ".backup", true);
432 }
433
434 bool bWriteSuccess = false;
435
436 // Write the file depending on its type
437 if (m_fileType == FILE_NSCR || m_fileType == FILE_NPRC || filename.find("numere.history") != string::npos)
438 bWriteSuccess = SaveNumeReFile(filename);
439 else
440 bWriteSuccess = SaveGeneralFile(filename);
441
442 // Check the contents of the newly created file
443 wxFile filecheck;
444 filecheck.Open(filename);
445
446 if (!bWriteSuccess)
447 {
448 // if the contents are not matching, restore the backup and signalize that an error occured
449 if (wxFileExists(filename + ".backup"))
450 wxCopyFile(filename + ".backup", filename, true);
451 else if (revisions.get() && revisions->getRevisionCount())
452 revisions->restoreRevision(revisions->getRevisionCount()-1, filename);
453
454 return false;
455 }
456 else if ((m_fileType == FILE_NSCR || m_fileType == FILE_NPRC) && filecheck.Length() != this->GetLength() - countUmlauts(this->GetText().ToStdString()))
457 {
458 // if the contents are not matching, restore the backup and signalize that an error occured
459 if (wxFileExists(filename + ".backup"))
460 wxCopyFile(filename + ".backup", filename, true);
461 else if (revisions.get() && revisions->getRevisionCount())
462 revisions->restoreRevision(revisions->getRevisionCount()-1, filename);
463
464 return false;
465 }
466 else if ((m_fileType != FILE_NSCR && m_fileType != FILE_NPRC) && !filecheck.Length() && this->GetLength())
467 {
468 // if the contents are not matching, restore the backup and signalize that an error occured
469 if (wxFileExists(filename + ".backup"))
470 wxCopyFile(filename + ".backup", filename, true);
471 else if (revisions.get() && revisions->getRevisionCount())
472 revisions->restoreRevision(revisions->getRevisionCount()-1, filename);
473
474 return false;
475 }
476
477 // Add the current text to the revisions, if the saving process was
478 // successful
479 if (revisions.get() && m_options->GetKeepBackupFile())
480 revisions->addRevision(GetText());
481
482 // If the user doesn't want to keep the backup files
483 // delete it here
484 if (!m_options->GetKeepBackupFile() && wxFileExists(filename + ".backup"))
485 wxRemoveFile(filename + ".backup");
486
487 // Only mark the editor as saved, if the saving process was successful
488 markSaved();
489 SetSavePoint();
491
494
495 m_filetime = fn.GetModificationTime();
496 m_bSetUnsaved = false;
497 return true;
498}
499
500
509bool NumeReEditor::SaveNumeReFile(const wxString& filename)
510{
511 // create a std::ofstream to avoid encoding issues
512 std::ofstream file;
513 file.open(filename.ToStdString().c_str(), std::ios_base::out | std::ios_base::trunc | std::ios_base::binary);
514
515 if (!file.is_open())
516 return false;
517
518 // write the contents of the file linewise
519 for (int i = 0; i < this->GetLineCount(); i++)
520 {
521 file << this->GetLine(i).ToStdString();
522 }
523
524 // flush the files content explicitly
525 file.flush();
526 file.close();
527
528 return true;
529}
530
531
539bool NumeReEditor::SaveGeneralFile(const wxString& filename)
540{
541 // Create file and check, if it has been opened successfully
542 wxFile file (filename, wxFile::write);
543
544 if (!file.IsOpened())
545 {
546 return false;
547 }
548
549 // Get text and write it to the file
550 wxString buf = GetText();
551 bool okay = file.Write(buf.ToStdString().c_str(), buf.ToStdString().length());
552
553 file.Close();
554
555 // Notify caller that there was an error during writing
556 if (!okay)
557 {
558 return false;
559 }
560 return true;
561}
562
563
576bool NumeReEditor::LoadFileText(wxString fileContents)
577{
578 if (fileContents.length() > 0)
579 {
580 m_bLoadingFile = true;
581 defaultPage = false;
582 SetReadOnly(false);
585 ClearAll();
586 StyleClearAll();
587 InsertText(0, fileContents);
588 }
589
590 EmptyUndoBuffer();
591 SetSavePoint();
592 m_bSetUnsaved = false;
593
594 // determine and set EOL mode
595 int eolMode = -1;
596
597 //wxString eolName;
598
599 if (fileContents.find("\r\n") != std::string::npos)
600 {
601 eolMode = wxSTC_EOL_CRLF;
602 //eolName = _("CR+LF (Windows)");
603 }
604 else if (fileContents.find("\r") != std::string::npos)
605 {
606 eolMode = wxSTC_EOL_CR;
607 //eolName = _("CR (Macintosh)");
608 }
609 else if (fileContents.find("\n") != std::string::npos)
610 {
611 eolMode = wxSTC_EOL_LF;
612 //eolName = _("LF (Unix)");
613 }
614
615 if (eolMode != -1)
616 {
617 SetEOLMode(eolMode);
618 }
619
620 m_bLoadingFile = false;
622 return true;
623}
624
625
635{
636 // return modified state
637 bool modified = GetModify();
638 bool readonly = !GetReadOnly();
639 bool canundo = CanUndo();
640
641
642
643 bool isModified = (modified && readonly && canundo) || m_bSetUnsaved;
644 return isModified;
645}
646
647
658void NumeReEditor::OnChar( wxStyledTextEvent& event )
659{
661 const wxChar chr = event.GetKey();
662 const int currentLine = GetCurrentLine();
663 const int currentPos = GetCurrentPos();
664 const int wordstartpos = WordStartPosition(currentPos, true);
665
666 MarkerDeleteAll(MARKER_FOCUSEDLINE);
667
668 if (chr == WXK_TAB)
669 {
670 event.Skip(true);
671
672 int startLine = LineFromPosition(GetSelectionStart());
673 int endline = LineFromPosition(GetSelectionEnd());
674 int newStartPos = PositionFromLine(startLine);
675 int newEndPos = PositionFromLine(endline) + LineLength(endline);
676 bool doIndent = event.GetShift();
677 int indentWidth = this->GetIndent();
678
679 this->SetSelection(newStartPos, newEndPos);
680
681 for (int i = startLine; i <= endline; i++)
682 {
683 int lineIndent = this->GetLineIndentation(i);
684
685 if (doIndent)
686 this->SetLineIndentation(i, lineIndent + indentWidth);
687 else
688 this->SetLineIndentation(i, lineIndent - indentWidth);
689 }
690 }
691
692 if (chr == '\n')
693 {
694 markModified(currentLine);
695 int previousLineInd = 0;
696
697 if (currentLine > 0)
698 {
699 markModified(currentLine - 1);
700 previousLineInd = GetLineIndentation(currentLine - 1);
701 }
702
703 if (previousLineInd == 0)
704 return;
705
706 SetLineIndentation(currentLine, previousLineInd);
707
708 // If tabs are being used then change previousLineInd to tab sizes
709 if (GetUseTabs())
710 previousLineInd /= GetTabWidth();
711
712 GotoPos(PositionFromLine(currentLine) + previousLineInd);
713 return;
714 }
715
716 if ((isspace(chr) || (ispunct(chr) && chr != '_' && chr != '~')) && AutoCompActive())
717 AutoCompCancel();
718
720 {
721 if (GetStyleAt(currentPos) != wxSTC_NSCR_STRING && GetStyleAt(currentPos) != wxSTC_NPRC_STRING)
722 InsertText(currentPos, "\"");
723 }
724
725 if (m_options->getSetting(SETTING_B_BRACEAUTOCOMP).active() && (chr == '(' || chr == '[' || chr == '{'))
726 {
727 int nMatchingPos = currentPos;
728
729 if (this->HasSelection())
730 nMatchingPos = this->GetSelectionEnd();
731
732 if (this->BraceMatch(currentPos - 1) == wxSTC_INVALID_POSITION)
733 {
734 if (chr == '(')
735 InsertText(nMatchingPos, ")");
736 else if (chr == '[')
737 InsertText(nMatchingPos, "]");
738 else
739 InsertText(nMatchingPos, "}");
740 }
741 }
742
743 int lenEntered = currentPos - wordstartpos;
744 AutoCompSetAutoHide(!m_options->getSetting(SETTING_B_SMARTSENSE).active());
745 wxString sAutoCompList;
746
747 if (lenEntered > 1
749 && !isStyleType(STYLE_COMMENT, wordstartpos)
750 && !isStyleType(STYLE_STRING, wordstartpos)
751 && !isStyleType(STYLE_PROCEDURE, wordstartpos))
752 {
753 int smartSenseWordStart = wordstartpos;
754
755 // SmartSense extension: match only methods
756 if (m_options->getSetting(SETTING_B_SMARTSENSE).active() && GetCharAt(wordstartpos-1) == '.')
757 smartSenseWordStart--;
758
759 sAutoCompList = generateAutoCompList(smartSenseWordStart, currentPos,
760 _syntax->getAutoCompList(GetTextRange(smartSenseWordStart, currentPos).ToStdString(),
762
763 if (sAutoCompList.length())
764 AutoCompShow(lenEntered, sAutoCompList);
765 }
766 else if (lenEntered > 1
768 && !isStyleType(STYLE_COMMENT, wordstartpos)
769 && !isStyleType(STYLE_STRING, wordstartpos))
770 {
771 sAutoCompList = generateAutoCompList(wordstartpos, currentPos,
772 _syntax->getAutoCompListMATLAB(GetTextRange(wordstartpos, currentPos).ToStdString()));
773 }
774 else if (lenEntered > 1
775 && m_fileType == FILE_CPP
776 && !isStyleType(STYLE_COMMENT, wordstartpos)
777 && !isStyleType(STYLE_STRING, wordstartpos))
778 {
779 sAutoCompList = generateAutoCompList(wordstartpos, currentPos,
780 _syntax->getAutoCompListCPP(GetTextRange(wordstartpos, currentPos).ToStdString()));
781 }
782 else if (lenEntered > 1
784 && GetStyleAt(wordstartpos) == wxSTC_NSCR_PROCEDURES)
785 {
786 wxString sNamespace;
787 wxString sSelectedNamespace;
788 int nNameSpacePosition = wordstartpos;
789
790 while (GetStyleAt(nNameSpacePosition - 1) == wxSTC_NSCR_PROCEDURES && GetCharAt(nNameSpacePosition - 1) != '$')
791 nNameSpacePosition--;
792
793 if (nNameSpacePosition == wordstartpos)
794 sNamespace = m_search->FindNameSpaceOfProcedure(wordstartpos) + "~";
795 else
796 sSelectedNamespace = GetTextRange(nNameSpacePosition, wordstartpos);
797
798 // If namespace == "this~" then replace it with the current namespace
799 if (sNamespace == "this~")
800 {
801 string filename = GetFileNameAndPath().ToStdString();
802 filename = replacePathSeparator(filename);
803 vector<string> vPaths = m_terminal->getPathSettings();
804
805 if (filename.substr(0, vPaths[PROCPATH].length()) == vPaths[PROCPATH])
806 {
807 filename.erase(0, vPaths[PROCPATH].length());
808
809 if (filename.find('/') != string::npos)
810 filename.erase(filename.rfind('/') + 1);
811
812 while (filename.front() == '/')
813 filename.erase(0, 1);
814
815 while (filename.find('/') != string::npos)
816 filename[filename.find('/')] = '~';
817
818 sNamespace = filename;
819 }
820 else
821 sNamespace = "";
822 }
823 else if (sSelectedNamespace == "this~")
824 {
825 string filename = GetFileNameAndPath().ToStdString();
826 filename = replacePathSeparator(filename);
827 vector<string> vPaths = m_terminal->getPathSettings();
828
829 if (filename.substr(0, vPaths[PROCPATH].length()) == vPaths[PROCPATH])
830 {
831 filename.erase(0, vPaths[PROCPATH].length());
832
833 if (filename.find('/') != string::npos)
834 filename.erase(filename.rfind('/') + 1);
835
836 while (filename.front() == '/')
837 filename.erase(0, 1);
838
839 while (filename.find('/') != string::npos)
840 filename[filename.find('/')] = '~';
841
842 sSelectedNamespace = filename;
843 }
844 else
845 sSelectedNamespace = "";
846 }
847 // If namespace == "thisfile~" then search for all procedures in the current file and use them as the
848 // autocompletion list entries
849 else if (sNamespace == "thisfile"
850 || sNamespace == "thisfile~"
851 || sSelectedNamespace == "thisfile"
852 || sSelectedNamespace == "thisfile~")
853 {
854 this->AutoCompSetIgnoreCase(true);
855 this->AutoCompSetCaseInsensitiveBehaviour(wxSTC_CASEINSENSITIVEBEHAVIOUR_IGNORECASE);
856 this->AutoCompShow(lenEntered, m_search->FindProceduresInCurrentFile(GetTextRange(wordstartpos, currentPos), sSelectedNamespace));
857 this->Colourise(0, -1);
858 event.Skip();
859 return;
860 }
861 // If namespace == "main~" (or similiar) then clear it's contents
862 else if (sNamespace == "main" || sNamespace == "main~" || sNamespace == "~")
863 sNamespace = "";
864 else if (sSelectedNamespace == "main" || sSelectedNamespace == "main~" || sSelectedNamespace == "~")
865 sSelectedNamespace = "";
866
867 sAutoCompList = _syntax->getProcAutoCompList(GetTextRange(wordstartpos, currentPos).ToStdString(),
868 sNamespace.ToStdString(), sSelectedNamespace.ToStdString());
869 }
870 else if (lenEntered > 1
872 && GetStyleAt(wordstartpos) == wxSTC_TEX_COMMAND)
873 {
874 sAutoCompList = generateAutoCompList(wordstartpos, currentPos,
875 _syntax->getAutoCompListTeX(GetTextRange(wordstartpos, currentPos).ToStdString()));
876 }
877 else if (lenEntered > 1)
878 sAutoCompList = generateAutoCompList(wordstartpos, currentPos, "");
879
880 if (sAutoCompList.length())
881 AutoCompShow(lenEntered, sAutoCompList);
882
883 Colourise(0, -1);
884
885 event.Skip();
886}
887
888
898{
899 int curPos = GetCurrentPos();
900 char CurrentChar = GetCharAt(curPos);
901 char PrevChar = 0;
902
903 // Find the previous character, if available
904 if (curPos)
905 PrevChar = GetCharAt(curPos - 1);
906
907 // Find the matching brace
908 if (CurrentChar == ')' || CurrentChar == ']' || CurrentChar == '}')
909 getMatchingBrace(curPos);
910 else if (PrevChar == '(' || PrevChar == '[' || PrevChar == '{')
911 getMatchingBrace(curPos - 1);
912 else if (CurrentChar == '(' || CurrentChar == '[' || CurrentChar == '{')
913 getMatchingBrace(curPos);
914 else if (PrevChar == ')' || PrevChar == ']' || PrevChar == '}')
915 getMatchingBrace(curPos - 1);
916 else if (m_braceIndicatorActive)
917 {
918 // Deactivate all indicators, if there's no brace is at cursor's
919 // position
920 this->SetIndicatorCurrent(HIGHLIGHT_MATCHING_BRACE);
921 this->IndicatorClearRange(0, GetLastPosition());
922 this->BraceBadLight(wxSTC_INVALID_POSITION);
923 this->BraceHighlight(wxSTC_INVALID_POSITION, wxSTC_INVALID_POSITION);
924
926 }
927
929 return;
930}
931
932
943{
944 if (this->m_fileType != FILE_NSCR && this->m_fileType != FILE_NPRC && this->m_fileType != FILE_MATLAB)
945 return;
946
947 // clear all indicators first
949 {
950 SetIndicatorCurrent(HIGHLIGHT_MATCHING_BLOCK);
951 IndicatorClearRange(0, GetLastPosition());
952 SetIndicatorCurrent(HIGHLIGHT_NOT_MATCHING_BLOCK);
953 IndicatorClearRange(0, GetLastPosition());
954
956 }
957
958 // Ensure that we have a command below the cursor
959 if (!isStyleType(STYLE_COMMAND, GetCurrentPos()) && !isStyleType(STYLE_COMMAND, GetCurrentPos()-1))
960 return;
961
962 // Get the word below the cursor
963 wxString currentWord = this->GetTextRange(WordStartPosition(GetCurrentPos(), true), WordEndPosition(GetCurrentPos(), true));
964
965 // If the word is a flow control statement
966 // find the matching block
967 if (isBlockStart(currentWord, true) != wxNOT_FOUND || isBlockEnd(currentWord) != wxNOT_FOUND)
968 getMatchingBlock(GetCurrentPos());
969}
970
971
986{
987 // do nothing if an autocompletion list is active
988 if (this->AutoCompActive())
989 return;
990
991 // do nothing, if language is not supported
992 if (this->getFileType() != FILE_NSCR && this->getFileType() != FILE_NPRC)
993 return;
994
995 int nStartingBrace = 0;
996 int nArgStartPos = 0;
997 string sFunctionContext = this->GetCurrentFunctionContext(nStartingBrace);
998 static NumeRe::CallTipProvider _provider = *m_terminal->getProvider();
999 NumeRe::CallTip _cTip;
1000
1001 if (!sFunctionContext.length())
1002 return;
1003
1004 if (sFunctionContext.front() == '$')
1005 {
1006 _cTip.sDefinition = m_search->FindProcedureDefinition().ToStdString();
1007
1008 if (_cTip.sDefinition.find('\n') != string::npos)
1009 _cTip.sDefinition.erase(_cTip.sDefinition.find('\n'));
1010
1011 if (_cTip.sDefinition.find(')') != string::npos)
1012 _cTip.sDefinition.erase(_cTip.sDefinition.rfind(')') + 1);
1013 }
1014 else if (sFunctionContext.front() == '.')
1015 {
1016 _cTip = _provider.getMethod(sFunctionContext.substr(1));
1017 size_t nDotPos = _cTip.sDefinition.find('.');
1018
1019 if (_cTip.sDefinition.find(')', nDotPos) != string::npos)
1020 _cTip.sDefinition.erase(_cTip.sDefinition.find(')', nDotPos) + 1);
1021 else
1022 _cTip.sDefinition.erase(_cTip.sDefinition.find(' ', nDotPos));
1023 }
1024 else
1025 {
1026 _cTip = _provider.getFunction(sFunctionContext);
1027
1028 if (_cTip.sDefinition.find(')') != string::npos)
1029 _cTip.sDefinition.erase(_cTip.sDefinition.find(')') + 1);
1030 }
1031
1032 if (!_cTip.sDefinition.length())
1033 return;
1034
1035 string sArgument = this->GetCurrentArgument(_cTip.sDefinition, nStartingBrace, nArgStartPos);
1036
1037 /*if (sArgument.length())
1038 {
1039 if (sArgument.substr(0,3) == "STR")
1040 sDefinition += "\n" + _guilang.get("GUI_EDITOR_ARGCALLTIP_STR", sArgument);
1041 else if (sArgument == "CHAR")
1042 sDefinition += "\n" + _guilang.get("GUI_EDITOR_ARGCALLTIP_CHAR", sArgument);
1043 else if (sArgument == "MAT")
1044 sDefinition += "\n" + _guilang.get("GUI_EDITOR_ARGCALLTIP_MAT", sArgument);
1045 else if (sArgument == "...")
1046 sDefinition += "\n" + _guilang.get("GUI_EDITOR_ARGCALLTIP_REPEATTYPE", sArgument);
1047 else if (sArgument == "x" || sArgument == "y" || sArgument == "z" || sArgument == "x1" || sArgument == "x0")
1048 sDefinition += "\n" + _guilang.get("GUI_EDITOR_ARGCALLTIP_FLOAT", sArgument);
1049 else if (sArgument == "l" || sArgument == "n" || sArgument == "m" || sArgument == "k" || sArgument == "P" || sArgument == "POS" || sArgument == "LEN")
1050 sDefinition += "\n" + _guilang.get("GUI_EDITOR_ARGCALLTIP_INTEGER", sArgument);
1051 else if (sArgument == "theta" || sArgument == "phi")
1052 sDefinition += "\n" + _guilang.get("GUI_EDITOR_ARGCALLTIP_ANGLE", sArgument);
1053 else
1054 sDefinition += "\n" + _guilang.get("GUI_EDITOR_ARGCALLTIP_NOHEURISTICS", sArgument);
1055
1056 }*/
1057
1058 if (this->CallTipActive() && this->CallTipStartPos() != nStartingBrace)
1059 {
1060 this->AdvCallTipCancel();
1061 this->AdvCallTipShow(nStartingBrace, _cTip.sDefinition);
1062 }
1063 else if (!this->CallTipActive())
1064 this->AdvCallTipShow(nStartingBrace, _cTip.sDefinition);
1065
1066 if (sArgument.length())
1067 this->CallTipSetHighlight(nArgStartPos, nArgStartPos + sArgument.length());
1068}
1069
1070
1080{
1082 {
1084 }
1085}
1086
1087
1097{
1098 int nCurrentLineStart = this->PositionFromLine(this->GetCurrentLine());
1099 int nCurrentPos = this->GetCurrentPos();
1100
1101 // Find the outermost brace for the current function call
1102 for (int i = nCurrentPos; i > nCurrentLineStart; i--)
1103 {
1104 if (this->GetCharAt(i) == '('
1105 && (this->BraceMatch(i) >= nCurrentPos || this->BraceMatch(i) == -1) // either no brace (yet) or the brace further right
1106 && (this->GetStyleAt(i - 1) == wxSTC_NSCR_FUNCTION
1107 || this->GetStyleAt(i - 1) == wxSTC_NSCR_PROCEDURES
1108 || this->GetStyleAt(i - 1) == wxSTC_NSCR_METHOD))
1109 {
1110 nStartingBrace = i;
1111
1112 // Get the word in front of the brace and return it
1113 if (this->GetStyleAt(i - 1) == wxSTC_NSCR_PROCEDURES)
1114 return m_search->FindMarkedProcedure(i - 1).ToStdString();
1115 else
1116 {
1117 if (this->GetStyleAt(i - 1) == wxSTC_NSCR_METHOD)
1118 return "." + this->GetTextRange(this->WordStartPosition(i - 1, true), this->WordEndPosition(i - 1, true)).ToStdString();
1119
1120 return this->GetTextRange(this->WordStartPosition(i - 1, true), this->WordEndPosition(i - 1, true)).ToStdString();
1121 }
1122 }
1123 }
1124
1125 return "";
1126}
1127
1128
1141string NumeReEditor::GetCurrentArgument(const string& sCallTip, int nStartingBrace, int& nArgStartPos)
1142{
1143 int nCurrentPos = this->GetCurrentPos();
1144 int nCurrentArg = 0;
1145 size_t nParensPos = 0;
1146 char currentChar;
1147
1148 // Do nothing, if no parenthesis is found
1149 if (sCallTip.find('(') == string::npos)
1150 return "";
1151
1152 nParensPos = sCallTip.find('(');
1153
1154 // If this is a method call of a table,
1155 // advance the position to the method
1156 // parenthesis, if it is available
1157 if (sCallTip.find("().") != string::npos)
1158 {
1159 if (sCallTip.find('(', sCallTip.find("().") + 3) == string::npos)
1160 return "";
1161
1162 nParensPos = sCallTip.find('(', sCallTip.find("().") + 3);
1163 }
1164
1165 // Extract the argument list
1166 string sArgList = sCallTip.substr(nParensPos);
1167 sArgList.erase(getMatchingParenthesis(sArgList));
1168
1169 // Find the n-th argument in the editor
1170 for (int i = nStartingBrace + 1; i < nCurrentPos && i < this->GetLineEndPosition(this->GetCurrentLine()); i++)
1171 {
1172 // Ignore comments and strings
1173 if (isStyleType(StyleType::STYLE_STRING, i)
1174 || isStyleType(StyleType::STYLE_COMMENT_LINE, i)
1175 || isStyleType(StyleType::STYLE_COMMENT_BLOCK, i))
1176 continue;
1177
1178 currentChar = this->GetCharAt(i);
1179
1180 // Increment the argument count, if a comma
1181 // has been found
1182 if (currentChar == ',')
1183 nCurrentArg++;
1184
1185 // Jump over parentheses and braces
1186 if ((currentChar == '(' || currentChar == '[' || currentChar == '{')
1187 && this->BraceMatch(i) != -1)
1188 i = this->BraceMatch(i);
1189 }
1190
1191 size_t nQuotationMarks = 0;
1192
1193 // Find the corresponding argument in the argument list
1194 for (size_t i = 1; i < sArgList.length(); i++)
1195 {
1196 // If this is the current argument and we're after
1197 // an opening parenthesis or a comma
1198 if (!(nQuotationMarks % 2) && !nCurrentArg && (sArgList[i - 1] == '(' || sArgList[i - 1] == ','))
1199 {
1200 nArgStartPos = i + nParensPos;
1201 string sArgument = sArgList.substr(i);
1202
1203 // If the argument still contains commas,
1204 // extract them here. Probably it is necessary
1205 // to move the position to the right
1206 if (sArgument.find(',') != string::npos)
1207 {
1208 sArgument = getNextArgument(sArgument, false);
1209 nArgStartPos = nParensPos + sArgList.find(sArgument, i);
1210 }
1211
1212 // return the extracted argument
1213 return sArgument;
1214 }
1215
1216 // Count and consider quotation marks
1217 if (sArgList[i] == '"' && sArgList[i-1] != '\\')
1218 nQuotationMarks++;
1219
1220 // If a parenthesis or a brace was found,
1221 // jump over it
1222 if (!(nQuotationMarks % 2) && (sArgList[i] == '(' || sArgList[i] == '{'))
1223 i += getMatchingParenthesis(sArgList.substr(i));
1224
1225 // If a comma was found,
1226 // decrement the argument count
1227 if (!(nQuotationMarks % 2) && sArgList[i] == ',')
1228 nCurrentArg--;
1229 }
1230
1231 // Return nothing
1232 return "";
1233}
1234
1235
1244{
1245 return m_nCallTipStart;
1246}
1247
1248
1259void NumeReEditor::AdvCallTipShow(int pos, const wxString& definition)
1260{
1261 m_nCallTipStart = pos;
1262
1263 if (m_sCallTipContent != definition)
1264 {
1265 if (CallTipActive())
1266 CallTipCancel();
1267
1268 m_sCallTipContent = definition;
1269 }
1270
1271 CallTipShow(pos, definition);
1272}
1273
1274
1283{
1284 m_nCallTipStart = 0;
1285 m_sCallTipContent.clear();
1286 CallTipCancel();
1287}
1288
1289
1305void NumeReEditor::OnKeyDn(wxKeyEvent& event)
1306{
1307 // Check the parentheses in the case of selections
1308 // and matching partners
1309 if (event.GetKeyCode() != WXK_SHIFT
1310 && event.GetKeyCode() != WXK_CAPITAL
1311 && event.GetKeyCode() != WXK_END
1312 && event.GetKeyCode() != WXK_HOME
1313 && event.GetKeyCode() != WXK_LEFT
1314 && event.GetKeyCode() != WXK_RIGHT
1315 && event.GetKeyCode() != WXK_UP
1316 && event.GetKeyCode() != WXK_DOWN)
1317 {
1318 if (this->HasSelection())
1319 {
1320 // Selection case: extract the position of the
1321 // end of the selection and insert the parenthesis
1322 // characters around the selection
1323 char chr = event.GetKeyCode();
1324 if (event.ShiftDown() && (chr == '8' || chr == '9'))
1325 {
1326 this->BeginUndoAction();
1327 int selStart = this->GetSelectionStart();
1328 int selEnd = this->GetSelectionEnd() + 1;
1329 this->InsertText(selStart, "(");
1330 this->InsertText(selEnd, ")");
1331 if (chr == '8')
1332 this->GotoPos(selStart);
1333 else
1334 this->GotoPos(selEnd + 1);
1335 this->EndUndoAction();
1338 return;
1339 }
1340 else if (event.ShiftDown() && chr == '2')
1341 {
1342 this->BeginUndoAction();
1343 int selStart = this->GetSelectionStart();
1344 int selEnd = this->GetSelectionEnd() + 1;
1345 this->InsertText(selStart, "\"");
1346 this->InsertText(selEnd, "\"");
1347 this->GotoPos(selEnd + 1);
1348 this->EndUndoAction();
1351 return;
1352 }
1353 else if (event.ControlDown() && event.AltDown() && (chr == '8' || chr == '9')) // Alt Gr means CTRL+ALT
1354 {
1355 this->BeginUndoAction();
1356 int selStart = this->GetSelectionStart();
1357 int selEnd = this->GetSelectionEnd() + 1;
1358 this->InsertText(selStart, "[");
1359 this->InsertText(selEnd, "]");
1360 if (chr == '8')
1361 this->GotoPos(selStart);
1362 else
1363 this->GotoPos(selEnd + 1);
1364 this->EndUndoAction();
1367 return;
1368 }
1369 else if (event.ControlDown() && event.AltDown() && (chr == '7' || chr == '0'))
1370 {
1371 this->BeginUndoAction();
1372 int selStart = this->GetSelectionStart();
1373 int selEnd = this->GetSelectionEnd() + 1;
1374 this->InsertText(selStart, "{");
1375 this->InsertText(selEnd, "}");
1376 if (chr == '7')
1377 this->GotoPos(selStart);
1378 else
1379 this->GotoPos(selEnd + 1);
1380 this->EndUndoAction();
1383 return;
1384 }
1385 }
1386 else
1387 {
1388 // Matching partner case: if the matching partner
1389 // is right to the current input position, simply
1390 // jump one position to the right. Note that this
1391 // algorithm will not work in strings, because
1392 // parenthesis matching in strings is not necessary
1393 char chr = event.GetKeyCode();
1394 if (event.ShiftDown() && chr == '9')
1395 {
1396 if (!isStyleType(STYLE_STRING, GetCurrentPos())
1397 && GetCharAt(GetCurrentPos()) == ')'
1398 && BraceMatch(GetCurrentPos()) != wxSTC_INVALID_POSITION)
1399 {
1400 GotoPos(GetCurrentPos()+1);
1401 return;
1402 }
1403 }
1404 else if (event.ShiftDown() && chr == '2')
1405 {
1406 if (isStyleType(STYLE_STRING, GetCurrentPos()-1)
1407 && GetCharAt(GetCurrentPos()) == '"'
1408 && GetCharAt(GetCurrentPos()-1) != '\\')
1409 {
1410 GotoPos(GetCurrentPos()+1);
1411 return;
1412 }
1413 }
1414 else if (event.ControlDown() && event.AltDown() && chr == '9') // Alt Gr means CTRL+ALT
1415 {
1416 if (!isStyleType(STYLE_STRING, GetCurrentPos())
1417 && GetCharAt(GetCurrentPos()) == ']'
1418 && BraceMatch(GetCurrentPos()) != wxSTC_INVALID_POSITION)
1419 {
1420 GotoPos(GetCurrentPos()+1);
1421 return;
1422 }
1423 }
1424 else if (event.ControlDown() && event.AltDown() && chr == '0')
1425 {
1426 if (!isStyleType(STYLE_STRING, GetCurrentPos())
1427 && GetCharAt(GetCurrentPos()) == '}'
1428 && BraceMatch(GetCurrentPos()) != wxSTC_INVALID_POSITION)
1429 {
1430 GotoPos(GetCurrentPos()+1);
1431 return;
1432 }
1433 }
1434 }
1435 }
1436
1437 // If the autocompletion dialog is open, we want the HOME and END
1438 // keys to automatically close it. Otherwise they are used
1439 // to navigate in the autocompletion list
1440 if (AutoCompActive()
1442 && (event.GetKeyCode() == WXK_END || event.GetKeyCode() == WXK_HOME))
1443 AutoCompCancel();
1444
1445 // Pass the control to the internal OnKeyDown event
1446 // handler, which will insert the correct character
1447 OnKeyDown(event);
1448
1449 // Apply the brace match indicator, if we have only
1450 // one or no selection
1451 if (this->GetSelections() <= 1)
1453
1454 // Apply the block match indicator
1456
1457 // Clear the double click occurence highlighter,
1458 // if the user doesn't press Ctrl or Shift.
1459 if (!event.ControlDown() && !event.ShiftDown())
1461}
1462
1463
1473void NumeReEditor::OnKeyRel(wxKeyEvent& event)
1474{
1475 if (this->GetSelections() <= 1)
1477
1478 m_nLastReleasedKey = event.GetKeyCode();
1479
1481 event.Skip();
1482 CallAfter(NumeReEditor::AsynchActions);
1483}
1484
1485
1495void NumeReEditor::OnMouseUp(wxMouseEvent& event)
1496{
1500 CallAfter(NumeReEditor::AsynchActions);
1501 event.Skip();
1502}
1503
1504
1515void NumeReEditor::OnMouseDn(wxMouseEvent& event)
1516{
1517 if (!event.ControlDown())
1519
1522 event.Skip();
1523}
1524
1525
1535void NumeReEditor::OnMouseDblClk(wxMouseEvent& event)
1536{
1537 int charpos = PositionFromPoint(event.GetPosition());
1538 int startPosition = WordStartPosition(charpos, true);
1539 int endPosition = WordEndPosition(charpos, true);
1540 wxString selection = this->GetTextRange(startPosition, endPosition);
1541
1542 // Ensure the user has selected a word
1543 if (!selection.length())
1544 {
1545 event.Skip();
1546 return;
1547 }
1548
1549 // Handle the control key and add the current selection
1550 // to the already existing one
1551 if (event.ControlDown() && this->HasSelection())
1552 this->AddSelection(endPosition, startPosition);
1553 else
1554 this->SetSelection(startPosition, endPosition);
1555
1557 long int maxpos = GetLastPosition();
1558
1559 // Update the Indicators
1560 SetIndicatorCurrent(HIGHLIGHT_DBLCLK);
1561 IndicatorClearRange(0, maxpos);
1562
1563 int nPos = 0;
1564 int nCurr = 0;
1565 int nLength = endPosition - startPosition;
1566 vector<int> vSelectionList;
1567
1568 // Find all occurences and store them in a vector
1569 while ((nPos = FindText(nCurr, maxpos, selection, wxSTC_FIND_MATCHCASE | wxSTC_FIND_WHOLEWORD)) != wxNOT_FOUND)
1570 {
1571 vSelectionList.push_back(nPos);
1572 nCurr = nPos + nLength;
1573 }
1574
1575 // Highlight the occurences
1576 for (size_t i = 0; i < vSelectionList.size(); i++)
1577 this->IndicatorFillRange(vSelectionList[i], nLength);
1578
1579 event.Skip();
1580}
1581
1582
1593void NumeReEditor::OnMouseCaptureLost(wxMouseCaptureLostEvent& event)
1594{
1595 if (GetCapture() == this)
1596 {
1597 ReleaseMouse();
1598 Refresh();
1599 }
1600}
1601
1602
1612void NumeReEditor::OnEnter(wxMouseEvent& event)
1613{
1614 if (g_findReplace != nullptr && g_findReplace->IsShown())
1615 {
1616 event.Skip();
1617 return;
1618 }
1619
1620 this->SetFocus();
1621 event.Skip();
1622}
1623
1624
1633void NumeReEditor::OnLeave(wxMouseEvent& event)
1634{
1635 // if (this->CallTipActive())
1636 // this->AdvCallTipCancel();
1637
1638 event.Skip();
1639}
1640
1641
1650void NumeReEditor::OnLoseFocus(wxFocusEvent& event)
1651{
1652 if (this->CallTipActive())
1653 this->AdvCallTipCancel();
1654
1655 event.Skip();
1656}
1657
1658
1670void NumeReEditor::OnMouseDwell(wxStyledTextEvent& event)
1671{
1672 if ((m_fileType != FILE_NSCR && m_fileType != FILE_NPRC) || m_PopUpActive || !this->HasFocus())
1673 return;
1674
1675 int charpos = event.GetPosition();
1676 int startPosition = WordStartPosition(charpos, true);
1677 int endPosition = WordEndPosition(charpos, true);
1678 static NumeRe::CallTipProvider _provider = *m_terminal->getProvider();
1679
1680 wxString selection = this->GetTextRange(startPosition, endPosition);
1681 NumeRe::CallTip _cTip;
1682
1683 if (GetStyleAt(charpos) == wxSTC_NSCR_FUNCTION)
1684 _cTip = _provider.getFunction(selection.ToStdString());
1685 else if (GetStyleAt(charpos) == wxSTC_NSCR_COMMAND
1686 || GetStyleAt(charpos) == wxSTC_NSCR_PROCEDURE_COMMANDS)
1687 {
1688 // Is it a block?
1689 int id = getBlockID(selection);
1690
1691 if (id != wxNOT_FOUND)
1692 {
1693 if (CallTipActive() && m_nCallTipStart == startPosition)
1694 return;
1695
1697
1698 size_t lastpos = 0;
1699 size_t nLength = 0;
1700 size_t lastpos2 = 0;
1701
1702 // Get the block definition
1703 SyntaxBlockDefinition blockDef = vBlockDefs[id];
1704
1705 // Construct the tooltip
1706 std::string sBlock = addLinebreaks(realignLangString(_guilang.get("PARSERFUNCS_LISTCMD_CMD_"
1707 + toUpperCase(blockDef.startWord)
1708 + "_*"), lastpos)) + "\n [...]\n";
1709
1710 if (selection != blockDef.startWord)
1711 nLength = sBlock.length() + countUmlauts(sBlock);
1712
1713 // Include middle words
1714 if (blockDef.middleWord1.length())
1715 {
1716 sBlock += addLinebreaks(realignLangString(_guilang.get("PARSERFUNCS_LISTCMD_CMD_"
1717 + toUpperCase(blockDef.middleWord1)
1718 + "_*"), lastpos2)) + "\n [...]\n";
1719
1720 if (selection != blockDef.startWord && selection != blockDef.middleWord1)
1721 nLength = sBlock.length() + countUmlauts(sBlock);
1722 }
1723
1724 // Include middle words
1725 if (blockDef.middleWord2.length())
1726 {
1727 sBlock += addLinebreaks(_guilang.get("PARSERFUNCS_LISTCMD_CMD_"
1728 + toUpperCase(blockDef.middleWord2) + "_*"))
1729 + "\n [...]\n";
1730
1731 if (selection != blockDef.startWord && selection != blockDef.middleWord1 && selection != blockDef.middleWord2)
1732 nLength = sBlock.length() + countUmlauts(sBlock);
1733 }
1734
1735 // Add the last word
1736 sBlock += addLinebreaks(realignLangString(_guilang.get("PARSERFUNCS_LISTCMD_CMD_"
1737 + toUpperCase(blockDef.endWord)
1738 + "_*"), lastpos));
1739
1740 // Display the tooltip and highlight the corresponding positions
1741 AdvCallTipShow(startPosition, sBlock);
1742 CallTipSetHighlight(nLength, selection.length() + nLength);
1743 return;
1744 }
1745 else
1746 _cTip = _provider.getCommand(selection.ToStdString());
1747 }
1748 else if (GetStyleAt(charpos) == wxSTC_NSCR_PROCEDURES)
1749 {
1750 if (GetCharAt(charpos) != '$')
1751 startPosition--;
1752
1753 if (CallTipActive() && m_nCallTipStart == startPosition)
1754 return;
1755
1757
1758 wxString proc = m_search->FindMarkedProcedure(charpos);
1759
1760 if (!proc.length())
1761 return;
1762
1763 wxString procdef = m_search->FindProcedureDefinition();
1764 wxString flags = "";
1765
1766 if (!procdef.length())
1767 procdef = m_clickedProcedure + "(...)";
1768
1769 size_t nSepPos = std::string::npos;
1770
1771 if (procdef.find("::") != std::string::npos)
1772 nSepPos = procdef.find("::");
1773 else if (procdef.find(" -> ") != std::string::npos)
1774 nSepPos = procdef.find(" -> ");
1775 else if (procdef.find('\n') != std::string::npos)
1776 nSepPos = procdef.find('\n');
1777
1778 if (nSepPos != std::string::npos)
1779 {
1780 flags = procdef.substr(nSepPos);
1781 procdef.erase(nSepPos);
1782 }
1783
1784 if (flags.find('\n') != string::npos)
1785 AdvCallTipShow(startPosition, procdef + flags);
1786 else
1787 AdvCallTipShow(startPosition, procdef + flags + "\n " + _guilang.get("GUI_EDITOR_CALLTIP_PROC2"));
1788
1789 CallTipSetHighlight(0, procdef.length());
1790 return;
1791 }
1792 else if (GetStyleAt(charpos) == wxSTC_NSCR_OPTION)
1793 _cTip = _provider.getOption(selection.ToStdString());
1794 else if (GetStyleAt(charpos) == wxSTC_NSCR_METHOD)
1795 _cTip = _provider.getMethod(selection.ToStdString());
1796 else if (GetStyleAt(charpos) == wxSTC_NSCR_PREDEFS)
1797 _cTip = _provider.getPredef(selection.ToStdString());
1798 else if (GetStyleAt(charpos) == wxSTC_NSCR_CONSTANTS)
1799 _cTip = _provider.getConstant(selection.ToStdString());
1800
1801 if (_cTip.sDefinition.length())
1802 {
1803 if (CallTipActive() && m_nCallTipStart == startPosition)
1804 return;
1805 else
1807
1808 AdvCallTipShow(startPosition, _cTip.sDefinition + (_cTip.sDocumentation.length() ? "\n" + _cTip.sDocumentation : ""));
1809 CallTipSetHighlight(_cTip.nStart, _cTip.nEnd);
1810 }
1811}
1812
1813
1826void NumeReEditor::OnIdle(wxIdleEvent& event)
1827{
1829 return;
1830
1831 m_modificationHappened = false;
1832 m_analyzerTimer->StartOnce(750);
1833}
1834
1835
1845void NumeReEditor::OnAnalyzerTimer(wxTimerEvent& event)
1846{
1848}
1849
1850
1862void NumeReEditor::OnSavePointReached(wxStyledTextEvent& event)
1863{
1864 markSaved();
1865 m_bSetUnsaved = false;
1866 event.Skip();
1867}
1868
1869
1881void NumeReEditor::OnSavePointLeft(wxStyledTextEvent& event)
1882{
1883 SetUnsaved();
1884}
1885
1886
1896void NumeReEditor::OnAutoCompletion(wxStyledTextEvent& event)
1897{
1898 // Is the autocompleted text a function or
1899 // a control flow statement?
1900 if (event.GetText()[event.GetText().length()-1] == '(')
1901 {
1902 // Ensure that there's actually a need for a new
1903 // parenthesis and insert a closed pair
1905 && (GetCharAt(GetCurrentPos()) != '(' || BraceMatch(GetCurrentPos()) == wxSTC_INVALID_POSITION))
1906 InsertText(GetCurrentPos(), "()");
1907
1908 // Replace the current text with the function's
1909 // name without the parenthesis
1910 Replace(event.GetPosition(), GetCurrentPos(), event.GetText().substr(0, event.GetText().length()-1));
1911
1912 // Jump into the parenthesis
1913 GotoPos(event.GetPosition() + event.GetText().length() - !m_options->getSetting(SETTING_B_BRACEAUTOCOMP).active());
1914 AutoCompCancel();
1915 }
1916 else if (event.GetText()[event.GetText().length()-1] == '{')
1917 {
1918 // Ensure that there's actually a need for a new
1919 // parenthesis and insert a closed pair
1921 && (GetCharAt(GetCurrentPos()) != '{' || BraceMatch(GetCurrentPos()) == wxSTC_INVALID_POSITION))
1922 InsertText(GetCurrentPos(), "{}");
1923
1924 // Replace the current text with the function's
1925 // name without the parenthesis
1926 Replace(event.GetPosition(), GetCurrentPos(), event.GetText().substr(0, event.GetText().length()-1));
1927
1928 // Jump into the parenthesis
1929 GotoPos(event.GetPosition() + event.GetText().length() - !m_options->getSetting(SETTING_B_BRACEAUTOCOMP).active());
1930 AutoCompCancel();
1931 }
1932 else if (m_options->getSetting(SETTING_B_BLOCKAUTOCOMP).active() && isBlockStart(event.GetText(), true) != wxNOT_FOUND)
1933 {
1934 // Get the autocompletion block and find
1935 // the pipe position
1936 wxString sAutoComp = getBlockAutoCompletion(event.GetText());
1937 size_t pos = sAutoComp.find('|');
1938
1939 // Remove the pipe position
1940 sAutoComp.erase(pos, 1);
1941
1942 // Replace the current text with the
1943 // complete autocompletion text
1944 Replace(event.GetPosition(), GetCurrentPos(), sAutoComp);
1945
1946 // Copy the line indentation for the second statement,
1947 // if needed
1948 if (sAutoComp.find("\r\n") != std::string::npos)
1949 SetLineIndentation(LineFromPosition(event.GetPosition())+1, GetLineIndentation(LineFromPosition(event.GetPosition())));
1950
1951 // Goto the pipe position
1952 GotoPos(event.GetPosition() + pos);
1953 AutoCompCancel();
1954 }
1955}
1956
1957
1969{
1971 return;
1972
1973 int nFirstLine = 0;
1974 int nLastLine = 0;
1975 int nSelectionStart = -1;
1976 int nSelectionEnd = 0;
1977 int nCommentStyle = 0;
1978 int nCommentCharSequenceLen = 0;
1979 wxString sLineCommentCharSequence;
1980
1981 // Determine the parameters for line comments
1983 {
1984 sLineCommentCharSequence = "## ";
1985 nCommentStyle = wxSTC_NSCR_COMMENT_LINE;
1986 }
1987 else if (m_fileType == FILE_TEXSOURCE)
1988 {
1989 sLineCommentCharSequence = "% ";
1990 nCommentStyle = wxSTC_TEX_DEFAULT;
1991 }
1992 else if (m_fileType == FILE_DATAFILES)
1993 {
1994 sLineCommentCharSequence = "# ";
1995 nCommentStyle = wxSTC_MATLAB_COMMENT;
1996 }
1997 else if (m_fileType == FILE_MATLAB)
1998 {
1999 sLineCommentCharSequence = "% ";
2000 nCommentStyle = wxSTC_MATLAB_COMMENT;
2001 }
2002 else if (m_fileType == FILE_CPP)
2003 {
2004 sLineCommentCharSequence = "// ";
2005 nCommentStyle = wxSTC_C_COMMENTLINE;
2006 }
2007
2008 nCommentCharSequenceLen = sLineCommentCharSequence.length();
2009
2010 // Get start and end of the commenting
2011 if (HasSelection())
2012 {
2013 nSelectionStart = GetSelectionStart();
2014 nSelectionEnd = GetSelectionEnd();
2015 nFirstLine = LineFromPosition(nSelectionStart);
2016 nLastLine = LineFromPosition(nSelectionEnd);
2017 }
2018 else
2019 {
2020 nFirstLine = GetCurrentLine();
2021 nLastLine = nFirstLine;
2022 }
2023
2024 BeginUndoAction();
2025
2026 // Go through the code section and toggle every comment line
2027 for (int i = nFirstLine; i <= nLastLine; i++)
2028 {
2029 int position = PositionFromLine(i);
2030
2031 while (GetCharAt(position) == ' ' || GetCharAt(position) == '\t')
2032 position++;
2033
2034 int style = GetStyleAt(position);
2035
2036 // TeX file syntax highlighting requires a special handling
2037 if ((m_fileType == FILE_TEXSOURCE && GetStyleAt(position + 1) == wxSTC_TEX_DEFAULT && GetCharAt(position) == '%')
2038 || (m_fileType != FILE_TEXSOURCE && style == nCommentStyle))
2039 {
2040 // Remove the line comment characters
2041 if (GetCharAt(position + nCommentCharSequenceLen-1) == ' ')
2042 {
2043 // With the separating whitespace
2044 if (i == nFirstLine && nSelectionStart >= 0 && nSelectionStart >= position + nCommentCharSequenceLen)
2045 nSelectionStart -= nCommentCharSequenceLen;
2046 else if (i == nFirstLine && nSelectionStart >= 0)
2047 nSelectionStart = position;
2048
2049 DeleteRange(position, nCommentCharSequenceLen);
2050 nSelectionEnd -= nCommentCharSequenceLen;
2051 }
2052 else
2053 {
2054 // Without the separating whitespace
2055 if (i == nFirstLine && nSelectionStart >= 0 && nSelectionStart >= position + nCommentCharSequenceLen-1)
2056 nSelectionStart -= nCommentCharSequenceLen-1;
2057 else if (i == nFirstLine && nSelectionStart >= 0)
2058 nSelectionStart = position;
2059
2060 DeleteRange(position, nCommentCharSequenceLen-1);
2061 nSelectionEnd -= nCommentCharSequenceLen-1;
2062 }
2063 }
2064 else if ((m_fileType == FILE_TEXSOURCE && (GetStyleAt(position + 1) != wxSTC_TEX_DEFAULT || GetCharAt(position) != '%'))
2065 || (m_fileType != FILE_TEXSOURCE && style != nCommentStyle))
2066 {
2067 // Add line comment characters
2068 InsertText(PositionFromLine(i), sLineCommentCharSequence);
2069
2070 if (nSelectionStart >= 0)
2071 {
2072 nSelectionStart += nCommentCharSequenceLen;
2073 nSelectionEnd += nCommentCharSequenceLen;
2074 }
2075 }
2076 }
2077
2078 if (nSelectionStart >= 0)
2079 SetSelection(nSelectionStart, nSelectionEnd);
2080
2081 EndUndoAction();
2082}
2083
2084
2097{
2099 return;
2100
2101 // Only works, if the user selected some code
2102 if (!HasSelection())
2103 return;
2104
2105 int nFirstPosition = GetSelectionStart();
2106 int nLastPosition = GetSelectionEnd();
2107 int nSelectionStart = nFirstPosition;
2108 int nSelectionEnd = nLastPosition;
2109 int style = GetStyleAt(nFirstPosition);
2110 int nCommentStyle = wxSTC_NSCR_COMMENT_BLOCK;
2111 wxString sBlockCommentStart = "#* ";
2112 wxString sBlockCommentEnd = " *#";
2113
2114 // Some code segments do not have block comments
2115 if (m_fileType != FILE_NSCR
2116 && m_fileType != FILE_NPRC
2117 && m_fileType != FILE_XML
2118 && m_fileType != FILE_CPP)
2119 {
2121 return;
2122 }
2123
2124 // Change characters and style for C++ or XML files
2125 if (m_fileType == FILE_CPP)
2126 {
2127 sBlockCommentEnd = " */";
2128 sBlockCommentStart = "/* ";
2129 nCommentStyle = wxSTC_C_COMMENT;
2130 }
2131 else if (m_fileType == FILE_XML)
2132 {
2133 sBlockCommentEnd = " -->";
2134 sBlockCommentStart = "<!-- ";
2135 nCommentStyle = wxSTC_H_COMMENT;
2136 }
2137
2138 BeginUndoAction();
2139
2140 if (style == nCommentStyle)
2141 {
2142 // Position before
2143 while (nFirstPosition && GetStyleAt(nFirstPosition - 1) == nCommentStyle)
2144 nFirstPosition--;
2145
2146 if (GetStyleAt(nLastPosition) != nCommentStyle)
2147 nLastPosition = nFirstPosition;
2148
2149 // Position after
2150 while (nLastPosition < GetLastPosition() && GetStyleAt(nLastPosition) == nCommentStyle)
2151 nLastPosition++;
2152
2153 // Remove the trailing block comment sequence
2154 if (GetTextRange(nLastPosition - sBlockCommentEnd.length(), nLastPosition) == sBlockCommentEnd)
2155 {
2156 if (nSelectionEnd > nLastPosition - (int)sBlockCommentEnd.length())
2157 nSelectionEnd -= sBlockCommentEnd.length();
2158
2159 DeleteRange(nLastPosition - sBlockCommentEnd.length(), sBlockCommentEnd.length());
2160 }
2161 else
2162 {
2163 if (nSelectionEnd > nLastPosition - (int)sBlockCommentEnd.length() + 1)
2164 nSelectionEnd -= sBlockCommentEnd.length() - 1;
2165
2166 DeleteRange(nFirstPosition - sBlockCommentEnd.length() + 1, sBlockCommentEnd.length() - 1);
2167 }
2168
2169 // Remove the leading block comment sequence
2170 if (GetTextRange(nFirstPosition, nFirstPosition + sBlockCommentStart.length()) == sBlockCommentStart)
2171 {
2172 if (nFirstPosition != nSelectionStart)
2173 nSelectionStart -= sBlockCommentStart.length();
2174
2175 DeleteRange(nFirstPosition, sBlockCommentStart.length());
2176 nSelectionEnd -= sBlockCommentStart.length();
2177 }
2178 else
2179 {
2180 if (nFirstPosition != nSelectionStart)
2181 nSelectionStart -= sBlockCommentStart.length() - 1;
2182
2183 DeleteRange(nFirstPosition, sBlockCommentStart.length() - 1);
2184 nSelectionEnd -= sBlockCommentStart.length() - 1;
2185 }
2186 }
2187 else
2188 {
2189 // Embed the selection into a block comment
2190 InsertText(nFirstPosition, sBlockCommentStart);
2191 InsertText(nLastPosition + sBlockCommentStart.length(), sBlockCommentEnd);
2192 nSelectionEnd += sBlockCommentEnd.length();
2193 nSelectionStart += sBlockCommentStart.length();
2194 }
2195
2196 EndUndoAction();
2197 SetSelection(nSelectionStart, nSelectionEnd);
2198}
2199
2200
2208{
2209 for (int i = GetLineCount() - 1; i >= 0; i--)
2210 {
2211 if (GetFoldLevel(i) & wxSTC_FOLDLEVELHEADERFLAG && GetFoldExpanded(i))
2212 ToggleFold(i);
2213 }
2214}
2215
2216
2224{
2225 for (int i = 0; i < GetLineCount(); i++)
2226 {
2227 if (GetFoldLevel(i) & wxSTC_FOLDLEVELHEADERFLAG && !GetFoldExpanded(i))
2228 ToggleFold(i);
2229 }
2230}
2231
2232
2243{
2244 int nCurrentLine = GetCurrentLine();
2245
2246 // Leave the line, if it contains already one of both markers
2247 if (MarkerOnLine(nCurrentLine, MARKER_BOOKMARK) || MarkerOnLine(nCurrentLine, MARKER_SECTION))
2248 {
2249 if (down)
2250 nCurrentLine++;
2251 else
2252 nCurrentLine--;
2253 }
2254
2255 int nMarker;
2256 int nMarkerMask = (1 << MARKER_BOOKMARK) | (1 << MARKER_SECTION);
2257
2258 // Find the next marker
2259 if (down)
2260 nMarker = MarkerNext(nCurrentLine, nMarkerMask);
2261 else
2262 nMarker = MarkerPrevious(nCurrentLine, nMarkerMask);
2263
2264 // Wrap around the search, if nothing was found
2265 if (nMarker == -1)
2266 {
2267 if (down)
2268 nMarker = MarkerNext(0, nMarkerMask);
2269 else
2270 nMarker = MarkerPrevious(LineFromPosition(GetLastPosition()), nMarkerMask);
2271 }
2272
2273 // Go to the marker, if a marker was found
2274 if (nMarker != -1)
2275 GotoLine(nMarker);
2276}
2277
2278
2288{
2289 vector<int> vBookmarks;
2290
2291 // Find all bookmark markers in the document
2292 for (int i = 0; i < GetLineCount(); i++)
2293 {
2295 vBookmarks.push_back(i);
2296 }
2297
2298 return vBookmarks;
2299}
2300
2301
2311void NumeReEditor::setBookmarks(const vector<int>& vBookmarks)
2312{
2313 // Remove all available bookmark markers
2314 MarkerDeleteAll(MARKER_BOOKMARK);
2315
2316 // Set the list of bookmarks
2317 for (size_t i = 0; i < vBookmarks.size(); i++)
2318 {
2319 MarkerAdd(vBookmarks[i], MARKER_BOOKMARK);
2320 }
2321}
2322
2323
2336{
2337 int nFirstline = 0;
2338 int nLastLine = GetLineCount() - 1;
2339
2340 // If the user selected something, use the
2341 // selection as begin and end lines
2342 if (HasSelection())
2343 {
2344 nFirstline = LineFromPosition(GetSelectionStart());
2345 nLastLine = LineFromPosition(GetSelectionEnd());
2346 }
2347
2348 BeginUndoAction();
2349
2350 // Go through each line and remove the white
2351 // spaces depending on the selected type
2352 for (int i = nFirstline; i <= nLastLine; i++)
2353 {
2354 if (nType == RM_WS_FRONT)
2355 SetLineIndentation(i, 0);
2356 else if (nType == RM_WS_BACK || nType == RM_WS_BOTH)
2357 {
2358 wxString sLine = this->GetLine(i);
2359
2360 if (sLine.find_first_of("\r\n") != string::npos)
2361 sLine.erase(sLine.find_first_of("\r\n"));
2362
2363 int nLineEndPos = sLine.length();
2364
2365 while (nLineEndPos && (sLine[nLineEndPos - 1] == ' ' || sLine[nLineEndPos - 1] == '\t'))
2366 {
2367 sLine.erase(nLineEndPos - 1);
2368 nLineEndPos--;
2369 }
2370
2371 if (nType == RM_WS_BOTH)
2372 {
2373 while (sLine[0] == ' ' || sLine[0] == '\t')
2374 sLine.erase(0, 1);
2375 }
2376
2377 Replace(this->PositionFromLine(i), this->GetLineEndPosition(i), sLine);
2378 }
2379 }
2380
2381 EndUndoAction();
2382}
2383
2384
2392{
2393 int nLine = GetCurrentLine();
2394
2395 if (MarkerOnLine(nLine, MARKER_BOOKMARK))
2396 MarkerDelete(nLine, MARKER_BOOKMARK);
2397 else
2398 MarkerAdd(nLine, MARKER_BOOKMARK);
2399}
2400
2401
2410{
2411 this->MarkerDeleteAll(MARKER_BOOKMARK);
2412}
2413
2414
2426{
2427 int nFirstline = 0;
2428 int nLastLine = GetLineCount() - 1;
2429 map<string, int> mSortMap;
2430 vector<wxString> vSortVector;
2431 string sCurrentLine;
2432
2433 // Use the selection, if it has any
2434 if (HasSelection())
2435 {
2436 nFirstline = LineFromPosition(GetSelectionStart());
2437 nLastLine = LineFromPosition(GetSelectionEnd());
2438 }
2439
2440 BeginUndoAction();
2441
2442 // Copy the contents between starting and ending
2443 // line into a vector omitting the trailing line
2444 // ending characters. The contents are also converted
2445 // into a lowercase standard string and stored into a map
2446 for (int i = nFirstline; i <= nLastLine; i++)
2447 {
2448 // Store the line in the vector
2449 vSortVector.push_back(this->GetLine(i));
2450
2451 if (vSortVector[i - nFirstline].find_first_of("\r\n") != string::npos)
2452 vSortVector[i - nFirstline].erase(vSortVector[i - nFirstline].find_first_of("\r\n"));
2453
2454 // Transform it to a lowercase standard string
2455 sCurrentLine = toLowerCase(vSortVector[i - nFirstline].ToStdString());
2456 StripSpaces(sCurrentLine);
2457
2458 if (!sCurrentLine.length())
2459 sCurrentLine = " " + toString(i + 256);
2460
2461 if (mSortMap.find(sCurrentLine) != mSortMap.end())
2462 sCurrentLine += "\n" + toString(i + 256); // need a value smaller than space therefore the \n
2463
2464 // Store it in a map
2465 mSortMap[sCurrentLine] = i - nFirstline;
2466 }
2467
2468 // Use the map auto-sorting feature to refill the section
2469 // with the sorted lines
2470 if (ascending)
2471 {
2472 for (auto iter = mSortMap.begin(); iter != mSortMap.end(); ++iter)
2473 {
2474 this->Replace(this->PositionFromLine(nFirstline), this->GetLineEndPosition(nFirstline), vSortVector[iter->second]);
2475 nFirstline++;
2476 }
2477 }
2478 else
2479 {
2480 for (auto iter = mSortMap.rbegin(); iter != mSortMap.rend(); ++iter)
2481 {
2482 this->Replace(this->PositionFromLine(nFirstline), this->GetLineEndPosition(nFirstline), vSortVector[iter->second]);
2483 nFirstline++;
2484 }
2485 }
2486
2487 EndUndoAction();
2488}
2489
2490
2499static char applyFunctionHeuristics(const std::string& func)
2500{
2501 // Check the following special cases
2502 if (func == "time" || func == "clock" || func == "to_time")
2503 return 't';
2504
2505 // Find the key for the corresponding language string
2506 std::string sKey = _guilang.getKey("PARSERFUNCS_LISTFUNC_FUNC_" + toUpperCase(func) + "_[*]");
2507 std::string sRetVal = _guilang.get(sKey);
2508 sRetVal.erase(0, sRetVal.find_first_not_of(' ', sRetVal.find(')')+1));
2509 sRetVal.erase(sRetVal.find_first_of(" -"));
2510
2511 // Use the documented return value to determine the type
2512 // of the variable
2513 if (sRetVal == "VAL" || sRetVal == "{VAL}" || sRetVal == "MAT" || sRetVal == "VEC")
2514 return 'f';
2515 else if (sRetVal == "LOG" || sRetVal == "{LOG}")
2516 return 'b';
2517 else if (sRetVal == "STR" || sRetVal == "{STR}")
2518 return 's';
2519 else if (sRetVal == "ARG" || sRetVal == "{ARG}")
2520 return 0; // Not detectable here
2521
2522 return 'f';
2523}
2524
2525
2534static char applyCommandHeuristics(const std::string& command)
2535{
2536 // Find the key for the corresponding language string
2537 std::string sKey = _guilang.getKey("PARSERFUNCS_LISTCMD_CMD_" + toUpperCase(command) + "_[*]");
2538 std::string sRetVal = _guilang.get(sKey);
2539
2540 if (sRetVal.find("->") == std::string::npos)
2541 return 0; // s.th.s is clearly wrong here
2542
2543 sRetVal.erase(0, sRetVal.find_first_not_of(' ', sRetVal.find("->")+2));
2544 sRetVal.erase(sRetVal.find_first_of(" -"));
2545
2546 // Use the documented return value to determine the type
2547 // of the variable
2548 if (sRetVal == "VAL" || sRetVal == "{VAL}" || sRetVal == "MAT" || sRetVal == "VEC")
2549 return 'f';
2550 else if (sRetVal == "LOG" || sRetVal == "{LOG}")
2551 return 'b';
2552 else if (sRetVal == "STR" || sRetVal == "{STR}")
2553 return 's';
2554 else if (sRetVal == "ARG" || sRetVal == "{ARG}")
2555 return 0; // Not detectable here
2556
2557 return 'f';
2558}
2559
2560
2569static char applyValueHeuristics(std::string val)
2570{
2571 val = getNextArgument(val);
2572
2573 if (val.find("##") != std::string::npos)
2574 val.erase(val.find("##"));
2575
2576 // We most probably have additional closing
2577 // parentheses
2578 if (!validateParenthesisNumber(val))
2579 {
2580 for (size_t i = 0; i < val.size(); i++)
2581 {
2582 if (val[i] == '(' || val[i] == '[' || val[i] == '{')
2583 {
2584 size_t pos = getMatchingParenthesis(StringView(val, i));
2585
2586 // S.th. is wrong
2587 if (pos == std::string::npos)
2588 return 0;
2589
2590 i += pos;
2591 continue;
2592 }
2593
2594 // These have to be unmatched
2595 if (val[i] == ')' || val[i] == ']' || val[i] == '}')
2596 {
2597 val.erase(i);
2598 break;
2599 }
2600 }
2601 }
2602
2603 StripSpaces(val);
2604
2605 if (val.back() == ';')
2606 val.pop_back();
2607
2608 if (val == "true" || val == "false")
2609 return 'b';
2610 else if (val.find_first_not_of("0123456789^, ") == std::string::npos)
2611 {
2612 if (val == "0") // 0 is too common
2613 return 0;
2614
2615 return 'n';
2616 }
2617 else if (val.find_first_of("/^'") != std::string::npos)
2618 return 'f';
2619 else if (val.length() > 2 && val[0] == '_' && std::islower(val[1]) && std::isupper(val[2]))
2620 return val[1];
2621 else if (val.length() > 1 && std::islower(val[0]) && std::isupper(val[1]))
2622 return val[0];
2623
2624 return 'f';
2625}
2626
2627
2638{
2639 if (m_fileType != FILE_NSCR && m_fileType != FILE_NPRC/* && m_fileType != FILE_MATLAB*/)
2640 return;
2641
2642 if (!isStyleType(STYLE_IDENTIFIER, pos))
2643 return;
2644
2645 // Get context
2646 std::pair<int, int> context = getCurrentContext(LineFromPosition(pos));
2647
2648 // Get the symbol's name below the cursor
2649 std::string sSymbol = GetTextRange(WordStartPosition(pos, true), WordEndPosition(pos, true)).ToStdString();
2650 std::string sOldName = sSymbol;
2651
2652 // Find all occurences
2653 std::vector<int> vMatches = m_search->FindAll(sSymbol, GetStyleAt(pos),
2654 PositionFromLine(context.first), GetLineEndPosition(context.second), false);
2655
2656 // Examine the first occurence
2657 wxString lineContent = GetLine(LineFromPosition(vMatches.front())).Strip(wxString::both);
2658
2659 // this character will contain the type of
2660 // this symbol once detected
2661 char type = 'f';
2662
2663 // Is it a variable definition?
2664 if (lineContent.StartsWith("str "))
2665 type = 's';
2666 else
2667 {
2668 // In all other cases, we need to examine the first assigned
2669 // value
2670 for (int match : vMatches)
2671 {
2672 match += sSymbol.length();
2673 int lineStartPosition = PositionFromLine(LineFromPosition(match));
2674 lineContent = GetLine(LineFromPosition(match)).Strip(wxString::both);
2675
2676 // This match is probably in a vector brace
2677 if (lineContent.rfind('{', match-lineStartPosition) != std::string::npos
2678 && lineContent.find('}', match-lineStartPosition) != std::string::npos)
2679 {
2680 int pos = match;
2681
2682 while (GetCharAt(pos) != '{')
2683 pos--;
2684
2685 pos = BraceMatch(pos);
2686
2687 // If the position is farther than the match, then
2688 // the match is part of a vector brace. We'll search
2689 // after the brace
2690 if (pos > match)
2691 match = pos+1;
2692 }
2693
2694 // Increment and decrement operators
2695 if (GetTextRange(match, match+2) == "++" || GetTextRange(match, match+2) == "--")
2696 {
2697 type = 'n';
2698 break;
2699 }
2700
2701 // Find the next character, which is no whitespace and not the initial
2702 // character of a definition
2703 while (GetCharAt(match) == ' ' || GetCharAt(match) == '\t' || GetCharAt(match) == ':')
2704 match++;
2705
2706 // Is it an assignment operator?
2707 if (GetCharAt(match) == '=' && GetCharAt(match+1) != '=')
2708 {
2709 // Move one char forward
2710 match++;
2711
2712 // Find the value
2713 while (GetCharAt(match) == ' ' || GetCharAt(match) == '\t')
2714 match++;
2715
2716 // Determine the type of the value. We'll default to
2717 // float
2718 if (isStyleType(STYLE_STRING, match) || GetStyleAt(match) == wxSTC_NSCR_STRING_PARSER)
2719 type = 's';
2720 else if (GetStyleAt(match) == wxSTC_NSCR_CONSTANTS)
2721 type = 'f';
2722 else if (isStyleType(STYLE_FUNCTION, match))
2723 {
2724 char funcType = applyFunctionHeuristics(GetTextRange(match, WordEndPosition(match, true)).ToStdString());
2725
2726 if (!funcType)
2727 continue;
2728
2729 type = funcType;
2730 }
2731 else if (isStyleType(STYLE_COMMAND, match))
2732 {
2733 char commandType = applyCommandHeuristics(GetTextRange(match, WordEndPosition(match, true)).ToStdString());
2734
2735 if (!commandType)
2736 continue;
2737
2738 type = commandType;
2739 }
2740 else
2741 {
2742 char valtype = applyValueHeuristics(GetTextRange(match, GetLineEndPosition(LineFromPosition(match))).ToStdString());
2743
2744 if (!valtype)
2745 continue;
2746
2747 type = valtype;
2748 }
2749
2750 // We have our information
2751 break;
2752 }
2753 }
2754 }
2755
2756 // Now create the fixed variable name
2757 CodeAnalyzer::changeVariableType(sSymbol, type);
2758
2759 if (sSymbol != sOldName)
2760 {
2761 int ret = wxMessageBox(_guilang.get("GUI_EDITOR_FIX_TYPE_MESSAGE", sOldName, sSymbol),
2762 _guilang.get("GUI_EDITOR_FIX_TYPE_TITLE"),
2763 wxCENTER | wxYES_NO,
2764 this);
2765
2766 if (ret == wxNO)
2767 return;
2768
2769 BeginUndoAction();
2770 // Now replace it everywhere
2771 ReplaceMatches(vMatches, sOldName, sSymbol);
2772 EndUndoAction();
2773 }
2774}
2775
2776
2787{
2788 m_duplicateCode = nullptr;
2789}
2790
2791
2802void NumeReEditor::SetEditorFont(const wxFont& font)
2803{
2804 wxFont newFont = font;
2805 StyleSetFont(wxSTC_STYLE_DEFAULT, newFont);
2806 StyleClearAll();
2808}
2809
2810
2820{
2821 return m_nEditorSetting & _setting;
2822}
2823
2824
2836{
2837 SetWhitespaceForeground(true, wxColor(170, 190, 210));
2838 SetWhitespaceSize(2);
2839
2840 // Determine, whether the corresponding setting
2841 // is already enabled
2842 if (!(m_nEditorSetting & _setting))
2843 {
2844 // Enable setting
2845 m_nEditorSetting |= _setting;
2846
2847 // Apply the necessary style calculations
2848 if (_setting & SETTING_WRAPEOL)
2849 {
2850 SetWrapMode(wxSTC_WRAP_WORD);
2851 SetWrapIndentMode(wxSTC_WRAPINDENT_INDENT);
2852 SetWrapStartIndent(1);
2853 SetWrapVisualFlags(wxSTC_WRAPVISUALFLAG_END);
2854 SetWrapVisualFlagsLocation(wxSTC_WRAPVISUALFLAGLOC_END_BY_TEXT);
2855 }
2856
2857 if (_setting & SETTING_DISPCTRLCHARS)
2858 {
2859 SetViewWhiteSpace(wxSTC_WS_VISIBLEALWAYS);
2860 SetViewEOL(true);
2861 }
2862
2863 if (_setting & SETTING_USESECTIONS)
2864 markSections(true);
2865 }
2866 else
2867 {
2868 // Disable setting
2869 m_nEditorSetting &= ~_setting;
2870
2871 // Apply the necessary style calculations
2872 if (_setting == SETTING_WRAPEOL)
2873 SetWrapMode(wxSTC_WRAP_NONE);
2874 else if (_setting == SETTING_DISPCTRLCHARS)
2875 {
2876 SetViewEOL(false);
2877 SetViewWhiteSpace(wxSTC_WS_INVISIBLE);
2878 }
2879 else if (_setting == SETTING_USETXTADV)
2880 {
2881 SetIndicatorCurrent(HIGHLIGHT_STRIKETHROUGH);
2882 IndicatorClearRange(0, GetLastPosition());
2883 }
2884 else if (_setting == SETTING_USESECTIONS)
2885 MarkerDeleteAll(MARKER_SECTION);
2886 }
2887
2889 m_analyzer->run();
2890}
2891
2892
2905{
2906 int nMatch = BraceMatch(nPos);
2907
2908 // Search the matching brace
2909 if (nMatch == wxSTC_INVALID_POSITION)
2910 BraceBadLight(nPos);
2911 else
2912 {
2913 // If one is found, then highlight the
2914 // the brace and the room in between
2915 SetIndicatorCurrent(HIGHLIGHT_MATCHING_BRACE);
2916 IndicatorClearRange(0, GetLastPosition());
2917
2918 if (nMatch < nPos)
2919 {
2920 BraceHighlight(nMatch, nPos);
2921 IndicatorFillRange(nMatch + 1, nPos - nMatch - 1);
2922 }
2923 else
2924 {
2925 BraceHighlight(nPos, nMatch);
2926 IndicatorFillRange(nPos + 1, nMatch - nPos - 1);
2927 }
2928 }
2929
2931}
2932
2933
2949{
2950 // Search all flow control statements
2951 vector<int> vMatch = BlockMatch(nPos);
2952
2953 if (vMatch.size() == 1 && vMatch[0] == wxSTC_INVALID_POSITION)
2954 return;
2955
2956 // Select the correct indicator for available
2957 // and missing blocks
2958 if (vMatch.front() == wxSTC_INVALID_POSITION || vMatch.back() == wxSTC_INVALID_POSITION)
2959 SetIndicatorCurrent(HIGHLIGHT_NOT_MATCHING_BLOCK);
2960 else
2961 SetIndicatorCurrent(HIGHLIGHT_MATCHING_BLOCK);
2962
2963 // Clear the indicators
2964 IndicatorClearRange(0, GetLastPosition());
2965
2966 // Highlight all occurences
2967 for (size_t i = 0; i < vMatch.size(); i++)
2968 {
2969 if (vMatch[i] == wxSTC_INVALID_POSITION)
2970 continue;
2971
2972 IndicatorFillRange(vMatch[i], WordEndPosition(vMatch[i], true) - vMatch[i]);
2973 }
2974
2976}
2977
2978
2994vector<int> NumeReEditor::BlockMatch(int nPos)
2995{
2996 // Select the correct helper function
2997 if (this->getFileType() == FILE_NSCR || this->getFileType() == FILE_NPRC)
2998 return BlockMatchNSCR(nPos);
2999 else if (this->getFileType() == FILE_MATLAB)
3000 return BlockMatchMATLAB(nPos);
3001 else
3002 {
3003 vector<int> vPos;
3004 vPos.push_back(wxSTC_INVALID_POSITION);
3005 return vPos;
3006 }
3007}
3008
3009
3019static bool isOnlyActiveBlock(int nBlockID, std::vector<int> vBlocks)
3020{
3021 for (size_t i = 0; i < vBlocks.size(); i++)
3022 {
3023 if ((int)i == nBlockID && vBlocks[i] != 1)
3024 return false;
3025 else if ((int)i != nBlockID && vBlocks[i])
3026 return false;
3027 }
3028
3029 return true;
3030}
3031
3032
3042vector<int> NumeReEditor::BlockMatchNSCR(int nPos)
3043{
3044 vector<int> vBlocks(vBlockDefs.size());
3045
3046 int nStartPos = WordStartPosition(nPos, true);
3047 vector<int> vPos;
3048 wxString startblock;
3049 wxString endblock;
3050
3051 int searchForMiddleWords = wxNOT_FOUND;
3052 int nSearchDir = 1; //direction in which to search for the matching block partner
3053
3054 if (GetStyleAt(nPos) != wxSTC_NSCR_COMMAND && GetStyleAt(nPos) != wxSTC_NPRC_COMMAND)
3055 {
3056 if (nPos && GetStyleAt(nPos - 1) == wxSTC_NSCR_COMMAND)
3057 nPos--;
3058 else
3059 {
3060 vPos.push_back(wxSTC_INVALID_POSITION);
3061 return vPos;
3062 }
3063 }
3064
3065 startblock = GetTextRange(WordStartPosition(nPos, true), WordEndPosition(nPos, true));
3066
3067 int blockMiddle = isBlockMiddle(startblock);
3068
3069 if (startblock.substr(0, 3) == "end")
3070 {
3071 endblock = getBlockStart(startblock);
3072 nSearchDir = -1;
3073 }
3074 else if (blockMiddle != wxNOT_FOUND)
3075 {
3076 // search for starting "if"
3077 // adding 1 to nIf, because we're already inside of an "if"
3078 vBlocks[blockMiddle]++;
3079
3080 for (int i = WordEndPosition(nPos, true); i >= 0; i--)
3081 {
3082 if (GetStyleAt(i) == wxSTC_NSCR_COMMAND)
3083 {
3084 wxString currentWord = GetTextRange(WordStartPosition(i, true), WordEndPosition(i, true));
3085
3086 int block = isBlockStart(currentWord, false);
3087
3088 // if we iterate upwards, the closing blocks shall increment and the opening blocks decrement the counter
3089 if (block != wxNOT_FOUND)
3090 vBlocks[block]--;
3091 else if ((block = isBlockEnd(currentWord)) != wxNOT_FOUND)
3092 vBlocks[block]++;
3093
3094 if (block == blockMiddle
3095 && !(*std::min_element(vBlocks.begin(), vBlocks.end()))
3096 && !(*std::max_element(vBlocks.begin(), vBlocks.end())))
3097 {
3098 nStartPos = WordStartPosition(i, true);
3099 break;
3100 }
3101
3102 i -= currentWord.length();
3103 }
3104
3105 if (*std::min_element(vBlocks.begin(), vBlocks.end()) < 0)
3106 {
3107 // There's no matching partner
3108 // set the first to invalid but do not return
3109 vPos.push_back(wxSTC_INVALID_POSITION);
3110 break;
3111 }
3112 }
3113
3114 if (*std::max_element(vBlocks.begin(), vBlocks.end()) > 0)
3115 {
3116 // There's no matching partner
3117 // set the first to invalid but do not return
3118 vPos.push_back(wxSTC_INVALID_POSITION);
3119 vBlocks.assign(vBlocks.size(), 0);
3120 vBlocks[blockMiddle] = 1;
3121 }
3122 else
3123 vBlocks.assign(vBlocks.size(), 0);
3124
3125 searchForMiddleWords = blockMiddle;
3126 endblock = getBlockEnd(startblock);
3127 }
3128 else
3129 endblock = getBlockEnd(startblock);
3130
3131 if (!endblock.length())
3132 {
3133 vPos.push_back(wxSTC_INVALID_POSITION);
3134 return vPos;
3135 }
3136
3137 if (hasBlockMiddle(endblock))
3138 searchForMiddleWords = getBlockID(endblock);
3139
3140 vPos.push_back(nStartPos);
3141
3142 if (nSearchDir == -1)
3143 nStartPos = WordEndPosition(nPos, true);
3144
3145 for (int i = nStartPos; (i < GetLastPosition() && i >= 0); i += nSearchDir) // iterates down, if nSearchDir == 1, and up of nSearchDir == -1
3146 {
3147 if (GetStyleAt(i) == wxSTC_NSCR_COMMAND)
3148 {
3149 wxString currentWord = GetTextRange(WordStartPosition(i, true), WordEndPosition(i, true));
3150
3151 int block = isBlockStart(currentWord, false);
3152
3153 // if we iterate upwards, the closing blocks shall increment and the opening blocks decrement the counter
3154 if (block != wxNOT_FOUND)
3155 vBlocks[block] += nSearchDir;
3156 else if ((block = isBlockEnd(currentWord)) != wxNOT_FOUND)
3157 vBlocks[block] -= nSearchDir;
3158
3159 // only in the current if block
3160 if (searchForMiddleWords != wxNOT_FOUND
3161 && isBlockMiddle(currentWord) == searchForMiddleWords
3162 && isOnlyActiveBlock(searchForMiddleWords, vBlocks))
3163 vPos.push_back(WordStartPosition(i, true));
3164
3165 if (currentWord == endblock
3166 && !(*std::min_element(vBlocks.begin(), vBlocks.end()))
3167 && !(*std::max_element(vBlocks.begin(), vBlocks.end())))
3168 {
3169 vPos.push_back(WordStartPosition(i, true));
3170 break;
3171 }
3172
3173 i += nSearchDir * currentWord.length();
3174 }
3175
3176 if (*std::min_element(vBlocks.begin(), vBlocks.end()) < 0)
3177 {
3178 // There's no matching partner
3179 vPos.push_back(wxSTC_INVALID_POSITION);
3180 break;
3181 }
3182 }
3183
3184 if (!vPos.size() || (*std::max_element(vBlocks.begin(), vBlocks.end()) > 0))
3185 vPos.push_back(wxSTC_INVALID_POSITION);
3186
3187 return vPos;
3188}
3189
3190
3201{
3202 int nBlock = 0;
3203
3204 int nStartPos = WordStartPosition(nPos, true);
3205 vector<int> vPos;
3206 wxString startblock;
3207 wxString endblock;
3208 bool bSearchForIf = false; //if we search for an if block element. If yes => also mark the "else..." parts.
3209 bool bSearchForSwitch = false;
3210 bool bSearchForCatch = false;
3211 int nSearchDir = 1; //direction in which to search for the matching block partner
3212
3213 if (GetStyleAt(nPos) != wxSTC_MATLAB_KEYWORD)
3214 {
3215 if (nPos && GetStyleAt(nPos - 1) == wxSTC_MATLAB_KEYWORD)
3216 nPos--;
3217 else
3218 {
3219 vPos.push_back(wxSTC_INVALID_POSITION);
3220 return vPos;
3221 }
3222 }
3223
3224
3225 startblock = GetTextRange(WordStartPosition(nPos, true), WordEndPosition(nPos, true));
3226
3227 if (startblock == "end")
3228 {
3229 // search for starting block
3230 // adding 1 to nBlock, because we're already inside of an "block"
3231 //nBlock++;
3232 for (int i = WordStartPosition(nPos, true); i >= 0; i--)
3233 {
3234 if (GetStyleAt(i) == wxSTC_MATLAB_KEYWORD)
3235 {
3236 wxString currentWord = GetTextRange(WordStartPosition(i, true), WordEndPosition(i, true));
3237
3238 if (currentWord == "for"
3239 || currentWord == "while"
3240 || currentWord == "function"
3241 || currentWord == "if"
3242 || currentWord == "switch"
3243 || currentWord == "try"
3244 || currentWord == "classdef"
3245 || currentWord == "properties"
3246 || currentWord == "methods")
3247 nBlock--;
3248 else if (currentWord == "end")
3249 nBlock++;
3250
3251 if (!nBlock)
3252 {
3253 nStartPos = WordStartPosition(i, true);
3254 startblock = currentWord;
3255 if (currentWord == "if")
3256 bSearchForIf = true;
3257 if (currentWord == "switch")
3258 bSearchForSwitch = true;
3259 if (currentWord == "try")
3260 bSearchForCatch = true;
3261 break;
3262 }
3263
3264 i -= currentWord.length();
3265 }
3266
3267 if (nBlock < 0)
3268 {
3269 // There's no matching partner
3270 // set the first to invalid but do not return
3271 vPos.push_back(wxSTC_INVALID_POSITION);
3272 break;
3273 }
3274 }
3275
3276 endblock = "end";
3277 }
3278 else if (startblock == "else" || startblock == "elseif")
3279 {
3280 // search for starting "if"
3281 // adding 1 to nBlock, because we're already inside of an "if"
3282 nBlock++;
3283 for (int i = WordEndPosition(nPos, true); i >= 0; i--)
3284 {
3285 if (GetStyleAt(i) == wxSTC_MATLAB_KEYWORD)
3286 {
3287 wxString currentWord = GetTextRange(WordStartPosition(i, true), WordEndPosition(i, true));
3288
3289 if (currentWord == "for"
3290 || currentWord == "while"
3291 || currentWord == "function"
3292 || currentWord == "if"
3293 || currentWord == "switch"
3294 || currentWord == "try"
3295 || currentWord == "classdef"
3296 || currentWord == "properties"
3297 || currentWord == "methods")
3298 nBlock--;
3299 else if (currentWord == "end")
3300 nBlock++;
3301
3302 if (currentWord == "if" && !nBlock)
3303 {
3304 nStartPos = WordStartPosition(i, true);
3305 startblock = "if";
3306 break;
3307 }
3308
3309 i -= currentWord.length();
3310 }
3311
3312 if (nBlock < 0)
3313 {
3314 // There's no matching partner
3315 // set the first to invalid but do not return
3316 vPos.push_back(wxSTC_INVALID_POSITION);
3317 break;
3318 }
3319 }
3320
3321 if (nBlock > 0)
3322 {
3323 // There's no matching partner
3324 // set the first to invalid but do not return
3325 vPos.push_back(wxSTC_INVALID_POSITION);
3326 nBlock = 1;
3327 }
3328 else
3329 nBlock = 0;
3330
3331 bSearchForIf = true;
3332 endblock = "end";
3333 }
3334 else if (startblock == "case" || startblock == "otherwise")
3335 {
3336 // search for starting "if"
3337 // adding 1 to nBlock, because we're already inside of an "if"
3338 nBlock++;
3339
3340 for (int i = WordEndPosition(nPos, true); i >= 0; i--)
3341 {
3342 if (GetStyleAt(i) == wxSTC_MATLAB_KEYWORD)
3343 {
3344 wxString currentWord = GetTextRange(WordStartPosition(i, true), WordEndPosition(i, true));
3345
3346 if (currentWord == "for"
3347 || currentWord == "while"
3348 || currentWord == "function"
3349 || currentWord == "if"
3350 || currentWord == "switch"
3351 || currentWord == "try"
3352 || currentWord == "classdef"
3353 || currentWord == "properties"
3354 || currentWord == "methods")
3355 nBlock--;
3356 else if (currentWord == "end")
3357 nBlock++;
3358
3359 if (currentWord == "switch" && !nBlock)
3360 {
3361 nStartPos = WordStartPosition(i, true);
3362 startblock = "switch";
3363 break;
3364 }
3365
3366 i -= currentWord.length();
3367 }
3368
3369 if (nBlock < 0)
3370 {
3371 // There's no matching partner
3372 // set the first to invalid but do not return
3373 vPos.push_back(wxSTC_INVALID_POSITION);
3374 break;
3375 }
3376 }
3377
3378 if (nBlock > 0)
3379 {
3380 // There's no matching partner
3381 // set the first to invalid but do not return
3382 vPos.push_back(wxSTC_INVALID_POSITION);
3383 nBlock = 1;
3384 }
3385 else
3386 nBlock = 0;
3387
3388 bSearchForSwitch = true;
3389 endblock = "end";
3390 }
3391 else if (startblock == "catch")
3392 {
3393 // search for starting "catch"
3394 // adding 1 to nBlock, because we're already inside of an "if"
3395 nBlock++;
3396
3397 for (int i = WordEndPosition(nPos, true); i >= 0; i--)
3398 {
3399 if (GetStyleAt(i) == wxSTC_MATLAB_KEYWORD)
3400 {
3401 wxString currentWord = GetTextRange(WordStartPosition(i, true), WordEndPosition(i, true));
3402
3403 if (currentWord == "for"
3404 || currentWord == "while"
3405 || currentWord == "function"
3406 || currentWord == "if"
3407 || currentWord == "switch"
3408 || currentWord == "try"
3409 || currentWord == "classdef"
3410 || currentWord == "properties"
3411 || currentWord == "methods")
3412 nBlock--;
3413 else if (currentWord == "end")
3414 nBlock++;
3415
3416 if (currentWord == "try" && !nBlock)
3417 {
3418 nStartPos = WordStartPosition(i, true);
3419 startblock = "try";
3420 break;
3421 }
3422
3423 i -= currentWord.length();
3424 }
3425
3426 if (nBlock < 0)
3427 {
3428 // There's no matching partner
3429 // set the first to invalid but do not return
3430 vPos.push_back(wxSTC_INVALID_POSITION);
3431 break;
3432 }
3433 }
3434
3435 if (nBlock > 0)
3436 {
3437 // There's no matching partner
3438 // set the first to invalid but do not return
3439 vPos.push_back(wxSTC_INVALID_POSITION);
3440 nBlock = 1;
3441 }
3442 else
3443 nBlock = 0;
3444
3445 bSearchForCatch = true;
3446 endblock = "end";
3447 }
3448
3449 if (startblock == "for"
3450 || startblock == "while"
3451 || startblock == "function"
3452 || startblock == "if"
3453 || startblock == "switch"
3454 || startblock == "try"
3455 || startblock == "classdef"
3456 || startblock == "properties"
3457 || startblock == "methods")
3458 endblock = "end";
3459 else
3460 {
3461 vPos.push_back(wxSTC_INVALID_POSITION);
3462 return vPos;
3463 }
3464
3465 if (startblock == "if" || endblock == "if")
3466 bSearchForIf = true;
3467
3468 if (startblock == "switch" || endblock == "switch")
3469 bSearchForSwitch = true;
3470
3471 if (startblock == "try" || endblock == "try")
3472 bSearchForCatch = true;
3473
3474 vPos.push_back(nStartPos);
3475
3476 //if (nSearchDir == -1)
3477 // nStartPos = WordEndPosition(nPos, true);
3478
3479 for (int i = nStartPos; (i < GetLastPosition() && i >= 0); i += nSearchDir) // iterates down, if nSearchDir == 1, and up of nSearchDir == -1
3480 {
3481 if (GetStyleAt(i) == wxSTC_MATLAB_KEYWORD)
3482 {
3483 wxString currentWord = GetTextRange(WordStartPosition(i, true), WordEndPosition(i, true));
3484
3485 if (currentWord == "for"
3486 || currentWord == "while"
3487 || currentWord == "function"
3488 || currentWord == "if"
3489 || currentWord == "switch"
3490 || currentWord == "try"
3491 || currentWord == "classdef"
3492 || currentWord == "properties"
3493 || currentWord == "methods")
3494 nBlock += nSearchDir; //if we iterate upwards, the closing blocks shall increment and the opening blocks decrement the counter
3495 else if (currentWord == "end")
3496 nBlock -= nSearchDir;
3497
3498 if (bSearchForIf && nBlock == 1 // only in the current if block
3499 && (currentWord == "else" || currentWord == "elseif"))
3500 vPos.push_back(WordStartPosition(i, true));
3501
3502 if (bSearchForSwitch && nBlock == 1 // only in the current if block
3503 && (currentWord == "case" || currentWord == "otherwise"))
3504 vPos.push_back(WordStartPosition(i, true));
3505
3506 if (bSearchForCatch && nBlock == 1 // only in the current if block
3507 && currentWord == "catch")
3508 vPos.push_back(WordStartPosition(i, true));
3509
3510 if (currentWord == endblock && !nBlock)
3511 {
3512 vPos.push_back(WordStartPosition(i, true));
3513 break;
3514 }
3515
3516 i += nSearchDir * currentWord.length();
3517 }
3518
3519 if (nBlock < 0)
3520 {
3521 // There's no matching partner
3522 vPos.push_back(wxSTC_INVALID_POSITION);
3523 break;
3524 }
3525 }
3526
3527 if (!vPos.size()
3528 || (nBlock > 0))
3529 vPos.push_back(wxSTC_INVALID_POSITION);
3530
3531 return vPos;
3532}
3533
3534
3544{
3545 bool result = m_fileNameAndPath.GetFullPath() != wxEmptyString;
3546 return result;// && !m_bSetUnsaved;
3547}
3548
3549
3557{
3558 m_bSetUnsaved = true;
3559}
3560
3561
3574{
3575 wxString filename = GetFileNameAndPath();
3576
3577 this->StyleSetBackground(wxSTC_STYLE_DEFAULT, m_options->GetSyntaxStyle(Options::STANDARD).background);
3578
3579 FileFilterType filetype = this->GetFileType(filename);
3580
3581 if (m_fileType != filetype)
3582 m_fileType = filetype;
3583 else if (!forceUpdate && (m_fileType == FILE_NSCR
3584 || m_fileType == FILE_NPRC
3588 || m_fileType == FILE_CPP))
3589 return;
3590
3591
3592 // make it for both: NSCR and NPRC
3593 if (filetype == FILE_NSCR || filetype == FILE_NPRC || filetype == FILE_MATLAB || filetype == FILE_CPP || filetype == FILE_DIFF)
3594 {
3595 SetFoldFlags(wxSTC_FOLDFLAG_LINEAFTER_CONTRACTED);
3596
3597 SetMarginType(MARGIN_FOLD, wxSTC_MARGIN_SYMBOL);
3598 SetMarginWidth(MARGIN_FOLD, 13);
3599 SetMarginMask(MARGIN_FOLD, wxSTC_MASK_FOLDERS);
3600 SetMarginSensitive(MARGIN_FOLD, true);
3601 StyleSetBackground(MARGIN_FOLD, wxColor(200, 200, 200) );
3602 SetMarginSensitive(MARGIN_FOLD, true);
3603
3604 wxColor grey( 100, 100, 100 );
3605 MarkerDefine (wxSTC_MARKNUM_FOLDER, wxSTC_MARK_BOXPLUS);
3606 MarkerSetForeground (wxSTC_MARKNUM_FOLDER, "WHITE");
3607 MarkerSetBackground (wxSTC_MARKNUM_FOLDER, grey);
3608
3609 MarkerDefine (wxSTC_MARKNUM_FOLDEROPEN, wxSTC_MARK_BOXMINUS);
3610 MarkerSetForeground (wxSTC_MARKNUM_FOLDEROPEN, "WHITE");
3611 MarkerSetBackground (wxSTC_MARKNUM_FOLDEROPEN, grey);
3612
3613 MarkerDefine (wxSTC_MARKNUM_FOLDERSUB, wxSTC_MARK_VLINE);
3614 MarkerSetForeground (wxSTC_MARKNUM_FOLDERSUB, grey);
3615 MarkerSetBackground (wxSTC_MARKNUM_FOLDERSUB, grey);
3616
3617 MarkerDefine (wxSTC_MARKNUM_FOLDEREND, wxSTC_MARK_BOXPLUSCONNECTED);
3618 MarkerSetForeground (wxSTC_MARKNUM_FOLDEREND, "WHITE");
3619 MarkerSetBackground (wxSTC_MARKNUM_FOLDEREND, grey);
3620
3621 MarkerDefine (wxSTC_MARKNUM_FOLDEROPENMID, wxSTC_MARK_BOXMINUSCONNECTED);
3622 MarkerSetForeground (wxSTC_MARKNUM_FOLDEROPENMID, "WHITE");
3623 MarkerSetBackground (wxSTC_MARKNUM_FOLDEROPENMID, grey);
3624
3625 MarkerDefine (wxSTC_MARKNUM_FOLDERMIDTAIL, wxSTC_MARK_TCORNER);
3626 MarkerSetForeground (wxSTC_MARKNUM_FOLDERMIDTAIL, grey);
3627 MarkerSetBackground (wxSTC_MARKNUM_FOLDERMIDTAIL, grey);
3628
3629 MarkerDefine (wxSTC_MARKNUM_FOLDERTAIL, wxSTC_MARK_LCORNER);
3630 MarkerSetForeground (wxSTC_MARKNUM_FOLDERTAIL, grey);
3631 MarkerSetBackground (wxSTC_MARKNUM_FOLDERTAIL, grey);
3632
3633 MarkerEnableHighlight(true);
3634 }
3635
3636 if (filetype == FILE_NSCR)
3637 {
3639 this->SetLexer(wxSTC_LEX_NSCR);
3640 this->SetProperty("fold", "1");
3641 if (_syntax)
3642 {
3643 this->SetKeyWords(0, _syntax->getCommands());
3644 this->SetKeyWords(1, _syntax->getOptions());
3645 this->SetKeyWords(2, _syntax->getFunctions());
3646 this->SetKeyWords(3, _syntax->getMethods());
3647 this->SetKeyWords(4, _syntax->getBlockDefs());
3648 this->SetKeyWords(5, _syntax->getConstants());
3649 this->SetKeyWords(6, _syntax->getSpecial());
3650 this->SetKeyWords(7, _syntax->getOperators());
3651 this->SetKeyWords(8, _syntax->getDocKeyWords());
3652 this->SetKeyWords(9, _syntax->getNPRCCommands());
3653 }
3654
3655 for (int i = 0; i <= wxSTC_NSCR_PROCEDURE_COMMANDS; i++)
3656 {
3657 SyntaxStyles _style;
3658 switch (i)
3659 {
3660 case wxSTC_NSCR_DEFAULT:
3661 case wxSTC_NSCR_IDENTIFIER:
3663 break;
3664 case wxSTC_NSCR_NUMBERS:
3666 break;
3667 case wxSTC_NSCR_COMMENT_BLOCK:
3668 case wxSTC_NSCR_COMMENT_LINE:
3670 break;
3671 case wxSTC_NSCR_DOCCOMMENT_BLOCK:
3672 case wxSTC_NSCR_DOCCOMMENT_LINE:
3674 break;
3675 case wxSTC_NSCR_DOCKEYWORD:
3677 break;
3678 case wxSTC_NSCR_COMMAND:
3680 break;
3681 case wxSTC_NSCR_OPTION:
3683 break;
3684 case wxSTC_NSCR_CONSTANTS:
3686 break;
3687 case wxSTC_NSCR_FUNCTION:
3689 break;
3690 case wxSTC_NSCR_METHOD:
3692 break;
3693 case wxSTC_NSCR_PREDEFS:
3695 break;
3696 case wxSTC_NSCR_STRING:
3698 break;
3699 case wxSTC_NSCR_STRING_PARSER:
3701 break;
3702 case wxSTC_NSCR_INCLUDES:
3704 break;
3705 case wxSTC_NSCR_PROCEDURES:
3707 break;
3708 case wxSTC_NSCR_PROCEDURE_COMMANDS:
3710 break;
3711 case wxSTC_NSCR_INSTALL:
3713 break;
3714 case wxSTC_NSCR_DEFAULT_VARS:
3716 break;
3717 case wxSTC_NSCR_CUSTOM_FUNCTION:
3719 break;
3720 case wxSTC_NSCR_CLUSTER:
3722 break;
3723 case wxSTC_NSCR_OPERATORS:
3724 case wxSTC_NSCR_OPERATOR_KEYWORDS:
3726 break;
3727 }
3728
3729 this->StyleSetForeground(i, _style.foreground);
3730 if (!_style.defaultbackground)
3731 this->StyleSetBackground(i, _style.background);
3732 else
3733 this->StyleSetBackground(i, this->StyleGetBackground(wxSTC_STYLE_DEFAULT));
3734 this->StyleSetBold(i, _style.bold);
3735 this->StyleSetItalic(i, _style.italics);
3736 this->StyleSetUnderline(i, _style.underline);
3737 }
3738 }
3739 else if (filetype == FILE_NPRC)
3740 {
3742 this->SetLexer(wxSTC_LEX_NPRC);
3743 this->SetProperty("fold", "1");
3744 if (_syntax)
3745 {
3746 this->SetKeyWords(0, _syntax->getCommands() + _syntax->getNPRCCommands());
3747 this->SetKeyWords(1, _syntax->getOptions());
3748 this->SetKeyWords(2, _syntax->getFunctions());
3749 this->SetKeyWords(3, _syntax->getMethods());
3750 this->SetKeyWords(4, _syntax->getBlockDefs());
3751 this->SetKeyWords(5, _syntax->getConstants());
3752 this->SetKeyWords(6, _syntax->getSpecial());
3753 this->SetKeyWords(7, _syntax->getOperators());
3754 this->SetKeyWords(8, _syntax->getDocKeyWords());
3755 }
3756
3757
3758 for (int i = 0; i <= wxSTC_NPRC_FLAGS; i++)
3759 {
3760 SyntaxStyles _style;
3761 switch (i)
3762 {
3763 case wxSTC_NPRC_DEFAULT:
3764 case wxSTC_NPRC_IDENTIFIER:
3766 break;
3767 case wxSTC_NPRC_NUMBERS:
3769 break;
3770 case wxSTC_NPRC_COMMENT_BLOCK:
3771 case wxSTC_NPRC_COMMENT_LINE:
3773 break;
3774 case wxSTC_NPRC_DOCCOMMENT_BLOCK:
3775 case wxSTC_NPRC_DOCCOMMENT_LINE:
3777 break;
3778 case wxSTC_NPRC_DOCKEYWORD:
3780 break;
3781 case wxSTC_NPRC_COMMAND:
3783 break;
3784 case wxSTC_NPRC_OPTION:
3786 break;
3787 case wxSTC_NPRC_CONSTANTS:
3789 break;
3790 case wxSTC_NPRC_FUNCTION:
3792 break;
3793 case wxSTC_NPRC_METHOD:
3795 break;
3796 case wxSTC_NPRC_PREDEFS:
3798 break;
3799 case wxSTC_NPRC_STRING:
3801 break;
3802 case wxSTC_NPRC_STRING_PARSER:
3804 break;
3805 case wxSTC_NPRC_INCLUDES:
3807 break;
3808 case wxSTC_NPRC_PROCEDURES:
3809 case wxSTC_NPRC_FLAGS:
3811 break;
3812 case wxSTC_NPRC_DEFAULT_VARS:
3814 break;
3815 case wxSTC_NPRC_CUSTOM_FUNCTION:
3817 break;
3818 case wxSTC_NPRC_CLUSTER:
3820 break;
3821 case wxSTC_NPRC_OPERATORS:
3822 case wxSTC_NPRC_OPERATOR_KEYWORDS:
3824 break;
3825 }
3826
3827 this->StyleSetForeground(i, _style.foreground);
3828 if (!_style.defaultbackground)
3829 this->StyleSetBackground(i, _style.background);
3830 else
3831 this->StyleSetBackground(i, this->StyleGetBackground(wxSTC_STYLE_DEFAULT));
3832 this->StyleSetBold(i, _style.bold);
3833 this->StyleSetItalic(i, _style.italics);
3834 this->StyleSetUnderline(i, _style.underline);
3835 }
3836 }
3837 else if (filetype == FILE_TEXSOURCE)
3838 {
3839 SetLexer(wxSTC_LEX_TEX);
3840 StyleSetForeground(wxSTC_TEX_DEFAULT, wxColor(0, 128, 0)); //Comment
3841 StyleSetForeground(wxSTC_TEX_COMMAND, wxColor(0, 0, 255)); //Command
3842 StyleSetBold(wxSTC_TEX_COMMAND, true);
3843 StyleSetUnderline(wxSTC_TEX_COMMAND, false);
3844 StyleSetForeground(wxSTC_TEX_TEXT, wxColor(0, 0, 0)); // Actual text
3845 StyleSetForeground(wxSTC_TEX_GROUP, wxColor(0, 128, 0)); // Grouping elements like $ $ or { }
3846 StyleSetBackground(wxSTC_TEX_GROUP, wxColor(255, 255, 183)); // Grouping elements like $ $ or { }
3847 StyleSetBold(wxSTC_TEX_GROUP, true);
3848 StyleSetForeground(wxSTC_TEX_SPECIAL, wxColor(255, 0, 196)); // Parentheses/Brackets
3849 StyleSetItalic(wxSTC_TEX_SPECIAL, false);
3850 StyleSetBold(wxSTC_TEX_SPECIAL, true);
3851 StyleSetForeground(wxSTC_TEX_SYMBOL, wxColor(255, 0, 0)); // Operators
3852 StyleSetBackground(wxSTC_TEX_SYMBOL, wxColor(255, 255, 255));
3853 StyleSetBold(wxSTC_TEX_SYMBOL, false);
3854 }
3855 else if (filetype == FILE_DATAFILES)
3856 {
3857 this->SetLexer(wxSTC_LEX_OCTAVE);
3858 this->StyleSetForeground(wxSTC_MATLAB_COMMENT, wxColor(0, 128, 0));
3859 this->StyleSetItalic(wxSTC_MATLAB_COMMENT, false);
3860 this->StyleSetForeground(wxSTC_MATLAB_OPERATOR, wxColor(255, 0, 0));
3861 this->StyleSetBold(wxSTC_MATLAB_OPERATOR, false);
3862 this->StyleSetForeground(wxSTC_MATLAB_NUMBER, wxColor(0, 0, 128));
3863 this->StyleSetBackground(wxSTC_MATLAB_NUMBER, wxColor(255, 255, 255));
3864 this->StyleSetForeground(wxSTC_MATLAB_IDENTIFIER, wxColor(0, 0, 0));
3865 this->StyleSetBold(wxSTC_MATLAB_IDENTIFIER, false);
3866 }
3867 else if (filetype == FILE_MATLAB)
3868 {
3869 this->SetLexer(wxSTC_LEX_MATLAB);
3870 this->SetProperty("fold", "1");
3871 if (_syntax)
3872 {
3873 this->SetKeyWords(0, _syntax->getMatlab());
3874 this->SetKeyWords(1, _syntax->getMatlabFunctions());
3875 }
3876
3877 for (int i = 0; i <= wxSTC_MATLAB_FUNCTIONS; i++)
3878 {
3879 SyntaxStyles _style;
3880 switch (i)
3881 {
3882 case wxSTC_MATLAB_DEFAULT:
3883 case wxSTC_MATLAB_IDENTIFIER:
3885 break;
3886 case wxSTC_MATLAB_NUMBER:
3888 break;
3889 case wxSTC_MATLAB_COMMENT:
3891 break;
3892 case wxSTC_MATLAB_COMMAND:
3893 case wxSTC_MATLAB_KEYWORD:
3895 break;
3896 case wxSTC_MATLAB_FUNCTIONS:
3898 break;
3899 case wxSTC_MATLAB_STRING:
3900 case wxSTC_MATLAB_DOUBLEQUOTESTRING:
3902 break;
3903 case wxSTC_MATLAB_OPERATOR:
3905 break;
3906 }
3907
3908 this->StyleSetForeground(i, _style.foreground);
3909 if (!_style.defaultbackground)
3910 this->StyleSetBackground(i, _style.background);
3911 else
3912 this->StyleSetBackground(i, this->StyleGetBackground(wxSTC_STYLE_DEFAULT));
3913 this->StyleSetBold(i, _style.bold);
3914 this->StyleSetItalic(i, _style.italics);
3915 this->StyleSetUnderline(i, _style.underline);
3916 }
3917
3918 }
3919 else if (filetype == FILE_CPP)
3920 {
3921 this->SetLexer(wxSTC_LEX_CPP);
3922 this->SetProperty("fold", "1");
3923 if (_syntax)
3924 {
3925 this->SetKeyWords(0, _syntax->getCpp());
3926 this->SetKeyWords(1, _syntax->getCppFunctions());
3927 }
3928
3929 for (int i = 0; i <= wxSTC_C_PREPROCESSORCOMMENT; i++)
3930 {
3931 SyntaxStyles _style;
3932 switch (i)
3933 {
3934 case wxSTC_C_DEFAULT :
3935 case wxSTC_C_IDENTIFIER:
3937 break;
3938 case wxSTC_C_NUMBER:
3940 break;
3941 case wxSTC_C_COMMENT:
3942 case wxSTC_C_COMMENTLINE:
3944 break;
3945 case wxSTC_C_COMMENTDOC:
3946 case wxSTC_C_COMMENTLINEDOC:
3948 break;
3949 case wxSTC_C_COMMENTDOCKEYWORD:
3950 case wxSTC_C_COMMENTDOCKEYWORDERROR:
3952 break;
3953 case wxSTC_C_WORD:
3955 break;
3956 case wxSTC_C_WORD2:
3958 break;
3959 case wxSTC_C_STRING:
3961 break;
3962 case wxSTC_C_CHARACTER:
3964 break;
3965 case wxSTC_C_PREPROCESSOR:
3967 break;
3968 case wxSTC_C_OPERATOR:
3970 break;
3971 }
3972
3973 this->StyleSetForeground(i, _style.foreground);
3974 if (!_style.defaultbackground)
3975 this->StyleSetBackground(i, _style.background);
3976 else
3977 this->StyleSetBackground(i, this->StyleGetBackground(wxSTC_STYLE_DEFAULT));
3978 this->StyleSetBold(i, _style.bold);
3979 this->StyleSetItalic(i, _style.italics);
3980 this->StyleSetUnderline(i, _style.underline);
3981 }
3982 }
3983 else if (filetype == FILE_DIFF)
3984 {
3985 SetLexer(wxSTC_LEX_DIFF);
3986 SetProperty("fold", "1");
3987 StyleSetForeground(wxSTC_DIFF_ADDED, wxColour(0, 128, 0));
3988 StyleSetBackground(wxSTC_DIFF_ADDED, wxColour(210, 255, 210));
3989 StyleSetForeground(wxSTC_DIFF_CHANGED, wxColour(128, 0, 0));
3990 StyleSetBackground(wxSTC_DIFF_CHANGED, wxColour(255, 210, 210));
3991 StyleSetForeground(wxSTC_DIFF_DELETED, wxColour(128, 0, 0));
3992 StyleSetBackground(wxSTC_DIFF_DELETED, wxColour(255, 210, 210));
3993 StyleSetForeground(wxSTC_DIFF_DEFAULT, *wxBLACK);
3994 StyleSetBackground(wxSTC_DIFF_DEFAULT, *wxWHITE);
3995 StyleSetForeground(wxSTC_DIFF_HEADER, *wxBLUE);
3996 StyleSetBackground(wxSTC_DIFF_HEADER, *wxWHITE);
3997 StyleSetForeground(wxSTC_DIFF_POSITION, wxColour(255, 128, 0));
3998 StyleSetBackground(wxSTC_DIFF_POSITION, *wxWHITE);
3999 StyleSetBold(wxSTC_DIFF_POSITION, true);
4000 }
4001 else if (filetype == FILE_XML)
4002 {
4003 SetLexer(wxSTC_LEX_XML);
4004 SetProperty("fold", "1");
4005 StyleSetForeground(wxSTC_H_DEFAULT, wxColour(0,0,0));
4006 StyleSetForeground(wxSTC_H_TAG, wxColour(0,0,255));
4007 StyleSetBold(wxSTC_H_TAG, true);
4008 StyleSetForeground(wxSTC_H_TAGEND, wxColour(0,0,255));
4009 StyleSetBold(wxSTC_H_TAGEND, true);
4010 StyleSetForeground(wxSTC_H_ATTRIBUTE, wxColour(255,0,0));
4011 StyleSetForeground(wxSTC_H_DOUBLESTRING, wxColour(128,0,255));
4012 StyleSetBold(wxSTC_H_DOUBLESTRING, true);
4013 StyleSetForeground(wxSTC_H_SINGLESTRING, wxColour(128,0,255));
4014 StyleSetBold(wxSTC_H_SINGLESTRING, true);
4015 StyleSetForeground(wxSTC_H_COMMENT, wxColour(0,128,0));
4016 StyleSetItalic(wxSTC_H_COMMENT, true);
4017 StyleSetForeground(wxSTC_H_ENTITY, wxColour(64,0,0));
4018 StyleSetBackground(wxSTC_H_ENTITY, wxColour(255,255,220));
4019 StyleSetBold(wxSTC_H_ENTITY, true);
4020 }
4021 else
4022 {
4024 {
4025 this->SetLexer(wxSTC_LEX_NULL);
4026 this->ClearDocumentStyle();
4027 }
4028 else
4029 {
4030 this->SetLexer(wxSTC_LEX_TXTADV);
4031 this->StyleSetItalic(wxSTC_TXTADV_DEFAULT, false);
4032 this->StyleSetItalic(wxSTC_TXTADV_MODIFIER, true);
4033 this->StyleSetForeground(wxSTC_TXTADV_MODIFIER, wxColor(255, 180, 180));
4034 this->StyleSetItalic(wxSTC_TXTADV_ITALIC, true);
4035 this->StyleSetItalic(wxSTC_TXTADV_BOLD, false);
4036 this->StyleSetBold(wxSTC_TXTADV_BOLD, true);
4037 this->StyleSetItalic(wxSTC_TXTADV_BOLD_ITALIC, true);
4038 this->StyleSetBold(wxSTC_TXTADV_BOLD_ITALIC, true);
4039 this->StyleSetUnderline(wxSTC_TXTADV_UNDERLINE, true);
4040 this->StyleSetForeground(wxSTC_TXTADV_STRIKETHROUGH, wxColor(140, 140, 140));
4041 this->StyleSetItalic(wxSTC_TXTADV_STRIKETHROUGH, true);
4042 this->StyleSetUnderline(wxSTC_TXTADV_URL, true);
4043 this->StyleSetForeground(wxSTC_TXTADV_URL, wxColor(0, 0, 255));
4044 this->StyleSetUnderline(wxSTC_TXTADV_HEAD, true);
4045 this->StyleSetBold(wxSTC_TXTADV_HEAD, true);
4046 this->StyleSetUnderline(wxSTC_TXTADV_BIGHEAD, true);
4047 this->StyleSetBold(wxSTC_TXTADV_BIGHEAD, true);
4048 this->StyleSetSize(wxSTC_TXTADV_BIGHEAD, this->StyleGetSize(0) + 1);
4049 this->StyleSetCase(wxSTC_TXTADV_BIGHEAD, wxSTC_CASE_UPPER);
4050 }
4051 //this->ClearDocumentStyle();
4052 }
4053
4055 Colourise(0, -1);
4057 markLocalVariables(true);
4058}
4059
4060
4069{
4070 // Indicator for the matching brace
4071 IndicatorSetStyle(HIGHLIGHT_MATCHING_BRACE, wxSTC_INDIC_ROUNDBOX);
4072 IndicatorSetForeground(HIGHLIGHT_MATCHING_BRACE, wxColour(0, 200, 0));
4073
4074 // Indicator for a matching control
4075 // flow block
4076 IndicatorSetStyle(HIGHLIGHT_MATCHING_BLOCK, wxSTC_INDIC_ROUNDBOX);
4077 IndicatorSetAlpha(HIGHLIGHT_MATCHING_BLOCK, 100);
4078 IndicatorSetForeground(HIGHLIGHT_MATCHING_BLOCK, wxColour(0, 220, 0));
4079
4080 // Indicator for a non-matching
4081 // control flow block
4082 IndicatorSetStyle(HIGHLIGHT_NOT_MATCHING_BLOCK, wxSTC_INDIC_ROUNDBOX);
4083 IndicatorSetAlpha(HIGHLIGHT_NOT_MATCHING_BLOCK, 128);
4084 IndicatorSetForeground(HIGHLIGHT_NOT_MATCHING_BLOCK, wxColour(255, 0, 0));
4085
4086 // Indicator for highlighted occurences
4087 // after double-clicking
4088 IndicatorSetStyle(HIGHLIGHT_DBLCLK, wxSTC_INDIC_ROUNDBOX);
4089 IndicatorSetAlpha(HIGHLIGHT_DBLCLK, 80);
4090 IndicatorSetForeground(HIGHLIGHT_DBLCLK, wxColor(0, 255, 0));
4091
4092 // Indicator for permanently highlighted
4093 // occurences
4094 IndicatorSetStyle(HIGHLIGHT, wxSTC_INDIC_ROUNDBOX);
4095 IndicatorSetAlpha(HIGHLIGHT, 100);
4096 IndicatorSetForeground(HIGHLIGHT, wxColor(255, 0, 0));
4097
4098 // Indicator for strike-through
4099 IndicatorSetStyle(HIGHLIGHT_STRIKETHROUGH, wxSTC_INDIC_STRIKE);
4100 IndicatorSetForeground(HIGHLIGHT_STRIKETHROUGH, wxColor(255, 0, 0));
4101
4102 // Indicator for highlighting local
4103 // variables
4104 IndicatorSetStyle(HIGHLIGHT_LOCALVARIABLES, wxSTC_INDIC_DOTS);
4105 IndicatorSetForeground(HIGHLIGHT_LOCALVARIABLES, wxColour(0, 0, 255));
4106// IndicatorSetForeground(HIGHLIGHT_LOCALVARIABLES, wxColour(255, 128, 128));
4107
4108 // Indicators for highlighting differences in
4109 // the duplicated code analysis
4110 IndicatorSetStyle(HIGHLIGHT_DIFFERENCES, wxSTC_INDIC_ROUNDBOX);
4111 IndicatorSetAlpha(HIGHLIGHT_DIFFERENCES, 64);
4112 IndicatorSetForeground(HIGHLIGHT_DIFFERENCES, wxColour(128, 0, 128));
4113
4114 IndicatorSetStyle(HIGHLIGHT_DIFFERENCE_SOURCE, wxSTC_INDIC_ROUNDBOX);
4115 IndicatorSetAlpha(HIGHLIGHT_DIFFERENCE_SOURCE, 64);
4116 IndicatorSetForeground(HIGHLIGHT_DIFFERENCE_SOURCE, wxColour(0, 128, 128));
4117}
4118
4119
4128{
4129 this->CallTipSetForegroundHighlight(*wxBLUE);
4130 this->SetCaretLineVisible(true);
4131 this->SetIndentationGuides(wxSTC_IV_LOOKBOTH);
4132
4133 this->StyleSetBackground(wxSTC_STYLE_INDENTGUIDE, m_options->GetSyntaxStyle(Options::STANDARD).foreground);
4134 this->StyleSetForeground(wxSTC_STYLE_INDENTGUIDE, m_options->GetSyntaxStyle(Options::STANDARD).background);
4135
4136 this->SetCaretForeground(m_options->GetSyntaxStyle(Options::STANDARD).foreground);
4137
4138 // Use these styles for enabling black mode
4139// this->StyleSetBackground(wxSTC_STYLE_LINENUMBER, m_options->GetSyntaxStyle(Options::STANDARD).background);
4140// this->StyleSetForeground(wxSTC_STYLE_LINENUMBER, m_options->GetSyntaxStyle(Options::STANDARD).foreground);
4141//
4142// this->SetFoldMarginColour(true, m_options->GetSyntaxStyle(Options::STANDARD).background);
4143// this->SetFoldMarginHiColour(true, m_options->GetSyntaxStyle(Options::STANDARD).foreground);
4144
4146 this->SetCaretLineBackground(m_options->GetSyntaxStyle(Options::ACTIVE_LINE).background);
4147 else
4148 this->SetCaretLineVisible(false);
4149
4151 {
4152 SetEdgeColour(wxColour(210, 210, 255));
4153 SetEdgeMode(wxSTC_EDGE_LINE);
4154 SetEdgeColumn(100);
4155 }
4156 else
4157 SetEdgeMode(wxSTC_EDGE_NONE);
4158
4159 // standard settings for the brace highlighting
4160 this->StyleSetForeground(wxSTC_STYLE_BRACELIGHT, wxColour(0, 150, 0));
4161 this->StyleSetBackground(wxSTC_STYLE_BRACELIGHT, wxColour(0, 220, 0));
4162 this->StyleSetBold(wxSTC_STYLE_BRACELIGHT, true);
4163 this->StyleSetSize(wxSTC_STYLE_BRACELIGHT, this->StyleGetSize(0) + 1);
4164 this->StyleSetForeground(wxSTC_STYLE_BRACEBAD, wxColour(150, 0, 0));
4165 this->StyleSetBackground(wxSTC_STYLE_BRACEBAD, wxColour(220, 0, 0));
4166 this->StyleSetBold(wxSTC_STYLE_BRACEBAD, true);
4167 this->StyleSetSize(wxSTC_STYLE_BRACEBAD, this->StyleGetSize(0) + 1);
4168
4169 // Style settings for the displayed annotations
4170 int nAnnotationFontSize = this->StyleGetSize(wxSTC_STYLE_DEFAULT);
4171
4172 if (nAnnotationFontSize >= 10)
4173 nAnnotationFontSize -= 2;
4174 else if (nAnnotationFontSize >= 8)
4175 nAnnotationFontSize -= 1;
4176
4177 this->StyleSetBackground(ANNOTATION_NOTE, wxColour(240, 240, 240));
4178 this->StyleSetForeground(ANNOTATION_NOTE, wxColour(120, 120, 120));
4179 this->StyleSetSize(ANNOTATION_NOTE, nAnnotationFontSize);
4180 this->StyleSetItalic(ANNOTATION_NOTE, true);
4181 this->StyleSetFaceName(ANNOTATION_NOTE, "Segoe UI");
4182 this->StyleSetBackground(ANNOTATION_WARN, wxColour(255, 240, 210));
4183 this->StyleSetForeground(ANNOTATION_WARN, wxColour(200, 120, 0));
4184 this->StyleSetSize(ANNOTATION_WARN, nAnnotationFontSize);
4185 this->StyleSetItalic(ANNOTATION_WARN, true);
4186 this->StyleSetFaceName(ANNOTATION_WARN, "Segoe UI");
4187 this->StyleSetBackground(ANNOTATION_ERROR, wxColour(255, 225, 225));
4188 this->StyleSetForeground(ANNOTATION_ERROR, wxColour(170, 0, 0));
4189 this->StyleSetSize(ANNOTATION_ERROR, nAnnotationFontSize);
4190 this->StyleSetItalic(ANNOTATION_ERROR, true);
4191 this->StyleSetFaceName(ANNOTATION_ERROR, "Segoe UI");
4192}
4193
4194
4204{
4206 || m_fileType == FILE_NSCR
4207 || m_fileType == FILE_NPRC
4209 || m_fileType == FILE_XML
4212 return;
4213
4214 SetIndicatorCurrent(HIGHLIGHT_STRIKETHROUGH);
4215 IndicatorClearRange(0, GetLastPosition());
4216
4217 for (int i = 0; i < GetLastPosition(); i++)
4218 {
4219 if (GetStyleAt(i) == wxSTC_TXTADV_STRIKETHROUGH)
4220 {
4221 for (int j = i; j < GetLastPosition(); j++)
4222 {
4223 if (GetStyleAt(j) == wxSTC_TXTADV_MODIFIER || j == GetLastPosition() - 1)
4224 {
4225 IndicatorFillRange(i, j - i);
4226 i = j;
4227 break;
4228 }
4229 }
4230 }
4231 }
4232}
4233
4234
4246void NumeReEditor::SetFilename(wxFileName filename, bool fileIsRemote)
4247{
4248 m_bLastSavedRemotely = fileIsRemote;
4249 m_fileNameAndPath = filename;
4250}
4251
4252
4262{
4263 wxFileName file(filename);
4264
4265 wxString extension = file.GetExt().Lower();
4266
4267 FileFilterType fileType = FILE_NONSOURCE;
4268
4269 if (extension == "nprc")
4270 fileType = FILE_NPRC;
4271 else if (extension == "nscr" || extension == "nlyt")
4272 fileType = FILE_NSCR;
4273 else if (extension == "ndat" || extension == "dat" || extension == "csv" || extension == "jdx" || extension == "dx" || extension == "jcm")
4274 fileType = FILE_DATAFILES;
4275 else if (extension == "tex")
4276 fileType = FILE_TEXSOURCE;
4277 else if (extension == "m")
4278 fileType = FILE_MATLAB;
4279 else if (extension == "cxx" || extension == "hxx" || extension == "c" || extension == "h" || extension == "cpp" || extension == "hpp")
4280 fileType = FILE_CPP;
4281 else if (extension == "diff" || extension == "patch")
4282 fileType = FILE_DIFF;
4283 else if (extension == "nhlp" || extension == "xml" || extension == "npkp")
4284 fileType = FILE_XML;
4285
4286 return fileType;
4287}
4288
4289
4290
4300{
4301 wxString nameAndPath = m_fileNameAndPath.GetFullPath();//m_bLastSavedRemotely ? wxPATH_UNIX : wxPATH_DOS);
4302 return nameAndPath;
4303}
4304
4305
4315{
4316 return m_fileNameAndPath.GetFullName();
4317}
4318
4319
4329{
4330 return m_fileNameAndPath;
4331}
4332
4333
4343{
4344 return m_fileNameAndPath.GetPath(false, m_bLastSavedRemotely ? wxPATH_UNIX : wxPATH_DOS);
4345}
4346
4347
4357{
4358 ClearAll();
4359
4360 m_fileNameAndPath.Clear();
4361 m_breakpoints.Clear();
4362 m_clickedWord.clear();
4363 m_clickedProcedure.clear();
4364 m_clickedInclude.clear();
4366 m_watchedString.clear();
4368
4369 SetReadOnly(false);
4370 SetText(wxEmptyString);
4371 SetSavePoint();
4372 EmptyUndoBuffer();
4373
4374 MarkerDeleteAll(MARKER_BREAKPOINT);
4375 MarkerDeleteAll(MARKER_FOCUSEDLINE);
4376 MarkerDeleteAll(MARKER_MODIFIED);
4377 MarkerDeleteAll(MARKER_SAVED);
4378}
4379
4380
4391void NumeReEditor::OnRightClick(wxMouseEvent& event)
4392{
4393 m_PopUpActive = true;
4394 m_lastRightClick = event.GetPosition();
4395 int charpos = PositionFromPoint(m_lastRightClick);
4396 int linenum = LineFromPosition(charpos);
4397 const int nINSERTIONPOINT = 16;
4398 wxString clickedWord = m_search->FindClickedWord();
4399
4400 // Determine the marker and breakpoint conditions
4401 bool breakpointOnLine = MarkerOnLine(linenum, MARKER_BREAKPOINT);
4402 bool bookmarkOnLine = MarkerOnLine(linenum, MARKER_BOOKMARK);
4403 bool breakpointsAllowed = isNumeReFileType();
4404
4405 // returns a copy of a member variable, which would seem sort of pointless, but
4406 // GetBreakpoints cleans up any stray marker IDs in the list before returning
4407 // so we have an accurate count of how many breakpoints there are
4408 wxArrayInt currentBreakpoints = GetBreakpoints();
4409 bool canClearBreakpoints = currentBreakpoints.GetCount() > 0;
4410
4411 // Prepare the context menu
4412 if (m_popupMenu.FindItem(ID_DEBUG_DISPLAY_SELECTION) != nullptr)
4413 {
4415 m_menuShowValue->SetItemLabel(_guilang.get("GUI_MENU_EDITOR_HIGHLIGHT", "..."));
4416 }
4417
4418 if (m_popupMenu.FindItem(ID_FIND_PROCEDURE) != nullptr)
4419 {
4421 }
4422
4423 if (m_popupMenu.FindItem(ID_FIND_INCLUDE) != nullptr)
4424 {
4426 }
4427
4428 if (m_popupMenu.FindItem(ID_MENU_HELP_ON_ITEM) != nullptr)
4429 {
4431 }
4432
4433 if (m_popupMenu.FindItem(ID_REFACTORING_MENU) != nullptr)
4434 {
4435 m_refactoringMenu->Enable(ID_RENAME_SYMBOLS, false);
4437 m_refactoringMenu->Enable(ID_FIX_TYPE, false);
4439 }
4440
4441 // Enable menus depending on the marker and breakpint states
4443 m_popupMenu.Enable(ID_HIDE_SELECTION, HasSelection());
4444 m_popupMenu.Enable(ID_DEBUG_ADD_BREAKPOINT, breakpointsAllowed && !breakpointOnLine);
4445 m_popupMenu.Enable(ID_DEBUG_REMOVE_BREAKPOINT, breakpointsAllowed && breakpointOnLine);
4446 m_popupMenu.Enable(ID_BOOKMARK_ADD, !bookmarkOnLine);
4447 m_popupMenu.Enable(ID_BOOKMARK_REMOVE, bookmarkOnLine);
4448 m_popupMenu.Enable(ID_DEBUG_CLEAR_ALL_BREAKPOINTS, canClearBreakpoints);
4449
4450 // Enable upper- and lowercase if the user made
4451 // a selection in advance
4452 if (HasSelection())
4453 {
4454 m_popupMenu.Enable(ID_UPPERCASE, true);
4455 m_popupMenu.Enable(ID_LOWERCASE, true);
4456 }
4457 else
4458 {
4459 m_popupMenu.Enable(ID_UPPERCASE, false);
4460 m_popupMenu.Enable(ID_LOWERCASE, false);
4461 }
4462
4463 // If th user clicked a word or made a selection
4464 if (clickedWord.length() > 0 || HasSelection())
4465 {
4466 if (this->GetStyleAt(charpos) == wxSTC_NSCR_PROCEDURES)
4467 {
4468 // Show "find procedure"
4469 wxString clickedProc = m_search->FindClickedProcedure();
4470
4471 if (clickedProc.length())
4472 {
4473 m_popupMenu.Insert(nINSERTIONPOINT, m_menuFindProcedure);
4474 m_menuFindProcedure->SetItemLabel(_guilang.get("GUI_MENU_EDITOR_FINDPROC", clickedProc.ToStdString()));
4475 }
4476 }
4477 else if (this->GetStyleAt(charpos) == wxSTC_NSCR_COMMAND
4478 || this->GetStyleAt(charpos) == wxSTC_NSCR_PROCEDURE_COMMANDS
4479 || this->GetStyleAt(charpos) == wxSTC_NSCR_OPTION)
4480 {
4481 // Show "help on item"
4482 m_popupMenu.Insert(nINSERTIONPOINT, m_menuHelpOnSelection);
4483 m_menuHelpOnSelection->SetItemLabel(_guilang.get("GUI_TREE_PUP_HELPONITEM", clickedWord.ToStdString()));
4484 }
4485 else if (this->GetStyleAt(charpos) == wxSTC_NSCR_INCLUDES
4486 || this->GetStyleAt(charpos) == wxSTC_NPRC_INCLUDES)
4487 {
4488 // Show "find included file"
4489 wxString clickedInclude = m_search->FindClickedInclude();
4490
4491 if (clickedInclude.length())
4492 {
4493 m_popupMenu.Insert(nINSERTIONPOINT, m_menuFindInclude);
4494 m_menuFindInclude->SetItemLabel(_guilang.get("GUI_MENU_EDITOR_FINDINCLUDE", clickedInclude.ToStdString()));
4495 }
4496 }
4497 else
4498 {
4499 // Show the refactoring menu
4500 m_popupMenu.Insert(nINSERTIONPOINT, m_menuRefactoring);
4501
4502 if (isStyleType(STYLE_DEFAULT, charpos)
4503 || isStyleType(STYLE_IDENTIFIER, charpos)
4504 || isStyleType(STYLE_DATAOBJECT, charpos)
4505 || isStyleType(STYLE_FUNCTION, charpos))
4506 m_refactoringMenu->Enable(ID_RENAME_SYMBOLS, true);
4507
4508 if (isStyleType(STYLE_IDENTIFIER, charpos))
4509 m_refactoringMenu->Enable(ID_FIX_TYPE, true);
4510
4511 if (HasSelection())
4513 }
4514
4515 // Enable the "highlight" menu item and add the clicked word
4516 // to the item text
4518 m_menuShowValue->SetItemLabel(_guilang.get("GUI_MENU_EDITOR_HIGHLIGHT", clickedWord.ToStdString()));
4519
4520 // Set the boolean flag to correspond to the highlight
4521 // state of the clicked word
4522 if (m_clickedWord == m_watchedString && m_clickedWord.length())
4523 m_menuShowValue->Check(true);
4524 else
4525 m_menuShowValue->Check(false);
4526 }
4527
4528 // Cancel the call tip, if there's one active
4529 if (this->CallTipActive())
4530 this->AdvCallTipCancel();
4531
4532 PopupMenu(&m_popupMenu, m_lastRightClick);
4533 m_PopUpActive = false;
4534}
4535
4536
4547{
4548 int nMarkSaved = 1 << (MARKER_SAVED);
4549 int nMarkModified = 1 << (MARKER_MODIFIED);
4550
4551 while (this->MarkerGet(nLine) & nMarkSaved)
4552 this->MarkerDelete(nLine, MARKER_SAVED);
4553
4554 if (!(this->MarkerGet(nLine) & nMarkModified))
4555 this->MarkerAdd(nLine, MARKER_MODIFIED);
4556}
4557
4558
4569{
4570 int nMarkModified = 1 << (MARKER_MODIFIED);
4571 int nMarkSaved = 1 << (MARKER_SAVED);
4572 int nNextLine = 0;
4573
4574 while ((nNextLine = this->MarkerNext(0, nMarkModified)) != -1)
4575 {
4576 this->MarkerDelete(nNextLine, MARKER_MODIFIED);
4577
4578 if (!(this->MarkerGet(nNextLine) & nMarkSaved))
4579 this->MarkerAdd(nNextLine, MARKER_SAVED);
4580 }
4581
4582 this->MarkerDeleteAll(MARKER_MODIFIED);
4583}
4584
4585
4596void NumeReEditor::OnEditorModified(wxStyledTextEvent& event)
4597{
4598 if (!m_bLoadingFile && (event.GetModificationType() & wxSTC_MOD_INSERTTEXT || event.GetModificationType() & wxSTC_MOD_DELETETEXT))
4599 {
4601 int nLine = this->LineFromPosition(event.GetPosition());
4602 int nLinesAdded = event.GetLinesAdded();
4603
4604 if (nLinesAdded > 0)
4605 {
4606 for (int i = 0; i < nLinesAdded; i++)
4607 this->markModified(i + nLine);
4608 }
4609 else if (nLinesAdded < 0)
4610 this->markModified(nLine);
4611 else
4612 this->markModified(nLine);
4613 }
4614
4615 event.Skip();
4616}
4617
4618
4628{
4629 // Get parent line
4630 int nParentline = this->GetFoldParent(nLine);
4631
4632 // Probably the current line is also a parent line -> take this one
4633 if (this->GetFoldLevel(nLine) & wxSTC_FOLDLEVELHEADERFLAG)
4634 nParentline = nLine;
4635
4636 // if not found -> return
4637 if (nParentline == -1)
4638 return;
4639
4640 // if already folded -> return
4641 if (!this->GetFoldExpanded(nLine))
4642 return;
4643
4644 // toggle the fold state of the current header line -> only folds because of previous condition
4645 this->ToggleFold(nParentline);
4646}
4647
4648
4663void NumeReEditor::markSections(bool bForceRefresh)
4664{
4665 // Ensure, that sectioning is activated
4667 return;
4668
4669 if (bForceRefresh)
4670 this->MarkerDeleteAll(MARKER_SECTION);
4671
4672 int startline = 0;
4673 int endline = this->GetLineCount();
4674
4675 // Find the first and last line, if not the whole
4676 // editor shall be examined
4677 if (!bForceRefresh)
4678 {
4679 int markermask = (1 << MARKER_SECTION);
4680
4681 if ((startline = this->MarkerPrevious(this->GetCurrentLine() - 1, markermask)) == -1)
4682 startline = 0;
4683
4684 if ((endline = this->MarkerNext(this->GetCurrentLine() + 1, markermask)) == -1)
4685 endline = this->GetLineCount();
4686 }
4687
4688 // NumeRe or MATLAB file?
4690 {
4691 // Search for documentation comment blocks
4692 // in the file and add markers
4693 for (int i = startline; i < endline; i++)
4694 {
4695 if (isStyleType(STYLE_COMMENT_SECTION_LINE, GetLineIndentPosition(i))
4696 || isStyleType(STYLE_COMMENT_SECTION_BLOCK, GetLineIndentPosition(i)))
4697 {
4699 MarkerAdd(i, MARKER_SECTION);
4700
4701 while (isStyleType(STYLE_COMMENT_SECTION_LINE, GetLineIndentPosition(i+1))
4702 || isStyleType(STYLE_COMMENT_SECTION_BLOCK, GetLineIndentPosition(i+1)))
4703 {
4704 i++;
4705
4706 // Only keep the very first section. Should also remove erroneously
4707 // placed markers
4709 MarkerDelete(i, MARKER_SECTION);
4710 }
4711 }
4712 else if (MarkerOnLine(i, MARKER_SECTION))
4713 MarkerDelete(i, MARKER_SECTION);
4714 }
4715 }
4716
4717 // LaTeX source?
4719 {
4720 // Search for LaTeX sectioning commands in
4721 // the examination range and add markers to them
4722 for (int i = startline; i < endline; i++)
4723 {
4724 for (int j = PositionFromLine(i); j < GetLineEndPosition(i) + 1; j++)
4725 {
4726 if (GetCharAt(j) == ' ' || GetCharAt(j) == '\t')
4727 continue;
4728
4729 if (GetStyleAt(j) == wxSTC_TEX_COMMAND)
4730 {
4731 int wordstart = WordStartPosition(j, false);
4732 int wordend = WordEndPosition(j, false);
4733
4734 wxString word = GetTextRange(wordstart, wordend);
4735
4736 if (word == "maketitle"
4737 || word == "part"
4738 || word == "chapter"
4739 || word == "section"
4740 || word == "subsection"
4741 || word == "subsubsection"
4742 || word == "subsubsubsection"
4743 || word == "paragraph"
4744 || word == "subparagraph"
4745 || word == "addchap"
4746 || word == "addsec")
4747 {
4749 MarkerAdd(i, MARKER_SECTION);
4750 }
4751
4752 j = wordend;
4753 }
4754 }
4755 }
4756 }
4757
4758 // Text file with advanced highlighting?
4760 {
4761 // Search for all headlines in the document and
4762 // add markers to them
4763 for (int i = startline; i < endline; i++)
4764 {
4765 for (int j = this->PositionFromLine(i); j < this->GetLineEndPosition(i) + 1; j++)
4766 {
4767 if (this->GetCharAt(j) == ' ' || this->GetCharAt(j) == '\t')
4768 continue;
4769
4770 if (this->GetStyleAt(j) == wxSTC_TXTADV_BIGHEAD || this->GetStyleAt(j) == wxSTC_TXTADV_HEAD)
4771 {
4772 if (!this->MarkerOnLine(i, MARKER_SECTION))
4773 this->MarkerAdd(i, MARKER_SECTION);
4774
4775 break;
4776 }
4777 }
4778
4779 if (this->GetLine(i).find('#') == string::npos)
4780 {
4781 if (this->MarkerOnLine(i, MARKER_SECTION))
4782 this->MarkerDelete(i, MARKER_SECTION);
4783 }
4784 }
4785 }
4786}
4787
4788
4797void NumeReEditor::markLocalVariables(bool bForceRefresh)
4798{
4799 SetIndicatorCurrent(HIGHLIGHT_LOCALVARIABLES);
4800
4801 // We clean everything, if need to refresh the indicators
4802 if (bForceRefresh)
4803 IndicatorClearRange(0, GetLastPosition());
4804
4806 return;
4807
4808 std::pair<int,int> context = getCurrentContext(GetCurrentLine());
4809 IndicatorClearRange(PositionFromLine(context.first),
4810 GetLineEndPosition(context.second) - PositionFromLine(context.first));
4811
4812 // Run the algorithm for every possible local variable declarator
4813 markLocalVariableOfType("var", bForceRefresh);
4814 markLocalVariableOfType("cst", bForceRefresh);
4815 markLocalVariableOfType("tab", bForceRefresh);
4816 markLocalVariableOfType("str", bForceRefresh);
4817}
4818
4819
4833void NumeReEditor::markLocalVariableOfType(const wxString& command, bool bForceRefresh)
4834{
4835 std::vector<int> matches;
4836 std::pair<int, int> context = std::make_pair(0, GetLineCount());
4837
4838 // Find the occurences of the variable declaration commands
4839 // in the corresponding scope
4840 if (!bForceRefresh)
4841 {
4842 context = getCurrentContext(GetCurrentLine());
4843 matches = m_search->FindAll(command,
4844 wxSTC_NPRC_COMMAND,
4845 PositionFromLine(context.first),
4846 GetLineEndPosition(context.second),
4847 false);
4848 }
4849 else
4850 matches = m_search->FindAll(command,
4851 wxSTC_NPRC_COMMAND,
4852 0,
4853 GetLastPosition(),
4854 false);
4855
4856 // Run through all found occurences and extract the definitions
4857 // of the local variables
4858 for (size_t i = 0; i < matches.size(); i++)
4859 {
4860 context = getCurrentContext(LineFromPosition(i));
4861 wxString line = GetTextRange(matches[i]+command.length(), GetLineEndPosition(LineFromPosition(matches[i])));
4862 int nPos = line.find_first_not_of(' ') + matches[i] + command.length();
4863
4864 for (int j = nPos; j < GetLineEndPosition(LineFromPosition(matches[i])) + 1; j++)
4865 {
4866 char currentChar = GetCharAt(j);
4867
4868 // If a separator character was found, highlight
4869 // the current word and find the next candidate
4870 if (currentChar == ' '
4871 || currentChar == '='
4872 || currentChar == ','
4873 || currentChar == '('
4874 || currentChar == '{'
4875 || currentChar == ';'
4876 || currentChar == '\r'
4877 || currentChar == '\n')
4878 {
4879 std::vector<int> localVars = m_search->FindAll(GetTextRange(nPos, j),
4880 GetStyleAt(nPos),
4881 nPos,
4882 GetLineEndPosition(context.second),
4883 false);
4884
4885 for (int n : localVars)
4886 {
4887 IndicatorFillRange(n, j - nPos);
4888 }
4889
4890 if (currentChar == ',')
4891 {
4892 // Only a declaration, find the next one
4893 while (GetCharAt(j) == ',' || GetCharAt(j) == ' ')
4894 j++;
4895 }
4896 else if (currentChar == ';')
4897 break;
4898 else
4899 {
4900 // This is also an initialization. Find the
4901 // next declaration by jumping over the assigned
4902 // value.
4903 for (int l = j; l < GetLineEndPosition(LineFromPosition(matches[i])); l++)
4904 {
4905 if (GetCharAt(l) == ',' && GetStyleAt(l) == wxSTC_NPRC_OPERATORS)
4906 {
4907 while (GetCharAt(l) == ',' || GetCharAt(l) == ' ')
4908 l++;
4909
4910 j = l;
4911 break;
4912 }
4913 else if (GetStyleAt(l) == wxSTC_NPRC_OPERATORS && (GetCharAt(l) == '(' || GetCharAt(l) == '{'))
4914 {
4915 j = -1;
4916 l = BraceMatch(l);
4917
4918 if (l == -1)
4919 break;
4920 }
4921 else if (l+1 == GetLineEndPosition(LineFromPosition(matches[i])))
4922 j = -1;
4923 }
4924 }
4925
4926 if (j == -1)
4927 break;
4928
4929 nPos = j;
4930 }
4931 else if (GetStyleAt(j) == wxSTC_NPRC_OPERATORS && (currentChar == '(' || currentChar == '{'))
4932 {
4933 j = BraceMatch(j);
4934
4935 if (j == -1)
4936 break;
4937 }
4938 }
4939 }
4940}
4941
4942
4953{
4954 return keycode == WXK_BACK
4955 || keycode == WXK_DELETE
4956 || keycode == WXK_TAB
4957 || keycode == WXK_SHIFT
4958 || keycode == WXK_CAPITAL
4959 || keycode == WXK_ALT
4960 || keycode == WXK_CONTROL
4961 || keycode == WXK_ESCAPE
4962 || keycode == WXK_LEFT
4963 || keycode == WXK_RIGHT
4964 || keycode == WXK_UP
4965 || keycode == WXK_DOWN
4966 || keycode == WXK_HOME
4967 || keycode == WXK_END;
4968}
4969
4970
4980{
4981 if (line <= 0)
4982 return false;
4983
4984 wxString lastLine = GetLine(line-1);
4985 lastLine.erase(lastLine.find_last_not_of("\r\n\t ")+1);
4986
4987 if (m_fileType == FILE_MATLAB)
4988 return lastLine.EndsWith("...");
4989 else if (m_fileType == FILE_NSCR || m_fileType == FILE_NPRC)
4990 return lastLine.EndsWith("\\\\");
4991
4992 return false;
4993}
4994
4995
5008{
5009 if (!this->AutoCompActive()
5013 && !HasSelection())
5014 {
5015 int nLine = GetCurrentLine();
5016 int offset = 0;
5017
5018 // Probably the current line is also a parent line -> take the parent
5019 if (GetFoldLevel(nLine) & wxSTC_FOLDLEVELHEADERFLAG)
5020 offset--;
5021
5022 // Get parent line
5023 int nParentline = GetFoldParent(nLine+offset);
5024
5025 // if not found -> return
5026 if (nParentline == wxNOT_FOUND)
5027 {
5028 nParentline = std::max(nLine-10, 0);
5029
5030 if (GetFoldParent(nParentline) != wxNOT_FOUND)
5031 nParentline = GetFoldParent(nParentline);
5032
5033 // Do not use comments or syntactial wrapped lines
5034 // to determine the indentation level (if avoidable)
5035 while (nParentline > 0 && (isStyleType(STYLE_COMMENT, PositionFromLine(nParentline)) || isWrappedLine(nParentline)))
5036 nParentline--;
5037 }
5038
5039 ApplyAutoIndentation(nParentline, nLine + 1);
5040 }
5041
5043}
5044
5045
5058{
5059 //if (!this->AutoCompActive()
5060 // && this->getEditorSetting(SETTING_INDENTONTYPE)
5061 // && (m_fileType == FILE_NSCR || m_fileType == FILE_NPRC || m_fileType == FILE_MATLAB || m_fileType == FILE_CPP)
5062 // && !isNoAutoIndentionKey(m_nLastReleasedKey)
5063 // && !HasSelection())
5064 // ApplyAutoIndentation(0, this->GetCurrentLine() + 1);
5065
5066
5068 m_analyzer->run();
5069
5070 markSections();
5072}
5073
5074
5082void NumeReEditor::OnStartDrag(wxStyledTextEvent& event)
5083{
5084 wxString gtxt = event.GetDragText();
5085}
5086
5087
5095void NumeReEditor::OnDragOver(wxStyledTextEvent& event)
5096{
5097 event.SetDragResult(wxDragMove);
5098 event.Skip();
5099}
5100
5101
5110void NumeReEditor::OnDrop(wxStyledTextEvent& event)
5111{
5112 event.Skip();
5113}
5114
5115
5124void NumeReEditor::OnMouseMotion(wxMouseEvent& event)
5125{
5126 if (m_dragging)
5127 DoDragOver(event.GetX(), event.GetY(), wxDragMove);
5128
5129 event.Skip();
5130}
5131
5132
5144void NumeReEditor::GotoPipe(int nStartPos)
5145{
5146 vector<int> vPos;
5147
5148 // Try to find the pipe in the file
5150 vPos = m_search->FindAll("|", wxSTC_NSCR_OPERATORS, nStartPos, GetLastPosition(), false);
5151
5152 // If nothting was found, try to find the pipe
5153 // in the install section
5154 if (m_fileType == FILE_NSCR && !vPos.size())
5155 vPos = m_search->FindAll("|", wxSTC_NSCR_INSTALL, nStartPos, GetLastPosition(), false);
5156
5157 // Go to the pipe, if it was found, and remove
5158 // it
5159 if (vPos.size())
5160 {
5161 GotoPos(vPos.front());
5162 DeleteRange(vPos.front(), 1);
5163 }
5164 else
5165 GotoLine(nStartPos); // fallback solution
5166}
5167
5168
5179void NumeReEditor::OnAddBreakpoint(wxCommandEvent& event)
5180{
5181 int linenum = GetLineForMarkerOperation();
5182 AddBreakpoint(linenum);
5184}
5185
5186
5201void NumeReEditor::OnRemoveBreakpoint(wxCommandEvent& event)
5202{
5203 int linenum = GetLineForMarkerOperation();
5204 RemoveBreakpoint(linenum);
5206}
5207
5208
5219void NumeReEditor::OnClearBreakpoints(wxCommandEvent& event)
5220{
5221 // m_breakpoints should have been cleared of any orphaned marker
5222 // handles during the right-click that led us here
5223 int numBreakpoints = GetBreakpoints().GetCount();
5224
5225 for (int i = 0; i < numBreakpoints; i++)
5226 {
5227 int markerHandle = m_breakpoints[i];
5228 this->MarkerDeleteHandle(markerHandle);
5229 }
5230
5233}
5234
5235
5243void NumeReEditor::OnAddBookmark(wxCommandEvent& event)
5244{
5245 int nLineNumber = GetLineForMarkerOperation();
5246 this->MarkerAdd(nLineNumber, MARKER_BOOKMARK);
5248}
5249
5250
5258void NumeReEditor::OnRemoveBookmark(wxCommandEvent& event)
5259{
5260 int nLineNumber = GetLineForMarkerOperation();
5261 this->MarkerDelete(nLineNumber, MARKER_BOOKMARK);
5262}
5263
5264
5273void NumeReEditor::OnClearBookmarks(wxCommandEvent& event)
5274{
5275 this->MarkerDeleteAll(MARKER_BOOKMARK);
5276}
5277
5278
5288{
5289 wxArrayInt linenumbers;
5290 wxArrayInt invalidBreakpoints;
5291
5292 int numStoredBreakpoints = m_breakpoints.GetCount();
5293 for (int i = 0; i < numStoredBreakpoints; i++)
5294 {
5295 int markerHandle = m_breakpoints[i];
5296
5297 int linenum = this->MarkerLineFromHandle(markerHandle);
5298
5299 if (linenum != -1)
5300 {
5301 linenumbers.Add(linenum + 1);
5302 }
5303 else
5304 {
5305 invalidBreakpoints.Add(markerHandle);
5306 }
5307 }
5308
5309 for (int i = 0; i < (int)invalidBreakpoints.GetCount(); i++)
5310 {
5311 m_breakpoints.Remove(invalidBreakpoints[i]);
5312 }
5313
5314 linenumbers.Sort((CMPFUNC_wxArraywxArrayInt)CompareInts);
5315 return linenumbers;
5316}
5317
5318
5327{
5328 m_procedureViewer = viewer;
5329}
5330
5331
5343void NumeReEditor::FocusOnLine(int linenumber, bool showMarker)
5344{
5345 GotoLine(linenumber);
5346 SetFirstVisibleLine(VisibleFromDocLine(linenumber) - m_options->GetDebuggerFocusLine());
5347 EnsureLineVisibility(linenumber);
5348
5349 if (showMarker)
5350 {
5351 MarkerDeleteAll(MARKER_FOCUSEDLINE);
5352 MarkerAdd(linenumber, MARKER_FOCUSEDLINE);
5353 }
5354}
5355
5356
5368{
5369 EnsureVisible(line);
5370
5371 // Unhide the lines, if the current line is part
5372 // of a hidden sectioon
5373 if (!GetLineVisible(line))
5374 {
5375 int nFirstLine = line-1;
5376 int nLastLine = line+1;
5377
5378 // Find the first unhidden line
5379 while (!GetLineVisible(nFirstLine))
5380 nFirstLine--;
5381
5382 // Find the last hidden line
5383 while (!GetLineVisible(nLastLine))
5384 nLastLine++;
5385
5386 // Show the lines
5387 ShowLines(nFirstLine, nLastLine);
5388
5389 // Delete the markers
5390 for (int i = nFirstLine; i < nLastLine; i++)
5391 {
5392 MarkerDelete(i, MARKER_HIDDEN);
5393 MarkerDelete(i, MARKER_HIDDEN_MARGIN);
5394 }
5395 }
5396}
5397
5398
5408{
5409 int lineNum = 0;
5410
5411 if (m_lastRightClick.x < 0 || m_lastRightClick.y < 0)
5412 lineNum = GetCurrentLine();
5413 else
5414 {
5415 int charpos = PositionFromPoint(m_lastRightClick);
5416 lineNum = LineFromPosition(charpos);
5417 }
5418
5419 return lineNum;
5420}
5421
5422
5431{
5432 m_lastRightClick.x = -1;
5433 m_lastRightClick.y = -1;
5434}
5435
5436
5444{
5445 m_analyzer->run();
5446}
5447
5448
5461void NumeReEditor::FindAndOpenProcedure(const wxString& procedurename)
5462{
5463 if (!procedurename.length())
5464 return;
5465
5466 vector<std::string> vPaths = m_terminal->getPathSettings();
5467 wxString pathname = procedurename;
5468
5469 // Validate the procedure name for unwanted characters
5470 for (size_t i = 0; i < pathname.length(); i++)
5471 {
5472 if (!isalnum(pathname[i])
5473 && pathname[i] != '$'
5474 && pathname[i] != '/'
5475 && pathname[i] != ':'
5476 && pathname[i] != '_'
5477 && pathname[i] != '\''
5478 && pathname[i] != '~')
5479 {
5480 wxMessageBox(_guilang.get("GUI_DLG_PROC_INVALIDCHARS", procedurename.ToStdString()), _guilang.get("GUI_DLG_PROC_INVALIDCHARS_HEADLINE"), wxCENTER | wxICON_ERROR | wxOK, this);
5481 return;
5482 }
5483 }
5484
5485 // Resolve the namespaces
5486 if (pathname.find("$this~") != string::npos)
5487 {
5488 // Get the current namespace and replace it
5489 wxString thispath = GetFileNameAndPath();
5490 pathname.replace(pathname.find("$this~"), 6, thispath.substr(0, thispath.rfind('\\') + 1));
5491
5492 while (pathname.find('~') != string::npos)
5493 pathname[pathname.find('~')] = '\\';
5494 }
5495 else if (pathname.find("$thisfile~") != string::npos)
5496 {
5497 // Search for the procedure in the current file
5498 wxString name = pathname.substr(pathname.rfind('~') + 1);
5499 wxString procedureline;
5500 int nminpos = 0;
5501 int nmaxpos = GetLastPosition();
5502
5503 // Search the procedure and check, whether it is uncommented
5504 while (nminpos < nmaxpos && FindText(nminpos, nmaxpos, "procedure", wxSTC_FIND_MATCHCASE | wxSTC_FIND_WHOLEWORD) != -1)
5505 {
5506 nminpos = FindText(nminpos, nmaxpos, "procedure", wxSTC_FIND_MATCHCASE | wxSTC_FIND_WHOLEWORD) + 1;
5507
5508 // Check for comments
5510 continue;
5511
5512 procedureline = GetLine(LineFromPosition(nminpos));
5513
5514 // If the line contains the necessary syntax elements
5515 // jump to it
5516 if (procedureline.find("$" + name) != string::npos && procedureline[procedureline.find_first_not_of(' ', procedureline.find("$" + name) + name.length() + 1)] == '(')
5517 {
5518 this->SetFocus();
5519 this->GotoLine(LineFromPosition(nminpos));
5520 this->SetFirstVisibleLine(VisibleFromDocLine(LineFromPosition(nminpos))-2);
5521 this->EnsureVisible(LineFromPosition(nminpos));
5522 return;
5523 }
5524 }
5525
5526 // If it is not found, ask the user for creation
5527 int ret = wxMessageBox(_guilang.get("GUI_DLG_PROC_NEXISTS_CREATE", procedurename.ToStdString()), _guilang.get("GUI_DLG_PROC_NEXISTS_CREATE_HEADLINE"), wxCENTER | wxICON_WARNING | wxYES_NO, this);
5528
5529 if (ret != wxYES)
5530 return;
5531
5532 // Get the template
5533 wxString proctemplate = getTemplateContent(name);
5534
5535 // Add the template after the last line
5536 int nLastLine = this->GetLineCount();
5537 this->GotoLine(nLastLine);
5538 this->AddText("\n");
5539 this->AddText(proctemplate);
5540
5541 // Replace the name in the template with the correct name
5542 // and goto the position
5543 nLastLine = FindText(this->PositionFromLine(nLastLine), this->GetLastPosition(), "procedure $" + name, wxSTC_FIND_MATCHCASE);
5544 this->GotoPipe(nLastLine);
5545
5546 // Update the syntax highlighting and the analyzer state
5548 m_analyzer->run();
5549
5550 return;
5551 }
5552 else
5553 {
5554 // Usual case: replace the namespace syntax with
5555 // the path syntax
5556 if (pathname.find("$main~") != string::npos)
5557 pathname.erase(pathname.find("$main~") + 1, 5);
5558
5559 while (pathname.find('~') != string::npos)
5560 pathname[pathname.find('~')] = '/';
5561
5562 if (pathname[0] == '$' && pathname.find(':') == string::npos)
5563 pathname.replace(0, 1, vPaths[5] + "/");
5564 else if (pathname.find(':') == string::npos)
5565 pathname.insert(0, vPaths[5]);
5566 else if (pathname.find('\'') != string::npos)
5567 pathname = pathname.substr(pathname.find('\'') + 1, pathname.rfind('\'') - pathname.find('\'') - 1);
5568 else if (pathname[0] == '$')
5569 pathname.erase(0, 1);
5570 }
5571
5572 wxArrayString pathnames;
5573 pathnames.Add(pathname + ".nprc");
5574
5575 // If the file with this path exists, open it,
5576 // otherwise ask the user for creation
5577 if (!fileExists((pathname + ".nprc").ToStdString()))
5578 {
5579 int ret = wxMessageBox(_guilang.get("GUI_DLG_PROC_NEXISTS_CREATE", procedurename.ToStdString()), _guilang.get("GUI_DLG_PROC_NEXISTS_CREATE_HEADLINE"), wxCENTER | wxICON_WARNING | wxYES_NO, this);
5580
5581 if (ret != wxYES)
5582 return;
5583
5584 m_mainFrame->NewFile(FILE_NPRC, pathname);
5585 }
5586 else
5587 m_mainFrame->OpenSourceFile(pathnames);
5588}
5589
5590
5601void NumeReEditor::FindAndOpenInclude(const wxString& includename)
5602{
5603 if (!includename.length())
5604 return;
5605
5606 wxArrayString pathnames;
5607 pathnames.Add(includename);
5608
5609 // If the file exists, open it, otherwise
5610 // ask the user for creation
5611 if (!fileExists((includename).ToStdString()))
5612 {
5613 int ret = wxMessageBox(_guilang.get("GUI_DLG_SCRIPT_NEXISTS_CREATE", includename.ToStdString()), _guilang.get("GUI_DLG_SCRIPT_NEXISTS_CREATE_HEADLINE"), wxCENTER | wxICON_WARNING | wxYES_NO, this);
5614
5615 if (ret != wxYES)
5616 return;
5617
5618 m_mainFrame->NewFile(FILE_NSCR, includename);
5619 }
5620 else
5621 m_mainFrame->OpenSourceFile(pathnames);
5622}
5623
5624
5632{
5633 return m_search->getProceduresInFile();
5634}
5635
5636
5648void NumeReEditor::ReplaceMatches(const vector<int>& vMatches, const wxString& sSymbol, const wxString& sNewSymbol)
5649{
5650 // During the replacement, the positions are moving
5651 // this variable tracks the differences
5652 int nInc = sNewSymbol.length() - sSymbol.length();
5653
5654 // Do nothing, if no match was found
5655 if (!vMatches.size())
5656 return;
5657
5658 // replace every match with the new symbol name
5659 for (size_t i = 0; i < vMatches.size(); i++)
5660 {
5661 this->Replace(vMatches[i] + i*nInc, vMatches[i]+sSymbol.length() + i*nInc, sNewSymbol);
5662 }
5663}
5664
5665
5680{
5681 wxString sNewName;
5682 wxString sCurrentName;
5683
5684 int nStartPos = 0;
5685 int nEndPos = this->GetLastPosition();
5686
5687 // Find the current symbol's name and ensure that it
5688 // exists
5689 sCurrentName = this->GetTextRange(this->WordStartPosition(nPos, true), this->WordEndPosition(nPos, true));
5690
5691 if (!sCurrentName.length())
5692 return;
5693
5694 // Change the position to the start of the selected symbol
5695 // to correctly identify the style of the selected symbol
5696 nPos = this->WordStartPosition(nPos, true);
5697
5698 // Prepare and show the text entry dialog, so that the
5699 // user may supply a new symbol name
5700 RenameSymbolsDialog textdialog(this, vRenameSymbolsChangeLog, wxID_ANY, _guilang.get("GUI_DLG_RENAMESYMBOLS"), sCurrentName);
5701 int retval = textdialog.ShowModal();
5702
5703 if (retval == wxID_CANCEL)
5704 return;
5705
5706 // Get the new symbol name and ensure that it
5707 // exists
5708 sNewName = textdialog.GetValue();
5709
5710 if (!sNewName.length() || (!textdialog.replaceAfterCursor() && !textdialog.replaceBeforeCursor()))
5711 return;
5712
5713 vRenameSymbolsChangeLog.push_back(sCurrentName + "\t" + sNewName);
5714
5715 // The selected symbol is probably part of a procedure. If this is
5716 // the case, get the start and end position here
5717 if ((m_fileType == FILE_NPRC || m_fileType == FILE_MATLAB) && !textdialog.replaceInWholeFile())
5718 {
5719 // Find the head of the current procedure
5720 nStartPos = m_search->FindCurrentProcedureHead(nPos);
5721
5722 // Find the end of the current procedure depending on
5723 // the located head
5724 vector<int> vBlock = this->BlockMatch(nStartPos);
5725 if (vBlock.back() != wxSTC_INVALID_POSITION)
5726 nEndPos = vBlock.back();
5727 }
5728
5729 // Adjust start and end position depending
5730 // on the flags of the renaming dialog
5731 if (!textdialog.replaceAfterCursor())
5732 {
5733 nEndPos = WordEndPosition(nPos, true);
5734 }
5735 else if (!textdialog.replaceBeforeCursor())
5736 {
5737 nStartPos = WordStartPosition(nPos, true);
5738 }
5739
5740 // Ensure that the new symbol is not already in use
5741 vector<int> vNewNameOccurences = m_search->FindAll(sNewName, GetStyleAt(nPos), nStartPos, nEndPos);
5742
5743 // It's possible to rename a standard function with
5744 // a new name. Check here against custom function
5745 // names
5746 if (!vNewNameOccurences.size() && isStyleType(STYLE_FUNCTION, nPos))
5747 vNewNameOccurences = m_search->FindAll(sNewName, wxSTC_NSCR_CUSTOM_FUNCTION, nStartPos, nEndPos);
5748
5749 // MATLAB-specific fix, because the MATLAB lexer
5750 // does know custom defined functions
5751 if (!vNewNameOccurences.size() && m_fileType == FILE_MATLAB && (isStyleType(STYLE_FUNCTION, nPos) || isStyleType(STYLE_COMMAND, nPos)))
5752 vNewNameOccurences = m_search->FindAll(sNewName, wxSTC_MATLAB_IDENTIFIER, nStartPos, nEndPos);
5753
5754 // If the vector size is non-zero, this symbol is
5755 // already in use
5756 if (vNewNameOccurences.size())
5757 {
5758 // Allow the user to cancel the replacement
5759 if (wxMessageBox(_guilang.get("GUI_DLG_RENAMESYMBOLS_ALREADYINUSE_WARNING"), _guilang.get("GUI_DLG_RENAMESYMBOLS_ALREADYINUSE"), wxCENTER | wxOK | wxCANCEL | wxICON_EXCLAMATION, this) == wxCANCEL)
5760 return;
5761 }
5762
5763 // Gather all operations into one undo step
5764 this->BeginUndoAction();
5765
5766 // Perform the renaming of symbols
5767 this->ReplaceMatches(m_search->FindAll(sCurrentName, this->GetStyleAt(nPos), nStartPos, nEndPos, textdialog.replaceInComments()), sCurrentName, sNewName);
5768 this->EndUndoAction();
5769}
5770
5771
5784{
5785 // Do nothing, if the user didn't select anything
5786 if (!HasSelection())
5787 return;
5788
5789 // Get start and end position (i.e. the corresponding lines)
5790 int nStartPos = PositionFromLine(LineFromPosition(GetSelectionStart()));
5791 int nEndPos = GetLineEndPosition(LineFromPosition(GetSelectionEnd()));
5792
5793 if (GetSelectionEnd() == PositionFromLine(LineFromPosition(GetSelectionEnd())))
5794 nEndPos = GetLineEndPosition(LineFromPosition(GetSelectionEnd()-1));
5795
5796 int nCurrentBlockStart = 0;
5797 int nCurrentBlockEnd = GetLastPosition();
5798
5799 std::list<wxString> lInputTokens;
5800 std::list<wxString> lOutputTokens;
5801
5802 std::set<std::string> sArgumentListSet;
5803 std::set<std::string> sMatlabReturnListSet;
5804
5805
5806 // If we have a procedure file, consider scoping
5808 {
5809 nCurrentBlockStart = m_search->FindCurrentProcedureHead(nStartPos);
5810
5811 std::string sArgumentList = getFunctionArgumentList(LineFromPosition(nCurrentBlockStart)).ToStdString();
5812
5813 // Split the argument list into single tokens
5814 while (sArgumentList.length())
5815 {
5816 std::string sCurrentArg = getNextArgument(sArgumentList, true);
5817
5818 // Remove possible default values
5819 if (sCurrentArg.find_first_of(" =") != std::string::npos)
5820 sCurrentArg.erase(sCurrentArg.find_first_of(" ="));
5821
5822 if (sCurrentArg.find('&') != std::string::npos)
5823 sCurrentArg.erase(sCurrentArg.find('&'), 1);
5824
5825 StripSpaces(sCurrentArg);
5826
5827 sArgumentListSet.insert(sCurrentArg);
5828 }
5829
5830 // In the MATLAB case, get the return list of
5831 // the function
5832 if (m_fileType == FILE_MATLAB)
5833 {
5834 std::string sReturnList = getMatlabReturnList(LineFromPosition(nCurrentBlockStart)).ToStdString();
5835
5836 // Split the return list into single tokens
5837 while (sReturnList.length())
5838 {
5839 sMatlabReturnListSet.insert(getNextArgument(sReturnList, true));
5840 }
5841 }
5842
5843 // Ensure that the end of the current block exists
5844 std::vector<int> vBlock = BlockMatch(nCurrentBlockStart);
5845
5846 if (vBlock.back() != wxSTC_INVALID_POSITION && vBlock.back() > nEndPos)
5847 nCurrentBlockEnd = vBlock.back();
5848
5849 // Increment the starting line to omit the argument list
5850 // as variable occurence source. Those will be detected
5851 // by comparing with the splitted argument list
5852 nCurrentBlockStart = PositionFromLine(LineFromPosition(nCurrentBlockStart)+1);
5853 }
5854
5855 // Determine the interface by searching for variables
5856 // and tables, which are used before or after the code
5857 // section and occure inside of the section
5858 for (int i = nStartPos; i <= nEndPos; i++)
5859 {
5861 {
5862 // Regular indices
5863 //
5864 // Jump over string parser characters
5865 while (isStyleType(STYLE_STRINGPARSER, i) && (GetCharAt(i) == '#' || GetCharAt(i) == '~'))
5866 i++;
5867
5869 continue;
5870
5871 // Get the token name
5872 wxString sCurrentToken = GetTextRange(WordStartPosition(i, true), WordEndPosition(i, true));
5873
5874 // Ignore MATLAB structure fields
5875 if (GetCharAt(WordStartPosition(i, true)-1) == '.')
5876 continue;
5877
5878 // Find all occurences
5879 std::vector<int> vMatch = m_search->FindAll(sCurrentToken, this->GetStyleAt(i), nCurrentBlockStart, nCurrentBlockEnd);
5880
5881 if (vMatch.size())
5882 {
5883 // Determine, whether the token is used before
5884 // or afer the current section
5885 if (vMatch.front() < nStartPos
5886 || (sArgumentListSet.size() && sArgumentListSet.find(sCurrentToken.ToStdString()) != sArgumentListSet.end()))
5887 lInputTokens.push_back(sCurrentToken);
5888
5889 if (vMatch.back() > nEndPos
5890 && vMatch.front() < nStartPos
5891 && IsModifiedInSection(nStartPos, nEndPos, sCurrentToken, vMatch))
5892 lOutputTokens.push_back(sCurrentToken);
5893 else if (vMatch.back() > nEndPos
5894 && vMatch.front() >= nStartPos
5895 && sArgumentListSet.find(sCurrentToken.ToStdString()) == sArgumentListSet.end())
5896 lOutputTokens.push_back(sCurrentToken);
5897 else if (sMatlabReturnListSet.size()
5898 && sMatlabReturnListSet.find(sCurrentToken.ToStdString()) != sMatlabReturnListSet.end()
5899 && IsModifiedInSection(nStartPos, nEndPos, sCurrentToken, vMatch))
5900 lOutputTokens.push_back(sCurrentToken);
5901 }
5902
5903 i += sCurrentToken.length();
5904 }
5906 {
5907 // Matlab specials
5908 //
5909 // Get the token name
5910 wxString sCurrentToken = GetTextRange(WordStartPosition(i, true), WordEndPosition(i, true));
5911
5912 // Ignore MATLAB structure fields
5913 if (GetCharAt(WordStartPosition(i, true)-1) == '.')
5914 continue;
5915
5916 // Ignore functions, which are not part of any argument list;
5917 // these are most probably actual functions
5918 if ((!sMatlabReturnListSet.size() || sMatlabReturnListSet.find(sCurrentToken.ToStdString()) == sMatlabReturnListSet.end())
5919 && (!sArgumentListSet.size() || sArgumentListSet.find(sCurrentToken.ToStdString()) == sArgumentListSet.end()))
5920 continue;
5921
5922 // Find all occurences
5923 std::vector<int> vMatch = m_search->FindAll(sCurrentToken, this->GetStyleAt(i), nCurrentBlockStart, nCurrentBlockEnd);
5924
5925 if (vMatch.size())
5926 {
5927 // Determine, whether the token is used before
5928 // or afer the current section
5929 if (sArgumentListSet.size() && sArgumentListSet.find(sCurrentToken.ToStdString()) != sArgumentListSet.end())
5930 lInputTokens.push_back(sCurrentToken);
5931
5932 if (sMatlabReturnListSet.size() && sMatlabReturnListSet.find(sCurrentToken.ToStdString()) != sMatlabReturnListSet.end() && IsModifiedInSection(nStartPos, nEndPos, sCurrentToken, vMatch))
5933 lOutputTokens.push_back(sCurrentToken);
5934 }
5935
5936 i += sCurrentToken.length();
5937 }
5938 else if (isStyleType(STYLE_DATAOBJECT, i))
5939 {
5940 // Tables
5941 //
5942 // Get the token name
5943 wxString sCurrentToken = GetTextRange(WordStartPosition(i, true), WordEndPosition(i, true));
5944
5945 // Find all occurences
5946 std::vector<int> vMatch = m_search->FindAll(sCurrentToken, this->GetStyleAt(i), nCurrentBlockStart, nCurrentBlockEnd);
5947
5948 if (vMatch.size())
5949 {
5950 // Determine, whether the token is used before
5951 // or after the current section
5952 if (vMatch.front() < nStartPos
5953 || (sArgumentListSet.find(sCurrentToken.ToStdString() + "()") != sArgumentListSet.end()
5954 && GetStyleAt(i) == wxSTC_NSCR_CUSTOM_FUNCTION)
5955 || (sArgumentListSet.find(sCurrentToken.ToStdString() + "{}") != sArgumentListSet.end()
5956 && GetStyleAt(i) == wxSTC_NSCR_CLUSTER))
5957 {
5958 if (GetStyleAt(i) == wxSTC_NSCR_CLUSTER)
5959 lInputTokens.push_back(sCurrentToken + "{}");
5960 else
5961 lInputTokens.push_back(sCurrentToken + "()");
5962 }
5963
5964 if (vMatch.back() > nEndPos
5965 && IsModifiedInSection(nStartPos, nEndPos, sCurrentToken, vMatch))
5966 {
5967 if (GetStyleAt(i) == wxSTC_NSCR_CLUSTER)
5968 lOutputTokens.push_back(sCurrentToken + "{}");
5969 else
5970 lOutputTokens.push_back(sCurrentToken + "()");
5971 }
5972 }
5973
5974 i += sCurrentToken.length();
5975 }
5976 }
5977
5978 // Only use each token once. We use the list
5979 // functionalities of C++
5980 if (lInputTokens.size())
5981 {
5982 lInputTokens.sort();
5983 lInputTokens.unique();
5984 }
5985
5986 if (lOutputTokens.size())
5987 {
5988 lOutputTokens.sort();
5989 lOutputTokens.unique();
5990 }
5991
5992 // If the output list is larger than one element
5993 // and we're extracting NumeRe code, we have to ensure
5994 // that it does not contain a table or a cluster, because
5995 // this mixtures are not possible
5996 if (lOutputTokens.size() > 1 && (m_fileType == FILE_NSCR || m_fileType == FILE_NPRC))
5997 {
5998 auto iter = lOutputTokens.begin();
5999
6000 while (iter != lOutputTokens.end())
6001 {
6002 if ((*iter).find("()") != std::string::npos
6003 || (*iter).find("{}") != std::string::npos)
6004 {
6005 // We have a table or a cluster as a mixture
6006 auto inputIter = std::find(lInputTokens.begin(), lInputTokens.end(), *iter);
6007
6008 if (inputIter != lInputTokens.end())
6009 *inputIter += "&";
6010 else
6011 lInputTokens.push_back(*iter + "&");
6012
6013 iter = lOutputTokens.erase(iter);
6014 continue;
6015 }
6016
6017 ++iter;
6018 }
6019 }
6020
6021 wxString sInputList;
6022 wxString sOutputList;
6023
6024 // Create the interface definition lists
6025 for (auto iter = lInputTokens.begin(); iter != lInputTokens.end(); ++iter)
6026 {
6027 sInputList += *iter + ",";
6028 }
6029
6030 if (sInputList.length())
6031 sInputList.erase(sInputList.length()-1);
6032
6033 for (auto iter = lOutputTokens.begin(); iter != lOutputTokens.end(); ++iter)
6034 {
6035 sOutputList += *iter + ",";
6036 }
6037
6038 if (sOutputList.length())
6039 sOutputList.erase(sOutputList.length()-1);
6040
6041 // Use these interfaces and the positions to
6042 // create the new procedure in a new window
6043 CreateProcedureFromSection(nStartPos, nEndPos, sInputList, sOutputList);
6044}
6045
6046
6062void NumeReEditor::CreateProcedureFromSection(int nStartPos, int nEndPos, const wxString& sInputList, const wxString sOutputList)
6063{
6064 // Creata a new window and a new editor
6065 ViewerFrame* copyFrame = new ViewerFrame(m_mainFrame, _guilang.get("GUI_REFACTORING_COPYWINDOW_HEAD"));
6066 NumeReEditor* edit = new NumeReEditor(m_mainFrame, m_options, copyFrame, wxID_ANY, _syntax, m_terminal, wxDefaultPosition, wxDefaultSize, wxBORDER_THEME);
6067 wxStatusBar* statusbar = copyFrame->CreateStatusBar();
6068 int sizes[] = {-2, -1};
6069 statusbar->SetFieldsCount(2, sizes);
6070 statusbar->SetStatusText(_guilang.get("GUI_STATUSBAR_UNSAVEDFILE"), 0);
6071
6072 // Fill the editor with the new procedure and its
6073 // determined interface
6075 {
6076 // Set a default file name with the corresponding
6077 // extension
6078 edit->SetFilename(wxFileName("numere.nprc"), false);
6079 edit->SetText("\r\n");
6080
6081 // Write some preface comment
6082 edit->AddText("## " + _guilang.get("GUI_REFACTORING_NOTE") + "\r\n");
6083 edit->AddText("##\r\n");
6084 edit->AddText("## " + _guilang.get("GUI_REFACTORING_ARGUMENTLIST") + "\r\n");
6085
6086 // Write the input argument list
6087 edit->AddText("procedure $NEWPROCEDURE(" + sInputList + ")\r\n");
6088
6089 // Write the actual section of code
6090 wxString sCodeFragment = GetTextRange(nStartPos, nEndPos);
6091 size_t nLastChar = sCodeFragment.find_last_not_of("\r\n \t");
6092 bool hasReturn = false;
6093
6094 if (nLastChar != std::string::npos)
6095 hasReturn = sCodeFragment.find("return", sCodeFragment.find_last_of("\r\n", nLastChar)) != std::string::npos;
6096
6097 edit->AddText(sCodeFragment + "\r\n");
6098
6099 // Write the output list
6100 if (sOutputList.length())
6101 {
6102 edit->AddText("\t## " + _guilang.get("GUI_REFACTORING_RETURNVALUES") + "\r\n");
6103
6104 if (sOutputList.find(',') != string::npos)
6105 edit->AddText("return {" + sOutputList + "};\r\n");
6106 else
6107 edit->AddText("return " + sOutputList + ";\r\n");
6108 }
6109 else if (!hasReturn)
6110 edit->AddText("return void\r\n");
6111
6112 edit->AddText("endprocedure\r\n");
6113 statusbar->SetStatusText(_guilang.get("GUI_STATUSBAR_NPRC"), 1);
6114 }
6115 else if (m_fileType == FILE_MATLAB)
6116 {
6117 // Set a default file name with the corresponding
6118 // extension
6119 edit->SetFilename(wxFileName("numere.m"), false);
6120 edit->SetText("\r\n");
6121
6122 // Write some preface comment
6123 edit->AddText("% " + _guilang.get("GUI_REFACTORING_NOTE") + "\r\n");
6124 edit->AddText("%\r\n");
6125 edit->AddText("% " + _guilang.get("GUI_REFACTORING_ARGUMENTLIST") + "\r\n");
6126
6127 if (sOutputList.length())
6128 edit->AddText("% " + _guilang.get("GUI_REFACTORING_RETURNVALUES") + "\r\n");
6129
6130 edit->AddText("function ");
6131
6132 // Write the output list
6133 if (sOutputList.length())
6134 {
6135 edit->AddText("[" + sOutputList + "] = ");
6136 }
6137
6138 // Write the input argument list
6139 edit->AddText("NEWFUNCTION(" + sInputList + ")\r\n");
6140
6141 // Write the actual section of code
6142 edit->AddText(this->GetTextRange(nStartPos, nEndPos) + "\r\n");
6143 edit->AddText("end\r\n");
6144 statusbar->SetStatusText(_guilang.get("GUI_STATUSBAR_M"), 1);
6145 }
6146
6147 // Update the syntax highlighting
6148 // and use the autoformatting feature
6149 edit->UpdateSyntaxHighlighting(true);
6150 edit->ApplyAutoFormat(0, -1);
6152
6153 // Set a reasonable window size and
6154 // display it to the user
6155 copyFrame->SetSize(800, 600);
6156 copyFrame->SetIcon(m_mainFrame->getStandardIcon());
6157 copyFrame->Show();
6158 copyFrame->SetFocus();
6159}
6160
6161
6178bool NumeReEditor::IsModifiedInSection(int nSectionStart, int nSectionEnd, const wxString& sToken, const vector<int>& vMatch)
6179{
6180 // define the set of modifying operators
6181 static wxString sModificationOperators = "+= -= /= ^= *= ++ --";
6182
6183 // Go through all occurences of the current token
6184 for (size_t i = 0; i < vMatch.size(); i++)
6185 {
6186 // Ignore occurences before or after the current
6187 // code section
6188 if (vMatch[i] < nSectionStart)
6189 continue;
6190 if (vMatch[i] > nSectionEnd)
6191 break;
6192
6193 // Ignore dynamic structure field accesses in MATLAB
6194 if (isStyleType(STYLE_OPERATOR, vMatch[i]-1)
6195 && (GetCharAt(vMatch[i]-1) == '.' || (GetCharAt(vMatch[i]-2) == '.' && GetCharAt(vMatch[i]-1) == '(')))
6196 continue;
6197
6198 // Examine the code part left of the token, whether
6199 // there's a modifying operator
6200 for (int j = vMatch[i]+sToken.length(); j < nSectionEnd; j++)
6201 {
6202 // Ignore whitespaces
6203 if (GetCharAt(j) == ' ' || GetCharAt(j) == '\t')
6204 continue;
6205
6206 // We only examine operator characters
6207 if (isStyleType(STYLE_OPERATOR, j) && isStyleType(STYLE_OPERATOR, j+1) && sModificationOperators.find(GetTextRange(j, j+2)) != string::npos)
6208 return true;
6209 else if (isStyleType(STYLE_OPERATOR, j) && GetCharAt(j) == '=' && GetCharAt(j+1) != '=')
6210 return true;
6211 else if (isStyleType(STYLE_OPERATOR, j) && (GetCharAt(j) == '(' || GetCharAt(j) == '[' || GetCharAt(j) == '{'))
6212 {
6213 // Jump over parentheses
6214 j = BraceMatch(j);
6215 if (j == wxSTC_INVALID_POSITION)
6216 return false;
6217 }
6218 else if (isStyleType(STYLE_OPERATOR, j) && (GetCharAt(j) == ')' || GetCharAt(j) == ']' || GetCharAt(j) == '}' || GetCharAt(j) == ':'))
6219 {
6220 // ignore closing parentheses
6221 continue;
6222 }
6223 else if (isStyleType(STYLE_OPERATOR, j) && GetCharAt(j) == '.' && isStyleType(STYLE_IDENTIFIER, j+1))
6224 {
6225 // MATLAB struct fix
6226 while (isStyleType(STYLE_IDENTIFIER, j+1))
6227 j++;
6228 }
6229 else if (isStyleType(STYLE_OPERATOR, j) && GetCharAt(j) == '.' && isStyleType(STYLE_FUNCTION, j+1))
6230 {
6231 // MATLAB struct fix
6232 while (isStyleType(STYLE_FUNCTION, j+1))
6233 j++;
6234 }
6235 else if (isStyleType(STYLE_OPERATOR, j) && GetCharAt(j) == '.' && GetCharAt(j+1) == '(')
6236 {
6237 // MATLAB struct fix
6238 // Jump over parentheses
6239 j = BraceMatch(j+1);
6240 if (j == wxSTC_INVALID_POSITION)
6241 return false;
6242 }
6243 else if (isStyleType(STYLE_OPERATOR, j) && GetCharAt(j) == ',')
6244 {
6245 // Try to find the end of the current bracket
6246 // or the current brace - we don't use parentheses
6247 // as terminators, because they are not used to
6248 // gather return values
6249 for (int k = j; k < nSectionEnd; k++)
6250 {
6251 if (isStyleType(STYLE_OPERATOR, k) && (GetCharAt(k) == ']' || GetCharAt(k) == '}'))
6252 {
6253 j = k;
6254 break;
6255 }
6256 else if (isStyleType(STYLE_OPERATOR, k) && GetCharAt(k) == ';')
6257 break;
6258 }
6259 }
6260 else
6261 break;
6262 }
6263 }
6264
6265 return false;
6266}
6267
6268
6279wxString NumeReEditor::getFunctionArgumentList(int nFunctionStartLine)
6280{
6281 // Get the complete line
6282 wxString sReturn = GetLine(nFunctionStartLine);
6283
6284 // Ensure that the line contains the keyword "function"
6285 // or "procedure", respectively
6286 if ((sReturn.find("function ") == string::npos && m_fileType == FILE_MATLAB)
6287 || (sReturn.find("procedure ") == string::npos && m_fileType == FILE_NPRC))
6288 return "";
6289
6290 // Ensure that the line contains opening and
6291 // closing parentheses
6292 if (sReturn.find('(') == string::npos || sReturn.find(')') == string::npos)
6293 return "";
6294
6295 // Extract the function argument list
6296 sReturn.erase(0, sReturn.find('(')+1);
6297 sReturn.erase(sReturn.rfind(')'));
6298
6299 // Return the argument list
6300 return sReturn;
6301}
6302
6303
6314wxString NumeReEditor::getMatlabReturnList(int nMatlabFunctionStartLine)
6315{
6316 // Get the complete line
6317 wxString sReturn = GetLine(nMatlabFunctionStartLine);
6318
6319 // Ensure that the line contains the keyword "function"
6320 if (sReturn.find("function") == string::npos)
6321 return "";
6322
6323 // Ensure that the line contains an equal sign
6324 if (sReturn.find('=') == string::npos)
6325 return "";
6326
6327 // Remove the keyword part and the function declaration itself
6328 sReturn.erase(0, sReturn.find("function")+8);
6329 sReturn.erase(sReturn.find('='));
6330
6331 // Remove surrounding brackets
6332 if (sReturn.find('[') != string::npos && sReturn.find(']') != string::npos)
6333 {
6334 sReturn.erase(0, sReturn.find('[')+1);
6335 sReturn.erase(sReturn.rfind(']'));
6336 }
6337
6338 // Return the return list
6339 return sReturn;
6340}
6341
6342
6353wxString NumeReEditor::getTemplateContent(const wxString& sFileName)
6354{
6355 wxString template_file, template_type, timestamp;
6356
6357 template_type = "tmpl_procedure.nlng";
6358 timestamp = getTimeStamp(false);
6359
6360 // Get the file's contents
6361 if (m_terminal->getKernelSettings().useCustomLangFiles() && wxFileExists(m_mainFrame->getProgramFolder() + "\\user\\lang\\" + template_type))
6362 m_mainFrame->GetFileContents(m_mainFrame->getProgramFolder() + "\\user\\lang\\" + template_type, template_file, template_type);
6363 else
6364 m_mainFrame->GetFileContents(m_mainFrame->getProgramFolder() + "\\lang\\" + template_type, template_file, template_type);
6365
6366 // Replace filenames
6367 while (template_file.find("%%1%%") != string::npos)
6368 template_file.replace(template_file.find("%%1%%"), 5, sFileName);
6369
6370 // Replace timestamps
6371 while (template_file.find("%%2%%") != string::npos)
6372 template_file.replace(template_file.find("%%2%%"), 5, timestamp);
6373
6374 return template_file;
6375}
6376
6377
6389bool NumeReEditor::isValidAutoCompMatch(int nPos, bool findAll, bool searchMethod)
6390{
6391 // Ignore self matches
6392 if (nPos <= GetCurrentPos() && WordEndPosition(nPos+1, true) >= GetCurrentPos())
6393 return false;
6394
6395 // Ignore matches not at the starting position
6396 if (nPos != WordStartPosition(nPos, true))
6397 return false;
6398
6399 // Check style conditions
6400 if (findAll)
6401 return true;
6402 else if (!isStyleType(STYLE_COMMENT, nPos)
6403 && !isStyleType(STYLE_STRING, nPos)
6404 && (!searchMethod || GetCharAt(nPos-1) == '.'))
6405 return true;
6406
6407 return false;
6408}
6409
6410
6426wxString NumeReEditor::generateAutoCompList(int wordstartpos, int currpos, std::string sPreDefList)
6427{
6428 std::map<wxString, int> mAutoCompMap;
6429 wxString wReturn = "";
6430 std::string sCurrentWord;
6431
6432 // Store the list of predefined values in the map
6433 if (sPreDefList.length())
6434 {
6435 while (sPreDefList.length())
6436 {
6437 sCurrentWord = sPreDefList.substr(0, sPreDefList.find(' '));
6438 mAutoCompMap[toUpperCase(sCurrentWord.substr(0, sCurrentWord.find_first_of("(?"))) + " |" + sCurrentWord] = -1;
6439 sPreDefList.erase(0, sPreDefList.find(' '));
6440
6441 if (sPreDefList.front() == ' ')
6442 sPreDefList.erase(0, 1);
6443 }
6444 }
6445
6446 bool useSmartSense = m_options->getSetting(SETTING_B_SMARTSENSE).active();
6447 bool searchMethod = GetCharAt(wordstartpos) == '.';
6448 wxString wordstart = GetTextRange(searchMethod ? wordstartpos+1 : wordstartpos, currpos);
6449 std::pair<int, int> context = std::make_pair(0, GetLineCount());
6450
6451 if (useSmartSense)
6452 context = getCurrentContext(LineFromPosition(currpos));
6453
6454 unsigned int nPos = PositionFromLine(context.first);
6455 bool findAll = !useSmartSense
6456 || isStyleType(STYLE_COMMENT, wordstartpos)
6457 || isStyleType(STYLE_STRING, wordstartpos);
6458
6459 int searchFlags = wxSTC_FIND_WORDSTART;
6460
6461 // If we use SmartSense, then we'll using RegEx and also
6462 // accept leading underscores as possible matches
6463 if (useSmartSense && !searchMethod)
6464 {
6465 wordstart.insert(0, "\\<_*");
6466 searchFlags = wxSTC_FIND_REGEXP;
6467 }
6468
6469 // Find every occurence of the current word start
6470 // and store the possible completions in the map
6471 while ((nPos = FindText(nPos, GetLineEndPosition(context.second), wordstart, searchFlags)) != std::string::npos)
6472 {
6473 if (isValidAutoCompMatch(nPos, findAll, searchMethod))
6474 {
6475 wxString sMatch = GetTextRange(nPos, WordEndPosition(nPos + 1, true));
6476 wxString sFillUp;
6477
6478 // Append the needed opening parentheses, if the completed
6479 // objects are data objects or functions
6481 sFillUp = "(?" + toString((int)NumeReSyntax::SYNTAX_TABLE);
6482 else if (isStyleType(STYLE_DATAOBJECT, nPos))
6483 sFillUp = "{?" + toString((int)NumeReSyntax::SYNTAX_CLUSTER);
6484 else if (isStyleType(STYLE_IDENTIFIER, nPos))
6485 sFillUp = "?" + toString((int)NumeReSyntax::SYNTAX_STD);
6486
6487 mAutoCompMap[toUpperCase(sMatch.ToStdString()) + " |" + sMatch+sFillUp] = 1;
6488 }
6489
6490 nPos++;
6491 }
6492
6493 // Get all declares if we do not start on the first line
6494 if (useSmartSense && context.first != 0 && !searchMethod)
6495 {
6496 // Find the declares in front of the current autocompletion part
6497 std::vector<int> vMatches = m_search->FindAll("declare", wxSTC_NSCR_COMMAND, 0, PositionFromLine(context.first), false);
6498
6499 for (int pos : vMatches)
6500 {
6501 int lineEnd = GetLineEndPosition(LineFromPosition(pos));
6502
6503 // Find every occurence of the current word start
6504 // and store the possible completions in the map
6505 while ((pos = FindText(pos, lineEnd, wordstart, searchFlags)) != wxNOT_FOUND)
6506 {
6507 if (isValidAutoCompMatch(pos, findAll, searchMethod))
6508 {
6509 wxString sMatch = GetTextRange(pos, WordEndPosition(pos + 1, true));
6510 wxString sFillUp;
6511
6512 // Append the needed opening parentheses, if the completed
6513 // objects are data objects or functions
6515 sFillUp = "(?" + toString((int)NumeReSyntax::SYNTAX_TABLE);
6516 else if (isStyleType(STYLE_DATAOBJECT, pos))
6517 sFillUp = "{?" + toString((int)NumeReSyntax::SYNTAX_CLUSTER);
6518 else if (isStyleType(STYLE_IDENTIFIER, pos))
6519 sFillUp = "?" + toString((int)NumeReSyntax::SYNTAX_STD);
6520
6521 mAutoCompMap[toUpperCase(sMatch.ToStdString()) + " |" + sMatch+sFillUp] = 1;
6522 }
6523
6524 pos++;
6525 }
6526 }
6527 }
6528
6529 // remove duplicates
6530 for (auto iter = mAutoCompMap.begin(); iter != mAutoCompMap.end(); ++iter)
6531 {
6532 if (iter->second == -1)
6533 {
6534 if ((iter->first).find('(') != std::string::npos)
6535 {
6536 if (mAutoCompMap.find((iter->first).substr(0, (iter->first).find('('))) != mAutoCompMap.end())
6537 {
6538 mAutoCompMap.erase((iter->first).substr(0, (iter->first).find('(')));
6539 iter = mAutoCompMap.begin();
6540 }
6541 }
6542 else
6543 {
6544 if (mAutoCompMap.find((iter->first).substr(0, (iter->first).find('?'))) != mAutoCompMap.end())
6545 {
6546 mAutoCompMap.erase((iter->first).substr(0, (iter->first).find('?')));
6547 iter = mAutoCompMap.begin();
6548 }
6549 }
6550 }
6551 }
6552
6553 // Re-combine the autocompletion list
6554 for (const auto& iter : mAutoCompMap)
6555 wReturn += iter.first.substr(iter.first.find('|') + 1) + " ";
6556
6557 return wReturn;
6558}
6559
6560
6571void NumeReEditor::OnDisplayVariable(wxCommandEvent& event)
6572{
6573 // Clear the highlighting state and prepare the
6574 // colors and style for the next highlighting
6575 long int maxpos = this->GetLastPosition();
6576 SetIndicatorCurrent(HIGHLIGHT);
6577 IndicatorClearRange(0, maxpos);
6578
6579 unsigned int nPos = 0;
6580 unsigned int nCurr = 0;
6581 vector<unsigned int> vSelectionList;
6582
6583 // If the current clicked word is already
6584 // highlighted, then simply clear out the
6585 // buffer string and return
6587 {
6588 m_watchedString.clear();
6589 return;
6590 }
6591
6592 // Update the buffer with the new clicked word
6594
6595 // Search for all occurences of the current clicked
6596 // word in the document and store them
6597 while ((nPos = this->FindText(nCurr, maxpos, m_clickedWord, wxSTC_FIND_MATCHCASE | wxSTC_FIND_WHOLEWORD)) != string::npos)
6598 {
6599 vSelectionList.push_back(nPos);
6600 nCurr = nPos + m_clickedWordLength;
6601 }
6602
6603 // Apply the indicator to all found occurences
6604 for (size_t i = 0; i < vSelectionList.size(); i++)
6605 {
6606 this->IndicatorFillRange(vSelectionList[i], m_clickedWordLength);
6607 }
6608}
6609
6610
6620void NumeReEditor::OnHelpOnSelection(wxCommandEvent& event)
6621{
6622 m_mainFrame->ShowHelp(m_clickedWord.ToStdString());
6623}
6624
6625
6634void NumeReEditor::OnFindProcedure(wxCommandEvent& event)
6635{
6636 if (!m_clickedProcedure.length())
6637 return;
6638
6640}
6641
6642
6651{
6652 if (!isNumeReFileType() || GetStyleAt(GetCurrentPos()) != wxSTC_NSCR_PROCEDURES)
6653 return;
6654
6655 m_search->FindMarkedProcedure(GetCurrentPos());
6657}
6658
6659
6668void NumeReEditor::OnFindInclude(wxCommandEvent& event)
6669{
6670 if (!m_clickedInclude.length())
6671 return;
6672
6674}
6675
6676
6685{
6686 if (!isNumeReFileType() || GetStyleAt(GetCurrentPos()) != wxSTC_NSCR_INCLUDES)
6687 return;
6688
6689 m_search->FindMarkedInclude(GetCurrentPos());
6691}
6692
6693
6702void NumeReEditor::OnChangeCase(wxCommandEvent& event)
6703{
6704 if (!HasSelection())
6705 return;
6706
6707 // Get selection positions
6708 int nFirstPos = GetSelectionStart();
6709 int nLastPos = GetSelectionEnd();
6710
6711 // Change the case
6712 if (event.GetId() == ID_UPPERCASE)
6713 Replace(nFirstPos, nLastPos, toUpperCase(GetSelectedText().ToStdString()));
6714 else
6715 Replace(nFirstPos, nLastPos, toLowerCase(GetSelectedText().ToStdString()));
6716}
6717
6718
6726void NumeReEditor::OnFoldCurrentBlock(wxCommandEvent& event)
6727{
6728 FoldCurrentBlock(this->LineFromPosition(this->PositionFromPoint(m_lastRightClick)));
6729}
6730
6731
6740void NumeReEditor::OnHideSelection(wxCommandEvent& event)
6741{
6742 int nFirstLine = LineFromPosition(GetSelectionStart());
6743 int nLastLine = LineFromPosition(GetSelectionEnd());
6744
6745 HideLines(nFirstLine, nLastLine);
6746
6747 MarkerAdd(nFirstLine-1, MARKER_HIDDEN);
6748 MarkerAdd(nFirstLine-1, MARKER_HIDDEN_MARGIN);
6749}
6750
6751
6760{
6761 if (GetAllLinesVisible())
6762 return;
6763
6764 ShowLines(0, LineFromPosition(GetLastPosition()));
6765
6766 MarkerDeleteAll(MARKER_HIDDEN);
6767 MarkerDeleteAll(MARKER_HIDDEN_MARGIN);
6768}
6769
6770
6778void NumeReEditor::OnRenameSymbols(wxCommandEvent& event)
6779{
6780 this->RenameSymbols(this->PositionFromPoint(m_lastRightClick));
6781}
6782
6783
6791{
6792 int charpos = GetCurrentPos();
6793
6794 if (this->isStyleType(STYLE_DEFAULT, charpos) || this->isStyleType(STYLE_IDENTIFIER, charpos) || this->isStyleType(STYLE_DATAOBJECT, charpos) || this->isStyleType(STYLE_FUNCTION, charpos))
6795 this->RenameSymbols(charpos);
6796}
6797
6798
6806void NumeReEditor::OnFixTypes(wxCommandEvent& event)
6807{
6808 fixSymbolName(this->PositionFromPoint(m_lastRightClick));
6809}
6810
6811
6820void NumeReEditor::OnAbstrahizeSection(wxCommandEvent& event)
6821{
6822 this->AbstrahizeSection();
6823}
6824
6825
6834{
6835 if (HasSelection())
6836 this->AbstrahizeSection();
6837}
6838
6839
6847void NumeReEditor::OnMenuEvent(wxCommandEvent& event)
6848{
6849 switch (event.GetId())
6850 {
6851 case ID_MENU_COPY:
6852 Copy();
6853 break;
6854 case ID_MENU_CUT:
6855 Cut();
6856 break;
6857 case ID_MENU_PASTE:
6858 Paste();
6859 break;
6860 }
6861}
6862
6863
6872{
6873 int nFirstLine = 0;
6874 int nLastLine = -1;
6875
6876 if (HasSelection())
6877 {
6878 nFirstLine = LineFromPosition(GetSelectionStart());
6879 nLastLine = LineFromPosition(GetSelectionEnd());
6880
6881 // Decrement, if first position is selected
6882 if (GetSelectionEnd() == PositionFromLine(nLastLine))
6883 nLastLine--;
6884 }
6885
6886 Transpose(nFirstLine, nLastLine);
6887}
6888
6889
6898{
6899 int nFirstLine = 0;
6900 int nLastLine = -1;
6901
6902 if (HasSelection())
6903 {
6904 nFirstLine = LineFromPosition(GetSelectionStart());
6905 nLastLine = LineFromPosition(GetSelectionEnd());
6906
6907 // Decrement, if first position is selected
6908 if (GetSelectionEnd() == PositionFromLine(nLastLine))
6909 nLastLine--;
6910 }
6911
6912 wxString sHtml = ExtractAsHTML(nFirstLine, nLastLine);
6913
6914 if (wxTheClipboard->Open())
6915 {
6916 wxTheClipboard->SetData(new wxTextDataObject(sHtml));
6917 wxTheClipboard->Close();
6918 }
6919}
6920
6921
6930{
6931 int nFirstLine = 0;
6932 int nLastLine = -1;
6933
6934 if (HasSelection())
6935 {
6936 nFirstLine = LineFromPosition(GetSelectionStart());
6937 nLastLine = LineFromPosition(GetSelectionEnd());
6938
6939 // Decrement, if first position is selected
6940 if (GetSelectionEnd() == PositionFromLine(nLastLine))
6941 nLastLine--;
6942 }
6943
6944 wxString sHtml = ExtractAsHTML(nFirstLine, nLastLine);
6945
6946 sHtml.Replace(" ", "&nbsp;&nbsp;");
6947 sHtml.Replace("\r\n", "\n");
6948 sHtml.Replace("\n\n", "<br>&nbsp;<br>");
6949 sHtml.Replace("\n", "<br>");
6950
6951 if (wxTheClipboard->Open())
6952 {
6953 wxTheClipboard->SetData(new wxHTMLDataObject(sHtml));
6954 wxTheClipboard->Close();
6955 }
6956}
6957
6958
6966{
6968 {
6969 m_duplicateCode = new DuplicateCodeDialog(this, "NumeRe: " + _guilang.get("GUI_DUPCODE_TITLE") + " [" + this->GetFilenameString() + "]");
6971 m_duplicateCode->Show();
6972 m_duplicateCode->SetFocus();
6973 m_duplicateCode->Refresh();
6974 return true;
6975 }
6976
6977 return false;
6978}
6979
6980
6989void NumeReEditor::OnFindDuplicateCode(int nDuplicateFlag, int nNumDuplicatedLines)
6990{
6991 detectCodeDuplicates(0, this->LineFromPosition(this->GetLastPosition()), nDuplicateFlag, nNumDuplicatedLines);
6992}
6993
6994
7006void NumeReEditor::OnThreadUpdate(wxThreadEvent& event)
7007{
7008 if (m_nProcessValue < 100)
7009 {
7010 // Update the gauge
7011 if (m_duplicateCode && m_duplicateCode->IsShown())
7013 }
7014 else
7015 {
7016 // Update the gauge
7017 if (m_duplicateCode && m_duplicateCode->IsShown())
7019 else
7020 {
7021 vDuplicateCodeResults.clear();
7022 return;
7023 }
7024
7025 // Pass the results
7026 wxCriticalSectionLocker lock(m_editorCS);
7028 vDuplicateCodeResults.clear();
7029 }
7030
7031}
7032
7033
7050void NumeReEditor::IndicateDuplicatedLine(int nStart1, int nEnd1, int nStart2, int nEnd2, int nSelectionLine)
7051{
7052 MarkerDeleteAll(MARKER_DUPLICATEINDICATOR_ONE);
7053 MarkerDeleteAll(MARKER_DUPLICATEINDICATOR_TWO);
7054
7055 SetIndicatorCurrent(HIGHLIGHT_DIFFERENCES);
7056 IndicatorClearRange(0, GetLastPosition());
7057
7058 SetIndicatorCurrent(HIGHLIGHT_DIFFERENCE_SOURCE);
7059 IndicatorClearRange(0, GetLastPosition());
7060
7061 if (nStart1 == -1 && nStart2 == -1 && nEnd1 == -1 && nEnd2 == -1)
7062 return;
7063
7064 // Mark section 1
7065 for (int i = nStart1; i <= nEnd1; i++)
7066 MarkerAdd(i, MARKER_DUPLICATEINDICATOR_ONE);
7067
7068 // Mark section 2
7069 for (int i = nStart2; i <= nEnd2; i++)
7070 MarkerAdd(i, MARKER_DUPLICATEINDICATOR_TWO);
7071
7072 // Determine the wordwise differences
7073 map<int, int> mDifferences = getDifferences(nStart1, nEnd1, nStart2, nEnd2);
7074
7075 // Mark the wordwise differences
7076 for (auto iter = mDifferences.begin(); iter != mDifferences.end(); ++iter)
7077 {
7078 if ((iter->first) < 0)
7079 SetIndicatorCurrent(HIGHLIGHT_DIFFERENCE_SOURCE);
7080 else
7081 SetIndicatorCurrent(HIGHLIGHT_DIFFERENCES);
7082
7083 IndicatorFillRange(abs(iter->first), iter->second);
7084 }
7085
7086 ScrollToLine(nSelectionLine);
7087}
7088
7089
7090static bool isEqualIgnoreWhitespace(wxString word1, wxString word2)
7091{
7092 word1.Trim();
7093 word2.Trim();
7094
7095 return word2.Trim(false) == word1.Trim(false);
7096}
7097
7098
7109int NumeReEditor::isBlockStart(const wxString& sWord, bool allowIntermediate)
7110{
7112 {
7113 int id = getBlockID(sWord);
7114
7115 if (id != wxNOT_FOUND)
7116 {
7117 if (isEqualIgnoreWhitespace(vBlockDefs[id].startWord, sWord)
7118 || (allowIntermediate && (isEqualIgnoreWhitespace(sWord, vBlockDefs[id].middleWord1) || isEqualIgnoreWhitespace(sWord, vBlockDefs[id].middleWord2))))
7119 return id;
7120 }
7121 }
7122 else if (m_fileType == FILE_MATLAB)
7123 return (sWord == "if"
7124 || sWord == "for"
7125 || sWord == "do"
7126 || sWord == "while"
7127 || sWord == "classdef"
7128 || sWord == "properties"
7129 || sWord == "function"
7130 || sWord == "methods"
7131 || sWord == "try"
7132 || sWord == "switch"
7133 || (allowIntermediate && (sWord == "elseif"
7134 || sWord == "else"
7135 || sWord == "case"
7136 || sWord == "otherwise"
7137 || sWord == "catch"))) ? 1 : wxNOT_FOUND;
7138
7139 return wxNOT_FOUND;
7140}
7141
7142
7152int NumeReEditor::isBlockEnd(const wxString& sWord)
7153{
7155 {
7156 int id = getBlockID(sWord);
7157
7158 if (id != wxNOT_FOUND)
7159 {
7160 if (isEqualIgnoreWhitespace(vBlockDefs[id].endWord, sWord))
7161 return id;
7162 }
7163 }
7164 else if (m_fileType == FILE_MATLAB)
7165 return sWord == "end" ? 1 : wxNOT_FOUND;
7166
7167 return wxNOT_FOUND;
7168}
7169
7170
7180int NumeReEditor::isBlockMiddle(const wxString& sWord)
7181{
7183 {
7184 int id = getBlockID(sWord);
7185
7186 if (id != wxNOT_FOUND
7187 && (isEqualIgnoreWhitespace(vBlockDefs[id].middleWord1, sWord) || isEqualIgnoreWhitespace(vBlockDefs[id].middleWord2, sWord)))
7188 return id;
7189 }
7190 else if (m_fileType == FILE_MATLAB)
7191 return (sWord == "elseif" || sWord == "else" || sWord == "case" || sWord == "otherwise" || sWord == "catch") ? 1 : wxNOT_FOUND;
7192
7193 return wxNOT_FOUND;
7194}
7195
7196
7205bool NumeReEditor::hasBlockMiddle(const wxString& sWord)
7206{
7208 {
7209 int id = getBlockID(sWord);
7210
7211 if (id != wxNOT_FOUND && vBlockDefs[id].middleWord1.length())
7212 return true;
7213 }
7214 else if (m_fileType == FILE_MATLAB)
7215 return sWord == "if"
7216 || sWord == "try"
7217 || sWord == "switch"
7218 || sWord == "elseif"
7219 || sWord == "else"
7220 || sWord == "case"
7221 || sWord == "otherwise"
7222 || sWord == "catch";
7223
7224 return false;
7225}
7226
7227
7235int NumeReEditor::getBlockID(const wxString& word)
7236{
7238 {
7239 if (!word.length())
7240 return wxNOT_FOUND;
7241
7242 for (size_t i = 0; i < vBlockDefs.size(); i++)
7243 {
7244 if (isEqualIgnoreWhitespace(vBlockDefs[i].startWord, word)
7245 || isEqualIgnoreWhitespace(vBlockDefs[i].middleWord1, word)
7246 || isEqualIgnoreWhitespace(vBlockDefs[i].middleWord2, word)
7247 || isEqualIgnoreWhitespace(vBlockDefs[i].endWord, word))
7248 return i;
7249 }
7250 }
7251 else if (m_fileType == FILE_MATLAB)
7252 return word == "if"
7253 || word == "for"
7254 || word == "while"
7255 || word == "classdef"
7256 || word == "properties"
7257 || word == "function"
7258 || word == "methods"
7259 || word == "try"
7260 || word == "switch"
7261 || word == "end"
7262 || word == "elseif"
7263 || word == "else"
7264 || word == "case"
7265 || word == "otherwise"
7266 || word == "catch";
7267
7268 return wxNOT_FOUND;
7269}
7270
7271
7281wxString NumeReEditor::getBlockAutoCompletion(const wxString& sWord)
7282{
7284 {
7285 if (sWord == "layout" || sWord == "compose" || sWord == "group")
7286 return sWord + " |\r\n" + getBlockEnd(sWord);
7287 else if (sWord == "try")
7288 return sWord + "|\r\n" + getBlockEnd(sWord); // Had to remove first "\r\n" due to a lack in the insertion algorithm
7289 else if (sWord == "procedure")
7290 return sWord + " $|()\r\nendprocedure";
7291 else if (sWord == "else")
7292 return sWord + "|";
7293 else if (sWord == "elseif")
7294 return sWord + " (|)";
7295 else if (sWord == "case" || sWord == "catch")
7296 return sWord + " |:";
7297 else if (sWord == "default")
7298 return sWord + ":|";
7299 else
7300 return sWord + " (|)\r\n" + getBlockEnd(sWord);
7301 }
7302 else if (m_fileType == FILE_MATLAB)
7303 {
7304 if (sWord == "else" || sWord == "otherwise")
7305 return sWord + "|";
7306 else if (sWord == "elseif" || sWord == "case" || sWord == "catch")
7307 return sWord + " |";
7308 else
7309 return sWord + " |\r\n" + getBlockEnd(sWord);
7310 }
7311
7312 return "";
7313}
7314
7324wxString NumeReEditor::getBlockEnd(const wxString& sWord)
7325{
7326 if (m_fileType == FILE_MATLAB)
7327 return "end";
7328
7329 int id = isBlockStart(sWord, true);
7330
7331 if (id != wxNOT_FOUND)
7332 return vBlockDefs[id].endWord;
7333
7334 return "";
7335}
7336
7337
7347wxString NumeReEditor::getBlockStart(const wxString& sWord)
7348{
7349 if (m_fileType == FILE_MATLAB)
7350 return "";
7351
7352 int id = getBlockID(sWord);
7353
7354 if (id != wxNOT_FOUND && !isEqualIgnoreWhitespace(sWord, vBlockDefs[id].startWord))
7355 return vBlockDefs[id].startWord;
7356
7357 return "";
7358}
7359
7360
7369{
7370 if (!m_dblclkString.length())
7371 return;
7372
7373 m_dblclkString.clear();
7374
7375 SetIndicatorCurrent(HIGHLIGHT_DBLCLK);
7376 long int maxpos = GetLastPosition();
7377 IndicatorClearRange(0, maxpos);
7378}
7379
7380
7392void NumeReEditor::OnMarginClick( wxStyledTextEvent& event )
7393{
7394 bool bCanUseBreakPoints = m_fileType == FILE_NSCR || m_fileType == FILE_NPRC;
7395 int position = event.GetPosition();
7396 int linenum = LineFromPosition(position);
7397
7398 if (event.GetMargin() == MARGIN_FOLD)
7399 {
7400 // Folding logic
7401 int levelClick = GetFoldLevel(linenum);
7402
7403 if ((levelClick & wxSTC_FOLDLEVELHEADERFLAG) > 0)
7404 ToggleFold(linenum);
7405 }
7406 else
7407 {
7408 // All other markers
7409 if (MarkerOnLine(linenum, MARKER_HIDDEN))
7410 {
7411 // Hidden lines
7412 int nNextVisibleLine = linenum+1;
7413
7414 while (!GetLineVisible(nNextVisibleLine))
7415 nNextVisibleLine++;
7416
7417 ShowLines(linenum, nNextVisibleLine);
7418
7419 for (int i = linenum; i < nNextVisibleLine; i++)
7420 {
7421 MarkerDelete(i, MARKER_HIDDEN);
7422 MarkerDelete(i, MARKER_HIDDEN_MARGIN);
7423 }
7424
7425 }
7426 else if (MarkerOnLine(linenum, MARKER_BREAKPOINT) && bCanUseBreakPoints)
7427 {
7428 // Breakpoint
7429 RemoveBreakpoint(linenum);
7430 }
7431 else if (bCanUseBreakPoints)
7432 {
7433 // Add breakpoint
7434 AddBreakpoint(linenum);
7435 }
7436 }
7437}
7438
7439
7451{
7452 // Go through the line and ensure that this
7453 // line actually contains executable code
7454 for (int i = PositionFromLine(linenum); i < GetLineEndPosition(linenum); i++)
7455 {
7456 // Check the current character
7461 && GetCharAt(i) != '\r'
7462 && GetCharAt(i) != '\n'
7463 && GetCharAt(i) != ' '
7464 && GetCharAt(i) != '\t')
7465 {
7466 // Add the breakpoint marker
7467 int markerNum = MarkerAdd(linenum, MARKER_BREAKPOINT);
7468
7469 // Add the breakpoint to the internal
7470 // logic
7471 m_breakpoints.Add(markerNum);
7472 m_terminal->addBreakpoint(GetFileNameAndPath().ToStdString(), linenum);
7473 break;
7474 }
7475 }
7476}
7477
7478
7488{
7489 // need to remove the marker handle from the array - use
7490 // LineFromHandle on debug start and clean up then
7491 MarkerDelete(linenum, MARKER_BREAKPOINT);
7492 m_terminal->removeBreakpoint(GetFileNameAndPath().ToStdString(), linenum);
7493}
7494
7495
7507{
7508 // Clear all breakpoints stored internally
7510 int line = 0;
7511
7512 // Re-set the existing breakpoints
7513 while ((line = MarkerNext(line, 1 << MARKER_BREAKPOINT)) != -1)
7514 {
7515 m_terminal->addBreakpoint(GetFileNameAndPath().ToStdString(), line);
7516 line++;
7517 }
7518}
7519
7520
7530{
7531 if (getFileType() != FILE_NPRC)
7532 return;
7533
7534 // Find the possible start position of the current procedure
7535 int nProcedureHeadPosition = m_search->FindCurrentProcedureHead(GetLineEndPosition(GetCurrentLine()));
7536
7537 // Ensure that the cursor is in the line of the procedure's
7538 // head
7539 if (LineFromPosition(nProcedureHeadPosition) != GetCurrentLine())
7540 return;
7541
7542 string sProcedureName = m_search->FindMarkedProcedure(nProcedureHeadPosition + 11, false).ToStdString();
7543 sProcedureName.erase(sProcedureName.find('('));
7544 replaceAll(sProcedureName, "_", "\\_");
7545
7546 string sDocumentation = "##! \\procedure " + sProcedureName.substr(1) + "\r\n##! [Procedure description]";
7547
7548 // Get the argument list
7549 string sFunctionArgumentList = getFunctionArgumentList(LineFromPosition(nProcedureHeadPosition)).ToStdString();
7550
7551 if (sFunctionArgumentList.length())
7552 sDocumentation += "\r\n##!";
7553
7554 // Separate the argument list and prepare the template
7555 while (sFunctionArgumentList.length())
7556 {
7557 string sCurArg = getNextArgument(sFunctionArgumentList, true);
7558 string sDefault;
7559
7560 // Remove default arguments from the list and store them separately
7561 if (sCurArg.find('=') != string::npos)
7562 {
7563 sDefault = sCurArg.substr(sCurArg.find_first_not_of(" =\t", sCurArg.find('=')));
7564 sCurArg.erase(sCurArg.find_last_not_of(" =", sCurArg.find('='))+1);
7565 }
7566
7567 sDocumentation += "\r\n##! \\param " + sCurArg + " ";
7568
7569 // Append default parameters, if they are available
7570 if (sDefault.length())
7571 sDocumentation += "(!!=" + sDefault + "!!) ";
7572
7573 sDocumentation += "[Parameter description]";
7574 }
7575
7576 // Insert the text before the procedure head
7577 InsertText(nProcedureHeadPosition, sDocumentation + "\r\n");
7578}
7579
7580
7590bool NumeReEditor::MarkerOnLine(int linenum, int nMarker)
7591{
7592 int markerLineBitmask = this->MarkerGet(linenum);
7593 return (markerLineBitmask & (1 << nMarker));
7594}
7595
7596
7604wxThread::ExitCode NumeReEditor::Entry()
7605{
7606 vDuplicateCodeResults.clear();
7607
7608 // Create the memory for the parsed line
7609 // This is done before the processing to avoid reallocs during the process
7610 vParsedSemanticCode.resize(m_nLastLine + 1);
7611
7612 double dMatch = 0.0;
7613 int nLongestMatch = 0;
7614 int nBlankLines = 0;
7615 int nLastStatusVal = 0;
7616 int currentDuplicateCodeLength = m_nDuplicateCodeLines;
7617
7618 if (getFileType() == FILE_CPP)
7619 currentDuplicateCodeLength *= 2;
7620
7621 // Go through the selected code
7622 for (int i = m_nFirstLine; i <= m_nLastLine - currentDuplicateCodeLength; i++)
7623 {
7624 if (GetThread()->TestDestroy())
7625 break;
7626
7627 if (m_duplicateCode && m_duplicateCode->IsShown())
7628 {
7629 // display some status value
7630 if ((int)((double)i / (double)(m_nLastLine - currentDuplicateCodeLength - m_nFirstLine) * 100) != nLastStatusVal)
7631 {
7632 nLastStatusVal = (double)i / (double)(m_nLastLine - currentDuplicateCodeLength - m_nFirstLine) * 100;
7633 wxCriticalSectionLocker lock(m_editorCS);
7634 m_nProcessValue = nLastStatusVal;
7635 wxQueueEvent(GetEventHandler(), new wxThreadEvent());
7636 }
7637 }
7638 else
7639 {
7640 // Stop this processing, if the duplicate code window was closed
7641 break;
7642 }
7643
7644 // Search for all possible duplications in the remaining document.
7645 // We don't have to search before the current line, because we would
7646 // have found this duplication earlier.
7647 for (int j = i + currentDuplicateCodeLength; j <= m_nLastLine - currentDuplicateCodeLength; j++)
7648 {
7649 dMatch = compareCodeLines(i, j, m_nDuplicateCodeFlag);
7650
7651 // The match should be at least 75%
7652 if (dMatch >= 0.75)
7653 {
7654 double dComp;
7655
7656 // Search the following code lines for a continuation
7657 // of the current match
7658 for (int k = 1; k <= m_nLastLine - j; k++)
7659 {
7660 dComp = compareCodeLines(i + k, j + k, m_nDuplicateCodeFlag);
7661
7662 if (dComp == -1.0)
7663 {
7664 nBlankLines++;
7665 continue;
7666 }
7667 else if (dComp < 0.75 || i + k == j)
7668 {
7669 // Was the last line of the duplication. Is it long
7670 // enough?
7671 if (k - nBlankLines > currentDuplicateCodeLength)
7672 {
7673 // Add the current duplication to the buffer
7674 wxCriticalSectionLocker lock(m_editorCS);
7675 vDuplicateCodeResults.push_back(toString(i + 1) + "-" + toString(i + k) + " == " + toString(j + 1) + "-" + toString(j + k) + " [" + toString(dMatch * 100.0 / (double)(k - nBlankLines), 3) + " %]");
7676 if (nLongestMatch < k - 1 - nBlankLines)
7677 nLongestMatch = k - 1 - nBlankLines;
7678 }
7679
7680 break;
7681 }
7682 else
7683 dMatch += dComp;
7684 }
7685
7686 nBlankLines = 0;
7687 }
7688 else if (dMatch < 0.0) // empty line at pos i
7689 break;
7690 }
7691
7692 i += nLongestMatch;
7693 nLongestMatch = 0;
7694 }
7695
7696 // clear the parsed code
7697 vParsedSemanticCode.clear();
7698
7699 wxCriticalSectionLocker lock(m_editorCS);
7700 m_nProcessValue = 100;
7701 wxQueueEvent(GetEventHandler(), new wxThreadEvent());
7702 return (wxThread::ExitCode)0;
7703}
7704
7705
7720void NumeReEditor::detectCodeDuplicates(int startline, int endline, int nDuplicateFlags, int nNumDuplicatedLines)
7721{
7722 m_nDuplicateCodeFlag = nDuplicateFlags;
7723 m_nFirstLine = startline;
7724 m_nLastLine = endline;
7725 m_nDuplicateCodeLines = nNumDuplicatedLines;
7726
7727 if (CreateThread(wxTHREAD_DETACHED) != wxTHREAD_NO_ERROR)
7728 return;
7729
7730 if (GetThread()->Run() != wxTHREAD_NO_ERROR)
7731 return;
7732}
7733
7734
7751double NumeReEditor::compareCodeLines(int nLine1, int nLine2, int nDuplicateFlags)
7752{
7753 size_t nMatchedCount = 0;
7754
7755 // Get the code lines transformed into semantic
7756 // code
7757 string sSemLine1 = this->getSemanticLine(nLine1, nDuplicateFlags);
7758 string sSemLine2 = this->getSemanticLine(nLine2, nDuplicateFlags);
7759
7760 // It is possible that the lines are semantical identical although they may contain different vars
7761 if (!sSemLine1.length() && sSemLine2.length())
7762 return -2.0;
7763 else if (!sSemLine1.length() && !sSemLine2.length())
7764 return -1.0;
7765 else if (sSemLine1.length() * 1.5 < sSemLine2.length() || sSemLine1.length() > sSemLine2.length() * 1.5)
7766 return 0.0;
7767
7768 // Check the actual match of the semantic code
7769 for (size_t i = 0; i < sSemLine1.length(); i++)
7770 {
7771 if (i >= sSemLine2.length())
7772 break;
7773
7774 if (sSemLine1[i] == sSemLine2[i])
7775 nMatchedCount++;
7776 }
7777
7778 return (double)nMatchedCount / (double)max(sSemLine1.length(), sSemLine2.length());
7779}
7780
7781
7794string NumeReEditor::getSemanticLine(int nLine, int nDuplicateFlags)
7795{
7796 if (vParsedSemanticCode[nLine].length())
7797 return vParsedSemanticCode[nLine];
7798
7799 // Use the correct parser for the current language
7800 if (getFileType() == FILE_NSCR || getFileType() == FILE_NPRC)
7801 return getSemanticLineNSCR(nLine, nDuplicateFlags);
7802 else if (getFileType() == FILE_MATLAB)
7803 return getSemanticLineMATLAB(nLine, nDuplicateFlags);
7804 else if (getFileType() == FILE_CPP)
7805 return getSemanticLineCPP(nLine, nDuplicateFlags);
7806 else
7807 return "";
7808}
7809
7810
7827string NumeReEditor::getSemanticLineNSCR(int nLine, int nDuplicateFlags)
7828{
7829 string sSemLine = "";
7830
7831 for (int i = this->PositionFromLine(nLine); i < this->GetLineEndPosition(nLine); i++)
7832 {
7833 if (this->GetCharAt(i) == ' '
7834 || this->GetCharAt(i) == '\t'
7835 || this->GetCharAt(i) == '\r'
7836 || this->GetCharAt(i) == '\n'
7839 continue;
7840 else if ((nDuplicateFlags & SEMANTICS_VAR)
7841 && (this->GetStyleAt(i) == wxSTC_NSCR_DEFAULT
7842 || this->GetStyleAt(i) == wxSTC_NSCR_DEFAULT_VARS
7843 || this->GetStyleAt(i) == wxSTC_NSCR_IDENTIFIER))
7844 {
7845 // replace vars with a placeholder
7846 i = this->WordEndPosition(i, true) - 1;
7847
7848 while (this->GetStyleAt(i + 1) == wxSTC_NSCR_DEFAULT
7849 || this->GetStyleAt(i + 1) == wxSTC_NSCR_DEFAULT_VARS
7850 || this->GetStyleAt(i + 1) == wxSTC_NSCR_IDENTIFIER)
7851 i++;
7852
7853 sSemLine += "VAR";
7854 }
7855 else if ((nDuplicateFlags & SEMANTICS_STRING) && this->GetStyleAt(i) == wxSTC_NSCR_STRING)
7856 {
7857 // replace string literals with a placeholder
7858 i++;
7859
7860 while (this->GetStyleAt(i + 1) == wxSTC_NSCR_STRING)
7861 i++;
7862
7863 sSemLine += "STR";
7864 }
7865 else if ((nDuplicateFlags & SEMANTICS_NUM) && this->GetStyleAt(i) == wxSTC_NSCR_NUMBERS)
7866 {
7867 // replace numeric literals with a placeholder
7868 while (this->GetStyleAt(i + 1) == wxSTC_NSCR_NUMBERS)
7869 i++;
7870
7871 if (sSemLine.back() == '-' || sSemLine.back() == '+')
7872 {
7873 if (sSemLine.length() == 1)
7874 sSemLine.clear();
7875 else
7876 {
7877 char cDelim = sSemLine[sSemLine.length() - 2];
7878
7879 if (cDelim == ':' || cDelim == '=' || cDelim == '?' || cDelim == ',' || cDelim == ';' || cDelim == '(' || cDelim == '[' || cDelim == '{')
7880 sSemLine.pop_back();
7881 }
7882 }
7883
7884 sSemLine += "NUM";
7885 }
7886 else if ((nDuplicateFlags & SEMANTICS_FUNCTION) && this->GetStyleAt(i) == wxSTC_NSCR_CUSTOM_FUNCTION)
7887 {
7888 // replace functions and caches with a placeholder
7889 while (this->GetStyleAt(i + 1) == wxSTC_NSCR_CUSTOM_FUNCTION)
7890 i++;
7891
7892 sSemLine += "FUNC";
7893 }
7894 else
7895 sSemLine += this->GetCharAt(i);
7896
7897 }
7898
7899 // Store the result to avoid repeated processing of this line
7900 vParsedSemanticCode[nLine] = sSemLine;
7901 return sSemLine;
7902}
7903
7904
7921string NumeReEditor::getSemanticLineMATLAB(int nLine, int nDuplicateFlags)
7922{
7923 string sSemLine = "";
7924
7925 for (int i = this->PositionFromLine(nLine); i < this->GetLineEndPosition(nLine); i++)
7926 {
7927 if (this->GetCharAt(i) == ' '
7928 || this->GetCharAt(i) == '\t'
7929 || this->GetCharAt(i) == '\r'
7930 || this->GetCharAt(i) == '\n'
7931 || this->GetStyleAt(i) == wxSTC_MATLAB_COMMENT)
7932 continue;
7933 else if ((nDuplicateFlags & SEMANTICS_VAR)
7934 && (this->GetStyleAt(i) == wxSTC_MATLAB_DEFAULT
7935 || this->GetStyleAt(i) == wxSTC_MATLAB_IDENTIFIER))
7936 {
7937 // replace vars with a placeholder
7938 i = this->WordEndPosition(i, true) - 1;
7939
7940 while (this->GetStyleAt(i + 1) == wxSTC_MATLAB_DEFAULT
7941 || this->GetStyleAt(i + 1) == wxSTC_MATLAB_IDENTIFIER)
7942 i++;
7943
7944 sSemLine += "VAR";
7945 }
7946 else if ((nDuplicateFlags & SEMANTICS_STRING) && this->GetStyleAt(i) == wxSTC_MATLAB_STRING)
7947 {
7948 // replace string literals with a placeholder
7949 i++;
7950
7951 while (this->GetStyleAt(i + 1) == wxSTC_MATLAB_STRING)
7952 i++;
7953
7954 sSemLine += "STR";
7955 }
7956 else if ((nDuplicateFlags & SEMANTICS_NUM) && this->GetStyleAt(i) == wxSTC_MATLAB_NUMBER)
7957 {
7958 // replace numeric literals with a placeholder
7959 while (this->GetStyleAt(i + 1) == wxSTC_MATLAB_NUMBER)
7960 i++;
7961
7962 if (sSemLine.back() == '-' || sSemLine.back() == '+')
7963 {
7964 if (sSemLine.length() == 1)
7965 sSemLine.clear();
7966 else
7967 {
7968 char cDelim = sSemLine[sSemLine.length() - 2];
7969
7970 if (cDelim == ':' || cDelim == '=' || cDelim == '?' || cDelim == ',' || cDelim == ';' || cDelim == '(' || cDelim == '[' || cDelim == '{')
7971 sSemLine.pop_back();
7972 }
7973 }
7974
7975 sSemLine += "NUM";
7976 }
7977 else
7978 sSemLine += this->GetCharAt(i);
7979
7980 }
7981
7982 // Store the result to avoid repeated processing of this line
7983 vParsedSemanticCode[nLine] = sSemLine;
7984 return sSemLine;
7985}
7986
7987
8004string NumeReEditor::getSemanticLineCPP(int nLine, int nDuplicateFlags)
8005{
8006 string sSemLine = "";
8007
8008 for (int i = this->PositionFromLine(nLine); i < this->GetLineEndPosition(nLine); i++)
8009 {
8010 if (this->GetCharAt(i) == ' '
8011 || this->GetCharAt(i) == '\t'
8012 || this->GetCharAt(i) == '\r'
8013 || this->GetCharAt(i) == '\n'
8015 continue;
8016 else if ((nDuplicateFlags & SEMANTICS_VAR)
8017 && (this->GetStyleAt(i) == wxSTC_C_DEFAULT
8018 || this->GetStyleAt(i) == wxSTC_C_IDENTIFIER))
8019 {
8020 // replace vars with a placeholder
8021 i = this->WordEndPosition(i, true) - 1;
8022
8023 while (this->GetStyleAt(i + 1) == wxSTC_C_DEFAULT
8024 || this->GetStyleAt(i + 1) == wxSTC_C_IDENTIFIER)
8025 i++;
8026
8027 sSemLine += "VAR";
8028 }
8029 else if ((nDuplicateFlags & SEMANTICS_STRING) && (this->GetStyleAt(i) == wxSTC_C_STRING || this->GetStyleAt(i) == wxSTC_C_CHARACTER))
8030 {
8031 // replace string literals with a placeholder
8032 i++;
8033
8034 while (this->GetStyleAt(i + 1) == wxSTC_C_STRING || this->GetStyleAt(i + 1) == wxSTC_C_CHARACTER)
8035 i++;
8036
8037 sSemLine += "STR";
8038 }
8039 else if ((nDuplicateFlags & SEMANTICS_NUM) && this->GetStyleAt(i) == wxSTC_C_NUMBER)
8040 {
8041 // replace numeric literals with a placeholder
8042 while (this->GetStyleAt(i + 1) == wxSTC_C_NUMBER)
8043 i++;
8044
8045 if (sSemLine.back() == '-' || sSemLine.back() == '+')
8046 {
8047 if (sSemLine.length() == 1)
8048 sSemLine.clear();
8049 else
8050 {
8051 char cDelim = sSemLine[sSemLine.length() - 2];
8052
8053 if (cDelim == ':' || cDelim == '=' || cDelim == '?' || cDelim == ',' || cDelim == ';' || cDelim == '(' || cDelim == '[' || cDelim == '{')
8054 sSemLine.pop_back();
8055 }
8056 }
8057
8058 sSemLine += "NUM";
8059 }
8060 else
8061 sSemLine += this->GetCharAt(i);
8062
8063 }
8064
8065 // Store the result to avoid repeated processing of this line
8066 vParsedSemanticCode[nLine] = sSemLine;
8067 return sSemLine;
8068}
8069
8070
8087map<int, int> NumeReEditor::getDifferences(int nStart1, int nEnd1, int nStart2, int nEnd2)
8088{
8089 map<int, int> mDifferences;
8090 int nLinePos1 = 0;
8091 int nLinePos2 = 0;
8092 wxString sToken1;
8093 wxString sToken2;
8094
8095 // Compare every line in the selected range
8096 for (int i = 0; i <= nEnd1 - nStart1; i++)
8097 {
8098 nLinePos1 = this->PositionFromLine(nStart1 + i);
8099 nLinePos2 = this->PositionFromLine(nStart2 + i);
8100
8101 // Read every token from the lines and compare them
8102 while (nLinePos1 < this->GetLineEndPosition(nStart1 + i) || nLinePos2 < this->GetLineEndPosition(nStart2 + i))
8103 {
8104 sToken1 = getNextToken(nLinePos1);
8105 sToken2 = getNextToken(nLinePos2);
8106
8107 // Break, if no tokens are available
8108 if (!sToken1.length() && !sToken2.length())
8109 break;
8110
8111 // Compare the tokens
8112 if (sToken1.length() && !sToken2.length())
8113 mDifferences[-nLinePos1] = sToken1.length();
8114 else if (sToken2.length() && !sToken1.length())
8115 mDifferences[nLinePos2] = sToken2.length();
8116 else
8117 {
8118 if (sToken1 != sToken2)
8119 {
8120 mDifferences[-nLinePos1] = sToken1.length();
8121 mDifferences[nLinePos2] = sToken2.length();
8122 }
8123 }
8124
8125 // Increment the search position
8126 nLinePos1 += sToken1.length();
8127 nLinePos2 += sToken2.length();
8128
8129 if (nLinePos1 > this->GetLineEndPosition(nStart1 + i))
8130 nLinePos1 = this->GetLineEndPosition(nStart1 + i);
8131
8132 if (nLinePos2 > this->GetLineEndPosition(nStart2 + i))
8133 nLinePos2 = this->GetLineEndPosition(nStart2 + i);
8134 }
8135 }
8136
8137 return mDifferences;
8138}
8139
8140
8150{
8151 int nCurrentLineEnd = this->GetLineEndPosition(this->LineFromPosition(nPos));
8152
8153 // return nothing, if already at line end
8154 if (nPos >= nCurrentLineEnd)
8155 return "";
8156
8157 int nCurrentStyle;
8158 int nEndPos;
8159
8160 // forward over all whitespace characters
8161 while (this->GetCharAt(nPos) == ' '
8162 || this->GetCharAt(nPos) == '\t'
8163 || this->GetCharAt(nPos) == '\r'
8164 || this->GetCharAt(nPos) == '\n')
8165 nPos++;
8166
8167 // return nothing, if already at line end (set position to line end)
8168 if (nPos >= nCurrentLineEnd)
8169 {
8170 nPos = nCurrentLineEnd;
8171 return "";
8172 }
8173
8174 // get the current style
8175 nCurrentStyle = this->GetStyleAt(nPos);
8176 nEndPos = nPos;
8177
8178 // while the style is identical forward the end position
8179 while (this->GetStyleAt(nEndPos) == nCurrentStyle)
8180 nEndPos++;
8181
8182 // it is possible that we walked over the last position
8183 if (nEndPos > nCurrentLineEnd)
8184 return this->GetTextRange(nPos, nCurrentLineEnd);
8185
8186 return this->GetTextRange(nPos, nEndPos);
8187}
8188
8189
8199std::pair<int,int> NumeReEditor::getCurrentContext(int line)
8200{
8201 if (m_fileType != FILE_NPRC
8203 && m_fileType != FILE_CPP)
8204 return std::make_pair(0, GetLineCount());
8205
8206 // Try to find the current procedure header
8207 while (GetFoldParent(line) != wxNOT_FOUND)
8208 {
8209 line = GetFoldParent(line);
8210 }
8211
8212 // Try to find the procedure foot
8213 std::vector<int> vMatch = BlockMatch(GetLineIndentPosition(line));
8214
8215 if (vMatch.back() == wxNOT_FOUND)
8216 return std::make_pair(line, GetLineCount());
8217
8218 return std::make_pair(line, LineFromPosition(vMatch.back()));
8219}
8220
8221
8230void NumeReEditor::ApplyAutoIndentation(int nFirstLine, int nLastLine)
8231{
8232 m_formatter->IndentCode(nFirstLine, nLastLine);
8233}
8234
8235
8250{
8251 switch (getFileType())
8252 {
8253 case FILE_NSCR:
8254 case FILE_NPRC:
8255 {
8256 switch (_type)
8257 {
8258 case STYLE_DEFAULT:
8259 return GetStyleAt(nPos) == wxSTC_NSCR_DEFAULT;
8260 case STYLE_COMMENT:
8261 return GetStyleAt(nPos) == wxSTC_NSCR_COMMENT_LINE
8262 || GetStyleAt(nPos) == wxSTC_NSCR_DOCCOMMENT_LINE
8263 || GetStyleAt(nPos) == wxSTC_NSCR_COMMENT_BLOCK
8264 || GetStyleAt(nPos) == wxSTC_NSCR_DOCCOMMENT_BLOCK
8265 || GetStyleAt(nPos) == wxSTC_NSCR_DOCKEYWORD;
8266 case STYLE_COMMENT_LINE:
8267 return GetStyleAt(nPos) == wxSTC_NSCR_COMMENT_LINE
8268 || GetStyleAt(nPos) == wxSTC_NSCR_DOCCOMMENT_LINE;
8270 return GetStyleAt(nPos) == wxSTC_NSCR_COMMENT_BLOCK
8271 || GetStyleAt(nPos) == wxSTC_NSCR_DOCCOMMENT_BLOCK;
8273 return GetStyleAt(nPos) == wxSTC_NSCR_DOCCOMMENT_LINE
8274 || GetStyleAt(nPos) == wxSTC_NSCR_DOCKEYWORD;
8276 return GetStyleAt(nPos) == wxSTC_NSCR_DOCCOMMENT_BLOCK
8277 || GetStyleAt(nPos) == wxSTC_NSCR_DOCKEYWORD;
8278 case STYLE_COMMAND:
8279 return GetStyleAt(nPos) == wxSTC_NSCR_COMMAND
8280 || GetStyleAt(nPos) == wxSTC_NPRC_COMMAND;
8281 case STYLE_FUNCTION:
8282 return GetStyleAt(nPos) == wxSTC_NSCR_FUNCTION;
8284 return GetStyleAt(nPos) == wxSTC_NSCR_CUSTOM_FUNCTION;
8285 case STYLE_OPERATOR:
8286 return GetStyleAt(nPos) == wxSTC_NSCR_OPERATORS;
8287 case STYLE_PROCEDURE:
8288 return GetStyleAt(nPos) == wxSTC_NSCR_PROCEDURES;
8289 case STYLE_IDENTIFIER:
8290 return GetStyleAt(nPos) == wxSTC_NSCR_IDENTIFIER;
8291 case STYLE_DATAOBJECT:
8292 return GetStyleAt(nPos) == wxSTC_NSCR_CUSTOM_FUNCTION || GetStyleAt(nPos) == wxSTC_NSCR_CLUSTER;
8293 case STYLE_NUMBER:
8294 return GetStyleAt(nPos) == wxSTC_NSCR_NUMBERS;
8295 case STYLE_STRINGPARSER:
8296 return GetStyleAt(nPos) == wxSTC_NSCR_STRING_PARSER;
8297 case STYLE_STRING:
8298 return GetStyleAt(nPos) == wxSTC_NSCR_STRING;
8299 }
8300 break;
8301 }
8302 case FILE_MATLAB:
8303 {
8304 switch (_type)
8305 {
8306 case STYLE_DEFAULT:
8307 return GetStyleAt(nPos) == wxSTC_MATLAB_DEFAULT;
8308 case STYLE_COMMENT:
8309 case STYLE_COMMENT_LINE:
8311 return GetStyleAt(nPos) == wxSTC_MATLAB_COMMENT;
8313 return GetStyleAt(nPos) == wxSTC_MATLAB_COMMENT && GetTextRange(nPos, nPos + 2) == "%%";
8315 return GetStyleAt(nPos) == wxSTC_MATLAB_COMMENT && GetTextRange(nPos, nPos + 2) == "%%";
8316 case STYLE_COMMAND:
8317 return GetStyleAt(nPos) == wxSTC_MATLAB_KEYWORD;
8318 case STYLE_FUNCTION:
8319 return GetStyleAt(nPos) == wxSTC_MATLAB_FUNCTIONS;
8321 return false;
8322 case STYLE_OPERATOR:
8323 return GetStyleAt(nPos) == wxSTC_MATLAB_OPERATOR;
8324 case STYLE_PROCEDURE:
8325 return false;
8326 case STYLE_IDENTIFIER:
8327 return GetStyleAt(nPos) == wxSTC_MATLAB_IDENTIFIER;
8328 case STYLE_DATAOBJECT:
8329 return false;
8330 case STYLE_NUMBER:
8331 return GetStyleAt(nPos) == wxSTC_MATLAB_NUMBER;
8332 case STYLE_STRINGPARSER:
8333 return false;
8334 case STYLE_STRING:
8335 return GetStyleAt(nPos) == wxSTC_MATLAB_STRING;
8336 }
8337 break;
8338 }
8339 case FILE_CPP:
8340 {
8341 switch (_type)
8342 {
8343 case STYLE_DEFAULT:
8344 return GetStyleAt(nPos) == wxSTC_C_DEFAULT;
8345 case STYLE_COMMENT:
8346 return GetStyleAt(nPos) == wxSTC_C_COMMENTLINE
8347 || GetStyleAt(nPos) == wxSTC_C_COMMENT
8348 || GetStyleAt(nPos) == wxSTC_C_COMMENTDOC
8349 || GetStyleAt(nPos) == wxSTC_C_COMMENTLINEDOC
8350 || GetStyleAt(nPos) == wxSTC_C_COMMENTDOCKEYWORD;
8351 case STYLE_COMMENT_LINE:
8352 return GetStyleAt(nPos) == wxSTC_C_COMMENTLINE
8353 || GetStyleAt(nPos) == wxSTC_C_COMMENTLINEDOC;
8355 return GetStyleAt(nPos) == wxSTC_C_COMMENT
8356 || GetStyleAt(nPos) == wxSTC_C_COMMENTDOC;
8358 return GetStyleAt(nPos) == wxSTC_C_COMMENTLINEDOC
8359 || GetStyleAt(nPos) == wxSTC_C_COMMENTDOCKEYWORD;
8361 return GetStyleAt(nPos) == wxSTC_C_COMMENTDOC
8362 || GetStyleAt(nPos) == wxSTC_C_COMMENTDOCKEYWORD;
8363 case STYLE_COMMAND:
8364 return GetStyleAt(nPos) == wxSTC_C_WORD;
8365 case STYLE_FUNCTION:
8366 return GetStyleAt(nPos) == wxSTC_C_WORD2;
8368 return false;
8369 case STYLE_OPERATOR:
8370 return GetStyleAt(nPos) == wxSTC_C_OPERATOR;
8371 case STYLE_PROCEDURE:
8372 return false;
8373 case STYLE_IDENTIFIER:
8374 return GetStyleAt(nPos) == wxSTC_C_IDENTIFIER;
8375 case STYLE_DATAOBJECT:
8376 return false;
8377 case STYLE_NUMBER:
8378 return GetStyleAt(nPos) == wxSTC_C_NUMBER;
8379 case STYLE_STRINGPARSER:
8380 return false;
8381 case STYLE_STRING:
8382 return GetStyleAt(nPos) == wxSTC_C_STRING;
8383 }
8384 break;
8385 }
8386 default:
8387 return false;
8388 }
8389 return false;
8390}
8391
8392
8401int NumeReEditor::countUmlauts(const string& sStr)
8402{
8403 int nUmlauts = 0;
8404 for (size_t i = 0; i < sStr.length(); i++)
8405 {
8406 if (sStr[i] == 'Ä'
8407 || sStr[i] == 'ä'
8408 || sStr[i] == 'Ö'
8409 || sStr[i] == 'ö'
8410 || sStr[i] == 'Ü'
8411 || sStr[i] == 'ü'
8412 || sStr[i] == 'ß'
8413 || sStr[i] == '°'
8414 || sStr[i] == 'µ'
8415 || sStr[i] == (char)142
8416 || sStr[i] == (char)132
8417 || sStr[i] == (char)153
8418 || sStr[i] == (char)148
8419 || sStr[i] == (char)154
8420 || sStr[i] == (char)129
8421 || sStr[i] == (char)225
8422 || sStr[i] == (char)167
8423 || sStr[i] == (char)230
8424 )
8425 nUmlauts++;
8426 }
8427 return nUmlauts;
8428}
8429
8430
8440string NumeReEditor::realignLangString(string sLine, size_t& lastpos)
8441{
8442 lastpos = sLine.find(' ');
8443
8444 if (lastpos == string::npos)
8445 return sLine;
8446
8447 // Find the first non-whitespace character
8448 size_t firstpos = sLine.find_first_not_of(' ', lastpos);
8449
8450 // Insert separation characters between syntax element
8451 // and return values
8452 if (sLine.find(')') < lastpos || sLine.find('.') < lastpos)
8453 sLine.replace(lastpos, firstpos - lastpos, " -> ");
8454 else
8455 {
8456 if (sLine.find("- ") == firstpos)
8457 return sLine;
8458
8459 if (firstpos - lastpos > 2)
8460 {
8461 sLine.erase(lastpos, firstpos - lastpos - 2);
8462 sLine.insert(sLine.find("- "), firstpos - lastpos - 2, ' ');
8463 }
8464 }
8465
8466 return sLine;
8467}
8468
8469
8483string NumeReEditor::addLinebreaks(const string& sLine, bool onlyDocumentation /* = false*/)
8484{
8485 const unsigned int nMAXLINE = 100;
8486
8487 string sReturn = sLine;
8488
8489 // Remove escaped dollar signs
8490 while (sReturn.find("\\$") != string::npos)
8491 sReturn.erase(sReturn.find("\\$"), 1);
8492
8493 unsigned int nDescStart = sReturn.find("- ");
8494 unsigned int nIndentPos = 4;
8495 unsigned int nLastLineBreak = 0;
8496 bool isItemize = false;
8497
8498 // Handle the first indent depending on whether this is
8499 // only a documentation string or a whole definition
8500 if (onlyDocumentation)
8501 {
8502 nDescStart = 0;
8503 sReturn.insert(0, " ");
8504 }
8505 else
8506 sReturn.replace(nDescStart, 2, "\n ");
8507
8508 if (nDescStart == string::npos)
8509 return sLine;
8510
8511 nLastLineBreak = nDescStart;
8512
8513 for (unsigned int i = nDescStart; i < sReturn.length(); i++)
8514 {
8515 if (sReturn[i] == '\n')
8516 {
8517 nLastLineBreak = i;
8518
8519 if (sReturn.substr(i, 7) == "\n - ")
8520 isItemize = true;
8521 else
8522 isItemize = false;
8523 }
8524
8525 if ((i == nMAXLINE && !nLastLineBreak)
8526 || (nLastLineBreak && i - nLastLineBreak == nMAXLINE))
8527 {
8528 for (int j = i; j >= 0; j--)
8529 {
8530 if (sReturn[j] == ' ')
8531 {
8532 sReturn[j] = '\n';
8533 sReturn.insert(j + 1, nIndentPos + 2*isItemize, ' ');
8534 nLastLineBreak = j;
8535 break;
8536 }
8537 else if (sReturn[j] == '-' && j != (int)i)
8538 {
8539 // --> Minuszeichen: nicht immer ist das Trennen an dieser Stelle sinnvoll. Wir pruefen die einfachsten Faelle <--
8540 if (j &&
8541 (sReturn[j - 1] == ' '
8542 || sReturn[j - 1] == '('
8543 || sReturn[j + 1] == ')'
8544 || sReturn[j - 1] == '['
8545 || (sReturn[j + 1] >= '0' && sReturn[j + 1] <= '9')
8546 || sReturn[j + 1] == ','
8547 || (sReturn[j + 1] == '"' && sReturn[j - 1] == '"')
8548 ))
8549 continue;
8550
8551 sReturn.insert(j + 1, "\n");
8552 sReturn.insert(j + 2, nIndentPos + 2*isItemize, ' ');
8553 nLastLineBreak = j + 1;
8554 break;
8555 }
8556 else if (sReturn[j] == ',' && j != (int)i && sReturn[j + 1] != ' ')
8557 {
8558 sReturn.insert(j + 1, "\n");
8559 sReturn.insert(j + 2, nIndentPos + 2*isItemize, ' ');
8560 nLastLineBreak = j + 1;
8561 break;
8562 }
8563 }
8564 }
8565 }
8566
8567 return sReturn;
8568}
8569
8570
8579void NumeReEditor::ApplyAutoFormat(int nFirstLine, int nLastLine)
8580{
8581 m_formatter->FormatCode(nFirstLine, nLastLine);
8582}
8583
8584
8599void NumeReEditor::Transpose(int nFirstLine, int nLastLine)
8600{
8601 if (nFirstLine < 0)
8602 nFirstLine = 0;
8603
8604 if (nLastLine <= 0 || nLastLine > GetLineCount())
8605 nLastLine = GetLineCount()-1;
8606
8607 int nFirstPos = PositionFromLine(nFirstLine);
8608 int nLastPos = GetLineEndPosition(nLastLine);
8609 size_t maxLines = 0;
8610
8611 // Clear all selections
8612 if (HasSelection())
8613 ClearSelections();
8614
8615 std::vector<std::vector<wxString>> vTable;
8616 wxStringTokenizer tokenizer;
8617 wxString sDelimiter;
8618
8619 // Determine the delimiter characters
8620 if (GetFileName().GetExt() == "csv")
8621 {
8622 // For a CSV file, we will search for
8623 // some distinct combinations to determine,
8624 // whether a comma or a semicolon is used
8625 // as separator character
8626 wxString origSection = GetTextRange(nFirstPos, nLastPos);
8627
8628 if (origSection.find(';') != string::npos && origSection.find(',') != string::npos)
8629 sDelimiter = ";\r\n"; // Comma is decimal separator
8630 else if (origSection.find('.') != string::npos && origSection.find(',') != string::npos)
8631 sDelimiter = ",\r\n"; // dot is decimal separator
8632 else
8633 sDelimiter = ";,\r\n"; // Fallback: separate both
8634 }
8635 else
8636 sDelimiter = "\t \r\n";
8637
8638 // Tokenize the selected lines into a string table
8639 for (int i = nFirstLine; i <= nLastLine; i++)
8640 {
8641 vTable.push_back(std::vector<wxString>());
8642 tokenizer.SetString(GetLine(i), sDelimiter);
8643
8644 while (tokenizer.HasMoreTokens())
8645 vTable[i-nFirstLine].push_back(tokenizer.GetNextToken());
8646
8647 // Update the numbers of columns (will be lines),
8648 // if necessary
8649 if (vTable[i-nFirstLine].size() > maxLines)
8650 maxLines = vTable[i-nFirstLine].size();
8651 }
8652
8653 wxString finalLayout;
8654
8655 // Layout the transposed table
8656 for (size_t i = 0; i < maxLines; i++)
8657 {
8658 for (size_t j = 0; j < vTable.size(); j++)
8659 {
8660 if (vTable[j].size() > i)
8661 finalLayout += vTable[j][i];
8662
8663 if (j+1 < vTable.size())
8664 finalLayout += sDelimiter[0];
8665 }
8666
8667 if (i+1 < maxLines)
8668 finalLayout += "\r\n";
8669 }
8670
8671 // Replace the original section with the
8672 // transposed table
8673 Replace(nFirstPos, nLastPos, finalLayout);
8674}
8675
8676
8686wxString NumeReEditor::ExtractAsHTML(int nFirstLine, int nLastLine)
8687{
8688 wxString sHtml = "<pre style=\"display: block; overflow-x: auto; padding: 0.5em; background-color: rgb(244, 244, 244); color: rgb(0, 0, 0); font-family: consolas, monospace;\">";
8689
8690 if (nFirstLine < 0)
8691 nFirstLine = 0;
8692
8693 if (nLastLine <= 0 || nLastLine > GetLineCount())
8694 nLastLine = GetLineCount()-1;
8695
8696 int nFirstPos = PositionFromLine(nFirstLine);
8697 int nLastPos = GetLineEndPosition(nLastLine);
8698 int nLastStatePosition = nFirstPos;
8699 wxTextAttr textAttr;
8700
8701 for (int i = nFirstPos; i < nLastPos; i++)
8702 {
8703 if (GetStyleAt(i) != GetStyleAt(nLastStatePosition) || i+1 == nLastPos)
8704 {
8705 int style = GetStyleAt(nLastStatePosition);
8706 wxString textRange;
8707
8708 if (i+1 == nLastPos)
8709 textRange = GetTextRange(nLastStatePosition, i+1);
8710 else
8711 textRange = GetTextRange(nLastStatePosition, i);
8712
8713 // Replace less and greater characters with the
8714 // HTML entities
8715 textRange.Replace("<", "&lt;");
8716 textRange.Replace(">", "&gt;");
8717
8718 if (textRange.find_first_not_of(" \r\t\n") == std::string::npos)
8719 {
8720 sHtml += textRange;
8721 nLastStatePosition = i;
8722 continue;
8723 }
8724
8725 sHtml += "<span style=\"color: rgb(" + toString(StyleGetForeground(style).Red()) + ", " + toString(StyleGetForeground(style).Green()) + ", " + toString(StyleGetForeground(style).Blue()) + ");";
8726
8727 if (StyleGetBackground(style) != *wxWHITE)
8728 sHtml += " background-color: rgb(" + toString(StyleGetBackground(style).Red()) + ", " + toString(StyleGetBackground(style).Green()) + ", " + toString(StyleGetBackground(style).Blue()) + ");";
8729
8730 if (StyleGetItalic(style))
8731 sHtml += " font-style: italic;";
8732
8733 if (StyleGetBold(style))
8734 sHtml += " font-weight: bold;";
8735
8736 if (StyleGetUnderline(style))
8737 sHtml += " text-decoration: underline;";
8738
8739 sHtml += "\">" + textRange + "</span>";
8740 nLastStatePosition = i;
8741 }
8742 }
8743
8744 sHtml += "</pre>";
8745
8746 sHtml.Replace("\t", " ");
8747
8748 return sHtml;
8749}
8750
8751
std::string toLowerCase(const std::string &)
Converts uppercase to lowercase letters.
void run()
Starts the code analysis. Requires a pointer to the editor and to the options.
static void changeVariableType(std::string &sVarName, char type)
Change the variable's type to the passed type.
void IndentCode(int nFirstLine, int nLastLine)
Automatically indents the code based upon its hierarchy.
void FormatCode(int nFirstLine, int nLastLine)
Applies automatic formatting to the selected code lines.
void SetResult(const std::vector< std::string > &vResult)
void SetProgress(double dPercentage)
NumeRe::CallTipProvider * getProvider()
Definition: gterm.hpp:146
This class handles the internal language system and returns the language strings of the selected lang...
Definition: language.hpp:38
std::string getKey(const std::string &sMessage) const
This member function searches the internal language map for an identifier, which starts similar with ...
Definition: language.cpp:257
std::string get(const std::string &sMessage, const std::vector< std::string > &vTokens) const
This member function returns the language string for the passed language identifier and replaces all ...
Definition: language.cpp:292
This class uses a global Language instance to obtain the language string associated with a distinct c...
CallTip getOption(std::string sToken) const
Get the calltip for the selected option.
CallTip getConstant(std::string sToken) const
Get the calltip for the selected constant.
CallTip getMethod(std::string sToken) const
Get the calltip for the selected method.
CallTip getFunction(std::string sToken) const
Get the calltip for the selected (built-in) function.
CallTip getCommand(std::string sToken) const
Get the calltip for the selected command.
CallTip getPredef(std::string sToken) const
Get the calltip for the selected predefined symbol.
The class of the editor window.
Definition: editor.h:53
void sortSelection(bool ascending=true)
Sorts the lines de- or ascending.
Definition: editor.cpp:2425
void AddProcedureDocumentation()
This member function handles the creation of documentation blocks in front of procedure heads.
Definition: editor.cpp:7529
wxString getMatlabReturnList(int nMatlabFunctionStartLine)
Gets the return list of a MATLAB function.
Definition: editor.cpp:6314
void SynchronizeBreakpoints()
Synchronizes all breakpoints between editor and kernel.
Definition: editor.cpp:7506
int m_nLastReleasedKey
Definition: editor.h:430
void OnTranspose()
On MenuEvent handler for the transpose functionality of the editor.
Definition: editor.cpp:6871
bool SaveNumeReFile(const wxString &filename)
Saves a NumeRe-specific file and tries to stick to ASCII encoding.
Definition: editor.cpp:509
void SetEditorFont(const wxFont &font)
Changes the editor's font face.
Definition: editor.cpp:2802
wxMenu m_popupMenu
Definition: editor.h:449
void SetUnsaved()
Marks the editor as modified.
Definition: editor.cpp:3556
wxMenuItem * m_menuRefactoring
Definition: editor.h:414
void ToggleSettings(int _setting)
Enables or disables an editor setting.
Definition: editor.cpp:2835
std::string getSemanticLine(int nLine, int nDuplicateFlags)
Returns the selected line as semantic code.
Definition: editor.cpp:7794
wxArrayInt m_breakpoints
Definition: editor.h:403
void OnRightClick(wxMouseEvent &event)
Definition: editor.cpp:4391
void OnClearBreakpoints(wxCommandEvent &event)
Definition: editor.cpp:5219
std::string addLinebreaks(const std::string &sLine, bool onlyDocumentation=false)
Adds linebreaks to the call tip language strings.
Definition: editor.cpp:8483
std::string getSemanticLineMATLAB(int nLine, int nDuplicateFlags)
Returns the selected line as semantic code.
Definition: editor.cpp:7921
wxString getTemplateContent(const wxString &sFileName)
Returns the contents of a template file.
Definition: editor.cpp:6353
bool m_dragging
Definition: editor.h:440
void ApplyAutoIndentation(int nFirstLine=0, int nLastLine=-1)
Wrapper for CodeFormatter.
Definition: editor.cpp:8230
std::string m_sCallTipContent
Definition: editor.h:432
wxString GetFilePath()
Definition: editor.cpp:4342
int GetLineForMarkerOperation()
Gets the line belonging to the last right mouse click or the current line of the caret.
Definition: editor.cpp:5407
bool isStyleType(StyleType _type, int nPos)
Determine the syntax style type at the selected position.
Definition: editor.cpp:8249
void OnFindProcedure(wxCommandEvent &event)
Private event handler function for finding the procedure definition.
Definition: editor.cpp:6634
std::vector< int > BlockMatchMATLAB(int nPos)
Finds all matching flow control statements for MATLAB command syntax.
Definition: editor.cpp:3200
void registerProcedureViewer(ProcedureViewer *viewer)
Registers the passed procedure viewer.
Definition: editor.cpp:5326
void FindAndOpenProcedure(const wxString &procedurename)
Finds the procedure definition and displays it in the editor.
Definition: editor.cpp:5461
wxString getNextToken(int &nPos)
Returns the next syntax token starting from the selected position.
Definition: editor.cpp:8149
wxString GetFilenameString()
Definition: editor.cpp:4314
void Transpose(int nFirstLine=0, int nLastLine=-1)
This method transposes tabular data in between (including) starting and last line....
Definition: editor.cpp:8599
CodeFormatter * m_formatter
Definition: editor.h:394
bool LoadFileText(wxString fileContents)
Definition: editor.cpp:576
void OnMarginClick(wxStyledTextEvent &event)
Event handler called when clicking on the editor margin.
Definition: editor.cpp:7392
void markLocalVariableOfType(const wxString &command, bool bForceRefresh)
This method finds all local variables of the selected type and highlights their definitions.
Definition: editor.cpp:4833
wxString m_clickedInclude
Definition: editor.h:407
bool SaveFile(const wxString &filename)
Definition: editor.cpp:396
int getBlockID(const wxString &word)
This function returns the block ID.
Definition: editor.cpp:7235
int isBlockStart(const wxString &sWord, bool allowIntermediate=false)
This function returns true, if a passed word corresponds to a control flow statement block start.
Definition: editor.cpp:7109
wxString generateAutoCompList(int wordstartpos, int currpos, std::string sPreDefList)
Generates an autocompletion list based upon the file's contents.
Definition: editor.cpp:6426
bool InitDuplicateCode()
Displays the duplicated code dialog.
Definition: editor.cpp:6965
void ResetEditor()
Definition: editor.cpp:4356
void markModified(int nLine)
Marks the selected line as modified.
Definition: editor.cpp:4546
void OnRemoveBreakpoint(wxCommandEvent &event)
Definition: editor.cpp:5201
void getMatchingBrace(int nPos)
Finds and highlights the matching brace.
Definition: editor.cpp:2904
void notifyDialogClose()
Notifies the editor that the duplicated code dialog had been closed.
Definition: editor.cpp:2786
bool getEditorSetting(EditorSettings _setting)
Returns true, if the selected setting is active.
Definition: editor.cpp:2819
void OnChangeCase(wxCommandEvent &event)
Changes the letters in the selection.
Definition: editor.cpp:6702
SearchController * m_search
Definition: editor.h:393
wxString getBlockEnd(const wxString &sWord)
This member function returns the control flow statement block end, which corresponds to the passed wo...
Definition: editor.cpp:7324
void UpdateProcedureViewer()
Update the assigned procedure viewer.
Definition: editor.cpp:1079
virtual wxThread::ExitCode Entry()
Main thread loop for the duplicated code analysis.
Definition: editor.cpp:7604
void ClearDblClkIndicator()
Removes the double-click occurence indicators from the document.
Definition: editor.cpp:7368
bool Modified()
Returns whether the current file was modified after the last time saved.
Definition: editor.cpp:634
int m_nProcessValue
Definition: editor.h:425
void OnAbstrahizeSection(wxCommandEvent &event)
Private event handler for extracting the selected section.
Definition: editor.cpp:6820
void OnLeave(wxMouseEvent &event)
Called, when the mouse leaves the editor window.
Definition: editor.cpp:1633
void FoldAll()
Folds all fold markers.
Definition: editor.cpp:2207
std::vector< wxString > getProceduresInFile()
Wrapper for the search controller.
Definition: editor.cpp:5631
wxMenu * m_refactoringMenu
Definition: editor.h:450
void OnLoseFocus(wxFocusEvent &event)
Called, when the editor loses focus.
Definition: editor.cpp:1650
Options * m_options
Definition: editor.h:313
void OnExtractFormatted()
On MenuEvent handler for the extract as formatted text functionality of the editor.
Definition: editor.cpp:6929
bool MarkerOnLine(int linenum, int nMarker)
Checks, whether the passed marker is set on the passed line.
Definition: editor.cpp:7590
void OnMouseUp(wxMouseEvent &event)
Called, when the user releases the mouse key.
Definition: editor.cpp:1495
wxFileName GetFileName()
Definition: editor.cpp:4328
void OnFindIncludeFromMenu()
Global event handler function for finding the included script.
Definition: editor.cpp:6684
void ResetRightClickLocation()
Invalidates the latest mouse right click position.
Definition: editor.cpp:5430
void OnAutoCompletion(wxStyledTextEvent &event)
This event handler fires, if the user selects an entry in the autocompletion list or if he presses e....
Definition: editor.cpp:1896
FileFilterType GetFileType(const wxString &filename)
Returns the FileFilterType which corresponds to the passed file name.
Definition: editor.cpp:4261
int m_nLastLine
Definition: editor.h:429
void OnHideSelection(wxCommandEvent &event)
Private event handling function for hiding the selection.
Definition: editor.cpp:6740
void OnIdle(wxIdleEvent &event)
Called, when the editor idles, i.e. the user is not using it.
Definition: editor.cpp:1826
wxMenuItem * m_menuFindProcedure
Definition: editor.h:411
bool m_blockIndicatorActive
Definition: editor.h:443
wxString m_clickedProcedure
Definition: editor.h:406
wxString getBlockStart(const wxString &sWord)
This member function returns the control flow statement block start, which corresponds to the passed ...
Definition: editor.cpp:7347
int m_nDuplicateCodeLines
Definition: editor.h:427
DuplicateCodeDialog * m_duplicateCode
Definition: editor.h:419
void toggleBookmark()
Toggles a bookmark marker on the current line.
Definition: editor.cpp:2391
bool m_bHasBeenCompiled
Definition: editor.h:436
void ApplyAutoFormat(int nFirstLine=0, int nLastLine=-1)
Wrapper for CodeFormatter.
Definition: editor.cpp:8579
void JumpToBookmark(bool down=true)
Jumps the cursor to the next bookmark in the current file.
Definition: editor.cpp:2242
void AdvCallTipCancel()
Simply closes the calltip and resets its associated variables.
Definition: editor.cpp:1282
void OnMouseMotion(wxMouseEvent &event)
Event handler for moving while performing a drag 'n drop operation.
Definition: editor.cpp:5124
bool isCodeFile()
Definition: editor.h:301
friend class SearchController
Definition: editor.h:56
bool SaveGeneralFile(const wxString &filename)
Saves a general file without touching the encoding.
Definition: editor.cpp:539
void OnFindDuplicateCode(int nDuplicateFlag=1, int nNumDuplicatedLines=6)
Wrapper for detectCodeDuplicates.
Definition: editor.cpp:6989
wxString getBlockAutoCompletion(const wxString &sWord)
This member function returns a the complete autocompletion block for the passed control flow statemen...
Definition: editor.cpp:7281
bool m_bLastSavedRemotely
Definition: editor.h:435
void FoldCurrentBlock(int nLine)
Folds the block, to which the current line belongs.
Definition: editor.cpp:4627
void MakeBraceCheck()
Checks for corresponding braces.
Definition: editor.cpp:897
ProcedureViewer * m_procedureViewer
Definition: editor.h:391
EditorSettings
The possible per-editor settings.
Definition: editor.h:68
@ SETTING_DISPCTRLCHARS
Definition: editor.h:70
@ SETTING_WRAPEOL
Definition: editor.h:69
@ SETTING_USETXTADV
Definition: editor.h:71
@ SETTING_USESECTIONS
Definition: editor.h:74
@ SETTING_USEANALYZER
Definition: editor.h:72
@ SETTING_INDENTONTYPE
Definition: editor.h:73
bool m_bNewFile
Definition: editor.h:437
bool isNoAutoIndentionKey(int keycode)
This method is a simple helper for AsynchActions to determine, which key should not trigger the autoi...
Definition: editor.cpp:4952
wxFileName m_fileNameAndPath
Definition: editor.h:396
void OnFixTypes(wxCommandEvent &event)
Event wrapper for fixSymbolName.
Definition: editor.cpp:6806
bool HasBeenSaved()
Definition: editor.cpp:3543
void updateDefaultHighlightSettings()
Performs all general default syntax highlightings.
Definition: editor.cpp:4127
int isBlockMiddle(const wxString &sWord)
This function returns, whether a word matches to a block middle statement (e.g. elseif).
Definition: editor.cpp:7180
void markSections(bool bForceRefresh=false)
Adds markers to section headlines.
Definition: editor.cpp:4663
void OnAddBookmark(wxCommandEvent &event)
Adds a bookmark at the selected line.
Definition: editor.cpp:5243
void OnFindProcedureFromMenu()
Global event handler function for finding the procedure definition.
Definition: editor.cpp:6650
std::vector< int > BlockMatch(int nPos)
Finds all matching flow control statements.
Definition: editor.cpp:2994
wxMenuItem * m_menuFindInclude
Definition: editor.h:413
void AbstrahizeSection()
Extracts the marked selection into a new procedure.
Definition: editor.cpp:5783
bool m_modificationHappened
Definition: editor.h:441
void OnHelpOnSelection(wxCommandEvent &event)
Triggers the main frame to show the documentation viewer concerning the selected command.
Definition: editor.cpp:6620
void OnExtractAsHTML()
On MenuEvent handler for the extract as HTML functionality of the editor.
Definition: editor.cpp:6897
wxString m_watchedString
Definition: editor.h:399
wxDateTime m_filetime
Definition: editor.h:401
NumeReWindow * m_mainFrame
Definition: editor.h:390
void OnSavePointLeft(wxStyledTextEvent &event)
Called, when the editor leaves the latest save point.
Definition: editor.cpp:1881
std::vector< int > BlockMatchNSCR(int nPos)
Finds all matching flow control statements for NumeRe command syntax.
Definition: editor.cpp:3042
wxCriticalSection m_editorCS
Definition: editor.h:420
std::pair< int, int > getCurrentContext(int line)
Returns the start and end line of the current code context (i.e. the first and the last line of the c...
Definition: editor.cpp:8199
std::string getSemanticLineCPP(int nLine, int nDuplicateFlags)
Returns the selected line as semantic code.
Definition: editor.cpp:8004
wxTimer * m_analyzerTimer
Definition: editor.h:451
FileFilterType m_fileType
Definition: editor.h:446
void OnChar(wxStyledTextEvent &event)
Definition: editor.cpp:658
size_t m_clickedWordLength
Definition: editor.h:408
void OnAddBreakpoint(wxCommandEvent &event)
Definition: editor.cpp:5179
void OnRenameSymbols(wxCommandEvent &event)
Event wrapper for RenameSymbols.
Definition: editor.cpp:6778
void removeWhiteSpaces(int nType=RM_WS_BOTH)
Removes whitespaces depending on the passed type.
Definition: editor.cpp:2335
int m_nEditorSetting
Definition: editor.h:445
void OnRemoveBookmark(wxCommandEvent &event)
Removes a bookmark from the selected line.
Definition: editor.cpp:5258
std::vector< std::string > vDuplicateCodeResults
Definition: editor.h:421
void AsynchEvaluations()
Performs asynchronous evaluations and is called automatically.
Definition: editor.cpp:5057
bool isWrappedLine(int line)
This member function checks, whether a line has been syntactically wrapped around.
Definition: editor.cpp:4979
@ STYLE_STRINGPARSER
Definition: editor.h:332
@ STYLE_NUMBER
Definition: editor.h:331
@ STYLE_STRING
Definition: editor.h:333
@ STYLE_OPERATOR
Definition: editor.h:327
@ STYLE_COMMENT_SECTION_BLOCK
Definition: editor.h:323
@ STYLE_DATAOBJECT
Definition: editor.h:330
@ STYLE_COMMAND
Definition: editor.h:324
@ STYLE_IDENTIFIER
Definition: editor.h:329
@ STYLE_PROCEDURE
Definition: editor.h:328
@ STYLE_COMMENT
Definition: editor.h:319
@ STYLE_CUSTOMFUNCTION
Definition: editor.h:326
@ STYLE_DEFAULT
Definition: editor.h:318
@ STYLE_COMMENT_SECTION_LINE
Definition: editor.h:322
@ STYLE_COMMENT_LINE
Definition: editor.h:320
@ STYLE_COMMENT_BLOCK
Definition: editor.h:321
@ STYLE_FUNCTION
Definition: editor.h:325
int isBlockEnd(const wxString &sWord)
This function returns true, if a passed word corresponds to a control flow statement block end.
Definition: editor.cpp:7152
wxArrayInt GetBreakpoints()
Definition: editor.cpp:5287
void OnKeyDn(wxKeyEvent &event)
Checks key input events, before they are typed into the editor.
Definition: editor.cpp:1305
int countUmlauts(const std::string &sStr)
Counts the german umlauts in the current string.
Definition: editor.cpp:8401
friend class CodeFormatter
Definition: editor.h:57
bool IsModifiedInSection(int nSectionStart, int nSectionEnd, const wxString &sToken, const std::vector< int > &vMatch)
Determines, whether sToken is modified in the section.
Definition: editor.cpp:6178
void UnfoldAll()
Unfolds all fold markers.
Definition: editor.cpp:2223
void OnEditorModified(wxStyledTextEvent &event)
Definition: editor.cpp:4596
void HandleFunctionCallTip()
This function handles the descriptive function call tip.
Definition: editor.cpp:985
void markSaved()
Marks the complete document as saved.
Definition: editor.cpp:4568
int m_nDuplicateCodeFlag
Definition: editor.h:426
void CreateProcedureFromSection(int nStartPos, int nEndPos, const wxString &sInputList, const wxString sOutputList)
Creates a new procedure from the analysed code section.
Definition: editor.cpp:6062
std::string realignLangString(std::string sLine, size_t &lastpos)
Re-alignes the passed language string to fit into a call tip.
Definition: editor.cpp:8440
std::vector< wxString > vRenameSymbolsChangeLog
Definition: editor.h:423
void OnDrop(wxStyledTextEvent &event)
Event handler for stopping drag 'n drop. (Actually does nothing)
Definition: editor.cpp:5110
void OnKeyRel(wxKeyEvent &event)
Called, when the user releases a key.
Definition: editor.cpp:1473
int CallTipStartPos()
Returns the starting position of the currently displayed calltip.
Definition: editor.cpp:1243
CodeAnalyzer * m_analyzer
Definition: editor.h:392
wxString getFunctionArgumentList(int nFunctionStartLine)
Gets the argument list of a procedure.
Definition: editor.cpp:6279
NumeReTerminal * m_terminal
Definition: editor.h:417
void OnMouseCaptureLost(wxMouseCaptureLostEvent &event)
Called, when the mouse leaves the editor screen, but the user keeps the mouse pressed.
Definition: editor.cpp:1593
std::string GetCurrentArgument(const std::string &sCallTip, int nStartingBrace, int &nArgStartPos)
Finds the current argument below the cursor.
Definition: editor.cpp:1141
void AdvCallTipShow(int pos, const wxString &definition)
A more advanced calltip display routine.
Definition: editor.cpp:1259
void MakeBlockCheck()
Checks for corresponding flow control statements.
Definition: editor.cpp:942
FileFilterType getFileType()
Definition: editor.h:290
void ToggleCommentLine()
Toggles a line comment.
Definition: editor.cpp:1968
void OnClearBookmarks(wxCommandEvent &event)
Removes all bookmarks from the whole file.
Definition: editor.cpp:5273
friend class CodeAnalyzer
Definition: editor.h:55
void OnAnalyzerTimer(wxTimerEvent &event)
This event handler fires, once the analyzer timer is finished and calls the time consuming analysis t...
Definition: editor.cpp:1845
wxString m_clickedWord
Definition: editor.h:405
void SetFilename(wxFileName filename, bool fileIsRemote)
Definition: editor.cpp:4246
int m_nFirstLine
Definition: editor.h:428
void AsynchActions()
Performs asynchronous actions and is called automatically.
Definition: editor.cpp:5007
void OnAbstrahizeSectionFromMenu()
Global event handler for extracting the selected section.
Definition: editor.cpp:6833
wxPoint m_lastRightClick
Definition: editor.h:404
void setBookmarks(const std::vector< int > &vBookmarks)
Set the bookmarks in the editor.
Definition: editor.cpp:2311
bool defaultPage
Definition: editor.h:76
void ToggleCommentSelection()
Toggles block comments in a selection.
Definition: editor.cpp:2096
void AnalyseCode()
Wrapper for the static code analyzer.
Definition: editor.cpp:5443
bool SaveFileLocal()
Definition: editor.cpp:380
void OnMouseDwell(wxStyledTextEvent &event)
Called, when the mouse dwells for some time.
Definition: editor.cpp:1670
void EnsureLineVisibility(int line)
Ensures that the selected line is visible and not hidden bei either a code fold or a explicit line hi...
Definition: editor.cpp:5367
void OnStartDrag(wxStyledTextEvent &event)
Event handler for starting drag 'n drop.
Definition: editor.cpp:5082
wxString ExtractAsHTML(int nFirstLine=0, int nLastLine=-1)
Extracts the selected lines as pre- formatted HTML and returns it.
Definition: editor.cpp:8686
void markLocalVariables(bool bForceRefresh=false)
This method wraps the detection of local variables.
Definition: editor.cpp:4797
bool isNumeReFileType()
Definition: editor.h:297
void OnEnter(wxMouseEvent &event)
Called, when the mouse enters the editor window.
Definition: editor.cpp:1612
void OnRenameSymbolsFromMenu()
Global wrapper for RenameSymbols.
Definition: editor.cpp:6790
void UpdateIndicators()
Defines and applies styles to all needed indicators.
Definition: editor.cpp:4068
wxString m_dblclkString
Definition: editor.h:400
NumeReSyntax * _syntax
Definition: editor.h:416
void clearBookmarks()
Removes all bookmark markers from the current document.
Definition: editor.cpp:2409
bool m_bSetUnsaved
Definition: editor.h:438
void OnDragOver(wxStyledTextEvent &event)
Event handler for stopping drag 'n drop.
Definition: editor.cpp:5095
int m_nCallTipStart
Definition: editor.h:431
bool m_PopUpActive
Definition: editor.h:439
void FindAndOpenInclude(const wxString &includename)
Finds the included script and displays it in the editor.
Definition: editor.cpp:5601
std::map< int, int > getDifferences(int nStart1, int nEnd1, int nStart2, int nEnd2)
Returns the actual word-wise differences in the selected lines.
Definition: editor.cpp:8087
void FocusOnLine(int linenumber, bool showMarker=true)
Definition: editor.cpp:5343
void UpdateSyntaxHighlighting(bool forceUpdate=false)
Definition: editor.cpp:3573
void AddBreakpoint(int linenum)
Adds a breakpoint to the selected line.
Definition: editor.cpp:7450
void IndicateDuplicatedLine(int nStart1, int nEnd1, int nStart2, int nEnd2, int nSelectionLine)
Highlights differences between two blocks of code.
Definition: editor.cpp:7050
wxMenuItem * m_menuHelpOnSelection
Definition: editor.h:412
wxString GetFileNameAndPath()
Definition: editor.cpp:4299
std::vector< SyntaxBlockDefinition > vBlockDefs
Definition: editor.h:424
bool m_braceIndicatorActive
Definition: editor.h:442
std::string getSemanticLineNSCR(int nLine, int nDuplicateFlags)
Returns the selected line as semantic code.
Definition: editor.cpp:7827
void ReplaceMatches(const std::vector< int > &vMatches, const wxString &sSymbol, const wxString &sNewSymbol)
Replaces the matches with a new symbol.
Definition: editor.cpp:5648
bool m_bLoadingFile
Definition: editor.h:434
bool hasBlockMiddle(const wxString &sWord)
This function returns, whether a block has block middle statements.
Definition: editor.cpp:7205
void OnMouseDn(wxMouseEvent &event)
Called, when the user presses the left mouse key.
Definition: editor.cpp:1515
void GotoPipe(int nStartPos=0)
Jumps to the predefined template caret position.
Definition: editor.cpp:5144
NumeReEditor(NumeReWindow *mframe, Options *options, wxWindow *parent, wxWindowID id, NumeReSyntax *__syntax, NumeReTerminal *__terminal, const wxPoint &pos=wxDefaultPosition, const wxSize &size=wxDefaultSize, long style=0, const wxString &name=wxSTCNameStr)
Editor constructor.
Definition: editor.cpp:146
wxMenuItem * m_menuShowValue
Definition: editor.h:410
void OnFoldCurrentBlock(wxCommandEvent &event)
Event wrapper for FoldCurrentBlock.
Definition: editor.cpp:6726
void applyStrikeThrough()
Applies the strike-through effect.
Definition: editor.cpp:4203
bool isValidAutoCompMatch(int nPos, bool findAll, bool searchMethod)
Ensures that the current position follows all rules to be a valid autocompletion match.
Definition: editor.cpp:6389
void fixSymbolName(int pos)
Fixes the symbol's type depending on either the declaration point or the first assigned value.
Definition: editor.cpp:2637
void OnDisplayVariable(wxCommandEvent &event)
Highlights all word occurences permanently.
Definition: editor.cpp:6571
std::vector< int > getBookmarks()
Returns the line positions of the bookmarks.
Definition: editor.cpp:2287
void OnSavePointReached(wxStyledTextEvent &event)
Called, when the editor reaches the latest save point.
Definition: editor.cpp:1862
void RenameSymbols(int nPos)
Asks the user to supply a new name for the symbol at the passed position and replaces all occurences.
Definition: editor.cpp:5679
void OnMenuEvent(wxCommandEvent &event)
OnMenu event handler.
Definition: editor.cpp:6847
void OnMouseDblClk(wxMouseEvent &event)
Called, when the user double clicks.
Definition: editor.cpp:1535
std::vector< std::string > vParsedSemanticCode
Definition: editor.h:422
void OnFindInclude(wxCommandEvent &event)
Private event handler function for finding the included script.
Definition: editor.cpp:6668
void RemoveBreakpoint(int linenum)
Removes a breakpoint from the selected line.
Definition: editor.cpp:7487
wxString m_simpleFileName
Definition: editor.h:398
void OnThreadUpdate(wxThreadEvent &event)
Thread event handler function for the duplicated code detection functionality.
Definition: editor.cpp:7006
double compareCodeLines(int nLine1, int nLine2, int nDuplicateFlags)
Performs a semantic code comparsion of the two selected lines.
Definition: editor.cpp:7751
void detectCodeDuplicates(int startline, int endline, int nDuplicateFlags, int nNumDuplicatedLines)
Starts the duplicated code analysis.
Definition: editor.cpp:7720
void getMatchingBlock(int nPos)
Finds and highlights the matching flow control statements.
Definition: editor.cpp:2948
std::string GetCurrentFunctionContext(int &nStartingBrace)
Find the function, whose braces the cursor is currently located in.
Definition: editor.cpp:1096
void OnUnhideAllFromMenu()
Global event handling function to unhide all lines from the main frame's menu.
Definition: editor.cpp:6759
This class contains all needed keywords to highlight their occurences correspondingly....
Definition: syntax.hpp:55
std::string getNPRCCommands() const
Definition: syntax.hpp:117
std::string getConstants() const
Definition: syntax.hpp:125
std::string getAutoCompListCPP(std::string sFirstChars)
The same as above but specialized for C++ Commands.
Definition: syntax.cpp:802
std::string getOperators() const
Definition: syntax.hpp:129
std::string getMethods() const
Definition: syntax.hpp:123
std::string getDocKeyWords() const
Definition: syntax.hpp:131
@ SYNTAX_OPTION
Definition: syntax.hpp:92
@ SYNTAX_FUNCTION
Definition: syntax.hpp:93
@ SYNTAX_METHODS
Definition: syntax.hpp:102
@ SYNTAX_PROCEDURE
Definition: syntax.hpp:99
@ SYNTAX_CONSTANT
Definition: syntax.hpp:94
@ SYNTAX_COMMAND
Definition: syntax.hpp:91
@ SYNTAX_SPECIALVAL
Definition: syntax.hpp:95
@ SYNTAX_OPERATOR
Definition: syntax.hpp:98
@ SYNTAX_CLUSTER
Definition: syntax.hpp:104
std::string getAutoCompListMATLAB(std::string sFirstChars)
The same as above but specialized for MATLAB commands.
Definition: syntax.cpp:764
std::string getCommands() const
Definition: syntax.hpp:115
std::string getCpp() const
Definition: syntax.hpp:138
std::string getAutoCompListTeX(std::string sFirstChars)
The same as above but specialized for LaTeX Commands.
Definition: syntax.cpp:840
std::string getBlockDefs() const
Returns all block definitions as a folding string for the lexers.
Definition: syntax.cpp:210
std::string getSpecial() const
Definition: syntax.hpp:127
std::string getAutoCompList(std::string sFirstChars, bool useSmartSense=false)
This function returns the autocompletion list for the editor.
Definition: syntax.cpp:670
std::string getMatlab() const
Definition: syntax.hpp:134
std::vector< SyntaxBlockDefinition > getFullBlockDefs() const
Definition: syntax.hpp:153
std::string getCppFunctions() const
Definition: syntax.hpp:140
std::string getMatlabFunctions() const
Definition: syntax.hpp:136
std::string getProcAutoCompList(std::string sFirstChars, std::string sBaseNameSpace, std::string sSelectedNameSpace)
This function will return the autocompletion list for the procedures based upon the provided procedur...
Definition: syntax.cpp:878
std::string getFunctions() const
Definition: syntax.hpp:121
std::string getOptions() const
Definition: syntax.hpp:119
The terminal class for the GUI. It's a specialisation of the GenericTerminal.
Definition: terminal.hpp:46
Settings getKernelSettings()
This will return a copy of the internal settings object of the kernel.
Definition: terminal.cpp:383
void clearBreakpoints(const std::string &_sFilename)
This member function removes all breakpoints from the passed file.
Definition: terminal.cpp:295
void removeBreakpoint(const std::string &_sFilename, size_t nLine)
This member function removes a breakpoint from the passed file at the indicated line number.
Definition: terminal.cpp:280
std::vector< std::string > getPathSettings()
Returns the standard paths as a STL vector.
Definition: terminal.cpp:185
void addBreakpoint(const std::string &_sFilename, size_t nLine)
This member function adds a breakpoint to the passed file at the indicated line number.
Definition: terminal.cpp:263
This class is the actual NumeRe main frame. The application's logic is implemented here.
Definition: NumeReWindow.h:177
void NewFile(FileFilterType _filetype=FILE_NONSOURCE, const wxString &defaultfilename="")
bool GetFileContents(wxString fileToLoad, wxString &fileContents, wxString &fileName)
bool ShowHelp(const wxString &sDocId)
This member function displays the help page for the selected documentation ID.
void OpenSourceFile(wxArrayString fnames, unsigned int nLine=0, int nOpenFileFlag=OPENFILE_NOTHING)
Opens the given list of source files in the editor.
wxIcon getStandardIcon()
This public member function returns the default icon usable by different windows.
wxString getProgramFolder()
This member function returns the application's root path.
This class implements an interface of the internal Settings object adapted to be usable from the GUI.
Definition: Options.h:178
bool GetHighlightLocalVariables() const
Definition: Options.h:269
wxFont GetEditorFont() const
Definition: Options.h:231
@ INCLUDES
Definition: Options.h:292
@ FUNCTION
Definition: Options.h:285
@ OPERATOR
Definition: Options.h:293
@ STRING
Definition: Options.h:290
@ COMMAND
Definition: Options.h:280
@ SPECIALVAL
Definition: Options.h:289
@ CLUSTER
Definition: Options.h:287
@ NUMBER
Definition: Options.h:295
@ INSTALL
Definition: Options.h:298
@ DEFAULT_VARS
Definition: Options.h:299
@ DOCKEYWORD
Definition: Options.h:283
@ COMMENT
Definition: Options.h:281
@ STANDARD
Definition: Options.h:278
@ ACTIVE_LINE
Definition: Options.h:300
@ PROCEDURE
Definition: Options.h:294
@ DOCCOMMENT
Definition: Options.h:282
@ STRINGPARSER
Definition: Options.h:291
@ OPTION
Definition: Options.h:284
@ CUSTOM_FUNCTION
Definition: Options.h:286
@ CONSTANT
Definition: Options.h:288
@ PROCEDURE_COMMAND
Definition: Options.h:296
@ METHODS
Definition: Options.h:297
SyntaxStyles GetSyntaxStyle(size_t i) const
Return the selected syntax style by constructing it from the style string.
Definition: options.cpp:112
int GetCaretBlinkTime() const
Definition: Options.h:255
int GetDebuggerFocusLine() const
Definition: Options.h:257
bool GetKeepBackupFile() const
Definition: Options.h:251
void updateProcedureList(const std::vector< wxString > &vProcedures)
std::vector< int > FindAll(const wxString &sSymbol, int nStyle, int nStartPos=0, int nEndPos=-1, bool bSearchInComments=false)
Finds all occurences of a code symbol considering the style.
wxString FindProceduresInCurrentFile(wxString sFirstChars, wxString sSelectedNameSpace)
Finds procedures, which might match the passed word start.
wxString FindMarkedProcedure(int charpos, bool ignoreDefinitions=true)
Extracts the procedure call at the selected position.
wxString FindNameSpaceOfProcedure(int charpos)
Finds the current namespace for the procedure call.
wxString FindProcedureDefinition()
Searches the definition below the cursor.
wxString FindMarkedInclude(int charpos)
Constructs the file name of the included file.
wxString FindClickedProcedure()
Gets the name of the clicked procedure.
wxString FindClickedInclude()
Gets the name of the clicked include file.
std::vector< wxString > getProceduresInFile()
Creates a list of procedures in the current file.
int FindCurrentProcedureHead(int pos)
Find the procedure head line for the selected position.
wxString FindClickedWord()
Returns the word under the cursor while clicking.
SettingsValue & getSetting(const std::string &value)
Returns a reference to the setting value, which corresponds to the passed string. Throws an exception...
Definition: settings.hpp:711
bool useCustomLangFiles() const
Returns, whether user language files shall be used to override internal language strings.
Definition: settings.hpp:1161
bool isEnabled(const std::string &option) const
Returns true, if the setting with boolean value type is enabled, false otherwise. If the setting does...
Definition: settings.hpp:810
bool & active()
Returns a reference to a boolean value type setting.
Definition: settings.hpp:556
This class is the immutable (const) version of a string view. It can be constructed from a MutableStr...
FileRevisions * getRevisions(const wxString &currentFile)
This method returns the file revisions as pointer.
Definition: vcsmanager.cpp:68
This class generalizes a set of basic floating window functionalities like being closable by pressing...
Definition: viewerframe.hpp:31
@ MARKER_DUPLICATEINDICATOR_TWO
@ MARKER_BREAKPOINT
@ MARKER_DUPLICATEINDICATOR_ONE
@ MARKER_HIDDEN
@ MARKER_BOOKMARK
@ MARKER_SAVED
@ MARKER_HIDDEN_MARGIN
@ MARKER_FOCUSEDLINE
@ MARKER_SECTION
@ MARKER_MODIFIED
@ PROCPATH
FileFilterType
@ FILE_NONSOURCE
@ FILE_CPP
@ FILE_DATAFILES
@ FILE_NPRC
@ FILE_XML
@ FILE_TEXSOURCE
@ FILE_NSCR
@ FILE_NOTYPE
@ FILE_MATLAB
@ FILE_DIFF
@ ID_ABSTRAHIZE_SECTION
@ ID_FIND_INCLUDE
@ ID_DEBUG_DISPLAY_SELECTION
@ ID_MENU_PASTE
@ ID_MENU_COPY
@ ID_REFACTORING_MENU
@ ID_BOOKMARK_ADD
@ ID_UPPERCASE
@ ID_BOOKMARK_CLEAR
@ ID_ANALYZERTIMER
@ ID_DEBUG_CLEAR_ALL_BREAKPOINTS
@ ID_DEBUG_REMOVE_BREAKPOINT
@ ID_FIND_PROCEDURE
@ ID_HIDE_SELECTION
@ ID_RENAME_SYMBOLS
@ ID_FIX_TYPE
@ ID_FOLD_CURRENT_BLOCK
@ ID_LOWERCASE
@ ID_MENU_HELP_ON_ITEM
@ ID_MENU_CUT
@ ID_DEBUG_ADD_BREAKPOINT
@ ID_BOOKMARK_REMOVE
#define HIGHLIGHT_NOT_MATCHING_BLOCK
Definition: editor.cpp:64
#define ANNOTATION_ERROR
Definition: editor.cpp:71
#define HIGHLIGHT_LOCALVARIABLES
Definition: editor.cpp:68
#define HIGHLIGHT_MATCHING_BRACE
Definition: editor.cpp:61
#define HIGHLIGHT_STRIKETHROUGH
Definition: editor.cpp:62
Language _guilang
#define SEMANTICS_STRING
Definition: editor.cpp:74
static char applyFunctionHeuristics(const std::string &func)
Apply the function heuristics to detect the current symbol's type.
Definition: editor.cpp:2499
int CompareInts(int n1, int n2)
Definition: editor.cpp:122
#define HIGHLIGHT_DIFFERENCES
Definition: editor.cpp:65
static bool isEqualIgnoreWhitespace(wxString word1, wxString word2)
Definition: editor.cpp:7090
static char applyValueHeuristics(std::string val)
Apply the value heuristics to detect the current symbol's type.
Definition: editor.cpp:2569
#define HIGHLIGHT_DBLCLK
Definition: editor.cpp:60
#define SEMANTICS_NUM
Definition: editor.cpp:75
static bool isOnlyActiveBlock(int nBlockID, std::vector< int > vBlocks)
Checks, if the selected block is the only block active.
Definition: editor.cpp:3019
#define MARGIN_FOLD
Definition: editor.cpp:58
#define SEMANTICS_VAR
Definition: editor.cpp:73
#define SEMANTICS_FUNCTION
Definition: editor.cpp:76
#define HIGHLIGHT
Definition: editor.cpp:59
#define HIGHLIGHT_MATCHING_BLOCK
Definition: editor.cpp:63
#define HIGHLIGHT_DIFFERENCE_SOURCE
Definition: editor.cpp:66
static char applyCommandHeuristics(const std::string &command)
Apply the command heuristics to detect the current symbol's type.
Definition: editor.cpp:2534
#define ANNOTATION_WARN
Definition: editor.cpp:70
#define ANNOTATION_NOTE
Definition: editor.cpp:69
#define RM_WS_FRONT
Definition: editor.h:37
#define RM_WS_BACK
Definition: editor.h:38
#define RM_WS_BOTH
Definition: editor.h:36
std::string replacePathSeparator(const std::string &)
This function replaces the Windows style path sparators to UNIX style.
FindReplaceDialog * g_findReplace
bool fileExists(const string &)
This function checks, whether the file with the passed file name exists.
Definition: tools.cpp:2500
static Matrix selection(const MatFuncData &funcData, const MatFuncErrorInfo &errorInfo)
Extracts a selection from a matrix iterating through two matrices simultaneously.
Definition: matfuncs.hpp:3151
unsigned int getMatchingParenthesis(const StringView &)
Returns the position of the closing parenthesis.
Definition: tools.cpp:414
CONSTCD11 std::enable_if<!std::chrono::treat_as_floating_point< T >::value, T >::type trunc(T t) NOEXCEPT
Definition: date.h:1113
CONSTCD11 std::chrono::duration< Rep, Period > abs(std::chrono::duration< Rep, Period > d)
Definition: date.h:1317
char name[32]
Definition: resampler.cpp:371
Resample_Real(* func)(Resample_Real t)
Definition: resampler.cpp:372
#define max(a, b)
Definition: resampler.cpp:30
void StripSpaces(std::string &)
Removes leading and trailing white spaces and tabulator characters.
#define SETTING_B_SMARTSENSE
Definition: settings.hpp:100
#define SETTING_B_QUOTEAUTOCOMP
Definition: settings.hpp:98
#define SETTING_B_BLOCKAUTOCOMP
Definition: settings.hpp:99
#define SETTING_B_LINELENGTH
Definition: settings.hpp:95
#define SETTING_B_HOMEENDCANCELS
Definition: settings.hpp:96
#define SETTING_B_BRACEAUTOCOMP
Definition: settings.hpp:97
std::string toUpperCase(const std::string &sLowerCase)
Converts lowercase letters to uppercase ones.
std::string getNextArgument(std::string &sArgList, bool bCut)
Definition: tools.cpp:2294
void replaceAll(std::string &sToModify, const char *sToRep, const char *sNewValue, size_t nStart, size_t nEnd)
This function replaces all occurences of the string sToRep in the string sToModify with the new value...
std::string getTimeStamp(bool bGetStamp)
This function simple returns the current time as a default timestamp.
This structure contains the data for a single calltip, which might be shown in the editor or the term...
std::string sDefinition
std::string sDocumentation
A simple structure to define a syntax block for folding, etc.
Definition: syntax.hpp:35
std::string middleWord2
Definition: syntax.hpp:39
std::string endWord
Definition: syntax.hpp:37
std::string middleWord1
Definition: syntax.hpp:38
std::string startWord
Definition: syntax.hpp:36
This structure contains the necessary data to completely define a style for a distinctive syntax elem...
Definition: Options.h:27
bool bold
Definition: Options.h:30
wxColour background
Definition: Options.h:29
bool italics
Definition: Options.h:31
bool defaultbackground
Definition: Options.h:33
wxColour foreground
Definition: Options.h:28
bool underline
Definition: Options.h:32
std::string toString(int)
Converts an integer to a string without the Settings bloat.
bool validateParenthesisNumber(const string &sCmd)
This function is used to validate the number of parentheses, i.e. whether there's a closing parenthes...
Definition: tools.cpp:3512
END_EVENT_TABLE()