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