]> git.saurik.com Git - wxWidgets.git/blame - src/motif/bitmap.cpp
Applied patch for multiple file selection, documented.
[wxWidgets.git] / src / motif / bitmap.cpp
CommitLineData
4bb6408c
JS
1/////////////////////////////////////////////////////////////////////////////
2// Name: bitmap.cpp
3// Purpose: wxBitmap
4// Author: Julian Smart
5// Modified by:
6// Created: 17/09/98
7// RCS-ID: $Id$
8// Copyright: (c) Julian Smart
9// Licence: wxWindows licence
10/////////////////////////////////////////////////////////////////////////////
11
12#ifdef __GNUG__
13#pragma implementation "bitmap.h"
14#endif
15
16#include "wx/setup.h"
17#include "wx/utils.h"
18#include "wx/palette.h"
19#include "wx/bitmap.h"
20#include "wx/icon.h"
21#include "wx/log.h"
a4294b78 22#include "wx/control.h"
321db4b6 23#include "wx/dcmemory.h"
b75dd496 24#include "wx/image.h"
4bb6408c 25
338dd992
JJ
26#ifdef __VMS__
27#pragma message disable nosimpint
28#endif
f97c9854 29#include <Xm/Xm.h>
338dd992
JJ
30#ifdef __VMS__
31#pragma message enable nosimpint
32#endif
f97c9854
JS
33
34#include "wx/motif/private.h"
35
31528cd3
VZ
36#if wxHAVE_LIB_XPM
37 #include <X11/xpm.h>
f97c9854
JS
38#endif
39
4bb6408c 40#if !USE_SHARED_LIBRARIES
31528cd3
VZ
41 IMPLEMENT_DYNAMIC_CLASS(wxBitmap, wxGDIObject)
42 IMPLEMENT_DYNAMIC_CLASS(wxMask, wxObject)
4bb6408c
JS
43#endif
44
45wxBitmapRefData::wxBitmapRefData()
46{
47 m_ok = FALSE;
48 m_width = 0;
49 m_height = 0;
50 m_depth = 0;
51 m_quality = 0;
52 m_numColors = 0;
53 m_bitmapMask = NULL;
31528cd3 54
16c1f7f3
JS
55 m_pixmap = (WXPixmap) 0;
56 m_display = (WXDisplay*) 0;
31528cd3 57
f97c9854
JS
58 m_freePixmap = TRUE; //TODO: necessary?
59 m_freeColors = (unsigned long*) 0;
60 m_freeColorsCount = 0;
31528cd3 61
f97c9854
JS
62 // These 5 variables are for wxControl
63 m_insensPixmap = (WXPixmap) 0;
64 m_labelPixmap = (WXPixmap) 0;
65 m_armPixmap = (WXPixmap) 0;
66 m_image = (WXImage*) 0;
67 m_insensImage = (WXImage*) 0;
4bb6408c
JS
68}
69
70wxBitmapRefData::~wxBitmapRefData()
71{
f97c9854
JS
72 if (m_labelPixmap)
73 XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_labelPixmap);
31528cd3 74
f97c9854
JS
75 if (m_armPixmap)
76 XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_armPixmap);
31528cd3 77
f97c9854
JS
78 if (m_insensPixmap)
79 XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) m_display), (Pixmap) m_insensPixmap);
31528cd3 80
f97c9854
JS
81 if (m_image)
82 {
83 XmUninstallImage ((XImage*) m_image);
84 XtFree ((char *) (XImage*) m_image);
85 }
31528cd3 86
f97c9854
JS
87 if (m_insensImage)
88 {
89 XmUninstallImage ((XImage*) m_insensImage);
90 delete[] ((XImage*) m_insensImage)->data;
91 XtFree ((char *) (XImage*) m_insensImage);
92 }
93 if (m_pixmap && m_freePixmap)
94 XFreePixmap ((Display*) m_display, (Pixmap) m_pixmap);
31528cd3 95
f97c9854
JS
96 if (m_freeColors)
97 {
2d120f83
JS
98 int screen = DefaultScreen((Display*) m_display);
99 Colormap cmp = DefaultColormap((Display*) m_display,screen);
100 long llp;
101 for(llp = 0;llp < m_freeColorsCount;llp++)
102 XFreeColors((Display*) m_display, cmp, &m_freeColors[llp], 1, 0L);
103 delete m_freeColors;
f97c9854 104 };
31528cd3 105
4bb6408c
JS
106 if (m_bitmapMask)
107 delete m_bitmapMask;
108 m_bitmapMask = NULL;
109}
110
111wxList wxBitmap::sm_handlers;
112
113wxBitmap::wxBitmap()
114{
115 m_refData = NULL;
31528cd3 116
4bb6408c
JS
117 if ( wxTheBitmapList )
118 wxTheBitmapList->AddBitmap(this);
119}
120
121wxBitmap::~wxBitmap()
122{
123 if (wxTheBitmapList)
124 wxTheBitmapList->DeleteObject(this);
125}
126
f97c9854 127wxBitmap::wxBitmap(const char bits[], int width, int height, int depth)
4bb6408c
JS
128{
129 m_refData = new wxBitmapRefData;
31528cd3 130
f97c9854 131 (void) Create((void*) bits, wxBITMAP_TYPE_XBM_DATA, width, height, depth);
31528cd3 132
4bb6408c
JS
133 if ( wxTheBitmapList )
134 wxTheBitmapList->AddBitmap(this);
135}
136
137wxBitmap::wxBitmap(int w, int h, int d)
138{
139 (void)Create(w, h, d);
31528cd3 140
4bb6408c
JS
141 if ( wxTheBitmapList )
142 wxTheBitmapList->AddBitmap(this);
143}
144
145wxBitmap::wxBitmap(void *data, long type, int width, int height, int depth)
146{
147 (void) Create(data, type, width, height, depth);
31528cd3 148
4bb6408c
JS
149 if ( wxTheBitmapList )
150 wxTheBitmapList->AddBitmap(this);
151}
152
153wxBitmap::wxBitmap(const wxString& filename, long type)
154{
155 LoadFile(filename, (int)type);
31528cd3 156
4bb6408c
JS
157 if ( wxTheBitmapList )
158 wxTheBitmapList->AddBitmap(this);
159}
160
f97c9854
JS
161// Create from XPM data
162static wxControl* sg_Control = NULL;
a4294b78 163wxBitmap::wxBitmap(char **data, wxControl* control)
4bb6408c 164{
f97c9854
JS
165 // Pass the control to the Create function using a global
166 sg_Control = control;
31528cd3 167
4bb6408c 168 (void) Create((void *)data, wxBITMAP_TYPE_XPM_DATA, 0, 0, 0);
31528cd3 169
f97c9854 170 sg_Control = (wxControl*) NULL;
4bb6408c 171}
4bb6408c
JS
172
173bool wxBitmap::Create(int w, int h, int d)
174{
175 UnRef();
31528cd3 176
4bb6408c 177 m_refData = new wxBitmapRefData;
31528cd3 178
f97c9854 179 if (d < 1)
2d120f83 180 d = wxDisplayDepth();
31528cd3 181
4bb6408c
JS
182 M_BITMAPDATA->m_width = w;
183 M_BITMAPDATA->m_height = h;
184 M_BITMAPDATA->m_depth = d;
f97c9854 185 M_BITMAPDATA->m_freePixmap = TRUE;
31528cd3 186
f97c9854 187 Display *dpy = (Display*) wxGetDisplay();
31528cd3 188
f97c9854 189 M_BITMAPDATA->m_display = dpy; /* MATTHEW: [4] Remember the display */
31528cd3 190
f97c9854 191 M_BITMAPDATA->m_pixmap = (WXPixmap) XCreatePixmap (dpy, RootWindow (dpy, DefaultScreen (dpy)),
2d120f83 192 w, h, d);
31528cd3 193
f97c9854 194 M_BITMAPDATA->m_ok = (M_BITMAPDATA->m_pixmap != (WXPixmap) 0) ;
4bb6408c
JS
195 return M_BITMAPDATA->m_ok;
196}
197
198bool wxBitmap::LoadFile(const wxString& filename, long type)
199{
200 UnRef();
31528cd3 201
4bb6408c 202 m_refData = new wxBitmapRefData;
31528cd3 203
4bb6408c 204 wxBitmapHandler *handler = FindHandler(type);
31528cd3 205
4bb6408c 206 if ( handler == NULL ) {
b75dd496
VS
207 wxImage image;
208 if (!image.LoadFile( filename, type )) return FALSE;
209 if (image.Ok())
210 {
211 *this = image.ConvertToBitmap();
212 return TRUE;
213 }
214 else return FALSE;
4bb6408c 215 }
31528cd3 216
4bb6408c
JS
217 return handler->LoadFile(this, filename, type, -1, -1);
218}
219
220bool wxBitmap::Create(void *data, long type, int width, int height, int depth)
221{
222 UnRef();
31528cd3 223
4bb6408c 224 m_refData = new wxBitmapRefData;
31528cd3 225
4bb6408c 226 wxBitmapHandler *handler = FindHandler(type);
31528cd3 227
4bb6408c 228 if ( handler == NULL ) {
7bcb11d3 229 wxLogWarning("no data bitmap handler for type %d defined.", type);
31528cd3 230
4bb6408c
JS
231 return FALSE;
232 }
31528cd3 233
4bb6408c
JS
234 return handler->Create(this, data, type, width, height, depth);
235}
236
237bool wxBitmap::SaveFile(const wxString& filename, int type, const wxPalette *palette)
238{
239 wxBitmapHandler *handler = FindHandler(type);
31528cd3 240
b75dd496
VS
241 if ( handler == NULL ) { // try wxImage
242 wxImage image( *this );
243 if (image.Ok()) return image.SaveFile( filename, type );
244 else return FALSE;
2d120f83 245 }
31528cd3 246
2d120f83 247 return handler->SaveFile(this, filename, type, palette);
4bb6408c
JS
248}
249
250void wxBitmap::SetWidth(int w)
251{
252 if (!M_BITMAPDATA)
253 m_refData = new wxBitmapRefData;
31528cd3 254
4bb6408c
JS
255 M_BITMAPDATA->m_width = w;
256}
257
258void wxBitmap::SetHeight(int h)
259{
260 if (!M_BITMAPDATA)
261 m_refData = new wxBitmapRefData;
31528cd3 262
4bb6408c
JS
263 M_BITMAPDATA->m_height = h;
264}
265
266void wxBitmap::SetDepth(int d)
267{
268 if (!M_BITMAPDATA)
269 m_refData = new wxBitmapRefData;
31528cd3 270
4bb6408c
JS
271 M_BITMAPDATA->m_depth = d;
272}
273
274void wxBitmap::SetQuality(int q)
275{
276 if (!M_BITMAPDATA)
277 m_refData = new wxBitmapRefData;
31528cd3 278
4bb6408c
JS
279 M_BITMAPDATA->m_quality = q;
280}
281
282void wxBitmap::SetOk(bool isOk)
283{
284 if (!M_BITMAPDATA)
285 m_refData = new wxBitmapRefData;
31528cd3 286
4bb6408c
JS
287 M_BITMAPDATA->m_ok = isOk;
288}
289
290void wxBitmap::SetPalette(const wxPalette& palette)
291{
292 if (!M_BITMAPDATA)
293 m_refData = new wxBitmapRefData;
31528cd3 294
4bb6408c
JS
295 M_BITMAPDATA->m_bitmapPalette = palette ;
296}
297
298void wxBitmap::SetMask(wxMask *mask)
299{
300 if (!M_BITMAPDATA)
301 m_refData = new wxBitmapRefData;
31528cd3 302
4bb6408c
JS
303 M_BITMAPDATA->m_bitmapMask = mask ;
304}
305
306void wxBitmap::AddHandler(wxBitmapHandler *handler)
307{
308 sm_handlers.Append(handler);
309}
310
311void wxBitmap::InsertHandler(wxBitmapHandler *handler)
312{
313 sm_handlers.Insert(handler);
314}
315
316bool wxBitmap::RemoveHandler(const wxString& name)
317{
318 wxBitmapHandler *handler = FindHandler(name);
319 if ( handler )
320 {
321 sm_handlers.DeleteObject(handler);
322 return TRUE;
323 }
324 else
325 return FALSE;
326}
327
328wxBitmapHandler *wxBitmap::FindHandler(const wxString& name)
329{
330 wxNode *node = sm_handlers.First();
331 while ( node )
332 {
333 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
334 if ( handler->GetName() == name )
335 return handler;
336 node = node->Next();
337 }
338 return NULL;
339}
340
341wxBitmapHandler *wxBitmap::FindHandler(const wxString& extension, long bitmapType)
342{
343 wxNode *node = sm_handlers.First();
344 while ( node )
345 {
346 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
347 if ( handler->GetExtension() == extension &&
2d120f83 348 (bitmapType == -1 || handler->GetType() == bitmapType) )
4bb6408c
JS
349 return handler;
350 node = node->Next();
351 }
352 return NULL;
353}
354
355wxBitmapHandler *wxBitmap::FindHandler(long bitmapType)
356{
357 wxNode *node = sm_handlers.First();
358 while ( node )
359 {
360 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
361 if (handler->GetType() == bitmapType)
362 return handler;
363 node = node->Next();
364 }
365 return NULL;
366}
367
368/*
2d120f83
JS
369* wxMask
370*/
4bb6408c
JS
371
372wxMask::wxMask()
373{
16c1f7f3 374 m_pixmap = (WXPixmap) 0;
4bb6408c
JS
375}
376
377// Construct a mask from a bitmap and a colour indicating
378// the transparent area
379wxMask::wxMask(const wxBitmap& bitmap, const wxColour& colour)
380{
16c1f7f3 381 m_pixmap = (WXPixmap) 0;
31528cd3 382
4bb6408c
JS
383 Create(bitmap, colour);
384}
385
386// Construct a mask from a bitmap and a palette index indicating
387// the transparent area
388wxMask::wxMask(const wxBitmap& bitmap, int paletteIndex)
389{
16c1f7f3 390 m_pixmap = (WXPixmap) 0;
31528cd3 391
4bb6408c
JS
392 Create(bitmap, paletteIndex);
393}
394
395// Construct a mask from a mono bitmap (copies the bitmap).
396wxMask::wxMask(const wxBitmap& bitmap)
397{
16c1f7f3 398 m_pixmap = (WXPixmap) 0;
31528cd3 399
4bb6408c
JS
400 Create(bitmap);
401}
402
403wxMask::~wxMask()
404{
f97c9854
JS
405 // TODO: this may be the wrong display
406 if ( m_pixmap )
407 XFreePixmap ((Display*) wxGetDisplay(), (Pixmap) m_pixmap);
4bb6408c
JS
408}
409
410// Create a mask from a mono bitmap (copies the bitmap).
f9e02ac7 411bool wxMask::Create(const wxBitmap& WXUNUSED(bitmap))
4bb6408c 412{
2d120f83 413 // TODO
4bb6408c
JS
414 return FALSE;
415}
416
417// Create a mask from a bitmap and a palette index indicating
418// the transparent area
f9e02ac7 419bool wxMask::Create(const wxBitmap& WXUNUSED(bitmap), int WXUNUSED(paletteIndex))
4bb6408c 420{
2d120f83 421 // TODO
4bb6408c
JS
422 return FALSE;
423}
424
425// Create a mask from a bitmap and a colour indicating
426// the transparent area
f9e02ac7 427bool wxMask::Create(const wxBitmap& WXUNUSED(bitmap), const wxColour& WXUNUSED(colour))
4bb6408c 428{
2d120f83 429 // TODO
4bb6408c
JS
430 return FALSE;
431}
432
433/*
2d120f83
JS
434* wxBitmapHandler
435*/
4bb6408c
JS
436
437IMPLEMENT_DYNAMIC_CLASS(wxBitmapHandler, wxObject)
438
31528cd3 439bool wxBitmapHandler::Create(wxBitmap *WXUNUSED(bitmap), void *WXUNUSED(data), long WXUNUSED(type),
2d120f83 440 int WXUNUSED(width), int WXUNUSED(height), int WXUNUSED(depth))
4bb6408c
JS
441{
442 return FALSE;
443}
444
f9e02ac7 445bool wxBitmapHandler::LoadFile(wxBitmap *WXUNUSED(bitmap), const wxString& WXUNUSED(name), long WXUNUSED(type),
2d120f83 446 int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight))
4bb6408c
JS
447{
448 return FALSE;
449}
450
31528cd3 451bool wxBitmapHandler::SaveFile(wxBitmap *WXUNUSED(bitmap), const wxString& WXUNUSED(name), int WXUNUSED(type),
2d120f83 452 const wxPalette *WXUNUSED(palette))
4bb6408c
JS
453{
454 return FALSE;
455}
456
457/*
2d120f83
JS
458* Standard handlers
459*/
4bb6408c 460
f97c9854 461class WXDLLEXPORT wxXBMFileHandler: public wxBitmapHandler
4bb6408c 462{
f97c9854 463 DECLARE_DYNAMIC_CLASS(wxXBMFileHandler)
4bb6408c 464public:
f97c9854 465 inline wxXBMFileHandler()
4bb6408c 466 {
f97c9854
JS
467 m_name = "XBM file";
468 m_extension = "xbm";
469 m_type = wxBITMAP_TYPE_XBM;
4bb6408c 470 };
31528cd3 471
4bb6408c 472 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
2d120f83 473 int desiredWidth, int desiredHeight);
4bb6408c 474};
f97c9854
JS
475IMPLEMENT_DYNAMIC_CLASS(wxXBMFileHandler, wxBitmapHandler)
476
f9e02ac7 477bool wxXBMFileHandler::LoadFile(wxBitmap *bitmap, const wxString& name, long WXUNUSED(flags),
2d120f83 478 int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight))
f97c9854
JS
479{
480 M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
31528cd3 481
f97c9854
JS
482 int hotX, hotY;
483 unsigned int w, h;
484 Pixmap pixmap;
31528cd3 485
f97c9854
JS
486 Display *dpy = (Display*) wxGetDisplay();
487 M_BITMAPDATA->m_display = (WXDisplay*) dpy;
31528cd3 488
f97c9854 489 int value = XReadBitmapFile (dpy, RootWindow (dpy, DefaultScreen (dpy)),
2d120f83 490 (char*) (const char*) name, &w, &h, &pixmap, &hotX, &hotY);
f97c9854
JS
491 M_BITMAPHANDLERDATA->m_width = w;
492 M_BITMAPHANDLERDATA->m_height = h;
493 M_BITMAPHANDLERDATA->m_depth = 1;
494 M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap;
31528cd3 495
f97c9854
JS
496 if ((value == BitmapFileInvalid) ||
497 (value == BitmapOpenFailed) ||
498 (value == BitmapNoMemory))
499 {
500 M_BITMAPHANDLERDATA->m_ok = FALSE;
501 M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) 0;
502 }
503 else
504 M_BITMAPHANDLERDATA->m_ok = TRUE;
31528cd3 505
f97c9854
JS
506 return M_BITMAPHANDLERDATA->m_ok ;
507}
508
509class WXDLLEXPORT wxXBMDataHandler: public wxBitmapHandler
510{
511 DECLARE_DYNAMIC_CLASS(wxXBMDataHandler)
512public:
513 inline wxXBMDataHandler()
514 {
515 m_name = "XBM data";
516 m_extension = "xbm";
517 m_type = wxBITMAP_TYPE_XBM_DATA;
518 };
31528cd3 519
f97c9854
JS
520 virtual bool Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth = 1);
521};
522IMPLEMENT_DYNAMIC_CLASS(wxXBMDataHandler, wxBitmapHandler)
523
31528cd3 524bool wxXBMDataHandler::Create( wxBitmap *bitmap, void *data, long WXUNUSED(flags),
2d120f83 525 int width, int height, int WXUNUSED(depth))
f97c9854
JS
526{
527 M_BITMAPHANDLERDATA->m_width = width;
528 M_BITMAPHANDLERDATA->m_height = height;
529 M_BITMAPHANDLERDATA->m_depth = 1;
530 M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
31528cd3 531
f97c9854
JS
532 Display *dpy = (Display*) wxGetDisplay();
533 M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy;
31528cd3 534
f97c9854
JS
535 M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) XCreateBitmapFromData (dpy, RootWindow (dpy, DefaultScreen (dpy)), (char*) data, width, height);
536 M_BITMAPHANDLERDATA->m_ok = (M_BITMAPHANDLERDATA->m_pixmap != (WXPixmap) 0) ;
31528cd3 537
f97c9854
JS
538 // code for wxControl. TODO: can we avoid doing this until we need it?
539 // E.g. have CreateButtonPixmaps which is called on demand.
540 XImage* image = (XImage *) XtMalloc (sizeof (XImage));
541 image->width = width;
542 image->height = height;
543 image->data = (char*) data;
544 image->depth = 1;
545 image->xoffset = 0;
546 image->format = XYBitmap;
547 image->byte_order = LSBFirst;
548 image->bitmap_unit = 8;
549 image->bitmap_bit_order = LSBFirst;
550 image->bitmap_pad = 8;
551 image->bytes_per_line = (width + 7) >> 3;
31528cd3 552
f97c9854
JS
553 char tmp[128];
554 sprintf (tmp, "Im%x", (unsigned int) image);
555 XmInstallImage (image, tmp);
31528cd3 556
f97c9854 557 // Build our manually stipped pixmap.
31528cd3 558
f97c9854
JS
559 int bpl = (width + 7) / 8;
560 char *data1 = new char[height * bpl];
561 char* bits = (char*) data;
562 int i;
563 for (i = 0; i < height; i++)
564 {
565 int mask = i % 2 ? 0x55 : 0xaa;
566 int j;
567 for (j = 0; j < bpl; j++)
568 data1[i * bpl + j] = bits[i * bpl + j] & mask;
569 }
570 XImage* insensImage = (XImage *) XtMalloc (sizeof (XImage));
571 insensImage->width = width;
572 insensImage->height = height;
573 insensImage->data = data1;
574 insensImage->depth = 1;
575 insensImage->xoffset = 0;
576 insensImage->format = XYBitmap;
577 insensImage->byte_order = LSBFirst;
578 insensImage->bitmap_unit = 8;
579 insensImage->bitmap_bit_order = LSBFirst;
580 insensImage->bitmap_pad = 8;
581 insensImage->bytes_per_line = bpl;
31528cd3 582
f97c9854
JS
583 sprintf (tmp, "Not%x", (unsigned int)insensImage);
584 XmInstallImage (insensImage, tmp);
31528cd3 585
f97c9854
JS
586 M_BITMAPHANDLERDATA->m_image = (WXImage*) image;
587 M_BITMAPHANDLERDATA->m_insensImage = (WXImage*) insensImage;
31528cd3 588
f97c9854
JS
589 return TRUE;
590}
591
31528cd3 592#if wxHAVE_LIB_XPM
f97c9854
JS
593class WXDLLEXPORT wxXPMFileHandler: public wxBitmapHandler
594{
595 DECLARE_DYNAMIC_CLASS(wxXPMFileHandler)
596public:
597 inline wxXPMFileHandler()
598 {
599 m_name = "XPM file";
600 m_extension = "xpm";
601 m_type = wxBITMAP_TYPE_XPM;
602 };
31528cd3 603
f97c9854 604 virtual bool LoadFile(wxBitmap *bitmap, const wxString& name, long flags,
2d120f83 605 int desiredWidth, int desiredHeight);
f97c9854
JS
606 virtual bool SaveFile(wxBitmap *bitmap, const wxString& name, int type, const wxPalette *palette = NULL);
607};
608
609IMPLEMENT_DYNAMIC_CLASS(wxXPMFileHandler, wxBitmapHandler)
610
f9e02ac7 611bool wxXPMFileHandler::LoadFile( wxBitmap *bitmap, const wxString& name, long WXUNUSED(flags),
2d120f83 612 int WXUNUSED(desiredWidth), int WXUNUSED(desiredHeight) )
f97c9854 613{
a4294b78 614 Display *dpy = (Display*) wxGetDisplay();
f97c9854 615 M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy;
31528cd3 616
f97c9854
JS
617 XpmAttributes xpmAttr;
618 Pixmap pixmap;
619 Pixmap mask = 0;
31528cd3 620
f97c9854
JS
621 M_BITMAPHANDLERDATA->m_ok = FALSE;
622 xpmAttr.valuemask = XpmReturnInfos | XpmCloseness;
623 xpmAttr.closeness = 40000;
624 int errorStatus = XpmReadFileToPixmap(dpy,
625 RootWindow(dpy, DefaultScreen(dpy)), (char*) (const char*) name,
626 &pixmap, &mask, &xpmAttr);
31528cd3 627
f97c9854
JS
628 if (errorStatus == XpmSuccess)
629 {
630 M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap;
631 if ( mask )
632 {
633 M_BITMAPHANDLERDATA->m_bitmapMask = new wxMask;
634 M_BITMAPHANDLERDATA->m_bitmapMask->SetPixmap((WXPixmap) mask);
635 }
31528cd3 636
0d57be45
JS
637 unsigned int depthRet;
638 int xRet, yRet;
639 unsigned int widthRet, heightRet, borderWidthRet;
640 Window rootWindowRet;
641 XGetGeometry(dpy, pixmap, &rootWindowRet, &xRet, &yRet,
642 &widthRet, &heightRet, &borderWidthRet, &depthRet);
31528cd3 643
f97c9854
JS
644 M_BITMAPHANDLERDATA->m_width = xpmAttr.width;
645 M_BITMAPHANDLERDATA->m_height = xpmAttr.height;
31528cd3 646
2d120f83 647 /*
f97c9854
JS
648 if ( xpmAttr.npixels > 2 )
649 {
2d120f83 650 M_BITMAPHANDLERDATA->m_depth = 8; // TODO: next time not just a guess :-) ...
f97c9854
JS
651 } else
652 {
2d120f83 653 M_BITMAPHANDLERDATA->m_depth = 1; // mono
f97c9854 654 }
2d120f83 655 */
31528cd3 656
0d57be45 657 M_BITMAPHANDLERDATA->m_depth = depthRet;
31528cd3 658
2d120f83 659 M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
31528cd3 660
2d120f83 661 XpmFreeAttributes(&xpmAttr);
31528cd3 662
f97c9854 663 M_BITMAPHANDLERDATA->m_ok = TRUE;
a4294b78 664 return TRUE;
f97c9854
JS
665 } else
666 {
2d120f83 667 // XpmDebugError(errorStatus, name);
f97c9854
JS
668 M_BITMAPHANDLERDATA->m_ok = FALSE;
669 return FALSE;
670 }
671}
672
31528cd3 673bool wxXPMFileHandler::SaveFile( wxBitmap *bitmap, const wxString& name, int WXUNUSED(type),
2d120f83 674 const wxPalette *WXUNUSED(palette))
f97c9854
JS
675{
676 if (M_BITMAPHANDLERDATA->m_ok && M_BITMAPHANDLERDATA->m_pixmap)
677 {
678 Display *dpy = (Display*) M_BITMAPHANDLERDATA->m_display;
679 int errorStatus = XpmWriteFileFromPixmap(dpy, (char*) (const char*) name,
2d120f83
JS
680 (Pixmap) M_BITMAPHANDLERDATA->m_pixmap,
681 (M_BITMAPHANDLERDATA->m_bitmapMask ? (Pixmap) M_BITMAPHANDLERDATA->m_bitmapMask->GetPixmap() : (Pixmap) 0),
682 (XpmAttributes *) NULL);
f97c9854 683 if (errorStatus == XpmSuccess)
2d120f83 684 return TRUE;
f97c9854 685 else
2d120f83 686 return FALSE;
f97c9854
JS
687 }
688 else
689 return FALSE;
690}
691
692class WXDLLEXPORT wxXPMDataHandler: public wxBitmapHandler
693{
694 DECLARE_DYNAMIC_CLASS(wxXPMDataHandler)
695public:
a4294b78 696 inline wxXPMDataHandler()
f97c9854
JS
697 {
698 m_name = "XPM data";
699 m_extension = "xpm";
700 m_type = wxBITMAP_TYPE_XPM_DATA;
701 };
31528cd3 702
f97c9854
JS
703 virtual bool Create(wxBitmap *bitmap, void *data, long flags, int width, int height, int depth = 1);
704};
705IMPLEMENT_DYNAMIC_CLASS(wxXPMDataHandler, wxBitmapHandler)
706
31528cd3 707bool wxXPMDataHandler::Create( wxBitmap *bitmap, void *data, long WXUNUSED(flags),
2d120f83 708 int width, int height, int WXUNUSED(depth))
f97c9854
JS
709{
710 M_BITMAPHANDLERDATA->m_width = width;
711 M_BITMAPHANDLERDATA->m_height = height;
712 M_BITMAPHANDLERDATA->m_depth = 1;
713 M_BITMAPHANDLERDATA->m_freePixmap = TRUE;
31528cd3 714
a4294b78 715 Display *dpy = (Display*) wxGetDisplay();
f97c9854 716 M_BITMAPHANDLERDATA->m_display = (WXDisplay*) dpy;
31528cd3 717
f97c9854 718 XpmAttributes xpmAttr;
31528cd3 719
f97c9854 720 xpmAttr.valuemask = XpmReturnInfos; /* nothing yet, but get infos back */
31528cd3 721
f97c9854
JS
722 XpmColorSymbol symbolicColors[4];
723 if (sg_Control && sg_Control->GetMainWidget())
724 {
725 symbolicColors[0].name = "foreground";
726 symbolicColors[0].value = NULL;
727 symbolicColors[1].name = "background";
728 symbolicColors[1].value = NULL;
729 XtVaGetValues((Widget) sg_Control->GetMainWidget(),
730 XmNforeground, &symbolicColors[0].pixel,
731 XmNbackground, &symbolicColors[1].pixel,NULL);
732 xpmAttr.numsymbols = 2;
733 xpmAttr.colorsymbols = symbolicColors;
734 xpmAttr.valuemask |= XpmColorSymbols; // add flag
735 }
31528cd3 736
f97c9854
JS
737 Pixmap pixmap;
738 Pixmap mask = 0;
739 int ErrorStatus = XpmCreatePixmapFromData(dpy, RootWindow(dpy, DefaultScreen(dpy)),
2d120f83 740 (char**) data, &pixmap, &mask, &xpmAttr);
f97c9854
JS
741 if (ErrorStatus == XpmSuccess)
742 {
743 // Set attributes
744 M_BITMAPHANDLERDATA->m_width = xpmAttr.width;
745 M_BITMAPHANDLERDATA->m_height = xpmAttr.height;
31528cd3 746
0d57be45
JS
747 unsigned int depthRet;
748 int xRet, yRet;
749 unsigned int widthRet, heightRet, borderWidthRet;
750 Window rootWindowRet;
751 XGetGeometry(dpy, pixmap, &rootWindowRet, &xRet, &yRet,
752 &widthRet, &heightRet, &borderWidthRet, &depthRet);
31528cd3 753
2d120f83
JS
754 /*
755 if ( xpmAttr.npixels > 2 )
756 {
f97c9854 757 M_BITMAPHANDLERDATA->m_depth = 8; // next time not just a guess :-) ...
2d120f83
JS
758 } else
759 {
f97c9854 760 M_BITMAPHANDLERDATA->m_depth = 1; // mono
2d120f83
JS
761 }
762 */
31528cd3 763
0d57be45 764 M_BITMAPHANDLERDATA->m_depth = depthRet;
31528cd3 765
f97c9854
JS
766 M_BITMAPHANDLERDATA->m_numColors = xpmAttr.npixels;
767 XpmFreeAttributes(&xpmAttr);
768 M_BITMAPHANDLERDATA->m_ok = TRUE;
769 M_BITMAPHANDLERDATA->m_pixmap = (WXPixmap) pixmap;
770 if ( mask )
771 {
772 M_BITMAPHANDLERDATA->m_bitmapMask = new wxMask;
773 M_BITMAPHANDLERDATA->m_bitmapMask->SetPixmap((WXPixmap) mask);
774 }
775 }
776 else
777 {
2d120f83 778 // XpmDebugError(ErrorStatus, NULL);
f97c9854
JS
779 M_BITMAPHANDLERDATA->m_ok = FALSE;
780 }
781 return M_BITMAPHANDLERDATA->m_ok ;
782}
783
31528cd3 784#endif // wxHAVE_LIB_XPM
4bb6408c
JS
785
786void wxBitmap::CleanUpHandlers()
787{
788 wxNode *node = sm_handlers.First();
789 while ( node )
790 {
791 wxBitmapHandler *handler = (wxBitmapHandler *)node->Data();
792 wxNode *next = node->Next();
793 delete handler;
794 delete node;
795 node = next;
796 }
797}
798
799void wxBitmap::InitStandardHandlers()
800{
f97c9854
JS
801 // Initialize all standard bitmap or derived class handlers here.
802 AddHandler(new wxXBMFileHandler);
803 AddHandler(new wxXBMDataHandler);
31528cd3
VZ
804
805 // XPM is considered standard for Motif, although it can be omitted if
806 // libXpm is not installed
807#if wxHAVE_LIB_XPM
4bb6408c
JS
808 AddHandler(new wxXPMFileHandler);
809 AddHandler(new wxXPMDataHandler);
31528cd3 810#endif // wxHAVE_LIB_XPM
f97c9854
JS
811}
812
813WXPixmap wxBitmap::GetLabelPixmap (WXWidget w)
814{
2d120f83
JS
815 if (M_BITMAPDATA->m_image == (WXPixmap) 0)
816 return M_BITMAPDATA->m_pixmap;
31528cd3 817
2d120f83 818 Display *dpy = (Display*) M_BITMAPDATA->m_display;
31528cd3 819
f97c9854 820#ifdef FOO
2d120f83
JS
821 /*
822 If we do:
823 if (labelPixmap) return labelPixmap;
824 things can be wrong, because colors can have been changed.
31528cd3 825
2d120f83
JS
826 If we do:
827 if (labelPixmap)
828 XmDestroyPixmap(DefaultScreenOfDisplay(dpy),labelPixmap) ;
829 we got BadDrawable if the pixmap is referenced by multiples widgets
31528cd3 830
2d120f83 831 this is a catch22!!
31528cd3 832
2d120f83
JS
833 So, before doing thing really clean, I just do nothing; if the pixmap is
834 referenced by many widgets, Motif performs caching functions.
835 And if pixmap is referenced with multiples colors, we just have some
836 memory leaks... I hope we can deal with them...
837 */
838 // Must be destroyed, because colours can have been changed!
839 if (M_BITMAPDATA->m_labelPixmap)
840 XmDestroyPixmap (DefaultScreenOfDisplay (dpy), M_BITMAPDATA->m_labelPixmap);
f97c9854 841#endif
31528cd3 842
2d120f83
JS
843 char tmp[128];
844 sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image);
31528cd3 845
2d120f83
JS
846 Pixel fg, bg;
847 Widget widget = (Widget) w;
31528cd3 848
2d120f83
JS
849 while (XmIsGadget ( widget ))
850 widget = XtParent (widget);
851 XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL);
31528cd3 852
2d120f83 853 M_BITMAPDATA->m_labelPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
31528cd3 854
2d120f83 855 return M_BITMAPDATA->m_labelPixmap;
f97c9854
JS
856}
857
858WXPixmap wxBitmap::GetArmPixmap (WXWidget w)
859{
2d120f83
JS
860 if (M_BITMAPDATA->m_image == (WXPixmap) 0)
861 return M_BITMAPDATA->m_pixmap;
31528cd3 862
2d120f83 863 Display *dpy = (Display*) M_BITMAPDATA->m_display;
f97c9854 864#ifdef FOO
2d120f83
JS
865 See GetLabelPixmap () comment
866 // Must be destroyed, because colours can have been changed!
867 if (M_BITMAPDATA->m_armPixmap)
868 XmDestroyPixmap (DefaultScreenOfDisplay (dpy), M_BITMAPDATA->m_armPixmap);
f97c9854 869#endif
31528cd3 870
2d120f83
JS
871 char tmp[128];
872 sprintf (tmp, "Im%x", (unsigned int) M_BITMAPDATA->m_image);
31528cd3 873
2d120f83
JS
874 Pixel fg, bg;
875 Widget widget = (Widget) w;
31528cd3 876
2d120f83
JS
877 XtVaGetValues (widget, XmNarmColor, &bg, NULL);
878 while (XmIsGadget (widget))
879 widget = XtParent (widget);
880 XtVaGetValues (widget, XmNforeground, &fg, NULL);
31528cd3 881
2d120f83 882 M_BITMAPDATA->m_armPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
31528cd3 883
2d120f83 884 return M_BITMAPDATA->m_armPixmap;
f97c9854
JS
885}
886
887WXPixmap wxBitmap::GetInsensPixmap (WXWidget w)
888{
2d120f83 889 Display *dpy = (Display*) M_BITMAPDATA->m_display;
31528cd3 890
0d57be45 891 if (M_BITMAPDATA->m_insensPixmap)
2d120f83 892 return M_BITMAPDATA->m_insensPixmap;
31528cd3 893
2d120f83
JS
894 if (!w)
895 {
896 M_BITMAPDATA->m_insensPixmap = (WXPixmap) XCreateInsensitivePixmap(dpy, (Pixmap) M_BITMAPDATA->m_pixmap);
897 if (M_BITMAPDATA->m_insensPixmap)
898 return M_BITMAPDATA->m_insensPixmap;
899 else
900 return M_BITMAPDATA->m_pixmap;
901 }
31528cd3 902
2d120f83
JS
903 if (M_BITMAPDATA->m_insensImage == (WXPixmap) 0)
904 return M_BITMAPDATA->m_pixmap;
31528cd3 905
f97c9854 906#ifdef FOO
2d120f83
JS
907 See GetLabelPixmap () comment
908 // Must be destroyed, because colours can have been changed!
909 if (M_BITMAPDATA->m_insensPixmap)
910 XmDestroyPixmap (DefaultScreenOfDisplay (dpy), (Pixmap) M_BITMAPDATA->m_insensPixmap);
f97c9854 911#endif
31528cd3 912
2d120f83
JS
913 char tmp[128];
914 sprintf (tmp, "Not%x", (unsigned int) M_BITMAPDATA->m_insensImage);
31528cd3 915
2d120f83
JS
916 Pixel fg, bg;
917 Widget widget = (Widget) w;
31528cd3 918
2d120f83
JS
919 while (XmIsGadget (widget))
920 widget = XtParent (widget);
921 XtVaGetValues (widget, XmNbackground, &bg, XmNforeground, &fg, NULL);
31528cd3 922
2d120f83 923 M_BITMAPDATA->m_insensPixmap = (WXPixmap) XmGetPixmap (DefaultScreenOfDisplay (dpy), tmp, fg, bg);
31528cd3 924
2d120f83 925 return M_BITMAPDATA->m_insensPixmap;
f97c9854
JS
926}
927
928// We may need this sometime...
929
930/****************************************************************************
931
2d120f83
JS
932 NAME
933 XCreateInsensitivePixmap - create a grayed-out copy of a pixmap
31528cd3 934
2d120f83 935 SYNOPSIS
f97c9854 936 Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
31528cd3 937
2d120f83
JS
938 DESCRIPTION
939 This function creates a grayed-out copy of the argument pixmap, suitable
940 for use as a XmLabel's XmNlabelInsensitivePixmap resource.
31528cd3 941
2d120f83
JS
942 RETURN VALUES
943 The return value is the new Pixmap id or zero on error. Errors include
944 a NULL display argument or an invalid Pixmap argument.
31528cd3 945
2d120f83
JS
946 ERRORS
947 If one of the XLib functions fail, it will produce a X error. The
948 default X error handler prints a diagnostic and calls exit().
31528cd3 949
2d120f83
JS
950 SEE ALSO
951 XCopyArea(3), XCreateBitmapFromData(3), XCreateGC(3), XCreatePixmap(3),
952 XFillRectangle(3), exit(2)
31528cd3 953
2d120f83
JS
954 AUTHOR
955 John R Veregge - john@puente.jpl.nasa.gov
956 Advanced Engineering and Prototyping Group (AEG)
957 Information Systems Technology Section (395)
958 Jet Propulsion Lab - Calif Institute of Technology
31528cd3 959
f97c9854
JS
960*****************************************************************************/
961
962Pixmap
963XCreateInsensitivePixmap( Display *display, Pixmap pixmap )
964
965{
2d120f83 966 static
31528cd3 967 char stipple_data[] =
2d120f83
JS
968 {
969 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
f97c9854
JS
970 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
971 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA,
972 0x55, 0x55, 0xAA, 0xAA, 0x55, 0x55, 0xAA, 0xAA
2d120f83 973 };
f97c9854
JS
974 GC gc;
975 Pixmap ipixmap, stipple;
976 unsigned width, height, depth;
31528cd3 977
f97c9854
JS
978 Window window; /* These return values */
979 unsigned border; /* from XGetGeometry() */
980 int x, y; /* are not needed. */
31528cd3 981
f97c9854 982 ipixmap = 0;
31528cd3 983
f97c9854 984 if ( NULL == display || 0 == pixmap )
2d120f83 985 return ipixmap;
31528cd3 986
f97c9854 987 if ( 0 == XGetGeometry( display, pixmap, &window, &x, &y,
2d120f83
JS
988 &width, &height, &border, &depth )
989 )
990 return ipixmap; /* BadDrawable: probably an invalid pixmap */
31528cd3 991
2d120f83 992 /* Get the stipple pixmap to be used to 'gray-out' the argument pixmap.
f97c9854
JS
993 */
994 stipple = XCreateBitmapFromData( display, pixmap, stipple_data, 16, 16 );
995 if ( 0 != stipple )
996 {
2d120f83
JS
997 gc = XCreateGC( display, pixmap, (XtGCMask)0, (XGCValues*)NULL );
998 if ( NULL != gc )
f97c9854 999 {
2d120f83
JS
1000 /* Create an identical copy of the argument pixmap.
1001 */
1002 ipixmap = XCreatePixmap( display, pixmap, width, height, depth );
1003 if ( 0 != ipixmap )
1004 {
1005 /* Copy the argument pixmap into the new pixmap.
1006 */
1007 XCopyArea( display, pixmap, ipixmap,
1008 gc, 0, 0, width, height, 0, 0 );
31528cd3 1009
2d120f83
JS
1010 /* Refill the new pixmap using the stipple algorithm/pixmap.
1011 */
1012 XSetStipple( display, gc, stipple );
1013 XSetFillStyle( display, gc, FillStippled );
1014 XFillRectangle( display, ipixmap, gc, 0, 0, width, height );
1015 }
1016 XFreeGC( display, gc );
f97c9854 1017 }
2d120f83 1018 XFreePixmap( display, stipple );
f97c9854
JS
1019 }
1020 return ipixmap;
4bb6408c 1021}
f97c9854 1022
321db4b6
JS
1023// Creates a bitmap with transparent areas drawn in
1024// the given colour.
1025wxBitmap wxCreateMaskedBitmap(wxBitmap& bitmap, wxColour& colour)
1026{
1027 wxBitmap newBitmap(bitmap.GetWidth(),
2d120f83
JS
1028 bitmap.GetHeight(),
1029 bitmap.GetDepth());
321db4b6
JS
1030 wxMemoryDC destDC;
1031 wxMemoryDC srcDC;
1032 srcDC.SelectObject(bitmap);
1033 destDC.SelectObject(newBitmap);
31528cd3 1034
321db4b6
JS
1035 wxBrush brush(colour, wxSOLID);
1036 destDC.SetOptimization(FALSE);
1037 destDC.SetBackground(brush);
1038 destDC.Clear();
1039 destDC.Blit(0, 0, bitmap.GetWidth(), bitmap.GetHeight(), & srcDC, 0, 0, wxCOPY, TRUE);
31528cd3 1040
321db4b6
JS
1041 return newBitmap;
1042}