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
wxColourFromCA(const ColourAllocated
& ca
) {
64 ColourDesired
cd(ca
.AsLong());
65 return wxColour((unsigned char)cd
.GetRed(),
66 (unsigned char)cd
.GetGreen(),
67 (unsigned char)cd
.GetBlue());
70 wxColour
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
);
78 //----------------------------------------------------------------------
82 allowRealization
= false;
84 entries
= new ColourPair
[size
];
92 void Palette::Release() {
96 entries
= new ColourPair
[size
];
99 // This method either adds a colour to the list of wanted colours (want==true)
100 // or retrieves the allocated colour back to the ColourPair.
101 // This is one method to make it easier to keep the code for wanting and retrieving in sync.
102 void Palette::WantFind(ColourPair
&cp
, bool want
) {
104 for (int i
=0; i
< used
; i
++) {
105 if (entries
[i
].desired
== cp
.desired
)
110 int sizeNew
= size
* 2;
111 ColourPair
*entriesNew
= new ColourPair
[sizeNew
];
112 for (int j
=0; j
<size
; j
++) {
113 entriesNew
[j
] = entries
[j
];
116 entries
= entriesNew
;
120 entries
[used
].desired
= cp
.desired
;
121 entries
[used
].allocated
.Set(cp
.desired
.AsLong());
124 for (int i
=0; i
< used
; i
++) {
125 if (entries
[i
].desired
== cp
.desired
) {
126 cp
.allocated
= entries
[i
].allocated
;
130 cp
.allocated
.Set(cp
.desired
.AsLong());
134 void Palette::Allocate(Window
&) {
135 if (allowRealization
) {
140 //----------------------------------------------------------------------
150 void Font::Create(const char *faceName
, int characterSet
,
151 int size
, bool bold
, bool italic
,
152 int WXUNUSED(extraFontFlag
)) {
155 // The minus one is done because since Scintilla uses SC_SHARSET_DEFAULT
156 // internally and we need to have wxFONENCODING_DEFAULT == SC_SHARSET_DEFAULT
157 // so we adjust the encoding before passing it to Scintilla. See also
158 // wxStyledTextCtrl::StyleSetCharacterSet
159 wxFontEncoding encoding
= (wxFontEncoding
)(characterSet
-1);
161 wxFontEncodingArray ea
= wxEncodingConverter::GetPlatformEquivalents(encoding
);
165 wxFont
* font
= new wxFont(size
,
167 italic
? wxITALIC
: wxNORMAL
,
168 bold
? wxBOLD
: wxNORMAL
,
176 void Font::Release() {
182 //----------------------------------------------------------------------
184 class SurfaceImpl
: public Surface
{
197 virtual void Init(WindowID wid
);
198 virtual void Init(SurfaceID sid
, WindowID wid
);
199 virtual void InitPixMap(int width
, int height
, Surface
*surface_
, WindowID wid
);
201 virtual void Release();
202 virtual bool Initialised();
203 virtual void PenColour(ColourAllocated fore
);
204 virtual int LogPixelsY();
205 virtual int DeviceHeightFont(int points
);
206 virtual void MoveTo(int x_
, int y_
);
207 virtual void LineTo(int x_
, int y_
);
208 virtual void Polygon(Point
*pts
, int npts
, ColourAllocated fore
, ColourAllocated back
);
209 virtual void RectangleDraw(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
);
210 virtual void FillRectangle(PRectangle rc
, ColourAllocated back
);
211 virtual void FillRectangle(PRectangle rc
, Surface
&surfacePattern
);
212 virtual void RoundedRectangle(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
);
213 virtual void AlphaRectangle(PRectangle rc
, int cornerSize
, ColourAllocated fill
, int alphaFill
,
214 ColourAllocated outline
, int alphaOutline
, int flags
);
215 virtual void Ellipse(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
);
216 virtual void Copy(PRectangle rc
, Point from
, Surface
&surfaceSource
);
218 virtual void DrawTextNoClip(PRectangle rc
, Font
&font_
, int ybase
, const char *s
, int len
, ColourAllocated fore
, ColourAllocated back
);
219 virtual void DrawTextClipped(PRectangle rc
, Font
&font_
, int ybase
, const char *s
, int len
, ColourAllocated fore
, ColourAllocated back
);
220 virtual void DrawTextTransparent(PRectangle rc
, Font
&font_
, int ybase
, const char *s
, int len
, ColourAllocated fore
);
221 virtual void MeasureWidths(Font
&font_
, const char *s
, int len
, int *positions
);
222 virtual int WidthText(Font
&font_
, const char *s
, int len
);
223 virtual int WidthChar(Font
&font_
, char ch
);
224 virtual int Ascent(Font
&font_
);
225 virtual int Descent(Font
&font_
);
226 virtual int InternalLeading(Font
&font_
);
227 virtual int ExternalLeading(Font
&font_
);
228 virtual int Height(Font
&font_
);
229 virtual int AverageCharWidth(Font
&font_
);
231 virtual int SetPalette(Palette
*pal
, bool inBackGround
);
232 virtual void SetClip(PRectangle rc
);
233 virtual void FlushCachedState();
235 virtual void SetUnicodeMode(bool unicodeMode_
);
236 virtual void SetDBCSMode(int codePage
);
238 void BrushColour(ColourAllocated back
);
239 void SetFont(Font
&font_
);
244 SurfaceImpl::SurfaceImpl() :
245 hdc(0), hdcOwned(0), bitmap(0),
246 x(0), y(0), unicodeMode(0)
249 SurfaceImpl::~SurfaceImpl() {
253 void SurfaceImpl::Init(WindowID wid
) {
256 hdc
= new wxMemoryDC();
259 // On Mac and GTK the DC is not really valid until it has a bitmap
260 // selected into it. So instead of just creating the DC with no bitmap,
261 // go ahead and give it one.
262 InitPixMap(1,1,NULL
,wid
);
266 void SurfaceImpl::Init(SurfaceID hdc_
, WindowID
) {
271 void SurfaceImpl::InitPixMap(int width
, int height
, Surface
*WXUNUSED(surface_
), WindowID
) {
273 hdc
= new wxMemoryDC();
275 if (width
< 1) width
= 1;
276 if (height
< 1) height
= 1;
277 bitmap
= new wxBitmap(width
, height
);
278 ((wxMemoryDC
*)hdc
)->SelectObject(*bitmap
);
282 void SurfaceImpl::Release() {
284 ((wxMemoryDC
*)hdc
)->SelectObject(wxNullBitmap
);
296 bool SurfaceImpl::Initialised() {
301 void SurfaceImpl::PenColour(ColourAllocated fore
) {
302 hdc
->SetPen(wxPen(wxColourFromCA(fore
)));
305 void SurfaceImpl::BrushColour(ColourAllocated back
) {
306 hdc
->SetBrush(wxBrush(wxColourFromCA(back
)));
309 void SurfaceImpl::SetFont(Font
&font_
) {
311 hdc
->SetFont(*((wxFont
*)font_
.GetID()));
315 int SurfaceImpl::LogPixelsY() {
316 return hdc
->GetPPI().y
;
319 int SurfaceImpl::DeviceHeightFont(int points
) {
323 void SurfaceImpl::MoveTo(int x_
, int y_
) {
328 void SurfaceImpl::LineTo(int x_
, int y_
) {
329 hdc
->DrawLine(x
,y
, x_
,y_
);
334 void SurfaceImpl::Polygon(Point
*pts
, int npts
, ColourAllocated fore
, ColourAllocated back
) {
337 hdc
->DrawPolygon(npts
, (wxPoint
*)pts
);
340 void SurfaceImpl::RectangleDraw(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
) {
343 hdc
->DrawRectangle(wxRectFromPRectangle(rc
));
346 void SurfaceImpl::FillRectangle(PRectangle rc
, ColourAllocated back
) {
348 hdc
->SetPen(*wxTRANSPARENT_PEN
);
349 hdc
->DrawRectangle(wxRectFromPRectangle(rc
));
352 void SurfaceImpl::FillRectangle(PRectangle rc
, Surface
&surfacePattern
) {
354 if (((SurfaceImpl
&)surfacePattern
).bitmap
)
355 br
= wxBrush(*((SurfaceImpl
&)surfacePattern
).bitmap
);
356 else // Something is wrong so display in red
357 br
= wxBrush(*wxRED
);
358 hdc
->SetPen(*wxTRANSPARENT_PEN
);
360 hdc
->DrawRectangle(wxRectFromPRectangle(rc
));
363 void SurfaceImpl::RoundedRectangle(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
) {
366 hdc
->DrawRoundedRectangle(wxRectFromPRectangle(rc
), 4);
370 #define wxPy_premultiply(p, a) ((p) * (a) / 0xff)
372 #define wxPy_premultiply(p, a) (p)
375 void SurfaceImpl::AlphaRectangle(PRectangle rc
, int cornerSize
,
376 ColourAllocated fill
, int alphaFill
,
377 ColourAllocated outline
, int alphaOutline
,
379 #if wxUSE_GRAPHICS_CONTEXT
380 wxGCDC
dc(*(wxMemoryDC
*)hdc
);
381 wxColour
penColour(wxColourFromCAandAlpha(outline
, alphaOutline
));
382 wxColour
brushColour(wxColourFromCAandAlpha(fill
, alphaFill
));
383 dc
.SetPen(wxPen(penColour
));
384 dc
.SetBrush(wxBrush(brushColour
));
385 dc
.DrawRoundedRectangle(wxRectFromPRectangle(rc
), cornerSize
);
389 #ifdef wxHAS_RAW_BITMAP
391 // TODO: do something with cornerSize
392 wxUnusedVar(cornerSize
);
395 wxRect r
= wxRectFromPRectangle(rc
);
396 wxBitmap
bmp(r
.width
, r
.height
, 32);
397 wxAlphaPixelData
pixData(bmp
);
399 // Set the fill pixels
400 ColourDesired
cdf(fill
.AsLong());
401 int red
= cdf
.GetRed();
402 int green
= cdf
.GetGreen();
403 int blue
= cdf
.GetBlue();
405 wxAlphaPixelData::Iterator
p(pixData
);
406 for (y
=0; y
<r
.height
; y
++) {
407 p
.MoveTo(pixData
, 0, y
);
408 for (x
=0; x
<r
.width
; x
++) {
409 p
.Red() = wxPy_premultiply(red
, alphaFill
);
410 p
.Green() = wxPy_premultiply(green
, alphaFill
);
411 p
.Blue() = wxPy_premultiply(blue
, alphaFill
);
412 p
.Alpha() = alphaFill
;
417 // Set the outline pixels
418 ColourDesired
cdo(outline
.AsLong());
420 green
= cdo
.GetGreen();
421 blue
= cdo
.GetBlue();
422 for (x
=0; x
<r
.width
; x
++) {
423 p
.MoveTo(pixData
, x
, 0);
424 p
.Red() = wxPy_premultiply(red
, alphaOutline
);
425 p
.Green() = wxPy_premultiply(green
, alphaOutline
);
426 p
.Blue() = wxPy_premultiply(blue
, alphaOutline
);
427 p
.Alpha() = alphaOutline
;
428 p
.MoveTo(pixData
, x
, r
.height
-1);
429 p
.Red() = wxPy_premultiply(red
, alphaOutline
);
430 p
.Green() = wxPy_premultiply(green
, alphaOutline
);
431 p
.Blue() = wxPy_premultiply(blue
, alphaOutline
);
432 p
.Alpha() = alphaOutline
;
435 for (y
=0; y
<r
.height
; y
++) {
436 p
.MoveTo(pixData
, 0, y
);
437 p
.Red() = wxPy_premultiply(red
, alphaOutline
);
438 p
.Green() = wxPy_premultiply(green
, alphaOutline
);
439 p
.Blue() = wxPy_premultiply(blue
, alphaOutline
);
440 p
.Alpha() = alphaOutline
;
441 p
.MoveTo(pixData
, r
.width
-1, y
);
442 p
.Red() = wxPy_premultiply(red
, alphaOutline
);
443 p
.Green() = wxPy_premultiply(green
, alphaOutline
);
444 p
.Blue() = wxPy_premultiply(blue
, alphaOutline
);
445 p
.Alpha() = alphaOutline
;
449 hdc
->DrawBitmap(bmp
, r
.x
, r
.y
, true);
452 wxUnusedVar(cornerSize
);
453 wxUnusedVar(alphaFill
);
454 wxUnusedVar(alphaOutline
);
455 RectangleDraw(rc
, outline
, fill
);
460 void SurfaceImpl::Ellipse(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
) {
463 hdc
->DrawEllipse(wxRectFromPRectangle(rc
));
466 void SurfaceImpl::Copy(PRectangle rc
, Point from
, Surface
&surfaceSource
) {
467 wxRect r
= wxRectFromPRectangle(rc
);
468 hdc
->Blit(r
.x
, r
.y
, r
.width
, r
.height
,
469 ((SurfaceImpl
&)surfaceSource
).hdc
,
470 from
.x
, from
.y
, wxCOPY
);
473 void SurfaceImpl::DrawTextNoClip(PRectangle rc
, Font
&font
, int ybase
,
474 const char *s
, int len
,
475 ColourAllocated fore
, ColourAllocated back
) {
477 hdc
->SetTextForeground(wxColourFromCA(fore
));
478 hdc
->SetTextBackground(wxColourFromCA(back
));
479 FillRectangle(rc
, back
);
481 // ybase is where the baseline should be, but wxWin uses the upper left
482 // corner, so I need to calculate the real position for the text...
483 hdc
->DrawText(stc2wx(s
, len
), rc
.left
, ybase
- font
.ascent
);
486 void SurfaceImpl::DrawTextClipped(PRectangle rc
, Font
&font
, int ybase
,
487 const char *s
, int len
,
488 ColourAllocated fore
, ColourAllocated back
) {
490 hdc
->SetTextForeground(wxColourFromCA(fore
));
491 hdc
->SetTextBackground(wxColourFromCA(back
));
492 FillRectangle(rc
, back
);
493 hdc
->SetClippingRegion(wxRectFromPRectangle(rc
));
495 // see comments above
496 hdc
->DrawText(stc2wx(s
, len
), rc
.left
, ybase
- font
.ascent
);
497 hdc
->DestroyClippingRegion();
501 void SurfaceImpl::DrawTextTransparent(PRectangle rc
, Font
&font
, int ybase
,
502 const char *s
, int len
,
503 ColourAllocated fore
) {
506 hdc
->SetTextForeground(wxColourFromCA(fore
));
507 hdc
->SetBackgroundMode(wxBRUSHSTYLE_TRANSPARENT
);
509 // ybase is where the baseline should be, but wxWin uses the upper left
510 // corner, so I need to calculate the real position for the text...
511 hdc
->DrawText(stc2wx(s
, len
), rc
.left
, ybase
- font
.ascent
);
513 hdc
->SetBackgroundMode(wxBRUSHSTYLE_SOLID
);
517 void SurfaceImpl::MeasureWidths(Font
&font
, const char *s
, int len
, int *positions
) {
519 wxString str
= stc2wx(s
, len
);
524 hdc
->GetPartialTextExtents(str
, tpos
);
527 // Map the widths for UCS-2 characters back to the UTF-8 input string
528 // NOTE: I don't think this is right for when sizeof(wxChar) > 2, ie wxGTK2
529 // so figure it out and fix it!
532 while ((int)i
< len
) {
533 unsigned char uch
= (unsigned char)s
[i
];
534 positions
[i
++] = tpos
[ui
];
536 if (uch
< (0x80 + 0x40 + 0x20)) {
537 positions
[i
++] = tpos
[ui
];
539 positions
[i
++] = tpos
[ui
];
540 positions
[i
++] = tpos
[ui
];
547 // If not unicode then just use the widths we have
548 #if wxUSE_STD_CONTAINERS
549 std::copy(tpos
.begin(), tpos
.end(), positions
);
551 memcpy(positions
, tpos
.begin(), len
* sizeof(int));
557 int SurfaceImpl::WidthText(Font
&font
, const char *s
, int len
) {
562 hdc
->GetTextExtent(stc2wx(s
, len
), &w
, &h
);
567 int SurfaceImpl::WidthChar(Font
&font
, char ch
) {
571 char s
[2] = { ch
, 0 };
573 hdc
->GetTextExtent(stc2wx(s
, 1), &w
, &h
);
577 #define EXTENT_TEST wxT(" `~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
579 int SurfaceImpl::Ascent(Font
&font
) {
582 hdc
->GetTextExtent(EXTENT_TEST
, &w
, &h
, &d
, &e
);
587 int SurfaceImpl::Descent(Font
&font
) {
590 hdc
->GetTextExtent(EXTENT_TEST
, &w
, &h
, &d
, &e
);
594 int SurfaceImpl::InternalLeading(Font
&WXUNUSED(font
)) {
598 int SurfaceImpl::ExternalLeading(Font
&font
) {
601 hdc
->GetTextExtent(EXTENT_TEST
, &w
, &h
, &d
, &e
);
605 int SurfaceImpl::Height(Font
&font
) {
607 return hdc
->GetCharHeight() + 1;
610 int SurfaceImpl::AverageCharWidth(Font
&font
) {
612 return hdc
->GetCharWidth();
615 int SurfaceImpl::SetPalette(Palette
*WXUNUSED(pal
), bool WXUNUSED(inBackGround
)) {
619 void SurfaceImpl::SetClip(PRectangle rc
) {
620 hdc
->SetClippingRegion(wxRectFromPRectangle(rc
));
623 void SurfaceImpl::FlushCachedState() {
626 void SurfaceImpl::SetUnicodeMode(bool unicodeMode_
) {
627 unicodeMode
=unicodeMode_
;
630 void SurfaceImpl::SetDBCSMode(int WXUNUSED(codePage
)) {
631 // dbcsMode = codePage == SC_CP_DBCS;
635 Surface
*Surface::Allocate() {
636 return new SurfaceImpl
;
640 //----------------------------------------------------------------------
643 inline wxWindow
* GETWIN(WindowID id
) { return (wxWindow
*)id
; }
648 void Window::Destroy() {
651 GETWIN(wid
)->Destroy();
656 bool Window::HasFocus() {
657 return wxWindow::FindFocus() == GETWIN(wid
);
660 PRectangle
Window::GetPosition() {
661 if (! wid
) return PRectangle();
662 wxRect
rc(GETWIN(wid
)->GetPosition(), GETWIN(wid
)->GetSize());
663 return PRectangleFromwxRect(rc
);
666 void Window::SetPosition(PRectangle rc
) {
667 wxRect r
= wxRectFromPRectangle(rc
);
668 GETWIN(wid
)->SetSize(r
);
671 void Window::SetPositionRelative(PRectangle rc
, Window
) {
672 SetPosition(rc
); // ????
675 PRectangle
Window::GetClientPosition() {
676 if (! wid
) return PRectangle();
677 wxSize sz
= GETWIN(wid
)->GetClientSize();
678 return PRectangle(0, 0, sz
.x
, sz
.y
);
681 void Window::Show(bool show
) {
682 GETWIN(wid
)->Show(show
);
685 void Window::InvalidateAll() {
686 GETWIN(wid
)->Refresh(false);
689 void Window::InvalidateRectangle(PRectangle rc
) {
690 wxRect r
= wxRectFromPRectangle(rc
);
691 GETWIN(wid
)->Refresh(false, &r
);
694 void Window::SetFont(Font
&font
) {
695 GETWIN(wid
)->SetFont(*((wxFont
*)font
.GetID()));
698 void Window::SetCursor(Cursor curs
) {
699 wxStockCursor cursorId
;
703 cursorId
= wxCURSOR_IBEAM
;
706 cursorId
= wxCURSOR_ARROW
;
709 cursorId
= wxCURSOR_ARROW
; // ** no up arrow... wxCURSOR_UPARROW;
712 cursorId
= wxCURSOR_WAIT
;
715 cursorId
= wxCURSOR_SIZEWE
;
718 cursorId
= wxCURSOR_SIZENS
;
720 case cursorReverseArrow
:
721 cursorId
= wxCURSOR_RIGHT_ARROW
;
724 cursorId
= wxCURSOR_HAND
;
727 cursorId
= wxCURSOR_ARROW
;
731 wxCursor wc
= wxCursor(cursorId
);
732 if(curs
!= cursorLast
)
734 GETWIN(wid
)->SetCursor(wc
);
740 void Window::SetTitle(const char *s
) {
741 GETWIN(wid
)->SetLabel(stc2wx(s
));
745 // Returns rectangle of monitor pt is on
746 PRectangle
Window::GetMonitorRect(Point pt
) {
748 if (! wid
) return PRectangle();
750 // Get the display the point is found on
751 int n
= wxDisplay::GetFromPoint(wxPoint(pt
.x
, pt
.y
));
752 wxDisplay
dpy(n
== wxNOT_FOUND
? 0 : n
);
753 rect
= dpy
.GetGeometry();
757 return PRectangleFromwxRect(rect
);
760 //----------------------------------------------------------------------
761 // Helper classes for ListBox
764 // This is a simple subclass of wxListView that just resets focus to the
765 // parent when it gets it.
766 class wxSTCListBox
: public wxListView
{
768 wxSTCListBox(wxWindow
* parent
, wxWindowID id
,
769 const wxPoint
& pos
, const wxSize
& size
,
774 Hide(); // don't flicker as we move it around...
776 Create(parent
, id
, pos
, size
, style
);
780 void OnFocus(wxFocusEvent
& event
) {
781 GetParent()->SetFocus();
785 void OnKillFocus(wxFocusEvent
& WXUNUSED(event
)) {
786 // Do nothing. Prevents base class from resetting the colors...
790 // For some reason I don't understand yet the focus doesn't really leave
791 // the listbox like it should, so if we get any events feed them back to
793 void OnKeyDown(wxKeyEvent
& event
) {
794 GetGrandParent()->GetEventHandler()->ProcessEvent(event
);
796 void OnChar(wxKeyEvent
& event
) {
797 GetGrandParent()->GetEventHandler()->ProcessEvent(event
);
800 // And we need to force the focus back when being destroyed
802 GetGrandParent()->SetFocus();
807 DECLARE_EVENT_TABLE()
810 BEGIN_EVENT_TABLE(wxSTCListBox
, wxListView
)
811 EVT_SET_FOCUS( wxSTCListBox::OnFocus
)
812 EVT_KILL_FOCUS(wxSTCListBox::OnKillFocus
)
814 EVT_KEY_DOWN( wxSTCListBox::OnKeyDown
)
815 EVT_CHAR( wxSTCListBox::OnChar
)
821 #if wxUSE_POPUPWIN //-----------------------------------
822 #include "wx/popupwin.h"
824 // A popup window to place the wxSTCListBox upon
825 class wxSTCListBoxWin
: public wxPopupWindow
829 CallBackAction doubleClickAction
;
830 void* doubleClickActionData
;
832 wxSTCListBoxWin(wxWindow
* parent
, wxWindowID id
, Point
WXUNUSED(location
)) :
833 wxPopupWindow(parent
, wxBORDER_SIMPLE
)
836 lv
= new wxSTCListBox(parent
, id
, wxPoint(-50,-50), wxDefaultSize
,
837 wxLC_REPORT
| wxLC_SINGLE_SEL
| wxLC_NO_HEADER
| wxBORDER_NONE
);
838 lv
->SetCursor(wxCursor(wxCURSOR_ARROW
));
839 lv
->InsertColumn(0, wxEmptyString
);
840 lv
->InsertColumn(1, wxEmptyString
);
842 // NOTE: We need to fool the wxListView into thinking that it has the
843 // focus so it will use the normal selection colour and will look
844 // "right" to the user. But since the wxPopupWindow or its children
845 // can't receive focus then we have to pull a fast one and temporarily
846 // parent the listctrl on the STC window and then call SetFocus and
847 // then reparent it back to the popup.
853 #ifdef __WXOSX_COCOA__
854 SetBackgroundColour(wxColour(0xC0, 0xC0, 0xC0));
859 // Set position in client coords
860 virtual void DoSetSize(int x
, int y
,
861 int width
, int height
,
862 int sizeFlags
= wxSIZE_AUTO
) {
863 if (x
!= wxDefaultCoord
) {
864 GetParent()->ClientToScreen(&x
, NULL
);
866 if (y
!= wxDefaultCoord
) {
867 GetParent()->ClientToScreen(NULL
, &y
);
869 wxPopupWindow::DoSetSize(x
, y
, width
, height
, sizeFlags
);
872 // return position as if it were in client coords
873 virtual void DoGetPosition( int *x
, int *y
) const {
875 wxPopupWindow::DoGetPosition(&sx
, &sy
);
876 GetParent()->ScreenToClient(&sx
, &sy
);
883 if ( !wxPendingDelete
.Member(this) )
884 wxPendingDelete
.Append(this);
890 wxImageList
* il
= lv
->GetImageList(wxIMAGE_LIST_SMALL
);
893 il
->GetSize(0, w
, h
);
900 void SetDoubleClickAction(CallBackAction action
, void *data
) {
901 doubleClickAction
= action
;
902 doubleClickActionData
= data
;
906 void OnFocus(wxFocusEvent
& event
) {
907 GetParent()->SetFocus();
911 void OnSize(wxSizeEvent
& event
) {
912 // resize the child to fill the popup
913 wxSize sz
= GetClientSize();
918 #ifdef __WXOSX_COCOA__
919 // make room for the parent's bg color to show, to act as a border
924 lv
->SetSize(x
, y
, w
, h
);
925 // reset the column widths
926 lv
->SetColumnWidth(0, IconWidth()+4);
927 lv
->SetColumnWidth(1, w
- 2 - lv
->GetColumnWidth(0) -
928 wxSystemSettings::GetMetric(wxSYS_VSCROLL_X
));
932 void OnActivate(wxListEvent
& WXUNUSED(event
)) {
933 doubleClickAction(doubleClickActionData
);
936 wxListView
* GetLB() { return lv
; }
939 DECLARE_EVENT_TABLE()
943 BEGIN_EVENT_TABLE(wxSTCListBoxWin
, wxPopupWindow
)
944 EVT_SET_FOCUS ( wxSTCListBoxWin::OnFocus
)
945 EVT_SIZE ( wxSTCListBoxWin::OnSize
)
946 EVT_LIST_ITEM_ACTIVATED(wxID_ANY
, wxSTCListBoxWin::OnActivate
)
951 #else // !wxUSE_POPUPWIN -----------------------------------
952 #include "wx/frame.h"
954 // A normal window to place the wxSTCListBox upon, but make it behave as much
955 // like a wxPopupWindow as possible
956 class wxSTCListBoxWin
: public wxFrame
{
959 CallBackAction doubleClickAction
;
960 void* doubleClickActionData
;
962 wxSTCListBoxWin(wxWindow
* parent
, wxWindowID id
, Point location
) :
963 wxFrame(parent
, id
, wxEmptyString
, wxPoint(location
.x
, location
.y
), wxSize(0,0),
965 | wxFRAME_FLOAT_ON_PARENT
975 lv
= new wxSTCListBox(this, id
, wxDefaultPosition
, wxDefaultSize
,
976 wxLC_REPORT
| wxLC_SINGLE_SEL
| wxLC_NO_HEADER
| wxNO_BORDER
);
977 lv
->SetCursor(wxCursor(wxCURSOR_ARROW
));
978 lv
->InsertColumn(0, wxEmptyString
);
979 lv
->InsertColumn(1, wxEmptyString
);
981 // Eventhough we immediately reset the focus to the parent, this helps
982 // things to look right...
989 // On OSX and (possibly others) there can still be pending
990 // messages/events for the list control when Scintilla wants to
991 // close it, so do a pending delete of it instead of destroying
996 // The bottom edge of this window is not getting properly
997 // refreshed upon deletion, so help it out...
998 wxWindow
* p
= GetParent();
999 wxRect
r(GetPosition(), GetSize());
1000 r
.SetHeight(r
.GetHeight()+1);
1001 p
->Refresh(false, &r
);
1003 if ( !wxPendingDelete
.Member(this) )
1004 wxPendingDelete
.Append(this);
1011 wxImageList
* il
= lv
->GetImageList(wxIMAGE_LIST_SMALL
);
1014 il
->GetSize(0, w
, h
);
1021 void SetDoubleClickAction(CallBackAction action
, void *data
)
1023 doubleClickAction
= action
;
1024 doubleClickActionData
= data
;
1028 void OnFocus(wxFocusEvent
& event
)
1031 GetParent()->SetFocus();
1035 void OnSize(wxSizeEvent
& event
)
1038 wxSize sz
= GetClientSize();
1040 // reset the column widths
1041 lv
->SetColumnWidth(0, IconWidth()+4);
1042 lv
->SetColumnWidth(1, sz
.x
- 2 - lv
->GetColumnWidth(0) -
1043 wxSystemSettings::GetMetric(wxSYS_VSCROLL_X
));
1047 void ActivateParent()
1049 // Although we're a frame, we always want the parent to be active, so
1050 // raise it whenever we get shown, focused, etc.
1051 wxTopLevelWindow
*frame
= wxDynamicCast(
1052 wxGetTopLevelParent(GetParent()), wxTopLevelWindow
);
1058 virtual void DoSetSize(int x
, int y
,
1059 int width
, int height
,
1060 int sizeFlags
= wxSIZE_AUTO
)
1062 // convert coords to screen coords since we're a top-level window
1063 if (x
!= wxDefaultCoord
) {
1064 GetParent()->ClientToScreen(&x
, NULL
);
1066 if (y
!= wxDefaultCoord
) {
1067 GetParent()->ClientToScreen(NULL
, &y
);
1069 wxFrame::DoSetSize(x
, y
, width
, height
, sizeFlags
);
1072 virtual bool Show(bool show
= true)
1074 bool rv
= wxFrame::Show(show
);
1078 GetParent()->Refresh(false);
1083 void OnActivate(wxListEvent
& WXUNUSED(event
))
1085 doubleClickAction(doubleClickActionData
);
1088 wxListView
* GetLB() { return lv
; }
1091 DECLARE_EVENT_TABLE()
1095 BEGIN_EVENT_TABLE(wxSTCListBoxWin
, wxWindow
)
1096 EVT_SET_FOCUS ( wxSTCListBoxWin::OnFocus
)
1097 EVT_SIZE ( wxSTCListBoxWin::OnSize
)
1098 EVT_LIST_ITEM_ACTIVATED(wxID_ANY
, wxSTCListBoxWin::OnActivate
)
1101 #endif // wxUSE_POPUPWIN -----------------------------------
1104 inline wxSTCListBoxWin
* GETLBW(WindowID win
) {
1105 return ((wxSTCListBoxWin
*)win
);
1108 inline wxListView
* GETLB(WindowID win
) {
1109 return GETLBW(win
)->GetLB();
1112 //----------------------------------------------------------------------
1114 class ListBoxImpl
: public ListBox
{
1118 int desiredVisibleRows
;
1121 Point location
; // Caret location at which the list is opened
1122 wxImageList
* imgList
;
1123 wxArrayInt
* imgTypeMap
;
1129 virtual void SetFont(Font
&font
);
1130 virtual void Create(Window
&parent
, int ctrlID
, Point location_
, int lineHeight_
, bool unicodeMode_
);
1131 virtual void SetAverageCharWidth(int width
);
1132 virtual void SetVisibleRows(int rows
);
1133 virtual int GetVisibleRows() const;
1134 virtual PRectangle
GetDesiredRect();
1135 virtual int CaretFromEdge();
1136 virtual void Clear();
1137 virtual void Append(char *s
, int type
= -1);
1138 void Append(const wxString
& text
, int type
);
1139 virtual int Length();
1140 virtual void Select(int n
);
1141 virtual int GetSelection();
1142 virtual int Find(const char *prefix
);
1143 virtual void GetValue(int n
, char *value
, int len
);
1144 virtual void RegisterImage(int type
, const char *xpm_data
);
1145 virtual void ClearRegisteredImages();
1146 virtual void SetDoubleClickAction(CallBackAction
, void *);
1147 virtual void SetList(const char* list
, char separator
, char typesep
);
1151 ListBoxImpl::ListBoxImpl()
1152 : lineHeight(10), unicodeMode(false),
1153 desiredVisibleRows(5), aveCharWidth(8), maxStrWidth(0),
1154 imgList(NULL
), imgTypeMap(NULL
)
1158 ListBoxImpl::~ListBoxImpl() {
1160 wxDELETE(imgTypeMap
);
1164 void ListBoxImpl::SetFont(Font
&font
) {
1165 GETLB(wid
)->SetFont(*((wxFont
*)font
.GetID()));
1169 void ListBoxImpl::Create(Window
&parent
, int ctrlID
, Point location_
, int lineHeight_
, bool unicodeMode_
) {
1170 location
= location_
;
1171 lineHeight
= lineHeight_
;
1172 unicodeMode
= unicodeMode_
;
1174 wid
= new wxSTCListBoxWin(GETWIN(parent
.GetID()), ctrlID
, location
);
1175 if (imgList
!= NULL
)
1176 GETLB(wid
)->SetImageList(imgList
, wxIMAGE_LIST_SMALL
);
1180 void ListBoxImpl::SetAverageCharWidth(int width
) {
1181 aveCharWidth
= width
;
1185 void ListBoxImpl::SetVisibleRows(int rows
) {
1186 desiredVisibleRows
= rows
;
1190 int ListBoxImpl::GetVisibleRows() const {
1191 return desiredVisibleRows
;
1194 PRectangle
ListBoxImpl::GetDesiredRect() {
1195 // wxListCtrl doesn't have a DoGetBestSize, so instead we kept track of
1196 // the max size in Append and calculate it here...
1197 int maxw
= maxStrWidth
* aveCharWidth
;
1200 // give it a default if there are no lines, and/or add a bit more
1201 if (maxw
== 0) maxw
= 100;
1202 maxw
+= aveCharWidth
* 3 +
1203 GETLBW(wid
)->IconWidth() + wxSystemSettings::GetMetric(wxSYS_VSCROLL_X
);
1207 // estimate a desired height
1208 int count
= GETLB(wid
)->GetItemCount();
1211 GETLB(wid
)->GetItemRect(0, rect
);
1212 maxh
= count
* rect
.GetHeight();
1213 if (maxh
> 140) // TODO: Use desiredVisibleRows??
1216 // Try to make the size an exact multiple of some number of lines
1217 int lines
= maxh
/ rect
.GetHeight();
1218 maxh
= (lines
+ 1) * rect
.GetHeight() + 2;
1232 int ListBoxImpl::CaretFromEdge() {
1233 return 4 + GETLBW(wid
)->IconWidth();
1237 void ListBoxImpl::Clear() {
1238 GETLB(wid
)->DeleteAllItems();
1242 void ListBoxImpl::Append(char *s
, int type
) {
1243 Append(stc2wx(s
), type
);
1246 void ListBoxImpl::Append(const wxString
& text
, int type
) {
1247 long count
= GETLB(wid
)->GetItemCount();
1248 long itemID
= GETLB(wid
)->InsertItem(count
, wxEmptyString
);
1250 GETLB(wid
)->SetItem(itemID
, 1, text
);
1251 maxStrWidth
= wxMax(maxStrWidth
, text
.length());
1253 wxCHECK_RET(imgTypeMap
, wxT("Unexpected NULL imgTypeMap"));
1254 idx
= imgTypeMap
->Item(type
);
1256 GETLB(wid
)->SetItemImage(itemID
, idx
, idx
);
1259 void ListBoxImpl::SetList(const char* list
, char separator
, char typesep
) {
1260 GETLB(wid
)->Freeze();
1262 wxStringTokenizer
tkzr(stc2wx(list
), (wxChar
)separator
);
1263 while ( tkzr
.HasMoreTokens() ) {
1264 wxString token
= tkzr
.GetNextToken();
1266 int pos
= token
.Find(typesep
);
1268 token
.Mid(pos
+1).ToLong(&type
);
1269 token
.Truncate(pos
);
1271 Append(token
, (int)type
);
1277 int ListBoxImpl::Length() {
1278 return GETLB(wid
)->GetItemCount();
1282 void ListBoxImpl::Select(int n
) {
1288 GETLB(wid
)->EnsureVisible(n
);
1289 GETLB(wid
)->Select(n
, select
);
1293 int ListBoxImpl::GetSelection() {
1294 return GETLB(wid
)->GetFirstSelected();
1298 int ListBoxImpl::Find(const char *WXUNUSED(prefix
)) {
1304 void ListBoxImpl::GetValue(int n
, char *value
, int len
) {
1308 item
.SetMask(wxLIST_MASK_TEXT
);
1309 GETLB(wid
)->GetItem(item
);
1310 strncpy(value
, wx2stc(item
.GetText()), len
);
1311 value
[len
-1] = '\0';
1315 void ListBoxImpl::RegisterImage(int type
, const char *xpm_data
) {
1316 wxMemoryInputStream
stream(xpm_data
, strlen(xpm_data
)+1);
1317 wxImage
img(stream
, wxBITMAP_TYPE_XPM
);
1321 // assumes all images are the same size
1322 imgList
= new wxImageList(bmp
.GetWidth(), bmp
.GetHeight(), true);
1323 imgTypeMap
= new wxArrayInt
;
1326 int idx
= imgList
->Add(bmp
);
1328 // do we need to extend the mapping array?
1329 wxArrayInt
& itm
= *imgTypeMap
;
1330 if ( itm
.GetCount() < (size_t)type
+1)
1331 itm
.Add(-1, type
- itm
.GetCount() + 1);
1333 // Add an item that maps type to the image index
1337 void ListBoxImpl::ClearRegisteredImages() {
1339 wxDELETE(imgTypeMap
);
1341 GETLB(wid
)->SetImageList(NULL
, wxIMAGE_LIST_SMALL
);
1345 void ListBoxImpl::SetDoubleClickAction(CallBackAction action
, void *data
) {
1346 GETLBW(wid
)->SetDoubleClickAction(action
, data
);
1350 ListBox::ListBox() {
1353 ListBox::~ListBox() {
1356 ListBox
*ListBox::Allocate() {
1357 return new ListBoxImpl();
1360 //----------------------------------------------------------------------
1362 Menu::Menu() : mid(0) {
1365 void Menu::CreatePopUp() {
1370 void Menu::Destroy() {
1372 delete (wxMenu
*)mid
;
1376 void Menu::Show(Point pt
, Window
&w
) {
1377 GETWIN(w
.GetID())->PopupMenu((wxMenu
*)mid
, pt
.x
- 4, pt
.y
);
1381 //----------------------------------------------------------------------
1383 DynamicLibrary
*DynamicLibrary::Load(const char *WXUNUSED(modulePath
)) {
1384 wxFAIL_MSG(wxT("Dynamic lexer loading not implemented yet"));
1388 //----------------------------------------------------------------------
1390 ColourDesired
Platform::Chrome() {
1392 c
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
1393 return ColourDesired(c
.Red(), c
.Green(), c
.Blue());
1396 ColourDesired
Platform::ChromeHighlight() {
1398 c
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT
);
1399 return ColourDesired(c
.Red(), c
.Green(), c
.Blue());
1402 const char *Platform::DefaultFont() {
1403 static char buf
[128];
1404 strcpy(buf
, wxNORMAL_FONT
->GetFaceName().mbc_str());
1408 int Platform::DefaultFontSize() {
1409 return wxNORMAL_FONT
->GetPointSize();
1412 unsigned int Platform::DoubleClickTime() {
1413 return 500; // **** ::GetDoubleClickTime();
1416 bool Platform::MouseButtonBounce() {
1420 bool Platform::IsKeyDown(int WXUNUSED(key
)) {
1421 return false; // I don't think we'll need this.
1424 long Platform::SendScintilla(WindowID w
,
1426 unsigned long wParam
,
1429 wxStyledTextCtrl
* stc
= (wxStyledTextCtrl
*)w
;
1430 return stc
->SendMsg(msg
, wParam
, lParam
);
1433 long Platform::SendScintillaPointer(WindowID w
,
1435 unsigned long wParam
,
1438 wxStyledTextCtrl
* stc
= (wxStyledTextCtrl
*)w
;
1439 return stc
->SendMsg(msg
, wParam
, (wxIntPtr
)lParam
);
1443 // These are utility functions not really tied to a platform
1445 int Platform::Minimum(int a
, int b
) {
1452 int Platform::Maximum(int a
, int b
) {
1461 void Platform::DebugDisplay(const char *s
) {
1463 wxLogDebug(stc2wx(s
));
1469 void Platform::DebugPrintf(const char *format
, ...) {
1473 va_start(pArguments
, format
);
1474 vsprintf(buffer
,format
,pArguments
);
1476 Platform::DebugDisplay(buffer
);
1478 wxUnusedVar(format
);
1483 static bool assertionPopUps
= true;
1485 bool Platform::ShowAssertionPopUps(bool assertionPopUps_
) {
1486 bool ret
= assertionPopUps
;
1487 assertionPopUps
= assertionPopUps_
;
1491 void Platform::Assert(const char *c
, const char *file
, int line
) {
1494 sprintf(buffer
, "Assertion [%s] failed at %s %d", c
, file
, line
);
1495 if (assertionPopUps
) {
1497 wxMessageBox(stc2wx(buffer
),
1498 wxT("Assertion failure"),
1499 wxICON_HAND
| wxOK
);
1501 strcat(buffer
, "\r\n");
1502 Platform::DebugDisplay(buffer
);
1513 int Platform::Clamp(int val
, int minVal
, int maxVal
) {
1522 bool Platform::IsDBCSLeadByte(int WXUNUSED(codePage
), char WXUNUSED(ch
)) {
1526 int Platform::DBCSCharLength(int WXUNUSED(codePage
), const char *WXUNUSED(s
)) {
1530 int Platform::DBCSCharMaxLength() {
1535 //----------------------------------------------------------------------
1537 ElapsedTime::ElapsedTime() {
1538 wxLongLong localTime
= wxGetLocalTimeMillis();
1539 littleBit
= localTime
.GetLo();
1540 bigBit
= localTime
.GetHi();
1543 double ElapsedTime::Duration(bool reset
) {
1544 wxLongLong
prevTime(bigBit
, littleBit
);
1545 wxLongLong localTime
= wxGetLocalTimeMillis();
1547 littleBit
= localTime
.GetLo();
1548 bigBit
= localTime
.GetHi();
1550 wxLongLong duration
= localTime
- prevTime
;
1551 double result
= duration
.ToDouble();
1557 //----------------------------------------------------------------------
1561 #include "UniConversion.h"
1563 // Convert using Scintilla's functions instead of wx's, Scintilla's are more
1564 // forgiving and won't assert...
1566 wxString
stc2wx(const char* str
, size_t len
)
1569 return wxEmptyString
;
1571 size_t wclen
= UTF16Length(str
, len
);
1572 wxWCharBuffer
buffer(wclen
+1);
1574 size_t actualLen
= UTF16FromUTF8(str
, len
, buffer
.data(), wclen
+1);
1575 return wxString(buffer
.data(), actualLen
);
1580 wxString
stc2wx(const char* str
)
1582 return stc2wx(str
, strlen(str
));
1586 const wxWX2MBbuf
wx2stc(const wxString
& str
)
1588 const wchar_t* wcstr
= str
.c_str();
1589 size_t wclen
= str
.length();
1590 size_t len
= UTF8Length(wcstr
, wclen
);
1592 wxCharBuffer
buffer(len
+1);
1593 UTF8FromUTF16(wcstr
, wclen
, buffer
.data(), len
);
1595 // TODO check NULL termination!!