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