diff --git a/pd/doc/5.reference/pdcontrol-abs.pd b/pd/doc/5.reference/pdcontrol-abs.pd
new file mode 100644
index 0000000000000000000000000000000000000000..5c96a5379ca4cf6db17bc1435ca03fc39cdc0987
--- /dev/null
+++ b/pd/doc/5.reference/pdcontrol-abs.pd
@@ -0,0 +1,9 @@
+#N canvas 674 311 471 296 12;
+#X obj 149 108 inlet;
+#X obj 149 228 outlet;
+#X obj 149 165 pdcontrol;
+#X text 78 28 This is the abstraction for the pdcontrol help patch.
+It serves an example on how it gets the arguments of an abstraction.
+, f 41;
+#X connect 0 0 2 0;
+#X connect 2 0 1 0;
diff --git a/pd/doc/5.reference/pdcontrol-arg-abs.pd b/pd/doc/5.reference/pdcontrol-arg-abs.pd
new file mode 100644
index 0000000000000000000000000000000000000000..f1f10520716257cfea08fb6de69daf3d2b210f7d
--- /dev/null
+++ b/pd/doc/5.reference/pdcontrol-arg-abs.pd
@@ -0,0 +1,21 @@
+#N canvas 584 240 582 350 12;
+#X obj 60 100 inlet;
+#X text 8 8 This is the abstraction for the pdcontrol help patch. It
+serves an example on how it determines the argument type of first argument.
+Similary can be done for all arguments, f 41;
+#X obj 60 129 pdcontrol;
+#X obj 60 160 list split 1;
+#X obj 60 189 route symbol float;
+#X obj 60 280 print symbol;
+#X obj 120 250 print float;
+#X obj 180 220 print other;
+#X text 130 100 args message as input;
+#X text 160 140 takes the first argument from the list of arguments.
+, f 41;
+#X text 270 220 prints the output correspondiing to type., f 28;
+#X connect 0 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 4 0;
+#X connect 4 0 5 0;
+#X connect 4 1 6 0;
+#X connect 4 2 7 0;
diff --git a/pd/doc/5.reference/pdcontrol-help.pd b/pd/doc/5.reference/pdcontrol-help.pd
new file mode 100644
index 0000000000000000000000000000000000000000..1b7c7ad8de5acd9f520bb7602a245a831eac6f3d
--- /dev/null
+++ b/pd/doc/5.reference/pdcontrol-help.pd
@@ -0,0 +1,119 @@
+#N canvas 272 92 553 622 10;
+#X obj 0 595 cnv 15 552 21 empty \$0-pddp.cnv.footer empty 20 12 0
+14 #dcdcdc #404040 0;
+#X obj 0 0 cnv 15 552 40 empty \$0-pddp.cnv.header pdcontrol 3 12 0
+18 #c4dcdc #000000 0;
+#X obj 0 310 cnv 3 550 3 empty \$0-pddp.cnv.inlets inlets 8 12 0 13
+#dcdcdc #000000 0;
+#N canvas 485 284 494 344 META 0;
+#X text 12 105 LIBRARY internal;
+#X text 12 145 WEBSITE http://crca.ucsd.edu/~msp/;
+#X text 12 25 LICENSE SIBSD;
+#X text 12 125 AUTHOR Miller Puckette;
+#X text 12 185 HELP_PATCH_AUTHORS Updated for Pd version 0.40. Jonathan
+Wilkes revised the patch to conform to the PDDP template for Pd version
+0.42.;
+#X text 12 5 KEYWORDS control GUI;
+#X text 12 45 DESCRIPTION query the user for a filename;
+#X text 12 65 INLET_0 bang symbol;
+#X text 12 85 OUTLET_0 symbol;
+#X text 12 165 RELEASE_DATE 1997;
+#X restore 500 597 pd META;
+#X obj 0 432 cnv 3 550 3 empty \$0-pddp.cnv.outlets outlets 8 12 0
+13 #dcdcdc #000000 0;
+#X obj 0 475 cnv 3 550 3 empty \$0-pddp.cnv.argument arguments 8 12
+0 13 #dcdcdc #000000 0;
+#X obj 0 503 cnv 3 550 3 empty \$0-pddp.cnv.more_info more_info 8 12
+0 13 #dcdcdc #000000 0;
+#X text 98 479 (none);
+#N canvas 216 520 428 109 Related_objects 0;
+#X obj 1 1 cnv 15 425 20 empty \$0-pddp.cnv.subheading empty 3 12 0
+14 #c4dcdc #000000 0;
+#X text 8 2 [openpanel] Related Objects;
+#X obj 22 43 canvasinfo;
+#X restore 102 597 pd Related_objects;
+#X obj 78 319 cnv 17 3 105 empty \$0-pddp.cnv.let.0 0 5 9 0 16 #dcdcdc
+#9c9c9c 0;
+#X obj 78 441 cnv 17 3 17 empty \$0-pddp.cnv.let.0 0 5 9 0 16 #dcdcdc
+#9c9c9c 0;
+#X text 98 440 symbol;
+#X obj 484 11 pdcontrol;
+#X text 11 23 communicate with pd and/or this patch;
+#X msg 10 70 browse;
+#X obj 10 240 pdcontrol;
+#X obj 10 265 print;
+#X msg 20 100 isvisible;
+#X msg 40 130 dir;
+#X msg 70 160 dir 0 ../3.audio-examples/A00.intro.pd;
+#X text 70 70 open a URL in a browser;
+#X text 90 100 1 if this patch is visible \, 0 if not;
+#X text 80 130 ouputs directory this patch is in;
+#X text 80 190 Optional argument to specify this patch (0) \, owning
+patch (1) \, its own owner (2) \, and so on \, and optionally also
+a filename relative to the patch's directory. (Ownership number is
+silently reduced if owners don't exist \, so here anything greater
+than zero is ignored.);
+#X text 98 318 browse;
+#X text 100 350 isvisible;
+#X text 100 380 dir;
+#X text 99 507 pdcontrol lets you communicate with the patch to get
+its owning directory \, arguments \, its visible/invisible state \,
+or to open a URL in a web browser. \; ;
+#N canvas 0 0 450 300 args 0;
+#X text 40 10 This is useful for managing a variable number of arguments.
+When it receives the 'args' message \, [pdcontrol] outputs the loaded
+arguments. An optional argument specifies this patch (0) \, owning
+patch (1) \, its own owner (2) \, and so on. (Ownership number is silently
+reduced if owners don't exist \, so here anything greater than zero
+is ignored.);
+#X obj 100 170 print;
+#X msg 100 110 args 0;
+#X obj 100 140 pdcontrol-abs foo 100 \$0-x \$0 \$1 \$2-x;
+#X text 160 110 <-- to get arguments;
+#X text 50 230 here's a simple abstraction to show how it works. Note
+how dollar signs (such as "\$0" \, "\$1" or "\$2-x") get expanded unless
+you escape them with a backlash ("\$2-x" may appear as an unexpanded
+symbol \, but it actually gets expanded if this abstraction is called
+inside another that contains arguments) \; ;
+#X connect 2 0 3 0;
+#X connect 3 0 1 0;
+#X restore 350 70 pd args;
+#N canvas 536 235 450 301 visible 0;
+#N canvas 0 0 450 300 subpatch 0;
+#X obj 90 30 inlet;
+#X obj 90 55 pdcontrol;
+#X obj 90 80 print;
+#X connect 0 0 1 0;
+#X connect 1 0 2 0;
+#X restore 60 60 pd subpatch;
+#X msg 60 30 isvisible;
+#X text 140 30 open and close subpatch \, to see different output;
+#X connect 1 0 0 0;
+#X restore 350 100 pd visible;
+#N canvas 0 0 450 300 extra 0;
+#X msg 60 115 args 0;
+#X msg 230 110 args 0;
+#X obj 230 135 pdcontrol-arg-abs purr;
+#X text 70 80 CLick on the message box to print output;
+#X obj 60 140 pdcontrol-arg-abs 12;
+#X text 70 40 This example shows how to do type detection of argument
+\, given to a patch. Open the below patch to see its content.;
+#X connect 0 0 4 0;
+#X connect 1 0 2 0;
+#X restore 350 130 pd extra;
+#X text 410 70 get patch's arguments;
+#X text 420 100 test visibility;
+#X text 410 130 extra examples;
+#X obj 0 599 pddp/pddplink all_about_help_patches.pd -text Usage Guide
+;
+#X text 170 350 - 1 if this patch is visible \, 0 if not;
+#X text 168 318 - Open a URL in a browser;
+#X text 170 380 - Ouputs directory this patch is in. Check above example
+for more optional arguments.;
+#X text 170 440 - Outputs path as symbol for dir message \, else float
+for visibility.;
+#X connect 14 0 15 0;
+#X connect 15 0 16 0;
+#X connect 17 0 15 0;
+#X connect 18 0 15 0;
+#X connect 19 0 15 0;
diff --git a/pd/src/x_gui.c b/pd/src/x_gui.c
index 862a73f064b8890dd46f1d2c6bba6b5ab1265426..decc2fc18c6eaed1ca03abba24c1d54ad63c8f81 100644
--- a/pd/src/x_gui.c
+++ b/pd/src/x_gui.c
@@ -8,6 +8,7 @@ away before the panel does... */
 #include "config.h"
 
 #include "m_pd.h"
+#include "g_canvas.h"
 #include <stdio.h>
 #include <string.h>
 
@@ -613,6 +614,94 @@ static void mouse_setup(void)
     mousewheel_sym = gensym("#legacy_mousewheel");
 }
 
+/* ------------------------ pdcontrol --------------------------------- */
+
+static t_class *pdcontrol_class;
+
+typedef struct _pdcontrol
+{
+    t_object x_obj;
+    t_canvas *x_canvas;
+    t_outlet *x_outlet;
+} t_pdcontrol;
+
+static void *pdcontrol_new( void)
+{
+    t_pdcontrol *x = (t_pdcontrol *)pd_new(pdcontrol_class);
+    x->x_canvas = canvas_getcurrent();
+    x->x_outlet = outlet_new(&x->x_obj, 0);
+    return (x);
+}
+
+    /* output containing directory of patch.  optional args:
+    1. a number, zero for this patch, one for the parent, etc.;
+    2. a symbol to concatenate onto the directory; */
+
+static void pdcontrol_dir(t_pdcontrol *x, t_symbol *s, t_floatarg f)
+{
+    t_canvas *c = x->x_canvas;
+    int i;
+    for (i = 0; i < (int)f; i++)
+    {
+        while (!c->gl_env)  /* back up to containing canvas or abstraction */
+            c = c->gl_owner;
+        if (c->gl_owner)    /* back up one more into an owner if any */
+            c = c->gl_owner;
+    }
+    if (*s->s_name)
+    {
+        char buf[MAXPDSTRING];
+        snprintf(buf, MAXPDSTRING, "%s/%s",
+            canvas_getdir(c)->s_name, s->s_name);
+        buf[MAXPDSTRING-1] = 0;
+        outlet_symbol(x->x_outlet, gensym(buf));
+    }
+    else outlet_symbol(x->x_outlet, canvas_getdir(c));
+}
+
+static void pdcontrol_args(t_pdcontrol *x, t_floatarg f)
+{
+    t_canvas *c = x->x_canvas;
+    int i;
+    int argc;
+    t_atom *argv;
+    for (i = 0; i < (int)f; i++)
+    {
+        while (!c->gl_env)  /* back up to containing canvas or abstraction */
+            c = c->gl_owner;
+        if (c->gl_owner)    /* back up one more into an owner if any */
+            c = c->gl_owner;
+    }
+    canvas_setcurrent(c);
+    canvas_getargs(&argc, &argv);
+    canvas_unsetcurrent(c);
+    outlet_list(x->x_outlet, &s_list, argc, argv);
+}
+
+static void pdcontrol_browse(t_pdcontrol *x, t_symbol *s)
+{
+    gui_vmess("gui_pddplink_open", "ss", s->s_name, "");
+}
+
+static void pdcontrol_isvisible(t_pdcontrol *x)
+{
+    outlet_float(x->x_outlet, glist_isvisible(x->x_canvas));
+}
+
+static void pdcontrol_setup(void)
+{
+    pdcontrol_class = class_new(gensym("pdcontrol"),
+        (t_newmethod)pdcontrol_new, 0, sizeof(t_pdcontrol), 0, 0);
+    class_addmethod(pdcontrol_class, (t_method)pdcontrol_dir,
+        gensym("dir"), A_DEFFLOAT, A_DEFSYMBOL, 0);
+    class_addmethod(pdcontrol_class, (t_method)pdcontrol_args,
+        gensym("args"), A_DEFFLOAT, 0);
+    class_addmethod(pdcontrol_class, (t_method)pdcontrol_browse,
+        gensym("browse"), A_SYMBOL, 0);
+    class_addmethod(pdcontrol_class, (t_method)pdcontrol_isvisible,
+        gensym("isvisible"), 0);
+}
+
 /* -------------------------- setup routine ------------------------------ */
 
 void x_gui_setup(void)
@@ -625,4 +714,5 @@ void x_gui_setup(void)
     // jsarlo
     magicGlass_setup();
     // end jsarlo
-}
+    pdcontrol_setup();
+}
\ No newline at end of file