This is the doxygen documentation for gtkboard.

.
Main Page   Data Structures   File List   Data Fields   Globals  

prefs.c

Go to the documentation of this file.
00001 /*  This file is a part of gtkboard, a board games system.
00002     Copyright (C) 2003, Arvind Narayanan <arvindn@users.sourceforge.net>
00003 
00004     This program is free software; you can redistribute it and/or modify
00005     it under the terms of the GNU General Public License as published by
00006     the Free Software Foundation; either version 2 of the License, or
00007     (at your option) any later version.
00008 
00009     This program is distributed in the hope that it will be useful,
00010     but WITHOUT ANY WARRANTY; without even the implied warranty of
00011     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00012     GNU General Public License for more details.
00013 
00014     You should have received a copy of the GNU General Public License
00015     along with this program; if not, write to the Free Software
00016     Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA
00017 
00018 */
00019 #include <time.h>
00020 #include <stdio.h>
00021 #include <sys/types.h>
00022 #include <sys/stat.h>
00023 #include <unistd.h>
00024 #include <string.h>
00025 #include <stdlib.h>
00026 
00027 #include "prefs.h"
00028 #include "ui_common.h"
00029 
00030 static Score scores[MAX_HIGHSCORES];
00031 static int num_highscores = 0;
00032 static gchar *gamename; // ugly
00033 
00034 SCORE_FIELD prefs_score_fields_def[] = 
00035 {SCORE_FIELD_USER, SCORE_FIELD_SCORE, SCORE_FIELD_TIME, SCORE_FIELD_DATE, SCORE_FIELD_NONE};
00036 
00037 gchar* prefs_score_field_names_def[] = {"User", "Score", "Time", "Date", NULL};
00038 
00039 static void prefs_strip_special_chars (gchar *str)
00040         // $ is the field separator in our scores file
00041         // '<' and '>' are used for markup in GtkLabel
00042 {
00043         for (; *str; str++)
00044                 if (*str == '$' || *str == '<' || *str == '>')
00045                         *str = ' ';
00046 }
00047 
00048 static gboolean prefs_create_dir (gchar *dir)
00049 {
00050         int retval;
00051         struct stat Stat;
00052         retval = stat (dir, &Stat);
00053         if (retval < 0)
00054         {
00055                 // try to create the directory
00056                 retval = mkdir (dir, 0755);
00057                 if (retval < 0) return FALSE;
00058         }
00059         else if (!S_ISDIR (Stat.st_mode)) return FALSE;
00060         return TRUE;
00061 }
00062 
00063 static gboolean prefs_first_time ()
00064 {
00065         static gboolean first_time = TRUE;
00066         static gboolean status = FALSE;
00067         gchar * prefsdir, *tempstr;
00068         if (!first_time) return status;
00069         first_time = FALSE;
00070         prefsdir = g_strdup_printf ("%s/%s", getenv("HOME"), ".gtkboard");
00071         if (!prefs_create_dir (prefsdir)) return FALSE;
00072         tempstr = g_strdup_printf ("%s/%s", prefsdir, "scores");
00073         if (!prefs_create_dir (tempstr)) return FALSE;
00074         g_free (tempstr);
00075         tempstr = g_strdup_printf ("%s/%s", prefsdir, "prefs");
00076         if (!prefs_create_dir (tempstr)) return FALSE;
00077         g_free (tempstr);
00078         tempstr = g_strdup_printf ("%s/%s", prefsdir, "plugins");
00079         if (!prefs_create_dir (tempstr)) return FALSE;
00080         g_free (tempstr);
00081         g_free (prefsdir);
00082         return status = TRUE;
00083 }
00084 
00085 gboolean prefs_load_scores (gchar *name)
00086 {
00087         gchar *scorefile;
00088         FILE *in;
00089         char linebuf[128];
00090         int i;
00091         gamename = name;
00092         if (!prefs_first_time ()) return FALSE;
00093         scorefile = g_strdup_printf ("%s/%s/%s", getenv("HOME"), 
00094                         ".gtkboard/scores", name);
00095         in = fopen (scorefile, "r");
00096         if (!in) 
00097         { 
00098                 g_free (scorefile);             
00099                 return FALSE;
00100         }
00101         for (i=0; !feof (in) && i < MAX_HIGHSCORES;)
00102         {
00103                 gchar **realline;
00104                 gchar ** score_fields;
00105                 /*
00106                 if (fscanf (in, "%[^$]$%[^$]$%d$%d\n", 
00107                                 scores[i].name, scores[i].score, 
00108                                 &scores[i].time, &scores[i].date) == EOF)*/
00109                 //scanf is buggy!!! - %[] shouldn't strip leading whitespace but does
00110                 if (!fgets (linebuf, 128, in))
00111                         break;
00112                 realline = g_strsplit (linebuf, "#", -1);
00113                 score_fields = g_strsplit (realline[0], "$", -1);
00114                 if (!score_fields[0] || !score_fields[1])
00115                 {
00116                         g_strfreev (realline);
00117                         g_strfreev (score_fields);
00118                         continue;
00119                 }
00120                 if (!score_fields[2] || !score_fields[3])
00121                 {
00122                         sb_error ("Error loading scores file", FALSE);
00123                         g_strfreev (realline);
00124                         g_strfreev (score_fields);
00125                         break;
00126                 }
00127                 strncpy (scores[i].name, score_fields[0], 31);
00128                 strncpy (scores[i].score, score_fields[1], 31);
00129                 scores[i].time = atoi(score_fields[2]);
00130                 scores[i].date = atoi(score_fields[3]);
00131                 g_strfreev (realline);
00132                 g_strfreev (score_fields);
00133                 i++;
00134         }
00135         num_highscores = i;
00136         fclose (in);
00137         g_free (scorefile);
00138         return TRUE;
00139 }
00140 
00141 static void prefs_show_scores_real (int index)
00142 {
00143         int i, j;
00144         gchar tempstr [128], tempstr1[128];
00145         time_t temps;
00146         GtkWidget *dialog, *okay_button, *label, *hbox, *vboxes[5];
00147         
00148         snprintf (tempstr, 128, "%s highscores - gtkboard", gamename);
00149 
00150 #if GTK_MAJOR_VERSION == 1
00151         dialog = gtk_dialog_new();
00152         gtk_window_set_title (GTK_WINDOW (dialog), tempstr);
00153         okay_button = gtk_button_new_with_label("OK");
00154 
00155         gtk_signal_connect_object (GTK_OBJECT (okay_button), "clicked",
00156                         GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog);
00157         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area),
00158                         okay_button);
00159         gtk_box_set_spacing (GTK_BOX (GTK_DIALOG(dialog)->vbox), 5);
00160         snprintf (tempstr, 128, "%s highscores", gamename);
00161         label = gtk_label_new (tempstr);
00162 #else
00163         dialog = gtk_dialog_new_with_buttons (tempstr, GTK_WINDOW (main_window),
00164                         GTK_DIALOG_MODAL, NULL);
00165         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 100);
00166         okay_button = gtk_dialog_add_button (GTK_DIALOG (dialog), 
00167                         GTK_STOCK_OK, GTK_RESPONSE_NONE);
00168         g_signal_connect_swapped (GTK_OBJECT (dialog), 
00169                         "response", G_CALLBACK (gtk_widget_destroy), GTK_OBJECT (dialog));
00170         gtk_box_set_spacing (GTK_BOX (GTK_DIALOG(dialog)->vbox), 5);
00171         snprintf (tempstr, 128, "<big>%s highscores</big>", gamename);
00172         label = gtk_label_new ("");
00173         gtk_label_set_markup (GTK_LABEL (label), tempstr);
00174 #endif
00175         gtk_widget_grab_focus (okay_button);
00176 
00177         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label);
00178         hbox = gtk_hbox_new (FALSE, 20);
00179         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), hbox);
00180         
00181         for (i=0; i<=num_highscores; i++)
00182         {
00183                 int num_score_fields;
00184                 gchar *strings[10];
00185                 gboolean found = FALSE;
00186                 for (j=0; !found && j < 10; j++)
00187                 {
00188                         switch (game_score_fields[j])
00189                         {
00190                                 case SCORE_FIELD_NONE: found = TRUE; break;
00191                                 case SCORE_FIELD_RANK:
00192                                            sprintf (tempstr, "%d", i);
00193                                            strings[j] = i ? tempstr : game_score_field_names[j];
00194                                            break;
00195                                 case SCORE_FIELD_USER:
00196                                                 strings[j] = i ? scores[i-1].name : game_score_field_names[j];
00197                                                 break;
00198                                 case SCORE_FIELD_SCORE:
00199                                                 strings[j] = i ? scores[i-1].score : game_score_field_names[j];
00200                                                 break;
00201                                 case SCORE_FIELD_TIME:
00202                                                 strings[j] = i ? sb_ftime (scores[i-1].time) : game_score_field_names[j];
00203                                                 break;
00204                                 case SCORE_FIELD_DATE:
00205                                                 temps = scores[i-1].date;
00206                                                 strncpy (tempstr1, ctime (&temps), 127);
00207                                                 tempstr1 [strlen (tempstr1) - 1] = '\0';
00208                                                 strings[j] = i ? tempstr1  : game_score_field_names[j];
00209                                                 break;
00210                                 default:
00211                                                 break;
00212                         }
00213                 }
00214                 num_score_fields = j-1;
00215                 for (j=0; j<num_score_fields; j++)
00216                 {
00217                         if (i == 0)
00218                         {
00219                                 vboxes[j] = gtk_vbox_new (FALSE, 0);
00220                                 gtk_box_pack_start (GTK_BOX (hbox), vboxes[j], TRUE, TRUE, 0);
00221                         }
00222                         label = gtk_label_new ("");
00223 #if GTK_MAJOR_VERSION > 1
00224                         gtk_label_set_selectable (GTK_LABEL (label), TRUE);
00225                         if (i > 0 && i-1 == index)
00226                         {
00227                                 gchar *tempstr = g_strdup_printf 
00228                                         ("<span foreground=\"blue\">%s</span>", strings[j]);
00229                                 gtk_label_set_markup (GTK_LABEL (label), tempstr);
00230                                 g_free (tempstr);
00231                         }
00232                         else
00233 #endif
00234                                 gtk_label_set_text (GTK_LABEL (label), strings[j]);
00235                         gtk_box_pack_start (GTK_BOX (vboxes[j]), label, FALSE, FALSE, 
00236                                         i ? 0 : 5);
00237                 }
00238         }
00239         gtk_widget_show_all (dialog);
00240 }
00241 
00242 void prefs_show_scores ()
00243 {
00244         if (!gamename)
00245                 return;
00246         prefs_show_scores_real (-1);
00247 }
00248 
00249 gboolean prefs_save_scores (gchar *name)
00250 {
00251         gchar *scorefile;
00252         FILE *out;
00253         char linebuf[128];
00254         int i;
00255         if (!prefs_first_time ()) return FALSE;
00256         scorefile = g_strdup_printf ("%s/%s/%s", getenv("HOME"), 
00257                         ".gtkboard/scores", name);
00258         out = fopen (scorefile, "w");
00259         if (!out) 
00260         { 
00261                 gchar *tempstr;
00262                 sb_error (tempstr = g_strdup_printf 
00263                                 ("couldn't write to %s", scorefile),
00264                                 FALSE);
00265                 g_free (tempstr);
00266                 g_free (scorefile);             
00267                 return FALSE;
00268         }
00269         fprintf (out, "#This is the gtkboard highscores file for the game %s\n"
00270                         "#The format is: name$score$time taken in ms$date (time (2))\n"
00271                         "#VERSION=0.10.0\n"
00272                         , gamename);
00273         for (i=0; i < num_highscores; i++)
00274         {
00275                 fprintf (out, "%s$%s$%d$%d\n", 
00276                                 scores[i].name, scores[i].score, 
00277                                 scores[i].time, scores[i].date);
00278         }
00279         fclose (out);
00280         g_free (scorefile);
00281         gamename = NULL;
00282         return TRUE;
00283 }
00284 
00285 int prefs_scorecmp_dscore (gchar *score1, int temps1, gchar* score2, int temps2)
00286 {
00287         int s1 = atoi (score1);
00288         int s2 = atoi (score2);
00289         if (s1 > s2) return 1;
00290         if (s1 < s2) return -1;
00291         if (temps1 < temps2) return 1;
00292         if (temps1 > temps2) return -1;
00293         return 0;
00294 }
00295 
00296 int prefs_scorecmp_iscore (gchar *score1, int temps1, gchar* score2, int temps2)
00297 {
00298         int s1 = atoi (score1);
00299         int s2 = atoi (score2);
00300         if (s1 < s2) return 1;
00301         if (s1 > s2) return -1;
00302         if (temps1 < temps2) return 1;
00303         if (temps1 > temps2) return -1;
00304         return 0;
00305 }
00306 
00307 int prefs_scorecmp_time (gchar *score1, int temps1, gchar* score2, int temps2)
00308 {
00309         if (temps1 < temps2) return 1;
00310         if (temps1 > temps2) return -1;
00311         return 0;
00312 }
00313 
00314 static int  highscore_temps, highscore_index, highscore_date;
00315 static gchar highscore_score[32];
00316 
00317 static void prefs_username_cb (GtkWidget *dialog, GtkEntry *entry)
00318 {
00319         int j;
00320         gchar username[32], *namep;
00321         strncpy (username, gtk_entry_get_text (entry), 31);
00322         prefs_strip_special_chars (username);
00323         for (j = num_highscores + 1; j > highscore_index; j--)
00324         {
00325                 if (j >= MAX_HIGHSCORES) continue;
00326                 memcpy (scores + j, scores + j - 1, sizeof (Score));
00327         }
00328         strncpy (scores[highscore_index].name, username, 31);
00329         snprintf (scores[highscore_index].score, 32, "%d", atoi (highscore_score));
00330         scores[highscore_index].time = highscore_temps;
00331         scores[highscore_index].date = highscore_date;
00332         if (num_highscores < MAX_HIGHSCORES) num_highscores++;
00333         gtk_widget_destroy (GTK_WIDGET (dialog));
00334         prefs_show_scores_real (highscore_index);
00335 }
00336 
00337 void prefs_show_username_dialog ()
00338 {
00339         GtkWidget *dialog, *label, *hbox, *entry;
00340         gchar *title = "Enter your name - gtkboard";
00341         
00342         entry = gtk_entry_new_with_max_length (31);
00343         gtk_entry_set_text (GTK_ENTRY (entry), getenv ("USER"));
00344         gtk_widget_grab_focus (entry);
00345 
00346 #if GTK_MAJOR_VERSION == 1
00347         dialog = gtk_dialog_new();
00348         gtk_window_set_title (GTK_WINDOW (dialog), title);
00349         gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (main_window));
00350         gtk_window_set_modal (GTK_WINDOW (dialog), TRUE);
00351         gtk_signal_connect_object (GTK_OBJECT (entry), "activate",
00352                         GTK_SIGNAL_FUNC (prefs_username_cb), GTK_OBJECT (dialog));
00353 #else
00354         dialog = gtk_dialog_new_with_buttons (title, GTK_WINDOW (main_window),
00355                         GTK_DIALOG_MODAL, NULL);
00356         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 100);
00357         g_signal_connect_swapped (GTK_OBJECT (entry),
00358                         "activate", G_CALLBACK (prefs_username_cb), GTK_OBJECT (dialog));
00359         gtk_dialog_add_button (GTK_DIALOG (dialog), GTK_STOCK_OK, GTK_RESPONSE_NONE);
00360 #endif
00361 
00362         label = gtk_label_new ("You've got a highscore!");
00363         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label);
00364         hbox = gtk_hbox_new (TRUE, 0);
00365         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), hbox);
00366         label = gtk_label_new ("Enter your name");
00367         gtk_container_add (GTK_CONTAINER (hbox), label);
00368         gtk_container_add (GTK_CONTAINER (hbox), entry);
00369         gtk_widget_show_all (dialog);
00370 #if GTK_MAJOR_VERSION > 1
00371         gtk_dialog_run (GTK_DIALOG (dialog));
00372         prefs_username_cb (dialog, GTK_ENTRY (entry));
00373 #endif
00374 }
00375 
00376 void prefs_add_highscore (gchar *score, int temps)
00377         // the argument score is the string returned by game_who_won. We expect
00378         // it to have a substring which is an integer
00379 {
00380         int i, j;
00381         char *realscore = strpbrk (score, "0123456789");
00382         if (!realscore) realscore = "";
00383         if (!game_scorecmp) return;
00384         for (i=0; i<num_highscores; i++)
00385                 if (game_scorecmp (realscore, temps, 
00386                                         scores[i].score, scores[i].time) > 0)
00387                         break;
00388         if (i == MAX_HIGHSCORES) return;
00389         highscore_index = i;
00390         strncpy (highscore_score, realscore, 31);
00391         prefs_strip_special_chars (highscore_score);
00392         highscore_temps = temps;
00393         highscore_date = time (0);
00394         prefs_show_username_dialog ();
00395 }
00396 
00397 void prefs_zap_highscores ()
00398 {
00399         gchar *tempstr;
00400         GtkWidget *dialog, *label;
00401         gint result;
00402         if (!gamename) return;
00403 #if GTK_MAJOR_VERSION == 1
00404         menu_show_dialog ("Zapped highscores",
00405                         tempstr = g_strdup_printf ("Zapped %s highscores", gamename));
00406         g_free (tempstr);
00407 #else
00408         dialog = gtk_dialog_new_with_buttons ("Zap highscores?", 
00409                         GTK_WINDOW (main_window), GTK_DIALOG_MODAL, 
00410                         GTK_STOCK_YES, GTK_RESPONSE_ACCEPT,
00411                         GTK_STOCK_NO, GTK_RESPONSE_REJECT,
00412                         NULL);
00413         tempstr = g_strdup_printf (
00414                         "<b>Warning</b>: This will clear your %s highscores.\n"
00415            "Your highscores in other games will be unaffected.\nProceed?", gamename);
00416         label = gtk_label_new (NULL);
00417         gtk_label_set_markup (GTK_LABEL (label), tempstr);
00418         g_free (tempstr);
00419         gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label);
00420         gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 100);
00421         gtk_widget_show_all (dialog);
00422         result = gtk_dialog_run (GTK_DIALOG (dialog));
00423         gtk_widget_destroy (dialog);
00424         if (result == GTK_RESPONSE_REJECT)
00425                 return;
00426 #endif
00427         num_highscores = 0;
00428 }