Crossfire Client, Branch  R11627
gx11.c
Go to the documentation of this file.
00001 const char * const rcsid_gtk_gx11_c =
00002     "$Id: gx11.c 9581 2008-07-20 00:54:34Z kbulgrien $";
00003 /*
00004     Crossfire client, a client program for the crossfire program.
00005 
00006     Copyright (C) 2001-2003,2006-2007 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 /*
00026  * This file contains the core window code.
00027  */
00028 
00029 /* Most functions in this file are private.  Here is a list of
00030  * the global functions:
00031  *
00032  * draw_color_info(int color, char*buf) - draws text in specified color
00033  * draw_info - draw info in the info window
00034  * end_windows - used when exiting
00035  * init_windows - called when starting up
00036  * load_images - creates the bitmaps and pixmaps (if being used)
00037  * create_pixmap - creates a pixmap from given file and assigns to
00038  *              the given face
00039  * create_xpm - as create_pixmap, but does an XPM image
00040  * load_additional_images - loads images that have been downloaded
00041  *      from the server in prior sessions
00042  *
00043  * draw_stats(int) - draws the stat window.  Pass 1 to redraw all
00044  *      stats, not only those that changed
00045  *
00046  * draw_message_window(int) - draws the message window.  Pass 1 to redraw
00047  *      all the bars, not only those that changed.
00048  *
00049  * NOTE: create_pixmap and create_xpm can be empty functions if the
00050  * client will always use fonts - in that case, it should never
00051  * request Bitmap or Pixmap data, and thus not need the create
00052  * functions above
00053  *
00054  * Only functions in this file should be calling functions like
00055  * draw_stats and draw_message_window with redraw set - functions
00056  * in other files should always pass 0, because they will never have
00057  * the information of whether a redraw is needed.
00058  */
00059 
00060 
00061 #include <config.h>
00062 
00063 #include <errno.h>
00064 
00065 /* gtk */
00066 #include <gtk/gtk.h>
00067 #ifndef WIN32
00068 #include <gdk/gdkx.h>
00069 #else
00070 #include <gdk/gdkwin32.h>
00071 #endif
00072 #include <gdk/gdkkeysyms.h>
00073 
00074 #ifdef HAVE_SDL
00075 #include <SDL.h>
00076 #include <SDL_image.h>
00077 #endif
00078 
00079 /* Always include our local headers after the system headers are included */
00080 #include "client.h"
00081 /*#include "clientbmap.h"*/
00082 #include "item.h"
00083 #include "pixmaps/crossfiretitle.xpm"
00084 #include "gx11.h"
00085 #include "gtkproto.h"
00086 #include <script.h>
00087 #include <p_cmd.h>
00088 #include <time.h>
00089 
00090 #include "mapdata.h"
00091 
00092 
00093 #ifdef HAVE_SDL
00094 /* These are only used in SDL mode at current time */
00095 extern SDL_Surface* mapsurface;
00096 #endif
00097 
00098 static const char *const colorname[] = {
00099 "Black",                /* 0  */
00100 "White",                /* 1  */
00101 "Navy",                 /* 2  */
00102 "Red",                  /* 3  */
00103 "Orange",               /* 4  */
00104 "DodgerBlue",           /* 5  */
00105 "DarkOrange2",          /* 6  */
00106 "SeaGreen",             /* 7  */
00107 "DarkSeaGreen",         /* 8  */        /* Used for window background color */
00108 "Grey50",               /* 9  */
00109 "Sienna",               /* 10 */
00110 "Gold",                 /* 11 */
00111 "Khaki"                 /* 12 */
00112 };
00113 
00114 #define DEFAULT_IMAGE_SIZE      32
00115 
00116 int image_size=DEFAULT_IMAGE_SIZE;
00117 int map_image_size=DEFAULT_IMAGE_SIZE, map_image_half_size=DEFAULT_IMAGE_SIZE/2;
00118 PixmapInfo *pixmaps[MAXPIXMAPNUM];
00119 
00120 
00121   /* Copy from server: include/define.h */
00122 #define PU_NOTHING              0x00000000
00123 
00124 #define PU_DEBUG                0x10000000
00125 #define PU_INHIBIT              0x20000000
00126 #define PU_STOP                 0x40000000
00127 #define PU_NEWMODE              0x80000000
00128 
00129 #define PU_RATIO                0x0000000F
00130 
00131 #define PU_FOOD                 0x00000010
00132 #define PU_DRINK                0x00000020
00133 #define PU_VALUABLES            0x00000040
00134 #define PU_BOW                  0x00000080
00135 
00136 #define PU_ARROW                0x00000100
00137 #define PU_HELMET               0x00000200
00138 #define PU_SHIELD               0x00000400
00139 #define PU_ARMOUR               0x00000800
00140 
00141 #define PU_BOOTS                0x00001000
00142 #define PU_GLOVES               0x00002000
00143 #define PU_CLOAK                0x00004000
00144 #define PU_KEY                  0x00008000
00145 
00146 #define PU_MISSILEWEAPON        0x00010000
00147 #define PU_ALLWEAPON            0x00020000
00148 #define PU_MAGICAL              0x00040000
00149 #define PU_POTION               0x00080000
00150 
00151 #define PU_SPELLBOOK            0x00100000
00152 #define PU_SKILLSCROLL          0x00200000
00153 #define PU_READABLES            0x00400000
00154 #define PU_MAGIC_DEVICE         0x00800000
00155 
00156 #define PU_NOT_CURSED           0x01000000
00157 #define PU_JEWELS               0x02000000
00158 #define PU_FLESH                0x04000000
00159 
00160 
00161 
00162 typedef struct {
00163   GtkWidget *playername;
00164   GtkWidget *score;
00165   GtkWidget *level;
00166   GtkWidget *hp;
00167   GtkWidget *sp;
00168   GtkWidget *gr;
00169   GtkWidget *Str;
00170   GtkWidget *Dex;
00171   GtkWidget *Con;
00172   GtkWidget *Int;
00173   GtkWidget *Wis;
00174   GtkWidget *Cha;
00175   GtkWidget *Pow;
00176   GtkWidget *wc;
00177   GtkWidget *dam;
00178   GtkWidget *ac;
00179   GtkWidget *armor;
00180   GtkWidget *speed;
00181   GtkWidget *food;
00182   GtkWidget *skill;
00183   GtkWidget *skill_exp[MAX_SKILL*2];
00184 } StatWindow;
00185 
00186 static char **gargv;
00187 
00188 #define MAX_HISTORY 50
00189 #define MAX_COMMAND_LEN 256
00190 static char history[MAX_HISTORY][MAX_COMMAND_LEN];
00191 static int cur_history_position=0, scroll_history_position=0;
00192 
00193 extern int maxfd;
00194 struct timeval timeout;
00195 static gint csocket_fd = 0;
00196 
00197 static int gargc;
00198 
00199 static uint8
00200     bigmap=FALSE;       /* True if we've moved some windows around for big maps */
00201 
00202 uint8
00203     time_map_redraw=FALSE,
00204     updatekeycodes=FALSE,
00205     redraw_needed=FALSE;
00206 
00207 
00208 /* Default size of scroll buffers is 100 K */
00209 static int info1_num_chars=0, info2_num_chars=0, info1_max_chars=100000,
00210     info2_max_chars=100000;
00211 
00212 
00213 typedef struct {
00214   int x;
00215   int y;
00216 } MapPos;
00217 
00218 
00219 /* vitals window */
00220 
00221 typedef struct {
00222   GtkWidget *bar;
00223   GtkStyle *style[2];
00224   int state;
00225 } Vitals;
00226 
00227 static Vitals vitals[4];
00228 GtkWidget *run_label, *fire_label;
00229 static GtkWidget *restable;     /* resistance table */
00230 static GtkWidget *res_scrolled_window;  /* window the resistances are in */
00231 static GtkWidget *skill_scrolled_window; /* window the skills are in */
00232 
00233 
00234 static GtkWidget *resists[NUM_RESISTS];
00235 GtkWidget *ckentrytext, *ckeyentrytext, *cmodentrytext, *cnumentrytext;
00236 
00237 GdkColor gdk_green =    { 0, 0, 0xcfff, 0 };
00238 GdkColor gdk_red =    { 0, 0xcfff, 0, 0 };
00239 GdkColor gdk_grey = { 0, 0xea60, 0xea60, 0xea60 };
00240 GdkColor gdk_black = { 0, 0, 0, 0 };
00241 
00242 static GdkColor map_color[16];
00243 /* Not static so it can be used in inventory.c for highlighting. */
00244 GdkColor root_color[16];
00245 static GdkPixmap *magicgdkpixmap;
00246 static GdkGC *magic_map_gc;
00247 static GtkWidget *mapvbox;
00248 GdkPixmap   *mapwindow;
00249 GdkBitmap *dark1, *dark2, *dark3;
00250 GdkPixmap *dark;
00251 
00252 GtkTooltips *tooltips;
00253 
00254 static GtkWidget *dialogtext;
00255 static GtkWidget *dialog_window;
00256 GtkWidget *drawingarea;
00257 
00258 GdkGC *mapgc;
00259 
00260 GtkWidget *cclist;
00261 static gboolean draw_info_freeze1=FALSE, draw_info_freeze2=FALSE;
00262 
00263 enum {
00264     locked_icon = 1, applied_icon, unpaid_icon,
00265     damned_icon, cursed_icon, magic_icon, close_icon,
00266     stipple1_icon, stipple2_icon, max_icons
00267 };
00268 
00269 
00270 GtkWidget *entrytext; /* "Command-line" frame, built in get_info_display(). */
00271 static GtkObject *text_hadj,*text_vadj;
00272 static GtkObject *text_hadj2,*text_vadj2;
00273 static GtkWidget *gameframe, *stat_frame, *message_frame;
00274 
00275 static StatWindow statwindow;
00276 /* gtk */
00277 
00278 GtkWidget *gtkwin_root, *gtkwin_info;
00279 GtkWidget *gtkwin_info_text; /* Referenced by inventory::count_callback. */
00280 GtkWidget *gtkwin_info_text2; /* Used when CONFIG_SPLITINFO */
00281 GtkWidget *gtkwin_stats, *gtkwin_message, *gtkwin_look, *gtkwin_inv;
00282 
00283 
00284 static GtkWidget *gtkwin_about = NULL;
00285 static GtkWidget *gtkwin_bug = NULL;
00286 static GtkWidget *gtkwin_splash = NULL;
00287 static GtkWidget *gtkwin_shelp = NULL;
00288 static GtkWidget *gtkwin_magicmap = NULL;
00289 
00290 static GtkWidget *bugtrack = NULL;
00291 
00292 /* These are the panes used in splitting up the window in non root
00293  * windows mode.  Need to be globals so we can get/set the
00294  * information when loading/saving the positions.
00295  */
00296 
00297 static GtkWidget
00298     *inv_hpane,         /* Split between inv,message window and stats/game/.. window */
00299     *stat_info_hpane,   /* Game/stats on left, info windows on right */
00300     *stat_game_vpane,   /* Status window/game window split */
00301     *game_bar_vpane,    /* Game/scroll split */
00302     *inv_look_vpane,    /* Inventory/look split */
00303     *info_vpane;        /* Split for 2 info windows */
00304 
00305 static char *last_str;
00306 
00308 static unsigned int pickup_mode = 0;
00309 
00310 int updatelock = 0;
00311 
00312 /* This is used for caching the images across runs.  When we get a face
00313  * command from the server, we check the facecache for that name.  If
00314  * so, we can then use the num to find out what face number it is on the
00315  * local side.
00316  */
00317 struct FaceCache {
00318     char    *name;
00319     uint16  num;
00320 } facecache[MAXPIXMAPNUM];
00321 
00322 int misses=0,total=0;
00323 
00324 void disconnect(GtkWidget *widget);
00325 
00326 /* Called from disconnect command - that closes the socket -
00327  * we just need to do the gtk cleanup.
00328  */
00329 void cleanup_connection(void) {
00330     if (csocket_fd) {
00331         gdk_input_remove(csocket_fd);
00332         csocket_fd=0;
00333         gtk_main_quit();
00334     }
00335     cleanup_textmanagers();
00336 }
00337 
00338 /* Main loop iteration related stuff */
00339 static void do_network(void) {
00340     fd_set tmp_read;
00341     int pollret;
00342     extern int updatelock;
00343 
00344     if (csocket.fd==-1) {
00345         if (csocket_fd) {
00346             gdk_input_remove(csocket_fd);
00347             csocket_fd=0;
00348             gtk_main_quit();
00349         }
00350         return;
00351     }
00352 
00353     if (updatelock < 20) {
00354         FD_ZERO(&tmp_read);
00355         FD_SET(csocket.fd, &tmp_read);
00356         script_fdset(&maxfd,&tmp_read);
00357         pollret = select(maxfd, &tmp_read, NULL, NULL, &timeout);
00358         if (pollret==-1) {
00359             LOG(LOG_WARNING,"gtk::do_network", "Got errno %d on select call.", errno);
00360         }
00361         else if ( pollret>0 ) {
00362             if (FD_ISSET(csocket.fd, &tmp_read)) {
00363                 DoClient(&csocket);
00364 #ifndef WIN32
00365                 if ( pollret > 1 ) script_process(&tmp_read);
00366 #endif
00367             }
00368             else {
00369                 script_process(&tmp_read);
00370             }
00371         }
00372     } else {
00373         LOG(LOG_INFO,"gtk::do_network","locked for network recieves.\n");
00374     }
00375     if (csocket.fd==-1) {
00376         if (csocket_fd) {
00377             gdk_input_remove(csocket_fd);
00378             csocket_fd=0;
00379             gtk_main_quit();
00380         }
00381         return;
00382     }
00383 
00384 }
00385 
00386 #ifdef WIN32 /* Win32 scripting support */
00387 int do_scriptout(void)
00388 {
00389   script_process(NULL);
00390   return(TRUE);
00391 }
00392 #endif /* WIN32 */
00393 
00394 static void event_loop(void)
00395 {
00396     gint fleep;
00397     extern int do_timeout(void); /* forward */
00398     int tag;
00399 
00400     if (MAX_TIME==0) {
00401         timeout.tv_sec = 0;
00402         timeout.tv_usec = 0;
00403     }
00404     maxfd = csocket.fd + 1;
00405 
00406     if (MAX_TIME!=0) {
00407         timeout.tv_sec = 0;/* MAX_TIME / 1000000;*/
00408         timeout.tv_usec = 0;/* MAX_TIME % 1000000;*/
00409     }
00410 
00411     fleep =  gtk_timeout_add (100,
00412                           (GtkFunction) do_timeout,
00413                           NULL);
00414 
00415 #ifdef WIN32
00416         gtk_timeout_add (25, (GtkFunction) do_scriptout, NULL);
00417 #endif
00418 
00419     csocket_fd = gdk_input_add ((gint) csocket.fd,
00420                               GDK_INPUT_READ,
00421                               (GdkInputFunction) do_network, &csocket);
00422     tag = csocket_fd;
00423 
00424     gtk_main();
00425     gtk_timeout_remove(tag);
00426 
00427     cleanup_textmanagers();
00428     LOG(LOG_INFO,"gtk::event_loop","gtk_main exited, returning from event_loop");
00429 }
00430 
00431 
00432 
00433 
00434 /* Handle mouse presses in the game window */
00435 
00436 static void button_map_event(GtkWidget *widget, GdkEventButton *event) {
00437     int dx, dy, i, x, y, xmidl, xmidh, ymidl, ymidh;
00438 
00439     x=(int)event->x;
00440     y=(int)event->y;
00441     dx=(x-2)/map_image_size-(use_config[CONFIG_MAPWIDTH]/2);
00442     dy=(y-2)/map_image_size-(use_config[CONFIG_MAPHEIGHT]/2);
00443     xmidl=(use_config[CONFIG_MAPWIDTH]/2) * map_image_size;
00444     xmidh=(use_config[CONFIG_MAPWIDTH]/2 + 1) * map_image_size;
00445     ymidl=(use_config[CONFIG_MAPHEIGHT]/2) * map_image_size;
00446     ymidh=(use_config[CONFIG_MAPHEIGHT]/2 + 1) * map_image_size;
00447 
00448     switch (event->button) {
00449         case 1:
00450             look_at(dx,dy);
00451             break;
00452 
00453         case 2:
00454         case 3:
00455             if (x<xmidl)
00456                 i = 0;
00457             else if (x>xmidh)
00458                 i = 6;
00459             else i =3;
00460 
00461             if (y>ymidh)
00462                 i += 2;
00463             else if (y>ymidl)
00464                 i++;
00465 
00466             if (event->button==2) {
00467                 switch (i) {
00468                     case 0: fire_dir (8);break;
00469                     case 1: fire_dir (7);break;
00470                     case 2: fire_dir (6);break;
00471                     case 3: fire_dir (1);break;
00472                     case 5: fire_dir (5);break;
00473                     case 6: fire_dir (2);break;
00474                     case 7: fire_dir (3);break;
00475                     case 8: fire_dir (4);break;
00476                 }
00477                 /* Only want to fire once */
00478                 clear_fire();
00479             }
00480             else switch (i) {
00481                 case 0: move_player (8);break;
00482                 case 1: move_player (7);break;
00483                 case 2: move_player (6);break;
00484                 case 3: move_player (1);break;
00485                 case 5: move_player (5);break;
00486                 case 6: move_player (2);break;
00487                 case 7: move_player (3);break;
00488                 case 8: move_player (4);break;
00489             }
00490     }
00491 }
00492 
00493 
00494 
00495 
00496 
00497 /******************************************************************************
00498  *
00499  * Code related to face caching.
00500  *
00501  *****************************************************************************/
00502 
00503 /* Initializes the data for image caching */
00504 static void init_cache_data(void)
00505 {
00506     int i;
00507     GtkStyle *style;
00508 #include "pixmaps/question.xpm"
00509 
00510 
00511     LOG(LOG_INFO,"gtk::init_cache_data","Init Cache");
00512 
00513     style = gtk_widget_get_style(gtkwin_root);
00514     pixmaps[0] = malloc(sizeof(PixmapInfo));
00515     pixmaps[0]->icon_image = gdk_pixmap_create_from_xpm_d(gtkwin_root->window,
00516                                                         (GdkBitmap**)&pixmaps[0]->icon_mask,
00517                                                         &style->bg[GTK_STATE_NORMAL],
00518                                                         (gchar **)question_xpm);
00519 #ifdef HAVE_SDL
00520     if (use_config[CONFIG_DISPLAYMODE]==CFG_DM_SDL) {
00521         /* Make a semi transparent question mark symbol to
00522          * use for the cached images.
00523          */
00524 #include "pixmaps/question.sdl"
00525         pixmaps[0]->map_image = SDL_CreateRGBSurfaceFrom(question_sdl,
00526                 32, 32, 1, 4, 1, 1, 1, 1);
00527         SDL_SetAlpha(pixmaps[0]->map_image, SDL_SRCALPHA, 70);
00528         pixmaps[0]->fog_image = SDL_CreateRGBSurfaceFrom(question_sdl,
00529                 32, 32, 1, 4, 1, 1, 1, 1);
00530         SDL_SetAlpha(pixmaps[0]->fog_image, SDL_SRCALPHA, 70);
00531     }
00532     else
00533 #endif
00534     {
00535         pixmaps[0]->map_image =  pixmaps[0]->icon_image;
00536         pixmaps[0]->fog_image =  pixmaps[0]->icon_image;
00537         pixmaps[0]->map_mask =  pixmaps[0]->icon_mask;
00538     }
00539     pixmaps[0]->icon_width = pixmaps[0]->icon_height = pixmaps[0]->map_width = pixmaps[0]->map_height = map_image_size;
00540     pixmaps[0]->smooth_face = 0;
00541 
00542     /* Don't do anything special for SDL image - rather, that drawing
00543      * code will check to see if there is no data
00544      */
00545 
00546     /* Initialize all the images to be of the same value. */
00547     for (i=1; i<MAXPIXMAPNUM; i++)  {
00548         pixmaps[i] = pixmaps[0];
00549     }
00550 
00551     init_common_cache_data();
00552 }
00553 
00554 /* Deals with command history.  If direction is 0, we are going backwards,
00555  * if 1, we are moving forward.
00556  */
00557 
00558 void gtk_command_history(int direction)
00559 {
00560     int i=scroll_history_position;
00561     if (direction) {
00562         i--;
00563         if (i<0) i+=MAX_HISTORY;
00564         if (i == cur_history_position) return;
00565     } else {
00566         i++;
00567         if (i>=MAX_HISTORY) i = 0;
00568         if (i == cur_history_position) {
00569             /* User has forwarded to what should be current entry - reset it now. */
00570             gtk_entry_set_text(GTK_ENTRY(entrytext), "");
00571             gtk_entry_set_position(GTK_ENTRY(entrytext), 0);
00572             scroll_history_position=cur_history_position;
00573             return;
00574         }
00575     }
00576 
00577     if (history[i][0] == 0) return;
00578 
00579     scroll_history_position=i;
00580 /*    fprintf(stderr,"resetting postion to %d, data = %s\n", i, history[i]);*/
00581     gtk_entry_set_text(GTK_ENTRY(entrytext), history[i]);
00582     gtk_entry_set_position(GTK_ENTRY(entrytext), strlen(history[i]));
00583     gtk_widget_grab_focus (GTK_WIDGET(entrytext));
00584     cpl.input_state = Command_Mode;
00585 }
00586 
00587 void gtk_complete_command(void)
00588 {
00589     const gchar *entry_text, *newcommand;
00590 
00591     entry_text = gtk_entry_get_text(GTK_ENTRY(entrytext));
00592     newcommand = complete_command(entry_text);
00593     /* Value differ, so update window */
00594     if (newcommand != NULL) {
00595         /* Set position to last character */
00596         gtk_entry_set_text(GTK_ENTRY(entrytext), newcommand);
00597     }
00598     else
00599     /* Grab focus anyway, key can be used somewhere, prevent other handlers */
00600         gtk_widget_grab_focus (GTK_WIDGET(entrytext));
00601     gtk_entry_set_position(GTK_ENTRY(entrytext), -1);
00602 }
00603 
00604 
00605 /* Event handlers for map drawing area */
00606 /* For a reason I don't know, this gets called a whole bunch.
00607  * every time a monster is killed, this gets called for a reason
00608  * I can't figure out.
00609  */
00610 
00611 static gint
00612 configure_event (GtkWidget *widget, GdkEventConfigure *event)
00613 {
00614     static sint16  ox=-1, oy=-1;
00615 
00616     /* Handle the surplus number of events that this causes to be generated.
00617      * Basically, if the size of the window hasn't changed, we really don't
00618      * care - position of the window isn't important.
00619      * Note that we could be more clever and free up the other data even on
00620      * requests that do change the size,
00621      * but this will fix the most horrendous memory leak
00622      */
00623     if (event->type == GDK_CONFIGURE) {
00624         if (((GdkEventConfigure*)event)->width == ox && ((GdkEventConfigure*)event)->height == oy)
00625             return TRUE;
00626         else {
00627 #if 0
00628             fprintf(stderr, "ox=%d != %d, oy=%d != %d\n", ox, ((GdkEventConfigure*)event)->width,
00629                     oy, ((GdkEventConfigure*)event)->height);
00630 #endif
00631             ox = ((GdkEventConfigure*)event)->width;
00632             oy = ((GdkEventConfigure*)event)->height;
00633         }
00634     }
00635 
00636 #ifdef HAVE_SDL
00637     if(use_config[CONFIG_DISPLAYMODE]==CFG_DM_SDL) {
00638         /* When program first runs, mapsurface can be null.
00639          * Either way, we want to catch it here.
00640          */
00641         if (mapsurface)
00642             SDL_UpdateRect( mapsurface, 0, 0, 0, 0);
00643         return TRUE;
00644     }
00645 #endif
00646 
00647     mapgc = gdk_gc_new (drawingarea->window);
00648 
00649     if (use_config[CONFIG_DISPLAYMODE]==CFG_DM_PIXMAP) {
00650         int x,y,count;
00651         GdkGC   *darkgc;
00652 
00653         /* This is used when drawing with GdkPixmaps.  Create another surface,
00654          * as well as some light/dark images
00655          */
00656         dark = gdk_pixmap_new(drawingarea->window, map_image_size, map_image_size, -1);
00657         gdk_draw_rectangle(dark, drawingarea->style->black_gc, TRUE, 0, 0, map_image_size, map_image_size);
00658         dark1 = gdk_pixmap_new(drawingarea->window, map_image_size, map_image_size, 1);
00659         dark2 = gdk_pixmap_new(drawingarea->window, map_image_size, map_image_size, 1);
00660         dark3 = gdk_pixmap_new(drawingarea->window, map_image_size, map_image_size, 1);
00661 
00662         /* We need our own GC here because we are working with single bit depth images */
00663         darkgc = gdk_gc_new(dark1);
00664         gdk_gc_set_foreground(darkgc, &root_color[NDI_WHITE]);
00665         /* Clear any garbage values we get when we create the bitmaps */
00666         gdk_draw_rectangle(dark1, darkgc, TRUE, 0, 0, map_image_size, map_image_size);
00667         gdk_draw_rectangle(dark2, darkgc, TRUE, 0, 0, map_image_size, map_image_size);
00668         gdk_draw_rectangle(dark3, darkgc, TRUE, 0, 0, map_image_size, map_image_size);
00669         gdk_gc_set_foreground(darkgc, &root_color[NDI_BLACK]);
00670         count=0;
00671         for (x=0; x<map_image_size; x++) {
00672             for (y=0; y<map_image_size; y++) {
00673 
00674                 /* We just fill in points every X pixels - dark1 is the darkest, dark3 is the lightest.
00675                  * dark1 has 50% of the pixels filled in, dark2 has 33%, dark3 has 25%
00676                  * The formulae here are not perfect - dark2 will not match perfectly with an
00677                  * adjacent dark2 image.  dark3 results in diagonal stripes.  OTOH, these will
00678                  * change depending on the image size.
00679                  */
00680                 if ((x+y) % 2) {
00681                     gdk_draw_point(dark1, darkgc, x, y);
00682                 }
00683                 if ((x+y) %3) {
00684                     gdk_draw_point(dark2, darkgc, x, y);
00685                 }
00686                 if ((x+y) % 4) {
00687                     gdk_draw_point(dark3, darkgc, x, y);
00688                 }
00689                 /* dark1 gets filled on 0x01, 0x11, 0x10, only leaving 0x00 empty */
00690             }
00691             /* If the row size is even, we put an extra value in count - in this
00692              * way, the pixels will be even on one line, odd on the next, etc
00693              * instead of vertical lines - at least for dark1 and dark3
00694              */
00695         }
00696         mapwindow = gdk_pixmap_new(gtkwin_root->window, use_config[CONFIG_MAPWIDTH] * map_image_size, use_config[CONFIG_MAPHEIGHT] * map_image_size, -1);
00697         gdk_gc_unref(darkgc);
00698     }
00699     display_map_doneupdate(TRUE, FALSE);
00700     return TRUE;
00701 }
00702 
00703 
00704 
00705 /* Redraw the screen from the backing pixmap */
00706 static gint
00707 expose_event (GtkWidget *widget, GdkEventExpose *event)
00708 {
00709 #ifdef HAVE_SDL
00710     if(use_config[CONFIG_DISPLAYMODE]==CFG_DM_SDL && mapsurface) {
00711         SDL_UpdateRect( mapsurface, 0, 0, 0, 0);
00712         return FALSE;
00713     }
00714 #endif
00715     display_map_doneupdate(FALSE, FALSE);
00716     return FALSE;
00717 }
00718 
00719 /*
00720  * Sets up player game view window, implemented as a gtk table. Cells are initialized
00721  * with the bg.xpm pixmap to avoid resizes and to initialize GC's and everything for the
00722  * actual drawing routines later.
00723  */
00724 
00725 static int get_game_display(GtkWidget *frame) {
00726     GtkWidget *gtvbox, *gthbox;
00727 
00728     gtvbox = gtk_vbox_new (FALSE, 0);
00729     gtk_container_add (GTK_CONTAINER (frame), gtvbox);
00730     gthbox = gtk_hbox_new (FALSE, 0);
00731     gtk_box_pack_start (GTK_BOX (gtvbox), gthbox, FALSE, FALSE, 1);
00732 
00733     drawingarea = gtk_drawing_area_new();
00734     gtk_drawing_area_size(GTK_DRAWING_AREA(drawingarea), map_image_size*use_config[CONFIG_MAPWIDTH],map_image_size*use_config[CONFIG_MAPHEIGHT]);
00735     /* Add mouseclick events to the drawing area */
00736 
00737     gtk_widget_set_events (drawingarea, GDK_BUTTON_PRESS_MASK);
00738 
00739     /* Set up X redraw routine signalling */
00740     gtk_signal_connect (GTK_OBJECT (drawingarea), "expose_event",
00741                       (GtkSignalFunc) expose_event, NULL);
00742     gtk_signal_connect (GTK_OBJECT(drawingarea),"configure_event",
00743                       (GtkSignalFunc) configure_event, NULL);
00744     /* Set up handling of mouseclicks in map */
00745 
00746     gtk_signal_connect (GTK_OBJECT(drawingarea),
00747                       "button_press_event",
00748                       GTK_SIGNAL_FUNC(button_map_event),
00749                       NULL);
00750 
00751     /* Pack it up and show it */
00752 
00753     gtk_box_pack_start (GTK_BOX (gthbox), drawingarea, FALSE, FALSE, 1);
00754 
00755     gtk_widget_show(drawingarea);
00756 
00757     gtk_widget_show(gthbox);
00758     gtk_widget_show(gtvbox);
00759 
00760 
00761     gtk_signal_connect (GTK_OBJECT (frame), "expose_event",
00762                       (GtkSignalFunc) expose_event, NULL);
00763     gtk_signal_connect (GTK_OBJECT(frame),"configure_event",
00764                       (GtkSignalFunc) configure_event, NULL);
00765 
00766     gtk_widget_show (frame);
00767   return 0;
00768 }
00769 
00770 
00771 
00772 /******************************************************************************
00773  *
00774  * The functions dealing with the info window follow
00775  *
00776  *****************************************************************************/
00777 
00778 
00779 static void enter_callback(GtkWidget *widget, GtkWidget *entry)
00780 {
00781     const gchar *entry_text;
00782 
00783     /* Next reply will reset this as necessary */
00784     gtk_entry_set_visibility(GTK_ENTRY(entrytext), TRUE);
00785 
00786     entry_text = gtk_entry_get_text(GTK_ENTRY(entrytext));
00787          /*         printf("Entry contents: %s\n", entry_text);*/
00788 
00789     if (cpl.input_state==Metaserver_Select) {
00790         strcpy(cpl.input_text, entry_text);
00791     } else if (cpl.input_state == Reply_One ||
00792                cpl.input_state == Reply_Many) {
00793         cpl.input_state = Playing;
00794         strcpy(cpl.input_text, entry_text);
00795         if (cpl.input_state == Reply_One)
00796             cpl.input_text[1] = 0;
00797 
00798         send_reply(cpl.input_text);
00799 
00800     } else {
00801         cpl.input_state = Playing;
00802         /* No reason to do anything for a null string */
00803         if (entry_text[0] != 0) {
00804             strncpy(history[cur_history_position], entry_text, MAX_COMMAND_LEN);
00805             history[cur_history_position][MAX_COMMAND_LEN-1] = 0;
00806             cur_history_position++;
00807             cur_history_position %= MAX_HISTORY;
00808             scroll_history_position = cur_history_position;
00809             extended_command(entry_text);
00810         }
00811     }
00812     gtk_entry_set_text(GTK_ENTRY(entrytext),"");
00813     gtk_widget_grab_focus (GTK_WIDGET(gtkwin_info_text));
00814 
00815     if( cpl.input_state == Metaserver_Select)
00816     {
00817       cpl.input_state= Playing;
00818       /* This is the gtk_main that is started up by get_metaserver
00819        * The client will start another one once it is connected
00820        * to a crossfire server
00821        */
00822       gtk_main_quit();
00823     }
00824 }
00825 
00826 /* Can use a wheeled mouse to scroll the info window */
00827 static gboolean
00828 info_text_button_press_event (GtkWidget *widget, GdkEventButton *event,
00829                               gpointer user_data)
00830 {
00831   GtkAdjustment *vadj;
00832   gboolean shifted;
00833   gfloat v_value;
00834 
00835   vadj = GTK_TEXT (widget)->vadj;
00836   v_value = vadj->value;
00837 
00838   shifted = (event->state & GDK_SHIFT_MASK) != 0;
00839 
00840   switch (event->button)
00841   {
00842     case 4:
00843       if (shifted)
00844         v_value -= vadj->page_size;
00845       else
00846         v_value -= vadj->step_increment * 5;
00847       break;
00848 
00849     case 5:
00850       if (shifted)
00851         v_value += vadj->page_size;
00852       else
00853         v_value += vadj->step_increment * 5;
00854       break;
00855 
00856     default:
00857       return FALSE;
00858   }
00859 
00860   v_value = CLAMP (v_value, vadj->lower, vadj->upper - vadj->page_size);
00861 
00862   gtk_adjustment_set_value (vadj, v_value);
00863 
00864   return TRUE;
00865 }
00866 
00867 static int get_info_display(GtkWidget *frame) {
00868     GtkWidget *box1;
00869     GtkWidget *box2;
00870     GtkWidget *tablet;
00871     GtkWidget *vscrollbar;
00872     FILE *infile;
00873 
00874     box1 = gtk_vbox_new (FALSE, 0);
00875     if (use_config[CONFIG_SPLITINFO]) {
00876         info_vpane = gtk_vpaned_new();
00877         gtk_container_add (GTK_CONTAINER (frame), info_vpane);
00878         gtk_widget_show(info_vpane);
00879         gtk_paned_add2(GTK_PANED(info_vpane), box1);
00880     } else {
00881         gtk_container_add (GTK_CONTAINER (frame), box1);
00882     }
00883     gtk_widget_show (box1);
00884 
00885     box2 = gtk_vbox_new (FALSE, 3);
00886     gtk_container_border_width (GTK_CONTAINER (box2), 3);
00887     gtk_box_pack_start (GTK_BOX (box1), box2, TRUE, TRUE, 0);
00888     gtk_widget_show (box2);
00889 
00890 
00891     tablet = gtk_table_new (2, 2, FALSE);
00892     gtk_table_set_row_spacing (GTK_TABLE (tablet), 0, 2);
00893     gtk_table_set_col_spacing (GTK_TABLE (tablet), 0, 2);
00894     gtk_box_pack_start (GTK_BOX (box2), tablet, TRUE, TRUE, 0);
00895     gtk_widget_show (tablet);
00896 
00897     text_hadj = gtk_adjustment_new(1, 0, 1, 0.01, 0.1, 40);
00898     text_vadj = gtk_adjustment_new(1, 0, 1, 0.01, 0.1, 40);
00899 
00900     gtkwin_info_text = gtk_text_new (GTK_ADJUSTMENT(text_hadj),GTK_ADJUSTMENT(text_vadj));
00901     gtk_text_set_editable (GTK_TEXT (gtkwin_info_text), FALSE);
00902     gtk_table_attach (GTK_TABLE (tablet), gtkwin_info_text, 0, 1, 0, 1,
00903                     GTK_EXPAND | GTK_SHRINK | GTK_FILL,
00904                     GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
00905     gtk_widget_show (gtkwin_info_text);
00906 
00907 
00908     vscrollbar = gtk_vscrollbar_new (GTK_TEXT (gtkwin_info_text)->vadj);
00909     gtk_table_attach (GTK_TABLE (tablet), vscrollbar, 1, 2, 0, 1,
00910                      GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
00911     gtk_widget_show (vscrollbar);
00912 
00913     gtk_signal_connect (GTK_OBJECT (gtkwin_info_text), "button_press_event",
00914                       GTK_SIGNAL_FUNC (info_text_button_press_event),
00915                       vscrollbar);
00916 
00917     gtk_text_freeze (GTK_TEXT (gtkwin_info_text));
00918 
00919     gtk_widget_realize (gtkwin_info_text);
00920 
00921     if (use_config[CONFIG_SPLITINFO]) {
00922 
00923         box1 = gtk_vbox_new (FALSE, 0);
00924         gtk_widget_show (box1);
00925         gtk_paned_add1(GTK_PANED(info_vpane), box1);
00926 
00927         tablet = gtk_table_new (2, 2, FALSE);
00928         gtk_table_set_row_spacing (GTK_TABLE (tablet), 0, 2);
00929         gtk_table_set_col_spacing (GTK_TABLE (tablet), 0, 2);
00930         gtk_box_pack_start (GTK_BOX (box1), tablet, TRUE, TRUE, 0);
00931         gtk_widget_show (tablet);
00932 
00933         text_hadj2 = gtk_adjustment_new(1, 0, 1, 0.01, 0.1, 40);
00934         text_vadj2 = gtk_adjustment_new(1, 0, 1, 0.01, 0.1, 40);
00935 
00936         gtkwin_info_text2 = gtk_text_new (GTK_ADJUSTMENT(text_hadj2),GTK_ADJUSTMENT(text_vadj2));
00937 
00938         gtk_text_set_editable (GTK_TEXT (gtkwin_info_text2), FALSE);
00939         gtk_table_attach (GTK_TABLE (tablet), gtkwin_info_text2, 0, 1, 0, 1,
00940                     GTK_EXPAND | GTK_SHRINK | GTK_FILL,
00941                     GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
00942         gtk_widget_show (gtkwin_info_text2);
00943 
00944         vscrollbar = gtk_vscrollbar_new (GTK_TEXT (gtkwin_info_text2)->vadj);
00945         gtk_table_attach (GTK_TABLE (tablet), vscrollbar, 1, 2, 0, 1,
00946                      GTK_FILL, GTK_EXPAND | GTK_SHRINK | GTK_FILL, 0, 0);
00947         gtk_widget_show (vscrollbar);
00948         gtk_signal_connect (GTK_OBJECT (gtkwin_info_text2), "button_press_event",
00949                       GTK_SIGNAL_FUNC (info_text_button_press_event),
00950                       vscrollbar);
00951 
00952         gtk_widget_realize (gtkwin_info_text2);
00953     }
00954 
00955   infile = fopen("Welcome", "r");
00956 
00957   if (infile)
00958     {
00959       char buffer[1024];
00960       int nchars;
00961 
00962       while (1)
00963         {
00964           nchars = fread(buffer, 1, 1024, infile);
00965           gtk_text_insert (GTK_TEXT (gtkwin_info_text), NULL, NULL,
00966                            NULL, buffer, nchars);
00967 
00968           if (nchars < 1024)
00969             break;
00970         }
00971 
00972       fclose (infile);
00973     }
00974 
00975   gtk_text_thaw (GTK_TEXT (gtkwin_info_text));
00976 
00977 
00978   entrytext = gtk_entry_new ();
00979   gtk_signal_connect(GTK_OBJECT(entrytext), "activate",
00980                      GTK_SIGNAL_FUNC(enter_callback),
00981                      entrytext);
00982   gtk_box_pack_start (GTK_BOX (box2),entrytext, FALSE, TRUE, 0);
00983   GTK_WIDGET_SET_FLAGS (entrytext, GTK_CAN_DEFAULT);
00984   gtk_widget_grab_default (entrytext);
00985   gtk_widget_show (entrytext);
00986 
00987   return 0;
00988 }
00989 
00990 /* Various replies */
00991 
00992 static void sendstr(char *sendstr)
00993 {
00994   gtk_widget_destroy (dialog_window);
00995   send_reply(sendstr);
00996   cpl.input_state = Playing;
00997 }
00998 
00999 
01000 /* This is similar to draw_info below, but doesn't advance to a new
01001  * line.  Generally queries use this function to draw the prompt for
01002  * the name, password, etc.
01003  */
01004 
01005 
01006 
01007 static void dialog_callback(GtkWidget *dialog)
01008 {
01009   const gchar *dialog_text;
01010   dialog_text = gtk_entry_get_text(GTK_ENTRY(dialogtext));
01011   send_reply(dialog_text);
01012   gtk_widget_destroy (dialog_window);
01013   cpl.input_state = Playing;
01014 }
01015 static GtkWidget *userText = NULL;
01016 static GtkWidget *passwordText = NULL;
01017 static GtkWidget *passwordText2 = NULL;
01018 static GtkWidget *loginWindow = NULL;
01019 static GtkWidget *motdText = NULL;
01020 static GtkWidget *rulesText = NULL;
01021 static GtkWidget *newsText = NULL;
01022 static GtkWidget *loginTabs = NULL;
01023 static GtkWidget *loginButtonOk = NULL;
01024 static GtkWidget *loginButtonCancel = NULL;
01025 static GtkWidget *loginMessage = NULL;
01026 
01027 char password[64]="";
01028 static void setUserPass(GtkButton *button, gpointer func_data) {
01029     gchar* user;
01030     gchar* pass;
01031     user=gtk_editable_get_chars (GTK_EDITABLE(userText),0,-1);
01032     pass=gtk_editable_get_chars (GTK_EDITABLE(passwordText),0,-1);
01033     strncpy(password,pass,sizeof(password));
01034     send_reply(user);
01035 #ifdef MULTKEYS
01036   /* Now is a good time to load player's specific key bindings */
01037     if (csocket.servername != NULL)
01038         sprintf(cpl.name, "%s.%s", user, csocket.servername);
01039     else
01040         strcpy( cpl.name, user );
01041     init_keys( );
01042 #endif
01043     cpl.input_state = Playing;
01044     g_free(user);
01045     g_free(pass);
01046     gtk_widget_hide(loginWindow);
01047 }
01048 static void confirmUserPass(GtkButton *button, gpointer func_data) {
01049     gchar* pass;
01050     pass=gtk_editable_get_chars (GTK_EDITABLE(passwordText2),0,-1);
01051     send_reply(pass);
01052     cpl.input_state = Playing;
01053     g_free(pass);
01054     gtk_widget_hide(loginWindow);
01055 }
01056 static void cancelConnection(GtkButton *button, gpointer func_data) {
01057     gtk_widget_hide(loginWindow);
01058     cpl.input_state = Metaserver_Select;
01059     disconnect(GTK_WIDGET(button));
01060 }
01061 
01062 static void disable_ok_if_empty(gpointer button, GtkEditable *entry) {
01063     gchar *passcontent,*txtcontent;
01064     txtcontent = gtk_editable_get_chars(GTK_EDITABLE(userText),0,-1);
01065     passcontent= gtk_editable_get_chars(GTK_EDITABLE(passwordText)  ,0,-1);
01066     if ( passcontent && txtcontent &&
01067          (strlen(txtcontent)>=1)&&
01068          (strlen(passcontent)>=1))
01069         gtk_widget_set_sensitive(GTK_WIDGET(loginButtonOk),TRUE);
01070     else
01071         gtk_widget_set_sensitive(GTK_WIDGET(loginButtonOk),FALSE);
01072     if (txtcontent && (strlen (txtcontent)>0))
01073         gtk_widget_show(passwordText);
01074     else
01075         gtk_widget_hide(passwordText);
01076     g_free(txtcontent);
01077     g_free(passcontent);
01078 }
01079 static void change_focus(GtkWidget *focusTo, GtkEditable *entry) {
01080 
01081     char *txtcontent = gtk_editable_get_chars(entry,0,-1);
01082 /*    printf("switch focus\n"); */
01083     if (txtcontent && (strlen(txtcontent)>0))
01084             gtk_widget_grab_focus(focusTo);
01085 }
01086 static void activate_ok_if_not_empty(GtkWidget *button, GtkEditable *entry) {
01087     char *txtcontent = gtk_editable_get_chars(entry,0,-1);
01088     if (txtcontent && (strlen(txtcontent)>0))
01089         gtk_widget_activate(button);
01090     if (txtcontent)
01091         g_free(txtcontent);
01092 }
01093 static void fill_news(GtkWidget *o, news_entry *news) {
01094     media_state state;
01095     while(news){
01096         state = write_media(GTK_TEXT(o),"[b]");
01097         write_media_with_state(GTK_TEXT(o),news->title,state);
01098         write_media(GTK_TEXT(o),"\n\n");
01099         write_media(GTK_TEXT(o),news->content);
01100         write_media(GTK_TEXT(o),"\n\n");
01101         news=news->next;
01102     }
01103 }
01104 static gint dialog_delete_event_callback(GtkWidget *widget, GdkEvent *event, gpointer data)
01105     {
01106     loginWindow = NULL;
01107     return FALSE;
01108     }
01109 static void buildLoginDialog(void) {
01110     if (loginWindow==NULL){
01111         /* Build window */
01112         GtkWidget *vbox, *table, *label, *hbox, *vscroll;
01113         loginWindow= gtk_window_new(GTK_WINDOW_TOPLEVEL);
01114         gtk_window_set_policy (GTK_WINDOW (loginWindow), TRUE, TRUE,
01115                  FALSE);
01116         gtk_window_set_transient_for (GTK_WINDOW (loginWindow),
01117                  GTK_WINDOW (gtkwin_root));
01118         gtk_window_set_title (GTK_WINDOW (loginWindow), "Login");
01119         gtk_window_set_transient_for(GTK_WINDOW (loginWindow),
01120                     GTK_WINDOW (gtkwin_root));
01121         vbox=gtk_vbox_new(FALSE,4);
01122 
01123         /* Build it's notebook */
01124         loginTabs = gtk_notebook_new();
01125         /* notebook -> news */
01126         hbox=gtk_hbox_new(FALSE,2);
01127         newsText = gtk_text_new(NULL,NULL);
01128         gtk_text_set_word_wrap(GTK_TEXT(newsText),TRUE);
01129         gtk_text_set_line_wrap(GTK_TEXT(newsText),TRUE);
01130         vscroll = gtk_vscrollbar_new (GTK_TEXT (newsText)->vadj);
01131         gtk_box_pack_start(GTK_BOX(hbox),newsText,TRUE,TRUE,0);
01132         gtk_box_pack_start(GTK_BOX(hbox),vscroll,FALSE,TRUE,0);
01133         label = gtk_label_new("News");
01134         gtk_notebook_append_page(GTK_NOTEBOOK(loginTabs),hbox,label);
01135         gtk_widget_show(vscroll);
01136         gtk_widget_show(newsText);
01137         gtk_widget_show(hbox);
01138         /* notebook -> rules */
01139         hbox=gtk_hbox_new(FALSE,2);
01140         rulesText = gtk_text_new(NULL,NULL);
01141         gtk_text_set_word_wrap(GTK_TEXT(rulesText),TRUE);
01142         gtk_text_set_line_wrap(GTK_TEXT(rulesText),TRUE);
01143         vscroll = gtk_vscrollbar_new (GTK_TEXT (rulesText)->vadj);
01144         gtk_box_pack_start(GTK_BOX(hbox),rulesText,TRUE,TRUE,0);
01145         gtk_box_pack_start(GTK_BOX(hbox),vscroll,FALSE,TRUE,0);
01146         label = gtk_label_new("Rules");
01147         gtk_notebook_append_page(GTK_NOTEBOOK(loginTabs),hbox,label);
01148         gtk_widget_show(vscroll);
01149         gtk_widget_show(rulesText);
01150         gtk_widget_show(hbox);
01151 
01152         /* notebook -> login */
01153         hbox=gtk_hbox_new(FALSE,2);
01154         motdText = gtk_text_new(NULL,NULL);
01155         vscroll = gtk_vscrollbar_new (GTK_TEXT (motdText)->vadj);
01156         gtk_box_pack_start(GTK_BOX(hbox),motdText,TRUE,TRUE,0);
01157         gtk_box_pack_start(GTK_BOX(hbox),vscroll,FALSE,TRUE,0);
01158         gtk_widget_show(hbox);
01159         gtk_widget_show(motdText);
01160         gtk_widget_show(vscroll);
01161         gtk_box_pack_start(GTK_BOX(vbox),hbox,TRUE,TRUE,0);
01162 
01163 
01164         /* Message information */
01165         loginMessage = gtk_label_new(NULL);
01166         gtk_box_pack_start(GTK_BOX(vbox),loginMessage,FALSE,FALSE,0);
01167         gtk_widget_show(loginMessage);
01168 
01169         /* user-pass table*/
01170         table=gtk_table_new(3,2,FALSE);
01171            /* TODO for strange reason justify does not work.
01172             * May someone fix this?*/
01173         label=gtk_label_new("User:");
01174         gtk_table_attach(GTK_TABLE(table),label,0,1,0,1,GTK_EXPAND|GTK_FILL,0,2,2);
01175         gtk_label_set_justify(GTK_LABEL(label),GTK_JUSTIFY_RIGHT);
01176         gtk_widget_show(label);
01177         label=gtk_label_new("Password:");
01178         gtk_table_attach(GTK_TABLE(table),label,0,1,1,2,GTK_EXPAND|GTK_FILL,0,2,2);
01179         gtk_label_set_justify(GTK_LABEL(label),GTK_JUSTIFY_RIGHT);
01180         gtk_widget_show(label);
01181         label=gtk_label_new("Re-type password:");
01182         gtk_table_attach(GTK_TABLE(table),label,0,1,2,3,GTK_EXPAND|GTK_FILL,0,2,2);
01183         gtk_label_set_justify(GTK_LABEL(label),GTK_JUSTIFY_RIGHT);
01184         gtk_widget_show(label);
01185         userText=gtk_entry_new();
01186         gtk_widget_show(userText);
01187         gtk_table_attach(GTK_TABLE(table),userText,1,2,0,1,GTK_EXPAND|GTK_FILL,0,2,2);
01188         passwordText= gtk_entry_new();
01189         gtk_entry_set_visibility(GTK_ENTRY(passwordText),FALSE);
01190         gtk_widget_show(passwordText);
01191         gtk_table_attach(GTK_TABLE(table),passwordText,1,2,1,2,GTK_EXPAND|GTK_FILL,0,2,2);
01192         passwordText2= gtk_entry_new();
01193         gtk_entry_set_visibility(GTK_ENTRY(passwordText2),FALSE);
01194         gtk_entry_set_editable(GTK_ENTRY(passwordText2),FALSE);
01195         gtk_table_attach(GTK_TABLE(table),passwordText2,1,2,2,3,GTK_EXPAND|GTK_FILL,0,2,2);
01196         gtk_widget_show(passwordText2);
01197         gtk_box_pack_start(GTK_BOX(vbox),table,FALSE,FALSE,0);
01198 
01199 
01200         hbox=gtk_hbox_new(FALSE,2);
01201         loginButtonOk = gtk_button_new_with_label("Ok");
01202         loginButtonCancel = gtk_button_new_with_label("Cancel");
01203         gtk_box_pack_start(GTK_BOX(hbox),loginButtonOk,TRUE,FALSE,0);
01204         gtk_box_pack_start(GTK_BOX(hbox),loginButtonCancel,TRUE,FALSE,0);
01205         gtk_widget_show(hbox);
01206         gtk_widget_show(loginButtonOk);
01207         gtk_widget_show(loginButtonCancel);
01208 
01209         /* Manage events on login widgets */
01210         gtk_signal_connect_object (GTK_OBJECT (loginWindow),
01211                 "delete_event",
01212                 GTK_SIGNAL_FUNC (dialog_delete_event_callback),
01213                 NULL);
01214         gtk_signal_connect_object (GTK_OBJECT (loginButtonCancel),
01215                 "clicked",
01216                 GTK_SIGNAL_FUNC (cancelConnection),
01217                 NULL);
01218         gtk_signal_connect_object (GTK_OBJECT (userText),
01219                 "changed",
01220                 GTK_SIGNAL_FUNC (disable_ok_if_empty),
01221                 GINT_TO_POINTER(loginButtonOk));
01222         gtk_signal_connect_object (GTK_OBJECT (passwordText),
01223                 "changed",
01224                 GTK_SIGNAL_FUNC (disable_ok_if_empty),
01225                 GINT_TO_POINTER(loginButtonOk));
01226         gtk_signal_connect_object (GTK_OBJECT (userText),
01227                 "activate",
01228                 GTK_SIGNAL_FUNC (change_focus),
01229                 GINT_TO_POINTER(passwordText));
01230         gtk_signal_connect_object (GTK_OBJECT (userText),
01231                 "activate",
01232                 GTK_SIGNAL_FUNC (change_focus),
01233                 GINT_TO_POINTER(passwordText));
01234         gtk_box_pack_start(GTK_BOX(vbox),hbox,FALSE,FALSE,0);
01235         gtk_signal_connect_object (GTK_OBJECT (passwordText),
01236                 "activate",
01237                 GTK_SIGNAL_FUNC (activate_ok_if_not_empty),
01238                 GINT_TO_POINTER(loginButtonOk));
01239         gtk_signal_connect_object (GTK_OBJECT (passwordText2),
01240                 "activate",
01241                 GTK_SIGNAL_FUNC (activate_ok_if_not_empty),
01242                 GINT_TO_POINTER(loginButtonOk));
01243         gtk_box_pack_start(GTK_BOX(vbox),hbox,FALSE,FALSE,0);
01244         gtk_widget_show(table);
01245         gtk_widget_show(vbox);
01246         label=gtk_label_new("login");
01247         gtk_notebook_append_page(GTK_NOTEBOOK(loginTabs),vbox,label);
01248         gtk_container_add(GTK_CONTAINER(loginWindow),loginTabs);
01249         gtk_widget_show(loginTabs);
01250         gtk_window_set_default_size(GTK_WINDOW(loginWindow),500,400);
01251         gtk_window_set_position(GTK_WINDOW(loginWindow),GTK_WIN_POS_CENTER);
01252     }
01253     gtk_editable_delete_text(GTK_EDITABLE(motdText),0,-1);
01254     write_media(GTK_TEXT(motdText), getMOTD());
01255     gtk_editable_delete_text(GTK_EDITABLE(rulesText),0,-1);
01256     write_media(GTK_TEXT(rulesText),get_rules());
01257     gtk_editable_delete_text(GTK_EDITABLE(newsText),0,-1);
01258     fill_news(newsText,get_news());
01259     gtk_widget_show(loginWindow);
01260 }
01261 guint signalLoginDialogClicked = -1;
01262 static void logUserIn(void) {
01263     buildLoginDialog();
01264     gtk_label_set_text(GTK_LABEL(loginMessage),"Type in user name and password");
01265     gtk_entry_set_editable(GTK_ENTRY(userText),TRUE);
01266     gtk_entry_set_editable(GTK_ENTRY(passwordText),TRUE);
01267     gtk_entry_set_editable(GTK_ENTRY(passwordText2),FALSE);
01268     gtk_widget_show(GTK_WIDGET(passwordText));
01269     gtk_widget_hide(GTK_WIDGET(passwordText2));
01270     if (signalLoginDialogClicked!=-1)
01271         gtk_signal_disconnect(GTK_OBJECT (loginButtonOk),
01272                 signalLoginDialogClicked);
01273     signalLoginDialogClicked = gtk_signal_connect_object (GTK_OBJECT (loginButtonOk),
01274             "clicked",
01275             GTK_SIGNAL_FUNC (setUserPass),
01276             NULL);
01277     gtk_widget_set_sensitive(GTK_WIDGET(loginButtonOk),TRUE);
01278     gtk_entry_set_text(GTK_ENTRY(userText),"");
01279     gtk_entry_set_text(GTK_ENTRY(passwordText),"");
01280     gtk_entry_set_text(GTK_ENTRY(passwordText2),"");
01281     gtk_widget_grab_focus(userText);
01282 }
01283 static void sendPassword(void) {
01284     send_reply(password);
01285         cpl.input_state = Playing;
01286 }
01287 static void confirmPassword(void) {
01288     buildLoginDialog();
01289     gtk_label_set_text(GTK_LABEL(loginMessage),"Creating new user, please confirm password");
01290     gtk_entry_set_editable(GTK_ENTRY(userText),FALSE);
01291     gtk_entry_set_editable(GTK_ENTRY(passwordText),FALSE);
01292     gtk_entry_set_editable(GTK_ENTRY(passwordText2),TRUE);
01293     gtk_widget_hide(GTK_WIDGET(passwordText));
01294     gtk_widget_show(GTK_WIDGET(passwordText2));
01295     if (signalLoginDialogClicked!=-1)
01296         gtk_signal_disconnect(GTK_OBJECT (loginButtonOk),
01297                 signalLoginDialogClicked);
01298     signalLoginDialogClicked = gtk_signal_connect_object (GTK_OBJECT (loginButtonOk),
01299             "clicked",
01300             GTK_SIGNAL_FUNC (confirmUserPass),
01301             NULL);
01302     gtk_widget_grab_focus(passwordText2);
01303 }
01304 /* Draw a prompt dialog window */
01305 /* Ok, now this is trying to be smart and decide what sort of dialog is
01306  * wanted.
01307  */
01308 
01309 void
01310 draw_prompt (const char *str)
01311 {
01312     GtkWidget *dbox;
01313     GtkWidget *hbox;
01314     GtkWidget *dialoglabel;
01315     GtkWidget *yesbutton, *nobutton;
01316     GtkWidget *strbutton, *dexbutton, *conbutton, *intbutton, *wisbutton,
01317         *powbutton, *chabutton;
01318 
01319     gint    found = FALSE;
01320 
01321     if (!use_config[CONFIG_POPUPS])
01322       {
01323         draw_info(str, NDI_BLACK);
01324       }
01325     else
01326       {
01327           dialog_window = gtk_window_new (GTK_WINDOW_DIALOG);
01328 
01329           gtk_window_set_policy (GTK_WINDOW (dialog_window), TRUE, TRUE,
01330                                  FALSE);
01331           gtk_window_set_title (GTK_WINDOW (dialog_window), "Dialog");
01332           gtk_window_set_transient_for (GTK_WINDOW (dialog_window),
01333                                         GTK_WINDOW (gtkwin_root));
01334 
01335           dbox = gtk_vbox_new (FALSE, 6);
01336           gtk_container_add (GTK_CONTAINER (dialog_window), dbox);
01337 
01338           /* Ok, here we start generating the contents */
01339 
01340           /*  printf ("Last info draw: %s\n", last_str); */
01341           while (!found)
01342             {
01343                 if (!strcmp (str, ":"))
01344                   {
01345                       if (!strcmp (last_str, "What is your name?"))
01346                         {
01347                 logUserIn();
01348                 return;
01349                         }
01350 
01351                       if (!strcmp (last_str, "What is your password?"))
01352                         {
01353                 sendPassword();
01354                 return;
01355                         }
01356                       if (!strcmp
01357                           (last_str, "Please type your password again."))
01358                         {
01359                 confirmPassword();
01360                 return;
01361                         }
01362                   }
01363                 /* Ok, tricky ones. */
01364                 if (!strcmp (last_str, "[1-7] [1-7] to swap stats.")
01365                     || !strncmp (last_str, "Str d", 5)
01366                     || !strncmp (last_str, "Dex d", 5)
01367                     || !strncmp (last_str, "Con d", 5)
01368                     || !strncmp (last_str, "Int d", 5)
01369                     || !strncmp (last_str, "Wis d", 5)
01370                     || !strncmp (last_str, "Pow d", 5)
01371                     || !strncmp (last_str, "Cha d", 5))
01372                   {
01373 
01374                       dialoglabel =
01375                           gtk_label_new ("Roll again or exchange ability.");
01376                       gtk_box_pack_start (GTK_BOX (dbox), dialoglabel, FALSE,
01377                                           TRUE, 6);
01378                       gtk_widget_show (dialoglabel);
01379 
01380                       hbox = gtk_hbox_new (TRUE, 2);
01381                       strbutton = gtk_button_new_with_label ("Str");
01382                       gtk_box_pack_start (GTK_BOX (hbox), strbutton, TRUE,
01383                                           TRUE, 1);
01384                       gtk_signal_connect_object (GTK_OBJECT (strbutton),
01385                                                  "clicked",
01386                                                  GTK_SIGNAL_FUNC (sendstr),
01387                                                  GINT_TO_POINTER ("1"));
01388 
01389 
01390                       dexbutton = gtk_button_new_with_label ("Dex");
01391                       gtk_box_pack_start (GTK_BOX (hbox), dexbutton, TRUE,
01392                                           TRUE, 1);
01393                       gtk_signal_connect_object (GTK_OBJECT (dexbutton),
01394                                                  "clicked",
01395                                                  GTK_SIGNAL_FUNC (sendstr),
01396                                                  GINT_TO_POINTER ("2"));
01397 
01398                       conbutton = gtk_button_new_with_label ("Con");
01399                       gtk_box_pack_start (GTK_BOX (hbox), conbutton, TRUE,
01400                                           TRUE, 1);
01401                       gtk_signal_connect_object (GTK_OBJECT (conbutton),
01402                                                  "clicked",
01403                                                  GTK_SIGNAL_FUNC (sendstr),
01404                                                  GINT_TO_POINTER ("3"));
01405 
01406                       intbutton = gtk_button_new_with_label ("Int");
01407                       gtk_box_pack_start (GTK_BOX (hbox), intbutton, TRUE,
01408                                           TRUE, 1);
01409                       gtk_signal_connect_object (GTK_OBJECT (intbutton),
01410                                                  "clicked",
01411                                                  GTK_SIGNAL_FUNC (sendstr),
01412                                                  GINT_TO_POINTER ("4"));
01413 
01414                       wisbutton = gtk_button_new_with_label ("Wis");
01415                       gtk_box_pack_start (GTK_BOX (hbox), wisbutton, TRUE,
01416                                           TRUE, 1);
01417                       gtk_signal_connect_object (GTK_OBJECT (wisbutton),
01418                                                  "clicked",
01419                                                  GTK_SIGNAL_FUNC (sendstr),
01420                                                  GINT_TO_POINTER ("5"));
01421 
01422                       powbutton = gtk_button_new_with_label ("Pow");
01423                       gtk_box_pack_start (GTK_BOX (hbox), powbutton, TRUE,
01424                                           TRUE, 1);
01425                       gtk_signal_connect_object (GTK_OBJECT (powbutton),
01426                                                  "clicked",
01427                                                  GTK_SIGNAL_FUNC (sendstr),
01428                                                  GINT_TO_POINTER ("6"));
01429 
01430                       chabutton = gtk_button_new_with_label ("Cha");
01431                       gtk_box_pack_start (GTK_BOX (hbox), chabutton, TRUE,
01432                                           TRUE, 1);
01433                       gtk_signal_connect_object (GTK_OBJECT (chabutton),
01434                                                  "clicked",
01435                                                  GTK_SIGNAL_FUNC (sendstr),
01436                                                  GINT_TO_POINTER ("7"));
01437 
01438                       gtk_widget_show (strbutton);
01439                       gtk_widget_show (dexbutton);
01440                       gtk_widget_show (conbutton);
01441                       gtk_widget_show (intbutton);
01442                       gtk_widget_show (wisbutton);
01443                       gtk_widget_show (powbutton);
01444                       gtk_widget_show (chabutton);
01445 
01446 
01447 
01448                       gtk_box_pack_start (GTK_BOX (dbox), hbox, FALSE, TRUE,
01449                                           6);
01450                       gtk_widget_show (hbox);
01451 
01452                       hbox = gtk_hbox_new (FALSE, 6);
01453 
01454                       yesbutton = gtk_button_new_with_label ("Roll again");
01455                       gtk_box_pack_start (GTK_BOX (hbox), yesbutton, TRUE,
01456                                           TRUE, 6);
01457                       gtk_signal_connect_object (GTK_OBJECT (yesbutton),
01458                                                  "clicked",
01459                                                  GTK_SIGNAL_FUNC (sendstr),
01460                                                  GINT_TO_POINTER ("y"));
01461 
01462                       nobutton = gtk_button_new_with_label ("Keep this");
01463                       gtk_box_pack_start (GTK_BOX (hbox), nobutton, TRUE,
01464                                           TRUE, 6);
01465                       gtk_signal_connect_object (GTK_OBJECT (nobutton),
01466                                                  "clicked",
01467                                                  GTK_SIGNAL_FUNC (sendstr),
01468                                                  GINT_TO_POINTER ("n"));
01469 
01470                       gtk_box_pack_start (GTK_BOX (dbox), hbox, FALSE, TRUE,
01471                                           6);
01472 
01473                       gtk_widget_show (yesbutton);
01474                       gtk_widget_show (nobutton);
01475                       gtk_widget_show (hbox);
01476 
01477                       found = TRUE;
01478                       continue;
01479                   }
01480                 if (!strncmp (last_str, "Str -", 5) ||
01481                     !strncmp (last_str, "Dex -", 5)
01482                     || !strncmp (last_str, "Con -", 5)
01483                     || !strncmp (last_str, "Int -", 5)
01484                     || !strncmp (last_str, "Wis -", 5)
01485                     || !strncmp (last_str, "Pow -", 5)
01486                     || !strncmp (last_str, "Cha -", 5))
01487                   {
01488 
01489 
01490                       dialoglabel =
01491                           gtk_label_new ("Exchange with which ability?");
01492                       gtk_box_pack_start (GTK_BOX (dbox), dialoglabel, FALSE,
01493                                           TRUE, 6);
01494                       gtk_widget_show (dialoglabel);
01495 
01496                       hbox = gtk_hbox_new (TRUE, 2);
01497                       strbutton = gtk_button_new_with_label ("Str");
01498                       gtk_box_pack_start (GTK_BOX (hbox), strbutton, TRUE,
01499                                           TRUE, 1);
01500                       gtk_signal_connect_object (GTK_OBJECT (strbutton),
01501                                                  "clicked",
01502                                                  GTK_SIGNAL_FUNC (sendstr),
01503                                                  GINT_TO_POINTER ("1"));
01504 
01505 
01506                       dexbutton = gtk_button_new_with_label ("Dex");
01507                       gtk_box_pack_start (GTK_BOX (hbox), dexbutton, TRUE,
01508                                           TRUE, 1);
01509                       gtk_signal_connect_object (GTK_OBJECT (dexbutton),
01510                                                  "clicked",
01511                                                  GTK_SIGNAL_FUNC (sendstr),
01512                                                  GINT_TO_POINTER ("2"));
01513 
01514                       conbutton = gtk_button_new_with_label ("Con");
01515                       gtk_box_pack_start (GTK_BOX (hbox), conbutton, TRUE,
01516                                           TRUE, 1);
01517                       gtk_signal_connect_object (GTK_OBJECT (conbutton),
01518                                                  "clicked",
01519                                                  GTK_SIGNAL_FUNC (sendstr),
01520                                                  GINT_TO_POINTER ("3"));
01521 
01522                       intbutton = gtk_button_new_with_label ("Int");
01523                       gtk_box_pack_start (GTK_BOX (hbox), intbutton, TRUE,
01524                                           TRUE, 1);
01525                       gtk_signal_connect_object (GTK_OBJECT (intbutton),
01526                                                  "clicked",
01527                                                  GTK_SIGNAL_FUNC (sendstr),
01528                                                  GINT_TO_POINTER ("4"));
01529 
01530                       wisbutton = gtk_button_new_with_label ("Wis");
01531                       gtk_box_pack_start (GTK_BOX (hbox), wisbutton, TRUE,
01532                                           TRUE, 1);
01533                       gtk_signal_connect_object (GTK_OBJECT (wisbutton),
01534                                                  "clicked",
01535                                                  GTK_SIGNAL_FUNC (sendstr),
01536                                                  GINT_TO_POINTER ("5"));
01537 
01538                       powbutton = gtk_button_new_with_label ("Pow");
01539                       gtk_box_pack_start (GTK_BOX (hbox), powbutton, TRUE,
01540                                           TRUE, 1);
01541                       gtk_signal_connect_object (GTK_OBJECT (powbutton),
01542                                                  "clicked",
01543                                                  GTK_SIGNAL_FUNC (sendstr),
01544                                                  GINT_TO_POINTER ("6"));
01545 
01546                       chabutton = gtk_button_new_with_label ("Cha");
01547                       gtk_box_pack_start (GTK_BOX (hbox), chabutton, TRUE,
01548                                           TRUE, 1);
01549                       gtk_signal_connect_object (GTK_OBJECT (chabutton),
01550                                                  "clicked",
01551                                                  GTK_SIGNAL_FUNC (sendstr),
01552                                                  GINT_TO_POINTER ("7"));
01553 
01554                       gtk_widget_show (strbutton);
01555                       gtk_widget_show (dexbutton);
01556                       gtk_widget_show (conbutton);
01557                       gtk_widget_show (intbutton);
01558                       gtk_widget_show (wisbutton);
01559                       gtk_widget_show (powbutton);
01560                       gtk_widget_show (chabutton);
01561 
01562 
01563                       gtk_box_pack_start (GTK_BOX (dbox), hbox, FALSE, TRUE,
01564                                           6);
01565                       gtk_widget_show (hbox);
01566 
01567                       found = TRUE;
01568                       continue;
01569                   }
01570 
01571                 if (!strncmp (last_str, "Press `d'", 9))
01572                   {
01573 
01574 
01575                       dialoglabel = gtk_label_new ("Choose a character.");
01576                       gtk_box_pack_start (GTK_BOX (dbox), dialoglabel, FALSE,
01577                                           TRUE, 6);
01578                       gtk_widget_show (dialoglabel);
01579 
01580                       hbox = gtk_hbox_new (FALSE, 6);
01581 
01582                       yesbutton = gtk_button_new_with_label ("Show next");
01583                       gtk_box_pack_start (GTK_BOX (hbox), yesbutton, TRUE,
01584                                           TRUE, 6);
01585                       gtk_signal_connect_object (GTK_OBJECT (yesbutton),
01586                                                  "clicked",
01587                                                  GTK_SIGNAL_FUNC (sendstr),
01588                                                  GINT_TO_POINTER (" "));
01589 
01590                       nobutton = gtk_button_new_with_label ("Keep this");
01591                       gtk_box_pack_start (GTK_BOX (hbox), nobutton, TRUE,
01592                                           TRUE, 6);
01593                       gtk_signal_connect_object (GTK_OBJECT (nobutton),
01594                                                  "clicked",
01595                                                  GTK_SIGNAL_FUNC (sendstr),
01596                                                  GINT_TO_POINTER ("d"));
01597 
01598                       gtk_box_pack_start (GTK_BOX (dbox), hbox, FALSE, TRUE,
01599                                           6);
01600 
01601                       gtk_widget_show (yesbutton);
01602                       gtk_widget_show (nobutton);
01603                       gtk_widget_show (hbox);
01604 
01605                       found = TRUE;
01606                       continue;
01607                   }
01608 
01609                 if (!strncmp (str, "Do you want to play", 18))
01610                   {
01611 
01612 
01613                       dialoglabel =
01614                           gtk_label_new ("Do you want to play again?");
01615                       gtk_box_pack_start (GTK_BOX (dbox), dialoglabel, FALSE,
01616                                           TRUE, 6);
01617                       gtk_widget_show (dialoglabel);
01618 
01619                       hbox = gtk_hbox_new (FALSE, 6);
01620 
01621                       yesbutton = gtk_button_new_with_label ("Play again");
01622                       gtk_box_pack_start (GTK_BOX (hbox), yesbutton, TRUE,
01623                                           TRUE, 6);
01624                       gtk_signal_connect_object (GTK_OBJECT (yesbutton),
01625                                                  "clicked",
01626                                                  GTK_SIGNAL_FUNC (sendstr),
01627                                                  GINT_TO_POINTER ("a"));
01628 
01629                       nobutton = gtk_button_new_with_label ("Quit");
01630                       gtk_box_pack_start (GTK_BOX (hbox), nobutton, TRUE,
01631                                           TRUE, 6);
01632                       gtk_signal_connect_object (GTK_OBJECT (nobutton),
01633                                                  "clicked",
01634                                                  GTK_SIGNAL_FUNC (sendstr),
01635                                                  GINT_TO_POINTER ("q"));
01636 
01637                       gtk_box_pack_start (GTK_BOX (dbox), hbox, FALSE, TRUE,
01638                                           6);
01639 
01640                       gtk_widget_show (yesbutton);
01641                       gtk_widget_show (nobutton);
01642                       gtk_widget_show (hbox);
01643 
01644                       found = TRUE;
01645                       continue;
01646                   }
01647 
01648                 if (!strncmp (str, "Are you sure you want", 21))
01649                   {
01650 
01651 
01652                       dialoglabel =
01653                           gtk_label_new ("Are you sure you want to quit?");
01654                       gtk_box_pack_start (GTK_BOX (dbox), dialoglabel, FALSE,
01655                                           TRUE, 6);
01656                       gtk_widget_show (dialoglabel);
01657 
01658                       hbox = gtk_hbox_new (FALSE, 6);
01659 
01660                       yesbutton = gtk_button_new_with_label ("Yes, quit");
01661                       gtk_box_pack_start (GTK_BOX (hbox), yesbutton, TRUE,
01662                                           TRUE, 6);
01663                       gtk_signal_connect_object (GTK_OBJECT (yesbutton),
01664                                                  "clicked",
01665                                                  GTK_SIGNAL_FUNC (sendstr),
01666                                                  GINT_TO_POINTER ("y"));
01667 
01668                       nobutton = gtk_button_new_with_label ("Don't quit");
01669                       gtk_box_pack_start (GTK_BOX (hbox), nobutton, TRUE,
01670                                           TRUE, 6);
01671                       gtk_signal_connect_object (GTK_OBJECT (nobutton),
01672                                                  "clicked",
01673                                                  GTK_SIGNAL_FUNC (sendstr),
01674                                                  GINT_TO_POINTER ("n"));
01675 
01676                       gtk_box_pack_start (GTK_BOX (dbox), hbox, FALSE, TRUE,
01677                                           6);
01678 
01679                       gtk_widget_show (yesbutton);
01680                       gtk_widget_show (nobutton);
01681                       gtk_widget_show (hbox);
01682 
01683                       found = TRUE;
01684                       continue;
01685                   }
01686 
01687         if (!strcmp (last_str, "What is the password?"))
01688                         {
01689 
01690                             dialoglabel =
01691                                 gtk_label_new ("What is the party password?");
01692                             gtk_box_pack_start (GTK_BOX (dbox), dialoglabel,
01693                                                 FALSE, TRUE, 6);
01694                             gtk_widget_show (dialoglabel);
01695 
01696                             hbox = gtk_hbox_new (FALSE, 6);
01697                             dialogtext = gtk_entry_new ();
01698                             gtk_entry_set_visibility (GTK_ENTRY (dialogtext),
01699                                                       FALSE);
01700                             gtk_signal_connect (GTK_OBJECT (dialogtext),
01701                                                 "activate",
01702                                                 GTK_SIGNAL_FUNC
01703                                                 (dialog_callback),
01704                                                 dialog_window);
01705                             gtk_box_pack_start (GTK_BOX (hbox), dialogtext,
01706                                                 TRUE, TRUE, 6);
01707                             gtk_box_pack_start (GTK_BOX (dbox), hbox, FALSE,
01708                                                 TRUE, 6);
01709 
01710                             gtk_widget_show (hbox);
01711 
01712                             gtk_widget_show (dialogtext);
01713                             gtk_widget_grab_focus (dialogtext);
01714                             found = TRUE;
01715                             continue;;
01716                         }
01717 
01718                 if (!found)
01719                   {
01720                       dialoglabel = gtk_label_new (str);
01721                       gtk_box_pack_start (GTK_BOX (dbox), dialoglabel, FALSE,
01722                                           TRUE, 6);
01723                       gtk_widget_show (dialoglabel);
01724 
01725                       hbox = gtk_hbox_new (FALSE, 6);
01726                       dialogtext = gtk_entry_new ();
01727                       if (cpl.no_echo == 1)
01728                           gtk_entry_set_visibility(GTK_ENTRY (dialogtext), FALSE);
01729 
01730                       gtk_signal_connect (GTK_OBJECT (dialogtext), "activate",
01731                                           GTK_SIGNAL_FUNC (dialog_callback),
01732                                           dialog_window);
01733                       gtk_box_pack_start (GTK_BOX (hbox), dialogtext, TRUE,
01734                                           TRUE, 6);
01735                       gtk_box_pack_start (GTK_BOX (dbox), hbox, FALSE, TRUE,
01736                                           6);
01737 
01738                       gtk_widget_show (hbox);
01739                       gtk_widget_show (dialogtext);
01740                       gtk_widget_grab_focus (dialogtext);
01741                       found = TRUE;
01742                       continue;
01743                   }
01744             }
01745 
01746           /* Finished with the contents. */
01747 
01748 
01749           gtk_widget_show (dbox);
01750           gtk_widget_show (dialog_window);
01751       }
01752 
01753 }
01754 
01755 /* draw_info adds a line to the info window. For speed reasons it will
01756  * automatically freeze the info window when adding text to it, set the
01757  * draw_info_freeze variable true and the actual drawing will take place
01758  * during the next do_timeout at which point it is unfrozen again. That way
01759  * we handle massive amounts of text addition with a single GUI event, which
01760  * results in a serious speed improvement for slow client machines (and
01761  * above all it avoids a GUI lockup when the client becomes congested with
01762  * updates (which is often when you're in the middle of fighting something
01763  * serious and not a good time to get slow reaction time)).
01764  *
01765  * MSW 2001-05-25: The removal of input from the text windows should
01766  * work, and in fact does about 90% of the time.  But that 10% it
01767  * doesn't, the client crashes.  The error itself is in the gtk library,
01768  * to hopefully they will fix it someday.  The reason to do this is
01769  * to keep these buffers a reasonable size so that performance stays
01770  * good - otherwise, performance slowly degrades.
01771  */
01772 
01773 void draw_info(const char *str, int color) {
01774     int ncolor = color;
01775     char timestamp[11]="";
01776 
01777     if (ncolor==NDI_WHITE) {
01778         ncolor=NDI_BLACK;
01779     }
01780     if (use_config[CONFIG_TIMESTAMP] && color != NDI_BLACK) {
01781         struct tm *now;
01782         time_t currenttime = time(0);
01783         now = localtime(&currenttime);
01784         strftime(timestamp, 10, "%I:%M: ", now);
01785     }
01786     strcpy (last_str, str);
01787     if (use_config[CONFIG_SPLITINFO] && color != NDI_BLACK) {
01788         if (!draw_info_freeze2){
01789             gtk_text_freeze (GTK_TEXT (gtkwin_info_text2));
01790             draw_info_freeze2=TRUE;
01791         }
01792         if (use_config[CONFIG_TRIMINFO]) {
01793             info2_num_chars += strlen(str) + 1;
01794             /* Limit size of scrollback buffer. To be more efficient, delete a good
01795              * blob (5000) characters at a time - in that way, there will be some
01796              * time between needing to delete.
01797              */
01798             if (info2_num_chars > info2_max_chars ) {
01799                 gtk_text_set_point(GTK_TEXT(gtkwin_info_text2),0);
01800                 gtk_text_forward_delete(GTK_TEXT(gtkwin_info_text2), (info2_num_chars - info2_max_chars) + 5000);
01801                 info2_num_chars = gtk_text_get_length(GTK_TEXT(gtkwin_info_text2));
01802                 gtk_text_set_point(GTK_TEXT(gtkwin_info_text2), info2_num_chars);
01803                 LOG(LOG_INFO,"gtk::draw_info","reduced output buffer2 to %d chars", info1_num_chars);
01804             }
01805         }
01806         if (use_config[CONFIG_TIMESTAMP])
01807             gtk_text_insert(GTK_TEXT (gtkwin_info_text2), NULL, &root_color[NDI_GREY], NULL, timestamp, -1);
01808         gtk_text_insert (GTK_TEXT (gtkwin_info_text2), NULL, &root_color[ncolor], NULL, str, -1);
01809         gtk_text_insert (GTK_TEXT (gtkwin_info_text2), NULL, &root_color[ncolor], NULL, "\n" , -1);
01810 
01811     } else {
01812         /* All notes in the above section apply here also */
01813         if (!draw_info_freeze1){
01814             gtk_text_freeze (GTK_TEXT (gtkwin_info_text));
01815             draw_info_freeze1=TRUE;
01816         }
01817         if (use_config[CONFIG_TRIMINFO]) {
01818             info1_num_chars += strlen(str) + 1;
01819             if (info1_num_chars > info1_max_chars ) {
01820 #if 1
01821                 int to_delete = (info1_num_chars - info1_max_chars) + 5000;
01822                 /* Delete on newline boundaries */
01823                 while (GTK_TEXT_INDEX(GTK_TEXT(gtkwin_info_text), to_delete)!='\n')
01824                     to_delete++;
01825                 gtk_text_set_point(GTK_TEXT(gtkwin_info_text),0);
01826                 gtk_text_forward_delete(GTK_TEXT(gtkwin_info_text), to_delete);
01827                 info1_num_chars = gtk_text_get_length(GTK_TEXT(gtkwin_info_text));
01828                 gtk_text_set_point(GTK_TEXT(gtkwin_info_text), info1_num_chars);
01829                 LOG(LOG_INFO,"gtk::draw_info",
01830                 "trim_info_window, deleted %d characters, %d remaining",
01831                 to_delete, info1_num_chars);
01832 #else
01833                 /* This works, so it is possible to completely clear the window */
01834                 info1_num_chars = gtk_text_get_length(GTK_TEXT (gtkwin_info_text));
01835                 gtk_text_set_point(GTK_TEXT (gtkwin_info_text), 0);
01836                 gtk_text_forward_delete (GTK_TEXT (gtkwin_info_text), info1_num_chars );
01837                 gtk_text_thaw (GTK_TEXT (gtkwin_info_text));
01838                 info1_num_chars=0;
01839 #endif
01840             }
01841 
01842         }
01843         if (use_config[CONFIG_TIMESTAMP])
01844             gtk_text_insert (GTK_TEXT (gtkwin_info_text2), NULL, &root_color[NDI_GREY], NULL, timestamp, -1);
01845         gtk_text_insert (GTK_TEXT (gtkwin_info_text), NULL, &root_color[ncolor], NULL, str , -1);
01846         gtk_text_insert (GTK_TEXT (gtkwin_info_text), NULL, &root_color[ncolor], NULL, "\n" , -1);
01847     }
01848 }
01849 
01850 
01851 void draw_color_info(int colr, const char *buf){
01852         draw_info(buf,colr);
01853 }
01854 
01855 /***********************************************************************
01856  *
01857  * Stats window functions follow
01858  *
01859  ***********************************************************************/
01860 
01861 static int get_stats_display(GtkWidget *frame) {
01862     GtkWidget *stats_vbox;
01863     GtkWidget *stats_box_1;
01864     GtkWidget *stats_box_2;
01865     GtkWidget *stats_box_4;
01866     GtkWidget *stats_box_5;
01867     GtkWidget *stats_box_6;
01868     GtkWidget *stats_box_7;
01869     GtkWidget *table;
01870     int i,x,y;
01871 
01872 
01873     stats_vbox = gtk_vbox_new (FALSE, 0);
01874 
01875     /* 1st row  - Player name */
01876     stats_box_1 = gtk_hbox_new (FALSE, 0);
01877 
01878     statwindow.playername = gtk_label_new("Player: ");
01879     gtk_box_pack_start (GTK_BOX (stats_box_1), statwindow.playername, FALSE, FALSE, 5);
01880     gtk_widget_show (statwindow.playername);
01881 
01882     gtk_box_pack_start (GTK_BOX (stats_vbox), stats_box_1, FALSE, FALSE, 0);
01883     gtk_widget_show (stats_box_1);
01884 
01885     /* 2nd row - score and level */
01886     stats_box_2 = gtk_hbox_new (FALSE, 0);
01887     statwindow.score = gtk_label_new("Score: 0");
01888     gtk_box_pack_start (GTK_BOX (stats_box_2), statwindow.score, FALSE, FALSE, 5);
01889     gtk_widget_show (statwindow.score);
01890 
01891     statwindow.level = gtk_label_new("Level: 0");
01892     gtk_box_pack_start (GTK_BOX (stats_box_2), statwindow.level, FALSE, FALSE, 5);
01893     gtk_widget_show (statwindow.level);
01894 
01895     gtk_box_pack_start (GTK_BOX (stats_vbox), stats_box_2, FALSE, FALSE, 0);
01896     gtk_widget_show (stats_box_2);
01897 
01898 
01899     /* 4th row (really the thrid) - the stats - str, dex, con, etc */
01900     stats_box_4 = gtk_hbox_new (FALSE, 0);
01901 
01902     statwindow.Str = gtk_label_new("S 0");
01903     gtk_box_pack_start (GTK_BOX (stats_box_4), statwindow.Str, FALSE, FALSE, 5);
01904     gtk_widget_show (statwindow.Str);
01905 
01906     statwindow.Dex = gtk_label_new("D 0");
01907     gtk_box_pack_start (GTK_BOX (stats_box_4), statwindow.Dex, FALSE, FALSE, 5);
01908     gtk_widget_show (statwindow.Dex);
01909 
01910     statwindow.Con = gtk_label_new("Co 0");
01911     gtk_box_pack_start (GTK_BOX (stats_box_4), statwindow.Con, FALSE, FALSE, 5);
01912     gtk_widget_show (statwindow.Con);
01913 
01914     statwindow.Int = gtk_label_new("I 0");
01915     gtk_box_pack_start (GTK_BOX (stats_box_4), statwindow.Int, FALSE, FALSE, 5);
01916     gtk_widget_show (statwindow.Int);
01917 
01918     statwindow.Wis = gtk_label_new("W 0");
01919     gtk_box_pack_start (GTK_BOX (stats_box_4), statwindow.Wis, FALSE, FALSE, 5);
01920     gtk_widget_show (statwindow.Wis);
01921 
01922     statwindow.Pow = gtk_label_new("P 0");
01923     gtk_box_pack_start (GTK_BOX (stats_box_4), statwindow.Pow, FALSE, FALSE, 5);
01924     gtk_widget_show (statwindow.Pow);
01925 
01926     statwindow.Cha = gtk_label_new("Ch 0");
01927     gtk_box_pack_start (GTK_BOX (stats_box_4), statwindow.Cha, FALSE, FALSE, 5);
01928     gtk_widget_show (statwindow.Cha);
01929 
01930     gtk_box_pack_start (GTK_BOX (stats_vbox), stats_box_4, FALSE, FALSE, 0);
01931     gtk_widget_show (stats_box_4);
01932 
01933     /* 5th row wc, dam, ac, armor*/
01934 
01935     stats_box_5 = gtk_hbox_new (FALSE, 0);
01936 
01937     statwindow.wc = gtk_label_new("Wc: 0");
01938     gtk_box_pack_start (GTK_BOX (stats_box_5), statwindow.wc, FALSE, FALSE, 5);
01939     gtk_widget_show (statwindow.wc);
01940 
01941     statwindow.dam = gtk_label_new("Dam: 0");
01942     gtk_box_pack_start (GTK_BOX (stats_box_5), statwindow.dam, FALSE, FALSE, 5);
01943     gtk_widget_show (statwindow.dam);
01944 
01945     statwindow.ac = gtk_label_new("Ac: 0");
01946     gtk_box_pack_start (GTK_BOX (stats_box_5), statwindow.ac, FALSE, FALSE, 5);
01947     gtk_widget_show (statwindow.ac);
01948 
01949     statwindow.armor = gtk_label_new("Armor: 0");
01950     gtk_box_pack_start (GTK_BOX (stats_box_5), statwindow.armor, FALSE, FALSE, 5);
01951     gtk_widget_show (statwindow.armor);
01952 
01953     gtk_box_pack_start (GTK_BOX (stats_vbox), stats_box_5, FALSE, FALSE, 0);
01954     gtk_widget_show (stats_box_5);
01955 
01956     /* 6th row speed and weapon speed */
01957 
01958     stats_box_6 = gtk_hbox_new (FALSE, 0);
01959 
01960     statwindow.speed = gtk_label_new("Speed: 0");
01961     gtk_box_pack_start (GTK_BOX (stats_box_6), statwindow.speed, FALSE, FALSE, 5);
01962     gtk_widget_show (statwindow.speed);
01963 
01964     gtk_box_pack_start (GTK_BOX (stats_vbox), stats_box_6, FALSE, FALSE, 0);
01965     gtk_widget_show (stats_box_6);
01966 
01967     /* 7th row - range */
01968 
01969     stats_box_7 = gtk_hbox_new (FALSE, 0);
01970 
01971     statwindow.skill = gtk_label_new("Skill: 0");
01972     gtk_box_pack_start (GTK_BOX (stats_box_7), statwindow.skill, FALSE, FALSE, 5);
01973     gtk_widget_show (statwindow.skill);
01974     gtk_box_pack_start (GTK_BOX (stats_vbox), stats_box_7, FALSE, FALSE, 0);
01975     gtk_widget_show (stats_box_7);
01976 
01977 
01978     /* Start of experience display - we do it in a 4 x 4 array.  Use a table
01979      * so that spacing is uniform - this should look better.
01980      * Change it so we use one field for the name, and the other for exp -
01981      * in this way, the values line up better.
01982      */
01983 
01984     table = gtk_table_new (4, 4, FALSE);
01985     x=0;
01986     y=0;
01987     /* This is all the same - we just pack it in different places */
01988     for (i=0; i<MAX_SKILL*2; i++) {
01989         statwindow.skill_exp[i] = gtk_label_new("");
01990         gtk_table_attach(GTK_TABLE(table), statwindow.skill_exp[i], x, x+1, y, y+1, GTK_FILL  | GTK_EXPAND, 0, 10, 0);
01991         x++;
01992         if (x==4) { x=0; y++; }
01993         gtk_widget_show(statwindow.skill_exp[i]);
01994     }
01995     skill_scrolled_window = gtk_scrolled_window_new (NULL, NULL);
01996     gtk_container_set_border_width (GTK_CONTAINER (res_scrolled_window), 0);
01997     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (skill_scrolled_window),GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
01998     gtk_box_pack_start(GTK_BOX(stats_vbox), skill_scrolled_window, TRUE, TRUE, 0);
01999     gtk_scrolled_window_add_with_viewport ( GTK_SCROLLED_WINDOW (skill_scrolled_window), table);
02000 
02001     gtk_widget_show(table);
02002 
02003     gtk_container_add (GTK_CONTAINER (frame), stats_vbox);
02004     gtk_widget_show (stats_vbox);
02005     gtk_widget_show (skill_scrolled_window);
02006 
02007     return 0;
02008 }
02009 
02010 /* This draws the stats window.  If redraw is true, it means
02011  * we need to redraw the entire thing, and not just do an
02012  * updated.
02013  */
02014 
02015 void draw_stats(int redraw) {
02016   static Stats last_stats;
02017   static char last_name[MAX_BUF]="", last_range[MAX_BUF]="";
02018   static int init_before=0, lastbeep=0, max_drawn_skill=0;
02019 
02020   float weap_sp;
02021   char buff[MAX_BUF];
02022   int i, on_skill;
02023 
02024   if (!init_before) {
02025     init_before=1;
02026     memset(&last_stats, 0, sizeof(Stats));
02027   }
02028 
02029   if (updatelock < 25) {
02030     updatelock++;
02031     if (strcmp(cpl.title, last_name) || redraw) {
02032       strcpy(last_name,cpl.title);
02033       strcpy(buff,cpl.title);
02034       gtk_label_set (GTK_LABEL(statwindow.playername), cpl.title);
02035       gtk_widget_draw (statwindow.playername, NULL);
02036     }
02037 
02038     if(redraw || cpl.stats.exp!=last_stats.exp) {
02039       last_stats.exp = cpl.stats.exp;
02040       sprintf(buff,"Score: %5" FMT64 ,cpl.stats.exp);
02041 
02042       gtk_label_set (GTK_LABEL(statwindow.score), buff);
02043       gtk_widget_draw (statwindow.score, NULL);
02044     }
02045 
02046     if(redraw || cpl.stats.level!=last_stats.level) {
02047       last_stats.level = cpl.stats.level;
02048       sprintf(buff,"Level: %d",cpl.stats.level);
02049       gtk_label_set (GTK_LABEL(statwindow.level), buff);
02050       gtk_widget_draw (statwindow.level, NULL);
02051     }
02052 
02053     if(redraw ||
02054        cpl.stats.hp!=last_stats.hp || cpl.stats.maxhp!=last_stats.maxhp) {
02055       last_stats.hp=cpl.stats.hp;
02056       last_stats.maxhp=cpl.stats.maxhp;
02057       sprintf(buff,"Hp: %d/%d",cpl.stats.hp, cpl.stats.maxhp);
02058       gtk_label_set (GTK_LABEL(statwindow.hp), buff);
02059       gtk_widget_draw (statwindow.hp, NULL);
02060     }
02061 
02062     if(redraw ||
02063        cpl.stats.sp!=last_stats.sp || cpl.stats.maxsp!=last_stats.maxsp) {
02064       last_stats.sp=cpl.stats.sp;
02065       last_stats.maxsp=cpl.stats.maxsp;
02066       sprintf(buff,"Sp: %d/%d",cpl.stats.sp, cpl.stats.maxsp);
02067       gtk_label_set (GTK_LABEL(statwindow.sp), buff);
02068       gtk_widget_draw (statwindow.sp, NULL);
02069     }
02070 
02071     if(redraw ||
02072        cpl.stats.grace!=last_stats.grace || cpl.stats.maxgrace!=last_stats.maxgrace) {
02073       last_stats.grace=cpl.stats.grace;
02074       last_stats.maxgrace=cpl.stats.maxgrace;
02075       sprintf(buff,"Gr: %d/%d",cpl.stats.grace, cpl.stats.maxgrace);
02076       gtk_label_set (GTK_LABEL(statwindow.gr), buff);
02077       gtk_widget_draw (statwindow.gr, NULL);
02078     }
02079 
02080     if(redraw || cpl.stats.Str!=last_stats.Str) {
02081       last_stats.Str=cpl.stats.Str;
02082       sprintf(buff,"S%2d",cpl.stats.Str);
02083       gtk_label_set (GTK_LABEL(statwindow.Str), buff);
02084       gtk_widget_draw (statwindow.Str, NULL);
02085     }
02086 
02087     if(redraw || cpl.stats.Dex!=last_stats.Dex) {
02088       last_stats.Dex=cpl.stats.Dex;
02089       sprintf(buff,"D%2d",cpl.stats.Dex);
02090       gtk_label_set (GTK_LABEL(statwindow.Dex), buff);
02091       gtk_widget_draw (statwindow.Dex, NULL);
02092     }
02093 
02094     if(redraw || cpl.stats.Con!=last_stats.Con) {
02095       last_stats.Con=cpl.stats.Con;
02096       sprintf(buff,"Co%2d",cpl.stats.Con);
02097       gtk_label_set (GTK_LABEL(statwindow.Con), buff);
02098       gtk_widget_draw (statwindow.Con, NULL);
02099     }
02100 
02101     if(redraw || cpl.stats.Int!=last_stats.Int) {
02102       last_stats.Int=cpl.stats.Int;
02103       sprintf(buff,"I%2d",cpl.stats.Int);
02104       gtk_label_set (GTK_LABEL(statwindow.Int), buff);
02105       gtk_widget_draw (statwindow.Int, NULL);
02106     }
02107 
02108     if(redraw || cpl.stats.Wis!=last_stats.Wis) {
02109       last_stats.Wis=cpl.stats.Wis;
02110       sprintf(buff,"W%2d",cpl.stats.Wis);
02111       gtk_label_set (GTK_LABEL(statwindow.Wis), buff);
02112       gtk_widget_draw (statwindow.Wis, NULL);
02113     }
02114 
02115     if(redraw || cpl.stats.Pow!=last_stats.Pow) {
02116       last_stats.Pow=cpl.stats.Pow;
02117       sprintf(buff,"P%2d",cpl.stats.Pow);
02118       gtk_label_set (GTK_LABEL(statwindow.Pow), buff);
02119       gtk_widget_draw (statwindow.Pow, NULL);
02120     }
02121 
02122     if(redraw || cpl.stats.Cha!=last_stats.Cha) {
02123       last_stats.Cha=cpl.stats.Cha;
02124       sprintf(buff,"Ch%2d",cpl.stats.Cha);
02125       gtk_label_set (GTK_LABEL(statwindow.Cha), buff);
02126       gtk_widget_draw (statwindow.Cha, NULL);
02127     }
02128 
02129     if(redraw || cpl.stats.wc!=last_stats.wc) {
02130       last_stats.wc=cpl.stats.wc;
02131       sprintf(buff,"Wc%3d",cpl.stats.wc);
02132       gtk_label_set (GTK_LABEL(statwindow.wc), buff);
02133       gtk_widget_draw (statwindow.wc, NULL);
02134     }
02135 
02136     if(redraw || cpl.stats.dam!=last_stats.dam) {
02137       last_stats.dam=cpl.stats.dam;
02138       sprintf(buff,"Dam%3d",cpl.stats.dam);
02139       gtk_label_set (GTK_LABEL(statwindow.dam), buff);
02140       gtk_widget_draw (statwindow.dam, NULL);
02141     }
02142 
02143     if(redraw || cpl.stats.ac!=last_stats.ac) {
02144       last_stats.ac=cpl.stats.ac;
02145       sprintf(buff,"Ac%3d",cpl.stats.ac);
02146       gtk_label_set (GTK_LABEL(statwindow.ac), buff);
02147       gtk_widget_draw (statwindow.ac, NULL);
02148     }
02149 
02150     if(redraw || cpl.stats.resists[0]!=last_stats.resists[0]) {
02151       last_stats.resists[0]=cpl.stats.resists[0];
02152       sprintf(buff,"Arm%3d",cpl.stats.resists[0]);
02153       gtk_label_set (GTK_LABEL(statwindow.armor), buff);
02154       gtk_widget_draw (statwindow.armor, NULL);
02155     }
02156 
02157     if(redraw || cpl.stats.speed!=last_stats.speed ||
02158        cpl.stats.weapon_sp != last_stats.weapon_sp) {
02159       last_stats.speed=cpl.stats.speed;
02160       last_stats.weapon_sp=cpl.stats.weapon_sp;
02161       weap_sp = (float) cpl.stats.speed/((float)cpl.stats.weapon_sp);
02162       sprintf(buff,"Speed: %3.2f (%1.2f)",(float)cpl.stats.speed/FLOAT_MULTF,weap_sp);
02163       gtk_label_set (GTK_LABEL(statwindow.speed), buff);
02164       gtk_widget_draw (statwindow.speed, NULL);
02165     }
02166 
02167     if(redraw || cpl.stats.food!=last_stats.food) {
02168       last_stats.food=cpl.stats.food;
02169       sprintf(buff,"Food: %3d",cpl.stats.food);
02170       gtk_label_set (GTK_LABEL(statwindow.food), buff);
02171       gtk_widget_draw (statwindow.food, NULL);
02172       if (use_config[CONFIG_FOODBEEP] && (cpl.stats.food%4==3) && (cpl.stats.food < 200))
02173 #ifndef WIN32
02174         XBell(GDK_DISPLAY(), 0);
02175 #else
02176             gdk_beep( );
02177 #endif
02178     } else if (use_config[CONFIG_FOODBEEP] && cpl.stats.food == 0 && ++lastbeep == 5) {
02179         lastbeep = 0;
02180 #ifndef WIN32
02181     XBell(GDK_DISPLAY(), 0);
02182 #else
02183     gdk_beep( );
02184 #endif
02185     }
02186 
02187     if(redraw || strcmp(cpl.range, last_range)) {
02188       strcpy(last_range, cpl.range);
02189       gtk_label_set (GTK_LABEL(statwindow.skill), cpl.range);
02190       gtk_widget_draw (statwindow.skill, NULL);
02191     }
02192     on_skill=0;
02193     for (i=0; i<MAX_SKILL; i++) {
02194         /* Drawing a particular skill entry is tricky - only draw if
02195          * different, and only draw if we have a name for the skill
02196          * and the player has some exp in the skill - don't draw
02197          * all 30 skills for no reason.
02198          */
02199         if ((redraw || cpl.stats.skill_exp[i] != last_stats.skill_exp[i]) &&
02200             skill_names[i] && cpl.stats.skill_level[i]) {
02201             gtk_label_set(GTK_LABEL(statwindow.skill_exp[on_skill++]), skill_names[i]);
02202             sprintf(buff,"%" FMT64 " (%d)", cpl.stats.skill_exp[i], cpl.stats.skill_level[i]);
02203             gtk_label_set(GTK_LABEL(statwindow.skill_exp[on_skill++]), buff);
02204             last_stats.skill_level[i] = cpl.stats.skill_level[i];
02205             last_stats.skill_exp[i] = cpl.stats.skill_exp[i];
02206         } else if (cpl.stats.skill_level[i]) {
02207             /* Don't need to draw the skill, but need to update the position
02208              * of where to draw the next one.
02209              */
02210             on_skill+=2;
02211         }
02212     }
02213     /* Since the number of skills we draw come and go, basically we want
02214      * to erase any extra.  This shows up when switching characters, eg, character
02215      * #1 knows 10 skills, #2 knows 5 - need to erase those 5 extra.
02216      */
02217     if (on_skill < max_drawn_skill) {
02218         int k;
02219 
02220         for (k = on_skill; k <= max_drawn_skill; k++)
02221             gtk_label_set(GTK_LABEL(statwindow.skill_exp[k]), "");
02222     }
02223     max_drawn_skill = on_skill;
02224   } /* updatelock < 25 */
02225 }
02226 
02227 
02228 /***********************************************************************
02229 *
02230 * Handles the message window
02231 *
02232 ***********************************************************************/
02233 
02234 
02235 static void create_stat_bar(GtkWidget *mtable, gint row, const gchar *label, gint bar, GtkWidget **plabel) {
02236   /*  GtkWidget *plabel;*/
02237 
02238   *plabel = gtk_label_new (label);
02239   gtk_table_attach (GTK_TABLE (mtable), *plabel, 0, 1, row, row+1,/*GTK_FILL |*/ GTK_EXPAND,GTK_FILL | GTK_EXPAND,0,0);
02240   gtk_widget_show (*plabel);
02241 
02242   vitals[bar].bar = gtk_progress_bar_new ();
02243   gtk_table_attach(GTK_TABLE(mtable), vitals[bar].bar, 0,1,row+1,row+2,GTK_FILL | GTK_EXPAND, 0 ,3,0);
02244   gtk_widget_set_usize (vitals[bar].bar,100,15);
02245 
02246 
02247   gtk_widget_show (vitals[bar].bar);
02248 
02249 
02250 
02251   vitals[bar].state=1;
02252 
02253   vitals[bar].style[0] = gtk_style_new ();
02254   vitals[bar].style[0]->bg[GTK_STATE_PRELIGHT] = gdk_green;
02255   gtk_widget_set_style (vitals[bar].bar, vitals[bar].style[0]);
02256   vitals[bar].style[1] = gtk_style_new ();
02257   vitals[bar].style[1]->bg[GTK_STATE_PRELIGHT] = gdk_red;
02258 
02259 }
02260 
02261 /* This is used when going from gradiated color stat bars back
02262  * to the normal - we need to reset the colors.
02263  */
02264 void reset_stat_bars(void) {
02265     int i;
02266 
02267     for (i=0; i<4; i++) {
02268         vitals[i].style[0]->bg[GTK_STATE_PRELIGHT] = gdk_green;
02269         vitals[i].style[1]->bg[GTK_STATE_PRELIGHT] = gdk_red;
02270         /* Need to do this double switch so that the color gets updated. Otherwise,
02271          * if we are currently using style[0] to draw, the update above won't
02272          * have any effect.
02273          */
02274         gtk_widget_set_style(vitals[i].bar, vitals[i].style[1]);
02275         gtk_widget_set_style(vitals[i].bar, vitals[i].style[0]);
02276         vitals[i].state = 0;
02277 
02278     }
02279     draw_message_window(1);
02280 }
02281 
02282 static int get_message_display(GtkWidget *frame) {
02283     GtkWidget *mtable;
02284     GtkWidget *vbox;
02285     GtkWidget *res_mainbox;
02286     GtkWidget *reswindow;
02287 
02288     /* Initialize the main hbox */
02289     res_mainbox = gtk_hbox_new (TRUE,0);
02290     gtk_container_add (GTK_CONTAINER(frame), res_mainbox);
02291 
02292     /* stat bar part - start */
02293 
02294     /* Initialize the vbox for the stat bars (Hp,Mana,Grace,Food)
02295      * and pack it into the main hbox
02296      */
02297     vbox = gtk_vbox_new (FALSE, 0);
02298     gtk_box_pack_start (GTK_BOX(res_mainbox), vbox, FALSE, TRUE, 0);
02299 
02300     /* Initialize the table and pack this into the vbox */
02301     mtable = gtk_table_new (2,4,FALSE);
02302     gtk_box_pack_start (GTK_BOX(vbox),mtable,FALSE,FALSE,0);
02303 
02304     /* Create the stat bars and place them in the table */
02305     create_stat_bar (mtable, 1,"Hp: 0",0, &statwindow.hp);
02306     create_stat_bar (mtable, 3,"Mana: 0",1, &statwindow.sp);
02307     create_stat_bar (mtable, 5,"Grace: 0",2, &statwindow.gr);
02308     create_stat_bar (mtable, 7,"Food: 0",3, &statwindow.food);
02309 
02310     /* Stat bar part - end */
02311 
02312 
02313     /* Resistances table part - start */
02314 
02315     /* Initialize the hbox for the resistances table */
02316     reswindow = gtk_hbox_new (TRUE, 0);
02317     gtk_box_pack_start(GTK_BOX(res_mainbox), reswindow, FALSE, TRUE, 0);
02318 
02319     /* Create the resistance table*/
02320     restable = gtk_table_new (4,12,FALSE);
02321 
02322     /* Packing the restable in a scrollable window*/
02323     res_scrolled_window = gtk_scrolled_window_new (NULL, NULL);
02324     gtk_container_set_border_width (GTK_CONTAINER (res_scrolled_window), 0);
02325     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (res_scrolled_window),
02326         GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
02327     gtk_box_pack_start(GTK_BOX(reswindow), res_scrolled_window, TRUE, TRUE, 0);
02328     gtk_widget_show (res_scrolled_window);
02329     gtk_scrolled_window_add_with_viewport ( GTK_SCROLLED_WINDOW (res_scrolled_window), restable);
02330 
02331     /* Finally, draw the resistances table */
02332     resize_resistance_table(use_config[CONFIG_RESISTS]);
02333 
02334     /* Resistances table part - end */
02335 
02336     /* Now showing all not already showed widgets */
02337     gtk_widget_show (res_mainbox);
02338     gtk_widget_show (reswindow);
02339     gtk_widget_show (restable);
02340     gtk_widget_show (mtable);
02341     gtk_widget_show (vbox);
02342     return 0;
02343 }
02344 
02345 /* This handles layout of the resistance window.
02346  * We end up just removing (and thus freeing) all the data and
02347  * then create new entries.  This keeps things simpler, because
02348  * in basic mode, not all the resist[] widgets are attached,
02349  */
02350 void resize_resistance_table(int resists_show) {
02351     int i, left=0, right=0;
02352 
02353     while (GTK_TABLE(restable)->children) {
02354         GtkTableChild *child;
02355         child = GTK_TABLE(restable)->children->data;
02356 
02357         gtk_container_remove(GTK_CONTAINER(restable),
02358                              child->widget);
02359     }
02360 
02361     /* Initialize labels for all modes of CONFIG_RESISTS */
02362     fire_label = gtk_label_new ("    ");
02363     run_label = gtk_label_new ("   ");
02364 
02365     /* Place labels for dual-column mode of CONFIG_RESISTS */
02366     if (resists_show) {
02367         gtk_table_resize(GTK_TABLE(restable), 4,12);
02368         gtk_table_attach (GTK_TABLE(restable), fire_label, 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
02369         gtk_table_attach (GTK_TABLE(restable), run_label, 3, 4, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
02370     }
02371     else { /* Single column mode */
02372         gtk_table_resize(GTK_TABLE(restable), 2,24);
02373         gtk_table_attach (GTK_TABLE(restable), fire_label, 0, 1, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
02374         gtk_table_attach (GTK_TABLE(restable), run_label, 1, 2, 0, 1, GTK_FILL | GTK_EXPAND, 0, 0, 0);
02375     }
02376     /* Show labels for all modes of CONFIG_RESISTS */
02377     gtk_widget_show (fire_label);
02378     gtk_widget_show (run_label);
02379     /* Make and place labels for showing the resistances - start */
02380 
02381     for (i=0; i< NUM_RESISTS; i++) {
02382         resists[i] = gtk_label_new("          ");
02383 
02384         /* Place the labels for dual columns in the table restable */
02385         if (resists_show) {
02386             if ((i/2)*2 != i) {
02387                 left++;
02388                 gtk_table_attach (GTK_TABLE(restable), resists[i], 1, 2, 3+left, 4+left, GTK_FILL | GTK_EXPAND, 0, 0, 0);
02389             } else {
02390                 right++;
02391                 gtk_table_attach (GTK_TABLE(restable), resists[i], 3, 4, 3+right, 4+right, GTK_FILL | GTK_EXPAND, 0, 0, 0);
02392             }
02393             gtk_widget_show (resists[i]);
02394         }
02395         else { /* Single column style */
02396             gtk_table_attach (GTK_TABLE(restable), resists[i], 0, 2, 3+i, 4+i, GTK_FILL | GTK_EXPAND, 0, 0, 0);
02397             gtk_widget_show (resists[i]);
02398         }
02399     }
02400     gtk_scrolled_window_set_policy (GTK_SCROLLED_WINDOW (res_scrolled_window),GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
02401 }
02402 
02403 static void draw_stat_bar(int bar_pos, float bar, int is_alert)
02404 {
02405     if (use_config[CONFIG_GRAD_COLOR]) {
02406         /* In this mode, the color of the stat bar were go between red and green
02407          * in a gradual style.  This, at 50% of the value, the stat bar will be
02408          * drawn in yellow.  Pure fluff I know.
02409          */
02410         int nstyle;
02411         GdkColor ncolor;
02412         /* We need to figure out what style to use.  We can't call gtk_widget_set_style
02413          * on the widget currently in use - doing so results in no effect.
02414          * 53247 is float value of 0xcfff, which is the value used in the gdk_red
02415          * and gdk_green values.  We double the values, so that it scales properly -
02416          * at .5, it then matches 53247, so the scaling appears proper.
02417          */
02418         if (gtk_widget_get_style(vitals[bar_pos].bar) == vitals[bar_pos].style[0]) nstyle=1;
02419         else nstyle=0;
02420         /* We are 'supercharged' - scale to max of 2.0 for pure blue */
02421         if (bar > 1.0) {
02422             if (bar>2.0) bar=2.0;   /* Doesn't affect display, just are calculations */
02423             ncolor.blue = 65535.0 * (bar - 1.0);
02424             ncolor.green = 53247.0 * (2.0 - bar);
02425             ncolor.red = 0;
02426             bar=1.0;
02427         } else {
02428             /* Use 0.5 as the adjustment - basically, if greater than 0.5,
02429              * we have pure green with lesser amounts of red.  If less than
02430              * 0.5, we have pure red with lesser amounts of green.
02431              */
02432             if (bar < 0.0) bar=0.0;  /* Like above, doesn't affect display */
02433             if (bar >= 0.5) ncolor.green = 0xcfff;
02434             else ncolor.green = 106494.0 * bar;
02435             if (bar <= 0.5) ncolor.red = 0xcfff;
02436             else ncolor.red = 106494.0 * (1.0 - bar);
02437             ncolor.blue = 0;
02438         }
02439         vitals[bar_pos].style[nstyle]->bg[GTK_STATE_PRELIGHT] = ncolor;
02440         gtk_widget_set_style(vitals[bar_pos].bar, vitals[bar_pos].style[nstyle]);
02441         vitals[bar_pos].state=is_alert;
02442     } else {
02443         if (bar>1.0) bar=1.0;
02444         if (is_alert) is_alert=1;       /* Safety check */
02445         if (vitals[bar_pos].state!=is_alert) {
02446             gtk_widget_set_style (vitals[bar_pos].bar, vitals[bar_pos].style[is_alert]);
02447             vitals[bar_pos].state=is_alert;
02448         }
02449     }
02450     gtk_progress_bar_update (GTK_PROGRESS_BAR (vitals[bar_pos].bar),bar );
02451     gtk_widget_draw (vitals[bar_pos].bar, NULL);
02452 }
02453 
02454 /* This updates the status bars.  If redraw, then redraw them
02455  * even if they have not changed
02456  */
02457 
02458 void draw_message_window(int redraw) {
02459     float bar;
02460     int is_alert,flags;
02461     static uint16 scrollsize_hp=0, scrollsize_sp=0, scrollsize_food=0,
02462         scrollsize_grace=0;
02463     static uint8 scrollhp_alert=FALSE, scrollsp_alert=FALSE,
02464         scrollfood_alert=FALSE, scrollgrace_alert=FALSE;
02465 
02466     if (updatelock < 25) {
02467         updatelock++;
02468         /* Draw hp bar */
02469         if(cpl.stats.maxhp>0)
02470         {
02471             bar=(float)cpl.stats.hp/cpl.stats.maxhp;
02472             if(bar<=0)
02473                 bar=(float)0.01;
02474             is_alert=(cpl.stats.hp <= cpl.stats.maxhp/4);
02475         }
02476         else
02477         {
02478             bar=(float)0.01;
02479             is_alert=0;
02480         }
02481 
02482         if (redraw || scrollsize_hp!=bar || scrollhp_alert!=is_alert)
02483             draw_stat_bar(0, bar, is_alert);
02484 
02485         scrollsize_hp=bar;
02486         scrollhp_alert=is_alert;
02487 
02488         /* Draw sp bar.  Let draw_stats_bar handle high values */
02489         bar=(float)cpl.stats.sp/cpl.stats.maxsp;
02490         if(bar<=0)
02491             bar=(float)0.01;
02492 
02493         is_alert=(cpl.stats.sp <= cpl.stats.maxsp/4);
02494 
02495         if (redraw || scrollsize_sp!=bar || scrollsp_alert!=is_alert)
02496             draw_stat_bar(1, bar, is_alert);
02497 
02498         scrollsize_sp=bar;
02499         scrollsp_alert=is_alert;
02500 
02501         /* Draw grace bar. Grace can go above max or below min */
02502         bar=(float)cpl.stats.grace/cpl.stats.maxgrace;
02503         if(bar<=0)
02504             bar=(float)0.01;
02505 
02506         is_alert=(cpl.stats.grace <= cpl.stats.maxgrace/4);
02507 
02508         if (redraw || scrollsize_grace!=bar || scrollgrace_alert!=is_alert)
02509             draw_stat_bar(2, bar, is_alert);
02510 
02511         scrollsize_grace=bar;
02512         scrollgrace_alert=is_alert;
02513 
02514         /* Draw food bar */
02515         bar=(float)cpl.stats.food/999;
02516         if(bar<=0)
02517             bar=(float)0.01;
02518         is_alert=(cpl.stats.food <= 999/4);
02519 
02520         if (redraw || scrollsize_food!=bar || scrollfood_alert!=is_alert)
02521             draw_stat_bar(3, bar, is_alert);
02522 
02523         scrollsize_food=bar;
02524         scrollfood_alert=is_alert;
02525 
02526         flags = cpl.stats.flags;
02527 
02528         if (redraw || cpl.stats.resist_change) {
02529             int i,j=0;
02530             char buf[40];
02531 
02532             cpl.stats.resist_change=0;
02533             for (i=0; i<NUM_RESISTS; i++) {
02534                 if (cpl.stats.resists[i]) {
02535                     sprintf(buf,"%-10s %+4d",
02536                         resists_name[i], cpl.stats.resists[i]);
02537                     gtk_label_set(GTK_LABEL(resists[j]), buf);
02538                     gtk_widget_draw(resists[j], NULL);
02539                     j++;
02540                     if (j >= NUM_RESISTS) break;
02541                 }
02542             }
02543             /* Erase old/unused resistances */
02544             while (j<NUM_RESISTS) {
02545                 gtk_label_set(GTK_LABEL(resists[j]), "              ");
02546                 gtk_widget_draw(resists[j], NULL);
02547                 j++;
02548             }
02549         } /* if we draw the resists */
02550     }
02551     else {
02552         /*    printf ("WARNING -- RACE. Frozen updates until updatelock is cleared!\n");*/
02553     }
02554 }
02555 
02556 
02557 
02558 
02559 
02560 
02561 
02562 /****************************************************************************
02563  *
02564  * Dialogue boxes and the menus that raise them.
02565  *
02566  ****************************************************************************/
02567 
02568 static void aboutdialog(GtkWidget *widget) {
02569 #include "help/about.h"
02570   GtkWidget *vbox;
02571   GtkWidget *hbox;
02572   GtkWidget *aboutlabel;
02573   GtkWidget *vscrollbar;
02574   GtkWidget *aboutbutton;
02575   GtkWidget *aboutgtkpixmap;
02576   GdkPixmap *aboutgdkpixmap;
02577   GdkBitmap *aboutgdkmask;
02578 
02579   GtkStyle *style;
02580 
02581   if(!gtkwin_about) {
02582 
02583     gtkwin_about = gtk_window_new (GTK_WINDOW_DIALOG);
02584     gtk_window_position (GTK_WINDOW (gtkwin_about), GTK_WIN_POS_CENTER);
02585     gtk_widget_set_usize (gtkwin_about,500,210);
02586     gtk_window_set_title (GTK_WINDOW (gtkwin_about), "About Crossfire");
02587 
02588     gtk_signal_connect (GTK_OBJECT (gtkwin_about), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &gtkwin_about);
02589 
02590     gtk_container_border_width (GTK_CONTAINER (gtkwin_about), 0);
02591     vbox = gtk_vbox_new(FALSE, 2);
02592     gtk_container_add (GTK_CONTAINER(gtkwin_about),vbox);
02593     style = gtk_widget_get_style(gtkwin_about);
02594     gtk_widget_realize(gtkwin_about);
02595     aboutgdkpixmap = gdk_pixmap_create_from_xpm_d(gtkwin_about->window,
02596                                                   &aboutgdkmask,
02597                                                   &style->bg[GTK_STATE_NORMAL],
02598                                                   (gchar **)crossfiretitle_xpm);
02599     aboutgtkpixmap= gtk_pixmap_new (aboutgdkpixmap, aboutgdkmask);
02600     gtk_box_pack_start (GTK_BOX (vbox),aboutgtkpixmap, FALSE, TRUE, 0);
02601     gtk_widget_show (aboutgtkpixmap);
02602 
02603     hbox = gtk_hbox_new(FALSE, 2);
02604     gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
02605 
02606     aboutlabel = gtk_text_new (NULL, NULL);
02607     gtk_text_set_editable (GTK_TEXT (aboutlabel), FALSE);
02608     gtk_box_pack_start (GTK_BOX (hbox),aboutlabel, TRUE, TRUE, 0);
02609     gtk_widget_show (aboutlabel);
02610 
02611     vscrollbar = gtk_vscrollbar_new (GTK_TEXT (aboutlabel)->vadj);
02612     gtk_box_pack_start (GTK_BOX (hbox),vscrollbar, FALSE, FALSE, 0);
02613 
02614     gtk_widget_show (vscrollbar);
02615 
02616     gtk_widget_show (hbox);
02617 
02618     hbox = gtk_hbox_new(FALSE, 2);
02619 
02620     aboutbutton = gtk_button_new_with_label ("Close");
02621     gtk_signal_connect_object (GTK_OBJECT (aboutbutton), "clicked",
02622                                GTK_SIGNAL_FUNC(gtk_widget_destroy),
02623                                GTK_OBJECT (gtkwin_about));
02624     gtk_box_pack_start (GTK_BOX (hbox), aboutbutton, TRUE, FALSE, 0);
02625     gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
02626     gtk_widget_show (aboutbutton);
02627     gtk_widget_show (hbox);
02628 
02629     gtk_widget_show (vbox);
02630     gtk_widget_show (gtkwin_about);
02631     gtk_text_insert (GTK_TEXT (aboutlabel), NULL, &aboutlabel->style->black,
02632                      NULL, VERSION_INFO , -1);
02633     gtk_text_insert (GTK_TEXT (aboutlabel), NULL, &aboutlabel->style->black,
02634                      NULL, text , -1);
02635     gtk_adjustment_set_value(GTK_TEXT(aboutlabel)->vadj, 0.0);
02636   }
02637   else {
02638     gdk_window_raise (gtkwin_about->window);
02639   }
02640 }
02641 
02642 static void createBugTracker(void) {
02643     if (bugtrack ==NULL){
02644         LogEntry* le;
02645         bugtrack = gtk_text_new (NULL, NULL);
02646         gtk_signal_connect (GTK_OBJECT (bugtrack), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &bugtrack);
02647         gtk_text_set_editable (GTK_TEXT (bugtrack), FALSE);
02648         gtk_text_insert (GTK_TEXT (bugtrack), NULL, &bugtrack->style->black,NULL, "MESSAGES TRACK:\n" , -1);
02649         for (le=LogFirst;le;le=le->next)
02650             gtk_text_insert (GTK_TEXT (bugtrack), NULL, &bugtrack->style->black,NULL, getLogText(le) , -1);
02651 
02652     }
02653 }
02654 
02655 static void bugdialog(GtkWidget *widget) {
02656 #include "help/bugreport.h"
02657   GtkWidget *vbox;
02658   GtkWidget *hbox;
02659   GtkWidget *buglabel;
02660   GtkWidget *vscrollbar;
02661   GtkWidget *bugbutton;
02662   GtkWidget *buggtkpixmap;
02663   GdkPixmap *buggdkpixmap;
02664   GdkBitmap *buggdkmask;
02665 
02666   GtkStyle *style;
02667 #ifndef CFGTK2
02668   GdkFont* font;
02669 #endif
02670 
02671   if(!gtkwin_bug) {
02672 
02673     gtkwin_bug = gtk_window_new (GTK_WINDOW_DIALOG);
02674     gtk_window_position (GTK_WINDOW (gtkwin_bug), GTK_WIN_POS_CENTER);
02675     gtk_widget_set_usize (gtkwin_bug,500,450);
02676     gtk_window_set_title (GTK_WINDOW (gtkwin_bug), "Report a bug in Crossfire");
02677 
02678     gtk_signal_connect (GTK_OBJECT (gtkwin_bug), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &gtkwin_bug);
02679     /*gtk_signal_connect (GTK_OBJECT (gtkwin_bug), "destroy", GTK_SIGNAL_FUNC(bugreportdestroy), &gtkwin_bug);*/
02680 
02681     gtk_container_border_width (GTK_CONTAINER (gtkwin_bug), 0);
02682     vbox = gtk_vbox_new(FALSE, 2);
02683     gtk_container_add (GTK_CONTAINER(gtkwin_bug),vbox);
02684     style = gtk_widget_get_style(gtkwin_bug);
02685     gtk_widget_realize(gtkwin_bug);
02686     buggdkpixmap = gdk_pixmap_create_from_xpm_d(gtkwin_bug->window,
02687                                                   &buggdkmask,
02688                                                   &style->bg[GTK_STATE_NORMAL],
02689                                                   (gchar **)crossfiretitle_xpm);
02690     buggtkpixmap= gtk_pixmap_new (buggdkpixmap, buggdkmask);
02691     gtk_box_pack_start (GTK_BOX (vbox),buggtkpixmap, FALSE, TRUE, 0);
02692     gtk_widget_show (buggtkpixmap);
02693 
02694     hbox = gtk_hbox_new(FALSE, 2);
02695     gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
02696 
02697     buglabel = gtk_text_new (NULL, NULL);
02698     gtk_widget_set_style(buglabel,style);
02699     /*GtkStyle*   gtk_widget_get_style            (GtkWidget *widget);*/
02700     gtk_text_set_editable (GTK_TEXT (buglabel), FALSE);
02701     gtk_box_pack_start (GTK_BOX (hbox),buglabel, TRUE, TRUE, 0);
02702     gtk_widget_show (buglabel);
02703 
02704     vscrollbar = gtk_vscrollbar_new (GTK_TEXT (buglabel)->vadj);
02705     gtk_box_pack_start (GTK_BOX (hbox),vscrollbar, FALSE, FALSE, 0);
02706 
02707     gtk_widget_show (vscrollbar);
02708 
02709     gtk_widget_show (hbox);
02710     hbox = gtk_hbox_new(FALSE, 2);
02711     createBugTracker();
02712 #ifndef CFGTK2
02713     /* Win32 uses GTK2, this apparently doesn't work... */
02714     font = gdk_font_load ("-*-fixed-*-*-*-*-12-*-*-*-*-*-*-*");
02715     if (font){
02716         style = gtk_style_copy(gtk_widget_get_style (bugtrack));
02717         gdk_font_unref(style->font);
02718         style->font=font; /*no ref since transfert*/
02719         font=NULL;
02720         gtk_widget_set_style(bugtrack,style);
02721     }
02722 #endif
02723     gtk_box_pack_start (GTK_BOX (hbox),bugtrack, TRUE, TRUE, 0);
02724     gtk_widget_show (bugtrack);
02725     vscrollbar = gtk_vscrollbar_new (GTK_TEXT (bugtrack)->vadj);
02726     gtk_box_pack_start (GTK_BOX (hbox),vscrollbar, FALSE, FALSE, 0);
02727     gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
02728     gtk_widget_show (vscrollbar);
02729     gtk_widget_show (hbox);
02730     hbox = gtk_hbox_new(FALSE, 2);
02731     bugbutton = gtk_button_new_with_label ("Close");
02732     gtk_signal_connect_object (GTK_OBJECT (bugbutton), "clicked",
02733                                GTK_SIGNAL_FUNC(gtk_widget_destroy),
02734                                GTK_OBJECT (gtkwin_bug));
02735     gtk_box_pack_start (GTK_BOX (hbox), bugbutton, TRUE, FALSE, 0);
02736     gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
02737     gtk_widget_show (bugbutton);
02738     gtk_widget_show (hbox);
02739 
02740     gtk_widget_show (vbox);
02741     gtk_widget_show (gtkwin_bug);
02742     gtk_text_insert (GTK_TEXT (buglabel), NULL, &buglabel->style->black,
02743                      NULL, VERSION_INFO , -1);
02744     gtk_text_insert (GTK_TEXT (buglabel), NULL, &buglabel->style->black,
02745                      NULL, text , -1);
02746 
02747     gtk_text_insert (GTK_TEXT (buglabel), NULL, &buglabel->style->black,
02748                      NULL, "\n\nVersion Information\n" , -1);
02749 
02750 
02751     gtk_adjustment_set_value(GTK_TEXT(buglabel)->vadj, 0.0);
02752   }
02753   else {
02754     gdk_window_raise (gtkwin_bug->window);
02755   }
02756 }
02757 
02758 void cclist_button_event(GtkWidget *gtklist, gint row, gint column, GdkEventButton *event) {
02759   gchar *buf;
02760   if (event->button==1) {
02761     gtk_clist_get_text (GTK_CLIST(cclist), row, 0, &buf);
02762     gtk_label_set (GTK_LABEL(cnumentrytext), buf);
02763     gtk_clist_get_text (GTK_CLIST(cclist), row, 1, &buf);
02764     gtk_entry_set_text (GTK_ENTRY(ckeyentrytext), buf);
02765     gtk_clist_get_text (GTK_CLIST(cclist), row, 3, &buf);
02766     gtk_entry_set_text (GTK_ENTRY(cmodentrytext), buf);
02767     gtk_clist_get_text (GTK_CLIST(cclist), row, 4, &buf);
02768     gtk_entry_set_text (GTK_ENTRY(ckentrytext), buf);
02769   }
02770 }
02771 
02772 
02773 void disconnect(GtkWidget *widget) {
02774 #ifdef WIN32
02775     closesocket(csocket.fd);
02776 #else
02777     close(csocket.fd);
02778 #endif
02779     csocket.fd = -1;
02780     if (csocket_fd) {
02781         gdk_input_remove(csocket_fd);
02782         csocket_fd=0;
02783         gtk_main_quit();
02784     }
02785     cleanup_textmanagers();
02786 }
02787 
02788 /* Ok, simplistic help system. Just put the text file up in a scrollable window */
02789 
02790 static void shelpdialog(GtkWidget *widget) {
02791 #include "help/shelp.h"
02792   GtkWidget *vbox;
02793   GtkWidget *hbox;
02794   GtkWidget *shelptext;
02795   GtkWidget *helpbutton;
02796   GtkWidget *vscrollbar;
02797   /*  GtkStyle *style;*/
02798 
02799   if(!gtkwin_shelp) {
02800 
02801     gtkwin_shelp = gtk_window_new (GTK_WINDOW_DIALOG);
02802     gtk_window_position (GTK_WINDOW (gtkwin_shelp), GTK_WIN_POS_CENTER);
02803     gtk_widget_set_usize (gtkwin_shelp,400,300);
02804     gtk_window_set_title (GTK_WINDOW (gtkwin_shelp), "Crossfire Server Help");
02805     gtk_window_set_policy (GTK_WINDOW (gtkwin_shelp), TRUE, TRUE, FALSE);
02806 
02807     gtk_signal_connect (GTK_OBJECT (gtkwin_shelp), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &gtkwin_shelp);
02808 
02809     gtk_container_border_width (GTK_CONTAINER (gtkwin_shelp), 0);
02810     vbox = gtk_vbox_new(FALSE, 2);
02811     gtk_container_add (GTK_CONTAINER(gtkwin_shelp),vbox);
02812     hbox = gtk_hbox_new(FALSE, 2);
02813     gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
02814 
02815     shelptext = gtk_text_new (NULL, NULL);
02816     gtk_text_set_editable (GTK_TEXT (shelptext), FALSE);
02817     gtk_box_pack_start (GTK_BOX (hbox),shelptext, TRUE, TRUE, 0);
02818     gtk_widget_show (shelptext);
02819 
02820     vscrollbar = gtk_vscrollbar_new (GTK_TEXT (shelptext)->vadj);
02821     gtk_box_pack_start (GTK_BOX (hbox),vscrollbar, FALSE, FALSE, 0);
02822 
02823     gtk_widget_show (vscrollbar);
02824     gtk_widget_show (hbox);
02825 
02826     hbox = gtk_hbox_new(FALSE, 2);
02827 
02828     helpbutton = gtk_button_new_with_label ("Close");
02829     gtk_signal_connect_object (GTK_OBJECT (helpbutton), "clicked",
02830                                GTK_SIGNAL_FUNC(gtk_widget_destroy),
02831                                GTK_OBJECT (gtkwin_shelp));
02832     gtk_box_pack_start (GTK_BOX (hbox), helpbutton, TRUE, FALSE, 0);
02833     gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
02834     gtk_widget_show (helpbutton);
02835     gtk_widget_show (hbox);
02836 
02837     gtk_widget_show (vbox);
02838     gtk_widget_show (gtkwin_shelp);
02839     gtk_text_insert (GTK_TEXT (shelptext), NULL, &shelptext->style->black, NULL, text , -1);
02840   }
02841   else {
02842     gdk_window_raise (gtkwin_shelp->window);
02843   }
02844 }
02845 
02846 /* Various routines for setting modes by menu choices. */
02847 static void new_menu_pickup(GtkWidget *button, int val)
02848 {
02849   char modestr[128];
02850   unsigned int old_pickup = pickup_mode;
02851 
02852   /* widget is GtkCheckMenuItem */
02853   if(GTK_CHECK_MENU_ITEM (button)->active) {
02854       pickup_mode=pickup_mode|val;
02855       if (val != PU_NEWMODE)
02856           pickup_mode = pickup_mode | PU_NEWMODE;
02857   } else pickup_mode=pickup_mode&~val;
02858 
02859 
02860   if (old_pickup == pickup_mode)
02861       return;
02862 
02863 #if 0
02864   fprintf(stderr,"val=0x%8x\n",val);
02865   fprintf(stderr,"mode=0x%8x\n",pmode);
02866 #endif
02867 
02868   sprintf(modestr,"bind pickup %u",pickup_mode);
02869   draw_info("To set this pickup mode to a key, use:",NDI_BLACK);
02870   draw_info(modestr,NDI_BLACK);
02871   sprintf(modestr,"pickup %u",pickup_mode);
02872   send_command(modestr, -1, 0);
02873 }
02874 
02875 
02876 static void menu_pickup0(void) {
02877   pickup_mode = 0;
02878   send_command("pickup 0", -1, 0);
02879 }
02880 
02881 static void menu_pickup1(void) {
02882   pickup_mode = 1;
02883   send_command("pickup 1", -1, 0);
02884 }
02885 
02886 static void menu_pickup2(void) {
02887   pickup_mode = 2;
02888   send_command("pickup 2", -1, 0);
02889 }
02890 
02891 static void menu_pickup3(void) {
02892   pickup_mode = 3;
02893   send_command("pickup 3", -1, 0);
02894 }
02895 
02896 static void menu_pickup4(void) {
02897   pickup_mode = 4;
02898   send_command("pickup 4", -1, 0);
02899 }
02900 
02901 static void menu_pickup5(void) {
02902   pickup_mode = 5;
02903   send_command("pickup 5", -1, 0);
02904 
02905 }
02906 
02907 static void menu_pickup6(void) {
02908   pickup_mode = 6;
02909   send_command("pickup 6", -1, 0);
02910 }
02911 
02912 static void menu_pickup7(void) {
02913   pickup_mode = 7;
02914   send_command("pickup 7", -1, 0);
02915 }
02916 
02917 static void menu_pickup10(void) {
02918   pickup_mode = 10;
02919   send_command("pickup 10", -1, 0);
02920 }
02921 
02922 
02923 
02924 static void menu_who(void) {
02925   extended_command("who");
02926 }
02927 
02928 static void menu_apply(void) {
02929   extended_command("apply");
02930 }
02931 
02932 static void menu_cast(void) {
02933     gtk_entry_set_text(GTK_ENTRY(entrytext),"cast ");
02934     gtk_widget_grab_focus (GTK_WIDGET(entrytext));
02935 }
02936 
02937 static void menu_search(void) {
02938   extended_command("search");
02939 }
02940 
02941 static void menu_disarm(void) {
02942   extended_command("disarm");
02943 }
02944 
02945 static void spellinventory_redraw(GtkWidget* list, GdkEventVisibility* event, gpointer view_x) {
02946     item* ob;
02947     char buffer[2][MAX_BUF];
02948     char* columns[2];
02949     gint row, selected = -1;
02950 
02951     if (GTK_CLIST(list)->selection != NULL)
02952         selected = GPOINTER_TO_INT(GTK_CLIST(list)->selection->data);
02953 
02954     gtk_clist_freeze(GTK_CLIST(list));
02955     gtk_clist_clear(GTK_CLIST(list));
02956 
02957     columns[0] = buffer[0];
02958     columns[1] = buffer[1];
02959 
02960     for (ob = cpl.ob->inv; ob != NULL; ob = ob->next) {
02961         if (!can_write_spell_on(ob))
02962             continue;
02963         snprintf(buffer[0], sizeof(buffer[0]), " ");
02964         snprintf(buffer[1], sizeof(buffer[1]), ob->d_name);
02965         row = gtk_clist_append(GTK_CLIST(list), columns);
02966         gtk_clist_set_pixmap (GTK_CLIST (list), row, 0,
02967             (GdkPixmap*)pixmaps[ob->face]->icon_image,
02968             (GdkBitmap*)pixmaps[ob->face]->icon_mask);
02969         gtk_clist_set_row_data (GTK_CLIST(list), row, ob);
02970     }
02971 
02972     gtk_clist_thaw(GTK_CLIST(list));
02973 
02974     if (selected != -1) {
02975         gtk_clist_select_row(GTK_CLIST(list), selected, 1);
02976         gtk_clist_moveto(GTK_CLIST(list), selected, 0, 0, 0);
02977     }
02978 }
02979 
02980 static GtkWidget *gtkwin_spell = NULL; /* Spell window */
02981 static GtkWidget *description  = NULL; /* The text box containing spell description */
02982 static GtkWidget *list         = NULL;
02983 static GtkWidget *spelloptions = NULL; /* Text box with extra options to pass to the spell */
02984 GtkWidget *spellinventory = NULL; /* List containing inventory for spell inscription. Not static because
02985                                      will be changed by inventory.c*/
02986 
02987 static void click_inscribe_spell(void) {
02988     int selection;
02989     item *scroll;
02990     Spell* spell;
02991 
02992     if (GTK_CLIST(spellinventory)->selection != NULL && GTK_CLIST(list)->selection != NULL) {
02993         selection = GPOINTER_TO_INT(GTK_CLIST(spellinventory)->selection->data);
02994         scroll = (item*)gtk_clist_get_row_data(GTK_CLIST(spellinventory), selection);
02995 
02996         selection = GPOINTER_TO_INT(GTK_CLIST(list)->selection->data);
02997         spell = (Spell*)gtk_clist_get_row_data(GTK_CLIST(list), selection);
02998 
02999         inscribe_magical_scroll(scroll, spell);
03000     }
03001 }
03002 
03003 static void select_spell_event(GtkWidget *gtklist, gint row, gint column,
03004     GdkEventButton *event) {
03005 
03006     char command[MAX_BUF], message[MAX_BUF];
03007     Spell *spell = gtk_clist_get_row_data (GTK_CLIST(gtklist), row);
03008     char *options = NULL;
03009 
03010     if (!event) return; /* We have nothing to do */
03011     /* Any click will select the spell, and show it's description */
03012     gtk_text_freeze(GTK_TEXT(description));
03013     gtk_text_set_point(GTK_TEXT(description), 0);
03014     gtk_text_forward_delete(GTK_TEXT(description), gtk_text_get_length(GTK_TEXT(description)));
03015     sprintf(message, "%s - level %d %s spell\n\n%s", spell->name, spell->level,
03016         spell->skill?spell->skill:"generic", spell->message);
03017     gtk_text_insert(GTK_TEXT(description), NULL, NULL, NULL, message, -1);
03018     gtk_text_thaw(GTK_TEXT(description));
03019     if (event->button==2) { /* On middle click, also invoke the spell */
03020         options = gtk_editable_get_chars(GTK_EDITABLE(spelloptions), 0, -1);
03021         sprintf(command, "invoke %d %s", spell->tag, options);
03022         send_command(command, -1, 1);
03023         g_free(options);
03024     }
03025     else if (event->button==3) { /* On right click, also cast the spell */
03026         options = gtk_editable_get_chars(GTK_EDITABLE(spelloptions), 0, -1);
03027         sprintf(command, "cast %d %s", spell->tag, options);
03028         send_command(command, -1, 1);
03029         g_free(options);
03030     }
03031 }
03032 
03033 static void update_spell_list(int force) {
03034     gint row;
03035     char buffer[3][MAX_BUF];
03036     char *columns[3];
03037     Spell *spell;
03038     PixmapInfo * pixmap;
03039 
03040     /* Only update if we have to */
03041     if (!force && !cpl.spells_updated) return;
03042     if (!gtkwin_spell || !GTK_IS_CLIST(list) || !GTK_WIDGET_VISIBLE(gtkwin_spell)) return;
03043 
03044     gtk_clist_freeze(GTK_CLIST(list));
03045 
03046     /* We are about to recreate the entire spell list, so remove the existing one first */
03047     gtk_clist_clear(GTK_CLIST(list));
03048 
03049     for (spell = cpl.spelldata; spell; spell=spell->next) {
03050         if (!spell) break;
03051         pixmap = pixmaps[spell->face];
03052         buffer[2][0]='\0';
03053         buffer[0][0]='\0';
03054         strcpy(buffer[1], spell->name);
03055         columns[0] = buffer[0];
03056         columns[1] = buffer[1];
03057         columns[2] = buffer[2];
03058         if (spell->sp) sprintf(buffer[2], "%d mana ", spell->sp);
03059         if (spell->grace) sprintf(buffer[2]+strlen(buffer[2]), "%d grace ", spell->grace);
03060         if (spell->dam) sprintf(buffer[2]+strlen(buffer[2]), "%d damage ", spell->dam);
03061 
03062         /* The columns array doesn't yet contain the data we need, but we can't set the
03063          * row colour until we create the row, so we create the row with gtk_clist_append()
03064          * set the colour, then reset the text in the second column
03065          */
03066         row = gtk_clist_append(GTK_CLIST(list), columns);
03067         gtk_clist_set_row_data(GTK_CLIST(list), row, spell);
03068         if (spell->path & cpl.stats.denied) {
03069             gtk_clist_set_background (GTK_CLIST(list), row, &root_color[NDI_RED]);
03070             strcat(buffer[2], "(DENIED) ");
03071         }
03072         else if (spell->path & cpl.stats.attuned) {
03073             gtk_clist_set_background (GTK_CLIST(list), row, &root_color[NDI_GREEN]);
03074             strcat(buffer[2], "(attuned) ");
03075         }
03076         else if (spell->path & cpl.stats.repelled) {
03077             gtk_clist_set_background (GTK_CLIST(list), row, &root_color[NDI_ORANGE]);
03078             strcat(buffer[2], "(repelled) ");
03079         }
03080         gtk_clist_set_text(GTK_CLIST(list), row, 2, columns[2]);
03081         gtk_clist_set_pixmap (GTK_CLIST (list), row, 0,
03082             (GdkPixmap*)pixmap->icon_image, (GdkBitmap*)pixmap->icon_mask);
03083     }
03084     gtk_clist_thaw(GTK_CLIST(list));
03085     cpl.spells_updated =0;
03086 }
03087 
03088 static void menu_spells(void) {
03089     GtkWidget * scroll_window;
03090     GtkStyle * liststyle;
03091     GtkWidget *cancelbutton;
03092     GtkWidget * vbox;
03093     GtkWidget * optionsbox;
03094     GtkWidget * spelloptionslabel;
03095     GtkWidget * notebook;
03096     GtkWidget * label;
03097     GtkWidget * frame;
03098     GtkWidget * inscribebutton;
03099     GtkWidget * inscribewindow;
03100     gchar *titles[] = {" ", "Name", "Cost"};
03101     gchar *titles_inv[] = {" ", "Name"};
03102 
03103     if (gtkwin_spell && GTK_IS_CLIST(list)) {
03104           /* The window is already created, re-present it */
03105         if (GTK_WIDGET_VISIBLE(gtkwin_spell)) {
03106             gdk_window_raise(gtkwin_spell->window);
03107             return;
03108         }
03109 
03110         /* The window is hidden at the moment, so we don't need to recreate it.
03111          * We can merely reshow it, but the spell list won't have updated while
03112          * it was hidden so we have to force an update */
03113         gtk_widget_show_all(gtkwin_spell);
03114         update_spell_list(1);
03115         return;
03116     }
03117 
03118     /* We can't use an existing version, so we must create a new one. First we
03119      * will deal with the window itself */
03120     gtkwin_spell = gtk_window_new (GTK_WINDOW_DIALOG);
03121     gtk_window_set_default_size(GTK_WINDOW(gtkwin_spell), 400+image_size, 400+image_size);
03122     gtk_window_set_title(GTK_WINDOW (gtkwin_spell), "Cast Spell");
03123 
03124     /* Now for its contents: first we'll deal with the options widget */
03125     spelloptions = gtk_entry_new();
03126     spelloptionslabel = gtk_label_new("Spell Options:");
03127     optionsbox = gtk_hbox_new(FALSE, 2);
03128     gtk_box_pack_start(GTK_BOX(optionsbox), spelloptionslabel, FALSE, FALSE, 0);
03129     gtk_box_pack_start(GTK_BOX(optionsbox), spelloptions, TRUE, TRUE, 0);
03130 
03131     /* rNw the list scroll window */
03132     scroll_window = gtk_scrolled_window_new (0,0);
03133     gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll_window),
03134         GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
03135 
03136     /* And the spell list itself */
03137     list = gtk_clist_new_with_titles(3, titles);
03138     gtk_clist_set_column_width(GTK_CLIST(list), 1, image_size);
03139     gtk_clist_set_column_width(GTK_CLIST(list), 1, 200);
03140     gtk_clist_set_column_width(GTK_CLIST(list), 2, 200);
03141     gtk_clist_set_selection_mode(GTK_CLIST(list) , GTK_SELECTION_BROWSE);
03142     gtk_clist_set_row_height (GTK_CLIST(list), image_size);
03143     liststyle = gtk_rc_get_style(list);
03144     if (liststyle) {
03145         liststyle->bg[GTK_STATE_SELECTED] = gdk_grey;
03146         liststyle->fg[GTK_STATE_SELECTED] = gdk_black;
03147         gtk_widget_set_style (list, liststyle);
03148     }
03149     /* Set the actions for the mouse buttons to trigger the callback function */
03150     gtk_clist_set_button_actions(GTK_CLIST(list), 1, GTK_BUTTON_SELECTS);
03151     gtk_clist_set_button_actions(GTK_CLIST(list), 2, GTK_BUTTON_SELECTS);
03152     gtk_signal_connect(GTK_OBJECT(list), "select_row",
03153         GTK_SIGNAL_FUNC(select_spell_event), NULL);
03154 
03155     /* With all that done, we can now add it to the scroll window */
03156     gtk_container_add(GTK_CONTAINER(scroll_window), list);
03157 
03158     /* Now we'll create the description box */
03159     description = gtk_text_new(NULL, NULL);
03160     gtk_text_set_editable(GTK_TEXT (description), FALSE);
03161 
03162     /* Finally add a close button to the window */
03163     cancelbutton = gtk_button_new_with_label("Close");
03164     gtk_signal_connect_object (GTK_OBJECT (cancelbutton), "clicked",
03165         GTK_SIGNAL_FUNC(gtk_widget_hide_all), GTK_OBJECT (gtkwin_spell));
03166 
03167     notebook = gtk_notebook_new ();
03168     gtk_notebook_set_tab_pos (GTK_NOTEBOOK (notebook), GTK_POS_TOP );
03169 
03170     label = gtk_label_new ("Information");
03171     gtk_widget_show (label);
03172 
03173     frame = gtk_frame_new("Spell information");
03174     gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
03175     gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame, label);
03176     vbox = gtk_vbox_new(FALSE, 0);
03177     gtk_box_pack_start(GTK_BOX(vbox), optionsbox, FALSE, FALSE, 0);
03178     gtk_box_pack_start(GTK_BOX(vbox), description, TRUE, TRUE, 0);
03179     gtk_container_add (GTK_CONTAINER(frame), vbox);
03180 
03181     /* Start of inventory list for inscription */
03182     if (command_inscribe) {
03183         label = gtk_label_new ("Inscribe");
03184         gtk_widget_show (label);
03185 
03186         frame = gtk_frame_new("Inscribe a spell");
03187         gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
03188         gtk_notebook_append_page(GTK_NOTEBOOK(notebook), frame, label);
03189         vbox = gtk_vbox_new(FALSE, 0);
03190         label = gtk_label_new ("Choose the item to write on:");
03191         gtk_box_pack_start(GTK_BOX(vbox), label, FALSE, FALSE, 0);
03192 
03193         inscribewindow = gtk_scrolled_window_new (0,0);
03194         gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(inscribewindow),
03195             GTK_POLICY_AUTOMATIC, GTK_POLICY_AUTOMATIC);
03196 
03197         spellinventory = gtk_clist_new_with_titles(2, titles_inv);
03198         gtk_clist_set_column_width(GTK_CLIST(spellinventory), 0, image_size);
03199         gtk_clist_set_selection_mode(GTK_CLIST(spellinventory) , GTK_SELECTION_BROWSE);
03200         gtk_clist_set_row_height (GTK_CLIST(spellinventory), image_size);
03201         liststyle = gtk_rc_get_style(spellinventory);
03202         if (liststyle) {
03203             liststyle->bg[GTK_STATE_SELECTED] = gdk_grey;
03204             liststyle->fg[GTK_STATE_SELECTED] = gdk_black;
03205             gtk_widget_set_style (spellinventory, liststyle);
03206         }
03207         gtk_signal_connect(GTK_OBJECT(spellinventory),
03208             "visibility-notify-event",
03209             (GtkSignalFunc)spellinventory_redraw, NULL);
03210         gtk_widget_add_events(spellinventory, GDK_VISIBILITY_NOTIFY_MASK);
03211 
03212         gtk_container_add(GTK_CONTAINER(inscribewindow), spellinventory);
03213         gtk_box_pack_start(GTK_BOX(vbox), inscribewindow, TRUE, TRUE, 0);
03214 
03215         inscribebutton = gtk_button_new_with_label("Inscribe");
03216         gtk_signal_connect_object (GTK_OBJECT (inscribebutton), "clicked",
03217             GTK_SIGNAL_FUNC(click_inscribe_spell), NULL);
03218         gtk_box_pack_start(GTK_BOX(vbox), inscribebutton, FALSE, FALSE, 0);
03219 
03220         gtk_container_add (GTK_CONTAINER(frame), vbox);
03221     }
03222     /* End of inscription logic */
03223 
03224     /* vbox holds all the widgets we just created, in order */
03225     vbox = gtk_vbox_new(FALSE, 2);
03226 
03227     /* Ok, time to pack it all up */
03228     gtk_container_add(GTK_CONTAINER(gtkwin_spell), vbox);
03229     gtk_box_pack_start(GTK_BOX(vbox), scroll_window, TRUE, TRUE, 0);
03230 
03231     gtk_box_pack_start (GTK_BOX(vbox),notebook, TRUE, TRUE, 0);
03232 
03233     gtk_box_pack_start(GTK_BOX(vbox), cancelbutton, FALSE, FALSE, 0);
03234 
03235     gtk_widget_show_all(gtkwin_spell);
03236 
03237     /* Let's add the spells to the list now */
03238     update_spell_list(1);
03239 }
03240 
03241 void menu_clear(void) {
03242   guint size;
03243 
03244   size = gtk_text_get_length(GTK_TEXT (gtkwin_info_text));
03245   gtk_text_freeze (GTK_TEXT (gtkwin_info_text));
03246   gtk_text_set_point(GTK_TEXT (gtkwin_info_text), 0);
03247   gtk_text_forward_delete (GTK_TEXT (gtkwin_info_text), size );
03248   gtk_text_thaw (GTK_TEXT (gtkwin_info_text));
03249 
03250 #ifdef WIN32
03251   if ( gtkwin_info_text2 )
03252       {
03253 #endif
03254   size = gtk_text_get_length(GTK_TEXT (gtkwin_info_text2));
03255   gtk_text_freeze (GTK_TEXT (gtkwin_info_text2));
03256   gtk_text_set_point(GTK_TEXT (gtkwin_info_text2), 0);
03257   gtk_text_forward_delete (GTK_TEXT (gtkwin_info_text2), size );
03258   gtk_text_thaw (GTK_TEXT (gtkwin_info_text2));
03259 #ifdef WIN32
03260       }
03261 #endif
03262 }
03263 
03264 static void sexit(void)
03265 {
03266     extended_command("quit");
03267 }
03268 
03269 void client_exit(void) {
03270     LOG(LOG_INFO,"gtk::client_exit","Exiting with return value 0.");
03271 #ifdef WIN32
03272         script_killall();
03273 #endif
03274     exit(0);
03275 }
03276 
03277 /* To keep track of pickup menus, and be able to check/uncheck them. */
03278 static GtkWidget* pickup_menus[43];
03279 static int pickup_value[43];
03280 static int pickup_count = 0;
03281 
03282 /* get_menu_display
03283  * This sets up menus
03284  */
03285 
03286 static int get_menu_display (GtkWidget *box) {
03287   GtkWidget *filemenu;
03288   GtkWidget *actionmenu;
03289   GtkWidget *pickupmenu;
03290   GtkWidget *newpickupmenu;
03291   GtkWidget *ratiopickupmenu;
03292   GtkWidget *weaponpickupmenu;
03293   GtkWidget *armourpickupmenu;
03294   GtkWidget *bookspickupmenu;
03295   GtkWidget *clientmenu;
03296   GtkWidget *helpmenu;
03297   GtkWidget *menu_bar;
03298   GtkWidget *root_filemenu;
03299   GtkWidget *root_helpmenu;
03300   GtkWidget *root_actionmenu;
03301   /*  GtkWidget *sub_pickupmenu;*/
03302   GtkWidget *root_clientmenu;
03303   GtkWidget *menu_items;
03304   GtkWidget *pickup_menu_item;
03305   GtkWidget *newpickup_menu_item;
03306   GtkWidget *ratiopickup_menu_item;
03307   GtkWidget *weaponpickup_menu_item;
03308   GtkWidget *armourpickup_menu_item;
03309   GtkWidget *bookspickup_menu_item;
03310   GSList *pickupgroup;
03311   GSList *ratiopickupgroup;
03312   int i;
03313   char menustring[128];
03314 
03315 
03316   /* Init the menu-widget, and remember -- never
03317    * gtk_show_widget() the menu widget!!
03318    * This is the menu that holds the menu items, the one that
03319    * will pop up when you click on the "Root Menu" in the app */
03320   filemenu = gtk_menu_new();
03321 
03322   /* Next we make a little loop that makes three menu-entries for "test-menu".
03323    * Notice the call to gtk_menu_append.  Here we are adding a list of
03324    * menu items to our menu.  Normally, we'd also catch the "clicked"
03325    * signal on each of the menu items and setup a callback for it,
03326    * but it's omitted here to save space. */
03327 
03328   menu_items = gtk_tearoff_menu_item_new ();
03329   gtk_menu_append (GTK_MENU (filemenu), menu_items);
03330   gtk_widget_show (menu_items);
03331 
03332   menu_items = gtk_menu_item_new_with_label("Save config");
03333   gtk_menu_append(GTK_MENU (filemenu), menu_items);
03334   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03335                             GTK_SIGNAL_FUNC(save_defaults), NULL);
03336   gtk_widget_show(menu_items);
03337 
03338   menu_items = gtk_menu_item_new_with_label("Save window positions");
03339   gtk_menu_append(GTK_MENU (filemenu), menu_items);
03340   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03341                             GTK_SIGNAL_FUNC(save_winpos), NULL);
03342   gtk_widget_show(menu_items);
03343 
03344   menu_items = gtk_menu_item_new ();
03345   gtk_menu_append(GTK_MENU (filemenu), menu_items);
03346   gtk_widget_show(menu_items);
03347 
03348 
03349   menu_items = gtk_menu_item_new_with_label("Quit character");
03350   gtk_menu_append(GTK_MENU (filemenu), menu_items);
03351   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03352                             GTK_SIGNAL_FUNC(sexit), NULL);
03353   gtk_widget_show(menu_items);
03354 
03355   menu_items = gtk_menu_item_new_with_label("Quit client");
03356   gtk_menu_append(GTK_MENU (filemenu), menu_items);
03357   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03358                             GTK_SIGNAL_FUNC(client_exit), NULL);
03359   gtk_widget_show(menu_items);
03360 
03361   /* This is the root menu, and will be the label
03362    * displayed on the menu bar.  There won't be a signal handler attached,
03363    * as it only pops up the rest of the menu when pressed. */
03364   root_filemenu = gtk_menu_item_new_with_label("File");
03365 
03366   gtk_widget_show(root_filemenu);
03367 
03368   /* Now we specify that we want our newly created "menu" to be the menu
03369    * for the "root menu" */
03370   gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_filemenu), filemenu);
03371 
03372  /* Do the clientmenu */
03373 
03374   clientmenu = gtk_menu_new();
03375 
03376   /*  menu_items = gtk_menu_item_new_with_label("Navigator");
03377   gtk_menu_append(GTK_MENU (clientmenu), menu_items);
03378   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03379                             GTK_SIGNAL_FUNC(navbut), NULL);
03380                             gtk_widget_show(menu_items);*/
03381 
03382   menu_items = gtk_tearoff_menu_item_new ();
03383   gtk_menu_append (GTK_MENU (clientmenu), menu_items);
03384   gtk_widget_show (menu_items);
03385 
03386   menu_items = gtk_menu_item_new_with_label("Clear info");
03387   gtk_menu_append(GTK_MENU (clientmenu), menu_items);
03388   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03389                             GTK_SIGNAL_FUNC(menu_clear), NULL);
03390   gtk_widget_show(menu_items);
03391 
03392 
03393   menu_items = gtk_menu_item_new_with_label("Spells");
03394   gtk_menu_append(GTK_MENU (clientmenu), menu_items);
03395   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03396                             GTK_SIGNAL_FUNC(menu_spells), NULL);
03397   gtk_widget_show(menu_items);
03398 
03399   menu_items = gtk_menu_item_new_with_label("Configure");
03400   gtk_menu_append(GTK_MENU (clientmenu), menu_items);
03401   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03402                             GTK_SIGNAL_FUNC(configdialog), NULL);
03403   gtk_widget_show(menu_items);
03404 
03405 
03406   menu_items = gtk_menu_item_new_with_label("Disconnect");
03407   gtk_menu_append(GTK_MENU (clientmenu), menu_items);
03408   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03409                             GTK_SIGNAL_FUNC(disconnect), NULL);
03410   gtk_widget_show(menu_items);
03411 
03412 
03413   root_clientmenu = gtk_menu_item_new_with_label("Client");
03414 
03415   gtk_widget_show(root_clientmenu);
03416   gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_clientmenu), clientmenu);
03417 
03418   /* Do the actionmenu */
03419 
03420   actionmenu = gtk_menu_new();
03421 
03422   menu_items = gtk_tearoff_menu_item_new ();
03423   gtk_menu_append (GTK_MENU (actionmenu), menu_items);
03424   gtk_widget_show (menu_items);
03425 
03426   menu_items = gtk_menu_item_new_with_label("Who");
03427   gtk_menu_append(GTK_MENU (actionmenu), menu_items);
03428   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03429                             GTK_SIGNAL_FUNC(menu_who), NULL);
03430   gtk_widget_show(menu_items);
03431 
03432   menu_items = gtk_menu_item_new_with_label("Cast...");
03433   gtk_menu_append(GTK_MENU (actionmenu), menu_items);
03434   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03435                             GTK_SIGNAL_FUNC(menu_cast), NULL);
03436   gtk_widget_show(menu_items);
03437 
03438   menu_items = gtk_menu_item_new_with_label("Apply");
03439   gtk_menu_append(GTK_MENU (actionmenu), menu_items);
03440   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03441                             GTK_SIGNAL_FUNC(menu_apply), NULL);
03442   gtk_widget_show(menu_items);
03443 
03444   pickup_menu_item = gtk_menu_item_new_with_label("Pickup");
03445   gtk_menu_append(GTK_MENU (actionmenu), pickup_menu_item);
03446   /*  gtk_signal_connect_object(GTK_OBJECT(pickup_menu_item), "activate",
03447                             GTK_SIGNAL_FUNC(menu_apply), NULL);*/
03448   gtk_widget_show(pickup_menu_item);
03449 
03450   newpickup_menu_item = gtk_menu_item_new_with_label("NEWPickup");
03451   gtk_menu_append(GTK_MENU (actionmenu), newpickup_menu_item);
03452   gtk_widget_show(newpickup_menu_item);
03453 
03454   menu_items = gtk_menu_item_new_with_label("Search");
03455   gtk_menu_append(GTK_MENU (actionmenu), menu_items);
03456   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03457                             GTK_SIGNAL_FUNC(menu_search), NULL);
03458   gtk_widget_show(menu_items);
03459 
03460   menu_items = gtk_menu_item_new_with_label("Disarm");
03461   gtk_menu_append(GTK_MENU (actionmenu), menu_items);
03462   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03463                             GTK_SIGNAL_FUNC(menu_disarm), NULL);
03464   gtk_widget_show(menu_items);
03465 
03466 
03467   root_actionmenu = gtk_menu_item_new_with_label("Action");
03468 
03469   gtk_widget_show(root_actionmenu);
03470   gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_actionmenu), actionmenu);
03471 
03472  /* Do the submenu */
03473 
03474   pickupmenu = gtk_menu_new();
03475 
03476   /*  This allows you to change your pickup status. Eight different modes for pick up exist: ``don't pick up'',``pick up 1
03477 item'', ``pick up 1 item and stop'', ``stop before picking up'', ``pick up all items'', pick up all items and stop'',
03478 ``pick up all magic items'', ``pick up all coins and gems''. Whenever you move over a pile of stuff your pickup*/
03479   pickupgroup=NULL;
03480 
03481   menu_items = gtk_tearoff_menu_item_new ();
03482   gtk_menu_append (GTK_MENU (pickupmenu), menu_items);
03483   gtk_widget_show (menu_items);
03484 
03485   menu_items = gtk_radio_menu_item_new_with_label(pickupgroup, "Don't pick up");
03486   pickupgroup = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menu_items));
03487   gtk_check_menu_item_set_show_toggle (GTK_CHECK_MENU_ITEM (menu_items), TRUE);
03488   gtk_menu_append(GTK_MENU (pickupmenu), menu_items);
03489   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03490                             GTK_SIGNAL_FUNC(menu_pickup0), NULL);
03491   gtk_widget_show(menu_items);
03492 
03493   menu_items = gtk_radio_menu_item_new_with_label(pickupgroup, "Pick up 1 item");
03494   pickupgroup = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menu_items));
03495   gtk_check_menu_item_set_show_toggle (GTK_CHECK_MENU_ITEM (menu_items), TRUE);
03496   gtk_menu_append(GTK_MENU (pickupmenu), menu_items);
03497   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03498                             GTK_SIGNAL_FUNC(menu_pickup1), NULL);
03499   gtk_widget_show(menu_items);
03500 
03501 
03502   menu_items = gtk_radio_menu_item_new_with_label(pickupgroup, "Pick up 1 item and stop");
03503   pickupgroup = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menu_items));
03504   gtk_check_menu_item_set_show_toggle (GTK_CHECK_MENU_ITEM (menu_items), TRUE);
03505   gtk_menu_append(GTK_MENU (pickupmenu), menu_items);
03506   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03507                             GTK_SIGNAL_FUNC(menu_pickup2), NULL);
03508   gtk_widget_show(menu_items);
03509 
03510   menu_items = gtk_radio_menu_item_new_with_label(pickupgroup, "Stop before picking up.");
03511   pickupgroup = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menu_items));
03512   gtk_check_menu_item_set_show_toggle (GTK_CHECK_MENU_ITEM (menu_items), TRUE);
03513   gtk_menu_append(GTK_MENU (pickupmenu), menu_items);
03514   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03515                             GTK_SIGNAL_FUNC(menu_pickup3), NULL);
03516   gtk_widget_show(menu_items);
03517 
03518   menu_items = gtk_radio_menu_item_new_with_label(pickupgroup, "Pick up all items.");
03519   pickupgroup = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menu_items));
03520   gtk_check_menu_item_set_show_toggle (GTK_CHECK_MENU_ITEM (menu_items), TRUE);
03521   gtk_menu_append(GTK_MENU (pickupmenu), menu_items);
03522   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03523                             GTK_SIGNAL_FUNC(menu_pickup4), NULL);
03524   gtk_widget_show(menu_items);
03525 
03526   menu_items = gtk_radio_menu_item_new_with_label(pickupgroup, "Pick up all items and stop.");
03527   pickupgroup = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menu_items));
03528   gtk_check_menu_item_set_show_toggle (GTK_CHECK_MENU_ITEM (menu_items), TRUE);
03529   gtk_menu_append(GTK_MENU (pickupmenu), menu_items);
03530   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03531                             GTK_SIGNAL_FUNC(menu_pickup5), NULL);
03532   gtk_widget_show(menu_items);
03533 
03534   menu_items = gtk_radio_menu_item_new_with_label(pickupgroup, "Pick up all magic items.");
03535   pickupgroup = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menu_items));
03536   gtk_check_menu_item_set_show_toggle (GTK_CHECK_MENU_ITEM (menu_items), TRUE);
03537   gtk_menu_append(GTK_MENU (pickupmenu), menu_items);
03538   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03539                             GTK_SIGNAL_FUNC(menu_pickup6), NULL);
03540   gtk_widget_show(menu_items);
03541 
03542   menu_items = gtk_radio_menu_item_new_with_label(pickupgroup, "Pick up all coins and gems.");
03543   pickupgroup = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menu_items));
03544   gtk_check_menu_item_set_show_toggle (GTK_CHECK_MENU_ITEM (menu_items), TRUE);
03545   gtk_menu_append(GTK_MENU (pickupmenu), menu_items);
03546   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03547                             GTK_SIGNAL_FUNC(menu_pickup7), NULL);
03548   gtk_widget_show(menu_items);
03549 
03550   menu_items = gtk_radio_menu_item_new_with_label(pickupgroup, "Pickup silver and higher value/weight.");
03551   pickupgroup = gtk_radio_menu_item_group (GTK_RADIO_MENU_ITEM (menu_items));
03552   gtk_check_menu_item_set_show_toggle (GTK_CHECK_MENU_ITEM (menu_items), TRUE);
03553   gtk_menu_append(GTK_MENU (pickupmenu), menu_items);
03554   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03555                             GTK_SIGNAL_FUNC(menu_pickup10), NULL);
03556   gtk_widget_show(menu_items);
03557 
03558 
03559   /*  sub_pickupmenu = gtk_menu_item_new_with_label("Action");
03560 
03561   gtk_widget_show(sub_pickupmenu);*/
03562   gtk_menu_item_set_submenu(GTK_MENU_ITEM (pickup_menu_item), pickupmenu);
03563 /* ENDPICKUP */
03564 
03565 /* --------------------------------------------------------------------- */
03566 /* --------------------------------------------------------------------- */
03567 /* --------------------------------------------------------------------- */
03568 /* --------------------------------------------------------------------- */
03569 /* --------------------------------------------------------------------- */
03570 
03571   /* Root of the NEWPickup menu */
03572   newpickupmenu = gtk_menu_new();
03573   gtk_menu_item_set_submenu(GTK_MENU_ITEM(newpickup_menu_item), newpickupmenu);
03574 
03575   menu_items = gtk_tearoff_menu_item_new();
03576   gtk_menu_append(GTK_MENU(newpickupmenu), menu_items);
03577   gtk_widget_show(menu_items);
03578 
03579   menu_items = gtk_check_menu_item_new_with_label("Enable NEW autopickup");
03580   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03581   gtk_menu_append(GTK_MENU(newpickupmenu), menu_items);
03582   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03583         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_NEWMODE));
03584   gtk_widget_show(menu_items);
03585   pickup_menus[pickup_count] = menu_items;
03586   pickup_value[pickup_count++] = PU_NEWMODE;
03587 
03588   menu_items = gtk_check_menu_item_new_with_label("Inhibit autopickup");
03589   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03590   gtk_menu_append(GTK_MENU(newpickupmenu), menu_items);
03591   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03592         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_INHIBIT));
03593   gtk_widget_show(menu_items);
03594   pickup_menus[pickup_count] = menu_items;
03595   pickup_value[pickup_count++] = PU_INHIBIT;
03596 
03597   menu_items = gtk_check_menu_item_new_with_label("Stop before pickup");
03598   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03599   gtk_menu_append(GTK_MENU(newpickupmenu), menu_items);
03600   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03601         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_STOP));
03602   gtk_widget_show(menu_items);
03603   pickup_menus[pickup_count] = menu_items;
03604   pickup_value[pickup_count++] = PU_STOP;
03605 
03606   menu_items = gtk_check_menu_item_new_with_label("Debug autopickup");
03607   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03608   gtk_menu_append(GTK_MENU(newpickupmenu), menu_items);
03609   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03610         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_DEBUG));
03611   gtk_widget_show(menu_items);
03612   pickup_menus[pickup_count] = menu_items;
03613   pickup_value[pickup_count++] = PU_DEBUG;
03614 
03615 
03616   /* The ratio pickup submenu */
03617   ratiopickupmenu = gtk_menu_new();
03618   ratiopickup_menu_item = gtk_menu_item_new_with_label("Weight/Value Ratio");
03619   gtk_menu_append(GTK_MENU(newpickupmenu), ratiopickup_menu_item);
03620   gtk_widget_show(ratiopickup_menu_item);
03621   gtk_menu_item_set_submenu(GTK_MENU_ITEM(ratiopickup_menu_item), ratiopickupmenu);
03622 
03623   ratiopickupgroup=NULL;
03624 
03625   menu_items = gtk_tearoff_menu_item_new();
03626   gtk_menu_append(GTK_MENU(ratiopickupmenu), menu_items);
03627   gtk_widget_show(menu_items);
03628 
03629   for (i=0;i<16;i++)
03630   {
03631     if (i==0) sprintf(menustring,"Ratio pickup OFF");
03632     else sprintf(menustring,"Ratio >= %d",i*5);
03633     menu_items = gtk_radio_menu_item_new_with_label(ratiopickupgroup, menustring);
03634     ratiopickupgroup = gtk_radio_menu_item_group(GTK_RADIO_MENU_ITEM(menu_items));
03635     gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03636     gtk_menu_append(GTK_MENU(ratiopickupmenu), menu_items);
03637     gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03638         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(i));
03639     gtk_widget_show(menu_items);
03640     pickup_menus[pickup_count] = menu_items;
03641     pickup_value[pickup_count++] = i;
03642   }
03643 
03644 
03645   /* Weapon pickup menu */
03646   weaponpickupmenu = gtk_menu_new();
03647   weaponpickup_menu_item = gtk_menu_item_new_with_label("Weapons");
03648   gtk_menu_append(GTK_MENU(newpickupmenu), weaponpickup_menu_item);
03649   gtk_widget_show(weaponpickup_menu_item);
03650   gtk_menu_item_set_submenu(GTK_MENU_ITEM(weaponpickup_menu_item), weaponpickupmenu);
03651 
03652   menu_items = gtk_tearoff_menu_item_new();
03653   gtk_menu_append(GTK_MENU(weaponpickupmenu), menu_items);
03654   gtk_widget_show(menu_items);
03655 
03656   menu_items = gtk_check_menu_item_new_with_label("All weapons");
03657   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03658   gtk_menu_append(GTK_MENU(weaponpickupmenu), menu_items);
03659   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03660         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_ALLWEAPON));
03661   gtk_widget_show(menu_items);
03662   pickup_menus[pickup_count] = menu_items;
03663   pickup_value[pickup_count++] = PU_ALLWEAPON;
03664 
03665   menu_items = gtk_check_menu_item_new_with_label("Missile Weapons");
03666   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03667   gtk_menu_append(GTK_MENU(weaponpickupmenu), menu_items);
03668   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03669         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_MISSILEWEAPON));
03670   gtk_widget_show(menu_items);
03671   pickup_menus[pickup_count] = menu_items;
03672   pickup_value[pickup_count++] = PU_MISSILEWEAPON;
03673 
03674   menu_items = gtk_check_menu_item_new_with_label("Bows");
03675   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03676   gtk_menu_append(GTK_MENU(weaponpickupmenu), menu_items);
03677   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03678         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_BOW));
03679   gtk_widget_show(menu_items);
03680   pickup_menus[pickup_count] = menu_items;
03681   pickup_value[pickup_count++] = PU_BOW;
03682 
03683   menu_items = gtk_check_menu_item_new_with_label("Arrows");
03684   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03685   gtk_menu_append(GTK_MENU(weaponpickupmenu), menu_items);
03686   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03687         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_ARROW));
03688   gtk_widget_show(menu_items);
03689   pickup_menus[pickup_count] = menu_items;
03690   pickup_value[pickup_count++] = PU_ARROW;
03691 
03692 
03693   /* Armour pickup menu */
03694   armourpickupmenu = gtk_menu_new();
03695   armourpickup_menu_item = gtk_menu_item_new_with_label("Armour");
03696   gtk_menu_append(GTK_MENU(newpickupmenu), armourpickup_menu_item);
03697   gtk_widget_show(armourpickup_menu_item);
03698   gtk_menu_item_set_submenu(GTK_MENU_ITEM(armourpickup_menu_item), armourpickupmenu);
03699 
03700   menu_items = gtk_tearoff_menu_item_new();
03701   gtk_menu_append(GTK_MENU(armourpickupmenu), menu_items);
03702   gtk_widget_show(menu_items);
03703 
03704   menu_items = gtk_check_menu_item_new_with_label("Helmets");
03705   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03706   gtk_menu_append(GTK_MENU(armourpickupmenu), menu_items);
03707   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03708         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_HELMET));
03709   gtk_widget_show(menu_items);
03710   pickup_menus[pickup_count] = menu_items;
03711   pickup_value[pickup_count++] = PU_HELMET;
03712 
03713   menu_items = gtk_check_menu_item_new_with_label("Shields");
03714   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03715   gtk_menu_append(GTK_MENU(armourpickupmenu), menu_items);
03716   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03717         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_SHIELD));
03718   gtk_widget_show(menu_items);
03719   pickup_menus[pickup_count] = menu_items;
03720   pickup_value[pickup_count++] = PU_SHIELD;
03721 
03722   menu_items = gtk_check_menu_item_new_with_label("Body Armour");
03723   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03724   gtk_menu_append(GTK_MENU(armourpickupmenu), menu_items);
03725   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03726         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_ARMOUR));
03727   gtk_widget_show(menu_items);
03728   pickup_menus[pickup_count] = menu_items;
03729   pickup_value[pickup_count++] = PU_ARMOUR;
03730 
03731   menu_items = gtk_check_menu_item_new_with_label("Boots");
03732   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03733   gtk_menu_append(GTK_MENU(armourpickupmenu), menu_items);
03734   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03735         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_BOOTS));
03736   gtk_widget_show(menu_items);
03737   pickup_menus[pickup_count] = menu_items;
03738   pickup_value[pickup_count++] = PU_BOOTS;
03739 
03740   menu_items = gtk_check_menu_item_new_with_label("Gloves");
03741   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03742   gtk_menu_append(GTK_MENU(armourpickupmenu), menu_items);
03743   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03744         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_GLOVES));
03745   gtk_widget_show(menu_items);
03746   pickup_menus[pickup_count] = menu_items;
03747   pickup_value[pickup_count++] = PU_GLOVES;
03748 
03749   menu_items = gtk_check_menu_item_new_with_label("Cloaks");
03750   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03751   gtk_menu_append(GTK_MENU(armourpickupmenu), menu_items);
03752   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03753         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_CLOAK));
03754   gtk_widget_show(menu_items);
03755   pickup_menus[pickup_count] = menu_items;
03756   pickup_value[pickup_count++] = PU_CLOAK;
03757 
03758 
03759   /* Books pickup menu */
03760   bookspickupmenu = gtk_menu_new();
03761   bookspickup_menu_item = gtk_menu_item_new_with_label("Books");
03762   gtk_menu_append(GTK_MENU(newpickupmenu), bookspickup_menu_item);
03763   gtk_widget_show(bookspickup_menu_item);
03764   gtk_menu_item_set_submenu(GTK_MENU_ITEM(bookspickup_menu_item), bookspickupmenu);
03765 
03766   menu_items = gtk_tearoff_menu_item_new();
03767   gtk_menu_append(GTK_MENU(bookspickupmenu), menu_items);
03768   gtk_widget_show(menu_items);
03769 
03770   menu_items = gtk_check_menu_item_new_with_label("Spellbooks");
03771   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03772   gtk_menu_append(GTK_MENU(bookspickupmenu), menu_items);
03773   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03774         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_SPELLBOOK));
03775   gtk_widget_show(menu_items);
03776   pickup_menus[pickup_count] = menu_items;
03777   pickup_value[pickup_count++] = PU_SPELLBOOK;
03778 
03779   menu_items = gtk_check_menu_item_new_with_label("Skillscrolls");
03780   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03781   gtk_menu_append(GTK_MENU(bookspickupmenu), menu_items);
03782   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03783         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_SKILLSCROLL));
03784   gtk_widget_show(menu_items);
03785   pickup_menus[pickup_count] = menu_items;
03786   pickup_value[pickup_count++] = PU_SKILLSCROLL;
03787 
03788   menu_items = gtk_check_menu_item_new_with_label("Normal Books/Scrolls");
03789   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03790   gtk_menu_append(GTK_MENU(bookspickupmenu), menu_items);
03791   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03792         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_READABLES));
03793   gtk_widget_show(menu_items);
03794   pickup_menus[pickup_count] = menu_items;
03795   pickup_value[pickup_count++] = PU_READABLES;
03796 
03797 
03798   /* Continue with the rest of the stuff... */
03799 
03800   menu_items = gtk_check_menu_item_new_with_label("Food");
03801   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03802   gtk_menu_append(GTK_MENU(newpickupmenu), menu_items);
03803   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03804         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_FOOD));
03805   gtk_widget_show(menu_items);
03806   pickup_menus[pickup_count] = menu_items;
03807   pickup_value[pickup_count++] = PU_FOOD;
03808 
03809   menu_items = gtk_check_menu_item_new_with_label("Drinks");
03810   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03811   gtk_menu_append(GTK_MENU(newpickupmenu), menu_items);
03812   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03813         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_DRINK));
03814   gtk_widget_show(menu_items);
03815   pickup_menus[pickup_count] = menu_items;
03816   pickup_value[pickup_count++] = PU_DRINK;
03817 
03818   menu_items = gtk_check_menu_item_new_with_label("Flesh");
03819   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03820   gtk_menu_append(GTK_MENU(newpickupmenu), menu_items);
03821   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03822         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_FLESH));
03823   gtk_widget_show(menu_items);
03824   pickup_menus[pickup_count] = menu_items;
03825   pickup_value[pickup_count++] = PU_FLESH;
03826 
03827   menu_items = gtk_check_menu_item_new_with_label("Valuables (Money, Gems)");
03828   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03829   gtk_menu_append(GTK_MENU(newpickupmenu), menu_items);
03830   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03831         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_VALUABLES));
03832   gtk_widget_show(menu_items);
03833   pickup_menus[pickup_count] = menu_items;
03834   pickup_value[pickup_count++] = PU_VALUABLES;
03835 
03836   menu_items = gtk_check_menu_item_new_with_label("Keys");
03837   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03838   gtk_menu_append(GTK_MENU(newpickupmenu), menu_items);
03839   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03840         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_KEY));
03841   gtk_widget_show(menu_items);
03842   pickup_menus[pickup_count] = menu_items;
03843   pickup_value[pickup_count++] = PU_KEY;
03844 
03845   menu_items = gtk_check_menu_item_new_with_label("Magical Items");
03846   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03847   gtk_menu_append(GTK_MENU(newpickupmenu), menu_items);
03848   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03849         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_MAGICAL));
03850   gtk_widget_show(menu_items);
03851   pickup_menus[pickup_count] = menu_items;
03852   pickup_value[pickup_count++] = PU_MAGICAL;
03853 
03854   menu_items = gtk_check_menu_item_new_with_label("Potions");
03855   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03856   gtk_menu_append(GTK_MENU(newpickupmenu), menu_items);
03857   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03858         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_POTION));
03859   gtk_widget_show(menu_items);
03860   pickup_menus[pickup_count] = menu_items;
03861   pickup_value[pickup_count++] = PU_POTION;
03862 
03863   menu_items = gtk_check_menu_item_new_with_label("Magic Devices");
03864   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03865   gtk_menu_append(GTK_MENU(newpickupmenu), menu_items);
03866   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03867   GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_MAGIC_DEVICE));
03868   gtk_widget_show(menu_items);
03869   pickup_menus[pickup_count] = menu_items;
03870   pickup_value[pickup_count++] = PU_MAGIC_DEVICE;
03871 
03872   menu_items = gtk_check_menu_item_new_with_label("Ignore cursed");
03873   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03874   gtk_menu_append(GTK_MENU(newpickupmenu), menu_items);
03875   gtk_signal_connect(GTK_OBJECT(menu_items), "activate",
03876         GTK_SIGNAL_FUNC(new_menu_pickup), GINT_TO_POINTER(PU_NOT_CURSED));
03877   gtk_widget_show(menu_items);
03878   pickup_menus[pickup_count] = menu_items;
03879   pickup_value[pickup_count++] = PU_NOT_CURSED;
03880 
03881   menu_items = gtk_check_menu_item_new_with_label("Jewelry");
03882   gtk_check_menu_item_set_show_toggle(GTK_CHECK_MENU_ITEM(menu_items), TRUE);
03883   gtk_menu_append(GTK_MENU(newpickupmenu), menu_items);
03884   gtk_signal_connect(GTK_OBJECT(menu_items),"activate",
03885     GTK_SIGNAL_FUNC(new_menu_pickup),GINT_TO_POINTER(PU_JEWELS));
03886   gtk_widget_show(menu_items);
03887   pickup_menus[pickup_count] = menu_items;
03888   pickup_value[pickup_count++] = PU_JEWELS;
03889 /* --------------------------------------------------------------------- */
03890 /* --------------------------------------------------------------------- */
03891 /* --------------------------------------------------------------------- */
03892 /* --------------------------------------------------------------------- */
03893 /* --------------------------------------------------------------------- */
03894 
03895   /*Do the helpmenu */
03896   helpmenu = gtk_menu_new();
03897 
03898   menu_items = gtk_tearoff_menu_item_new ();
03899   gtk_menu_append (GTK_MENU (helpmenu), menu_items);
03900   gtk_widget_show (menu_items);
03901 
03902   menu_items = gtk_menu_item_new_with_label("Client commands");
03903   gtk_menu_append(GTK_MENU (helpmenu), menu_items);
03904   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03905                             GTK_SIGNAL_FUNC(chelpdialog), NULL);
03906   gtk_widget_show(menu_items);
03907 
03908   menu_items = gtk_menu_item_new_with_label("Server help");
03909   gtk_menu_append(GTK_MENU (helpmenu), menu_items);
03910   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03911                             GTK_SIGNAL_FUNC(shelpdialog), NULL);
03912   gtk_widget_show(menu_items);
03913 
03914   menu_items = gtk_menu_item_new ();
03915   gtk_menu_append(GTK_MENU (helpmenu), menu_items);
03916   gtk_widget_show(menu_items);
03917 
03918   /* Link to things like the client-walkthrough and the playbook? */
03919 
03920   menu_items = gtk_menu_item_new_with_label("Report a bug");
03921   gtk_menu_append(GTK_MENU (helpmenu), menu_items);
03922   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03923                             GTK_SIGNAL_FUNC(bugdialog), NULL);
03924   gtk_widget_show(menu_items);
03925 
03926   menu_items = gtk_menu_item_new ();
03927   gtk_menu_append(GTK_MENU (helpmenu), menu_items);
03928   gtk_widget_show(menu_items);
03929 
03930 
03931   menu_items = gtk_menu_item_new_with_label("About");
03932   gtk_menu_append(GTK_MENU (helpmenu), menu_items);
03933   gtk_signal_connect_object(GTK_OBJECT(menu_items), "activate",
03934                             GTK_SIGNAL_FUNC(aboutdialog), NULL);
03935   gtk_widget_show(menu_items);
03936 
03937   root_helpmenu = gtk_menu_item_new_with_label("Help");
03938 
03939   gtk_widget_show(root_helpmenu);
03940   gtk_menu_item_set_submenu(GTK_MENU_ITEM (root_helpmenu), helpmenu);
03941 
03942   /* Create a menu-bar to hold the menus and add it to our main window */
03943 
03944 
03945   menu_bar = gtk_menu_bar_new();
03946   gtk_box_pack_start(GTK_BOX(box), menu_bar, FALSE, FALSE, 2);
03947   gtk_widget_show(menu_bar);
03948 
03949   /* Create a button to which to attach menu as a popup */
03950 
03951   /* And finally we append the menu-item to the menu-bar -- this is the
03952    * "root" menu-item I have been raving about =) */
03953   gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), root_filemenu);
03954   gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), root_clientmenu);
03955   gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), root_actionmenu);
03956   gtk_menu_item_right_justify (GTK_MENU_ITEM(root_helpmenu));
03957   gtk_menu_bar_append(GTK_MENU_BAR (menu_bar), root_helpmenu);
03958 
03959   /* Always display the window as the last step so it all splashes on
03960    * the screen at once. */
03961 
03962   return 0;
03963 }
03964 
03965 
03966 
03967 /* get_root_display:
03968  * This sets up the root window (or none, if in split
03969  * windows mode, and also scans for any Xdefaults.  Right now, only
03970  * splitwindow and image are used.  image is the display
03971  * mechanism to use.  I thought having one type that is set
03972  * to font, xpm, or pixmap was better than using xpm and pixmap
03973  * resources with on/off values (which gets pretty weird
03974  * if one of this is set to off.
03975  */
03976 
03977 
03978 /* Create the splash window at startup */
03979 
03980 static void create_splash(void) {
03981     GtkWidget *vbox;
03982     GtkWidget *aboutgtkpixmap;
03983     GdkPixmap *aboutgdkpixmap;
03984     GdkBitmap *aboutgdkmask;
03985     GtkStyle *style;
03986 
03987     gtkwin_splash = gtk_window_new (GTK_WINDOW_DIALOG);
03988     gtk_window_position (GTK_WINDOW (gtkwin_splash), GTK_WIN_POS_CENTER);
03989     gtk_widget_set_usize (gtkwin_splash,346,87);
03990     gtk_window_set_title (GTK_WINDOW (gtkwin_splash), "Welcome to Crossfire");
03991     gtk_signal_connect (GTK_OBJECT (gtkwin_splash), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &gtkwin_splash);
03992 
03993     gtk_container_border_width (GTK_CONTAINER (gtkwin_splash), 0);
03994     vbox = gtk_vbox_new(FALSE, 0);
03995     gtk_container_add (GTK_CONTAINER(gtkwin_splash),vbox);
03996     style = gtk_widget_get_style(gtkwin_splash);
03997     gtk_widget_realize(gtkwin_splash);
03998     aboutgdkpixmap = gdk_pixmap_create_from_xpm_d(gtkwin_splash->window,
03999                                                &aboutgdkmask,
04000                                                   &style->bg[GTK_STATE_NORMAL],
04001                                                (gchar **)crossfiretitle_xpm);
04002     aboutgtkpixmap= gtk_pixmap_new (aboutgdkpixmap, aboutgdkmask);
04003     gtk_box_pack_start (GTK_BOX (vbox),aboutgtkpixmap, FALSE, TRUE, 0);
04004     gtk_widget_show (aboutgtkpixmap);
04005 
04006     gtk_widget_show (vbox);
04007     gtk_widget_show (gtkwin_splash);
04008 
04009 
04010     while ( gtk_events_pending() ) {
04011         gtk_main_iteration();
04012     }
04013     sleep (1);
04014     while ( gtk_events_pending() ) {
04015         gtk_main_iteration();
04016     }
04017 
04018 }
04019 
04020 
04021 static void destroy_splash(void) {
04022   gtk_widget_destroy(gtkwin_splash);
04023 }
04024 
04025 /* Error handlers removed.  Right now, there is nothing for
04026  * the client to do if it gets a fatal error - it doesn't have
04027  * any information to save.  And we might as well let the standard
04028  * X11 error handler handle non fatal errors.
04029  */
04030 
04031 
04032 void create_windows(void) {
04033   GtkWidget *rootvbox;
04034   GtkWidget *frame;
04035   int i;
04036 
04037   tooltips = gtk_tooltips_new();
04038 
04039   if (want_config[CONFIG_SPLITWIN]==FALSE) {
04040     GtkStyle    *style;
04041     int gcw;
04042     int gch;
04043     int rootwin_width;
04044     int rootwin_height;
04045 
04046     gtkwin_root = gtk_window_new (GTK_WINDOW_TOPLEVEL);
04047     style = gtk_rc_get_style(gtkwin_root);
04048     if (style) {
04049 #ifdef CFGTK2 /* GTK 2.2 stuff */
04050         gcw = gdk_char_width(gdk_font_from_description(style->font_desc), '0') + 4;
04051         gch = gdk_char_height(gdk_font_from_description(style->font_desc), '0') + 2;
04052 #else
04053         gcw = gdk_char_width(style->font, '0') + 4;
04054         gch = gdk_char_height(style->font, '0') + 2;
04055 #endif
04056     } else {
04057         /* These are what the old defaults values were */
04058         gcw = 11;
04059         gch = 10;
04060     }
04061 
04062     gtk_widget_set_events (gtkwin_root, GDK_KEY_RELEASE_MASK);
04063     gtk_widget_set_uposition (gtkwin_root, 0, 0);
04064 
04065     if ((55*gcw)+(map_image_size*use_config[CONFIG_MAPWIDTH]) >= gdk_screen_width())
04066         rootwin_width = gdk_screen_width() - 30;
04067     else
04068         rootwin_width = (55*gcw)+(map_image_size*use_config[CONFIG_MAPWIDTH]);
04069     if ((33*gch)+(map_image_size*use_config[CONFIG_MAPHEIGHT]) >= gdk_screen_height())
04070         rootwin_height = gdk_screen_height() - 50;
04071     else
04072         rootwin_height = (33*gch)+(map_image_size*use_config[CONFIG_MAPHEIGHT]);
04073     gtk_widget_set_usize (gtkwin_root,rootwin_width,rootwin_height);
04074     gtk_window_set_title (GTK_WINDOW (gtkwin_root), "Crossfire GTK Client");
04075     gtk_signal_connect_object(GTK_OBJECT(gtkwin_root), "destroy",GTK_SIGNAL_FUNC(main_window_destroyed), NULL);
04076 
04077     gtk_container_border_width (GTK_CONTAINER (gtkwin_root), 0);
04078 
04079     /* Alloc colors.  colorname[] comes from xutil.c */
04080     for (i=0; i<=12; i++ ) {
04081         if ( !gdk_color_parse(colorname[i], &root_color[i])) {
04082             printf ("cparse failed (%s)\n",colorname[i]);
04083         }
04084         if ( !gdk_color_alloc (gtk_widget_get_colormap (gtkwin_root), &root_color[i])) {
04085             printf ("calloc failed\n");
04086         }
04087     }
04088 
04089     /* menu / windows division */
04090     rootvbox = gtk_vbox_new(FALSE, 0);
04091     gtk_container_add (GTK_CONTAINER (gtkwin_root), rootvbox);
04092     gtk_widget_show (rootvbox);
04093 
04094     get_menu_display(rootvbox);
04095 
04096     /* first horizontal division. inv+obj on left, rest on right */
04097 
04098     inv_hpane = gtk_hpaned_new ();
04099 
04100     gtk_box_pack_start (GTK_BOX (rootvbox), inv_hpane, TRUE, TRUE, 0);
04101     gtk_container_border_width (GTK_CONTAINER(inv_hpane), 5);
04102     gtk_widget_show (inv_hpane);
04103 
04104     /* Divisior game+stats | text */
04105 
04106     stat_info_hpane = gtk_hpaned_new ();
04107     gtk_paned_add2 (GTK_PANED (inv_hpane), stat_info_hpane);
04108 
04109     /* text frame */
04110 
04111     frame = gtk_frame_new (NULL);
04112     gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
04113     gtk_widget_set_usize (frame, (25*gcw), (30*gch));
04114     gtk_paned_add2 (GTK_PANED (stat_info_hpane), frame);
04115 
04116     get_info_display (frame);
04117     gtk_widget_show (frame);
04118 
04119     /* game & statbars below, stats above */
04120     stat_game_vpane = gtk_vpaned_new ();
04121     gtk_paned_add1 (GTK_PANED (stat_info_hpane), stat_game_vpane);
04122 
04123 #if 0
04124     /* game - statbars */
04125     if (want_config[CONFIG_MAPWIDTH]>15) {
04126         bigmap=TRUE;
04127 
04128         game_bar_vpane = gtk_hpaned_new ();
04129         gtk_paned_add1 (GTK_PANED (stat_game_vpane), game_bar_vpane);
04130     } else {
04131         game_bar_vpane = gtk_vpaned_new ();
04132         gtk_paned_add2 (GTK_PANED (stat_game_vpane), game_bar_vpane);
04133     }
04134 #else
04135     game_bar_vpane = gtk_vpaned_new ();
04136     gtk_paned_add2 (GTK_PANED (stat_game_vpane), game_bar_vpane);
04137 #endif
04138 
04139 
04140     /* Statbars frame */
04141     message_frame = gtk_frame_new (NULL);
04142     gtk_frame_set_shadow_type (GTK_FRAME(message_frame), GTK_SHADOW_ETCHED_IN);
04143     gtk_widget_set_usize (message_frame, (22*gcw)+6,  (map_image_size*use_config[CONFIG_MAPHEIGHT])+6);
04144     gtk_paned_add2 (GTK_PANED (game_bar_vpane), message_frame);
04145 
04146     get_message_display(message_frame);
04147 
04148     gtk_widget_show (message_frame);
04149 
04150     /* Game frame */
04151     gameframe = gtk_frame_new (NULL);
04152     gtk_frame_set_shadow_type (GTK_FRAME(gameframe), GTK_SHADOW_ETCHED_IN);
04153     gtk_widget_set_usize (gameframe, (map_image_size*use_config[CONFIG_MAPWIDTH])+6, (map_image_size*use_config[CONFIG_MAPHEIGHT])+6);
04154 
04155     if (bigmap)
04156         gtk_paned_add2 (GTK_PANED (stat_game_vpane), gameframe);
04157     else
04158         gtk_paned_add1 (GTK_PANED (game_bar_vpane), gameframe);
04159 
04160     get_game_display (gameframe);
04161 
04162     gtk_widget_show (gameframe);
04163 
04164     /* stats frame */
04165     stat_frame = gtk_frame_new (NULL);
04166     gtk_frame_set_shadow_type (GTK_FRAME(stat_frame), GTK_SHADOW_ETCHED_IN);
04167     if (bigmap)
04168         gtk_paned_add1 (GTK_PANED (game_bar_vpane), stat_frame);
04169     else
04170         gtk_paned_add1 (GTK_PANED (stat_game_vpane), stat_frame);
04171 
04172     get_stats_display (stat_frame);
04173 
04174     gtk_widget_show (stat_frame);
04175 
04176     gtk_widget_show (game_bar_vpane);
04177     gtk_widget_show (stat_game_vpane);
04178 
04179     inv_look_vpane = gtk_vpaned_new ();
04180     gtk_paned_add1 (GTK_PANED (inv_hpane), inv_look_vpane);
04181 
04182     /* inventory frame */
04183     frame = gtk_frame_new (NULL);
04184     gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
04185     gtk_widget_set_usize (frame, (24*gcw), (33*gch));
04186     gtk_paned_add1 (GTK_PANED (inv_look_vpane), frame);
04187 
04188     get_inv_display (frame);
04189 
04190     gtk_widget_show (frame);
04191 
04192     /* look frame */
04193     frame = gtk_frame_new (NULL);
04194     gtk_frame_set_shadow_type (GTK_FRAME(frame), GTK_SHADOW_ETCHED_IN);
04195     gtk_widget_set_usize (frame, (24*gcw), (12*gch));
04196     gtk_paned_add2 (GTK_PANED (inv_look_vpane), frame);
04197 
04198     get_look_display (frame);
04199 
04200     gtk_widget_show (frame);
04201 
04202     gtk_widget_show (inv_look_vpane);
04203 
04204     gtk_widget_show (stat_info_hpane);
04205 
04206     gtk_widget_show (inv_hpane);
04207 
04208 
04209     /* Connect signals */
04210 
04211     gtk_signal_connect_object (GTK_OBJECT (gtkwin_root), "key_press_event",
04212                                GTK_SIGNAL_FUNC(keyfunc), GTK_OBJECT(gtkwin_root));
04213     gtk_signal_connect_object (GTK_OBJECT (gtkwin_root), "key_release_event",
04214                                GTK_SIGNAL_FUNC(keyrelfunc), GTK_OBJECT(gtkwin_root));
04215     gtk_widget_show (gtkwin_root);
04216 
04217 #ifdef HAVE_SDL
04218     if (use_config[CONFIG_DISPLAYMODE]==CFG_DM_SDL)
04219         init_SDL( drawingarea, 0);
04220 #endif
04221 
04222   } else { /* split window mode */
04223 
04224 
04225   /* game window */
04226 
04227     gtkwin_root = gtk_window_new (GTK_WINDOW_TOPLEVEL);
04228     gtk_widget_set_events (gtkwin_root, GDK_KEY_RELEASE_MASK);
04229     gtk_widget_set_uposition (gtkwin_root, 300, 160);
04230     gtk_widget_set_usize (gtkwin_root,(map_image_size*use_config[CONFIG_MAPWIDTH])+6,(map_image_size*use_config[CONFIG_MAPHEIGHT])+6);
04231     gtk_window_set_title (GTK_WINDOW (gtkwin_root), "Crossfire - view");
04232     gtk_window_set_policy (GTK_WINDOW (gtkwin_root), TRUE, TRUE, FALSE);
04233     gtk_signal_connect_object(GTK_OBJECT(gtkwin_root), "destroy",GTK_SIGNAL_FUNC(main_window_destroyed), NULL);
04234 
04235 
04236     gtk_container_border_width (GTK_CONTAINER (gtkwin_root), 0);
04237 
04238 
04239     rootvbox = gtk_vbox_new(FALSE, 0);
04240     gtk_container_add (GTK_CONTAINER (gtkwin_root), rootvbox);
04241 
04242     gtk_widget_realize (rootvbox);
04243 
04244     gtk_widget_realize (gtkwin_root);
04245 
04246 
04247 
04248     gtk_widget_show (rootvbox);
04249     gtk_widget_show (gtkwin_root);
04250     gtk_widget_draw (gtkwin_root,NULL);
04251     gtk_widget_draw (rootvbox,NULL);
04252 
04253     get_game_display(rootvbox);
04254 
04255 
04256 
04257   /* Stats and menu window */
04258     gtkwin_stats = gtk_window_new (GTK_WINDOW_TOPLEVEL);
04259     gtk_widget_set_events (gtkwin_stats, GDK_KEY_RELEASE_MASK);
04260     gtk_widget_set_uposition (gtkwin_stats, 300, 0);
04261     gtk_widget_set_usize (gtkwin_stats,(map_image_size*use_config[CONFIG_MAPWIDTH])+6,140);
04262     gtk_window_set_title (GTK_WINDOW (gtkwin_stats), "Crossfire GTK Client");
04263     gtk_window_set_policy (GTK_WINDOW (gtkwin_stats), TRUE, TRUE, FALSE);
04264     gtk_signal_connect (GTK_OBJECT (gtkwin_stats), "destroy", GTK_SIGNAL_FUNC(main_window_destroyed), &gtkwin_stats);
04265 
04266     gtk_container_border_width (GTK_CONTAINER (gtkwin_stats), 0);
04267 
04268 
04269     rootvbox = gtk_vbox_new(FALSE, 0);
04270     gtk_container_add (GTK_CONTAINER (gtkwin_stats), rootvbox);
04271     gtk_widget_show (rootvbox);
04272 
04273     get_menu_display(rootvbox);
04274     get_stats_display (rootvbox);
04275     gtk_widget_realize (gtkwin_stats);
04276     gdk_window_set_group (gtkwin_stats->window, gtkwin_root->window);
04277     gtk_widget_show (gtkwin_stats);
04278 
04279 
04280    /* info window - text and messages */
04281     gtkwin_info = gtk_window_new (GTK_WINDOW_TOPLEVEL);
04282     gtk_widget_set_events (gtkwin_info, GDK_KEY_RELEASE_MASK);
04283     gtk_widget_set_uposition (gtkwin_info, 570, 0);
04284     gtk_widget_set_usize (gtkwin_info,400,600);
04285     gtk_window_set_title (GTK_WINDOW (gtkwin_info), "Crossfire - info");
04286     gtk_window_set_policy (GTK_WINDOW (gtkwin_info), TRUE, TRUE, FALSE);
04287     gtk_signal_connect (GTK_OBJECT (gtkwin_info), "destroy", GTK_SIGNAL_FUNC(main_window_destroyed), &gtkwin_info);
04288 
04289     gtk_container_border_width (GTK_CONTAINER (gtkwin_info), 0);
04290 
04291     /* Alloc colors - not entirely necessary, really, since GTK should do this */
04292     /* colorname[] comes from xutil.c */
04293     for (i=0; i<=12; i++ ) {
04294         if ( !gdk_color_parse(colorname[i], &root_color[i])) {
04295             printf ("cparse failed (%s)\n",colorname[i]);
04296         }
04297         if ( !gdk_color_alloc (gtk_widget_get_colormap (gtkwin_info), &root_color[i])) {
04298             printf ("calloc failed\n");
04299         }
04300     }
04301 
04302     rootvbox = gtk_vbox_new(FALSE, 0);
04303     gtk_container_add (GTK_CONTAINER (gtkwin_info), rootvbox);
04304     gtk_widget_show (rootvbox);
04305 
04306     get_info_display(rootvbox);
04307 
04308     gtk_widget_show (gtkwin_info);
04309     gtk_widget_realize (gtkwin_info);
04310     gdk_window_set_group (gtkwin_info->window, gtkwin_root->window);
04311 
04312  /* statbars window */
04313     gtkwin_message = gtk_window_new (GTK_WINDOW_TOPLEVEL);
04314     gtk_widget_set_events (gtkwin_message, GDK_KEY_RELEASE_MASK);
04315     gtk_widget_set_uposition (gtkwin_message, 300, 450);
04316     gtk_widget_set_usize (gtkwin_message,(map_image_size*use_config[CONFIG_MAPWIDTH])+6,170);
04317     gtk_window_set_title (GTK_WINDOW (gtkwin_message), "Crossfire - vitals");
04318     gtk_window_set_policy (GTK_WINDOW (gtkwin_message), TRUE, TRUE, FALSE);
04319     gtk_signal_connect (GTK_OBJECT (gtkwin_message), "destroy", GTK_SIGNAL_FUNC(main_window_destroyed), &gtkwin_message);
04320 
04321     gtk_container_border_width (GTK_CONTAINER (gtkwin_message), 0);
04322 
04323 
04324     rootvbox = gtk_vbox_new(FALSE, 0);
04325     gtk_container_add (GTK_CONTAINER (gtkwin_message), rootvbox);
04326     gtk_widget_show (rootvbox);
04327 
04328     get_message_display(rootvbox);
04329 
04330     gtk_widget_show (gtkwin_message);
04331     gtk_widget_realize (gtkwin_message);
04332     gdk_window_set_group (gtkwin_message->window, gtkwin_root->window);
04333 
04334  /* inventory window */
04335     gtkwin_inv = gtk_window_new (GTK_WINDOW_TOPLEVEL);
04336     gtk_widget_set_events (gtkwin_inv, GDK_KEY_RELEASE_MASK);
04337     gtk_widget_set_uposition (gtkwin_inv, 0, 0);
04338     gtk_widget_set_usize (gtkwin_inv,290,400);
04339     gtk_window_set_title (GTK_WINDOW (gtkwin_inv), "Crossfire - inventory");
04340     gtk_window_set_policy (GTK_WINDOW (gtkwin_inv), TRUE, TRUE, FALSE);
04341     gtk_signal_connect (GTK_OBJECT (gtkwin_inv), "destroy", GTK_SIGNAL_FUNC(main_window_destroyed), &gtkwin_inv);
04342 
04343     gtk_container_border_width (GTK_CONTAINER (gtkwin_inv), 0);
04344 
04345 
04346     rootvbox = gtk_vbox_new(FALSE, 0);
04347     gtk_container_add (GTK_CONTAINER (gtkwin_inv), rootvbox);
04348     gtk_widget_show (rootvbox);
04349 
04350     get_inv_display(rootvbox);
04351 
04352     gtk_widget_show (gtkwin_inv);
04353     gtk_widget_realize (gtkwin_inv);
04354     gdk_window_set_group (gtkwin_inv->window, gtkwin_root->window);
04355  /* look window */
04356     gtkwin_look = gtk_window_new (GTK_WINDOW_TOPLEVEL);
04357     gtk_widget_set_events (gtkwin_look, GDK_KEY_RELEASE_MASK);
04358     gtk_widget_set_uposition (gtkwin_look, 0, 420);
04359     gtk_widget_set_usize (gtkwin_look,290,150);
04360     gtk_window_set_title (GTK_WINDOW (gtkwin_look), "Crossfire - look");
04361     gtk_window_set_policy (GTK_WINDOW (gtkwin_look), TRUE, TRUE, FALSE);
04362     gtk_signal_connect (GTK_OBJECT (gtkwin_look), "destroy", GTK_SIGNAL_FUNC(main_window_destroyed), &gtkwin_look);
04363 
04364     gtk_container_border_width (GTK_CONTAINER (gtkwin_look), 0);
04365 
04366 
04367     rootvbox = gtk_vbox_new(FALSE, 0);
04368     gtk_container_add (GTK_CONTAINER (gtkwin_look), rootvbox);
04369     gtk_widget_show (rootvbox);
04370 
04371     get_look_display(rootvbox);
04372 
04373     gtk_widget_show (gtkwin_look);
04374     gtk_widget_realize (gtkwin_look);
04375     gdk_window_set_group (gtkwin_look->window, gtkwin_root->window);
04376     /* Setup key events */
04377 
04378     gtk_signal_connect_object (GTK_OBJECT (gtkwin_message), "key_press_event",
04379                                GTK_SIGNAL_FUNC(keyfunc), GTK_OBJECT(gtkwin_message));
04380     gtk_signal_connect_object (GTK_OBJECT (gtkwin_message), "key_release_event",
04381                                GTK_SIGNAL_FUNC(keyrelfunc), GTK_OBJECT(gtkwin_message));
04382 
04383     gtk_signal_connect_object (GTK_OBJECT (gtkwin_root), "key_press_event",
04384                                GTK_SIGNAL_FUNC(keyfunc), GTK_OBJECT(gtkwin_root));
04385     gtk_signal_connect_object (GTK_OBJECT (gtkwin_root), "key_release_event",
04386                                GTK_SIGNAL_FUNC(keyrelfunc), GTK_OBJECT(gtkwin_root));
04387 
04388     gtk_signal_connect_object (GTK_OBJECT (gtkwin_info), "key_press_event",
04389                                GTK_SIGNAL_FUNC(keyfunc), GTK_OBJECT(gtkwin_info));
04390     gtk_signal_connect_object (GTK_OBJECT (gtkwin_info), "key_release_event",
04391                                GTK_SIGNAL_FUNC(keyrelfunc), GTK_OBJECT(gtkwin_info));
04392 
04393     gtk_signal_connect_object (GTK_OBJECT (gtkwin_look), "key_press_event",
04394                                GTK_SIGNAL_FUNC(keyfunc), GTK_OBJECT(gtkwin_look));
04395     gtk_signal_connect_object (GTK_OBJECT (gtkwin_look), "key_release_event",
04396                                GTK_SIGNAL_FUNC(keyrelfunc), GTK_OBJECT(gtkwin_look));
04397 
04398     gtk_signal_connect_object (GTK_OBJECT (gtkwin_inv), "key_press_event",
04399                                GTK_SIGNAL_FUNC(keyfunc), GTK_OBJECT(gtkwin_inv));
04400     gtk_signal_connect_object (GTK_OBJECT (gtkwin_inv), "key_release_event",
04401                                GTK_SIGNAL_FUNC(keyrelfunc), GTK_OBJECT(gtkwin_inv));
04402 
04403     gtk_signal_connect_object (GTK_OBJECT (gtkwin_stats), "key_press_event",
04404                                GTK_SIGNAL_FUNC(keyfunc), GTK_OBJECT(gtkwin_stats));
04405     gtk_signal_connect_object (GTK_OBJECT (gtkwin_stats), "key_release_event",
04406                                GTK_SIGNAL_FUNC(keyrelfunc), GTK_OBJECT(gtkwin_stats));
04407 
04408 #ifdef HAVE_SDL
04409     if (use_config[CONFIG_DISPLAYMODE]==CFG_DM_SDL)
04410         init_SDL( drawingarea, 0);
04411 #endif
04412 
04413   } /* else split windows */
04414 
04415   /* load window positions from file */
04416   set_window_pos();
04417   gtk_tooltips_set_delay(tooltips, 1000 );
04418   if (use_config[CONFIG_TOOLTIPS]) {
04419     gtk_tooltips_enable(tooltips);
04420   }
04421 
04422 }
04423 
04424 static int get_root_display(char *display_name,int gargc, char **gargv) {
04425     gtk_init (&gargc,&gargv);
04426     last_str=malloc(32767);
04427 
04428     if (want_config[CONFIG_SPLASH]) create_splash();
04429     /* we need to call gdk_rgb_init very early on, as some of the
04430      * create window functions may do callbacks in which case we try
04431      * to draw the game window.
04432      */
04433     gdk_rgb_init();
04434     create_windows();
04435 
04436     return 0;
04437 }
04438 
04439 
04440 /* null procedures. gtk does this for us. */
04441 
04442 /* TODO Make these commands specific to x11 toolkit. */
04443 void set_scroll(const char *s)
04444 {
04445 }
04446 
04447 
04448 void set_autorepeat(const char *s) /* ...and what does this one *do*, anyway? */
04449 {
04450 }
04451 
04452 
04453 int get_info_width(void)
04454 {
04455     /*
04456      * TODO Have crossfire-server send paragraphs rather than lines, so to
04457      * speak. Except for ASCII maps and things. Then this can go away
04458      * completely.
04459      */
04460     return 40;
04461 }
04462 
04463 
04464 
04465 /***********************************************************************
04466  *
04467  * Here is the start of event handling functions
04468  *
04469  ***********************************************************************/
04470 
04471 
04472 
04473 /* This function handles the reading of the X Events and then
04474  * doing the appropriate action.  For most input events, it is calling
04475  * another function.
04476  *
04477  * It can also call display functions to make sure the information is
04478  * correct - in this way, updates will not be done so often (like
04479  * for every ITEM command received), but less frequently but still
04480  * update the display fully.  All the functions above are optimized to
04481  * only draw stuff that needs drawing.  So calling them a lot is not
04482  * going to draw stuff too much.
04483  */
04484 
04485 void do_clearlock(void) {
04486 }
04487 
04488 void x_set_echo(void) {
04489   gtk_entry_set_visibility(GTK_ENTRY(entrytext), !cpl.no_echo);
04490 }
04491 
04492 void draw_info_windows(void)
04493     {
04494     if (draw_info_freeze1) {
04495         gtk_text_thaw (GTK_TEXT (gtkwin_info_text));
04496         gtk_adjustment_set_value(GTK_ADJUSTMENT(text_vadj), GTK_ADJUSTMENT(text_vadj)->upper-GTK_ADJUSTMENT(text_vadj)->page_size);
04497         gtk_text_set_adjustments(GTK_TEXT (gtkwin_info_text),GTK_ADJUSTMENT(text_hadj),GTK_ADJUSTMENT(text_vadj));
04498         draw_info_freeze1=FALSE;
04499     }
04500     if (draw_info_freeze2) {
04501         gtk_text_thaw (GTK_TEXT (gtkwin_info_text2));
04502         gtk_adjustment_set_value(GTK_ADJUSTMENT(text_vadj2), GTK_ADJUSTMENT(text_vadj2)->upper-GTK_ADJUSTMENT(text_vadj2)->page_size);
04503         gtk_text_set_adjustments(GTK_TEXT (gtkwin_info_text2),GTK_ADJUSTMENT(text_hadj2),GTK_ADJUSTMENT(text_vadj2));
04504         draw_info_freeze2=FALSE;
04505     }
04506     }
04507 
04508 
04509 /* X11 client doesn't care about this */
04510 void client_tick(uint32 tick)
04511 {
04512     inventory_tick();
04513     mapdata_animation();
04514 #ifdef HAVE_SDL
04515     if (use_config[CONFIG_DISPLAYMODE]==CFG_DM_SDL) sdl_gen_map(0);
04516     else
04517 #endif
04518     gtk_draw_map(0);
04519 }
04520 
04524 void client_pickup(uint32 pickup)
04525 {
04526     int menu;
04527 
04528     /* Update value, so handling function won't resend info. */
04529     pickup_mode = pickup;
04530 
04531     for (menu = 0; menu < pickup_count; menu++)
04532         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(pickup_menus[menu]), (pickup & pickup_value[menu]) ? 1 : 0);
04533 }
04534 
04535 int do_timeout(void) {
04536 
04537     updatelock=0;
04538 
04539     if (!tick) {
04540         inventory_tick();
04541         mapdata_animation();
04542     }
04543     update_spell_list(0);
04544     draw_info_windows();
04545     if (redraw_needed) {
04546         display_map_doneupdate(TRUE, FALSE);
04547         redraw_needed=FALSE;
04548     }
04549     if (cpl.showmagic) magic_map_flash_pos();
04550     return TRUE;
04551 }
04552 
04553 int gtk_checkchilds(void) {
04554     monitorChilds();
04555     return FALSE;
04556 }
04557 
04558 
04559 
04560 /* Here are the old Xutil commands needed. */
04561 /* ----------------------------------------------------------------------------*/
04562 
04563 
04564 /* This function draws the magic map in the game window.  I guess if
04565  * we wanted to get clever, we could open up some other window or
04566  * something.
04567  *
04568  * A lot of this code was taken from server/xio.c  But being all
04569  * the map data has been figured, it tends to be much simpler.
04570  */
04571 void draw_magic_map(void)
04572 {
04573 
04574   int x=0;
04575   int y=0;
04576 
04577   GtkWidget *hbox;
04578   GtkWidget *closebutton;
04579   GtkStyle *style;
04580 
04581   static GtkWidget *magicgtkpixmap;
04582 
04583 
04584   static GdkBitmap *magicgdkmask;
04585 
04586 
04587   if (!cpl.magicmap) {
04588     draw_info ("You have yet to cast magic map.",NDI_BLACK);
04589     return;
04590   }
04591 
04592   if(!gtkwin_magicmap) {
04593 
04594     gtkwin_magicmap = gtk_window_new (GTK_WINDOW_DIALOG);
04595     gtk_window_position (GTK_WINDOW (gtkwin_magicmap), GTK_WIN_POS_CENTER);
04596     gtk_widget_set_usize (gtkwin_magicmap,264,300);
04597     gtk_window_set_title (GTK_WINDOW (gtkwin_magicmap), "Magic map");
04598     gtk_window_set_policy (GTK_WINDOW (gtkwin_magicmap), FALSE, FALSE, FALSE);
04599 
04600     gtk_signal_connect (GTK_OBJECT (gtkwin_magicmap), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &gtkwin_magicmap);
04601 
04602     mapvbox = gtk_vbox_new(FALSE, 0);
04603     gtk_widget_set_usize (mapvbox,264,300);
04604     gtk_container_add (GTK_CONTAINER(gtkwin_magicmap),mapvbox);
04605 
04606     style = gtk_widget_get_style(gtkwin_magicmap);
04607     gtk_widget_realize(mapvbox);
04608 
04609 
04610     magicgdkpixmap = gdk_pixmap_new(gtkwin_magicmap->window,
04611                                     264,
04612                                     264,
04613                                     -1);
04614     magicgtkpixmap= gtk_pixmap_new (magicgdkpixmap, magicgdkmask);
04615     gtk_box_pack_start (GTK_BOX (mapvbox),magicgtkpixmap, FALSE, FALSE, 0);
04616     gtk_widget_show (magicgtkpixmap);
04617 
04618     hbox = gtk_hbox_new(FALSE, 2);
04619 
04620     closebutton = gtk_button_new_with_label ("Close");
04621     gtk_signal_connect_object (GTK_OBJECT (closebutton), "clicked",
04622                                GTK_SIGNAL_FUNC(gtk_widget_destroy),
04623                                GTK_OBJECT (gtkwin_magicmap));
04624     gtk_box_pack_start (GTK_BOX (hbox), closebutton, TRUE, FALSE, 0);
04625     gtk_box_pack_start (GTK_BOX (mapvbox), hbox, FALSE, FALSE, 0);
04626     gtk_widget_show (closebutton);
04627     gtk_widget_show (hbox);
04628 
04629     gtk_widget_show (mapvbox);
04630     gtk_widget_show (gtkwin_magicmap);
04631 
04632 
04633     gdk_color_parse("Black", &map_color[0]);
04634     gdk_color_alloc (gtk_widget_get_colormap (magicgtkpixmap), &map_color[0]);
04635     gdk_color_parse("White", &map_color[1]);
04636     gdk_color_alloc (gtk_widget_get_colormap (magicgtkpixmap), &map_color[1]);
04637     gdk_color_parse("Navy", &map_color[2]);
04638     gdk_color_alloc (gtk_widget_get_colormap (magicgtkpixmap), &map_color[2]);
04639     gdk_color_parse("Red", &map_color[3]);
04640     gdk_color_alloc (gtk_widget_get_colormap (magicgtkpixmap), &map_color[3]);
04641     gdk_color_parse("Orange", &map_color[4]);
04642     gdk_color_alloc (gtk_widget_get_colormap (magicgtkpixmap), &map_color[4]);
04643     gdk_color_parse("DodgerBlue", &map_color[5]);
04644     gdk_color_alloc (gtk_widget_get_colormap (magicgtkpixmap), &map_color[5]);
04645     gdk_color_parse("DarkOrange2", &map_color[6]);
04646     gdk_color_alloc (gtk_widget_get_colormap (magicgtkpixmap), &map_color[6]);
04647     gdk_color_parse("SeaGreen", &map_color[7]);
04648     gdk_color_alloc (gtk_widget_get_colormap (magicgtkpixmap), &map_color[7]);
04649     gdk_color_parse("DarkSeaGreen", &map_color[8]);
04650     gdk_color_alloc (gtk_widget_get_colormap (magicgtkpixmap), &map_color[8]);
04651     gdk_color_parse("Grey50", &map_color[9]);
04652     gdk_color_alloc (gtk_widget_get_colormap (magicgtkpixmap), &map_color[9]);
04653     gdk_color_parse("Sienna", &map_color[10]);
04654     gdk_color_alloc (gtk_widget_get_colormap (magicgtkpixmap), &map_color[10]);
04655     gdk_color_parse("Gold", &map_color[11]);
04656     gdk_color_alloc (gtk_widget_get_colormap (magicgtkpixmap), &map_color[11]);
04657     gdk_color_parse("Khaki", &map_color[12]);
04658     gdk_color_alloc (gtk_widget_get_colormap (magicgtkpixmap), &map_color[12]);
04659 
04660 
04661     magic_map_gc = gdk_gc_new (magicgdkpixmap);
04662 
04663 
04664    gdk_gc_set_foreground (magic_map_gc, &map_color[0]);
04665    gdk_draw_rectangle (magicgdkpixmap, magic_map_gc,
04666                        TRUE,
04667                        0,
04668                        0,
04669                        264,
04670                        264);
04671     cpl.mapxres = (262)/cpl.mmapx;
04672     cpl.mapyres = (262)/cpl.mmapy;
04673     if (cpl.mapxres < 1 || cpl.mapyres<1) {
04674       LOG(LOG_WARNING,"gtk::draw_magic_map","magic map resolution less than 1, map is %dx%d",
04675               cpl.mmapx, cpl.mmapy);
04676       return;
04677     }
04678     /* In theory, cpl.mapxres and cpl.mapyres do not have to be the same.  However,
04679      * it probably makes sense to keep them the same value.
04680      * Need to take the smaller value.
04681      */
04682     if (cpl.mapxres>cpl.mapyres) cpl.mapxres=cpl.mapyres;
04683     else cpl.mapyres=cpl.mapxres;
04684 
04685     if (cpl.mapxres>24) {
04686       cpl.mapxres=24;
04687       cpl.mapyres=24;
04688     }
04689     /* This is keeping the same unpacking scheme that the server uses
04690      * to pack it up.
04691      */
04692     for (y = 0; y < cpl.mmapy; y++) {
04693       for (x = 0; x < cpl.mmapx; x++) {
04694         uint8 val = cpl.magicmap[y*cpl.mmapx + x];
04695 
04696     gdk_gc_set_foreground (magic_map_gc, &map_color[val&FACE_COLOR_MASK]);
04697 
04698         gdk_draw_rectangle (magicgdkpixmap, magic_map_gc,
04699                             TRUE,
04700                             2+cpl.mapxres*x,
04701                             2+cpl.mapyres*y,
04702                             cpl.mapxres,
04703                             cpl.mapyres);
04704       } /* Saw into this space */
04705     }
04706     /*    gdk_gc_destroy (magic_map_gc);*/
04707     gtk_widget_draw (mapvbox,NULL);
04708   }
04709 
04710   else {
04711     /* ------------------ There is already a magic map up - replace it ---------*/
04712 
04713     gdk_window_raise (gtkwin_magicmap->window);
04714     /* --------------------------- */
04715 
04716    gdk_gc_set_foreground (magic_map_gc, &map_color[0]);
04717    gdk_draw_rectangle (magicgdkpixmap, magic_map_gc,
04718                        TRUE,
04719                        0,
04720                        0,
04721                        264,
04722                        264);
04723 
04724     cpl.mapxres = (262)/cpl.mmapx;
04725     cpl.mapyres = (262)/cpl.mmapy;
04726     if (cpl.mapxres < 1 || cpl.mapyres<1) {
04727       LOG(LOG_WARNING,"gtk::draw_magic_map","magic map resolution less than 1, map is %dx%d\n",
04728               cpl.mmapx, cpl.mmapy);
04729       return;
04730     }
04731 
04732     if (cpl.mapxres>cpl.mapyres) cpl.mapxres=cpl.mapyres;
04733     else cpl.mapyres=cpl.mapxres;
04734 
04735 
04736 
04737     if (cpl.mapxres>24) {
04738       cpl.mapxres=24;
04739       cpl.mapyres=24;
04740     }
04741 
04742 
04743 
04744     for (y = 0; y < cpl.mmapy; y++) {
04745       for (x = 0; x < cpl.mmapx; x++) {
04746         uint8 val = cpl.magicmap[y*cpl.mmapx + x];
04747 
04748     gdk_gc_set_foreground (magic_map_gc, &map_color[val&FACE_COLOR_MASK]);
04749 
04750         gdk_draw_rectangle (magicgdkpixmap, magic_map_gc,
04751                             TRUE,
04752                             2+cpl.mapxres*x,
04753                             2+cpl.mapyres*y,
04754                             cpl.mapxres,
04755                             cpl.mapyres);
04756 
04757       }
04758 
04759     }
04760  gtk_widget_draw (mapvbox,NULL);
04761   }
04762 }
04763 
04764 /* Basically, this just flashes the player position on the magic map */
04765 
04766 void magic_map_flash_pos(void)
04767 {
04768   if (!cpl.showmagic) return;
04769   if (!gtkwin_magicmap) return;
04770   cpl.showmagic ^=2;
04771   if (cpl.showmagic & 2) {
04772     gdk_gc_set_foreground (magic_map_gc, &map_color[0]);
04773   } else {
04774     gdk_gc_set_foreground (magic_map_gc, &map_color[1]);
04775   }
04776   gdk_draw_rectangle (magicgdkpixmap, magic_map_gc,
04777                       TRUE,
04778                       2+cpl.mapxres*cpl.pmapx,
04779                       2+cpl.mapyres*cpl.pmapy,
04780                       cpl.mapxres,
04781                       cpl.mapyres);
04782   gtk_widget_draw (mapvbox,NULL);
04783 }
04784 
04785 /* Gets a specified windows coordinates.  This function is pretty much
04786  * an exact copy out of the server.
04787  */
04788 
04789 void get_window_coord(GtkWidget *win,
04790                  int *x,int *y,
04791                  int *wx,int *wy,
04792                  int *w,int *h)
04793 {
04794   int tmp;
04795   gdk_window_get_geometry (win->window, x, y, w, h, &tmp);
04796 /*  gdk_window_get_root_origin (win->window, wx, wy); */
04797 /*  gdk_window_get_deskrelative_origin (win->window, wx, wy); */
04798   gdk_window_get_origin (win->window, wx, wy);
04799   *wx -= *x;
04800   *wy -= *y;
04801 }
04802 
04803 
04804 void save_winpos(void)
04805 {
04806     char savename[MAX_BUF],buf[MAX_BUF];
04807     FILE    *fp;
04808     int     x,y,w,h,wx,wy;
04809 
04810     if (!want_config[CONFIG_SPLITWIN])
04811         sprintf(savename,"%s/.crossfire/gwinpos", getenv("HOME"));
04812     else
04813         sprintf(savename,"%s/.crossfire/winpos", getenv("HOME"));
04814 
04815     if (!(fp=fopen(savename,"w"))) {
04816         sprintf(buf,"Unable to open %s, window positions not saved",savename);
04817         draw_info(buf,NDI_BLUE);
04818         return;
04819     }
04820 
04821     get_window_coord(gtkwin_root, &x,&y, &wx,&wy,&w,&h);
04822     fprintf(fp,"win_game: %d %d %d %d\n", wx,wy, w, h);
04823     if (want_config[CONFIG_SPLITWIN]) {
04824         get_window_coord(gtkwin_stats, &x,&y, &wx,&wy,&w,&h);
04825         fprintf(fp,"win_stats: %d %d %d %d\n", wx,wy, w, h);
04826         get_window_coord(gtkwin_info, &x,&y, &wx,&wy,&w,&h);
04827         fprintf(fp,"win_info: %d %d %d %d\n", wx,wy, w, h);
04828         get_window_coord(gtkwin_inv, &x,&y, &wx,&wy,&w,&h);
04829         fprintf(fp,"win_inv: %d %d %d %d\n", wx,wy, w, h);
04830         get_window_coord(gtkwin_look, &x,&y, &wx,&wy,&w,&h);
04831         fprintf(fp,"win_look: %d %d %d %d\n", wx,wy, w, h);
04832         get_window_coord(gtkwin_message, &x,&y, &wx,&wy,&w,&h);
04833         fprintf(fp,"win_message: %d %d %d %d\n", wx,wy, w, h);
04834     } else {
04835         /* in non split mode, we really want the position of the
04836          * various panes.  Current versions do not have a proper
04837          * way (ie, function call/macro) to do this - future
04838          * versions of gtk will have a gtk_paned_get_position.
04839          * That code basically does the same thing as what we
04840          * are doing below (version 1.3)
04841          */
04842         fprintf(fp,"inv_hpane: %d\n",
04843                 GTK_PANED(inv_hpane)->child1_size);
04844         fprintf(fp,"stat_info_hpane: %d\n",
04845                 GTK_PANED(stat_info_hpane)->child1_size);
04846         fprintf(fp,"stat_game_vpane: %d\n",
04847                 GTK_PANED(stat_game_vpane)->child1_size);
04848         fprintf(fp,"game_bar_vpane: %d\n",
04849                 GTK_PANED(game_bar_vpane)->child1_size);
04850         fprintf(fp,"inv_look_vpane: %d\n",
04851                 GTK_PANED(inv_look_vpane)->child1_size);
04852         if (use_config[CONFIG_SPLITINFO])
04853             fprintf(fp,"info_vpane: %d\n",
04854                 GTK_PANED(info_vpane)->child1_size);
04855     }
04856     fclose(fp);
04857     sprintf(buf,"Window positions saved to %s",savename);
04858     draw_info(buf,NDI_BLUE);
04859 }
04860 
04861 
04862 /* Reads in the winpos file created by the above function and sets the
04863  * the window positions appropriately.
04864  */
04865 void set_window_pos(void)
04866 {
04867     gint wx=0;
04868     gint wy=0;
04869     gint w=0;
04870     gint h=0;
04871 
04872     char buf[MAX_BUF],*cp;
04873     FILE *fp;
04874 
04875     if (want_config[CONFIG_SPLITWIN])
04876         sprintf(buf,"%s/.crossfire/winpos", getenv("HOME"));
04877     else
04878         sprintf(buf,"%s/.crossfire/gwinpos", getenv("HOME"));
04879 
04880     if (!(fp=fopen(buf,"r"))) return;
04881 
04882     while(fgets(buf,MAX_BUF-1, fp)!=NULL) {
04883         buf[MAX_BUF-1]='\0';
04884         if (!(cp=strchr(buf,' '))) continue;
04885         *cp++='\0';
04886         if (sscanf(cp,"%d %d %d %d",&wx,&wy,&w,&h)!=4) {
04887             gint pos = atoi(cp);
04888             if (pos == 0) continue;
04889 
04890             if (!strcmp(buf, "inv_hpane:")) gtk_paned_set_position(GTK_PANED(inv_hpane),pos);
04891             else if (!strcmp(buf, "stat_info_hpane:")) gtk_paned_set_position(GTK_PANED(stat_info_hpane),pos);
04892             else if (!strcmp(buf, "stat_game_vpane:")) gtk_paned_set_position(GTK_PANED(stat_game_vpane),pos);
04893             else if (!strcmp(buf, "game_bar_vpane:")) gtk_paned_set_position(GTK_PANED(game_bar_vpane),pos);
04894             else if (!strcmp(buf, "inv_look_vpane:")) gtk_paned_set_position(GTK_PANED(inv_look_vpane),pos);
04895             else if (use_config[CONFIG_SPLITINFO] && !strcmp(buf, "info_vpane:")) gtk_paned_set_position(GTK_PANED(info_vpane),pos);
04896             else LOG(LOG_ERROR,"gtk::set_window_pos","Found bogus line in window position file:\n/%s/ /%s/", buf, cp);
04897         } else {
04898             if (!strcmp(buf,"win_game:")) {
04899                 gdk_window_move_resize(gtkwin_root->window, wx, wy, w, h);
04900                 continue;
04901             }
04902             if (!want_config[CONFIG_SPLITWIN]) {
04903                 LOG(LOG_ERROR,"gtk::set_window_pos","Found bogus line in window position file:\n%s %s", buf, cp);
04904                 continue;
04905             }
04906             if (!strcmp(buf,"win_stats:")) {
04907                 gdk_window_move_resize(gtkwin_stats->window, wx, wy, w, h);
04908             }
04909             if (!strcmp(buf,"win_info:")) {
04910                 gdk_window_move_resize(gtkwin_info->window, wx, wy, w, h);
04911             }
04912             if (!strcmp(buf,"win_inv:")) {
04913                 gdk_window_move_resize(gtkwin_inv->window, wx, wy, w, h);
04914             }
04915             if (!strcmp(buf,"win_look:")) {
04916                 gdk_window_move_resize(gtkwin_look->window, wx, wy, w, h);
04917             }
04918             if (!strcmp(buf,"win_message:")) {
04919                gdk_window_move_resize(gtkwin_message->window, wx, wy, w, h);
04920             }
04921         } /* else if split windows */
04922     } /* while fgets */
04923     fclose(fp);
04924 }
04925 
04926 
04927 
04928 
04929 /***********************************************************************
04930  *
04931  * Here starts the X11 init functions.  It will call other
04932  * functions that were grouped previously by window
04933  *
04934  ***********************************************************************/
04935 
04936 /* Usage routine.  All clients should support server, port and
04937  * display options, with -pix and -xpm also suggested.  -split
04938  * does not need to be supported - it is in this copy because
04939  * the old code supported it.
04940  */
04941 
04942 static void usage(const char *progname)
04943 {
04944     puts("Usage of crossfire-client-gtk:\n\n");
04945     puts("-cache           - Cache images for future use.");
04946     puts("-nocache         - Do not cache images (default action).");
04947     puts("-darkness        - Enables darkness code (default)");
04948     puts("-nodarkness      - Disables darkness code");
04949     puts("-display <name>  - Use <name> instead if DISPLAY environment variable.");
04950     puts("-download_all_faces - Download all needed faces before play starts");
04951     puts("-echo            - Echo the bound commands");
04952     puts("-noecho          - Do not echo the bound commands (default)");
04953     puts("-faceset <name>  - Use faceset <name> if available");
04954     puts("-fasttcpsend     - Send data immediately to server, may increase bandwidth");
04955     puts("-nofasttcpsend   - Disables fasttcpsend");
04956     puts("-fog             - Enable fog of war code");
04957     puts("-help            - Display this message.");
04958     puts("-loglevel <val>  - Set default logging level (0 is most verbose)");
04959     puts("-iconscale %%    - Set icon scale percentage");
04960     puts("-mapscale %%     - Set map scale percentage");
04961     puts("-mapsize xXy     - Set the mapsize to be X by Y spaces. (default 11x11)");
04962     puts("-splash          - Display the splash screen (default)");
04963     puts("-nosplash        - Don't display the splash screen (startup logo)");
04964     puts("-popups          - Use pop up windows for input (default)");
04965     puts("-nopopups        - Don't use pop up windows for input");
04966     puts("-port <number>   - Use port <number> instead of the standard port number");
04967     puts("-sdl             - Use sdl for drawing png (may not work on all hardware");
04968     puts("-server <name>   - Connect to <name> instead of localhost.");
04969     puts("-showicon        - Print status icons in inventory window");
04970     puts("-smooth          - Enable smooth");
04971     puts("-nosmooth        - Disable smooth");
04972     puts("-mapscroll       - Enable mapscrolling by bitmap operations");
04973     puts("-nomapscroll     - Disable mapscrolling by bitmap operations");
04974     puts("-sound           - Enable sound output (default).");
04975     puts("-nosound         - Disable sound output.");
04976     puts("-sound_server <path> - Executable to use to play sounds.");
04977     puts("-resists <val>   - Control look of resistances.");
04978     puts("-split           - Use split windows.");
04979     puts("-splitinfo       - Use two information windows, segregated by information type.");
04980     puts("-timemapredraw   - Print out timing information for map generation");
04981     puts("-triminfowindow  - Trims size of information window(s)");
04982     puts("-notriminfowindow  - Do not trims size of information window(s) (default)");
04983     puts("-updatekeycodes  - Update the saved bindings for this keyboard.");
04984 
04985     exit(0);
04986 }
04987 
04988 /* init_windows:  This initializes all the windows - it is an
04989  * interface routine.  The command line arguments are passed to
04990  * this function to interpret.  Note that it is not in fact
04991  * required to parse anything, but doing at least -server and
04992  * -port would be a good idea.
04993  *
04994  * This function returns 0 on success, nonzero on failure.
04995  */
04996 
04997 int init_windows(int argc, char **argv)
04998 {
04999     int on_arg=1;
05000     char *display_name="";
05001     load_defaults();
05002 
05003 #ifndef WIN32
05004     strcpy(VERSION_INFO,"GTK Unix Client " FULL_VERSION);
05005 #else
05006     strcpy(VERSION_INFO,"GTK Win32 Client " FULL_VERSION);
05007 #endif
05008     /* Set this global so we get skill experience - gtk client can display
05009      * it, so lets get the info.
05010      */
05011     want_skill_exp=1;
05012     for (on_arg=1; on_arg<argc; on_arg++) {
05013         if (!strcmp(argv[on_arg],"-cache")) {
05014             want_config[CONFIG_CACHE]= TRUE;
05015             continue;
05016         }
05017         else if (!strcmp(argv[on_arg],"-nocache")) {
05018             want_config[CONFIG_CACHE]= FALSE;
05019             continue;
05020         }
05021         else if (!strcmp(argv[on_arg],"-darkness")) {
05022             want_config[CONFIG_DARKNESS]= TRUE;
05023             continue;
05024         }
05025         else if (!strcmp(argv[on_arg],"-nodarkness")) {
05026             want_config[CONFIG_DARKNESS]= FALSE;
05027             continue;
05028         }
05029         else if (!strcmp(argv[on_arg],"-display")) {
05030             if (++on_arg == argc) {
05031                 LOG(LOG_WARNING,"gtk::init_windows","-display requires a display name");
05032                 return 1;
05033             }
05034             display_name = argv[on_arg];
05035             continue;
05036         }
05037         else if (!strcmp(argv[on_arg],"-download_all_faces")) {
05038             want_config[CONFIG_DOWNLOAD]= TRUE;
05039             continue;
05040         }
05041         else if (!strcmp(argv[on_arg],"-echo")) {
05042             want_config[CONFIG_ECHO]= TRUE;
05043             continue;
05044         }
05045         else if (!strcmp(argv[on_arg],"-noecho")) {
05046             want_config[CONFIG_ECHO]= FALSE;
05047             continue;
05048         }
05049         else if (!strcmp(argv[on_arg],"-faceset")) {
05050             if (++on_arg == argc) {
05051                 LOG(LOG_WARNING,"gtk::init_windows","-faceset requires a faceset name/number");
05052                 return 1;
05053             }
05054             face_info.want_faceset = argv[on_arg];
05055             continue;
05056         }
05057         else if( !strcmp( argv[on_arg],"-fog")) {
05058             want_config[CONFIG_FOGWAR]= TRUE;
05059             continue;
05060         }
05061         else if( !strcmp( argv[on_arg],"-nofog")) {
05062             want_config[CONFIG_FOGWAR]= FALSE;
05063             continue;
05064         }
05065         else if (!strcmp(argv[on_arg],"-help")) {
05066             usage(argv[0]);
05067             continue;
05068         }
05069         else if( !strcmp( argv[on_arg],"-iconscale")) {
05070             if (++on_arg == argc) {
05071                 LOG(LOG_WARNING,"gtk::init_windows","-iconscale requires a percentage value");
05072                 return 1;
05073             }
05074             want_config[CONFIG_ICONSCALE] = atoi(argv[on_arg]);
05075             if (want_config[CONFIG_ICONSCALE] < 25 || want_config[CONFIG_ICONSCALE]>200) {
05076                 LOG(LOG_WARNING,"gtk::init_windows","Valid range for -iconscale is 25 through 200");
05077                 want_config[CONFIG_ICONSCALE]=100;
05078                 return 1;
05079             }
05080             continue;
05081         }
05082         else if( !strcmp( argv[on_arg],"-mapscale")) {
05083             if (++on_arg == argc) {
05084                 LOG(LOG_WARNING,"gtk::init_windows","-mapscale requires a percentage value");
05085                 return 1;
05086             }
05087             want_config[CONFIG_MAPSCALE] = atoi(argv[on_arg]);
05088             if (want_config[CONFIG_MAPSCALE] < 25 || want_config[CONFIG_MAPSCALE]>200) {
05089                 LOG(LOG_WARNING,"gtk::init_windows","Valid range for -mapscale is 25 through 200");
05090                 want_config[CONFIG_MAPSCALE]=100;
05091                 return 1;
05092             }
05093             continue;
05094         }
05095         else if (!strcmp(argv[on_arg],"-mapsize")) {
05096             char *cp, x, y=0;
05097             if (++on_arg == argc) {
05098                 LOG(LOG_WARNING,"gtk::init_windows","-mapsize requires a XxY value");
05099                 return 1;
05100             }
05101             x = atoi(argv[on_arg]);
05102             for (cp = argv[on_arg]; *cp!='\0'; cp++)
05103                 if (*cp == 'x' || *cp == 'X') break;
05104 
05105             if (*cp==0) {
05106                 LOG(LOG_WARNING,"gtk::init_windows","-mapsize requires both and X and Y value (ie, XxY - note the\nx in between.");
05107             } else {
05108                 y = atoi(cp+1);
05109             }
05110             if (x<9 || y<9) {
05111                 LOG(LOG_WARNING,"gtk::init_windows","map size must be positive values of at least 9");
05112             } else if (x>MAP_MAX_SIZE || y>MAP_MAX_SIZE) {
05113                 LOG(LOG_WARNING,"gtk::init_windows","Map size can not be larger than %d x %d", MAP_MAX_SIZE, MAP_MAX_SIZE);
05114 
05115             } else {
05116                 want_config[CONFIG_MAPWIDTH]=x;
05117                 want_config[CONFIG_MAPHEIGHT]=y;
05118             }
05119             continue;
05120         }
05121         else if (!strcmp(argv[on_arg],"-fasttcpsend")) {
05122             want_config[CONFIG_FASTTCP] = TRUE;
05123             continue;
05124         }
05125         else if (!strcmp(argv[on_arg],"-nofasttcpsend")) {
05126             want_config[CONFIG_FASTTCP] = FALSE;
05127             continue;
05128         }
05129         else if (!strcmp(argv[on_arg],"-popups")) {
05130             want_config[CONFIG_POPUPS] = TRUE;
05131             continue;
05132         }
05133         else if (!strcmp(argv[on_arg],"-nopopups")) {
05134             want_config[CONFIG_POPUPS] = FALSE;
05135             continue;
05136         }
05137         else if (!strcmp(argv[on_arg],"-port")) {
05138             if (++on_arg == argc) {
05139                 LOG(LOG_WARNING,"gtk::init_windows","-port requires a port number");
05140                 return 1;
05141             }
05142             want_config[CONFIG_PORT] = atoi(argv[on_arg]);
05143             continue;
05144         }
05145         else if (!strcmp(argv[on_arg],"-sdl")) {
05146 #ifndef HAVE_SDL
05147             LOG(LOG_WARNING,"gtk::init_windows","client not compiled with sdl support.  Ignoring -sdl");
05148 #else
05149             want_config[CONFIG_DISPLAYMODE] = CFG_DM_SDL;
05150 #endif
05151             continue;
05152         }
05153         else if (!strcmp(argv[on_arg],"+sdl")) {
05154             want_config[CONFIG_DISPLAYMODE] = CFG_DM_PIXMAP;
05155             continue;
05156         }
05157         else if (!strcmp(argv[on_arg],"-server")) {
05158             if (++on_arg == argc) {
05159                 LOG(LOG_WARNING,"gtk::init_windows","-server requires a host name");
05160                 return 1;
05161             }
05162             server = argv[on_arg];
05163             continue;
05164         }
05165         else if (!strcmp(argv[on_arg],"-showicon")) {
05166             want_config[CONFIG_SHOWICON] = TRUE;
05167             continue;
05168         }
05169         else if (!strcmp(argv[on_arg],"-smooth")) {
05170             want_config[CONFIG_SMOOTH] = TRUE;
05171         }
05172         else if (!strcmp(argv[on_arg],"-nosmooth")) {
05173             want_config[CONFIG_SMOOTH] = FALSE;
05174         }
05175         else if (!strcmp(argv[on_arg],"-mapscroll")) {
05176             want_config[CONFIG_MAPSCROLL] = TRUE;
05177         }
05178         else if (!strcmp(argv[on_arg],"-nomapscroll")) {
05179             want_config[CONFIG_MAPSCROLL] = FALSE;
05180         }
05181         else if (!strcmp(argv[on_arg],"-sound")) {
05182             want_config[CONFIG_SOUND] = TRUE;
05183             continue;
05184         }
05185         else if (!strcmp(argv[on_arg],"-nosound")) {
05186             want_config[CONFIG_SOUND] = FALSE;
05187             continue;
05188         }
05189         else if (!strcmp(argv[on_arg],"-sound_server")) {
05190             if (++on_arg == argc) {
05191                 LOG(LOG_WARNING,"gtk::init_windows","-sound_server requires an executable pathname");
05192                 return 1;
05193             }
05194             sound_server = argv[on_arg];
05195             continue;
05196         }
05197         else if (!strcmp(argv[on_arg],"-split")) {
05198             want_config[CONFIG_SPLITWIN]=TRUE;
05199             continue;
05200         }
05201         else if (!strcmp(argv[on_arg],"-nosplit")) {
05202             want_config[CONFIG_SPLITWIN]=FALSE;
05203             continue;
05204         }
05205         else if (!strcmp(argv[on_arg],"-resists")) {
05206             if (++on_arg == argc) {
05207                 LOG(LOG_WARNING,"gtk::init_windows","-resists requires a value");
05208                 return 1;
05209             }
05210             want_config[CONFIG_RESISTS]=atoi(argv[on_arg]);
05211             continue;
05212         }
05213         else if (!strcmp(argv[on_arg],"-loglevel")) {
05214             extern int MINLOG;
05215 
05216             if (++on_arg == argc) {
05217                 LOG(LOG_WARNING,"gtk::init_windows","-loglevel requires a value");
05218                 return 1;
05219             }
05220             MINLOG = atoi(argv[on_arg]);
05221             continue;
05222         }
05223         else if (!strcmp(argv[on_arg],"-splitinfo")) {
05224             want_config[CONFIG_SPLITINFO]=TRUE;
05225             continue;
05226         }
05227         else if (!strcmp(argv[on_arg],"-timemapredraw")) {
05228             time_map_redraw=TRUE;
05229             continue;
05230         }
05231         else if (!strcmp(argv[on_arg],"-triminfowindow")) {
05232             want_config[CONFIG_TRIMINFO] = TRUE;
05233             continue;
05234         }
05235         else if (!strcmp(argv[on_arg],"-notriminfowindow")) {
05236             want_config[CONFIG_TRIMINFO] = FALSE;
05237             continue;
05238         }
05239         else if (!strcmp(argv[on_arg],"-updatekeycodes")) {
05240             updatekeycodes=TRUE;
05241             continue;
05242         }
05243         else if (!strcmp(argv[on_arg],"-splash")) {
05244             want_config[CONFIG_SPLASH] = TRUE;
05245             continue;
05246         }
05247         else if (!strcmp(argv[on_arg],"-nosplash")) {
05248             want_config[CONFIG_SPLASH] = FALSE;
05249             continue;
05250         }
05251         else {
05252             LOG(LOG_WARNING,"gtk::init_windows","Do not understand option %s", argv[on_arg]);
05253             usage(argv[0]);
05254             return 1;
05255         }
05256     }
05257 
05258     LOG(LOG_INFO,"Client Version",VERSION_INFO);
05259 
05260     /* Now copy over the values just loaded */
05261     for (on_arg=0; on_arg<CONFIG_NUMS; on_arg++) {
05262         use_config[on_arg] = want_config[on_arg];
05263     }
05264 
05265     image_size = DEFAULT_IMAGE_SIZE * use_config[CONFIG_ICONSCALE] / 100;
05266     map_image_size = DEFAULT_IMAGE_SIZE * use_config[CONFIG_MAPSCALE] / 100;
05267     map_image_half_size = DEFAULT_IMAGE_SIZE * use_config[CONFIG_MAPSCALE] / 200;
05268     itemlist_set_show_icon(&inv_list, use_config[CONFIG_SHOWICON]);
05269     if (!use_config[CONFIG_CACHE]) use_config[CONFIG_DOWNLOAD] = FALSE;
05270 
05271     mapdata_init();
05272 
05273     /* Finished parsing all the command line options.  Now start
05274      * working on the display.
05275      */
05276     gargc=argc;
05277     gargv=argv;
05278 
05279     for (on_arg = 0; on_arg<MAX_HISTORY; on_arg++)
05280         history[on_arg][0]=0;
05281 
05282 
05283     if (get_root_display(display_name,gargc,gargv))
05284                 return 1;
05285 
05286     init_keys();
05287     init_cache_data();
05288     if (want_config[CONFIG_SPLASH]) destroy_splash();
05289     gtk_timeout_add (10,(GtkFunction)gtk_checkchilds,NULL);
05290     return 0;
05291 }
05292 
05293 
05300 void display_map_doneupdate(int redraw, int notice)
05301 {
05302     if (notice)
05303         return;
05304 
05305     if (updatelock < 30) {
05306         updatelock++;
05307 
05308 #ifdef HAVE_SDL
05309         if (use_config[CONFIG_DISPLAYMODE]==CFG_DM_SDL) sdl_gen_map(redraw);
05310         else
05311 #endif
05312         gtk_draw_map(redraw);
05313     } /* if updatelock */
05314     else {
05315         redraw_needed = TRUE;
05316     }
05317 }
05318 
05319 void display_map_newmap(void)
05320 {
05321     reset_map();
05322 }
05323 
05324 void resize_map_window(int x, int y)
05325 {
05326     gtk_drawing_area_size(GTK_DRAWING_AREA(drawingarea), map_image_size * x, map_image_size * y);
05327     if (!want_config[CONFIG_SPLITWIN]) {
05328 #if 0
05329         /* 15 it is a purely arbitary value.  But basically, if the map window is
05330          * narrow, we then will have the stats on top, with message down below
05331          * the map window.  IF the map window is wide, we put these side
05332          * by side at the top
05333          */
05334         if (bigmap && x<15) {
05335 
05336             /* reverse of below basically. */
05337             GtkWidget   *newpane;   /* will take place of game_bar_vpane */
05338 
05339             bigmap =FALSE;
05340 
05341             newpane = gtk_vpaned_new(); /*game in pane1, bars in pane2 */
05342 
05343             /* Remove referance to the split - the stats frame takes its place */
05344             gtk_widget_ref(game_bar_vpane);
05345             gtk_container_remove(GTK_CONTAINER(stat_game_vpane), game_bar_vpane);
05346 
05347             /* Stat now gets the entire top pane to itself */
05348             gtk_widget_ref(stat_frame);
05349             gtk_container_remove(GTK_CONTAINER(game_bar_vpane), stat_frame);
05350             gtk_paned_add1(GTK_PANED(stat_game_vpane), stat_frame);
05351             gtk_widget_unref(stat_frame);
05352 
05353             /* statbars now second part of bottom frame */
05354             gtk_widget_ref(message_frame);
05355             gtk_container_remove(GTK_CONTAINER(game_bar_vpane), message_frame);
05356             gtk_paned_add2(GTK_PANED(newpane), message_frame);
05357             gtk_widget_unref(message_frame);
05358 
05359             /* game now first part of bottom frame */
05360             gtk_widget_ref(gameframe);
05361             gtk_container_remove(GTK_CONTAINER(stat_game_vpane), gameframe);
05362             gtk_paned_add1(GTK_PANED(newpane), gameframe);
05363             gtk_widget_unref(gameframe);
05364 
05365             gtk_paned_add2(GTK_PANED(stat_game_vpane), newpane);
05366 
05367             gtk_widget_show(newpane);
05368             /* This should also destroy it */
05369             gtk_widget_unref(game_bar_vpane);
05370             game_bar_vpane = newpane;
05371 
05372         } else if (!bigmap && x>=15) {
05373 
05374             GtkWidget   *newpane;   /* will take place of game_bar_vpane */
05375             bigmap=TRUE;
05376             newpane = gtk_hpaned_new();
05377 
05378             /* We need to remove this here - the game pane is goind to
05379              * take game_bar_vpane as second position in the stat_game_vpane.
05380              * add a refcount so it isn't destroyed.
05381              */
05382             gtk_widget_ref(game_bar_vpane);
05383             gtk_container_remove(GTK_CONTAINER(stat_game_vpane), game_bar_vpane);
05384 
05385 
05386             /* Stat and message are now split on 'newpane' */
05387             gtk_widget_ref(stat_frame);
05388             gtk_container_remove(GTK_CONTAINER(stat_game_vpane), stat_frame);
05389             gtk_paned_add1(GTK_PANED(newpane), stat_frame);
05390             gtk_widget_unref(stat_frame);
05391 
05392             gtk_widget_ref(message_frame);
05393             gtk_container_remove(GTK_CONTAINER(game_bar_vpane), message_frame);
05394             gtk_paned_add2(GTK_PANED(newpane), message_frame);
05395             gtk_widget_unref(message_frame);
05396 
05397             /* the game is now part 2 of stat_game_vpane, and not part of
05398              * game_bar_vpane
05399              */
05400 
05401             gtk_widget_ref(gameframe);
05402             gtk_container_remove(GTK_CONTAINER(game_bar_vpane), gameframe);
05403             gtk_paned_add2(GTK_PANED(stat_game_vpane), gameframe);
05404             gtk_widget_unref(gameframe);
05405 
05406             /* Newpane (split stat/message) is now part one of stat_game_vpane */
05407             gtk_paned_add1(GTK_PANED(stat_game_vpane), newpane);
05408 
05409             gtk_widget_show(newpane);
05410             /* This should also destroy it */
05411             gtk_widget_unref(game_bar_vpane);
05412             game_bar_vpane = newpane;
05413         }
05414 #endif
05415         gtk_widget_set_usize (gameframe, (map_image_size*use_config[CONFIG_MAPWIDTH])+6, (map_image_size*use_config[CONFIG_MAPHEIGHT])+6);
05416     } else {
05417       gtk_widget_set_usize (gtkwin_root,(map_image_size*use_config[CONFIG_MAPWIDTH])+6,(map_image_size*use_config[CONFIG_MAPHEIGHT])+6);
05418     }
05419 
05420 #ifdef HAVE_SDL
05421     if (use_config[CONFIG_DISPLAYMODE]==CFG_DM_SDL)
05422         init_SDL( drawingarea, FALSE);
05423 #endif
05424 
05425 }
05426 
05427 
05428 void display_map_startupdate(void)
05429 {
05430 }
05431 
05432 char *get_metaserver(void)
05433 {
05434     cpl.input_state = Metaserver_Select;
05435 
05436 
05437     while(cpl.input_state==Metaserver_Select) {
05438         /*
05439          * This gtk_main will be quit inside of event_callback
05440          * when the user enters data into the input_text box
05441          * at which point the input_state will change.
05442          */
05443         gtk_main();
05444         usleep(10*1000);    /* 10 milliseconds */
05445     }
05446     return cpl.input_text;
05447 }
05448 /*default log window to 200 lines of about 50 characters*/
05449 #define MAX_LOG_CHARACTERS 10000
05450 void gtkLogListener (LogEntry *le){
05451     if (bugtrack){
05452         gtk_text_freeze (GTK_TEXT (bugtrack));
05453         gtk_text_insert (GTK_TEXT (bugtrack), NULL, &bugtrack->style->black,NULL, getLogText(le), -1);
05454         printf ("current gtk len: %d\n",gtk_text_get_length(GTK_TEXT (bugtrack)));
05455         if (gtk_text_get_length(GTK_TEXT (bugtrack)) > MAX_LOG_CHARACTERS){
05456             /*gtk_text_set_editable (GTK_TEXT (gtkwin_info_text), TRUE);*/
05457             guint toomuch =gtk_text_get_length(GTK_TEXT (bugtrack))-MAX_LOG_CHARACTERS;
05458             printf("Deleteing..%d\n",toomuch);
05459             gtk_text_set_point(GTK_TEXT (bugtrack),toomuch);
05460             gtk_text_backward_delete(GTK_TEXT (bugtrack),toomuch);
05461             gtk_text_set_point(GTK_TEXT (bugtrack),gtk_text_get_length(GTK_TEXT (bugtrack)));
05462            /* gtk_text_set_editable (GTK_TEXT (gtkwin_info_text), FALSE);*/
05463         }
05464         gtk_text_thaw (GTK_TEXT (bugtrack));
05465     }
05466 }
05467 #define MAX_RECURSE 50
05468 /* a handler for the glib error logging. Used so we care ourself of the gtk/gdk warnings
05469  * and make them appear in message window using the logging facility
05470  */
05471 void gLogHandler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer user_data){
05472     static char LogOrigin[4096];
05473     static int recurse = 0;
05474     LogLevel level;
05475     gboolean in_recursion;
05476     gboolean is_fatal;
05477     /*printf ("hi i received a g error on %s with severity %d and message %s\n",log_domain,log_level,message);*/
05478     if (recurse > MAX_RECURSE)
05479         return; /*don't Log*/
05480     if (recurse == MAX_RECURSE){
05481         recurse++;
05482         LOG(LOG_ERROR,"gtk::gLogHandler","Too many recurse, reached limit: %d",recurse);
05483         recurse--;
05484         return;
05485     }
05486     LogOrigin[0]='\0';
05487     strcat (LogOrigin,"Library::");
05488     in_recursion = (log_level & G_LOG_FLAG_RECURSION) != 0;
05489     is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
05490     log_level &= G_LOG_LEVEL_MASK;
05491 
05492     if (!message)
05493         message = "gLogHandler: (NULL) message";
05494     if (log_domain){
05495         strcat(LogOrigin,log_domain);
05496         strcat(LogOrigin,"-");
05497     }else
05498         strcat(LogOrigin, "** ");
05499 
05500 
05501     switch (log_level)
05502     {
05503     case G_LOG_LEVEL_ERROR:/*Our critical*/
05504         strcat (LogOrigin,"ERROR");
05505         level=LOG_CRITICAL;
05506         break;
05507     case G_LOG_LEVEL_CRITICAL:/*our error*/
05508         strcat (LogOrigin,"CRITICAL");
05509         level=LOG_ERROR;
05510         break;
05511     case G_LOG_LEVEL_WARNING:/*our warning*/
05512         strcat (LogOrigin,"WARNING");
05513         level=LOG_WARNING;
05514         break;
05515     case G_LOG_LEVEL_MESSAGE:/* message */
05516         strcat (LogOrigin,"Message");
05517         level=LOG_INFO;
05518         break;
05519     case G_LOG_LEVEL_INFO:/* message */
05520         strcat (LogOrigin,"Info");
05521         level=LOG_INFO;
05522         break;
05523     case G_LOG_LEVEL_DEBUG:/*our debug*/
05524         strcat (LogOrigin,"DEBUG");
05525         level=LOG_DEBUG;
05526         break;
05527     default:
05528         strcat (LogOrigin,"LOG");
05529         level=LOG_WARNING;
05530       break;
05531     }
05532     if (in_recursion)
05533         strcat(LogOrigin," (recursed)");
05534     /*else
05535         strcat(LogOrigin,"**: ");*/
05536     recurse++;
05537     LOG(level,LogOrigin,"%s",message);
05538     if (is_fatal)
05539             LOG(level,LogOrigin,"Last Message was fatal, aborting...");
05540     recurse--;
05541 }
05542 
05543 
05544 extern const char* cached_server_file;
05545 
05546 int main(int argc, char *argv[])
05547 {
05548     int got_one=0;
05549     static char file_cache[ MAX_BUF ];
05550 
05551     g_log_set_handler (NULL,G_LOG_FLAG_RECURSION|G_LOG_FLAG_FATAL|G_LOG_LEVEL_ERROR|
05552             G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING |G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_INFO|
05553             G_LOG_LEVEL_DEBUG,(GLogFunc)gLogHandler,NULL);
05554     g_log_set_handler ("Gtk",G_LOG_FLAG_RECURSION|G_LOG_FLAG_FATAL|G_LOG_LEVEL_ERROR|
05555             G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING |G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_INFO|
05556             G_LOG_LEVEL_DEBUG,(GLogFunc)gLogHandler,NULL);
05557     g_log_set_handler ("Gdk",G_LOG_FLAG_RECURSION|G_LOG_FLAG_FATAL|G_LOG_LEVEL_ERROR|
05558             G_LOG_LEVEL_CRITICAL|G_LOG_LEVEL_WARNING |G_LOG_LEVEL_MESSAGE|G_LOG_LEVEL_INFO|
05559             G_LOG_LEVEL_DEBUG,(GLogFunc)gLogHandler,NULL);
05560 
05561     /* This needs to be done first.  In addition to being quite quick,
05562      * it also sets up some paths (client_libdir) that are needed by
05563      * the other functions.
05564      */
05565     init_client_vars();
05566 
05567     /* Override ../common/init.c default for POPUPS for this client only
05568      * because when compiled with --enable-cfgtk2, a player is not able to
05569      * login to the server if POPUPS are disabled.  See bug # 2022488 at
05570      * http://sourceforge.net/tracker/index.php?func=detail&aid=2022488&group_id=13833&atid=113833
05571      */
05572     want_config[CONFIG_POPUPS] = TRUE;
05573 
05574 
05575     snprintf( file_cache, MAX_BUF, "%s/.crossfire/servers.cache", getenv( "HOME" ) );
05576     cached_server_file = file_cache;
05577     init_text_callbacks();
05578     setLogListener(gtkLogListener);
05579     /* Call this very early.  It should parse all command
05580      * line arguments and set the pertinent ones up in
05581      * globals.  Also call it early so that if it can't set up
05582      * the windowing system, we get an error before trying to
05583      * to connect to the server.  And command line options will
05584      * likely change on the server we connect to.
05585      */
05586     if (init_windows(argc, argv)) {     /* x11.c */
05587         LOG(LOG_CRITICAL,"gtk::main","Failure to init windows.");
05588         exit(1);
05589     }
05590 
05591     csocket.inbuf.buf=malloc(MAXSOCKBUF);
05592 
05593 #ifdef WIN32 /* def WIN32 */
05594         maxfd = 0; /* This is ignored on win32 platforms */
05595 
05596         /* This is required for sockets to be used under win32 */
05597         {
05598                 WORD Version = 0x0202;
05599                 WSADATA wsaData;
05600                 if (WSAStartup( Version, &wsaData ) != 0) {
05601                         LOG(LOG_CRITICAL,"gtk::main", "Couldn't load winsock!");
05602                         exit(1);
05603                 }
05604         }
05605 #else /* def WIN32 */
05606 #ifdef HAVE_SYSCONF
05607     maxfd = sysconf(_SC_OPEN_MAX);
05608 #else
05609     maxfd = getdtablesize();
05610 #endif
05611 #endif /* def WIN32 */
05612 
05613     if (init_sounds() == -1)
05614         use_config[CONFIG_SOUND] = FALSE;
05615     else use_config[CONFIG_SOUND] = TRUE;
05616 
05617     /* Loop to connect to server/metaserver and play the game */
05618     while (1) {
05619         reset_client_vars();
05620         csocket.inbuf.len=0;
05621         csocket.cs_version=0;
05622 
05623         /* Perhaps not the best assumption, but we are taking it that
05624          * if the player has not specified a server (ie, server
05625          * matches compiled in default), we use the metaserver.
05626          * otherwise, use the server provided, bypassing metaserver.
05627          * Also, if the player has already played on a server once (defined
05628          * by got_one), go to the metaserver.  That gives them the opportunity
05629          * to quit the client or select another server.  We should really add
05630          * an entry for the last server there also.
05631          */
05632 
05633         if (!server || got_one) {
05634             char *ms;
05635             metaserver_get_info(meta_server, meta_port);
05636             metaserver_show(TRUE);
05637             do {
05638             draw_info_windows();
05639             ms=get_metaserver();
05640             } while (metaserver_select(ms));
05641             negotiate_connection(use_config[CONFIG_SOUND]);
05642         } else {
05643             csocket.fd=init_connection(server, use_config[CONFIG_PORT]);
05644             if (csocket.fd == -1) { /* specified server no longer valid */
05645                 server = NULL;
05646                 continue;
05647             }
05648             negotiate_connection(use_config[CONFIG_SOUND]);
05649         }
05650 
05651         got_one=1;
05652         event_loop();
05653         /* if event_loop has exited, we most of lost our connection, so we
05654          * loop again to establish a new one.
05655          */
05656 
05657         mapdata_reset();
05658         /* Need to reset the images so they match up properly and prevent
05659          * memory leaks.
05660          */
05661         reset_image_data();
05662         remove_item_inventory(cpl.ob);
05663         remove_item_inventory(cpl.below);
05664         set_look_list_env(cpl.below);
05665     }
05666     exit(0);    /* never reached */
05667 }