Crossfire Client, Branches  R11627
main.c
Go to the documentation of this file.
1 const char * const rcsid_gtk2_main_c = "$Id: main.c 10739 2008-11-26 19:50:37Z kbulgrien $";
2 
3 /*
4  Crossfire client, a client program for the crossfire program.
5 
6  Copyright (C) 2005-2007 Mark Wedel & Crossfire Development Team
7 
8  This program is free software; you can redistribute it and/or modify
9  it under the terms of the GNU General Public License as published by
10  the Free Software Foundation; either version 2 of the License, or
11  (at your option) any later version.
12 
13  This program is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  GNU General Public License for more details.
17 
18  You should have received a copy of the GNU General Public License
19  along with this program; if not, write to the Free Software
20  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
21 
22  The author can be reached via e-mail to crossfire@metalforge.org
23 */
24 
33 #ifdef HAVE_CONFIG_H
34 # include <config.h>
35 #endif
36 
37 #ifdef WIN32
38 #include <windows.h>
39 #endif
40 #include <gtk/gtk.h>
41 #include <glade/glade.h>
42 #include <stdio.h>
43 #include <errno.h>
44 #ifndef WIN32
45 #include <signal.h>
46 #endif
47 
48 #include "main.h"
49 #include "client.h"
50 #include "image.h"
51 #include "gtk2proto.h"
52 #include "script.h"
53 #include "metaserver.h"
54 #include "mapdata.h"
55 
56 GtkWidget *window_root, *magic_map;
57 GladeXML *dialog_xml, *window_xml;
58 
59 /* Sets up the basic colors. */
60 const char * const colorname[NUM_COLORS] = {
61 "Black", /* 0 */
62 "White", /* 1 */
63 "Navy", /* 2 */
64 "Red", /* 3 */
65 "Orange", /* 4 */
66 "DodgerBlue", /* 5 */
67 "DarkOrange2", /* 6 */
68 "SeaGreen", /* 7 */
69 "DarkSeaGreen", /* 8 *//* Used for window background color */
70 "Grey50", /* 9 */
71 "Sienna", /* 10 */
72 "Gold", /* 11 */
73 "Khaki" /* 12 */
74 };
75 
76 /* These are the names as set by the user within the rc file.
77  * We use lower case to be consistent, but also change the names
78  * to be more generic instead of specific X11 color names.
79  */
80 const char * const usercolorname[NUM_COLORS] = {
81 "black", /* 0 */
82 "white", /* 1 */
83 "darkblue", /* 2 */
84 "red", /* 3 */
85 "orange", /* 4 */
86 "lightblue", /* 5 */
87 "darkorange", /* 6 */
88 "green", /* 7 */
89 "darkgreen", /* 8 *//* Used for window background color */
90 "grey", /* 9 */
91 "brown", /* 10 */
92 "yellow", /* 11 */
93 "tan" /* 12 */
94 };
95 
105 struct timeval timeout;
106 extern int maxfd;
107 gint csocket_fd=0;
109 extern int time_map_redraw;
110 
111 #ifdef WIN32 /* Win32 scripting support */
112 #define PACKAGE_DATA_DIR "."
113 
114 int do_scriptout(void)
115 {
116  script_process(NULL);
117  return(TRUE);
118 }
119 #endif /* WIN32 */
120 
125 int do_timeout(void)
126 {
129  if (!tick) {
130  inventory_tick();
132  }
133  return TRUE;
134 }
135 
140 {
141  inventory_tick();
143  draw_map(0);
144 }
145 
151 {
152  if (csocket_fd) {
153  gdk_input_remove(csocket_fd);
154  csocket_fd=0;
155  gtk_main_quit();
156  }
157 }
158 
162 void on_window_destroy_event (GtkObject *object,
163  gpointer user_data)
164 {
165 #ifdef WIN32
166  script_killall();
167 #endif
168 
169  LOG(LOG_INFO, "main.c::client_exit", "Exiting with return value 0.");
170  exit(0);
171 }
172 
176 void do_network(void)
177 {
178  fd_set tmp_read;
179  int pollret;
180 
181  if (csocket.fd==-1) {
182  if (csocket_fd) {
183  gdk_input_remove(csocket_fd);
184  csocket_fd=0;
185  gtk_main_quit();
186  }
187  return;
188  }
189 
190  FD_ZERO(&tmp_read);
191  FD_SET(csocket.fd, &tmp_read);
192  script_fdset(&maxfd,&tmp_read);
193  pollret = select(maxfd, &tmp_read, NULL, NULL, &timeout);
194  if (pollret==-1) {
195  LOG(LOG_WARNING, "main.c::do_network",
196  "Got errno %d on select call.", errno);
197  } else if ( pollret>0 ) {
198  if (FD_ISSET(csocket.fd, &tmp_read)) {
199  DoClient(&csocket);
200 #ifndef WIN32
201  if ( pollret > 1 ) script_process(&tmp_read);
202 #endif
203  } else {
204  script_process(&tmp_read);
205  }
206  }
207  /* DoClient now closes the socket, so we need to check for this here -
208  * with the socket being closed, this function will otherwise never be
209  * called again. */
210  if (csocket.fd==-1) {
211  if (csocket_fd) {
212  gdk_input_remove(csocket_fd);
213  csocket_fd=0;
214  gtk_main_quit();
215  }
216  return;
217  }
218 #ifdef HAVE_SDL
220  else
221 #endif
222 #ifdef HAVE_OPENGL
224  else
225 #endif
226  draw_map(FALSE);
227 
228  draw_lists();
229 }
230 
234 void event_loop(void)
235 {
236  gint fleep;
237  extern int do_timeout(void);
238  int tag;
239 
240  if (MAX_TIME==0) {
241  timeout.tv_sec = 0;
242  timeout.tv_usec = 0;
243  }
244  maxfd = csocket.fd + 1;
245 
246  if (MAX_TIME!=0) {
247  timeout.tv_sec = 0;/* MAX_TIME / 1000000;*/
248  timeout.tv_usec = 0;/* MAX_TIME % 1000000;*/
249  }
250 
251  fleep = gtk_timeout_add (10, (GtkFunction) do_timeout, NULL);
252 
253 #ifdef WIN32
254  gtk_timeout_add (25, (GtkFunction) do_scriptout, NULL);
255 #endif
256 
257  if (csocket.fd==-1) {
258  if (csocket_fd) {
259  gdk_input_remove(csocket_fd);
260  csocket_fd=0;
261  gtk_main_quit();
262  }
263  return;
264  }
265  csocket_fd = gdk_input_add ((gint) csocket.fd,
266  GDK_INPUT_READ,
267  (GdkInputFunction) do_network, &csocket);
268  tag = csocket_fd;
269 
270  gtk_main();
271  gtk_timeout_remove(tag);
272 
273  LOG(LOG_INFO, "main.c::event_loop",
274  "gtk_main exited, returning from event_loop");
275 }
276 
277 #ifndef WIN32
278 
286 static void sigpipe_handler(int sig) {
287  /* ignore that signal for now */
288 }
289 #endif
290 
298 static void usage(char *progname)
299 {
300  puts("Usage of crossfire-client-gtk2:\n");
301  puts("-cache - Cache images for future use.");
302  puts("-nocache - Do not cache images (default action).");
303  puts("-darkness - Enables darkness code (default)");
304  puts("-nodarkness - Disables darkness code");
305  puts("-display <name> - Use <name> instead if DISPLAY environment variable.");
306  puts("-download_all_faces - Download all needed faces before play starts");
307  puts("-echo - Echo the bound commands");
308  puts("-noecho - Do not echo the bound commands (default)");
309  puts("-faceset <name> - Use faceset <name> if available");
310  puts("-fasttcpsend - Send data immediately to server, may increase bandwidth");
311  puts("-nofasttcpsend - Disables fasttcpsend");
312  puts("-fog - Enable fog of war code");
313  puts("-help - Display this message.");
314  puts("-loglevel <val> - Set default logging level (0 is most verbose)");
315  puts("-iconscale %% - Set icon scale percentage");
316  puts("-mapscale %% - Set map scale percentage");
317  puts("-mapsize xXy - Set the mapsize to be X by Y spaces. (default 11x11)");
318  puts("-splash - Display the splash screen (default)");
319  puts("-nosplash - Don't display the splash screen (startup logo)");
320  puts("-opengl - Use opengl drawing code");
321  puts("-pixmap - Use pixmap drawing code");
322  puts("-port <number> - Use port <number> instead of the standard port number");
323  puts("-sdl - Use sdl for drawing png (may not work on all hardware");
324  puts("-server <name> - Connect to <name> instead of localhost.");
325  puts("-showicon - Print status icons in inventory window");
326  puts("-smooth - Enable smooth");
327  puts("-nosmooth - Disable smooth (default)");
328  puts("-sound - Enable sound output (default).");
329  puts("-nosound - Disable sound output.");
330  puts("-sound_server <path> - Executable to use to play sounds.");
331  puts("-resists <val> - Control look of resistances.");
332  puts("-split - Use split windows.");
333  puts("-splitinfo - Use two information windows, segregated by information type.");
334  puts("-timemapredraw - Print out timing information for map generation");
335  puts("-triminfowindow - Trims size of information window(s)");
336  puts("-notriminfowindow - Do not trims size of information window(s) (default)");
337  puts("-updatekeycodes - Update the saved bindings for this keyboard.");
338  puts("-window_xml <file> - Glade Designer client UI layout XML file.");
339  puts("-dialog_xml <file> - Glade Designer popup dialog XML file.");
340 
341  exit(0);
342 }
343 
350 int parse_args(int argc, char **argv)
351 {
352  int on_arg=1;
353  char *display_name="";
354 
355  load_defaults();
356 
357 #ifndef WIN32
358  strcpy(VERSION_INFO,"GTK V2 Unix Client " FULL_VERSION);
359 #else
360  strcpy(VERSION_INFO,"GTK V2 Win32 Client " FULL_VERSION);
361 #endif
362  /*
363  * Set this global so we get skill experience - gtk client can display
364  * it, so lets get the info.
365  */
366  want_skill_exp=1;
367  for (on_arg=1; on_arg<argc; on_arg++) {
368  if (!strcmp(argv[on_arg], "-cache")) {
370  continue;
371  } else if (!strcmp(argv[on_arg], "-nocache")) {
373  continue;
374  } else if (!strcmp(argv[on_arg], "-darkness")) {
376  continue;
377  } else if (!strcmp(argv[on_arg], "-nodarkness")) {
379  continue;
380  } else if (!strcmp(argv[on_arg], "-display")) {
381  if (++on_arg == argc) {
382  LOG(LOG_WARNING, "main.c::init_windows",
383  "-display requires a display name");
384  return 1;
385  }
386  display_name = argv[on_arg];
387  continue;
388  } else if (!strcmp(argv[on_arg], "-download_all_faces")) {
390  continue;
391  } else if (!strcmp(argv[on_arg], "-echo")) {
393  continue;
394  } else if (!strcmp(argv[on_arg], "-noecho")) {
396  continue;
397  } else if (!strcmp(argv[on_arg], "-faceset")) {
398  if (++on_arg == argc) {
399  LOG(LOG_WARNING, "main.c::init_windows",
400  "-faceset requires a faceset name/number");
401  return 1;
402  }
403  face_info.want_faceset = argv[on_arg];
404  continue;
405  } else if (!strcmp(argv[on_arg], "-fog")) {
407  continue;
408  } else if (!strcmp(argv[on_arg], "-nofog")) {
410  continue;
411  } else if (!strcmp(argv[on_arg], "-help")) {
412  usage(argv[0]);
413  continue;
414  } else if (!strcmp(argv[on_arg], "-iconscale")) {
415  if (++on_arg == argc) {
416  LOG(LOG_WARNING, "main.c::init_windows",
417  "-iconscale requires a percentage value");
418  return 1;
419  }
420  want_config[CONFIG_ICONSCALE] = atoi(argv[on_arg]);
422  LOG(LOG_WARNING, "main.c::init_windows",
423  "Valid range for -iconscale is 25 through 200");
425  return 1;
426  }
427  continue;
428  } else if (!strcmp(argv[on_arg], "-mapscale")) {
429  if (++on_arg == argc) {
430  LOG(LOG_WARNING, "main.c::init_windows",
431  "-mapscale requires a percentage value");
432  return 1;
433  }
434  want_config[CONFIG_MAPSCALE] = atoi(argv[on_arg]);
436  LOG(LOG_WARNING, "main.c::init_windows",
437  "Valid range for -mapscale is 25 through 200");
439  return 1;
440  }
441  continue;
442  } else if (!strcmp(argv[on_arg], "-mapsize")) {
443  char *cp, x, y=0;
444 
445  if (++on_arg == argc) {
446  LOG(LOG_WARNING, "main.c::init_windows",
447  "-mapsize requires a XxY value");
448  return 1;
449  }
450  x = atoi(argv[on_arg]);
451  for (cp = argv[on_arg]; *cp!='\0'; cp++)
452  if (*cp == 'x' || *cp == 'X') break;
453 
454  if (*cp == 0) {
455  LOG(LOG_WARNING, "main.c::init_windows", "-mapsize requires "
456  "both X and Y values (ie, XxY - note the\nx in between.");
457  } else {
458  y = atoi(cp+1);
459  }
460  if (x<9 || y<9) {
461  LOG(LOG_WARNING, "main.c::init_windows",
462  "Map size must be positive values of at least 9");
463  } else if (x>MAP_MAX_SIZE || y>MAP_MAX_SIZE) {
464  LOG(LOG_WARNING, "main.c::init_windows", "Map size cannot be "
465  "larger than %d x %d", MAP_MAX_SIZE, MAP_MAX_SIZE);
466 
467  } else {
470  }
471  continue;
472  } else if (!strcmp(argv[on_arg], "-fasttcpsend")) {
474  continue;
475  } else if (!strcmp(argv[on_arg], "-nofasttcpsend")) {
477  continue;
478  } else if (!strcmp(argv[on_arg], "-opengl")) {
479 #ifndef HAVE_OPENGL
480  LOG(LOG_WARNING, "main.c::init_windows", "client not compiled "
481  "with opengl support. Ignoring -opengl");
482 #else
484 #endif
485  continue;
486  } else if (!strcmp(argv[on_arg], "-pixmap")) {
488  } else if (!strcmp(argv[on_arg], "-port")) {
489  if (++on_arg == argc) {
490  LOG(LOG_WARNING, "main.c::init_windows",
491  "-port requires a port number");
492  return 1;
493  }
494  want_config[CONFIG_PORT] = atoi(argv[on_arg]);
495  continue;
496  } else if (!strcmp(argv[on_arg], "-sdl")) {
497 #ifndef HAVE_SDL
498  LOG(LOG_WARNING, "main.c::init_windows",
499  "client not compiled with sdl support. Ignoring -sdl");
500 #else
502 #endif
503  continue;
504  } else if (!strcmp(argv[on_arg], "-server")) {
505  if (++on_arg == argc) {
506  LOG(LOG_WARNING, "main.c::init_windows",
507  "-server requires a host name");
508  return 1;
509  }
510  server = argv[on_arg];
511  continue;
512  } else if (!strcmp(argv[on_arg], "-showicon")) {
514  continue;
515  } else if (!strcmp(argv[on_arg], "-smooth")) {
517  } else if (!strcmp(argv[on_arg], "-nosmooth")) {
519  } else if (!strcmp(argv[on_arg], "-sound")) {
521  continue;
522  } else if (!strcmp(argv[on_arg], "-nosound")) {
524  continue;
525  } else if (!strcmp(argv[on_arg], "-sound_server")) {
526  if (++on_arg == argc) {
527  LOG(LOG_WARNING, "main.c::init_windows",
528  "-sound_server requires an executable pathname");
529  return 1;
530  }
531  sound_server = argv[on_arg];
532  continue;
533  } else if (!strcmp(argv[on_arg], "-split")) {
535  continue;
536  } else if (!strcmp(argv[on_arg], "-nosplit")) {
538  continue;
539  } else if (!strcmp(argv[on_arg], "-resists")) {
540  if (++on_arg == argc) {
541  LOG(LOG_WARNING, "main.c::init_windows",
542  "-resists requires a value");
543  return 1;
544  }
545  want_config[CONFIG_RESISTS]=atoi(argv[on_arg]);
546  continue;
547  } else if (!strcmp(argv[on_arg], "-loglevel")) {
548  extern int MINLOG;
549 
550  if (++on_arg == argc) {
551  LOG(LOG_WARNING, "main.c::init_windows",
552  "-loglevel requires a value");
553  return 1;
554  }
555  MINLOG = atoi(argv[on_arg]);
556  continue;
557  } else if (!strcmp(argv[on_arg], "-splitinfo")) {
559  continue;
560  } else if (!strcmp(argv[on_arg], "-timemapredraw")) {
562  continue;
563  } else if (!strcmp(argv[on_arg], "-triminfowindow")) {
565  continue;
566  } else if (!strcmp(argv[on_arg], "-notriminfowindow")) {
568  continue;
569  } else if (!strcmp(argv[on_arg], "-updatekeycodes")) {
571  continue;
572  } else if (!strcmp(argv[on_arg], "-splash")) {
574  continue;
575  } else if (!strcmp(argv[on_arg], "-nosplash")) {
577  continue;
578  } else if (!strcmp(argv[on_arg], "-window_xml")) {
579  if (++on_arg == argc) {
580  LOG(LOG_WARNING, "main.c::init_windows",
581  "-window_xml requires a glade xml file name");
582  return 1;
583  }
584  strncpy (window_xml_path, argv[on_arg], MAX_BUF-1);
585  continue;
586  } else if (!strcmp(argv[on_arg], "-dialog_xml")) {
587  if (++on_arg == argc) {
588  LOG(LOG_WARNING, "main.c::init_windows",
589  "-dialog_xml requires a glade xml file name");
590  return 1;
591  }
592  strncpy (dialog_xml_path, argv[on_arg], MAX_BUF-1);
593  continue;
594  } else {
595  LOG(LOG_WARNING, "main.c::init_windows",
596  "Do not understand option %s", argv[on_arg]);
597  usage(argv[0]);
598  return 1;
599  }
600  }
601 
602  /*
603  * Move this after the parsing of command line options, since that can
604  * change the default log level.
605  */
606  LOG(LOG_INFO, "Client Version", VERSION_INFO);
607 
608  /* Now copy over the values just loaded */
609  for (on_arg=0; on_arg<CONFIG_NUMS; on_arg++) {
610  use_config[on_arg] = want_config[on_arg];
611  }
612 
617 
618  mapdata_init();
619 
620  return 0;
621 }
622 
636 static void error_dialog(char *description, char *information)
637 {
638  GtkWidget *dialog;
639 
640  gtk_init(NULL, NULL);
641  dialog =
642  gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
643  GTK_MESSAGE_ERROR, GTK_BUTTONS_CLOSE, "Crossfire %s\n%s",
644  VERSION_INFO, description);
645  gtk_message_dialog_format_secondary_markup(GTK_MESSAGE_DIALOG(dialog),
646  "%s", information);
647  gtk_dialog_run(GTK_DIALOG(dialog));
648  gtk_widget_destroy(dialog);
649 }
650 
657 int
658 main (int argc, char *argv[])
659 {
660  int i, got_one=0;
661  static char file_cache[ MAX_BUF ];
662  GdkGeometry geometry;
663  GladeXML *xml_tree;
664 
665 #ifdef ENABLE_NLS
666  bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR);
667  bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
668  textdomain (GETTEXT_PACKAGE);
669 #endif
670 
671  gtk_set_locale ();
672  gtk_init (&argc, &argv);
673 
674  /* parse_args() has to come after init_client_vars() */
678 
679 
680  parse_args(argc, argv);
681  load_theme(FALSE);
682 
683  csocket.inbuf.buf=malloc(MAXSOCKBUF);
684 
685 #ifdef WIN32 /* def WIN32 */
686  maxfd = 0; /* This is ignored on win32 platforms */
687 
688  /* This is required for sockets to be used under win32 */
689  {
690  WORD Version = 0x0202;
691  WSADATA wsaData;
692 
693  if (WSAStartup( Version, &wsaData ) != 0) {
694  LOG(LOG_CRITICAL, "main.c::main", "Could not load winsock!");
695  exit(1);
696  }
697  }
698 #else /* def WIN32 */
699  signal(SIGPIPE, sigpipe_handler);
700 #ifdef HAVE_SYSCONF
701  maxfd = sysconf(_SC_OPEN_MAX);
702 #else
703  maxfd = getdtablesize();
704 #endif
705 #endif /* def WIN32 */
706 
707  if (init_sounds() == -1)
709  else use_config[CONFIG_SOUND] = TRUE;
710 
711  /*
712  * Load Glade XML layout files for the main client window and for the other
713  * popup dialogs. The popup dialogs must all have the "visible" attribute
714  * set to "no" so they are not shown initially.
715  *
716  * NOTE: glade_init() is implicitly called on glade_xml_new().
717  *
718  * First, load up the common dialogs. If the XML file path is already set,
719  * it is because a command-line parameter was used to specify it. If not
720  * set, construct the path to the file from the default path and name
721  * settings.
722  */
723  if (! dialog_xml_path[0]) {
726  MAX_BUF-strlen(dialog_xml_path)-1);
727  }
728  dialog_xml = glade_xml_new(dialog_xml_path, NULL, NULL);
729  if (! dialog_xml) {
730  sprintf(dialog_xml_file, "Dialog layout file load failed");
732  exit(-1);
733  }
734 
735  /*
736  * Next, load up the root window. If the XML file path is already set, it
737  * is because a command-line parameter was used to specify it. If not set,
738  * construct the path to the file from the default settings, and any values
739  * loaded from the gdefaults2 file.
740  */
741  if (! window_xml_path[0]) {
744  MAX_BUF-strlen(window_xml_path)-1);
745  }
746  window_xml = glade_xml_new(window_xml_path, NULL, NULL);
747  if (! window_xml) {
748  sprintf(window_xml_file, "Main window layout file load failed");
750  exit(-1);
751  }
752 
753  /* Begin connecting signals for the root window loaded by libglade. */
754  window_root = glade_xml_get_widget(window_xml, "window_root");
755 
756  g_signal_connect_swapped ((gpointer) window_root, "key_press_event",
757  G_CALLBACK (keyfunc), GTK_OBJECT (window_root));
758  g_signal_connect_swapped ((gpointer) window_root, "key_release_event",
759  G_CALLBACK (keyrelfunc), GTK_OBJECT (window_root));
760  g_signal_connect ((gpointer) window_root, "destroy",
761  G_CALLBACK (on_window_destroy_event), NULL);
762 
763  /* Purely arbitrary min window size */
764  geometry.min_width=640;
765  geometry.min_height=480;
766 
767  gtk_window_set_geometry_hints(GTK_WINDOW(window_root), window_root,
768  &geometry, GDK_HINT_MIN_SIZE);
769 
770  /* Set up colors before doing the other initialization functions */
771  for (i=0; i<NUM_COLORS; i++) {
772  if ( !gdk_color_parse(colorname[i], &root_color[i])) {
773  fprintf(stderr, "gdk_color_parse failed (%s)\n",colorname[i]);
774  }
775  if ( !gdk_color_alloc (gtk_widget_get_colormap (window_root),
776  &root_color[i])) {
777  fprintf(stderr, "gdk_color_alloc failed\n");
778  }
779  }
780 
781  inventory_init(window_root);
782  info_init(window_root);
783  keys_init(window_root);
784  stats_init(window_root);
785  config_init(window_root);
786  pickup_init(window_root);
787 
788  load_window_positions(window_root);
789 
790  /* We want this as late as possible in the process. This way, adjustments
791  * that the widgets make on initialization are not visible - this is most
792  * important with the inventory widget which has to create the panes and
793  * fill in the data - if the window_root is shown before that, there is a
794  * brief glimpse of the glade layout, which, IMO, doesn't look great.
795  * Also, it should be faster to realize this as later as possible. */
796  gtk_widget_show (window_root);
797 
798  map_init(window_root);
799 
800  xml_tree = glade_get_widget_tree(GTK_WIDGET(window_root));
801  magic_map = glade_xml_get_widget(xml_tree, "drawingarea_magic_map");
802 
803  g_signal_connect ((gpointer) magic_map, "expose_event",
804  G_CALLBACK (on_drawingarea_magic_map_expose_event), NULL);
805 
806  snprintf( file_cache, MAX_BUF, "%s/.crossfire/servers.cache", getenv( "HOME" ) );
807  cached_server_file = file_cache;
808 
809  init_cache_data();
810 
811  /* Loop to connect to server/metaserver and play the game */
812  while (1) {
815  csocket.inbuf.len=0;
817 
818  /*
819  * Perhaps not the best assumption, but we are taking it that if the
820  * player has not specified a server (ie, server matches compiled in
821  * default), we use the metaserver. Otherwise, use the server
822  * provided, bypassing metaserver. Also, if the player has already
823  * played on a server once (defined by got_one), go to the metaserver.
824  * That gives them the opportunity to quit the client or select another
825  * server. We should really add an entry for the last server there
826  * also.
827  */
828  if (!server || got_one) {
829  draw_splash();
831  get_metaserver();
832  /* Call this after get_metaserver so one can't do anything
833  * with the menus at that point.
834  */
837  } else {
840  if (csocket.fd == -1) { /* specified server no longer valid */
841  server = NULL;
842  continue;
843  }
845  }
846 
847  got_one=1;
848 
849  event_loop();
850  /*
851  * if event_loop has exited, we most likely of lost our connection, so
852  * we loop again to establish a new one.
853  */
854 
856  /*
857  * We know the following is the private map structure in item.c. But
858  * we don't have direct access to it, so we still use locate.
859  */
861  draw_look_list();
862 
863  mapdata_reset();
864  /*
865  * Need to reset the images so they match up properly and prevent
866  * memory leaks.
867  */
869  }
870  exit(0); /* never reached */
871 
872  return 0;
873 }
874 
886 void get_window_coord(GtkWidget *win,
887  int *x,int *y,
888  int *wx,int *wy,
889  int *w,int *h)
890 {
891  /* Position of a window relative to its parent window. */
892  gdk_window_get_geometry (win->window, x, y, w, h, NULL);
893  /* Position of the window in root window coordinates. */
894  gdk_window_get_origin (win->window, wx, wy);
895  *wx -= *x;
896  *wy -= *y;
897 }
char dialog_xml_file[MAX_BUF]
Definition: main.c:96
void negotiate_connection(int sound)
Definition: client.c:338
void update_spell_information(void)
Definition: spells.c:119
uint32 spells_updated
Definition: client.h:289
int main(int argc, char *argv[])
Definition: main.c:658
static void usage(char *progname)
Definition: main.c:298
void load_window_positions(GtkWidget *window_root)
Definition: config.c:1064
#define XML_PATH_DEFAULT
Definition: main.h:40
char dialog_xml_path[MAX_BUF]
Definition: main.c:97
#define DEFAULT_IMAGE_SIZE
Definition: gx11.c:114
void mapdata_animation(void)
Definition: mapdata.c:1264
void init_client_vars(void)
Definition: init.c:97
void inventory_init(GtkWidget *window_root)
Definition: inventory.c:421
static void init_cache_data(void)
Definition: gx11.c:504
#define CONFIG_ECHO
Definition: client.h:153
GladeXML * window_xml
Definition: main.c:57
char window_xml_file[MAX_BUF]
Definition: main.c:98
item * ob
Definition: client.h:272
void magic_map_flash_pos(void)
Definition: gx11.c:4766
void keyfunc(GtkWidget *widget, GdkEventKey *event, GtkWidget *window)
Definition: keys.c:1008
void stats_init(GtkWidget *window_root)
Definition: stats.c:176
void enable_menu_items(int enable)
Definition: menubar.c:121
void config_init(GtkWidget *window_root)
Definition: config.c:407
#define MAP_MAX_SIZE
Definition: client.h:447
ClientSocket csocket
Definition: client.c:78
void mapdata_reset(void)
Definition: mapdata.c:572
GdkColor root_color[NUM_COLORS]
Definition: main.c:104
void clear_stat_mapping(void)
Definition: stats.c:725
Face_Information face_info
Definition: image.c:167
int map_image_half_size
Definition: gx11.c:117
#define CONFIG_SPLASH
Definition: client.h:178
const char *const colorname[NUM_COLORS]
Definition: main.c:60
#define CONFIG_FOGWAR
Definition: client.h:157
sint16 want_config[CONFIG_NUMS]
Definition: init.c:50
#define CONFIG_MAPSCALE
Definition: client.h:159
void pickup_init(GtkWidget *window_root)
Definition: pickup.c:405
void inventory_tick(void)
Definition: inventory.c:1374
int meta_port
Definition: client.c:67
#define WINDOW_XML_FILENAME
Definition: main.h:41
#define CONFIG_SPLITINFO
Definition: client.h:165
char * server
Definition: client.c:56
gint csocket_fd
Definition: main.c:107
const char *const rcsid_gtk2_main_c
Definition: main.c:1
int init_sounds(void)
Definition: sound.c:60
void client_tick(uint32 tick)
Definition: main.c:139
GladeXML * dialog_xml
Definition: main.c:57
int init_connection(char *host, int port)
Definition: client.c:205
#define CFG_DM_SDL
Definition: client.h:195
void LOG(LogLevel level, const char *origin, const char *format,...)
Definition: misc.c:178
void reset_client_vars(void)
Definition: init.c:249
#define TRUE
Definition: client-types.h:71
void reset_image_data(void)
Definition: image.c:387
uint32 tick
Definition: client.c:70
static void sigpipe_handler(int sig)
Definition: main.c:286
char * get_metaserver(void)
Definition: gx11.c:5432
int map_image_size
Definition: gx11.c:117
struct timeval timeout
Definition: main.c:105
#define CONFIG_NUMS
Definition: client.h:183
#define CONFIG_PORT
Definition: client.h:174
sint16 use_config[CONFIG_NUMS]
Definition: init.c:50
void on_window_destroy_event(GtkObject *object, gpointer user_data)
Definition: main.c:162
void draw_lists(void)
Definition: inventory.c:1029
Client_Player cpl
Definition: client.c:77
#define CONFIG_CACHE
Definition: client.h:156
void mapdata_init(void)
Definition: mapdata.c:514
#define CONFIG_FASTTCP
Definition: client.h:154
int fd
Definition: client.h:97
void info_init(GtkWidget *window_root)
Definition: info.c:413
#define DIALOG_XML_FILENAME
Definition: main.h:42
gboolean on_drawingarea_magic_map_expose_event(GtkWidget *widget, GdkEventExpose *event, gpointer user_data)
Definition: magicmap.c:154
void keys_init(GtkWidget *window_root)
Definition: keys.c:399
static GtkWidget * description
Definition: gx11.c:2981
int time_map_redraw
Definition: gx11.c:203
#define NUM_COLORS
Definition: main.h:32
GtkWidget * window_root
Definition: main.c:56
char window_xml_path[MAX_BUF]
Definition: main.c:103
int do_timeout(void)
Definition: main.c:125
#define CONFIG_SMOOTH
Definition: client.h:177
void get_window_coord(GtkWidget *win, int *x, int *y, int *wx, int *wy, int *w, int *h)
Definition: main.c:886
#define MAX_BUF
Definition: client-types.h:128
#define CFG_DM_PIXMAP
Definition: client.h:194
void map_init(GtkWidget *window_root)
Definition: map.c:103
void do_network(void)
Definition: main.c:176
#define MAX_TIME
Definition: cconfig.h:39
int maxfd
Definition: client.c:68
unsigned int uint32
Definition: client-types.h:77
#define CONFIG_MAPWIDTH
Definition: client.h:170
item * locate_item(sint32 tag)
Definition: item.c:292
#define CONFIG_SHOWICON
Definition: client.h:162
unsigned char * buf
Definition: newclient.h:573
int len
Definition: newclient.h:572
#define CONFIG_TRIMINFO
Definition: client.h:169
void draw_look_list(void)
Definition: inventory.c:718
char * sound_server
Definition: client.c:62
#define CONFIG_ICONSCALE
Definition: client.h:158
uint8 showmagic
Definition: client.h:300
static uint8 updatekeycodes
Definition: main.c:108
static void error_dialog(char *description, char *information)
Definition: main.c:636
#define MAXSOCKBUF
Definition: newclient.h:79
void script_fdset(int *maxfd, fd_set *set)
Definition: script.c:559
void remove_item_inventory(item *op)
Definition: item.c:382
#define CONFIG_MAPHEIGHT
Definition: client.h:171
void event_loop(void)
Definition: main.c:234
void cleanup_connection(void)
Definition: main.c:150
#define CONFIG_DOWNLOAD
Definition: client.h:152
#define CONFIG_RESISTS
Definition: client.h:176
void load_theme(int reload)
Definition: config.c:116
int want_skill_exp
Definition: client.c:67
void opengl_gen_map(int redraw)
SockList inbuf
Definition: client.h:98
void draw_splash(void)
Definition: map.c:620
int parse_args(int argc, char **argv)
Definition: main.c:350
void DoClient(ClientSocket *csocket)
Definition: client.c:149
void load_defaults(void)
Definition: config.c:710
int metaserver_get_info(char *metaserver, int meta_port)
Definition: metaserver.c:791
#define CFG_DM_OPENGL
Definition: client.h:196
char VERSION_INFO[256]
Definition: client.c:59
#define CONFIG_DISPLAYMODE
Definition: client.h:161
unsigned char uint8
Definition: client-types.h:81
#define FULL_VERSION
Definition: version.h:6
const char *const usercolorname[NUM_COLORS]
Definition: main.c:80
char * meta_server
Definition: client.c:61
int MINLOG
Definition: misc.c:174
#define FALSE
Definition: client-types.h:68
int image_size
Definition: gx11.c:116
#define CONFIG_SPLITWIN
Definition: client.h:166
void script_process(fd_set *set)
Definition: script.c:572
#define CONFIG_DARKNESS
Definition: client.h:173
void sdl_gen_map(int redraw)
void draw_map(int redraw)
Definition: map.c:654
const char * cached_server_file
Definition: metaserver.c:107
void keyrelfunc(GtkWidget *widget, GdkEventKey *event, GtkWidget *window)
Definition: keys.c:994
#define CONFIG_SOUND
Definition: client.h:164
GtkWidget * magic_map
Definition: main.c:56
int cs_version
Definition: client.h:99