diff --git a/doc/1.manual/x5.htm b/doc/1.manual/x5.htm
index 9cccef2575b12ef5312b458aebf128d2c2f86e6a..634e0eeb92671085096b990f2336f8d040fa26a2 100644
--- a/doc/1.manual/x5.htm
+++ b/doc/1.manual/x5.htm
@@ -20,6 +20,16 @@
 
 <H3> <A name="s2"> 5.1. release notes </A> </H3>
 
+<P> ------------------ 0.42 ---------------------------
+
+<P> ".pdrc" loading suppressed if pd is started with "-noprefs".
+
+<P> Bug fix in pipe object: if sending a list to pipe, it didn't update the
+delay time when asked to.
+
+<P> Binbufs fixed to handle arbitrary length messages.  (This fixed a problem
+reloading data structures with huge arrays).
+
 <P> ------------------ 0.41-3,4 ---------------------------
 
 <P> 2 fixes for PC: no bonk~, and the audio device selection
diff --git a/doc/3.audio.examples/I01.Fourier.analysis.pd b/doc/3.audio.examples/I01.Fourier.analysis.pd
index 31bcce631e6d064d44cd547650790c4e448ee079..f82e1710547cd4ceada5d4fba44d7699fbf80ff2 100644
--- a/doc/3.audio.examples/I01.Fourier.analysis.pd
+++ b/doc/3.audio.examples/I01.Fourier.analysis.pd
@@ -1,6 +1,6 @@
-#N canvas 25 8 688 708 12;
+#N canvas 247 4 688 708 12;
 #X floatatom 38 264 7 0 0 0 - - -;
-#N canvas 0 0 450 300 graph1 0;
+#N canvas 0 0 450 300 (subpatch) 0;
 #X array \$0-real 64 float 2;
 #X coords 0 64 64 -64 256 200 1;
 #X restore 423 184 graph;
@@ -12,7 +12,7 @@
 #X obj 38 637 tabwrite~ \$0-real;
 #X obj 67 614 tabwrite~ \$0-imaginary;
 #X obj 38 384 osc~;
-#N canvas 0 0 450 300 graph1 0;
+#N canvas 0 0 450 300 (subpatch) 0;
 #X array \$0-imaginary 64 float 2;
 #X coords 0 64 64 -64 256 200 1;
 #X restore 423 417 graph;
@@ -20,8 +20,8 @@
 #X floatatom 91 316 3 0 100 0 - - -;
 #X obj 91 337 / 100;
 #X obj 38 191 / 64;
-#X text 504 163 real part;
-#X text 489 398 imaginary part;
+#X text 595 165 real part;
+#X text 550 398 imaginary part;
 #X obj 80 545 loadbang;
 #X text 94 166 <- frequency;
 #X text 133 182 (as multiple;
diff --git a/doc/5.reference/exp~-help.pd b/doc/5.reference/exp~-help.pd
new file mode 100644
index 0000000000000000000000000000000000000000..fc9089af98e488f60550f3a71d614c18fba5cad8
--- /dev/null
+++ b/doc/5.reference/exp~-help.pd
@@ -0,0 +1,23 @@
+#N canvas 35 5 531 296 10;
+#X obj 19 107 sig~;
+#X obj 50 167 loadbang;
+#X obj 50 191 metro 100;
+#X obj 50 215 snapshot~;
+#X floatatom 19 88 5 0 0 0 - - -;
+#X floatatom 50 240 7 0 0 0 - - -;
+#X text 314 271 updated for Pd version 0.42.;
+#X text 83 131 <-- optional creation argument initializes right inlet
+(the base of the logarithm).;
+#X obj 21 14 exp~;
+#X text 60 14 - exponential function;
+#X text 76 31 raises the Euler number 'e' (about 2.718) \, to the power
+of the input signal.;
+#X text 18 272 See also:;
+#X obj 92 271 pow~;
+#X obj 20 132 exp~;
+#X connect 0 0 13 0;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 5 0;
+#X connect 4 0 0 0;
+#X connect 13 0 3 0;
diff --git a/doc/5.reference/help-intro.pd b/doc/5.reference/help-intro.pd
index 10ae3502f2a1079e3ad1fcb05a1d4f26fef10e06..1315f27c576bb25cb4ca18fa0ee485da4872a338 100644
--- a/doc/5.reference/help-intro.pd
+++ b/doc/5.reference/help-intro.pd
@@ -81,15 +81,15 @@
 #X text 119 1178 - greater or lesser of 2 numbers;
 #X obj 19 1201 clip;
 #X text 119 1201 - force a number into a range;
-#X obj 16 1251 notein;
-#X obj 75 1251 ctlin;
-#X obj 126 1251 pgmin;
-#X obj 176 1251 bendin;
-#X obj 235 1251 touchin;
-#X obj 16 1274 polytouchin;
-#X obj 120 1274 midiin;
-#X obj 179 1274 sysexin;
-#X text 318 1263 - MIDI input;
+#X obj 16 1261 notein;
+#X obj 75 1261 ctlin;
+#X obj 126 1261 pgmin;
+#X obj 176 1261 bendin;
+#X obj 235 1261 touchin;
+#X obj 16 1284 polytouchin;
+#X obj 120 1284 midiin;
+#X obj 179 1284 sysexin;
+#X text 318 1273 - MIDI input;
 #X obj 19 1317 noteout;
 #X obj 87 1317 ctlout;
 #X obj 147 1317 pgmout;
@@ -99,8 +99,6 @@
 #X obj 210 1338 midiout;
 #X text 318 1327 - MIDI output;
 #X obj 20 1370 makenote;
-#X text 109 1368 - schedule a delayed "note off" message corresponding
-to a note-on;
 #X obj 19 1402 stripnote;
 #X text 112 1403 - strip "note off" messages;
 #X obj 17 1441 tabread;
@@ -143,18 +141,17 @@ to a note-on;
 #X obj 16 2052 q8_rsqrt~;
 #X text 116 2052 - cheap reciprocal square root (beware -- 8 bits!)
 ;
-#X obj 16 2082 q8_sqrt~;
-#X text 116 2082 - cheap square root (beware -- 8 bits!);
-#X obj 16 2112 wrap~;
-#X text 116 2112 - wraparound (fractional part;
-#X obj 16 2142 fft~;
-#X text 116 2142 - complex forward discrete Fourier transform;
-#X obj 16 2172 ifft~;
-#X text 116 2172 - complex inverse discrete Fourier transform;
-#X obj 16 2202 rfft~;
-#X text 116 2202 - real forward discrete Fourier transform;
-#X obj 16 2232 rifft~;
-#X text 116 2232 - real inverse discrete Fourier transform;
+#X obj 16 2074 q8_sqrt~;
+#X text 116 2074 - cheap square root (beware -- 8 bits!);
+#X obj 16 2104 wrap~;
+#X obj 16 2134 fft~;
+#X text 116 2134 - complex forward discrete Fourier transform;
+#X obj 16 2156 ifft~;
+#X text 116 2156 - complex inverse discrete Fourier transform;
+#X obj 16 2186 rfft~;
+#X text 116 2186 - real forward discrete Fourier transform;
+#X obj 16 2208 rifft~;
+#X text 116 2208 - real inverse discrete Fourier transform;
 #X obj 16 2262 framp~;
 #X text 116 2262 - output a ramp for each block;
 #X obj 16 2292 mtof~;
@@ -314,7 +311,7 @@ to a note-on;
 #X text 20 961 ------------------------- MATH -----------------;
 #X text 19 721 ------------------------- TIME --------------------------
 ;
-#X text 17 1232 ------------------------ MIDI -------------------------
+#X text 17 1242 ------------------------ MIDI -------------------------
 ;
 #X text 24 120 --------------- GLUE ----------------;
 #X text 18 3768 ------------------------ SUBWINDOWS ------------------------
@@ -358,3 +355,13 @@ aren't typed into object boxes but come straight off the "add" menu.)
 Right-click (or double-click on a Macintosh) on any object to get its
 "help window".;
 #X text 118 4368 - get a pointer into a list within a scalar;
+#X obj 19 1224 wrap;
+#X text 118 1224 - wrap a number to range [0 \, 1);
+#X text 116 2104 - wraparound (fractional part);
+#X obj 15 2236 pow~;
+#X obj 59 2236 log~;
+#X obj 103 2236 exp~;
+#X text 197 2238 - math;
+#X obj 149 2237 abs~;
+#X text 109 1368 - schedule delayed "note off" message corresponding
+to a note-on;
diff --git a/doc/5.reference/log~-help.pd b/doc/5.reference/log~-help.pd
new file mode 100644
index 0000000000000000000000000000000000000000..fdad98d2af358573c4293d301ee7c2f9b17adb86
--- /dev/null
+++ b/doc/5.reference/log~-help.pd
@@ -0,0 +1,26 @@
+#N canvas 299 273 531 296 10;
+#X obj 19 103 sig~;
+#X obj 50 167 loadbang;
+#X obj 50 191 metro 100;
+#X obj 50 215 snapshot~;
+#X floatatom 19 79 5 0 0 0 - - -;
+#X obj 60 103 sig~;
+#X floatatom 60 79 5 0 0 0 - - -;
+#X floatatom 50 240 7 0 0 0 - - -;
+#X text 316 257 updated for Pd version 0.42.;
+#X obj 21 14 log~;
+#X text 60 14 - logarithms;
+#X text 76 31 computes the logarithm of the left inlet \, to the base
+'e' (about 2.718) \, or to another base specified by the inlet or a
+cration argument.;
+#X obj 20 132 log~ 2;
+#X text 83 131 <-- optional creation argument initializes right inlet
+(the base of the logarithm).;
+#X connect 0 0 12 0;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 7 0;
+#X connect 4 0 0 0;
+#X connect 5 0 12 1;
+#X connect 6 0 5 0;
+#X connect 12 0 3 0;
diff --git a/doc/5.reference/pow~-help.pd b/doc/5.reference/pow~-help.pd
new file mode 100644
index 0000000000000000000000000000000000000000..049e8ba948f875c97283e57e0ab7a95dfcd3bf90
--- /dev/null
+++ b/doc/5.reference/pow~-help.pd
@@ -0,0 +1,30 @@
+#N canvas 191 0 534 413 10;
+#X obj 21 14 pow~;
+#X obj 67 109 sig~;
+#X obj 98 173 loadbang;
+#X obj 98 197 metro 100;
+#X obj 98 221 snapshot~;
+#X floatatom 67 73 5 0 0 0 - - -;
+#X obj 108 109 sig~;
+#X floatatom 108 73 5 0 0 0 - - -;
+#X obj 68 138 pow~ 2;
+#X floatatom 98 246 7 0 0 0 - - -;
+#X obj 413 268 pow~ 2;
+#X text 20 271 An optional creation argument initializes right inlet:
+;
+#X text 319 384 updated for Pd version 0.42.;
+#X text 23 303 WARNING: it's easy to generate "infinity" by accident
+\, and if you do \, the DSP chain may dramatically slow down if you're
+using an i386 or ia64 processor. Out-of-range floating point values
+are thousands of times slower to compute with than in-range ones.;
+#X text 68 12 - raise a signal to a numeric power (given by another
+signal). The left inlet must be a positive number. The right inlet
+my be positive \, zero \, or negative.;
+#X connect 1 0 8 0;
+#X connect 2 0 3 0;
+#X connect 3 0 4 0;
+#X connect 4 0 9 0;
+#X connect 5 0 1 0;
+#X connect 6 0 8 1;
+#X connect 7 0 6 0;
+#X connect 8 0 4 0;
diff --git a/extra/makefile b/extra/makefile
index 944475a1c477063f182ce982271def72c6974916..313795235e375f23c89903c99c308286455e8302 100644
--- a/extra/makefile
+++ b/extra/makefile
@@ -23,36 +23,6 @@ PDNTLIB = /NODEFAULTLIB:libcmt /NODEFAULTLIB:oldnames /NODEFAULTLIB:kernel32 \
 	cl $(PDNTCFLAGS) $(PDNTINCLUDE) /c $*.c
 	link /nologo /dll /export:$(CSYM)_setup $*.obj $(PDNTLIB)
 
-# ----------------------- IRIX 5.x -----------------------
-
-pd_irix5: $(NAME).pd_irix5
-
-.SUFFIXES: .pd_irix5
-
-SGICFLAGS5 = -o32 -DPD -DUNIX -DIRIX -O2
-
-SGIINCLUDE =  -I../../src
-
-.c.pd_irix5:
-	$(CC) $(SGICFLAGS5) $(SGIINCLUDE) -o $*.o -c $*.c
-	ld -elf -shared -rdata_shared -o $*.pd_irix5 $*.o
-	rm $*.o
-
-# ----------------------- IRIX 6.x -----------------------
-
-pd_irix6: $(NAME).pd_irix6
-
-.SUFFIXES: .pd_irix6
-
-SGICFLAGS6 = -n32 -DPD -DUNIX -DIRIX -DN32 -woff 1080,1064,1185 \
-	-OPT:roundoff=3 -OPT:IEEE_arithmetic=3 -OPT:cray_ivdep=true \
-	-Ofast=ip32
-
-.c.pd_irix6:
-	$(CC) $(SGICFLAGS6) $(SGIINCLUDE) -o $*.o -c $*.c
-	ld -n32 -IPA -shared -rdata_shared -o $*.pd_irix6 $*.o
-	rm $*.o
-
 # ----------------------- LINUX i386 -----------------------
 
 pd_linux: $(NAME).pd_linux
diff --git a/extra/pd~/makefile b/extra/pd~/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..e0599d541afa571ac1eb4308eaefcc54e97b4769
--- /dev/null
+++ b/extra/pd~/makefile
@@ -0,0 +1,12 @@
+NAME=pd~
+CSYM=pd_tilde
+
+include ../makefile
+
+pd_linux: pdsched.pd_linux
+
+pdsched.pd_linux: pdsched.c
+	$(CC) $(LINUXCFLAGS) $(LINUXINCLUDE) -o $*.o -c $*.c
+	$(CC) -export_dynamic -shared -o $*.pd_linux $*.o -lc -lm
+	strip --strip-unneeded $*.pd_linux
+	rm -f $*.o
diff --git a/extra/pd~/notes.txt b/extra/pd~/notes.txt
new file mode 100644
index 0000000000000000000000000000000000000000..466c5cdc39aeeeedf6aee1f70267b8758e3a29ce
--- /dev/null
+++ b/extra/pd~/notes.txt
@@ -0,0 +1,23 @@
+pd -schedlib `pwd`/pdsched
+
+
+problems:
+confusion about file extent (l_ia64 / pd_linux)
+Pd dies silently if scheduler doesn't load
+figure out about setting nchannels from command line
+maximum nchannels in and out
+
+
+paper?
+cost per watt
+flops per watt
+cost per flop
+cost of multiprocessing
+
+history - 6-processor ISPW / 1-processor PC / 4-processor PC
+will multiprocessing ever get cheap enough to be worth it?
+    (including programming/complexity cost)
+will multiprocessing be 2-to-4 or 16-up?
+
+Max/FTS, pd, pd~
+
diff --git a/extra/pd~/pdsched.c b/extra/pd~/pdsched.c
new file mode 100644
index 0000000000000000000000000000000000000000..0a0852d173bf146ccf1abb888f3f86c27abeff17
--- /dev/null
+++ b/extra/pd~/pdsched.c
@@ -0,0 +1,83 @@
+/* Copyright 2008 Miller Puckette.  Berkeley license; see the
+file LICENSE.txt in this distribution. */
+
+/* A plug-in scheduler that turns Pd into a filter that inputs and
+outputs audio and messages. */
+
+/* todo: 
+    fix schedlib code to use extent2
+    figure out about  if (sys_externalschedlib) { return; } in s_audio.c
+    make buffer size ynamically growable
+
+*/    
+#include "m_pd.h"
+#include "s_stuff.h"
+#include <stdio.h>
+
+#define BUFSIZE 65536
+static char inbuf[BUFSIZE];
+
+int pd_extern_sched(char *flags)
+{
+    int naudioindev, audioindev[MAXAUDIOINDEV], chindev[MAXAUDIOINDEV];
+    int naudiooutdev, audiooutdev[MAXAUDIOOUTDEV], choutdev[MAXAUDIOOUTDEV];
+    int i, j, rate, advance, callback, chin, chout, fill = 0, c;
+    t_binbuf *b = binbuf_new();
+
+    sys_get_audio_params(&naudioindev, audioindev, chindev,
+        &naudiooutdev, audiooutdev, choutdev, &rate, &advance, &callback);
+
+    chin = (naudioindev < 1 ? 0 : chindev[0]);
+    chout = (naudiooutdev < 1 ? 0 : choutdev[0]);
+
+    fprintf(stderr, "Pd plug-in scheduler called, chans %d %d, sr %d\n",
+        chin, chout, (int)rate);
+    sys_setchsr(chin, chout, rate);
+    while ((c = getchar()) != EOF)
+    {
+        if (c == ';')
+        {
+            int n;
+            t_atom *ap;
+            binbuf_text(b, inbuf, fill);
+            n = binbuf_getnatom(b);
+            ap = binbuf_getvec(b);
+            fill = 0;
+            if (n > 0 && ap[0].a_type == A_FLOAT)
+            {
+                /* a list -- take it as incoming signals. */
+                int chan, nchan = n/DEFDACBLKSIZE;
+                t_sample *fp;
+                for (i = chan = 0, fp = sys_soundin; chan < nchan; chan++)
+                    for (j = 0; j < DEFDACBLKSIZE; j++)
+                        *fp++ = atom_getfloat(ap++);
+                for (; chan < chin; chan++)
+                    for (j = 0; j < DEFDACBLKSIZE; j++)
+                        *fp++ = 0;
+                sched_tick(sys_time+sys_time_per_dsp_tick);
+                sys_pollgui();
+                printf(";\n");
+                for (i = chout*DEFDACBLKSIZE, fp = sys_soundout; i--; fp++)
+                {
+                    printf("%g\n", *fp);
+                    *fp = 0;
+                }
+                printf(";\n");
+            }
+            else if (n > 1 && ap[0].a_type == A_SYMBOL)
+            {
+                t_pd *whom = ap[0].a_w.w_symbol->s_thing;
+                if (!whom)
+                    error("%s: no such object", ap[0].a_w.w_symbol->s_name);
+                else if (ap[1].a_type == A_SYMBOL)
+                    typedmess(whom, ap[1].a_w.w_symbol, n-2, ap+2);
+                else pd_list(whom, 0, n-1, ap+1);
+            }
+        }
+        else if (fill < BUFSIZE)
+            inbuf[fill++] = c;
+        else if (fill == BUFSIZE)
+            fprintf(stderr, "pd-extern: input buffer overflow\n");
+    }
+    return (0);
+}
diff --git a/extra/pd~/pd~-help.pd b/extra/pd~/pd~-help.pd
new file mode 100644
index 0000000000000000000000000000000000000000..6ff3bb0614cd601a63f0cc0c525b7700975661bc
--- /dev/null
+++ b/extra/pd~/pd~-help.pd
@@ -0,0 +1,13 @@
+#N canvas 315 103 450 300 10;
+#X msg 52 86 foo bar baz;
+#X obj 209 52 osc~ 440;
+#X obj 74 211 env~ 8192;
+#X floatatom 77 243 5 0 0 0 - - -;
+#X obj 285 204 r a;
+#X obj 281 232 print a;
+#X obj 70 166 pd~ -pddir /home/msp/pd z.pd;
+#X connect 0 0 6 0;
+#X connect 1 0 6 0;
+#X connect 2 0 3 0;
+#X connect 4 0 5 0;
+#X connect 6 0 2 0;
diff --git a/extra/pd~/pd~.c b/extra/pd~/pd~.c
new file mode 100644
index 0000000000000000000000000000000000000000..477cae0f9c0a6edc23bdc83c5566e6c36048d93c
--- /dev/null
+++ b/extra/pd~/pd~.c
@@ -0,0 +1,599 @@
+/*
+  pd~.c - embed a Pd process within Pd or Max.
+
+  Copyright 2008 Miller Puckette
+  BSD license; see README.txt in this distribution for details.
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+
+#ifdef NT
+#pragma warning (disable: 4305 4244)
+#endif
+ 
+#ifdef MSP
+#include "ext.h"
+#include "z_dsp.h"
+#include "math.h"
+#include "ext_support.h"
+#include "ext_proto.h"
+#include "ext_obex.h"
+
+typedef double t_floatarg;
+
+void *pd_tilde_class;
+#define getbytes t_getbytes
+#define freebytes t_freebytes
+#endif /* MSP */
+
+#ifdef PD
+#include "m_pd.h"
+#include "s_stuff.h"
+static t_class *pd_tilde_class;
+char *class_gethelpdir(t_class *c);
+#endif
+
+#ifdef __linux__
+#ifdef __x86_64__
+static char pd_tilde_dllextent[] = ".l_ia64",
+    pd_tilde_dllextent2[] = ".pd_linux";
+#else
+static char pd_tilde_dllextent[] = ".l_i386",
+    pd_tilde_dllextent2[] = ".pd_linux";
+#endif
+#endif
+#ifdef __APPLE__
+static char pd_tilde_dllextent[] = ".d_ppc",
+    pd_tilde_dllextent2[] = ".pd_darwin";
+#endif
+
+/* ------------------------ pd_tilde~ ----------------------------- */
+
+#define MSGBUFSIZE 65536
+
+typedef struct _pd_tilde
+{
+#ifdef PD
+    t_object x_obj;
+    t_clock *x_clock;
+#endif /* PD */
+#ifdef MSP
+    t_pxobject x_obj;
+    void *obex;
+    void *x_cookedout;
+    void *x_clock;
+    short x_vol;
+        
+#endif /* MSP */
+    FILE *x_infd;
+    FILE *x_outfd;
+    char *x_msgbuf;
+    int x_msgbufsize;
+    int x_infill;
+    int x_childpid;
+    int x_ninsig;
+    int x_noutsig;
+    t_sample **x_insig;
+    t_sample **x_outsig;
+} t_pd_tilde;
+
+#ifdef MSP
+static void *pd_tilde_new(t_symbol *s, long ac, t_atom *av);
+static void pd_tilde_tick(t_pd_tilde *x);
+static t_int *pd_tilde_perform(t_int *w);
+static void pd_tilde_dsp(t_pd_tilde *x, t_signal **sp);
+void pd_tilde_assist(t_pd_tilde *x, void *b, long m, long a, char *s);
+static void pd_tilde_free(t_pd_tilde *x);
+void pd_tilde_setup(void);
+void main();
+static void pd_tilde_thresh(t_pd_tilde *x, t_floatarg f1, t_floatarg f2);
+void pd_tilde_minvel_set(t_pd_tilde *x, void *attr, long ac, t_atom *av);
+char *strcpy(char *s1, const char *s2);
+#endif
+
+static void pd_tilde_tick(t_pd_tilde *x);
+static void pd_tilde_close(t_pd_tilde *x)
+{
+    if (x->x_outfd)
+        fclose(x->x_outfd);
+    if (x->x_infd)
+        fclose(x->x_infd);
+    if (x->x_childpid > 0)
+        waitpid(x->x_childpid, 0, 0);
+    if (x->x_msgbuf)
+        free(x->x_msgbuf);
+    x->x_infd = x->x_outfd = 0;
+    x->x_childpid = -1;
+    x->x_msgbuf = 0;
+    x->x_msgbufsize = 0;
+}
+
+static void pd_tilde_readmessages(t_pd_tilde *x)
+{
+    int gotsomething = 0, setclock = 0, wasempty = (x->x_infill == 0);
+    FILE *infd = x->x_infd;
+    while (1)
+    {
+        int c = getc(infd);
+        if (c == EOF)
+        {
+            pd_error(x, "pd~: %s", strerror(errno));
+            pd_tilde_close(x);
+            break;
+        }
+        if (x->x_infill >= x->x_msgbufsize)
+        {
+            char *z = realloc(x->x_msgbuf, x->x_msgbufsize+MSGBUFSIZE);
+            if (!z)
+            {
+                pd_error(x, "pd~: failed to grow input buffer");
+                pd_tilde_close(x);
+                break;
+            }
+            x->x_msgbuf = z;
+            x->x_msgbufsize += MSGBUFSIZE;
+        }
+        x->x_msgbuf[x->x_infill++] = c;
+        if (c == ';')
+        {
+            if (!gotsomething)
+                break;
+            gotsomething = 0;
+        }
+        else if (!isspace(c))
+            gotsomething = setclock = 1;
+    }
+    if (setclock)
+        clock_delay(x->x_clock, 0);
+    else if (wasempty)
+        x->x_infill = 0;
+}
+
+static void pd_tilde_donew(t_pd_tilde *x, char *pddir, char *schedlibdir,
+    char *pdargs, int ninsig, int noutsig, int fifo, float samplerate)
+{
+    int i, pid, pipe1[2], pipe2[2];
+    char cmdbuf[MAXPDSTRING], pdexecbuf[MAXPDSTRING], schedbuf[MAXPDSTRING];
+    float *fp;
+    t_sample **g;
+    struct stat statbuf;
+    x->x_infd = x->x_outfd = 0;
+    x->x_childpid = -1;
+    snprintf(pdexecbuf, MAXPDSTRING, "%s/bin/pd", pddir);
+    if (stat(pdexecbuf, &statbuf) < 0)
+    {
+        pd_error(x, "pd~: can't stat %s", pdexecbuf);
+        goto fail1;
+    }
+    snprintf(schedbuf, MAXPDSTRING, "%s/pdsched%s", schedlibdir, 
+        pd_tilde_dllextent);
+    if (stat(schedbuf, &statbuf) < 0)
+    {
+        snprintf(schedbuf, MAXPDSTRING, "%s/pdsched%s", schedlibdir, 
+            pd_tilde_dllextent2);
+        if (stat(schedbuf, &statbuf) < 0)
+        {
+            pd_error(x, "pd~: can't stat %s", schedbuf);
+            goto fail1;
+        }
+    }
+    snprintf(cmdbuf, MAXPDSTRING, "%s -schedlib %s/pdsched %s\n",
+        pdexecbuf, schedlibdir, pdargs);
+    fprintf(stderr, "%s", cmdbuf);
+    if (pipe(pipe1) < 0)   
+    {
+        pd_error(x, "pd~: can't create pipe");
+        goto fail1;
+    }
+    if (pipe(pipe2) < 0)   
+    {
+        pd_error(x, "pd~: can't create pipe");
+        goto fail2;
+    }
+    if ((pid = fork()) < 0)
+    {
+        pd_error(x, "pd~: can't fork");
+        goto fail3;
+    }
+    else if (pid == 0)
+    {
+        /* child process */
+        if (pipe2[1] == 0)
+        {
+            dup2(pipe2[1], 20);
+            close(pipe2[1]);
+            pipe2[1] = 20;
+        }
+        dup2(pipe1[0], 0);
+        dup2(pipe2[1], 1);
+        if (pipe1[0] >= 2)
+            close(pipe1[0]);
+        if (pipe1[1] >= 2)
+            close(pipe1[1]);
+        if (pipe2[0] >= 2)
+            close(pipe2[0]);
+        if (pipe2[1] >= 2)
+            close(pipe2[1]);
+        execl("/bin/sh", "sh", "-c", cmdbuf, (char*)0);
+        _exit(1);
+    }
+        /* OK, we're parent */
+    close(pipe1[0]);
+    close(pipe2[1]);
+    x->x_outfd = fdopen(pipe1[1], "w");
+    x->x_infd = fdopen(pipe2[0], "r");
+    x->x_childpid = pid;
+    for (i = 0; i < fifo; i++)
+        fprintf(x->x_outfd, "%s", ";\n0;\n");
+    fflush(x->x_outfd);
+    if (!(x->x_msgbuf = calloc(MSGBUFSIZE, 1)))
+    {
+        pd_error(x, "pd~: can't allocate message buffer");
+        goto fail3;
+    }
+    x->x_msgbufsize = MSGBUFSIZE;
+    x->x_infill = 0;
+    fprintf(stderr, "read...\n");
+    pd_tilde_readmessages(x);
+    fprintf(stderr, "... done.\n");
+    return;
+fail3:
+    close(pipe2[0]);
+    close(pipe2[1]);
+    if (x->x_childpid > 0)
+        waitpid(x->x_childpid, 0, 0);
+fail2:
+    close(pipe1[0]);
+    close(pipe1[1]);
+fail1:
+    x->x_infd = x->x_outfd = 0;
+    x->x_childpid = -1;
+    return;
+}
+
+static t_int *pd_tilde_perform(t_int *w)
+{
+    t_pd_tilde *x = (t_pd_tilde *)(w[1]);
+    int n = (int)(w[2]), i, j, gotsomething = 0, setclock = 0,
+        numbuffill = 0, c;
+    char numbuf[80];
+    FILE *infd = x->x_infd;
+    if (!infd)
+        goto zeroit;
+    fprintf(x->x_outfd, ";\n");
+    for (i = 0; i < x->x_ninsig; i++)
+    {
+        t_sample *fp = x->x_insig[i];
+        for (j = 0; j < n; j++)
+            fprintf(x->x_outfd, "%g\n", *fp++);
+        for (; j < DEFDACBLKSIZE; j++)
+            fprintf(x->x_outfd, "0\n");
+    }
+    fprintf(x->x_outfd, ";\n");
+    fflush(x->x_outfd);
+    i = j = 0;
+    while (1)
+    {
+        while (1)
+        {
+            c = getc(infd);
+            if (c == EOF)
+            {
+                if (errno)
+                    pd_error(x, "pd~: %s", strerror(errno));
+                else pd_error(x, "pd~: subprocess exited");
+                pd_tilde_close(x);
+                goto zeroit;
+            }
+            else if (!isspace(c) && c != ';')
+            {
+                if (numbuffill < (80-1))
+                    numbuf[numbuffill++] = c;
+            }
+            else
+            {
+                t_sample z;
+                if (numbuffill)
+                {
+                    if (sscanf(numbuf, "%f", &z) < 1)
+                        continue;
+                    if (i < x->x_noutsig)
+                        x->x_outsig[i][j] = z;
+                    if (++j >= DEFDACBLKSIZE)
+                        j = 0, i++;
+                }
+                numbuffill = 0;
+                break;
+            }
+        }
+        /* message terminated */
+        if (c == ';')
+            break;
+    }
+    for (; i < x->x_noutsig; i++, j = 0)
+    {
+        for (; j < DEFDACBLKSIZE; j++)
+            x->x_outsig[i][j] = 0;
+    }
+    pd_tilde_readmessages(x);
+    return (w+3);
+zeroit:
+    for (i = 0; i < x->x_noutsig; i++)
+    {
+        for (j = 0; j < DEFDACBLKSIZE; j++)
+            x->x_outsig[i][j] = 0;
+    }
+    return (w+3);
+}
+
+static void pd_tilde_dsp(t_pd_tilde *x, t_signal **sp)
+{
+    int i, n = (x->x_ninsig || x->x_noutsig ? sp[0]->s_n : 1);
+    t_sample **g;
+        
+    for (i = 0, g = x->x_insig; i < x->x_ninsig; i++, g++)
+        *g = (*(sp++))->s_vec;
+    
+    for (i = 0, g = x->x_outsig; i < x->x_noutsig; i++, g++)
+        *g = (*(sp++))->s_vec;
+    
+    dsp_add(pd_tilde_perform, 2, x, n);
+}
+
+static void pd_tilde_free(t_pd_tilde *x)
+{
+#ifdef MSP
+    dsp_free((t_pxobject *)x);
+#endif
+    pd_tilde_close(x);
+    clock_free(x->x_clock);
+}
+
+/* -------------------------- Pd glue ------------------------- */
+#ifdef PD
+
+static void pd_tilde_tick(t_pd_tilde *x)
+{
+    int messstart = 0, i, n;
+    t_atom *vec;
+    t_binbuf *b = binbuf_new();
+    binbuf_text(b, x->x_msgbuf, x->x_infill);
+    /* binbuf_print(b); */
+    n = binbuf_getnatom(b);
+    vec = binbuf_getvec(b);
+    for (i = 0; i < n; i++)
+    {
+        if (vec[i].a_type == A_SEMI)
+        {
+            if (i > messstart + 1)
+            {
+                t_pd *whom;
+                if (vec[messstart].a_type != A_SYMBOL)
+                    bug("pd_tilde_tick");
+                else if (!(whom = vec[messstart].a_w.w_symbol->s_thing))
+                    pd_error(x, "%s: no such object",
+                        vec[messstart].a_w.w_symbol->s_name);
+                else if (vec[messstart+1].a_type == A_SYMBOL)
+                    typedmess(whom, vec[messstart+1].a_w.w_symbol,
+                        i-messstart-2, vec+(messstart+2));
+                else pd_list(whom, 0, i-messstart-1, vec+(messstart+1));
+            }
+            messstart = i+1;
+        }
+    }
+    binbuf_free(b);
+    x->x_infill = 0;
+}
+
+static void pd_tilde_anything(t_pd_tilde *x, t_symbol *s,
+    int argc, t_atom *argv)
+{
+    char msgbuf[MAXPDSTRING], *sp, *ep = msgbuf+MAXPDSTRING;
+    if (!x->x_outfd)
+        return;
+    msgbuf[0] = 0;
+    strncpy(msgbuf, s->s_name, MAXPDSTRING);
+    msgbuf[MAXPDSTRING-1] = 0;
+    sp = msgbuf + strlen(msgbuf);
+    while (argc--)
+    {
+        if (sp < ep-1)
+            sp[0] = ' ', sp[1] = 0, sp++;
+        atom_string(argv++, sp, ep-sp);
+        sp += strlen(sp);
+    }
+    fprintf(x->x_outfd, "%s;\n", msgbuf);
+}
+
+static void *pd_tilde_new(t_symbol *s, int argc, t_atom *argv)
+{
+    t_pd_tilde *x = (t_pd_tilde *)pd_new(pd_tilde_class);
+    int ninsig = 2, noutsig = 2, j, arglength, fifo = 5;
+    float sr = sys_getsr();
+    t_sample **g;
+    t_symbol *pddir = gensym("."),
+        *scheddir = gensym(class_gethelpdir(pd_tilde_class));
+    char pdargstring[MAXPDSTRING];
+    while (argc > 0)
+    {
+        t_symbol *firstarg = atom_getsymbolarg(0, argc, argv);
+        if (!strcmp(firstarg->s_name, "-sr") && argc > 1)
+        {
+            sr = atom_getfloatarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-ninsig") && argc > 1)
+        {
+            ninsig = atom_getfloatarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-noutsig") && argc > 1)
+        {
+            noutsig = atom_getfloatarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-fifo") && argc > 1)
+        {
+            fifo = atom_getfloatarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-pddir") && argc > 1)
+        {
+            pddir = atom_getsymbolarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
+        else if (!strcmp(firstarg->s_name, "-scheddir") && argc > 1)
+        {
+            scheddir = atom_getsymbolarg(1, argc, argv);
+            argc -= 2; argv += 2;
+        }
+        else break;
+    }
+#if 0
+        {
+            pd_error(x,
+"usage: pd~ [-sr #] [-ninsig #] [-noutsig #] [-fifo #] [-pddir <>]");
+            post(
+"... [-scheddir <>] [pd-argument...]");
+            argc = 0;
+        }
+#endif
+    
+    pdargstring[0] = 0;
+    while (argc--)
+    {
+        atom_string(argv++, pdargstring + strlen(pdargstring), 
+            MAXPDSTRING - strlen(pdargstring));
+        if (strlen(pdargstring) < MAXPDSTRING-1)
+            strcat(pdargstring, " ");
+    }
+    x->x_clock = clock_new(x, (t_method)pd_tilde_tick);
+    x->x_insig = (t_sample **)getbytes(ninsig * sizeof(*x->x_insig));
+    x->x_outsig = (t_sample **)getbytes(noutsig * sizeof(*x->x_outsig));
+    x->x_ninsig = ninsig;
+    x->x_noutsig = noutsig;
+    for (j = 1, g = x->x_insig; j < ninsig; j++, g++)
+        inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+    for (j = 0, g = x->x_outsig; j < noutsig; j++, g++)
+        outlet_new(&x->x_obj, &s_signal);
+    
+    pd_tilde_donew(x, pddir->s_name, scheddir->s_name, pdargstring,
+        ninsig, noutsig, fifo, sr);
+
+    return (x);
+}
+
+
+void pd_tilde_setup(void)
+{
+    pd_tilde_class = class_new(gensym("pd~"), (t_newmethod)pd_tilde_new,
+        (t_method)pd_tilde_free, sizeof(t_pd_tilde), 0, A_GIMME, 0);
+    class_addmethod(pd_tilde_class, nullfn, gensym("signal"), 0);
+    class_addmethod(pd_tilde_class, (t_method)pd_tilde_dsp, gensym("dsp"), 0);
+    class_addanything(pd_tilde_class, pd_tilde_anything);
+    post("pd~ version 0.1");
+}
+#endif
+
+/* -------------------------- MSP glue ------------------------- */
+#ifdef MSP
+
+void main()
+{       
+    t_class *c;
+    t_object *attr;
+    long attrflags = 0;
+    t_symbol *sym_long = gensym("long"), *sym_float32 = gensym("float32");
+
+    c = class_new("pd_tilde~", (method)pd_tilde_new, (method)pd_tilde_free, sizeof(t_pd_tilde), (method)0L, A_GIMME, 0);
+
+    class_obexoffset_set(c, calcoffset(t_pd_tilde, obex));
+
+    attr = attr_offset_new("npoints", sym_long, attrflags, (method)0L, (method)0L, calcoffset(t_pd_tilde, x_npoints));
+    class_addattr(c, attr);
+
+    class_addmethod(c, (method)pd_tilde_dsp, "dsp", A_CANT, 0);
+    class_addmethod(c, (method)pd_tilde_bang, "bang", A_CANT, 0);
+    class_addmethod(c, (method)pd_tilde_forget, "forget", 0);
+    class_addmethod(c, (method)pd_tilde_thresh, "thresh", A_FLOAT, A_FLOAT, 0);
+    class_addmethod(c, (method)pd_tilde_print, "print", A_DEFFLOAT, 0);
+    class_addmethod(c, (method)pd_tilde_read, "read", A_DEFSYM, 0);
+    class_addmethod(c, (method)pd_tilde_write, "write", A_DEFSYM, 0);
+    class_addmethod(c, (method)pd_tilde_assist, "assist", A_CANT, 0);
+
+    class_addmethod(c, (method)object_obex_dumpout, "dumpout", A_CANT, 0);
+    class_addmethod(c, (method)object_obex_quickref, "quickref", A_CANT, 0);
+
+    class_dspinit(c);
+
+    class_register(CLASS_BOX, c);
+    pd_tilde_class = c;
+}
+
+static void *pd_tilde_new(t_symbol *s, long ac, t_atom *av)
+{
+    short j;
+    t_pd_tilde *x;
+        
+    if (x = (t_pd_tilde *)object_alloc(pd_tilde_class)) {
+        
+        t_insig *g;
+        
+        if (ac) {
+            switch (av[0].a_type) {
+                case A_LONG:
+                    x->x_nsig = av[0].a_w.w_long;
+                    break;
+            }
+        }
+        
+        attr_args_process(x, ac, av);   
+
+        x->x_insig = (t_insig *)getbytes(x->x_nsig * sizeof(*x->x_insig));
+        
+        x->x_ninsig = x->x_nsig;
+
+        dsp_setup((t_pxobject *)x, x->x_nsig);
+
+        object_obex_store(x, gensym("dumpout"), outlet_new(x, NULL));
+
+        x->x_cookedout = listout((t_object *)x);
+
+        for (j = 0, g = x->x_insig + x->x_nsig-1; j < x->x_nsig; j++, g--)
+        {
+            g->g_outlet = listout((t_object *)x);
+        }
+
+        x->x_clock = clock_new(x, (method)pd_tilde_tick);
+
+        pd_tilde_donew(x, x->x_npoints, x->x_period, x->x_nsig, x->x_nfilters,
+            x->x_halftones, x->x_overlap, x->x_firstbin, sys_getsr());
+    }
+    return (x);
+}
+
+/* Attribute setters. */
+void pd_tilde_minvel_set(t_pd_tilde *x, void *attr, long ac, t_atom *av)
+{
+    if (ac && av) {
+        float f = atom_getfloat(av);
+        if (f < 0) f = 0; 
+        x->x_minvel = f;
+    }
+}
+
+/* end attr setters */
+
+void pd_tilde_assist(t_pd_tilde *x, void *b, long m, long a, char *s)
+{
+}
+
+#endif /* MSP */
diff --git a/extra/pd~/z.txt b/extra/pd~/z.txt
new file mode 100644
index 0000000000000000000000000000000000000000..89e279680b382063c616be633698ef3bbaeafbcf
--- /dev/null
+++ b/extra/pd~/z.txt
@@ -0,0 +1,128 @@
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
+0
diff --git a/extra/stdout/makefile b/extra/stdout/makefile
new file mode 100644
index 0000000000000000000000000000000000000000..67801999bf27df3cacaf2b8f8373bedbcc2d006d
--- /dev/null
+++ b/extra/stdout/makefile
@@ -0,0 +1,4 @@
+NAME=stdout
+CSYM=stdout
+
+include ../makefile
diff --git a/extra/stdout/stdout-help.pd b/extra/stdout/stdout-help.pd
new file mode 100644
index 0000000000000000000000000000000000000000..b3d024896238edc7043a72b24e650a27cfc9b846
--- /dev/null
+++ b/extra/stdout/stdout-help.pd
@@ -0,0 +1,13 @@
+#N canvas 110 37 789 525 10;
+#X msg 84 147 walk the dog;
+#X msg 91 169 1;
+#X msg 90 215 flush;
+#X obj 84 240 stdout;
+#X text 472 410 updated for Pd version 0.42;
+#X obj 14 13 stdout;
+#X text 67 14 - write messages to standard output;
+#X msg 96 192 1 2;
+#X connect 0 0 3 0;
+#X connect 1 0 3 0;
+#X connect 2 0 3 0;
+#X connect 7 0 3 0;
diff --git a/extra/stdout/stdout.c b/extra/stdout/stdout.c
new file mode 100644
index 0000000000000000000000000000000000000000..06c99308ba9839389af405c02ab3ca7776f24e02
--- /dev/null
+++ b/extra/stdout/stdout.c
@@ -0,0 +1,51 @@
+/* stdout -- write messages to standard output.
+
+  Copyright 2008 Miller Puckette
+  BSD license; see README.txt in this distribution for details.
+*/
+
+#include "m_pd.h"
+#include <stdio.h>
+#include <string.h>
+static t_class *stdout_class;
+
+typedef struct _stdout
+{
+    t_object x_obj;
+} t_stdout;
+
+static void *stdout_new(t_float fnonrepeat)
+{
+    t_stdout *x = (t_stdout *)pd_new(stdout_class);
+    return (x);
+}
+
+static void stdout_anything(t_stdout *x, t_symbol *s, int argc, t_atom *argv)
+{
+    char msgbuf[MAXPDSTRING], *sp, *ep = msgbuf+MAXPDSTRING;
+    msgbuf[0] = 0;
+    strncpy(msgbuf, s->s_name, MAXPDSTRING);
+    msgbuf[MAXPDSTRING-1] = 0;
+    sp = msgbuf + strlen(msgbuf);
+    while (argc--)
+    {
+        if (sp < ep-1)
+            sp[0] = ' ', sp[1] = 0, sp++;
+        atom_string(argv++, sp, ep-sp);
+        sp += strlen(sp);
+    }
+    printf("%s;\n", msgbuf);
+}
+
+static void stdout_flush(t_stdout *x)
+{
+    fflush(stdout);
+}
+
+void stdout_setup(void)
+{
+    stdout_class = class_new(gensym("stdout"), (t_newmethod)stdout_new,
+        (t_method)stdout_flush, sizeof(t_stdout), 0, 0);
+    class_addmethod(stdout_class, (t_method)stdout_flush, gensym("flush"), 0);
+    class_addanything(stdout_class, stdout_anything);
+}
diff --git a/src/CHANGELOG.txt b/src/CHANGELOG.txt
index 9620a7fae1925aba8885de15216490fa29290502..6d7891713967b613e589ce5c7c2d245ff3e47a3f 100644
--- a/src/CHANGELOG.txt
+++ b/src/CHANGELOG.txt
@@ -2,6 +2,11 @@ This file describes implementation and API changes; stuff more visible to the
 user appears in the "release notes" instead.  See the bottom of this file
 for original notes on source stype and organization.
 
+0.42.0 
+
+changed definition of t_float, t_sample, t_floatarg so that they can be
+set via #defines (PD_FLOATTYPE, etc).
+
 0.41.0
 
 add support for callback-based audio I/O
diff --git a/src/d_fftroutine.c b/src/d_fftroutine.c
index 4678d38a77797c4f4a6737ede8055352fcde6c01..0222a0c006ac522e93e1334f4ea5e59cf13eab86 100644
--- a/src/d_fftroutine.c
+++ b/src/d_fftroutine.c
@@ -98,7 +98,7 @@
 #define        FALSE                   0
 #endif
 
-#define        SAMPLE float     /* data type used in calculation */
+#define        SAMPLE PD_FLOATTYPE     /* data type used in calculation */
 
 #define        SHORT_SIZE              sizeof(short)
 #define        INT_SIZE                sizeof(int)
@@ -154,8 +154,8 @@ typedef struct Tfft_net {
 
 
 void cfft(int trnsfrm_dir, int npnt, int window,
-    float *source_buf, int source_form, int source_scale,
-    float *result_buf, int result_form, int result_scale, int debug);
+    SAMPLE *source_buf, int source_form, int source_scale,
+    SAMPLE *result_buf, int result_form, int result_scale, int debug);
 
 
 /*****************************************************************************/
@@ -172,10 +172,10 @@ int power_of_two(int n);
 void create_hanning(SAMPLE *window, int n, SAMPLE scale);
 void create_rectangular(SAMPLE *window, int n, SAMPLE scale);
 void short_to_float(short *short_buf, float *float_buf, int n);
-void load_registers(FFT_NET *fft_net, float *buf, int buf_form,
+void load_registers(FFT_NET *fft_net, SAMPLE *buf, int buf_form,
     int buf_scale, int trnsfrm_dir);
 void compute_fft(FFT_NET  *fft_net);
-void store_registers(FFT_NET    *fft_net, float *buf, int buf_form,
+void store_registers(FFT_NET    *fft_net, SAMPLE *buf, int buf_form,
     int buf_scale, int debug);
 void build_fft_network(FFT_NET *fft_net, int n, int window_type);
 
@@ -184,8 +184,8 @@ void build_fft_network(FFT_NET *fft_net, int n, int window_type);
 /*****************************************************************************/
 
 void cfft(int trnsfrm_dir, int npnt, int window,
-    float *source_buf, int source_form, int source_scale,
-    float *result_buf, int result_form, int result_scale, int debug)
+    SAMPLE *source_buf, int source_form, int source_scale,
+    SAMPLE *result_buf, int result_form, int result_scale, int debug)
 
 /* modifies: result_buf
    effects:  Computes npnt FFT specified by form, scale, and dir parameters.  
@@ -471,7 +471,7 @@ void build_fft_network(FFT_NET *fft_net, int n, int window_type)
 /* REGISTER LOAD AND STORE                                                   */
 /*****************************************************************************/
 
-void load_registers(FFT_NET *fft_net, float *buf, int buf_form,
+void load_registers(FFT_NET *fft_net, SAMPLE *buf, int buf_form,
     int buf_scale, int trnsfrm_dir)
 
 /* effects:  Multiplies the input buffer with the appropriate window and
@@ -605,7 +605,7 @@ void load_registers(FFT_NET *fft_net, float *buf, int buf_form,
 }
 
 
-void store_registers(FFT_NET    *fft_net, float *buf, int buf_form,
+void store_registers(FFT_NET    *fft_net, SAMPLE *buf, int buf_form,
     int buf_scale, int debug)
 
 /* modifies: buf
@@ -989,10 +989,10 @@ void short_to_float(short *short_buf, float *float_buf, int n)
 
 /* here's the meat: */
 
-void pd_fft(float *buf, int npoints, int inverse)
+void pd_fft(t_float *buf, int npoints, int inverse)
 {
   double renorm;
-  float *fp, *fp2;
+  SAMPLE *fp, *fp2;
   int i;
   renorm = (inverse ? npoints : 1.);
   cfft((inverse ? INVERSE : FORWARD), npoints, RECTANGULAR, 
diff --git a/src/d_math.c b/src/d_math.c
index 213b866e556fc174a4e21ed192ca0213437d22f9..738f2d6cdc0f913d22a64b46c45d1d717c555a82 100644
--- a/src/d_math.c
+++ b/src/d_math.c
@@ -97,7 +97,7 @@ static void init_rsqrt(void)
 
     /* these are used in externs like "bonk" */
 
-float q8_rsqrt(float f)
+t_float q8_rsqrt(t_float f)
 {
     long l = *(long *)(&f);
     if (f < 0) return (0);
@@ -105,7 +105,7 @@ float q8_rsqrt(float f)
             rsqrt_mantissatab[(l >> 13) & 0x3ff]);
 }
 
-float q8_sqrt(float f)
+t_float q8_sqrt(t_float f)
 {
     long l = *(long *)(&f);
     if (f < 0) return (0);
@@ -116,8 +116,8 @@ float q8_sqrt(float f)
     /* the old names are OK unless we're in IRIX N32 */
 
 #ifndef N32
-float qsqrt(float f) {return (q8_sqrt(f)); }
-float qrsqrt(float f) {return (q8_rsqrt(f)); }
+t_float qsqrt(t_float f) {return (q8_sqrt(f)); }
+t_float qrsqrt(t_float f) {return (q8_rsqrt(f)); }
 #endif
 
 
@@ -555,6 +555,189 @@ void powtodb_tilde_setup(void)
     class_addmethod(powtodb_tilde_class, (t_method)powtodb_tilde_dsp, gensym("dsp"), 0);
 }
 
+/* ----------------------------- pow ----------------------------- */
+static t_class *pow_tilde_class;
+
+typedef struct _pow_tilde
+{
+    t_object x_obj;
+    t_float x_f;
+} t_pow_tilde;
+
+static void *pow_tilde_new(t_symbol *s, int argc, t_atom *argv)
+{
+    t_pow_tilde *x = (t_pow_tilde *)pd_new(pow_tilde_class);
+    inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+    outlet_new(&x->x_obj, &s_signal);
+    x->x_f = 0;
+    return (x);
+}
+
+t_int *pow_tilde_perform(t_int *w)
+{
+    t_sample *in1 = (t_sample *)(w[1]);
+    t_sample *in2 = (t_sample *)(w[2]);
+    t_sample *out = (t_sample *)(w[3]);
+    int n = (int)(w[4]);
+    while (n--)
+    {
+        float f = *in1++;
+        if (f > 0)
+            *out = pow(f, *in2);
+        else *out = 0;
+        out++;
+        in2++;
+    }
+    return (w+5);
+}
+
+static void pow_tilde_dsp(t_pow_tilde *x, t_signal **sp)
+{
+    dsp_add(pow_tilde_perform, 4,
+        sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
+}
+
+static void pow_tilde_setup(void)
+{
+    pow_tilde_class = class_new(gensym("pow~"), (t_newmethod)pow_tilde_new, 0,
+        sizeof(t_pow_tilde), 0, A_DEFFLOAT, 0);
+    CLASS_MAINSIGNALIN(pow_tilde_class, t_pow_tilde, x_f);
+    class_addmethod(pow_tilde_class, (t_method)pow_tilde_dsp, gensym("dsp"), 0);
+}
+
+/* ----------------------------- exp ----------------------------- */
+static t_class *exp_tilde_class;
+
+typedef struct _exp_tilde
+{
+    t_object x_obj;
+    t_float x_f;
+} t_exp_tilde;
+
+static void *exp_tilde_new(t_symbol *s, int argc, t_atom *argv)
+{
+    t_exp_tilde *x = (t_exp_tilde *)pd_new(exp_tilde_class);
+    outlet_new(&x->x_obj, &s_signal);
+    return (x);
+}
+
+t_int *exp_tilde_perform(t_int *w)
+{
+    t_sample *in1 = (t_sample *)(w[1]);
+    t_sample *out = (t_sample *)(w[2]);
+    int n = (int)(w[3]);
+    while (n--)
+        *out = exp(*in1);
+    return (w+4);
+}
+
+static void exp_tilde_dsp(t_exp_tilde *x, t_signal **sp)
+{
+    dsp_add(exp_tilde_perform, 3,
+        sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
+}
+
+static void exp_tilde_setup(void)
+{
+    exp_tilde_class = class_new(gensym("exp~"), (t_newmethod)exp_tilde_new, 0,
+        sizeof(t_exp_tilde), 0, 0);
+    CLASS_MAINSIGNALIN(exp_tilde_class, t_exp_tilde, x_f);
+    class_addmethod(exp_tilde_class, (t_method)exp_tilde_dsp, gensym("dsp"), 0);
+}
+
+/* ----------------------------- log ----------------------------- */
+static t_class *log_tilde_class;
+
+typedef struct _log_tilde
+{
+    t_object x_obj;
+    t_float x_f;
+} t_log_tilde;
+
+static void *log_tilde_new(t_symbol *s, int argc, t_atom *argv)
+{
+    t_log_tilde *x = (t_log_tilde *)pd_new(log_tilde_class);
+    inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal);
+    outlet_new(&x->x_obj, &s_signal);
+    x->x_f = 0;
+    return (x);
+}
+
+t_int *log_tilde_perform(t_int *w)
+{
+    t_sample *in1 = (t_sample *)(w[1]);
+    t_sample *in2 = (t_sample *)(w[2]);
+    t_sample *out = (t_sample *)(w[3]);
+    int n = (int)(w[4]);
+    while (n--)
+    {
+        float f = *in1++, g = *in2++;
+        if (f <= 0)
+            *out = -1000;   /* rather than blow up, output a number << 0 */
+        else if (g <= 0)
+            *out = log(f);
+        else *out = log(f)/log(g);
+        out++;
+    }
+    return (w+5);
+}
+
+static void log_tilde_dsp(t_log_tilde *x, t_signal **sp)
+{
+    dsp_add(log_tilde_perform, 4,
+        sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n);
+}
+
+static void log_tilde_setup(void)
+{
+    log_tilde_class = class_new(gensym("log~"), (t_newmethod)log_tilde_new, 0,
+        sizeof(t_log_tilde), 0, A_DEFFLOAT, 0);
+    CLASS_MAINSIGNALIN(log_tilde_class, t_log_tilde, x_f);
+    class_addmethod(log_tilde_class, (t_method)log_tilde_dsp, gensym("dsp"), 0);
+}
+
+/* ----------------------------- abs ----------------------------- */
+static t_class *abs_tilde_class;
+
+typedef struct _abs_tilde
+{
+    t_object x_obj;
+    t_float x_f;
+} t_abs_tilde;
+
+static void *abs_tilde_new(t_symbol *s, int argc, t_atom *argv)
+{
+    t_abs_tilde *x = (t_abs_tilde *)pd_new(abs_tilde_class);
+    outlet_new(&x->x_obj, &s_signal);
+    return (x);
+}
+
+t_int *abs_tilde_perform(t_int *w)
+{
+    t_sample *in1 = (t_sample *)(w[1]);
+    t_sample *out = (t_sample *)(w[2]);
+    int n = (int)(w[3]);
+    while (n--)
+    {
+        float f = *in1++;
+        *out = (f >= 0 ? f : -f);
+    }
+    return (w+4);
+}
+
+static void abs_tilde_dsp(t_abs_tilde *x, t_signal **sp)
+{
+    dsp_add(abs_tilde_perform, 3,
+        sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
+}
+
+static void abs_tilde_setup(void)
+{
+    abs_tilde_class = class_new(gensym("abs~"), (t_newmethod)abs_tilde_new, 0,
+        sizeof(t_abs_tilde), 0, 0);
+    CLASS_MAINSIGNALIN(abs_tilde_class, t_abs_tilde, x_f);
+    class_addmethod(abs_tilde_class, (t_method)abs_tilde_dsp, gensym("dsp"), 0);
+}
 
 /* ------------------------ global setup routine ------------------------- */
 
@@ -571,6 +754,10 @@ void d_math_setup(void)
     rmstodb_tilde_setup();
     dbtopow_tilde_setup();
     powtodb_tilde_setup();
+    pow_tilde_setup();
+    exp_tilde_setup();
+    log_tilde_setup();
+    abs_tilde_setup();
 
     class_sethelpsymbol(mtof_tilde_class, s);
     class_sethelpsymbol(ftom_tilde_class, s);
diff --git a/src/g_array.c b/src/g_array.c
index 0ebc99fb814113dd47fdd0f2e4929699e4da37ae..a73c5ba544a07b9f9a8a5869f2bf9e90e8d368fc 100644
--- a/src/g_array.c
+++ b/src/g_array.c
@@ -1402,13 +1402,14 @@ static void garray_read(t_garray *x, t_symbol *filename)
     }
     for (i = 0; i < nelem; i++)
     {
-        if (!fscanf(fd, "%f", ((t_float *)(array->a_vec +
-            elemsize * i) + yonset)))
+        float f;
+        if (!fscanf(fd, "%f", &f))
         {
             post("%s: read %d elements into table of size %d",
                 filename->s_name, i, nelem);
             break;
         }
+        else *((t_float *)(array->a_vec + elemsize * i) + yonset) = f;
     }
     while (i < nelem)
         *((t_float *)(array->a_vec +
diff --git a/src/g_canvas.c b/src/g_canvas.c
index 36d3d3d64446d9d19e31903c5a708a7b60787b43..3220360f51a257401d6956a0ec4f09459ce47979 100644
--- a/src/g_canvas.c
+++ b/src/g_canvas.c
@@ -47,7 +47,7 @@ static void canvas_start_dsp(void);
 static void canvas_stop_dsp(void);
 static void canvas_drawlines(t_canvas *x);
 static void canvas_setbounds(t_canvas *x, int x1, int y1, int x2, int y2);
-static void canvas_reflecttitle(t_canvas *x);
+void canvas_reflecttitle(t_canvas *x);
 static void canvas_addtolist(t_canvas *x);
 static void canvas_takeofflist(t_canvas *x);
 static void canvas_pop(t_canvas *x, t_floatarg fvis);
@@ -682,144 +682,6 @@ void canvas_redraw(t_canvas *x)
     }
 }
 
-/* ----  editors -- perhaps this and "vis" should go to g_editor.c ------- */
-
-static t_editor *editor_new(t_glist *owner)
-{
-    char buf[40];
-    t_editor *x = (t_editor *)getbytes(sizeof(*x));
-    x->e_connectbuf = binbuf_new();
-    x->e_deleted = binbuf_new();
-    x->e_glist = owner;
-    sprintf(buf, ".x%lx", (t_int)owner);
-    x->e_guiconnect = guiconnect_new(&owner->gl_pd, gensym(buf));
-    return (x);
-}
-
-static void editor_free(t_editor *x, t_glist *y)
-{
-    glist_noselect(y);
-    guiconnect_notarget(x->e_guiconnect, 1000);
-    binbuf_free(x->e_connectbuf);
-    binbuf_free(x->e_deleted);
-    freebytes((void *)x, sizeof(*x));
-}
-
-    /* recursively create or destroy all editors of a glist and its 
-    sub-glists, as long as they aren't toplevels. */
-void canvas_create_editor(t_glist *x, int createit)
-{
-    t_gobj *y;
-    t_object *ob;
-    if (createit)
-    {
-        if (x->gl_editor)
-            bug("canvas_create_editor");
-        else
-        {
-            x->gl_editor = editor_new(x);
-            for (y = x->gl_list; y; y = y->g_next)
-                if (ob = pd_checkobject(&y->g_pd))
-                    rtext_new(x, ob);
-        }
-    }
-    else
-    {
-        if (!x->gl_editor)
-            bug("canvas_create_editor");
-        else
-        {
-            for (y = x->gl_list; y; y = y->g_next)
-                if (ob = pd_checkobject(&y->g_pd))
-                    rtext_free(glist_findrtext(x, ob));
-            editor_free(x->gl_editor, x);
-            x->gl_editor = 0;
-        }
-    }
-    for (y = x->gl_list; y; y = y->g_next)
-        if (pd_class(&y->g_pd) == canvas_class &&
-            ((t_canvas *)y)->gl_isgraph && !((t_canvas *)y)->gl_havewindow)
-                canvas_create_editor((t_canvas *)y, createit);
-}
-
-    /* we call this when we want the window to become visible, mapped, and
-    in front of all windows; or with "f" zero, when we want to get rid of
-    the window. */
-void canvas_vis(t_canvas *x, t_floatarg f)
-{
-    char buf[30];
-    int flag = (f != 0);
-    if (flag)
-    {
-        /* post("havewindow %d, isgraph %d, isvisible %d  editor %d",
-            x->gl_havewindow, x->gl_isgraph, glist_isvisible(x),
-                (x->gl_editor != 0)); */
-            /* test if we're already visible and toplevel */
-        if (x->gl_editor)
-        {           /* just put us in front */
-#ifdef MSW
-            canvas_vis(x, 0);
-            canvas_vis(x, 1);
-#else
-            sys_vgui("raise .x%lx\n", x);
-            sys_vgui("focus .x%lx.c\n", x);
-            sys_vgui("wm deiconify .x%lx\n", x);  
-#endif
-        }
-        else
-        {
-            canvas_create_editor(x, 1);
-            sys_vgui("pdtk_canvas_new .x%lx %d %d +%d+%d %d\n", x,
-                (int)(x->gl_screenx2 - x->gl_screenx1),
-                (int)(x->gl_screeny2 - x->gl_screeny1),
-                (int)(x->gl_screenx1), (int)(x->gl_screeny1),
-                x->gl_edit);
-            canvas_reflecttitle(x);
-            x->gl_havewindow = 1;
-            canvas_updatewindowlist();
-        }
-    }
-    else    /* make invisible */
-    {
-        int i;
-        t_canvas *x2;
-        if (!x->gl_havewindow)
-        {
-                /* bug workaround -- a graph in a visible patch gets "invised"
-                when the patch is closed, and must lose the editor here.  It's
-                probably not the natural place to do this.  Other cases like
-                subpatches fall here too but don'd need the editor freed, so
-                we check if it exists. */
-            if (x->gl_editor)
-                canvas_create_editor(x, 0);
-            return;
-        }
-        sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x);
-        glist_noselect(x);
-        if (glist_isvisible(x))
-            canvas_map(x, 0);
-        canvas_create_editor(x, 0);
-        sys_vgui("destroy .x%lx\n", x);
-        for (i = 1, x2 = x; x2; x2 = x2->gl_next, i++)
-            ;
-        sys_vgui(".mbar.find delete %d\n", i);
-            /* if we're a graph on our parent, and if the parent exists
-               and is visible, show ourselves on parent. */
-        if (glist_isgraph(x) && x->gl_owner)
-        {
-            t_glist *gl2 = x->gl_owner;
-            if (!x->gl_owner->gl_isdeleting)
-                canvas_create_editor(x, 1);
-            if (glist_isvisible(gl2))
-                gobj_vis(&x->gl_gobj, gl2, 0);
-            x->gl_havewindow = 0;
-            if (glist_isvisible(gl2))
-                gobj_vis(&x->gl_gobj, gl2, 1);
-        }
-        else x->gl_havewindow = 0;
-        canvas_updatewindowlist();
-    }
-}
 
     /* we call this on a non-toplevel glist to "open" it into its
     own window. */
@@ -835,7 +697,8 @@ void glist_menu_open(t_glist *x)
                 /* erase ourself in parent window */
             gobj_vis(&x->gl_gobj, gl2, 0);
                     /* get rid of our editor (and subeditors) */
-            canvas_create_editor(x, 0);
+            if (x->gl_editor)
+                canvas_create_editor(x, 0);
             x->gl_havewindow = 1;
                     /* redraw ourself in parent window (blanked out this time) */
             gobj_vis(&x->gl_gobj, gl2, 1);
@@ -1475,6 +1338,22 @@ void canvas_savedeclarationsto(t_canvas *x, t_binbuf *b)
     }
 }
 
+static void canvas_completepath(char *from, char *to, int bufsize)
+{
+    if (sys_isabsolutepath(from))
+    {
+        to[0] = '\0';
+    }
+    else
+    {   // if not absolute path, append Pd lib dir
+        strncpy(to, sys_libdir->s_name, bufsize-4);
+        to[bufsize-3] = '\0';
+        strcat(to, "/");
+    }
+    strncat(to, from, bufsize-strlen(to));
+    to[bufsize-1] = '\0';
+}
+
 static void canvas_declare(t_canvas *x, t_symbol *s, int argc, t_atom *argv)
 {
     int i;
@@ -1496,12 +1375,8 @@ static void canvas_declare(t_canvas *x, t_symbol *s, int argc, t_atom *argv)
         }
         else if ((argc > i+1) && !strcmp(flag, "-stdpath"))
         {
-            strncpy(strbuf, sys_libdir->s_name, MAXPDSTRING-3);
-            strbuf[MAXPDSTRING-4] = 0;
-            strcat(strbuf, "/");
-            strncpy(strbuf, atom_getsymbolarg(i+1, argc, argv)->s_name,
-                MAXPDSTRING-strlen(strbuf));
-            strbuf[MAXPDSTRING-1] = 0;
+            canvas_completepath(atom_getsymbolarg(i+1, argc, argv)->s_name,
+                strbuf, MAXPDSTRING);
             e->ce_path = namelist_append(e->ce_path, strbuf, 0);
             i++;
         }
@@ -1512,12 +1387,8 @@ static void canvas_declare(t_canvas *x, t_symbol *s, int argc, t_atom *argv)
         }
         else if ((argc > i+1) && !strcmp(flag, "-stdlib"))
         {
-            strncpy(strbuf, sys_libdir->s_name, MAXPDSTRING-3);
-            strbuf[MAXPDSTRING-4] = 0;
-            strcat(strbuf, "/");
-            strncpy(strbuf, atom_getsymbolarg(i+1, argc, argv)->s_name,
-                MAXPDSTRING-strlen(strbuf));
-            strbuf[MAXPDSTRING-1] = 0;
+            canvas_completepath(atom_getsymbolarg(i+1, argc, argv)->s_name,
+                strbuf, MAXPDSTRING);
             sys_load_lib(0, strbuf);
             i++;
         }
@@ -1564,9 +1435,16 @@ int canvas_open(t_canvas *x, const char *name, const char *ext,
         for (nl = y->gl_env->ce_path; nl; nl = nl->nl_next)
         {
             char realname[MAXPDSTRING];
-            strncpy(realname, dir, MAXPDSTRING);
-            realname[MAXPDSTRING-3] = 0;
-            strcat(realname, "/");
+            if (sys_isabsolutepath(nl->nl_string))
+            {
+                realname[0] = '\0';
+            }
+            else
+            {   /* if not absolute path, append Pd lib dir */
+                strncpy(realname, dir, MAXPDSTRING);
+                realname[MAXPDSTRING-3] = 0;
+                strcat(realname, "/");
+            }
             strncat(realname, nl->nl_string, MAXPDSTRING-strlen(realname));
             realname[MAXPDSTRING-1] = 0;
             if ((fd = sys_trytoopenone(realname, name, ext,
diff --git a/src/g_canvas.h b/src/g_canvas.h
index e2b6626a4cf4eb7fac446046ccc6ed7e7a0b62bc..c074ad5c1e9012bd5026195b7fa61d4ff3ad1d9d 100644
--- a/src/g_canvas.h
+++ b/src/g_canvas.h
@@ -7,8 +7,8 @@ functions.  "Glists" and "canvases" and "graphs" used to be different
 structures until being unified in version 0.35.
 
 A glist occupies its own window if the "gl_havewindow" flag is set.  Its
-appearance on its "parent" or "owner" (if it has one) is as a graph if
-"gl_isgraph" is set, and otherwise as a text box.
+appearance on its "parent", also called "owner", (if it has one) is as a graph
+if "gl_isgraph" is set, and otherwise as a text box.
 
 A glist is "root" if it has no owner, i.e., a document window.  In this
 case "gl_havewindow" is always set.
@@ -353,6 +353,7 @@ EXTERN int gobj_click(t_gobj *x, struct _glist *glist,
 EXTERN void gobj_save(t_gobj *x, t_binbuf *b);
 EXTERN void gobj_properties(t_gobj *x, struct _glist *glist);
 EXTERN void gobj_save(t_gobj *x, t_binbuf *b);
+EXTERN int gobj_shouldvis(t_gobj *x, struct _glist *glist);
 
 /* -------------------- functions on glists --------------------- */
 EXTERN t_glist *glist_new( void);
@@ -414,7 +415,6 @@ EXTERN int text_xcoord(t_text *x, t_glist *glist);
 EXTERN int text_ycoord(t_text *x, t_glist *glist);
 EXTERN int text_xpix(t_text *x, t_glist *glist);
 EXTERN int text_ypix(t_text *x, t_glist *glist);
-EXTERN int text_shouldvis(t_text *x, t_glist *glist);
 
 /* -------------------- functions on rtexts ------------------------- */
 #define RTEXT_DOWN 1
diff --git a/src/g_editor.c b/src/g_editor.c
index a44d952a3e3c9a486bee9f7b9e56d4bfe27f3ea6..ee2a76ac531304daddbcd9964e636f0a315a3af9 100644
--- a/src/g_editor.c
+++ b/src/g_editor.c
@@ -61,28 +61,43 @@ void gobj_delete(t_gobj *x, t_glist *glist)
         (*x->g_pd->c_wb->w_deletefn)(x, glist);
 }
 
+int gobj_shouldvis(t_gobj *x, struct _glist *glist)
+{
+    t_object *ob;
+    if (!glist->gl_havewindow && glist->gl_isgraph && glist->gl_goprect &&
+        glist->gl_owner && (pd_class(&glist->gl_pd) != garray_class))
+    {
+        /* if we're graphing-on-parent and the object falls outside the
+        graph rectangle, don't draw it. */
+        int x1, y1, x2, y2, gx1, gy1, gx2, gy2, m;
+        gobj_getrect(&glist->gl_gobj, glist->gl_owner, &x1, &y1, &x2, &y2);
+        if (x1 > x2)
+            m = x1, x1 = x2, x2 = m;
+        if (y1 > y2)
+            m = y1, y1 = y2, y2 = m;
+        gobj_getrect(x, glist, &gx1, &gy1, &gx2, &gy2);
+        if (gx1 < x1 || gx1 > x2 || gx2 < x1 || gx2 > x2 ||
+            gy1 < y1 || gy1 > y2 || gy2 < y1 || gy2 > y2)
+                return (0);
+    }
+    if (ob = pd_checkobject(&x->g_pd))
+    {
+        /* return true if the text box should be drawn.  We don't show text
+        boxes inside graphs---except comments, if we're doing the new
+        (goprect) style. */
+        return (glist->gl_havewindow ||
+            (ob->te_pd != canvas_class &&
+                ob->te_pd->c_wb != &text_widgetbehavior) ||
+            (ob->te_pd == canvas_class && (((t_glist *)ob)->gl_isgraph)) ||
+            (glist->gl_goprect && (ob->te_type == T_TEXT)));
+    }
+    else return (1);
+}
+
 void gobj_vis(t_gobj *x, struct _glist *glist, int flag)
 {
-    if (x->g_pd->c_wb && x->g_pd->c_wb->w_visfn)
-    {
-        if (!glist->gl_havewindow && glist->gl_isgraph && glist->gl_goprect &&
-            glist->gl_owner && (pd_class(&glist->gl_pd) != garray_class))
-        {
-            /* if we're graphing-on-parent and the object falls outside the
-            graph rectangle, don't draw it. */
-            int x1, y1, x2, y2, gx1, gy1, gx2, gy2, m;
-            gobj_getrect(&glist->gl_gobj, glist->gl_owner, &x1, &y1, &x2, &y2);
-            if (x1 > x2)
-                m = x1, x1 = x2, x2 = m;
-            if (y1 > y2)
-                m = y1, y1 = y2, y2 = m;
-            gobj_getrect(x, glist, &gx1, &gy1, &gx2, &gy2);
-            if (gx1 < x1 || gx1 > x2 || gx2 < x1 || gx2 > x2 ||
-                gy1 < y1 || gy1 > y2 || gy2 < y1 || gy2 > y2)
-                    return;
-        }
+    if (x->g_pd->c_wb && x->g_pd->c_wb->w_visfn && gobj_shouldvis(x, glist))
         (*x->g_pd->c_wb->w_visfn)(x, glist, flag);
-    }
 }
 
 int gobj_click(t_gobj *x, struct _glist *glist,
@@ -765,9 +780,8 @@ int canvas_hitbox(t_canvas *x, t_gobj *y, int xpos, int ypos,
 {
     int x1, y1, x2, y2;
     t_text *ob;
-    if ((ob = pd_checkobject(&y->g_pd)) && 
-        !text_shouldvis(ob, x))
-            return (0);
+    if (!gobj_shouldvis(y, x))
+        return (0);
     gobj_getrect(y, x, &x1, &y1, &x2, &y2);
     if (xpos >= x1 && xpos <= x2 && ypos >= y1 && ypos <= y2)
     {
@@ -817,12 +831,157 @@ static void canvas_rightclick(t_canvas *x, int xpos, int ypos, t_gobj *y)
         x, xpos, ypos, canprop, canopen);
 }
 
+/* ----  editors -- perhaps this and "vis" should go to g_editor.c ------- */
+
+static t_editor *editor_new(t_glist *owner)
+{
+    char buf[40];
+    t_editor *x = (t_editor *)getbytes(sizeof(*x));
+    x->e_connectbuf = binbuf_new();
+    x->e_deleted = binbuf_new();
+    x->e_glist = owner;
+    sprintf(buf, ".x%lx", (t_int)owner);
+    x->e_guiconnect = guiconnect_new(&owner->gl_pd, gensym(buf));
+    return (x);
+}
+
+static void editor_free(t_editor *x, t_glist *y)
+{
+    glist_noselect(y);
+    guiconnect_notarget(x->e_guiconnect, 1000);
+    binbuf_free(x->e_connectbuf);
+    binbuf_free(x->e_deleted);
+    freebytes((void *)x, sizeof(*x));
+}
+
+    /* recursively create or destroy all editors of a glist and its 
+    sub-glists, as long as they aren't toplevels. */
+void canvas_create_editor(t_glist *x, int createit)
+{
+    t_gobj *y;
+    t_object *ob;
+    if (createit)
+    {
+        if (x->gl_editor)
+            bug("canvas_create_editor");
+        else
+        {
+            x->gl_editor = editor_new(x);
+            for (y = x->gl_list; y; y = y->g_next)
+                if (ob = pd_checkobject(&y->g_pd))
+                    rtext_new(x, ob);
+        }
+    }
+    else
+    {
+        if (!x->gl_editor)
+            bug("canvas_create_editor");
+        else
+        {
+            for (y = x->gl_list; y; y = y->g_next)
+                if (ob = pd_checkobject(&y->g_pd))
+                    rtext_free(glist_findrtext(x, ob));
+            editor_free(x->gl_editor, x);
+            x->gl_editor = 0;
+        }
+    }
+    for (y = x->gl_list; y; y = y->g_next)
+        if (pd_class(&y->g_pd) == canvas_class &&
+            ((t_canvas *)y)->gl_isgraph && !((t_canvas *)y)->gl_havewindow)
+                canvas_create_editor((t_canvas *)y, createit);
+}
+
+void canvas_reflecttitle(t_canvas *x);
+void canvas_map(t_canvas *x, t_floatarg f);
+
+    /* we call this when we want the window to become visible, mapped, and
+    in front of all windows; or with "f" zero, when we want to get rid of
+    the window. */
+void canvas_vis(t_canvas *x, t_floatarg f)
+{
+    char buf[30];
+    int flag = (f != 0);
+    if (flag)
+    {
+        /* post("havewindow %d, isgraph %d, isvisible %d  editor %d",
+            x->gl_havewindow, x->gl_isgraph, glist_isvisible(x),
+                (x->gl_editor != 0)); */
+            /* test if we're already visible and toplevel */
+        if (x->gl_editor)
+        {           /* just put us in front */
+#ifdef MSW
+            canvas_vis(x, 0);
+            canvas_vis(x, 1);
+#else
+            sys_vgui("raise .x%lx\n", x);
+            sys_vgui("focus .x%lx.c\n", x);
+            sys_vgui("wm deiconify .x%lx\n", x);  
+#endif
+        }
+        else
+        {
+            canvas_create_editor(x, 1);
+            sys_vgui("pdtk_canvas_new .x%lx %d %d +%d+%d %d\n", x,
+                (int)(x->gl_screenx2 - x->gl_screenx1),
+                (int)(x->gl_screeny2 - x->gl_screeny1),
+                (int)(x->gl_screenx1), (int)(x->gl_screeny1),
+                x->gl_edit);
+            canvas_reflecttitle(x);
+            x->gl_havewindow = 1;
+            canvas_updatewindowlist();
+        }
+    }
+    else    /* make invisible */
+    {
+        int i;
+        t_canvas *x2;
+        if (!x->gl_havewindow)
+        {
+                /* bug workaround -- a graph in a visible patch gets "invised"
+                when the patch is closed, and must lose the editor here.  It's
+                probably not the natural place to do this.  Other cases like
+                subpatches fall here too but don'd need the editor freed, so
+                we check if it exists. */
+            if (x->gl_editor)
+                canvas_create_editor(x, 0);
+            return;
+        }
+        sys_vgui("pdtk_canvas_getscroll .x%lx.c\n", x);
+        glist_noselect(x);
+        if (glist_isvisible(x))
+            canvas_map(x, 0);
+        canvas_create_editor(x, 0);
+        sys_vgui("destroy .x%lx\n", x);
+        for (i = 1, x2 = x; x2; x2 = x2->gl_next, i++)
+            ;
+        sys_vgui(".mbar.find delete %d\n", i);
+            /* if we're a graph on our parent, and if the parent exists
+               and is visible, show ourselves on parent. */
+        if (glist_isgraph(x) && x->gl_owner)
+        {
+            t_glist *gl2 = x->gl_owner;
+            if (!x->gl_owner->gl_isdeleting)
+                canvas_create_editor(x, 1);
+            if (glist_isvisible(gl2))
+                gobj_vis(&x->gl_gobj, gl2, 0);
+            x->gl_havewindow = 0;
+            if (glist_isvisible(gl2))
+                gobj_vis(&x->gl_gobj, gl2, 1);
+        }
+        else x->gl_havewindow = 0;
+        canvas_updatewindowlist();
+    }
+}
+
     /* set a canvas up as a graph-on-parent.  Set reasonable defaults for
     any missing paramters and redraw things if necessary. */
 void canvas_setgraph(t_glist *x, int flag, int nogoprect)
 {
     if (!flag && glist_isgraph(x))
     {
+        int hadeditor = (x->gl_editor != 0);
+        if (hadeditor)
+            canvas_create_editor(x, 0);
         if (x->gl_owner && !x->gl_loading && glist_isvisible(x->gl_owner))
             gobj_vis(&x->gl_gobj, x->gl_owner, 0);
         x->gl_isgraph = 0;
@@ -831,6 +990,8 @@ void canvas_setgraph(t_glist *x, int flag, int nogoprect)
             gobj_vis(&x->gl_gobj, x->gl_owner, 1);
             canvas_fixlinesfor(x->gl_owner, &x->gl_obj);
         }
+        if (hadeditor)
+            canvas_create_editor(x, 1);
     }
     else if (flag)
     {
diff --git a/src/g_graph.c b/src/g_graph.c
index f4196def136bb0f69364113b899c0d46a41ea385..cfda6c2ca14d90ed8d4e8f121399acdcfcd9aa56 100644
--- a/src/g_graph.c
+++ b/src/g_graph.c
@@ -176,8 +176,9 @@ void glist_grab(t_glist *x, t_gobj *y, t_glistmotionfn motionfn,
 
 t_canvas *glist_getcanvas(t_glist *x)
 {
-    while (x->gl_owner && !x->gl_havewindow && x->gl_isgraph)
-        x = x->gl_owner;
+    while (x->gl_owner && !x->gl_havewindow && x->gl_isgraph &&
+        gobj_shouldvis(&x->gl_gobj, x->gl_owner))
+            x = x->gl_owner;
     return((t_canvas *)x);
 }
 
@@ -671,7 +672,6 @@ void glist_redraw(t_glist *x)
 
 /* --------------------------- widget behavior  ------------------- */
 
-extern t_widgetbehavior text_widgetbehavior;
 int garray_getname(t_garray *x, t_symbol **namep);
 
 
@@ -904,7 +904,7 @@ static void graph_getrect(t_gobj *z, t_glist *glist,
             hadwindow = x->gl_havewindow;
             x->gl_havewindow = 0;
             for (g = x->gl_list; g; g = g->g_next)
-                if ((!(ob = pd_checkobject(&g->g_pd))) || text_shouldvis(ob, x))
+                if (gobj_shouldvis(g, x))
             {
                     /* don't do this for arrays, just let them hang outside the
                     box. */
@@ -1107,8 +1107,6 @@ void g_graph_setup(void)
         A_SYMBOL, A_FLOAT, A_SYMBOL, A_DEFFLOAT, A_NULL);
     class_addmethod(canvas_class, (t_method)canvas_menuarray,
         gensym("menuarray"), A_NULL);
-    class_addmethod(canvas_class, (t_method)glist_arraydialog,
-        gensym("arraydialog"), A_SYMBOL, A_FLOAT, A_FLOAT, A_FLOAT, A_NULL);
     class_addmethod(canvas_class, (t_method)glist_sort,
         gensym("sort"), A_NULL);
 }
diff --git a/src/g_template.c b/src/g_template.c
index 4d66bbed55d1bd91e648945c4a8e0715d8b1198c..aff6f7cb443e5da78891836cf0a8c800f236654e 100644
--- a/src/g_template.c
+++ b/src/g_template.c
@@ -721,11 +721,11 @@ struct _fielddesc
         t_symbol *fd_symbol;    /* the field is a constant symbol */
         t_symbol *fd_varsym;    /* the field is variable and this is the name */
     } fd_un;
-    t_float fd_v1;        /* min and max values */
-    t_float fd_v2;
-    t_float fd_screen1;   /* min and max screen values */
-    t_float fd_screen2;
-    t_float fd_quantum;   /* quantization in value */ 
+    float fd_v1;        /* min and max values */
+    float fd_v2;
+    float fd_screen1;   /* min and max screen values */
+    float fd_screen2;
+    float fd_quantum;   /* quantization in value */ 
 };
 
 static void fielddesc_setfloat_const(t_fielddesc *fd, t_float f)
@@ -2225,7 +2225,7 @@ static void drawnumber_key(void *z, t_floatarg fkey)
     else
     {
             /* key entry for a numeric field.  This is just a stopgap. */
-        t_float newf;
+        float newf;
         if (drawnumber_motion_firstkey)
             sbuf[0] = 0;
         else sprintf(sbuf, "%g", template_getfloat(drawnumber_motion_template,
diff --git a/src/g_text.c b/src/g_text.c
index bbdb7729d3a980bec4299bf1398b5b269f62e0d0..1d4559ecd36464e40b28faea2f4b734a97c92a71 100644
--- a/src/g_text.c
+++ b/src/g_text.c
@@ -989,7 +989,7 @@ static void text_select(t_gobj *z, t_glist *glist, int state)
     t_text *x = (t_text *)z;
     t_rtext *y = glist_findrtext(glist, x);
     rtext_select(y, state);
-    if (glist_isvisible(glist) && text_shouldvis(x, glist))
+    if (glist_isvisible(glist) && gobj_shouldvis(&x->te_g, glist))
         sys_vgui(".x%lx.c itemconfigure %sR -fill %s\n", glist, 
             rtext_gettag(y), (state? "blue" : "black"));
 }
@@ -1007,22 +1007,12 @@ static void text_delete(t_gobj *z, t_glist *glist)
     canvas_deletelinesfor(glist, x);
 }
 
-    /* return true if the text box should be drawn.  We don't show text boxes
-    inside graphs---except comments, if we're doing the new (goprect) style. */
-int text_shouldvis(t_text *x, t_glist *glist)
-{
-    return (glist->gl_havewindow ||
-        (x->te_pd != canvas_class && x->te_pd->c_wb != &text_widgetbehavior) ||
-        (x->te_pd == canvas_class && (((t_glist *)x)->gl_isgraph)) ||
-        (glist->gl_goprect && (x->te_type == T_TEXT)));
-}
-
 static void text_vis(t_gobj *z, t_glist *glist, int vis)
 {
     t_text *x = (t_text *)z;
     if (vis)
     {
-        if (text_shouldvis(x, glist))
+        if (gobj_shouldvis(&x->te_g, glist))
         {
             t_rtext *y = glist_findrtext(glist, x);
             if (x->te_type == T_ATOM)
@@ -1035,7 +1025,7 @@ static void text_vis(t_gobj *z, t_glist *glist, int vis)
     else
     {
         t_rtext *y = glist_findrtext(glist, x);
-        if (text_shouldvis(x, glist))
+        if (gobj_shouldvis(&x->te_g, glist))
         {
             text_eraseborder(x, glist, rtext_gettag(y));
             rtext_erase(y);
diff --git a/src/m_class.c b/src/m_class.c
index ab0b86bed226bfb76ed33e4b14a656f5ca8e53f0..cd4fbb1c60d0086b1988f0927a2f224bb2c46514 100644
--- a/src/m_class.c
+++ b/src/m_class.c
@@ -18,6 +18,10 @@
 #include <string.h>
 #include <stdio.h>
 
+#ifdef _MSC_VER  /* This is only for Microsoft's compiler, not cygwin, e.g. */
+#define snprintf sprintf_s
+#endif
+
 static t_symbol *class_loadsym;     /* name under which an extern is invoked */
 static void pd_defaultfloat(t_pd *x, t_float f);
 static void pd_defaultlist(t_pd *x, t_symbol *s, int argc, t_atom *argv);
@@ -149,7 +153,6 @@ static void pd_defaultlist(t_pd *x, t_symbol *s, int argc, t_atom *argv)
     argument form, one for the multiple one; see select_setup() to find out
     how this is handled.  */
 
-extern t_widgetbehavior text_widgetbehavior;
 extern void text_save(t_gobj *z, t_binbuf *b);
 
 t_class *class_new(t_symbol *s, t_newmethod newmethod, t_method freemethod,
@@ -168,7 +171,7 @@ t_class *class_new(t_symbol *s, t_newmethod newmethod, t_method freemethod,
     {
         if (count == MAXPDARG)
         {
-            error("class %s: sorry: only %d creation args allowed",
+            error("class %s: sorry: only %d args typechecked; use A_GIMME",
                 s->s_name, MAXPDARG);
             break;
         }
@@ -300,6 +303,19 @@ void class_addmethod(t_class *c, t_method fn, t_symbol *sel,
     }
     else
     {
+        int i;
+        for (i = 0; i < c->c_nmethod; i++)
+            if (c->c_methods[i].me_name == sel)
+        {
+            char nbuf[80];
+            snprintf(nbuf, 80, "%s_aliased", sel->s_name);
+            c->c_methods[i].me_name = gensym(nbuf);
+            if (c == pd_objectmaker)
+                post("warning: class '%s' overwritten; old one renamed '%s'",
+                    sel->s_name, nbuf);
+            else post("warning: old method '%s' for class '%s' renamed '%s'",
+                sel->s_name, c->c_name->s_name, nbuf);
+        }
         c->c_methods = t_resizebytes(c->c_methods,
             c->c_nmethod * sizeof(*c->c_methods),
             (c->c_nmethod + 1) * sizeof(*c->c_methods));
@@ -753,19 +769,22 @@ badarg:
         s->s_name, c->c_name->s_name);
 }
 
+    /* convenience routine giving a stdarg interface to typedmess().  Only
+    ten args supported; it seems unlikely anyone will need more since
+    longer messages are likely to be programmatically generated anyway. */
 void pd_vmess(t_pd *x, t_symbol *sel, char *fmt, ...)
 {
     va_list ap;
-    t_atom arg[MAXPDARG], *at =arg;
+    t_atom arg[10], *at = arg;
     int nargs = 0;
     char *fp = fmt;
 
     va_start(ap, fmt);
     while (1)
     {
-        if (nargs > MAXPDARG)
+        if (nargs >= 10)
         {
-            pd_error(x, "pd_vmess: only %d allowed", MAXPDARG);
+            pd_error(x, "pd_vmess: only 10 allowed");
             break;
         }
         switch(*fp++)
diff --git a/src/m_pd.h b/src/m_pd.h
index 580bac0b8ea2a3dc0bdb3ddacb63993eb0fd37e5..f48a13b915f6f5460b388d98a9ec89ae203a1574 100644
--- a/src/m_pd.h
+++ b/src/m_pd.h
@@ -9,9 +9,9 @@ extern "C" {
 #endif
 
 #define PD_MAJOR_VERSION 0
-#define PD_MINOR_VERSION 41
-#define PD_BUGFIX_VERSION 4
-#define PD_TEST_VERSION ""
+#define PD_MINOR_VERSION 42
+#define PD_BUGFIX_VERSION 0
+#define PD_TEST_VERSION "test1"
 
 /* old name for "MSW" flag -- we have to take it for the sake of many old
 "nmakefiles" for externs, which will define NT and not MSW */
@@ -55,11 +55,15 @@ extern "C" {
 #define MAXPDARG 5              /* max number of args we can typecheck today */
 
 /* signed and unsigned integer types the size of a pointer:  */
-/* GG: long is the size of a pointer */
-typedef long t_int;
-
-typedef float t_float;  /* a floating-point number at most the same size */
-typedef float t_floatarg;  /* floating-point type for function calls */
+#if !defined(PD_LONGINTTYPE)
+#define PD_LONGINTTYPE long
+#endif
+#if !defined(PD_FLOATTYPE)
+#define PD_FLOATTYPE float
+#endif
+typedef PD_LONGINTTYPE t_int;       /* pointer-size integer */
+typedef PD_FLOATTYPE t_float;       /* a float type at most the same size */
+typedef PD_FLOATTYPE t_floatarg;    /* float type for function calls */
 
 typedef struct _symbol
 {
@@ -443,7 +447,7 @@ EXTERN t_propertiesfn class_getpropertiesfn(t_class *c);
 EXTERN void post(const char *fmt, ...);
 EXTERN void startpost(const char *fmt, ...);
 EXTERN void poststring(const char *s);
-EXTERN void postfloat(float f);
+EXTERN void postfloat(t_floatarg f);
 EXTERN void postatom(int argc, t_atom *argv);
 EXTERN void endpost(void);
 EXTERN void error(const char *fmt, ...);
@@ -457,6 +461,7 @@ EXTERN void sys_ouch(void);
 
 /* ------------  system interface routines ------------------- */
 EXTERN int sys_isreadablefile(const char *name);
+EXTERN int sys_isabsolutepath(const char *dir);
 EXTERN void sys_bashfilename(const char *from, char *to);
 EXTERN void sys_unbashfilename(const char *from, char *to);
 EXTERN int open_via_path(const char *name, const char *ext, const char *dir,
@@ -474,7 +479,7 @@ EXTERN int sys_trylock(void);
 
 /* --------------- signals ----------------------------------- */
 
-typedef float t_sample;
+typedef PD_FLOATTYPE t_sample;
 #define MAXLOGSIG 32
 #define MAXSIGSIZE (1 << MAXLOGSIG)
 
diff --git a/src/notes.txt b/src/notes.txt
index ea8ed631d312e76b6330751c5b7816c96ccb0873..622b6548a327a4a3f65e11185a34b8dcd39cacc1 100644
--- a/src/notes.txt
+++ b/src/notes.txt
@@ -1,4 +1,6 @@
 ---------------- dolist --------------------
+done: 
+
 test:
 compile on various versions of linux
 windows:
@@ -43,6 +45,7 @@ scofo reports error on reading score1.txt
 loading e-mailed patches without removing headers crashes pd
 check if _vsnprintf with zero argument in windows works any better...
 detect adc~ and dac~ reblocking
+wierd bug: help doesn't work if pd is started in 5.reference directory
 
 more demonstration patches:
 vibrato using variable delay
@@ -50,6 +53,8 @@ real-time spectrum grapher
 document ||, |, etc, better
 
 features:
+pasting should look at current mouse location
+optionally suppress leading "." directories and files on "open"
 change config.h to #ifdef _MSC_VER (include MSW fake) else include a real one
 stick snprintf alias in the MSW fake.
 flag to prevent unlocking patches
@@ -80,7 +85,6 @@ tables:
     flag to hide array names 
 think of a way to embed abstractions in a patch
 make watchdog work for MACOSX
-pasting should look at current mouse location
 delete-in-rectangle message to Pds
 put serial object in main dist (see rat@telecoma, Apr. 25; winfried May 22)
 open/save panel to take messages to init directory, and to set extent list
diff --git a/src/s_loader.c b/src/s_loader.c
index aac508985cefca41c255558782b70b03e4121aa4..c608508cd18fcd612a119a5ac8e334dfe9bb066c 100644
--- a/src/s_loader.c
+++ b/src/s_loader.c
@@ -247,7 +247,7 @@ int sys_run_scheduler(const char *externalschedlibname,
     typedef int (*t_externalschedlibmain)(const char *);
     t_externalschedlibmain externalmainfunc;
     char filename[MAXPDSTRING];
-    snprintf(filename, sizeof(filename), "%s.%s", externalschedlibname,
+    snprintf(filename, sizeof(filename), "%s%s", externalschedlibname,
         sys_dllextent);
     sys_bashfilename(filename, filename);
 #ifdef MSW
diff --git a/src/s_main.c b/src/s_main.c
index 877ed41f626953dc8e90b26c7240acdb3243b67d..dc4c3f6e9408269de00b11ac63009ee3a32563e8 100644
--- a/src/s_main.c
+++ b/src/s_main.c
@@ -282,7 +282,8 @@ int sys_main(int argc, char **argv)
     if (!noprefs)
         sys_loadpreferences();                  /* load default settings */
 #ifndef MSW
-    sys_rcfile();                               /* parse the startup file */
+    if (!noprefs)
+        sys_rcfile();                           /* parse the startup file */
 #endif
     if (sys_argparse(argc-1, argv+1))           /* parse cmd line */
         return (1);
@@ -391,6 +392,8 @@ static char *(usagemessage[]) = {
 "-nrt             -- don't use real-time priority\n",
 #endif
 "-nosleep         -- spin, don't sleep (may lower latency on multi-CPUs)\n",
+"-schedlib <file> -- plug in external scheduler\n",
+"-extraflags <s>  -- string argument to send schedlib\n",
 };
 
 static void sys_parsedevlist(int *np, int *vecp, int max, char *str)
@@ -809,7 +812,7 @@ int sys_argparse(int argc, char **argv)
             sys_listplease = 1;
             argc--; argv++;
         }
-        else if (!strcmp(*argv, "-schedlib"))
+        else if (!strcmp(*argv, "-schedlib") && argc > 1)
         {
             sys_externalschedlib = 1;
             strncpy(sys_externalschedlibname, argv[1],
@@ -817,7 +820,7 @@ int sys_argparse(int argc, char **argv)
             argv += 2;
             argc -= 2;
         }
-        else if (!strcmp(*argv, "-extraflags"))
+        else if (!strcmp(*argv, "-extraflags") && argc > 1)
         {
             sys_extraflags = 1;
             strncpy(sys_extraflagsstring, argv[1],
diff --git a/src/s_midi_oss.c b/src/s_midi_oss.c
index 354dc0d58457705c5d4a77365da03a8e7902cc0e..e1f7c8c63378013e44af685df71761597e6435d6 100644
--- a/src/s_midi_oss.c
+++ b/src/s_midi_oss.c
@@ -81,7 +81,7 @@ void sys_do_open_midi(int nmidiin, int *midiinvec,
             if (outdevindex >= 0 && fd >= 0)
                 oss_midioutfd[outdevindex] = fd;
         }
-        if (devno == 1 && fd < 0)
+        if (devno == 0 && fd < 0)
         {
             sys_setalarm(1000000);
             fd = open("/dev/midi", O_RDONLY | O_MIDIFLAG);
@@ -116,7 +116,7 @@ void sys_do_open_midi(int nmidiin, int *midiinvec,
         int fd = oss_midioutfd[i];
         char namebuf[80];
         int devno = midioutvec[i];
-        if (devno == 1 && fd < 0)
+        if (devno == 0 && fd < 0)
         {
             sys_setalarm(1000000);
             fd = open("/dev/midi", O_WRONLY | O_MIDIFLAG);
diff --git a/src/s_path.c b/src/s_path.c
index f59f09c77cb1da0146d2ca1719d9318af28cb542..ef4411844a21d019ab8cde647b447147d256c9c2 100644
--- a/src/s_path.c
+++ b/src/s_path.c
@@ -69,6 +69,24 @@ void sys_unbashfilename(const char *from, char *to)
     *to = 0;
 }
 
+/* test if path is absolute or relative, based on leading /, env vars, ~, etc */
+int sys_isabsolutepath(const char *dir)
+{
+    if (dir[0] == '/' || dir[0] == '~'
+#ifdef MSW
+        || dir[0] == '%' || (dir[1] == ':' && dir[2] == '/')
+#endif
+        )
+    {
+        return 1;
+    }
+    else
+    {
+        return 0;            
+    }
+}
+
+
 /*******************  Utility functions used below ******************/
 
 /*!
@@ -250,11 +268,7 @@ int sys_trytoopenone(const char *dir, const char *name, const char* ext,
 int sys_open_absolute(const char *name, const char* ext,
     char *dirresult, char **nameresult, unsigned int size, int bin, int *fdp)
 {
-    if (name[0] == '/' 
-#ifdef MSW
-        || (name[1] == ':' && name[2] == '/')
-#endif
-            )
+    if (sys_isabsolutepath(name))
     {
         char dirbuf[MAXPDSTRING];
         int dirlen = (strrchr(name, '/') - name);
diff --git a/src/s_stuff.h b/src/s_stuff.h
index a1f9026c4d336967b6a24ed20c2ad7ad57dd4ec8..e53d3edc9b918eac29342ee45b450a61e3b0ef95 100644
--- a/src/s_stuff.h
+++ b/src/s_stuff.h
@@ -325,3 +325,4 @@ EXTERN void inmidi_polyaftertouch(int portno,
                                   int pitch,
                                   int value);
 /* } jsarlo */
+extern t_widgetbehavior text_widgetbehavior;
diff --git a/src/x_arithmetic.c b/src/x_arithmetic.c
index f64c8cbd46bf9266b06798d1bfd23196cc1e65c0..0dd199372b260166e2b266b8d6cc81ed70c31ce4 100644
--- a/src/x_arithmetic.c
+++ b/src/x_arithmetic.c
@@ -623,7 +623,6 @@ static void log_float(t_object *x, t_float f)
     outlet_float(x->ob_outlet, r);
 }
 
-
 static t_class *exp_class;      /* ----------- exp --------------- */
 
 static void *exp_new(void)
@@ -659,6 +658,20 @@ static void abs_float(t_object *x, t_float f)
     outlet_float(x->ob_outlet, fabsf(f));
 }
 
+static t_class *wrap_class;      /* ----------- wrap --------------- */
+
+static void *wrap_new(void)
+{
+    t_object *x = (t_object *)pd_new(wrap_class);
+    outlet_new(x, &s_float);
+    return (x);
+}
+
+static void wrap_float(t_object *x, t_float f)
+{
+    outlet_float(x->ob_outlet, f - floor(f));
+}
+
 /* ------------------------  misc ------------------------ */
 
 static t_class *clip_class;
@@ -898,6 +911,11 @@ void x_arithmetic_setup(void)
     class_addfloat(abs_class, (t_method)abs_float);    
     class_sethelpsymbol(abs_class, math_sym);
 
+    wrap_class = class_new(gensym("wrap"), wrap_new, 0,
+        sizeof(t_object), 0, 0);
+    class_addfloat(wrap_class, (t_method)wrap_float);    
+    class_sethelpsymbol(wrap_class, math_sym);
+
 /* ------------------------  misc ------------------------ */
 
     clip_setup();
diff --git a/src/x_time.c b/src/x_time.c
index 60dcf9a50ffe801adeaeea235112a7af96a2e134..5dc9d37ffeda5b2b867b379b6b73aba4206b2c08 100644
--- a/src/x_time.c
+++ b/src/x_time.c
@@ -334,7 +334,7 @@ static void *pipe_new(t_symbol *s, int argc, t_atom *argv)
         {
             char stupid[80];
             atom_string(&argv[argc-1], stupid, 79);
-            post("pipe: %s: bad time delay value", stupid);
+            pd_error(x, "pipe: %s: bad time delay value", stupid);
             deltime = 0;
         }
         else deltime = argv[argc-1].a_w.w_float;
@@ -385,7 +385,7 @@ static void *pipe_new(t_symbol *s, int argc, t_atom *argv)
             }
             else
             {
-                if (c != 'f') error("pack: %s: bad type",
+                if (c != 'f') pd_error(x, "pipe: %s: bad type",
                     ap->a_w.w_symbol->s_name);
                 SETFLOAT(&vp->p_atom, 0);
                 vp->p_outlet = outlet_new(&x->x_obj, &s_float);
@@ -437,7 +437,7 @@ static void hang_tick(t_hang *h)
         case A_POINTER:
             if (gpointer_check(w->w_gpointer, 1))
                 outlet_pointer(p->p_outlet, w->w_gpointer);
-            else post("pipe: stale pointer");
+            else pd_error(x, "pipe: stale pointer");
             break;
         }
     }
@@ -454,7 +454,13 @@ static void pipe_list(t_pipe *x, t_symbol *s, int ac, t_atom *av)
     t_atom *ap;
     t_word *w;
     h->h_gp = (t_gpointer *)getbytes(x->x_nptr * sizeof(t_gpointer));
-    if (ac > n) ac = n;
+    if (ac > n)
+    {
+        if (av[n].a_type == A_FLOAT)
+            x->x_deltime = av[n].a_w.w_float;
+        else pd_error(x, "pipe: symbol or pointer in time inlet");
+        ac = n;
+    }
     for (i = 0, gp = x->x_gp, p = x->x_vec, ap = av; i < ac;
         i++, p++, ap++)
     {
@@ -465,7 +471,7 @@ static void pipe_list(t_pipe *x, t_symbol *s, int ac, t_atom *av)
         case A_POINTER:
             gpointer_unset(gp);
             if (ap->a_type != A_POINTER)
-                post("pipe: bad pointer");
+                pd_error(x, "pipe: bad pointer");
             else
             {
                 *gp = *(ap->a_w.w_gpointer);