blob: ef03f9227fc0d909f4e4c79c75f7e68e728daffe [file] [log] [blame]
Jack Jansenee735be1994-12-14 13:31:11 +00001/***********************************************************
Guido van Rossum4410d571995-02-21 20:58:53 +00002Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
3The Netherlands.
Jack Jansenee735be1994-12-14 13:31:11 +00004
5 All Rights Reserved
6
7Permission to use, copy, modify, and distribute this software and its
8documentation for any purpose and without fee is hereby granted,
9provided that the above copyright notice appear in all copies and that
10both that copyright notice and this permission notice appear in
11supporting documentation, and that the names of Stichting Mathematisch
12Centrum or CWI not be used in advertising or publicity pertaining to
13distribution of the software without specific, written prior permission.
14
15STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
16THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
17FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
18FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
21OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22
23******************************************************************/
24
25/* Note: This file is partially converted to the new naming standard */
26/* ctbcm objects */
27
28
29#include "allobjects.h"
Jack Jansenee735be1994-12-14 13:31:11 +000030
Guido van Rossum4410d571995-02-21 20:58:53 +000031#include "macglue.h"
32
Jack Jansenee735be1994-12-14 13:31:11 +000033#include <CommResources.h>
34#include <Connections.h>
35#include <ToolUtils.h>
36#include <OSUtils.h>
Guido van Rossum4410d571995-02-21 20:58:53 +000037
38#ifndef HAVE_UNIVERSAL_HEADERS
Jack Jansenee735be1994-12-14 13:31:11 +000039#define ConnectionCompletionUPP ProcPtr
40#define ConnectionChooseIdleUPP ProcPtr
41#define NewConnectionCompletionProc(x) (x)
42#define NewConnectionChooseIdleProc(x) (x)
43#endif
44
45#define _UnimplementedToolTrap 0xA89F
46#define _CommToolboxTrap 0x8B
47#define _UnimplementedOSTrap 0x9F
48
49extern object *PyErr_Mac(object *,int);
50
51static object *ErrorObject;
52
53typedef struct {
54 OB_HEAD
55 ConnHandle hdl; /* The handle to the connection */
56 object *callback; /* Python callback routine */
57 int has_callback; /* True if callback not None */
58 int err; /* Error to pass to the callback */
59} ctbcmobject;
60
61staticforward typeobject ctbcmtype;
62
63#define is_ctbcmobject(v) ((v)->ob_type == &ctbcmtype)
64
65static
66TrapAvailable(short tNumber, TrapType tType)
67{
68 short unImplemented;
69
70 if (tType == OSTrap)
71 unImplemented = _UnimplementedOSTrap;
72 else
73 unImplemented = _UnimplementedToolTrap;
74
75 return NGetTrapAddress(tNumber, tType) != NGetTrapAddress(unImplemented, tType);
76}
77
78static
79initialize_ctb()
80{
81 OSErr err;
82 static initialized = -1;
83
84 if ( initialized >= 0 )
85 return initialized;
86 initialized = 0;
87
88 if ( !TrapAvailable(_CommToolboxTrap, OSTrap) ) {
89 err_setstr(ErrorObject, "CTB not available");
90 return 0;
91 }
92 if ( (err=InitCTBUtilities()) ) {
93 PyErr_Mac(ErrorObject, (int)err);
94 return 0;
95 }
96 if ( (err=InitCRM()) ) {
97 PyErr_Mac(ErrorObject, (int)err);
98 return 0;
99 }
100 if ( (err=InitCM()) ) {
101 PyErr_Mac(ErrorObject, (int)err);
102 return 0;
103 }
104 initialized = 1;
105 return 1;
106}
107
108static int
109ctbcm_pycallback(arg)
110 void *arg;
111{
112 ctbcmobject *self = (ctbcmobject *)arg;
113 object *args, *rv;
114
115 if ( !self->has_callback ) /* It could have been removed in the meantime */
116 return 0;
117 args = mkvalue("(i)", self->err);
118 rv = call_object(self->callback, args);
119 DECREF(args);
120 if( rv == NULL )
121 return -1;
122 DECREF(rv);
123 return 0;
124}
125
126/*DBG*/int ncallback;
127static pascal void
128ctbcm_ctbcallback(hconn)
129 ConnHandle hconn;
130{
131 ctbcmobject *self;
132
133 /* XXXX Do I have to do the A5 mumbo-jumbo? */
134 ncallback++; /*DBG*/
135 self = (ctbcmobject *)CMGetUserData(hconn);
136 self->err = (int)((*hconn)->errCode);
137 Py_AddPendingCall(ctbcm_pycallback, (void *)self);
138}
139
140static ctbcmobject *
141newctbcmobject(arg)
142 object *arg;
143{
144 ctbcmobject *self;
145 self = NEWOBJ(ctbcmobject, &ctbcmtype);
146 if (self == NULL)
147 return NULL;
148 self->hdl = NULL;
149 INCREF(None);
150 self->callback = None;
151 self->has_callback = 0;
152 return self;
153}
154
155/* ctbcm methods */
156
157static void
158ctbcm_dealloc(self)
159 ctbcmobject *self;
160{
161 if ( self->hdl ) {
162 (void)CMClose(self->hdl, 0, (ConnectionCompletionUPP)0, 0, 1);
163 /*XXXX Is this safe? */
164 CMDispose(self->hdl);
165 self->hdl = NULL;
166 }
167 DEL(self);
168}
169
170static object *
171ctbcm_open(self, args)
172 ctbcmobject *self;
173 object *args;
174{
175 long timeout;
176 OSErr err;
177 ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback);
178
179 if (!getargs(args, "l", &timeout))
180 return NULL;
181 if ( (err=CMOpen(self->hdl, self->has_callback, cb_upp, timeout)) < 0)
182 return PyErr_Mac(ErrorObject, (int)err);
183 INCREF(None);
184 return None;
185}
186
187static object *
188ctbcm_listen(self, args)
189 ctbcmobject *self;
190 object *args;
191{
192 long timeout;
193 OSErr err;
194 ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback);
195
196 if (!getargs(args, "l", &timeout))
197 return NULL;
198 if ( (err=CMListen(self->hdl,self->has_callback, cb_upp, timeout)) < 0)
199 return PyErr_Mac(ErrorObject, (int)err);
200 INCREF(None);
201 return None;
202}
203
204static object *
205ctbcm_accept(self, args)
206 ctbcmobject *self;
207 object *args;
208{
209 int accept;
210 OSErr err;
211
212 if (!getargs(args, "i", &accept))
213 return NULL;
214 if ( (err=CMAccept(self->hdl, accept)) < 0)
215 return PyErr_Mac(ErrorObject, (int)err);
216 INCREF(None);
217 return None;
218}
219
220static object *
221ctbcm_close(self, args)
222 ctbcmobject *self;
223 object *args;
224{
225 int now;
226 long timeout;
227 OSErr err;
228 ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback);
229
230 if (!getargs(args, "(li)", &timeout, &now))
231 return NULL;
232 if ( (err=CMClose(self->hdl, self->has_callback, cb_upp, timeout, now)) < 0)
233 return PyErr_Mac(ErrorObject, (int)err);
234 INCREF(None);
235 return None;
236}
237
238static object *
239ctbcm_read(self, args)
240 ctbcmobject *self;
241 object *args;
242{
243 long timeout, len;
244 int chan;
245 CMFlags flags;
246 OSErr err;
247 object *rv;
248 ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback);
249
250 if (!getargs(args, "(lil)", &len, &chan, &timeout))
251 return NULL;
252 if ((rv=newsizedstringobject(NULL, len)) == NULL)
253 return NULL;
254 if ((err=CMRead(self->hdl, (Ptr)getstringvalue(rv), &len, (CMChannel)chan,
255 self->has_callback, cb_upp, timeout, &flags)) < 0)
256 return PyErr_Mac(ErrorObject, (int)err);
257 resizestring(&rv, len);
258 return mkvalue("(Oi)", rv, (int)flags);
259}
260
261static object *
262ctbcm_write(self, args)
263 ctbcmobject *self;
264 object *args;
265{
266 long timeout, len;
267 int chan, ilen, flags;
268 OSErr err;
269 char *buf;
270 ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback);
271
272 if (!getargs(args, "(s#ili)", &buf, &ilen, &chan, &timeout, &flags))
273 return NULL;
274 len = ilen;
275 if ((err=CMWrite(self->hdl, (Ptr)buf, &len, (CMChannel)chan,
276 self->has_callback, cb_upp, timeout, (CMFlags)flags)) < 0)
277 return PyErr_Mac(ErrorObject, (int)err);
278 return newintobject((int)len);
279}
280
281static object *
282ctbcm_status(self, args)
283 ctbcmobject *self;
284 object *args;
285{
286 CMBufferSizes sizes;
287 CMStatFlags flags;
288 OSErr err;
289 object *rv;
290
291 if (!getnoarg(args))
292 return NULL;
293 if ((err=CMStatus(self->hdl, sizes, &flags)) < 0)
294 return PyErr_Mac(ErrorObject, (int)err);
295 rv = mkvalue("(llllll)", sizes[0], sizes[1], sizes[2], sizes[3], sizes[4], sizes[5]);
296 if ( rv == NULL )
297 return NULL;
298 return mkvalue("(Ol)", rv, (long)flags);
299}
300
301static object *
302ctbcm_getconfig(self, args)
303 ctbcmobject *self;
304 object *args;
305{
306 char *rv;
307
308 if (!getnoarg(args))
309 return NULL;
310 if ((rv=(char *)CMGetConfig(self->hdl)) == NULL ) {
311 err_setstr(ErrorObject, "CMGetConfig failed");
312 return NULL;
313 }
314 return newstringobject(rv);
315}
316
317static object *
318ctbcm_setconfig(self, args)
319 ctbcmobject *self;
320 object *args;
321{
322 char *cfg;
323 OSErr err;
324
325 if (!getargs(args, "s", &cfg))
326 return NULL;
327 if ((err=CMSetConfig(self->hdl, (Ptr)cfg)) < 0)
328 return PyErr_Mac(ErrorObject, err);
329 return newintobject((int)err);
330}
331
332static object *
333ctbcm_choose(self, args)
334 ctbcmobject *self;
335 object *args;
336{
337 int rv;
338 Point pt;
339
340 if (!getnoarg(args))
341 return NULL;
342 pt.v = 40;
343 pt.h = 40;
344 rv=CMChoose(&self->hdl, pt, (ConnectionChooseIdleUPP)0);
345 return newintobject(rv);
346}
347
348static object *
349ctbcm_idle(self, args)
350 ctbcmobject *self;
351 object *args;
352{
353 if (!getnoarg(args))
354 return NULL;
355 CMIdle(self->hdl);
356 INCREF(None);
357 return None;
358}
359
360static object *
361ctbcm_abort(self, args)
362 ctbcmobject *self;
363 object *args;
364{
365 if (!getnoarg(args))
366 return NULL;
367 CMAbort(self->hdl);
368 INCREF(None);
369 return None;
370}
371
372static object *
373ctbcm_reset(self, args)
374 ctbcmobject *self;
375 object *args;
376{
377 if (!getnoarg(args))
378 return NULL;
379 CMReset(self->hdl);
380 INCREF(None);
381 return None;
382}
383
384static object *
385ctbcm_break(self, args)
386 ctbcmobject *self;
387 object *args;
388{
389 long duration;
390 ConnectionCompletionUPP cb_upp = NewConnectionCompletionProc(ctbcm_ctbcallback);
391
392 if (!getargs(args, "l", &duration))
393 return NULL;
394 CMBreak(self->hdl, duration,self->has_callback, cb_upp);
395 INCREF(None);
396 return None;
397}
398
399static struct methodlist ctbcm_methods[] = {
400 {"Open", (method)ctbcm_open},
401 {"Close", (method)ctbcm_close},
402 {"Read", (method)ctbcm_read},
403 {"Write", (method)ctbcm_write},
404 {"Status", (method)ctbcm_status},
405 {"GetConfig", (method)ctbcm_getconfig},
406 {"SetConfig", (method)ctbcm_setconfig},
407 {"Choose", (method)ctbcm_choose},
408 {"Idle", (method)ctbcm_idle},
409 {"Listen", (method)ctbcm_listen},
410 {"Accept", (method)ctbcm_accept},
411 {"Abort", (method)ctbcm_abort},
412 {"Reset", (method)ctbcm_reset},
413 {"Break", (method)ctbcm_break},
414 {NULL, NULL} /* sentinel */
415};
416
417static object *
418ctbcm_getattr(self, name)
419 ctbcmobject *self;
420 char *name;
421{
422 if ( strcmp(name, "callback") == 0 ) {
423 INCREF(self->callback);
424 return self->callback;
425 }
426 return findmethod(ctbcm_methods, (object *)self, name);
427}
428
429static int
430ctbcm_setattr(self, name, v)
431 ctbcmobject *self;
432 char *name;
433 object *v;
434{
435 if ( strcmp(name, "callback") != 0 ) {
436 err_setstr(AttributeError, "ctbcm objects have callback attr only");
437 return -1;
438 }
439 if ( v == NULL ) {
440 v = None;
441 }
442 INCREF(v); /* XXXX Must I do this? */
443 self->callback = v;
444 self->has_callback = (v != None);
445 return 0;
446}
447
Guido van Rossum4410d571995-02-21 20:58:53 +0000448statichere typeobject ctbcmtype = {
Jack Jansenee735be1994-12-14 13:31:11 +0000449 OB_HEAD_INIT(&Typetype)
450 0, /*ob_size*/
451 "ctbcm", /*tp_name*/
452 sizeof(ctbcmobject), /*tp_basicsize*/
453 0, /*tp_itemsize*/
454 /* methods */
455 (destructor)ctbcm_dealloc, /*tp_dealloc*/
456 0, /*tp_print*/
457 (getattrfunc)ctbcm_getattr, /*tp_getattr*/
458 (setattrfunc)ctbcm_setattr, /*tp_setattr*/
459 0, /*tp_compare*/
460 0, /*tp_repr*/
461 0, /*tp_as_number*/
462 0, /*tp_as_sequence*/
463 0, /*tp_as_mapping*/
464 0, /*tp_hash*/
465};
466/* --------------------------------------------------------------------- */
467
468/* Function of no arguments returning new ctbcm object */
469
470static object *
471ctb_cmnew(self, args)
472 object *self; /* Not used */
473 object *args;
474{
475 int strlen;
476 object *sizes_obj;
477 char *c_str;
478 unsigned char p_str[255];
479 CMBufferSizes sizes;
480 short procid;
481 ConnHandle hdl;
482 ctbcmobject *rv;
483
484 if (!getargs(args, "(s#O)", &c_str, &strlen, &sizes_obj))
485 return NULL;
486 strncpy((char *)p_str+1, c_str, strlen);
487 p_str[0] = strlen;
488 if (!initialize_ctb())
489 return NULL;
490 if ( sizes_obj == None ) {
491 memset(sizes, '\0', sizeof sizes);
492 } else {
493 if ( !getargs(sizes_obj, "(llllll)", &sizes[0], &sizes[1], &sizes[2],
494 &sizes[3], &sizes[4], &sizes[5]))
495 return NULL;
496 }
497 if ( (procid=CMGetProcID(p_str)) < 0 )
498 return PyErr_Mac(ErrorObject, procid);
499 hdl = CMNew(procid, cmNoMenus|cmQuiet, sizes, 0, 0);
500 if ( hdl == NULL ) {
501 err_setstr(ErrorObject, "CMNew failed");
502 return NULL;
503 }
504 rv = newctbcmobject(args);
505 if ( rv == NULL )
506 return NULL; /* XXXX Should dispose of hdl */
507 rv->hdl = hdl;
508 CMSetUserData(hdl, (long)rv);
509 return (object *)rv;
510}
511
512static object *
513ctb_available(self, args)
514 object *self;
515 object *args;
516{
517 int ok;
518
519 if (!getnoarg(args))
520 return NULL;
521 ok = initialize_ctb();
522 err_clear();
523 return newintobject(ok);
524}
525
526/* List of functions defined in the module */
527
528static struct methodlist ctb_methods[] = {
529 {"CMNew", ctb_cmnew},
530 {"available", ctb_available},
531 {NULL, NULL} /* sentinel */
532};
533
534
535/* Initialization function for the module (*must* be called initctb) */
536
537void
538initctb()
539{
540 object *m, *d, *o;
541
542 /* Create the module and add the functions */
543 m = initmodule("ctb", ctb_methods);
544
545 /* Add some symbolic constants to the module */
546 d = getmoduledict(m);
547
548#define CMCONST(name, value) o = newintobject(value); dictinsert(d, name, o)
549
550 CMCONST("cmData", 1);
551 CMCONST("cmCntl", 2);
552 CMCONST("cmAttn", 3);
553
554 CMCONST("cmFlagsEOM", 1);
555
556 CMCONST("chooseDisaster", -2);
557 CMCONST("chooseFailed", -1);
558 CMCONST("chooseAborted", 0);
559 CMCONST("chooseOKMinor", 1);
560 CMCONST("chooseOKMajor", 2);
561 CMCONST("chooseCancel", 3);
562
563 CMCONST("cmStatusOpening", 1);
564 CMCONST("cmStatusOpen", 2);
565 CMCONST("cmStatusClosing", 4);
566 CMCONST("cmStatusDataAvail", 8);
567 CMCONST("cmStatusCntlAvail", 0x10);
568 CMCONST("cmStatusAttnAvail", 0x20);
569 CMCONST("cmStatusDRPend", 0x40);
570 CMCONST("cmStatusDWPend", 0x80);
571 CMCONST("cmStatusCWPend", 0x100);
572 CMCONST("cmStatusCWPend", 0x200);
573 CMCONST("cmStatusARPend", 0x400);
574 CMCONST("cmStatusAWPend", 0x800);
575 CMCONST("cmStatusBreakPending", 0x1000);
576 CMCONST("cmStatusListenPend", 0x2000);
577 CMCONST("cmStatusIncomingCallPresent", 0x4000);
578
579 ErrorObject = newstringobject("ctb.error");
580 dictinsert(d, "error", ErrorObject);
581
582 /* Check for errors */
583 if (err_occurred())
584 fatal("can't initialize module ctb");
585}