home *** CD-ROM | disk | FTP | other *** search
- /*
- * Spider
- *
- * (c) Copyright 1989, Donald R. Woods and Sun Microsystems, Inc.
- * (c) Copyright 1990, David Lemke and Network Computing Devices Inc.
- *
- * See copyright.h for the terms of the copyright.
- *
- * @(#)events.c 2.6 91/05/09
- *
- */
-
- /*
- * Spider event handlers
- */
-
- #include "defs.h"
- #include "globals.h"
-
- extern int cheat_count;
-
- static CardPtr current_card = CARDNULL;
- static CardList current_list = CARDLISTNULL;
-
- static CardList coords_to_list();
- static CardPtr coords_to_card();
- static Bool hit_deck();
- Bool write_confirmer();
- Bool newgame_confirmer();
- #ifdef XVIEW
- extern void show_play();
- #else
- extern Bool show_play_events();
- #endif
- #ifdef KITLESS
- static void handle_table_event();
- static void redraw_table();
- static void button_press();
- static void button_release();
- static void key_press();
- static void resize_event();
- static void do_expand();
- static void handle_message_event();
- #endif /* KITLESS */
-
- Bool usebell = False;
-
- #ifdef KITLESS
- /*
- * main event handling loop
- */
- event_loop()
- {
- XEvent xev;
-
- while (1) {
- XNextEvent(dpy, &xev);
- if (xev.xany.window == table) {
- handle_table_event(&xev);
- } else if (xev.xany.window == message_win) {
- handle_message_event(&xev);
- }
- if (restart) {
- shuffle_cards();
- }
- }
- }
-
- /*
- * event on table
- */
- static void
- handle_table_event(xev)
- XEvent *xev;
- {
- if (xev->xany.type == Expose) {
- redraw_table((XExposeEvent *)xev);
- } else if (xev->xany.type == ButtonPress) {
- button_press((XButtonPressedEvent *)xev);
- } else if (xev->xany.type == ButtonRelease) {
- button_release((XButtonReleasedEvent *)xev);
- current_list = CARDLISTNULL;
- } else if (xev->xany.type == KeyPress) {
- key_press((XKeyPressedEvent *)xev);
- } else if (xev->xany.type == ConfigureNotify) {
- resize_event((XConfigureEvent *)xev);
- }
- }
-
- static void
- handle_message_event(xev)
- XEvent *xev;
- {
- if (xev->xany.type == Expose) {
- show_message(NULL);
- }
- }
-
- /* KITLESS doesn't bother to check -- just clobbers existing file */
- Bool
- write_confirmer()
- {
- return True;
- }
-
- Bool
- newgame_confirmer()
- {
- return True;
- }
- #endif /* KITLESS */
-
-
- #ifndef KITLESS
- void
- #else /* KITLESS */
- static void
- #endif /* KITLESS */
- redraw_table(xev)
- XExposeEvent *xev;
- {
- static Bool last_was_zero = True; /* so at init time it paints */
-
- /*
- * this mess is to optimize the painting. a complex exposure
- * area could cause a card to have several damage areas. since
- * the entire card is painted when damaged, the following keeps
- * track of whether its been painted in the latest flurry of
- * exposures, and prevents it being painted multiple times.
- */
- if (last_was_zero) {
- draw_count++;
- last_was_zero = False;
- }
- if (xev->count == 0)
- last_was_zero = True;
-
- redraw_deck(xev->x, xev->y, xev->width, xev->height);
- redraw_card_piles(xev->x, xev->y, xev->width, xev->height);
- redraw_card_stacks(xev->x, xev->y, xev->width, xev->height);
- }
-
- /*
- * ignore y when getting list
- */
- static CardList
- coords_to_list(x, y)
- int x, y;
- {
- int i;
-
- if (y < STACK_LOC_Y) {
- for (i = 0; i < NUM_PILES; i++) {
- if ((x >= PILE_LOC_X(piles[i]->place)) &&
- (x <= (PILE_LOC_X(piles[i]->place) + CARD_WIDTH)))
- return (piles[i]);
- }
- return (CARDLISTNULL);
- } else {
- for (i = 0; i < NUM_STACKS; i++) {
- if ((x >= STACK_LOC_X(stack[i]->place)) &&
- (x <= (STACK_LOC_X(stack[i]->place) + CARD_WIDTH)))
- return (stack[i]);
- }
- return (CARDLISTNULL);
- }
- }
-
- static CardPtr
- coords_to_card(x, y)
- int x, y;
- {
- CardList list;
- CardPtr tmp;
-
- list = coords_to_list(x, y);
- if (list == CARDLISTNULL || IS_PILE(list))
- return (CARDNULL);
- tmp = list->cards;
- if (tmp == CARDNULL)
- return CARDNULL;
- while (tmp) {
- if (tmp->next) {
- if ((y <= tmp->next->y) && (y >= tmp->y)) {
- return (tmp);
- }
- } else {
- if ((y <= (tmp->y + CARD_HEIGHT)) &&
- (y >= tmp->y)) {
- return (tmp);
- }
- }
- tmp = tmp->next;
- }
- return CARDNULL;
- }
-
- static Bool
- hit_deck(x, y)
- int x, y;
- {
- return ((x <= (deck->x + CARD_WIDTH)) && (x >= deck->x) &&
- (y <= (deck->y + CARD_HEIGHT)) && (y >= deck->y));
- }
-
- #ifndef KITLESS
- void
- #else /* KITLESS */
- static void
- #endif /* KITLESS */
- button_press(xev)
- XButtonPressedEvent *xev;
- {
-
- if (hit_deck(xev->x, xev->y)) {
- current_list = deck;
- return;
- }
- current_card = coords_to_card(xev->x, xev->y);
- if (xev->button == Button2) {
- if (current_card == CARDNULL)
- return;
- /* ignore facedown cards */
- if (current_card->type != Faceup) {
- current_card = CARDNULL;
- current_list = coords_to_list(xev->x, xev->y);
- return;
- }
- #ifdef DEBUG
- if (xev->state & ShiftMask) {
- current_list = coords_to_list(xev->x, xev->y);
- return;
- }
- #endif /* DEBUG */
- if (!can_move(current_card)) {
- card_message("Can't move", current_card);
- spider_bell(dpy, 0);
- current_card = CARDNULL;
- }
- } else {
- current_card = CARDNULL;
- }
- current_list = coords_to_list(xev->x, xev->y);
- if (IS_PILE(current_list)) {
- if (current_list->cards) {
- show_message("Can't move removed cards.");
- spider_bell(dpy, 0);
- } else {
- show_full_suits();
- }
- current_list = CARDLISTNULL;
- } else if (current_list && current_list->cards == CARDNULL) {
- show_message("No cards to move.");
- current_list = CARDLISTNULL;
- }
- }
-
- #ifndef KITLESS
- void
- #else /* KITLESS */
- static void
- #endif /* KITLESS */
- button_release(xev)
- XButtonReleasedEvent *xev;
- {
- CardList list_hit;
- CardPtr tmp;
-
- if (current_list == CARDLISTNULL)
- return;
-
- if (hit_deck(xev->x, xev->y)) {
- if (current_list == deck) {
- if (deal_number == 0) {
- deal_cards();
- } else {
- deal_next_hand(True);
- }
- } else { /* no dropping on deck */
- show_message("Can't move cards to deck");
- spider_bell(dpy, 0);
- }
- return;
- }
-
- list_hit = coords_to_list(xev->x, xev->y);
- if (list_hit == CARDLISTNULL)
- return;
-
- if (current_card) {
- #ifdef DEBUG
- if (xev->state & ShiftMask) {
- move_to_list(current_card, list_hit, True);
- current_card = CARDNULL;
- return;
- }
- #endif
- if (list_hit == current_list) {
- best_list_move(list_hit, current_card);
- return;
- }
- if ((IS_PILE(list_hit))) {
- if((current_card->rank == King) &&
- (can_move(current_card)) &&
- (last_card(current_card->list)->rank == Ace)) {
- move_to_pile(current_card);
- } else {
- card_message("Can't remove", current_card);
- spider_bell(dpy, 0);
- }
- current_card = CARDNULL;
- return;
- }
- if (can_move_to(current_card, list_hit)) {
- move_to_list(current_card, list_hit, True);
- } else {
- card2_message("Can't move", current_card, "to",
- last_card(list_hit));
- spider_bell(dpy, 0);
- }
- current_card = CARDNULL;
- /* try best move if the mouse wasn't moved */
- } else if (list_hit == current_list) {
- best_list_move(list_hit, CARDNULL);
- } else {
- if (IS_PILE(list_hit)) {
- tmp = last_card(current_list);
- if (tmp->rank == Ace) {
- while (tmp && can_move(tmp)) {
- if (tmp->rank == King) {
- move_to_pile(tmp);
- return;
- }
- tmp = tmp->prev;
- }
- }
- card_message("Can't remove", tmp);
- spider_bell(dpy, 0);
- return;
- }
- tmp = current_list->cards;
- while (tmp) {
- if (can_move(tmp)) {
- if (can_move_to(tmp, list_hit)) {
- move_to_list(tmp, list_hit, True);
- return;
- }
- }
- tmp = tmp->next;
- }
- if (tmp)
- card_message("Can't move", tmp);
- else
- show_message("No movable cards");
- spider_bell(dpy, 0);
- }
- }
-
- #ifndef KITLESS
- void
- #else /* KITLESS */
- static void
- #endif /* KITLESS */
- key_press(xev)
- XKeyPressedEvent *xev;
- {
- char str[32];
- char buf[512];
- char *fname;
- int num;
- #ifdef KITLESS
- #define get_name_field(x) get_selection(x)
- #else
- extern char *get_name_field();
- #endif /* KITLESS */
-
- num = XLookupString(xev, str, 32, NULL, NULL);
- if (num == 0)
- return;
- switch (str[0]) {
- case 'f': /* find card */
- case 'F':
- fname = get_name_field();
- if (fname == NULL || strlen(fname) == 0) {
- show_message("Selection is unusable or unobtainable.");
- } else {
- locate(fname);
- }
- break;
- case 'l':
- case 'L':
- if ((fname = get_name_field()) == NULL) {
- show_message("Selection is unusable or unobtainable.");
- } else {
- read_file_or_selection(fname);
- }
- /* force everything to redraw */
- force_redraw();
- break;
- case 'w':
- case 'W':
- /* write to selection */
- if ((fname = get_name_field()) == NULL) {
- show_message("Selection is unusable or unobtainable.");
- } else {
- write_file(fname, write_confirmer);
- }
- break;
- case 's':
- case 'S':
- /* score */
- (void)sprintf(buf, "Current position scores %d out of 1000.",
- compute_score());
- show_message(buf);
- break;
- case 'a':
- case 'A':
- /* play again */
- (void)replay();
- init_cache(); /* reset move cache */
- break;
- case 'r':
- case 'R':
- /* show move log */
- #ifdef XVIEW
- show_play();
- #else
- show_play(0, 0, show_play_events, delay);
- #endif
- break;
- case 'n':
- case 'N':
- /* start over */
- if (newgame_confirmer()) {
- restart = True;
- clear_message();
- }
- break;
- case 'e':
- case 'E':
- do_expand();
- break;
- case 'd':
- case 'D':
- if (deal_number == 0) {
- deal_cards();
- } else {
- deal_next_hand(True);
- }
- /* deal next hand */
- break;
- case 'u':
- case 'U':
- undo();
- break;
- case 'v':
- case 'V':
- print_version();
- break;
- case 'Q':
- /* quit */
- exit(0);
- case '#':
- if (deal_number == 0) {
- show_message("Haven't dealt yet.");
- } else if (deal_number == 1) {
- sprintf(buf, "Initial deal; cheat count: %d",
- cheat_count);
- show_message(buf);
- } else {
- sprintf(buf, "Deal number %d of 5; cheat count: %d",
- deal_number - 1, cheat_count);
- show_message(buf);
- }
- break;
- case '?':
- if (deal_number == 0) {
- show_message("Haven't dealt yet.");
- } else {
- advise_best_move();
- }
- break;
- default:
- str[num] = '\0'; /* NULL terminate it */
- (void) sprintf(buf, "Unknown command: '%s'", str);
- show_message(buf);
- break;
- }
- }
-
- #ifdef KITLESS
- static void
- resize_event(xev)
- XConfigureEvent *xev;
- {
- int i;
-
- table_height = xev->height;
- table_width = xev->width;
-
- /* adjust message window */
- XMoveResizeWindow(dpy, message_win, 0, (table_height - 2 * TABLE_BW -
- (message_font->ascent + message_font->descent)),
- (table_width - 2 * TABLE_BW),
- (message_font->ascent + message_font->descent));
-
- /* fix stacks */
- for (i = 0; i < NUM_STACKS; i++) {
- if (stack[i])
- recompute_list_deltas(stack[i]);
- }
- /* exposure will repaint them */
- }
- #endif /* KITLESS */
-
- void
- print_version()
- {
- char buf[256];
-
- (void)sprintf(buf, "Spider version %s, last built: %s", version,
- build_date);
- show_message(buf);
- }
-
-
- static CardList
- get_list()
- {
- XEvent event;
- CardList list = CARDLISTNULL;
-
- if (XGrabPointer(dpy, table, False,
- ButtonPressMask | ButtonReleaseMask,
- GrabModeAsync, GrabModeAsync, table, None,
- CurrentTime) != GrabSuccess) {
- show_message("Unable to grab pointer.");
- return CARDLISTNULL;
- }
- while (1) {
- XNextEvent(dpy, &event);
-
- switch (event.type) {
- case ButtonRelease:
- if (event.xbutton.window == table) {
- list = coords_to_list(event.xbutton.x,
- event.xbutton.y);
- }
- XUngrabPointer(dpy, CurrentTime);
- return list;
- default:
- break;
- }
- }
- }
-
- #ifdef KITLESS
- static void
- #else /* KITLESS */
- void
- #endif /* KITLESS */
- do_expand()
- {
- CardList list;
-
- show_message("Click over the column whose contents you want to see.");
- #ifdef XAW
- flush_message();
- #endif /* XAW */
- list = get_list();
- if (list && !IS_PILE(list)) {
- expand(list);
- } else {
- show_message("That wasn't over a column!");
- }
- }
-
- #ifdef KITLESS
- Bool
- show_play_events()
- {
- XEvent xev;
-
- while (XPending(dpy)) {
- XNextEvent(dpy, &xev);
-
- /* any key or button will stop it */
- switch(xev.type) {
- default:
- if (xev.xany.window == table) {
- handle_table_event(&xev);
- } else if (xev.xany.window == message_win) {
- handle_message_event(&xev);
- }
- break;
-
- case KeyPress:
- case KeyRelease:
- case ButtonPress:
- case ButtonRelease:
- return False;
- }
- }
- return True;
- }
- #endif /* KITLESS */
-
- spider_bell(d, level)
- Display *d;
- int level;
- {
- if (usebell)
- XBell(d, level);
- }
-