diff --git a/aisleriot/board-noclutter.c b/aisleriot/board-noclutter.c index 8854263..295121e 100644 --- a/aisleriot/board-noclutter.c +++ b/aisleriot/board-noclutter.c @@ -24,6 +24,7 @@ #include +#include #include #include @@ -1469,6 +1470,69 @@ aisleriot_board_move_selected_cards_to_slot (AisleriotBoard *board, return moved; } +#if GTK_CHECK_VERSION (2, 12, 0) && !defined(HAVE_HILDON) + +static const char * +get_slot_description (AisleriotSlotType type) +{ + const char *text = NULL; + + switch (type) { + case AISLERIOT_SLOT_UNKNOWN: + text = NULL; + break; + case AISLERIOT_SLOT_FOUNDATION: + text = _("Foundation slot"); + break; + case AISLERIOT_SLOT_RESERVE: + text = _("Reserve slot"); + break; + case AISLERIOT_SLOT_STOCK: + text = _("Stock slot"); + break; + case AISLERIOT_SLOT_TABLEAU: + text = _("Tableau slot"); + break; + case AISLERIOT_SLOT_WASTE: + text = _("Waste slot"); + break; + } + + return text; +} + +static gboolean +aisleriot_board_query_tooltip_cb (GtkWidget *widget, + int x, + int y, + gboolean keyboard_mode, + GtkTooltip *tooltip, + AisleriotBoard *board) +{ + Slot *slot; + int cardid; + char *card_name, *text; + + get_slot_and_card_from_point (board, x, y, &slot, &cardid); + if (!slot || slot->type == AISLERIOT_SLOT_UNKNOWN) + return FALSE; + + if (cardid < 0 || CARD_GET_FACE_DOWN (CARD (slot->cards->data[cardid]))) { + gtk_tooltip_set_text (tooltip, get_slot_description (slot->type)); + return TRUE; + } + + card_name = games_card_get_localised_name (CARD (slot->cards->data[cardid])); + text = g_strdup_printf (_("%s on %s"), card_name, get_slot_description (slot->type)); + gtk_tooltip_set_text (tooltip, text); + g_free (card_name); + g_free (text); + + return TRUE; +} + +#endif /* GTK >= 2.12.0 && !HAVE_HILDON */ + /* Keynav */ #ifdef ENABLE_KEYNAV @@ -3311,6 +3375,12 @@ aisleriot_board_init (AisleriotBoard *board) #ifdef HAVE_MAEMO gtk_widget_tap_and_hold_setup (widget, NULL, NULL, GTK_TAP_AND_HOLD_PASS_PRESS); #endif + +#if GTK_CHECK_VERSION (2, 12, 0) && !defined(HAVE_HILDON) + gtk_widget_set_has_tooltip (widget, TRUE); + g_signal_connect (widget, "query-tooltip", + G_CALLBACK (aisleriot_board_query_tooltip_cb), board); +#endif } static GObject * diff --git a/aisleriot/game.c b/aisleriot/game.c index 7245c25..38e2c0e 100644 --- a/aisleriot/game.c +++ b/aisleriot/game.c @@ -569,6 +569,8 @@ cscmi_add_slot (SCM slot_data) gboolean expanded_down = FALSE; gboolean expanded_right = FALSE; int expansion_depth = 0; + AisleriotSlotType type = AISLERIOT_SLOT_UNKNOWN; + SCM slot_placement, slot_type; if (game->state > GAME_BEGIN) { return scm_throw (scm_from_locale_symbol ("game-started"), @@ -577,30 +579,53 @@ cscmi_add_slot (SCM slot_data) } #ifdef HAVE_GUILE_1_8 -#define CHECK_EXPANSION(string,object) (scm_is_true (scm_equal_p (scm_from_locale_symbol (string), object))) +#define EQUALS_SYMBOL(string,object) (scm_is_true (scm_equal_p (scm_from_locale_symbol (string), object))) #else -#define CHECK_EXPANSION(string,object) (!strcmp (string, SCM_CHARS (object))) +#define EQUALS_SYMBOL(string,object) (!strcmp (string, SCM_CHARS (object))) #endif - if (CHECK_EXPANSION ("expanded", SCM_CAR (SCM_CADDR (slot_data)))) { + slot_placement = SCM_CADDR (slot_data); + if (EQUALS_SYMBOL ("expanded", SCM_CAR (slot_placement))) { expanded_down = TRUE; - } else if (CHECK_EXPANSION ("expanded-right", SCM_CAR (SCM_CADDR (slot_data)))) { + } else if (EQUALS_SYMBOL ("expanded-right", SCM_CAR (slot_placement))) { expanded_right = TRUE; - } else if (CHECK_EXPANSION ("partially-expanded", SCM_CAR (SCM_CADDR (slot_data)))) { + } else if (EQUALS_SYMBOL ("partially-expanded", SCM_CAR (slot_placement))) { expanded_down = TRUE; - expansion_depth = scm_to_int (SCM_CADDR (SCM_CADDR (slot_data))); - } else if (CHECK_EXPANSION ("partially-expanded-right", SCM_CAR (SCM_CADDR (slot_data)))) { + expansion_depth = scm_to_int (SCM_CADDR (slot_placement)); + } else if (EQUALS_SYMBOL ("partially-expanded-right", SCM_CAR (slot_placement))) { expanded_right = TRUE; - expansion_depth = scm_to_int (SCM_CADDR (SCM_CADDR (slot_data))); + expansion_depth = scm_to_int (SCM_CADDR (slot_placement)); } -#undef CHECK_EXPANSION + /* 3rd argument is the slot type (optionally) */ + slot_type = SCM_CDDDR (slot_data); + if (slot_type != SCM_EOL) { + if (EQUALS_SYMBOL ("foundation", SCM_CAR (slot_type))) { + type = AISLERIOT_SLOT_FOUNDATION; + } else if (EQUALS_SYMBOL ("reserve", SCM_CAR (slot_type))) { + type = AISLERIOT_SLOT_RESERVE; + } else if (EQUALS_SYMBOL ("stock", SCM_CAR (slot_type))) { + type = AISLERIOT_SLOT_STOCK; + } else if (EQUALS_SYMBOL ("tableau", SCM_CAR (slot_type))) { + type = AISLERIOT_SLOT_TABLEAU; + } else if (EQUALS_SYMBOL ("waste", SCM_CAR (slot_type))) { + type = AISLERIOT_SLOT_WASTE; + } + } + +#undef EQUALS_SYMBOL + + { + static const char *types[] = { "unknown", "foundation", "reserve", "stock", "tableau", "waste" }; + g_print ("add-slot ID %d type %s\n", scm_to_int (SCM_CAR (slot_data)), types[type]); + } /* create and initialize slot */ slot = g_slice_new0 (Slot); g_ptr_array_add (game->slots, slot); slot->id = scm_to_int (SCM_CAR (slot_data)); + slot->type = type; slot->cards = g_byte_array_sized_new (SLOT_CARDS_N_PREALLOC); slot->exposed = 0; diff --git a/aisleriot/game.h b/aisleriot/game.h index 541e34a..ba63bfa 100644 --- a/aisleriot/game.h +++ b/aisleriot/game.h @@ -29,10 +29,20 @@ G_BEGIN_DECLS +typedef enum { + AISLERIOT_SLOT_UNKNOWN, + AISLERIOT_SLOT_FOUNDATION, + AISLERIOT_SLOT_RESERVE, + AISLERIOT_SLOT_STOCK, + AISLERIOT_SLOT_TABLEAU, + AISLERIOT_SLOT_WASTE +} AisleriotSlotType; + /* A slot */ typedef struct { int id; + AisleriotSlotType type; GByteArray *cards; #ifdef HAVE_CLUTTER diff --git a/aisleriot/rules/freecell.scm b/aisleriot/rules/freecell.scm index 46c23d9..fbc4b93 100644 --- a/aisleriot/rules/freecell.scm +++ b/aisleriot/rules/freecell.scm @@ -324,34 +324,34 @@ ;; set up the board ; freecells - (add-normal-slot '()) ; 0 + (add-normal-slot '() 'reserve) ; 0 (set! HORIZPOS (- HORIZPOS (/ 1 24))) - (add-normal-slot '()) ; 1 + (add-normal-slot '() 'reserve) ; 1 (set! HORIZPOS (- HORIZPOS (/ 1 24))) - (add-normal-slot '()) ; 2 + (add-normal-slot '() 'reserve) ; 2 (set! HORIZPOS (- HORIZPOS (/ 1 24))) - (add-normal-slot '()) ; 3 + (add-normal-slot '() 'reserve) ; 3 (set! HORIZPOS (+ HORIZPOS 0.25)) ; homecells - (add-normal-slot '()) ; 4 + (add-normal-slot '() 'foundation) ; 4 (set! HORIZPOS (- HORIZPOS (/ 1 24))) - (add-normal-slot '()) ; 5 + (add-normal-slot '() 'foundation) ; 5 (set! HORIZPOS (- HORIZPOS (/ 1 24))) - (add-normal-slot '()) ; 6 + (add-normal-slot '() 'foundation) ; 6 (set! HORIZPOS (- HORIZPOS (/ 1 24))) - (add-normal-slot '()) ; 7 + (add-normal-slot '() 'foundation) ; 7 (add-carriage-return-slot) ; fields - (add-extended-slot '() down) ; 8 - (add-extended-slot '() down) ; 9 - (add-extended-slot '() down) ; 10 - (add-extended-slot '() down) ; 11 - (add-extended-slot '() down) ; 12 - (add-extended-slot '() down) ; 13 - (add-extended-slot '() down) ; 14 - (add-extended-slot '() down) ; 15 + (add-extended-slot '() down 'tableau) ; 8 + (add-extended-slot '() down 'tableau) ; 9 + (add-extended-slot '() down 'tableau) ; 10 + (add-extended-slot '() down 'tableau) ; 11 + (add-extended-slot '() down 'tableau) ; 12 + (add-extended-slot '() down 'tableau) ; 13 + (add-extended-slot '() down 'tableau) ; 14 + (add-extended-slot '() down 'tableau) ; 15 (add-blank-slot) (deal-initial-setup) diff --git a/aisleriot/rules/klondike.scm b/aisleriot/rules/klondike.scm index 425c99b..11bb9ea 100644 --- a/aisleriot/rules/klondike.scm +++ b/aisleriot/rules/klondike.scm @@ -37,25 +37,25 @@ (make-standard-deck) (shuffle-deck) - (add-normal-slot DECK) + (add-normal-slot DECK 'stock) (if deal-three - (add-partially-extended-slot '() right 3) - (add-normal-slot '())) + (add-partially-extended-slot '() right 3 'waste) + (add-normal-slot '() 'waste)) (add-blank-slot) - (add-normal-slot '()) - (add-normal-slot '()) - (add-normal-slot '()) - (add-normal-slot '()) + (add-normal-slot '() 'foundation) + (add-normal-slot '() 'foundation) + (add-normal-slot '() 'foundation) + (add-normal-slot '() 'foundation) (add-carriage-return-slot) - (add-extended-slot '() down) - (add-extended-slot '() down) - (add-extended-slot '() down) - (add-extended-slot '() down) - (add-extended-slot '() down) - (add-extended-slot '() down) - (add-extended-slot '() down) + (add-extended-slot '() down 'tableau) + (add-extended-slot '() down 'tableau) + (add-extended-slot '() down 'tableau) + (add-extended-slot '() down 'tableau) + (add-extended-slot '() down 'tableau) + (add-extended-slot '() down 'tableau) + (add-extended-slot '() down 'tableau) (deal-tableau tableau) diff --git a/aisleriot/rules/spider.scm b/aisleriot/rules/spider.scm index 7fd1612..003f573 100644 --- a/aisleriot/rules/spider.scm +++ b/aisleriot/rules/spider.scm @@ -53,27 +53,27 @@ (shuffle-deck) ;set up the board - (add-normal-slot DECK) + (add-normal-slot DECK 'stock) (add-blank-slot) - (add-normal-slot '()) - (add-normal-slot '()) - (add-normal-slot '()) - (add-normal-slot '()) - (add-normal-slot '()) - (add-normal-slot '()) - (add-normal-slot '()) - (add-normal-slot '()) + (add-normal-slot '() 'foundation) + (add-normal-slot '() 'foundation) + (add-normal-slot '() 'foundation) + (add-normal-slot '() 'foundation) + (add-normal-slot '() 'foundation) + (add-normal-slot '() 'foundation) + (add-normal-slot '() 'foundation) + (add-normal-slot '() 'foundation) (add-carriage-return-slot) - (add-extended-slot '() down) - (add-extended-slot '() down) - (add-extended-slot '() down) - (add-extended-slot '() down) - (add-extended-slot '() down) - (add-extended-slot '() down) - (add-extended-slot '() down) - (add-extended-slot '() down) - (add-extended-slot '() down) - (add-extended-slot '() down) + (add-extended-slot '() down 'tableau) + (add-extended-slot '() down 'tableau) + (add-extended-slot '() down 'tableau) + (add-extended-slot '() down 'tableau) + (add-extended-slot '() down 'tableau) + (add-extended-slot '() down 'tableau) + (add-extended-slot '() down 'tableau) + (add-extended-slot '() down 'tableau) + (add-extended-slot '() down 'tableau) + (add-extended-slot '() down 'tableau) (deal-initial-setup) (give-status-message) diff --git a/aisleriot/sol.scm b/aisleriot/sol.scm index b60f9b2..e9139e8 100644 --- a/aisleriot/sol.scm +++ b/aisleriot/sol.scm @@ -162,30 +162,30 @@ ; The real slots come in three varieties: ; A slot in which only the topmost card is visible: -(define (add-normal-slot cards) - (add-slot (set-tag! (new-slot cards - (list 'normal (get-and-increment-position)))))) +(define (add-normal-slot cards . type) + (add-slot (set-tag! (new-slot cards + (list 'normal (get-and-increment-position)) type)))) ; A slot in which all the cards are visible, arranged as an overlapped pile: ; (either proceeding to the right or down). -(define (add-extended-slot cards direction) +(define (add-extended-slot cards direction . type) (if (= right direction) (add-slot (set-tag! (new-slot cards (list 'expanded-right - (get-and-increment-position))))) + (get-and-increment-position)) type))) (add-slot (set-tag! (new-slot cards (list 'expanded - (get-and-increment-position))))))) + (get-and-increment-position)) type))))) ; A slot in only the n topmost cards are visible: -(define (add-partially-extended-slot cards direction n) +(define (add-partially-extended-slot cards direction n . type) (if (= right direction) (add-slot (set-tag! (new-slot cards (list 'partially-expanded-right - (get-and-increment-position) n)))) + (get-and-increment-position) n) type))) (add-slot (set-tag! (new-slot cards (list 'partially-expanded - (get-and-increment-position) n)))))) + (get-and-increment-position) n) type))))) ; Cards may be dealt off one slot (usually the one containing the deck) ; and onto a list of other slots using these procedures: @@ -516,8 +516,8 @@ (vector-set! deck ref2 (vector-ref deck ref1)) (shuffle-deck-helper deck (cons val-at-ref2 result) (+ ref1 1) (- len 1))))) -(define (new-slot deck placement) - (list #f deck placement)) +(define (new-slot deck placement type) + (list #f deck placement (if (null? type) 'unknown (car type)))) (define (set-tag! slot) (set! SLOTS (+ 1 SLOTS)) diff --git a/libgames-support/games-card.c b/libgames-support/games-card.c index 3877a60..1d16298 100644 --- a/libgames-support/games-card.c +++ b/libgames-support/games-card.c @@ -248,3 +248,94 @@ _games_card_to_index (Card card) return card_id; } + +/* FIXMEchpe compactify & constify */ +static const char *card_names[] = { +"ace of clubs", +"two of clubs", +"three of clubs", +"four of clubs", +"five of clubs", +"six of clubs", +"seven of clubs", +"eight of clubs", +"nine of clubs", +"ten of clubs", +"jack of clubs", +"queen of clubs", +"king of clubs", +"ace of hearts", +"two of hearts", +"three of hearts", +"four of hearts", +"five of hearts", +"six of hearts", +"seven of hearts", +"eight of hearts", +"nine of hearts", +"ten of hearts", +"jack of hearts", +"queen of hearts", +"king of hearts", +"ace of diamonds", +"two of diamonds", +"three of diamonds", +"four of diamonds", +"five of diamonds", +"six of diamonds", +"seven of diamonds", +"eight of diamonds", +"nine of diamonds", +"ten of diamonds", +"jack of diamonds", +"queen of diamonds", +"king of diamonds", +"ace of spades", +"two of spades", +"three of spades", +"four of spades", +"five of spades", +"six of spades", +"seven of spades", +"eight of spades", +"nine of spades", +"ten of spades", +"jack of spades", +"queen of spades", +"king of spades" +}; +#define GAMES_CARD_ID(suit, rank) ((13*(suit)) + ((rank-1)%13)) + +/** + * games_card_get_localized_name: + * @card: + * + * Returns: a localised name for @card, e.g. "Face-down card" or + * "9 of clubs", etc. + */ +char * +games_card_get_localised_name (Card card) +{ + guint rank, suit; + + if (CARD_GET_FACE_DOWN (card)) { + return g_strdup (_("face-down card")); + }; + + rank = CARD_GET_RANK (card); + suit = CARD_GET_SUIT (card); + + if (G_UNLIKELY (rank == 0)) { + /* A joker */ + if (suit == GAMES_CARDS_CLUBS || + suit == GAMES_CARDS_SPADES) { + /* A black joker. */ + return g_strdup (_("black joker")); + } else { + /* A red joker. */ + return g_strdup (_("red joker")); + } + } + + return g_strdup (_(card_names[GAMES_CARD_ID(suit, rank)])); +} diff --git a/libgames-support/games-card.h b/libgames-support/games-card.h index 5945183..0deb249 100644 --- a/libgames-support/games-card.h +++ b/libgames-support/games-card.h @@ -85,8 +85,8 @@ typedef enum { /* Suites */ GAMES_CARDS_CLUBS = 0, - GAMES_CARDS_DIAMONDS = 2, - GAMES_CARDS_HEARTS = 1, + GAMES_CARDS_DIAMONDS = 1, + GAMES_CARDS_HEARTS = 2, GAMES_CARDS_SPADES = 3, /* Jokers */ @@ -116,6 +116,8 @@ char * games_card_get_name_by_id (int card_id); const char * games_card_get_localised_rank_symbol (int rank); +char * games_card_get_localised_name (Card card); + G_END_DECLS #endif /* !GAMES_CARD_H */