Apparently the code to forestall Tk eating events was too aggressive (Tk user input...
[python/dscho.git] / Mac / Modules / ctbmodule.c
blobdea35b76b8cc92ba4d4a5d64e65ef1c100b1536f
1 /***********************************************************
2 Copyright 1991-1997 by Stichting Mathematisch Centrum, Amsterdam,
3 The Netherlands.
5 All Rights Reserved
7 Permission to use, copy, modify, and distribute this software and its
8 documentation for any purpose and without fee is hereby granted,
9 provided that the above copyright notice appear in all copies and that
10 both that copyright notice and this permission notice appear in
11 supporting documentation, and that the names of Stichting Mathematisch
12 Centrum or CWI not be used in advertising or publicity pertaining to
13 distribution of the software without specific, written prior permission.
15 STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16 THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17 FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18 FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21 OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
23 ******************************************************************/
25 /* Note: This file is partially converted to the new naming standard */
26 /* ctbcm objects */
29 #include "Python.h"
31 #include "macglue.h"
33 #include <CommResources.h>
34 #include <Connections.h>
35 #include <CTBUtilities.h>
36 #include <ToolUtils.h>
37 #include <OSUtils.h>
40 #define _UnimplementedToolTrap 0xA89F
41 #define _CommToolboxTrap 0x8B
42 #define _UnimplementedOSTrap 0x9F
44 static char *errornames[] = {
45 "No Error",
46 "Rejected", /* 1 */
47 "Failed", /* 2 */
48 "Timeout", /* 3 */
49 "Not Open", /* 4 */
50 "Not Closed", /* 5 */
51 "No Request Pending", /* 6 */
52 "Not Supported", /* 7 */
53 "No Tools", /* 8 */
54 "User Cancel", /* 9 */
55 "Error 10", /* 10 */
56 "Unknown Error", /* 11 */
57 #define MAX_POS_ERROR 11
60 extern PyObject *PyErr_Mac(PyObject *,int);
62 static PyObject *
63 PyCtb_Error(PyObject *errobj, int errcode)
65 if ( errcode > 0 && errcode <= MAX_POS_ERROR ) {
66 PyErr_SetString(errobj, errornames[errcode]);
67 return NULL;
68 } else {
69 return PyErr_Mac(errobj, errcode);
73 static PyObject *ErrorObject;
75 typedef struct {
76 PyObject_HEAD
77 ConnHandle hdl; /* The handle to the connection */
78 PyObject *callback; /* Python callback routine */
79 int has_callback; /* True if callback not None */
80 int err; /* Error to pass to the callback */
81 } ctbcmobject;
83 staticforward PyTypeObject ctbcmtype;
85 #define is_ctbcmobject(v) ((v)->ob_type == &ctbcmtype)
87 static
88 TrapAvailable(short tNumber, TrapType tType)
90 short unImplemented;
92 if (tType == OSTrap)
93 unImplemented = _UnimplementedOSTrap;
94 else
95 unImplemented = _UnimplementedToolTrap;
97 return NGetTrapAddress(tNumber, tType) != NGetTrapAddress(unImplemented, tType);
100 static
101 initialize_ctb()
103 OSErr err;
104 static initialized = -1;
106 if ( initialized >= 0 )
107 return initialized;
108 initialized = 0;
110 if ( !TrapAvailable(_CommToolboxTrap, OSTrap) ) {
111 PyErr_SetString(ErrorObject, "CTB not available");
112 return 0;
114 if ( (err=InitCTBUtilities()) ) {
115 PyCtb_Error(ErrorObject, (int)err);
116 return 0;
118 if ( (err=InitCRM()) ) {
119 PyCtb_Error(ErrorObject, (int)err);
120 return 0;
122 if ( (err=InitCM()) ) {
123 PyCtb_Error(ErrorObject, (int)err);
124 return 0;
126 initialized = 1;
127 return 1;
130 static int
131 ctbcm_pycallback(arg)
132 void *arg;
134 ctbcmobject *self = (ctbcmobject *)arg;
135 PyObject *args, *rv;
137 if ( !self->has_callback ) /* It could have been removed in the meantime */
138 return 0;
139 args = Py_BuildValue("(i)", self->err);
140 rv = PyEval_CallObject(self->callback, args);
141 Py_DECREF(args);
142 if( rv == NULL )
143 return -1;
144 Py_DECREF(rv);
145 return 0;
148 /*DBG*/int ncallback;
149 static pascal void
150 ctbcm_ctbcallback(hconn)
151 ConnHandle hconn;
153 ctbcmobject *self;
155 /* XXXX Do I have to do the A5 mumbo-jumbo? */
156 ncallback++; /*DBG*/
157 self = (ctbcmobject *)CMGetUserData(hconn);
158 self->err = (int)((*hconn)->errCode);
159 Py_AddPendingCall(ctbcm_pycallback, (void *)self);
162 static ctbcmobject *
163 newctbcmobject(arg)
164 PyObject *arg;
166 ctbcmobject *self;
167 self = PyObject_NEW(ctbcmobject, &ctbcmtype);
168 if (self == NULL)
169 return NULL;
170 self->hdl = NULL;
171 Py_INCREF(Py_None);
172 self->callback = Py_None;
173 self->has_callback = 0;
174 return self;
177 /* ctbcm methods */
179 static void
180 ctbcm_dealloc(self)
181 ctbcmobject *self;
183 if ( self->hdl ) {
184 (void)CMClose(self->hdl, 0, (ConnectionCompletionUPP)0, 0, 1);
185 /*XXXX Is this safe? */
186 CMDispose(self->hdl);
187 self->hdl = NULL;
189 PyMem_DEL(self);
192 static PyObject *
193 ctbcm_open(self, args)
194 ctbcmobject *self;
195 PyObject *args;
197 long timeout;
198 OSErr err;
199 ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback);
201 if (!PyArg_Parse(args, "l", &timeout))
202 return NULL;
203 if ( (err=CMOpen(self->hdl, self->has_callback, cb_upp, timeout)) != 0)
204 return PyCtb_Error(ErrorObject, (int)err);
205 Py_INCREF(Py_None);
206 return Py_None;
209 static PyObject *
210 ctbcm_listen(self, args)
211 ctbcmobject *self;
212 PyObject *args;
214 long timeout;
215 OSErr err;
216 ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback);
218 if (!PyArg_Parse(args, "l", &timeout))
219 return NULL;
220 if ( (err=CMListen(self->hdl,self->has_callback, cb_upp, timeout)) != 0)
221 return PyCtb_Error(ErrorObject, (int)err);
222 Py_INCREF(Py_None);
223 return Py_None;
226 static PyObject *
227 ctbcm_accept(self, args)
228 ctbcmobject *self;
229 PyObject *args;
231 int accept;
232 OSErr err;
234 if (!PyArg_Parse(args, "i", &accept))
235 return NULL;
236 if ( (err=CMAccept(self->hdl, accept)) != 0)
237 return PyCtb_Error(ErrorObject, (int)err);
238 Py_INCREF(Py_None);
239 return Py_None;
242 static PyObject *
243 ctbcm_close(self, args)
244 ctbcmobject *self;
245 PyObject *args;
247 int now;
248 long timeout;
249 OSErr err;
250 ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback);
252 if (!PyArg_Parse(args, "(li)", &timeout, &now))
253 return NULL;
254 if ( (err=CMClose(self->hdl, self->has_callback, cb_upp, timeout, now)) != 0)
255 return PyCtb_Error(ErrorObject, (int)err);
256 Py_INCREF(Py_None);
257 return Py_None;
260 static PyObject *
261 ctbcm_read(self, args)
262 ctbcmobject *self;
263 PyObject *args;
265 long timeout, len;
266 int chan;
267 CMFlags flags;
268 OSErr err;
269 PyObject *rv, *rrv;
270 ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback);
272 if (!PyArg_Parse(args, "(lil)", &len, &chan, &timeout))
273 return NULL;
274 if ((rv=PyString_FromStringAndSize(NULL, len)) == NULL)
275 return NULL;
276 if ((err=CMRead(self->hdl, (Ptr)PyString_AsString(rv), &len, (CMChannel)chan,
277 self->has_callback, cb_upp, timeout, &flags)) != 0 && err != cmTimeOut)
278 return PyCtb_Error(ErrorObject, (int)err);
279 _PyString_Resize(&rv, len);
280 rrv = Py_BuildValue("(Oi)", rv, (int)flags);
281 Py_DECREF(rv);
282 return rrv;
285 static PyObject *
286 ctbcm_write(self, args)
287 ctbcmobject *self;
288 PyObject *args;
290 long timeout, len;
291 int chan, ilen, flags;
292 OSErr err;
293 char *buf;
294 ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback);
296 if (!PyArg_Parse(args, "(s#ili)", &buf, &ilen, &chan, &timeout, &flags))
297 return NULL;
298 len = ilen;
299 if ((err=CMWrite(self->hdl, (Ptr)buf, &len, (CMChannel)chan,
300 self->has_callback, cb_upp, timeout, (CMFlags)flags)) != 0 && err != cmTimeOut)
301 return PyCtb_Error(ErrorObject, (int)err);
302 return PyInt_FromLong((int)len);
305 static PyObject *
306 ctbcm_status(self, args)
307 ctbcmobject *self;
308 PyObject *args;
310 CMBufferSizes sizes;
311 CMStatFlags flags;
312 OSErr err;
313 PyObject *rv, *rrv;
315 if (!PyArg_NoArgs(args))
316 return NULL;
317 if ((err=CMStatus(self->hdl, sizes, &flags)) != 0)
318 return PyCtb_Error(ErrorObject, (int)err);
319 rv = Py_BuildValue("(llllll)", sizes[0], sizes[1], sizes[2], sizes[3], sizes[4], sizes[5]);
320 if ( rv == NULL )
321 return NULL;
322 rrv = Py_BuildValue("(Ol)", rv, (long)flags);
323 Py_DECREF(rv);
324 return rrv;
327 static PyObject *
328 ctbcm_getconfig(self, args)
329 ctbcmobject *self;
330 PyObject *args;
332 char *rv;
334 if (!PyArg_NoArgs(args))
335 return NULL;
336 if ((rv=(char *)CMGetConfig(self->hdl)) == NULL ) {
337 PyErr_SetString(ErrorObject, "CMGetConfig failed");
338 return NULL;
340 return PyString_FromString(rv);
343 static PyObject *
344 ctbcm_setconfig(self, args)
345 ctbcmobject *self;
346 PyObject *args;
348 char *cfg;
349 short rv;
351 if (!PyArg_Parse(args, "s", &cfg))
352 return NULL;
353 rv=CMSetConfig(self->hdl, (Ptr)cfg);
354 return PyInt_FromLong((long)rv);
357 static PyObject *
358 ctbcm_choose(self, args)
359 ctbcmobject *self;
360 PyObject *args;
362 int rv;
363 Point pt;
365 if (!PyArg_NoArgs(args))
366 return NULL;
367 pt.v = 40;
368 pt.h = 40;
369 rv=CMChoose(&self->hdl, pt, (ConnectionChooseIdleUPP)0);
370 return PyInt_FromLong(rv);
373 static PyObject *
374 ctbcm_idle(self, args)
375 ctbcmobject *self;
376 PyObject *args;
378 if (!PyArg_NoArgs(args))
379 return NULL;
380 CMIdle(self->hdl);
381 Py_INCREF(Py_None);
382 return Py_None;
385 static PyObject *
386 ctbcm_abort(self, args)
387 ctbcmobject *self;
388 PyObject *args;
390 if (!PyArg_NoArgs(args))
391 return NULL;
392 CMAbort(self->hdl);
393 Py_INCREF(Py_None);
394 return Py_None;
397 static PyObject *
398 ctbcm_reset(self, args)
399 ctbcmobject *self;
400 PyObject *args;
402 if (!PyArg_NoArgs(args))
403 return NULL;
404 CMReset(self->hdl);
405 Py_INCREF(Py_None);
406 return Py_None;
409 static PyObject *
410 ctbcm_break(self, args)
411 ctbcmobject *self;
412 PyObject *args;
414 long duration;
415 ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback);
417 if (!PyArg_Parse(args, "l", &duration))
418 return NULL;
419 CMBreak(self->hdl, duration,self->has_callback, cb_upp);
420 Py_INCREF(Py_None);
421 return Py_None;
424 static struct PyMethodDef ctbcm_methods[] = {
425 {"Open", (PyCFunction)ctbcm_open},
426 {"Close", (PyCFunction)ctbcm_close},
427 {"Read", (PyCFunction)ctbcm_read},
428 {"Write", (PyCFunction)ctbcm_write},
429 {"Status", (PyCFunction)ctbcm_status},
430 {"GetConfig", (PyCFunction)ctbcm_getconfig},
431 {"SetConfig", (PyCFunction)ctbcm_setconfig},
432 {"Choose", (PyCFunction)ctbcm_choose},
433 {"Idle", (PyCFunction)ctbcm_idle},
434 {"Listen", (PyCFunction)ctbcm_listen},
435 {"Accept", (PyCFunction)ctbcm_accept},
436 {"Abort", (PyCFunction)ctbcm_abort},
437 {"Reset", (PyCFunction)ctbcm_reset},
438 {"Break", (PyCFunction)ctbcm_break},
439 {NULL, NULL} /* sentinel */
442 static PyObject *
443 ctbcm_getattr(self, name)
444 ctbcmobject *self;
445 char *name;
447 if ( strcmp(name, "callback") == 0 ) {
448 Py_INCREF(self->callback);
449 return self->callback;
451 return Py_FindMethod(ctbcm_methods, (PyObject *)self, name);
454 static int
455 ctbcm_setattr(self, name, v)
456 ctbcmobject *self;
457 char *name;
458 PyObject *v;
460 if ( strcmp(name, "callback") != 0 ) {
461 PyErr_SetString(PyExc_AttributeError, "ctbcm objects have callback attr only");
462 return -1;
464 if ( v == NULL ) {
465 v = Py_None;
467 Py_INCREF(v);
468 self->callback = v;
469 self->has_callback = (v != Py_None);
470 return 0;
473 statichere PyTypeObject ctbcmtype = {
474 PyObject_HEAD_INIT(&PyType_Type)
475 0, /*ob_size*/
476 "CTBConnectionMgr", /*tp_name*/
477 sizeof(ctbcmobject), /*tp_basicsize*/
478 0, /*tp_itemsize*/
479 /* methods */
480 (destructor)ctbcm_dealloc, /*tp_dealloc*/
481 0, /*tp_print*/
482 (getattrfunc)ctbcm_getattr, /*tp_getattr*/
483 (setattrfunc)ctbcm_setattr, /*tp_setattr*/
484 0, /*tp_compare*/
485 0, /*tp_repr*/
486 0, /*tp_as_number*/
487 0, /*tp_as_sequence*/
488 0, /*tp_as_mapping*/
489 0, /*tp_hash*/
491 /* --------------------------------------------------------------------- */
493 /* Function of no arguments returning new ctbcm object */
495 static PyObject *
496 ctb_cmnew(self, args)
497 PyObject *self; /* Not used */
498 PyObject *args;
500 int strlen;
501 PyObject *sizes_obj;
502 char *c_str;
503 unsigned char p_str[255];
504 CMBufferSizes sizes;
505 short procid;
506 ConnHandle hdl;
507 ctbcmobject *rv;
509 if (!PyArg_Parse(args, "(s#O)", &c_str, &strlen, &sizes_obj))
510 return NULL;
511 strncpy((char *)p_str+1, c_str, strlen);
512 p_str[0] = strlen;
513 if (!initialize_ctb())
514 return NULL;
515 if ( sizes_obj == Py_None ) {
516 memset(sizes, '\0', sizeof sizes);
517 } else {
518 if ( !PyArg_Parse(sizes_obj, "(llllll)", &sizes[0], &sizes[1], &sizes[2],
519 &sizes[3], &sizes[4], &sizes[5]))
520 return NULL;
522 if ( (procid=CMGetProcID(p_str)) < 0 )
523 return PyCtb_Error(ErrorObject, procid);
524 hdl = CMNew(procid, cmNoMenus|cmQuiet, sizes, 0, 0);
525 if ( hdl == NULL ) {
526 PyErr_SetString(ErrorObject, "CMNew failed");
527 return NULL;
529 rv = newctbcmobject(args);
530 if ( rv == NULL )
531 return NULL; /* XXXX Should dispose of hdl */
532 rv->hdl = hdl;
533 CMSetUserData(hdl, (long)rv);
534 return (PyObject *)rv;
537 static PyObject *
538 ctb_available(self, args)
539 PyObject *self;
540 PyObject *args;
542 int ok;
544 if (!PyArg_NoArgs(args))
545 return NULL;
546 ok = initialize_ctb();
547 PyErr_Clear();
548 return PyInt_FromLong(ok);
551 /* List of functions defined in the module */
553 static struct PyMethodDef ctb_methods[] = {
554 {"CMNew", ctb_cmnew},
555 {"available", ctb_available},
556 {NULL, NULL} /* sentinel */
560 /* Initialization function for the module (*must* be called initctb) */
562 void
563 initctb()
565 PyObject *m, *d, *o;
567 /* Create the module and add the functions */
568 m = Py_InitModule("ctb", ctb_methods);
570 /* Add some symbolic constants to the module */
571 d = PyModule_GetDict(m);
573 #define CMCONST(name, value) o = PyInt_FromLong(value); PyDict_SetItemString(d, name, o)
575 CMCONST("cmData", 1);
576 CMCONST("cmCntl", 2);
577 CMCONST("cmAttn", 3);
579 CMCONST("cmFlagsEOM", 1);
581 CMCONST("chooseDisaster", -2);
582 CMCONST("chooseFailed", -1);
583 CMCONST("chooseAborted", 0);
584 CMCONST("chooseOKMinor", 1);
585 CMCONST("chooseOKMajor", 2);
586 CMCONST("chooseCancel", 3);
588 CMCONST("cmStatusOpening", 1);
589 CMCONST("cmStatusOpen", 2);
590 CMCONST("cmStatusClosing", 4);
591 CMCONST("cmStatusDataAvail", 8);
592 CMCONST("cmStatusCntlAvail", 0x10);
593 CMCONST("cmStatusAttnAvail", 0x20);
594 CMCONST("cmStatusDRPend", 0x40);
595 CMCONST("cmStatusDWPend", 0x80);
596 CMCONST("cmStatusCWPend", 0x100);
597 CMCONST("cmStatusCWPend", 0x200);
598 CMCONST("cmStatusARPend", 0x400);
599 CMCONST("cmStatusAWPend", 0x800);
600 CMCONST("cmStatusBreakPending", 0x1000);
601 CMCONST("cmStatusListenPend", 0x2000);
602 CMCONST("cmStatusIncomingCallPresent", 0x4000);
604 ErrorObject = PyErr_NewException("ctb.error", NULL, NULL);
605 PyDict_SetItemString(d, "error", ErrorObject);
606 ctbcmtype.ob_type = &PyType_Type;
607 Py_INCREF(&ctbcmtype);
608 PyDict_SetItemString(d, "CTBConnectionMgrType", (PyObject *)&ctbcmtype);