This is the doxygen documentation for gtkboard.
.00001 /* This file is a part of gtkboard, a board games system. 00002 Copyright (C) 2003, Arvind Narayanan <arvindn@users.sourceforge.net> 00003 00004 This program is free software; you can redistribute it and/or modify 00005 it under the terms of the GNU General Public License as published by 00006 the Free Software Foundation; either version 2 of the License, or 00007 (at your option) any later version. 00008 00009 This program is distributed in the hope that it will be useful, 00010 but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00012 GNU General Public License for more details. 00013 00014 You should have received a copy of the GNU General Public License 00015 along with this program; if not, write to the Free Software 00016 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111 USA 00017 00018 */ 00019 #include <string.h> 00020 #include <assert.h> 00021 #include <stdlib.h> 00022 00023 #include "config.h" 00024 #include "ui.h" 00025 #include "menu.h" 00026 #include "move.h" 00027 #include "ui_common.h" 00028 #include "aaball.h" 00029 #include "board.h" 00030 00031 GtkWidget *sb_message_label, *sb_game_label, *sb_score_label, 00032 *sb_who_label, *sb_player_label, *sb_time_label, *sb_turn_image, 00033 *menu_main; 00034 GtkWidget *sb_game_separator, *sb_who_separator, *sb_score_separator, 00035 *sb_player_separator, *sb_time_separator, *sb_turn_separator; 00036 #define SB_MESSAGE_STRLEN 64 00037 gchar sb_message_str[SB_MESSAGE_STRLEN] = ""; 00038 #define SB_SCORE_STRLEN 32 00039 gchar sb_score_str[SB_SCORE_STRLEN] = ""; 00040 GtkItemFactory *menu_factory = NULL; 00041 00042 void sb_messagebar_message (gchar *); 00043 00044 static char * menu_paths_sens_machine_thinking[] = 00045 { 00046 "/File/Load game", 00047 "/File/Save game", 00048 "/Game/Start", 00049 "/Game/New", 00050 "/Game/Select Game", 00051 "/Settings", 00052 "/Move/Back", 00053 "/Move/Forward", 00054 }; 00055 00056 static char * menu_paths_sens_no_game[] = 00057 { 00058 "/Game/Start", 00059 "/Game/Pause", 00060 "/Game/New", 00061 "/Game/Highscores", 00062 "/Game/Zap Highscores", 00063 "/File/Save game", 00064 "/Move/Back", 00065 "/Move/Forward", 00066 "/Settings/Flip Board", 00067 "/Settings/Player", 00068 }; 00069 00070 static char * menu_paths_sens_no_back_forw[] = 00071 { 00072 "/Move/Back", 00073 "/Move/Forward", 00074 }; 00075 00076 static char *menu_paths_sens_single_player[] = 00077 { 00078 "/Settings/Player", 00079 "/Settings/Flip Board", 00080 // "/Settings/Eval function", 00081 }; 00082 00083 static char *menu_paths_sens_two_players[] = 00084 { 00085 "/Game/Highscores", 00086 "/Game/Zap Highscores", 00087 }; 00088 00089 static char *menu_paths_sens_ui_stopped[] = 00090 { 00091 "/Game/Pause", 00092 }; 00093 00094 static char *menu_paths_sens_machine_not_thinking[] = 00095 { 00096 "/Move/Move Now", 00097 }; 00098 00099 static char *menu_paths_sens_eval_function[] = 00100 { 00101 // "/Settings/Eval function", 00102 }; 00103 00104 void sb_set_score (gchar *score) 00105 { 00106 strncpy (sb_score_str, score, SB_SCORE_STRLEN-1); 00107 sb_update (); 00108 } 00109 00110 void menu_sensitize (int which, gboolean sens) 00111 { 00112 int i, num_paths = -1; 00113 char **menu_des_paths = NULL; 00114 if (!state_gui_active) return; 00115 switch (which) 00116 { 00117 case MENU_SENS_MACHINE_THINKING: 00118 menu_des_paths = menu_paths_sens_machine_thinking; 00119 num_paths = sizeof (menu_paths_sens_machine_thinking) / 00120 sizeof (menu_paths_sens_machine_thinking[0]); 00121 break; 00122 case MENU_SENS_MACHINE_NOT_THINKING: 00123 menu_des_paths = menu_paths_sens_machine_not_thinking; 00124 num_paths = sizeof (menu_paths_sens_machine_not_thinking) / 00125 sizeof (menu_paths_sens_machine_not_thinking[0]); 00126 break; 00127 case MENU_SENS_NO_GAME: 00128 menu_des_paths = menu_paths_sens_no_game; 00129 num_paths = sizeof (menu_paths_sens_no_game) / 00130 sizeof (menu_paths_sens_no_game[0]); 00131 break; 00132 case MENU_SENS_NO_BACK_FORW: 00133 menu_des_paths = menu_paths_sens_no_back_forw; 00134 num_paths = sizeof (menu_paths_sens_no_back_forw) / 00135 sizeof (menu_paths_sens_no_back_forw[0]); 00136 break; 00137 case MENU_SENS_SINGLE_PLAYER: 00138 menu_des_paths = menu_paths_sens_single_player; 00139 num_paths = sizeof (menu_paths_sens_single_player) / 00140 sizeof (menu_paths_sens_single_player[0]); 00141 break; 00142 case MENU_SENS_TWO_PlayerS: 00143 menu_des_paths = menu_paths_sens_two_players; 00144 num_paths = sizeof (menu_paths_sens_two_players) / 00145 sizeof (menu_paths_sens_two_players[0]); 00146 break; 00147 case MENU_SENS_UI_STOPPED: 00148 menu_des_paths = menu_paths_sens_ui_stopped; 00149 num_paths = sizeof (menu_paths_sens_ui_stopped) / 00150 sizeof (menu_paths_sens_ui_stopped[0]); 00151 break; 00152 case MENU_SENS_EVAL_FUNCTION: 00153 menu_des_paths = menu_paths_sens_eval_function; 00154 num_paths = sizeof (menu_paths_sens_eval_function) / 00155 sizeof (menu_paths_sens_eval_function[0]); 00156 break; 00157 default: 00158 g_assert_not_reached (); 00159 } 00160 for (i=0; i<num_paths; i++) 00161 gtk_widget_set_sensitive (gtk_item_factory_get_widget (menu_factory, 00162 menu_des_paths[i]), sens); 00163 } 00164 00165 void sb_set_turn_image () 00166 { 00167 #if GTK_MAJOR_VERSION == 2 00168 // FIXME: can't get existing bgcolor 00169 const int size = 20; 00170 static char pixbufs [7][size*(size+1)]; 00171 char **pixmap_data; 00172 static GdkPixmap *pixmaps[7]; 00173 int colors[7] = {0x007700, 0x77ff77, 0x770000, 0xff7777, 0x000077, 0x7777ff, 00174 0x777777}; 00175 int i, j; 00176 static int first = 1; 00177 static int previndex = -1; 00178 int index = -1; 00179 if (first) 00180 { 00181 int i; 00182 for (i=0; i<7; i++) 00183 { 00184 pixmap_data = pixmap_ball_gen (size, pixbufs[i], colors[i], 00185 0xffffff, 6.5, 24); 00186 pixmaps[i] = gdk_pixmap_create_from_xpm_d 00187 ((GdkWindow *)main_window->window, NULL, NULL, pixmap_data); 00188 } 00189 gtk_image_set_from_pixmap (GTK_IMAGE (sb_turn_image), 00190 pixmaps[previndex = 6], NULL); 00191 first = 0; 00192 } 00193 if (opt_infile || !opt_game) 00194 index = 6; 00195 else 00196 { 00197 if (!game_single_player && ui_white == HUMAN && ui_black == HUMAN 00198 && cur_pos.player == BLACK) index = 4; 00199 else index = (player_to_play == HUMAN ? 0 : 2); 00200 if (ui_stopped) index++; 00201 } 00202 g_assert (index >= 0 && index <= 6); 00203 if (index == previndex) return; 00204 gtk_image_set_from_pixmap (GTK_IMAGE (sb_turn_image), 00205 pixmaps[previndex = index], NULL); 00206 #endif 00207 } 00208 00209 static void sb_set_cursor () 00210 { 00211 static GdkCursor *cursor_normal = NULL, *cursor_busy = NULL, 00212 *cursor_inactive = NULL; 00213 // FIXME: is it ok to hard code the shape of the normal cursor? 00214 if (!cursor_normal) cursor_normal = gdk_cursor_new (GDK_LEFT_PTR); 00215 if (!cursor_busy) cursor_busy = gdk_cursor_new (GDK_WATCH); 00216 if (!cursor_inactive) cursor_inactive = gdk_cursor_new (GDK_XTERM); 00217 if (player_to_play == MACHINE && !ui_stopped) 00218 gdk_window_set_cursor (board_area->window, cursor_busy); 00219 else if (player_to_play == MACHINE && ui_stopped) 00220 gdk_window_set_cursor (board_area->window, cursor_inactive); 00221 else 00222 gdk_window_set_cursor (board_area->window, cursor_normal); 00223 } 00224 00225 void menu_board_flip_cb () 00226 { 00227 if (game_single_player) 00228 { 00229 sb_error ("Can't flip board in single player game", TRUE); 00230 return; 00231 } 00232 if (!game_allow_flip) 00233 { 00234 sb_error ("This game doesn't allow the board to be flipped", TRUE); 00235 return; 00236 } 00237 state_board_flipped = state_board_flipped ? FALSE : TRUE; 00238 board_redraw (NULL, NULL); 00239 } 00240 00241 00242 static void menu_show_dialog_real (gchar *title, gchar *message, gboolean wrap) 00243 // A modal dialog with a label. Don't use it for showing large amounts of text 00244 { 00245 GtkWidget *dialog, *okay_button, *label; 00246 00247 label = gtk_label_new (message); 00248 #if GTK_MAJOR_VERSION == 1 00249 dialog = gtk_dialog_new(); 00250 gtk_window_set_title (GTK_WINDOW (dialog), title); 00251 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (main_window)); 00252 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); 00253 okay_button = gtk_button_new_with_label("OK"); 00254 00255 gtk_signal_connect_object (GTK_OBJECT (okay_button), "clicked", 00256 GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog); 00257 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area), 00258 okay_button); 00259 #else 00260 dialog = gtk_dialog_new_with_buttons (title, GTK_WINDOW (main_window), 00261 GTK_DIALOG_MODAL, NULL); 00262 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 100); 00263 okay_button = gtk_dialog_add_button (GTK_DIALOG (dialog), 00264 GTK_STOCK_OK, GTK_RESPONSE_NONE); 00265 g_signal_connect_swapped (GTK_OBJECT (dialog), 00266 "response", G_CALLBACK (gtk_widget_destroy), GTK_OBJECT (dialog)); 00267 gtk_label_set_selectable (GTK_LABEL (label), TRUE); 00268 #endif 00269 gtk_label_set_line_wrap (GTK_LABEL (label), wrap); 00270 gtk_widget_grab_focus (okay_button); 00271 00272 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label); 00273 gtk_widget_show_all (dialog); 00274 } 00275 00276 void menu_show_dialog (gchar *title, gchar *message) 00277 { 00278 menu_show_dialog_real (title, message, FALSE); 00279 } 00280 00281 void menu_show_dialog_wrap (gchar *title, gchar *message) 00282 { 00283 menu_show_dialog_real (title, message, TRUE); 00284 } 00285 00286 00287 void menu_pause_cb (GtkWidget *dialog) 00288 { 00289 gtk_widget_destroy (GTK_WIDGET (dialog)); 00290 menu_start_stop_game (NULL, MENU_START_GAME); 00291 } 00292 00293 void menu_show_pause_dialog () 00294 // Game paused 00295 { 00296 GtkWidget *dialog, *okay_button, *label; 00297 gchar *title = "Game paused - gtkboard"; 00298 00299 board_hide(); 00300 00301 label = gtk_label_new ("Game paused. Click OK to continue"); 00302 #if GTK_MAJOR_VERSION == 1 00303 dialog = gtk_dialog_new(); 00304 gtk_window_set_title (GTK_WINDOW (dialog), title); 00305 gtk_window_set_transient_for (GTK_WINDOW (dialog), GTK_WINDOW (main_window)); 00306 gtk_window_set_modal (GTK_WINDOW (dialog), TRUE); 00307 okay_button = gtk_button_new_with_label("OK"); 00308 00309 gtk_signal_connect_object (GTK_OBJECT (okay_button), "clicked", 00310 GTK_SIGNAL_FUNC (menu_pause_cb), (gpointer) dialog); 00311 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->action_area), 00312 okay_button); 00313 #else 00314 dialog = gtk_dialog_new_with_buttons (title, GTK_WINDOW (main_window), 00315 GTK_DIALOG_MODAL, NULL); 00316 gtk_window_set_default_size (GTK_WINDOW (dialog), 300, 100); 00317 okay_button = gtk_dialog_add_button (GTK_DIALOG (dialog), 00318 GTK_STOCK_OK, GTK_RESPONSE_NONE); 00319 gtk_label_set_selectable (GTK_LABEL (label), TRUE); 00320 #endif 00321 gtk_widget_grab_focus (okay_button); 00322 00323 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), label); 00324 gtk_widget_show_all (dialog); 00325 00326 #if GTK_MAJOR_VERSION > 1 00327 gtk_dialog_run (GTK_DIALOG (dialog)); 00328 menu_pause_cb (dialog); 00329 #endif 00330 } 00331 00332 void menu_show_about_dialog (gpointer data) 00333 { 00334 menu_show_dialog ("About gtkboard", 00335 "gtkboard " VERSION "\n" 00336 "http://gtkboard.sourceforge.net/\n" 00337 "Maintainer: Arvind Narayanan <arvindn@users.sourceforge.net>\n" 00338 "Released under the GNU General Public License\n" 00339 "See the file COPYING for details\n" 00340 "\n" 00341 "The documentation is available in the doc/ directory\n" 00342 "of the source distribution or in the directory\n" 00343 "/usr/local/doc/gtkboard-" VERSION "/ if you installed from binary rpm.\n" 00344 "The latest documentation will always be available at\n" 00345 "http://gtkboard.sourceforge.net/doc/" 00346 ); 00347 } 00348 00349 void menu_show_begging_dialog (gpointer data) 00350 { 00351 menu_show_dialog_wrap ("Begging bowl", 00352 "Thanks for using gtkboard. I hope you liked it.\n\n" 00353 "The download counter on sourceforge is broken. " 00354 "They call it an \"inaccuracy\", but the fact of the matter is that it's firmly stuck at zero, which means that I have no idea how many people are downloading/using the software. So you see, I'm as lonely as a lark (or whatever it is that's supposed to be very lonely.) So if you have any comments or suggestions, or even just some kind words, it would be nice if you can mail them me. My email is arvindn@users.sourceforge.net. Thanks." 00355 ); 00356 } 00357 00358 00359 void menu_put_player (); 00360 00361 void menu_start_stop_game (gpointer data, guint what) 00362 { 00363 switch (what) 00364 { 00365 case MENU_START_GAME: 00366 if (!opt_game) break; 00367 if (!ui_stopped) 00368 break; 00369 board_show(); 00370 if (ui_gameover) 00371 { 00372 sb_error ("Game over", FALSE); 00373 break; 00374 } 00375 if (!impl_check()) 00376 { 00377 sb_error ("Not yet implemented", TRUE); 00378 break; 00379 } 00380 ui_stopped = FALSE; 00381 ui_send_make_move (); 00382 sb_update(); 00383 break; 00384 case MENU_STOP_GAME: 00385 if (!opt_game) break; 00386 if (ui_stopped) break; 00387 ui_stopped = TRUE; 00388 ui_cancel_move (); 00389 sb_update(); 00390 if (game_single_player && ui_white == HUMAN) 00391 menu_show_pause_dialog (); 00392 break; 00393 case MENU_RESET_GAME: 00394 { 00395 int saved_white = ui_white; 00396 int saved_black = ui_black; 00397 if (!opt_game) break; 00398 ui_terminate_game (); 00399 ui_start_game (); 00400 ui_white = saved_white; 00401 ui_black = saved_black; 00402 menu_put_player(FALSE); 00403 sb_reset_human_time (); 00404 sb_update(); 00405 break; 00406 } 00407 default: 00408 printf ("menu_start_stop_game: %d\n", what); 00409 assert (0); 00410 } 00411 } 00412 00413 00414 // set the menu corresponding to ui_white and ui_black 00415 // if first is TRUE use opt_white and opt_black 00416 void menu_put_player (gboolean first) 00417 { 00418 gchar *path, *paths[4] = { 00419 "/Settings/Player/Human-Human", "/Settings/Player/Human-Machine", 00420 "/Settings/Player/Machine-Human", "/Settings/Player/Machine-Machine"}; 00421 if (!state_gui_active) return; 00422 if (first) {ui_white = opt_white; ui_black = opt_black;} 00423 if (opt_infile) 00424 { 00425 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM 00426 (gtk_item_factory_get_widget (menu_factory, "/Settings/Player/File")), 00427 TRUE); 00428 00429 return; 00430 } 00431 else if (ui_white == HUMAN && ui_black == HUMAN) 00432 path = paths[0]; 00433 else if (ui_white == HUMAN && ui_black == MACHINE) 00434 path = paths[1]; 00435 else if (ui_white == MACHINE && ui_black == HUMAN) 00436 path = paths[2]; 00437 else if (ui_white == MACHINE && ui_black == MACHINE) 00438 path = paths[3]; 00439 else 00440 return; 00441 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM 00442 (gtk_item_factory_get_widget (menu_factory, path)), TRUE); 00443 } 00444 00445 void menu_put_game () 00446 { 00447 gchar path[32] = "/Game/Select Game/"; 00448 strcat (path, opt_game->name); 00449 gtk_check_menu_item_set_active (GTK_CHECK_MENU_ITEM 00450 (gtk_item_factory_get_widget (menu_factory, path)), TRUE); 00451 } 00452 00453 GtkWidget *menu_selector; 00454 00455 void menu_load_file (GtkFileSelection *selector, gpointer user_data) 00456 { 00457 gchar const *filename; 00458 static FILE *in; 00459 filename = gtk_file_selection_get_filename 00460 (GTK_FILE_SELECTION(menu_selector)); 00461 if (!(in = fopen (filename, "r"))) 00462 { 00463 gchar *tempstr = g_strdup_printf 00464 ("Could not open file \"%s\" for reading", filename); 00465 sb_error (tempstr, TRUE); 00466 g_free (tempstr); 00467 return; 00468 } 00469 if (opt_infile) 00470 fclose (opt_infile); 00471 opt_infile = in; 00472 // FIXME: shouldn't this be MACHINE ? 00473 ui_white = ui_black = NONE; 00474 menu_put_player (FALSE); 00475 cur_pos.player = WHITE; 00476 game_set_init_pos (&cur_pos); 00477 board_redraw_all (); 00478 sb_message ("Opened file", FALSE); 00479 } 00480 00481 void menu_set_player (gpointer *data, guint what, GtkWidget *widget) 00482 { 00483 /* the callback for a radio button appears to 00484 be called TWICE, once when selected and once when something else 00485 is selected. */ 00486 00487 if (!GTK_CHECK_MENU_ITEM(widget)->active) 00488 return; 00489 00490 if (what >= 1 && what <= 4) 00491 if (opt_infile) 00492 { 00493 fclose (opt_infile); 00494 opt_infile = NULL; 00495 } 00496 00497 ui_stopped = TRUE; 00498 00499 switch (what) 00500 { 00501 case 1: 00502 ui_white = HUMAN; 00503 ui_black = HUMAN; 00504 break; 00505 case 2: 00506 ui_white = HUMAN; 00507 ui_black = MACHINE; 00508 break; 00509 case 3: 00510 ui_white = MACHINE; 00511 ui_black = HUMAN; 00512 break; 00513 case 4: 00514 ui_white = MACHINE; 00515 ui_black = MACHINE; 00516 break; 00517 00518 default: 00519 ui_white = NONE; 00520 ui_black = NONE; 00521 break; 00522 } 00523 00524 sb_update (); 00525 } 00526 00527 void menu_save_file_dialog () 00528 { 00529 sb_error ("Not yet implemented", TRUE); 00530 } 00531 00532 void menu_load_file_dialog () 00533 { 00534 if (game_single_player) 00535 { 00536 sb_error ("Can't load from file for single player game.", FALSE); 00537 return; 00538 } 00539 menu_selector = gtk_file_selection_new (""); 00540 g_assert (menu_selector); 00541 /*gtk_file_selection_complete ( 00542 GTK_FILE_SELECTION (menu_selector), "*.cbgf");*/ 00543 00544 gtk_signal_connect (GTK_OBJECT 00545 (GTK_FILE_SELECTION(menu_selector)->ok_button), 00546 "clicked", GTK_SIGNAL_FUNC (menu_load_file), NULL); 00547 00548 gtk_signal_connect_object (GTK_OBJECT 00549 (GTK_FILE_SELECTION(menu_selector)->ok_button), 00550 "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), 00551 (gpointer) menu_selector); 00552 00553 gtk_signal_connect_object ( 00554 GTK_OBJECT (GTK_FILE_SELECTION(menu_selector)->cancel_button), 00555 "clicked", GTK_SIGNAL_FUNC (gtk_widget_destroy), 00556 (gpointer) menu_selector); 00557 00558 gtk_widget_show (menu_selector); 00559 } 00560 00561 void menu_show_game_doc (gpointer data, guint which) 00562 { 00563 GtkWidget *dialog, *msgarea, *okay_button, *vbar, *hbox, *scrwin; 00564 char *msgstr = "Nothing available"; // default 00565 char titlestr[64]; 00566 switch (which) 00567 { 00568 case MENU_DOC_ABOUT: 00569 snprintf (titlestr, 64, "About %s - gtkboard", opt_game->name); 00570 if (game_doc_about) msgstr = game_doc_about; 00571 menu_show_dialog (titlestr, msgstr); 00572 return; 00573 case MENU_DOC_RULES: 00574 snprintf (titlestr, 64, "%s rules - gtkboard", opt_game->name); 00575 if (game_doc_rules) msgstr = game_doc_rules; 00576 break; 00577 case MENU_DOC_STRATEGY: 00578 snprintf (titlestr, 64, "%s strategy - gtkboard", opt_game->name); 00579 if (game_doc_strategy) msgstr = game_doc_strategy; 00580 break; 00581 default: 00582 assert (0); 00583 } 00584 00585 vbar = gtk_vscrollbar_new(NULL); 00586 #if GTK_MAJOR_VERSION == 1 00587 dialog = gtk_dialog_new(); 00588 gtk_window_set_title (GTK_WINDOW (dialog), titlestr); 00589 hbox = gtk_hbox_new (FALSE, 0); 00590 msgarea = gtk_text_new (NULL, 00591 gtk_range_get_adjustment (GTK_RANGE (vbar))); 00592 gtk_text_set_word_wrap (GTK_TEXT (msgarea), TRUE); 00593 gtk_text_insert (GTK_TEXT (msgarea), NULL, NULL, NULL, msgstr, -1); 00594 gtk_box_pack_start (GTK_BOX (hbox), msgarea, TRUE, TRUE, 10); 00595 gtk_box_pack_start (GTK_BOX (hbox), vbar, FALSE, FALSE, 0); 00596 okay_button = gtk_button_new_with_label(" OK "); 00597 gtk_signal_connect_object (GTK_OBJECT (okay_button), "clicked", 00598 GTK_SIGNAL_FUNC (gtk_widget_destroy), (gpointer) dialog); 00599 gtk_box_pack_start (GTK_BOX (GTK_DIALOG(dialog)->action_area), 00600 okay_button, FALSE, FALSE, 0); 00601 gtk_widget_grab_focus (okay_button); // contributed by Paddu 00602 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), hbox); 00603 00604 #else 00605 dialog = gtk_dialog_new_with_buttons (titlestr, GTK_WINDOW (main_window), 00606 0, GTK_STOCK_OK, GTK_RESPONSE_NONE, NULL); 00607 gtk_window_set_default_size (GTK_WINDOW (dialog), 400, 300); 00608 g_signal_connect_swapped (GTK_OBJECT (dialog), 00609 "response", G_CALLBACK (gtk_widget_destroy), 00610 GTK_OBJECT (dialog)); 00611 msgarea = gtk_text_view_new (); 00612 gtk_text_view_set_editable (GTK_TEXT_VIEW (msgarea), FALSE); 00613 gtk_text_view_set_wrap_mode (GTK_TEXT_VIEW (msgarea), GTK_WRAP_WORD); 00614 gtk_text_view_set_cursor_visible (GTK_TEXT_VIEW (msgarea), FALSE); 00615 gtk_text_buffer_set_text (gtk_text_view_get_buffer 00616 (GTK_TEXT_VIEW (msgarea)), msgstr, -1); 00617 scrwin = gtk_scrolled_window_new (NULL, 00618 gtk_range_get_adjustment (GTK_RANGE(vbar))); 00619 gtk_container_add (GTK_CONTAINER (scrwin), msgarea); 00620 gtk_container_add (GTK_CONTAINER (GTK_DIALOG(dialog)->vbox), scrwin); 00621 #endif 00622 gtk_widget_show_all (dialog); 00623 } 00624 00625 void menu_start_game () 00626 { 00627 ui_start_game (); 00628 00629 { 00630 int i; 00631 GtkItemFactoryEntry help_items [3]; 00632 help_items[0].path = g_strdup_printf ("/Help/%s", opt_game->name); 00633 help_items[0].accelerator = NULL; 00634 help_items[0].callback = NULL; 00635 help_items[0].item_type = "<Branch>"; 00636 gtk_item_factory_create_item (menu_factory, help_items, NULL, 1); 00637 00638 help_items[0].path = g_strdup_printf ("/Help/%s/_About", opt_game->name); 00639 help_items[0].callback_action = MENU_DOC_ABOUT; 00640 help_items[1].path = g_strdup_printf ("/Help/%s/_Rules", opt_game->name); 00641 help_items[1].callback_action = MENU_DOC_RULES; 00642 help_items[2].path = g_strdup_printf ("/Help/%s/_Strategy", opt_game->name); 00643 help_items[2].callback_action = MENU_DOC_STRATEGY; 00644 for (i=0; i<3; i++) 00645 { 00646 help_items[i].accelerator = NULL; 00647 help_items[i].callback = menu_show_game_doc; 00648 help_items[i].item_type = ""; 00649 } 00650 gtk_item_factory_create_items (menu_factory, 00651 3, help_items, NULL); 00652 } 00653 gtk_label_set_text (GTK_LABEL (sb_game_label), opt_game->name); 00654 } 00655 00656 void menu_set_game (gpointer data, guint which, GtkWidget *widget) 00657 { 00658 gchar *tempstr; 00659 if (!GTK_CHECK_MENU_ITEM(widget)->active) 00660 return; 00661 if (!state_gui_active) 00662 return; 00663 g_assert (which >= 0 && which < num_games); 00664 00665 if (opt_game) 00666 { 00667 // FIXME: do we need to delete recursively? 00668 gtk_item_factory_delete_item (menu_factory, 00669 tempstr = g_strdup_printf ("/Help/%s", opt_game->name)); 00670 g_free (tempstr); 00671 } 00672 00673 if (opt_game) 00674 ui_terminate_game (); 00675 opt_game = games[which]; 00676 menu_start_game (); 00677 sb_update (); 00678 } 00679 00680 00681 void menu_set_delay_cb (gpointer data, guint delay, GtkWidget *widget) 00682 { 00683 if (!GTK_CHECK_MENU_ITEM(widget)->active) 00684 return; 00685 if (move_fout) 00686 { 00687 fprintf (move_fout, "MSEC_PER_MOVE %d\n", opt_delay = delay); 00688 fflush (move_fout); 00689 } 00690 } 00691 00692 00693 void menu_back_forw (gpointer data, guint what) 00694 { 00695 byte *move; 00696 switch (what) 00697 { 00698 case MENU_BACK: 00699 if (!game_allow_back_forw) break; 00700 if (!opt_game) break; 00701 if (!game_allow_undo) 00702 ui_stopped = TRUE; 00703 if (move_fout) 00704 { 00705 fprintf (move_fout, "BACK_MOVE \n"); 00706 fflush (move_fout); 00707 } 00708 move = move_fread_ack (move_fin); 00709 if (!move) 00710 { 00711 sb_error ("Initial position. Can't go back.", FALSE); 00712 break; 00713 } 00714 board_apply_refresh (move, NULL); 00715 if (!game_single_player) 00716 cur_pos.player = (cur_pos.player == WHITE ? BLACK : WHITE); 00717 cur_pos.num_moves --; 00718 if (game_single_player && !game_allow_undo) 00719 { 00720 if (!ui_cheated && game_scorecmp) 00721 sb_message ("You cheated! No highscore for this game.", FALSE); 00722 ui_cheated = TRUE; 00723 } 00724 // FIXME: there should be only one round of communication 00725 // in which client gets both the move and who_won 00726 ui_check_who_won (); 00727 if (game_reset_uistate) game_reset_uistate(); 00728 sb_update (); 00729 break; 00730 case MENU_FORW: 00731 if (!game_allow_back_forw) break; 00732 if (!opt_game) break; 00733 if (move_fout) 00734 { 00735 fprintf (move_fout, "FORW_MOVE \n"); 00736 fflush (move_fout); 00737 } 00738 move = move_fread_ack (move_fin); 00739 if (!move) 00740 { 00741 sb_error ("Final position. Can't go forward.", FALSE); 00742 break; 00743 } 00744 board_apply_refresh (move, NULL); 00745 if (!game_single_player) 00746 cur_pos.player = (cur_pos.player == WHITE ? BLACK : WHITE); 00747 cur_pos.num_moves ++; 00748 ui_check_who_won (); 00749 if (game_reset_uistate) game_reset_uistate(); 00750 sb_update (); 00751 break; 00752 default: 00753 assert (0); 00754 } 00755 } 00756 00758 void menu_set_eval_function () 00759 { 00760 int i; 00761 GtkWidget *menu, *menuitem; 00762 GtkItemFactoryEntry heur_item; 00763 static HeurTab *oldtab = NULL; 00764 char *colors[2], **color, pathbuf[64]; 00765 return; 00766 colors[0] = game_white_string; 00767 colors[1] = game_black_string; 00768 for (color = colors; color <= colors+1; color++) 00769 { 00770 if (oldtab) 00771 for (i=0; oldtab[i].name; i++) 00772 { 00773 char *path = g_strdup_printf ("/Settings/Eval function/%s/%s", 00774 *color, oldtab[i].name); 00775 gtk_item_factory_delete_item (menu_factory, path); 00776 g_free (path); 00777 } 00778 if (game_htab) 00779 for (i=0; game_htab[i].name; i++) 00780 { 00781 heur_item.path = g_strdup_printf ("/Settings/Eval function/%s/%s", 00782 *color, game_htab[i].name); 00783 if (i == 0) strncpy (pathbuf, heur_item.path, 63); 00784 heur_item.accelerator = NULL; 00785 heur_item.callback = NULL; 00786 heur_item.callback_action = 0; 00787 heur_item.item_type = (i == 0 ? "<RadioItem>" : pathbuf); 00788 gtk_item_factory_create_item (menu_factory, &heur_item, NULL, 1); 00789 g_free (heur_item.path); 00790 } 00791 } 00792 oldtab = game_htab; 00793 } 00794 00795 void sb_error (char *msg, gboolean serious) 00796 { 00797 if (!state_gui_active) 00798 { 00799 fprintf (stderr, "Fatal error: %s\n", msg); 00800 exit (2); 00801 } 00802 if (serious) 00803 menu_show_dialog ("Error - gtkboard", msg); 00804 else 00805 sb_messagebar_message (msg); 00806 } 00807 00808 void sb_message (char *msg, gboolean serious) 00809 { 00810 if (!state_gui_active) 00811 fprintf (stderr, "%s\n", msg); 00812 else 00813 sb_error (msg, serious); 00814 } 00815 00816 gchar *sb_ftime(int temps) 00817 { 00818 static gchar ftime[10] = " : : "; 00819 ftime[6] = temps % 10 + '0'; 00820 temps /= 10; 00821 ftime[4] = temps % 10 + '0'; 00822 temps /= 10; 00823 ftime[3] = temps % 6 + '0'; 00824 temps /= 6; 00825 ftime[1] = temps % 10 + '0'; 00826 temps /= 10; 00827 ftime[0] = temps % 6 + '0'; 00828 temps /= 6; 00829 return ftime; 00830 } 00831 00832 static int sb_human_time = 0; 00833 00834 void sb_reset_human_time () 00835 { 00836 gchar *tempstr; 00837 sb_human_time = 0; 00838 if (!state_gui_active) 00839 return; 00840 gtk_label_set_text (GTK_LABEL(sb_time_label), tempstr 00841 = g_strdup_printf ("Time:%s", sb_ftime(sb_human_time))); 00842 g_free (tempstr); 00843 } 00844 00845 int sb_get_human_time () 00846 { 00847 return sb_human_time; 00848 } 00849 00850 static int sb_last_msg_time = -1; 00851 00852 void sb_messagebar_message (gchar *msg) 00853 { 00854 sb_last_msg_time = 0; 00855 strncpy (sb_message_str, msg, SB_MESSAGE_STRLEN-1); 00856 sb_update (); 00857 } 00858 00859 void menu_update () 00860 // first call all the sens and then all the desens 00861 { 00862 // FIXME: isn't there a more elegant way to do this? 00863 gboolean machine_thinking, machine_not_thinking, 00864 no_game, single_player, two_players, 00865 no_back_forw, eval_fn; 00866 machine_thinking = (!ui_stopped && player_to_play == MACHINE); 00867 machine_not_thinking = !machine_thinking; 00868 no_game = opt_game ? FALSE : TRUE; 00869 single_player = game_single_player; 00870 two_players = !single_player; 00871 no_back_forw = !game_allow_back_forw; 00872 eval_fn = game_htab ? FALSE : TRUE; 00873 00874 if (!machine_thinking) menu_sensitize (MENU_SENS_MACHINE_THINKING, TRUE); 00875 if (!machine_not_thinking) menu_sensitize (MENU_SENS_MACHINE_NOT_THINKING, TRUE); 00876 if (!no_game) menu_sensitize (MENU_SENS_NO_GAME, TRUE); 00877 if (!single_player) menu_sensitize (MENU_SENS_SINGLE_PLAYER, TRUE); 00878 if (!two_players) menu_sensitize (MENU_SENS_TWO_PlayerS, TRUE); 00879 if (!no_back_forw) menu_sensitize (MENU_SENS_NO_BACK_FORW, TRUE); 00880 if (!ui_stopped) menu_sensitize (MENU_SENS_UI_STOPPED, TRUE); 00881 if (!eval_fn) menu_sensitize (MENU_SENS_EVAL_FUNCTION, TRUE); 00882 00883 if (machine_thinking) menu_sensitize (MENU_SENS_MACHINE_THINKING, FALSE); 00884 if (machine_not_thinking) menu_sensitize (MENU_SENS_MACHINE_NOT_THINKING, FALSE); 00885 if (no_game) menu_sensitize (MENU_SENS_NO_GAME, FALSE); 00886 if (single_player) menu_sensitize (MENU_SENS_SINGLE_PLAYER, FALSE); 00887 if (two_players) menu_sensitize (MENU_SENS_TWO_PlayerS, FALSE); 00888 if (no_back_forw) menu_sensitize (MENU_SENS_NO_BACK_FORW, FALSE); 00889 if (ui_stopped) menu_sensitize (MENU_SENS_UI_STOPPED, FALSE); 00890 if (eval_fn) menu_sensitize (MENU_SENS_EVAL_FUNCTION, FALSE); 00891 00892 } 00893 00894 void sb_update () 00895 { 00896 char player[5] = "?/?"; 00897 if (!state_gui_active) return; 00898 menu_update (); 00899 if (game_single_player) 00900 { 00901 gtk_widget_hide (sb_player_label); 00902 gtk_widget_hide (sb_who_label); 00903 gtk_widget_hide (sb_player_separator); 00904 gtk_widget_hide (sb_who_separator); 00905 gtk_widget_show (sb_time_separator); 00906 gtk_widget_show (sb_time_label); 00907 } 00908 else 00909 { 00910 gtk_widget_show (sb_player_label); 00911 gtk_widget_show (sb_who_label); 00912 gtk_widget_show (sb_player_separator); 00913 gtk_widget_show (sb_who_separator); 00914 gtk_widget_hide (sb_time_separator); 00915 gtk_widget_hide (sb_time_label); 00916 if (ui_white == HUMAN) player[0] = 'H'; 00917 if (ui_white == MACHINE) player[0] = 'M'; 00918 if (ui_black == HUMAN) player[2] = 'H'; 00919 if (ui_black == MACHINE) player[2] = 'M'; 00920 gtk_label_set_text (GTK_LABEL(sb_player_label), 00921 ui_white != NONE ? player : "File"); 00922 gtk_label_set_text (GTK_LABEL(sb_who_label), cur_pos.player == WHITE ? 00923 game_white_string : game_black_string); 00924 } 00925 gtk_label_set_text (GTK_LABEL(sb_score_label), sb_score_str); 00926 sb_set_turn_image(); 00927 sb_set_cursor (); 00928 } 00929 00930 gboolean sb_update_periodic () 00931 { 00932 static gboolean first = TRUE; 00933 if (!state_gui_active) return TRUE; 00934 if (sb_message_str[0] != '\0' && sb_last_msg_time < 0) 00935 sb_last_msg_time = 0; 00936 if (sb_message_str[0] == '\0') sb_last_msg_time = -1; 00937 if (sb_last_msg_time >= 0) sb_last_msg_time++; 00938 if (sb_last_msg_time >= 30) 00939 sb_message_str[0] = '\0'; 00940 gtk_label_set_text (GTK_LABEL(sb_message_label), sb_message_str); 00941 { 00942 gchar *tempstr = NULL; 00943 if (!ui_stopped && (player_to_play == HUMAN)) 00944 gtk_label_set_text (GTK_LABEL(sb_time_label), 00945 tempstr = g_strdup_printf ("Time:%s", sb_ftime(sb_human_time++))); 00946 if (first) 00947 gtk_label_set_text (GTK_LABEL(sb_time_label), 00948 tempstr = g_strdup_printf ("Time:%s", sb_ftime(sb_human_time))); 00949 if (tempstr) g_free (tempstr); 00950 } 00951 first = FALSE; 00952 return TRUE; 00953 }