Switch back to not using wxPopupWindow since wxMSW's version can't
[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 <wx/wx.h>
10 #include <wx/encconv.h>
11
12
13 #include "Platform.h"
14 #include "PlatWX.h"
15 #include "wx/stc/stc.h"
16
17
18 #ifdef __WXGTK__
19 #include <gtk/gtk.h>
20 #endif
21
22
23 Point Point::FromLong(long lpoint) {
24 return Point(lpoint & 0xFFFF, lpoint >> 16);
25 }
26
27 wxRect wxRectFromPRectangle(PRectangle prc) {
28 wxRect rc(prc.left, prc.top,
29 prc.right-prc.left, prc.bottom-prc.top);
30 return rc;
31 }
32
33 PRectangle PRectangleFromwxRect(wxRect rc) {
34 return PRectangle(rc.GetLeft(), rc.GetTop(),
35 rc.GetRight()+1, rc.GetBottom()+1);
36 }
37
38 wxColour wxColourFromCA(const ColourAllocated& ca) {
39 ColourDesired cd(ca.AsLong());
40 return wxColour(cd.GetRed(), cd.GetGreen(), cd.GetBlue());
41 }
42
43 //----------------------------------------------------------------------
44
45 Palette::Palette() {
46 used = 0;
47 allowRealization = false;
48 }
49
50 Palette::~Palette() {
51 Release();
52 }
53
54 void Palette::Release() {
55 used = 0;
56 }
57
58 // This method either adds a colour to the list of wanted colours (want==true)
59 // or retrieves the allocated colour back to the ColourPair.
60 // This is one method to make it easier to keep the code for wanting and retrieving in sync.
61 void Palette::WantFind(ColourPair &cp, bool want) {
62 if (want) {
63 for (int i=0; i < used; i++) {
64 if (entries[i].desired == cp.desired)
65 return;
66 }
67
68 if (used < numEntries) {
69 entries[used].desired = cp.desired;
70 entries[used].allocated.Set(cp.desired.AsLong());
71 used++;
72 }
73 } else {
74 for (int i=0; i < used; i++) {
75 if (entries[i].desired == cp.desired) {
76 cp.allocated = entries[i].allocated;
77 return;
78 }
79 }
80 cp.allocated.Set(cp.desired.AsLong());
81 }
82 }
83
84 void Palette::Allocate(Window &) {
85 if (allowRealization) {
86 }
87 }
88
89
90 //----------------------------------------------------------------------
91
92 Font::Font() {
93 id = 0;
94 ascent = 0;
95 }
96
97 Font::~Font() {
98 }
99
100 void Font::Create(const char *faceName, int characterSet, int size, bool bold, bool italic) {
101 wxFontEncoding encoding;
102
103 Release();
104
105 switch (characterSet) {
106 default:
107 case wxSTC_CHARSET_ANSI:
108 case wxSTC_CHARSET_DEFAULT:
109 encoding = wxFONTENCODING_DEFAULT;
110 break;
111
112 case wxSTC_CHARSET_BALTIC:
113 encoding = wxFONTENCODING_ISO8859_13;
114 break;
115
116 case wxSTC_CHARSET_CHINESEBIG5:
117 encoding = wxFONTENCODING_CP950;
118 break;
119
120 case wxSTC_CHARSET_EASTEUROPE:
121 encoding = wxFONTENCODING_ISO8859_2;
122 break;
123
124 case wxSTC_CHARSET_GB2312:
125 encoding = wxFONTENCODING_CP936;
126 break;
127
128 case wxSTC_CHARSET_GREEK:
129 encoding = wxFONTENCODING_ISO8859_7;
130 break;
131
132 case wxSTC_CHARSET_HANGUL:
133 encoding = wxFONTENCODING_CP949;
134 break;
135
136 case wxSTC_CHARSET_MAC:
137 encoding = wxFONTENCODING_DEFAULT;
138 break;
139
140 case wxSTC_CHARSET_OEM:
141 encoding = wxFONTENCODING_DEFAULT;
142 break;
143
144 case wxSTC_CHARSET_RUSSIAN:
145 encoding = wxFONTENCODING_KOI8;
146 break;
147
148 case wxSTC_CHARSET_SHIFTJIS:
149 encoding = wxFONTENCODING_CP932;
150 break;
151
152 case wxSTC_CHARSET_SYMBOL:
153 encoding = wxFONTENCODING_DEFAULT;
154 break;
155
156 case wxSTC_CHARSET_TURKISH:
157 encoding = wxFONTENCODING_ISO8859_9;
158 break;
159
160 case wxSTC_CHARSET_JOHAB:
161 encoding = wxFONTENCODING_DEFAULT;
162 break;
163
164 case wxSTC_CHARSET_HEBREW:
165 encoding = wxFONTENCODING_ISO8859_8;
166 break;
167
168 case wxSTC_CHARSET_ARABIC:
169 encoding = wxFONTENCODING_ISO8859_6;
170 break;
171
172 case wxSTC_CHARSET_VIETNAMESE:
173 encoding = wxFONTENCODING_DEFAULT;
174 break;
175
176 case wxSTC_CHARSET_THAI:
177 encoding = wxFONTENCODING_ISO8859_11;
178 break;
179 }
180
181 wxFontEncodingArray ea = wxEncodingConverter::GetPlatformEquivalents(encoding);
182 if (ea.GetCount())
183 encoding = ea[0];
184
185 id = new wxFont(size,
186 wxDEFAULT,
187 italic ? wxITALIC : wxNORMAL,
188 bold ? wxBOLD : wxNORMAL,
189 false,
190 stc2wx(faceName),
191 encoding);
192 }
193
194
195 void Font::Release() {
196 if (id)
197 delete (wxFont*)id;
198 id = 0;
199 }
200
201 //----------------------------------------------------------------------
202
203 class SurfaceImpl : public Surface {
204 private:
205 wxDC* hdc;
206 bool hdcOwned;
207 wxBitmap* bitmap;
208 int x;
209 int y;
210 bool unicodeMode;
211
212 public:
213 SurfaceImpl();
214 ~SurfaceImpl();
215
216 void Init();
217 void Init(SurfaceID sid);
218 void InitPixMap(int width, int height, Surface *surface_);
219
220 void Release();
221 bool Initialised();
222 void PenColour(ColourAllocated fore);
223 int LogPixelsY();
224 int DeviceHeightFont(int points);
225 void MoveTo(int x_, int y_);
226 void LineTo(int x_, int y_);
227 void Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back);
228 void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back);
229 void FillRectangle(PRectangle rc, ColourAllocated back);
230 void FillRectangle(PRectangle rc, Surface &surfacePattern);
231 void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back);
232 void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back);
233 void Copy(PRectangle rc, Point from, Surface &surfaceSource);
234
235 void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
236 void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
237 void MeasureWidths(Font &font_, const char *s, int len, int *positions);
238 int WidthText(Font &font_, const char *s, int len);
239 int WidthChar(Font &font_, char ch);
240 int Ascent(Font &font_);
241 int Descent(Font &font_);
242 int InternalLeading(Font &font_);
243 int ExternalLeading(Font &font_);
244 int Height(Font &font_);
245 int AverageCharWidth(Font &font_);
246
247 int SetPalette(Palette *pal, bool inBackGround);
248 void SetClip(PRectangle rc);
249 void FlushCachedState();
250
251 void SetUnicodeMode(bool unicodeMode_);
252
253 void BrushColour(ColourAllocated back);
254 void SetFont(Font &font_);
255 };
256
257
258
259 SurfaceImpl::SurfaceImpl() :
260 hdc(0), hdcOwned(0), bitmap(0),
261 x(0), y(0), unicodeMode(0)
262 {}
263
264 SurfaceImpl::~SurfaceImpl() {
265 Release();
266 }
267
268 void SurfaceImpl::Release() {
269 if (bitmap) {
270 ((wxMemoryDC*)hdc)->SelectObject(wxNullBitmap);
271 delete bitmap;
272 bitmap = 0;
273 }
274 if (hdcOwned) {
275 delete hdc;
276 hdc = 0;
277 hdcOwned = false;
278 }
279 }
280
281
282 bool SurfaceImpl::Initialised() {
283 return hdc != 0;
284 }
285
286 void SurfaceImpl::Init() {
287 #if 0
288 Release();
289 hdc = new wxMemoryDC();
290 hdcOwned = true;
291 #else
292 // On Mac and GTK(?) the DC is not really valid until it has a bitmap
293 // selected into it. So instead of just creating the DC with no bitmap,
294 // go ahead and give it one.
295 InitPixMap(1,1,NULL);
296 #endif
297 }
298
299 void SurfaceImpl::Init(SurfaceID hdc_) {
300 Release();
301 hdc = (wxDC*)hdc_;
302 }
303
304 void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_) {
305 Release();
306 hdc = new wxMemoryDC();
307 hdcOwned = true;
308 if (width < 1) width = 1;
309 if (height < 1) height = 1;
310 bitmap = new wxBitmap(width, height);
311 ((wxMemoryDC*)hdc)->SelectObject(*bitmap);
312 }
313
314 void SurfaceImpl::PenColour(ColourAllocated fore) {
315 hdc->SetPen(wxPen(wxColourFromCA(fore), 1, wxSOLID));
316 }
317
318 void SurfaceImpl::BrushColour(ColourAllocated back) {
319 hdc->SetBrush(wxBrush(wxColourFromCA(back), wxSOLID));
320 }
321
322 void SurfaceImpl::SetFont(Font &font_) {
323 if (font_.GetID()) {
324 hdc->SetFont(*((wxFont*)font_.GetID()));
325 }
326 }
327
328 int SurfaceImpl::LogPixelsY() {
329 return hdc->GetPPI().y;
330 }
331
332 int SurfaceImpl::DeviceHeightFont(int points) {
333 return points;
334 }
335
336 void SurfaceImpl::MoveTo(int x_, int y_) {
337 x = x_;
338 y = y_;
339 }
340
341 void SurfaceImpl::LineTo(int x_, int y_) {
342 hdc->DrawLine(x,y, x_,y_);
343 x = x_;
344 y = y_;
345 }
346
347 void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) {
348 PenColour(fore);
349 BrushColour(back);
350 hdc->DrawPolygon(npts, (wxPoint*)pts);
351 }
352
353 void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
354 PenColour(fore);
355 BrushColour(back);
356 hdc->DrawRectangle(wxRectFromPRectangle(rc));
357 }
358
359 void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) {
360 BrushColour(back);
361 hdc->SetPen(*wxTRANSPARENT_PEN);
362 hdc->DrawRectangle(wxRectFromPRectangle(rc));
363 }
364
365 void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
366 wxBrush br;
367 if (((SurfaceImpl&)surfacePattern).bitmap)
368 br = wxBrush(*((SurfaceImpl&)surfacePattern).bitmap);
369 else // Something is wrong so display in red
370 br = wxBrush(*wxRED, wxSOLID);
371 hdc->SetPen(*wxTRANSPARENT_PEN);
372 hdc->SetBrush(br);
373 hdc->DrawRectangle(wxRectFromPRectangle(rc));
374 }
375
376 void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
377 PenColour(fore);
378 BrushColour(back);
379 hdc->DrawRoundedRectangle(wxRectFromPRectangle(rc), 4);
380 }
381
382 void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
383 PenColour(fore);
384 BrushColour(back);
385 hdc->DrawEllipse(wxRectFromPRectangle(rc));
386 }
387
388 void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
389 wxRect r = wxRectFromPRectangle(rc);
390 hdc->Blit(r.x, r.y, r.width, r.height,
391 ((SurfaceImpl&)surfaceSource).hdc,
392 from.x, from.y, wxCOPY);
393 }
394
395 void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font, int ybase,
396 const char *s, int len,
397 ColourAllocated fore, ColourAllocated back) {
398 SetFont(font);
399 hdc->SetTextForeground(wxColourFromCA(fore));
400 hdc->SetTextBackground(wxColourFromCA(back));
401 FillRectangle(rc, back);
402
403 // ybase is where the baseline should be, but wxWin uses the upper left
404 // corner, so I need to calculate the real position for the text...
405 hdc->DrawText(stc2wx(s, len), rc.left, ybase - font.ascent);
406 }
407
408 void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font, int ybase,
409 const char *s, int len,
410 ColourAllocated fore, ColourAllocated back) {
411 SetFont(font);
412 hdc->SetTextForeground(wxColourFromCA(fore));
413 hdc->SetTextBackground(wxColourFromCA(back));
414 FillRectangle(rc, back);
415 hdc->SetClippingRegion(wxRectFromPRectangle(rc));
416
417 // see comments above
418 hdc->DrawText(stc2wx(s, len), rc.left, ybase - font.ascent);
419 hdc->DestroyClippingRegion();
420 }
421
422 int SurfaceImpl::WidthText(Font &font, const char *s, int len) {
423 SetFont(font);
424 int w;
425 int h;
426
427 hdc->GetTextExtent(stc2wx(s, len), &w, &h);
428 return w;
429 }
430
431
432 void SurfaceImpl::MeasureWidths(Font &font, const char *s, int len, int *positions) {
433 wxString str = stc2wx(s, len);
434 SetFont(font);
435
436 // Calculate the position of each character based on the widths of
437 // the previous characters
438 int* tpos = new int[len];
439 int totalWidth = 0;
440 size_t i;
441 for (i=0; i<str.Length(); i++) {
442 int w, h;
443 hdc->GetTextExtent(str[i], &w, &h);
444 totalWidth += w;
445 tpos[i] = totalWidth;
446 }
447
448 #if wxUSE_UNICODE
449 // Map the widths for UCS-2 characters back to the UTF-8 input string
450 i = 0;
451 size_t ui = 0;
452 while (i < len) {
453 unsigned char uch = (unsigned char)s[i];
454 positions[i++] = tpos[ui];
455 if (uch >= 0x80) {
456 if (uch < (0x80 + 0x40 + 0x20)) {
457 positions[i++] = tpos[ui];
458 } else {
459 positions[i++] = tpos[ui];
460 positions[i++] = tpos[ui];
461 }
462 }
463 ui++;
464 }
465 #else
466
467 // If not unicode then just use the widths we have
468 memcpy(positions, tpos, len * sizeof(*tpos));
469 #endif
470
471 delete [] tpos;
472 }
473
474
475 int SurfaceImpl::WidthChar(Font &font, char ch) {
476 SetFont(font);
477 int w;
478 int h;
479 char s[2] = { ch, 0 };
480
481 hdc->GetTextExtent(stc2wx(s, 1), &w, &h);
482 return w;
483 }
484
485 #define EXTENT_TEST wxT(" `~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
486
487 int SurfaceImpl::Ascent(Font &font) {
488 SetFont(font);
489 int w, h, d, e;
490 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
491 font.ascent = h - d;
492 return font.ascent;
493 }
494
495 int SurfaceImpl::Descent(Font &font) {
496 SetFont(font);
497 int w, h, d, e;
498 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
499 return d;
500 }
501
502 int SurfaceImpl::InternalLeading(Font &font) {
503 return 0;
504 }
505
506 int SurfaceImpl::ExternalLeading(Font &font) {
507 SetFont(font);
508 int w, h, d, e;
509 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
510 return e;
511 }
512
513 int SurfaceImpl::Height(Font &font) {
514 SetFont(font);
515 return hdc->GetCharHeight();
516 }
517
518 int SurfaceImpl::AverageCharWidth(Font &font) {
519 SetFont(font);
520 return hdc->GetCharWidth();
521 }
522
523 int SurfaceImpl::SetPalette(Palette *pal, bool inBackGround) {
524 return 0;
525 }
526
527 void SurfaceImpl::SetClip(PRectangle rc) {
528 hdc->SetClippingRegion(wxRectFromPRectangle(rc));
529 }
530
531 void SurfaceImpl::FlushCachedState() {
532 }
533
534 void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {
535 unicodeMode=unicodeMode_;
536 #if wxUSE_UNICODE
537 wxASSERT_MSG(unicodeMode == wxUSE_UNICODE,
538 wxT("Only unicode may be used when wxUSE_UNICODE is on."));
539 #else
540 wxASSERT_MSG(unicodeMode == wxUSE_UNICODE,
541 wxT("Only non-unicode may be used when wxUSE_UNICODE is off."));
542 #endif
543 }
544
545 Surface *Surface::Allocate() {
546 return new SurfaceImpl;
547 }
548
549
550 //----------------------------------------------------------------------
551
552
553 inline wxWindow* GETWIN(WindowID id) { return (wxWindow*)id; }
554
555 Window::~Window() {
556 }
557
558 void Window::Destroy() {
559 if (id)
560 GETWIN(id)->Destroy();
561 id = 0;
562 }
563
564 bool Window::HasFocus() {
565 return wxWindow::FindFocus() == GETWIN(id);
566 }
567
568 PRectangle Window::GetPosition() {
569 wxRect rc(GETWIN(id)->GetPosition(), GETWIN(id)->GetSize());
570 return PRectangleFromwxRect(rc);
571 }
572
573 void Window::SetPosition(PRectangle rc) {
574 wxRect r = wxRectFromPRectangle(rc);
575 GETWIN(id)->SetSize(r);
576 }
577
578 void Window::SetPositionRelative(PRectangle rc, Window) {
579 SetPosition(rc); // ????
580 }
581
582 PRectangle Window::GetClientPosition() {
583 wxSize sz = GETWIN(id)->GetClientSize();
584 return PRectangle(0, 0, sz.x, sz.y);
585 }
586
587 void Window::Show(bool show) {
588 GETWIN(id)->Show(show);
589 }
590
591 void Window::InvalidateAll() {
592 GETWIN(id)->Refresh(false);
593 wxWakeUpIdle();
594 }
595
596 void Window::InvalidateRectangle(PRectangle rc) {
597 wxRect r = wxRectFromPRectangle(rc);
598 GETWIN(id)->Refresh(false, &r);
599 wxWakeUpIdle();
600 }
601
602 void Window::SetFont(Font &font) {
603 GETWIN(id)->SetFont(*((wxFont*)font.GetID()));
604 }
605
606 void Window::SetCursor(Cursor curs) {
607 int cursorId;
608
609 switch (curs) {
610 case cursorText:
611 cursorId = wxCURSOR_IBEAM;
612 break;
613 case cursorArrow:
614 cursorId = wxCURSOR_ARROW;
615 break;
616 case cursorUp:
617 cursorId = wxCURSOR_ARROW; // ** no up arrow... wxCURSOR_UPARROW;
618 break;
619 case cursorWait:
620 cursorId = wxCURSOR_WAIT;
621 break;
622 case cursorHoriz:
623 cursorId = wxCURSOR_SIZEWE;
624 break;
625 case cursorVert:
626 cursorId = wxCURSOR_SIZENS;
627 break;
628 case cursorReverseArrow:
629 cursorId = wxCURSOR_RIGHT_ARROW;
630 break;
631 default:
632 cursorId = wxCURSOR_ARROW;
633 break;
634 }
635
636 GETWIN(id)->SetCursor(wxCursor(cursorId));
637 }
638
639
640 void Window::SetTitle(const char *s) {
641 GETWIN(id)->SetTitle(stc2wx(s));
642 }
643
644
645 //----------------------------------------------------------------------
646 // Helper classes for ListBox
647
648
649 #if defined(__WXMAC__)
650 class wxSTCListBoxWin : public wxListBox {
651 public:
652 wxSTCListBoxWin(wxWindow* parent, wxWindowID id)
653 : wxListBox(parent, id, wxDefaultPosition, wxSize(0,0),
654 0, NULL, wxLB_SINGLE | wxSIMPLE_BORDER) {
655 SetCursor(wxCursor(wxCURSOR_ARROW));
656 Hide();
657 }
658
659 void OnFocus(wxFocusEvent& event) {
660 GetParent()->SetFocus();
661 event.Skip();
662 }
663
664 wxListBox* GetLB() { return this; }
665
666 private:
667 DECLARE_EVENT_TABLE()
668 };
669
670
671 BEGIN_EVENT_TABLE(wxSTCListBoxWin, wxListBox)
672 EVT_SET_FOCUS(wxSTCListBoxWin::OnFocus)
673 END_EVENT_TABLE()
674
675
676
677 #else
678
679
680 class wxSTCListBox : public wxListBox {
681 public:
682 wxSTCListBox(wxWindow* parent, wxWindowID id)
683 : wxListBox(parent, id, wxDefaultPosition, wxDefaultSize,
684 0, NULL, wxLB_SINGLE | wxSIMPLE_BORDER)
685 {}
686
687 void OnKeyDown(wxKeyEvent& event) {
688 // Give the key events to the STC. It will then update
689 // the listbox as needed.
690 GetGrandParent()->GetEventHandler()->ProcessEvent(event);
691 }
692
693 private:
694 DECLARE_EVENT_TABLE()
695 };
696
697 BEGIN_EVENT_TABLE(wxSTCListBox, wxListBox)
698 EVT_KEY_DOWN(wxSTCListBox::OnKeyDown)
699 EVT_CHAR(wxSTCListBox::OnKeyDown)
700 END_EVENT_TABLE()
701
702
703
704 #undef wxSTC_USE_POPUP
705 #define wxSTC_USE_POPUP 0 // wxPopupWindow just doesn't work well in this case...
706
707 // A window to place the listbox upon. If wxPopupWindow is supported then
708 // that will be used so the listbox can extend beyond the client area of the
709 // wxSTC if needed.
710 #if wxUSE_POPUPWIN && wxSTC_USE_POPUP
711 #include <wx/popupwin.h>
712 #define wxSTCListBoxWinBase wxPopupWindow
713 #define param2 wxBORDER_NONE // popup's 2nd param is flags
714 #else
715 #define wxSTCListBoxWinBase wxWindow
716 #define param2 -1 // wxWindow's 2nd param is ID
717 #endif
718
719 class wxSTCListBoxWin : public wxSTCListBoxWinBase {
720 public:
721 wxSTCListBoxWin(wxWindow* parent, wxWindowID id)
722 : wxSTCListBoxWinBase(parent, param2) {
723 lb = new wxSTCListBox(this, id);
724 lb->SetCursor(wxCursor(wxCURSOR_ARROW));
725 lb->SetFocus();
726 }
727
728 void OnSize(wxSizeEvent& event) {
729 lb->SetSize(GetSize());
730 }
731
732 wxListBox* GetLB() { return lb; }
733
734 #if wxUSE_POPUPWIN && wxSTC_USE_POPUP
735 virtual void DoSetSize(int x, int y,
736 int width, int height,
737 int sizeFlags = wxSIZE_AUTO) {
738 if (x != -1)
739 GetParent()->ClientToScreen(&x, NULL);
740 if (y != -1)
741 GetParent()->ClientToScreen(NULL, &y);
742 wxSTCListBoxWinBase::DoSetSize(x, y, width, height, sizeFlags);
743 }
744 #endif
745
746 private:
747 wxSTCListBox* lb;
748 DECLARE_EVENT_TABLE()
749 };
750
751 BEGIN_EVENT_TABLE(wxSTCListBoxWin, wxSTCListBoxWinBase)
752 EVT_SIZE(wxSTCListBoxWin::OnSize)
753 END_EVENT_TABLE()
754 #endif
755
756 inline wxListBox* GETLB(WindowID win) {
757 return (((wxSTCListBoxWin*)win)->GetLB());
758 }
759
760 //----------------------------------------------------------------------
761
762 ListBox::ListBox() {
763 }
764
765 ListBox::~ListBox() {
766 }
767
768 void ListBox::Create(Window &parent, int ctrlID) {
769 id = new wxSTCListBoxWin(GETWIN(parent.GetID()), ctrlID);
770 }
771
772 void ListBox::SetVisibleRows(int rows) {
773 desiredVisibleRows = rows;
774 }
775
776 PRectangle ListBox::GetDesiredRect() {
777 wxSize sz = GETLB(id)->GetBestSize();
778 PRectangle rc;
779 rc.top = 0;
780 rc.left = 0;
781 if (sz.x > 400)
782 sz.x = 400;
783 if (sz.y > 140) // TODO: Use desiredVisibleRows??
784 sz.y = 140;
785 rc.right = sz.x;
786 rc.bottom = sz.y;
787 return rc;
788 }
789
790 void ListBox::SetAverageCharWidth(int width) {
791 aveCharWidth = width;
792 }
793
794 void ListBox::SetFont(Font &font) {
795 GETLB(id)->SetFont(*((wxFont*)font.GetID()));
796 }
797
798 void ListBox::Clear() {
799 GETLB(id)->Clear();
800 }
801
802 void ListBox::Append(char *s) {
803 GETLB(id)->Append(s);
804 }
805
806 int ListBox::Length() {
807 return GETLB(id)->GetCount();
808 }
809
810 void ListBox::Select(int n) {
811 GETLB(id)->SetSelection(n);
812 #ifdef __WXGTK__
813 if (n > 4)
814 n = n - 4;
815 else
816 n = 1;
817 GETLB(id)->SetFirstItem(n);
818 #endif
819 }
820
821 int ListBox::GetSelection() {
822 return GETLB(id)->GetSelection();
823 }
824
825 int ListBox::Find(const char *prefix) {
826 // No longer used
827 return -1;
828 }
829
830 void ListBox::GetValue(int n, char *value, int len) {
831 wxString text = GETLB(id)->GetString(n);
832 strncpy(value, wx2stc(text), len);
833 value[len-1] = '\0';
834 }
835
836 void ListBox::Sort() {
837 }
838
839 //----------------------------------------------------------------------
840
841 Menu::Menu() : id(0) {
842 }
843
844 void Menu::CreatePopUp() {
845 Destroy();
846 id = new wxMenu();
847 }
848
849 void Menu::Destroy() {
850 if (id)
851 delete (wxMenu*)id;
852 id = 0;
853 }
854
855 void Menu::Show(Point pt, Window &w) {
856 GETWIN(w.GetID())->PopupMenu((wxMenu*)id, pt.x - 4, pt.y);
857 Destroy();
858 }
859
860 //----------------------------------------------------------------------
861
862 ColourDesired Platform::Chrome() {
863 wxColour c;
864 c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
865 return ColourDesired(c.Red(), c.Green(), c.Blue());
866 }
867
868 ColourDesired Platform::ChromeHighlight() {
869 wxColour c;
870 c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT);
871 return ColourDesired(c.Red(), c.Green(), c.Blue());
872 }
873
874 const char *Platform::DefaultFont() {
875 static char buf[128];
876 strcpy(buf, wxNORMAL_FONT->GetFaceName().mbc_str());
877 return buf;
878 }
879
880 int Platform::DefaultFontSize() {
881 return 8;
882 }
883
884 unsigned int Platform::DoubleClickTime() {
885 return 500; // **** ::GetDoubleClickTime();
886 }
887
888 void Platform::DebugDisplay(const char *s) {
889 wxLogDebug(stc2wx(s));
890 }
891
892 bool Platform::IsKeyDown(int key) {
893 return false; // I don't think we'll need this.
894 }
895
896 long Platform::SendScintilla(WindowID w,
897 unsigned int msg,
898 unsigned long wParam,
899 long lParam) {
900
901 wxStyledTextCtrl* stc = (wxStyledTextCtrl*)w;
902 return stc->SendMsg(msg, wParam, lParam);
903 }
904
905
906 // These are utility functions not really tied to a platform
907
908 int Platform::Minimum(int a, int b) {
909 if (a < b)
910 return a;
911 else
912 return b;
913 }
914
915 int Platform::Maximum(int a, int b) {
916 if (a > b)
917 return a;
918 else
919 return b;
920 }
921
922 #define TRACE
923
924 void Platform::DebugPrintf(const char *format, ...) {
925 #ifdef TRACE
926 char buffer[2000];
927 va_list pArguments;
928 va_start(pArguments, format);
929 vsprintf(buffer,format,pArguments);
930 va_end(pArguments);
931 Platform::DebugDisplay(buffer);
932 #endif
933 }
934
935
936 static bool assertionPopUps = true;
937
938 bool Platform::ShowAssertionPopUps(bool assertionPopUps_) {
939 bool ret = assertionPopUps;
940 assertionPopUps = assertionPopUps_;
941 return ret;
942 }
943
944 void Platform::Assert(const char *c, const char *file, int line) {
945 char buffer[2000];
946 sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line);
947 if (assertionPopUps) {
948 /*int idButton = */
949 wxMessageBox(stc2wx(buffer),
950 wxT("Assertion failure"),
951 wxICON_HAND | wxOK);
952 // if (idButton == IDRETRY) {
953 // ::DebugBreak();
954 // } else if (idButton == IDIGNORE) {
955 // // all OK
956 // } else {
957 // abort();
958 // }
959 } else {
960 strcat(buffer, "\r\n");
961 Platform::DebugDisplay(buffer);
962 abort();
963 }
964 }
965
966
967 int Platform::Clamp(int val, int minVal, int maxVal) {
968 if (val > maxVal)
969 val = maxVal;
970 if (val < minVal)
971 val = minVal;
972 return val;
973 }
974
975
976 bool Platform::IsDBCSLeadByte(int codePage, char ch) {
977 return false;
978 }
979
980
981
982 //----------------------------------------------------------------------
983
984 ElapsedTime::ElapsedTime() {
985 wxStartTimer();
986 }
987
988 double ElapsedTime::Duration(bool reset) {
989 double result = wxGetElapsedTime(reset);
990 result /= 1000.0;
991 return result;
992 }
993
994
995 //----------------------------------------------------------------------
996
997
998
999