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