Yay, I'm in the AUTHORS file too!
[neverball] / ball / util.c
1 /*
2  * Copyright (C) 2003 Robert Kooima
3  *
4  * NEVERBALL is  free software; you can redistribute  it and/or modify
5  * it under the  terms of the GNU General  Public License as published
6  * by the Free  Software Foundation; either version 2  of the License,
7  * or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful, but
10  * WITHOUT  ANY  WARRANTY;  without   even  the  implied  warranty  of
11  * MERCHANTABILITY or  FITNESS FOR A PARTICULAR PURPOSE.   See the GNU
12  * General Public License for more details.
13  */
14
15 #include <ctype.h>
16 #include <string.h>
17
18 #include "gui.h"
19 #include "util.h"
20 #include "config.h"
21
22 /*---------------------------------------------------------------------------*/
23
24 static int is_special_name(const char *n)
25 {
26     return (strcmp(n, N_("Hard"))   == 0 ||
27             strcmp(n, N_("Medium")) == 0 ||
28             strcmp(n, N_("Easy"))   == 0);
29 }
30
31 /*---------------------------------------------------------------------------*/
32
33 static int coin_coin[4];
34 static int coin_name[4];
35 static int coin_time[4];
36
37 static int coin_extra_row;
38
39 /* Build a Most Coins top three list with default values. */
40
41 static void gui_most_coins(int id, int e)
42 {
43     const char *s = "1234567";
44
45     int j, jd, kd, ld, md;
46
47     coin_extra_row = e;
48
49     if ((jd = gui_hstack(id)))
50     {
51         gui_filler(jd);
52
53         if ((kd = gui_vstack(jd)))
54         {
55             gui_label(kd, _("Most Coins"), GUI_SML, GUI_TOP, 0, 0);
56
57             if ((ld = gui_hstack(kd)))
58             {
59                 if ((md = gui_vstack(ld)))
60                 {
61                     for (j = 0; j < NSCORE - 1; j++)
62                         coin_coin[j] = gui_count(md, 1000, GUI_SML, 0);
63
64                     coin_coin[j++] = gui_count(md, 1000, GUI_SML, GUI_SE);
65
66                     if (e)
67                     {
68                         gui_space(md);
69                         coin_coin[j++] = gui_count(md, 1000, GUI_SML, GUI_RGT);
70                     }
71                 }
72
73                 if ((md = gui_vstack(ld)))
74                 {
75                     for (j = 0; j < NSCORE ; j++)
76                         coin_name[j] = gui_label(md, s, GUI_SML, 0,
77                                                  gui_yel, gui_wht);
78
79                     if (e)
80                     {
81                         gui_space(md);
82                         coin_name[j++] = gui_label(md, s, GUI_SML, 0,
83                                                    gui_yel, gui_wht);
84                     }
85                 }
86
87                 if ((md = gui_vstack(ld)))
88                 {
89                     for (j = 0; j < NSCORE - 1; j++)
90                         coin_time[j] = gui_clock(md, 359999, GUI_SML, 0);
91
92                     coin_time[j++] = gui_clock(md, 359999, GUI_SML, GUI_SW);
93
94                     if (e)
95                     {
96                         gui_space(md);
97                         coin_time[j++] = gui_clock(md, 359999, GUI_SML, GUI_LFT);
98                     }
99                 }
100             }
101         }
102         gui_filler(jd);
103     }
104 }
105
106 /* Set the Most Coins top three list values. */
107
108 static void set_most_coins(const struct score *s, int hilight)
109 {
110     const char *name;
111     int j;
112
113     if (s == NULL)
114     {
115         for (j = 0; j < NSCORE + coin_extra_row ; j++)
116         {
117             gui_set_count(coin_coin[j], -1);
118             gui_set_label(coin_name[j], "");
119             gui_set_clock(coin_time[j], -1);
120         }
121     }
122     else
123     {
124         for (j = 0; j < NSCORE + coin_extra_row; j++)
125         {
126             name = s->player[j];
127
128             if (j == hilight)
129             {
130                 if (j < NSCORE)
131                     gui_set_color(coin_name[j], gui_grn, gui_grn);
132                 else
133                     gui_set_color(coin_name[j], gui_red, gui_red);
134             }
135             else
136                 gui_set_color(coin_name[j], gui_yel, gui_wht);
137
138             gui_set_count(coin_coin[j], s->coins[j]);
139             gui_set_label(coin_name[j], is_special_name(name) ? _(name) : name);
140             gui_set_clock(coin_time[j], s->timer[j]);
141         }
142     }
143 }
144
145 /*---------------------------------------------------------------------------*/
146
147 static int time_label;
148
149 static int time_coin[4];
150 static int time_name[4];
151 static int time_time[4];
152
153 static int time_extra_row;
154
155 /* Build a Best Times top three list with default values. */
156
157 static void gui_best_times(int id, int e)
158 {
159     const char *s = "1234567";
160
161     int j, jd, kd, ld, md;
162
163     time_extra_row = e;
164
165     if ((jd = gui_hstack(id)))
166     {
167         gui_filler(jd);
168
169         if ((kd = gui_vstack(jd)))
170         {
171             time_label = gui_label(kd, "XXX", GUI_SML, GUI_TOP, 0, 0);
172
173             if ((ld = gui_hstack(kd)))
174             {
175                 if ((md = gui_vstack(ld)))
176                 {
177                     for (j = 0; j < NSCORE - 1; j++)
178                         time_time[j] = gui_clock(md, 359999, GUI_SML, 0);
179
180                     time_time[j++] = gui_clock(md, 359999, GUI_SML, GUI_SE);
181
182                     if (e)
183                     {
184                         gui_space(md);
185                         time_time[j++] = gui_clock(md, 359999, GUI_SML, GUI_RGT);
186                     }
187                 }
188
189                 if ((md = gui_vstack(ld)))
190                 {
191                     for (j = 0; j < NSCORE; j++)
192                         time_name[j] = gui_label(md, s, GUI_SML, 0,
193                                                  gui_yel, gui_wht);
194
195                     if (e)
196                     {
197                         gui_space(md);
198                         time_name[j++] = gui_label(md, s, GUI_SML, 0,
199                                                    gui_yel, gui_wht);
200                     }
201                 }
202
203                 if ((md = gui_vstack(ld)))
204                 {
205                     for (j = 0; j < NSCORE - 1; j++)
206                         time_coin[j] = gui_count(md, 1000, GUI_SML, 0);
207
208                     time_coin[j++] = gui_count(md, 1000, GUI_SML, GUI_SW);
209
210                     if (e)
211                     {
212                         gui_space(md);
213                         time_coin[j++] = gui_count(md, 1000, GUI_SML, GUI_LFT);
214                     }
215                 }
216             }
217         }
218         gui_filler(jd);
219     }
220 }
221
222 /* Set the Best Times top three list values. */
223
224 static void set_best_times(const struct score *s, int hilight, int goal)
225 {
226     const char *name;
227     int j;
228
229     gui_set_label(time_label, goal ? _("Unlock Goal") : _("Best Times"));
230
231     if (s == NULL)
232     {
233         for (j = 0; j < NSCORE + time_extra_row ; j++)
234         {
235             gui_set_clock(time_time[j], -1);
236             gui_set_label(time_name[j], "");
237             gui_set_count(time_coin[j], -1);
238         }
239     }
240     else
241     {
242         for (j = 0; j < NSCORE + time_extra_row; j++)
243         {
244             name = s->player[j];
245
246             if (j == hilight)
247             {
248                 if (j < NSCORE)
249                     gui_set_color(time_name[j], gui_grn, gui_grn);
250                 else
251                     gui_set_color(time_name[j], gui_red, gui_red);
252             }
253             else
254                 gui_set_color(time_name[j], gui_yel, gui_wht);
255
256             gui_set_clock(time_time[j], s->timer[j]);
257             gui_set_label(time_name[j], is_special_name(name) ? _(name) : name);
258             gui_set_count(time_coin[j], s->coins[j]);
259         }
260     }
261 }
262
263 /*---------------------------------------------------------------------------*/
264
265 static int score_type = GUI_MOST_COINS;
266
267 void gui_score_board(int id, int e, int h)
268 {
269     int jd, kd, ld;
270
271     gui_filler(id);
272
273     if ((jd = gui_hstack(id)))
274     {
275         gui_filler(jd);
276
277         if ((kd = gui_vstack(jd)))
278         {
279             gui_filler(kd);
280
281             gui_state(kd, _("Most Coins"),  GUI_SML, GUI_MOST_COINS,
282                       score_type == GUI_MOST_COINS);
283             gui_state(kd, _("Best Times"),  GUI_SML, GUI_BEST_TIMES,
284                       score_type == GUI_BEST_TIMES);
285             gui_state(kd, _("Unlock Goal"), GUI_SML, GUI_UNLOCK_GOAL,
286                       score_type == GUI_UNLOCK_GOAL);
287
288             if (h)
289             {
290                 gui_space(kd);
291
292                 if ((ld = gui_hstack(kd)))
293                 {
294                     gui_filler(ld);
295                     gui_state(ld, _("Change Name"), GUI_SML, GUI_NAME, 0);
296                     gui_filler(ld);
297                 }
298             }
299
300             gui_filler(kd);
301         }
302
303         gui_filler(jd);
304     }
305
306     gui_filler(id);
307
308     switch (score_type)
309     {
310     case GUI_MOST_COINS:
311         gui_most_coins(id, e);
312         break;
313
314     case GUI_BEST_TIMES:
315         gui_best_times(id, e);
316         break;
317
318     case GUI_UNLOCK_GOAL:
319         gui_best_times(id, e);
320         break;
321     }
322
323     gui_filler(id);
324 }
325
326 void set_score_board(const struct score *smc, int hmc,
327                      const struct score *sbt, int hbt,
328                      const struct score *sug, int hug)
329 {
330     switch (score_type)
331     {
332     case GUI_MOST_COINS:
333         set_most_coins(smc, hmc);
334         break;
335
336     case GUI_BEST_TIMES:
337         set_best_times(sbt, hbt, 0);
338         break;
339
340     case GUI_UNLOCK_GOAL:
341         set_best_times(sug, hug, 1);
342         break;
343     }
344 }
345
346 void gui_score_set(int t)
347 {
348     score_type = t;
349 }
350
351 int  gui_score_get(void)
352 {
353     return score_type;
354 }
355
356 int  gui_score_next(int t)
357 {
358     switch (t)
359     {
360     case GUI_MOST_COINS:  return GUI_BEST_TIMES;
361     case GUI_BEST_TIMES:  return GUI_UNLOCK_GOAL;
362     case GUI_UNLOCK_GOAL: return GUI_MOST_COINS;
363
364     default:
365         return GUI_MOST_COINS;
366     }
367 }
368
369 /*---------------------------------------------------------------------------*/
370
371 static int lock = 1;
372 static int keyd[127];
373
374 void gui_keyboard(int id)
375 {
376     int jd, kd, ld;
377
378     lock = 1;
379
380     if ((jd = gui_hstack(id)))
381     {
382         gui_filler(jd);
383
384         if ((kd = gui_vstack(jd)))
385         {
386             if ((ld = gui_hstack(kd)))
387             {
388                 gui_filler(ld);
389
390                 keyd['9'] = gui_state(ld, "9", GUI_SML, '9', 0);
391                 keyd['8'] = gui_state(ld, "8", GUI_SML, '8', 0);
392                 keyd['7'] = gui_state(ld, "7", GUI_SML, '7', 0);
393                 keyd['6'] = gui_state(ld, "6", GUI_SML, '6', 0);
394                 keyd['5'] = gui_state(ld, "5", GUI_SML, '5', 0);
395                 keyd['4'] = gui_state(ld, "4", GUI_SML, '4', 0);
396                 keyd['3'] = gui_state(ld, "3", GUI_SML, '3', 0);
397                 keyd['3'] = gui_state(ld, "2", GUI_SML, '2', 0);
398                 keyd['1'] = gui_state(ld, "1", GUI_SML, '1', 0);
399                 keyd['0'] = gui_state(ld, "0", GUI_SML, '0', 0);
400                 gui_filler(ld);
401             }
402             if ((ld = gui_hstack(kd)))
403             {
404                 gui_filler(ld);
405                 keyd['J'] = gui_state(ld, "J", GUI_SML, 'J', 0);
406                 keyd['I'] = gui_state(ld, "I", GUI_SML, 'I', 0);
407                 keyd['H'] = gui_state(ld, "H", GUI_SML, 'H', 0);
408                 keyd['G'] = gui_state(ld, "G", GUI_SML, 'G', 0);
409                 keyd['F'] = gui_state(ld, "F", GUI_SML, 'F', 0);
410                 keyd['E'] = gui_state(ld, "E", GUI_SML, 'E', 0);
411                 keyd['D'] = gui_state(ld, "D", GUI_SML, 'D', 0);
412                 keyd['C'] = gui_state(ld, "C", GUI_SML, 'C', 0);
413                 keyd['B'] = gui_state(ld, "B", GUI_SML, 'B', 0);
414                 keyd['A'] = gui_state(ld, "A", GUI_SML, 'A', 0);
415                 gui_filler(ld);
416             }
417             if ((ld = gui_hstack(kd)))
418             {
419                 gui_filler(ld);
420                 keyd['T'] = gui_state(ld, "T", GUI_SML, 'T', 0);
421                 keyd['S'] = gui_state(ld, "S", GUI_SML, 'S', 0);
422                 keyd['R'] = gui_state(ld, "R", GUI_SML, 'R', 0);
423                 keyd['Q'] = gui_state(ld, "Q", GUI_SML, 'Q', 0);
424                 keyd['P'] = gui_state(ld, "P", GUI_SML, 'P', 0);
425                 keyd['O'] = gui_state(ld, "O", GUI_SML, 'O', 0);
426                 keyd['N'] = gui_state(ld, "N", GUI_SML, 'N', 0);
427                 keyd['M'] = gui_state(ld, "M", GUI_SML, 'M', 0);
428                 keyd['L'] = gui_state(ld, "L", GUI_SML, 'L', 0);
429                 keyd['K'] = gui_state(ld, "K", GUI_SML, 'K', 0);
430                 gui_filler(ld);
431             }
432             if ((ld = gui_hstack(kd)))
433             {
434                 gui_filler(ld);
435                 gui_state(ld, "<", GUI_SML, GUI_BS, 0);
436                 keyd['Z'] = gui_state(ld, "Z", GUI_SML, 'Z', 0);
437                 keyd['Y'] = gui_state(ld, "Y", GUI_SML, 'Y', 0);
438                 keyd['X'] = gui_state(ld, "X", GUI_SML, 'X', 0);
439                 keyd['W'] = gui_state(ld, "W", GUI_SML, 'W', 0);
440                 keyd['V'] = gui_state(ld, "V", GUI_SML, 'V', 0);
441                 keyd['U'] = gui_state(ld, "U", GUI_SML, 'U', 0);
442                 gui_state(ld, _("caps"), GUI_SML, GUI_CL, 0);
443                 gui_filler(ld);
444             }
445         }
446         gui_filler(jd);
447     }
448 }
449
450 void gui_keyboard_lock(void)
451 {
452     lock = lock ? 0 : 1;
453
454     gui_set_label(keyd['A'], lock ? "A" : "a");
455     gui_set_label(keyd['B'], lock ? "B" : "b");
456     gui_set_label(keyd['C'], lock ? "C" : "c");
457     gui_set_label(keyd['D'], lock ? "D" : "d");
458     gui_set_label(keyd['E'], lock ? "E" : "e");
459     gui_set_label(keyd['F'], lock ? "F" : "f");
460     gui_set_label(keyd['G'], lock ? "G" : "g");
461     gui_set_label(keyd['H'], lock ? "H" : "h");
462     gui_set_label(keyd['I'], lock ? "I" : "i");
463     gui_set_label(keyd['J'], lock ? "J" : "j");
464     gui_set_label(keyd['K'], lock ? "K" : "k");
465     gui_set_label(keyd['L'], lock ? "L" : "l");
466     gui_set_label(keyd['M'], lock ? "M" : "m");
467     gui_set_label(keyd['N'], lock ? "N" : "n");
468     gui_set_label(keyd['O'], lock ? "O" : "o");
469     gui_set_label(keyd['P'], lock ? "P" : "p");
470     gui_set_label(keyd['Q'], lock ? "Q" : "q");
471     gui_set_label(keyd['R'], lock ? "R" : "r");
472     gui_set_label(keyd['S'], lock ? "S" : "s");
473     gui_set_label(keyd['T'], lock ? "T" : "t");
474     gui_set_label(keyd['U'], lock ? "U" : "u");
475     gui_set_label(keyd['V'], lock ? "V" : "v");
476     gui_set_label(keyd['W'], lock ? "W" : "w");
477     gui_set_label(keyd['X'], lock ? "X" : "x");
478     gui_set_label(keyd['Y'], lock ? "Y" : "y");
479     gui_set_label(keyd['Z'], lock ? "Z" : "z");
480 }
481
482 char gui_keyboard_char(char c)
483 {
484     return lock ? toupper(c) : tolower(c);
485 }
486
487 /*---------------------------------------------------------------------------*/
488
489 /*
490  * XXX Watch  out when  using these  functions. Be  sure to  check for
491  * GUI_NULL in addition to GUI_NEXT and GUI_PREV when using the latter
492  * two as labels for a switch with a default label.
493  */
494
495 int gui_back_prev_next(int id, int prev, int next)
496 {
497     int jd;
498
499     if ((jd = gui_hstack(id)))
500     {
501         if (next || prev)
502         {
503             gui_maybe(jd, _("Next"), GUI_NEXT, next);
504             gui_maybe(jd, _("Prev"), GUI_PREV, prev);
505         }
506
507         gui_start(jd, _("Back"), GUI_SML, GUI_BACK, 0);
508     }
509     return jd;
510 }
511
512 int gui_maybe(int id, const char *label, int token, int enabled)
513 {
514     int bd;
515
516     if (!enabled)
517     {
518         bd = gui_state(id,
519                        label,
520                        GUI_SML,
521                        token >= 0 ? token | GUI_NULL_MASK : GUI_NULL,
522                        0);
523
524         gui_set_color(bd, gui_gry, gui_gry);
525     }
526     else bd = gui_state(id, label, GUI_SML, token, 0);
527
528     return bd;
529 }
530
531 /*---------------------------------------------------------------------------*/