Updated wxSTC from Scintilla 1.40 to Scintilla 1.45
[wxWidgets.git] / contrib / src / stc / stc.cpp.in
1 ////////////////////////////////////////////////////////////////////////////
2 // Name: stc.cpp
3 // Purpose: A wxWindows 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 license
16 /////////////////////////////////////////////////////////////////////////////
17
18 #include <ctype.h>
19
20 #include "wx/stc/stc.h"
21 #include "ScintillaWX.h"
22
23 #include <wx/tokenzr.h>
24
25
26 //----------------------------------------------------------------------
27
28 const wxChar* wxSTCNameStr = "stcwindow";
29
30 DEFINE_EVENT_TYPE( wxEVT_STC_CHANGE )
31 DEFINE_EVENT_TYPE( wxEVT_STC_STYLENEEDED )
32 DEFINE_EVENT_TYPE( wxEVT_STC_CHARADDED )
33 DEFINE_EVENT_TYPE( wxEVT_STC_SAVEPOINTREACHED )
34 DEFINE_EVENT_TYPE( wxEVT_STC_SAVEPOINTLEFT )
35 DEFINE_EVENT_TYPE( wxEVT_STC_ROMODIFYATTEMPT )
36 DEFINE_EVENT_TYPE( wxEVT_STC_KEY )
37 DEFINE_EVENT_TYPE( wxEVT_STC_DOUBLECLICK )
38 DEFINE_EVENT_TYPE( wxEVT_STC_UPDATEUI )
39 DEFINE_EVENT_TYPE( wxEVT_STC_MODIFIED )
40 DEFINE_EVENT_TYPE( wxEVT_STC_MACRORECORD )
41 DEFINE_EVENT_TYPE( wxEVT_STC_MARGINCLICK )
42 DEFINE_EVENT_TYPE( wxEVT_STC_NEEDSHOWN )
43 DEFINE_EVENT_TYPE( wxEVT_STC_POSCHANGED )
44 DEFINE_EVENT_TYPE( wxEVT_STC_PAINTED )
45 DEFINE_EVENT_TYPE( wxEVT_STC_USERLISTSELECTION )
46 DEFINE_EVENT_TYPE( wxEVT_STC_URIDROPPED )
47 DEFINE_EVENT_TYPE( wxEVT_STC_DWELLSTART )
48 DEFINE_EVENT_TYPE( wxEVT_STC_DWELLEND )
49 DEFINE_EVENT_TYPE( wxEVT_STC_START_DRAG )
50 DEFINE_EVENT_TYPE( wxEVT_STC_DRAG_OVER )
51 DEFINE_EVENT_TYPE( wxEVT_STC_DO_DROP )
52
53
54 BEGIN_EVENT_TABLE(wxStyledTextCtrl, wxControl)
55 EVT_PAINT (wxStyledTextCtrl::OnPaint)
56 EVT_SCROLLWIN (wxStyledTextCtrl::OnScrollWin)
57 EVT_SCROLL (wxStyledTextCtrl::OnScroll)
58 EVT_SIZE (wxStyledTextCtrl::OnSize)
59 EVT_LEFT_DOWN (wxStyledTextCtrl::OnMouseLeftDown)
60 #ifdef __WXMSW__
61 // Let Scintilla see the double click as a second click
62 EVT_LEFT_DCLICK (wxStyledTextCtrl::OnMouseLeftDown)
63 #endif
64 EVT_MOTION (wxStyledTextCtrl::OnMouseMove)
65 EVT_LEFT_UP (wxStyledTextCtrl::OnMouseLeftUp)
66 #ifdef __WXGTK__
67 EVT_RIGHT_UP (wxStyledTextCtrl::OnMouseRightUp)
68 #else
69 EVT_CONTEXT_MENU (wxStyledTextCtrl::OnContextMenu)
70 #endif
71 EVT_MOUSEWHEEL (wxStyledTextCtrl::OnMouseWheel)
72 EVT_CHAR (wxStyledTextCtrl::OnChar)
73 EVT_KEY_DOWN (wxStyledTextCtrl::OnKeyDown)
74 EVT_KILL_FOCUS (wxStyledTextCtrl::OnLoseFocus)
75 EVT_SET_FOCUS (wxStyledTextCtrl::OnGainFocus)
76 EVT_SYS_COLOUR_CHANGED (wxStyledTextCtrl::OnSysColourChanged)
77 EVT_ERASE_BACKGROUND (wxStyledTextCtrl::OnEraseBackground)
78 EVT_MENU_RANGE (-1, -1, wxStyledTextCtrl::OnMenu)
79 EVT_LISTBOX_DCLICK (-1, wxStyledTextCtrl::OnListBox)
80 END_EVENT_TABLE()
81
82
83 IMPLEMENT_CLASS(wxStyledTextCtrl, wxControl)
84 IMPLEMENT_DYNAMIC_CLASS(wxStyledTextEvent, wxCommandEvent)
85
86 // forces the linking of the lexer modules
87 int Scintilla_LinkLexers();
88
89 //----------------------------------------------------------------------
90 // Constructor and Destructor
91
92 wxStyledTextCtrl::wxStyledTextCtrl(wxWindow *parent,
93 wxWindowID id,
94 const wxPoint& pos,
95 const wxSize& size,
96 long style,
97 const wxString& name) :
98 wxControl(parent, id, pos, size,
99 style | wxVSCROLL | wxHSCROLL | wxWANTS_CHARS | wxCLIP_CHILDREN,
100 wxDefaultValidator, name)
101 {
102 Scintilla_LinkLexers();
103 m_swx = new ScintillaWX(this);
104 m_stopWatch.Start();
105 m_lastKeyDownConsumed = FALSE;
106 m_vScrollBar = NULL;
107 m_hScrollBar = NULL;
108 }
109
110
111 wxStyledTextCtrl::~wxStyledTextCtrl() {
112 delete m_swx;
113 }
114
115
116 //----------------------------------------------------------------------
117
118 long wxStyledTextCtrl::SendMsg(int msg, long wp, long lp) {
119
120 return m_swx->WndProc(msg, wp, lp);
121 }
122
123
124 #ifdef MAKELONG
125 #undef MAKELONG
126 #endif
127
128 #define MAKELONG(a, b) ((a) | ((b) << 16))
129
130
131 static long wxColourAsLong(const wxColour& co) {
132 return (((long)co.Blue() << 16) |
133 ((long)co.Green() << 8) |
134 ((long)co.Red()));
135 }
136
137 static wxColour wxColourFromLong(long c) {
138 wxColour clr;
139 clr.Set(c & 0xff, (c >> 8) & 0xff, (c >> 16) & 0xff);
140 return clr;
141 }
142
143
144 static wxColour wxColourFromSpec(const wxString& spec) {
145 // spec should be #RRGGBB
146 char* junk;
147 int red = strtol(spec.Mid(1,2), &junk, 16);
148 int green = strtol(spec.Mid(3,2), &junk, 16);
149 int blue = strtol(spec.Mid(5,2), &junk, 16);
150 return wxColour(red, green, blue);
151 }
152
153
154 //----------------------------------------------------------------------
155 // BEGIN generated section. The following code is automatically generated
156 // by gen_iface.py from the contents of Scintilla.iface. Do not edit
157 // this file. Edit stc.cpp.in or gen_iface.py instead and regenerate.
158
159 %(METHOD_IMPS)s
160
161 // END of generated section
162 //----------------------------------------------------------------------
163
164
165 // Returns the line number of the line with the caret.
166 int wxStyledTextCtrl::GetCurrentLine() {
167 int line = LineFromPosition(GetCurrentPos());
168 return line;
169 }
170
171
172 // Extract style settings from a spec-string which is composed of one or
173 // more of the following comma separated elements:
174 //
175 // bold turns on bold
176 // italic turns on italics
177 // fore:#RRGGBB sets the foreground colour
178 // back:#RRGGBB sets the background colour
179 // face:[facename] sets the font face name to use
180 // size:[num] sets the font size in points
181 // eol turns on eol filling
182 // underline turns on underlining
183 //
184 void wxStyledTextCtrl::StyleSetSpec(int styleNum, const wxString& spec) {
185
186 wxStringTokenizer tkz(spec, ",");
187 while (tkz.HasMoreTokens()) {
188 wxString token = tkz.GetNextToken();
189
190 wxString option = token.BeforeFirst(':');
191 wxString val = token.AfterFirst(':');
192
193 if (option == "bold")
194 StyleSetBold(styleNum, true);
195
196 else if (option == "italic")
197 StyleSetItalic(styleNum, true);
198
199 else if (option == "underline")
200 StyleSetUnderline(styleNum, true);
201
202 else if (option == "eol")
203 StyleSetEOLFilled(styleNum, true);
204
205 else if (option == "size") {
206 long points;
207 if (val.ToLong(&points))
208 StyleSetSize(styleNum, points);
209 }
210
211 else if (option == "face")
212 StyleSetFaceName(styleNum, val);
213
214 else if (option == "fore")
215 StyleSetForeground(styleNum, wxColourFromSpec(val));
216
217 else if (option == "back")
218 StyleSetBackground(styleNum, wxColourFromSpec(val));
219 }
220 }
221
222
223 // Set style size, face, bold, italic, and underline attributes from
224 // a wxFont's attributes.
225 void wxStyledTextCtrl::StyleSetFont(int styleNum, wxFont& font) {
226 int size = font.GetPointSize();
227 wxString faceName = font.GetFaceName();
228 bool bold = font.GetWeight() == wxBOLD;
229 bool italic = font.GetStyle() != wxNORMAL;
230 bool under = font.GetUnderlined();
231
232 // TODO: add encoding/charset mapping
233 StyleSetFontAttr(styleNum, size, faceName, bold, italic, under);
234 }
235
236 // Set all font style attributes at once.
237 void wxStyledTextCtrl::StyleSetFontAttr(int styleNum, int size,
238 const wxString& faceName,
239 bool bold, bool italic,
240 bool underline) {
241 StyleSetSize(styleNum, size);
242 StyleSetFaceName(styleNum, faceName);
243 StyleSetBold(styleNum, bold);
244 StyleSetItalic(styleNum, italic);
245 StyleSetUnderline(styleNum, underline);
246
247 // TODO: add encoding/charset mapping
248 }
249
250
251 // Perform one of the operations defined by the wxSTC_CMD_* constants.
252 void wxStyledTextCtrl::CmdKeyExecute(int cmd) {
253 SendMsg(cmd);
254 }
255
256
257 // Set the left and right margin in the edit area, measured in pixels.
258 void wxStyledTextCtrl::SetMargins(int left, int right) {
259 SetMarginLeft(left);
260 SetMarginRight(right);
261 }
262
263
264 // Retrieve the start and end positions of the current selection.
265 void wxStyledTextCtrl::GetSelection(int* startPos, int* endPos) {
266 if (startPos != NULL)
267 *startPos = SendMsg(SCI_GETSELECTIONSTART);
268 if (endPos != NULL)
269 *endPos = SendMsg(SCI_GETSELECTIONEND);
270 }
271
272
273 // Retrieve the point in the window where a position is displayed.
274 wxPoint wxStyledTextCtrl::PointFromPosition(int pos) {
275 int x = SendMsg(SCI_POINTXFROMPOSITION, 0, pos);
276 int y = SendMsg(SCI_POINTYFROMPOSITION, 0, pos);
277 return wxPoint(x, y);
278 }
279
280 // Scroll enough to make the given line visible
281 void wxStyledTextCtrl::ScrollToLine(int line) {
282 m_swx->DoScrollToLine(line);
283 }
284
285
286 // Scroll enough to make the given column visible
287 void wxStyledTextCtrl::ScrollToColumn(int column) {
288 m_swx->DoScrollToColumn(column);
289 }
290
291
292
293 //----------------------------------------------------------------------
294 // Event handlers
295
296 void wxStyledTextCtrl::OnPaint(wxPaintEvent& evt) {
297 wxPaintDC dc(this);
298 wxRegion region = GetUpdateRegion();
299
300 m_swx->DoPaint(&dc, region.GetBox());
301 }
302
303 void wxStyledTextCtrl::OnScrollWin(wxScrollWinEvent& evt) {
304 if (evt.GetOrientation() == wxHORIZONTAL)
305 m_swx->DoHScroll(evt.GetEventType(), evt.GetPosition());
306 else
307 m_swx->DoVScroll(evt.GetEventType(), evt.GetPosition());
308 }
309
310 void wxStyledTextCtrl::OnScroll(wxScrollEvent& evt) {
311 wxScrollBar* sb = wxDynamicCast(evt.GetEventObject(), wxScrollBar);
312 if (sb) {
313 if (sb->IsVertical())
314 m_swx->DoVScroll(evt.GetEventType(), evt.GetPosition());
315 else
316 m_swx->DoHScroll(evt.GetEventType(), evt.GetPosition());
317 }
318 }
319
320 void wxStyledTextCtrl::OnSize(wxSizeEvent& evt) {
321 wxSize sz = GetClientSize();
322 m_swx->DoSize(sz.x, sz.y);
323 }
324
325 void wxStyledTextCtrl::OnMouseLeftDown(wxMouseEvent& evt) {
326 wxPoint pt = evt.GetPosition();
327 m_swx->DoButtonDown(Point(pt.x, pt.y), m_stopWatch.Time(),
328 evt.ShiftDown(), evt.ControlDown(), evt.AltDown());
329 }
330
331 void wxStyledTextCtrl::OnMouseMove(wxMouseEvent& evt) {
332 wxPoint pt = evt.GetPosition();
333 m_swx->DoButtonMove(Point(pt.x, pt.y));
334 }
335
336 void wxStyledTextCtrl::OnMouseLeftUp(wxMouseEvent& evt) {
337 wxPoint pt = evt.GetPosition();
338 m_swx->DoButtonUp(Point(pt.x, pt.y), m_stopWatch.Time(),
339 evt.ControlDown());
340 }
341
342
343 void wxStyledTextCtrl::OnMouseRightUp(wxMouseEvent& evt) {
344 wxPoint pt = evt.GetPosition();
345 m_swx->DoContextMenu(Point(pt.x, pt.y));
346 }
347
348
349 void wxStyledTextCtrl::OnContextMenu(wxContextMenuEvent& evt) {
350 wxPoint pt = evt.GetPosition();
351 ScreenToClient(&pt.x, &pt.y);
352 m_swx->DoContextMenu(Point(pt.x, pt.y));
353 }
354
355
356 void wxStyledTextCtrl::OnMouseWheel(wxMouseEvent& evt) {
357 m_swx->DoMouseWheel(evt.GetWheelRotation(),
358 evt.GetWheelDelta(),
359 evt.GetLinesPerAction(),
360 evt.ControlDown());
361 }
362
363
364 void wxStyledTextCtrl::OnChar(wxKeyEvent& evt) {
365 long key = evt.KeyCode();
366
367 // printf("OnChar key:%%d consumed:%%d ctrl:%%d alt:%%d\n",
368 // key, m_lastKeyDownConsumed, evt.ControlDown(), evt.AltDown());
369
370 // AltGr keys???
371 // \|@#¬[]{}?£$~ ã,õ,Ã,Õ, ñ, Ñ
372
373 // On (some?) non-US keyboards the AltGr key is required to enter some
374 // common characters. It comes to us as both Alt and Ctrl down so we need
375 // to let the char through in that case, otherwise if only ctrl or only
376 // alt let's skip it.
377 bool ctrl = evt.ControlDown();
378 bool alt = evt.AltDown();
379 bool skip = ((ctrl || alt) && ! (ctrl && alt));
380
381 if (key <= 0xff && key >= 32 && !m_lastKeyDownConsumed && !skip) {
382 m_swx->DoAddChar(key);
383 return;
384 }
385 evt.Skip();
386 }
387
388
389 void wxStyledTextCtrl::OnKeyDown(wxKeyEvent& evt) {
390 long key = evt.KeyCode();
391 bool shift = evt.ShiftDown(),
392 ctrl = evt.ControlDown(),
393 alt = evt.AltDown();
394
395 int processed = m_swx->DoKeyDown(key, shift, ctrl, alt, &m_lastKeyDownConsumed);
396
397 // printf("key: %%d shift: %%d ctrl: %%d alt: %%d processed: %%d consumed: %%d\n",
398 // key, shift, ctrl, alt, processed, m_lastKeyDownConsumed);
399
400 if (!processed && !m_lastKeyDownConsumed)
401 evt.Skip();
402 }
403
404
405 void wxStyledTextCtrl::OnLoseFocus(wxFocusEvent& evt) {
406 m_swx->DoLoseFocus();
407 }
408
409
410 void wxStyledTextCtrl::OnGainFocus(wxFocusEvent& evt) {
411 m_swx->DoGainFocus();
412 }
413
414
415 void wxStyledTextCtrl::OnSysColourChanged(wxSysColourChangedEvent& evt) {
416 m_swx->DoSysColourChange();
417 }
418
419
420 void wxStyledTextCtrl::OnEraseBackground(wxEraseEvent& evt) {
421 // do nothing to help avoid flashing
422 }
423
424
425
426 void wxStyledTextCtrl::OnMenu(wxCommandEvent& evt) {
427 m_swx->DoCommand(evt.GetId());
428 }
429
430
431 void wxStyledTextCtrl::OnListBox(wxCommandEvent& evt) {
432 m_swx->DoOnListBox();
433 }
434
435
436 //----------------------------------------------------------------------
437 // Turn notifications from Scintilla into events
438
439
440 void wxStyledTextCtrl::NotifyChange() {
441 wxStyledTextEvent evt(wxEVT_STC_CHANGE, GetId());
442 evt.SetEventObject(this);
443 GetEventHandler()->ProcessEvent(evt);
444 }
445
446 void wxStyledTextCtrl::NotifyParent(SCNotification* _scn) {
447 SCNotification& scn = *_scn;
448 wxStyledTextEvent evt(0, GetId());
449
450 evt.SetEventObject(this);
451 evt.SetPosition(scn.position);
452 evt.SetKey(scn.ch);
453 evt.SetModifiers(scn.modifiers);
454
455 switch (scn.nmhdr.code) {
456 case SCN_STYLENEEDED:
457 evt.SetEventType(wxEVT_STC_STYLENEEDED);
458 break;
459
460 case SCN_CHARADDED:
461 evt.SetEventType(wxEVT_STC_CHARADDED);
462 break;
463
464 case SCN_SAVEPOINTREACHED:
465 evt.SetEventType(wxEVT_STC_SAVEPOINTREACHED);
466 break;
467
468 case SCN_SAVEPOINTLEFT:
469 evt.SetEventType(wxEVT_STC_SAVEPOINTLEFT);
470 break;
471
472 case SCN_MODIFYATTEMPTRO:
473 evt.SetEventType(wxEVT_STC_ROMODIFYATTEMPT);
474 break;
475
476 case SCN_KEY:
477 evt.SetEventType(wxEVT_STC_KEY);
478 break;
479
480 case SCN_DOUBLECLICK:
481 evt.SetEventType(wxEVT_STC_DOUBLECLICK);
482 break;
483
484 case SCN_UPDATEUI:
485 evt.SetEventType(wxEVT_STC_UPDATEUI);
486 break;
487
488 case SCN_MODIFIED:
489 evt.SetEventType(wxEVT_STC_MODIFIED);
490 evt.SetModificationType(scn.modificationType);
491 if (scn.text)
492 evt.SetText(wxString(scn.text, scn.length));
493 evt.SetLength(scn.length);
494 evt.SetLinesAdded(scn.linesAdded);
495 evt.SetLine(scn.line);
496 evt.SetFoldLevelNow(scn.foldLevelNow);
497 evt.SetFoldLevelPrev(scn.foldLevelPrev);
498 break;
499
500 case SCN_MACRORECORD:
501 evt.SetEventType(wxEVT_STC_MACRORECORD);
502 evt.SetMessage(scn.message);
503 evt.SetWParam(scn.wParam);
504 evt.SetLParam(scn.lParam);
505 break;
506
507 case SCN_MARGINCLICK:
508 evt.SetEventType(wxEVT_STC_MARGINCLICK);
509 evt.SetMargin(scn.margin);
510 break;
511
512 case SCN_NEEDSHOWN:
513 evt.SetEventType(wxEVT_STC_NEEDSHOWN);
514 evt.SetLength(scn.length);
515 break;
516
517 case SCN_PAINTED:
518 evt.SetEventType(wxEVT_STC_PAINTED);
519 break;
520
521 case SCN_USERLISTSELECTION:
522 evt.SetEventType(wxEVT_STC_USERLISTSELECTION);
523 evt.SetListType(scn.listType);
524 evt.SetText(scn.text);
525 break;
526
527 case SCN_URIDROPPED:
528 evt.SetEventType(wxEVT_STC_URIDROPPED);
529 evt.SetText(scn.text);
530 break;
531
532 case SCN_DWELLSTART:
533 evt.SetEventType(wxEVT_STC_DWELLSTART);
534 evt.SetX(scn.x);
535 evt.SetY(scn.y);
536 break;
537
538 case SCN_DWELLEND:
539 evt.SetEventType(wxEVT_STC_DWELLEND);
540 evt.SetX(scn.x);
541 evt.SetY(scn.y);
542 break;
543
544 default:
545 return;
546 }
547
548 GetEventHandler()->ProcessEvent(evt);
549 }
550
551
552 //----------------------------------------------------------------------
553 //----------------------------------------------------------------------
554 //----------------------------------------------------------------------
555
556 wxStyledTextEvent::wxStyledTextEvent(wxEventType commandType, int id)
557 : wxCommandEvent(commandType, id)
558 {
559 m_position = 0;
560 m_key = 0;
561 m_modifiers = 0;
562 m_modificationType = 0;
563 m_length = 0;
564 m_linesAdded = 0;
565 m_line = 0;
566 m_foldLevelNow = 0;
567 m_foldLevelPrev = 0;
568 m_margin = 0;
569 m_message = 0;
570 m_wParam = 0;
571 m_lParam = 0;
572 m_listType = 0;
573 m_x = 0;
574 m_y = 0;
575 m_dragAllowMove = FALSE;
576 m_dragResult = wxDragNone;
577 }
578
579 bool wxStyledTextEvent::GetShift() const { return (m_modifiers & SCI_SHIFT) != 0; }
580 bool wxStyledTextEvent::GetControl() const { return (m_modifiers & SCI_CTRL) != 0; }
581 bool wxStyledTextEvent::GetAlt() const { return (m_modifiers & SCI_ALT) != 0; }
582
583
584 wxStyledTextEvent::wxStyledTextEvent(const wxStyledTextEvent& event):
585 wxCommandEvent(event)
586 {
587 m_position = event.m_position;
588 m_key = event.m_key;
589 m_modifiers = event.m_modifiers;
590 m_modificationType = event.m_modificationType;
591 m_text = event.m_text;
592 m_length = event.m_length;
593 m_linesAdded = event.m_linesAdded;
594 m_line = event.m_line;
595 m_foldLevelNow = event.m_foldLevelNow;
596 m_foldLevelPrev = event.m_foldLevelPrev;
597
598 m_margin = event.m_margin;
599
600 m_message = event.m_message;
601 m_wParam = event.m_wParam;
602 m_lParam = event.m_lParam;
603
604 m_listType = event.m_listType;
605 m_x = event.m_x;
606 m_y = event.m_y;
607
608 m_dragText = event.m_dragText;
609 m_dragAllowMove =event.m_dragAllowMove;
610 m_dragResult = event.m_dragResult;
611 }
612
613 //----------------------------------------------------------------------
614 //----------------------------------------------------------------------
615
616
617
618
619
620
621
622
623