Added reset of pointer after memory free to avoid double-free crash
[wmaker-crm.git] / WPrefs.app / double.c
blobd708b0d8d8bdaa749e5375d26454d0481afd5d03
2 /*
3 * Widget for testing double-clicks
5 */
7 #include <WINGs/WINGsP.h>
9 #include "double.h"
11 typedef struct W_DoubleTest {
12 W_Class widgetClass;
13 WMView *view;
15 WMHandlerID timer;
16 char on;
17 char active;
18 char *text;
19 } _DoubleTest;
21 /* some forward declarations */
23 static void destroyDoubleTest(_DoubleTest * dPtr);
24 static void paintDoubleTest(_DoubleTest * dPtr);
26 static void handleEvents(XEvent * event, void *data);
27 static void handleActionEvents(XEvent * event, void *data);
29 /* our widget class ID */
30 static W_Class DoubleTestClass = 0;
33 * Initializer for our widget. Must be called before creating any
34 * instances of the widget.
36 W_Class InitDoubleTest(WMScreen * scr)
38 /* register our widget with WINGs and get our widget class ID */
39 if (!DoubleTestClass) {
40 DoubleTestClass = W_RegisterUserWidget();
43 return DoubleTestClass;
47 * Our widget fabrication plant.
49 DoubleTest *CreateDoubleTest(WMWidget * parent, char *text)
51 DoubleTest *dPtr;
53 if (!DoubleTestClass)
54 InitDoubleTest(WMWidgetScreen(parent));
56 /* allocate some storage for our new widget instance */
57 dPtr = wmalloc(sizeof(DoubleTest));
59 /* set the class ID */
60 dPtr->widgetClass = DoubleTestClass;
62 dPtr->view = W_CreateView(W_VIEW(parent));
63 if (!dPtr->view) {
64 wfree(dPtr);
65 return NULL;
67 /* always do this */
68 dPtr->view->self = dPtr;
70 dPtr->text = wstrdup(text);
72 WMCreateEventHandler(dPtr->view, ExposureMask /* this allows us to know when we should paint */
73 | StructureNotifyMask, /* this allows us to know things like when we are destroyed */
74 handleEvents, dPtr);
76 WMCreateEventHandler(dPtr->view, ButtonPressMask, handleActionEvents, dPtr);
78 return dPtr;
81 static void paintDoubleTest(_DoubleTest * dPtr)
83 W_Screen *scr = dPtr->view->screen;
85 if (dPtr->active) {
86 XFillRectangle(scr->display, dPtr->view->window, WMColorGC(scr->white),
87 0, 0, dPtr->view->size.width, dPtr->view->size.height);
88 } else {
89 XClearWindow(scr->display, dPtr->view->window);
92 W_DrawRelief(scr, dPtr->view->window, 0, 0, dPtr->view->size.width,
93 dPtr->view->size.height, dPtr->on ? WRSunken : WRRaised);
95 if (dPtr->text) {
96 int y;
97 y = (dPtr->view->size.height - scr->normalFont->height) / 2;
98 W_PaintText(dPtr->view, dPtr->view->window, scr->normalFont,
99 dPtr->on, dPtr->on + y, dPtr->view->size.width, WACenter,
100 scr->black, False, dPtr->text, strlen(dPtr->text));
104 static void handleEvents(XEvent * event, void *data)
106 _DoubleTest *dPtr = (_DoubleTest *) data;
108 switch (event->type) {
109 case Expose:
110 if (event->xexpose.count != 0)
111 break;
112 paintDoubleTest(dPtr);
113 break;
115 case DestroyNotify:
116 destroyDoubleTest(dPtr);
117 break;
122 static void deactivate(void *data)
124 _DoubleTest *dPtr = (_DoubleTest *) data;
126 if (dPtr->active)
127 dPtr->active = 0;
128 paintDoubleTest(dPtr);
130 dPtr->timer = NULL;
133 static void handleActionEvents(XEvent * event, void *data)
135 _DoubleTest *dPtr = (_DoubleTest *) data;
136 extern _WINGsConfiguration WINGsConfiguration;
138 switch (event->type) {
139 case ButtonPress:
140 if (WMIsDoubleClick(event)) {
141 if (dPtr->timer)
142 WMDeleteTimerHandler(dPtr->timer);
143 dPtr->timer = NULL;
144 dPtr->on = !dPtr->on;
145 dPtr->active = 0;
146 paintDoubleTest(dPtr);
147 } else {
148 dPtr->timer = WMAddTimerHandler(WINGsConfiguration.doubleClickDelay, deactivate, dPtr);
149 dPtr->active = 1;
150 paintDoubleTest(dPtr);
152 break;
156 static void destroyDoubleTest(_DoubleTest * dPtr)
158 if (dPtr->timer)
159 WMDeleteTimerHandler(dPtr->timer);
160 if (dPtr->text)
161 wfree(dPtr->text);
163 wfree(dPtr);