From 70d116c047f04b31939c11a3856be04e1edcd783 Mon Sep 17 00:00:00 2001 From: Harishankar Date: Mon, 4 May 2020 19:10:36 +0530 Subject: [PATCH] Functionality for keyboard and mouse in puzzle area Added the functionality in the player for handling keyboard and mouse input --- Makefile | 2 + wordblox.h | 98 +++++++++++++++- wordblox_player.c | 266 +++++++++++++++++++++++++++--------------- wordblox_player.glade | 1 + 4 files changed, 269 insertions(+), 98 deletions(-) diff --git a/Makefile b/Makefile index 81d882d..4936f00 100644 --- 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 diff --git a/wordblox.h b/wordblox.h index 8886fab..2978e0d 100644 --- a/wordblox.h +++ b/wordblox.h @@ -58,6 +58,17 @@ typedef struct { 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 () { @@ -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) -{ +{ 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 */ - 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 @@ -692,6 +703,7 @@ void print_menu (enum COLOR fg, enum COLOR bg, const char* title, printf ("\u2550"); printf ("\u2557"); reset_color (); printf ("\n"); + set_color (fg, bg, NORMAL); 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 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 diff --git a/wordblox_player.c b/wordblox_player.c index a3105d6..46a41fd 100644 --- a/wordblox_player.c +++ b/wordblox_player.c @@ -8,15 +8,9 @@ GtkWidget *window; 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); @@ -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) @@ -132,32 +88,131 @@ gboolean on_puzzle_area_key_press_event (GtkWidget *widget, { 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; - 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; - 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; - 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; } @@ -241,6 +296,18 @@ gboolean on_puzzle_area_draw (GtkWidget *widget, cairo_t *cr, gpointer data) 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)); - 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 (app_data.puzzle.grid_frozen == false) + if (temp.is_loaded == false) { 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); - app_data.is_loaded = false; - app_data.cur_col = -1; - app_data.cur_row = -1; } 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); - update_clue_items (); + } + update_clue_items (); g_free (filename); } @@ -363,7 +429,15 @@ int main (int argc, char *argv []) 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); diff --git a/wordblox_player.glade b/wordblox_player.glade index bc9f27a..7c1bc92 100644 --- a/wordblox_player.glade +++ b/wordblox_player.glade @@ -160,6 +160,7 @@ True True True + -- 2.20.1