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.
10 #include <wx/encconv.h>
11 #include <wx/listctrl.h>
12 #include <wx/mstream.h>
14 #include <wx/imaglist.h>
18 #include "wx/stc/stc.h"
22 Point Point
::FromLong(long lpoint
) {
23 return Point(lpoint
& 0xFFFF, lpoint
>> 16);
26 wxRect
wxRectFromPRectangle(PRectangle prc
) {
27 wxRect
r(prc
.left
, prc
.top
,
28 prc
.Width(), prc
.Height());
32 PRectangle
PRectangleFromwxRect(wxRect rc
) {
33 return PRectangle(rc
.GetLeft(), rc
.GetTop(),
34 rc
.GetRight()+1, rc
.GetBottom()+1);
37 wxColour
wxColourFromCA(const ColourAllocated
& ca
) {
38 ColourDesired
cd(ca
.AsLong());
39 return wxColour((unsigned char)cd
.GetRed(),
40 (unsigned char)cd
.GetGreen(),
41 (unsigned char)cd
.GetBlue());
44 //----------------------------------------------------------------------
48 allowRealization
= false;
55 void Palette
::Release() {
59 // This method either adds a colour to the list of wanted colours (want==true)
60 // or retrieves the allocated colour back to the ColourPair.
61 // This is one method to make it easier to keep the code for wanting and retrieving in sync.
62 void Palette
::WantFind(ColourPair
&cp
, bool want
) {
64 for (int i
=0; i
< used
; i
++) {
65 if (entries
[i
].desired
== cp
.desired
)
69 if (used
< numEntries
) {
70 entries
[used
].desired
= cp
.desired
;
71 entries
[used
].allocated
.Set(cp
.desired
.AsLong());
75 for (int i
=0; i
< used
; i
++) {
76 if (entries
[i
].desired
== cp
.desired
) {
77 cp
.allocated
= entries
[i
].allocated
;
81 cp
.allocated
.Set(cp
.desired
.AsLong());
85 void Palette
::Allocate(Window
&) {
86 if (allowRealization
) {
91 //----------------------------------------------------------------------
101 void Font
::Create(const char *faceName
, int characterSet
, int size
, bool bold
, bool italic
, bool extraFontFlag
) {
105 // The minus one is done because since Scintilla uses SC_SHARSET_DEFAULT
106 // internally and we need to have wxFONENCODING_DEFAULT == SC_SHARSET_DEFAULT
107 // so we adjust the encoding before passing it to Scintilla. See also
108 // wxStyledTextCtrl::StyleSetCharacterSet
109 wxFontEncoding encoding
= (wxFontEncoding
)(characterSet
-1);
111 wxFontEncodingArray ea
= wxEncodingConverter
::GetPlatformEquivalents(encoding
);
115 wxFont
* font
= new wxFont(size
,
117 italic ? wxITALIC
: wxNORMAL
,
118 bold ? wxBOLD
: wxNORMAL
,
122 font
->SetNoAntiAliasing(!extraFontFlag
);
127 void Font
::Release() {
133 //----------------------------------------------------------------------
135 class SurfaceImpl
: public Surface
{
148 virtual void Init(WindowID wid
);
149 virtual void Init(SurfaceID sid
, WindowID wid
);
150 virtual void InitPixMap(int width
, int height
, Surface
*surface_
, WindowID wid
);
152 virtual void Release();
153 virtual bool Initialised();
154 virtual void PenColour(ColourAllocated fore
);
155 virtual int LogPixelsY();
156 virtual int DeviceHeightFont(int points
);
157 virtual void MoveTo(int x_
, int y_
);
158 virtual void LineTo(int x_
, int y_
);
159 virtual void Polygon(Point
*pts
, int npts
, ColourAllocated fore
, ColourAllocated back
);
160 virtual void RectangleDraw(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
);
161 virtual void FillRectangle(PRectangle rc
, ColourAllocated back
);
162 virtual void FillRectangle(PRectangle rc
, Surface
&surfacePattern
);
163 virtual void RoundedRectangle(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
);
164 virtual void Ellipse(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
);
165 virtual void Copy(PRectangle rc
, Point from
, Surface
&surfaceSource
);
167 virtual void DrawTextNoClip(PRectangle rc
, Font
&font_
, int ybase
, const char *s
, int len
, ColourAllocated fore
, ColourAllocated back
);
168 virtual void DrawTextClipped(PRectangle rc
, Font
&font_
, int ybase
, const char *s
, int len
, ColourAllocated fore
, ColourAllocated back
);
169 virtual void DrawTextTransparent(PRectangle rc
, Font
&font_
, int ybase
, const char *s
, int len
, ColourAllocated fore
);
170 virtual void MeasureWidths(Font
&font_
, const char *s
, int len
, int *positions
);
171 virtual int WidthText(Font
&font_
, const char *s
, int len
);
172 virtual int WidthChar(Font
&font_
, char ch
);
173 virtual int Ascent(Font
&font_
);
174 virtual int Descent(Font
&font_
);
175 virtual int InternalLeading(Font
&font_
);
176 virtual int ExternalLeading(Font
&font_
);
177 virtual int Height(Font
&font_
);
178 virtual int AverageCharWidth(Font
&font_
);
180 virtual int SetPalette(Palette
*pal
, bool inBackGround
);
181 virtual void SetClip(PRectangle rc
);
182 virtual void FlushCachedState();
184 virtual void SetUnicodeMode(bool unicodeMode_
);
185 virtual void SetDBCSMode(int codePage
);
187 void BrushColour(ColourAllocated back
);
188 void SetFont(Font
&font_
);
193 SurfaceImpl
::SurfaceImpl() :
194 hdc(0), hdcOwned(0), bitmap(0),
195 x(0), y(0), unicodeMode(0)
198 SurfaceImpl
::~SurfaceImpl() {
202 void SurfaceImpl
::Init(WindowID wid
) {
205 hdc
= new wxMemoryDC();
208 // On Mac and GTK the DC is not really valid until it has a bitmap
209 // selected into it. So instead of just creating the DC with no bitmap,
210 // go ahead and give it one.
211 InitPixMap(1,1,NULL
,wid
);
215 void SurfaceImpl
::Init(SurfaceID hdc_
, WindowID
) {
220 void SurfaceImpl
::InitPixMap(int width
, int height
, Surface
*WXUNUSED(surface_
), WindowID
) {
222 hdc
= new wxMemoryDC();
224 if (width
< 1) width
= 1;
225 if (height
< 1) height
= 1;
226 bitmap
= new wxBitmap(width
, height
);
227 ((wxMemoryDC
*)hdc
)->SelectObject(*bitmap
);
231 void SurfaceImpl
::Release() {
233 ((wxMemoryDC
*)hdc
)->SelectObject(wxNullBitmap
);
245 bool SurfaceImpl
::Initialised() {
250 void SurfaceImpl
::PenColour(ColourAllocated fore
) {
251 hdc
->SetPen(wxPen(wxColourFromCA(fore
), 1, wxSOLID
));
254 void SurfaceImpl
::BrushColour(ColourAllocated back
) {
255 hdc
->SetBrush(wxBrush(wxColourFromCA(back
), wxSOLID
));
258 void SurfaceImpl
::SetFont(Font
&font_
) {
260 hdc
->SetFont(*((wxFont
*)font_
.GetID()));
264 int SurfaceImpl
::LogPixelsY() {
265 return hdc
->GetPPI().y
;
268 int SurfaceImpl
::DeviceHeightFont(int points
) {
272 void SurfaceImpl
::MoveTo(int x_
, int y_
) {
277 void SurfaceImpl
::LineTo(int x_
, int y_
) {
278 hdc
->DrawLine(x
,y
, x_
,y_
);
283 void SurfaceImpl
::Polygon(Point
*pts
, int npts
, ColourAllocated fore
, ColourAllocated back
) {
286 hdc
->DrawPolygon(npts
, (wxPoint
*)pts
);
289 void SurfaceImpl
::RectangleDraw(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
) {
292 hdc
->DrawRectangle(wxRectFromPRectangle(rc
));
295 void SurfaceImpl
::FillRectangle(PRectangle rc
, ColourAllocated back
) {
297 hdc
->SetPen(*wxTRANSPARENT_PEN
);
298 hdc
->DrawRectangle(wxRectFromPRectangle(rc
));
301 void SurfaceImpl
::FillRectangle(PRectangle rc
, Surface
&surfacePattern
) {
303 if (((SurfaceImpl
&)surfacePattern
).bitmap
)
304 br
= wxBrush(*((SurfaceImpl
&)surfacePattern
).bitmap
);
305 else // Something is wrong so display in red
306 br
= wxBrush(*wxRED
, wxSOLID
);
307 hdc
->SetPen(*wxTRANSPARENT_PEN
);
309 hdc
->DrawRectangle(wxRectFromPRectangle(rc
));
312 void SurfaceImpl
::RoundedRectangle(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
) {
315 hdc
->DrawRoundedRectangle(wxRectFromPRectangle(rc
), 4);
318 void SurfaceImpl
::Ellipse(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
) {
321 hdc
->DrawEllipse(wxRectFromPRectangle(rc
));
324 void SurfaceImpl
::Copy(PRectangle rc
, Point from
, Surface
&surfaceSource
) {
325 wxRect r
= wxRectFromPRectangle(rc
);
326 hdc
->Blit(r
.x
, r
.y
, r
.width
, r
.height
,
327 ((SurfaceImpl
&)surfaceSource
).hdc
,
328 from
.x
, from
.y
, wxCOPY
);
331 void SurfaceImpl
::DrawTextNoClip(PRectangle rc
, Font
&font
, int ybase
,
332 const char *s
, int len
,
333 ColourAllocated fore
, ColourAllocated back
) {
335 hdc
->SetTextForeground(wxColourFromCA(fore
));
336 hdc
->SetTextBackground(wxColourFromCA(back
));
337 FillRectangle(rc
, back
);
339 // ybase is where the baseline should be, but wxWin uses the upper left
340 // corner, so I need to calculate the real position for the text...
341 hdc
->DrawText(stc2wx(s
, len
), rc
.left
, ybase
- font
.ascent
);
344 void SurfaceImpl
::DrawTextClipped(PRectangle rc
, Font
&font
, int ybase
,
345 const char *s
, int len
,
346 ColourAllocated fore
, ColourAllocated back
) {
348 hdc
->SetTextForeground(wxColourFromCA(fore
));
349 hdc
->SetTextBackground(wxColourFromCA(back
));
350 FillRectangle(rc
, back
);
351 hdc
->SetClippingRegion(wxRectFromPRectangle(rc
));
353 // see comments above
354 hdc
->DrawText(stc2wx(s
, len
), rc
.left
, ybase
- font
.ascent
);
355 hdc
->DestroyClippingRegion();
359 void SurfaceImpl
::DrawTextTransparent(PRectangle rc
, Font
&font
, int ybase
,
360 const char *s
, int len
,
361 ColourAllocated fore
) {
364 hdc
->SetTextForeground(wxColourFromCA(fore
));
365 hdc
->SetBackgroundMode(wxTRANSPARENT
);
367 // ybase is where the baseline should be, but wxWin uses the upper left
368 // corner, so I need to calculate the real position for the text...
369 hdc
->DrawText(stc2wx(s
, len
), rc
.left
, ybase
- font
.ascent
);
371 hdc
->SetBackgroundMode(wxSOLID
);
375 void SurfaceImpl
::MeasureWidths(Font
&font
, const char *s
, int len
, int *positions
) {
377 wxString str
= stc2wx(s
, len
);
382 hdc
->GetPartialTextExtents(str
, tpos
);
385 // Map the widths for UCS-2 characters back to the UTF-8 input string
386 // NOTE: I don't think this is right for when sizeof(wxChar) > 2, ie wxGTK2
387 // so figure it out and fix it!
390 while ((int)i
< len
) {
391 unsigned char uch
= (unsigned char)s
[i
];
392 positions
[i
++] = tpos
[ui
];
394 if (uch
< (0x80 + 0x40 + 0x20)) {
395 positions
[i
++] = tpos
[ui
];
397 positions
[i
++] = tpos
[ui
];
398 positions
[i
++] = tpos
[ui
];
405 // If not unicode then just use the widths we have
406 memcpy(positions
, tpos
.begin(), len
* sizeof(int));
411 int SurfaceImpl
::WidthText(Font
&font
, const char *s
, int len
) {
416 hdc
->GetTextExtent(stc2wx(s
, len
), &w
, &h
);
421 int SurfaceImpl
::WidthChar(Font
&font
, char ch
) {
425 char s
[2] = { ch
, 0 };
427 hdc
->GetTextExtent(stc2wx(s
, 1), &w
, &h
);
431 #define EXTENT_TEST wxT(" `~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
433 int SurfaceImpl
::Ascent(Font
&font
) {
436 hdc
->GetTextExtent(EXTENT_TEST
, &w
, &h
, &d
, &e
);
441 int SurfaceImpl
::Descent(Font
&font
) {
444 hdc
->GetTextExtent(EXTENT_TEST
, &w
, &h
, &d
, &e
);
448 int SurfaceImpl
::InternalLeading(Font
&WXUNUSED(font
)) {
452 int SurfaceImpl
::ExternalLeading(Font
&font
) {
455 hdc
->GetTextExtent(EXTENT_TEST
, &w
, &h
, &d
, &e
);
459 int SurfaceImpl
::Height(Font
&font
) {
461 return hdc
->GetCharHeight() + 1;
464 int SurfaceImpl
::AverageCharWidth(Font
&font
) {
466 return hdc
->GetCharWidth();
469 int SurfaceImpl
::SetPalette(Palette
*WXUNUSED(pal
), bool WXUNUSED(inBackGround
)) {
473 void SurfaceImpl
::SetClip(PRectangle rc
) {
474 hdc
->SetClippingRegion(wxRectFromPRectangle(rc
));
477 void SurfaceImpl
::FlushCachedState() {
480 void SurfaceImpl
::SetUnicodeMode(bool unicodeMode_
) {
481 unicodeMode
=unicodeMode_
;
484 void SurfaceImpl
::SetDBCSMode(int WXUNUSED(codePage
)) {
485 // dbcsMode = codePage == SC_CP_DBCS;
489 Surface
*Surface
::Allocate() {
490 return new SurfaceImpl
;
494 //----------------------------------------------------------------------
497 inline wxWindow
* GETWIN(WindowID id
) { return (wxWindow
*)id
; }
502 void Window
::Destroy() {
505 GETWIN(id
)->Destroy();
510 bool Window
::HasFocus() {
511 return wxWindow
::FindFocus() == GETWIN(id
);
514 PRectangle Window
::GetPosition() {
515 if (! id
) return PRectangle();
516 wxRect
rc(GETWIN(id
)->GetPosition(), GETWIN(id
)->GetSize());
517 return PRectangleFromwxRect(rc
);
520 void Window
::SetPosition(PRectangle rc
) {
521 wxRect r
= wxRectFromPRectangle(rc
);
522 GETWIN(id
)->SetSize(r
);
525 void Window
::SetPositionRelative(PRectangle rc
, Window
) {
526 SetPosition(rc
); // ????
529 PRectangle Window
::GetClientPosition() {
530 if (! id
) return PRectangle();
531 wxSize sz
= GETWIN(id
)->GetClientSize();
532 return PRectangle(0, 0, sz
.x
, sz
.y
);
535 void Window
::Show(bool show
) {
536 GETWIN(id
)->Show(show
);
539 void Window
::InvalidateAll() {
540 GETWIN(id
)->Refresh(false);
544 void Window
::InvalidateRectangle(PRectangle rc
) {
545 wxRect r
= wxRectFromPRectangle(rc
);
546 GETWIN(id
)->Refresh(false, &r
);
550 void Window
::SetFont(Font
&font
) {
551 GETWIN(id
)->SetFont(*((wxFont
*)font
.GetID()));
554 void Window
::SetCursor(Cursor curs
) {
559 cursorId
= wxCURSOR_IBEAM
;
562 cursorId
= wxCURSOR_ARROW
;
565 cursorId
= wxCURSOR_ARROW
; // ** no up arrow... wxCURSOR_UPARROW;
568 cursorId
= wxCURSOR_WAIT
;
571 cursorId
= wxCURSOR_SIZEWE
;
574 cursorId
= wxCURSOR_SIZENS
;
576 case cursorReverseArrow
:
577 cursorId
= wxCURSOR_RIGHT_ARROW
;
580 cursorId
= wxCURSOR_HAND
;
583 cursorId
= wxCURSOR_ARROW
;
587 wxCursor wc
= wxStockCursor(cursorId
) ;
589 wxCursor wc
= wxCursor(cursorId
) ;
591 GETWIN(id
)->SetCursor(wc
);
595 void Window
::SetTitle(const char *s
) {
596 GETWIN(id
)->SetTitle(stc2wx(s
));
600 //----------------------------------------------------------------------
601 // Helper classes for ListBox
604 // This is a simple subclass of wxListView that just resets focus to the
605 // parent when it gets it.
606 class wxSTCListBox
: public wxListView
{
608 wxSTCListBox(wxWindow
* parent
, wxWindowID id
,
609 const wxPoint
& pos
, const wxSize
& size
,
614 Hide(); // don't flicker as we move it around...
616 Create(parent
, id
, pos
, size
, style
);
620 void OnFocus(wxFocusEvent
& event
) {
621 GetParent()->SetFocus();
625 void OnKillFocus(wxFocusEvent
& WXUNUSED(event
)) {
626 // Do nothing. Prevents base class from resetting the colors...
630 // For some reason I don't understand yet the focus doesn't really leave
631 // the listbox like it should, so if we get any events feed them back to
633 void OnKeyDown(wxKeyEvent
& event
) {
634 GetGrandParent()->GetEventHandler()->ProcessEvent(event
);
636 void OnChar(wxKeyEvent
& event
) {
637 GetGrandParent()->GetEventHandler()->ProcessEvent(event
);
640 // And we need to force the focus back when being destroyed
642 GetGrandParent()->SetFocus();
647 DECLARE_EVENT_TABLE()
650 BEGIN_EVENT_TABLE(wxSTCListBox
, wxListView
)
651 EVT_SET_FOCUS( wxSTCListBox
::OnFocus
)
652 EVT_KILL_FOCUS(wxSTCListBox
::OnKillFocus
)
654 EVT_KEY_DOWN( wxSTCListBox
::OnKeyDown
)
655 EVT_CHAR( wxSTCListBox
::OnChar
)
661 #if wxUSE_POPUPWIN //-----------------------------------
662 #include <wx/popupwin.h>
666 // TODO: Refactor these two classes to have a common base (or a mix-in) to get
667 // rid of the code duplication. (Either that or convince somebody to
668 // implement wxPopupWindow for the Mac!!)
670 // In the meantime, be careful to duplicate any changes as needed...
673 // A popup window to place the wxSTCListBox upon
674 class wxSTCListBoxWin
: public wxPopupWindow
678 CallBackAction doubleClickAction
;
679 void* doubleClickActionData
;
681 wxSTCListBoxWin(wxWindow
* parent
, wxWindowID id
) :
682 wxPopupWindow(parent
, wxBORDER_NONE
)
684 SetBackgroundColour(*wxBLACK
); // for our simple border
686 lv
= new wxSTCListBox(parent
, id
, wxDefaultPosition
, wxDefaultSize
,
687 wxLC_REPORT
| wxLC_SINGLE_SEL
| wxLC_NO_HEADER
| wxBORDER_NONE
);
688 lv
->SetCursor(wxCursor(wxCURSOR_ARROW
));
689 lv
->InsertColumn(0, wxEmptyString
);
690 lv
->InsertColumn(1, wxEmptyString
);
692 // NOTE: We need to fool the wxListView into thinking that it has the
693 // focus so it will use the normal selection colour and will look
694 // "right" to the user. But since the wxPopupWindow or its children
695 // can't receive focus then we have to pull a fast one and temporarily
696 // parent the listctrl on the STC window and then call SetFocus and
697 // then reparent it back to the popup.
706 // Set position in client coords
707 virtual void DoSetSize(int x
, int y
,
708 int width
, int height
,
709 int sizeFlags
= wxSIZE_AUTO
) {
710 if (x
!= wxDefaultCoord
) {
711 GetParent()->ClientToScreen(&x
, NULL
);
713 if (y
!= wxDefaultCoord
) {
714 GetParent()->ClientToScreen(NULL
, &y
);
716 wxPopupWindow
::DoSetSize(x
, y
, width
, height
, sizeFlags
);
719 // return position as if it were in client coords
720 virtual void DoGetPosition( int *x
, int *y
) const {
722 wxPopupWindow
::DoGetPosition(&sx
, &sy
);
723 GetParent()->ScreenToClient(&sx
, &sy
);
730 if ( !wxPendingDelete
.Member(this) )
731 wxPendingDelete
.Append(this);
737 wxImageList
* il
= lv
->GetImageList(wxIMAGE_LIST_SMALL
);
740 il
->GetSize(0, w
, h
);
747 void SetDoubleClickAction(CallBackAction action
, void *data
) {
748 doubleClickAction
= action
;
749 doubleClickActionData
= data
;
753 void OnFocus(wxFocusEvent
& event
) {
754 GetParent()->SetFocus();
758 void OnSize(wxSizeEvent
& event
) {
760 wxSize sz
= GetSize();
763 lv
->SetSize(1, 1, sz
.x
, sz
.y
);
764 // reset the column widths
765 lv
->SetColumnWidth(0, IconWidth()+4);
766 lv
->SetColumnWidth(1, sz
.x
- 2 - lv
->GetColumnWidth(0) -
767 wxSystemSettings
::GetMetric(wxSYS_VSCROLL_X
));
771 void OnActivate(wxListEvent
& WXUNUSED(event
)) {
772 doubleClickAction(doubleClickActionData
);
775 wxListView
* GetLB() { return lv
; }
778 DECLARE_EVENT_TABLE()
782 BEGIN_EVENT_TABLE(wxSTCListBoxWin
, wxPopupWindow
)
783 EVT_SET_FOCUS ( wxSTCListBoxWin
::OnFocus
)
784 EVT_SIZE ( wxSTCListBoxWin
::OnSize
)
785 EVT_LIST_ITEM_ACTIVATED(wxID_ANY
, wxSTCListBoxWin
::OnActivate
)
790 #else // wxUSE_POPUPWIN -----------------------------------
792 // A normal window to place the wxSTCListBox upon.
793 class wxSTCListBoxWin
: public wxWindow
{
796 CallBackAction doubleClickAction
;
797 void* doubleClickActionData
;
799 wxSTCListBoxWin(wxWindow
* parent
, wxWindowID id
) :
800 wxWindow(parent
, id
, wxDefaultPosition
, wxSize(0,0), wxSIMPLE_BORDER
)
803 lv
= new wxSTCListBox(this, id
, wxDefaultPosition
, wxDefaultSize
,
804 wxLC_REPORT
| wxLC_SINGLE_SEL
| wxLC_NO_HEADER
| wxNO_BORDER
);
805 lv
->SetCursor(wxCursor(wxCURSOR_ARROW
));
806 lv
->InsertColumn(0, wxEmptyString
);
807 lv
->InsertColumn(1, wxEmptyString
);
809 // Eventhough we immediately reset the focus to the parent, this helps
810 // things to look right...
817 // On OSX and (possibly others) there can still be pending
818 // messages/events for the list control when Scintilla wants to
819 // close it, so do a pending delete of it instead of destroying
823 // The bottom edge of this window is not getting properly
824 // refreshed upon deletion, so help it out...
825 wxWindow
* p
= GetParent();
826 wxRect
r(GetPosition(), GetSize());
827 r
.SetHeight(r
.GetHeight()+1);
828 p
->Refresh(false, &r
);
830 if ( !wxPendingDelete
.Member(this) )
831 wxPendingDelete
.Append(this);
837 wxImageList
* il
= lv
->GetImageList(wxIMAGE_LIST_SMALL
);
840 il
->GetSize(0, w
, h
);
847 void SetDoubleClickAction(CallBackAction action
, void *data
) {
848 doubleClickAction
= action
;
849 doubleClickActionData
= data
;
853 void OnFocus(wxFocusEvent
& event
) {
854 GetParent()->SetFocus();
858 void OnSize(wxSizeEvent
& event
) {
860 wxSize sz
= GetClientSize();
862 // reset the column widths
863 lv
->SetColumnWidth(0, IconWidth()+4);
864 lv
->SetColumnWidth(1, sz
.x
- 2 - lv
->GetColumnWidth(0) -
865 wxSystemSettings
::GetMetric(wxSYS_VSCROLL_X
));
870 virtual bool Show(bool show
= true) {
871 bool rv
= wxWindow
::Show(show
);
872 GetParent()->Refresh(false);
877 void OnActivate(wxListEvent
& WXUNUSED(event
)) {
878 doubleClickAction(doubleClickActionData
);
881 wxListView
* GetLB() { return lv
; }
884 DECLARE_EVENT_TABLE()
888 BEGIN_EVENT_TABLE(wxSTCListBoxWin
, wxWindow
)
889 EVT_SET_FOCUS ( wxSTCListBoxWin
::OnFocus
)
890 EVT_SIZE ( wxSTCListBoxWin
::OnSize
)
891 EVT_LIST_ITEM_ACTIVATED(wxID_ANY
, wxSTCListBoxWin
::OnActivate
)
894 #endif // wxUSE_POPUPWIN -----------------------------------
897 inline wxSTCListBoxWin
* GETLBW(WindowID win
) {
898 return ((wxSTCListBoxWin
*)win
);
901 inline wxListView
* GETLB(WindowID win
) {
902 return GETLBW(win
)->GetLB();
905 //----------------------------------------------------------------------
907 class ListBoxImpl
: public ListBox
{
911 int desiredVisibleRows
;
914 wxImageList
* imgList
;
915 wxArrayInt
* imgTypeMap
;
921 virtual void SetFont(Font
&font
);
922 virtual void Create(Window
&parent
, int ctrlID
, int lineHeight_
, bool unicodeMode_
);
923 virtual void SetAverageCharWidth(int width
);
924 virtual void SetVisibleRows(int rows
);
925 virtual PRectangle
GetDesiredRect();
926 virtual int CaretFromEdge();
927 virtual void Clear();
928 virtual void Append(char *s
, int type
= -1);
929 virtual int Length();
930 virtual void Select(int n
);
931 virtual int GetSelection();
932 virtual int Find(const char *prefix
);
933 virtual void GetValue(int n
, char *value
, int len
);
934 virtual void RegisterImage(int type
, const char *xpm_data
);
935 virtual void ClearRegisteredImages();
936 virtual void SetDoubleClickAction(CallBackAction
, void *);
941 ListBoxImpl
::ListBoxImpl()
942 : lineHeight(10), unicodeMode(false),
943 desiredVisibleRows(5), aveCharWidth(8), maxStrWidth(0),
944 imgList(NULL
), imgTypeMap(NULL
)
948 ListBoxImpl
::~ListBoxImpl() {
960 void ListBoxImpl
::SetFont(Font
&font
) {
961 GETLB(id
)->SetFont(*((wxFont
*)font
.GetID()));
965 void ListBoxImpl
::Create(Window
&parent
, int ctrlID
, int lineHeight_
, bool unicodeMode_
) {
966 lineHeight
= lineHeight_
;
967 unicodeMode
= unicodeMode_
;
969 id
= new wxSTCListBoxWin(GETWIN(parent
.GetID()), ctrlID
);
971 GETLB(id
)->SetImageList(imgList
, wxIMAGE_LIST_SMALL
);
975 void ListBoxImpl
::SetAverageCharWidth(int width
) {
976 aveCharWidth
= width
;
980 void ListBoxImpl
::SetVisibleRows(int rows
) {
981 desiredVisibleRows
= rows
;
985 PRectangle ListBoxImpl
::GetDesiredRect() {
986 // wxListCtrl doesn't have a DoGetBestSize, so instead we kept track of
987 // the max size in Append and calculate it here...
988 int maxw
= maxStrWidth
;
991 // give it a default if there are no lines, and/or add a bit more
992 if (maxw
== 0) maxw
= 100;
993 maxw
+= aveCharWidth
* 3 +
994 GETLBW(id
)->IconWidth() + wxSystemSettings
::GetMetric(wxSYS_VSCROLL_X
);
998 // estimate a desired height
999 int count
= GETLB(id
)->GetItemCount();
1002 GETLB(id
)->GetItemRect(0, rect
);
1003 maxh
= count
* rect
.GetHeight();
1004 if (maxh
> 140) // TODO: Use desiredVisibleRows??
1007 // Try to make the size an exact multiple of some number of lines
1008 int lines
= maxh
/ rect
.GetHeight();
1009 maxh
= (lines
+ 1) * rect
.GetHeight() + 2;
1023 int ListBoxImpl
::CaretFromEdge() {
1024 return 4 + GETLBW(id
)->IconWidth();
1028 void ListBoxImpl
::Clear() {
1029 GETLB(id
)->DeleteAllItems();
1033 void ListBoxImpl
::Append(char *s
, int type
) {
1034 wxString text
= stc2wx(s
);
1035 long count
= GETLB(id
)->GetItemCount();
1036 long itemID
= GETLB(id
)->InsertItem(count
, wxEmptyString
);
1037 GETLB(id
)->SetItem(itemID
, 1, text
);
1039 GETLB(id
)->GetTextExtent(text
, &itemWidth
, NULL
);
1040 maxStrWidth
= wxMax(maxStrWidth
, itemWidth
);
1042 wxCHECK_RET(imgTypeMap
, wxT("Unexpected NULL imgTypeMap"));
1043 long idx
= imgTypeMap
->Item(type
);
1044 GETLB(id
)->SetItemImage(itemID
, idx
, idx
);
1049 int ListBoxImpl
::Length() {
1050 return GETLB(id
)->GetItemCount();
1054 void ListBoxImpl
::Select(int n
) {
1060 GETLB(id
)->Focus(n
);
1061 GETLB(id
)->Select(n
, select
);
1065 int ListBoxImpl
::GetSelection() {
1066 return GETLB(id
)->GetFirstSelected();
1070 int ListBoxImpl
::Find(const char *WXUNUSED(prefix
)) {
1076 void ListBoxImpl
::GetValue(int n
, char *value
, int len
) {
1080 item
.SetMask(wxLIST_MASK_TEXT
);
1081 GETLB(id
)->GetItem(item
);
1082 strncpy(value
, wx2stc(item
.GetText()), len
);
1083 value
[len
-1] = '\0';
1087 void ListBoxImpl
::RegisterImage(int type
, const char *xpm_data
) {
1088 wxMemoryInputStream
stream(xpm_data
, strlen(xpm_data
)+1);
1089 wxImage
img(stream
, wxBITMAP_TYPE_XPM
);
1093 // assumes all images are the same size
1094 imgList
= new wxImageList(bmp
.GetWidth(), bmp
.GetHeight(), true);
1095 imgTypeMap
= new wxArrayInt
;
1098 int idx
= imgList
->Add(bmp
);
1100 // do we need to extend the mapping array?
1101 wxArrayInt
& itm
= *imgTypeMap
;
1102 if ( itm
.GetCount() < (size_t)type
+1)
1103 itm
.Add(-1, type
- itm
.GetCount() + 1);
1105 // Add an item that maps type to the image index
1109 void ListBoxImpl
::ClearRegisteredImages() {
1119 GETLB(id
)->SetImageList(NULL
, wxIMAGE_LIST_SMALL
);
1123 void ListBoxImpl
::SetDoubleClickAction(CallBackAction action
, void *data
) {
1124 GETLBW(id
)->SetDoubleClickAction(action
, data
);
1129 ListBox
::ListBox() {
1132 ListBox
::~ListBox() {
1135 ListBox
*ListBox
::Allocate() {
1136 return new ListBoxImpl();
1139 //----------------------------------------------------------------------
1141 Menu
::Menu() : id(0) {
1144 void Menu
::CreatePopUp() {
1149 void Menu
::Destroy() {
1155 void Menu
::Show(Point pt
, Window
&w
) {
1156 GETWIN(w
.GetID())->PopupMenu((wxMenu
*)id
, pt
.x
- 4, pt
.y
);
1160 //----------------------------------------------------------------------
1162 DynamicLibrary
*DynamicLibrary
::Load(const char *WXUNUSED(modulePath
)) {
1163 wxFAIL_MSG(wxT("Dynamic lexer loading not implemented yet"));
1167 //----------------------------------------------------------------------
1169 ColourDesired Platform
::Chrome() {
1171 c
= wxSystemSettings
::GetColour(wxSYS_COLOUR_3DFACE
);
1172 return ColourDesired(c
.Red(), c
.Green(), c
.Blue());
1175 ColourDesired Platform
::ChromeHighlight() {
1177 c
= wxSystemSettings
::GetColour(wxSYS_COLOUR_3DHIGHLIGHT
);
1178 return ColourDesired(c
.Red(), c
.Green(), c
.Blue());
1181 const char *Platform
::DefaultFont() {
1182 static char buf
[128];
1183 strcpy(buf
, wxNORMAL_FONT
->GetFaceName().mbc_str());
1187 int Platform
::DefaultFontSize() {
1188 return wxNORMAL_FONT
->GetPointSize();
1191 unsigned int Platform
::DoubleClickTime() {
1192 return 500; // **** ::GetDoubleClickTime();
1195 bool Platform
::MouseButtonBounce() {
1198 void Platform
::DebugDisplay(const char *s
) {
1199 wxLogDebug(stc2wx(s
));
1202 bool Platform
::IsKeyDown(int WXUNUSED(key
)) {
1203 return false; // I don't think we'll need this.
1206 long Platform
::SendScintilla(WindowID w
,
1208 unsigned long wParam
,
1211 wxStyledTextCtrl
* stc
= (wxStyledTextCtrl
*)w
;
1212 return stc
->SendMsg(msg
, wParam
, lParam
);
1215 long Platform
::SendScintillaPointer(WindowID w
,
1217 unsigned long wParam
,
1220 wxStyledTextCtrl
* stc
= (wxStyledTextCtrl
*)w
;
1221 return stc
->SendMsg(msg
, wParam
, (long)lParam
);
1225 // These are utility functions not really tied to a platform
1227 int Platform
::Minimum(int a
, int b
) {
1234 int Platform
::Maximum(int a
, int b
) {
1243 void Platform
::DebugPrintf(const char *format
, ...) {
1247 va_start(pArguments
, format
);
1248 vsprintf(buffer
,format
,pArguments
);
1250 Platform
::DebugDisplay(buffer
);
1255 static bool assertionPopUps
= true;
1257 bool Platform
::ShowAssertionPopUps(bool assertionPopUps_
) {
1258 bool ret
= assertionPopUps
;
1259 assertionPopUps
= assertionPopUps_
;
1263 void Platform
::Assert(const char *c
, const char *file
, int line
) {
1265 sprintf(buffer
, "Assertion [%s] failed at %s %d", c
, file
, line
);
1266 if (assertionPopUps
) {
1268 wxMessageBox(stc2wx(buffer
),
1269 wxT("Assertion failure"),
1270 wxICON_HAND
| wxOK
);
1271 // if (idButton == IDRETRY) {
1273 // } else if (idButton == IDIGNORE) {
1279 strcat(buffer
, "\r\n");
1280 Platform
::DebugDisplay(buffer
);
1286 int Platform
::Clamp(int val
, int minVal
, int maxVal
) {
1295 bool Platform
::IsDBCSLeadByte(int WXUNUSED(codePage
), char WXUNUSED(ch
)) {
1299 int Platform
::DBCSCharLength(int WXUNUSED(codePage
), const char *WXUNUSED(s
)) {
1303 int Platform
::DBCSCharMaxLength() {
1308 //----------------------------------------------------------------------
1310 ElapsedTime
::ElapsedTime() {
1314 double ElapsedTime
::Duration(bool reset
) {
1315 double result
= wxGetElapsedTime(reset
);
1321 //----------------------------------------------------------------------
1325 #include "UniConversion.h"
1327 // Convert using Scintilla's functions instead of wx's, Scintilla's are more
1328 // forgiving and won't assert...
1330 wxString
stc2wx(const char* str
, size_t len
)
1333 return wxEmptyString
;
1335 size_t wclen
= UCS2Length(str
, len
);
1336 wxWCharBuffer
buffer(wclen
+1);
1338 size_t actualLen
= UCS2FromUTF8(str
, len
, buffer
.data(), wclen
+1);
1339 return wxString(buffer
.data(), actualLen
);
1344 wxString
stc2wx(const char* str
)
1346 return stc2wx(str
, strlen(str
));
1350 const wxWX2MBbuf
wx2stc(const wxString
& str
)
1352 const wchar_t* wcstr
= str
.c_str();
1353 size_t wclen
= str
.length();
1354 size_t len
= UTF8Length(wcstr
, wclen
);
1356 wxCharBuffer
buffer(len
+1);
1357 UTF8FromUCS2(wcstr
, wclen
, buffer
.data(), len
);
1359 // TODO check NULL termination!!