]> git.saurik.com Git - wxWidgets.git/blame_incremental - src/stc/PlatWX.cpp
Added resize support to wxMiniFrame.
[wxWidgets.git] / src / stc / PlatWX.cpp
... / ...
CommitLineData
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.
6
7#include <ctype.h>
8
9#include "wx/wx.h"
10#include "wx/encconv.h"
11#include "wx/listctrl.h"
12#include "wx/mstream.h"
13#include "wx/image.h"
14#include "wx/imaglist.h"
15#include "wx/tokenzr.h"
16
17#include "Platform.h"
18#include "PlatWX.h"
19#include "wx/stc/stc.h"
20
21
22
23Point Point::FromLong(long lpoint) {
24 return Point(lpoint & 0xFFFF, lpoint >> 16);
25}
26
27wxRect wxRectFromPRectangle(PRectangle prc) {
28 wxRect r(prc.left, prc.top,
29 prc.Width(), prc.Height());
30 return r;
31}
32
33PRectangle PRectangleFromwxRect(wxRect rc) {
34 return PRectangle(rc.GetLeft(), rc.GetTop(),
35 rc.GetRight()+1, rc.GetBottom()+1);
36}
37
38wxColour 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());
43}
44
45//----------------------------------------------------------------------
46
47Palette::Palette() {
48 used = 0;
49 allowRealization = false;
50 size = 100;
51 entries = new ColourPair[size];
52}
53
54Palette::~Palette() {
55 Release();
56 delete [] entries;
57 entries = 0;
58}
59
60void Palette::Release() {
61 used = 0;
62 delete [] entries;
63 size = 100;
64 entries = new ColourPair[size];
65}
66
67// This method either adds a colour to the list of wanted colours (want==true)
68// or retrieves the allocated colour back to the ColourPair.
69// This is one method to make it easier to keep the code for wanting and retrieving in sync.
70void Palette::WantFind(ColourPair &cp, bool want) {
71 if (want) {
72 for (int i=0; i < used; i++) {
73 if (entries[i].desired == cp.desired)
74 return;
75 }
76
77 if (used >= size) {
78 int sizeNew = size * 2;
79 ColourPair *entriesNew = new ColourPair[sizeNew];
80 for (int j=0; j<size; j++) {
81 entriesNew[j] = entries[j];
82 }
83 delete []entries;
84 entries = entriesNew;
85 size = sizeNew;
86 }
87
88 entries[used].desired = cp.desired;
89 entries[used].allocated.Set(cp.desired.AsLong());
90 used++;
91 } else {
92 for (int i=0; i < used; i++) {
93 if (entries[i].desired == cp.desired) {
94 cp.allocated = entries[i].allocated;
95 return;
96 }
97 }
98 cp.allocated.Set(cp.desired.AsLong());
99 }
100}
101
102void Palette::Allocate(Window &) {
103 if (allowRealization) {
104 }
105}
106
107
108//----------------------------------------------------------------------
109
110Font::Font() {
111 id = 0;
112 ascent = 0;
113}
114
115Font::~Font() {
116}
117
118void Font::Create(const char *faceName, int characterSet, int size, bool bold, bool italic, bool extraFontFlag) {
119
120 Release();
121
122 // The minus one is done because since Scintilla uses SC_SHARSET_DEFAULT
123 // internally and we need to have wxFONENCODING_DEFAULT == SC_SHARSET_DEFAULT
124 // so we adjust the encoding before passing it to Scintilla. See also
125 // wxStyledTextCtrl::StyleSetCharacterSet
126 wxFontEncoding encoding = (wxFontEncoding)(characterSet-1);
127
128 wxFontEncodingArray ea = wxEncodingConverter::GetPlatformEquivalents(encoding);
129 if (ea.GetCount())
130 encoding = ea[0];
131
132 wxFont* font = new wxFont(size,
133 wxDEFAULT,
134 italic ? wxITALIC : wxNORMAL,
135 bold ? wxBOLD : wxNORMAL,
136 false,
137 stc2wx(faceName),
138 encoding);
139 font->SetNoAntiAliasing(!extraFontFlag);
140 id = font;
141}
142
143
144void Font::Release() {
145 if (id)
146 delete (wxFont*)id;
147 id = 0;
148}
149
150//----------------------------------------------------------------------
151
152class SurfaceImpl : public Surface {
153private:
154 wxDC* hdc;
155 bool hdcOwned;
156 wxBitmap* bitmap;
157 int x;
158 int y;
159 bool unicodeMode;
160
161public:
162 SurfaceImpl();
163 ~SurfaceImpl();
164
165 virtual void Init(WindowID wid);
166 virtual void Init(SurfaceID sid, WindowID wid);
167 virtual void InitPixMap(int width, int height, Surface *surface_, WindowID wid);
168
169 virtual void Release();
170 virtual bool Initialised();
171 virtual void PenColour(ColourAllocated fore);
172 virtual int LogPixelsY();
173 virtual int DeviceHeightFont(int points);
174 virtual void MoveTo(int x_, int y_);
175 virtual void LineTo(int x_, int y_);
176 virtual void Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back);
177 virtual void RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back);
178 virtual void FillRectangle(PRectangle rc, ColourAllocated back);
179 virtual void FillRectangle(PRectangle rc, Surface &surfacePattern);
180 virtual void RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back);
181 virtual void AlphaRectangle(PRectangle rc, int cornerSize, ColourAllocated fill, int alphaFill,
182 ColourAllocated outline, int alphaOutline, int flags);
183 virtual void Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back);
184 virtual void Copy(PRectangle rc, Point from, Surface &surfaceSource);
185
186 virtual void DrawTextNoClip(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
187 virtual void DrawTextClipped(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore, ColourAllocated back);
188 virtual void DrawTextTransparent(PRectangle rc, Font &font_, int ybase, const char *s, int len, ColourAllocated fore);
189 virtual void MeasureWidths(Font &font_, const char *s, int len, int *positions);
190 virtual int WidthText(Font &font_, const char *s, int len);
191 virtual int WidthChar(Font &font_, char ch);
192 virtual int Ascent(Font &font_);
193 virtual int Descent(Font &font_);
194 virtual int InternalLeading(Font &font_);
195 virtual int ExternalLeading(Font &font_);
196 virtual int Height(Font &font_);
197 virtual int AverageCharWidth(Font &font_);
198
199 virtual int SetPalette(Palette *pal, bool inBackGround);
200 virtual void SetClip(PRectangle rc);
201 virtual void FlushCachedState();
202
203 virtual void SetUnicodeMode(bool unicodeMode_);
204 virtual void SetDBCSMode(int codePage);
205
206 void BrushColour(ColourAllocated back);
207 void SetFont(Font &font_);
208};
209
210
211
212SurfaceImpl::SurfaceImpl() :
213 hdc(0), hdcOwned(0), bitmap(0),
214 x(0), y(0), unicodeMode(0)
215{}
216
217SurfaceImpl::~SurfaceImpl() {
218 Release();
219}
220
221void SurfaceImpl::Init(WindowID wid) {
222#if 0
223 Release();
224 hdc = new wxMemoryDC();
225 hdcOwned = true;
226#else
227 // On Mac and GTK the DC is not really valid until it has a bitmap
228 // selected into it. So instead of just creating the DC with no bitmap,
229 // go ahead and give it one.
230 InitPixMap(1,1,NULL,wid);
231#endif
232}
233
234void SurfaceImpl::Init(SurfaceID hdc_, WindowID) {
235 Release();
236 hdc = (wxDC*)hdc_;
237}
238
239void SurfaceImpl::InitPixMap(int width, int height, Surface *WXUNUSED(surface_), WindowID) {
240 Release();
241 hdc = new wxMemoryDC();
242 hdcOwned = true;
243 if (width < 1) width = 1;
244 if (height < 1) height = 1;
245 bitmap = new wxBitmap(width, height);
246 ((wxMemoryDC*)hdc)->SelectObject(*bitmap);
247}
248
249
250void SurfaceImpl::Release() {
251 if (bitmap) {
252 ((wxMemoryDC*)hdc)->SelectObject(wxNullBitmap);
253 delete bitmap;
254 bitmap = 0;
255 }
256 if (hdcOwned) {
257 delete hdc;
258 hdc = 0;
259 hdcOwned = false;
260 }
261}
262
263
264bool SurfaceImpl::Initialised() {
265 return hdc != 0;
266}
267
268
269void SurfaceImpl::PenColour(ColourAllocated fore) {
270 hdc->SetPen(wxPen(wxColourFromCA(fore), 1, wxSOLID));
271}
272
273void SurfaceImpl::BrushColour(ColourAllocated back) {
274 hdc->SetBrush(wxBrush(wxColourFromCA(back), wxSOLID));
275}
276
277void SurfaceImpl::SetFont(Font &font_) {
278 if (font_.GetID()) {
279 hdc->SetFont(*((wxFont*)font_.GetID()));
280 }
281}
282
283int SurfaceImpl::LogPixelsY() {
284 return hdc->GetPPI().y;
285}
286
287int SurfaceImpl::DeviceHeightFont(int points) {
288 return points;
289}
290
291void SurfaceImpl::MoveTo(int x_, int y_) {
292 x = x_;
293 y = y_;
294}
295
296void SurfaceImpl::LineTo(int x_, int y_) {
297 hdc->DrawLine(x,y, x_,y_);
298 x = x_;
299 y = y_;
300}
301
302void SurfaceImpl::Polygon(Point *pts, int npts, ColourAllocated fore, ColourAllocated back) {
303 PenColour(fore);
304 BrushColour(back);
305 hdc->DrawPolygon(npts, (wxPoint*)pts);
306}
307
308void SurfaceImpl::RectangleDraw(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
309 PenColour(fore);
310 BrushColour(back);
311 hdc->DrawRectangle(wxRectFromPRectangle(rc));
312}
313
314void SurfaceImpl::FillRectangle(PRectangle rc, ColourAllocated back) {
315 BrushColour(back);
316 hdc->SetPen(*wxTRANSPARENT_PEN);
317 hdc->DrawRectangle(wxRectFromPRectangle(rc));
318}
319
320void SurfaceImpl::FillRectangle(PRectangle rc, Surface &surfacePattern) {
321 wxBrush br;
322 if (((SurfaceImpl&)surfacePattern).bitmap)
323 br = wxBrush(*((SurfaceImpl&)surfacePattern).bitmap);
324 else // Something is wrong so display in red
325 br = wxBrush(*wxRED, wxSOLID);
326 hdc->SetPen(*wxTRANSPARENT_PEN);
327 hdc->SetBrush(br);
328 hdc->DrawRectangle(wxRectFromPRectangle(rc));
329}
330
331void SurfaceImpl::RoundedRectangle(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
332 PenColour(fore);
333 BrushColour(back);
334 hdc->DrawRoundedRectangle(wxRectFromPRectangle(rc), 4);
335}
336
337void SurfaceImpl::AlphaRectangle(PRectangle rc, int cornerSize,
338 ColourAllocated fill, int alphaFill,
339 ColourAllocated outline, int alphaOutline, int flags) {
340// ** TODO
341
342 RectangleDraw(rc, outline, fill);
343}
344
345void SurfaceImpl::Ellipse(PRectangle rc, ColourAllocated fore, ColourAllocated back) {
346 PenColour(fore);
347 BrushColour(back);
348 hdc->DrawEllipse(wxRectFromPRectangle(rc));
349}
350
351void SurfaceImpl::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
352 wxRect r = wxRectFromPRectangle(rc);
353 hdc->Blit(r.x, r.y, r.width, r.height,
354 ((SurfaceImpl&)surfaceSource).hdc,
355 from.x, from.y, wxCOPY);
356}
357
358void SurfaceImpl::DrawTextNoClip(PRectangle rc, Font &font, int ybase,
359 const char *s, int len,
360 ColourAllocated fore, ColourAllocated back) {
361 SetFont(font);
362 hdc->SetTextForeground(wxColourFromCA(fore));
363 hdc->SetTextBackground(wxColourFromCA(back));
364 FillRectangle(rc, back);
365
366 // ybase is where the baseline should be, but wxWin uses the upper left
367 // corner, so I need to calculate the real position for the text...
368 hdc->DrawText(stc2wx(s, len), rc.left, ybase - font.ascent);
369}
370
371void SurfaceImpl::DrawTextClipped(PRectangle rc, Font &font, int ybase,
372 const char *s, int len,
373 ColourAllocated fore, ColourAllocated back) {
374 SetFont(font);
375 hdc->SetTextForeground(wxColourFromCA(fore));
376 hdc->SetTextBackground(wxColourFromCA(back));
377 FillRectangle(rc, back);
378 hdc->SetClippingRegion(wxRectFromPRectangle(rc));
379
380 // see comments above
381 hdc->DrawText(stc2wx(s, len), rc.left, ybase - font.ascent);
382 hdc->DestroyClippingRegion();
383}
384
385
386void SurfaceImpl::DrawTextTransparent(PRectangle rc, Font &font, int ybase,
387 const char *s, int len,
388 ColourAllocated fore) {
389
390 SetFont(font);
391 hdc->SetTextForeground(wxColourFromCA(fore));
392 hdc->SetBackgroundMode(wxTRANSPARENT);
393
394 // ybase is where the baseline should be, but wxWin uses the upper left
395 // corner, so I need to calculate the real position for the text...
396 hdc->DrawText(stc2wx(s, len), rc.left, ybase - font.ascent);
397
398 hdc->SetBackgroundMode(wxSOLID);
399}
400
401
402void SurfaceImpl::MeasureWidths(Font &font, const char *s, int len, int *positions) {
403
404 wxString str = stc2wx(s, len);
405 wxArrayInt tpos;
406
407 SetFont(font);
408
409 hdc->GetPartialTextExtents(str, tpos);
410
411#if wxUSE_UNICODE
412 // Map the widths for UCS-2 characters back to the UTF-8 input string
413 // NOTE: I don't think this is right for when sizeof(wxChar) > 2, ie wxGTK2
414 // so figure it out and fix it!
415 size_t i = 0;
416 size_t ui = 0;
417 while ((int)i < len) {
418 unsigned char uch = (unsigned char)s[i];
419 positions[i++] = tpos[ui];
420 if (uch >= 0x80) {
421 if (uch < (0x80 + 0x40 + 0x20)) {
422 positions[i++] = tpos[ui];
423 } else {
424 positions[i++] = tpos[ui];
425 positions[i++] = tpos[ui];
426 }
427 }
428 ui++;
429 }
430#else
431
432 // If not unicode then just use the widths we have
433#if wxUSE_STL
434 std::copy(tpos.begin(), tpos.end(), positions);
435#else
436 memcpy(positions, tpos.begin(), len * sizeof(int));
437#endif
438#endif
439}
440
441
442int SurfaceImpl::WidthText(Font &font, const char *s, int len) {
443 SetFont(font);
444 int w;
445 int h;
446
447 hdc->GetTextExtent(stc2wx(s, len), &w, &h);
448 return w;
449}
450
451
452int SurfaceImpl::WidthChar(Font &font, char ch) {
453 SetFont(font);
454 int w;
455 int h;
456 char s[2] = { ch, 0 };
457
458 hdc->GetTextExtent(stc2wx(s, 1), &w, &h);
459 return w;
460}
461
462#define EXTENT_TEST wxT(" `~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
463
464int SurfaceImpl::Ascent(Font &font) {
465 SetFont(font);
466 int w, h, d, e;
467 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
468 font.ascent = h - d;
469 return font.ascent;
470}
471
472int SurfaceImpl::Descent(Font &font) {
473 SetFont(font);
474 int w, h, d, e;
475 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
476 return d;
477}
478
479int SurfaceImpl::InternalLeading(Font &WXUNUSED(font)) {
480 return 0;
481}
482
483int SurfaceImpl::ExternalLeading(Font &font) {
484 SetFont(font);
485 int w, h, d, e;
486 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
487 return e;
488}
489
490int SurfaceImpl::Height(Font &font) {
491 SetFont(font);
492 return hdc->GetCharHeight() + 1;
493}
494
495int SurfaceImpl::AverageCharWidth(Font &font) {
496 SetFont(font);
497 return hdc->GetCharWidth();
498}
499
500int SurfaceImpl::SetPalette(Palette *WXUNUSED(pal), bool WXUNUSED(inBackGround)) {
501 return 0;
502}
503
504void SurfaceImpl::SetClip(PRectangle rc) {
505 hdc->SetClippingRegion(wxRectFromPRectangle(rc));
506}
507
508void SurfaceImpl::FlushCachedState() {
509}
510
511void SurfaceImpl::SetUnicodeMode(bool unicodeMode_) {
512 unicodeMode=unicodeMode_;
513}
514
515void SurfaceImpl::SetDBCSMode(int WXUNUSED(codePage)) {
516 // dbcsMode = codePage == SC_CP_DBCS;
517}
518
519
520Surface *Surface::Allocate() {
521 return new SurfaceImpl;
522}
523
524
525//----------------------------------------------------------------------
526
527
528inline wxWindow* GETWIN(WindowID id) { return (wxWindow*)id; }
529
530Window::~Window() {
531}
532
533void Window::Destroy() {
534 if (id) {
535 Show(false);
536 GETWIN(id)->Destroy();
537 }
538 id = 0;
539}
540
541bool Window::HasFocus() {
542 return wxWindow::FindFocus() == GETWIN(id);
543}
544
545PRectangle Window::GetPosition() {
546 if (! id) return PRectangle();
547 wxRect rc(GETWIN(id)->GetPosition(), GETWIN(id)->GetSize());
548 return PRectangleFromwxRect(rc);
549}
550
551void Window::SetPosition(PRectangle rc) {
552 wxRect r = wxRectFromPRectangle(rc);
553 GETWIN(id)->SetSize(r);
554}
555
556void Window::SetPositionRelative(PRectangle rc, Window) {
557 SetPosition(rc); // ????
558}
559
560PRectangle Window::GetClientPosition() {
561 if (! id) return PRectangle();
562 wxSize sz = GETWIN(id)->GetClientSize();
563 return PRectangle(0, 0, sz.x, sz.y);
564}
565
566void Window::Show(bool show) {
567 GETWIN(id)->Show(show);
568}
569
570void Window::InvalidateAll() {
571 GETWIN(id)->Refresh(false);
572}
573
574void Window::InvalidateRectangle(PRectangle rc) {
575 wxRect r = wxRectFromPRectangle(rc);
576 GETWIN(id)->Refresh(false, &r);
577}
578
579void Window::SetFont(Font &font) {
580 GETWIN(id)->SetFont(*((wxFont*)font.GetID()));
581}
582
583void Window::SetCursor(Cursor curs) {
584 int cursorId;
585
586 switch (curs) {
587 case cursorText:
588 cursorId = wxCURSOR_IBEAM;
589 break;
590 case cursorArrow:
591 cursorId = wxCURSOR_ARROW;
592 break;
593 case cursorUp:
594 cursorId = wxCURSOR_ARROW; // ** no up arrow... wxCURSOR_UPARROW;
595 break;
596 case cursorWait:
597 cursorId = wxCURSOR_WAIT;
598 break;
599 case cursorHoriz:
600 cursorId = wxCURSOR_SIZEWE;
601 break;
602 case cursorVert:
603 cursorId = wxCURSOR_SIZENS;
604 break;
605 case cursorReverseArrow:
606 cursorId = wxCURSOR_RIGHT_ARROW;
607 break;
608 case cursorHand:
609 cursorId = wxCURSOR_HAND;
610 break;
611 default:
612 cursorId = wxCURSOR_ARROW;
613 break;
614 }
615#ifdef __WXMOTIF__
616 wxCursor wc = wxStockCursor(cursorId) ;
617#else
618 wxCursor wc = wxCursor(cursorId) ;
619#endif
620 if(curs != cursorLast)
621 {
622 GETWIN(id)->SetCursor(wc);
623 cursorLast = curs;
624 }
625}
626
627
628void Window::SetTitle(const char *s) {
629 GETWIN(id)->SetLabel(stc2wx(s));
630}
631
632
633//----------------------------------------------------------------------
634// Helper classes for ListBox
635
636
637// This is a simple subclass of wxListView that just resets focus to the
638// parent when it gets it.
639class wxSTCListBox : public wxListView {
640public:
641 wxSTCListBox(wxWindow* parent, wxWindowID id,
642 const wxPoint& pos, const wxSize& size,
643 long style)
644 : wxListView()
645 {
646#ifdef __WXMSW__
647 Hide(); // don't flicker as we move it around...
648#endif
649 Create(parent, id, pos, size, style);
650 }
651
652
653 void OnFocus(wxFocusEvent& event) {
654 GetParent()->SetFocus();
655 event.Skip();
656 }
657
658 void OnKillFocus(wxFocusEvent& WXUNUSED(event)) {
659 // Do nothing. Prevents base class from resetting the colors...
660 }
661
662#ifdef __WXMAC__
663 // For some reason I don't understand yet the focus doesn't really leave
664 // the listbox like it should, so if we get any events feed them back to
665 // the wxSTC
666 void OnKeyDown(wxKeyEvent& event) {
667 GetGrandParent()->GetEventHandler()->ProcessEvent(event);
668 }
669 void OnChar(wxKeyEvent& event) {
670 GetGrandParent()->GetEventHandler()->ProcessEvent(event);
671 }
672
673 // And we need to force the focus back when being destroyed
674 ~wxSTCListBox() {
675 GetGrandParent()->SetFocus();
676 }
677#endif
678
679private:
680 DECLARE_EVENT_TABLE()
681};
682
683BEGIN_EVENT_TABLE(wxSTCListBox, wxListView)
684 EVT_SET_FOCUS( wxSTCListBox::OnFocus)
685 EVT_KILL_FOCUS(wxSTCListBox::OnKillFocus)
686#ifdef __WXMAC__
687 EVT_KEY_DOWN( wxSTCListBox::OnKeyDown)
688 EVT_CHAR( wxSTCListBox::OnChar)
689#endif
690END_EVENT_TABLE()
691
692
693
694#if wxUSE_POPUPWIN //-----------------------------------
695#include <wx/popupwin.h>
696
697
698//
699// TODO: Refactor these two classes to have a common base (or a mix-in) to get
700// rid of the code duplication. (Either that or convince somebody to
701// implement wxPopupWindow for the Mac!!)
702//
703// In the meantime, be careful to duplicate any changes as needed...
704//
705
706// A popup window to place the wxSTCListBox upon
707class wxSTCListBoxWin : public wxPopupWindow
708{
709private:
710 wxListView* lv;
711 CallBackAction doubleClickAction;
712 void* doubleClickActionData;
713public:
714 wxSTCListBoxWin(wxWindow* parent, wxWindowID id, Point WXUNUSED(location)) :
715 wxPopupWindow(parent, wxBORDER_NONE)
716 {
717 SetBackgroundColour(*wxBLACK); // for our simple border
718
719 lv = new wxSTCListBox(parent, 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);
724
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.
731 lv->SetFocus();
732 lv->Reparent(this);
733#ifdef __WXMSW__
734 lv->Show();
735#endif
736 }
737
738
739 // Set position in client coords
740 virtual void DoSetSize(int x, int y,
741 int width, int height,
742 int sizeFlags = wxSIZE_AUTO) {
743 if (x != wxDefaultCoord) {
744 GetParent()->ClientToScreen(&x, NULL);
745 }
746 if (y != wxDefaultCoord) {
747 GetParent()->ClientToScreen(NULL, &y);
748 }
749 wxPopupWindow::DoSetSize(x, y, width, height, sizeFlags);
750 }
751
752 // return position as if it were in client coords
753 virtual void DoGetPosition( int *x, int *y ) const {
754 int sx, sy;
755 wxPopupWindow::DoGetPosition(&sx, &sy);
756 GetParent()->ScreenToClient(&sx, &sy);
757 if (x) *x = sx;
758 if (y) *y = sy;
759 }
760
761
762 bool Destroy() {
763 if ( !wxPendingDelete.Member(this) )
764 wxPendingDelete.Append(this);
765 return true;
766 }
767
768
769 int IconWidth() {
770 wxImageList* il = lv->GetImageList(wxIMAGE_LIST_SMALL);
771 if (il != NULL) {
772 int w, h;
773 il->GetSize(0, w, h);
774 return w;
775 }
776 return 0;
777 }
778
779
780 void SetDoubleClickAction(CallBackAction action, void *data) {
781 doubleClickAction = action;
782 doubleClickActionData = data;
783 }
784
785
786 void OnFocus(wxFocusEvent& event) {
787 GetParent()->SetFocus();
788 event.Skip();
789 }
790
791 void OnSize(wxSizeEvent& event) {
792 // resize the child
793 wxSize sz = GetSize();
794 sz.x -= 2;
795 sz.y -= 2;
796 lv->SetSize(1, 1, sz.x, sz.y);
797 // reset the column widths
798 lv->SetColumnWidth(0, IconWidth()+4);
799 lv->SetColumnWidth(1, sz.x - 2 - lv->GetColumnWidth(0) -
800 wxSystemSettings::GetMetric(wxSYS_VSCROLL_X));
801 event.Skip();
802 }
803
804 void OnActivate(wxListEvent& WXUNUSED(event)) {
805 doubleClickAction(doubleClickActionData);
806 }
807
808 wxListView* GetLB() { return lv; }
809
810private:
811 DECLARE_EVENT_TABLE()
812
813};
814
815BEGIN_EVENT_TABLE(wxSTCListBoxWin, wxPopupWindow)
816 EVT_SET_FOCUS ( wxSTCListBoxWin::OnFocus)
817 EVT_SIZE ( wxSTCListBoxWin::OnSize)
818 EVT_LIST_ITEM_ACTIVATED(wxID_ANY, wxSTCListBoxWin::OnActivate)
819END_EVENT_TABLE()
820
821
822
823#else // wxUSE_POPUPWIN -----------------------------------
824
825// A normal window to place the wxSTCListBox upon.
826class wxSTCListBoxWin : public wxWindow {
827private:
828 wxListView* lv;
829 CallBackAction doubleClickAction;
830 void* doubleClickActionData;
831public:
832 wxSTCListBoxWin(wxWindow* parent, wxWindowID id, Point location) :
833 wxWindow(parent, id, wxPoint(location.x, location.y), wxSize(0,0), wxSIMPLE_BORDER )
834 {
835
836 lv = new wxSTCListBox(this, id, wxDefaultPosition, wxDefaultSize,
837 wxLC_REPORT | wxLC_SINGLE_SEL | wxLC_NO_HEADER | wxNO_BORDER);
838 lv->SetCursor(wxCursor(wxCURSOR_ARROW));
839 lv->InsertColumn(0, wxEmptyString);
840 lv->InsertColumn(1, wxEmptyString);
841
842 // Eventhough we immediately reset the focus to the parent, this helps
843 // things to look right...
844 lv->SetFocus();
845
846 Hide();
847 }
848
849
850 // On OSX and (possibly others) there can still be pending
851 // messages/events for the list control when Scintilla wants to
852 // close it, so do a pending delete of it instead of destroying
853 // immediately.
854 bool Destroy() {
855#ifdef __WXMAC__
856 // The bottom edge of this window is not getting properly
857 // refreshed upon deletion, so help it out...
858 wxWindow* p = GetParent();
859 wxRect r(GetPosition(), GetSize());
860 r.SetHeight(r.GetHeight()+1);
861 p->Refresh(false, &r);
862#endif
863 if ( !wxPendingDelete.Member(this) )
864 wxPendingDelete.Append(this);
865 return true;
866 }
867
868
869 int IconWidth() {
870 wxImageList* il = lv->GetImageList(wxIMAGE_LIST_SMALL);
871 if (il != NULL) {
872 int w, h;
873 il->GetSize(0, w, h);
874 return w;
875 }
876 return 0;
877 }
878
879
880 void SetDoubleClickAction(CallBackAction action, void *data) {
881 doubleClickAction = action;
882 doubleClickActionData = data;
883 }
884
885
886 void OnFocus(wxFocusEvent& event) {
887 GetParent()->SetFocus();
888 event.Skip();
889 }
890
891 void OnSize(wxSizeEvent& event) {
892 // resize the child
893 wxSize sz = GetClientSize();
894 lv->SetSize(sz);
895 // reset the column widths
896 lv->SetColumnWidth(0, IconWidth()+4);
897 lv->SetColumnWidth(1, sz.x - 2 - lv->GetColumnWidth(0) -
898 wxSystemSettings::GetMetric(wxSYS_VSCROLL_X));
899 event.Skip();
900 }
901
902#ifdef __WXMAC__
903 virtual bool Show(bool show = true) {
904 bool rv = wxWindow::Show(show);
905 GetParent()->Refresh(false);
906 return rv;
907 }
908#endif
909
910 void OnActivate(wxListEvent& WXUNUSED(event)) {
911 doubleClickAction(doubleClickActionData);
912 }
913
914 wxListView* GetLB() { return lv; }
915
916private:
917 DECLARE_EVENT_TABLE()
918};
919
920
921BEGIN_EVENT_TABLE(wxSTCListBoxWin, wxWindow)
922 EVT_SET_FOCUS ( wxSTCListBoxWin::OnFocus)
923 EVT_SIZE ( wxSTCListBoxWin::OnSize)
924 EVT_LIST_ITEM_ACTIVATED(wxID_ANY, wxSTCListBoxWin::OnActivate)
925END_EVENT_TABLE()
926
927#endif // wxUSE_POPUPWIN -----------------------------------
928
929
930inline wxSTCListBoxWin* GETLBW(WindowID win) {
931 return ((wxSTCListBoxWin*)win);
932}
933
934inline wxListView* GETLB(WindowID win) {
935 return GETLBW(win)->GetLB();
936}
937
938//----------------------------------------------------------------------
939
940class ListBoxImpl : public ListBox {
941private:
942 int lineHeight;
943 bool unicodeMode;
944 int desiredVisibleRows;
945 int aveCharWidth;
946 size_t maxStrWidth;
947 Point location; // Caret location at which the list is opened
948 wxImageList* imgList;
949 wxArrayInt* imgTypeMap;
950
951public:
952 ListBoxImpl();
953 ~ListBoxImpl();
954
955 virtual void SetFont(Font &font);
956 virtual void Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_);
957 virtual void SetAverageCharWidth(int width);
958 virtual void SetVisibleRows(int rows);
959 virtual int GetVisibleRows() const;
960 virtual PRectangle GetDesiredRect();
961 virtual int CaretFromEdge();
962 virtual void Clear();
963 virtual void Append(char *s, int type = -1);
964 void Append(const wxString& text, int type);
965 virtual int Length();
966 virtual void Select(int n);
967 virtual int GetSelection();
968 virtual int Find(const char *prefix);
969 virtual void GetValue(int n, char *value, int len);
970 virtual void RegisterImage(int type, const char *xpm_data);
971 virtual void ClearRegisteredImages();
972 virtual void SetDoubleClickAction(CallBackAction, void *);
973 virtual void SetList(const char* list, char separator, char typesep);
974};
975
976
977ListBoxImpl::ListBoxImpl()
978 : lineHeight(10), unicodeMode(false),
979 desiredVisibleRows(5), aveCharWidth(8), maxStrWidth(0),
980 imgList(NULL), imgTypeMap(NULL)
981{
982}
983
984ListBoxImpl::~ListBoxImpl() {
985 if (imgList) {
986 delete imgList;
987 imgList = NULL;
988 }
989 if (imgTypeMap) {
990 delete imgTypeMap;
991 imgTypeMap = NULL;
992 }
993}
994
995
996void ListBoxImpl::SetFont(Font &font) {
997 GETLB(id)->SetFont(*((wxFont*)font.GetID()));
998}
999
1000
1001void ListBoxImpl::Create(Window &parent, int ctrlID, Point location_, int lineHeight_, bool unicodeMode_) {
1002 location = location_;
1003 lineHeight = lineHeight_;
1004 unicodeMode = unicodeMode_;
1005 maxStrWidth = 0;
1006 id = new wxSTCListBoxWin(GETWIN(parent.GetID()), ctrlID, location);
1007 if (imgList != NULL)
1008 GETLB(id)->SetImageList(imgList, wxIMAGE_LIST_SMALL);
1009}
1010
1011
1012void ListBoxImpl::SetAverageCharWidth(int width) {
1013 aveCharWidth = width;
1014}
1015
1016
1017void ListBoxImpl::SetVisibleRows(int rows) {
1018 desiredVisibleRows = rows;
1019}
1020
1021
1022int ListBoxImpl::GetVisibleRows() const {
1023 return desiredVisibleRows;
1024}
1025
1026PRectangle ListBoxImpl::GetDesiredRect() {
1027 // wxListCtrl doesn't have a DoGetBestSize, so instead we kept track of
1028 // the max size in Append and calculate it here...
1029 int maxw = maxStrWidth * aveCharWidth;
1030 int maxh ;
1031
1032 // give it a default if there are no lines, and/or add a bit more
1033 if (maxw == 0) maxw = 100;
1034 maxw += aveCharWidth * 3 +
1035 GETLBW(id)->IconWidth() + wxSystemSettings::GetMetric(wxSYS_VSCROLL_X);
1036 if (maxw > 350)
1037 maxw = 350;
1038
1039 // estimate a desired height
1040 int count = GETLB(id)->GetItemCount();
1041 if (count) {
1042 wxRect rect;
1043 GETLB(id)->GetItemRect(0, rect);
1044 maxh = count * rect.GetHeight();
1045 if (maxh > 140) // TODO: Use desiredVisibleRows??
1046 maxh = 140;
1047
1048 // Try to make the size an exact multiple of some number of lines
1049 int lines = maxh / rect.GetHeight();
1050 maxh = (lines + 1) * rect.GetHeight() + 2;
1051 }
1052 else
1053 maxh = 100;
1054
1055 PRectangle rc;
1056 rc.top = 0;
1057 rc.left = 0;
1058 rc.right = maxw;
1059 rc.bottom = maxh;
1060 return rc;
1061}
1062
1063
1064int ListBoxImpl::CaretFromEdge() {
1065 return 4 + GETLBW(id)->IconWidth();
1066}
1067
1068
1069void ListBoxImpl::Clear() {
1070 GETLB(id)->DeleteAllItems();
1071}
1072
1073
1074void ListBoxImpl::Append(char *s, int type) {
1075 Append(stc2wx(s), type);
1076}
1077
1078void ListBoxImpl::Append(const wxString& text, int type) {
1079 long count = GETLB(id)->GetItemCount();
1080 long itemID = GETLB(id)->InsertItem(count, wxEmptyString);
1081 GETLB(id)->SetItem(itemID, 1, text);
1082 maxStrWidth = wxMax(maxStrWidth, text.length());
1083 if (type != -1) {
1084 wxCHECK_RET(imgTypeMap, wxT("Unexpected NULL imgTypeMap"));
1085 long idx = imgTypeMap->Item(type);
1086 GETLB(id)->SetItemImage(itemID, idx, idx);
1087 }
1088}
1089
1090void ListBoxImpl::SetList(const char* list, char separator, char typesep) {
1091 GETLB(id)->Freeze();
1092 Clear();
1093 wxStringTokenizer tkzr(stc2wx(list), (wxChar)separator);
1094 while ( tkzr.HasMoreTokens() ) {
1095 wxString token = tkzr.GetNextToken();
1096 long type = -1;
1097 int pos = token.Find(typesep);
1098 if (pos != -1) {
1099 token.Mid(pos+1).ToLong(&type);
1100 token.Truncate(pos);
1101 }
1102 Append(token, (int)type);
1103 }
1104 GETLB(id)->Thaw();
1105}
1106
1107
1108int ListBoxImpl::Length() {
1109 return GETLB(id)->GetItemCount();
1110}
1111
1112
1113void ListBoxImpl::Select(int n) {
1114 bool select = true;
1115 if (n == -1) {
1116 n = 0;
1117 select = false;
1118 }
1119 GETLB(id)->Focus(n);
1120 GETLB(id)->Select(n, select);
1121}
1122
1123
1124int ListBoxImpl::GetSelection() {
1125 return GETLB(id)->GetFirstSelected();
1126}
1127
1128
1129int ListBoxImpl::Find(const char *WXUNUSED(prefix)) {
1130 // No longer used
1131 return wxNOT_FOUND;
1132}
1133
1134
1135void ListBoxImpl::GetValue(int n, char *value, int len) {
1136 wxListItem item;
1137 item.SetId(n);
1138 item.SetColumn(1);
1139 item.SetMask(wxLIST_MASK_TEXT);
1140 GETLB(id)->GetItem(item);
1141 strncpy(value, wx2stc(item.GetText()), len);
1142 value[len-1] = '\0';
1143}
1144
1145
1146void ListBoxImpl::RegisterImage(int type, const char *xpm_data) {
1147 wxMemoryInputStream stream(xpm_data, strlen(xpm_data)+1);
1148 wxImage img(stream, wxBITMAP_TYPE_XPM);
1149 wxBitmap bmp(img);
1150
1151 if (! imgList) {
1152 // assumes all images are the same size
1153 imgList = new wxImageList(bmp.GetWidth(), bmp.GetHeight(), true);
1154 imgTypeMap = new wxArrayInt;
1155 }
1156
1157 int idx = imgList->Add(bmp);
1158
1159 // do we need to extend the mapping array?
1160 wxArrayInt& itm = *imgTypeMap;
1161 if ( itm.GetCount() < (size_t)type+1)
1162 itm.Add(-1, type - itm.GetCount() + 1);
1163
1164 // Add an item that maps type to the image index
1165 itm[type] = idx;
1166}
1167
1168void ListBoxImpl::ClearRegisteredImages() {
1169 if (imgList) {
1170 delete imgList;
1171 imgList = NULL;
1172 }
1173 if (imgTypeMap) {
1174 delete imgTypeMap;
1175 imgTypeMap = NULL;
1176 }
1177 if (id)
1178 GETLB(id)->SetImageList(NULL, wxIMAGE_LIST_SMALL);
1179}
1180
1181
1182void ListBoxImpl::SetDoubleClickAction(CallBackAction action, void *data) {
1183 GETLBW(id)->SetDoubleClickAction(action, data);
1184}
1185
1186
1187ListBox::ListBox() {
1188}
1189
1190ListBox::~ListBox() {
1191}
1192
1193ListBox *ListBox::Allocate() {
1194 return new ListBoxImpl();
1195}
1196
1197//----------------------------------------------------------------------
1198
1199Menu::Menu() : id(0) {
1200}
1201
1202void Menu::CreatePopUp() {
1203 Destroy();
1204 id = new wxMenu();
1205}
1206
1207void Menu::Destroy() {
1208 if (id)
1209 delete (wxMenu*)id;
1210 id = 0;
1211}
1212
1213void Menu::Show(Point pt, Window &w) {
1214 GETWIN(w.GetID())->PopupMenu((wxMenu*)id, pt.x - 4, pt.y);
1215 Destroy();
1216}
1217
1218//----------------------------------------------------------------------
1219
1220DynamicLibrary *DynamicLibrary::Load(const char *WXUNUSED(modulePath)) {
1221 wxFAIL_MSG(wxT("Dynamic lexer loading not implemented yet"));
1222 return NULL;
1223}
1224
1225//----------------------------------------------------------------------
1226
1227ColourDesired Platform::Chrome() {
1228 wxColour c;
1229 c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DFACE);
1230 return ColourDesired(c.Red(), c.Green(), c.Blue());
1231}
1232
1233ColourDesired Platform::ChromeHighlight() {
1234 wxColour c;
1235 c = wxSystemSettings::GetColour(wxSYS_COLOUR_3DHIGHLIGHT);
1236 return ColourDesired(c.Red(), c.Green(), c.Blue());
1237}
1238
1239const char *Platform::DefaultFont() {
1240 static char buf[128];
1241 strcpy(buf, wxNORMAL_FONT->GetFaceName().mbc_str());
1242 return buf;
1243}
1244
1245int Platform::DefaultFontSize() {
1246 return wxNORMAL_FONT->GetPointSize();
1247}
1248
1249unsigned int Platform::DoubleClickTime() {
1250 return 500; // **** ::GetDoubleClickTime();
1251}
1252
1253bool Platform::MouseButtonBounce() {
1254 return false;
1255}
1256void Platform::DebugDisplay(const char *s) {
1257 wxLogDebug(stc2wx(s));
1258}
1259
1260bool Platform::IsKeyDown(int WXUNUSED(key)) {
1261 return false; // I don't think we'll need this.
1262}
1263
1264long Platform::SendScintilla(WindowID w,
1265 unsigned int msg,
1266 unsigned long wParam,
1267 long lParam) {
1268
1269 wxStyledTextCtrl* stc = (wxStyledTextCtrl*)w;
1270 return stc->SendMsg(msg, wParam, lParam);
1271}
1272
1273long Platform::SendScintillaPointer(WindowID w,
1274 unsigned int msg,
1275 unsigned long wParam,
1276 void *lParam) {
1277
1278 wxStyledTextCtrl* stc = (wxStyledTextCtrl*)w;
1279 return stc->SendMsg(msg, wParam, (long)lParam);
1280}
1281
1282
1283// These are utility functions not really tied to a platform
1284
1285int Platform::Minimum(int a, int b) {
1286 if (a < b)
1287 return a;
1288 else
1289 return b;
1290}
1291
1292int Platform::Maximum(int a, int b) {
1293 if (a > b)
1294 return a;
1295 else
1296 return b;
1297}
1298
1299#define TRACE
1300
1301void Platform::DebugPrintf(const char *format, ...) {
1302#ifdef TRACE
1303 char buffer[2000];
1304 va_list pArguments;
1305 va_start(pArguments, format);
1306 vsprintf(buffer,format,pArguments);
1307 va_end(pArguments);
1308 Platform::DebugDisplay(buffer);
1309#endif
1310}
1311
1312
1313static bool assertionPopUps = true;
1314
1315bool Platform::ShowAssertionPopUps(bool assertionPopUps_) {
1316 bool ret = assertionPopUps;
1317 assertionPopUps = assertionPopUps_;
1318 return ret;
1319}
1320
1321void Platform::Assert(const char *c, const char *file, int line) {
1322 char buffer[2000];
1323 sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line);
1324 if (assertionPopUps) {
1325 /*int idButton = */
1326 wxMessageBox(stc2wx(buffer),
1327 wxT("Assertion failure"),
1328 wxICON_HAND | wxOK);
1329// if (idButton == IDRETRY) {
1330// ::DebugBreak();
1331// } else if (idButton == IDIGNORE) {
1332// // all OK
1333// } else {
1334// abort();
1335// }
1336 } else {
1337 strcat(buffer, "\r\n");
1338 Platform::DebugDisplay(buffer);
1339 abort();
1340 }
1341}
1342
1343
1344int Platform::Clamp(int val, int minVal, int maxVal) {
1345 if (val > maxVal)
1346 val = maxVal;
1347 if (val < minVal)
1348 val = minVal;
1349 return val;
1350}
1351
1352
1353bool Platform::IsDBCSLeadByte(int WXUNUSED(codePage), char WXUNUSED(ch)) {
1354 return false;
1355}
1356
1357int Platform::DBCSCharLength(int WXUNUSED(codePage), const char *WXUNUSED(s)) {
1358 return 1;
1359}
1360
1361int Platform::DBCSCharMaxLength() {
1362 return 1;
1363}
1364
1365
1366//----------------------------------------------------------------------
1367
1368ElapsedTime::ElapsedTime() {
1369 wxLongLong localTime = wxGetLocalTimeMillis();
1370 littleBit = localTime.GetLo();
1371 bigBit = localTime.GetHi();
1372}
1373
1374double ElapsedTime::Duration(bool reset) {
1375 wxLongLong prevTime(bigBit, littleBit);
1376 wxLongLong localTime = wxGetLocalTimeMillis();
1377 if(reset) {
1378 littleBit = localTime.GetLo();
1379 bigBit = localTime.GetHi();
1380 }
1381 wxLongLong duration = localTime - prevTime;
1382 double result = duration.ToDouble();
1383 result /= 1000.0;
1384 return result;
1385}
1386
1387
1388//----------------------------------------------------------------------
1389
1390#if wxUSE_UNICODE
1391
1392#include "UniConversion.h"
1393
1394// Convert using Scintilla's functions instead of wx's, Scintilla's are more
1395// forgiving and won't assert...
1396
1397wxString stc2wx(const char* str, size_t len)
1398{
1399 if (!len)
1400 return wxEmptyString;
1401
1402 size_t wclen = UCS2Length(str, len);
1403 wxWCharBuffer buffer(wclen+1);
1404
1405 size_t actualLen = UCS2FromUTF8(str, len, buffer.data(), wclen+1);
1406 return wxString(buffer.data(), actualLen);
1407}
1408
1409
1410
1411wxString stc2wx(const char* str)
1412{
1413 return stc2wx(str, strlen(str));
1414}
1415
1416
1417const wxWX2MBbuf wx2stc(const wxString& str)
1418{
1419 const wchar_t* wcstr = str.c_str();
1420 size_t wclen = str.length();
1421 size_t len = UTF8Length(wcstr, wclen);
1422
1423 wxCharBuffer buffer(len+1);
1424 UTF8FromUCS2(wcstr, wclen, buffer.data(), len);
1425
1426 // TODO check NULL termination!!
1427
1428 return buffer;
1429}
1430
1431#endif