Fix buffer overrun in Linux/x86_64 (Pixel is a 64 bit long, passing
[wxWidgets.git] / src / motif / bmpbuttn.cpp
1 /////////////////////////////////////////////////////////////////////////////
2 // Name: src/motif/bmpbuttn.cpp
3 // Purpose: wxBitmapButton
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 // For compilers that support precompilation, includes "wx.h".
13 #include "wx/wxprec.h"
14
15 #ifdef __VMS
16 #define XtScreen XTSCREEN
17 #endif
18
19 #include "wx/bmpbuttn.h"
20
21 #ifdef __VMS__
22 #pragma message disable nosimpint
23 #endif
24 #include <Xm/PushBG.h>
25 #include <Xm/PushB.h>
26 #ifdef __VMS__
27 #pragma message enable nosimpint
28 #endif
29
30 #include "wx/motif/private.h"
31
32 // Implemented in button.cpp
33 void wxButtonCallback (Widget w, XtPointer clientData, XtPointer ptr);
34
35 // Pixmap XCreateInsensitivePixmap( Display *display, Pixmap pixmap );
36
37 IMPLEMENT_DYNAMIC_CLASS(wxBitmapButton, wxButton)
38
39 wxBitmapButton::wxBitmapButton()
40 {
41 m_marginX = m_marginY = wxDEFAULT_BUTTON_MARGIN;
42 m_insensPixmap = (WXPixmap) 0;
43 }
44
45 bool wxBitmapButton::Create(wxWindow *parent, wxWindowID id,
46 const wxBitmap& bitmap,
47 const wxPoint& pos,
48 const wxSize& size, long style,
49 const wxValidator& validator,
50 const wxString& name)
51 {
52 if( !CreateControl( parent, id, pos, size, style, validator, name ) )
53 return false;
54
55 m_bmpNormal = m_bmpNormalOriginal = bitmap;
56 m_bmpSelected = m_bmpSelectedOriginal = bitmap;
57
58 Widget parentWidget = (Widget) parent->GetClientWidget();
59
60 /*
61 * Patch Note (important)
62 * There is no major reason to put a defaultButtonThickness here.
63 * Not requesting it give the ability to put wxButton with a spacing
64 * as small as requested. However, if some button become a DefaultButton,
65 * other buttons are no more aligned -- This is why we set
66 * defaultButtonThickness of ALL buttons belonging to the same wxPanel,
67 * in the ::SetDefaultButton method.
68 */
69 Widget buttonWidget = XtVaCreateManagedWidget ("button",
70
71 // Gadget causes problems for default button operation.
72 #if wxUSE_GADGETS
73 xmPushButtonGadgetClass, parentWidget,
74 #else
75 xmPushButtonWidgetClass, parentWidget,
76 #endif
77 // See comment for wxButton::SetDefault
78 // XmNdefaultButtonShadowThickness, 1,
79 XmNrecomputeSize, False,
80 NULL);
81
82 m_mainWidget = (WXWidget) buttonWidget;
83
84 ChangeFont(false);
85
86 ChangeBackgroundColour ();
87
88 DoSetBitmap();
89
90 XtAddCallback (buttonWidget,
91 XmNactivateCallback, (XtCallbackProc) wxButtonCallback,
92 (XtPointer) this);
93
94 wxSize best = m_bmpNormal.Ok() ? GetBestSize() : wxSize(30, 30);
95 if( size.x != -1 ) best.x = size.x;
96 if( size.y != -1 ) best.y = size.y;
97
98 AttachWidget (parent, m_mainWidget, (WXWidget) NULL,
99 pos.x, pos.y, best.x, best.y);
100
101 return true;
102 }
103
104 wxBitmapButton::~wxBitmapButton()
105 {
106 SetBitmapLabel(wxNullBitmap);
107
108 if (m_insensPixmap)
109 XmDestroyPixmap (DefaultScreenOfDisplay ((Display*) GetXDisplay()),
110 (Pixmap) m_insensPixmap);
111 }
112
113 void wxBitmapButton::SetBitmapLabel(const wxBitmap& bitmap)
114 {
115 m_bmpNormalOriginal = bitmap;
116 m_bmpNormal = bitmap;
117
118 DoSetBitmap();
119 }
120
121 void wxBitmapButton::SetBitmapSelected(const wxBitmap& sel)
122 {
123 m_bmpSelected = sel;
124 m_bmpSelectedOriginal = sel;
125
126 DoSetBitmap();
127 }
128
129 void wxBitmapButton::SetBitmapFocus(const wxBitmap& focus)
130 {
131 m_bmpFocus = focus;
132 // Not used in Motif
133 }
134
135 void wxBitmapButton::SetBitmapDisabled(const wxBitmap& disabled)
136 {
137 m_bmpDisabled = disabled;
138 m_bmpDisabledOriginal = disabled;
139
140 DoSetBitmap();
141 }
142
143 void wxBitmapButton::DoSetBitmap()
144 {
145 if (m_bmpNormalOriginal.Ok())
146 {
147 Pixmap pixmap = 0;
148 Pixmap insensPixmap = 0;
149 Pixmap armPixmap = 0;
150
151 // Must re-make the bitmap to have its transparent areas drawn
152 // in the current widget background colour.
153 if (m_bmpNormalOriginal.GetMask())
154 {
155 WXPixel backgroundPixel;
156 XtVaGetValues((Widget) m_mainWidget,
157 XmNbackground, &backgroundPixel,
158 NULL);
159
160 wxColour col;
161 col.SetPixel(backgroundPixel);
162
163 wxBitmap newBitmap =
164 wxCreateMaskedBitmap(m_bmpNormalOriginal, col);
165 m_bmpNormal = newBitmap;
166 m_bitmapCache.SetBitmap( m_bmpNormal );
167
168 pixmap = (Pixmap) m_bmpNormal.GetDrawable();
169 }
170 else
171 {
172 m_bitmapCache.SetBitmap( m_bmpNormal );
173 pixmap = (Pixmap) m_bitmapCache.GetLabelPixmap(m_mainWidget);
174 }
175
176 if (m_bmpDisabledOriginal.Ok())
177 {
178 if (m_bmpDisabledOriginal.GetMask())
179 {
180 WXPixel backgroundPixel;
181 XtVaGetValues((Widget) m_mainWidget,
182 XmNbackground, &backgroundPixel,
183 NULL);
184
185 wxColour col;
186 col.SetPixel(backgroundPixel);
187
188 wxBitmap newBitmap =
189 wxCreateMaskedBitmap(m_bmpDisabledOriginal, col);
190 m_bmpDisabled = newBitmap;
191
192 insensPixmap = (Pixmap) m_bmpDisabled.GetDrawable();
193 }
194 else
195 insensPixmap = (Pixmap) m_bitmapCache.GetInsensPixmap(m_mainWidget);
196 }
197 else
198 insensPixmap = (Pixmap) m_bitmapCache.GetInsensPixmap(m_mainWidget);
199
200 // Now make the bitmap representing the armed state
201 if (m_bmpSelectedOriginal.Ok())
202 {
203 if (m_bmpSelectedOriginal.GetMask())
204 {
205 WXPixel backgroundPixel;
206 XtVaGetValues((Widget) m_mainWidget,
207 XmNarmColor, &backgroundPixel,
208 NULL);
209
210 wxColour col;
211 col.SetPixel(backgroundPixel);
212
213 wxBitmap newBitmap =
214 wxCreateMaskedBitmap(m_bmpSelectedOriginal, col);
215 m_bmpSelected = newBitmap;
216
217 armPixmap = (Pixmap) m_bmpSelected.GetDrawable();
218 }
219 else
220 armPixmap = (Pixmap) m_bitmapCache.GetArmPixmap(m_mainWidget);
221 }
222 else
223 armPixmap = (Pixmap) m_bitmapCache.GetArmPixmap(m_mainWidget);
224
225 XtVaSetValues ((Widget) m_mainWidget,
226 XmNlabelPixmap, pixmap,
227 XmNlabelInsensitivePixmap, insensPixmap,
228 XmNarmPixmap, armPixmap,
229 XmNlabelType, XmPIXMAP,
230 NULL);
231 }
232 else
233 {
234 // Null bitmap: must not use current pixmap
235 // since it is no longer valid.
236 XtVaSetValues ((Widget) m_mainWidget,
237 XmNlabelType, XmSTRING,
238 XmNlabelPixmap, XmUNSPECIFIED_PIXMAP,
239 XmNlabelInsensitivePixmap, XmUNSPECIFIED_PIXMAP,
240 XmNarmPixmap, XmUNSPECIFIED_PIXMAP,
241 NULL);
242 }
243 }
244
245 void wxBitmapButton::ChangeBackgroundColour()
246 {
247 wxDoChangeBackgroundColour(m_mainWidget, m_backgroundColour, true);
248
249 // Must reset the bitmaps since the colours have changed.
250 DoSetBitmap();
251 }
252
253 wxSize wxBitmapButton::DoGetBestSize() const
254 {
255 wxSize ret( 30,30 );
256
257 if (m_bmpNormal.Ok())
258 {
259 int border = (GetWindowStyle() & wxNO_BORDER) ? 4 : 10;
260 ret.x = m_bmpNormal.GetWidth()+border;
261 ret.y = m_bmpNormal.GetHeight()+border;
262 }
263
264 return ret;
265 }