Allow YAZ 2 series only
[ir-tcl-moved-to-github.git] / select.c
index 93f2012..d9baf65 100644 (file)
--- a/select.c
+++ b/select.c
@@ -1,50 +1,58 @@
 /*
  * IR toolkit for tcl/tk
- * (c) Index Data 1996
+ * (c) Index Data 1996-1999
  * See the file LICENSE for details.
  * Sebastian Hammer, Adam Dickmeiss
  *
  * $Log: select.c,v $
- * Revision 1.1  1996-08-20 09:33:23  adam
+ * Revision 1.7  1999-11-30 14:05:58  adam
+ * Updated for new location of YAZ headers.
+ *
+ * Revision 1.6  1999/02/11 11:30:13  adam
+ * Updated for WIN32.
+ *
+ * Revision 1.5  1997/09/09 10:19:55  adam
+ * New MSV5.0 port with fewer warnings.
+ *
+ * Revision 1.4  1997/08/28 20:20:48  adam
+ * Added support for Tk8.0/Tcl8.0. Since Tcl_File handlers are gone
+ * we've moved to Tcl_Channel handlers instead.
+ *
+ * Revision 1.3  1997/04/13 18:57:28  adam
+ * Better error reporting and aligned with Tcl/Tk style.
+ * Rework of notifier code with Tcl_File handles.
+ *
+ * Revision 1.2  1996/09/13 10:51:48  adam
+ * Bug fix: ir_tcl_select_set called Tcl_GetFile at disconnect.
+ *
+ * Revision 1.1  1996/08/20  09:33:23  adam
  * Tcl7.5 Generic file handling.
  *
  */
 
 #include <tcl.h>
-#include <log.h>
+#include <yaz/log.h>
 #include "ir-tcl.h"
 
-#if TCL_MAJOR_VERSION > 7 || (TCL_MAJOR_VERSION == 7 && TCL_MINOR_VERSION > 4)
-
-#define IRTCL_USE_TIMER 0
-
+#if TCL_MAJOR_VERSION == 8
 struct sel_proc {
     void (*f)(ClientData clientData, int r, int w, int e);
     ClientData clientData;
     int fd;
-#if IRTCL_USE_TIMER
-    int mask;
-    Tcl_TimerToken timer_token;
-#else
-    Tcl_File tcl_File;
-#endif
+    Tcl_Channel tcl_Channel;
     struct sel_proc *next;
 };
 
 static struct sel_proc *sel_proc_list = NULL;
 
-#if IRTCL_USE_TIMER
-static void ir_tcl_timer_proc (ClientData clientData)
+static void ir_tcl_tk_select_proc (ClientData clientData, int mask)
 {
     struct sel_proc *sp = (struct sel_proc *) clientData;
 
     if (!sp->f)
         return ;
-    sp->timer_token =
-        Tcl_CreateTimerHandler (250, ir_tcl_timer_proc, clientData);
-    (*sp->f)(sp->clientData, sp->mask & TCL_READABLE, sp->mask & TCL_WRITABLE,
-             sp->mask & TCL_EXCEPTION);
-    
+    (*sp->f)(sp->clientData, mask & TCL_READABLE, mask & TCL_WRITABLE,
+             mask & TCL_EXCEPTION);
 }
 
 void ir_tcl_select_set (void (*f)(ClientData clientData, int r, int w, int e),
@@ -62,30 +70,49 @@ void ir_tcl_select_set (void (*f)(ClientData clientData, int r, int w, int e),
     while (*sp)
     {
         if ((*sp)->fd == fd)
-            break;
+             break;
         sp = &(*sp)->next;
     }
+    logf (LOG_DEBUG, "r=%d w=%d e=%d sp=%p", r, w, e, *sp);
+    if (*sp)
+        Tcl_DeleteChannelHandler ((*sp)->tcl_Channel, ir_tcl_tk_select_proc,
+                                  (*sp)->clientData);
+    if (!f)
+    {
+        if (*sp)
+        {
+            Tcl_Close (NULL, (*sp)->tcl_Channel);
+            *sp = (*sp)->next;
+        }
+        return ;
+    }
     if (!*sp)
     {
         *sp = ir_tcl_malloc (sizeof(**sp));
         (*sp)->next = NULL;
         (*sp)->fd = fd;
-        (*sp)->timer_token =
-            Tcl_CreateTimerHandler (250, ir_tcl_timer_proc, *sp);
+        (*sp)->tcl_Channel = Tcl_MakeTcpClientChannel ((ClientData) fd);
     }
-    (*sp)->mask = TCL_READABLE|TCL_WRITABLE;
     (*sp)->f = f;
     (*sp)->clientData = clientData;
-    if (!f)
-    {
-        struct sel_proc *sp_tmp = *sp;
-        Tcl_DeleteTimerHandler ((*sp)->timer_token);
-        *sp = (*sp)->next;
-        xfree (sp_tmp);
-    }
+    Tcl_CreateChannelHandler ((*sp)->tcl_Channel, mask,
+                              ir_tcl_tk_select_proc,
+                             (ClientData) *sp);
 }
+#endif
+
+#if (TCL_MAJOR_VERSION == 7 && TCL_MINOR_VERSION > 4)
+
+struct sel_proc {
+    void (*f)(ClientData clientData, int r, int w, int e);
+    ClientData clientData;
+    int fd;
+    Tcl_File tcl_File;
+    struct sel_proc *next;
+};
+
+static struct sel_proc *sel_proc_list = NULL;
 
-#else
 static void ir_tcl_tk_select_proc (ClientData clientData, int mask)
 {
     struct sel_proc *sp = (struct sel_proc *) clientData;
@@ -100,7 +127,7 @@ void ir_tcl_select_set (void (*f)(ClientData clientData, int r, int w, int e),
                         int fd, ClientData clientData, int r, int w, int e)
 {
     int mask = 0;
-    struct sel_proc *sp = sel_proc_list;
+    struct sel_proc **sp = &sel_proc_list;
 
     if (r)
         mask |= TCL_READABLE;
@@ -108,31 +135,37 @@ void ir_tcl_select_set (void (*f)(ClientData clientData, int r, int w, int e),
         mask |= TCL_WRITABLE;
     if (e)
         mask |= TCL_EXCEPTION;
-    while (sp)
+    while (*sp)
     {
-        if (sp->fd == fd)
+        if ((*sp)->fd == fd)
              break;
-        sp = sp->next;
+        sp = &(*sp)->next;
+    }
+    logf (LOG_DEBUG, "r=%d w=%d e=%d sp=%p", r, w, e, *sp);
+    if (!f)
+    {
+        if (*sp)
+        {
+            Tcl_DeleteFileHandler ((*sp)->tcl_File);
+            Tcl_FreeFile ((*sp)->tcl_File);
+            *sp = (*sp)->next;
+        }
+        return ;
     }
-    if (!sp)
+    if (!*sp)
     {
-        sp = ir_tcl_malloc (sizeof(*sp));
-        sp->next = sel_proc_list;
-        sel_proc_list = sp;
-        sp->fd = fd;
-#if WINDOWS
-        sp->tcl_File = Tcl_GetFile ((ClientData) fd, TCL_WIN_SOCKET);
+        *sp = ir_tcl_malloc (sizeof(**sp));
+        (*sp)->next = NULL;
+        (*sp)->fd = fd;
+#if WIN32
+        (*sp)->tcl_File = Tcl_GetFile ((ClientData) fd, TCL_WIN_SOCKET);
 #else
-        sp->tcl_File = Tcl_GetFile ((ClientData) fd, TCL_UNIX_FD);
+        (*sp)->tcl_File = Tcl_GetFile ((ClientData) fd, TCL_UNIX_FD);
 #endif
     }
-    sp->f = f;
-    sp->clientData = clientData;
-    if (f)
-        Tcl_CreateFileHandler (sp->tcl_File, mask, ir_tcl_tk_select_proc, sp);
-    else
-        Tcl_DeleteFileHandler (sp->tcl_File);
+    (*sp)->f = f;
+    (*sp)->clientData = clientData;
+    Tcl_CreateFileHandler ((*sp)->tcl_File, mask, ir_tcl_tk_select_proc, *sp);
 }
 #endif
 
-#endif