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