]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/stc/PlatWX.cpp
added code to free memory allocated in wxSetEnv() when it uses putenv()
[wxWidgets.git] / src / stc / PlatWX.cpp
... / ...
CommitLineData
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
42Point Point::FromLong(long lpoint) {
43 return Point(lpoint & 0xFFFF, lpoint >> 16);
44}
45
46wxRect wxRectFromPRectangle(PRectangle prc) {
47 wxRect r(prc.left, prc.top,
48 prc.Width(), prc.Height());
49 return r;
50}
51
52PRectangle PRectangleFromwxRect(wxRect rc) {
53 return PRectangle(rc.GetLeft(), rc.GetTop(),
54 rc.GetRight()+1, rc.GetBottom()+1);
55}
56
57wxColour 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
66Palette::Palette() {
67 used = 0;
68 allowRealization = false;
69 size = 100;
70 entries = new ColourPair[size];
71}
72
73Palette::~Palette() {
74 Release();
75 delete [] entries;
76 entries = 0;
77}
78
79void 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.
89void 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
121void Palette::Allocate(Window &) {
122 if (allowRealization) {
123 }
124}
125
126
127//----------------------------------------------------------------------
128
129Font::Font() {
130 id = 0;
131 ascent = 0;
132}
133
134Font::~Font() {
135}
136
137void 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
163void Font::Release() {
164 if (id)
165 delete (wxFont*)id;
166 id = 0;
167}
168
169//----------------------------------------------------------------------
170
171class SurfaceImpl : public Surface {
172private:
173 wxDC* hdc;
174 bool hdcOwned;
175 wxBitmap* bitmap;
176 int x;
177 int y;
178 bool unicodeMode;
179
180public:
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
231SurfaceImpl::SurfaceImpl() :
232 hdc(0), hdcOwned(0), bitmap(0),
233 x(0), y(0), unicodeMode(0)
234{}
235
236SurfaceImpl::~SurfaceImpl() {
237 Release();
238}
239
240void 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
253void SurfaceImpl::Init(SurfaceID hdc_, WindowID) {
254 Release();
255 hdc = (wxDC*)hdc_;
256}
257
258void 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
269void 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
283bool SurfaceImpl::Initialised() {
284 return hdc != 0;
285}
286
287
288void SurfaceImpl::PenColour(ColourAllocated fore) {
289 hdc->SetPen(wxPen(wxColourFromCA(fore), 1, wxSOLID));
290}
291
292void SurfaceImpl::BrushColour(ColourAllocated back) {
293 hdc->SetBrush(wxBrush(wxColourFromCA(back), wxSOLID));
294}
295
296void SurfaceImpl::SetFont(Font &font_) {
297 if (font_.GetID()) {
298 hdc->SetFont(*((wxFont*)font_.GetID()));
299 }
300}
301
302int SurfaceImpl::LogPixelsY() {
303 return hdc->GetPPI().y;
304}
305
306int SurfaceImpl::DeviceHeightFont(int points) {
307 return points;
308}
309
310void SurfaceImpl::MoveTo(int x_, int y_) {
311 x = x_;
312 y = y_;
313}
314
315void SurfaceImpl::LineTo(int x_, int y_) {
316 hdc->DrawLine(x,y, x_,y_);
317 x = x_;
318 y = y_;
319}
320
321void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) {
322 PenColour(fore);
323 BrushColour(back);
324 hdc->DrawPolygon(npts, (wxPoint*)pts);
325}
326
327void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
328 PenColour(fore);
329 BrushColour(back);
330 hdc->DrawRectangle(wxRectFromPRectangle(rc));
331}
332
333void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) {
334 BrushColour(back);
335 hdc->SetPen(*wxTRANSPARENT_PEN);
336 hdc->DrawRectangle(wxRectFromPRectangle(rc));
337}
338
339void 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
350void 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
362void 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
436void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
437 PenColour(fore);
438 BrushColour(back);
439 hdc->DrawEllipse(wxRectFromPRectangle(rc));
440}
441
442void 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
449void 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
462void 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
477void 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
493void 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
533int 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
543int 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
555int 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
563int 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
570int SurfaceImpl::InternalLeading(Font &WXUNUSED(font)) {
571 return 0;
572}
573
574int 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
581int SurfaceImpl::Height(Font &font) {
582 SetFont(font);
583 return hdc->GetCharHeight() + 1;
584}
585
586int SurfaceImpl::AverageCharWidth(Font &font) {
587 SetFont(font);
588 return hdc->GetCharWidth();
589}
590
591int SurfaceImpl::SetPalette(Palette *WXUNUSED(pal), bool WXUNUSED(inBackGround)) {
592 return 0;
593}
594
595void SurfaceImpl::SetClip(PRectangle rc) {
596 hdc->SetClippingRegion(wxRectFromPRectangle(rc));
597}
598
599void SurfaceImpl::FlushCachedState() {
600}
601
602void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {
603 unicodeMode=unicodeMode_;
604}
605
606void SurfaceImpl::SetDBCSMode(int WXUNUSED(codePage)) {
607 // dbcsMode = codePage == SC_CP_DBCS;
608}
609
610
611Surface *Surface::Allocate() {
612 return new SurfaceImpl;
613}
614
615
616//----------------------------------------------------------------------
617
618
619inline wxWindow* GETWIN(WindowID id) { return (wxWindow*)id; }
620
621Window::~Window() {
622}
623
624void Window::Destroy() {
625 if (id) {
626 Show(false);
627 GETWIN(id)->Destroy();
628 }
629 id = 0;
630}
631
632bool Window::HasFocus() {
633 return wxWindow::FindFocus() == GETWIN(id);
634}
635
636PRectangle Window::GetPosition() {
637 if (! id) return PRectangle();
638 wxRect rc(GETWIN(id)->GetPosition(), GETWIN(id)->GetSize());
639 return PRectangleFromwxRect(rc);
640}
641
642void Window::SetPosition(PRectangle rc) {
643 wxRect r = wxRectFromPRectangle(rc);
644 GETWIN(id)->SetSize(r);
645}
646
647void Window::SetPositionRelative(PRectangle rc, Window) {
648 SetPosition(rc); // ????
649}
650
651PRectangle Window::GetClientPosition() {
652 if (! id) return PRectangle();
653 wxSize sz = GETWIN(id)->GetClientSize();
654 return PRectangle(0, 0, sz.x, sz.y);
655}
656
657void Window::Show(bool show) {
658 GETWIN(id)->Show(show);
659}
660
661void Window::InvalidateAll() {
662 GETWIN(id)->Refresh(false);
663}
664
665void Window::InvalidateRectangle(PRectangle rc) {
666 wxRect r = wxRectFromPRectangle(rc);
667 GETWIN(id)->Refresh(false, &r);
668}
669
670void Window::SetFont(Font &font) {
671 GETWIN(id)->SetFont(*((wxFont*)font.GetID()));
672}
673
674void 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
719void 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.
730class wxSTCListBox : public wxListView {
731public:
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
770private:
771 DECLARE_EVENT_TABLE()
772};
773
774BEGIN_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
781END_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
798class wxSTCListBoxWin : public wxPopupWindow
799{
800private:
801 wxListView* lv;
802 CallBackAction doubleClickAction;
803 void* doubleClickActionData;
804public:
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
902private:
903 DECLARE_EVENT_TABLE()
904
905};
906
907BEGIN_EVENT_TABLE(wxSTCListBoxWin, wxPopupWindow)
908 EVT_SET_FOCUS ( wxSTCListBoxWin::OnFocus)
909 EVT_SIZE ( wxSTCListBoxWin::OnSize)
910 EVT_LIST_ITEM_ACTIVATED(wxID_ANY, wxSTCListBoxWin::OnActivate)
911END_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
920class wxSTCListBoxWin : public wxFrame {
921private:
922 wxListView* lv;
923 CallBackAction doubleClickAction;
924 void* doubleClickActionData;
925public:
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
1054private:
1055 DECLARE_EVENT_TABLE()
1056};
1057
1058
1059BEGIN_EVENT_TABLE(wxSTCListBoxWin, wxWindow)
1060 EVT_SET_FOCUS ( wxSTCListBoxWin::OnFocus)
1061 EVT_SIZE ( wxSTCListBoxWin::OnSize)
1062 EVT_LIST_ITEM_ACTIVATED(wxID_ANY, wxSTCListBoxWin::OnActivate)
1063END_EVENT_TABLE()
1064
1065#endif // wxUSE_POPUPWIN -----------------------------------
1066
1067
1068inline wxSTCListBoxWin* GETLBW(WindowID win) {
1069 return ((wxSTCListBoxWin*)win);
1070}
1071
1072inline wxListView* GETLB(WindowID win) {
1073 return GETLBW(win)->GetLB();
1074}
1075
1076//----------------------------------------------------------------------
1077
1078class ListBoxImpl : public ListBox {
1079private:
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
1089public:
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
1115ListBoxImpl::ListBoxImpl()
1116 : lineHeight(10), unicodeMode(false),
1117 desiredVisibleRows(5), aveCharWidth(8), maxStrWidth(0),
1118 imgList(NULL), imgTypeMap(NULL)
1119{
1120}
1121
1122ListBoxImpl::~ListBoxImpl() {
1123 if (imgList) {
1124 delete imgList;
1125 imgList = NULL;
1126 }
1127 if (imgTypeMap) {
1128 delete imgTypeMap;
1129 imgTypeMap = NULL;
1130 }
1131}
1132
1133
1134void ListBoxImpl::SetFont(Font &font) {
1135 GETLB(id)->SetFont(*((wxFont*)font.GetID()));
1136}
1137
1138
1139void 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
1150void ListBoxImpl::SetAverageCharWidth(int width) {
1151 aveCharWidth = width;
1152}
1153
1154
1155void ListBoxImpl::SetVisibleRows(int rows) {
1156 desiredVisibleRows = rows;
1157}
1158
1159
1160int ListBoxImpl::GetVisibleRows() const {
1161 return desiredVisibleRows;
1162}
1163
1164PRectangle 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
1202int ListBoxImpl::CaretFromEdge() {
1203 return 4 + GETLBW(id)->IconWidth();
1204}
1205
1206
1207void ListBoxImpl::Clear() {
1208 GETLB(id)->DeleteAllItems();
1209}
1210
1211
1212void ListBoxImpl::Append(char *s, int type) {
1213 Append(stc2wx(s), type);
1214}
1215
1216void 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
1228void 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
1246int ListBoxImpl::Length() {
1247 return GETLB(id)->GetItemCount();
1248}
1249
1250
1251void 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
1262int ListBoxImpl::GetSelection() {
1263 return GETLB(id)->GetFirstSelected();
1264}
1265
1266
1267int ListBoxImpl::Find(const char *WXUNUSED(prefix)) {
1268 // No longer used
1269 return wxNOT_FOUND;
1270}
1271
1272
1273void 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
1284void 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
1306void 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
1320void ListBoxImpl::SetDoubleClickAction(CallBackAction action, void *data) {
1321 GETLBW(id)->SetDoubleClickAction(action, data);
1322}
1323
1324
1325ListBox::ListBox() {
1326}
1327
1328ListBox::~ListBox() {
1329}
1330
1331ListBox *ListBox::Allocate() {
1332 return new ListBoxImpl();
1333}
1334
1335//----------------------------------------------------------------------
1336
1337Menu::Menu() : id(0) {
1338}
1339
1340void Menu::CreatePopUp() {
1341 Destroy();
1342 id = new wxMenu();
1343}
1344
1345void Menu::Destroy() {
1346 if (id)
1347 delete (wxMenu*)id;
1348 id = 0;
1349}
1350
1351void Menu::Show(Point pt, Window &w) {
1352 GETWIN(w.GetID())->PopupMenu((wxMenu*)id, pt.x - 4, pt.y);
1353 Destroy();
1354}
1355
1356//----------------------------------------------------------------------
1357
1358DynamicLibrary *DynamicLibrary::Load(const char *WXUNUSED(modulePath)) {
1359 wxFAIL_MSG(wxT("Dynamic lexer loading not implemented yet"));
1360 return NULL;
1361}
1362
1363//----------------------------------------------------------------------
1364
1365ColourDesired Platform::Chrome() {
1366 wxColour c;
1367 c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
1368 return ColourDesired(c.Red(), c.Green(), c.Blue());
1369}
1370
1371ColourDesired Platform::ChromeHighlight() {
1372 wxColour c;
1373 c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT);
1374 return ColourDesired(c.Red(), c.Green(), c.Blue());
1375}
1376
1377const char *Platform::DefaultFont() {
1378 static char buf[128];
1379 strcpy(buf, wxNORMAL_FONT->GetFaceName().mbc_str());
1380 return buf;
1381}
1382
1383int Platform::DefaultFontSize() {
1384 return wxNORMAL_FONT->GetPointSize();
1385}
1386
1387unsigned int Platform::DoubleClickTime() {
1388 return 500; // **** ::GetDoubleClickTime();
1389}
1390
1391bool Platform::MouseButtonBounce() {
1392 return false;
1393}
1394
1395bool Platform::IsKeyDown(int WXUNUSED(key)) {
1396 return false; // I don't think we'll need this.
1397}
1398
1399long 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
1408long 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
1420int Platform::Minimum(int a, int b) {
1421 if (a < b)
1422 return a;
1423 else
1424 return b;
1425}
1426
1427int Platform::Maximum(int a, int b) {
1428 if (a > b)
1429 return a;
1430 else
1431 return b;
1432}
1433
1434//#define TRACE
1435
1436void Platform::DebugDisplay(const char *s) {
1437#ifdef TRACE
1438 wxLogDebug(stc2wx(s));
1439#else
1440 wxUnusedVar(s);
1441#endif
1442}
1443
1444void 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
1458static bool assertionPopUps = true;
1459
1460bool Platform::ShowAssertionPopUps(bool assertionPopUps_) {
1461 bool ret = assertionPopUps;
1462 assertionPopUps = assertionPopUps_;
1463 return ret;
1464}
1465
1466void 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
1488int 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
1497bool Platform::IsDBCSLeadByte(int WXUNUSED(codePage), char WXUNUSED(ch)) {
1498 return false;
1499}
1500
1501int Platform::DBCSCharLength(int WXUNUSED(codePage), const char *WXUNUSED(s)) {
1502 return 1;
1503}
1504
1505int Platform::DBCSCharMaxLength() {
1506 return 1;
1507}
1508
1509
1510//----------------------------------------------------------------------
1511
1512ElapsedTime::ElapsedTime() {
1513 wxLongLong localTime = wxGetLocalTimeMillis();
1514 littleBit = localTime.GetLo();
1515 bigBit = localTime.GetHi();
1516}
1517
1518double 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
1541wxString 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
1555wxString stc2wx(const char* str)
1556{
1557 return stc2wx(str, strlen(str));
1558}
1559
1560
1561const 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