The calltip window and autocomplete window in wxSTC will now use a
[wxWidgets.git] / src / stc / PlatWX.cpp
1 // Scintilla source code edit control
2 // PlatWX.cxx - implementation of platform facilities on wxWindows
3 // Copyright 1998-1999 by Neil Hodgson <neilh@scintilla.org>
4 // Robin Dunn <robin@aldunn.com>
5 // The License.txt file describes the conditions under which this software may be distributed.
6
7 #include <ctype.h>
8
9 #include "Platform.h"
10 #include "wx/stc/stc.h"
11
12
13 #ifdef __WXGTK__
14 #include <gtk/gtk.h>
15 #endif
16
17 Point Point::FromLong(long lpoint) {
18 return Point(lpoint & 0xFFFF, lpoint >> 16);
19 }
20
21 wxRect wxRectFromPRectangle(PRectangle prc) {
22 wxRect rc(prc.left, prc.top,
23 prc.right-prc.left, prc.bottom-prc.top);
24 return rc;
25 }
26
27 PRectangle PRectangleFromwxRect(wxRect rc) {
28 return PRectangle(rc.GetLeft(), rc.GetTop(),
29 rc.GetRight()+1, rc.GetBottom()+1);
30 }
31
32 Colour::Colour(long lcol) {
33 co.Set(lcol & 0xff, (lcol >> 8) & 0xff, (lcol >> 16) & 0xff);
34 }
35
36 Colour::Colour(unsigned int red, unsigned int green, unsigned int blue) {
37 co.Set(red, green, blue);
38 }
39
40 bool Colour::operator==(const Colour &other) const {
41 return co == other.co;
42 }
43
44 long Colour::AsLong() const {
45 return (((long)co.Blue() << 16) |
46 ((long)co.Green() << 8) |
47 ((long)co.Red()));
48 }
49
50 unsigned int Colour::GetRed() {
51 return co.Red();
52 }
53
54 unsigned int Colour::GetGreen() {
55 return co.Green();
56 }
57
58 unsigned int Colour::GetBlue() {
59 return co.Blue();
60 }
61
62 Palette::Palette() {
63 used = 0;
64 allowRealization = false;
65 }
66
67 Palette::~Palette() {
68 Release();
69 }
70
71 void Palette::Release() {
72 used = 0;
73 }
74
75 // This method either adds a colour to the list of wanted colours (want==true)
76 // or retrieves the allocated colour back to the ColourPair.
77 // This is one method to make it easier to keep the code for wanting and retrieving in sync.
78 void Palette::WantFind(ColourPair &cp, bool want) {
79 if (want) {
80 for (int i=0; i < used; i++) {
81 if (entries[i].desired == cp.desired)
82 return;
83 }
84
85 if (used < numEntries) {
86 entries[used].desired = cp.desired;
87 entries[used].allocated = cp.desired;
88 used++;
89 }
90 } else {
91 for (int i=0; i < used; i++) {
92 if (entries[i].desired == cp.desired) {
93 cp.allocated = entries[i].allocated;
94 return;
95 }
96 }
97 cp.allocated = cp.desired;
98 }
99 }
100
101 void Palette::Allocate(Window &) {
102 if (allowRealization) {
103 }
104 }
105
106
107 Font::Font() {
108 id = 0;
109 ascent = 0;
110 }
111
112 Font::~Font() {
113 }
114
115 void Font::Create(const char *faceName, int characterSet, int size, bool bold, bool italic) {
116 // TODO: what to do about the characterSet?
117
118 Release();
119 id = new wxFont(size,
120 wxDEFAULT,
121 italic ? wxITALIC : wxNORMAL,
122 bold ? wxBOLD : wxNORMAL,
123 false,
124 faceName,
125 wxFONTENCODING_DEFAULT);
126 }
127
128
129 void Font::Release() {
130 if (id)
131 delete id;
132 id = 0;
133 }
134
135
136 Surface::Surface() :
137 hdc(0), hdcOwned(0), bitmap(0),
138 x(0), y(0) {
139 }
140
141 Surface::~Surface() {
142 Release();
143 }
144
145 void Surface::Release() {
146 if (bitmap) {
147 ((wxMemoryDC*)hdc)->SelectObject(wxNullBitmap);
148 delete bitmap;
149 bitmap = 0;
150 }
151 if (hdcOwned) {
152 delete hdc;
153 hdc = 0;
154 hdcOwned = false;
155 }
156 }
157
158
159 bool Surface::Initialised() {
160 return hdc != 0;
161 }
162
163 void Surface::Init() {
164 Release();
165 hdc = new wxMemoryDC();
166 hdcOwned = true;
167 }
168
169 void Surface::Init(SurfaceID hdc_) {
170 Release();
171 hdc = hdc_;
172 }
173
174 void Surface::InitPixMap(int width, int height, Surface *surface_) {
175 Release();
176 hdc = new wxMemoryDC(surface_->hdc);
177 hdcOwned = true;
178 if (width < 1) width = 1;
179 if (height < 1) height = 1;
180 bitmap = new wxBitmap(width, height);
181 ((wxMemoryDC*)hdc)->SelectObject(*bitmap);
182 }
183
184 void Surface::PenColour(Colour fore) {
185 hdc->SetPen(wxPen(fore.co, 1, wxSOLID));
186 }
187
188 void Surface::BrushColor(Colour back) {
189 hdc->SetBrush(wxBrush(back.co, wxSOLID));
190 }
191
192 void Surface::SetFont(Font &font_) {
193 if (font_.GetID()) {
194 hdc->SetFont(*font_.GetID());
195 }
196 }
197
198 int Surface::LogPixelsY() {
199 return hdc->GetPPI().y;
200 }
201
202
203 int Surface::DeviceHeightFont(int points) {
204 return points;
205 }
206
207
208 void Surface::MoveTo(int x_, int y_) {
209 x = x_;
210 y = y_;
211 }
212
213 void Surface::LineTo(int x_, int y_) {
214 hdc->DrawLine(x,y, x_,y_);
215 x = x_;
216 y = y_;
217 }
218
219 void Surface::Polygon(Point *pts, int npts, Colour fore,
220 Colour back) {
221 PenColour(fore);
222 BrushColor(back);
223 hdc->DrawPolygon(npts, (wxPoint*)pts);
224 }
225
226 void Surface::RectangleDraw(PRectangle rc, Colour fore, Colour back) {
227 PenColour(fore);
228 BrushColor(back);
229 hdc->DrawRectangle(wxRectFromPRectangle(rc));
230 }
231
232 void Surface::FillRectangle(PRectangle rc, Colour back) {
233 BrushColor(back);
234 hdc->SetPen(*wxTRANSPARENT_PEN);
235 hdc->DrawRectangle(wxRectFromPRectangle(rc));
236 }
237
238 void Surface::FillRectangle(PRectangle rc, Surface &surfacePattern) {
239 wxBrush br;
240 if (surfacePattern.bitmap)
241 br = wxBrush(*surfacePattern.bitmap);
242 else // Something is wrong so display in red
243 br = wxBrush(*wxRED, wxSOLID);
244 hdc->SetPen(*wxTRANSPARENT_PEN);
245 hdc->SetBrush(br);
246 hdc->DrawRectangle(wxRectFromPRectangle(rc));
247 }
248
249 void Surface::RoundedRectangle(PRectangle rc, Colour fore, Colour back) {
250 PenColour(fore);
251 BrushColor(back);
252 hdc->DrawRoundedRectangle(wxRectFromPRectangle(rc), 4);
253 }
254
255 void Surface::Ellipse(PRectangle rc, Colour fore, Colour back) {
256 PenColour(fore);
257 BrushColor(back);
258 hdc->DrawEllipse(wxRectFromPRectangle(rc));
259 }
260
261 void Surface::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
262 wxRect r = wxRectFromPRectangle(rc);
263 hdc->Blit(r.x, r.y, r.width, r.height,
264 surfaceSource.hdc, from.x, from.y, wxCOPY);
265 }
266
267 void Surface::DrawText(PRectangle rc, Font &font, int ybase,
268 const char *s, int len, Colour fore, Colour back) {
269 SetFont(font);
270 hdc->SetTextForeground(fore.co);
271 hdc->SetTextBackground(back.co);
272 FillRectangle(rc, back);
273
274 // ybase is where the baseline should be, but wxWin uses the upper left
275 // corner, so I need to calculate the real position for the text...
276 hdc->DrawText(wxString(s, len), rc.left, ybase - font.ascent);
277 }
278
279 void Surface::DrawTextClipped(PRectangle rc, Font &font, int ybase, const char *s, int len, Colour fore, Colour back) {
280 SetFont(font);
281 hdc->SetTextForeground(fore.co);
282 hdc->SetTextBackground(back.co);
283 FillRectangle(rc, back);
284 hdc->SetClippingRegion(wxRectFromPRectangle(rc));
285
286 // see comments above
287 hdc->DrawText(wxString(s, len), rc.left, ybase - font.ascent);
288 hdc->DestroyClippingRegion();
289 }
290
291 int Surface::WidthText(Font &font, const char *s, int len) {
292 SetFont(font);
293 int w;
294 int h;
295 hdc->GetTextExtent(wxString(s, len), &w, &h);
296 return w;
297 }
298
299 void Surface::MeasureWidths(Font &font, const char *s, int len, int *positions) {
300 SetFont(font);
301 int totalWidth = 0;
302 for (int i=0; i<len; i++) {
303 int w;
304 int h;
305 hdc->GetTextExtent(s[i], &w, &h);
306 totalWidth += w;
307 positions[i] = totalWidth;
308 }
309 }
310
311 int Surface::WidthChar(Font &font, char ch) {
312 SetFont(font);
313 int w;
314 int h;
315 hdc->GetTextExtent(ch, &w, &h);
316 return w;
317 }
318
319 #define EXTENT_TEST " `~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
320
321 int Surface::Ascent(Font &font) {
322 SetFont(font);
323 int w, h, d, e;
324 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
325 font.ascent = h - d;
326 return font.ascent;
327 }
328
329 int Surface::Descent(Font &font) {
330 SetFont(font);
331 int w, h, d, e;
332 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
333 return d;
334 }
335
336 int Surface::InternalLeading(Font &font) {
337 return 0;
338 }
339
340 int Surface::ExternalLeading(Font &font) {
341 SetFont(font);
342 int w, h, d, e;
343 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
344 return e;
345 }
346
347 int Surface::Height(Font &font) {
348 SetFont(font);
349 return hdc->GetCharHeight();
350 }
351
352 int Surface::AverageCharWidth(Font &font) {
353 SetFont(font);
354 return hdc->GetCharWidth();
355 }
356
357 int Surface::SetPalette(Palette *pal, bool inBackGround) {
358 return 0;
359 }
360
361 void Surface::SetClip(PRectangle rc) {
362 hdc->SetClippingRegion(wxRectFromPRectangle(rc));
363 }
364
365 void Surface::FlushCachedState() {
366 }
367
368 Window::~Window() {
369 }
370
371 void Window::Destroy() {
372 if (id)
373 id->Destroy();
374 id = 0;
375 }
376
377 bool Window::HasFocus() {
378 return wxWindow::FindFocus() == id;
379 }
380
381 PRectangle Window::GetPosition() {
382 wxRect rc(id->GetPosition(), id->GetSize());
383 return PRectangleFromwxRect(rc);
384 }
385
386 void Window::SetPosition(PRectangle rc) {
387 wxRect r = wxRectFromPRectangle(rc);
388 id->SetSize(r);
389 }
390
391 void Window::SetPositionRelative(PRectangle rc, Window) {
392 SetPosition(rc); // ????
393 }
394
395 PRectangle Window::GetClientPosition() {
396 wxSize sz = id->GetClientSize();
397 return PRectangle(0, 0, sz.x, sz.y);
398 }
399
400 void Window::Show(bool show) {
401 id->Show(show);
402 }
403
404 void Window::InvalidateAll() {
405 id->Refresh(false);
406 }
407
408 void Window::InvalidateRectangle(PRectangle rc) {
409 wxRect r = wxRectFromPRectangle(rc);
410 id->Refresh(false, &r);
411 }
412
413 void Window::SetFont(Font &font) {
414 id->SetFont(*font.GetID());
415 }
416
417 void Window::SetCursor(Cursor curs) {
418 int cursorId;
419
420 switch (curs) {
421 case cursorText:
422 cursorId = wxCURSOR_IBEAM;
423 break;
424 case cursorArrow:
425 cursorId = wxCURSOR_ARROW;
426 break;
427 case cursorUp:
428 cursorId = wxCURSOR_ARROW; // ** no up arrow... wxCURSOR_UPARROW;
429 break;
430 case cursorWait:
431 cursorId = wxCURSOR_WAIT;
432 break;
433 case cursorHoriz:
434 cursorId = wxCURSOR_SIZEWE;
435 break;
436 case cursorVert:
437 cursorId = wxCURSOR_SIZENS;
438 break;
439 case cursorReverseArrow:
440 cursorId = wxCURSOR_POINT_RIGHT;
441 break;
442 default:
443 cursorId = wxCURSOR_ARROW;
444 break;
445 }
446
447 id->SetCursor(wxCursor(cursorId));
448 }
449
450
451 void Window::SetTitle(const char *s) {
452 id->SetTitle(s);
453 }
454
455
456 //----------------------------------------------------------------------
457 // Helper classes for ListBox
458
459 // A wxListBox that gives focus to its parent if it gets it.
460 class wxSTCListBox : public wxListBox {
461 public:
462 wxSTCListBox(wxWindow* parent, wxWindowID id)
463 : wxListBox(parent, id, wxDefaultPosition, wxDefaultSize,
464 0, NULL, wxLB_SINGLE | wxSIMPLE_BORDER)
465 {}
466
467 void OnFocus(wxFocusEvent& event) {
468 GetParent()->SetFocus();
469 event.Skip();
470 }
471
472 private:
473 DECLARE_EVENT_TABLE()
474 };
475
476 BEGIN_EVENT_TABLE(wxSTCListBox, wxListBox)
477 EVT_SET_FOCUS(wxSTCListBox::OnFocus)
478 END_EVENT_TABLE()
479
480
481
482 // A window to place the listbox upon. If wxPopupWindow is supported then
483 // that will be used so the listbox can extend beyond the client area of the
484 // wxSTC if needed.
485
486 #if wxUSE_POPUPWIN
487 #include <wx/popupwin.h>
488 #define wxSTCListBoxWinBase wxPopupWindow
489 #define param2 wxBORDER_NONE // popup's 2nd param is flags
490 #else
491 #define wxSTCListBoxWinBase wxWindow
492 #define param2 -1 // wxWindows 2nd param is ID
493 #endif
494
495 class wxSTCListBoxWin : public wxSTCListBoxWinBase {
496 public:
497 wxSTCListBoxWin(wxWindow* parent, wxWindowID id)
498 : wxSTCListBoxWinBase(parent, param2) {
499 lb = new wxSTCListBox(this, id);
500 }
501
502 void OnSize(wxSizeEvent& event) {
503 lb->SetSize(GetSize());
504 }
505 void OnFocus(wxFocusEvent& event) {
506 GetParent()->SetFocus();
507 event.Skip();
508 }
509
510 wxListBox* GetLB() { return lb; }
511
512 #if wxUSE_POPUPWIN
513 virtual void DoSetSize(int x, int y,
514 int width, int height,
515 int sizeFlags = wxSIZE_AUTO) {
516 if (x != -1)
517 GetParent()->ClientToScreen(&x, NULL);
518 if (y != -1)
519 GetParent()->ClientToScreen(NULL, &y);
520 wxSTCListBoxWinBase::DoSetSize(x, y, width, height, sizeFlags);
521 }
522 #endif
523
524 private:
525 wxSTCListBox* lb;
526 DECLARE_EVENT_TABLE()
527 };
528
529 BEGIN_EVENT_TABLE(wxSTCListBoxWin, wxSTCListBoxWinBase)
530 EVT_SIZE (wxSTCListBoxWin::OnSize)
531 EVT_SET_FOCUS (wxSTCListBoxWin::OnFocus)
532 END_EVENT_TABLE()
533
534
535 #define GETLB(win) (((wxSTCListBoxWin*)win)->GetLB())
536
537 //----------------------------------------------------------------------
538
539 ListBox::ListBox() {
540 }
541
542 ListBox::~ListBox() {
543 }
544
545 void ListBox::Create(Window &parent, int ctrlID) {
546 id = new wxSTCListBoxWin(parent.id, ctrlID);
547 }
548
549 void ListBox::SetVisibleRows(int rows) {
550 desiredVisibleRows = rows;
551 }
552
553 PRectangle ListBox::GetDesiredRect() {
554 wxSize sz = GETLB(id)->GetBestSize();
555 PRectangle rc;
556 rc.top = 0;
557 rc.left = 0;
558 if (sz.x > 400)
559 sz.x = 400;
560 if (sz.y > 160) // TODO: Use desiredVisibleRows??
561 sz.y = 160;
562 rc.right = sz.x;
563 rc.bottom = sz.y;
564 return rc;
565 }
566
567 void ListBox::SetAverageCharWidth(int width) {
568 aveCharWidth = width;
569 }
570
571 void ListBox::SetFont(Font &font) {
572 GETLB(id)->SetFont(*font.GetID());
573 }
574
575 void ListBox::Clear() {
576 GETLB(id)->Clear();
577 }
578
579 void ListBox::Append(char *s) {
580 GETLB(id)->Append(s);
581 }
582
583 int ListBox::Length() {
584 return GETLB(id)->GetCount();
585 }
586
587 void ListBox::Select(int n) {
588 GETLB(id)->SetSelection(n);
589 #ifdef __WXGTK__
590 if (n > 4)
591 n = n - 4;
592 else
593 n = 1;
594 GETLB(id)->SetFirstItem(n);
595 #endif
596 }
597
598 int ListBox::GetSelection() {
599 return GETLB(id)->GetSelection();
600 }
601
602 int ListBox::Find(const char *prefix) {
603 // No longer used
604 return -1;
605 }
606
607 void ListBox::GetValue(int n, char *value, int len) {
608 wxString text = GETLB(id)->GetString(n);
609 strncpy(value, text.c_str(), len);
610 value[len-1] = '\0';
611 }
612
613 void ListBox::Sort() {
614 }
615
616
617 Menu::Menu() : id(0) {
618 }
619
620 void Menu::CreatePopUp() {
621 Destroy();
622 id = new wxMenu();
623 }
624
625 void Menu::Destroy() {
626 if (id)
627 delete id;
628 id = 0;
629 }
630
631 void Menu::Show(Point pt, Window &w) {
632 w.GetID()->PopupMenu(id, pt.x - 4, pt.y);
633 Destroy();
634 }
635
636
637 Colour Platform::Chrome() {
638 wxColour c;
639 c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
640 return Colour(c.Red(), c.Green(), c.Blue());
641 }
642
643 Colour Platform::ChromeHighlight() {
644 wxColour c;
645 c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT);
646 return Colour(c.Red(), c.Green(), c.Blue());
647 }
648
649 const char *Platform::DefaultFont() {
650 return wxNORMAL_FONT->GetFaceName();
651 }
652
653 int Platform::DefaultFontSize() {
654 return 8;
655 }
656
657 unsigned int Platform::DoubleClickTime() {
658 return 500; // **** ::GetDoubleClickTime();
659 }
660
661 void Platform::DebugDisplay(const char *s) {
662 wxLogDebug(s);
663 }
664
665 bool Platform::IsKeyDown(int key) {
666 return false; // I don't think we'll need this.
667 }
668
669 long Platform::SendScintilla(WindowID w,
670 unsigned int msg,
671 unsigned long wParam,
672 long lParam) {
673
674 wxStyledTextCtrl* stc = (wxStyledTextCtrl*)w;
675 return stc->SendMsg(msg, wParam, lParam);
676 }
677
678
679 // These are utility functions not really tied to a platform
680
681 int Platform::Minimum(int a, int b) {
682 if (a < b)
683 return a;
684 else
685 return b;
686 }
687
688 int Platform::Maximum(int a, int b) {
689 if (a > b)
690 return a;
691 else
692 return b;
693 }
694
695 #define TRACE
696
697 void Platform::DebugPrintf(const char *format, ...) {
698 #ifdef TRACE
699 char buffer[2000];
700 va_list pArguments;
701 va_start(pArguments, format);
702 vsprintf(buffer,format,pArguments);
703 va_end(pArguments);
704 Platform::DebugDisplay(buffer);
705 #endif
706 }
707
708
709 static bool assertionPopUps = true;
710
711 bool Platform::ShowAssertionPopUps(bool assertionPopUps_) {
712 bool ret = assertionPopUps;
713 assertionPopUps = assertionPopUps_;
714 return ret;
715 }
716
717 void Platform::Assert(const char *c, const char *file, int line) {
718 char buffer[2000];
719 sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line);
720 if (assertionPopUps) {
721 int idButton = wxMessageBox(buffer, "Assertion failure",
722 wxICON_HAND | wxOK);
723 // if (idButton == IDRETRY) {
724 // ::DebugBreak();
725 // } else if (idButton == IDIGNORE) {
726 // // all OK
727 // } else {
728 // abort();
729 // }
730 } else {
731 strcat(buffer, "\r\n");
732 Platform::DebugDisplay(buffer);
733 abort();
734 }
735 }
736
737
738 int Platform::Clamp(int val, int minVal, int maxVal) {
739 if (val > maxVal)
740 val = maxVal;
741 if (val < minVal)
742 val = minVal;
743 return val;
744 }
745
746
747
748
749
750