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