~ubuntu-branches/ubuntu/raring/codeblocks/raring-proposed

« back to all changes in this revision

Viewing changes to src/sdk/cbeditor.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Cosme Domínguez Díaz
  • Date: 2010-08-09 04:38:38 UTC
  • mfrom: (1.1.1 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20100809043838-a59ygguym4eg0jgw
Tags: 10.05-0ubuntu1
* New upstream release. Closes (LP: #322350)
 - Switch to dpkg-source 3.0 (quilt) format
 - Remove unneeded README.source
 - Add debian/get-source-orig script that removes all
   Windows prebuilt binaries
* Bump Standards-Version to 3.9.1
 - Stop shipping *.la files
* debian/control
 - Add cdbs package as Build-Depend
 - Add libbz2-dev and zlib1g-dev packages as
   Build-Depends (needed by libhelp_plugin.so)
 - Remove dpatch package of Build-Depends
 - Add codeblocks-contrib-debug package
 - Split architecture-independent files of codeblocks
   package in codeblocks-common package
* debian/rules
 - Switch to CDBS rules system
 - Add parallel build support
 - Add a call to debian/get-source-orig script
 - Use lzma compression (saves 23,5 MB of free space)
* debian/patches
 - Refresh 01_codeblocks_plugin_path
 - Add 02_no_Makefiles_in_debian_dir to remove any link
   in codeblocks build system to deleted Makefiles of debian directory
 - Drop 02_ftbfs_gcc44 and 03_ftbfs_glib221 (merged in upstream)
* debian/watch
 - Update to use the new host (berlios.de)

Show diffs side-by-side

added added

removed removed

Lines of Context:
2
2
 * This file is part of the Code::Blocks IDE and licensed under the GNU Lesser General Public License, version 3
3
3
 * http://www.gnu.org/licenses/lgpl-3.0.html
4
4
 *
5
 
 * $Revision: 4909 $
6
 
 * $Id: cbeditor.cpp 4909 2008-02-27 13:15:26Z mortenmacfly $
7
 
 * $HeadURL: svn://svn.berlios.de/codeblocks/tags/8.02/src/sdk/cbeditor.cpp $
 
5
 * $Revision: 6198 $
 
6
 * $Id: cbeditor.cpp 6198 2010-03-30 18:07:42Z killerbot $
 
7
 * $HeadURL: svn+ssh://jenslody@svn.berlios.de/svnroot/repos/codeblocks/trunk/src/sdk/cbeditor.cpp $
8
8
 */
9
9
 
10
10
#include "sdk_precomp.h"
43
43
 
44
44
const wxString g_EditorModified = _T("*");
45
45
 
46
 
#define ERROR_MARKER        1
47
 
#define ERROR_STYLE            wxSCI_MARK_SMALLRECT
48
 
 
49
 
#define BOOKMARK_MARKER        2
50
 
#define BOOKMARK_STYLE         wxSCI_MARK_ARROW
51
 
 
52
 
#define BREAKPOINT_MARKER    3
53
 
#define BREAKPOINT_STYLE     wxSCI_MARK_CIRCLE
54
 
 
55
 
#define DEBUG_MARKER        4
56
 
#define DEBUG_STYLE         wxSCI_MARK_ARROW
57
 
 
 
46
#define ERROR_MARKER          1
 
47
#define ERROR_STYLE           wxSCI_MARK_SMALLRECT
 
48
 
 
49
#define BOOKMARK_MARKER       2
 
50
#define BOOKMARK_STYLE        wxSCI_MARK_ARROW
 
51
 
 
52
#define BREAKPOINT_MARKER     3
 
53
#define BREAKPOINT_STYLE      wxSCI_MARK_CIRCLE
 
54
 
 
55
#define DEBUG_MARKER          4
 
56
#define DEBUG_STYLE           wxSCI_MARK_ARROW
 
57
 
 
58
static const int lineMargin      = 0; // Line numbers
 
59
static const int markerMargin    = 1; // Bookmarks, Breakpoints...
 
60
static const int changebarMargin = 2;
 
61
static const int foldingMargin   = 3;
58
62
 
59
63
 
60
64
/* This struct holds private data for the cbEditor class.
97
101
 
98
102
        if (m_pFileLoader)
99
103
        {
 
104
#ifdef fileload_measuring
 
105
            wxStopWatch sw;
 
106
#endif
100
107
            EncodingDetector enc(fileLoader);
101
108
            if (enc.IsOK())
102
109
            {
104
111
                m_useByteOrderMark = enc.UsesBOM();
105
112
                m_encoding = enc.GetFontEncoding();
106
113
            }
 
114
#ifdef fileload_measuring
 
115
            Manager::Get()->GetLogManager()->DebugLog(F(_T("Encoding via fileloader took : %d ms"),(int)sw.Time()));
 
116
#endif
107
117
        }
108
118
    }
109
119
 
135
145
        return eolstring;
136
146
    }
137
147
    // funcs
 
148
    int GetFirstBraceInLine(int string_style)
 
149
    {
 
150
        cbStyledTextCtrl* control = m_pOwner->GetControl();
 
151
        int curr_position = control->GetCurrentPos();
 
152
        int position = curr_position;
 
153
        int min_brace_position = position;
 
154
        int closing_braces = 0;
 
155
        bool found_brace = false;
 
156
        bool has_braces = false;
 
157
 
 
158
        while (position)
 
159
        {
 
160
            wxChar c = control->GetCharAt(--position);
 
161
 
 
162
            int style = control->GetStyleAt(position);
 
163
            if(style == string_style)
 
164
                continue;
 
165
 
 
166
            if (c == _T(';'))
 
167
            {
 
168
                found_brace = false;
 
169
                break;
 
170
            }
 
171
            else if (c == _T(')'))
 
172
            {
 
173
                ++closing_braces;
 
174
                has_braces = true;
 
175
            }
 
176
            else if (c == _T('('))
 
177
            {
 
178
                has_braces = true;
 
179
                if(closing_braces > 0)
 
180
                    --closing_braces;
 
181
                else if(!found_brace)
 
182
                {
 
183
                    min_brace_position = position + 1;
 
184
                    found_brace = true;
 
185
                    break;
 
186
                }
 
187
            }
 
188
            else if (c == _T('\n') && position + 1 != curr_position && !has_braces)
 
189
            {
 
190
                break;
 
191
            }
 
192
        }
 
193
 
 
194
        if (!found_brace)
 
195
            return -1;
 
196
 
 
197
        int tab_characters = 0;
 
198
 
 
199
        while (position)
 
200
        {
 
201
            wxChar c = control->GetCharAt(--position);
 
202
            if (c == _T('\n') && position + 1 != curr_position)
 
203
            {
 
204
                break;
 
205
            }
 
206
            else if (c == _T('\t'))
 
207
                ++tab_characters;
 
208
        }
 
209
 
 
210
        if (control->GetUseTabs())
 
211
        {
 
212
            position -= tab_characters * control->GetTabWidth();
 
213
        }
 
214
        return min_brace_position - position - 1;
 
215
    }
 
216
 
138
217
    /** Get the last non-whitespace character before position */
139
218
    wxChar GetLastNonWhitespaceChar(int position = -1)
140
219
    {
170
249
        return 0;
171
250
    }
172
251
 
 
252
    /** Get the last non-whitespace character from position in line */
 
253
    wxChar GetNextNonWhitespaceCharOfLine(int position = -1, int *pos = 0)
 
254
    {
 
255
        cbStyledTextCtrl* control = m_pOwner->GetControl();
 
256
        if (position == -1)
 
257
            position = control->GetCurrentPos();
 
258
 
 
259
        while (position < control->GetLength())
 
260
        {
 
261
            wxChar c = control->GetCharAt(position);
 
262
            if ( c == _T('\n') || c ==  _T('\r') )
 
263
            {
 
264
                if ( pos ) *pos = position;
 
265
                return 0;
 
266
            }
 
267
            if ( c !=  _T(' ') && c != _T('\t') )
 
268
            {
 
269
                if ( pos ) *pos = position;
 
270
                return c;
 
271
            }
 
272
            position++;
 
273
        }
 
274
 
 
275
        return 0;
 
276
    }
 
277
 
173
278
    int FindBlockStart(int position, wxChar blockStart, wxChar blockEnd, bool skipNested = true)
174
279
    {
175
280
        cbStyledTextCtrl* control = m_pOwner->GetControl();
191
296
        return -1;
192
297
    }
193
298
 
194
 
    /** Strip Trailing Blanks before saving */
 
299
    bool IsComment( int style )
 
300
    {
 
301
        cbStyledTextCtrl* control = m_pOwner->GetControl();
 
302
        switch ( control->GetLexer() )
 
303
        {
 
304
            case wxSCI_LEX_CPP:
 
305
                return  style == wxSCI_C_COMMENT ||
 
306
                        style == wxSCI_C_COMMENTLINE ||
 
307
                        style == wxSCI_C_COMMENTDOC ||
 
308
                        style == wxSCI_C_COMMENTDOCKEYWORD ||
 
309
                        style == wxSCI_C_COMMENTDOCKEYWORDERROR ||
 
310
                        style == wxSCI_C_COMMENTLINEDOC;
 
311
            case wxSCI_LEX_D:
 
312
                return  style == wxSCI_D_COMMENT ||
 
313
                        style == wxSCI_D_COMMENTLINE ||
 
314
                        style == wxSCI_D_COMMENTDOC ||
 
315
                        style == wxSCI_D_COMMENTDOCKEYWORD ||
 
316
                        style == wxSCI_D_COMMENTDOCKEYWORDERROR ||
 
317
                        style == wxSCI_D_COMMENTLINEDOC;
 
318
            default:
 
319
                return false;
 
320
        }
 
321
        return false;
 
322
    }
 
323
 
 
324
    bool IsPreprocessor( int style )
 
325
    {
 
326
        cbStyledTextCtrl* control = m_pOwner->GetControl();
 
327
        if ( control->GetLexer() == wxSCI_LEX_CPP )
 
328
            return  style == wxSCI_C_PREPROCESSOR;
 
329
        return false;
 
330
    }
 
331
 
 
332
    bool IsCharacterOrString( int  style )
 
333
    {
 
334
        cbStyledTextCtrl* control = m_pOwner->GetControl();
 
335
        switch ( control->GetLexer() )
 
336
        {
 
337
            case wxSCI_LEX_CPP:
 
338
                return style == wxSCI_C_STRING || style == wxSCI_C_CHARACTER;
 
339
            case wxSCI_LEX_D:
 
340
                return style == wxSCI_D_STRING || style == wxSCI_D_CHARACTER;
 
341
            default:
 
342
                return false;
 
343
        }
 
344
        return false;
 
345
    }
 
346
 
 
347
    bool IsCharacter( int  style )
 
348
    {
 
349
        cbStyledTextCtrl* control = m_pOwner->GetControl();
 
350
        switch ( control->GetLexer() )
 
351
        {
 
352
            case wxSCI_LEX_CPP:
 
353
                return style == wxSCI_C_CHARACTER;
 
354
            case wxSCI_LEX_D:
 
355
                return style == wxSCI_D_CHARACTER;
 
356
            default:
 
357
                return false;
 
358
        }
 
359
        return false;
 
360
    }
 
361
 
 
362
    void DoBraceCompletion(const wxChar& ch)
 
363
    {
 
364
        cbStyledTextCtrl* control = m_pOwner->GetControl();
 
365
        int pos = control->GetCurrentPos();
 
366
        int style = control->GetStyleAt(pos);
 
367
        if ( IsComment(style) || IsPreprocessor(style) )
 
368
            return;
 
369
        if ( ch == _T('\'') )
 
370
        {
 
371
            if ( (control->GetCharAt(pos) == ch) && (pos > 1) && (control->GetCharAt(pos-2) != _T('\\')) )
 
372
            {
 
373
                control->DeleteBack();
 
374
                control->GotoPos(pos);
 
375
            }
 
376
            else
 
377
            {
 
378
                if ( (control->GetCharAt(pos-2) == _T('\\')) || IsCharacterOrString(style) )
 
379
                    return;
 
380
                control->AddText(ch);
 
381
                control->GotoPos(pos);
 
382
            }
 
383
            return;
 
384
        }
 
385
        if ( ch == _T('"') )
 
386
        {
 
387
            if ( (control->GetCharAt(pos) == ch) && (pos > 1) && (control->GetCharAt(pos-2) != _T('\\')) )
 
388
            {
 
389
                control->DeleteBack();
 
390
                control->GotoPos(pos);
 
391
            }
 
392
            else
 
393
            {
 
394
                if ( (control->GetCharAt(pos-2) == _T('\\')) || IsCharacter(style) )
 
395
                    return;
 
396
                control->AddText(ch);
 
397
                control->GotoPos(pos);
 
398
            }
 
399
            return;
 
400
        }
 
401
        if ( IsCharacterOrString(style) )
 
402
            return;
 
403
        const wxString leftBrace(_T("([{"));
 
404
        const wxString rightBrace(_T(")]}"));
 
405
        int index = leftBrace.Find(ch);
 
406
        const wxString unWant(_T(");\n\r\t\b "));
 
407
        const wxChar nextChar = control->GetCharAt(pos);
 
408
        #if wxCHECK_VERSION(2, 9, 0)
 
409
        if ((index != wxNOT_FOUND) && ((unWant.Find(wxUniChar(nextChar)) != wxNOT_FOUND) || nextChar == _T('\0')))
 
410
        #else
 
411
        if ((index != wxNOT_FOUND) && ((unWant.Find(nextChar) != wxNOT_FOUND) || nextChar == _T('\0')))
 
412
        #endif
 
413
        {
 
414
            control->AddText(rightBrace.GetChar(index));
 
415
            control->GotoPos(pos);
 
416
            if (ch == _T('{'))
 
417
            {
 
418
                const wxRegEx reg(_T("^[ \t]*{}[ \t]*"));
 
419
                if (reg.Matches(control->GetCurLine()))
 
420
                {
 
421
                    control->NewLine();
 
422
                    control->GotoPos(pos);
 
423
                    control->NewLine();
 
424
                    return;
 
425
                }
 
426
            }
 
427
        }
 
428
        else
 
429
        {
 
430
            index = rightBrace.Find(ch);
 
431
            if (index != wxNOT_FOUND)
 
432
            {
 
433
                if (control->GetCharAt(pos) == ch)
 
434
                {
 
435
                    control->DeleteBack();
 
436
                    control->GotoPos(pos);
 
437
                    return;
 
438
                }
 
439
            }
 
440
        }
 
441
    }
 
442
 
 
443
    /** Strip trailing blanks before saving */
195
444
    void StripTrailingSpaces()
196
445
    {
197
446
        cbStyledTextCtrl* control = m_pOwner->GetControl();
257
506
 
258
507
            if (lineNumWidth != m_lineNumbersWidth)
259
508
            {
260
 
                m_pOwner->m_pControl->SetMarginWidth(0, 6 + lineNumWidth * pixelWidth);
 
509
                m_pOwner->m_pControl->SetMarginWidth(lineMargin, 6 + lineNumWidth * pixelWidth);
261
510
                if (m_pOwner->m_pControl2)
262
 
                    m_pOwner->m_pControl2->SetMarginWidth(0, 6 + lineNumWidth * pixelWidth);
 
511
                    m_pOwner->m_pControl2->SetMarginWidth(lineMargin, 6 + lineNumWidth * pixelWidth);
263
512
                m_lineNumbersWidth = lineNumWidth;
264
513
            }
265
514
        }
266
515
        else
267
516
        {
268
 
            m_pOwner->m_pControl->SetMarginWidth(0, 6 + cfg->ReadInt(_T("/margin/width_chars"), 6) * pixelWidth);
 
517
            m_pOwner->m_pControl->SetMarginWidth(lineMargin, 6 + cfg->ReadInt(_T("/margin/width_chars"), 6) * pixelWidth);
269
518
            if (m_pOwner->m_pControl2)
270
 
                m_pOwner->m_pControl2->SetMarginWidth(0, 6 + cfg->ReadInt(_T("/margin/width_chars"), 6) * pixelWidth);
 
519
                m_pOwner->m_pControl2->SetMarginWidth(lineMargin, 6 + cfg->ReadInt(_T("/margin/width_chars"), 6) * pixelWidth);
 
520
        }
 
521
    }
 
522
 
 
523
    void HighlightOccurrences()
 
524
    {
 
525
        static long old_a;
 
526
        static long old_b;
 
527
        // chosed a high value for indicator, in the hope not to interfere with the indicators used by some lexers (,
 
528
        // if they get updated from deprecated oldstyle indicators somedays.
 
529
        const int theIndicator = 10;
 
530
 
 
531
        long a, b;
 
532
        m_pOwner->GetControl()->GetSelection(&a, &b);
 
533
 
 
534
        m_pOwner->GetControl()->SetIndicatorCurrent(theIndicator);
 
535
 
 
536
        if(old_a == a && old_b == b) // whatever the current state is, we've already done it once
 
537
            return;
 
538
 
 
539
        old_a = a; old_b = b;
 
540
 
 
541
        wxString selectedText(m_pOwner->GetControl()->GetTextRange(a, b));
 
542
 
 
543
        int eof = m_pOwner->m_pControl->GetLength();
 
544
        ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("editor"));
 
545
 
 
546
        // Set Styling:
 
547
        // clear all style indications set in a previous run (is also done once after text gets unselected)
 
548
        m_pOwner->GetControl()->IndicatorClearRange(0, eof);
 
549
 
 
550
        // check that feature is enabled,
 
551
        // selected text has a minimal length of 3 and contains no spaces
 
552
        if( cfg->ReadBool(_T("/highlight_occurrence/enabled"), true)
 
553
                && selectedText.Len() > 2        // if there is no text selected (a == b), it stops here and does not hog the cpu further
 
554
                && selectedText.Find(_T(' ')) == wxNOT_FOUND
 
555
                && selectedText.Find(_T('\t')) == wxNOT_FOUND
 
556
                && selectedText.Find(_T('\n')) == wxNOT_FOUND )
 
557
        {
 
558
            wxColour highlightColour(cfg->ReadColour(_T("/highlight_occurrence/colour"), wxColour(255, 0, 0)));
 
559
            if ( m_pOwner->m_pControl )
 
560
            {
 
561
                m_pOwner->m_pControl->IndicatorSetStyle(theIndicator, wxSCI_INDIC_HIGHLIGHT);
 
562
                m_pOwner->m_pControl->IndicatorSetForeground(theIndicator, highlightColour );
 
563
#ifndef wxHAVE_RAW_BITMAP
 
564
                // If wxWidgets is build without rawbitmap-support, the indicators become opaque
 
565
                // and hide the text, so we show them under the text.
 
566
                // Not enabled as default, because the readability is a little bit worse.
 
567
                m_pOwner->m_pControl->IndicatorSetUnder(theIndicator,true);
 
568
#endif
 
569
            }
 
570
            if ( m_pOwner->m_pControl2 )
 
571
            {
 
572
                m_pOwner->m_pControl2->IndicatorSetStyle(theIndicator, wxSCI_INDIC_HIGHLIGHT);
 
573
                m_pOwner->m_pControl2->IndicatorSetForeground(theIndicator, highlightColour );
 
574
#ifndef wxHAVE_RAW_BITMAP
 
575
                m_pOwner->m_pControl2->IndicatorSetUnder(theIndicator,true);
 
576
#endif
 
577
            }
 
578
 
 
579
            int flag = 0;
 
580
            if (cfg->ReadBool(_T("/highlight_occurrence/case_sensitive"), true))
 
581
            {
 
582
                flag |= wxSCI_FIND_MATCHCASE;
 
583
            }
 
584
            if (cfg->ReadBool(_T("/highlight_occurrence/whole_word"), true))
 
585
            {
 
586
                flag |= wxSCI_FIND_WHOLEWORD;
 
587
            }
 
588
            // search for every occurence
 
589
            int lengthFound = 0; // we need this to work properly with multibyte characters
 
590
            for ( int pos = m_pOwner->GetControl()->FindText(0, eof, selectedText, flag, &lengthFound);
 
591
                pos != wxSCI_INVALID_POSITION ;
 
592
                pos = m_pOwner->GetControl()->FindText(pos+=selectedText.Len(), eof, selectedText, flag, &lengthFound) )
 
593
            {
 
594
                // does not make sense anymore: check that the found occurrence is not the same as the selected,
 
595
                // since it is not selected in the second view -> so highlight it
 
596
                m_pOwner->m_pControl->IndicatorFillRange(pos, lengthFound);
 
597
            }
271
598
        }
272
599
    }
273
600
 
297
624
const int idEdit = wxNewId();
298
625
const int idUndo = wxNewId();
299
626
const int idRedo = wxNewId();
 
627
const int idClearHistory = wxNewId();
300
628
const int idCut = wxNewId();
301
629
const int idCopy = wxNewId();
302
630
const int idPaste = wxNewId();
323
651
const int idUnsplit = wxNewId();
324
652
const int idConfigureEditor = wxNewId();
325
653
const int idProperties = wxNewId();
 
654
const int idAddFileToProject = wxNewId();
 
655
const int idRemoveFileFromProject = wxNewId();
326
656
 
327
657
const int idBookmarkAdd = wxNewId();
328
658
const int idBookmarkRemove = wxNewId();
337
667
 
338
668
    EVT_MENU(idUndo, cbEditor::OnContextMenuEntry)
339
669
    EVT_MENU(idRedo, cbEditor::OnContextMenuEntry)
 
670
    EVT_MENU(idClearHistory, cbEditor::OnContextMenuEntry)
340
671
    EVT_MENU(idCut, cbEditor::OnContextMenuEntry)
341
672
    EVT_MENU(idCopy, cbEditor::OnContextMenuEntry)
342
673
    EVT_MENU(idPaste, cbEditor::OnContextMenuEntry)
356
687
    EVT_MENU(idFoldingToggleCurrent, cbEditor::OnContextMenuEntry)
357
688
    EVT_MENU(idConfigureEditor, cbEditor::OnContextMenuEntry)
358
689
    EVT_MENU(idProperties, cbEditor::OnContextMenuEntry)
 
690
    EVT_MENU(idAddFileToProject, cbEditor::OnContextMenuEntry)
 
691
    EVT_MENU(idRemoveFileFromProject, cbEditor::OnContextMenuEntry)
359
692
    EVT_MENU(idBookmarkAdd, cbEditor::OnContextMenuEntry)
360
693
    EVT_MENU(idBookmarkRemove, cbEditor::OnContextMenuEntry)
361
694
    EVT_MENU(idBreakpointAdd, cbEditor::OnContextMenuEntry)
431
764
{
432
765
    // first thing to do!
433
766
    // if we add more constructors in the future, don't forget to set this!
434
 
    m_pData = new cbEditorInternalData(this, fileLdr);
 
767
    m_pData = new cbEditorInternalData(this);//, fileLdr);
435
768
    m_pData->m_pFileLoader = fileLdr;
436
769
    m_IsBuiltinEditor = true;
437
770
 
475
808
    m_pControl->SetZoom(Manager::Get()->GetEditorManager()->GetZoom());
476
809
    m_pSizer->SetItemMinSize(m_pControl, 32, 32);
477
810
 
 
811
    // by default we show no markers, marginMasks are set explicitely in "InternalSetEditorStyleBeforeFileOpen()"
 
812
    // and/or by plugins, that use markers, like browsemarks-plugin
 
813
    m_pControl->SetMarginMask(lineMargin, 0);
 
814
    m_pControl->SetMarginMask(markerMargin, 0);
 
815
    m_pControl->SetMarginMask(changebarMargin, 0);
 
816
    m_pControl->SetMarginMask(foldingMargin, 0);
 
817
 
478
818
    SetEditorStyleBeforeFileOpen();
479
819
    m_IsOK = Open();
480
820
    SetEditorStyleAfterFileOpen();
517
857
 
518
858
cbStyledTextCtrl* cbEditor::GetControl() const
519
859
{
520
 
    // return the focused control (left or right)
 
860
    // return the last focused control (left or right)
521
861
    if (m_pControl2)
522
862
    {
523
 
        wxWindow* focused = wxWindow::FindFocus();
524
 
        if (focused == m_pControl2)
 
863
        // every time a control gets the focus it stores the actual timestamp, the timestamp defaults to 0 so the
 
864
        // greater is the timestamp of the control that had the focus last time
 
865
        // finding the focused window does not work if another control has the keyboard-focus
 
866
        if( m_pControl2->GetLastFocusTime() > m_pControl->GetLastFocusTime() )
525
867
            return m_pControl2;
526
868
    }
527
869
    return m_pControl;
567
909
        return; // we 've been here before ;)
568
910
 
569
911
    bool wasmodified = false;
570
 
    if(preserve_modified)
 
912
    if (preserve_modified)
571
913
        wasmodified = GetModified();
572
914
 
573
915
    m_pProjectFile = project_file;
587
929
        else
588
930
            m_Shortname = m_pProjectFile->file.GetFullName();
589
931
        SetEditorTitle(m_Shortname);
 
932
 
 
933
        if (!wxFileExists(m_Filename))
 
934
            m_pProjectFile->SetFileState(fvsMissing);
 
935
        else if (!wxFile::Access(m_Filename.c_str(), wxFile::write)) // readonly
 
936
            m_pProjectFile->SetFileState(fvsReadOnly);
590
937
    }
591
938
 
592
 
    if (!wxFileExists(m_Filename))
593
 
        m_pProjectFile->SetFileState(fvsMissing);
594
 
    else if (!wxFile::Access(m_Filename.c_str(), wxFile::write)) // readonly
595
 
        m_pProjectFile->SetFileState(fvsReadOnly);
596
 
 
597
939
#if 0
598
940
    wxString dbg;
599
941
    dbg << _T("[ed] Filename: ") << GetFilename() << _T('\n');
603
945
    dbg << _T("[ed] Project file: ") << (m_pProjectFile ? m_pProjectFile->relativeFilename : _T("unknown")) << _T('\n');
604
946
    Manager::Get()->GetLogManager()->DebugLog(dbg);
605
947
#endif
606
 
    if(preserve_modified)
 
948
    if (preserve_modified)
607
949
        SetModified(wasmodified);
608
950
}
609
951
 
620
962
void cbEditor::SetMarkerStyle(int marker, int markerType, wxColor fore, wxColor back)
621
963
{
622
964
    m_pControl->MarkerDefine(marker, markerType);
623
 
        m_pControl->MarkerSetForeground(marker, fore);
624
 
        m_pControl->MarkerSetBackground(marker, back);
625
 
        
626
 
        if (m_pControl2)
627
 
        {
628
 
                m_pControl2->MarkerDefine(marker, markerType);
629
 
                m_pControl2->MarkerSetForeground(marker, fore);
630
 
                m_pControl2->MarkerSetBackground(marker, back);
631
 
        }
 
965
    m_pControl->MarkerSetForeground(marker, fore);
 
966
    m_pControl->MarkerSetBackground(marker, back);
 
967
 
 
968
    if (m_pControl2)
 
969
    {
 
970
        m_pControl2->MarkerDefine(marker, markerType);
 
971
        m_pControl2->MarkerSetForeground(marker, fore);
 
972
        m_pControl2->MarkerSetBackground(marker, back);
 
973
    }
632
974
}
633
975
 
634
976
void cbEditor::UnderlineFoldedLines(bool underline)
635
977
{
636
978
    m_pControl->SetFoldFlags(underline ? 16 : 0);
637
979
    if (m_pControl2)
638
 
                m_pControl2->SetFoldFlags(underline ? 16 : 0);
 
980
        m_pControl2->SetFoldFlags(underline ? 16 : 0);
639
981
}
640
982
 
641
983
cbStyledTextCtrl* cbEditor::CreateEditor()
642
984
{
643
985
    m_ID = wxNewId();
644
986
 
645
 
    cbStyledTextCtrl* control = new cbStyledTextCtrl(this, m_ID, wxDefaultPosition, m_pControl ? wxDefaultSize : GetSize());
 
987
    // avoid gtk-critical because of sizes less than -1 (can happen with wxAuiNotebook/cbAuiNotebook)
 
988
    wxSize size = m_pControl ? wxDefaultSize : GetSize();
 
989
    size.x = std::max(size.x, -1);
 
990
    size.y = std::max(size.y, -1);
 
991
 
 
992
    cbStyledTextCtrl* control = new cbStyledTextCtrl(this, m_ID, wxDefaultPosition, size);
646
993
    control->UsePopUp(false);
647
994
 
648
995
    wxString enc_name = Manager::Get()->GetConfigManager(_T("editor"))->Read(_T("/default_encoding"), wxEmptyString);
708
1055
        wxEVT_SCI_HOTSPOT_CLICK,
709
1056
        wxEVT_SCI_HOTSPOT_DCLICK,
710
1057
        wxEVT_SCI_CALLTIP_CLICK,
 
1058
        wxEVT_SCI_AUTOCOMP_SELECTION,
 
1059
//        wxEVT_SCI_INDICATOR_CLICK,
 
1060
//        wxEVT_SCI_INDICATOR_RELEASE,
711
1061
 
712
1062
        -1 // to help enumeration of this array
713
1063
    };
750
1100
    // create the right control
751
1101
    m_pControl2 = CreateEditor();
752
1102
 
 
1103
    // update controls' look'n'feel
 
1104
    // do it here (before) document is attached, speeds up syntaxhighlighting
 
1105
    // we do not call "SetEditorStyleAfterFileOpen" here becaus it calls SetLanguage for the already loaded text inside
 
1106
    // the left control and slows down loading of large files a lot.
 
1107
    InternalSetEditorStyleBeforeFileOpen(m_pControl2);
 
1108
 
 
1109
    ConfigManager* mgr = Manager::Get()->GetConfigManager(_T("editor"));
 
1110
    SetFoldingIndicator(mgr->ReadInt(_T("/folding/indicator"), 2));
 
1111
    UnderlineFoldedLines(mgr->ReadBool(_T("/folding/underline_folded_line"), true));
 
1112
 
 
1113
    if (m_pTheme)
 
1114
        m_pTheme->Apply(m_lang, m_pControl2);
 
1115
 
753
1116
    // and make it a live copy of left control
754
1117
    m_pControl2->SetDocPointer(m_pControl->GetDocPointer());
755
1118
 
777
1140
            break;
778
1141
    }
779
1142
 
780
 
    // update controls' look'n'feel
781
 
    SetEditorStyleBeforeFileOpen();
782
1143
    SetEditorStyleAfterFileOpen();
783
 
    
784
 
    // apply syntax highlighting too
785
 
    if (m_pTheme)
786
 
        m_pTheme->Apply(m_lang, m_pControl2);
 
1144
 
787
1145
 
788
1146
    // make sure the line numbers margin is correct for the new control
789
 
    m_pControl2->SetMarginWidth(0, m_pControl->GetMarginWidth(0));
 
1147
    m_pControl2->SetMarginWidth(lineMargin, m_pControl->GetMarginWidth(lineMargin));
790
1148
 
791
1149
    Thaw();
792
1150
}
848
1206
    }
849
1207
 
850
1208
    // Folding properties.
851
 
        m_pData->mFoldingLimit = mgr->ReadBool(_T("/folding/limit"), false);
 
1209
    m_pData->mFoldingLimit = mgr->ReadBool(_T("/folding/limit"), false);
852
1210
    m_pData->mFoldingLimitLevel = mgr->ReadInt(_T("/folding/limit_level"), 1);
853
1211
 
854
1212
    // EOL properties
858
1216
 
859
1217
    InternalSetEditorStyleBeforeFileOpen(m_pControl);
860
1218
 
861
 
    SetFoldingIndicator(mgr->ReadInt(_T("/folding/indicator"), 2));
862
 
    UnderlineFoldedLines(mgr->ReadBool(_T("/folding/underline_folded_line"), true));
863
 
 
864
1219
    if (m_pControl2)
865
1220
        InternalSetEditorStyleBeforeFileOpen(m_pControl2);
866
1221
 
 
1222
    SetFoldingIndicator(mgr->ReadInt(_T("/folding/indicator"), 2));
 
1223
    UnderlineFoldedLines(mgr->ReadBool(_T("/folding/underline_folded_line"), true));
 
1224
 
867
1225
    SetLanguage( HL_AUTO );
868
1226
}
869
1227
 
880
1238
        m_pData->SetLineNumberColWidth();
881
1239
    else
882
1240
    {
883
 
        m_pControl->SetMarginWidth(0, 0);
 
1241
        m_pControl->SetMarginWidth(lineMargin, 0);
884
1242
        if (m_pControl2)
885
 
            m_pControl2->SetMarginWidth(0, 0);
 
1243
            m_pControl2->SetMarginWidth(lineMargin, 0);
886
1244
    }
887
1245
}
888
1246
 
899
1257
 
900
1258
    int pixelWidth = control->TextWidth(wxSCI_STYLE_LINENUMBER, _T("9"));
901
1259
    if (mgr->ReadBool(_T("/show_line_numbers"), true))
902
 
        control->SetMarginWidth(0, 5 * pixelWidth); // hardcoded width up to 99999 lines
 
1260
        control->SetMarginWidth(lineMargin, 5 * pixelWidth); // hardcoded width up to 99999 lines
903
1261
}
904
1262
 
905
1263
// static
933
1291
    // if user wants "Home" key to set cursor to the very beginning of line
934
1292
    if (mgr->ReadBool(_T("/simplified_home"), false))
935
1293
    {
936
 
        control->CmdKeyAssign(wxSCI_KEY_HOME, wxSCI_SCMOD_NULL, wxSCI_CMD_HOME);
 
1294
        control->CmdKeyAssign(wxSCI_KEY_HOME, wxSCI_SCMOD_NORM, wxSCI_CMD_HOME);
937
1295
        control->CmdKeyAssign(wxSCI_KEY_HOME, wxSCI_SCMOD_SHIFT, wxSCI_CMD_HOMEEXTEND);
938
1296
        control->CmdKeyAssign(wxSCI_KEY_HOME, wxSCI_SCMOD_ALT | wxSCI_SCMOD_SHIFT, wxSCI_CMD_HOMERECTEXTEND);
939
1297
    }
940
1298
    else // else set default "Home" key behavior
941
1299
    {
942
 
        control->CmdKeyAssign(wxSCI_KEY_HOME, wxSCI_SCMOD_NULL, wxSCI_CMD_VCHOME);
 
1300
        control->CmdKeyAssign(wxSCI_KEY_HOME, wxSCI_SCMOD_NORM, wxSCI_CMD_VCHOME);
943
1301
        control->CmdKeyAssign(wxSCI_KEY_HOME, wxSCI_SCMOD_SHIFT, wxSCI_CMD_VCHOMEEXTEND);
944
1302
        control->CmdKeyAssign(wxSCI_KEY_HOME, wxSCI_SCMOD_ALT | wxSCI_SCMOD_SHIFT, wxSCI_CMD_VCHOMERECTEXTEND);
945
1303
    }
946
1304
 
947
1305
    control->SetUseTabs(mgr->ReadBool(_T("/use_tab"), false));
948
 
    control->SetIndentationGuides(mgr->ReadBool(_T("/show_indent_guides"), false));
 
1306
    control->SetIndentationGuides(mgr->ReadBool(_T("/show_indent_guides"), false)?wxSCI_IV_LOOKBOTH:wxSCI_IV_NONE);
949
1307
    control->SetTabIndents(mgr->ReadBool(_T("/tab_indents"), true));
950
1308
    control->SetBackSpaceUnIndents(mgr->ReadBool(_T("/backspace_unindents"), true));
951
1309
    control->SetWrapMode(mgr->ReadBool(_T("/word_wrap"), false));
 
1310
    if(mgr->ReadBool(_T("/word_wrap_style_home_end"), true))
 
1311
    {
 
1312
        //in word wrap mode, home/end keys goto the wrap point if not already there,
 
1313
        //otherwise to the start/end of the entire line.
 
1314
        //alt+home/end go to start/end of the entire line.
 
1315
        //in unwrapped mode, there is no difference between home/end and alt+home/end
 
1316
        control->CmdKeyAssign(wxSCI_KEY_HOME,wxSCI_SCMOD_NORM,wxSCI_CMD_VCHOMEWRAP);
 
1317
        control->CmdKeyAssign(wxSCI_KEY_END,wxSCI_SCMOD_NORM,wxSCI_CMD_LINEENDWRAP);
 
1318
        control->CmdKeyAssign(wxSCI_KEY_HOME,wxSCI_SCMOD_ALT,wxSCI_CMD_VCHOME);
 
1319
        control->CmdKeyAssign(wxSCI_KEY_END,wxSCI_SCMOD_ALT,wxSCI_CMD_LINEEND);
 
1320
        control->CmdKeyAssign(wxSCI_KEY_HOME,wxSCI_SCMOD_SHIFT,wxSCI_CMD_VCHOMEWRAPEXTEND);
 
1321
        control->CmdKeyAssign(wxSCI_KEY_END,wxSCI_SCMOD_SHIFT,wxSCI_CMD_LINEENDWRAPEXTEND);
 
1322
        control->CmdKeyAssign(wxSCI_KEY_HOME,wxSCI_SCMOD_SHIFT|wxSCI_SCMOD_ALT,wxSCI_CMD_VCHOMEEXTEND);
 
1323
        control->CmdKeyAssign(wxSCI_KEY_END,wxSCI_SCMOD_SHIFT|wxSCI_SCMOD_ALT,wxSCI_CMD_LINEENDEXTEND);
 
1324
    }
 
1325
    else
 
1326
    { //in word wrap mode, home/end keys goto start/end of the entire line. alt+home/end goes to wrap points
 
1327
        control->CmdKeyAssign(wxSCI_KEY_HOME,wxSCI_SCMOD_ALT,wxSCI_CMD_VCHOMEWRAP);
 
1328
        control->CmdKeyAssign(wxSCI_KEY_END,wxSCI_SCMOD_ALT,wxSCI_CMD_LINEENDWRAP);
 
1329
        control->CmdKeyAssign(wxSCI_KEY_HOME,wxSCI_SCMOD_SHIFT|wxSCI_SCMOD_ALT,wxSCI_CMD_VCHOMEWRAPEXTEND);
 
1330
        control->CmdKeyAssign(wxSCI_KEY_END,wxSCI_SCMOD_SHIFT|wxSCI_SCMOD_ALT,wxSCI_CMD_LINEENDWRAPEXTEND);
 
1331
    }
952
1332
    control->SetViewEOL(mgr->ReadBool(_T("/show_eol"), false));
953
1333
    control->SetViewWhiteSpace(mgr->ReadInt(_T("/view_whitespace"), 0));
954
1334
    //gutter
963
1343
 
964
1344
    // margin for bookmarks, breakpoints etc.
965
1345
    // FIXME: how to display a mark with an offset???
966
 
    control->SetMarginWidth(1, 16);
967
 
    control->SetMarginType(1, wxSCI_MARGIN_SYMBOL);
968
 
    control->SetMarginSensitive(1, mgr->ReadBool(_T("/margin_1_sensitive"), true));
969
 
    control->SetMarginMask(1, (1 << BOOKMARK_MARKER) |
970
 
                                 (1 << BREAKPOINT_MARKER) |
971
 
                                 (1 << DEBUG_MARKER) |
972
 
                                 (1 << ERROR_MARKER));
 
1346
    control->SetMarginWidth(markerMargin, 16);
 
1347
    control->SetMarginType(markerMargin, wxSCI_MARGIN_SYMBOL);
 
1348
    control->SetMarginSensitive(markerMargin, mgr->ReadBool(_T("/margin_1_sensitive"), true));
 
1349
    // use "|" here or we might break plugins that use the margin (like browsemarks)
 
1350
    control->SetMarginMask(markerMargin, control->GetMarginMask(markerMargin) |
 
1351
                                         (1 << BOOKMARK_MARKER) |
 
1352
                                         (1 << BREAKPOINT_MARKER) |
 
1353
                                         (1 << DEBUG_MARKER) |
 
1354
                                         (1 << ERROR_MARKER));
973
1355
    control->MarkerDefine(BOOKMARK_MARKER, BOOKMARK_STYLE);
974
1356
    control->MarkerSetBackground(BOOKMARK_MARKER, wxColour(0xA0, 0xA0, 0xFF));
975
1357
    control->MarkerDefine(BREAKPOINT_MARKER, BREAKPOINT_STYLE);
993
1375
    if (mgr->ReadBool(_T("/folding/show_folds"), true))
994
1376
    {
995
1377
        control->SetFoldFlags(16);
996
 
        control->SetMarginType(2, wxSCI_MARGIN_SYMBOL);
997
 
        control->SetMarginWidth(2, 16);
998
 
        control->SetMarginMask(2, wxSCI_MASK_FOLDERS);
999
 
        control->SetMarginSensitive(2, 1);
 
1378
        control->SetMarginType(foldingMargin, wxSCI_MARGIN_SYMBOL);
 
1379
        control->SetMarginWidth(foldingMargin, 16);
 
1380
        // use "|" here or we might break plugins that use the margin (none at the moment)
 
1381
        control->SetMarginMask(foldingMargin, control->GetMarginMask(foldingMargin) |
 
1382
                                              (wxSCI_MASK_FOLDERS - ((1 << wxSCI_MARKNUM_CHANGEUNSAVED) | (1 << wxSCI_MARKNUM_CHANGESAVED))));
 
1383
        control->SetMarginSensitive(foldingMargin, 1);
1000
1384
 
1001
1385
        /*Default behaviour
1002
1386
        control->MarkerDefine(wxSCI_MARKNUM_FOLDEROPEN, wxSCI_MARK_BOXMINUS);
1023
1407
        */
1024
1408
    }
1025
1409
    else
1026
 
        control->SetMarginWidth(2, 0);
 
1410
        control->SetMarginWidth(foldingMargin, 0);
 
1411
 
 
1412
    // changebar margin
 
1413
    if (mgr->ReadBool(_T("/margin/use_changebar"), true))
 
1414
    {
 
1415
        control->SetMarginWidth(changebarMargin, 4);
 
1416
        control->SetMarginType(changebarMargin,  wxSCI_MARGIN_SYMBOL);
 
1417
        // use "|" here or we might break plugins that use the margin (none at the moment)
 
1418
        control->SetMarginMask(changebarMargin, control->GetMarginMask(changebarMargin) |
 
1419
                                                (1 << wxSCI_MARKNUM_CHANGEUNSAVED) | (1 << wxSCI_MARKNUM_CHANGESAVED) );
 
1420
 
 
1421
        control->MarkerDefine(wxSCI_MARKNUM_CHANGEUNSAVED, wxSCI_MARK_LEFTRECT);
 
1422
        control->MarkerSetBackground(wxSCI_MARKNUM_CHANGEUNSAVED, wxColour(0xFF, 0xE6, 0x04));
 
1423
        control->MarkerDefine(wxSCI_MARKNUM_CHANGESAVED, wxSCI_MARK_LEFTRECT);
 
1424
        control->MarkerSetBackground(wxSCI_MARKNUM_CHANGESAVED, wxColour(0x04, 0xFF, 0x50));
 
1425
    }
 
1426
    else
 
1427
        control->SetMarginWidth(changebarMargin, 0);
 
1428
 
 
1429
    control->SetScrollWidthTracking(mgr->ReadBool(_T("/margin/scroll_width_tracking"), false));
 
1430
 
 
1431
    control->SetMultipleSelection(mgr->ReadBool(_T("/selection/multi_select"), false));
 
1432
    control->SetAdditionalSelectionTyping(mgr->ReadBool(_T("/selection/multi_typing"), false));
 
1433
    if(mgr->ReadBool(_T("/selection/use_vspace"), false))
 
1434
    {
 
1435
        control->SetVirtualSpaceOptions(wxSCI_SCVS_RECTANGULARSELECTION | wxSCI_SCVS_USERACCESSIBLE);
 
1436
    }
 
1437
    else
 
1438
    {
 
1439
        control->SetVirtualSpaceOptions(wxSCI_SCVS_NONE);
 
1440
    }
1027
1441
}
1028
1442
 
1029
1443
// static
1033
1447
        return;
1034
1448
 
1035
1449
    // line numbering
1036
 
    control->SetMarginType(0, wxSCI_MARGIN_NUMBER);
 
1450
    control->SetMarginType(lineMargin, wxSCI_MARGIN_NUMBER);
1037
1451
}
1038
1452
 
1039
1453
void cbEditor::SetColourSet(EditorColourSet* theme)
1097
1511
    SetModified(true);
1098
1512
}
1099
1513
 
1100
 
bool cbEditor::Reload(bool detectEncoding)
 
1514
bool cbEditor::Reload(bool DetectEncoding)
1101
1515
{
1102
1516
    // keep current pos
1103
 
    int pos = m_pControl ? m_pControl->GetCurrentPos() : 0;
1104
 
    int pos2 = m_pControl2 ? m_pControl2->GetCurrentPos() : 0;
 
1517
    const int pos = m_pControl ? m_pControl->GetCurrentPos() : 0;
 
1518
    const int pos2 = m_pControl2 ? m_pControl2->GetCurrentPos() : 0;
1105
1519
 
1106
1520
    // call open
1107
 
    if (!Open(detectEncoding))
 
1521
    if (!Open(DetectEncoding))
 
1522
    {
1108
1523
        return false;
 
1524
    }
 
1525
    // Re-establish margin styles, width,  etc
 
1526
    SetEditorStyleAfterFileOpen();
1109
1527
 
1110
1528
    // return (if possible) to old pos
1111
1529
    if (m_pControl)
 
1530
    {
1112
1531
        m_pControl->GotoPos(pos);
 
1532
    }
1113
1533
    if (m_pControl2)
 
1534
    {
1114
1535
        m_pControl2->GotoPos(pos2);
1115
 
 
 
1536
    }
1116
1537
    return true;
1117
 
}
 
1538
} // end of Reload
1118
1539
 
1119
1540
void cbEditor::Touch()
1120
1541
{
1125
1546
{
1126
1547
    if (!m_pData)
1127
1548
        return;
1128
 
 
 
1549
#ifdef fileload_measuring
 
1550
    wxStopWatch sw;
 
1551
#endif
1129
1552
    EncodingDetector detector(m_Filename);
1130
1553
    if (!detector.IsOK())
1131
1554
        return;
1142
1565
        wxString enc_name = Manager::Get()->GetConfigManager(_T("editor"))->Read(_T("/default_encoding"), wxLocale::GetSystemEncodingName());
1143
1566
        m_pData->m_encoding = wxFontMapper::GetEncodingFromName(enc_name);
1144
1567
    }
 
1568
#ifdef fileload_measuring
 
1569
    Manager::Get()->GetLogManager()->DebugLog(F(_T("Encoding via filename took : %d ms"),(int)sw.Time()));
 
1570
#endif
1145
1571
}
1146
1572
 
1147
1573
void cbEditor::SetLanguage( HighlightLanguage lang )
1171
1597
 
1172
1598
    // open file
1173
1599
    m_pControl->SetReadOnly(false);
 
1600
 
1174
1601
    wxString st;
1175
1602
 
1176
1603
    m_pControl->ClearAll();
1184
1611
        m_pData->m_pFileLoader = Manager::Get()->GetFileManager()->Load(m_Filename, false);
1185
1612
    }
1186
1613
 
 
1614
#ifdef fileload_measuring
 
1615
    wxStopWatch sw;
 
1616
#endif
1187
1617
    EncodingDetector enc((wxByte*)m_pData->m_pFileLoader->GetData(), m_pData->m_pFileLoader->GetLength());
1188
1618
    st = enc.GetWxStr();
1189
1619
    if (detectEncoding)
1190
1620
    {
 
1621
        m_pData->m_useByteOrderMark = enc.UsesBOM();
 
1622
        m_pData->m_byteOrderMarkLength = enc.GetBOMSizeInBytes();
 
1623
        m_pData->m_encoding = enc.GetFontEncoding();
 
1624
 
1191
1625
        SetEncoding(enc.GetFontEncoding());
1192
1626
        m_pData->m_byteOrderMarkLength = enc.GetBOMSizeInBytes();
1193
1627
        SetUseBom(m_pData->m_byteOrderMarkLength > 0);
1194
1628
    }
1195
1629
 
 
1630
    ConfigManager* mgr = Manager::Get()->GetConfigManager(_T("editor"));
 
1631
#ifdef fileload_measuring
 
1632
    Manager::Get()->GetLogManager()->DebugLog(F(_T("cbEditor::Open() => Encoding detection and conversion took : %d ms"),(int)sw.Time()));
 
1633
    sw.Start();
 
1634
#endif
 
1635
 
1196
1636
    m_pControl->InsertText(0, st);
1197
 
    m_pControl->EmptyUndoBuffer();
 
1637
    m_pControl->EmptyUndoBuffer(mgr->ReadBool(_T("/margin/use_changebar"), true));
1198
1638
    m_pControl->SetModEventMask(wxSCI_MODEVENTMASKALL);
1199
1639
 
1200
1640
    // mark the file read-only, if applicable
1201
1641
    bool read_only = !wxFile::Access(m_Filename.c_str(), wxFile::write);
1202
1642
    m_pControl->SetReadOnly(read_only);
1203
 
    SetLanguage(HL_AUTO);
 
1643
//    SetLanguage(HL_AUTO); // bottleneck !!! no need to set it here, it's already done in SetEditorStyleBeforeFileOpen
1204
1644
 
1205
1645
    if (Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/folding/fold_all_on_open"), false))
1206
1646
        FoldAll();
1209
1649
    m_LastModified = fname.GetModificationTime();
1210
1650
 
1211
1651
    SetModified(false);
 
1652
 
1212
1653
    NotifyPlugins(cbEVT_EDITOR_OPEN);
1213
1654
 
1214
1655
    m_pControl->SetZoom(Manager::Get()->GetEditorManager()->GetZoom());
1220
1661
        delete m_pData->m_pFileLoader;
1221
1662
        m_pData->m_pFileLoader = 0;
1222
1663
    }
1223
 
 
 
1664
#ifdef fileload_measuring
 
1665
    Manager::Get()->GetLogManager()->DebugLog(F(_T("loading into editor needs : %d ms"),(int)sw.Time()));
 
1666
#endif
1224
1667
    return true;
1225
1668
}
1226
1669
 
1253
1696
        return SaveAs();
1254
1697
    }
1255
1698
 
 
1699
    m_pControl->BeginUndoAction();
 
1700
    NotifyPlugins(cbEVT_EDITOR_BEFORE_SAVE);
 
1701
    m_pControl->EndUndoAction();
 
1702
 
1256
1703
    if(!cbSaveToFile(m_Filename, m_pControl->GetText(),GetEncoding(),GetUseBom()))
1257
1704
    {
1258
1705
        wxString msg;
1311
1758
    {
1312
1759
        Path = mgr->Read(_T("/file_dialogs/save_file_as/directory"), Path);
1313
1760
    }
1314
 
    wxFileDialog* dlg = new wxFileDialog(Manager::Get()->GetAppWindow(),
 
1761
    wxFileDialog dlg(Manager::Get()->GetAppWindow(),
1315
1762
                                         _("Save file"),
1316
1763
                                         Path,
1317
1764
                                         fname.GetFullName(),
1318
1765
                                         Filters,
1319
 
                                         wxSAVE | wxOVERWRITE_PROMPT);
1320
 
    dlg->SetFilterIndex(StoredIndex);
1321
 
    PlaceWindow(dlg);
1322
 
    if (dlg->ShowModal() != wxID_OK)
 
1766
                                         wxFD_SAVE | wxFD_OVERWRITE_PROMPT);
 
1767
    dlg.SetFilterIndex(StoredIndex);
 
1768
    PlaceWindow(&dlg);
 
1769
    if (dlg.ShowModal() != wxID_OK)
1323
1770
    {  // cancelled out
1324
1771
        return false;
1325
1772
    }
1326
 
    m_Filename = dlg->GetPath();
 
1773
    m_Filename = dlg.GetPath();
1327
1774
    Manager::Get()->GetLogManager()->Log(m_Filename);
1328
1775
    fname.Assign(m_Filename);
1329
1776
    m_Shortname = fname.GetFullName();
1330
1777
    SetEditorTitle(m_Shortname);
 
1778
    // invalidate m_pProjectFile, because if kept, it would point to the ProjectFile with old name and
 
1779
    // cause ProjectManager::RemoveFileFromProject called via context menu to crash
 
1780
    SetProjectFile(0);
1331
1781
    //Manager::Get()->GetLogManager()->Log(mltDevDebug, "Filename=%s\nShort=%s", m_Filename.c_str(), m_Shortname.c_str());
1332
1782
    m_IsOK = true;
1333
1783
    SetModified(true);
1335
1785
    // store the last used filter and directory
1336
1786
    if(mgr)
1337
1787
    {
1338
 
        int Index = dlg->GetFilterIndex();
 
1788
        int Index = dlg.GetFilterIndex();
1339
1789
        wxString Filter;
1340
1790
        if(FileFilters::GetFilterNameFromIndex(Filters, Index, Filter))
1341
1791
        {
1342
1792
            mgr->Write(_T("/file_dialogs/save_file_as/filter"), Filter);
1343
1793
        }
1344
 
        wxString Test = dlg->GetDirectory();
1345
 
        mgr->Write(_T("/file_dialogs/save_file_as/directory"), dlg->GetDirectory());
 
1794
        wxString Test = dlg.GetDirectory();
 
1795
        mgr->Write(_T("/file_dialogs/save_file_as/directory"), dlg.GetDirectory());
1346
1796
    }
1347
 
    dlg->Destroy();
1348
1797
    return Save();
1349
1798
} // end of SaveAs
1350
1799
 
1458
1907
                wxString macro = wxGetTextFromUser(_("Please enter the text for \"") + macroName + _T("\":"), _("Macro substitution"));
1459
1908
                if (macro.IsEmpty())
1460
1909
                {
1461
 
                        canceled = true;
1462
 
                        break;
 
1910
                    canceled = true;
 
1911
                    break;
1463
1912
                }
1464
1913
                code.Replace(_T("$(") + macroName + _T(")"), macro);
1465
1914
                macroPos = code.Find(_T("$("));
1466
1915
            }
1467
 
            
 
1916
 
1468
1917
            if (canceled)
1469
 
                                break;
 
1918
                break;
1470
1919
 
1471
1920
            control->BeginUndoAction();
1472
1921
 
1473
1922
            // delete keyword
1474
 
            control->SetSelection(wordStartPos, curPos);
 
1923
            control->SetSelectionVoid(wordStartPos, curPos);
1475
1924
            control->ReplaceSelection(_T(""));
1476
1925
            curPos = wordStartPos;
1477
1926
 
1485
1934
            if (caretPos != -1)
1486
1935
            {
1487
1936
                control->SetCurrentPos(curPos + caretPos);
1488
 
                control->SetSelection(curPos + caretPos, curPos + caretPos + 1);
 
1937
                control->SetSelectionVoid(curPos + caretPos, curPos + caretPos + 1);
1489
1938
                control->ReplaceSelection(_T(""));
1490
1939
            }
1491
1940
 
1553
2002
    cbStyledTextCtrl* ctrl = GetControl();
1554
2003
    int level = ctrl->GetFoldLevel(line);
1555
2004
 
1556
 
        // The fold parameter is the type of folding action requested
1557
 
        // 0 = Unfold; 1 = Fold; 2 = Toggle folding.
 
2005
    // The fold parameter is the type of folding action requested
 
2006
    // 0 = Unfold; 1 = Fold; 2 = Toggle folding.
1558
2007
 
1559
 
        // Check if the line is a header (fold point).
 
2008
    // Check if the line is a header (fold point).
1560
2009
    if (level & wxSCI_FOLDLEVELHEADERFLAG)
1561
2010
    {
1562
 
        bool IsExpanded = ctrl->GetFoldExpanded(line);
1563
 
 
1564
 
                // If a fold/unfold request is issued when the block is already
1565
 
                // folded/unfolded, ignore the request.
1566
 
        if (fold == 0 && IsExpanded) return true;
1567
 
        if (fold == 1 && !IsExpanded) return true;
1568
 
 
1569
 
        // Apply the folding level limit only if the current block will be
1570
 
        // folded (that means it's currently expanded), folding level limiter
1571
 
        // must be enabled of course. Unfolding will not be affected.
1572
 
        if (m_pData->mFoldingLimit && IsExpanded)
1573
 
        {
1574
 
                if ((level & wxSCI_FOLDLEVELNUMBERMASK) > (wxSCI_FOLDLEVELBASE + m_pData->mFoldingLimitLevel-1))
1575
 
                                return false;
1576
 
        }
1577
 
 
1578
 
        ctrl->ToggleFold(line);
1579
 
        return true;
 
2011
        bool IsExpanded = ctrl->GetFoldExpanded(line);
 
2012
 
 
2013
        // If a fold/unfold request is issued when the block is already
 
2014
        // folded/unfolded, ignore the request.
 
2015
        if (fold == 0 && IsExpanded) return true;
 
2016
        if (fold == 1 && !IsExpanded) return true;
 
2017
 
 
2018
        // Apply the folding level limit only if the current block will be
 
2019
        // folded (that means it's currently expanded), folding level limiter
 
2020
        // must be enabled of course. Unfolding will not be affected.
 
2021
        if (m_pData->mFoldingLimit && IsExpanded)
 
2022
        {
 
2023
            if ((level & wxSCI_FOLDLEVELNUMBERMASK) > (wxSCI_FOLDLEVELBASE + m_pData->mFoldingLimitLevel-1))
 
2024
                return false;
 
2025
        }
 
2026
 
 
2027
        ctrl->ToggleFold(line);
 
2028
        return true;
1580
2029
    }
1581
2030
    return false;
1582
2031
}
1602
2051
    if(id == 0)
1603
2052
    {
1604
2053
        SetMarkerStyle(wxSCI_MARKNUM_FOLDEROPEN, wxSCI_MARK_ARROWDOWN, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1605
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDER, wxSCI_MARK_ARROW, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1606
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDERSUB, wxSCI_MARK_BACKGROUND, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1607
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDERTAIL, wxSCI_MARK_BACKGROUND, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1608
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDEREND, wxSCI_MARK_ARROW, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1609
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDEROPENMID, wxSCI_MARK_ARROWDOWN, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1610
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDERMIDTAIL, wxSCI_MARK_BACKGROUND, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2054
        SetMarkerStyle(wxSCI_MARKNUM_FOLDER, wxSCI_MARK_ARROW, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2055
        SetMarkerStyle(wxSCI_MARKNUM_FOLDERSUB, wxSCI_MARK_BACKGROUND, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2056
        SetMarkerStyle(wxSCI_MARKNUM_FOLDERTAIL, wxSCI_MARK_BACKGROUND, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2057
        SetMarkerStyle(wxSCI_MARKNUM_FOLDEREND, wxSCI_MARK_ARROW, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2058
        SetMarkerStyle(wxSCI_MARKNUM_FOLDEROPENMID, wxSCI_MARK_ARROWDOWN, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2059
        SetMarkerStyle(wxSCI_MARKNUM_FOLDERMIDTAIL, wxSCI_MARK_BACKGROUND, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1611
2060
    }
1612
2061
 
1613
2062
    //Circle
1614
2063
    else if(id == 1)
1615
2064
    {
1616
2065
        SetMarkerStyle(wxSCI_MARKNUM_FOLDEROPEN, wxSCI_MARK_CIRCLEMINUS, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1617
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDER, wxSCI_MARK_CIRCLEPLUS, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1618
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDERSUB, wxSCI_MARK_VLINE, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1619
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDERTAIL, wxSCI_MARK_LCORNERCURVE, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1620
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDEREND, wxSCI_MARK_CIRCLEPLUSCONNECTED, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1621
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDEROPENMID, wxSCI_MARK_CIRCLEMINUSCONNECTED, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1622
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDERMIDTAIL, wxSCI_MARK_TCORNER, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2066
        SetMarkerStyle(wxSCI_MARKNUM_FOLDER, wxSCI_MARK_CIRCLEPLUS, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2067
        SetMarkerStyle(wxSCI_MARKNUM_FOLDERSUB, wxSCI_MARK_VLINE, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2068
        SetMarkerStyle(wxSCI_MARKNUM_FOLDERTAIL, wxSCI_MARK_LCORNERCURVE, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2069
        SetMarkerStyle(wxSCI_MARKNUM_FOLDEREND, wxSCI_MARK_CIRCLEPLUSCONNECTED, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2070
        SetMarkerStyle(wxSCI_MARKNUM_FOLDEROPENMID, wxSCI_MARK_CIRCLEMINUSCONNECTED, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2071
        SetMarkerStyle(wxSCI_MARKNUM_FOLDERMIDTAIL, wxSCI_MARK_TCORNER, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1623
2072
    }
1624
2073
 
1625
2074
    //Square
1626
2075
    else if(id == 2)
1627
2076
    {
1628
2077
        SetMarkerStyle(wxSCI_MARKNUM_FOLDEROPEN, wxSCI_MARK_BOXMINUS, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1629
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDER, wxSCI_MARK_BOXPLUS, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1630
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDERSUB, wxSCI_MARK_VLINE, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1631
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDERTAIL, wxSCI_MARK_LCORNER, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1632
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDEREND, wxSCI_MARK_BOXPLUSCONNECTED, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1633
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDEROPENMID, wxSCI_MARK_BOXMINUSCONNECTED, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1634
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDERMIDTAIL, wxSCI_MARK_TCORNER, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2078
        SetMarkerStyle(wxSCI_MARKNUM_FOLDER, wxSCI_MARK_BOXPLUS, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2079
        SetMarkerStyle(wxSCI_MARKNUM_FOLDERSUB, wxSCI_MARK_VLINE, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2080
        SetMarkerStyle(wxSCI_MARKNUM_FOLDERTAIL, wxSCI_MARK_LCORNER, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2081
        SetMarkerStyle(wxSCI_MARKNUM_FOLDEREND, wxSCI_MARK_BOXPLUSCONNECTED, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2082
        SetMarkerStyle(wxSCI_MARKNUM_FOLDEROPENMID, wxSCI_MARK_BOXMINUSCONNECTED, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2083
        SetMarkerStyle(wxSCI_MARKNUM_FOLDERMIDTAIL, wxSCI_MARK_TCORNER, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1635
2084
    }
1636
2085
 
1637
2086
    //Simple
1638
2087
    else if(id == 3)
1639
2088
    {
1640
2089
        SetMarkerStyle(wxSCI_MARKNUM_FOLDEROPEN, wxSCI_MARK_MINUS, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1641
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDER, wxSCI_MARK_PLUS, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1642
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDERSUB, wxSCI_MARK_BACKGROUND, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1643
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDERTAIL, wxSCI_MARK_BACKGROUND, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1644
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDEREND, wxSCI_MARK_PLUS, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1645
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDEROPENMID, wxSCI_MARK_MINUS, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1646
 
                SetMarkerStyle(wxSCI_MARKNUM_FOLDERMIDTAIL, wxSCI_MARK_BACKGROUND, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2090
        SetMarkerStyle(wxSCI_MARKNUM_FOLDER, wxSCI_MARK_PLUS, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2091
        SetMarkerStyle(wxSCI_MARKNUM_FOLDERSUB, wxSCI_MARK_BACKGROUND, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2092
        SetMarkerStyle(wxSCI_MARKNUM_FOLDERTAIL, wxSCI_MARK_BACKGROUND, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2093
        SetMarkerStyle(wxSCI_MARKNUM_FOLDEREND, wxSCI_MARK_PLUS, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2094
        SetMarkerStyle(wxSCI_MARKNUM_FOLDEROPENMID, wxSCI_MARK_MINUS, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
 
2095
        SetMarkerStyle(wxSCI_MARKNUM_FOLDERMIDTAIL, wxSCI_MARK_BACKGROUND, wxColor(0xff, 0xff, 0xff), wxColor(0x80, 0x80, 0x80));
1647
2096
    }
1648
2097
}
1649
2098
 
1671
2120
void cbEditor::GotoLine(int line, bool centerOnScreen)
1672
2121
{
1673
2122
    cbStyledTextCtrl* control = GetControl();
 
2123
 
 
2124
    // Make sure the line is not folded. This is done before moving to that
 
2125
    // line because folding may change the lines layout.
 
2126
    control->EnsureVisible(line);
 
2127
 
 
2128
    // If the line or the following is a fold point it will be unfolded, in this way
 
2129
    // when the line is a function declaration (or only contains the opening brace of it [yes, that happens sometimes] )
 
2130
    // the body is shown.
 
2131
    DoFoldLine(line,0);
 
2132
    DoFoldLine(line+1,0);
 
2133
 
1674
2134
    if (centerOnScreen)
1675
2135
    {
1676
2136
        int onScreen = control->LinesOnScreen() >> 1;
1678
2138
        control->GotoLine(line + onScreen);
1679
2139
    }
1680
2140
    control->GotoLine(line);
1681
 
    UnfoldBlockFromLine(line); // make sure it's visible (not folded)
1682
2141
}
1683
2142
 
1684
2143
bool cbEditor::AddBreakpoint(int line, bool notifyDebugger)
1685
2144
{
1686
2145
    if (HasBreakpoint(line))
1687
2146
        return false;
 
2147
 
1688
2148
    if (line == -1)
1689
2149
        line = GetControl()->GetCurrentLine();
1690
2150
 
1725
2185
{
1726
2186
    if (!HasBreakpoint(line))
1727
2187
        return false;
 
2188
 
1728
2189
    if (line == -1)
1729
2190
        line = GetControl()->GetCurrentLine();
1730
2191
 
1848
2309
    GetControl()->Redo();
1849
2310
}
1850
2311
 
 
2312
void cbEditor::ClearHistory()
 
2313
{
 
2314
    cbAssert(GetControl());
 
2315
    GetControl()->EmptyUndoBuffer(Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/margin/use_changebar"), true));
 
2316
}
 
2317
 
 
2318
void cbEditor::GotoNextChanged()
 
2319
{
 
2320
    cbAssert(GetControl());
 
2321
    cbStyledTextCtrl* p_Control = GetControl();
 
2322
    int fromLine = p_Control->LineFromPosition(p_Control->GetCurrentPos());
 
2323
    int toLine = p_Control->GetLineCount() - 1;
 
2324
    if(fromLine == toLine)
 
2325
    {
 
2326
        fromLine = 0;
 
2327
    }
 
2328
    else
 
2329
    {
 
2330
        fromLine++;
 
2331
    }
 
2332
 
 
2333
    int newLine = p_Control->FindChangedLine(fromLine, toLine);
 
2334
    if(newLine != wxSCI_INVALID_POSITION)
 
2335
    {
 
2336
        p_Control->GotoLine(newLine);
 
2337
    }
 
2338
}
 
2339
 
 
2340
void cbEditor::GotoPreviousChanged()
 
2341
{
 
2342
    cbAssert(GetControl());
 
2343
    cbStyledTextCtrl* p_Control = GetControl();
 
2344
    int fromLine = p_Control->LineFromPosition(p_Control->GetCurrentPos());
 
2345
    int toLine = 0;
 
2346
    if(fromLine == toLine)
 
2347
    {
 
2348
        fromLine = p_Control->GetLineCount() - 1;
 
2349
        }
 
2350
        else
 
2351
        {
 
2352
            fromLine--;
 
2353
        }
 
2354
 
 
2355
    int newLine = p_Control->FindChangedLine(fromLine, toLine);
 
2356
    if(newLine != wxSCI_INVALID_POSITION)
 
2357
    {
 
2358
        p_Control->GotoLine(newLine);
 
2359
    }
 
2360
}
 
2361
 
 
2362
void cbEditor::SetChangeCollection(bool collectChange)
 
2363
{
 
2364
    cbAssert(GetControl());
 
2365
    GetControl()->SetChangeCollection(collectChange);
 
2366
}
 
2367
 
1851
2368
void cbEditor::Cut()
1852
2369
{
1853
2370
    cbAssert(GetControl());
1967
2484
    if (newPos == wxSCI_INVALID_POSITION)
1968
2485
    {
1969
2486
        if(currPos > 0)
 
2487
        {
1970
2488
            currPos--;
 
2489
        }
1971
2490
        newPos = control->BraceMatch(currPos);
1972
2491
    }
1973
2492
    wxChar ch = control->GetCharAt(currPos);
1975
2494
        ch == _T('}') || ch == _T(']') || ch == _T(')'))
1976
2495
    {
1977
2496
        if (newPos != wxSCI_INVALID_POSITION)
 
2497
        {
1978
2498
            control->BraceHighlight(currPos, newPos);
 
2499
            const int currColum = control->GetColumn(currPos);
 
2500
            const int newColum = control->GetColumn(newPos);
 
2501
            control->SetHighlightGuide((currColum < newColum) ? currColum :newColum);
 
2502
        }
1979
2503
        else
 
2504
        {
1980
2505
            control->BraceBadLight(currPos);
 
2506
        }
1981
2507
    }
1982
2508
    else
 
2509
    {
1983
2510
        control->BraceHighlight(-1, -1);
 
2511
    }
1984
2512
}
1985
2513
 
1986
2514
int cbEditor::GetLineIndentInSpaces(int line) const
1995
2523
    for (unsigned int i = 0; i < len; ++i)
1996
2524
    {
1997
2525
        if (text[i] == _T(' '))
 
2526
        {
1998
2527
            ++spaceCount;
 
2528
        }
1999
2529
        else if (text[i] == _T('\t'))
 
2530
        {
2000
2531
            spaceCount += control->GetTabWidth();
 
2532
        }
2001
2533
        else
 
2534
        {
2002
2535
            break;
 
2536
        }
2003
2537
    }
2004
2538
    return spaceCount;
2005
2539
}
2016
2550
    for (unsigned int i = 0; i < len; ++i)
2017
2551
    {
2018
2552
        if (text[i] == _T(' ') || text[i] == _T('\t'))
 
2553
        {
2019
2554
            indent << text[i];
 
2555
        }
2020
2556
        else
 
2557
        {
2021
2558
            break;
 
2559
        }
2022
2560
    }
2023
2561
    return indent;
2024
2562
}
2039
2577
        menu = new wxMenu;
2040
2578
        menu->Append(idUndo, _("Undo"));
2041
2579
        menu->Append(idRedo, _("Redo"));
 
2580
        menu->Append(idClearHistory, _("Clear changes history"));
2042
2581
        menu->AppendSeparator();
2043
2582
        menu->Append(idCut, _("Cut"));
2044
2583
        menu->Append(idCopy, _("Copy"));
2048
2587
        menu->Append(idUpperCase, _("UPPERCASE"));
2049
2588
        menu->Append(idLowerCase, _("lowercase"));
2050
2589
        menu->AppendSeparator();
2051
 
        menu->Append(idSelectAll, _("Select All"));
 
2590
        menu->Append(idSelectAll, _("Select all"));
2052
2591
 
2053
2592
        bool hasSel = control->GetSelectionEnd() - control->GetSelectionStart() != 0;
2054
2593
 
2055
2594
        menu->Enable(idUndo, control->CanUndo());
2056
2595
        menu->Enable(idRedo, control->CanRedo());
 
2596
        menu->Enable(idClearHistory, control->CanUndo() || control->CanRedo());
2057
2597
        menu->Enable(idCut, !control->GetReadOnly() && hasSel);
2058
2598
        menu->Enable(idCopy, hasSel);
2059
2599
 
2070
2610
    {
2071
2611
        menu = new wxMenu;
2072
2612
        menu->Append(idBookmarksToggle, _("Toggle bookmark"));
2073
 
        menu->Append(idBookmarksPrevious, _("Previous bookmark"));
2074
 
        menu->Append(idBookmarksNext, _("Next bookmark"));
 
2613
        menu->Append(idBookmarksPrevious, _("Goto previous bookmark"));
 
2614
        menu->Append(idBookmarksNext, _("Goto next bookmark"));
2075
2615
    }
2076
2616
    else if(id == idFolding)
2077
2617
    {
2078
2618
        menu = new wxMenu;
2079
2619
        menu->Append(idFoldingFoldAll, _("Fold all"));
2080
2620
        menu->Append(idFoldingUnfoldAll, _("Unfold all"));
2081
 
        menu->Append(idFoldingToggleAll, _("Toggle all folds"));
 
2621
        menu->Append(idFoldingToggleAll, _("Toggle all"));
2082
2622
        menu->AppendSeparator();
2083
2623
        menu->Append(idFoldingFoldCurrent, _("Fold current block"));
2084
2624
        menu->Append(idFoldingUnfoldCurrent, _("Unfold current block"));
2139
2679
            popup->Append(idConfigureEditor, _("Configure editor..."));
2140
2680
        popup->Append(idProperties, _("Properties..."));
2141
2681
 
 
2682
        if (Manager::Get()->GetProjectManager()->GetActiveProject()) // project must be open
 
2683
        {
 
2684
            bool isAddRemoveEnabled = true;
 
2685
            isAddRemoveEnabled = Manager::Get()->GetProjectManager()->GetActiveProject()->GetCurrentlyCompilingTarget() == 0;
 
2686
            popup->AppendSeparator();
 
2687
 
 
2688
            if (m_pProjectFile)
 
2689
            {
 
2690
                popup->Append(idRemoveFileFromProject, _("Remove file from project"));
 
2691
                popup->Enable(idRemoveFileFromProject, isAddRemoveEnabled);
 
2692
            }
 
2693
            else
 
2694
            {
 
2695
                popup->Append(idAddFileToProject, _("Add file to active project"));
 
2696
                popup->Enable(idAddFileToProject, isAddRemoveEnabled);
 
2697
            }
 
2698
        }
2142
2699
        // remove "Insert/Empty" if more than one entry
2143
2700
        wxMenu* insert = 0;
2144
2701
        wxMenuItem* insertitem = popup->FindItem(idInsert);
2162
2719
        // because here the focus has not switched yet (i.e. the left control has the focus,
2163
2720
        // but the user right-clicked inside the right control), we find out the active control differently...
2164
2721
        wxPoint clientpos(ScreenToClient(position));
2165
 
        const int margin = m_pControl->GetMarginWidth(0) + // numbers, if present
2166
 
                           m_pControl->GetMarginWidth(1) + // breakpoints, bookmarks... if present
2167
 
                           m_pControl->GetMarginWidth(2);  // folding, if present
 
2722
        const int margin = m_pControl->GetMarginWidth(lineMargin) +     // numbers, if present
 
2723
                           m_pControl->GetMarginWidth(markerMargin) +   // breakpoints, bookmarks... if present
 
2724
                           m_pControl->GetMarginWidth(foldingMargin) +  // folding, if present
 
2725
                           m_pControl->GetMarginWidth(changebarMargin); // changebar, if present
2168
2726
        wxRect r = m_pControl->GetRect();
2169
2727
 
2170
2728
        bool inside1 = r.Contains(clientpos);
2236
2794
void cbEditor::Print(bool selectionOnly, PrintColourMode pcm, bool line_numbers)
2237
2795
{
2238
2796
    // print line numbers?
2239
 
    m_pControl->SetMarginType(0, wxSCI_MARGIN_NUMBER);
 
2797
    m_pControl->SetMarginType(lineMargin, wxSCI_MARGIN_NUMBER);
2240
2798
    if (!line_numbers)
2241
2799
    {
2242
2800
        m_pControl->SetPrintMagnification(-1);
2243
 
        m_pControl->SetMarginWidth(0, 0);
 
2801
        m_pControl->SetMarginWidth(lineMargin, 0);
2244
2802
    }
2245
2803
    else
2246
2804
    {
2247
2805
        m_pControl->SetPrintMagnification(-2);
2248
 
        m_pControl->SetMarginWidth(0, 1);
 
2806
        m_pControl->SetMarginWidth(lineMargin, 1);
2249
2807
    }
2250
2808
    // never print the gutter line
2251
2809
    m_pControl->SetEdgeMode(wxSCI_EDGE_NONE);
2287
2845
    // revert line numbers and gutter settings
2288
2846
    ConfigManager* mgr = Manager::Get()->GetConfigManager(_T("editor"));
2289
2847
    if (mgr->ReadBool(_T("/show_line_numbers"), true))
2290
 
        m_pControl->SetMarginWidth(0, 48);
 
2848
        m_pControl->SetMarginWidth(lineMargin, 48);
2291
2849
    else
2292
 
        m_pControl->SetMarginWidth(0, 0);
 
2850
        m_pControl->SetMarginWidth(lineMargin, 0);
2293
2851
    m_pControl->SetEdgeMode(mgr->ReadInt(_T("/gutter/mode"), 0));
2294
2852
}
2295
2853
 
2309
2867
        control->Undo();
2310
2868
    else if (id == idRedo)
2311
2869
        control->Redo();
 
2870
    else if (id == idClearHistory)
 
2871
        control->EmptyUndoBuffer(Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/margin/use_changebar"), true));
2312
2872
    else if (id == idCut)
2313
2873
        control->Cut();
2314
2874
    else if (id == idCopy)
2367
2927
            dlg.ShowModal();
2368
2928
        }
2369
2929
    }
 
2930
    else if (id == idAddFileToProject)
 
2931
    {
 
2932
        cbProject *prj = Manager::Get()->GetProjectManager()->GetActiveProject();
 
2933
 
 
2934
        wxArrayInt targets;
 
2935
        if (Manager::Get()->GetProjectManager()->AddFileToProject(m_Filename, prj, targets) != 0)
 
2936
        {
 
2937
            ProjectFile* pf = prj->GetFileByFilename(m_Filename, false);
 
2938
            SetProjectFile(pf);
 
2939
            Manager::Get()->GetProjectManager()->RebuildTree();
 
2940
        }
 
2941
    }
 
2942
    else if (id == idRemoveFileFromProject)
 
2943
    {
 
2944
        if (m_pProjectFile)
 
2945
        {
 
2946
            cbProject *prj = m_pProjectFile->GetParentProject();
 
2947
            Manager::Get()->GetProjectManager()->RemoveFileFromProject(m_pProjectFile, prj);
 
2948
            Manager::Get()->GetProjectManager()->RebuildTree();
 
2949
        }
 
2950
    }
2370
2951
    else if (id == idBreakpointAdd)
2371
2952
        AddBreakpoint(m_pData->m_LastMarginMenuLine);
2372
2953
    else if (id == idBreakpointEdit)
2382
2963
{
2383
2964
    switch (event.GetMargin())
2384
2965
    {
2385
 
        case 1: // bookmarks and breakpoints margin
 
2966
        case markerMargin: // bookmarks and breakpoints margin
2386
2967
        {
2387
2968
            int lineYpix = event.GetPosition();
2388
2969
            int line = GetControl()->LineFromPosition(lineYpix);
2390
2971
            ToggleBreakpoint(line);
2391
2972
            break;
2392
2973
        }
2393
 
        case 2: // folding margin
 
2974
        case foldingMargin: // folding margin
2394
2975
        {
2395
2976
            int lineYpix = event.GetPosition();
2396
2977
            int line = GetControl()->LineFromPosition(lineYpix);
2408
2989
    {
2409
2990
        NotifyPlugins(cbEVT_EDITOR_UPDATE_UI);
2410
2991
        HighlightBraces(); // brace highlighting
 
2992
        m_pData->HighlightOccurrences();
2411
2993
    }
2412
2994
    OnScintillaEvent(event);
2413
2995
}
2438
3020
        if (autoIndent && currLine > 0)
2439
3021
        {
2440
3022
            wxString indent = GetLineIndentString(currLine - 1);
2441
 
            if (smartIndent)
 
3023
            if (   smartIndent
 
3024
                && (   (control->GetLexer() == wxSCI_LEX_CPP)
 
3025
                    || (control->GetLexer() == wxSCI_LEX_D)
 
3026
                    || (control->GetLexer() == wxSCI_LEX_PYTHON) ) )
2442
3027
            {
2443
 
                cbStyledTextCtrl* stc = GetControl();
2444
 
                 // if the last entered char before newline was an opening curly brace,
2445
 
                 // increase indentation level (the closing brace is handled in another block)
 
3028
                // if the last entered char before newline was an opening curly brace,
 
3029
                // increase indentation level (the closing brace is handled in another block)
2446
3030
 
2447
3031
                // SMART INDENTING - THIS IS LANGUAGE SPECIFIC, BUT CURRENTLY ONLY IMPLEMENTED FOR C/C++ AND PYTHON
2448
3032
                wxChar b = m_pData->GetLastNonWhitespaceChar();
2449
 
                switch(stc->GetLexer())
 
3033
                switch(control->GetLexer())
2450
3034
                {
2451
3035
                    case wxSCI_LEX_CPP:
 
3036
                    case wxSCI_LEX_D:
 
3037
                        {
 
3038
                            int string_style = control->GetLexer() == wxSCI_LEX_CPP ? wxSCI_C_STRING : wxSCI_D_STRING;
 
3039
 
 
3040
                            int brace_position = m_pData->GetFirstBraceInLine(string_style);
 
3041
                            if (brace_position >= 0)
 
3042
                            {
 
3043
                                if(control->GetUseTabs())
 
3044
                                {
 
3045
                                    brace_position /= control->GetTabWidth();
 
3046
                                    indent = wxString(_T('\t'), brace_position);
 
3047
                                }
 
3048
                                else
 
3049
                                    indent = wxString(_T(' '), brace_position); // n spaces
 
3050
                                break;
 
3051
                            }
 
3052
                        }
 
3053
 
2452
3054
                        if (b == _T('{'))
2453
3055
                        {
2454
 
                            if(control->GetUseTabs())
2455
 
                                indent << _T('\t'); // 1 tab
 
3056
                            int nonblankpos;
 
3057
                            wxChar c = m_pData->GetNextNonWhitespaceCharOfLine(pos, &nonblankpos);
 
3058
 
 
3059
                            if ( c != _T('}') )
 
3060
                            {
 
3061
                                if(control->GetUseTabs())
 
3062
                                    indent << _T('\t'); // 1 tab
 
3063
                                else
 
3064
                                    indent << wxString(_T(' '), control->GetTabWidth()); // n spaces
 
3065
                            }
2456
3066
                            else
2457
 
                                indent << wxString(_T(' '), control->GetTabWidth()); // n spaces
 
3067
                            {
 
3068
                                if ( pos != nonblankpos )
 
3069
                                {
 
3070
                                    control->SetCurrentPos(nonblankpos);
 
3071
                                    control->DeleteBack();
 
3072
                                }
 
3073
                            }
2458
3074
                        }
2459
3075
                        break;
2460
3076
                    case wxSCI_LEX_PYTHON:
2479
3095
    else if (ch == _T('}'))
2480
3096
    {
2481
3097
        bool smartIndent = Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/smart_indent"), true);
2482
 
        if (smartIndent)
 
3098
        if ( smartIndent && ( (control->GetLexer() == wxSCI_LEX_CPP) || (control->GetLexer() == wxSCI_LEX_D) ) )
2483
3099
        {
2484
3100
            control->BeginUndoAction();
2485
3101
            // undo block indentation, if needed
2508
3124
        }
2509
3125
    }
2510
3126
 
 
3127
    bool braceCompletion = Manager::Get()->GetConfigManager(_T("editor"))->ReadBool(_T("/brace_completion"), true);
 
3128
    if ( braceCompletion )
 
3129
    {
 
3130
        if ( control->GetLexer() == wxSCI_LEX_CPP || control->GetLexer() == wxSCI_LEX_D )
 
3131
        {
 
3132
            m_pData->DoBraceCompletion(ch );
 
3133
        }
 
3134
    }
 
3135
 
2511
3136
    OnScintillaEvent(event);
2512
3137
}
2513
3138
 
2613
3238
// generic scintilla event handler
2614
3239
void cbEditor::OnScintillaEvent(wxScintillaEvent& event)
2615
3240
{
2616
 
//      wxString txt;
 
3241
//  wxString txt;
2617
3242
//    wxEventType type = event.GetEventType();
2618
 
//      if (type == wxEVT_SCI_CHANGE) txt << _T("wxEVT_SCI_CHANGE");
2619
 
//      else if (type == wxEVT_SCI_STYLENEEDED) txt << _T("wxEVT_SCI_STYLENEEDED");
2620
 
//      else if (type == wxEVT_SCI_CHARADDED) txt << _T("wxEVT_SCI_CHARADDED");
2621
 
//      else if (type == wxEVT_SCI_SAVEPOINTREACHED) txt << _T("wxEVT_SCI_SAVEPOINTREACHED");
2622
 
//      else if (type == wxEVT_SCI_SAVEPOINTLEFT) txt << _T("wxEVT_SCI_SAVEPOINTLEFT");
2623
 
//      else if (type == wxEVT_SCI_ROMODIFYATTEMPT) txt << _T("wxEVT_SCI_ROMODIFYATTEMPT");
2624
 
//      else if (type == wxEVT_SCI_KEY) txt << _T("wxEVT_SCI_KEY");
2625
 
//      else if (type == wxEVT_SCI_DOUBLECLICK) txt << _T("wxEVT_SCI_DOUBLECLICK");
2626
 
//      else if (type == wxEVT_SCI_UPDATEUI) txt << _T("wxEVT_SCI_UPDATEUI");
2627
 
//      else if (type == wxEVT_SCI_MODIFIED) txt << _T("wxEVT_SCI_MODIFIED");
2628
 
//      else if (type == wxEVT_SCI_MACRORECORD) txt << _T("wxEVT_SCI_MACRORECORD");
2629
 
//      else if (type == wxEVT_SCI_MARGINCLICK) txt << _T("wxEVT_SCI_MARGINCLICK");
2630
 
//      else if (type == wxEVT_SCI_NEEDSHOWN) txt << _T("wxEVT_SCI_NEEDSHOWN");
2631
 
//      else if (type == wxEVT_SCI_PAINTED) txt << _T("wxEVT_SCI_PAINTED");
2632
 
//      else if (type == wxEVT_SCI_USERLISTSELECTION) txt << _T("wxEVT_SCI_USERLISTSELECTION");
2633
 
//      else if (type == wxEVT_SCI_URIDROPPED) txt << _T("wxEVT_SCI_URIDROPPED");
2634
 
//      else if (type == wxEVT_SCI_DWELLSTART) txt << _T("wxEVT_SCI_DWELLSTART");
2635
 
//      else if (type == wxEVT_SCI_DWELLEND) txt << _T("wxEVT_SCI_DWELLEND");
2636
 
//      else if (type == wxEVT_SCI_START_DRAG) txt << _T("wxEVT_SCI_START_DRAG");
2637
 
//      else if (type == wxEVT_SCI_DRAG_OVER) txt << _T("wxEVT_SCI_DRAG_OVER");
2638
 
//      else if (type == wxEVT_SCI_DO_DROP) txt << _T("wxEVT_SCI_DO_DROP");
2639
 
//      else if (type == wxEVT_SCI_ZOOM) txt << _T("wxEVT_SCI_ZOOM");
2640
 
//      else if (type == wxEVT_SCI_HOTSPOT_CLICK) txt << _T("wxEVT_SCI_HOTSPOT_CLICK");
2641
 
//      else if (type == wxEVT_SCI_HOTSPOT_DCLICK) txt << _T("wxEVT_SCI_HOTSPOT_DCLICK");
2642
 
//      else if (type == wxEVT_SCI_CALLTIP_CLICK) txt << _T("wxEVT_SCI_CALLTIP_CLICK");
 
3243
//  if (type == wxEVT_SCI_CHANGE) txt << _T("wxEVT_SCI_CHANGE");
 
3244
//  else if (type == wxEVT_SCI_STYLENEEDED) txt << _T("wxEVT_SCI_STYLENEEDED");
 
3245
//  else if (type == wxEVT_SCI_CHARADDED) txt << _T("wxEVT_SCI_CHARADDED");
 
3246
//  else if (type == wxEVT_SCI_SAVEPOINTREACHED) txt << _T("wxEVT_SCI_SAVEPOINTREACHED");
 
3247
//  else if (type == wxEVT_SCI_SAVEPOINTLEFT) txt << _T("wxEVT_SCI_SAVEPOINTLEFT");
 
3248
//  else if (type == wxEVT_SCI_ROMODIFYATTEMPT) txt << _T("wxEVT_SCI_ROMODIFYATTEMPT");
 
3249
//  else if (type == wxEVT_SCI_KEY) txt << _T("wxEVT_SCI_KEY");
 
3250
//  else if (type == wxEVT_SCI_DOUBLECLICK) txt << _T("wxEVT_SCI_DOUBLECLICK");
 
3251
//  else if (type == wxEVT_SCI_UPDATEUI) txt << _T("wxEVT_SCI_UPDATEUI");
 
3252
//  else if (type == wxEVT_SCI_MODIFIED) txt << _T("wxEVT_SCI_MODIFIED");
 
3253
//  else if (type == wxEVT_SCI_MACRORECORD) txt << _T("wxEVT_SCI_MACRORECORD");
 
3254
//  else if (type == wxEVT_SCI_MARGINCLICK) txt << _T("wxEVT_SCI_MARGINCLICK");
 
3255
//  else if (type == wxEVT_SCI_NEEDSHOWN) txt << _T("wxEVT_SCI_NEEDSHOWN");
 
3256
//  else if (type == wxEVT_SCI_PAINTED) txt << _T("wxEVT_SCI_PAINTED");
 
3257
//  else if (type == wxEVT_SCI_USERLISTSELECTION) txt << _T("wxEVT_SCI_USERLISTSELECTION");
 
3258
//  else if (type == wxEVT_SCI_URIDROPPED) txt << _T("wxEVT_SCI_URIDROPPED");
 
3259
//  else if (type == wxEVT_SCI_DWELLSTART) txt << _T("wxEVT_SCI_DWELLSTART");
 
3260
//  else if (type == wxEVT_SCI_DWELLEND) txt << _T("wxEVT_SCI_DWELLEND");
 
3261
//  else if (type == wxEVT_SCI_START_DRAG) txt << _T("wxEVT_SCI_START_DRAG");
 
3262
//  else if (type == wxEVT_SCI_DRAG_OVER) txt << _T("wxEVT_SCI_DRAG_OVER");
 
3263
//  else if (type == wxEVT_SCI_DO_DROP) txt << _T("wxEVT_SCI_DO_DROP");
 
3264
//  else if (type == wxEVT_SCI_ZOOM) txt << _T("wxEVT_SCI_ZOOM");
 
3265
//  else if (type == wxEVT_SCI_HOTSPOT_CLICK) txt << _T("wxEVT_SCI_HOTSPOT_CLICK");
 
3266
//  else if (type == wxEVT_SCI_HOTSPOT_DCLICK) txt << _T("wxEVT_SCI_HOTSPOT_DCLICK");
 
3267
//  else if (type == wxEVT_SCI_CALLTIP_CLICK) txt << _T("wxEVT_SCI_CALLTIP_CLICK");
 
3268
//  else if (type == wxEVT_SCI_AUTOCOMP_SELECTION) txt << _T("wxEVT_SCI_AUTOCOMP_SELECTION");
 
3269
//  else if (type == wxEVT_SCI_INDICATOR_CLICK) txt << _T("wxEVT_SCI_INDICATOR_CLICK");
 
3270
//  else if (type == wxEVT_SCI_INDICATOR_RELEASE) txt << _T("wxEVT_SCI_INDICATOR_RELEASE");
2643
3271
//    Manager::Get()->GetLogManager()->DebugLog(txt);
2644
3272
 
2645
3273
    // call any hooked functors
2648
3276
        EditorHooks::CallHooks(this, event);
2649
3277
    }
2650
3278
}
 
3279
 
 
3280
bool cbEditor::CanSelectAll() const
 
3281
{
 
3282
    return GetControl()->GetLength() > 0;
 
3283
}
 
3284
 
 
3285
void cbEditor::SelectAll()
 
3286
{
 
3287
    GetControl()->SelectAll();
 
3288
}