]> git.saurik.com Git - wxWidgets.git/blame - src/stc/PlatWX.cpp
fixed crash in OnSize() handler
[wxWidgets.git] / src / stc / PlatWX.cpp
CommitLineData
9ce192d4
RD
1// Scintilla source code edit control
2// PlatWX.cxx - implementation of platform facilities on wxWindows
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
f6bcfd97 7#include <ctype.h>
9ce192d4
RD
8
9#include "Platform.h"
10#include "wx/stc/stc.h"
11
f97d84a6
RD
12
13#ifdef __WXGTK__
14#include <gtk/gtk.h>
15#endif
16
9ce192d4 17Point Point::FromLong(long lpoint) {
f6bcfd97 18 return Point(lpoint & 0xFFFF, lpoint >> 16);
9ce192d4
RD
19}
20
21wxRect wxRectFromPRectangle(PRectangle prc) {
22 wxRect rc(prc.left, prc.top,
21156596 23 prc.right-prc.left, prc.bottom-prc.top);
9ce192d4
RD
24 return rc;
25}
26
27PRectangle PRectangleFromwxRect(wxRect rc) {
28 return PRectangle(rc.GetLeft(), rc.GetTop(), rc.GetRight(), rc.GetBottom());
29}
30
31Colour::Colour(long lcol) {
32 co.Set(lcol & 0xff, (lcol >> 8) & 0xff, (lcol >> 16) & 0xff);
33}
34
35Colour::Colour(unsigned int red, unsigned int green, unsigned int blue) {
36 co.Set(red, green, blue);
37}
38
39bool Colour::operator==(const Colour &other) const {
40 return co == other.co;
41}
42
43long Colour::AsLong() const {
44 return (((long)co.Blue() << 16) |
45 ((long)co.Green() << 8) |
46 ((long)co.Red()));
47}
48
49unsigned int Colour::GetRed() {
50 return co.Red();
51}
52
53unsigned int Colour::GetGreen() {
54 return co.Green();
55}
56
57unsigned int Colour::GetBlue() {
58 return co.Blue();
59}
60
61Palette::Palette() {
62 used = 0;
63 allowRealization = false;
64}
65
66Palette::~Palette() {
67 Release();
68}
69
70void Palette::Release() {
71 used = 0;
72}
73
74// This method either adds a colour to the list of wanted colours (want==true)
75// or retrieves the allocated colour back to the ColourPair.
76// This is one method to make it easier to keep the code for wanting and retrieving in sync.
77void Palette::WantFind(ColourPair &cp, bool want) {
78 if (want) {
79 for (int i=0; i < used; i++) {
80 if (entries[i].desired == cp.desired)
81 return;
82 }
83
84 if (used < numEntries) {
85 entries[used].desired = cp.desired;
86 entries[used].allocated = cp.desired;
87 used++;
88 }
89 } else {
90 for (int i=0; i < used; i++) {
91 if (entries[i].desired == cp.desired) {
92 cp.allocated = entries[i].allocated;
93 return;
94 }
95 }
96 cp.allocated = cp.desired;
97 }
98}
99
100void Palette::Allocate(Window &) {
101 if (allowRealization) {
102 }
103}
104
105
106Font::Font() {
107 id = 0;
108 ascent = 0;
109}
110
111Font::~Font() {
112}
113
f6bcfd97 114void Font::Create(const char *faceName, int characterSet, int size, bool bold, bool italic) {
65ec6247
RD
115 // TODO: what to do about the characterSet?
116
9ce192d4
RD
117 Release();
118 id = new wxFont(size,
119 wxDEFAULT,
120 italic ? wxITALIC : wxNORMAL,
121 bold ? wxBOLD : wxNORMAL,
122 false,
f6bcfd97
BP
123 faceName,
124 wxFONTENCODING_DEFAULT);
9ce192d4
RD
125}
126
127
128void Font::Release() {
129 if (id)
130 delete id;
131 id = 0;
132}
133
134
135Surface::Surface() :
136 hdc(0), hdcOwned(0), bitmap(0),
137 x(0), y(0) {
138}
139
140Surface::~Surface() {
141 Release();
142}
143
144void Surface::Release() {
145 if (bitmap) {
146 ((wxMemoryDC*)hdc)->SelectObject(wxNullBitmap);
147 delete bitmap;
148 bitmap = 0;
149 }
150 if (hdcOwned) {
151 delete hdc;
152 hdc = 0;
153 hdcOwned = false;
154 }
155}
156
157
158bool Surface::Initialised() {
159 return hdc != 0;
160}
161
162void Surface::Init() {
163 Release();
164 hdc = new wxMemoryDC();
165 hdcOwned = true;
9ce192d4
RD
166}
167
168void Surface::Init(SurfaceID hdc_) {
169 Release();
170 hdc = hdc_;
9ce192d4
RD
171}
172
173void Surface::InitPixMap(int width, int height, Surface *surface_) {
174 Release();
175 hdc = new wxMemoryDC(surface_->hdc);
176 hdcOwned = true;
2beb01db
RD
177 if (width < 1) width = 1;
178 if (height < 1) height = 1;
21156596 179 bitmap = new wxBitmap(width, height);
9ce192d4 180 ((wxMemoryDC*)hdc)->SelectObject(*bitmap);
9ce192d4
RD
181}
182
183void Surface::PenColour(Colour fore) {
184 hdc->SetPen(wxPen(fore.co, 1, wxSOLID));
185}
186
187void Surface::BrushColor(Colour back) {
188 hdc->SetBrush(wxBrush(back.co, wxSOLID));
189}
190
191void Surface::SetFont(Font &font_) {
21156596 192 if (font_.GetID()) {
f6bcfd97
BP
193 hdc->SetFont(*font_.GetID());
194 }
9ce192d4
RD
195}
196
197int Surface::LogPixelsY() {
198 return hdc->GetPPI().y;
199}
200
f6bcfd97
BP
201
202int Surface::DeviceHeightFont(int points) {
9968ba85 203 return points;
f6bcfd97
BP
204}
205
206
9ce192d4
RD
207void Surface::MoveTo(int x_, int y_) {
208 x = x_;
209 y = y_;
210}
211
212void Surface::LineTo(int x_, int y_) {
213 hdc->DrawLine(x,y, x_,y_);
214 x = x_;
215 y = y_;
216}
217
218void Surface::Polygon(Point *pts, int npts, Colour fore,
219 Colour back) {
220 PenColour(fore);
221 BrushColor(back);
222 hdc->DrawPolygon(npts, (wxPoint*)pts);
223}
224
225void Surface::RectangleDraw(PRectangle rc, Colour fore, Colour back) {
226 PenColour(fore);
227 BrushColor(back);
228 hdc->DrawRectangle(wxRectFromPRectangle(rc));
229}
230
231void Surface::FillRectangle(PRectangle rc, Colour back) {
232 BrushColor(back);
233 hdc->SetPen(*wxTRANSPARENT_PEN);
234 hdc->DrawRectangle(wxRectFromPRectangle(rc));
235}
236
237void Surface::FillRectangle(PRectangle rc, Surface &surfacePattern) {
238 wxBrush br;
239 if (surfacePattern.bitmap)
240 br = wxBrush(*surfacePattern.bitmap);
241 else // Something is wrong so display in red
242 br = wxBrush(*wxRED, wxSOLID);
243 hdc->SetPen(*wxTRANSPARENT_PEN);
244 hdc->SetBrush(br);
245 hdc->DrawRectangle(wxRectFromPRectangle(rc));
246}
247
248void Surface::RoundedRectangle(PRectangle rc, Colour fore, Colour back) {
249 PenColour(fore);
250 BrushColor(back);
f6bcfd97 251 hdc->DrawRoundedRectangle(wxRectFromPRectangle(rc), 4);
9ce192d4
RD
252}
253
254void Surface::Ellipse(PRectangle rc, Colour fore, Colour back) {
255 PenColour(fore);
256 BrushColor(back);
257 hdc->DrawEllipse(wxRectFromPRectangle(rc));
258}
259
260void Surface::Copy(PRectangle rc, Point from, Surface &surfaceSource) {
f6bcfd97
BP
261 wxRect r = wxRectFromPRectangle(rc);
262 hdc->Blit(r.x, r.y, r.width, r.height,
9ce192d4
RD
263 surfaceSource.hdc, from.x, from.y, wxCOPY);
264}
265
266void Surface::DrawText(PRectangle rc, Font &font, int ybase,
267 const char *s, int len, Colour fore, Colour back) {
268 SetFont(font);
269 hdc->SetTextForeground(fore.co);
270 hdc->SetTextBackground(back.co);
271 FillRectangle(rc, back);
272
273 // ybase is where the baseline should be, but wxWin uses the upper left
274 // corner, so I need to calculate the real position for the text...
275 hdc->DrawText(wxString(s, len), rc.left, ybase - font.ascent);
276}
277
278void Surface::DrawTextClipped(PRectangle rc, Font &font, int ybase, const char *s, int len, Colour fore, Colour back) {
279 SetFont(font);
280 hdc->SetTextForeground(fore.co);
281 hdc->SetTextBackground(back.co);
282 FillRectangle(rc, back);
283 hdc->SetClippingRegion(wxRectFromPRectangle(rc));
284
285 // see comments above
286 hdc->DrawText(wxString(s, len), rc.left, ybase - font.ascent);
287 hdc->DestroyClippingRegion();
288}
289
290int Surface::WidthText(Font &font, const char *s, int len) {
291 SetFont(font);
292 int w;
293 int h;
294 hdc->GetTextExtent(wxString(s, len), &w, &h);
295 return w;
296}
297
298void Surface::MeasureWidths(Font &font, const char *s, int len, int *positions) {
299 SetFont(font);
300 int totalWidth = 0;
301 for (int i=0; i<len; i++) {
302 int w;
303 int h;
304 hdc->GetTextExtent(s[i], &w, &h);
305 totalWidth += w;
306 positions[i] = totalWidth;
307 }
308}
309
310int Surface::WidthChar(Font &font, char ch) {
311 SetFont(font);
312 int w;
313 int h;
314 hdc->GetTextExtent(ch, &w, &h);
315 return w;
316}
317
318#define EXTENT_TEST " `~!@#$%^&*()-_=+\\|[]{};:\"\'<,>.?/1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
319
320int Surface::Ascent(Font &font) {
321 SetFont(font);
322 int w, h, d, e;
323 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
324 font.ascent = h - d;
325 return font.ascent;
326}
327
328int Surface::Descent(Font &font) {
329 SetFont(font);
330 int w, h, d, e;
331 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
332 return d;
333}
334
335int Surface::InternalLeading(Font &font) {
336 return 0;
337}
338
339int Surface::ExternalLeading(Font &font) {
340 SetFont(font);
341 int w, h, d, e;
342 hdc->GetTextExtent(EXTENT_TEST, &w, &h, &d, &e);
343 return e;
344}
345
346int Surface::Height(Font &font) {
347 SetFont(font);
348 return hdc->GetCharHeight();
349}
350
351int Surface::AverageCharWidth(Font &font) {
352 SetFont(font);
353 return hdc->GetCharWidth();
354}
355
356int Surface::SetPalette(Palette *pal, bool inBackGround) {
65ec6247 357 return 0;
9ce192d4
RD
358}
359
360void Surface::SetClip(PRectangle rc) {
361 hdc->SetClippingRegion(wxRectFromPRectangle(rc));
362}
363
f6bcfd97 364void Surface::FlushCachedState() {
f6bcfd97 365}
9ce192d4
RD
366
367Window::~Window() {
368}
369
370void Window::Destroy() {
371 if (id)
372 id->Destroy();
373 id = 0;
374}
375
376bool Window::HasFocus() {
377 return wxWindow::FindFocus() == id;
378}
379
380PRectangle Window::GetPosition() {
381 wxRect rc(id->GetPosition(), id->GetSize());
382 return PRectangleFromwxRect(rc);
383}
384
385void Window::SetPosition(PRectangle rc) {
f6bcfd97
BP
386 wxRect r = wxRectFromPRectangle(rc);
387 id->SetSize(r);
9ce192d4
RD
388}
389
390void Window::SetPositionRelative(PRectangle rc, Window) {
391 SetPosition(rc); // ????
392}
393
394PRectangle Window::GetClientPosition() {
395 wxSize sz = id->GetClientSize();
21156596 396 return PRectangle(0, 0, sz.x, sz.y);
9ce192d4
RD
397}
398
399void Window::Show(bool show) {
400 id->Show(show);
401}
402
403void Window::InvalidateAll() {
404 id->Refresh(false);
405}
406
407void Window::InvalidateRectangle(PRectangle rc) {
f6bcfd97
BP
408 wxRect r = wxRectFromPRectangle(rc);
409 id->Refresh(false, &r);
9ce192d4
RD
410}
411
412void Window::SetFont(Font &font) {
413 id->SetFont(*font.GetID());
414}
415
416void Window::SetCursor(Cursor curs) {
417 int cursorId;
418
419 switch (curs) {
420 case cursorText:
421 cursorId = wxCURSOR_IBEAM;
422 break;
423 case cursorArrow:
424 cursorId = wxCURSOR_ARROW;
425 break;
426 case cursorUp:
427 cursorId = wxCURSOR_ARROW; // ** no up arrow... wxCURSOR_UPARROW;
428 break;
429 case cursorWait:
430 cursorId = wxCURSOR_WAIT;
431 break;
432 case cursorHoriz:
433 cursorId = wxCURSOR_SIZEWE;
434 break;
435 case cursorVert:
436 cursorId = wxCURSOR_SIZENS;
437 break;
438 case cursorReverseArrow:
439 cursorId = wxCURSOR_POINT_RIGHT;
440 break;
441 default:
442 cursorId = wxCURSOR_ARROW;
443 break;
444 }
445
446 id->SetCursor(wxCursor(cursorId));
447}
448
449
450void Window::SetTitle(const char *s) {
451 id->SetTitle(s);
452}
453
454
f97d84a6
RD
455class wxSTCListBox : public wxListBox {
456public:
457 wxSTCListBox(wxWindow* parent, wxWindowID id)
458 : wxListBox(parent, id, wxDefaultPosition, wxDefaultSize,
459 0, NULL, wxLB_SINGLE | wxLB_SORT | wxSIMPLE_BORDER)
460 {}
461
462 void OnFocus(wxFocusEvent& event) {
463 GetParent()->SetFocus();
464 event.Skip();
465 }
466
467#ifdef __WXGTK__
468 void DoSetFirstItem(int n);
469#endif
470
471private:
472 DECLARE_EVENT_TABLE()
473};
474
475BEGIN_EVENT_TABLE(wxSTCListBox, wxListBox)
476 EVT_SET_FOCUS(wxSTCListBox::OnFocus)
477END_EVENT_TABLE()
478
479
480
481
482#ifdef __WXGTK__
483 // This can be removed after 2.2.2 I think
484void wxSTCListBox::DoSetFirstItem( int n )
485{
486 wxCHECK_RET( m_list, wxT("invalid listbox") );
487
488 if (gdk_pointer_is_grabbed () && GTK_WIDGET_HAS_GRAB (m_list))
489 return;
490
491 // terribly efficient
492 const gchar *vadjustment_key = "gtk-vadjustment";
493 guint vadjustment_key_id = g_quark_from_static_string (vadjustment_key);
494
495 GtkAdjustment *adjustment =
496 (GtkAdjustment*) gtk_object_get_data_by_id (GTK_OBJECT (m_list), vadjustment_key_id);
497 wxCHECK_RET( adjustment, wxT("invalid listbox code") );
498
499 GList *target = g_list_nth( m_list->children, n );
500 wxCHECK_RET( target, wxT("invalid listbox index") );
501
502 GtkWidget *item = GTK_WIDGET(target->data);
503 wxCHECK_RET( item, wxT("invalid listbox code") );
504
505 // find the last item before this one which is already realized
506 size_t nItemsBefore;
507 for ( nItemsBefore = 0; item && (item->allocation.y == -1); nItemsBefore++ )
508 {
509 target = target->prev;
510 if ( !target )
511 {
512 // nothing we can do if there are no allocated items yet
513 return;
514 }
515
516 item = GTK_WIDGET(target->data);
517 }
518
519 gtk_adjustment_set_value(adjustment,
520 item->allocation.y +
521 nItemsBefore*item->allocation.height);
522}
523#endif
524
9ce192d4
RD
525
526ListBox::ListBox() {
527}
528
529ListBox::~ListBox() {
530}
531
532void ListBox::Create(Window &parent, int ctrlID) {
f97d84a6
RD
533 id = new wxSTCListBox(parent.id, ctrlID);
534// id = new wxListBox(parent.id, ctrlID, wxDefaultPosition, wxDefaultSize,
535// 0, NULL, wxLB_SINGLE | wxLB_SORT | wxSIMPLE_BORDER);
9ce192d4
RD
536}
537
d134f170
RD
538PRectangle ListBox::GetDesiredRect() {
539 wxSize sz = ((wxListBox*)id)->GetBestSize();
540 PRectangle rc;
541 rc.top = 0;
542 rc.left = 0;
f97d84a6
RD
543 if (sz.x > 150) // TODO: A better way to determine these max sizes
544 sz.x = 150;
545 if (sz.y > 100)
546 sz.y = 100;
d134f170
RD
547 rc.right = sz.x;
548 rc.bottom = sz.y;
549
550 return rc;
551}
552
553void ListBox::SetAverageCharWidth(int width) {
554 aveCharWidth = width;
555}
556
557void ListBox::SetFont(Font &font) {
558 Window::SetFont(font);
559}
560
9ce192d4
RD
561void ListBox::Clear() {
562 ((wxListBox*)id)->Clear();
563}
564
565void ListBox::Append(char *s) {
566 ((wxListBox*)id)->Append(s);
567}
568
569int ListBox::Length() {
257ed895 570 return ((wxListBox*)id)->GetCount();
9ce192d4
RD
571}
572
573void ListBox::Select(int n) {
574 ((wxListBox*)id)->SetSelection(n);
f97d84a6
RD
575#ifdef __WXGTK__
576 if (n > 4)
577 n = n - 4;
578 else
579 n = 1;
580 ((wxListBox*)id)->SetFirstItem(n);
581#endif
9ce192d4
RD
582}
583
584int ListBox::GetSelection() {
585 return ((wxListBox*)id)->GetSelection();
586}
587
588int ListBox::Find(const char *prefix) {
21156596 589 if (prefix) {
257ed895 590 for (int x=0; x < ((wxListBox*)id)->GetCount(); x++) {
21156596
RD
591 wxString text = ((wxListBox*)id)->GetString(x);
592 if (text.StartsWith(prefix))
593 return x;
594 }
f6bcfd97
BP
595 }
596 return -1;
9ce192d4
RD
597}
598
599void ListBox::GetValue(int n, char *value, int len) {
600 wxString text = ((wxListBox*)id)->GetString(n);
601 strncpy(value, text.c_str(), len);
602 value[len-1] = '\0';
603}
604
605void ListBox::Sort() {
606 // wxWindows keeps sorted so no need to sort
607}
608
609
610Menu::Menu() : id(0) {
611}
612
613void Menu::CreatePopUp() {
614 Destroy();
615 id = new wxMenu();
616}
617
618void Menu::Destroy() {
619 if (id)
620 delete id;
621 id = 0;
622}
623
624void Menu::Show(Point pt, Window &w) {
625 w.GetID()->PopupMenu(id, pt.x - 4, pt.y);
626 Destroy();
627}
628
629
630Colour Platform::Chrome() {
631 wxColour c;
632 c = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DFACE);
633 return Colour(c.Red(), c.Green(), c.Blue());
634}
635
636Colour Platform::ChromeHighlight() {
637 wxColour c;
638 c = wxSystemSettings::GetSystemColour(wxSYS_COLOUR_3DHIGHLIGHT);
639 return Colour(c.Red(), c.Green(), c.Blue());
640}
641
642const char *Platform::DefaultFont() {
643 return wxNORMAL_FONT->GetFaceName();
644}
645
646int Platform::DefaultFontSize() {
647 return 8;
648}
649
650unsigned int Platform::DoubleClickTime() {
651 return 500; // **** ::GetDoubleClickTime();
652}
653
654void Platform::DebugDisplay(const char *s) {
655 wxLogDebug(s);
656}
657
658bool Platform::IsKeyDown(int key) {
659 return false; // I don't think we'll need this.
660}
661
662long Platform::SendScintilla(WindowID w,
663 unsigned int msg,
664 unsigned long wParam,
665 long lParam) {
666
667 wxStyledTextCtrl* stc = (wxStyledTextCtrl*)w;
668 return stc->SendMsg(msg, wParam, lParam);
669}
670
671
672// These are utility functions not really tied to a platform
673
674int Platform::Minimum(int a, int b) {
675 if (a < b)
676 return a;
677 else
678 return b;
679}
680
681int Platform::Maximum(int a, int b) {
682 if (a > b)
683 return a;
684 else
685 return b;
686}
687
688#define TRACE
689
690void Platform::DebugPrintf(const char *format, ...) {
691#ifdef TRACE
692 char buffer[2000];
693 va_list pArguments;
694 va_start(pArguments, format);
695 vsprintf(buffer,format,pArguments);
696 va_end(pArguments);
697 Platform::DebugDisplay(buffer);
698#endif
699}
700
65ec6247
RD
701
702static bool assertionPopUps = true;
703
704bool Platform::ShowAssertionPopUps(bool assertionPopUps_) {
705 bool ret = assertionPopUps;
706 assertionPopUps = assertionPopUps_;
707 return ret;
708}
709
710void Platform::Assert(const char *c, const char *file, int line) {
711 char buffer[2000];
712 sprintf(buffer, "Assertion [%s] failed at %s %d", c, file, line);
713 if (assertionPopUps) {
714 int idButton = wxMessageBox(buffer, "Assertion failure",
715 wxICON_HAND | wxOK);
716// if (idButton == IDRETRY) {
717// ::DebugBreak();
718// } else if (idButton == IDIGNORE) {
719// // all OK
720// } else {
721// abort();
722// }
723 } else {
724 strcat(buffer, "\r\n");
725 Platform::DebugDisplay(buffer);
726 abort();
727 }
728}
729
730
9ce192d4
RD
731int Platform::Clamp(int val, int minVal, int maxVal) {
732 if (val > maxVal)
733 val = maxVal;
734 if (val < minVal)
735 val = minVal;
736 return val;
737}
738
739
740
741
742
743