Used strlen instead of checking first byte for NUL and added some
[neverball] / ball / st_save.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 <string.h>
16 #include <ctype.h>
17
18 #include "gui.h"
19 #include "game.h"
20 #include "util.h"
21 #include "audio.h"
22 #include "config.h"
23 #include "demo.h"
24
25 #include "st_shared.h"
26 #include "st_save.h"
27
28 extern struct state st_save;
29 extern struct state st_clobber;
30
31 static char filename[MAXNAM];
32
33 /*---------------------------------------------------------------------------*/
34
35 static struct state *ok_state;
36 static struct state *cancel_state;
37
38 int goto_save(struct state *ok, struct state *cancel)
39 {
40     demo_unique(filename);
41
42     ok_state     = ok;
43     cancel_state = cancel;
44
45     return goto_state(&st_save);
46 }
47
48 /*---------------------------------------------------------------------------*/
49
50 static int file_id;
51
52 #define SAVE_SAVE   1
53 #define SAVE_CANCEL 2
54
55 static int save_action(int i)
56 {
57     size_t l = strlen(filename);
58
59     audio_play(AUD_MENU, 1.0f);
60
61     switch (i)
62     {
63     case SAVE_SAVE:
64         if (strlen(filename) == 0)
65             return 1;
66         if (demo_exists(filename))
67             return goto_state(&st_clobber);
68         else
69         {
70             demo_play_save(filename);
71             return goto_state(ok_state);
72         }
73
74     case SAVE_CANCEL:
75         return goto_state(cancel_state);
76
77     case GUI_CL:
78         gui_keyboard_lock();
79         break;
80
81     case GUI_BS:
82         if (l > 0)
83         {
84             filename[l - 1] = 0;
85             gui_set_label(file_id, filename);
86         }
87         break;
88
89     default:
90         if (l < MAXNAM - 1)
91         {
92             filename[l + 0] = (char) i;
93             filename[l + 1] = 0;
94             gui_set_label(file_id, filename);
95         }
96     }
97     return 1;
98 }
99
100 static int enter_id;
101
102 static int save_enter(void)
103 {
104     int id, jd;
105
106     if ((id = gui_vstack(0)))
107     {
108         gui_label(id, _("Replay Name"), GUI_MED, GUI_ALL, 0, 0);
109
110         gui_space(id);
111
112         file_id = gui_label(id, filename, GUI_MED, GUI_ALL, gui_yel, gui_yel);
113
114         gui_space(id);
115
116         gui_keyboard(id);
117
118         if ((jd = gui_harray(id)))
119         {
120             enter_id = gui_start(jd, _("Save"), GUI_SML, SAVE_SAVE, 0);
121             gui_state(jd, _("Cancel"), GUI_SML, SAVE_CANCEL, 0);
122         }
123
124         gui_layout(id, 0, 0);
125     }
126
127     SDL_EnableUNICODE(1);
128
129     return id;
130 }
131
132 static void save_leave(int id)
133 {
134     SDL_EnableUNICODE(0);
135     gui_delete(id);
136 }
137
138 static int save_keybd(int c, int d)
139 {
140     if (d && (c & 0xFF80) == 0)
141     {
142         gui_focus(enter_id);
143
144         if (c == '\b' || c == 0x7F)
145             return save_action(GUI_BS);
146         if (c > ' ')
147             return save_action(c);
148     }
149     return 1;
150 }
151
152 static int save_buttn(int b, int d)
153 {
154     if (d)
155     {
156         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
157         {
158             int c = gui_token(gui_click());
159
160             /* Ugh.  This is such a hack. */
161
162             return save_action(isupper(c) ? gui_keyboard_char(c) : c);
163         }
164         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
165             return save_action(SAVE_CANCEL);
166     }
167     return 1;
168 }
169
170 /*---------------------------------------------------------------------------*/
171
172 static int clobber_action(int i)
173 {
174     audio_play(AUD_MENU, 1.0f);
175
176     if (i == SAVE_SAVE)
177     {
178         demo_play_save(filename);
179         return goto_state(ok_state);
180     }
181     return goto_state(&st_save);
182 }
183
184 static int clobber_enter(void)
185 {
186     int id, jd, kd;
187
188     if ((id = gui_vstack(0)))
189     {
190         kd = gui_label(id, _("Overwrite?"), GUI_MED, GUI_ALL, gui_red, gui_red);
191
192         gui_label(id, filename, GUI_MED, GUI_ALL, gui_yel, gui_yel);
193
194         if ((jd = gui_harray(id)))
195         {
196             gui_start(jd, _("No"),  GUI_SML, SAVE_CANCEL, 1);
197             gui_state(jd, _("Yes"), GUI_SML, SAVE_SAVE,   0);
198         }
199
200         gui_pulse(kd, 1.2f);
201         gui_layout(id, 0, 0);
202     }
203
204     return id;
205 }
206
207 static int clobber_buttn(int b, int d)
208 {
209     if (d)
210     {
211         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_A, b))
212             return clobber_action(gui_token(gui_click()));
213         if (config_tst_d(CONFIG_JOYSTICK_BUTTON_EXIT, b))
214             return clobber_action(SAVE_CANCEL);
215     }
216     return 1;
217 }
218
219 /*---------------------------------------------------------------------------*/
220
221 struct state st_save = {
222     save_enter,
223     save_leave,
224     shared_paint,
225     shared_timer,
226     shared_point,
227     shared_stick,
228     shared_click,
229     save_keybd,
230     save_buttn,
231     1, 0
232 };
233
234 struct state st_clobber = {
235     clobber_enter,
236     shared_leave,
237     shared_paint,
238     shared_timer,
239     shared_point,
240     shared_stick,
241     shared_click,
242     NULL,
243     clobber_buttn,
244     1, 0
245 };