[gnome-games] gnotravex: Tidy up the code
- From: Robert Ancell <rancell src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gnome-games] gnotravex: Tidy up the code
- Date: Mon, 12 Jul 2010 01:27:05 +0000 (UTC)
commit 361007edae4ee2da3dc52f71629e333c383ef65c
Author: Robert Ancell <robert ancell gmail com>
Date: Mon Jul 12 11:26:05 2010 +1000
gnotravex: Tidy up the code
gnotravex/gnotravex.c | 2110 +++++++++++++++++++++++--------------------------
1 files changed, 1007 insertions(+), 1103 deletions(-)
---
diff --git a/gnotravex/gnotravex.c b/gnotravex/gnotravex.c
index 48196d1..a4a53ab 100644
--- a/gnotravex/gnotravex.c
+++ b/gnotravex/gnotravex.c
@@ -1,9 +1,9 @@
/* -*- mode:C; indent-tabs-mode: nil; tab-width: 8; c-basic-offset: 2; -*- */
-/*
+/*
* Gnome Tetravex: Tetravex clone
* Written by Lars Rydlinge <lars rydlinge hig se>
- *
+ *
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
@@ -20,16 +20,13 @@
*/
#include <config.h>
-
#include <string.h>
#include <math.h>
#include <time.h>
#include <stdlib.h>
-
#include <glib/gi18n.h>
#include <gtk/gtk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
-
#include <libgames-support/games-clock.h>
#include <libgames-support/games-conf.h>
#include <libgames-support/games-gtk-compat.h>
@@ -48,88 +45,83 @@
#define APPNAME "gnotravex"
#define APPNAME_LONG N_("Tetravex")
-/* This is based on the point where the numbers become unreadable on my
- * screen at 3x3. - Callum */
-#define MINIMUM_TILE_SIZE 40
-
#define RELEASE 4
#define PRESS 3
#define MOVING 2
#define UNUSED 1
#define USED 0
+#define LONG_COUNT 15
+#define SHORT_COUNT 5
+#define DELAY 10
+
#define KEY_GRID_SIZE "grid_size"
#define KEY_CLICK_MOVE "click_to_move"
#define DEFAULT_WIDTH 320
#define DEFAULT_HEIGHT 240
-static const char *translatable_number[10] = {
- /* Translators: in-game numbers, replaceable with single-character local ideograms */
- NC_("number", "0"),
- NC_("number", "1"),
- NC_("number", "2"),
- NC_("number", "3"),
- NC_("number", "4"),
- NC_("number", "5"),
- NC_("number", "6"),
- NC_("number", "7"),
- NC_("number", "8"),
- NC_("number", "9")
-};
-
-static GtkWidget *window;
-static GtkWidget *statusbar;
-static GtkWidget *space;
-static GtkWidget *timer;
-static GdkGC *bg_gc;
-
-static const GamesScoresCategory scorecats[] = {
- { "2x2", N_("2\303\2272") },
- { "3x3", N_("3\303\2273") },
- { "4x4", N_("4\303\2274") },
- { "5x5", N_("5\303\2275") },
- { "6x6", N_("6\303\2276") }
-};
-
-static GamesScores *highscores;
-
-static int xborder;
-static int yborder;
-static int gap;
+/* The sector of a tile to mark quads with */
+#define NORTH 0
+#define SOUTH 1
+#define EAST 2
+#define WEST 3
-static GdkPixmap *buffer = NULL;
+#define HIGHLIGHT 0
+#define BASE 1
+#define SHADOW 2
+#define TEXT 3
-typedef struct _tile {
+typedef struct
+{
gint n, w, e, s;
gint status;
-} tile;
-
-static tile tiles[9][18];
-static tile orig_tiles[9][9];
+} Tile;
-typedef struct _mover {
+typedef struct
+{
GdkWindow *window;
GdkPixmap *pixmap;
- tile heldtile;
+ Tile heldtile;
gint xstart, ystart;
gint xend, yend;
gint xoff, yoff;
gint x, y;
} Mover;
+typedef enum
+{
+ GAME_OVER,
+ PAUSED,
+ PLAYING,
+} GameState;
+
+static GtkWidget *window = NULL;
+static GtkWidget *statusbar = NULL;
+static GtkWidget *space = NULL;
+static GtkWidget *timer = NULL;
+static GdkGC *bg_gc = NULL;
+static GdkPixmap *background_pixmap = NULL;
+static GamesScores *highscores = NULL;
+static gint xborder = 0;
+static gint yborder = 0;
+static gint gap = 0;
+static GdkPixmap *buffer = NULL;
+static Tile tiles[9][18];
+static Tile orig_tiles[9][9];
static GdkWindowAttr windowattrib;
static Mover mousemover;
static Mover automover;
-
-enum {
- gameover,
- paused,
- playing,
+static const GamesScoresCategory scorecats[] = {
+ { "2x2", N_("2\303\2272") },
+ { "3x3", N_("3\303\2273") },
+ { "4x4", N_("4\303\2274") },
+ { "5x5", N_("5\303\2275") },
+ { "6x6", N_("6\303\2276") }
};
static gint size = -1;
-static gint game_state = gameover;
+static GameState game_state = GAME_OVER;
static gint have_been_hinted = 0;
static gint solve_me = 0;
static gint moving = 0;
@@ -140,22 +132,16 @@ static gint tile_size = 0;
static gdouble tile_border_size = 3.0;
static gdouble arrow_border_size = 1.5;
static gboolean click_to_move = FALSE;
+static gint button_down = 0;
+
+static gint animcount = 0;
+static gboolean swapanim = FALSE;
+static gint move_src_x = 0, move_src_y = 0, move_dest_x = 0, move_dest_y = 0;
/* The vertices used in the tiles/sockets. These are built using gui_build_vertices() */
static gdouble vertices[27][2];
static gboolean rebuild_vertices = TRUE;
-/* The sector of a tile to mark quads with */
-#define NORTH 0
-#define SOUTH 1
-#define EAST 2
-#define WEST 3
-
-#define HIGHLIGHT 0
-#define BASE 1
-#define SHADOW 2
-#define TEXT 3
-
/* The faces used to build a socket */
static int socket_faces[4][7] = {
{NORTH, SHADOW, 4, 0, 1, 18, 17},
@@ -209,123 +195,6 @@ static gdouble tile_colours[11][4][4] = {
/* The colour to use when drawing the sockets */
#define SOCKET_COLOUR 10
-void make_buffer (GtkWidget *);
-void create_window (void);
-GtkWidget *create_menu (GtkUIManager *);
-void init_window_attrib (void);
-GtkWidget *create_statusbar (void);
-GdkPixmap *default_background_pixmap;
-
-gboolean expose_space (GtkWidget *, GdkEventExpose *);
-gint button_press_space (GtkWidget *, GdkEventButton *);
-gint button_release_space (GtkWidget *, GdkEventButton *);
-gint button_motion_space (GtkWidget *, GdkEventButton *);
-
-void gui_build_vertices (void);
-void gui_draw_faces (cairo_t * context, gint xadd, gint yadd, int quads[][7],
- int count, guint colours[4], gboolean prelight);
-void gui_draw_arrow (GdkPixmap * target);
-void gui_draw_socket (GdkPixmap * target, GtkStateType state, gint xadd,
- gint yadd);
-void gui_draw_number (cairo_t * context, gdouble x, gdouble y, guint number, gdouble *colour);
-void gui_draw_tile (GdkPixmap * target, GtkStateType state, gint xadd,
- gint yadd, gint north, gint south, gint east, gint west, gboolean prelight);
-void gui_draw_pixmap (GdkPixmap *, gint, gint, gboolean, Mover*);
-
-void get_pixeltilexy (gint, gint, gint *, gint *);
-void get_tilexy (gint, gint, gint *, gint *);
-void get_offsetxy (gint, gint, gint *, gint *);
-
-void message (gchar *);
-void new_board (gint);
-void redraw_all (void);
-void redraw_left (void);
-gint setup_mover (gint, gint, Mover*);
-void clear_mover(Mover*);
-void release_tile (gint, gint);
-void place_tile (gint, gint);
-void tile_tilexy (gint, gint, gint*, gint*);
-void swap_without_validation (gint, gint, gint, gint);
-gint valid_drop (gint, gint, gint, gint);
-
-void update_tile_size (gint, gint);
-gboolean configure_space (GtkWidget *, GdkEventConfigure *);
-gint compare_tile (tile *, tile *);
-void find_first_tile (gint, gint *, gint *);
-void move_tile (gint, gint, gint, gint);
-void move_column (unsigned char);
-gint game_over (void);
-void game_score (void);
-gint timer_cb (void);
-void timer_start (void);
-void pause_game (void);
-void resume_game (void);
-void pause_cb (void);
-void move_cb (void);
-void clickmove_toggle_cb (GtkToggleAction *, gpointer);
-void hint_move (gint, gint, gint, gint);
-void move_tile_animate (gint, gint, gint, gint, gboolean);
-void move_held_animate (gint, gint, gint, gint);
-gint show_score_dialog (gint, gboolean);
-void new_game (void);
-
-#ifdef WITH_SMCLIENT
-static int save_state_cb (EggSMClient *client, GKeyFile *keyfile, gpointer client_data);
-static int quit_cb (EggSMClient *client, gpointer client_data);
-#endif /* WITH_SMCLIENT */
-static void load_default_background (void);
-
-static GtkAction *new_game_action;
-static GtkAction *pause_action;
-static GtkAction *hint_action;
-static GtkAction *solve_action;
-static GtkAction *scores_action;
-static GtkAction *move_up_action;
-static GtkAction *move_left_action;
-static GtkAction *move_right_action;
-static GtkAction *move_down_action;
-static GtkAction *fullscreen_action;
-
-
-/* ------------------------- MENU ------------------------ */
-void new_game_cb (GtkAction *, gpointer);
-void size_cb (GtkAction *, gpointer);
-void about_cb (GtkAction *, gpointer);
-void score_cb (GtkAction *, gpointer);
-void hint_cb (GtkAction *, gpointer);
-void solve_cb (GtkAction *, gpointer);
-void move_up_cb (GtkAction *, gpointer);
-void move_left_cb (GtkAction *, gpointer);
-void move_right_cb (GtkAction *, gpointer);
-void move_down_cb (GtkAction *, gpointer);
-void help_cb (GtkAction *, gpointer);
-void quit_game_cb (void);
-
-const GtkActionEntry action_entry[] = {
- {"GameMenu", NULL, N_("_Game")},
- {"MoveMenu", NULL, N_("_Move")},
- {"SettingsMenu", NULL, N_("_Settings")},
- {"SizeMenu", NULL, N_("_Size")},
- {"HelpMenu", NULL, N_("_Help")},
- {"NewGame", GAMES_STOCK_NEW_GAME, NULL, NULL, NULL,
- G_CALLBACK (new_game_cb)},
- {"Hint", GAMES_STOCK_HINT, NULL, NULL, NULL, G_CALLBACK (hint_cb)},
- {"Solve", GTK_STOCK_REFRESH, N_("Sol_ve"), NULL, N_("Solve the game"),
- G_CALLBACK (solve_cb)},
- {"Scores", GAMES_STOCK_SCORES, NULL, NULL, NULL, G_CALLBACK (score_cb)},
- {"Quit", GTK_STOCK_QUIT, NULL, NULL, NULL, G_CALLBACK (quit_game_cb)},
- {"MoveUp", GTK_STOCK_GO_UP, N_("_Up"), "<control>Up",
- N_("Move the pieces up"), G_CALLBACK (move_up_cb)},
- {"MoveLeft", GTK_STOCK_GO_BACK, N_("_Left"), "<control>Left",
- N_("Move the pieces left"), G_CALLBACK (move_left_cb)},
- {"MoveRight", GTK_STOCK_GO_FORWARD, N_("_Right"), "<control>Right",
- N_("Move the pieces right"), G_CALLBACK (move_right_cb)},
- {"MoveDown", GTK_STOCK_GO_DOWN, N_("_Down"), "<control>Down",
- N_("Move the pieces down"), G_CALLBACK (move_down_cb)},
- {"Contents", GAMES_STOCK_CONTENTS, NULL, NULL, NULL, G_CALLBACK (help_cb)},
- {"About", GTK_STOCK_ABOUT, NULL, NULL, NULL, G_CALLBACK (about_cb)}
-};
-
const GtkRadioActionEntry size_action_entry[] = {
{"Size2x2", NULL, N_("_2\303\2272"), NULL, N_("Play on a 2\303\2272 board"),
2},
@@ -339,11 +208,16 @@ const GtkRadioActionEntry size_action_entry[] = {
6}
};
-static const GtkToggleActionEntry toggles[] = {
- {"ClickToMove", NULL, N_("_Click to Move"), NULL, "Pick up and drop tiles by clicking",
- G_CALLBACK (clickmove_toggle_cb)}
-};
-
+static GtkAction *new_game_action;
+static GtkAction *pause_action;
+static GtkAction *hint_action;
+static GtkAction *solve_action;
+static GtkAction *scores_action;
+static GtkAction *move_up_action;
+static GtkAction *move_left_action;
+static GtkAction *move_right_action;
+static GtkAction *move_down_action;
+static GtkAction *fullscreen_action;
static GtkAction *size_action[G_N_ELEMENTS (size_action_entry)];
static const char ui_description[] =
@@ -396,275 +270,7 @@ static const GOptionEntry options[] = {
/* ------------------------------------------------------- */
-int
-main (int argc, char **argv)
-{
- GOptionContext *context;
- GtkWidget *vbox;
- GtkWidget *menubar;
- GtkUIManager *ui_manager;
- GtkAccelGroup *accel_group;
- gboolean retval;
- GError *error = NULL;
-#ifdef WITH_SMCLIENT
- EggSMClient *sm_client;
-#endif /* WITH_SMCLIENT */
-
- if (!games_runtime_init ("gnotravex"))
- return 1;
-
-#ifdef ENABLE_SETGID
- setgid_io_init ();
-#endif
-
- context = g_option_context_new (NULL);
-#if GLIB_CHECK_VERSION (2, 12, 0)
- g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
-#endif /* GLIB_CHECK_VERSION (2, 12, 0) */
- g_option_context_add_group (context, gtk_get_option_group (TRUE));
-#ifdef WITH_SMCLIENT
- g_option_context_add_group (context, egg_sm_client_get_option_group ());
-#endif /* WITH_SMCLIENT */
-
- g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE);
- retval = g_option_context_parse (context, &argc, &argv, &error);
-
- g_option_context_free (context);
- if (!retval) {
- g_print ("%s", error->message);
- g_error_free (error);
- exit (1);
- }
-
- g_set_application_name (_(APPNAME_LONG));
-
- games_conf_initialise (APPNAME);
-
- highscores = games_scores_new ("gnotravex",
- scorecats, G_N_ELEMENTS (scorecats),
- NULL, NULL,
- 1 /* default category */,
- GAMES_SCORES_STYLE_TIME_ASCENDING);
-
- games_stock_init ();
-
- gtk_window_set_default_icon_name ("gnome-tetravex");
-
-#ifdef WITH_SMCLIENT
- sm_client = egg_sm_client_get ();
- g_signal_connect (sm_client, "save-state",
- G_CALLBACK (save_state_cb), NULL);
- g_signal_connect (sm_client, "quit",
- G_CALLBACK (quit_cb), NULL);
-#endif /* WITH_SMCLIENT */
-
- if (size == -1)
- size = games_conf_get_integer (NULL, KEY_GRID_SIZE, NULL);
- if (size < 2 || size > 6)
- size = 3;
- games_scores_set_category (highscores, scorecats[size - 2].key);
-
- click_to_move = games_conf_get_boolean (NULL, KEY_CLICK_MOVE, NULL);
-
- load_default_background ();
- create_window ();
-
- space = gtk_drawing_area_new ();
- gtk_widget_set_events (space,
- GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
- | GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK);
-
- statusbar = create_statusbar ();
-
- ui_manager = gtk_ui_manager_new ();
- games_stock_prepare_for_statusbar_tooltips (ui_manager, statusbar);
-
- menubar = create_menu (ui_manager);
-
- vbox = gtk_vbox_new (FALSE, 0);
- gtk_container_add (GTK_CONTAINER (window), vbox);
-
- gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, FALSE, 0);
- gtk_box_pack_start (GTK_BOX (vbox), space, TRUE, TRUE, 0);
- gtk_box_pack_start (GTK_BOX (vbox), statusbar, FALSE, FALSE, 0);
-
- accel_group = gtk_ui_manager_get_accel_group (ui_manager);
- gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
-
- gtk_widget_realize (space);
- bg_gc = gdk_gc_new (gtk_widget_get_window (space));
- gdk_gc_set_tile (bg_gc, default_background_pixmap);
- gdk_gc_set_fill (bg_gc, GDK_TILED);
-
- g_signal_connect (G_OBJECT (space), "expose_event",
- G_CALLBACK (expose_space), NULL);
- g_signal_connect (G_OBJECT (space), "configure_event",
- G_CALLBACK (configure_space), NULL);
- g_signal_connect (G_OBJECT (space), "button_press_event",
- G_CALLBACK (button_press_space), NULL);
- g_signal_connect (G_OBJECT (space), "button_release_event",
- G_CALLBACK (button_release_space), NULL);
- g_signal_connect (G_OBJECT (space), "motion_notify_event",
- G_CALLBACK (button_motion_space), NULL);
- /* We do our own double-buffering. */
- gtk_widget_set_double_buffered (space, FALSE);
-
- gtk_widget_show (space);
-
-
- if (session_xpos >= 0 && session_ypos >= 0)
- gtk_window_move (GTK_WINDOW (window), session_xpos, session_ypos);
-
- gtk_widget_show_all (window);
- init_window_attrib ();
-
- gtk_action_activate (new_game_action);
-
- gtk_action_activate (size_action[size - 2]);
-
- gtk_main ();
-
- games_conf_shutdown ();
-
- games_runtime_shutdown ();
-
- return 0;
-}
-
-/* Enable or disable the game menu items that are only relevant
- * during a game. */
-static
- void
-set_game_menu_items_sensitive (gboolean state)
-{
- gtk_action_set_sensitive (pause_action, state);
- gtk_action_set_sensitive (hint_action, state);
- gtk_action_set_sensitive (solve_action, state);
-}
-
-/* Show only valid options in the move menu. */
-static
- void
-update_move_menu_sensitivity (void)
-{
- int x, y;
- gboolean clear;
- gboolean n, w, e, s;
-
- n = w = e = s = TRUE;
-
- clear = TRUE;
- for (x = 0; x < size; x++) {
- if (tiles[0][x].status == USED)
- n = FALSE;
- if (tiles[x][0].status == USED)
- w = FALSE;
- if (tiles[x][size - 1].status == USED)
- e = FALSE;
- if (tiles[size - 1][x].status == USED)
- s = FALSE;
- for (y = 0; y < size; y++)
- if (tiles[x][y].status == USED)
- clear = FALSE;
- }
-
- if (clear || (game_state == paused))
- n = w = e = s = FALSE;
-
- gtk_action_set_sensitive (move_up_action, n);
- gtk_action_set_sensitive (move_left_action, w);
- gtk_action_set_sensitive (move_right_action, e);
- gtk_action_set_sensitive (move_down_action, s);
-}
-
-
-void
-create_window (void)
-{
- window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
-
- gtk_window_set_title (GTK_WINDOW (window), _(APPNAME_LONG));
-
- gtk_window_set_default_size (GTK_WINDOW (window), DEFAULT_WIDTH, DEFAULT_HEIGHT);
- games_conf_add_window (GTK_WINDOW (window), NULL);
- gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
-
- gtk_widget_realize (window);
- g_signal_connect (G_OBJECT (window), "delete_event",
- G_CALLBACK (quit_game_cb), NULL);
-}
-
-gboolean
-expose_space (GtkWidget * widget, GdkEventExpose * event)
-{
- gdk_draw_drawable (gtk_widget_get_window (widget),
- gtk_widget_get_style (widget)->fg_gc[GTK_STATE_NORMAL],
- buffer, event->area.x, event->area.y,
- event->area.x, event->area.y,
- event->area.width, event->area.height);
- return FALSE;
-}
-
-gint button_down = 0;
-
-gint
-button_press_space (GtkWidget * widget, GdkEventButton * event)
-{
- if (game_state == paused)
- gtk_action_activate (pause_action);
-
- if (game_state != playing)
- return FALSE;
-
- if (event->button != 1)
- return FALSE;
-
- if (click_to_move)
- {
- if (button_down)
- {
- release_tile (event->x,event->y); /* Seen it happened */
- button_down = 0;
- return FALSE;
- }
- else
- {
- if (setup_mover (event->x, event->y, &mousemover))
- button_down = 1;
- }
- }
- else
- {
- if (button_down == 1)
- {
- release_tile (event->x,event->y); /* Seen it happened */
- button_down = 0;
- return FALSE;
- }
- if (setup_mover (event->x, event->y, &mousemover))
- button_down = 1;
- }
-
- return FALSE;
-}
-
-gint
-button_release_space (GtkWidget * widget, GdkEventButton * event)
-{
- /* Ignore when using click to move mode */
- if (click_to_move)
- return FALSE;
-
- if (event->button == 1) {
- if (button_down == 1) {
- release_tile (event->x, event->y);
- }
- button_down = 0;
- }
- return FALSE;
-}
-
-void
+static void
gui_build_vertices (void)
{
gdouble z, midx, midy, offset, far_offset;
@@ -735,7 +341,7 @@ gui_build_vertices (void)
vertices[19][1] = tile_size - tile_border_size;
vertices[20][0] = tile_border_size;
vertices[20][1] = tile_size - tile_border_size;
-
+
/* Edges for the arrow */
w = gap;
h = size * tile_size;
@@ -747,7 +353,7 @@ gui_build_vertices (void)
vertices[22][1] = yoffset;
vertices[23][0] = vertices[22][0];
vertices[23][1] = h - yoffset;
-
+
/* Arrow inner edges */
dx = w - 2*xoffset;
dy = (h - 2*yoffset) * 0.5;
@@ -761,7 +367,7 @@ gui_build_vertices (void)
vertices[26][1] = vertices[21][1] + z2;
}
-void
+static void
gui_draw_faces (cairo_t * context, gint xadd, gint yadd, int quads[][7],
int count, guint colours[4], gboolean prelight)
{
@@ -795,30 +401,30 @@ gui_draw_faces (cairo_t * context, gint xadd, gint yadd, int quads[][7],
}
}
-void
+static void
gui_draw_arrow (GdkPixmap * target)
{
cairo_t *context;
gdouble x, y;
guint colours[4] = { SOCKET_COLOUR, SOCKET_COLOUR, SOCKET_COLOUR, SOCKET_COLOUR };
-
+
context = gdk_cairo_create (GDK_DRAWABLE (buffer));
-
+
x = xborder + size * tile_size;
y = yborder;
gui_draw_faces (context, x, y, arrow_faces, 3, colours, FALSE);
-
+
cairo_destroy (context);
}
-void
+static void
gui_draw_socket (GdkPixmap * target, GtkStateType state, gint xadd, gint yadd)
{
cairo_t *context;
guint colours[4] = { SOCKET_COLOUR, SOCKET_COLOUR, SOCKET_COLOUR, SOCKET_COLOUR };
gdouble *colour;
-
- gdk_draw_rectangle (GDK_DRAWABLE(target), bg_gc, TRUE, xadd, yadd,
+
+ gdk_draw_rectangle (GDK_DRAWABLE(target), bg_gc, TRUE, xadd, yadd,
tile_size, tile_size);
context = gdk_cairo_create (GDK_DRAWABLE (target));
@@ -844,11 +450,24 @@ gui_draw_socket (GdkPixmap * target, GtkStateType state, gint xadd, gint yadd)
cairo_destroy (context);
}
-void
+static void
gui_draw_number (cairo_t * context, gdouble x, gdouble y, guint number, gdouble *colour)
{
const gchar *text;
cairo_text_extents_t extents;
+ static const char *translatable_number[10] = {
+ /* Translators: in-game numbers, replaceable with single-character local ideograms */
+ NC_("number", "0"),
+ NC_("number", "1"),
+ NC_("number", "2"),
+ NC_("number", "3"),
+ NC_("number", "4"),
+ NC_("number", "5"),
+ NC_("number", "6"),
+ NC_("number", "7"),
+ NC_("number", "8"),
+ NC_("number", "9")
+ };
text = g_dpgettext2 (NULL, "number", translatable_number[number]);
@@ -860,7 +479,7 @@ gui_draw_number (cairo_t * context, gdouble x, gdouble y, guint number, gdouble
cairo_show_text (context, text);
}
-void
+static void
gui_draw_tile (GdkPixmap * target, GtkStateType state, gint xadd, gint yadd,
gint north, gint south, gint east, gint west, gboolean prelight)
{
@@ -878,7 +497,7 @@ gui_draw_tile (GdkPixmap * target, GtkStateType state, gint xadd, gint yadd,
/* Only draw inside the allocated space */
cairo_rectangle (context, xadd, yadd, tile_size, tile_size);
cairo_clip (context);
-
+
/* Clear background */
cairo_set_source_rgba (context, 0.0, 0.0, 0.0, 1.0);
cairo_paint (context);
@@ -910,47 +529,7 @@ gui_draw_tile (GdkPixmap * target, GtkStateType state, gint xadd, gint yadd,
cairo_destroy (context);
}
-gint
-button_motion_space (GtkWidget * widget, GdkEventButton * event)
-{
- static int oldx = -1, oldy = -1;
- gint x, y;
-
- if (game_state == paused)
- return FALSE;
-
- if (button_down == 1) {
- mousemover.x = event->x;
- mousemover.y = event->y;
- x = event->x - mousemover.xoff;
- y = event->y - mousemover.yoff;
- gdk_window_move (mousemover.window, x, y);
- gdk_window_clear (mousemover.window);
- }
-
- /* This code hilights pieces as the mouse moves over them
- * in general imitation of "prelight" in GTK. Need to highlight
- * differently depending on if we are holding a tile or not */
- if(mousemover.window == NULL)
- get_tilexy (event->x, event->y, &x, &y);
- else
- tile_tilexy (event->x, event->y, &x, &y);
-
- if ((x != oldx) || (y != oldy)) {
- if ((oldx != -1) && (tiles[oldy][oldx].status == USED)) {
- gui_draw_pixmap (buffer, oldx, oldy, FALSE, NULL);
- }
- if ((x != -1) && (tiles[y][x].status == USED)) {
- gui_draw_pixmap (buffer, x, y, TRUE, NULL);
- }
- oldx = x;
- oldy = y;
- }
-
- return FALSE;
-}
-
-void
+static void
gui_draw_pixmap (GdkPixmap * target, gint x, gint y, gboolean prelight, Mover *mover)
{
gint which, xadd = 0, yadd = 0;
@@ -975,8 +554,8 @@ gui_draw_pixmap (GdkPixmap * target, gint x, gint y, gboolean prelight, Mover *m
state = GTK_STATE_PRELIGHT;
if (which == USED) {
- if (game_state == paused)
- gui_draw_tile (buffer, GTK_STATE_NORMAL, xadd, yadd, 0, 0, 0, 0, FALSE);
+ if (game_state == PAUSED)
+ gui_draw_tile (buffer, GTK_STATE_NORMAL, xadd, yadd, 0, 0, 0, 0, FALSE);
else
gui_draw_tile (target, state, xadd, yadd, tiles[y][x].n, tiles[y][x].s,
tiles[y][x].e, tiles[y][x].w, state);
@@ -987,7 +566,197 @@ gui_draw_pixmap (GdkPixmap * target, gint x, gint y, gboolean prelight, Mover *m
gtk_widget_queue_draw_area (space, xadd, yadd, tile_size, tile_size);
}
-void
+static void
+redraw_all (void)
+{
+ guint x, y;
+#if GTK_CHECK_VERSION (2, 90, 5)
+ cairo_region_t *region;
+#else
+ GdkRegion *region;
+#endif
+
+ if (!gtk_widget_get_window (space))
+ return;
+
+ region = gdk_drawable_get_clip_region (GDK_DRAWABLE (gtk_widget_get_window (space)));
+ gdk_window_begin_paint_region (gtk_widget_get_window (space), region);
+
+ gdk_window_clear (gtk_widget_get_window (space));
+ gdk_draw_rectangle (gtk_widget_get_window (space), bg_gc, TRUE, 0, 0, -1, -1);
+ gdk_draw_rectangle (buffer, bg_gc, TRUE, 0, 0, -1, -1);
+ for (y = 0; y < size; y++)
+ for (x = 0; x < size * 2; x++)
+ gui_draw_pixmap (buffer, x, y, FALSE, NULL);
+
+ gui_draw_arrow(buffer);
+
+ gdk_window_end_paint (gtk_widget_get_window (space));
+
+#if GTK_CHECK_VERSION (2, 90, 5)
+ cairo_region_destroy (region);
+#else
+ gdk_region_destroy (region);
+#endif
+}
+
+static void
+redraw_left (void)
+{
+ gint x, y;
+#if GTK_CHECK_VERSION (2, 90, 5)
+ cairo_region_t *region;
+ cairo_rectangle_int_t rect =
+#else
+ GdkRegion *region;
+ GdkRectangle rect =
+#endif
+ { xborder, yborder, tile_size * size, tile_size * size };
+
+#if GTK_CHECK_VERSION (2, 90, 5)
+ region = cairo_region_create_rectangle (&rect);
+#else
+ region = gdk_region_rectangle (&rect);
+#endif
+
+ gdk_window_begin_paint_region (gtk_widget_get_window (space), region);
+
+ for (y = 0; y < size; y++)
+ for (x = 0; x < size; x++)
+ gui_draw_pixmap (buffer, x, y, FALSE, NULL);
+
+ gdk_window_end_paint (gtk_widget_get_window (space));
+
+#if GTK_CHECK_VERSION (2, 90, 5)
+ cairo_region_destroy (region);
+#else
+ gdk_region_destroy (region);
+#endif
+}
+
+/* Enable or disable the game menu items that are only relevant
+ * during a game. */
+static void
+set_game_menu_items_sensitive (gboolean state)
+{
+ gtk_action_set_sensitive (pause_action, state);
+ gtk_action_set_sensitive (hint_action, state);
+ gtk_action_set_sensitive (solve_action, state);
+}
+
+/* Show only valid options in the move menu. */
+static void
+update_move_menu_sensitivity (void)
+{
+ int x, y;
+ gboolean clear;
+ gboolean n, w, e, s;
+
+ n = w = e = s = TRUE;
+
+ clear = TRUE;
+ for (x = 0; x < size; x++) {
+ if (tiles[0][x].status == USED)
+ n = FALSE;
+ if (tiles[x][0].status == USED)
+ w = FALSE;
+ if (tiles[x][size - 1].status == USED)
+ e = FALSE;
+ if (tiles[size - 1][x].status == USED)
+ s = FALSE;
+ for (y = 0; y < size; y++)
+ if (tiles[x][y].status == USED)
+ clear = FALSE;
+ }
+
+ if (clear || (game_state == PAUSED))
+ n = w = e = s = FALSE;
+
+ gtk_action_set_sensitive (move_up_action, n);
+ gtk_action_set_sensitive (move_left_action, w);
+ gtk_action_set_sensitive (move_right_action, e);
+ gtk_action_set_sensitive (move_down_action, s);
+}
+
+static void
+clear_mover(Mover* mover)
+{
+ if(mover->window != NULL)
+ gdk_window_destroy(mover->window);
+ mover->window = NULL;
+ if (mover->pixmap)
+ g_object_unref (mover->pixmap);
+ mover->pixmap = NULL;
+}
+
+static void
+new_board (gint size)
+{
+ static gint myrand = 498;
+ gint x, y, x1, y1, i, j;
+ Tile tmp;
+
+ have_been_hinted = 0;
+ solve_me = 0;
+
+ if (timer_timeout) {
+ g_source_remove (timer_timeout);
+ gtk_widget_set_sensitive (GTK_WIDGET (space), TRUE);
+ }
+
+ if (button_down || moving) {
+ clear_mover(&mousemover);
+ clear_mover(&automover);
+ button_down = 0;
+ moving = 0;
+ }
+
+ g_random_set_seed (time (NULL) + myrand);
+
+ myrand += 17;
+
+ for (y = 0; y < size; y++)
+ for (x = 0; x < size; x++)
+ tiles[y][x].status = UNUSED;
+
+ for (y = 0; y < size; y++)
+ for (x = size; x < size * 2; x++) {
+ tiles[y][x].status = USED;
+ tiles[y][x].n = g_random_int () % 10;
+ tiles[y][x].s = g_random_int () % 10;
+ tiles[y][x].w = g_random_int () % 10;
+ tiles[y][x].e = g_random_int () % 10;
+ }
+
+ /* Sort */
+ for (y = 0; y < size; y++)
+ for (x = size; x < size * 2 - 1; x++)
+ tiles[y][x].e = tiles[y][x + 1].w;
+ for (y = 0; y < size - 1; y++)
+ for (x = size; x < size * 2; x++)
+ tiles[y][x].s = tiles[y + 1][x].n;
+
+ /* Copy tiles to orig_tiles */
+ for (y = 0; y < size; y++)
+ for (x = 0; x < size; x++)
+ orig_tiles[y][x] = tiles[y][x + size];
+
+ /* Unsort */
+ j = 0;
+ do {
+ for (i = 0; i < size * size * size; i++) {
+ x = g_random_int () % size + size;
+ y = g_random_int () % size;
+ x1 = g_random_int () % size + size;
+ y1 = g_random_int () % size;
+ tmp = tiles[y1][x1];
+ tiles[y1][x1] = tiles[y][x];
+ tiles[y][x] = tmp;
+ }
+ } while (tiles[0][size].e == tiles[0][size + 1].w && j++ < 8);
+}
+
+static void
get_pixeltilexy (gint x, gint y, gint * xx, gint * yy)
{
gint sumx = xborder, sumy = yborder;
@@ -1001,30 +770,7 @@ get_pixeltilexy (gint x, gint y, gint * xx, gint * yy)
*yy = sumy;
}
-/* We use this slightly less strict version when dropping tiles. */
static void
-get_tilexy_lazy (gint x, gint y, gint * xx, gint * yy)
-{
- x = x - xborder;
- y = y - yborder;
- if (x / tile_size < size)
- *xx = x / tile_size;
- else
- *xx = size + (x - (gap + tile_size * size)) / tile_size;
- *yy = (y / tile_size);
-
- /* Bounds checking */
- if (*xx < 0)
- *xx = 0;
- else if (*xx >= size * 2)
- *xx = size * 2 - 1;
- if (y < 0)
- *yy = 0;
- else if (*yy >= size)
- *yy = size - 1;
-}
-
-void
get_tilexy (gint x, gint y, gint * xx, gint * yy)
{
/* We return -1, -1 if the location doesn't correspond to a tile. */
@@ -1051,10 +797,9 @@ get_tilexy (gint x, gint y, gint * xx, gint * yy)
}
}
-void
+static void
get_offsetxy (gint x, gint y, gint * xoff, gint * yoff)
{
-
x = x - xborder;
y = y - yborder;
if (x / tile_size < size)
@@ -1064,18 +809,18 @@ get_offsetxy (gint x, gint y, gint * xoff, gint * yoff)
*yoff = y % tile_size;
}
-gint
+static gboolean
setup_mover (gint x, gint y, Mover *mover)
{
gint xx, yy;
get_tilexy (x, y, &xx, &yy);
if (xx == -1)
- return 0; /* No move */
+ return FALSE; /* No move */
if (tiles[yy][xx].status == UNUSED)
- return 0; /* No move */
+ return FALSE; /* No move */
get_offsetxy (x, y, &mover->xoff, &mover->yoff);
-
+
mover->heldtile = tiles[yy][xx];
mover->xstart = xx;
mover->ystart = yy;
@@ -1093,119 +838,30 @@ setup_mover (gint x, gint y, Mover *mover)
/* Show held tile on top if swapping */
if(mover == &automover && mousemover.window != NULL)
gdk_window_show(mousemover.window);
-
+
tiles[yy][xx].status = UNUSED;
gui_draw_pixmap (buffer, xx, yy, FALSE, NULL);
- return 1;
-}
-
-void
-clear_mover(Mover* mover)
-{
- if(mover->window != NULL)
- gdk_window_destroy(mover->window);
- mover->window = NULL;
- if (mover->pixmap)
- g_object_unref (mover->pixmap);
- mover->pixmap = NULL;
-}
-
-void
-release_tile(gint x, gint y) {
- gint xx, yy;
-
- tile_tilexy (x, y, &xx, &yy);
- if (xx >= 0 && xx < size * 2 && yy >= 0 && yy < size) {
- if (tiles[yy][xx].status == UNUSED && valid_drop (mousemover.xstart, mousemover.ystart, xx, yy)) {
- move_held_animate (x, y, xx, yy);
- return;
- } else if (tiles[yy][xx].status == USED) {
- swap_without_validation(xx, yy, mousemover.xstart, mousemover.ystart);
- if(valid_drop (xx, yy, xx, yy) && valid_drop (mousemover.xstart, mousemover.ystart, mousemover.xstart, mousemover.ystart)) {
- swap_without_validation (xx, yy, mousemover.xstart, mousemover.ystart);
- move_tile_animate (xx, yy, mousemover.xstart, mousemover.ystart, TRUE);
- return;
- } else
- swap_without_validation (xx, yy, mousemover.xstart, mousemover.ystart);
- }
- }
-
- /* Tile needs to go back to its original position */
- move_held_animate (x, y, mousemover.xstart, mousemover.ystart);
-}
-
-void
-place_tile (gint x, gint y)
-{
- tiles[automover.yend][automover.xend] = automover.heldtile;
- gui_draw_pixmap (buffer, automover.xend, automover.yend, FALSE, NULL);
-
- clear_mover(&automover);
- if (game_over () && game_state != gameover) {
- game_state = gameover;
- games_clock_stop (GAMES_CLOCK (timer));
- set_game_menu_items_sensitive (FALSE);
- if (!have_been_hinted) {
- message (_("Puzzle solved! Well done!"));
- } else {
- message (_("Puzzle solved!"));
- }
- game_score ();
- }
- update_move_menu_sensitivity ();
-}
-
-void
-tile_tilexy (gint x, gint y, gint *xx, gint *yy)
-{
- get_tilexy_lazy (x - mousemover.xoff + tile_size / 2,
- y - mousemover.yoff + tile_size / 2, xx, yy);
+ return TRUE;
}
-void
+static void
swap_without_validation (gint x1, gint y1, gint x2, gint y2)
{
- tile swp = tiles[y1][x1];
+ Tile swp = tiles[y1][x1];
tiles[y1][x1] = tiles[y2][x2];
tiles[y2][x2] = swp;
tiles[y1][x1].status = USED;
tiles[y2][x2].status = USED;
}
-gint
-valid_drop (gint sx, gint sy, gint ex, gint ey)
-{
- if (ex >= size)
- return 1;
-
- /* West */
- if (ex != 0 && tiles[ey][ex - 1].status == USED
- && tiles[ey][ex - 1].e != tiles[sy][sx].w)
- return 0;
- /* East */
- if (ex != size - 1 && tiles[ey][ex + 1].status == USED
- && tiles[ey][ex + 1].w != tiles[sy][sx].e)
- return 0;
- /* North */
- if (ey != 0 && tiles[ey - 1][ex].status == USED
- && tiles[ey - 1][ex].s != tiles[sy][sx].n)
- return 0;
- /* South */
- if (ey != size - 1 && tiles[ey + 1][ex].status == USED
- && tiles[ey + 1][ex].n != tiles[sy][sx].s)
- return 0;
-
- return 1;
-}
-
-void
+static void
move_tile (gint xx, gint yy, gint x, gint y)
{
tiles[yy][xx] = tiles[y][x];
tiles[y][x].status = UNUSED;
}
-void
+static void
move_column (unsigned char dir)
{
gint x, y;
@@ -1252,19 +908,200 @@ move_column (unsigned char dir)
update_move_menu_sensitivity ();
}
-gint
+static gboolean
game_over (void)
{
gint x, y;
for (y = 0; y < size; y++)
for (x = 0; x < size; x++)
if (tiles[y][x].status == UNUSED)
- return 0;
+ return FALSE;
- return 1;
+ return TRUE;
}
-gint
+static void
+message (gchar * message)
+{
+ guint context_id;
+
+ context_id =
+ gtk_statusbar_get_context_id (GTK_STATUSBAR (statusbar), "mesasge");
+ gtk_statusbar_pop (GTK_STATUSBAR (statusbar), context_id);
+ gtk_statusbar_push (GTK_STATUSBAR (statusbar), context_id, message);
+}
+
+static void
+pause_game (void)
+{
+ if (game_state != PAUSED) {
+ game_state = PAUSED;
+ message (_("Game paused"));
+ redraw_all ();
+ update_move_menu_sensitivity ();
+ gtk_action_set_sensitive (hint_action, FALSE);
+ gtk_action_set_sensitive (solve_action, FALSE);
+ games_clock_stop (GAMES_CLOCK (timer));
+ }
+}
+
+static void
+resume_game (void)
+{
+ if (game_state == PAUSED) {
+ game_state = PLAYING;
+ message ("");
+ redraw_all ();
+ update_move_menu_sensitivity ();
+ gtk_action_set_sensitive (hint_action, TRUE);
+ gtk_action_set_sensitive (solve_action, TRUE);
+ games_clock_start (GAMES_CLOCK (timer));
+ }
+}
+
+static void
+make_buffer (GtkWidget * widget)
+{
+ GtkAllocation allocation;
+
+ if (buffer)
+ g_object_unref (buffer);
+
+ gtk_widget_get_allocation (widget, &allocation);
+ buffer = gdk_pixmap_new (gtk_widget_get_window (widget),
+ allocation.width,
+ allocation.height, -1);
+}
+
+static void
+timer_start (void)
+{
+ games_clock_stop (GAMES_CLOCK (timer));
+ games_clock_reset (GAMES_CLOCK (timer));
+ games_clock_start (GAMES_CLOCK (timer));
+}
+
+static void
+new_game (void)
+{
+ gchar *str;
+
+ /* Reset pause menu */
+ gtk_action_set_sensitive(pause_action, TRUE);
+
+ game_state = GAME_OVER;
+
+ new_board (size);
+ gtk_widget_freeze_child_notify (space);
+ make_buffer (space);
+ redraw_all ();
+ gtk_widget_thaw_child_notify (space);
+ timer_start ();
+ set_game_menu_items_sensitive (TRUE);
+ update_move_menu_sensitivity ();
+ str = g_strdup_printf (_("Playing %d\303\227%d board"), size, size);
+ message (str);
+ g_free (str);
+
+ game_state = PLAYING;
+}
+
+static void
+new_game_cb (GtkAction * action, gpointer data)
+{
+ new_game ();
+}
+
+static void
+quit_game_cb (void)
+{
+ gtk_main_quit ();
+}
+
+static void
+create_window (void)
+{
+ window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+
+ gtk_window_set_title (GTK_WINDOW (window), _(APPNAME_LONG));
+
+ gtk_window_set_default_size (GTK_WINDOW (window), DEFAULT_WIDTH, DEFAULT_HEIGHT);
+ games_conf_add_window (GTK_WINDOW (window), NULL);
+ gtk_window_set_resizable (GTK_WINDOW (window), TRUE);
+
+ gtk_widget_realize (window);
+ g_signal_connect (G_OBJECT (window), "delete_event",
+ G_CALLBACK (quit_game_cb), NULL);
+}
+
+static gboolean
+expose_space (GtkWidget * widget, GdkEventExpose * event)
+{
+ gdk_draw_drawable (gtk_widget_get_window (widget),
+ gtk_widget_get_style (widget)->fg_gc[GTK_STATE_NORMAL],
+ buffer, event->area.x, event->area.y,
+ event->area.x, event->area.y,
+ event->area.width, event->area.height);
+ return FALSE;
+}
+
+/* We use this slightly less strict version when dropping tiles. */
+static void
+get_tilexy_lazy (gint x, gint y, gint * xx, gint * yy)
+{
+ x = x - xborder;
+ y = y - yborder;
+ if (x / tile_size < size)
+ *xx = x / tile_size;
+ else
+ *xx = size + (x - (gap + tile_size * size)) / tile_size;
+ *yy = (y / tile_size);
+
+ /* Bounds checking */
+ if (*xx < 0)
+ *xx = 0;
+ else if (*xx >= size * 2)
+ *xx = size * 2 - 1;
+ if (y < 0)
+ *yy = 0;
+ else if (*yy >= size)
+ *yy = size - 1;
+}
+
+static void
+tile_tilexy (gint x, gint y, gint *xx, gint *yy)
+{
+ get_tilexy_lazy (x - mousemover.xoff + tile_size / 2,
+ y - mousemover.yoff + tile_size / 2, xx, yy);
+}
+
+static gboolean
+valid_drop (gint sx, gint sy, gint ex, gint ey)
+{
+ if (ex >= size)
+ return TRUE;
+
+ /* West */
+ if (ex != 0 && tiles[ey][ex - 1].status == USED
+ && tiles[ey][ex - 1].e != tiles[sy][sx].w)
+ return FALSE;
+ /* East */
+ if (ex != size - 1 && tiles[ey][ex + 1].status == USED
+ && tiles[ey][ex + 1].w != tiles[sy][sx].e)
+ return FALSE;
+ /* North */
+ if (ey != 0 && tiles[ey - 1][ex].status == USED
+ && tiles[ey - 1][ex].s != tiles[sy][sx].n)
+ return FALSE;
+ /* South */
+ if (ey != size - 1 && tiles[ey + 1][ex].status == USED
+ && tiles[ey + 1][ex].n != tiles[sy][sx].s)
+ return FALSE;
+
+ return TRUE;
+}
+
+static gint
show_score_dialog (gint pos, gboolean endofgame)
{
static GtkWidget *scoresdialog = NULL;
@@ -1304,13 +1141,7 @@ show_score_dialog (gint pos, gboolean endofgame)
return result;
}
-void
-score_cb (GtkAction * action, gpointer data)
-{
- show_score_dialog (0, FALSE);
-}
-
-void
+static void
game_score (void)
{
gint pos = 0;
@@ -1330,7 +1161,232 @@ game_score (void)
}
}
-void
+static void
+place_tile (gint x, gint y)
+{
+ tiles[automover.yend][automover.xend] = automover.heldtile;
+ gui_draw_pixmap (buffer, automover.xend, automover.yend, FALSE, NULL);
+
+ clear_mover(&automover);
+ if (game_over () && game_state != GAME_OVER) {
+ game_state = GAME_OVER;
+ games_clock_stop (GAMES_CLOCK (timer));
+ set_game_menu_items_sensitive (FALSE);
+ if (!have_been_hinted) {
+ message (_("Puzzle solved! Well done!"));
+ } else {
+ message (_("Puzzle solved!"));
+ }
+ game_score ();
+ }
+ update_move_menu_sensitivity ();
+}
+
+static void move_cb (void);
+
+static void
+move_held_animate (gint x, gint y, gint tx, gint ty)
+{
+ /* Need to take over movement from mouse mover to auto mover */
+ gint xx, yy;
+ move_src_x = x - mousemover.xoff;
+ move_src_y = y - mousemover.yoff;
+ get_tilexy (move_src_x, move_src_y, &xx, &yy);
+ get_pixeltilexy (tx, ty, &move_dest_x, &move_dest_y);
+
+ clear_mover(&automover);
+ automover = mousemover;
+ mousemover.window = NULL;
+ mousemover.pixmap = NULL;
+
+ automover.xend = tx;
+ automover.yend = ty;
+ moving = 1;
+ if(xx == tx && yy == ty)
+ animcount = SHORT_COUNT;
+ else
+ animcount = LONG_COUNT;
+ swapanim = FALSE;
+ gtk_widget_set_sensitive (GTK_WIDGET (space), FALSE);
+ timer_timeout = g_timeout_add (DELAY, (GSourceFunc) (move_cb), NULL);
+}
+
+static void
+move_cb (void)
+{
+ float dx, dy;
+ static gint count = 0;
+ dx = (float) (move_src_x - move_dest_x) / animcount;
+ dy = (float) (move_src_y - move_dest_y) / animcount;
+ if (count <= animcount) {
+ gdk_window_move (automover.window, move_src_x - (gint) (count * dx),
+ (gint) move_src_y - (gint) (count * dy));
+ count++;
+ }
+ if (count > animcount) {
+ count = 0;
+ place_tile (move_dest_x + 1, move_dest_y + 1);
+ moving = 0;
+ g_source_remove (timer_timeout);
+ gtk_widget_set_sensitive (GTK_WIDGET (space), TRUE);
+
+ if (swapanim) {
+ move_held_animate (mousemover.x, mousemover.y, automover.xstart, automover.ystart);
+ return;
+ }
+
+ if (game_state != PLAYING)
+ return;
+ if (solve_me)
+ gtk_action_activate (hint_action);
+ }
+}
+
+static void
+move_tile_animate (gint x1, gint y1, gint x2, gint y2, gboolean sa)
+{
+ get_pixeltilexy (x1, y1, &move_src_x, &move_src_y);
+ get_pixeltilexy (x2, y2, &move_dest_x, &move_dest_y);
+
+ setup_mover (move_src_x, move_src_y, &automover);
+ automover.xend = x2;
+ automover.yend = y2;
+ moving = 1;
+ animcount = LONG_COUNT;
+ swapanim = sa;
+ gtk_widget_set_sensitive (GTK_WIDGET (space), FALSE);
+ timer_timeout = g_timeout_add (DELAY, (GSourceFunc) (move_cb), NULL);
+}
+
+static void
+release_tile(gint x, gint y)
+{
+ gint xx, yy;
+
+ tile_tilexy (x, y, &xx, &yy);
+ if (xx >= 0 && xx < size * 2 && yy >= 0 && yy < size) {
+ if (tiles[yy][xx].status == UNUSED && valid_drop (mousemover.xstart, mousemover.ystart, xx, yy)) {
+ move_held_animate (x, y, xx, yy);
+ return;
+ } else if (tiles[yy][xx].status == USED) {
+ swap_without_validation(xx, yy, mousemover.xstart, mousemover.ystart);
+ if(valid_drop (xx, yy, xx, yy) && valid_drop (mousemover.xstart, mousemover.ystart, mousemover.xstart, mousemover.ystart)) {
+ swap_without_validation (xx, yy, mousemover.xstart, mousemover.ystart);
+ move_tile_animate (xx, yy, mousemover.xstart, mousemover.ystart, TRUE);
+ return;
+ } else
+ swap_without_validation (xx, yy, mousemover.xstart, mousemover.ystart);
+ }
+ }
+
+ /* Tile needs to go back to its original position */
+ move_held_animate (x, y, mousemover.xstart, mousemover.ystart);
+}
+
+static gint
+button_press_space (GtkWidget * widget, GdkEventButton * event)
+{
+ if (game_state == PAUSED)
+ gtk_action_activate (pause_action);
+
+ if (game_state != PLAYING)
+ return FALSE;
+
+ if (event->button != 1)
+ return FALSE;
+
+ if (click_to_move)
+ {
+ if (button_down)
+ {
+ release_tile (event->x,event->y); /* Seen it happened */
+ button_down = 0;
+ return FALSE;
+ }
+ else
+ {
+ if (setup_mover (event->x, event->y, &mousemover))
+ button_down = 1;
+ }
+ }
+ else
+ {
+ if (button_down == 1)
+ {
+ release_tile (event->x,event->y); /* Seen it happened */
+ button_down = 0;
+ return FALSE;
+ }
+ if (setup_mover (event->x, event->y, &mousemover))
+ button_down = 1;
+ }
+
+ return FALSE;
+}
+
+static gint
+button_release_space (GtkWidget * widget, GdkEventButton * event)
+{
+ /* Ignore when using click to move mode */
+ if (click_to_move)
+ return FALSE;
+
+ if (event->button == 1) {
+ if (button_down == 1) {
+ release_tile (event->x, event->y);
+ }
+ button_down = 0;
+ }
+ return FALSE;
+}
+
+static gint
+button_motion_space (GtkWidget * widget, GdkEventButton * event)
+{
+ static int oldx = -1, oldy = -1;
+ gint x, y;
+
+ if (game_state == PAUSED)
+ return FALSE;
+
+ if (button_down == 1) {
+ mousemover.x = event->x;
+ mousemover.y = event->y;
+ x = event->x - mousemover.xoff;
+ y = event->y - mousemover.yoff;
+ gdk_window_move (mousemover.window, x, y);
+ gdk_window_clear (mousemover.window);
+ }
+
+ /* This code hilights pieces as the mouse moves over them
+ * in general imitation of "prelight" in GTK. Need to highlight
+ * differently depending on if we are holding a tile or not */
+ if(mousemover.window == NULL)
+ get_tilexy (event->x, event->y, &x, &y);
+ else
+ tile_tilexy (event->x, event->y, &x, &y);
+
+ if ((x != oldx) || (y != oldy)) {
+ if ((oldx != -1) && (tiles[oldy][oldx].status == USED)) {
+ gui_draw_pixmap (buffer, oldx, oldy, FALSE, NULL);
+ }
+ if ((x != -1) && (tiles[y][x].status == USED)) {
+ gui_draw_pixmap (buffer, x, y, TRUE, NULL);
+ }
+ oldx = x;
+ oldy = y;
+ }
+
+ return FALSE;
+}
+
+static void
+score_cb (GtkAction * action, gpointer data)
+{
+ show_score_dialog (0, FALSE);
+}
+
+static void
update_tile_size (gint screen_width, gint screen_height)
{
gint xt_size, yt_size;
@@ -1353,13 +1409,13 @@ update_tile_size (gint screen_width, gint screen_height)
/* Make arrow less sunken */
arrow_border_size = 0.5 * tile_border_size;
if (arrow_border_size < 1.0)
- arrow_border_size = 1.0;
+ arrow_border_size = 1.0;
/* Rebuild the tile/socket vertices when required */
rebuild_vertices = TRUE;
}
-gboolean
+static gboolean
configure_space (GtkWidget * widget, GdkEventConfigure * event)
{
gtk_widget_freeze_child_notify (widget);
@@ -1371,76 +1427,7 @@ configure_space (GtkWidget * widget, GdkEventConfigure * event)
return FALSE;
}
-void
-redraw_all (void)
-{
- guint x, y;
-#if GTK_CHECK_VERSION (2, 90, 5)
- cairo_region_t *region;
-#else
- GdkRegion *region;
-#endif
-
- if (!gtk_widget_get_window (space))
- return;
-
- region = gdk_drawable_get_clip_region (GDK_DRAWABLE (gtk_widget_get_window (space)));
- gdk_window_begin_paint_region (gtk_widget_get_window (space), region);
-
- gdk_window_clear (gtk_widget_get_window (space));
- gdk_draw_rectangle (gtk_widget_get_window (space), bg_gc, TRUE, 0, 0, -1, -1);
- gdk_draw_rectangle (buffer, bg_gc, TRUE, 0, 0, -1, -1);
- for (y = 0; y < size; y++)
- for (x = 0; x < size * 2; x++)
- gui_draw_pixmap (buffer, x, y, FALSE, NULL);
-
- gui_draw_arrow(buffer);
-
- gdk_window_end_paint (gtk_widget_get_window (space));
-
-#if GTK_CHECK_VERSION (2, 90, 5)
- cairo_region_destroy (region);
-#else
- gdk_region_destroy (region);
-#endif
-}
-
-void
-redraw_left (void)
-{
- gint x, y;
-#if GTK_CHECK_VERSION (2, 90, 5)
- cairo_region_t *region;
- cairo_rectangle_int_t rect =
-#else
- GdkRegion *region;
- GdkRectangle rect =
-#endif
- { xborder, yborder, tile_size * size, tile_size * size };
-
-#if GTK_CHECK_VERSION (2, 90, 5)
- region = cairo_region_create_rectangle (&rect);
-#else
- region = gdk_region_rectangle (&rect);
-#endif
-
- gdk_window_begin_paint_region (gtk_widget_get_window (space), region);
-
- for (y = 0; y < size; y++)
- for (x = 0; x < size; x++)
- gui_draw_pixmap (buffer, x, y, FALSE, NULL);
-
- gdk_window_end_paint (gtk_widget_get_window (space));
-
-#if GTK_CHECK_VERSION (2, 90, 5)
- cairo_region_destroy (region);
-#else
- gdk_region_destroy (region);
-#endif
-}
-
-
-GtkWidget *
+static GtkWidget *
create_statusbar (void)
{
GtkWidget *status_bar, *time_label, *time_box;
@@ -1460,21 +1447,9 @@ create_statusbar (void)
return status_bar;
}
-void
-message (gchar * message)
-{
- guint context_id;
-
- context_id =
- gtk_statusbar_get_context_id (GTK_STATUSBAR (statusbar), "mesasge");
- gtk_statusbar_pop (GTK_STATUSBAR (statusbar), context_id);
- gtk_statusbar_push (GTK_STATUSBAR (statusbar), context_id, message);
-}
-
-void
+static void
init_window_attrib (void)
{
-
/* The depth of mover.window must match the depth of gtk_widget_get_window (space). */
windowattrib.wclass = GDK_INPUT_OUTPUT;
windowattrib.window_type = GDK_WINDOW_CHILD;
@@ -1485,218 +1460,19 @@ init_window_attrib (void)
windowattrib.visual = gdk_drawable_get_visual (gtk_widget_get_window (space));
}
-void
-new_board (gint size)
-{
- static gint myrand = 498;
- gint x, y, x1, y1, i, j;
- tile tmp;
-
- have_been_hinted = 0;
- solve_me = 0;
-
- if (timer_timeout) {
- g_source_remove (timer_timeout);
- gtk_widget_set_sensitive (GTK_WIDGET (space), TRUE);
- }
-
- if (button_down || moving) {
- clear_mover(&mousemover);
- clear_mover(&automover);
- button_down = 0;
- moving = 0;
- }
-
- g_random_set_seed (time (NULL) + myrand);
-
- myrand += 17;
-
- for (y = 0; y < size; y++)
- for (x = 0; x < size; x++)
- tiles[y][x].status = UNUSED;
-
- for (y = 0; y < size; y++)
- for (x = size; x < size * 2; x++) {
- tiles[y][x].status = USED;
- tiles[y][x].n = g_random_int () % 10;
- tiles[y][x].s = g_random_int () % 10;
- tiles[y][x].w = g_random_int () % 10;
- tiles[y][x].e = g_random_int () % 10;
- }
-
- /* Sort */
- for (y = 0; y < size; y++)
- for (x = size; x < size * 2 - 1; x++)
- tiles[y][x].e = tiles[y][x + 1].w;
- for (y = 0; y < size - 1; y++)
- for (x = size; x < size * 2; x++)
- tiles[y][x].s = tiles[y + 1][x].n;
-
- /* Copy tiles to orig_tiles */
- for (y = 0; y < size; y++)
- for (x = 0; x < size; x++)
- orig_tiles[y][x] = tiles[y][x + size];
-
- /* Unsort */
- j = 0;
- do {
- for (i = 0; i < size * size * size; i++) {
- x = g_random_int () % size + size;
- y = g_random_int () % size;
- x1 = g_random_int () % size + size;
- y1 = g_random_int () % size;
- tmp = tiles[y1][x1];
- tiles[y1][x1] = tiles[y][x];
- tiles[y][x] = tmp;
- }
- } while (tiles[0][size].e == tiles[0][size + 1].w && j++ < 8);
-}
-
-void
-pause_game (void)
-{
- if (game_state != paused) {
- game_state = paused;
- message (_("Game paused"));
- redraw_all ();
- update_move_menu_sensitivity ();
- gtk_action_set_sensitive (hint_action, FALSE);
- gtk_action_set_sensitive (solve_action, FALSE);
- games_clock_stop (GAMES_CLOCK (timer));
- }
-}
-
-void
-resume_game (void)
-{
- if (game_state == paused) {
- game_state = playing;
- message ("");
- redraw_all ();
- update_move_menu_sensitivity ();
- gtk_action_set_sensitive (hint_action, TRUE);
- gtk_action_set_sensitive (solve_action, TRUE);
- games_clock_start (GAMES_CLOCK (timer));
- }
-}
-
-void
+static void
pause_cb (void)
{
- if (game_state == gameover)
+ if (game_state == GAME_OVER)
return;
- if (game_state != paused) {
+ if (game_state != PAUSED) {
pause_game ();
} else {
resume_game ();
}
}
-void
-timer_start (void)
-{
- games_clock_stop (GAMES_CLOCK (timer));
- games_clock_reset (GAMES_CLOCK (timer));
- games_clock_start (GAMES_CLOCK (timer));
-}
-
-/* --------------------------- MENU --------------------- */
-GtkWidget *
-create_menu (GtkUIManager * ui_manager)
-{
- gint i;
- GtkActionGroup *action_group;
- GtkAction *action;
-
- action_group = gtk_action_group_new ("actions");
-
- gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
- gtk_action_group_add_actions (action_group, action_entry,
- G_N_ELEMENTS (action_entry), window);
- gtk_action_group_add_radio_actions (action_group, size_action_entry,
- G_N_ELEMENTS (size_action_entry), -1,
- G_CALLBACK (size_cb), NULL);
-
- gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
- gtk_ui_manager_add_ui_from_string (ui_manager, ui_description, -1, NULL);
-
- new_game_action = gtk_action_group_get_action (action_group, "NewGame");
- hint_action = gtk_action_group_get_action (action_group, "Hint");
- solve_action = gtk_action_group_get_action (action_group, "Solve");
- scores_action = gtk_action_group_get_action (action_group, "Scores");
- move_up_action = gtk_action_group_get_action (action_group, "MoveUp");
- move_left_action = gtk_action_group_get_action (action_group, "MoveLeft");
- move_right_action = gtk_action_group_get_action (action_group, "MoveRight");
- move_down_action = gtk_action_group_get_action (action_group, "MoveDown");
- pause_action = GTK_ACTION (games_pause_action_new ("PauseGame"));
- g_signal_connect (G_OBJECT (pause_action), "state-changed", G_CALLBACK (pause_cb), NULL);
- gtk_action_group_add_action_with_accel (action_group, pause_action, NULL);
- fullscreen_action = GTK_ACTION (games_fullscreen_action_new ("Fullscreen", GTK_WINDOW(window)));
- gtk_action_group_add_action_with_accel (action_group, fullscreen_action, NULL);
-
- gtk_action_group_add_toggle_actions (action_group, toggles,
- G_N_ELEMENTS (toggles), NULL);
- action = gtk_action_group_get_action (action_group, "ClickToMove");
- gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), click_to_move);
-
- for (i = 0; i < G_N_ELEMENTS (size_action_entry); i++)
- size_action[i] =
- gtk_action_group_get_action (action_group, size_action_entry[i].name);
-
- return gtk_ui_manager_get_widget (ui_manager, "/MainMenu");
-}
-
-void
-make_buffer (GtkWidget * widget)
-{
- GtkAllocation allocation;
-
- if (buffer)
- g_object_unref (buffer);
-
- gtk_widget_get_allocation (widget, &allocation);
- buffer = gdk_pixmap_new (gtk_widget_get_window (widget),
- allocation.width,
- allocation.height, -1);
-}
-
-void
-new_game (void){
- gchar *str;
-
- /* Reset pause menu */
- gtk_action_set_sensitive(pause_action, TRUE);
-
- game_state = gameover;
-
- new_board (size);
- gtk_widget_freeze_child_notify (space);
- make_buffer (space);
- redraw_all ();
- gtk_widget_thaw_child_notify (space);
- timer_start ();
- set_game_menu_items_sensitive (TRUE);
- update_move_menu_sensitivity ();
- str = g_strdup_printf (_("Playing %d\303\227%d board"), size, size);
- message (str);
- g_free (str);
-
- game_state = playing;
-}
-
-void
-new_game_cb (GtkAction * action, gpointer data)
-{
- new_game ();
-}
-
-void
-quit_game_cb (void)
-{
- gtk_main_quit ();
-}
-
#ifdef WITH_SMCLIENT
static int
save_state_cb (EggSMClient *client,
@@ -1724,79 +1500,7 @@ save_state_cb (EggSMClient *client,
return TRUE;
}
-static gint
-quit_cb (EggSMClient *client,
- gpointer client_data)
-{
- quit_game_cb ();
-
- return FALSE;
-}
-
-#endif /* WITH_SMCLIENT */
-
-void
-size_cb (GtkAction * action, gpointer data)
-{
- gint newsize;
- gint width, height;
-
- newsize = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action));
-
- gdk_drawable_get_size (gtk_widget_get_window (space), &width, &height);
-
- if (game_state == paused)
- gtk_action_activate (pause_action);
-
- if (size == newsize)
- return;
- size = newsize;
- update_tile_size (width, height);
- games_scores_set_category (highscores, scorecats[size - 2].key);
- games_conf_set_integer (NULL, KEY_GRID_SIZE, size);
- gtk_action_activate (new_game_action);
-}
-
-void
-clickmove_toggle_cb(GtkToggleAction * togglebutton, gpointer data)
-{
- click_to_move = gtk_toggle_action_get_active (togglebutton);
- games_conf_set_boolean (NULL, KEY_CLICK_MOVE, click_to_move);
-}
-
-void
-move_up_cb (GtkAction * action, gpointer data)
-{
- move_column ('n');
-}
-
-void
-move_left_cb (GtkAction * action, gpointer data)
-{
- move_column ('w');
-}
-
-void
-move_right_cb (GtkAction * action, gpointer data)
-{
- move_column ('e');
-}
-
-void
-move_down_cb (GtkAction * action, gpointer data)
-{
- move_column ('s');
-}
-
-gint
-compare_tile (tile * t1, tile * t2)
-{
- if (t1->e == t2->e && t1->w == t2->w && t1->s == t2->s && t1->n == t2->n)
- return 0;
- return 1;
-}
-
-void
+static void
find_first_tile (gint status, gint * xx, gint * yy)
{
gint x, y;
@@ -1809,101 +1513,28 @@ find_first_tile (gint status, gint * xx, gint * yy)
}
}
-#define LONG_COUNT 15
-#define SHORT_COUNT 5
-#define DELAY 10
-
-gint animcount;
-gboolean swapanim;
-gint move_src_x, move_src_y, move_dest_x, move_dest_y;
-
-void
-move_cb (void)
+static gboolean
+tiles_match (Tile * t1, Tile * t2)
{
- float dx, dy;
- static gint count = 0;
- dx = (float) (move_src_x - move_dest_x) / animcount;
- dy = (float) (move_src_y - move_dest_y) / animcount;
- if (count <= animcount) {
- gdk_window_move (automover.window, move_src_x - (gint) (count * dx),
- (gint) move_src_y - (gint) (count * dy));
- count++;
- }
- if (count > animcount) {
- count = 0;
- place_tile (move_dest_x + 1, move_dest_y + 1);
- moving = 0;
- g_source_remove (timer_timeout);
- gtk_widget_set_sensitive (GTK_WIDGET (space), TRUE);
-
- if(swapanim) {
- move_held_animate (mousemover.x, mousemover.y, automover.xstart, automover.ystart);
- return;
- }
-
- if (game_state != playing)
- return;
- if (solve_me)
- gtk_action_activate (hint_action);
- }
+ if (t1->e == t2->e && t1->w == t2->w && t1->s == t2->s && t1->n == t2->n)
+ return FALSE;
+ return TRUE;
}
-void
+static void
hint_move (gint x1, gint y1, gint x2, gint y2)
{
have_been_hinted = 1;
move_tile_animate (x1, y1, x2, y2, FALSE);
}
-void
-move_tile_animate (gint x1, gint y1, gint x2, gint y2, gboolean sa)
-{
- get_pixeltilexy (x1, y1, &move_src_x, &move_src_y);
- get_pixeltilexy (x2, y2, &move_dest_x, &move_dest_y);
-
- setup_mover (move_src_x, move_src_y, &automover);
- automover.xend = x2;
- automover.yend = y2;
- moving = 1;
- animcount = LONG_COUNT;
- swapanim = sa;
- gtk_widget_set_sensitive (GTK_WIDGET (space), FALSE);
- timer_timeout = g_timeout_add (DELAY, (GSourceFunc) (move_cb), NULL);
-}
-
-void
-move_held_animate (gint x, gint y, gint tx, gint ty) {
- /* Need to take over movement from mouse mover to auto mover */
- gint xx, yy;
- move_src_x = x - mousemover.xoff;
- move_src_y = y - mousemover.yoff;
- get_tilexy (move_src_x, move_src_y, &xx, &yy);
- get_pixeltilexy (tx, ty, &move_dest_x, &move_dest_y);
-
- clear_mover(&automover);
- automover = mousemover;
- mousemover.window = NULL;
- mousemover.pixmap = NULL;
-
- automover.xend = tx;
- automover.yend = ty;
- moving = 1;
- if(xx == tx && yy == ty)
- animcount = SHORT_COUNT;
- else
- animcount = LONG_COUNT;
- swapanim = FALSE;
- gtk_widget_set_sensitive (GTK_WIDGET (space), FALSE);
- timer_timeout = g_timeout_add (DELAY, (GSourceFunc) (move_cb), NULL);
-}
-
-void
+static void
hint_cb (GtkAction * action, gpointer data)
{
gint x1, y1, x2 = 0, y2 = 0, x = 0, y = 0;
- tile hint_tile;
+ Tile hint_tile;
- if ((game_state != playing) || button_down || moving)
+ if ((game_state != PLAYING) || button_down || moving)
return;
find_first_tile (USED, &x, &y);
@@ -1914,9 +1545,9 @@ hint_cb (GtkAction * action, gpointer data)
/* Find position in original map */
for (y = 0; y < size; y++)
for (x = 0; x < size; x++)
- if (compare_tile (&hint_tile, &orig_tiles[y][x]) == 0) {
+ if (!tiles_match (&hint_tile, &orig_tiles[y][x])) {
if (tiles[y][x].status == USED
- && compare_tile (&hint_tile, &tiles[y][x]) == 0) {
+ && !tiles_match (&hint_tile, &tiles[y][x])) {
/* Do Nothing */
} else {
x2 = x;
@@ -1968,20 +1599,20 @@ hint_cb (GtkAction * action, gpointer data)
hint_move (x1, y1, x2, y2);
}
-void
+static void
solve_cb (GtkAction * action, gpointer data)
{
solve_me = 1;
gtk_action_activate (hint_action);
}
-void
+static void
help_cb (GtkAction * action, gpointer data)
{
games_help_display (window, "gnotravex", NULL);
}
-void
+static void
about_cb (GtkAction * action, gpointer data)
{
const gchar *authors[] = { "Lars Rydlinge", NULL };
@@ -2016,13 +1647,77 @@ about_cb (GtkAction * action, gpointer data)
g_free (license);
}
+static gint
+quit_cb (EggSMClient *client,
+ gpointer client_data)
+{
+ quit_game_cb ();
+
+ return FALSE;
+}
+
+#endif /* WITH_SMCLIENT */
+
static void
-load_default_background (void)
+size_cb (GtkAction * action, gpointer data)
+{
+ gint newsize;
+ gint width, height;
+
+ newsize = gtk_radio_action_get_current_value (GTK_RADIO_ACTION (action));
+
+ gdk_drawable_get_size (gtk_widget_get_window (space), &width, &height);
+
+ if (game_state == PAUSED)
+ gtk_action_activate (pause_action);
+
+ if (size == newsize)
+ return;
+ size = newsize;
+ update_tile_size (width, height);
+ games_scores_set_category (highscores, scorecats[size - 2].key);
+ games_conf_set_integer (NULL, KEY_GRID_SIZE, size);
+ gtk_action_activate (new_game_action);
+}
+
+static void
+clickmove_toggle_cb(GtkToggleAction * togglebutton, gpointer data)
+{
+ click_to_move = gtk_toggle_action_get_active (togglebutton);
+ games_conf_set_boolean (NULL, KEY_CLICK_MOVE, click_to_move);
+}
+
+static void
+move_up_cb (GtkAction * action, gpointer data)
+{
+ move_column ('n');
+}
+
+static void
+move_left_cb (GtkAction * action, gpointer data)
+{
+ move_column ('w');
+}
+
+static void
+move_right_cb (GtkAction * action, gpointer data)
+{
+ move_column ('e');
+}
+
+static void
+move_down_cb (GtkAction * action, gpointer data)
+{
+ move_column ('s');
+}
+
+static void
+load_background (void)
{
GdkPixmap *pm;
GdkPixbuf *pb;
char *path;
- const char * dname;
+ const char * dname;
const char * filename = "baize.png";
GError *error = NULL;
@@ -2034,16 +1729,225 @@ load_default_background (void)
g_error_free (error);
pb = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
- FALSE,
+ FALSE,
8,1,1);
gdk_pixbuf_fill (pb, 0xffffffff);
}
gdk_pixbuf_render_pixmap_and_mask_for_colormap (pb,
- gdk_colormap_get_system (),
+ gdk_colormap_get_system (),
&pm, NULL, 127);
g_object_unref (pb);
g_free (path);
- default_background_pixmap = pm;
+ background_pixmap = pm;
+}
+static GtkWidget *
+create_menu (GtkUIManager * ui_manager)
+{
+ gint i;
+ GtkActionGroup *action_group;
+ GtkAction *action;
+ const GtkActionEntry action_entry[] = {
+ {"GameMenu", NULL, N_("_Game")},
+ {"MoveMenu", NULL, N_("_Move")},
+ {"SettingsMenu", NULL, N_("_Settings")},
+ {"SizeMenu", NULL, N_("_Size")},
+ {"HelpMenu", NULL, N_("_Help")},
+ {"NewGame", GAMES_STOCK_NEW_GAME, NULL, NULL, NULL,
+ G_CALLBACK (new_game_cb)},
+ {"Hint", GAMES_STOCK_HINT, NULL, NULL, NULL, G_CALLBACK (hint_cb)},
+ {"Solve", GTK_STOCK_REFRESH, N_("Sol_ve"), NULL, N_("Solve the game"),
+ G_CALLBACK (solve_cb)},
+ {"Scores", GAMES_STOCK_SCORES, NULL, NULL, NULL, G_CALLBACK (score_cb)},
+ {"Quit", GTK_STOCK_QUIT, NULL, NULL, NULL, G_CALLBACK (quit_game_cb)},
+ {"MoveUp", GTK_STOCK_GO_UP, N_("_Up"), "<control>Up",
+ N_("Move the pieces up"), G_CALLBACK (move_up_cb)},
+ {"MoveLeft", GTK_STOCK_GO_BACK, N_("_Left"), "<control>Left",
+ N_("Move the pieces left"), G_CALLBACK (move_left_cb)},
+ {"MoveRight", GTK_STOCK_GO_FORWARD, N_("_Right"), "<control>Right",
+ N_("Move the pieces right"), G_CALLBACK (move_right_cb)},
+ {"MoveDown", GTK_STOCK_GO_DOWN, N_("_Down"), "<control>Down",
+ N_("Move the pieces down"), G_CALLBACK (move_down_cb)},
+ {"Contents", GAMES_STOCK_CONTENTS, NULL, NULL, NULL, G_CALLBACK (help_cb)},
+ {"About", GTK_STOCK_ABOUT, NULL, NULL, NULL, G_CALLBACK (about_cb)}
+ };
+ const GtkToggleActionEntry toggles[] = {
+ {"ClickToMove", NULL, N_("_Click to Move"), NULL, "Pick up and drop tiles by clicking",
+ G_CALLBACK (clickmove_toggle_cb)}
+ };
+
+ action_group = gtk_action_group_new ("actions");
+
+ gtk_action_group_set_translation_domain (action_group, GETTEXT_PACKAGE);
+ gtk_action_group_add_actions (action_group, action_entry,
+ G_N_ELEMENTS (action_entry), window);
+ gtk_action_group_add_radio_actions (action_group, size_action_entry,
+ G_N_ELEMENTS (size_action_entry), -1,
+ G_CALLBACK (size_cb), NULL);
+
+ gtk_ui_manager_insert_action_group (ui_manager, action_group, 0);
+ gtk_ui_manager_add_ui_from_string (ui_manager, ui_description, -1, NULL);
+
+ new_game_action = gtk_action_group_get_action (action_group, "NewGame");
+ hint_action = gtk_action_group_get_action (action_group, "Hint");
+ solve_action = gtk_action_group_get_action (action_group, "Solve");
+ scores_action = gtk_action_group_get_action (action_group, "Scores");
+ move_up_action = gtk_action_group_get_action (action_group, "MoveUp");
+ move_left_action = gtk_action_group_get_action (action_group, "MoveLeft");
+ move_right_action = gtk_action_group_get_action (action_group, "MoveRight");
+ move_down_action = gtk_action_group_get_action (action_group, "MoveDown");
+ pause_action = GTK_ACTION (games_pause_action_new ("PauseGame"));
+ g_signal_connect (G_OBJECT (pause_action), "state-changed", G_CALLBACK (pause_cb), NULL);
+ gtk_action_group_add_action_with_accel (action_group, pause_action, NULL);
+ fullscreen_action = GTK_ACTION (games_fullscreen_action_new ("Fullscreen", GTK_WINDOW(window)));
+ gtk_action_group_add_action_with_accel (action_group, fullscreen_action, NULL);
+
+ gtk_action_group_add_toggle_actions (action_group, toggles,
+ G_N_ELEMENTS (toggles), NULL);
+ action = gtk_action_group_get_action (action_group, "ClickToMove");
+ gtk_toggle_action_set_active (GTK_TOGGLE_ACTION (action), click_to_move);
+
+ for (i = 0; i < G_N_ELEMENTS (size_action_entry); i++)
+ size_action[i] =
+ gtk_action_group_get_action (action_group, size_action_entry[i].name);
+
+ return gtk_ui_manager_get_widget (ui_manager, "/MainMenu");
+}
+
+int
+main (int argc, char **argv)
+{
+ GOptionContext *context;
+ GtkWidget *vbox;
+ GtkWidget *menubar;
+ GtkUIManager *ui_manager;
+ GtkAccelGroup *accel_group;
+ gboolean retval;
+ GError *error = NULL;
+#ifdef WITH_SMCLIENT
+ EggSMClient *sm_client;
+#endif /* WITH_SMCLIENT */
+
+ if (!games_runtime_init ("gnotravex"))
+ return 1;
+
+#ifdef ENABLE_SETGID
+ setgid_io_init ();
+#endif
+
+ context = g_option_context_new (NULL);
+#if GLIB_CHECK_VERSION (2, 12, 0)
+ g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
+#endif /* GLIB_CHECK_VERSION (2, 12, 0) */
+ g_option_context_add_group (context, gtk_get_option_group (TRUE));
+#ifdef WITH_SMCLIENT
+ g_option_context_add_group (context, egg_sm_client_get_option_group ());
+#endif /* WITH_SMCLIENT */
+
+ g_option_context_add_main_entries (context, options, GETTEXT_PACKAGE);
+ retval = g_option_context_parse (context, &argc, &argv, &error);
+
+ g_option_context_free (context);
+ if (!retval) {
+ g_print ("%s", error->message);
+ g_error_free (error);
+ exit (1);
+ }
+
+ g_set_application_name (_(APPNAME_LONG));
+
+ games_conf_initialise (APPNAME);
+
+ highscores = games_scores_new ("gnotravex",
+ scorecats, G_N_ELEMENTS (scorecats),
+ NULL, NULL,
+ 1 /* default category */,
+ GAMES_SCORES_STYLE_TIME_ASCENDING);
+
+ games_stock_init ();
+
+ gtk_window_set_default_icon_name ("gnome-tetravex");
+
+#ifdef WITH_SMCLIENT
+ sm_client = egg_sm_client_get ();
+ g_signal_connect (sm_client, "save-state",
+ G_CALLBACK (save_state_cb), NULL);
+ g_signal_connect (sm_client, "quit",
+ G_CALLBACK (quit_cb), NULL);
+#endif /* WITH_SMCLIENT */
+
+ if (size == -1)
+ size = games_conf_get_integer (NULL, KEY_GRID_SIZE, NULL);
+ if (size < 2 || size > 6)
+ size = 3;
+ games_scores_set_category (highscores, scorecats[size - 2].key);
+
+ click_to_move = games_conf_get_boolean (NULL, KEY_CLICK_MOVE, NULL);
+
+ load_background ();
+ create_window ();
+
+ space = gtk_drawing_area_new ();
+ gtk_widget_set_events (space,
+ GDK_EXPOSURE_MASK | GDK_BUTTON_PRESS_MASK
+ | GDK_POINTER_MOTION_MASK | GDK_BUTTON_RELEASE_MASK);
+
+ statusbar = create_statusbar ();
+
+ ui_manager = gtk_ui_manager_new ();
+ games_stock_prepare_for_statusbar_tooltips (ui_manager, statusbar);
+
+ menubar = create_menu (ui_manager);
+
+ vbox = gtk_vbox_new (FALSE, 0);
+ gtk_container_add (GTK_CONTAINER (window), vbox);
+
+ gtk_box_pack_start (GTK_BOX (vbox), menubar, FALSE, FALSE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), space, TRUE, TRUE, 0);
+ gtk_box_pack_start (GTK_BOX (vbox), statusbar, FALSE, FALSE, 0);
+
+ accel_group = gtk_ui_manager_get_accel_group (ui_manager);
+ gtk_window_add_accel_group (GTK_WINDOW (window), accel_group);
+
+ gtk_widget_realize (space);
+ bg_gc = gdk_gc_new (gtk_widget_get_window (space));
+ if (background_pixmap)
+ {
+ gdk_gc_set_tile (bg_gc, background_pixmap);
+ gdk_gc_set_fill (bg_gc, GDK_TILED);
+ }
+
+ g_signal_connect (G_OBJECT (space), "expose_event",
+ G_CALLBACK (expose_space), NULL);
+ g_signal_connect (G_OBJECT (space), "configure_event",
+ G_CALLBACK (configure_space), NULL);
+ g_signal_connect (G_OBJECT (space), "button_press_event",
+ G_CALLBACK (button_press_space), NULL);
+ g_signal_connect (G_OBJECT (space), "button_release_event",
+ G_CALLBACK (button_release_space), NULL);
+ g_signal_connect (G_OBJECT (space), "motion_notify_event",
+ G_CALLBACK (button_motion_space), NULL);
+ /* We do our own double-buffering. */
+ gtk_widget_set_double_buffered (space, FALSE);
+
+ gtk_widget_show (space);
+
+ if (session_xpos >= 0 && session_ypos >= 0)
+ gtk_window_move (GTK_WINDOW (window), session_xpos, session_ypos);
+
+ gtk_widget_show_all (window);
+ init_window_attrib ();
+
+ gtk_action_activate (new_game_action);
+
+ gtk_action_activate (size_action[size - 2]);
+
+ gtk_main ();
+
+ games_conf_shutdown ();
+
+ games_runtime_shutdown ();
+
+ return 0;
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]