1 /* */
2 /* score.c -- for xemeraldia */
3 /* */
4 /* This file is copied from "xtetris" Version 2.5, and modified */
5
6 #ifdef HAVE_CONFIG_H
7 #include <config.h>
8 #endif
9
10 #include "games.h"
11 #include <string.h>
12 #include <errno.h>
13 #include <sys/file.h>
14 #include <sys/types.h>
15 #include <time.h>
16 #include <unistd.h>
17
18 #ifdef HAVE_FCNTL_H
19 #include <fcntl.h>
20 #endif
21
22 FILE *f_scores = NULL;
23 int errno_scores;
24
25 /* #define DEBUG */
26
27 #define HIGH_TABLE_SIZE 30 /* size of high score table */
28
29 static struct score_table
30 {
31 char name[28];
32 int score;
33 int level;
34 time_t date;
35 } high_scores[HIGH_TABLE_SIZE];
36
37
update_highscore_table()38 void update_highscore_table ()
39 {
40 int i, j;
41
42 if (! app_data.usescorefile) return;
43 read_high_scores ();
44
45 /* Check for previous best score */
46 for (i = 0; i < HIGH_TABLE_SIZE; i++)
47 {
48 if (strcmp (name, high_scores[i].name) == 0) break;
49 }
50 if (i < HIGH_TABLE_SIZE)
51 {
52 /* We have a previous best score. */
53 if (high_scores[i].score >= sc)
54 return; /* Same/worse score - no update */
55 for (j = i; j > 0; j--) /* Remove previous best */
56 high_scores[j] = high_scores[j - 1];
57 }
58
59 /* Next line finds score greater than current one */
60 for (i = 0; i < HIGH_TABLE_SIZE && sc >= high_scores[i].score; i++);
61 i--;
62 if (i >= 0)
63 {
64 for (j = 0; j < i; j++)
65 high_scores[j] = high_scores[j + 1];
66 strcpy(high_scores[i].name, name);
67 high_scores[i].score = sc;
68 high_scores[i].level = blocks / 20 + 1;
69 time(&(high_scores[i].date));
70 write_high_scores ();
71 }
72 }
73
open_high_scores_file()74 void open_high_scores_file()
75 {
76 f_scores = fopen (app_data.scorefile, "r+");
77 if(!f_scores)
78 f_scores = fopen (app_data.scorefile, "w+");
79 if(!f_scores)
80 errno_scores = errno;
81 #ifdef HAVE_SETREGID
82 setregid(getgid(),getgid());
83 #endif
84 }
85
read_high_scores()86 void read_high_scores()
87 {
88 int i;
89 #if HAVE_LOCKF
90 struct flock fl;
91 #endif
92
93 if (! app_data.usescorefile) return;
94
95 #ifdef F_SETLKW
96 fl.l_type = F_RDLCK;
97 fl.l_whence = SEEK_SET;
98 fl.l_start = 0;
99 fl.l_len = 0;
100 if(fcntl(fileno(f_scores), F_SETLKW, &fl))
101 {
102 perror(_("read_high_scores:can't lock for reading"));
103 return;
104 }
105 #elif HAVE_FLOCK
106 if(flock(fileno(f_scores), LOCK_SH) == -1)
107 {
108 perror(_("read_high_scores:can't lock for reading"));
109 return;
110 }
111 #endif
112 clearerr(f_scores);
113 rewind(f_scores);
114 for (i = 0; i < HIGH_TABLE_SIZE; i++)
115 {
116 struct score_table *score = &(high_scores[i]);
117 if(feof(f_scores) || ferror(f_scores) || 4 != fscanf(f_scores, "%12[^,],%7d,%6d,%ld\n",
118 score->name,
119 &score->score,
120 &score->level,
121 &score->date))
122 {
123 strcpy( score->name, _("No name") );
124 score->date = -1;
125 score->level = score->score = 0;
126 }
127 }
128 #ifdef F_SETLKW
129 fl.l_type = F_UNLCK;
130 if(fcntl(fileno(f_scores), F_SETLKW, &fl))
131 perror(_("read_high_scores:can't unlock"));
132 #elif HAVE_FLOCK
133 if (flock (fileno (f_scores), LOCK_UN) == -1)
134 perror (_("read_high_scores:can't unlock"));
135 #endif
136 }
137
138
write_high_scores()139 void write_high_scores()
140 {
141 int i;
142 #if HAVE_LOCKF
143 struct flock fl;
144 #endif
145
146 #ifdef F_SETLKW
147 fl.l_type = F_WRLCK;
148 fl.l_whence = SEEK_SET;
149 fl.l_start = 0;
150 fl.l_len = 0;
151 if(fcntl(fileno(f_scores), F_SETLKW, &fl))
152 {
153 perror(_("write_high_scores:can't lock for writing"));
154 return;
155 }
156 #elif HAVE_FLOCK
157 if (flock(fileno(f_scores), LOCK_EX) == -1)
158 {
159 perror(_("write_high_scores:can't lock for writing"));
160 return;
161 }
162 #endif
163 rewind(f_scores);
164 if(ftruncate(fileno(f_scores), 0) != 0)
165 {
166 perror(_("write_high_scores:can't truncate scores file"));
167 return;
168 }
169 for (i = 0; i < HIGH_TABLE_SIZE; i++)
170 fprintf (f_scores, "%-12s,%7d,%6d,%ld\n",
171 high_scores[i].name,
172 high_scores[i].score,
173 high_scores[i].level,
174 high_scores[i].date);
175 fflush(f_scores);
176 #if HAVE_LOCKF
177 fl.l_type = F_UNLCK;
178 if(fcntl(fileno(f_scores), F_SETLKW, &fl))
179 perror(_("write_high_scores:can't unlock"));
180 #elif HAVE_FLOCK
181 if (flock (fileno (f_scores), LOCK_UN) == -1)
182 perror (_("write_high_scores:can't unlock"));
183 #endif
184 }
185
186
PrintHighScores()187 void PrintHighScores ()
188 {
189 GtkWidget *table, *align, *scroll;
190 GtkListStore *model;
191 GtkTreeIter iter;
192 GtkCellRenderer *renderer;
193 GtkTreeViewColumn *column;
194 GtkTreeSelection *sel;
195 int i;
196
197 if (! app_data.usescorefile) return;
198 read_high_scores();
199 score_frame = gtk_dialog_new_with_buttons(_("xemeraldia's high scores"),
200 GTK_WINDOW(topLevel),
201 GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT,
202 GTK_STOCK_CLOSE, GTK_RESPONSE_ACCEPT,
203 NULL);
204 gtk_dialog_set_default_response(GTK_DIALOG(score_frame), GTK_RESPONSE_ACCEPT);
205
206 model = gtk_list_store_new(4,
207 G_TYPE_STRING, G_TYPE_INT, G_TYPE_INT, G_TYPE_STRING);
208
209 for (i = HIGH_TABLE_SIZE-1; i >= 0; i--)
210 {
211 if (high_scores[i].score != 0)
212 {
213 char d[100], *dd;
214 strftime(d, sizeof(d), "%c", localtime(&(high_scores[i].date)));
215 dd = g_locale_to_utf8(d, -1, NULL, NULL, NULL);
216 gtk_list_store_append(model, &iter);
217 gtk_list_store_set(model, &iter,
218 0, high_scores[i].name,
219 1, high_scores[i].score,
220 2, high_scores[i].level,
221 3, dd,
222 -1);
223 g_free(dd);
224 }
225 }
226
227 table = gtk_tree_view_new_with_model(GTK_TREE_MODEL(model));
228 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(table), TRUE);
229 sel = gtk_tree_view_get_selection(GTK_TREE_VIEW(table));
230 gtk_tree_selection_set_mode(sel, GTK_SELECTION_NONE);
231
232 renderer = gtk_cell_renderer_text_new ();
233 column = gtk_tree_view_column_new_with_attributes (_("Name"),
234 renderer,
235 "text", 0,
236 NULL);
237 gtk_tree_view_append_column (GTK_TREE_VIEW (table), column);
238
239 renderer = gtk_cell_renderer_text_new ();
240 column = gtk_tree_view_column_new_with_attributes (_("Score"),
241 renderer,
242 "text", 1,
243 NULL);
244 gtk_tree_view_append_column (GTK_TREE_VIEW (table), column);
245
246 renderer = gtk_cell_renderer_text_new ();
247 column = gtk_tree_view_column_new_with_attributes (_("Level"),
248 renderer,
249 "text", 2,
250 NULL);
251 gtk_tree_view_append_column (GTK_TREE_VIEW (table), column);
252
253 renderer = gtk_cell_renderer_text_new ();
254 column = gtk_tree_view_column_new_with_attributes (_("Date"),
255 renderer,
256 "text", 3,
257 NULL);
258 gtk_tree_view_append_column (GTK_TREE_VIEW (table), column);
259
260 align = gtk_alignment_new(.5, .5, .8, .7);
261 gtk_box_pack_start(GTK_BOX(GTK_DIALOG(score_frame)->vbox), align, TRUE, TRUE, 0);
262
263 scroll = gtk_scrolled_window_new(NULL, NULL);
264 gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
265
266 gtk_container_add(GTK_CONTAINER(scroll), table);
267
268 gtk_container_add(GTK_CONTAINER(align), scroll);
269
270 // gtk_box_pack_start(GTK_BOX(GTK_DIALOG(score_frame)->vbox), gtk_label_new("Hola"), TRUE, TRUE, 0);
271
272 gtk_widget_set_size_request(score_frame,500,200);
273
274 gtk_widget_show_all(score_frame);
275 gtk_dialog_run(GTK_DIALOG(score_frame));
276 gtk_widget_destroy(score_frame);
277 }
278