1 // Scintilla source code edit control
2 // PlatWX.cxx - implementation of platform facilities on wxWidgets
3 // Copyright 1998-1999 by Neil Hodgson <neilh@scintilla.org>
4 // Robin Dunn <robin@aldunn.com>
5 // The License.txt file describes the conditions under which this software may be distributed.
7 // For compilers that support precompilation, includes "wx.h".
18 #include "wx/dcmemory.h"
19 #include "wx/settings.h"
25 #include "wx/display.h"
28 #include "wx/encconv.h"
29 #include "wx/listctrl.h"
30 #include "wx/mstream.h"
32 #include "wx/imaglist.h"
33 #include "wx/tokenzr.h"
35 #ifdef wxHAS_RAW_BITMAP
36 #include "wx/rawbmp.h"
38 #if wxUSE_GRAPHICS_CONTEXT
39 #include "wx/dcgraph.h"
44 #include "wx/stc/stc.h"
45 #include "wx/stc/private.h"
48 Point
Point::FromLong(long lpoint
) {
49 return Point(lpoint
& 0xFFFF, lpoint
>> 16);
52 wxRect
wxRectFromPRectangle(PRectangle prc
) {
53 wxRect
r(prc
.left
, prc
.top
,
54 prc
.Width(), prc
.Height());
58 PRectangle
PRectangleFromwxRect(wxRect rc
) {
59 return PRectangle(rc
.GetLeft(), rc
.GetTop(),
60 rc
.GetRight()+1, rc
.GetBottom()+1);
63 wxColour
wxColourFromCD(ColourDesired
& cd
) {
64 return wxColour((unsigned char)cd
.GetRed(),
65 (unsigned char)cd
.GetGreen(),
66 (unsigned char)cd
.GetBlue());
69 wxColour
wxColourFromCDandAlpha(ColourDesired
& cd
, int alpha
) {
70 return wxColour((unsigned char)cd
.GetRed(),
71 (unsigned char)cd
.GetGreen(),
72 (unsigned char)cd
.GetBlue(),
73 (unsigned char)alpha
);
76 //----------------------------------------------------------------------
86 void Font::Create(const FontParameters
&fp
) {
89 // The minus one is done because since Scintilla uses SC_CHARSET_DEFAULT
90 // internally and we need to have wxFONENCODING_DEFAULT == SC_SHARSET_DEFAULT
91 // so we adjust the encoding before passing it to Scintilla. See also
92 // wxStyledTextCtrl::StyleSetCharacterSet
93 wxFontEncoding encoding
= (wxFontEncoding
)(fp
.characterSet
-1);
95 wxFontEncodingArray ea
= wxEncodingConverter::GetPlatformEquivalents(encoding
);
100 if (fp
.weight
<= 300)
101 weight
= wxFONTWEIGHT_LIGHT
;
102 else if (fp
.weight
>= 700)
103 weight
= wxFONTWEIGHT_BOLD
;
105 weight
= wxFONTWEIGHT_NORMAL
;
107 wxFont
* font
= new wxFont(fp
.size
,
108 wxFONTFAMILY_DEFAULT
,
109 fp
.italic
? wxFONTSTYLE_ITALIC
: wxFONTSTYLE_NORMAL
,
118 void Font::Release() {
124 //----------------------------------------------------------------------
126 class SurfaceImpl
: public Surface
{
139 virtual void Init(WindowID wid
);
140 virtual void Init(SurfaceID sid
, WindowID wid
);
141 virtual void InitPixMap(int width
, int height
, Surface
*surface_
, WindowID wid
);
143 virtual void Release();
144 virtual bool Initialised();
145 virtual void PenColour(ColourDesired fore
);
146 virtual int LogPixelsY();
147 virtual int DeviceHeightFont(int points
);
148 virtual void MoveTo(int x_
, int y_
);
149 virtual void LineTo(int x_
, int y_
);
150 virtual void Polygon(Point
*pts
, int npts
, ColourDesired fore
, ColourDesired back
);
151 virtual void RectangleDraw(PRectangle rc
, ColourDesired fore
, ColourDesired back
);
152 virtual void FillRectangle(PRectangle rc
, ColourDesired back
);
153 virtual void FillRectangle(PRectangle rc
, Surface
&surfacePattern
);
154 virtual void RoundedRectangle(PRectangle rc
, ColourDesired fore
, ColourDesired back
);
155 virtual void AlphaRectangle(PRectangle rc
, int cornerSize
, ColourDesired fill
, int alphaFill
,
156 ColourDesired outline
, int alphaOutline
, int flags
);
157 virtual void DrawRGBAImage(PRectangle rc
, int width
, int height
,
158 const unsigned char *pixelsImage
);
159 virtual void Ellipse(PRectangle rc
, ColourDesired fore
, ColourDesired back
);
160 virtual void Copy(PRectangle rc
, Point from
, Surface
&surfaceSource
);
162 virtual void DrawTextNoClip(PRectangle rc
, Font
&font_
, XYPOSITION ybase
, const char *s
, int len
, ColourDesired fore
, ColourDesired back
);
163 virtual void DrawTextClipped(PRectangle rc
, Font
&font_
, XYPOSITION ybase
, const char *s
, int len
, ColourDesired fore
, ColourDesired back
);
164 virtual void DrawTextTransparent(PRectangle rc
, Font
&font_
, XYPOSITION ybase
, const char *s
, int len
, ColourDesired fore
);
165 virtual void MeasureWidths(Font
&font_
, const char *s
, int len
, XYPOSITION
*positions
);
166 virtual XYPOSITION
WidthText(Font
&font_
, const char *s
, int len
);
167 virtual XYPOSITION
WidthChar(Font
&font_
, char ch
);
168 virtual XYPOSITION
Ascent(Font
&font_
);
169 virtual XYPOSITION
Descent(Font
&font_
);
170 virtual XYPOSITION
InternalLeading(Font
&font_
);
171 virtual XYPOSITION
ExternalLeading(Font
&font_
);
172 virtual XYPOSITION
Height(Font
&font_
);
173 virtual XYPOSITION
AverageCharWidth(Font
&font_
);
175 virtual void SetClip(PRectangle rc
);
176 virtual void FlushCachedState();
178 virtual void SetUnicodeMode(bool unicodeMode_
);
179 virtual void SetDBCSMode(int codePage
);
181 void BrushColour(ColourDesired back
);
182 void SetFont(Font
&font_
);
187 SurfaceImpl::SurfaceImpl() :
188 hdc(0), hdcOwned(0), bitmap(0),
189 x(0), y(0), unicodeMode(0)
192 SurfaceImpl::~SurfaceImpl() {
196 void SurfaceImpl::Init(WindowID wid
) {
199 hdc
= new wxMemoryDC();
202 // On Mac and GTK the DC is not really valid until it has a bitmap
203 // selected into it. So instead of just creating the DC with no bitmap,
204 // go ahead and give it one.
205 InitPixMap(1,1,NULL
,wid
);
209 void SurfaceImpl::Init(SurfaceID hdc_
, WindowID
) {
214 void SurfaceImpl::InitPixMap(int width
, int height
, Surface
*WXUNUSED(surface_
), WindowID winid
) {
216 hdc
= new wxMemoryDC();
218 if (width
< 1) width
= 1;
219 if (height
< 1) height
= 1;
220 bitmap
= new wxBitmap();
221 bitmap
->CreateScaled(width
, height
,wxBITMAP_SCREEN_DEPTH
,((wxWindow
*)winid
)->GetContentScaleFactor());
222 ((wxMemoryDC
*)hdc
)->SelectObject(*bitmap
);
226 void SurfaceImpl::Release() {
228 ((wxMemoryDC
*)hdc
)->SelectObject(wxNullBitmap
);
240 bool SurfaceImpl::Initialised() {
245 void SurfaceImpl::PenColour(ColourDesired fore
) {
246 hdc
->SetPen(wxPen(wxColourFromCD(fore
)));
249 void SurfaceImpl::BrushColour(ColourDesired back
) {
250 hdc
->SetBrush(wxBrush(wxColourFromCD(back
)));
253 void SurfaceImpl::SetFont(Font
&font_
) {
255 hdc
->SetFont(*((wxFont
*)font_
.GetID()));
259 int SurfaceImpl::LogPixelsY() {
260 return hdc
->GetPPI().y
;
263 int SurfaceImpl::DeviceHeightFont(int points
) {
267 void SurfaceImpl::MoveTo(int x_
, int y_
) {
272 void SurfaceImpl::LineTo(int x_
, int y_
) {
273 hdc
->DrawLine(x
,y
, x_
,y_
);
278 void SurfaceImpl::Polygon(Point
*pts
, int npts
, ColourDesired fore
, ColourDesired back
) {
281 wxPoint
*p
= new wxPoint
[npts
];
283 for (int i
=0; i
<npts
; i
++) {
287 hdc
->DrawPolygon(npts
, p
);
291 void SurfaceImpl::RectangleDraw(PRectangle rc
, ColourDesired fore
, ColourDesired back
) {
294 hdc
->DrawRectangle(wxRectFromPRectangle(rc
));
297 void SurfaceImpl::FillRectangle(PRectangle rc
, ColourDesired back
) {
299 hdc
->SetPen(*wxTRANSPARENT_PEN
);
300 hdc
->DrawRectangle(wxRectFromPRectangle(rc
));
303 void SurfaceImpl::FillRectangle(PRectangle rc
, Surface
&surfacePattern
) {
305 if (((SurfaceImpl
&)surfacePattern
).bitmap
)
306 br
= wxBrush(*((SurfaceImpl
&)surfacePattern
).bitmap
);
307 else // Something is wrong so display in red
308 br
= wxBrush(*wxRED
);
309 hdc
->SetPen(*wxTRANSPARENT_PEN
);
311 hdc
->DrawRectangle(wxRectFromPRectangle(rc
));
314 void SurfaceImpl::RoundedRectangle(PRectangle rc
, ColourDesired fore
, ColourDesired back
) {
317 hdc
->DrawRoundedRectangle(wxRectFromPRectangle(rc
), 4);
320 #if defined(__WXMSW__) || defined(__WXMAC__)
321 #define wxPy_premultiply(p, a) ((p) * (a) / 0xff)
323 #define wxPy_premultiply(p, a) (p)
326 void SurfaceImpl::AlphaRectangle(PRectangle rc
, int cornerSize
,
327 ColourDesired fill
, int alphaFill
,
328 ColourDesired outline
, int alphaOutline
,
330 #if wxUSE_GRAPHICS_CONTEXT
331 wxGCDC
dc(*(wxMemoryDC
*)hdc
);
332 wxColour
penColour(wxColourFromCDandAlpha(outline
, alphaOutline
));
333 wxColour
brushColour(wxColourFromCDandAlpha(fill
, alphaFill
));
334 dc
.SetPen(wxPen(penColour
));
335 dc
.SetBrush(wxBrush(brushColour
));
336 dc
.DrawRoundedRectangle(wxRectFromPRectangle(rc
), cornerSize
);
340 #ifdef wxHAS_RAW_BITMAP
342 // TODO: do something with cornerSize
343 wxUnusedVar(cornerSize
);
346 wxRect r
= wxRectFromPRectangle(rc
);
347 wxBitmap
bmp(r
.width
, r
.height
, 32);
349 // This block is needed to ensure that the changes done to the bitmap via
350 // pixel data object are committed before the bitmap is drawn.
352 wxAlphaPixelData
pixData(bmp
);
354 // Set the fill pixels
355 ColourDesired
cdf(fill
.AsLong());
356 int red
= cdf
.GetRed();
357 int green
= cdf
.GetGreen();
358 int blue
= cdf
.GetBlue();
360 wxAlphaPixelData::Iterator
p(pixData
);
361 for (y
=0; y
<r
.height
; y
++) {
362 p
.MoveTo(pixData
, 0, y
);
363 for (x
=0; x
<r
.width
; x
++) {
364 p
.Red() = wxPy_premultiply(red
, alphaFill
);
365 p
.Green() = wxPy_premultiply(green
, alphaFill
);
366 p
.Blue() = wxPy_premultiply(blue
, alphaFill
);
367 p
.Alpha() = alphaFill
;
372 // Set the outline pixels
373 ColourDesired
cdo(outline
.AsLong());
375 green
= cdo
.GetGreen();
376 blue
= cdo
.GetBlue();
377 for (x
=0; x
<r
.width
; x
++) {
378 p
.MoveTo(pixData
, x
, 0);
379 p
.Red() = wxPy_premultiply(red
, alphaOutline
);
380 p
.Green() = wxPy_premultiply(green
, alphaOutline
);
381 p
.Blue() = wxPy_premultiply(blue
, alphaOutline
);
382 p
.Alpha() = alphaOutline
;
383 p
.MoveTo(pixData
, x
, r
.height
-1);
384 p
.Red() = wxPy_premultiply(red
, alphaOutline
);
385 p
.Green() = wxPy_premultiply(green
, alphaOutline
);
386 p
.Blue() = wxPy_premultiply(blue
, alphaOutline
);
387 p
.Alpha() = alphaOutline
;
390 for (y
=0; y
<r
.height
; y
++) {
391 p
.MoveTo(pixData
, 0, y
);
392 p
.Red() = wxPy_premultiply(red
, alphaOutline
);
393 p
.Green() = wxPy_premultiply(green
, alphaOutline
);
394 p
.Blue() = wxPy_premultiply(blue
, alphaOutline
);
395 p
.Alpha() = alphaOutline
;
396 p
.MoveTo(pixData
, r
.width
-1, y
);
397 p
.Red() = wxPy_premultiply(red
, alphaOutline
);
398 p
.Green() = wxPy_premultiply(green
, alphaOutline
);
399 p
.Blue() = wxPy_premultiply(blue
, alphaOutline
);
400 p
.Alpha() = alphaOutline
;
405 hdc
->DrawBitmap(bmp
, r
.x
, r
.y
, true);
408 wxUnusedVar(cornerSize
);
409 wxUnusedVar(alphaFill
);
410 wxUnusedVar(alphaOutline
);
411 RectangleDraw(rc
, outline
, fill
);
416 #ifdef wxHAS_RAW_BITMAP
417 wxBitmap
BitmapFromRGBAImage(int width
, int height
, const unsigned char *pixelsImage
)
420 wxBitmap
bmp(width
, height
, 32);
421 wxAlphaPixelData
pixData(bmp
);
423 wxAlphaPixelData::Iterator
p(pixData
);
424 for (y
=0; y
<height
; y
++) {
425 p
.MoveTo(pixData
, 0, y
);
426 for (x
=0; x
<width
; x
++) {
427 unsigned char red
= *pixelsImage
++;
428 unsigned char green
= *pixelsImage
++;
429 unsigned char blue
= *pixelsImage
++;
430 unsigned char alpha
= *pixelsImage
++;
432 p
.Red() = wxPy_premultiply(red
, alpha
);
433 p
.Green() = wxPy_premultiply(green
, alpha
);
434 p
.Blue() = wxPy_premultiply(blue
, alpha
);
444 void SurfaceImpl::DrawRGBAImage(PRectangle rc
, int width
, int height
,
445 const unsigned char *pixelsImage
)
447 #ifdef wxHAS_RAW_BITMAP
448 wxRect r
= wxRectFromPRectangle(rc
);
449 wxBitmap bmp
= BitmapFromRGBAImage(width
, height
, pixelsImage
);
450 hdc
->DrawBitmap(bmp
, r
.x
, r
.y
, true);
455 void SurfaceImpl::Ellipse(PRectangle rc
, ColourDesired fore
, ColourDesired back
) {
458 hdc
->DrawEllipse(wxRectFromPRectangle(rc
));
461 void SurfaceImpl::Copy(PRectangle rc
, Point from
, Surface
&surfaceSource
) {
462 wxRect r
= wxRectFromPRectangle(rc
);
463 hdc
->Blit(r
.x
, r
.y
, r
.width
, r
.height
,
464 ((SurfaceImpl
&)surfaceSource
).hdc
,
465 from
.x
, from
.y
, wxCOPY
);
468 void SurfaceImpl::DrawTextNoClip(PRectangle rc
, Font
&font
, XYPOSITION ybase
,
469 const char *s
, int len
,
470 ColourDesired fore
, ColourDesired back
) {
472 hdc
->SetTextForeground(wxColourFromCD(fore
));
473 hdc
->SetTextBackground(wxColourFromCD(back
));
474 FillRectangle(rc
, back
);
476 // ybase is where the baseline should be, but wxWin uses the upper left
477 // corner, so I need to calculate the real position for the text...
478 hdc
->DrawText(stc2wx(s
, len
), rc
.left
, ybase
- font
.ascent
);
481 void SurfaceImpl::DrawTextClipped(PRectangle rc
, Font
&font
, XYPOSITION ybase
,
482 const char *s
, int len
,
483 ColourDesired fore
, ColourDesired back
) {
485 hdc
->SetTextForeground(wxColourFromCD(fore
));
486 hdc
->SetTextBackground(wxColourFromCD(back
));
487 FillRectangle(rc
, back
);
488 hdc
->SetClippingRegion(wxRectFromPRectangle(rc
));
490 // see comments above
491 hdc
->DrawText(stc2wx(s
, len
), rc
.left
, ybase
- font
.ascent
);
492 hdc
->DestroyClippingRegion();
496 void SurfaceImpl::DrawTextTransparent(PRectangle rc
, Font
&font
, XYPOSITION ybase
,
497 const char *s
, int len
,
498 ColourDesired fore
) {
501 hdc
->SetTextForeground(wxColourFromCD(fore
));
502 hdc
->SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT
);
504 // ybase is where the baseline should be, but wxWin uses the upper left
505 // corner, so I need to calculate the real position for the text...
506 hdc
->DrawText(stc2wx(s
, len
), rc
.left
, ybase
- font
.ascent
);
508 hdc
->SetBackgroundMode(wxBRUSHSTYLE_SOLID
);
512 void SurfaceImpl::MeasureWidths(Font
&font
, const char *s
, int len
, XYPOSITION
*positions
) {
514 wxString str
= stc2wx(s
, len
);
519 hdc
->GetPartialTextExtents(str
, tpos
);
522 // Map the widths for UCS-2 characters back to the UTF-8 input string
523 // NOTE: I don't think this is right for when sizeof(wxChar) > 2, ie wxGTK2
524 // so figure it out and fix it!
527 while ((int)i
< len
) {
528 unsigned char uch
= (unsigned char)s
[i
];
529 positions
[i
++] = tpos
[ui
];
531 if (uch
< (0x80 + 0x40 + 0x20)) {
532 positions
[i
++] = tpos
[ui
];
534 positions
[i
++] = tpos
[ui
];
535 positions
[i
++] = tpos
[ui
];
542 // If not unicode then just use the widths we have
543 #if wxUSE_STD_CONTAINERS
544 std::copy(tpos
.begin(), tpos
.end(), positions
);
546 memcpy(positions
, tpos
.begin(), len
* sizeof(int));
552 XYPOSITION
SurfaceImpl::WidthText(Font
&font
, const char *s
, int len
) {
557 hdc
->GetTextExtent(stc2wx(s
, len
), &w
, &h
);
562 XYPOSITION
SurfaceImpl::WidthChar(Font
&font
, char ch
) {
566 char s
[2] = { ch
, 0 };
568 hdc
->GetTextExtent(stc2wx(s
, 1), &w
, &h
);
572 #define EXTENT_TEST wxT(" `~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
574 XYPOSITION
SurfaceImpl::Ascent(Font
&font
) {
577 hdc
->GetTextExtent(EXTENT_TEST
, &w
, &h
, &d
, &e
);
582 XYPOSITION
SurfaceImpl::Descent(Font
&font
) {
585 hdc
->GetTextExtent(EXTENT_TEST
, &w
, &h
, &d
, &e
);
589 XYPOSITION
SurfaceImpl::InternalLeading(Font
&WXUNUSED(font
)) {
593 XYPOSITION
SurfaceImpl::ExternalLeading(Font
&font
) {
596 hdc
->GetTextExtent(EXTENT_TEST
, &w
, &h
, &d
, &e
);
600 XYPOSITION
SurfaceImpl::Height(Font
&font
) {
602 return hdc
->GetCharHeight() + 1;
605 XYPOSITION
SurfaceImpl::AverageCharWidth(Font
&font
) {
607 return hdc
->GetCharWidth();
610 void SurfaceImpl::SetClip(PRectangle rc
) {
611 hdc
->SetClippingRegion(wxRectFromPRectangle(rc
));
614 void SurfaceImpl::FlushCachedState() {
617 void SurfaceImpl::SetUnicodeMode(bool unicodeMode_
) {
618 unicodeMode
=unicodeMode_
;
621 void SurfaceImpl::SetDBCSMode(int WXUNUSED(codePage
)) {
622 // dbcsMode = codePage == SC_CP_DBCS;
626 Surface
*Surface::Allocate(int WXUNUSED(technology
)) {
627 return new SurfaceImpl
;
631 //----------------------------------------------------------------------
634 inline wxWindow
* GETWIN(WindowID id
) { return (wxWindow
*)id
; }
639 void Window::Destroy() {
642 GETWIN(wid
)->Destroy();
647 bool Window::HasFocus() {
648 return wxWindow::FindFocus() == GETWIN(wid
);
651 PRectangle
Window::GetPosition() {
652 if (! wid
) return PRectangle();
653 wxRect
rc(GETWIN(wid
)->GetPosition(), GETWIN(wid
)->GetSize());
654 return PRectangleFromwxRect(rc
);
657 void Window::SetPosition(PRectangle rc
) {
658 wxRect r
= wxRectFromPRectangle(rc
);
659 GETWIN(wid
)->SetSize(r
);
662 void Window::SetPositionRelative(PRectangle rc
, Window
) {
663 SetPosition(rc
); // ????
666 PRectangle
Window::GetClientPosition() {
667 if (! wid
) return PRectangle();
668 wxSize sz
= GETWIN(wid
)->GetClientSize();
669 return PRectangle(0, 0, sz
.x
, sz
.y
);
672 void Window::Show(bool show
) {
673 GETWIN(wid
)->Show(show
);
676 void Window::InvalidateAll() {
677 GETWIN(wid
)->Refresh(false);
680 void Window::InvalidateRectangle(PRectangle rc
) {
681 wxRect r
= wxRectFromPRectangle(rc
);
682 GETWIN(wid
)->Refresh(false, &r
);
685 void Window::SetFont(Font
&font
) {
686 GETWIN(wid
)->SetFont(*((wxFont
*)font
.GetID()));
689 void Window::SetCursor(Cursor curs
) {
690 wxStockCursor cursorId
;
694 cursorId
= wxCURSOR_IBEAM
;
697 cursorId
= wxCURSOR_ARROW
;
700 cursorId
= wxCURSOR_ARROW
; // ** no up arrow... wxCURSOR_UPARROW;
703 cursorId
= wxCURSOR_WAIT
;
706 cursorId
= wxCURSOR_SIZEWE
;
709 cursorId
= wxCURSOR_SIZENS
;
711 case cursorReverseArrow
:
712 cursorId
= wxCURSOR_RIGHT_ARROW
;
715 cursorId
= wxCURSOR_HAND
;
718 cursorId
= wxCURSOR_ARROW
;
722 wxCursor wc
= wxCursor(cursorId
);
723 if(curs
!= cursorLast
)
725 GETWIN(wid
)->SetCursor(wc
);
731 void Window::SetTitle(const char *s
) {
732 GETWIN(wid
)->SetLabel(stc2wx(s
));
736 // Returns rectangle of monitor pt is on
737 PRectangle
Window::GetMonitorRect(Point pt
) {
739 if (! wid
) return PRectangle();
741 // Get the display the point is found on
742 int n
= wxDisplay::GetFromPoint(wxPoint(pt
.x
, pt
.y
));
743 wxDisplay
dpy(n
== wxNOT_FOUND
? 0 : n
);
744 rect
= dpy
.GetGeometry();
748 return PRectangleFromwxRect(rect
);
751 //----------------------------------------------------------------------
752 // Helper classes for ListBox
755 // This is a simple subclass of wxListView that just resets focus to the
756 // parent when it gets it.
757 class wxSTCListBox
: public wxListView
{
759 wxSTCListBox(wxWindow
* parent
, wxWindowID id
,
760 const wxPoint
& pos
, const wxSize
& size
,
765 Hide(); // don't flicker as we move it around...
767 Create(parent
, id
, pos
, size
, style
);
771 void OnFocus(wxFocusEvent
& event
) {
772 GetParent()->SetFocus();
776 void OnKillFocus(wxFocusEvent
& WXUNUSED(event
)) {
777 // Do nothing. Prevents base class from resetting the colors...
781 // For some reason I don't understand yet the focus doesn't really leave
782 // the listbox like it should, so if we get any events feed them back to
784 void OnKeyDown(wxKeyEvent
& event
) {
785 GetGrandParent()->GetEventHandler()->ProcessEvent(event
);
787 void OnChar(wxKeyEvent
& event
) {
788 GetGrandParent()->GetEventHandler()->ProcessEvent(event
);
791 // And we need to force the focus back when being destroyed
793 GetGrandParent()->SetFocus();
798 DECLARE_EVENT_TABLE()
801 BEGIN_EVENT_TABLE(wxSTCListBox
, wxListView
)
802 EVT_SET_FOCUS( wxSTCListBox::OnFocus
)
803 EVT_KILL_FOCUS(wxSTCListBox::OnKillFocus
)
805 EVT_KEY_DOWN( wxSTCListBox::OnKeyDown
)
806 EVT_CHAR( wxSTCListBox::OnChar
)
812 #if wxUSE_POPUPWIN //-----------------------------------
813 #include "wx/popupwin.h"
815 // A popup window to place the wxSTCListBox upon
816 class wxSTCListBoxWin
: public wxPopupWindow
820 CallBackAction doubleClickAction
;
821 void* doubleClickActionData
;
823 wxSTCListBoxWin(wxWindow
* parent
, wxWindowID id
, Point
WXUNUSED(location
)) :
824 wxPopupWindow(parent
, wxBORDER_SIMPLE
)
827 lv
= new wxSTCListBox(parent
, id
, wxPoint(-50,-50), wxDefaultSize
,
828 wxLC_REPORT
| wxLC_SINGLE_SEL
| wxLC_NO_HEADER
| wxBORDER_NONE
);
829 lv
->SetCursor(wxCursor(wxCURSOR_ARROW
));
830 lv
->InsertColumn(0, wxEmptyString
);
831 lv
->InsertColumn(1, wxEmptyString
);
833 // NOTE: We need to fool the wxListView into thinking that it has the
834 // focus so it will use the normal selection colour and will look
835 // "right" to the user. But since the wxPopupWindow or its children
836 // can't receive focus then we have to pull a fast one and temporarily
837 // parent the listctrl on the STC window and then call SetFocus and
838 // then reparent it back to the popup.
844 #if defined(__WXOSX_COCOA__) || defined(__WXGTK__)
845 // This color will end up being our border
846 SetBackgroundColour(wxColour(0xC0, 0xC0, 0xC0));
851 // Set position in client coords
852 virtual void DoSetSize(int x
, int y
,
853 int width
, int height
,
854 int sizeFlags
= wxSIZE_AUTO
) {
855 if (x
!= wxDefaultCoord
) {
856 GetParent()->ClientToScreen(&x
, NULL
);
858 if (y
!= wxDefaultCoord
) {
859 GetParent()->ClientToScreen(NULL
, &y
);
861 wxPopupWindow::DoSetSize(x
, y
, width
, height
, sizeFlags
);
864 // return position as if it were in client coords
865 virtual void DoGetPosition( int *x
, int *y
) const {
867 wxPopupWindow::DoGetPosition(&sx
, &sy
);
868 GetParent()->ScreenToClient(&sx
, &sy
);
875 if ( !wxPendingDelete
.Member(this) )
876 wxPendingDelete
.Append(this);
882 wxImageList
* il
= lv
->GetImageList(wxIMAGE_LIST_SMALL
);
885 il
->GetSize(0, w
, h
);
892 void SetDoubleClickAction(CallBackAction action
, void *data
) {
893 doubleClickAction
= action
;
894 doubleClickActionData
= data
;
898 void OnFocus(wxFocusEvent
& event
) {
899 GetParent()->SetFocus();
903 void OnSize(wxSizeEvent
& event
) {
904 // resize the child to fill the popup
905 wxSize sz
= GetClientSize();
910 #if defined(__WXOSX_COCOA__) || defined(__WXGTK__)
911 // make room for the parent's bg color to show, to act as a border
916 lv
->SetSize(x
, y
, w
, h
);
917 // reset the column widths
918 lv
->SetColumnWidth(0, IconWidth()+4);
919 lv
->SetColumnWidth(1, w
- 2 - lv
->GetColumnWidth(0) -
920 wxSystemSettings::GetMetric(wxSYS_VSCROLL_X
));
924 void OnActivate(wxListEvent
& WXUNUSED(event
)) {
925 doubleClickAction(doubleClickActionData
);
928 wxListView
* GetLB() { return lv
; }
931 DECLARE_EVENT_TABLE()
935 BEGIN_EVENT_TABLE(wxSTCListBoxWin
, wxPopupWindow
)
936 EVT_SET_FOCUS ( wxSTCListBoxWin::OnFocus
)
937 EVT_SIZE ( wxSTCListBoxWin::OnSize
)
938 EVT_LIST_ITEM_ACTIVATED(wxID_ANY
, wxSTCListBoxWin::OnActivate
)
943 #else // !wxUSE_POPUPWIN -----------------------------------
944 #include "wx/frame.h"
946 // A normal window to place the wxSTCListBox upon, but make it behave as much
947 // like a wxPopupWindow as possible
948 class wxSTCListBoxWin
: public wxFrame
{
951 CallBackAction doubleClickAction
;
952 void* doubleClickActionData
;
954 wxSTCListBoxWin(wxWindow
* parent
, wxWindowID id
, Point location
) :
955 wxFrame(parent
, id
, wxEmptyString
, wxPoint(location
.x
, location
.y
), wxSize(0,0),
957 | wxFRAME_FLOAT_ON_PARENT
967 lv
= new wxSTCListBox(this, id
, wxDefaultPosition
, wxDefaultSize
,
968 wxLC_REPORT
| wxLC_SINGLE_SEL
| wxLC_NO_HEADER
| wxNO_BORDER
);
969 lv
->SetCursor(wxCursor(wxCURSOR_ARROW
));
970 lv
->InsertColumn(0, wxEmptyString
);
971 lv
->InsertColumn(1, wxEmptyString
);
973 // Eventhough we immediately reset the focus to the parent, this helps
974 // things to look right...
981 // On OSX and (possibly others) there can still be pending
982 // messages/events for the list control when Scintilla wants to
983 // close it, so do a pending delete of it instead of destroying
988 // The bottom edge of this window is not getting properly
989 // refreshed upon deletion, so help it out...
990 wxWindow
* p
= GetParent();
991 wxRect
r(GetPosition(), GetSize());
992 r
.SetHeight(r
.GetHeight()+1);
993 p
->Refresh(false, &r
);
995 if ( !wxPendingDelete
.Member(this) )
996 wxPendingDelete
.Append(this);
1003 wxImageList
* il
= lv
->GetImageList(wxIMAGE_LIST_SMALL
);
1006 il
->GetSize(0, w
, h
);
1013 void SetDoubleClickAction(CallBackAction action
, void *data
)
1015 doubleClickAction
= action
;
1016 doubleClickActionData
= data
;
1020 void OnFocus(wxFocusEvent
& event
)
1023 GetParent()->SetFocus();
1027 void OnSize(wxSizeEvent
& event
)
1030 wxSize sz
= GetClientSize();
1032 // reset the column widths
1033 lv
->SetColumnWidth(0, IconWidth()+4);
1034 lv
->SetColumnWidth(1, sz
.x
- 2 - lv
->GetColumnWidth(0) -
1035 wxSystemSettings::GetMetric(wxSYS_VSCROLL_X
));
1039 void ActivateParent()
1041 // Although we're a frame, we always want the parent to be active, so
1042 // raise it whenever we get shown, focused, etc.
1043 wxTopLevelWindow
*frame
= wxDynamicCast(
1044 wxGetTopLevelParent(GetParent()), wxTopLevelWindow
);
1050 virtual void DoSetSize(int x
, int y
,
1051 int width
, int height
,
1052 int sizeFlags
= wxSIZE_AUTO
)
1054 // convert coords to screen coords since we're a top-level window
1055 if (x
!= wxDefaultCoord
) {
1056 GetParent()->ClientToScreen(&x
, NULL
);
1058 if (y
!= wxDefaultCoord
) {
1059 GetParent()->ClientToScreen(NULL
, &y
);
1061 wxFrame::DoSetSize(x
, y
, width
, height
, sizeFlags
);
1064 virtual bool Show(bool show
= true)
1066 bool rv
= wxFrame::Show(show
);
1070 GetParent()->Refresh(false);
1075 void OnActivate(wxListEvent
& WXUNUSED(event
))
1077 doubleClickAction(doubleClickActionData
);
1080 wxListView
* GetLB() { return lv
; }
1083 DECLARE_EVENT_TABLE()
1087 BEGIN_EVENT_TABLE(wxSTCListBoxWin
, wxWindow
)
1088 EVT_SET_FOCUS ( wxSTCListBoxWin::OnFocus
)
1089 EVT_SIZE ( wxSTCListBoxWin::OnSize
)
1090 EVT_LIST_ITEM_ACTIVATED(wxID_ANY
, wxSTCListBoxWin::OnActivate
)
1093 #endif // wxUSE_POPUPWIN -----------------------------------
1096 inline wxSTCListBoxWin
* GETLBW(WindowID win
) {
1097 return ((wxSTCListBoxWin
*)win
);
1100 inline wxListView
* GETLB(WindowID win
) {
1101 return GETLBW(win
)->GetLB();
1104 //----------------------------------------------------------------------
1106 class ListBoxImpl
: public ListBox
{
1110 int desiredVisibleRows
;
1113 Point location
; // Caret location at which the list is opened
1114 wxImageList
* imgList
;
1115 wxArrayInt
* imgTypeMap
;
1120 static ListBox
*Allocate();
1122 virtual void SetFont(Font
&font
);
1123 virtual void Create(Window
&parent
, int ctrlID
, Point location_
, int lineHeight_
, bool unicodeMode_
, int technology_
);
1124 virtual void SetAverageCharWidth(int width
);
1125 virtual void SetVisibleRows(int rows
);
1126 virtual int GetVisibleRows() const;
1127 virtual PRectangle
GetDesiredRect();
1128 virtual int CaretFromEdge();
1129 virtual void Clear();
1130 virtual void Append(char *s
, int type
= -1);
1131 void Append(const wxString
& text
, int type
);
1132 virtual int Length();
1133 virtual void Select(int n
);
1134 virtual int GetSelection();
1135 virtual int Find(const char *prefix
);
1136 virtual void GetValue(int n
, char *value
, int len
);
1137 virtual void RegisterImage(int type
, const char *xpm_data
);
1138 void RegisterImageHelper(int type
, wxBitmap
& bmp
);
1139 virtual void RegisterRGBAImage(int type
, int width
, int height
, const unsigned char *pixelsImage
);
1140 virtual void ClearRegisteredImages();
1141 virtual void SetDoubleClickAction(CallBackAction
, void *);
1142 virtual void SetList(const char* list
, char separator
, char typesep
);
1146 ListBoxImpl::ListBoxImpl()
1147 : lineHeight(10), unicodeMode(false),
1148 desiredVisibleRows(5), aveCharWidth(8), maxStrWidth(0),
1149 imgList(NULL
), imgTypeMap(NULL
)
1153 ListBoxImpl::~ListBoxImpl() {
1155 wxDELETE(imgTypeMap
);
1159 void ListBoxImpl::SetFont(Font
&font
) {
1160 GETLB(wid
)->SetFont(*((wxFont
*)font
.GetID()));
1164 void ListBoxImpl::Create(Window
&parent
, int ctrlID
, Point location_
, int lineHeight_
, bool unicodeMode_
, int WXUNUSED(technology_
)) {
1165 location
= location_
;
1166 lineHeight
= lineHeight_
;
1167 unicodeMode
= unicodeMode_
;
1169 wid
= new wxSTCListBoxWin(GETWIN(parent
.GetID()), ctrlID
, location
);
1170 if (imgList
!= NULL
)
1171 GETLB(wid
)->SetImageList(imgList
, wxIMAGE_LIST_SMALL
);
1175 void ListBoxImpl::SetAverageCharWidth(int width
) {
1176 aveCharWidth
= width
;
1180 void ListBoxImpl::SetVisibleRows(int rows
) {
1181 desiredVisibleRows
= rows
;
1185 int ListBoxImpl::GetVisibleRows() const {
1186 return desiredVisibleRows
;
1189 PRectangle
ListBoxImpl::GetDesiredRect() {
1190 // wxListCtrl doesn't have a DoGetBestSize, so instead we kept track of
1191 // the max size in Append and calculate it here...
1192 int maxw
= maxStrWidth
* aveCharWidth
;
1195 // give it a default if there are no lines, and/or add a bit more
1196 if (maxw
== 0) maxw
= 100;
1197 maxw
+= aveCharWidth
* 3 +
1198 GETLBW(wid
)->IconWidth() + wxSystemSettings::GetMetric(wxSYS_VSCROLL_X
);
1202 // estimate a desired height
1203 int count
= GETLB(wid
)->GetItemCount();
1206 GETLB(wid
)->GetItemRect(0, rect
);
1207 maxh
= count
* rect
.GetHeight();
1208 if (maxh
> 140) // TODO: Use desiredVisibleRows??
1211 // Try to make the size an exact multiple of some number of lines
1212 int lines
= maxh
/ rect
.GetHeight();
1213 maxh
= (lines
+ 1) * rect
.GetHeight() + 2;
1227 int ListBoxImpl::CaretFromEdge() {
1228 return 4 + GETLBW(wid
)->IconWidth();
1232 void ListBoxImpl::Clear() {
1233 GETLB(wid
)->DeleteAllItems();
1237 void ListBoxImpl::Append(char *s
, int type
) {
1238 Append(stc2wx(s
), type
);
1241 void ListBoxImpl::Append(const wxString
& text
, int type
) {
1242 long count
= GETLB(wid
)->GetItemCount();
1243 long itemID
= GETLB(wid
)->InsertItem(count
, wxEmptyString
);
1245 GETLB(wid
)->SetItem(itemID
, 1, text
);
1246 maxStrWidth
= wxMax(maxStrWidth
, text
.length());
1248 wxCHECK_RET(imgTypeMap
, wxT("Unexpected NULL imgTypeMap"));
1249 idx
= imgTypeMap
->Item(type
);
1251 GETLB(wid
)->SetItemImage(itemID
, idx
, idx
);
1254 void ListBoxImpl::SetList(const char* list
, char separator
, char typesep
) {
1255 GETLB(wid
)->Freeze();
1257 wxStringTokenizer
tkzr(stc2wx(list
), (wxChar
)separator
);
1258 while ( tkzr
.HasMoreTokens() ) {
1259 wxString token
= tkzr
.GetNextToken();
1261 int pos
= token
.Find(typesep
);
1263 token
.Mid(pos
+1).ToLong(&type
);
1264 token
.Truncate(pos
);
1266 Append(token
, (int)type
);
1272 int ListBoxImpl::Length() {
1273 return GETLB(wid
)->GetItemCount();
1277 void ListBoxImpl::Select(int n
) {
1283 GETLB(wid
)->EnsureVisible(n
);
1284 GETLB(wid
)->Select(n
, select
);
1288 int ListBoxImpl::GetSelection() {
1289 return GETLB(wid
)->GetFirstSelected();
1293 int ListBoxImpl::Find(const char *WXUNUSED(prefix
)) {
1299 void ListBoxImpl::GetValue(int n
, char *value
, int len
) {
1303 item
.SetMask(wxLIST_MASK_TEXT
);
1304 GETLB(wid
)->GetItem(item
);
1305 strncpy(value
, wx2stc(item
.GetText()), len
);
1306 value
[len
-1] = '\0';
1309 void ListBoxImpl::RegisterImageHelper(int type
, wxBitmap
& bmp
)
1312 // assumes all images are the same size
1313 imgList
= new wxImageList(bmp
.GetWidth(), bmp
.GetHeight(), true);
1314 imgTypeMap
= new wxArrayInt
;
1317 int idx
= imgList
->Add(bmp
);
1319 // do we need to extend the mapping array?
1320 wxArrayInt
& itm
= *imgTypeMap
;
1321 if ( itm
.GetCount() < (size_t)type
+1)
1322 itm
.Add(-1, type
- itm
.GetCount() + 1);
1324 // Add an item that maps type to the image index
1328 void ListBoxImpl::RegisterImage(int type
, const char *xpm_data
) {
1329 wxMemoryInputStream
stream(xpm_data
, strlen(xpm_data
)+1);
1330 wxImage
img(stream
, wxBITMAP_TYPE_XPM
);
1332 RegisterImageHelper(type
, bmp
);
1336 void ListBoxImpl::RegisterRGBAImage(int type
, int width
, int height
,
1337 const unsigned char *pixelsImage
)
1339 #ifdef wxHAS_RAW_BITMAP
1340 wxBitmap bmp
= BitmapFromRGBAImage(width
, height
, pixelsImage
);
1341 RegisterImageHelper(type
, bmp
);
1346 void ListBoxImpl::ClearRegisteredImages() {
1348 wxDELETE(imgTypeMap
);
1350 GETLB(wid
)->SetImageList(NULL
, wxIMAGE_LIST_SMALL
);
1354 void ListBoxImpl::SetDoubleClickAction(CallBackAction action
, void *data
) {
1355 GETLBW(wid
)->SetDoubleClickAction(action
, data
);
1359 ListBox::ListBox() {
1362 ListBox::~ListBox() {
1365 ListBox
*ListBox::Allocate() {
1366 return new ListBoxImpl();
1369 //----------------------------------------------------------------------
1371 Menu::Menu() : mid(0) {
1374 void Menu::CreatePopUp() {
1379 void Menu::Destroy() {
1381 delete (wxMenu
*)mid
;
1385 void Menu::Show(Point pt
, Window
&w
) {
1386 GETWIN(w
.GetID())->PopupMenu((wxMenu
*)mid
, pt
.x
- 4, pt
.y
);
1390 //----------------------------------------------------------------------
1392 DynamicLibrary
*DynamicLibrary::Load(const char *WXUNUSED(modulePath
)) {
1393 wxFAIL_MSG(wxT("Dynamic lexer loading not implemented yet"));
1397 //----------------------------------------------------------------------
1399 ColourDesired
Platform::Chrome() {
1401 c
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
1402 return ColourDesired(c
.Red(), c
.Green(), c
.Blue());
1405 ColourDesired
Platform::ChromeHighlight() {
1407 c
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT
);
1408 return ColourDesired(c
.Red(), c
.Green(), c
.Blue());
1411 const char *Platform::DefaultFont() {
1412 static char buf
[128];
1413 strcpy(buf
, wxNORMAL_FONT
->GetFaceName().mbc_str());
1417 int Platform::DefaultFontSize() {
1418 return wxNORMAL_FONT
->GetPointSize();
1421 unsigned int Platform::DoubleClickTime() {
1422 return 500; // **** ::GetDoubleClickTime();
1425 bool Platform::MouseButtonBounce() {
1429 bool Platform::IsKeyDown(int WXUNUSED(key
)) {
1430 return false; // I don't think we'll need this.
1433 long Platform::SendScintilla(WindowID w
,
1435 unsigned long wParam
,
1438 wxStyledTextCtrl
* stc
= (wxStyledTextCtrl
*)w
;
1439 return stc
->SendMsg(msg
, wParam
, lParam
);
1442 long Platform::SendScintillaPointer(WindowID w
,
1444 unsigned long wParam
,
1447 wxStyledTextCtrl
* stc
= (wxStyledTextCtrl
*)w
;
1448 return stc
->SendMsg(msg
, wParam
, (wxIntPtr
)lParam
);
1452 // These are utility functions not really tied to a platform
1454 int Platform::Minimum(int a
, int b
) {
1461 int Platform::Maximum(int a
, int b
) {
1470 void Platform::DebugDisplay(const char *s
) {
1472 wxLogDebug(stc2wx(s
));
1478 void Platform::DebugPrintf(const char *format
, ...) {
1482 va_start(pArguments
, format
);
1483 vsprintf(buffer
,format
,pArguments
);
1485 Platform::DebugDisplay(buffer
);
1487 wxUnusedVar(format
);
1492 static bool assertionPopUps
= true;
1494 bool Platform::ShowAssertionPopUps(bool assertionPopUps_
) {
1495 bool ret
= assertionPopUps
;
1496 assertionPopUps
= assertionPopUps_
;
1500 void Platform::Assert(const char *c
, const char *file
, int line
) {
1503 sprintf(buffer
, "Assertion [%s] failed at %s %d", c
, file
, line
);
1504 if (assertionPopUps
) {
1506 wxMessageBox(stc2wx(buffer
),
1507 wxT("Assertion failure"),
1508 wxICON_HAND
| wxOK
);
1510 strcat(buffer
, "\r\n");
1511 Platform::DebugDisplay(buffer
);
1522 int Platform::Clamp(int val
, int minVal
, int maxVal
) {
1531 bool Platform::IsDBCSLeadByte(int WXUNUSED(codePage
), char WXUNUSED(ch
)) {
1535 int Platform::DBCSCharLength(int WXUNUSED(codePage
), const char *WXUNUSED(s
)) {
1539 int Platform::DBCSCharMaxLength() {
1544 //----------------------------------------------------------------------
1546 ElapsedTime::ElapsedTime() {
1547 wxLongLong localTime
= wxGetLocalTimeMillis();
1548 littleBit
= localTime
.GetLo();
1549 bigBit
= localTime
.GetHi();
1552 double ElapsedTime::Duration(bool reset
) {
1553 wxLongLong
prevTime(bigBit
, littleBit
);
1554 wxLongLong localTime
= wxGetLocalTimeMillis();
1556 littleBit
= localTime
.GetLo();
1557 bigBit
= localTime
.GetHi();
1559 wxLongLong duration
= localTime
- prevTime
;
1560 double result
= duration
.ToDouble();
1566 //----------------------------------------------------------------------
1570 #include "UniConversion.h"
1572 // Convert using Scintilla's functions instead of wx's, Scintilla's are more
1573 // forgiving and won't assert...
1575 wxString
stc2wx(const char* str
, size_t len
)
1578 return wxEmptyString
;
1580 size_t wclen
= UTF16Length(str
, len
);
1581 wxWCharBuffer
buffer(wclen
+1);
1583 size_t actualLen
= UTF16FromUTF8(str
, len
, buffer
.data(), wclen
+1);
1584 return wxString(buffer
.data(), actualLen
);
1589 wxString
stc2wx(const char* str
)
1591 return stc2wx(str
, strlen(str
));
1595 wxWX2MBbuf
wx2stc(const wxString
& str
)
1597 const wchar_t* wcstr
= str
.c_str();
1598 size_t wclen
= str
.length();
1599 size_t len
= UTF8Length(wcstr
, wclen
);
1601 wxCharBuffer
buffer(len
+1);
1602 UTF8FromUTF16(wcstr
, wclen
, buffer
.data(), len
);
1604 // TODO check NULL termination!!