Index: src/System/Link/connection.cpp
===================================================================
--- src/System/Link/connection.cpp	(révision 2724)
+++ src/System/Link/connection.cpp	(copie de travail)
@@ -48,6 +48,7 @@
   void   read (int channel);
   void   stop ();
   void   interrupt ();
+  void   listen ();
 };
 RESOURCE_CODE(connection);
 
@@ -55,6 +56,13 @@
 * Routines for connections
 ******************************************************************************/
 
+static void 
+listen_callback (void *obj, void* info) {
+  //cout << "connection callback" << LF;
+  ((connection_rep*) obj)->listen ();
+}
+
+
 connection_rep::connection_rep (string name2, string session2, tm_link ln2):
   rep<connection> (name2 * "-" * session2),
   name (name2), session (session2), ln (ln2),
@@ -80,6 +88,9 @@
   }
   tm_in ->bof ();
   tm_err->bof ();
+  
+  ln->set_command (generic_command (listen_callback, this));
+  
   return message;
 }
 
@@ -167,25 +178,30 @@
   while (it->busy()) {
     string name= it->next ();
     connection con (name);
-    connection_notify_status (con);
-    if (con->status != CONNECTION_DEAD) {
-      con->read (LINK_ERR);
-      connection_notify (con, "error", con->tm_err->get ("error"));
-      con->read (LINK_OUT);
-      connection_notify (con, "output", con->tm_in->get ("output"));
-      connection_notify (con, "prompt", con->tm_in->get ("prompt"));
-      connection_notify (con, "input", con->tm_in->get ("input"));
-      tree t= connection_handlers (con->name);
-      int i, n= N(t);
-      for (i=0; i<n; i++) {
-	tree doc= con->tm_in->get (t[i][0]->label);
-	if (doc != "") call (t[i][1]->label, doc);
-	doc= con->tm_err->get (t[i][0]->label);
-	if (doc != "") call (t[i][1]->label, doc);
-      }
+    con->listen ();
+   }
+}
+
+void
+connection_rep::listen () {
+  connection_notify_status (this);
+  if (status != CONNECTION_DEAD) {
+    read (LINK_ERR);
+    connection_notify (this, "error", tm_err->get ("error"));
+    read (LINK_OUT);
+    connection_notify (this, "output", tm_in->get ("output"));
+    connection_notify (this, "prompt", tm_in->get ("prompt"));
+    connection_notify (this, "input", tm_in->get ("input"));
+    tree t= connection_handlers (name);
+    int i, n= N(t);
+    for (i=0; i<n; i++) {
+      tree doc= tm_in->get (t[i][0]->label);
+      if (doc != "") call (t[i][1]->label, doc);
+      doc= tm_err->get (t[i][0]->label);
+      if (doc != "") call (t[i][1]->label, doc);
     }
-    connection_notify_status (con);
   }
+  connection_notify_status (this);  
 }
 
 /******************************************************************************
Index: src/System/Link/tm_link.hpp
===================================================================
--- src/System/Link/tm_link.hpp	(révision 2724)
+++ src/System/Link/tm_link.hpp	(copie de travail)
@@ -12,7 +12,9 @@
 #ifndef TM_LINK_H
 #define TM_LINK_H
 #include "tree.hpp"
+#include "command.hpp"
 
+
 #define CONNECTION_DEAD    0
 #define CONNECTION_DYING   1
 #define WAITING_FOR_INPUT  2
@@ -39,6 +41,8 @@
   bool   alive;   // link is alive
   string secret;  // empty string or secret key for encrypted connections
 
+  command feed_cmd; // called when async data available
+  
 public:
   inline tm_link_rep () {}
   inline virtual ~tm_link_rep () {}
@@ -57,6 +61,9 @@
   void secure_server (string cmd);
   void secure_client ();
 
+  void set_command (command _cmd) { feed_cmd = _cmd; }
+  
+  
   friend class tm_link;
 };
 
Index: src/System/Link/socket_link.cpp
===================================================================
--- src/System/Link/socket_link.cpp	(révision 2724)
+++ src/System/Link/socket_link.cpp	(copie de travail)
@@ -34,6 +34,13 @@
 
 hashset<pointer> socket_link_set;
 
+
+static void
+sn_callback (void *obj, void* info) {
+  socket_link_rep* con= (socket_link_rep*) obj;
+  if (con->alive) con->feed (LINK_OUT);
+}
+
 /******************************************************************************
 * Constructors and destructors for socket_links
 ******************************************************************************/
@@ -125,6 +132,9 @@
 #endif
     return "Error: non working connection to '" * where * "'";
   alive= true;
+
+  sn = socket_notifier (io, &sn_callback, this, NULL);
+  
   return "ok";
 #else
   return "Error: sockets not implemented";
@@ -194,6 +204,8 @@
     if (DEBUG_IO) cout << debug_io_string (string (tempout, r));
     outbuf << string (tempout, r);
   }
+
+  if (!is_nil(feed_cmd)) (feed_cmd)->apply();
 #endif
 }
 
@@ -242,6 +254,7 @@
   close (io);
   io= -1;
   alive= false;
+  sn = socket_notifier ();
   wait (NULL);
 #endif
 }
Index: src/System/Link/pipe_link.cpp
===================================================================
--- src/System/Link/pipe_link.cpp	(révision 2724)
+++ src/System/Link/pipe_link.cpp	(copie de travail)
@@ -31,6 +31,19 @@
 
 hashset<pointer> pipe_link_set;
 
+
+static void
+sn_callback_out (void *obj, void *info) {
+  pipe_link_rep* con= (pipe_link_rep*) obj;
+  if (con->alive) con->feed (LINK_OUT);
+}
+
+static void
+sn_callback_err (void *obj, void *info) {
+  pipe_link_rep* con= (pipe_link_rep*) obj;
+  if (con->alive) con->feed (LINK_ERR);
+}
+
 /******************************************************************************
 * Constructors and destructors for pipe_links
 ******************************************************************************/
@@ -124,6 +137,10 @@
 #endif
 
     alive= true;
+    
+    snout = socket_notifier (out, &sn_callback_out, this, NULL);
+    snerr = socket_notifier (err, &sn_callback_err, this, NULL);
+        
     if (/* !banner */ true) return "ok";
     else {
       int r;
@@ -214,6 +231,9 @@
     }
 #endif
     alive= false;
+    snout = socket_notifier ();
+    snerr = socket_notifier ();
+
   }
   else {
     if (DEBUG_IO) cout << debug_io_string (string (tempout, r));
@@ -221,6 +241,8 @@
     else errbuf << string (tempout, r);
   }
 #endif
+
+  if (!is_nil(feed_cmd)) feed_cmd->apply(); // call the data processor
 }
 
 string&
@@ -280,11 +302,16 @@
     killpg(pid,SIGKILL);
   }
   alive= false;
+  
+  
   close (in);
 #endif
   alive= false;
   wait (NULL);
 #endif
+
+  snout = socket_notifier ();
+  snerr = socket_notifier ();
 }
 
 /******************************************************************************
Index: src/System/Link/socket_link.hpp
===================================================================
--- src/System/Link/socket_link.hpp	(révision 2724)
+++ src/System/Link/socket_link.hpp	(copie de travail)
@@ -12,6 +12,7 @@
 #ifndef SOCKET_LINK_H
 #define SOCKET_LINK_H
 #include "tm_link.hpp"
+#include "socket_notifier.hpp"
 
 /******************************************************************************
 * The socket_link class
@@ -24,6 +25,8 @@
   int    io;            // file descriptor for data going to the child
   string outbuf;        // pending output from plugin
 
+  socket_notifier sn;
+  
 public:
   socket_link_rep (string host, int port, int type, int fd);
   ~socket_link_rep ();
Index: src/System/Link/socket_server.cpp
===================================================================
--- src/System/Link/socket_server.cpp	(révision 2724)
+++ src/System/Link/socket_server.cpp	(copie de travail)
@@ -23,14 +23,21 @@
 #include <sys/wait.h>
 #endif
 
+
 hashset<pointer> socket_server_set;
 
+
+static void 
+sn_callback(void *obj, void *info) {
+  ((socket_server_rep*) obj)->start ();
+}
+
 /******************************************************************************
 * Constructors and destructors for socket_servers
 ******************************************************************************/
 
 socket_server_rep::socket_server_rep (int port2):
-  port (port2)
+ port (port2), sn ()
 {
   socket_server_set->insert ((pointer) this);
   server= -1;
@@ -84,6 +91,9 @@
     return "Error: call to 'listen' failed";
 
   alive= true;
+  
+  sn = socket_notifier (server, &sn_callback, this, NULL);
+  
   return "ok";
 #else
   return "Error: sockets not implemented";
@@ -107,6 +117,8 @@
     incoming= update;
     incoming << make_socket_link (addr, -1, SOCKET_SERVER, client);
   }
+  
+  if (!is_nil(feed_cmd)) feed_cmd->apply(); // call the data processor
 #endif
 }
 
@@ -142,6 +154,9 @@
   if (!alive) return;
   incoming= array<tm_link> ();
   alive= false;
+  
+  sn = socket_notifier ();
+
   close (server);
   wait (NULL);
 #endif
Index: src/System/Link/pipe_link.hpp
===================================================================
--- src/System/Link/pipe_link.hpp	(révision 2724)
+++ src/System/Link/pipe_link.hpp	(copie de travail)
@@ -12,6 +12,7 @@
 #ifndef PIPE_LINK_H
 #define PIPE_LINK_H
 #include "tm_link.hpp"
+#include "socket_notifier.hpp"
 
 #ifdef OS_WIN32
 #include <sys/pipe.h>
@@ -50,6 +51,8 @@
   string outbuf;        // pending output from plugin
   string errbuf;        // pending errors from plugin
 
+  socket_notifier snout, snerr;
+  
 public:
   pipe_link_rep (string cmd);
   ~pipe_link_rep ();
Index: src/System/Link/socket_server.hpp
===================================================================
--- src/System/Link/socket_server.hpp	(révision 2724)
+++ src/System/Link/socket_server.hpp	(copie de travail)
@@ -12,6 +12,7 @@
 #ifndef SOCKET_SERVER_H
 #define SOCKET_SERVER_H
 #include "tm_link.hpp"
+#include "socket_notifier.hpp"
 
 /******************************************************************************
 * The socket_server class
@@ -22,6 +23,8 @@
   int server;               // listening socket descriptor
   array<tm_link> incoming;  // list of clients
 
+  socket_notifier sn;
+  
 public:
   socket_server_rep (int port);
   ~socket_server_rep ();
Index: src/System/Link/socket_notifier.cpp
===================================================================
--- src/System/Link/socket_notifier.cpp	(révision 0)
+++ src/System/Link/socket_notifier.cpp	(révision 0)
@@ -0,0 +1,86 @@
+
+/******************************************************************************
+* MODULE     : socket_notifier.cpp
+* DESCRIPTION: Notifiers for socket activity
+* COPYRIGHT  : (C) 2009 Massimiliano Gubinelli
+*******************************************************************************
+* This software falls under the GNU general public license version 3 or later.
+* It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
+* in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
+******************************************************************************/
+
+#ifndef __MINGW32__
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/wait.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netdb.h>
+#endif
+#include <errno.h>
+#ifdef OS_WIN32
+#include <sys/misc.h>
+#endif
+
+#include "socket_notifier.hpp"
+#include "list.hpp"
+#include "iterator.hpp"
+
+class generic_command_rep: public command_rep {
+  void (*callback) (void*, void*); // callback
+  void *obj; // argument for callback
+  void *info; // additional info
+  
+public:
+  generic_command_rep (void (*_callback) (void*, void*), void *_obj, void *_info) 
+  : callback (_callback), obj (_obj), info (_info) {}
+  void apply () { if (callback) callback (obj, info); }
+  ostream& print (ostream& out) { return out << "generic_command_rep"; }
+};
+
+command
+generic_command (void (*_callback) (void*, void*), void *_obj, void *_info) {
+  return tm_new<generic_command_rep> (_callback, _obj, _info);
+}
+
+
+
+
+
+hashset<pointer> socket_notifier_rep::notifiers;
+
+void 
+perform_select () {
+#ifndef __MINGW32__
+ // cout << "**********************************************" << LF;
+ // cout << "perform_select cycle" << LF;
+  while (true) {
+    fd_set rfds;
+    FD_ZERO (&rfds);
+    int max_fd= 0;
+    iterator<pointer> it = iterate (socket_notifier_rep::notifiers);
+    while (it->busy ()) {
+      socket_notifier_rep *sn= (socket_notifier_rep *) it->next ();
+      FD_SET (sn->fd, &rfds);
+      //cout << sn->fd << LF;
+      if (sn->fd >= max_fd) max_fd= sn->fd+1;
+    }
+    if (max_fd == 0) break;
+    
+    struct timeval tv;
+    tv.tv_sec  = 0;
+    tv.tv_usec = 0;
+    int nr = select (max_fd, &rfds, NULL, NULL, &tv);
+    if (nr==0) break;
+    
+    it = iterate (socket_notifier_rep::notifiers);
+    while (it->busy ()) {
+      socket_notifier_rep *sn= (socket_notifier_rep *) it->next ();
+      if (FD_ISSET (sn->fd, &rfds)) sn->notify ();
+    }
+  }
+#endif  
+}
+
+
Index: src/System/Link/socket_notifier.hpp
===================================================================
--- src/System/Link/socket_notifier.hpp	(révision 0)
+++ src/System/Link/socket_notifier.hpp	(révision 0)
@@ -0,0 +1,59 @@
+
+/******************************************************************************
+* MODULE     : socket_notifier.hpp
+* DESCRIPTION: Notifiers for socket activity
+* COPYRIGHT  : (C) 2009 Massimiliano Gubinelli
+*******************************************************************************
+* This software falls under the GNU general public license version 3 or later.
+* It comes WITHOUT ANY WARRANTY WHATSOEVER. For details, see the file LICENSE
+* in the root directory or <http://www.gnu.org/licenses/gpl-3.0.html>.
+******************************************************************************/
+
+#ifndef SOCKET_NOTIFIER_H
+#define SOCKET_NOTIFIER_H
+
+#include "basic.hpp"
+#include "hashset.hpp"
+#include "command.hpp"
+
+
+
+command generic_command (void (*_callback) (void*, void*), void *_obj, void *_info = NULL);
+
+struct socket_notifier_rep : concrete_struct {
+
+  int fd; // file descriptor for the socket
+  command cmd;
+  
+  static hashset<pointer> notifiers;
+  
+public:
+  socket_notifier_rep (int _fd, command _cmd)
+    : fd(_fd), cmd(_cmd) {
+    //cout << "add notifier" << LF;
+    notifiers -> insert (this);
+  } 
+  ~socket_notifier_rep () {
+    //cout << "remove notifier" << LF;
+    notifiers -> remove (this);
+  }
+  void notify () { if (!is_nil(cmd)) cmd->apply (); } 
+
+  friend void perform_select ();
+};
+
+
+class socket_notifier {
+  CONCRETE_NULL(socket_notifier);
+  inline socket_notifier (int _fd, void (*_callback) (void*, void*), void *_obj, void *_info = NULL) 
+    : rep (tm_new<socket_notifier_rep> (_fd, generic_command (_callback, _obj, _info))) {}
+  friend bool operator==(socket_notifier sn1, socket_notifier sn2) {
+    return (sn1.rep == sn2.rep);
+  }
+};
+
+CONCRETE_NULL_CODE(socket_notifier);
+
+void perform_select ();
+
+#endif // SOCKET_NOTIFIER_H
Index: src/Texmacs/Server/tm_server.cpp
===================================================================
--- src/Texmacs/Server/tm_server.cpp	(révision 2724)
+++ src/Texmacs/Server/tm_server.cpp	(copie de travail)
@@ -19,6 +19,7 @@
 #include "socket_link.hpp"
 #include "socket_server.hpp"
 #include "dictionary.hpp"
+#include "socket_notifier.hpp"
 
 server* the_server= NULL;
 bool texmacs_started= false;
@@ -291,10 +292,14 @@
 
 void
 tm_server_rep::interpose_handler () {
+#if 0
   listen_to_servers ();
   listen_to_pipes ();
   listen_to_sockets ();
   listen_to_connections ();
+#else
+  perform_select ();
+#endif
   exec_pending_commands ();
 
   int i,j;
Index: src/Guile/Scheme/object.cpp
===================================================================
--- src/Guile/Scheme/object.cpp	(révision 2724)
+++ src/Guile/Scheme/object.cpp	(copie de travail)
@@ -396,3 +396,8 @@
       delayed_queue << a[i];
   }
 }
+
+bool
+has_pending_commands () {
+  return (N(delayed_queue) > 0);
+}
Index: src/Guile/Scheme/object.hpp
===================================================================
--- src/Guile/Scheme/object.hpp	(révision 2724)
+++ src/Guile/Scheme/object.hpp	(copie de travail)
@@ -147,6 +147,7 @@
 void   eval_delayed (object expr);
 void   exec_delayed (object cmd);
 void   exec_pending_commands ();
+bool   has_pending_commands ();
 
 object call (const char* fun);
 object call (const char* fun, object a1);
Index: misc/admin/admin.makefile
===================================================================
--- misc/admin/admin.makefile	(révision 2724)
+++ misc/admin/admin.makefile	(copie de travail)
@@ -19,8 +19,8 @@
 tmdir = TeXmacs
 tmtgz = TeXmacs-1.0.7.2
 tmrpm = TeXmacs-1.0.7.2-1
-tmorig = /Users/vdhoeven/texmacs/src
-tmsrc = /Users/vdhoeven/texmacs/src/TeXmacs
+tmorig = /Users/mgubi/t/exp-notify
+tmsrc = /Users/mgubi/t/exp-notify/TeXmacs
 tmbin = ${exec_prefix}/libexec/TeXmacs
 tmdata = ${datarootdir}/TeXmacs
 so = dylib
