1 /*****************************************************************************/
2 /* */
3 /* */
4 /* X patience version 2 -- module X-events.c */
5 /* */
6 /* Event handlers for the X interface */
7 /* written by Heiko Eissfeldt and Michael Bischoff */
8 /* see COPYRIGHT.xpat2 for Copyright details */
9 /* */
10 /* */
11 /*****************************************************************************/
12 #include "X-pat.h"
13
14 /* #define LABER */
15
16 Display *dpy;
17 int screen;
18 unsigned long blackpixel;
19 unsigned long whitepixel;
20 GC blackgc;
21 GC whitegc;
22
23 /* flush event queue */
flush_display(void)24 void flush_display(void) {
25 XSync(dpy, 0); /* text first! */
26 }
27
28 #ifdef useXlib
intersect(int x1,int w1,int x2,int w2)29 static int intersect(int x1, int w1, int x2, int w2) {
30 if (x1 < x2)
31 return x1+w1 > x2;
32 else
33 return x2+w2 > x1;
34 }
35 #endif
36
37 /* events for Xlib AND Xaw interface */
38 /* event entry points are: key_press, button_press, button_release,
39 mouse_motion (only called with button 3 pressed) redraw_table */
40
41
key_press(XKeyPressedEvent * xev)42 void key_press(XKeyPressedEvent *xev) {
43 char str[32];
44 int num;
45
46 #define get_name_field() get_selection()
47
48 num = XLookupString(xev, str, 31, NULL, NULL);
49 if (num == 0)
50 return;
51 str[num] = '\0'; /* NULL to terminate it */
52
53 show_exposed_card(False);
54 key_pressed(str);
55 }
56
57 /* SPEEDUP does not work yet */
58 #ifdef SPEEDUP
59 static int pile_is_drawn[MAXPILES] = { 0, 0 };
60 static int buttons_are_drawn = 0;
61 #endif
62
63 extern int table_clear;
64
redraw_table(XExposeEvent * xev)65 void redraw_table(XExposeEvent *xev) {
66 int i;
67 table_clear = 0;
68 #ifdef useXlib
69 if (intersect(0, graphic.buttons_height, xev->y, xev->height))
70 #ifdef SPEEDUP
71 if (!buttons_are_drawn++)
72 #endif
73 redraw_buttons(xev->x, xev->y, xev->width, xev->height, table, button.num, button.b);
74 if (intersect(graphic.buttons_height, graphic.message_height, xev->y, xev->height))
75 show_message(NULL);
76 if (xev->count && xev->y + xev->height < graphic.yoff) /* else may miss the last event */
77 return;
78 #endif
79
80 #ifdef LABER
81 printf("request for expose %d,%d of size %d,%d, cnt %d\n", xev->x, xev->y, xev->width, xev->height, xev->count);
82 /* printf("height of 0=%d, 8=%d\n", p.geo[0], p.geo[8].h); */
83 #endif
84
85 for (i = 0; i < game.numpiles; ++i) {
86 struct pilegeometry *p;
87 #ifdef SPEEDUP
88 if (pile_is_drawn[i]++)
89 continue;
90 #endif
91 p = geo.pg + i;
92 if (NOT_DISPLAYED(p) ||
93 xev->x >= p->x + p->w || xev->x + xev->width <= p->x ||
94 xev->y >= p->y + p->h || xev->y + xev->height <= p->y)
95 continue; /* this pile is not affected */
96 #ifdef LABER
97 printf("request for update pile %d of pos %d,%d, size %d,%d\n", i,
98 p->x, p->y, p->w, p->h);
99 #endif
100 draw_pileupdate(i, 0);
101 }
102 if (!xev->count) {
103 show_arrow(2); /* Update hint arrow */
104 }
105 #ifdef LABER
106 if (!xev->count)
107 printf(" => last expose-table call\n");
108 #endif
109 #ifdef SPEEDUP
110 if (xev->count)
111 return;
112 /* was last event, unmark piles */
113 for (i = 0; i < MAXPILES; ++i)
114 pile_is_drawn[i] = 0;
115 buttons_are_drawn = 0;
116 #endif
117 }
118
119
120 /* the pointer is somewhere in the area of pile i */
121 /* check, if a card has to be exposed */
122
expose_card(Pileindex i,int x,int y)123 static void expose_card(Pileindex i, int x, int y) {
124 struct pilegeometry *p;
125 Cardindex ind;
126
127 if (EMPTY(i))
128 return;
129 p = geo.pg + i;
130 #if 0
131 ind = game.ind[i];
132 while (ind != INDEX_OF_LAST_CARD(i) && y >= p->y + graphic.cardy[ind+1])
133 ++ind;
134 #else
135 ind = FindCardOfMousePos(i, x, y);
136 #endif
137 if (ind == INDEX_OF_LAST_CARD(i)) /* the most bottom card don't has to */
138 ind = -1; /* be put on foreground */
139 if (graphic.zoomed_card != ind) { /* change of state */
140 show_exposed_card(False); /* hide it */
141 /* graphic.zoomed_card is now -1 */
142 if (ind >= 0) {
143 graphic.zoomed_card = ind;
144 show_exposed_card(True);
145 }
146 }
147 }
148
mouse_motion(XPointerMovedEvent * xev)149 void mouse_motion(XPointerMovedEvent *xev) {
150 Pileindex i;
151 /* find new pile */
152 for (i = FIRST_SLOT; i <= LAST_SLOT; ++i) {
153 struct pilegeometry *p;
154 p = geo.pg + i;
155 if (xev->x >= p->x && xev->x < p->x + p->w &&
156 xev->y >= p->y && xev->y < p->y + p->h) {
157 /* yeah, a slot is hit */
158 /* find out which card is the target */
159 expose_card(i, xev->x - p->x, xev->y - p->y);
160 return;
161 }
162 }
163 /* pointer moved out of scope: */
164 show_exposed_card(False);
165 }
166
button_release(XButtonPressedEvent * xev)167 void button_release(XButtonPressedEvent *xev) {
168 show_exposed_card(False);
169 }
170
button_press(XButtonPressedEvent * xev)171 void button_press(XButtonPressedEvent *xev) {
172 Pileindex i;
173
174 show_exposed_card(False);
175 #ifdef useXlib
176 { void (*func)(void);
177 func = check_button_list(button.b, button.num, xev);
178
179 /* check for hit button */
180 if (func) {
181 (*func)();
182 return;
183 }
184 }
185 #endif
186
187 for (i = 0; i < game.numpiles; ++i) {
188 struct pilegeometry *p;
189 p = geo.pg + i;
190 if (NOT_DISPLAYED(p))
191 continue;
192 if (xev->x >= p->x && xev->x < p->x + p->w &&
193 xev->y >= p->y && xev->y < p->y + p->h) {
194 Cardindex cardi;
195 #if 0
196 if EMPTY(i)
197 cardi = -1;
198 else {
199 cardi = INDEX_OF_LAST_CARD(i);
200 if (game.piletype[i] == Slot)
201 /* possibly a different card */
202 while (cardi != INDEX_OF_FIRST_CARD(i) &&
203 graphic.cardy[cardi] > xev->y - graphic.pile[i].y)
204 --cardi;
205 }
206 #else
207 cardi = FindCardOfMousePos(i, xev->x - p->x, xev->y - p->y);
208 if (cardi == -2) /* below := lowest */
209 cardi = INDEX_OF_LAST_CARD(i);
210 #endif
211 switch (xev->button) {
212 case Button1: /* quick move */
213 button_pressed(i, cardi, 1);
214 break;
215 case Button2: /* select / deselect */
216 button_pressed(i, cardi, 2);
217 break;
218 case Button3:
219 #ifdef BUTTON_3_DRAGS_CARD
220 button_pressed(i, cardi, 3);
221 #else
222 #ifndef useXview
223 if (game.piletype[i] == Slot)
224 expose_card(i, xev->x - p->x, xev->y - p->y);
225 #else
226 if (game.piletype[i] == Slot && cardi >= 0) {
227 expose_card(i, xev->x - p->x, xev->y - p->y);
228 } else {
229 menu_show(cmenu, canvas, bp_event, 0);
230 return;
231 }
232 #endif
233 break;
234 #endif
235 }
236 return;
237 }
238 }
239 #ifdef useXview
240 if (xev->button == Button3)
241 {
242 menu_show(cmenu, canvas, bp_event, 0);
243 return;
244 }
245 #endif
246 button_pressed(-1, -1, -1); /* cancel action */
247 }
248
249 /*****************************************************************************/
250 /* */
251 /* Functions for resize events and resize requests */
252 /* */
253 /*****************************************************************************/
254
255 /* 1) hard resizes (i.e. forcing the outer window to change size) */
256 /* I think these are not liked in the Xaw community */
257
cmd_MinWindow(void)258 void cmd_MinWindow(void) {
259 XSize_t w, h;
260 w = geo.min_width;
261 h = geo.min_height;
262 /* printf("Force resize to min (%d,%d)\n", w, h); */
263 Force_Resize(w, h);
264 }
265
cmd_PreferredWindow(void)266 void cmd_PreferredWindow(void) {
267 XSize_t w, h;
268 w = geo.preferred_width;
269 h = geo.preferred_height;
270 /* printf("Force resize to prf (%d,%d)\n", w, h); */
271 Force_Resize(w, h);
272 }
273
274 /* event handler function. This function is called by the Widget in response
275 to a request from us. In Xaw, this is a resize of the logical area, i.e.
276 of the virtual size of the tableau. */
277
resize_event(XSize_t w,XSize_t h)278 void resize_event(XSize_t w, XSize_t h) {
279 #ifdef LABER
280 printf("resize event to (%d,%d) called\n", w, h);
281 #endif
282 if (game.graphic)
283 cmd_ResetHints();
284 if (graphic.height == h && graphic.width == w)
285 return; /* no change of size */
286
287 /* in xlib, we must clear the new area by hand; there may be illegal data
288 left in the server. This applies to Xaw as well */
289 { XExposeEvent xev;
290 xev.count = -1;
291 if (game.graphic) {
292 if (graphic.height < h) {
293 /* window is greater now */
294 XClearArea(dpy, table, 0, graphic.height, graphic.width, h - graphic.height, True);
295 ++xev.count;
296 }
297 if (graphic.width < w) {
298 /* window is greater now */
299 XClearArea(dpy, table, graphic.width, 0, w - graphic.width, h, True);
300 ++xev.count;
301 }
302 if (xev.count >= 0) {
303 /* generate synthetic expose events for the new area */
304 /* this must be done before we possibly change the layout */
305 if (graphic.height < h) {
306 /* window is greater now */
307 xev.x = 0;
308 xev.y = graphic.height;
309 xev.width = graphic.width;
310 xev.height = h - graphic.height;
311 redraw_table(&xev);
312 --xev.count;
313 }
314 if (graphic.width < w) {
315 /* window is greater now */
316 xev.x = graphic.width;
317 xev.y = 0;
318 xev.width = w - graphic.width;
319 xev.height = h;
320 redraw_table(&xev);
321 }
322 }
323 }
324 }
325 graphic.height = h;
326 graphic.width = w;
327
328 if (!game.graphic)
329 return;
330 #ifdef useXlib
331 confirm.x = (graphic.width - confirm.w) / 2;
332 confirm.y = (graphic.height - confirm.h) / 2;
333 XMoveWindow(dpy, confirm.win, confirm.x, confirm.y);
334 #endif
335
336 if (graphic.autolayout) {
337 cmd_Layout(); /* change everything */
338 } else {
339 Pileindex i;
340 /* fix piles THIS IS WRONG FOR 2-ROW LAYOUTS!!!! FIX THIS! */
341 for (i = 0; i < rules.numslots; ++i)
342 geo.pg[XPATSLOT(i)].h = geo.h - geo.pg[XPATSLOT(i)].y;
343
344 for (i = FIRST_SLOT; i <= LAST_SLOT; ++i)
345 if (pile_resize(i))
346 draw_pileupdate(i, 0);
347 }
348
349 }
350