61de6b6991fba50c54baa4d86f48110e6ed9ad7e
[wordblah.git] / wordblox.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <time.h>
4 #include <stdbool.h>
5 #include <string.h>
6 #include <ctype.h>
7
8 #include "wordblox.h"
9 #include "constantstrings.h"
10
11 /* export the clues to a text file */
12 void do_export_clues (Puzzle *p)
13 {
14 if (p->grid_frozen == false)
15 {
16 printf (UNFROZEN_GRID);
17 char ch = getchar ();
18 return;
19 }
20 char fname[256];
21 printf (INPUT_FILE);
22 fgets (fname, 256, stdin);
23 if (strlen(fname) == 1)
24 return;
25 char *filename = strtok (fname, "\n");
26
27 export_clues (p, filename);
28 printf (FILE_SAVED);
29 char ch = getchar ();
30 }
31
32 /* export the puzzle to a png file */
33 void do_export_puzzle (Puzzle *p)
34 {
35 if (p->grid_frozen == false)
36 {
37 printf (UNFROZEN_GRID);
38 char ch = getchar ();
39 return;
40 }
41 char fname[256];
42 printf (INPUT_FILE);
43 fgets (fname, 256, stdin);
44 if (strlen (fname) == 1)
45 return;
46 char* filename = strtok (fname, "\n");
47
48 printf (INPUT_EXPORT_ANSWERS);
49 char ans[3];
50 fgets (ans, 3, stdin);
51 bool solution;
52 solution = (toupper (ans[0]) == 'Y') ? true : false;
53
54 export_grid_image (p, filename, solution);
55 printf (FILE_SAVED);
56 char ch = getchar ();
57 }
58
59 /* reset the grid */
60 void do_reset_puzzle (Puzzle *p)
61 {
62 int grid_size = p->grid_size;
63 printf (INPUT_CONFIRM_RESET);
64 char conf[3];
65 fgets (conf, 3, stdin);
66 if (toupper (conf[0]) == 'Y')
67 init_puzzle (p, grid_size);
68
69 print_puzzle (p);
70 char ch = getchar ();
71 }
72
73 /* set the password for the puzzle */
74 void do_set_password (Puzzle *p)
75 {
76 printf (INPUT_PASSWORD);
77 char password[256];
78 fgets (password, 256, stdin);
79 /* if empty reset the password to nothing */
80 if (strlen (password) == 1)
81 {
82 set_puzzle_password (p, "\0");
83 printf (PASSWORD_RESET);
84 char ch = getchar ();
85 }
86 /* set the password */
87 else
88 {
89 char *passwd = strtok (password, "\n");
90
91 set_puzzle_password (p, (const char* )passwd);
92 printf (PASSWORD_SET);
93 char ch = getchar ();
94 }
95 }
96
97 /* set clue for a word - only for frozen grid */
98 void do_set_clue_word (Puzzle *p, enum ORIENTATION orient)
99 {
100 print_puzzle (p);
101 if (p->grid_frozen == false)
102 {
103 printf (UNFROZEN_GRID);
104 char ch = getchar ();
105 return;
106 }
107 int index;
108 String clue;
109 printf (INPUT_INDEX);
110 index = get_num ();
111 printf (INPUT_CLUE);
112 fgets (clue, MAX_CLUE_LENGTH, stdin);
113 char* cl = strtok (clue, "\n");
114
115 bool res;
116 res = set_clue (p, cl, index, orient);
117
118 if (res == false)
119 {
120 printf (NO_WORD_INDEX);
121 char ch = getchar ();
122 }
123 }
124
125 /* clear a cell in the grid */
126 void do_clear_cell (Puzzle *p)
127 {
128 print_puzzle (p);
129 if (p->grid_frozen == true)
130 {
131 printf (FROZEN_GRID);
132 char ch = getchar ();
133 return;
134 }
135 int row, col;
136 printf (INPUT_ROW);
137 row = get_num ();
138 printf (INPUT_COL);
139 col = get_num ();
140 if (row >= p->grid_size || col >= p->grid_size)
141 {
142 printf (EXCEED_GRID_SIZE);
143 char ch = getchar ();
144 return;
145 }
146 p->chars[row][col] = ' ';
147 print_puzzle (p);
148
149 char ch = getchar ();
150 }
151
152 /* add a down word to the grid */
153 void do_add_down_word (Puzzle *p)
154 {
155 print_puzzle (p);
156 if (p->grid_frozen == true)
157 {
158 printf (FROZEN_GRID);
159 char ch = getchar ();
160 return;
161 }
162 char wd[MAX_PUZZLE_SIZE];
163 int row, col;
164 printf (INPUT_WORD);
165 fgets (wd, MAX_PUZZLE_SIZE, stdin);
166 char *word = is_valid_word (wd);
167 if (word == NULL)
168 {
169 printf (INVALID_WORD);
170 char ch = getchar ();
171 return;
172 }
173 printf (INPUT_ROW);
174 row = get_num ();
175 printf (INPUT_COL);
176 col = get_num ();
177 if (row >= p->grid_size || col >= p->grid_size)
178 {
179 printf (EXCEED_GRID_SIZE);
180 char ch = getchar ();
181 return;
182 }
183 if (strlen (word) > (p->grid_size - row))
184 {
185 printf (WORD_TOO_LONG);
186 char ch = getchar ();
187 return;
188 }
189
190 for (int i = row; i < row + strlen(word); i ++)
191 p->chars[i][col] = toupper(word[i - row]);
192
193 print_puzzle (p);
194 char ch = getchar ();
195 }
196
197 /* add an across word to the grid */
198 void do_add_across_word (Puzzle *p)
199 {
200 print_puzzle (p);
201 if (p->grid_frozen == true)
202 {
203 printf (FROZEN_GRID);
204 char ch = getchar ();
205 return;
206 }
207 char wd[MAX_PUZZLE_SIZE];
208 int row, col;
209 printf (INPUT_WORD);
210 fgets (wd, MAX_PUZZLE_SIZE, stdin);
211 char *word = is_valid_word (wd);
212 if (word == NULL)
213 {
214 printf (INVALID_WORD);
215 char ch = getchar ();
216 return;
217 }
218 printf (INPUT_ROW);
219 row = get_num ();
220 printf (INPUT_COL);
221 col = get_num ();
222 if (row >= p->grid_size || col >= p->grid_size)
223 {
224 printf (EXCEED_GRID_SIZE);
225 char ch = getchar ();
226 return;
227 }
228
229 if (strlen (word) > (p->grid_size - col))
230 {
231 printf (WORD_TOO_LONG);
232 char ch = getchar ();
233 return;
234 }
235
236 for (int i = col; i < col+strlen (word); i ++)
237 p->chars[row][i] = toupper(word[i - col]);
238
239 print_puzzle (p);
240 char ch = getchar ();
241 }
242 /* confirm exit */
243 bool do_confirm_exit ()
244 {
245 printf (INPUT_CONFIRM_EXIT);
246 char res[3];
247 fgets (res, 3, stdin);
248 if (toupper(res[0]) == 'Y')
249 return true;
250 else
251 return false;
252 }
253
254 /* main loop for the puzzle editor */
255 void puzzle_editor_loop (Puzzle *p, const char *filename)
256 {
257 bool loop = true;
258 while (loop)
259 {
260 print_menu (WHITE, BLUE, PUZZLE_MENU_TITLE, PUZZLE_EDIT_MENU, 14, 50);
261 printf (INPUT_CHOICE);
262 int ch = get_num ();
263 switch (ch)
264 {
265 case 1: print_puzzle (p);
266 char ch = getchar ();
267 break;
268 case 2: do_add_across_word (p);
269 break;
270 case 3: do_add_down_word (p);
271 break;
272 case 4: do_clear_cell (p);
273 break;
274 case 5: freeze_puzzle (p);
275 print_puzzle (p);
276 ch = getchar ();
277 break;
278 case 6: unfreeze_puzzle (p);
279 print_puzzle (p);
280 ch = getchar ();
281 break;
282 case 7: do_set_clue_word (p, ACROSS);
283 break;
284 case 8: do_set_clue_word (p, DOWN);
285 break;
286 case 9: save_puzzle (p, filename);
287 printf ("%s\n",FILE_SAVED);
288 ch = getchar ();
289 break;
290 case 10: do_set_password (p);
291 break;
292 case 11: do_reset_puzzle (p);
293 break;
294 case 12: do_export_puzzle (p);
295 break;
296 case 13: do_export_clues (p);
297 break;
298 case 14: loop = ! do_confirm_exit ();
299 break;
300 }
301 }
302 }
303
304 /* open an existing puzzle */
305 void do_open_puzzle (const char *filename)
306 {
307 Puzzle p;
308 /* if no filename is provided, get it from command line */
309 if (filename == NULL)
310 {
311 printf (INPUT_FILE);
312 char fname[256];
313 fgets(fname, 256, stdin);
314 if (strlen (fname) == 1)
315 return;
316 filename = strtok (fname, "\n");
317 }
318
319 p = load_puzzle (filename);
320
321 if (strcmp (p.hashed_password, "\0") != 0)
322 {
323 char passwd[256];
324 printf (INPUT_PASSWORD);
325 fgets (passwd, 256, stdin);
326 if (strlen (passwd) == 1)
327 return;
328 char *pwd = strtok (passwd, "\n");
329
330 if (verify_password (&p, (const char*) pwd))
331 puzzle_editor_loop (&p, filename);
332 else
333 {
334 printf (WRONG_PASSWORD);
335 char ch = getchar ();
336 }
337 }
338 else
339 puzzle_editor_loop (&p, filename);
340 }
341
342 /* create a new blank puzzle */
343 void do_new_puzzle (char *filename, int size)
344 {
345 Puzzle p;
346 /* if filename is not provided get it from command line */
347 if (filename == NULL)
348 {
349 printf (INPUT_FILE);
350 char fname[256];
351 fgets (fname, 256, stdin);
352 if (strlen (fname) == 1)
353 return;
354 filename = strtok (fname, "\n");
355 }
356 /* if no size is specified get it from command line */
357 if (size == -1)
358 {
359 printf (INPUT_GRID_SIZE);
360 size = get_num ();
361 }
362
363 if (size > MAX_PUZZLE_SIZE)
364 {
365 printf (EXCEED_MAX_GRID_SIZE);
366 char c = getchar ();
367 }
368 else
369 {
370 init_puzzle (&p, size);
371 puzzle_editor_loop (&p, filename);
372 }
373 }
374
375 /* The main loop of the program */
376 int main_loop ()
377 {
378 /* Print the main menu */
379 while (1)
380 {
381 print_menu (WHITE, BLUE, MAIN_MENU_TITLE, MAIN_MENU, 3, 50);
382 printf (INPUT_CHOICE);
383 int ch = get_num ();
384 switch (ch)
385 {
386 case 1: do_new_puzzle (NULL, -1);
387 break;
388 case 2: do_open_puzzle (NULL);
389 break;
390 case 3: exit (0);
391 }
392 }
393 }
394
395 int main (int argc, char* argv[])
396 {
397 if (argc >= 2)
398 {
399 Puzzle p;
400 switch (argc)
401 {
402 case 2 : do_open_puzzle (argv[1]);
403 break;
404 case 4 : if (strcmp (argv[2], "new") == 0)
405 {
406 int grid_size = atoi (argv[3]);
407 do_new_puzzle (argv[1], grid_size);
408 break;
409 }
410 default: fprintf (stderr, USAGE_LINE_1, argv[0]);
411 fprintf (stderr, USAGE_LINE_2);
412 fprintf (stderr, USAGE_LINE_3);
413 exit (3);
414 }
415 }
416 return (main_loop ());
417 }