+#ifndef __WORDBLOX_H
+#define __WORDBLOX_H
+
+#include "constantstrings.h"
+
+#define MAX_PUZZLE_SIZE 20
+#define MAX_CLUE_LENGTH 150
+
+/* Enum to define terminal colours */
+enum COLOR {
+ BLACK = 0,
+ RED= 1,
+ GREEN=2,
+ YELLOW=3,
+ BLUE=4,
+ MAGENTA=5,
+ CYAN=6,
+ WHITE=7
+};
+
+typedef char String[MAX_CLUE_LENGTH];
+
+/* The main puzzle struct type */
+typedef struct {
+ char chars[MAX_PUZZLE_SIZE][MAX_PUZZLE_SIZE];
+ int start_across_word[MAX_PUZZLE_SIZE][MAX_PUZZLE_SIZE];
+ int start_down_word[MAX_PUZZLE_SIZE][MAX_PUZZLE_SIZE];
+ String clue_across[MAX_PUZZLE_SIZE][MAX_PUZZLE_SIZE];
+ String clue_down[MAX_PUZZLE_SIZE][MAX_PUZZLE_SIZE];
+ int grid_size;
+ bool grid_frozen;
+} Puzzle;
+
+/* Set the terminal colour */
+void set_color (enum COLOR fg, enum COLOR bg) {
+ printf ("\x1B[%d;%dm", fg+30, bg+40);
+}
+
+/* Reset the terminal colour */
+void reset_color () {
+ printf ("\x1B[0m");
+}
+
+/* reset the entire grid */
+void init_puzzle (Puzzle *p, int grid_size)
+{
+ p->grid_size = grid_size;
+ p->grid_frozen = false;
+ for (int i = 0; i < p->grid_size; i ++)
+ {
+ for (int j = 0; j < p->grid_size; j ++)
+ {
+ p->chars[i][j] = ' ';
+ p->start_across_word[i][j] = -1;
+ p->start_down_word[i][j] = -1;
+ strcpy (p->clue_across[i][j], "");
+ strcpy (p->clue_down[i][j], "");
+ }
+ }
+}
+
+/* save the puzzle */
+void save_puzzle (Puzzle *puzzle, const char* file) {
+ FILE *outfile;
+ outfile = fopen (file, "wb");
+ if (outfile == NULL)
+ {
+ fprintf (stderr, "%s\n", ERROR_WRITING_FILE);
+ exit (1);
+ }
+ fwrite (puzzle, sizeof (*puzzle), 1, outfile);
+ fclose (outfile);
+}
+
+/* read the puzzle */
+Puzzle load_puzzle (const char* file) {
+ FILE *infile;
+ Puzzle p;
+ infile = fopen (file, "rb");
+ if (infile == NULL)
+ {
+ fprintf (stderr, "%s\n", ERROR_READING_FILE);
+ exit (1);
+ }
+ fread (&p, sizeof(p), 1, infile);
+ fclose (infile);
+ return p;
+}
+
+/* display the puzzle */
+void print_puzzle (Puzzle *p)
+{
+ set_color (WHITE, CYAN);
+ printf (" ");
+ for (int i = 0; i < p->grid_size; i ++)
+ printf ("%3d", i);
+ reset_color ();
+ printf("\n");
+ for (int i = 0; i < p->grid_size; i ++)
+ {
+ set_color (WHITE, CYAN);
+ printf ("%3d ", i);
+ for (int j = 0; j < p->grid_size; j ++)
+ {
+ if (p->chars[i][j] == '#') {
+ set_color (WHITE, BLACK);
+ printf (" ");
+ }
+ else
+ {
+ if (p->start_across_word[i][j] != -1)
+ {
+ set_color (BLUE, WHITE);
+ printf ("%2d", p->start_across_word[i][j]);
+ }
+ else
+ {
+ set_color (BLACK, WHITE);
+ printf (" ");
+ }
+
+ set_color (BLACK, WHITE);
+ printf ("%c", p->chars[i][j]);
+ }
+ reset_color ();
+ }
+ printf ("\n");
+ }
+}
+
+/* function to check if a word is valid or not */
+bool is_valid_word (const char *word)
+{
+ for (int i = 0; i < strlen (word); i ++)
+ if (! isalpha (word[i]))
+ return false;
+
+ return true;
+}
+
+/* function to print a menu */
+void print_menu (enum COLOR fg, enum COLOR bg, const char* title,
+ char **items, int num_items, int padding)
+{
+ /* clear screen */
+ printf ("\e[1;1H\e[2J");
+ set_color (fg, bg);
+ printf ("\u2554");
+ for (int i = 0; i < padding; i ++)
+ printf ("\u2550");
+ printf ("\u2557");
+ reset_color (); printf ("\n");
+ set_color (fg, bg);
+ printf ("\u2551%-*s\u2551", padding, title);
+ reset_color (); printf ("\n");
+ set_color (fg, bg);
+ printf ("\u2560");
+ for (int i = 0; i < padding; i ++)
+ printf ("\u2550");
+ printf ("\u2563");
+ reset_color (); printf ("\n");
+ for (int i = 0; i < num_items; i ++)
+ {
+ set_color (fg, bg);
+ printf ("\u2551%-*s\u2551", padding, items[i]);
+ reset_color (); printf ("\n");
+ }
+ set_color (fg, bg);
+ printf ("\u255A");
+ for (int i = 0; i < padding; i ++)
+ printf ("\u2550");
+ printf ("\u255D");
+ reset_color (); printf ("\n");
+}
+
+#endif