Complete.Org: Mailing Lists: Archives: freeciv-dev: September 2001:
[Freeciv-Dev] [Patch] Extended connect dialog (PR#977)
Home

[Freeciv-Dev] [Patch] Extended connect dialog (PR#977)

[Top] [All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index] [Thread Index]
To: freeciv-dev@xxxxxxxxxxx
Cc: bugs@xxxxxxxxxxxxxxxxxxx
Subject: [Freeciv-Dev] [Patch] Extended connect dialog (PR#977)
From: Andreas Kemnade <akemnade@xxxxxxxxxxx>
Date: Mon, 24 Sep 2001 05:52:57 -0700 (PDT)

This patch pops up a new dialog after starting civclient.
It has three buttons:
New Game
Load Game
Join Game

The last button pops up the normal connect dialog. The other buttons
start the server and pipe its stdout and stderr to a window.
You can load games without using the keyboard.

Todo:
- Menu item for server window.
- Chatline should send server commands through stdin pipe, if
possible.
- What should happen if you select "Disconnect from server" if civclient
has started the server?
- Kill server when civclient exits (How to do this?)
- More error checking

Comments?

Greetings
Andreas Kemnade

diff --exclude-from freeciv/diff_ignore -Nur 
/usr/src/cvs/freeciv/client/gui-gtk/connectdlg.c 
freeciv/client/gui-gtk/connectdlg.c
--- /usr/src/cvs/freeciv/client/gui-gtk/connectdlg.c    Sun Sep  9 15:35:39 2001
+++ freeciv/client/gui-gtk/connectdlg.c Mon Sep 24 14:32:49 2001
@@ -17,6 +17,9 @@
 #include <errno.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+
 
 #include <gtk/gtk.h>
 
@@ -40,6 +43,14 @@
 
 static GtkWidget *dialog;
 
+static GtkWidget *server_window=NULL;
+static GtkWidget *server_output;
+static GtkWidget *server_output_scrollbar;
+
+static int stdin_pipe[2];
+static int stderr_pipe[2];
+static int stdout_pipe[2];
+
 /* meta Server */
 static int update_meta_dialog(GtkWidget *meta_list);
 static void meta_list_callback(GtkWidget *w, gint row, gint column);
@@ -120,10 +131,11 @@
   return FALSE;
 }
 
+
 /**************************************************************************
 ...
 **************************************************************************/
-void gui_server_connect(void)
+void join_game_callback(GtkWidget *w,gpointer data)
 {
   GtkWidget *label, *table, *book, *scrolled, *list, *vbox, *update;
   static char *titles_[6]= {N_("Server Name"), N_("Port"), N_("Version"),
@@ -132,6 +144,8 @@
   char buf [256];
   int i;
 
+  if (w)
+    destroy_message_dialog(w);
   if (!titles) titles = intl_slist(6, titles_);
 
   gtk_widget_set_sensitive(turn_done_button, FALSE);
@@ -365,4 +379,183 @@
   if (try_to_autoconnect()) {
     gtk_timeout_add(AUTOCONNECT_INTERVAL, try_to_autoconnect, NULL);
   }
+}
+
+/**************************************************************************
+  Sends a server command to the stdin pipe
+**************************************************************************/
+static void server_command_callback(GtkWidget *w,gpointer data)
+{
+  char *s;
+  if (data) {
+    s=(char *)data;
+  } else {
+    s=gtk_editable_get_chars(GTK_EDITABLE(w),0,-1);
+  }
+  write(stdin_pipe[1],s,strlen(s));
+  write(stdin_pipe[1],"\n",1);
+  if (!data)
+    g_free(s);
+}
+
+/**************************************************************************
+ Reads input from the server (pipe)
+**************************************************************************/
+static void get_pipe_input(gpointer data,
+                          gint fid,
+                          GdkInputCondition condition)
+{
+  char buf[1024];
+  int len;
+  len=read(fid,buf,sizeof(buf)-1);
+  if (len>0) { 
+    buf[len]=0;
+    gtk_text_freeze(GTK_TEXT(server_output));
+    gtk_text_insert(GTK_TEXT(server_output),NULL,NULL,NULL,buf,-1);
+    gtk_text_thaw(GTK_TEXT(server_output));
+  }
+
+  /* move the scrollbar forward by a ridiculous amount */
+  gtk_range_default_vmotion(GTK_RANGE(server_output_scrollbar), 0, 10000);
+  
+}
+
+/**************************************************************************
+ Creates the server window (which shows stdout and stderr of the server)
+**************************************************************************/
+static void create_server_window()
+{
+  GtkWidget *entry;
+  GtkWidget *button;
+  GtkWidget *vbox;
+  GtkWidget *hbox;
+  server_window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_title(GTK_WINDOW(server_window),_("Game control"));
+  gtk_signal_connect(GTK_OBJECT(server_window),"delete_event",
+                    GTK_SIGNAL_FUNC(gtk_widget_hide),server_window);
+  vbox=gtk_vbox_new(FALSE,5);
+  gtk_container_add(GTK_CONTAINER(server_window),vbox);
+  server_output=gtk_text_new(NULL,NULL);
+  gtk_text_set_editable(GTK_TEXT(server_output),FALSE);
+  server_output_scrollbar=gtk_vscrollbar_new(GTK_TEXT(server_output)->vadj);
+  hbox=gtk_hbox_new(FALSE,0);
+  gtk_box_pack_start(GTK_BOX(hbox),server_output,TRUE,TRUE,0);
+  gtk_box_pack_start(GTK_BOX(hbox),server_output_scrollbar,FALSE,FALSE,0);
+  gtk_box_pack_start(GTK_BOX(vbox),hbox,FALSE,FALSE,0);
+  gtk_widget_set_usize(server_output,600,100);
+  
+  hbox=gtk_hbox_new(FALSE,5);
+  gtk_box_pack_start(GTK_BOX(vbox),hbox,FALSE,FALSE,0);
+  
+  button=gtk_button_new_with_label(_("Start game"));
+  gtk_box_pack_start(GTK_BOX(hbox),button,FALSE,FALSE,0);
+  gtk_signal_connect(GTK_OBJECT(button),"clicked",
+                    GTK_SIGNAL_FUNC(server_command_callback),"start");
+  
+  button=gtk_button_new_with_label(_("End game"));
+  gtk_signal_connect(GTK_OBJECT(button),"clicked",
+                    GTK_SIGNAL_FUNC(server_command_callback),"quit");
+  gtk_box_pack_start(GTK_BOX(hbox),button,FALSE,FALSE,0);
+  
+  entry=gtk_entry_new();
+  gtk_box_pack_start(GTK_BOX(hbox),entry,TRUE,TRUE,0);
+  gtk_signal_connect(GTK_OBJECT(entry),"activate",
+                    GTK_SIGNAL_FUNC(server_command_callback),
+                    NULL);
+  gtk_widget_show_all(vbox);
+
+  if (pipe(stdin_pipe)) {
+    freelog(LOG_FATAL,_("Cannot create pipe"));
+    exit(1);
+  }
+  if (pipe(stdout_pipe)) {
+    freelog(LOG_FATAL,_("Cannot create pipe"));
+    exit(1);
+  }
+  if (pipe(stderr_pipe)) {
+    freelog(LOG_FATAL,_("Cannot create pipe"));
+    exit(1);
+  }
+  gdk_input_add(stdout_pipe[0],GDK_INPUT_READ,
+               get_pipe_input,NULL);
+  gdk_input_add(stderr_pipe[0],GDK_INPUT_READ,
+               get_pipe_input,NULL);
+}
+
+/**************************************************************************
+ Starts the server. data can contain the filename of a game. 
+**************************************************************************/
+static void start_server_callback(GtkWidget *w,gpointer data)
+{
+  pid_t pid;
+  if (w)
+    destroy_message_dialog(w);
+  if (!server_window)        /* will also create pipes */
+    create_server_window();
+  pid=fork();
+  if (pid==0) {
+    char *argv[4];
+    /* redirecting stdio */
+    dup2(stdout_pipe[1],1);
+    dup2(stderr_pipe[1],2);
+    dup2(stdin_pipe[0],0);
+    argv[0]="civserver";
+    argv[1]=NULL;
+    if (data) {
+      argv[1]="-f";
+      argv[2]=data;
+      argv[3]=NULL;
+    }
+    execvp("civserver",argv);
+    /* This line is only reached if civserver cannot be started. 
+       Calling exit here is dangerous due to X11 problems
+       (async replies) */
+    _exit(1);
+  }
+
+  gtk_widget_show(server_window);
+  server_autoconnect();
+}
+
+/**************************************************************************
+
+**************************************************************************/
+void filesel_callback(GtkWidget *w,gpointer data)
+{
+  char *filename;
+  filename=gtk_file_selection_get_filename(GTK_FILE_SELECTION(data));
+  start_server_callback(NULL,filename);
+}
+
+
+/**************************************************************************
+
+**************************************************************************/
+void load_game_callback(GtkWidget *w,gpointer data)
+{
+  GtkWidget *filesel;
+  destroy_message_dialog(w);
+  filesel=gtk_file_selection_new(_("Please select a game file to load"));
+  gtk_signal_connect(GTK_OBJECT(GTK_FILE_SELECTION(filesel)->ok_button),
+                    "clicked",GTK_SIGNAL_FUNC(filesel_callback),filesel);
+  gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(filesel)
+                                      ->ok_button),"clicked",
+                           GTK_SIGNAL_FUNC(gtk_widget_destroy),
+                           (gpointer)filesel);
+  gtk_signal_connect_object(GTK_OBJECT(GTK_FILE_SELECTION(filesel)
+                                      ->cancel_button),"clicked",
+                           GTK_SIGNAL_FUNC(gtk_widget_destroy),
+                           (gpointer)filesel);
+  gtk_widget_show(filesel);
+}
+/**************************************************************************
+
+**************************************************************************/
+void gui_server_connect(void)
+{
+  popup_message_dialog(top_vbox,
+                      _("Start a game"),_("What do you wish to to?"),
+                      _("New Game"),start_server_callback,NULL,
+                      _("Load Game"),load_game_callback,NULL,
+                      _("Join Game"),join_game_callback,NULL);
 }

[Prev in Thread] Current Thread [Next in Thread]