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"
17 #ifdef wxHAVE_RAW_BITMAP
18 #include "wx/rawbmp.h"
23 #include "wx/stc/stc.h"
27 Point
Point::FromLong(long lpoint
) {
28 return Point(lpoint
& 0xFFFF, lpoint
>> 16);
31 wxRect
wxRectFromPRectangle(PRectangle prc
) {
32 wxRect
r(prc
.left
, prc
.top
,
33 prc
.Width(), prc
.Height());
37 PRectangle
PRectangleFromwxRect(wxRect rc
) {
38 return PRectangle(rc
.GetLeft(), rc
.GetTop(),
39 rc
.GetRight()+1, rc
.GetBottom()+1);
42 wxColour
wxColourFromCA(const ColourAllocated
& ca
) {
43 ColourDesired
cd(ca
.AsLong());
44 return wxColour((unsigned char)cd
.GetRed(),
45 (unsigned char)cd
.GetGreen(),
46 (unsigned char)cd
.GetBlue());
49 //----------------------------------------------------------------------
53 allowRealization
= false;
55 entries
= new ColourPair
[size
];
64 void Palette::Release() {
68 entries
= new ColourPair
[size
];
71 // This method either adds a colour to the list of wanted colours (want==true)
72 // or retrieves the allocated colour back to the ColourPair.
73 // This is one method to make it easier to keep the code for wanting and retrieving in sync.
74 void Palette::WantFind(ColourPair
&cp
, bool want
) {
76 for (int i
=0; i
< used
; i
++) {
77 if (entries
[i
].desired
== cp
.desired
)
82 int sizeNew
= size
* 2;
83 ColourPair
*entriesNew
= new ColourPair
[sizeNew
];
84 for (int j
=0; j
<size
; j
++) {
85 entriesNew
[j
] = entries
[j
];
92 entries
[used
].desired
= cp
.desired
;
93 entries
[used
].allocated
.Set(cp
.desired
.AsLong());
96 for (int i
=0; i
< used
; i
++) {
97 if (entries
[i
].desired
== cp
.desired
) {
98 cp
.allocated
= entries
[i
].allocated
;
102 cp
.allocated
.Set(cp
.desired
.AsLong());
106 void Palette::Allocate(Window
&) {
107 if (allowRealization
) {
112 //----------------------------------------------------------------------
122 void Font::Create(const char *faceName
, int characterSet
, int size
, bool bold
, bool italic
, bool extraFontFlag
) {
126 // The minus one is done because since Scintilla uses SC_SHARSET_DEFAULT
127 // internally and we need to have wxFONENCODING_DEFAULT == SC_SHARSET_DEFAULT
128 // so we adjust the encoding before passing it to Scintilla. See also
129 // wxStyledTextCtrl::StyleSetCharacterSet
130 wxFontEncoding encoding
= (wxFontEncoding
)(characterSet
-1);
132 wxFontEncodingArray ea
= wxEncodingConverter::GetPlatformEquivalents(encoding
);
136 wxFont
* font
= new wxFont(size
,
138 italic
? wxITALIC
: wxNORMAL
,
139 bold
? wxBOLD
: wxNORMAL
,
143 font
->SetNoAntiAliasing(!extraFontFlag
);
148 void Font::Release() {
154 //----------------------------------------------------------------------
156 class SurfaceImpl
: public Surface
{
169 virtual void Init(WindowID wid
);
170 virtual void Init(SurfaceID sid
, WindowID wid
);
171 virtual void InitPixMap(int width
, int height
, Surface
*surface_
, WindowID wid
);
173 virtual void Release();
174 virtual bool Initialised();
175 virtual void PenColour(ColourAllocated fore
);
176 virtual int LogPixelsY();
177 virtual int DeviceHeightFont(int points
);
178 virtual void MoveTo(int x_
, int y_
);
179 virtual void LineTo(int x_
, int y_
);
180 virtual void Polygon(Point
*pts
, int npts
, ColourAllocated fore
, ColourAllocated back
);
181 virtual void RectangleDraw(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
);
182 virtual void FillRectangle(PRectangle rc
, ColourAllocated back
);
183 virtual void FillRectangle(PRectangle rc
, Surface
&surfacePattern
);
184 virtual void RoundedRectangle(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
);
185 virtual void AlphaRectangle(PRectangle rc
, int cornerSize
, ColourAllocated fill
, int alphaFill
,
186 ColourAllocated outline
, int alphaOutline
, int flags
);
187 virtual void Ellipse(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
);
188 virtual void Copy(PRectangle rc
, Point from
, Surface
&surfaceSource
);
190 virtual void DrawTextNoClip(PRectangle rc
, Font
&font_
, int ybase
, const char *s
, int len
, ColourAllocated fore
, ColourAllocated back
);
191 virtual void DrawTextClipped(PRectangle rc
, Font
&font_
, int ybase
, const char *s
, int len
, ColourAllocated fore
, ColourAllocated back
);
192 virtual void DrawTextTransparent(PRectangle rc
, Font
&font_
, int ybase
, const char *s
, int len
, ColourAllocated fore
);
193 virtual void MeasureWidths(Font
&font_
, const char *s
, int len
, int *positions
);
194 virtual int WidthText(Font
&font_
, const char *s
, int len
);
195 virtual int WidthChar(Font
&font_
, char ch
);
196 virtual int Ascent(Font
&font_
);
197 virtual int Descent(Font
&font_
);
198 virtual int InternalLeading(Font
&font_
);
199 virtual int ExternalLeading(Font
&font_
);
200 virtual int Height(Font
&font_
);
201 virtual int AverageCharWidth(Font
&font_
);
203 virtual int SetPalette(Palette
*pal
, bool inBackGround
);
204 virtual void SetClip(PRectangle rc
);
205 virtual void FlushCachedState();
207 virtual void SetUnicodeMode(bool unicodeMode_
);
208 virtual void SetDBCSMode(int codePage
);
210 void BrushColour(ColourAllocated back
);
211 void SetFont(Font
&font_
);
216 SurfaceImpl::SurfaceImpl() :
217 hdc(0), hdcOwned(0), bitmap(0),
218 x(0), y(0), unicodeMode(0)
221 SurfaceImpl::~SurfaceImpl() {
225 void SurfaceImpl::Init(WindowID wid
) {
228 hdc
= new wxMemoryDC();
231 // On Mac and GTK the DC is not really valid until it has a bitmap
232 // selected into it. So instead of just creating the DC with no bitmap,
233 // go ahead and give it one.
234 InitPixMap(1,1,NULL
,wid
);
238 void SurfaceImpl::Init(SurfaceID hdc_
, WindowID
) {
243 void SurfaceImpl::InitPixMap(int width
, int height
, Surface
*WXUNUSED(surface_
), WindowID
) {
245 hdc
= new wxMemoryDC();
247 if (width
< 1) width
= 1;
248 if (height
< 1) height
= 1;
249 bitmap
= new wxBitmap(width
, height
);
250 ((wxMemoryDC
*)hdc
)->SelectObject(*bitmap
);
254 void SurfaceImpl::Release() {
256 ((wxMemoryDC
*)hdc
)->SelectObject(wxNullBitmap
);
268 bool SurfaceImpl::Initialised() {
273 void SurfaceImpl::PenColour(ColourAllocated fore
) {
274 hdc
->SetPen(wxPen(wxColourFromCA(fore
), 1, wxSOLID
));
277 void SurfaceImpl::BrushColour(ColourAllocated back
) {
278 hdc
->SetBrush(wxBrush(wxColourFromCA(back
), wxSOLID
));
281 void SurfaceImpl::SetFont(Font
&font_
) {
283 hdc
->SetFont(*((wxFont
*)font_
.GetID()));
287 int SurfaceImpl::LogPixelsY() {
288 return hdc
->GetPPI().y
;
291 int SurfaceImpl::DeviceHeightFont(int points
) {
295 void SurfaceImpl::MoveTo(int x_
, int y_
) {
300 void SurfaceImpl::LineTo(int x_
, int y_
) {
301 hdc
->DrawLine(x
,y
, x_
,y_
);
306 void SurfaceImpl::Polygon(Point
*pts
, int npts
, ColourAllocated fore
, ColourAllocated back
) {
309 hdc
->DrawPolygon(npts
, (wxPoint
*)pts
);
312 void SurfaceImpl::RectangleDraw(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
) {
315 hdc
->DrawRectangle(wxRectFromPRectangle(rc
));
318 void SurfaceImpl::FillRectangle(PRectangle rc
, ColourAllocated back
) {
320 hdc
->SetPen(*wxTRANSPARENT_PEN
);
321 hdc
->DrawRectangle(wxRectFromPRectangle(rc
));
324 void SurfaceImpl::FillRectangle(PRectangle rc
, Surface
&surfacePattern
) {
326 if (((SurfaceImpl
&)surfacePattern
).bitmap
)
327 br
= wxBrush(*((SurfaceImpl
&)surfacePattern
).bitmap
);
328 else // Something is wrong so display in red
329 br
= wxBrush(*wxRED
, wxSOLID
);
330 hdc
->SetPen(*wxTRANSPARENT_PEN
);
332 hdc
->DrawRectangle(wxRectFromPRectangle(rc
));
335 void SurfaceImpl::RoundedRectangle(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
) {
338 hdc
->DrawRoundedRectangle(wxRectFromPRectangle(rc
), 4);
342 #define wxPy_premultiply(p, a) ((p) * (a) / 0xff)
344 #define wxPy_premultiply(p, a) (p)
347 void SurfaceImpl::AlphaRectangle(PRectangle rc
, int cornerSize
,
348 ColourAllocated fill
, int alphaFill
,
349 ColourAllocated outline
, int alphaOutline
,
351 #ifdef wxHAVE_RAW_BITMAP
353 // TODO: do something with cornerSize
354 wxUnusedVar(cornerSize
);
357 wxRect r
= wxRectFromPRectangle(rc
);
358 wxBitmap
bmp(r
.width
, r
.height
, 32);
359 wxAlphaPixelData
pixData(bmp
);
362 // Set the fill pixels
363 ColourDesired
cdf(fill
.AsLong());
364 int red
= cdf
.GetRed();
365 int green
= cdf
.GetGreen();
366 int blue
= cdf
.GetBlue();
368 wxAlphaPixelData::Iterator
p(pixData
);
369 for (y
=0; y
<r
.height
; y
++) {
370 p
.MoveTo(pixData
, 0, y
);
371 for (x
=0; x
<r
.width
; x
++) {
372 p
.Red() = wxPy_premultiply(red
, alphaFill
);
373 p
.Green() = wxPy_premultiply(green
, alphaFill
);
374 p
.Blue() = wxPy_premultiply(blue
, alphaFill
);
375 p
.Alpha() = alphaFill
;
380 // Set the outline pixels
381 ColourDesired
cdo(outline
.AsLong());
383 green
= cdo
.GetGreen();
384 blue
= cdo
.GetBlue();
385 for (x
=0; x
<r
.width
; x
++) {
386 p
.MoveTo(pixData
, x
, 0);
387 p
.Red() = wxPy_premultiply(red
, alphaOutline
);
388 p
.Green() = wxPy_premultiply(green
, alphaOutline
);
389 p
.Blue() = wxPy_premultiply(blue
, alphaOutline
);
390 p
.Alpha() = alphaOutline
;
391 p
.MoveTo(pixData
, x
, r
.height
-1);
392 p
.Red() = wxPy_premultiply(red
, alphaOutline
);
393 p
.Green() = wxPy_premultiply(green
, alphaOutline
);
394 p
.Blue() = wxPy_premultiply(blue
, alphaOutline
);
395 p
.Alpha() = alphaOutline
;
398 for (y
=0; y
<r
.height
; y
++) {
399 p
.MoveTo(pixData
, 0, y
);
400 p
.Red() = wxPy_premultiply(red
, alphaOutline
);
401 p
.Green() = wxPy_premultiply(green
, alphaOutline
);
402 p
.Blue() = wxPy_premultiply(blue
, alphaOutline
);
403 p
.Alpha() = alphaOutline
;
404 p
.MoveTo(pixData
, r
.width
-1, y
);
405 p
.Red() = wxPy_premultiply(red
, alphaOutline
);
406 p
.Green() = wxPy_premultiply(green
, alphaOutline
);
407 p
.Blue() = wxPy_premultiply(blue
, alphaOutline
);
408 p
.Alpha() = alphaOutline
;
412 hdc
->DrawBitmap(bmp
, r
.x
, r
.y
, true);
415 wxUnusedVar(cornerSize
);
416 wxUnusedVar(alphaFill
);
417 wxUnusedVar(alphaOutline
);
418 RectangleDraw(rc
, outline
, fill
);
422 void SurfaceImpl::Ellipse(PRectangle rc
, ColourAllocated fore
, ColourAllocated back
) {
425 hdc
->DrawEllipse(wxRectFromPRectangle(rc
));
428 void SurfaceImpl::Copy(PRectangle rc
, Point from
, Surface
&surfaceSource
) {
429 wxRect r
= wxRectFromPRectangle(rc
);
430 hdc
->Blit(r
.x
, r
.y
, r
.width
, r
.height
,
431 ((SurfaceImpl
&)surfaceSource
).hdc
,
432 from
.x
, from
.y
, wxCOPY
);
435 void SurfaceImpl::DrawTextNoClip(PRectangle rc
, Font
&font
, int ybase
,
436 const char *s
, int len
,
437 ColourAllocated fore
, ColourAllocated back
) {
439 hdc
->SetTextForeground(wxColourFromCA(fore
));
440 hdc
->SetTextBackground(wxColourFromCA(back
));
441 FillRectangle(rc
, back
);
443 // ybase is where the baseline should be, but wxWin uses the upper left
444 // corner, so I need to calculate the real position for the text...
445 hdc
->DrawText(stc2wx(s
, len
), rc
.left
, ybase
- font
.ascent
);
448 void SurfaceImpl::DrawTextClipped(PRectangle rc
, Font
&font
, int ybase
,
449 const char *s
, int len
,
450 ColourAllocated fore
, ColourAllocated back
) {
452 hdc
->SetTextForeground(wxColourFromCA(fore
));
453 hdc
->SetTextBackground(wxColourFromCA(back
));
454 FillRectangle(rc
, back
);
455 hdc
->SetClippingRegion(wxRectFromPRectangle(rc
));
457 // see comments above
458 hdc
->DrawText(stc2wx(s
, len
), rc
.left
, ybase
- font
.ascent
);
459 hdc
->DestroyClippingRegion();
463 void SurfaceImpl::DrawTextTransparent(PRectangle rc
, Font
&font
, int ybase
,
464 const char *s
, int len
,
465 ColourAllocated fore
) {
468 hdc
->SetTextForeground(wxColourFromCA(fore
));
469 hdc
->SetBackgroundMode(wxTRANSPARENT
);
471 // ybase is where the baseline should be, but wxWin uses the upper left
472 // corner, so I need to calculate the real position for the text...
473 hdc
->DrawText(stc2wx(s
, len
), rc
.left
, ybase
- font
.ascent
);
475 hdc
->SetBackgroundMode(wxSOLID
);
479 void SurfaceImpl::MeasureWidths(Font
&font
, const char *s
, int len
, int *positions
) {
481 wxString str
= stc2wx(s
, len
);
486 hdc
->GetPartialTextExtents(str
, tpos
);
489 // Map the widths for UCS-2 characters back to the UTF-8 input string
490 // NOTE: I don't think this is right for when sizeof(wxChar) > 2, ie wxGTK2
491 // so figure it out and fix it!
494 while ((int)i
< len
) {
495 unsigned char uch
= (unsigned char)s
[i
];
496 positions
[i
++] = tpos
[ui
];
498 if (uch
< (0x80 + 0x40 + 0x20)) {
499 positions
[i
++] = tpos
[ui
];
501 positions
[i
++] = tpos
[ui
];
502 positions
[i
++] = tpos
[ui
];
509 // If not unicode then just use the widths we have
511 std::copy(tpos
.begin(), tpos
.end(), positions
);
513 memcpy(positions
, tpos
.begin(), len
* sizeof(int));
519 int SurfaceImpl::WidthText(Font
&font
, const char *s
, int len
) {
524 hdc
->GetTextExtent(stc2wx(s
, len
), &w
, &h
);
529 int SurfaceImpl::WidthChar(Font
&font
, char ch
) {
533 char s
[2] = { ch
, 0 };
535 hdc
->GetTextExtent(stc2wx(s
, 1), &w
, &h
);
539 #define EXTENT_TEST wxT(" `~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
541 int SurfaceImpl::Ascent(Font
&font
) {
544 hdc
->GetTextExtent(EXTENT_TEST
, &w
, &h
, &d
, &e
);
549 int SurfaceImpl::Descent(Font
&font
) {
552 hdc
->GetTextExtent(EXTENT_TEST
, &w
, &h
, &d
, &e
);
556 int SurfaceImpl::InternalLeading(Font
&WXUNUSED(font
)) {
560 int SurfaceImpl::ExternalLeading(Font
&font
) {
563 hdc
->GetTextExtent(EXTENT_TEST
, &w
, &h
, &d
, &e
);
567 int SurfaceImpl::Height(Font
&font
) {
569 return hdc
->GetCharHeight() + 1;
572 int SurfaceImpl::AverageCharWidth(Font
&font
) {
574 return hdc
->GetCharWidth();
577 int SurfaceImpl::SetPalette(Palette
*WXUNUSED(pal
), bool WXUNUSED(inBackGround
)) {
581 void SurfaceImpl::SetClip(PRectangle rc
) {
582 hdc
->SetClippingRegion(wxRectFromPRectangle(rc
));
585 void SurfaceImpl::FlushCachedState() {
588 void SurfaceImpl::SetUnicodeMode(bool unicodeMode_
) {
589 unicodeMode
=unicodeMode_
;
592 void SurfaceImpl::SetDBCSMode(int WXUNUSED(codePage
)) {
593 // dbcsMode = codePage == SC_CP_DBCS;
597 Surface
*Surface::Allocate() {
598 return new SurfaceImpl
;
602 //----------------------------------------------------------------------
605 inline wxWindow
* GETWIN(WindowID id
) { return (wxWindow
*)id
; }
610 void Window::Destroy() {
613 GETWIN(id
)->Destroy();
618 bool Window::HasFocus() {
619 return wxWindow::FindFocus() == GETWIN(id
);
622 PRectangle
Window::GetPosition() {
623 if (! id
) return PRectangle();
624 wxRect
rc(GETWIN(id
)->GetPosition(), GETWIN(id
)->GetSize());
625 return PRectangleFromwxRect(rc
);
628 void Window::SetPosition(PRectangle rc
) {
629 wxRect r
= wxRectFromPRectangle(rc
);
630 GETWIN(id
)->SetSize(r
);
633 void Window::SetPositionRelative(PRectangle rc
, Window
) {
634 SetPosition(rc
); // ????
637 PRectangle
Window::GetClientPosition() {
638 if (! id
) return PRectangle();
639 wxSize sz
= GETWIN(id
)->GetClientSize();
640 return PRectangle(0, 0, sz
.x
, sz
.y
);
643 void Window::Show(bool show
) {
644 GETWIN(id
)->Show(show
);
647 void Window::InvalidateAll() {
648 GETWIN(id
)->Refresh(false);
651 void Window::InvalidateRectangle(PRectangle rc
) {
652 wxRect r
= wxRectFromPRectangle(rc
);
653 GETWIN(id
)->Refresh(false, &r
);
656 void Window::SetFont(Font
&font
) {
657 GETWIN(id
)->SetFont(*((wxFont
*)font
.GetID()));
660 void Window::SetCursor(Cursor curs
) {
665 cursorId
= wxCURSOR_IBEAM
;
668 cursorId
= wxCURSOR_ARROW
;
671 cursorId
= wxCURSOR_ARROW
; // ** no up arrow... wxCURSOR_UPARROW;
674 cursorId
= wxCURSOR_WAIT
;
677 cursorId
= wxCURSOR_SIZEWE
;
680 cursorId
= wxCURSOR_SIZENS
;
682 case cursorReverseArrow
:
683 cursorId
= wxCURSOR_RIGHT_ARROW
;
686 cursorId
= wxCURSOR_HAND
;
689 cursorId
= wxCURSOR_ARROW
;
693 wxCursor wc
= wxStockCursor(cursorId
) ;
695 wxCursor wc
= wxCursor(cursorId
) ;
697 if(curs
!= cursorLast
)
699 GETWIN(id
)->SetCursor(wc
);
705 void Window::SetTitle(const char *s
) {
706 GETWIN(id
)->SetLabel(stc2wx(s
));
710 //----------------------------------------------------------------------
711 // Helper classes for ListBox
714 // This is a simple subclass of wxListView that just resets focus to the
715 // parent when it gets it.
716 class wxSTCListBox
: public wxListView
{
718 wxSTCListBox(wxWindow
* parent
, wxWindowID id
,
719 const wxPoint
& pos
, const wxSize
& size
,
724 Hide(); // don't flicker as we move it around...
726 Create(parent
, id
, pos
, size
, style
);
730 void OnFocus(wxFocusEvent
& event
) {
731 GetParent()->SetFocus();
735 void OnKillFocus(wxFocusEvent
& WXUNUSED(event
)) {
736 // Do nothing. Prevents base class from resetting the colors...
740 // For some reason I don't understand yet the focus doesn't really leave
741 // the listbox like it should, so if we get any events feed them back to
743 void OnKeyDown(wxKeyEvent
& event
) {
744 GetGrandParent()->GetEventHandler()->ProcessEvent(event
);
746 void OnChar(wxKeyEvent
& event
) {
747 GetGrandParent()->GetEventHandler()->ProcessEvent(event
);
750 // And we need to force the focus back when being destroyed
752 GetGrandParent()->SetFocus();
757 DECLARE_EVENT_TABLE()
760 BEGIN_EVENT_TABLE(wxSTCListBox
, wxListView
)
761 EVT_SET_FOCUS( wxSTCListBox::OnFocus
)
762 EVT_KILL_FOCUS(wxSTCListBox::OnKillFocus
)
764 EVT_KEY_DOWN( wxSTCListBox::OnKeyDown
)
765 EVT_CHAR( wxSTCListBox::OnChar
)
771 #if wxUSE_POPUPWIN //-----------------------------------
772 #include <wx/popupwin.h>
776 // TODO: Refactor these two classes to have a common base (or a mix-in) to get
777 // rid of the code duplication. (Either that or convince somebody to
778 // implement wxPopupWindow for the Mac!!)
780 // In the meantime, be careful to duplicate any changes as needed...
783 // A popup window to place the wxSTCListBox upon
784 class wxSTCListBoxWin
: public wxPopupWindow
788 CallBackAction doubleClickAction
;
789 void* doubleClickActionData
;
791 wxSTCListBoxWin(wxWindow
* parent
, wxWindowID id
, Point
WXUNUSED(location
)) :
792 wxPopupWindow(parent
, wxBORDER_NONE
)
795 SetBackgroundColour(*wxBLACK
); // for our simple border
797 lv
= new wxSTCListBox(parent
, id
, wxPoint(-50,-50), wxDefaultSize
,
798 wxLC_REPORT
| wxLC_SINGLE_SEL
| wxLC_NO_HEADER
| wxBORDER_NONE
);
799 lv
->SetCursor(wxCursor(wxCURSOR_ARROW
));
800 lv
->InsertColumn(0, wxEmptyString
);
801 lv
->InsertColumn(1, wxEmptyString
);
803 // NOTE: We need to fool the wxListView into thinking that it has the
804 // focus so it will use the normal selection colour and will look
805 // "right" to the user. But since the wxPopupWindow or its children
806 // can't receive focus then we have to pull a fast one and temporarily
807 // parent the listctrl on the STC window and then call SetFocus and
808 // then reparent it back to the popup.
817 // Set position in client coords
818 virtual void DoSetSize(int x
, int y
,
819 int width
, int height
,
820 int sizeFlags
= wxSIZE_AUTO
) {
821 if (x
!= wxDefaultCoord
) {
822 GetParent()->ClientToScreen(&x
, NULL
);
824 if (y
!= wxDefaultCoord
) {
825 GetParent()->ClientToScreen(NULL
, &y
);
827 wxPopupWindow::DoSetSize(x
, y
, width
, height
, sizeFlags
);
830 // return position as if it were in client coords
831 virtual void DoGetPosition( int *x
, int *y
) const {
833 wxPopupWindow::DoGetPosition(&sx
, &sy
);
834 GetParent()->ScreenToClient(&sx
, &sy
);
841 if ( !wxPendingDelete
.Member(this) )
842 wxPendingDelete
.Append(this);
848 wxImageList
* il
= lv
->GetImageList(wxIMAGE_LIST_SMALL
);
851 il
->GetSize(0, w
, h
);
858 void SetDoubleClickAction(CallBackAction action
, void *data
) {
859 doubleClickAction
= action
;
860 doubleClickActionData
= data
;
864 void OnFocus(wxFocusEvent
& event
) {
865 GetParent()->SetFocus();
869 void OnSize(wxSizeEvent
& event
) {
871 wxSize sz
= GetSize();
874 lv
->SetSize(1, 1, sz
.x
, sz
.y
);
875 // reset the column widths
876 lv
->SetColumnWidth(0, IconWidth()+4);
877 lv
->SetColumnWidth(1, sz
.x
- 2 - lv
->GetColumnWidth(0) -
878 wxSystemSettings::GetMetric(wxSYS_VSCROLL_X
));
882 void OnActivate(wxListEvent
& WXUNUSED(event
)) {
883 doubleClickAction(doubleClickActionData
);
886 wxListView
* GetLB() { return lv
; }
889 DECLARE_EVENT_TABLE()
893 BEGIN_EVENT_TABLE(wxSTCListBoxWin
, wxPopupWindow
)
894 EVT_SET_FOCUS ( wxSTCListBoxWin::OnFocus
)
895 EVT_SIZE ( wxSTCListBoxWin::OnSize
)
896 EVT_LIST_ITEM_ACTIVATED(wxID_ANY
, wxSTCListBoxWin::OnActivate
)
901 #else // !wxUSE_POPUPWIN -----------------------------------
903 // A normal window to place the wxSTCListBox upon, but make it behave as much
904 // like a wxPopupWindow as possible
905 class wxSTCListBoxWin
: public wxFrame
{
908 CallBackAction doubleClickAction
;
909 void* doubleClickActionData
;
911 wxSTCListBoxWin(wxWindow
* parent
, wxWindowID id
, Point location
) :
912 wxFrame(parent
, id
, wxEmptyString
, wxPoint(location
.x
, location
.y
), wxSize(0,0),
914 | wxFRAME_FLOAT_ON_PARENT
924 lv
= new wxSTCListBox(this, id
, wxDefaultPosition
, wxDefaultSize
,
925 wxLC_REPORT
| wxLC_SINGLE_SEL
| wxLC_NO_HEADER
| wxNO_BORDER
);
926 lv
->SetCursor(wxCursor(wxCURSOR_ARROW
));
927 lv
->InsertColumn(0, wxEmptyString
);
928 lv
->InsertColumn(1, wxEmptyString
);
930 // Eventhough we immediately reset the focus to the parent, this helps
931 // things to look right...
938 // On OSX and (possibly others) there can still be pending
939 // messages/events for the list control when Scintilla wants to
940 // close it, so do a pending delete of it instead of destroying
945 // The bottom edge of this window is not getting properly
946 // refreshed upon deletion, so help it out...
947 wxWindow
* p
= GetParent();
948 wxRect
r(GetPosition(), GetSize());
949 r
.SetHeight(r
.GetHeight()+1);
950 p
->Refresh(false, &r
);
952 if ( !wxPendingDelete
.Member(this) )
953 wxPendingDelete
.Append(this);
960 wxImageList
* il
= lv
->GetImageList(wxIMAGE_LIST_SMALL
);
963 il
->GetSize(0, w
, h
);
970 void SetDoubleClickAction(CallBackAction action
, void *data
)
972 doubleClickAction
= action
;
973 doubleClickActionData
= data
;
977 void OnFocus(wxFocusEvent
& event
)
980 GetParent()->SetFocus();
984 void OnSize(wxSizeEvent
& event
)
987 wxSize sz
= GetClientSize();
989 // reset the column widths
990 lv
->SetColumnWidth(0, IconWidth()+4);
991 lv
->SetColumnWidth(1, sz
.x
- 2 - lv
->GetColumnWidth(0) -
992 wxSystemSettings::GetMetric(wxSYS_VSCROLL_X
));
996 void ActivateParent()
998 // Although we're a frame, we always want the parent to be active, so
999 // raise it whenever we get shown, focused, etc.
1000 wxTopLevelWindow
*frame
= wxDynamicCast(
1001 wxGetTopLevelParent(GetParent()), wxTopLevelWindow
);
1007 virtual void DoSetSize(int x
, int y
,
1008 int width
, int height
,
1009 int sizeFlags
= wxSIZE_AUTO
)
1011 // convert coords to screen coords since we're a top-level window
1012 if (x
!= wxDefaultCoord
) {
1013 GetParent()->ClientToScreen(&x
, NULL
);
1015 if (y
!= wxDefaultCoord
) {
1016 GetParent()->ClientToScreen(NULL
, &y
);
1018 wxFrame::DoSetSize(x
, y
, width
, height
, sizeFlags
);
1021 virtual bool Show(bool show
= true)
1023 bool rv
= wxFrame::Show(show
);
1027 GetParent()->Refresh(false);
1032 void OnActivate(wxListEvent
& WXUNUSED(event
))
1034 doubleClickAction(doubleClickActionData
);
1037 wxListView
* GetLB() { return lv
; }
1040 DECLARE_EVENT_TABLE()
1044 BEGIN_EVENT_TABLE(wxSTCListBoxWin
, wxWindow
)
1045 EVT_SET_FOCUS ( wxSTCListBoxWin::OnFocus
)
1046 EVT_SIZE ( wxSTCListBoxWin::OnSize
)
1047 EVT_LIST_ITEM_ACTIVATED(wxID_ANY
, wxSTCListBoxWin::OnActivate
)
1050 #endif // wxUSE_POPUPWIN -----------------------------------
1053 inline wxSTCListBoxWin
* GETLBW(WindowID win
) {
1054 return ((wxSTCListBoxWin
*)win
);
1057 inline wxListView
* GETLB(WindowID win
) {
1058 return GETLBW(win
)->GetLB();
1061 //----------------------------------------------------------------------
1063 class ListBoxImpl
: public ListBox
{
1067 int desiredVisibleRows
;
1070 Point location
; // Caret location at which the list is opened
1071 wxImageList
* imgList
;
1072 wxArrayInt
* imgTypeMap
;
1078 virtual void SetFont(Font
&font
);
1079 virtual void Create(Window
&parent
, int ctrlID
, Point location_
, int lineHeight_
, bool unicodeMode_
);
1080 virtual void SetAverageCharWidth(int width
);
1081 virtual void SetVisibleRows(int rows
);
1082 virtual int GetVisibleRows() const;
1083 virtual PRectangle
GetDesiredRect();
1084 virtual int CaretFromEdge();
1085 virtual void Clear();
1086 virtual void Append(char *s
, int type
= -1);
1087 void Append(const wxString
& text
, int type
);
1088 virtual int Length();
1089 virtual void Select(int n
);
1090 virtual int GetSelection();
1091 virtual int Find(const char *prefix
);
1092 virtual void GetValue(int n
, char *value
, int len
);
1093 virtual void RegisterImage(int type
, const char *xpm_data
);
1094 virtual void ClearRegisteredImages();
1095 virtual void SetDoubleClickAction(CallBackAction
, void *);
1096 virtual void SetList(const char* list
, char separator
, char typesep
);
1100 ListBoxImpl::ListBoxImpl()
1101 : lineHeight(10), unicodeMode(false),
1102 desiredVisibleRows(5), aveCharWidth(8), maxStrWidth(0),
1103 imgList(NULL
), imgTypeMap(NULL
)
1107 ListBoxImpl::~ListBoxImpl() {
1119 void ListBoxImpl::SetFont(Font
&font
) {
1120 GETLB(id
)->SetFont(*((wxFont
*)font
.GetID()));
1124 void ListBoxImpl::Create(Window
&parent
, int ctrlID
, Point location_
, int lineHeight_
, bool unicodeMode_
) {
1125 location
= location_
;
1126 lineHeight
= lineHeight_
;
1127 unicodeMode
= unicodeMode_
;
1129 id
= new wxSTCListBoxWin(GETWIN(parent
.GetID()), ctrlID
, location
);
1130 if (imgList
!= NULL
)
1131 GETLB(id
)->SetImageList(imgList
, wxIMAGE_LIST_SMALL
);
1135 void ListBoxImpl::SetAverageCharWidth(int width
) {
1136 aveCharWidth
= width
;
1140 void ListBoxImpl::SetVisibleRows(int rows
) {
1141 desiredVisibleRows
= rows
;
1145 int ListBoxImpl::GetVisibleRows() const {
1146 return desiredVisibleRows
;
1149 PRectangle
ListBoxImpl::GetDesiredRect() {
1150 // wxListCtrl doesn't have a DoGetBestSize, so instead we kept track of
1151 // the max size in Append and calculate it here...
1152 int maxw
= maxStrWidth
* aveCharWidth
;
1155 // give it a default if there are no lines, and/or add a bit more
1156 if (maxw
== 0) maxw
= 100;
1157 maxw
+= aveCharWidth
* 3 +
1158 GETLBW(id
)->IconWidth() + wxSystemSettings::GetMetric(wxSYS_VSCROLL_X
);
1162 // estimate a desired height
1163 int count
= GETLB(id
)->GetItemCount();
1166 GETLB(id
)->GetItemRect(0, rect
);
1167 maxh
= count
* rect
.GetHeight();
1168 if (maxh
> 140) // TODO: Use desiredVisibleRows??
1171 // Try to make the size an exact multiple of some number of lines
1172 int lines
= maxh
/ rect
.GetHeight();
1173 maxh
= (lines
+ 1) * rect
.GetHeight() + 2;
1187 int ListBoxImpl::CaretFromEdge() {
1188 return 4 + GETLBW(id
)->IconWidth();
1192 void ListBoxImpl::Clear() {
1193 GETLB(id
)->DeleteAllItems();
1197 void ListBoxImpl::Append(char *s
, int type
) {
1198 Append(stc2wx(s
), type
);
1201 void ListBoxImpl::Append(const wxString
& text
, int type
) {
1202 long count
= GETLB(id
)->GetItemCount();
1203 long itemID
= GETLB(id
)->InsertItem(count
, wxEmptyString
);
1204 GETLB(id
)->SetItem(itemID
, 1, text
);
1205 maxStrWidth
= wxMax(maxStrWidth
, text
.length());
1207 wxCHECK_RET(imgTypeMap
, wxT("Unexpected NULL imgTypeMap"));
1208 long idx
= imgTypeMap
->Item(type
);
1209 GETLB(id
)->SetItemImage(itemID
, idx
, idx
);
1213 void ListBoxImpl::SetList(const char* list
, char separator
, char typesep
) {
1214 GETLB(id
)->Freeze();
1216 wxStringTokenizer
tkzr(stc2wx(list
), (wxChar
)separator
);
1217 while ( tkzr
.HasMoreTokens() ) {
1218 wxString token
= tkzr
.GetNextToken();
1220 int pos
= token
.Find(typesep
);
1222 token
.Mid(pos
+1).ToLong(&type
);
1223 token
.Truncate(pos
);
1225 Append(token
, (int)type
);
1231 int ListBoxImpl::Length() {
1232 return GETLB(id
)->GetItemCount();
1236 void ListBoxImpl::Select(int n
) {
1242 GETLB(id
)->EnsureVisible(n
);
1243 GETLB(id
)->Select(n
, select
);
1247 int ListBoxImpl::GetSelection() {
1248 return GETLB(id
)->GetFirstSelected();
1252 int ListBoxImpl::Find(const char *WXUNUSED(prefix
)) {
1258 void ListBoxImpl::GetValue(int n
, char *value
, int len
) {
1262 item
.SetMask(wxLIST_MASK_TEXT
);
1263 GETLB(id
)->GetItem(item
);
1264 strncpy(value
, wx2stc(item
.GetText()), len
);
1265 value
[len
-1] = '\0';
1269 void ListBoxImpl::RegisterImage(int type
, const char *xpm_data
) {
1270 wxMemoryInputStream
stream(xpm_data
, strlen(xpm_data
)+1);
1271 wxImage
img(stream
, wxBITMAP_TYPE_XPM
);
1275 // assumes all images are the same size
1276 imgList
= new wxImageList(bmp
.GetWidth(), bmp
.GetHeight(), true);
1277 imgTypeMap
= new wxArrayInt
;
1280 int idx
= imgList
->Add(bmp
);
1282 // do we need to extend the mapping array?
1283 wxArrayInt
& itm
= *imgTypeMap
;
1284 if ( itm
.GetCount() < (size_t)type
+1)
1285 itm
.Add(-1, type
- itm
.GetCount() + 1);
1287 // Add an item that maps type to the image index
1291 void ListBoxImpl::ClearRegisteredImages() {
1301 GETLB(id
)->SetImageList(NULL
, wxIMAGE_LIST_SMALL
);
1305 void ListBoxImpl::SetDoubleClickAction(CallBackAction action
, void *data
) {
1306 GETLBW(id
)->SetDoubleClickAction(action
, data
);
1310 ListBox::ListBox() {
1313 ListBox::~ListBox() {
1316 ListBox
*ListBox::Allocate() {
1317 return new ListBoxImpl();
1320 //----------------------------------------------------------------------
1322 Menu::Menu() : id(0) {
1325 void Menu::CreatePopUp() {
1330 void Menu::Destroy() {
1336 void Menu::Show(Point pt
, Window
&w
) {
1337 GETWIN(w
.GetID())->PopupMenu((wxMenu
*)id
, pt
.x
- 4, pt
.y
);
1341 //----------------------------------------------------------------------
1343 DynamicLibrary
*DynamicLibrary::Load(const char *WXUNUSED(modulePath
)) {
1344 wxFAIL_MSG(wxT("Dynamic lexer loading not implemented yet"));
1348 //----------------------------------------------------------------------
1350 ColourDesired
Platform::Chrome() {
1352 c
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE
);
1353 return ColourDesired(c
.Red(), c
.Green(), c
.Blue());
1356 ColourDesired
Platform::ChromeHighlight() {
1358 c
= wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT
);
1359 return ColourDesired(c
.Red(), c
.Green(), c
.Blue());
1362 const char *Platform::DefaultFont() {
1363 static char buf
[128];
1364 strcpy(buf
, wxNORMAL_FONT
->GetFaceName().mbc_str());
1368 int Platform::DefaultFontSize() {
1369 return wxNORMAL_FONT
->GetPointSize();
1372 unsigned int Platform::DoubleClickTime() {
1373 return 500; // **** ::GetDoubleClickTime();
1376 bool Platform::MouseButtonBounce() {
1380 bool Platform::IsKeyDown(int WXUNUSED(key
)) {
1381 return false; // I don't think we'll need this.
1384 long Platform::SendScintilla(WindowID w
,
1386 unsigned long wParam
,
1389 wxStyledTextCtrl
* stc
= (wxStyledTextCtrl
*)w
;
1390 return stc
->SendMsg(msg
, wParam
, lParam
);
1393 long Platform::SendScintillaPointer(WindowID w
,
1395 unsigned long wParam
,
1398 wxStyledTextCtrl
* stc
= (wxStyledTextCtrl
*)w
;
1399 return stc
->SendMsg(msg
, wParam
, (long)lParam
);
1403 // These are utility functions not really tied to a platform
1405 int Platform::Minimum(int a
, int b
) {
1412 int Platform::Maximum(int a
, int b
) {
1421 void Platform::DebugDisplay(const char *s
) {
1423 wxLogDebug(stc2wx(s
));
1429 void Platform::DebugPrintf(const char *format
, ...) {
1433 va_start(pArguments
, format
);
1434 vsprintf(buffer
,format
,pArguments
);
1436 Platform::DebugDisplay(buffer
);
1441 static bool assertionPopUps
= true;
1443 bool Platform::ShowAssertionPopUps(bool assertionPopUps_
) {
1444 bool ret
= assertionPopUps
;
1445 assertionPopUps
= assertionPopUps_
;
1449 void Platform::Assert(const char *c
, const char *file
, int line
) {
1452 sprintf(buffer
, "Assertion [%s] failed at %s %d", c
, file
, line
);
1453 if (assertionPopUps
) {
1455 wxMessageBox(stc2wx(buffer
),
1456 wxT("Assertion failure"),
1457 wxICON_HAND
| wxOK
);
1459 strcat(buffer
, "\r\n");
1460 Platform::DebugDisplay(buffer
);
1471 int Platform::Clamp(int val
, int minVal
, int maxVal
) {
1480 bool Platform::IsDBCSLeadByte(int WXUNUSED(codePage
), char WXUNUSED(ch
)) {
1484 int Platform::DBCSCharLength(int WXUNUSED(codePage
), const char *WXUNUSED(s
)) {
1488 int Platform::DBCSCharMaxLength() {
1493 //----------------------------------------------------------------------
1495 ElapsedTime::ElapsedTime() {
1496 wxLongLong localTime
= wxGetLocalTimeMillis();
1497 littleBit
= localTime
.GetLo();
1498 bigBit
= localTime
.GetHi();
1501 double ElapsedTime::Duration(bool reset
) {
1502 wxLongLong
prevTime(bigBit
, littleBit
);
1503 wxLongLong localTime
= wxGetLocalTimeMillis();
1505 littleBit
= localTime
.GetLo();
1506 bigBit
= localTime
.GetHi();
1508 wxLongLong duration
= localTime
- prevTime
;
1509 double result
= duration
.ToDouble();
1515 //----------------------------------------------------------------------
1519 #include "UniConversion.h"
1521 // Convert using Scintilla's functions instead of wx's, Scintilla's are more
1522 // forgiving and won't assert...
1524 wxString
stc2wx(const char* str
, size_t len
)
1527 return wxEmptyString
;
1529 size_t wclen
= UCS2Length(str
, len
);
1530 wxWCharBuffer
buffer(wclen
+1);
1532 size_t actualLen
= UCS2FromUTF8(str
, len
, buffer
.data(), wclen
+1);
1533 return wxString(buffer
.data(), actualLen
);
1538 wxString
stc2wx(const char* str
)
1540 return stc2wx(str
, strlen(str
));
1544 const wxWX2MBbuf
wx2stc(const wxString
& str
)
1546 const wchar_t* wcstr
= str
.c_str();
1547 size_t wclen
= str
.length();
1548 size_t len
= UTF8Length(wcstr
, wclen
);
1550 wxCharBuffer
buffer(len
+1);
1551 UTF8FromUCS2(wcstr
, wclen
, buffer
.data(), len
);
1553 // TODO check NULL termination!!