summaryrefslogtreecommitdiff
path: root/apps/plugins/pdbox/PDa/src/g_readwrite.c
diff options
context:
space:
mode:
Diffstat (limited to 'apps/plugins/pdbox/PDa/src/g_readwrite.c')
-rw-r--r--apps/plugins/pdbox/PDa/src/g_readwrite.c722
1 files changed, 0 insertions, 722 deletions
diff --git a/apps/plugins/pdbox/PDa/src/g_readwrite.c b/apps/plugins/pdbox/PDa/src/g_readwrite.c
index a25b60c443..55759dbf1a 100644
--- a/apps/plugins/pdbox/PDa/src/g_readwrite.c
+++ b/apps/plugins/pdbox/PDa/src/g_readwrite.c
@@ -721,726 +721,4 @@ void g_readwrite_setup(void)
721 class_addmethod(canvas_class, (t_method)canvas_menusaveas, 721 class_addmethod(canvas_class, (t_method)canvas_menusaveas,
722 gensym("menusaveas"), 0); 722 gensym("menusaveas"), 0);
723} 723}
724/* Copyright (c) 1997-2002 Miller Puckette and others.
725* For information on usage and redistribution, and for a DISCLAIMER OF ALL
726* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */
727
728/* this file reads and writes the "data" portions of a canvas to a file.
729See also canvas_saveto(), etc., in g_editor.c. The data portion is a
730collection of "scalar" objects. Routines here can save collections of
731scalars into a file and reload them; also, support is included here for
732*/
733
734#include <stdlib.h>
735#include <stdio.h>
736#include "m_pd.h"
737#include "g_canvas.h"
738#include <string.h>
739
740 /* the following routines read "scalars" from a file into a canvas. */
741
742static int canvas_scanbinbuf(int natoms, t_atom *vec, int *p_indexout,
743 int *p_next)
744{
745 int i, j;
746 int indexwas = *p_next;
747 *p_indexout = indexwas;
748 if (indexwas >= natoms)
749 return (0);
750 for (i = indexwas; i < natoms && vec[i].a_type != A_SEMI; i++)
751 ;
752 if (i >= natoms)
753 *p_next = i;
754 else *p_next = i + 1;
755 return (i - indexwas);
756}
757
758int glist_readscalar(t_glist *x, int natoms, t_atom *vec,
759 int *p_nextmsg, int selectit);
760
761static void canvas_readerror(int natoms, t_atom *vec, int message,
762 int nline, char *s)
763{
764 error(s);
765 startpost("line was:");
766 postatom(nline, vec + message);
767 endpost();
768}
769
770 /* fill in the contents of the scalar into the vector w. */
771
772static void glist_readatoms(t_glist *x, int natoms, t_atom *vec,
773 int *p_nextmsg, t_symbol *templatesym, t_word *w, int argc, t_atom *argv)
774{
775 int message, nline, n, i;
776
777 t_template *template = template_findbyname(templatesym);
778 if (!template)
779 {
780 error("%s: no such template", templatesym->s_name);
781 *p_nextmsg = natoms;
782 return;
783 }
784 word_restore(w, template, argc, argv);
785 n = template->t_n;
786 for (i = 0; i < n; i++)
787 {
788 if (template->t_vec[i].ds_type == DT_ARRAY)
789 {
790 int j;
791 t_array *a = w[i].w_array;
792 int elemsize = a->a_elemsize, nitems = 0;
793 t_symbol *arraytemplatesym = template->t_vec[i].ds_arraytemplate;
794 t_template *arraytemplate =
795 template_findbyname(arraytemplatesym);
796 if (!arraytemplate)
797 {
798 error("%s: no such template", arraytemplatesym->s_name);
799 }
800 else while (1)
801 {
802 t_word *element;
803 int nline = canvas_scanbinbuf(natoms, vec, &message, p_nextmsg);
804 /* empty line terminates array */
805 if (!nline)
806 break;
807 array_resize(a, arraytemplate, nitems + 1);
808 element = (t_word *)(((char *)a->a_vec) +
809 nitems * elemsize);
810 glist_readatoms(x, natoms, vec, p_nextmsg, arraytemplatesym,
811 element, nline, vec + message);
812 nitems++;
813 }
814 }
815 else if (template->t_vec[i].ds_type == DT_LIST)
816 {
817 while (1)
818 {
819 if (!glist_readscalar(w->w_list, natoms, vec,
820 p_nextmsg, 0))
821 break;
822 }
823 }
824 }
825}
826
827int glist_readscalar(t_glist *x, int natoms, t_atom *vec,
828 int *p_nextmsg, int selectit)
829{
830 int message, i, j, nline;
831 t_template *template;
832 t_symbol *templatesym;
833 t_scalar *sc;
834 int nextmsg = *p_nextmsg;
835 int wasvis = glist_isvisible(x);
836
837 if (nextmsg >= natoms || vec[nextmsg].a_type != A_SYMBOL)
838 {
839 if (nextmsg < natoms)
840 post("stopping early: type %d", vec[nextmsg].a_type);
841 *p_nextmsg = natoms;
842 return (0);
843 }
844 templatesym = canvas_makebindsym(vec[nextmsg].a_w.w_symbol);
845 *p_nextmsg = nextmsg + 1;
846
847 if (!(template = template_findbyname(templatesym)))
848 {
849 error("canvas_read: %s: no such template", templatesym->s_name);
850 *p_nextmsg = natoms;
851 return (0);
852 }
853 sc = scalar_new(x, templatesym);
854 if (!sc)
855 {
856 error("couldn't create scalar \"%s\"", templatesym->s_name);
857 *p_nextmsg = natoms;
858 return (0);
859 }
860 if (wasvis)
861 {
862 /* temporarily lie about vis flag while this is built */
863 glist_getcanvas(x)->gl_mapped = 0;
864 }
865 glist_add(x, &sc->sc_gobj);
866
867 nline = canvas_scanbinbuf(natoms, vec, &message, p_nextmsg);
868 glist_readatoms(x, natoms, vec, p_nextmsg, templatesym, sc->sc_vec,
869 nline, vec + message);
870 if (wasvis)
871 {
872 /* reset vis flag as before */
873 glist_getcanvas(x)->gl_mapped = 1;
874 gobj_vis(&sc->sc_gobj, x, 1);
875 }
876 if (selectit)
877 {
878 glist_select(x, &sc->sc_gobj);
879 }
880 return (1);
881}
882
883void glist_readfrombinbuf(t_glist *x, t_binbuf *b, char *filename, int selectem)
884{
885 t_canvas *canvas = glist_getcanvas(x);
886 int cr = 0, natoms, nline, message, nextmsg = 0, i, j, nitems;
887 t_atom *vec;
888 t_gobj *gobj;
889
890 natoms = binbuf_getnatom(b);
891 vec = binbuf_getvec(b);
892
893
894 /* check for file type */
895 nline = canvas_scanbinbuf(natoms, vec, &message, &nextmsg);
896 if (nline != 1 && vec[message].a_type != A_SYMBOL &&
897 strcmp(vec[message].a_w.w_symbol->s_name, "data"))
898 {
899 pd_error(x, "%s: file apparently of wrong type", filename);
900 binbuf_free(b);
901 return;
902 }
903 /* read in templates and check for consistency */
904 while (1)
905 {
906 t_template *newtemplate, *existtemplate;
907 t_symbol *templatesym;
908 t_atom *templateargs = getbytes(0);
909 int ntemplateargs = 0, newnargs;
910 nline = canvas_scanbinbuf(natoms, vec, &message, &nextmsg);
911 if (nline < 2)
912 break;
913 else if (nline > 2)
914 canvas_readerror(natoms, vec, message, nline,
915 "extra items ignored");
916 else if (vec[message].a_type != A_SYMBOL ||
917 strcmp(vec[message].a_w.w_symbol->s_name, "template") ||
918 vec[message + 1].a_type != A_SYMBOL)
919 {
920 canvas_readerror(natoms, vec, message, nline,
921 "bad template header");
922 continue;
923 }
924 templatesym = canvas_makebindsym(vec[message + 1].a_w.w_symbol);
925 while (1)
926 {
927 nline = canvas_scanbinbuf(natoms, vec, &message, &nextmsg);
928 if (nline != 2 && nline != 3)
929 break;
930 newnargs = ntemplateargs + nline;
931 templateargs = (t_atom *)t_resizebytes(templateargs,
932 sizeof(*templateargs) * ntemplateargs,
933 sizeof(*templateargs) * newnargs);
934 templateargs[ntemplateargs] = vec[message];
935 templateargs[ntemplateargs + 1] = vec[message + 1];
936 if (nline == 3)
937 templateargs[ntemplateargs + 2] = vec[message + 2];
938 ntemplateargs = newnargs;
939 }
940 newtemplate = template_new(templatesym, ntemplateargs, templateargs);
941 t_freebytes(templateargs, sizeof (*templateargs) * ntemplateargs);
942 if (!(existtemplate = template_findbyname(templatesym)))
943 {
944 error("%s: template not found in current patch",
945 templatesym->s_name);
946 template_free(newtemplate);
947 return;
948 }
949 if (!template_match(existtemplate, newtemplate))
950 {
951 error("%s: template doesn't match current one",
952 templatesym->s_name);
953 template_free(newtemplate);
954 return;
955 }
956 template_free(newtemplate);
957 }
958 while (nextmsg < natoms)
959 {
960 glist_readscalar(x, natoms, vec, &nextmsg, selectem);
961 }
962}
963
964static void glist_doread(t_glist *x, t_symbol *filename, t_symbol *format,
965 int clearme)
966{
967 t_binbuf *b = binbuf_new();
968 t_canvas *canvas = glist_getcanvas(x);
969 int wasvis = glist_isvisible(canvas);
970 int cr = 0, natoms, nline, message, nextmsg = 0, i, j;
971 t_atom *vec;
972
973 if (!strcmp(format->s_name, "cr"))
974 cr = 1;
975 else if (*format->s_name)
976 error("qlist_read: unknown flag: %s", format->s_name);
977
978 if (binbuf_read_via_path(b, filename->s_name,
979 canvas_getdir(canvas)->s_name, cr))
980 {
981 pd_error(x, "read failed");
982 binbuf_free(b);
983 return;
984 }
985 if (wasvis)
986 canvas_vis(canvas, 0);
987 if (clearme)
988 glist_clear(x);
989 glist_readfrombinbuf(x, b, filename->s_name, 0);
990 if (wasvis)
991 canvas_vis(canvas, 1);
992 binbuf_free(b);
993}
994
995void glist_read(t_glist *x, t_symbol *filename, t_symbol *format)
996{
997 glist_doread(x, filename, format, 1);
998}
999
1000void glist_mergefile(t_glist *x, t_symbol *filename, t_symbol *format)
1001{
1002 glist_doread(x, filename, format, 0);
1003}
1004
1005 /* read text from a "properties" window, called from a gfxstub set
1006 up in scalar_properties(). We try to restore the object; if successful
1007 we delete the scalar and put the new thing in its place on the list. */
1008void canvas_dataproperties(t_canvas *x, t_scalar *sc, t_binbuf *b)
1009{
1010 int ntotal, nnew, scindex;
1011 t_gobj *y, *y2 = 0, *newone, *oldone = 0;
1012 for (y = x->gl_list, ntotal = 0, scindex = -1; y; y = y->g_next)
1013 {
1014 if (y == &sc->sc_gobj)
1015 scindex = ntotal, oldone = y;
1016 ntotal++;
1017 }
1018
1019 if (scindex == -1)
1020 bug("data_properties: scalar disappeared");
1021 glist_readfrombinbuf(x, b, "properties dialog", 0);
1022 newone = 0;
1023 if (scindex >= 0)
1024 {
1025 /* take the new object off the list */
1026 if (ntotal)
1027 {
1028 for (y = x->gl_list, nnew = 1; y2 = y->g_next;
1029 y = y2, nnew++)
1030 if (nnew == ntotal)
1031 {
1032 newone = y2;
1033 y->g_next = y2->g_next;
1034 break;
1035 }
1036 }
1037 else newone = x->gl_list, x->gl_list = newone->g_next;
1038 }
1039 if (!newone)
1040 error("couldn't update properties (perhaps a format problem?)");
1041 else if (!oldone)
1042 bug("data_properties: couldn't find old element");
1043 else
1044 {
1045 glist_delete(x, oldone);
1046 if (scindex > 0)
1047 {
1048 for (y = x->gl_list, nnew = 1; y;
1049 y = y->g_next, nnew++)
1050 if (nnew == scindex || !y->g_next)
1051 {
1052 newone->g_next = y->g_next;
1053 y->g_next = newone;
1054 goto didit;
1055 }
1056 bug("data_properties: can't reinsert");
1057 }
1058 else newone->g_next = x->gl_list, x->gl_list = newone;
1059 }
1060didit:
1061 ;
1062}
1063
1064 /* ----------- routines to write data to a binbuf ----------- */
1065
1066void canvas_doaddtemplate(t_symbol *templatesym,
1067 int *p_ntemplates, t_symbol ***p_templatevec)
1068{
1069 int n = *p_ntemplates, i;
1070 t_symbol **templatevec = *p_templatevec;
1071 for (i = 0; i < n; i++)
1072 if (templatevec[i] == templatesym)
1073 return;
1074 templatevec = (t_symbol **)t_resizebytes(templatevec,
1075 n * sizeof(*templatevec), (n+1) * sizeof(*templatevec));
1076 templatevec[n] = templatesym;
1077 *p_templatevec = templatevec;
1078 *p_ntemplates = n+1;
1079}
1080
1081static void glist_writelist(t_gobj *y, t_binbuf *b);
1082
1083void canvas_writescalar(t_symbol *templatesym, t_word *w, t_binbuf *b,
1084 int amarrayelement)
1085{
1086 t_dataslot *ds;
1087 t_template *template = template_findbyname(templatesym);
1088 t_atom *a = (t_atom *)t_getbytes(0);
1089 int i, n = template->t_n, natom = 0;
1090 if (!amarrayelement)
1091 {
1092 t_atom templatename;
1093 SETSYMBOL(&templatename, gensym(templatesym->s_name + 3));
1094 binbuf_add(b, 1, &templatename);
1095 }
1096 if (!template)
1097 bug("canvas_writescalar");
1098 /* write the atoms (floats and symbols) */
1099 for (i = 0; i < n; i++)
1100 {
1101 if (template->t_vec[i].ds_type == DT_FLOAT ||
1102 template->t_vec[i].ds_type == DT_SYMBOL)
1103 {
1104 a = (t_atom *)t_resizebytes(a,
1105 natom * sizeof(*a), (natom + 1) * sizeof (*a));
1106 if (template->t_vec[i].ds_type == DT_FLOAT)
1107 SETFLOAT(a + natom, w[i].w_float);
1108 else SETSYMBOL(a + natom, w[i].w_symbol);
1109 natom++;
1110 }
1111 }
1112 /* array elements have to have at least something */
1113 if (natom == 0 && amarrayelement)
1114 SETSYMBOL(a + natom, &s_bang), natom++;
1115 binbuf_add(b, natom, a);
1116 binbuf_addsemi(b);
1117 t_freebytes(a, natom * sizeof(*a));
1118 for (i = 0; i < n; i++)
1119 {
1120 if (template->t_vec[i].ds_type == DT_ARRAY)
1121 {
1122 int j;
1123 t_array *a = w[i].w_array;
1124 int elemsize = a->a_elemsize, nitems = a->a_n;
1125 t_symbol *arraytemplatesym = template->t_vec[i].ds_arraytemplate;
1126 for (j = 0; j < nitems; j++)
1127 canvas_writescalar(arraytemplatesym,
1128 (t_word *)(((char *)a->a_vec) + elemsize * j), b, 1);
1129 binbuf_addsemi(b);
1130 }
1131 else if (template->t_vec[i].ds_type == DT_LIST)
1132 {
1133 glist_writelist(w->w_list->gl_list, b);
1134 binbuf_addsemi(b);
1135 }
1136 }
1137}
1138 724
1139static void glist_writelist(t_gobj *y, t_binbuf *b)
1140{
1141 for (; y; y = y->g_next)
1142 {
1143 if (pd_class(&y->g_pd) == scalar_class)
1144 {
1145 canvas_writescalar(((t_scalar *)y)->sc_template,
1146 ((t_scalar *)y)->sc_vec, b, 0);
1147 }
1148 }
1149}
1150
1151 /* ------------ routines to write out templates for data ------- */
1152
1153static void canvas_addtemplatesforlist(t_gobj *y,
1154 int *p_ntemplates, t_symbol ***p_templatevec);
1155
1156static void canvas_addtemplatesforscalar(t_symbol *templatesym,
1157 t_word *w, int *p_ntemplates, t_symbol ***p_templatevec)
1158{
1159 t_dataslot *ds;
1160 int i;
1161 t_template *template = template_findbyname(templatesym);
1162 canvas_doaddtemplate(templatesym, p_ntemplates, p_templatevec);
1163 if (!template)
1164 bug("canvas_addtemplatesforscalar");
1165 else for (ds = template->t_vec, i = template->t_n; i--; ds++, w++)
1166 {
1167 if (ds->ds_type == DT_ARRAY)
1168 {
1169 int j;
1170 t_array *a = w->w_array;
1171 int elemsize = a->a_elemsize, nitems = a->a_n;
1172 t_symbol *arraytemplatesym = ds->ds_arraytemplate;
1173 canvas_doaddtemplate(arraytemplatesym, p_ntemplates, p_templatevec);
1174 for (j = 0; j < nitems; j++)
1175 canvas_addtemplatesforscalar(arraytemplatesym,
1176 (t_word *)(((char *)a->a_vec) + elemsize * j),
1177 p_ntemplates, p_templatevec);
1178 }
1179 else if (ds->ds_type == DT_LIST)
1180 canvas_addtemplatesforlist(w->w_list->gl_list,
1181 p_ntemplates, p_templatevec);
1182 }
1183}
1184
1185static void canvas_addtemplatesforlist(t_gobj *y,
1186 int *p_ntemplates, t_symbol ***p_templatevec)
1187{
1188 for (; y; y = y->g_next)
1189 {
1190 if (pd_class(&y->g_pd) == scalar_class)
1191 {
1192 canvas_addtemplatesforscalar(((t_scalar *)y)->sc_template,
1193 ((t_scalar *)y)->sc_vec, p_ntemplates, p_templatevec);
1194 }
1195 }
1196}
1197
1198 /* write all "scalars" in a glist to a binbuf. */
1199t_binbuf *glist_writetobinbuf(t_glist *x, int wholething)
1200{
1201 int i;
1202 t_symbol **templatevec = getbytes(0);
1203 int ntemplates = 0;
1204 t_gobj *y;
1205 t_binbuf *b = binbuf_new();
1206
1207 for (y = x->gl_list; y; y = y->g_next)
1208 {
1209 if ((pd_class(&y->g_pd) == scalar_class) &&
1210 (wholething || glist_isselected(x, y)))
1211 {
1212 canvas_addtemplatesforscalar(((t_scalar *)y)->sc_template,
1213 ((t_scalar *)y)->sc_vec, &ntemplates, &templatevec);
1214 }
1215 }
1216 binbuf_addv(b, "s;", gensym("data"));
1217 for (i = 0; i < ntemplates; i++)
1218 {
1219 t_template *template = template_findbyname(templatevec[i]);
1220 int j, m = template->t_n;
1221 /* drop "pd-" prefix from template symbol to print it: */
1222 binbuf_addv(b, "ss;", gensym("template"),
1223 gensym(templatevec[i]->s_name + 3));
1224 for (j = 0; j < m; j++)
1225 {
1226 t_symbol *type;
1227 switch (template->t_vec[j].ds_type)
1228 {
1229 case DT_FLOAT: type = &s_float; break;
1230 case DT_SYMBOL: type = &s_symbol; break;
1231 case DT_ARRAY: type = gensym("array"); break;
1232 case DT_LIST: type = &s_list; break;
1233 default: type = &s_float; bug("canvas_write");
1234 }
1235 if (template->t_vec[j].ds_type == DT_ARRAY)
1236 binbuf_addv(b, "sss;", type, template->t_vec[j].ds_name,
1237 gensym(template->t_vec[j].ds_arraytemplate->s_name + 3));
1238 else binbuf_addv(b, "ss;", type, template->t_vec[j].ds_name);
1239 }
1240 binbuf_addsemi(b);
1241 }
1242 binbuf_addsemi(b);
1243 /* now write out the objects themselves */
1244 for (y = x->gl_list; y; y = y->g_next)
1245 {
1246 if ((pd_class(&y->g_pd) == scalar_class) &&
1247 (wholething || glist_isselected(x, y)))
1248 {
1249 canvas_writescalar(((t_scalar *)y)->sc_template,
1250 ((t_scalar *)y)->sc_vec, b, 0);
1251 }
1252 }
1253 return (b);
1254}
1255
1256static void glist_write(t_glist *x, t_symbol *filename, t_symbol *format)
1257{
1258 int cr = 0, i;
1259 t_binbuf *b;
1260 char buf[MAXPDSTRING];
1261 t_symbol **templatevec = getbytes(0);
1262 int ntemplates = 0;
1263 t_gobj *y;
1264 t_canvas *canvas = glist_getcanvas(x);
1265 canvas_makefilename(canvas, filename->s_name, buf, MAXPDSTRING);
1266 if (!strcmp(format->s_name, "cr"))
1267 cr = 1;
1268 else if (*format->s_name)
1269 error("qlist_read: unknown flag: %s", format->s_name);
1270
1271 b = glist_writetobinbuf(x, 1);
1272 if (b)
1273 {
1274 if (binbuf_write(b, buf, "", cr))
1275 error("%s: write failed", filename->s_name);
1276 binbuf_free(b);
1277 }
1278}
1279
1280/* ------ routines to save and restore canvases (patches) recursively. ----*/
1281
1282 /* save to a binbuf, called recursively; cf. canvas_savetofile() which
1283 saves the document, and is only called on root canvases. */
1284static void canvas_saveto(t_canvas *x, t_binbuf *b)
1285{
1286 t_gobj *y;
1287 t_linetraverser t;
1288 t_outconnect *oc;
1289 /* subpatch */
1290 if (x->gl_owner && !x->gl_env)
1291 {
1292 binbuf_addv(b, "ssiiiisi;", gensym("#N"), gensym("canvas"),
1293 (t_int)(x->gl_screenx1),
1294 (t_int)(x->gl_screeny1),
1295 (t_int)(x->gl_screenx2 - x->gl_screenx1),
1296 (t_int)(x->gl_screeny2 - x->gl_screeny1),
1297 (*x->gl_name->s_name ? x->gl_name: gensym("(subpatch)")),
1298 x->gl_mapped);
1299 }
1300 /* root or abstraction */
1301 else binbuf_addv(b, "ssiiiii;", gensym("#N"), gensym("canvas"),
1302 (t_int)(x->gl_screenx1),
1303 (t_int)(x->gl_screeny1),
1304 (t_int)(x->gl_screenx2 - x->gl_screenx1),
1305 (t_int)(x->gl_screeny2 - x->gl_screeny1),
1306 x->gl_font);
1307
1308 for (y = x->gl_list; y; y = y->g_next)
1309 gobj_save(y, b);
1310
1311 linetraverser_start(&t, x);
1312 while (oc = linetraverser_next(&t))
1313 {
1314 int srcno = canvas_getindex(x, &t.tr_ob->ob_g);
1315 int sinkno = canvas_getindex(x, &t.tr_ob2->ob_g);
1316 binbuf_addv(b, "ssiiii;", gensym("#X"), gensym("connect"),
1317 srcno, t.tr_outno, sinkno, t.tr_inno);
1318 }
1319 /* unless everything is the default (as in ordinary subpatches)
1320 print out a "coords" message to set up the coordinate systems */
1321 if (x->gl_isgraph || x->gl_x1 || x->gl_y1 ||
1322 x->gl_x2 != 1 || x->gl_y2 != 1 || x->gl_pixwidth || x->gl_pixheight)
1323 binbuf_addv(b, "ssfffffff;", gensym("#X"), gensym("coords"),
1324 x->gl_x1, x->gl_y1,
1325 x->gl_x2, x->gl_y2,
1326 (float)x->gl_pixwidth, (float)x->gl_pixheight,
1327 (float)x->gl_isgraph);
1328}
1329
1330 /* call this recursively to collect all the template names for
1331 a canvas or for the selection. */
1332static void canvas_collecttemplatesfor(t_canvas *x, int *ntemplatesp,
1333 t_symbol ***templatevecp, int wholething)
1334{
1335 t_gobj *y;
1336
1337 for (y = x->gl_list; y; y = y->g_next)
1338 {
1339 if ((pd_class(&y->g_pd) == scalar_class) &&
1340 (wholething || glist_isselected(x, y)))
1341 canvas_addtemplatesforscalar(((t_scalar *)y)->sc_template,
1342 ((t_scalar *)y)->sc_vec, ntemplatesp, templatevecp);
1343 else if ((pd_class(&y->g_pd) == canvas_class) &&
1344 (wholething || glist_isselected(x, y)))
1345 canvas_collecttemplatesfor((t_canvas *)y,
1346 ntemplatesp, templatevecp, 1);
1347 }
1348}
1349
1350 /* save the templates needed by a canvas to a binbuf. */
1351static void canvas_savetemplatesto(t_canvas *x, t_binbuf *b, int wholething)
1352{
1353 t_symbol **templatevec = getbytes(0);
1354 int i, ntemplates = 0;
1355 t_gobj *y;
1356 canvas_collecttemplatesfor(x, &ntemplates, &templatevec, wholething);
1357 for (i = 0; i < ntemplates; i++)
1358 {
1359 t_template *template = template_findbyname(templatevec[i]);
1360 int j, m = template->t_n;
1361 if (!template)
1362 {
1363 bug("canvas_savetemplatesto");
1364 continue;
1365 }
1366 /* drop "pd-" prefix from template symbol to print */
1367 binbuf_addv(b, "sss", &s__N, gensym("struct"),
1368 gensym(templatevec[i]->s_name + 3));
1369 for (j = 0; j < m; j++)
1370 {
1371 t_symbol *type;
1372 switch (template->t_vec[j].ds_type)
1373 {
1374 case DT_FLOAT: type = &s_float; break;
1375 case DT_SYMBOL: type = &s_symbol; break;
1376 case DT_ARRAY: type = gensym("array"); break;
1377 case DT_LIST: type = &s_list; break;
1378 default: type = &s_float; bug("canvas_write");
1379 }
1380 if (template->t_vec[j].ds_type == DT_ARRAY)
1381 binbuf_addv(b, "sss", type, template->t_vec[j].ds_name,
1382 gensym(template->t_vec[j].ds_arraytemplate->s_name + 3));
1383 else binbuf_addv(b, "ss", type, template->t_vec[j].ds_name);
1384 }
1385 binbuf_addsemi(b);
1386 }
1387}
1388
1389void canvas_reload(t_symbol *name, t_symbol *dir, t_gobj *except);
1390
1391 /* save a "root" canvas to a file; cf. canvas_saveto() which saves the
1392 body (and which is called recursively.) */
1393static void canvas_savetofile(t_canvas *x, t_symbol *filename, t_symbol *dir)
1394{
1395 t_binbuf *b = binbuf_new();
1396 canvas_savetemplatesto(x, b, 1);
1397 canvas_saveto(x, b);
1398 if (binbuf_write(b, filename->s_name, dir->s_name, 0)) sys_ouch();
1399 else
1400 {
1401 /* if not an abstraction, reset title bar and directory */
1402 if (!x->gl_owner)
1403 canvas_rename(x, filename, dir);
1404 post("saved to: %s/%s", dir->s_name, filename->s_name);
1405 canvas_dirty(x, 0);
1406 canvas_reload(filename, dir, &x->gl_gobj);
1407 }
1408 binbuf_free(b);
1409}
1410
1411static void canvas_menusaveas(t_canvas *x)
1412{
1413 t_canvas *x2 = canvas_getrootfor(x);
1414 sys_vgui("pdtk_canvas_saveas .x%x \"%s\" \"%s\"\n", x2,
1415 x2->gl_name->s_name, canvas_getdir(x2)->s_name);
1416}
1417
1418static void canvas_menusave(t_canvas *x)
1419{
1420 t_canvas *x2 = canvas_getrootfor(x);
1421 char *name = x2->gl_name->s_name;
1422 if (*name && strncmp(name, "Untitled", 8)
1423 && (strlen(name) < 4 || strcmp(name + strlen(name)-4, ".pat")))
1424 canvas_savetofile(x2, x2->gl_name, canvas_getdir(x2));
1425 else canvas_menusaveas(x2);
1426}
1427
1428
1429void g_readwrite_setup(void)
1430{
1431 class_addmethod(canvas_class, (t_method)glist_write,
1432 gensym("write"), A_SYMBOL, A_DEFSYM, A_NULL);
1433 class_addmethod(canvas_class, (t_method)glist_read,
1434 gensym("read"), A_SYMBOL, A_DEFSYM, A_NULL);
1435 class_addmethod(canvas_class, (t_method)glist_mergefile,
1436 gensym("mergefile"), A_SYMBOL, A_DEFSYM, A_NULL);
1437 class_addmethod(canvas_class, (t_method)canvas_savetofile,
1438 gensym("savetofile"), A_SYMBOL, A_SYMBOL, 0);
1439 class_addmethod(canvas_class, (t_method)canvas_saveto,
1440 gensym("saveto"), A_CANT, 0);
1441/* ------------------ from the menu ------------------------- */
1442 class_addmethod(canvas_class, (t_method)canvas_menusave,
1443 gensym("menusave"), 0);
1444 class_addmethod(canvas_class, (t_method)canvas_menusaveas,
1445 gensym("menusaveas"), 0);
1446}