1 /*
2 * XP-Replay, playback an XPilot session. Copyright (C) 1994-98 by
3 *
4 * Bj�rn Stabell <bjoern@xpilot.org>
5 * Ken Ronny Schouten <ken@xpilot.org>
6 * Bert Gijsbers <bert@xpilot.org>
7 * Steven Singer (S.Singer@ph.surrey.ac.uk)
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERC_HANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License
20 * along with this program; if not, write to the Free Software
21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 */
23
24 #include "xp-replay.h"
25
26 #include "tools/grey.xbm"
27
28 struct button {
29 struct button *next;
30 Display *display;
31 Window window;
32 unsigned long fg;
33 unsigned int width;
34 unsigned int height;
35 union button_image image;
36 unsigned int imagewidth;
37 unsigned int imageheight;
38 int flags;
39 int group;
40 void (*callback)(void *);
41 void *data;
42 };
43
44 static unsigned long background = 0,
45 topshadow = 0,
46 bottomshadow = 0,
47 black = 0;
48 static Button buttonhead = NULL, buttontail = NULL;
49 static XFontStruct *buttonFont = NULL;
50
SetGlobalButtonAttributes(unsigned long bg,unsigned long ts,unsigned long bs,unsigned long bl)51 void SetGlobalButtonAttributes(unsigned long bg,
52 unsigned long ts,
53 unsigned long bs,
54 unsigned long bl)
55 {
56 Button b;
57 int flag = 0;
58
59 if (background != bg) {
60 for (b = buttonhead; b != NULL; b = b->next)
61 XSetWindowBackground(b->display, b->window, bg);
62 background = bg;
63 flag = 1;
64 }
65 background = bg;
66 if (topshadow != ts || bottomshadow != bs || black != bl)
67 flag = 1;
68 topshadow = ts;
69 bottomshadow = bs;
70 black = bl;
71 if (flag)
72 for (b = buttonhead; b != NULL; b = b->next)
73 RedrawButton(b);
74 }
75
SetButtonFont(Display * display)76 static void SetButtonFont(Display *display)
77 {
78 if ((buttonFont =
79 XLoadQueryFont(display,
80 "-*-helvetica-bold-r-*--14-*-*-*-*-*-*-*")) == NULL)
81 buttonFont = XQueryFont(display, XGContextFromGC(DefaultGC(display,
82 DefaultScreen(display))));
83 }
84
CreateButton(Display * display,Window parent,int x,int y,unsigned int width,unsigned int height,union button_image image,unsigned iw,unsigned ih,unsigned long foreground,void (* callback)(void *),void * data,int flags,int group)85 Button CreateButton(Display *display, Window parent,
86 int x, int y,
87 unsigned int width, unsigned int height,
88 union button_image image,
89 unsigned iw, unsigned ih,
90 unsigned long foreground,
91 void (*callback)(void *),
92 void *data, int flags, int group)
93 {
94 Window window;
95 Button b;
96
97 b = (Button) MyMalloc(sizeof(struct button), MEM_UI);
98
99 if ((width == 0 || height == 0) && (flags & BUTTON_TEXT)) {
100 if (buttonFont == NULL)
101 SetButtonFont(display);
102 if (width == 0)
103 width = XTextWidth(buttonFont, image.string,
104 (int)strlen(image.string)) + 10;
105 if (height == 0)
106 height = buttonFont->ascent + buttonFont->descent + 10;
107 }
108
109 window = XCreateSimpleWindow(display, parent,
110 x, y,
111 width, height,
112 0,
113 background, background);
114
115 b->display = display;
116 b->window = window;
117 b->fg = foreground;
118 b->width = width;
119 b->height = height;
120 b->image = image;
121 b->imagewidth = iw;
122 b->imageheight = ih;
123 b->flags = flags;
124 b->group = group;
125 b->callback = callback;
126 b->data = data;
127 b->next = NULL;
128
129 if (buttontail == NULL)
130 buttonhead = buttontail = b;
131 else {
132 buttontail->next = b;
133 buttontail = b;
134 }
135
136 XSelectInput(display, window,
137 ExposureMask | ButtonPressMask | ButtonReleaseMask);
138
139 XMapWindow(display, window);
140
141 return(b);
142 }
143
ReleaseButtons(Button b)144 static void ReleaseButtons(Button b)
145 {
146 Button c;
147
148 if (b->group != 0) {
149 for (c = buttonhead; c != NULL; c = c->next)
150 if (c->group == b->group && c != b
151 && (c->flags & BUTTON_PRESSED)) {
152 c->flags &= ~BUTTON_PRESSED;
153 RedrawButton(c);
154 }
155 }
156 }
157
PressButton(Button b)158 static void PressButton(Button b)
159 {
160 /* Buttons which stay in have no affect if pressed when in */
161
162 if ((b->flags & BUTTON_PRESSED && !(b->flags & BUTTON_RELEASE)) ||
163 b->flags & BUTTON_DISABLED)
164 return;
165
166 ReleaseButtons(b);
167
168 b->flags |= BUTTON_PRESSED;
169
170 RedrawButton(b);
171
172 if (!(b->flags & BUTTON_RELEASE) && b->callback != NULL)
173 b->callback(b->data);
174 }
175
ReleaseButton(Button b,Bool inwindow)176 static void ReleaseButton(Button b, Bool inwindow)
177 {
178
179 if (!(b->flags & BUTTON_PRESSED) || !(b->flags & BUTTON_RELEASE) ||
180 b->flags & BUTTON_DISABLED)
181 return;
182
183 b->flags &= ~BUTTON_PRESSED;
184
185 RedrawButton(b);
186
187 if (inwindow && b->callback != NULL)
188 b->callback(b->data);
189 }
190
CheckButtonEvent(XEvent * event)191 int CheckButtonEvent(XEvent *event)
192 {
193 Button b;
194
195 for (b = buttonhead; b != NULL; b = b->next)
196 if (event->xany.window == b->window)
197 break;
198
199 if (b == NULL)
200 return(0);
201
202 switch(event->type) {
203 case Expose:
204 if (event->xexpose.count != 0)
205 return(1);
206 RedrawButton(b);
207 return(1);
208 case ButtonPress:
209 if (event->xbutton.button == 1)
210 PressButton(b);
211 return(1);
212 case ButtonRelease:
213 if (event->xbutton.button == 1)
214 ReleaseButton(b, (event->xbutton.x >= 0 &&
215 event->xbutton.y >= 0 &&
216 event->xbutton.x < (int)b->width &&
217 event->xbutton.y < (int)b->height)
218 ? True : False);
219 return(1);
220 default:
221 break;
222 }
223
224 return(0);
225 }
226
RedrawButton(Button b)227 void RedrawButton(Button b)
228 {
229 static GC gc = 0;
230 static Pixmap grey = 0;
231 int bh = b->height, bw = b->width;
232
233 if (gc == 0) {
234 gc = XCreateGC(b->display, b->window, 0, NULL);
235 if (buttonFont == NULL)
236 SetButtonFont(b->display);
237 XSetFont(b->display, gc, buttonFont->fid);
238 }
239
240 if (grey == 0) {
241 grey = XCreateBitmapFromData(b->display, b->window, (char *) grey_bits,
242 grey_width, grey_height);
243 XSetStipple(b->display, gc, grey);
244 }
245
246 XSetBackground(b->display, gc, background);
247
248 XClearWindow(b->display, b->window);
249
250 XSetForeground(b->display, gc, b->fg);
251
252 if (b->flags & BUTTON_TEXT)
253 XDrawString(b->display, b->window, gc, 5, 5 + buttonFont->ascent,
254 b->image.string, (int)strlen(b->image.string));
255 else if (b->image.icon != None) {
256 int x, y;
257 unsigned w, h;
258
259 w = (b->imagewidth);
260 if (w > b->width)
261 w = b->width;
262 h = (b->imageheight);
263 if (h > b->height)
264 h = b->height;
265 x = (b->width - w) >> 1;
266 y = (b->height - h) >> 1;
267 XCopyPlane(b->display, b->image.icon, b->window, gc,
268 (int)((b->imagewidth-w) >> 1),
269 (int)((b->imageheight-h) >> 1),
270 w, h, x, y, 1);
271 }
272
273 if (b->flags & BUTTON_DISABLED) {
274 XSetForeground(b->display, gc, background);
275 XSetFillStyle(b->display, gc, FillStippled);
276 XFillRectangle(b->display, b->window, gc, 0, 0, b->width, b->height);
277 XSetFillStyle(b->display, gc, FillSolid);
278 }
279
280 if (b->flags & BUTTON_PRESSED) {
281 XSetForeground(b->display, gc, black);
282 XDrawRectangle(b->display, b->window, gc,
283 0, 0, b->width-1, b->height-1);
284 XDrawRectangle(b->display, b->window, gc,
285 1, 1, b->width-3, b->height-3);
286 } else {
287 XSetForeground(b->display, gc, bottomshadow);
288 XDrawLine(b->display, b->window, gc, 0, bh-1, bw-1, bh-1);
289 XDrawLine(b->display, b->window, gc, bw-1, bh-1, bw-1, 0);
290 XSetForeground(b->display, gc, topshadow);
291 XDrawLine(b->display, b->window, gc, 0, 0, bw-1, 0);
292 XDrawLine(b->display, b->window, gc, 0, 0, 0, bh-1);
293 XSetForeground(b->display, gc, bottomshadow);
294 XDrawLine(b->display, b->window, gc, 1, bh-2, bw-2, bh-2);
295 XDrawLine(b->display, b->window, gc, bw-2, bh-2, bw-2, 1);
296 XSetForeground(b->display, gc, topshadow);
297 XDrawLine(b->display, b->window, gc, 1, 1, bw-2, 1);
298 XDrawLine(b->display, b->window, gc, 1, 1, 1, bh-2);
299 }
300
301 XSetForeground(b->display, gc, bottomshadow);
302 XDrawLine(b->display, b->window, gc, 2, bh-3, bw-3, bh-3);
303 XDrawLine(b->display, b->window, gc, bw-3, bh-3, bw-3, 2);
304 XSetForeground(b->display, gc, topshadow);
305 XDrawLine(b->display, b->window, gc, 2, 2, bw-3, 2);
306 XDrawLine(b->display, b->window, gc, 2, 2, 2, bh-3);
307
308 }
309
DisableButton(Button b)310 void DisableButton(Button b)
311 {
312 if (b->flags & BUTTON_DISABLED)
313 return;
314
315 b->flags |= BUTTON_DISABLED;
316
317 RedrawButton(b);
318 }
319
EnableButton(Button b)320 void EnableButton(Button b)
321 {
322 if (!(b->flags & BUTTON_DISABLED))
323 return;
324
325 b->flags &= ~BUTTON_DISABLED;
326
327 RedrawButton(b);
328 }
329
ReleaseableButton(Button b)330 void ReleaseableButton(Button b)
331 {
332 int i;
333
334 i = (b->flags & BUTTON_PRESSED);
335
336 b->flags &= ~BUTTON_PRESSED;
337 b->flags |= BUTTON_RELEASE;
338
339 if (i)
340 RedrawButton(b);
341 }
342
NonreleaseableButton(Button b)343 void NonreleaseableButton(Button b)
344 {
345 b->flags &= ~BUTTON_RELEASE;
346 }
347
ChangeButtonGroup(Button b,int group)348 void ChangeButtonGroup(Button b, int group)
349 {
350 if (group == b->group)
351 return;
352
353 b->group = group;
354
355 if (b->flags & BUTTON_PRESSED)
356 ReleaseButtons(b);
357 }
358
MoveButton(Button b,int x,int y)359 void MoveButton(Button b, int x, int y)
360 {
361 XWindowChanges values;
362
363 values.x = x;
364 values.y = y;
365
366 XConfigureWindow(b->display, b->window, CWX | CWY, &values);
367 }
368
GetButtonSize(Button b,unsigned * width,unsigned * height)369 void GetButtonSize(Button b, unsigned *width, unsigned *height)
370 {
371 *width = b->width;
372 *height = b->height;
373 }
374