]> git.saurik.com Git - wxWidgets.git/blame - contrib/src/stc/PlatWX.cpp
Fix setting the scrollbar positions (SF Bug #721159)
[wxWidgets.git] / contrib / src / stc / PlatWX.cpp
CommitLineData
9ce192d4
RD
1// Scintilla source code edit control
2// PlatWX.cxx - implementation of platform facilities on wxWindows
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
f6bcfd97 7#include <ctype.h>
9ce192d4 8
1a2fb4cd 9#include <wx/wx.h>
10ef30eb 10#include <wx/encconv.h>
9e730a78
RD
11#include <wx/listctrl.h>
12#include <wx/mstream.h>
13#include <wx/image.h>
14#include <wx/imaglist.h>
1a2fb4cd 15
9ce192d4 16#include "Platform.h"
1a2fb4cd 17#include "PlatWX.h"
9ce192d4
RD
18#include "wx/stc/stc.h"
19
f97d84a6
RD
20
21#ifdef __WXGTK__
22#include <gtk/gtk.h>
23#endif
24
1a2fb4cd 25
9ce192d4 26Point Point::FromLong(long lpoint) {
f6bcfd97 27 return Point(lpoint & 0xFFFF, lpoint >> 16);
9ce192d4
RD
28}
29
30wxRect wxRectFromPRectangle(PRectangle prc) {
31 wxRect rc(prc.left, prc.top,
21156596 32 prc.right-prc.left, prc.bottom-prc.top);
9ce192d4
RD
33 return rc;
34}
35
36PRectangle PRectangleFromwxRect(wxRect rc) {
bec17edf
RD
37 return PRectangle(rc.GetLeft(), rc.GetTop(),
38 rc.GetRight()+1, rc.GetBottom()+1);
9ce192d4
RD
39}
40
1a2fb4cd
RD
41wxColour wxColourFromCA(const ColourAllocated& ca) {
42 ColourDesired cd(ca.AsLong());
43 return wxColour(cd.GetRed(), cd.GetGreen(), cd.GetBlue());
9ce192d4
RD
44}
45
1a2fb4cd 46//----------------------------------------------------------------------
9ce192d4
RD
47
48Palette::Palette() {
49 used = 0;
50 allowRealization = false;
51}
52
53Palette::~Palette() {
54 Release();
55}
56
57void Palette::Release() {
58 used = 0;
59}
60
61// This method either adds a colour to the list of wanted colours (want==true)
62// or retrieves the allocated colour back to the ColourPair.
63// This is one method to make it easier to keep the code for wanting and retrieving in sync.
64void Palette::WantFind(ColourPair &cp, bool want) {
65 if (want) {
66 for (int i=0; i < used; i++) {
67 if (entries[i].desired == cp.desired)
68 return;
69 }
70
71 if (used < numEntries) {
72 entries[used].desired = cp.desired;
1a2fb4cd 73 entries[used].allocated.Set(cp.desired.AsLong());
9ce192d4
RD
74 used++;
75 }
76 } else {
77 for (int i=0; i < used; i++) {
78 if (entries[i].desired == cp.desired) {
79 cp.allocated = entries[i].allocated;
80 return;
81 }
82 }
1a2fb4cd 83 cp.allocated.Set(cp.desired.AsLong());
9ce192d4
RD
84 }
85}
86
87void Palette::Allocate(Window &) {
88 if (allowRealization) {
89 }
90}
91
92
1a2fb4cd
RD
93//----------------------------------------------------------------------
94
9ce192d4
RD
95Font::Font() {
96 id = 0;
97 ascent = 0;
98}
99
100Font::~Font() {
101}
102
f6bcfd97 103void Font::Create(const char *faceName, int characterSet, int size, bool bold, bool italic) {
1a2fb4cd 104 wxFontEncoding encoding;
65ec6247 105
9ce192d4 106 Release();
1a2fb4cd
RD
107
108 switch (characterSet) {
109 default:
110 case wxSTC_CHARSET_ANSI:
111 case wxSTC_CHARSET_DEFAULT:
112 encoding = wxFONTENCODING_DEFAULT;
113 break;
114
115 case wxSTC_CHARSET_BALTIC:
116 encoding = wxFONTENCODING_ISO8859_13;
117 break;
118
119 case wxSTC_CHARSET_CHINESEBIG5:
120 encoding = wxFONTENCODING_CP950;
121 break;
122
123 case wxSTC_CHARSET_EASTEUROPE:
124 encoding = wxFONTENCODING_ISO8859_2;
125 break;
126
127 case wxSTC_CHARSET_GB2312:
128 encoding = wxFONTENCODING_CP936;
129 break;
130
131 case wxSTC_CHARSET_GREEK:
132 encoding = wxFONTENCODING_ISO8859_7;
133 break;
134
135 case wxSTC_CHARSET_HANGUL:
136 encoding = wxFONTENCODING_CP949;
137 break;
138
139 case wxSTC_CHARSET_MAC:
140 encoding = wxFONTENCODING_DEFAULT;
141 break;
142
143 case wxSTC_CHARSET_OEM:
144 encoding = wxFONTENCODING_DEFAULT;
145 break;
146
147 case wxSTC_CHARSET_RUSSIAN:
148 encoding = wxFONTENCODING_KOI8;
149 break;
150
151 case wxSTC_CHARSET_SHIFTJIS:
152 encoding = wxFONTENCODING_CP932;
153 break;
154
155 case wxSTC_CHARSET_SYMBOL:
156 encoding = wxFONTENCODING_DEFAULT;
157 break;
158
159 case wxSTC_CHARSET_TURKISH:
160 encoding = wxFONTENCODING_ISO8859_9;
161 break;
162
163 case wxSTC_CHARSET_JOHAB:
164 encoding = wxFONTENCODING_DEFAULT;
165 break;
166
167 case wxSTC_CHARSET_HEBREW:
168 encoding = wxFONTENCODING_ISO8859_8;
169 break;
170
171 case wxSTC_CHARSET_ARABIC:
172 encoding = wxFONTENCODING_ISO8859_6;
173 break;
174
175 case wxSTC_CHARSET_VIETNAMESE:
176 encoding = wxFONTENCODING_DEFAULT;
177 break;
178
179 case wxSTC_CHARSET_THAI:
180 encoding = wxFONTENCODING_ISO8859_11;
181 break;
182 }
183
10ef30eb
RD
184 wxFontEncodingArray ea = wxEncodingConverter::GetPlatformEquivalents(encoding);
185 if (ea.GetCount())
186 encoding = ea[0];
1a2fb4cd 187
9ce192d4
RD
188 id = new wxFont(size,
189 wxDEFAULT,
190 italic ? wxITALIC : wxNORMAL,
191 bold ? wxBOLD : wxNORMAL,
192 false,
0c5b83b0 193 stc2wx(faceName),
1a2fb4cd 194 encoding);
9ce192d4
RD
195}
196
197
198void Font::Release() {
199 if (id)
1a2fb4cd 200 delete (wxFont*)id;
9ce192d4
RD
201 id = 0;
202}
203
1a2fb4cd
RD
204//----------------------------------------------------------------------
205
206class SurfaceImpl : public Surface {
207private:
208 wxDC* hdc;
209 bool hdcOwned;
210 wxBitmap* bitmap;
211 int x;
212 int y;
213 bool unicodeMode;
9ce192d4 214
1a2fb4cd
RD
215public:
216 SurfaceImpl();
217 ~SurfaceImpl();
218
9e730a78
RD
219 virtual void Init(WindowID wid);
220 virtual void Init(SurfaceID sid, WindowID wid);
221 virtual void InitPixMap(int width, int height, Surface *surface_, WindowID wid);
222
223 virtual void Release();
224 virtual bool Initialised();
225 virtual void PenColour(ColourAllocated fore);
226 virtual int LogPixelsY();
227 virtual int DeviceHeightFont(int points);
228 virtual void MoveTo(int x_, int y_);
229 virtual void LineTo(int x_, int y_);
230 virtual void Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back);
231 virtual void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back);
232 virtual void FillRectangle(PRectangle rc, ColourAllocated back);
233 virtual void FillRectangle(PRectangle rc, Surface &surfacePattern);
234 virtual void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back);
235 virtual void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back);
236 virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource);
237
238 virtual void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
239 virtual void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
240 virtual void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);
241 virtual void MeasureWidths(Font &font_, const char *s, int len, int *positions);
242 virtual int WidthText(Font &font_, const char *s, int len);
243 virtual int WidthChar(Font &font_, char ch);
244 virtual int Ascent(Font &font_);
245 virtual int Descent(Font &font_);
246 virtual int InternalLeading(Font &font_);
247 virtual int ExternalLeading(Font &font_);
248 virtual int Height(Font &font_);
249 virtual int AverageCharWidth(Font &font_);
250
251 virtual int SetPalette(Palette *pal, bool inBackGround);
252 virtual void SetClip(PRectangle rc);
253 virtual void FlushCachedState();
254
255 virtual void SetUnicodeMode(bool unicodeMode_);
256 virtual void SetDBCSMode(int codePage);
1a2fb4cd
RD
257
258 void BrushColour(ColourAllocated back);
259 void SetFont(Font &font_);
260};
261
262
263
264SurfaceImpl::SurfaceImpl() :
9ce192d4 265 hdc(0), hdcOwned(0), bitmap(0),
1a2fb4cd
RD
266 x(0), y(0), unicodeMode(0)
267{}
9ce192d4 268
1a2fb4cd 269SurfaceImpl::~SurfaceImpl() {
9ce192d4
RD
270 Release();
271}
272
9e730a78 273void SurfaceImpl::Init(WindowID wid) {
81b32ce5 274#if 0
9ce192d4
RD
275 Release();
276 hdc = new wxMemoryDC();
277 hdcOwned = true;
81b32ce5 278#else
09bb2551 279 // On Mac and GTK the DC is not really valid until it has a bitmap
81b32ce5
RD
280 // selected into it. So instead of just creating the DC with no bitmap,
281 // go ahead and give it one.
9e730a78 282 InitPixMap(1,1,NULL,wid);
0f713d48 283#endif
9ce192d4
RD
284}
285
9e730a78 286void SurfaceImpl::Init(SurfaceID hdc_, WindowID) {
9ce192d4 287 Release();
1a2fb4cd 288 hdc = (wxDC*)hdc_;
9ce192d4
RD
289}
290
9e730a78 291void SurfaceImpl::InitPixMap(int width, int height, Surface *surface_, WindowID) {
9ce192d4 292 Release();
1a2fb4cd 293 hdc = new wxMemoryDC();
9ce192d4 294 hdcOwned = true;
2beb01db
RD
295 if (width < 1) width = 1;
296 if (height < 1) height = 1;
21156596 297 bitmap = new wxBitmap(width, height);
9ce192d4 298 ((wxMemoryDC*)hdc)->SelectObject(*bitmap);
9ce192d4
RD
299}
300
9e730a78
RD
301
302void SurfaceImpl::Release() {
303 if (bitmap) {
304 ((wxMemoryDC*)hdc)->SelectObject(wxNullBitmap);
305 delete bitmap;
306 bitmap = 0;
307 }
308 if (hdcOwned) {
309 delete hdc;
310 hdc = 0;
311 hdcOwned = false;
312 }
313}
314
315
316bool SurfaceImpl::Initialised() {
317 return hdc != 0;
318}
319
320
1a2fb4cd
RD
321void SurfaceImpl::PenColour(ColourAllocated fore) {
322 hdc->SetPen(wxPen(wxColourFromCA(fore), 1, wxSOLID));
9ce192d4
RD
323}
324
1a2fb4cd
RD
325void SurfaceImpl::BrushColour(ColourAllocated back) {
326 hdc->SetBrush(wxBrush(wxColourFromCA(back), wxSOLID));
9ce192d4
RD
327}
328
1a2fb4cd 329void SurfaceImpl::SetFont(Font &font_) {
21156596 330 if (font_.GetID()) {
1a2fb4cd 331 hdc->SetFont(*((wxFont*)font_.GetID()));
f6bcfd97 332 }
9ce192d4
RD
333}
334
1a2fb4cd 335int SurfaceImpl::LogPixelsY() {
9ce192d4
RD
336 return hdc->GetPPI().y;
337}
338
1a2fb4cd 339int SurfaceImpl::DeviceHeightFont(int points) {
9968ba85 340 return points;
f6bcfd97
BP
341}
342
1a2fb4cd 343void SurfaceImpl::MoveTo(int x_, int y_) {
9ce192d4
RD
344 x = x_;
345 y = y_;
346}
347
1a2fb4cd 348void SurfaceImpl::LineTo(int x_, int y_) {
9ce192d4
RD
349 hdc->DrawLine(x,y, x_,y_);
350 x = x_;
351 y = y_;
352}
353
1a2fb4cd 354void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) {
9ce192d4 355 PenColour(fore);
1a2fb4cd 356 BrushColour(back);
9ce192d4
RD
357 hdc->DrawPolygon(npts, (wxPoint*)pts);
358}
359
1a2fb4cd 360void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
9ce192d4 361 PenColour(fore);
1a2fb4cd 362 BrushColour(back);
9ce192d4
RD
363 hdc->DrawRectangle(wxRectFromPRectangle(rc));
364}
365
1a2fb4cd
RD
366void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) {
367 BrushColour(back);
9ce192d4
RD
368 hdc->SetPen(*wxTRANSPARENT_PEN);
369 hdc->DrawRectangle(wxRectFromPRectangle(rc));
370}
371
1a2fb4cd 372void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
9ce192d4 373 wxBrush br;
1a2fb4cd
RD
374 if (((SurfaceImpl&)surfacePattern).bitmap)
375 br = wxBrush(*((SurfaceImpl&)surfacePattern).bitmap);
9ce192d4
RD
376 else // Something is wrong so display in red
377 br = wxBrush(*wxRED, wxSOLID);
378 hdc->SetPen(*wxTRANSPARENT_PEN);
379 hdc->SetBrush(br);
380 hdc->DrawRectangle(wxRectFromPRectangle(rc));
381}
382
1a2fb4cd 383void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
9ce192d4 384 PenColour(fore);
1a2fb4cd 385 BrushColour(back);
f6bcfd97 386 hdc->DrawRoundedRectangle(wxRectFromPRectangle(rc), 4);
9ce192d4
RD
387}
388
1a2fb4cd 389void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
9ce192d4 390 PenColour(fore);
1a2fb4cd 391 BrushColour(back);
9ce192d4
RD
392 hdc->DrawEllipse(wxRectFromPRectangle(rc));
393}
394
1a2fb4cd 395void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
f6bcfd97
BP
396 wxRect r = wxRectFromPRectangle(rc);
397 hdc->Blit(r.x, r.y, r.width, r.height,
1a2fb4cd
RD
398 ((SurfaceImpl&)surfaceSource).hdc,
399 from.x, from.y, wxCOPY);
9ce192d4
RD
400}
401
1a2fb4cd
RD
402void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font, int ybase,
403 const char *s, int len,
404 ColourAllocated fore, ColourAllocated back) {
9ce192d4 405 SetFont(font);
1a2fb4cd
RD
406 hdc->SetTextForeground(wxColourFromCA(fore));
407 hdc->SetTextBackground(wxColourFromCA(back));
9e730a78 408 //FillRectangle(rc, back);
9ce192d4
RD
409
410 // ybase is where the baseline should be, but wxWin uses the upper left
411 // corner, so I need to calculate the real position for the text...
0c5b83b0 412 hdc->DrawText(stc2wx(s, len), rc.left, ybase - font.ascent);
9ce192d4
RD
413}
414
1a2fb4cd
RD
415void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font, int ybase,
416 const char *s, int len,
417 ColourAllocated fore, ColourAllocated back) {
9ce192d4 418 SetFont(font);
1a2fb4cd
RD
419 hdc->SetTextForeground(wxColourFromCA(fore));
420 hdc->SetTextBackground(wxColourFromCA(back));
9e730a78 421 //FillRectangle(rc, back);
9ce192d4
RD
422 hdc->SetClippingRegion(wxRectFromPRectangle(rc));
423
424 // see comments above
0c5b83b0 425 hdc->DrawText(stc2wx(s, len), rc.left, ybase - font.ascent);
9ce192d4
RD
426}
427
9e730a78
RD
428
429void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font, int ybase,
430 const char *s, int len,
431 ColourAllocated fore) {
432
9ce192d4 433 SetFont(font);
9e730a78
RD
434 hdc->SetTextForeground(wxColourFromCA(fore));
435 hdc->SetBackgroundMode(wxTRANSPARENT);
1a2fb4cd 436
9e730a78
RD
437 // ybase is where the baseline should be, but wxWin uses the upper left
438 // corner, so I need to calculate the real position for the text...
439 hdc->DrawText(stc2wx(s, len), rc.left, ybase - font.ascent);
440
441 hdc->SetBackgroundMode(wxSOLID);
9ce192d4
RD
442}
443
1a2fb4cd 444
10ef30eb 445void SurfaceImpl::MeasureWidths(Font &font, const char *s, int len, int *positions) {
9e730a78 446
0c5b83b0 447 wxString str = stc2wx(s, len);
9ce192d4 448 SetFont(font);
10ef30eb 449
9e730a78 450#ifndef __WXMAC__
10ef30eb
RD
451 // Calculate the position of each character based on the widths of
452 // the previous characters
453 int* tpos = new int[len];
9ce192d4 454 int totalWidth = 0;
10ef30eb
RD
455 size_t i;
456 for (i=0; i<str.Length(); i++) {
457 int w, h;
1a2fb4cd 458 hdc->GetTextExtent(str[i], &w, &h);
9ce192d4 459 totalWidth += w;
10ef30eb 460 tpos[i] = totalWidth;
9ce192d4 461 }
9e730a78
RD
462#else
463 // Instead of a running total, remeasure from the begining of the
464 // text for each character's position. This is because with AA fonts
465 // on OS X widths can be fractions of pixels wide when more than one
466 // are drawn together, so the sum of all character widths is not necessarily
467 // (and probably not) the same as the whole string width.
468 int* tpos = new int[len];
469 size_t i;
470 for (i=0; i<str.Length(); i++) {
471 int w, h;
472 hdc->GetTextExtent(str.Left(i+1), &w, &h);
473 tpos[i] = w;
474 }
475#endif
476
10ef30eb
RD
477
478#if wxUSE_UNICODE
479 // Map the widths for UCS-2 characters back to the UTF-8 input string
9e730a78
RD
480 // NOTE: I don't think this is right for when sizeof(wxChar) > 2, ie wxGTK2
481 // so figure it out and fix it!
10ef30eb
RD
482 i = 0;
483 size_t ui = 0;
484 while (i < len) {
485 unsigned char uch = (unsigned char)s[i];
486 positions[i++] = tpos[ui];
487 if (uch >= 0x80) {
488 if (uch < (0x80 + 0x40 + 0x20)) {
489 positions[i++] = tpos[ui];
490 } else {
491 positions[i++] = tpos[ui];
492 positions[i++] = tpos[ui];
493 }
494 }
495 ui++;
496 }
497#else
498
499 // If not unicode then just use the widths we have
500 memcpy(positions, tpos, len * sizeof(*tpos));
501#endif
502
503 delete [] tpos;
9ce192d4
RD
504}
505
10ef30eb 506
9e730a78
RD
507int SurfaceImpl::WidthText(Font &font, const char *s, int len) {
508 SetFont(font);
509 int w;
510 int h;
511
512 hdc->GetTextExtent(stc2wx(s, len), &w, &h);
513 return w;
514}
515
516
1a2fb4cd 517int SurfaceImpl::WidthChar(Font &font, char ch) {
9ce192d4
RD
518 SetFont(font);
519 int w;
520 int h;
10ef30eb
RD
521 char s[2] = { ch, 0 };
522
0c5b83b0 523 hdc->GetTextExtent(stc2wx(s, 1), &w, &h);
9ce192d4
RD
524 return w;
525}
526
1a2fb4cd 527#define EXTENT_TEST wxT(" `~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
9ce192d4 528
1a2fb4cd 529int SurfaceImpl::Ascent(Font &font) {
9ce192d4
RD
530 SetFont(font);
531 int w, h, d, e;
532 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
533 font.ascent = h - d;
534 return font.ascent;
535}
536
1a2fb4cd 537int SurfaceImpl::Descent(Font &font) {
9ce192d4
RD
538 SetFont(font);
539 int w, h, d, e;
540 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
541 return d;
542}
543
1a2fb4cd 544int SurfaceImpl::InternalLeading(Font &font) {
9ce192d4
RD
545 return 0;
546}
547
1a2fb4cd 548int SurfaceImpl::ExternalLeading(Font &font) {
9ce192d4
RD
549 SetFont(font);
550 int w, h, d, e;
551 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
552 return e;
553}
554
1a2fb4cd 555int SurfaceImpl::Height(Font &font) {
9ce192d4
RD
556 SetFont(font);
557 return hdc->GetCharHeight();
558}
559
1a2fb4cd 560int SurfaceImpl::AverageCharWidth(Font &font) {
9ce192d4
RD
561 SetFont(font);
562 return hdc->GetCharWidth();
563}
564
1a2fb4cd 565int SurfaceImpl::SetPalette(Palette *pal, bool inBackGround) {
65ec6247 566 return 0;
9ce192d4
RD
567}
568
1a2fb4cd 569void SurfaceImpl::SetClip(PRectangle rc) {
9ce192d4
RD
570 hdc->SetClippingRegion(wxRectFromPRectangle(rc));
571}
572
1a2fb4cd 573void SurfaceImpl::FlushCachedState() {
f6bcfd97 574}
9ce192d4 575
1a2fb4cd 576void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {
1a2fb4cd 577 unicodeMode=unicodeMode_;
10ef30eb
RD
578#if wxUSE_UNICODE
579 wxASSERT_MSG(unicodeMode == wxUSE_UNICODE,
580 wxT("Only unicode may be used when wxUSE_UNICODE is on."));
581#else
582 wxASSERT_MSG(unicodeMode == wxUSE_UNICODE,
583 wxT("Only non-unicode may be used when wxUSE_UNICODE is off."));
584#endif
1a2fb4cd
RD
585}
586
9e730a78
RD
587void SurfaceImpl::SetDBCSMode(int codePage) {
588 // dbcsMode = codePage == SC_CP_DBCS;
589}
590
591
1a2fb4cd
RD
592Surface *Surface::Allocate() {
593 return new SurfaceImpl;
594}
595
596
597//----------------------------------------------------------------------
598
599
600inline wxWindow* GETWIN(WindowID id) { return (wxWindow*)id; }
601
9ce192d4
RD
602Window::~Window() {
603}
604
605void Window::Destroy() {
9e730a78
RD
606 if (id) {
607 Show(FALSE);
1a2fb4cd 608 GETWIN(id)->Destroy();
9e730a78 609 }
9ce192d4
RD
610 id = 0;
611}
612
613bool Window::HasFocus() {
1a2fb4cd 614 return wxWindow::FindFocus() == GETWIN(id);
9ce192d4
RD
615}
616
617PRectangle Window::GetPosition() {
9e730a78 618 if (! id) return PRectangle();
1a2fb4cd 619 wxRect rc(GETWIN(id)->GetPosition(), GETWIN(id)->GetSize());
9ce192d4
RD
620 return PRectangleFromwxRect(rc);
621}
622
623void Window::SetPosition(PRectangle rc) {
f6bcfd97 624 wxRect r = wxRectFromPRectangle(rc);
1a2fb4cd 625 GETWIN(id)->SetSize(r);
9ce192d4
RD
626}
627
628void Window::SetPositionRelative(PRectangle rc, Window) {
629 SetPosition(rc); // ????
630}
631
632PRectangle Window::GetClientPosition() {
9e730a78 633 if (! id) return PRectangle();
1a2fb4cd 634 wxSize sz = GETWIN(id)->GetClientSize();
21156596 635 return PRectangle(0, 0, sz.x, sz.y);
9ce192d4
RD
636}
637
638void Window::Show(bool show) {
1a2fb4cd 639 GETWIN(id)->Show(show);
9ce192d4
RD
640}
641
642void Window::InvalidateAll() {
1a2fb4cd 643 GETWIN(id)->Refresh(false);
26f4607d 644 wxWakeUpIdle();
9ce192d4
RD
645}
646
647void Window::InvalidateRectangle(PRectangle rc) {
f6bcfd97 648 wxRect r = wxRectFromPRectangle(rc);
1a2fb4cd 649 GETWIN(id)->Refresh(false, &r);
26f4607d 650 wxWakeUpIdle();
9ce192d4
RD
651}
652
653void Window::SetFont(Font &font) {
1a2fb4cd 654 GETWIN(id)->SetFont(*((wxFont*)font.GetID()));
9ce192d4
RD
655}
656
657void Window::SetCursor(Cursor curs) {
658 int cursorId;
659
660 switch (curs) {
661 case cursorText:
662 cursorId = wxCURSOR_IBEAM;
663 break;
664 case cursorArrow:
665 cursorId = wxCURSOR_ARROW;
666 break;
667 case cursorUp:
668 cursorId = wxCURSOR_ARROW; // ** no up arrow... wxCURSOR_UPARROW;
669 break;
670 case cursorWait:
671 cursorId = wxCURSOR_WAIT;
672 break;
673 case cursorHoriz:
674 cursorId = wxCURSOR_SIZEWE;
675 break;
676 case cursorVert:
677 cursorId = wxCURSOR_SIZENS;
678 break;
679 case cursorReverseArrow:
15dadf31 680 cursorId = wxCURSOR_RIGHT_ARROW;
9ce192d4 681 break;
9e730a78
RD
682 case cursorHand:
683 cursorId = wxCURSOR_HAND;
9ce192d4
RD
684 default:
685 cursorId = wxCURSOR_ARROW;
686 break;
687 }
9f79d14b
CE
688#ifdef __WXMOTIF__
689 wxCursor wc = wxStockCursor(cursorId) ;
690#else
691 wxCursor wc = wxCursor(cursorId) ;
692#endif
cb1871ca 693 GETWIN(id)->SetCursor(wc);
9ce192d4
RD
694}
695
696
697void Window::SetTitle(const char *s) {
0c5b83b0 698 GETWIN(id)->SetTitle(stc2wx(s));
9ce192d4
RD
699}
700
701
769a9cb2
RD
702//----------------------------------------------------------------------
703// Helper classes for ListBox
704
267484bc 705
9e730a78
RD
706// This is a simple subclass of wxLIstView that just resets focus to the
707// parent when it gets it.
708class wxSTCListBox : public wxListView {
451c5cc7 709public:
9e730a78
RD
710 wxSTCListBox(wxWindow* parent, wxWindowID id,
711 const wxPoint& pos, const wxSize& size,
712 long style)
713 : wxListView(parent, id, pos, size, style)
714 {}
451c5cc7
RD
715
716 void OnFocus(wxFocusEvent& event) {
717 GetParent()->SetFocus();
718 event.Skip();
719 }
720
451c5cc7
RD
721private:
722 DECLARE_EVENT_TABLE()
723};
724
9e730a78
RD
725BEGIN_EVENT_TABLE(wxSTCListBox, wxListView)
726 EVT_SET_FOCUS( wxSTCListBox::OnFocus)
451c5cc7
RD
727END_EVENT_TABLE()
728
729
730
267484bc 731
9e730a78
RD
732// A window to place the wxSTCListBox upon
733class wxSTCListBoxWin : public wxWindow {
734private:
735 wxListView* lv;
736 CallBackAction doubleClickAction;
737 void* doubleClickActionData;
f97d84a6 738public:
9e730a78
RD
739 wxSTCListBoxWin(wxWindow* parent, wxWindowID id) :
740 wxWindow(parent, id, wxDefaultPosition, wxSize(0,0), wxNO_BORDER )
741 {
742
743 SetBackgroundColour(*wxBLACK);
744 lv = new wxSTCListBox(this, id, wxDefaultPosition, wxDefaultSize,
745 wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_NO_HEADER | wxNO_BORDER);
746 lv->SetCursor(wxCursor(wxCURSOR_ARROW));
747 lv->InsertColumn(0, wxEmptyString);
748 lv->InsertColumn(1, wxEmptyString);
749 Hide();
f97d84a6
RD
750 }
751
9e730a78
RD
752 int IconWidth() {
753 wxImageList* il = lv->GetImageList(wxIMAGE_LIST_SMALL);
754 if (il != NULL) {
755 int w, h;
756 il->GetSize(0, w, h);
757 return w;
758 }
759 return 0;
760 }
f97d84a6 761
769a9cb2 762
9e730a78
RD
763 void SetDoubleClickAction(CallBackAction action, void *data) {
764 doubleClickAction = action;
765 doubleClickActionData = data;
766 }
451c5cc7 767
769a9cb2 768
9e730a78
RD
769 void OnFocus(wxFocusEvent& event) {
770 GetParent()->SetFocus();
771 event.Skip();
772 }
769a9cb2
RD
773
774 void OnSize(wxSizeEvent& event) {
9e730a78
RD
775 // resize the child, leaving a 1 pixel border
776 wxSize sz = GetClientSize();
777 lv->SetSize(1, 1, sz.x-2, sz.y-2);
778 // reset the column widths
779 lv->SetColumnWidth(0, IconWidth()+4);
780 lv->SetColumnWidth(1, sz.x - 2 - lv->GetColumnWidth(0) -
781 wxSystemSettings::GetMetric(wxSYS_VSCROLL_X));
782 event.Skip();
769a9cb2 783 }
769a9cb2 784
9e730a78
RD
785 void OnActivate(wxListEvent& event) {
786 doubleClickAction(doubleClickActionData);
769a9cb2 787 }
9e730a78
RD
788
789 wxListView* GetLB() { return lv; }
769a9cb2
RD
790
791private:
769a9cb2
RD
792 DECLARE_EVENT_TABLE()
793};
794
9e730a78
RD
795
796BEGIN_EVENT_TABLE(wxSTCListBoxWin, wxWindow)
797 EVT_SET_FOCUS ( wxSTCListBoxWin::OnFocus)
798 EVT_SIZE ( wxSTCListBoxWin::OnSize)
799 EVT_LIST_ITEM_ACTIVATED(-1, wxSTCListBoxWin::OnActivate)
769a9cb2 800END_EVENT_TABLE()
769a9cb2 801
9e730a78
RD
802
803
804inline wxSTCListBoxWin* GETLBW(WindowID win) {
805 return ((wxSTCListBoxWin*)win);
806}
807
808inline wxListView* GETLB(WindowID win) {
809 return GETLBW(win)->GetLB();
1a2fb4cd 810}
769a9cb2
RD
811
812//----------------------------------------------------------------------
813
9e730a78
RD
814class ListBoxImpl : public ListBox {
815private:
816 int lineHeight;
817 bool unicodeMode;
818 int desiredVisibleRows;
819 int aveCharWidth;
820 int maxStrWidth;
821 wxImageList* imgList;
822 wxArrayInt* imgTypeMap;
823
824public:
825 ListBoxImpl();
826 ~ListBoxImpl();
827
828 virtual void SetFont(Font &font);
829 virtual void Create(Window &parent, int ctrlID, int lineHeight_, bool unicodeMode_);
830 virtual void SetAverageCharWidth(int width);
831 virtual void SetVisibleRows(int rows);
832 virtual PRectangle GetDesiredRect();
833 virtual int CaretFromEdge();
834 virtual void Clear();
835 virtual void Append(char *s, int type = -1);
836 virtual int Length();
837 virtual void Select(int n);
838 virtual int GetSelection();
839 virtual int Find(const char *prefix);
840 virtual void GetValue(int n, char *value, int len);
841 virtual void Sort();
842 virtual void RegisterImage(int type, const char *xpm_data);
843 virtual void ClearRegisteredImages();
844 virtual void SetDoubleClickAction(CallBackAction, void *);
845
846};
847
848
849ListBoxImpl::ListBoxImpl()
850 : lineHeight(10), unicodeMode(false),
851 desiredVisibleRows(5), aveCharWidth(8), maxStrWidth(0),
852 imgList(NULL), imgTypeMap(NULL)
853{
9ce192d4
RD
854}
855
9e730a78
RD
856ListBoxImpl::~ListBoxImpl() {
857 if (imgList) {
858 delete imgList;
859 imgList = NULL;
860 }
861 if (imgTypeMap) {
862 delete imgTypeMap;
863 imgTypeMap = NULL;
864 }
9ce192d4
RD
865}
866
9e730a78
RD
867
868void ListBoxImpl::SetFont(Font &font) {
869 GETLB(id)->SetFont(*((wxFont*)font.GetID()));
870}
871
872
873void ListBoxImpl::Create(Window &parent, int ctrlID, int lineHeight_, bool unicodeMode_) {
874 lineHeight = lineHeight_;
875 unicodeMode = unicodeMode_;
876 maxStrWidth = 0;
1a2fb4cd 877 id = new wxSTCListBoxWin(GETWIN(parent.GetID()), ctrlID);
9e730a78
RD
878 if (imgList != NULL)
879 GETLB(id)->SetImageList(imgList, wxIMAGE_LIST_SMALL);
9ce192d4
RD
880}
881
9e730a78
RD
882
883void ListBoxImpl::SetAverageCharWidth(int width) {
884 aveCharWidth = width;
885}
886
887
888void ListBoxImpl::SetVisibleRows(int rows) {
769a9cb2 889 desiredVisibleRows = rows;
f3c2c221
RD
890}
891
9e730a78
RD
892
893PRectangle ListBoxImpl::GetDesiredRect() {
894 // wxListCtrl doesn't have a DoGetBestSize, so instead we kept track of
895 // the max size in Append and calculate it here...
896 int maxw = maxStrWidth;
897 int maxh = 0;
898
899 // give it a default if there are no lines, and/or add a bit more
900 if (maxw == 0) maxw = 100;
901 maxw += aveCharWidth * 3 +
902 GETLBW(id)->IconWidth() + wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
903 if (maxw > 350)
904 maxw = 350;
905
906 // estimate a desired height
907 int count = GETLB(id)->GetItemCount();
908 if (count) {
909 wxRect rect;
910 GETLB(id)->GetItemRect(0, rect);
911 maxh = count * rect.GetHeight();
912 if (maxh > 140) // TODO: Use desiredVisibleRows??
913 maxh = 140;
914
915 // Try to make the size an exact multiple of some number of lines
916 int lines = maxh / rect.GetHeight();
917 maxh = (lines + 1) * rect.GetHeight() + 2;
918 }
919 else
920 maxh = 100;
921
d134f170
RD
922 PRectangle rc;
923 rc.top = 0;
924 rc.left = 0;
9e730a78
RD
925 rc.right = maxw;
926 rc.bottom = maxh;
d134f170
RD
927 return rc;
928}
929
d134f170 930
9e730a78
RD
931int ListBoxImpl::CaretFromEdge() {
932 return 4 + GETLBW(id)->IconWidth();
d134f170
RD
933}
934
9e730a78
RD
935
936void ListBoxImpl::Clear() {
937 GETLB(id)->DeleteAllItems();
9ce192d4
RD
938}
939
9e730a78
RD
940
941void ListBoxImpl::Append(char *s, int type) {
942 wxString text = stc2wx(s);
943 long count = GETLB(id)->GetItemCount();
944 long itemID = GETLB(id)->InsertItem(count, wxEmptyString);
945 GETLB(id)->SetItem(itemID, 1, text);
946 int itemWidth = 0;
947 GETLB(id)->GetTextExtent(text, &itemWidth, NULL);
948 maxStrWidth = wxMax(maxStrWidth, itemWidth);
949 if (type != -1) {
950 wxCHECK_RET(imgTypeMap, wxT("Unexpected NULL imgTypeMap"));
951 long idx = imgTypeMap->Item(type);
952 GETLB(id)->SetItemImage(itemID, idx, idx);
953 }
9ce192d4
RD
954}
955
9e730a78
RD
956
957int ListBoxImpl::Length() {
958 return GETLB(id)->GetItemCount();
9ce192d4
RD
959}
960
9e730a78
RD
961
962void ListBoxImpl::Select(int n) {
895066d8
RD
963 bool select = TRUE;
964 if (n == -1) {
965 n = 0;
966 select = FALSE;
967 }
9e730a78
RD
968 GETLB(id)->Focus(n);
969 GETLB(id)->Select(n, select);
9ce192d4
RD
970}
971
9e730a78
RD
972
973int ListBoxImpl::GetSelection() {
974 return GETLB(id)->GetFirstSelected();
9ce192d4
RD
975}
976
9e730a78
RD
977
978int ListBoxImpl::Find(const char *prefix) {
b8b0e402 979 // No longer used
f6bcfd97 980 return -1;
9ce192d4
RD
981}
982
9e730a78
RD
983
984void ListBoxImpl::GetValue(int n, char *value, int len) {
985 wxListItem item;
986 item.SetId(n);
987 item.SetColumn(1);
988 item.SetMask(wxLIST_MASK_TEXT);
989 GETLB(id)->GetItem(item);
990 strncpy(value, wx2stc(item.GetText()), len);
9ce192d4
RD
991 value[len-1] = '\0';
992}
993
9e730a78
RD
994void ListBoxImpl::Sort() {
995}
996
997
998void ListBoxImpl::RegisterImage(int type, const char *xpm_data) {
999 wxMemoryInputStream stream(xpm_data, strlen(xpm_data)+1);
1000 wxBitmap bmp(wxImage(stream, wxBITMAP_TYPE_XPM));
1001
1002 if (! imgList) {
1003 // assumes all images are the same size
1004 imgList = new wxImageList(bmp.GetWidth(), bmp.GetHeight(), TRUE);
1005 imgTypeMap = new wxArrayInt;
1006 }
1007
1008 int idx = imgList->Add(bmp);
1009
1010 // do we need to extend the mapping array?
1011 wxArrayInt& itm = *imgTypeMap;
1012 if ( itm.GetCount() < type+1)
1013 itm.Add(-1, type - itm.GetCount() + 1);
1014
1015 // Add an item that maps type to the image index
1016 itm[type] = idx;
1017}
1018
1019void ListBoxImpl::ClearRegisteredImages() {
1020 if (imgList) {
1021 delete imgList;
1022 imgList = NULL;
1023 }
1024 if (imgTypeMap) {
1025 delete imgTypeMap;
1026 imgTypeMap = NULL;
1027 }
1028 if (id)
1029 GETLB(id)->SetImageList(NULL, wxIMAGE_LIST_SMALL);
1030}
1031
1032
1033void ListBoxImpl::SetDoubleClickAction(CallBackAction action, void *data) {
1034 GETLBW(id)->SetDoubleClickAction(action, data);
1035}
1036
1037
1038
1039ListBox::ListBox() {
1040}
1041
1042ListBox::~ListBox() {
1043}
1044
1045ListBox *ListBox::Allocate() {
1046 return new ListBoxImpl();
9ce192d4
RD
1047}
1048
1a2fb4cd 1049//----------------------------------------------------------------------
9ce192d4
RD
1050
1051Menu::Menu() : id(0) {
1052}
1053
1054void Menu::CreatePopUp() {
1055 Destroy();
1056 id = new wxMenu();
1057}
1058
1059void Menu::Destroy() {
1060 if (id)
1a2fb4cd 1061 delete (wxMenu*)id;
9ce192d4
RD
1062 id = 0;
1063}
1064
1065void Menu::Show(Point pt, Window &w) {
1a2fb4cd 1066 GETWIN(w.GetID())->PopupMenu((wxMenu*)id, pt.x - 4, pt.y);
9ce192d4
RD
1067 Destroy();
1068}
1069
1a2fb4cd 1070//----------------------------------------------------------------------
9ce192d4 1071
1a2fb4cd 1072ColourDesired Platform::Chrome() {
9ce192d4 1073 wxColour c;
e1c6c6ae 1074 c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
1a2fb4cd 1075 return ColourDesired(c.Red(), c.Green(), c.Blue());
9ce192d4
RD
1076}
1077
1a2fb4cd 1078ColourDesired Platform::ChromeHighlight() {
9ce192d4 1079 wxColour c;
e1c6c6ae 1080 c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT);
1a2fb4cd 1081 return ColourDesired(c.Red(), c.Green(), c.Blue());
9ce192d4
RD
1082}
1083
1084const char *Platform::DefaultFont() {
10ef30eb
RD
1085 static char buf[128];
1086 strcpy(buf, wxNORMAL_FONT->GetFaceName().mbc_str());
1087 return buf;
9ce192d4
RD
1088}
1089
1090int Platform::DefaultFontSize() {
9e730a78 1091 return wxNORMAL_FONT->GetPointSize();
9ce192d4
RD
1092}
1093
1094unsigned int Platform::DoubleClickTime() {
1095 return 500; // **** ::GetDoubleClickTime();
1096}
1097
9e730a78
RD
1098bool Platform::MouseButtonBounce() {
1099 return FALSE;
1100}
9ce192d4 1101void Platform::DebugDisplay(const char *s) {
0c5b83b0 1102 wxLogDebug(stc2wx(s));
9ce192d4
RD
1103}
1104
1105bool Platform::IsKeyDown(int key) {
1106 return false; // I don't think we'll need this.
1107}
1108
1109long Platform::SendScintilla(WindowID w,
1110 unsigned int msg,
1111 unsigned long wParam,
1112 long lParam) {
1113
1114 wxStyledTextCtrl* stc = (wxStyledTextCtrl*)w;
1115 return stc->SendMsg(msg, wParam, lParam);
1116}
1117
a834585d
RD
1118long Platform::SendScintillaPointer(WindowID w,
1119 unsigned int msg,
1120 unsigned long wParam,
1121 void *lParam) {
1122
1123 wxStyledTextCtrl* stc = (wxStyledTextCtrl*)w;
1124 return stc->SendMsg(msg, wParam, (long)lParam);
1125}
1126
9ce192d4
RD
1127
1128// These are utility functions not really tied to a platform
1129
1130int Platform::Minimum(int a, int b) {
1131 if (a < b)
1132 return a;
1133 else
1134 return b;
1135}
1136
1137int Platform::Maximum(int a, int b) {
1138 if (a > b)
1139 return a;
1140 else
1141 return b;
1142}
1143
1144#define TRACE
1145
1146void Platform::DebugPrintf(const char *format, ...) {
1147#ifdef TRACE
1148 char buffer[2000];
1149 va_list pArguments;
1150 va_start(pArguments, format);
1151 vsprintf(buffer,format,pArguments);
1152 va_end(pArguments);
1153 Platform::DebugDisplay(buffer);
1154#endif
1155}
1156
65ec6247
RD
1157
1158static bool assertionPopUps = true;
1159
1160bool Platform::ShowAssertionPopUps(bool assertionPopUps_) {
1161 bool ret = assertionPopUps;
1162 assertionPopUps = assertionPopUps_;
1163 return ret;
1164}
1165
1166void Platform::Assert(const char *c, const char *file, int line) {
1167 char buffer[2000];
1168 sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line);
1169 if (assertionPopUps) {
0c5b83b0
RD
1170 /*int idButton = */
1171 wxMessageBox(stc2wx(buffer),
1172 wxT("Assertion failure"),
1173 wxICON_HAND | wxOK);
65ec6247
RD
1174// if (idButton == IDRETRY) {
1175// ::DebugBreak();
1176// } else if (idButton == IDIGNORE) {
1177// // all OK
1178// } else {
1179// abort();
1180// }
1181 } else {
1182 strcat(buffer, "\r\n");
1183 Platform::DebugDisplay(buffer);
1184 abort();
1185 }
1186}
1187
1188
9ce192d4
RD
1189int Platform::Clamp(int val, int minVal, int maxVal) {
1190 if (val > maxVal)
1191 val = maxVal;
1192 if (val < minVal)
1193 val = minVal;
1194 return val;
1195}
1196
1197
1a2fb4cd
RD
1198bool Platform::IsDBCSLeadByte(int codePage, char ch) {
1199 return false;
1200}
1201
9e730a78
RD
1202int Platform::DBCSCharLength(int codePage, const char *s) {
1203 return 0;
1204}
1205
1206int Platform::DBCSCharMaxLength() {
1207 return 0;
1208}
1a2fb4cd
RD
1209
1210
1211//----------------------------------------------------------------------
1212
1213ElapsedTime::ElapsedTime() {
1214 wxStartTimer();
1215}
1216
1217double ElapsedTime::Duration(bool reset) {
1218 double result = wxGetElapsedTime(reset);
1219 result /= 1000.0;
1220 return result;
1221}
1222
1223
1224//----------------------------------------------------------------------
9ce192d4
RD
1225
1226
1227
1228