Crossfire Client, Branch
R11627
|
00001 const char * const rcsid_gtk_config_c = 00002 "$Id: config.c 9576 2008-07-19 23:42:35Z kbulgrien $"; 00003 /* 00004 Crossfire client, a client program for the crossfire program. 00005 00006 Copyright (C) 2001 Mark Wedel & Crossfire Development Team 00007 00008 This program is free software; you can redistribute it and/or modify 00009 it under the terms of the GNU General Public License as published by 00010 the Free Software Foundation; either version 2 of the License, or 00011 (at your option) any later version. 00012 00013 This program is distributed in the hope that it will be useful, 00014 but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00016 GNU General Public License for more details. 00017 00018 You should have received a copy of the GNU General Public License 00019 along with this program; if not, write to the Free Software 00020 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00021 00022 The author can be reached via e-mail to crossfire-devel@real-time.com 00023 */ 00024 00025 /* This file handles the loading and saving of the configuration options, 00026 * as well as presenting a nice gui to select the 00027 * options 00028 */ 00029 00030 #include <config.h> 00031 00032 #ifdef __CYGWIN__ 00033 #include <errno.h> 00034 #endif 00035 00036 /* gtk */ 00037 #include <gtk/gtk.h> 00038 #ifndef WIN32 00039 #include <gdk/gdkx.h> 00040 #else 00041 #include <gdk/gdkwin32.h> 00042 #endif 00043 #include <gdk/gdkkeysyms.h> 00044 00045 00046 /* always include our local headers after the system headers are included */ 00047 #include "client.h" 00048 /*#include "clientbmap.h"*/ 00049 #include "item.h" 00050 #include "gx11.h" 00051 #include "gtkproto.h" 00052 #include <ctype.h> 00053 00054 00055 /* Abstract this out a bit - rather than have a whole bunch of 00056 * duplicated code that generates these values, instead use 00057 * pointers to functions that set and get the values - this 00058 * makes adding new widgets a lot easier in most cases. 00059 * 00060 * button is the actual widget that is created. 00061 * 00062 * label is the label that is to be printed 00063 * 00064 * type if the type of widget. As long as the widget only 00065 * needs to deal with numeric type values, this works 00066 * fine - this means that dials can get just as easily 00067 * added to this list 00068 * 00069 * config holds the corresponding CONFIG value from 00070 * the common/client.h file. This allows 00071 * use to use a fairly common function for most 00072 * values. 00073 * 00074 * flags holds flags. Currently, the 00075 * only flag is FLAG_UPDATE - if set, 00076 * then we automatically the running total 00077 * immediately. Otherwise, the want_config value 00078 * only gets updated, and depending on the value, 00079 * that value may get used/copied into the use_config 00080 * at a later point. Many values which can change at 00081 * runtime do not have this flag set simply so that it 00082 * is easier to notice if it has changed and do the 00083 * appropraite thing (eg, stop/start sound daemon, etc) 00084 * 00085 * Note on RBUTTON (radio button usage): Since a radio 00086 * button is a collection of buttons of only which one can 00087 * be pressed, the logic the program uses is this: 00088 * 1) If the previous widget was a radio button, we add 00089 * this one to the same group. This means if you want to 00090 * have multiple sets of radio buttons, you should seperate 00091 * them with something. 00092 * 2) Since the radio button is several widgets, its not as simple 00093 * as normal buttons to map them to a config value. Instead, 00094 * use a range so that it is easy to tell what config value 00095 * your button belongs to, eg, 100-199 is for the lighting 00096 * options. 00097 */ 00098 00099 #define MAX_BUTTONS 33 00100 #define RBUTTON 1 00101 #define CBUTTON 2 00102 #define SEPERATOR 3 /* Seperator in the window */ 00103 00104 #define SPIN 0x100 00105 #define SPIN_SCALE 0x101 /* Spin Button that is image scale */ 00106 #define SPIN_MAP 0x102 /* Spin button that is map size */ 00107 #define SPIN_CWINDOW 0x103 /* Spin command window */ 00108 00109 #define FLAG_UPDATE 0x1 00110 #define FLAG_MAPPANE 0x2 /* Display on the map/image pane */ 00111 00112 typedef struct { 00113 GtkWidget *widget; 00114 int type; 00115 int config; 00116 int flags; 00117 const char *label; 00118 } CButtons; 00119 00120 static GtkWidget *gtkwin_config = NULL, /* main window */ 00121 *faceset_combo; /* Combo box for faceset selection */ 00122 00123 00124 /* A dispatch table that can deal with the entire selection of 00125 * config gui elements. 00126 */ 00127 00128 static CButtons cbuttons[MAX_BUTTONS] = { 00129 {NULL, CBUTTON, CONFIG_FOODBEEP, FLAG_UPDATE, 00130 "Beep When Food is Low"}, 00131 {NULL, CBUTTON, CONFIG_TIMESTAMP, FLAG_UPDATE, 00132 "Timestamp Messages"}, 00133 {NULL, SPIN_CWINDOW, CONFIG_CWINDOW, FLAG_UPDATE, 00134 "Command Window"}, 00135 {NULL, CBUTTON, CONFIG_ECHO, FLAG_UPDATE, 00136 "Echo Bound Commands"}, 00137 {NULL, CBUTTON, CONFIG_FASTTCP, 0, 00138 "Fast TCP Send (May improve performance at expense\n of outgoing bandwidth)"}, 00139 {NULL, CBUTTON, CONFIG_GRAD_COLOR, FLAG_UPDATE, 00140 "Gradually change stat bar color based on value of the stat.\nThis option will result in some extra CPU usage."}, 00141 {NULL, CBUTTON, CONFIG_POPUPS, FLAG_UPDATE, 00142 "Popup Windows"}, 00143 {NULL, CBUTTON, CONFIG_SIGNPOPUP, FLAG_UPDATE, 00144 "Popup Sign Windows (need Popup Windows checked to be used)"}, 00145 {NULL, CBUTTON, CONFIG_SPLASH, FLAG_UPDATE, 00146 "Splash Window"}, 00147 {NULL, CBUTTON, CONFIG_SHOWICON, FLAG_UPDATE, 00148 "Show Inventory Icon"}, 00149 {NULL, CBUTTON, CONFIG_TOOLTIPS, 0, 00150 "Show Tooltips"}, 00151 {NULL, CBUTTON, CONFIG_SOUND, 0, 00152 "Sound"}, 00153 {NULL, CBUTTON, CONFIG_SPLITINFO, 0, 00154 "Split Information Window (Takes effect next run)"}, 00155 {NULL, CBUTTON, CONFIG_SPLITWIN, 0, 00156 "Split Windows"}, 00157 {NULL, CBUTTON, CONFIG_TRIMINFO, FLAG_UPDATE, 00158 "Trims text in the information window - " 00159 "improves performance but bugs in\n gtk make the client unstable if this is used." 00160 "This may work better with gtk 2.0"}, 00161 {NULL, CBUTTON, CONFIG_APPLY_CONTAINER, FLAG_UPDATE, 00162 "Automatically re-applies a container when you use apply to close it. \nIf off, when you use apply to close the container, it stays unapplied"}, 00163 00164 {NULL, CBUTTON, CONFIG_RESISTS, 0, 00165 "Display resistances in two columns rather than only one."}, 00166 00167 /* The following items are shown in the map tag. 00168 * I grouped them together to make reading them a bit easier, 00169 * but in fact, they could be intermixed with the other 00170 * options. 00171 */ 00172 00173 {NULL, CBUTTON, CONFIG_CACHE, FLAG_MAPPANE, 00174 "Cache Images"}, 00175 {NULL, CBUTTON, CONFIG_DOWNLOAD, FLAG_MAPPANE | FLAG_UPDATE, 00176 "Download All Image Information (Takes effect on next server connection)"}, 00177 {NULL, CBUTTON, CONFIG_FOGWAR, FLAG_MAPPANE | FLAG_UPDATE, 00178 "Fog of War"}, 00179 {NULL, SPIN_SCALE, CONFIG_ICONSCALE, FLAG_MAPPANE, 00180 "Icon Scale (Takes effect next run)"}, 00181 {NULL, SPIN_SCALE, CONFIG_MAPSCALE, FLAG_MAPPANE, 00182 "Map Scale (Takes effect next run)"}, 00183 {NULL, CBUTTON, CONFIG_SMOOTH, FLAG_MAPPANE | FLAG_UPDATE, 00184 "Enable smoothing - Use additionnal CPU (Take effect on next connection)."}, 00185 {NULL, CBUTTON, CONFIG_DISPLAYMODE, FLAG_MAPPANE, 00186 "SDL Image Support (Take effect next run)"}, 00187 {NULL, CBUTTON, CONFIG_SHOWGRID, FLAG_MAPPANE | FLAG_UPDATE, 00188 "Print Grid Overlay (SDL only, Slow, useful for debugging/development"}, 00189 00190 {NULL, SEPERATOR, 0, FLAG_MAPPANE, 00191 "Lighting options, per pixel is prettier, per tile is faster.\nIf the darkness code is off, the pixel/tile options will be ignored."}, 00192 {NULL, RBUTTON, 100 + CFG_LT_PIXEL_BEST, FLAG_MAPPANE, 00193 "Best Per Pixel Lighting (slowest)"}, 00194 {NULL, RBUTTON, 100 + CFG_LT_PIXEL, FLAG_MAPPANE, 00195 "Fast Per Pixel Lighting"}, 00196 {NULL, RBUTTON, 100 + CFG_LT_TILE, FLAG_MAPPANE, 00197 "Per Tile Lighting"}, 00198 {NULL, CBUTTON, CONFIG_DARKNESS, FLAG_MAPPANE | FLAG_UPDATE, 00199 "Enable darkness code - if off, all spaces will not be dimmed."}, 00200 00201 {NULL, SEPERATOR, 0, FLAG_MAPPANE, 00202 "Map Size: Larger map lets you see more information, but takes more CPU\npower and bandwidth. Changing these will not take effect until the next time\nyou connect to a server"}, 00203 {NULL, SPIN_MAP, CONFIG_MAPHEIGHT, FLAG_MAPPANE, 00204 "Map Height"}, 00205 {NULL, SPIN_MAP, CONFIG_MAPWIDTH, FLAG_MAPPANE, 00206 "Map Width"}, 00207 }; 00208 00209 00210 static void set_config_value(int cval, int value) 00211 { 00212 want_config[cbuttons[cval].config] = value; 00213 if (cbuttons[cval].flags & FLAG_UPDATE) 00214 use_config[cbuttons[cval].config] = value; 00215 } 00216 00217 static int splitwin_toggling = FALSE; 00218 00219 void main_window_destroyed(void) { 00220 if (!splitwin_toggling) { 00221 client_exit(); 00222 } 00223 } 00224 00225 static void toggle_splitwin(int newval) 00226 { 00227 splitwin_toggling = TRUE; 00228 00229 inventory_splitwin_toggling(); 00230 gtk_widget_destroy(gtkwin_root); 00231 00232 if (newval) { 00233 ; /* Currently don't have it, but want splitwindows */ 00234 } else { 00235 /* opposite - do have it, but don't want it */ 00236 gtk_widget_destroy(gtkwin_info); 00237 gtk_widget_destroy(gtkwin_stats); 00238 gtk_widget_destroy(gtkwin_message); 00239 gtk_widget_destroy(gtkwin_inv); 00240 gtk_widget_destroy(gtkwin_look); 00241 } 00242 00243 create_windows(); 00244 display_map_doneupdate(TRUE, FALSE); 00245 draw_stats (1); 00246 update_list_labels(&inv_list); /* After exploding or unexploding client, redraw weight labels. */ 00247 update_list_labels(&look_list); 00248 00249 splitwin_toggling = FALSE; 00250 } 00251 00252 /* Ok, here it sets the config and saves it. This is sorta dangerous, and I'm not sure 00253 * if it's actually possible to do dynamic reconfiguration of everything this way. Something may 00254 * blow up in our faces. 00255 */ 00256 00257 #define IS_DIFFERENT(TYPE) (want_config[TYPE] != use_config[TYPE]) 00258 00259 static void applyconfig(void) { 00260 00261 int onbutton; 00262 int lighting = 0; 00263 00264 free(face_info.want_faceset); 00265 face_info.want_faceset = strdup_local(gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(faceset_combo)->entry))); 00266 for (onbutton =0; onbutton < MAX_BUTTONS; onbutton++) { 00267 if (cbuttons[onbutton].type == CBUTTON) { 00268 set_config_value(onbutton, GTK_TOGGLE_BUTTON (cbuttons[onbutton].widget)->active); 00269 } else if (cbuttons[onbutton].type & SPIN) { 00270 set_config_value(onbutton, gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(cbuttons[onbutton].widget))); 00271 /* 00272 * Nothing special for command window, icon_scale, map_scale, 00273 * map width and height. It should be possible to dynamically 00274 * change the width and height values, but that is for another day. 00275 */ 00276 00277 } else if (cbuttons[onbutton].type == RBUTTON) { 00278 /* We know that the only radio buttons currently in use are those for 00279 * lighting. IF other radio buttons are added later, this should 00280 * be changed. 00281 */ 00282 if ( GTK_TOGGLE_BUTTON (cbuttons[onbutton].widget)->active) { 00283 if ( cbuttons[onbutton].config >= 100 && cbuttons[onbutton].config < 200) 00284 lighting = cbuttons[onbutton].config - 100; 00285 } 00286 } 00287 } /* for onbutton ... loop */ 00288 00289 00290 /* User has toggled splitwindows - adjust accordingly */ 00291 if (IS_DIFFERENT(CONFIG_SPLITWIN)) { 00292 use_config[CONFIG_SPLITWIN] = want_config[CONFIG_SPLITWIN]; 00293 toggle_splitwin(want_config[CONFIG_SPLITWIN]); 00294 } 00295 if (IS_DIFFERENT(CONFIG_SOUND)) { 00296 int tmp; 00297 if (want_config[CONFIG_SOUND]) { 00298 tmp = init_sounds(); 00299 if (csocket.fd) 00300 cs_print_string(csocket.fd, "setup sound %d", tmp >= 0); 00301 } else { 00302 if (csocket.fd) 00303 cs_print_string(csocket.fd, "setup sound 0"); 00304 } 00305 use_config[CONFIG_SOUND] = want_config[CONFIG_SOUND]; 00306 } 00307 if (IS_DIFFERENT(CONFIG_TOOLTIPS)) { 00308 if (want_config[CONFIG_TOOLTIPS]) gtk_tooltips_enable(tooltips); 00309 else gtk_tooltips_disable(tooltips); 00310 use_config[CONFIG_TOOLTIPS] = want_config[CONFIG_TOOLTIPS]; 00311 } 00312 else if (IS_DIFFERENT(CONFIG_FASTTCP)) { 00313 #ifdef TCP_NODELAY 00314 #ifndef WIN32 00315 int q = want_config[CONFIG_FASTTCP]; 00316 00317 if (csocket.fd && setsockopt(csocket.fd, SOL_TCP, TCP_NODELAY, &q, sizeof(q)) == -1) 00318 perror("TCP_NODELAY"); 00319 #else 00320 int q = want_config[CONFIG_FASTTCP]; 00321 00322 if (csocket.fd && setsockopt(csocket.fd, SOL_TCP, TCP_NODELAY, ( const char* )&q, sizeof(q)) == -1) 00323 perror("TCP_NODELAY"); 00324 #endif 00325 #endif 00326 use_config[CONFIG_FASTTCP] = want_config[CONFIG_FASTTCP]; 00327 } 00328 if (IS_DIFFERENT(CONFIG_SHOWICON)) { 00329 itemlist_set_show_icon(&inv_list, want_config[CONFIG_SHOWICON]); 00330 /* TODO What about the look list? And should showicon propogate back here? */ 00331 use_config[CONFIG_SHOWICON] = want_config[CONFIG_SHOWICON]; 00332 } 00333 if (IS_DIFFERENT(CONFIG_RESISTS)) { 00334 use_config[CONFIG_RESISTS] = want_config[CONFIG_RESISTS]; 00335 resize_resistance_table(use_config[CONFIG_RESISTS]); 00336 } 00337 if (!use_config[CONFIG_GRAD_COLOR]) { 00338 reset_stat_bars(); 00339 } 00340 00341 if (lighting) { 00342 if (want_config[CONFIG_LIGHTING] != lighting) { 00343 want_config[CONFIG_LIGHTING] = lighting; 00344 use_config[CONFIG_LIGHTING] = lighting; 00345 } 00346 #ifdef HAVE_SDL 00347 if (use_config[CONFIG_DISPLAYMODE]==CFG_DM_SDL) 00348 /* This is done to make the 'lightmap' in the proper format */ 00349 init_SDL( NULL, 1); 00350 #endif 00351 } 00352 if (want_config[CONFIG_RESISTS] != use_config[CONFIG_RESISTS]) { 00353 resize_resistance_table(want_config[CONFIG_RESISTS]); 00354 use_config[CONFIG_RESISTS] = want_config[CONFIG_RESISTS]; 00355 draw_message_window(1); 00356 } 00357 } 00358 00359 00360 /* Ok, here it sets the config and saves it. This is sorta dangerous, and I'm not sure 00361 * if it's actually possible to do dynamic reconfiguration of everything this way. 00362 */ 00363 00364 static void saveconfig(void) { 00365 00366 /* No idea why applyconfig was basically replicated - just call the 00367 * function instead! 00368 */ 00369 applyconfig(); 00370 save_defaults(); 00371 } 00372 00373 /* 00374 * GUI Config dialog. 00375 * 00376 * 00377 */ 00378 00379 void configdialog(GtkWidget *widget) { 00380 GtkWidget *vbox; 00381 GtkWidget *tablabel; 00382 GtkWidget *notebook; 00383 GtkWidget *vbox1; 00384 GtkWidget *vbox2; 00385 GtkWidget *hbox1; 00386 GtkWidget *applybutton; 00387 GtkWidget *cancelbutton; 00388 GtkWidget *savebutton; 00389 GtkWidget *frame1; 00390 GtkWidget *frame_map, *vbox_map; /* frame and vbox for map notebook */ 00391 GtkWidget *addwidget; /* Used in buildin the tab to point to the widget to add to */ 00392 GtkWidget *ehbox; 00393 GtkWidget *clabel1, *clabel2, *clabel4, *clabel5, *cb1, *cb2, *cb3; 00394 GtkWidget *cclists; 00395 GtkWidget *extras[250]; 00396 GList *flist; 00397 int i, num_extras=0; 00398 00399 gchar *titles[] ={"#","Key","(#)","Mods","Command"}; 00400 00401 /* If the window isnt already up (in which case it's just raised) */ 00402 if(!gtkwin_config) { 00403 int x, y, wx, wy, w, h; 00404 00405 00406 gtkwin_config = gtk_window_new (GTK_WINDOW_DIALOG); 00407 /* Pet peeve - center new window on top of parent, and not on the 00408 * the center of the screen - the later is really annoying in 00409 * xinerama mode. Thankfully, GTK 2.0 adds an option to 00410 * center on parent - for now, just fake it by getting the parents 00411 * geometry. 00412 */ 00413 /*gtk_window_position (GTK_WINDOW (gtkwin_config), GTK_WIN_POS_CENTER);*/ 00414 get_window_coord(gtkwin_root, &x,&y, &wx,&wy,&w,&h); 00415 gtk_widget_set_uposition(gtkwin_config, (wx + w - 450)/2, (wy + h-500) / 2); 00416 gtk_widget_set_usize (gtkwin_config,450,600); 00417 gtk_window_set_title (GTK_WINDOW (gtkwin_config), "Crossfire Configure"); 00418 gtk_window_set_policy (GTK_WINDOW (gtkwin_config), TRUE, TRUE, FALSE); 00419 00420 gtk_signal_connect (GTK_OBJECT (gtkwin_config), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), >kwin_config); 00421 00422 gtk_container_border_width (GTK_CONTAINER (gtkwin_config), 0); 00423 00424 /* vbox splits the window - top portion is the notebook, bottom 00425 * portion is for the tabs for apply/save/config. 00426 */ 00427 vbox = gtk_vbox_new(FALSE, 2); 00428 gtk_container_add (GTK_CONTAINER(gtkwin_config),vbox); 00429 00430 notebook = gtk_notebook_new (); 00431 gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP ); 00432 gtk_box_pack_start (GTK_BOX(vbox),notebook, TRUE, TRUE, 0); 00433 00434 tablabel = gtk_label_new ("General"); 00435 gtk_widget_show (tablabel); 00436 00437 frame1 = gtk_frame_new("General options"); 00438 gtk_frame_set_shadow_type (GTK_FRAME(frame1), GTK_SHADOW_ETCHED_IN); 00439 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame1, tablabel); 00440 00441 vbox1 = gtk_vbox_new(FALSE, 0); 00442 gtk_container_add (GTK_CONTAINER(frame1), vbox1); 00443 00444 tablabel = gtk_label_new ("Map & Image"); 00445 gtk_widget_show (tablabel); 00446 00447 frame_map = gtk_frame_new("Map and Image options"); 00448 gtk_frame_set_shadow_type (GTK_FRAME(frame_map), GTK_SHADOW_ETCHED_IN); 00449 gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame_map, tablabel); 00450 00451 vbox_map = gtk_vbox_new(FALSE, 0); 00452 gtk_container_add (GTK_CONTAINER(frame_map), vbox_map); 00453 00454 for (i=0; i < MAX_BUTTONS; i++) { 00455 if (cbuttons[i].flags & FLAG_MAPPANE) 00456 addwidget = vbox_map; 00457 else 00458 addwidget = vbox1; 00459 00460 if (cbuttons[i].type == CBUTTON) { 00461 cbuttons[i].widget = gtk_check_button_new_with_label(cbuttons[i].label); 00462 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(cbuttons[i].widget), want_config[cbuttons[i].config]); 00463 } 00464 else if (cbuttons[i].type == RBUTTON) { 00465 if ((i>0) && (cbuttons[i-1].type == RBUTTON)) { 00466 cbuttons[i].widget = gtk_radio_button_new_with_label_from_widget( 00467 GTK_RADIO_BUTTON(cbuttons[i-1].widget), cbuttons[i].label); 00468 } else { 00469 cbuttons[i].widget = gtk_radio_button_new_with_label(NULL, cbuttons[i].label); 00470 } 00471 if ((want_config[CONFIG_LIGHTING]+100) == cbuttons[i].config) 00472 gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(cbuttons[i].widget), 1); 00473 } 00474 else if (cbuttons[i].type & SPIN) { 00475 GtkAdjustment *adj=NULL; 00476 00477 if (cbuttons[i].type == SPIN_SCALE) 00478 adj = (GtkAdjustment *) gtk_adjustment_new(want_config[cbuttons[i].config], 25, 200, 1, 5, 5); 00479 else if (cbuttons[i].type == SPIN_MAP) 00480 adj = (GtkAdjustment *) gtk_adjustment_new(want_config[cbuttons[i].config], 9, MAP_MAX_SIZE, 1, 5, 5); 00481 else if (cbuttons[i].type == SPIN_CWINDOW) 00482 adj = (GtkAdjustment *) gtk_adjustment_new(want_config[cbuttons[i].config], 1, 127, 1, 5, 5); 00483 cbuttons[i].widget = gtk_spin_button_new(adj, 1, 0); 00484 extras[num_extras] = gtk_hbox_new(FALSE, 2); 00485 gtk_box_pack_start(GTK_BOX(extras[num_extras]), cbuttons[i].widget, FALSE, FALSE, 0); 00486 extras[++num_extras] = gtk_label_new(cbuttons[i].label); 00487 gtk_box_pack_start(GTK_BOX(extras[num_extras-1]), extras[num_extras], FALSE, FALSE, 0); 00488 gtk_box_pack_start(GTK_BOX(addwidget), extras[num_extras-1], FALSE, FALSE, 0); 00489 num_extras++; 00490 extras[num_extras++] = cbuttons[i].widget; 00491 continue; /* What to skip the box_pack_start below */ 00492 } 00493 else if (cbuttons[i].type == SEPERATOR) { 00494 extras[num_extras] = (GtkWidget*)gtk_hseparator_new (); 00495 gtk_box_pack_start (GTK_BOX (addwidget), extras[num_extras], FALSE, FALSE, 0); 00496 cbuttons[i].widget = gtk_label_new(cbuttons[i].label); 00497 gtk_label_set_justify(GTK_LABEL(cbuttons[i].widget), GTK_JUSTIFY_LEFT); 00498 num_extras++; 00499 } 00500 else { 00501 LOG(LOG_WARNING,"gtk::configdialog","Unknown cbutton type %d", cbuttons[i].type); 00502 } 00503 if (cbuttons[i].widget) { 00504 extras[num_extras++] = cbuttons[i].widget; 00505 gtk_box_pack_start(GTK_BOX(addwidget), cbuttons[i].widget, FALSE, FALSE, 0); 00506 } 00507 } 00508 00509 for (i=0; i < num_extras; i++) { 00510 gtk_widget_show(extras[i]); 00511 } 00512 00513 /* faceset is special because it is string data. */ 00514 faceset_combo = gtk_combo_new(); 00515 flist = NULL; 00516 if (face_info.want_faceset) { 00517 gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(faceset_combo)->entry), face_info.want_faceset); 00518 flist = g_list_append(flist, face_info.want_faceset); 00519 } 00520 00521 /* If we have real faceset info from the server, use it */ 00522 if (face_info.have_faceset_info) { 00523 for (i=0; i<MAX_FACE_SETS; i++) 00524 if (face_info.facesets[i].fullname) 00525 flist = g_list_append(flist, face_info.facesets[i].fullname); 00526 } else { 00527 flist = g_list_append(flist, "standard"); 00528 flist = g_list_append(flist, "classic"); 00529 } 00530 if (flist) gtk_combo_set_popdown_strings(GTK_COMBO(faceset_combo), flist); 00531 addwidget = gtk_hbox_new(FALSE, 0); 00532 gtk_box_pack_start(GTK_BOX(addwidget), faceset_combo, FALSE, FALSE, 0); 00533 tablabel = gtk_label_new("Faceset to use. Only takes effect for new\n face information from server. Not supported on\n all servers."); 00534 gtk_label_set_justify(GTK_LABEL(tablabel), GTK_JUSTIFY_LEFT); 00535 gtk_box_pack_start(GTK_BOX(addwidget), tablabel, FALSE, FALSE, 0); 00536 00537 gtk_box_pack_start(GTK_BOX(vbox_map), addwidget, FALSE, FALSE, 0); 00538 gtk_widget_show(tablabel); 00539 gtk_widget_show(faceset_combo); 00540 gtk_widget_show(addwidget); 00541 00542 gtk_widget_show (vbox1); 00543 gtk_widget_show (frame1); 00544 gtk_widget_show(vbox_map); 00545 gtk_widget_show(frame_map); 00546 00547 00548 /* 00549 * This block deals with drawing the keybindings 00550 * block. 00551 */ 00552 00553 tablabel = gtk_label_new ("Keybindings"); 00554 gtk_widget_show (tablabel); 00555 vbox2 = gtk_vbox_new(FALSE, 0); 00556 gtk_notebook_append_page (GTK_NOTEBOOK (notebook), vbox2, tablabel); 00557 frame1 = gtk_frame_new("Keybindings"); 00558 gtk_frame_set_shadow_type (GTK_FRAME(frame1), GTK_SHADOW_ETCHED_IN); 00559 gtk_box_pack_start (GTK_BOX (vbox2), frame1, TRUE, TRUE, 0); 00560 vbox1 = gtk_vbox_new(FALSE, 0); 00561 gtk_container_add (GTK_CONTAINER(frame1), vbox1); 00562 cclists = gtk_scrolled_window_new (0,0); 00563 cclist = gtk_clist_new_with_titles (5, titles); 00564 00565 gtk_clist_set_column_width (GTK_CLIST(cclist), 0, 20); 00566 gtk_clist_set_column_width (GTK_CLIST(cclist), 1, 50); 00567 gtk_clist_set_column_width (GTK_CLIST(cclist), 2, 20); 00568 gtk_clist_set_column_width (GTK_CLIST(cclist), 3, 40); 00569 gtk_clist_set_column_width (GTK_CLIST(cclist), 4, 245); 00570 gtk_clist_set_selection_mode (GTK_CLIST(cclist) , GTK_SELECTION_SINGLE); 00571 00572 gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW(cclists), 00573 GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC); 00574 gtk_container_add (GTK_CONTAINER (cclists), cclist); 00575 gtk_box_pack_start (GTK_BOX(vbox1),cclists, TRUE, TRUE, 0); 00576 draw_keybindings (cclist); 00577 00578 gtk_signal_connect_after (GTK_OBJECT(cclist), 00579 "select_row", 00580 GTK_SIGNAL_FUNC(cclist_button_event), 00581 NULL); 00582 00583 gtk_widget_show(cclist); 00584 gtk_widget_show(cclists); 00585 00586 ehbox=gtk_hbox_new(FALSE, 0); 00587 00588 00589 clabel1 = gtk_label_new ("Binding #:"); 00590 gtk_box_pack_start (GTK_BOX (ehbox),clabel1, FALSE, TRUE, 2); 00591 gtk_widget_show (clabel1); 00592 00593 cnumentrytext = gtk_label_new ("0"); 00594 gtk_box_pack_start (GTK_BOX (ehbox),cnumentrytext, FALSE, TRUE, 2); 00595 gtk_widget_set_usize (cnumentrytext, 25, 0); 00596 gtk_widget_show (cnumentrytext); 00597 00598 clabel2 = gtk_label_new ("Key:"); 00599 gtk_box_pack_start (GTK_BOX (ehbox),clabel2, FALSE, TRUE, 2); 00600 gtk_widget_show (clabel2); 00601 00602 ckeyentrytext = gtk_entry_new (); 00603 gtk_box_pack_start (GTK_BOX (ehbox),ckeyentrytext, TRUE, TRUE, 2); 00604 gtk_widget_set_usize (ckeyentrytext, 110, 0); 00605 gtk_signal_connect(GTK_OBJECT(ckeyentrytext), "key_press_event", 00606 GTK_SIGNAL_FUNC(ckeyentry_callback), 00607 ckeyentrytext); 00608 gtk_widget_show (ckeyentrytext); 00609 gtk_entry_set_text (GTK_ENTRY(ckeyentrytext), "Press key to bind here"); 00610 00611 clabel4 = gtk_label_new ("Mods:"); 00612 gtk_box_pack_start (GTK_BOX (ehbox),clabel4, FALSE, TRUE, 2); 00613 gtk_widget_show (clabel4); 00614 00615 cmodentrytext = gtk_entry_new (); 00616 gtk_box_pack_start (GTK_BOX (ehbox),cmodentrytext, FALSE, TRUE, 2); 00617 gtk_widget_set_usize (cmodentrytext, 45, 0); 00618 gtk_widget_show (cmodentrytext); 00619 00620 gtk_box_pack_start (GTK_BOX (vbox1),ehbox, FALSE, TRUE, 2); 00621 00622 gtk_widget_show (ehbox); 00623 00624 ehbox=gtk_hbox_new(FALSE, 0); 00625 00626 clabel5 = gtk_label_new ("Command:"); 00627 gtk_box_pack_start (GTK_BOX (ehbox),clabel5, FALSE, TRUE, 2); 00628 gtk_widget_show (clabel5); 00629 00630 ckentrytext = gtk_entry_new (); 00631 gtk_box_pack_start (GTK_BOX (ehbox),ckentrytext, TRUE, TRUE, 2); 00632 gtk_widget_show (ckentrytext); 00633 00634 gtk_box_pack_start (GTK_BOX (vbox1),ehbox, FALSE, TRUE, 2); 00635 00636 gtk_widget_show (ehbox); 00637 00638 ehbox=gtk_hbox_new(TRUE, 0); 00639 00640 00641 cb1 = gtk_button_new_with_label ("Unbind"); 00642 gtk_box_pack_start (GTK_BOX (ehbox),cb1, FALSE, TRUE, 4); 00643 /*gtk_widget_set_usize (cb1, 45, 0);*/ 00644 gtk_signal_connect_object (GTK_OBJECT (cb1), "clicked", 00645 GTK_SIGNAL_FUNC(ckeyunbind), 00646 NULL); 00647 gtk_widget_show (cb1); 00648 00649 cb2 = gtk_button_new_with_label ("Bind"); 00650 gtk_box_pack_start (GTK_BOX (ehbox),cb2, FALSE, TRUE, 4); 00651 gtk_signal_connect_object (GTK_OBJECT (cb2), "clicked", 00652 GTK_SIGNAL_FUNC(bind_callback), 00653 NULL); 00654 /* gtk_widget_set_usize (cb2, 45, 0);*/ 00655 gtk_widget_show (cb2); 00656 00657 cb3 = gtk_button_new_with_label ("Clear"); 00658 gtk_box_pack_start (GTK_BOX (ehbox),cb3, FALSE, TRUE, 4); 00659 /* gtk_widget_set_usize (cb2, 45, 0);*/ 00660 gtk_signal_connect_object (GTK_OBJECT (cb3), "clicked", 00661 GTK_SIGNAL_FUNC(ckeyclear), 00662 NULL); 00663 gtk_widget_show (cb3); 00664 gtk_box_pack_start (GTK_BOX (vbox1),ehbox, FALSE, TRUE, 2); 00665 00666 gtk_widget_show (ehbox); 00667 00668 gtk_widget_show (vbox1); 00669 gtk_widget_show (frame1); 00670 gtk_widget_show (vbox2); 00671 00672 gtk_widget_show (notebook); 00673 00674 /* And give some options to actually do something with our new nifty configuration */ 00675 00676 hbox1 = gtk_hbox_new(TRUE, 0); 00677 gtk_box_pack_start(GTK_BOX(vbox), hbox1, FALSE, FALSE, 6); 00678 savebutton = gtk_button_new_with_label("Save"); 00679 gtk_signal_connect_object (GTK_OBJECT (savebutton), "clicked", 00680 GTK_SIGNAL_FUNC(saveconfig), 00681 NULL); 00682 gtk_box_pack_start(GTK_BOX(hbox1), savebutton, FALSE, TRUE, 4); 00683 00684 applybutton = gtk_button_new_with_label("Apply"); 00685 gtk_signal_connect_object (GTK_OBJECT (applybutton), "clicked", 00686 GTK_SIGNAL_FUNC(applyconfig), 00687 NULL); 00688 gtk_box_pack_start(GTK_BOX(hbox1), applybutton, FALSE, TRUE, 4); 00689 00690 cancelbutton = gtk_button_new_with_label("Close"); 00691 gtk_signal_connect_object (GTK_OBJECT (cancelbutton), "clicked", 00692 GTK_SIGNAL_FUNC(gtk_widget_destroy), 00693 GTK_OBJECT (gtkwin_config)); 00694 00695 gtk_box_pack_start(GTK_BOX(hbox1), cancelbutton, FALSE, TRUE, 4); 00696 gtk_widget_show(savebutton); 00697 gtk_widget_show(applybutton); 00698 gtk_widget_show(cancelbutton); 00699 00700 gtk_widget_show (hbox1); 00701 gtk_widget_show (vbox); 00702 gtk_widget_show (gtkwin_config); 00703 } 00704 else { 00705 gdk_window_raise (gtkwin_config->window); 00706 } 00707 } 00708 00709 00710 void load_defaults(void) 00711 { 00712 char path[MAX_BUF],inbuf[MAX_BUF],*cp; 00713 FILE *fp; 00714 int i, val; 00715 00716 /* Copy over the want values to use values now */ 00717 for (i=0; i<CONFIG_NUMS; i++) { 00718 use_config[i] = want_config[i]; 00719 } 00720 00721 sprintf(path,"%s/.crossfire/gdefaults", getenv("HOME")); 00722 if ((fp=fopen(path,"r"))==NULL) return; 00723 while (fgets(inbuf, MAX_BUF-1, fp)) { 00724 inbuf[MAX_BUF-1]='\0'; 00725 inbuf[strlen(inbuf)-1]='\0'; /* kill newline */ 00726 00727 if (inbuf[0]=='#') continue; 00728 /* IF no colon, then we certainly don't have a real value, so just skip */ 00729 if (!(cp=strchr(inbuf,':'))) continue; 00730 *cp='\0'; 00731 cp+=2; /* colon, space, then value */ 00732 00733 val = -1; 00734 if (isdigit(*cp)) val=atoi(cp); 00735 else if (!strcmp(cp,"True")) val = TRUE; 00736 else if (!strcmp(cp,"False")) val = FALSE; 00737 00738 for (i=1; i<CONFIG_NUMS; i++) { 00739 if (!strcmp(config_names[i], inbuf)) { 00740 if (val == -1) { 00741 LOG(LOG_WARNING,"gtk::load_defaults","Invalid value/line: %s: %s", inbuf, cp); 00742 } else { 00743 want_config[i] = val; 00744 } 00745 break; /* Found a match - won't find another */ 00746 } 00747 } 00748 /* We found a match in the loop above, so no need to do anything more */ 00749 if (i < CONFIG_NUMS) continue; 00750 00751 /* Legacy - now use the map_width and map_height values 00752 * Don't do sanity checking - that will be done below 00753 */ 00754 if (!strcmp(inbuf,"mapsize")) { 00755 if (sscanf(cp,"%hdx%hd", &want_config[CONFIG_MAPWIDTH], &want_config[CONFIG_MAPHEIGHT])!=2) { 00756 LOG(LOG_WARNING,"gtk::load_defaults","Malformed mapsize option in gdefaults. Ignoring"); 00757 } 00758 } 00759 else if (!strcmp(inbuf, "server")) { 00760 server = strdup_local(cp); /* memory leak ! */ 00761 continue; 00762 } 00763 else if (!strcmp(inbuf, "sound_server")) { 00764 sound_server = strdup_local(cp); /* memory leak ! */ 00765 continue; 00766 } 00767 else if (!strcmp(inbuf, "nopopups")) { 00768 /* Changed name from nopopups to popups, so inverse value */ 00769 want_config[CONFIG_POPUPS] = !val; 00770 continue; 00771 } 00772 else if (!strcmp(inbuf, "nosplash")) { 00773 want_config[CONFIG_SPLASH] = !val; 00774 continue; 00775 } 00776 else if (!strcmp(inbuf, "splash")) { 00777 want_config[CONFIG_SPLASH] = val; 00778 continue; 00779 } 00780 else if (!strcmp(inbuf, "faceset")) { 00781 face_info.want_faceset = strdup_local(cp); /* memory leak ! */ 00782 continue; 00783 } 00784 /* legacy support for the old resistances values, we need to adjust the values to the new form */ 00785 else if (!strcmp(inbuf, "resists")) { 00786 if (val) want_config[CONFIG_RESISTS] = val-1; 00787 } 00788 else if (!strcmp(inbuf, "sdl")) { 00789 if (val) want_config[CONFIG_DISPLAYMODE] = CFG_DM_SDL; 00790 } 00791 00792 00793 else LOG(LOG_WARNING,"gtk::load_defaults","Unknown line in gdefaults: %s %s", inbuf, cp); 00794 } 00795 fclose(fp); 00796 /* Make sure some of the values entered are sane - since a user can 00797 * edit the defaults file directly, they could put bogus values 00798 * in 00799 */ 00800 if (want_config[CONFIG_ICONSCALE]< 25 || want_config[CONFIG_ICONSCALE]>200) { 00801 LOG(LOG_WARNING,"gtk::load_defaults","Ignoring iconscale value read for gdefaults file.\n" 00802 "Invalid iconscale range (%d), valid range for -iconscale is 25 through 200", 00803 want_config[CONFIG_ICONSCALE]); 00804 want_config[CONFIG_ICONSCALE] = use_config[CONFIG_ICONSCALE]; 00805 } 00806 if (want_config[CONFIG_MAPSCALE]< 25 || want_config[CONFIG_MAPSCALE]>200) { 00807 LOG(LOG_WARNING,"gtk::load_defaults","ignoring mapscale value read for gdefaults file.\n" 00808 "Invalid mapscale range (%d), valid range for -iconscale is 25 through 200", 00809 want_config[CONFIG_MAPSCALE]); 00810 want_config[CONFIG_MAPSCALE] = use_config[CONFIG_MAPSCALE]; 00811 } 00812 if (!want_config[CONFIG_LIGHTING]) { 00813 LOG(LOG_WARNING,"gtk::load_defaults","No lighting mechanism selected - will not use darkness code"); 00814 want_config[CONFIG_DARKNESS] = FALSE; 00815 } 00816 00817 /* Make sure the map size os OK */ 00818 if (want_config[CONFIG_MAPWIDTH] < 9 || want_config[CONFIG_MAPWIDTH] > MAP_MAX_SIZE) { 00819 LOG(LOG_WARNING,"gtk::load_defaults", 00820 "Invalid map width (%d) option in gdefaults. Valid range is 9 to %d", 00821 want_config[CONFIG_MAPWIDTH], MAP_MAX_SIZE); 00822 want_config[CONFIG_MAPWIDTH] = use_config[CONFIG_MAPWIDTH]; 00823 } 00824 if (want_config[CONFIG_MAPHEIGHT] < 9 || want_config[CONFIG_MAPHEIGHT] > MAP_MAX_SIZE) { 00825 LOG(LOG_WARNING,"gtk::load_defaults", 00826 "Invalid map height (%d) option in gdefaults. Valid range is 9 to %d", 00827 want_config[CONFIG_MAPHEIGHT], MAP_MAX_SIZE); 00828 want_config[CONFIG_MAPHEIGHT] = use_config[CONFIG_MAPHEIGHT]; 00829 } 00830 00831 #ifndef HAVE_SDL 00832 /* If SDL is not built in, having SDL mode turned on causes many issues. */ 00833 want_config[CONFIG_DISPLAYMODE] = CFG_DM_PIXMAP; 00834 #endif 00835 00836 /* Now copy over the values just loaded */ 00837 for (i=0; i<CONFIG_NUMS; i++) { 00838 use_config[i] = want_config[i]; 00839 } 00840 00841 image_size = DEFAULT_IMAGE_SIZE * use_config[CONFIG_ICONSCALE] / 100; 00842 map_image_size = DEFAULT_IMAGE_SIZE * use_config[CONFIG_MAPSCALE] / 100; 00843 map_image_half_size = DEFAULT_IMAGE_SIZE * use_config[CONFIG_MAPSCALE] / 200; 00844 itemlist_set_show_icon(&inv_list, use_config[CONFIG_SHOWICON]); 00845 00846 } 00847 00848 void save_defaults(void) 00849 { 00850 char path[MAX_BUF],buf[MAX_BUF]; 00851 FILE *fp; 00852 int i; 00853 00854 sprintf(path,"%s/.crossfire/gdefaults", getenv("HOME")); 00855 if (make_path_to_file(path)==-1) { 00856 LOG(LOG_ERROR,"gtk::save_defaults","Could not create %s", path); 00857 return; 00858 } 00859 if ((fp=fopen(path,"w"))==NULL) { 00860 LOG(LOG_ERROR,"gtk::save_defaults","Could not open %s", path); 00861 return; 00862 } 00863 fprintf(fp,"# This file is generated automatically by crossfire-client-gtk.\n"); 00864 fprintf(fp,"# Manual editing is allowed, but the client may be finicky about\n"); 00865 fprintf(fp,"# some of the matching it does. All comparisons are case sensitive.\n"); 00866 fprintf(fp,"# 'True' and 'False' are the proper cases for those two values\n"); 00867 fprintf(fp,"# 'True' and 'False' have been replaced with 1 and 0 respectively\n"); 00868 fprintf(fp,"server: %s\n", server); 00869 fprintf(fp,"sound_server: %s\n", sound_server); 00870 fprintf(fp,"faceset: %s\n", face_info.want_faceset); 00871 00872 /* This isn't quite as good as before, as instead of saving things as 'True' 00873 * or 'False', it is just 1 or 0. However, for the most part, the user isn't 00874 * going to be editing the file directly. 00875 */ 00876 for (i=1; i < CONFIG_NUMS; i++) { 00877 fprintf(fp,"%s: %d\n", config_names[i], want_config[i]); 00878 } 00879 00880 fclose(fp); 00881 sprintf(buf,"Defaults saved to %s",path); 00882 draw_info(buf,NDI_BLUE); 00883 }