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