return sensible (fake) values for DBCS query methods
[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 #include <wx/listctrl.h>
12 #include <wx/mstream.h>
13 #include <wx/image.h>
14 #include <wx/imaglist.h>
15
16 #include "Platform.h"
17 #include "PlatWX.h"
18 #include "wx/stc/stc.h"
19
20
21 #ifdef __WXGTK__
22 #include <gtk/gtk.h>
23 #endif
24
25
26 Point Point::FromLong(long lpoint) {
27 return Point(lpoint & 0xFFFF, lpoint >> 16);
28 }
29
30 wxRect wxRectFromPRectangle(PRectangle prc) {
31 wxRect rc(prc.left, prc.top,
32 prc.right-prc.left, prc.bottom-prc.top);
33 return rc;
34 }
35
36 PRectangle PRectangleFromwxRect(wxRect rc) {
37 return PRectangle(rc.GetLeft(), rc.GetTop(),
38 rc.GetRight()+1, rc.GetBottom()+1);
39 }
40
41 wxColour wxColourFromCA(const ColourAllocated& ca) {
42 ColourDesired cd(ca.AsLong());
43 return wxColour(cd.GetRed(), cd.GetGreen(), cd.GetBlue());
44 }
45
46 //----------------------------------------------------------------------
47
48 Palette::Palette() {
49 used = 0;
50 allowRealization = false;
51 }
52
53 Palette::~Palette() {
54 Release();
55 }
56
57 void Palette::Release() {
58 used = 0;
59 }
60
61 // This method either adds a colour to the list of wanted colours (want==true)
62 // or retrieves the allocated colour back to the ColourPair.
63 // This is one method to make it easier to keep the code for wanting and retrieving in sync.
64 void Palette::WantFind(ColourPair &cp, bool want) {
65 if (want) {
66 for (int i=0; i < used; i++) {
67 if (entries[i].desired == cp.desired)
68 return;
69 }
70
71 if (used < numEntries) {
72 entries[used].desired = cp.desired;
73 entries[used].allocated.Set(cp.desired.AsLong());
74 used++;
75 }
76 } else {
77 for (int i=0; i < used; i++) {
78 if (entries[i].desired == cp.desired) {
79 cp.allocated = entries[i].allocated;
80 return;
81 }
82 }
83 cp.allocated.Set(cp.desired.AsLong());
84 }
85 }
86
87 void Palette::Allocate(Window &) {
88 if (allowRealization) {
89 }
90 }
91
92
93 //----------------------------------------------------------------------
94
95 Font::Font() {
96 id = 0;
97 ascent = 0;
98 }
99
100 Font::~Font() {
101 }
102
103 void Font::Create(const char *faceName, int characterSet, int size, bool bold, bool italic) {
104 wxFontEncoding encoding;
105
106 Release();
107
108 switch (characterSet) {
109 default:
110 case wxSTC_CHARSET_ANSI:
111 case wxSTC_CHARSET_DEFAULT:
112 encoding = wxFONTENCODING_DEFAULT;
113 break;
114
115 case wxSTC_CHARSET_BALTIC:
116 encoding = wxFONTENCODING_ISO8859_13;
117 break;
118
119 case wxSTC_CHARSET_CHINESEBIG5:
120 encoding = wxFONTENCODING_CP950;
121 break;
122
123 case wxSTC_CHARSET_EASTEUROPE:
124 encoding = wxFONTENCODING_ISO8859_2;
125 break;
126
127 case wxSTC_CHARSET_GB2312:
128 encoding = wxFONTENCODING_CP936;
129 break;
130
131 case wxSTC_CHARSET_GREEK:
132 encoding = wxFONTENCODING_ISO8859_7;
133 break;
134
135 case wxSTC_CHARSET_HANGUL:
136 encoding = wxFONTENCODING_CP949;
137 break;
138
139 case wxSTC_CHARSET_MAC:
140 encoding = wxFONTENCODING_DEFAULT;
141 break;
142
143 case wxSTC_CHARSET_OEM:
144 encoding = wxFONTENCODING_DEFAULT;
145 break;
146
147 case wxSTC_CHARSET_RUSSIAN:
148 encoding = wxFONTENCODING_KOI8;
149 break;
150
151 case wxSTC_CHARSET_SHIFTJIS:
152 encoding = wxFONTENCODING_CP932;
153 break;
154
155 case wxSTC_CHARSET_SYMBOL:
156 encoding = wxFONTENCODING_DEFAULT;
157 break;
158
159 case wxSTC_CHARSET_TURKISH:
160 encoding = wxFONTENCODING_ISO8859_9;
161 break;
162
163 case wxSTC_CHARSET_JOHAB:
164 encoding = wxFONTENCODING_DEFAULT;
165 break;
166
167 case wxSTC_CHARSET_HEBREW:
168 encoding = wxFONTENCODING_ISO8859_8;
169 break;
170
171 case wxSTC_CHARSET_ARABIC:
172 encoding = wxFONTENCODING_ISO8859_6;
173 break;
174
175 case wxSTC_CHARSET_VIETNAMESE:
176 encoding = wxFONTENCODING_DEFAULT;
177 break;
178
179 case wxSTC_CHARSET_THAI:
180 encoding = wxFONTENCODING_ISO8859_11;
181 break;
182 }
183
184 wxFontEncodingArray ea = wxEncodingConverter::GetPlatformEquivalents(encoding);
185 if (ea.GetCount())
186 encoding = ea[0];
187
188 id = new wxFont(size,
189 wxDEFAULT,
190 italic ? wxITALIC : wxNORMAL,
191 bold ? wxBOLD : wxNORMAL,
192 false,
193 stc2wx(faceName),
194 encoding);
195 }
196
197
198 void Font::Release() {
199 if (id)
200 delete (wxFont*)id;
201 id = 0;
202 }
203
204 //----------------------------------------------------------------------
205
206 class SurfaceImpl : public Surface {
207 private:
208 wxDC* hdc;
209 bool hdcOwned;
210 wxBitmap* bitmap;
211 int x;
212 int y;
213 bool unicodeMode;
214
215 public:
216 SurfaceImpl();
217 ~SurfaceImpl();
218
219 virtual void Init(WindowID wid);
220 virtual void Init(SurfaceID sid, WindowID wid);
221 virtual void InitPixMap(int width, int height, Surface *surface_, WindowID wid);
222
223 virtual void Release();
224 virtual bool Initialised();
225 virtual void PenColour(ColourAllocated fore);
226 virtual int LogPixelsY();
227 virtual int DeviceHeightFont(int points);
228 virtual void MoveTo(int x_, int y_);
229 virtual void LineTo(int x_, int y_);
230 virtual void Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back);
231 virtual void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back);
232 virtual void FillRectangle(PRectangle rc, ColourAllocated back);
233 virtual void FillRectangle(PRectangle rc, Surface &surfacePattern);
234 virtual void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back);
235 virtual void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back);
236 virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource);
237
238 virtual void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
239 virtual void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
240 virtual void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);
241 virtual void MeasureWidths(Font &font_, const char *s, int len, int *positions);
242 virtual int WidthText(Font &font_, const char *s, int len);
243 virtual int WidthChar(Font &font_, char ch);
244 virtual int Ascent(Font &font_);
245 virtual int Descent(Font &font_);
246 virtual int InternalLeading(Font &font_);
247 virtual int ExternalLeading(Font &font_);
248 virtual int Height(Font &font_);
249 virtual int AverageCharWidth(Font &font_);
250
251 virtual int SetPalette(Palette *pal, bool inBackGround);
252 virtual void SetClip(PRectangle rc);
253 virtual void FlushCachedState();
254
255 virtual void SetUnicodeMode(bool unicodeMode_);
256 virtual void SetDBCSMode(int codePage);
257
258 void BrushColour(ColourAllocated back);
259 void SetFont(Font &font_);
260 };
261
262
263
264 SurfaceImpl::SurfaceImpl() :
265 hdc(0), hdcOwned(0), bitmap(0),
266 x(0), y(0), unicodeMode(0)
267 {}
268
269 SurfaceImpl::~SurfaceImpl() {
270 Release();
271 }
272
273 void SurfaceImpl::Init(WindowID wid) {
274 #if 0
275 Release();
276 hdc = new wxMemoryDC();
277 hdcOwned = true;
278 #else
279 // On Mac and GTK the DC is not really valid until it has a bitmap
280 // selected into it. So instead of just creating the DC with no bitmap,
281 // go ahead and give it one.
282 InitPixMap(1,1,NULL,wid);
283 #endif
284 }
285
286 void SurfaceImpl::Init(SurfaceID hdc_, WindowID) {
287 Release();
288 hdc = (wxDC*)hdc_;
289 }
290
291 void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID) {
292 Release();
293 hdc = new wxMemoryDC();
294 hdcOwned = true;
295 if (width < 1) width = 1;
296 if (height < 1) height = 1;
297 bitmap = new wxBitmap(width, height);
298 ((wxMemoryDC*)hdc)->SelectObject(*bitmap);
299 }
300
301
302 void SurfaceImpl::Release() {
303 if (bitmap) {
304 ((wxMemoryDC*)hdc)->SelectObject(wxNullBitmap);
305 delete bitmap;
306 bitmap = 0;
307 }
308 if (hdcOwned) {
309 delete hdc;
310 hdc = 0;
311 hdcOwned = false;
312 }
313 }
314
315
316 bool SurfaceImpl::Initialised() {
317 return hdc != 0;
318 }
319
320
321 void SurfaceImpl::PenColour(ColourAllocated fore) {
322 hdc->SetPen(wxPen(wxColourFromCA(fore), 1, wxSOLID));
323 }
324
325 void SurfaceImpl::BrushColour(ColourAllocated back) {
326 hdc->SetBrush(wxBrush(wxColourFromCA(back), wxSOLID));
327 }
328
329 void SurfaceImpl::SetFont(Font &font_) {
330 if (font_.GetID()) {
331 hdc->SetFont(*((wxFont*)font_.GetID()));
332 }
333 }
334
335 int SurfaceImpl::LogPixelsY() {
336 return hdc->GetPPI().y;
337 }
338
339 int SurfaceImpl::DeviceHeightFont(int points) {
340 return points;
341 }
342
343 void SurfaceImpl::MoveTo(int x_, int y_) {
344 x = x_;
345 y = y_;
346 }
347
348 void SurfaceImpl::LineTo(int x_, int y_) {
349 hdc->DrawLine(x,y, x_,y_);
350 x = x_;
351 y = y_;
352 }
353
354 void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) {
355 PenColour(fore);
356 BrushColour(back);
357 hdc->DrawPolygon(npts, (wxPoint*)pts);
358 }
359
360 void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
361 PenColour(fore);
362 BrushColour(back);
363 hdc->DrawRectangle(wxRectFromPRectangle(rc));
364 }
365
366 void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) {
367 BrushColour(back);
368 hdc->SetPen(*wxTRANSPARENT_PEN);
369 hdc->DrawRectangle(wxRectFromPRectangle(rc));
370 }
371
372 void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
373 wxBrush br;
374 if (((SurfaceImpl&)surfacePattern).bitmap)
375 br = wxBrush(*((SurfaceImpl&)surfacePattern).bitmap);
376 else // Something is wrong so display in red
377 br = wxBrush(*wxRED, wxSOLID);
378 hdc->SetPen(*wxTRANSPARENT_PEN);
379 hdc->SetBrush(br);
380 hdc->DrawRectangle(wxRectFromPRectangle(rc));
381 }
382
383 void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
384 PenColour(fore);
385 BrushColour(back);
386 hdc->DrawRoundedRectangle(wxRectFromPRectangle(rc), 4);
387 }
388
389 void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
390 PenColour(fore);
391 BrushColour(back);
392 hdc->DrawEllipse(wxRectFromPRectangle(rc));
393 }
394
395 void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
396 wxRect r = wxRectFromPRectangle(rc);
397 hdc->Blit(r.x, r.y, r.width, r.height,
398 ((SurfaceImpl&)surfaceSource).hdc,
399 from.x, from.y, wxCOPY);
400 }
401
402 void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font, int ybase,
403 const char *s, int len,
404 ColourAllocated fore, ColourAllocated back) {
405 SetFont(font);
406 hdc->SetTextForeground(wxColourFromCA(fore));
407 hdc->SetTextBackground(wxColourFromCA(back));
408 //FillRectangle(rc, back);
409
410 // ybase is where the baseline should be, but wxWin uses the upper left
411 // corner, so I need to calculate the real position for the text...
412 hdc->DrawText(stc2wx(s, len), rc.left, ybase - font.ascent);
413 }
414
415 void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font, int ybase,
416 const char *s, int len,
417 ColourAllocated fore, ColourAllocated back) {
418 SetFont(font);
419 hdc->SetTextForeground(wxColourFromCA(fore));
420 hdc->SetTextBackground(wxColourFromCA(back));
421 //FillRectangle(rc, back);
422 hdc->SetClippingRegion(wxRectFromPRectangle(rc));
423
424 // see comments above
425 hdc->DrawText(stc2wx(s, len), rc.left, ybase - font.ascent);
426 }
427
428
429 void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font, int ybase,
430 const char *s, int len,
431 ColourAllocated fore) {
432
433 SetFont(font);
434 hdc->SetTextForeground(wxColourFromCA(fore));
435 hdc->SetBackgroundMode(wxTRANSPARENT);
436
437 // ybase is where the baseline should be, but wxWin uses the upper left
438 // corner, so I need to calculate the real position for the text...
439 hdc->DrawText(stc2wx(s, len), rc.left, ybase - font.ascent);
440
441 hdc->SetBackgroundMode(wxSOLID);
442 }
443
444
445 void SurfaceImpl::MeasureWidths(Font &font, const char *s, int len, int *positions) {
446
447 wxString str = stc2wx(s, len);
448 SetFont(font);
449
450 #ifndef __WXMAC__
451 // Calculate the position of each character based on the widths of
452 // the previous characters
453 int* tpos = new int[len];
454 int totalWidth = 0;
455 size_t i;
456 for (i=0; i<str.Length(); i++) {
457 int w, h;
458 hdc->GetTextExtent(str[i], &w, &h);
459 totalWidth += w;
460 tpos[i] = totalWidth;
461 }
462 #else
463 // Instead of a running total, remeasure from the begining of the
464 // text for each character's position. This is because with AA fonts
465 // on OS X widths can be fractions of pixels wide when more than one
466 // are drawn together, so the sum of all character widths is not necessarily
467 // (and probably not) the same as the whole string width.
468 int* tpos = new int[len];
469 size_t i;
470 for (i=0; i<str.Length(); i++) {
471 int w, h;
472 hdc->GetTextExtent(str.Left(i+1), &w, &h);
473 tpos[i] = w;
474 }
475 #endif
476
477
478 #if wxUSE_UNICODE
479 // Map the widths for UCS-2 characters back to the UTF-8 input string
480 // NOTE: I don't think this is right for when sizeof(wxChar) > 2, ie wxGTK2
481 // so figure it out and fix it!
482 i = 0;
483 size_t ui = 0;
484 while ((int)i < len) {
485 unsigned char uch = (unsigned char)s[i];
486 positions[i++] = tpos[ui];
487 if (uch >= 0x80) {
488 if (uch < (0x80 + 0x40 + 0x20)) {
489 positions[i++] = tpos[ui];
490 } else {
491 positions[i++] = tpos[ui];
492 positions[i++] = tpos[ui];
493 }
494 }
495 ui++;
496 }
497 #else
498
499 // If not unicode then just use the widths we have
500 memcpy(positions, tpos, len * sizeof(*tpos));
501 #endif
502
503 delete [] tpos;
504 }
505
506
507 int SurfaceImpl::WidthText(Font &font, const char *s, int len) {
508 SetFont(font);
509 int w;
510 int h;
511
512 hdc->GetTextExtent(stc2wx(s, len), &w, &h);
513 return w;
514 }
515
516
517 int SurfaceImpl::WidthChar(Font &font, char ch) {
518 SetFont(font);
519 int w;
520 int h;
521 char s[2] = { ch, 0 };
522
523 hdc->GetTextExtent(stc2wx(s, 1), &w, &h);
524 return w;
525 }
526
527 #define EXTENT_TEST wxT(" `~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
528
529 int SurfaceImpl::Ascent(Font &font) {
530 SetFont(font);
531 int w, h, d, e;
532 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
533 font.ascent = h - d;
534 return font.ascent;
535 }
536
537 int SurfaceImpl::Descent(Font &font) {
538 SetFont(font);
539 int w, h, d, e;
540 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
541 return d;
542 }
543
544 int SurfaceImpl::InternalLeading(Font &font) {
545 return 0;
546 }
547
548 int SurfaceImpl::ExternalLeading(Font &font) {
549 SetFont(font);
550 int w, h, d, e;
551 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
552 return e;
553 }
554
555 int SurfaceImpl::Height(Font &font) {
556 SetFont(font);
557 return hdc->GetCharHeight();
558 }
559
560 int SurfaceImpl::AverageCharWidth(Font &font) {
561 SetFont(font);
562 return hdc->GetCharWidth();
563 }
564
565 int SurfaceImpl::SetPalette(Palette *pal, bool inBackGround) {
566 return 0;
567 }
568
569 void SurfaceImpl::SetClip(PRectangle rc) {
570 hdc->SetClippingRegion(wxRectFromPRectangle(rc));
571 }
572
573 void SurfaceImpl::FlushCachedState() {
574 }
575
576 void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {
577 unicodeMode=unicodeMode_;
578 }
579
580 void SurfaceImpl::SetDBCSMode(int codePage) {
581 // dbcsMode = codePage == SC_CP_DBCS;
582 }
583
584
585 Surface *Surface::Allocate() {
586 return new SurfaceImpl;
587 }
588
589
590 //----------------------------------------------------------------------
591
592
593 inline wxWindow* GETWIN(WindowID id) { return (wxWindow*)id; }
594
595 Window::~Window() {
596 }
597
598 void Window::Destroy() {
599 if (id) {
600 Show(FALSE);
601 GETWIN(id)->Destroy();
602 }
603 id = 0;
604 }
605
606 bool Window::HasFocus() {
607 return wxWindow::FindFocus() == GETWIN(id);
608 }
609
610 PRectangle Window::GetPosition() {
611 if (! id) return PRectangle();
612 wxRect rc(GETWIN(id)->GetPosition(), GETWIN(id)->GetSize());
613 return PRectangleFromwxRect(rc);
614 }
615
616 void Window::SetPosition(PRectangle rc) {
617 wxRect r = wxRectFromPRectangle(rc);
618 GETWIN(id)->SetSize(r);
619 }
620
621 void Window::SetPositionRelative(PRectangle rc, Window) {
622 SetPosition(rc); // ????
623 }
624
625 PRectangle Window::GetClientPosition() {
626 if (! id) return PRectangle();
627 wxSize sz = GETWIN(id)->GetClientSize();
628 return PRectangle(0, 0, sz.x, sz.y);
629 }
630
631 void Window::Show(bool show) {
632 GETWIN(id)->Show(show);
633 }
634
635 void Window::InvalidateAll() {
636 GETWIN(id)->Refresh(false);
637 wxWakeUpIdle();
638 }
639
640 void Window::InvalidateRectangle(PRectangle rc) {
641 wxRect r = wxRectFromPRectangle(rc);
642 GETWIN(id)->Refresh(false, &r);
643 wxWakeUpIdle();
644 }
645
646 void Window::SetFont(Font &font) {
647 GETWIN(id)->SetFont(*((wxFont*)font.GetID()));
648 }
649
650 void Window::SetCursor(Cursor curs) {
651 int cursorId;
652
653 switch (curs) {
654 case cursorText:
655 cursorId = wxCURSOR_IBEAM;
656 break;
657 case cursorArrow:
658 cursorId = wxCURSOR_ARROW;
659 break;
660 case cursorUp:
661 cursorId = wxCURSOR_ARROW; // ** no up arrow... wxCURSOR_UPARROW;
662 break;
663 case cursorWait:
664 cursorId = wxCURSOR_WAIT;
665 break;
666 case cursorHoriz:
667 cursorId = wxCURSOR_SIZEWE;
668 break;
669 case cursorVert:
670 cursorId = wxCURSOR_SIZENS;
671 break;
672 case cursorReverseArrow:
673 cursorId = wxCURSOR_RIGHT_ARROW;
674 break;
675 case cursorHand:
676 cursorId = wxCURSOR_HAND;
677 default:
678 cursorId = wxCURSOR_ARROW;
679 break;
680 }
681 #ifdef __WXMOTIF__
682 wxCursor wc = wxStockCursor(cursorId) ;
683 #else
684 wxCursor wc = wxCursor(cursorId) ;
685 #endif
686 GETWIN(id)->SetCursor(wc);
687 }
688
689
690 void Window::SetTitle(const char *s) {
691 GETWIN(id)->SetTitle(stc2wx(s));
692 }
693
694
695 //----------------------------------------------------------------------
696 // Helper classes for ListBox
697
698
699 // This is a simple subclass of wxLIstView that just resets focus to the
700 // parent when it gets it.
701 class wxSTCListBox : public wxListView {
702 public:
703 wxSTCListBox(wxWindow* parent, wxWindowID id,
704 const wxPoint& pos, const wxSize& size,
705 long style)
706 : wxListView(parent, id, pos, size, style)
707 {}
708
709 void OnFocus(wxFocusEvent& event) {
710 GetParent()->SetFocus();
711 event.Skip();
712 }
713
714 private:
715 DECLARE_EVENT_TABLE()
716 };
717
718 BEGIN_EVENT_TABLE(wxSTCListBox, wxListView)
719 EVT_SET_FOCUS( wxSTCListBox::OnFocus)
720 END_EVENT_TABLE()
721
722
723
724
725 // A window to place the wxSTCListBox upon
726 class wxSTCListBoxWin : public wxWindow {
727 private:
728 wxListView* lv;
729 CallBackAction doubleClickAction;
730 void* doubleClickActionData;
731 public:
732 wxSTCListBoxWin(wxWindow* parent, wxWindowID id) :
733 wxWindow(parent, id, wxDefaultPosition, wxSize(0,0), wxNO_BORDER )
734 {
735
736 SetBackgroundColour(*wxBLACK);
737 lv = new wxSTCListBox(this, id, wxDefaultPosition, wxDefaultSize,
738 wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_NO_HEADER | wxNO_BORDER);
739 lv->SetCursor(wxCursor(wxCURSOR_ARROW));
740 lv->InsertColumn(0, wxEmptyString);
741 lv->InsertColumn(1, wxEmptyString);
742 Hide();
743 }
744
745 int IconWidth() {
746 wxImageList* il = lv->GetImageList(wxIMAGE_LIST_SMALL);
747 if (il != NULL) {
748 int w, h;
749 il->GetSize(0, w, h);
750 return w;
751 }
752 return 0;
753 }
754
755
756 void SetDoubleClickAction(CallBackAction action, void *data) {
757 doubleClickAction = action;
758 doubleClickActionData = data;
759 }
760
761
762 void OnFocus(wxFocusEvent& event) {
763 GetParent()->SetFocus();
764 event.Skip();
765 }
766
767 void OnSize(wxSizeEvent& event) {
768 // resize the child, leaving a 1 pixel border
769 wxSize sz = GetClientSize();
770 lv->SetSize(1, 1, sz.x-2, sz.y-2);
771 // reset the column widths
772 lv->SetColumnWidth(0, IconWidth()+4);
773 lv->SetColumnWidth(1, sz.x - 2 - lv->GetColumnWidth(0) -
774 wxSystemSettings::GetMetric(wxSYS_VSCROLL_X));
775 event.Skip();
776 }
777
778 void OnActivate(wxListEvent& event) {
779 doubleClickAction(doubleClickActionData);
780 }
781
782 wxListView* GetLB() { return lv; }
783
784 private:
785 DECLARE_EVENT_TABLE()
786 };
787
788
789 BEGIN_EVENT_TABLE(wxSTCListBoxWin, wxWindow)
790 EVT_SET_FOCUS ( wxSTCListBoxWin::OnFocus)
791 EVT_SIZE ( wxSTCListBoxWin::OnSize)
792 EVT_LIST_ITEM_ACTIVATED(-1, wxSTCListBoxWin::OnActivate)
793 END_EVENT_TABLE()
794
795
796
797 inline wxSTCListBoxWin* GETLBW(WindowID win) {
798 return ((wxSTCListBoxWin*)win);
799 }
800
801 inline wxListView* GETLB(WindowID win) {
802 return GETLBW(win)->GetLB();
803 }
804
805 //----------------------------------------------------------------------
806
807 class ListBoxImpl : public ListBox {
808 private:
809 int lineHeight;
810 bool unicodeMode;
811 int desiredVisibleRows;
812 int aveCharWidth;
813 int maxStrWidth;
814 wxImageList* imgList;
815 wxArrayInt* imgTypeMap;
816
817 public:
818 ListBoxImpl();
819 ~ListBoxImpl();
820
821 virtual void SetFont(Font &font);
822 virtual void Create(Window &parent, int ctrlID, int lineHeight_, bool unicodeMode_);
823 virtual void SetAverageCharWidth(int width);
824 virtual void SetVisibleRows(int rows);
825 virtual PRectangle GetDesiredRect();
826 virtual int CaretFromEdge();
827 virtual void Clear();
828 virtual void Append(char *s, int type = -1);
829 virtual int Length();
830 virtual void Select(int n);
831 virtual int GetSelection();
832 virtual int Find(const char *prefix);
833 virtual void GetValue(int n, char *value, int len);
834 virtual void Sort();
835 virtual void RegisterImage(int type, const char *xpm_data);
836 virtual void ClearRegisteredImages();
837 virtual void SetDoubleClickAction(CallBackAction, void *);
838
839 };
840
841
842 ListBoxImpl::ListBoxImpl()
843 : lineHeight(10), unicodeMode(false),
844 desiredVisibleRows(5), aveCharWidth(8), maxStrWidth(0),
845 imgList(NULL), imgTypeMap(NULL)
846 {
847 }
848
849 ListBoxImpl::~ListBoxImpl() {
850 if (imgList) {
851 delete imgList;
852 imgList = NULL;
853 }
854 if (imgTypeMap) {
855 delete imgTypeMap;
856 imgTypeMap = NULL;
857 }
858 }
859
860
861 void ListBoxImpl::SetFont(Font &font) {
862 GETLB(id)->SetFont(*((wxFont*)font.GetID()));
863 }
864
865
866 void ListBoxImpl::Create(Window &parent, int ctrlID, int lineHeight_, bool unicodeMode_) {
867 lineHeight = lineHeight_;
868 unicodeMode = unicodeMode_;
869 maxStrWidth = 0;
870 id = new wxSTCListBoxWin(GETWIN(parent.GetID()), ctrlID);
871 if (imgList != NULL)
872 GETLB(id)->SetImageList(imgList, wxIMAGE_LIST_SMALL);
873 }
874
875
876 void ListBoxImpl::SetAverageCharWidth(int width) {
877 aveCharWidth = width;
878 }
879
880
881 void ListBoxImpl::SetVisibleRows(int rows) {
882 desiredVisibleRows = rows;
883 }
884
885
886 PRectangle ListBoxImpl::GetDesiredRect() {
887 // wxListCtrl doesn't have a DoGetBestSize, so instead we kept track of
888 // the max size in Append and calculate it here...
889 int maxw = maxStrWidth;
890 int maxh = 0;
891
892 // give it a default if there are no lines, and/or add a bit more
893 if (maxw == 0) maxw = 100;
894 maxw += aveCharWidth * 3 +
895 GETLBW(id)->IconWidth() + wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
896 if (maxw > 350)
897 maxw = 350;
898
899 // estimate a desired height
900 int count = GETLB(id)->GetItemCount();
901 if (count) {
902 wxRect rect;
903 GETLB(id)->GetItemRect(0, rect);
904 maxh = count * rect.GetHeight();
905 if (maxh > 140) // TODO: Use desiredVisibleRows??
906 maxh = 140;
907
908 // Try to make the size an exact multiple of some number of lines
909 int lines = maxh / rect.GetHeight();
910 maxh = (lines + 1) * rect.GetHeight() + 2;
911 }
912 else
913 maxh = 100;
914
915 PRectangle rc;
916 rc.top = 0;
917 rc.left = 0;
918 rc.right = maxw;
919 rc.bottom = maxh;
920 return rc;
921 }
922
923
924 int ListBoxImpl::CaretFromEdge() {
925 return 4 + GETLBW(id)->IconWidth();
926 }
927
928
929 void ListBoxImpl::Clear() {
930 GETLB(id)->DeleteAllItems();
931 }
932
933
934 void ListBoxImpl::Append(char *s, int type) {
935 wxString text = stc2wx(s);
936 long count = GETLB(id)->GetItemCount();
937 long itemID = GETLB(id)->InsertItem(count, wxEmptyString);
938 GETLB(id)->SetItem(itemID, 1, text);
939 int itemWidth = 0;
940 GETLB(id)->GetTextExtent(text, &itemWidth, NULL);
941 maxStrWidth = wxMax(maxStrWidth, itemWidth);
942 if (type != -1) {
943 wxCHECK_RET(imgTypeMap, wxT("Unexpected NULL imgTypeMap"));
944 long idx = imgTypeMap->Item(type);
945 GETLB(id)->SetItemImage(itemID, idx, idx);
946 }
947 }
948
949
950 int ListBoxImpl::Length() {
951 return GETLB(id)->GetItemCount();
952 }
953
954
955 void ListBoxImpl::Select(int n) {
956 bool select = TRUE;
957 if (n == -1) {
958 n = 0;
959 select = FALSE;
960 }
961 GETLB(id)->Focus(n);
962 GETLB(id)->Select(n, select);
963 }
964
965
966 int ListBoxImpl::GetSelection() {
967 return GETLB(id)->GetFirstSelected();
968 }
969
970
971 int ListBoxImpl::Find(const char *prefix) {
972 // No longer used
973 return -1;
974 }
975
976
977 void ListBoxImpl::GetValue(int n, char *value, int len) {
978 wxListItem item;
979 item.SetId(n);
980 item.SetColumn(1);
981 item.SetMask(wxLIST_MASK_TEXT);
982 GETLB(id)->GetItem(item);
983 strncpy(value, wx2stc(item.GetText()), len);
984 value[len-1] = '\0';
985 }
986
987 void ListBoxImpl::Sort() {
988 }
989
990
991 void ListBoxImpl::RegisterImage(int type, const char *xpm_data) {
992 wxMemoryInputStream stream(xpm_data, strlen(xpm_data)+1);
993 wxBitmap bmp(wxImage(stream, wxBITMAP_TYPE_XPM));
994
995 if (! imgList) {
996 // assumes all images are the same size
997 imgList = new wxImageList(bmp.GetWidth(), bmp.GetHeight(), TRUE);
998 imgTypeMap = new wxArrayInt;
999 }
1000
1001 int idx = imgList->Add(bmp);
1002
1003 // do we need to extend the mapping array?
1004 wxArrayInt& itm = *imgTypeMap;
1005 if ( itm.GetCount() < (size_t)type+1)
1006 itm.Add(-1, type - itm.GetCount() + 1);
1007
1008 // Add an item that maps type to the image index
1009 itm[type] = idx;
1010 }
1011
1012 void ListBoxImpl::ClearRegisteredImages() {
1013 if (imgList) {
1014 delete imgList;
1015 imgList = NULL;
1016 }
1017 if (imgTypeMap) {
1018 delete imgTypeMap;
1019 imgTypeMap = NULL;
1020 }
1021 if (id)
1022 GETLB(id)->SetImageList(NULL, wxIMAGE_LIST_SMALL);
1023 }
1024
1025
1026 void ListBoxImpl::SetDoubleClickAction(CallBackAction action, void *data) {
1027 GETLBW(id)->SetDoubleClickAction(action, data);
1028 }
1029
1030
1031
1032 ListBox::ListBox() {
1033 }
1034
1035 ListBox::~ListBox() {
1036 }
1037
1038 ListBox *ListBox::Allocate() {
1039 return new ListBoxImpl();
1040 }
1041
1042 //----------------------------------------------------------------------
1043
1044 Menu::Menu() : id(0) {
1045 }
1046
1047 void Menu::CreatePopUp() {
1048 Destroy();
1049 id = new wxMenu();
1050 }
1051
1052 void Menu::Destroy() {
1053 if (id)
1054 delete (wxMenu*)id;
1055 id = 0;
1056 }
1057
1058 void Menu::Show(Point pt, Window &w) {
1059 GETWIN(w.GetID())->PopupMenu((wxMenu*)id, pt.x - 4, pt.y);
1060 Destroy();
1061 }
1062
1063 //----------------------------------------------------------------------
1064
1065 DynamicLibrary *DynamicLibrary::Load(const char *modulePath) {
1066 wxFAIL_MSG(wxT("Dynamic lexer loading not implemented yet"));
1067 return NULL;
1068 }
1069
1070 //----------------------------------------------------------------------
1071
1072 ColourDesired Platform::Chrome() {
1073 wxColour c;
1074 c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
1075 return ColourDesired(c.Red(), c.Green(), c.Blue());
1076 }
1077
1078 ColourDesired Platform::ChromeHighlight() {
1079 wxColour c;
1080 c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT);
1081 return ColourDesired(c.Red(), c.Green(), c.Blue());
1082 }
1083
1084 const char *Platform::DefaultFont() {
1085 static char buf[128];
1086 strcpy(buf, wxNORMAL_FONT->GetFaceName().mbc_str());
1087 return buf;
1088 }
1089
1090 int Platform::DefaultFontSize() {
1091 return wxNORMAL_FONT->GetPointSize();
1092 }
1093
1094 unsigned int Platform::DoubleClickTime() {
1095 return 500; // **** ::GetDoubleClickTime();
1096 }
1097
1098 bool Platform::MouseButtonBounce() {
1099 return FALSE;
1100 }
1101 void Platform::DebugDisplay(const char *s) {
1102 wxLogDebug(stc2wx(s));
1103 }
1104
1105 bool Platform::IsKeyDown(int key) {
1106 return false; // I don't think we'll need this.
1107 }
1108
1109 long Platform::SendScintilla(WindowID w,
1110 unsigned int msg,
1111 unsigned long wParam,
1112 long lParam) {
1113
1114 wxStyledTextCtrl* stc = (wxStyledTextCtrl*)w;
1115 return stc->SendMsg(msg, wParam, lParam);
1116 }
1117
1118 long Platform::SendScintillaPointer(WindowID w,
1119 unsigned int msg,
1120 unsigned long wParam,
1121 void *lParam) {
1122
1123 wxStyledTextCtrl* stc = (wxStyledTextCtrl*)w;
1124 return stc->SendMsg(msg, wParam, (long)lParam);
1125 }
1126
1127
1128 // These are utility functions not really tied to a platform
1129
1130 int Platform::Minimum(int a, int b) {
1131 if (a < b)
1132 return a;
1133 else
1134 return b;
1135 }
1136
1137 int Platform::Maximum(int a, int b) {
1138 if (a > b)
1139 return a;
1140 else
1141 return b;
1142 }
1143
1144 #define TRACE
1145
1146 void Platform::DebugPrintf(const char *format, ...) {
1147 #ifdef TRACE
1148 char buffer[2000];
1149 va_list pArguments;
1150 va_start(pArguments, format);
1151 vsprintf(buffer,format,pArguments);
1152 va_end(pArguments);
1153 Platform::DebugDisplay(buffer);
1154 #endif
1155 }
1156
1157
1158 static bool assertionPopUps = true;
1159
1160 bool Platform::ShowAssertionPopUps(bool assertionPopUps_) {
1161 bool ret = assertionPopUps;
1162 assertionPopUps = assertionPopUps_;
1163 return ret;
1164 }
1165
1166 void Platform::Assert(const char *c, const char *file, int line) {
1167 char buffer[2000];
1168 sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line);
1169 if (assertionPopUps) {
1170 /*int idButton = */
1171 wxMessageBox(stc2wx(buffer),
1172 wxT("Assertion failure"),
1173 wxICON_HAND | wxOK);
1174 // if (idButton == IDRETRY) {
1175 // ::DebugBreak();
1176 // } else if (idButton == IDIGNORE) {
1177 // // all OK
1178 // } else {
1179 // abort();
1180 // }
1181 } else {
1182 strcat(buffer, "\r\n");
1183 Platform::DebugDisplay(buffer);
1184 abort();
1185 }
1186 }
1187
1188
1189 int Platform::Clamp(int val, int minVal, int maxVal) {
1190 if (val > maxVal)
1191 val = maxVal;
1192 if (val < minVal)
1193 val = minVal;
1194 return val;
1195 }
1196
1197
1198 bool Platform::IsDBCSLeadByte(int codePage, char ch) {
1199 return false;
1200 }
1201
1202 int Platform::DBCSCharLength(int codePage, const char *s) {
1203 return 1;
1204 }
1205
1206 int Platform::DBCSCharMaxLength() {
1207 return 1;
1208 }
1209
1210
1211 //----------------------------------------------------------------------
1212
1213 ElapsedTime::ElapsedTime() {
1214 wxStartTimer();
1215 }
1216
1217 double ElapsedTime::Duration(bool reset) {
1218 double result = wxGetElapsedTime(reset);
1219 result /= 1000.0;
1220 return result;
1221 }
1222
1223
1224 //----------------------------------------------------------------------
1225
1226 #if wxUSE_UNICODE
1227 wxString stc2wx(const char* str, size_t len)
1228 {
1229 char *buffer=new char[len+1];
1230 strncpy(buffer, str, len);
1231 buffer[len]=0;
1232
1233 wxString cstr(buffer, wxConvUTF8);
1234
1235 delete[] buffer;
1236 return cstr;
1237 }
1238 #endif
1239
1240
1241
1242
1243
1244