]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/stc/PlatWX.cpp
A little clarification
[wxWidgets.git] / src / stc / PlatWX.cpp
... / ...
CommitLineData
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
26Point Point::FromLong(long lpoint) {
27 return Point(lpoint & 0xFFFF, lpoint >> 16);
28}
29
30wxRect wxRectFromPRectangle(PRectangle prc) {
31 wxRect rc(prc.left, prc.top,
32 prc.right-prc.left, prc.bottom-prc.top);
33 return rc;
34}
35
36PRectangle PRectangleFromwxRect(wxRect rc) {
37 return PRectangle(rc.GetLeft(), rc.GetTop(),
38 rc.GetRight()+1, rc.GetBottom()+1);
39}
40
41wxColour wxColourFromCA(const ColourAllocated& ca) {
42 ColourDesired cd(ca.AsLong());
43 return wxColour(cd.GetRed(), cd.GetGreen(), cd.GetBlue());
44}
45
46//----------------------------------------------------------------------
47
48Palette::Palette() {
49 used = 0;
50 allowRealization = false;
51}
52
53Palette::~Palette() {
54 Release();
55}
56
57void 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.
64void 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
87void Palette::Allocate(Window &) {
88 if (allowRealization) {
89 }
90}
91
92
93//----------------------------------------------------------------------
94
95Font::Font() {
96 id = 0;
97 ascent = 0;
98}
99
100Font::~Font() {
101}
102
103void 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
198void Font::Release() {
199 if (id)
200 delete (wxFont*)id;
201 id = 0;
202}
203
204//----------------------------------------------------------------------
205
206class SurfaceImpl : public Surface {
207private:
208 wxDC* hdc;
209 bool hdcOwned;
210 wxBitmap* bitmap;
211 int x;
212 int y;
213 bool unicodeMode;
214
215public:
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
264SurfaceImpl::SurfaceImpl() :
265 hdc(0), hdcOwned(0), bitmap(0),
266 x(0), y(0), unicodeMode(0)
267{}
268
269SurfaceImpl::~SurfaceImpl() {
270 Release();
271}
272
273void 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
286void SurfaceImpl::Init(SurfaceID hdc_, WindowID) {
287 Release();
288 hdc = (wxDC*)hdc_;
289}
290
291void SurfaceImpl::InitPixMap(int width, int height, Surface *WXUNUSED(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
302void 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
316bool SurfaceImpl::Initialised() {
317 return hdc != 0;
318}
319
320
321void SurfaceImpl::PenColour(ColourAllocated fore) {
322 hdc->SetPen(wxPen(wxColourFromCA(fore), 1, wxSOLID));
323}
324
325void SurfaceImpl::BrushColour(ColourAllocated back) {
326 hdc->SetBrush(wxBrush(wxColourFromCA(back), wxSOLID));
327}
328
329void SurfaceImpl::SetFont(Font &font_) {
330 if (font_.GetID()) {
331 hdc->SetFont(*((wxFont*)font_.GetID()));
332 }
333}
334
335int SurfaceImpl::LogPixelsY() {
336 return hdc->GetPPI().y;
337}
338
339int SurfaceImpl::DeviceHeightFont(int points) {
340 return points;
341}
342
343void SurfaceImpl::MoveTo(int x_, int y_) {
344 x = x_;
345 y = y_;
346}
347
348void SurfaceImpl::LineTo(int x_, int y_) {
349 hdc->DrawLine(x,y, x_,y_);
350 x = x_;
351 y = y_;
352}
353
354void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) {
355 PenColour(fore);
356 BrushColour(back);
357 hdc->DrawPolygon(npts, (wxPoint*)pts);
358}
359
360void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
361 PenColour(fore);
362 BrushColour(back);
363 hdc->DrawRectangle(wxRectFromPRectangle(rc));
364}
365
366void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) {
367 BrushColour(back);
368 hdc->SetPen(*wxTRANSPARENT_PEN);
369 hdc->DrawRectangle(wxRectFromPRectangle(rc));
370}
371
372void 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
383void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
384 PenColour(fore);
385 BrushColour(back);
386 hdc->DrawRoundedRectangle(wxRectFromPRectangle(rc), 4);
387}
388
389void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
390 PenColour(fore);
391 BrushColour(back);
392 hdc->DrawEllipse(wxRectFromPRectangle(rc));
393}
394
395void 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
402void 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
415void 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 hdc->DestroyClippingRegion();
427}
428
429
430void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font, int ybase,
431 const char *s, int len,
432 ColourAllocated fore) {
433
434 SetFont(font);
435 hdc->SetTextForeground(wxColourFromCA(fore));
436 hdc->SetBackgroundMode(wxTRANSPARENT);
437
438 // ybase is where the baseline should be, but wxWin uses the upper left
439 // corner, so I need to calculate the real position for the text...
440 hdc->DrawText(stc2wx(s, len), rc.left, ybase - font.ascent);
441
442 hdc->SetBackgroundMode(wxSOLID);
443}
444
445
446void SurfaceImpl::MeasureWidths(Font &font, const char *s, int len, int *positions) {
447
448 wxString str = stc2wx(s, len);
449 SetFont(font);
450
451#ifndef __WXMAC__
452 // Calculate the position of each character based on the widths of
453 // the previous characters
454 int* tpos = new int[len+1];
455 int totalWidth = 0;
456 size_t i;
457 for (i=0; i<str.Length(); i++) {
458 int w, h;
459 hdc->GetTextExtent(str[i], &w, &h);
460 totalWidth += w;
461 tpos[i] = totalWidth;
462 }
463#else
464 // Instead of a running total, remeasure from the begining of the
465 // text for each character's position. This is because with AA fonts
466 // on OS X widths can be fractions of pixels wide when more than one
467 // are drawn together, so the sum of all character widths is not necessarily
468 // (and probably not) the same as the whole string width.
469 int* tpos = new int[len+1];
470 size_t i;
471 for (i=0; i<str.Length(); i++) {
472 int w, h;
473 hdc->GetTextExtent(str.Left(i+1), &w, &h);
474 tpos[i] = w;
475 }
476#endif
477
478
479#if wxUSE_UNICODE
480 // Map the widths for UCS-2 characters back to the UTF-8 input string
481 // NOTE: I don't think this is right for when sizeof(wxChar) > 2, ie wxGTK2
482 // so figure it out and fix it!
483 i = 0;
484 size_t ui = 0;
485 while ((int)i < len) {
486 unsigned char uch = (unsigned char)s[i];
487 positions[i++] = tpos[ui];
488 if (uch >= 0x80) {
489 if (uch < (0x80 + 0x40 + 0x20)) {
490 positions[i++] = tpos[ui];
491 } else {
492 positions[i++] = tpos[ui];
493 positions[i++] = tpos[ui];
494 }
495 }
496 ui++;
497 }
498#else
499
500 // If not unicode then just use the widths we have
501 memcpy(positions, tpos, len * sizeof(*tpos));
502#endif
503
504 delete [] tpos;
505}
506
507
508int SurfaceImpl::WidthText(Font &font, const char *s, int len) {
509 SetFont(font);
510 int w;
511 int h;
512
513 hdc->GetTextExtent(stc2wx(s, len), &w, &h);
514 return w;
515}
516
517
518int SurfaceImpl::WidthChar(Font &font, char ch) {
519 SetFont(font);
520 int w;
521 int h;
522 char s[2] = { ch, 0 };
523
524 hdc->GetTextExtent(stc2wx(s, 1), &w, &h);
525 return w;
526}
527
528#define EXTENT_TEST wxT(" `~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
529
530int SurfaceImpl::Ascent(Font &font) {
531 SetFont(font);
532 int w, h, d, e;
533 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
534 font.ascent = h - d;
535 return font.ascent;
536}
537
538int SurfaceImpl::Descent(Font &font) {
539 SetFont(font);
540 int w, h, d, e;
541 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
542 return d;
543}
544
545int SurfaceImpl::InternalLeading(Font &WXUNUSED(font)) {
546 return 0;
547}
548
549int SurfaceImpl::ExternalLeading(Font &font) {
550 SetFont(font);
551 int w, h, d, e;
552 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
553 return e;
554}
555
556int SurfaceImpl::Height(Font &font) {
557 SetFont(font);
558 return hdc->GetCharHeight();
559}
560
561int SurfaceImpl::AverageCharWidth(Font &font) {
562 SetFont(font);
563 return hdc->GetCharWidth();
564}
565
566int SurfaceImpl::SetPalette(Palette *WXUNUSED(pal), bool WXUNUSED(inBackGround)) {
567 return 0;
568}
569
570void SurfaceImpl::SetClip(PRectangle rc) {
571 hdc->SetClippingRegion(wxRectFromPRectangle(rc));
572}
573
574void SurfaceImpl::FlushCachedState() {
575}
576
577void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {
578 unicodeMode=unicodeMode_;
579}
580
581void SurfaceImpl::SetDBCSMode(int WXUNUSED(codePage)) {
582 // dbcsMode = codePage == SC_CP_DBCS;
583}
584
585
586Surface *Surface::Allocate() {
587 return new SurfaceImpl;
588}
589
590
591//----------------------------------------------------------------------
592
593
594inline wxWindow* GETWIN(WindowID id) { return (wxWindow*)id; }
595
596Window::~Window() {
597}
598
599void Window::Destroy() {
600 if (id) {
601 Show(FALSE);
602 GETWIN(id)->Destroy();
603 }
604 id = 0;
605}
606
607bool Window::HasFocus() {
608 return wxWindow::FindFocus() == GETWIN(id);
609}
610
611PRectangle Window::GetPosition() {
612 if (! id) return PRectangle();
613 wxRect rc(GETWIN(id)->GetPosition(), GETWIN(id)->GetSize());
614 return PRectangleFromwxRect(rc);
615}
616
617void Window::SetPosition(PRectangle rc) {
618 wxRect r = wxRectFromPRectangle(rc);
619 GETWIN(id)->SetSize(r);
620}
621
622void Window::SetPositionRelative(PRectangle rc, Window) {
623 SetPosition(rc); // ????
624}
625
626PRectangle Window::GetClientPosition() {
627 if (! id) return PRectangle();
628 wxSize sz = GETWIN(id)->GetClientSize();
629 return PRectangle(0, 0, sz.x, sz.y);
630}
631
632void Window::Show(bool show) {
633 GETWIN(id)->Show(show);
634}
635
636void Window::InvalidateAll() {
637 GETWIN(id)->Refresh(false);
638 wxWakeUpIdle();
639}
640
641void Window::InvalidateRectangle(PRectangle rc) {
642 wxRect r = wxRectFromPRectangle(rc);
643 GETWIN(id)->Refresh(false, &r);
644 wxWakeUpIdle();
645}
646
647void Window::SetFont(Font &font) {
648 GETWIN(id)->SetFont(*((wxFont*)font.GetID()));
649}
650
651void Window::SetCursor(Cursor curs) {
652 int cursorId;
653
654 switch (curs) {
655 case cursorText:
656 cursorId = wxCURSOR_IBEAM;
657 break;
658 case cursorArrow:
659 cursorId = wxCURSOR_ARROW;
660 break;
661 case cursorUp:
662 cursorId = wxCURSOR_ARROW; // ** no up arrow... wxCURSOR_UPARROW;
663 break;
664 case cursorWait:
665 cursorId = wxCURSOR_WAIT;
666 break;
667 case cursorHoriz:
668 cursorId = wxCURSOR_SIZEWE;
669 break;
670 case cursorVert:
671 cursorId = wxCURSOR_SIZENS;
672 break;
673 case cursorReverseArrow:
674 cursorId = wxCURSOR_RIGHT_ARROW;
675 break;
676 case cursorHand:
677 cursorId = wxCURSOR_HAND;
678 break;
679 default:
680 cursorId = wxCURSOR_ARROW;
681 break;
682 }
683#ifdef __WXMOTIF__
684 wxCursor wc = wxStockCursor(cursorId) ;
685#else
686 wxCursor wc = wxCursor(cursorId) ;
687#endif
688 GETWIN(id)->SetCursor(wc);
689}
690
691
692void Window::SetTitle(const char *s) {
693 GETWIN(id)->SetTitle(stc2wx(s));
694}
695
696
697//----------------------------------------------------------------------
698// Helper classes for ListBox
699
700
701// This is a simple subclass of wxListView that just resets focus to the
702// parent when it gets it.
703class wxSTCListBox : public wxListView {
704public:
705 wxSTCListBox(wxWindow* parent, wxWindowID id,
706 const wxPoint& pos, const wxSize& size,
707 long style)
708 : wxListView(parent, id, pos, size, style)
709 {}
710
711 void OnFocus(wxFocusEvent& event) {
712 GetParent()->SetFocus();
713 event.Skip();
714 }
715
716 void OnKillFocus(wxFocusEvent& event) {
717 // Do nothing. Prevents base class from resetting the colors...
718 }
719
720private:
721 DECLARE_EVENT_TABLE()
722};
723
724BEGIN_EVENT_TABLE(wxSTCListBox, wxListView)
725 EVT_SET_FOCUS( wxSTCListBox::OnFocus)
726 EVT_KILL_FOCUS(wxSTCListBox::OnKillFocus)
727END_EVENT_TABLE()
728
729
730
731
732// A window to place the wxSTCListBox upon
733class wxSTCListBoxWin : public wxWindow {
734private:
735 wxListView* lv;
736 CallBackAction doubleClickAction;
737 void* doubleClickActionData;
738public:
739 wxSTCListBoxWin(wxWindow* parent, wxWindowID id) :
740 wxWindow(parent, id, wxDefaultPosition, wxSize(0,0), wxNO_BORDER )
741 {
742
743 SetBackgroundColour(*wxBLACK);
744 lv = new wxSTCListBox(this, id, wxDefaultPosition, wxDefaultSize,
745 wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_NO_HEADER | wxNO_BORDER);
746 lv->SetCursor(wxCursor(wxCURSOR_ARROW));
747 lv->InsertColumn(0, wxEmptyString);
748 lv->InsertColumn(1, wxEmptyString);
749
750 // Eventhough we immediately reset the focus to the parent, this helps
751 // things to look right...
752 lv->SetFocus();
753
754 Hide();
755 }
756
757
758 // On OSX and (possibly others) there can still be pending
759 // messages/events for the list control when Scintilla wants to
760 // close it, so do a pending delete of it instead of destroying
761 // immediately.
762 bool Destroy() {
763 if ( !wxPendingDelete.Member(this) )
764 wxPendingDelete.Append(this);
765 return TRUE;
766 }
767
768
769 int IconWidth() {
770 wxImageList* il = lv->GetImageList(wxIMAGE_LIST_SMALL);
771 if (il != NULL) {
772 int w, h;
773 il->GetSize(0, w, h);
774 return w;
775 }
776 return 0;
777 }
778
779
780 void SetDoubleClickAction(CallBackAction action, void *data) {
781 doubleClickAction = action;
782 doubleClickActionData = data;
783 }
784
785
786 void OnFocus(wxFocusEvent& event) {
787 GetParent()->SetFocus();
788 event.Skip();
789 }
790
791 void OnSize(wxSizeEvent& event) {
792 // resize the child, leaving a 1 pixel border
793 wxSize sz = GetClientSize();
794 lv->SetSize(1, 1, sz.x-2, sz.y-2);
795 // reset the column widths
796 lv->SetColumnWidth(0, IconWidth()+4);
797 lv->SetColumnWidth(1, sz.x - 2 - lv->GetColumnWidth(0) -
798 wxSystemSettings::GetMetric(wxSYS_VSCROLL_X));
799 event.Skip();
800 }
801
802 void OnActivate(wxListEvent& event) {
803 doubleClickAction(doubleClickActionData);
804 }
805
806 wxListView* GetLB() { return lv; }
807
808private:
809 DECLARE_EVENT_TABLE()
810};
811
812
813BEGIN_EVENT_TABLE(wxSTCListBoxWin, wxWindow)
814 EVT_SET_FOCUS ( wxSTCListBoxWin::OnFocus)
815 EVT_SIZE ( wxSTCListBoxWin::OnSize)
816 EVT_LIST_ITEM_ACTIVATED(-1, wxSTCListBoxWin::OnActivate)
817END_EVENT_TABLE()
818
819
820
821inline wxSTCListBoxWin* GETLBW(WindowID win) {
822 return ((wxSTCListBoxWin*)win);
823}
824
825inline wxListView* GETLB(WindowID win) {
826 return GETLBW(win)->GetLB();
827}
828
829//----------------------------------------------------------------------
830
831class ListBoxImpl : public ListBox {
832private:
833 int lineHeight;
834 bool unicodeMode;
835 int desiredVisibleRows;
836 int aveCharWidth;
837 int maxStrWidth;
838 wxImageList* imgList;
839 wxArrayInt* imgTypeMap;
840
841public:
842 ListBoxImpl();
843 ~ListBoxImpl();
844
845 virtual void SetFont(Font &font);
846 virtual void Create(Window &parent, int ctrlID, int lineHeight_, bool unicodeMode_);
847 virtual void SetAverageCharWidth(int width);
848 virtual void SetVisibleRows(int rows);
849 virtual PRectangle GetDesiredRect();
850 virtual int CaretFromEdge();
851 virtual void Clear();
852 virtual void Append(char *s, int type = -1);
853 virtual int Length();
854 virtual void Select(int n);
855 virtual int GetSelection();
856 virtual int Find(const char *prefix);
857 virtual void GetValue(int n, char *value, int len);
858 virtual void Sort();
859 virtual void RegisterImage(int type, const char *xpm_data);
860 virtual void ClearRegisteredImages();
861 virtual void SetDoubleClickAction(CallBackAction, void *);
862
863};
864
865
866ListBoxImpl::ListBoxImpl()
867 : lineHeight(10), unicodeMode(false),
868 desiredVisibleRows(5), aveCharWidth(8), maxStrWidth(0),
869 imgList(NULL), imgTypeMap(NULL)
870{
871}
872
873ListBoxImpl::~ListBoxImpl() {
874 if (imgList) {
875 delete imgList;
876 imgList = NULL;
877 }
878 if (imgTypeMap) {
879 delete imgTypeMap;
880 imgTypeMap = NULL;
881 }
882}
883
884
885void ListBoxImpl::SetFont(Font &font) {
886 GETLB(id)->SetFont(*((wxFont*)font.GetID()));
887}
888
889
890void ListBoxImpl::Create(Window &parent, int ctrlID, int lineHeight_, bool unicodeMode_) {
891 lineHeight = lineHeight_;
892 unicodeMode = unicodeMode_;
893 maxStrWidth = 0;
894 id = new wxSTCListBoxWin(GETWIN(parent.GetID()), ctrlID);
895 if (imgList != NULL)
896 GETLB(id)->SetImageList(imgList, wxIMAGE_LIST_SMALL);
897}
898
899
900void ListBoxImpl::SetAverageCharWidth(int width) {
901 aveCharWidth = width;
902}
903
904
905void ListBoxImpl::SetVisibleRows(int rows) {
906 desiredVisibleRows = rows;
907}
908
909
910PRectangle ListBoxImpl::GetDesiredRect() {
911 // wxListCtrl doesn't have a DoGetBestSize, so instead we kept track of
912 // the max size in Append and calculate it here...
913 int maxw = maxStrWidth;
914 int maxh ;
915
916 // give it a default if there are no lines, and/or add a bit more
917 if (maxw == 0) maxw = 100;
918 maxw += aveCharWidth * 3 +
919 GETLBW(id)->IconWidth() + wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
920 if (maxw > 350)
921 maxw = 350;
922
923 // estimate a desired height
924 int count = GETLB(id)->GetItemCount();
925 if (count) {
926 wxRect rect;
927 GETLB(id)->GetItemRect(0, rect);
928 maxh = count * rect.GetHeight();
929 if (maxh > 140) // TODO: Use desiredVisibleRows??
930 maxh = 140;
931
932 // Try to make the size an exact multiple of some number of lines
933 int lines = maxh / rect.GetHeight();
934 maxh = (lines + 1) * rect.GetHeight() + 2;
935 }
936 else
937 maxh = 100;
938
939 PRectangle rc;
940 rc.top = 0;
941 rc.left = 0;
942 rc.right = maxw;
943 rc.bottom = maxh;
944 return rc;
945}
946
947
948int ListBoxImpl::CaretFromEdge() {
949 return 4 + GETLBW(id)->IconWidth();
950}
951
952
953void ListBoxImpl::Clear() {
954 GETLB(id)->DeleteAllItems();
955}
956
957
958void ListBoxImpl::Append(char *s, int type) {
959 wxString text = stc2wx(s);
960 long count = GETLB(id)->GetItemCount();
961 long itemID = GETLB(id)->InsertItem(count, wxEmptyString);
962 GETLB(id)->SetItem(itemID, 1, text);
963 int itemWidth = 0;
964 GETLB(id)->GetTextExtent(text, &itemWidth, NULL);
965 maxStrWidth = wxMax(maxStrWidth, itemWidth);
966 if (type != -1) {
967 wxCHECK_RET(imgTypeMap, wxT("Unexpected NULL imgTypeMap"));
968 long idx = imgTypeMap->Item(type);
969 GETLB(id)->SetItemImage(itemID, idx, idx);
970 }
971}
972
973
974int ListBoxImpl::Length() {
975 return GETLB(id)->GetItemCount();
976}
977
978
979void ListBoxImpl::Select(int n) {
980 bool select = TRUE;
981 if (n == -1) {
982 n = 0;
983 select = FALSE;
984 }
985 GETLB(id)->Focus(n);
986 GETLB(id)->Select(n, select);
987}
988
989
990int ListBoxImpl::GetSelection() {
991 return GETLB(id)->GetFirstSelected();
992}
993
994
995int ListBoxImpl::Find(const char *WXUNUSED(prefix)) {
996 // No longer used
997 return -1;
998}
999
1000
1001void ListBoxImpl::GetValue(int n, char *value, int len) {
1002 wxListItem item;
1003 item.SetId(n);
1004 item.SetColumn(1);
1005 item.SetMask(wxLIST_MASK_TEXT);
1006 GETLB(id)->GetItem(item);
1007 strncpy(value, wx2stc(item.GetText()), len);
1008 value[len-1] = '\0';
1009}
1010
1011void ListBoxImpl::Sort() {
1012}
1013
1014
1015void ListBoxImpl::RegisterImage(int type, const char *xpm_data) {
1016 wxMemoryInputStream stream(xpm_data, strlen(xpm_data)+1);
1017 wxBitmap bmp(wxImage(stream, wxBITMAP_TYPE_XPM));
1018
1019 if (! imgList) {
1020 // assumes all images are the same size
1021 imgList = new wxImageList(bmp.GetWidth(), bmp.GetHeight(), TRUE);
1022 imgTypeMap = new wxArrayInt;
1023 }
1024
1025 int idx = imgList->Add(bmp);
1026
1027 // do we need to extend the mapping array?
1028 wxArrayInt& itm = *imgTypeMap;
1029 if ( itm.GetCount() < (size_t)type+1)
1030 itm.Add(-1, type - itm.GetCount() + 1);
1031
1032 // Add an item that maps type to the image index
1033 itm[type] = idx;
1034}
1035
1036void ListBoxImpl::ClearRegisteredImages() {
1037 if (imgList) {
1038 delete imgList;
1039 imgList = NULL;
1040 }
1041 if (imgTypeMap) {
1042 delete imgTypeMap;
1043 imgTypeMap = NULL;
1044 }
1045 if (id)
1046 GETLB(id)->SetImageList(NULL, wxIMAGE_LIST_SMALL);
1047}
1048
1049
1050void ListBoxImpl::SetDoubleClickAction(CallBackAction action, void *data) {
1051 GETLBW(id)->SetDoubleClickAction(action, data);
1052}
1053
1054
1055
1056ListBox::ListBox() {
1057}
1058
1059ListBox::~ListBox() {
1060}
1061
1062ListBox *ListBox::Allocate() {
1063 return new ListBoxImpl();
1064}
1065
1066//----------------------------------------------------------------------
1067
1068Menu::Menu() : id(0) {
1069}
1070
1071void Menu::CreatePopUp() {
1072 Destroy();
1073 id = new wxMenu();
1074}
1075
1076void Menu::Destroy() {
1077 if (id)
1078 delete (wxMenu*)id;
1079 id = 0;
1080}
1081
1082void Menu::Show(Point pt, Window &w) {
1083 GETWIN(w.GetID())->PopupMenu((wxMenu*)id, pt.x - 4, pt.y);
1084 Destroy();
1085}
1086
1087//----------------------------------------------------------------------
1088
1089DynamicLibrary *DynamicLibrary::Load(const char *WXUNUSED(modulePath)) {
1090 wxFAIL_MSG(wxT("Dynamic lexer loading not implemented yet"));
1091 return NULL;
1092}
1093
1094//----------------------------------------------------------------------
1095
1096ColourDesired Platform::Chrome() {
1097 wxColour c;
1098 c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
1099 return ColourDesired(c.Red(), c.Green(), c.Blue());
1100}
1101
1102ColourDesired Platform::ChromeHighlight() {
1103 wxColour c;
1104 c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT);
1105 return ColourDesired(c.Red(), c.Green(), c.Blue());
1106}
1107
1108const char *Platform::DefaultFont() {
1109 static char buf[128];
1110 strcpy(buf, wxNORMAL_FONT->GetFaceName().mbc_str());
1111 return buf;
1112}
1113
1114int Platform::DefaultFontSize() {
1115 return wxNORMAL_FONT->GetPointSize();
1116}
1117
1118unsigned int Platform::DoubleClickTime() {
1119 return 500; // **** ::GetDoubleClickTime();
1120}
1121
1122bool Platform::MouseButtonBounce() {
1123 return FALSE;
1124}
1125void Platform::DebugDisplay(const char *s) {
1126 wxLogDebug(stc2wx(s));
1127}
1128
1129bool Platform::IsKeyDown(int WXUNUSED(key)) {
1130 return false; // I don't think we'll need this.
1131}
1132
1133long Platform::SendScintilla(WindowID w,
1134 unsigned int msg,
1135 unsigned long wParam,
1136 long lParam) {
1137
1138 wxStyledTextCtrl* stc = (wxStyledTextCtrl*)w;
1139 return stc->SendMsg(msg, wParam, lParam);
1140}
1141
1142long Platform::SendScintillaPointer(WindowID w,
1143 unsigned int msg,
1144 unsigned long wParam,
1145 void *lParam) {
1146
1147 wxStyledTextCtrl* stc = (wxStyledTextCtrl*)w;
1148 return stc->SendMsg(msg, wParam, (long)lParam);
1149}
1150
1151
1152// These are utility functions not really tied to a platform
1153
1154int Platform::Minimum(int a, int b) {
1155 if (a < b)
1156 return a;
1157 else
1158 return b;
1159}
1160
1161int Platform::Maximum(int a, int b) {
1162 if (a > b)
1163 return a;
1164 else
1165 return b;
1166}
1167
1168#define TRACE
1169
1170void Platform::DebugPrintf(const char *format, ...) {
1171#ifdef TRACE
1172 char buffer[2000];
1173 va_list pArguments;
1174 va_start(pArguments, format);
1175 vsprintf(buffer,format,pArguments);
1176 va_end(pArguments);
1177 Platform::DebugDisplay(buffer);
1178#endif
1179}
1180
1181
1182static bool assertionPopUps = true;
1183
1184bool Platform::ShowAssertionPopUps(bool assertionPopUps_) {
1185 bool ret = assertionPopUps;
1186 assertionPopUps = assertionPopUps_;
1187 return ret;
1188}
1189
1190void Platform::Assert(const char *c, const char *file, int line) {
1191 char buffer[2000];
1192 sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line);
1193 if (assertionPopUps) {
1194 /*int idButton = */
1195 wxMessageBox(stc2wx(buffer),
1196 wxT("Assertion failure"),
1197 wxICON_HAND | wxOK);
1198// if (idButton == IDRETRY) {
1199// ::DebugBreak();
1200// } else if (idButton == IDIGNORE) {
1201// // all OK
1202// } else {
1203// abort();
1204// }
1205 } else {
1206 strcat(buffer, "\r\n");
1207 Platform::DebugDisplay(buffer);
1208 abort();
1209 }
1210}
1211
1212
1213int Platform::Clamp(int val, int minVal, int maxVal) {
1214 if (val > maxVal)
1215 val = maxVal;
1216 if (val < minVal)
1217 val = minVal;
1218 return val;
1219}
1220
1221
1222bool Platform::IsDBCSLeadByte(int WXUNUSED(codePage), char WXUNUSED(ch)) {
1223 return false;
1224}
1225
1226int Platform::DBCSCharLength(int WXUNUSED(codePage), const char *WXUNUSED(s)) {
1227 return 1;
1228}
1229
1230int Platform::DBCSCharMaxLength() {
1231 return 1;
1232}
1233
1234
1235//----------------------------------------------------------------------
1236
1237ElapsedTime::ElapsedTime() {
1238 wxStartTimer();
1239}
1240
1241double ElapsedTime::Duration(bool reset) {
1242 double result = wxGetElapsedTime(reset);
1243 result /= 1000.0;
1244 return result;
1245}
1246
1247
1248//----------------------------------------------------------------------
1249
1250#if wxUSE_UNICODE
1251wxString stc2wx(const char* str, size_t len)
1252{
1253 char *buffer=new char[len+1];
1254 strncpy(buffer, str, len);
1255 buffer[len]=0;
1256
1257 wxString cstr(buffer, wxConvUTF8);
1258
1259 delete[] buffer;
1260 return cstr;
1261}
1262#endif
1263
1264
1265
1266
1267
1268