Bump version to 1.4.3
[ir-tcl-moved-to-github.git] / select.c
1 /*
2  * IR toolkit for tcl/tk
3  * (c) Index Data 1996-1999
4  * See the file LICENSE for details.
5  * Sebastian Hammer, Adam Dickmeiss
6  *
7  * $Log: select.c,v $
8  * Revision 1.7  1999-11-30 14:05:58  adam
9  * Updated for new location of YAZ headers.
10  *
11  * Revision 1.6  1999/02/11 11:30:13  adam
12  * Updated for WIN32.
13  *
14  * Revision 1.5  1997/09/09 10:19:55  adam
15  * New MSV5.0 port with fewer warnings.
16  *
17  * Revision 1.4  1997/08/28 20:20:48  adam
18  * Added support for Tk8.0/Tcl8.0. Since Tcl_File handlers are gone
19  * we've moved to Tcl_Channel handlers instead.
20  *
21  * Revision 1.3  1997/04/13 18:57:28  adam
22  * Better error reporting and aligned with Tcl/Tk style.
23  * Rework of notifier code with Tcl_File handles.
24  *
25  * Revision 1.2  1996/09/13 10:51:48  adam
26  * Bug fix: ir_tcl_select_set called Tcl_GetFile at disconnect.
27  *
28  * Revision 1.1  1996/08/20  09:33:23  adam
29  * Tcl7.5 Generic file handling.
30  *
31  */
32
33 #include <tcl.h>
34 #include <yaz/log.h>
35 #include "ir-tcl.h"
36
37 #if TCL_MAJOR_VERSION == 8
38 struct sel_proc {
39     void (*f)(ClientData clientData, int r, int w, int e);
40     ClientData clientData;
41     int fd;
42     Tcl_Channel tcl_Channel;
43     struct sel_proc *next;
44 };
45
46 static struct sel_proc *sel_proc_list = NULL;
47
48 static void ir_tcl_tk_select_proc (ClientData clientData, int mask)
49 {
50     struct sel_proc *sp = (struct sel_proc *) clientData;
51
52     if (!sp->f)
53         return ;
54     (*sp->f)(sp->clientData, mask & TCL_READABLE, mask & TCL_WRITABLE,
55              mask & TCL_EXCEPTION);
56 }
57
58 void ir_tcl_select_set (void (*f)(ClientData clientData, int r, int w, int e),
59                         int fd, ClientData clientData, int r, int w, int e)
60 {
61     int mask = 0;
62     struct sel_proc **sp = &sel_proc_list;
63
64     if (r)
65         mask |= TCL_READABLE;
66     if (w)
67         mask |= TCL_WRITABLE;
68     if (e)
69         mask |= TCL_EXCEPTION;
70     while (*sp)
71     {
72         if ((*sp)->fd == fd)
73              break;
74         sp = &(*sp)->next;
75     }
76     logf (LOG_DEBUG, "r=%d w=%d e=%d sp=%p", r, w, e, *sp);
77     if (*sp)
78         Tcl_DeleteChannelHandler ((*sp)->tcl_Channel, ir_tcl_tk_select_proc,
79                                   (*sp)->clientData);
80     if (!f)
81     {
82         if (*sp)
83         {
84             Tcl_Close (NULL, (*sp)->tcl_Channel);
85             *sp = (*sp)->next;
86         }
87         return ;
88     }
89     if (!*sp)
90     {
91         *sp = ir_tcl_malloc (sizeof(**sp));
92         (*sp)->next = NULL;
93         (*sp)->fd = fd;
94         (*sp)->tcl_Channel = Tcl_MakeTcpClientChannel ((ClientData) fd);
95     }
96     (*sp)->f = f;
97     (*sp)->clientData = clientData;
98     Tcl_CreateChannelHandler ((*sp)->tcl_Channel, mask,
99                               ir_tcl_tk_select_proc,
100                               (ClientData) *sp);
101 }
102 #endif
103
104 #if (TCL_MAJOR_VERSION == 7 && TCL_MINOR_VERSION > 4)
105
106 struct sel_proc {
107     void (*f)(ClientData clientData, int r, int w, int e);
108     ClientData clientData;
109     int fd;
110     Tcl_File tcl_File;
111     struct sel_proc *next;
112 };
113
114 static struct sel_proc *sel_proc_list = NULL;
115
116 static void ir_tcl_tk_select_proc (ClientData clientData, int mask)
117 {
118     struct sel_proc *sp = (struct sel_proc *) clientData;
119
120     if (!sp->f)
121         return ;
122     (*sp->f)(sp->clientData, mask & TCL_READABLE, mask & TCL_WRITABLE,
123              mask & TCL_EXCEPTION);
124 }
125
126 void ir_tcl_select_set (void (*f)(ClientData clientData, int r, int w, int e),
127                         int fd, ClientData clientData, int r, int w, int e)
128 {
129     int mask = 0;
130     struct sel_proc **sp = &sel_proc_list;
131
132     if (r)
133         mask |= TCL_READABLE;
134     if (w)
135         mask |= TCL_WRITABLE;
136     if (e)
137         mask |= TCL_EXCEPTION;
138     while (*sp)
139     {
140         if ((*sp)->fd == fd)
141              break;
142         sp = &(*sp)->next;
143     }
144     logf (LOG_DEBUG, "r=%d w=%d e=%d sp=%p", r, w, e, *sp);
145     if (!f)
146     {
147         if (*sp)
148         {
149             Tcl_DeleteFileHandler ((*sp)->tcl_File);
150             Tcl_FreeFile ((*sp)->tcl_File);
151             *sp = (*sp)->next;
152         }
153         return ;
154     }
155     if (!*sp)
156     {
157         *sp = ir_tcl_malloc (sizeof(**sp));
158         (*sp)->next = NULL;
159         (*sp)->fd = fd;
160 #if WIN32
161         (*sp)->tcl_File = Tcl_GetFile ((ClientData) fd, TCL_WIN_SOCKET);
162 #else
163         (*sp)->tcl_File = Tcl_GetFile ((ClientData) fd, TCL_UNIX_FD);
164 #endif
165     }
166     (*sp)->f = f;
167     (*sp)->clientData = clientData;
168     Tcl_CreateFileHandler ((*sp)->tcl_File, mask, ir_tcl_tk_select_proc, *sp);
169 }
170 #endif
171