diff --git a/src/zmapServer/README b/src/zmapServer/README
new file mode 100755
index 0000000000000000000000000000000000000000..2b1d9204be9e3ee1bf95ee46db76d1c810b67fae
--- /dev/null
+++ b/src/zmapServer/README
@@ -0,0 +1,7 @@
+================================================================================   
+Server interface
+
+Code that provides an interface to contacting a server over the network and
+asking for and collecting data from the server.
+
+Subdirectories contain any code required for particular servers.
diff --git a/src/zmapServer/makefile b/src/zmapServer/makefile
new file mode 100755
index 0000000000000000000000000000000000000000..34c94e962f8a0c4288ceffc5ac4d20c734425f82
--- /dev/null
+++ b/src/zmapServer/makefile
@@ -0,0 +1,30 @@
+#
+# Makes the manager part of the ZMap application.
+#
+
+
+# local macros
+SERV_PRIV_HDRS = zmapServer_P.h
+PUB_HDRS = zmapServer.h
+SERV_SRC = zmapServer.c
+SERV_OBJ = zmapServer.o
+
+
+
+#
+# These must all be set for the common includes to work.
+# Need to include AceConn header.
+#
+CURRENT_LIB = $(ZMAP_LIB)
+CURRENT_OBJ = $(SERV_OBJ)
+CURRENT_DEP = $(PUB_HDRS) $(SERV_PRIV_HDRS)
+CURRENT_SRC = $(SERV_PRIV_HDRS) $(SERV_SRC)
+CURRENT_INC = -I$(HOME)/acedb/CODE/Ace-Conn
+
+#
+# point to common make include file which contains all the rules etc.
+#
+ROOT_DIRECTORY = ..
+MAKE_DIR = $(ROOT_DIRECTORY)/zmapMake
+include $(MAKE_DIR)/build.make
+
diff --git a/src/zmapServer/zmapServer.c b/src/zmapServer/zmapServer.c
new file mode 100755
index 0000000000000000000000000000000000000000..3cdef3c9e45c15bfc54e10cace01275200b24339
--- /dev/null
+++ b/src/zmapServer/zmapServer.c
@@ -0,0 +1,132 @@
+/*  File: zmapServer.c
+ *  Author: Ed Griffiths (edgrif@sanger.ac.uk)
+ *  Copyright (c) Sanger Institute, 2003
+ *-------------------------------------------------------------------
+ * ZMap is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * or see the on-line version at http://www.gnu.org/copyleft/gpl.txt
+ *-------------------------------------------------------------------
+ * This file is part of the ZMap genome database package
+ * and was written by
+ * 	Ed Griffiths (Sanger Institute, UK) edgrif@sanger.ac.uk,
+ *	Simon Kelley (Sanger Institute, UK) srk@sanger.ac.uk and
+ *      Rob Clack (Sanger Institute, UK) rnc@sanger.ac.uk
+ *
+ * Description: 
+ * Exported functions: See zmapServer.h
+ * HISTORY:
+ * Last edited: Sep  5 16:20 2003 (edgrif)
+ * Created: Wed Aug  6 15:46:38 2003 (edgrif)
+ * CVS info:   $Id: zmapServer.c,v 1.1 2003-11-13 15:01:09 edgrif Exp $
+ *-------------------------------------------------------------------
+ */
+
+#include <AceConn.h>
+#include <zmapServer_P.h>
+
+
+
+gboolean zMapServerCreateConnection(ZMapServer *server_out, char *host, int port,
+				    char *userid, char *passwd)
+{
+  gboolean result = FALSE ;
+  ZMapServer server ;
+  AceConnection connection = NULL ;
+  AceConnStatus status ;
+
+  /* slightly odd, always return a struct to provide error information. */
+  server = g_new(ZMapServerStruct, sizeof(ZMapServerStruct)) ; /* n.b. crashes on failure. */
+  *server_out = server ;
+
+  if ((status = AceConnCreate(&connection, host, port, userid, passwd, 20)) == ACECONN_OK)
+    {
+      /* Don't know if we really need to keep hold of these... */
+      server->host = g_strdup(host) ;
+      server->port = port ;
+
+      server->connection = connection ;
+
+      server->last_error_msg = NULL ;
+
+      result = TRUE ;
+    }
+  else
+    server->last_error_msg = AceConnGetErrorMsg(connection, status) ;
+
+  return result ;
+}
+
+
+gboolean zMapServerOpenConnection(ZMapServer server)
+{
+  gboolean result = FALSE ;
+  AceConnStatus status ;
+
+  if ((status = AceConnConnect(server->connection)) == ACECONN_OK)
+    result = TRUE ;
+  else
+    server->last_error_msg = AceConnGetErrorMsg(server->connection, status) ;
+
+  return result ;
+}
+
+
+gboolean zMapServerRequest(ZMapServer server, char *request, char **reply)
+{
+  gboolean result = FALSE ;
+  int reply_len = 0 ;
+  AceConnStatus status ;
+
+  if ((status = AceConnRequest(server->connection, request, (void **)reply, &reply_len)) == ACECONN_OK)
+    result = TRUE ;
+  else
+    server->last_error_msg = AceConnGetErrorMsg(server->connection, status) ;
+
+  return result ;
+}
+
+gboolean zMapServerCloseConnection(ZMapServer server)
+{
+  gboolean result = TRUE ;
+  AceConnStatus status ;
+
+  if ((status = AceConnConnectionOpen(server->connection)) == ACECONN_OK)
+    {
+      if ((status = AceConnDisconnect(server->connection)) != ACECONN_OK)
+	result = FALSE ;
+      else
+	server->last_error_msg = AceConnGetErrorMsg(server->connection, status) ;
+    }
+  else
+    server->last_error_msg = AceConnGetErrorMsg(server->connection, status) ;
+
+  return result ;
+}
+
+gboolean zMapServerFreeConnection(ZMapServer server)
+{
+  gboolean result = TRUE ;
+
+  AceConnDestroy(server->connection) ;			    /* Does not fail. */
+  g_free(server->host) ;
+  g_free(server) ;
+
+  return result ;
+}
+
+
+char *zMapServerLastErrorMsg(ZMapServer server)
+{
+  return server->last_error_msg ;
+}
diff --git a/src/zmapServer/zmapServer_P.h b/src/zmapServer/zmapServer_P.h
new file mode 100755
index 0000000000000000000000000000000000000000..1bde57e10f9822066abc0239a3421e87acbc2cc1
--- /dev/null
+++ b/src/zmapServer/zmapServer_P.h
@@ -0,0 +1,57 @@
+/*  File: zmapServer_P.h
+ *  Author: Ed Griffiths (edgrif@sanger.ac.uk)
+ *  Copyright (c) Sanger Institute, 2003
+ *-------------------------------------------------------------------
+ * ZMap is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * or see the on-line version at http://www.gnu.org/copyleft/gpl.txt
+ *-------------------------------------------------------------------
+ * This file is part of the ZMap genome database package
+ * and was written by
+ * 	Ed Griffiths (Sanger Institute, UK) edgrif@sanger.ac.uk,
+ *	Simon Kelley (Sanger Institute, UK) srk@sanger.ac.uk and
+ *      Rob Clack (Sanger Institute, UK) rnc@sanger.ac.uk
+ *
+ * Description: 
+ * Exported functions: See XXXXXXXXXXXXX.h
+ * HISTORY:
+ * Last edited: Nov 12 15:59 2003 (edgrif)
+ * Created: Wed Aug  6 15:48:47 2003 (edgrif)
+ * CVS info:   $Id: zmapServer_P.h,v 1.1 2003-11-13 15:01:09 edgrif Exp $
+ *-------------------------------------------------------------------
+ */
+#ifndef ZMAP_SERVER_P_H
+#define ZMAP_SERVER_P_H
+
+#include <ZMap/zmapServer.h>
+
+
+/* A connection to a database. */
+typedef struct _ZMapServerStruct
+{
+  char *host ;
+  int port ;
+
+  AceConnection connection ;
+
+  char *last_error_msg ;
+
+} ZMapServerStruct ;
+
+
+
+
+
+
+#endif /* !ZMAP_SERVER_P_H */
diff --git a/src/zmapThreads/README b/src/zmapThreads/README
new file mode 100755
index 0000000000000000000000000000000000000000..5b0566958c13662e520c2d8db779ee74bd954492
--- /dev/null
+++ b/src/zmapThreads/README
@@ -0,0 +1,5 @@
+================================================================================   
+threads
+
+Code to create and run threads and have them interact with the main zmapwindow
+code.
diff --git a/src/zmapThreads/makefile b/src/zmapThreads/makefile
new file mode 100755
index 0000000000000000000000000000000000000000..adf5118330e8a09ec8a1963572929297cc68c429
--- /dev/null
+++ b/src/zmapThreads/makefile
@@ -0,0 +1,28 @@
+#
+# Makes the manager part of the ZMap application.
+#
+
+
+# local macros
+PUB_HDRS = zmapSys.h zmapConn.h zmapServer.h
+APP_PRIV_HDRS = zmapConn_P.h zmapSlave_P.h
+APP_SRC = zmapConn.c zmapSlave.c zmapConnutils.c
+APP_OBJ = zmapConn.o zmapSlave.o zmapConnutils.o
+
+# the main routines will need some different treatment maybe...???? try putting
+# them all together, don't know if it will work.....
+
+#
+# These must all be set for the common includes to work.
+#
+CURRENT_LIB = $(ZMAP_LIB)
+CURRENT_OBJ = $(APP_OBJ)
+CURRENT_DEP = $(PUB_HDRS) $(APP_PRIV_HDRS)
+CURRENT_SRC = $(APP_PRIV_HDRS) $(APP_SRC)
+
+#
+# point to common make include file which contains all the rules etc.
+#
+ROOT_DIRECTORY = ..
+MAKE_DIR = $(ROOT_DIRECTORY)/zmapMake
+include $(MAKE_DIR)/build.make
diff --git a/src/zmapThreads/zmapConn.c b/src/zmapThreads/zmapConn.c
new file mode 100755
index 0000000000000000000000000000000000000000..bef8e0df63b9def81e7803d2687d42c971cee8ef
--- /dev/null
+++ b/src/zmapThreads/zmapConn.c
@@ -0,0 +1,183 @@
+/*  File: zmapthrcontrol.c
+ *  Author: Ed Griffiths (edgrif@sanger.ac.uk)
+ *  Copyright (c) Sanger Institute, 2003
+ *-------------------------------------------------------------------
+ * ZMap is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * or see the on-line version at http://www.gnu.org/copyleft/gpl.txt
+ *-------------------------------------------------------------------
+ * This file is part of the ZMap genome database package
+ * and was written by
+ *      Rob Clack (Sanger Institute, UK) rnc@sanger.ac.uk,
+ * 	Ed Griffiths (Sanger Institute, UK) edgrif@sanger.ac.uk and
+ *	Simon Kelley (Sanger Institute, UK) srk@sanger.ac.uk
+ *
+ * Description: 
+ * Exported functions: See XXXXXXXXXXXXX.h
+ * HISTORY:
+ * Last edited: Sep  3 16:25 2003 (edgrif)
+ * Created: Thu Jul 24 14:37:18 2003 (edgrif)
+ * CVS info:   $Id: zmapConn.c,v 1.1 2003-11-13 15:02:12 edgrif Exp $
+ *-------------------------------------------------------------------
+ */
+
+#include <zmapConn_P.h>
+
+/* Turn on/off all debugging messages for threads. */
+gboolean zmap_thr_debug_G = TRUE ;
+
+
+
+
+
+ZMapConnection zMapConnCreate(char *machine, int port, char *sequence)
+{
+  ZMapConnection connection ;
+  pthread_t thread_id ;
+  pthread_attr_t thread_attr ;
+  int status ;
+
+  connection = g_new(ZMapConnectionStruct, sizeof(ZMapConnectionStruct)) ;
+
+  connection->machine = g_strdup(machine) ;
+  connection->port = port ;
+  connection->sequence = g_strdup(sequence) ;
+
+  /* ok to just set state here because we have not started the thread yet.... */
+  zmapCondVarCreate(&(connection->request)) ;
+  connection->request.state = ZMAP_REQUEST_WAIT ;
+
+  zmapVarCreate(&(connection->reply)) ;
+  connection->reply.state = ZMAP_REPLY_WAIT ;
+
+
+  /* Set the new threads attributes so it will run "detached", we do not want anything from them.
+   * when they die, we want them to go away and release their resources. */
+  if ((status = pthread_attr_init(&thread_attr)) != 0)
+    {
+      ZMAPSYSERR(status, "Create thread attibutes") ;
+    }
+
+  if ((status = pthread_attr_setdetachstate(&thread_attr, PTHREAD_CREATE_DETACHED)) != 0)
+    {
+      ZMAPSYSERR(status, "Set thread detached attibute") ;
+    }
+
+
+  /* Create the new thread. */
+  if ((status = pthread_create(&thread_id, &thread_attr, zmapNewThread, (void *)connection)) != 0)
+    {
+      ZMAPSYSERR(status, "Thread creation") ;
+    }
+
+
+  connection->thread_id = thread_id ;
+
+
+  return connection ;
+}
+
+
+void zMapConnLoadData(ZMapConnection connection)
+{
+  zmapCondVarSignal(&connection->request, ZMAP_REQUEST_GETDATA) ;
+
+  return ;
+}
+
+
+gboolean zMapConnGetReply(ZMapConnection connection, ZMapThreadReply *state)
+{
+  gboolean got_value ;
+  
+  got_value = zmapVarGetValue(&(connection->reply), state) ;
+  
+  return got_value ;
+}
+
+
+
+void zMapConnSetReply(ZMapConnection connection, ZMapThreadReply state)
+{
+  zmapVarSetValue(&(connection->reply), state) ;
+
+  return ;
+}
+
+
+gboolean zMapConnGetReplyWithData(ZMapConnection connection, ZMapThreadReply *state,
+				  void **data, char **err_msg)
+{
+  gboolean got_value ;
+  
+  got_value = zmapVarGetValueWithData(&(connection->reply), state, data, err_msg) ;
+  
+  return got_value ;
+}
+
+
+
+
+
+pthread_t zMapConnGetThreadid(ZMapConnection connection)
+{
+  return connection->thread_id ;
+}
+
+/* Kill the thread by cancelling it, as this will asynchronously we cannot release the connections
+ * resources in this call. */
+void zMapConnKill(ZMapConnection connection)
+{
+  int status ;
+
+  ZMAP_THR_DEBUG(("GUI: killing and destroying connection for thread %x\n", connection->thread_id)) ;
+
+  /* Really we should signal an exit here...but that lead to deadlocks, think about this bit.. */
+
+  /* Signal the thread to cancel it, we could set a cond var of EXIT but this will take ages
+   * for the thread to be cancelled. */
+  if ((status = pthread_cancel(connection->thread_id)) != 0)
+    {
+      ZMAPSYSERR(status, "Thread cancel") ;
+    }
+
+  return ;
+}
+
+
+/* Release the connections resources, don't do this until the slave thread has gone. */
+void zMapConnDestroy(ZMapConnection connection)
+{
+  int status ;
+
+  ZMAP_THR_DEBUG(("GUI: destroying connection for thread %x\n", connection->thread_id)) ;
+
+  zmapVarDestroy(&connection->reply) ;
+  zmapCondVarDestroy(&(connection->request)) ;
+
+  g_free(connection->machine) ;
+  g_free(connection->sequence) ;
+
+  g_free(connection) ;
+
+  return ;
+}
+
+
+
+
+/* 
+ * ---------------------  Internal routines  ------------------------------
+ */
+
diff --git a/src/zmapThreads/zmapConn_P.h b/src/zmapThreads/zmapConn_P.h
new file mode 100755
index 0000000000000000000000000000000000000000..749d9969efe616236335edf6a293d751af0eb5e5
--- /dev/null
+++ b/src/zmapThreads/zmapConn_P.h
@@ -0,0 +1,126 @@
+/*  File: zmapConn_P.h
+ *  Author: Ed Griffiths (edgrif@sanger.ac.uk)
+ *  Copyright (c) Sanger Institute, 2003
+ *-------------------------------------------------------------------
+ * ZMap is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * or see the on-line version at http://www.gnu.org/copyleft/gpl.txt
+ *-------------------------------------------------------------------
+ * This file is part of the ZMap genome database package
+ * and was written by
+ *      Rob Clack (Sanger Institute, UK) rnc@sanger.ac.uk,
+ * 	Ed Griffiths (Sanger Institute, UK) edgrif@sanger.ac.uk and
+ *	Simon Kelley (Sanger Institute, UK) srk@sanger.ac.uk
+ *
+ * Description: 
+ * Exported functions: See XXXXXXXXXXXXX.h
+ * HISTORY:
+ * Last edited: Nov 12 16:35 2003 (edgrif)
+ * Created: Thu Jul 24 14:36:08 2003 (edgrif)
+ * CVS info:   $Id: zmapConn_P.h,v 1.1 2003-11-13 15:02:12 edgrif Exp $
+ *-------------------------------------------------------------------
+ */
+#ifndef ZMAP_CONN_PRIV_H
+#define ZMAP_CONN_PRIV_H
+
+
+#include <pthread.h>
+#include <glib.h>
+#include <ZMap/zmapSys.h>
+#include <ZMap/zmapConn.h>
+
+
+/* Seems that Linux defines the time structure used in some pthread calls as "timespec",
+ * whereas alphas call it "timespec_t"....deep sigh.... */
+#ifdef LINUX
+#define TIMESPEC struct timespec
+#else
+#define TIMESPEC timespec_t
+#endif
+
+#define ZMAP_THR_DEBUG(ALL_ARGS_WITH_BRACKETS) \
+do { \
+     if (zmap_thr_debug_G) \
+       printf ALL_ARGS_WITH_BRACKETS ; \
+   } while (0)
+
+
+/* Requests are via a cond var system. */
+typedef struct
+{
+  pthread_mutex_t mutex ;				    /* controls access to this struct. */
+  pthread_cond_t cond ;					    /* Slave waits on this. */
+  ZMapThreadRequest state ;				    /* Contains request to slave. */
+} ZMapRequestStruct, *ZMapRequest ;
+
+/* Replies via a simpler mutex. */
+typedef struct
+{
+  pthread_mutex_t mutex ;				    /* controls access to this struct. */
+  ZMapThreadReply state ;				    /* Contains reply from slave. */
+  char *data ;						    /* May also contain data for some replies. */
+  char *error_msg ;					    /* May contain error message for when
+							       thread fails. */
+} ZMapReplyStruct, *ZMapReply ;
+
+
+
+/* The ZMapConnection, there is one per connection to a database, i.e. one per slave
+ * thread. */
+typedef struct _ZMapConnectionStruct
+{
+  /* These are read only after creation of the thread. */
+  gchar *machine ;
+  int port ;
+  gchar *sequence ;
+  pthread_t thread_id ;
+
+
+  /* These control the communication between the GUI thread and the connection threads,
+   * they are mutex locked and the request code makes use of the condition variable. */
+  ZMapRequestStruct request ;				    /* GUIs request. */
+  ZMapReplyStruct reply ;				    /* Slaves reply. */
+
+} ZMapConnectionStruct ;
+
+
+/* Thread calls. */
+void *zmapNewThread(void *thread_args) ;
+
+
+/* Request routines. */
+void zmapCondVarCreate(ZMapRequest thread_state) ;
+void zmapCondVarSignal(ZMapRequest thread_state, ZMapThreadRequest new_state) ;
+void zmapCondVarWait(ZMapRequest thread_state, ZMapThreadRequest waiting_state) ;
+ZMapThreadRequest zmapCondVarWaitTimed(ZMapRequest condvar, ZMapThreadRequest waiting_state,
+				       TIMESPEC *timeout, gboolean reset_to_waiting) ;
+void zmapCondVarDestroy(ZMapRequest thread_state) ;
+
+char *zmapVarGetRequestString(ZMapThreadRequest signalled_state) ;
+
+
+
+/* Reply routines. */
+void zmapVarCreate(ZMapReply thread_state) ;
+void zmapVarSetValue(ZMapReply thread_state, ZMapThreadReply new_state) ;
+gboolean zmapVarGetValue(ZMapReply thread_state, ZMapThreadReply *state_out) ;
+void zmapVarSetValueWithData(ZMapReply thread_state, ZMapThreadReply new_state, void *data) ;
+void zmapVarSetValueWithError(ZMapReply thread_state, ZMapThreadReply new_state, char *err_msg) ;
+gboolean zmapVarGetValueWithData(ZMapReply thread_state, ZMapThreadReply *state_out,
+				 void **data_out, char **err_msg_out) ;
+void zmapVarDestroy(ZMapReply thread_state) ;
+
+char *zmapVarGetReplyString(ZMapThreadReply signalled_state) ;
+
+#endif /* !ZMAP_CONN_PRIV_H */
diff --git a/src/zmapThreads/zmapConnutils.c b/src/zmapThreads/zmapConnutils.c
new file mode 100755
index 0000000000000000000000000000000000000000..49cbf9f077a653ab25ceec3a7098ab7375bce863
--- /dev/null
+++ b/src/zmapThreads/zmapConnutils.c
@@ -0,0 +1,405 @@
+/*  File: zmapthrutils.c
+ *  Author: Ed Griffiths (edgrif@sanger.ac.uk)
+ *  Copyright (c) Sanger Institute, 2003
+ *-------------------------------------------------------------------
+ * ZMap is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * or see the on-line version at http://www.gnu.org/copyleft/gpl.txt
+ *-------------------------------------------------------------------
+ * This file is part of the ZMap genome database package
+ * and was written by
+ *      Rob Clack (Sanger Institute, UK) rnc@sanger.ac.uk,
+ * 	Ed Griffiths (Sanger Institute, UK) edgrif@sanger.ac.uk and
+ *	Simon Kelley (Sanger Institute, UK) srk@sanger.ac.uk
+ *
+ * Description: 
+ * Exported functions: See XXXXXXXXXXXXX.h
+ * HISTORY:
+ * Last edited: Nov 12 16:42 2003 (edgrif)
+ * Created: Thu Jul 24 14:37:35 2003 (edgrif)
+ * CVS info:   $Id: zmapConnutils.c,v 1.1 2003-11-13 15:02:13 edgrif Exp $
+ *-------------------------------------------------------------------
+ */
+
+#include <errno.h>
+#include <zmapConn_P.h>
+
+
+static void releaseCondvarMutex(void *thread_data) ;
+
+
+
+
+void zmapCondVarCreate(ZMapRequest thread_state)
+{
+  int status ;
+
+  if ((status = pthread_mutex_init(&(thread_state->mutex), NULL)) != 0)
+    {
+      ZMAPSYSERR(status, "mutex init") ;
+    }
+
+  if ((status = pthread_cond_init(&(thread_state->cond), NULL)) != 0)
+    {
+      ZMAPSYSERR(status, "cond init") ;
+    }
+  
+  thread_state->state = ZMAP_REQUEST_INIT ;
+  
+  return ;
+}
+
+void zmapCondVarSignal(ZMapRequest thread_state, ZMapThreadRequest new_state)
+{
+  int status ;
+  
+  pthread_cleanup_push(releaseCondvarMutex, (void *)thread_state) ;
+  
+  if ((status = pthread_mutex_lock(&(thread_state->mutex))) != 0)
+    {
+      ZMAPSYSERR(status, "zmapCondVarSignal mutex lock") ;
+    }
+
+  thread_state->state = new_state ;
+
+  if ((status = pthread_cond_signal(&(thread_state->cond))) != 0)
+    {
+      ZMAPSYSERR(status, "zmapCondVarSignal cond signal") ;
+    }
+
+  if ((status = pthread_mutex_unlock(&(thread_state->mutex))) != 0)
+    {
+      ZMAPSYSERR(status, "zmapCondVarSignal mutex unlock") ;
+    }
+
+  pthread_cleanup_pop(0) ;				    /* 0 => only call cleanup if cancelled. */
+
+  return ;
+}
+
+
+/* Blocking wait.... */
+void zmapCondVarWait(ZMapRequest thread_state, ZMapThreadRequest waiting_state)
+{
+  int status ;
+
+  pthread_cleanup_push(releaseCondvarMutex, (void *)thread_state) ;
+
+  if ((status = pthread_mutex_lock(&(thread_state->mutex))) != 0)
+    {
+      ZMAPSYSERR(status, "zmapCondVarWait mutex lock") ;
+    }
+
+  while (thread_state->state == waiting_state)
+    {
+      if ((status = pthread_cond_wait(&(thread_state->cond), &(thread_state->mutex))) != 0)
+	{
+	  ZMAPSYSERR(status, "zmapCondVarWait cond wait") ;
+	}
+    }
+
+  if ((status = pthread_mutex_unlock(&(thread_state->mutex))) != 0)
+    {
+      ZMAPSYSERR(status, "zmapCondVarWait mutex unlock") ;
+    }
+
+  pthread_cleanup_pop(0) ;				    /* 0 => only call cleanup if cancelled. */
+
+  return ;
+}
+
+
+/* timed wait, returns FALSE if cond var was not signalled (i.e. it timed out),
+ * TRUE otherwise....
+ * NOTE that you can optionally get the condvar state reset to the waiting_state, this
+ * can be useful if you are calling this routine from a loop in which you wait until
+ * something has changed from the waiting state...i.e. somehow you need to return to the
+ * waiting state before looping again. */
+ZMapThreadRequest zmapCondVarWaitTimed(ZMapRequest condvar, ZMapThreadRequest waiting_state,
+				       TIMESPEC *relative_timeout, gboolean reset_to_waiting)
+{
+  ZMapThreadRequest signalled_state = ZMAP_REQUEST_INIT ;
+  int status ;
+  TIMESPEC systimeout ;
+
+
+  pthread_cleanup_push(releaseCondvarMutex, (void *)condvar) ;
+
+
+  if ((status = pthread_mutex_lock(&(condvar->mutex))) != 0)
+    {
+      ZMAPSYSERR(status, "zmapCondVarWait mutex lock") ;
+    }
+  
+  /* Get the relative timeout converted to absolute for the call. */
+  if ((status = pthread_get_expiration_np(relative_timeout, &systimeout)) != 0)
+    ZMAPSYSERR(status, "zmapCondVarWaitTimed invalid time") ;
+
+  while (condvar->state == waiting_state)
+    {
+      if ((status = pthread_cond_timedwait(&(condvar->cond), &(condvar->mutex),
+					   &systimeout)) != 0)
+	{
+	  if (status == ETIMEDOUT)			    /* Timed out so return. */
+	    {
+	      condvar->state = ZMAP_REQUEST_TIMED_OUT ;
+	      break ;
+	    }
+	  else
+	    ZMAPSYSERR(status, "zmapCondVarWait cond wait") ;
+	}
+    }
+
+  signalled_state = condvar->state ;			    /* return signalled end state. */
+
+  /* optionally reset current state to wait state. */
+  if (reset_to_waiting)
+    condvar->state = waiting_state ;
+
+  if ((status = pthread_mutex_unlock(&(condvar->mutex))) != 0)
+    {
+      ZMAPSYSERR(status, "zmapCondVarWait mutex unlock") ;
+    }
+
+  pthread_cleanup_pop(0) ;				    /* 0 => only call cleanup if cancelled. */
+
+  return signalled_state ;
+}
+
+
+void zmapCondVarDestroy(ZMapRequest thread_state)
+{
+  int status ;
+  
+  if ((status = pthread_cond_destroy(&(thread_state->cond))) != 0)
+    {
+      ZMAPSYSERR(status, "cond destroy") ;
+    }
+  
+
+  if ((status = pthread_mutex_destroy(&(thread_state->mutex))) != 0)
+    {
+      ZMAPSYSERR(status, "mutex destroy") ;
+    }
+  
+  return ;
+}
+
+
+/* Must be kept in step with declaration of ZMapThreadRequest enums in zmapConn_P.h */
+char *zmapVarGetRequestString(ZMapThreadRequest signalled_state)
+{
+  char *str_states[] = {"ZMAP_REQUEST_INIT", "ZMAP_REQUEST_WAIT", "ZMAP_REQUEST_TIMED_OUT",
+			"ZMAP_REQUEST_GETDATA", "ZMAP_REQUEST_EXIT"} ;
+
+  return str_states[signalled_state] ;
+}
+
+
+
+
+/* this set of routines manipulates the variable in the thread state struct but do not
+ * involve the Condition Variable. */
+
+void zmapVarCreate(ZMapReply thread_state)
+{
+  int status ;
+
+  if ((status = pthread_mutex_init(&(thread_state->mutex), NULL)) != 0)
+    {
+      ZMAPSYSERR(status, "mutex init") ;
+    }
+
+  thread_state->state = ZMAP_REPLY_INIT ;
+  
+  return ;
+}
+
+
+
+void zmapVarSetValue(ZMapReply thread_state, ZMapThreadReply new_state)
+{
+  int status ;
+
+  if ((status = pthread_mutex_lock(&(thread_state->mutex))) != 0)
+    {
+      ZMAPSYSERR(status, "zmapVarSetValue mutex lock") ;
+    }
+
+  thread_state->state = new_state ;
+
+  if ((status = pthread_mutex_unlock(&(thread_state->mutex))) != 0)
+    {
+      ZMAPSYSERR(status, "zmapVarSetValue mutex unlock") ;
+    }
+
+  return ;
+}
+
+
+/* Returns TRUE if it could read the value (i.e. the mutex was unlocked)
+ * and returns the value in state_out,
+ * returns FALSE otherwise. */
+gboolean zmapVarGetValue(ZMapReply thread_state, ZMapThreadReply *state_out)
+{
+  gboolean unlocked = TRUE ;
+  int status ;
+
+  if ((status = pthread_mutex_trylock(&(thread_state->mutex))) != 0)
+    {
+      if (status == EBUSY)
+	unlocked = FALSE ;
+      else
+	ZMAPSYSERR(status, "zmapVarGetValue mutex lock") ;
+    }
+  else
+    {
+      *state_out = thread_state->state ;
+      unlocked = TRUE ;
+
+      if ((status = pthread_mutex_unlock(&(thread_state->mutex))) != 0)
+	{
+	  ZMAPSYSERR(status, "zmapVarGetValue mutex unlock") ;
+	}
+    }
+
+  return unlocked ;
+}
+
+
+void zmapVarSetValueWithData(ZMapReply thread_state, ZMapThreadReply new_state, void *data)
+{
+  int status ;
+
+  if ((status = pthread_mutex_lock(&(thread_state->mutex))) != 0)
+    {
+      ZMAPSYSERR(status, "zmapVarSetValueWithData mutex lock") ;
+    }
+
+  thread_state->state = new_state ;
+  thread_state->data = data ;
+
+  if ((status = pthread_mutex_unlock(&(thread_state->mutex))) != 0)
+    {
+      ZMAPSYSERR(status, "zmapVarSetValueWithData mutex unlock") ;
+    }
+
+  return ;
+}
+
+
+void zmapVarSetValueWithError(ZMapReply thread_state, ZMapThreadReply new_state, char *err_msg)
+{
+  int status ;
+
+  if ((status = pthread_mutex_lock(&(thread_state->mutex))) != 0)
+    {
+      ZMAPSYSERR(status, "zmapVarSetValueWithError mutex lock") ;
+    }
+
+  thread_state->state = new_state ;
+  thread_state->error_msg = err_msg ;
+
+  if ((status = pthread_mutex_unlock(&(thread_state->mutex))) != 0)
+    {
+      ZMAPSYSERR(status, "zmapVarSetValueWithError mutex unlock") ;
+    }
+
+  return ;
+}
+
+
+/* Returns TRUE if it could read the value (i.e. the mutex was unlocked)
+ * and returns the value in state_out and also if there is any data it
+ * is returned in data_out and if there is an err_msg it is returned in err_msg_out,
+ * returns FALSE if it could not read the value. */
+gboolean zmapVarGetValueWithData(ZMapReply thread_state, ZMapThreadReply *state_out,
+				 void **data_out, char **err_msg_out)
+{
+  gboolean unlocked = TRUE ;
+  int status ;
+
+  if ((status = pthread_mutex_trylock(&(thread_state->mutex))) != 0)
+    {
+      if (status == EBUSY)
+	unlocked = FALSE ;
+      else
+	ZMAPSYSERR(status, "zmapVarGetValue mutex lock") ;
+    }
+  else
+    {
+      *state_out = thread_state->state ;
+      if (thread_state->data)
+	*data_out = thread_state->data ;
+      if (thread_state->error_msg)
+	*err_msg_out = thread_state->error_msg ;
+
+      unlocked = TRUE ;
+
+      if ((status = pthread_mutex_unlock(&(thread_state->mutex))) != 0)
+	{
+	  ZMAPSYSERR(status, "zmapVarGetValue mutex unlock") ;
+	}
+    }
+
+  return unlocked ;
+}
+
+
+void zmapVarDestroy(ZMapReply thread_state)
+{
+  int status ;
+  
+  if ((status = pthread_mutex_destroy(&(thread_state->mutex))) != 0)
+    {
+      ZMAPSYSERR(status, "mutex destroy") ;
+    }
+  
+  return ;
+}
+
+
+
+/* Must be kept in step with declaration of ZMapThreadReply enums in zmapConn_P.h */
+char *zmapVarGetReplyString(ZMapThreadReply signalled_state)
+{
+  char *str_states[] = {"ZMAP_REPLY_INIT", "ZMAP_REPLY_WAIT",
+			"ZMAP_REPLY_GOTDATA", "ZMAP_REPLY_EXIT", "ZMAP_REPLY_DESTROYED"} ;
+
+  return str_states[signalled_state] ;
+}
+
+
+
+
+/* 
+ * -----------------------  Internal Routines  -----------------------
+ */
+
+/* Called when a thread gets cancelled while waiting on a mutex to ensure that the mutex
+ * gets released. */
+static void releaseCondvarMutex(void *thread_data)
+{
+  ZMapRequest condvar = (ZMapRequest)thread_data ;
+  int status ;
+
+  ZMAP_THR_DEBUG(("releaseCondvarMutex cleanup handler\n")) ;
+
+  if ((status = pthread_mutex_unlock(&(condvar->mutex))) != 0)
+    {
+      ZMAPSYSERR(status, "releaseCondvarMutex cleanup handler - mutex unlock") ;
+    }
+
+  return ;
+}
diff --git a/src/zmapThreads/zmapSlave.c b/src/zmapThreads/zmapSlave.c
new file mode 100755
index 0000000000000000000000000000000000000000..24f0c1746ce1a0b62c236ee966f4e42588c50def
--- /dev/null
+++ b/src/zmapThreads/zmapSlave.c
@@ -0,0 +1,234 @@
+/*  File: zmapthrslave.c
+ *  Author: Ed Griffiths (edgrif@sanger.ac.uk)
+ *  Copyright (c) Sanger Institute, 2003
+ *-------------------------------------------------------------------
+ * ZMap is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * or see the on-line version at http://www.gnu.org/copyleft/gpl.txt
+ *-------------------------------------------------------------------
+ * This file is part of the ZMap genome database package
+ * and was written by
+ *      Rob Clack (Sanger Institute, UK) rnc@sanger.ac.uk,
+ * 	Ed Griffiths (Sanger Institute, UK) edgrif@sanger.ac.uk and
+ *	Simon Kelley (Sanger Institute, UK) srk@sanger.ac.uk
+ *
+ * Description: 
+ * Exported functions: See XXXXXXXXXXXXX.h
+ * HISTORY:
+ * Last edited: Nov 12 16:36 2003 (edgrif)
+ * Created: Thu Jul 24 14:37:26 2003 (edgrif)
+ * CVS info:   $Id: zmapSlave.c,v 1.1 2003-11-13 15:02:13 edgrif Exp $
+ *-------------------------------------------------------------------
+ */
+
+/* With some additional calls in the zmapConn code I could get rid of the need for
+ * the private header here...... */
+
+#include <zmapConn_P.h>
+#include <ZMap/zmapServer.h>
+#include <zmapSlave_P.h>
+
+
+
+enum {ZMAP_SLAVE_REQ_BUFSIZE = 512} ;
+
+
+
+static void cleanUpThread(void *thread_args) ;
+
+
+
+
+
+/* This is the routine that is called by the pthread_create() function, in effect
+ * this is an endless loop processing requests signalled to the thread via a
+ * condition variable. If this thread kills itself we will exit this routine
+ * normally, if the thread is cancelled however we may exit from any thread cancellable
+ * system call currently in progress or any of our cancellation points so its
+ * important that the clean up routine registered with pthread_cleanup_push()
+ * really does clean up properly. */
+void *zmapNewThread(void *thread_args)
+{
+  zmapThreadCB thread_cb ;
+  ZMapConnection connection = (ZMapConnection)thread_args ;
+  ZMapRequest thread_state = &(connection->request) ;
+  int status ;
+  TIMESPEC timeout ;
+  ZMapThreadRequest signalled_state ;
+
+
+  thread_cb = g_new(zmapThreadCBstruct, sizeof(zmapThreadCBstruct)) ;
+  thread_cb->connection = connection ;
+  thread_cb->thread_died = FALSE ;
+  thread_cb->initial_error = NULL ;
+  thread_cb->server = NULL ;
+  thread_cb->server_request = g_string_sized_new(ZMAP_SLAVE_REQ_BUFSIZE) ;
+  thread_cb->server_reply = NULL ;
+
+
+  /* Only do the minimum before setting this up as this is the call that makes sure our
+   * cleanup routine is called. */
+  pthread_cleanup_push(cleanUpThread, (void *)thread_cb) ;
+
+  if (!zMapServerCreateConnection(&(thread_cb->server), connection->machine, connection->port,
+				  "any", "any"))
+    {
+      thread_cb->thread_died = TRUE ;
+      thread_cb->initial_error = g_strdup_printf("%s - %s", ZMAPSLAVE_CONNCREATE,
+						 zMapServerLastErrorMsg(thread_cb->server)) ;
+      goto clean_up ;
+    }
+
+  if (!zMapServerOpenConnection(thread_cb->server))
+    {
+      thread_cb->thread_died = TRUE ;
+      thread_cb->initial_error = g_strdup_printf("%s - %s", ZMAPSLAVE_CONNOPEN,
+						 zMapServerLastErrorMsg(thread_cb->server)) ;
+      goto clean_up ;
+    }
+
+
+  while (1)
+    {
+      ZMAP_THR_DEBUG(("%x: about to do timed wait\n", connection->thread_id)) ;
+
+      /* this will crap over performance...asking the time all the time !! */
+      timeout.tv_sec = 5 ;				    /* n.b. interface seems to absolute time. */
+      timeout.tv_nsec = 0 ;
+      signalled_state = zmapCondVarWaitTimed(thread_state, ZMAP_REQUEST_WAIT, &timeout, TRUE) ;
+
+      ZMAP_THR_DEBUG(("%x: finished condvar wait, state = %s\n", connection->thread_id,
+		      zmapVarGetRequestString(signalled_state))) ;
+
+      if (signalled_state == ZMAP_REQUEST_TIMED_OUT)
+	{
+	  continue ;
+	}
+      else if (signalled_state == ZMAP_REQUEST_GETDATA)
+	{
+	  static int failure = 0 ;
+	  char *server_command ;
+
+	  ZMAP_THR_DEBUG(("%x: getting data....\n", connection->thread_id)) ;
+
+	  g_string_sprintf(thread_cb->server_request,
+			   "gif seqget %s ; seqfeatures", connection->sequence) ;
+
+	  if (!zMapServerRequest(thread_cb->server, thread_cb->server_request->str,
+				 &(thread_cb->server_reply)))
+	    {
+	      thread_cb->thread_died = TRUE ;
+
+	      /* NOTE IMPLICIT TERMINATION OF THREAD BY JUMPING OUT OF THIS LOOP
+	       * WHICH LEADS TO EXITTING FROM THIS ROUTINE. FOR OTHER ERRORS WE WIL
+	       * HAVE TO HAVE A MORE FORMAL MECHANISM.... */
+	      break ;
+	    }
+
+	  ZMAP_THR_DEBUG(("%x: got all data....\n", connection->thread_id)) ;
+
+
+	  /* Signal that we got some data. */
+	  zmapVarSetValueWithData(&(connection->reply), ZMAP_REPLY_GOTDATA,
+				  (void *)(thread_cb->server_reply)) ;
+
+	  thread_cb->server_reply = NULL ;		    /* Reset, we don't free this string. */
+	}
+    }
+
+
+  /* Note that once we reach here the thread will exit, the pthread_cleanup_pop(1) ensures
+   * we call our cleanup routine before we exit.
+   * Most times we will not get here because we will be pthread_cancel'd and go straight into
+   * our clean_up routine. */
+ clean_up:
+
+  pthread_cleanup_pop(1) ;				    /* 1 => always call clean up routine */
+
+
+  ZMAP_THR_DEBUG(("%x: thread exitting from main thread routine....\n", connection->thread_id)) ;
+
+
+  return thread_args ;
+}
+
+
+/* Gets called when:
+ *  1) There is an error and the thread has to exit.
+ *  2) The thread gets cancelled, can happen in any of the POSIX cancellable
+ *     system calls (e.g. read, select etc.) or from anywhere we declare as a cancellation point.
+ *
+ * This means some care is needed in handling resources to be released, we may need to set flags
+ * to remember which resources have been allocated.
+ * In particular we DO NOT free the thread_cb->connection, this is done by the GUI thread
+ * which created it.
+ */
+static void cleanUpThread(void *thread_args)
+{
+  zmapThreadCB thread_cb = (zmapThreadCB)thread_args ;
+  ZMapConnection connection = thread_cb->connection ;
+  ZMapThreadReply reply ;
+  gchar *error_msg = NULL ;
+
+  printf("in cleanup routine\n") ;
+
+  ZMAP_THR_DEBUG(("%x: in overall thread clean up routine....\n", connection->thread_id)) ;
+
+  if (thread_cb->thread_died)
+    {
+      reply = ZMAP_REPLY_DIED ;
+      if (thread_cb->initial_error)
+	error_msg =  g_strdup(thread_cb->initial_error) ;
+    }
+  else
+    reply = ZMAP_REPLY_CANCELLED ;
+
+  if (thread_cb->server)
+    {
+      if (zMapServerCloseConnection(thread_cb->server)
+	  && zMapServerFreeConnection(thread_cb->server))
+	{
+	  thread_cb->server = NULL ;
+	}
+      else
+	ZMAP_THR_DEBUG(("%x: Unable to close connection to server cleanly\n",
+			connection->thread_id)) ;
+
+      /* this should be an error message now as well as a debug message..... */
+    }
+
+
+  if (thread_cb->server_request)
+    g_string_free(thread_cb->server_request, TRUE) ;
+  if (thread_cb->server_reply)
+    g_free(thread_cb->server_reply) ;
+
+
+  g_free(thread_cb) ;
+
+
+  if (!error_msg)
+    zmapVarSetValue(&(connection->reply), reply) ;
+  else
+    zmapVarSetValueWithError(&(connection->reply), reply, error_msg) ;
+
+
+  ZMAP_THR_DEBUG(("%x: Leaving overall thread clean up routine because %s....\n",
+		  connection->thread_id,
+		  zmapVarGetReplyString(reply))) ;
+
+  return ;
+}
+
+
diff --git a/src/zmapThreads/zmapSlave.test.c b/src/zmapThreads/zmapSlave.test.c
new file mode 100755
index 0000000000000000000000000000000000000000..d8026e96d72d50572c47d3fd8e5928446f04b504
--- /dev/null
+++ b/src/zmapThreads/zmapSlave.test.c
@@ -0,0 +1,207 @@
+/*  File: zmapthrslave.c
+ *  Author: Ed Griffiths (edgrif@sanger.ac.uk)
+ *  Copyright (c) Sanger Institute, 2003
+ *-------------------------------------------------------------------
+ * ZMap is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * or see the on-line version at http://www.gnu.org/copyleft/gpl.txt
+ *-------------------------------------------------------------------
+ * This file is part of the ZMap genome database package
+ * and was written by
+ *      Rob Clack (Sanger Institute, UK) rnc@sanger.ac.uk,
+ * 	Ed Griffiths (Sanger Institute, UK) edgrif@sanger.ac.uk and
+ *	Simon Kelley (Sanger Institute, UK) srk@sanger.ac.uk
+ *
+ * Description: 
+ * Exported functions: See XXXXXXXXXXXXX.h
+ * HISTORY:
+ * Last edited: Aug  6 10:16 2003 (edgrif)
+ * Created: Thu Jul 24 14:37:26 2003 (edgrif)
+ * CVS info:   $Id: zmapSlave.test.c,v 1.1 2003-11-13 15:02:13 edgrif Exp $
+ *-------------------------------------------------------------------
+ */
+
+/* With some additional calls in the zmapConn code I could get rid of the need for
+ * the private header here...... */
+
+#include <zmapConn_P.h>
+
+
+typedef struct
+{
+  ZMapConnection connection ;
+  gboolean thread_died ;
+} zmapThreadCBstruct, *zmapThreadCB ;
+
+
+
+static void delay(void) ;				    /* testing only */
+
+static void cleanUpThread(void *thread_args) ;
+
+
+/* This is the routine that is called by the pthread_create() function, in effect
+ * this is an endless loop processing requests signalled to the thread via a
+ * condition variable. If this thread kills itself we will exit this routine
+ * normally, if the thread is cancelled however we may exit from anywhere so its
+ * important that the clean up thread registered with pthread_cleanup_push()
+ * really does clean up properly. */
+void *zmapNewThread(void *thread_args)
+{
+  zmapThreadCB thread_cb ;
+  ZMapConnection connection = (ZMapConnection)thread_args ;
+  ZMapRequest thread_state = &(connection->request) ;
+  int status ;
+  timespec_t timeout ;
+  ZMapThreadRequest signalled_state ;
+
+
+  thread_cb = g_new(zmapThreadCBstruct, sizeof(zmapThreadCBstruct)) ;
+  thread_cb->connection = connection ;
+  thread_cb->thread_died = FALSE ;
+  
+
+  pthread_cleanup_push(cleanUpThread, (void *)thread_cb) ;
+
+
+  while (1)
+    {
+      ZMAP_THR_DEBUG(("%x: about to do timed wait\n", connection->thread_id)) ;
+
+      /* this will crap over performance...asking the time all the time !! */
+      timeout.tv_sec = 5 ;				    /* n.b. interface seems to absolute time. */
+      timeout.tv_nsec = 0 ;
+      signalled_state = zmapCondVarWaitTimed(thread_state, ZMAP_REQUEST_WAIT, &timeout, TRUE) ;
+
+      ZMAP_THR_DEBUG(("%x: finished condvar wait, state = %s\n", connection->thread_id,
+		      zmapVarGetRequestString(signalled_state))) ;
+
+      if (signalled_state == ZMAP_REQUEST_TIMED_OUT)
+	{
+	  continue ;
+	}
+      else if (signalled_state == ZMAP_REQUEST_GETDATA)
+	{
+	  static int failure = 0 ;
+	  char *data = NULL ;
+
+
+	  /* simulation code only...in the final app we would call the socket here... */
+	  ZMAP_THR_DEBUG(("%x: getting data....\n", connection->thread_id)) ;
+
+	  delay() ;
+	  pthread_testcancel() ;			    /* allow cancel point.... */
+	  delay() ;
+	  pthread_testcancel() ;			    /* allow cancel point.... */
+	  delay() ;
+	  pthread_testcancel() ;			    /* allow cancel point.... */
+	  delay() ;
+	  pthread_testcancel() ;			    /* allow cancel point.... */
+
+	  ZMAP_THR_DEBUG(("%x: got all data....\n", connection->thread_id)) ;
+
+
+	  /* This snippet is for testing only, just fakes the thread failing. */
+	  failure++ ;
+	  if (!(failure % 5))
+	    {
+	      thread_cb->thread_died = TRUE ;
+
+	      /* NOTE IMPLICIT TERMINATION OF THREAD BY JUMPING OUT OF THIS LOOP
+	       * WHICH LEADS TO EXITTING FROM THIS ROUTINE. FOR OTHER ERRORS WE WIL
+	       * HAVE TO HAVE A MORE FORMAL MECHANISM.... */
+	      break ;
+	    }
+
+
+	  data = g_strdup_printf("some really wild thread data for thread %x", connection->thread_id) ;
+
+	  /* Signal that we got some data. */
+	  zmapVarSetValueWithData(&(connection->reply), ZMAP_REPLY_GOTDATA, (void *)data) ;
+
+
+	}
+      else if (signalled_state == ZMAP_REQUEST_EXIT)
+	{
+	  /* THIS DOESN'T REALLY HAPPEN AT THE MOMENT.....THINK ABOUT THIS....
+	   * We actually just do a thread cancel because it gives better control
+	   * to the GUI and perhaps that's the best way..... */
+
+	  ZMAP_THR_DEBUG(("%x: gotta exit now....\n", connection->thread_id)) ;
+	  break ;
+	}
+    }
+
+
+  /* Note that once we reach here the thread will exit, the pthread_cleanup_pop(1) ensures
+   * we call our cleanup routine before we exit.
+   * Most times we will not get here because we will be pthread_cancel'd and go straight into
+   * our clean_up routine. */
+
+  pthread_cleanup_pop(1) ;				    /* 1 => always call clean up routine */
+
+
+  ZMAP_THR_DEBUG(("%x: thread exitting from main thread routine....\n", connection->thread_id)) ;
+
+
+  return thread_args ;
+}
+
+
+/* Gets called when:
+ *  1) There is an error and the thread has to exit.
+ *  2) The thread gets cancelled, can happen in any of the POSIX cancellable
+ *     system calls (e.g. read, select etc.) or from anywhere we declare as a cancellation point.
+ *
+ * This means some care is needed in handling resources to be released, we may need to set flags
+ * to remember which resources have been allocated.
+ */
+static void cleanUpThread(void *thread_args)
+{
+  zmapThreadCB thread_cb = (zmapThreadCB)thread_args ;
+  ZMapConnection connection = thread_cb->connection ;
+  ZMapThreadReply reply ;
+
+  ZMAP_THR_DEBUG(("%x: in overall thread clean up routine....\n", connection->thread_id)) ;
+
+  if (thread_cb->thread_died)
+    reply = ZMAP_REPLY_DIED ;
+  else
+    reply = ZMAP_REPLY_CANCELLED ;
+
+  zmapVarSetValue(&(connection->reply), reply) ;
+
+  ZMAP_THR_DEBUG(("%x: Leaving overall thread clean up routine because %s....\n",
+		  connection->thread_id,
+		  zmapVarGetReplyString(reply))) ;
+
+  return ;
+}
+
+
+/* Testing only.... */
+static void delay(void)
+{
+  enum {ITERATIONS = INT_MAX/32} ;
+  int i, j ;
+
+  for (i = 0, j = 0 ; i < ITERATIONS ; i++)
+    {
+      j++ ;
+    }
+
+  return ;
+}
+
+
diff --git a/src/zmapThreads/zmapSlave_P.h b/src/zmapThreads/zmapSlave_P.h
new file mode 100755
index 0000000000000000000000000000000000000000..75e76a985bba6a68b19d850b5f358d26e6d33eb3
--- /dev/null
+++ b/src/zmapThreads/zmapSlave_P.h
@@ -0,0 +1,60 @@
+/*  File: zmapSlave_P.h
+ *  Author: Ed Griffiths (edgrif@sanger.ac.uk)
+ *  Copyright (c) Sanger Institute, 2003
+ *-------------------------------------------------------------------
+ * ZMap is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * or see the on-line version at http://www.gnu.org/copyleft/gpl.txt
+ *-------------------------------------------------------------------
+ * This file is part of the ZMap genome database package
+ * and was written by
+ * 	Ed Griffiths (Sanger Institute, UK) edgrif@sanger.ac.uk,
+ *	Simon Kelley (Sanger Institute, UK) srk@sanger.ac.uk and
+ *      Rob Clack (Sanger Institute, UK) rnc@sanger.ac.uk
+ *
+ * Description: 
+ * HISTORY:
+ * Last edited: Sep  5 17:31 2003 (edgrif)
+ * Created: Wed Aug  6 15:48:47 2003 (edgrif)
+ * CVS info:   $Id: zmapSlave_P.h,v 1.1 2003-11-13 15:02:13 edgrif Exp $
+ *-------------------------------------------------------------------
+ */
+#ifndef ZMAP_SLAVE_P_H
+#define ZMAP_SLAVE_P_H
+
+typedef struct
+{
+  ZMapConnection connection ;
+  gboolean thread_died ;
+  gchar *initial_error ;				    /* Holds string description of first
+							       serious error that caused thread
+							       termination. */
+
+  ZMapServer server ;
+  GString *server_request ;
+  gchar *server_reply ;
+
+} zmapThreadCBstruct, *zmapThreadCB ;
+
+
+
+
+/* Error messages, needs some refining. */
+#define ZMAPSLAVE_CONNCREATE "Connection creation failed"
+#define ZMAPSLAVE_CONNOPEN   "Connection open failed"
+
+
+
+
+#endif /* !ZMAP_SLAVE_P_H */
diff --git a/src/zmapUtils/README b/src/zmapUtils/README
new file mode 100755
index 0000000000000000000000000000000000000000..a122f19341890c770dca5c3ff23f62664c749fb4
--- /dev/null
+++ b/src/zmapUtils/README
@@ -0,0 +1,4 @@
+================================================================================   
+utilities
+
+general utility code, GUI or otherwise.
diff --git a/src/zmapUtils/makefile b/src/zmapUtils/makefile
new file mode 100755
index 0000000000000000000000000000000000000000..129a95183a246423a507e2244c4c0a114b632277
--- /dev/null
+++ b/src/zmapUtils/makefile
@@ -0,0 +1,26 @@
+#
+# Makes the manager part of the ZMap application.
+#
+
+
+# local macros
+UTILS_SRC = zmapGUIutils.c
+UTILS_OBJ = zmapGUIutils.o
+
+# the main routines will need some different treatment maybe...???? try putting
+# them all together, don't know if it will work.....
+
+#
+# These must all be set for the common includes to work.
+#
+CURRENT_LIB = $(ZMAP_LIB)
+CURRENT_OBJ = $(UTILS_OBJ)
+CURRENT_DEP = 
+CURRENT_SRC = $(UTILS_SRC)
+
+#
+# point to common make include file which contains all the rules etc.
+#
+ROOT_DIRECTORY = ..
+MAKE_DIR = $(ROOT_DIRECTORY)/zmapMake
+include $(MAKE_DIR)/build.make
diff --git a/src/zmapUtils/zmapGUIutils.c b/src/zmapUtils/zmapGUIutils.c
new file mode 100755
index 0000000000000000000000000000000000000000..9d1112d68087830487395c453da78810ff1e8042
--- /dev/null
+++ b/src/zmapUtils/zmapGUIutils.c
@@ -0,0 +1,110 @@
+/*  File: zmapGUIutils.c
+ *  Author: Ed Griffiths (edgrif@sanger.ac.uk)
+ *  Copyright (c) Sanger Institute, 2003
+ *-------------------------------------------------------------------
+ * ZMap is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * or see the on-line version at http://www.gnu.org/copyleft/gpl.txt
+ *-------------------------------------------------------------------
+ * This file is part of the ZMap genome database package
+ * and was written by
+ *      Rob Clack (Sanger Institute, UK) rnc@sanger.ac.uk,
+ * 	Ed Griffiths (Sanger Institute, UK) edgrif@sanger.ac.uk and
+ *	Simon Kelley (Sanger Institute, UK) srk@sanger.ac.uk
+ *
+ * Description: 
+ * Exported functions: See XXXXXXXXXXXXX.h
+ * HISTORY:
+ * Last edited: Sep  9 15:15 2003 (edgrif)
+ * Created: Thu Jul 24 14:37:35 2003 (edgrif)
+ * CVS info:   $Id: zmapGUIutils.c,v 1.1 2003-11-13 15:03:08 edgrif Exp $
+ *-------------------------------------------------------------------
+ */
+
+#include <gtk/gtk.h>
+
+
+typedef struct
+{
+  GtkWidget *dialog ;
+  GtkWidget *button ;
+} zmapDialogCBStruct, *zmapDialogCB ;
+
+
+
+
+static void clickButton(GtkWidget *widget, zmapDialogCB cb_data) ;
+
+
+void zmapGUIShowMsg(char *msg)
+{
+  GtkWidget *dialog, *label, *button;
+  zmapDialogCBStruct cb_data ;
+
+
+  dialog = gtk_dialog_new();
+
+
+#ifdef ED_G_NEVER_INCLUDE_THIS_CODE
+  gtk_window_set_policy( GTK_WINDOW( dialog ), FALSE, FALSE, FALSE );
+#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */
+
+
+  gtk_window_set_title( GTK_WINDOW( dialog ), "ZMAP - Error !" );
+
+  gtk_container_set_border_width( GTK_CONTAINER(dialog), 5 );
+
+  label = gtk_label_new(msg) ;
+
+  gtk_label_set_justify( GTK_LABEL(label), GTK_JUSTIFY_CENTER );
+  gtk_label_set_line_wrap( GTK_LABEL(label), TRUE );
+
+  gtk_box_pack_start(GTK_BOX(GTK_DIALOG(dialog)->vbox), label, TRUE, TRUE, 20);
+
+  button = gtk_button_new_with_label ("OK");
+  GTK_WIDGET_SET_FLAGS (button, GTK_CAN_DEFAULT);
+  gtk_box_pack_start (GTK_BOX (GTK_DIALOG (dialog)->action_area),
+		      button, FALSE, FALSE, 0);
+  gtk_widget_grab_default (button);
+  gtk_signal_connect(GTK_OBJECT(button), "clicked", GTK_SIGNAL_FUNC(clickButton), &cb_data) ;
+
+  cb_data.dialog = dialog ;
+  cb_data.button = button ;
+
+  gtk_widget_show_all( dialog );
+
+  /* This is supposed to block interaction with the rest of the application...it doesn't. */
+  gtk_grab_add(button) ;
+
+
+  /* note this call will block until user clicks....not good we need to choose when to be modal
+   * or not.... */
+  gtk_main();
+
+
+  return ;
+}
+
+
+static void clickButton(GtkWidget *widget, zmapDialogCB cb_data)
+{
+
+  gtk_grab_remove(cb_data->button) ;
+
+  gtk_widget_destroy(cb_data->dialog) ;
+
+  gtk_main_quit() ;
+
+  return ;
+}
diff --git a/src/zmapWindow/README b/src/zmapWindow/README
new file mode 100755
index 0000000000000000000000000000000000000000..c44fe4c3dde143fae558c9d7113137761e65aa3b
--- /dev/null
+++ b/src/zmapWindow/README
@@ -0,0 +1,4 @@
+================================================================================   
+The ZMap window
+
+The code that creates a ZMap window and associated gubbins (threads etc.).
diff --git a/src/zmapWindow/zmapWindow.c b/src/zmapWindow/zmapWindow.c
new file mode 100755
index 0000000000000000000000000000000000000000..63287789f9284bae2f0c49cd7340465ac1b20a51
--- /dev/null
+++ b/src/zmapWindow/zmapWindow.c
@@ -0,0 +1,210 @@
+/*  File: zmapWindow.c
+ *  Author: Ed Griffiths (edgrif@sanger.ac.uk)
+ *  Copyright (c) Sanger Institute, 2003
+ *-------------------------------------------------------------------
+ * ZMap is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * or see the on-line version at http://www.gnu.org/copyleft/gpl.txt
+ *-------------------------------------------------------------------
+ * This file is part of the ZMap genome database package
+ * and was written by
+ *      Rob Clack (Sanger Institute, UK) rnc@sanger.ac.uk,
+ * 	Ed Griffiths (Sanger Institute, UK) edgrif@sanger.ac.uk and
+ *	Simon Kelley (Sanger Institute, UK) srk@sanger.ac.uk
+ *
+ * Description: 
+ * Exported functions: See XXXXXXXXXXXXX.h
+ * HISTORY:
+ * Last edited: Aug  7 14:48 2003 (edgrif)
+ * Created: Thu Jul 24 14:36:27 2003 (edgrif)
+ * CVS info:   $Id: zmapWindow.c,v 1.1 2003-11-13 15:06:17 edgrif Exp $
+ *-------------------------------------------------------------------
+ */
+
+#include <string.h>
+#include <zmapWindow_P.h>
+
+
+static void quitCB(GtkWidget *widget, gpointer cb_data) ;
+static void dataEventCB(GtkWidget *widget, GdkEventClient *event, gpointer data) ;
+
+
+
+ZMapWindow zMapWindowCreate(char *machine, int port, char *sequence, 
+			    zmapVoidIntCallbackFunc manager_routine, void *manager_data)
+{
+  ZMapWindow window ;
+  GtkWidget *toplevel, *vbox, *menubar, *button_frame, *connect_frame ;
+  char *title ;
+
+  window = g_new(ZMapWindowStruct, sizeof(ZMapWindowStruct)) ;
+
+  window->machine = g_strdup(machine) ;
+  window->port = port ;
+  window->sequence = g_strdup(sequence) ;
+  window->manager_routine = manager_routine ;
+  window->manager_data = manager_data ;
+  window->zmap_atom = gdk_atom_intern(ZMAP_ATOM, FALSE) ;
+
+  title = g_strdup_printf("ZMap (%s, port %d): %s", machine, port,
+			  sequence ? sequence : "") ;
+
+  window->toplevel = toplevel = gtk_window_new(GTK_WINDOW_TOPLEVEL) ;
+  gtk_window_set_policy(GTK_WINDOW(toplevel), FALSE, TRUE, FALSE ) ;
+  gtk_window_set_title(GTK_WINDOW(toplevel), title) ;
+  gtk_container_border_width(GTK_CONTAINER(toplevel), 5) ;
+  gtk_signal_connect(GTK_OBJECT(toplevel), "destroy", 
+		     GTK_SIGNAL_FUNC(quitCB), (gpointer)window) ;
+  gtk_signal_connect(GTK_OBJECT(toplevel), "client_event", 
+		     GTK_SIGNAL_FUNC(dataEventCB), (gpointer)window) ;
+
+  vbox = gtk_vbox_new(FALSE, 0) ;
+  gtk_container_add(GTK_CONTAINER(toplevel), vbox) ;
+
+  menubar = zmapWindowMakeMenuBar(window) ;
+  gtk_box_pack_start(GTK_BOX(vbox), menubar, FALSE, TRUE, 0);
+
+  button_frame = zmapWindowMakeButtons(window) ;
+  gtk_box_pack_start(GTK_BOX(vbox), button_frame, FALSE, TRUE, 0);
+
+  connect_frame = zmapWindowMakeFrame(window) ;
+  gtk_box_pack_start(GTK_BOX(vbox), connect_frame, TRUE, TRUE, 0);
+
+  gtk_widget_show_all(toplevel) ;
+
+
+  g_free(title) ;
+
+
+  return(window) ;
+}
+
+
+
+/* This routine is called by the code that manages the slave threads, it makes
+ * the call to tell the GUI code that there is something to do. This routine
+ * then sends this event to alert the GUI that it needs to do some work and
+ * will supply the data via the event struct. */
+void zMapWindowSignalData(ZMapWindow window, void *data)
+{
+  GdkEventClient event ;
+  GdkAtom zmap_atom ;
+  gint ret_val = 0 ;
+  zmapWindowData window_data ;
+
+  /* Set up struct to be passed to our callback. */
+  window_data = g_new(zmapWindowDataStruct, sizeof(zmapWindowDataStruct)) ;
+  window_data->window = window ;
+  window_data->data = data ;
+
+  event.type = GDK_CLIENT_EVENT ;
+  event.window = NULL ;					    /* no window generates this event. */
+  event.send_event = TRUE ;				    /* we sent this event. */
+  event.message_type = window->zmap_atom ;		    /* This is our id for events. */
+  event.data_format = 8 ;				    /* Not sure about data format here... */
+
+  /* Load the pointer value, not what the pointer points to.... */
+  {
+    void **dummy ;
+
+    dummy = (void *)&window_data ;
+    memmove(&(event.data.b[0]), dummy, sizeof(void *)) ;
+  }
+
+  gtk_signal_emit_by_name(GTK_OBJECT(window->toplevel), "client_event",
+			  &event, &ret_val) ;
+
+  return ;
+}
+
+
+
+void zMapWindowDestroy(ZMapWindow window)
+{
+  ZMAP_DEBUG(("GUI: in window destroy...\n")) ;
+
+  /* We must disconnect the "destroy" callback otherwise we will enter quitCB()
+   * below and that will try to call our callers destroy routine which has already
+   * called this routine...i.e. a circularity which results in attempts to
+   * destroy already destroyed windows etc. */
+  gtk_signal_disconnect_by_data(GTK_OBJECT(window->toplevel), (gpointer)window) ;
+
+  gtk_widget_destroy(window->toplevel) ;
+
+  g_free(window->machine) ;
+  g_free(window->sequence) ;
+
+  g_free(window) ;
+
+  return ;
+}
+
+
+
+/*
+ *  ------------------- Internal functions -------------------
+ */
+
+
+static void quitCB(GtkWidget *widget, gpointer cb_data)
+{
+  ZMapWindow window = (ZMapWindow)cb_data ;
+
+  (*(window->manager_routine))(window->manager_data, ZMAP_WINDOW_QUIT) ;
+
+  return ;
+}
+
+
+
+/* Called when gtk detects the event sent by signalDataToGUI(), in the end this
+ * routine will call zmap routines to display data etc. */
+static void dataEventCB(GtkWidget *widget, GdkEventClient *event, gpointer cb_data)
+{
+  ZMapWindow window = (ZMapWindow)cb_data ;
+
+  if (event->type != GDK_CLIENT_EVENT)
+    ZMAPERR("dataEventCB() received non-GdkEventClient event") ;
+  
+  if (event->send_event == TRUE && event->message_type == gdk_atom_intern(ZMAP_ATOM, TRUE))
+    {
+      zmapWindowData window_data = NULL ;
+      ZMapWindow window = NULL ;
+      char *string = NULL ;
+
+      /* Retrieve the data pointer from the event struct */
+      memmove(&window_data, &(event->data.b[0]), sizeof(void *)) ;
+
+      window = window_data->window ;
+      string = (char *)(window_data->data) ;
+
+
+#ifdef ED_G_NEVER_INCLUDE_THIS_CODE
+      ZMAP_DEBUG(("GUI: got dataEvent, contents: \"%s\"\n", string)) ;
+#endif /* ED_G_NEVER_INCLUDE_THIS_CODE */
+
+
+      gtk_text_insert(GTK_TEXT(window->text), NULL, NULL, NULL, string, strlen(string)) ;
+
+      g_free(string) ;
+      g_free(window_data) ;
+    }
+  else
+    {
+      ZMAP_DEBUG(("unknown client event in zmapevent handler\n")) ;
+    }
+
+
+  return ;
+}
diff --git a/src/zmapWindow/zmapWindow_P.h b/src/zmapWindow/zmapWindow_P.h
new file mode 100755
index 0000000000000000000000000000000000000000..313661d76c33463725c026b29bc6f0f1253bdeee
--- /dev/null
+++ b/src/zmapWindow/zmapWindow_P.h
@@ -0,0 +1,77 @@
+/*  File: zmapWindow_P.h
+ *  Author: Ed Griffiths (edgrif@sanger.ac.uk)
+ *  Copyright (c) Sanger Institute, 2003
+ *-------------------------------------------------------------------
+ * ZMap is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
+ * or see the on-line version at http://www.gnu.org/copyleft/gpl.txt
+ *-------------------------------------------------------------------
+ * This file is part of the ZMap genome database package
+ * and was written by
+ *      Rob Clack (Sanger Institute, UK) rnc@sanger.ac.uk,
+ * 	Ed Griffiths (Sanger Institute, UK) edgrif@sanger.ac.uk and
+ *	Simon Kelley (Sanger Institute, UK) srk@sanger.ac.uk
+ *
+ * Description: 
+ * Exported functions: See XXXXXXXXXXXXX.h
+ * HISTORY:
+ * Last edited: Nov 13 10:26 2003 (edgrif)
+ * Created: Fri Aug  1 16:45:58 2003 (edgrif)
+ * CVS info:   $Id: zmapWindow_P.h,v 1.1 2003-11-13 15:06:17 edgrif Exp $
+ *-------------------------------------------------------------------
+ */
+#ifndef ZMAP_WINDOW_P_H
+#define ZMAP_WINDOW_P_H
+
+#include <gtk/gtk.h>
+#include <ZMap/zmapWindow.h>
+
+typedef struct _ZMapWindowStruct
+{
+  gchar *machine ;
+  int port ;
+  gchar *sequence ;
+
+  GtkWidget *toplevel ;
+  GtkWidget *text ;
+
+  GdkAtom zmap_atom ;
+
+  zmapVoidIntCallbackFunc manager_routine ;
+  void *manager_data ;
+
+} ZMapWindowStruct ;
+
+
+typedef struct
+{
+  ZMapWindow window ;
+  void *data ;						    /* void for now, union later ?? */
+} zmapWindowDataStruct, *zmapWindowData ;
+
+
+
+
+
+/* Used in our event communication.... */
+#define ZMAP_ATOM  "ZMap_Atom"
+
+
+GtkWidget *zmapWindowMakeMenuBar(ZMapWindow window) ;
+GtkWidget *zmapWindowMakeButtons(ZMapWindow window) ;
+GtkWidget *zmapWindowMakeFrame(ZMapWindow window) ;
+
+
+
+#endif /* !ZMAP_WINDOW_P_H */