/*****************************************************************************/ /* */ /* */ /* X patience version 2 -- module X-events.c */ /* */ /* Event handlers for the X interface */ /* written by Heiko Eissfeldt and Michael Bischoff */ /* see COPYRIGHT.xpat2 for Copyright details */ /* */ /* */ /*****************************************************************************/ #include "X-pat.h" /* #define LABER */ Display *dpy; int screen; unsigned long blackpixel; unsigned long whitepixel; GC blackgc; GC whitegc; /* flush event queue */ void flush_display(void) { XSync(dpy, 0); /* text first! */ } #ifdef useXlib static int intersect(int x1, int w1, int x2, int w2) { if (x1 < x2) return x1+w1 > x2; else return x2+w2 > x1; } #endif /* events for Xlib AND Xaw interface */ /* event entry points are: key_press, button_press, button_release, mouse_motion (only called with button 3 pressed) redraw_table */ void key_press(XKeyPressedEvent *xev) { char str[32]; int num; #define get_name_field() get_selection() num = XLookupString(xev, str, 31, NULL, NULL); if (num == 0) return; str[num] = '\0'; /* NULL to terminate it */ show_exposed_card(False); key_pressed(str); } /* SPEEDUP does not work yet */ #ifdef SPEEDUP static int pile_is_drawn[MAXPILES] = { 0, 0 }; static int buttons_are_drawn = 0; #endif extern int table_clear; void redraw_table(XExposeEvent *xev) { int i; table_clear = 0; #ifdef useXlib if (intersect(0, graphic.buttons_height, xev->y, xev->height)) #ifdef SPEEDUP if (!buttons_are_drawn++) #endif redraw_buttons(xev->x, xev->y, xev->width, xev->height, table, button.num, button.b); if (intersect(graphic.buttons_height, graphic.message_height, xev->y, xev->height)) show_message(NULL); if (xev->count && xev->y + xev->height < graphic.yoff) /* else may miss the last event */ return; #endif #ifdef LABER printf("request for expose %d,%d of size %d,%d, cnt %d\n", xev->x, xev->y, xev->width, xev->height, xev->count); /* printf("height of 0=%d, 8=%d\n", p.geo[0], p.geo[8].h); */ #endif for (i = 0; i < game.numpiles; ++i) { struct pilegeometry *p; #ifdef SPEEDUP if (pile_is_drawn[i]++) continue; #endif p = geo.pg + i; if (NOT_DISPLAYED(p) || xev->x >= p->x + p->w || xev->x + xev->width <= p->x || xev->y >= p->y + p->h || xev->y + xev->height <= p->y) continue; /* this pile is not affected */ #ifdef LABER printf("request for update pile %d of pos %d,%d, size %d,%d\n", i, p->x, p->y, p->w, p->h); #endif draw_pileupdate(i, 0); } if (!xev->count) { show_arrow(2); /* Update hint arrow */ } #ifdef LABER if (!xev->count) printf(" => last expose-table call\n"); #endif #ifdef SPEEDUP if (xev->count) return; /* was last event, unmark piles */ for (i = 0; i < MAXPILES; ++i) pile_is_drawn[i] = 0; buttons_are_drawn = 0; #endif } /* the pointer is somewhere in the area of pile i */ /* check, if a card has to be exposed */ static void expose_card(Pileindex i, int x, int y) { struct pilegeometry *p; Cardindex ind; if (EMPTY(i)) return; p = geo.pg + i; #if 0 ind = game.ind[i]; while (ind != INDEX_OF_LAST_CARD(i) && y >= p->y + graphic.cardy[ind+1]) ++ind; #else ind = FindCardOfMousePos(i, x, y); #endif if (ind == INDEX_OF_LAST_CARD(i)) /* the most bottom card don't has to */ ind = -1; /* be put on foreground */ if (graphic.zoomed_card != ind) { /* change of state */ show_exposed_card(False); /* hide it */ /* graphic.zoomed_card is now -1 */ if (ind >= 0) { graphic.zoomed_card = ind; show_exposed_card(True); } } } void mouse_motion(XPointerMovedEvent *xev) { Pileindex i; /* find new pile */ for (i = FIRST_SLOT; i <= LAST_SLOT; ++i) { struct pilegeometry *p; p = geo.pg + i; if (xev->x >= p->x && xev->x < p->x + p->w && xev->y >= p->y && xev->y < p->y + p->h) { /* yeah, a slot is hit */ /* find out which card is the target */ expose_card(i, xev->x - p->x, xev->y - p->y); return; } } /* pointer moved out of scope: */ show_exposed_card(False); } void button_release(XButtonPressedEvent *xev) { show_exposed_card(False); } void button_press(XButtonPressedEvent *xev) { Pileindex i; show_exposed_card(False); #ifdef useXlib { void (*func)(void); func = check_button_list(button.b, button.num, xev); /* check for hit button */ if (func) { (*func)(); return; } } #endif for (i = 0; i < game.numpiles; ++i) { struct pilegeometry *p; p = geo.pg + i; if (NOT_DISPLAYED(p)) continue; if (xev->x >= p->x && xev->x < p->x + p->w && xev->y >= p->y && xev->y < p->y + p->h) { Cardindex cardi; #if 0 if EMPTY(i) cardi = -1; else { cardi = INDEX_OF_LAST_CARD(i); if (game.piletype[i] == Slot) /* possibly a different card */ while (cardi != INDEX_OF_FIRST_CARD(i) && graphic.cardy[cardi] > xev->y - graphic.pile[i].y) --cardi; } #else cardi = FindCardOfMousePos(i, xev->x - p->x, xev->y - p->y); if (cardi == -2) /* below := lowest */ cardi = INDEX_OF_LAST_CARD(i); #endif switch (xev->button) { case Button1: /* quick move */ button_pressed(i, cardi, 1); break; case Button2: /* select / deselect */ button_pressed(i, cardi, 2); break; case Button3: #ifdef BUTTON_3_DRAGS_CARD button_pressed(i, cardi, 3); #else #ifndef useXview if (game.piletype[i] == Slot) expose_card(i, xev->x - p->x, xev->y - p->y); #else if (game.piletype[i] == Slot && cardi >= 0) { expose_card(i, xev->x - p->x, xev->y - p->y); } else { menu_show(cmenu, canvas, bp_event, 0); return; } #endif break; #endif } return; } } #ifdef useXview if (xev->button == Button3) { menu_show(cmenu, canvas, bp_event, 0); return; } #endif button_pressed(-1, -1, -1); /* cancel action */ } /*****************************************************************************/ /* */ /* Functions for resize events and resize requests */ /* */ /*****************************************************************************/ /* 1) hard resizes (i.e. forcing the outer window to change size) */ /* I think these are not liked in the Xaw community */ void cmd_MinWindow(void) { XSize_t w, h; w = geo.min_width; h = geo.min_height; /* printf("Force resize to min (%d,%d)\n", w, h); */ Force_Resize(w, h); } void cmd_PreferredWindow(void) { XSize_t w, h; w = geo.preferred_width; h = geo.preferred_height; /* printf("Force resize to prf (%d,%d)\n", w, h); */ Force_Resize(w, h); } /* event handler function. This function is called by the Widget in response to a request from us. In Xaw, this is a resize of the logical area, i.e. of the virtual size of the tableau. */ void resize_event(XSize_t w, XSize_t h) { #ifdef LABER printf("resize event to (%d,%d) called\n", w, h); #endif if (game.graphic) cmd_ResetHints(); if (graphic.height == h && graphic.width == w) return; /* no change of size */ /* in xlib, we must clear the new area by hand; there may be illegal data left in the server. This applies to Xaw as well */ { XExposeEvent xev; xev.count = -1; if (game.graphic) { if (graphic.height < h) { /* window is greater now */ XClearArea(dpy, table, 0, graphic.height, graphic.width, h - graphic.height, True); ++xev.count; } if (graphic.width < w) { /* window is greater now */ XClearArea(dpy, table, graphic.width, 0, w - graphic.width, h, True); ++xev.count; } if (xev.count >= 0) { /* generate synthetic expose events for the new area */ /* this must be done before we possibly change the layout */ if (graphic.height < h) { /* window is greater now */ xev.x = 0; xev.y = graphic.height; xev.width = graphic.width; xev.height = h - graphic.height; redraw_table(&xev); --xev.count; } if (graphic.width < w) { /* window is greater now */ xev.x = graphic.width; xev.y = 0; xev.width = w - graphic.width; xev.height = h; redraw_table(&xev); } } } } graphic.height = h; graphic.width = w; if (!game.graphic) return; #ifdef useXlib confirm.x = (graphic.width - confirm.w) / 2; confirm.y = (graphic.height - confirm.h) / 2; XMoveWindow(dpy, confirm.win, confirm.x, confirm.y); #endif if (graphic.autolayout) { cmd_Layout(); /* change everything */ } else { Pileindex i; /* fix piles THIS IS WRONG FOR 2-ROW LAYOUTS!!!! FIX THIS! */ for (i = 0; i < rules.numslots; ++i) geo.pg[XPATSLOT(i)].h = geo.h - geo.pg[XPATSLOT(i)].y; for (i = FIRST_SLOT; i <= LAST_SLOT; ++i) if (pile_resize(i)) draw_pileupdate(i, 0); } }