From ab4741dadd699c8be78bd42c7a69828f83b3d382 Mon Sep 17 00:00:00 2001
From: Jonathan Wilkes <jon.w.wilkes@gmail.com>
Date: Mon, 23 Apr 2018 17:55:22 -0400
Subject: [PATCH] get linked [print] selectors working, manual regtest,
 improved creation errmsg

---
 pd/nw/pdgui.js                                | 101 +++++++++---------
 pd/src/g_text.c                               |  13 ++-
 pd/src/s_print.c                              |   2 +-
 pd/src/x_interface.c                          |  56 ++++++----
 scripts/manual_tests/message_errors.pd        |  56 +++++-----
 .../{message-perf.pd => message_perf.pd}      |   0
 scripts/manual_tests/print_output.pd          |  66 ++++++++++++
 .../{trigger-perf.pd => trigger_perf.pd}      |   0
 8 files changed, 190 insertions(+), 104 deletions(-)
 rename scripts/manual_tests/{message-perf.pd => message_perf.pd} (100%)
 create mode 100644 scripts/manual_tests/print_output.pd
 rename scripts/manual_tests/{trigger-perf.pd => trigger_perf.pd} (100%)

diff --git a/pd/nw/pdgui.js b/pd/nw/pdgui.js
index a9f5cbac0..e40a3072c 100644
--- a/pd/nw/pdgui.js
+++ b/pd/nw/pdgui.js
@@ -659,30 +659,50 @@ var last_child = {};
 var last_object_id = "";
 var duplicate = 0;
 
-function do_post(string, type) {
-    var myp, span, text, printout;
-    current_string += string;
-    myp = pd_window.document.getElementById("p1");
+function do_post(object_id, selector, string, type, loglevel) {
+    var my_p, my_a, span, text, sel_span, printout, dup_span;
+    current_string = current_string + (selector ? selector : "") + string;
+    my_p = pd_window.document.getElementById("p1");
+    // We can get posts from Pd that are build incrementally, with the final
+    // message having a "\n" at the end. So we test for that.
     if (string.slice(-1) === "\n") {
-        if (current_string === last_string) {
-            last_child.textContent = "[" + (duplicate + 2) + "] " + last_string;
-            duplicate++;
+        if (current_string === last_string
+            && object_id === last_object_id) {
+            duplicate += 1;
+            dup_span = last_child.firstElementChild;
+            dup_span.textContent = "[" + (duplicate + 1) + "] ";
             current_string = "";
-            if (myp.lastChild !== last_child) {
-                myp.appendChild(last_child);
+            if (my_p.lastChild !== last_child) {
+                my_p.appendChild(last_child);
             }
         } else {
             span = pd_window.document.createElement("span");
             if (type) {
                 span.classList.add(type);
             }
-            text = pd_window.document.createTextNode(current_string);
+            dup_span = pd_window.document.createElement("span");
+            sel_span = pd_window.document.createTextNode(
+                selector ? selector : "");
+            text = pd_window.document.createTextNode(
+                (selector && selector !== "") ? ": " + string : current_string);
+            if (object_id && object_id.length > 0) {
+                my_a = pd_window.document.createElement("a");
+                my_a.href = "javascript:pdgui.pd_error_select_by_id('" +
+                    object_id + "')";
+                my_a.appendChild(sel_span);
+                span.appendChild(dup_span); // duplicate tally
+                span.appendChild(my_a);
+            } else {
+                span.appendChild(dup_span);
+                span.appendChild(sel_span);
+                my_p.appendChild(span);
+            }
             span.appendChild(text);
-            myp.appendChild(span);
+            my_p.appendChild(span);
             last_string = current_string;
             current_string = "";
             last_child = span;
-            last_object_id = "";
+            last_object_id = object_id;
             duplicate = 0;
             // update the scrollbars to the bottom, but throttle it
             // since it is expensive
@@ -693,14 +713,14 @@ function do_post(string, type) {
 
 // print message to console-- add a newline for convenience
 function post(string, type) {
-    do_post(string + "\n", type);
+    do_post(null, null, string + "\n", type, null);
 }
 
 exports.post = post;
 
 // print message to console from Pd-- don't add newline
 function gui_post(string, type) {
-    do_post(string, type);
+    do_post(null, "", string, type, null);
 }
 
 function pd_error_select_by_id(objectid) {
@@ -709,46 +729,21 @@ function pd_error_select_by_id(objectid) {
     }
 }
 
-exports.pd_error_select_by_id = pd_error_select_by_id
+exports.pd_error_select_by_id = pd_error_select_by_id;
 
-function gui_post_error(objectid, loglevel, errormsg) {
-    var my_p, error_span, error_title, my_a, rest, printout, dup_span;
-    if (last_object_id === objectid
-        && last_string === errormsg)
-    {
-        dup_span = last_child.firstElementChild;
-        dup_span.textContent = "[" + (duplicate + 2) + "] ";
-        duplicate++;
-    } else {
-        my_p = pd_window.document.getElementById("p1");
-        // if we have an object id, make a friendly link...
-        error_span = pd_window.document.createElement("span");
-        error_span.classList.add("error");
-        dup_span = pd_window.document.createElement("span");
-        last_child = error_span;
-        error_title = pd_window.document.createTextNode("error");
-        if (objectid.length > 0) {
-            my_a = pd_window.document.createElement("a");
-            my_a.href =
-                "javascript:pdgui.pd_error_select_by_id('" + objectid + "')";
-            my_a.appendChild(error_title);
-            error_span.appendChild(dup_span); // for duplicate tally
-            error_span.appendChild(my_a);
-            my_p.appendChild(error_span);
-        } else {
-            error_span.appendChild(dup_span);
-            error_span.appendChild(error_title);
-            my_p.appendChild(error_span);
-        }
-        rest = pd_window.document.createTextNode(": " + errormsg);
-        error_span.appendChild(rest);
-        printout = pd_window.document.getElementById("console_bottom");
-        printout.scrollTop = printout.scrollHeight;
-        last_string = errormsg;
-        last_object_id = objectid;
-        current_string = "";
-        duplicate = 0;
-    }
+function gui_post_error(objectid, loglevel, error_msg) {
+    do_post(objectid, "error", error_msg, "error", loglevel);
+}
+
+// This is used specifically by [print] so that we can receive the full
+// message in a single call. This way we can call do_post with a single
+// string message and track the object id with the selector.
+
+function gui_print(object_id, selector, array_of_strings) {
+    // Unfortunately the instance finder still uses a "." prefix, so we
+    // have to add that here
+    do_post("." + object_id, selector, array_of_strings.join(" ") + "\n",
+        null, null);
 }
 
 function gui_legacy_tcl_command(file, line_number, text) {
diff --git a/pd/src/g_text.c b/pd/src/g_text.c
index 7c7fc1602..2d41440d3 100644
--- a/pd/src/g_text.c
+++ b/pd/src/g_text.c
@@ -167,8 +167,6 @@ static void canvas_objtext(t_glist *gl, int xpix, int ypix,
                     return;
                 }
             }
-            binbuf_print(b);
-            post("... couldn't create");
             x = 0;
         }
         else if (!(x = pd_checkobject(newest)))
@@ -182,7 +180,16 @@ static void canvas_objtext(t_glist *gl, int xpix, int ypix,
     {
         /* LATER make the color reflect this */
         x = (t_text *)pd_new(text_class);
-        //fprintf(stderr,"creating blank object %lx\n", x);
+        if (binbuf_getnatom(b))
+        {
+            int bufsize;
+            char *buf;
+            binbuf_gettext(b, &buf, &bufsize);
+            buf = t_resizebytes(buf, bufsize, bufsize+1);
+            buf[bufsize] = 0;
+            pd_error(x, "couldn't create \"%s\"", buf);
+            t_freebytes(buf, bufsize + 1);
+        }
     }
     /* special case: an object, like preset_hub, hides its arguments
        beyond the first n, so we modify its binbuf here */
diff --git a/pd/src/s_print.c b/pd/src/s_print.c
index f9600704c..19d1760cb 100644
--- a/pd/src/s_print.c
+++ b/pd/src/s_print.c
@@ -244,7 +244,7 @@ void pd_error(void *object, const char *fmt, ...)
     {
         /* move this to a function in the GUI so that we can change the
            message without having to recompile */
-        post("... you might be able to track this down from the 'Find Last Error' item in the Edit menu, or by clicking the error link above.");
+        post("... click the link above to track it down, or click the 'Find Last Error' item in the Edit menu.");
         saidit = 1;
     }
 }
diff --git a/pd/src/x_interface.c b/pd/src/x_interface.c
index 3486b4ff9..0282cd560 100644
--- a/pd/src/x_interface.c
+++ b/pd/src/x_interface.c
@@ -56,39 +56,55 @@ static void *print_new(t_symbol *sel, int argc, t_atom *argv)
 
 static void print_bang(t_print *x)
 {
-    post("%s%sbang", x->x_sym->s_name, (*x->x_sym->s_name ? ": " : ""));
+    gui_start_vmess("gui_print", "xs", x, x->x_sym->s_name);
+    gui_start_array();
+    gui_s(s_bang.s_name);
+    gui_end_array();
+    gui_end_vmess();
 }
 
 static void print_pointer(t_print *x, t_gpointer *gp)
 {
-    post("%s%s(gpointer)", x->x_sym->s_name, (*x->x_sym->s_name ? ": " : ""));
+    gui_start_vmess("gui_print", "xs", x, x->x_sym->s_name);
+    gui_start_array();
+    gui_s("(gpointer)");
+    gui_end_array();
+    gui_end_vmess();
 }
 
-static void print_float(t_print *x, t_float f)
+static void print_float(t_print *x, t_floatarg f)
 {
-    post("%s%s%g", x->x_sym->s_name, (*x->x_sym->s_name ? ": " : ""), f);
+    gui_start_vmess("gui_print", "xs", x, x->x_sym->s_name);
+    gui_start_array();
+    gui_f(f);
+    gui_end_array();
+    gui_end_vmess();
 }
 
-static void print_list(t_print *x, t_symbol *s, int argc, t_atom *argv)
+static void print_symbol(t_print *x, t_symbol *s)
 {
-    if (argc && argv->a_type != A_SYMBOL)
-        startpost("%s%s%g", x->x_sym->s_name,
-            (*x->x_sym->s_name ? ": " : ""),
-            atom_getfloatarg(0, argc--, argv++));
-    else startpost("%s%s%s", x->x_sym->s_name,
-        (*x->x_sym->s_name ? ": " : ""),
-        (argc > 1 ? s_list.s_name : (argc == 1 ? s_symbol.s_name :
-            s_bang.s_name)));
-    postatom(argc, argv);
-    endpost();
+    gui_start_vmess("gui_print", "xs", x, x->x_sym->s_name);
+    gui_start_array();
+    gui_s(s_symbol.s_name);
+    gui_s(s->s_name);
+    gui_end_array();
+    gui_end_vmess();
 }
 
 static void print_anything(t_print *x, t_symbol *s, int argc, t_atom *argv)
 {
-    startpost("%s%s%s", x->x_sym->s_name, (*x->x_sym->s_name ? ": " : ""),
-        s->s_name);
-    postatom(argc, argv);
-    endpost();
+    char buf[MAXPDSTRING];
+    gui_start_vmess("gui_print", "xs", x, x->x_sym->s_name);
+    gui_start_array();
+    if (s && (s != &s_list || (argc && argv->a_type != A_FLOAT)))
+        gui_s(s->s_name);
+    for(; argc; argv++, argc--)
+    {
+        atom_string(argv, buf, MAXPDSTRING);
+        gui_s(buf);
+    }
+    gui_end_array();
+    gui_end_vmess();
 }
 
 static void print_setup(void)
@@ -98,7 +114,7 @@ static void print_setup(void)
     class_addbang(print_class, print_bang);
     class_addfloat(print_class, print_float);
     class_addpointer(print_class, print_pointer);
-    class_addlist(print_class, print_list);
+    class_addsymbol(print_class, print_symbol);
     class_addanything(print_class, print_anything);
 }
 
diff --git a/scripts/manual_tests/message_errors.pd b/scripts/manual_tests/message_errors.pd
index aef80b9f6..90c0b285c 100644
--- a/scripts/manual_tests/message_errors.pd
+++ b/scripts/manual_tests/message_errors.pd
@@ -1,31 +1,33 @@
-#N canvas 3 60 508 425 10;
-#X msg 21 41 \; \$1;
-#X msg 21 131 \; \$0;
-#X msg 21 220 42;
-#X msg 21 251 \; \$1;
-#X text 21 11 1) dollar target is out of range;
-#X text 21 101 2) dollar target is dollar zero;
-#X text 21 191 3) dollar target isn't a symbol;
-#X text 251 11 4) not enough args to dollsym;
-#X msg 251 67 \; \$1-foo;
-#X msg 251 36 bang;
-#X text 299 59 ERROR: double doll sign;
-#X msg 251 130 bang;
-#X text 251 101 5) no such object;
-#X msg 251 161 \; 42;
-#X msg 251 230 bang;
-#X msg 251 261 \; foo \$1;
-#X obj 329 228 r foo;
-#X obj 329 250 == 0;
-#X floatatom 329 272 5 0 0 0 - - -, f 5;
-#X msg 251 340 bang;
-#X text 251 201 6) dollar argument number out of range;
-#X text 251 311 7) dollsym argument number out of range;
-#X obj 379 360 sel 0-foo;
-#X obj 379 338 r seven;
-#X msg 251 371 \; seven symbol \$1-foo;
-#X obj 430 382 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
+#N canvas 3 60 508 497 10;
+#X msg 21 101 \; \$1;
+#X msg 21 191 \; \$0;
+#X msg 21 280 42;
+#X msg 21 311 \; \$1;
+#X text 21 71 1) dollar target is out of range;
+#X text 21 161 2) dollar target is dollar zero;
+#X text 21 251 3) dollar target isn't a symbol;
+#X text 251 71 4) not enough args to dollsym;
+#X msg 251 127 \; \$1-foo;
+#X msg 251 96 bang;
+#X text 299 119 ERROR: double doll sign;
+#X msg 251 190 bang;
+#X text 251 161 5) no such object;
+#X msg 251 221 \; 42;
+#X msg 251 290 bang;
+#X msg 251 321 \; foo \$1;
+#X obj 329 288 r foo;
+#X obj 329 310 == 0;
+#X floatatom 329 332 5 0 0 0 - - -, f 5;
+#X msg 251 400 bang;
+#X text 251 261 6) dollar argument number out of range;
+#X text 251 371 7) dollsym argument number out of range;
+#X obj 379 420 sel 0-foo;
+#X obj 379 398 r seven;
+#X msg 251 431 \; seven symbol \$1-foo;
+#X obj 430 442 bng 15 250 50 0 empty empty empty 17 7 0 10 -262144
 -1 -1;
+#X text 21 19 All of these should output an error with a link back
+to the relevant message box.;
 #X connect 2 0 3 0;
 #X connect 9 0 8 0;
 #X connect 11 0 13 0;
diff --git a/scripts/manual_tests/message-perf.pd b/scripts/manual_tests/message_perf.pd
similarity index 100%
rename from scripts/manual_tests/message-perf.pd
rename to scripts/manual_tests/message_perf.pd
diff --git a/scripts/manual_tests/print_output.pd b/scripts/manual_tests/print_output.pd
new file mode 100644
index 000000000..f848335c4
--- /dev/null
+++ b/scripts/manual_tests/print_output.pd
@@ -0,0 +1,66 @@
+#N canvas 3 60 731 585 12;
+#X msg 19 64 0;
+#X obj 19 549 print;
+#X text 130 63 "print: 0";
+#X msg 31 101 foo bar;
+#X obj 31 126 list split 1;
+#X text 130 100 "print: symbol foo";
+#X msg 46 160 list 0;
+#X text 130 160 "print: 0";
+#X msg 57 199 foo bar;
+#X text 130 199 "print: foo bar";
+#X msg 77 234 list;
+#X msg 79 284 bang;
+#X msg 85 325 bang;
+#X obj 85 350 symbol;
+#X msg 85 375 \$1;
+#X text 130 234 "print: bang";
+#X text 131 284 "print: bang";
+#X text 131 324 "print: ";
+#X msg 416 161 a 2;
+#X text 529 161 "print: a 2";
+#X msg 416 455 pointer;
+#X obj 416 480 canvasinfo;
+#X text 529 455 "print: (gpointer)";
+#X msg 416 213 grapes;
+#X obj 416 238 list;
+#X text 529 213 "print: symbol grapes";
+#X msg 416 125 symbol grapes;
+#X text 529 125 "print: symbol grapes";
+#X msg 416 279 pointer;
+#X obj 416 304 canvasinfo;
+#X msg 416 329 grapes \$1;
+#X obj 416 505 pointer;
+#X text 529 279 "print: grapes (pointer)";
+#X msg 416 370 pointer;
+#X obj 416 395 canvasinfo;
+#X text 19 14 These should output the same text as Pd Vanilla which
+is written in the comments.;
+#X msg 416 75 2 a b;
+#X text 529 75 "print: 2 a b";
+#X msg 416 420 list \$1 \$1;
+#X text 489 369 "print: list (pointer) (pointer)";
+#X connect 0 0 1 0;
+#X connect 3 0 4 0;
+#X connect 4 0 1 0;
+#X connect 6 0 1 0;
+#X connect 8 0 1 0;
+#X connect 10 0 1 0;
+#X connect 11 0 1 0;
+#X connect 12 0 13 0;
+#X connect 13 0 14 0;
+#X connect 14 0 1 0;
+#X connect 18 0 1 0;
+#X connect 20 0 21 0;
+#X connect 21 0 31 0;
+#X connect 23 0 24 0;
+#X connect 24 0 1 0;
+#X connect 26 0 1 0;
+#X connect 28 0 29 0;
+#X connect 29 0 30 0;
+#X connect 30 0 1 0;
+#X connect 31 0 1 0;
+#X connect 33 0 34 0;
+#X connect 34 0 38 0;
+#X connect 36 0 1 0;
+#X connect 38 0 1 0;
diff --git a/scripts/manual_tests/trigger-perf.pd b/scripts/manual_tests/trigger_perf.pd
similarity index 100%
rename from scripts/manual_tests/trigger-perf.pd
rename to scripts/manual_tests/trigger_perf.pd
-- 
GitLab