1. MSW message handling simplifications
[wxWidgets.git] / src / common / gdicmn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: gdicmn.cpp
3 // Purpose: Common GDI classes
4 // Author: Julian Smart
5 // Modified by:
6 // Created: 01/02/97
7 // RCS-ID: $Id$
8 // Copyright: (c) Julian Smart and Markus Holzem
9 // Licence: wxWindows licence
10 /////////////////////////////////////////////////////////////////////////////
11
12 #ifdef __GNUG__
13 #pragma implementation "gdicmn.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #include "wx/event.h"
24 #include "wx/gdicmn.h"
25 #include "wx/brush.h"
26 #include "wx/pen.h"
27 #include "wx/bitmap.h"
28 #include "wx/icon.h"
29 #include "wx/cursor.h"
30 #include "wx/font.h"
31 #include "wx/palette.h"
32 #include "wx/app.h"
33
34 #include "wx/log.h"
35 #include <string.h>
36
37 #ifdef __WXMSW__
38 #include <windows.h>
39 #endif
40
41 #ifdef __WXMOTIF__
42 #include <Xm/Xm.h>
43 #endif
44
45 #if !USE_SHARED_LIBRARY
46 IMPLEMENT_CLASS(wxColourDatabase, wxList)
47 IMPLEMENT_DYNAMIC_CLASS(wxFontList, wxList)
48 IMPLEMENT_DYNAMIC_CLASS(wxPenList, wxList)
49 IMPLEMENT_DYNAMIC_CLASS(wxBrushList, wxList)
50 IMPLEMENT_DYNAMIC_CLASS(wxBitmapList, wxList)
51 IMPLEMENT_DYNAMIC_CLASS(wxResourceCache, wxList)
52
53 IMPLEMENT_ABSTRACT_CLASS(wxDCBase, wxObject)
54 #endif
55
56 wxRect::wxRect(const wxPoint& topLeft, const wxPoint& bottomRight)
57 {
58 x = topLeft.x;
59 y = topLeft.y;
60 width = bottomRight.x - topLeft.x;
61 height = bottomRight.y - topLeft.y;
62
63 if (width < 0)
64 {
65 width = -width;
66 x -= width;
67 }
68
69 if (height < 0)
70 {
71 height = -height;
72 y -= height;
73 }
74 }
75
76 wxRect::wxRect(const wxPoint& point, const wxSize& size)
77 {
78 x = point.x; y = point.y;
79 width = size.x; height = size.y;
80 }
81
82 bool wxRect::operator==(const wxRect& rect) const
83 {
84 return ((x == rect.x) &&
85 (y == rect.y) &&
86 (width == rect.width) &&
87 (height == rect.height));
88 }
89
90 wxColourDatabase::wxColourDatabase (int type) : wxList (type)
91 {
92 }
93
94 wxColourDatabase::~wxColourDatabase ()
95 {
96 // Cleanup Colour allocated in Initialize()
97 wxNode *node = First ();
98 while (node)
99 {
100 wxColour *col = (wxColour *) node->Data ();
101 wxNode *next = node->Next ();
102 delete col;
103 node = next;
104 }
105 }
106
107 // Colour database stuff
108 void wxColourDatabase::Initialize ()
109 {
110 // Don't initialize for X: colours are found
111 // in FindColour below.
112 // Added: Not all
113
114 struct cdef {
115 wxChar *name;
116 int r,g,b;
117 };
118 cdef cc;
119 static cdef table[]={
120
121 // #ifdef __WXMSW__
122 {_T("AQUAMARINE"),112, 219, 147},
123 {_T("BLACK"),0, 0, 0},
124 {_T("BLUE"), 0, 0, 255},
125 {_T("BLUE VIOLET"), 159, 95, 159},
126 {_T("BROWN"), 165, 42, 42},
127 {_T("CADET BLUE"), 95, 159, 159},
128 {_T("CORAL"), 255, 127, 0},
129 {_T("CORNFLOWER BLUE"), 66, 66, 111},
130 {_T("CYAN"), 0, 255, 255},
131 {_T("DARK GREY"), 47, 47, 47}, // ?
132
133 {_T("DARK GREEN"), 47, 79, 47},
134 {_T("DARK OLIVE GREEN"), 79, 79, 47},
135 {_T("DARK ORCHID"), 153, 50, 204},
136 {_T("DARK SLATE BLUE"), 107, 35, 142},
137 {_T("DARK SLATE GREY"), 47, 79, 79},
138 {_T("DARK TURQUOISE"), 112, 147, 219},
139 {_T("DIM GREY"), 84, 84, 84},
140 {_T("FIREBRICK"), 142, 35, 35},
141 {_T("FOREST GREEN"), 35, 142, 35},
142 {_T("GOLD"), 204, 127, 50},
143 {_T("GOLDENROD"), 219, 219, 112},
144 {_T("GREY"), 128, 128, 128},
145 {_T("GREEN"), 0, 255, 0},
146 {_T("GREEN YELLOW"), 147, 219, 112},
147 {_T("INDIAN RED"), 79, 47, 47},
148 {_T("KHAKI"), 159, 159, 95},
149 {_T("LIGHT BLUE"), 191, 216, 216},
150 {_T("LIGHT GREY"), 192, 192, 192},
151 {_T("LIGHT STEEL BLUE"), 143, 143, 188},
152 {_T("LIME GREEN"), 50, 204, 50},
153 {_T("LIGHT MAGENTA"), 255, 0, 255},
154 {_T("MAGENTA"), 255, 0, 255},
155 {_T("MAROON"), 142, 35, 107},
156 {_T("MEDIUM AQUAMARINE"), 50, 204, 153},
157 {_T("MEDIUM GREY"), 100, 100, 100},
158 {_T("MEDIUM BLUE"), 50, 50, 204},
159 {_T("MEDIUM FOREST GREEN"), 107, 142, 35},
160 {_T("MEDIUM GOLDENROD"), 234, 234, 173},
161 {_T("MEDIUM ORCHID"), 147, 112, 219},
162 {_T("MEDIUM SEA GREEN"), 66, 111, 66},
163 {_T("MEDIUM SLATE BLUE"), 127, 0, 255},
164 {_T("MEDIUM SPRING GREEN"), 127, 255, 0},
165 {_T("MEDIUM TURQUOISE"), 112, 219, 219},
166 {_T("MEDIUM VIOLET RED"), 219, 112, 147},
167 {_T("MIDNIGHT BLUE"), 47, 47, 79},
168 {_T("NAVY"), 35, 35, 142},
169 {_T("ORANGE"), 204, 50, 50},
170 {_T("ORANGE RED"), 255, 0, 127},
171 {_T("ORCHID"), 219, 112, 219},
172 {_T("PALE GREEN"), 143, 188, 143},
173 {_T("PINK"), 188, 143, 234},
174 {_T("PLUM"), 234, 173, 234},
175 {_T("PURPLE"), 176, 0, 255},
176 {_T("RED"), 255, 0, 0},
177 {_T("SALMON"), 111, 66, 66},
178 {_T("SEA GREEN"), 35, 142, 107},
179 {_T("SIENNA"), 142, 107, 35},
180 {_T("SKY BLUE"), 50, 153, 204},
181 {_T("SLATE BLUE"), 0, 127, 255},
182 {_T("SPRING GREEN"), 0, 255, 127},
183 {_T("STEEL BLUE"), 35, 107, 142},
184 {_T("TAN"), 219, 147, 112},
185 {_T("THISTLE"), 216, 191, 216},
186 {_T("TURQUOISE"), 173, 234, 234},
187 {_T("VIOLET"), 79, 47, 79},
188 {_T("VIOLET RED"), 204, 50, 153},
189 {_T("WHEAT"), 216, 216, 191},
190 {_T("WHITE"), 255, 255, 255},
191 {_T("YELLOW"), 255, 255, 0},
192 {_T("YELLOW GREEN"), 153, 204, 50},
193 // #endif
194
195 #if defined(__WXGTK__) || defined(__X__)
196 {_T("MEDIUM GOLDENROD"), 234, 234, 173},
197 {_T("MEDIUM FOREST GREEN"), 107, 142, 35},
198 {_T("LIGHT MAGENTA"), 255, 0, 255},
199 {_T("MEDIUM GREY"), 100, 100, 100},
200 #endif
201
202 {0,0,0,0}
203 };
204 int i;
205 for (i=0;cc=table[i],cc.name!=0;i++)
206 {
207 Append(cc.name,new wxColour(cc.r,cc.g,cc.b));
208 }
209
210 }
211
212 /*
213 * Changed by Ian Brown, July 1994.
214 *
215 * When running under X, the Colour Database starts off empty. The X server
216 * is queried for the colour first time after which it is entered into the
217 * database. This allows our client to use the server colour database which
218 * is hopefully gamma corrected for the display being used.
219 */
220
221 wxColour *wxColourDatabase::FindColour(const wxString& colour)
222 {
223 // VZ: make the comparaison case insensitive
224 wxString str = colour;
225 str.MakeUpper();
226
227 wxNode *node = Find(str);
228 if (node)
229 return (wxColour *)node->Data();
230
231 #ifdef __WXMSW__
232 else return NULL;
233 #endif
234
235 // TODO for other implementations. This should really go into
236 // platform-specific directories.
237 #ifdef __WXMAC__
238 else return NULL;
239 #endif
240 #ifdef __WXSTUBS__
241 else return NULL;
242 #endif
243
244 #ifdef __WXGTK__
245 else {
246 wxColour *col = new wxColour( colour );
247
248 if (!(col->Ok())) {
249 delete col;
250 return (wxColour *) NULL;
251 }
252 Append( colour, col );
253 return col;
254 }
255 #endif
256
257 #ifdef __X__
258 else {
259 XColor xcolour;
260
261 #ifdef __WXMOTIF__
262 Display *display = XtDisplay((Widget) wxTheApp->GetTopLevelWidget()) ;
263 #endif
264 #ifdef __XVIEW__
265 Xv_Screen screen = xv_get(xview_server, SERVER_NTH_SCREEN, 0);
266 Xv_opaque root_window = xv_get(screen, XV_ROOT);
267 Display *display = (Display *)xv_get(root_window, XV_DISPLAY);
268 #endif
269
270 /* MATTHEW: [4] Use wxGetMainColormap */
271 if (!XParseColor(display, (Colormap) wxTheApp->GetMainColormap((WXDisplay*) display), colour,&xcolour))
272 return NULL;
273
274 unsigned char r = (unsigned char)(xcolour.red >> 8);
275 unsigned char g = (unsigned char)(xcolour.green >> 8);
276 unsigned char b = (unsigned char)(xcolour.blue >> 8);
277
278 wxColour *col = new wxColour(r, g, b);
279 Append(colour, col);
280
281 return col;
282 }
283 #endif
284 }
285
286 wxString wxColourDatabase::FindName (const wxColour& colour) const
287 {
288 wxString name;
289
290 unsigned char red = colour.Red ();
291 unsigned char green = colour.Green ();
292 unsigned char blue = colour.Blue ();
293
294 for (wxNode * node = First (); node; node = node->Next ())
295 {
296 wxColour *col = (wxColour *) node->Data ();
297
298 if (col->Red () == red && col->Green () == green && col->Blue () == blue)
299 {
300 const wxChar *found = node->GetKeyString();
301 if ( found )
302 {
303 name = found;
304
305 break;
306 }
307 }
308 }
309
310 return name;
311 }
312
313 void wxInitializeStockLists () {
314 wxTheBrushList = new wxBrushList;
315 wxThePenList = new wxPenList;
316 wxTheFontList = new wxFontList;
317 wxTheBitmapList = new wxBitmapList;
318 }
319
320 void wxInitializeStockObjects ()
321 {
322 #ifdef __WXMOTIF__
323 #endif
324 #ifdef __X__
325 // TODO
326 // wxFontPool = new XFontPool;
327 #endif
328
329 wxNORMAL_FONT = new wxFont (12, wxMODERN, wxNORMAL, wxNORMAL);
330 wxSMALL_FONT = new wxFont (10, wxSWISS, wxNORMAL, wxNORMAL);
331 wxITALIC_FONT = new wxFont (12, wxROMAN, wxITALIC, wxNORMAL);
332 wxSWISS_FONT = new wxFont (12, wxSWISS, wxNORMAL, wxNORMAL);
333
334 wxRED_PEN = new wxPen ("RED", 1, wxSOLID);
335 wxCYAN_PEN = new wxPen ("CYAN", 1, wxSOLID);
336 wxGREEN_PEN = new wxPen ("GREEN", 1, wxSOLID);
337 wxBLACK_PEN = new wxPen ("BLACK", 1, wxSOLID);
338 wxWHITE_PEN = new wxPen ("WHITE", 1, wxSOLID);
339 wxTRANSPARENT_PEN = new wxPen ("BLACK", 1, wxTRANSPARENT);
340 wxBLACK_DASHED_PEN = new wxPen ("BLACK", 1, wxSHORT_DASH);
341 wxGREY_PEN = new wxPen ("GREY", 1, wxSOLID);
342 wxMEDIUM_GREY_PEN = new wxPen ("MEDIUM GREY", 1, wxSOLID);
343 wxLIGHT_GREY_PEN = new wxPen ("LIGHT GREY", 1, wxSOLID);
344
345 wxBLUE_BRUSH = new wxBrush ("BLUE", wxSOLID);
346 wxGREEN_BRUSH = new wxBrush ("GREEN", wxSOLID);
347 wxWHITE_BRUSH = new wxBrush ("WHITE", wxSOLID);
348 wxBLACK_BRUSH = new wxBrush ("BLACK", wxSOLID);
349 wxTRANSPARENT_BRUSH = new wxBrush ("BLACK", wxTRANSPARENT);
350 wxCYAN_BRUSH = new wxBrush ("CYAN", wxSOLID);
351 wxRED_BRUSH = new wxBrush ("RED", wxSOLID);
352 wxGREY_BRUSH = new wxBrush ("GREY", wxSOLID);
353 wxMEDIUM_GREY_BRUSH = new wxBrush ("MEDIUM GREY", wxSOLID);
354 wxLIGHT_GREY_BRUSH = new wxBrush ("LIGHT GREY", wxSOLID);
355
356 wxBLACK = new wxColour ("BLACK");
357 wxWHITE = new wxColour ("WHITE");
358 wxRED = new wxColour ("RED");
359 wxBLUE = new wxColour ("BLUE");
360 wxGREEN = new wxColour ("GREEN");
361 wxCYAN = new wxColour ("CYAN");
362 wxLIGHT_GREY = new wxColour ("LIGHT GREY");
363
364 wxSTANDARD_CURSOR = new wxCursor (wxCURSOR_ARROW);
365 wxHOURGLASS_CURSOR = new wxCursor (wxCURSOR_WAIT);
366 wxCROSS_CURSOR = new wxCursor (wxCURSOR_CROSS);
367 }
368
369 void wxDeleteStockObjects ()
370 {
371 wxDELETE(wxNORMAL_FONT);
372 wxDELETE(wxSMALL_FONT);
373 wxDELETE(wxITALIC_FONT);
374 wxDELETE(wxSWISS_FONT);
375
376 wxDELETE(wxRED_PEN);
377 wxDELETE(wxCYAN_PEN);
378 wxDELETE(wxGREEN_PEN);
379 wxDELETE(wxBLACK_PEN);
380 wxDELETE(wxWHITE_PEN);
381 wxDELETE(wxTRANSPARENT_PEN);
382 wxDELETE(wxBLACK_DASHED_PEN);
383 wxDELETE(wxGREY_PEN);
384 wxDELETE(wxMEDIUM_GREY_PEN);
385 wxDELETE(wxLIGHT_GREY_PEN);
386
387 wxDELETE(wxBLUE_BRUSH);
388 wxDELETE(wxGREEN_BRUSH);
389 wxDELETE(wxWHITE_BRUSH);
390 wxDELETE(wxBLACK_BRUSH);
391 wxDELETE(wxTRANSPARENT_BRUSH);
392 wxDELETE(wxCYAN_BRUSH);
393 wxDELETE(wxRED_BRUSH);
394 wxDELETE(wxGREY_BRUSH);
395 wxDELETE(wxMEDIUM_GREY_BRUSH);
396 wxDELETE(wxLIGHT_GREY_BRUSH);
397
398 wxDELETE(wxBLACK);
399 wxDELETE(wxWHITE);
400 wxDELETE(wxRED);
401 wxDELETE(wxBLUE);
402 wxDELETE(wxGREEN);
403 wxDELETE(wxCYAN);
404 wxDELETE(wxLIGHT_GREY);
405
406 wxDELETE(wxSTANDARD_CURSOR);
407 wxDELETE(wxHOURGLASS_CURSOR);
408 wxDELETE(wxCROSS_CURSOR);
409 }
410
411 void wxDeleteStockLists() {
412 wxDELETE(wxTheBrushList);
413 wxDELETE(wxThePenList);
414 wxDELETE(wxTheFontList);
415 wxDELETE(wxTheBitmapList);
416 }
417
418 wxBitmapList::wxBitmapList ()
419 {
420 }
421
422 wxBitmapList::~wxBitmapList ()
423 {
424 #if defined(__WXMSW__) || defined(__WXMOTIF__)
425 wxNode *node = First ();
426 while (node)
427 {
428 wxBitmap *bitmap = (wxBitmap *) node->Data ();
429 wxNode *next = node->Next ();
430 if (bitmap->GetVisible())
431 delete bitmap;
432 node = next;
433 }
434 #endif
435 }
436
437 // Pen and Brush lists
438 wxPenList::~wxPenList ()
439 {
440 #if defined(__WXMSW__) || defined(__WXMOTIF__)
441 wxNode *node = First ();
442 while (node)
443 {
444 wxPen *pen = (wxPen *) node->Data ();
445 wxNode *next = node->Next ();
446 if (pen->GetVisible())
447 delete pen;
448 node = next;
449 }
450 #endif
451 }
452
453 void wxPenList::AddPen (wxPen * pen)
454 {
455 Append (pen);
456 }
457
458 void wxPenList::RemovePen (wxPen * pen)
459 {
460 DeleteObject (pen);
461 }
462
463 wxPen *wxPenList::FindOrCreatePen (const wxColour& colour, int width, int style)
464 {
465 for (wxNode * node = First (); node; node = node->Next ())
466 {
467 wxPen *each_pen = (wxPen *) node->Data ();
468 if (each_pen && each_pen->GetVisible() &&
469 each_pen->GetWidth () == width &&
470 each_pen->GetStyle () == style &&
471 each_pen->GetColour ().Red () == colour.Red () &&
472 each_pen->GetColour ().Green () == colour.Green () &&
473 each_pen->GetColour ().Blue () == colour.Blue ())
474 return each_pen;
475 }
476 wxPen *pen = new wxPen (colour, width, style);
477
478 // Yes, we can return a pointer to this in a later FindOrCreatePen call,
479 // because we created it within FindOrCreatePen. Safeguards against
480 // returning a pointer to an automatic variable and hanging on to it
481 // (dangling pointer).
482 pen->SetVisible(TRUE);
483 return pen;
484 }
485
486 wxBrushList::~wxBrushList ()
487 {
488 #if defined(__WXMSW__) || defined(__WXMOTIF__)
489 wxNode *node = First ();
490 while (node)
491 {
492 wxBrush *brush = (wxBrush *) node->Data ();
493 wxNode *next = node->Next ();
494 if (brush->GetVisible())
495 delete brush;
496 node = next;
497 }
498 #endif
499 }
500
501 void wxBrushList::AddBrush (wxBrush * brush)
502 {
503 Append (brush);
504 }
505
506 wxBrush *wxBrushList::FindOrCreateBrush (const wxColour& colour, int style)
507 {
508 for (wxNode * node = First (); node; node = node->Next ())
509 {
510 wxBrush *each_brush = (wxBrush *) node->Data ();
511 if (each_brush && each_brush->GetVisible() &&
512 each_brush->GetStyle () == style &&
513 each_brush->GetColour ().Red () == colour.Red () &&
514 each_brush->GetColour ().Green () == colour.Green () &&
515 each_brush->GetColour ().Blue () == colour.Blue ())
516 return each_brush;
517 }
518 // Yes, we can return a pointer to this in a later FindOrCreateBrush call,
519 // because we created it within FindOrCreateBrush. Safeguards against
520 // returning a pointer to an automatic variable and hanging on to it
521 // (dangling pointer).
522 wxBrush *brush = new wxBrush (colour, style);
523 brush->SetVisible(TRUE);
524 return brush;
525 }
526
527 void wxBrushList::RemoveBrush (wxBrush * brush)
528 {
529 DeleteObject (brush);
530 }
531
532 wxFontList::~wxFontList ()
533 {
534 wxNode *node = First ();
535 while (node)
536 {
537 // Only delete objects that are 'visible', i.e.
538 // that have been created using FindOrCreate...,
539 // where the pointers are expected to be shared
540 // (and therefore not deleted by any one part of an app).
541 wxFont *font = (wxFont *) node->Data ();
542 wxNode *next = node->Next ();
543 if (font->GetVisible())
544 delete font;
545 node = next;
546 }
547 }
548
549 void wxFontList::AddFont (wxFont * font)
550 {
551 Append (font);
552 }
553
554 void wxFontList::RemoveFont (wxFont * font)
555 {
556 DeleteObject (font);
557 }
558
559 wxFont *wxFontList::
560 FindOrCreateFont (int PointSize, int FamilyOrFontId, int Style, int Weight, bool underline, const wxString& Face)
561 {
562 for (wxNode * node = First (); node; node = node->Next ())
563 {
564 wxFont *each_font = (wxFont *) node->Data ();
565 if (each_font && each_font->GetVisible() && each_font->Ok() &&
566 each_font->GetPointSize () == PointSize &&
567 each_font->GetStyle () == Style &&
568 each_font->GetWeight () == Weight &&
569 each_font->GetUnderlined () == underline &&
570 //#if defined(__X__)
571 // each_font->GetFontId () == FamilyOrFontId) /* New font system */
572 //#else
573 each_font->GetFamily () == FamilyOrFontId &&
574 ((each_font->GetFaceName() == _T("")) || each_font->GetFaceName() == Face))
575 //#endif
576 return each_font;
577 }
578 wxFont *font = new wxFont (PointSize, FamilyOrFontId, Style, Weight, underline, Face);
579 font->SetVisible(TRUE);
580 return font;
581 }
582
583 void wxBitmapList::AddBitmap(wxBitmap *bitmap)
584 {
585 Append(bitmap);
586 }
587
588 void wxBitmapList::RemoveBitmap(wxBitmap *bitmap)
589 {
590 DeleteObject(bitmap);
591 }
592
593 wxSize wxGetDisplaySize()
594 {
595 int x, y;
596 wxDisplaySize(& x, & y);
597 return wxSize(x, y);
598 }
599
600 wxResourceCache::~wxResourceCache ()
601 {
602 wxNode *node = First ();
603 while (node) {
604 wxGDIObject *item = (wxGDIObject *)node->Data();
605 if (item->IsKindOf(CLASSINFO(wxBrush))) {
606 wxBrush *brush = (wxBrush *)item;
607 delete brush;
608 }
609
610 if (item->IsKindOf(CLASSINFO(wxFont))) {
611 wxFont *font = (wxFont *)item;
612 delete font;
613 }
614
615 if (item->IsKindOf(CLASSINFO(wxBitmap))) {
616 wxBitmap *bitmap = (wxBitmap *)item;
617 delete bitmap;
618 }
619
620 if (item->IsKindOf(CLASSINFO(wxColour))) {
621 wxColour *colour = (wxColour *)item;
622 delete colour;
623 }
624
625 wxNode *next = node->Next ();
626 node = next;
627 }
628 }
629