FS#8961 - Anti-Aliased Fonts.
[kugel-rb.git] / apps / plugins / pdbox / PDa / src / m_class.c
blob95623fd0142053268fa27204261d7c87ad3577c4
1 /* Copyright (c) 1997-1999 Miller Puckette.
2 * For information on usage and redistribution, and for a DISCLAIMER OF ALL
3 * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
5 #if 0
6 //#ifdef ROCKBOX
7 #include "plugin.h"
8 #include "pdbox.h"
9 #endif
11 #define PD_CLASS_DEF
12 #include "m_pd.h"
13 #include "m_imp.h"
14 #include "s_stuff.h"
16 #ifdef ROCKBOX
18 #include "plugin.h"
19 #include "pdbox.h"
21 #else /* ROCKBOX */
22 #include <stdlib.h>
23 #ifdef UNIX
24 #include <unistd.h>
25 #endif
26 #ifdef MSW
27 #include <io.h>
28 #endif
30 #include <stdarg.h>
31 #include <string.h>
32 #endif /* ROCKBOX */
34 static t_symbol *class_loadsym; /* name under which an extern is invoked */
35 static void pd_defaultfloat(t_pd *x, t_float f);
36 static void pd_defaultlist(t_pd *x, t_symbol *s, int argc, t_atom *argv);
37 t_pd pd_objectmaker; /* factory for creating "object" boxes */
38 t_pd pd_canvasmaker; /* factory for creating canvases */
40 static t_symbol *class_extern_dir = &s_;
42 static void pd_defaultanything(t_pd *x, t_symbol *s, int argc, t_atom *argv)
44 #ifdef ROCKBOX
45 (void) argc;
46 (void) argv;
47 #endif
48 pd_error(x, "%s: no method for '%s'", (*x)->c_name->s_name, s->s_name);
51 static void pd_defaultbang(t_pd *x)
53 if (*(*x)->c_listmethod != pd_defaultlist)
54 (*(*x)->c_listmethod)(x, 0, 0, 0);
55 else (*(*x)->c_anymethod)(x, &s_bang, 0, 0);
58 static void pd_defaultpointer(t_pd *x, t_gpointer *gp)
60 if (*(*x)->c_listmethod != pd_defaultlist)
62 t_atom at;
63 SETPOINTER(&at, gp);
64 (*(*x)->c_listmethod)(x, 0, 1, &at);
66 else
68 t_atom at;
69 SETPOINTER(&at, gp);
70 (*(*x)->c_anymethod)(x, &s_pointer, 1, &at);
74 static void pd_defaultfloat(t_pd *x, t_float f)
76 if (*(*x)->c_listmethod != pd_defaultlist)
78 t_atom at;
79 SETFLOAT(&at, f);
80 (*(*x)->c_listmethod)(x, 0, 1, &at);
82 else
84 t_atom at;
85 SETFLOAT(&at, f);
86 (*(*x)->c_anymethod)(x, &s_float, 1, &at);
90 static void pd_defaultsymbol(t_pd *x, t_symbol *s)
92 if (*(*x)->c_listmethod != pd_defaultlist)
94 t_atom at;
95 SETSYMBOL(&at, s);
96 (*(*x)->c_listmethod)(x, 0, 1, &at);
98 else
100 t_atom at;
101 SETSYMBOL(&at, s);
102 (*(*x)->c_anymethod)(x, &s_symbol, 1, &at);
106 void obj_list(t_object *x, t_symbol *s, int argc, t_atom *argv);
107 static void class_nosavefn(t_gobj *z, t_binbuf *b);
109 /* handle "list" messages to Pds without explicit list methods defined. */
110 static void pd_defaultlist(t_pd *x, t_symbol *s, int argc, t_atom *argv)
112 /* a list with one element which is a number can be handled by a
113 "float" method if any is defined; same for "symbol", "pointer". */
114 if (argc == 1)
116 if (argv->a_type == A_FLOAT &&
117 *(*x)->c_floatmethod != pd_defaultfloat)
119 (*(*x)->c_floatmethod)(x, argv->a_w.w_float);
120 return;
122 else if (argv->a_type == A_SYMBOL &&
123 *(*x)->c_symbolmethod != pd_defaultsymbol)
125 (*(*x)->c_symbolmethod)(x, argv->a_w.w_symbol);
126 return;
128 else if (argv->a_type == A_POINTER &&
129 *(*x)->c_pointermethod != pd_defaultpointer)
131 (*(*x)->c_pointermethod)(x, argv->a_w.w_gpointer);
132 return;
135 /* Next try for an "anything" method */
136 if ((*x)->c_anymethod != pd_defaultanything)
137 (*(*x)->c_anymethod)(x, &s_list, argc, argv);
139 /* if the object is patchable (i.e., can have proper inlets)
140 send it on to obj_list which will unpack the list into the inlets */
141 else if ((*x)->c_patchable)
142 obj_list((t_object *)x, s, argc, argv);
143 /* otherwise gove up and complain. */
144 else pd_defaultanything(x, &s_list, argc, argv);
147 /* for now we assume that all "gobjs" are text unless explicitly
148 overridden later by calling class_setbehavior(). I'm not sure
149 how to deal with Pds that aren't gobjs; shouldn't there be a
150 way to check that at run time? Perhaps the presence of a "newmethod"
151 should be our cue, or perhaps the "tiny" flag. */
153 /* another matter. This routine does two unrelated things: it creates
154 a Pd class, but also adds a "new" method to create an instance of it.
155 These are combined for historical reasons and for brevity in writing
156 objects. To avoid adding a "new" method send a null function pointer.
157 To add additional ones, use class_addcreator below. Some "classes", like
158 "select", are actually two classes of the same name, one for the single-
159 argument form, one for the multiple one; see select_setup() to find out
160 how this is handled. */
162 extern t_widgetbehavior text_widgetbehavior;
163 extern void text_save(t_gobj *z, t_binbuf *b);
165 t_class *class_new(t_symbol *s, t_newmethod newmethod, t_method freemethod,
166 size_t size, int flags, t_atomtype type1, ...)
168 va_list ap;
169 t_atomtype vec[MAXPDARG+1], *vp = vec;
170 int count = 0;
171 t_class *c;
172 int typeflag = flags & CLASS_TYPEMASK;
173 if (!typeflag) typeflag = CLASS_PATCHABLE;
174 *vp = type1;
176 va_start(ap, type1);
177 while (*vp)
179 if (count == MAXPDARG)
181 error("class %s: sorry: only %d creation args allowed",
182 s->s_name, MAXPDARG);
183 break;
185 vp++;
186 count++;
187 *vp = va_arg(ap, t_atomtype);
189 va_end(ap);
190 if (pd_objectmaker && newmethod)
192 /* add a "new" method by the name specified by the object */
193 class_addmethod(pd_objectmaker, (t_method)newmethod, s,
194 vec[0], vec[1], vec[2], vec[3], vec[4], vec[5]);
195 if (class_loadsym)
197 /* if we're loading an extern it might have been invoked by a
198 longer file name; in this case, make this an admissible name
199 too. */
200 char *loadstring = class_loadsym->s_name,
201 l1 = strlen(s->s_name), l2 = strlen(loadstring);
202 if (l2 > l1 && !strcmp(s->s_name, loadstring + (l2 - l1)))
203 class_addmethod(pd_objectmaker, (t_method)newmethod,
204 class_loadsym,
205 vec[0], vec[1], vec[2], vec[3], vec[4], vec[5]);
208 c = (t_class *)t_getbytes(sizeof(*c));
209 c->c_name = c->c_helpname = s;
210 c->c_size = size;
211 c->c_methods = t_getbytes(0);
212 c->c_nmethod = 0;
213 c->c_freemethod = (t_method)freemethod;
214 c->c_bangmethod = pd_defaultbang;
215 c->c_pointermethod = pd_defaultpointer;
216 c->c_floatmethod = pd_defaultfloat;
217 c->c_symbolmethod = pd_defaultsymbol;
218 c->c_listmethod = pd_defaultlist;
219 c->c_anymethod = pd_defaultanything;
220 c->c_wb = (typeflag == CLASS_PATCHABLE ? &text_widgetbehavior : 0);
221 c->c_pwb = 0;
222 c->c_firstin = ((flags & CLASS_NOINLET) == 0);
223 c->c_patchable = (typeflag == CLASS_PATCHABLE);
224 c->c_gobj = (typeflag >= CLASS_GOBJ);
225 c->c_drawcommand = 0;
226 c->c_floatsignalin = 0;
227 c->c_externdir = class_extern_dir;
228 c->c_savefn = (typeflag == CLASS_PATCHABLE ? text_save : class_nosavefn);
229 #if 0
230 post("class: %s", c->c_name->s_name);
231 #endif
232 return (c);
235 /* add a creation method, which is a function that returns a Pd object
236 suitable for putting in an object box. We presume you've got a class it
237 can belong to, but this won't be used until the newmethod is actually
238 called back (and the new method explicitly takes care of this.) */
240 void class_addcreator(t_newmethod newmethod, t_symbol *s,
241 t_atomtype type1, ...)
243 va_list ap;
244 t_atomtype vec[MAXPDARG+1], *vp = vec;
245 int count = 0;
246 *vp = type1;
248 va_start(ap, type1);
249 while (*vp)
251 if (count == MAXPDARG)
253 error("class %s: sorry: only %d creation args allowed",
254 s->s_name, MAXPDARG);
255 break;
257 vp++;
258 count++;
259 *vp = va_arg(ap, t_atomtype);
261 va_end(ap);
262 class_addmethod(pd_objectmaker, (t_method)newmethod, s,
263 vec[0], vec[1], vec[2], vec[3], vec[4], vec[5]);
266 void class_addmethod(t_class *c, t_method fn, t_symbol *sel,
267 t_atomtype arg1, ...)
269 va_list ap;
270 t_methodentry *m;
271 t_atomtype argtype = arg1;
272 int nargs;
274 va_start(ap, arg1);
275 /* "signal" method specifies that we take audio signals but
276 that we don't want automatic float to signal conversion. This
277 is obsolete; you should now use the CLASS_MAINSIGNALIN macro. */
278 if (sel == &s_signal)
280 if (c->c_floatsignalin)
281 post("warning: signal method overrides class_mainsignalin");
282 c->c_floatsignalin = -1;
284 /* check for special cases. "Pointer" is missing here so that
285 pd_objectmaker's pointer method can be typechecked differently. */
286 if (sel == &s_bang)
288 if (argtype) goto phooey;
289 class_addbang(c, fn);
291 else if (sel == &s_float)
293 if (argtype != A_FLOAT || va_arg(ap, t_atomtype)) goto phooey;
294 class_doaddfloat(c, fn);
296 else if (sel == &s_symbol)
298 if (argtype != A_SYMBOL || va_arg(ap, t_atomtype)) goto phooey;
299 class_addsymbol(c, fn);
301 else if (sel == &s_list)
303 if (argtype != A_GIMME) goto phooey;
304 class_addlist(c, fn);
306 else if (sel == &s_anything)
308 if (argtype != A_GIMME) goto phooey;
309 class_addanything(c, fn);
311 else
313 c->c_methods = t_resizebytes(c->c_methods,
314 c->c_nmethod * sizeof(*c->c_methods),
315 (c->c_nmethod + 1) * sizeof(*c->c_methods));
316 m = c->c_methods + c->c_nmethod;
317 c->c_nmethod++;
318 m->me_name = sel;
319 m->me_fun = (t_gotfn)fn;
320 nargs = 0;
321 while (argtype != A_NULL && nargs < MAXPDARG)
323 m->me_arg[nargs++] = argtype;
324 argtype = va_arg(ap, t_atomtype);
326 if (argtype != A_NULL)
327 error("%s_%s: only 5 arguments are typecheckable; use A_GIMME",
328 c->c_name->s_name, sel->s_name);
329 va_end(ap);
330 m->me_arg[nargs] = A_NULL;
332 return;
333 phooey:
334 bug("class_addmethod: %s_%s: bad argument types\n",
335 c->c_name->s_name, sel->s_name);
338 /* Instead of these, see the "class_addfloat", etc., macros in m_pd.h */
339 void class_addbang(t_class *c, t_method fn)
341 c->c_bangmethod = (t_bangmethod)fn;
344 void class_addpointer(t_class *c, t_method fn)
346 c->c_pointermethod = (t_pointermethod)fn;
349 void class_doaddfloat(t_class *c, t_method fn)
351 c->c_floatmethod = (t_floatmethod)fn;
354 void class_addsymbol(t_class *c, t_method fn)
356 c->c_symbolmethod = (t_symbolmethod)fn;
359 void class_addlist(t_class *c, t_method fn)
361 c->c_listmethod = (t_listmethod)fn;
364 void class_addanything(t_class *c, t_method fn)
366 c->c_anymethod = (t_anymethod)fn;
369 void class_setwidget(t_class *c, t_widgetbehavior *w)
371 c->c_wb = w;
374 void class_setparentwidget(t_class *c, t_parentwidgetbehavior *pw)
376 c->c_pwb = pw;
379 char *class_getname(t_class *c)
381 return (c->c_name->s_name);
384 char *class_gethelpname(t_class *c)
386 return (c->c_helpname->s_name);
389 void class_sethelpsymbol(t_class *c, t_symbol *s)
391 c->c_helpname = s;
394 t_parentwidgetbehavior *pd_getparentwidget(t_pd *x)
396 return ((*x)->c_pwb);
399 void class_setdrawcommand(t_class *c)
401 c->c_drawcommand = 1;
404 int class_isdrawcommand(t_class *c)
406 return (c->c_drawcommand);
409 static void pd_floatforsignal(t_pd *x, t_float f)
411 int offset = (*x)->c_floatsignalin;
412 if (offset > 0)
413 *(t_sample *)(((char *)x) + offset) = ftofix(f);
414 else
415 pd_error(x, "%s: float unexpected for signal input",
416 (*x)->c_name->s_name);
419 void class_domainsignalin(t_class *c, int onset)
421 if (onset <= 0) onset = -1;
422 else
424 if (c->c_floatmethod != pd_defaultfloat)
425 post("warning: %s: float method overwritten", c->c_name->s_name);
426 c->c_floatmethod = (t_floatmethod)pd_floatforsignal;
428 c->c_floatsignalin = onset;
431 void class_set_extern_dir(t_symbol *s)
433 class_extern_dir = s;
436 char *class_gethelpdir(t_class *c)
438 return (c->c_externdir->s_name);
441 static void class_nosavefn(t_gobj *z, t_binbuf *b)
443 #ifdef ROCKBOX
444 (void) z;
445 (void) b;
446 #endif
447 bug("save function called but not defined");
450 void class_setsavefn(t_class *c, t_savefn f)
452 c->c_savefn = f;
455 t_savefn class_getsavefn(t_class *c)
457 return (c->c_savefn);
460 void class_setpropertiesfn(t_class *c, t_propertiesfn f)
462 c->c_propertiesfn = f;
465 t_propertiesfn class_getpropertiesfn(t_class *c)
467 return (c->c_propertiesfn);
470 /* ---------------- the symbol table ------------------------ */
472 #define HASHSIZE 1024
474 static t_symbol *symhash[HASHSIZE];
476 t_symbol *dogensym(char *s, t_symbol *oldsym)
478 t_symbol **sym1, *sym2;
479 unsigned int hash1 = 0, hash2 = 0;
480 int length = 0;
481 char *s2 = s;
482 while (*s2)
484 hash1 += *s2;
485 hash2 += hash1;
486 length++;
487 s2++;
489 sym1 = symhash + (hash2 & (HASHSIZE-1));
490 while ((sym2 = *sym1))
492 if (!strcmp(sym2->s_name, s)) return(sym2);
493 sym1 = &sym2->s_next;
495 if (oldsym) sym2 = oldsym;
496 else
498 sym2 = (t_symbol *)t_getbytes(sizeof(*sym2));
499 sym2->s_name = t_getbytes(length+1);
500 sym2->s_next = 0;
501 sym2->s_thing = 0;
502 strcpy(sym2->s_name, s);
504 *sym1 = sym2;
505 return (sym2);
508 t_symbol *gensym(char *s)
510 // printf("gensym: %s\n", s);
511 #ifdef ROCKBOX
512 if(s == NULL)
513 return dogensym("/", 0);
514 else
515 #endif
516 return(dogensym(s, 0));
519 #ifndef ROCKBOX
520 static
521 #endif
522 t_symbol *addfileextent(t_symbol *s)
524 char namebuf[MAXPDSTRING], *str = s->s_name;
525 int ln = strlen(str);
526 if (!strcmp(str + ln - 3, ".pd")) return (s);
527 strcpy(namebuf, str);
528 strcpy(namebuf+ln, ".pd");
529 return (gensym(namebuf));
532 static int tryingalready;
534 void canvas_popabstraction(t_canvas *x);
535 extern t_pd *newest;
537 t_symbol* pathsearch(t_symbol *s,char* ext);
538 int pd_setloadingabstraction(t_symbol *sym);
540 /* this routine is called when a new "object" is requested whose class Pd
541 doesn't know. Pd tries to load it as an extern, then as an abstraction. */
542 void new_anything(void *dummy, t_symbol *s, int argc, t_atom *argv)
544 t_pd *current;
545 t_symbol *dir = canvas_getcurrentdir();
546 int fd;
547 char dirbuf[MAXPDSTRING], *nameptr;
548 if (tryingalready) return;
549 newest = 0;
550 class_loadsym = s;
551 if (sys_load_lib(dir->s_name, s->s_name))
553 tryingalready = 1;
554 typedmess(dummy, s, argc, argv);
555 tryingalready = 0;
556 return;
558 class_loadsym = 0;
559 current = s__X.s_thing;
560 if ((fd = open_via_path(dir->s_name, s->s_name, ".pd",
561 dirbuf, &nameptr, MAXPDSTRING, 0)) >= 0 ||
562 (fd = open_via_path(dir->s_name, s->s_name, ".pat",
563 dirbuf, &nameptr, MAXPDSTRING, 0)) >= 0)
565 close (fd);
566 if (!pd_setloadingabstraction(s))
568 canvas_setargs(argc, argv); /* bug fix by Krzysztof Czaja */
569 binbuf_evalfile(gensym(nameptr), gensym(dirbuf));
570 if (s__X.s_thing != current)
571 canvas_popabstraction((t_canvas *)(s__X.s_thing));
572 canvas_setargs(0, 0);
574 else error("%s: can't load abstraction within itself\n", s->s_name);
576 else newest = 0;
579 t_symbol s_pointer = {"pointer", 0, 0};
580 t_symbol s_float = {"float", 0, 0};
581 t_symbol s_symbol = {"symbol", 0, 0};
582 t_symbol s_bang = {"bang", 0, 0};
583 t_symbol s_list = {"list", 0, 0};
584 t_symbol s_anything = {"anything", 0, 0};
585 t_symbol s_signal = {"signal", 0, 0};
586 t_symbol s__N = {"#N", 0, 0};
587 t_symbol s__X = {"#X", 0, 0};
588 t_symbol s_x = {"x", 0, 0};
589 t_symbol s_y = {"y", 0, 0};
590 t_symbol s_ = {"", 0, 0};
592 static t_symbol *symlist[] = { &s_pointer, &s_float, &s_symbol, &s_bang,
593 &s_list, &s_anything, &s_signal, &s__N, &s__X, &s_x, &s_y, &s_};
595 void mess_init(void)
597 t_symbol **sp;
598 int i;
600 if (pd_objectmaker) return;
601 for (i = sizeof(symlist)/sizeof(*symlist), sp = symlist; i--; sp++)
602 (void) dogensym((*sp)->s_name, *sp);
603 pd_objectmaker = class_new(gensym("objectmaker"), 0, 0, sizeof(t_pd),
604 CLASS_DEFAULT, A_NULL);
605 pd_canvasmaker = class_new(gensym("classmaker"), 0, 0, sizeof(t_pd),
606 CLASS_DEFAULT, A_NULL);
607 pd_bind(&pd_canvasmaker, &s__N);
608 class_addanything(pd_objectmaker, (t_method)new_anything);
611 t_pd *newest;
613 /* This is externally available, but note that it might later disappear; the
614 whole "newest" thing is a hack which needs to be redesigned. */
615 t_pd *pd_newest(void)
617 return (newest);
620 /* horribly, we need prototypes for each of the artificial function
621 calls in typedmess(), to keep the compiler quiet. */
622 typedef t_pd *(*t_newgimme)(t_symbol *s, int argc, t_atom *argv);
623 typedef void(*t_messgimme)(t_pd *x, t_symbol *s, int argc, t_atom *argv);
625 typedef t_pd *(*t_fun0)(
626 t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5);
627 typedef t_pd *(*t_fun1)(t_int i1,
628 t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5);
629 typedef t_pd *(*t_fun2)(t_int i1, t_int i2,
630 t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5);
631 typedef t_pd *(*t_fun3)(t_int i1, t_int i2, t_int i3,
632 t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5);
633 typedef t_pd *(*t_fun4)(t_int i1, t_int i2, t_int i3, t_int i4,
634 t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5);
635 typedef t_pd *(*t_fun5)(t_int i1, t_int i2, t_int i3, t_int i4, t_int i5,
636 t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5);
637 typedef t_pd *(*t_fun6)(t_int i1, t_int i2, t_int i3, t_int i4, t_int i5, t_int i6,
638 t_floatarg d1, t_floatarg d2, t_floatarg d3, t_floatarg d4, t_floatarg d5);
640 void pd_typedmess(t_pd *x, t_symbol *s, int argc, t_atom *argv)
642 #ifndef ROCKBOX
643 t_method *f;
644 #endif
645 t_class *c = *x;
646 t_methodentry *m;
647 t_atomtype *wp, wanttype;
648 int i;
649 t_int ai[MAXPDARG+1], *ap = ai;
650 t_floatarg ad[MAXPDARG+1], *dp = ad;
651 int narg = 0;
652 t_pd *bonzo;
654 /* check for messages that are handled by fixed slots in the class
655 structure. We don't catch "pointer" though so that sending "pointer"
656 to pd_objectmaker doesn't require that we supply a pointer value. */
657 if (s == &s_float)
659 if (!argc) (*c->c_floatmethod)(x, 0.);
660 else if (argv->a_type == A_FLOAT)
661 (*c->c_floatmethod)(x, argv->a_w.w_float);
662 else goto badarg;
663 return;
665 if (s == &s_bang)
667 (*c->c_bangmethod)(x);
668 return;
670 if (s == &s_list)
672 (*c->c_listmethod)(x, s, argc, argv);
673 return;
675 if (s == &s_symbol)
677 if (argc && argv->a_type == A_SYMBOL)
678 (*c->c_symbolmethod)(x, argv->a_w.w_symbol);
679 else
680 (*c->c_symbolmethod)(x, &s_);
681 return;
683 for (i = c->c_nmethod, m = c->c_methods; i--; m++)
684 if (m->me_name == s)
686 wp = m->me_arg;
687 if (*wp == A_GIMME)
689 if (x == &pd_objectmaker)
690 newest = (*((t_newgimme)(m->me_fun)))(s, argc, argv);
691 else (*((t_messgimme)(m->me_fun)))(x, s, argc, argv);
692 return;
695 if (argc > MAXPDARG) argc = MAXPDARG;
696 if (x != &pd_objectmaker) *(ap++) = (t_int)x, narg++;
697 while((wanttype = *wp++))
699 switch (wanttype)
701 case A_POINTER:
702 if (!argc) goto badarg;
703 else
705 if (argv->a_type == A_POINTER)
706 *ap = (t_int)(argv->a_w.w_gpointer);
707 else goto badarg;
708 argc--;
709 argv++;
711 narg++;
712 ap++;
713 break;
714 case A_FLOAT:
715 if (!argc) goto badarg;
716 case A_DEFFLOAT:
717 if (!argc) *dp = 0;
718 else
720 if (argv->a_type == A_FLOAT)
721 *dp = argv->a_w.w_float;
722 else goto badarg;
723 argc--;
724 argv++;
726 dp++;
727 break;
728 case A_SYMBOL:
729 if (!argc) goto badarg;
730 case A_DEFSYM:
731 if (!argc) *ap = (t_int)(&s_);
732 else
734 if (argv->a_type == A_SYMBOL)
735 *ap = (t_int)(argv->a_w.w_symbol);
736 /* if it's an unfilled "dollar" argument it appears
737 as zero here; cheat and bash it to the null
738 symbol. Unfortunately, this lets real zeros
739 pass as symbols too, which seems wrong... */
740 else if (x == &pd_objectmaker && argv->a_type == A_FLOAT
741 && argv->a_w.w_float == 0)
742 *ap = (t_int)(&s_);
743 else goto badarg;
744 argc--;
745 argv++;
747 narg++;
748 ap++;
749 #ifdef ROCKBOX
750 break;
751 default:
752 break;
753 #endif
756 switch (narg)
758 case 0 : bonzo = (*(t_fun0)(m->me_fun))
759 (ad[0], ad[1], ad[2], ad[3], ad[4]); break;
760 case 1 : bonzo = (*(t_fun1)(m->me_fun))
761 (ai[0], ad[0], ad[1], ad[2], ad[3], ad[4]); break;
762 case 2 : bonzo = (*(t_fun2)(m->me_fun))
763 (ai[0], ai[1], ad[0], ad[1], ad[2], ad[3], ad[4]); break;
764 case 3 : bonzo = (*(t_fun3)(m->me_fun))
765 (ai[0], ai[1], ai[2], ad[0], ad[1], ad[2], ad[3], ad[4]); break;
766 case 4 : bonzo = (*(t_fun4)(m->me_fun))
767 (ai[0], ai[1], ai[2], ai[3],
768 ad[0], ad[1], ad[2], ad[3], ad[4]); break;
769 case 5 : bonzo = (*(t_fun5)(m->me_fun))
770 (ai[0], ai[1], ai[2], ai[3], ai[4],
771 ad[0], ad[1], ad[2], ad[3], ad[4]); break;
772 case 6 : bonzo = (*(t_fun6)(m->me_fun))
773 (ai[0], ai[1], ai[2], ai[3], ai[4], ai[5],
774 ad[0], ad[1], ad[2], ad[3], ad[4]); break;
775 default: bonzo = 0;
777 if (x == &pd_objectmaker)
778 newest = bonzo;
779 return;
781 (*c->c_anymethod)(x, s, argc, argv);
782 return;
783 badarg:
784 pd_error(x, "Bad arguments for message '%s' to object '%s'",
785 s->s_name, c->c_name->s_name);
788 void pd_vmess(t_pd *x, t_symbol *sel, char *fmt, ...)
790 va_list ap;
791 t_atom arg[MAXPDARG], *at =arg;
792 int nargs = 0;
793 char *fp = fmt;
795 va_start(ap, fmt);
796 while (1)
798 if (nargs > MAXPDARG)
800 pd_error(x, "pd_vmess: only %d allowed", MAXPDARG);
801 break;
803 switch(*fp++)
805 case 'f': SETFLOAT(at, va_arg(ap, double)); break;
806 case 's': SETSYMBOL(at, va_arg(ap, t_symbol *)); break;
807 case 'i': SETFLOAT(at, va_arg(ap, t_int)); break;
808 case 'p': SETPOINTER(at, va_arg(ap, t_gpointer *)); break;
809 default: goto done;
811 at++;
812 nargs++;
814 done:
815 va_end(ap);
816 typedmess(x, sel, nargs, arg);
819 void pd_forwardmess(t_pd *x, int argc, t_atom *argv)
821 if (argc)
823 t_atomtype t = argv->a_type;
824 if (t == A_SYMBOL) pd_typedmess(x, argv->a_w.w_symbol, argc-1, argv+1);
825 else if (t == A_POINTER)
827 if (argc == 1) pd_pointer(x, argv->a_w.w_gpointer);
828 else pd_list(x, &s_list, argc, argv);
830 else if (t == A_FLOAT)
832 if (argc == 1) pd_float(x, argv->a_w.w_float);
833 else pd_list(x, &s_list, argc, argv);
835 else bug("pd_forwardmess");
840 void nullfn(void) {}
842 t_gotfn getfn(t_pd *x, t_symbol *s)
844 t_class *c = *x;
845 t_methodentry *m;
846 int i;
848 for (i = c->c_nmethod, m = c->c_methods; i--; m++)
849 if (m->me_name == s) return(m->me_fun);
850 pd_error(x, "%s: no method for message '%s'", c->c_name->s_name, s->s_name);
851 return((t_gotfn)nullfn);
854 t_gotfn zgetfn(t_pd *x, t_symbol *s)
856 t_class *c = *x;
857 t_methodentry *m;
858 int i;
860 for (i = c->c_nmethod, m = c->c_methods; i--; m++)
861 if (m->me_name == s) return(m->me_fun);
862 return(0);