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