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