diff --git a/pd/src/s_stuff.h.in b/pd/src/s_stuff.h.in
index 0fb85a58a9024504c115fb3d5655f23cad1b2890..5e48f33cec95e009f10a2e67922c3f901c2ae98d 100644
--- a/pd/src/s_stuff.h.in
+++ b/pd/src/s_stuff.h.in
@@ -440,7 +440,7 @@ EXTERN void alist_init(t_alist *x);
 EXTERN void alist_clear(t_alist *x);
 EXTERN void alist_list(t_alist *x, t_symbol *s, int argc, t_atom *argv);
 EXTERN void alist_anything(t_alist *x, t_symbol *s, int argc, t_atom *argv);
-EXTERN void alist_toatoms(t_alist *x, t_atom *to);
-EXTERN void alist_clone(t_alist *x, t_alist *y);
+EXTERN void alist_toatoms(t_alist *x, t_atom *to, int onset, int count);
+EXTERN void alist_clone(t_alist *x, t_alist *y, int onset, int count);
 
 #endif /* __s_stuff_h_ */
diff --git a/pd/src/x_list.c b/pd/src/x_list.c
index d43378a2191d50ed063a0ab1d303873aa3e287c8..e03829441cb2800ad4c5df064d248a3a241a426a 100644
--- a/pd/src/x_list.c
+++ b/pd/src/x_list.c
@@ -79,21 +79,33 @@ void alist_init(t_alist *x)
 
 void alist_clear(t_alist *x)
 {
-    if (x->l_n)
+    int i;
+    for (i = 0; i < x->l_n; i++)
     {
-        int i;
-        for (i = 0; i < x->l_n; i++)
+        if (x->l_vec[i].l_a.a_type == A_POINTER)
+            gpointer_unset(x->l_vec[i].l_a.a_w.w_gpointer);
+    }
+    if (x->l_vec)
+        freebytes(x->l_vec, x->l_n * sizeof(*x->l_vec));
+}
+
+static void alist_copyin(t_alist *x, t_symbol *s, int argc, t_atom *argv,
+    int where)
+{
+    int i, j;
+    for (i = 0, j = where; i < argc; i++, j++)
+    {
+        x->l_vec[j].l_a = argv[i];
+        if (x->l_vec[j].l_a.a_type == A_POINTER)
         {
-            if (x->l_vec[i].l_a.a_type == A_POINTER)
-                gpointer_unset(x->l_vec[i].l_a.a_w.w_gpointer);
+            x->l_npointer++;
+            gpointer_copy(x->l_vec[j].l_a.a_w.w_gpointer, &x->l_vec[j].l_p);
+            x->l_vec[j].l_a.a_w.w_gpointer = &x->l_vec[j].l_p;
         }
-        if (x->l_vec)
-            freebytes(x->l_vec, x->l_n * sizeof(*x->l_vec));
     }
-    x->l_n = 0;
-    x->l_npointer = 0;
 }
 
+    /* set contents to a list */
 void alist_list(t_alist *x, t_symbol *s, int argc, t_atom *argv)
 {
     int i;
@@ -118,6 +130,7 @@ void alist_list(t_alist *x, t_symbol *s, int argc, t_atom *argv)
     }
 }
 
+    /* set contents to an arbitrary non-list message */
 void alist_anything(t_alist *x, t_symbol *s, int argc, t_atom *argv)
 {
     int i;
@@ -143,32 +156,32 @@ void alist_anything(t_alist *x, t_symbol *s, int argc, t_atom *argv)
     }
 }
 
-void alist_toatoms(t_alist *x, t_atom *to)
+void alist_toatoms(t_alist *x, t_atom *to, int onset, int count)
 {
     int i;
-    for (i = 0; i < x->l_n; i++)
-        to[i] = x->l_vec[i].l_a;
+    for (i = 0; i < count; i++)
+        to[i] = x->l_vec[onset + i].l_a;
 }
 
-
-void alist_clone(t_alist *x, t_alist *y)
+void alist_clone(t_alist *x, t_alist *y, int onset, int count)
 {
     int i;
     y->l_pd = alist_class;
-    y->l_n = x->l_n;
-    y->l_npointer = x->l_npointer;
+    y->l_n = count;
+    y->l_npointer = 0;
     if (!(y->l_vec = (t_listelem *)getbytes(y->l_n * sizeof(*y->l_vec))))
     {
         y->l_n = 0;
         error("list_alloc: out of memory");
     }
-    else for (i = 0; i < x->l_n; i++)
+    else for (i = 0; i < count; i++)
     {
-        y->l_vec[i].l_a = x->l_vec[i].l_a;
+        y->l_vec[i].l_a = x->l_vec[onset + i].l_a;
         if (y->l_vec[i].l_a.a_type == A_POINTER)
         {
             gpointer_copy(y->l_vec[i].l_a.a_w.w_gpointer, &y->l_vec[i].l_p);
             y->l_vec[i].l_a.a_w.w_gpointer = &y->l_vec[i].l_p;
+            y->l_npointer++;
         }
     }
 }
@@ -205,20 +218,22 @@ static void list_append_list(t_list_append *x, t_symbol *s,
     int argc, t_atom *argv)
 {
     t_atom *outv;
-    int outc = x->x_alist.l_n + argc;
+    int n, outc;
+    n = x->x_alist.l_n;
+    outc = n + argc;
     XL_ATOMS_ALLOCA(outv, outc);
     atoms_copy(argc, argv, outv);
     if (x->x_alist.l_npointer)
     {
         t_alist y;
-        alist_clone(&x->x_alist, &y);
-        alist_toatoms(&y, outv+argc);
+        alist_clone(&x->x_alist, &y, 0, n);
+        alist_toatoms(&y, outv+argc, 0, n);
         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
         alist_clear(&y);
     }
     else
     {
-        alist_toatoms(&x->x_alist, outv+argc);
+        alist_toatoms(&x->x_alist, outv+argc, 0, n);
         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
     }
     XL_ATOMS_FREEA(outv, outc);
@@ -228,21 +243,23 @@ static void list_append_anything(t_list_append *x, t_symbol *s,
     int argc, t_atom *argv)
 {
     t_atom *outv;
-    int outc = x->x_alist.l_n + argc + 1;
+    int n, outc;
+    n = x->x_alist.l_n;
+    outc = n + argc + 1;
     XL_ATOMS_ALLOCA(outv, outc);
     SETSYMBOL(outv, s);
     atoms_copy(argc, argv, outv + 1);
     if (x->x_alist.l_npointer)
     {
         t_alist y;
-        alist_clone(&x->x_alist, &y);
-        alist_toatoms(&y, outv + 1 + argc);
+        alist_clone(&x->x_alist, &y, 0, n);
+        alist_toatoms(&y, outv + 1 + argc, 0, n);
         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
         alist_clear(&y);
     }
     else
     {
-        alist_toatoms(&x->x_alist, outv + 1 + argc);
+        alist_toatoms(&x->x_alist, outv + 1 + argc, 0, n);
         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
     }
     XL_ATOMS_FREEA(outv, outc);
@@ -309,20 +326,22 @@ static void list_cat_list(t_list_cat *x, t_symbol *s,
     int argc, t_atom *argv)
 {
     t_atom *outv;
-    int outc = x->x_alist.l_n + argc;
+    int n, outc;
+    n = x->x_alist.l_n;
+    outc = n + argc;
     XL_ATOMS_ALLOCA(outv, outc);
     atoms_copy(argc, argv, outv + x->x_alist.l_n);
     if (x->x_alist.l_npointer)
     {
         t_alist y;
-        alist_clone(&x->x_alist, &y);
-        alist_toatoms(&y, outv);
+        alist_clone(&x->x_alist, &y, 0, n);
+        alist_toatoms(&y, outv, 0, n);
         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
         alist_clear(&y);
     }
     else
     {
-        alist_toatoms(&x->x_alist, outv);
+        alist_toatoms(&x->x_alist, outv, 0, n);
         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
     }
     alist_list(&x->x_alist, s, outc, outv);
@@ -333,21 +352,23 @@ static void list_cat_anything(t_list_cat *x, t_symbol *s,
     int argc, t_atom *argv)
 {
     t_atom *outv;
-    int outc = x->x_alist.l_n + argc + 1;
+    int n, outc;
+    n = x->x_alist.l_n;
+    outc = n + argc + 1;
     XL_ATOMS_ALLOCA(outv, outc);
     SETSYMBOL(outv + x->x_alist.l_n, s);
     atoms_copy(argc, argv, outv + x->x_alist.l_n + 1);
     if (x->x_alist.l_npointer)
     {
         t_alist y;
-        alist_clone(&x->x_alist, &y);
-        alist_toatoms(&y, outv);
+        alist_clone(&x->x_alist, &y, 0, n);
+        alist_toatoms(&y, outv, 0, n);
         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
         alist_clear(&y);
     }
     else
     {
-        alist_toatoms(&x->x_alist, outv);
+        alist_toatoms(&x->x_alist, outv, 0, n);
         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
     }
     if (x->x_alist.l_n <= 1)
@@ -406,20 +427,22 @@ static void list_prepend_list(t_list_prepend *x, t_symbol *s,
     int argc, t_atom *argv)
 {
     t_atom *outv;
-    int outc = x->x_alist.l_n + argc;
+    int n, outc;
+    n = x->x_alist.l_n;
+    outc = n + argc;
     XL_ATOMS_ALLOCA(outv, outc);
-    atoms_copy(argc, argv, outv + x->x_alist.l_n);
+    atoms_copy(argc, argv, outv + n);
     if (x->x_alist.l_npointer)
     {
         t_alist y;
-        alist_clone(&x->x_alist, &y);
-        alist_toatoms(&y, outv);
+        alist_clone(&x->x_alist, &y, 0, n);
+        alist_toatoms(&y, outv, 0, n);
         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
         alist_clear(&y);
     }
     else
     {
-        alist_toatoms(&x->x_alist, outv);
+        alist_toatoms(&x->x_alist, outv, 0, n);
         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
     }
     XL_ATOMS_FREEA(outv, outc);
@@ -431,21 +454,23 @@ static void list_prepend_anything(t_list_prepend *x, t_symbol *s,
     int argc, t_atom *argv)
 {
     t_atom *outv;
-    int outc = x->x_alist.l_n + argc + 1;
+    int n, outc;
+    n = x->x_alist.l_n;
+    outc = n + argc + 1;
     XL_ATOMS_ALLOCA(outv, outc);
-    SETSYMBOL(outv + x->x_alist.l_n, s);
-    atoms_copy(argc, argv, outv + x->x_alist.l_n + 1);
+    SETSYMBOL(outv + n, s);
+    atoms_copy(argc, argv, outv + n + 1);
     if (x->x_alist.l_npointer)
     {
         t_alist y;
-        alist_clone(&x->x_alist, &y);
-        alist_toatoms(&y, outv);
+        alist_clone(&x->x_alist, &y, 0, n);
+        alist_toatoms(&y, outv, 0, n);
         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
         alist_clear(&y);
     }
     else
     {
-        alist_toatoms(&x->x_alist, outv);
+        alist_toatoms(&x->x_alist, outv, 0, n);
         outlet_list(x->x_obj.ob_outlet, &s_list, outc, outv);
     }
     XL_ATOMS_FREEA(outv, outc);
@@ -468,6 +493,162 @@ static void list_prepend_setup(void)
 
 }
 
+/* ------------- list store --------------------- */
+
+t_class *list_store_class;
+
+typedef struct _list_store
+{
+    t_object x_obj;
+    t_alist x_alist;
+    t_outlet *x_out1;
+    t_outlet *x_out2;
+} t_list_store;
+
+static void *list_store_new(t_symbol *s, int argc, t_atom *argv)
+{
+    t_list_store *x = (t_list_store *)pd_new(list_store_class);
+    alist_init(&x->x_alist);
+    alist_list(&x->x_alist, 0, argc, argv);
+    x->x_out1 = outlet_new(&x->x_obj, &s_list);
+    x->x_out2 = outlet_new(&x->x_obj, &s_bang);
+    inlet_new(&x->x_obj, &x->x_alist.l_pd, 0, 0);
+    return (x);
+}
+
+static void list_store_list(t_list_store *x, t_symbol *s,
+    int argc, t_atom *argv)
+{
+    t_atom *outv;
+    int n, outc;
+    n = x->x_alist.l_n;
+    outc = n + argc;
+    ATOMS_ALLOCA(outv, outc);
+    atoms_copy(argc, argv, outv);
+    if (x->x_alist.l_npointer)
+    {
+        t_alist y;
+        alist_clone(&x->x_alist, &y, 0, n);
+        alist_toatoms(&y, outv+argc, 0, n);
+        outlet_list(x->x_out1, &s_list, outc, outv);
+        alist_clear(&y);
+    }
+    else
+    {
+        alist_toatoms(&x->x_alist, outv+argc, 0, n);
+        outlet_list(x->x_out1, &s_list, outc, outv);
+    }
+    ATOMS_FREEA(outv, outc);
+}
+
+/* function to restore gpointers after the list has moved in memory */
+static void list_store_restore_gpointers(t_list_store *x, int offset, int count)
+{
+    t_listelem *vec = x->x_alist.l_vec + offset;
+    while (count--)
+    {
+        if (vec->l_a.a_type == A_POINTER)
+            vec->l_a.a_w.w_gpointer = &vec->l_p;
+        vec++;
+    }
+}
+
+static void list_store_append(t_list_store *x, t_symbol *s,
+    int argc, t_atom *argv)
+{
+    t_listelem *oldptr = x->x_alist.l_vec;
+
+    if (!(x->x_alist.l_vec = (t_listelem *)resizebytes(x->x_alist.l_vec,
+        (x->x_alist.l_n) * sizeof(*x->x_alist.l_vec),
+        (x->x_alist.l_n + argc) * sizeof(*x->x_alist.l_vec))))
+    {
+        x->x_alist.l_n = 0;
+        error("list: out of memory");
+        return;
+    }
+
+        /* fix gpointers if resizebytes() has moved the alist in memory */
+    if (x->x_alist.l_vec != oldptr && x->x_alist.l_npointer)
+        list_store_restore_gpointers(x, 0, x->x_alist.l_n);
+
+    alist_copyin(&x->x_alist, s, argc, argv, x->x_alist.l_n);
+    x->x_alist.l_n += argc;
+}
+
+static void list_store_prepend(t_list_store *x, t_symbol *s,
+    int argc, t_atom *argv)
+{
+    if (!(x->x_alist.l_vec = (t_listelem *)resizebytes(x->x_alist.l_vec,
+    (x->x_alist.l_n) * sizeof(*x->x_alist.l_vec),
+    (x->x_alist.l_n + argc) * sizeof(*x->x_alist.l_vec))))
+    {
+        x->x_alist.l_n = 0;
+        error("list: out of memory");
+        return;
+    }
+
+    memmove(x->x_alist.l_vec + argc, x->x_alist.l_vec,
+        x->x_alist.l_n * sizeof(*x->x_alist.l_vec));
+
+        /* we always have to fix gpointers because of memmove() */
+    if (x->x_alist.l_npointer)
+        list_store_restore_gpointers(x, argc, x->x_alist.l_n);
+
+    alist_copyin(&x->x_alist, s, argc, argv, 0);
+    x->x_alist.l_n += argc;
+}
+
+static void list_store_get(t_list_store *x, float f1, float f2)
+{
+    t_atom *outv;
+    int onset = f1, outc = f2;
+    if (onset < 0 || outc < 0)
+    {
+        pd_error(x, "list_store_get: negative range (%d %d)", onset, outc);
+        return;
+    }
+    if (onset + outc > x->x_alist.l_n)
+    {
+        outlet_bang(x->x_out2);
+        return;
+    }
+    ATOMS_ALLOCA(outv, outc);
+    if (x->x_alist.l_npointer)
+    {
+        t_alist y;
+        alist_clone(&x->x_alist, &y, onset, outc);
+        alist_toatoms(&y, outv, 0, outc);
+        outlet_list(x->x_out1, &s_list, outc, outv);
+        alist_clear(&y);
+    }
+    else
+    {
+        alist_toatoms(&x->x_alist, outv, onset, outc);
+        outlet_list(x->x_out1, &s_list, outc, outv);
+    }
+    ATOMS_FREEA(outv, outc);
+}
+
+static void list_store_free(t_list_store *x)
+{
+    alist_clear(&x->x_alist);
+}
+
+static void list_store_setup(void)
+{
+    list_store_class = class_new(gensym("list store"),
+        (t_newmethod)list_store_new, (t_method)list_store_free,
+        sizeof(t_list_store), 0, A_GIMME, 0);
+    class_addlist(list_store_class, list_store_list);
+    class_addmethod(list_store_class, (t_method)list_store_append,
+        gensym("append"), A_GIMME, 0);
+    class_addmethod(list_store_class, (t_method)list_store_prepend,
+        gensym("prepend"), A_GIMME, 0);
+    class_addmethod(list_store_class, (t_method)list_store_get,
+        gensym("get"), A_FLOAT, A_FLOAT, 0);
+    class_sethelpsymbol(list_store_class, &s_list);
+}
+
 /* ------------- list split --------------------- */
 
 t_class *list_split_class;
@@ -709,6 +890,8 @@ static void *list_new(t_pd *dummy, t_symbol *s, int argc, t_atom *argv)
             newest = list_fromsymbol_new();
         else if (s2 == gensym("tosymbol"))
             newest = list_tosymbol_new();
+        else if (s2 == gensym("store"))
+            newest = list_store_new(s, argc-1, argv+1);
         else 
         {
             error("list %s: unknown function", s2->s_name);
@@ -724,6 +907,7 @@ void x_list_setup(void)
     list_append_setup();
     list_cat_setup();
     list_prepend_setup();
+    list_store_setup();
     list_split_setup();
     list_trim_setup();
     list_length_setup();
diff --git a/pd/src/x_preset.c b/pd/src/x_preset.c
index d618696a8942e074c1a94002910bf5ebd3bf4a1f..e4224c43c40cfadfb1550cc6c1a311fcc8bdf41f 100644
--- a/pd/src/x_preset.c
+++ b/pd/src/x_preset.c
@@ -614,9 +614,9 @@ void preset_node_set_and_output_value(t_preset_node *x, t_alist val)
     if (val.l_n > 0)
     {
         alist_clear(&x->pn_val);
-        alist_clone(&val, &x->pn_val);
+        alist_clone(&val, &x->pn_val, 0, val.l_n);
         XL_ATOMS_ALLOCA(outv, x->pn_val.l_n);
-        alist_toatoms(&x->pn_val, outv);
+        alist_toatoms(&x->pn_val, outv, 0, x->pn_val.l_n);
         outlet_list(x->pn_outlet, &s_list, x->pn_val.l_n, outv);
         if(PH_DEBUG)
         {
@@ -1199,7 +1199,8 @@ void preset_hub_store(t_preset_hub *h, t_float f)
                             }
                         }
                         alist_clear(&np2->np_val);
-                        alist_clone(&hd1->phd_node->pn_val, &np2->np_val);
+                        alist_clone(&hd1->phd_node->pn_val, &np2->np_val,
+                            0, hd1->phd_node->pn_val.l_n);
                         if (PH_DEBUG)
                         {
                             fprintf(stderr,"    node data len = %d, "