~damien-moore/+junk/codeblocks

« back to all changes in this revision

Viewing changes to src/plugins/contrib/wxSmithSTC/stedit/src/steshell.cpp

  • Committer: Damien Moore
  • Date: 2013-10-11 14:25:27 UTC
  • Revision ID: damienlmoore@gmail.com-20131011142527-w13ki0x8yjd7973d
copy of Code::Blocks repo based on SVN rev 9395

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
///////////////////////////////////////////////////////////////////////////////
 
2
// Name:        steshell.cpp
 
3
// Purpose:     wxSTEditorShell
 
4
// Author:      John Labenski
 
5
// Modified by:
 
6
// Created:     11/05/2002
 
7
// RCS-ID:
 
8
// Copyright:   (c) John Labenski
 
9
// Licence:     wxWidgets licence
 
10
///////////////////////////////////////////////////////////////////////////////
 
11
 
 
12
#include "precomp.h"
 
13
 
 
14
#include "wx/stedit/stedit.h"
 
15
#include "wx/stedit/steshell.h"
 
16
 
 
17
//-----------------------------------------------------------------------------
 
18
// wxSTEditorShell
 
19
//-----------------------------------------------------------------------------
 
20
IMPLEMENT_DYNAMIC_CLASS(wxSTEditorShell, wxSTEditor)
 
21
 
 
22
BEGIN_EVENT_TABLE(wxSTEditorShell, wxSTEditor)
 
23
    EVT_KEY_DOWN     (          wxSTEditorShell::OnKeyDown)
 
24
    EVT_STC_UPDATEUI (wxID_ANY, wxSTEditorShell::OnSTCUpdateUI)
 
25
END_EVENT_TABLE()
 
26
 
 
27
void wxSTEditorShell::Init()
 
28
{
 
29
    m_line_history_index = 0;
 
30
    m_max_history_lines  = 100;
 
31
 
 
32
    m_max_lines          = 10000; // arbitrary, seems reasonable
 
33
    m_overflow_lines     = 2000;
 
34
 
 
35
    m_writeable_count    = 0;
 
36
}
 
37
 
 
38
bool wxSTEditorShell::Create(wxWindow *parent, wxWindowID id,
 
39
                             const wxPoint& pos, const wxSize& size,
 
40
                             long style, const wxString& name)
 
41
{
 
42
    if (!wxSTEditor::Create(parent, id, pos, size, style, name))
 
43
        return false;
 
44
 
 
45
    // set this up in case they don't want to bother with the preferences
 
46
    SetMarginWidth(STE_MARGIN_NUMBER, 0);
 
47
    SetMarginWidth(STE_MARGIN_FOLD,   0);
 
48
    SetMarginWidth(PROMPT_MARGIN,     16);
 
49
 
 
50
    SetMarginType(PROMPT_MARGIN, wxSTC_MARGIN_SYMBOL);
 
51
    SetMarginMask(PROMPT_MARGIN, 1<<PROMPT_MARKER);
 
52
    // after creation you can change this to whatever prompt you prefer
 
53
    MarkerDefine(PROMPT_MARKER, wxSTC_MARK_ARROWS, *wxBLACK, wxColour(255,255,0));
 
54
    return true;
 
55
}
 
56
 
 
57
wxSTEditorShell::~wxSTEditorShell()
 
58
{
 
59
}
 
60
 
 
61
void wxSTEditorShell::AppendText(const wxString &text)
 
62
{
 
63
    BeginWriteable();                   // make it writeable
 
64
 
 
65
    wxSTEditor::AppendText(text);       // write the text
 
66
    SetMaxLines(m_max_lines, m_overflow_lines); // check for line count overflow
 
67
    GotoPos(GetLength());               // put cursor at end
 
68
    EmptyUndoBuffer();                  // don't let them undo what you wrote!
 
69
                                        //   but they can undo their own typing
 
70
 
 
71
    EndWriteable();                     // end the writeable state
 
72
}
 
73
 
 
74
void wxSTEditorShell::SetPromptText(const wxString& text)
 
75
{
 
76
    BeginWriteable();
 
77
    int length      = GetLength();
 
78
    int prompt_line = GetPromptLine();
 
79
    int start_pos   = PositionFromLine(prompt_line);
 
80
    SetTargetStart(start_pos);
 
81
    SetTargetEnd(length);
 
82
    ReplaceTarget(text);
 
83
    GotoPos(GetLength());
 
84
    EndWriteable();
 
85
}
 
86
 
 
87
wxString wxSTEditorShell::GetPromptText()
 
88
{
 
89
    int prompt_line = GetPromptLine();
 
90
    int start_pos   = PositionFromLine(prompt_line);
 
91
    int end_pos     = GetLength();
 
92
    wxString text(GetTextRange(start_pos, end_pos));
 
93
    return text;
 
94
}
 
95
 
 
96
void wxSTEditorShell::BeginWriteable(bool make_writeable)
 
97
{
 
98
    m_writeable_count++;
 
99
    if (make_writeable && GetReadOnly())
 
100
        SetReadOnly(false);
 
101
}
 
102
void wxSTEditorShell::EndWriteable(bool check_ro)
 
103
{
 
104
    if (m_writeable_count > 0)
 
105
        m_writeable_count--;
 
106
 
 
107
    if (check_ro && (m_writeable_count == 0))
 
108
        CheckReadOnly(true);
 
109
}
 
110
 
 
111
int wxSTEditorShell::GetPromptLine()
 
112
{
 
113
    int total_lines = GetLineCount();
 
114
    return MarkerPrevious(total_lines+1, (1<<PROMPT_MARKER));
 
115
 
 
116
    // single line entry, return text on last line  FIXME - double check this
 
117
    // Scintilla doesn't complain if you enter a line greater than the length to get last prompt
 
118
    //int marker = MarkerGet(total_lines);
 
119
    //if (((marker & (1<<PROMPT_MARKER)) != 0)
 
120
    //{
 
121
    //    text = GetLineText(total_lines); //.Strip(wxString::both);
 
122
    //}
 
123
    //else
 
124
    //{
 
125
    //    int marker_line = MarkerPrevious(total_lines+1, (1<<PROMPT_MARKER));
 
126
    //}
 
127
}
 
128
 
 
129
bool wxSTEditorShell::CaretOnPromptLine(STE_CaretPos_Type option)
 
130
{
 
131
    int prompt_line = GetPromptLine();
 
132
    bool on_last    = (GetCurrentLine() >= prompt_line);
 
133
 
 
134
    //wxPrintf(wxT("Caret on last line total %d current %d onlast %d\n"), total_lines, GetCurrentLine(), (int)on_last);
 
135
 
 
136
    if (!on_last && (option != STE_CARET_MOVE_NONE))
 
137
    {
 
138
        if ((option & STE_CARET_MOVE_LASTLINE) != 0)
 
139
            GotoLine(prompt_line);
 
140
        else if ((option & STE_CARET_MOVE_ENDTEXT) != 0)
 
141
            GotoPos(GetLength());
 
142
    }
 
143
 
 
144
    return GetCurrentLine() >= prompt_line;
 
145
}
 
146
 
 
147
bool wxSTEditorShell::CheckReadOnly(bool set)
 
148
{
 
149
    bool make_ro = !CaretOnPromptLine(STE_CARET_MOVE_NONE);
 
150
 
 
151
    if (!make_ro)
 
152
    {
 
153
        // also check selection and make ro so they can't cut text not on last line
 
154
        int prompt_line = GetPromptLine();
 
155
        make_ro |= ((LineFromPosition(GetSelectionStart()) < prompt_line) ||
 
156
                    (LineFromPosition(GetSelectionEnd())   < prompt_line));
 
157
    }
 
158
 
 
159
    if (set && (make_ro != GetReadOnly()))
 
160
        SetReadOnly(make_ro);
 
161
 
 
162
    return make_ro;
 
163
}
 
164
 
 
165
bool wxSTEditorShell::CheckPrompt(bool set)
 
166
{
 
167
    int total_lines = GetLineCount();
 
168
    total_lines     = wxMax(0, total_lines-1);
 
169
    bool has_prompt = (MarkerGet(total_lines) & (1<<PROMPT_MARKER)) != 0;
 
170
 
 
171
    if (set && !has_prompt)
 
172
    {
 
173
        MarkerAdd(total_lines, PROMPT_MARKER);
 
174
        return true;
 
175
    }
 
176
 
 
177
    return has_prompt;
 
178
}
 
179
 
 
180
void wxSTEditorShell::OnSTCUpdateUI(wxStyledTextEvent &event)
 
181
{
 
182
    event.Skip();
 
183
    if (m_writeable_count == 0)
 
184
        CheckReadOnly(true);
 
185
}
 
186
 
 
187
wxString wxSTEditorShell::GetNextHistoryLine(bool forwards, const wxString &line)
 
188
{
 
189
    int count = (int)m_lineHistoryArray.GetCount();
 
190
 
 
191
    // no history, just return ""
 
192
    if (count == 0)
 
193
        return wxEmptyString;
 
194
 
 
195
    // return current one if it's different
 
196
    if ((m_line_history_index >= 0) && (m_line_history_index < count) &&
 
197
        (line != m_lineHistoryArray[m_line_history_index]))
 
198
        return m_lineHistoryArray[m_line_history_index];
 
199
 
 
200
    if (forwards)
 
201
    {
 
202
        if (m_line_history_index >= count - 1)
 
203
        {
 
204
            m_line_history_index = (int)(count - 1); // fix it up
 
205
            return wxEmptyString;
 
206
        }
 
207
 
 
208
        m_line_history_index++;
 
209
    }
 
210
    else // reverse
 
211
    {
 
212
        if (m_line_history_index < 1) // already checked for empty array
 
213
        {
 
214
            m_line_history_index = 0; // fix it up
 
215
            return wxEmptyString;
 
216
        }
 
217
 
 
218
        m_line_history_index--;
 
219
    }
 
220
 
 
221
    return m_lineHistoryArray[m_line_history_index];
 
222
}
 
223
 
 
224
void wxSTEditorShell::AddHistoryLine(const wxString& string, bool set_index_to_last)
 
225
{
 
226
    size_t count = m_lineHistoryArray.GetCount();
 
227
 
 
228
    // don't add same line twice
 
229
    if ((count > 0) && (string == m_lineHistoryArray[count-1]))
 
230
        return;
 
231
 
 
232
    m_lineHistoryArray.Add(string);
 
233
    if (set_index_to_last)
 
234
        m_line_history_index = (int)(m_lineHistoryArray.GetCount() - 1);
 
235
 
 
236
    SetMaxHistoryLines(GetMaxHistoryLines()); // remove any extra
 
237
}
 
238
 
 
239
void wxSTEditorShell::SetMaxHistoryLines(int max_lines)
 
240
{
 
241
    m_max_history_lines = max_lines;
 
242
 
 
243
    int extra = int(m_lineHistoryArray.GetCount()) - m_max_history_lines;
 
244
    if ((m_max_history_lines >= 0) && (extra > 0))
 
245
        m_lineHistoryArray.RemoveAt(0, extra);
 
246
 
 
247
    m_line_history_index = wxMin(m_line_history_index, int(m_lineHistoryArray.GetCount())-1);
 
248
}
 
249
 
 
250
bool wxSTEditorShell::SetMaxLines(int max_lines, int overflow_lines)
 
251
{
 
252
    m_max_lines      = max_lines;
 
253
    m_overflow_lines = overflow_lines;
 
254
    if (m_max_lines < 0) return false;
 
255
 
 
256
    int total_lines = GetLineCount();
 
257
    total_lines     = wxMax(0, total_lines-1);
 
258
 
 
259
    // delete lines when more than m_max_lines, you'll eventually crash otherwise
 
260
    if (total_lines > m_max_lines + m_overflow_lines)
 
261
    {
 
262
        BeginWriteable();
 
263
 
 
264
        int marker = MarkerGet(total_lines - m_max_lines);
 
265
 
 
266
        SetTargetStart(0);
 
267
        SetTargetEnd(PositionFromLine(total_lines - m_max_lines));
 
268
        ReplaceTarget(wxEmptyString);
 
269
 
 
270
        // wipe marker that has moved up if there shouldn't be a marker
 
271
        if ((marker & (1<<PROMPT_MARKER)) == 0)
 
272
            MarkerDelete(0, PROMPT_MARKER);
 
273
 
 
274
        EndWriteable();
 
275
        return true;
 
276
    }
 
277
 
 
278
    return false;
 
279
}
 
280
 
 
281
void wxSTEditorShell::OnKeyDown(wxKeyEvent &event)
 
282
{
 
283
    // don't steal any keys from the autocomplete dropdown
 
284
    if (AutoCompActive())
 
285
    {
 
286
        event.Skip(true);
 
287
        return;
 
288
    }
 
289
 
 
290
    event.Skip(false);
 
291
    CheckReadOnly(true);
 
292
 
 
293
    switch (event.GetKeyCode())
 
294
    {
 
295
        case WXK_UP : case WXK_NUMPAD_UP :
 
296
        {
 
297
            // you can scroll up through multiline entry
 
298
            int current_line = GetCurrentLine();
 
299
            int prompt_line  = GetPromptLine();
 
300
            if ((current_line < prompt_line) || (current_line > prompt_line))
 
301
                break;
 
302
 
 
303
            // up/down arrows go through the history buffer
 
304
            wxString promptText = GetPromptText();
 
305
            SetPromptText(GetNextHistoryLine(false, promptText));
 
306
            return;
 
307
        }
 
308
        case WXK_DOWN : case WXK_NUMPAD_DOWN :
 
309
        {
 
310
            // you can scroll down through multiline entry
 
311
            int total_lines  = GetLineCount();
 
312
            total_lines      = wxMax(0, total_lines - 1);
 
313
            int current_line = GetCurrentLine();
 
314
            if (current_line < total_lines)
 
315
                break;
 
316
 
 
317
            // up/down arrows go through the history buffer
 
318
            wxString promptText = GetPromptText();
 
319
            SetPromptText(GetNextHistoryLine(true, promptText));
 
320
            return;
 
321
        }
 
322
        case WXK_LEFT : case WXK_NUMPAD_LEFT :
 
323
        {
 
324
            int current_line = GetCurrentLine();
 
325
            int prompt_line  = GetPromptLine();
 
326
            if (current_line >= prompt_line)
 
327
            {
 
328
                int caret_pos = 0;
 
329
                GetCurLine(&caret_pos);
 
330
                if (caret_pos < 1)
 
331
                    return;
 
332
            }
 
333
            break;
 
334
        }
 
335
 
 
336
        case WXK_PAGEUP   : case WXK_NUMPAD_PAGEUP   :
 
337
        case WXK_PAGEDOWN : case WXK_NUMPAD_PAGEDOWN :
 
338
        case WXK_END      : case WXK_NUMPAD_END   :
 
339
        case WXK_HOME     : case WXK_NUMPAD_HOME  :
 
340
        case WXK_RIGHT    : case WXK_NUMPAD_RIGHT :
 
341
 
 
342
        case WXK_SHIFT   :
 
343
        case WXK_CONTROL :
 
344
        case WXK_ALT     :
 
345
        {
 
346
            // default processing for these keys
 
347
            event.Skip();
 
348
            return;
 
349
        }
 
350
 
 
351
        case WXK_RETURN : case WXK_NUMPAD_ENTER :
 
352
        {
 
353
            // put cursor at end if not already on the last line
 
354
            if (!CaretOnPromptLine(STE_CARET_MOVE_NONE))
 
355
            {
 
356
                GotoPos(GetLength());
 
357
                return;
 
358
            }
 
359
 
 
360
            int current_line = GetCurrentLine();
 
361
            int prompt_line  = GetPromptLine();
 
362
 
 
363
            // allow multiline entry for shift+enter
 
364
            if ((current_line >= prompt_line) && event.ShiftDown())
 
365
            {
 
366
                event.Skip();
 
367
                return;
 
368
            }
 
369
 
 
370
            wxString promptText = GetPromptText();
 
371
 
 
372
            // goto the end of the line and store the line for the history
 
373
            LineEnd();
 
374
            if (promptText.Length())
 
375
                AddHistoryLine(promptText, true);
 
376
 
 
377
            // just send the event, the receiver can do what they like
 
378
            SendEvent(wxEVT_STESHELL_ENTER, 0, GetState(), promptText);
 
379
            return;
 
380
        }
 
381
        case WXK_BACK :
 
382
        {
 
383
            // go to the end of the last line if not on last line
 
384
            if (!CaretOnPromptLine(STE_CARET_MOVE_NONE))
 
385
            {
 
386
                GotoPos(GetLength());
 
387
                return;
 
388
            }
 
389
            // don't let them backspace into previous line
 
390
            int caret_pos = 0;
 
391
            GetCurLine(&caret_pos);
 
392
            if (caret_pos < 1)
 
393
                return;
 
394
 
 
395
            break;
 
396
        }
 
397
        default : // move cursor to end if not already there
 
398
        {
 
399
            // reset history to start at most recent again
 
400
            m_line_history_index = (int)(m_lineHistoryArray.GetCount() - 1);
 
401
 
 
402
            CaretOnPromptLine(STE_CARET_MOVE_ENDTEXT);
 
403
            break;
 
404
        }
 
405
    }
 
406
 
 
407
    event.Skip();
 
408
}