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!!