Allow comment characters (#) to be escaped:
[python/dscho.git] / Mac / Modules / ctbmodule.c
blobd95cc990b8885b831efce757837895c22b82e931
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>
39 #ifndef HAVE_UNIVERSAL_HEADERS
40 #define ConnectionCompletionUPP ProcPtr
41 #define ConnectionChooseIdleUPP ProcPtr
42 #define NewConnectionCompletionProc(x) (x)
43 #define NewConnectionChooseIdleProc(x) (x)
44 #endif
46 #define _UnimplementedToolTrap 0xA89F
47 #define _CommToolboxTrap 0x8B
48 #define _UnimplementedOSTrap 0x9F
50 static char *errornames[] = {
51 "No Error",
52 "Rejected", /* 1 */
53 "Failed", /* 2 */
54 "Timeout", /* 3 */
55 "Not Open", /* 4 */
56 "Not Closed", /* 5 */
57 "No Request Pending", /* 6 */
58 "Not Supported", /* 7 */
59 "No Tools", /* 8 */
60 "User Cancel", /* 9 */
61 "Error 10", /* 10 */
62 "Unknown Error", /* 11 */
63 #define MAX_POS_ERROR 11
66 extern PyObject *PyErr_Mac(PyObject *,int);
68 static PyObject *
69 PyCtb_Error(PyObject *errobj, int errcode)
71 if ( errcode > 0 && errcode <= MAX_POS_ERROR ) {
72 PyErr_SetString(errobj, errornames[errcode]);
73 return NULL;
74 } else {
75 return PyErr_Mac(errobj, errcode);
79 static PyObject *ErrorObject;
81 typedef struct {
82 PyObject_HEAD
83 ConnHandle hdl; /* The handle to the connection */
84 PyObject *callback; /* Python callback routine */
85 int has_callback; /* True if callback not None */
86 int err; /* Error to pass to the callback */
87 } ctbcmobject;
89 staticforward PyTypeObject ctbcmtype;
91 #define is_ctbcmobject(v) ((v)->ob_type == &ctbcmtype)
93 static
94 TrapAvailable(short tNumber, TrapType tType)
96 short unImplemented;
98 if (tType == OSTrap)
99 unImplemented = _UnimplementedOSTrap;
100 else
101 unImplemented = _UnimplementedToolTrap;
103 return NGetTrapAddress(tNumber, tType) != NGetTrapAddress(unImplemented, tType);
106 static
107 initialize_ctb()
109 OSErr err;
110 static initialized = -1;
112 if ( initialized >= 0 )
113 return initialized;
114 initialized = 0;
116 if ( !TrapAvailable(_CommToolboxTrap, OSTrap) ) {
117 PyErr_SetString(ErrorObject, "CTB not available");
118 return 0;
120 if ( (err=InitCTBUtilities()) ) {
121 PyCtb_Error(ErrorObject, (int)err);
122 return 0;
124 if ( (err=InitCRM()) ) {
125 PyCtb_Error(ErrorObject, (int)err);
126 return 0;
128 if ( (err=InitCM()) ) {
129 PyCtb_Error(ErrorObject, (int)err);
130 return 0;
132 initialized = 1;
133 return 1;
136 static int
137 ctbcm_pycallback(arg)
138 void *arg;
140 ctbcmobject *self = (ctbcmobject *)arg;
141 PyObject *args, *rv;
143 if ( !self->has_callback ) /* It could have been removed in the meantime */
144 return 0;
145 args = Py_BuildValue("(i)", self->err);
146 rv = PyEval_CallObject(self->callback, args);
147 Py_DECREF(args);
148 if( rv == NULL )
149 return -1;
150 Py_DECREF(rv);
151 return 0;
154 /*DBG*/int ncallback;
155 static pascal void
156 ctbcm_ctbcallback(hconn)
157 ConnHandle hconn;
159 ctbcmobject *self;
161 /* XXXX Do I have to do the A5 mumbo-jumbo? */
162 ncallback++; /*DBG*/
163 self = (ctbcmobject *)CMGetUserData(hconn);
164 self->err = (int)((*hconn)->errCode);
165 Py_AddPendingCall(ctbcm_pycallback, (void *)self);
168 static ctbcmobject *
169 newctbcmobject(arg)
170 PyObject *arg;
172 ctbcmobject *self;
173 self = PyObject_NEW(ctbcmobject, &ctbcmtype);
174 if (self == NULL)
175 return NULL;
176 self->hdl = NULL;
177 Py_INCREF(Py_None);
178 self->callback = Py_None;
179 self->has_callback = 0;
180 return self;
183 /* ctbcm methods */
185 static void
186 ctbcm_dealloc(self)
187 ctbcmobject *self;
189 if ( self->hdl ) {
190 (void)CMClose(self->hdl, 0, (ConnectionCompletionUPP)0, 0, 1);
191 /*XXXX Is this safe? */
192 CMDispose(self->hdl);
193 self->hdl = NULL;
195 PyMem_DEL(self);
198 static PyObject *
199 ctbcm_open(self, args)
200 ctbcmobject *self;
201 PyObject *args;
203 long timeout;
204 OSErr err;
205 ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback);
207 if (!PyArg_Parse(args, "l", &timeout))
208 return NULL;
209 if ( (err=CMOpen(self->hdl, self->has_callback, cb_upp, timeout)) != 0)
210 return PyCtb_Error(ErrorObject, (int)err);
211 Py_INCREF(Py_None);
212 return Py_None;
215 static PyObject *
216 ctbcm_listen(self, args)
217 ctbcmobject *self;
218 PyObject *args;
220 long timeout;
221 OSErr err;
222 ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback);
224 if (!PyArg_Parse(args, "l", &timeout))
225 return NULL;
226 if ( (err=CMListen(self->hdl,self->has_callback, cb_upp, timeout)) != 0)
227 return PyCtb_Error(ErrorObject, (int)err);
228 Py_INCREF(Py_None);
229 return Py_None;
232 static PyObject *
233 ctbcm_accept(self, args)
234 ctbcmobject *self;
235 PyObject *args;
237 int accept;
238 OSErr err;
240 if (!PyArg_Parse(args, "i", &accept))
241 return NULL;
242 if ( (err=CMAccept(self->hdl, accept)) != 0)
243 return PyCtb_Error(ErrorObject, (int)err);
244 Py_INCREF(Py_None);
245 return Py_None;
248 static PyObject *
249 ctbcm_close(self, args)
250 ctbcmobject *self;
251 PyObject *args;
253 int now;
254 long timeout;
255 OSErr err;
256 ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback);
258 if (!PyArg_Parse(args, "(li)", &timeout, &now))
259 return NULL;
260 if ( (err=CMClose(self->hdl, self->has_callback, cb_upp, timeout, now)) != 0)
261 return PyCtb_Error(ErrorObject, (int)err);
262 Py_INCREF(Py_None);
263 return Py_None;
266 static PyObject *
267 ctbcm_read(self, args)
268 ctbcmobject *self;
269 PyObject *args;
271 long timeout, len;
272 int chan;
273 CMFlags flags;
274 OSErr err;
275 PyObject *rv, *rrv;
276 ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback);
278 if (!PyArg_Parse(args, "(lil)", &len, &chan, &timeout))
279 return NULL;
280 if ((rv=PyString_FromStringAndSize(NULL, len)) == NULL)
281 return NULL;
282 if ((err=CMRead(self->hdl, (Ptr)PyString_AsString(rv), &len, (CMChannel)chan,
283 self->has_callback, cb_upp, timeout, &flags)) != 0 && err != cmTimeOut)
284 return PyCtb_Error(ErrorObject, (int)err);
285 _PyString_Resize(&rv, len);
286 rrv = Py_BuildValue("(Oi)", rv, (int)flags);
287 Py_DECREF(rv);
288 return rrv;
291 static PyObject *
292 ctbcm_write(self, args)
293 ctbcmobject *self;
294 PyObject *args;
296 long timeout, len;
297 int chan, ilen, flags;
298 OSErr err;
299 char *buf;
300 ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback);
302 if (!PyArg_Parse(args, "(s#ili)", &buf, &ilen, &chan, &timeout, &flags))
303 return NULL;
304 len = ilen;
305 if ((err=CMWrite(self->hdl, (Ptr)buf, &len, (CMChannel)chan,
306 self->has_callback, cb_upp, timeout, (CMFlags)flags)) != 0 && err != cmTimeOut)
307 return PyCtb_Error(ErrorObject, (int)err);
308 return PyInt_FromLong((int)len);
311 static PyObject *
312 ctbcm_status(self, args)
313 ctbcmobject *self;
314 PyObject *args;
316 CMBufferSizes sizes;
317 CMStatFlags flags;
318 OSErr err;
319 PyObject *rv, *rrv;
321 if (!PyArg_NoArgs(args))
322 return NULL;
323 if ((err=CMStatus(self->hdl, sizes, &flags)) != 0)
324 return PyCtb_Error(ErrorObject, (int)err);
325 rv = Py_BuildValue("(llllll)", sizes[0], sizes[1], sizes[2], sizes[3], sizes[4], sizes[5]);
326 if ( rv == NULL )
327 return NULL;
328 rrv = Py_BuildValue("(Ol)", rv, (long)flags);
329 Py_DECREF(rv);
330 return rrv;
333 static PyObject *
334 ctbcm_getconfig(self, args)
335 ctbcmobject *self;
336 PyObject *args;
338 char *rv;
340 if (!PyArg_NoArgs(args))
341 return NULL;
342 if ((rv=(char *)CMGetConfig(self->hdl)) == NULL ) {
343 PyErr_SetString(ErrorObject, "CMGetConfig failed");
344 return NULL;
346 return PyString_FromString(rv);
349 static PyObject *
350 ctbcm_setconfig(self, args)
351 ctbcmobject *self;
352 PyObject *args;
354 char *cfg;
355 short rv;
357 if (!PyArg_Parse(args, "s", &cfg))
358 return NULL;
359 rv=CMSetConfig(self->hdl, (Ptr)cfg);
360 return PyInt_FromLong((long)rv);
363 static PyObject *
364 ctbcm_choose(self, args)
365 ctbcmobject *self;
366 PyObject *args;
368 int rv;
369 Point pt;
371 if (!PyArg_NoArgs(args))
372 return NULL;
373 pt.v = 40;
374 pt.h = 40;
375 rv=CMChoose(&self->hdl, pt, (ConnectionChooseIdleUPP)0);
376 return PyInt_FromLong(rv);
379 static PyObject *
380 ctbcm_idle(self, args)
381 ctbcmobject *self;
382 PyObject *args;
384 if (!PyArg_NoArgs(args))
385 return NULL;
386 CMIdle(self->hdl);
387 Py_INCREF(Py_None);
388 return Py_None;
391 static PyObject *
392 ctbcm_abort(self, args)
393 ctbcmobject *self;
394 PyObject *args;
396 if (!PyArg_NoArgs(args))
397 return NULL;
398 CMAbort(self->hdl);
399 Py_INCREF(Py_None);
400 return Py_None;
403 static PyObject *
404 ctbcm_reset(self, args)
405 ctbcmobject *self;
406 PyObject *args;
408 if (!PyArg_NoArgs(args))
409 return NULL;
410 CMReset(self->hdl);
411 Py_INCREF(Py_None);
412 return Py_None;
415 static PyObject *
416 ctbcm_break(self, args)
417 ctbcmobject *self;
418 PyObject *args;
420 long duration;
421 ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback);
423 if (!PyArg_Parse(args, "l", &duration))
424 return NULL;
425 CMBreak(self->hdl, duration,self->has_callback, cb_upp);
426 Py_INCREF(Py_None);
427 return Py_None;
430 static struct PyMethodDef ctbcm_methods[] = {
431 {"Open", (PyCFunction)ctbcm_open},
432 {"Close", (PyCFunction)ctbcm_close},
433 {"Read", (PyCFunction)ctbcm_read},
434 {"Write", (PyCFunction)ctbcm_write},
435 {"Status", (PyCFunction)ctbcm_status},
436 {"GetConfig", (PyCFunction)ctbcm_getconfig},
437 {"SetConfig", (PyCFunction)ctbcm_setconfig},
438 {"Choose", (PyCFunction)ctbcm_choose},
439 {"Idle", (PyCFunction)ctbcm_idle},
440 {"Listen", (PyCFunction)ctbcm_listen},
441 {"Accept", (PyCFunction)ctbcm_accept},
442 {"Abort", (PyCFunction)ctbcm_abort},
443 {"Reset", (PyCFunction)ctbcm_reset},
444 {"Break", (PyCFunction)ctbcm_break},
445 {NULL, NULL} /* sentinel */
448 static PyObject *
449 ctbcm_getattr(self, name)
450 ctbcmobject *self;
451 char *name;
453 if ( strcmp(name, "callback") == 0 ) {
454 Py_INCREF(self->callback);
455 return self->callback;
457 return Py_FindMethod(ctbcm_methods, (PyObject *)self, name);
460 static int
461 ctbcm_setattr(self, name, v)
462 ctbcmobject *self;
463 char *name;
464 PyObject *v;
466 if ( strcmp(name, "callback") != 0 ) {
467 PyErr_SetString(PyExc_AttributeError, "ctbcm objects have callback attr only");
468 return -1;
470 if ( v == NULL ) {
471 v = Py_None;
473 Py_INCREF(v);
474 self->callback = v;
475 self->has_callback = (v != Py_None);
476 return 0;
479 statichere PyTypeObject ctbcmtype = {
480 PyObject_HEAD_INIT(&PyType_Type)
481 0, /*ob_size*/
482 "CTBConnectionMgr", /*tp_name*/
483 sizeof(ctbcmobject), /*tp_basicsize*/
484 0, /*tp_itemsize*/
485 /* methods */
486 (destructor)ctbcm_dealloc, /*tp_dealloc*/
487 0, /*tp_print*/
488 (getattrfunc)ctbcm_getattr, /*tp_getattr*/
489 (setattrfunc)ctbcm_setattr, /*tp_setattr*/
490 0, /*tp_compare*/
491 0, /*tp_repr*/
492 0, /*tp_as_number*/
493 0, /*tp_as_sequence*/
494 0, /*tp_as_mapping*/
495 0, /*tp_hash*/
497 /* --------------------------------------------------------------------- */
499 /* Function of no arguments returning new ctbcm object */
501 static PyObject *
502 ctb_cmnew(self, args)
503 PyObject *self; /* Not used */
504 PyObject *args;
506 int strlen;
507 PyObject *sizes_obj;
508 char *c_str;
509 unsigned char p_str[255];
510 CMBufferSizes sizes;
511 short procid;
512 ConnHandle hdl;
513 ctbcmobject *rv;
515 if (!PyArg_Parse(args, "(s#O)", &c_str, &strlen, &sizes_obj))
516 return NULL;
517 strncpy((char *)p_str+1, c_str, strlen);
518 p_str[0] = strlen;
519 if (!initialize_ctb())
520 return NULL;
521 if ( sizes_obj == Py_None ) {
522 memset(sizes, '\0', sizeof sizes);
523 } else {
524 if ( !PyArg_Parse(sizes_obj, "(llllll)", &sizes[0], &sizes[1], &sizes[2],
525 &sizes[3], &sizes[4], &sizes[5]))
526 return NULL;
528 if ( (procid=CMGetProcID(p_str)) < 0 )
529 return PyCtb_Error(ErrorObject, procid);
530 hdl = CMNew(procid, cmNoMenus|cmQuiet, sizes, 0, 0);
531 if ( hdl == NULL ) {
532 PyErr_SetString(ErrorObject, "CMNew failed");
533 return NULL;
535 rv = newctbcmobject(args);
536 if ( rv == NULL )
537 return NULL; /* XXXX Should dispose of hdl */
538 rv->hdl = hdl;
539 CMSetUserData(hdl, (long)rv);
540 return (PyObject *)rv;
543 static PyObject *
544 ctb_available(self, args)
545 PyObject *self;
546 PyObject *args;
548 int ok;
550 if (!PyArg_NoArgs(args))
551 return NULL;
552 ok = initialize_ctb();
553 PyErr_Clear();
554 return PyInt_FromLong(ok);
557 /* List of functions defined in the module */
559 static struct PyMethodDef ctb_methods[] = {
560 {"CMNew", ctb_cmnew},
561 {"available", ctb_available},
562 {NULL, NULL} /* sentinel */
566 /* Initialization function for the module (*must* be called initctb) */
568 void
569 initctb()
571 PyObject *m, *d, *o;
573 /* Create the module and add the functions */
574 m = Py_InitModule("ctb", ctb_methods);
576 /* Add some symbolic constants to the module */
577 d = PyModule_GetDict(m);
579 #define CMCONST(name, value) o = PyInt_FromLong(value); PyDict_SetItemString(d, name, o)
581 CMCONST("cmData", 1);
582 CMCONST("cmCntl", 2);
583 CMCONST("cmAttn", 3);
585 CMCONST("cmFlagsEOM", 1);
587 CMCONST("chooseDisaster", -2);
588 CMCONST("chooseFailed", -1);
589 CMCONST("chooseAborted", 0);
590 CMCONST("chooseOKMinor", 1);
591 CMCONST("chooseOKMajor", 2);
592 CMCONST("chooseCancel", 3);
594 CMCONST("cmStatusOpening", 1);
595 CMCONST("cmStatusOpen", 2);
596 CMCONST("cmStatusClosing", 4);
597 CMCONST("cmStatusDataAvail", 8);
598 CMCONST("cmStatusCntlAvail", 0x10);
599 CMCONST("cmStatusAttnAvail", 0x20);
600 CMCONST("cmStatusDRPend", 0x40);
601 CMCONST("cmStatusDWPend", 0x80);
602 CMCONST("cmStatusCWPend", 0x100);
603 CMCONST("cmStatusCWPend", 0x200);
604 CMCONST("cmStatusARPend", 0x400);
605 CMCONST("cmStatusAWPend", 0x800);
606 CMCONST("cmStatusBreakPending", 0x1000);
607 CMCONST("cmStatusListenPend", 0x2000);
608 CMCONST("cmStatusIncomingCallPresent", 0x4000);
610 ErrorObject = PyErr_NewException("ctb.error", NULL, NULL);
611 PyDict_SetItemString(d, "error", ErrorObject);
612 ctbcmtype.ob_type = &PyType_Type;
613 Py_INCREF(&ctbcmtype);
614 PyDict_SetItemString(d, "CTBConnectionMgrType", (PyObject *)&ctbcmtype);