]> git.saurik.com Git - wxWidgets.git/blame - src/stc/PlatWX.cpp
don't overwrite the existing local file if we failed to open it but it does exist
[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
d6655166
WS
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"
1e9bafca 29#include "wx/tokenzr.h"
8b3d52fc
RD
30
31#ifdef wxHAVE_RAW_BITMAP
6a93571d 32#include "wx/rawbmp.h"
8b3d52fc 33#endif
1a2fb4cd 34
9ce192d4 35#include "Platform.h"
1a2fb4cd 36#include "PlatWX.h"
9ce192d4 37#include "wx/stc/stc.h"
ea88e9bc 38#include "wx/stc/private.h"
9ce192d4 39
f97d84a6 40
f9ee2e27 41
9ce192d4 42Point Point::FromLong(long lpoint) {
f6bcfd97 43 return Point(lpoint & 0xFFFF, lpoint >> 16);
9ce192d4
RD
44}
45
46wxRect wxRectFromPRectangle(PRectangle prc) {
d13ea3aa
RD
47 wxRect r(prc.left, prc.top,
48 prc.Width(), prc.Height());
49 return r;
9ce192d4
RD
50}
51
52PRectangle PRectangleFromwxRect(wxRect rc) {
bec17edf 53 return PRectangle(rc.GetLeft(), rc.GetTop(),
04ebdf40 54 rc.GetRight()+1, rc.GetBottom()+1);
9ce192d4
RD
55}
56
1a2fb4cd
RD
57wxColour wxColourFromCA(const ColourAllocated& ca) {
58 ColourDesired cd(ca.AsLong());
c8b75e94
WS
59 return wxColour((unsigned char)cd.GetRed(),
60 (unsigned char)cd.GetGreen(),
61 (unsigned char)cd.GetBlue());
9ce192d4
RD
62}
63
1a2fb4cd 64//----------------------------------------------------------------------
9ce192d4
RD
65
66Palette::Palette() {
67 used = 0;
68 allowRealization = false;
b8193d80
RD
69 size = 100;
70 entries = new ColourPair[size];
9ce192d4
RD
71}
72
73Palette::~Palette() {
74 Release();
b8193d80
RD
75 delete [] entries;
76 entries = 0;
9ce192d4
RD
77}
78
79void Palette::Release() {
80 used = 0;
b8193d80
RD
81 delete [] entries;
82 size = 100;
83 entries = new ColourPair[size];
9ce192d4
RD
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
b8193d80
RD
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;
9ce192d4 105 }
b8193d80
RD
106
107 entries[used].desired = cp.desired;
108 entries[used].allocated.Set(cp.desired.AsLong());
109 used++;
9ce192d4
RD
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 }
1a2fb4cd 117 cp.allocated.Set(cp.desired.AsLong());
9ce192d4
RD
118 }
119}
120
121void Palette::Allocate(Window &) {
122 if (allowRealization) {
123 }
124}
125
126
1a2fb4cd
RD
127//----------------------------------------------------------------------
128
9ce192d4
RD
129Font::Font() {
130 id = 0;
131 ascent = 0;
132}
133
134Font::~Font() {
135}
136
d1558f3d 137void Font::Create(const char *faceName, int characterSet, int size, bool bold, bool italic, bool extraFontFlag) {
65ec6247 138
9ce192d4 139 Release();
1a2fb4cd 140
3727c043
RD
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);
d35ad26e 146
10ef30eb
RD
147 wxFontEncodingArray ea = wxEncodingConverter::GetPlatformEquivalents(encoding);
148 if (ea.GetCount())
149 encoding = ea[0];
1a2fb4cd 150
d1558f3d 151 wxFont* font = new wxFont(size,
9ce192d4
RD
152 wxDEFAULT,
153 italic ? wxITALIC : wxNORMAL,
154 bold ? wxBOLD : wxNORMAL,
155 false,
0c5b83b0 156 stc2wx(faceName),
1a2fb4cd 157 encoding);
d1558f3d
RD
158 font->SetNoAntiAliasing(!extraFontFlag);
159 id = font;
9ce192d4
RD
160}
161
162
163void Font::Release() {
164 if (id)
1a2fb4cd 165 delete (wxFont*)id;
9ce192d4
RD
166 id = 0;
167}
168
1a2fb4cd
RD
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;
9ce192d4 179
1a2fb4cd
RD
180public:
181 SurfaceImpl();
182 ~SurfaceImpl();
183
9e730a78
RD
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);
b8193d80
RD
200 virtual void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
201 ColourAllocated outline, int alphaOutline, int flags);
9e730a78
RD
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);
1a2fb4cd
RD
224
225 void BrushColour(ColourAllocated back);
226 void SetFont(Font &font_);
227};
228
229
230
231SurfaceImpl::SurfaceImpl() :
9ce192d4 232 hdc(0), hdcOwned(0), bitmap(0),
1a2fb4cd
RD
233 x(0), y(0), unicodeMode(0)
234{}
9ce192d4 235
1a2fb4cd 236SurfaceImpl::~SurfaceImpl() {
9ce192d4
RD
237 Release();
238}
239
9e730a78 240void SurfaceImpl::Init(WindowID wid) {
81b32ce5 241#if 0
9ce192d4
RD
242 Release();
243 hdc = new wxMemoryDC();
244 hdcOwned = true;
81b32ce5 245#else
09bb2551 246 // On Mac and GTK the DC is not really valid until it has a bitmap
81b32ce5
RD
247 // selected into it. So instead of just creating the DC with no bitmap,
248 // go ahead and give it one.
9e730a78 249 InitPixMap(1,1,NULL,wid);
0f713d48 250#endif
9ce192d4
RD
251}
252
9e730a78 253void SurfaceImpl::Init(SurfaceID hdc_, WindowID) {
9ce192d4 254 Release();
1a2fb4cd 255 hdc = (wxDC*)hdc_;
9ce192d4
RD
256}
257
88a8b04e 258void SurfaceImpl::InitPixMap(int width, int height, Surface *WXUNUSED(surface_), WindowID) {
9ce192d4 259 Release();
1a2fb4cd 260 hdc = new wxMemoryDC();
9ce192d4 261 hdcOwned = true;
2beb01db
RD
262 if (width < 1) width = 1;
263 if (height < 1) height = 1;
21156596 264 bitmap = new wxBitmap(width, height);
9ce192d4 265 ((wxMemoryDC*)hdc)->SelectObject(*bitmap);
9ce192d4
RD
266}
267
9e730a78
RD
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
1a2fb4cd
RD
288void SurfaceImpl::PenColour(ColourAllocated fore) {
289 hdc->SetPen(wxPen(wxColourFromCA(fore), 1, wxSOLID));
9ce192d4
RD
290}
291
1a2fb4cd
RD
292void SurfaceImpl::BrushColour(ColourAllocated back) {
293 hdc->SetBrush(wxBrush(wxColourFromCA(back), wxSOLID));
9ce192d4
RD
294}
295
1a2fb4cd 296void SurfaceImpl::SetFont(Font &font_) {
21156596 297 if (font_.GetID()) {
1a2fb4cd 298 hdc->SetFont(*((wxFont*)font_.GetID()));
f6bcfd97 299 }
9ce192d4
RD
300}
301
1a2fb4cd 302int SurfaceImpl::LogPixelsY() {
9ce192d4
RD
303 return hdc->GetPPI().y;
304}
305
1a2fb4cd 306int SurfaceImpl::DeviceHeightFont(int points) {
9968ba85 307 return points;
f6bcfd97
BP
308}
309
1a2fb4cd 310void SurfaceImpl::MoveTo(int x_, int y_) {
9ce192d4
RD
311 x = x_;
312 y = y_;
313}
314
1a2fb4cd 315void SurfaceImpl::LineTo(int x_, int y_) {
9ce192d4
RD
316 hdc->DrawLine(x,y, x_,y_);
317 x = x_;
318 y = y_;
319}
320
1a2fb4cd 321void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) {
9ce192d4 322 PenColour(fore);
1a2fb4cd 323 BrushColour(back);
9ce192d4
RD
324 hdc->DrawPolygon(npts, (wxPoint*)pts);
325}
326
1a2fb4cd 327void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
9ce192d4 328 PenColour(fore);
1a2fb4cd 329 BrushColour(back);
9ce192d4
RD
330 hdc->DrawRectangle(wxRectFromPRectangle(rc));
331}
332
1a2fb4cd
RD
333void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) {
334 BrushColour(back);
9ce192d4
RD
335 hdc->SetPen(*wxTRANSPARENT_PEN);
336 hdc->DrawRectangle(wxRectFromPRectangle(rc));
337}
338
1a2fb4cd 339void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
9ce192d4 340 wxBrush br;
1a2fb4cd
RD
341 if (((SurfaceImpl&)surfacePattern).bitmap)
342 br = wxBrush(*((SurfaceImpl&)surfacePattern).bitmap);
9ce192d4
RD
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
1a2fb4cd 350void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
9ce192d4 351 PenColour(fore);
1a2fb4cd 352 BrushColour(back);
f6bcfd97 353 hdc->DrawRoundedRectangle(wxRectFromPRectangle(rc), 4);
9ce192d4
RD
354}
355
6a93571d
RD
356#ifdef __WXMSW__
357#define wxPy_premultiply(p, a) ((p) * (a) / 0xff)
358#else
359#define wxPy_premultiply(p, a) (p)
360#endif
361
b8193d80
RD
362void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize,
363 ColourAllocated fill, int alphaFill,
6a93571d
RD
364 ColourAllocated outline, int alphaOutline,
365 int /*flags*/) {
8b3d52fc 366#ifdef wxHAVE_RAW_BITMAP
a3511a2e
RD
367
368 // TODO: do something with cornerSize
369 wxUnusedVar(cornerSize);
370
6a93571d
RD
371 int x, y;
372 wxRect r = wxRectFromPRectangle(rc);
373 wxBitmap bmp(r.width, r.height, 32);
374 wxAlphaPixelData pixData(bmp);
6a93571d
RD
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 }
b8193d80 411
6a93571d
RD
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);
8b3d52fc
RD
427
428#else
a3511a2e
RD
429 wxUnusedVar(cornerSize);
430 wxUnusedVar(alphaFill);
431 wxUnusedVar(alphaOutline);
432 RectangleDraw(rc, outline, fill);
8b3d52fc 433#endif
b8193d80
RD
434}
435
1a2fb4cd 436void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
9ce192d4 437 PenColour(fore);
1a2fb4cd 438 BrushColour(back);
9ce192d4
RD
439 hdc->DrawEllipse(wxRectFromPRectangle(rc));
440}
441
1a2fb4cd 442void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
f6bcfd97
BP
443 wxRect r = wxRectFromPRectangle(rc);
444 hdc->Blit(r.x, r.y, r.width, r.height,
1a2fb4cd
RD
445 ((SurfaceImpl&)surfaceSource).hdc,
446 from.x, from.y, wxCOPY);
9ce192d4
RD
447}
448
1a2fb4cd
RD
449void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font, int ybase,
450 const char *s, int len,
451 ColourAllocated fore, ColourAllocated back) {
9ce192d4 452 SetFont(font);
1a2fb4cd
RD
453 hdc->SetTextForeground(wxColourFromCA(fore));
454 hdc->SetTextBackground(wxColourFromCA(back));
3d7a4fe8 455 FillRectangle(rc, back);
9ce192d4
RD
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...
d13ea3aa 459 hdc->DrawText(stc2wx(s, len), rc.left, ybase - font.ascent);
9ce192d4
RD
460}
461
1a2fb4cd
RD
462void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font, int ybase,
463 const char *s, int len,
464 ColourAllocated fore, ColourAllocated back) {
9ce192d4 465 SetFont(font);
1a2fb4cd
RD
466 hdc->SetTextForeground(wxColourFromCA(fore));
467 hdc->SetTextBackground(wxColourFromCA(back));
3d7a4fe8 468 FillRectangle(rc, back);
9ce192d4
RD
469 hdc->SetClippingRegion(wxRectFromPRectangle(rc));
470
471 // see comments above
d13ea3aa 472 hdc->DrawText(stc2wx(s, len), rc.left, ybase - font.ascent);
3d7a4fe8 473 hdc->DestroyClippingRegion();
9ce192d4
RD
474}
475
9e730a78
RD
476
477void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font, int ybase,
478 const char *s, int len,
479 ColourAllocated fore) {
480
9ce192d4 481 SetFont(font);
9e730a78
RD
482 hdc->SetTextForeground(wxColourFromCA(fore));
483 hdc->SetBackgroundMode(wxTRANSPARENT);
1a2fb4cd 484
9e730a78
RD
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...
d13ea3aa 487 hdc->DrawText(stc2wx(s, len), rc.left, ybase - font.ascent);
9e730a78
RD
488
489 hdc->SetBackgroundMode(wxSOLID);
9ce192d4
RD
490}
491
1a2fb4cd 492
10ef30eb 493void SurfaceImpl::MeasureWidths(Font &font, const char *s, int len, int *positions) {
9e730a78 494
d1558f3d
RD
495 wxString str = stc2wx(s, len);
496 wxArrayInt tpos;
10ef30eb 497
d1558f3d 498 SetFont(font);
9e730a78 499
d1558f3d 500 hdc->GetPartialTextExtents(str, tpos);
10ef30eb
RD
501
502#if wxUSE_UNICODE
503 // Map the widths for UCS-2 characters back to the UTF-8 input string
9e730a78
RD
504 // NOTE: I don't think this is right for when sizeof(wxChar) > 2, ie wxGTK2
505 // so figure it out and fix it!
d1558f3d 506 size_t i = 0;
10ef30eb 507 size_t ui = 0;
d99859e4 508 while ((int)i < len) {
10ef30eb
RD
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
f3ee029e
MB
524#if wxUSE_STL
525 std::copy(tpos.begin(), tpos.end(), positions);
526#else
d1558f3d 527 memcpy(positions, tpos.begin(), len * sizeof(int));
10ef30eb 528#endif
f3ee029e 529#endif
9ce192d4
RD
530}
531
10ef30eb 532
9e730a78
RD
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
1a2fb4cd 543int SurfaceImpl::WidthChar(Font &font, char ch) {
9ce192d4
RD
544 SetFont(font);
545 int w;
546 int h;
10ef30eb
RD
547 char s[2] = { ch, 0 };
548
0c5b83b0 549 hdc->GetTextExtent(stc2wx(s, 1), &w, &h);
9ce192d4
RD
550 return w;
551}
552
1a2fb4cd 553#define EXTENT_TEST wxT(" `~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
9ce192d4 554
1a2fb4cd 555int SurfaceImpl::Ascent(Font &font) {
9ce192d4
RD
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
1a2fb4cd 563int SurfaceImpl::Descent(Font &font) {
9ce192d4
RD
564 SetFont(font);
565 int w, h, d, e;
566 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
567 return d;
568}
569
88a8b04e 570int SurfaceImpl::InternalLeading(Font &WXUNUSED(font)) {
9ce192d4
RD
571 return 0;
572}
573
1a2fb4cd 574int SurfaceImpl::ExternalLeading(Font &font) {
9ce192d4
RD
575 SetFont(font);
576 int w, h, d, e;
577 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
578 return e;
579}
580
1a2fb4cd 581int SurfaceImpl::Height(Font &font) {
9ce192d4 582 SetFont(font);
d13ea3aa 583 return hdc->GetCharHeight() + 1;
9ce192d4
RD
584}
585
1a2fb4cd 586int SurfaceImpl::AverageCharWidth(Font &font) {
9ce192d4
RD
587 SetFont(font);
588 return hdc->GetCharWidth();
589}
590
88a8b04e 591int SurfaceImpl::SetPalette(Palette *WXUNUSED(pal), bool WXUNUSED(inBackGround)) {
65ec6247 592 return 0;
9ce192d4
RD
593}
594
1a2fb4cd 595void SurfaceImpl::SetClip(PRectangle rc) {
9ce192d4
RD
596 hdc->SetClippingRegion(wxRectFromPRectangle(rc));
597}
598
1a2fb4cd 599void SurfaceImpl::FlushCachedState() {
f6bcfd97 600}
9ce192d4 601
1a2fb4cd 602void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {
1a2fb4cd
RD
603 unicodeMode=unicodeMode_;
604}
605
88a8b04e 606void SurfaceImpl::SetDBCSMode(int WXUNUSED(codePage)) {
9e730a78
RD
607 // dbcsMode = codePage == SC_CP_DBCS;
608}
609
610
1a2fb4cd
RD
611Surface *Surface::Allocate() {
612 return new SurfaceImpl;
613}
614
615
616//----------------------------------------------------------------------
617
618
619inline wxWindow* GETWIN(WindowID id) { return (wxWindow*)id; }
620
9ce192d4
RD
621Window::~Window() {
622}
623
624void Window::Destroy() {
9e730a78 625 if (id) {
7e126a07 626 Show(false);
1a2fb4cd 627 GETWIN(id)->Destroy();
9e730a78 628 }
9ce192d4
RD
629 id = 0;
630}
631
632bool Window::HasFocus() {
1a2fb4cd 633 return wxWindow::FindFocus() == GETWIN(id);
9ce192d4
RD
634}
635
636PRectangle Window::GetPosition() {
9e730a78 637 if (! id) return PRectangle();
1a2fb4cd 638 wxRect rc(GETWIN(id)->GetPosition(), GETWIN(id)->GetSize());
9ce192d4
RD
639 return PRectangleFromwxRect(rc);
640}
641
642void Window::SetPosition(PRectangle rc) {
f6bcfd97 643 wxRect r = wxRectFromPRectangle(rc);
1a2fb4cd 644 GETWIN(id)->SetSize(r);
9ce192d4
RD
645}
646
647void Window::SetPositionRelative(PRectangle rc, Window) {
648 SetPosition(rc); // ????
649}
650
651PRectangle Window::GetClientPosition() {
9e730a78 652 if (! id) return PRectangle();
1a2fb4cd 653 wxSize sz = GETWIN(id)->GetClientSize();
21156596 654 return PRectangle(0, 0, sz.x, sz.y);
9ce192d4
RD
655}
656
657void Window::Show(bool show) {
1a2fb4cd 658 GETWIN(id)->Show(show);
9ce192d4
RD
659}
660
661void Window::InvalidateAll() {
1a2fb4cd 662 GETWIN(id)->Refresh(false);
9ce192d4
RD
663}
664
665void Window::InvalidateRectangle(PRectangle rc) {
f6bcfd97 666 wxRect r = wxRectFromPRectangle(rc);
1a2fb4cd 667 GETWIN(id)->Refresh(false, &r);
9ce192d4
RD
668}
669
670void Window::SetFont(Font &font) {
1a2fb4cd 671 GETWIN(id)->SetFont(*((wxFont*)font.GetID()));
9ce192d4
RD
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:
15dadf31 697 cursorId = wxCURSOR_RIGHT_ARROW;
9ce192d4 698 break;
9e730a78
RD
699 case cursorHand:
700 cursorId = wxCURSOR_HAND;
1e545382 701 break;
9ce192d4
RD
702 default:
703 cursorId = wxCURSOR_ARROW;
704 break;
705 }
9f79d14b
CE
706#ifdef __WXMOTIF__
707 wxCursor wc = wxStockCursor(cursorId) ;
708#else
709 wxCursor wc = wxCursor(cursorId) ;
710#endif
5e99793e
VZ
711 if(curs != cursorLast)
712 {
713 GETWIN(id)->SetCursor(wc);
714 cursorLast = curs;
715 }
9ce192d4
RD
716}
717
718
719void Window::SetTitle(const char *s) {
fd39aa23 720 GETWIN(id)->SetLabel(stc2wx(s));
9ce192d4
RD
721}
722
723
769a9cb2
RD
724//----------------------------------------------------------------------
725// Helper classes for ListBox
726
267484bc 727
b0d0494f 728// This is a simple subclass of wxListView that just resets focus to the
9e730a78
RD
729// parent when it gets it.
730class wxSTCListBox : public wxListView {
451c5cc7 731public:
9e730a78
RD
732 wxSTCListBox(wxWindow* parent, wxWindowID id,
733 const wxPoint& pos, const wxSize& size,
734 long style)
382fe640
RD
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 }
451c5cc7 742
7e126a07 743
451c5cc7
RD
744 void OnFocus(wxFocusEvent& event) {
745 GetParent()->SetFocus();
746 event.Skip();
747 }
748
5f9eb69c 749 void OnKillFocus(wxFocusEvent& WXUNUSED(event)) {
b0d0494f
RD
750 // Do nothing. Prevents base class from resetting the colors...
751 }
7e126a07 752
719ee9c3
RD
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 }
b0d0494f 763
719ee9c3
RD
764 // And we need to force the focus back when being destroyed
765 ~wxSTCListBox() {
766 GetGrandParent()->SetFocus();
7e126a07
WS
767 }
768#endif
769
451c5cc7
RD
770private:
771 DECLARE_EVENT_TABLE()
772};
773
9e730a78
RD
774BEGIN_EVENT_TABLE(wxSTCListBox, wxListView)
775 EVT_SET_FOCUS( wxSTCListBox::OnFocus)
b0d0494f 776 EVT_KILL_FOCUS(wxSTCListBox::OnKillFocus)
719ee9c3
RD
777#ifdef __WXMAC__
778 EVT_KEY_DOWN( wxSTCListBox::OnKeyDown)
779 EVT_CHAR( wxSTCListBox::OnChar)
780#endif
451c5cc7
RD
781END_EVENT_TABLE()
782
783
784
d35ad26e 785#if wxUSE_POPUPWIN //-----------------------------------
819850ff 786#include "wx/popupwin.h"
382fe640
RD
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...
d35ad26e
WS
795//
796
797// A popup window to place the wxSTCListBox upon
382fe640
RD
798class wxSTCListBoxWin : public wxPopupWindow
799{
800private:
801 wxListView* lv;
802 CallBackAction doubleClickAction;
803 void* doubleClickActionData;
804public:
d35ad26e 805 wxSTCListBoxWin(wxWindow* parent, wxWindowID id, Point WXUNUSED(location)) :
382fe640
RD
806 wxPopupWindow(parent, wxBORDER_NONE)
807 {
67879c5b 808
382fe640
RD
809 SetBackgroundColour(*wxBLACK); // for our simple border
810
67879c5b 811 lv = new wxSTCListBox(parent, id, wxPoint(-50,-50), wxDefaultSize,
382fe640
RD
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
d35ad26e 822 // then reparent it back to the popup.
382fe640
RD
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
d35ad26e 913
382fe640 914
67879c5b 915#else // !wxUSE_POPUPWIN -----------------------------------
819850ff 916#include "wx/frame.h"
267484bc 917
67879c5b
RD
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 {
9e730a78
RD
921private:
922 wxListView* lv;
923 CallBackAction doubleClickAction;
924 void* doubleClickActionData;
f97d84a6 925public:
1e9bafca 926 wxSTCListBoxWin(wxWindow* parent, wxWindowID id, Point location) :
67879c5b
RD
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 )
9e730a78
RD
937 {
938
9e730a78
RD
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);
b0d0494f
RD
944
945 // Eventhough we immediately reset the focus to the parent, this helps
946 // things to look right...
947 lv->SetFocus();
948
6612393c 949 Hide();
67879c5b 950 }
6612393c 951
7e126a07 952
a4f3565e
RD
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.
67879c5b
RD
957 bool Destroy()
958 {
d13ea3aa 959#ifdef __WXMAC__
719ee9c3 960 // The bottom edge of this window is not getting properly
d13ea3aa
RD
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
a4f3565e
RD
967 if ( !wxPendingDelete.Member(this) )
968 wxPendingDelete.Append(this);
7e126a07 969 return true;
f97d84a6
RD
970 }
971
7e126a07 972
67879c5b
RD
973 int IconWidth()
974 {
9e730a78
RD
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 }
f97d84a6 983
769a9cb2 984
67879c5b
RD
985 void SetDoubleClickAction(CallBackAction action, void *data)
986 {
9e730a78
RD
987 doubleClickAction = action;
988 doubleClickActionData = data;
989 }
451c5cc7 990
769a9cb2 991
67879c5b
RD
992 void OnFocus(wxFocusEvent& event)
993 {
994 ActivateParent();
9e730a78
RD
995 GetParent()->SetFocus();
996 event.Skip();
997 }
769a9cb2 998
67879c5b
RD
999 void OnSize(wxSizeEvent& event)
1000 {
d13ea3aa 1001 // resize the child
9e730a78 1002 wxSize sz = GetClientSize();
d13ea3aa 1003 lv->SetSize(sz);
9e730a78
RD
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();
769a9cb2 1009 }
769a9cb2 1010
67879c5b
RD
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();
719493e1 1041#ifdef __WXMAC__
719493e1 1042 GetParent()->Refresh(false);
67879c5b 1043#endif
719493e1
RD
1044 return rv;
1045 }
d35ad26e 1046
67879c5b
RD
1047 void OnActivate(wxListEvent& WXUNUSED(event))
1048 {
9e730a78 1049 doubleClickAction(doubleClickActionData);
769a9cb2 1050 }
9e730a78
RD
1051
1052 wxListView* GetLB() { return lv; }
769a9cb2
RD
1053
1054private:
769a9cb2
RD
1055 DECLARE_EVENT_TABLE()
1056};
1057
9e730a78
RD
1058
1059BEGIN_EVENT_TABLE(wxSTCListBoxWin, wxWindow)
7e126a07
WS
1060 EVT_SET_FOCUS ( wxSTCListBoxWin::OnFocus)
1061 EVT_SIZE ( wxSTCListBoxWin::OnSize)
1062 EVT_LIST_ITEM_ACTIVATED(wxID_ANY, wxSTCListBoxWin::OnActivate)
769a9cb2 1063END_EVENT_TABLE()
769a9cb2 1064
382fe640 1065#endif // wxUSE_POPUPWIN -----------------------------------
9e730a78
RD
1066
1067
1068inline wxSTCListBoxWin* GETLBW(WindowID win) {
1069 return ((wxSTCListBoxWin*)win);
1070}
1071
1072inline wxListView* GETLB(WindowID win) {
1073 return GETLBW(win)->GetLB();
1a2fb4cd 1074}
769a9cb2
RD
1075
1076//----------------------------------------------------------------------
1077
9e730a78
RD
1078class ListBoxImpl : public ListBox {
1079private:
1080 int lineHeight;
1081 bool unicodeMode;
1082 int desiredVisibleRows;
1083 int aveCharWidth;
80cac95e 1084 size_t maxStrWidth;
1e9bafca 1085 Point location; // Caret location at which the list is opened
9e730a78
RD
1086 wxImageList* imgList;
1087 wxArrayInt* imgTypeMap;
1088
1089public:
1090 ListBoxImpl();
1091 ~ListBoxImpl();
1092
1093 virtual void SetFont(Font &font);
1e9bafca 1094 virtual void Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_);
9e730a78
RD
1095 virtual void SetAverageCharWidth(int width);
1096 virtual void SetVisibleRows(int rows);
1e9bafca 1097 virtual int GetVisibleRows() const;
9e730a78
RD
1098 virtual PRectangle GetDesiredRect();
1099 virtual int CaretFromEdge();
1100 virtual void Clear();
1101 virtual void Append(char *s, int type = -1);
1e9bafca 1102 void Append(const wxString& text, int type);
9e730a78
RD
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);
9e730a78
RD
1108 virtual void RegisterImage(int type, const char *xpm_data);
1109 virtual void ClearRegisteredImages();
1110 virtual void SetDoubleClickAction(CallBackAction, void *);
1e9bafca 1111 virtual void SetList(const char* list, char separator, char typesep);
9e730a78
RD
1112};
1113
1114
1115ListBoxImpl::ListBoxImpl()
1116 : lineHeight(10), unicodeMode(false),
1117 desiredVisibleRows(5), aveCharWidth(8), maxStrWidth(0),
1118 imgList(NULL), imgTypeMap(NULL)
1119{
9ce192d4
RD
1120}
1121
9e730a78
RD
1122ListBoxImpl::~ListBoxImpl() {
1123 if (imgList) {
1124 delete imgList;
1125 imgList = NULL;
1126 }
1127 if (imgTypeMap) {
1128 delete imgTypeMap;
1129 imgTypeMap = NULL;
1130 }
9ce192d4
RD
1131}
1132
9e730a78
RD
1133
1134void ListBoxImpl::SetFont(Font &font) {
1135 GETLB(id)->SetFont(*((wxFont*)font.GetID()));
1136}
1137
1138
1e9bafca
RD
1139void ListBoxImpl::Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_) {
1140 location = location_;
9e730a78
RD
1141 lineHeight = lineHeight_;
1142 unicodeMode = unicodeMode_;
1143 maxStrWidth = 0;
1e9bafca 1144 id = new wxSTCListBoxWin(GETWIN(parent.GetID()), ctrlID, location);
9e730a78
RD
1145 if (imgList != NULL)
1146 GETLB(id)->SetImageList(imgList, wxIMAGE_LIST_SMALL);
9ce192d4
RD
1147}
1148
9e730a78
RD
1149
1150void ListBoxImpl::SetAverageCharWidth(int width) {
1151 aveCharWidth = width;
1152}
1153
1154
1155void ListBoxImpl::SetVisibleRows(int rows) {
769a9cb2 1156 desiredVisibleRows = rows;
f3c2c221
RD
1157}
1158
9e730a78 1159
1e9bafca
RD
1160int ListBoxImpl::GetVisibleRows() const {
1161 return desiredVisibleRows;
1162}
1163
9e730a78
RD
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...
1e9bafca 1167 int maxw = maxStrWidth * aveCharWidth;
1e545382 1168 int maxh ;
9e730a78
RD
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
d134f170
RD
1193 PRectangle rc;
1194 rc.top = 0;
1195 rc.left = 0;
9e730a78
RD
1196 rc.right = maxw;
1197 rc.bottom = maxh;
d134f170
RD
1198 return rc;
1199}
1200
d134f170 1201
9e730a78
RD
1202int ListBoxImpl::CaretFromEdge() {
1203 return 4 + GETLBW(id)->IconWidth();
d134f170
RD
1204}
1205
9e730a78
RD
1206
1207void ListBoxImpl::Clear() {
1208 GETLB(id)->DeleteAllItems();
9ce192d4
RD
1209}
1210
9e730a78
RD
1211
1212void ListBoxImpl::Append(char *s, int type) {
1e9bafca
RD
1213 Append(stc2wx(s), type);
1214}
1215
1216void ListBoxImpl::Append(const wxString& text, int type) {
9e730a78
RD
1217 long count = GETLB(id)->GetItemCount();
1218 long itemID = GETLB(id)->InsertItem(count, wxEmptyString);
1219 GETLB(id)->SetItem(itemID, 1, text);
d35ad26e 1220 maxStrWidth = wxMax(maxStrWidth, text.length());
9e730a78
RD
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 }
9ce192d4
RD
1226}
1227
1e9bafca
RD
1228void ListBoxImpl::SetList(const char* list, char separator, char typesep) {
1229 GETLB(id)->Freeze();
d35ad26e 1230 Clear();
1e9bafca
RD
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
9e730a78
RD
1245
1246int ListBoxImpl::Length() {
1247 return GETLB(id)->GetItemCount();
9ce192d4
RD
1248}
1249
9e730a78
RD
1250
1251void ListBoxImpl::Select(int n) {
7e126a07 1252 bool select = true;
895066d8
RD
1253 if (n == -1) {
1254 n = 0;
7e126a07 1255 select = false;
895066d8 1256 }
67879c5b 1257 GETLB(id)->EnsureVisible(n);
9e730a78 1258 GETLB(id)->Select(n, select);
9ce192d4
RD
1259}
1260
9e730a78
RD
1261
1262int ListBoxImpl::GetSelection() {
1263 return GETLB(id)->GetFirstSelected();
9ce192d4
RD
1264}
1265
9e730a78 1266
88a8b04e 1267int ListBoxImpl::Find(const char *WXUNUSED(prefix)) {
b8b0e402 1268 // No longer used
7e126a07 1269 return wxNOT_FOUND;
9ce192d4
RD
1270}
1271
9e730a78
RD
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);
9ce192d4
RD
1280 value[len-1] = '\0';
1281}
1282
9e730a78
RD
1283
1284void ListBoxImpl::RegisterImage(int type, const char *xpm_data) {
1285 wxMemoryInputStream stream(xpm_data, strlen(xpm_data)+1);
c8b75e94
WS
1286 wxImage img(stream, wxBITMAP_TYPE_XPM);
1287 wxBitmap bmp(img);
9e730a78
RD
1288
1289 if (! imgList) {
1290 // assumes all images are the same size
7e126a07 1291 imgList = new wxImageList(bmp.GetWidth(), bmp.GetHeight(), true);
9e730a78
RD
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;
9a8ffadd 1299 if ( itm.GetCount() < (size_t)type+1)
9e730a78
RD
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
9e730a78
RD
1325ListBox::ListBox() {
1326}
1327
1328ListBox::~ListBox() {
1329}
1330
1331ListBox *ListBox::Allocate() {
1332 return new ListBoxImpl();
9ce192d4
RD
1333}
1334
1a2fb4cd 1335//----------------------------------------------------------------------
9ce192d4
RD
1336
1337Menu::Menu() : id(0) {
1338}
1339
1340void Menu::CreatePopUp() {
1341 Destroy();
1342 id = new wxMenu();
1343}
1344
1345void Menu::Destroy() {
1346 if (id)
1a2fb4cd 1347 delete (wxMenu*)id;
9ce192d4
RD
1348 id = 0;
1349}
1350
1351void Menu::Show(Point pt, Window &w) {
1a2fb4cd 1352 GETWIN(w.GetID())->PopupMenu((wxMenu*)id, pt.x - 4, pt.y);
9ce192d4
RD
1353 Destroy();
1354}
1355
1a2fb4cd 1356//----------------------------------------------------------------------
9ce192d4 1357
88a8b04e 1358DynamicLibrary *DynamicLibrary::Load(const char *WXUNUSED(modulePath)) {
e14d10b0
RD
1359 wxFAIL_MSG(wxT("Dynamic lexer loading not implemented yet"));
1360 return NULL;
1361}
1362
1363//----------------------------------------------------------------------
1364
1a2fb4cd 1365ColourDesired Platform::Chrome() {
9ce192d4 1366 wxColour c;
e1c6c6ae 1367 c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
1a2fb4cd 1368 return ColourDesired(c.Red(), c.Green(), c.Blue());
9ce192d4
RD
1369}
1370
1a2fb4cd 1371ColourDesired Platform::ChromeHighlight() {
9ce192d4 1372 wxColour c;
e1c6c6ae 1373 c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT);
1a2fb4cd 1374 return ColourDesired(c.Red(), c.Green(), c.Blue());
9ce192d4
RD
1375}
1376
1377const char *Platform::DefaultFont() {
10ef30eb
RD
1378 static char buf[128];
1379 strcpy(buf, wxNORMAL_FONT->GetFaceName().mbc_str());
1380 return buf;
9ce192d4
RD
1381}
1382
1383int Platform::DefaultFontSize() {
9e730a78 1384 return wxNORMAL_FONT->GetPointSize();
9ce192d4
RD
1385}
1386
1387unsigned int Platform::DoubleClickTime() {
1388 return 500; // **** ::GetDoubleClickTime();
1389}
1390
9e730a78 1391bool Platform::MouseButtonBounce() {
7e126a07 1392 return false;
9e730a78 1393}
9ce192d4 1394
88a8b04e 1395bool Platform::IsKeyDown(int WXUNUSED(key)) {
9ce192d4
RD
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
a834585d
RD
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
9ce192d4
RD
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
74e1efdd
VZ
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}
9ce192d4
RD
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);
8d3a5374
VZ
1452#else
1453 wxUnusedVar(format);
9ce192d4
RD
1454#endif
1455}
1456
65ec6247
RD
1457
1458static bool assertionPopUps = true;
1459
1460bool Platform::ShowAssertionPopUps(bool assertionPopUps_) {
7e126a07
WS
1461 bool ret = assertionPopUps;
1462 assertionPopUps = assertionPopUps_;
1463 return ret;
65ec6247
RD
1464}
1465
1466void Platform::Assert(const char *c, const char *file, int line) {
74e1efdd 1467#ifdef TRACE
7e126a07
WS
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);
7e126a07
WS
1475 } else {
1476 strcat(buffer, "\r\n");
1477 Platform::DebugDisplay(buffer);
1478 abort();
1479 }
74e1efdd
VZ
1480#else
1481 wxUnusedVar(c);
1482 wxUnusedVar(file);
1483 wxUnusedVar(line);
1484#endif
65ec6247
RD
1485}
1486
1487
9ce192d4
RD
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
88a8b04e 1497bool Platform::IsDBCSLeadByte(int WXUNUSED(codePage), char WXUNUSED(ch)) {
1a2fb4cd
RD
1498 return false;
1499}
1500
88a8b04e 1501int Platform::DBCSCharLength(int WXUNUSED(codePage), const char *WXUNUSED(s)) {
215ef7ae 1502 return 1;
9e730a78
RD
1503}
1504
1505int Platform::DBCSCharMaxLength() {
215ef7ae 1506 return 1;
9e730a78 1507}
1a2fb4cd
RD
1508
1509
1510//----------------------------------------------------------------------
1511
1512ElapsedTime::ElapsedTime() {
1d94e268
WS
1513 wxLongLong localTime = wxGetLocalTimeMillis();
1514 littleBit = localTime.GetLo();
1515 bigBit = localTime.GetHi();
1a2fb4cd
RD
1516}
1517
1518double ElapsedTime::Duration(bool reset) {
1d94e268
WS
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();
1a2fb4cd
RD
1527 result /= 1000.0;
1528 return result;
1529}
1530
1531
1532//----------------------------------------------------------------------
9ce192d4 1533
d99859e4 1534#if wxUSE_UNICODE
6636ac1e
RD
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...
c8b75e94 1540
d99859e4
RD
1541wxString stc2wx(const char* str, size_t len)
1542{
81bfa5ae
RD
1543 if (!len)
1544 return wxEmptyString;
8a07b43c 1545
6636ac1e
RD
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
d99859e4 1553
d99859e4 1554
6636ac1e
RD
1555wxString stc2wx(const char* str)
1556{
1557 return stc2wx(str, strlen(str));
d99859e4 1558}
6636ac1e
RD
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
6636ac1e
RD
1572 return buffer;
1573}
1574
d99859e4 1575#endif
29825f5f
PC
1576
1577#endif // wxUSE_STC