Don't use -kAddToPopUp() gettext hack with Scintilla.
[wxWidgets.git] / src / stc / PlatWX.cpp
1 // Scintilla source code edit control
2 // PlatWX.cxx - implementation of platform facilities on wxWidgets
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 // For compilers that support precompilation, includes "wx.h".
8 #include "wx/wxprec.h"
9
10 #ifdef __BORLANDC__
11 #pragma hdrstop
12 #endif
13
14 #if wxUSE_STC
15
16 #ifndef WX_PRECOMP
17 #include "wx/menu.h"
18 #include "wx/dcmemory.h"
19 #include "wx/settings.h"
20 #endif // WX_PRECOMP
21
22 #include <ctype.h>
23
24 #if wxUSE_DISPLAY
25 #include "wx/display.h"
26 #endif
27
28 #include "wx/encconv.h"
29 #include "wx/listctrl.h"
30 #include "wx/mstream.h"
31 #include "wx/image.h"
32 #include "wx/imaglist.h"
33 #include "wx/tokenzr.h"
34
35 #ifdef wxHAS_RAW_BITMAP
36 #include "wx/rawbmp.h"
37 #endif
38 #if wxUSE_GRAPHICS_CONTEXT
39 #include "wx/dcgraph.h"
40 #endif
41
42 #include "Platform.h"
43 #include "PlatWX.h"
44 #include "wx/stc/stc.h"
45 #include "wx/stc/private.h"
46
47
48 Point Point::FromLong(long lpoint) {
49 return Point(lpoint & 0xFFFF, lpoint >> 16);
50 }
51
52 wxRect wxRectFromPRectangle(PRectangle prc) {
53 wxRect r(prc.left, prc.top,
54 prc.Width(), prc.Height());
55 return r;
56 }
57
58 PRectangle PRectangleFromwxRect(wxRect rc) {
59 return PRectangle(rc.GetLeft(), rc.GetTop(),
60 rc.GetRight()+1, rc.GetBottom()+1);
61 }
62
63 wxColour wxColourFromCA(const ColourAllocated& ca) {
64 ColourDesired cd(ca.AsLong());
65 return wxColour((unsigned char)cd.GetRed(),
66 (unsigned char)cd.GetGreen(),
67 (unsigned char)cd.GetBlue());
68 }
69
70 wxColour wxColourFromCAandAlpha(const ColourAllocated& ca, int alpha) {
71 ColourDesired cd(ca.AsLong());
72 return wxColour((unsigned char)cd.GetRed(),
73 (unsigned char)cd.GetGreen(),
74 (unsigned char)cd.GetBlue(),
75 (unsigned char)alpha);
76 }
77
78 //----------------------------------------------------------------------
79
80 Palette::Palette() {
81 used = 0;
82 allowRealization = false;
83 size = 100;
84 entries = new ColourPair[size];
85 }
86
87 Palette::~Palette() {
88 Release();
89 delete [] entries;
90 entries = 0;
91 }
92
93 void Palette::Release() {
94 used = 0;
95 delete [] entries;
96 size = 100;
97 entries = new ColourPair[size];
98 }
99
100 // This method either adds a colour to the list of wanted colours (want==true)
101 // or retrieves the allocated colour back to the ColourPair.
102 // This is one method to make it easier to keep the code for wanting and retrieving in sync.
103 void Palette::WantFind(ColourPair &cp, bool want) {
104 if (want) {
105 for (int i=0; i < used; i++) {
106 if (entries[i].desired == cp.desired)
107 return;
108 }
109
110 if (used >= size) {
111 int sizeNew = size * 2;
112 ColourPair *entriesNew = new ColourPair[sizeNew];
113 for (int j=0; j<size; j++) {
114 entriesNew[j] = entries[j];
115 }
116 delete []entries;
117 entries = entriesNew;
118 size = sizeNew;
119 }
120
121 entries[used].desired = cp.desired;
122 entries[used].allocated.Set(cp.desired.AsLong());
123 used++;
124 } else {
125 for (int i=0; i < used; i++) {
126 if (entries[i].desired == cp.desired) {
127 cp.allocated = entries[i].allocated;
128 return;
129 }
130 }
131 cp.allocated.Set(cp.desired.AsLong());
132 }
133 }
134
135 void Palette::Allocate(Window &) {
136 if (allowRealization) {
137 }
138 }
139
140
141 //----------------------------------------------------------------------
142
143 Font::Font() {
144 fid = 0;
145 ascent = 0;
146 }
147
148 Font::~Font() {
149 }
150
151 void Font::Create(const char *faceName, int characterSet,
152 int size, bool bold, bool italic,
153 int WXUNUSED(extraFontFlag)) {
154 Release();
155
156 // The minus one is done because since Scintilla uses SC_SHARSET_DEFAULT
157 // internally and we need to have wxFONENCODING_DEFAULT == SC_SHARSET_DEFAULT
158 // so we adjust the encoding before passing it to Scintilla. See also
159 // wxStyledTextCtrl::StyleSetCharacterSet
160 wxFontEncoding encoding = (wxFontEncoding)(characterSet-1);
161
162 wxFontEncodingArray ea = wxEncodingConverter::GetPlatformEquivalents(encoding);
163 if (ea.GetCount())
164 encoding = ea[0];
165
166 wxFont* font = new wxFont(size,
167 wxDEFAULT,
168 italic ? wxITALIC : wxNORMAL,
169 bold ? wxBOLD : wxNORMAL,
170 false,
171 stc2wx(faceName),
172 encoding);
173 fid = font;
174 }
175
176
177 void Font::Release() {
178 if (fid)
179 delete (wxFont*)fid;
180 fid = 0;
181 }
182
183 //----------------------------------------------------------------------
184
185 class SurfaceImpl : public Surface {
186 private:
187 wxDC* hdc;
188 bool hdcOwned;
189 wxBitmap* bitmap;
190 int x;
191 int y;
192 bool unicodeMode;
193
194 public:
195 SurfaceImpl();
196 ~SurfaceImpl();
197
198 virtual void Init(WindowID wid);
199 virtual void Init(SurfaceID sid, WindowID wid);
200 virtual void InitPixMap(int width, int height, Surface *surface_, WindowID wid);
201
202 virtual void Release();
203 virtual bool Initialised();
204 virtual void PenColour(ColourAllocated fore);
205 virtual int LogPixelsY();
206 virtual int DeviceHeightFont(int points);
207 virtual void MoveTo(int x_, int y_);
208 virtual void LineTo(int x_, int y_);
209 virtual void Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back);
210 virtual void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back);
211 virtual void FillRectangle(PRectangle rc, ColourAllocated back);
212 virtual void FillRectangle(PRectangle rc, Surface &surfacePattern);
213 virtual void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back);
214 virtual void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
215 ColourAllocated outline, int alphaOutline, int flags);
216 virtual void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back);
217 virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource);
218
219 virtual void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
220 virtual void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
221 virtual void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);
222 virtual void MeasureWidths(Font &font_, const char *s, int len, int *positions);
223 virtual int WidthText(Font &font_, const char *s, int len);
224 virtual int WidthChar(Font &font_, char ch);
225 virtual int Ascent(Font &font_);
226 virtual int Descent(Font &font_);
227 virtual int InternalLeading(Font &font_);
228 virtual int ExternalLeading(Font &font_);
229 virtual int Height(Font &font_);
230 virtual int AverageCharWidth(Font &font_);
231
232 virtual int SetPalette(Palette *pal, bool inBackGround);
233 virtual void SetClip(PRectangle rc);
234 virtual void FlushCachedState();
235
236 virtual void SetUnicodeMode(bool unicodeMode_);
237 virtual void SetDBCSMode(int codePage);
238
239 void BrushColour(ColourAllocated back);
240 void SetFont(Font &font_);
241 };
242
243
244
245 SurfaceImpl::SurfaceImpl() :
246 hdc(0), hdcOwned(0), bitmap(0),
247 x(0), y(0), unicodeMode(0)
248 {}
249
250 SurfaceImpl::~SurfaceImpl() {
251 Release();
252 }
253
254 void SurfaceImpl::Init(WindowID wid) {
255 #if 0
256 Release();
257 hdc = new wxMemoryDC();
258 hdcOwned = true;
259 #else
260 // On Mac and GTK the DC is not really valid until it has a bitmap
261 // selected into it. So instead of just creating the DC with no bitmap,
262 // go ahead and give it one.
263 InitPixMap(1,1,NULL,wid);
264 #endif
265 }
266
267 void SurfaceImpl::Init(SurfaceID hdc_, WindowID) {
268 Release();
269 hdc = (wxDC*)hdc_;
270 }
271
272 void SurfaceImpl::InitPixMap(int width, int height, Surface *WXUNUSED(surface_), WindowID) {
273 Release();
274 hdc = new wxMemoryDC();
275 hdcOwned = true;
276 if (width < 1) width = 1;
277 if (height < 1) height = 1;
278 bitmap = new wxBitmap(width, height);
279 ((wxMemoryDC*)hdc)->SelectObject(*bitmap);
280 }
281
282
283 void SurfaceImpl::Release() {
284 if (bitmap) {
285 ((wxMemoryDC*)hdc)->SelectObject(wxNullBitmap);
286 delete bitmap;
287 bitmap = 0;
288 }
289 if (hdcOwned) {
290 delete hdc;
291 hdc = 0;
292 hdcOwned = false;
293 }
294 }
295
296
297 bool SurfaceImpl::Initialised() {
298 return hdc != 0;
299 }
300
301
302 void SurfaceImpl::PenColour(ColourAllocated fore) {
303 hdc->SetPen(wxPen(wxColourFromCA(fore)));
304 }
305
306 void SurfaceImpl::BrushColour(ColourAllocated back) {
307 hdc->SetBrush(wxBrush(wxColourFromCA(back)));
308 }
309
310 void SurfaceImpl::SetFont(Font &font_) {
311 if (font_.GetID()) {
312 hdc->SetFont(*((wxFont*)font_.GetID()));
313 }
314 }
315
316 int SurfaceImpl::LogPixelsY() {
317 return hdc->GetPPI().y;
318 }
319
320 int SurfaceImpl::DeviceHeightFont(int points) {
321 return points;
322 }
323
324 void SurfaceImpl::MoveTo(int x_, int y_) {
325 x = x_;
326 y = y_;
327 }
328
329 void SurfaceImpl::LineTo(int x_, int y_) {
330 hdc->DrawLine(x,y, x_,y_);
331 x = x_;
332 y = y_;
333 }
334
335 void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) {
336 PenColour(fore);
337 BrushColour(back);
338 hdc->DrawPolygon(npts, (wxPoint*)pts);
339 }
340
341 void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
342 PenColour(fore);
343 BrushColour(back);
344 hdc->DrawRectangle(wxRectFromPRectangle(rc));
345 }
346
347 void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) {
348 BrushColour(back);
349 hdc->SetPen(*wxTRANSPARENT_PEN);
350 hdc->DrawRectangle(wxRectFromPRectangle(rc));
351 }
352
353 void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
354 wxBrush br;
355 if (((SurfaceImpl&)surfacePattern).bitmap)
356 br = wxBrush(*((SurfaceImpl&)surfacePattern).bitmap);
357 else // Something is wrong so display in red
358 br = wxBrush(*wxRED);
359 hdc->SetPen(*wxTRANSPARENT_PEN);
360 hdc->SetBrush(br);
361 hdc->DrawRectangle(wxRectFromPRectangle(rc));
362 }
363
364 void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
365 PenColour(fore);
366 BrushColour(back);
367 hdc->DrawRoundedRectangle(wxRectFromPRectangle(rc), 4);
368 }
369
370 #ifdef __WXMSW__
371 #define wxPy_premultiply(p, a) ((p) * (a) / 0xff)
372 #else
373 #define wxPy_premultiply(p, a) (p)
374 #endif
375
376 void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize,
377 ColourAllocated fill, int alphaFill,
378 ColourAllocated outline, int alphaOutline,
379 int /*flags*/) {
380 #if wxUSE_GRAPHICS_CONTEXT
381 wxGCDC dc(*(wxMemoryDC*)hdc);
382 wxColour penColour(wxColourFromCAandAlpha(outline, alphaOutline));
383 wxColour brushColour(wxColourFromCAandAlpha(fill, alphaFill));
384 dc.SetPen(wxPen(penColour));
385 dc.SetBrush(wxBrush(brushColour));
386 dc.DrawRoundedRectangle(wxRectFromPRectangle(rc), cornerSize);
387 return;
388 #else
389
390 #ifdef wxHAS_RAW_BITMAP
391
392 // TODO: do something with cornerSize
393 wxUnusedVar(cornerSize);
394
395 int x, y;
396 wxRect r = wxRectFromPRectangle(rc);
397 wxBitmap bmp(r.width, r.height, 32);
398 wxAlphaPixelData pixData(bmp);
399
400 // Set the fill pixels
401 ColourDesired cdf(fill.AsLong());
402 int red = cdf.GetRed();
403 int green = cdf.GetGreen();
404 int blue = cdf.GetBlue();
405
406 wxAlphaPixelData::Iterator p(pixData);
407 for (y=0; y<r.height; y++) {
408 p.MoveTo(pixData, 0, y);
409 for (x=0; x<r.width; x++) {
410 p.Red() = wxPy_premultiply(red, alphaFill);
411 p.Green() = wxPy_premultiply(green, alphaFill);
412 p.Blue() = wxPy_premultiply(blue, alphaFill);
413 p.Alpha() = alphaFill;
414 ++p;
415 }
416 }
417
418 // Set the outline pixels
419 ColourDesired cdo(outline.AsLong());
420 red = cdo.GetRed();
421 green = cdo.GetGreen();
422 blue = cdo.GetBlue();
423 for (x=0; x<r.width; x++) {
424 p.MoveTo(pixData, x, 0);
425 p.Red() = wxPy_premultiply(red, alphaOutline);
426 p.Green() = wxPy_premultiply(green, alphaOutline);
427 p.Blue() = wxPy_premultiply(blue, alphaOutline);
428 p.Alpha() = alphaOutline;
429 p.MoveTo(pixData, x, r.height-1);
430 p.Red() = wxPy_premultiply(red, alphaOutline);
431 p.Green() = wxPy_premultiply(green, alphaOutline);
432 p.Blue() = wxPy_premultiply(blue, alphaOutline);
433 p.Alpha() = alphaOutline;
434 }
435
436 for (y=0; y<r.height; y++) {
437 p.MoveTo(pixData, 0, y);
438 p.Red() = wxPy_premultiply(red, alphaOutline);
439 p.Green() = wxPy_premultiply(green, alphaOutline);
440 p.Blue() = wxPy_premultiply(blue, alphaOutline);
441 p.Alpha() = alphaOutline;
442 p.MoveTo(pixData, r.width-1, y);
443 p.Red() = wxPy_premultiply(red, alphaOutline);
444 p.Green() = wxPy_premultiply(green, alphaOutline);
445 p.Blue() = wxPy_premultiply(blue, alphaOutline);
446 p.Alpha() = alphaOutline;
447 }
448
449 // Draw the bitmap
450 hdc->DrawBitmap(bmp, r.x, r.y, true);
451
452 #else
453 wxUnusedVar(cornerSize);
454 wxUnusedVar(alphaFill);
455 wxUnusedVar(alphaOutline);
456 RectangleDraw(rc, outline, fill);
457 #endif
458 #endif
459 }
460
461 void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
462 PenColour(fore);
463 BrushColour(back);
464 hdc->DrawEllipse(wxRectFromPRectangle(rc));
465 }
466
467 void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
468 wxRect r = wxRectFromPRectangle(rc);
469 hdc->Blit(r.x, r.y, r.width, r.height,
470 ((SurfaceImpl&)surfaceSource).hdc,
471 from.x, from.y, wxCOPY);
472 }
473
474 void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font, int ybase,
475 const char *s, int len,
476 ColourAllocated fore, ColourAllocated back) {
477 SetFont(font);
478 hdc->SetTextForeground(wxColourFromCA(fore));
479 hdc->SetTextBackground(wxColourFromCA(back));
480 FillRectangle(rc, back);
481
482 // ybase is where the baseline should be, but wxWin uses the upper left
483 // corner, so I need to calculate the real position for the text...
484 hdc->DrawText(stc2wx(s, len), rc.left, ybase - font.ascent);
485 }
486
487 void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font, int ybase,
488 const char *s, int len,
489 ColourAllocated fore, ColourAllocated back) {
490 SetFont(font);
491 hdc->SetTextForeground(wxColourFromCA(fore));
492 hdc->SetTextBackground(wxColourFromCA(back));
493 FillRectangle(rc, back);
494 hdc->SetClippingRegion(wxRectFromPRectangle(rc));
495
496 // see comments above
497 hdc->DrawText(stc2wx(s, len), rc.left, ybase - font.ascent);
498 hdc->DestroyClippingRegion();
499 }
500
501
502 void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font, int ybase,
503 const char *s, int len,
504 ColourAllocated fore) {
505
506 SetFont(font);
507 hdc->SetTextForeground(wxColourFromCA(fore));
508 hdc->SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT);
509
510 // ybase is where the baseline should be, but wxWin uses the upper left
511 // corner, so I need to calculate the real position for the text...
512 hdc->DrawText(stc2wx(s, len), rc.left, ybase - font.ascent);
513
514 hdc->SetBackgroundMode(wxBRUSHSTYLE_SOLID);
515 }
516
517
518 void SurfaceImpl::MeasureWidths(Font &font, const char *s, int len, int *positions) {
519
520 wxString str = stc2wx(s, len);
521 wxArrayInt tpos;
522
523 SetFont(font);
524
525 hdc->GetPartialTextExtents(str, tpos);
526
527 #if wxUSE_UNICODE
528 // Map the widths for UCS-2 characters back to the UTF-8 input string
529 // NOTE: I don't think this is right for when sizeof(wxChar) > 2, ie wxGTK2
530 // so figure it out and fix it!
531 size_t i = 0;
532 size_t ui = 0;
533 while ((int)i < len) {
534 unsigned char uch = (unsigned char)s[i];
535 positions[i++] = tpos[ui];
536 if (uch >= 0x80) {
537 if (uch < (0x80 + 0x40 + 0x20)) {
538 positions[i++] = tpos[ui];
539 } else {
540 positions[i++] = tpos[ui];
541 positions[i++] = tpos[ui];
542 }
543 }
544 ui++;
545 }
546 #else
547
548 // If not unicode then just use the widths we have
549 #if wxUSE_STL
550 std::copy(tpos.begin(), tpos.end(), positions);
551 #else
552 memcpy(positions, tpos.begin(), len * sizeof(int));
553 #endif
554 #endif
555 }
556
557
558 int SurfaceImpl::WidthText(Font &font, const char *s, int len) {
559 SetFont(font);
560 int w;
561 int h;
562
563 hdc->GetTextExtent(stc2wx(s, len), &w, &h);
564 return w;
565 }
566
567
568 int SurfaceImpl::WidthChar(Font &font, char ch) {
569 SetFont(font);
570 int w;
571 int h;
572 char s[2] = { ch, 0 };
573
574 hdc->GetTextExtent(stc2wx(s, 1), &w, &h);
575 return w;
576 }
577
578 #define EXTENT_TEST wxT(" `~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
579
580 int SurfaceImpl::Ascent(Font &font) {
581 SetFont(font);
582 int w, h, d, e;
583 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
584 font.ascent = h - d;
585 return font.ascent;
586 }
587
588 int SurfaceImpl::Descent(Font &font) {
589 SetFont(font);
590 int w, h, d, e;
591 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
592 return d;
593 }
594
595 int SurfaceImpl::InternalLeading(Font &WXUNUSED(font)) {
596 return 0;
597 }
598
599 int SurfaceImpl::ExternalLeading(Font &font) {
600 SetFont(font);
601 int w, h, d, e;
602 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
603 return e;
604 }
605
606 int SurfaceImpl::Height(Font &font) {
607 SetFont(font);
608 return hdc->GetCharHeight() + 1;
609 }
610
611 int SurfaceImpl::AverageCharWidth(Font &font) {
612 SetFont(font);
613 return hdc->GetCharWidth();
614 }
615
616 int SurfaceImpl::SetPalette(Palette *WXUNUSED(pal), bool WXUNUSED(inBackGround)) {
617 return 0;
618 }
619
620 void SurfaceImpl::SetClip(PRectangle rc) {
621 hdc->SetClippingRegion(wxRectFromPRectangle(rc));
622 }
623
624 void SurfaceImpl::FlushCachedState() {
625 }
626
627 void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {
628 unicodeMode=unicodeMode_;
629 }
630
631 void SurfaceImpl::SetDBCSMode(int WXUNUSED(codePage)) {
632 // dbcsMode = codePage == SC_CP_DBCS;
633 }
634
635
636 Surface *Surface::Allocate() {
637 return new SurfaceImpl;
638 }
639
640
641 //----------------------------------------------------------------------
642
643
644 inline wxWindow* GETWIN(WindowID id) { return (wxWindow*)id; }
645
646 Window::~Window() {
647 }
648
649 void Window::Destroy() {
650 if (wid) {
651 Show(false);
652 GETWIN(wid)->Destroy();
653 }
654 wid = 0;
655 }
656
657 bool Window::HasFocus() {
658 return wxWindow::FindFocus() == GETWIN(wid);
659 }
660
661 PRectangle Window::GetPosition() {
662 if (! wid) return PRectangle();
663 wxRect rc(GETWIN(wid)->GetPosition(), GETWIN(wid)->GetSize());
664 return PRectangleFromwxRect(rc);
665 }
666
667 void Window::SetPosition(PRectangle rc) {
668 wxRect r = wxRectFromPRectangle(rc);
669 GETWIN(wid)->SetSize(r);
670 }
671
672 void Window::SetPositionRelative(PRectangle rc, Window) {
673 SetPosition(rc); // ????
674 }
675
676 PRectangle Window::GetClientPosition() {
677 if (! wid) return PRectangle();
678 wxSize sz = GETWIN(wid)->GetClientSize();
679 return PRectangle(0, 0, sz.x, sz.y);
680 }
681
682 void Window::Show(bool show) {
683 GETWIN(wid)->Show(show);
684 }
685
686 void Window::InvalidateAll() {
687 GETWIN(wid)->Refresh(false);
688 }
689
690 void Window::InvalidateRectangle(PRectangle rc) {
691 wxRect r = wxRectFromPRectangle(rc);
692 GETWIN(wid)->Refresh(false, &r);
693 }
694
695 void Window::SetFont(Font &font) {
696 GETWIN(wid)->SetFont(*((wxFont*)font.GetID()));
697 }
698
699 void Window::SetCursor(Cursor curs) {
700 wxStockCursor cursorId;
701
702 switch (curs) {
703 case cursorText:
704 cursorId = wxCURSOR_IBEAM;
705 break;
706 case cursorArrow:
707 cursorId = wxCURSOR_ARROW;
708 break;
709 case cursorUp:
710 cursorId = wxCURSOR_ARROW; // ** no up arrow... wxCURSOR_UPARROW;
711 break;
712 case cursorWait:
713 cursorId = wxCURSOR_WAIT;
714 break;
715 case cursorHoriz:
716 cursorId = wxCURSOR_SIZEWE;
717 break;
718 case cursorVert:
719 cursorId = wxCURSOR_SIZENS;
720 break;
721 case cursorReverseArrow:
722 cursorId = wxCURSOR_RIGHT_ARROW;
723 break;
724 case cursorHand:
725 cursorId = wxCURSOR_HAND;
726 break;
727 default:
728 cursorId = wxCURSOR_ARROW;
729 break;
730 }
731
732 wxCursor wc = wxCursor(cursorId);
733 if(curs != cursorLast)
734 {
735 GETWIN(wid)->SetCursor(wc);
736 cursorLast = curs;
737 }
738 }
739
740
741 void Window::SetTitle(const char *s) {
742 GETWIN(wid)->SetLabel(stc2wx(s));
743 }
744
745
746 // Returns rectangle of monitor pt is on
747 PRectangle Window::GetMonitorRect(Point pt) {
748 wxRect rect;
749 if (! wid) return PRectangle();
750 #if wxUSE_DISPLAY
751 // Get the display the point is found on
752 int n = wxDisplay::GetFromPoint(wxPoint(pt.x, pt.y));
753 wxDisplay dpy(n == wxNOT_FOUND ? 0 : n);
754 rect = dpy.GetGeometry();
755 #else
756 wxUnusedVar(pt);
757 #endif
758 return PRectangleFromwxRect(rect);
759 }
760
761 //----------------------------------------------------------------------
762 // Helper classes for ListBox
763
764
765 // This is a simple subclass of wxListView that just resets focus to the
766 // parent when it gets it.
767 class wxSTCListBox : public wxListView {
768 public:
769 wxSTCListBox(wxWindow* parent, wxWindowID id,
770 const wxPoint& pos, const wxSize& size,
771 long style)
772 : wxListView()
773 {
774 #ifdef __WXMSW__
775 Hide(); // don't flicker as we move it around...
776 #endif
777 Create(parent, id, pos, size, style);
778 }
779
780
781 void OnFocus(wxFocusEvent& event) {
782 GetParent()->SetFocus();
783 event.Skip();
784 }
785
786 void OnKillFocus(wxFocusEvent& WXUNUSED(event)) {
787 // Do nothing. Prevents base class from resetting the colors...
788 }
789
790 #ifdef __WXMAC__
791 // For some reason I don't understand yet the focus doesn't really leave
792 // the listbox like it should, so if we get any events feed them back to
793 // the wxSTC
794 void OnKeyDown(wxKeyEvent& event) {
795 GetGrandParent()->GetEventHandler()->ProcessEvent(event);
796 }
797 void OnChar(wxKeyEvent& event) {
798 GetGrandParent()->GetEventHandler()->ProcessEvent(event);
799 }
800
801 // And we need to force the focus back when being destroyed
802 ~wxSTCListBox() {
803 GetGrandParent()->SetFocus();
804 }
805 #endif
806
807 private:
808 DECLARE_EVENT_TABLE()
809 };
810
811 BEGIN_EVENT_TABLE(wxSTCListBox, wxListView)
812 EVT_SET_FOCUS( wxSTCListBox::OnFocus)
813 EVT_KILL_FOCUS(wxSTCListBox::OnKillFocus)
814 #ifdef __WXMAC__
815 EVT_KEY_DOWN( wxSTCListBox::OnKeyDown)
816 EVT_CHAR( wxSTCListBox::OnChar)
817 #endif
818 END_EVENT_TABLE()
819
820
821
822 #if wxUSE_POPUPWIN //-----------------------------------
823 #include "wx/popupwin.h"
824
825 // A popup window to place the wxSTCListBox upon
826 class wxSTCListBoxWin : public wxPopupWindow
827 {
828 private:
829 wxListView* lv;
830 CallBackAction doubleClickAction;
831 void* doubleClickActionData;
832 public:
833 wxSTCListBoxWin(wxWindow* parent, wxWindowID id, Point WXUNUSED(location)) :
834 wxPopupWindow(parent, wxBORDER_SIMPLE)
835 {
836
837 lv = new wxSTCListBox(parent, id, wxPoint(-50,-50), wxDefaultSize,
838 wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_NO_HEADER | wxBORDER_NONE);
839 lv->SetCursor(wxCursor(wxCURSOR_ARROW));
840 lv->InsertColumn(0, wxEmptyString);
841 lv->InsertColumn(1, wxEmptyString);
842
843 // NOTE: We need to fool the wxListView into thinking that it has the
844 // focus so it will use the normal selection colour and will look
845 // "right" to the user. But since the wxPopupWindow or its children
846 // can't receive focus then we have to pull a fast one and temporarily
847 // parent the listctrl on the STC window and then call SetFocus and
848 // then reparent it back to the popup.
849 lv->SetFocus();
850 lv->Reparent(this);
851 #ifdef __WXMSW__
852 lv->Show();
853 #endif
854 }
855
856
857 // Set position in client coords
858 virtual void DoSetSize(int x, int y,
859 int width, int height,
860 int sizeFlags = wxSIZE_AUTO) {
861 if (x != wxDefaultCoord) {
862 GetParent()->ClientToScreen(&x, NULL);
863 }
864 if (y != wxDefaultCoord) {
865 GetParent()->ClientToScreen(NULL, &y);
866 }
867 wxPopupWindow::DoSetSize(x, y, width, height, sizeFlags);
868 }
869
870 // return position as if it were in client coords
871 virtual void DoGetPosition( int *x, int *y ) const {
872 int sx, sy;
873 wxPopupWindow::DoGetPosition(&sx, &sy);
874 GetParent()->ScreenToClient(&sx, &sy);
875 if (x) *x = sx;
876 if (y) *y = sy;
877 }
878
879
880 bool Destroy() {
881 if ( !wxPendingDelete.Member(this) )
882 wxPendingDelete.Append(this);
883 return true;
884 }
885
886
887 int IconWidth() {
888 wxImageList* il = lv->GetImageList(wxIMAGE_LIST_SMALL);
889 if (il != NULL) {
890 int w, h;
891 il->GetSize(0, w, h);
892 return w;
893 }
894 return 0;
895 }
896
897
898 void SetDoubleClickAction(CallBackAction action, void *data) {
899 doubleClickAction = action;
900 doubleClickActionData = data;
901 }
902
903
904 void OnFocus(wxFocusEvent& event) {
905 GetParent()->SetFocus();
906 event.Skip();
907 }
908
909 void OnSize(wxSizeEvent& event) {
910 // resize the child to fill the popup
911 wxSize sz = GetClientSize();
912 lv->SetSize(0, 0, sz.x, sz.y);
913 // reset the column widths
914 lv->SetColumnWidth(0, IconWidth()+4);
915 lv->SetColumnWidth(1, sz.x - 2 - lv->GetColumnWidth(0) -
916 wxSystemSettings::GetMetric(wxSYS_VSCROLL_X));
917 event.Skip();
918 }
919
920 void OnActivate(wxListEvent& WXUNUSED(event)) {
921 doubleClickAction(doubleClickActionData);
922 }
923
924 wxListView* GetLB() { return lv; }
925
926 private:
927 DECLARE_EVENT_TABLE()
928
929 };
930
931 BEGIN_EVENT_TABLE(wxSTCListBoxWin, wxPopupWindow)
932 EVT_SET_FOCUS ( wxSTCListBoxWin::OnFocus)
933 EVT_SIZE ( wxSTCListBoxWin::OnSize)
934 EVT_LIST_ITEM_ACTIVATED(wxID_ANY, wxSTCListBoxWin::OnActivate)
935 END_EVENT_TABLE()
936
937
938
939 #else // !wxUSE_POPUPWIN -----------------------------------
940 #include "wx/frame.h"
941
942 // A normal window to place the wxSTCListBox upon, but make it behave as much
943 // like a wxPopupWindow as possible
944 class wxSTCListBoxWin : public wxFrame {
945 private:
946 wxListView* lv;
947 CallBackAction doubleClickAction;
948 void* doubleClickActionData;
949 public:
950 wxSTCListBoxWin(wxWindow* parent, wxWindowID id, Point location) :
951 wxFrame(parent, id, wxEmptyString, wxPoint(location.x, location.y), wxSize(0,0),
952 wxFRAME_NO_TASKBAR
953 | wxFRAME_FLOAT_ON_PARENT
954 #ifdef __WXMAC__
955 | wxPOPUP_WINDOW
956 | wxNO_BORDER
957 #else
958 | wxSIMPLE_BORDER
959 #endif
960 )
961 {
962
963 lv = new wxSTCListBox(this, id, wxDefaultPosition, wxDefaultSize,
964 wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_NO_HEADER | wxNO_BORDER);
965 lv->SetCursor(wxCursor(wxCURSOR_ARROW));
966 lv->InsertColumn(0, wxEmptyString);
967 lv->InsertColumn(1, wxEmptyString);
968
969 // Eventhough we immediately reset the focus to the parent, this helps
970 // things to look right...
971 lv->SetFocus();
972
973 Hide();
974 }
975
976
977 // On OSX and (possibly others) there can still be pending
978 // messages/events for the list control when Scintilla wants to
979 // close it, so do a pending delete of it instead of destroying
980 // immediately.
981 bool Destroy()
982 {
983 #ifdef __WXMAC__
984 // The bottom edge of this window is not getting properly
985 // refreshed upon deletion, so help it out...
986 wxWindow* p = GetParent();
987 wxRect r(GetPosition(), GetSize());
988 r.SetHeight(r.GetHeight()+1);
989 p->Refresh(false, &r);
990 #endif
991 if ( !wxPendingDelete.Member(this) )
992 wxPendingDelete.Append(this);
993 return true;
994 }
995
996
997 int IconWidth()
998 {
999 wxImageList* il = lv->GetImageList(wxIMAGE_LIST_SMALL);
1000 if (il != NULL) {
1001 int w, h;
1002 il->GetSize(0, w, h);
1003 return w;
1004 }
1005 return 0;
1006 }
1007
1008
1009 void SetDoubleClickAction(CallBackAction action, void *data)
1010 {
1011 doubleClickAction = action;
1012 doubleClickActionData = data;
1013 }
1014
1015
1016 void OnFocus(wxFocusEvent& event)
1017 {
1018 ActivateParent();
1019 GetParent()->SetFocus();
1020 event.Skip();
1021 }
1022
1023 void OnSize(wxSizeEvent& event)
1024 {
1025 // resize the child
1026 wxSize sz = GetClientSize();
1027 lv->SetSize(sz);
1028 // reset the column widths
1029 lv->SetColumnWidth(0, IconWidth()+4);
1030 lv->SetColumnWidth(1, sz.x - 2 - lv->GetColumnWidth(0) -
1031 wxSystemSettings::GetMetric(wxSYS_VSCROLL_X));
1032 event.Skip();
1033 }
1034
1035 void ActivateParent()
1036 {
1037 // Although we're a frame, we always want the parent to be active, so
1038 // raise it whenever we get shown, focused, etc.
1039 wxTopLevelWindow *frame = wxDynamicCast(
1040 wxGetTopLevelParent(GetParent()), wxTopLevelWindow);
1041 if (frame)
1042 frame->Raise();
1043 }
1044
1045
1046 virtual void DoSetSize(int x, int y,
1047 int width, int height,
1048 int sizeFlags = wxSIZE_AUTO)
1049 {
1050 // convert coords to screen coords since we're a top-level window
1051 if (x != wxDefaultCoord) {
1052 GetParent()->ClientToScreen(&x, NULL);
1053 }
1054 if (y != wxDefaultCoord) {
1055 GetParent()->ClientToScreen(NULL, &y);
1056 }
1057 wxFrame::DoSetSize(x, y, width, height, sizeFlags);
1058 }
1059
1060 virtual bool Show(bool show = true)
1061 {
1062 bool rv = wxFrame::Show(show);
1063 if (rv && show)
1064 ActivateParent();
1065 #ifdef __WXMAC__
1066 GetParent()->Refresh(false);
1067 #endif
1068 return rv;
1069 }
1070
1071 void OnActivate(wxListEvent& WXUNUSED(event))
1072 {
1073 doubleClickAction(doubleClickActionData);
1074 }
1075
1076 wxListView* GetLB() { return lv; }
1077
1078 private:
1079 DECLARE_EVENT_TABLE()
1080 };
1081
1082
1083 BEGIN_EVENT_TABLE(wxSTCListBoxWin, wxWindow)
1084 EVT_SET_FOCUS ( wxSTCListBoxWin::OnFocus)
1085 EVT_SIZE ( wxSTCListBoxWin::OnSize)
1086 EVT_LIST_ITEM_ACTIVATED(wxID_ANY, wxSTCListBoxWin::OnActivate)
1087 END_EVENT_TABLE()
1088
1089 #endif // wxUSE_POPUPWIN -----------------------------------
1090
1091
1092 inline wxSTCListBoxWin* GETLBW(WindowID win) {
1093 return ((wxSTCListBoxWin*)win);
1094 }
1095
1096 inline wxListView* GETLB(WindowID win) {
1097 return GETLBW(win)->GetLB();
1098 }
1099
1100 //----------------------------------------------------------------------
1101
1102 class ListBoxImpl : public ListBox {
1103 private:
1104 int lineHeight;
1105 bool unicodeMode;
1106 int desiredVisibleRows;
1107 int aveCharWidth;
1108 size_t maxStrWidth;
1109 Point location; // Caret location at which the list is opened
1110 wxImageList* imgList;
1111 wxArrayInt* imgTypeMap;
1112
1113 public:
1114 ListBoxImpl();
1115 ~ListBoxImpl();
1116
1117 virtual void SetFont(Font &font);
1118 virtual void Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_);
1119 virtual void SetAverageCharWidth(int width);
1120 virtual void SetVisibleRows(int rows);
1121 virtual int GetVisibleRows() const;
1122 virtual PRectangle GetDesiredRect();
1123 virtual int CaretFromEdge();
1124 virtual void Clear();
1125 virtual void Append(char *s, int type = -1);
1126 void Append(const wxString& text, int type);
1127 virtual int Length();
1128 virtual void Select(int n);
1129 virtual int GetSelection();
1130 virtual int Find(const char *prefix);
1131 virtual void GetValue(int n, char *value, int len);
1132 virtual void RegisterImage(int type, const char *xpm_data);
1133 virtual void ClearRegisteredImages();
1134 virtual void SetDoubleClickAction(CallBackAction, void *);
1135 virtual void SetList(const char* list, char separator, char typesep);
1136 };
1137
1138
1139 ListBoxImpl::ListBoxImpl()
1140 : lineHeight(10), unicodeMode(false),
1141 desiredVisibleRows(5), aveCharWidth(8), maxStrWidth(0),
1142 imgList(NULL), imgTypeMap(NULL)
1143 {
1144 }
1145
1146 ListBoxImpl::~ListBoxImpl() {
1147 if (imgList) {
1148 delete imgList;
1149 imgList = NULL;
1150 }
1151 if (imgTypeMap) {
1152 delete imgTypeMap;
1153 imgTypeMap = NULL;
1154 }
1155 }
1156
1157
1158 void ListBoxImpl::SetFont(Font &font) {
1159 GETLB(wid)->SetFont(*((wxFont*)font.GetID()));
1160 }
1161
1162
1163 void ListBoxImpl::Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_) {
1164 location = location_;
1165 lineHeight = lineHeight_;
1166 unicodeMode = unicodeMode_;
1167 maxStrWidth = 0;
1168 wid = new wxSTCListBoxWin(GETWIN(parent.GetID()), ctrlID, location);
1169 if (imgList != NULL)
1170 GETLB(wid)->SetImageList(imgList, wxIMAGE_LIST_SMALL);
1171 }
1172
1173
1174 void ListBoxImpl::SetAverageCharWidth(int width) {
1175 aveCharWidth = width;
1176 }
1177
1178
1179 void ListBoxImpl::SetVisibleRows(int rows) {
1180 desiredVisibleRows = rows;
1181 }
1182
1183
1184 int ListBoxImpl::GetVisibleRows() const {
1185 return desiredVisibleRows;
1186 }
1187
1188 PRectangle ListBoxImpl::GetDesiredRect() {
1189 // wxListCtrl doesn't have a DoGetBestSize, so instead we kept track of
1190 // the max size in Append and calculate it here...
1191 int maxw = maxStrWidth * aveCharWidth;
1192 int maxh ;
1193
1194 // give it a default if there are no lines, and/or add a bit more
1195 if (maxw == 0) maxw = 100;
1196 maxw += aveCharWidth * 3 +
1197 GETLBW(wid)->IconWidth() + wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
1198 if (maxw > 350)
1199 maxw = 350;
1200
1201 // estimate a desired height
1202 int count = GETLB(wid)->GetItemCount();
1203 if (count) {
1204 wxRect rect;
1205 GETLB(wid)->GetItemRect(0, rect);
1206 maxh = count * rect.GetHeight();
1207 if (maxh > 140) // TODO: Use desiredVisibleRows??
1208 maxh = 140;
1209
1210 // Try to make the size an exact multiple of some number of lines
1211 int lines = maxh / rect.GetHeight();
1212 maxh = (lines + 1) * rect.GetHeight() + 2;
1213 }
1214 else
1215 maxh = 100;
1216
1217 PRectangle rc;
1218 rc.top = 0;
1219 rc.left = 0;
1220 rc.right = maxw;
1221 rc.bottom = maxh;
1222 return rc;
1223 }
1224
1225
1226 int ListBoxImpl::CaretFromEdge() {
1227 return 4 + GETLBW(wid)->IconWidth();
1228 }
1229
1230
1231 void ListBoxImpl::Clear() {
1232 GETLB(wid)->DeleteAllItems();
1233 }
1234
1235
1236 void ListBoxImpl::Append(char *s, int type) {
1237 Append(stc2wx(s), type);
1238 }
1239
1240 void ListBoxImpl::Append(const wxString& text, int type) {
1241 long count = GETLB(wid)->GetItemCount();
1242 long itemID = GETLB(wid)->InsertItem(count, wxEmptyString);
1243 long idx = -1;
1244 GETLB(wid)->SetItem(itemID, 1, text);
1245 maxStrWidth = wxMax(maxStrWidth, text.length());
1246 if (type != -1) {
1247 wxCHECK_RET(imgTypeMap, wxT("Unexpected NULL imgTypeMap"));
1248 idx = imgTypeMap->Item(type);
1249 }
1250 GETLB(wid)->SetItemImage(itemID, idx, idx);
1251 }
1252
1253 void ListBoxImpl::SetList(const char* list, char separator, char typesep) {
1254 GETLB(wid)->Freeze();
1255 Clear();
1256 wxStringTokenizer tkzr(stc2wx(list), (wxChar)separator);
1257 while ( tkzr.HasMoreTokens() ) {
1258 wxString token = tkzr.GetNextToken();
1259 long type = -1;
1260 int pos = token.Find(typesep);
1261 if (pos != -1) {
1262 token.Mid(pos+1).ToLong(&type);
1263 token.Truncate(pos);
1264 }
1265 Append(token, (int)type);
1266 }
1267 GETLB(wid)->Thaw();
1268 }
1269
1270
1271 int ListBoxImpl::Length() {
1272 return GETLB(wid)->GetItemCount();
1273 }
1274
1275
1276 void ListBoxImpl::Select(int n) {
1277 bool select = true;
1278 if (n == -1) {
1279 n = 0;
1280 select = false;
1281 }
1282 GETLB(wid)->EnsureVisible(n);
1283 GETLB(wid)->Select(n, select);
1284 }
1285
1286
1287 int ListBoxImpl::GetSelection() {
1288 return GETLB(wid)->GetFirstSelected();
1289 }
1290
1291
1292 int ListBoxImpl::Find(const char *WXUNUSED(prefix)) {
1293 // No longer used
1294 return wxNOT_FOUND;
1295 }
1296
1297
1298 void ListBoxImpl::GetValue(int n, char *value, int len) {
1299 wxListItem item;
1300 item.SetId(n);
1301 item.SetColumn(1);
1302 item.SetMask(wxLIST_MASK_TEXT);
1303 GETLB(wid)->GetItem(item);
1304 strncpy(value, wx2stc(item.GetText()), len);
1305 value[len-1] = '\0';
1306 }
1307
1308
1309 void ListBoxImpl::RegisterImage(int type, const char *xpm_data) {
1310 wxMemoryInputStream stream(xpm_data, strlen(xpm_data)+1);
1311 wxImage img(stream, wxBITMAP_TYPE_XPM);
1312 wxBitmap bmp(img);
1313
1314 if (! imgList) {
1315 // assumes all images are the same size
1316 imgList = new wxImageList(bmp.GetWidth(), bmp.GetHeight(), true);
1317 imgTypeMap = new wxArrayInt;
1318 }
1319
1320 int idx = imgList->Add(bmp);
1321
1322 // do we need to extend the mapping array?
1323 wxArrayInt& itm = *imgTypeMap;
1324 if ( itm.GetCount() < (size_t)type+1)
1325 itm.Add(-1, type - itm.GetCount() + 1);
1326
1327 // Add an item that maps type to the image index
1328 itm[type] = idx;
1329 }
1330
1331 void ListBoxImpl::ClearRegisteredImages() {
1332 if (imgList) {
1333 delete imgList;
1334 imgList = NULL;
1335 }
1336 if (imgTypeMap) {
1337 delete imgTypeMap;
1338 imgTypeMap = NULL;
1339 }
1340 if (wid)
1341 GETLB(wid)->SetImageList(NULL, wxIMAGE_LIST_SMALL);
1342 }
1343
1344
1345 void ListBoxImpl::SetDoubleClickAction(CallBackAction action, void *data) {
1346 GETLBW(wid)->SetDoubleClickAction(action, data);
1347 }
1348
1349
1350 ListBox::ListBox() {
1351 }
1352
1353 ListBox::~ListBox() {
1354 }
1355
1356 ListBox *ListBox::Allocate() {
1357 return new ListBoxImpl();
1358 }
1359
1360 //----------------------------------------------------------------------
1361
1362 Menu::Menu() : mid(0) {
1363 }
1364
1365 void Menu::CreatePopUp() {
1366 Destroy();
1367 mid = new wxMenu();
1368 }
1369
1370 void Menu::Destroy() {
1371 if (mid)
1372 delete (wxMenu*)mid;
1373 mid = 0;
1374 }
1375
1376 void Menu::Show(Point pt, Window &w) {
1377 GETWIN(w.GetID())->PopupMenu((wxMenu*)mid, pt.x - 4, pt.y);
1378 Destroy();
1379 }
1380
1381 //----------------------------------------------------------------------
1382
1383 DynamicLibrary *DynamicLibrary::Load(const char *WXUNUSED(modulePath)) {
1384 wxFAIL_MSG(wxT("Dynamic lexer loading not implemented yet"));
1385 return NULL;
1386 }
1387
1388 //----------------------------------------------------------------------
1389
1390 ColourDesired Platform::Chrome() {
1391 wxColour c;
1392 c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
1393 return ColourDesired(c.Red(), c.Green(), c.Blue());
1394 }
1395
1396 ColourDesired Platform::ChromeHighlight() {
1397 wxColour c;
1398 c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT);
1399 return ColourDesired(c.Red(), c.Green(), c.Blue());
1400 }
1401
1402 const char *Platform::DefaultFont() {
1403 static char buf[128];
1404 strcpy(buf, wxNORMAL_FONT->GetFaceName().mbc_str());
1405 return buf;
1406 }
1407
1408 int Platform::DefaultFontSize() {
1409 return wxNORMAL_FONT->GetPointSize();
1410 }
1411
1412 unsigned int Platform::DoubleClickTime() {
1413 return 500; // **** ::GetDoubleClickTime();
1414 }
1415
1416 bool Platform::MouseButtonBounce() {
1417 return false;
1418 }
1419
1420 bool Platform::IsKeyDown(int WXUNUSED(key)) {
1421 return false; // I don't think we'll need this.
1422 }
1423
1424 long Platform::SendScintilla(WindowID w,
1425 unsigned int msg,
1426 unsigned long wParam,
1427 long lParam) {
1428
1429 wxStyledTextCtrl* stc = (wxStyledTextCtrl*)w;
1430 return stc->SendMsg(msg, wParam, lParam);
1431 }
1432
1433 long Platform::SendScintillaPointer(WindowID w,
1434 unsigned int msg,
1435 unsigned long wParam,
1436 void *lParam) {
1437
1438 wxStyledTextCtrl* stc = (wxStyledTextCtrl*)w;
1439 return stc->SendMsg(msg, wParam, (wxIntPtr)lParam);
1440 }
1441
1442
1443 // These are utility functions not really tied to a platform
1444
1445 int Platform::Minimum(int a, int b) {
1446 if (a < b)
1447 return a;
1448 else
1449 return b;
1450 }
1451
1452 int Platform::Maximum(int a, int b) {
1453 if (a > b)
1454 return a;
1455 else
1456 return b;
1457 }
1458
1459 //#define TRACE
1460
1461 void Platform::DebugDisplay(const char *s) {
1462 #ifdef TRACE
1463 wxLogDebug(stc2wx(s));
1464 #else
1465 wxUnusedVar(s);
1466 #endif
1467 }
1468
1469 void Platform::DebugPrintf(const char *format, ...) {
1470 #ifdef TRACE
1471 char buffer[2000];
1472 va_list pArguments;
1473 va_start(pArguments, format);
1474 vsprintf(buffer,format,pArguments);
1475 va_end(pArguments);
1476 Platform::DebugDisplay(buffer);
1477 #else
1478 wxUnusedVar(format);
1479 #endif
1480 }
1481
1482
1483 static bool assertionPopUps = true;
1484
1485 bool Platform::ShowAssertionPopUps(bool assertionPopUps_) {
1486 bool ret = assertionPopUps;
1487 assertionPopUps = assertionPopUps_;
1488 return ret;
1489 }
1490
1491 void Platform::Assert(const char *c, const char *file, int line) {
1492 #ifdef TRACE
1493 char buffer[2000];
1494 sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line);
1495 if (assertionPopUps) {
1496 /*int idButton = */
1497 wxMessageBox(stc2wx(buffer),
1498 wxT("Assertion failure"),
1499 wxICON_HAND | wxOK);
1500 } else {
1501 strcat(buffer, "\r\n");
1502 Platform::DebugDisplay(buffer);
1503 abort();
1504 }
1505 #else
1506 wxUnusedVar(c);
1507 wxUnusedVar(file);
1508 wxUnusedVar(line);
1509 #endif
1510 }
1511
1512
1513 int Platform::Clamp(int val, int minVal, int maxVal) {
1514 if (val > maxVal)
1515 val = maxVal;
1516 if (val < minVal)
1517 val = minVal;
1518 return val;
1519 }
1520
1521
1522 bool Platform::IsDBCSLeadByte(int WXUNUSED(codePage), char WXUNUSED(ch)) {
1523 return false;
1524 }
1525
1526 int Platform::DBCSCharLength(int WXUNUSED(codePage), const char *WXUNUSED(s)) {
1527 return 1;
1528 }
1529
1530 int Platform::DBCSCharMaxLength() {
1531 return 1;
1532 }
1533
1534
1535 //----------------------------------------------------------------------
1536
1537 ElapsedTime::ElapsedTime() {
1538 wxLongLong localTime = wxGetLocalTimeMillis();
1539 littleBit = localTime.GetLo();
1540 bigBit = localTime.GetHi();
1541 }
1542
1543 double ElapsedTime::Duration(bool reset) {
1544 wxLongLong prevTime(bigBit, littleBit);
1545 wxLongLong localTime = wxGetLocalTimeMillis();
1546 if(reset) {
1547 littleBit = localTime.GetLo();
1548 bigBit = localTime.GetHi();
1549 }
1550 wxLongLong duration = localTime - prevTime;
1551 double result = duration.ToDouble();
1552 result /= 1000.0;
1553 return result;
1554 }
1555
1556
1557 //----------------------------------------------------------------------
1558
1559 #if wxUSE_UNICODE
1560
1561 #include "UniConversion.h"
1562
1563 // Convert using Scintilla's functions instead of wx's, Scintilla's are more
1564 // forgiving and won't assert...
1565
1566 wxString stc2wx(const char* str, size_t len)
1567 {
1568 if (!len)
1569 return wxEmptyString;
1570
1571 size_t wclen = UTF16Length(str, len);
1572 wxWCharBuffer buffer(wclen+1);
1573
1574 size_t actualLen = UTF16FromUTF8(str, len, buffer.data(), wclen+1);
1575 return wxString(buffer.data(), actualLen);
1576 }
1577
1578
1579
1580 wxString stc2wx(const char* str)
1581 {
1582 return stc2wx(str, strlen(str));
1583 }
1584
1585
1586 const wxWX2MBbuf wx2stc(const wxString& str)
1587 {
1588 const wchar_t* wcstr = str.c_str();
1589 size_t wclen = str.length();
1590 size_t len = UTF8Length(wcstr, wclen);
1591
1592 wxCharBuffer buffer(len+1);
1593 UTF8FromUTF16(wcstr, wclen, buffer.data(), len);
1594
1595 // TODO check NULL termination!!
1596
1597 return buffer;
1598 }
1599
1600 #endif
1601
1602 #endif // wxUSE_STC