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