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