1
#include <sdk.h> // Code::Blocks SDK
2
#include <algorithm> // std::sort
3
#include <configurationpanel.h>
4
#include "EditorTweaks.h"
8
#include <wx/textdlg.h>
9
#include <wx/toolbar.h>
12
#include "EditorTweaksConfDlg.h"
16
#include <configmanager.h>
17
#include <logmanager.h>
18
#include <editor_hooks.h>
20
#include <wx/wxscintilla.h>
21
#include <editormanager.h>
22
#include "cbstyledtextctrl.h"
25
// Register the plugin with Code::Blocks.
26
// We are using an anonymous namespace so we don't litter the global one.
29
PluginRegistrant<EditorTweaks> reg(_T("EditorTweaks"));
31
struct CompareAlignerMenuEntry
33
bool operator() (AlignerMenuEntry i, AlignerMenuEntry j) { return (i.UsageCount<=j.UsageCount);}
34
} CompareAlignerMenuEntryObject;
36
const unsigned int defaultStoredAlignerEntries = 4;
38
wxString defaultNames[defaultStoredAlignerEntries] = { _T("Equality Operator"), _T("C/C++ line Comment "), _T("VHDL Signal Assignment"), _T("VHDL named association")};
39
wxString defaultStrings[defaultStoredAlignerEntries] = { _T("="), _T("//"), _T("<="), _T("=>") };
43
int id_et = wxNewId();
44
int id_et_WordWrap = wxNewId();
45
int id_et_CharWrap = wxNewId();
46
int id_et_ShowLineNumbers = wxNewId();
47
int id_et_TabChar = wxNewId();
48
int id_et_TabIndent = wxNewId();
49
int id_et_TabSize2 = wxNewId();
50
int id_et_TabSize4 = wxNewId();
51
int id_et_TabSize6 = wxNewId();
52
int id_et_TabSize8 = wxNewId();
53
int id_et_ConsistentIndent = wxNewId();
54
int id_et_ShowWhitespaceChars = wxNewId();
55
int id_et_ShowEOL = wxNewId();
56
int id_et_StripTrailingBlanks = wxNewId();
57
int id_et_EnsureConsistentEOL = wxNewId();
58
int id_et_EOLCRLF = wxNewId();
59
int id_et_EOLCR = wxNewId();
60
int id_et_EOLLF = wxNewId();
61
int id_et_Fold1 = wxNewId();
62
int id_et_Fold2 = wxNewId();
63
int id_et_Fold3 = wxNewId();
64
int id_et_Fold4 = wxNewId();
65
int id_et_Fold5 = wxNewId();
66
int id_et_Unfold1 = wxNewId();
67
int id_et_Unfold2 = wxNewId();
68
int id_et_Unfold3 = wxNewId();
69
int id_et_Unfold4 = wxNewId();
70
int id_et_Unfold5 = wxNewId();
71
int id_et_align_others = wxNewId();
72
int id_et_align_auto = wxNewId();
73
int id_et_align_last = wxNewId();
74
int id_et_LaptopFriendly = wxNewId();
75
int id_et_SuppressInsertKey = wxNewId();
76
int id_et_ConvertBraces = wxNewId();
77
int id_et_ScrollTimer = wxNewId();
80
BEGIN_EVENT_TABLE(EditorTweaks, cbPlugin)
81
EVT_UPDATE_UI(id_et_WordWrap, EditorTweaks::OnUpdateUI)
82
EVT_UPDATE_UI(id_et_CharWrap, EditorTweaks::OnUpdateUI)
83
EVT_UPDATE_UI(id_et_ShowLineNumbers, EditorTweaks::OnUpdateUI)
84
EVT_UPDATE_UI(id_et_TabChar, EditorTweaks::OnUpdateUI)
85
EVT_UPDATE_UI(id_et_TabIndent, EditorTweaks::OnUpdateUI)
86
EVT_UPDATE_UI(id_et_TabSize2, EditorTweaks::OnUpdateUI)
87
EVT_UPDATE_UI(id_et_TabSize4, EditorTweaks::OnUpdateUI)
88
EVT_UPDATE_UI(id_et_TabSize6, EditorTweaks::OnUpdateUI)
89
EVT_UPDATE_UI(id_et_TabSize8, EditorTweaks::OnUpdateUI)
90
EVT_UPDATE_UI(id_et_ShowEOL, EditorTweaks::OnUpdateUI)
91
EVT_UPDATE_UI(id_et_StripTrailingBlanks, EditorTweaks::OnUpdateUI)
92
EVT_UPDATE_UI(id_et_EnsureConsistentEOL, EditorTweaks::OnUpdateUI)
93
EVT_UPDATE_UI(id_et_EOLCRLF, EditorTweaks::OnUpdateUI)
94
EVT_UPDATE_UI(id_et_EOLCR, EditorTweaks::OnUpdateUI)
95
EVT_UPDATE_UI(id_et_EOLLF, EditorTweaks::OnUpdateUI)
98
EVT_MENU(id_et_WordWrap, EditorTweaks::OnWordWrap)
99
EVT_MENU(id_et_CharWrap, EditorTweaks::OnCharWrap)
100
EVT_MENU(id_et_ShowLineNumbers, EditorTweaks::OnShowLineNumbers)
101
EVT_MENU(id_et_TabChar, EditorTweaks::OnTabChar)
102
EVT_MENU(id_et_TabIndent, EditorTweaks::OnTabIndent)
103
EVT_MENU(id_et_TabSize2, EditorTweaks::OnTabSize2)
104
EVT_MENU(id_et_TabSize4, EditorTweaks::OnTabSize4)
105
EVT_MENU(id_et_TabSize6, EditorTweaks::OnTabSize6)
106
EVT_MENU(id_et_TabSize8, EditorTweaks::OnTabSize8)
107
EVT_MENU(id_et_ConsistentIndent, EditorTweaks::OnMakeIndentsConsistent)
108
EVT_MENU(id_et_ShowWhitespaceChars, EditorTweaks::OnShowWhitespaceChars)
109
EVT_MENU(id_et_ShowEOL, EditorTweaks::OnShowEOL)
110
EVT_MENU(id_et_StripTrailingBlanks, EditorTweaks::OnStripTrailingBlanks)
111
EVT_MENU(id_et_EnsureConsistentEOL, EditorTweaks::OnEnsureConsistentEOL)
112
EVT_MENU(id_et_EOLCRLF, EditorTweaks::OnEOLCRLF)
113
EVT_MENU(id_et_EOLCR, EditorTweaks::OnEOLCR)
114
EVT_MENU(id_et_EOLLF, EditorTweaks::OnEOLLF)
115
EVT_MENU(id_et_Fold1, EditorTweaks::OnFold)
116
EVT_MENU(id_et_Fold2, EditorTweaks::OnFold)
117
EVT_MENU(id_et_Fold3, EditorTweaks::OnFold)
118
EVT_MENU(id_et_Fold4, EditorTweaks::OnFold)
119
EVT_MENU(id_et_Fold5, EditorTweaks::OnFold)
120
EVT_MENU(id_et_Unfold1, EditorTweaks::OnUnfold)
121
EVT_MENU(id_et_Unfold2, EditorTweaks::OnUnfold)
122
EVT_MENU(id_et_Unfold3, EditorTweaks::OnUnfold)
123
EVT_MENU(id_et_Unfold4, EditorTweaks::OnUnfold)
124
EVT_MENU(id_et_Unfold5, EditorTweaks::OnUnfold)
126
EVT_MENU(id_et_LaptopFriendly, EditorTweaks::OnLaptopFriendly)
127
EVT_MENU(id_et_SuppressInsertKey, EditorTweaks::OnSuppressInsert)
128
EVT_MENU(id_et_ConvertBraces, EditorTweaks::OnConvertBraces)
129
EVT_MENU(id_et_align_others, EditorTweaks::OnAlignOthers)
130
EVT_MENU(id_et_align_auto, EditorTweaks::OnAlignAuto)
131
EVT_MENU(id_et_align_last, EditorTweaks::OnAlignLast)
133
EVT_TIMER(id_et_ScrollTimer, EditorTweaks::OnScrollTimer)
137
EditorTweaks::EditorTweaks() :
138
AlignerLastUsedIdx(0),
139
AlignerLastUsedAuto(false),
140
AlignerLastUsed(false),
141
m_scrollTimer(this, id_et_ScrollTimer)
143
// Make sure our resources are available.
144
// In the generated boilerplate code we have no resources but when
145
// we add some, it will be nice that this code is in place already ;)
146
if (!Manager::LoadResource(_T("EditorTweaks.zip")))
147
NotifyMissingFile(_T("EditorTweaks.zip"));
151
EditorTweaks::~EditorTweaks()
155
void EditorTweaks::OnAttach()
157
// do whatever initialization you need for your plugin
158
// NOTE: after this function, the inherited member variable
159
// m_IsAttached will be TRUE...
160
// You should check for it in other functions, because if it
161
// is FALSE, it means that the application did *not* "load"
162
// (see: does not need) this plugin...
164
Manager* pm = Manager::Get();
165
pm->RegisterEventSink(cbEVT_EDITOR_OPEN, new cbEventFunctor<EditorTweaks, CodeBlocksEvent>(this, &EditorTweaks::OnEditorOpen));
169
EditorManager* em = Manager::Get()->GetEditorManager();
170
for (int i=0;i<em->GetEditorsCount();i++)
172
cbEditor* ed=em->GetBuiltinEditor(i);
173
if (ed && ed->GetControl())
175
ed->GetControl()->SetOvertype(false);
176
ed->GetControl()->Connect(wxEVT_KEY_DOWN,(wxObjectEventFunction) (wxEventFunction) (wxCharEventFunction)&EditorTweaks::OnKeyPress,NULL,this);
177
ed->GetControl()->Connect(wxEVT_CHAR,(wxObjectEventFunction) (wxEventFunction) (wxCharEventFunction)&EditorTweaks::OnChar,NULL,this);
184
ConfigManager *cfg = Manager::Get()->GetConfigManager(_T("EditorTweaks"));
186
for (int i = 0 ; i < cfg->ReadInt(_T("/aligner/saved_entries"),defaultStoredAlignerEntries) ; ++i)
188
e.MenuName = cfg->Read(wxString::Format(_T("/aligner/first_name_%d"),i),defaultNames[i]);
189
e.ArgumentString = cfg->Read(wxString::Format(_T("/aligner/first_argument_string_%d"),i) ,defaultStrings[i]);
192
AlignerMenuEntries.push_back(e);
193
Connect(e.id, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(EditorTweaks::OnAlign) );
195
m_suppress_insert = cfg->ReadBool(wxT("/suppress_insert_key"), false);
196
m_laptop_friendly = cfg->ReadBool(wxT("/laptop_friendly"), false);
197
m_convert_braces = cfg->ReadBool(wxT("/convert_braces"), false);
201
void EditorTweaks::OnRelease(bool /*appShutDown*/)
205
// EditorHooks::UnregisterHook(m_EditorHookId, true);
206
EditorManager* em = Manager::Get()->GetEditorManager();
207
for (int i=0;i<em->GetEditorsCount();i++)
209
cbEditor* ed=em->GetBuiltinEditor(i);
210
if (ed && ed->GetControl())
212
ed->GetControl()->Disconnect(wxEVT_NULL,(wxObjectEventFunction) (wxEventFunction) (wxCharEventFunction)&EditorTweaks::OnKeyPress);
213
ed->GetControl()->Disconnect(wxEVT_NULL,(wxObjectEventFunction) (wxEventFunction) (wxCharEventFunction)&EditorTweaks::OnChar);
219
ConfigManager *cfg = Manager::Get()->GetConfigManager(_T("EditorTweaks"));
220
std::sort (AlignerMenuEntries.begin(), AlignerMenuEntries.end(),CompareAlignerMenuEntryObject);
221
std::reverse( AlignerMenuEntries.begin(), AlignerMenuEntries.end());
223
for (; i < cfg->ReadInt(_T("/aligner/max_saved_entries"),defaultStoredAlignerEntries) && i < static_cast<int>(AlignerMenuEntries.size()) ; ++i)
225
cfg->Write(wxString::Format(_T("/aligner/first_name_%d"),i),AlignerMenuEntries[i].MenuName);
226
cfg->Write(wxString::Format(_T("/aligner/first_argument_string_%d"),i) ,AlignerMenuEntries[i].ArgumentString);
228
Disconnect(AlignerMenuEntries[i].id, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(EditorTweaks::OnAlign) );
230
cfg->Write(_T("/aligner/saved_entries"),i);
231
for (; i < static_cast<int>(AlignerMenuEntries.size()) ; ++i)
232
Disconnect(AlignerMenuEntries[i].id, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(EditorTweaks::OnAlign) );
233
cfg->Write(wxT("/suppress_insert_key"), m_suppress_insert);
234
cfg->Write(wxT("/laptop_friendly"), m_laptop_friendly);
235
cfg->Write(wxT("/convert_braces"), m_convert_braces);
238
cbConfigurationPanel* EditorTweaks::GetConfigurationPanel(wxWindow* parent)
243
m_buffer_caret = -1; // invalidate so value will be read from configuration on next use
244
EditorTweaksConfDlg* cfg = new EditorTweaksConfDlg(parent);
248
void EditorTweaks::BuildMenu(wxMenuBar* menuBar)
250
Manager::Get()->GetLogManager()->DebugLog(_("Editor Tweaks plugin: Building menu"));
251
int i=menuBar->FindMenu(_("&Edit"));
254
Manager::Get()->GetLogManager()->DebugLog(_("Editor Tweaks plugin: edit menu not found"));
257
wxMenu *menu=menuBar->GetMenu(i);
258
for (i = 0; i < static_cast<int>(menu->GetMenuItemCount()); ++i)
260
wxMenuItem *mm=menu->FindItemByPosition(i);
261
#if wxCHECK_VERSION(2, 9, 0)
262
if (mm->GetItemLabel()==_("End-of-line mode"))
264
if (mm->GetLabel()==_("End-of-line mode"))
267
#if wxCHECK_VERSION(2, 9, 0)
268
if (mm->GetItemLabel()==_("Special commands"))
270
if (mm->GetLabel()==_("Special commands"))
274
if (i == static_cast<int>(menu->GetMenuItemCount()))
276
Manager::Get()->GetLogManager()->DebugLog(_("Editor Tweaks plugin: Special commands menu not found"));
279
Manager::Get()->GetLogManager()->DebugLog(wxString::Format(_("Editor Tweaks plugin: making the menu %i"),i));
280
m_tweakmenu=new wxMenu();
281
m_tweakmenuitem=new wxMenuItem(menu, id_et, _("Editor Tweaks"), _("Tweak the settings of the active editor"), wxITEM_NORMAL, m_tweakmenu);
282
menu->Insert(i+1,m_tweakmenuitem);
284
wxMenu *submenu=m_tweakmenu; //_("Editor Tweaks")
286
submenu->AppendCheckItem( id_et_WordWrap, _( "Word wrap" ), _( "Wrap word" ) );
287
submenu->AppendCheckItem( id_et_CharWrap, _( "Char wrap" ), _( "Wrap char" ) );
288
submenu->AppendCheckItem( id_et_ShowLineNumbers, _( "Show Line Numbers" ), _( "Show Line Numbers" ) );
289
submenu->AppendSeparator();
290
submenu->AppendCheckItem( id_et_TabChar, _( "Use Tab Character" ), _( "Use Tab Character" ) );
291
submenu->AppendCheckItem( id_et_TabIndent, _( "Tab Indents" ), _( "Tab Indents" ) );
292
wxMenu *tabsizemenu=new wxMenu();
293
tabsizemenu->AppendRadioItem( id_et_TabSize2, _( "2" ), _( "Tab Width of 2" ) );
294
tabsizemenu->AppendRadioItem( id_et_TabSize4, _( "4" ), _( "Tab Width of 4" ) );
295
tabsizemenu->AppendRadioItem( id_et_TabSize6, _( "6" ), _( "Tab Width of 6" ) );
296
tabsizemenu->AppendRadioItem( id_et_TabSize8, _( "8" ), _( "Tab Width of 8" ) );
297
submenu->Append(wxID_ANY,_("Tab Size"),tabsizemenu);
298
submenu->Append( id_et_ConsistentIndent, _( "Make Indents Consistent" ), _( "Convert leading tabs/spaces to the active setting" ) );
299
submenu->AppendCheckItem(id_et_ShowWhitespaceChars, _("Show whitespace characters"),
300
_("Shows the space and tab characters in the editor"));
301
submenu->AppendSeparator();
302
wxMenu *eolmenu=new wxMenu();
303
eolmenu->AppendRadioItem( id_et_EOLCRLF, _( "CR LF" ), _( "Carriage Return - Line Feed (Windows Default)" ) );
304
eolmenu->AppendRadioItem( id_et_EOLCR, _( "CR" ), _( "Carriage Return (Mac Default)" ) );
305
eolmenu->AppendRadioItem( id_et_EOLLF, _( "LF" ), _( "Line Feed (Unix Default)" ) );
306
submenu->Append(wxID_ANY,_("End-of-Line Mode"),eolmenu);
307
submenu->AppendCheckItem( id_et_ShowEOL, _( "Show EOL Chars" ), _( "Show End-of-Line Characters" ) );
308
submenu->Append( id_et_StripTrailingBlanks, _( "Strip Trailing Blanks Now" ), _( "Strip trailing blanks from each line" ) );
309
submenu->Append( id_et_EnsureConsistentEOL, _( "Make EOLs Consistent Now" ), _( "Convert End-of-Line Characters to the Active Setting" ) );
310
submenu->AppendSeparator();
311
submenu->AppendCheckItem( id_et_LaptopFriendly, _("Laptop Friendly Keyboard Navigation"), _("Enables keyboard shortcuts: Shift+Backspace = Delete, Alt+Down = Page Down, Alt+Up = Page Up, Alt+Left = Home, Alt+Right = End") );
312
submenu->AppendCheckItem( id_et_SuppressInsertKey, _("Suppress Insert Key"), _("Disable the effect of the insert key (toggle between insert and overwrite mode)") );
313
submenu->AppendCheckItem( id_et_ConvertBraces, _("Convert Matching Braces"), _("Selecting a brace and typing a new brace character will change the matching brace appropriately") );
314
submenu->AppendSeparator();
315
submenu->Append( id_et_align_last, _("Last Align"), _("repeat last Align command") );
316
submenu->Append( id_et_align_auto, _("Auto Align"), _("Align lines automatically") );
319
wxMenu *foldmenu = 0;
320
for (i = 0; i < static_cast<int>(menu->GetMenuItemCount()); ++i)
322
wxMenuItem *mm = menu->FindItemByPosition(i);
323
#if wxCHECK_VERSION(2, 9, 0)
324
if (mm->GetItemLabel()==_("Folding"))
326
if (mm->GetLabel()==_("Folding"))
329
foldmenu=mm->GetSubMenu();
335
Manager::Get()->GetLogManager()->DebugLog(_("Editor Tweaks plugin: Folding menu"));
339
foldmenu->AppendSeparator();
340
wxMenu *foldlevelmenu=new wxMenu();
341
foldlevelmenu->Append( id_et_Fold1, _( "1" ), _( "Fold all code to the first level" ) );
342
foldlevelmenu->Append( id_et_Fold2, _( "2" ), _( "Fold all code to the second level" ) );
343
foldlevelmenu->Append( id_et_Fold3, _( "3" ), _( "Fold all code to the third level" ) );
344
foldlevelmenu->Append( id_et_Fold4, _( "4" ), _( "Fold all code to the fourth level" ) );
345
foldlevelmenu->Append( id_et_Fold5, _( "5" ), _( "Fold all code to the fifth level" ) );
346
foldmenu->Append(wxID_ANY,_("Fold all above level"),foldlevelmenu);
348
wxMenu *unfoldlevelmenu=new wxMenu();
349
unfoldlevelmenu->Append( id_et_Unfold1, _( "1" ), _( "Unfold all code to the first level" ) );
350
unfoldlevelmenu->Append( id_et_Unfold2, _( "2" ), _( "Unfold all code to the second level" ) );
351
unfoldlevelmenu->Append( id_et_Unfold3, _( "3" ), _( "Unfold all code to the third level" ) );
352
unfoldlevelmenu->Append( id_et_Unfold4, _( "4" ), _( "Unfold all code to the fourth level" ) );
353
unfoldlevelmenu->Append( id_et_Unfold5, _( "5" ), _( "Unfold all code to the fifth level" ) );
354
foldmenu->Append(wxID_ANY,_("Unfold all above level"),unfoldlevelmenu);
360
void EditorTweaks::UpdateUI()
365
cbStyledTextCtrl* control = GetSafeControl();
367
m_tweakmenuitem->Enable(false);
369
m_tweakmenuitem->Enable(true);
371
wxMenu *submenu = m_tweakmenu;
375
submenu->Check(id_et_WordWrap,control->GetWrapMode()==wxSCI_WRAP_WORD);
376
submenu->Check(id_et_CharWrap,control->GetWrapMode()==wxSCI_WRAP_CHAR);
377
submenu->Check(id_et_ShowLineNumbers,control->GetMarginWidth(0)>0);
378
submenu->Check(id_et_TabChar,control->GetUseTabs());
379
submenu->Check(id_et_TabIndent,control->GetTabIndents());
380
submenu->Check(id_et_TabSize2,control->GetTabWidth()==2);
381
submenu->Check(id_et_TabSize4,control->GetTabWidth()==4);
382
submenu->Check(id_et_TabSize6,control->GetTabWidth()==6);
383
submenu->Check(id_et_TabSize8,control->GetTabWidth()==8);
384
submenu->Check(id_et_EOLCRLF,control->GetEOLMode()==wxSCI_EOL_CRLF);
385
submenu->Check(id_et_EOLCR,control->GetEOLMode()==wxSCI_EOL_CR);
386
submenu->Check(id_et_EOLLF,control->GetEOLMode()==wxSCI_EOL_LF);
387
submenu->Check(id_et_ShowEOL,control->GetViewEOL());
388
submenu->Check(id_et_ShowWhitespaceChars, control->GetViewWhiteSpace()!=wxSCI_WS_INVISIBLE);
390
submenu->Check(id_et_SuppressInsertKey, m_suppress_insert);
391
submenu->Check(id_et_LaptopFriendly, m_laptop_friendly);
392
submenu->Check(id_et_ConvertBraces, m_convert_braces);
395
void EditorTweaks::OnUpdateUI(wxUpdateUIEvent &/*event*/)
403
void EditorTweaks::OnEditorOpen(CodeBlocksEvent& /*event*/)
405
Manager::Get()->GetLogManager()->DebugLog(wxString::Format(_("Editor Open")));
406
cbStyledTextCtrl* control = GetSafeControl();
410
control->SetOvertype(false);
411
control->Connect(wxEVT_KEY_DOWN,(wxObjectEventFunction) (wxEventFunction) (wxCharEventFunction)&EditorTweaks::OnKeyPress,NULL,this);
412
control->Connect(wxEVT_CHAR,(wxObjectEventFunction) (wxEventFunction) (wxCharEventFunction)&EditorTweaks::OnChar,NULL,this);
416
void EditorTweaks::OnKeyPress(wxKeyEvent& event)
418
const int keyCode = event.GetKeyCode();
421
case WXK_NUMPAD_UP: case WXK_UP:
422
if (event.GetModifiers() != wxMOD_CONTROL)
423
DoBufferEditorPos(-1);
426
case WXK_NUMPAD_DOWN: case WXK_DOWN:
427
if (event.GetModifiers() == wxMOD_CONTROL)
430
case WXK_NUMPAD_ENTER: case WXK_RETURN:
431
DoBufferEditorPos(1);
434
case WXK_NUMPAD_TAB: case WXK_TAB:
435
if (event.GetModifiers() != wxMOD_NONE)
439
case WXK_NUMPAD_DELETE: case WXK_DELETE:
440
case WXK_NUMPAD_LEFT: case WXK_LEFT:
441
case WXK_NUMPAD_RIGHT: case WXK_RIGHT:
442
if (event.GetModifiers() == wxMOD_ALT)
445
case WXK_NUMPAD_HOME: case WXK_HOME:
446
case WXK_NUMPAD_END: case WXK_END:
453
// This set of laptop friendly helpers are a bit of a hack to make up for the lack of
454
// page up, page down, home, end, and delete keys on some laptops (especially Chromebooks)
455
if (m_laptop_friendly && keyCode == WXK_LEFT && event.AltDown())
457
cbStyledTextCtrl* control = GetSafeControl();
458
if (event.ShiftDown())
459
control->VCHomeDisplayExtend();
461
control->VCHomeDisplay();
464
else if (m_laptop_friendly && keyCode == WXK_RIGHT && event.AltDown())
466
cbStyledTextCtrl* control = GetSafeControl();
467
if (event.ShiftDown())
468
control->LineEndDisplayExtend();
470
control->LineEndDisplay();
473
else if (m_laptop_friendly && keyCode == WXK_UP && event.AltDown())
475
cbStyledTextCtrl* control = GetSafeControl();
476
if (event.ControlDown())
478
if (event.ShiftDown())
479
control->DocumentStartExtend();
481
control->DocumentStart();
484
if (event.ShiftDown())
485
control->PageUpExtend();
491
else if (m_laptop_friendly && keyCode == WXK_DOWN && event.AltDown())
493
cbStyledTextCtrl* control = GetSafeControl();
494
if (event.ControlDown())
496
if (event.ShiftDown())
497
control->DocumentEndExtend();
499
control->DocumentEnd();
502
if (event.ShiftDown())
503
control->PageDownExtend();
509
else if (m_laptop_friendly && keyCode == WXK_BACK && event.GetModifiers() == wxMOD_SHIFT)
511
cbStyledTextCtrl* control = GetSafeControl();
512
int anchor = control->GetAnchor();
513
int pos = control->GetCurrentPos();
514
if (anchor >= 0 && anchor != pos)
515
control->DeleteRange(control->GetSelectionStart(), control->GetSelectionEnd() - control->GetSelectionStart());
517
control->DeleteRange(control->GetCurrentPos(), 1);
520
else if (m_suppress_insert && keyCode == WXK_INSERT && event.GetModifiers() == wxMOD_NONE)
522
else if (m_convert_braces && keyCode == WXK_DELETE && (event.GetModifiers() == wxMOD_NONE || event.GetModifiers() == wxMOD_SHIFT))
526
cbStyledTextCtrl* control = GetSafeControl();
530
int p = control->GetCurrentPos();
531
int a = control->GetAnchor();
535
int m = control->BraceMatch(l);
536
if (m == wxSCI_INVALID_POSITION)
538
control->BeginUndoAction();
541
control->DeleteRange(m, 1);
542
control->DeleteRange(l, 1);
546
control->DeleteRange(l, 1);
547
control->DeleteRange(m, 1);
550
control->SetCurrentPos(l);
551
control->SetAnchor(l);
552
control->EndUndoAction();
559
void EditorTweaks::OnChar(wxKeyEvent& event)
563
wxChar ch = event.GetKeyCode();
564
if (m_convert_braces &&
577
cbStyledTextCtrl* control = GetSafeControl();
581
int p = control->GetCurrentPos();
582
int a = control->GetAnchor();
616
int m = control->BraceMatch(l);
617
if (m == wxSCI_INVALID_POSITION)
619
control->BeginUndoAction();
620
control->InsertText(l, wxString(ch,1));
621
control->DeleteRange(l+1, 1);
622
control->InsertText(m, opch);
623
control->DeleteRange(m+1, 1);
624
control->SetCurrentPos(p);
625
control->SetAnchor(a);
626
control->EndUndoAction();
631
void EditorTweaks::OnSuppressInsert(wxCommandEvent& event)
633
m_suppress_insert = event.IsChecked();
636
void EditorTweaks::OnLaptopFriendly(wxCommandEvent& event)
638
m_laptop_friendly = event.IsChecked();
641
void EditorTweaks::OnConvertBraces(wxCommandEvent& event)
643
m_convert_braces = event.IsChecked();
647
void EditorTweaks::BuildModuleMenu(const ModuleType type, wxMenu* menu, const FileTreeData* /*data*/)
649
//Some library module is ready to display a pop-up menu.
650
//Check the parameter \"type\" and see which module it is
651
//and append any items you need in the menu...
652
//TIP: for consistency, add a separator as the first item...
654
//make sure we have an editor
655
if (type != mtEditorManager || !m_tweakmenu)
658
cbStyledTextCtrl* control = GetSafeControl();
661
m_tweakmenuitem->Enable(false);
665
m_tweakmenuitem->Enable(true);
667
// build aligner menu and items
668
wxMenu* alignerMenu = new wxMenu();
670
std::sort (AlignerMenuEntries.begin(), AlignerMenuEntries.end(),CompareAlignerMenuEntryObject);
671
std::reverse( AlignerMenuEntries.begin(), AlignerMenuEntries.end());
673
for ( unsigned int i = 0; i < AlignerMenuEntries.size() ; i++ )
674
alignerMenu->Append(AlignerMenuEntries[i].id, AlignerMenuEntries[i].MenuName + _T("\t") + _T("[") + AlignerMenuEntries[i].ArgumentString + _T("]"));
675
alignerMenu->AppendSeparator();
676
alignerMenu->Append(id_et_align_auto, _("Auto"));
677
alignerMenu->Append(id_et_align_last, _("Last Align"), _("repeat last Align command") );
678
alignerMenu->Append(id_et_align_others, _("More ..."));
680
// attach aligner menu
681
menu->AppendSeparator();
682
menu->Append(wxID_ANY, _T("Aligner"), alignerMenu);
686
// DISABLED ALL OF THE STUFF BELOW (IT IS ALREADY IN THE MAIN MENU BAR)
688
// build "editor tweaks" menu
689
wxMenu *submenu=new wxMenu(); //_("Editor Tweaks")
691
menu->Append(id_et,_("Editor Tweaks"),submenu);
693
submenu->AppendCheckItem( id_et_WordWrap, _( "Word wrap" ), _( "Wrap word" ) );
694
if (control->GetWrapMode()==wxSCI_WRAP_WORD)
695
submenu->Check(id_et_WordWrap,true);
697
submenu->AppendCheckItem( id_et_CharWrap, _( "Char wrap" ), _( "Wrap char" ) );
698
if (control->GetWrapMode()==wxSCI_WRAP_CHAR)
699
submenu->Check(id_et_CharWrap,true);
701
submenu->AppendCheckItem( id_et_ShowLineNumbers, _( "Show Line Numbers" ), _( "Show Line Numbers" ) );
702
if (control->GetMarginWidth(0)>0)
703
submenu->Check(id_et_ShowLineNumbers,true);
705
submenu->AppendSeparator();
707
submenu->AppendCheckItem( id_et_TabChar, _( "Use Tab Character" ), _( "Use Tab Character" ) );
708
if (control->GetUseTabs())
709
submenu->Check(id_et_TabChar,true);
711
submenu->AppendCheckItem( id_et_TabIndent, _( "Tab Indents" ), _( "Tab Indents" ) );
712
if (control->GetTabIndents())
713
submenu->Check(id_et_TabIndent,true);
715
wxMenu *tabsizemenu=new wxMenu();
716
tabsizemenu->AppendRadioItem( id_et_TabSize2, _( "2" ), _( "Tab Width of 2" ) );
717
if (control->GetTabWidth()==2)
718
tabsizemenu->Check(id_et_TabSize2,true);
719
tabsizemenu->AppendRadioItem( id_et_TabSize4, _( "4" ), _( "Tab Width of 4" ) );
720
if (control->GetTabWidth()==4)
721
tabsizemenu->Check(id_et_TabSize4,true);
722
tabsizemenu->AppendRadioItem( id_et_TabSize6, _( "6" ), _( "Tab Width of 6" ) );
723
if (control->GetTabWidth()==6)
724
tabsizemenu->Check(id_et_TabSize6,true);
725
tabsizemenu->AppendRadioItem( id_et_TabSize8, _( "8" ), _( "Tab Width of 8" ) );
726
if (control->GetTabWidth()==8)
727
tabsizemenu->Check(id_et_TabSize8,true);
728
submenu->Append(wxID_ANY,_("Tab Size"),tabsizemenu);
730
submenu->AppendSeparator();
732
wxMenu *eolmenu=new wxMenu();
733
eolmenu->AppendRadioItem( id_et_EOLCRLF, _( "CR LF" ), _( "Carriage Return - Line Feed (Windows Default)" ) );
734
if (control->GetEOLMode()==wxSCI_EOL_CRLF)
735
eolmenu->Check(id_et_EOLCRLF,true);
736
eolmenu->AppendRadioItem( id_et_EOLCR, _( "CR" ), _( "Carriage Return (Mac Default)" ) );
737
if (control->GetEOLMode()==wxSCI_EOL_CR)
738
eolmenu->Check(id_et_EOLCR,true);
739
eolmenu->AppendRadioItem( id_et_EOLLF, _( "LF" ), _( "Line Feed (Unix Default)" ) );
740
if (control->GetEOLMode()==wxSCI_EOL_LF)
741
eolmenu->Check(id_et_EOLLF,true);
742
submenu->Append(wxID_ANY,_("End-of-Line Mode"),eolmenu);
744
submenu->AppendCheckItem( id_et_ShowEOL, _( "Show EOL Chars" ), _( "Show End-of-Line Characters" ) );
745
if (control->GetViewEOL())
746
submenu->Check(id_et_ShowEOL,true);
748
submenu->Append( id_et_StripTrailingBlanks, _( "Strip Trailing Blanks Now" ), _( "Strip trailing blanks from each line" ) );
750
submenu->Append( id_et_EnsureConsistentEOL, _( "Make EOLs Consistent Now" ), _( "Convert End-of-Line Characters to the Active Setting" ) );
752
menu->Append(wxID_ANY, _T("Editor Tweaks"), submenu);
756
void EditorTweaks::OnWordWrap(wxCommandEvent &/*event*/)
758
cbStyledTextCtrl* control = GetSafeControl();
762
bool enabled = control->GetWrapMode() == wxSCI_WRAP_WORD;
765
control->SetWrapMode(wxSCI_WRAP_NONE);
767
control->SetWrapMode(wxSCI_WRAP_WORD);
770
void EditorTweaks::OnCharWrap(wxCommandEvent &/*event*/)
772
cbStyledTextCtrl* control = GetSafeControl();
776
bool enabled = control->GetWrapMode() == wxSCI_WRAP_CHAR;
779
control->SetWrapMode(wxSCI_WRAP_NONE);
781
control->SetWrapMode(wxSCI_WRAP_CHAR);
784
void EditorTweaks::OnShowLineNumbers(wxCommandEvent &/*event*/)
786
cbStyledTextCtrl* control = GetSafeControl();
788
bool enabled=control->GetMarginWidth(0)>0;
790
// bool old_state=mgr->ReadBool(_T("/show_line_numbers"), true);
791
// mgr->Write(_T("/show_line_numbers"), !enabled);
792
// ed->SetEditorStyleAfterFileOpen();
793
// mgr->Write(_T("/show_line_numbers"), old_state);
796
control->SetMarginWidth(0, 0);
799
ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("editor"));
800
int pixelWidth = control->TextWidth(wxSCI_STYLE_LINENUMBER, _T("9"));
802
if (cfg->ReadBool(_T("/margin/dynamic_width"), false))
804
int lineNumWidth = 1;
805
int lineCount = control->GetLineCount();
807
while (lineCount >= 10)
813
control->SetMarginWidth(0, 6 + lineNumWidth * pixelWidth);
816
control->SetMarginWidth(0, 6 + cfg->ReadInt(_T("/margin/width_chars"), 6) * pixelWidth);
820
void EditorTweaks::OnTabChar(wxCommandEvent &/*event*/)
822
cbStyledTextCtrl* control = GetSafeControl();
826
control->SetUseTabs(!control->GetUseTabs());
829
void EditorTweaks::OnTabIndent(wxCommandEvent &/*event*/)
831
cbStyledTextCtrl* control = GetSafeControl();
835
control->SetTabIndents(!control->GetTabIndents());
838
void EditorTweaks::OnTabSize2(wxCommandEvent &/*event*/)
840
cbStyledTextCtrl* control = GetSafeControl();
844
control->SetTabWidth(2);
847
void EditorTweaks::OnTabSize4(wxCommandEvent &/*event*/)
849
cbStyledTextCtrl* control = GetSafeControl();
853
control->SetTabWidth(4);
856
void EditorTweaks::OnTabSize6(wxCommandEvent &/*event*/)
858
cbStyledTextCtrl* control = GetSafeControl();
862
control->SetTabWidth(6);
865
void EditorTweaks::OnTabSize8(wxCommandEvent &/*event*/)
867
cbStyledTextCtrl* control = GetSafeControl();
871
control->SetTabWidth(8);
874
void EditorTweaks::OnMakeIndentsConsistent(wxCommandEvent& /*event*/)
876
cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
880
MakeIndentsConsistent(ed);
883
void EditorTweaks::MakeIndentsConsistent(cbEditor* ed)
885
cbStyledTextCtrl* stc = ed->GetControl();
887
const bool useTab = stc->GetUseTabs();
888
const int tabWidth = stc->GetTabWidth();
889
const int maxLines = stc->GetLineCount();
890
bool changed = false;
891
for (int curLine = 0; curLine < maxLines; ++curLine)
893
const wxString curInd = ed->GetLineIndentString(curLine);
894
wxString indent = curInd;
896
indent.Replace(wxString(wxT(' '), tabWidth), wxT("\t"));
898
indent.Replace(wxT("\t"), wxString(wxT(' '), tabWidth));
899
if (indent != curInd)
901
if (!changed) // all changes in a single undo step
903
stc->BeginUndoAction();
906
stc->SetTargetStart(stc->PositionFromLine(curLine));
907
stc->SetTargetEnd(stc->PositionFromLine(curLine) + curInd.Length());
908
stc->ReplaceTarget(indent);
912
stc->EndUndoAction();
915
void EditorTweaks::OnShowWhitespaceChars(wxCommandEvent &event)
917
cbStyledTextCtrl* control = GetSafeControl();
919
control->SetViewWhiteSpace(event.IsChecked() ? wxSCI_WS_VISIBLEALWAYS : wxSCI_WS_INVISIBLE);
922
void EditorTweaks::OnShowEOL(wxCommandEvent &/*event*/)
924
cbStyledTextCtrl* control = GetSafeControl();
928
control->SetViewEOL(!control->GetViewEOL());
931
void EditorTweaks::OnStripTrailingBlanks(wxCommandEvent &/*event*/)
933
cbStyledTextCtrl* control = GetSafeControl();
937
StripTrailingBlanks(control);
940
void EditorTweaks::StripTrailingBlanks(cbStyledTextCtrl* control)
942
int maxLines = control->GetLineCount();
943
control->BeginUndoAction();
944
for (int line = 0; line < maxLines; line++)
946
int lineStart = control->PositionFromLine(line);
947
int lineEnd = control->GetLineEndPosition(line);
949
wxChar ch = (wxChar)(control->GetCharAt(i));
950
while ((i >= lineStart) && ((ch == _T(' ')) || (ch == _T('\t'))))
953
ch = (wxChar)(control->GetCharAt(i));
957
control->SetTargetStart(i+1);
958
control->SetTargetEnd(lineEnd);
959
control->ReplaceTarget(_T(""));
962
control->EndUndoAction();
965
void EditorTweaks::OnEnsureConsistentEOL(wxCommandEvent &/*event*/)
967
cbStyledTextCtrl* control = GetSafeControl();
971
control->ConvertEOLs(control->GetEOLMode());
974
void EditorTweaks::OnEOLCRLF(wxCommandEvent &/*event*/)
976
cbStyledTextCtrl* control = GetSafeControl();
980
control->SetEOLMode(wxSCI_EOL_CRLF);
983
void EditorTweaks::OnEOLCR(wxCommandEvent &/*event*/)
985
cbStyledTextCtrl* control = GetSafeControl();
989
control->SetEOLMode(wxSCI_EOL_CR);
992
void EditorTweaks::OnEOLLF(wxCommandEvent &/*event*/)
994
cbStyledTextCtrl* control = GetSafeControl();
998
control->SetEOLMode(wxSCI_EOL_LF);
1001
void EditorTweaks::OnFold(wxCommandEvent &event)
1003
int level=event.GetId()-id_et_Fold1;
1004
Manager::Get()->GetLogManager()->DebugLog(wxString::Format(_("Fold at level %i"),level));
1005
DoFoldAboveLevel(level,1);
1008
void EditorTweaks::OnUnfold(wxCommandEvent &event)
1010
int level=event.GetId()-id_et_Unfold1;
1011
Manager::Get()->GetLogManager()->DebugLog(wxString::Format(_("Unfold at level %i"),level));
1012
DoFoldAboveLevel(level,0);
1016
/** Fold/Unfold/Toggle all folds in the givel level.
1017
\param level Level number of folding, starting from 0.
1018
\param fold Type of folding action requested: \n
1022
void EditorTweaks::DoFoldAboveLevel(int level, int fold)
1024
cbStyledTextCtrl* control = GetSafeControl();
1028
level+=wxSCI_FOLDLEVELBASE;
1030
control->Colourise(0, -1); // the *most* important part!
1032
// Scan all file lines searching for the specified folding level.
1033
int count = control->GetLineCount();
1034
for (int line = 0; line <= count; ++line)
1036
int line_level_data = control->GetFoldLevel(line);
1037
if (!(line_level_data & wxSCI_FOLDLEVELHEADERFLAG))
1039
const int line_level = line_level_data & wxSCI_FOLDLEVELNUMBERMASK;
1041
const bool IsExpanded = control->GetFoldExpanded(line);
1043
// If a fold/unfold request is issued when the block is already
1044
// folded/unfolded, ignore the request.
1045
if (line_level<=level)
1052
if ((fold==0 && IsExpanded) || (fold ==1 && !IsExpanded))
1055
control->ToggleFold(line);
1059
void EditorTweaks::OnAlign(wxCommandEvent& event)
1061
int id = event.GetId();
1062
for ( unsigned int i = 0 ; i < AlignerMenuEntries.size(); i++)
1064
if ( AlignerMenuEntries[i].id == id )
1071
void EditorTweaks::DoAlign(unsigned int idx)
1073
if (idx >= AlignerMenuEntries.size())
1075
AlignToString(AlignerMenuEntries[idx].ArgumentString);
1076
AlignerMenuEntries[idx].UsageCount ++;
1078
AlignerLastUsedIdx = idx;
1079
AlignerLastUsedAuto = false;
1080
AlignerLastUsed = true;
1082
void EditorTweaks::OnAlignOthers(wxCommandEvent& /*event*/)
1084
wxString NewAlignmentString;
1085
wxString NewAlignmentStringName;
1086
bool NewCharacter = true;
1088
// create the name and call the first DialogBox
1089
const wxString MessageArgumentString = _("Insert a new character");
1090
const wxString CaptionArgumentString = _("New character");
1091
NewAlignmentString = wxGetTextFromUser( MessageArgumentString, CaptionArgumentString );
1092
if (NewAlignmentString !=_T(""))
1094
// check if the new character is equal as an exist
1096
for ( i = 0 ; i < AlignerMenuEntries.size(); i++)
1098
if (AlignerMenuEntries[i].ArgumentString == NewAlignmentString)
1100
NewCharacter = false;
1110
e.ArgumentString = NewAlignmentString;
1111
AlignerMenuEntries.push_back(e);
1112
Connect(e.id, wxEVT_COMMAND_MENU_SELECTED, wxCommandEventHandler(EditorTweaks::OnAlign) );
1115
// create the name and call the second DialogBox
1116
const wxString MessageName = _("Insert a name for the (new) character");
1117
const wxString CaptionName = NewAlignmentString;
1118
NewAlignmentStringName = wxGetTextFromUser( MessageName, CaptionName , AlignerMenuEntries[i].MenuName);
1119
if (NewAlignmentStringName != _T(""))
1120
AlignerMenuEntries[i].MenuName = NewAlignmentStringName;
1122
AlignToString(AlignerMenuEntries[i].ArgumentString);
1123
AlignerMenuEntries[i].UsageCount++;
1127
void EditorTweaks::OnAlignLast(cb_unused wxCommandEvent& event)
1129
if(!AlignerLastUsed)
1132
if (AlignerLastUsedAuto)
1135
DoAlign(AlignerLastUsedIdx);
1138
void EditorTweaks::OnAlignAuto(cb_unused wxCommandEvent& event)
1142
void EditorTweaks::DoAlignAuto()
1144
cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
1147
cbStyledTextCtrl* stc = ed->GetControl();
1151
int line_start = wxSCI_INVALID_POSITION;
1152
int line_end = wxSCI_INVALID_POSITION;
1153
if (!GetSelectionLines(line_start, line_end))
1155
wxArrayString lines;
1156
for (int i = line_start; i <= line_end; ++i)
1157
lines.Add(stc->GetLine(i));
1158
if (lines.GetCount() < 2)
1160
int lexer = stc->GetLexer();
1162
for (size_t i = 0; i < lines.GetCount(); ++i)
1164
lines[i].Replace(wxT("\t"), wxT(" "));
1165
// buffer assignment operators and commas in C++
1166
if (lexer == wxSCI_LEX_CPP)
1168
const wxString op = wxT("=<>!+-*/%&^| "); // do not split compound operators
1169
for (int j = lines[i].Length() - 2; j >= 0; --j)
1171
if ( lines[i][j] == wxT(',')
1172
|| (lines[i][j] == wxT('=') && lines[i][j + 1] != wxT('='))
1173
|| (lines[i][j + 1] == wxT('=') && op.Find(lines[i][j]) == wxNOT_FOUND) )
1175
lines[i].insert(j + 1, wxT(' '));
1179
// initialize output strings with their current indentation
1180
out.Add(ed->GetLineIndentString(line_start + i));
1182
// loop through number of columns
1184
for (size_t i = 0; i < numCols; ++i)
1186
// add the next token
1187
for (size_t j = 0; j < lines.GetCount(); ++j)
1189
wxArrayString lnParts = GetArrayFromString(lines[j], wxT(" "));
1190
if (i < lnParts.GetCount())
1191
out[j].Append(lnParts[i]);
1192
// set actual number of columns
1193
if (lnParts.GetCount() > numCols)
1194
numCols = lnParts.GetCount();
1196
// find the column size
1198
for (size_t j = 0; j < out.GetCount(); ++j)
1200
if (out[j].Length() > colPos)
1201
colPos = out[j].Length();
1203
// buffer output lines to column size + 1
1204
for (size_t j = 0; j < out.GetCount(); ++j)
1206
while (out[j].Length() <= colPos)
1207
out[j].Append(wxT(' '));
1210
// replace only the lines that have been modified
1211
stc->BeginUndoAction();
1212
for (size_t i = 0; i < out.GetCount(); ++i)
1214
stc->SetSelectionVoid(stc->PositionFromLine(line_start + i),
1215
stc->GetLineEndPosition(line_start + i));
1216
if (stc->GetSelectedText() != out[i].Trim())
1217
stc->ReplaceSelection(out[i]);
1219
stc->LineEnd(); // remove selection (if last line was not replaced)
1220
stc->EndUndoAction();
1222
AlignerLastUsedAuto = true;
1223
AlignerLastUsed = true;
1226
void EditorTweaks::AlignToString(const wxString AlignmentString)
1228
cbStyledTextCtrl* control = GetSafeControl();
1232
int line_start = wxSCI_INVALID_POSITION;
1233
int line_end = wxSCI_INVALID_POSITION;
1234
if (GetSelectionLines(line_start, line_end))
1236
// get furthest position of alignmentstring
1237
size_t find_position = wxString::npos;
1238
size_t max_position = wxString::npos;
1240
for (int i=line_start; i<=line_end; i++)
1243
find_position = control->GetLine(i).Find(AlignmentString);
1245
// store max position
1246
if (find_position != wxString::npos)
1249
if ((int) find_position > (int) max_position)
1250
max_position = find_position;
1254
// if string has been found more than once
1257
// loop through lines
1258
wxString replacement_text = _T("");
1259
wxString current_line = _T("");
1260
int spacing_diff = 0;
1261
for (int i=line_start; i<=line_end; i++)
1264
current_line = control->GetLine(i);
1265
if ( i == line_end )
1266
current_line = current_line.Trim();
1270
find_position = current_line.Find(AlignmentString);
1273
if (find_position != wxString::npos)
1275
spacing_diff = (int) max_position - (int) find_position;
1276
if (spacing_diff > 0)
1278
// assemble next part of replacement string
1279
current_line = current_line.insert(find_position, GetPadding(_T(" "), spacing_diff));
1284
replacement_text += current_line;
1288
control->BeginUndoAction();
1290
// get character positions of true selection start and end
1291
int pos_start = control->PositionFromLine(line_start);
1292
int pos_end = control->GetLineEndPosition(line_end);
1294
// select all lines properly
1295
control->SetSelectionVoid(pos_start, pos_end);
1297
// replace with replacement string
1298
control->ReplaceSelection(replacement_text);
1301
control->EndUndoAction();
1307
wxString EditorTweaks::GetPadding(const wxString& Padding, const int Count)
1309
wxString padding = _T("");
1310
for (int i=0;i<Count;i++)
1315
bool EditorTweaks::GetSelectionLines(int& LineStart, int& LineEnd)
1317
bool found_lines = false;
1319
cbEditor* editor = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
1320
if ( (editor) && (editor->HasSelection()) )
1322
cbStyledTextCtrl* control = editor->GetControl();
1326
int line_start = control->GetSelectionStart();
1327
int line_end = control->GetSelectionEnd();
1329
if ( (line_start != wxSCI_INVALID_POSITION) && (line_end != wxSCI_INVALID_POSITION) )
1331
LineStart = control->LineFromPosition(line_start);
1332
LineEnd = control->LineFromPosition(line_end);
1333
found_lines = (line_end > line_start);
1342
void EditorTweaks::DoBufferEditorPos(int delta, bool isScrollTimer)
1344
if (m_buffer_caret == -1)
1345
m_buffer_caret = Manager::Get()->GetConfigManager(wxT("EditorTweaks"))->ReadInt(wxT("/buffer_caret"), 1);
1346
if (m_buffer_caret < 1) // feature disabled (selected "None" in settings)
1349
cbStyledTextCtrl* stc = GetSafeControl();
1353
if (!stc || stc->AutoCompActive() || stc->LinesOnScreen() < 10) // ignore small editors
1355
const int firstVisibleLine = stc->GetFirstVisibleLine();
1356
const int dist = stc->VisibleFromDocLine(stc->GetCurrentLine()) + delta - firstVisibleLine;
1357
if (dist < 0 || dist > stc->LinesOnScreen()) // caret is off screen (see bug #18795)
1359
if (!isScrollTimer && !m_scrollTimer.IsRunning())
1360
m_scrollTimer.Start(5, wxTIMER_ONE_SHOT); // check to see if we moved into place
1363
const int buffer = (m_buffer_caret > 4 ? (stc->LinesOnScreen() >> 1) - 2 : m_buffer_caret);
1367
remaining = buffer - dist - 1;
1368
stc->LineScroll(0, (remaining > 3 ? -2 : -1)); // scroll up
1370
else if (dist >= stc->LinesOnScreen() - buffer)
1372
remaining = dist + buffer - stc->LinesOnScreen();
1373
stc->LineScroll(0, (remaining > 3 ? 2 : 1)); // scroll down
1375
if (!m_scrollTimer.IsRunning() && remaining > 0 && firstVisibleLine != stc->GetFirstVisibleLine())
1376
m_scrollTimer.Start(4 + (30 / remaining), wxTIMER_ONE_SHOT); // smooth scroll required lines
1379
void EditorTweaks::OnScrollTimer(wxTimerEvent& WXUNUSED(event))
1381
DoBufferEditorPos(0, true);
1384
cbStyledTextCtrl* EditorTweaks::GetSafeControl()
1386
if ( !IsAttached() )
1389
cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
1390
return ed ? ed->GetControl() : nullptr;