]> git.saurik.com Git - wxWidgets.git/blob - src/stc/PlatWX.cpp
Patch from Bo for recent API changes
[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 #include "wx/stc/private.h"
39
40
41
42 Point Point::FromLong(long lpoint) {
43 return Point(lpoint & 0xFFFF, lpoint >> 16);
44 }
45
46 wxRect wxRectFromPRectangle(PRectangle prc) {
47 wxRect r(prc.left, prc.top,
48 prc.Width(), prc.Height());
49 return r;
50 }
51
52 PRectangle PRectangleFromwxRect(wxRect rc) {
53 return PRectangle(rc.GetLeft(), rc.GetTop(),
54 rc.GetRight()+1, rc.GetBottom()+1);
55 }
56
57 wxColour wxColourFromCA(const ColourAllocated& ca) {
58 ColourDesired cd(ca.AsLong());
59 return wxColour((unsigned char)cd.GetRed(),
60 (unsigned char)cd.GetGreen(),
61 (unsigned char)cd.GetBlue());
62 }
63
64 //----------------------------------------------------------------------
65
66 Palette::Palette() {
67 used = 0;
68 allowRealization = false;
69 size = 100;
70 entries = new ColourPair[size];
71 }
72
73 Palette::~Palette() {
74 Release();
75 delete [] entries;
76 entries = 0;
77 }
78
79 void Palette::Release() {
80 used = 0;
81 delete [] entries;
82 size = 100;
83 entries = new ColourPair[size];
84 }
85
86 // This method either adds a colour to the list of wanted colours (want==true)
87 // or retrieves the allocated colour back to the ColourPair.
88 // This is one method to make it easier to keep the code for wanting and retrieving in sync.
89 void Palette::WantFind(ColourPair &cp, bool want) {
90 if (want) {
91 for (int i=0; i < used; i++) {
92 if (entries[i].desired == cp.desired)
93 return;
94 }
95
96 if (used >= size) {
97 int sizeNew = size * 2;
98 ColourPair *entriesNew = new ColourPair[sizeNew];
99 for (int j=0; j<size; j++) {
100 entriesNew[j] = entries[j];
101 }
102 delete []entries;
103 entries = entriesNew;
104 size = sizeNew;
105 }
106
107 entries[used].desired = cp.desired;
108 entries[used].allocated.Set(cp.desired.AsLong());
109 used++;
110 } else {
111 for (int i=0; i < used; i++) {
112 if (entries[i].desired == cp.desired) {
113 cp.allocated = entries[i].allocated;
114 return;
115 }
116 }
117 cp.allocated.Set(cp.desired.AsLong());
118 }
119 }
120
121 void Palette::Allocate(Window &) {
122 if (allowRealization) {
123 }
124 }
125
126
127 //----------------------------------------------------------------------
128
129 Font::Font() {
130 id = 0;
131 ascent = 0;
132 }
133
134 Font::~Font() {
135 }
136
137 void Font::Create(const char *faceName, int characterSet, int size, bool bold, bool italic, bool extraFontFlag) {
138
139 Release();
140
141 // The minus one is done because since Scintilla uses SC_SHARSET_DEFAULT
142 // internally and we need to have wxFONENCODING_DEFAULT == SC_SHARSET_DEFAULT
143 // so we adjust the encoding before passing it to Scintilla. See also
144 // wxStyledTextCtrl::StyleSetCharacterSet
145 wxFontEncoding encoding = (wxFontEncoding)(characterSet-1);
146
147 wxFontEncodingArray ea = wxEncodingConverter::GetPlatformEquivalents(encoding);
148 if (ea.GetCount())
149 encoding = ea[0];
150
151 wxFont* font = new wxFont(size,
152 wxDEFAULT,
153 italic ? wxITALIC : wxNORMAL,
154 bold ? wxBOLD : wxNORMAL,
155 false,
156 stc2wx(faceName),
157 encoding);
158 font->SetNoAntiAliasing(!extraFontFlag);
159 id = font;
160 }
161
162
163 void Font::Release() {
164 if (id)
165 delete (wxFont*)id;
166 id = 0;
167 }
168
169 //----------------------------------------------------------------------
170
171 class SurfaceImpl : public Surface {
172 private:
173 wxDC* hdc;
174 bool hdcOwned;
175 wxBitmap* bitmap;
176 int x;
177 int y;
178 bool unicodeMode;
179
180 public:
181 SurfaceImpl();
182 ~SurfaceImpl();
183
184 virtual void Init(WindowID wid);
185 virtual void Init(SurfaceID sid, WindowID wid);
186 virtual void InitPixMap(int width, int height, Surface *surface_, WindowID wid);
187
188 virtual void Release();
189 virtual bool Initialised();
190 virtual void PenColour(ColourAllocated fore);
191 virtual int LogPixelsY();
192 virtual int DeviceHeightFont(int points);
193 virtual void MoveTo(int x_, int y_);
194 virtual void LineTo(int x_, int y_);
195 virtual void Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back);
196 virtual void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back);
197 virtual void FillRectangle(PRectangle rc, ColourAllocated back);
198 virtual void FillRectangle(PRectangle rc, Surface &surfacePattern);
199 virtual void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back);
200 virtual void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
201 ColourAllocated outline, int alphaOutline, int flags);
202 virtual void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back);
203 virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource);
204
205 virtual void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
206 virtual void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
207 virtual void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);
208 virtual void MeasureWidths(Font &font_, const char *s, int len, int *positions);
209 virtual int WidthText(Font &font_, const char *s, int len);
210 virtual int WidthChar(Font &font_, char ch);
211 virtual int Ascent(Font &font_);
212 virtual int Descent(Font &font_);
213 virtual int InternalLeading(Font &font_);
214 virtual int ExternalLeading(Font &font_);
215 virtual int Height(Font &font_);
216 virtual int AverageCharWidth(Font &font_);
217
218 virtual int SetPalette(Palette *pal, bool inBackGround);
219 virtual void SetClip(PRectangle rc);
220 virtual void FlushCachedState();
221
222 virtual void SetUnicodeMode(bool unicodeMode_);
223 virtual void SetDBCSMode(int codePage);
224
225 void BrushColour(ColourAllocated back);
226 void SetFont(Font &font_);
227 };
228
229
230
231 SurfaceImpl::SurfaceImpl() :
232 hdc(0), hdcOwned(0), bitmap(0),
233 x(0), y(0), unicodeMode(0)
234 {}
235
236 SurfaceImpl::~SurfaceImpl() {
237 Release();
238 }
239
240 void SurfaceImpl::Init(WindowID wid) {
241 #if 0
242 Release();
243 hdc = new wxMemoryDC();
244 hdcOwned = true;
245 #else
246 // On Mac and GTK the DC is not really valid until it has a bitmap
247 // selected into it. So instead of just creating the DC with no bitmap,
248 // go ahead and give it one.
249 InitPixMap(1,1,NULL,wid);
250 #endif
251 }
252
253 void SurfaceImpl::Init(SurfaceID hdc_, WindowID) {
254 Release();
255 hdc = (wxDC*)hdc_;
256 }
257
258 void SurfaceImpl::InitPixMap(int width, int height, Surface *WXUNUSED(surface_), WindowID) {
259 Release();
260 hdc = new wxMemoryDC();
261 hdcOwned = true;
262 if (width < 1) width = 1;
263 if (height < 1) height = 1;
264 bitmap = new wxBitmap(width, height);
265 ((wxMemoryDC*)hdc)->SelectObject(*bitmap);
266 }
267
268
269 void SurfaceImpl::Release() {
270 if (bitmap) {
271 ((wxMemoryDC*)hdc)->SelectObject(wxNullBitmap);
272 delete bitmap;
273 bitmap = 0;
274 }
275 if (hdcOwned) {
276 delete hdc;
277 hdc = 0;
278 hdcOwned = false;
279 }
280 }
281
282
283 bool SurfaceImpl::Initialised() {
284 return hdc != 0;
285 }
286
287
288 void SurfaceImpl::PenColour(ColourAllocated fore) {
289 hdc->SetPen(wxPen(wxColourFromCA(fore), 1, wxSOLID));
290 }
291
292 void SurfaceImpl::BrushColour(ColourAllocated back) {
293 hdc->SetBrush(wxBrush(wxColourFromCA(back), wxSOLID));
294 }
295
296 void SurfaceImpl::SetFont(Font &font_) {
297 if (font_.GetID()) {
298 hdc->SetFont(*((wxFont*)font_.GetID()));
299 }
300 }
301
302 int SurfaceImpl::LogPixelsY() {
303 return hdc->GetPPI().y;
304 }
305
306 int SurfaceImpl::DeviceHeightFont(int points) {
307 return points;
308 }
309
310 void SurfaceImpl::MoveTo(int x_, int y_) {
311 x = x_;
312 y = y_;
313 }
314
315 void SurfaceImpl::LineTo(int x_, int y_) {
316 hdc->DrawLine(x,y, x_,y_);
317 x = x_;
318 y = y_;
319 }
320
321 void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) {
322 PenColour(fore);
323 BrushColour(back);
324 hdc->DrawPolygon(npts, (wxPoint*)pts);
325 }
326
327 void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
328 PenColour(fore);
329 BrushColour(back);
330 hdc->DrawRectangle(wxRectFromPRectangle(rc));
331 }
332
333 void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) {
334 BrushColour(back);
335 hdc->SetPen(*wxTRANSPARENT_PEN);
336 hdc->DrawRectangle(wxRectFromPRectangle(rc));
337 }
338
339 void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
340 wxBrush br;
341 if (((SurfaceImpl&)surfacePattern).bitmap)
342 br = wxBrush(*((SurfaceImpl&)surfacePattern).bitmap);
343 else // Something is wrong so display in red
344 br = wxBrush(*wxRED, wxSOLID);
345 hdc->SetPen(*wxTRANSPARENT_PEN);
346 hdc->SetBrush(br);
347 hdc->DrawRectangle(wxRectFromPRectangle(rc));
348 }
349
350 void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
351 PenColour(fore);
352 BrushColour(back);
353 hdc->DrawRoundedRectangle(wxRectFromPRectangle(rc), 4);
354 }
355
356 #ifdef __WXMSW__
357 #define wxPy_premultiply(p, a) ((p) * (a) / 0xff)
358 #else
359 #define wxPy_premultiply(p, a) (p)
360 #endif
361
362 void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize,
363 ColourAllocated fill, int alphaFill,
364 ColourAllocated outline, int alphaOutline,
365 int /*flags*/) {
366 #ifdef wxHAVE_RAW_BITMAP
367
368 // TODO: do something with cornerSize
369 wxUnusedVar(cornerSize);
370
371 int x, y;
372 wxRect r = wxRectFromPRectangle(rc);
373 wxBitmap bmp(r.width, r.height, 32);
374 wxAlphaPixelData pixData(bmp);
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