aboutsummaryrefslogtreecommitdiff
path: root/pdstring+wchar
diff options
context:
space:
mode:
authorBryan Jurish <mukau@users.sourceforge.net>2009-01-25 22:16:17 +0000
committerBryan Jurish <mukau@users.sourceforge.net>2009-01-25 22:16:17 +0000
commit9f6510850e3782a22b0ac282161f5e1e7413f3f2 (patch)
treede3c296e65faf6f4355f0fb345f4eed1b069d2bc /pdstring+wchar
parent2fca84eeb6f1079b1f8a0723f5d2b176aa1b62e3 (diff)
+ got 'wchars' objects working
svn path=/trunk/externals/moocow/; revision=10638
Diffstat (limited to 'pdstring+wchar')
-rwxr-xr-xpdstring+wchar/configure2
-rw-r--r--pdstring+wchar/configure.ac2
-rw-r--r--pdstring+wchar/src/Makefile.am30
-rw-r--r--pdstring+wchar/src/Makefile.in45
-rw-r--r--pdstring+wchar/src/any2bytes-help.pd4
-rw-r--r--pdstring+wchar/src/any2bytes.c108
-rw-r--r--pdstring+wchar/src/any2wchars-help.pd37
-rw-r--r--pdstring+wchar/src/any2wchars.pd10
-rw-r--r--pdstring+wchar/src/bytes2any.c9
-rw-r--r--pdstring+wchar/src/bytes2wchars-help.pd46
-rw-r--r--pdstring+wchar/src/bytes2wchars-test.pd16
-rw-r--r--pdstring+wchar/src/bytes2wchars.c8
-rw-r--r--pdstring+wchar/src/pdstring-help.pd82
-rw-r--r--pdstring+wchar/src/pdstring.c2
-rw-r--r--pdstring+wchar/src/pdstringUtils.c239
-rw-r--r--pdstring+wchar/src/pdstringUtils.h452
-rw-r--r--pdstring+wchar/src/wchars2any-help.pd42
-rw-r--r--pdstring+wchar/src/wchars2any.pd12
-rw-r--r--pdstring+wchar/src/wchars2bytes-help.pd44
-rw-r--r--pdstring+wchar/src/wchars2bytes-test.pd46
-rw-r--r--pdstring+wchar/src/wchars2bytes.c157
21 files changed, 1209 insertions, 184 deletions
diff --git a/pdstring+wchar/configure b/pdstring+wchar/configure
index d4be0f4..9787a42 100755
--- a/pdstring+wchar/configure
+++ b/pdstring+wchar/configure
@@ -3543,7 +3543,7 @@ esac
##------- PD externals: hack EXEEXT?
PD_LIB_EXTERNALS="pdstring"
-PD_OBJ_EXTERNALS="any2bytes bytes2any bytes2wchars"
+PD_OBJ_EXTERNALS="any2bytes bytes2any bytes2wchars wchars2bytes"
# Check whether --enable-object-externals was given.
if test "${enable_object_externals+set}" = set; then
diff --git a/pdstring+wchar/configure.ac b/pdstring+wchar/configure.ac
index cca35f6..aa2af8d 100644
--- a/pdstring+wchar/configure.ac
+++ b/pdstring+wchar/configure.ac
@@ -88,7 +88,7 @@ esac
##------- PD externals: hack EXEEXT?
PD_LIB_EXTERNALS="pdstring"
-PD_OBJ_EXTERNALS="any2bytes bytes2any bytes2wchars"
+PD_OBJ_EXTERNALS="any2bytes bytes2any bytes2wchars wchars2bytes"
AC_ARG_ENABLE(object-externals,
AC_HELP_STRING([--enable-object-externals], [Whether to build single-object externals (default=no)]),
diff --git a/pdstring+wchar/src/Makefile.am b/pdstring+wchar/src/Makefile.am
index 69e2efb..7f8df55 100644
--- a/pdstring+wchar/src/Makefile.am
+++ b/pdstring+wchar/src/Makefile.am
@@ -33,27 +33,41 @@ pdexterns_PROGRAMS = @PD_OBJECT_EXTERNALS@
EXTRA_PROGRAMS = \
pdstring \
any2bytes \
- bytes2any
+ bytes2any \
+ bytes2wchars \
+ wchars2bytes
## --- patches
-pdexterns_DATA =
+pdexterns_DATA = \
+ any2wchars.pd \
+ wchars2any.pd
## --- documentation
pddoc_DATA = \
pdstring-help.pd \
any2bytes-help.pd \
- bytes2any-help.pd
+ bytes2any-help.pd \
+ bytes2wchars-help.pd \
+ wchars2bytes-help.pd \
+ any2wchars-help.pd \
+ wchars2any-help.pd
#-----------------------------------------------------------------------
# sources
#-----------------------------------------------------------------------
-pdstring_SOURCES = pdstring.c mooPdUtils.h
+any2bytes_SOURCES = any2bytes.c mooPdUtils.h pdstringUtils.h
-any2bytes_SOURCES = any2bytes.c mooPdUtils.h
+bytes2any_SOURCES = bytes2any.c mooPdUtils.h pdstringUtils.h
-bytes2any_SOURCES = bytes2any.c mooPdUtils.h
+bytes2wchars_SOURCES = bytes2wchars.c mooPdUtils.h pdstringUtils.h
+
+wchars2bytes_SOURCES = wchars2bytes.c mooPdUtils.h pdstringUtils.h
+
+pdstring_SOURCES = pdstring.c mooPdUtils.h pdstringUtils.h
+
+pdstring.$(OBJECT): $(any2bytes_SOURCES) $(bytes2any_SOURCES) $(bytes2wchars_SOURCES) $(wchars2bytes_SOURCES)
#-----------------------------------------------------------------------
# external compilation : flags
@@ -78,6 +92,10 @@ bytes2any_LDFLAGS = $(LFLAGS)
any2bytes_LDFLAGS = $(LFLAGS)
+bytes2wchars_LDFLAGS = $(LFLAGS)
+
+wchars2bytes_LDFLAGS = $(LFLAGS)
+
#-----------------------------------------------------------------------
# Variables: cleanup
#-----------------------------------------------------------------------
diff --git a/pdstring+wchar/src/Makefile.in b/pdstring+wchar/src/Makefile.in
index 5f5b1ae..265ee20 100644
--- a/pdstring+wchar/src/Makefile.in
+++ b/pdstring+wchar/src/Makefile.in
@@ -51,7 +51,7 @@ PRE_UNINSTALL = :
POST_UNINSTALL = :
pdexterns_PROGRAMS = @PD_OBJECT_EXTERNALS@
EXTRA_PROGRAMS = pdstring$(EXEEXT) any2bytes$(EXEEXT) \
- bytes2any$(EXEEXT)
+ bytes2any$(EXEEXT) bytes2wchars$(EXEEXT) wchars2bytes$(EXEEXT)
subdir = src
SUBDIRS =
DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in \
@@ -73,9 +73,15 @@ any2bytes_LDADD = $(LDADD)
am_bytes2any_OBJECTS = bytes2any.$(OBJEXT)
bytes2any_OBJECTS = $(am_bytes2any_OBJECTS)
bytes2any_LDADD = $(LDADD)
+am_bytes2wchars_OBJECTS = bytes2wchars.$(OBJEXT)
+bytes2wchars_OBJECTS = $(am_bytes2wchars_OBJECTS)
+bytes2wchars_LDADD = $(LDADD)
am_pdstring_OBJECTS = pdstring.$(OBJEXT)
pdstring_OBJECTS = $(am_pdstring_OBJECTS)
pdstring_LDADD = $(LDADD)
+am_wchars2bytes_OBJECTS = wchars2bytes.$(OBJEXT)
+wchars2bytes_OBJECTS = $(am_wchars2bytes_OBJECTS)
+wchars2bytes_LDADD = $(LDADD)
DEFAULT_INCLUDES = -I. -I$(srcdir) -I.
depcomp = $(SHELL) $(top_srcdir)/config/depcomp
am__depfiles_maybe = depfiles
@@ -84,9 +90,11 @@ COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
CCLD = $(CC)
LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
SOURCES = $(any2bytes_SOURCES) $(bytes2any_SOURCES) \
- $(pdstring_SOURCES)
+ $(bytes2wchars_SOURCES) $(pdstring_SOURCES) \
+ $(wchars2bytes_SOURCES)
DIST_SOURCES = $(any2bytes_SOURCES) $(bytes2any_SOURCES) \
- $(pdstring_SOURCES)
+ $(bytes2wchars_SOURCES) $(pdstring_SOURCES) \
+ $(wchars2bytes_SOURCES)
RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
html-recursive info-recursive install-data-recursive \
install-exec-recursive install-info-recursive \
@@ -204,19 +212,28 @@ sharedstatedir = @sharedstatedir@
sysconfdir = @sysconfdir@
target_alias = @target_alias@
SUFFIXES = .@PDEXT@
-pdexterns_DATA =
+pdexterns_DATA = \
+ any2wchars.pd \
+ wchars2any.pd
+
pddoc_DATA = \
pdstring-help.pd \
any2bytes-help.pd \
- bytes2any-help.pd
+ bytes2any-help.pd \
+ bytes2wchars-help.pd \
+ wchars2bytes-help.pd \
+ any2wchars-help.pd \
+ wchars2any-help.pd
#-----------------------------------------------------------------------
# sources
#-----------------------------------------------------------------------
-pdstring_SOURCES = pdstring.c mooPdUtils.h
-any2bytes_SOURCES = any2bytes.c mooPdUtils.h
-bytes2any_SOURCES = bytes2any.c mooPdUtils.h
+any2bytes_SOURCES = any2bytes.c mooPdUtils.h pdstringUtils.h
+bytes2any_SOURCES = bytes2any.c mooPdUtils.h pdstringUtils.h
+bytes2wchars_SOURCES = bytes2wchars.c mooPdUtils.h pdstringUtils.h
+wchars2bytes_SOURCES = wchars2bytes.c mooPdUtils.h pdstringUtils.h
+pdstring_SOURCES = pdstring.c mooPdUtils.h pdstringUtils.h
#GLIB_IFLAGS = @GLIB_IFLAGS@
#GLIB_LFLAGS = @GLIB_LFLAGS@
@@ -225,6 +242,8 @@ AM_CFLAGS = $(OFLAGS) $(WFLAGS) $(AFLAGS)
pdstring_LDFLAGS = $(LFLAGS)
bytes2any_LDFLAGS = $(LFLAGS)
any2bytes_LDFLAGS = $(LFLAGS)
+bytes2wchars_LDFLAGS = $(LFLAGS)
+wchars2bytes_LDFLAGS = $(LFLAGS)
#-----------------------------------------------------------------------
# Variables: cleanup
@@ -338,9 +357,15 @@ any2bytes$(EXEEXT): $(any2bytes_OBJECTS) $(any2bytes_DEPENDENCIES)
bytes2any$(EXEEXT): $(bytes2any_OBJECTS) $(bytes2any_DEPENDENCIES)
@rm -f bytes2any$(EXEEXT)
$(LINK) $(bytes2any_LDFLAGS) $(bytes2any_OBJECTS) $(bytes2any_LDADD) $(LIBS)
+bytes2wchars$(EXEEXT): $(bytes2wchars_OBJECTS) $(bytes2wchars_DEPENDENCIES)
+ @rm -f bytes2wchars$(EXEEXT)
+ $(LINK) $(bytes2wchars_LDFLAGS) $(bytes2wchars_OBJECTS) $(bytes2wchars_LDADD) $(LIBS)
pdstring$(EXEEXT): $(pdstring_OBJECTS) $(pdstring_DEPENDENCIES)
@rm -f pdstring$(EXEEXT)
$(LINK) $(pdstring_LDFLAGS) $(pdstring_OBJECTS) $(pdstring_LDADD) $(LIBS)
+wchars2bytes$(EXEEXT): $(wchars2bytes_OBJECTS) $(wchars2bytes_DEPENDENCIES)
+ @rm -f wchars2bytes$(EXEEXT)
+ $(LINK) $(wchars2bytes_LDFLAGS) $(wchars2bytes_OBJECTS) $(wchars2bytes_LDADD) $(LIBS)
mostlyclean-compile:
-rm -f *.$(OBJEXT)
@@ -350,7 +375,9 @@ distclean-compile:
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/any2bytes.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bytes2any.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/bytes2wchars.Po@am__quote@
@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/pdstring.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/wchars2bytes.Po@am__quote@
.c.o:
@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
@@ -682,6 +709,8 @@ uninstall-info: uninstall-info-recursive
uninstall-pdexternsPROGRAMS
+pdstring.$(OBJECT): $(any2bytes_SOURCES) $(bytes2any_SOURCES) $(bytes2wchars_SOURCES) $(wchars2bytes_SOURCES)
+
maintainer-clean-local:
rm -rf autom4te.cache
diff --git a/pdstring+wchar/src/any2bytes-help.pd b/pdstring+wchar/src/any2bytes-help.pd
index 215a27f..ef0ce17 100644
--- a/pdstring+wchar/src/any2bytes-help.pd
+++ b/pdstring+wchar/src/any2bytes-help.pd
@@ -10,10 +10,10 @@
#X text 188 103 anything can be converted to a list...;
#X text 190 147 ... but "float" selector is silently dropped;
#X msg 25 104 A B C;
-#X text 193 312 First argument: initial buffer size (length of object-local
+#X text 182 312 First argument: initial buffer size (length of object-local
text buffer). This should get re-allocated when necessary. Specify
0 (zero) to use the default value.;
-#X text 195 367 Second argument: initial EOS character. See above.
+#X text 184 367 Second argument: initial EOS character. See above.
;
#X text 320 458 Bryan Jurish <moocow@ling.uni-potsdam.de>;
#X text 19 439 SEE ALSO:;
diff --git a/pdstring+wchar/src/any2bytes.c b/pdstring+wchar/src/any2bytes.c
index 4500ee3..c2b2425 100644
--- a/pdstring+wchar/src/any2bytes.c
+++ b/pdstring+wchar/src/any2bytes.c
@@ -32,7 +32,7 @@
#endif
#include "mooPdUtils.h"
-#include "pdstringUtils.c"
+#include "pdstringUtils.h"
/* black magic */
#ifdef NT
@@ -62,14 +62,12 @@ static t_class *any2bytes_class;
typedef struct _any2bytes
{
t_object x_obj;
- int x_alloc;
- int x_argc;
- t_float x_eos; //-- EOS character to add (<0 for none)
- char *x_text;
- t_atom *x_argv;
- t_binbuf *x_binbuf;
- t_inlet *x_eos_in;
- t_outlet *x_outlet;
+ t_pdstring_bytes x_bytes; //-- byte buffer
+ t_pdstring_atoms x_atoms; //-- atom buffer (for output)
+ t_float x_eos; //-- EOS character to add (<0 for none)
+ t_binbuf *x_binbuf;
+ t_inlet *x_eos_in;
+ t_outlet *x_outlet;
} t_any2bytes;
@@ -87,82 +85,31 @@ static char *any2bytes_banner = "any2bytes: pdstring version " PACKAGE_VERSION "
*/
static void any2bytes_anything(t_any2bytes *x, t_symbol *sel, int argc, t_atom *argv)
{
- t_atom *ap;
- unsigned char *s, *s_max;
- int len;
-
- A2SDEBUG(post("-------any2bytes_anything(%p,...)---------", x));
-
- /*-- set up binbuf --*/
- A2SDEBUG(post("any2bytes[%p]: binbuf_clear()", x));
- binbuf_clear(x->x_binbuf);
-
- /*-- binbuf_add(): selector --*/
- if (sel != &s_float && sel != &s_list && sel != &s_) {
- t_atom a;
- A2SDEBUG(post("any2bytes[%p]: binbuf_add(): selector: '%s'", x, sel->s_name));
- SETSYMBOL((&a), sel);
- binbuf_add(x->x_binbuf, 1, &a);
- }
- A2SDEBUG(else { post("any2bytes[%p]: selector: '%s': IGNORED", x, sel->s_name); });
-
- /*-- binbuf_add(): arg list --*/
- A2SDEBUG(post("any2bytes[%p]: binbuf_add(): arg list", x));
- binbuf_add(x->x_binbuf, argc, argv);
- A2SDEBUG(post("any2bytes[%p]: binbuf_print: ", x));
- A2SDEBUG(binbuf_print(x->x_binbuf));
-
- A2SDEBUG(post("any2bytes[%p]: binbuf_gettext()", x));
- binbuf_gettext(x->x_binbuf, &(x->x_text), &len);
- A2SDEBUG(post("any2bytes[%p]: binbuf_gettext() = \"%s\" ; len=%d", x, x->x_text, len));
- /*text[len] = 0;*/ /*-- ? avoid errors: "free(): invalid next size(fast): 0x..." */
-
- /*-- get output atom-list length --*/
- x->x_argc = len;
- if (x->x_eos >= 0) { x->x_argc++; }
- A2SDEBUG(post("any2bytes[%p]: argc=%d", x, x->x_argc));
-
- /*-- (re-)allocate (maybe) --*/
- if (x->x_alloc < x->x_argc) {
- A2SDEBUG(post("any2bytes[%p]: reallocate(%d->%d)", x, x->x_alloc, x->x_argc));
- freebytes(x->x_argv, x->x_alloc*sizeof(t_atom));
- x->x_argv = (t_atom*)getbytes(x->x_argc * sizeof(t_atom));
- x->x_alloc = x->x_argc;
- }
-
- /*-- atom buffer: binbuf text --*/
- A2SDEBUG(post("any2bytes[%p]: atom buffer: for {...}", x));
- ap = x->x_argv;
- s_max = ((unsigned char *)x->x_text)+len;
- for (s=((unsigned char *)x->x_text); s < s_max; s++, ap++) {
- A2SDEBUG(post("any2bytes[%p]: atom buffer[%d]: SETFLOAT(a,%d='%c')", x, (ap-x->x_argv), *s, *s));
- SETFLOAT(ap,*s);
- }
- A2SDEBUG(post("any2bytes: atom buffer: DONE"));
-
- /*-- add EOS character (maybe) --*/
- if (x->x_eos >= 0) { SETFLOAT(ap, ((int)x->x_eos)); }
-
- A2SDEBUG(post("any2bytes: outlet_list(..., %d, ...)", x->x_argc));
- outlet_list(x->x_outlet, &s_list, x->x_argc, x->x_argv);
+ //-- convert any -> bytes -> atoms
+ t_pdstring_atoms arg_atoms = {argv,argc,0};
+ pdstring_bytes_clear(&x->x_bytes);
+ pdstring_any2bytes(x, &x->x_bytes, sel, &arg_atoms, x->x_binbuf);
+ pdstring_bytes2atoms(x, &x->x_atoms, &x->x_bytes, x->x_eos);
+
+ //-- output
+ outlet_list(x->x_outlet, &s_list, x->x_atoms.a_len, x->x_atoms.a_buf);
}
-
/*--------------------------------------------------------------------
* new
*/
static void *any2bytes_new(MOO_UNUSED t_symbol *sel, int argc, t_atom *argv)
{
t_any2bytes *x = (t_any2bytes *)pd_new(any2bytes_class);
+ int bufsize = ANY2BYTES_DEFAULT_BUFLEN;
//-- defaults
- x->x_eos = 0;
- x->x_alloc = ANY2BYTES_DEFAULT_BUFLEN;
+ x->x_eos = 0;
//-- args: 0: bufsize
if (argc > 0) {
- int bufsize = atom_getintarg(0, argc, argv);
- if (bufsize > 0) { x->x_alloc = bufsize; }
+ int initial_bufsize = atom_getintarg(0, argc, argv);
+ if (initial_bufsize > 0) { bufsize = initial_bufsize; }
}
//-- args: 1: eos
if (argc > 1) {
@@ -170,9 +117,8 @@ static void *any2bytes_new(MOO_UNUSED t_symbol *sel, int argc, t_atom *argv)
}
//-- allocate
- x->x_text = getbytes(x->x_alloc*sizeof(char));
- x->x_argc = 0;
- x->x_argv = (t_atom *)getbytes(x->x_alloc*sizeof(t_atom));
+ pdstring_bytes_init(&x->x_bytes, 0); //-- x_bytes gets clobbered by binbuf_gettext()
+ pdstring_atoms_init(&x->x_atoms, bufsize);
x->x_binbuf = binbuf_new();
//-- inlets
@@ -182,7 +128,7 @@ static void *any2bytes_new(MOO_UNUSED t_symbol *sel, int argc, t_atom *argv)
x->x_outlet = outlet_new(&x->x_obj, &s_list);
//-- report
- A2SDEBUG(post("any2bytes_new(): x=%p, alloc=%d, eos=%d, text=%p, argv=%p, binbuf=%p", x, x->x_alloc, x->x_eos, x->x_text, x->x_argv, x->x_binbuf));
+ A2SDEBUG(post("any2bytes_new(): x=%p, eos=%d, binbuf=%p", x, x->x_eos, x->x_binbuf));
return (void *)x;
}
@@ -192,14 +138,8 @@ static void *any2bytes_new(MOO_UNUSED t_symbol *sel, int argc, t_atom *argv)
*/
static void any2bytes_free(t_any2bytes *x)
{
- if (x->x_text) {
- freebytes(x->x_text, x->x_alloc*sizeof(char));
- x->x_text = NULL;
- }
- if (x->x_argv) {
- freebytes(x->x_argv, x->x_alloc*sizeof(t_atom));
- x->x_argv = NULL;
- }
+ pdstring_bytes_clear(&x->x_bytes);
+ pdstring_atoms_clear(&x->x_atoms);
binbuf_free(x->x_binbuf);
inlet_free(x->x_eos_in);
outlet_free(x->x_outlet);
diff --git a/pdstring+wchar/src/any2wchars-help.pd b/pdstring+wchar/src/any2wchars-help.pd
new file mode 100644
index 0000000..3ed9e63
--- /dev/null
+++ b/pdstring+wchar/src/any2wchars-help.pd
@@ -0,0 +1,37 @@
+#N canvas 72 8 636 478 10;
+#X msg 109 197 0;
+#X msg 77 197 -1;
+#X text 19 47 INLETS:;
+#X text 31 61 1 - pd messages;
+#X text 247 49 OUTLETS:;
+#X floatatom 44 147 8 0 0 0 - - -;
+#X symbolatom 34 125 10 0 0 0 - - -;
+#X text 189 125 ... no special handling for symbols;
+#X text 188 103 anything can be converted to a list...;
+#X text 190 147 ... but "float" selector is silently dropped;
+#X msg 25 104 A B C;
+#X text 182 312 First argument: initial buffer size (length of object-local
+text buffer). This should get re-allocated when necessary. Specify
+0 (zero) to use the default value.;
+#X text 320 458 Bryan Jurish <moocow@ling.uni-potsdam.de>;
+#X text 19 439 SEE ALSO:;
+#X msg 139 197 42;
+#X text 31 75 2 - EOS character (float);
+#X obj 100 438 pdstring;
+#X obj 25 314 any2wchars 128 -1;
+#X obj 25 400 print any2wchars-help;
+#X text 21 29 SYNTAX: any2wchars [INITIAL_BUFSIZE [EOS_CHAR]];
+#X text 49 5 any2wchars : convert pd messages to a list of wchar_t
+values;
+#X text 263 63 1 - lists of wchar_t-valued floats;
+#X text 184 194 The second inlet is as for [any2bytes];
+#X text 184 367 Second argument: initial EOS character. See [any2bytes].
+;
+#X obj 168 438 locale;
+#X connect 0 0 17 1;
+#X connect 1 0 17 1;
+#X connect 5 0 17 0;
+#X connect 6 0 17 0;
+#X connect 10 0 17 0;
+#X connect 14 0 17 1;
+#X connect 17 0 18 0;
diff --git a/pdstring+wchar/src/any2wchars.pd b/pdstring+wchar/src/any2wchars.pd
new file mode 100644
index 0000000..a531952
--- /dev/null
+++ b/pdstring+wchar/src/any2wchars.pd
@@ -0,0 +1,10 @@
+#N canvas 398 18 328 196 10;
+#X obj 54 20 inlet;
+#X obj 154 20 inlet;
+#X obj 54 62 any2bytes \$1 \$2;
+#X obj 54 134 outlet;
+#X obj 54 90 bytes2wchars \$1;
+#X connect 0 0 2 0;
+#X connect 1 0 2 1;
+#X connect 2 0 4 0;
+#X connect 4 0 3 0;
diff --git a/pdstring+wchar/src/bytes2any.c b/pdstring+wchar/src/bytes2any.c
index 81f28bd..e4b3715 100644
--- a/pdstring+wchar/src/bytes2any.c
+++ b/pdstring+wchar/src/bytes2any.c
@@ -32,7 +32,7 @@
#endif
#include "mooPdUtils.h"
-#include "pdstringUtils.c"
+#include "pdstringUtils.h"
/* black magic */
#ifdef NT
@@ -87,8 +87,8 @@ typedef struct _bytes2any
static void bytes2any_atoms(t_bytes2any *x, int argc, t_atom *argv)
{
t_pdstring_atoms src = {argv,argc,argc};
- pdstring_atoms2bytes(&(x->x_bytes), &src, x->x_eos);
- pdstring_bytes2any(NULL, &(x->x_bytes), x->x_binbuf);
+ pdstring_atoms2bytes(x, &(x->x_bytes), &src, x->x_eos);
+ pdstring_bytes2any(x, NULL, &(x->x_bytes), x->x_binbuf);
int x_argc;
t_atom *x_argv;
@@ -183,8 +183,7 @@ static void *bytes2any_new(MOO_UNUSED t_symbol *sel, int argc, t_atom *argv)
*/
static void bytes2any_free(t_bytes2any *x)
{
- if (x->x_bytes.b_buf)
- freebytes(x->x_bytes.b_buf, x->x_bytes.b_alloc*sizeof(unsigned char));
+ pdstring_bytes_clear(&x->x_bytes);
binbuf_free(x->x_binbuf);
inlet_free(x->x_eos_in);
outlet_free(x->x_outlet_done);
diff --git a/pdstring+wchar/src/bytes2wchars-help.pd b/pdstring+wchar/src/bytes2wchars-help.pd
new file mode 100644
index 0000000..3d3d0b6
--- /dev/null
+++ b/pdstring+wchar/src/bytes2wchars-help.pd
@@ -0,0 +1,46 @@
+#N canvas 610 14 566 410 10;
+#X text 81 5 bytes2wchars : convert bytes to wide characters;
+#X text 11 27 SYNTAX: bytes2wchars [INITIAL_BUFSIZE];
+#X text 11 46 INLETS:;
+#X text 241 48 OUTLETS:;
+#X text 19 62 1 - byte-valued float lists;
+#X text 257 62 1 - wchar_t-valued float lists;
+#X obj 24 310 bytes2wchars;
+#X obj 24 334 print bytes2wchars-help;
+#X msg 24 95 97 32 98 32 99;
+#X msg 41 227 228 246 252;
+#X msg 71 159 C;
+#X text 69 129 8-bit values are interpreted according to the current
+locale's LC_CTYPE category: here are some examples:;
+#N canvas 0 0 338 182 locale_LC_CTYPE 0;
+#X obj 48 124 locale;
+#X obj 48 36 inlet;
+#X obj 48 64 symbol;
+#X msg 48 92 set LC_CTYPE \$1;
+#X text 57 143 + requires the "locale" external;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 0 0;
+#X restore 103 190 pd locale_LC_CTYPE;
+#X msg 45 255 195 164 195 182 195 188;
+#X text 219 253 ... the same string encoded in UTF-8;
+#X text 205 387 Bryan Jurish <moocow@ling.uni-potsdam.de>;
+#X text 11 371 SEE ALSO:;
+#X obj 26 388 pdstring;
+#X obj 93 388 locale;
+#X text 11 355 BUGS: float representation is only safe up to 24-bit
+values;
+#X msg 103 159 en_DK.ISO-8859-1;
+#X msg 225 159 en_DK.UTF-8;
+#X text 145 97 Values <= 127 are unchanged;
+#X msg 49 281 207 128 206 180;
+#X text 217 225 ISO-8859-1 bytes "&auml \, &ouml \, &uuml";
+#X text 219 283 "&pi &delta" in UTF-8;
+#X connect 6 0 7 0;
+#X connect 8 0 6 0;
+#X connect 9 0 6 0;
+#X connect 10 0 12 0;
+#X connect 13 0 6 0;
+#X connect 20 0 12 0;
+#X connect 21 0 12 0;
+#X connect 23 0 6 0;
diff --git a/pdstring+wchar/src/bytes2wchars-test.pd b/pdstring+wchar/src/bytes2wchars-test.pd
index b5d3706..faeaea1 100644
--- a/pdstring+wchar/src/bytes2wchars-test.pd
+++ b/pdstring+wchar/src/bytes2wchars-test.pd
@@ -1,4 +1,4 @@
-#N canvas 96 10 578 300 10;
+#N canvas 600 24 578 300 10;
#X obj 114 136 bytes2wchars;
#X obj 138 168 print wchars;
#X obj 285 238 locale;
@@ -13,15 +13,16 @@
#X floatatom 116 204 5 0 0 0 - - -;
#X msg 41 61 195 182;
#X text 39 23 &ouml \;;
-#X text 95 41 latin1;
-#X text 99 59 utf8;
#X msg 159 61 197 147;
#X text 155 23 &oelig \;;
#X msg 159 39 339;
#X msg 245 37 960;
#X msg 245 59 207 128;
#X text 245 21 &pi \;;
-#X msg 337 63 207 128 197 147 195 182 0;
+#X obj 353 136 loadbang;
+#X text 97 41 ucs-4;
+#X text 99 59 utf-8;
+#X msg 337 63 207 128 0 197 147 0 195 182 0;
#X connect 0 0 1 0;
#X connect 0 0 11 0;
#X connect 2 0 9 0;
@@ -33,8 +34,9 @@
#X connect 8 0 5 0;
#X connect 10 0 0 0;
#X connect 12 0 0 0;
+#X connect 14 0 0 0;
#X connect 16 0 0 0;
+#X connect 17 0 0 0;
#X connect 18 0 0 0;
-#X connect 19 0 0 0;
-#X connect 20 0 0 0;
-#X connect 22 0 0 0;
+#X connect 20 0 7 0;
+#X connect 23 0 0 0;
diff --git a/pdstring+wchar/src/bytes2wchars.c b/pdstring+wchar/src/bytes2wchars.c
index 185a3cb..7fbbc99 100644
--- a/pdstring+wchar/src/bytes2wchars.c
+++ b/pdstring+wchar/src/bytes2wchars.c
@@ -34,7 +34,7 @@
#endif
#include "mooPdUtils.h"
-#include "pdstringUtils.c"
+#include "pdstringUtils.h"
/* black magic */
#ifdef NT
@@ -81,9 +81,9 @@ static void bytes2wchars_atoms(t_bytes2wchars *x, int argc, t_atom *argv)
t_pdstring_atoms src = {argv,argc,0};
/*-- convert atoms -> bytes -> wchars -> atoms --*/
- pdstring_atoms2bytes(&x->x_bytes, &src, PDSTRING_EOS_NONE);
- pdstring_bytes2wchars(&x->x_wchars, &x->x_bytes);
- pdstring_wchars2atoms(&x->x_atoms, &x->x_wchars); //-- TODO
+ pdstring_atoms2bytes (x, &x->x_bytes, &src, PDSTRING_EOS_NONE);
+ pdstring_bytes2wchars(x, &x->x_wchars, &x->x_bytes);
+ pdstring_wchars2atoms(x, &x->x_atoms, &x->x_wchars);
}
diff --git a/pdstring+wchar/src/pdstring-help.pd b/pdstring+wchar/src/pdstring-help.pd
index 12e6d42..9e3e0c3 100644
--- a/pdstring+wchar/src/pdstring-help.pd
+++ b/pdstring+wchar/src/pdstring-help.pd
@@ -1,11 +1,26 @@
-#N canvas 191 76 563 311 10;
-#X text 258 284 Bryan Jurish <moocow@ling.uni-potsdam.de>;
+#N canvas 163 18 501 441 10;
+#X text 196 400 Bryan Jurish <moocow@ling.uni-potsdam.de>;
+#X text 54 3 [pdstring] library : byte and wide-character strings;
+#X obj 51 76 bytes2any;
+#X obj 51 52 any2bytes;
+#X text 148 77 convert byte strings to pd messages;
+#X text 148 53 convert pd messages to byte strings;
+#X obj 45 142 bytes2wchars;
+#X text 147 143 convert byte strings to wide character strings;
+#X obj 45 168 wchars2bytes;
+#X text 148 169 convert wide character strings to byte strings;
+#X text 22 121 BYTES <-> WIDE CHARACTERS;
+#X text 26 33 BYTES <-> PD MESSAGES;
+#X text 20 211 WIDE CHARACTERS <-> PD MESSAGES;
+#X text 145 233 convert pd messages to wide character strings;
+#X text 146 259 convert wide character strings to pd messages;
+#X text 18 369 SEE ALSO:;
+#N canvas 0 0 584 308 pdstring-bytes 0;
#X floatatom 56 81 8 0 0 0 - - -;
#X symbolatom 46 59 10 0 0 0 - - -;
#X text 201 59 ... no special handling for symbols;
#X text 200 37 anything can be converted to a list...;
#X floatatom 54 178 4 0 0 0 - - -;
-#X text 213 230 string2any converts ASCII lists to Pd messages...;
#X text 202 81 ... but "float" selector is silently dropped;
#N canvas 0 0 448 335 ascii-table 0;
#X obj 162 144 f 0;
@@ -37,23 +52,52 @@
#X connect 10 0 11 0;
#X connect 10 1 11 0;
#X connect 12 0 5 0;
-#X restore 249 144 pd ascii-table;
-#X msg 249 121 bang;
-#X text 361 143 know your charset;
+#X restore 289 156 pd ascii-table;
+#X msg 289 133 bang;
#X msg 37 38 A B C;
#X msg 55 199 list 49 50 51;
-#X text 54 3 any2string \, string2any : ASCII conversions in [pdstring]
-lib;
-#X obj 37 108 any2bytes;
-#X obj 37 230 bytes2any;
#X obj 58 139 print any2bytes-out;
+#X obj 37 108 any2bytes;
#X obj 37 254 print bytes2any-out;
-#X connect 1 0 14 0;
-#X connect 2 0 14 0;
-#X connect 5 0 15 0;
-#X connect 9 0 8 0;
-#X connect 11 0 14 0;
-#X connect 12 0 15 0;
-#X connect 14 0 15 0;
-#X connect 14 0 16 0;
-#X connect 15 0 17 0;
+#X obj 37 230 bytes2any;
+#X text 289 173 ... know your character set;
+#X text 213 230 bytes2any converts byte lists to Pd messages...;
+#X connect 0 0 11 0;
+#X connect 1 0 11 0;
+#X connect 4 0 13 0;
+#X connect 7 0 6 0;
+#X connect 8 0 11 0;
+#X connect 9 0 13 0;
+#X connect 11 0 10 0;
+#X connect 11 0 13 0;
+#X connect 13 0 12 0;
+#X restore 87 368 pd pdstring-bytes;
+#N canvas 0 0 584 308 pdstring-wchars 0;
+#X floatatom 56 81 8 0 0 0 - - -;
+#X symbolatom 46 59 10 0 0 0 - - -;
+#X text 201 59 ... no special handling for symbols;
+#X text 200 37 anything can be converted to a list...;
+#X floatatom 54 178 4 0 0 0 - - -;
+#X text 202 81 ... but "float" selector is silently dropped;
+#X msg 37 38 A B C;
+#X msg 55 199 list 49 50 51;
+#X obj 37 254 print wchars2any-out;
+#X text 213 230 wchars2any converts wchar lists to Pd messages...;
+#X obj 58 139 print any2wchars-out;
+#X obj 37 108 any2wchars;
+#X obj 37 230 wchars2any;
+#X connect 0 0 11 0;
+#X connect 1 0 11 0;
+#X connect 4 0 12 0;
+#X connect 6 0 11 0;
+#X connect 7 0 12 0;
+#X connect 11 0 10 0;
+#X connect 11 0 12 0;
+#X connect 12 0 8 0;
+#X restore 217 368 pd pdstring-wchars;
+#X obj 43 232 any2wchars;
+#X obj 43 258 wchars2any;
+#X obj 355 368 locale;
+#X text 18 303 NOTE:;
+#X text 26 319 Wide character support requires locale support to be
+enabled \, e.g. by the [locale] external.;
diff --git a/pdstring+wchar/src/pdstring.c b/pdstring+wchar/src/pdstring.c
index bea27b1..907d16d 100644
--- a/pdstring+wchar/src/pdstring.c
+++ b/pdstring+wchar/src/pdstring.c
@@ -58,6 +58,7 @@ typedef struct _pdstring
# include "any2bytes.c"
# include "bytes2any.c"
# include "bytes2wchars.c"
+# include "wchars2bytes.c"
#endif
/*--------------------------------------------------------------------
@@ -90,6 +91,7 @@ void pdstring_setup(void)
any2bytes_setup_guts();
bytes2any_setup_guts();
bytes2wchars_setup_guts();
+ wchars2bytes_setup_guts();
#endif
pdstring_class = class_new(gensym("pdstring"),
diff --git a/pdstring+wchar/src/pdstringUtils.c b/pdstring+wchar/src/pdstringUtils.c
index b07f760..2596422 100644
--- a/pdstring+wchar/src/pdstringUtils.c
+++ b/pdstring+wchar/src/pdstringUtils.c
@@ -105,7 +105,9 @@ typedef struct _pdstring_atoms {
* Initialization
*=====================================================================*/
-//-- bytes
+/*---------------------------------------------------------------------
+ * bytes
+ */
static void pdstring_bytes_clear(t_pdstring_bytes *b)
{
if (b->b_alloc) freebytes(b->b_buf, (b->b_alloc)*sizeof(unsigned char));
@@ -125,7 +127,9 @@ static void pdstring_bytes_init(t_pdstring_bytes *b, size_t n)
pdstring_bytes_realloc(b,n);
}
-//-- wchars
+/*---------------------------------------------------------------------
+ * wchars
+ */
static void pdstring_wchars_clear(t_pdstring_wchars *w)
{
if (w->w_alloc) freebytes(w->w_buf, (w->w_alloc)*sizeof(wchar_t));
@@ -145,7 +149,9 @@ static void pdstring_wchars_init(t_pdstring_wchars *w, size_t n)
pdstring_wchars_realloc(w,n);
}
-//-- atoms
+/*---------------------------------------------------------------------
+ * atoms
+ */
static void pdstring_atoms_clear(t_pdstring_atoms *a)
{
if (a->a_alloc) freebytes(a->a_buf, (a->a_alloc)*sizeof(t_atom));
@@ -171,35 +177,67 @@ static void pdstring_atoms_init(t_pdstring_atoms *a, size_t n)
*=====================================================================*/
/*--------------------------------------------------------------------
- * pdstring_atoms2bytes()
- * + always appends a final NUL byte to *dst_buf, even if src_argv doesn't contain one
- * + returns number of bytes actually written to *dst_buf, __including__ implicit trailing NUL
+ * pdstring_any2bytes()
+ * + x is used for error reporting
+ * + uses x_binbuf for conversion
+ * + selector sel is added to binbuf too, if it is none of {NULL, &s_float, &s_list, &s_}
+ * + x_binbuf may be NULL, in which case a temporary t_binbuf is created and used
+ * - in this case, output bytes are copied into *dst, reallocating if required
+ * + if x_binbuf is given and non-NULL, dst may be NULL.
+ * - if dst is non-NULL, its values will be clobbered by those returned by
+ * binbuf_gettext()
*/
-static int pdstring_atoms2bytes(t_pdstring_bytes *dst, //-- destination byte buffer
- t_pdstring_atoms *src, //-- source t_atom float list
- t_float x_eos) //-- EOS byte value: stop if reached (negative ~ 0)
+static void pdstring_any2bytes(void *x, t_pdstring_bytes *dst, t_symbol *sel, t_pdstring_atoms *src, t_binbuf *x_binbuf)
{
- t_atom *argv = src->a_buf;
- int argc = src->a_len;
- unsigned char *s;
- int new_len=0;
+ int bb_is_tmp=0;
- /*-- re-allocate? --*/
- if (dst->b_alloc <= (argc+1))
- pdstring_bytes_realloc(dst, argc + 1 + PDSTRING_BYTES_GET);
+ //-- create temporary binbuf?
+ if (!x_binbuf) {
+ x_binbuf = binbuf_new();
+ bb_is_tmp = 1;
+ }
- /*-- get byte string --*/
- for (s=dst->b_buf, new_len=0; argc > 0; argc--, argv++, s++, new_len++)
- {
- *s = atom_getfloat(argv);
- if ((x_eos<0 && !*s) || (*s==x_eos)) { break; } /*-- hack: truncate at first EOS char --*/
- }
- *s = '\0'; /*-- always append terminating NUL */
- dst->b_len = new_len;
+ //-- prepare binbuf
+ binbuf_clear(x_binbuf);
- return new_len+1;
+ //-- binbuf_add(): selector
+ if (sel && sel != &s_float && sel != &s_list && sel != &s_) {
+ t_atom a;
+ SETSYMBOL((&a), sel);
+ binbuf_add(x_binbuf, 1, &a);
+ }
+
+ //-- binbuf_add(): src atoms
+ binbuf_add(x_binbuf, src->a_len, src->a_buf);
+
+ //-- output: get text string
+ if (bb_is_tmp) {
+ //-- temporary binbuf: copy text
+ char *text;
+ int len;
+ binbuf_gettext(x_binbuf, &text, &len);
+
+ //-- reallocate?
+ if ( dst->b_alloc < len )
+ pdstring_bytes_realloc(dst, len + PDSTRING_BYTES_GET);
+
+ //-- copy
+ memcpy(dst->b_buf, text, len*sizeof(char));
+ dst->b_len = len;
+
+ //-- cleanup
+ binbuf_free(x_binbuf);
+ if (text) freebytes(text,len);
+ }
+ else if (dst) {
+ //-- permanent binbuf: clobber dst
+ pdstring_bytes_clear(dst);
+ binbuf_gettext(x_binbuf, ((char**)((void*)(&dst->b_buf))), &dst->b_len);
+ dst->b_alloc = dst->b_len;
+ }
}
+
/*--------------------------------------------------------------------
* pdstring_bytes2any()
* + uses x_binbuf for conversion
@@ -209,7 +247,7 @@ static int pdstring_atoms2bytes(t_pdstring_bytes *dst, //-- destination byte buf
* - if dst is non-NULL, its values will be clobbered by those returned by
* binbuf_getnatom() and binbuf_getvec()
*/
-static void pdstring_bytes2any(t_pdstring_atoms *dst, t_pdstring_bytes *src, t_binbuf *x_binbuf)
+static void pdstring_bytes2any(void *x, t_pdstring_atoms *dst, t_pdstring_bytes *src, t_binbuf *x_binbuf)
{
int bb_is_tmp=0;
@@ -235,7 +273,6 @@ static void pdstring_bytes2any(t_pdstring_atoms *dst, t_pdstring_bytes *src, t_b
if ( dst->a_alloc < argc )
pdstring_atoms_realloc(dst, argc + PDSTRING_ATOMS_GET);
-
//-- copy
memcpy(dst->a_buf, argv, argc*sizeof(t_atom));
dst->a_len = argc;
@@ -251,44 +288,152 @@ static void pdstring_bytes2any(t_pdstring_atoms *dst, t_pdstring_bytes *src, t_b
}
}
+
/*--------------------------------------------------------------------
- * pdstring_bytes2wchars()
+ * pdstring_atoms2bytes()
+ * + always appends a final NUL byte to *dst_buf, even if src_argv doesn't contain one
+ * + returns number of bytes actually written to *dst_buf, __including__ implicit trailing NUL
*/
-static int pdstring_bytes2wchars(t_pdstring_wchars *dst, t_pdstring_bytes *src)
+static int pdstring_atoms2bytes(void *x, t_pdstring_bytes *dst, t_pdstring_atoms *src, t_float x_eos)
{
- /*
- //-- get required length
- int nwc=0, size;
+ t_atom *argv = src->a_buf;
+ int argc = src->a_len;
unsigned char *s;
- for (s=src->b_buf, size=src->b_len, nwc=0; size>0; nwc++) {
- int csize = mblen(s,size);
- if (csize < 0) {
- error("pdstring_bytes2wchars(): could not compute length for byte-string \"%s\" - skipping a byte!");
- s++;
- continue;
+ int new_len=0;
+
+ /*-- re-allocate? --*/
+ if (dst->b_alloc <= (argc+1))
+ pdstring_bytes_realloc(dst, argc + 1 + PDSTRING_BYTES_GET);
+
+ /*-- get byte string --*/
+ for (s=dst->b_buf, new_len=0; argc > 0; argc--, argv++, s++, new_len++)
+ {
+ *s = atom_getfloat(argv);
+ if ((x_eos<0 && !*s) || (*s==x_eos)) { break; } /*-- hack: truncate at first EOS char --*/
}
- s += csize;
- }
- */
+ *s = '\0'; /*-- always append terminating NUL */
+ dst->b_len = new_len;
+
+ return new_len+1;
+}
+
+/*--------------------------------------------------------------------
+ * pdstring_atoms2wchars()
+ * + always appends a final NUL wchar_t to dst->w_buf, even if src->a_buf doesn't contain one
+ * + returns number of bytes actually written to dst->w_buf, __including__ implicit trailing NUL
+ * + but dst->w_len does NOT include implicit trailing NUL
+ */
+static int pdstring_atoms2wchars(void *x, t_pdstring_wchars *dst, t_pdstring_atoms *src, t_float x_eos)
+{
+ t_atom *argv = src->a_buf;
+ int argc = src->a_len;
+ int new_len=0;
+ wchar_t *s;
+
+ /*-- re-allocate? --*/
+ if (dst->w_alloc <= (argc+1))
+ pdstring_wchars_realloc(dst, argc + 1 + PDSTRING_WCHARS_GET);
+
+ /*-- get wchar_t string --*/
+ for (s=dst->w_buf, new_len=0; argc > 0; argc--, argv++, s++, new_len++)
+ {
+ *s = atom_getfloat(argv);
+ if ((x_eos<0 && !*s) || (*s==x_eos)) { break; } /*-- hack: truncate at first EOS char --*/
+ }
+ *s = L'\0'; /*-- always append terminating NUL */
+ dst->w_len = new_len;
+
+ return new_len+1;
+}
+
+
+/*--------------------------------------------------------------------
+ * pdstring_bytes2wchars()
+ */
+static int pdstring_bytes2wchars(void *x, t_pdstring_wchars *dst, t_pdstring_bytes *src)
+{
+ size_t bi, wi;
//-- re-allocate?
if ( dst->w_alloc < src->b_len )
pdstring_wchars_realloc(dst, src->b_len + PDSTRING_WCHARS_GET);
//-- convert
- size_t newlen = mbstowcs(dst->w_buf, (char*)src->b_buf, src->b_len);
- if (newlen==((size_t)-1)) {
- error("pdstring_bytes2wchars(): could not convert multibyte string \"%s\"", src->b_buf);
+ //PDSDEBUG(post("\nbytes2wchars[dst=%p,src=%p]: init", dst,src);)
+ mbtowc(NULL,NULL,0); //-- re-initialize conversion state for mbtowc()
+ for (bi=0,wi=0; bi<src->b_len; wi++) {
+ int nbytes = mbtowc(dst->w_buf+wi, (char*)(src->b_buf+bi), src->b_len-bi);
+ if (nbytes <= 0) {
+ if (nbytes < 0) {
+ pd_error(x,"pdstring_bytes2wchars(): malformed byte string \"%s\" at char '%c' - copying literal byte", src->b_buf, src->b_buf[bi]);
+ }
+ dst->w_buf[wi] = src->b_buf[bi];
+ nbytes = 1;
+ }
+ bi += nbytes;
+ //PDSDEBUG(post("bytes2wchars[dst=%p,src=%p]: loop[bi=%d,wi=%d,src=%s]: nbytes=%d,wc=%u", dst,src, bi,wi,src, nbytes,dst->w_buf[wi]));
+ }
+ dst->w_len = wi;
+ return wi;
+}
+
+/*--------------------------------------------------------------------
+ * pdstring_wchars2bytes()
+ */
+static int pdstring_wchars2bytes(void *x, t_pdstring_bytes *dst, t_pdstring_wchars *src)
+{
+ size_t bi, wi;
+
+ //-- re-allocate?
+ if ( dst->b_alloc < src->w_len * MB_CUR_MAX )
+ pdstring_bytes_realloc(dst, src->w_len * MB_CUR_MAX + PDSTRING_WCHARS_GET);
+
+ //-- convert
+ for (bi=0,wi=0; wi < src->w_len; wi++) {
+ int nbytes = wctomb((char*)dst->b_buf+bi, src->w_buf[wi]);
+ if (nbytes <= 0) {
+ if (nbytes < 0) {
+ pd_error(x,"pdstring_wchars2bytes(): malformed wide string \"%S\" at wchar_t '%C' - forcing literal value", src->w_buf, src->w_buf[wi]);
+ }
+ dst->b_buf[bi] = src->w_buf[wi];
+ nbytes = 1;
+ }
+ bi += nbytes;
}
- dst->w_len = newlen;
+ dst->b_len = bi;
+ return bi;
+}
+
- return (newlen < src->b_len ? newlen : newlen+1);
+/*--------------------------------------------------------------------
+ * pdstring_bytes2atoms()
+ * + implicitly appends x_eos if >= 0 and != PDSTRING_EOS_NONE
+ */
+static void pdstring_bytes2atoms(void *x, t_pdstring_atoms *dst, t_pdstring_bytes *src, t_float x_eos)
+{
+ int i;
+
+ //-- re-allocate?
+ if ( dst->a_alloc <= src->b_len )
+ pdstring_atoms_realloc(dst, src->b_len + 1 + PDSTRING_ATOMS_GET);
+
+ //-- convert
+ for (i=0; i < src->b_len; i++) {
+ SETFLOAT((dst->a_buf+i), src->b_buf[i]);
+ }
+ dst->a_len = src->b_len;
+
+ //-- append eos atom?
+ if (x_eos >= 0 && x_eos != PDSTRING_EOS_NONE) {
+ SETFLOAT(dst->a_buf+dst->a_len, x_eos);
+ dst->a_len++;
+ }
}
/*--------------------------------------------------------------------
* pdstring_wchars2atoms()
*/
-static void pdstring_wchars2atoms(t_pdstring_atoms *dst, t_pdstring_wchars *src)
+static void pdstring_wchars2atoms(void *x, t_pdstring_atoms *dst, t_pdstring_wchars *src)
{
int i;
diff --git a/pdstring+wchar/src/pdstringUtils.h b/pdstring+wchar/src/pdstringUtils.h
new file mode 100644
index 0000000..85a72a5
--- /dev/null
+++ b/pdstring+wchar/src/pdstringUtils.h
@@ -0,0 +1,452 @@
+/* -*- Mode: C -*- */
+/*=============================================================================*\
+ * File: pdstringUtils.h
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: pdstring: common utilities (static include)
+ *
+ * Copyright (c) 2009 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file "COPYING", in this distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *=============================================================================*/
+
+#ifndef PDSTRING_UTILS_H
+#define PDSTRING_UTILS_H
+
+#include <string.h>
+#include <m_pd.h>
+#include <stdlib.h>
+#include "mooPdUtils.h"
+
+/*=====================================================================
+ * Debugging
+ *=====================================================================*/
+#define PDSTRING_UTILS_DEBUG 1
+//#undef PDSTRING_UTILS_DEBUG
+
+#ifdef PDSTRING_UTILS_DEBUG
+# define PDSDEBUG(x) x
+#else
+# define PDSDEBUG(x)
+#endif
+
+/*=====================================================================
+ * Constants
+ *=====================================================================*/
+
+/* PDSTRING_EOS_NONE
+ * + "safe" float value to use as x_eos if no truncation is desired
+ */
+#define PDSTRING_EOS_NONE 1e38f
+
+/* PDSTRING_DEFAULT_BUFLEN
+ * + common default buffer length
+ */
+#define PDSTRING_DEFAULT_BUFLEN 256
+
+/* PDSTRING_DEFAULT_GET
+ * + common default buffer grow length
+ */
+#define PDSTRING_DEFAULT_GET 256
+
+/* PDSTRING_BYSTES_GET
+ * + number of extra bytes to get when buffer must grow
+ */
+#define PDSTRING_BYTES_GET PDSTRING_DEFAULT_GET
+#define PDSTRING_WCHARS_GET PDSTRING_DEFAULT_GET
+#define PDSTRING_ATOMS_GET PDSTRING_DEFAULT_GET
+
+/*=====================================================================
+ * Structures & Types
+ *=====================================================================*/
+
+/* t_pdstring_bytes
+ * + a byte-string buffer
+ */
+typedef struct _pdstring_bytes {
+ unsigned char *b_buf; //-- byte-string buffer
+ int b_len; //-- current length of b_buf
+ size_t b_alloc; //-- allocated size of b_buf
+} t_pdstring_bytes;
+
+/* t_pdstring_wchars
+ * + a wide character buffer
+ */
+typedef struct _pdstring_wchars {
+ wchar_t *w_buf; //-- wide character buffer
+ int w_len; //-- current length of w_buf
+ size_t w_alloc; //-- allocated size of w_buf
+} t_pdstring_wchars;
+
+/* t_pdstring_atoms
+ * + an atom-list buffer
+ */
+typedef struct _pdstring_atoms {
+ t_atom *a_buf; //-- t_atom buffer (aka argv)
+ int a_len; //-- current length of a_buf (aka argc)
+ size_t a_alloc; //-- allocated size of a_buf
+} t_pdstring_atoms;
+
+/*=====================================================================
+ * Initialization
+ *=====================================================================*/
+
+/*---------------------------------------------------------------------
+ * bytes
+ */
+static void pdstring_bytes_clear(t_pdstring_bytes *b)
+{
+ if (b->b_alloc) freebytes(b->b_buf, (b->b_alloc)*sizeof(unsigned char));
+ b->b_buf = NULL;
+ b->b_len = 0;
+ b->b_alloc = 0;
+}
+static void pdstring_bytes_realloc(t_pdstring_bytes *b, size_t n)
+{
+ pdstring_bytes_clear(b);
+ b->b_buf = n ? (unsigned char*)getbytes(n*sizeof(unsigned char)) : NULL;
+ b->b_alloc = n;
+}
+static void pdstring_bytes_init(t_pdstring_bytes *b, size_t n)
+{
+ pdstring_bytes_clear(b);
+ pdstring_bytes_realloc(b,n);
+}
+
+/*---------------------------------------------------------------------
+ * wchars
+ */
+static void pdstring_wchars_clear(t_pdstring_wchars *w)
+{
+ if (w->w_alloc) freebytes(w->w_buf, (w->w_alloc)*sizeof(wchar_t));
+ w->w_buf = NULL;
+ w->w_len = 0;
+ w->w_alloc = 0;
+}
+static void pdstring_wchars_realloc(t_pdstring_wchars *w, size_t n)
+{
+ pdstring_wchars_clear(w);
+ w->w_buf = n ? (wchar_t*)getbytes(n*sizeof(wchar_t)) : NULL;
+ w->w_alloc = n;
+}
+static void pdstring_wchars_init(t_pdstring_wchars *w, size_t n)
+{
+ pdstring_wchars_clear(w);
+ pdstring_wchars_realloc(w,n);
+}
+
+/*---------------------------------------------------------------------
+ * atoms
+ */
+static void pdstring_atoms_clear(t_pdstring_atoms *a)
+{
+ if (a->a_alloc) freebytes(a->a_buf, (a->a_alloc)*sizeof(t_atom));
+ a->a_buf = NULL;
+ a->a_len = 0;
+ a->a_alloc = 0;
+}
+static void pdstring_atoms_realloc(t_pdstring_atoms *a, size_t n)
+{
+ pdstring_atoms_clear(a);
+ a->a_buf = n ? (t_atom*)getbytes(n*sizeof(t_atom)) : NULL;
+ a->a_alloc = n;
+}
+static void pdstring_atoms_init(t_pdstring_atoms *a, size_t n)
+{
+ pdstring_atoms_clear(a);
+ pdstring_atoms_realloc(a,n);
+}
+
+
+/*=====================================================================
+ * Utilities
+ *=====================================================================*/
+
+/*--------------------------------------------------------------------
+ * pdstring_any2bytes()
+ * + x is used for error reporting
+ * + uses x_binbuf for conversion
+ * + selector sel is added to binbuf too, if it is none of {NULL, &s_float, &s_list, &s_}
+ * + x_binbuf may be NULL, in which case a temporary t_binbuf is created and used
+ * - in this case, output bytes are copied into *dst, reallocating if required
+ * + if x_binbuf is given and non-NULL, dst may be NULL.
+ * - if dst is non-NULL, its values will be clobbered by those returned by
+ * binbuf_gettext()
+ */
+static void pdstring_any2bytes(void *x, t_pdstring_bytes *dst, t_symbol *sel, t_pdstring_atoms *src, t_binbuf *x_binbuf)
+{
+ int bb_is_tmp=0;
+
+ //-- create temporary binbuf?
+ if (!x_binbuf) {
+ x_binbuf = binbuf_new();
+ bb_is_tmp = 1;
+ }
+
+ //-- prepare binbuf
+ binbuf_clear(x_binbuf);
+
+ //-- binbuf_add(): selector
+ if (sel && sel != &s_float && sel != &s_list && sel != &s_) {
+ t_atom a;
+ SETSYMBOL((&a), sel);
+ binbuf_add(x_binbuf, 1, &a);
+ }
+
+ //-- binbuf_add(): src atoms
+ binbuf_add(x_binbuf, src->a_len, src->a_buf);
+
+ //-- output: get text string
+ if (bb_is_tmp) {
+ //-- temporary binbuf: copy text
+ char *text;
+ int len;
+ binbuf_gettext(x_binbuf, &text, &len);
+
+ //-- reallocate?
+ if ( dst->b_alloc < len )
+ pdstring_bytes_realloc(dst, len + PDSTRING_BYTES_GET);
+
+ //-- copy
+ memcpy(dst->b_buf, text, len*sizeof(char));
+ dst->b_len = len;
+
+ //-- cleanup
+ binbuf_free(x_binbuf);
+ if (text) freebytes(text,len);
+ }
+ else if (dst) {
+ //-- permanent binbuf: clobber dst
+ pdstring_bytes_clear(dst);
+ binbuf_gettext(x_binbuf, ((char**)((void*)(&dst->b_buf))), &dst->b_len);
+ dst->b_alloc = dst->b_len;
+ }
+}
+
+
+/*--------------------------------------------------------------------
+ * pdstring_bytes2any()
+ * + uses x_binbuf for conversion
+ * + x_binbuf may be NULL, in which case a temporary t_binbuf is created and used
+ * - in this case, output atoms are copied into *dst, reallocating if required
+ * + if x_binbuf is given and non-NULL, dst may be NULL.
+ * - if dst is non-NULL, its values will be clobbered by those returned by
+ * binbuf_getnatom() and binbuf_getvec()
+ */
+static void pdstring_bytes2any(void *x, t_pdstring_atoms *dst, t_pdstring_bytes *src, t_binbuf *x_binbuf)
+{
+ int bb_is_tmp=0;
+
+ //-- create temporary binbuf?
+ if (!x_binbuf) {
+ x_binbuf = binbuf_new();
+ bb_is_tmp = 1;
+ }
+
+ //-- populate binbuf
+ binbuf_clear(x_binbuf);
+ binbuf_text(x_binbuf, (char*)src->b_buf, src->b_len);
+ //PDSDEBUG(post("bytes2any[dst=%p,src=%p,bb=%p]: binbuf_print: ", dst,src,x_binbuf));
+ //PDSDEBUG(binbuf_print(x_binbuf));
+
+ //-- populate atom list
+ if (bb_is_tmp) {
+ //-- temporary binbuf: copy atoms
+ t_atom *argv = binbuf_getvec(x_binbuf);
+ int argc = binbuf_getnatom(x_binbuf);
+
+ //-- reallocate?
+ if ( dst->a_alloc < argc )
+ pdstring_atoms_realloc(dst, argc + PDSTRING_ATOMS_GET);
+
+ //-- copy
+ memcpy(dst->a_buf, argv, argc*sizeof(t_atom));
+ dst->a_len = argc;
+
+ //-- cleanup
+ binbuf_free(x_binbuf);
+ }
+ else if (dst) {
+ //-- permanent binbuf: clobber dst
+ dst->a_buf = binbuf_getvec(x_binbuf);
+ dst->a_len = binbuf_getnatom(x_binbuf);
+ dst->a_alloc = 0; //-- don't try to free this
+ }
+}
+
+
+/*--------------------------------------------------------------------
+ * pdstring_atoms2bytes()
+ * + always appends a final NUL byte to *dst_buf, even if src_argv doesn't contain one
+ * + returns number of bytes actually written to *dst_buf, __including__ implicit trailing NUL
+ */
+static int pdstring_atoms2bytes(void *x, t_pdstring_bytes *dst, t_pdstring_atoms *src, t_float x_eos)
+{
+ t_atom *argv = src->a_buf;
+ int argc = src->a_len;
+ unsigned char *s;
+ int new_len=0;
+
+ /*-- re-allocate? --*/
+ if (dst->b_alloc <= (argc+1))
+ pdstring_bytes_realloc(dst, argc + 1 + PDSTRING_BYTES_GET);
+
+ /*-- get byte string --*/
+ for (s=dst->b_buf, new_len=0; argc > 0; argc--, argv++, s++, new_len++)
+ {
+ *s = atom_getfloat(argv);
+ if ((x_eos<0 && !*s) || (*s==x_eos)) { break; } /*-- hack: truncate at first EOS char --*/
+ }
+ *s = '\0'; /*-- always append terminating NUL */
+ dst->b_len = new_len;
+
+ return new_len+1;
+}
+
+/*--------------------------------------------------------------------
+ * pdstring_atoms2wchars()
+ * + always appends a final NUL wchar_t to dst->w_buf, even if src->a_buf doesn't contain one
+ * + returns number of bytes actually written to dst->w_buf, __including__ implicit trailing NUL
+ * + but dst->w_len does NOT include implicit trailing NUL
+ */
+static int pdstring_atoms2wchars(void *x, t_pdstring_wchars *dst, t_pdstring_atoms *src, t_float x_eos)
+{
+ t_atom *argv = src->a_buf;
+ int argc = src->a_len;
+ int new_len=0;
+ wchar_t *s;
+
+ /*-- re-allocate? --*/
+ if (dst->w_alloc <= (argc+1))
+ pdstring_wchars_realloc(dst, argc + 1 + PDSTRING_WCHARS_GET);
+
+ /*-- get wchar_t string --*/
+ for (s=dst->w_buf, new_len=0; argc > 0; argc--, argv++, s++, new_len++)
+ {
+ *s = atom_getfloat(argv);
+ if ((x_eos<0 && !*s) || (*s==x_eos)) { break; } /*-- hack: truncate at first EOS char --*/
+ }
+ *s = L'\0'; /*-- always append terminating NUL */
+ dst->w_len = new_len;
+
+ return new_len+1;
+}
+
+
+/*--------------------------------------------------------------------
+ * pdstring_bytes2wchars()
+ */
+static int pdstring_bytes2wchars(void *x, t_pdstring_wchars *dst, t_pdstring_bytes *src)
+{
+ size_t bi, wi;
+
+ //-- re-allocate?
+ if ( dst->w_alloc < src->b_len )
+ pdstring_wchars_realloc(dst, src->b_len + PDSTRING_WCHARS_GET);
+
+ //-- convert
+ //PDSDEBUG(post("\nbytes2wchars[dst=%p,src=%p]: init", dst,src);)
+ mbtowc(NULL,NULL,0); //-- re-initialize conversion state for mbtowc()
+ for (bi=0,wi=0; bi<src->b_len; wi++) {
+ int nbytes = mbtowc(dst->w_buf+wi, (char*)(src->b_buf+bi), src->b_len-bi);
+ if (nbytes <= 0) {
+ if (nbytes < 0) {
+ pd_error(x,"pdstring_bytes2wchars(): malformed byte string \"%s\" at char '%c' - copying literal byte", src->b_buf, src->b_buf[bi]);
+ }
+ dst->w_buf[wi] = src->b_buf[bi];
+ nbytes = 1;
+ }
+ bi += nbytes;
+ //PDSDEBUG(post("bytes2wchars[dst=%p,src=%p]: loop[bi=%d,wi=%d,src=%s]: nbytes=%d,wc=%u", dst,src, bi,wi,src, nbytes,dst->w_buf[wi]));
+ }
+ dst->w_len = wi;
+ return wi;
+}
+
+/*--------------------------------------------------------------------
+ * pdstring_wchars2bytes()
+ */
+static int pdstring_wchars2bytes(void *x, t_pdstring_bytes *dst, t_pdstring_wchars *src)
+{
+ size_t bi, wi;
+
+ //-- re-allocate?
+ if ( dst->b_alloc < src->w_len * MB_CUR_MAX )
+ pdstring_bytes_realloc(dst, src->w_len * MB_CUR_MAX + PDSTRING_WCHARS_GET);
+
+ //-- convert
+ for (bi=0,wi=0; wi < src->w_len; wi++) {
+ int nbytes = wctomb((char*)dst->b_buf+bi, src->w_buf[wi]);
+ if (nbytes <= 0) {
+ if (nbytes < 0) {
+ pd_error(x,"pdstring_wchars2bytes(): malformed wide character (%u) - bashing to byte", src->w_buf[wi]);
+ }
+ dst->b_buf[bi] = src->w_buf[wi];
+ nbytes = 1;
+ }
+ bi += nbytes;
+ }
+ dst->b_len = bi;
+ return bi;
+}
+
+
+/*--------------------------------------------------------------------
+ * pdstring_bytes2atoms()
+ * + implicitly appends x_eos if >= 0 and != PDSTRING_EOS_NONE
+ */
+static void pdstring_bytes2atoms(void *x, t_pdstring_atoms *dst, t_pdstring_bytes *src, t_float x_eos)
+{
+ int i;
+
+ //-- re-allocate?
+ if ( dst->a_alloc <= src->b_len )
+ pdstring_atoms_realloc(dst, src->b_len + 1 + PDSTRING_ATOMS_GET);
+
+ //-- convert
+ for (i=0; i < src->b_len; i++) {
+ SETFLOAT((dst->a_buf+i), src->b_buf[i]);
+ }
+ dst->a_len = src->b_len;
+
+ //-- append eos atom?
+ if (x_eos >= 0 && x_eos != PDSTRING_EOS_NONE) {
+ SETFLOAT(dst->a_buf+dst->a_len, x_eos);
+ dst->a_len++;
+ }
+}
+
+/*--------------------------------------------------------------------
+ * pdstring_wchars2atoms()
+ */
+static void pdstring_wchars2atoms(void *x, t_pdstring_atoms *dst, t_pdstring_wchars *src)
+{
+ int i;
+
+ //-- re-allocate?
+ if ( dst->a_alloc < src->w_len )
+ pdstring_atoms_realloc(dst, src->w_len + PDSTRING_ATOMS_GET);
+
+ //-- convert
+ for (i=0; i < src->w_len; i++) {
+ SETFLOAT((dst->a_buf+i), src->w_buf[i]);
+ }
+ dst->a_len = src->w_len;
+}
+
+
+#endif /* PDSTRING_UTILS_H */
diff --git a/pdstring+wchar/src/wchars2any-help.pd b/pdstring+wchar/src/wchars2any-help.pd
new file mode 100644
index 0000000..d57343e
--- /dev/null
+++ b/pdstring+wchar/src/wchars2any-help.pd
@@ -0,0 +1,42 @@
+#N canvas 101 18 612 604 10;
+#X text 13 52 INLETS:;
+#X text 309 54 OUTLETS:;
+#X text 325 68 1 - pd messages;
+#X text 325 82 2 - bang on done;
+#X msg 24 113 97 32 98 32 99;
+#X msg 39 135 97 0 98 0 99;
+#X msg 92 206 0;
+#X msg 60 206 -1;
+#X msg 124 206 32;
+#X text 163 350 First argument: initial buffer size (length of object-local
+text buffer). This should get re-allocated when necessary. Specify
+0 (zero) to use the default value.;
+#X text 165 405 Second argument: initial EOS character. See above.
+;
+#X text 159 477 Right outlet gives a bang after the entire input list
+has been processed.;
+#X text 189 531 Parsed pd messages are sent to the left outlet.;
+#X text 306 580 Bryan Jurish <moocow@ling.uni-potsdam.de>;
+#X text 27 83 2 - EOS character (float);
+#X text 161 121 lists of floats are converted to pd messages.;
+#X text 168 161 ... selector is ignored ...;
+#X text 21 571 SEE ALSO:;
+#X obj 102 570 pdstring;
+#X text 13 30 SYNTAX: wchars2any [INITIAL_BUFSIZE [EOS_CHAR]];
+#X obj 131 454 print wchars2any-help-done;
+#X obj 24 529 print wchars2any-help;
+#X msg 54 161 StringThing 97;
+#X obj 24 350 wchars2any 128 0;
+#X text 59 7 wchars2any : convert lists of wchar_t values to pd messages
+;
+#X text 27 68 1 - wchar_t-valued float lists;
+#X text 166 202 The second inlet is as for [bytes2any];
+#X obj 169 570 locale;
+#X connect 4 0 23 0;
+#X connect 5 0 23 0;
+#X connect 6 0 23 1;
+#X connect 7 0 23 1;
+#X connect 8 0 23 1;
+#X connect 22 0 23 0;
+#X connect 23 0 21 0;
+#X connect 23 1 20 0;
diff --git a/pdstring+wchar/src/wchars2any.pd b/pdstring+wchar/src/wchars2any.pd
new file mode 100644
index 0000000..63bdc26
--- /dev/null
+++ b/pdstring+wchar/src/wchars2any.pd
@@ -0,0 +1,12 @@
+#N canvas 398 276 384 218 10;
+#X obj 68 22 inlet;
+#X obj 221 22 inlet;
+#X obj 68 112 bytes2any \$1 \$2;
+#X obj 68 73 wchars2bytes \$1;
+#X obj 68 146 outlet;
+#X obj 168 146 outlet;
+#X connect 0 0 3 0;
+#X connect 1 0 2 1;
+#X connect 2 0 4 0;
+#X connect 2 1 5 0;
+#X connect 3 0 2 0;
diff --git a/pdstring+wchar/src/wchars2bytes-help.pd b/pdstring+wchar/src/wchars2bytes-help.pd
new file mode 100644
index 0000000..b892bea
--- /dev/null
+++ b/pdstring+wchar/src/wchars2bytes-help.pd
@@ -0,0 +1,44 @@
+#N canvas 66 8 522 426 10;
+#X text 11 46 INLETS:;
+#X text 269 48 OUTLETS:;
+#X text 283 64 1 - byte-valued float lists;
+#X text 21 62 1 - wchar_t-valued float lists;
+#X msg 24 95 97 32 98 32 99;
+#X msg 45 229 228 246 252;
+#X msg 71 159 C;
+#N canvas 0 0 338 182 locale_LC_CTYPE 0;
+#X obj 48 124 locale;
+#X obj 48 36 inlet;
+#X obj 48 64 symbol;
+#X msg 48 92 set LC_CTYPE \$1;
+#X text 57 143 + requires the "locale" external;
+#X connect 1 0 2 0;
+#X connect 2 0 3 0;
+#X connect 3 0 0 0;
+#X restore 103 190 pd locale_LC_CTYPE;
+#X text 213 393 Bryan Jurish <moocow@ling.uni-potsdam.de>;
+#X text 9 377 SEE ALSO:;
+#X obj 24 394 pdstring;
+#X obj 91 394 locale;
+#X text 11 355 BUGS: float representation is only safe up to 24-bit
+values;
+#X text 81 5 wchars2bytes : convert wide characters to (multiple) bytes
+;
+#X text 11 27 SYNTAX: wchars2bytes [INITIAL_BUFSIZE];
+#X msg 103 159 en_DK.ISO-8859-1;
+#X msg 225 159 en_DK.UTF-8;
+#X text 69 129 Greater values are interpreted according to the current
+locale's LC_CTYPE category: here are some examples:;
+#X text 145 97 Values <= 127 are unchanged;
+#X msg 47 260 960 948;
+#X text 157 229 "&auml &ouml &uuml" \, ISO-8859-1 safe;
+#X text 159 259 "&pi &delta" \, not ISO-8859-1 safe;
+#X obj 24 310 wchars2bytes;
+#X obj 24 334 print wchars2bytes-help;
+#X connect 4 0 22 0;
+#X connect 5 0 22 0;
+#X connect 6 0 7 0;
+#X connect 15 0 7 0;
+#X connect 16 0 7 0;
+#X connect 19 0 22 0;
+#X connect 22 0 23 0;
diff --git a/pdstring+wchar/src/wchars2bytes-test.pd b/pdstring+wchar/src/wchars2bytes-test.pd
new file mode 100644
index 0000000..2a5bcc5
--- /dev/null
+++ b/pdstring+wchar/src/wchars2bytes-test.pd
@@ -0,0 +1,46 @@
+#N canvas 376 34 606 300 10;
+#X obj 114 136 bytes2wchars;
+#X obj 138 168 print wchars;
+#X obj 323 222 locale;
+#X msg 323 149 get;
+#X msg 359 199 set LC_CTYPE \$1;
+#X obj 359 178 symbol;
+#X msg 359 147 C;
+#X msg 393 147 en_US.ISO-8859-1;
+#X msg 515 147 en_US.UTF-8;
+#X obj 322 246 print locale;
+#X msg 37 41 246;
+#X floatatom 56 178 5 0 0 0 - - -;
+#X msg 37 61 195 182;
+#X text 35 23 &ouml \;;
+#X msg 159 61 197 147;
+#X text 155 23 &oelig \;;
+#X msg 159 39 339;
+#X msg 245 37 960;
+#X msg 245 59 207 128;
+#X text 245 21 &pi \;;
+#X obj 391 120 loadbang;
+#X text 93 41 ucs-4;
+#X text 95 59 utf-8;
+#X msg 325 61 207 128 0 197 147 0 195 182 0;
+#X obj 114 198 wchars2bytes;
+#X obj 112 226 print bytes;
+#X connect 0 0 1 0;
+#X connect 0 0 11 0;
+#X connect 0 0 24 0;
+#X connect 2 0 9 0;
+#X connect 3 0 2 0;
+#X connect 4 0 2 0;
+#X connect 5 0 4 0;
+#X connect 6 0 5 0;
+#X connect 7 0 5 0;
+#X connect 8 0 5 0;
+#X connect 10 0 0 0;
+#X connect 12 0 0 0;
+#X connect 14 0 0 0;
+#X connect 16 0 0 0;
+#X connect 17 0 0 0;
+#X connect 18 0 0 0;
+#X connect 20 0 7 0;
+#X connect 23 0 0 0;
+#X connect 24 0 25 0;
diff --git a/pdstring+wchar/src/wchars2bytes.c b/pdstring+wchar/src/wchars2bytes.c
new file mode 100644
index 0000000..8c6f74d
--- /dev/null
+++ b/pdstring+wchar/src/wchars2bytes.c
@@ -0,0 +1,157 @@
+/* -*- Mode: C -*- */
+/*=============================================================================*\
+ * File: wchars2bytes.c
+ * Author: Bryan Jurish <moocow@ling.uni-potsdam.de>
+ * Description: convert wchar_t-valued atom lists to byte-valued atom lists
+ *
+ * Copyright (c) 2009 Bryan Jurish.
+ *
+ * For information on usage and redistribution, and for a DISCLAIMER OF ALL
+ * WARRANTIES, see the file "COPYING", in this distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *=============================================================================*/
+
+#include <string.h>
+#include <wchar.h>
+#include <stdlib.h>
+#include <m_pd.h>
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "mooPdUtils.h"
+#include "pdstringUtils.h"
+
+/* black magic */
+#ifdef NT
+#pragma warning( disable : 4244 )
+#pragma warning( disable : 4305 )
+#endif
+
+/*--------------------------------------------------------------------
+ * DEBUG
+ *--------------------------------------------------------------------*/
+
+/*=====================================================================
+ * Constants
+ *=====================================================================*/
+static char *wchars2bytes_banner = "wchars2bytes: pdstring version " PACKAGE_VERSION " by Bryan Jurish";
+
+#define WCHARS2BYTES_DEFAULT_BUFLEN PDSTRING_DEFAULT_BUFLEN
+
+/*=====================================================================
+ * Structures and Types: any2string
+ *=====================================================================*/
+
+static t_class *wchars2bytes_class;
+
+typedef struct _wchars2bytes
+{
+ t_object x_obj;
+ t_pdstring_wchars x_wchars; //-- wide character buffer
+ t_pdstring_bytes x_bytes; //-- byte buffer
+ t_pdstring_atoms x_atoms; //-- atoms to output
+ t_outlet *x_outlet;
+} t_wchars2bytes;
+
+
+/*=====================================================================
+ * Methods
+ *=====================================================================*/
+
+/*--------------------------------------------------------------------
+ * anything
+ */
+static void wchars2bytes_anything(t_wchars2bytes *x, MOO_UNUSED t_symbol *sel, int argc, t_atom *argv)
+{
+ //-- convert arg_atoms -> wchars -> bytes -> atoms
+ t_pdstring_atoms arg_atoms = {argv,argc,0};
+ pdstring_atoms2wchars(x, &x->x_wchars, &arg_atoms, PDSTRING_EOS_NONE);
+ pdstring_wchars2bytes(x, &x->x_bytes, &x->x_wchars);
+ pdstring_bytes2atoms (x, &x->x_atoms, &x->x_bytes, PDSTRING_EOS_NONE);
+
+ //-- output
+ outlet_anything(x->x_outlet, &s_list, x->x_atoms.a_len, x->x_atoms.a_buf);
+}
+
+
+/*--------------------------------------------------------------------
+ * new
+ */
+static void *wchars2bytes_new(MOO_UNUSED t_symbol *sel, int argc, t_atom *argv)
+{
+ t_wchars2bytes *x = (t_wchars2bytes *)pd_new(wchars2bytes_class);
+ int bufsize = PDSTRING_DEFAULT_BUFLEN;
+
+ //-- args: 0: bufsize
+ if (argc > 0) {
+ int initial_bufsize = atom_getintarg(0,argc,argv);
+ if (initial_bufsize > 0) bufsize = initial_bufsize;
+ }
+
+ //-- allocate
+ pdstring_wchars_init(&x->x_wchars, bufsize);
+ pdstring_bytes_init (&x->x_bytes, bufsize);
+ pdstring_atoms_init (&x->x_atoms, bufsize);
+
+ //-- outlets
+ x->x_outlet = outlet_new(&x->x_obj, &s_list);
+
+ return (void *)x;
+}
+
+/*--------------------------------------------------------------------
+ * free
+ */
+static void wchars2bytes_free(t_wchars2bytes *x)
+{
+ pdstring_wchars_clear(&x->x_wchars);
+ pdstring_bytes_clear(&x->x_bytes);
+ pdstring_atoms_clear(&x->x_atoms);
+ outlet_free(x->x_outlet);
+ return;
+}
+
+/*--------------------------------------------------------------------
+ * setup: guts
+ */
+void wchars2bytes_setup_guts(void)
+{
+ //-- class
+ wchars2bytes_class = class_new(gensym("wchars2bytes"),
+ (t_newmethod)wchars2bytes_new,
+ (t_method)wchars2bytes_free,
+ sizeof(t_wchars2bytes),
+ CLASS_DEFAULT,
+ A_GIMME, //-- initial_bufsize
+ 0);
+
+ //-- methods
+ class_addanything(wchars2bytes_class, (t_method)wchars2bytes_anything);
+
+ //-- help symbol
+ //class_sethelpsymbol(wchars2bytes_class, gensym("wchars2bytes-help.pd")); //-- breaks pd-extended help lookup
+}
+
+/*--------------------------------------------------------------------
+ * setup
+ */
+void wchars2bytes_setup(void)
+{
+ post(wchars2bytes_banner);
+ wchars2bytes_setup_guts();
+}