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