diff options
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/g_traversal.c')
-rw-r--r-- | apps/plugins/pdbox/PDa/src/g_traversal.c | 1083 |
1 files changed, 0 insertions, 1083 deletions
diff --git a/apps/plugins/pdbox/PDa/src/g_traversal.c b/apps/plugins/pdbox/PDa/src/g_traversal.c index 2a34f5c1e6..0e2c6855b4 100644 --- a/apps/plugins/pdbox/PDa/src/g_traversal.c +++ b/apps/plugins/pdbox/PDa/src/g_traversal.c | |||
@@ -1082,1087 +1082,4 @@ void g_traversal_setup(void) | |||
1082 | append_setup(); | 1082 | append_setup(); |
1083 | sublist_setup(); | 1083 | sublist_setup(); |
1084 | } | 1084 | } |
1085 | /* Copyright (c) 1997-1999 Miller Puckette. | ||
1086 | * For information on usage and redistribution, and for a DISCLAIMER OF ALL | ||
1087 | * WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ | ||
1088 | |||
1089 | /* This file defines Text objects which traverse data contained in scalars | ||
1090 | and arrays: | ||
1091 | |||
1092 | pointer - point to an object belonging to a template | ||
1093 | get - get numeric fields | ||
1094 | set - change numeric fields | ||
1095 | element - get an array element | ||
1096 | getsize - get the size of an array | ||
1097 | setsize - change the size of an array | ||
1098 | append - add an element to a list | ||
1099 | sublist - get a pointer into a list which is an element of another scalar | ||
1100 | |||
1101 | */ | ||
1102 | |||
1103 | #include <stdlib.h> | ||
1104 | #include <string.h> | ||
1105 | #include <stdio.h> /* for read/write to files */ | ||
1106 | #include "m_pd.h" | ||
1107 | #include "g_canvas.h" | ||
1108 | |||
1109 | /* ------------- gstubs and gpointers - safe pointing --------------- */ | ||
1110 | |||
1111 | /* create a gstub which is "owned" by a glist (gl) or an array ("a"). */ | ||
1112 | |||
1113 | t_gstub *gstub_new(t_glist *gl, t_array *a) | ||
1114 | { | ||
1115 | t_gstub *gs = t_getbytes(sizeof(*gs)); | ||
1116 | if (gl) | ||
1117 | { | ||
1118 | gs->gs_which = GP_GLIST; | ||
1119 | gs->gs_un.gs_glist = gl; | ||
1120 | } | ||
1121 | else | ||
1122 | { | ||
1123 | gs->gs_which = GP_ARRAY; | ||
1124 | gs->gs_un.gs_array = a; | ||
1125 | } | ||
1126 | gs->gs_refcount = 0; | ||
1127 | return (gs); | ||
1128 | } | ||
1129 | |||
1130 | /* when a "gpointer" is set to point to this stub (so we can later chase | ||
1131 | down the owner) we increase a reference count. The following routine is called | ||
1132 | whenever a gpointer is unset from pointing here. If the owner is | ||
1133 | gone and the refcount goes to zero, we can free the gstub safely. */ | ||
1134 | |||
1135 | static void gstub_dis(t_gstub *gs) | ||
1136 | { | ||
1137 | int refcount = --gs->gs_refcount; | ||
1138 | if ((!refcount) && gs->gs_which == GP_NONE) | ||
1139 | t_freebytes(gs, sizeof (*gs)); | ||
1140 | else if (refcount < 0) bug("gstub_dis"); | ||
1141 | } | ||
1142 | |||
1143 | /* this routing is called by the owner to inform the gstub that it is | ||
1144 | being deleted. If no gpointers are pointing here, we can free the gstub; | ||
1145 | otherwise we wait for the last gstub_dis() to free it. */ | ||
1146 | |||
1147 | void gstub_cutoff(t_gstub *gs) | ||
1148 | { | ||
1149 | gs->gs_which = GP_NONE; | ||
1150 | if (gs->gs_refcount < 0) bug("gstub_cutoff"); | ||
1151 | if (!gs->gs_refcount) t_freebytes(gs, sizeof (*gs)); | ||
1152 | } | ||
1153 | |||
1154 | /* call this to verify that a pointer is fresh, i.e., that it either | ||
1155 | points to real data or to the head of a list, and that in either case | ||
1156 | the object hasn't disappeared since this pointer was generated. | ||
1157 | Unless "headok" is set, the routine also fails for the head of a list. */ | ||
1158 | |||
1159 | int gpointer_check(const t_gpointer *gp, int headok) | ||
1160 | { | ||
1161 | t_gstub *gs = gp->gp_stub; | ||
1162 | if (!gs) return (0); | ||
1163 | if (gs->gs_which == GP_ARRAY) | ||
1164 | { | ||
1165 | if (gs->gs_un.gs_array->a_valid != gp->gp_valid) return (0); | ||
1166 | else return (1); | ||
1167 | } | ||
1168 | else if (gs->gs_which == GP_GLIST) | ||
1169 | { | ||
1170 | if (!headok && !gp->gp_un.gp_scalar) return (0); | ||
1171 | else if (gs->gs_un.gs_glist->gl_valid != gp->gp_valid) return (0); | ||
1172 | else return (1); | ||
1173 | } | ||
1174 | else return (0); | ||
1175 | } | ||
1176 | |||
1177 | /* call this if you know the pointer is fresh but don't know if we're pointing | ||
1178 | to the head of a list or to real data. Any pointer is known to be fresh | ||
1179 | when it appears as the argument of a message, but if your "pointer" method | ||
1180 | or inlet stores it and you use it later, call gpointer_check above. */ | ||
1181 | |||
1182 | /* LATER reconsider the above... I no longer think it's true! */ | ||
1183 | |||
1184 | static int gpointer_ishead(const t_gpointer *gp) | ||
1185 | { | ||
1186 | return ((gp->gp_stub->gs_which == GP_GLIST) && !gp->gp_un.gp_scalar); | ||
1187 | } | ||
1188 | |||
1189 | /* get the template for the object pointer to. Assumes we've already checked | ||
1190 | freshness. Returns 0 if head of list. */ | ||
1191 | |||
1192 | static t_symbol *gpointer_gettemplatesym(const t_gpointer *gp) | ||
1193 | { | ||
1194 | t_gstub *gs = gp->gp_stub; | ||
1195 | if (gs->gs_which == GP_GLIST) | ||
1196 | { | ||
1197 | t_scalar *sc = gp->gp_un.gp_scalar; | ||
1198 | if (sc) | ||
1199 | return (sc->sc_template); | ||
1200 | else return (0); | ||
1201 | } | ||
1202 | else | ||
1203 | { | ||
1204 | t_array *a = gs->gs_un.gs_array; | ||
1205 | return (a->a_templatesym); | ||
1206 | } | ||
1207 | } | ||
1208 | |||
1209 | /* copy a pointer to another, assuming the first one is fresh and | ||
1210 | the second one hasn't yet been initialized. */ | ||
1211 | void gpointer_copy(const t_gpointer *gpfrom, t_gpointer *gpto) | ||
1212 | { | ||
1213 | *gpto = *gpfrom; | ||
1214 | if (gpto->gp_stub) | ||
1215 | gpto->gp_stub->gs_refcount++; | ||
1216 | else bug("gpointer_copy"); | ||
1217 | } | ||
1218 | |||
1219 | void gpointer_unset(t_gpointer *gp) | ||
1220 | { | ||
1221 | t_gstub *gs; | ||
1222 | if (gs = gp->gp_stub) | ||
1223 | { | ||
1224 | gstub_dis(gs); | ||
1225 | gp->gp_stub = 0; | ||
1226 | } | ||
1227 | } | ||
1228 | |||
1229 | void gpointer_setglist(t_gpointer *gp, t_glist *glist, t_scalar *x) | ||
1230 | { | ||
1231 | t_gstub *gs; | ||
1232 | if (gs = gp->gp_stub) gstub_dis(gs); | ||
1233 | gp->gp_stub = gs = glist->gl_stub; | ||
1234 | gp->gp_valid = glist->gl_valid; | ||
1235 | gp->gp_un.gp_scalar = x; | ||
1236 | gs->gs_refcount++; | ||
1237 | } | ||
1238 | |||
1239 | static void gpointer_setarray(t_gpointer *gp, t_array *array, t_word *w) | ||
1240 | { | ||
1241 | t_gstub *gs; | ||
1242 | if (gs = gp->gp_stub) gstub_dis(gs); | ||
1243 | gp->gp_stub = gs = array->a_stub; | ||
1244 | gp->gp_valid = array->a_valid; | ||
1245 | gp->gp_un.gp_w = w; | ||
1246 | gs->gs_refcount++; | ||
1247 | } | ||
1248 | |||
1249 | void gpointer_init(t_gpointer *gp) | ||
1250 | { | ||
1251 | gp->gp_stub = 0; | ||
1252 | gp->gp_valid = 0; | ||
1253 | gp->gp_un.gp_scalar = 0; | ||
1254 | } | ||
1255 | |||
1256 | /* ---------------------- pointers ----------------------------- */ | ||
1257 | |||
1258 | static t_class *ptrobj_class; | ||
1259 | |||
1260 | typedef struct | ||
1261 | { | ||
1262 | t_symbol *to_type; | ||
1263 | t_outlet *to_outlet; | ||
1264 | } t_typedout; | ||
1265 | |||
1266 | typedef struct _ptrobj | ||
1267 | { | ||
1268 | t_object x_obj; | ||
1269 | t_gpointer x_gp; | ||
1270 | t_typedout *x_typedout; | ||
1271 | int x_ntypedout; | ||
1272 | t_outlet *x_otherout; | ||
1273 | t_outlet *x_bangout; | ||
1274 | } t_ptrobj; | ||
1275 | |||
1276 | static void *ptrobj_new(t_symbol *classname, int argc, t_atom *argv) | ||
1277 | { | ||
1278 | t_ptrobj *x = (t_ptrobj *)pd_new(ptrobj_class); | ||
1279 | t_typedout *to; | ||
1280 | int n; | ||
1281 | gpointer_init(&x->x_gp); | ||
1282 | x->x_typedout = to = (t_typedout *)getbytes(argc * sizeof (*to)); | ||
1283 | x->x_ntypedout = n = argc; | ||
1284 | for (; n--; to++) | ||
1285 | { | ||
1286 | to->to_outlet = outlet_new(&x->x_obj, &s_pointer); | ||
1287 | to->to_type = canvas_makebindsym(atom_getsymbol(argv++)); | ||
1288 | } | ||
1289 | x->x_otherout = outlet_new(&x->x_obj, &s_pointer); | ||
1290 | x->x_bangout = outlet_new(&x->x_obj, &s_bang); | ||
1291 | pointerinlet_new(&x->x_obj, &x->x_gp); | ||
1292 | return (x); | ||
1293 | } | ||
1294 | |||
1295 | static void ptrobj_traverse(t_ptrobj *x, t_symbol *s) | ||
1296 | { | ||
1297 | t_glist *glist = (t_glist *)pd_findbyclass(s, canvas_class); | ||
1298 | if (glist) gpointer_setglist(&x->x_gp, glist, 0); | ||
1299 | else pd_error(x, "pointer: list '%s' not found", s->s_name); | ||
1300 | } | ||
1301 | |||
1302 | static void ptrobj_vnext(t_ptrobj *x, float f) | ||
1303 | { | ||
1304 | t_gobj *gobj; | ||
1305 | t_gpointer *gp = &x->x_gp; | ||
1306 | t_gstub *gs = gp->gp_stub; | ||
1307 | t_glist *glist; | ||
1308 | int wantselected = (f != 0); | ||
1309 | |||
1310 | if (!gs) | ||
1311 | { | ||
1312 | pd_error(x, "ptrobj_next: no current pointer"); | ||
1313 | return; | ||
1314 | } | ||
1315 | if (gs->gs_which != GP_GLIST) | ||
1316 | { | ||
1317 | pd_error(x, "ptrobj_next: lists only, not arrays"); | ||
1318 | return; | ||
1319 | } | ||
1320 | glist = gs->gs_un.gs_glist; | ||
1321 | if (glist->gl_valid != gp->gp_valid) | ||
1322 | { | ||
1323 | pd_error(x, "ptrobj_next: stale pointer"); | ||
1324 | return; | ||
1325 | } | ||
1326 | if (wantselected && !glist_isvisible(glist)) | ||
1327 | { | ||
1328 | pd_error(x, | ||
1329 | "ptrobj_vnext: next-selected only works for a visible window"); | ||
1330 | return; | ||
1331 | } | ||
1332 | gobj = &gp->gp_un.gp_scalar->sc_gobj; | ||
1333 | |||
1334 | if (!gobj) gobj = glist->gl_list; | ||
1335 | else gobj = gobj->g_next; | ||
1336 | while (gobj && ((pd_class(&gobj->g_pd) != scalar_class) || | ||
1337 | (wantselected && !glist_isselected(glist, gobj)))) | ||
1338 | gobj = gobj->g_next; | ||
1339 | |||
1340 | if (gobj) | ||
1341 | { | ||
1342 | t_typedout *to; | ||
1343 | int n; | ||
1344 | t_scalar *sc = (t_scalar *)gobj; | ||
1345 | t_symbol *templatesym = sc->sc_template; | ||
1346 | |||
1347 | gp->gp_un.gp_scalar = sc; | ||
1348 | for (n = x->x_ntypedout, to = x->x_typedout; n--; to++) | ||
1349 | { | ||
1350 | if (to->to_type == templatesym) | ||
1351 | { | ||
1352 | outlet_pointer(to->to_outlet, &x->x_gp); | ||
1353 | return; | ||
1354 | } | ||
1355 | } | ||
1356 | outlet_pointer(x->x_otherout, &x->x_gp); | ||
1357 | } | ||
1358 | else | ||
1359 | { | ||
1360 | gpointer_unset(gp); | ||
1361 | outlet_bang(x->x_bangout); | ||
1362 | } | ||
1363 | } | ||
1364 | |||
1365 | static void ptrobj_next(t_ptrobj *x) | ||
1366 | { | ||
1367 | ptrobj_vnext(x, 0); | ||
1368 | } | ||
1369 | |||
1370 | static void ptrobj_sendwindow(t_ptrobj *x, t_symbol *s, int argc, t_atom *argv) | ||
1371 | { | ||
1372 | t_scalar *sc; | ||
1373 | t_symbol *templatesym; | ||
1374 | int n; | ||
1375 | t_typedout *to; | ||
1376 | t_glist *glist; | ||
1377 | t_pd *canvas; | ||
1378 | t_gstub *gs; | ||
1379 | if (!gpointer_check(&x->x_gp, 1)) | ||
1380 | { | ||
1381 | pd_error(x, "ptrobj_bang: empty pointer"); | ||
1382 | return; | ||
1383 | } | ||
1384 | gs = x->x_gp.gp_stub; | ||
1385 | if (gs->gs_which == GP_GLIST) | ||
1386 | glist = gs->gs_un.gs_glist; | ||
1387 | else | ||
1388 | { | ||
1389 | t_array *owner_array = gs->gs_un.gs_array; | ||
1390 | while (owner_array->a_gp.gp_stub->gs_which == GP_ARRAY) | ||
1391 | owner_array = owner_array->a_gp.gp_stub->gs_un.gs_array; | ||
1392 | glist = owner_array->a_gp.gp_stub->gs_un.gs_glist; | ||
1393 | } | ||
1394 | canvas = (t_pd *)glist_getcanvas(glist); | ||
1395 | if (argc && argv->a_type == A_SYMBOL) | ||
1396 | pd_typedmess(canvas, argv->a_w.w_symbol, argc-1, argv+1); | ||
1397 | else pd_error(x, "send-window: no message?"); | ||
1398 | } | ||
1399 | |||
1400 | static void ptrobj_bang(t_ptrobj *x) | ||
1401 | { | ||
1402 | t_symbol *templatesym; | ||
1403 | int n; | ||
1404 | t_typedout *to; | ||
1405 | if (!gpointer_check(&x->x_gp, 1)) | ||
1406 | { | ||
1407 | pd_error(x, "ptrobj_bang: empty pointer"); | ||
1408 | return; | ||
1409 | } | ||
1410 | templatesym = gpointer_gettemplatesym(&x->x_gp); | ||
1411 | for (n = x->x_ntypedout, to = x->x_typedout; n--; to++) | ||
1412 | { | ||
1413 | if (to->to_type == templatesym) | ||
1414 | { | ||
1415 | outlet_pointer(to->to_outlet, &x->x_gp); | ||
1416 | return; | ||
1417 | } | ||
1418 | } | ||
1419 | outlet_pointer(x->x_otherout, &x->x_gp); | ||
1420 | } | ||
1421 | |||
1422 | |||
1423 | static void ptrobj_pointer(t_ptrobj *x, t_gpointer *gp) | ||
1424 | { | ||
1425 | gpointer_unset(&x->x_gp); | ||
1426 | gpointer_copy(gp, &x->x_gp); | ||
1427 | ptrobj_bang(x); | ||
1428 | } | ||
1429 | |||
1430 | static void ptrobj_free(t_ptrobj *x) | ||
1431 | { | ||
1432 | freebytes(x->x_typedout, x->x_ntypedout * sizeof (*x->x_typedout)); | ||
1433 | gpointer_unset(&x->x_gp); | ||
1434 | } | ||
1435 | |||
1436 | static void ptrobj_setup(void) | ||
1437 | { | ||
1438 | ptrobj_class = class_new(gensym("pointer"), (t_newmethod)ptrobj_new, | ||
1439 | (t_method)ptrobj_free, sizeof(t_ptrobj), 0, A_GIMME, 0); | ||
1440 | class_addmethod(ptrobj_class, (t_method)ptrobj_traverse, gensym("traverse"), | ||
1441 | A_SYMBOL, 0); | ||
1442 | class_addmethod(ptrobj_class, (t_method)ptrobj_next, gensym("next"), 0); | ||
1443 | class_addmethod(ptrobj_class, (t_method)ptrobj_vnext, gensym("vnext"), | ||
1444 | A_DEFFLOAT, 0); | ||
1445 | class_addmethod(ptrobj_class, (t_method)ptrobj_sendwindow, | ||
1446 | gensym("send-window"), A_GIMME, 0); | ||
1447 | class_addpointer(ptrobj_class, ptrobj_pointer); | ||
1448 | class_addbang(ptrobj_class, ptrobj_bang); | ||
1449 | } | ||
1450 | |||
1451 | /* ---------------------- get ----------------------------- */ | ||
1452 | |||
1453 | static t_class *get_class; | ||
1454 | |||
1455 | typedef struct _getvariable | ||
1456 | { | ||
1457 | t_symbol *gv_sym; | ||
1458 | t_outlet *gv_outlet; | ||
1459 | } t_getvariable; | ||
1460 | |||
1461 | typedef struct _get | ||
1462 | { | ||
1463 | t_object x_obj; | ||
1464 | t_symbol *x_templatesym; | ||
1465 | int x_nout; | ||
1466 | t_getvariable *x_variables; | ||
1467 | } t_get; | ||
1468 | |||
1469 | static void *get_new(t_symbol *why, int argc, t_atom *argv) | ||
1470 | { | ||
1471 | t_get *x = (t_get *)pd_new(get_class); | ||
1472 | int i; | ||
1473 | t_getvariable *sp; | ||
1474 | x->x_templatesym = canvas_makebindsym(atom_getsymbolarg(0, argc, argv)); | ||
1475 | if (argc) argc--, argv++; | ||
1476 | x->x_variables | ||
1477 | = (t_getvariable *)getbytes(argc * sizeof (*x->x_variables)); | ||
1478 | x->x_nout = argc; | ||
1479 | for (i = 0, sp = x->x_variables; i < argc; i++, sp++) | ||
1480 | { | ||
1481 | sp->gv_sym = atom_getsymbolarg(i, argc, argv); | ||
1482 | sp->gv_outlet = outlet_new(&x->x_obj, 0); | ||
1483 | /* LATER connect with the template and set the outlet's type | ||
1484 | correctly. We can't yet guarantee that the template is there | ||
1485 | before we hit this routine. */ | ||
1486 | } | ||
1487 | return (x); | ||
1488 | } | ||
1489 | 1085 | ||
1490 | static void get_pointer(t_get *x, t_gpointer *gp) | ||
1491 | { | ||
1492 | int nitems = x->x_nout, i; | ||
1493 | t_symbol *templatesym = x->x_templatesym; | ||
1494 | t_template *template = template_findbyname(templatesym); | ||
1495 | t_gstub *gs = gp->gp_stub; | ||
1496 | t_word *vec; | ||
1497 | t_getvariable *vp; | ||
1498 | if (!template) | ||
1499 | { | ||
1500 | pd_error(x, "get: couldn't find template %s", templatesym->s_name); | ||
1501 | return; | ||
1502 | } | ||
1503 | if (gpointer_ishead(gp)) | ||
1504 | { | ||
1505 | pd_error(x, "get: empty pointer"); | ||
1506 | return; | ||
1507 | } | ||
1508 | if (gs->gs_which == GP_ARRAY) vec = gp->gp_un.gp_w; | ||
1509 | else vec = gp->gp_un.gp_scalar->sc_vec; | ||
1510 | for (i = nitems - 1, vp = x->x_variables + i; i >= 0; i--, vp--) | ||
1511 | { | ||
1512 | float f = template_getfloat(template, vp->gv_sym, vec, 1); | ||
1513 | outlet_float(vp->gv_outlet, f); | ||
1514 | /* LATER deal with other types. */ | ||
1515 | } | ||
1516 | } | ||
1517 | |||
1518 | static void get_free(t_get *x) | ||
1519 | { | ||
1520 | freebytes(x->x_variables, x->x_nout * sizeof (*x->x_variables)); | ||
1521 | } | ||
1522 | |||
1523 | static void get_setup(void) | ||
1524 | { | ||
1525 | get_class = class_new(gensym("get"), (t_newmethod)get_new, | ||
1526 | (t_method)get_free, sizeof(t_get), 0, A_GIMME, 0); | ||
1527 | class_addpointer(get_class, get_pointer); | ||
1528 | } | ||
1529 | |||
1530 | /* ---------------------- set ----------------------------- */ | ||
1531 | |||
1532 | static t_class *set_class; | ||
1533 | |||
1534 | typedef struct _setvariable | ||
1535 | { | ||
1536 | t_symbol *gv_sym; | ||
1537 | t_float gv_f; /* LATER take other types */ | ||
1538 | } t_setvariable; | ||
1539 | |||
1540 | typedef struct _set | ||
1541 | { | ||
1542 | t_object x_obj; | ||
1543 | t_gpointer x_gp; | ||
1544 | t_symbol *x_templatesym; | ||
1545 | int x_nin; | ||
1546 | t_setvariable *x_variables; | ||
1547 | } t_set; | ||
1548 | |||
1549 | static void *set_new(t_symbol *why, int argc, t_atom *argv) | ||
1550 | { | ||
1551 | t_set *x = (t_set *)pd_new(set_class); | ||
1552 | int i; | ||
1553 | t_setvariable *sp; | ||
1554 | x->x_templatesym = canvas_makebindsym(atom_getsymbolarg(0, argc, argv)); | ||
1555 | if (argc) argc--, argv++; | ||
1556 | x->x_variables | ||
1557 | = (t_setvariable *)getbytes(argc * sizeof (*x->x_variables)); | ||
1558 | x->x_nin = argc; | ||
1559 | if (argc) | ||
1560 | { | ||
1561 | for (i = 0, sp = x->x_variables; i < argc; i++, sp++) | ||
1562 | { | ||
1563 | sp->gv_sym = atom_getsymbolarg(i, argc, argv); | ||
1564 | sp->gv_f = 0; | ||
1565 | if (i) floatinlet_new(&x->x_obj, &sp->gv_f); | ||
1566 | /* LATER figure out type as in "get" object. */ | ||
1567 | } | ||
1568 | } | ||
1569 | pointerinlet_new(&x->x_obj, &x->x_gp); | ||
1570 | gpointer_init(&x->x_gp); | ||
1571 | return (x); | ||
1572 | } | ||
1573 | |||
1574 | static void set_float(t_set *x, t_float f) | ||
1575 | { | ||
1576 | int nitems = x->x_nin, i; | ||
1577 | t_symbol *templatesym = x->x_templatesym; | ||
1578 | t_template *template = template_findbyname(templatesym); | ||
1579 | t_setvariable *vp; | ||
1580 | t_gpointer *gp = &x->x_gp; | ||
1581 | t_gstub *gs = gp->gp_stub; | ||
1582 | t_word *vec; | ||
1583 | if (!template) | ||
1584 | { | ||
1585 | pd_error(x, "set: couldn't find template %s", templatesym->s_name); | ||
1586 | return; | ||
1587 | } | ||
1588 | if (!gpointer_check(gp, 0)) | ||
1589 | { | ||
1590 | pd_error(x, "set: empty pointer"); | ||
1591 | return; | ||
1592 | } | ||
1593 | if (gpointer_gettemplatesym(gp) != x->x_templatesym) | ||
1594 | { | ||
1595 | pd_error(x, "set %s: got wrong template (%s)", | ||
1596 | x->x_templatesym->s_name, gpointer_gettemplatesym(gp)->s_name); | ||
1597 | return; | ||
1598 | } | ||
1599 | if (!nitems) return; | ||
1600 | x->x_variables[0].gv_f = f; | ||
1601 | if (gs->gs_which == GP_ARRAY) vec = gp->gp_un.gp_w; | ||
1602 | else vec = gp->gp_un.gp_scalar->sc_vec; | ||
1603 | for (i = 0, vp = x->x_variables; i < nitems; i++, vp++) | ||
1604 | { | ||
1605 | template_setfloat(template, vp->gv_sym, vec, vp->gv_f, 1); | ||
1606 | /* LATER deal with other types ala get_pointer. */ | ||
1607 | } | ||
1608 | if (gs->gs_which == GP_GLIST) | ||
1609 | glist_redrawitem(gs->gs_un.gs_glist, (t_gobj *)(gp->gp_un.gp_scalar)); | ||
1610 | else | ||
1611 | { | ||
1612 | t_array *owner_array = gs->gs_un.gs_array; | ||
1613 | while (owner_array->a_gp.gp_stub->gs_which == GP_ARRAY) | ||
1614 | owner_array = owner_array->a_gp.gp_stub->gs_un.gs_array; | ||
1615 | glist_redrawitem(owner_array->a_gp.gp_stub->gs_un.gs_glist, | ||
1616 | (t_gobj *)(owner_array->a_gp.gp_un.gp_scalar)); | ||
1617 | } | ||
1618 | } | ||
1619 | |||
1620 | static void set_free(t_set *x) | ||
1621 | { | ||
1622 | freebytes(x->x_variables, x->x_nin * sizeof (*x->x_variables)); | ||
1623 | gpointer_unset(&x->x_gp); | ||
1624 | } | ||
1625 | |||
1626 | static void set_setup(void) | ||
1627 | { | ||
1628 | set_class = class_new(gensym("set"), (t_newmethod)set_new, | ||
1629 | (t_method)set_free, sizeof(t_set), 0, A_GIMME, 0); | ||
1630 | class_addfloat(set_class, set_float); | ||
1631 | } | ||
1632 | |||
1633 | /* ---------------------- elem ----------------------------- */ | ||
1634 | |||
1635 | static t_class *elem_class; | ||
1636 | |||
1637 | typedef struct _elem | ||
1638 | { | ||
1639 | t_object x_obj; | ||
1640 | t_symbol *x_templatesym; | ||
1641 | t_symbol *x_fieldsym; | ||
1642 | t_gpointer x_gp; | ||
1643 | t_gpointer x_gparent; | ||
1644 | } t_elem; | ||
1645 | |||
1646 | static void *elem_new(t_symbol *templatesym, t_symbol *fieldsym) | ||
1647 | { | ||
1648 | t_elem *x = (t_elem *)pd_new(elem_class); | ||
1649 | x->x_templatesym = canvas_makebindsym(templatesym); | ||
1650 | x->x_fieldsym = fieldsym; | ||
1651 | gpointer_init(&x->x_gp); | ||
1652 | gpointer_init(&x->x_gparent); | ||
1653 | pointerinlet_new(&x->x_obj, &x->x_gparent); | ||
1654 | outlet_new(&x->x_obj, &s_pointer); | ||
1655 | return (x); | ||
1656 | } | ||
1657 | |||
1658 | static void elem_float(t_elem *x, t_float f) | ||
1659 | { | ||
1660 | int indx = f, nitems, onset; | ||
1661 | t_symbol *templatesym = x->x_templatesym, *fieldsym = x->x_fieldsym, | ||
1662 | *elemtemplatesym; | ||
1663 | t_template *template = template_findbyname(templatesym); | ||
1664 | t_template *elemtemplate; | ||
1665 | t_gpointer *gparent = &x->x_gparent; | ||
1666 | t_word *w; | ||
1667 | t_array *array; | ||
1668 | int elemsize, type; | ||
1669 | |||
1670 | if (!gpointer_check(gparent, 0)) | ||
1671 | { | ||
1672 | pd_error(x, "element: empty pointer"); | ||
1673 | return; | ||
1674 | } | ||
1675 | if (gpointer_gettemplatesym(gparent) != x->x_templatesym) | ||
1676 | { | ||
1677 | pd_error(x, "element %s: got wrong template (%s)", | ||
1678 | x->x_templatesym->s_name, gpointer_gettemplatesym(gparent)->s_name); | ||
1679 | return; | ||
1680 | } | ||
1681 | if (gparent->gp_stub->gs_which == GP_ARRAY) w = gparent->gp_un.gp_w; | ||
1682 | else w = gparent->gp_un.gp_scalar->sc_vec; | ||
1683 | if (!template) | ||
1684 | { | ||
1685 | pd_error(x, "element: couldn't find template %s", templatesym->s_name); | ||
1686 | return; | ||
1687 | } | ||
1688 | if (!template_find_field(template, fieldsym, | ||
1689 | &onset, &type, &elemtemplatesym)) | ||
1690 | { | ||
1691 | pd_error(x, "element: couldn't find array field %s", fieldsym->s_name); | ||
1692 | return; | ||
1693 | } | ||
1694 | if (type != DT_ARRAY) | ||
1695 | { | ||
1696 | pd_error(x, "element: field %s not of type array", fieldsym->s_name); | ||
1697 | return; | ||
1698 | } | ||
1699 | if (!(elemtemplate = template_findbyname(elemtemplatesym))) | ||
1700 | { | ||
1701 | pd_error(x, "element: couldn't find field template %s", | ||
1702 | elemtemplatesym->s_name); | ||
1703 | return; | ||
1704 | } | ||
1705 | |||
1706 | elemsize = elemtemplate->t_n * sizeof(t_word); | ||
1707 | |||
1708 | array = *(t_array **)(((char *)w) + onset); | ||
1709 | |||
1710 | nitems = array->a_n; | ||
1711 | if (indx < 0) indx = 0; | ||
1712 | if (indx >= nitems) indx = nitems-1; | ||
1713 | |||
1714 | gpointer_setarray(&x->x_gp, array, | ||
1715 | (t_word *)((char *)(array->a_vec) + indx * elemsize)); | ||
1716 | outlet_pointer(x->x_obj.ob_outlet, &x->x_gp); | ||
1717 | } | ||
1718 | |||
1719 | static void elem_free(t_elem *x, t_gpointer *gp) | ||
1720 | { | ||
1721 | gpointer_unset(&x->x_gp); | ||
1722 | gpointer_unset(&x->x_gparent); | ||
1723 | } | ||
1724 | |||
1725 | static void elem_setup(void) | ||
1726 | { | ||
1727 | elem_class = class_new(gensym("element"), (t_newmethod)elem_new, | ||
1728 | (t_method)elem_free, sizeof(t_elem), 0, A_DEFSYM, A_DEFSYM, 0); | ||
1729 | class_addfloat(elem_class, elem_float); | ||
1730 | } | ||
1731 | |||
1732 | /* ---------------------- getsize ----------------------------- */ | ||
1733 | |||
1734 | static t_class *getsize_class; | ||
1735 | |||
1736 | typedef struct _getsize | ||
1737 | { | ||
1738 | t_object x_obj; | ||
1739 | t_symbol *x_templatesym; | ||
1740 | t_symbol *x_fieldsym; | ||
1741 | } t_getsize; | ||
1742 | |||
1743 | static void *getsize_new(t_symbol *templatesym, t_symbol *fieldsym) | ||
1744 | { | ||
1745 | t_getsize *x = (t_getsize *)pd_new(getsize_class); | ||
1746 | x->x_templatesym = canvas_makebindsym(templatesym); | ||
1747 | x->x_fieldsym = fieldsym; | ||
1748 | outlet_new(&x->x_obj, &s_float); | ||
1749 | return (x); | ||
1750 | } | ||
1751 | |||
1752 | static void getsize_pointer(t_getsize *x, t_gpointer *gp) | ||
1753 | { | ||
1754 | int nitems, onset, type; | ||
1755 | t_symbol *templatesym = x->x_templatesym, *fieldsym = x->x_fieldsym, | ||
1756 | *elemtemplatesym; | ||
1757 | t_template *template = template_findbyname(templatesym); | ||
1758 | t_word *w; | ||
1759 | t_array *array; | ||
1760 | int elemsize; | ||
1761 | t_gstub *gs = gp->gp_stub; | ||
1762 | if (!template) | ||
1763 | { | ||
1764 | pd_error(x, "getsize: couldn't find template %s", templatesym->s_name); | ||
1765 | return; | ||
1766 | } | ||
1767 | if (!template_find_field(template, fieldsym, | ||
1768 | &onset, &type, &elemtemplatesym)) | ||
1769 | { | ||
1770 | pd_error(x, "getsize: couldn't find array field %s", fieldsym->s_name); | ||
1771 | return; | ||
1772 | } | ||
1773 | if (type != DT_ARRAY) | ||
1774 | { | ||
1775 | pd_error(x, "getsize: field %s not of type array", fieldsym->s_name); | ||
1776 | return; | ||
1777 | } | ||
1778 | if (gpointer_ishead(gp)) | ||
1779 | { | ||
1780 | pd_error(x, "getsize: empty pointer"); | ||
1781 | return; | ||
1782 | } | ||
1783 | if (gpointer_gettemplatesym(gp) != x->x_templatesym) | ||
1784 | { | ||
1785 | pd_error(x, "getsize %s: got wrong template (%s)", | ||
1786 | x->x_templatesym->s_name, gpointer_gettemplatesym(gp)->s_name); | ||
1787 | return; | ||
1788 | } | ||
1789 | if (gs->gs_which == GP_ARRAY) w = gp->gp_un.gp_w; | ||
1790 | else w = gp->gp_un.gp_scalar->sc_vec; | ||
1791 | |||
1792 | array = *(t_array **)(((char *)w) + onset); | ||
1793 | outlet_float(x->x_obj.ob_outlet, (float)(array->a_n)); | ||
1794 | } | ||
1795 | |||
1796 | static void getsize_setup(void) | ||
1797 | { | ||
1798 | getsize_class = class_new(gensym("getsize"), (t_newmethod)getsize_new, 0, | ||
1799 | sizeof(t_getsize), 0, A_DEFSYM, A_DEFSYM, 0); | ||
1800 | class_addpointer(getsize_class, getsize_pointer); | ||
1801 | } | ||
1802 | |||
1803 | /* ---------------------- setsize ----------------------------- */ | ||
1804 | |||
1805 | static t_class *setsize_class; | ||
1806 | |||
1807 | typedef struct _setsize | ||
1808 | { | ||
1809 | t_object x_obj; | ||
1810 | t_symbol *x_templatesym; | ||
1811 | t_symbol *x_fieldsym; | ||
1812 | t_gpointer x_gp; | ||
1813 | } t_setsize; | ||
1814 | |||
1815 | static void *setsize_new(t_symbol *templatesym, t_symbol *fieldsym, | ||
1816 | t_floatarg newsize) | ||
1817 | { | ||
1818 | t_setsize *x = (t_setsize *)pd_new(setsize_class); | ||
1819 | x->x_templatesym = canvas_makebindsym(templatesym); | ||
1820 | x->x_fieldsym = fieldsym; | ||
1821 | gpointer_init(&x->x_gp); | ||
1822 | |||
1823 | pointerinlet_new(&x->x_obj, &x->x_gp); | ||
1824 | return (x); | ||
1825 | } | ||
1826 | |||
1827 | static void setsize_float(t_setsize *x, t_float f) | ||
1828 | { | ||
1829 | int nitems, onset, type; | ||
1830 | t_symbol *templatesym = x->x_templatesym, *fieldsym = x->x_fieldsym, | ||
1831 | *elemtemplatesym; | ||
1832 | t_template *template = template_findbyname(templatesym); | ||
1833 | t_template *elemtemplate; | ||
1834 | t_word *w; | ||
1835 | t_atom at; | ||
1836 | t_array *array; | ||
1837 | int elemsize; | ||
1838 | int newsize = f; | ||
1839 | t_gpointer *gp = &x->x_gp; | ||
1840 | t_gstub *gs = gp->gp_stub; | ||
1841 | if (!gpointer_check(&x->x_gp, 0)) | ||
1842 | { | ||
1843 | pd_error(x, "setsize: empty pointer"); | ||
1844 | return; | ||
1845 | } | ||
1846 | if (gpointer_gettemplatesym(&x->x_gp) != x->x_templatesym) | ||
1847 | { | ||
1848 | pd_error(x, "setsize %s: got wrong template (%s)", | ||
1849 | x->x_templatesym->s_name, | ||
1850 | gpointer_gettemplatesym(&x->x_gp)->s_name); | ||
1851 | return; | ||
1852 | } | ||
1853 | if (gs->gs_which == GP_ARRAY) w = gp->gp_un.gp_w; | ||
1854 | else w = gp->gp_un.gp_scalar->sc_vec; | ||
1855 | |||
1856 | if (!template) | ||
1857 | { | ||
1858 | pd_error(x,"setsize: couldn't find template %s", templatesym->s_name); | ||
1859 | return; | ||
1860 | } | ||
1861 | if (!template_find_field(template, fieldsym, | ||
1862 | &onset, &type, &elemtemplatesym)) | ||
1863 | { | ||
1864 | pd_error(x,"setsize: couldn't find array field %s", fieldsym->s_name); | ||
1865 | return; | ||
1866 | } | ||
1867 | if (type != DT_ARRAY) | ||
1868 | { | ||
1869 | pd_error(x,"setsize: field %s not of type array", fieldsym->s_name); | ||
1870 | return; | ||
1871 | } | ||
1872 | |||
1873 | if (!(elemtemplate = template_findbyname(elemtemplatesym))) | ||
1874 | { | ||
1875 | pd_error(x,"element: couldn't find field template %s", | ||
1876 | elemtemplatesym->s_name); | ||
1877 | return; | ||
1878 | } | ||
1879 | |||
1880 | elemsize = elemtemplate->t_n * sizeof(t_word); | ||
1881 | |||
1882 | array = *(t_array **)(((char *)w) + onset); | ||
1883 | |||
1884 | if (elemsize != array->a_elemsize) bug("setsize_gpointer"); | ||
1885 | |||
1886 | nitems = array->a_n; | ||
1887 | if (newsize < 1) newsize = 1; | ||
1888 | if (newsize == nitems) return; | ||
1889 | |||
1890 | /* erase the array before resizing it. If we belong to a | ||
1891 | scalar it's easy, but if we belong to an element of another | ||
1892 | array we have to search back until we get to a scalar to erase. | ||
1893 | When graphics updates become queueable this may fall apart... */ | ||
1894 | |||
1895 | |||
1896 | if (gs->gs_which == GP_GLIST) | ||
1897 | { | ||
1898 | if (glist_isvisible(gs->gs_un.gs_glist)) | ||
1899 | gobj_vis((t_gobj *)(gp->gp_un.gp_scalar), gs->gs_un.gs_glist, 0); | ||
1900 | } | ||
1901 | else | ||
1902 | { | ||
1903 | t_array *owner_array = gs->gs_un.gs_array; | ||
1904 | while (owner_array->a_gp.gp_stub->gs_which == GP_ARRAY) | ||
1905 | owner_array = owner_array->a_gp.gp_stub->gs_un.gs_array; | ||
1906 | if (glist_isvisible(owner_array->a_gp.gp_stub->gs_un.gs_glist)) | ||
1907 | gobj_vis((t_gobj *)(owner_array->a_gp.gp_un.gp_scalar), | ||
1908 | owner_array->a_gp.gp_stub->gs_un.gs_glist, 0); | ||
1909 | } | ||
1910 | /* now do the resizing and, if growing, initialize new scalars */ | ||
1911 | array->a_vec = (char *)resizebytes(array->a_vec, | ||
1912 | elemsize * nitems, elemsize * newsize); | ||
1913 | array->a_n = newsize; | ||
1914 | if (newsize > nitems) | ||
1915 | { | ||
1916 | char *newelem = ((char *)array->a_vec) + nitems * elemsize; | ||
1917 | int i = 0, nnew = newsize - nitems; | ||
1918 | |||
1919 | while (nnew--) | ||
1920 | { | ||
1921 | word_init((t_word *)newelem, elemtemplate, gp); | ||
1922 | newelem += elemsize; | ||
1923 | /* post("new %x %x, ntypes %d", newelem, *(int *)newelem, ntypes); */ | ||
1924 | } | ||
1925 | } | ||
1926 | |||
1927 | /* redraw again. */ | ||
1928 | if (gs->gs_which == GP_GLIST) | ||
1929 | { | ||
1930 | if (glist_isvisible(gs->gs_un.gs_glist)) | ||
1931 | gobj_vis((t_gobj *)(gp->gp_un.gp_scalar), gs->gs_un.gs_glist, 1); | ||
1932 | } | ||
1933 | else | ||
1934 | { | ||
1935 | t_array *owner_array = gs->gs_un.gs_array; | ||
1936 | while (owner_array->a_gp.gp_stub->gs_which == GP_ARRAY) | ||
1937 | owner_array = owner_array->a_gp.gp_stub->gs_un.gs_array; | ||
1938 | if (glist_isvisible(owner_array->a_gp.gp_stub->gs_un.gs_glist)) | ||
1939 | gobj_vis((t_gobj *)(owner_array->a_gp.gp_un.gp_scalar), | ||
1940 | owner_array->a_gp.gp_stub->gs_un.gs_glist, 1); | ||
1941 | } | ||
1942 | } | ||
1943 | |||
1944 | |||
1945 | static void setsize_free(t_setsize *x) | ||
1946 | { | ||
1947 | gpointer_unset(&x->x_gp); | ||
1948 | } | ||
1949 | |||
1950 | static void setsize_setup(void) | ||
1951 | { | ||
1952 | setsize_class = class_new(gensym("setsize"), (t_newmethod)setsize_new, | ||
1953 | (t_method)setsize_free, sizeof(t_setsize), 0, | ||
1954 | A_DEFSYM, A_DEFSYM, A_DEFFLOAT, 0); | ||
1955 | class_addfloat(setsize_class, setsize_float); | ||
1956 | } | ||
1957 | |||
1958 | /* ---------------------- append ----------------------------- */ | ||
1959 | |||
1960 | static t_class *append_class; | ||
1961 | |||
1962 | typedef struct _appendvariable | ||
1963 | { | ||
1964 | t_symbol *gv_sym; | ||
1965 | t_float gv_f; | ||
1966 | } t_appendvariable; | ||
1967 | |||
1968 | typedef struct _append | ||
1969 | { | ||
1970 | t_object x_obj; | ||
1971 | t_gpointer x_gp; | ||
1972 | t_symbol *x_templatesym; | ||
1973 | int x_nin; | ||
1974 | t_appendvariable *x_variables; | ||
1975 | } t_append; | ||
1976 | |||
1977 | static void *append_new(t_symbol *why, int argc, t_atom *argv) | ||
1978 | { | ||
1979 | t_append *x = (t_append *)pd_new(append_class); | ||
1980 | int i; | ||
1981 | t_appendvariable *sp; | ||
1982 | x->x_templatesym = canvas_makebindsym(atom_getsymbolarg(0, argc, argv)); | ||
1983 | if (argc) argc--, argv++; | ||
1984 | x->x_variables | ||
1985 | = (t_appendvariable *)getbytes(argc * sizeof (*x->x_variables)); | ||
1986 | x->x_nin = argc; | ||
1987 | if (argc) | ||
1988 | { | ||
1989 | for (i = 0, sp = x->x_variables; i < argc; i++, sp++) | ||
1990 | { | ||
1991 | sp->gv_sym = atom_getsymbolarg(i, argc, argv); | ||
1992 | sp->gv_f = 0; | ||
1993 | if (i) floatinlet_new(&x->x_obj, &sp->gv_f); | ||
1994 | } | ||
1995 | } | ||
1996 | pointerinlet_new(&x->x_obj, &x->x_gp); | ||
1997 | outlet_new(&x->x_obj, &s_pointer); | ||
1998 | gpointer_init(&x->x_gp); | ||
1999 | return (x); | ||
2000 | } | ||
2001 | |||
2002 | static void append_float(t_append *x, t_float f) | ||
2003 | { | ||
2004 | int nitems = x->x_nin, i; | ||
2005 | t_symbol *templatesym = x->x_templatesym; | ||
2006 | t_template *template = template_findbyname(templatesym); | ||
2007 | t_appendvariable *vp; | ||
2008 | t_gpointer *gp = &x->x_gp; | ||
2009 | t_gstub *gs = gp->gp_stub; | ||
2010 | t_word *vec; | ||
2011 | t_scalar *sc, *oldsc; | ||
2012 | t_glist *glist; | ||
2013 | if (!template) | ||
2014 | { | ||
2015 | pd_error(x, "append: couldn't find template %s", templatesym->s_name); | ||
2016 | return; | ||
2017 | } | ||
2018 | if (!gs) | ||
2019 | { | ||
2020 | pd_error(x, "append: no current pointer"); | ||
2021 | return; | ||
2022 | } | ||
2023 | if (gs->gs_which != GP_GLIST) | ||
2024 | { | ||
2025 | pd_error(x, "append: lists only, not arrays"); | ||
2026 | return; | ||
2027 | } | ||
2028 | glist = gs->gs_un.gs_glist; | ||
2029 | if (glist->gl_valid != gp->gp_valid) | ||
2030 | { | ||
2031 | pd_error(x, "append: stale pointer"); | ||
2032 | return; | ||
2033 | } | ||
2034 | if (!nitems) return; | ||
2035 | x->x_variables[0].gv_f = f; | ||
2036 | |||
2037 | sc = scalar_new(glist, templatesym); | ||
2038 | if (!sc) | ||
2039 | { | ||
2040 | pd_error(x, "%s: couldn't create scalar", templatesym->s_name); | ||
2041 | return; | ||
2042 | } | ||
2043 | oldsc = gp->gp_un.gp_scalar; | ||
2044 | |||
2045 | if (oldsc) | ||
2046 | { | ||
2047 | sc->sc_gobj.g_next = oldsc->sc_gobj.g_next; | ||
2048 | oldsc->sc_gobj.g_next = &sc->sc_gobj; | ||
2049 | } | ||
2050 | else | ||
2051 | { | ||
2052 | sc->sc_gobj.g_next = glist->gl_list; | ||
2053 | glist->gl_list = &sc->sc_gobj; | ||
2054 | } | ||
2055 | if (glist_isvisible(glist_getcanvas(glist))) | ||
2056 | gobj_vis(&sc->sc_gobj, glist, 1); | ||
2057 | |||
2058 | gp->gp_un.gp_scalar = sc; | ||
2059 | vec = sc->sc_vec; | ||
2060 | for (i = 0, vp = x->x_variables; i < nitems; i++, vp++) | ||
2061 | { | ||
2062 | template_setfloat(template, vp->gv_sym, vec, vp->gv_f, 1); | ||
2063 | } | ||
2064 | |||
2065 | glist_redrawitem(glist, (t_gobj *)sc); | ||
2066 | |||
2067 | outlet_pointer(x->x_obj.ob_outlet, gp); | ||
2068 | } | ||
2069 | |||
2070 | static void append_free(t_append *x) | ||
2071 | { | ||
2072 | freebytes(x->x_variables, x->x_nin * sizeof (*x->x_variables)); | ||
2073 | gpointer_unset(&x->x_gp); | ||
2074 | } | ||
2075 | |||
2076 | static void append_setup(void) | ||
2077 | { | ||
2078 | append_class = class_new(gensym("append"), (t_newmethod)append_new, | ||
2079 | (t_method)append_free, sizeof(t_append), 0, A_GIMME, 0); | ||
2080 | class_addfloat(append_class, append_float); | ||
2081 | } | ||
2082 | |||
2083 | /* ---------------------- sublist ----------------------------- */ | ||
2084 | |||
2085 | static t_class *sublist_class; | ||
2086 | |||
2087 | typedef struct _sublist | ||
2088 | { | ||
2089 | t_object x_obj; | ||
2090 | t_symbol *x_templatesym; | ||
2091 | t_symbol *x_fieldsym; | ||
2092 | t_gpointer x_gp; | ||
2093 | } t_sublist; | ||
2094 | |||
2095 | static void *sublist_new(t_symbol *templatesym, t_symbol *fieldsym) | ||
2096 | { | ||
2097 | t_sublist *x = (t_sublist *)pd_new(sublist_class); | ||
2098 | x->x_templatesym = canvas_makebindsym(templatesym); | ||
2099 | x->x_fieldsym = fieldsym; | ||
2100 | gpointer_init(&x->x_gp); | ||
2101 | outlet_new(&x->x_obj, &s_pointer); | ||
2102 | return (x); | ||
2103 | } | ||
2104 | |||
2105 | static void sublist_pointer(t_sublist *x, t_gpointer *gp) | ||
2106 | { | ||
2107 | t_symbol *templatesym = x->x_templatesym, *dummy; | ||
2108 | t_template *template = template_findbyname(templatesym); | ||
2109 | t_gstub *gs = gp->gp_stub; | ||
2110 | t_word *vec; | ||
2111 | t_getvariable *vp; | ||
2112 | int onset, type; | ||
2113 | t_word *w; | ||
2114 | |||
2115 | if (!template) | ||
2116 | { | ||
2117 | pd_error(x, "sublist: couldn't find template %s", templatesym->s_name); | ||
2118 | return; | ||
2119 | } | ||
2120 | if (gpointer_ishead(gp)) | ||
2121 | { | ||
2122 | pd_error(x, "sublist: empty pointer"); | ||
2123 | return; | ||
2124 | } | ||
2125 | if (!template_find_field(template, x->x_fieldsym, | ||
2126 | &onset, &type, &dummy)) | ||
2127 | { | ||
2128 | pd_error(x, "sublist: couldn't find field %s", x->x_fieldsym->s_name); | ||
2129 | return; | ||
2130 | } | ||
2131 | if (type != DT_LIST) | ||
2132 | { | ||
2133 | pd_error(x, "sublist: field %s not of type list", x->x_fieldsym->s_name); | ||
2134 | return; | ||
2135 | } | ||
2136 | if (gs->gs_which == GP_ARRAY) w = gp->gp_un.gp_w; | ||
2137 | else w = gp->gp_un.gp_scalar->sc_vec; | ||
2138 | |||
2139 | gpointer_setglist(&x->x_gp, *(t_glist **)(((char *)w) + onset), 0); | ||
2140 | |||
2141 | outlet_pointer(x->x_obj.ob_outlet, &x->x_gp); | ||
2142 | } | ||
2143 | |||
2144 | static void sublist_free(t_sublist *x, t_gpointer *gp) | ||
2145 | { | ||
2146 | gpointer_unset(&x->x_gp); | ||
2147 | } | ||
2148 | |||
2149 | static void sublist_setup(void) | ||
2150 | { | ||
2151 | sublist_class = class_new(gensym("sublist"), (t_newmethod)sublist_new, | ||
2152 | (t_method)sublist_free, sizeof(t_sublist), 0, A_DEFSYM, A_DEFSYM, 0); | ||
2153 | class_addpointer(sublist_class, sublist_pointer); | ||
2154 | } | ||
2155 | |||
2156 | /* ----------------- setup function ------------------- */ | ||
2157 | |||
2158 | void g_traversal_setup(void) | ||
2159 | { | ||
2160 | ptrobj_setup(); | ||
2161 | get_setup(); | ||
2162 | set_setup(); | ||
2163 | elem_setup(); | ||
2164 | getsize_setup(); | ||
2165 | setsize_setup(); | ||
2166 | append_setup(); | ||
2167 | sublist_setup(); | ||
2168 | } | ||