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"
15 #include "wx/tokenzr.h"
19 #include "wx/stc/stc.h"
23 Point
Point::FromLong(long lpoint
) {
24 return Point(lpoint
& 0xFFFF, lpoint
>> 16);
27 wxRect
wxRectFromPRectangle(PRectangle prc
) {
28 wxRect
r(prc
.left
, prc
.top
,
29 prc
.Width(), prc
.Height());
33 PRectangle
PRectangleFromwxRect(wxRect rc
) {
34 return PRectangle(rc
.GetLeft(), rc
.GetTop(),
35 rc
.GetRight()+1, rc
.GetBottom()+1);
38 wxColour
wxColourFromCA(const ColourAllocated
& ca
) {
39 ColourDesired
cd(ca
.AsLong());
40 return wxColour((unsigned char)cd
.GetRed(),
41 (unsigned char)cd
.GetGreen(),
42 (unsigned char)cd
.GetBlue());
45 //----------------------------------------------------------------------
49 allowRealization
= false;
56 void Palette::Release() {
60 // This method either adds a colour to the list of wanted colours (want==true)
61 // or retrieves the allocated colour back to the ColourPair.
62 // This is one method to make it easier to keep the code for wanting and retrieving in sync.
63 void Palette::WantFind(ColourPair
&cp
, bool want
) {
65 for (int i
=0; i
< used
; i
++) {
66 if (entries
[i
].desired
== cp
.desired
)
70 if (used
< numEntries
) {
71 entries
[used
].desired
= cp
.desired
;
72 entries
[used
].allocated
.Set(cp
.desired
.AsLong());
76 for (int i
=0; i
< used
; i
++) {
77 if (entries
[i
].desired
== cp
.desired
) {
78 cp
.allocated
= entries
[i
].allocated
;
82 cp
.allocated
.Set(cp
.desired
.AsLong());
86 void Palette::Allocate(Window
&) {
87 if (allowRealization
) {
92 //----------------------------------------------------------------------
102 void Font::Create(const char *faceName
, int characterSet
, int size
, bool bold
, bool italic
, bool extraFontFlag
) {
106 // The minus one is done because since Scintilla uses SC_SHARSET_DEFAULT
107 // internally and we need to have wxFONENCODING_DEFAULT == SC_SHARSET_DEFAULT
108 // so we adjust the encoding before passing it to Scintilla. See also
109 // wxStyledTextCtrl::StyleSetCharacterSet
110 wxFontEncoding encoding
= (wxFontEncoding
)(characterSet
-1);
112 wxFontEncodingArray ea
= wxEncodingConverter::GetPlatformEquivalents(encoding
);
116 wxFont
* font
= new wxFont(size
,
118 italic
? wxITALIC
: wxNORMAL
,
119 bold
? wxBOLD
: wxNORMAL
,
123 font
->SetNoAntiAliasing(!extraFontFlag
);
128 void Font::Release() {
134 //----------------------------------------------------------------------
136 class SurfaceImpl
: public Surface
{
149 virtual void Init(WindowID wid
);
150 virtual void Init(SurfaceID sid
, WindowID wid
);
151 virtual void InitPixMap(int width
, int height
, Surface
*surface_
, WindowID wid
);
153 virtual void Release();
154 virtual bool Initialised();
155 virtual void PenColour(ColourAllocated fore
);
156 virtual int LogPixelsY();
157 virtual int DeviceHeightFont(int points
);
158 virtual void MoveTo(int x_
, int y_
);
159 virtual void LineTo(int x_
, int y_
);
160 virtual void Polygon(Point
*pts
, int npts
, ColourAllocated fore
, ColourAllocated back
);
161 virtual void RectangleDraw(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
);
162 virtual void FillRectangle(PRectangle rc
, ColourAllocated back
);
163 virtual void FillRectangle(PRectangle rc
, Surface
&surfacePattern
);
164 virtual void RoundedRectangle(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
);
165 virtual void Ellipse(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
);
166 virtual void Copy(PRectangle rc
, Point from
, Surface
&surfaceSource
);
168 virtual void DrawTextNoClip(PRectangle rc
, Font
&font_
, int ybase
, const char *s
, int len
, ColourAllocated fore
, ColourAllocated back
);
169 virtual void DrawTextClipped(PRectangle rc
, Font
&font_
, int ybase
, const char *s
, int len
, ColourAllocated fore
, ColourAllocated back
);
170 virtual void DrawTextTransparent(PRectangle rc
, Font
&font_
, int ybase
, const char *s
, int len
, ColourAllocated fore
);
171 virtual void MeasureWidths(Font
&font_
, const char *s
, int len
, int *positions
);
172 virtual int WidthText(Font
&font_
, const char *s
, int len
);
173 virtual int WidthChar(Font
&font_
, char ch
);
174 virtual int Ascent(Font
&font_
);
175 virtual int Descent(Font
&font_
);
176 virtual int InternalLeading(Font
&font_
);
177 virtual int ExternalLeading(Font
&font_
);
178 virtual int Height(Font
&font_
);
179 virtual int AverageCharWidth(Font
&font_
);
181 virtual int SetPalette(Palette
*pal
, bool inBackGround
);
182 virtual void SetClip(PRectangle rc
);
183 virtual void FlushCachedState();
185 virtual void SetUnicodeMode(bool unicodeMode_
);
186 virtual void SetDBCSMode(int codePage
);
188 void BrushColour(ColourAllocated back
);
189 void SetFont(Font
&font_
);
194 SurfaceImpl::SurfaceImpl() :
195 hdc(0), hdcOwned(0), bitmap(0),
196 x(0), y(0), unicodeMode(0)
199 SurfaceImpl::~SurfaceImpl() {
203 void SurfaceImpl::Init(WindowID wid
) {
206 hdc
= new wxMemoryDC();
209 // On Mac and GTK the DC is not really valid until it has a bitmap
210 // selected into it. So instead of just creating the DC with no bitmap,
211 // go ahead and give it one.
212 InitPixMap(1,1,NULL
,wid
);
216 void SurfaceImpl::Init(SurfaceID hdc_
, WindowID
) {
221 void SurfaceImpl::InitPixMap(int width
, int height
, Surface
*WXUNUSED(surface_
), WindowID
) {
223 hdc
= new wxMemoryDC();
225 if (width
< 1) width
= 1;
226 if (height
< 1) height
= 1;
227 bitmap
= new wxBitmap(width
, height
);
228 ((wxMemoryDC
*)hdc
)->SelectObject(*bitmap
);
232 void SurfaceImpl::Release() {
234 ((wxMemoryDC
*)hdc
)->SelectObject(wxNullBitmap
);
246 bool SurfaceImpl::Initialised() {
251 void SurfaceImpl::PenColour(ColourAllocated fore
) {
252 hdc
->SetPen(wxPen(wxColourFromCA(fore
), 1, wxSOLID
));
255 void SurfaceImpl::BrushColour(ColourAllocated back
) {
256 hdc
->SetBrush(wxBrush(wxColourFromCA(back
), wxSOLID
));
259 void SurfaceImpl::SetFont(Font
&font_
) {
261 hdc
->SetFont(*((wxFont
*)font_
.GetID()));
265 int SurfaceImpl::LogPixelsY() {
266 return hdc
->GetPPI().y
;
269 int SurfaceImpl::DeviceHeightFont(int points
) {
273 void SurfaceImpl::MoveTo(int x_
, int y_
) {
278 void SurfaceImpl::LineTo(int x_
, int y_
) {
279 hdc
->DrawLine(x
,y
, x_
,y_
);
284 void SurfaceImpl::Polygon(Point
*pts
, int npts
, ColourAllocated fore
, ColourAllocated back
) {
287 hdc
->DrawPolygon(npts
, (wxPoint
*)pts
);
290 void SurfaceImpl::RectangleDraw(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
) {
293 hdc
->DrawRectangle(wxRectFromPRectangle(rc
));
296 void SurfaceImpl::FillRectangle(PRectangle rc
, ColourAllocated back
) {
298 hdc
->SetPen(*wxTRANSPARENT_PEN
);
299 hdc
->DrawRectangle(wxRectFromPRectangle(rc
));
302 void SurfaceImpl::FillRectangle(PRectangle rc
, Surface
&surfacePattern
) {
304 if (((SurfaceImpl
&)surfacePattern
).bitmap
)
305 br
= wxBrush(*((SurfaceImpl
&)surfacePattern
).bitmap
);
306 else // Something is wrong so display in red
307 br
= wxBrush(*wxRED
, wxSOLID
);
308 hdc
->SetPen(*wxTRANSPARENT_PEN
);
310 hdc
->DrawRectangle(wxRectFromPRectangle(rc
));
313 void SurfaceImpl::RoundedRectangle(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
) {
316 hdc
->DrawRoundedRectangle(wxRectFromPRectangle(rc
), 4);
319 void SurfaceImpl::Ellipse(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
) {
322 hdc
->DrawEllipse(wxRectFromPRectangle(rc
));
325 void SurfaceImpl::Copy(PRectangle rc
, Point from
, Surface
&surfaceSource
) {
326 wxRect r
= wxRectFromPRectangle(rc
);
327 hdc
->Blit(r
.x
, r
.y
, r
.width
, r
.height
,
328 ((SurfaceImpl
&)surfaceSource
).hdc
,
329 from
.x
, from
.y
, wxCOPY
);
332 void SurfaceImpl::DrawTextNoClip(PRectangle rc
, Font
&font
, int ybase
,
333 const char *s
, int len
,
334 ColourAllocated fore
, ColourAllocated back
) {
336 hdc
->SetTextForeground(wxColourFromCA(fore
));
337 hdc
->SetTextBackground(wxColourFromCA(back
));
338 FillRectangle(rc
, back
);
340 // ybase is where the baseline should be, but wxWin uses the upper left
341 // corner, so I need to calculate the real position for the text...
342 hdc
->DrawText(stc2wx(s
, len
), rc
.left
, ybase
- font
.ascent
);
345 void SurfaceImpl::DrawTextClipped(PRectangle rc
, Font
&font
, int ybase
,
346 const char *s
, int len
,
347 ColourAllocated fore
, ColourAllocated back
) {
349 hdc
->SetTextForeground(wxColourFromCA(fore
));
350 hdc
->SetTextBackground(wxColourFromCA(back
));
351 FillRectangle(rc
, back
);
352 hdc
->SetClippingRegion(wxRectFromPRectangle(rc
));
354 // see comments above
355 hdc
->DrawText(stc2wx(s
, len
), rc
.left
, ybase
- font
.ascent
);
356 hdc
->DestroyClippingRegion();
360 void SurfaceImpl::DrawTextTransparent(PRectangle rc
, Font
&font
, int ybase
,
361 const char *s
, int len
,
362 ColourAllocated fore
) {
365 hdc
->SetTextForeground(wxColourFromCA(fore
));
366 hdc
->SetBackgroundMode(wxTRANSPARENT
);
368 // ybase is where the baseline should be, but wxWin uses the upper left
369 // corner, so I need to calculate the real position for the text...
370 hdc
->DrawText(stc2wx(s
, len
), rc
.left
, ybase
- font
.ascent
);
372 hdc
->SetBackgroundMode(wxSOLID
);
376 void SurfaceImpl::MeasureWidths(Font
&font
, const char *s
, int len
, int *positions
) {
378 wxString str
= stc2wx(s
, len
);
383 hdc
->GetPartialTextExtents(str
, tpos
);
386 // Map the widths for UCS-2 characters back to the UTF-8 input string
387 // NOTE: I don't think this is right for when sizeof(wxChar) > 2, ie wxGTK2
388 // so figure it out and fix it!
391 while ((int)i
< len
) {
392 unsigned char uch
= (unsigned char)s
[i
];
393 positions
[i
++] = tpos
[ui
];
395 if (uch
< (0x80 + 0x40 + 0x20)) {
396 positions
[i
++] = tpos
[ui
];
398 positions
[i
++] = tpos
[ui
];
399 positions
[i
++] = tpos
[ui
];
406 // If not unicode then just use the widths we have
408 std::copy(tpos
.begin(), tpos
.end(), positions
);
410 memcpy(positions
, tpos
.begin(), len
* sizeof(int));
416 int SurfaceImpl::WidthText(Font
&font
, const char *s
, int len
) {
421 hdc
->GetTextExtent(stc2wx(s
, len
), &w
, &h
);
426 int SurfaceImpl::WidthChar(Font
&font
, char ch
) {
430 char s
[2] = { ch
, 0 };
432 hdc
->GetTextExtent(stc2wx(s
, 1), &w
, &h
);
436 #define EXTENT_TEST wxT(" `~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
438 int SurfaceImpl::Ascent(Font
&font
) {
441 hdc
->GetTextExtent(EXTENT_TEST
, &w
, &h
, &d
, &e
);
446 int SurfaceImpl::Descent(Font
&font
) {
449 hdc
->GetTextExtent(EXTENT_TEST
, &w
, &h
, &d
, &e
);
453 int SurfaceImpl::InternalLeading(Font
&WXUNUSED(font
)) {
457 int SurfaceImpl::ExternalLeading(Font
&font
) {
460 hdc
->GetTextExtent(EXTENT_TEST
, &w
, &h
, &d
, &e
);
464 int SurfaceImpl::Height(Font
&font
) {
466 return hdc
->GetCharHeight() + 1;
469 int SurfaceImpl::AverageCharWidth(Font
&font
) {
471 return hdc
->GetCharWidth();
474 int SurfaceImpl::SetPalette(Palette
*WXUNUSED(pal
), bool WXUNUSED(inBackGround
)) {
478 void SurfaceImpl::SetClip(PRectangle rc
) {
479 hdc
->SetClippingRegion(wxRectFromPRectangle(rc
));
482 void SurfaceImpl::FlushCachedState() {
485 void SurfaceImpl::SetUnicodeMode(bool unicodeMode_
) {
486 unicodeMode
=unicodeMode_
;
489 void SurfaceImpl::SetDBCSMode(int WXUNUSED(codePage
)) {
490 // dbcsMode = codePage == SC_CP_DBCS;
494 Surface
*Surface::Allocate() {
495 return new SurfaceImpl
;
499 //----------------------------------------------------------------------
502 inline wxWindow
* GETWIN(WindowID id
) { return (wxWindow
*)id
; }
507 void Window::Destroy() {
510 GETWIN(id
)->Destroy();
515 bool Window::HasFocus() {
516 return wxWindow::FindFocus() == GETWIN(id
);
519 PRectangle
Window::GetPosition() {
520 if (! id
) return PRectangle();
521 wxRect
rc(GETWIN(id
)->GetPosition(), GETWIN(id
)->GetSize());
522 return PRectangleFromwxRect(rc
);
525 void Window::SetPosition(PRectangle rc
) {
526 wxRect r
= wxRectFromPRectangle(rc
);
527 GETWIN(id
)->SetSize(r
);
530 void Window::SetPositionRelative(PRectangle rc
, Window
) {
531 SetPosition(rc
); // ????
534 PRectangle
Window::GetClientPosition() {
535 if (! id
) return PRectangle();
536 wxSize sz
= GETWIN(id
)->GetClientSize();
537 return PRectangle(0, 0, sz
.x
, sz
.y
);
540 void Window::Show(bool show
) {
541 GETWIN(id
)->Show(show
);
544 void Window::InvalidateAll() {
545 GETWIN(id
)->Refresh(false);
549 void Window::InvalidateRectangle(PRectangle rc
) {
550 wxRect r
= wxRectFromPRectangle(rc
);
551 GETWIN(id
)->Refresh(false, &r
);
555 void Window::SetFont(Font
&font
) {
556 GETWIN(id
)->SetFont(*((wxFont
*)font
.GetID()));
559 void Window::SetCursor(Cursor curs
) {
564 cursorId
= wxCURSOR_IBEAM
;
567 cursorId
= wxCURSOR_ARROW
;
570 cursorId
= wxCURSOR_ARROW
; // ** no up arrow... wxCURSOR_UPARROW;
573 cursorId
= wxCURSOR_WAIT
;
576 cursorId
= wxCURSOR_SIZEWE
;
579 cursorId
= wxCURSOR_SIZENS
;
581 case cursorReverseArrow
:
582 cursorId
= wxCURSOR_RIGHT_ARROW
;
585 cursorId
= wxCURSOR_HAND
;
588 cursorId
= wxCURSOR_ARROW
;
592 wxCursor wc
= wxStockCursor(cursorId
) ;
594 wxCursor wc
= wxCursor(cursorId
) ;
596 if(curs
!= cursorLast
)
598 GETWIN(id
)->SetCursor(wc
);
604 void Window::SetTitle(const char *s
) {
605 GETWIN(id
)->SetLabel(stc2wx(s
));
609 //----------------------------------------------------------------------
610 // Helper classes for ListBox
613 // This is a simple subclass of wxListView that just resets focus to the
614 // parent when it gets it.
615 class wxSTCListBox
: public wxListView
{
617 wxSTCListBox(wxWindow
* parent
, wxWindowID id
,
618 const wxPoint
& pos
, const wxSize
& size
,
623 Hide(); // don't flicker as we move it around...
625 Create(parent
, id
, pos
, size
, style
);
629 void OnFocus(wxFocusEvent
& event
) {
630 GetParent()->SetFocus();
634 void OnKillFocus(wxFocusEvent
& WXUNUSED(event
)) {
635 // Do nothing. Prevents base class from resetting the colors...
639 // For some reason I don't understand yet the focus doesn't really leave
640 // the listbox like it should, so if we get any events feed them back to
642 void OnKeyDown(wxKeyEvent
& event
) {
643 GetGrandParent()->GetEventHandler()->ProcessEvent(event
);
645 void OnChar(wxKeyEvent
& event
) {
646 GetGrandParent()->GetEventHandler()->ProcessEvent(event
);
649 // And we need to force the focus back when being destroyed
651 GetGrandParent()->SetFocus();
656 DECLARE_EVENT_TABLE()
659 BEGIN_EVENT_TABLE(wxSTCListBox
, wxListView
)
660 EVT_SET_FOCUS( wxSTCListBox::OnFocus
)
661 EVT_KILL_FOCUS(wxSTCListBox::OnKillFocus
)
663 EVT_KEY_DOWN( wxSTCListBox::OnKeyDown
)
664 EVT_CHAR( wxSTCListBox::OnChar
)
670 #if wxUSE_POPUPWIN //-----------------------------------
671 #include <wx/popupwin.h>
675 // TODO: Refactor these two classes to have a common base (or a mix-in) to get
676 // rid of the code duplication. (Either that or convince somebody to
677 // implement wxPopupWindow for the Mac!!)
679 // In the meantime, be careful to duplicate any changes as needed...
682 // A popup window to place the wxSTCListBox upon
683 class wxSTCListBoxWin
: public wxPopupWindow
687 CallBackAction doubleClickAction
;
688 void* doubleClickActionData
;
690 wxSTCListBoxWin(wxWindow
* parent
, wxWindowID id
, Point
WXUNUSED(location
)) :
691 wxPopupWindow(parent
, wxBORDER_NONE
)
693 SetBackgroundColour(*wxBLACK
); // for our simple border
695 lv
= new wxSTCListBox(parent
, id
, wxDefaultPosition
, wxDefaultSize
,
696 wxLC_REPORT
| wxLC_SINGLE_SEL
| wxLC_NO_HEADER
| wxBORDER_NONE
);
697 lv
->SetCursor(wxCursor(wxCURSOR_ARROW
));
698 lv
->InsertColumn(0, wxEmptyString
);
699 lv
->InsertColumn(1, wxEmptyString
);
701 // NOTE: We need to fool the wxListView into thinking that it has the
702 // focus so it will use the normal selection colour and will look
703 // "right" to the user. But since the wxPopupWindow or its children
704 // can't receive focus then we have to pull a fast one and temporarily
705 // parent the listctrl on the STC window and then call SetFocus and
706 // then reparent it back to the popup.
715 // Set position in client coords
716 virtual void DoSetSize(int x
, int y
,
717 int width
, int height
,
718 int sizeFlags
= wxSIZE_AUTO
) {
719 if (x
!= wxDefaultCoord
) {
720 GetParent()->ClientToScreen(&x
, NULL
);
722 if (y
!= wxDefaultCoord
) {
723 GetParent()->ClientToScreen(NULL
, &y
);
725 wxPopupWindow::DoSetSize(x
, y
, width
, height
, sizeFlags
);
728 // return position as if it were in client coords
729 virtual void DoGetPosition( int *x
, int *y
) const {
731 wxPopupWindow::DoGetPosition(&sx
, &sy
);
732 GetParent()->ScreenToClient(&sx
, &sy
);
739 if ( !wxPendingDelete
.Member(this) )
740 wxPendingDelete
.Append(this);
746 wxImageList
* il
= lv
->GetImageList(wxIMAGE_LIST_SMALL
);
749 il
->GetSize(0, w
, h
);
756 void SetDoubleClickAction(CallBackAction action
, void *data
) {
757 doubleClickAction
= action
;
758 doubleClickActionData
= data
;
762 void OnFocus(wxFocusEvent
& event
) {
763 GetParent()->SetFocus();
767 void OnSize(wxSizeEvent
& event
) {
769 wxSize sz
= GetSize();
772 lv
->SetSize(1, 1, sz
.x
, sz
.y
);
773 // reset the column widths
774 lv
->SetColumnWidth(0, IconWidth()+4);
775 lv
->SetColumnWidth(1, sz
.x
- 2 - lv
->GetColumnWidth(0) -
776 wxSystemSettings::GetMetric(wxSYS_VSCROLL_X
));
780 void OnActivate(wxListEvent
& WXUNUSED(event
)) {
781 doubleClickAction(doubleClickActionData
);
784 wxListView
* GetLB() { return lv
; }
787 DECLARE_EVENT_TABLE()
791 BEGIN_EVENT_TABLE(wxSTCListBoxWin
, wxPopupWindow
)
792 EVT_SET_FOCUS ( wxSTCListBoxWin::OnFocus
)
793 EVT_SIZE ( wxSTCListBoxWin::OnSize
)
794 EVT_LIST_ITEM_ACTIVATED(wxID_ANY
, wxSTCListBoxWin::OnActivate
)
799 #else // wxUSE_POPUPWIN -----------------------------------
801 // A normal window to place the wxSTCListBox upon.
802 class wxSTCListBoxWin
: public wxWindow
{
805 CallBackAction doubleClickAction
;
806 void* doubleClickActionData
;
808 wxSTCListBoxWin(wxWindow
* parent
, wxWindowID id
, Point location
) :
809 wxWindow(parent
, id
, wxPoint(location
.x
, location
.y
), wxSize(0,0), wxSIMPLE_BORDER
)
812 lv
= new wxSTCListBox(this, id
, wxDefaultPosition
, wxDefaultSize
,
813 wxLC_REPORT
| wxLC_SINGLE_SEL
| wxLC_NO_HEADER
| wxNO_BORDER
);
814 lv
->SetCursor(wxCursor(wxCURSOR_ARROW
));
815 lv
->InsertColumn(0, wxEmptyString
);
816 lv
->InsertColumn(1, wxEmptyString
);
818 // Eventhough we immediately reset the focus to the parent, this helps
819 // things to look right...
826 // On OSX and (possibly others) there can still be pending
827 // messages/events for the list control when Scintilla wants to
828 // close it, so do a pending delete of it instead of destroying
832 // The bottom edge of this window is not getting properly
833 // refreshed upon deletion, so help it out...
834 wxWindow
* p
= GetParent();
835 wxRect
r(GetPosition(), GetSize());
836 r
.SetHeight(r
.GetHeight()+1);
837 p
->Refresh(false, &r
);
839 if ( !wxPendingDelete
.Member(this) )
840 wxPendingDelete
.Append(this);
846 wxImageList
* il
= lv
->GetImageList(wxIMAGE_LIST_SMALL
);
849 il
->GetSize(0, w
, h
);
856 void SetDoubleClickAction(CallBackAction action
, void *data
) {
857 doubleClickAction
= action
;
858 doubleClickActionData
= data
;
862 void OnFocus(wxFocusEvent
& event
) {
863 GetParent()->SetFocus();
867 void OnSize(wxSizeEvent
& event
) {
869 wxSize sz
= GetClientSize();
871 // reset the column widths
872 lv
->SetColumnWidth(0, IconWidth()+4);
873 lv
->SetColumnWidth(1, sz
.x
- 2 - lv
->GetColumnWidth(0) -
874 wxSystemSettings::GetMetric(wxSYS_VSCROLL_X
));
879 virtual bool Show(bool show
= true) {
880 bool rv
= wxWindow::Show(show
);
881 GetParent()->Refresh(false);
886 void OnActivate(wxListEvent
& WXUNUSED(event
)) {
887 doubleClickAction(doubleClickActionData
);
890 wxListView
* GetLB() { return lv
; }
893 DECLARE_EVENT_TABLE()
897 BEGIN_EVENT_TABLE(wxSTCListBoxWin
, wxWindow
)
898 EVT_SET_FOCUS ( wxSTCListBoxWin::OnFocus
)
899 EVT_SIZE ( wxSTCListBoxWin::OnSize
)
900 EVT_LIST_ITEM_ACTIVATED(wxID_ANY
, wxSTCListBoxWin::OnActivate
)
903 #endif // wxUSE_POPUPWIN -----------------------------------
906 inline wxSTCListBoxWin
* GETLBW(WindowID win
) {
907 return ((wxSTCListBoxWin
*)win
);
910 inline wxListView
* GETLB(WindowID win
) {
911 return GETLBW(win
)->GetLB();
914 //----------------------------------------------------------------------
916 class ListBoxImpl
: public ListBox
{
920 int desiredVisibleRows
;
923 Point location
; // Caret location at which the list is opened
924 wxImageList
* imgList
;
925 wxArrayInt
* imgTypeMap
;
931 virtual void SetFont(Font
&font
);
932 virtual void Create(Window
&parent
, int ctrlID
, Point location_
, int lineHeight_
, bool unicodeMode_
);
933 virtual void SetAverageCharWidth(int width
);
934 virtual void SetVisibleRows(int rows
);
935 virtual int GetVisibleRows() const;
936 virtual PRectangle
GetDesiredRect();
937 virtual int CaretFromEdge();
938 virtual void Clear();
939 virtual void Append(char *s
, int type
= -1);
940 void Append(const wxString
& text
, int type
);
941 virtual int Length();
942 virtual void Select(int n
);
943 virtual int GetSelection();
944 virtual int Find(const char *prefix
);
945 virtual void GetValue(int n
, char *value
, int len
);
946 virtual void RegisterImage(int type
, const char *xpm_data
);
947 virtual void ClearRegisteredImages();
948 virtual void SetDoubleClickAction(CallBackAction
, void *);
949 virtual void SetList(const char* list
, char separator
, char typesep
);
953 ListBoxImpl::ListBoxImpl()
954 : lineHeight(10), unicodeMode(false),
955 desiredVisibleRows(5), aveCharWidth(8), maxStrWidth(0),
956 imgList(NULL
), imgTypeMap(NULL
)
960 ListBoxImpl::~ListBoxImpl() {
972 void ListBoxImpl::SetFont(Font
&font
) {
973 GETLB(id
)->SetFont(*((wxFont
*)font
.GetID()));
977 void ListBoxImpl::Create(Window
&parent
, int ctrlID
, Point location_
, int lineHeight_
, bool unicodeMode_
) {
978 location
= location_
;
979 lineHeight
= lineHeight_
;
980 unicodeMode
= unicodeMode_
;
982 id
= new wxSTCListBoxWin(GETWIN(parent
.GetID()), ctrlID
, location
);
984 GETLB(id
)->SetImageList(imgList
, wxIMAGE_LIST_SMALL
);
988 void ListBoxImpl::SetAverageCharWidth(int width
) {
989 aveCharWidth
= width
;
993 void ListBoxImpl::SetVisibleRows(int rows
) {
994 desiredVisibleRows
= rows
;
998 int ListBoxImpl::GetVisibleRows() const {
999 return desiredVisibleRows
;
1002 PRectangle
ListBoxImpl::GetDesiredRect() {
1003 // wxListCtrl doesn't have a DoGetBestSize, so instead we kept track of
1004 // the max size in Append and calculate it here...
1005 int maxw
= maxStrWidth
* aveCharWidth
;
1008 // give it a default if there are no lines, and/or add a bit more
1009 if (maxw
== 0) maxw
= 100;
1010 maxw
+= aveCharWidth
* 3 +
1011 GETLBW(id
)->IconWidth() + wxSystemSettings::GetMetric(wxSYS_VSCROLL_X
);
1015 // estimate a desired height
1016 int count
= GETLB(id
)->GetItemCount();
1019 GETLB(id
)->GetItemRect(0, rect
);
1020 maxh
= count
* rect
.GetHeight();
1021 if (maxh
> 140) // TODO: Use desiredVisibleRows??
1024 // Try to make the size an exact multiple of some number of lines
1025 int lines
= maxh
/ rect
.GetHeight();
1026 maxh
= (lines
+ 1) * rect
.GetHeight() + 2;
1040 int ListBoxImpl::CaretFromEdge() {
1041 return 4 + GETLBW(id
)->IconWidth();
1045 void ListBoxImpl::Clear() {
1046 GETLB(id
)->DeleteAllItems();
1050 void ListBoxImpl::Append(char *s
, int type
) {
1051 Append(stc2wx(s
), type
);
1054 void ListBoxImpl::Append(const wxString
& text
, int type
) {
1055 long count
= GETLB(id
)->GetItemCount();
1056 long itemID
= GETLB(id
)->InsertItem(count
, wxEmptyString
);
1057 GETLB(id
)->SetItem(itemID
, 1, text
);
1058 maxStrWidth
= wxMax(maxStrWidth
, text
.length());
1060 wxCHECK_RET(imgTypeMap
, wxT("Unexpected NULL imgTypeMap"));
1061 long idx
= imgTypeMap
->Item(type
);
1062 GETLB(id
)->SetItemImage(itemID
, idx
, idx
);
1066 void ListBoxImpl::SetList(const char* list
, char separator
, char typesep
) {
1067 GETLB(id
)->Freeze();
1069 wxStringTokenizer
tkzr(stc2wx(list
), (wxChar
)separator
);
1070 while ( tkzr
.HasMoreTokens() ) {
1071 wxString token
= tkzr
.GetNextToken();
1073 int pos
= token
.Find(typesep
);
1075 token
.Mid(pos
+1).ToLong(&type
);
1076 token
.Truncate(pos
);
1078 Append(token
, (int)type
);
1084 int ListBoxImpl::Length() {
1085 return GETLB(id
)->GetItemCount();
1089 void ListBoxImpl::Select(int n
) {
1095 GETLB(id
)->Focus(n
);
1096 GETLB(id
)->Select(n
, select
);
1100 int ListBoxImpl::GetSelection() {
1101 return GETLB(id
)->GetFirstSelected();
1105 int ListBoxImpl::Find(const char *WXUNUSED(prefix
)) {
1111 void ListBoxImpl::GetValue(int n
, char *value
, int len
) {
1115 item
.SetMask(wxLIST_MASK_TEXT
);
1116 GETLB(id
)->GetItem(item
);
1117 strncpy(value
, wx2stc(item
.GetText()), len
);
1118 value
[len
-1] = '\0';
1122 void ListBoxImpl::RegisterImage(int type
, const char *xpm_data
) {
1123 wxMemoryInputStream
stream(xpm_data
, strlen(xpm_data
)+1);
1124 wxImage
img(stream
, wxBITMAP_TYPE_XPM
);
1128 // assumes all images are the same size
1129 imgList
= new wxImageList(bmp
.GetWidth(), bmp
.GetHeight(), true);
1130 imgTypeMap
= new wxArrayInt
;
1133 int idx
= imgList
->Add(bmp
);
1135 // do we need to extend the mapping array?
1136 wxArrayInt
& itm
= *imgTypeMap
;
1137 if ( itm
.GetCount() < (size_t)type
+1)
1138 itm
.Add(-1, type
- itm
.GetCount() + 1);
1140 // Add an item that maps type to the image index
1144 void ListBoxImpl::ClearRegisteredImages() {
1154 GETLB(id
)->SetImageList(NULL
, wxIMAGE_LIST_SMALL
);
1158 void ListBoxImpl::SetDoubleClickAction(CallBackAction action
, void *data
) {
1159 GETLBW(id
)->SetDoubleClickAction(action
, data
);
1163 ListBox::ListBox() {
1166 ListBox::~ListBox() {
1169 ListBox
*ListBox::Allocate() {
1170 return new ListBoxImpl();
1173 //----------------------------------------------------------------------
1175 Menu::Menu() : id(0) {
1178 void Menu::CreatePopUp() {
1183 void Menu::Destroy() {
1189 void Menu::Show(Point pt
, Window
&w
) {
1190 GETWIN(w
.GetID())->PopupMenu((wxMenu
*)id
, pt
.x
- 4, pt
.y
);
1194 //----------------------------------------------------------------------
1196 DynamicLibrary
*DynamicLibrary::Load(const char *WXUNUSED(modulePath
)) {
1197 wxFAIL_MSG(wxT("Dynamic lexer loading not implemented yet"));
1201 //----------------------------------------------------------------------
1203 ColourDesired
Platform::Chrome() {
1205 c
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
1206 return ColourDesired(c
.Red(), c
.Green(), c
.Blue());
1209 ColourDesired
Platform::ChromeHighlight() {
1211 c
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT
);
1212 return ColourDesired(c
.Red(), c
.Green(), c
.Blue());
1215 const char *Platform::DefaultFont() {
1216 static char buf
[128];
1217 strcpy(buf
, wxNORMAL_FONT
->GetFaceName().mbc_str());
1221 int Platform::DefaultFontSize() {
1222 return wxNORMAL_FONT
->GetPointSize();
1225 unsigned int Platform::DoubleClickTime() {
1226 return 500; // **** ::GetDoubleClickTime();
1229 bool Platform::MouseButtonBounce() {
1232 void Platform::DebugDisplay(const char *s
) {
1233 wxLogDebug(stc2wx(s
));
1236 bool Platform::IsKeyDown(int WXUNUSED(key
)) {
1237 return false; // I don't think we'll need this.
1240 long Platform::SendScintilla(WindowID w
,
1242 unsigned long wParam
,
1245 wxStyledTextCtrl
* stc
= (wxStyledTextCtrl
*)w
;
1246 return stc
->SendMsg(msg
, wParam
, lParam
);
1249 long Platform::SendScintillaPointer(WindowID w
,
1251 unsigned long wParam
,
1254 wxStyledTextCtrl
* stc
= (wxStyledTextCtrl
*)w
;
1255 return stc
->SendMsg(msg
, wParam
, (long)lParam
);
1259 // These are utility functions not really tied to a platform
1261 int Platform::Minimum(int a
, int b
) {
1268 int Platform::Maximum(int a
, int b
) {
1277 void Platform::DebugPrintf(const char *format
, ...) {
1281 va_start(pArguments
, format
);
1282 vsprintf(buffer
,format
,pArguments
);
1284 Platform::DebugDisplay(buffer
);
1289 static bool assertionPopUps
= true;
1291 bool Platform::ShowAssertionPopUps(bool assertionPopUps_
) {
1292 bool ret
= assertionPopUps
;
1293 assertionPopUps
= assertionPopUps_
;
1297 void Platform::Assert(const char *c
, const char *file
, int line
) {
1299 sprintf(buffer
, "Assertion [%s] failed at %s %d", c
, file
, line
);
1300 if (assertionPopUps
) {
1302 wxMessageBox(stc2wx(buffer
),
1303 wxT("Assertion failure"),
1304 wxICON_HAND
| wxOK
);
1305 // if (idButton == IDRETRY) {
1307 // } else if (idButton == IDIGNORE) {
1313 strcat(buffer
, "\r\n");
1314 Platform::DebugDisplay(buffer
);
1320 int Platform::Clamp(int val
, int minVal
, int maxVal
) {
1329 bool Platform::IsDBCSLeadByte(int WXUNUSED(codePage
), char WXUNUSED(ch
)) {
1333 int Platform::DBCSCharLength(int WXUNUSED(codePage
), const char *WXUNUSED(s
)) {
1337 int Platform::DBCSCharMaxLength() {
1342 //----------------------------------------------------------------------
1344 ElapsedTime::ElapsedTime() {
1345 wxLongLong localTime
= wxGetLocalTimeMillis();
1346 littleBit
= localTime
.GetLo();
1347 bigBit
= localTime
.GetHi();
1350 double ElapsedTime::Duration(bool reset
) {
1351 wxLongLong
prevTime(bigBit
, littleBit
);
1352 wxLongLong localTime
= wxGetLocalTimeMillis();
1354 littleBit
= localTime
.GetLo();
1355 bigBit
= localTime
.GetHi();
1357 wxLongLong duration
= localTime
- prevTime
;
1358 double result
= duration
.ToDouble();
1364 //----------------------------------------------------------------------
1368 #include "UniConversion.h"
1370 // Convert using Scintilla's functions instead of wx's, Scintilla's are more
1371 // forgiving and won't assert...
1373 wxString
stc2wx(const char* str
, size_t len
)
1376 return wxEmptyString
;
1378 size_t wclen
= UCS2Length(str
, len
);
1379 wxWCharBuffer
buffer(wclen
+1);
1381 size_t actualLen
= UCS2FromUTF8(str
, len
, buffer
.data(), wclen
+1);
1382 return wxString(buffer
.data(), actualLen
);
1387 wxString
stc2wx(const char* str
)
1389 return stc2wx(str
, strlen(str
));
1393 const wxWX2MBbuf
wx2stc(const wxString
& str
)
1395 const wchar_t* wcstr
= str
.c_str();
1396 size_t wclen
= str
.length();
1397 size_t len
= UTF8Length(wcstr
, wclen
);
1399 wxCharBuffer
buffer(len
+1);
1400 UTF8FromUCS2(wcstr
, wclen
, buffer
.data(), len
);
1402 // TODO check NULL termination!!