diff --git a/pd/doc/5.reference/canvasinfo-help.pd b/pd/doc/5.reference/canvasinfo-help.pd
new file mode 100644
index 0000000000000000000000000000000000000000..688683ded276e782620b36e3842865c0f695af51
--- /dev/null
+++ b/pd/doc/5.reference/canvasinfo-help.pd
@@ -0,0 +1,54 @@
+#N canvas 275 179 549 358 10;
+#N canvas 530 268 625 300 foo 0;
+#X obj 42 195 canvasinfo;
+#X text 124 195 get information about the properties of a canvas;
+#X msg 42 17 bang;
+#X text 79 17 print all properties and values to the console;
+#X msg 58 40 editmode;
+#X obj 42 215 print output;
+#X text 119 40 send an anything to retrieve a property's value;
+#X floatatom 99 173 5 0 0 0 - - -;
+#X text 138 172 set the parent level to get properties from a parent
+canvas;
+#X symbolatom 76 91 10 0 0 0 - - -;
+#X text 184 80 or use a symbol;
+#X msg 87 145 dollarzero 1;
+#X msg 87 117 list dollarzero 1;
+#X text 207 117 or use a list to set parent level as well;
+#X text 177 145 or even an anything to do the same \, like [pack];
+#X msg 69 65 symbol editmode;
+#X connect 0 0 5 0;
+#X connect 2 0 0 0;
+#X connect 4 0 0 0;
+#X connect 7 0 0 1;
+#X connect 9 0 0 0;
+#X connect 11 0 0 0;
+#X connect 12 0 0 0;
+#X connect 15 0 0 0;
+#X restore 243 256 pd foo bar;
+#X obj 338 256 demo-abs foo bar bee;
+#X obj 62 225 canvasinfo;
+#X text 144 225 get information about the properties of a canvas;
+#X msg 62 47 bang;
+#X text 99 47 print all properties and values to the console;
+#X msg 78 70 editmode;
+#X obj 62 245 print output;
+#X text 139 70 send an anything to retrieve a property's value;
+#X floatatom 119 203 5 0 0 0 - - -;
+#X text 158 202 set the parent level to get properties from a parent
+canvas;
+#X symbolatom 96 121 10 0 0 0 - - -;
+#X text 204 110 or use a symbol;
+#X msg 107 175 dollarzero 1;
+#X msg 107 147 list dollarzero 1;
+#X text 227 147 or use a list to set parent level as well;
+#X text 197 175 or even an anything to do the same \, like [pack];
+#X msg 89 95 symbol editmode;
+#X connect 2 0 7 0;
+#X connect 4 0 2 0;
+#X connect 6 0 2 0;
+#X connect 9 0 2 1;
+#X connect 11 0 2 0;
+#X connect 13 0 2 0;
+#X connect 14 0 2 0;
+#X connect 17 0 2 0;
diff --git a/pd/doc/5.reference/classinfo.pd b/pd/doc/5.reference/classinfo.pd
new file mode 100644
index 0000000000000000000000000000000000000000..c3069b7c827e11bb8e155adcbefb3aa2c2d05215
--- /dev/null
+++ b/pd/doc/5.reference/classinfo.pd
@@ -0,0 +1,13 @@
+#N canvas 495 201 450 300 10;
+#X obj 53 152 print;
+#X msg 53 23 bang;
+#X text 89 23 print all properties and values to the console;
+#X obj 53 132 classinfo;
+#X msg 83 52 symbol moses;
+#X msg 94 77 int;
+#X msg 100 99 foo;
+#X connect 1 0 3 0;
+#X connect 3 0 0 0;
+#X connect 4 0 3 0;
+#X connect 5 0 3 0;
+#X connect 6 0 3 0;
diff --git a/pd/doc/5.reference/demo-abs.pd b/pd/doc/5.reference/demo-abs.pd
new file mode 100644
index 0000000000000000000000000000000000000000..da0ca387fba5251fd49cb917fdd4c280d559ad10
--- /dev/null
+++ b/pd/doc/5.reference/demo-abs.pd
@@ -0,0 +1,66 @@
+#N canvas 594 311 611 456 10;
+#N canvas 690 273 595 300 (subpatch) 0;
+#X obj 82 205 canvasinfo;
+#X text 164 205 get information about the properties of a canvas;
+#X msg 82 27 bang;
+#X text 119 27 print all properties and values to the console;
+#X msg 98 50 editmode;
+#X obj 82 225 print output;
+#X text 159 50 send an anything to retrieve a property's value;
+#X floatatom 139 183 5 0 0 0 - - -;
+#X text 178 182 set the parent level to get properties from a parent
+canvas;
+#X symbolatom 116 101 10 0 0 0 - - -;
+#X text 224 90 or use a symbol;
+#X msg 127 127 list dollarzero 1;
+#X text 247 127 or use a list to set parent level as well;
+#X text 217 155 or even an anything to do the same \, like [pack];
+#X msg 109 75 symbol editmode;
+#X msg 10 156 args 1;
+#X msg 127 155 dollarzero 0;
+#X connect 0 0 5 0;
+#X connect 2 0 0 0;
+#X connect 4 0 0 0;
+#X connect 7 0 0 1;
+#X connect 9 0 0 0;
+#X connect 11 0 0 0;
+#X connect 14 0 0 0;
+#X connect 15 0 0 0;
+#X connect 16 0 0 0;
+#X restore 361 267 pd;
+#X obj 72 220 canvasinfo;
+#X text 154 220 get information about the properties of a canvas;
+#X msg 72 42 bang;
+#X text 109 42 print all properties and values to the console;
+#X msg 88 65 editmode;
+#X obj 72 240 print output;
+#X text 149 65 send an anything to retrieve a property's value;
+#X floatatom 129 198 5 0 0 0 - - -;
+#X text 168 197 set the parent level to get properties from a parent
+canvas;
+#X symbolatom 106 116 10 0 0 0 - - -;
+#X text 214 105 or use a symbol;
+#X msg 117 170 dollarzero 1;
+#X msg 117 142 list dollarzero 1;
+#X text 237 142 or use a list to set parent level as well;
+#X text 207 170 or even an anything to do the same \, like [pack];
+#X msg 99 90 symbol editmode;
+#X obj 141 384 canvasinfo 1;
+#X obj 141 324 loadbang;
+#X obj 120 413 send;
+#X msg 84 299 msg 20 20 look ma no [namecanvas];
+#X msg 141 343 name 1;
+#X msg 193 361 name 0;
+#X connect 1 0 6 0;
+#X connect 3 0 1 0;
+#X connect 5 0 1 0;
+#X connect 8 0 1 1;
+#X connect 10 0 1 0;
+#X connect 12 0 1 0;
+#X connect 13 0 1 0;
+#X connect 16 0 1 0;
+#X connect 17 0 19 1;
+#X connect 18 0 21 0;
+#X connect 20 0 19 0;
+#X connect 21 0 17 0;
+#X connect 22 0 17 0;
diff --git a/pd/doc/5.reference/pdinfo-help.pd b/pd/doc/5.reference/pdinfo-help.pd
new file mode 100644
index 0000000000000000000000000000000000000000..47c552cdd362f6ca005d1174fd4c421ca92537e3
--- /dev/null
+++ b/pd/doc/5.reference/pdinfo-help.pd
@@ -0,0 +1,13 @@
+#N canvas 495 201 450 300 10;
+#X msg 83 52 dsp;
+#X obj 53 132 pdinfo;
+#X obj 53 152 print;
+#X msg 53 23 bang;
+#X text 89 23 print all properties and values to the console;
+#X msg 94 77 version;
+#X msg 100 99 symbol dsp;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X connect 3 0 1 0;
+#X connect 5 0 1 0;
+#X connect 6 0 1 0;
diff --git a/pd/src/x_interface.c b/pd/src/x_interface.c
index f1487122aa33ae8d40930b8a855b4760580e632b..8a94e64a50d27e74c6df25bbd46ed88aa1268116 100644
--- a/pd/src/x_interface.c
+++ b/pd/src/x_interface.c
@@ -5,6 +5,10 @@
 /* interface objects */
 
 #include "m_pd.h"
+#include "g_canvas.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
 
 /* -------------------------- print ------------------------------ */
 t_class *print_class;
@@ -81,9 +85,396 @@ static void print_setup(void)
     class_addanything(print_class, print_anything);
 }
 
+/* -----------------canvasinfo, pdinfo, classinfo ------------------------------ */
+static t_class *canvasinfo_class;
 
+typedef struct _canvasinfo {
+    t_object x_obj;
+    t_canvas *x_canvas;
+    t_float   x_depth;
+} t_canvasinfo;
+
+static t_class *pdinfo_class;
+
+typedef struct _pdinfo {
+    t_object x_obj;
+} t_pdinfo;
+
+static t_class *classinfo_class;
+
+typedef struct _classinfo {
+    t_object x_obj;
+    t_float   x_depth;
+} t_classinfo;
+
+/* used by all the *info objects */
+void info_out(t_text *te, t_int all, t_symbol *s, int argc, t_atom *argv)
+{
+    if (all)
+    {
+        startpost("%s:", s->s_name);
+        if (argc > 0)
+            postatom(argc, argv);
+        endpost();
+    }
+    else {
+        outlet_list(te->ob_outlet,
+            &s_list, argc, argv);
+    }
+}
+
+/* -------------------------- canvasinfo ------------------------------ */
+t_canvas *canvasinfo_dig(t_canvasinfo *x)
+{
+  int depth = (int)x->x_depth;
+  t_canvas *c = x->x_canvas;
+  if(depth<0) depth = 0;
+
+  while(depth && c->gl_owner) {
+    c = c->gl_owner;
+    depth--;
+  }
+  return c;
+}
+
+void canvasinfo_get(t_canvasinfo *x, t_symbol *s, t_int all)
+{
+    t_canvas *c = canvasinfo_dig(x);
+    if(s == gensym("args"))
+    {
+        int argc = 0;
+        t_atom *argv = 0;
+        t_binbuf *b;
+        if(!c) return;
+        c = canvas_getrootfor(c);
+        b = c->gl_obj.te_binbuf;
+
+        if(!b)
+        {
+            info_out((t_text *)x, all, s, 0, 0);
+        }
+        else
+        {
+            argc = binbuf_getnatom(b);
+            argv = binbuf_getvec(b);
+            info_out((t_text *)x, all, s, argc-1, argv+1);
+        }
+    }
+    else if(s == gensym("coords"))
+    {
+        t_int gop = c->gl_isgraph + c->gl_hidetext;
+        t_atom at[9];
+        SETFLOAT(at, (c->gl_isgraph) ? c->gl_x1 : 0);
+        SETFLOAT(at+1, (c->gl_isgraph) ? c->gl_y1 : 0);
+        SETFLOAT(at+2, (c->gl_isgraph) ? c->gl_x2 : 0);
+        SETFLOAT(at+3, (c->gl_isgraph) ? c->gl_y2 : 0);
+        SETFLOAT(at+4, (c->gl_isgraph) ? c->gl_pixwidth : 0);
+        SETFLOAT(at+5, (c->gl_isgraph) ? c->gl_pixheight : 0);
+        SETFLOAT(at+6, (c->gl_isgraph) ? gop : 0);
+        SETFLOAT(at+7, (c->gl_isgraph) ? c->gl_xmargin : 0);
+        SETFLOAT(at+8, (c->gl_isgraph) ? c->gl_ymargin : 0);
+        info_out((t_text *)x, all, s, 9, at);
+    }
+    else if(s == gensym("dir"))
+    {
+        c = canvas_getrootfor(c);
+        t_atom at[1];
+        SETSYMBOL(at, canvas_getdir(c));
+        info_out((t_text *)x, all, s, 1, at);
+    }
+    else if (s == gensym("dirty"))
+    {
+        t_atom at[1];
+        SETFLOAT(at, c->gl_dirty);
+        info_out((t_text *)x, all, s, 1, at);
+    }
+    else if (s == gensym("dollarzero"))
+    {
+        c = canvas_getrootfor(c);
+        t_symbol *d = gensym("$0");
+        t_symbol *ret = canvas_realizedollar(c, d);
+        float f = (float)strtod(ret->s_name,NULL);
+        t_atom at[1];
+        SETFLOAT(at, f);
+        info_out((t_text *)x, all, s, 1, at);
+    }
+    else if (s == gensym("editmode"))
+    {
+        t_atom at[1];
+        SETFLOAT(at, c->gl_edit);
+        info_out((t_text *)x, all, s, 1, at);
+    }
+    else if (s == gensym("filename"))
+    {
+        c = canvas_getrootfor(c);
+        t_atom at[1];
+        SETSYMBOL(at, c->gl_name);
+        info_out((t_text *)x, all, s, 1, at);
+    }
+    else if (s == gensym("name"))
+    {
+        char buf[MAXPDSTRING];
+        snprintf(buf, MAXPDSTRING, ".x%lx", (long unsigned int)c);
+        t_atom at[1];
+        SETSYMBOL(at, gensym(buf));
+        info_out((t_text *)x, all, s, 1, at);
+    }
+    else if (s == gensym("parent"))
+    {
+        t_atom at[1];
+        if (c->gl_owner)
+        {
+            t_gpointer gp;
+            gpointer_init(&gp);
+            gpointer_setglist(&gp, c->gl_owner, 0);
+            SETPOINTER(at, &gp);
+            info_out((t_text *)x, all, s, 1, at);
+            gpointer_unset(&gp);
+        }
+        else
+        {
+            SETFLOAT(at, 0);
+            info_out((t_text *)x, all, s, 1, at);
+        }
+    }
+    else if (s == gensym("posonparent"))
+    {
+        t_atom at[2];
+        SETFLOAT(at, c->gl_obj.te_xpix);
+        SETFLOAT(at+1, c->gl_obj.te_ypix);
+        info_out((t_text *)x, all, s, 2, at);
+    }
+    else if (s == gensym("screenpos"))
+    {
+        t_atom at[4];
+        SETFLOAT(at, c->gl_screenx1);
+        SETFLOAT(at+1, c->gl_screeny1);
+        SETFLOAT(at+2, c->gl_screenx2);
+        SETFLOAT(at+3, c->gl_screeny2);
+        info_out((t_text *)x, all, s, 4, at);
+    }
+    else if (s == gensym("self"))
+    {
+        t_atom at[1];
+        t_gpointer gp;
+        gpointer_init(&gp);
+        gpointer_setglist(&gp, c, 0);
+        SETPOINTER(at, &gp);
+        info_out((t_text *)x, all, s, 1, at);
+        gpointer_unset(&gp);
+    }
+    else if (s == gensym("vis"))
+    {
+        t_atom at[1];
+        SETFLOAT(at, glist_isvisible(c));
+        info_out((t_text *)x, all, s, 1, at);
+    }
+    else
+    {
+        pd_error(x, "canvasinfo: no %s property", s->s_name);
+    }
+}
+
+void canvasinfo_symbol(t_canvasinfo *x, t_symbol *s)
+{
+    canvasinfo_get(x, s, 0);
+}
+
+void canvasinfo_bang(t_canvasinfo *x)
+{
+    canvasinfo_get(x, gensym("args"), 1);
+    canvasinfo_get(x, gensym("coords"), 1);
+    canvasinfo_get(x, gensym("dir"), 1);
+    canvasinfo_get(x, gensym("dollarzero"), 1);
+    canvasinfo_get(x, gensym("editmode"), 1);
+    canvasinfo_get(x, gensym("filename"), 1);
+    canvasinfo_get(x, gensym("name"), 1);
+    canvasinfo_get(x, gensym("parent"), 1);
+    canvasinfo_get(x, gensym("posonparent"), 1);
+    canvasinfo_get(x, gensym("screenpos"), 1);
+    canvasinfo_get(x, gensym("self"), 1);
+    canvasinfo_get(x, gensym("vis"), 1);
+}
+
+void canvasinfo_pointer(t_canvasinfo *x, t_gpointer *gp)
+{
+    pd_error(x, "canvasinfo: no method for pointer");
+}
+
+void canvasinfo_float(t_canvasinfo *x, t_float f)
+{
+    pd_error(x, "canvasinfo: no method for float");
+}
+
+static void canvasinfo_list(t_canvasinfo *x, t_symbol *s, int ac, t_atom *av)
+{
+    obj_list(&x->x_obj, 0, ac, av);
+}
+
+static void canvasinfo_anything(t_canvasinfo *x, t_symbol *s, int ac, t_atom *av)
+{
+    t_atom *av2 = (t_atom *)getbytes((ac + 1) * sizeof(t_atom));
+    int i;
+    for (i = 0; i < ac; i++)
+        av2[i + 1] = av[i];
+    SETSYMBOL(av2, s);
+    obj_list(&x->x_obj, 0, ac+1, av2);
+    freebytes(av2, (ac + 1) * sizeof(t_atom));
+}
+
+void *canvasinfo_new(t_floatarg f)
+{
+    t_canvasinfo *x = (t_canvasinfo *)pd_new(canvasinfo_class);
+    t_glist *glist = (t_glist *)canvas_getcurrent();
+    t_canvas *c = (t_canvas*)glist_getcanvas(glist);
+    x->x_canvas = c;
+    floatinlet_new(&x->x_obj, &x->x_depth);
+    outlet_new(&x->x_obj, &s_list);
+    x->x_depth = f;
+    return (void *)x;
+}
+
+void canvasinfo_setup(void)
+{
+    canvasinfo_class = class_new(gensym("canvasinfo"),
+        (t_newmethod)canvasinfo_new, 0,
+        sizeof(t_canvasinfo),
+        CLASS_DEFAULT, A_DEFFLOAT, 0);
+
+    class_addbang(canvasinfo_class, canvasinfo_bang);
+    class_addpointer(canvasinfo_class, canvasinfo_pointer);
+    class_addfloat(canvasinfo_class, canvasinfo_float);
+    class_addsymbol(canvasinfo_class, canvasinfo_symbol);
+    class_addlist(canvasinfo_class, canvasinfo_list);
+    class_addanything(canvasinfo_class, canvasinfo_anything);
+}
+
+/* -------------------------- pdinfo ------------------------------ */
+static t_class *pdinfo_class;
+
+void pdinfo_get(t_pdinfo *x, t_symbol *s, t_int all)
+{
+    if(s == gensym("dsp"))
+    {
+        t_atom at[1];
+        SETFLOAT(at, (t_float)canvas_dspstate);
+        info_out((t_text *)x, all, s, 1, at);
+    }
+    else if(s == gensym("version"))
+    {
+        int major=0, minor=0, bugfix=0;
+        sys_getversion(&major, &minor, &bugfix);
+        t_atom at[3];
+        SETFLOAT(at, (t_float)major);
+        SETFLOAT(at+1, (t_float)minor);
+        SETFLOAT(at+2, (t_float)bugfix);
+        info_out((t_text *)x, all, s, 3, at);
+    }
+}
+
+void pdinfo_symbol(t_pdinfo *x, t_symbol *s)
+{
+    pdinfo_get(x, s, 0);
+}
+
+void pdinfo_bang(t_pdinfo *x)
+{
+    pdinfo_get(x, gensym("dsp"), 1);
+    pdinfo_get(x, gensym("version"), 1);
+}
+
+static void pdinfo_anything(t_pdinfo *x, t_symbol *s, int ac, t_atom *av)
+{
+    if(av->a_type == A_FLOAT)
+    {
+        pd_error(x, "pdinfo: no method for float");
+        return;
+    }
+    else if(av->a_type == A_POINTER)
+    {
+        pd_error(x, "pdinfo: no method for pointer");
+        return;
+    }
+    pdinfo_get(x, s, 0);
+}
+
+void *pdinfo_new(t_symbol *s, t_int argc, t_atom *argv)
+{
+    t_pdinfo *x = (t_pdinfo *)pd_new(pdinfo_class);
+
+    outlet_new(&x->x_obj, &s_list);    
+    return (void *)x;
+}
+
+void pdinfo_setup(void)
+{
+    pdinfo_class = class_new(gensym("pdinfo"),
+        (t_newmethod)pdinfo_new, 0,
+        sizeof(t_pdinfo),
+        CLASS_DEFAULT, 0);
+
+    class_addbang(pdinfo_class, pdinfo_bang);
+    class_addsymbol(pdinfo_class, pdinfo_symbol);
+    class_addanything(pdinfo_class, pdinfo_anything);
+}
+
+/* -------------------------- classinfo ------------------------------ */
+void classinfo_get(t_classinfo *x, t_symbol *s, t_int all)
+{
+    t_atom at[1];
+    SETFLOAT(at, (zgetfn(&pd_objectmaker, s)) ? 1 : 0);
+    info_out((t_text *)x, all, s, 1, at);
+}
+
+void classinfo_symbol(t_classinfo *x, t_symbol *s)
+{
+    classinfo_get(x, s, 0);
+}
+
+void classinfo_bang(t_classinfo *x)
+{
+     
+}
+
+static void classinfo_anything(t_classinfo *x, t_symbol *s, int ac, t_atom *av)
+{
+    if(av->a_type == A_FLOAT)
+    {
+        pd_error(x, "classinfo: no method for float");
+        return;
+    }
+    else if(av->a_type == A_POINTER)
+    {
+        pd_error(x, "classinfo: no method for pointer");
+        return;
+    }
+    classinfo_get(x, s, 0);
+}
+
+void *classinfo_new(t_symbol *s, t_int argc, t_atom *argv)
+{
+    t_classinfo *x = (t_classinfo *)pd_new(classinfo_class);
+
+    outlet_new(&x->x_obj, &s_anything);    
+    return (void *)x;
+}
+
+void classinfo_setup(void)
+{
+    classinfo_class = class_new(gensym("classinfo"),
+        (t_newmethod)classinfo_new, 0,
+        sizeof(t_classinfo),
+        CLASS_DEFAULT, 0);
+
+    class_addbang(classinfo_class, classinfo_bang);
+    class_addanything(classinfo_class, classinfo_anything);
+    class_addsymbol(classinfo_class, classinfo_symbol);
+}
 
 void x_interface_setup(void)
 {
     print_setup();
+    canvasinfo_setup();
+    pdinfo_setup();
+    classinfo_setup();
 }