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/wxscintilla.h"
21
Point Point::FromLong(long lpoint) {
22
return Point(lpoint & 0xFFFF, lpoint >> 16);
25
wxRect wxRectFromPRectangle(PRectangle prc) {
26
wxRect r(prc.left, prc.top,
27
prc.Width(), prc.Height());
30
PRectangle PRectangleFromwxRect(wxRect rc) {
31
return PRectangle(rc.GetLeft(), rc.GetTop(),
32
rc.GetRight()+1, rc.GetBottom()+1);
35
wxColour wxColourFromCA(const ColourAllocated& ca) {
36
ColourDesired cd(ca.AsLong());
37
return wxColour((unsigned char)cd.GetRed(),
38
(unsigned char)cd.GetGreen(),
39
(unsigned char)cd.GetBlue());
42
//----------------------------------------------------------------------
46
allowRealization = false;
53
void Palette::Release() {
57
// This method either adds a colour to the list of wanted colours (want==true)
58
// or retrieves the allocated colour back to the ColourPair.
59
// This is one method to make it easier to keep the code for wanting and retrieving in sync.
60
void Palette::WantFind(ColourPair &cp, bool want) {
62
for (int i=0; i < used; i++) {
63
if (entries[i].desired == cp.desired)
67
if (used < numEntries) {
68
entries[used].desired = cp.desired;
69
entries[used].allocated.Set(cp.desired.AsLong());
73
for (int i=0; i < used; i++) {
74
if (entries[i].desired == cp.desired) {
75
cp.allocated = entries[i].allocated;
79
cp.allocated.Set(cp.desired.AsLong());
83
void Palette::Allocate(Window &) {
84
if (allowRealization) {
89
//----------------------------------------------------------------------
99
void Font::Create (const char *faceName, int characterSet, int size,
100
bool bold, bool italic, bool extraFontFlag) {
103
// The minus one is done because since Scintilla uses SC_SHARSET_DEFAULT
104
// internally and we need to have wxFONENCODING_DEFAULT == SC_SHARSET_DEFAULT
105
// so we adjust the encoding before passing it to Scintilla. See also
106
// wxScintilla::StyleSetCharacterSet
107
wxFontEncoding encoding = (wxFontEncoding)(characterSet-1);
109
wxFontEncodingArray ea = wxEncodingConverter::GetPlatformEquivalents(encoding);
110
if (ea.GetCount()) encoding = ea[0];
112
wxFont* font = new wxFont (size, wxDEFAULT,
113
italic ? wxITALIC : wxNORMAL,
114
bold ? wxBOLD : wxNORMAL,
118
font->SetNoAntiAliasing (!extraFontFlag);
123
void Font::Release() {
129
//----------------------------------------------------------------------
131
class SurfaceImpl : public Surface {
144
virtual void Init(WindowID wid);
145
virtual void Init(SurfaceID sid, WindowID wid);
146
virtual void InitPixMap(int width, int height, Surface *surface_, WindowID wid);
148
virtual void Release();
149
virtual bool Initialised();
150
virtual void PenColour(ColourAllocated fore);
151
virtual int LogPixelsY();
152
virtual int DeviceHeightFont(int points);
153
virtual void MoveTo(int x_, int y_);
154
virtual void LineTo(int x_, int y_);
155
virtual void Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back);
156
virtual void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back);
157
virtual void FillRectangle(PRectangle rc, ColourAllocated back);
158
virtual void FillRectangle(PRectangle rc, Surface &surfacePattern);
159
virtual void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back);
160
virtual void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back);
161
virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource);
163
virtual void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
164
virtual void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
165
virtual void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);
166
virtual void MeasureWidths(Font &font_, const char *s, int len, int *positions);
167
virtual int WidthText(Font &font_, const char *s, int len);
168
virtual int WidthChar(Font &font_, char ch);
169
virtual int Ascent(Font &font_);
170
virtual int Descent(Font &font_);
171
virtual int InternalLeading(Font &font_);
172
virtual int ExternalLeading(Font &font_);
173
virtual int Height(Font &font_);
174
virtual int AverageCharWidth(Font &font_);
176
virtual int SetPalette(Palette *pal, bool inBackGround);
177
virtual void SetClip(PRectangle rc);
178
virtual void FlushCachedState();
180
virtual void SetUnicodeMode(bool unicodeMode_);
181
virtual void SetDBCSMode(int codePage);
183
void BrushColour(ColourAllocated back);
184
void SetFont(Font &font_);
189
SurfaceImpl::SurfaceImpl() :
190
hdc(0), hdcOwned(0), bitmap(0),
191
x(0), y(0), unicodeMode(0)
194
SurfaceImpl::~SurfaceImpl() {
198
void SurfaceImpl::Init(WindowID wid) {
201
hdc = new wxMemoryDC();
204
// On Mac and GTK the DC is not really valid until it has a bitmap
205
// selected into it. So instead of just creating the DC with no bitmap,
206
// go ahead and give it one.
207
InitPixMap(1,1,NULL,wid);
211
void SurfaceImpl::Init(SurfaceID hdc_, WindowID) {
216
void SurfaceImpl::InitPixMap(int width, int height, Surface *WXUNUSED(surface_), WindowID) {
218
hdc = new wxMemoryDC();
220
if (width < 1) width = 1;
221
if (height < 1) height = 1;
222
bitmap = new wxBitmap(width, height);
223
((wxMemoryDC*)hdc)->SelectObject(*bitmap);
227
void SurfaceImpl::Release() {
229
((wxMemoryDC*)hdc)->SelectObject(wxNullBitmap);
241
bool SurfaceImpl::Initialised() {
246
void SurfaceImpl::PenColour(ColourAllocated fore) {
247
hdc->SetPen(wxPen(wxColourFromCA(fore), 1, wxSOLID));
250
void SurfaceImpl::BrushColour(ColourAllocated back) {
251
hdc->SetBrush(wxBrush(wxColourFromCA(back), wxSOLID));
254
void SurfaceImpl::SetFont(Font &font_) {
256
hdc->SetFont(*((wxFont*)font_.GetID()));
260
int SurfaceImpl::LogPixelsY() {
261
return hdc->GetPPI().y;
264
int SurfaceImpl::DeviceHeightFont(int points) {
268
void SurfaceImpl::MoveTo(int x_, int y_) {
273
void SurfaceImpl::LineTo(int x_, int y_) {
274
hdc->DrawLine(x,y, x_,y_);
279
void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) {
282
hdc->DrawPolygon(npts, (wxPoint*)pts);
285
void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
288
hdc->DrawRectangle(wxRectFromPRectangle(rc));
291
void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) {
293
hdc->SetPen(*wxTRANSPARENT_PEN);
294
hdc->DrawRectangle(wxRectFromPRectangle(rc));
297
void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
299
if (((SurfaceImpl&)surfacePattern).bitmap)
300
br = wxBrush(*((SurfaceImpl&)surfacePattern).bitmap);
301
else // Something is wrong so display in red
302
br = wxBrush(*wxRED, wxSOLID);
303
hdc->SetPen(*wxTRANSPARENT_PEN);
305
hdc->DrawRectangle(wxRectFromPRectangle(rc));
308
void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
311
hdc->DrawRoundedRectangle(wxRectFromPRectangle(rc), 4);
314
void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
317
hdc->DrawEllipse(wxRectFromPRectangle(rc));
320
void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
321
wxRect r = wxRectFromPRectangle(rc);
322
hdc->Blit(r.x, r.y, r.width, r.height,
323
((SurfaceImpl&)surfaceSource).hdc,
324
from.x, from.y, wxCOPY);
327
void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font, int ybase,
328
const char *s, int len,
329
ColourAllocated fore, ColourAllocated back) {
331
hdc->SetTextForeground(wxColourFromCA(fore));
332
hdc->SetTextBackground(wxColourFromCA(back));
333
FillRectangle(rc, back);
335
// ybase is where the baseline should be, but wxWin uses the upper left
336
// corner, so I need to calculate the real position for the text...
337
hdc->DrawText(sci2wx(s, len), rc.left, ybase - font.ascent);
340
void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font, int ybase,
341
const char *s, int len,
342
ColourAllocated fore, ColourAllocated back) {
344
hdc->SetTextForeground(wxColourFromCA(fore));
345
hdc->SetTextBackground(wxColourFromCA(back));
346
FillRectangle(rc, back);
347
hdc->SetClippingRegion(wxRectFromPRectangle(rc));
349
// see comments above
350
hdc->DrawText(sci2wx(s, len), rc.left, ybase - font.ascent);
351
hdc->DestroyClippingRegion();
355
void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font, int ybase,
356
const char *s, int len,
357
ColourAllocated fore) {
360
hdc->SetTextForeground(wxColourFromCA(fore));
361
hdc->SetBackgroundMode(wxTRANSPARENT);
363
// ybase is where the baseline should be, but wxWin uses the upper left
364
// corner, so I need to calculate the real position for the text...
365
hdc->DrawText(sci2wx(s, len), rc.left, ybase - font.ascent);
367
hdc->SetBackgroundMode(wxSOLID);
371
void SurfaceImpl::MeasureWidths(Font &font, const char *s, int len, int *positions) {
373
wxString str = sci2wx(s, len);
376
#if !wxCHECK_VERSION(2, 5, 0)
378
// Calculate the position of each character based on the widths of
379
// the previous characters
380
int* tpos = new int[len+1];
383
for (i=0; i<str.Length(); i++) {
385
hdc->GetTextExtent(str[i], &w, &h);
387
tpos[i] = totalWidth;
390
// Instead of a running total, remeasure from the begining of the
391
// text for each character's position. This is because with AA fonts
392
// on OS X widths can be fractions of pixels wide when more than one
393
// are drawn together, so the sum of all character widths is not necessarily
394
// (and probably not) the same as the whole string width.
395
int* tpos = new int[len+1];
397
for (i=0; i<str.Length(); i++) {
399
hdc->GetTextExtent(str.Left(i+1), &w, &h);
405
hdc->GetPartialTextExtents(str, tpos);
410
// Map the widths for UCS-2 characters back to the UTF-8 input string
411
// NOTE: I don't think this is right for when sizeof(wxChar) > 2, ie wxGTK2
412
// so figure it out and fix it!
415
while ((int)j < len) {
416
unsigned char uch = (unsigned char)s[j];
417
positions[j++] = tpos[ui];
419
if (uch < (0x80 + 0x40 + 0x20)) {
420
positions[j++] = tpos[ui];
422
positions[j++] = tpos[ui];
423
positions[j++] = tpos[ui];
430
// If not unicode then just use the widths we have
431
#if !wxCHECK_VERSION(2, 5, 0)
432
memcpy(positions, tpos, len * sizeof(*tpos));
435
std::copy(tpos.begin(), tpos.end(), positions);
437
memcpy(positions, tpos.begin(), len * sizeof(int));
442
#if !wxCHECK_VERSION(2, 5, 0)
448
int SurfaceImpl::WidthText(Font &font, const char *s, int len) {
453
hdc->GetTextExtent(sci2wx(s, len), &w, &h);
458
int SurfaceImpl::WidthChar(Font &font, char ch) {
462
char s[2] = { ch, 0 };
464
hdc->GetTextExtent(sci2wx(s, 1), &w, &h);
468
#define EXTENT_TEST wxT(" `~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
470
int SurfaceImpl::Ascent(Font &font) {
473
hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
478
int SurfaceImpl::Descent(Font &font) {
481
hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
485
int SurfaceImpl::InternalLeading(Font &WXUNUSED(font)) {
489
int SurfaceImpl::ExternalLeading(Font &font) {
492
hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
496
int SurfaceImpl::Height(Font &font) {
498
return hdc->GetCharHeight() + 1;
501
int SurfaceImpl::AverageCharWidth(Font &font) {
503
return hdc->GetCharWidth();
506
int SurfaceImpl::SetPalette(Palette *WXUNUSED(pal), bool WXUNUSED(inBackGround)) {
510
void SurfaceImpl::SetClip(PRectangle rc) {
511
hdc->SetClippingRegion(wxRectFromPRectangle(rc));
514
void SurfaceImpl::FlushCachedState() {
517
void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {
518
unicodeMode=unicodeMode_;
521
void SurfaceImpl::SetDBCSMode(int WXUNUSED(codePage)) {
522
// dbcsMode = codePage == SC_CP_DBCS;
526
Surface *Surface::Allocate() {
527
return new SurfaceImpl;
531
//----------------------------------------------------------------------
534
inline wxWindow* GETWIN(WindowID id) { return (wxWindow*)id; }
539
void Window::Destroy() {
542
GETWIN(id)->Destroy();
547
bool Window::HasFocus() {
548
return wxWindow::FindFocus() == GETWIN(id);
551
PRectangle Window::GetPosition() {
552
if (! id) return PRectangle();
553
wxRect rc(GETWIN(id)->GetPosition(), GETWIN(id)->GetSize());
554
return PRectangleFromwxRect(rc);
557
void Window::SetPosition(PRectangle rc) {
558
wxRect r = wxRectFromPRectangle(rc);
559
GETWIN(id)->SetSize(r);
562
void Window::SetPositionRelative(PRectangle rc, Window) {
563
SetPosition(rc); // ????
566
PRectangle Window::GetClientPosition() {
567
if (! id) return PRectangle();
568
wxSize sz = GETWIN(id)->GetClientSize();
569
return PRectangle(0, 0, sz.x, sz.y);
572
void Window::Show(bool show) {
573
GETWIN(id)->Show(show);
576
void Window::InvalidateAll() {
577
GETWIN(id)->Refresh(false);
581
void Window::InvalidateRectangle(PRectangle rc) {
582
wxRect r = wxRectFromPRectangle(rc);
583
GETWIN(id)->Refresh(false, &r);
587
void Window::SetFont(Font &font) {
588
GETWIN(id)->SetFont(*((wxFont*)font.GetID()));
591
void Window::SetCursor(Cursor curs) {
596
cursorId = wxCURSOR_IBEAM;
599
cursorId = wxCURSOR_ARROW;
602
cursorId = wxCURSOR_ARROW; // ** no up arrow... wxCURSOR_UPARROW;
605
cursorId = wxCURSOR_WAIT;
608
cursorId = wxCURSOR_SIZEWE;
611
cursorId = wxCURSOR_SIZENS;
613
case cursorReverseArrow:
614
cursorId = wxCURSOR_RIGHT_ARROW;
617
cursorId = wxCURSOR_HAND;
620
cursorId = wxCURSOR_ARROW;
624
wxCursor wc = wxStockCursor(cursorId) ;
626
wxCursor wc = wxCursor(cursorId) ;
628
if(curs != cursorLast) {
629
GETWIN(id)->SetCursor(wc);
635
void Window::SetTitle (const char *s) {
636
GETWIN(id)->SetLabel (sci2wx(s));
640
//----------------------------------------------------------------------
641
// Helper classes for ListBox
644
// This is a simple subclass of wxListView that just resets focus to the
645
// parent when it gets it.
646
class wxSCIListBox : public wxListView {
648
wxSCIListBox (wxWindow* parent, wxWindowID id,
649
const wxPoint& pos, const wxSize& size,
650
long style) : wxListView() {
652
Hide(); // don't flicker as we move it around...
654
Create(parent, id, pos, size, style);
657
void OnFocus(wxFocusEvent& event) {
658
GetParent()->SetFocus();
662
void OnKillFocus(wxFocusEvent& WXUNUSED(event)) {
663
// Do nothing. Prevents base class from resetting the colors...
667
// For some reason I don't understand yet the focus doesn't really leave
668
// the listbox like it should, so if we get any events feed them back to
670
void OnKeyDown(wxKeyEvent& event) {
671
GetGrandParent()->GetEventHandler()->ProcessEvent(event);
673
void OnChar(wxKeyEvent& event) {
674
GetGrandParent()->GetEventHandler()->ProcessEvent(event);
677
// And we need to force the focus back when being destroyed
679
GetGrandParent()->SetFocus();
684
DECLARE_EVENT_TABLE()
687
BEGIN_EVENT_TABLE(wxSCIListBox, wxListView)
688
EVT_SET_FOCUS( wxSCIListBox::OnFocus)
689
EVT_KILL_FOCUS(wxSCIListBox::OnKillFocus)
691
EVT_KEY_DOWN( wxSCIListBox::OnKeyDown)
692
EVT_CHAR( wxSCIListBox::OnChar)
697
#if wxUSE_POPUPWIN //-----------------------------------
698
#include <wx/popupwin.h>
700
// TODO: Refactor these two classes to have a common base (or a mix-in) to get
701
// rid of the code duplication. (Either that or convince somebody to
702
// implement wxPopupWindow for the Mac!!)
704
// In the meantime, be careful to duplicate any changes as needed...
706
// A popup window to place the wxSCIListBox upon
707
class wxSCIListBoxWin : public wxPopupWindow
711
CallBackAction doubleClickAction;
712
void* doubleClickActionData;
714
wxSCIListBoxWin(wxWindow* parent, wxWindowID id) :
715
wxPopupWindow(parent, wxBORDER_NONE)
717
SetBackgroundColour(*wxBLACK); // for our simple border
719
lv = new wxSCIListBox(this, id, wxDefaultPosition, wxDefaultSize,
720
wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_NO_HEADER | wxBORDER_NONE);
721
lv->SetCursor(wxCursor(wxCURSOR_ARROW));
722
lv->InsertColumn(0, wxEmptyString);
723
lv->InsertColumn(1, wxEmptyString);
725
// NOTE: We need to fool the wxListView into thinking that it has the
726
// focus so it will use the normal selection colour and will look
727
// "right" to the user. But since the wxPopupWindow or its children
728
// can't receive focus then we have to pull a fast one and temporarily
729
// parent the listctrl on the STC window and then call SetFocus and
730
// then reparent it back to the popup.
732
// lv->Reparent(this);
734
// NOTE (mandrav): Removed the above hack because it causes bad flickering in C::B.
735
// I prefer having a "gray" (non-focused) selection, than this
743
// Set position in client coords
744
virtual void DoSetSize(int x, int y,
745
int width, int height,
746
int sizeFlags = wxSIZE_AUTO) {
747
#if !wxCHECK_VERSION(2, 5, 0)
750
if (x != wxDefaultCoord) {
752
GetParent()->ClientToScreen(&x, NULL);
754
#if !wxCHECK_VERSION(2, 5, 0)
757
if (y != wxDefaultCoord) {
759
GetParent()->ClientToScreen(NULL, &y);
761
wxPopupWindow::DoSetSize(x, y, width, height, sizeFlags);
764
// return position as if it were in client coords
765
virtual void DoGetPosition( int *x, int *y ) const {
767
wxPopupWindow::DoGetPosition(&sx, &sy);
768
GetParent()->ScreenToClient(&sx, &sy);
775
if ( !wxPendingDelete.Member(this) )
776
wxPendingDelete.Append(this);
782
wxImageList* il = lv->GetImageList(wxIMAGE_LIST_SMALL);
785
il->GetSize(0, w, h);
792
void SetDoubleClickAction(CallBackAction action, void *data) {
793
doubleClickAction = action;
794
doubleClickActionData = data;
798
void OnFocus(wxFocusEvent& event) {
799
GetParent()->SetFocus();
803
void OnSize(wxSizeEvent& event) {
805
wxSize sz = GetSize();
808
lv->SetSize(1, 1, sz.x, sz.y);
809
// reset the column widths
810
lv->SetColumnWidth(0, IconWidth()+4);
811
lv->SetColumnWidth(1, sz.x - 2 - lv->GetColumnWidth(0) -
812
wxSystemSettings::GetMetric(wxSYS_VSCROLL_X));
816
void OnActivate(wxListEvent& WXUNUSED(event)) {
817
doubleClickAction(doubleClickActionData);
820
wxListView* GetLB() { return lv; }
823
DECLARE_EVENT_TABLE()
827
BEGIN_EVENT_TABLE(wxSCIListBoxWin, wxPopupWindow)
828
EVT_SET_FOCUS ( wxSCIListBoxWin::OnFocus)
829
EVT_SIZE ( wxSCIListBoxWin::OnSize)
830
EVT_LIST_ITEM_ACTIVATED(wxID_ANY, wxSCIListBoxWin::OnActivate)
833
#else // wxUSE_POPUPWIN -----------------------------------
835
// A normal window to place the wxSCIListBox upon.
836
class wxSCIListBoxWin : public wxWindow {
839
CallBackAction doubleClickAction;
840
void* doubleClickActionData;
842
wxSCIListBoxWin(wxWindow* parent, wxWindowID id) :
843
wxWindow(parent, id, wxDefaultPosition, wxSize(0,0), wxSIMPLE_BORDER )
846
lv = new wxSCIListBox(this, id, wxDefaultPosition, wxDefaultSize,
847
wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_NO_HEADER | wxNO_BORDER);
848
lv->SetCursor(wxCursor(wxCURSOR_ARROW));
849
lv->InsertColumn(0, wxEmptyString);
850
lv->InsertColumn(1, wxEmptyString);
852
// Eventhough we immediately reset the focus to the parent, this helps
853
// things to look right...
860
// On OSX and (possibly others) there can still be pending
861
// messages/events for the list control when Scintilla wants to
862
// close it, so do a pending delete of it instead of destroying
866
// The bottom edge of this window is not getting properly
867
// refreshed upon deletion, so help it out...
868
wxWindow* p = GetParent();
869
wxRect r(GetPosition(), GetSize());
870
r.SetHeight(r.GetHeight()+1);
871
p->Refresh(false, &r);
873
if ( !wxPendingDelete.Member(this) )
874
wxPendingDelete.Append(this);
880
wxImageList* il = lv->GetImageList(wxIMAGE_LIST_SMALL);
883
il->GetSize(0, w, h);
890
void SetDoubleClickAction(CallBackAction action, void *data) {
891
doubleClickAction = action;
892
doubleClickActionData = data;
896
void OnFocus(wxFocusEvent& event) {
897
GetParent()->SetFocus();
901
void OnSize(wxSizeEvent& event) {
903
wxSize sz = GetClientSize();
905
// reset the column widths
906
lv->SetColumnWidth(0, IconWidth()+4);
907
lv->SetColumnWidth(1, sz.x - 2 - lv->GetColumnWidth(0) -
908
wxSystemSettings::GetMetric(wxSYS_VSCROLL_X));
913
virtual bool Show(bool show = true) {
914
bool rv = wxWindow::Show(show);
915
GetParent()->Refresh(false);
920
void OnActivate(wxListEvent& WXUNUSED(event)) {
921
doubleClickAction(doubleClickActionData);
924
wxListView* GetLB() { return lv; }
927
DECLARE_EVENT_TABLE()
931
BEGIN_EVENT_TABLE(wxSCIListBoxWin, wxWindow)
932
EVT_SET_FOCUS ( wxSCIListBoxWin::OnFocus)
933
EVT_SIZE ( wxSCIListBoxWin::OnSize)
934
EVT_LIST_ITEM_ACTIVATED(wxID_ANY, wxSCIListBoxWin::OnActivate)
937
#endif // wxUSE_POPUPWIN -----------------------------------
939
inline wxSCIListBoxWin* GETLBW(WindowID win) {
940
return ((wxSCIListBoxWin*)win);
943
inline wxListView* GETLB(WindowID win) {
944
return GETLBW(win)->GetLB();
947
//----------------------------------------------------------------------
949
class ListBoxImpl : public ListBox {
953
int desiredVisibleRows;
956
wxImageList* imgList;
957
wxArrayInt* imgTypeMap;
963
virtual void SetFont(Font &font);
964
virtual void Create(Window &parent, int ctrlID, Point location, int lineHeight_, bool unicodeMode_);
965
virtual void SetAverageCharWidth(int width);
966
virtual void SetVisibleRows(int rows);
967
virtual int GetVisibleRows() const;
968
virtual PRectangle GetDesiredRect();
969
virtual int CaretFromEdge();
970
virtual void Clear();
971
virtual void Append(char *s, int type = -1);
972
virtual int Length();
973
virtual void Select(int n);
974
virtual int GetSelection();
975
virtual int Find(const char *prefix);
976
virtual void GetValue(int n, char *value, int len);
977
virtual void RegisterImage(int type, const char *xpm_data);
978
virtual void ClearRegisteredImages();
979
virtual void SetDoubleClickAction(CallBackAction, void *);
980
virtual void SetList(const char* list, char separator, char typesep);
985
ListBoxImpl::ListBoxImpl()
986
: lineHeight(10), unicodeMode(false),
987
desiredVisibleRows(5), aveCharWidth(8), maxStrWidth(0),
988
imgList(NULL), imgTypeMap(NULL)
992
ListBoxImpl::~ListBoxImpl() {
1004
void ListBoxImpl::SetFont(Font &font) {
1005
GETLB(id)->SetFont(*((wxFont*)font.GetID()));
1009
void ListBoxImpl::Create (Window &parent, int ctrlID, Point WXUNUSED(location),
1010
int lineHeight_, bool unicodeMode_) {
1011
lineHeight = lineHeight_;
1012
unicodeMode = unicodeMode_;
1014
id = new wxSCIListBoxWin (GETWIN(parent.GetID()), ctrlID);
1015
if (imgList != NULL) GETLB(id)->SetImageList (imgList, wxIMAGE_LIST_SMALL);
1019
void ListBoxImpl::SetAverageCharWidth(int width) {
1020
aveCharWidth = width;
1024
void ListBoxImpl::SetVisibleRows(int rows) {
1025
desiredVisibleRows = rows;
1029
int ListBoxImpl::GetVisibleRows() const {
1030
return desiredVisibleRows;
1034
PRectangle ListBoxImpl::GetDesiredRect() {
1035
// wxListCtrl doesn't have a DoGetBestSize, so instead we kept track of
1036
// the max size in Append and calculate it here...
1037
int maxw = maxStrWidth;
1040
// give it a default if there are no lines, and/or add a bit more
1041
if (maxw == 0) maxw = 100;
1042
maxw += aveCharWidth * 3 +
1043
GETLBW(id)->IconWidth() + wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
1047
// estimate a desired height
1048
int count = GETLB(id)->GetItemCount();
1051
GETLB(id)->GetItemRect(0, rect);
1052
maxh = count * rect.GetHeight();
1053
if (maxh > 140) // TODO: Use desiredVisibleRows??
1056
// Try to make the size an exact multiple of some number of lines
1057
int lines = maxh / rect.GetHeight();
1058
maxh = (lines + 1) * rect.GetHeight() + 2;
1072
int ListBoxImpl::CaretFromEdge() {
1073
return 4 + GETLBW(id)->IconWidth();
1077
void ListBoxImpl::Clear() {
1078
GETLB(id)->DeleteAllItems();
1082
void ListBoxImpl::Append(char *s, int type) {
1083
wxString text = sci2wx(s);
1084
long count = GETLB(id)->GetItemCount();
1085
long itemID = GETLB(id)->InsertItem(count, wxEmptyString);
1086
GETLB(id)->SetItem(itemID, 1, text);
1088
GETLB(id)->GetTextExtent(text, &itemWidth, NULL);
1089
maxStrWidth = wxMax(maxStrWidth, itemWidth);
1091
wxCHECK_RET(imgTypeMap, wxT("Unexpected NULL imgTypeMap"));
1092
long idx = imgTypeMap->Item(type);
1093
GETLB(id)->SetItemImage(itemID, idx, idx);
1098
int ListBoxImpl::Length() {
1099
return GETLB(id)->GetItemCount();
1103
void ListBoxImpl::Select(int n) {
1109
GETLB(id)->Focus(n);
1110
GETLB(id)->Select(n, select);
1114
int ListBoxImpl::GetSelection() {
1115
return GETLB(id)->GetFirstSelected();
1119
int ListBoxImpl::Find(const char *WXUNUSED(prefix)) {
1125
void ListBoxImpl::GetValue(int n, char *value, int len) {
1129
item.SetMask(wxLIST_MASK_TEXT);
1130
GETLB(id)->GetItem(item);
1131
strncpy(value, wx2sci(item.GetText()), len);
1132
value[len-1] = '\0';
1136
void ListBoxImpl::RegisterImage(int type, const char *xpm_data) {
1137
wxMemoryInputStream stream(xpm_data, strlen(xpm_data)+1);
1138
wxImage img(stream, wxBITMAP_TYPE_XPM);
1142
// assumes all images are the same size
1143
imgList = new wxImageList(bmp.GetWidth(), bmp.GetHeight(), TRUE);
1144
imgTypeMap = new wxArrayInt;
1147
int idx = imgList->Add(bmp);
1149
// do we need to extend the mapping array?
1150
wxArrayInt& itm = *imgTypeMap;
1151
if ( itm.GetCount() < (size_t)type+1)
1152
itm.Add(-1, type - itm.GetCount() + 1);
1154
// Add an item that maps type to the image index
1158
void ListBoxImpl::ClearRegisteredImages() {
1167
if (id) GETLB(id)->SetImageList(NULL, wxIMAGE_LIST_SMALL);
1171
void ListBoxImpl::SetDoubleClickAction(CallBackAction action, void *data) {
1172
GETLBW(id)->SetDoubleClickAction(action, data);
1175
void ListBoxImpl::SetList(const char* list, char separator, char typesep) {
1177
char *words = new char[strlen(list) + 1];
1179
strcpy (words, list);
1180
char *startword = words;
1181
char *numword = NULL;
1183
for (; words && words[i]; i++) {
1184
if (words[i] == separator) {
1186
if (numword) *numword = '\0';
1187
Append (startword, numword?atoi(numword + 1):-1);
1188
startword = words + i + 1;
1190
} else if (words[i] == typesep) {
1191
numword = words + i;
1195
if (numword) *numword = '\0';
1196
Append(startword, numword?atoi(numword + 1):-1);
1203
ListBox::ListBox() {
1206
ListBox::~ListBox() {
1209
ListBox *ListBox::Allocate() {
1210
return new ListBoxImpl();
1213
//----------------------------------------------------------------------
1215
Menu::Menu() : id(0) {
1218
void Menu::CreatePopUp() {
1223
void Menu::Destroy() {
1229
void Menu::Show(Point pt, Window &w) {
1230
GETWIN(w.GetID())->PopupMenu((wxMenu*)id, pt.x - 4, pt.y);
1234
//----------------------------------------------------------------------
1236
DynamicLibrary *DynamicLibrary::Load(const char *WXUNUSED(modulePath)) {
1237
wxFAIL_MSG(wxT("Dynamic lexer loading not implemented yet"));
1241
//----------------------------------------------------------------------
1243
ColourDesired Platform::Chrome() {
1245
c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
1246
return ColourDesired(c.Red(), c.Green(), c.Blue());
1249
ColourDesired Platform::ChromeHighlight() {
1251
c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT);
1252
return ColourDesired(c.Red(), c.Green(), c.Blue());
1255
const char *Platform::DefaultFont() {
1256
static char buf[128];
1257
strcpy(buf, wxNORMAL_FONT->GetFaceName().mbc_str());
1261
int Platform::DefaultFontSize() {
1262
return wxNORMAL_FONT->GetPointSize();
1265
unsigned int Platform::DoubleClickTime() {
1266
return 500; // **** ::GetDoubleClickTime();
1269
bool Platform::MouseButtonBounce() {
1272
void Platform::DebugDisplay(const char *s) {
1273
wxLogDebug(sci2wx(s));
1276
bool Platform::IsKeyDown(int WXUNUSED(key)) {
1277
return false; // I don't think we'll need this.
1280
long Platform::SendScintilla(WindowID w,
1282
unsigned long wParam,
1285
wxScintilla* sci = (wxScintilla*)w;
1286
return sci->SendMsg(msg, wParam, lParam);
1289
long Platform::SendScintillaPointer(WindowID w,
1291
unsigned long wParam,
1294
wxScintilla* sci = (wxScintilla*)w;
1295
return sci->SendMsg(msg, wParam, (long)lParam);
1299
// These are utility functions not really tied to a platform
1301
int Platform::Minimum(int a, int b) {
1308
int Platform::Maximum(int a, int b) {
1317
void Platform::DebugPrintf(const char *format, ...) {
1321
va_start(pArguments, format);
1322
vsprintf(buffer,format,pArguments);
1324
Platform::DebugDisplay(buffer);
1329
static bool assertionPopUps = true;
1331
bool Platform::ShowAssertionPopUps(bool assertionPopUps_) {
1332
bool ret = assertionPopUps;
1333
assertionPopUps = assertionPopUps_;
1337
void Platform::Assert(const char *c, const char *file, int line) {
1339
sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line);
1340
if (assertionPopUps) {
1342
wxMessageBox(sci2wx(buffer),
1343
wxT("Assertion failure"),
1344
wxICON_HAND | wxOK);
1345
// if (idButton == IDRETRY) {
1347
// } else if (idButton == IDIGNORE) {
1353
strcat(buffer, "\r\n");
1354
Platform::DebugDisplay(buffer);
1360
int Platform::Clamp(int val, int minVal, int maxVal) {
1369
bool Platform::IsDBCSLeadByte(int WXUNUSED(codePage), char WXUNUSED(ch)) {
1373
int Platform::DBCSCharLength(int WXUNUSED(codePage), const char *WXUNUSED(s)) {
1377
int Platform::DBCSCharMaxLength() {
1382
//----------------------------------------------------------------------
1384
ElapsedTime::ElapsedTime() {
1385
m_StopWatch.Start();
1388
double ElapsedTime::Duration(bool reset) {
1389
double result = m_StopWatch.Time();
1391
m_StopWatch.Start();
1397
//----------------------------------------------------------------------
1401
#include "UniConversion.h"
1403
// Convert using Scintilla's functions instead of wx's, Scintilla's are more
1404
// forgiving and won't assert...
1406
wxString sci2wx(const char* str, size_t len)
1409
return wxEmptyString;
1411
size_t wclen = UCS2Length(str, len);
1412
wxWCharBuffer buffer(wclen+1);
1414
size_t actualLen = UCS2FromUTF8(str, len, buffer.data(), wclen+1);
1415
return wxString(buffer.data(), actualLen);
1418
const wxWX2MBbuf wx2stc(const wxString& str)
1420
const wchar_t* wcstr = str.c_str();
1421
size_t wclen = str.length();
1422
size_t len = UTF8Length(wcstr, wclen);
1424
wxCharBuffer buffer(len+1);
1425
UTF8FromUCS2(wcstr, wclen, buffer.data(), len);
1427
// TODO check NULL termination!!