]> git.saurik.com Git - wxWidgets.git/blame - src/stc/stc.cpp.in
added virtual wxFrame::FindItemInMenuBar(): overriding it in wxMDIParentFrame allows...
[wxWidgets.git] / src / stc / stc.cpp.in
CommitLineData
f97d84a6
RD
1////////////////////////////////////////////////////////////////////////////
2// Name: stc.cpp
be5a51fb 3// Purpose: A wxWidgets implementation of Scintilla. This class is the
f97d84a6
RD
4// one meant to be used directly by wx applications. It does not
5// derive directly from the Scintilla classes, but instead
6// delegates most things to the real Scintilla class.
7// This allows the use of Scintilla without polluting the
8// namespace with all the classes and identifiers from Scintilla.
9//
10// Author: Robin Dunn
11//
12// Created: 13-Jan-2000
13// RCS-ID: $Id$
14// Copyright: (c) 2000 by Total Control Software
15// Licence: wxWindows license
16/////////////////////////////////////////////////////////////////////////////
17
54429bb3
RD
18// For compilers that support precompilation, includes "wx.h".
19#include "wx/wxprec.h"
20
21#ifdef __BORLANDC__
22 #pragma hdrstop
23#endif
24
29825f5f
PC
25#if wxUSE_STC
26
27#include "wx/stc/stc.h"
54429bb3
RD
28
29#ifndef WX_PRECOMP
29825f5f 30 #include "wx/wx.h"
54429bb3
RD
31#endif // WX_PRECOMP
32
f97d84a6
RD
33#include <ctype.h>
34
d6655166
WS
35#include "wx/tokenzr.h"
36#include "wx/mstream.h"
37#include "wx/image.h"
38#include "wx/file.h"
f97d84a6 39
f9ee2e27 40#include "ScintillaWX.h"
f97d84a6
RD
41
42//----------------------------------------------------------------------
43
10ef30eb 44const wxChar* wxSTCNameStr = wxT("stcwindow");
f97d84a6 45
451c5cc7
RD
46#ifdef MAKELONG
47#undef MAKELONG
48#endif
49
50#define MAKELONG(a, b) ((a) | ((b) << 16))
51
52
53static long wxColourAsLong(const wxColour& co) {
54 return (((long)co.Blue() << 16) |
55 ((long)co.Green() << 8) |
56 ((long)co.Red()));
57}
58
59static wxColour wxColourFromLong(long c) {
60 wxColour clr;
a5b274d7
WS
61 clr.Set((unsigned char)(c & 0xff),
62 (unsigned char)((c >> 8) & 0xff),
63 (unsigned char)((c >> 16) & 0xff));
451c5cc7
RD
64 return clr;
65}
66
67
68static wxColour wxColourFromSpec(const wxString& spec) {
5ee1d760
RD
69 // spec should be a colour name or "#RRGGBB"
70 if (spec.GetChar(0) == wxT('#')) {
dc8005e2 71
5ee1d760
RD
72 long red, green, blue;
73 red = green = blue = 0;
74 spec.Mid(1,2).ToLong(&red, 16);
75 spec.Mid(3,2).ToLong(&green, 16);
76 spec.Mid(5,2).ToLong(&blue, 16);
a5b274d7
WS
77 return wxColour((unsigned char)red,
78 (unsigned char)green,
79 (unsigned char)blue);
5ee1d760
RD
80 }
81 else
82 return wxColour(spec);
451c5cc7
RD
83}
84
85//----------------------------------------------------------------------
86
d25f5fbb
RD
87DEFINE_EVENT_TYPE( wxEVT_STC_CHANGE )
88DEFINE_EVENT_TYPE( wxEVT_STC_STYLENEEDED )
89DEFINE_EVENT_TYPE( wxEVT_STC_CHARADDED )
d25f5fbb
RD
90DEFINE_EVENT_TYPE( wxEVT_STC_SAVEPOINTREACHED )
91DEFINE_EVENT_TYPE( wxEVT_STC_SAVEPOINTLEFT )
92DEFINE_EVENT_TYPE( wxEVT_STC_ROMODIFYATTEMPT )
65ec6247 93DEFINE_EVENT_TYPE( wxEVT_STC_KEY )
d25f5fbb 94DEFINE_EVENT_TYPE( wxEVT_STC_DOUBLECLICK )
65ec6247 95DEFINE_EVENT_TYPE( wxEVT_STC_UPDATEUI )
d25f5fbb 96DEFINE_EVENT_TYPE( wxEVT_STC_MODIFIED )
d25f5fbb
RD
97DEFINE_EVENT_TYPE( wxEVT_STC_MACRORECORD )
98DEFINE_EVENT_TYPE( wxEVT_STC_MARGINCLICK )
99DEFINE_EVENT_TYPE( wxEVT_STC_NEEDSHOWN )
65ec6247
RD
100DEFINE_EVENT_TYPE( wxEVT_STC_PAINTED )
101DEFINE_EVENT_TYPE( wxEVT_STC_USERLISTSELECTION )
102DEFINE_EVENT_TYPE( wxEVT_STC_URIDROPPED )
103DEFINE_EVENT_TYPE( wxEVT_STC_DWELLSTART )
104DEFINE_EVENT_TYPE( wxEVT_STC_DWELLEND )
a29a241f
RD
105DEFINE_EVENT_TYPE( wxEVT_STC_START_DRAG )
106DEFINE_EVENT_TYPE( wxEVT_STC_DRAG_OVER )
107DEFINE_EVENT_TYPE( wxEVT_STC_DO_DROP )
a834585d 108DEFINE_EVENT_TYPE( wxEVT_STC_ZOOM )
9e730a78
RD
109DEFINE_EVENT_TYPE( wxEVT_STC_HOTSPOT_CLICK )
110DEFINE_EVENT_TYPE( wxEVT_STC_HOTSPOT_DCLICK )
111DEFINE_EVENT_TYPE( wxEVT_STC_CALLTIP_CLICK )
1e9bafca 112DEFINE_EVENT_TYPE( wxEVT_STC_AUTOCOMP_SELECTION )
9e730a78 113
d25f5fbb
RD
114
115
f97d84a6
RD
116BEGIN_EVENT_TABLE(wxStyledTextCtrl, wxControl)
117 EVT_PAINT (wxStyledTextCtrl::OnPaint)
118 EVT_SCROLLWIN (wxStyledTextCtrl::OnScrollWin)
5fa4613c 119 EVT_SCROLL (wxStyledTextCtrl::OnScroll)
f97d84a6
RD
120 EVT_SIZE (wxStyledTextCtrl::OnSize)
121 EVT_LEFT_DOWN (wxStyledTextCtrl::OnMouseLeftDown)
4ceb1196
RD
122 // Let Scintilla see the double click as a second click
123 EVT_LEFT_DCLICK (wxStyledTextCtrl::OnMouseLeftDown)
f97d84a6
RD
124 EVT_MOTION (wxStyledTextCtrl::OnMouseMove)
125 EVT_LEFT_UP (wxStyledTextCtrl::OnMouseLeftUp)
451c5cc7 126#if defined(__WXGTK__) || defined(__WXMAC__)
ddf2da08
RD
127 EVT_RIGHT_UP (wxStyledTextCtrl::OnMouseRightUp)
128#else
65ec6247 129 EVT_CONTEXT_MENU (wxStyledTextCtrl::OnContextMenu)
ddf2da08 130#endif
37d62433 131 EVT_MOUSEWHEEL (wxStyledTextCtrl::OnMouseWheel)
2b5f62a0 132 EVT_MIDDLE_UP (wxStyledTextCtrl::OnMouseMiddleUp)
f97d84a6
RD
133 EVT_CHAR (wxStyledTextCtrl::OnChar)
134 EVT_KEY_DOWN (wxStyledTextCtrl::OnKeyDown)
135 EVT_KILL_FOCUS (wxStyledTextCtrl::OnLoseFocus)
136 EVT_SET_FOCUS (wxStyledTextCtrl::OnGainFocus)
137 EVT_SYS_COLOUR_CHANGED (wxStyledTextCtrl::OnSysColourChanged)
138 EVT_ERASE_BACKGROUND (wxStyledTextCtrl::OnEraseBackground)
dd4aa550 139 EVT_MENU_RANGE (10, 16, wxStyledTextCtrl::OnMenu)
dc8005e2 140 EVT_LISTBOX_DCLICK (wxID_ANY, wxStyledTextCtrl::OnListBox)
f97d84a6
RD
141END_EVENT_TABLE()
142
143
144IMPLEMENT_CLASS(wxStyledTextCtrl, wxControl)
145IMPLEMENT_DYNAMIC_CLASS(wxStyledTextEvent, wxCommandEvent)
146
40716a51 147#ifdef LINK_LEXERS
1a2fb4cd 148// forces the linking of the lexer modules
a834585d 149int Scintilla_LinkLexers();
40716a51 150#endif
1a2fb4cd 151
f97d84a6
RD
152//----------------------------------------------------------------------
153// Constructor and Destructor
154
155wxStyledTextCtrl::wxStyledTextCtrl(wxWindow *parent,
156 wxWindowID id,
157 const wxPoint& pos,
158 const wxSize& size,
159 long style,
39c0acb6
RD
160 const wxString& name)
161{
162 m_swx = NULL;
163 Create(parent, id, pos, size, style, name);
164}
165
166
a48cb415
RD
167bool wxStyledTextCtrl::Create(wxWindow *parent,
168 wxWindowID id,
169 const wxPoint& pos,
170 const wxSize& size,
171 long style,
172 const wxString& name)
f97d84a6 173{
2659dad3 174 style |= wxVSCROLL | wxHSCROLL;
a48cb415
RD
175 if (!wxControl::Create(parent, id, pos, size,
176 style | wxWANTS_CHARS | wxCLIP_CHILDREN,
177 wxDefaultValidator, name))
178 return false;
39c0acb6 179
40716a51 180#ifdef LINK_LEXERS
a834585d 181 Scintilla_LinkLexers();
40716a51 182#endif
f97d84a6
RD
183 m_swx = new ScintillaWX(this);
184 m_stopWatch.Start();
dc8005e2 185 m_lastKeyDownConsumed = false;
5fa4613c
RD
186 m_vScrollBar = NULL;
187 m_hScrollBar = NULL;
10ef30eb
RD
188#if wxUSE_UNICODE
189 // Put Scintilla into unicode (UTF-8) mode
190 SetCodePage(wxSTC_CP_UTF8);
191#endif
8ae4f086 192
170acdc9 193 SetInitialSize(size);
f9ee2e27
RD
194
195 // Reduces flicker on GTK+/X11
196 SetBackgroundStyle(wxBG_STYLE_CUSTOM);
a48cb415 197 return true;
f97d84a6
RD
198}
199
200
201wxStyledTextCtrl::~wxStyledTextCtrl() {
202 delete m_swx;
203}
204
205
206//----------------------------------------------------------------------
207
208long wxStyledTextCtrl::SendMsg(int msg, long wp, long lp) {
209
210 return m_swx->WndProc(msg, wp, lp);
211}
212
ccfc3219
RD
213//----------------------------------------------------------------------
214
215// Set the vertical scrollbar to use instead of the ont that's built-in.
216void wxStyledTextCtrl::SetVScrollBar(wxScrollBar* bar) {
217 m_vScrollBar = bar;
218 if (bar != NULL) {
219 // ensure that the built-in scrollbar is not visible
220 SetScrollbar(wxVERTICAL, 0, 0, 0);
221 }
222}
f97d84a6 223
f97d84a6 224
ccfc3219
RD
225// Set the horizontal scrollbar to use instead of the ont that's built-in.
226void wxStyledTextCtrl::SetHScrollBar(wxScrollBar* bar) {
227 m_hScrollBar = bar;
228 if (bar != NULL) {
229 // ensure that the built-in scrollbar is not visible
230 SetScrollbar(wxHORIZONTAL, 0, 0, 0);
231 }
232}
233
f97d84a6
RD
234//----------------------------------------------------------------------
235// BEGIN generated section. The following code is automatically generated
236// by gen_iface.py from the contents of Scintilla.iface. Do not edit
237// this file. Edit stc.cpp.in or gen_iface.py instead and regenerate.
238
239%(METHOD_IMPS)s
240
241// END of generated section
242//----------------------------------------------------------------------
243
244
245// Returns the line number of the line with the caret.
246int wxStyledTextCtrl::GetCurrentLine() {
247 int line = LineFromPosition(GetCurrentPos());
248 return line;
249}
250
251
252// Extract style settings from a spec-string which is composed of one or
253// more of the following comma separated elements:
254//
255// bold turns on bold
256// italic turns on italics
5ee1d760
RD
257// fore:[name or #RRGGBB] sets the foreground colour
258// back:[name or #RRGGBB] sets the background colour
f97d84a6
RD
259// face:[facename] sets the font face name to use
260// size:[num] sets the font size in points
261// eol turns on eol filling
262// underline turns on underlining
263//
264void wxStyledTextCtrl::StyleSetSpec(int styleNum, const wxString& spec) {
265
451c5cc7 266 wxStringTokenizer tkz(spec, wxT(","));
f97d84a6
RD
267 while (tkz.HasMoreTokens()) {
268 wxString token = tkz.GetNextToken();
269
270 wxString option = token.BeforeFirst(':');
271 wxString val = token.AfterFirst(':');
272
451c5cc7 273 if (option == wxT("bold"))
f97d84a6
RD
274 StyleSetBold(styleNum, true);
275
451c5cc7 276 else if (option == wxT("italic"))
f97d84a6
RD
277 StyleSetItalic(styleNum, true);
278
451c5cc7 279 else if (option == wxT("underline"))
f97d84a6
RD
280 StyleSetUnderline(styleNum, true);
281
451c5cc7 282 else if (option == wxT("eol"))
f97d84a6
RD
283 StyleSetEOLFilled(styleNum, true);
284
451c5cc7 285 else if (option == wxT("size")) {
f97d84a6
RD
286 long points;
287 if (val.ToLong(&points))
288 StyleSetSize(styleNum, points);
289 }
290
451c5cc7 291 else if (option == wxT("face"))
f97d84a6
RD
292 StyleSetFaceName(styleNum, val);
293
451c5cc7 294 else if (option == wxT("fore"))
f97d84a6
RD
295 StyleSetForeground(styleNum, wxColourFromSpec(val));
296
451c5cc7 297 else if (option == wxT("back"))
f97d84a6
RD
298 StyleSetBackground(styleNum, wxColourFromSpec(val));
299 }
300}
301
302
303// Set style size, face, bold, italic, and underline attributes from
304// a wxFont's attributes.
305void wxStyledTextCtrl::StyleSetFont(int styleNum, wxFont& font) {
7475e814
RD
306#ifdef __WXGTK__
307 // Ensure that the native font is initialized
308 int x, y;
309 GetTextExtent(wxT("X"), &x, &y, NULL, NULL, &font);
310#endif
af0531a5
RD
311 int size = font.GetPointSize();
312 wxString faceName = font.GetFaceName();
313 bool bold = font.GetWeight() == wxBOLD;
314 bool italic = font.GetStyle() != wxNORMAL;
315 bool under = font.GetUnderlined();
c5bd09bf 316 wxFontEncoding encoding = font.GetEncoding();
af0531a5
RD
317
318 StyleSetFontAttr(styleNum, size, faceName, bold, italic, under, encoding);
f97d84a6
RD
319}
320
321// Set all font style attributes at once.
322void wxStyledTextCtrl::StyleSetFontAttr(int styleNum, int size,
323 const wxString& faceName,
324 bool bold, bool italic,
3727c043
RD
325 bool underline,
326 wxFontEncoding encoding) {
f97d84a6
RD
327 StyleSetSize(styleNum, size);
328 StyleSetFaceName(styleNum, faceName);
329 StyleSetBold(styleNum, bold);
330 StyleSetItalic(styleNum, italic);
331 StyleSetUnderline(styleNum, underline);
3727c043
RD
332 StyleSetFontEncoding(styleNum, encoding);
333}
f97d84a6 334
3727c043
RD
335
336// Set the character set of the font in a style. Converts the Scintilla
337// character set values to a wxFontEncoding.
338void wxStyledTextCtrl::StyleSetCharacterSet(int style, int characterSet)
339{
340 wxFontEncoding encoding;
341
342 // Translate the Scintilla characterSet to a wxFontEncoding
343 switch (characterSet) {
344 default:
345 case wxSTC_CHARSET_ANSI:
346 case wxSTC_CHARSET_DEFAULT:
347 encoding = wxFONTENCODING_DEFAULT;
348 break;
349
350 case wxSTC_CHARSET_BALTIC:
351 encoding = wxFONTENCODING_ISO8859_13;
352 break;
353
354 case wxSTC_CHARSET_CHINESEBIG5:
355 encoding = wxFONTENCODING_CP950;
356 break;
357
358 case wxSTC_CHARSET_EASTEUROPE:
359 encoding = wxFONTENCODING_ISO8859_2;
360 break;
361
362 case wxSTC_CHARSET_GB2312:
363 encoding = wxFONTENCODING_CP936;
364 break;
365
366 case wxSTC_CHARSET_GREEK:
367 encoding = wxFONTENCODING_ISO8859_7;
368 break;
369
370 case wxSTC_CHARSET_HANGUL:
371 encoding = wxFONTENCODING_CP949;
372 break;
373
374 case wxSTC_CHARSET_MAC:
375 encoding = wxFONTENCODING_DEFAULT;
376 break;
377
378 case wxSTC_CHARSET_OEM:
379 encoding = wxFONTENCODING_DEFAULT;
380 break;
381
382 case wxSTC_CHARSET_RUSSIAN:
383 encoding = wxFONTENCODING_KOI8;
384 break;
385
386 case wxSTC_CHARSET_SHIFTJIS:
387 encoding = wxFONTENCODING_CP932;
388 break;
389
390 case wxSTC_CHARSET_SYMBOL:
391 encoding = wxFONTENCODING_DEFAULT;
392 break;
393
394 case wxSTC_CHARSET_TURKISH:
395 encoding = wxFONTENCODING_ISO8859_9;
396 break;
397
398 case wxSTC_CHARSET_JOHAB:
399 encoding = wxFONTENCODING_DEFAULT;
400 break;
401
402 case wxSTC_CHARSET_HEBREW:
403 encoding = wxFONTENCODING_ISO8859_8;
404 break;
405
406 case wxSTC_CHARSET_ARABIC:
407 encoding = wxFONTENCODING_ISO8859_6;
408 break;
409
410 case wxSTC_CHARSET_VIETNAMESE:
411 encoding = wxFONTENCODING_DEFAULT;
412 break;
413
414 case wxSTC_CHARSET_THAI:
415 encoding = wxFONTENCODING_ISO8859_11;
416 break;
1e9bafca
RD
417
418 case wxSTC_CHARSET_CYRILLIC:
419 encoding = wxFONTENCODING_ISO8859_5;
420 break;
421
422 case wxSTC_CHARSET_8859_15:
423 encoding = wxFONTENCODING_ISO8859_15;;
424 break;
3727c043
RD
425 }
426
427 // We just have Scintilla track the wxFontEncoding for us. It gets used
428 // in Font::Create in PlatWX.cpp. We add one to the value so that the
429 // effective wxFONENCODING_DEFAULT == SC_SHARSET_DEFAULT and so when
430 // Scintilla internally uses SC_CHARSET_DEFAULT we will translate it back
431 // to wxFONENCODING_DEFAULT in Font::Create.
432 SendMsg(SCI_STYLESETCHARACTERSET, style, encoding+1);
433}
434
435
436// Set the font encoding to be used by a style.
437void wxStyledTextCtrl::StyleSetFontEncoding(int style, wxFontEncoding encoding)
438{
439 SendMsg(SCI_STYLESETCHARACTERSET, style, encoding+1);
f97d84a6
RD
440}
441
442
443// Perform one of the operations defined by the wxSTC_CMD_* constants.
444void wxStyledTextCtrl::CmdKeyExecute(int cmd) {
445 SendMsg(cmd);
446}
447
448
449// Set the left and right margin in the edit area, measured in pixels.
450void wxStyledTextCtrl::SetMargins(int left, int right) {
451 SetMarginLeft(left);
452 SetMarginRight(right);
453}
454
455
456// Retrieve the start and end positions of the current selection.
457void wxStyledTextCtrl::GetSelection(int* startPos, int* endPos) {
458 if (startPos != NULL)
459 *startPos = SendMsg(SCI_GETSELECTIONSTART);
460 if (endPos != NULL)
461 *endPos = SendMsg(SCI_GETSELECTIONEND);
462}
463
464
465// Retrieve the point in the window where a position is displayed.
466wxPoint wxStyledTextCtrl::PointFromPosition(int pos) {
467 int x = SendMsg(SCI_POINTXFROMPOSITION, 0, pos);
468 int y = SendMsg(SCI_POINTYFROMPOSITION, 0, pos);
469 return wxPoint(x, y);
470}
471
472// Scroll enough to make the given line visible
473void wxStyledTextCtrl::ScrollToLine(int line) {
474 m_swx->DoScrollToLine(line);
475}
476
477
478// Scroll enough to make the given column visible
479void wxStyledTextCtrl::ScrollToColumn(int column) {
480 m_swx->DoScrollToColumn(column);
481}
482
483
51566b0b
RD
484bool wxStyledTextCtrl::SaveFile(const wxString& filename)
485{
486 wxFile file(filename, wxFile::write);
487
488 if (!file.IsOpened())
dc8005e2 489 return false;
51566b0b 490
4a65f2c8 491 bool success = file.Write(GetText(), *wxConvCurrent);
51566b0b
RD
492
493 if (success)
494 SetSavePoint();
495
496 return success;
497}
498
499bool wxStyledTextCtrl::LoadFile(const wxString& filename)
500{
041973c5 501 bool success = false;
51566b0b
RD
502 wxFile file(filename, wxFile::read);
503
041973c5 504 if (file.IsOpened())
51566b0b 505 {
041973c5 506 wxString contents;
a5b274d7
WS
507 // get the file size (assume it is not huge file...)
508 ssize_t len = (ssize_t)file.Length();
509
041973c5
RD
510 if (len > 0)
511 {
1e545382 512#if wxUSE_UNICODE
1c26fbe0 513 wxMemoryBuffer buffer(len+1);
8e5ec9cc 514 success = (file.Read(buffer.GetData(), len) == len);
dc8005e2 515 if (success) {
9efe0302
RD
516 ((char*)buffer.GetData())[len] = 0;
517 contents = wxString(buffer, *wxConvCurrent, len);
518 }
4a65f2c8 519#else
8e5ec9cc
MB
520 wxString buffer;
521 success = (file.Read(wxStringBuffer(buffer, len), len) == len);
4a65f2c8
RD
522 contents = buffer;
523#endif
041973c5
RD
524 }
525 else
a5b274d7
WS
526 {
527 if (len == 0)
528 success = true; // empty file is ok
529 else
530 success = false; // len == wxInvalidOffset
531 }
041973c5
RD
532
533 if (success)
534 {
535 SetText(contents);
536 EmptyUndoBuffer();
537 SetSavePoint();
538 }
51566b0b
RD
539 }
540
541 return success;
542}
543
f97d84a6 544
2fcce896 545#if wxUSE_DRAG_AND_DROP
dc8005e2
RD
546wxDragResult wxStyledTextCtrl::DoDragOver(wxCoord x, wxCoord y, wxDragResult def) {
547 return m_swx->DoDragOver(x, y, def);
548}
4a65f2c8
RD
549
550
dc8005e2 551bool wxStyledTextCtrl::DoDropText(long x, long y, const wxString& data) {
4a65f2c8
RD
552 return m_swx->DoDropText(x, y, data);
553}
2fcce896 554#endif
4a65f2c8
RD
555
556
d1558f3d
RD
557void wxStyledTextCtrl::SetUseAntiAliasing(bool useAA) {
558 m_swx->SetUseAntiAliasing(useAA);
559}
560
561bool wxStyledTextCtrl::GetUseAntiAliasing() {
562 return m_swx->GetUseAntiAliasing();
563}
564
41a499cd
RD
565
566
567
568
569void wxStyledTextCtrl::AddTextRaw(const char* text)
570{
571 SendMsg(SCI_ADDTEXT, strlen(text), (long)text);
572}
573
574void wxStyledTextCtrl::InsertTextRaw(int pos, const char* text)
575{
576 SendMsg(SCI_INSERTTEXT, pos, (long)text);
577}
578
579wxCharBuffer wxStyledTextCtrl::GetCurLineRaw(int* linePos)
580{
581 int len = LineLength(GetCurrentLine());
582 if (!len) {
583 if (linePos) *linePos = 0;
584 wxCharBuffer empty;
585 return empty;
586 }
587
588 wxCharBuffer buf(len);
589 int pos = SendMsg(SCI_GETCURLINE, len, (long)buf.data());
590 if (linePos) *linePos = pos;
591 return buf;
592}
593
594wxCharBuffer wxStyledTextCtrl::GetLineRaw(int line)
595{
596 int len = LineLength(line);
597 if (!len) {
598 wxCharBuffer empty;
599 return empty;
600 }
601
602 wxCharBuffer buf(len);
603 SendMsg(SCI_GETLINE, line, (long)buf.data());
604 return buf;
605}
606
607wxCharBuffer wxStyledTextCtrl::GetSelectedTextRaw()
608{
609 int start;
610 int end;
611
612 GetSelection(&start, &end);
613 int len = end - start;
614 if (!len) {
615 wxCharBuffer empty;
616 return empty;
617 }
618
619 wxCharBuffer buf(len);
620 SendMsg(SCI_GETSELTEXT, 0, (long)buf.data());
621 return buf;
622}
623
624wxCharBuffer wxStyledTextCtrl::GetTextRangeRaw(int startPos, int endPos)
625{
626 if (endPos < startPos) {
627 int temp = startPos;
628 startPos = endPos;
629 endPos = temp;
630 }
631 int len = endPos - startPos;
632 if (!len) {
633 wxCharBuffer empty;
634 return empty;
635 }
636
637 wxCharBuffer buf(len);
638 TextRange tr;
639 tr.lpstrText = buf.data();
640 tr.chrg.cpMin = startPos;
641 tr.chrg.cpMax = endPos;
642 SendMsg(SCI_GETTEXTRANGE, 0, (long)&tr);
643 return buf;
644}
645
646void wxStyledTextCtrl::SetTextRaw(const char* text)
647{
648 SendMsg(SCI_SETTEXT, 0, (long)text);
649}
650
651wxCharBuffer wxStyledTextCtrl::GetTextRaw()
652{
653 int len = GetTextLength();
654 wxCharBuffer buf(len);
655 SendMsg(SCI_GETTEXT, len, (long)buf.data());
656 return buf;
657}
658
659void wxStyledTextCtrl::AppendTextRaw(const char* text)
660{
661 SendMsg(SCI_APPENDTEXT, strlen(text), (long)text);
662}
663
664
665
666
667
f97d84a6
RD
668//----------------------------------------------------------------------
669// Event handlers
670
88a8b04e 671void wxStyledTextCtrl::OnPaint(wxPaintEvent& WXUNUSED(evt)) {
f97d84a6 672 wxPaintDC dc(this);
9e730a78 673 m_swx->DoPaint(&dc, GetUpdateRegion().GetBox());
f97d84a6
RD
674}
675
676void wxStyledTextCtrl::OnScrollWin(wxScrollWinEvent& evt) {
677 if (evt.GetOrientation() == wxHORIZONTAL)
678 m_swx->DoHScroll(evt.GetEventType(), evt.GetPosition());
679 else
680 m_swx->DoVScroll(evt.GetEventType(), evt.GetPosition());
681}
682
5fa4613c
RD
683void wxStyledTextCtrl::OnScroll(wxScrollEvent& evt) {
684 wxScrollBar* sb = wxDynamicCast(evt.GetEventObject(), wxScrollBar);
685 if (sb) {
686 if (sb->IsVertical())
687 m_swx->DoVScroll(evt.GetEventType(), evt.GetPosition());
688 else
689 m_swx->DoHScroll(evt.GetEventType(), evt.GetPosition());
690 }
691}
692
88a8b04e 693void wxStyledTextCtrl::OnSize(wxSizeEvent& WXUNUSED(evt)) {
39c0acb6
RD
694 if (m_swx) {
695 wxSize sz = GetClientSize();
696 m_swx->DoSize(sz.x, sz.y);
697 }
f97d84a6
RD
698}
699
700void wxStyledTextCtrl::OnMouseLeftDown(wxMouseEvent& evt) {
cb1871ca 701 SetFocus();
f97d84a6 702 wxPoint pt = evt.GetPosition();
2b5f62a0 703 m_swx->DoLeftButtonDown(Point(pt.x, pt.y), m_stopWatch.Time(),
f97d84a6
RD
704 evt.ShiftDown(), evt.ControlDown(), evt.AltDown());
705}
706
707void wxStyledTextCtrl::OnMouseMove(wxMouseEvent& evt) {
708 wxPoint pt = evt.GetPosition();
2b5f62a0 709 m_swx->DoLeftButtonMove(Point(pt.x, pt.y));
f97d84a6
RD
710}
711
712void wxStyledTextCtrl::OnMouseLeftUp(wxMouseEvent& evt) {
713 wxPoint pt = evt.GetPosition();
2b5f62a0 714 m_swx->DoLeftButtonUp(Point(pt.x, pt.y), m_stopWatch.Time(),
f97d84a6
RD
715 evt.ControlDown());
716}
717
718
ddf2da08
RD
719void wxStyledTextCtrl::OnMouseRightUp(wxMouseEvent& evt) {
720 wxPoint pt = evt.GetPosition();
721 m_swx->DoContextMenu(Point(pt.x, pt.y));
722}
723
724
2b5f62a0
VZ
725void wxStyledTextCtrl::OnMouseMiddleUp(wxMouseEvent& evt) {
726 wxPoint pt = evt.GetPosition();
727 m_swx->DoMiddleButtonUp(Point(pt.x, pt.y));
728}
729
65ec6247 730void wxStyledTextCtrl::OnContextMenu(wxContextMenuEvent& evt) {
f97d84a6 731 wxPoint pt = evt.GetPosition();
65ec6247 732 ScreenToClient(&pt.x, &pt.y);
25484746
RD
733 /*
734 Show context menu at event point if it's within the window,
735 or at caret location if not
736 */
737 wxHitTest ht = this->HitTest(pt);
738 if (ht != wxHT_WINDOW_INSIDE) {
739 pt = this->PointFromPosition(this->GetCurrentPos());
740 }
f97d84a6
RD
741 m_swx->DoContextMenu(Point(pt.x, pt.y));
742}
743
37d62433
RD
744
745void wxStyledTextCtrl::OnMouseWheel(wxMouseEvent& evt) {
746 m_swx->DoMouseWheel(evt.GetWheelRotation(),
747 evt.GetWheelDelta(),
65ec6247 748 evt.GetLinesPerAction(),
9b9337da
RD
749 evt.ControlDown(),
750 evt.IsPageScroll());
37d62433
RD
751}
752
753
f97d84a6 754void wxStyledTextCtrl::OnChar(wxKeyEvent& evt) {
5fd656d5 755 // On (some?) non-US PC keyboards the AltGr key is required to enter some
f3c2c221
RD
756 // common characters. It comes to us as both Alt and Ctrl down so we need
757 // to let the char through in that case, otherwise if only ctrl or only
758 // alt let's skip it.
759 bool ctrl = evt.ControlDown();
28e0c28e
RD
760#ifdef __WXMAC__
761 // On the Mac the Alt key is just a modifier key (like Shift) so we need
762 // to allow the char events to be processed when Alt is pressed.
763 // TODO: Should we check MetaDown instead in this case?
764 bool alt = false;
765#else
f3c2c221 766 bool alt = evt.AltDown();
28e0c28e 767#endif
00c64037 768 bool skip = ((ctrl || alt) && ! (ctrl && alt));
f3c2c221 769
4358b585
VZ
770#if wxUSE_UNICODE
771 // apparently if we don't do this, Unicode keys pressed after non-char
772 // ASCII ones (e.g. Enter, Tab) are not taken into account (patch 1615989)
773 if (m_lastKeyDownConsumed && evt.GetUnicodeKey() > 255)
774 m_lastKeyDownConsumed = false;
775#endif
776
5fd656d5
RD
777 if (!m_lastKeyDownConsumed && !skip) {
778#if wxUSE_UNICODE
779 int key = evt.GetUnicodeKey();
780 bool keyOk = true;
781
782 // if the unicode key code is not really a unicode character (it may
783 // be a function key or etc., the platforms appear to always give us a
784 // small value in this case) then fallback to the ascii key code but
785 // don't do anything for function keys or etc.
1b14227e 786 if (key <= 127) {
5fd656d5 787 key = evt.GetKeyCode();
1b14227e 788 keyOk = (key <= 127);
5fd656d5
RD
789 }
790 if (keyOk) {
791 m_swx->DoAddChar(key);
792 return;
793 }
794#else
795 int key = evt.GetKeyCode();
796 if (key <= WXK_START || key > WXK_COMMAND) {
797 m_swx->DoAddChar(key);
798 return;
799 }
800#endif
f97d84a6 801 }
5fd656d5 802
f3c2c221 803 evt.Skip();
f97d84a6
RD
804}
805
d6582821 806
f97d84a6 807void wxStyledTextCtrl::OnKeyDown(wxKeyEvent& evt) {
5fd656d5 808 int processed = m_swx->DoKeyDown(evt, &m_lastKeyDownConsumed);
d6582821 809 if (!processed && !m_lastKeyDownConsumed)
f97d84a6
RD
810 evt.Skip();
811}
812
d6582821 813
b6bfd8e8 814void wxStyledTextCtrl::OnLoseFocus(wxFocusEvent& evt) {
ec830416 815 m_swx->DoLoseFocus();
b6bfd8e8 816 evt.Skip();
f97d84a6
RD
817}
818
d6582821 819
b6bfd8e8 820void wxStyledTextCtrl::OnGainFocus(wxFocusEvent& evt) {
f97d84a6 821 m_swx->DoGainFocus();
b6bfd8e8 822 evt.Skip();
f97d84a6
RD
823}
824
d6582821 825
88a8b04e 826void wxStyledTextCtrl::OnSysColourChanged(wxSysColourChangedEvent& WXUNUSED(evt)) {
f97d84a6
RD
827 m_swx->DoSysColourChange();
828}
829
d6582821 830
88a8b04e 831void wxStyledTextCtrl::OnEraseBackground(wxEraseEvent& WXUNUSED(evt)) {
f97d84a6
RD
832 // do nothing to help avoid flashing
833}
834
835
836
837void wxStyledTextCtrl::OnMenu(wxCommandEvent& evt) {
838 m_swx->DoCommand(evt.GetId());
839}
840
841
88a8b04e 842void wxStyledTextCtrl::OnListBox(wxCommandEvent& WXUNUSED(evt)) {
f97d84a6
RD
843 m_swx->DoOnListBox();
844}
845
846
8e54aaed
RD
847void wxStyledTextCtrl::OnIdle(wxIdleEvent& evt) {
848 m_swx->DoOnIdle(evt);
849}
850
851
8ae4f086
RD
852wxSize wxStyledTextCtrl::DoGetBestSize() const
853{
854 // What would be the best size for a wxSTC?
855 // Just give a reasonable minimum until something else can be figured out.
856 return wxSize(200,100);
857}
858
859
f97d84a6
RD
860//----------------------------------------------------------------------
861// Turn notifications from Scintilla into events
862
863
864void wxStyledTextCtrl::NotifyChange() {
865 wxStyledTextEvent evt(wxEVT_STC_CHANGE, GetId());
a29a241f 866 evt.SetEventObject(this);
f97d84a6
RD
867 GetEventHandler()->ProcessEvent(evt);
868}
869
2b5f62a0
VZ
870
871static void SetEventText(wxStyledTextEvent& evt, const char* text,
872 size_t length) {
873 if(!text) return;
874
1c930beb 875 evt.SetText(stc2wx(text, length));
2b5f62a0
VZ
876}
877
878
f97d84a6
RD
879void wxStyledTextCtrl::NotifyParent(SCNotification* _scn) {
880 SCNotification& scn = *_scn;
65ec6247
RD
881 wxStyledTextEvent evt(0, GetId());
882
a29a241f 883 evt.SetEventObject(this);
65ec6247
RD
884 evt.SetPosition(scn.position);
885 evt.SetKey(scn.ch);
886 evt.SetModifiers(scn.modifiers);
887
f97d84a6
RD
888 switch (scn.nmhdr.code) {
889 case SCN_STYLENEEDED:
65ec6247 890 evt.SetEventType(wxEVT_STC_STYLENEEDED);
f97d84a6 891 break;
65ec6247 892
f97d84a6 893 case SCN_CHARADDED:
65ec6247 894 evt.SetEventType(wxEVT_STC_CHARADDED);
f97d84a6 895 break;
65ec6247 896
f97d84a6 897 case SCN_SAVEPOINTREACHED:
65ec6247 898 evt.SetEventType(wxEVT_STC_SAVEPOINTREACHED);
f97d84a6 899 break;
65ec6247 900
f97d84a6 901 case SCN_SAVEPOINTLEFT:
65ec6247 902 evt.SetEventType(wxEVT_STC_SAVEPOINTLEFT);
f97d84a6 903 break;
65ec6247 904
f97d84a6 905 case SCN_MODIFYATTEMPTRO:
65ec6247
RD
906 evt.SetEventType(wxEVT_STC_ROMODIFYATTEMPT);
907 break;
908
909 case SCN_KEY:
910 evt.SetEventType(wxEVT_STC_KEY);
f97d84a6 911 break;
65ec6247 912
f97d84a6 913 case SCN_DOUBLECLICK:
65ec6247 914 evt.SetEventType(wxEVT_STC_DOUBLECLICK);
f97d84a6 915 break;
65ec6247
RD
916
917 case SCN_UPDATEUI:
918 evt.SetEventType(wxEVT_STC_UPDATEUI);
f97d84a6 919 break;
65ec6247
RD
920
921 case SCN_MODIFIED:
922 evt.SetEventType(wxEVT_STC_MODIFIED);
923 evt.SetModificationType(scn.modificationType);
2b5f62a0 924 SetEventText(evt, scn.text, scn.length);
65ec6247
RD
925 evt.SetLength(scn.length);
926 evt.SetLinesAdded(scn.linesAdded);
927 evt.SetLine(scn.line);
928 evt.SetFoldLevelNow(scn.foldLevelNow);
929 evt.SetFoldLevelPrev(scn.foldLevelPrev);
f97d84a6 930 break;
65ec6247 931
f97d84a6 932 case SCN_MACRORECORD:
65ec6247
RD
933 evt.SetEventType(wxEVT_STC_MACRORECORD);
934 evt.SetMessage(scn.message);
935 evt.SetWParam(scn.wParam);
936 evt.SetLParam(scn.lParam);
f97d84a6 937 break;
65ec6247 938
f97d84a6 939 case SCN_MARGINCLICK:
65ec6247
RD
940 evt.SetEventType(wxEVT_STC_MARGINCLICK);
941 evt.SetMargin(scn.margin);
f97d84a6 942 break;
65ec6247 943
f97d84a6 944 case SCN_NEEDSHOWN:
65ec6247
RD
945 evt.SetEventType(wxEVT_STC_NEEDSHOWN);
946 evt.SetLength(scn.length);
f97d84a6 947 break;
65ec6247 948
65ec6247
RD
949 case SCN_PAINTED:
950 evt.SetEventType(wxEVT_STC_PAINTED);
951 break;
952
0daf5e6b
RD
953 case SCN_AUTOCSELECTION:
954 evt.SetEventType(wxEVT_STC_AUTOCOMP_SELECTION);
955 evt.SetListType(scn.listType);
956 SetEventText(evt, scn.text, strlen(scn.text));
957 evt.SetPosition(scn.lParam);
958 break;
959
65ec6247
RD
960 case SCN_USERLISTSELECTION:
961 evt.SetEventType(wxEVT_STC_USERLISTSELECTION);
962 evt.SetListType(scn.listType);
2b5f62a0 963 SetEventText(evt, scn.text, strlen(scn.text));
0daf5e6b 964 evt.SetPosition(scn.lParam);
f97d84a6 965 break;
f97d84a6 966
65ec6247
RD
967 case SCN_URIDROPPED:
968 evt.SetEventType(wxEVT_STC_URIDROPPED);
2b5f62a0 969 SetEventText(evt, scn.text, strlen(scn.text));
65ec6247
RD
970 break;
971
972 case SCN_DWELLSTART:
973 evt.SetEventType(wxEVT_STC_DWELLSTART);
974 evt.SetX(scn.x);
975 evt.SetY(scn.y);
976 break;
977
978 case SCN_DWELLEND:
979 evt.SetEventType(wxEVT_STC_DWELLEND);
980 evt.SetX(scn.x);
981 evt.SetY(scn.y);
982 break;
983
a834585d
RD
984 case SCN_ZOOM:
985 evt.SetEventType(wxEVT_STC_ZOOM);
986 break;
987
9e730a78
RD
988 case SCN_HOTSPOTCLICK:
989 evt.SetEventType(wxEVT_STC_HOTSPOT_CLICK);
990 break;
991
992 case SCN_HOTSPOTDOUBLECLICK:
993 evt.SetEventType(wxEVT_STC_HOTSPOT_DCLICK);
994 break;
995
996 case SCN_CALLTIPCLICK:
997 evt.SetEventType(wxEVT_STC_CALLTIP_CLICK);
998 break;
0daf5e6b 999
65ec6247
RD
1000 default:
1001 return;
f97d84a6 1002 }
65ec6247
RD
1003
1004 GetEventHandler()->ProcessEvent(evt);
f97d84a6
RD
1005}
1006
1007
f97d84a6
RD
1008//----------------------------------------------------------------------
1009//----------------------------------------------------------------------
1010//----------------------------------------------------------------------
1011
1012wxStyledTextEvent::wxStyledTextEvent(wxEventType commandType, int id)
1013 : wxCommandEvent(commandType, id)
1014{
1015 m_position = 0;
1016 m_key = 0;
1017 m_modifiers = 0;
1018 m_modificationType = 0;
1019 m_length = 0;
1020 m_linesAdded = 0;
1021 m_line = 0;
1022 m_foldLevelNow = 0;
1023 m_foldLevelPrev = 0;
1024 m_margin = 0;
1025 m_message = 0;
1026 m_wParam = 0;
1027 m_lParam = 0;
65ec6247
RD
1028 m_listType = 0;
1029 m_x = 0;
1030 m_y = 0;
dc8005e2 1031 m_dragAllowMove = false;
92bbd64f 1032#if wxUSE_DRAG_AND_DROP
a29a241f 1033 m_dragResult = wxDragNone;
92bbd64f 1034#endif
f97d84a6
RD
1035}
1036
1037bool wxStyledTextEvent::GetShift() const { return (m_modifiers & SCI_SHIFT) != 0; }
1038bool wxStyledTextEvent::GetControl() const { return (m_modifiers & SCI_CTRL) != 0; }
1039bool wxStyledTextEvent::GetAlt() const { return (m_modifiers & SCI_ALT) != 0; }
1040
f97d84a6 1041
5fa4613c
RD
1042wxStyledTextEvent::wxStyledTextEvent(const wxStyledTextEvent& event):
1043 wxCommandEvent(event)
1044{
1045 m_position = event.m_position;
1046 m_key = event.m_key;
1047 m_modifiers = event.m_modifiers;
1048 m_modificationType = event.m_modificationType;
1049 m_text = event.m_text;
1050 m_length = event.m_length;
1051 m_linesAdded = event.m_linesAdded;
1052 m_line = event.m_line;
1053 m_foldLevelNow = event.m_foldLevelNow;
1054 m_foldLevelPrev = event.m_foldLevelPrev;
1055
1056 m_margin = event.m_margin;
1057
1058 m_message = event.m_message;
1059 m_wParam = event.m_wParam;
1060 m_lParam = event.m_lParam;
1061
1062 m_listType = event.m_listType;
1063 m_x = event.m_x;
1064 m_y = event.m_y;
f97d84a6 1065
5fa4613c
RD
1066 m_dragText = event.m_dragText;
1067 m_dragAllowMove =event.m_dragAllowMove;
92bbd64f 1068#if wxUSE_DRAG_AND_DROP
5fa4613c 1069 m_dragResult = event.m_dragResult;
92bbd64f 1070#endif
f97d84a6
RD
1071}
1072
1073//----------------------------------------------------------------------
1074//----------------------------------------------------------------------
1075
29825f5f 1076#endif // wxUSE_STC