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