586 lines
13 KiB
C
586 lines
13 KiB
C
/***********************************************************
|
|
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 <stdio.h>
|
|
#include <CommResources.h>
|
|
#include <Connections.h>
|
|
#include <ToolUtils.h>
|
|
#include <OSUtils.h>
|
|
/* #include <pascal.h> */
|
|
#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");
|
|
}
|