Functionality for keyboard and mouse in puzzle area
authorHarishankar <v.harishankar@gmail.com>
Mon, 4 May 2020 13:40:36 +0000 (19:10 +0530)
committerHarishankar <v.harishankar@gmail.com>
Mon, 4 May 2020 13:40:36 +0000 (19:10 +0530)
Added the functionality in the player for handling keyboard and
mouse input

Makefile
wordblox.h
wordblox_player.c
wordblox_player.glade

index 81d882d..4936f00 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -1,3 +1,5 @@
+all:  wordblox wordblox_player
+
 wordblox: wordblox.c wordblox.h constantstrings.h
        clang wordblox.c -lgd -lz -lcrypt -o wordblox
 
 wordblox: wordblox.c wordblox.h constantstrings.h
        clang wordblox.c -lgd -lz -lcrypt -o wordblox
 
index 8886fab..2978e0d 100644 (file)
@@ -58,6 +58,17 @@ typedef struct {
        char salt[256];
 } Puzzle;
 
        char salt[256];
 } Puzzle;
 
+/* The player data struct type - for the player app */
+typedef struct {
+       Puzzle puzzle;
+       char filename[65535];
+       bool is_loaded;
+       char char_ans[MAX_PUZZLE_SIZE][MAX_PUZZLE_SIZE];
+       int cur_row;
+       int cur_col;
+} MainPlayerData;
+
+
 /* get a number from the user */
 int get_num ()
 {
 /* get a number from the user */
 int get_num ()
 {
@@ -267,7 +278,7 @@ void unfreeze_puzzle (Puzzle *p)
 /* freeze the grid - make editing impossible because it finalizes the
    across and down words in the grid */
 void freeze_puzzle (Puzzle *p)
 /* freeze the grid - make editing impossible because it finalizes the
    across and down words in the grid */
 void freeze_puzzle (Puzzle *p)
-{
+{              
        int word_num = 1;
        bool across_word_start, down_word_start;
        for (int i = 0; i < p->grid_size; i ++)
        int word_num = 1;
        bool across_word_start, down_word_start;
        for (int i = 0; i < p->grid_size; i ++)
@@ -277,7 +288,7 @@ void freeze_puzzle (Puzzle *p)
                        across_word_start = false; 
                        down_word_start = false;
                        /* if it is a blank cell - cover it with a block */
                        across_word_start = false; 
                        down_word_start = false;
                        /* if it is a blank cell - cover it with a block */
-                       if (p->chars[i][j] == ' ')
+                       if (p->chars[i][j] == ' ' || p->chars[i][j] == '#')
                                p->chars[i][j] = '#';
                        /* it is not a blank cell - check all possibilities */
                        else 
                                p->chars[i][j] = '#';
                        /* it is not a blank cell - check all possibilities */
                        else 
@@ -692,6 +703,7 @@ void print_menu (enum COLOR fg, enum COLOR bg, const char* title,
                        printf ("\u2550");
                printf ("\u2557"); 
                reset_color (); printf ("\n");
                        printf ("\u2550");
                printf ("\u2557"); 
                reset_color (); printf ("\n");
+               set_color (fg, bg, NORMAL);
                printf ("\u2551");
                set_color (fg, bg, BOLD);
                printf ("%-*s", padding, title);
                printf ("\u2551");
                set_color (fg, bg, BOLD);
                printf ("%-*s", padding, title);
@@ -719,4 +731,86 @@ void print_menu (enum COLOR fg, enum COLOR bg, const char* title,
                reset_color (); printf ("\n");
 }
 
                reset_color (); printf ("\n");
 }
 
+/* reset the player data, from the new file */
+void reset_player_data (MainPlayerData *app_data, const char *filename)
+{
+       app_data->puzzle = load_puzzle (filename);
+
+       app_data->is_loaded = app_data->puzzle.grid_frozen;
+       app_data->cur_col = -1;
+       app_data->cur_row = -1;
+       strcpy (app_data->filename, filename);
+       /* reset the answer keys */
+       for (int i = 0; i < app_data->puzzle.grid_size; i ++)
+               for (int j = 0; j < app_data->puzzle.grid_size; j ++)
+                       app_data->char_ans[i][j] = ' ';
+       
+}
+
+/* in the player app, move the current selection index left or right */
+void move_current_col (MainPlayerData *app_data, enum DIRECTION dir)
+{
+       int r = app_data->cur_row;
+       int c = app_data->cur_col;
+       if (dir == DIR_FORWARD)
+       {
+               c ++;
+               while (c < app_data->puzzle.grid_size)
+               {
+                       if (app_data->puzzle.chars[r][c] == '#')
+                               c ++;
+                       else
+                               break;
+               }
+               if (c < app_data->puzzle.grid_size)
+                       app_data->cur_col = c;
+       }
+       else 
+       {
+               c --;
+               while (c >= 0)
+               {
+                       if (app_data->puzzle.chars[r][c] == '#')
+                               c --;
+                       else
+                               break;
+               }
+               if (c >= 0)
+                       app_data->cur_col = c;
+       }
+}
+
+/* in the player app move the current selection index up or down */
+void move_current_row (MainPlayerData *app_data, enum DIRECTION dir)
+{
+       int r = app_data->cur_row;
+       int c = app_data->cur_col;
+       if (dir == DIR_FORWARD)
+       {
+               r ++;
+               while (r < app_data->puzzle.grid_size)
+               {
+                       if (app_data->puzzle.chars[r][c] == '#')
+                               r ++;
+                       else
+                               break;
+               }
+               if (r < app_data->puzzle.grid_size)
+                       app_data->cur_row = r;
+       }
+       else 
+       {
+               r --;
+               while (r >= 0)
+               {
+                       if (app_data->puzzle.chars[r][c] == '#')
+                               r --;
+                       else
+                               break;
+               }
+               if (r >= 0)
+                       app_data->cur_row = r;
+       }
+}
+
 #endif
 #endif
index a3105d6..46a41fd 100644 (file)
@@ -8,15 +8,9 @@ GtkWidget *window;
 GtkListStore *across_store;
 GtkListStore *down_store;
 
 GtkListStore *across_store;
 GtkListStore *down_store;
 
-struct MainAppData {
-       Puzzle puzzle;
-       char filename[65535];
-       bool is_loaded;
-       int cur_row;
-       int cur_col;
-} app_data;
+MainPlayerData app_data;
 
 
-/* update the clue items */
+/* update the clue items store */
 void update_clue_items ()
 {
        gtk_list_store_clear (across_store);
 void update_clue_items ()
 {
        gtk_list_store_clear (across_store);
@@ -56,73 +50,35 @@ void update_clue_items ()
        } 
 }
 
        } 
 }
 
-/* move the current selection index left or right */
-void move_current_col (enum DIRECTION dir)
+/* slot for handling mouse button event for puzzle drawing area */
+gboolean on_puzzle_area_button_press_event (GtkWidget *widget, 
+                                                                       GdkEventButton *event, gpointer data)
 {
 {
-       int r = app_data.cur_row;
-       int c = app_data.cur_col;
-       if (dir == DIR_FORWARD)
+       if (event->type == GDK_BUTTON_PRESS && event->button == 1)
        {
        {
-               c ++;
-               while (c < app_data.puzzle.grid_size)
-               {
-                       if (app_data.puzzle.chars[r][c] == '#')
-                               c ++;
-                       else
-                               break;
-               }
-               if (c < app_data.puzzle.grid_size)
-                       app_data.cur_col = c;
-       }
-       else 
-       {
-               c --;
-               while (c >= 0)
+               int col = (event->x - 5) / GRID_PIXELS;
+               int row = (event->y - 5) / GRID_PIXELS;
+       
+               if (app_data.puzzle.chars[row][col] != '#')
                {
                {
-                       if (app_data.puzzle.chars[r][c] == '#')
-                               c --;
-                       else
-                               break;
+                       if (row < app_data.puzzle.grid_size && 
+                               col < app_data.puzzle.grid_size)
+                       {
+                               app_data.cur_row = row;
+                               app_data.cur_col = col;
+                       }
                }
                }
-               if (c >= 0)
-                       app_data.cur_col = c;
        }
        }
-}
+       
+       gtk_widget_queue_draw_area (widget, 0, 0,  
+               app_data.puzzle.grid_size*GRID_PIXELS+10, 
+               app_data.puzzle.grid_size*GRID_PIXELS+10);
+       
 
 
-/* move the current selection index up or down */
-void move_current_row (enum DIRECTION dir)
-{
-       int r = app_data.cur_row;
-       int c = app_data.cur_col;
-       if (dir == DIR_FORWARD)
-       {
-               r ++;
-               while (r < app_data.puzzle.grid_size)
-               {
-                       if (app_data.puzzle.chars[r][c] == '#')
-                               r ++;
-                       else
-                               break;
-               }
-               if (r < app_data.puzzle.grid_size)
-                       app_data.cur_row = r;
-       }
-       else 
-       {
-               r --;
-               while (r >= 0)
-               {
-                       if (app_data.puzzle.chars[r][c] == '#')
-                               r --;
-                       else
-                               break;
-               }
-               if (r >= 0)
-                       app_data.cur_row = r;
-       }
+               
+       return FALSE;   
 }
 
 }
 
-
 /* slot for handling key press event for puzzle drawing area */
 gboolean on_puzzle_area_key_press_event (GtkWidget *widget, 
                                                                        GdkEventKey *event, gpointer data)
 /* slot for handling key press event for puzzle drawing area */
 gboolean on_puzzle_area_key_press_event (GtkWidget *widget, 
                                                                        GdkEventKey *event, gpointer data)
@@ -132,32 +88,131 @@ gboolean on_puzzle_area_key_press_event (GtkWidget *widget,
        {
                switch (event->keyval)
                {
        {
                switch (event->keyval)
                {
-                       case GDK_KEY_Down : move_current_row (DIR_FORWARD);
-                                                               gtk_widget_queue_draw_area (widget, 
-                                                                       0, 0, 
-                                                                       app_data.puzzle.grid_size*GRID_PIXELS+10,
-                                                                       app_data.puzzle.grid_size*GRID_PIXELS+10);
+                       case GDK_KEY_Down : move_current_row (&app_data, DIR_FORWARD);
+                                                               break;
+                       case GDK_KEY_Up   : move_current_row (&app_data, DIR_BACK);
+                                                               break;
+                       case GDK_KEY_Right: move_current_col (&app_data, DIR_FORWARD);
+                                                               break;
+                       case GDK_KEY_Left : move_current_col (&app_data, DIR_BACK);
+                                                               break;
+                       case GDK_KEY_Delete:
+                       case GDK_KEY_space: 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = ' ';
+                                                               break;                  
+                       case GDK_KEY_a    :
+                       case GDK_KEY_A    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'A';
+                                                               break;
+                       case GDK_KEY_b    :
+                       case GDK_KEY_B    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'B';
                                                                break;
                                                                break;
-                       case GDK_KEY_Up   : move_current_row (DIR_BACK);
-                                                               gtk_widget_queue_draw_area (widget, 
-                                                                       0, 0, 
-                                                                       app_data.puzzle.grid_size*GRID_PIXELS+10,
-                                                                       app_data.puzzle.grid_size*GRID_PIXELS+10);
+                       case GDK_KEY_c    :
+                       case GDK_KEY_C    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'C';
                                                                break;
                                                                break;
-                       case GDK_KEY_Right: move_current_col (DIR_FORWARD);
-                                                               gtk_widget_queue_draw_area (widget, 
-                                                                       0, 0, 
-                                                                       app_data.puzzle.grid_size*GRID_PIXELS+10,
-                                                                       app_data.puzzle.grid_size*GRID_PIXELS+10);
+                       case GDK_KEY_d    :
+                       case GDK_KEY_D    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'D';
                                                                break;
                                                                break;
-                       case GDK_KEY_Left : move_current_col (DIR_BACK);
-                                                               gtk_widget_queue_draw_area (widget, 
-                                                                       0, 0, 
-                                                                       app_data.puzzle.grid_size*GRID_PIXELS+10,
-                                                                       app_data.puzzle.grid_size*GRID_PIXELS+10);                      
+                       case GDK_KEY_e    :
+                       case GDK_KEY_E    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'E';
+                                                               break;
+                       case GDK_KEY_f    :
+                       case GDK_KEY_F    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'F';            
+                                                               break;
+                       case GDK_KEY_g    :
+                       case GDK_KEY_G    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'G';
+                                                               break;
+                       case GDK_KEY_h    :
+                       case GDK_KEY_H    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'H';
+                                                               break;
+                       case GDK_KEY_i    :
+                       case GDK_KEY_I    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'I';
+                                                               break;
+                       case GDK_KEY_j    :
+                       case GDK_KEY_J    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'J';
+                                                               break;
+                       case GDK_KEY_k    :
+                       case GDK_KEY_K    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'K';
+                                                               break;
+                       case GDK_KEY_l    :
+                       case GDK_KEY_L    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'L';
+                                                               break;
+                       case GDK_KEY_m    :
+                       case GDK_KEY_M    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'M';
+                                                               break;
+                       case GDK_KEY_n    :
+                       case GDK_KEY_N    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'N';
+                                                               break;
+                       case GDK_KEY_o    :
+                       case GDK_KEY_O    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'O';
+                                                               break;
+                       case GDK_KEY_p    :
+                       case GDK_KEY_P    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'P';
+                                                               break;
+                       case GDK_KEY_q    :
+                       case GDK_KEY_Q    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'Q';
+                                                               break;
+                       case GDK_KEY_r    :
+                       case GDK_KEY_R    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'R';
+                                                               break;
+                       case GDK_KEY_s    :
+                       case GDK_KEY_S    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'S';
+                                                               break;
+                       case GDK_KEY_t    :
+                       case GDK_KEY_T    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'T';
+                                                               break;
+                       case GDK_KEY_u    :
+                       case GDK_KEY_U    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'U';
+                                                               break;
+                       case GDK_KEY_v    :
+                       case GDK_KEY_V    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'V';
+                                                               break;
+                       case GDK_KEY_w    :
+                       case GDK_KEY_W    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'W';
+                                                               break;
+                       case GDK_KEY_x    :
+                       case GDK_KEY_X    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'X';
+                                                               break;
+                       case GDK_KEY_y    :
+                       case GDK_KEY_Y    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'Y';
+                                                               break;
+                       case GDK_KEY_z    :
+                       case GDK_KEY_Z    : 
+                                       app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'Z';
+                                                               break;
+                       default                   : return FALSE;
+                                                                               
                }
        }
        
                }
        }
        
+       gtk_widget_queue_draw_area (widget, 0, 0,  
+               app_data.puzzle.grid_size*GRID_PIXELS+10, 
+               app_data.puzzle.grid_size*GRID_PIXELS+10);      
+       
        return FALSE;
 }
 
        return FALSE;
 }
 
@@ -241,6 +296,18 @@ gboolean on_puzzle_area_draw (GtkWidget *widget, cairo_t *cr, gpointer data)
                                        cairo_show_text (cr, (const char*)cnum);
                                }
                                
                                        cairo_show_text (cr, (const char*)cnum);
                                }
                                
+                               /* draw the answer if it is there */
+                               gdk_cairo_set_source_rgba (cr, &colorfore);     
+                               cairo_select_font_face (cr, "sans serif", 
+                                                                               CAIRO_FONT_SLANT_NORMAL,
+                                                                               CAIRO_FONT_WEIGHT_BOLD);
+                               
+                               cairo_set_font_size (cr, 16);
+                               cairo_move_to (cr, j*GRID_PIXELS+GRID_PIXELS/2, 
+                                                               i*GRID_PIXELS+GRID_PIXELS-10);
+                               char ctxt[3];
+                               sprintf (ctxt, "%c", app_data.char_ans[i][j]);
+                               cairo_show_text (cr, (const char*) ctxt);
 
                        }
                }
 
                        }
                }
@@ -285,11 +352,11 @@ void on_menu_open_activate (GtkMenuItem *item, GtkDrawingArea* area)
        {
                char *filename;
                filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(dialog));
        {
                char *filename;
                filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(dialog));
-               app_data.puzzle = load_puzzle (filename);
-               app_data.is_loaded = true;
-               strcpy (app_data.filename, filename);           
+               MainPlayerData temp;
+               reset_player_data (&temp, filename);
+
                /* if the grid is not frozen then the game cannot be played */
                /* if the grid is not frozen then the game cannot be played */
-               if (app_data.puzzle.grid_frozen == false)
+               if (temp.is_loaded == false)
                {
                        GtkWidget *errordlg ;
                        errordlg = gtk_message_dialog_new (GTK_WINDOW(window), 
                {
                        GtkWidget *errordlg ;
                        errordlg = gtk_message_dialog_new (GTK_WINDOW(window), 
@@ -299,17 +366,16 @@ void on_menu_open_activate (GtkMenuItem *item, GtkDrawingArea* area)
                                                                                                UNFROZEN_GRID_PLAYER);
                        gtk_dialog_run (GTK_DIALOG(errordlg));
                        gtk_widget_destroy (errordlg);
                                                                                                UNFROZEN_GRID_PLAYER);
                        gtk_dialog_run (GTK_DIALOG(errordlg));
                        gtk_widget_destroy (errordlg);
-                       app_data.is_loaded = false;
-                       app_data.cur_col = -1;
-                       app_data.cur_row = -1;
                }
                else
                {
                }
                else
                {
+                       app_data = temp;
                        gtk_widget_queue_draw_area (GTK_WIDGET (area), 0, 0, 
                                                                                app_data.puzzle.grid_size*30+10, 
                                                                                app_data.puzzle.grid_size*30+10);
                        gtk_widget_queue_draw_area (GTK_WIDGET (area), 0, 0, 
                                                                                app_data.puzzle.grid_size*30+10, 
                                                                                app_data.puzzle.grid_size*30+10);
-                       update_clue_items ();
+
                }
                }
+               update_clue_items ();           
                g_free (filename);
        }
        
                g_free (filename);
        }
        
@@ -363,7 +429,15 @@ int main (int argc, char *argv [])
                                                                                        
                if (window != NULL)
                {
                                                                                        
                if (window != NULL)
                {
-                       gtk_window_set_default_icon (icon);             
+                       gtk_window_set_default_icon (icon);
+                       
+                       GtkWidget *draw_area = GTK_WIDGET (
+                                                       gtk_builder_get_object(builder, "puzzle_area"));
+                       
+                       /* make drawing area respond to mouse event */
+                       gtk_widget_set_events(draw_area,
+                                       gtk_widget_get_events(draw_area) 
+                                               | GDK_BUTTON_PRESS_MASK);
                
                        gtk_builder_connect_signals (builder, NULL);
                        g_object_unref (builder);
                
                        gtk_builder_connect_signals (builder, NULL);
                        g_object_unref (builder);
index bc9f27a..7c1bc92 100644 (file)
                         <property name="has_focus">True</property>
                         <property name="can_default">True</property>
                         <property name="has_default">True</property>
                         <property name="has_focus">True</property>
                         <property name="can_default">True</property>
                         <property name="has_default">True</property>
+                        <signal name="button-press-event" handler="on_puzzle_area_button_press_event" swapped="no"/>
                         <signal name="draw" handler="on_puzzle_area_draw" swapped="no"/>
                         <signal name="key-press-event" handler="on_puzzle_area_key_press_event" swapped="no"/>
                       </object>
                         <signal name="draw" handler="on_puzzle_area_draw" swapped="no"/>
                         <signal name="key-press-event" handler="on_puzzle_area_key_press_event" swapped="no"/>
                       </object>