[five-or-more] Split five-or-more.c The current code existing in five-or-more.c has been split into:
- From: Robert Roth <robertroth src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [five-or-more] Split five-or-more.c The current code existing in five-or-more.c has been split into:
- Date: Wed, 21 Mar 2018 00:56:33 +0000 (UTC)
commit 7294fa2d3e23fb2d1ab2eddf5a940128187239fc
Author: Karuna Grewal <karunagrewal98 gmail com>
Date: Sun Mar 18 18:28:21 2018 +0530
Split five-or-more.c The current code existing in five-or-more.c has been split into:
* five-or-more-app.c : Here all the callbacks to the application are connected,
followed by the general setting related to the application like background
color etc. are moved to this file
* game-area.c: Drawing area related code ,say, binding signals to callbacks,
or rendering the graphics, controlling the animation are handled here.
* balls-preview.c: This has the necessary functions for previewing.
Getters are used to access the static variables used across the appliaction
which weren't currently required since all the code was mash-up into
a single file.
https://bugzilla.gnome.org/show_bug.cgi?id=794273
po/POTFILES.in | 3 +
src/Makefile.am | 9 +-
src/balls-preview.c | 168 +++++
src/balls-preview.h | 35 +
src/five-or-more-app.c | 695 ++++++++++++++++++++
src/five-or-more-app.h | 51 ++
src/five-or-more.c | 1668 +-----------------------------------------------
src/five-or-more.h | 57 --
src/game-area.c | 1057 ++++++++++++++++++++++++++++++
src/game-area.h | 55 ++
src/meson.build | 6 +
11 files changed, 2084 insertions(+), 1720 deletions(-)
---
diff --git a/po/POTFILES.in b/po/POTFILES.in
index f354a02..980c576 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -9,3 +9,6 @@ data/org.gnome.five-or-more.gschema.xml
data/translatable_themes.h
src/five-or-more.c
src/games-scores-dialog.c
+src/five-or-more-app.c
+src/game-area.c
+src/balls-preview.c
diff --git a/src/Makefile.am b/src/Makefile.am
index 12edd52..79d7d95 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -2,7 +2,6 @@ bin_PROGRAMS = five-or-more
five_or_more_SOURCES = \
five-or-more.c \
- five-or-more.h \
games-file-list.c \
games-file-list.h \
games-gridframe.c \
@@ -16,7 +15,13 @@ five_or_more_SOURCES = \
games-scores-dialog.c \
games-scores-dialog.h \
games-scores-backend.c \
- games-scores-backend.h
+ games-scores-backend.h \
+ five-or-more-app.h \
+ five-or-more-app.c \
+ balls-preview.c \
+ balls-preview.h \
+ game-area.h \
+ game-area.c
five_or_more_CPPFLAGS = \
-I$(top_srcdir) \
diff --git a/src/balls-preview.c b/src/balls-preview.c
new file mode 100644
index 0000000..c68e3e0
--- /dev/null
+++ b/src/balls-preview.c
@@ -0,0 +1,168 @@
+/* -*- mode:C; indent-tabs-mode:t; tab-width:8; c-basic-offset:8; -*- */
+
+/*
+ * Color lines for GNOME
+ * Copyright © 1999 Free Software Foundation
+ * Authors: Robert Szokovacs <szo appaloosacorp hu>
+ * Szabolcs Ban <shooby gnome hu>
+ * Karuna Grewal <karunagrewal98 gmail com>
+ * Copyright © 2007 Christian Persch
+ *
+ * This game 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <locale.h>
+#include <math.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "games-preimage.h"
+#include "balls-preview.h"
+#include "game-area.h"
+
+#define MAXNPIECES 10
+#define PREVIEW_IMAGE_WIDTH 20
+#define PREVIEW_IMAGE_HEIGHT 20
+
+static GtkImage* preview_images[MAXNPIECES];
+static GdkPixbuf* preview_pixbufs[MAXNPIECES];
+static int preview[MAXNPIECES];
+
+void
+init_preview (void)
+{
+ int i;
+ gint npieces = get_npieces();
+ for (i = 0; i < npieces; i++) {
+ preview[i] = g_rand_int_range (*get_rgen(), 1, get_ncolors() + 1);
+ }
+}
+
+void
+draw_preview (void)
+{
+ guint i;
+ gint npieces = get_npieces();
+ /* This function can be called before the images are initialized */
+ if (!GTK_IS_IMAGE (preview_images[0]))
+ return;
+
+ for (i = 0; i < MAXNPIECES; i++) {
+ if (i < npieces)
+ gtk_image_set_from_pixbuf (preview_images[i], preview_pixbufs[preview[i] - 1]);
+ else
+ gtk_image_clear (preview_images[i]);
+ }
+}
+
+void
+refresh_preview_surfaces (void)
+{
+ guint i;
+ GdkPixbuf *scaled = NULL;
+ GtkWidget *widget = GTK_WIDGET (preview_images[0]);
+ GtkStyleContext *context;
+ GdkRGBA bg;
+ cairo_t *cr;
+ GdkRectangle preview_rect;
+ cairo_surface_t *blank_preview_surface = NULL;
+ /* The balls rendered to a size appropriate for the preview. */
+ cairo_surface_t *preview_surface = NULL;
+
+ context = gtk_widget_get_style_context (widget);
+ gtk_style_context_get_background_color (context, gtk_style_context_get_state (context), &bg);
+
+ /* Like the refresh_pixmaps() function, we may be called before
+ * the window is ready. */
+ if (PREVIEW_IMAGE_HEIGHT == 0)
+ return;
+
+ preview_rect.x = 0;
+ preview_rect.y = 0;
+ preview_rect.width = PREVIEW_IMAGE_WIDTH;
+ preview_rect.height = PREVIEW_IMAGE_HEIGHT;
+
+ /* We create pixmaps for each of the ball colours and then
+ * set them as the background for each widget in the preview array.
+ * This code assumes that each preview window is identical. */
+ GamesPreimage *ball_preimage = get_ball_preimage();
+ if (ball_preimage)
+ scaled = games_preimage_render (ball_preimage, 4 * PREVIEW_IMAGE_WIDTH,
+ 7 * PREVIEW_IMAGE_HEIGHT);
+
+ if (!scaled) {
+ scaled = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
+ 4 * PREVIEW_IMAGE_WIDTH, 7 * PREVIEW_IMAGE_HEIGHT);
+ gdk_pixbuf_fill (scaled, 0x00000000);
+ }
+
+ for (i = 0; i < 7; i++) {
+ preview_surface = gdk_window_create_similar_image_surface (gtk_widget_get_window (widget),
+ CAIRO_FORMAT_ARGB32,
+ PREVIEW_IMAGE_WIDTH, PREVIEW_IMAGE_HEIGHT, 1);
+ cr = cairo_create (preview_surface);
+ gdk_cairo_set_source_rgba (cr, &bg);
+ gdk_cairo_rectangle (cr, &preview_rect);
+ cairo_fill (cr);
+
+ gdk_cairo_set_source_pixbuf (cr, scaled, 0, -1.0 * PREVIEW_IMAGE_HEIGHT * i);
+ cairo_mask (cr, cairo_get_source (cr));
+
+ if (preview_pixbufs[i])
+ g_object_unref (preview_pixbufs[i]);
+
+ preview_pixbufs[i] = gdk_pixbuf_get_from_surface (preview_surface, 0, 0,
+ PREVIEW_IMAGE_WIDTH, PREVIEW_IMAGE_HEIGHT);
+
+ cairo_destroy (cr);
+ cairo_surface_destroy (preview_surface);
+ }
+
+ blank_preview_surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ PREVIEW_IMAGE_WIDTH, PREVIEW_IMAGE_HEIGHT);
+ cr = cairo_create (blank_preview_surface);
+ gdk_cairo_set_source_rgba (cr, &bg);
+ gdk_cairo_rectangle (cr, &preview_rect);
+ cairo_fill (cr);
+
+ cairo_surface_destroy (blank_preview_surface);
+ cairo_destroy (cr);
+ g_object_unref (scaled);
+}
+
+GtkImage **
+get_preview_images()
+{
+ return preview_images;
+}
+
+int *
+get_preview()
+{
+ return preview;
+}
+
+GdkPixbuf **
+get_preview_pixbufs()
+{
+ return preview_pixbufs;
+}
\ No newline at end of file
diff --git a/src/balls-preview.h b/src/balls-preview.h
new file mode 100644
index 0000000..13fa64f
--- /dev/null
+++ b/src/balls-preview.h
@@ -0,0 +1,35 @@
+/*
+ * Color lines for GNOME
+ * Copyright © 1999 Free Software Foundation
+ * Authors: Robert Szokovacs <szo appaloosacorp hu>
+ * Szabolcs Ban <shooby gnome hu>
+ * Karuna Grewal <karunagrewal98 gmail com>
+ * Copyright © 2007 Christian Persch
+ *
+ * This game 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef BALLS_PREVIEW_H
+#define BALLS_PREVIEW_H
+
+#include <gtk/gtk.h>
+
+void init_preview (void);
+void draw_preview (void);
+void refresh_preview_surfaces (void);
+GtkImage **get_preview_images ();
+int * get_preview ();
+GdkPixbuf **get_preview_pixbufs ();
+
+#endif
\ No newline at end of file
diff --git a/src/five-or-more-app.c b/src/five-or-more-app.c
new file mode 100644
index 0000000..8c94ddc
--- /dev/null
+++ b/src/five-or-more-app.c
@@ -0,0 +1,695 @@
+/* -*- mode:C; indent-tabs-mode:t; tab-width:8; c-basic-offset:8; -*- */
+
+/*
+ * Color lines for GNOME
+ * Copyright © 1999 Free Software Foundation
+ * Authors: Robert Szokovacs <szo appaloosacorp hu>
+ * Szabolcs Ban <shooby gnome hu>
+ * Karuna Grewal <karunagrewal98 gmail com>
+ * Copyright © 2007 Christian Persch
+ *
+ * This game 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <locale.h>
+#include <math.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "games-file-list.h"
+#include "games-preimage.h"
+#include "games-gridframe.h"
+#include "games-scores.h"
+#include "games-scores-dialog.h"
+#include "game-area.h"
+#include "five-or-more-app.h"
+#include "balls-preview.h"
+
+#define DEFAULT_GAME_SIZE MEDIUM
+#define KEY_SIZE "size"
+#define MAXNPIECES 10
+#define KEY_MOVE_TIMEOUT "move-timeout"
+#define KEY_BACKGROUND_COLOR "background-color"
+#define KEY_BALL_THEME "ball-theme"
+
+static const GamesScoresCategory scorecats[] = {
+ { "Small", NC_("board size", "Small") },
+ { "Medium", NC_("board size", "Medium") },
+ { "Large", NC_("board size", "Large") }
+};
+
+enum {
+ UNSET = 0,
+ SMALL = 1,
+ MEDIUM,
+ LARGE,
+ MAX_SIZE,
+};
+
+static background backgnd = { { 0, 0, 0, 0}, NULL, 0 };
+static GtkWidget *gridframe;
+static GtkWidget *app, *headerbar, *restart_game_dialog, *pref_dialog;
+
+static char *ball_filename;
+static gint game_size = UNSET;
+static gboolean pref_dialog_done = FALSE;
+static GamesFileList *theme_file_list = NULL;
+static GtkWidget *size_radio_s, *size_radio_m, *size_radio_l;
+
+static int move_timeout = 100;
+static gboolean window_is_fullscreen = FALSE, window_is_maximized = FALSE;
+static gint window_width = 0, window_height = 0;
+static GamesScores *highscores;
+static GSettings *settings;
+static GtkBuilder *builder;
+static GtkBuilder *builder_preferences;
+
+static guint score = 0;
+static GtkWidget *scorelabel;
+
+/*getter funcs*/
+
+GSettings **
+get_settings ()
+{
+ return &settings;
+}
+
+const GamesScoresCategory *
+get_scorecats ()
+{
+ return scorecats;
+}
+
+gint *
+get_game_size ()
+{
+ return &game_size;
+}
+
+GtkWidget *
+get_gridframe ()
+{
+ return gridframe;
+}
+
+char *
+get_ball_filename ()
+{
+ return ball_filename;
+}
+
+background
+get_backgnd ()
+{
+ return backgnd;
+}
+
+int
+get_move_timeout ()
+{
+ return move_timeout;
+}
+
+GamesScores *
+get_highscores()
+{
+ return highscores;
+}
+
+void
+update_score (guint value)
+{
+ char string[20];
+ if(value)
+ score += value;
+ else
+ score = value;
+ g_snprintf (string, 19, "%d", score);
+ gtk_label_set_text (GTK_LABEL (scorelabel), string);
+}
+
+void
+set_status_message (gchar * message)
+{
+ gtk_header_bar_set_subtitle (GTK_HEADER_BAR (headerbar), message);
+}
+
+static void
+set_backgnd_color (const gchar * str)
+{
+ if (!str)
+ str = g_strdup ("#000000");
+
+ if (str != backgnd.name) {
+ g_free (backgnd.name);
+ backgnd.name = g_strdup (str);
+ }
+
+ if (!gdk_rgba_parse (&backgnd.color, backgnd.name)) {
+ gdk_rgba_parse (&backgnd.color, "#000000");
+ }
+}
+
+static void
+show_scores (gint pos)
+{
+ static GtkWidget *dialog;
+
+ if (dialog == NULL) {
+ dialog = games_scores_dialog_new (GTK_WINDOW (app), highscores, _("Five or More Scores"));
+ games_scores_dialog_set_category_description (GAMES_SCORES_DIALOG
+ (dialog), _("_Board size:"));
+ }
+
+ if (pos > 0) {
+ games_scores_dialog_set_hilight (GAMES_SCORES_DIALOG (dialog), pos);
+ }
+
+ gtk_window_present (GTK_WINDOW (dialog));
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_hide (dialog);
+}
+
+static void
+load_properties (void)
+{
+ gchar *buf;
+ ball_filename = g_settings_get_string (settings, KEY_BALL_THEME);
+
+ move_timeout = g_settings_get_int (settings, KEY_MOVE_TIMEOUT);
+ if (move_timeout <= 0)
+ move_timeout = 100;
+
+ buf = g_settings_get_string (settings, KEY_BACKGROUND_COLOR); /* FIXMEchpe? */
+ set_backgnd_color (buf);
+ g_free (buf);
+ load_theme ();
+}
+
+void
+game_over (void)
+{
+ int pos;
+
+ set_status_message (_("Game Over!"));
+ if (score > 0)
+ pos = games_scores_add_plain_score (highscores, score);
+ show_scores (pos);
+}
+
+static void
+start_game (void)
+{
+ set_status_message (_("Match five objects of the same type in a row to score!"));
+ refresh_screen ();
+ update_score(0);
+ set_inmove (0);
+}
+
+static void
+conf_value_changed_cb (GSettings *settings, gchar *key)
+{
+ if (strcmp (key, KEY_BACKGROUND_COLOR) == 0) {
+ gchar *color;
+ color = g_settings_get_string (settings, KEY_BACKGROUND_COLOR);
+ if (color != NULL) {
+ set_backgnd_color (color);
+ g_free (color);
+ }
+ } else if (strcmp (key, KEY_BALL_THEME) == 0) {
+ gchar *theme_tmp = NULL;
+
+ theme_tmp = g_settings_get_string (settings, KEY_BALL_THEME);
+ if (theme_tmp) {
+ if (strcmp (theme_tmp, ball_filename) != 0) {
+ g_free (ball_filename);
+ ball_filename = theme_tmp;
+ load_theme ();
+ refresh_screen ();
+ } else
+ g_free (theme_tmp);
+ }
+ /* FIXME apply in the prefs dialog GUI */
+ } else if (strcmp (key, KEY_MOVE_TIMEOUT) == 0) {
+ gint timeout_tmp;
+
+ timeout_tmp = g_settings_get_int (settings, KEY_MOVE_TIMEOUT);
+ timeout_tmp = CLAMP (timeout_tmp, 1, 1000);
+ if (timeout_tmp != move_timeout)
+ move_timeout = timeout_tmp;
+
+ } else if (strcmp (key, KEY_SIZE) == 0) {
+ gint size_tmp;
+ size_tmp = g_settings_get_int (settings, KEY_SIZE);
+
+ if (size_tmp != game_size) {
+ set_sizes (size_tmp);
+ reset_game ();
+ start_game ();
+ }
+ }
+}
+
+static void
+init_config (void)
+{
+ g_signal_connect (settings, "changed",
+ G_CALLBACK (conf_value_changed_cb), NULL);
+
+ game_size = g_settings_get_int (settings, KEY_SIZE);
+ if (game_size == UNSET)
+ game_size = DEFAULT_GAME_SIZE;
+
+ game_size = CLAMP (game_size, SMALL, MAX_SIZE - 1);
+
+ set_sizes (game_size);
+}
+
+static gboolean
+window_size_allocate_cb (GtkWidget *widget, GdkRectangle *allocation)
+{
+ if (!window_is_maximized && !window_is_fullscreen)
+ gtk_window_get_size (GTK_WINDOW (widget), &window_width, &window_height);
+
+ return FALSE;
+}
+
+static gboolean
+window_state_event_cb (GtkWidget *widget, GdkEventWindowState *event)
+{
+ if ((event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) != 0)
+ window_is_maximized = (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
+ if ((event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) != 0)
+ window_is_fullscreen = (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0;
+ return FALSE;
+}
+
+
+void
+game_new_callback (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ reset_game ();
+ start_game ();
+}
+
+void
+game_top_ten_callback (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ show_scores (0);
+}
+
+
+static void
+set_selection (GtkWidget * widget, char *data)
+{
+ const gchar *entry;
+
+ entry = games_file_list_get_nth (theme_file_list,
+ gtk_combo_box_get_active (GTK_COMBO_BOX
+ (widget)));
+ g_settings_set_string (settings, KEY_BALL_THEME, entry);
+}
+
+
+
+void
+pref_dialog_response (GtkDialog * dialog, gint response, gpointer data)
+{
+ gtk_widget_hide (GTK_WIDGET (dialog));
+}
+
+static void
+bg_color_callback (GtkWidget * widget, gpointer data)
+{
+ GdkRGBA c;
+ char str[64];
+
+ gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (widget), &c);
+
+ g_snprintf (str, sizeof (str), "#%04x%04x%04x", (int) (c.red * 65535 + 0.5), (int) (c.green * 65535 +
0.5), (int) (c.blue * 65535 + 0.5));
+
+ g_settings_set_string (settings, KEY_BACKGROUND_COLOR, str);
+ //area,h
+ load_theme ();
+ //area.h
+ refresh_screen ();
+}
+
+static void
+size_callback (GtkWidget * widget, gpointer data)
+{
+ GtkWidget *size_radio, *content_area, *label;
+
+ game_size = g_settings_get_int (settings, KEY_SIZE);
+ if (pref_dialog_done && game_size != GPOINTER_TO_INT (data) && !restart_game_dialog) {
+ GtkDialogFlags flags = GTK_DIALOG_DESTROY_WITH_PARENT;
+
+ restart_game_dialog = gtk_message_dialog_new (GTK_WINDOW (pref_dialog),
+ GTK_MESSAGE_WARNING,
+ flags,
+ GTK_BUTTONS_NONE,
+ _("Are you sure you want to restart the game?"));
+
+ gtk_dialog_add_buttons (GTK_DIALOG (restart_game_dialog),
+ _("_Cancel"), GTK_RESPONSE_CANCEL,
+ _("_Restart"), GTK_RESPONSE_OK,
+ NULL);
+
+ gint result = gtk_dialog_run (GTK_DIALOG (restart_game_dialog));
+ gtk_widget_destroy (restart_game_dialog);
+
+ switch (result) {
+ case GTK_RESPONSE_OK:
+ g_settings_set_int (settings, KEY_SIZE, GPOINTER_TO_INT (data));
+ break;
+ case GTK_RESPONSE_CANCEL:
+ switch (game_size) {
+ case SMALL:
+ size_radio = size_radio_s;
+ break;
+ case MEDIUM:
+ size_radio = size_radio_m;
+ break;
+ case LARGE:
+ size_radio = size_radio_l;
+ break;
+ }
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (size_radio), TRUE);
+ }
+
+ restart_game_dialog = NULL;
+ }
+}
+
+static GtkWidget *
+fill_menu (void)
+{
+ gchar *pixmap_dir;
+
+ if (theme_file_list)
+ g_object_unref (theme_file_list);
+
+ pixmap_dir = g_build_filename (DATA_DIRECTORY, "themes", NULL);
+ theme_file_list = games_file_list_new_images (pixmap_dir, NULL);
+ g_free (pixmap_dir);
+ games_file_list_transform_basename (theme_file_list);
+
+ return games_file_list_create_widget (theme_file_list, ball_filename,
+ GAMES_FILE_LIST_REMOVE_EXTENSION |
+ GAMES_FILE_LIST_REPLACE_UNDERSCORES);
+}
+
+static void
+set_fast_moves_callback (GtkWidget * widget, gpointer * data)
+{
+ gboolean is_on = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
+ gint timeout = is_on ? 10 : 100;
+ g_settings_set_int (settings, KEY_MOVE_TIMEOUT, timeout);
+}
+
+void
+game_props_callback (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ gchar *ui_path;
+ GError *error = NULL;
+ GtkWidget *omenu;
+ GtkWidget *grid;
+ GtkWidget *color_button;
+ GtkWidget *size_radio;
+ GtkWidget *fast_moves_checkbutton;
+
+ if (!pref_dialog) {
+ ui_path = g_build_filename (DATA_DIRECTORY, "five-or-more-preferences.ui", NULL);
+ builder_preferences = gtk_builder_new ();
+ gtk_builder_add_from_file (builder_preferences, ui_path, &error);
+ g_free (ui_path);
+
+ if (error) {
+ g_critical ("Unable to load the user interface file: %s", error->message);
+ g_error_free (error);
+ g_assert_not_reached ();
+ }
+
+ pref_dialog = GTK_WIDGET (gtk_builder_get_object (builder_preferences, "preferences_dialog"));
+ g_signal_connect (pref_dialog, "response",
+ G_CALLBACK (pref_dialog_response), NULL);
+ g_signal_connect (pref_dialog, "delete-event",
+ G_CALLBACK (gtk_widget_hide), NULL);
+
+ grid = GTK_WIDGET (gtk_builder_get_object (builder_preferences, "grid1"));
+ omenu = fill_menu ();
+ gtk_widget_show_all (GTK_WIDGET (omenu));
+ gtk_grid_attach (GTK_GRID (grid), GTK_WIDGET (omenu), 1, 0, 1, 1);
+ g_signal_connect (omenu, "changed",
+ G_CALLBACK (set_selection), NULL);
+
+ color_button = GTK_WIDGET (gtk_builder_get_object (builder_preferences, "colorbutton1"));
+ gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (color_button), &backgnd.color);
+ g_signal_connect (color_button, "color-set",
+ G_CALLBACK (bg_color_callback), NULL);
+
+ size_radio = GTK_WIDGET (gtk_builder_get_object (builder_preferences, "radiobutton_small"));
+ size_radio_s = size_radio;
+ g_signal_connect (size_radio, "clicked",
+ G_CALLBACK (size_callback), GINT_TO_POINTER (1));
+ if (game_size == SMALL)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (size_radio), TRUE);
+
+ size_radio = GTK_WIDGET (gtk_builder_get_object (builder_preferences, "radiobutton_medium"));
+ size_radio_m = size_radio;
+ g_signal_connect (size_radio, "clicked",
+ G_CALLBACK (size_callback), GINT_TO_POINTER (2));
+ if (game_size == MEDIUM)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (size_radio), TRUE);
+
+ size_radio = GTK_WIDGET (gtk_builder_get_object (builder_preferences, "radiobutton_large"));
+ size_radio_l = size_radio;
+ g_signal_connect (size_radio, "clicked",
+ G_CALLBACK (size_callback), GINT_TO_POINTER (3));
+ if (game_size == LARGE)
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (size_radio), TRUE);
+
+ fast_moves_checkbutton = GTK_WIDGET (gtk_builder_get_object (builder_preferences,
"checkbutton_fast_moves"));
+ if (move_timeout == 10) {
+ gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fast_moves_checkbutton), TRUE);
+ }
+
+ g_signal_connect (fast_moves_checkbutton, "clicked",
+ G_CALLBACK (set_fast_moves_callback), NULL);
+
+ g_object_unref (G_OBJECT (builder_preferences));
+
+ pref_dialog_done = TRUE;
+ gtk_window_set_transient_for (GTK_WINDOW (pref_dialog), GTK_WINDOW (app));
+ }
+ gtk_dialog_run (GTK_DIALOG (pref_dialog));
+}
+
+void
+game_help_callback (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ GError *error = NULL;
+
+ gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (app)), "help:five-or-more", gtk_get_current_event_time
(), &error);
+ if (error)
+ g_warning ("Failed to show help: %s", error->message);
+ g_clear_error (&error);
+}
+
+void
+game_about_callback (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ const gchar *authors[] = { "Robert Szokovacs <szo appaloosacorp hu>",
+ "Szabolcs B\xc3\xa1n <shooby gnome hu>",
+ NULL
+ };
+
+ const gchar *documenters[] = { "Tiffany Antopolski",
+ "Lanka Rathnayaka",
+ NULL
+ };
+
+ gtk_show_about_dialog (GTK_WINDOW (app),
+ "program-name", _("Five or More"),
+ "version", VERSION,
+ "comments", _("GNOME port of the once-popular Color Lines game"),
+ "copyright",
+ "Copyright © 1997–2008 Free Software Foundation, Inc.\n Copyright © 2013–2014
Michael Catanzaro",
+ "license-type", GTK_LICENSE_GPL_2_0,
+ "authors", authors,
+ "documenters", documenters,
+ "translator-credits", _("translator-credits"),
+ "logo-icon-name", "five-or-more",
+ "website", "https://wiki.gnome.org/Apps/Five%20or%20more",
+ NULL);
+}
+
+void
+game_quit_callback (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data)
+{
+ g_application_quit (G_APPLICATION (user_data));
+}
+
+void
+startup_cb (GApplication *application)
+{
+ gchar *ui_path;
+ GtkWidget *hbox;
+ GtkWidget *preview_hbox;
+ GtkWidget *new_game_button;
+ guint i;
+ GError *error = NULL;
+
+ GActionEntry app_actions[] = {
+ { "new-game", game_new_callback },
+ { "scores", game_top_ten_callback },
+ { "preferences", game_props_callback },
+ { "help", game_help_callback },
+ { "about", game_about_callback },
+ { "quit", game_quit_callback }
+ };
+
+ g_action_map_add_action_entries (G_ACTION_MAP (application),
+ app_actions, G_N_ELEMENTS (app_actions),
+ application);
+
+ gtk_application_add_accelerator (GTK_APPLICATION (application), "<Primary>N", "app.new-game", NULL);
+
+ settings = g_settings_new ("org.gnome.five-or-more");
+
+ highscores = games_scores_new ("five-or-more",
+ scorecats, G_N_ELEMENTS (scorecats),
+ "board size", NULL,
+ 0 /* default category */,
+ GAMES_SCORES_STYLE_PLAIN_DESCENDING);
+ init_config ();
+ builder = gtk_builder_new ();
+ ui_path = g_build_filename (DATA_DIRECTORY, "menu.ui", NULL);
+ gtk_builder_add_from_file (builder, ui_path, &error);
+ g_free (ui_path);
+
+ if (error) {
+ g_critical ("Unable to load the application menu file: %s", error->message);
+ g_error_free (error);
+ } else {
+ gtk_application_set_app_menu (GTK_APPLICATION (application),
+ G_MENU_MODEL (gtk_builder_get_object (builder, "appmenu")));
+ }
+
+ ui_path = g_build_filename (DATA_DIRECTORY, "five-or-more.ui", NULL);
+ gtk_builder_add_from_file (builder, ui_path, &error);
+ g_free (ui_path);
+
+ if (error) {
+ g_critical ("Unable to load the user interface file: %s", error->message);
+ g_error_free (error);
+ g_assert_not_reached ();
+ }
+
+ app = GTK_WIDGET (gtk_builder_get_object (builder, "glines_window"));
+ gtk_window_set_icon_name (GTK_WINDOW (app), "five-or-more");
+ g_signal_connect (GTK_WINDOW (app), "size-allocate", G_CALLBACK (window_size_allocate_cb), NULL);
+ g_signal_connect (GTK_WINDOW (app), "window-state-event", G_CALLBACK (window_state_event_cb), NULL);
+ gtk_window_set_default_size (GTK_WINDOW (app), g_settings_get_int (settings, "window-width"),
g_settings_get_int (settings, "window-height"));
+ if (g_settings_get_boolean (settings, "window-is-maximized"))
+ gtk_window_maximize (GTK_WINDOW (app));
+ gtk_container_set_border_width (GTK_CONTAINER (app), 20);
+ gtk_application_add_window (GTK_APPLICATION (application), GTK_WINDOW (app));
+
+ headerbar = GTK_WIDGET (gtk_builder_get_object (builder, "headerbar"));
+
+ GtkImage **preview_images = get_preview_images();
+ preview_hbox = GTK_WIDGET (gtk_builder_get_object (builder, "preview_hbox"));
+ for (i = 0; i < MAXNPIECES; i++) {
+ //preview images getter req this is defiend in src or here
+ preview_images[i] = GTK_IMAGE (gtk_image_new ());
+ gtk_box_pack_start (GTK_BOX (preview_hbox), GTK_WIDGET (preview_images[i]), FALSE, FALSE, 0);
+ gtk_widget_realize (GTK_WIDGET (preview_images[i]));
+ }
+
+ scorelabel = GTK_WIDGET (gtk_builder_get_object (builder, "scorelabel"));
+
+ hbox = GTK_WIDGET (gtk_builder_get_object (builder, "hbox"));
+
+ GtkWidget *draw_area = game_area_init ();
+
+ gridframe = games_grid_frame_new (get_hfieldsize(), get_vfieldsize());
+ games_grid_frame_set_padding (GAMES_GRID_FRAME (gridframe), 1, 1);
+ gtk_container_add (GTK_CONTAINER (gridframe), draw_area);
+ gtk_box_pack_start (GTK_BOX (hbox), gridframe, TRUE, TRUE, 0);
+
+ new_game_button = GTK_WIDGET (gtk_builder_get_object (builder, "new_game_button"));
+
+ load_properties ();
+
+ gtk_builder_connect_signals (builder, NULL);
+
+ g_object_unref (G_OBJECT (builder));
+}
+
+
+void
+activate_cb (GApplication *application)
+{
+ reset_game ();
+ gtk_widget_show_all (app);
+ start_game ();
+}
+
+void
+shutdown_cb (GApplication *application)
+{
+ int i = 0;
+ GtkImage **preview_images = get_preview_images();
+ GdkPixbuf **preview_pixbufs = get_preview_pixbufs();
+ for (i = 0; i < G_N_ELEMENTS (preview_images); i++)
+ if (preview_pixbufs[i])
+ g_object_unref (preview_pixbufs[i]);
+
+ GamesPreimage *ball_preimage = get_ball_preimage();
+ g_clear_object (&ball_preimage);
+ g_object_unref (highscores);
+
+ g_settings_set_int (settings, "window-width", window_width);
+ g_settings_set_int (settings, "window-height", window_height);
+ g_settings_set_boolean (settings, "window-is-maximized", window_is_maximized);
+}
+
+void
+set_application_callbacks(GtkApplication *application)
+{
+ g_signal_connect (application, "startup", G_CALLBACK (startup_cb), NULL);
+ g_signal_connect (application, "activate", G_CALLBACK (activate_cb), NULL);
+ g_signal_connect (application, "shutdown", G_CALLBACK (shutdown_cb), NULL);
+}
\ No newline at end of file
diff --git a/src/five-or-more-app.h b/src/five-or-more-app.h
new file mode 100644
index 0000000..6e9a6b6
--- /dev/null
+++ b/src/five-or-more-app.h
@@ -0,0 +1,51 @@
+/*
+ * Color lines for GNOME
+ * Copyright © 1999 Free Software Foundation
+ * Authors: Robert Szokovacs <szo appaloosacorp hu>
+ * Szabolcs Ban <shooby gnome hu>
+ * Karuna Grewal <karunagrewal98 gmail com>
+ * Copyright © 2007 Christian Persch
+ *
+ * This game 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef FIVE_OR_MORE_APP_H
+#define FIVE_OR_MORE_APP_H
+
+#include <gtk/gtk.h>
+#include "games-scores.h"
+
+typedef struct _background background;
+struct _background{
+ GdkRGBA color;
+ gchar *name;
+ gint set;
+} ;
+
+GamesScores *get_highscores ();
+GtkWidget *get_gridframe ();
+char *get_ball_filename ();
+background get_backgnd ();
+void set_status_message (gchar * message);
+void game_over (void);
+void set_application_callbacks (GtkApplication *application);
+gint *get_game_size ();
+const GamesScoresCategory *get_scorecats ();
+GSettings **get_settings ();
+int get_move_timeout ();
+void game_props_callback (GSimpleAction *action,
+ GVariant *parameter,
+ gpointer user_data);
+void update_score (guint value);
+#endif
\ No newline at end of file
diff --git a/src/five-or-more.c b/src/five-or-more.c
index f2a3dc7..cc9e1fe 100644
--- a/src/five-or-more.c
+++ b/src/five-or-more.c
@@ -34,1662 +34,8 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gdk/gdkkeysyms.h>
-#include "five-or-more.h"
-#include "games-file-list.h"
-#include "games-preimage.h"
-#include "games-gridframe.h"
-#include "games-scores.h"
-#include "games-scores-dialog.h"
-
-#define KEY_BACKGROUND_COLOR "background-color"
-#define KEY_BALL_THEME "ball-theme"
-#define KEY_MOVE_TIMEOUT "move-timeout"
-#define KEY_SIZE "size"
-
-#define KEY_SAVED_SCORE "score"
-#define KEY_SAVED_FIELD "field"
-#define KEY_SAVED_PREVIEW "preview"
-
-#define MAXNPIECES 10
-#define MAXFIELDSIZE 30
-#define DEFAULT_GAME_SIZE MEDIUM
-#define DEFAULT_BALL_THEME "balls.svg"
-
-#define PREVIEW_IMAGE_WIDTH 20
-#define PREVIEW_IMAGE_HEIGHT 20
-
-enum {
- UNSET = 0,
- SMALL = 1,
- MEDIUM,
- LARGE,
- MAX_SIZE,
-};
-
-/* Keep these in sync with the enum above. */
-static const gint field_sizes[MAX_SIZE][4] = {
- {-1, -1, -1, -1}, /* This is a dummy entry. */
- {7, 7, 5, 3}, /* SMALL */
- {9, 9, 7, 3}, /* MEDIUM */
- {20, 15, 7, 7} /* LARGE */
-};
-
-static const GamesScoresCategory scorecats[] = {
- { "Small", NC_("board size", "Small") },
- { "Medium", NC_("board size", "Medium") },
- { "Large", NC_("board size", "Large") }
-};
-
-static GamesScores *highscores;
-static GSettings *settings;
-static GtkBuilder *builder;
-static GtkBuilder *builder_preferences;
-
-static gint hfieldsize;
-static gint vfieldsize;
-static gint ncolors;
-static gint npieces;
-static gint game_size = UNSET;
-static gboolean pref_dialog_done = FALSE;
-
-static GRand *rgen;
-
-static GtkWidget *draw_area;
-static GtkWidget *app, *headerbar, *pref_dialog, *gridframe, *restart_game_dialog;
-static GtkWidget *size_radio_s, *size_radio_m, *size_radio_l;
-
-static gint window_width = 0, window_height = 0;
-static gboolean window_is_fullscreen = FALSE, window_is_maximized = FALSE;
-
-static field_props field[MAXFIELDSIZE * MAXFIELDSIZE];
-
-/* Pre-rendering image data prepared from file. */
-static GamesPreimage *ball_preimage = NULL;
-/* The tile images with balls rendered on them. */
-static cairo_surface_t *ball_surface = NULL;
-
-static GtkImage* preview_images[MAXNPIECES];
-static GdkPixbuf* preview_pixbufs[MAXNPIECES];
-
-/* A cairo_surface_t of a blank tile. */
-static cairo_surface_t *blank_surface = NULL;
-
-static GamesFileList *theme_file_list = NULL;
-
-static int active = -1;
-static int target = -1;
-static int inmove = 0;
-static guint score = 0;
-static int cursor_x = MAXFIELDSIZE / 2;
-static int cursor_y = MAXFIELDSIZE / 2;
-static gboolean show_cursor = FALSE;
-
-static int boxsize;
-
-static int move_timeout = 100;
-static int animate_id = 0;
-static int preview[MAXNPIECES];
-static char *ball_filename;
-static GtkWidget *scorelabel;
-static scoretable sctab[] =
- { {5, 10}, {6, 12}, {7, 18}, {8, 28}, {9, 42}, {10, 82}, {11, 108}, {12,
- 138},
- {13, 172}, {14, 210}, {0, 0} };
-
-static struct {
- GdkRGBA color;
- gchar *name;
- gint set;
-} backgnd = { { 0, 0, 0, 0}, NULL, 0 };
-
-static gchar *warning_message = NULL;
-
-static void
-set_status_message (gchar * message)
-{
- gtk_header_bar_set_subtitle (GTK_HEADER_BAR (headerbar), message);
-}
-
-static void
-show_image_warning (gchar * message)
-{
- GtkWidget *dialog;
- GtkWidget *button;
-
- dialog = gtk_message_dialog_new (GTK_WINDOW (app),
- GTK_DIALOG_MODAL,
- GTK_MESSAGE_WARNING,
- GTK_BUTTONS_CLOSE,
- "%s",_("Could not load theme"));
-
- gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
- "%s", message);
-
- button = gtk_dialog_add_button (GTK_DIALOG (dialog),
- _("Preferences"), GTK_RESPONSE_ACCEPT);
-
- gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
-
- g_signal_connect (button, "clicked", G_CALLBACK (game_props_callback),
- NULL);
-
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_destroy (dialog);
-}
-
-static GamesPreimage *
-load_image (gchar * fname)
-{
- GamesPreimage *preimage;
- gchar *path;
- GError *error = NULL;
-
- path = g_build_filename (DATA_DIRECTORY, "themes", fname, NULL);
- if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
- warning_message = g_strdup_printf (_("Unable to locate file:\n%s\n\n"
- "The default theme will be loaded instead."),
- fname);
-
- path = g_build_filename (DATA_DIRECTORY, "themes", "balls.svg", NULL);
- if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
- g_free (warning_message);
- warning_message = g_strdup_printf (_("Unable to locate file:\n%s\n\n"
- "Please check that Five or More is installed correctly."),
- fname);
- }
- }
-
- preimage = games_preimage_new_from_file (path, &error);
- g_free (path);
-
- if (error) {
- warning_message = g_strdup (error->message);
- g_error_free (error);
- }
-
- return preimage;
-}
-
-static void
-refresh_pixmaps (void)
-{
- cairo_t *cr, *cr_blank;
- GdkPixbuf *ball_pixbuf = NULL;
-
- /* Since we get called both by configure and after loading an image.
- * it is possible the pixmaps aren't initialised. If they aren't
- * we don't do anything. */
- if (!ball_surface)
- return;
-
- if (!boxsize)
- return;
-
- if (ball_preimage) {
- ball_pixbuf = games_preimage_render (ball_preimage, 4 * boxsize,
- 7 * boxsize);
-
- /* Handle rendering problems. */
- if (!ball_pixbuf) {
- g_object_unref (ball_preimage);
- ball_preimage = NULL;
-
- if (!warning_message) {
- warning_message = g_strdup ("The selected theme failed to render.\n\n"
- "Please check that Five or More is installed correctly.");
- }
- }
- }
-
- if (!ball_pixbuf) {
- ball_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
- 4 * boxsize, 7 * boxsize);
- gdk_pixbuf_fill (ball_pixbuf, 0x00000000);
- }
-
- if (warning_message)
- show_image_warning (warning_message);
- g_free (warning_message);
- warning_message = NULL;
-
- cr = cairo_create (ball_surface);
- gdk_cairo_set_source_rgba (cr, &backgnd.color);
-
- cairo_rectangle (cr, 0, 0, boxsize * 4, boxsize * 7);
- cairo_fill (cr);
-
- gdk_cairo_set_source_pixbuf (cr, ball_pixbuf, 0, 0);
- cairo_mask (cr, cairo_get_source (cr));
- g_object_unref (ball_pixbuf);
-
- cairo_destroy (cr);
-
- cr_blank = cairo_create (blank_surface);
- gdk_cairo_set_source_rgba (cr_blank, &backgnd.color);
-
- cairo_rectangle (cr_blank, 0, 0, boxsize, boxsize);
- cairo_fill (cr_blank);
-
- cairo_destroy (cr_blank);
-}
-
-static void
-refresh_preview_surfaces (void)
-{
- guint i;
- GdkPixbuf *scaled = NULL;
- GtkWidget *widget = GTK_WIDGET (preview_images[0]);
- GtkStyleContext *context;
- GdkRGBA bg;
- cairo_t *cr;
- GdkRectangle preview_rect;
- cairo_surface_t *blank_preview_surface = NULL;
- /* The balls rendered to a size appropriate for the preview. */
- cairo_surface_t *preview_surface = NULL;
-
- context = gtk_widget_get_style_context (widget);
- gtk_style_context_get_background_color (context, gtk_style_context_get_state (context), &bg);
-
- /* Like the refresh_pixmaps() function, we may be called before
- * the window is ready. */
- if (PREVIEW_IMAGE_HEIGHT == 0)
- return;
-
- preview_rect.x = 0;
- preview_rect.y = 0;
- preview_rect.width = PREVIEW_IMAGE_WIDTH;
- preview_rect.height = PREVIEW_IMAGE_HEIGHT;
-
- /* We create pixmaps for each of the ball colours and then
- * set them as the background for each widget in the preview array.
- * This code assumes that each preview window is identical. */
-
- if (ball_preimage)
- scaled = games_preimage_render (ball_preimage, 4 * PREVIEW_IMAGE_WIDTH,
- 7 * PREVIEW_IMAGE_HEIGHT);
-
- if (!scaled) {
- scaled = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
- 4 * PREVIEW_IMAGE_WIDTH, 7 * PREVIEW_IMAGE_HEIGHT);
- gdk_pixbuf_fill (scaled, 0x00000000);
- }
-
- for (i = 0; i < 7; i++) {
- preview_surface = gdk_window_create_similar_image_surface (gtk_widget_get_window (widget),
- CAIRO_FORMAT_ARGB32,
- PREVIEW_IMAGE_WIDTH, PREVIEW_IMAGE_HEIGHT, 1);
- cr = cairo_create (preview_surface);
- gdk_cairo_set_source_rgba (cr, &bg);
- gdk_cairo_rectangle (cr, &preview_rect);
- cairo_fill (cr);
-
- gdk_cairo_set_source_pixbuf (cr, scaled, 0, -1.0 * PREVIEW_IMAGE_HEIGHT * i);
- cairo_mask (cr, cairo_get_source (cr));
-
- if (preview_pixbufs[i])
- g_object_unref (preview_pixbufs[i]);
-
- preview_pixbufs[i] = gdk_pixbuf_get_from_surface (preview_surface, 0, 0,
- PREVIEW_IMAGE_WIDTH, PREVIEW_IMAGE_HEIGHT);
-
- cairo_destroy (cr);
- cairo_surface_destroy (preview_surface);
- }
-
- blank_preview_surface = gdk_window_create_similar_surface (gtk_widget_get_window (widget),
- CAIRO_CONTENT_COLOR_ALPHA,
- PREVIEW_IMAGE_WIDTH, PREVIEW_IMAGE_HEIGHT);
- cr = cairo_create (blank_preview_surface);
- gdk_cairo_set_source_rgba (cr, &bg);
- gdk_cairo_rectangle (cr, &preview_rect);
- cairo_fill (cr);
-
- cairo_surface_destroy (blank_preview_surface);
- cairo_destroy (cr);
- g_object_unref (scaled);
-}
-
-static void
-draw_all_balls (GtkWidget * widget)
-{
- gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE);
-}
-
-static void
-start_animation (void)
-{
- int ms;
-
- ms = (inmove ? move_timeout : 100);
- if (animate_id == 0)
- animate_id = g_timeout_add (ms, animate, draw_area);
-}
-
-void
-set_inmove (int i)
-{
- if (inmove != i) {
- inmove = i;
- if (animate_id)
- g_source_remove (animate_id);
- animate_id = 0;
- start_animation ();
- }
-}
-
-static void
-reset_game (void)
-{
- int i;
-
- for (i = 0; i < hfieldsize * vfieldsize; i++) {
- field[i].color = 0;
- field[i].phase = 0;
- field[i].active = 0;
- field[i].pathsearch = -1;
- }
- score = 0;
- init_preview ();
- init_new_balls (npieces, -1);
-}
-
-static void
-refresh_screen (void)
-{
- draw_all_balls (draw_area);
- draw_preview ();
-}
-
-static void
-start_game (void)
-{
- char string[20];
-
- set_status_message (_("Match five objects of the same type in a row to score!"));
- refresh_screen ();
- active = -1;
- target = -1;
- inmove = -1;
- g_snprintf (string, 19, "%d", score);
- gtk_label_set_text (GTK_LABEL (scorelabel), string);
- set_inmove (0);
-}
-
-static void
-reset_pathsearch (void)
-{
- int i;
-
- for (i = 0; i < hfieldsize * vfieldsize; i++)
- field[i].pathsearch = -1;
-}
-
-void
-init_preview (void)
-{
- int i;
-
- for (i = 0; i < npieces; i++) {
- preview[i] = g_rand_int_range (rgen, 1, ncolors + 1);
- }
-}
-
-void
-draw_preview (void)
-{
- guint i;
-
- /* This function can be called before the images are initialized */
- if (!GTK_IS_IMAGE (preview_images[0]))
- return;
-
- for (i = 0; i < MAXNPIECES; i++) {
- if (i < npieces)
- gtk_image_set_from_pixbuf (preview_images[i], preview_pixbufs[preview[i] - 1]);
- else
- gtk_image_clear (preview_images[i]);
- }
-}
-
-void
-game_new_callback (GSimpleAction *action,
- GVariant *parameter,
- gpointer user_data)
-{
- reset_game ();
- start_game ();
-}
-
-static void
-show_scores (gint pos)
-{
- static GtkWidget *dialog;
-
- if (dialog == NULL) {
- dialog = games_scores_dialog_new (GTK_WINDOW (app), highscores, _("Five or More Scores"));
- games_scores_dialog_set_category_description (GAMES_SCORES_DIALOG
- (dialog), _("_Board size:"));
- }
-
- if (pos > 0) {
- games_scores_dialog_set_hilight (GAMES_SCORES_DIALOG (dialog), pos);
- }
-
- gtk_window_present (GTK_WINDOW (dialog));
- gtk_dialog_run (GTK_DIALOG (dialog));
- gtk_widget_hide (dialog);
-}
-
-static void
-game_over (void)
-{
- int pos;
-
- set_status_message (_("Game Over!"));
- if (score > 0)
- pos = games_scores_add_plain_score (highscores, score);
- show_scores (pos);
-}
-
-static int
-spaces_left (void)
-{
- int i, j;
-
- j = 0;
-
- for (i = 0; i < hfieldsize * vfieldsize; i++) {
- if (field[i].color == 0)
- j++;
- }
-
- return j;
-}
-
-static int
-check_gameover (void)
-{
- if (spaces_left () > 0)
- return 1;
-
- game_over ();
-
- return -1;
-}
-
-int
-init_new_balls (int num, int prev)
-{
- int i, j = -1;
- gfloat num_boxes = hfieldsize * vfieldsize;
- for (i = 0; i < num;) {
- j = g_rand_int_range (rgen, 0, num_boxes);
- if (field[j].color == 0) {
- field[j].color = (prev == -1) ?
- g_rand_int_range (rgen, 1, ncolors + 1) : preview[prev];
- i++;
- }
- }
- return j;
-}
-
-void
-draw_box (GtkWidget * widget, int x, int y)
-{
- gtk_widget_queue_draw_area (widget, x * boxsize, y * boxsize,
- boxsize, boxsize);
-}
-
-static int
-route (int num)
-{
- int i;
- int flag = 0;
-
- if (field[target].pathsearch == num)
- return 1;
- for (i = 0; i < hfieldsize * vfieldsize; i++) {
- if (field[i].pathsearch == num) {
- flag = 1;
- if ((i / hfieldsize > 0) && (field[i - hfieldsize].pathsearch == -1)
- && (field[i - hfieldsize].color == 0))
- field[i - hfieldsize].pathsearch = num + 1;
- if ((i / hfieldsize < vfieldsize - 1)
- && (field[i + hfieldsize].pathsearch == -1)
- && (field[i + hfieldsize].color == 0))
- field[i + hfieldsize].pathsearch = num + 1;
- if ((i % hfieldsize > 0) && (field[i - 1].pathsearch == -1)
- && (field[i - 1].color == 0))
- field[i - 1].pathsearch = num + 1;
- if ((i % hfieldsize < hfieldsize - 1) && (field[i + 1].pathsearch == -1)
- && (field[i + 1].color == 0)) {
- field[i + 1].pathsearch = num + 1;
- }
- }
- }
- if (flag == 0)
- return 0;
- return 2;
-}
-
-static void
-fix_route (int num, int pos)
-{
- int i;
-
- for (i = 0; i < hfieldsize * vfieldsize; i++)
- if ((i != pos) && (field[i].pathsearch == num))
- field[i].pathsearch = -1;
- if (num < 2)
- return;
- if ((pos / hfieldsize > 0)
- && (field[pos - hfieldsize].pathsearch == num - 1))
- fix_route (num - 1, pos - hfieldsize);
- if ((pos % hfieldsize > 0) && (field[pos - 1].pathsearch == num - 1))
- fix_route (num - 1, pos - 1);
- if ((pos / hfieldsize < vfieldsize - 1)
- && (field[pos + hfieldsize].pathsearch == num - 1))
- fix_route (num - 1, pos + hfieldsize);
- if ((pos % hfieldsize < hfieldsize - 1)
- && (field[pos + 1].pathsearch == num - 1))
- fix_route (num - 1, pos + 1);
-}
-
-int
-find_route (void)
-{
- int i = 0;
- int j = 0;
-
- field[active].pathsearch = i;
- while ((j = route (i))) {
- if (j == 1) {
- fix_route (i, target);
- return 1;
- }
- i++;
- }
- return 0;
-}
-
-static void
-deactivate (GtkWidget * widget, int x, int y)
-{
- field[active].active = 0;
- field[active].phase = 0;
- draw_box (widget, x, y);
- active = -1;
-}
-
-static void
-cell_clicked (GtkWidget * widget, int fx, int fy)
-{
- int x, y;
-
- set_status_message (NULL);
- if (field[fx + fy * hfieldsize].color == 0) {
- /* Clicked on an empty field */
-
- if ((active != -1) && (inmove != 1)) {
- /* We have an active ball, and it's not
- * already in move. Therefore we should begin
- * the moving sequence */
-
- target = fx + fy * hfieldsize;
- if (find_route ()) {
- /* We found a route to the new position */
-
- set_inmove (1);
- } else {
- /* Can't move there! */
- set_status_message (_("You can’t move there!"));
- reset_pathsearch ();
- target = -1;
- }
- }
- } else {
- /* Clicked on a ball */
-
- if ((fx + fy * hfieldsize) == active) {
- /* It's active, so let's deactivate it! */
-
- deactivate (widget, fx, fy);
- } else {
- /* It's not active, so let's activate it! */
-
- if (active != -1) {
- /* There is an other active ball, we should deactivate it first! */
-
- x = active % hfieldsize;
- y = active / hfieldsize;
- deactivate (widget, x, y);
- }
-
- active = fx + fy * hfieldsize;
- field[active].active = 1;
- start_animation();
- }
- }
-
-}
-
-static gint
-button_press_event (GtkWidget * widget, GdkEvent * event)
-{
- int x, y;
- int fx, fy;
-
- if (inmove)
- return TRUE;
-
- /* Ignore the 2BUTTON and 3BUTTON events. */
- if (event->type != GDK_BUTTON_PRESS)
- return TRUE;
-
- if (show_cursor) {
- show_cursor = FALSE;
- draw_box (draw_area, cursor_x, cursor_y);
- }
-
- fx = event->button.x / boxsize;
- fy = event->button.y / boxsize;
-
- /* If we click on the outer border pixels, the previous calculation
- * will be wrong and we must correct. */
- fx = CLAMP (fx, 0, hfieldsize - 1);
- fy = CLAMP (fy, 0, vfieldsize - 1);
-
- cursor_x = fx;
- cursor_y = fy;
-
- cell_clicked (widget, fx, fy);
-
- return TRUE;
-}
-
-static void
-move_cursor (int dx, int dy)
-{
- int old_x = cursor_x;
- int old_y = cursor_y;
-
- if (!show_cursor) {
- show_cursor = TRUE;
- draw_box (draw_area, cursor_x, cursor_y);
- }
-
- cursor_x = cursor_x + dx;
- if (cursor_x < 0)
- cursor_x = 0;
- if (cursor_x >= hfieldsize)
- cursor_x = hfieldsize - 1;
- cursor_y = cursor_y + dy;
- if (cursor_y < 0)
- cursor_y = 0;
- if (cursor_y >= vfieldsize)
- cursor_y = vfieldsize - 1;
-
- if (cursor_x == old_x && cursor_y == old_y)
- return;
-
- draw_box (draw_area, old_x, old_y);
- draw_box (draw_area, cursor_x, cursor_y);
-}
-
-static gboolean
-key_press_event (GtkWidget * widget, GdkEventKey * event, void *d)
-{
- guint key;
-
- key = event->keyval;
-
- switch (key) {
- case GDK_KEY_Left:
- case GDK_KEY_KP_Left:
- move_cursor (-1, 0);
- break;
- case GDK_KEY_Right:
- case GDK_KEY_KP_Right:
- move_cursor (1, 0);
- break;
- case GDK_KEY_Up:
- case GDK_KEY_KP_Up:
- move_cursor (0, -1);
- break;
- case GDK_KEY_Down:
- case GDK_KEY_KP_Down:
- move_cursor (0, 1);
- break;
- case GDK_KEY_Home:
- case GDK_KEY_KP_Home:
- move_cursor (-999, 0);
- break;
- case GDK_KEY_End:
- case GDK_KEY_KP_End:
- move_cursor (999, 0);
- break;
- case GDK_KEY_Page_Up:
- case GDK_KEY_KP_Page_Up:
- move_cursor (0, -999);
- break;
- case GDK_KEY_Page_Down:
- case GDK_KEY_KP_Page_Down:
- move_cursor (0, 999);
- break;
-
- case GDK_KEY_space:
- case GDK_KEY_Return:
- case GDK_KEY_KP_Enter:
- if (show_cursor)
- cell_clicked (widget, cursor_x, cursor_y);
- break;
- }
-
- return TRUE;
-}
-
-static void
-draw_grid (cairo_t *cr)
-{
- GdkRGBA color;
- guint w, h;
- guint i;
-
- w = gtk_widget_get_allocated_width(draw_area);
- h = gtk_widget_get_allocated_height(draw_area);
-
- gdk_rgba_parse (&color, "#525F6C");
- gdk_cairo_set_source_rgba (cr, &color);
- cairo_set_line_width (cr, 1.0);
-
- for (i = boxsize; i < w; i = i + boxsize)
- {
- cairo_move_to (cr, i + 0.5, 0 + 0.5);
- cairo_line_to (cr, i + 0.5, h + 0.5);
- }
-
- for (i = boxsize; i < h; i = i + boxsize)
- {
- cairo_move_to (cr, 0 + 0.5, i + 0.5);
- cairo_line_to (cr, w + 0.5, i + 0.5);
- }
-
- cairo_rectangle (cr, 0.5, 0.5, w - 0.5, h - 0.5);
- cairo_stroke (cr);
-}
-
-static gboolean
-field_draw_callback (GtkWidget * widget, cairo_t *cr)
-{
- guint i, j, idx;
- GdkRGBA cursorColor;
-
- for (i = 0; i < vfieldsize; i++) {
- for (j = 0; j < hfieldsize; j++) {
- int phase, color;
-
- idx = j + i * hfieldsize;
-
- cairo_rectangle (cr, j * boxsize, i * boxsize, boxsize, boxsize);
-
- if (field[idx].color != 0) {
- phase = field[idx].phase;
- color = field[idx].color - 1;
-
- phase = ABS (ABS (3 - phase) - 3);
-
- cairo_set_source_surface (cr, ball_surface,
- (1.0 * j - phase) * boxsize,
- (1.0 * i - color) * boxsize);
- } else {
- cairo_set_source_surface (cr, blank_surface, 1.0 * j * boxsize, 1.0 * i * boxsize);
- }
-
- cairo_fill (cr);
- }
- }
-
- /* Cursor */
- if (show_cursor) {
- if (((backgnd.color.red + backgnd.color.green + backgnd.color.blue) / 3) > 0.5)
- gdk_rgba_parse (&cursorColor, "#000000");
- else
- gdk_rgba_parse (&cursorColor, "#FFFFFF");
-
- gdk_cairo_set_source_rgba (cr, &cursorColor);
- cairo_set_line_width (cr, 1.0);
- cairo_rectangle (cr,
- cursor_x * boxsize + 1.5, cursor_y * boxsize + 1.5,
- boxsize - 2.5, boxsize - 2.5);
- cairo_stroke (cr);
- }
-
- draw_grid (cr);
-
- return FALSE;
-}
-
-static int
-addscore (int num)
-{
- gchar string[20];
- int i = 0;
- int retval;
-
- while ((sctab[i].num != num) && (sctab[i].num != 0))
- i++;
- if (sctab[i].num == 0) {
- num-=5;
- retval = sctab[num%5].score + 72 * (num/5) + (num-5)*24 ;
- } else
- retval = sctab[i].score;
-
- score += retval;
- g_snprintf (string, 19, "%d", score);
- gtk_label_set_text (GTK_LABEL (scorelabel), string);
-
- return retval;
-}
-
-
-static void
-tag_list (int *list, int len)
-{
- int i;
-
- for (i = 0; i < len; i++)
- field[list[i]].tag = 1;
-}
-
-static int
-find_lines (int num)
-{
- int count = 1;
- int subcount = 0;
- int x = num % hfieldsize;
- int y = num / hfieldsize;
- int list[hfieldsize];
-
- /* Horizontal */
-
- x++;
- while ((x <= hfieldsize - 1)
- && (field[x + y * hfieldsize].color == field[num].color)) {
- list[subcount] = x + y * hfieldsize;
- subcount++;
- x++;
- }
- x = num % hfieldsize - 1;
- while ((x >= 0) && (field[x + y * hfieldsize].color == field[num].color)) {
- list[subcount] = x + y * hfieldsize;
- subcount++;
- x--;
- }
- if (subcount >= 4) {
- field[num].tag = 1;
- tag_list (list, subcount);
- count += subcount;
- }
- subcount = 0;
-
- /* Vertical */
-
- x = num % hfieldsize;
- y++;
- while ((y <= vfieldsize - 1)
- && (field[x + y * hfieldsize].color == field[num].color)) {
- list[subcount] = x + y * hfieldsize;
- subcount++;
- y++;
- }
- y = num / hfieldsize - 1;
- while ((y >= 0) && (field[x + y * hfieldsize].color == field[num].color)) {
- list[subcount] = x + y * hfieldsize;
- subcount++;
- y--;
- }
- if (subcount >= 4) {
- field[num].tag = 1;
- tag_list (list, subcount);
- count += subcount;
- }
- subcount = 0;
-
- /* Diagonal ++ */
-
- x = num % hfieldsize + 1;
- y = num / hfieldsize + 1;
- while ((y <= vfieldsize - 1) && (x <= hfieldsize - 1)
- && (field[x + y * hfieldsize].color == field[num].color)) {
- list[subcount] = x + y * hfieldsize;
- subcount++;
- y++;
- x++;
- }
- x = num % hfieldsize - 1;
- y = num / hfieldsize - 1;
- while ((y >= 0) && (x >= 0)
- && (field[x + y * hfieldsize].color == field[num].color)) {
- list[subcount] = x + y * hfieldsize;
- subcount++;
- y--;
- x--;
- }
- if (subcount >= 4) {
- field[num].tag = 1;
- tag_list (list, subcount);
- count += subcount;
- }
- subcount = 0;
-
- /* Diagonal +- */
-
- x = num % hfieldsize + 1;
- y = num / hfieldsize - 1;
- while ((y >= 0) && (x <= hfieldsize - 1)
- && (field[x + y * hfieldsize].color == field[num].color)) {
- list[subcount] = x + y * hfieldsize;
- subcount++;
- y--;
- x++;
- }
- x = num % hfieldsize - 1;
- y = num / hfieldsize + 1;
- while ((y <= vfieldsize - 1) && (x >= 0)
- && (field[x + y * hfieldsize].color == field[num].color)) {
- list[subcount] = x + y * hfieldsize;
- subcount++;
- y++;
- x--;
- }
- if (subcount >= 4) {
- field[num].tag = 1;
- tag_list (list, subcount);
- count += subcount;
- }
-
- return count;
-}
-
-static void
-clear_tags (void)
-{
- int i;
-
- for (i = 0; i < hfieldsize * vfieldsize; i++)
- field[i].tag = 0;
-}
-
-static int
-kill_tags (GtkWidget * widget)
-{
- int i, j;
-
- j = 0;
- for (i = 0; i < hfieldsize * vfieldsize; i++) {
- if (field[i].tag == 1) {
- j++;
- field[i].color = 0;
- field[i].phase = 0;
- field[i].active = 0;
- draw_box (widget, i % hfieldsize, i / hfieldsize);
- }
- }
-
- return j;
-}
-
-static gboolean
-check_goal (GtkWidget * w, int target)
-{
- gboolean lines_cleared;
- int count;
-
- clear_tags ();
-
- count = find_lines (target);
- lines_cleared = count >= 5;
-
- if (lines_cleared) {
- kill_tags (w);
- addscore (count);
- }
- reset_pathsearch ();
-
- return lines_cleared;
-}
-
-gint
-animate (gpointer gp)
-{
- GtkWidget *widget = GTK_WIDGET (gp);
- int x, y;
- int newactive = 0;
-
- x = active % hfieldsize;
- y = active / hfieldsize;
-
- if (active == -1) {
- animate_id = 0;
- return FALSE;
- }
-
- if (inmove != 0) {
- if ((x > 0)
- && (field[active - 1].pathsearch == field[active].pathsearch + 1))
- newactive = active - 1;
- else if ((x < hfieldsize - 1)
- && (field[active + 1].pathsearch ==
- field[active].pathsearch + 1))
- newactive = active + 1;
- else if ((y > 0)
- && (field[active - hfieldsize].pathsearch ==
- field[active].pathsearch + 1))
- newactive = active - hfieldsize;
- else if ((y < vfieldsize - 1)
- && (field[active + hfieldsize].pathsearch ==
- field[active].pathsearch + 1))
- newactive = active + hfieldsize;
- else {
- set_inmove (0);
- }
- draw_box (widget, x, y);
- x = newactive % hfieldsize;
- y = newactive / hfieldsize;
- field[newactive].phase = field[active].phase;
- field[newactive].color = field[active].color;
- field[active].phase = 0;
- field[active].color = 0;
- field[active].active = 0;
- if (newactive == target) {
- target = -1;
- set_inmove (0);
- active = -1;
- field[newactive].phase = 0;
- field[newactive].active = 0;
- draw_box (widget, x, y);
- reset_pathsearch ();
- if (!check_goal (widget, newactive)) {
- gboolean fullline;
- int balls[npieces];
- int spaces;
-
- clear_tags ();
- fullline = FALSE;
- spaces = spaces_left ();
- if (spaces > npieces)
- spaces = npieces;
- for (x = 0; x < spaces; x++) {
- int tmp = init_new_balls (1, x);
- draw_box (widget, tmp % hfieldsize, tmp / hfieldsize);
- balls[x] = tmp;
- fullline = (find_lines (balls[x]) >= 5) || fullline;
- }
- if (fullline)
- addscore (kill_tags (widget));
- if (check_gameover () == -1)
- return FALSE;
- init_preview ();
- draw_preview ();
- }
- return TRUE;
- }
- field[newactive].active = 1;
- active = newactive;
- }
-
- field[active].phase++;
- if (field[active].phase >= 4)
- field[active].phase = 0;
- draw_box (widget, x, y);
-
- return TRUE;
-}
-
-void
-game_top_ten_callback (GSimpleAction *action,
- GVariant *parameter,
- gpointer user_data)
-{
- show_scores (0);
-}
-
-void
-game_about_callback (GSimpleAction *action,
- GVariant *parameter,
- gpointer user_data)
-{
- const gchar *authors[] = { "Robert Szokovacs <szo appaloosacorp hu>",
- "Szabolcs B\xc3\xa1n <shooby gnome hu>",
- NULL
- };
-
- const gchar *documenters[] = { "Tiffany Antopolski",
- "Lanka Rathnayaka",
- NULL
- };
-
- gtk_show_about_dialog (GTK_WINDOW (app),
- "program-name", _("Five or More"),
- "version", VERSION,
- "comments", _("GNOME port of the once-popular Color Lines game"),
- "copyright",
- "Copyright © 1997–2008 Free Software Foundation, Inc.\n Copyright © 2013–2014
Michael Catanzaro",
- "license-type", GTK_LICENSE_GPL_2_0,
- "authors", authors,
- "documenters", documenters,
- "translator-credits", _("translator-credits"),
- "logo-icon-name", "five-or-more",
- "website", "https://wiki.gnome.org/Apps/Five%20or%20more",
- NULL);
-}
-
-static void
-set_backgnd_color (const gchar * str)
-{
- if (!str)
- str = g_strdup ("#000000");
-
- if (str != backgnd.name) {
- g_free (backgnd.name);
- backgnd.name = g_strdup (str);
- }
-
- if (!gdk_rgba_parse (&backgnd.color, backgnd.name)) {
- gdk_rgba_parse (&backgnd.color, "#000000");
- }
-}
-
-static void
-set_sizes (gint size)
-{
- hfieldsize = field_sizes[size][0];
- vfieldsize = field_sizes[size][1];
- ncolors = field_sizes[size][2];
- npieces = field_sizes[size][3];
- game_size = size;
- games_scores_set_category (highscores, scorecats[size - 1].key);
-
- g_settings_set_int (settings, KEY_SIZE, size);
-
- if (gridframe)
- games_grid_frame_set (GAMES_GRID_FRAME (gridframe),
- hfieldsize, vfieldsize);
-}
-
-static void
-load_theme (void)
-{
- if (ball_preimage)
- g_object_unref (ball_preimage);
- ball_preimage = load_image (ball_filename);
-
- refresh_pixmaps ();
- refresh_preview_surfaces ();
-}
-
-static void
-conf_value_changed_cb (GSettings *settings, gchar *key)
-{
- if (strcmp (key, KEY_BACKGROUND_COLOR) == 0) {
- gchar *color;
-
- color = g_settings_get_string (settings, KEY_BACKGROUND_COLOR);
- if (color != NULL) {
- set_backgnd_color (color);
- g_free (color);
- }
- } else if (strcmp (key, KEY_BALL_THEME) == 0) {
- gchar *theme_tmp = NULL;
-
- theme_tmp = g_settings_get_string (settings, KEY_BALL_THEME);
- if (theme_tmp) {
- if (strcmp (theme_tmp, ball_filename) != 0) {
- g_free (ball_filename);
- ball_filename = theme_tmp;
- load_theme ();
- refresh_screen ();
- } else
- g_free (theme_tmp);
- }
- /* FIXME apply in the prefs dialog GUI */
- } else if (strcmp (key, KEY_MOVE_TIMEOUT) == 0) {
- gint timeout_tmp;
-
- timeout_tmp = g_settings_get_int (settings, KEY_MOVE_TIMEOUT);
- timeout_tmp = CLAMP (timeout_tmp, 1, 1000);
- if (timeout_tmp != move_timeout)
- move_timeout = timeout_tmp;
-
- } else if (strcmp (key, KEY_SIZE) == 0) {
- gint size_tmp;
- size_tmp = g_settings_get_int (settings, KEY_SIZE);
-
- if (size_tmp != game_size) {
- set_sizes (size_tmp);
- reset_game ();
- start_game ();
- }
- }
-}
-
-static void
-bg_color_callback (GtkWidget * widget, gpointer data)
-{
- GdkRGBA c;
- char str[64];
-
- gtk_color_chooser_get_rgba (GTK_COLOR_CHOOSER (widget), &c);
-
- g_snprintf (str, sizeof (str), "#%04x%04x%04x", (int) (c.red * 65535 + 0.5), (int) (c.green * 65535 +
0.5), (int) (c.blue * 65535 + 0.5));
-
- g_settings_set_string (settings, KEY_BACKGROUND_COLOR, str);
-
- load_theme ();
- refresh_screen ();
-}
-
-static void
-size_callback (GtkWidget * widget, gpointer data)
-{
- GtkWidget *size_radio, *content_area, *label;
-
- game_size = g_settings_get_int (settings, KEY_SIZE);
- if (pref_dialog_done && game_size != GPOINTER_TO_INT (data) && !restart_game_dialog) {
- GtkDialogFlags flags = GTK_DIALOG_DESTROY_WITH_PARENT;
-
- restart_game_dialog = gtk_message_dialog_new (GTK_WINDOW (pref_dialog),
- GTK_MESSAGE_WARNING,
- flags,
- GTK_BUTTONS_NONE,
- _("Are you sure you want to restart the game?"));
-
- gtk_dialog_add_buttons (GTK_DIALOG (restart_game_dialog),
- _("_Cancel"), GTK_RESPONSE_CANCEL,
- _("_Restart"), GTK_RESPONSE_OK,
- NULL);
-
- gint result = gtk_dialog_run (GTK_DIALOG (restart_game_dialog));
- gtk_widget_destroy (restart_game_dialog);
-
- switch (result) {
- case GTK_RESPONSE_OK:
- g_settings_set_int (settings, KEY_SIZE, GPOINTER_TO_INT (data));
- break;
- case GTK_RESPONSE_CANCEL:
- switch (game_size) {
- case SMALL:
- size_radio = size_radio_s;
- break;
- case MEDIUM:
- size_radio = size_radio_m;
- break;
- case LARGE:
- size_radio = size_radio_l;
- break;
- }
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (size_radio), TRUE);
- }
-
- restart_game_dialog = NULL;
- }
-}
-
-static void
-set_selection (GtkWidget * widget, char *data)
-{
- const gchar *entry;
-
- entry = games_file_list_get_nth (theme_file_list,
- gtk_combo_box_get_active (GTK_COMBO_BOX
- (widget)));
- g_settings_set_string (settings, KEY_BALL_THEME, entry);
-}
-
-static GtkWidget *
-fill_menu (void)
-{
- gchar *pixmap_dir;
-
- if (theme_file_list)
- g_object_unref (theme_file_list);
-
- pixmap_dir = g_build_filename (DATA_DIRECTORY, "themes", NULL);
- theme_file_list = games_file_list_new_images (pixmap_dir, NULL);
- g_free (pixmap_dir);
- games_file_list_transform_basename (theme_file_list);
-
- return games_file_list_create_widget (theme_file_list, ball_filename,
- GAMES_FILE_LIST_REMOVE_EXTENSION |
- GAMES_FILE_LIST_REPLACE_UNDERSCORES);
-}
-
-static void
-set_fast_moves_callback (GtkWidget * widget, gpointer * data)
-{
- gboolean is_on = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget));
- gint timeout = is_on ? 10 : 100;
- g_settings_set_int (settings, KEY_MOVE_TIMEOUT, timeout);
-}
-
-void
-pref_dialog_response (GtkDialog * dialog, gint response, gpointer data)
-{
- gtk_widget_hide (GTK_WIDGET (dialog));
-}
-
-void
-game_props_callback (GSimpleAction *action,
- GVariant *parameter,
- gpointer user_data)
-{
- gchar *ui_path;
- GError *error = NULL;
- GtkWidget *omenu;
- GtkWidget *grid;
- GtkWidget *color_button;
- GtkWidget *size_radio;
- GtkWidget *fast_moves_checkbutton;
-
- if (!pref_dialog) {
- ui_path = g_build_filename (DATA_DIRECTORY, "five-or-more-preferences.ui", NULL);
- builder_preferences = gtk_builder_new ();
- gtk_builder_add_from_file (builder_preferences, ui_path, &error);
- g_free (ui_path);
-
- if (error) {
- g_critical ("Unable to load the user interface file: %s", error->message);
- g_error_free (error);
- g_assert_not_reached ();
- }
-
- pref_dialog = GTK_WIDGET (gtk_builder_get_object (builder_preferences, "preferences_dialog"));
- g_signal_connect (pref_dialog, "response",
- G_CALLBACK (pref_dialog_response), NULL);
- g_signal_connect (pref_dialog, "delete-event",
- G_CALLBACK (gtk_widget_hide), NULL);
-
- grid = GTK_WIDGET (gtk_builder_get_object (builder_preferences, "grid1"));
- omenu = fill_menu ();
- gtk_widget_show_all (GTK_WIDGET (omenu));
- gtk_grid_attach (GTK_GRID (grid), GTK_WIDGET (omenu), 1, 0, 1, 1);
- g_signal_connect (omenu, "changed",
- G_CALLBACK (set_selection), NULL);
-
- color_button = GTK_WIDGET (gtk_builder_get_object (builder_preferences, "colorbutton1"));
- gtk_color_chooser_set_rgba (GTK_COLOR_CHOOSER (color_button), &backgnd.color);
- g_signal_connect (color_button, "color-set",
- G_CALLBACK (bg_color_callback), NULL);
-
- size_radio = GTK_WIDGET (gtk_builder_get_object (builder_preferences, "radiobutton_small"));
- size_radio_s = size_radio;
- g_signal_connect (size_radio, "clicked",
- G_CALLBACK (size_callback), GINT_TO_POINTER (1));
- if (game_size == SMALL)
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (size_radio), TRUE);
-
- size_radio = GTK_WIDGET (gtk_builder_get_object (builder_preferences, "radiobutton_medium"));
- size_radio_m = size_radio;
- g_signal_connect (size_radio, "clicked",
- G_CALLBACK (size_callback), GINT_TO_POINTER (2));
- if (game_size == MEDIUM)
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (size_radio), TRUE);
-
- size_radio = GTK_WIDGET (gtk_builder_get_object (builder_preferences, "radiobutton_large"));
- size_radio_l = size_radio;
- g_signal_connect (size_radio, "clicked",
- G_CALLBACK (size_callback), GINT_TO_POINTER (3));
- if (game_size == LARGE)
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (size_radio), TRUE);
-
- fast_moves_checkbutton = GTK_WIDGET (gtk_builder_get_object (builder_preferences,
"checkbutton_fast_moves"));
- if (move_timeout == 10) {
- gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (fast_moves_checkbutton), TRUE);
- }
-
- g_signal_connect (fast_moves_checkbutton, "clicked",
- G_CALLBACK (set_fast_moves_callback), NULL);
-
- g_object_unref (G_OBJECT (builder_preferences));
-
- pref_dialog_done = TRUE;
- gtk_window_set_transient_for (GTK_WINDOW (pref_dialog), GTK_WINDOW (app));
- }
- gtk_dialog_run (GTK_DIALOG (pref_dialog));
-}
-
-void
-game_quit_callback (GSimpleAction *action,
- GVariant *parameter,
- gpointer user_data)
-{
- g_application_quit (G_APPLICATION (user_data));
-}
-
-void
-game_help_callback (GSimpleAction *action,
- GVariant *parameter,
- gpointer user_data)
-{
- GError *error = NULL;
-
- gtk_show_uri (gtk_widget_get_screen (GTK_WIDGET (app)), "help:five-or-more", gtk_get_current_event_time
(), &error);
- if (error)
- g_warning ("Failed to show help: %s", error->message);
- g_clear_error (&error);
-}
-
-static int
-configure_event_callback (GtkWidget * widget, GdkEventConfigure * event)
-{
- if (ball_surface)
- cairo_surface_destroy(ball_surface);
-
- if (blank_surface)
- cairo_surface_destroy (blank_surface);
-
- boxsize = (event->width - 1) / hfieldsize;
- ball_surface = gdk_window_create_similar_surface (gtk_widget_get_window (draw_area),
- CAIRO_CONTENT_COLOR_ALPHA,
- boxsize * 4, boxsize * 7);
- blank_surface = gdk_window_create_similar_surface (gtk_widget_get_window (draw_area),
- CAIRO_CONTENT_COLOR_ALPHA,
- boxsize, boxsize);
- refresh_pixmaps ();
-
- refresh_screen ();
-
- return TRUE;
-}
-
-static void
-load_properties (void)
-{
- gchar *buf;
-
- ball_filename = g_settings_get_string (settings, KEY_BALL_THEME);
-
- move_timeout = g_settings_get_int (settings, KEY_MOVE_TIMEOUT);
- if (move_timeout <= 0)
- move_timeout = 100;
-
- buf = g_settings_get_string (settings, KEY_BACKGROUND_COLOR); /* FIXMEchpe? */
- set_backgnd_color (buf);
- g_free (buf);
-
- load_theme ();
-}
-
-static void
-init_config (void)
-{
- g_signal_connect (settings, "changed",
- G_CALLBACK (conf_value_changed_cb), NULL);
-
- game_size = g_settings_get_int (settings, KEY_SIZE);
- if (game_size == UNSET)
- game_size = DEFAULT_GAME_SIZE;
-
- game_size = CLAMP (game_size, SMALL, MAX_SIZE - 1);
- set_sizes (game_size);
-}
-
-static gboolean
-window_size_allocate_cb (GtkWidget *widget, GdkRectangle *allocation)
-{
- if (!window_is_maximized && !window_is_fullscreen)
- gtk_window_get_size (GTK_WINDOW (widget), &window_width, &window_height);
-
- return FALSE;
-}
-
-static gboolean
-window_state_event_cb (GtkWidget *widget, GdkEventWindowState *event)
-{
- if ((event->changed_mask & GDK_WINDOW_STATE_MAXIMIZED) != 0)
- window_is_maximized = (event->new_window_state & GDK_WINDOW_STATE_MAXIMIZED) != 0;
- if ((event->changed_mask & GDK_WINDOW_STATE_FULLSCREEN) != 0)
- window_is_fullscreen = (event->new_window_state & GDK_WINDOW_STATE_FULLSCREEN) != 0;
- return FALSE;
-}
-
-static void
-startup_cb (GApplication *application)
-{
- gchar *ui_path;
- GtkWidget *hbox;
- GtkWidget *preview_hbox;
- GtkWidget *new_game_button;
- guint i;
- GError *error = NULL;
-
- GActionEntry app_actions[] = {
- { "new-game", game_new_callback },
- { "scores", game_top_ten_callback },
- { "preferences", game_props_callback },
- { "help", game_help_callback },
- { "about", game_about_callback },
- { "quit", game_quit_callback }
- };
-
- g_action_map_add_action_entries (G_ACTION_MAP (application),
- app_actions, G_N_ELEMENTS (app_actions),
- application);
-
- gtk_application_add_accelerator (GTK_APPLICATION (application), "<Primary>N", "app.new-game", NULL);
-
- settings = g_settings_new ("org.gnome.five-or-more");
-
- highscores = games_scores_new ("five-or-more",
- scorecats, G_N_ELEMENTS (scorecats),
- "board size", NULL,
- 0 /* default category */,
- GAMES_SCORES_STYLE_PLAIN_DESCENDING);
-
- init_config ();
-
- builder = gtk_builder_new ();
-
- ui_path = g_build_filename (DATA_DIRECTORY, "menu.ui", NULL);
- gtk_builder_add_from_file (builder, ui_path, &error);
- g_free (ui_path);
-
- if (error) {
- g_critical ("Unable to load the application menu file: %s", error->message);
- g_error_free (error);
- } else {
- gtk_application_set_app_menu (GTK_APPLICATION (application),
- G_MENU_MODEL (gtk_builder_get_object (builder, "appmenu")));
- }
-
- ui_path = g_build_filename (DATA_DIRECTORY, "five-or-more.ui", NULL);
- gtk_builder_add_from_file (builder, ui_path, &error);
- g_free (ui_path);
-
- if (error) {
- g_critical ("Unable to load the user interface file: %s", error->message);
- g_error_free (error);
- g_assert_not_reached ();
- }
-
- app = GTK_WIDGET (gtk_builder_get_object (builder, "glines_window"));
- gtk_window_set_icon_name (GTK_WINDOW (app), "five-or-more");
- g_signal_connect (GTK_WINDOW (app), "size-allocate", G_CALLBACK (window_size_allocate_cb), NULL);
- g_signal_connect (GTK_WINDOW (app), "window-state-event", G_CALLBACK (window_state_event_cb), NULL);
- gtk_window_set_default_size (GTK_WINDOW (app), g_settings_get_int (settings, "window-width"),
g_settings_get_int (settings, "window-height"));
- if (g_settings_get_boolean (settings, "window-is-maximized"))
- gtk_window_maximize (GTK_WINDOW (app));
- gtk_container_set_border_width (GTK_CONTAINER (app), 20);
- gtk_application_add_window (GTK_APPLICATION (application), GTK_WINDOW (app));
-
- headerbar = GTK_WIDGET (gtk_builder_get_object (builder, "headerbar"));
-
- preview_hbox = GTK_WIDGET (gtk_builder_get_object (builder, "preview_hbox"));
-
- for (i = 0; i < MAXNPIECES; i++) {
- preview_images[i] = GTK_IMAGE (gtk_image_new ());
- gtk_box_pack_start (GTK_BOX (preview_hbox), GTK_WIDGET (preview_images[i]), FALSE, FALSE, 0);
- gtk_widget_realize (GTK_WIDGET (preview_images[i]));
- }
-
- scorelabel = GTK_WIDGET (gtk_builder_get_object (builder, "scorelabel"));
-
- hbox = GTK_WIDGET (gtk_builder_get_object (builder, "hbox"));
- draw_area = gtk_drawing_area_new ();
- gtk_widget_set_size_request (draw_area, 300, 300);
- g_signal_connect (draw_area, "button-press-event",
- G_CALLBACK (button_press_event), NULL);
- g_signal_connect (draw_area, "key-press-event",
- G_CALLBACK (key_press_event), NULL);
- g_signal_connect (draw_area, "configure-event",
- G_CALLBACK (configure_event_callback), NULL);
- g_signal_connect (draw_area, "draw",
- G_CALLBACK (field_draw_callback), NULL);
- gridframe = games_grid_frame_new (hfieldsize, vfieldsize);
- games_grid_frame_set_padding (GAMES_GRID_FRAME (gridframe), 1, 1);
- gtk_container_add (GTK_CONTAINER (gridframe), draw_area);
- gtk_box_pack_start (GTK_BOX (hbox), gridframe, TRUE, TRUE, 0);
-
- gtk_widget_set_events (draw_area,
- gtk_widget_get_events (draw_area) |
- GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK);
-
- gtk_widget_set_can_focus (draw_area, TRUE);
- gtk_widget_grab_focus (draw_area);
-
- new_game_button = GTK_WIDGET (gtk_builder_get_object (builder, "new_game_button"));
-
- load_properties ();
-
- gtk_builder_connect_signals (builder, NULL);
-
- g_object_unref (G_OBJECT (builder));
-}
-
-static void
-activate_cb (GApplication *application)
-{
- reset_game ();
- gtk_widget_show_all (app);
- start_game ();
-}
-
-static void
-shutdown_cb (GApplication *application)
-{
- int i = 0;
-
- for (i = 0; i < G_N_ELEMENTS (preview_images); i++)
- if (preview_pixbufs[i])
- g_object_unref (preview_pixbufs[i]);
-
- g_clear_object (&ball_preimage);
- g_object_unref (highscores);
-
- g_settings_set_int (settings, "window-width", window_width);
- g_settings_set_int (settings, "window-height", window_height);
- g_settings_set_boolean (settings, "window-is-maximized", window_is_maximized);
-}
+#include "game-area.h"
+#include "five-or-more-app.h"
int
main (int argc, char *argv[])
@@ -1706,8 +52,9 @@ main (int argc, char *argv[])
textdomain (GETTEXT_PACKAGE);
games_scores_startup ();
+ GRand **rgen = get_rgen();
- rgen = g_rand_new ();
+ *rgen = g_rand_new ();
context = g_option_context_new (NULL);
g_option_context_set_translation_domain (context, GETTEXT_PACKAGE);
@@ -1721,14 +68,13 @@ main (int argc, char *argv[])
exit (1);
}
- g_set_application_name (_("Five or More"));
+ g_set_application_name (_("Five Or More"));
gtk_window_set_default_icon_name ("five-or-more");
application = gtk_application_new ("org.gnome.five-or-more", G_APPLICATION_FLAGS_NONE);
- g_signal_connect (application, "startup", G_CALLBACK (startup_cb), NULL);
- g_signal_connect (application, "activate", G_CALLBACK (activate_cb), NULL);
- g_signal_connect (application, "shutdown", G_CALLBACK (shutdown_cb), NULL);
+ //defined in header
+ set_application_callbacks(application);
status = g_application_run (G_APPLICATION (application), argc, argv);
diff --git a/src/game-area.c b/src/game-area.c
new file mode 100644
index 0000000..7a3043b
--- /dev/null
+++ b/src/game-area.c
@@ -0,0 +1,1057 @@
+/* -*- mode:C; indent-tabs-mode:t; tab-width:8; c-basic-offset:8; -*- */
+
+/*
+ * Color lines for GNOME
+ * Copyright © 1999 Free Software Foundation
+ * Authors: Robert Szokovacs <szo appaloosacorp hu>
+ * Szabolcs Ban <shooby gnome hu>
+ * Karuna Grewal <karunagrewal98 gmail com>
+ * Copyright © 2007 Christian Persch
+ *
+ * This game 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include <config.h>
+
+#include <stdlib.h>
+#include <locale.h>
+#include <math.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <gtk/gtk.h>
+#include <gdk-pixbuf/gdk-pixbuf.h>
+#include <gdk/gdkkeysyms.h>
+
+#include "games-gridframe.h"
+#include "game-area.h"
+#include "five-or-more-app.h"
+#include "balls-preview.h"
+
+#define MAXFIELDSIZE 30
+#define KEY_SIZE "size"
+static GRand *rgen;
+static int inmove = 0;
+static int active = -1;
+static int target = -1;
+
+static int animate_id = 0;
+
+static gboolean show_cursor = FALSE;
+static int cursor_x = MAXFIELDSIZE / 2;
+static int cursor_y = MAXFIELDSIZE / 2;
+static field_props field[MAXFIELDSIZE * MAXFIELDSIZE];
+static gint hfieldsize;
+static gint vfieldsize;
+static int boxsize;
+static gint ncolors;
+
+static gint npieces;
+/* The tile images with balls rendered on them. */
+static cairo_surface_t *ball_surface = NULL;
+/* A cairo_surface_t of a blank tile. */
+static cairo_surface_t *blank_surface = NULL;
+/* Pre-rendering image data prepared from file. */
+static GamesPreimage *ball_preimage = NULL;
+
+enum {
+ UNSET = 0,
+ SMALL = 1,
+ MEDIUM,
+ LARGE,
+ MAX_SIZE,
+};
+
+/* Keep these in sync with the enum above. */
+static const gint field_sizes[MAX_SIZE][4] = {
+ {-1, -1, -1, -1}, /* This is a dummy entry. */
+ {7, 7, 5, 3}, /* SMALL */
+ {9, 9, 7, 3}, /* MEDIUM */
+ {20, 15, 7, 7} /* LARGE */
+};
+
+static scoretable sctab[] =
+ { {5, 10}, {6, 12}, {7, 18}, {8, 28}, {9, 42}, {10, 82}, {11, 108}, {12,
+ 138},
+ {13, 172}, {14, 210}, {0, 0} };
+
+static gchar *warning_message = NULL;
+static GtkWidget *draw_area;
+
+void
+set_sizes (gint size)
+{
+ hfieldsize = field_sizes[size][0];
+ vfieldsize = field_sizes[size][1];
+ ncolors = field_sizes[size][2];
+ npieces = field_sizes[size][3];
+ gint *game_size = get_game_size();
+ *game_size = size;
+ GamesScoresCategory *scorecats = get_scorecats();
+ games_scores_set_category (get_highscores(), scorecats[size - 1].key);
+
+ g_settings_set_int (*(get_settings()), KEY_SIZE, size);
+ GtkWidget *gridframe = get_gridframe();
+ if (gridframe)
+ games_grid_frame_set (GAMES_GRID_FRAME (gridframe),
+ hfieldsize, vfieldsize);
+}
+
+gint
+get_hfieldsize()
+{
+ return hfieldsize;
+}
+
+gint
+get_vfieldsize()
+{
+ return vfieldsize;
+}
+
+gint *
+get_active_status()
+{
+ return &active;
+}
+
+gint *
+get_target_status()
+{
+ return ⌖
+}
+
+gint *
+get_inmove_status()
+{
+ return &inmove;
+}
+
+gint
+get_ncolors()
+{
+ return ncolors;
+}
+
+GRand **
+get_rgen()
+{
+ return &rgen;
+}
+
+GamesPreimage *
+get_ball_preimage()
+{
+ return ball_preimage;
+}
+
+gint
+get_npieces()
+{
+ return npieces;
+}
+
+int
+init_new_balls (int num, int prev)
+{
+ int i, j = -1;
+ gfloat num_boxes = hfieldsize * vfieldsize;
+ for (i = 0; i < num;) {
+ j = g_rand_int_range (rgen, 0, num_boxes);
+ if (field[j].color == 0) {
+ field[j].color = (prev == -1) ?
+ g_rand_int_range (rgen, 1, ncolors + 1) : get_preview()[prev];
+ i++;
+ }
+ }
+ return j;
+}
+
+void
+reset_game (void)
+{
+ int i;
+
+ for (i = 0; i < hfieldsize * vfieldsize; i++) {
+ field[i].color = 0;
+ field[i].phase = 0;
+ field[i].active = 0;
+ field[i].pathsearch = -1;
+ }
+ update_score(0);
+ init_preview ();
+ init_new_balls (npieces, -1);
+}
+
+static void
+fix_route (int num, int pos)
+{
+ int i;
+
+ for (i = 0; i < hfieldsize * vfieldsize; i++)
+ if ((i != pos) && (field[i].pathsearch == num))
+ field[i].pathsearch = -1;
+ if (num < 2)
+ return;
+ if ((pos / hfieldsize > 0)
+ && (field[pos - hfieldsize].pathsearch == num - 1))
+ fix_route (num - 1, pos - hfieldsize);
+ if ((pos % hfieldsize > 0) && (field[pos - 1].pathsearch == num - 1))
+ fix_route (num - 1, pos - 1);
+ if ((pos / hfieldsize < vfieldsize - 1)
+ && (field[pos + hfieldsize].pathsearch == num - 1))
+ fix_route (num - 1, pos + hfieldsize);
+ if ((pos % hfieldsize < hfieldsize - 1)
+ && (field[pos + 1].pathsearch == num - 1))
+ fix_route (num - 1, pos + 1);
+}
+
+static int
+route (int num)
+{
+ int i;
+ int flag = 0;
+
+ if (field[target].pathsearch == num)
+ return 1;
+ for (i = 0; i < hfieldsize * vfieldsize; i++) {
+ if (field[i].pathsearch == num) {
+ flag = 1;
+ if ((i / hfieldsize > 0) && (field[i - hfieldsize].pathsearch == -1)
+ && (field[i - hfieldsize].color == 0))
+ field[i - hfieldsize].pathsearch = num + 1;
+ if ((i / hfieldsize < vfieldsize - 1)
+ && (field[i + hfieldsize].pathsearch == -1)
+ && (field[i + hfieldsize].color == 0))
+ field[i + hfieldsize].pathsearch = num + 1;
+ if ((i % hfieldsize > 0) && (field[i - 1].pathsearch == -1)
+ && (field[i - 1].color == 0))
+ field[i - 1].pathsearch = num + 1;
+ if ((i % hfieldsize < hfieldsize - 1) && (field[i + 1].pathsearch == -1)
+ && (field[i + 1].color == 0)) {
+ field[i + 1].pathsearch = num + 1;
+ }
+ }
+ }
+ if (flag == 0)
+ return 0;
+ return 2;
+}
+
+int
+find_route (void)
+{
+ int i = 0;
+ int j = 0;
+
+ field[active].pathsearch = i;
+ while ((j = route (i))) {
+ if (j == 1) {
+ fix_route (i, target);
+ return 1;
+ }
+ i++;
+ }
+ return 0;
+}
+
+
+static void
+reset_pathsearch (void)
+{
+ int i;
+
+ for (i = 0; i < hfieldsize * vfieldsize; i++)
+ field[i].pathsearch = -1;
+}
+
+void
+draw_box (GtkWidget * widget, int x, int y)
+{
+ gtk_widget_queue_draw_area (widget, x * boxsize, y * boxsize,
+ boxsize, boxsize);
+}
+
+
+static void
+deactivate (GtkWidget * widget, int x, int y)
+{
+ field[active].active = 0;
+ field[active].phase = 0;
+ draw_box (widget, x, y);
+ active = -1;
+}
+
+static int
+spaces_left (void)
+{
+ int i, j;
+
+ j = 0;
+
+ for (i = 0; i < hfieldsize * vfieldsize; i++) {
+ if (field[i].color == 0)
+ j++;
+ }
+
+ return j;
+}
+
+static int
+check_gameover (void)
+{
+ if (spaces_left () > 0)
+ return 1;
+ game_over ();
+ return -1;
+}
+
+
+static int
+addscore (int num)
+{
+ gchar string[20];
+ int i = 0;
+ int retval;
+
+ while ((sctab[i].num != num) && (sctab[i].num != 0))
+ i++;
+ if (sctab[i].num == 0) {
+ num-=5;
+ retval = sctab[num%5].score + 72 * (num/5) + (num-5)*24 ;
+ } else
+ retval = sctab[i].score;
+ update_score(retval);
+
+ return retval;
+}
+
+
+static void
+tag_list (int *list, int len)
+{
+ int i;
+
+ for (i = 0; i < len; i++)
+ field[list[i]].tag = 1;
+}
+
+static int
+find_lines (int num)
+{
+ int count = 1;
+ int subcount = 0;
+ int x = num % hfieldsize;
+ int y = num / hfieldsize;
+ int list[hfieldsize];
+
+ /* Horizontal */
+
+ x++;
+ while ((x <= hfieldsize - 1)
+ && (field[x + y * hfieldsize].color == field[num].color)) {
+ list[subcount] = x + y * hfieldsize;
+ subcount++;
+ x++;
+ }
+ x = num % hfieldsize - 1;
+ while ((x >= 0) && (field[x + y * hfieldsize].color == field[num].color)) {
+ list[subcount] = x + y * hfieldsize;
+ subcount++;
+ x--;
+ }
+ if (subcount >= 4) {
+ field[num].tag = 1;
+ tag_list (list, subcount);
+ count += subcount;
+ }
+ subcount = 0;
+
+ /* Vertical */
+
+ x = num % hfieldsize;
+ y++;
+ while ((y <= vfieldsize - 1)
+ && (field[x + y * hfieldsize].color == field[num].color)) {
+ list[subcount] = x + y * hfieldsize;
+ subcount++;
+ y++;
+ }
+ y = num / hfieldsize - 1;
+ while ((y >= 0) && (field[x + y * hfieldsize].color == field[num].color)) {
+ list[subcount] = x + y * hfieldsize;
+ subcount++;
+ y--;
+ }
+ if (subcount >= 4) {
+ field[num].tag = 1;
+ tag_list (list, subcount);
+ count += subcount;
+ }
+ subcount = 0;
+
+ /* Diagonal ++ */
+
+ x = num % hfieldsize + 1;
+ y = num / hfieldsize + 1;
+ while ((y <= vfieldsize - 1) && (x <= hfieldsize - 1)
+ && (field[x + y * hfieldsize].color == field[num].color)) {
+ list[subcount] = x + y * hfieldsize;
+ subcount++;
+ y++;
+ x++;
+ }
+ x = num % hfieldsize - 1;
+ y = num / hfieldsize - 1;
+ while ((y >= 0) && (x >= 0)
+ && (field[x + y * hfieldsize].color == field[num].color)) {
+ list[subcount] = x + y * hfieldsize;
+ subcount++;
+ y--;
+ x--;
+ }
+ if (subcount >= 4) {
+ field[num].tag = 1;
+ tag_list (list, subcount);
+ count += subcount;
+ }
+ subcount = 0;
+
+ /* Diagonal +- */
+
+ x = num % hfieldsize + 1;
+ y = num / hfieldsize - 1;
+ while ((y >= 0) && (x <= hfieldsize - 1)
+ && (field[x + y * hfieldsize].color == field[num].color)) {
+ list[subcount] = x + y * hfieldsize;
+ subcount++;
+ y--;
+ x++;
+ }
+ x = num % hfieldsize - 1;
+ y = num / hfieldsize + 1;
+ while ((y <= vfieldsize - 1) && (x >= 0)
+ && (field[x + y * hfieldsize].color == field[num].color)) {
+ list[subcount] = x + y * hfieldsize;
+ subcount++;
+ y++;
+ x--;
+ }
+ if (subcount >= 4) {
+ field[num].tag = 1;
+ tag_list (list, subcount);
+ count += subcount;
+ }
+
+ return count;
+}
+
+
+static void
+clear_tags (void)
+{
+ int i;
+
+ for (i = 0; i < hfieldsize * vfieldsize; i++)
+ field[i].tag = 0;
+}
+
+static int
+kill_tags (GtkWidget * widget)
+{
+ int i, j;
+
+ j = 0;
+ for (i = 0; i < hfieldsize * vfieldsize; i++) {
+ if (field[i].tag == 1) {
+ j++;
+ field[i].color = 0;
+ field[i].phase = 0;
+ field[i].active = 0;
+ draw_box (widget, i % hfieldsize, i / hfieldsize);
+ }
+ }
+
+ return j;
+}
+
+static gboolean
+check_goal (GtkWidget * w, int target)
+{
+ gboolean lines_cleared;
+ int count;
+
+ clear_tags ();
+
+ count = find_lines (target);
+ lines_cleared = count >= 5;
+
+ if (lines_cleared) {
+ kill_tags (w);
+ addscore (count);
+ }
+ reset_pathsearch ();
+
+ return lines_cleared;
+}
+
+gint
+animate (gpointer gp)
+{
+ GtkWidget *widget = GTK_WIDGET (gp);
+ int x, y;
+ int newactive = 0;
+
+ x = active % hfieldsize;
+ y = active / hfieldsize;
+
+ if (active == -1) {
+ animate_id = 0;
+ return FALSE;
+ }
+
+ if (inmove != 0) {
+ if ((x > 0)
+ && (field[active - 1].pathsearch == field[active].pathsearch + 1))
+ newactive = active - 1;
+ else if ((x < hfieldsize - 1)
+ && (field[active + 1].pathsearch ==
+ field[active].pathsearch + 1))
+ newactive = active + 1;
+ else if ((y > 0)
+ && (field[active - hfieldsize].pathsearch ==
+ field[active].pathsearch + 1))
+ newactive = active - hfieldsize;
+ else if ((y < vfieldsize - 1)
+ && (field[active + hfieldsize].pathsearch ==
+ field[active].pathsearch + 1))
+ newactive = active + hfieldsize;
+ else {
+ set_inmove (0);
+ }
+ draw_box (widget, x, y);
+ x = newactive % hfieldsize;
+ y = newactive / hfieldsize;
+ field[newactive].phase = field[active].phase;
+ field[newactive].color = field[active].color;
+ field[active].phase = 0;
+ field[active].color = 0;
+ field[active].active = 0;
+ if (newactive == target) {
+ target = -1;
+ set_inmove (0);
+ active = -1;
+ field[newactive].phase = 0;
+ field[newactive].active = 0;
+ draw_box (widget, x, y);
+ reset_pathsearch ();
+ if (!check_goal (widget, newactive)) {
+ gboolean fullline;
+ int balls[npieces];
+ int spaces;
+
+ clear_tags ();
+ fullline = FALSE;
+ spaces = spaces_left ();
+ if (spaces > npieces)
+ spaces = npieces;
+ for (x = 0; x < spaces; x++) {
+ int tmp = init_new_balls (1, x);
+ draw_box (widget, tmp % hfieldsize, tmp / hfieldsize);
+ balls[x] = tmp;
+ fullline = (find_lines (balls[x]) >= 5) || fullline;
+ }
+ if (fullline)
+ addscore (kill_tags (widget));
+ if (check_gameover () == -1)
+ return FALSE;
+ init_preview ();
+ draw_preview ();
+ }
+ return TRUE;
+ }
+ field[newactive].active = 1;
+ active = newactive;
+ }
+
+ field[active].phase++;
+ if (field[active].phase >= 4)
+ field[active].phase = 0;
+ draw_box (widget, x, y);
+
+ return TRUE;
+}
+
+static void
+start_animation (void)
+{
+ int ms;
+
+ ms = (inmove ? get_move_timeout() : 100);
+ if (animate_id == 0)
+ animate_id = g_timeout_add (ms, animate, draw_area);
+}
+
+void
+set_inmove (int i)
+{
+ if (inmove != i) {
+ inmove = i;
+ if (animate_id)
+ g_source_remove (animate_id);
+ animate_id = 0;
+ start_animation ();
+ }
+}
+
+static void
+cell_clicked (GtkWidget * widget, int fx, int fy)
+{
+ int x, y;
+
+ set_status_message (NULL);
+ if (field[fx + fy * hfieldsize].color == 0) {
+ /* Clicked on an empty field */
+
+ if ((active != -1) && (inmove != 1)) {
+ /* We have an active ball, and it's not
+ * already in move. Therefore we should begin
+ * the moving sequence */
+
+ target = fx + fy * hfieldsize;
+ if (find_route ()) {
+ /* We found a route to the new position */
+
+ set_inmove (1);
+ } else {
+ /* Can't move there! */
+ set_status_message (_("You can’t move there!"));
+ reset_pathsearch ();
+ target = -1;
+ }
+ }
+ } else {
+ /* Clicked on a ball */
+
+ if ((fx + fy * hfieldsize) == active) {
+ /* It's active, so let's deactivate it! */
+
+ deactivate (widget, fx, fy);
+ } else {
+ /* It's not active, so let's activate it! */
+
+ if (active != -1) {
+ /* There is an other active ball, we should deactivate it first! */
+
+ x = active % hfieldsize;
+ y = active / hfieldsize;
+ deactivate (widget, x, y);
+ }
+
+ active = fx + fy * hfieldsize;
+ field[active].active = 1;
+ start_animation();
+ }
+ }
+
+}
+
+static gint
+button_press_event (GtkWidget * widget, GdkEvent * event)
+{
+ int x, y;
+ int fx, fy;
+
+ if (inmove)
+ return TRUE;
+
+ /* Ignore the 2BUTTON and 3BUTTON events. */
+ if (event->type != GDK_BUTTON_PRESS)
+ return TRUE;
+
+ if (show_cursor) {
+ show_cursor = FALSE;
+ draw_box (draw_area, cursor_x, cursor_y);//put in header
+ }
+
+ fx = event->button.x / boxsize;
+ fy = event->button.y / boxsize;
+
+ /* If we click on the outer border pixels, the previous calculation
+ * will be wrong and we must correct. */
+ fx = CLAMP (fx, 0, hfieldsize - 1);
+ fy = CLAMP (fy, 0, vfieldsize - 1);
+
+ cursor_x = fx;
+ cursor_y = fy;
+
+ cell_clicked (widget, fx, fy);
+
+ return TRUE;
+}
+
+static void
+move_cursor (int dx, int dy)
+{
+ int old_x = cursor_x;
+ int old_y = cursor_y;
+
+ if (!show_cursor) {
+ show_cursor = TRUE;
+ draw_box (draw_area, cursor_x, cursor_y);
+ }
+
+ cursor_x = cursor_x + dx;
+ if (cursor_x < 0)
+ cursor_x = 0;
+ if (cursor_x >= hfieldsize)
+ cursor_x = hfieldsize - 1;
+ cursor_y = cursor_y + dy;
+ if (cursor_y < 0)
+ cursor_y = 0;
+ if (cursor_y >= vfieldsize)
+ cursor_y = vfieldsize - 1;
+
+ if (cursor_x == old_x && cursor_y == old_y)
+ return;
+
+ draw_box (draw_area, old_x, old_y);
+ draw_box (draw_area, cursor_x, cursor_y);
+}
+
+static gboolean
+key_press_event (GtkWidget * widget, GdkEventKey * event, void *d)
+{
+ guint key;
+
+ key = event->keyval;
+
+ switch (key) {
+ case GDK_KEY_Left:
+ case GDK_KEY_KP_Left:
+ move_cursor (-1, 0);
+ break;
+ case GDK_KEY_Right:
+ case GDK_KEY_KP_Right:
+ move_cursor (1, 0);
+ break;
+ case GDK_KEY_Up:
+ case GDK_KEY_KP_Up:
+ move_cursor (0, -1);
+ break;
+ case GDK_KEY_Down:
+ case GDK_KEY_KP_Down:
+ move_cursor (0, 1);
+ break;
+ case GDK_KEY_Home:
+ case GDK_KEY_KP_Home:
+ move_cursor (-999, 0);
+ break;
+ case GDK_KEY_End:
+ case GDK_KEY_KP_End:
+ move_cursor (999, 0);
+ break;
+ case GDK_KEY_Page_Up:
+ case GDK_KEY_KP_Page_Up:
+ move_cursor (0, -999);
+ break;
+ case GDK_KEY_Page_Down:
+ case GDK_KEY_KP_Page_Down:
+ move_cursor (0, 999);
+ break;
+
+ case GDK_KEY_space:
+ case GDK_KEY_Return:
+ case GDK_KEY_KP_Enter:
+ if (show_cursor)
+ cell_clicked (widget, cursor_x, cursor_y);
+ break;
+ }
+
+ return TRUE;
+}
+
+static void
+draw_grid (cairo_t *cr)
+{
+ GdkRGBA color;
+ guint w, h;
+ guint i;
+ w = gtk_widget_get_allocated_width(draw_area);
+ h = gtk_widget_get_allocated_height(draw_area);
+
+ gdk_rgba_parse (&color, "#525F6C");
+ gdk_cairo_set_source_rgba (cr, &color);
+ cairo_set_line_width (cr, 1.0);
+
+ for (i = boxsize; i < w; i = i + boxsize)
+ {
+ cairo_move_to (cr, i + 0.5, 0 + 0.5);
+ cairo_line_to (cr, i + 0.5, h + 0.5);
+ }
+
+ for (i = boxsize; i < h; i = i + boxsize)
+ {
+ cairo_move_to (cr, 0 + 0.5, i + 0.5);
+ cairo_line_to (cr, w + 0.5, i + 0.5);
+ }
+
+ cairo_rectangle (cr, 0.5, 0.5, w - 0.5, h - 0.5);
+ cairo_stroke (cr);
+}
+
+static GamesPreimage *
+load_image (gchar * fname)
+{
+ GamesPreimage *preimage;
+ gchar *path;
+ GError *error = NULL;
+
+ path = g_build_filename (DATA_DIRECTORY, "themes", fname, NULL);
+ if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
+ warning_message = g_strdup_printf (_("Unable to locate file:\n%s\n\n"
+ "The default theme will be loaded instead."),
+ fname);
+
+ path = g_build_filename (DATA_DIRECTORY, "themes", "balls.svg", NULL);
+ if (!g_file_test (path, G_FILE_TEST_EXISTS)) {
+ g_free (warning_message);
+ warning_message = g_strdup_printf (_("Unable to locate file:\n%s\n\n"
+ "Please check that Five or More is installed correctly."),
+ fname);
+ }
+ }
+
+ preimage = games_preimage_new_from_file (path, &error);
+ g_free (path);
+
+ if (error) {
+ warning_message = g_strdup (error->message);
+ g_error_free (error);
+ }
+
+ return preimage;
+}
+
+static void
+show_image_warning (gchar * message)
+{
+ GtkWidget *dialog;
+ GtkWidget *button;
+
+ dialog = gtk_message_dialog_new (NULL,
+ GTK_DIALOG_MODAL,
+ GTK_MESSAGE_WARNING,
+ GTK_BUTTONS_CLOSE,
+ "%s",_("Could not load theme"));
+
+ gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
+ "%s", message);
+
+ button = gtk_dialog_add_button (GTK_DIALOG (dialog),
+ _("Preferences"), GTK_RESPONSE_ACCEPT);
+
+ gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_ACCEPT);
+
+ g_signal_connect (button, "clicked", G_CALLBACK (game_props_callback),
+ NULL);
+
+ gtk_dialog_run (GTK_DIALOG (dialog));
+ gtk_widget_destroy (dialog);
+}
+
+void
+refresh_pixmaps (void)
+{
+ cairo_t *cr, *cr_blank;
+ GdkPixbuf *ball_pixbuf = NULL;
+ background backgnd = get_backgnd();
+ /* Since we get called both by configure and after loading an image.
+ * it is possible the pixmaps aren't initialised. If they aren't
+ * we don't do anything. */
+ if (!ball_surface)
+ return;
+
+ if (!boxsize)
+ return;
+
+ if (ball_preimage) {
+ ball_pixbuf = games_preimage_render (ball_preimage, 4 * boxsize,
+ 7 * boxsize);
+
+ /* Handle rendering problems. */
+ if (!ball_pixbuf) {
+ g_object_unref (ball_preimage);
+ ball_preimage = NULL;
+
+ if (!warning_message) {
+ warning_message = g_strdup ("The selected theme failed to render.\n\n"
+ "Please check that Five or More is installed correctly.");
+ }
+ }
+ }
+
+ if (!ball_pixbuf) {
+ ball_pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8,
+ 4 * boxsize, 7 * boxsize);
+ gdk_pixbuf_fill (ball_pixbuf, 0x00000000);
+ }
+
+ if (warning_message)
+ show_image_warning (warning_message);
+ g_free (warning_message);
+ warning_message = NULL;
+
+ cr = cairo_create (ball_surface);
+ gdk_cairo_set_source_rgba (cr, &backgnd.color);
+
+ cairo_rectangle (cr, 0, 0, boxsize * 4, boxsize * 7);
+ cairo_fill (cr);
+
+ gdk_cairo_set_source_pixbuf (cr, ball_pixbuf, 0, 0);
+ cairo_mask (cr, cairo_get_source (cr));
+ g_object_unref (ball_pixbuf);
+
+ cairo_destroy (cr);
+
+ cr_blank = cairo_create (blank_surface);
+ gdk_cairo_set_source_rgba (cr_blank, &backgnd.color);
+
+ cairo_rectangle (cr_blank, 0, 0, boxsize, boxsize);
+ cairo_fill (cr_blank);
+
+ cairo_destroy (cr_blank);
+}
+
+static void
+draw_all_balls (GtkWidget * widget)
+{
+ gdk_window_invalidate_rect (gtk_widget_get_window (widget), NULL, FALSE);
+}
+
+void
+refresh_screen (void)
+{
+ draw_all_balls (draw_area);
+ draw_preview ();
+}
+
+static int
+configure_event_callback (GtkWidget * widget, GdkEventConfigure * event)
+{
+ if (ball_surface)
+ cairo_surface_destroy(ball_surface);
+
+ if (blank_surface)
+ cairo_surface_destroy (blank_surface);
+
+ boxsize = (event->width - 1) / hfieldsize;
+ ball_surface = gdk_window_create_similar_surface (gtk_widget_get_window (draw_area),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ boxsize * 4, boxsize * 7);
+ blank_surface = gdk_window_create_similar_surface (gtk_widget_get_window (draw_area),
+ CAIRO_CONTENT_COLOR_ALPHA,
+ boxsize, boxsize);
+ refresh_pixmaps ();
+
+ refresh_screen ();
+
+ return TRUE;
+}
+
+void
+load_theme (void)
+{
+ if (ball_preimage)
+ g_object_unref (ball_preimage);
+ char *ball_filename = get_ball_filename();
+ ball_preimage = load_image (ball_filename);
+
+ refresh_pixmaps ();
+ refresh_preview_surfaces ();
+}
+
+static gboolean
+field_draw_callback (GtkWidget * widget, cairo_t *cr)
+{
+ guint i, j, idx;
+ GdkRGBA cursorColor;
+ background backgnd = get_backgnd();
+
+ for (i = 0; i < vfieldsize; i++) {
+ for (j = 0; j < hfieldsize; j++) {
+ int phase, color;
+
+ idx = j + i * hfieldsize;
+
+ cairo_rectangle (cr, j * boxsize, i * boxsize, boxsize, boxsize);
+
+ if (field[idx].color != 0) {
+ phase = field[idx].phase;
+ color = field[idx].color - 1;
+
+ phase = ABS (ABS (3 - phase) - 3);
+
+ cairo_set_source_surface (cr, ball_surface,
+ (1.0 * j - phase) * boxsize,
+ (1.0 * i - color) * boxsize);
+ } else {
+ cairo_set_source_surface (cr, blank_surface, 1.0 * j * boxsize, 1.0 * i * boxsize);
+ }
+
+ cairo_fill (cr);
+ }
+ }
+
+ /* Cursor */
+ if (show_cursor) {
+ if (((backgnd.color.red + backgnd.color.green + backgnd.color.blue) / 3) > 0.5)
+ gdk_rgba_parse (&cursorColor, "#000000");
+ else
+ gdk_rgba_parse (&cursorColor, "#FFFFFF");
+
+ gdk_cairo_set_source_rgba (cr, &cursorColor);
+ cairo_set_line_width (cr, 1.0);
+ cairo_rectangle (cr,
+ cursor_x * boxsize + 1.5, cursor_y * boxsize + 1.5,
+ boxsize - 2.5, boxsize - 2.5);
+ cairo_stroke (cr);
+ }
+
+ draw_grid (cr);
+
+ return FALSE;
+}
+
+GtkWidget *
+game_area_init (void)
+{
+ draw_area = gtk_drawing_area_new ();
+ gtk_widget_set_size_request (draw_area, 300, 300);
+ g_signal_connect (draw_area, "button-press-event",
+ G_CALLBACK (button_press_event), NULL);
+ g_signal_connect (draw_area, "key-press-event",
+ G_CALLBACK (key_press_event), NULL);
+ g_signal_connect (draw_area, "configure-event",
+ G_CALLBACK (configure_event_callback), NULL);
+ g_signal_connect (draw_area, "draw",
+ G_CALLBACK (field_draw_callback), NULL);
+ gtk_widget_set_events (draw_area,
+ gtk_widget_get_events (draw_area) |
+ GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_KEY_PRESS_MASK);
+
+ gtk_widget_set_can_focus (draw_area, TRUE);
+ gtk_widget_grab_focus (draw_area);
+ return draw_area;
+}
\ No newline at end of file
diff --git a/src/game-area.h b/src/game-area.h
new file mode 100644
index 0000000..44d3303
--- /dev/null
+++ b/src/game-area.h
@@ -0,0 +1,55 @@
+/*
+ * Color lines for GNOME
+ * Copyright © 1999 Free Software Foundation
+ * Authors: Robert Szokovacs <szo appaloosacorp hu>
+ * Szabolcs Ban <shooby gnome hu>
+ * Karuna Grewal <karunagrewal98 gmail com>
+ * Copyright © 2007 Christian Persch
+ *
+ * This game 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, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, see <https://www.gnu.org/licenses/>.
+ */
+
+#ifndef GAME_AREA_H
+#define GAME_AREA_H
+
+#include <gtk/gtk.h>
+#include "games-preimage.h"
+
+typedef struct {
+ int num;
+ int score;
+} scoretable;
+
+typedef struct {
+ int color;
+ int pathsearch;
+ int phase;
+ int active;
+ int tag;
+} field_props;
+
+GRand **get_rgen ();
+GamesPreimage *get_ball_preimage ();
+gint get_npieces ();
+void set_inmove (int i);
+void refresh_pixmaps (void);
+void refresh_screen (void);
+void load_theme (void);
+GtkWidget * game_area_init (void);
+gint get_ncolors ();
+void set_sizes (gint size);
+void reset_game (void);
+gint get_hfieldsize ();
+gint get_vfieldsize ();
+#endif
\ No newline at end of file
diff --git a/src/meson.build b/src/meson.build
index ab170fa..de29f83 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -3,6 +3,12 @@
five_or_more_c_sources = [
'five-or-more.c',
'five-or-more.h',
+ 'game-area.h',
+ 'game-area.c',
+ 'five-or-more-app.c',
+ 'five-or-more-app.h',
+ 'balls-preview.c',
+ 'balls-preview.h',
'games-file-list.c',
'games-file-list.h',
'games-gridframe.c',
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]