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