From ee735be06a5f37ab59f4f51b6965ddb30314bc55 Mon Sep 17 00:00:00 2001 From: Jack Jansen Date: Wed, 14 Dec 1994 13:31:11 +0000 Subject: [PATCH] Interface to Mac Communications Toolbox (only Connection Manager for now) --- Mac/Modules/ctbmodule.c | 585 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 585 insertions(+) create mode 100644 Mac/Modules/ctbmodule.c diff --git a/Mac/Modules/ctbmodule.c b/Mac/Modules/ctbmodule.c new file mode 100644 index 00000000000..52009a04a5f --- /dev/null +++ b/Mac/Modules/ctbmodule.c @@ -0,0 +1,585 @@ +/*********************************************************** +Copyright 1991, 1992, 1993, 1994 by Stichting Mathematisch Centrum, +Amsterdam, The Netherlands. + + All Rights Reserved + +Permission to use, copy, modify, and distribute this software and its +documentation for any purpose and without fee is hereby granted, +provided that the above copyright notice appear in all copies and that +both that copyright notice and this permission notice appear in +supporting documentation, and that the names of Stichting Mathematisch +Centrum or CWI not be used in advertising or publicity pertaining to +distribution of the software without specific, written prior permission. + +STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO +THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE +FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT +OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + +******************************************************************/ + +/* Note: This file is partially converted to the new naming standard */ +/* ctbcm objects */ + + +#include "allobjects.h" +#include "modsupport.h" /* For getargs() etc. */ + +#include +#include +#include +#include +#include +/* #include */ +#ifndef __MWERKS__ +#define ConnectionCompletionUPP ProcPtr +#define ConnectionChooseIdleUPP ProcPtr +#define NewConnectionCompletionProc(x) (x) +#define NewConnectionChooseIdleProc(x) (x) +#endif + +#define _UnimplementedToolTrap 0xA89F +#define _CommToolboxTrap 0x8B +#define _UnimplementedOSTrap 0x9F + +extern object *PyErr_Mac(object *,int); + +static object *ErrorObject; + +typedef struct { + OB_HEAD + ConnHandle hdl; /* The handle to the connection */ + object *callback; /* Python callback routine */ + int has_callback; /* True if callback not None */ + int err; /* Error to pass to the callback */ +} ctbcmobject; + +staticforward typeobject ctbcmtype; + +#define is_ctbcmobject(v) ((v)->ob_type == &ctbcmtype) + +static +TrapAvailable(short tNumber, TrapType tType) +{ + short unImplemented; + + if (tType == OSTrap) + unImplemented = _UnimplementedOSTrap; + else + unImplemented = _UnimplementedToolTrap; + + return NGetTrapAddress(tNumber, tType) != NGetTrapAddress(unImplemented, tType); +} + +static +initialize_ctb() +{ + OSErr err; + static initialized = -1; + + if ( initialized >= 0 ) + return initialized; + initialized = 0; + + if ( !TrapAvailable(_CommToolboxTrap, OSTrap) ) { + err_setstr(ErrorObject, "CTB not available"); + return 0; + } + if ( (err=InitCTBUtilities()) ) { + PyErr_Mac(ErrorObject, (int)err); + return 0; + } + if ( (err=InitCRM()) ) { + PyErr_Mac(ErrorObject, (int)err); + return 0; + } + if ( (err=InitCM()) ) { + PyErr_Mac(ErrorObject, (int)err); + return 0; + } + initialized = 1; + return 1; +} + +static int +ctbcm_pycallback(arg) + void *arg; +{ + ctbcmobject *self = (ctbcmobject *)arg; + object *args, *rv; + + if ( !self->has_callback ) /* It could have been removed in the meantime */ + return 0; + args = mkvalue("(i)", self->err); + rv = call_object(self->callback, args); + DECREF(args); + if( rv == NULL ) + return -1; + DECREF(rv); + return 0; +} + +/*DBG*/int ncallback; +static pascal void +ctbcm_ctbcallback(hconn) + ConnHandle hconn; +{ + ctbcmobject *self; + + /* XXXX Do I have to do the A5 mumbo-jumbo? */ + ncallback++; /*DBG*/ + self = (ctbcmobject *)CMGetUserData(hconn); + self->err = (int)((*hconn)->errCode); + Py_AddPendingCall(ctbcm_pycallback, (void *)self); +} + +static ctbcmobject * +newctbcmobject(arg) + object *arg; +{ + ctbcmobject *self; + self = NEWOBJ(ctbcmobject, &ctbcmtype); + if (self == NULL) + return NULL; + self->hdl = NULL; + INCREF(None); + self->callback = None; + self->has_callback = 0; + return self; +} + +/* ctbcm methods */ + +static void +ctbcm_dealloc(self) + ctbcmobject *self; +{ + if ( self->hdl ) { + (void)CMClose(self->hdl, 0, (ConnectionCompletionUPP)0, 0, 1); + /*XXXX Is this safe? */ + CMDispose(self->hdl); + self->hdl = NULL; + } + DEL(self); +} + +static object * +ctbcm_open(self, args) + ctbcmobject *self; + object *args; +{ + long timeout; + OSErr err; + ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback); + + if (!getargs(args, "l", &timeout)) + return NULL; + if ( (err=CMOpen(self->hdl, self->has_callback, cb_upp, timeout)) < 0) + return PyErr_Mac(ErrorObject, (int)err); + INCREF(None); + return None; +} + +static object * +ctbcm_listen(self, args) + ctbcmobject *self; + object *args; +{ + long timeout; + OSErr err; + ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback); + + if (!getargs(args, "l", &timeout)) + return NULL; + if ( (err=CMListen(self->hdl,self->has_callback, cb_upp, timeout)) < 0) + return PyErr_Mac(ErrorObject, (int)err); + INCREF(None); + return None; +} + +static object * +ctbcm_accept(self, args) + ctbcmobject *self; + object *args; +{ + int accept; + OSErr err; + + if (!getargs(args, "i", &accept)) + return NULL; + if ( (err=CMAccept(self->hdl, accept)) < 0) + return PyErr_Mac(ErrorObject, (int)err); + INCREF(None); + return None; +} + +static object * +ctbcm_close(self, args) + ctbcmobject *self; + object *args; +{ + int now; + long timeout; + OSErr err; + ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback); + + if (!getargs(args, "(li)", &timeout, &now)) + return NULL; + if ( (err=CMClose(self->hdl, self->has_callback, cb_upp, timeout, now)) < 0) + return PyErr_Mac(ErrorObject, (int)err); + INCREF(None); + return None; +} + +static object * +ctbcm_read(self, args) + ctbcmobject *self; + object *args; +{ + long timeout, len; + int chan; + CMFlags flags; + OSErr err; + object *rv; + ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback); + + if (!getargs(args, "(lil)", &len, &chan, &timeout)) + return NULL; + if ((rv=newsizedstringobject(NULL, len)) == NULL) + return NULL; + if ((err=CMRead(self->hdl, (Ptr)getstringvalue(rv), &len, (CMChannel)chan, + self->has_callback, cb_upp, timeout, &flags)) < 0) + return PyErr_Mac(ErrorObject, (int)err); + resizestring(&rv, len); + return mkvalue("(Oi)", rv, (int)flags); +} + +static object * +ctbcm_write(self, args) + ctbcmobject *self; + object *args; +{ + long timeout, len; + int chan, ilen, flags; + OSErr err; + char *buf; + ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback); + + if (!getargs(args, "(s#ili)", &buf, &ilen, &chan, &timeout, &flags)) + return NULL; + len = ilen; + if ((err=CMWrite(self->hdl, (Ptr)buf, &len, (CMChannel)chan, + self->has_callback, cb_upp, timeout, (CMFlags)flags)) < 0) + return PyErr_Mac(ErrorObject, (int)err); + return newintobject((int)len); +} + +static object * +ctbcm_status(self, args) + ctbcmobject *self; + object *args; +{ + CMBufferSizes sizes; + CMStatFlags flags; + OSErr err; + object *rv; + + if (!getnoarg(args)) + return NULL; + if ((err=CMStatus(self->hdl, sizes, &flags)) < 0) + return PyErr_Mac(ErrorObject, (int)err); + rv = mkvalue("(llllll)", sizes[0], sizes[1], sizes[2], sizes[3], sizes[4], sizes[5]); + if ( rv == NULL ) + return NULL; + return mkvalue("(Ol)", rv, (long)flags); +} + +static object * +ctbcm_getconfig(self, args) + ctbcmobject *self; + object *args; +{ + char *rv; + + if (!getnoarg(args)) + return NULL; + if ((rv=(char *)CMGetConfig(self->hdl)) == NULL ) { + err_setstr(ErrorObject, "CMGetConfig failed"); + return NULL; + } + return newstringobject(rv); +} + +static object * +ctbcm_setconfig(self, args) + ctbcmobject *self; + object *args; +{ + char *cfg; + OSErr err; + + if (!getargs(args, "s", &cfg)) + return NULL; + if ((err=CMSetConfig(self->hdl, (Ptr)cfg)) < 0) + return PyErr_Mac(ErrorObject, err); + return newintobject((int)err); +} + +static object * +ctbcm_choose(self, args) + ctbcmobject *self; + object *args; +{ + int rv; + Point pt; + + if (!getnoarg(args)) + return NULL; + pt.v = 40; + pt.h = 40; + rv=CMChoose(&self->hdl, pt, (ConnectionChooseIdleUPP)0); + return newintobject(rv); +} + +static object * +ctbcm_idle(self, args) + ctbcmobject *self; + object *args; +{ + if (!getnoarg(args)) + return NULL; + CMIdle(self->hdl); + INCREF(None); + return None; +} + +static object * +ctbcm_abort(self, args) + ctbcmobject *self; + object *args; +{ + if (!getnoarg(args)) + return NULL; + CMAbort(self->hdl); + INCREF(None); + return None; +} + +static object * +ctbcm_reset(self, args) + ctbcmobject *self; + object *args; +{ + if (!getnoarg(args)) + return NULL; + CMReset(self->hdl); + INCREF(None); + return None; +} + +static object * +ctbcm_break(self, args) + ctbcmobject *self; + object *args; +{ + long duration; + ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback); + + if (!getargs(args, "l", &duration)) + return NULL; + CMBreak(self->hdl, duration,self->has_callback, cb_upp); + INCREF(None); + return None; +} + +static struct methodlist ctbcm_methods[] = { + {"Open", (method)ctbcm_open}, + {"Close", (method)ctbcm_close}, + {"Read", (method)ctbcm_read}, + {"Write", (method)ctbcm_write}, + {"Status", (method)ctbcm_status}, + {"GetConfig", (method)ctbcm_getconfig}, + {"SetConfig", (method)ctbcm_setconfig}, + {"Choose", (method)ctbcm_choose}, + {"Idle", (method)ctbcm_idle}, + {"Listen", (method)ctbcm_listen}, + {"Accept", (method)ctbcm_accept}, + {"Abort", (method)ctbcm_abort}, + {"Reset", (method)ctbcm_reset}, + {"Break", (method)ctbcm_break}, + {NULL, NULL} /* sentinel */ +}; + +static object * +ctbcm_getattr(self, name) + ctbcmobject *self; + char *name; +{ + if ( strcmp(name, "callback") == 0 ) { + INCREF(self->callback); + return self->callback; + } + return findmethod(ctbcm_methods, (object *)self, name); +} + +static int +ctbcm_setattr(self, name, v) + ctbcmobject *self; + char *name; + object *v; +{ + if ( strcmp(name, "callback") != 0 ) { + err_setstr(AttributeError, "ctbcm objects have callback attr only"); + return -1; + } + if ( v == NULL ) { + v = None; + } + INCREF(v); /* XXXX Must I do this? */ + self->callback = v; + self->has_callback = (v != None); + return 0; +} + +static typeobject ctbcmtype = { + OB_HEAD_INIT(&Typetype) + 0, /*ob_size*/ + "ctbcm", /*tp_name*/ + sizeof(ctbcmobject), /*tp_basicsize*/ + 0, /*tp_itemsize*/ + /* methods */ + (destructor)ctbcm_dealloc, /*tp_dealloc*/ + 0, /*tp_print*/ + (getattrfunc)ctbcm_getattr, /*tp_getattr*/ + (setattrfunc)ctbcm_setattr, /*tp_setattr*/ + 0, /*tp_compare*/ + 0, /*tp_repr*/ + 0, /*tp_as_number*/ + 0, /*tp_as_sequence*/ + 0, /*tp_as_mapping*/ + 0, /*tp_hash*/ +}; +/* --------------------------------------------------------------------- */ + +/* Function of no arguments returning new ctbcm object */ + +static object * +ctb_cmnew(self, args) + object *self; /* Not used */ + object *args; +{ + int strlen; + object *sizes_obj; + char *c_str; + unsigned char p_str[255]; + CMBufferSizes sizes; + short procid; + ConnHandle hdl; + ctbcmobject *rv; + + if (!getargs(args, "(s#O)", &c_str, &strlen, &sizes_obj)) + return NULL; + strncpy((char *)p_str+1, c_str, strlen); + p_str[0] = strlen; + if (!initialize_ctb()) + return NULL; + if ( sizes_obj == None ) { + memset(sizes, '\0', sizeof sizes); + } else { + if ( !getargs(sizes_obj, "(llllll)", &sizes[0], &sizes[1], &sizes[2], + &sizes[3], &sizes[4], &sizes[5])) + return NULL; + } + if ( (procid=CMGetProcID(p_str)) < 0 ) + return PyErr_Mac(ErrorObject, procid); + hdl = CMNew(procid, cmNoMenus|cmQuiet, sizes, 0, 0); + if ( hdl == NULL ) { + err_setstr(ErrorObject, "CMNew failed"); + return NULL; + } + rv = newctbcmobject(args); + if ( rv == NULL ) + return NULL; /* XXXX Should dispose of hdl */ + rv->hdl = hdl; + CMSetUserData(hdl, (long)rv); + return (object *)rv; +} + +static object * +ctb_available(self, args) + object *self; + object *args; +{ + int ok; + + if (!getnoarg(args)) + return NULL; + ok = initialize_ctb(); + err_clear(); + return newintobject(ok); +} + +/* List of functions defined in the module */ + +static struct methodlist ctb_methods[] = { + {"CMNew", ctb_cmnew}, + {"available", ctb_available}, + {NULL, NULL} /* sentinel */ +}; + + +/* Initialization function for the module (*must* be called initctb) */ + +void +initctb() +{ + object *m, *d, *o; + + /* Create the module and add the functions */ + m = initmodule("ctb", ctb_methods); + + /* Add some symbolic constants to the module */ + d = getmoduledict(m); + +#define CMCONST(name, value) o = newintobject(value); dictinsert(d, name, o) + + CMCONST("cmData", 1); + CMCONST("cmCntl", 2); + CMCONST("cmAttn", 3); + + CMCONST("cmFlagsEOM", 1); + + CMCONST("chooseDisaster", -2); + CMCONST("chooseFailed", -1); + CMCONST("chooseAborted", 0); + CMCONST("chooseOKMinor", 1); + CMCONST("chooseOKMajor", 2); + CMCONST("chooseCancel", 3); + + CMCONST("cmStatusOpening", 1); + CMCONST("cmStatusOpen", 2); + CMCONST("cmStatusClosing", 4); + CMCONST("cmStatusDataAvail", 8); + CMCONST("cmStatusCntlAvail", 0x10); + CMCONST("cmStatusAttnAvail", 0x20); + CMCONST("cmStatusDRPend", 0x40); + CMCONST("cmStatusDWPend", 0x80); + CMCONST("cmStatusCWPend", 0x100); + CMCONST("cmStatusCWPend", 0x200); + CMCONST("cmStatusARPend", 0x400); + CMCONST("cmStatusAWPend", 0x800); + CMCONST("cmStatusBreakPending", 0x1000); + CMCONST("cmStatusListenPend", 0x2000); + CMCONST("cmStatusIncomingCallPresent", 0x4000); + + ErrorObject = newstringobject("ctb.error"); + dictinsert(d, "error", ErrorObject); + + /* Check for errors */ + if (err_occurred()) + fatal("can't initialize module ctb"); +}