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