1 /*
2  * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3
3  * http://www.gnu.org/licenses/lgpl-3.0.html
4  */
5 
6 #ifndef CBEDITOR_H
7 #define CBEDITOR_H
8 
9 #include <wx/hashmap.h>
10 #include <wx/datetime.h>
11 #include <wx/fontmap.h>
12 #include <wx/timer.h>
13 
14 #include "settings.h"
15 #include "editorbase.h"
16 #include "printing_types.h"
17 
18 extern const wxString g_EditorModified;
19 
20 // forward decls
21 struct cbEditorInternalData; // this is the private data struct used by the editor.
22 class cbEditor;
23 class ProjectFile;
24 class EditorColourSet;
25 class wxSplitterWindow;
26 class LoaderBase;
27 class cbStyledTextCtrl;
28 class wxScintillaEvent;
29 class wxBoxSizer;
30 
31 
32 /** @brief A file editor
33   *
34   * This class represents one builtin editor in Code::Blocks. It holds all the necessary
35   * information about an editor. When you want to access a Code::Blocks editor,
36   * this is the class you want to get at ;)\n
37   *
38   * To do this, use Manager::Get()->GetEditorManager() functions.
39   *
40   * The actual editor component used is Scintilla and it can be accessed through
41   * the member function GetControl().
42   */
43 class DLLIMPORT cbEditor : public EditorBase
44 {
45         DECLARE_EVENT_TABLE()
46         friend class EditorManager;
47 
48     protected:
49         /** cbEditor constructor.
50           * @param parent the parent notebook - you should use EditorManager::Get()
51           * @param filename the filename to open. If filename is empty, it creates a
52           * new, empty, editor.
53           * @param theme the initial colour set to use\n
54           * <em>Note: you cannot create a cbEditor object directly. Instead
55           * use EditorManager's methods to do it...</em>
56           */
57         cbEditor(wxWindow* parent, const wxString& filename, EditorColourSet* theme);
58         cbEditor(wxWindow* parent, LoaderBase* fileLdr, const wxString& filename, EditorColourSet* theme);
59         /** cbEditor destructor. */
60         ~cbEditor() override;
61     public:
62         enum SplitType
63         {
64             stNoSplit = 0,
65             stHorizontal,
66             stVertical
67         };
68 
69         /** Don't use this. It throws an exception if you do. */
70         void operator=(cb_unused const cbEditor& rhs){ cbThrow(_T("Can't assign an cbEditor* !!!")); }
71 
72         // properties
73 
74         /** Returns a pointer to the underlying cbStyledTextCtrl object (which
75           * itself is the wxWindows implementation of Scintilla). If you want
76           * to mess with the actual contents of an editor, this is the object
77           * you want to get.
78           * @remarks If the editor is split, this function returns the control
79           * which currently has the keyboard focus. Don't save this pointer
80           * because it might be invalid at any later time...
81           */
82         cbStyledTextCtrl* GetControl() const;
83 
84         /** Returns a pointer to the left (or top) split-view cbStyledTextCtrl.
85           * This function always returns a valid pointer.
86           */
GetLeftSplitViewControl()87         cbStyledTextCtrl* GetLeftSplitViewControl() const { return m_pControl; }
88 
89         /** Returns a pointer to the right (or bottom) split-view cbStyledTextCtrl.
90           * This function may return NULL if the editor is not split.
91           */
GetRightSplitViewControl()92         cbStyledTextCtrl* GetRightSplitViewControl() const { return m_pControl2; }
93 
94         /** Returns the state of split-view for this editor. */
GetSplitType()95         SplitType GetSplitType() const { return m_SplitType; }
96 
97         /** Returns true if editor is OK, i.e. constructor was called with a filename
98           * parameter and file was opened successfully. If it returns false, you
99           * should delete the editor...
100           */
IsOK()101         bool IsOK() const { return m_IsOK; }
102 
103         /** Sets the editor title. For tabbed interface, it sets the corresponding
104           * tab text, while for MDI interface it sets the MDI window title...
105           */
106         void SetEditorTitle(const wxString& title);
107 
108         /** Returns true if editor is modified, false otherwise */
109         bool GetModified() const override;
110 
111         /** Set the editor's modification state to \c modified. */
112         void SetModified(bool modified = true) override;
113 
114         /** Set the ProjectFile pointer associated with this editor. All editors
115           * which belong to a project file, should have this set. All others should return NULL.
116           * Optionally you can preserve the "modified" flag of the file.
117           */
118         void SetProjectFile(ProjectFile* project_file,bool preserve_modified = false);
119 
120         /** Read the ProjectFile pointer associated with this editor. All editors
121           * which belong to a project file, have this set. All others return NULL.
122           */
GetProjectFile()123         ProjectFile* GetProjectFile() const { return m_pProjectFile; }
124 
125         /** Updates the associated ProjectFile object with the editor's caret
126           * position, top visible line and its open state. Used in devProject
127           * layout information, so that each time the user opens a project
128           * file in the IDE, it opens exactly in the same state it was when last
129           * closed.
130           */
131         void UpdateProjectFile();
132 
133         /** Save editor contents. Returns true on success, false otherwise. */
134         bool Save() override;
135 
136         /** Save editor contents under a different filename. Returns true on success, false otherwise. */
137         bool SaveAs() override;
138 
139         /** Save fold states within a new cbStyledTextCtrl. This saves the whole document, thus saving the fold states before the Fold Options Change*/
140         bool SaveFoldState();
141 
142         /** Fix fold states by comparing foldBackup with m_pControl. This is a temp fix for the Scintilla bug*/
143         bool FixFoldState();
144 
145         /** Fold all editor folds (hides blocks of code). */
146         void FoldAll();
147 
148         /** Unfold all editor folds (shows blocks of code). */
149         void UnfoldAll();
150 
151         /** Toggle all editor folds (inverts the show/hide state of blocks of code). */
152         void ToggleAllFolds();
153 
154         /** Sets the type of folding indicator where id is one of the following: 0->Arrow, 1->Circle, 2->Square, 3->simple */
155         void SetFoldingIndicator(int id);
156 
157         /** Folds the block containing \c line. If \c line is -1, folds the block containing the caret. */
158         void FoldBlockFromLine(int line = -1);
159 
160         /** Unfolds the block containing \c line. If \c line is -1, unfolds the block containing the caret. */
161         void UnfoldBlockFromLine(int line = -1);
162 
163         /** Toggles folding of the block containing \c line. If \c line is -1, toggles folding of the block containing the caret. */
164         void ToggleFoldBlockFromLine(int line = -1);
165 
166         /** Set the colour set to use. */
167         void SetColourSet(EditorColourSet* theme);
168 
169         /** Get the colour set in use. */
GetColourSet()170         EditorColourSet* GetColourSet() const { return m_pTheme; }
171 
172         /** Jumps to the matching brace (if there is one). */
173         void GotoMatchingBrace();
174 
175         /** Highlights the brace pair (one of the braces must be under the cursor) */
176         void HighlightBraces();
177 
178         /** Returns the specified line's (0-based) indentation (whitespace) in spaces. If line is -1, it uses the current line */
179         int GetLineIndentInSpaces(int line = -1) const;
180 
181         /** Returns the specified line's (0-based) indentation (whitespace) string. If line is -1, it uses the current line */
182         wxString GetLineIndentString(int line = -1) const;
183 
184         /** Returns the last modification time for the file. Used to detect modifications outside the editor. */
GetLastModificationTime()185         wxDateTime GetLastModificationTime() const { return m_LastModified; }
186 
187         /** Sets the last modification time for the file to 'now'. Used to detect modifications outside the editor. */
188         void Touch();
189 
190         /** Reloads the file from disk. @return True on success, False on failure. */
191         bool Reload(bool detectEncoding = true);
192 
193         /** Print the file.
194           * @param selectionOnly Should the selected text be printed only?
195           * @param pcm The colour mode to use when printing
196           * @param line_numbers Print the line numbers of file, too.
197           */
198         void Print(bool selectionOnly, PrintColourMode pcm, bool line_numbers);
199 
200         /** This method is obsolete, use the abbreviations plugin instead. */
201         void AutoComplete();
202 
203         /** Move the caret at the specified line.
204           * @param line Line to move caret to.
205           * @param centerOnScreen If true (default), tries to bring the specified line to the centre of the editor.*/
206         void GotoLine(int line, bool centerOnScreen = true) override;
207 
208         /** Move the caret at the specified line.
209           * @param line      Line to move caret to (where the token is).
210           * @param tokenName Token name (string) to highlight, if found
211           * @return Editor found, position set and token highlighted? */
212         bool GotoTokenPosition(int line, const wxString& tokenName);
213 
214         /** Add debugger breakpoint at specified line. If @c line is -1, use current line. */
215         bool AddBreakpoint(int line = -1, bool notifyDebugger = true);
216 
217         /** Remove debugger breakpoint at specified line. If @c line is -1, use current line. */
218         bool RemoveBreakpoint(int line = -1, bool notifyDebugger = true);
219 
220         /** Toggle debugger breakpoint at specified line. If @c line is -1, use current line. */
221         virtual void ToggleBreakpoint(int line = -1, bool notifyDebugger = true);
222 
223         /** Does @c line has debugger breakpoint? If @c line is -1, use current line. */
224         virtual bool HasBreakpoint(int line) const;
225 
226         /** Go to next debugger breakpoint. */
227         virtual void GotoNextBreakpoint();
228 
229         /** Go to previous debugger breakpoint. */
230         virtual void GotoPreviousBreakpoint();
231 
232         /** Refresh all markers for the breakpoints (only the markers for the current debugger will be shown) */
233         virtual void RefreshBreakpointMarkers();
234 
235         /** Clear all bookmarks. */
236         virtual void ClearAllBookmarks();
237 
238         /** Toggle bookmark at specified line. If @c line is -1, use current line. */
239         virtual void ToggleBookmark(int line = -1);
240 
241         /** Does @c line has bookmark? */
242         virtual bool HasBookmark(int line) const;
243 
244         /** Go to next bookmark. */
245         virtual void GotoNextBookmark();
246 
247         /** Go to previous bookmark. */
248         virtual void GotoPreviousBookmark();
249 
250         /** Highlight the line the debugger will execute next. */
251         virtual void SetDebugLine(int line);
252 
253         /** Highlight the specified line as error. */
254         virtual void SetErrorLine(int line);
255 
256         /** Split the editor window.
257           * @param split The type of split: horizontal or vertical. */
258         void Split(SplitType split);
259 
260         /** Unsplit the editor window. */
261         void Unsplit();
262 
263         // the following functions, although self-explanatory, are documented
264         // in EditorBase.
265         void Undo() override;
266         void Redo() override;
267         void ClearHistory() override;
268         void GotoNextChanged() override;
269         void GotoPreviousChanged() override;
270         void SetChangeCollection(bool collectChange) override;
271         void Cut() override;
272         void Copy() override;
273         void Paste() override;
274         bool CanUndo() const override;
275         bool CanRedo() const override;
276         bool HasSelection() const override;
277         bool CanPaste() const override;
278         bool IsReadOnly() const override;
279         void SetReadOnly(bool readonly = true) override;
280 
281         bool CanSelectAll() const override;
282         void SelectAll() override;
283 
284         // Workaround for shift-tab bug in wx2.4.2
285         void DoIndent();   //!< Indents current line/block
286         void DoUnIndent(); //!< UnIndents current line/block
287 
288         // misc. functions
289         wxMenu* CreateContextSubMenu(long id) override;
290         void AddToContextMenu(wxMenu* popup,ModuleType type,bool pluginsdone) override;
291 
GetLanguage()292         HighlightLanguage GetLanguage( ) const { return m_lang; }
293         /// Sets the language for this editor.
294         /// @param lang The language for the editor. If you pass HL_AUTO the language would be
295         /// autodetected.
296         /// @param colourise Pass true if you want to apply the style. If you intend to do more
297         /// operations which would affect styling pass false.
298         void SetLanguage(HighlightLanguage lang, bool colourise);
299 
300         wxFontEncoding GetEncoding( ) const;
301         wxString GetEncodingName( ) const;
302         void SetEncoding( wxFontEncoding encoding );
303 
304         bool GetUseBom() const;
305         void SetUseBom( bool bom );
306 
307         void SetZoom(int zoom, bool both = true);
308 
309         /// Apply the editor defaults to any (possibly foreign) cbStyledTextCtrl.
310         static void ApplyStyles(cbStyledTextCtrl* control);
311 
312         void AutoIndentDone();
313 
314         /// Applies the styles that match the filename of the editor.
315         /// Should be called after new file is created. Calling SaveAs does the same thing.
316         void SetEditorStyle();
317     private:
318         cbEditor(cb_unused const cbEditor& rhs); // prevent copy construction
319 
320         // functions
321         bool LineHasMarker(int marker, int line = -1) const;
322         void MarkerToggle(int marker, int line = -1);
323         void MarkerNext(int marker);
324         void MarkerPrevious(int marker);
325         void MarkLine(int marker, int line);
326 
327         enum class FoldMode : int
328         {
329             contract = 0, // wxSCI_FOLDACTION_CONTRACT
330             expand = 1, // wxSCI_FOLDACTION_EXPAND,
331             toggle = 2, //wxSCI_FOLDACTION_TOGGLE
332         };
333         enum FoldFlags : unsigned
334         {
335             none = 0x0,
336             ensureVisible = 0x2,
337         };
338 
339         void DoFoldAll(FoldMode fold);
340         void DoFoldBlockFromLine(int line, FoldMode fold, unsigned foldFlags);
341         void SetMarkerStyle(int marker, int markerType, wxColor fore, wxColor back);
342         void UnderlineFoldedLines(bool underline);
343         cbStyledTextCtrl* CreateEditor();
344         void ConnectEvents(cbStyledTextCtrl* stc);
345         void SetEditorStyleBeforeFileOpen();
346         void SetEditorStyleAfterFileOpen();
347         static void InternalSetEditorStyleBeforeFileOpen(cbStyledTextCtrl* control);
348         static void InternalSetEditorStyleAfterFileOpen(cbStyledTextCtrl* control);
349         bool Open(bool detectEncoding = true);
350         void DoAskForCodeCompletion(); // relevant to code-completion plugins
351         void SetLanguageDependentColours(cbStyledTextCtrl &control);
352         void NotifyPlugins(wxEventType type, int intArg = 0, const wxString& strArg = wxEmptyString, int xArg = 0, int yArg = 0);
353 
354         // events
355         void OnMarginClick(wxScintillaEvent& event);
356         void OnEditorUpdateUI(wxScintillaEvent& event);
357         void OnEditorChange(wxScintillaEvent& event);
358         void OnEditorCharAdded(wxScintillaEvent& event);
359         void OnEditorDwellStart(wxScintillaEvent& event);
360         void OnEditorDwellEnd(wxScintillaEvent& event);
361         void OnEditorModified(wxScintillaEvent& event);
362         void OnUserListSelection(wxScintillaEvent& event);
363         void OnZoom(wxScintillaEvent& event);
364         /** notify all the registered EditorHook functions
365          * @param event indicates which event is received by the cbEditor
366          * You should bind OnScintillaEvent to every wxScintillaEvent events, either directly or
367          * indirectly, see cbEditor::ConnectEvents() for more details.
368          */
369         void OnScintillaEvent(wxScintillaEvent& event);
370         void OnClose(wxCloseEvent& event);
371 
372         // one event handler for all popup menu entries
373         void OnContextMenuEntry(wxCommandEvent& event);
374         bool OnBeforeBuildContextMenu(const wxPoint& position, ModuleType type) override;
375         void OnAfterBuildContextMenu(ModuleType type) override;
376 
377         void DestroySplitView();
378 
379         void DoInitializations(const wxString& filename, LoaderBase* fileLdr = nullptr);
380 
381         void BreakpointMarkerToggle(int line);
382 
383         // variables
384         bool m_IsOK;
385         wxSplitterWindow* m_pSplitter;
386         wxBoxSizer* m_pSizer;
387         cbStyledTextCtrl* m_pControl;
388         cbStyledTextCtrl* m_pControl2;
389         cbStyledTextCtrl* m_foldBackup;
390         SplitType m_SplitType;
391         bool m_Modified;
392         int m_Index;
393         wxTimer m_timerWait;
394         ProjectFile* m_pProjectFile;
395         EditorColourSet* m_pTheme;
396         HighlightLanguage m_lang;
397         wxDateTime m_LastModified; // to check if the file was modified outside the editor
398         bool m_autoIndentDone;
399 
400         // DO NOT ADD ANY MORE VARIABLES HERE!
401         // ADD THEM IN cbEditorInternalData INSTEAD!
402 
403         friend struct cbEditorInternalData; // allow cbEditorInternalData to access cbEditor
404         cbEditorInternalData* m_pData;
405 };
406 
407 #endif // CBEDITOR_H
408