Bug fix: ir_tcl_select_set called Tcl_GetFile at disconnect.
[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.2  1996-09-13 10:51:48  adam
9  * Bug fix: ir_tcl_select_set called Tcl_GetFile at disconnect.
10  *
11  * Revision 1.1  1996/08/20  09:33:23  adam
12  * Tcl7.5 Generic file handling.
13  *
14  */
15
16 #include <tcl.h>
17 #include <log.h>
18 #include "ir-tcl.h"
19
20 #if TCL_MAJOR_VERSION > 7 || (TCL_MAJOR_VERSION == 7 && TCL_MINOR_VERSION > 4)
21
22 #define IRTCL_USE_TIMER 0
23
24 struct sel_proc {
25     void (*f)(ClientData clientData, int r, int w, int e);
26     ClientData clientData;
27     int fd;
28 #if IRTCL_USE_TIMER
29     int mask;
30     Tcl_TimerToken timer_token;
31 #else
32     Tcl_File tcl_File;
33 #endif
34     struct sel_proc *next;
35 };
36
37 static struct sel_proc *sel_proc_list = NULL;
38
39 #if IRTCL_USE_TIMER
40 static void ir_tcl_timer_proc (ClientData clientData)
41 {
42     struct sel_proc *sp = (struct sel_proc *) clientData;
43
44     if (!sp->f)
45         return ;
46     sp->timer_token =
47         Tcl_CreateTimerHandler (250, ir_tcl_timer_proc, clientData);
48     (*sp->f)(sp->clientData, sp->mask & TCL_READABLE, sp->mask & TCL_WRITABLE,
49              sp->mask & TCL_EXCEPTION);
50     
51 }
52
53 void ir_tcl_select_set (void (*f)(ClientData clientData, int r, int w, int e),
54                         int fd, ClientData clientData, int r, int w, int e)
55 {
56     int mask = 0;
57     struct sel_proc **sp = &sel_proc_list;
58
59     if (r)
60         mask |= TCL_READABLE;
61     if (w)
62         mask |= TCL_WRITABLE;
63     if (e)
64         mask |= TCL_EXCEPTION;
65     while (*sp)
66     {
67         if ((*sp)->fd == fd)
68             break;
69         sp = &(*sp)->next;
70     }
71     if (!*sp)
72     {
73         if (!f)
74             return;
75         *sp = ir_tcl_malloc (sizeof(**sp));
76         (*sp)->next = NULL;
77         (*sp)->fd = fd;
78         (*sp)->timer_token =
79             Tcl_CreateTimerHandler (250, ir_tcl_timer_proc, *sp);
80     }
81     (*sp)->mask = TCL_READABLE|TCL_WRITABLE;
82     (*sp)->f = f;
83     (*sp)->clientData = clientData;
84     if (!f)
85     {
86         struct sel_proc *sp_tmp = *sp;
87         Tcl_DeleteTimerHandler ((*sp)->timer_token);
88         *sp = (*sp)->next;
89         xfree (sp_tmp);
90     }
91 }
92
93 #else
94 static void ir_tcl_tk_select_proc (ClientData clientData, int mask)
95 {
96     struct sel_proc *sp = (struct sel_proc *) clientData;
97
98     if (!sp->f)
99         return ;
100     (*sp->f)(sp->clientData, mask & TCL_READABLE, mask & TCL_WRITABLE,
101              mask & TCL_EXCEPTION);
102 }
103
104 void ir_tcl_select_set (void (*f)(ClientData clientData, int r, int w, int e),
105                         int fd, ClientData clientData, int r, int w, int e)
106 {
107     int mask = 0;
108     struct sel_proc *sp = sel_proc_list;
109
110     if (r)
111         mask |= TCL_READABLE;
112     if (w)
113         mask |= TCL_WRITABLE;
114     if (e)
115         mask |= TCL_EXCEPTION;
116     while (sp)
117     {
118         if (sp->fd == fd)
119              break;
120         sp = sp->next;
121     }
122     if (!sp)
123     {
124         if (!f)
125             return;
126         sp = ir_tcl_malloc (sizeof(*sp));
127         sp->next = sel_proc_list;
128         sel_proc_list = sp;
129         sp->fd = fd;
130 #if WINDOWS
131         sp->tcl_File = Tcl_GetFile ((ClientData) fd, TCL_WIN_SOCKET);
132 #else
133         sp->tcl_File = Tcl_GetFile ((ClientData) fd, TCL_UNIX_FD);
134 #endif
135     }
136     sp->f = f;
137     sp->clientData = clientData;
138     if (f)
139         Tcl_CreateFileHandler (sp->tcl_File, mask, ir_tcl_tk_select_proc, sp);
140     else
141         Tcl_DeleteFileHandler (sp->tcl_File);
142 }
143 #endif
144
145 #endif