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