wxInputConsumer
[wxWidgets.git] / src / stc / stc.cpp.in
CommitLineData
f97d84a6
RD
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
29int wxForceScintillaLexers(void)
30{
65ec6247
RD
31 extern LexerModule lmAda;
32 extern LexerModule lmAVE;
33 extern LexerModule lmConf;
f97d84a6 34 extern LexerModule lmCPP;
65ec6247 35 extern LexerModule lmEiffel;
f97d84a6 36 extern LexerModule lmHTML;
65ec6247
RD
37 extern LexerModule lmLISP;
38 extern LexerModule lmLua;
39 extern LexerModule lmBatch; // In LexOthers.cxx
40 extern LexerModule lmPascal;
f97d84a6
RD
41 extern LexerModule lmPerl;
42 extern LexerModule lmPython;
65ec6247 43 extern LexerModule lmRuby;
f97d84a6
RD
44 extern LexerModule lmSQL;
45 extern LexerModule lmVB;
46
65ec6247
RD
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 )
f97d84a6
RD
62 {
63 return 1;
64 }
65 else
66 {
67 return 0;
68 }
69}
70
71//----------------------------------------------------------------------
72
73const wxChar* wxSTCNameStr = "stcwindow";
74
d25f5fbb
RD
75DEFINE_EVENT_TYPE( wxEVT_STC_CHANGE )
76DEFINE_EVENT_TYPE( wxEVT_STC_STYLENEEDED )
77DEFINE_EVENT_TYPE( wxEVT_STC_CHARADDED )
d25f5fbb
RD
78DEFINE_EVENT_TYPE( wxEVT_STC_SAVEPOINTREACHED )
79DEFINE_EVENT_TYPE( wxEVT_STC_SAVEPOINTLEFT )
80DEFINE_EVENT_TYPE( wxEVT_STC_ROMODIFYATTEMPT )
65ec6247 81DEFINE_EVENT_TYPE( wxEVT_STC_KEY )
d25f5fbb 82DEFINE_EVENT_TYPE( wxEVT_STC_DOUBLECLICK )
65ec6247 83DEFINE_EVENT_TYPE( wxEVT_STC_UPDATEUI )
d25f5fbb 84DEFINE_EVENT_TYPE( wxEVT_STC_MODIFIED )
d25f5fbb
RD
85DEFINE_EVENT_TYPE( wxEVT_STC_MACRORECORD )
86DEFINE_EVENT_TYPE( wxEVT_STC_MARGINCLICK )
87DEFINE_EVENT_TYPE( wxEVT_STC_NEEDSHOWN )
88DEFINE_EVENT_TYPE( wxEVT_STC_POSCHANGED )
65ec6247
RD
89DEFINE_EVENT_TYPE( wxEVT_STC_PAINTED )
90DEFINE_EVENT_TYPE( wxEVT_STC_USERLISTSELECTION )
91DEFINE_EVENT_TYPE( wxEVT_STC_URIDROPPED )
92DEFINE_EVENT_TYPE( wxEVT_STC_DWELLSTART )
93DEFINE_EVENT_TYPE( wxEVT_STC_DWELLEND )
94
95
d25f5fbb
RD
96
97
f97d84a6
RD
98BEGIN_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)
4ceb1196
RD
103#ifdef __WXMSW__
104 // Let Scintilla see the double click as a second click
105 EVT_LEFT_DCLICK (wxStyledTextCtrl::OnMouseLeftDown)
106#endif
f97d84a6
RD
107 EVT_MOTION (wxStyledTextCtrl::OnMouseMove)
108 EVT_LEFT_UP (wxStyledTextCtrl::OnMouseLeftUp)
65ec6247 109 EVT_CONTEXT_MENU (wxStyledTextCtrl::OnContextMenu)
37d62433 110 EVT_MOUSEWHEEL (wxStyledTextCtrl::OnMouseWheel)
f97d84a6
RD
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)
119END_EVENT_TABLE()
120
121
122IMPLEMENT_CLASS(wxStyledTextCtrl, wxControl)
123IMPLEMENT_DYNAMIC_CLASS(wxStyledTextEvent, wxCommandEvent)
124
125//----------------------------------------------------------------------
126// Constructor and Destructor
127
128wxStyledTextCtrl::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
143wxStyledTextCtrl::~wxStyledTextCtrl() {
144 delete m_swx;
145}
146
147
148//----------------------------------------------------------------------
149
150long 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
163static long wxColourAsLong(const wxColour& co) {
164 return (((long)co.Blue() << 16) |
165 ((long)co.Green() << 8) |
166 ((long)co.Red()));
167}
168
169static wxColour wxColourFromLong(long c) {
170 wxColour clr;
171 clr.Set(c & 0xff, (c >> 8) & 0xff, (c >> 16) & 0xff);
172 return clr;
173}
174
175
176static 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.
198int 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//
216void 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.
257void 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.
269void 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.
284void wxStyledTextCtrl::CmdKeyExecute(int cmd) {
285 SendMsg(cmd);
286}
287
288
289// Set the left and right margin in the edit area, measured in pixels.
290void 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.
297void 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.
306wxPoint 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
313void wxStyledTextCtrl::ScrollToLine(int line) {
314 m_swx->DoScrollToLine(line);
315}
316
317
318// Scroll enough to make the given column visible
319void wxStyledTextCtrl::ScrollToColumn(int column) {
320 m_swx->DoScrollToColumn(column);
321}
322
323
324
325//----------------------------------------------------------------------
326// Event handlers
327
328void wxStyledTextCtrl::OnPaint(wxPaintEvent& evt) {
329 wxPaintDC dc(this);
330 wxRegion region = GetUpdateRegion();
331
332 m_swx->DoPaint(&dc, region.GetBox());
333}
334
335void 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
342void wxStyledTextCtrl::OnSize(wxSizeEvent& evt) {
343 wxSize sz = GetClientSize();
344 m_swx->DoSize(sz.x, sz.y);
345}
346
347void 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
353void wxStyledTextCtrl::OnMouseMove(wxMouseEvent& evt) {
354 wxPoint pt = evt.GetPosition();
355 m_swx->DoButtonMove(Point(pt.x, pt.y));
356}
357
358void 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
65ec6247 365void wxStyledTextCtrl::OnContextMenu(wxContextMenuEvent& evt) {
f97d84a6 366 wxPoint pt = evt.GetPosition();
65ec6247 367 ScreenToClient(&pt.x, &pt.y);
f97d84a6
RD
368 m_swx->DoContextMenu(Point(pt.x, pt.y));
369}
370
37d62433
RD
371
372void wxStyledTextCtrl::OnMouseWheel(wxMouseEvent& evt) {
373 m_swx->DoMouseWheel(evt.GetWheelRotation(),
374 evt.GetWheelDelta(),
65ec6247
RD
375 evt.GetLinesPerAction(),
376 evt.ControlDown());
37d62433
RD
377}
378
379
f97d84a6
RD
380void 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
393void wxStyledTextCtrl::OnKeyDown(wxKeyEvent& evt) {
394 long key = evt.KeyCode();
65ec6247
RD
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)
f97d84a6
RD
403 evt.Skip();
404}
405
406void wxStyledTextCtrl::OnLoseFocus(wxFocusEvent& evt) {
407 m_swx->DoLoseFocus();
408}
409
410void wxStyledTextCtrl::OnGainFocus(wxFocusEvent& evt) {
411 m_swx->DoGainFocus();
412}
413
414void wxStyledTextCtrl::OnSysColourChanged(wxSysColourChangedEvent& evt) {
415 m_swx->DoSysColourChange();
416}
417
418void wxStyledTextCtrl::OnEraseBackground(wxEraseEvent& evt) {
419 // do nothing to help avoid flashing
420}
421
422
423
424void wxStyledTextCtrl::OnMenu(wxCommandEvent& evt) {
425 m_swx->DoCommand(evt.GetId());
426}
427
428
429void wxStyledTextCtrl::OnListBox(wxCommandEvent& evt) {
430 m_swx->DoOnListBox();
431}
432
433
434//----------------------------------------------------------------------
435// Turn notifications from Scintilla into events
436
437
438void wxStyledTextCtrl::NotifyChange() {
439 wxStyledTextEvent evt(wxEVT_STC_CHANGE, GetId());
440 GetEventHandler()->ProcessEvent(evt);
441}
442
443void wxStyledTextCtrl::NotifyParent(SCNotification* _scn) {
444 SCNotification& scn = *_scn;
65ec6247
RD
445 wxStyledTextEvent evt(0, GetId());
446
447 evt.SetPosition(scn.position);
448 evt.SetKey(scn.ch);
449 evt.SetModifiers(scn.modifiers);
450
f97d84a6
RD
451 switch (scn.nmhdr.code) {
452 case SCN_STYLENEEDED:
65ec6247 453 evt.SetEventType(wxEVT_STC_STYLENEEDED);
f97d84a6 454 break;
65ec6247 455
f97d84a6 456 case SCN_CHARADDED:
65ec6247 457 evt.SetEventType(wxEVT_STC_CHARADDED);
f97d84a6 458 break;
65ec6247 459
f97d84a6 460 case SCN_SAVEPOINTREACHED:
65ec6247 461 evt.SetEventType(wxEVT_STC_SAVEPOINTREACHED);
f97d84a6 462 break;
65ec6247 463
f97d84a6 464 case SCN_SAVEPOINTLEFT:
65ec6247 465 evt.SetEventType(wxEVT_STC_SAVEPOINTLEFT);
f97d84a6 466 break;
65ec6247 467
f97d84a6 468 case SCN_MODIFYATTEMPTRO:
65ec6247
RD
469 evt.SetEventType(wxEVT_STC_ROMODIFYATTEMPT);
470 break;
471
472 case SCN_KEY:
473 evt.SetEventType(wxEVT_STC_KEY);
f97d84a6 474 break;
65ec6247 475
f97d84a6 476 case SCN_DOUBLECLICK:
65ec6247 477 evt.SetEventType(wxEVT_STC_DOUBLECLICK);
f97d84a6 478 break;
65ec6247
RD
479
480 case SCN_UPDATEUI:
481 evt.SetEventType(wxEVT_STC_UPDATEUI);
f97d84a6 482 break;
65ec6247
RD
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);
f97d84a6 494 break;
65ec6247 495
f97d84a6 496 case SCN_MACRORECORD:
65ec6247
RD
497 evt.SetEventType(wxEVT_STC_MACRORECORD);
498 evt.SetMessage(scn.message);
499 evt.SetWParam(scn.wParam);
500 evt.SetLParam(scn.lParam);
f97d84a6 501 break;
65ec6247 502
f97d84a6 503 case SCN_MARGINCLICK:
65ec6247
RD
504 evt.SetEventType(wxEVT_STC_MARGINCLICK);
505 evt.SetMargin(scn.margin);
f97d84a6 506 break;
65ec6247 507
f97d84a6 508 case SCN_NEEDSHOWN:
65ec6247
RD
509 evt.SetEventType(wxEVT_STC_NEEDSHOWN);
510 evt.SetLength(scn.length);
f97d84a6 511 break;
65ec6247 512
f97d84a6 513 case SCN_POSCHANGED:
65ec6247
RD
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);
f97d84a6 525 break;
f97d84a6 526
65ec6247
RD
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;
f97d84a6 546 }
65ec6247
RD
547
548 GetEventHandler()->ProcessEvent(evt);
f97d84a6
RD
549}
550
551
552
553//----------------------------------------------------------------------
554//----------------------------------------------------------------------
555//----------------------------------------------------------------------
556
557wxStyledTextEvent::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;
65ec6247
RD
573 m_listType = 0;
574 m_x = 0;
575 m_y = 0;
f97d84a6
RD
576}
577
578bool wxStyledTextEvent::GetShift() const { return (m_modifiers & SCI_SHIFT) != 0; }
579bool wxStyledTextEvent::GetControl() const { return (m_modifiers & SCI_CTRL) != 0; }
580bool wxStyledTextEvent::GetAlt() const { return (m_modifiers & SCI_ALT) != 0; }
581
582void 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
65ec6247
RD
603 o->m_listType = m_listType;
604 o->m_x = m_x;
605 o->m_y = m_y;
f97d84a6
RD
606
607}
608
609//----------------------------------------------------------------------
610//----------------------------------------------------------------------
611