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