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