X-Git-Url: https://harishankar.org/repos/?p=wordblah.git;a=blobdiff_plain;f=wordblah_player.c;fp=wordblah_player.c;h=26dab2991e2579e7226f9ba8e4aec7e9f925eed3;hp=0000000000000000000000000000000000000000;hb=2aac9fd96329b27dffec6534a042cfbe045f3a11;hpb=7defe51e8a1da9feec6319defa7c906fcb735726 diff --git a/wordblah_player.c b/wordblah_player.c new file mode 100644 index 0000000..26dab29 --- /dev/null +++ b/wordblah_player.c @@ -0,0 +1,724 @@ +#include + +#include "constantstrings.h" +#include "wordblah_resource.c" +#include "wordblah.h" + +GtkWidget *main_window; +GtkListStore *across_store; +GtkListStore *down_store; + +MainPlayerData app_data; + +/* update the clue items store */ +void update_clue_items () +{ + gtk_list_store_clear (across_store); + gtk_list_store_clear (down_store); + + /* if the puzzle is loaded */ + if (app_data.is_loaded == true) + { + /* iterate through the puzzle grid and gte the clues */ + for (int i = 0; i < app_data.puzzle.grid_size; i ++) + { + for (int j = 0; j < app_data.puzzle.grid_size; j ++) + { + /* if it is the start of an across word */ + if (app_data.puzzle.start_across_word[i][j] != -1) + { + GtkTreeIter iter; + + gtk_list_store_append (across_store, &iter); + gtk_list_store_set (across_store, &iter, 0, + app_data.puzzle.start_across_word[i][j], + 1, app_data.puzzle.clue_across[i][j], + -1); + } + /* if it is the start of a down word */ + if (app_data.puzzle.start_down_word[i][j] != -1) + { + GtkTreeIter iter; + gtk_list_store_append (down_store, &iter); + gtk_list_store_set (down_store, &iter, 0, + app_data.puzzle.start_down_word[i][j], + 1, app_data.puzzle.clue_down[i][j], + -1); + } + } + } + } +} + +/* slot for handling list down selection changed */ +gboolean on_down_list_selection_changed (GtkTreeSelection *sel, + GtkDrawingArea *area) +{ + GtkTreeIter iter; + GtkTreeModel* mod; + + if (gtk_tree_selection_get_selected (sel, &mod, &iter)) + { + guint sel_word_index; + gtk_tree_model_get (mod, &iter, 0, &sel_word_index, -1); + set_selection_to_word_start (&app_data, DOWN, sel_word_index); + } + + gtk_widget_queue_draw_area (GTK_WIDGET(area), 0, 0, + app_data.puzzle.grid_size*GRID_PIXELS+10, + app_data.puzzle.grid_size*GRID_PIXELS+10); + + return FALSE; + +} +/* slot for handling list across selection changed */ +gboolean on_across_list_selection_changed (GtkTreeSelection *sel, + GtkDrawingArea *area) +{ + GtkTreeIter iter; + GtkTreeModel* mod; + + if (gtk_tree_selection_get_selected (sel, &mod, &iter)) + { + guint sel_word_index; + gtk_tree_model_get (mod, &iter, 0, &sel_word_index, -1); + set_selection_to_word_start (&app_data, ACROSS, sel_word_index); + } + + gtk_widget_queue_draw_area (GTK_WIDGET(area), 0, 0, + app_data.puzzle.grid_size*GRID_PIXELS+10, + app_data.puzzle.grid_size*GRID_PIXELS+10); + + return FALSE; + +} + +/* slot for handling mouse button event for puzzle drawing area */ +gboolean on_puzzle_area_button_press_event (GtkWidget *widget, + GdkEventButton *event, gpointer data) +{ + /* if it is solution mode, then don't do anything but reset it to + non solution mode */ + if (app_data.solution_revealed == true) + { + app_data.solution_revealed = 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; + } + + /* Depending on the type of button handle the movement */ + if (event->type == GDK_BUTTON_PRESS && event->button == 1) + { + int col = (event->x - 5) / GRID_PIXELS; + int row = (event->y - 5) / GRID_PIXELS; + + if (app_data.puzzle.chars[row][col] != '#') + { + if (row < app_data.puzzle.grid_size && + col < app_data.puzzle.grid_size) + { + app_data.cur_row = row; + app_data.cur_col = col; + + /* if it is a start of both across and down word, then + toggle the movement on clicking it */ + if (app_data.puzzle.start_across_word[row][col] != -1 && + app_data.puzzle.start_down_word[row][col] != -1) + { + if (app_data.current_movement == ACROSS) + app_data.current_movement = DOWN; + else + app_data.current_movement = ACROSS; + } + /* if it is only start of across word, make the current + movement across */ + else if (app_data.puzzle.start_across_word[row][col] != -1) + app_data.current_movement = ACROSS; + /* else down movement */ + else if (app_data.puzzle.start_down_word[row][col] != -1) + app_data.current_movement = DOWN; + } + } + } + + 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; +} + +/* slot for handling key press event for puzzle drawing area */ +gboolean on_puzzle_area_key_press_event (GtkWidget *widget, + GdkEventKey *event, gpointer data) +{ + /* respond to key events only if the puzzle is loaded */ + if (app_data.is_loaded == true) + { + /* if the solution is revealed, don't respond to key events except + to return to the non-solution mode */ + if (app_data.solution_revealed == true) + { + app_data.solution_revealed = 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; + } + + switch (event->keyval) + { + case GDK_KEY_Down : move_current_row (&app_data, DIR_FORWARD); + app_data.current_movement = DOWN; + break; + case GDK_KEY_Up : move_current_row (&app_data, DIR_BACK); + app_data.current_movement = DOWN; + break; + case GDK_KEY_Right: move_current_col (&app_data, DIR_FORWARD); + app_data.current_movement = ACROSS; + break; + case GDK_KEY_Left : move_current_col (&app_data, DIR_BACK); + app_data.current_movement = ACROSS; + break; + case GDK_KEY_BackSpace: + 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_c : + case GDK_KEY_C : + app_data.char_ans[app_data.cur_row][app_data.cur_col] = 'C'; + break; + 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_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; + + } + } + + /* move the selection pointer to next row/col as per the current + movement orientation if it is not a key left right up or down */ + if (event->keyval != GDK_KEY_Down && event->keyval != GDK_KEY_Up && + event->keyval != GDK_KEY_Left && event->keyval != GDK_KEY_Right + && event->keyval != GDK_KEY_Delete) + { + /* if the current movement is an across movement */ + if (app_data.current_movement == ACROSS) + { + /* if the next column is not blocking move the col */ + if (event->keyval != GDK_KEY_BackSpace && + next_col_block (&app_data.puzzle, app_data.cur_row, + app_data.cur_col) == false) + move_current_col (&app_data, DIR_FORWARD); + else if (event->keyval == GDK_KEY_BackSpace && + prev_col_block (&app_data.puzzle, app_data.cur_row, + app_data.cur_col) == false) + move_current_col (&app_data, DIR_BACK); + } + /* current movement is a up/down movement */ + else + { + if (event->keyval != GDK_KEY_BackSpace && + next_row_block (&app_data.puzzle, + app_data.cur_row, app_data.cur_col) == false) + move_current_row (&app_data, DIR_FORWARD); + else if (event->keyval == GDK_KEY_BackSpace && + prev_row_block (&app_data.puzzle, + app_data.cur_row, app_data.cur_col) == false) + move_current_row (&app_data, 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); + + return FALSE; +} + +/* slot for drawing the puzzle */ +gboolean on_puzzle_area_draw (GtkWidget *widget, cairo_t *cr, gpointer data) +{ + /* if a puzzle is loaded */ + if (app_data.is_loaded == true) + { + GdkRGBA colorfore, colorback, colorblue, colorbacksel1, + colorbacksel2, colorsolution; + gdk_rgba_parse (&colorfore, "#000000"); + gdk_rgba_parse (&colorback, "#ffffff"); + gdk_rgba_parse (&colorblue, "#0000dd"); + gdk_rgba_parse (&colorbacksel1, "#ffffaa"); + gdk_rgba_parse (&colorbacksel2, "#aaffff"); + gdk_rgba_parse (&colorsolution, "#990099"); + cairo_set_line_width (cr, 3); + + /* set the size of the drawing area */ + gtk_widget_set_size_request (widget, + app_data.puzzle.grid_size*GRID_PIXELS+10, + app_data.puzzle.grid_size*GRID_PIXELS+10); + + /* Draw the grid */ + for (int i = 0; i < app_data.puzzle.grid_size; i ++) + { + for (int j = 0; j < app_data.puzzle.grid_size; j ++) + { + /* if it is the current selection or if -1 is the current + selection then let the current selection be the first word */ + if (app_data.cur_col == -1 && app_data.cur_row == -1) + { + if (app_data.puzzle.start_across_word[i][j] == 1) + { + app_data.cur_row = i; + app_data.cur_col = j; + app_data.current_movement = ACROSS; + } + else if (app_data.puzzle.start_down_word[i][j] == 1) + { + app_data.cur_row = i; + app_data.cur_col = j; + app_data.current_movement = DOWN; + } + } + + gdk_cairo_set_source_rgba (cr, &colorfore); + cairo_rectangle (cr, j*GRID_PIXELS+5, i*GRID_PIXELS+5, + GRID_PIXELS, GRID_PIXELS); + + cairo_stroke (cr); + + /* if it is not a blank grid then set the background color + to black */ + if (app_data.puzzle.chars[i][j] != '#') + gdk_cairo_set_source_rgba (cr, &colorback); + + /* if it is a current selection and solution reveal mode is not + set then then set the background depending on whether across + or down movement mode is current */ + if (app_data.solution_revealed == false && + app_data.cur_row == i && app_data.cur_col == j) + { + if (app_data.current_movement == ACROSS) + gdk_cairo_set_source_rgba (cr, &colorbacksel1); + else + gdk_cairo_set_source_rgba (cr, &colorbacksel2); + } + + cairo_rectangle (cr, j*GRID_PIXELS+5, i*GRID_PIXELS+5, + GRID_PIXELS, GRID_PIXELS); + cairo_fill (cr); + + /* draw the word number if it is the start of a word */ + if (app_data.puzzle.start_across_word[i][j] != -1 || + app_data.puzzle.start_down_word[i][j] != -1) + { + int num; + if (app_data.puzzle.start_across_word[i][j] != -1) + num = app_data.puzzle.start_across_word[i][j]; + else + num = app_data.puzzle.start_down_word[i][j]; + + gdk_cairo_set_source_rgba (cr, &colorblue); + cairo_select_font_face (cr, "sans serif", + CAIRO_FONT_SLANT_NORMAL, + CAIRO_FONT_WEIGHT_NORMAL); + cairo_set_font_size (cr, 11); + cairo_move_to (cr, j*GRID_PIXELS+7, i*GRID_PIXELS+15); + char cnum[3]; + sprintf (cnum, "%d", num); + cairo_show_text (cr, (const char*)cnum); + } + + /* if solution is not revealed set the color to normal + or set it to solution color */ + if (app_data.solution_revealed == false) + gdk_cairo_set_source_rgba (cr, &colorfore); + else + gdk_cairo_set_source_rgba (cr, &colorsolution); + + 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]; + /* if it is solution mode reveal the answer or else the + user input */ + if (app_data.solution_revealed == false) + sprintf (ctxt, "%c", app_data.char_ans[i][j]); + else + if (app_data.puzzle.chars[i][j] != '#') + sprintf (ctxt, "%c", app_data.puzzle.chars[i][j]); + else + sprintf (ctxt, "%c", ' '); + cairo_show_text (cr, (const char*) ctxt); + + } + } + } + + return FALSE; + +} + +/* slot for reveal solution menu */ +void on_menu_reveal_solution_activate (GtkMenuItem *item, GtkDrawingArea *area) +{ + /* if puzzle solution is password protected ask for the password */ + if (strlen (app_data.puzzle.hashed_solution_password) > 0) + { + GtkBuilder *builder; + builder = gtk_builder_new (); + + guint ret = gtk_builder_add_from_resource + (builder, + "/org/harishankar/wordblah/wordblah_player.glade", + NULL); + if (ret == 0) + { + fprintf (stderr, ERROR_WINDOW); + g_object_unref (builder); + return; + } + + GtkWidget *password_dialog = GTK_WIDGET (gtk_builder_get_object + (builder, "password_dialog")); + GtkWidget *password_text = GTK_WIDGET (gtk_builder_get_object + (builder, "password_text")); + + if (password_dialog == NULL) + { + fprintf (stderr, ERROR_WINDOW); + g_object_unref (builder); + return; + } + gtk_window_set_transient_for (GTK_WINDOW(password_dialog), + GTK_WINDOW(main_window)); + gtk_dialog_set_default_response (GTK_DIALOG(password_dialog), + GTK_RESPONSE_ACCEPT); + gint res = gtk_dialog_run (GTK_DIALOG (password_dialog)); + if (res == GTK_RESPONSE_ACCEPT) + { + const gchar *user_pwd = gtk_entry_get_text + (GTK_ENTRY(password_text)); + /* if password is correct */ + if (verify_solution_password (&app_data.puzzle, user_pwd) == true) + app_data.solution_revealed = true; + /* password is incorrect */ + else + { + app_data.solution_revealed = false; + GtkWidget *errordlg ; + errordlg = gtk_message_dialog_new (GTK_WINDOW(main_window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + WRONG_PASSWORD); + gtk_dialog_run (GTK_DIALOG(errordlg)); + gtk_widget_destroy (errordlg); + } + } + + gtk_widget_destroy (password_text); + gtk_widget_destroy (password_dialog); + g_object_unref (builder); + } + else + app_data.solution_revealed = true; + + gtk_widget_queue_draw_area (GTK_WIDGET(area), 0, 0, + app_data.puzzle.grid_size*GRID_PIXELS+10, + app_data.puzzle.grid_size*GRID_PIXELS+10); + +} + +/* slot for load grid state menu */ +void on_menu_load_grid_state_activate (GtkMenuItem *item, GtkDrawingArea *area) +{ + GtkWidget *dialog; + GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN; + gint res; + dialog = gtk_file_chooser_dialog_new (OPEN_FILE, GTK_WINDOW (main_window), + action, + "_Cancel", + GTK_RESPONSE_CANCEL, + "_Open", + GTK_RESPONSE_ACCEPT, + NULL + ); + + res = gtk_dialog_run (GTK_DIALOG (dialog)); + if (res == GTK_RESPONSE_ACCEPT) + { + char *filename; + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + load_user_data (&app_data, filename); + g_free (filename); + } + + gtk_widget_destroy (dialog); + + gtk_widget_queue_draw_area (GTK_WIDGET(area), 0, 0, + app_data.puzzle.grid_size*GRID_PIXELS+10, + app_data.puzzle.grid_size*GRID_PIXELS+10); + + update_clue_items (); +} + +/* slot for save grid state menu */ +void on_menu_save_grid_state_activate (GtkMenuItem *item, gpointer *data) +{ + if (app_data.is_loaded == false) + return; + + GtkWidget *dialog; + GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_SAVE; + gint res; + dialog = gtk_file_chooser_dialog_new (SAVE_FILE, GTK_WINDOW(main_window), + action, + "_Cancel", + GTK_RESPONSE_CANCEL, + "_Save", + GTK_RESPONSE_ACCEPT, + NULL); + res = gtk_dialog_run (GTK_DIALOG (dialog)); + if (res == GTK_RESPONSE_ACCEPT) + { + char *filename; + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog)); + save_user_data (&app_data, filename); + g_free (filename); + } + + gtk_widget_destroy (dialog); +} + +/* slot for exit menu */ +void on_menu_exit_activate (GtkMenuItem *item, gpointer data) +{ + gtk_main_quit (); +} + +/* slot for open menu */ +void on_menu_open_activate (GtkMenuItem *item, GtkDrawingArea* area) +{ + GtkWidget *dialog; + GtkFileChooserAction action = GTK_FILE_CHOOSER_ACTION_OPEN; + gint res; + dialog = gtk_file_chooser_dialog_new (OPEN_FILE, GTK_WINDOW(main_window), + action, + "_Cancel", + GTK_RESPONSE_CANCEL, + "_Open", + GTK_RESPONSE_ACCEPT, + NULL); + res = gtk_dialog_run (GTK_DIALOG (dialog)); + if (res == GTK_RESPONSE_ACCEPT) + { + char *filename; + filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER(dialog)); + MainPlayerData temp; + reset_player_data (&temp, filename); + + /* if the grid is not frozen then the game cannot be played */ + if (temp.is_loaded == false) + { + GtkWidget *errordlg ; + errordlg = gtk_message_dialog_new (GTK_WINDOW(main_window), + GTK_DIALOG_DESTROY_WITH_PARENT, + GTK_MESSAGE_ERROR, + GTK_BUTTONS_CLOSE, + UNFROZEN_GRID_PLAYER); + gtk_dialog_run (GTK_DIALOG(errordlg)); + gtk_widget_destroy (errordlg); + } + 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 (); + g_free (filename); + } + + gtk_widget_destroy (dialog); +} + +/* slot for about menu */ +void on_menu_about_activate (GtkMenuItem *item, gpointer data) +{ + const char *AUTHOR[] = {"V.Harishankar", NULL}; + gtk_show_about_dialog (GTK_WINDOW(main_window), "authors",AUTHOR, + "program-name", PROGRAM_NAME, + "copyright", COPYRIGHT, + "comments", COMMENTS, + "website", WEBSITE, + "website-label", WEBSITE_LABEL, + "license-type", GTK_LICENSE_GPL_2_0, + "version", VERSION, + (char*)NULL); +} + +int main (int argc, char *argv []) +{ + gtk_init (&argc, &argv); + GdkPixbuf *icon; + icon = gdk_pixbuf_new_from_resource + ("/org/harishankar/wordblah/wordblah.svg", NULL); + if (icon == NULL) + fprintf (stderr, ERROR_ICON); + + GtkBuilder *builder; + builder = gtk_builder_new (); + guint ret = gtk_builder_add_from_resource (builder, + "/org/harishankar/wordblah/wordblah_player.glade", NULL); + + app_data.is_loaded = false; + + if (ret == 0) + { + fprintf (stderr, ERROR_WINDOW); + g_object_unref (builder); + return 1; + } + else + { + main_window = GTK_WIDGET (gtk_builder_get_object (builder, + "main_window")); + + across_store = GTK_LIST_STORE (gtk_builder_get_object + (builder, "store_across_clues")); + down_store = GTK_LIST_STORE (gtk_builder_get_object + (builder, "store_down_clues")); + + if (main_window != NULL) + { + 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_widget_show (main_window); + gtk_main (); + return 0; + } + else + { + g_object_unref (builder); + fprintf (stderr, ERROR_WINDOW); + return 1; + } + } +}