[med-svn] [praat] 01/03: Imported Upstream version 5.4.6

Rafael Laboissière rlaboiss-guest at moszumanska.debian.org
Sat Mar 14 22:36:30 UTC 2015


This is an automated email from the git hooks/post-receive script.

rlaboiss-guest pushed a commit to branch master
in repository praat.

commit 8f11966720af2013a5f8e424efb4b3ee21fc7ec0
Author: Rafael Laboissiere <rafael at laboissiere.net>
Date:   Sat Mar 14 17:33:19 2015 -0300

    Imported Upstream version 5.4.6
---
 dwtools/LongSound_extensions.cpp |   3 +-
 dwtools/Sound_extensions.cpp     |  14 +-
 external/espeak/speech.h         |   2 +-
 external/flac/flac_share_alloc.h |   2 +
 external/mp3/mp3.cpp             |   4 +
 fon/Matrix.cpp                   |   6 +-
 fon/Pitch.cpp                    |   2 +-
 fon/Praat_tests.cpp              |  34 +-
 fon/Praat_tests_enums.h          |   8 +-
 fon/Sampled_def.h                |   2 +-
 fon/Sound_files.cpp              |  41 +--
 fon/TimeSoundAnalysisEditor.cpp  |  50 +--
 fon/WordList.cpp                 |  12 +-
 fon/manual_tutorials.cpp         |   7 +-
 fon/praat_Sound_init.cpp         |   2 +-
 main/main_Praat.cpp              |  11 +-
 sys/Collection.cpp               |  58 ++--
 sys/Graphics.cpp                 |   2 +
 sys/GraphicsScreen.cpp           |   2 +-
 sys/Graphics_enums.h             |  13 +-
 sys/Graphics_record.cpp          |   8 +-
 sys/Graphics_text.cpp            |  43 ++-
 sys/GuiList.cpp                  |   6 +-
 sys/GuiMenu.cpp                  |   2 +-
 sys/GuiText.cpp                  |  16 +-
 sys/TextEditor.cpp               |   4 +-
 sys/abcio.cpp                    | 680 +++++++++++++++++++++------------------
 sys/abcio.h                      |  28 +-
 sys/melder.cpp                   |   2 +-
 sys/melder.h                     | 417 ++++++++++++++----------
 sys/melder_alloc.cpp             |  97 ++++--
 sys/melder_audiofiles.cpp        | 459 ++++++++++++++++----------
 sys/melder_debug.cpp             |  20 +-
 sys/melder_files.cpp             |  32 +-
 sys/melder_ftoa.cpp              |  38 ++-
 sys/melder_readtext.cpp          |  86 ++---
 sys/melder_strings.cpp           | 208 ++++++------
 sys/melder_textencoding.cpp      | 350 ++++++++++++--------
 sys/melder_writetext.cpp         | 262 +++++++--------
 sys/oo.h                         |   9 +-
 sys/oo_DESCRIPTION.h             |   4 +-
 sys/oo_READ_BINARY.h             |   4 +-
 sys/praat.cpp                    |  10 +
 sys/praat_logo.cpp               |   6 +-
 sys/praat_objectMenus.cpp        |   2 +-
 sys/praat_version.h              |  10 +-
 test/fon/data.praat              | Bin 6455 -> 13426 bytes
 test/fon/soundFiles.praat        |   9 +
 test/runAllTests.praat           |  33 +-
 49 files changed, 1827 insertions(+), 1293 deletions(-)

diff --git a/dwtools/LongSound_extensions.cpp b/dwtools/LongSound_extensions.cpp
index 020ad1c..a8175fa 100644
--- a/dwtools/LongSound_extensions.cpp
+++ b/dwtools/LongSound_extensions.cpp
@@ -198,7 +198,8 @@ void LongSounds_appendToExistingSoundFile (Collection me, MelderFile file) {
 		autofile f = Melder_fopen (file, "r+b");
 		file -> filePointer = f; // essential !!
 		double sampleRate_d;
-		long startOfData, numberOfSamples;
+		long startOfData;
+		int32 numberOfSamples;
 		int numberOfChannels, encoding;
 		int audioFileType = MelderFile_checkSoundFile (file, &numberOfChannels,
 		                    &encoding, &sampleRate_d, &startOfData, &numberOfSamples);
diff --git a/dwtools/Sound_extensions.cpp b/dwtools/Sound_extensions.cpp
index 35916af..8d174d5 100644
--- a/dwtools/Sound_extensions.cpp
+++ b/dwtools/Sound_extensions.cpp
@@ -158,7 +158,7 @@ static void u1read (Sound me, FILE *f) {
 
 static void i2write (Sound me, FILE *f, int littleEndian, long *nClip) {
 	double *s = my z[1], min = -32768, max = 32767;
-	void (*put) (int, FILE *) = littleEndian ? binputi2LE : binputi2;
+	void (*put) (int16_t, FILE *) = littleEndian ? binputi2LE : binputi2;
 	*nClip = 0;
 	for (long i = 1; i <= my nx; i++) {
 		double sample = floor (s[i] * 32768 + 0.5);
@@ -175,7 +175,7 @@ static void i2write (Sound me, FILE *f, int littleEndian, long *nClip) {
 
 static void i2read (Sound me, FILE *f, int littleEndian) {
 	double *s = my z[1];
-	int (*get) (FILE *) = littleEndian ? bingeti2LE : bingeti2;
+	int16_t (*get) (FILE *) = littleEndian ? bingeti2LE : bingeti2;
 	for (long i = 1; i <= my nx; i++) {
 		s[i] = get (f) / 32768.;
 	}
@@ -183,7 +183,7 @@ static void i2read (Sound me, FILE *f, int littleEndian) {
 
 static void u2write (Sound me, FILE *f, int littleEndian, long *nClip) {
 	double *s = my z[1], min = 0, max = 65535;
-	void (*put) (unsigned int, FILE *) = littleEndian ? binputu2LE : binputu2;
+	void (*put) (uint16_t, FILE *) = littleEndian ? binputu2LE : binputu2;
 	*nClip = 0;
 	for (long i = 1; i <= my nx; i++) {
 		double sample = floor ( (s[i] + 1) * 65535 / 2 + 0.5);
@@ -208,7 +208,7 @@ static void u2read (Sound me, FILE *f, int littleEndian) {
 
 static void i4write (Sound me, FILE *f, int littleEndian, long *nClip) {
 	double *s = my z[1]; double min = -2147483648.0, max = 2147483647.0;
-	void (*put) (long, FILE *) = littleEndian ? binputi4LE : binputi4;
+	void (*put) (int32_t, FILE *) = littleEndian ? binputi4LE : binputi4;
 	*nClip = 0;
 	for (long i = 1; i <= my nx; i++) {
 		double sample = floor (s[i] * 2147483648.0 + 0.5);
@@ -225,7 +225,7 @@ static void i4write (Sound me, FILE *f, int littleEndian, long *nClip) {
 
 static void i4read (Sound me, FILE *f, int littleEndian) {
 	double *s = my z[1];
-	long (*get) (FILE *) = littleEndian ? bingeti4LE : bingeti4;
+	int32_t (*get) (FILE *) = littleEndian ? bingeti4LE : bingeti4;
 	for (long i = 1; i <= my nx; i++) {
 		s[i] = get (f) / 2147483648.;
 	}
@@ -234,7 +234,7 @@ static void i4read (Sound me, FILE *f, int littleEndian) {
 
 static void u4write (Sound me, FILE *f, int littleEndian, long *nClip) {
 	double *s = my z[1]; double min = 0.0, max = 4294967295.0;
-	void (*put) (unsigned long, FILE *) = littleEndian ? binputu4LE : binputu4;
+	void (*put) (uint32_t, FILE *) = littleEndian ? binputu4LE : binputu4;
 	*nClip = 0;
 	for (long i = 1; i <= my nx; i++) {
 		double sample = floor (s[i] * 4294967295.0 + 0.5);
@@ -251,7 +251,7 @@ static void u4write (Sound me, FILE *f, int littleEndian, long *nClip) {
 
 static void u4read (Sound me, FILE *f, int littleEndian) {
 	double *s = my z[1];
-	long (*get) (FILE *) = littleEndian ? bingeti4LE : bingeti4;
+	int32_t (*get) (FILE *) = littleEndian ? bingeti4LE : bingeti4;
 	for (long i = 1; i <= my nx; i++) {
 		s[i] = get (f) / 2147483648.0 - 1.0;
 	}
diff --git a/external/espeak/speech.h b/external/espeak/speech.h
index 24c8bfd..7f1dc96 100644
--- a/external/espeak/speech.h
+++ b/external/espeak/speech.h
@@ -26,7 +26,7 @@
 
 #ifdef _WIN32
 	wchar_t * Melder_peekUtf8ToWcs (const char *string);
-	const utf16_t * Melder_peekWcsToUtf16 (const wchar_t *string);
+	const uint16_t * Melder_peekWcsToUtf16 (const wchar_t *string);
 #endif
 
 // conditional compilation options
diff --git a/external/flac/flac_share_alloc.h b/external/flac/flac_share_alloc.h
index 34cde29..c746d61 100644
--- a/external/flac/flac_share_alloc.h
+++ b/external/flac/flac_share_alloc.h
@@ -33,6 +33,7 @@
 #endif
 #include <stdlib.h> /* for size_t, malloc(), etc */
 
+/* ppgb 20141231
 #ifndef SIZE_MAX
 # ifndef SIZE_T_MAX
 #  ifdef _MSC_VER
@@ -43,6 +44,7 @@
 # endif
 # define SIZE_MAX SIZE_T_MAX
 #endif
+*/
 
 #ifndef FLaC__INLINE
 #define FLaC__INLINE  inline   // ppgb 20071120
diff --git a/external/mp3/mp3.cpp b/external/mp3/mp3.cpp
index c110c45..c7b7191 100644
--- a/external/mp3/mp3.cpp
+++ b/external/mp3/mp3.cpp
@@ -273,6 +273,7 @@ int mp3f_analyze (MP3_FILE mp3f)
 				last * mp3f -> samples_per_frame / (float)mp3f -> frequency));
 #endif /* MP3_DEBUG */
 
+if(status!=-1)   // ppgb 2015-01-17
 	mp3f_seek (mp3f, 0);
 
 end:
@@ -323,12 +324,15 @@ int mp3f_seek (MP3_FILE mp3f, MP3F_OFFSET sample)
 		-- frame; 
 	if ( frame ) /* ...and the first frame it decodes is useless */
 		-- frame; 
+Melder_assert (mp3f -> frames_per_location > 0);
+Melder_assert (mp3f -> num_locations > 0);
 	location = frame / mp3f -> frames_per_location;
 	if (location >= mp3f -> num_locations)
 		location = mp3f -> num_locations - 1;
 	frame = location * mp3f -> frames_per_location;
 	base = frame * mp3f -> samples_per_frame;
 
+Melder_assert (location >= 0);
 	offset = mp3f -> locations [location];
 	if (fseek (mp3f -> f, offset, SEEK_SET) < 0)
 		return 0;
diff --git a/fon/Matrix.cpp b/fon/Matrix.cpp
index 0e6705a..85db3bc 100644
--- a/fon/Matrix.cpp
+++ b/fon/Matrix.cpp
@@ -436,10 +436,10 @@ void Matrix_movie (Matrix me, Graphics g) {
 Matrix Matrix_readAP (MelderFile file) {
 	try {
 		autofile f = Melder_fopen (file, "rb");
-		short header [256];
+		int16_t header [256];
 		for (long i = 0; i < 256; i ++)
 			header [i] = bingeti2LE (f);
-		double samplingFrequency = header [100];
+		double samplingFrequency = header [100];   // converting up (from 16 to 54 bytes)
 		Melder_casual ("Sampling frequency %.10g.", samplingFrequency);
 		autoMatrix me = Matrix_create (0, header [34], header [34] /* Number of frames. */, 1, 0.5,
 			0, header [35], header [35] /* Number of words per frame. */, 1, 0.5);
@@ -451,7 +451,7 @@ Matrix Matrix_readAP (MelderFile file) {
 		Melder_casual ("... Loading %d frames of %d words ...", header [34], header [35]);
 		for (long i = 1; i <= my nx; i ++)
 			for (long j = 1; j <= my ny; j ++)
-				my z [j] [i] = bingeti2LE (f);
+				my z [j] [i] = bingeti2LE (f);   // converting up (from 16 to 54 bytes)
 
 		/*
 		 * Get pitch frequencies.
diff --git a/fon/Pitch.cpp b/fon/Pitch.cpp
index 0a3fb9f..7f3ed01 100644
--- a/fon/Pitch.cpp
+++ b/fon/Pitch.cpp
@@ -753,7 +753,7 @@ Pitch Pitch_smooth (Pitch me, double bandWidth) {
 		long firstVoiced = 0, lastVoiced = 0;
 		for (long i = 1; i <= matrix1 -> nx; i ++) {
 			double f = matrix1 -> z [1] [i];
-			if (f) {
+			if (f != 0.0) {
 				if (! firstVoiced) firstVoiced = i;
 				lastVoiced = i;
 				sound1 -> z [1] [i + matrix1 -> nx] = f;
diff --git a/fon/Praat_tests.cpp b/fon/Praat_tests.cpp
index f266d55..41a738c 100644
--- a/fon/Praat_tests.cpp
+++ b/fon/Praat_tests.cpp
@@ -14,7 +14,7 @@
 
 
 int Praat_tests (int itest, wchar_t *arg1, wchar_t *arg2, wchar_t *arg3, wchar_t *arg4) {
-	long i, n = wcstol (arg1, NULL, 10);
+	unsigned long i, n = wcstoul (arg1, NULL, 10);
 	double x, t;
 	(void) arg1;
 	(void) arg2;
@@ -58,6 +58,38 @@ int Praat_tests (int itest, wchar_t *arg1, wchar_t *arg2, wchar_t *arg3, wchar_t
 			t = Melder_stopwatch ();
 			MelderInfo_writeLine (Melder_double (sum));
 		} break;
+		case kPraatTests_TIME_FLOAT_TO_UNSIGNED_BUILTIN: {
+			uint64_t sum = 0;
+			double fn = n;
+			for (double fi = 1.0; fi <= fn; fi = fi + 1.0)
+				sum += (uint32_t) fi;
+			t = Melder_stopwatch ();   // 2.59   // 1.60
+			MelderInfo_writeLine (Melder_double (sum));
+		} break;
+		case kPraatTests_TIME_FLOAT_TO_UNSIGNED_EXTERN: {
+			uint64_t sum = 0;
+			double fn = n;
+			for (double fi = 1.0; fi <= fn; fi = fi + 1.0)
+				sum += (uint32_t) ((int32_t) (fi - 2147483648.0) + 2147483647L + 1);
+			t = Melder_stopwatch ();   // 1.60
+			MelderInfo_writeLine (Melder_double (sum));
+		} break;
+		case kPraatTests_TIME_UNSIGNED_TO_FLOAT_BUILTIN: {
+			double sum = 0.0;
+			uint32_t nu = (uint32_t) n;
+			for (uint32_t iu = 1; iu <= nu; iu ++)
+				sum += (double) iu;
+			t = Melder_stopwatch ();   // 1.35
+			MelderInfo_writeLine (Melder_double (sum));
+		} break;
+		case kPraatTests_TIME_UNSIGNED_TO_FLOAT_EXTERN: {
+			double sum = 0.0;
+			uint32_t nu = (uint32_t) n;
+			for (uint32_t iu = 1; iu <= nu; iu ++)
+				sum += (double) (int32_t) (iu - 2147483647L - 1) + 2147483648.0;
+			t = Melder_stopwatch ();   // 0.96
+			MelderInfo_writeLine (Melder_double (sum));
+		} break;
 	}
 	MelderInfo_writeLine (Melder_single (t / n * 1e9), L" nanoseconds");
 	MelderInfo_close ();
diff --git a/fon/Praat_tests_enums.h b/fon/Praat_tests_enums.h
index bd746ed..0039524 100644
--- a/fon/Praat_tests_enums.h
+++ b/fon/Praat_tests_enums.h
@@ -1,5 +1,5 @@
 /* Praat_tests_enums.h */
-/* Paul Boersma, 16 June 2014 */
+/* Paul Boersma, 2 January 2015 */
 
 enums_begin (kPraatTests, 0)
 	enums_add (kPraatTests, 0, _, L"_")
@@ -9,6 +9,10 @@ enums_begin (kPraatTests, 0)
 	enums_add (kPraatTests, 4, TIME_SORT, L"TimeSort")
 	enums_add (kPraatTests, 5, TIME_INTEGER, L"TimeInteger")
 	enums_add (kPraatTests, 6, TIME_FLOAT, L"TimeFloat")
-enums_end (kPraatTests, 6, CHECK_RANDOM_1009_2009)
+	enums_add (kPraatTests, 7, TIME_FLOAT_TO_UNSIGNED_BUILTIN, L"TimeFloatToUnsigned_builtin")
+	enums_add (kPraatTests, 8, TIME_FLOAT_TO_UNSIGNED_EXTERN, L"TimeFloatToUnsigned_extern")
+	enums_add (kPraatTests, 9, TIME_UNSIGNED_TO_FLOAT_BUILTIN, L"TimeUnsignedToFloat_builtin")
+	enums_add (kPraatTests, 10, TIME_UNSIGNED_TO_FLOAT_EXTERN, L"TimeUnsignedToFloat_extern")
+enums_end (kPraatTests, 10, CHECK_RANDOM_1009_2009)
 
 /* End of file Praat_tests_enums.h */
diff --git a/fon/Sampled_def.h b/fon/Sampled_def.h
index 9255c29..bce9e20 100644
--- a/fon/Sampled_def.h
+++ b/fon/Sampled_def.h
@@ -21,7 +21,7 @@
 #define ooSTRUCT Sampled
 oo_DEFINE_CLASS (Sampled, Function)
 
-	oo_LONG (nx)
+	oo_INT32 (nx)
 	oo_DOUBLE (dx)
 	oo_DOUBLE (x1)
 
diff --git a/fon/Sound_files.cpp b/fon/Sound_files.cpp
index f471a7d..8be0de7 100644
--- a/fon/Sound_files.cpp
+++ b/fon/Sound_files.cpp
@@ -1,6 +1,6 @@
 /* Sound_files.cpp
  *
- * Copyright (C) 1992-2011,2012,2014 Paul Boersma & David Weenink
+ * Copyright (C) 1992-2011,2012,2014,2015 Paul Boersma & David Weenink
  *
  * 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
@@ -71,7 +71,8 @@ Sound Sound_readFromSoundFile (MelderFile file) {
 		autoMelderFile mfile = MelderFile_open (file);
 		int numberOfChannels, encoding;
 		double sampleRate;
-		long startOfData, numberOfSamples;
+		long startOfData;
+		int32 numberOfSamples;
 		int fileType = MelderFile_checkSoundFile (file, & numberOfChannels, & encoding, & sampleRate, & startOfData, & numberOfSamples);
 		if (fileType == 0)
 			Melder_throw ("Not an audio file.");
@@ -91,14 +92,14 @@ Sound Sound_readFromSoundFile (MelderFile file) {
 Sound Sound_readFromSesamFile (MelderFile file) {
 	try {
 		autofile f = Melder_fopen (file, "rb");
-		long header [1 + 128];
+		int32_t header [1 + 128];
 		for (long i = 1; i <= 128; i ++)
 			header [i] = bingeti4LE (f);
 		/*
 		 * Try SESAM header.
 		 */
-		double samplingFrequency = header [126];
-		long numberOfSamples = header [127];
+		double samplingFrequency = header [126];   // converting up (from 32 to 54 bits)
+		int32_t numberOfSamples = header [127];
 		if (samplingFrequency == 0.0 || numberOfSamples == 0) {
 			/*
 			 * Try LVS header.
@@ -109,8 +110,8 @@ Sound Sound_readFromSesamFile (MelderFile file) {
 		if (numberOfSamples < 1 || numberOfSamples > 1000000000 || samplingFrequency < 10.0 || samplingFrequency > 100000000.0)
 			Melder_throw ("Not a correct SESAM or LVS file.");
 		autoSound me = Sound_createSimple (1, numberOfSamples / samplingFrequency, samplingFrequency);
-		for (long i = 1; i <= numberOfSamples; i ++) {
-			my z [1] [i] = bingeti2LE (f) * (1.0 / 2048);   // 12 bits
+		for (int32_t i = 1; i <= numberOfSamples; i ++) {
+			my z [1] [i] = (double) bingeti2LE (f) * (1.0 / 2048);   // 12 bits
 		}
 		f.close (file);
 		return me.transfer();
@@ -135,7 +136,7 @@ Sound Sound_readFromBellLabsFile (MelderFile file) {
 		char *endOfTag = strchr (tag + 4, '\n');
 		if (endOfTag == NULL)
 			Melder_throw ("Second line missing or too long.");
-		unsigned long tagLength = endOfTag - tag + 1;   // probably 12
+		unsigned long tagLength = (endOfTag - tag) + 1;   // probably 12
 		unsigned long headerLength = atol (tag + 4);
 		if (headerLength <= 0)
 			Melder_throw ("Wrong header-length info.");
@@ -175,7 +176,7 @@ Sound Sound_readFromBellLabsFile (MelderFile file) {
 		 */
 		fseek (f, tagLength + headerLength, SEEK_SET);
 		for (unsigned long i = 1; i <= numberOfSamples; i ++)
-			my z [1] [i] = bingeti2 (f) * (1.0 / 32768);   // 16-bits big-endian
+			my z [1] [i] = (double) bingeti2 (f) * (1.0 / 32768);   // 16-bits big-endian
 
 		f.close (file);
 		return me.transfer();
@@ -204,17 +205,17 @@ Sound Sound_readFromKayFile (MelderFile file) {
 		if (fread (data, 1, 4, f) < 4) readError ();
 		if (! strnequ (data, "HEDR", 4) && ! strnequ (data, "HDR8", 4))
 			Melder_throw ("Missing HEDR or HDR8 chunk. Please report to paul.boersma at uva.nl.");
-		unsigned long chunkSize = bingetu4LE (f);
+		uint32_t chunkSize = bingetu4LE (f);
 		if (chunkSize & 1) ++ chunkSize;
 		if (chunkSize != 32 && chunkSize != 44)
 			Melder_throw ("Unknown chunk size %ld. Please report to paul.boersma at uva.nl.", chunkSize);
 		if (fread (data, 1, 20, f) < 20) readError ();
-		double samplingFrequency = bingetu4LE (f);
-		unsigned long numberOfSamples = bingetu4LE (f);
+		double samplingFrequency = bingetu4LE (f);   // converting up (from 32 to 53 bits)
+		uint32_t numberOfSamples = bingetu4LE (f);
 		if (samplingFrequency <= 0 || samplingFrequency > 1e7 || numberOfSamples >= 1000000000)
 			Melder_throw ("Not a correct Kay file.");
-		signed int tmp1 = bingeti2LE (f);
-		signed int tmp2 = bingeti2LE (f);
+		int16_t tmp1 = bingeti2LE (f);
+		int16_t tmp2 = bingeti2LE (f);
 		long numberOfChannels = tmp1 == -1 || tmp2 == -1 ? 1 : 2;
 		if (chunkSize == 44)
 			if (fread (data, 1, 12, f) < 12) readError ();
@@ -237,7 +238,7 @@ Sound Sound_readFromKayFile (MelderFile file) {
 		autoSound me = Sound_createSimple (numberOfChannels, numberOfSamples / samplingFrequency, samplingFrequency);
 		for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
 			for (unsigned long i = 1; i <= numberOfSamples; i ++) {
-				my z [ichan] [i] = bingeti2LE (f) / 32768.0;
+				my z [ichan] [i] = (double) bingeti2LE (f) / 32768.0;
 			}
 		}
 		f.close (file);
@@ -284,17 +285,17 @@ void Sound_writeToSesamFile (Sound me, MelderFile file) {
 			header [6] = ((my nx - 1) >> 8) + 1;   /* Number of disk blocks. */
 			header [64] = 32149;   /* ILS magic. */
 		/* LVS header. */
-			header [62] = floor (1 / my dx + 0.5);   /* Sampling frequency, rounded to n Hz. */
+			header [62] = round (1 / my dx);   /* Sampling frequency, rounded to n Hz. */
 			header [63] = -32000;   /* Magic: "sampled signal." */
 			header [66] = 2047;   /* Maximum absolute value: 12 bits. */
 			header [67] = 2047;   /* LVS magic. */
 			header [68] = my nx % 256;   /* Number of samples in last block. */
 			header [69] = 1;   /* ? */
 		/* Sesam header. */
-			header [126] = floor (1 / my dx + 0.5);   /* Sampling frequency, rounded to n Hz. */
+			header [126] = round (1 / my dx);   /* Sampling frequency, rounded to n Hz. */
 			header [127] = my nx;   /* Number of samples. */
 		for (long i = 1; i <= 128; i ++) binputi4LE (header [i], f);
-		for (long i = 1; i <= my nx; i ++) binputi2LE (floor (my z [1] [i] * 2048 + 0.5), f);
+		for (long i = 1; i <= my nx; i ++) binputi2LE (round (my z [1] [i] * 2048), f);
 		tail = 256 - my nx % 256;
 		if (tail == 256) tail = 0;
 		for (long i = 1; i <= tail; i ++) binputi2LE (0, f);   /* Pad last block with zeroes. */
@@ -319,7 +320,7 @@ void Sound_writeToKayFile (Sound me, MelderFile file) {
 		strcpy (date, ctime (& today));	
 		fwrite (date+4, 1, 20, file -> filePointer);   // skip weekday
 
-		binputi4LE (floor (1 / my dx + 0.5), file -> filePointer);   // sampling frequency
+		binputi4LE (round (1 / my dx), file -> filePointer);   // sampling frequency
 		binputi4LE (my nx, file -> filePointer);   // number of samples
 		int maximumA = 0;
 		for (long i = 1; i <= my nx; i ++) {
@@ -333,7 +334,7 @@ void Sound_writeToKayFile (Sound me, MelderFile file) {
 		} else {
 			int maximumB = 0;
 			for (long i = 1; i <= my nx; i ++) {
-				long value = floor (my z [2] [i] * 32768 + 0.5);
+				long value = round (my z [2] [i] * 32768);
 				if (value < - maximumB) maximumB = - value;
 				if (value > maximumB) maximumB = value;
 			}
diff --git a/fon/TimeSoundAnalysisEditor.cpp b/fon/TimeSoundAnalysisEditor.cpp
index 2809c09..8afa1f1 100644
--- a/fon/TimeSoundAnalysisEditor.cpp
+++ b/fon/TimeSoundAnalysisEditor.cpp
@@ -1868,32 +1868,34 @@ static void TimeSoundAnalysisEditor_v_draw_analysis (TimeSoundAnalysisEditor me)
 		if (! my p_pitch_show) textColour = Graphics_GREEN, alignment = Graphics_LEFT, y = my d_endWindow;
 		else if (! my p_spectrogram_show && ! my p_formant_show) textColour = Graphics_GREEN, alignment = Graphics_RIGHT, y = my d_startWindow;
 		else textColour = my p_spectrogram_show ? Graphics_LIME : Graphics_GREEN, alignment = Graphics_RIGHT, y = my d_endWindow;
-		Graphics_setWindow (my d_graphics, my d_startWindow, my d_endWindow, my p_intensity_viewFrom, my p_intensity_viewTo);
-		if (my d_intensity) {
-			if (my d_startSelection == my d_endSelection) {
-				intensityCursor = Vector_getValueAtX (my d_intensity, my d_startSelection, Vector_CHANNEL_1, Vector_VALUE_INTERPOLATION_LINEAR);
-			} else {
-				intensityCursor = Intensity_getAverage (my d_intensity, my d_startSelection, my d_endSelection, my p_intensity_averagingMethod);
+		if (my p_intensity_viewTo > my p_intensity_viewFrom) {
+			Graphics_setWindow (my d_graphics, my d_startWindow, my d_endWindow, my p_intensity_viewFrom, my p_intensity_viewTo);
+			if (my d_intensity) {
+				if (my d_startSelection == my d_endSelection) {
+					intensityCursor = Vector_getValueAtX (my d_intensity, my d_startSelection, Vector_CHANNEL_1, Vector_VALUE_INTERPOLATION_LINEAR);
+				} else {
+					intensityCursor = Intensity_getAverage (my d_intensity, my d_startSelection, my d_endSelection, my p_intensity_averagingMethod);
+				}
 			}
+			Graphics_setColour (my d_graphics, textColour);
+			intensityCursorVisible = NUMdefined (intensityCursor) && intensityCursor > my p_intensity_viewFrom && intensityCursor < my p_intensity_viewTo;
+			if (intensityCursorVisible) {
+				static const wchar_t *methodString [] = { L" (.5)", L" (μE)", L" (μS)", L" (μ)" };
+				Graphics_setTextAlignment (my d_graphics, alignment, Graphics_HALF);
+				Graphics_text3 (my d_graphics, y, intensityCursor, Melder_float (Melder_half (intensityCursor)), L" dB",
+					my d_startSelection == my d_endSelection ? L"" : methodString [my p_intensity_averagingMethod]);
+			}
+			if (! intensityCursorVisible || Graphics_dyWCtoMM (my d_graphics, intensityCursor - my p_intensity_viewFrom) > 5.0) {
+				Graphics_setTextAlignment (my d_graphics, alignment, Graphics_BOTTOM);
+				Graphics_text2 (my d_graphics, y, my p_intensity_viewFrom - Graphics_dyMMtoWC (my d_graphics, 0.5),
+					Melder_float (Melder_half (my p_intensity_viewFrom)), L" dB");
+			}
+			if (! intensityCursorVisible || Graphics_dyWCtoMM (my d_graphics, my p_intensity_viewTo - intensityCursor) > 5.0) {
+				Graphics_setTextAlignment (my d_graphics, alignment, Graphics_TOP);
+				Graphics_text2 (my d_graphics, y, my p_intensity_viewTo, Melder_float (Melder_half (my p_intensity_viewTo)), L" dB");
+			}
+			Graphics_setColour (my d_graphics, Graphics_BLACK);
 		}
-		Graphics_setColour (my d_graphics, textColour);
-		intensityCursorVisible = NUMdefined (intensityCursor) && intensityCursor > my p_intensity_viewFrom && intensityCursor < my p_intensity_viewTo;
-		if (intensityCursorVisible) {
-			static const wchar_t *methodString [] = { L" (.5)", L" (μE)", L" (μS)", L" (μ)" };
-			Graphics_setTextAlignment (my d_graphics, alignment, Graphics_HALF);
-			Graphics_text3 (my d_graphics, y, intensityCursor, Melder_float (Melder_half (intensityCursor)), L" dB",
-				my d_startSelection == my d_endSelection ? L"" : methodString [my p_intensity_averagingMethod]);
-		}
-		if (! intensityCursorVisible || Graphics_dyWCtoMM (my d_graphics, intensityCursor - my p_intensity_viewFrom) > 5.0) {
-			Graphics_setTextAlignment (my d_graphics, alignment, Graphics_BOTTOM);
-			Graphics_text2 (my d_graphics, y, my p_intensity_viewFrom - Graphics_dyMMtoWC (my d_graphics, 0.5),
-				Melder_float (Melder_half (my p_intensity_viewFrom)), L" dB");
-		}
-		if (! intensityCursorVisible || Graphics_dyWCtoMM (my d_graphics, my p_intensity_viewTo - intensityCursor) > 5.0) {
-			Graphics_setTextAlignment (my d_graphics, alignment, Graphics_TOP);
-			Graphics_text2 (my d_graphics, y, my p_intensity_viewTo, Melder_float (Melder_half (my p_intensity_viewTo)), L" dB");
-		}
-		Graphics_setColour (my d_graphics, Graphics_BLACK);
 	}
 	if (my p_spectrogram_show || my p_formant_show) {
 		static MelderString text = { 0 };
diff --git a/fon/WordList.cpp b/fon/WordList.cpp
index 059cd94..5e5c39c 100644
--- a/fon/WordList.cpp
+++ b/fon/WordList.cpp
@@ -50,7 +50,7 @@ static long WordList_count (WordList me) {
 void structWordList :: v_info () {
 	structData :: v_info ();
 	long n = WordList_count (this);
-	if (! length) length = wcslen (string);
+	if (! our length) our length = wcslen (our string);
 	MelderInfo_writeLine (L"Number of words: ", Melder_integer (n));
 	MelderInfo_writeLine (L"Number of characters: ", Melder_integer (length - n));
 }
@@ -58,12 +58,12 @@ void structWordList :: v_info () {
 void structWordList :: v_readBinary (FILE *f) {
 	wchar_t *current, *p;
 	int kar = 0;
-	length = bingeti4 (f);
-	if (length < 0)
-		Melder_throw ("Wrong length ", length, ".");
-	string = Melder_calloc (wchar_t, length + 1);
+	our length = bingeti4 (f);
+	if (our length < 0)
+		Melder_throw ("Wrong length ", our length, ".");
+	string = Melder_calloc (wchar_t, our length + 1);
 	p = current = string;
-	if (length > 0) {
+	if (our length > 0) {
 		/*
 		 * Read first word.
 		 */
diff --git a/fon/manual_tutorials.cpp b/fon/manual_tutorials.cpp
index 7007e82..4bab514 100644
--- a/fon/manual_tutorials.cpp
+++ b/fon/manual_tutorials.cpp
@@ -23,9 +23,14 @@
 void manual_tutorials_init (ManPages me);
 void manual_tutorials_init (ManPages me) {
 
-MAN_BEGIN (L"What's new?", L"ppgb", 20141228)
+MAN_BEGIN (L"What's new?", L"ppgb", 20150221)
 INTRO (L"Latest changes in Praat.")
 /*LIST_ITEM (L"• Manual page about @@drawing a vowel triangle at .")*/
+NORMAL (L"##5.4.06# (21 February 2015)")
+LIST_ITEM (L"• Windows: repaired a bug that could cause Praat to crash if a metafile resolution was 200 dpi.")
+NORMAL (L"##5.4.05# (13 February 2015)")
+LIST_ITEM (L"• Better support for big integer numbers on Windows XP.")
+LIST_ITEM (L"• Sound window: guarded against empty view ranges for the intensity curve.")
 NORMAL (L"##5.4.04# (28 December 2014)")
 LIST_ITEM (L"• Windows audio playback: if the sound has more channels than the audio hardware, distribute them evenly.")
 NORMAL (L"##5.4.03# (18 December 2014)")
diff --git a/fon/praat_Sound_init.cpp b/fon/praat_Sound_init.cpp
index f9c876f..a2931b4 100644
--- a/fon/praat_Sound_init.cpp
+++ b/fon/praat_Sound_init.cpp
@@ -478,7 +478,7 @@ static void common_Sound_create (void *dia, Interpreter interpreter, bool allowM
 	double startTime = GET_REAL (L"Start time");
 	double endTime = GET_REAL (L"End time");
 	double samplingFrequency = GET_REAL (L"Sampling frequency");
-	double numberOfSamples_real = floor ((endTime - startTime) * samplingFrequency + 0.5);
+	double numberOfSamples_real = round ((endTime - startTime) * samplingFrequency);
 	long numberOfSamples;
 	if (endTime <= startTime) {
 		if (endTime == startTime)
diff --git a/main/main_Praat.cpp b/main/main_Praat.cpp
index 314531c..4030e27 100644
--- a/main/main_Praat.cpp
+++ b/main/main_Praat.cpp
@@ -1,6 +1,6 @@
 /* main_Praat.cpp
  *
- * Copyright (C) 1992-2012,2013,2014 Paul Boersma
+ * Copyright (C) 1992-2012,2013,2014,2015 Paul Boersma
  *
  * 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
@@ -20,6 +20,11 @@
 #include "praat.h"
 #include "praat_version.h"
 
+#define UTF32_C(string) \
+	({ static const wchar_t *_static_utf32_string = Melder_utf8ToWcs (string); _static_utf32_string; })
+
+static const char32_t *greeting = U"Hello?";
+
 static void logo (Graphics g) {
 	Graphics_setWindow (g, 0, 1, 0.00, 0.80);
 	Graphics_setTextAlignment (g, Graphics_CENTRE, Graphics_HALF);
@@ -41,13 +46,13 @@ static void logo (Graphics g) {
 	Graphics_text (g, 0.5, 0.33, L"www.praat.org");
 	Graphics_setFont (g, kGraphics_font_HELVETICA);
 	Graphics_setFontSize (g, 10);
-	Graphics_text (g, 0.5, 0.16, L"Copyright © 1992–" xstr(PRAAT_YEAR) " by Paul Boersma and David Weenink");
+	Graphics_text (g, 0.5, 0.16, UTF32_C ("Copyright © 1992–" xstr(PRAAT_YEAR) " by Paul Boersma and David Weenink"));
 }
 
 int main (int argc, char *argv []) {
 	try {
 		praat_setLogo (130, 80, logo);
-		praat_init ("Praat", argc, argv);
+		praat_init ("Praat", (unsigned int) argc, argv);
 		INCLUDE_LIBRARY (praat_uvafon_init)
 		INCLUDE_LIBRARY (praat_contrib_Ola_KNN_init)
 		praat_run ();
diff --git a/sys/Collection.cpp b/sys/Collection.cpp
index 2fcf47d..79a468b 100644
--- a/sys/Collection.cpp
+++ b/sys/Collection.cpp
@@ -73,7 +73,7 @@ bool structCollection :: v_equal (thou) {
 				"cannot compare items of class ", Thing_className ((Thing) thy item [i]), ".");
 		bool equal = Data_equal ((Data) item [i], (Data) thy item [i]);
 		//Melder_casual ("classCollection_equal: %d, items %ld, types %ls and %ls",
-		//	equal, i, Thing_className (my item [i]), Thing_className (thy item [i]));
+		//	equal, (long) i, Thing_className (my item [i]), Thing_className (thy item [i]));
 		if (! equal) return false;
 	}
 	return true;
@@ -133,9 +133,9 @@ void structCollection :: v_readText (MelderReadText text) {
 			our item [i] = Thing_newFromClassNameA (klas);
 			Thing_version = -1;   /* Override. */
 			our size ++;
-			if (! Thing_member ((Thing) item [i], classData) || ! Data_canReadText ((Data) item [i]))
-				Melder_throw ("Cannot read item of class ", Thing_className ((Thing) item [i]), " in collection.");
-			Data_readText ((Data) item [i], text);
+			if (! Thing_member ((Thing) our item [i], classData) || ! Data_canReadText ((Data) our item [i]))
+				Melder_throw ("Cannot read item of class ", Thing_className ((Thing) our item [i]), " in collection.");
+			Data_readText ((Data) our item [i], text);
 			if (stringsRead == 3) {
 				if (line [n] == ' ') n ++;   // skip space character
 				length = wcslen (line+n);
@@ -144,27 +144,27 @@ void structCollection :: v_readText (MelderReadText text) {
 			}
 		}
 	} else {
-		long l_size = texgeti4 (text);
+		int32_t l_size = texgeti4 (text);
 		Collection_init (this, NULL, l_size);
-		for (long i = 1; i <= l_size; i ++) {
+		for (int32_t i = 1; i <= l_size; i ++) {
 			long saveVersion = Thing_version;   /* The version of the Collection... */
 			autostring8 className = texgets2 (text);
 			our item [i] = Thing_newFromClassNameA (className.peek());
 			our size ++;
-			if (! Thing_member ((Thing) item [i], classData) || ! Data_canReadText ((Data) item [i]))
-				Melder_throw ("Cannot read item of class ", Thing_className ((Thing) item [i]), " in collection.");
+			if (! Thing_member ((Thing) our item [i], classData) || ! Data_canReadText ((Data) our item [i]))
+				Melder_throw ("Cannot read item of class ", Thing_className ((Thing) our item [i]), " in collection.");
 			autostring objectName = texgetw2 (text);
-			Thing_setName ((Thing) item [i], objectName.peek());
-			Data_readText ((Data) item [i], text);
+			Thing_setName ((Thing) our item [i], objectName.peek());
+			Data_readText ((Data) our item [i], text);
 			Thing_version = saveVersion;
 		}
 	}
 }
 
 void structCollection :: v_writeBinary (FILE *f) {
-	binputi4 (size, f);
-	for (long i = 1; i <= size; i ++) {
-		Thing thing = (Thing) item [i];
+	binputi4 (our size, f);
+	for (long i = 1; i <= our size; i ++) {
+		Thing thing = (Thing) our item [i];
 		ClassInfo classInfo = thing -> classInfo;
 		if (! Thing_member (thing, classData) || ! Data_canWriteBinary ((Data) thing))
 			Melder_throw ("Objects of class ", classInfo -> className, L" cannot be written.");
@@ -177,43 +177,43 @@ void structCollection :: v_writeBinary (FILE *f) {
 
 void structCollection :: v_readBinary (FILE *f) {
 	if (Thing_version < 0) {
-		long l_size = bingeti4 (f);
+		int32_t l_size = bingeti4 (f);
 		if (l_size < 0)
 			Melder_throw ("Empty collection.");
 		Collection_init (this, NULL, l_size);
-		for (long i = 1; i <= l_size; i ++) {
+		for (int32_t i = 1; i <= l_size; i ++) {
 			char klas [200], name [2000];
-			if (fscanf (f, "%s%s", klas, name) < 2)
+			if (fscanf (f, "%s%s", klas, name) < 2)   // BUG
 				Melder_throw ("Cannot read class and name.");
-			item [i] = Thing_newFromClassNameA (klas);
+			our item [i] = Thing_newFromClassNameA (klas);
 			Thing_version = -1;   /* Override. */
 			our size ++;
-			if (! Thing_member ((Thing) item [i], classData))
-				Melder_throw ("Cannot read item of class ", Thing_className ((Thing) item [i]), ".");
+			if (! Thing_member ((Thing) our item [i], classData))
+				Melder_throw ("Cannot read item of class ", Thing_className ((Thing) our item [i]), ".");
 			if (fgetc (f) != ' ')
 				Melder_throw ("Cannot read space.");
-			Data_readBinary ((Data) item [i], f);
-			if (strcmp (name, "?")) Thing_setName ((Thing) item [i], Melder_peekUtf8ToWcs (name));
+			Data_readBinary ((Data) our item [i], f);
+			if (strcmp (name, "?")) Thing_setName ((Thing) our item [i], Melder_peekUtf8ToWcs (name));
 		}
 	} else {
-		long l_size = bingeti4 (f);
+		int32_t l_size = bingeti4 (f);
 		if (Melder_debug == 44)
-			Melder_casual ("structCollection :: v_readBinary: Reading %ld objects", l_size);
+			Melder_casual ("structCollection :: v_readBinary: Reading %ld objects", (long) l_size);
 		Collection_init (this, NULL, l_size);
-		for (long i = 1; i <= l_size; i ++) {
+		for (int32_t i = 1; i <= l_size; i ++) {
 			long saveVersion = Thing_version;   // the version of the Collection...
 			autostring8 klas = bingets1 (f);
 			if (Melder_debug == 44)
 				Melder_casual ("structCollection :: v_readBinary: Reading object of type %s", klas.peek());
-			item [i] = Thing_newFromClassNameA (klas.peek());
+			our item [i] = Thing_newFromClassNameA (klas.peek());
 			our size ++;
-			if (! Thing_member ((Thing) item [i], classData) || ! Data_canReadBinary ((Data) item [i]))
-				Melder_throw ("Objects of class ", Thing_className ((Thing) item [i]), " cannot be read.");
+			if (! Thing_member ((Thing) our item [i], classData) || ! Data_canReadBinary ((Data) our item [i]))
+				Melder_throw ("Objects of class ", Thing_className ((Thing) our item [i]), " cannot be read.");
 			autostring name = bingetw2 (f);
 			if (Melder_debug == 44)
 				Melder_casual ("structCollection :: v_readBinary: Reading object with name %ls", name.peek());
-			Thing_setName ((Thing) item [i], name.peek());
-			Data_readBinary ((Data) item [i], f);
+			Thing_setName ((Thing) our item [i], name.peek());
+			Data_readBinary ((Data) our item [i], f);
 			Thing_version = saveVersion;
 		}
 	}
diff --git a/sys/Graphics.cpp b/sys/Graphics.cpp
index 04044cf..f7c7247 100644
--- a/sys/Graphics.cpp
+++ b/sys/Graphics.cpp
@@ -106,6 +106,8 @@ void Graphics_init (Graphics me, int resolution) {
 		my resolutionNumber = kGraphics_resolution_100;
 	} else if (resolution == 180) {
 		my resolutionNumber = kGraphics_resolution_180;
+	} else if (resolution == 200) {
+		my resolutionNumber = kGraphics_resolution_200;
 	} else if (resolution == 300) {
 		my resolutionNumber = kGraphics_resolution_300;
 	} else if (resolution == 360) {
diff --git a/sys/GraphicsScreen.cpp b/sys/GraphicsScreen.cpp
index f63e6b4..65609c5 100644
--- a/sys/GraphicsScreen.cpp
+++ b/sys/GraphicsScreen.cpp
@@ -232,7 +232,7 @@ void structGraphicsScreen :: v_flushWs () {
 		// Ik weet niet of dit is wat het zou moeten zijn ;)
 		//gdk_window_process_updates (d_window, TRUE);   // this "works" but is incorrect because it's not the expose events that have to be carried out
 		//gdk_window_flush (d_window);
-		//gdk_flush ();
+		gdk_flush ();
 		// TODO: een aanroep die de eventuele grafische buffer ledigt,
 		// zodat de gebruiker de grafica ziet ook al blijft Praat in hetzelfde event zitten
 	#elif cocoa
diff --git a/sys/Graphics_enums.h b/sys/Graphics_enums.h
index 3e5d4d7..9bef38f 100644
--- a/sys/Graphics_enums.h
+++ b/sys/Graphics_enums.h
@@ -1,6 +1,6 @@
 /* Graphics_enums.h
  *
- * Copyright (C) 1992-2007,2013,2014 Paul Boersma
+ * Copyright (C) 1992-2007,2013,2014,2015 Paul Boersma
  *
  * 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
@@ -35,11 +35,12 @@ enums_begin (kGraphics_resolution, 0)
 	enums_add (kGraphics_resolution, 0,  96, L"96 dpi")
 	enums_add (kGraphics_resolution, 1, 100, L"100 dpi")
 	enums_add (kGraphics_resolution, 2, 180, L"180 dpi")
-	enums_add (kGraphics_resolution, 3, 300, L"300 dpi")
-	enums_add (kGraphics_resolution, 4, 360, L"360 dpi")
-	enums_add (kGraphics_resolution, 5, 600, L"600 dpi")
-	enums_add (kGraphics_resolution, 6, 1200, L"1200 dpi")
-enums_end (kGraphics_resolution, 6, 100)
+	enums_add (kGraphics_resolution, 3, 200, L"200 dpi")
+	enums_add (kGraphics_resolution, 4, 300, L"300 dpi")
+	enums_add (kGraphics_resolution, 5, 360, L"360 dpi")
+	enums_add (kGraphics_resolution, 6, 600, L"600 dpi")
+	enums_add (kGraphics_resolution, 7, 1200, L"1200 dpi")
+enums_end (kGraphics_resolution, 7, 100)
 
 enums_begin (kGraphics_colourScale, 0)
 	enums_add (kGraphics_colourScale, 0, GREY, L"grey")
diff --git a/sys/Graphics_record.cpp b/sys/Graphics_record.cpp
index 831c0d5..0568ba1 100644
--- a/sys/Graphics_record.cpp
+++ b/sys/Graphics_record.cpp
@@ -447,7 +447,7 @@ void Graphics_readRecordings (Graphics me, FILE *f) {
 	long old_irecord = my irecord;
 	long added_irecord = 0;
 	double *p = NULL, *endp = NULL;
-	long numberOfArguments = 0;
+	signed long numberOfArguments = 0;
 	int opcode = 0;
 	try {
 		added_irecord = bingeti4 (f);
@@ -458,7 +458,7 @@ void Graphics_readRecordings (Graphics me, FILE *f) {
 		while (p < endp) {
 			opcode = (int) bingetr4 (f);
 			put (opcode);
-			numberOfArguments = (long) bingetr4 (f);
+			numberOfArguments = (signed long) bingetr4 (f);
 			if (numberOfArguments == -1) {
 				numberOfArguments = bingeti4 (f);
 			}
@@ -467,7 +467,7 @@ void Graphics_readRecordings (Graphics me, FILE *f) {
 				put (bingetr4 (f));   // x
 				put (bingetr4 (f));   // y
 				put (bingetr4 (f));   // length
-				if ((long) fread (++ p, 8, numberOfArguments - 3, f) < numberOfArguments - 3)   // text
+				if (fread (++ p, 8, (size_t) numberOfArguments - 3, f) < (size_t) numberOfArguments - 3)   // text
 					Melder_throw ("Error reading graphics recordings.");
 				p += numberOfArguments - 4;
 			} else if (opcode == IMAGE_FROM_FILE) {
@@ -476,7 +476,7 @@ void Graphics_readRecordings (Graphics me, FILE *f) {
 				put (bingetr4 (f));   // y1
 				put (bingetr4 (f));   // y2
 				put (bingetr4 (f));   // length
-				if ((long) fread (++ p, 8, numberOfArguments - 5, f) < numberOfArguments - 5)   // text
+				if (fread (++ p, 8, (size_t) numberOfArguments - 5, f) < (size_t) numberOfArguments - 5)   // text
 					Melder_throw ("Error reading graphics recordings.");
 				p += numberOfArguments - 6;
 			} else {
diff --git a/sys/Graphics_text.cpp b/sys/Graphics_text.cpp
index 2d9a7e5..5dbb30e 100644
--- a/sys/Graphics_text.cpp
+++ b/sys/Graphics_text.cpp
@@ -387,15 +387,18 @@ static void charSize (I, _Graphics_widechar *lc) {
 			int normalSize = my fontSize * my resolution / 72.0;
 			lc -> size = lc -> size < 100 ? (3 * normalSize + 2) / 4 : normalSize;
         
-			utf16_t codes16 [2];
+			char16_t codes16 [2];
 			int nchars = 1;
-			if (lc -> kar > 0xFFFF) {
-				utf32_t kar = lc -> kar - 0x10000;
-				codes16 [0] = 0xD800 + (kar >> 10);
-				codes16 [1] = 0xDC00 + (kar & 0x3FF);
+			if (lc -> kar > 0x00FFFF) {
+				char32_t kar = lc -> kar - 0x010000;   // subtract the BMP
+				Melder_assert (lc -> kar <= 0x0FFFFF);   // no more than 20 bits should remain
+				// encode the upper 10 bits
+				codes16 [0] = (char16) (0x00D800 | (kar >> 10));   // at most 0x00D800 | 0x0003FF = 0x00DBFF
+				// encode the lower 10 bits
+				codes16 [1] = (char16) (0x00DC00 | (kar & 0x0003FF));   // at most 0x00DC00 | 0x0003FF = 0x00DFFF
 				nchars = 2;
 			} else {
-				codes16 [0] = lc -> kar;
+				codes16 [0] = (char16) lc -> kar;   // guarded conversion down
 			}
 			NSString *s = [[NSString alloc]
 				initWithBytes: codes16
@@ -480,16 +483,20 @@ static void charSize (I, _Graphics_widechar *lc) {
 				OSStatus err = ATSUCreateTextLayout (& textLayout);
 				if (err != 0) Melder_fatal ("Graphics_text/ATSUCreateTextLayout: unknown MacOS error %d.", (int) err);
 			}
-			utf16_t code16 [2];
+			char16_t code16 [2];
 			if (lc -> kar <= 0xFFFF) {
 				code16 [0] = lc -> kar;
-				OSStatus err = ATSUSetTextPointerLocation (textLayout, & code16 [0], kATSUFromTextBeginning, kATSUToTextEnd, 1);   // BUG: not 64-bit
+				OSStatus err = ATSUSetTextPointerLocation (textLayout,
+					(ConstUniCharArrayPtr) & code16 [0],
+					kATSUFromTextBeginning, kATSUToTextEnd, 1);   // BUG: not 64-bit
 				if (err != 0) Melder_fatal ("Graphics_text/ATSUSetTextPointerLocation low Unicode: unknown MacOS error %d.", (int) err);
 			} else {
-				utf32_t kar = lc -> kar - 0x10000;
+				char32_t kar = lc -> kar - 0x10000;
 				code16 [0] = 0xD800 + (kar >> 10);
 				code16 [1] = 0xDC00 + (kar & 0x3FF);
-				OSStatus err = ATSUSetTextPointerLocation (textLayout, & code16 [0], kATSUFromTextBeginning, kATSUToTextEnd, 2);   // BUG: not 64-bit
+				OSStatus err = ATSUSetTextPointerLocation (textLayout,
+					(ConstUniCharArrayPtr) & code16 [0],
+					kATSUFromTextBeginning, kATSUToTextEnd, 2);   // BUG: not 64-bit
 				if (err != 0) Melder_fatal ("Graphics_text/ATSUSetTextPointerLocation high Unicode: unknown MacOS error %d.", (int) err);
 			}
 			static ATSUFontFallbacks fontFallbacks = NULL;
@@ -682,7 +689,7 @@ static void charSize (I, _Graphics_widechar *lc) {
 }
 
 static void charDraw (I, int xDC, int yDC, _Graphics_widechar *lc,
-	const wchar_t *codes, const char *codes8, const utf16_t *codes16, int nchars, int width)
+	const wchar_t *codes, const char *codes8, const char16_t *codes16, int nchars, int width)
 {
 	iam (Graphics);
 	//Melder_casual ("nchars %d first %d %c rightToLeft %d", nchars, lc->kar, lc -> kar, lc->rightToLeft);
@@ -812,7 +819,7 @@ static void charDraw (I, int xDC, int yDC, _Graphics_widechar *lc,
 			}
 			if (hasHighUnicodeValues) {
 				nchars = wcslen_utf16 (codes, 0);
-				codes16 = Melder_peekWcsToUtf16 (codes);
+				codes16 = (const char16_t *) Melder_peekWcsToUtf16 (codes);
 			}
 			#if 1
 				CFStringRef s = CFStringCreateWithBytes (NULL, (const UInt8 *) codes16, nchars * 2, kCFStringEncodingUTF16LE, false);
@@ -917,10 +924,14 @@ static void charDraw (I, int xDC, int yDC, _Graphics_widechar *lc,
 			}
 			if (hasHighUnicodeValues) {
 				nchars = wcslen_utf16 (codes, 0);
-				OSStatus err = ATSUSetTextPointerLocation (theAtsuiTextLayout, Melder_peekWcsToUtf16 (codes), kATSUFromTextBeginning, kATSUToTextEnd, nchars);
+				OSStatus err = ATSUSetTextPointerLocation (theAtsuiTextLayout,
+					(ConstUniCharArrayPtr) Melder_peekWcsToUtf16 (codes),
+					kATSUFromTextBeginning, kATSUToTextEnd, nchars);
 				if (err != 0) Melder_fatal ("Graphics_text/ATSUSetTextPointerLocation hasHighUnicodeValues true: unknown MacOS error %d.", (int) err);
 			} else {
-				OSStatus err = ATSUSetTextPointerLocation (theAtsuiTextLayout, codes16, kATSUFromTextBeginning, kATSUToTextEnd, nchars);
+				OSStatus err = ATSUSetTextPointerLocation (theAtsuiTextLayout,
+					(ConstUniCharArrayPtr) codes16,
+					kATSUFromTextBeginning, kATSUToTextEnd, nchars);
 				if (err != 0) Melder_fatal ("Graphics_text/ATSUSetTextPointerLocation hasHighUnicodeValues false: unknown MacOS error %d.", (int) err);
 			}
 			static ATSUFontFallbacks fontFallbacks = NULL;
@@ -1273,7 +1284,7 @@ static long bufferSize;
 static _Graphics_widechar *theWidechar;
 static wchar_t *charCodes;
 static char *charCodes8;
-static utf16_t *charCodes16;
+static char16_t *charCodes16;
 static int initBuffer (const wchar_t *txt) {
 	try {
 		long sizeNeeded = wcslen (txt) + 1;   /* It is true that some characters are split into two, but all of these are backslash sequences. */
@@ -1286,7 +1297,7 @@ static int initBuffer (const wchar_t *txt) {
 			theWidechar = Melder_calloc (_Graphics_widechar, sizeNeeded);
 			charCodes = Melder_calloc (wchar_t, sizeNeeded);
 			charCodes8 = Melder_calloc (char, sizeNeeded);
-			charCodes16 = Melder_calloc (utf16_t, sizeNeeded);
+			charCodes16 = Melder_calloc (char16_t, sizeNeeded);
 			bufferSize = sizeNeeded;
 		}
 		return 1;
diff --git a/sys/GuiList.cpp b/sys/GuiList.cpp
index 14faa98..da8b9ef 100644
--- a/sys/GuiList.cpp
+++ b/sys/GuiList.cpp
@@ -319,7 +319,7 @@ Thing_implement (GuiList, GuiControl, 0);
 				strncpy (Melder_buffer1, text_utf8, dataLength);
 				Melder_buffer1 [dataLength] = '\0';
 				wchar_t *text_wcs = Melder_peekUtf8ToWcs (Melder_buffer1);
-				const utf16_t *text_utf16 = Melder_peekWcsToUtf16 (text_wcs);
+				const char16_t *text_utf16 = (const char16_t *) Melder_peekWcsToUtf16 (text_wcs);
 				UniCharCount runLength = wcslen (text_wcs);   // BUG
 				ATSUTextLayout textLayout;
 				ATSUStyle style;
@@ -331,7 +331,8 @@ Thing_implement (GuiList, GuiControl, 0);
 				ByteCount styleValueSizes [] = { sizeof (Fixed), sizeof (Boolean), sizeof (Boolean) };
 				ATSUAttributeValuePtr styleValues [] = { & fontSize, & boldStyle, & italicStyle };
 				ATSUSetAttributes (style, 3, styleAttributeTags, styleValueSizes, styleValues);
-				OSStatus err = ATSUCreateTextLayoutWithTextPtr (text_utf16, kATSUFromTextBeginning, kATSUToTextEnd, runLength,
+				OSStatus err = ATSUCreateTextLayoutWithTextPtr ((ConstUniCharArrayPtr) text_utf16,
+					kATSUFromTextBeginning, kATSUToTextEnd, runLength,
 					1, & runLength, & style, & textLayout);
 				Melder_assert (err == 0);
 				ATSUAttributeTag attributeTags [] = { kATSUCGContextTag, kATSULineFontFallbacksTag };
@@ -784,7 +785,6 @@ void structGuiList :: f_replaceItem (const wchar_t *itemText, long position) {
 		GuiCocoaList *list = (GuiCocoaList *) d_widget;
 		NSString *nsString = [[NSString alloc] initWithUTF8String: Melder_peekWcsToUtf8 (itemText)];
 		[[list contents]   replaceObjectAtIndex: position - 1   withObject: nsString];
-		Melder_assert ([nsString retainCount] == 2);
 		[nsString release];
 		[[list tableView] reloadData];
 	#elif win
diff --git a/sys/GuiMenu.cpp b/sys/GuiMenu.cpp
index 095719b..cc5001b 100644
--- a/sys/GuiMenu.cpp
+++ b/sys/GuiMenu.cpp
@@ -66,7 +66,7 @@ void structGuiMenu :: v_destroy () {
 				return;
 			}
 			unichar character = [characters characterAtIndex: 0];   // there is now at least one character, so no range exception can be raised
-			if (Melder_getTracing ()) {
+			if (Melder_isTracing) {
 				for (NSUInteger i = 0; i < [characters length]; i ++) {
 					unichar kar = [characters characterAtIndex: 0];
 					trace ("character [%d]: %d", (int) i, (int) kar);
diff --git a/sys/GuiText.cpp b/sys/GuiText.cpp
index e55ade6..532c5fd 100644
--- a/sys/GuiText.cpp
+++ b/sys/GuiText.cpp
@@ -1437,7 +1437,7 @@ void structGuiText :: f_replace (long from_pos, long to_pos, const wchar_t *text
 		Melder_free (winText);
 		UpdateWindow (d_widget -> window);
 	#elif mac
-		long length = wcslen (text), i;
+		size_t length = wcslen (text);
 		wchar_t *macText = Melder_malloc_f (wchar_t, length + 1);
 		Melder_assert (d_widget -> widgetClass == xmTextWidgetClass);
 		wcsncpy (macText, text, length);
@@ -1445,7 +1445,7 @@ void structGuiText :: f_replace (long from_pos, long to_pos, const wchar_t *text
 		/*
 		 * Replace all LF with CR.
 		 */
-		for (i = 0; i < length; i ++) if (macText [i] == '\n') macText [i] = 13;
+		for (size_t i = 0; i < length; i ++) if (macText [i] == '\n') macText [i] = 13;
 		/*
 		 * We DON'T replace any text without selecting it, so we can deselect any other text,
 		 * thus allowing ourselves to select [from_pos, to_pos] and use selection replacement.
@@ -1473,7 +1473,7 @@ void structGuiText :: f_replace (long from_pos, long to_pos, const wchar_t *text
 			for (long i = from_pos; i < to_pos; i ++) if (oldText [i] > 0xFFFF) numberOfSelectedHighUnicodeValues ++;
 			from_pos += numberOfLeadingHighUnicodeValues;
 			to_pos += numberOfLeadingHighUnicodeValues + numberOfSelectedHighUnicodeValues;
-			const UniChar *macText_utf16 = Melder_peekWcsToUtf16 (macText);
+			const char16_t *macText_utf16 = (const char16_t *) Melder_peekWcsToUtf16 (macText);
 			TXNSetData (d_macMlteObject, kTXNUnicodeTextData, macText_utf16, wcslen_utf16 (macText, 0) * 2, from_pos, to_pos);
 		}
 		Melder_free (macText);
@@ -1701,16 +1701,16 @@ void structGuiText :: f_setString (const wchar_t *text) {
 		 */
 		long j = 0;
 		for (long i = 0; i < length_utf32; i ++) {
-			utf32_t kar = text [i];
+			char32_t kar = (char32_t) text [i];   // reinterpret sign bit
 			if (kar == '\n') {   // LF
 				macText [j ++] = 13;   // CR
-			} else if (kar <= 0xFFFF) {
+			} else if (kar <= 0x00FFFF) {
 				macText [j ++] = kar;
 			} else {
 				Melder_assert (kar <= 0x10FFFF);
-				kar -= 0x10000;
-				macText [j ++] = 0xD800 | (kar >> 10);   // first UTF-16 surrogate character
-				macText [j ++] = 0xDC00 | (kar & 0x3FF);   // second UTF-16 surrogate character
+				kar -= 0x010000;
+				macText [j ++] = (UniChar) (0x00D800 | (kar >> 10));   // first UTF-16 surrogate character
+				macText [j ++] = (UniChar) (0x00DC00 | (kar & 0x0003FF));   // second UTF-16 surrogate character
 			}
 		}
 		macText [j] = '\0';
diff --git a/sys/TextEditor.cpp b/sys/TextEditor.cpp
index f93c19a..117f5ef 100644
--- a/sys/TextEditor.cpp
+++ b/sys/TextEditor.cpp
@@ -594,7 +594,9 @@ static void menu_cb_convertToCString (EDITOR_ARGS) {
 		} else if (*p == '\\') {
 			MelderInfo_write (L"\\\\");
 		} else if (*p < 0 || *p > 127) {
-			utf32_t kar = sizeof (wchar_t) == 2 ? (utf16_t) *p : *p;
+			char32_t kar = sizeof (wchar_t) == 2 ?
+				(char16_t) *p :   // reinterpret sign before extending -> zero extension
+				(char32_t) *p;
 			if (kar <= 0xFFFF) {   // BUG on Windows
 				MelderInfo_write (L"\\u", hex [kar >> 12], hex [(kar >> 8) & 0x0000000F], hex [(kar >> 4) & 0x0000000F], hex [kar & 0x0000000F]);
 			} else {
diff --git a/sys/abcio.cpp b/sys/abcio.cpp
index 4d87f9f..a30239f 100644
--- a/sys/abcio.cpp
+++ b/sys/abcio.cpp
@@ -41,6 +41,8 @@
 #endif
 #include "abcio.h"
 
+const uint16_t endiannessTest = 769;
+
 /********** ASCII I/O **********/
 
 #define WCHAR_MINUS_1  (sizeof (wchar_t) == 2 ? 0xFFFF : 0xFFFFFFFF)
@@ -289,7 +291,7 @@ long texgeti4 (MelderReadText text) {
 
 unsigned int texgetu1 (MelderReadText text) {
 	try {
-		long externalValue = getUnsigned (text);
+		unsigned long externalValue = getUnsigned (text);
 		if (externalValue > 255)
 			Melder_throw ("Value (", externalValue, ") out of range (0 .. 255).");
 		return (unsigned int) externalValue;
@@ -300,7 +302,7 @@ unsigned int texgetu1 (MelderReadText text) {
 
 unsigned int texgetu2 (MelderReadText text) {
 	try {
-		long externalValue = getUnsigned (text);
+		unsigned long externalValue = getUnsigned (text);
 		if (externalValue > 65535)
 			Melder_throw ("Value (", externalValue, ") out of range (0 .. 65535).");
 		return (unsigned int) externalValue;
@@ -311,7 +313,7 @@ unsigned int texgetu2 (MelderReadText text) {
 
 unsigned long texgetu4 (MelderReadText text) {
 	try {
-		long externalValue = getUnsigned (text);
+		unsigned long externalValue = getUnsigned (text);
 		return externalValue;
 	} catch (MelderError) {
 		Melder_throw ("Unsigned integer not read from text file.");
@@ -500,27 +502,27 @@ void texputw4 (MelderFile file, const wchar_t *s, const wchar_t *s1, const wchar
 /* On which machines is "short" a two's complement Big-Endian (MSB-first) 2-byte word? */
 
 #if defined (macintosh) && TARGET_RT_BIG_ENDIAN == 1
-	#define binario_shortBE2 (sizeof (short) == 2)
-	#define binario_shortLE2 0
+	#define binario_16bitBE 1
+	#define binario_16bitLE 0
 #elif defined (_WIN32) || defined (macintosh) && TARGET_RT_LITTLE_ENDIAN == 1
-	#define binario_shortBE2 0
-	#define binario_shortLE2 (sizeof (short) == 2)
+	#define binario_16bitBE 0
+	#define binario_16bitLE 1
 #else
-	#define binario_shortBE2 0
-	#define binario_shortLE2 0
+	#define binario_16bitBE 0
+	#define binario_16bitLE 0
 #endif
 
 /* On which machines is "long" a two's complement Big-Endian (MSB-first) 4-byte word? */
 
 #if defined (macintosh) && TARGET_RT_BIG_ENDIAN == 1
-	#define binario_longBE4 (sizeof (long) == 4)
-	#define binario_longLE4 0
+	#define binario_32bitBE 1
+	#define binario_32bitLE 0
 #elif defined (_WIN32) || defined (macintosh) && TARGET_RT_LITTLE_ENDIAN == 1
-	#define binario_longBE4 0
-	#define binario_longLE4 (sizeof (long) == 4)
+	#define binario_32bitBE 0
+	#define binario_32bitLE 1
 #else
-	#define binario_longBE4 0
-	#define binario_longLE4 0
+	#define binario_32bitBE 0
+	#define binario_32bitLE 0
 #endif
 
 /* On which machines is "float" IEEE, four bytes, Most Significant Bit first? */
@@ -606,6 +608,9 @@ void texputw4 (MelderFile file, const wchar_t *s, const wchar_t *s1, const wchar
 # define UnsignedToFloat(u)    \
 	  (((double)((long)((u) - 2147483647L - 1))) + 2147483648.0)
 
+//#define FloatToUnsigned(f) (uint32_t) (f)
+//#define UnsignedToFloat(u) (double) (u)
+
 /****************************************************************
  * Extended precision IEEE floating-point conversion routines.
  ****************************************************************/
@@ -640,7 +645,7 @@ unsigned int bingetu1 (FILE *f) {
 
 void binputu1 (unsigned int u, FILE *f) {
 	try {
-		if (putc (u, f) < 0) writeError ("a byte.");
+		if (putc ((int) u, f) < 0) writeError ("a byte.");   //
 	} catch (MelderError) {
 		Melder_throw ("Unsigned integer not written to 1 byte in binary file.");
 	}
@@ -690,14 +695,13 @@ static unsigned char readBuffer;
 
 #define macro_bingetb(nbits) \
 unsigned int bingetb##nbits (FILE *f) { \
-	unsigned char result; \
 	if (bitsInReadBuffer < nbits) { \
 		int externalValue = fgetc (f); \
 		if (externalValue < 0) readError (f, "a bit."); \
 		readBuffer = (unsigned char) externalValue; \
 		bitsInReadBuffer = 8; \
 	} \
-	result = readBuffer << (8 - bitsInReadBuffer); \
+	unsigned char result = (unsigned char) ((uint32_t) readBuffer << (8 - bitsInReadBuffer)); \
 	bitsInReadBuffer -= nbits; \
 	return result >> (8 - nbits); \
 }
@@ -711,17 +715,36 @@ macro_bingetb (7)
 
 void bingetb (FILE *f) { (void) f; bitsInReadBuffer = 0; }
 
-int bingeti2 (FILE *f) {
+int16_t bingeti2 (FILE *f) {
 	try {
-		if (binario_shortBE2 && Melder_debug != 18) {
-			signed short s;
-			if (fread (& s, sizeof (signed short), 1, f) != 1) readError (f, "a signed short integer.");
-			return (int) s;   // with sign extension if an int is 4 bytes
+		if (binario_16bitBE && Melder_debug != 18) {
+			int16_t s;
+			if (fread (& s, sizeof (int16_t), 1, f) != 1) readError (f, "a signed 16-bit integer.");
+			return s;
 		} else {
 			unsigned char bytes [2];
 			if (fread (bytes, sizeof (unsigned char), 2, f) != 2) readError (f, "two bytes.");
-			uint16_t externalValue = (uint16_t) ((uint16_t) bytes [0] << 8) | (uint16_t) bytes [1];
-			return (int) (int16_t) externalValue;   // with sign extension if an int is 4 bytes
+			return (int16_t)   // reinterpret sign bit
+				((uint16_t) ((uint16_t) bytes [0] << 8) |
+				             (uint16_t) bytes [1]);
+		}
+	} catch (MelderError) {
+		Melder_throw ("Signed integer not read from 2 bytes in binary file.");
+	}
+}
+
+int16_t bingeti2LE (FILE *f) {
+	try {
+		if (binario_16bitLE && Melder_debug != 18) {
+			int16_t s;
+			if (fread (& s, sizeof (int16_t), 1, f) != 1) readError (f, "a signed 16-bit integer.");
+			return s;
+		} else {
+			unsigned char bytes [2];
+			if (fread (bytes, sizeof (unsigned char), 2, f) != 2) readError (f, "two bytes.");
+			return (int16_t)   // reinterpret sign bit
+				((uint16_t) ((uint16_t) bytes [1] << 8) |
+				             (uint16_t) bytes [0]);
 		}
 	} catch (MelderError) {
 		Melder_throw ("Signed integer not read from 2 bytes in binary file.");
@@ -730,15 +753,34 @@ int bingeti2 (FILE *f) {
 
 uint16_t bingetu2 (FILE *f) {
 	try {
-		if (binario_shortBE2 && Melder_debug != 18) {
-			unsigned short s;
-			if (fread (& s, sizeof (unsigned short), 1, f) != 1) readError (f, "an unsigned short integer.");
+		if (binario_16bitBE && Melder_debug != 18) {
+			uint16_t s;
+			if (fread (& s, sizeof (uint16_t), 1, f) != 1) readError (f, "an unsigned 16-bit integer.");
 			return s;   // without sign extension
 		} else {
 			unsigned char bytes [2];
 			if (fread (bytes, sizeof (unsigned char), 2, f) != 2) readError (f, "two bytes.");
-			uint16_t externalValue = (uint16_t) ((uint16_t) bytes [0] << 8) | (uint16_t) bytes [1];
-			return externalValue;
+			return
+				(uint16_t) ((uint16_t) bytes [0] << 8) |
+				            (uint16_t) bytes [1];
+		}
+	} catch (MelderError) {
+		Melder_throw ("Unsigned integer not read from 2 bytes in binary file.");
+	}
+}
+
+uint16_t bingetu2LE (FILE *f) {
+	try {
+		if (binario_16bitLE && Melder_debug != 18) {
+			uint16_t s;
+			if (fread (& s, sizeof (uint16_t), 1, f) != 1) readError (f, "an unsigned 16-bit integer.");
+			return s;   // without sign extension
+		} else {
+			unsigned char bytes [2];
+			if (fread (bytes, sizeof (unsigned char), 2, f) != 2) readError (f, "two bytes.");
+			return
+				(uint16_t) ((uint16_t) bytes [1] << 8) |
+				            (uint16_t) bytes [0];
 		}
 	} catch (MelderError) {
 		Melder_throw ("Unsigned integer not read from 2 bytes in binary file.");
@@ -747,14 +789,16 @@ uint16_t bingetu2 (FILE *f) {
 
 int bingete2 (FILE *f, int min, int max, const wchar_t *type) {
 	try {
-		short result;
-		if (binario_shortBE2 && Melder_debug != 18) {
-			if (fread (& result, sizeof (short), 1, f) != 1) readError (f, "a signed short integer.");
+		int16_t result;
+		if (binario_16bitBE && Melder_debug != 18) {
+			if (fread (& result, sizeof (uint16_t), 1, f) != 1) readError (f, "a signed 16-bit integer.");
 		} else {
 			unsigned char bytes [2];
 			if (fread (bytes, sizeof (unsigned char), 2, f) != 2) readError (f, "two bytes.");
-			uint16_t externalValue = (uint16_t) ((uint16_t) bytes [0] << 8) | (uint16_t) bytes [1];
-			result = (short) (int16_t) externalValue;
+			uint16_t externalValue =
+				(uint16_t) ((uint16_t) bytes [0] << 8) |
+				            (uint16_t) bytes [1];
+			result = (int16_t) externalValue;
 		}
 		if (result < min || result > max)
 			Melder_throw (result, " is not a value of enumerated type \"", type, L"\".");
@@ -764,139 +808,115 @@ int bingete2 (FILE *f, int min, int max, const wchar_t *type) {
 	}
 }
 
-long bingeti3 (FILE *f) {
+int32_t bingeti3 (FILE *f) {
 	try {
 		unsigned char bytes [3];
 		if (fread (bytes, sizeof (unsigned char), 3, f) != 3) readError (f, "three bytes.");
-		uint32_t externalValue = (uint32_t) ((uint32_t) bytes [0] << 16) | (uint32_t) ((uint32_t) bytes [1] << 8) | (uint32_t) bytes [2];
+		uint32_t externalValue =
+			(uint32_t) ((uint32_t) bytes [0] << 16) |
+			(uint32_t) ((uint32_t) bytes [1] << 8) |
+			            (uint32_t) bytes [2];
 		if ((bytes [0] & 128) != 0)   // is the 24-bit sign bit on?
 			externalValue |= 0xFF000000;   // extend negative sign to 32 bits
-		return (long) (int32_t) externalValue;   // first add sign, then perhaps extend sign
+		return (int32_t) externalValue;   // reinterpret sign bit
 	} catch (MelderError) {
-		Melder_throw ("Signed long integer not read from 3 bytes in binary file.");
+		Melder_throw ("Signed integer not read from 3 bytes in binary file.");
 	}
 }
 
-long bingeti4 (FILE *f) {
+int32_t bingeti3LE (FILE *f) {
 	try {
-		if (binario_longBE4 && Melder_debug != 18) {
-			long l;
-			if (fread (& l, sizeof (long), 1, f) != 1) readError (f, "a signed long integer.");
-			return l;
-		} else {
-			unsigned char bytes [4];
-			if (fread (bytes, sizeof (unsigned char), 4, f) != 4) readError (f, "four bytes.");
-			uint32_t externalValue = 
-				(uint32_t) ((uint32_t) bytes [0] << 24) | (uint32_t) ((uint32_t) bytes [1] << 16) |
-				(uint32_t) ((uint32_t) bytes [2] << 8) | (uint32_t) bytes [3];
-			return (long) (int32_t) externalValue;   // first add sign, then perhaps extend sign
-		}
+		unsigned char bytes [3];
+		if (fread (bytes, sizeof (unsigned char), 3, f) != 3) readError (f, "three bytes.");
+		uint32_t externalValue =
+			(uint32_t) ((uint32_t) bytes [2] << 16) |
+			(uint32_t) ((uint32_t) bytes [1] << 8) |
+			            (uint32_t) bytes [0];
+		if ((bytes [2] & 128) != 0)   // is the 24-bit sign bit on?
+			externalValue |= 0xFF000000;   // extend negative sign to 32 bits
+		return (int32_t) externalValue;   // reinterpret sign bit
 	} catch (MelderError) {
-		Melder_throw ("Signed long integer not read from 4 bytes in binary file.");
+		Melder_throw ("Signed integer not read from 3 bytes in binary file.");
 	}
 }
 
-unsigned long bingetu4 (FILE *f) {
+int32_t bingeti4 (FILE *f) {
 	try {
-		if (binario_longBE4 && Melder_debug != 18) {
-			unsigned long l;
-			if (fread (& l, sizeof (unsigned long), 1, f) != 1) readError (f, "an unsigned long integer.");
+		if (binario_32bitBE && Melder_debug != 18) {
+			int32_t l;
+			if (fread (& l, sizeof (int32_t), 1, f) != 1) readError (f, "a signed 32-bit integer.");
 			return l;
 		} else {
 			unsigned char bytes [4];
 			if (fread (bytes, sizeof (unsigned char), 4, f) != 4) readError (f, "four bytes.");
-			uint32_t externalValue = 
-				(uint32_t) ((uint32_t) bytes [0] << 24) | (uint32_t) ((uint32_t) bytes [1] << 16) |
-				(uint32_t) ((uint32_t) bytes [2] << 8) | (uint32_t) bytes [3];
-			return (unsigned long) externalValue;
+			return (int32_t)
+				((uint32_t) ((uint32_t) bytes [0] << 24) |
+				 (uint32_t) ((uint32_t) bytes [1] << 16) |
+				 (uint32_t) ((uint32_t) bytes [2] << 8) |
+				             (uint32_t) bytes [3]);
 		}
 	} catch (MelderError) {
-		Melder_throw ("Unsigned long integer not read from 4 bytes in binary file.");
+		Melder_throw ("Signed integer not read from 4 bytes in binary file.");
 	}
 }
 
-int bingeti2LE (FILE *f) {
+int32_t bingeti4LE (FILE *f) {
 	try {
-		if (binario_shortLE2 && Melder_debug != 18) {
-			signed short s;
-			if (fread (& s, sizeof (signed short), 1, f) != 1) readError (f, "a signed short integer.");
-			int result = (int) s;   // with sign extension if an int is 4 bytes
-			Melder_assert (result >= -32768 && result <= 32767);
-			return result;   // with sign extension if an int is 4 bytes
-		} else {
-			unsigned char bytes [2];
-			if (fread (bytes, sizeof (unsigned char), 2, f) != 2) readError (f, "two bytes.");
-			uint16_t externalValue = (uint16_t) ((uint16_t) bytes [1] << 8) | (uint16_t) bytes [0];
-			return (int) (int16_t) externalValue;   // with sign extension if an int is 4 bytes
-		}
-	} catch (MelderError) {
-		Melder_throw ("Signed integer not read from 2 bytes in binary file.");
-	}
-}
-
-uint16_t bingetu2LE (FILE *f) {
-	try {
-		if (binario_shortLE2 && Melder_debug != 18) {
-			unsigned short s;
-			if (fread (& s, sizeof (unsigned short), 1, f) != 1) readError (f, "an unsigned short integer.");
-			return s;   // without sign extension
+		if (binario_32bitLE && Melder_debug != 18) {
+			int32_t l;
+			if (fread (& l, sizeof (int32_t), 1, f) != 1) readError (f, "a signed 32-bit integer.");
+			return l;
 		} else {
-			unsigned char bytes [2];
-			if (fread (bytes, sizeof (unsigned char), 2, f) != 2) readError (f, "two bytes.");
-			uint16_t externalValue = (uint16_t) ((uint16_t) bytes [1] << 8) | (uint16_t) bytes [0];
-			return externalValue;
+			unsigned char bytes [4];
+			if (fread (bytes, sizeof (unsigned char), 4, f) != 4) readError (f, "four bytes.");
+			return (int32_t)   // reinterpret sign bit
+				((uint32_t) ((uint32_t) bytes [3] << 24) |
+				 (uint32_t) ((uint32_t) bytes [2] << 16) |
+				 (uint32_t) ((uint32_t) bytes [1] << 8) |
+				             (uint32_t) bytes [0]);
 		}
 	} catch (MelderError) {
-		Melder_throw ("Unsigned integer not read from 2 bytes in binary file.");
-	}
-}
-
-long bingeti3LE (FILE *f) {
-	try {
-		unsigned char bytes [3];
-		if (fread (bytes, sizeof (unsigned char), 3, f) != 3) readError (f, "three bytes.");
-		uint32_t externalValue = ((uint32_t) bytes [2] << 16) | ((uint32_t) bytes [1] << 8) | (uint32_t) bytes [0];
-		if ((bytes [2] & 128) != 0)   // is the 24-bit sign bit on?
-			externalValue |= 0xFF000000;   // extend negative sign to 32 bits
-		return (long) (int32_t) externalValue;   // first convert signedness, then perhaps extend sign to 64 bits!
-	} catch (MelderError) {
-		Melder_throw ("Signed long integer not read from 3 bytes in binary file.");
+		Melder_throw ("Signed integer not read from 4 bytes in binary file.");
 	}
 }
 
-long bingeti4LE (FILE *f) {
+uint32_t bingetu4 (FILE *f) {
 	try {
-		if (binario_longLE4 && Melder_debug != 18) {
-			long l;
-			if (fread (& l, sizeof (long), 1, f) != 1) readError (f, "a signed long integer.");
+		if (binario_32bitBE && Melder_debug != 18) {
+			uint32_t l;
+			if (fread (& l, sizeof (uint32_t), 1, f) != 1) readError (f, "an unsigned 32-bit integer.");
 			return l;
 		} else {
 			unsigned char bytes [4];
 			if (fread (bytes, sizeof (unsigned char), 4, f) != 4) readError (f, "four bytes.");
-			uint32_t externalValue = (uint32_t) ((uint32_t) bytes [3] << 24) | (uint32_t) ((uint32_t) bytes [2] << 16) |
-				(uint32_t) ((uint32_t) bytes [1] << 8) | (uint32_t) bytes [0];
-			return (long) (int32_t) externalValue;   // first add signedness, then extend
+			return
+				(uint32_t) ((uint32_t) bytes [0] << 24) |
+				(uint32_t) ((uint32_t) bytes [1] << 16) |
+				(uint32_t) ((uint32_t) bytes [2] << 8) |
+				            (uint32_t) bytes [3];
 		}
 	} catch (MelderError) {
-		Melder_throw ("Signed long integer not read from 4 bytes in binary file.");
+		Melder_throw ("Unsigned integer not read from 4 bytes in binary file.");
 	}
 }
 
-unsigned long bingetu4LE (FILE *f) {
+uint32_t bingetu4LE (FILE *f) {
 	try {
-		if (binario_longLE4 && Melder_debug != 18) {
-			unsigned long l;
-			if (fread (& l, sizeof (unsigned long), 1, f) != 1) readError (f, "an unsigned long integer.");
+		if (binario_32bitLE && Melder_debug != 18) {
+			uint32_t l;
+			if (fread (& l, sizeof (uint32_t), 1, f) != 1) readError (f, "an unsigned 32-bit integer.");
 			return l;
 		} else {
 			unsigned char bytes [4];
 			if (fread (bytes, sizeof (unsigned char), 4, f) != 4) readError (f, "four bytes.");
-			uint32_t externalValue = (uint32_t) ((uint32_t) bytes [3] << 24) | (uint32_t) ((uint32_t) bytes [2] << 16) |
-				(uint32_t) ((uint32_t) bytes [1] << 8) | (uint32_t) bytes [0];
-			return (unsigned long) externalValue;
+			return
+				(uint32_t) ((uint32_t) bytes [3] << 24) |
+				(uint32_t) ((uint32_t) bytes [2] << 16) |
+				(uint32_t) ((uint32_t) bytes [1] << 8) |
+				            (uint32_t) bytes [0];
 		}
 	} catch (MelderError) {
-		Melder_throw ("Unsigned long integer not read from 4 bytes in binary file.");
+		Melder_throw ("Unsigned integer not read from 4 bytes in binary file.");
 	}
 }
 
@@ -904,21 +924,26 @@ double bingetr4 (FILE *f) {
 	try {
 		if (binario_floatIEEE4msb && Melder_debug != 18) {
 			float x;
-			if (fread (& x, sizeof (float), 1, f) != 1) readError (f, "a single-precision floating-point number.");
+			if (fread (& x, sizeof (float), 1, f) != 1) readError (f, "a 32-bit floating-point number.");
 			return x;
 		} else {
 			unsigned char bytes [4];
 			if (fread (bytes, sizeof (unsigned char), 4, f) != 4) readError (f, "four bytes.");
-			long exponent = ((unsigned long) (bytes [0] & 0x7F) << 1) | ((unsigned long) (bytes [1] & 0x80) >> 7);   // 32 or 64 bits
-			unsigned long mantissa = ((unsigned long) (bytes [1] & 0x7F) << 16) | ((unsigned long) bytes [2] << 8) | (unsigned long) bytes [3];   // 32 or 64 bits
+			int32_t exponent = (int32_t)
+				((uint32_t) ((uint32_t) ((uint32_t) bytes [0] & 0x7F) << 1) |
+				 (uint32_t) ((uint32_t) ((uint32_t) bytes [1] & 0x80) >> 7));
+			uint32_t mantissa =
+				(uint32_t) ((uint32_t) ((uint32_t) bytes [1] & 0x7F) << 16) |
+				            (uint32_t) ((uint32_t) bytes [2] << 8) |
+				                        (uint32_t) bytes [3];
 			double x;
 			if (exponent == 0)
 				if (mantissa == 0) x = 0.0;
-				else x = ldexp (UnsignedToFloat (mantissa), exponent - 149);   // denormalized
+				else x = ldexp ((double) mantissa, exponent - 149);   // denormalized
 			else if (exponent == 0x00FF)   // Infinity or Not-a-Number
 				x = HUGE_VAL;
 			else   // finite
-				x = ldexp (UnsignedToFloat (mantissa | 0x00800000), exponent - 150);
+				x = ldexp ((double) (mantissa | 0x00800000), exponent - 150);
 			return bytes [0] & 0x80 ? - x : x;
 		}
 	} catch (MelderError) {
@@ -930,21 +955,26 @@ double bingetr4LE (FILE *f) {
 	try {
 		if (binario_floatIEEE4lsb && Melder_debug != 18) {
 			float x;
-			if (fread (& x, sizeof (float), 1, f) != 1) readError (f, "a single-precision floating-point number.");
+			if (fread (& x, sizeof (float), 1, f) != 1) readError (f, "a 32-bit floating-point number.");
 			return x;
 		} else {
 			unsigned char bytes [4];
 			if (fread (bytes, sizeof (unsigned char), 4, f) != 4) readError (f, "four bytes.");
-			long exponent = ((unsigned long) (bytes [3] & 0x7F) << 1) | ((unsigned long) (bytes [2] & 0x80) >> 7);   // 32 or 64 bits
-			unsigned long mantissa = ((unsigned long) (bytes [2] & 0x7F) << 16) | ((unsigned long) bytes [1] << 8) | (unsigned long) bytes [0];   // 32 or 64 bits
+			int32_t exponent = (int32_t)
+				((uint32_t) ((uint32_t) ((uint32_t) bytes [3] & 0x7F) << 1) |
+				 (uint32_t) ((uint32_t) ((uint32_t) bytes [2] & 0x80) >> 7));
+			uint32_t mantissa =
+				(uint32_t) ((uint32_t) ((uint32_t) bytes [2] & 0x7F) << 16) |
+				            (uint32_t) ((uint32_t) bytes [1] << 8) |
+				                        (uint32_t) bytes [0];
 			double x;
 			if (exponent == 0)
 				if (mantissa == 0) x = 0.0;
-				else x = ldexp (UnsignedToFloat (mantissa), exponent - 149);   // denormalized
-			else if (exponent == 0x00FF)   // Infinity or Not-a-Number. */
+				else x = ldexp ((double) mantissa, exponent - 149);   // denormalized
+			else if (exponent == 0x00FF)   // Infinity or Not-a-Number
 				x = HUGE_VAL;
 			else   // finite
-				x = ldexp (UnsignedToFloat (mantissa | 0x00800000), exponent - 150);
+				x = ldexp ((double) (mantissa | 0x00800000), exponent - 150);
 			return bytes [3] & 0x80 ? - x : x;
 		}
 	} catch (MelderError) {
@@ -956,25 +986,34 @@ double bingetr8 (FILE *f) {
 	try {
 		if (binario_doubleIEEE8msb && Melder_debug != 18) {
 			double x;
-			if (fread (& x, sizeof (double), 1, f) != 1) readError (f, "a double-precision floating-point number.");
+			if (fread (& x, sizeof (double), 1, f) != 1) readError (f, "a 64-bit floating-point number.");
 			return x;
 		} else {
 			unsigned char bytes [8];
 			if (fread (bytes, sizeof (unsigned char), 8, f) != 8) readError (f, "eight bytes.");
 			Melder_assert (sizeof (long) >= 4);
-			long exponent = ((unsigned long) (bytes [0] & 0x7F) << 4) | ((unsigned long) (bytes [1] & 0xF0) >> 4);
-			unsigned long highMantissa = ((unsigned long) (bytes [1] & 0x0F) << 16) | ((unsigned long) bytes [2] << 8) | (unsigned long) bytes [3];
-			unsigned long lowMantissa = ((unsigned long) bytes [4] << 24) | ((unsigned long) bytes [5] << 16) | ((unsigned long) bytes [6] << 8) | (unsigned long) bytes [7];
+			int32_t exponent = (int32_t)
+				((uint32_t) ((uint32_t) ((uint32_t) bytes [0] & 0x7F) << 4) |
+				 (uint32_t) ((uint32_t) ((uint32_t) bytes [1] & 0xF0) >> 4));
+			uint32_t highMantissa =
+				(uint32_t) ((uint32_t) ((uint32_t) bytes [1] & 0x0F) << 16) |
+							(uint32_t) ((uint32_t) bytes [2] << 8) |
+				                        (uint32_t) bytes [3];
+			uint32_t lowMantissa =
+				(uint32_t) ((uint32_t) bytes [4] << 24) |
+				(uint32_t) ((uint32_t) bytes [5] << 16) |
+				(uint32_t) ((uint32_t) bytes [6] << 8) |
+				            (uint32_t) bytes [7];
 			double x;
 			if (exponent == 0)
 				if (highMantissa == 0 && lowMantissa == 0) x = 0.0;
-				else x = ldexp (UnsignedToFloat (highMantissa), exponent - 1042) +
-					ldexp (UnsignedToFloat (lowMantissa), exponent - 1074);   // denormalized
+				else x = ldexp ((double) highMantissa, exponent - 1042) +
+					ldexp ((double) lowMantissa, exponent - 1074);   // denormalized
 			else if (exponent == 0x07FF)   // Infinity or Not-a-Number
 				x = HUGE_VAL;
 			else
-				x = ldexp (UnsignedToFloat (highMantissa | 0x00100000), exponent - 1043) +
-					ldexp (UnsignedToFloat (lowMantissa), exponent - 1075);
+				x = ldexp ((double) (highMantissa | 0x00100000), exponent - 1043) +
+					ldexp ((double) lowMantissa, exponent - 1075);
 			return bytes [0] & 0x80 ? - x : x;
 		}
 	} catch (MelderError) {
@@ -986,16 +1025,26 @@ double bingetr10 (FILE *f) {
 	try {
 		unsigned char bytes [10];
 		if (fread (bytes, sizeof (unsigned char), 10, f) != 10) readError (f, "ten bytes.");
-		long exponent = ((bytes [0] & 0x7F) << 8) | bytes [1];
-		unsigned long highMantissa = ((unsigned long) bytes [2] << 24) | ((unsigned long) bytes [3] << 16) | ((unsigned long) bytes [4] << 8) | (unsigned long) bytes [5];
-		unsigned long lowMantissa = ((unsigned long) bytes [6] << 24) | ((unsigned long) bytes [7] << 16) | ((unsigned long) bytes [8] << 8) | (unsigned long) bytes [9];
+		int32_t exponent = (int32_t)
+			((uint32_t) ((uint32_t) ((uint32_t) bytes [0] & 0x7F) << 8) |
+			                         (uint32_t) bytes [1]);
+		uint32_t highMantissa =
+			(uint32_t) ((uint32_t) bytes [2] << 24) |
+			(uint32_t) ((uint32_t) bytes [3] << 16) |
+			(uint32_t) ((uint32_t) bytes [4] << 8) |
+			            (uint32_t) bytes [5];
+		uint32_t lowMantissa =
+			(uint32_t) ((uint32_t) bytes [6] << 24) |
+			(uint32_t) ((uint32_t) bytes [7] << 16) |
+			(uint32_t) ((uint32_t) bytes [8] << 8) |
+			            (uint32_t) bytes [9];
 		double x;
 		if (exponent == 0 && highMantissa == 0 && lowMantissa == 0) x = 0;
-		else if (exponent == 0x7FFF) x = HUGE_VAL;   /* Infinity or NaN */
+		else if (exponent == 0x7FFF) x = HUGE_VAL;   // Infinity or NaN
 		else {
 			exponent -= 16383;
-			x = ldexp (UnsignedToFloat (highMantissa), exponent - 31);
-			x += ldexp (UnsignedToFloat (lowMantissa), exponent - 63);
+			x = ldexp ((double) highMantissa, exponent - 31);
+			x += ldexp ((double) lowMantissa, exponent - 63);
 		}
 		return bytes [0] & 0x80 ? - x : x;
 	} catch (MelderError) {
@@ -1030,15 +1079,14 @@ void binputb (FILE *f) {
 	writeBuffer = 0;
 }
 
-void binputi2 (int i, FILE *f) {
+void binputi2 (int16_t i, FILE *f) {
 	try {
-		if (binario_shortBE2 && Melder_debug != 18) {
-			short s = i;
-			if (fwrite (& s, sizeof (short), 1, f) != 1) writeError ("a signed short integer.");
+		if (binario_16bitBE && Melder_debug != 18) {
+			if (fwrite (& i, sizeof (short), 1, f) != 1) writeError ("a signed 16-bit integer.");
 		} else {
 			char bytes [2];
-			bytes [0] = i >> 8;
-			bytes [1] = i;
+			bytes [0] = (char) (i >> 8);   // truncate
+			bytes [1] = (char) (i);   // truncate
 			if (fwrite (bytes, sizeof (char), 2, f) != 2) writeError ("two bytes.");
 		}
 	} catch (MelderError) {
@@ -1046,155 +1094,152 @@ void binputi2 (int i, FILE *f) {
 	}
 }
 
-void binputu2 (unsigned int u, FILE *f) {
+void binputi2LE (int16_t i, FILE *f) {
 	try {
-		if (binario_shortBE2 && Melder_debug != 18) {
-			unsigned short s = u;
-			if (fwrite (& s, sizeof (unsigned short), 1, f) != 1) writeError ("an unsigned short integer.");
+		if (binario_16bitLE && Melder_debug != 18) {
+			if (fwrite (& i, sizeof (short), 1, f) != 1) writeError ("a signed 16-bit integer.");
 		} else {
 			char bytes [2];
-			bytes [0] = u >> 8;
-			bytes [1] = u;
+			bytes [1] = (char) (i >> 8);   // truncate
+			bytes [0] = (char) (i);   // truncate
 			if (fwrite (bytes, sizeof (char), 2, f) != 2) writeError ("two bytes.");
 		}
 	} catch (MelderError) {
-		Melder_throw ("Unsigned integer not written to 2 bytes in binary file.");
+		Melder_throw ("Signed integer not written to 2 bytes in binary file.");
 	}
 }
 
-void binpute2 (int value, FILE *f) {
+void binputu2 (uint16_t u, FILE *f) {
 	try {
-		if (binario_shortBE2 && Melder_debug != 18) {
-			short s = value;
-			if (fwrite (& s, sizeof (short), 1, f) != 1) writeError ("a signed short integer");
+		if (binario_16bitBE && Melder_debug != 18) {
+			if (fwrite (& u, sizeof (uint16_t), 1, f) != 1) writeError ("an unsigned 16-bit integer.");
 		} else {
 			char bytes [2];
-			bytes [0] = value >> 8;
-			bytes [1] = value;
+			bytes [0] = (char) (u >> 8);   // truncate
+			bytes [1] = (char) (u);   // truncate
 			if (fwrite (bytes, sizeof (char), 2, f) != 2) writeError ("two bytes.");
 		}
 	} catch (MelderError) {
-		Melder_throw ("Enumerated value not written to 2 bytes in binary file.");
+		Melder_throw ("Unsigned integer not written to 2 bytes in binary file.");
 	}
 }
 
-void binputi3 (long i, FILE *f) {
+void binputu2LE (uint16_t u, FILE *f) {
 	try {
-		char bytes [3];
-		bytes [0] = i >> 16;
-		bytes [1] = i >> 8;
-		bytes [2] = i;
-		if (fwrite (bytes, sizeof (char), 3, f) != 3) writeError ("three bytes");
+		if (binario_16bitLE && Melder_debug != 18) {
+			if (fwrite (& u, sizeof (uint16_t), 1, f) != 1) writeError ("an unsigned 16-bit integer.");
+		} else {
+			char bytes [2];
+			bytes [1] = (char) (u >> 8);   // truncate
+			bytes [0] = (char) (u);   // truncate
+			if (fwrite (bytes, sizeof (char), 2, f) != 2) writeError ("two bytes.");
+		}
 	} catch (MelderError) {
-		Melder_throw ("Signed integer not written to 3 bytes in binary file.");
+		Melder_throw ("Unsigned integer not written to 2 bytes in binary file.");
 	}
 }
 
-void binputi4 (long i, FILE *f) {
+void binpute2 (int value, FILE *f) {
 	try {
-		if (binario_longBE4 && Melder_debug != 18) {
-			if (fwrite (& i, sizeof (long), 1, f) != 1) writeError ("a signed long integer.");
+		if (binario_16bitBE && Melder_debug != 18) {
+			short s = value;
+			if (fwrite (& s, sizeof (short), 1, f) != 1) writeError ("a signed 16-bit integer");
 		} else {
-			char bytes [4];
-			bytes [0] = i >> 24;
-			bytes [1] = i >> 16;
-			bytes [2] = i >> 8;
-			bytes [3] = i;
-			if (fwrite (bytes, sizeof (char), 4, f) != 4) writeError ("four bytes.");
+			char bytes [2];
+			bytes [0] = (char) (value >> 8);   // truncate
+			bytes [1] = (char) (value);   // truncate
+			if (fwrite (bytes, sizeof (char), 2, f) != 2) writeError ("two bytes.");
 		}
 	} catch (MelderError) {
-		Melder_throw ("Signed integer not written to 4 bytes in binary file.");
+		Melder_throw ("Enumerated value not written to 2 bytes in binary file.");
 	}
 }
 
-void binputu4 (unsigned long u, FILE *f) {
+void binputi3 (int32_t i, FILE *f) {
 	try {
-		if (binario_longBE4 && Melder_debug != 18) {
-			if (fwrite (& u, sizeof (unsigned long), 1, f) != 1) writeError ("an unsigned long integer.");
-		} else {
-			char bytes [4];
-			bytes [0] = u >> 24;
-			bytes [1] = u >> 16;
-			bytes [2] = u >> 8;
-			bytes [3] = u;
-			if (fwrite (bytes, sizeof (char), 4, f) != 4) writeError ("four bytes.");
-		}
+		char bytes [3];
+		bytes [0] = (char) (i >> 16);   // truncate
+		bytes [1] = (char) (i >> 8);   // truncate
+		bytes [2] = (char) (i);   // truncate
+		if (fwrite (bytes, sizeof (char), 3, f) != 3) writeError ("three bytes");
 	} catch (MelderError) {
-		Melder_throw ("Unsigned integer not written to 4 bytes in binary file.");
+		Melder_throw ("Signed integer not written to 3 bytes in binary file.");
 	}
 }
 
-void binputi2LE (int i, FILE *f) {
+void binputi3LE (int32_t i, FILE *f) {
 	try {
-		if (binario_shortLE2 && Melder_debug != 18) {
-			short s = i;
-			if (fwrite (& s, sizeof (short), 1, f) != 1) writeError ("a signed short integer.");
-		} else {
-			char bytes [2];
-			bytes [1] = i >> 8;
-			bytes [0] = i;
-			if (fwrite (bytes, sizeof (char), 2, f) != 2) writeError ("two bytes.");
-		}
+		char bytes [3];
+		bytes [2] = (char) (i >> 16);   // truncate
+		bytes [1] = (char) (i >> 8);   // truncate
+		bytes [0] = (char) (i);   // truncate
+		if (fwrite (bytes, sizeof (char), 3, f) != 3) writeError ("three bytes");
 	} catch (MelderError) {
-		Melder_throw ("Signed integer not written to 2 bytes in binary file.");
+		Melder_throw ("Signed integer not written to 3 bytes in binary file.");
 	}
 }
 
-void binputu2LE (unsigned int u, FILE *f) {
+void binputi4 (int32_t i, FILE *f) {
 	try {
-		if (binario_shortLE2 && Melder_debug != 18) {
-			unsigned short s = u;
-			if (fwrite (& s, sizeof (unsigned short), 1, f) != 1) writeError ("an unsigned short integer.");
+		if (binario_32bitBE && Melder_debug != 18) {
+			if (fwrite (& i, sizeof (int32_t), 1, f) != 1) writeError ("a signed 32-bit integer.");
 		} else {
-			char bytes [2];
-			bytes [1] = u >> 8;
-			bytes [0] = u;
-			if (fwrite (bytes, sizeof (char), 2, f) != 2) writeError ("two bytes.");
+			char bytes [4];
+			bytes [0] = (char) (i >> 24);   // truncate
+			bytes [1] = (char) (i >> 16);   // truncate
+			bytes [2] = (char) (i >> 8);   // truncate
+			bytes [3] = (char) (i);   // truncate
+			if (fwrite (bytes, sizeof (char), 4, f) != 4) writeError ("four bytes.");
 		}
 	} catch (MelderError) {
-		Melder_throw ("Unsigned integer not written to 2 bytes in binary file.");
+		Melder_throw ("Signed integer not written to 4 bytes in binary file.");
 	}
 }
 
-void binputi3LE (long i, FILE *f) {
+void binputi4LE (int32_t i, FILE *f) {
 	try {
-		char bytes [3];
-		bytes [2] = i >> 16;
-		bytes [1] = i >> 8;
-		bytes [0] = i;
-		if (fwrite (bytes, sizeof (char), 3, f) != 3) writeError ("three bytes");
+		if (binario_32bitLE && Melder_debug != 18) {
+			if (fwrite (& i, sizeof (int32_t), 1, f) != 1) writeError ("a signed 32-bit integer.");
+		} else {
+			char bytes [4];
+			bytes [3] = (char) (i >> 24);   // truncate
+			bytes [2] = (char) (i >> 16);   // truncate
+			bytes [1] = (char) (i >> 8);   // truncate
+			bytes [0] = (char) (i);   // truncate
+			if (fwrite (bytes, sizeof (char), 4, f) != 4) writeError ("four bytes.");
+		}
 	} catch (MelderError) {
-		Melder_throw ("Signed integer not written to 3 bytes in binary file.");
+		Melder_throw ("Signed integer not written to 4 bytes in binary file.");
 	}
 }
 
-void binputi4LE (long i, FILE *f) {
+void binputu4 (uint32_t u, FILE *f) {
 	try {
-		if (binario_longLE4 && Melder_debug != 18) {
-			if (fwrite (& i, sizeof (long), 1, f) != 1) writeError ("a signed long integer.");
+		if (binario_32bitBE && Melder_debug != 18) {
+			if (fwrite (& u, sizeof (uint32_t), 1, f) != 1) writeError ("an unsigned 32-bit integer.");
 		} else {
 			char bytes [4];
-			bytes [3] = i >> 24;
-			bytes [2] = i >> 16;
-			bytes [1] = i >> 8;
-			bytes [0] = i;
+			bytes [0] = (char) (u >> 24);   // truncate
+			bytes [1] = (char) (u >> 16);   // truncate
+			bytes [2] = (char) (u >> 8);   // truncate
+			bytes [3] = (char) (u);   // truncate
 			if (fwrite (bytes, sizeof (char), 4, f) != 4) writeError ("four bytes.");
 		}
 	} catch (MelderError) {
-		Melder_throw ("Signed integer not written to 4 bytes in binary file.");
+		Melder_throw ("Unsigned integer not written to 4 bytes in binary file.");
 	}
 }
 
-void binputu4LE (unsigned long u, FILE *f) {
+void binputu4LE (uint32_t u, FILE *f) {
 	try {
-		if (binario_longLE4 && Melder_debug != 18) {
-			if (fwrite (& u, sizeof (unsigned long), 1, f) != 1) writeError ("an unsigned long integer.");
+		if (binario_32bitLE && Melder_debug != 18) {
+			if (fwrite (& u, sizeof (uint32_t), 1, f) != 1) writeError ("an unsigned 32-bit integer.");
 		} else {
 			char bytes [4];
-			bytes [3] = u >> 24;
-			bytes [2] = u >> 16;
-			bytes [1] = u >> 8;
-			bytes [0] = u;
+			bytes [3] = (char) (u >> 24);   // truncate
+			bytes [2] = (char) (u >> 16);  // truncate
+			bytes [1] = (char) (u >> 8);  // truncate
+			bytes [0] = (char) (u);  // truncate
 			if (fwrite (bytes, sizeof (char), 4, f) != 4) writeError ("four bytes.");
 		}
 	} catch (MelderError) {
@@ -1205,13 +1250,13 @@ void binputu4LE (unsigned long u, FILE *f) {
 void binputr4 (double x, FILE *f) {
 	try {
 		if (binario_floatIEEE4msb && Melder_debug != 18) {
-			float x4 = x;
-			if (fwrite (& x4, sizeof (float), 1, f) != 1) writeError ("a single-precision floating-point number.");
+			float x4 = (float) x;   // convert down, with loss of precision
+			if (fwrite (& x4, sizeof (float), 1, f) != 1) writeError ("a 32-bit floating-point number.");
 		} else {
 			unsigned char bytes [4];
 			int sign, exponent;
 			double fMantissa, fsMantissa;
-			unsigned long mantissa;
+			uint32_t mantissa;
 			if (x < 0.0) { sign = 0x0100; x *= -1; }
 			else sign = 0;
 			if (x == 0.0) { exponent = 0; mantissa = 0; }
@@ -1219,7 +1264,7 @@ void binputr4 (double x, FILE *f) {
 				fMantissa = frexp (x, & exponent);
 				if ((exponent > 128) || ! (fMantissa < 1))   // Infinity or Not-a-Number
 					{ exponent = sign | 0x00FF; mantissa = 0; }   // Infinity
-				else {   /* Finite. */
+				else {   // finite
 					exponent += 126;   // add bias
 					if (exponent <= 0) {   // denormalized
 						fMantissa = ldexp (fMantissa, exponent - 1);
@@ -1228,10 +1273,10 @@ void binputr4 (double x, FILE *f) {
 					exponent |= sign;
 					fMantissa = ldexp (fMantissa, 24);          
 					fsMantissa = floor (fMantissa); 
-					mantissa = FloatToUnsigned (fsMantissa) & 0x007FFFFF;
+					mantissa = (uint32_t) fsMantissa & 0x007FFFFF;
 				}
 			}
-			bytes [0] = exponent >> 1;
+			bytes [0] = (uint8_t) (exponent >> 1);   // truncate: bits 2 through 9 (bit 9 is the sign bit)
 			bytes [1] = (exponent << 7) | (mantissa >> 16);
 			bytes [2] = mantissa >> 8;
 			bytes [3] = mantissa;
@@ -1245,13 +1290,13 @@ void binputr4 (double x, FILE *f) {
 void binputr4LE (double x, FILE *f) {
 	try {
 		if (binario_floatIEEE4lsb && Melder_debug != 18) {
-			float x4 = x;
-			if (fwrite (& x4, sizeof (float), 1, f) != 1) writeError ("a single-precision floating-point number.");
+			float x4 = (float) x;   // convert down, with loss of precision
+			if (fwrite (& x4, sizeof (float), 1, f) != 1) writeError ("a 32-bit floating-point number.");
 		} else {
 			unsigned char bytes [4];
 			int sign, exponent;
 			double fMantissa, fsMantissa;
-			unsigned long mantissa;
+			uint32_t mantissa;
 			if (x < 0.0) { sign = 0x0100; x *= -1; }
 			else sign = 0;
 			if (x == 0.0) { exponent = 0; mantissa = 0; }
@@ -1268,7 +1313,7 @@ void binputr4LE (double x, FILE *f) {
 					exponent |= sign;
 					fMantissa = ldexp (fMantissa, 24);          
 					fsMantissa = floor (fMantissa); 
-					mantissa = FloatToUnsigned (fsMantissa) & 0x007FFFFF;
+					mantissa = (uint32_t) fsMantissa & 0x007FFFFF;
 				}
 			}
 			bytes [3] = exponent >> 1;
@@ -1285,12 +1330,12 @@ void binputr4LE (double x, FILE *f) {
 void binputr8 (double x, FILE *f) {
 	try {
 		if (binario_doubleIEEE8msb && Melder_debug != 18) {
-			if (fwrite (& x, sizeof (double), 1, f) != 1) writeError ("a double-precision floating-point number.");
+			if (fwrite (& x, sizeof (double), 1, f) != 1) writeError ("a 64-bit floating-point number.");
 		} else {
 			unsigned char bytes [8];
 			int sign, exponent;
 			double fMantissa, fsMantissa;
-			unsigned long highMantissa, lowMantissa;
+			uint32_t highMantissa, lowMantissa;
 			if (x < 0.0) { sign = 0x0800; x *= -1; }
 			else sign = 0;
 			if (x == 0.0) { exponent = 0; highMantissa = 0; lowMantissa = 0; }
@@ -1307,10 +1352,10 @@ void binputr8 (double x, FILE *f) {
 					exponent |= sign;
 					fMantissa = ldexp (fMantissa, 21);          
 					fsMantissa = floor (fMantissa); 
-					highMantissa = FloatToUnsigned (fsMantissa) & 0x000FFFFF;
+					highMantissa = (uint32_t) fsMantissa & 0x000FFFFF;
 					fMantissa = ldexp (fMantissa - fsMantissa, 32); 
 					fsMantissa = floor (fMantissa); 
-					lowMantissa = FloatToUnsigned (fsMantissa);
+					lowMantissa = (uint32_t) fsMantissa;
 				}
 			}
 			bytes [0] = exponent >> 4;
@@ -1331,9 +1376,10 @@ void binputr8 (double x, FILE *f) {
 void binputr10 (double x, FILE *f) {
 	try {
 		unsigned char bytes [10];
-		int sign, exponent;
+		Melder_assert (sizeof (int) > 2);
+		int sign, exponent;   // these should be uint16_t, but frexp() expects an int
 		double fMantissa, fsMantissa;
-		unsigned long highMantissa, lowMantissa;
+		uint32_t highMantissa, lowMantissa;
 		if (x < 0.0) { sign = 0x8000; x *= -1; }
 		else sign = 0;
 		if (x == 0.0) { exponent = 0; highMantissa = 0; lowMantissa = 0; }
@@ -1341,19 +1387,19 @@ void binputr10 (double x, FILE *f) {
 			fMantissa = frexp (x, & exponent);
 			if ((exponent > 16384) || ! (fMantissa < 1))   // Infinity or Not-a-Number
 				{ exponent = sign | 0x7FFF; highMantissa = 0; lowMantissa = 0; }   // Infinity
-			else {   /* Finite */
-				exponent += 16382;   /* Add bias. */
-				if (exponent < 0) {   /* Denormalized. */
+			else {   // finite
+				exponent += 16382;   // add bias
+				if (exponent < 0) {   // denormalized
 					fMantissa = ldexp (fMantissa, exponent);
 					exponent = 0;
 				}
 				exponent |= sign;
 				fMantissa = ldexp (fMantissa, 32);          
 				fsMantissa = floor (fMantissa); 
-				highMantissa = FloatToUnsigned (fsMantissa);
+				highMantissa = (uint32_t) fsMantissa;
 				fMantissa = ldexp (fMantissa - fsMantissa, 32); 
 				fsMantissa = floor (fMantissa); 
-				lowMantissa = FloatToUnsigned (fsMantissa);
+				lowMantissa = (uint32_t) fsMantissa;
 			}
 		}
 		bytes [0] = exponent >> 8;
@@ -1444,8 +1490,8 @@ char * bingets2 (FILE *f) {
 
 char * bingets4 (FILE *f) {
 	try {
-		unsigned long length = bingetu4 (f);
-		autostring8 result = Melder_malloc (char, length + 1);
+		uint32_t length = bingetu4 (f);
+		autostring8 result = Melder_malloc (char, (int64_t) length + 1);
 		if (fread (result.peek(), sizeof (char), length, f) != length)
 			Melder_throw (feof (f) ? "Reached end of file" : "Error in file", " while trying to read ", length, " one-byte characters.");
 		result [length] = 0;   // trailing null byte
@@ -1464,7 +1510,7 @@ wchar_t * bingetw1 (FILE *f) {
 			 * UTF-16
 			 */
 			length = bingetu1 (f);
-			result.reset (Melder_malloc (wchar_t, length + 1));
+			result.reset (Melder_malloc (wchar_t, (int64_t) length + 1));
 			for (unsigned short i = 0; i < length; i ++) {
 				if (sizeof (wchar_t) == 2) {
 					result [i] = (wchar_t) bingetu2 (f);   // add sign
@@ -1486,7 +1532,7 @@ wchar_t * bingetw1 (FILE *f) {
 			/*
 			 * ASCII
 			 */
-			result.reset (Melder_malloc (wchar_t, length + 1));
+			result.reset (Melder_malloc (wchar_t, (int64_t) length + 1));
 			for (unsigned short i = 0; i < length; i ++) {
 				result [i] = bingetu1 (f);
 			}
@@ -1507,8 +1553,8 @@ wchar_t * bingetw2 (FILE *f) {
 			 * UTF-16
 			 */
 			length = bingetu2 (f);
-			result.reset (Melder_malloc (wchar_t, length + 1));
-			for (unsigned short i = 0; i < length; i ++) {
+			result.reset (Melder_malloc (wchar_t, (int64_t) length + 1));
+			for (uint16_t i = 0; i < length; i ++) {
 				if (sizeof (wchar_t) == 2) {
 					result [i] = (wchar_t) bingetu2 (f);
 				} else {
@@ -1544,14 +1590,14 @@ wchar_t * bingetw2 (FILE *f) {
 wchar_t * bingetw4 (FILE *f) {
 	try {
 		autostring result = NULL;
-		unsigned long length = bingetu4 (f);
+		uint32_t length = bingetu4 (f);
 		if (length == 0xFFFFFFFF) {   // an escape for encoding
 			/*
 			 * UTF-16
 			 */
 			length = bingetu4 (f);
-			result.reset (Melder_malloc (wchar_t, length + 1));
-			for (unsigned long i = 0; i < length; i ++) {
+			result.reset (Melder_malloc (wchar_t, (int64_t) length + 1));
+			for (uint32_t i = 0; i < length; i ++) {
 				if (sizeof (wchar_t) == 2) {
 					result [i] = (wchar_t) bingetu2 (f);
 				} else {
@@ -1572,8 +1618,8 @@ wchar_t * bingetw4 (FILE *f) {
 			/*
 			 * ASCII
 			 */
-			result.reset (Melder_malloc (wchar_t, length + 1));
-			for (unsigned long i = 0; i < length; i ++) {
+			result.reset (Melder_malloc (wchar_t, (int64_t) length + 1));
+			for (uint32_t i = 0; i < length; i ++) {
 				result [i] = bingetu1 (f);
 			}
 		}
@@ -1589,10 +1635,10 @@ void binputs1 (const char *s, FILE *f) {
 		if (s == NULL) {
 			binputu1 (0, f);
 		} else {
-			unsigned long length = strlen (s);
-			if (length > 255) {
+			size_t length = strlen (s);
+			if (length > UINT8_MAX) {
 				Melder_warning ("Text of ", length, " characters truncated to 255 characters.");
-				length = 255;
+				length = UINT8_MAX;
 			}
 			binputu1 (length, f);
 			if (fwrite (s, sizeof (char), length, f) != length)
@@ -1608,12 +1654,12 @@ void binputs2 (const char *s, FILE *f) {
 		if (s == NULL) {
 			binputu2 (0, f);
 		} else {
-			unsigned long length = strlen (s);
-			if (length > 65535) {
+			size_t length = strlen (s);
+			if (length > UINT16_MAX) {
 				Melder_warning ("Text of ", length, " characters truncated to 65535 characters.");
-				length = 65535;
+				length = UINT16_MAX;
 			}
-			binputu2 (length, f);
+			binputu2 ((uint16_t) length, f);   // safe conversion down
 			if (fwrite (s, sizeof (char), length, f) != length)
 				Melder_throw ("Error in file while trying to write ", length, " one-byte characters.");
 		}
@@ -1627,7 +1673,11 @@ void binputs4 (const char *s, FILE *f) {
 		if (s == NULL) {
 			binputu4 (0, f);
 		} else {
-			unsigned long length = strlen (s);
+			size_t length = strlen (s);
+			if (length > UINT32_MAX) {
+				Melder_warning ("Text of ", length, " characters truncated to 4,294,967,295 characters.");
+				length = UINT32_MAX;
+			}
 			binputu4 (length, f);
 			if (fwrite (s, sizeof (char), length, f) != length)
 				Melder_throw ("Error in file while trying to write ", length, " one-byte characters.");
@@ -1638,16 +1688,16 @@ void binputs4 (const char *s, FILE *f) {
 }
 
 static inline void binpututf16 (wchar_t character, FILE *f) {
-	if (sizeof (wchar_t) == 2) {   // wchar_t is UTF-16?
-		binputu2 (character, f);
-	} else {   // wchar_t is UTF-32.
-		utf32_t kar = character;
-		if (kar <= 0xFFFF) {
-			binputu2 (character, f);
-		} else if (kar <= 0x10FFFF) {
+	if (sizeof (wchar_t) == 2) {   // wchar_t is (signed) UTF-16?
+		binputu2 ((uint16_t) character, f);   // convert sign
+	} else {   // wchar_t is (signed) UTF-32.
+		char32_t kar = (char32_t) character;   // safe, because sign bit is always zero
+		if (kar <= 0x0000FFFF) {
+			binputu2 ((uint16_t) character, f);   // truncate to lower 16 bits
+		} else if (kar <= 0x0010FFFF) {
 			kar -= 0x10000;
-			binputu2 (0xD800 | (kar >> 10), f);
-			binputu2 (0xDC00 | (kar & 0x3FF), f);
+			binputu2 ((uint16_t) (0x0000D800 | (kar >> 10)), f);
+			binputu2 ((uint16_t) (0xDC00 | (kar & 0x3FF)), f);
 		} else {
 			Melder_fatal ("Impossible Unicode value.");
 		}
@@ -1659,18 +1709,18 @@ void binputw1 (const wchar_t *s, FILE *f) {
 		if (s == NULL) {
 			binputu1 (0, f);
 		} else {
-			unsigned long length = wcslen (s);
-			if (length > 254) {
+			size_t length = wcslen (s);
+			if (length > UINT8_MAX - 1) {
 				Melder_warning ("Text of ", length, " characters truncated to 254 characters.");
-				length = 254;
+				length = UINT8_MAX - 1;
 			}
 			if (Melder_isValidAscii (s)) {
 				/*
 				 * ASCII
 				 */
 				binputu1 (length, f);
-				for (unsigned long i = 0; i < length; i ++) {
-					binputu1 (s [i], f);
+				for (size_t i = 0; i < length; i ++) {
+					binputu1 ((unsigned int) (char) s [i], f);
 				}
 			} else {
 				/*
@@ -1678,7 +1728,7 @@ void binputw1 (const wchar_t *s, FILE *f) {
 				 */
 				binputu1 (0xFF, f);   // an escape for multibyte encoding
 				binputu1 (length, f);
-				for (unsigned long i = 0; i < length; i ++) {
+				for (size_t i = 0; i < length; i ++) {
 					binpututf16 (s [i], f);
 				}
 			}
@@ -1693,26 +1743,26 @@ void binputw2 (const wchar_t *s, FILE *f) {
 		if (s == NULL) {
 			binputu2 (0, f);
 		} else {
-			unsigned long length = wcslen (s);
-			if (length > 65534) {
+			size_t length = wcslen (s);
+			if (length > UINT16_MAX - 1) {
 				Melder_warning ("Text of ", length, " characters truncated to 65534 characters.");
-				length = 65534;
+				length = UINT16_MAX - 1;
 			}
 			if (Melder_isValidAscii (s)) {
 				/*
 				 * ASCII
 				 */
-				binputu2 (length, f);
-				for (unsigned long i = 0; i < length; i ++) {
-					binputu1 (s [i], f);
+				binputu2 ((uint16_t) length, f);
+				for (size_t i = 0; i < length; i ++) {
+					binputu1 ((unsigned int) (char) s [i], f);
 				}
 			} else {
 				/*
 				 * UTF-16
 				 */
 				binputu2 (0xFFFF, f);   // an escape for multibyte encoding
-				binputu2 (length, f);
-				for (unsigned long i = 0; i < length; i ++) {
+				binputu2 ((uint16_t) length, f);
+				for (size_t i = 0; i < length; i ++) {
 					binpututf16 (s [i], f);
 				}
 			}
@@ -1727,14 +1777,18 @@ void binputw4 (const wchar_t *s, FILE *f) {
 		if (s == NULL) {
 			binputu4 (0, f);
 		} else {
-			unsigned long length = wcslen (s);
+			size_t length = wcslen (s);
+			if (length > UINT32_MAX - 1) {
+				Melder_warning ("Text of ", length, " characters truncated to 4,294,967,294 characters.");
+				length = UINT32_MAX - 1;
+			}
 			if (Melder_isValidAscii (s)) {
 				/*
 				 * ASCII
 				 */
 				binputu4 (length, f);
-				for (unsigned long i = 0; i < length; i ++) {
-					binputu1 (s [i], f);
+				for (size_t i = 0; i < length; i ++) {
+					binputu1 ((unsigned int) (char) s [i], f);
 				}
 			} else {
 				/*
@@ -1742,7 +1796,7 @@ void binputw4 (const wchar_t *s, FILE *f) {
 				 */
 				binputu4 (0xFFFFFFFF, f);   // an escape for multibyte encoding
 				binputu4 (length, f);
-				for (unsigned long i = 0; i < length; i ++) {
+				for (size_t i = 0; i < length; i ++) {
 					binpututf16 (s [i], f);
 				}
 			}
@@ -1859,7 +1913,7 @@ macro_cacgetb (7)
 void cacgetb (CACHE *f) { (void) f; bitsInReadBuffer = 0; }
 
 int cacgeti2 (CACHE *f) {
-	if (binario_shortBE2) {
+	if (binario_16bitBE) {
 		short s;
 		START (s) READ READ
 		return s;   /* With sign extension if an int is 4 bytes. */
@@ -1871,7 +1925,7 @@ int cacgeti2 (CACHE *f) {
 }
 
 unsigned int cacgetu2 (CACHE *f) {
-	if (binario_shortBE2) {
+	if (binario_16bitBE) {
 		unsigned short s;
 		START (s) READ READ
 		return s;   /* Without sign extension. */
@@ -1884,7 +1938,7 @@ unsigned int cacgetu2 (CACHE *f) {
 
 int cacgete2 (CACHE *f, const wchar_t *type) {
 	signed short s;
-	if (binario_shortBE2) {
+	if (binario_16bitBE) {
 		START (s) READ READ
 	} else {
 		unsigned char bytes [2];
@@ -1897,7 +1951,7 @@ int cacgete2 (CACHE *f, const wchar_t *type) {
 }
 
 long cacgeti4 (CACHE *f) {
-	if (binario_longBE4) {
+	if (binario_32bitBE) {
 		long l;
 		START (l) READ READ READ READ
 		return l;
@@ -1913,7 +1967,7 @@ long cacgeti4 (CACHE *f) {
 }
 
 unsigned long cacgetu4 (CACHE *f) {
-	if (binario_longBE4) {
+	if (binario_32bitBE) {
 		unsigned long l;
 		START (l) READ READ READ READ
 		return l;
@@ -2054,7 +2108,7 @@ void cacputb (CACHE *f) {
 }
 
 void cacputi2 (int i, CACHE *f) {
-	if (binario_shortBE2) {
+	if (binario_16bitBE) {
 		short s = i;
 		START (s) WRITE WRITE
 	} else {
@@ -2066,7 +2120,7 @@ void cacputi2 (int i, CACHE *f) {
 }
 
 void cacputu2 (unsigned int u, CACHE *f) {
-	if (binario_shortBE2) {
+	if (binario_16bitBE) {
 		unsigned short s = u;
 		START (s) WRITE WRITE
 	} else {
@@ -2078,7 +2132,7 @@ void cacputu2 (unsigned int u, CACHE *f) {
 }
 
 void cacpute2 (int value, CACHE *f) {
-	if (binario_shortBE2) {
+	if (binario_16bitBE) {
 		signed short s = value;
 		START (s) WRITE WRITE
 	} else {
@@ -2090,7 +2144,7 @@ void cacpute2 (int value, CACHE *f) {
 }
 
 void cacputi4 (long i, CACHE *f) {
-	if (binario_longBE4) {
+	if (binario_32bitBE) {
 		START (i) WRITE WRITE WRITE WRITE
 	} else {
 		char bytes [4];
@@ -2103,7 +2157,7 @@ void cacputi4 (long i, CACHE *f) {
 }
 
 void cacputu4 (unsigned long u, CACHE *f) {
-	if (binario_longBE4) {
+	if (binario_32bitBE) {
 		START (u) WRITE WRITE WRITE WRITE
 	} else {
 		char bytes [4];
diff --git a/sys/abcio.h b/sys/abcio.h
index c303810..c582a6d 100644
--- a/sys/abcio.h
+++ b/sys/abcio.h
@@ -28,7 +28,8 @@
 
 int texgeti1 (MelderReadText text);
 int texgeti2 (MelderReadText text);
-long texgeti4 (MelderReadText text);
+long texgeti32 (MelderReadText text);
+#define texgeti4 texgeti32
 unsigned int texgetu1 (MelderReadText text);
 unsigned int texgetu2 (MelderReadText text);
 unsigned long texgetu4 (MelderReadText text);
@@ -54,7 +55,8 @@ void texputintro (MelderFile file, const wchar_t *s1, const wchar_t *s2, const w
 
 void texputi1 (MelderFile file, int i, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3, const wchar_t *s4, const wchar_t *s5, const wchar_t *s6);
 void texputi2 (MelderFile file, int i, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3, const wchar_t *s4, const wchar_t *s5, const wchar_t *s6);
-void texputi4 (MelderFile file, long i, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3, const wchar_t *s4, const wchar_t *s5, const wchar_t *s6);
+void texputi32 (MelderFile file, long i, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3, const wchar_t *s4, const wchar_t *s5, const wchar_t *s6);
+#define texputi4 texputi32
 void texputu1 (MelderFile file, unsigned int u, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3, const wchar_t *s4, const wchar_t *s5, const wchar_t *s6);
 void texputu2 (MelderFile file, unsigned int u, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3, const wchar_t *s4, const wchar_t *s5, const wchar_t *s6);
 void texputu4 (MelderFile file, unsigned long u, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3, const wchar_t *s4, const wchar_t *s5, const wchar_t *s6);
@@ -81,24 +83,26 @@ void texputw4 (MelderFile file, const wchar_t *s, const wchar_t *s1, const wchar
 		int fgetc (FILE *f);   int fputc (int c, FILE *f);   // 0..255
 */
 unsigned int bingetu1 (FILE *f);   void binputu1 (unsigned int i, FILE *f);   /* 0..255 */
-uint16_t bingetu2 (FILE *f);   void binputu2 (unsigned int i, FILE *f);   /* 0..65535 */
-unsigned long bingetu4 (FILE *f);   void binputu4 (unsigned long i, FILE *f);   /* 0..4294967295 */
+uint16_t bingetu2 (FILE *f);   void binputu2 (uint16_t i, FILE *f);   /* 0..65535 */
+uint32_t bingetu4 (FILE *f);   void binputu4 (uint32_t i, FILE *f);   /* 0..4294967295 */
 
 int bingeti1 (FILE *f);   void binputi1 (int i, FILE *f);   /* -128..127 */
-int bingeti2 (FILE *f);   void binputi2 (int i, FILE *f);   /* -32768..32767 */
-long bingeti3 (FILE *f);   void binputi3 (long i, FILE *f);   /* -8388608..2148388607 */
-long bingeti4 (FILE *f);   void binputi4 (long i, FILE *f);   /* -2147483648..2147483647 */
+int16_t bingeti2 (FILE *f);   void binputi2 (int16_t i, FILE *f);   /* -32768..32767 */
+int32_t bingeti3 (FILE *f);   void binputi3 (int32_t i, FILE *f);   /* -8388608..2148388607 */
+int32_t bingeti32 (FILE *f);   void binputi32 (int32_t i, FILE *f);   /* -2147483648..2147483647 */
+#define bingeti4 bingeti32
+#define binputi4 binputi32
 /*
 	Read or write signed or unsigned integers from or to 2 or 4 bytes in the stream 'f',
 	in big-endian byte order (most significant byte first).
 	This is the native integer format on Macintosh and Silicon Graphics Iris.
 */
 
-int bingeti2LE (FILE *f);   void binputi2LE (int i, FILE *f);   /* -32768..32767 */
-long bingeti3LE (FILE *f);   void binputi3LE (long i, FILE *f);   /* -8388608..2148388607 */
-long bingeti4LE (FILE *f);   void binputi4LE (long i, FILE *f);   /* -2147483648..2147483647 */
-uint16_t bingetu2LE (FILE *f);   void binputu2LE (unsigned int i, FILE *f);   /* 0..65535 */
-unsigned long bingetu4LE (FILE *f);   void binputu4LE (unsigned long i, FILE *f);   /* 0..4294967295 */
+int16_t bingeti2LE (FILE *f);   void binputi2LE (int16_t i, FILE *f);   /* -32768..32767 */
+int32_t bingeti3LE (FILE *f);   void binputi3LE (int32_t i, FILE *f);   /* -8388608..2148388607 */
+int32_t bingeti4LE (FILE *f);   void binputi4LE (int32_t i, FILE *f);   /* -2147483648..2147483647 */
+uint16_t bingetu2LE (FILE *f);   void binputu2LE (uint16_t i, FILE *f);   /* 0..65535 */
+uint32_t bingetu4LE (FILE *f);   void binputu4LE (uint32_t i, FILE *f);   /* 0..4294967295 */
 /*
 	Read or write signed or unsigned integers from or to 2 or 4 bytes in the stream 'f',
 	in little-endian byte order (least significant byte first).
diff --git a/sys/melder.cpp b/sys/melder.cpp
index 8e9c8e1..c69f1a6 100644
--- a/sys/melder.cpp
+++ b/sys/melder.cpp
@@ -817,7 +817,7 @@ static void mac_message (NSAlertStyle macAlertType, const wchar_t *messageW) {
 	int messageLength = wcslen (messageW);
 	int j = 0;
 	for (int i = 0; i < messageLength && j <= 4000 - 3; i ++) {
-		utf32_t kar = messageW [i];
+		char32_t kar = (char32_t) messageW [i];   // change sign
 		if (kar <= 0xFFFF) {
 			messageU [j ++] = kar;
 		} else if (kar <= 0x10FFFF) {
diff --git a/sys/melder.h b/sys/melder.h
index af3262f..6b38f50 100644
--- a/sys/melder.h
+++ b/sys/melder.h
@@ -2,7 +2,7 @@
 #define _melder_h_
 /* melder.h
  *
- * Copyright (C) 1992-2012,2013,2014 Paul Boersma
+ * Copyright (C) 1992-2012,2013,2014,2015 Paul Boersma
  *
  * 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
@@ -37,6 +37,7 @@
 	#undef swprintf
 	#define swprintf  _snwprintf
 	//#define swprintf  __mingw_snwprintf
+	#include <sys/types.h>   // for off_t
 #endif
 #include <stdbool.h>
 /*
@@ -45,11 +46,23 @@
 #define __STDC_LIMIT_MACROS
 #define __STDC_CONSTANT_MACROS
 #include <stdint.h>
+#ifndef INT54_MAX
+	#define INT54_MAX   9007199254740991LL
+	#define INT54_MIN  -9007199254740991LL
+#endif
 
 typedef wchar_t wchar;
-typedef uint8_t  utf8_t;
-typedef uint16_t utf16_t;
-typedef uint32_t utf32_t;
+typedef uint8_t  char8_t;
+typedef char32_t char32;
+typedef char16_t char16;
+typedef char8_t char8;
+typedef int8_t int8;
+typedef int16_t int16;
+typedef int32_t int32;
+typedef int64_t int64;
+typedef uint8_t uint8;
+typedef uint16_t uint16;
+typedef uint32_t uint32;
 
 bool Melder_wcsequ_firstCharacterCaseInsensitive (const wchar_t *string1, const wchar_t *string2);
 
@@ -66,24 +79,203 @@ bool Melder_wcsequ_firstCharacterCaseInsensitive (const wchar_t *string1, const
 #ifndef NULL
 	#define NULL  ((void *) 0)
 #endif
-#ifndef INT32_MAX
-	#define INT8_MAX         127
-	#define INT16_MAX        32767
-	#define INT32_MAX        2147483647
-	#define INT64_MAX        9223372036854775807LL
-
-	#define INT8_MIN          -128
-	#define INT16_MIN         -32768
-	#define INT32_MIN        (-INT32_MAX-1)
-	#define INT64_MIN        (-INT64_MAX-1)
-
-	#define UINT8_MAX         255
-	#define UINT16_MAX        65535
-	#define UINT32_MAX        4294967295U
-	#define UINT64_MAX        18446744073709551615ULL
+
+/********** FILES **********/
+
+#if defined (_WIN32)
+	#define Melder_DIRECTORY_SEPARATOR  '\\'
+#else
+	#define Melder_DIRECTORY_SEPARATOR  '/'
+#endif
+
+struct FLAC__StreamDecoder;
+struct FLAC__StreamEncoder;
+
+#define kMelder_MAXPATH 1023   /* excluding the null byte */
+
+struct structMelderFile {
+	FILE *filePointer;
+	wchar_t path [kMelder_MAXPATH+1];
+	bool openForReading, openForWriting, verbose, requiresCRLF;
+	unsigned long outputEncoding;
+	int indent;
+	struct FLAC__StreamEncoder *flacEncoder;
+};
+typedef struct structMelderFile *MelderFile;
+
+struct structMelderDir {
+	wchar_t path [kMelder_MAXPATH+1];
+};
+typedef struct structMelderDir *MelderDir;
+
+#if defined (macintosh) && useCarbon
+	void Melder_machToFile (void *void_fsref, MelderFile file);
+#endif
+
+const wchar_t * MelderFile_name (MelderFile file);
+wchar_t * MelderDir_name (MelderDir dir);
+void Melder_pathToDir (const wchar_t *path, MelderDir dir);
+void Melder_pathToFile (const wchar_t *path, MelderFile file);
+void Melder_relativePathToFile (const wchar_t *path, MelderFile file);
+wchar_t * Melder_dirToPath (MelderDir dir);
+	/* Returns a pointer internal to 'dir', like "/u/paul/praats" or "D:\Paul\Praats" */
+wchar_t * Melder_fileToPath (MelderFile file);
+void MelderFile_copy (MelderFile file, MelderFile copy);
+void MelderDir_copy (MelderDir dir, MelderDir copy);
+bool MelderFile_equal (MelderFile file1, MelderFile file2);
+bool MelderDir_equal (MelderDir dir1, MelderDir dir2);
+void MelderFile_setToNull (MelderFile file);
+bool MelderFile_isNull (MelderFile file);
+void MelderDir_setToNull (MelderDir dir);
+bool MelderDir_isNull (MelderDir dir);
+void MelderDir_getFile (MelderDir parent, const wchar_t *fileName, MelderFile file);
+void MelderDir_relativePathToFile (MelderDir dir, const wchar_t *path, MelderFile file);
+void MelderFile_getParentDir (MelderFile file, MelderDir parent);
+void MelderDir_getParentDir (MelderDir file, MelderDir parent);
+bool MelderDir_isDesktop (MelderDir dir);
+void MelderDir_getSubdir (MelderDir parent, const wchar_t *subdirName, MelderDir subdir);
+void Melder_rememberShellDirectory (void);
+wchar_t * Melder_getShellDirectory (void);
+void Melder_getHomeDir (MelderDir homeDir);
+void Melder_getPrefDir (MelderDir prefDir);
+void Melder_getTempDir (MelderDir tempDir);
+
+bool MelderFile_exists (MelderFile file);
+bool MelderFile_readable (MelderFile file);
+long MelderFile_length (MelderFile file);
+void MelderFile_delete (MelderFile file);
+
+/* The following two should be combined with each other and with Windows extension setting: */
+FILE * Melder_fopen (MelderFile file, const char *type);
+void Melder_fclose (MelderFile file, FILE *stream);
+void Melder_files_cleanUp (void);
+
+/* So these will be the future replacements for the above, as soon as we rid of text files: */
+MelderFile MelderFile_open (MelderFile file);
+MelderFile MelderFile_append (MelderFile file);
+MelderFile MelderFile_create (MelderFile file);
+void * MelderFile_read (MelderFile file, long nbytes);
+char * MelderFile_readLine (MelderFile file);
+void MelderFile_writeCharacter (MelderFile file, wchar_t kar);
+void MelderFile_write (MelderFile file, const wchar_t *s1);
+void MelderFile_write (MelderFile file, const wchar_t *s1, const wchar_t *s2);
+void MelderFile_write (MelderFile file, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3);
+void MelderFile_write (MelderFile file, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3, const wchar_t *s4);
+void MelderFile_write (MelderFile file, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3, const wchar_t *s4, const wchar_t *s5);
+void MelderFile_write (MelderFile file, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3, const wchar_t *s4, const wchar_t *s5, const wchar_t *s6);
+void MelderFile_write (MelderFile file, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3, const wchar_t *s4, const wchar_t *s5, const wchar_t *s6, const wchar_t *s7);
+void MelderFile_write (MelderFile file, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3, const wchar_t *s4, const wchar_t *s5, const wchar_t *s6, const wchar_t *s7, const wchar_t *s8);
+void MelderFile_write (MelderFile file, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3, const wchar_t *s4, const wchar_t *s5, const wchar_t *s6, const wchar_t *s7, const wchar_t *s8, const wchar_t *s9);
+void MelderFile_rewind (MelderFile file);
+void MelderFile_seek (MelderFile file, long position, int direction);
+long MelderFile_tell (MelderFile file);
+void MelderFile_close (MelderFile file);
+void MelderFile_close_nothrow (MelderFile file);
+
+/* Read and write whole text files. */
+wchar_t * MelderFile_readText (MelderFile file);
+void MelderFile_writeText (MelderFile file, const wchar_t *text, enum kMelder_textOutputEncoding outputEncoding);
+void MelderFile_appendText (MelderFile file, const wchar_t *text);
+
+void Melder_createDirectory (MelderDir parent, const wchar_t *subdirName, int mode);
+
+void Melder_getDefaultDir (MelderDir dir);
+void Melder_setDefaultDir (MelderDir dir);
+void MelderFile_setDefaultDir (MelderFile file);
+
+/* Use the following functions to pass unchanged text or file names to Melder_* functions. */
+/* Backslashes are replaced by "\bs". */
+/* The trick is that they return one of 11 cyclically used static strings, */
+/* so you can use up to 11 strings in a single Melder_* call. */
+wchar_t * Melder_peekExpandBackslashes (const wchar_t *message);
+const wchar_t * MelderFile_messageName (MelderFile file);   // Calls Melder_peekExpandBackslashes ().
+
+/*
+ * Debugging.
+ */
+int Melder_fatal (const char *format, ...);
+	/* Give error message, abort program. */
+	/* Should only be caused by programming errors. */
+
+int Melder_assert_ (const char *condition, const char *fileName, int lineNumber);
+	/* Call Melder_fatal with a message based on the following template: */
+	/*    "Assertion failed in file <fileName> on line <lineNumber>: <condition>" */
+
+void Melder_setTracing (bool tracing);
+extern bool Melder_isTracing;
+void Melder_tracingToFile (MelderFile file);
+void Melder_trace_FMT (const char *fileName, int lineNumber, const char *functionName, const char *format, ...);
+#ifdef NDEBUG
+	#define Melder_assert(x)   ((void) 0)
+	#define trace(x)   ((void) 0)
+#else
+	#define Melder_assert(x)   ((x) ? (void) (0) : (void) Melder_assert_ (#x, __FILE__, __LINE__))
+	#define trace(...)   ((! Melder_isTracing) ? (void) 0 : Melder_trace_FMT (__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__))
 #endif
 
 /*
+ * char16 and char32 handling.
+ */
+static inline int64_t str16len (const char16_t *string) {
+	if (sizeof (wchar_t) == 2) {
+		return (int64_t) wcslen ((const wchar_t *) string);
+	} else {
+		int64_t result = 0;
+		while (* string ++ != u'\0') result ++;
+		return result;
+	}
+}
+static inline void str16cpy (char16_t *target, const char16_t *source) {
+	if (sizeof (wchar_t) == 2) {
+		wcscpy ((wchar_t *) target, (const wchar_t *) source);
+	} else {
+		while (* source != u'\0') * target ++ = * source ++;
+		* target = u'\0';
+	}
+}
+static inline int str16cmp (const char16_t *string1, const char16_t *string2) {
+	if (sizeof (wchar_t) == 2) {
+		return wcscmp ((const wchar_t *) string1, (const wchar_t *) string2);
+	} else {
+		while (*string1 == *string2 ++) {
+			if (*string1 ++ == u'\0') {
+				return 0;
+			}
+		}
+		return (int) (int16_t) (string1 [0] - string2 [-1]);   // unsigned subtraction, then sign conversion, then up conversion
+	}
+}
+static inline int64_t str32len (const char32_t *string) {
+	if (sizeof (wchar_t) == 4) {
+		return (int64_t) wcslen ((const wchar_t *) string);
+	} else {
+		int64_t result = 0;
+		while (* string ++ != U'\0') result ++;
+		return result;
+	}
+}
+static inline void str32cpy (char32_t *target, const char32_t *source) {
+	if (sizeof (wchar_t) == 4) {
+		wcscpy ((wchar_t *) target, (const wchar_t *) source);
+	} else {
+		while (* source != U'\0') * target ++ = * source ++;
+		* target = U'\0';
+	}
+}
+static inline int str32cmp (const char32_t *string1, const char32_t *string2) {
+	if (sizeof (wchar_t) == 4) {
+		return wcscmp ((const wchar_t *) string1, (const wchar_t *) string2);
+	} else {
+		while (*string1 == *string2 ++) {
+			if (*string1 ++ == U'\0') {
+				return 0;
+			}
+		}
+		return (int) (int32_t) (string1 [0] - string2 [-1]);   // unsigned subtraction, then sign conversion, then perhaps up conversion
+	}
+}
+
+/*
  * Operating system version control.
  */
 #define ALLOW_GDK_DRAWING  1
@@ -138,7 +330,7 @@ void Melder_message_init (void);   // to be called around program start-up
 void * _Melder_malloc (int64_t size);
 #define Melder_malloc(type,numberOfElements)  (type *) _Melder_malloc ((numberOfElements) * (int64_t) sizeof (type))
 void * _Melder_malloc_f (int64_t size);
-#define Melder_malloc_f(type,numberOfElements)  (type *) _Melder_malloc_f ((numberOfElements) * sizeof (type))
+#define Melder_malloc_f(type,numberOfElements)  (type *) _Melder_malloc_f ((numberOfElements) * (int64_t) sizeof (type))
 void * Melder_realloc (void *pointer, int64_t size);
 void * Melder_realloc_f (void *pointer, int64_t size);
 void * _Melder_calloc (int64_t numberOfElements, int64_t elementSize);
@@ -182,22 +374,29 @@ const uint32_t kMelder_textOutputEncoding_FLAC = 0x464C4143;
 bool Melder_isValidAscii (const wchar_t *string);
 bool Melder_strIsValidUtf8 (const char *string);
 bool Melder_isEncodable (const wchar_t *string, int outputEncoding);
-extern wchar_t Melder_decodeMacRoman [256];
-extern wchar_t Melder_decodeWindowsLatin1 [256];
+extern char32_t Melder_decodeMacRoman [256];
+extern char32_t Melder_decodeWindowsLatin1 [256];
 
-long Melder_killReturns_inlineW (wchar_t *text);
+long Melder_killReturns_inlineW  (wchar_t *text);
+long Melder_killReturns_inline32 (char32_t *text);
 
-unsigned long wcslen_utf8 (const wchar_t *wcs, bool expandNewlines);
-unsigned long wcslen_utf16 (const wchar_t *wcs, bool expandNewlines);
-unsigned long wcslen_utf32 (const wchar_t *wcs, bool expandNewlines);
+size_t wcslen_utf8  (const wchar_t *wcs, bool expandNewlines);
+size_t wcslen_utf16 (const wchar_t *wcs, bool expandNewlines);
+size_t wcslen_char32 (const wchar_t *wcs, bool expandNewlines);
 
-void Melder_8bitToWcs_inline (const char *string, wchar_t *wcs, int inputEncoding);
+void Melder_8bitToWcs_inline   (const char *source, wchar_t *target, int inputEncoding);
+void Melder_8bitToChar32_inline (const char *source, char32_t *target, int inputEncoding);
 	// errors: Text is not valid UTF-8.
 wchar_t * Melder_8bitToWcs (const char *string, int inputEncoding);
+char32 * Melder_8bitToChar32 (const char *string, int inputEncoding);
 	// errors: Out of memory; Text is not valid UTF-8.
 wchar_t * Melder_utf8ToWcs (const char *string);
+char32 * Melder_utf8ToChar32 (const char *string);
 	// errors: Out of memory; Text is not valid UTF-8.
 
+char32 * Melder_utf8ToChar32_f (const char *string);   // for use in string constants only
+	// crashes: Out of memory; Text is not valid UTF-8.
+
 void Melder_wcsToUtf8_inline (const wchar_t *wcs, char *utf8);
 char * Melder_wcsToUtf8 (const wchar_t *string);
 	// errors: Out of memory.
@@ -205,7 +404,7 @@ void Melder_wcsTo8bitFileRepresentation_inline (const wchar_t *wcs, char *utf8);
 void Melder_8bitFileRepresentationToWcs_inline (const char *utf8, wchar_t *wcs);
 extern "C" wchar_t * Melder_peekUtf8ToWcs (const char *string);
 extern "C" char * Melder_peekWcsToUtf8 (const wchar_t *string);
-extern "C" const utf16_t * Melder_peekWcsToUtf16 (const wchar_t *string);
+extern "C" const uint16_t * Melder_peekWcsToUtf16 (const wchar_t *string);   // char16_t is C++-only
 const void * Melder_peekWcsToCfstring (const wchar_t *string);
 void Melder_fwriteWcsAsUtf8 (const wchar_t *ptr, size_t n, FILE *f);
 
@@ -251,137 +450,34 @@ double Melder_allocationSize (void);
 double Melder_reallocationsInSituCount (void);
 double Melder_movingReallocationsCount (void);
 
-/********** FILES **********/
-
-#if defined (_WIN32)
-	#define Melder_DIRECTORY_SEPARATOR  '\\'
-#else
-	#define Melder_DIRECTORY_SEPARATOR  '/'
-#endif
-
-struct FLAC__StreamDecoder;
-struct FLAC__StreamEncoder;
-
-#define kMelder_MAXPATH 1023   /* excluding the null byte */
-
-struct structMelderFile {
-	FILE *filePointer;
-	wchar_t path [kMelder_MAXPATH+1];
-	bool openForReading, openForWriting, verbose, requiresCRLF;
-	unsigned long outputEncoding;
-	int indent;
-	struct FLAC__StreamEncoder *flacEncoder;
-};
-typedef struct structMelderFile *MelderFile;
-
-struct structMelderDir {
-	wchar_t path [kMelder_MAXPATH+1];
-};
-typedef struct structMelderDir *MelderDir;
-
-#if defined (macintosh) && useCarbon
-	void Melder_machToFile (void *void_fsref, MelderFile file);
-#endif
-
-const wchar_t * MelderFile_name (MelderFile file);
-wchar_t * MelderDir_name (MelderDir dir);
-void Melder_pathToDir (const wchar_t *path, MelderDir dir);
-void Melder_pathToFile (const wchar_t *path, MelderFile file);
-void Melder_relativePathToFile (const wchar_t *path, MelderFile file);
-wchar_t * Melder_dirToPath (MelderDir dir);
-	/* Returns a pointer internal to 'dir', like "/u/paul/praats" or "D:\Paul\Praats" */
-wchar_t * Melder_fileToPath (MelderFile file);
-void MelderFile_copy (MelderFile file, MelderFile copy);
-void MelderDir_copy (MelderDir dir, MelderDir copy);
-bool MelderFile_equal (MelderFile file1, MelderFile file2);
-bool MelderDir_equal (MelderDir dir1, MelderDir dir2);
-void MelderFile_setToNull (MelderFile file);
-bool MelderFile_isNull (MelderFile file);
-void MelderDir_setToNull (MelderDir dir);
-bool MelderDir_isNull (MelderDir dir);
-void MelderDir_getFile (MelderDir parent, const wchar_t *fileName, MelderFile file);
-void MelderDir_relativePathToFile (MelderDir dir, const wchar_t *path, MelderFile file);
-void MelderFile_getParentDir (MelderFile file, MelderDir parent);
-void MelderDir_getParentDir (MelderDir file, MelderDir parent);
-bool MelderDir_isDesktop (MelderDir dir);
-void MelderDir_getSubdir (MelderDir parent, const wchar_t *subdirName, MelderDir subdir);
-void Melder_rememberShellDirectory (void);
-wchar_t * Melder_getShellDirectory (void);
-void Melder_getHomeDir (MelderDir homeDir);
-void Melder_getPrefDir (MelderDir prefDir);
-void Melder_getTempDir (MelderDir tempDir);
-
-bool MelderFile_exists (MelderFile file);
-bool MelderFile_readable (MelderFile file);
-long MelderFile_length (MelderFile file);
-void MelderFile_delete (MelderFile file);
-
-/* The following two should be combined with each other and with Windows extension setting: */
-FILE * Melder_fopen (MelderFile file, const char *type);
-void Melder_fclose (MelderFile file, FILE *stream);
-void Melder_files_cleanUp (void);
-
-/* So these will be the future replacements for the above, as soon as we rid of text files: */
-MelderFile MelderFile_open (MelderFile file);
-MelderFile MelderFile_append (MelderFile file);
-MelderFile MelderFile_create (MelderFile file);
-void * MelderFile_read (MelderFile file, long nbytes);
-char * MelderFile_readLine (MelderFile file);
-void MelderFile_writeCharacter (MelderFile file, wchar_t kar);
-void MelderFile_write (MelderFile file, const wchar_t *s1);
-void MelderFile_write (MelderFile file, const wchar_t *s1, const wchar_t *s2);
-void MelderFile_write (MelderFile file, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3);
-void MelderFile_write (MelderFile file, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3, const wchar_t *s4);
-void MelderFile_write (MelderFile file, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3, const wchar_t *s4, const wchar_t *s5);
-void MelderFile_write (MelderFile file, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3, const wchar_t *s4, const wchar_t *s5, const wchar_t *s6);
-void MelderFile_write (MelderFile file, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3, const wchar_t *s4, const wchar_t *s5, const wchar_t *s6, const wchar_t *s7);
-void MelderFile_write (MelderFile file, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3, const wchar_t *s4, const wchar_t *s5, const wchar_t *s6, const wchar_t *s7, const wchar_t *s8);
-void MelderFile_write (MelderFile file, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3, const wchar_t *s4, const wchar_t *s5, const wchar_t *s6, const wchar_t *s7, const wchar_t *s8, const wchar_t *s9);
-void MelderFile_rewind (MelderFile file);
-void MelderFile_seek (MelderFile file, long position, int direction);
-long MelderFile_tell (MelderFile file);
-void MelderFile_close (MelderFile file);
-void MelderFile_close_nothrow (MelderFile file);
-
-/* Read and write whole text files. */
-wchar_t * MelderFile_readText (MelderFile file);
-void MelderFile_writeText (MelderFile file, const wchar_t *text, enum kMelder_textOutputEncoding outputEncoding);
-void MelderFile_appendText (MelderFile file, const wchar_t *text);
-
-void Melder_createDirectory (MelderDir parent, const wchar_t *subdirName, int mode);
-
-void Melder_getDefaultDir (MelderDir dir);
-void Melder_setDefaultDir (MelderDir dir);
-void MelderFile_setDefaultDir (MelderFile file);
-
-/* Use the following functions to pass unchanged text or file names to Melder_* functions. */
-/* Backslashes are replaced by "\bs". */
-/* The trick is that they return one of 11 cyclically used static strings, */
-/* so you can use up to 11 strings in a single Melder_* call. */
-wchar_t * Melder_peekExpandBackslashes (const wchar_t *message);
-const wchar_t * MelderFile_messageName (MelderFile file);   // Calls Melder_peekExpandBackslashes ().
-
 /********** STRINGS **********/
 
 /* These are routines for never having to check string boundaries again. */
 
 typedef struct {
-	unsigned long length;
-	unsigned long bufferSize;
-	wchar_t *string;   // a growing buffer, never shrunk (can only be freed by MelderString_free)
+	int64 length;
+	int64 bufferSize;
+	wchar *string;   // a growing buffer, never shrunk (can only be freed by MelderString_free)
 } MelderString;
 typedef struct {
-	unsigned long length;
-	unsigned long bufferSize;
-	utf16_t *string;   // a growing buffer, never shrunk (can only be freed by MelderString16_free)
+	int64 length;
+	int64 bufferSize;
+	char16 *string;   // a growing buffer, never shrunk (can only be freed by MelderString16_free)
 } MelderString16;
+typedef struct {
+	int64 length;
+	int64 bufferSize;
+	char32 *string;   // a growing buffer, never shrunk (can only be freed by MelderString32_free)
+} MelderString32;
 
 void MelderString_free (MelderString *me);   // frees the "string" attribute only (and sets other attributes to zero)
 void MelderString16_free (MelderString16 *me);   // frees the "string" attribute only (and sets other attributes to zero)
+void MelderString32_free (MelderString32 *me);   // frees the "string" attribute only (and sets other attributes to zero)
 void MelderString_empty (MelderString *me);   // sets to empty string (buffer not freed)
 void MelderString16_empty (MelderString16 *me);   // sets to empty string (buffer not freed)
+void MelderString32_empty (MelderString32 *me);   // sets to empty string (buffer not freed)
 void MelderString_copy (MelderString *me, const wchar_t *source);
-void MelderString_ncopy (MelderString *me, const wchar_t *source, unsigned long n);
+void MelderString_ncopy (MelderString *me, const wchar_t *source, int64 n);
 void MelderString_append (MelderString *me, const wchar_t *s1);
 void MelderString_append (MelderString *me, const wchar_t *s1, const wchar_t *s2);
 void MelderString_append (MelderString *me, const wchar_t *s1, const wchar_t *s2, const wchar_t *s3);
@@ -398,6 +494,7 @@ void MelderString_append (MelderString *me, const wchar_t *s1, const wchar_t *s2
 	const wchar_t *s5, const wchar_t *s6, const wchar_t *s7, const wchar_t *s8, const wchar_t *s9);
 void MelderString_appendCharacter (MelderString *me, wchar_t character);
 void MelderString16_appendCharacter (MelderString16 *me, wchar_t character);
+void MelderString32_appendCharacter (MelderString32 *me, char32_t character);
 void MelderString_get (MelderString *me, wchar_t *destination);   // performs no boundary checking
 double MelderString_allocationCount (void);
 double MelderString_deallocationCount (void);
@@ -552,9 +649,10 @@ struct MelderArg {
 	MelderArg (const wchar_t *      arg) : type (1), argW (arg) { }
 	MelderArg (const  char   *      arg) : type (2), arg8 (arg) { }
 	MelderArg (const double         arg) : type (1), argW (Melder_double          (arg)) { }
-	MelderArg (const     long long  arg) : type (1), argW (Melder_integer         (arg)) { }
+	MelderArg (const          long long  arg) : type (1), argW (Melder_integer         (arg)) { }
+	MelderArg (const unsigned long long  arg) : type (1), argW (Melder_integer         ((int64_t) arg)) { }
 	MelderArg (const          long  arg) : type (1), argW (Melder_integer         (arg)) { }
-	MelderArg (const unsigned long  arg) : type (1), argW (Melder_integer         (arg)) { }
+	MelderArg (const unsigned long  arg) : type (1), argW (Melder_integer         ((int64_t) arg)) { }   // ignore ULL above 2^63
 	MelderArg (const          int   arg) : type (1), argW (Melder_integer         (arg)) { }
 	MelderArg (const unsigned int   arg) : type (1), argW (Melder_integer         (arg)) { }
 	MelderArg (const          short arg) : type (1), argW (Melder_integer         (arg)) { }
@@ -639,25 +737,6 @@ void Melder_clearError (void);
 wchar_t * Melder_getError (void);
 	/* Returns the error string. Mainly used with wcsstr. */
 
-int Melder_fatal (const char *format, ...);
-	/* Give error message, abort program. */
-	/* Should only be caused by programming errors. */
-
-#ifdef NDEBUG
-	#define Melder_assert(x)   ((void) 0)
-	#define trace(x)   ((void) 0)
-#else
-	#define Melder_assert(x)   ((x) ? (void) (0) : (void) Melder_assert_ (#x, __FILE__, __LINE__))
-	#define trace(...)   Melder_trace_ (__FILE__, __LINE__, __FUNCTION__, __VA_ARGS__)
-#endif
-int Melder_assert_ (const char *condition, const char *fileName, int lineNumber);
-	/* Call Melder_fatal with a message based on the following template: */
-	/*    "Assertion failed in file <fileName> on line <lineNumber>: <condition>" */
-void Melder_setTracing (bool tracing);
-bool Melder_getTracing ();
-void Melder_tracingToFile (MelderFile file);
-void Melder_trace_ (const char *fileName, int lineNumber, const char *functionName, const char *format, ...);
-
 /********** WARNING: ive warning to stderr (batch) or to a "Warning" dialog **********/
 
 void Melder_warning (const MelderArg& arg1);
@@ -995,7 +1074,7 @@ void MelderFile_writeAudioFileTrailer (MelderFile file, int audioFileType, long
 void MelderFile_writeAudioFile (MelderFile file, int audioFileType, const short *buffer, long sampleRate, long numberOfSamples, int numberOfChannels, int numberOfBitsPerSamplePoint);
 
 int MelderFile_checkSoundFile (MelderFile file, int *numberOfChannels, int *encoding,
-	double *sampleRate, long *startOfData, long *numberOfSamples);
+	double *sampleRate, long *startOfData, int32 *numberOfSamples);
 /* Returns information about a just opened audio file.
  * The return value is the audio file type, or 0 if it is not a sound file or in case of error.
  * The data start at 'startOfData' bytes from the start of the file.
@@ -1221,12 +1300,14 @@ public:
 	}
 private:
 	_autostring& operator= (const _autostring&);   // disable copy assignment
-	//autostring (autostring &);   // disable copy constructor (trying it this way also disables good things like autostring s1 = wcsdup("hello");)
+	//_autostring (_autostring &);   // disable copy constructor (trying it this way also disables good things like autostring s1 = wcsdup("hello");)
 	template <class Y> _autostring (_autostring<Y> &);   // disable copy constructor
 };
 
 typedef _autostring <wchar_t> autostring;
 typedef _autostring <char> autostring8;
+typedef _autostring <char16_t> autostring16;
+typedef _autostring <char32_t> autostring32;
 
 class autoMelderAudioSaveMaximumAsynchronicity {
 	enum kMelder_asynchronicityLevel d_saveAsynchronicity;
diff --git a/sys/melder_alloc.cpp b/sys/melder_alloc.cpp
index 76b9599..9954943 100644
--- a/sys/melder_alloc.cpp
+++ b/sys/melder_alloc.cpp
@@ -65,9 +65,9 @@ void Melder_alloc_init (void) {
 void * _Melder_malloc (int64_t size) {
 	if (size <= 0)
 		Melder_throw ("Can never allocate ", Melder_bigInteger (size), " bytes.");
-	if (sizeof (size_t) < 8 && size > /*2147483647*/ INT32_MAX)
+	if (sizeof (size_t) < 8 && (double) size > SIZE_MAX)
 		Melder_throw ("Can never allocate ", Melder_bigInteger (size), " bytes. Use a 64-bit edition of Praat instead?");
-	void *result = malloc (size);
+	void *result = malloc ((size_t) size);
 	if (result == NULL)
 		Melder_throw ("Out of memory: there is not enough room for another ", Melder_bigInteger (size), " bytes.");
 	if (Melder_debug == 34) { Melder_casual ("Melder_malloc\t%p\t%ls\t1", result, Melder_bigInteger (size)); }
@@ -79,10 +79,12 @@ void * _Melder_malloc (int64_t size) {
 void * _Melder_malloc_f (int64_t size) {
 	if (size <= 0)
 		Melder_fatal ("(Melder_malloc_f:) Can never allocate %ls bytes.", Melder_bigInteger (size));
-	void *result = malloc (size);
+	if (sizeof (size_t) < 8 && (double) size > SIZE_MAX)
+		Melder_fatal ("(Melder_malloc_f:) Can never allocate %ls bytes.", Melder_bigInteger (size));
+	void *result = malloc ((size_t) size);
 	if (result == NULL) {
 		if (theRainyDayFund != NULL) { free (theRainyDayFund); theRainyDayFund = NULL; }
-		result = malloc (size);
+		result = malloc ((size_t) size);
 		if (result != NULL) {
 			Melder_flushError ("Praat is very low on memory.\nSave your work and quit Praat.\nIf you don't do that, Praat may crash.");
 		} else {
@@ -105,7 +107,9 @@ void _Melder_free (void **ptr) {
 void * Melder_realloc (void *ptr, int64_t size) {
 	if (size <= 0)
 		Melder_throw ("Can never allocate ", Melder_bigInteger (size), " bytes.");
-	void *result = realloc (ptr, size);   // will not show in the statistics...
+	if (sizeof (size_t) < 8 && (double) size > SIZE_MAX)
+		Melder_throw ("Can never allocate ", Melder_bigInteger (size), " bytes. Use a 64-bit edition of Praat instead?");
+	void *result = realloc (ptr, (size_t) size);   // will not show in the statistics...
 	if (result == NULL)
 		Melder_throw ("Out of memory. Could not extend room to ", Melder_bigInteger (size), " bytes.");
 	if (ptr == NULL) {   // is it like malloc?
@@ -127,10 +131,12 @@ void * Melder_realloc_f (void *ptr, int64_t size) {
 	void *result;
 	if (size <= 0)
 		Melder_fatal ("(Melder_realloc_f:) Can never allocate %ls bytes.", Melder_bigInteger (size));
-	result = realloc (ptr, size);   /* Will not show in the statistics... */
+	if (sizeof (size_t) < 8 && (double) size > SIZE_MAX)
+		Melder_fatal ("(Melder_realloc_f:) Can never allocate %ls bytes.", Melder_bigInteger (size));
+	result = realloc (ptr, (size_t) size);   // will not show in the statistics...
 	if (result == NULL) {
 		if (theRainyDayFund != NULL) { free (theRainyDayFund); theRainyDayFund = NULL; }
-		result = realloc (ptr, size);
+		result = realloc (ptr, (size_t) size);
 		if (result != NULL) {
 			Melder_flushError ("Praat is very low on memory.\nSave your work and quit Praat.\nIf you don't do that, Praat may crash.");
 		} else {
@@ -157,14 +163,14 @@ void * _Melder_calloc (int64_t nelem, int64_t elsize) {
 		Melder_throw ("Can never allocate ", Melder_bigInteger (nelem), " elements.");
 	if (elsize <= 0)
 		Melder_throw ("Can never allocate elements whose size is ", Melder_bigInteger (elsize), " bytes.");
-	if (sizeof (size_t) < 8 && nelem * elsize > 2147483647)
+	if (sizeof (size_t) < 8 && (double) nelem * (double) elsize > SIZE_MAX)
 		Melder_throw ("Can never allocate ", Melder_bigInteger (nelem * elsize), " bytes. Use a 64-bit edition of Praat instead?");
-	result = calloc (nelem, elsize);
+	result = calloc ((size_t) nelem, (size_t) elsize);
 	if (result == NULL)
 		Melder_throw ("Out of memory: there is not enough room for ", Melder_bigInteger (nelem), " more elements whose sizes are ", elsize, " bytes each.");
 	if (Melder_debug == 34) { Melder_casual ("Melder_calloc\t%p\t%ls\t%ls", result, Melder_bigInteger (nelem), Melder_bigInteger (elsize)); }
 	totalNumberOfAllocations += 1;
-	totalAllocationSize += nelem * elsize;
+	totalAllocationSize += (double) nelem * (double) elsize;
 	return result;
 }
 
@@ -174,10 +180,12 @@ void * _Melder_calloc_f (int64_t nelem, int64_t elsize) {
 		Melder_fatal ("(Melder_calloc_f:) Can never allocate %ls elements.", Melder_bigInteger (nelem));
 	if (elsize <= 0)
 		Melder_fatal ("(Melder_calloc_f:) Can never allocate elements whose size is %ls bytes.", Melder_bigInteger (elsize));
-	result = calloc (nelem, elsize);
+	if (sizeof (size_t) < 8 && (double) nelem * (double) elsize > SIZE_MAX)
+		Melder_fatal ("(Melder_calloc_f:) Can never allocate %ls bytes.", Melder_double ((double) nelem * (double) elsize));
+	result = calloc ((size_t) nelem, (size_t) elsize);
 	if (result == NULL) {
 		if (theRainyDayFund != NULL) { free (theRainyDayFund); theRainyDayFund = NULL; }
-		result = calloc (nelem, elsize);
+		result = calloc ((size_t) nelem, (size_t) elsize);
 		if (result != NULL) {
 			Melder_flushError ("Praat is very low on memory.\nSave your work and quit Praat.\nIf you don't do that, Praat may crash.");
 		} else {
@@ -185,30 +193,34 @@ void * _Melder_calloc_f (int64_t nelem, int64_t elsize) {
 		}
 	}
 	totalNumberOfAllocations += 1;
-	totalAllocationSize += nelem * elsize;
+	totalAllocationSize += (double) nelem * (double) elsize;
 	return result;
 }
 
 char * Melder_strdup (const char *string) {
 	if (! string) return NULL;
-	int64_t size = strlen (string) + 1;
-	char *result = (char *) malloc (size * sizeof (char));
+	int64_t size = (int64_t) strlen (string) + 1;
+	if (sizeof (size_t) < 8 && (double) size > SIZE_MAX)
+		Melder_throw ("Can never allocate ", Melder_bigInteger (size), " bytes. Use a 64-bit edition of Praat instead?");
+	char *result = (char *) malloc ((size_t) size * sizeof (char));
 	if (result == NULL)
 		Melder_throw ("Out of memory: there is not enough room to duplicate a text of ", Melder_bigInteger (size - 1), " characters.");
 	strcpy (result, string);
 	if (Melder_debug == 34) { Melder_casual ("Melder_strdup\t%p\t%ls\t1", result, Melder_bigInteger (size)); }
 	totalNumberOfAllocations += 1;
-	totalAllocationSize += size;
+	totalAllocationSize += (double) size;
 	return result;
 }
 
 char * Melder_strdup_f (const char *string) {
 	if (! string) return NULL;
-	int64_t size = strlen (string) + 1;
-	char *result = (char *) malloc (size * sizeof (char));
+	int64_t size = (int64_t) strlen (string) + 1;
+	if (sizeof (size_t) < 8 && (double) size > SIZE_MAX)
+		Melder_fatal ("(Melder_strdup_f:) Can never allocate %ls bytes.", Melder_bigInteger (size));
+	char *result = (char *) malloc ((size_t) size * sizeof (char));
 	if (result == NULL) {
 		if (theRainyDayFund != NULL) { free (theRainyDayFund); theRainyDayFund = NULL; }
-		result = (char *) malloc (size * sizeof (char));
+		result = (char *) malloc ((size_t) size * sizeof (char));
 		if (result != NULL) {
 			Melder_flushError ("Praat is very low on memory.\nSave your work and quit Praat.\nIf you don't do that, Praat may crash.");
 		} else {
@@ -217,30 +229,55 @@ char * Melder_strdup_f (const char *string) {
 	}
 	strcpy (result, string);
 	totalNumberOfAllocations += 1;
-	totalAllocationSize += size;
+	totalAllocationSize += (double) size;
 	return result;
 }
 
 wchar_t * Melder_wcsdup (const wchar_t *string) {
 	if (! string) return NULL;
-	int64_t size = wcslen (string) + 1;
-	wchar_t *result = (wchar_t *) malloc (size * sizeof (wchar_t));
+	int64_t size = (int64_t) wcslen (string) + 1;
+	double allocationSize = (double) size * (double) sizeof (wchar_t);
+	if (allocationSize > INT54_MAX)
+		Melder_throw ("Can never allocate ", Melder_bigInteger (size), " bytes. It is above the 9-petabyte limit.");
+	if (sizeof (size_t) < 8 && allocationSize > SIZE_MAX)
+		Melder_throw ("Can never allocate ", Melder_bigInteger (size), " bytes. Use a 64-bit edition of Praat instead?");
+	wchar_t *result = (wchar_t *) malloc ((size_t) allocationSize);   // guarded conversion
 	if (result == NULL)
 		Melder_throw ("Out of memory: there is not enough room to duplicate a text of ", Melder_bigInteger (size - 1), " characters.");
 	wcscpy (result, string);
 	if (Melder_debug == 34) { Melder_casual ("Melder_wcsdup\t%p\t%ls\t4", result, Melder_bigInteger (size)); }
 	totalNumberOfAllocations += 1;
-	totalAllocationSize += size * sizeof (wchar_t);
+	totalAllocationSize += allocationSize;
+	return result;
+}
+
+char32_t * Melder_str32dup (const char32_t *string) {
+	if (! string) return NULL;
+	int64_t size = (int64_t) str32len (string) + 1;
+	double allocationSize = (double) size * (double) sizeof (char32_t);
+	if (allocationSize > INT54_MAX)
+		Melder_throw ("Can never allocate ", Melder_bigInteger (size), " bytes. It is above the 9-petabyte limit.");
+	if (sizeof (size_t) < 8 && allocationSize > SIZE_MAX)
+		Melder_throw ("Can never allocate ", Melder_bigInteger (size), " bytes. Use a 64-bit edition of Praat instead?");
+	char32_t *result = (char32_t *) malloc ((size_t) allocationSize);   // guarded conversion
+	if (result == NULL)
+		Melder_throw ("Out of memory: there is not enough room to duplicate a text of ", Melder_bigInteger (size - 1), " characters.");
+	str32cpy (result, string);
+	if (Melder_debug == 34) { Melder_casual ("Melder_str32dup\t%p\t%ls\t4", result, Melder_bigInteger (size)); }
+	totalNumberOfAllocations += 1;
+	totalAllocationSize += allocationSize;
 	return result;
 }
 
 wchar_t * Melder_wcsdup_f (const wchar_t *string) {
 	if (! string) return NULL;
-	int64_t size = wcslen (string) + 1;
-	wchar_t *result = (wchar_t *) malloc (size * sizeof (wchar_t));
+	int64_t size = (int64_t) wcslen (string) + 1;
+	if (sizeof (size_t) < 8 && (double) size * (double) sizeof (wchar_t) > SIZE_MAX)
+		Melder_fatal ("(Melder_wcsdup_f:) Can never allocate %ls characters.", Melder_bigInteger (size));
+	wchar_t *result = (wchar_t *) malloc ((size_t) size * sizeof (wchar_t));
 	if (result == NULL) {
 		if (theRainyDayFund != NULL) { free (theRainyDayFund); theRainyDayFund = NULL; }
-		result = (wchar_t *) malloc (size * sizeof (wchar_t));
+		result = (wchar_t *) malloc ((size_t) size * sizeof (wchar_t));
 		if (result != NULL) {
 			Melder_flushError ("Praat is very low on memory.\nSave your work and quit Praat.\nIf you don't do that, Praat may crash.");
 		} else {
@@ -249,7 +286,7 @@ wchar_t * Melder_wcsdup_f (const wchar_t *string) {
 	}
 	wcscpy (result, string);
 	totalNumberOfAllocations += 1;
-	totalAllocationSize += size * sizeof (wchar_t);
+	totalAllocationSize += (double) size * sizeof (wchar_t);
 	return result;
 }
 
@@ -279,6 +316,12 @@ int Melder_strcmp (const char *string1, const char *string2) {
 	return strcmp (string1, string2);
 }
 
+int Melder_str32cmp (const char32 *string1, const char32 *string2) {
+	if (string1 == NULL) string1 = U"";
+	if (string2 == NULL) string2 = U"";
+	return str32cmp (string1, string2);
+}
+
 int Melder_strncmp (const char *string1, const char *string2, int64_t n) {
 	if (string1 == NULL) string1 = "";
 	if (string2 == NULL) string2 = "";
diff --git a/sys/melder_audiofiles.cpp b/sys/melder_audiofiles.cpp
index 1ed117d..34d49d1 100644
--- a/sys/melder_audiofiles.cpp
+++ b/sys/melder_audiofiles.cpp
@@ -1,6 +1,6 @@
 /* melder_audiofiles.cpp
  *
- * Copyright (C) 1992-2011,2013 Paul Boersma & David Weenink, 2007 Erez Volk (for FLAC)
+ * Copyright (C) 1992-2011,2013,2015 Paul Boersma & David Weenink, 2007 Erez Volk (for FLAC)
  *
  * 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
@@ -80,8 +80,8 @@ void MelderFile_writeAudioFileHeader (MelderFile file, int audioFileType, long s
 
 					/* Format Version Chunk: 8 + 4 bytes. */
 					if (fwrite ("FVER", 1, 4, f) != 4) Melder_throw ("Error in file while trying to write the FVER statement.");
-					binputi4 (4, f);   // the size of what follows
-					binputi4 (0xA2805140, f);   // time of version
+					binputu4 (4, f);   // the size of what follows
+					binputu4 (0xA2805140, f);   // time of version
 
 					/* Common Chunk: 8 + 18 bytes. */
 					if (fwrite ("COMM", 1, 4, f) != 4) Melder_throw ("Error in file while trying to write the COMM statement.");
@@ -111,8 +111,8 @@ void MelderFile_writeAudioFileHeader (MelderFile file, int audioFileType, long s
 
 					/* Format Version Chunk: 8 + 4 bytes. */
 					if (fwrite ("FVER", 1, 4, f) != 4) Melder_throw ("Error in file while trying to write the FVER statement.");
-					binputi4 (4, f);   // the size of what follows
-					binputi4 (0xA2805140, f);   // time of version
+					binputu4 (4, f);   // the size of what follows
+					binputu4 (0xA2805140, f);   // time of version
 
 					/* Common Chunk: 8 + 24 bytes. */
 					if (fwrite ("COMM", 1, 4, f) != 4) Melder_throw ("Error in file while trying to write the COMM statement.");
@@ -140,11 +140,18 @@ void MelderFile_writeAudioFileHeader (MelderFile file, int audioFileType, long s
 						numberOfChannels > 2 ||
 						numberOfBitsPerSamplePoint != numberOfBytesPerSamplePoint * 8;
 					const int formatSize = needExtensibleFormat ? 40 : 16;
-					long dataSize = numberOfSamples * numberOfBytesPerSamplePoint * numberOfChannels;
+					double dataSize_f = (double) numberOfSamples * (double) numberOfBytesPerSamplePoint * (double) numberOfChannels;
+					if (dataSize_f > INT54_MAX)
+						Melder_throw ("Cannot save data over the 9-petabyte limit.");
+					int64_t dataSize = (int64_t) dataSize_f;
 
 					/* RIFF Chunk: contains all other chunks. */
 					if (fwrite ("RIFF", 1, 4, f) != 4) Melder_throw ("Error in file while trying to write the RIFF statement.");
-					binputi4LE (4 + (12 + formatSize) + (4 + dataSize), f);
+					int64_t sizeOfRiffChunk_i64 = 4 + (12 + formatSize) + (4 + dataSize);
+					if (sizeOfRiffChunk_i64 > UINT32_MAX)
+						Melder_throw ("Cannot save a WAV file with more than ", UINT32_MAX, " bytes.");
+					uint32_t sizeOfRiffChunk_u32 = (uint32_t) sizeOfRiffChunk_i64;
+					binputu4LE (sizeOfRiffChunk_u32, f);
 					if (fwrite ("WAVE", 1, 4, f) != 4) Melder_throw ("Error in file while trying to write the WAV file type.");
 
 					/* Format Chunk: if 16-bits audio, then 8 + 16 bytes; else 8 + 40 bytes. */
@@ -365,7 +372,7 @@ static short alaw2linear[] =
 };
 
 static void Melder_checkAiffFile (FILE *f, int *numberOfChannels, int *encoding,
-	double *sampleRate, long *startOfData, long *numberOfSamples)
+	double *sampleRate, long *startOfData, int32 *numberOfSamples)
 {
 	char data [8], chunkID [4];
 	bool commonChunkPresent = false, dataChunkPresent = false, isAifc = true;
@@ -452,7 +459,7 @@ static void Melder_checkAiffFile (FILE *f, int *numberOfChannels, int *encoding,
 }
 
 static void Melder_checkWavFile (FILE *f, int *numberOfChannels, int *encoding,
-	double *sampleRate, long *startOfData, long *numberOfSamples)
+	double *sampleRate, long *startOfData, int32 *numberOfSamples)
 {
 	char data [14], chunkID [4];
 	bool formatChunkPresent = false, dataChunkPresent = false;
@@ -564,7 +571,7 @@ static void Melder_checkWavFile (FILE *f, int *numberOfChannels, int *encoding,
 			dataChunkSize = chunkSize;
 			*startOfData = ftell (f);
 			if (chunkSize & 1) chunkSize ++;
-			if (chunkSize < 0) {   // incorrect data chunk (sometimes -44); assume that the data run till the end of the file
+			if (chunkSize > UINT32_MAX - 100) {   // incorrect data chunk (sometimes -44); assume that the data run till the end of the file
 				fseeko (f, 0LL, SEEK_END);
 				off_t endOfData = ftello (f);
 				dataChunkSize = chunkSize = endOfData - *startOfData;
@@ -586,12 +593,12 @@ static void Melder_checkWavFile (FILE *f, int *numberOfChannels, int *encoding,
 
 	if (! formatChunkPresent) Melder_throw (L"Found no Format Chunk.");
 	if (! dataChunkPresent) Melder_throw (L"Found no Data Chunk.");
-	Melder_assert (numberOfBitsPerSamplePoint != -1 && dataChunkSize != -1);
+	Melder_assert (numberOfBitsPerSamplePoint != -1 && dataChunkSize != 0xffffffff);
 	*numberOfSamples = dataChunkSize / *numberOfChannels / ((numberOfBitsPerSamplePoint + 7) / 8);
 }
 
 static void Melder_checkNextSunFile (FILE *f, int *numberOfChannels, int *encoding,
-	double *sampleRate, long *startOfData, long *numberOfSamples)
+	double *sampleRate, long *startOfData, int32 *numberOfSamples)
 {
 	char tag [4];
 	fread (tag, 1, 4, f);
@@ -637,7 +644,7 @@ static int nistGetValue (const char *header, const char *object, double *rval, c
 	return 1;
 }
 static void Melder_checkNistFile (FILE *f, int *numberOfChannels, int *encoding,
-	double *sampleRate, long *startOfData, long *numberOfSamples)
+	double *sampleRate, long *startOfData, int32 *numberOfSamples)
 {
 	char header [1024], sval [100];
  	double rval;
@@ -677,7 +684,7 @@ static void Melder_checkNistFile (FILE *f, int *numberOfChannels, int *encoding,
 }
 
 static void Melder_checkFlacFile (MelderFile file, int *numberOfChannels, int *encoding,
-	double *sampleRate, long *startOfData, long *numberOfSamples)
+	double *sampleRate, long *startOfData, int32 *numberOfSamples)
 {
 	FLAC__StreamMetadata metadata;
 	FLAC__StreamMetadata_StreamInfo *info;
@@ -688,13 +695,13 @@ static void Melder_checkFlacFile (MelderFile file, int *numberOfChannels, int *e
 	*encoding = Melder_FLAC_COMPRESSION_16;
 	*sampleRate = (double) info -> sample_rate;
 	*startOfData = 0;   // meaningless: libFLAC does the I/O
-	*numberOfSamples = info -> total_samples;   // FIXME: may lose bits above LONG_MAX
+	*numberOfSamples = info -> total_samples;   // BUG: loses bits above INT32_MAX
 	if ((FLAC__uint64) *numberOfSamples != info -> total_samples)
 		Melder_throw ("FLAC file too long.");
 }
 
 static void Melder_checkMp3File (FILE *f, int *numberOfChannels, int *encoding,
-	double *sampleRate, long *startOfData, long *numberOfSamples)
+	double *sampleRate, long *startOfData, int32 *numberOfSamples)
 {
 	MP3_FILE mp3f = mp3f_new ();
 	mp3f_set_file (mp3f, f);
@@ -706,14 +713,14 @@ static void Melder_checkMp3File (FILE *f, int *numberOfChannels, int *encoding,
 	*numberOfChannels = mp3f_channels (mp3f);
 	*sampleRate = mp3f_frequency (mp3f);
 	*numberOfSamples = mp3f_samples (mp3f);
-	if ((MP3F_OFFSET)*numberOfSamples != mp3f_samples (mp3f))
+	if ((MP3F_OFFSET)*numberOfSamples != mp3f_samples (mp3f))   // BUG: loses bits above INT32_MAX
 		Melder_throw ("MP3 file too long.");
 	*startOfData = 0;   // meaningless
 	mp3f_delete (mp3f);
 }
 
 int MelderFile_checkSoundFile (MelderFile file, int *numberOfChannels, int *encoding,
-	double *sampleRate, long *startOfData, long *numberOfSamples)
+	double *sampleRate, long *startOfData, int32 *numberOfSamples)
 {
 	char data [16];
 	FILE *f = file -> filePointer;
@@ -905,179 +912,277 @@ void Melder_readAudioToFloat (FILE *f, int numberOfChannels, int encoding, doubl
 					Melder_warning ("File too small (", numberOfChannels, "-channel 8-bit).\nMissing samples set to zero.");
 				}
 				break;
-			case Melder_LINEAR_16_BIG_ENDIAN: {
-				try {
-					const int numberOfBytesPerSamplePerChannel = 2;
-					if (numberOfChannels > (int) sizeof (double) / numberOfBytesPerSamplePerChannel) {
-						for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
-							for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
-								buffer [ichan] [isamp] = bingeti2 (f) * (1.0 / 32768);
+			case Melder_LINEAR_16_BIG_ENDIAN:
+			case Melder_LINEAR_16_LITTLE_ENDIAN:
+			case Melder_LINEAR_24_BIG_ENDIAN:
+			case Melder_LINEAR_24_LITTLE_ENDIAN:
+			case Melder_LINEAR_32_BIG_ENDIAN:
+			case Melder_LINEAR_32_LITTLE_ENDIAN:
+			{
+				int numberOfBytesPerSamplePerChannel =
+					encoding == Melder_LINEAR_16_BIG_ENDIAN || encoding == Melder_LINEAR_16_LITTLE_ENDIAN ? 2 :
+					encoding == Melder_LINEAR_24_BIG_ENDIAN || encoding == Melder_LINEAR_24_LITTLE_ENDIAN ? 3 : 4;
+				double numberOfBytes_f = (double) numberOfChannels * (double) numberOfSamples * (double) numberOfBytesPerSamplePerChannel;
+				if (isinf (numberOfBytes_f) || numberOfBytes_f > (double) (1LL << 53)) {
+					Melder_throw ("Cannot read ", numberOfBytes_f, " bytes, "
+						"because that crosses the 9-petabyte limit.");
+				}
+				if (numberOfBytes_f > (double) SIZE_MAX) {
+					Melder_throw ("Cannot read ", numberOfBytes_f, " bytes. "
+						"Perhaps try a 64-bit edition of Praat?");
+				}
+				Melder_assert (numberOfBytes_f >= 0.0);
+				size_t numberOfBytes = (size_t) numberOfBytes_f;   // cast is safe because overflow and signedness have been checked
+				uint8_t *bytes = (uint8_t *) & buffer [numberOfChannels] [numberOfSamples] + sizeof (double) - numberOfBytes;
+				/*
+				 * Read 16-bit data into the last quarter of the buffer,
+				 * or 24-bit data into the last three-eighths of the buffer,
+				 * or 32-bit data into the last half of the buffer.
+				 */
+				size_t numberOfBytesRead = fread (bytes, 1, numberOfBytes, f);
+				if (numberOfChannels == 1) {
+					switch (encoding) {
+						case Melder_LINEAR_16_BIG_ENDIAN: {
+							for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
+								unsigned char byte1 = * bytes ++, byte2 = * bytes ++;
+								int value = (int) (int16_t) (((uint16_t) byte1 << 8) | (uint16_t) byte2);   // extend sign
+								buffer [1] [isamp] = value * (1.0 / 32768);
 							}
-						}
-					} else { // optimize
-						long numberOfBytes = numberOfChannels * numberOfSamples * numberOfBytesPerSamplePerChannel;
-						unsigned char *bytes = (unsigned char *) & buffer [numberOfChannels] [numberOfSamples] + sizeof (double) - numberOfBytes;
-						Melder_assert (numberOfBytes > 0);
-						if (fread (bytes, 1, numberOfBytes, f) < (size_t) numberOfBytes) throw MelderError ();   // read 16-bit data into last quarter of buffer
-						if (numberOfChannels == 1) {
+						} break;
+						case Melder_LINEAR_16_LITTLE_ENDIAN: {
 							for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
 								unsigned char byte1 = * bytes ++, byte2 = * bytes ++;
-								long value = (int16_t) (((uint16_t) byte1 << 8) | (uint16_t) byte2);
+								int value = (int) (int16_t) (((uint16_t) byte2 << 8) | (uint16_t) byte1);   // extend sign
 								buffer [1] [isamp] = value * (1.0 / 32768);
 							}
-						} else {
+						} break;
+						case Melder_LINEAR_24_BIG_ENDIAN: {
 							for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
-								for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
-									unsigned char byte1 = * bytes ++, byte2 = * bytes ++;
-									long value = (int16_t) (((uint16_t) byte1 << 8) | (uint16_t) byte2);
-									buffer [ichan] [isamp] = value * (1.0 / 32768);
-								}
+								unsigned char byte1 = * bytes ++, byte2 = * bytes ++, byte3 = * bytes ++;
+								int32_t value = (int32_t)
+									((uint32_t) ((uint32_t) byte1 << 24) |
+									 (uint32_t) ((uint32_t) byte2 << 16) |
+									            ((uint32_t) byte3 << 8));
+								buffer [1] [isamp] = value * (1.0 / 32768 / 65536);
 							}
-						}
-					}
-				} catch (MelderError) {
-					Melder_clearError ();
-					Melder_warning (L"File too small (", numberOfChannels, "-channel 16-bit).\nMissing samples set to zero.");
-				}
-			} break;
-			case Melder_LINEAR_16_LITTLE_ENDIAN: {
-				try {
-					const int numberOfBytesPerSamplePerChannel = 2;
-					if (numberOfChannels > (int) sizeof (double) / numberOfBytesPerSamplePerChannel) {
-						for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
-							for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
-								buffer [ichan] [isamp] = bingeti2LE (f) * (1.0 / 32768);
+						} break;
+						case Melder_LINEAR_24_LITTLE_ENDIAN: {
+							for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
+								unsigned char byte1 = * bytes ++, byte2 = * bytes ++, byte3 = * bytes ++;
+								int32_t value = (int32_t)
+									((uint32_t) ((uint32_t) byte3 << 24) |
+									 (uint32_t) ((uint32_t) byte2 << 16) |
+									            ((uint32_t) byte1 << 8));
+								buffer [1] [isamp] = value * (1.0 / 32768 / 65536);
 							}
-						}
-					} else { // optimize
-						double numberOfBytes_f = (double) numberOfChannels * (double) numberOfSamples * (double) numberOfBytesPerSamplePerChannel;
-						if (isinf (numberOfBytes_f) || numberOfBytes_f > (double) (1LL << 53)) {
-							Melder_throw ("Cannot read ", numberOfBytes_f, " bytes, because that crosses the 9-petabyte limit.");
-						}
-						if (numberOfBytes_f > (double) SIZE_MAX) {
-							Melder_throw ("Cannot read ", numberOfBytes_f, " bytes. Perhaps try a 64-bit edition of Praat?");
-						}
-						Melder_assert (numberOfBytes_f >= 0.0);
-						size_t numberOfBytes = (size_t) numberOfBytes_f;   // cast is safe because overflow and signedness have been checked
-						unsigned char *bytes = (unsigned char *) & buffer [numberOfChannels] [numberOfSamples] + sizeof (double) - numberOfBytes;
-						if (fread (bytes, 1, numberOfBytes, f) < (size_t) numberOfBytes) throw MelderError ();   // read 16-bit data into last quarter of buffer
-						if (numberOfChannels == 1) {
+						} break;
+						case Melder_LINEAR_32_BIG_ENDIAN: {
 							for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
-								unsigned char byte1 = * bytes ++, byte2 = * bytes ++;
-								long value = (int16_t) (((uint16_t) byte2 << 8) | (uint16_t) byte1);
-								buffer [1] [isamp] = value * (1.0 / 32768);
+								unsigned char byte1 = * bytes ++, byte2 = * bytes ++, byte3 = * bytes ++, byte4 = * bytes ++;
+								int32_t value = (int32_t)
+									((uint32_t) ((uint32_t) byte1 << 24) |
+									 (uint32_t) ((uint32_t) byte2 << 16) |
+									 (uint32_t) ((uint32_t) byte3 << 8) |
+									             (uint32_t) byte4);
+								buffer [1] [isamp] = value * (1.0 / 32768 / 65536);
 							}
-						} else {
+						} break;
+						case Melder_LINEAR_32_LITTLE_ENDIAN: {
+							for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
+								unsigned char byte1 = * bytes ++, byte2 = * bytes ++, byte3 = * bytes ++, byte4 = * bytes ++;
+								int32_t value = (int32_t)
+									((uint32_t) ((uint32_t) byte4 << 24) |
+									 (uint32_t) ((uint32_t) byte3 << 16) |
+									 (uint32_t) ((uint32_t) byte2 << 8) |
+									             (uint32_t) byte1);
+								buffer [1] [isamp] = value * (1.0 / 32768 / 65536);
+							}
+						} break;
+					}
+				} else if (numberOfChannels <= (int) sizeof (double) / numberOfBytesPerSamplePerChannel) {
+					switch (encoding) {
+						case Melder_LINEAR_16_BIG_ENDIAN: {
 							for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
 								for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
 									unsigned char byte1 = * bytes ++, byte2 = * bytes ++;
-									long value = (int16_t) (((uint16_t) byte2 << 8) | (uint16_t) byte1);
+									int value = (int) (int16_t) (((uint16_t) byte1 << 8) | (uint16_t) byte2);
 									buffer [ichan] [isamp] = value * (1.0 / 32768);
 								}
 							}
-						}
-					}
-				} catch (MelderError) {
-					Melder_clearError ();
-					Melder_warning ("File too small (", numberOfChannels, "-channel 16-bit).\nMissing samples set to zero.");
-				}
-			} break;
-			case Melder_LINEAR_24_BIG_ENDIAN: {
-				try {
-					const int numberOfBytesPerSamplePerChannel = 3;
-					if (numberOfChannels > (int) sizeof (double) / numberOfBytesPerSamplePerChannel) {
-						for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
-							for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
-								buffer [ichan] [isamp] = bingeti3 (f) * (1.0 / 8388608);
+						} break;
+						case Melder_LINEAR_16_LITTLE_ENDIAN: {
+							for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
+								for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
+									uint8_t byte1 = * bytes ++, byte2 = * bytes ++;
+									int value = (int) (int16_t) (((uint16_t) byte2 << 8) | (uint16_t) byte1);
+									buffer [ichan] [isamp] = value * (1.0 / 32768);
+								}
 							}
-						}
-					} else { // optimize
-						long numberOfBytes = numberOfChannels * numberOfSamples * numberOfBytesPerSamplePerChannel;
-						unsigned char *bytes = (unsigned char *) & buffer [numberOfChannels] [numberOfSamples] + sizeof (double) - numberOfBytes;
-						if (fread (bytes, 1, numberOfBytes, f) < numberOfBytes) throw MelderError ();   // read 24-bit data into last three-eighths of buffer
-						if (numberOfChannels == 1) {
+						} break;
+						case Melder_LINEAR_24_BIG_ENDIAN: {
 							for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
-								unsigned char byte1 = * bytes ++, byte2 = * bytes ++, byte3 = * bytes ++;
-								uint32_t unsignedValue = ((uint32_t) byte1 << 16) | ((uint32_t) byte2 << 8) | (uint32_t) byte3;
-								if ((byte1 & 128) != 0) unsignedValue |= 0xFF000000;
-								buffer [1] [isamp] = (int32_t) unsignedValue * (1.0 / 8388608);
+								for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
+									unsigned char byte1 = * bytes ++, byte2 = * bytes ++, byte3 = * bytes ++;
+									uint32_t unsignedValue =
+										(uint32_t) ((uint32_t) byte1 << 16) |
+										(uint32_t) ((uint32_t) byte2 << 8) |
+										            (uint32_t) byte3;
+									if ((byte1 & 128) != 0) unsignedValue |= 0xFF000000;   // extend sign
+									buffer [ichan] [isamp] = (int32_t) unsignedValue * (1.0 / 8388608);
+								}
 							}
-						} else {
+						} break;
+						case Melder_LINEAR_24_LITTLE_ENDIAN: {
 							for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
 								for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
 									unsigned char byte1 = * bytes ++, byte2 = * bytes ++, byte3 = * bytes ++;
-									uint32_t unsignedValue = ((uint32_t) byte1 << 16) | ((uint32_t) byte2 << 8) | (uint32_t) byte3;
-									if ((byte1 & 128) != 0) unsignedValue |= 0xFF000000;
+									uint32_t unsignedValue = ((uint32_t) byte3 << 16) | ((uint32_t) byte2 << 8) | (uint32_t) byte1;
+									if ((byte3 & 128) != 0) unsignedValue |= 0xFF000000;
 									buffer [ichan] [isamp] = (int32_t) unsignedValue * (1.0 / 8388608);
 								}
 							}
-						}
+						} break;
+						case Melder_LINEAR_32_BIG_ENDIAN: {
+							for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
+								for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
+									unsigned char byte1 = * bytes ++, byte2 = * bytes ++, byte3 = * bytes ++, byte4 = * bytes ++;
+									int32_t value = (int32_t)
+										((uint32_t) ((uint32_t) byte1 << 24) |
+										 (uint32_t) ((uint32_t) byte2 << 16) |
+										 (uint32_t) ((uint32_t) byte3 << 8) |
+													 (uint32_t) byte4);
+									buffer [ichan] [isamp] = value * (1.0 / 32768 / 65536);
+								}
+							}
+						} break;
+						case Melder_LINEAR_32_LITTLE_ENDIAN: {
+							for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
+								for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
+									unsigned char byte1 = * bytes ++, byte2 = * bytes ++, byte3 = * bytes ++, byte4 = * bytes ++;
+									int32_t value = (int32_t)
+										((uint32_t) ((uint32_t) byte4 << 24) |
+										 (uint32_t) ((uint32_t) byte3 << 16) |
+										 (uint32_t) ((uint32_t) byte2 << 8) |
+													 (uint32_t) byte1);
+									buffer [ichan] [isamp] = value * (1.0 / 32768 / 65536);
+								}
+							}
+						} break;
 					}
-				} catch (MelderError) {
-					Melder_clearError ();
-					Melder_warning ("File too small (", numberOfChannels, "-channel 24-bit).\nMissing samples set to zero.");
-				}
-			} break;
-			case Melder_LINEAR_24_LITTLE_ENDIAN: {
-				try {
-					const int numberOfBytesPerSamplePerChannel = 3;
-					if (numberOfChannels > (int) sizeof (double) / numberOfBytesPerSamplePerChannel) {
-						for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
-							for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
-								buffer [ichan] [isamp] = bingeti3LE (f) * (1.0 / 8388608);
+				} else {
+					Melder_assert (sizeof (double) == 8);
+					int32_t *ints = (int32_t *) & buffer [1] [1];
+					switch (encoding) {
+						case Melder_LINEAR_16_BIG_ENDIAN: {
+							for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
+								for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
+									unsigned char byte1 = * bytes ++, byte2 = * bytes ++;
+									int32_t value = (int32_t)
+										(((uint32_t) byte1 << 24) |
+										 ((uint32_t) byte2 << 16));
+									* ints ++ = value;
+									* ints ++ = 0;   // the marker
+								}
 							}
-						}
-					} else { // optimize
-						long numberOfBytes = numberOfChannels * numberOfSamples * numberOfBytesPerSamplePerChannel;
-						unsigned char *bytes = (unsigned char *) & buffer [numberOfChannels] [numberOfSamples] + sizeof (double) - numberOfBytes;
-						if (fread (bytes, 1, numberOfBytes, f) < numberOfBytes) throw MelderError ();   // read 24-bit data into last three-eighths of buffer
-						if (numberOfChannels == 1) {
+						} break;
+						case Melder_LINEAR_16_LITTLE_ENDIAN: {
 							for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
-								unsigned char byte1 = * bytes ++, byte2 = * bytes ++, byte3 = * bytes ++;
-								uint32_t unsignedValue = ((uint32_t) byte3 << 16) | ((uint32_t) byte2 << 8) | (uint32_t) byte1;
-								if ((byte3 & 128) != 0) unsignedValue |= 0xFF000000;
-								buffer [1] [isamp] = (int32_t) unsignedValue * (1.0 / 8388608);
+								for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
+									unsigned char byte1 = * bytes ++, byte2 = * bytes ++;
+									int32_t value = (int32_t)
+										(((uint32_t) byte2 << 24) |
+										 ((uint32_t) byte1 << 16));
+									* ints ++ = value;
+									* ints ++ = 0;   // the marker
+								}
 							}
-						} else {
+						} break;
+						case Melder_LINEAR_24_BIG_ENDIAN: {
 							for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
 								for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
 									unsigned char byte1 = * bytes ++, byte2 = * bytes ++, byte3 = * bytes ++;
-									uint32_t unsignedValue = ((uint32_t) byte3 << 16) | ((uint32_t) byte2 << 8) | (uint32_t) byte1;
-									if ((byte3 & 128) != 0) unsignedValue |= 0xFF000000;
-									buffer [ichan] [isamp] = (int32_t) unsignedValue * (1.0 / 8388608);
+									int32_t value = (int32_t)
+										(((uint32_t) byte1 << 24) |
+										 ((uint32_t) byte2 << 16) |
+										 ((uint32_t) byte3 << 8));
+									* ints ++ = value;
+									* ints ++ = 0;   // the marker
+								}
+							}
+						} break;
+						case Melder_LINEAR_24_LITTLE_ENDIAN: {
+							for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
+								for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
+									unsigned char byte1 = * bytes ++, byte2 = * bytes ++, byte3 = * bytes ++;
+									int32_t value = (int32_t)
+										(((uint32_t) byte3 << 24) |
+										 ((uint32_t) byte2 << 16) |
+										 ((uint32_t) byte1 << 8));
+									* ints ++ = value;
+									* ints ++ = 0;   // the marker
+								}
+							}
+						} break;
+						case Melder_LINEAR_32_BIG_ENDIAN: {
+							for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
+								for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
+									unsigned char byte1 = * bytes ++, byte2 = * bytes ++, byte3 = * bytes ++, byte4 = * bytes ++;
+									int32_t value = (int32_t)
+										(((uint32_t) byte1 << 24) |
+										 ((uint32_t) byte2 << 16) |
+										 ((uint32_t) byte3 << 8) |
+										  (uint32_t) byte4);
+									* ints ++ = value;
+									* ints ++ = 0;   // the marker
+								}
+							}
+						} break;
+						case Melder_LINEAR_32_LITTLE_ENDIAN: {
+							for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
+								for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
+									unsigned char byte1 = * bytes ++, byte2 = * bytes ++, byte3 = * bytes ++, byte4 = * bytes ++;
+									int32_t value = (int32_t)
+										(((uint32_t) byte4 << 24) |
+										 ((uint32_t) byte3 << 16) |
+										 ((uint32_t) byte2 << 8) |
+										  (uint32_t) byte1);
+									* ints ++ = value;
+									* ints ++ = 0;   // the marker
 								}
 							}
 						}
 					}
-				} catch (MelderError) {
-					Melder_clearError ();
-					Melder_warning ("File too small (", numberOfChannels, "-channel 24-bit).\nMissing samples set to zero.");
-				}
-			} break;
-			case Melder_LINEAR_32_BIG_ENDIAN:
-				try {
-					for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
-						for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
-							buffer [ichan] [isamp] = bingeti4 (f) * (1.0 / 32768 / 65536);
+					double *doubles = & buffer [1] [1];
+					long n = numberOfSamples * numberOfChannels;
+					for (long i = 0; i < n; i ++) {
+						int32_t *valuePosition = (int32_t *) & doubles [i];
+						int32_t *markerPosition = valuePosition + 1;
+						if (! *markerPosition) {
+							int32_t value = *valuePosition;
+							long ichan = i / numberOfSamples, isamp = i % numberOfSamples;
+							for (long other = isamp * numberOfChannels + ichan; other != i; ) {
+								int32_t *otherValuePosition = (int32_t *) & doubles [other];
+								*valuePosition = *otherValuePosition;
+								*markerPosition = 1;
+								valuePosition = otherValuePosition;
+								markerPosition = valuePosition + 1;
+								ichan = other / numberOfSamples, isamp = other % numberOfSamples;
+								other = isamp * numberOfChannels + ichan;
+							}
+							*valuePosition = value;
+							*markerPosition = 1;
 						}
 					}
-				} catch (MelderError) {
-					Melder_clearError ();
-					Melder_warning ("File too small (", numberOfChannels, "-channel 32-bit).\nMissing samples set to zero.");
-				}
-				break;
-			case Melder_LINEAR_32_LITTLE_ENDIAN:
-				try {
 					for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
 						for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
-							buffer [ichan] [isamp] = bingeti4LE (f) * (1.0 / 32768 / 65536);
+							buffer [ichan] [isamp] = * (int32_t *) & buffer [ichan] [isamp] * (1.0 / 32768 / 65536);
 						}
 					}
-				} catch (MelderError) {
-					Melder_clearError ();
-					Melder_warning ("File too small (", numberOfChannels, "-channel 32-bit).\nMissing samples set to zero.");
 				}
-				break;
+				if (numberOfBytesRead < numberOfBytes)
+					Melder_warning ("File too small (", numberOfChannels, "-channel ", numberOfBytesPerSamplePerChannel * 8, "-bit).\n"
+						"Missing samples were set to zero.");
+			} break;
 			case Melder_IEEE_FLOAT_32_BIG_ENDIAN:
 				try {
 					for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
@@ -1302,60 +1407,60 @@ void MelderFile_writeFloatToAudio (MelderFile file, int numberOfChannels, int en
 			case Melder_LINEAR_8_SIGNED:
 				for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
 					for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
-						long value = round (buffer [ichan] [isamp] * 128);
-						if (value < -128) { value = -128; nclipped ++; }
-						if (value > 127) { value = 127; nclipped ++; }
-						binputi1 (value, f);
+						double value = round (buffer [ichan] [isamp] * 128.0);
+						if (value < -128.0) { value = -128.0; nclipped ++; }
+						if (value > 127.0) { value = 127.0; nclipped ++; }
+						binputi1 ((int) value, f);
 					}
 				}
 				break;
 			case Melder_LINEAR_8_UNSIGNED:
 				for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
 					for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
-						long value = floor ((buffer [ichan] [isamp] + 1.0) * 128);
-						if (value < 0) { value = 0; nclipped ++; }
-						if (value > 255) { value = 255; nclipped ++; }
-						binputu1 (value, f);
+						double value = floor ((buffer [ichan] [isamp] + 1.0) * 128.0);
+						if (value < 0.0) { value = 0.0; nclipped ++; }
+						if (value > 255.0) { value = 255.0; nclipped ++; }
+						binputu1 ((int) value, f);
 					}
 				}
 				break;
 			case Melder_LINEAR_16_BIG_ENDIAN:
 				for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
 					for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
-						long value = round (buffer [ichan] [isamp] * 32768);
-						if (value < -32768) { value = -32768; nclipped ++; }
-						if (value > 32767) { value = 32767; nclipped ++; }
-						binputi2 (value, f);
+						double value = round (buffer [ichan] [isamp] * 32768.0);
+						if (value < -32768.0) { value = -32768.0; nclipped ++; }
+						if (value > 32767.0) { value = 32767.0; nclipped ++; }
+						binputi2 ((int16) value, f);
 					}
 				}
 				break;
 			case Melder_LINEAR_16_LITTLE_ENDIAN:
 				for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
 					for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
-						long value = round (buffer [ichan] [isamp] * 32768);
-						if (value < -32768) { value = -32768; nclipped ++; }
-						if (value > 32767) { value = 32767; nclipped ++; }
-						binputi2LE (value, f);
+						double value = round (buffer [ichan] [isamp] * 32768.0);
+						if (value < -32768.0) { value = -32768.0; nclipped ++; }
+						if (value > 32767.0) { value = 32767.0; nclipped ++; }
+						binputi2LE ((int16) value, f);
 					}
 				}
 				break;
 			case Melder_LINEAR_24_BIG_ENDIAN:
 				for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
 					for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
-						long value = round (buffer [ichan] [isamp] * 8388608);
-						if (value < -8388608) { value = -8388608; nclipped ++; }
-						if (value > 8388607) { value = 8388607; nclipped ++; }
-						binputi3 (value, f);
+						double value = round (buffer [ichan] [isamp] * 8388608.0);
+						if (value < -8388608.0) { value = -8388608.0; nclipped ++; }
+						if (value > 8388607.0) { value = 8388607.0; nclipped ++; }
+						binputi3 ((int32) value, f);
 					}
 				}
 				break;
 			case Melder_LINEAR_24_LITTLE_ENDIAN:
 				for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
 					for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
-						long value = round (buffer [ichan] [isamp] * 8388608);
-						if (value < -8388608) { value = -8388608; nclipped ++; }
-						if (value > 8388607) { value = 8388607; nclipped ++; }
-						binputi3LE (value, f);
+						double value = round (buffer [ichan] [isamp] * 8388608.0);
+						if (value < -8388608.0) { value = -8388608.0; nclipped ++; }
+						if (value > 8388607.0) { value = 8388607.0; nclipped ++; }
+						binputi3LE ((int32) value, f);
 					}
 				}
 				break;
@@ -1365,7 +1470,7 @@ void MelderFile_writeFloatToAudio (MelderFile file, int numberOfChannels, int en
 						double value = round (buffer [ichan] [isamp] * 2147483648.0);
 						if (value < -2147483648.0) { value = -2147483648.0; nclipped ++; }
 						if (value > 2147483647.0) { value = 2147483647.0; nclipped ++; }
-						binputi4 (value, f);
+						binputi4 ((int32) value, f);   // safe cast: rounding and range already handled
 					}
 				}
 				break;
@@ -1375,7 +1480,7 @@ void MelderFile_writeFloatToAudio (MelderFile file, int numberOfChannels, int en
 						double value = round (buffer [ichan] [isamp] * 2147483648.0);
 						if (value < -2147483648.0) { value = -2147483648.0; nclipped ++; }
 						if (value > 2147483647.0) { value = 2147483647.0; nclipped ++; }
-						binputi4LE (value, f);
+						binputi4LE ((int32) value, f);
 					}
 				}
 				break;
@@ -1403,9 +1508,9 @@ void MelderFile_writeFloatToAudio (MelderFile file, int numberOfChannels, int en
 				for (long isamp = 1; isamp <= numberOfSamples; isamp ++) {
 					FLAC__int32 samples [FLAC__MAX_CHANNELS];
 					for (long ichan = 1; ichan <= numberOfChannels; ichan ++) {
-						long value = round (buffer [ichan] [isamp] * 32768);
-						if (value < -32768) { value = -32768; nclipped ++; }
-						if (value > 32767) { value = 32767; nclipped ++; }
+						double value = round (buffer [ichan] [isamp] * 32768.0);
+						if (value < -32768.0) { value = -32768.0; nclipped ++; }
+						if (value > 32767.0) { value = 32767.0; nclipped ++; }
 						samples [ichan - 1] = (FLAC__int32) value;
 					}
 					if (! FLAC__stream_encoder_process_interleaved (file -> flacEncoder, samples, 1))
diff --git a/sys/melder_debug.cpp b/sys/melder_debug.cpp
index ac78833..42bd9ea 100644
--- a/sys/melder_debug.cpp
+++ b/sys/melder_debug.cpp
@@ -1,6 +1,6 @@
 /* melder_debug.cpp
  *
- * Copyright (C) 2000-2012,2014 Paul Boersma
+ * Copyright (C) 2000-2012,2014,2015 Paul Boersma
  *
  * 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
@@ -81,18 +81,18 @@ the behaviour of that program changes in the following way:
 
 */
 
-static bool theTracing = false;
+bool Melder_isTracing = false;
 static structMelderFile theTracingFile = { 0 };
 
 #ifdef linux
 static void theGtkLogHandler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer unused_data) {
-	Melder_trace_ (NULL, 0, "GTK", "%s", message);
+	Melder_trace_FMT (NULL, 0, "GTK", "%s", message);
 }
 static void theGlibLogHandler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer unused_data) {
-	Melder_trace_ (NULL, 0, "GLib", "%s", message);
+	Melder_trace_FMT (NULL, 0, "GLib", "%s", message);
 }
 static void theGlibGobjectLogHandler (const gchar *log_domain, GLogLevelFlags log_level, const gchar *message, gpointer unused_data) {
-	Melder_trace_ (NULL, 0, "GLib-GObject", "%s", message);
+	Melder_trace_FMT (NULL, 0, "GLib-GObject", "%s", message);
 }
 #endif
 
@@ -102,7 +102,7 @@ void Melder_setTracing (bool tracing) {
 	#define str(s) #s
 	if (! tracing)
 		trace ("switch tracing off in Praat version %s at %s", xstr (PRAAT_VERSION_STR), ctime (& today));
-	theTracing = tracing;
+	Melder_isTracing = tracing;
 	#ifdef linux
 		static guint handler_id1, handler_id2, handler_id3;
 		if (tracing) {
@@ -120,17 +120,13 @@ void Melder_setTracing (bool tracing) {
 		trace ("switch tracing on in Praat version %s at %s", xstr (PRAAT_VERSION_STR), ctime (& today));
 }
 
-bool Melder_getTracing () {
-	return theTracing;
-}
-
 void Melder_tracingToFile (MelderFile file) {
 	MelderFile_copy (file, & theTracingFile);
 	MelderFile_delete (& theTracingFile);
 }
 
-void Melder_trace_ (const char *fileName, int lineNumber, const char *functionName, const char *format, ...) {
-	if (! theTracing || MelderFile_isNull (& theTracingFile)) return;
+void Melder_trace_FMT (const char *fileName, int lineNumber, const char *functionName, const char *format, ...) {
+	if (! Melder_isTracing || MelderFile_isNull (& theTracingFile)) return;
 	try {
 		FILE *f = Melder_fopen (& theTracingFile, "a");
 		if (fileName) {
diff --git a/sys/melder_files.cpp b/sys/melder_files.cpp
index 28ded40..05c4c04 100644
--- a/sys/melder_files.cpp
+++ b/sys/melder_files.cpp
@@ -101,15 +101,15 @@ void Melder_wcsTo8bitFileRepresentation_inline (const wchar_t *wcs, char *utf8)
 			So we first convert to UTF-16, then turn into CFString, then decompose, then convert to UTF-8.
 		*/
 		UniChar unipath [kMelder_MAXPATH+1];
-		long n = wcslen (wcs), n_utf16 = 0;
-		for (long i = 0; i < n; i ++) {
-			utf32_t kar = wcs [i];
-			if (kar <= 0xFFFF) {
-				unipath [n_utf16 ++] = kar;   // including null byte
+		size_t n = wcslen (wcs), n_utf16 = 0;
+		for (size_t i = 0; i < n; i ++) {
+			char32_t kar = (char32_t) wcs [i];   // change sign (bit 32 is never used)
+			if (kar <= 0x00FFFF) {
+				unipath [n_utf16 ++] = (UniChar) kar;   // including null byte; guarded truncation
 			} else if (kar <= 0x10FFFF) {
-				kar -= 0x10000;
-				unipath [n_utf16 ++] = 0xD800 | (kar >> 10);
-				unipath [n_utf16 ++] = 0xDC00 | (kar & 0x3FF);
+				kar -= 0x010000;
+				unipath [n_utf16 ++] = (UniChar) (0x00D800 | (kar >> 10));   // correct truncation, because UTF-32 has fewer than 27 bits (in fact it has 21 bits)
+				unipath [n_utf16 ++] = (UniChar) (0x00DC00 | (kar & 0x0003FF));
 			} else {
 				unipath [n_utf16 ++] = UNICODE_REPLACEMENT_CHARACTER;
 			}
@@ -137,16 +137,16 @@ void Melder_8bitFileRepresentationToWcs_inline (const char *path, wchar_t *wpath
 		long n_utf16 = CFStringGetLength (cfpath2);
 		long n_wcs = 0;
 		for (long i = 0; i < n_utf16; i ++) {
-			utf32_t kar = CFStringGetCharacterAtIndex (cfpath2, i);
-			if (kar >= 0xD800 && kar <= 0xDBFF) {
-				utf32_t kar2 = CFStringGetCharacterAtIndex (cfpath2, ++ i);
-				if (kar2 >= 0xDC00 && kar2 <= 0xDFFF) {
-					kar = (((kar & 0x3FF) << 10) | (kar2 & 0x3FF)) + 0x10000;
+			char32_t kar1 = CFStringGetCharacterAtIndex (cfpath2, i);
+			if (kar1 >= 0x00D800 && kar1 <= 0x00DBFF) {
+				char32_t kar2 = (char32_t) CFStringGetCharacterAtIndex (cfpath2, ++ i);   // convert up
+				if (kar2 >= 0x00DC00 && kar2 <= 0x00DFFF) {
+					kar1 = (((kar1 & 0x3FF) << 10) | (kar2 & 0x3FF)) + 0x10000;
 				} else {
-					kar = UNICODE_REPLACEMENT_CHARACTER;
+					kar1 = UNICODE_REPLACEMENT_CHARACTER;
 				}
 			}
-			wpath [n_wcs ++] = kar;
+			wpath [n_wcs ++] = (wchar_t) kar1;
 		}
 		wpath [n_wcs] = '\0';
 		CFRelease (cfpath2);
@@ -535,7 +535,7 @@ static size_t read_URL_data_from_file (void *buffer, size_t size, size_t nmemb,
 #endif
 
 FILE * Melder_fopen (MelderFile file, const char *type) {
-	if (! Melder_getTracing())
+	if (! Melder_isTracing)
 		Melder_assert (wcsequ (Melder_double (1.5), L"1.5"));   // check locale settings; because of the required file portability Praat cannot stand "1,5"
 	/*
 	 * On the Unix-like systems (including MacOS), the path has to be converted to 8-bit characters in UTF-8 encoding.
diff --git a/sys/melder_ftoa.cpp b/sys/melder_ftoa.cpp
index 411de42..7161b95 100644
--- a/sys/melder_ftoa.cpp
+++ b/sys/melder_ftoa.cpp
@@ -31,7 +31,7 @@
  * pb 2008/01/06 Mac: use strtod instead of wcstod for speed
  * pb 2010/10/16 Melder_naturalLogarithm
  * pb 2011/04/05 C++
- * pb 2014/01/09 use fabs in the calculating minimum precision
+ * pb 2014/01/09 use fabs in calculating minimum precision
  */
 
 #include "melder.h"
@@ -41,8 +41,8 @@
 
 #define NUMBER_OF_BUFFERS  32
 	/* = maximum number of arguments to a function call */
-#define MAXIMUM_NUMERIC_STRING_LENGTH  386
-	/* = sign + 308 + point + 60 + e + sign + 3 + null byte + (\.c10^^ - 1) + 4 extra */
+#define MAXIMUM_NUMERIC_STRING_LENGTH  400
+	/* = sign + 324 + point + 60 + e + sign + 3 + null byte + ("·10^^" - "e") + 4 extra */
 
 static wchar_t buffers [NUMBER_OF_BUFFERS] [MAXIMUM_NUMERIC_STRING_LENGTH + 1];
 static int ibuffer = 0;
@@ -52,7 +52,29 @@ const wchar_t * Melder_integer (int64_t value) {
 	if (sizeof (long) == 8) {
 		swprintf (buffers [ibuffer], MAXIMUM_NUMERIC_STRING_LENGTH, L"%ld", value);
 	} else if (sizeof (long long) == 8) {
-		swprintf (buffers [ibuffer], MAXIMUM_NUMERIC_STRING_LENGTH, L"%lld", value);
+		/*
+		 * There are buggy platforms (namely 32-bit Mingw on Windows XP) that support long long and %lld but that convert
+		 * the argument to a 32-bit long.
+		 * There are also buggy platforms (namely 32-bit gcc on Linux) that support long long and %I64d but that convert
+		 * the argument to a 32-bit long.
+		 */
+		static const wchar_t *formatString = NULL;
+		if (! formatString) {
+			wchar_t tryBuffer [MAXIMUM_NUMERIC_STRING_LENGTH + 1];
+			swprintf (tryBuffer, MAXIMUM_NUMERIC_STRING_LENGTH, L"%lld", 1000000000000LL);
+			if (wcsequ (tryBuffer, L"1000000000000")) {
+				formatString = L"%lld";
+			} else {
+				swprintf (tryBuffer, MAXIMUM_NUMERIC_STRING_LENGTH, L"%I64d", 1000000000000LL);
+				if (wcsequ (tryBuffer, L"1000000000000")) {
+					formatString = L"%I64d";
+				} else {
+					wprintf (tryBuffer);
+					Melder_fatal ("Found no way to print 64-bit integers.");
+				}
+			}
+		}
+		swprintf (buffers [ibuffer], MAXIMUM_NUMERIC_STRING_LENGTH, formatString, value);
 	} else {
 		Melder_fatal ("Neither long nor long long is 8 bytes on this machine.");
 	}
@@ -214,12 +236,12 @@ const wchar_t * Melder_float (const wchar_t *number) {
 		if (number [0] == '1' && number [1] == 'e') {
 			wcscpy (buffers [ibuffer], L"10^^"); b = buffers [ibuffer] + 4;
 		} else {
-			wcscat (buffers [ibuffer], L"\\.c10^^"); b += 7;
+			wcscat (buffers [ibuffer], L"·10^^"); b += 7;
 		}
 		Melder_assert (*n == 'e');
-		if (*++n == '+') n ++;   /* Ignore leading plus sign in exponent. */
-		if (*n == '-') *(b++) = *(n++);   /* Copy sign of negative exponent. */
-		while (*n == '0') n ++;   /* Ignore leading zeroes in exponent. */
+		if (*++n == '+') n ++;   // ignore leading plus sign in exponent
+		if (*n == '-') *(b++) = *(n++);   // copy sign of negative exponent
+		while (*n == '0') n ++;   // ignore leading zeroes in exponent
 		while (*n >= '0' && *n <= '9') *(b++) = *(n++);
 		*(b++) = '^';
 		while (*n != '\0') *(b++) = *(n++); *b = '\0';
diff --git a/sys/melder_readtext.cpp b/sys/melder_readtext.cpp
index aa88101..a1852d5 100644
--- a/sys/melder_readtext.cpp
+++ b/sys/melder_readtext.cpp
@@ -37,28 +37,32 @@ wchar_t MelderReadText_getChar (MelderReadText me) {
 	} else {
 		if (* my readPointer8 == '\0') return 0;
 		if (my input8Encoding == kMelder_textInputEncoding_UTF8) {
-			utf32_t kar = * (unsigned char *) my readPointer8 ++;
-			if (kar <= 0x7F) {
-				return kar;
-			} else if (kar <= 0xDF) {
-				utf32_t kar2 = * (unsigned char *) my readPointer8 ++;
-				return ((kar & 0x1F) << 6) | (kar2 & 0x3F);
-			} else if (kar <= 0xEF) {
-				utf32_t kar2 = * (unsigned char *) my readPointer8 ++;
-				utf32_t kar3 = * (unsigned char *) my readPointer8 ++;
-				return ((kar & 0x0F) << 12) | ((kar2 & 0x3F) << 6) | (kar3 & 0x3F);
-			} else if (kar <= 0xF4) {
-				utf32_t kar2 = * (unsigned char *) my readPointer8 ++;
-				utf32_t kar3 = * (unsigned char *) my readPointer8 ++;
-				utf32_t kar4 = * (unsigned char *) my readPointer8 ++;
-				return ((kar & 0x07) << 18) | ((kar2 & 0x3F) << 12) | ((kar3 & 0x3F) << 6) | (kar4 & 0x3F);   // BUG: should be UTF-16 on Windows
+			char32_t kar1 = * (char8_t *) my readPointer8 ++;
+			if (kar1 <= 0x7F) {
+				return kar1;
+			} else if (kar1 <= 0xDF) {
+				char32_t kar2 = * (char8_t *) my readPointer8 ++;
+				return ((kar1 & 0x1F) << 6) | (kar2 & 0x3F);
+			} else if (kar1 <= 0xEF) {
+				char32_t kar2 = * (char8_t *) my readPointer8 ++;
+				char32_t kar3 = * (char8_t *) my readPointer8 ++;
+				return ((kar1 & 0x0F) << 12) | ((kar2 & 0x3F) << 6) | (kar3 & 0x3F);
+			} else if (kar1 <= 0xF4) {
+				char32_t kar2 = * (char8_t *) my readPointer8 ++;
+				char32_t kar3 = * (char8_t *) my readPointer8 ++;
+				char32_t kar4 = * (char8_t *) my readPointer8 ++;
+				return ((kar1 & 0x07) << 18) | ((kar2 & 0x3F) << 12) | ((kar3 & 0x3F) << 6) | (kar4 & 0x3F);   // BUG: should be UTF-16 on Windows
+			} else {
+				return UNICODE_REPLACEMENT_CHARACTER;
 			}
 		} else if (my input8Encoding == kMelder_textInputEncoding_MACROMAN) {
 			return Melder_decodeMacRoman [* (unsigned char *) my readPointer8 ++];
 		} else if (my input8Encoding == kMelder_textInputEncoding_WINDOWS_LATIN1) {
 			return Melder_decodeWindowsLatin1 [* (unsigned char *) my readPointer8 ++];
+		} else {
+			/* Unknown encoding. */
+			return * (char8_t *) my readPointer8 ++;
 		}
-		return * (unsigned char *) my readPointer8 ++;
 	}
 }
 
@@ -180,8 +184,8 @@ static wchar_t * _MelderFile_readText (MelderFile file, char **string8) {
 			rewind (f);   // length and type already set correctly.
 			autostring8 text8bit = Melder_malloc (char, length + 1);
 			Melder_assert (text8bit.peek() != NULL);
-			int64_t numberOfBytesRead = fread_multi (text8bit.peek(), length, f);
-			if (numberOfBytesRead < length)
+			size_t numberOfBytesRead = fread_multi (text8bit.peek(), (size_t) length, f);
+			if ((int64_t) numberOfBytesRead < length)
 				Melder_throw ("The file contains ", (double) length, " bytes, but we could read only ",
 					(double) numberOfBytesRead, " of them.");
 			text8bit [length] = '\0';
@@ -217,49 +221,51 @@ static wchar_t * _MelderFile_readText (MelderFile file, char **string8) {
 			text.reset (Melder_malloc (wchar_t, length + 1));
 			if (type == 1) {
 				for (int64_t i = 0; i < length; i ++) {
-					utf16_t kar = bingetu2 (f);
+					char16_t kar1 = bingetu2 (f);
 					if (sizeof (wchar_t) == 2) {   // wchar_t is UTF-16 (or its signed counterpart)?
-						text [i] = (wchar_t) kar;
+						text [i] = (wchar_t) kar1;
 					} else {   // wchar_t is UTF-32 (or its signed counterpart)
-						if (kar < 0xD800) {
-							text [i] = (wchar_t) kar;   // convert up without sign extension
-						} else if (kar < 0xDC00) {
+						if (kar1 < 0xD800) {
+							text [i] = (wchar_t) kar1;   // convert up without sign extension
+						} else if (kar1 < 0xDC00) {
 							length --;
-							utf16_t kar2 = bingetu2 (f);
+							char16_t kar2 = bingetu2 (f);
 							if (kar2 >= 0xDC00 && kar2 <= 0xDFFF) {
-								text [i] = (wchar_t) (0x00010000 + (uint32_t) (((uint32_t) kar & 0x000003FF) << 10) + (uint32_t) ((uint32_t) kar2 & 0x000003FF));
+								text [i] = (wchar_t) (0x00010000 +
+									(uint32_t) (((uint32_t) kar1 & 0x000003FF) << 10) +
+									(uint32_t)  ((uint32_t) kar2 & 0x000003FF));
 							} else {
 								text [i] = UNICODE_REPLACEMENT_CHARACTER;
 							}
-						} else if (kar < 0xE000) {
+						} else if (kar1 < 0xE000) {
 							text [i] = UNICODE_REPLACEMENT_CHARACTER;
-						} else if (kar <= 0xFFFF) {
-							text [i] = (wchar_t) kar;   // convert up without sign extension
 						} else {
-							Melder_fatal ("MelderFile_readText: unsigned short greater than 0xFFFF: should not occur.");
+							text [i] = (wchar_t) kar1;   // convert up without sign extension
 						}
 					}
 				}
 			} else {
 				for (int64_t i = 0; i < length; i ++) {
-					utf16_t kar = bingetu2LE (f);
+					char16_t kar1 = bingetu2LE (f);
 					if (sizeof (wchar_t) == 2) {   // wchar_t is UTF-16 (or its signed counterpart)?
-						text [i] = (wchar_t) kar;
+						text [i] = (wchar_t) kar1;
 					} else {   // wchar_t is UTF-32 (or its signed counterpart)
-						if (kar < 0xD800) {
-							text [i] = (wchar_t) kar;   // convert up without sign extension
-						} else if (kar < 0xDC00) {
+						if (kar1 < 0xD800) {
+							text [i] = (wchar_t) kar1;   // convert up without sign extension
+						} else if (kar1 < 0xDC00) {
 							length --;
-							utf16_t kar1 = bingetu2LE (f);
-							if (kar1 >= 0xDC00 && kar1 <= 0xDFFF) {
-								text [i] = (wchar_t) (0x00010000 + (uint32_t) (((uint32_t) kar & 0x000003FF) << 10) + (uint32_t) ((uint32_t) kar1 & 0x000003FF));
+							char16_t kar2 = bingetu2LE (f);
+							if (kar2 >= 0xDC00 && kar2 <= 0xDFFF) {
+								text [i] = (wchar_t) (0x00010000 +
+									(uint32_t) (((uint32_t) kar1 & 0x000003FF) << 10) +
+									(uint32_t)  ((uint32_t) kar2 & 0x000003FF));
 							} else {
 								text [i] = UNICODE_REPLACEMENT_CHARACTER;
 							}
-						} else if (kar < 0xE000) {
+						} else if (kar1 < 0xE000) {
 							text [i] = UNICODE_REPLACEMENT_CHARACTER;
-						} else if (kar <= 0xFFFF) {
-							text [i] = (wchar_t) kar;   // convert up without sign extension
+						} else if (kar1 <= 0xFFFF) {
+							text [i] = (wchar_t) kar1;   // convert up without sign extension
 						} else {
 							Melder_fatal ("MelderFile_readText: unsigned short greater than 0xFFFF: should not occur.");
 						}
diff --git a/sys/melder_strings.cpp b/sys/melder_strings.cpp
index 2e56d22..5b38a98 100644
--- a/sys/melder_strings.cpp
+++ b/sys/melder_strings.cpp
@@ -1,6 +1,6 @@
 /* melder_strings.cpp
  *
- * Copyright (C) 2006-2011 Paul Boersma
+ * Copyright (C) 2006-2011,2015 Paul Boersma
  *
  * 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
@@ -20,16 +20,16 @@
 #include "melder.h"
 #include "UnicodeData.h"
 #define my  me ->
-#define FREE_THRESHOLD_BYTES 10000
+#define FREE_THRESHOLD_BYTES 10000LL
 
 static double totalNumberOfAllocations = 0, totalNumberOfDeallocations = 0, totalAllocationSize = 0, totalDeallocationSize = 0;
 
 void MelderString_free (MelderString *me) {
 	if (my string == NULL) return;
 	Melder_free (my string);
-	if (Melder_debug == 34) fprintf (stderr, "from MelderString_free\t%p\t%ld\t%ld\n", my string, my bufferSize, sizeof (wchar_t));
+	if (Melder_debug == 34) fprintf (stderr, "from MelderString_free\t%p\t%lld\t%d\n", my string, (long long) my bufferSize, (int) sizeof (wchar_t));
 	totalNumberOfDeallocations += 1;
-	totalDeallocationSize += my bufferSize * sizeof (wchar_t);
+	totalDeallocationSize += my bufferSize * (int64_t) sizeof (wchar_t);
 	my bufferSize = 0;
 	my length = 0;
 }
@@ -37,9 +37,9 @@ void MelderString_free (MelderString *me) {
 void MelderString16_free (MelderString16 *me) {
 	if (my string == NULL) return;
 	Melder_free (my string);
-	if (Melder_debug == 34) fprintf (stderr, "from MelderString16_free\t%p\t%ld\t%ld\n", my string, my bufferSize, 2L);
+	if (Melder_debug == 34) fprintf (stderr, "from MelderString16_free\t%p\t%lld\t%d\n", my string, (long long) my bufferSize, 2);
 	totalNumberOfDeallocations += 1;
-	totalDeallocationSize += my bufferSize * sizeof (utf16_t);
+	totalDeallocationSize += my bufferSize * (int64_t) sizeof (char16_t);
 	my bufferSize = 0;
 	my length = 0;
 }
@@ -48,16 +48,16 @@ void MelderString16_free (MelderString16 *me) {
 	if (sizeNeeded > my bufferSize) { \
 		Melder_assert (my bufferSize >= 0); \
 		Melder_assert (sizeNeeded >= 0); \
-		sizeNeeded = 1.618034 * sizeNeeded + 100; \
+		sizeNeeded = (int64) (1.618034 * sizeNeeded) + 100; \
 		Melder_assert (sizeNeeded > 0); \
 		if (my string) { \
 			totalNumberOfDeallocations += 1; \
-			totalDeallocationSize += my bufferSize * sizeof (type); \
+			totalDeallocationSize += my bufferSize * (int64) sizeof (type); \
 		} \
-		long bytesNeeded = sizeNeeded * sizeof (type); \
+		int64 bytesNeeded = sizeNeeded * (int64) sizeof (type); \
 		Melder_assert (bytesNeeded > 0); \
 		try { \
-			if (Melder_debug == 34) fprintf (stderr, "from MelderString:expandIfNecessary\t%p\t%ld\t%ld\n", my string, sizeNeeded, sizeof (type)); \
+			if (Melder_debug == 34) fprintf (stderr, "from MelderString:expandIfNecessary\t%p\t%lld\t%d\n", my string, (long long) sizeNeeded, (int) sizeof (type)); \
 			my string = (type *) Melder_realloc (my string, bytesNeeded); \
 		} catch (MelderError) { \
 			my bufferSize = 0; \
@@ -70,54 +70,54 @@ void MelderString16_free (MelderString16 *me) {
 	}
 
 void MelderString_empty (MelderString *me) {
-	if (my bufferSize * sizeof (wchar_t) >= FREE_THRESHOLD_BYTES) {
+	if (my bufferSize * (int64) sizeof (wchar) >= FREE_THRESHOLD_BYTES) {
 		MelderString_free (me);
 	}
-	unsigned long sizeNeeded = 1;
-	expandIfNecessary (wchar_t)
+	int64 sizeNeeded = 1;
+	expandIfNecessary (wchar)
 	my string [0] = '\0';
 	my length = 0;
 }
 
 void MelderString16_empty (MelderString16 *me) {
-	if (my bufferSize * sizeof (wchar_t) >= FREE_THRESHOLD_BYTES) {
+	if (my bufferSize * (int64) sizeof (wchar) >= FREE_THRESHOLD_BYTES) {
 		MelderString16_free (me);
 	}
-	unsigned long sizeNeeded = 1;
-	expandIfNecessary (utf16_t)
+	int64_t sizeNeeded = 1;
+	expandIfNecessary (char16)
 	my string [0] = '\0';
 	my length = 0;
 }
 
 void MelderString_copy (MelderString *me, const wchar_t *source) {
-	if (my bufferSize * sizeof (wchar_t) >= FREE_THRESHOLD_BYTES)
+	if (my bufferSize * (int64) sizeof (wchar) >= FREE_THRESHOLD_BYTES)
 		MelderString_free (me);
 	if (source == NULL) source = L"";
-	unsigned long length = wcslen (source);
-	unsigned long sizeNeeded = length + 1;
-	expandIfNecessary (wchar_t)
+	int64 length = (int64) wcslen (source);
+	int64 sizeNeeded = length + 1;
+	expandIfNecessary (wchar)
 	wcscpy (my string, source);
 	my length = length;
 }
 
-void MelderString_ncopy (MelderString *me, const wchar_t *source, unsigned long n) {
-	if (my bufferSize * sizeof (wchar_t) >= FREE_THRESHOLD_BYTES)
+void MelderString_ncopy (MelderString *me, const wchar_t *source, int64 n) {
+	if (my bufferSize * (int64) sizeof (wchar_t) >= FREE_THRESHOLD_BYTES)
 		MelderString_free (me);
 	if (source == NULL) source = L"";
-	unsigned long length = wcslen (source);
+	int64 length = (int64) wcslen (source);
 	if (length > n) length = n;
-	unsigned long sizeNeeded = length + 1;
-	expandIfNecessary (wchar_t)
-	wcsncpy (my string, source, length);
+	int64 sizeNeeded = length + 1;
+	expandIfNecessary (wchar)
+	wcsncpy (my string, source, (size_t) length);
 	my string [length] = '\0';
 	my length = length;
 }
 
 void MelderString_append (MelderString *me, const wchar_t *s1) {
 	if (s1 == NULL) s1 = L"";
-	unsigned long length1 = wcslen (s1);
-	unsigned long sizeNeeded = my length + length1 + 1;
-	expandIfNecessary (wchar_t)
+	int64 length1 = (int64) wcslen (s1);
+	int64 sizeNeeded = my length + length1 + 1;
+	expandIfNecessary (wchar)
 	wcscpy (my string + my length, s1);
 	my length += length1;
 }
@@ -125,10 +125,10 @@ void MelderString_append (MelderString *me, const wchar_t *s1) {
 void MelderString_append (MelderString *me, const wchar_t *s1, const wchar_t *s2) {
 	if (s1 == NULL) s1 = L"";
 	if (s2 == NULL) s2 = L"";
-	unsigned long length1 = wcslen (s1);
-	unsigned long length2 = wcslen (s2);
-	unsigned long sizeNeeded = my length + length1 + length2 + 1;
-	expandIfNecessary (wchar_t)
+	int64 length1 = (int64) wcslen (s1);
+	int64 length2 = (int64) wcslen (s2);
+	int64 sizeNeeded = my length + length1 + length2 + 1;
+	expandIfNecessary (wchar)
 	wcscpy (my string + my length, s1);
 	my length += length1;
 	wcscpy (my string + my length, s2);
@@ -139,11 +139,11 @@ void MelderString_append (MelderString *me, const wchar_t *s1, const wchar_t *s2
 	if (s1 == NULL) s1 = L"";
 	if (s2 == NULL) s2 = L"";
 	if (s3 == NULL) s3 = L"";
-	unsigned long length1 = wcslen (s1);
-	unsigned long length2 = wcslen (s2);
-	unsigned long length3 = wcslen (s3);
-	unsigned long sizeNeeded = my length + length1 + length2 + length3 + 1;
-	expandIfNecessary (wchar_t)
+	int64 length1 = (int64) wcslen (s1);
+	int64 length2 = (int64) wcslen (s2);
+	int64 length3 = (int64) wcslen (s3);
+	int64 sizeNeeded = my length + length1 + length2 + length3 + 1;
+	expandIfNecessary (wchar)
 	wcscpy (my string + my length, s1);
 	my length += length1;
 	wcscpy (my string + my length, s2);
@@ -157,12 +157,12 @@ void MelderString_append (MelderString *me, const wchar_t *s1, const wchar_t *s2
 	if (s2 == NULL) s2 = L"";
 	if (s3 == NULL) s3 = L"";
 	if (s4 == NULL) s4 = L"";
-	unsigned long length1 = wcslen (s1);
-	unsigned long length2 = wcslen (s2);
-	unsigned long length3 = wcslen (s3);
-	unsigned long length4 = wcslen (s4);
-	unsigned long sizeNeeded = my length + length1 + length2 + length3 + length4 + 1;
-	expandIfNecessary (wchar_t)
+	int64 length1 = (int64) wcslen (s1);
+	int64 length2 = (int64) wcslen (s2);
+	int64 length3 = (int64) wcslen (s3);
+	int64 length4 = (int64) wcslen (s4);
+	int64 sizeNeeded = my length + length1 + length2 + length3 + length4 + 1;
+	expandIfNecessary (wchar)
 	wcscpy (my string + my length, s1);
 	my length += length1;
 	wcscpy (my string + my length, s2);
@@ -181,13 +181,13 @@ void MelderString_append (MelderString *me, const wchar_t *s1, const wchar_t *s2
 	if (s3 == NULL) s3 = L"";
 	if (s4 == NULL) s4 = L"";
 	if (s5 == NULL) s5 = L"";
-	unsigned long length1 = wcslen (s1);
-	unsigned long length2 = wcslen (s2);
-	unsigned long length3 = wcslen (s3);
-	unsigned long length4 = wcslen (s4);
-	unsigned long length5 = wcslen (s5);
-	unsigned long sizeNeeded = my length + length1 + length2 + length3 + length4 + length5 + 1;
-	expandIfNecessary (wchar_t)
+	int64 length1 = (int64) wcslen (s1);
+	int64 length2 = (int64) wcslen (s2);
+	int64 length3 = (int64) wcslen (s3);
+	int64 length4 = (int64) wcslen (s4);
+	int64 length5 = (int64) wcslen (s5);
+	int64 sizeNeeded = my length + length1 + length2 + length3 + length4 + length5 + 1;
+	expandIfNecessary (wchar)
 	wcscpy (my string + my length, s1);
 	my length += length1;
 	wcscpy (my string + my length, s2);
@@ -209,14 +209,14 @@ void MelderString_append (MelderString *me, const wchar_t *s1, const wchar_t *s2
 	if (s4 == NULL) s4 = L"";
 	if (s5 == NULL) s5 = L"";
 	if (s6 == NULL) s6 = L"";
-	unsigned long length1 = wcslen (s1);
-	unsigned long length2 = wcslen (s2);
-	unsigned long length3 = wcslen (s3);
-	unsigned long length4 = wcslen (s4);
-	unsigned long length5 = wcslen (s5);
-	unsigned long length6 = wcslen (s6);
-	unsigned long sizeNeeded = my length + length1 + length2 + length3 + length4 + length5 + length6 + 1;
-	expandIfNecessary (wchar_t)
+	int64 length1 = (int64) wcslen (s1);
+	int64 length2 = (int64) wcslen (s2);
+	int64 length3 = (int64) wcslen (s3);
+	int64 length4 = (int64) wcslen (s4);
+	int64 length5 = (int64) wcslen (s5);
+	int64 length6 = (int64) wcslen (s6);
+	int64 sizeNeeded = my length + length1 + length2 + length3 + length4 + length5 + length6 + 1;
+	expandIfNecessary (wchar)
 	wcscpy (my string + my length, s1);
 	my length += length1;
 	wcscpy (my string + my length, s2);
@@ -241,15 +241,15 @@ void MelderString_append (MelderString *me, const wchar_t *s1, const wchar_t *s2
 	if (s5 == NULL) s5 = L"";
 	if (s6 == NULL) s6 = L"";
 	if (s7 == NULL) s7 = L"";
-	unsigned long length1 = wcslen (s1);
-	unsigned long length2 = wcslen (s2);
-	unsigned long length3 = wcslen (s3);
-	unsigned long length4 = wcslen (s4);
-	unsigned long length5 = wcslen (s5);
-	unsigned long length6 = wcslen (s6);
-	unsigned long length7 = wcslen (s7);
-	unsigned long sizeNeeded = my length + length1 + length2 + length3 + length4 + length5 + length6 + length7 + 1;
-	expandIfNecessary (wchar_t)
+	int64 length1 = (int64) wcslen (s1);
+	int64 length2 = (int64) wcslen (s2);
+	int64 length3 = (int64) wcslen (s3);
+	int64 length4 = (int64) wcslen (s4);
+	int64 length5 = (int64) wcslen (s5);
+	int64 length6 = (int64) wcslen (s6);
+	int64 length7 = (int64) wcslen (s7);
+	int64 sizeNeeded = my length + length1 + length2 + length3 + length4 + length5 + length6 + length7 + 1;
+	expandIfNecessary (wchar)
 	wcscpy (my string + my length, s1);
 	my length += length1;
 	wcscpy (my string + my length, s2);
@@ -277,16 +277,16 @@ void MelderString_append (MelderString *me, const wchar_t *s1, const wchar_t *s2
 	if (s6 == NULL) s6 = L"";
 	if (s7 == NULL) s7 = L"";
 	if (s8 == NULL) s8 = L"";
-	unsigned long length1 = wcslen (s1);
-	unsigned long length2 = wcslen (s2);
-	unsigned long length3 = wcslen (s3);
-	unsigned long length4 = wcslen (s4);
-	unsigned long length5 = wcslen (s5);
-	unsigned long length6 = wcslen (s6);
-	unsigned long length7 = wcslen (s7);
-	unsigned long length8 = wcslen (s8);
-	unsigned long sizeNeeded = my length + length1 + length2 + length3 + length4 + length5 + length6 + length7 + length8 + 1;
-	expandIfNecessary (wchar_t)
+	int64 length1 = (int64) wcslen (s1);
+	int64 length2 = (int64) wcslen (s2);
+	int64 length3 = (int64) wcslen (s3);
+	int64 length4 = (int64) wcslen (s4);
+	int64 length5 = (int64) wcslen (s5);
+	int64 length6 = (int64) wcslen (s6);
+	int64 length7 = (int64) wcslen (s7);
+	int64 length8 = (int64) wcslen (s8);
+	int64 sizeNeeded = my length + length1 + length2 + length3 + length4 + length5 + length6 + length7 + length8 + 1;
+	expandIfNecessary (wchar)
 	wcscpy (my string + my length, s1);
 	my length += length1;
 	wcscpy (my string + my length, s2);
@@ -317,17 +317,17 @@ void MelderString_append (MelderString *me, const wchar_t *s1, const wchar_t *s2
 	if (s7 == NULL) s7 = L"";
 	if (s8 == NULL) s8 = L"";
 	if (s9 == NULL) s9 = L"";
-	unsigned long length1 = wcslen (s1);
-	unsigned long length2 = wcslen (s2);
-	unsigned long length3 = wcslen (s3);
-	unsigned long length4 = wcslen (s4);
-	unsigned long length5 = wcslen (s5);
-	unsigned long length6 = wcslen (s6);
-	unsigned long length7 = wcslen (s7);
-	unsigned long length8 = wcslen (s8);
-	unsigned long length9 = wcslen (s9);
-	unsigned long sizeNeeded = my length + length1 + length2 + length3 + length4 + length5 + length6 + length7 + length8 + length9 + 1;
-	expandIfNecessary (wchar_t)
+	int64 length1 = (int64) wcslen (s1);
+	int64 length2 = (int64) wcslen (s2);
+	int64 length3 = (int64) wcslen (s3);
+	int64 length4 = (int64) wcslen (s4);
+	int64 length5 = (int64) wcslen (s5);
+	int64 length6 = (int64) wcslen (s6);
+	int64 length7 = (int64) wcslen (s7);
+	int64 length8 = (int64) wcslen (s8);
+	int64 length9 = (int64) wcslen (s9);
+	int64 sizeNeeded = my length + length1 + length2 + length3 + length4 + length5 + length6 + length7 + length8 + length9 + 1;
+	expandIfNecessary (wchar)
 	wcscpy (my string + my length, s1);
 	my length += length1;
 	wcscpy (my string + my length, s2);
@@ -349,29 +349,29 @@ void MelderString_append (MelderString *me, const wchar_t *s1, const wchar_t *s2
 }
 
 void MelderString_appendCharacter (MelderString *me, wchar_t character) {
-	unsigned long sizeNeeded = my length + 2;   // make room for character and null byte
-	expandIfNecessary (wchar_t)
+	int64 sizeNeeded = my length + 2;   // make room for character and null byte
+	expandIfNecessary (wchar)
 	my string [my length] = character;
 	my length ++;
 	my string [my length] = L'\0';
 }
 
 void MelderString16_appendCharacter (MelderString16 *me, wchar_t character) {
-	unsigned long sizeNeeded = my length + 3;   // make room for character, potential surrogate character, and null byte
-	expandIfNecessary (utf16_t)
+	int64 sizeNeeded = my length + 3;   // make room for character, potential surrogate character, and null byte
+	expandIfNecessary (char16)
 	if (sizeof (wchar_t) == 2) {   // wchar_t is UTF-16?
-		my string [my length] = character;
+		my string [my length] = (char16) character;   // guarded cast
 		my length ++;
 	} else {   // wchar_t is UTF-32.
-		utf32_t kar = character;
-		if (kar <= 0xFFFF) {
-			my string [my length] = character;
+		char32 kar = (char32) character;
+		if (kar <= 0x00FFFF) {
+			my string [my length] = (char16) character;   // guarded cast
 			my length ++;
 		} else if (kar <= 0x10FFFF) {
-			kar -= 0x10000;
-			my string [my length] = 0xD800 | (kar >> 10);
+			kar -= 0x010000;
+			my string [my length] = (char16) (0x00D800 | (kar >> 10));
 			my length ++;
-			my string [my length] = 0xDC00 | (kar & 0x3FF);
+			my string [my length] = (char16) (0x00DC00 | (kar & 0x0003FF));
 			my length ++;
 		} else {
 			my string [my length] = UNICODE_REPLACEMENT_CHARACTER;
@@ -381,6 +381,14 @@ void MelderString16_appendCharacter (MelderString16 *me, wchar_t character) {
 	my string [my length] = '\0';
 }
 
+void MelderString32_appendCharacter (MelderString32 *me, char32 character) {
+	int64 sizeNeeded = my length + 2;   // make room for character and null byte
+	expandIfNecessary (char32)
+	my string [my length] = character;
+	my length ++;
+	my string [my length] = U'\0';
+}
+
 void MelderString_get (MelderString *me, wchar_t *destination) {
 	if (my string) {
 		wcscpy (destination, my string);
diff --git a/sys/melder_textencoding.cpp b/sys/melder_textencoding.cpp
index fd9b014..85c4a8a 100644
--- a/sys/melder_textencoding.cpp
+++ b/sys/melder_textencoding.cpp
@@ -66,24 +66,29 @@ void Melder_textEncoding_prefs (void) {
 bool Melder_isValidAscii (const wchar_t *text) {
 	for (; *text != '\0'; text ++) {
 		if (sizeof (wchar_t) == 2) {
-			unsigned short kar = *text;
-			if (kar > 127) return false;
+			if ((char16_t) *text > 127) return false;   // make unsigned
 		} else {
-			if (*text > 127) return false;
+			if ((char32_t) *text > 127) return false;   // make unsigned
 		}
 	}
 	return true;
 }
 
+bool Melder_isValidAscii (const char32_t *text) {
+	for (; *text != '\0'; text ++) {
+		if (*text > 127) return false;
+	}
+	return true;
+}
+
 bool Melder_isEncodable (const wchar_t *text, int outputEncoding) {
 	switch (outputEncoding) {
 		case kMelder_textOutputEncoding_ASCII: {
 			for (; *text != '\0'; text ++) {
 				if (sizeof (wchar_t) == 2) {
-					unsigned short kar = *text;
-					if (kar > 127) return false;
+					if ((char16_t) *text > 127) return false;   // make unsigned
 				} else {
-					if (*text > 127) return false;
+					if ((char32_t) *text > 127) return false;   // make unsigned
 				}
 			}
 			return true;
@@ -91,10 +96,9 @@ bool Melder_isEncodable (const wchar_t *text, int outputEncoding) {
 		case kMelder_textOutputEncoding_ISO_LATIN1: {
 			for (; *text != '\0'; text ++) {
 				if (sizeof (wchar_t) == 2) {
-					unsigned short kar = *text;
-					if (kar > 255) return false;
+					if ((char16_t) *text > 255) return false;   // make unsigned
 				} else {
-					if (*text > 255) return false;
+					if ((char32_t) *text > 255) return false;   // make unsigned
 				}
 			}
 			return true;
@@ -110,8 +114,8 @@ bool Melder_isEncodable (const wchar_t *text, int outputEncoding) {
 }
 
 bool Melder_strIsValidUtf8 (const char *string) {
-	for (const unsigned char *p = (const unsigned char *) & string [0]; *p != '\0'; p ++) {
-		unsigned long kar = *p;
+	for (const char8_t *p = (const char8_t *) & string [0]; *p != '\0'; p ++) {
+		char32_t kar = (char32_t) *p;
 		if (kar <= 0x7F) {
 			;
 		} else if (kar <= 0xC1) {
@@ -136,31 +140,32 @@ long Melder_killReturns_inline (char *text) {
 	const char *from;
 	char *to;
 	for (from = text, to = text; *from != '\0'; from ++, to ++) {
-		if (*from == 13) {   /* Carriage return? */
-			if (from [1] == '\n') {   /* Followed by linefeed? Must be a Windows text. */
-				from ++;   /* Ignore carriage return. */
-				*to = '\n';   /* Copy linefeed. */
-			} else {   /* Bare carriage return? Must be a Macintosh text. */
-				*to = '\n';   /* Change to linefeed. */
+		if (*from == 13) {   // carriage return?
+			if (from [1] == '\n') {   // followed by linefeed? Must be a Windows text
+				from ++;   // ignore carriage return
+				*to = '\n';   // copy linefeed
+			} else {   // bare carriage return? Must be a Macintosh text
+				*to = '\n';   // change to linefeed
 			}
 		} else {
 			*to = *from;
 		}
 	}
-	*to = '\0';   /* Closing null byte. */
+	*to = '\0';   // closing null byte
 	return to - text;
 }
 
-long Melder_killReturns_inlineW (wchar_t *text) {
-	const wchar_t *from;
-	wchar_t *to;
+template <class CHAR>
+long Melder_killReturns_inlineCHAR (CHAR *text) {
+	const CHAR *from;
+	CHAR *to;
 	for (from = text, to = text; *from != '\0'; from ++, to ++) {
-		if (*from == 13) {   /* Carriage return? */
-			if (from [1] == '\n' || from [1] == 0x0085 /* NextLine */) {   /* Followed by linefeed? Must be a Windows text. */
-				from ++;   /* Ignore carriage return. */
-				*to = '\n';   /* Copy linefeed. */
-			} else {   /* Bare carriage return? Must be a Macintosh text. */
-				*to = '\n';   /* Change to linefeed (10). */
+		if (*from == 13) {   // carriage return?
+			if (from [1] == '\n' || from [1] == 0x0085 /* NextLine */) {   // followed by linefeed? Must be a Windows text
+				from ++;   // ignore carriage return
+				*to = '\n';   // copy linefeed
+			} else {   // bare carriage return? Must be a Macintosh text
+				*to = '\n';   // change to linefeed (10)
 			}
 		} else if (*from == 0x0085 /* NextLine */ || *from == 0x000C /* FormFeed */ ||
 		    *from == UNICODE_LINE_SEPARATOR || *from == UNICODE_PARAGRAPH_SEPARATOR)
@@ -170,11 +175,17 @@ long Melder_killReturns_inlineW (wchar_t *text) {
 			*to = *from;
 		}
 	}
-	*to = '\0';   /* Closing null char. */
+	*to = '\0';   // closing null character
 	return to - text;
 }
+long Melder_killReturns_inlineW (wchar_t *text) {
+	return Melder_killReturns_inlineCHAR <wchar_t> (text);
+}
+long Melder_killReturns_inline32 (char32_t *text) {
+	return Melder_killReturns_inlineCHAR <char32_t> (text);
+}
 
-wchar_t Melder_decodeMacRoman [256] = {
+char32_t Melder_decodeMacRoman [256] = {
 	  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18,  19,
 	 20,  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,
 	 40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,
@@ -242,7 +253,7 @@ wchar_t Melder_decodeMacRoman [256] = {
 	UNICODE_MACRON, UNICODE_BREVE, UNICODE_DOT_ABOVE, UNICODE_RING_ABOVE, UNICODE_CEDILLA,
 	UNICODE_DOUBLE_ACUTE_ACCENT, UNICODE_OGONEK, UNICODE_CARON };
 
-wchar_t Melder_decodeWindowsLatin1 [256] = {
+char32_t Melder_decodeWindowsLatin1 [256] = {
 	  0,   1,   2,   3,   4,   5,   6,   7,   8,   9,  10,  11,  12,  13,  14,  15,  16,  17,  18,  19,
 	 20,  21,  22,  23,  24,  25,  26,  27,  28,  29,  30,  31,  32,  33,  34,  35,  36,  37,  38,  39,
 	 40,  41,  42,  43,  44,  45,  46,  47,  48,  49,  50,  51,  52,  53,  54,  55,  56,  57,  58,  59,
@@ -266,8 +277,9 @@ wchar_t Melder_decodeWindowsLatin1 [256] = {
 	220, 221, 222, 223, 224, 225, 226, 227, 228, 229, 230, 231, 232, 233, 234, 235, 236, 237, 238, 239,
 	240, 241, 242, 243, 244, 245, 246, 247, 248, 249, 250, 251, 252, 253, 254, 255 };
 
-void Melder_8bitToWcs_inline (const char *string, wchar_t *wcs, int inputEncoding) {
-	wchar_t *q = & wcs [0];
+template <class CHAR>
+void Melder_8bitToCHAR_inline (const char *string, CHAR *wcs, int inputEncoding) {
+	CHAR *q = & wcs [0];
 	if (inputEncoding == 0) {
 		inputEncoding = preferences. inputEncoding;
 		/*
@@ -304,19 +316,19 @@ void Melder_8bitToWcs_inline (const char *string, wchar_t *wcs, int inputEncodin
 	const unsigned char *p = (const unsigned char *) & string [0];
 	if (inputEncoding == kMelder_textInputEncoding_UTF8) {
 		while (*p != '\0') {
-			utf32_t kar = * p ++;
-			if (kar <= 0x7F) {
-				* q ++ = kar;
-			} else if (kar <= 0xDF) {
-				unsigned long kar2 = * p ++;
-				* q ++ = ((kar & 0x1F) << 6) | (kar2 & 0x3F);
-			} else if (kar <= 0xEF) {
-				unsigned long kar2 = * p ++, kar3 = * p ++;
-				* q ++ = ((kar & 0x0F) << 12) | ((kar2 & 0x3F) << 6) | (kar3 & 0x3F);
-			} else if (kar <= 0xF4) {
-				unsigned long kar2 = * p ++, kar3 = * p ++, kar4 = * p ++;
-				kar = ((kar & 0x07) << 18) | ((kar2 & 0x3F) << 12) | ((kar3 & 0x3F) << 6) | (kar4 & 0x3F);
-				if (sizeof (wchar_t) == 2) {
+			char32_t kar1 = * p ++;
+			if (kar1 <= 0x7F) {
+				* q ++ = (CHAR) kar1;
+			} else if (kar1 <= 0xDF) {
+				char32_t kar2 = * p ++;
+				* q ++ = (CHAR) (((kar1 & 0x1F) << 6) | (kar2 & 0x3F));
+			} else if (kar1 <= 0xEF) {
+				char32_t kar2 = * p ++, kar3 = * p ++;
+				* q ++ = (CHAR) (((kar1 & 0x0F) << 12) | ((kar2 & 0x3F) << 6) | (kar3 & 0x3F));
+			} else if (kar1 <= 0xF4) {
+				char32_t kar2 = * p ++, kar3 = * p ++, kar4 = * p ++;
+				char32_t kar = ((kar1 & 0x07) << 18) | ((kar2 & 0x3F) << 12) | ((kar3 & 0x3F) << 6) | (kar4 & 0x3F);
+				if (sizeof (CHAR) == 2) {
 					/*
 					 * Convert to UTF-16 surrogate pair.
 					 */
@@ -324,7 +336,7 @@ void Melder_8bitToWcs_inline (const char *string, wchar_t *wcs, int inputEncodin
 					* q ++ = 0xD800 | (kar >> 10);
 					* q ++ = 0xDC00 | (kar & 0x3FF);
 				} else {
-					* q ++ = kar;
+					* q ++ = (CHAR) kar;
 				}
 			}
 		}
@@ -334,32 +346,74 @@ void Melder_8bitToWcs_inline (const char *string, wchar_t *wcs, int inputEncodin
 		}
 	} else if (inputEncoding == kMelder_textInputEncoding_WINDOWS_LATIN1) {
 		while (*p != '\0') {
-			* q ++ = Melder_decodeWindowsLatin1 [* p ++];
+			* q ++ = (CHAR) Melder_decodeWindowsLatin1 [* p ++];
 		}
 	} else if (inputEncoding == kMelder_textInputEncoding_MACROMAN) {
 		while (*p != '\0') {
-			* q ++ = Melder_decodeMacRoman [* p ++];
+			* q ++ = (CHAR) Melder_decodeMacRoman [* p ++];
 		}
 	} else if (inputEncoding != kMelder_textInputEncoding_UTF8) {
 		Melder_fatal ("Unknown text input encoding %d.", inputEncoding);
 	}
 	* q = '\0';
-	(void) Melder_killReturns_inlineW (wcs);
+	(void) Melder_killReturns_inlineCHAR <CHAR> (wcs);
+}
+void Melder_8bitToWcs_inline (const char *string, wchar_t *wcs, int inputEncoding) {
+	Melder_8bitToCHAR_inline <wchar_t> (string, wcs, inputEncoding);
+}
+void Melder_8bitToUtf32_inline (const char *string, char32_t *wcs, int inputEncoding) {
+	Melder_8bitToCHAR_inline <char32_t> (string, wcs, inputEncoding);
 }
 
 wchar_t * Melder_8bitToWcs (const char *string, int inputEncoding) {
 	if (string == NULL) return NULL;
-	autostring result = Melder_malloc (wchar_t, strlen (string) + 1);
+	autostring result = Melder_malloc (wchar_t, (int64_t) strlen (string) + 1);
 	Melder_8bitToWcs_inline (string, result.peek(), inputEncoding);
 	return result.transfer();
 }
+char32_t * Melder_8bitToUtf32 (const char *string, int inputEncoding) {
+	if (string == NULL) return NULL;
+	autostring32 result = Melder_malloc (char32_t, (int64_t) strlen (string) + 1);
+	Melder_8bitToUtf32_inline (string, result.peek(), inputEncoding);
+	return result.transfer();
+}
 
 wchar_t * Melder_utf8ToWcs (const char *string) {
 	if (string == NULL) return NULL;
-	autostring result = Melder_malloc (wchar_t, strlen (string) + 1);
+	autostring result = Melder_malloc (wchar_t, (int64_t) strlen (string) + 1);
 	Melder_8bitToWcs_inline (string, result.peek(), kMelder_textInputEncoding_UTF8);
 	return result.transfer();
 }
+char32_t * Melder_utf8ToUtf32 (const char *string) {
+	if (string == NULL) return NULL;
+	autostring32 result = Melder_malloc (char32_t, (int64_t) strlen (string) + 1);
+	Melder_8bitToUtf32_inline (string, result.peek(), kMelder_textInputEncoding_UTF8);
+	return result.transfer();
+}
+
+char32_t * Melder_utf8ToUtf32_f (const char *string) {
+	char32_t *result = Melder_malloc_f (char32_t, (int64_t) strlen (string) + 1);
+	Melder_assert (Melder_strIsValidUtf8 (string));
+	const char8_t *p = (const char8_t *) & string [0];
+	char32_t *q = & result [0];
+	while (*p != '\0') {
+		char32_t kar1 = (char32_t) * p ++;   // convert up
+		if (kar1 <= 0x7F) {
+			* q ++ = kar1;
+		} else if (kar1 <= 0xDF) {
+			char32_t kar2 = (char32_t) * p ++;   // convert up
+			* q ++ = ((kar1 & 0x1F) << 6) | (kar2 & 0x3F);
+		} else if (kar1 <= 0xEF) {
+			char32_t kar2 = (char32_t) * p ++, kar3 = (char32_t) * p ++;   // convert up
+			* q ++ = ((kar1 & 0x0F) << 12) | ((kar2 & 0x3F) << 6) | (kar3 & 0x3F);
+		} else if (kar1 <= 0xF4) {
+			char32_t kar2 = (char32_t) * p ++, kar3 = (char32_t) * p ++, kar4 = (char32_t) * p ++;   // convert up
+			* q ++ = ((kar1 & 0x07) << 18) | ((kar2 & 0x3F) << 12) | ((kar3 & 0x3F) << 6) | (kar4 & 0x3F);
+		}
+	}
+	* q = '\0';   // closing null character
+	return result;
+}
 
 wchar_t * Melder_peekUtf8ToWcs (const char *textA) {
 	if (textA == NULL) return NULL;
@@ -369,38 +423,48 @@ wchar_t * Melder_peekUtf8ToWcs (const char *textA) {
 	MelderString_empty (& buffers [ibuffer]);
 	unsigned long n = strlen (textA), i, j;
 	for (i = 0, j = 0; i <= n; i ++) {
-		unsigned char kar = textA [i];
-		if (kar <= 0x7F) {
-			MelderString_appendCharacter (& buffers [ibuffer], kar);
-		} else if (kar <= 0xC1) {
+		char8_t kar1 = (char8_t) textA [i];   // convert sign
+		if (kar1 <= 0x7F) {
+			MelderString_appendCharacter (& buffers [ibuffer],
+				(char32_t) kar1);
+		} else if (kar1 <= 0xC1) {
 			MelderString_appendCharacter (& buffers [ibuffer], UNICODE_REPLACEMENT_CHARACTER);
-		} else if (kar <= 0xDF) {
-			unsigned char kar2 = textA [++ i];
-			if (kar2 == '\0' || ! (kar2 & 0x80) || (kar2 & 0x40)) MelderString_appendCharacter (& buffers [ibuffer], UNICODE_REPLACEMENT_CHARACTER);
-			MelderString_appendCharacter (& buffers [ibuffer], ((kar & 0x1F) << 6) | (kar2 & 0x3F));
-		} else if (kar <= 0xEF) {
-			unsigned char kar2 = textA [++ i];
-			if (kar2 == '\0' || ! (kar2 & 0x80) || (kar2 & 0x40)) MelderString_appendCharacter (& buffers [ibuffer], UNICODE_REPLACEMENT_CHARACTER);
-			unsigned char kar3 = textA [++ i];
-			if (kar3 == '\0' || ! (kar3 & 0x80) || (kar3 & 0x40)) MelderString_appendCharacter (& buffers [ibuffer], UNICODE_REPLACEMENT_CHARACTER);
-			MelderString_appendCharacter (& buffers [ibuffer], ((kar & 0x0F) << 12) | ((kar2 & 0x3F) << 6) | (kar3 & 0x3F));
-		} else if (kar <= 0xF4) {
-			unsigned char kar2 = textA [++ i];
-			if (kar2 == '\0' || ! (kar2 & 0x80) || (kar2 & 0x40)) MelderString_appendCharacter (& buffers [ibuffer], UNICODE_REPLACEMENT_CHARACTER);
-			unsigned char kar3 = textA [++ i];
-			if (kar3 == '\0' || ! (kar3 & 0x80) || (kar3 & 0x40)) MelderString_appendCharacter (& buffers [ibuffer], UNICODE_REPLACEMENT_CHARACTER);
-			unsigned char kar4 = textA [++ i];
-			if (kar4 == '\0' || ! (kar4 & 0x80) || (kar4 & 0x40)) MelderString_appendCharacter (& buffers [ibuffer], UNICODE_REPLACEMENT_CHARACTER);
-			unsigned long character = ((kar & 0x07) << 18) | ((kar2 & 0x3F) << 12) | ((kar3 & 0x3F) << 6) | (kar4 & 0x3F);
+		} else if (kar1 <= 0xDF) {
+			char8_t kar2 = (char8_t) textA [++ i];
+			if ((kar2 & 0xC0) != 0x80) MelderString_appendCharacter (& buffers [ibuffer], UNICODE_REPLACEMENT_CHARACTER);
+			MelderString_appendCharacter (& buffers [ibuffer],
+				(char32_t) ((char32_t) ((char32_t) kar1 & 0x1F) << 6) |
+				            (char32_t) ((char32_t) kar2 & 0x3F));
+		} else if (kar1 <= 0xEF) {
+			char8_t kar2 = (char8_t) textA [++ i];
+			if ((kar2 & 0xC0) != 0x80) MelderString_appendCharacter (& buffers [ibuffer], UNICODE_REPLACEMENT_CHARACTER);
+			char8_t kar3 = (char8_t) textA [++ i];
+			if ((kar3 & 0xC0) != 0x80) MelderString_appendCharacter (& buffers [ibuffer], UNICODE_REPLACEMENT_CHARACTER);
+			MelderString_appendCharacter (& buffers [ibuffer],
+				(char32_t) ((char32_t) ((char32_t) kar1 & 0x0F) << 12) |
+				(char32_t) ((char32_t) ((char32_t) kar2 & 0x3F) << 6) |
+				            (char32_t) ((char32_t) kar3 & 0x3F));
+		} else if (kar1 <= 0xF4) {
+			char8_t kar2 = (char8_t) textA [++ i];
+			if ((kar2 & 0xC0) != 0x80) MelderString_appendCharacter (& buffers [ibuffer], UNICODE_REPLACEMENT_CHARACTER);
+			char8_t kar3 = (char8_t) textA [++ i];
+			if ((kar3 & 0xC0) != 0x80) MelderString_appendCharacter (& buffers [ibuffer], UNICODE_REPLACEMENT_CHARACTER);
+			char8_t kar4 = (char8_t) textA [++ i];
+			if ((kar4 & 0xC0) != 0x80) MelderString_appendCharacter (& buffers [ibuffer], UNICODE_REPLACEMENT_CHARACTER);
+			char32_t character =
+				(char32_t) ((char32_t) ((char32_t) kar1 & 0x07) << 18) |
+				(char32_t) ((char32_t) ((char32_t) kar2 & 0x3F) << 12) |
+				(char32_t) ((char32_t) ((char32_t) kar3 & 0x3F) << 6) |
+			                (char32_t) ((char32_t) kar4 & 0x3F);
 			if (sizeof (wchar_t) == 2) {
 				/*
 				 * Convert to UTF-16 surrogate pair.
 				 */
-				character -= 0x10000;
-				MelderString_appendCharacter (& buffers [ibuffer], 0xD800 | (character >> 10));
-				MelderString_appendCharacter (& buffers [ibuffer], 0xDC00 | (character & 0x3FF));
+				character -= 0x010000;
+				MelderString_appendCharacter (& buffers [ibuffer], 0x00D800 | (character >> 10));
+				MelderString_appendCharacter (& buffers [ibuffer], 0x00DC00 | (character & 0x0003FF));
 			} else {
-				MelderString_appendCharacter (& buffers [ibuffer], character);
+				MelderString_appendCharacter (& buffers [ibuffer], (wchar_t) character);   // convert sign
 			}
 		} else {
 			MelderString_appendCharacter (& buffers [ibuffer], UNICODE_REPLACEMENT_CHARACTER);
@@ -409,43 +473,43 @@ wchar_t * Melder_peekUtf8ToWcs (const char *textA) {
 	return buffers [ibuffer]. string;
 }
 
-unsigned long wcslen_utf8 (const wchar_t *wcs, bool expandNewlines) {
-	long length = 0;
+size_t wcslen_utf8 (const wchar_t *wcs, bool expandNewlines) {
+	size_t length = 0;
 	for (const wchar_t *p = & wcs [0]; *p != '\0'; p ++) {
 		if (sizeof (wchar_t) == 2) {
-			utf16_t kar = *p;
-			if (kar <= 0x007F) {
+			char16_t kar1 = (char16_t) *p;   // convert sign
+			if (kar1 <= 0x007F) {
 				#ifdef _WIN32
-					if (expandNewlines && kar == '\n') length ++;
+					if (expandNewlines && kar1 == '\n') length ++;
 				#else
 					(void) expandNewlines;
 				#endif
 				length ++;
-			} else if (kar <= 0x07FF) {
+			} else if (kar1 <= 0x07FF) {
 				length += 2;
-			} else if (kar >= 0xD800 && kar <= 0xDBFF) {
-				unsigned short kar2 = * ++ p;
+			} else if (kar1 >= 0xD800 && kar1 <= 0xDBFF) {
+				char16_t kar2 = (char16_t) * ++ p;
 				Melder_assert (kar2 >= 0xDC00 && kar2 <= 0xDFFF);
 				length += 4;
 			} else {
-				Melder_assert (kar <= 0xD7FF || kar >= 0xE000);
+				Melder_assert (kar1 <= 0xD7FF || kar1 >= 0xE000);
 				length += 3;
 			}
 		} else {
-			utf32_t kar = *p;
-			if (kar <= 0x00007F) {
+			char32_t kar = (char32_t) *p;   // convert sign
+			if (kar <= 0x0000007F) {
 				#ifdef _WIN32
 					if (expandNewlines && kar == '\n') length ++;
 				#else
 					(void) expandNewlines;
 				#endif
 				length ++;
-			} else if (kar <= 0x0007FF) {
+			} else if (kar <= 0x000007FF) {
 				length += 2;
-			} else if (kar <= 0x00FFFF) {
+			} else if (kar <= 0x0000FFFF) {
 				length += 3;
 			} else {
-				Melder_assert (kar <= 0x10FFFF);
+				Melder_assert (kar <= 0x0010FFFF);
 				length += 4;
 			}
 		}
@@ -453,27 +517,27 @@ unsigned long wcslen_utf8 (const wchar_t *wcs, bool expandNewlines) {
 	return length;
 }
 
-unsigned long wcslen_utf16 (const wchar_t *wcs, bool expandNewlines) {
-	long length = 0;
+size_t wcslen_utf16 (const wchar_t *wcs, bool expandNewlines) {
+	size_t length = 0;
 	for (const wchar_t *p = & wcs [0]; *p != '\0'; p ++) {
 		if (sizeof (wchar_t) == 2) {
 			#ifdef _WIN32
-				unsigned short kar = *p;
+				char16_t kar = (char16_t) *p;   // convert sign
 				if (expandNewlines && kar == '\n') length ++;
 			#else
 				(void) expandNewlines;
 			#endif
 			length ++;
 		} else {
-			unsigned long kar = *p;
-			if (kar <= 0x00007F) {
+			char32_t kar = (char32_t) *p;   // convert sign
+			if (kar <= 0x0000007F) {
 				#ifdef _WIN32
 					if (expandNewlines && kar == '\n') length ++;
 				#else
 					(void) expandNewlines;
 				#endif
 				length ++;
-			} else if (kar >= 0x10000) {
+			} else if (kar >= 0x00010000) {
 				length += 2;
 			} else {
 				length += 1;
@@ -484,45 +548,73 @@ unsigned long wcslen_utf16 (const wchar_t *wcs, bool expandNewlines) {
 }
 
 void Melder_wcsToUtf8_inline (const wchar_t *wcs, char *utf8) {
-	long n = wcslen (wcs), i, j;
+	size_t n = wcslen (wcs), i, j;
 	for (i = 0, j = 0; i < n; i ++) {
-		unsigned long kar = sizeof (wchar_t) == 2 ? (unsigned short) wcs [i] : wcs [i];   // crucial cast: prevents sign extension
-		if (kar <= 0x00007F) {
+		char32_t kar = sizeof (wchar_t) == 2 ?
+			(char16_t) wcs [i] :   // crucial cast: prevents sign extension
+			(char32_t) wcs [i];
+		if (kar <= 0x0000007F) {
 			#ifdef _WIN32
 				if (kar == '\n') utf8 [j ++] = 13;
 			#endif
-			utf8 [j ++] = kar;
-		} else if (kar <= 0x0007FF) {
-			utf8 [j ++] = 0xC0 | (kar >> 6);
-			utf8 [j ++] = 0x80 | (kar & 0x00003F);
-		} else if (kar <= 0x00FFFF) {
+			utf8 [j ++] = (char) (char8_t) kar;   // guarded truncation
+		} else if (kar <= 0x000007FF) {
+			utf8 [j ++] = (char) (char8_t) (0xC0 | (kar >> 6));
+			utf8 [j ++] = (char) (char8_t) (0x80 | (kar & 0x00003F));
+		} else if (kar <= 0x0000FFFF) {
 			if (sizeof (wchar_t) == 2) {
 				if ((kar & 0xF800) == 0xD800) {
 					if (kar > 0xDBFF)
-						Melder_fatal ("Incorrect Unicode value (first surrogate member %lX).", kar);
-					unsigned long kar2 = (unsigned short) wcs [++ i];   // crucial cast: prevents sign extension
+						Melder_fatal ("Incorrect Unicode value (first surrogate member %X).", kar);
+					char32_t kar2 = (char16_t) wcs [++ i];   // crucial cast: prevents sign extension
 					if (kar2 < 0xDC00 || kar2 > 0xDFFF)
-						Melder_fatal ("Incorrect Unicode value (second surrogate member %lX).", kar2);
+						Melder_fatal ("Incorrect Unicode value (second surrogate member %X).", kar2);
 					kar = (((kar & 0x3FF) << 10) | (kar2 & 0x3FF)) + 0x10000;   // decode UTF-16
-					utf8 [j ++] = 0xF0 | (kar >> 18);
-					utf8 [j ++] = 0x80 | ((kar >> 12) & 0x00003F);
-					utf8 [j ++] = 0x80 | ((kar >> 6) & 0x00003F);
-					utf8 [j ++] = 0x80 | (kar & 0x00003F);
+					utf8 [j ++] = (char) (char8_t) (0xF0 | (kar >> 18));
+					utf8 [j ++] = (char) (char8_t) (0x80 | ((kar >> 12) & 0x00003F));
+					utf8 [j ++] = (char) (char8_t) (0x80 | ((kar >> 6) & 0x00003F));
+					utf8 [j ++] = (char) (char8_t) (0x80 | (kar & 0x00003F));
 				} else {
-					utf8 [j ++] = 0xE0 | (kar >> 12);
-					utf8 [j ++] = 0x80 | ((kar >> 6) & 0x00003F);
-					utf8 [j ++] = 0x80 | (kar & 0x00003F);
+					utf8 [j ++] = (char) (char8_t) (0xE0 | (kar >> 12));
+					utf8 [j ++] = (char) (char8_t) (0x80 | ((kar >> 6) & 0x00003F));
+					utf8 [j ++] = (char) (char8_t) (0x80 | (kar & 0x00003F));
 				}
 			} else {
-				utf8 [j ++] = 0xE0 | (kar >> 12);
-				utf8 [j ++] = 0x80 | ((kar >> 6) & 0x00003F);
-				utf8 [j ++] = 0x80 | (kar & 0x00003F);
+				utf8 [j ++] = (char) (char8_t) (0xE0 | (kar >> 12));
+				utf8 [j ++] = (char) (char8_t) (0x80 | ((kar >> 6) & 0x00003F));
+				utf8 [j ++] = (char) (char8_t) (0x80 | (kar & 0x00003F));
 			}
 		} else {
-			utf8 [j ++] = 0xF0 | (kar >> 18);
-			utf8 [j ++] = 0x80 | ((kar >> 12) & 0x00003F);
-			utf8 [j ++] = 0x80 | ((kar >> 6) & 0x00003F);
-			utf8 [j ++] = 0x80 | (kar & 0x00003F);
+			utf8 [j ++] = (char) (char8_t) (0xF0 | (kar >> 18));
+			utf8 [j ++] = (char) (char8_t) (0x80 | ((kar >> 12) & 0x00003F));
+			utf8 [j ++] = (char) (char8_t) (0x80 | ((kar >> 6) & 0x00003F));
+			utf8 [j ++] = (char) (char8_t) (0x80 | (kar & 0x00003F));
+		}
+	}
+	utf8 [j] = '\0';
+}
+
+void Melder_str32ToUtf8_inline (const char32 *string, char *utf8) {
+	int64 n = str32len (string), i, j;
+	for (i = 0, j = 0; i < n; i ++) {
+		char32 kar = string [i];
+		if (kar <= 0x00007F) {   // 7 bits
+			#ifdef _WIN32
+				if (kar == '\n') utf8 [j ++] = 13;
+			#endif
+			utf8 [j ++] = (char) (char8_t) kar;   // guarded truncation
+		} else if (kar <= 0x0007FF) {   // 11 bits
+			utf8 [j ++] = (char) (char8_t) (0xC0 | (kar >> 6));   // the upper 5 bits yield a number between 0xC4 and 0xDF
+			utf8 [j ++] = (char) (char8_t) (0x80 | (kar & 0x00003F));   // the lower 6 bits yield a number between 0x80 and 0xBF
+		} else if (kar <= 0x00FFFF) {   // 16 bits
+			utf8 [j ++] = (char) (char8_t) (0xE0 | (kar >> 12));   // the upper 4 bits yield a number between 0xE0 and 0xEF
+			utf8 [j ++] = (char) (char8_t) (0x80 | ((kar >> 6) & 0x00003F));
+			utf8 [j ++] = (char) (char8_t) (0x80 | (kar & 0x00003F));
+		} else {   // 21 bits
+			utf8 [j ++] = (char) (char8_t) (0xF0 | (kar >> 18));   // the upper 3 bits yield a number between 0xF0 and 0xF4 (0x10FFFF >> 18 == 4)
+			utf8 [j ++] = (char) (char8_t) (0x80 | ((kar >> 12) & 0x00003F));   // the next 6 bits
+			utf8 [j ++] = (char) (char8_t) (0x80 | ((kar >> 6) & 0x00003F));   // the third 6 bits
+			utf8 [j ++] = (char) (char8_t) (0x80 | (kar & 0x00003F));   // the lower 6 bits
 		}
 	}
 	utf8 [j] = '\0';
@@ -530,7 +622,7 @@ void Melder_wcsToUtf8_inline (const wchar_t *wcs, char *utf8) {
 
 char * Melder_wcsToUtf8 (const wchar_t *string) {
 	if (string == NULL) return NULL;
-	autostring8 result = Melder_malloc (char, wcslen_utf8 (string, true) + 1);
+	autostring8 result = Melder_malloc (char, (int64_t) wcslen_utf8 (string, true) + 1);
 	Melder_wcsToUtf8_inline (string, result.peek());
 	return result.transfer();
 }
@@ -538,24 +630,24 @@ char * Melder_wcsToUtf8 (const wchar_t *string) {
 char * Melder_peekWcsToUtf8 (const wchar_t *text) {
 	if (text == NULL) return NULL;
 	static char *buffer [11] = { NULL };
-	static long bufferSize [11] = { 0 };
+	static size_t bufferSize [11] = { 0 };
 	static int ibuffer = 0;
 	if (++ ibuffer == 11) ibuffer = 0;
-	long sizeNeeded = wcslen (text) * 4 + 1;
+	size_t sizeNeeded = wcslen (text) * 4 + 1;
 	if ((bufferSize [ibuffer] - sizeNeeded) * sizeof (char) >= 10000) {
 		Melder_free (buffer [ibuffer]);
 		bufferSize [ibuffer] = 0;
 	}
 	if (sizeNeeded > bufferSize [ibuffer]) {
-		sizeNeeded = sizeNeeded * 1.61803 + 100;
-		buffer [ibuffer] = (char *) Melder_realloc_f (buffer [ibuffer], sizeNeeded * sizeof (char));
+		sizeNeeded = (size_t) (sizeNeeded * 1.61803) + 100;
+		buffer [ibuffer] = (char *) Melder_realloc_f (buffer [ibuffer], (int64) sizeNeeded * (int64) sizeof (char));
 		bufferSize [ibuffer] = sizeNeeded;
 	}
 	Melder_wcsToUtf8_inline (text, buffer [ibuffer]);
 	return buffer [ibuffer];
 }
 
-const utf16_t * Melder_peekWcsToUtf16 (const wchar_t *text) {
+const uint16_t * Melder_peekWcsToUtf16 (const wchar_t *text) {
 	if (text == NULL) return NULL;
 	static MelderString16 buffers [11] = { { 0 } };
 	static int ibuffer = 0;
@@ -568,7 +660,7 @@ const utf16_t * Melder_peekWcsToUtf16 (const wchar_t *text) {
 		#endif
 		MelderString16_appendCharacter (& buffers [ibuffer], text [i]);
 	}
-	return buffers [ibuffer]. string;
+	return (uint16_t *) buffers [ibuffer]. string;   // return type is such that this routine can be called by C
 }
 
 #if defined (macintosh)
diff --git a/sys/melder_writetext.cpp b/sys/melder_writetext.cpp
index ff7a933..795d95f 100644
--- a/sys/melder_writetext.cpp
+++ b/sys/melder_writetext.cpp
@@ -1,6 +1,6 @@
 /* melder_writetext.cpp
  *
- * Copyright (C) 2007-2011 Paul Boersma
+ * Copyright (C) 2007-2011,2015 Paul Boersma
  *
  * 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
@@ -44,24 +44,24 @@
 	#include "macport_off.h"
 #endif
 
-static void Melder_fwriteUnicodeAsUtf8 (unsigned long unicode, FILE *f) {
-	if (unicode <= 0x00007F) {
+static void Melder_fwriteUnicodeAsUtf8 (char32_t unicode, FILE *f) {
+	if (unicode <= 0x0000007F) {
 		#ifdef _WIN32
 			if (unicode == '\n') fputc (13, f);
 		#endif
-		fputc (unicode, f);
-	} else if (unicode <= 0x0007FF) {
+		fputc ((int) unicode, f);   // because fputc wants an int instead of an uint8_t (guarded conversion)
+	} else if (unicode <= 0x000007FF) {
 		fputc (0xC0 | (unicode >> 6), f);
-		fputc (0x80 | (unicode & 0x00003F), f);
-	} else if (unicode <= 0x00FFFF) {
+		fputc (0x80 | (unicode & 0x0000003F), f);
+	} else if (unicode <= 0x0000FFFF) {
 		fputc (0xE0 | (unicode >> 12), f);
-		fputc (0x80 | ((unicode >> 6) & 0x00003F), f);
-		fputc (0x80 | (unicode & 0x00003F), f);
+		fputc (0x80 | ((unicode >> 6) & 0x0000003F), f);
+		fputc (0x80 | (unicode & 0x0000003F), f);
 	} else {
 		fputc (0xF0 | (unicode >> 18), f);
-		fputc (0x80 | ((unicode >> 12) & 0x00003F), f);
-		fputc (0x80 | ((unicode >> 6) & 0x00003F), f);
-		fputc (0x80 | (unicode & 0x00003F), f);
+		fputc (0x80 | ((unicode >> 12) & 0x0000003F), f);
+		fputc (0x80 | ((unicode >> 6) & 0x0000003F), f);
+		fputc (0x80 | (unicode & 0x0000003F), f);
 	}
 }
 
@@ -79,38 +79,38 @@ void Melder_fwriteWcsAsUtf8 (const wchar_t *ptr, size_t n, FILE *f) {
 			 * We are likely to be on Macintosh or Linux.
 			 * We assume that the string's encoding is UTF-32.
 			 */
-			Melder_fwriteUnicodeAsUtf8 (ptr [i], f);
+			Melder_fwriteUnicodeAsUtf8 ((char32_t) ptr [i], f);   // safe conversion, because sign bit is zero
 		} else if (sizeof (wchar_t) == 2) {
 			/*
 			 * We are likely to be on Windows.
 			 * We assume that the string's encoding is UTF-16;
 			 * if it turns out to be otherwise, we write question marks.
 			 */
-			unsigned long kar1 = (unsigned short) ptr [i];   // potential intermediate conversion from signed short to unsigned short
-			if (kar1 < 0xD800) {
+			char32_t kar1 = (char32_t) (char16_t) ptr [i];   // don't extend sign
+			if (kar1 < 0x00D800) {
 				Melder_fwriteUnicodeAsUtf8 (kar1, f);   // a character from the Basic Multilingual Plane
-			} else if (kar1 < 0xDC00) {
+			} else if (kar1 < 0x00DC00) {
 				/*
 				 * We detected a surrogate code point
 				 * and will therefore translate two UTF-16 words into one Unicode supplementary character.
 				 */
-				unsigned long kar2 = ptr [++ i];
+				char32_t kar2 = (char32_t) (char16_t) ptr [++ i];   // don't extend sign
 				if (kar2 == 0) {   // string exhausted?
 					// Melder_fatal ("Detected a bare (final) high surrogate in UTF-16.");
 					Melder_fwriteUnicodeAsUtf8 (UNICODE_REPLACEMENT_CHARACTER, f);
 					return;
 				}
-				if (kar2 >= 0xDC00 && kar2 <= 0xDFFF) {
-					Melder_fwriteUnicodeAsUtf8 (0x10000 + ((kar1 - 0xD800) << 10) + (kar2 - 0xDC00), f);
+				if (kar2 >= 0x00DC00 && kar2 <= 0x00DFFF) {
+					Melder_fwriteUnicodeAsUtf8 (0x010000 + ((kar1 - 0x00D800) << 10) + (kar2 - 0x00DC00), f);
 				} else {
 					// Melder_fatal ("Detected a bare high surrogate in UTF-16.");
 					Melder_fwriteUnicodeAsUtf8 (UNICODE_REPLACEMENT_CHARACTER, f);
 					i --;   // try to interpret the next character in the normal way
 				}
-			} else if (kar1 < 0xE000) {
+			} else if (kar1 < 0x00E000) {
 				// Melder_fatal ("Detected a bare low surrogate in UTF-16.");
 				Melder_fwriteUnicodeAsUtf8 (UNICODE_REPLACEMENT_CHARACTER, f);
-			} else if (kar1 <= 0xFFFF) {
+			} else if (kar1 <= 0x00FFFF) {
 				Melder_fwriteUnicodeAsUtf8 (kar1, f);   // a character from the Basic Multilingual Plane
 			} else {
 				Melder_fatal ("Melder_fwriteWcsAsUtf8: unsigned short greater than 0xFFFF: should not occur.");
@@ -136,7 +136,9 @@ void MelderFile_writeText (MelderFile file, const wchar_t *text, enum kMelder_te
 		flockfile (f);
 		size_t n = wcslen (text);
 		for (size_t i = 0; i < n; i ++) {
-			unsigned long kar = sizeof (wchar_t) == 2 ? (unsigned short) text [i] : text [i];
+			char32_t kar = sizeof (wchar_t) == 2 ?
+				(char16_t) text [i] :   // don't extend sign
+				(char32_t) text [i];
 			#ifdef _WIN32
 				if (kar == '\n') putc_unlocked (13, f);
 			#endif
@@ -145,25 +147,25 @@ void MelderFile_writeText (MelderFile file, const wchar_t *text, enum kMelder_te
 		funlockfile (f);
 	} else {
 		binputu2 (0xFEFF, f);   // Byte Order Mark
-		long n = wcslen (text);
-		for (long i = 0; i < n; i ++) {
+		size_t n = wcslen (text);
+		for (size_t i = 0; i < n; i ++) {
 			if (sizeof (wchar_t) == 2) {   // wchar_t is UTF-16?
-				unsigned short kar = text [i];
+				char16_t kar = (char16_t) text [i];
 				#ifdef _WIN32
 					if (kar == '\n') binputu2 (13, f);
 				#endif
 				binputu2 (kar, f);
 			} else {   // wchar_t is UTF-32.
-				unsigned long kar = text [i];
+				char32_t kar = (char32_t) text [i];
 				#ifdef _WIN32
 					if (kar == '\n') binputu2 (13, f);
 				#endif
-				if (kar <= 0xFFFF) {
-					binputu2 (kar, f);
+				if (kar <= 0x00FFFF) {
+					binputu2 ((char16_t) kar, f);   // guarded conversion down
 				} else if (kar <= 0x10FFFF) {
-					kar -= 0x10000;
-					binputu2 (0xD800 | (kar >> 10), f);
-					binputu2 (0xDC00 | (kar & 0x3ff), f);
+					kar -= 0x010000;
+					binputu2 (0xD800 | (uint16_t) (kar >> 10), f);
+					binputu2 (0xDC00 | (uint16_t) ((char16_t) kar & 0x3ff), f);
 				} else {
 					binputu2 (UNICODE_REPLACEMENT_CHARACTER, f);
 				}
@@ -174,9 +176,9 @@ void MelderFile_writeText (MelderFile file, const wchar_t *text, enum kMelder_te
 }
 
 void MelderFile_appendText (MelderFile file, const wchar_t *text) {
-	autofile f;
+	autofile f1;
 	try {
-		f.reset (Melder_fopen (file, "rb"));
+		f1.reset (Melder_fopen (file, "rb"));
 	} catch (MelderError) {
 		Melder_clearError ();   // it's OK if the file didn't exist yet...
 		MelderFile_writeText (file, text, Melder_getOutputEncoding ());   // because then we just "write"
@@ -185,8 +187,8 @@ void MelderFile_appendText (MelderFile file, const wchar_t *text) {
 	/*
 	 * The file already exists and is open. Determine its type.
 	 */
-	int firstByte = fgetc (f), secondByte = fgetc (f);
-	f.close (file);
+	int firstByte = fgetc (f1), secondByte = fgetc (f1);
+	f1.close (file);
 	int type = 0;
 	if (firstByte == 0xfe && secondByte == 0xff) {
 		type = 1;   // big-endian 16-bit
@@ -196,164 +198,168 @@ void MelderFile_appendText (MelderFile file, const wchar_t *text) {
 	if (type == 0) {
 		int outputEncoding = Melder_getOutputEncoding ();
 		if (outputEncoding == kMelder_textOutputEncoding_UTF8) {   // TODO: read as file's encoding
-			autofile f = Melder_fopen (file, "ab");
-			Melder_fwriteWcsAsUtf8 (text, wcslen (text), f);
-			f.close (file);
+			autofile f2 = Melder_fopen (file, "ab");
+			Melder_fwriteWcsAsUtf8 (text, wcslen (text), f2);
+			f2.close (file);
 		} else if ((outputEncoding == kMelder_textOutputEncoding_ASCII_THEN_UTF16 && Melder_isEncodable (text, kMelder_textOutputEncoding_ASCII))
 		    || (outputEncoding == kMelder_textOutputEncoding_ISO_LATIN1_THEN_UTF16 && Melder_isEncodable (text, kMelder_textOutputEncoding_ISO_LATIN1)))
 		{
 			/*
 			 * Append ASCII or ISOLatin1 text to ASCII or ISOLatin1 file.
 			 */
-			autofile f = Melder_fopen (file, "ab");
+			autofile f2 = Melder_fopen (file, "ab");
 			size_t n = wcslen (text);
 			for (size_t i = 0; i < n; i ++) {
-				unsigned long kar = sizeof (wchar_t) == 2 ? (unsigned short) text [i] : text [i];
+				uint32_t kar = sizeof (wchar_t) == 2 ?
+					(uint16_t) text [i] :   // don't extend sign
+					(uint32_t) text [i];
 				#ifdef _WIN32
-					if (kar == '\n') fputc (13, f);
+					if (kar == '\n') fputc (13, f2);
 				#endif
-				fputc (kar, f);
+				fputc ((uint8_t) kar, f2);
 			}
-			f.close (file);
+			f2.close (file);
 		} else {
 			/*
 			 * Convert to wide character file.
 			 */
 			autostring oldText = MelderFile_readText (file);
-			autofile f = Melder_fopen (file, "wb");
-			binputu2 (0xfeff, f);
-			unsigned long n = wcslen (oldText.peek());
-			for (unsigned long i = 0; i < n; i ++) {
+			autofile f2 = Melder_fopen (file, "wb");
+			binputu2 (0xfeff, f2);
+			size_t n = wcslen (oldText.peek());
+			for (size_t i = 0; i < n; i ++) {
 				if (sizeof (wchar_t) == 2) {   // wchar_t is UTF-16?
-					wchar_t kar = oldText [i];
+					char16_t kar = (char16_t) oldText [i];   // reinterpret sign bit
 					#ifdef _WIN32
-						if (kar == '\n') binputu2 (13, f);
+						if (kar == '\n') binputu2 (13, f2);
 					#endif
-					binputu2 (kar, f);
+					binputu2 (kar, f2);
 				} else {   // wchar_t is UTF-32.
-					unsigned long kar = oldText [i];
+					char32_t kar = (char32_t) oldText [i];   // sign bit is always 0
 					#ifdef _WIN32
-						if (kar == '\n') binputu2 (13, f);
+						if (kar == '\n') binputu2 (13, f2);
 					#endif
-					if (kar <= 0xFFFF) {
-						binputu2 (kar, f);
-					} else if (kar <= 0x10FFFF) {
-						kar -= 0x10000;
-						binputu2 (0xD800 | (kar >> 10), f);
-						binputu2 (0xDC00 | (kar & 0x3ff), f);
+					if (kar <= 0x0000FFFF) {
+						binputu2 ((uint16_t) kar, f2);   // guarded conversion down
+					} else if (kar <= 0x0010FFFF) {
+						kar -= 0x00010000;
+						binputu2 (0xD800 | (uint16_t) (kar >> 10), f2);
+						binputu2 (0xDC00 | (uint16_t) ((uint16_t) kar & 0x03ff), f2);
 					} else {
-						binputu2 (UNICODE_REPLACEMENT_CHARACTER, f);
+						binputu2 (UNICODE_REPLACEMENT_CHARACTER, f2);
 					}
 				}
 			}
 			n = wcslen (text);
 			for (unsigned long i = 0; i < n; i ++) {
 				if (sizeof (wchar_t) == 2) {   // wchar_t is UTF-16?
-					unsigned short kar = text [i];
+					char16_t kar = (char16_t) text [i];   // reinterpret sign bit
 					#ifdef _WIN32
-						if (kar == '\n') binputu2 (13, f);
+						if (kar == '\n') binputu2 (13, f2);
 					#endif
-					binputu2 (kar, f);
+					binputu2 (kar, f2);
 				} else {   // wchar_t is UTF-32.
-					unsigned long kar = text [i];
+					char32_t kar = (char32_t) text [i];   // sign bit is always 0
 					#ifdef _WIN32
-						if (kar == '\n') binputu2 (13, f);
+						if (kar == '\n') binputu2 (13, f2);
 					#endif
-					if (kar <= 0xFFFF) {
-						binputu2 (kar, f);
+					if (kar <= 0x00FFFF) {
+						binputu2 ((char16_t) kar, f2);   // guarded conversion down
 					} else if (kar <= 0x10FFFF) {
-						kar -= 0x10000;
-						binputu2 (0xD800 | (kar >> 10), f);
-						binputu2 (0xDC00 | (kar & 0x3ff), f);
+						kar -= 0x010000;
+						binputu2 (0xD800 | (char16_t) (kar >> 10), f2);
+						binputu2 (0xDC00 | (char16_t) ((char16_t) kar & 0x03ff), f2);
 					} else {
-						binputu2 (UNICODE_REPLACEMENT_CHARACTER, f);
+						binputu2 (UNICODE_REPLACEMENT_CHARACTER, f2);
 					}
 				}
 			}
-			f.close (file);
+			f2.close (file);
 		}
 	} else {
-		autofile f = Melder_fopen (file, "ab");
+		autofile f2 = Melder_fopen (file, "ab");
 		unsigned long n = wcslen (text);
 		for (unsigned long i = 0; i < n; i ++) {
 			if (type == 1) {
 				if (sizeof (wchar_t) == 2) {   // wchar_t is UTF-16?
-					unsigned short kar = text [i];
+					uint16_t kar = (uint16_t) text [i];   // reinterpret sign bit
 					#ifdef _WIN32
-						if (kar == '\n') binputu2 (13, f);
+						if (kar == '\n') binputu2 (13, f2);
 					#endif
-					binputu2 (kar, f);
+					binputu2 (kar, f2);
 				} else {   // wchar_t is UTF-32
-					unsigned long kar = text [i];
+					char32_t kar = (char32_t) text [i];   // sign bit is always 0
 					#ifdef _WIN32
-						if (kar == '\n') binputu2 (13, f);
+						if (kar == '\n') binputu2 (13, f2);
 					#endif
-					if (kar <= 0xFFFF) {
-						binputu2 (kar, f);
+					if (kar <= 0x00FFFF) {
+						binputu2 ((char16_t) kar, f2);   // guarded conversion down
 					} else if (kar <= 0x10FFFF) {
-						kar -= 0x10000;
-						binputu2 (0xD800 | (kar >> 10), f);
-						binputu2 (0xDC00 | (kar & 0x3ff), f);
+						kar -= 0x010000;
+						binputu2 (0xD800 | (uint16_t) (kar >> 10), f2);
+						binputu2 (0xDC00 | (uint16_t) ((uint16_t) kar & 0x03ff), f2);
 					} else {
-						binputu2 (UNICODE_REPLACEMENT_CHARACTER, f);
+						binputu2 (UNICODE_REPLACEMENT_CHARACTER, f2);
 					}
 				}
 			} else {
 				if (sizeof (wchar_t) == 2) {   // wchar_t is UTF-16?
-					unsigned short kar = text [i];
+					uint16_t kar = (uint16_t) text [i];   // reinterpret sign bit
 					#ifdef _WIN32
-						if (kar == '\n') binputu2LE (13, f);
+						if (kar == '\n') binputu2LE (13, f2);
 					#endif
-					binputu2LE (kar, f);
+					binputu2LE (kar, f2);
 				} else {   // wchar_t is UTF-32
-					unsigned long kar = text [i];
+					char32_t kar = (char32_t) text [i];   // sign bit is always 0
 					#ifdef _WIN32
-						if (kar == '\n') binputu2LE (13, f);
+						if (kar == '\n') binputu2LE (13, f2);
 					#endif
-					if (kar <= 0xFFFF) {
-						binputu2LE (kar, f);
+					if (kar <= 0x00FFFF) {
+						binputu2LE ((char16_t) kar, f2);   // guarded conversion down
 					} else if (kar <= 0x10FFFF) {
-						kar -= 0x10000;
-						binputu2LE (0xD800 | (kar >> 10), f);
-						binputu2LE (0xDC00 | (kar & 0x3ff), f);
+						kar -= 0x010000;
+						binputu2LE (0xD800 | (uint16_t) (kar >> 10), f2);
+						binputu2LE (0xDC00 | (uint16_t) ((uint16_t) kar & 0x3ff), f2);
 					} else {
-						binputu2LE (UNICODE_REPLACEMENT_CHARACTER, f);
+						binputu2LE (UNICODE_REPLACEMENT_CHARACTER, f2);
 					}
 				}
 			}
 		}
-		f.close (file);
+		f2.close (file);
 	}
 }
 
 static void _MelderFile_write (MelderFile file, const wchar_t *string) {
 	if (string == NULL) return;
-	unsigned long length = wcslen (string);
+	size_t length = wcslen (string);
 	FILE *f = file -> filePointer;
 	if (file -> outputEncoding == kMelder_textOutputEncoding_ASCII || file -> outputEncoding == kMelder_textOutputEncoding_ISO_LATIN1) {
-		for (unsigned long i = 0; i < length; i ++) {
-			char kar = string [i];
+		for (size_t i = 0; i < length; i ++) {
+			char kar = string [i];   // truncate
 			if (kar == '\n' && file -> requiresCRLF) putc (13, f);
 			putc (kar, f);
 		}
 	} else if (file -> outputEncoding == kMelder_textOutputEncoding_UTF8) {
-		for (unsigned long i = 0; i < length; i ++) {
-			unsigned long kar = sizeof (wchar_t) == 2 ? (unsigned short) string [i] : string [i];
+		for (size_t i = 0; i < length; i ++) {
+			char32_t kar = sizeof (wchar_t) == 2 ?
+				(char16_t) string [i] :   // don't extend sign
+				(char32_t) string [i];
 			if (kar <= 0x00007F) {
 				if (kar == '\n' && file -> requiresCRLF) putc (13, f);
-				putc (kar, f);
+				putc ((int) kar, f);   // guarded conversion down
 			} else if (kar <= 0x0007FF) {
 				putc (0xC0 | (kar >> 6), f);
 				putc (0x80 | (kar & 0x00003F), f);
 			} else if (kar <= 0x00FFFF) {
 				if (sizeof (wchar_t) == 2) {
-					if ((kar & 0xF800) == 0xD800) {
-						if (kar > 0xDBFF)
+					if ((kar & 0x00F800) == 0x00D800) {
+						if (kar > 0x00DBFF)
 							Melder_fatal ("Incorrect Unicode value (first surrogate member %lX).", kar);
-						unsigned long kar2 = (unsigned short) string [++ i];   // crucial cast: prevents sign extension
-						if (kar2 < 0xDC00 || kar2 > 0xDFFF)
+						char32_t kar2 = (char32_t) (char16_t) string [++ i];   // don't extend sign
+						if (kar2 < 0x00DC00 || kar2 > 0x00DFFF)
 							Melder_fatal ("Incorrect Unicode value (second surrogate member %lX).", kar2);
-						kar = (((kar & 0x3FF) << 10) | (kar2 & 0x3FF)) + 0x10000;   // decode UTF-16
+						kar = (((kar & 0x0003FF) << 10) | (kar2 & 0x0003FF)) + 0x010000;   // decode UTF-16
 						putc (0xF0 | (kar >> 18), f);
 						putc (0x80 | ((kar >> 12) & 0x00003F), f);
 						putc (0x80 | ((kar >> 6) & 0x00003F), f);
@@ -376,18 +382,20 @@ static void _MelderFile_write (MelderFile file, const wchar_t *string) {
 			}
 		}
 	} else {
-		for (unsigned long i = 0; i < length; i ++) {
-			unsigned long kar = sizeof (wchar_t) == 2 ? (unsigned short) string [i] : string [i];
+		for (size_t i = 0; i < length; i ++) {
+			char32_t kar = sizeof (wchar_t) == 2 ?
+				(char16_t) string [i] :   // don't extend sign
+				(char32_t) string [i];
 			if (kar == '\n' && file -> requiresCRLF) binputu2 (13, f);
 			if (sizeof (wchar_t) == 2) {   // wchar_t is UTF-16?
-				binputu2 (kar, f);
+				binputu2 ((char16_t) kar, f);
 			} else {   // wchar_t is UTF-32.
-				if (kar <= 0xFFFF) {
-					binputu2 (kar, f);
+				if (kar <= 0x00FFFF) {
+					binputu2 ((char16_t) kar, f);
 				} else if (kar <= 0x10FFFF) {
-					kar -= 0x10000;
-					binputu2 (0xD800 | (kar >> 10), f);
-					binputu2 (0xDC00 | (kar & 0x3ff), f);
+					kar -= 0x010000;
+					binputu2 (0xD800 | (char16_t) (kar >> 10), f);
+					binputu2 (0xDC00 | (char16_t) ((char16_t) kar & 0x03ff), f);
 				} else {
 					binputu2 (UNICODE_REPLACEMENT_CHARACTER, f);
 				}
@@ -398,22 +406,24 @@ static void _MelderFile_write (MelderFile file, const wchar_t *string) {
 
 void MelderFile_writeCharacter (MelderFile file, wchar_t character) {
 	FILE *f = file -> filePointer;
-	unsigned long kar = sizeof (wchar_t) == 2 ? (unsigned short) character : character;
+	char32_t kar = sizeof (wchar_t) == 2 ?
+		(char16_t) character :   // don't extend sign
+		(char32_t) character;
 	if (file -> outputEncoding == kMelder_textOutputEncoding_ASCII || file -> outputEncoding == kMelder_textOutputEncoding_ISO_LATIN1) {
 		if (kar == '\n' && file -> requiresCRLF) putc (13, f);
 		putc (kar, f);
 	} else if (file -> outputEncoding == kMelder_textOutputEncoding_UTF8) {
 		if (kar <= 0x00007F) {
 			if (kar == '\n' && file -> requiresCRLF) putc (13, f);
-			putc (kar, f);
+			putc ((int) kar, f);   // guarded conversion down
 		} else if (kar <= 0x0007FF) {
 			putc (0xC0 | (kar >> 6), f);
 			putc (0x80 | (kar & 0x00003F), f);
 		} else if (kar <= 0x00FFFF) {
 			if (sizeof (wchar_t) == 2) {
-				if ((kar & 0xF800) == 0xD800) {
-					static unsigned long buffer;   // NOT REENTRANT
-					if (kar >= 0xD800 && kar <= 0xDBFF) {
+				if ((kar & 0x00F800) == 0x00D800) {
+					static char32_t buffer;   // NOT REENTRANT
+					if (kar >= 0x00D800 && kar <= 0x00DBFF) {
 						buffer = kar;
 					} else {
 						kar = (((buffer & 0x3FF) << 10) | (kar & 0x3FF)) + 0x10000;   // decode UTF-16
@@ -441,14 +451,14 @@ void MelderFile_writeCharacter (MelderFile file, wchar_t character) {
 	} else {
 		if (kar == '\n' && file -> requiresCRLF) binputu2 (13, f);
 		if (sizeof (wchar_t) == 2) {   // wchar_t is UTF-16?
-			binputu2 (kar, f);
+			binputu2 ((uint16_t) kar, f);
 		} else {   // wchar_t is UTF-32.
-			if (kar <= 0xFFFF) {
-				binputu2 (kar, f);
-			} else if (kar <= 0x10FFFF) {
-				kar -= 0x10000;
-				binputu2 (0xD800 | (kar >> 10), f);
-				binputu2 (0xDC00 | (kar & 0x3ff), f);
+			if (kar <= 0x0000FFFF) {
+				binputu2 ((uint16_t) kar, f);
+			} else if (kar <= 0x0010FFFF) {
+				kar -= 0x00010000;
+				binputu2 (0xD800 | (uint16_t) (kar >> 10), f);
+				binputu2 (0xDC00 | (uint16_t) ((uint16_t) kar & 0x03ff), f);
 			} else {
 				binputu2 (UNICODE_REPLACEMENT_CHARACTER, f);
 			}
diff --git a/sys/oo.h b/sys/oo.h
index 5402d7e..232aa81 100644
--- a/sys/oo.h
+++ b/sys/oo.h
@@ -2,7 +2,7 @@
 #define _oo_h_
 /* oo.h
  *
- * Copyright (C) 1994-2012,2013 Paul Boersma
+ * Copyright (C) 1994-2012,2013,2015 Paul Boersma
  *
  * 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
@@ -45,6 +45,13 @@
 #define oo_UBYTE(x)  oo_SIMPLE (unsigned char, u1, x)
 #define oo_UINT(x)  oo_SIMPLE (unsigned int, u2, x)
 #define oo_ULONG(x)  oo_SIMPLE (unsigned long, u4, x)
+#define oo_INT8(x)  oo_SIMPLE (int8, i8, x)
+#define oo_INT16(x)  oo_SIMPLE (int16, i16, x)
+#define oo_INT32(x)  oo_SIMPLE (int32, i32, x)
+#define oo_INT64(x)  oo_SIMPLE (int64, i64, x)
+#define oo_UINT8(x)  oo_SIMPLE (uint8, u8, x)
+#define oo_UINT16(x)  oo_SIMPLE (uint16, u16, x)
+#define oo_UINT32(x)  oo_SIMPLE (uint32, u32, x)
 #define oo_BOOL(x)  oo_SIMPLE (unsigned char, u1, x)
 #define oo_FLOAT(x)  oo_SIMPLE (double, r4, x)
 #define oo_DOUBLE(x)  oo_SIMPLE (double, r8, x)
diff --git a/sys/oo_DESCRIPTION.h b/sys/oo_DESCRIPTION.h
index 0485756..88f3f34 100644
--- a/sys/oo_DESCRIPTION.h
+++ b/sys/oo_DESCRIPTION.h
@@ -1,6 +1,6 @@
 /* oo_DESCRIPTION.h
  *
- * Copyright (C) 1994-2012,2013 Paul Boersma
+ * Copyright (C) 1994-2012,2013,2015 Paul Boersma
  *
  * 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
@@ -23,6 +23,8 @@
 #define oo_BYTE(x)  { L"" #x, bytewa, Melder_offsetof (ooSTRUCT, x), sizeof (signed char) },
 #undef oo_INT
 #define oo_INT(x)  { L"" #x, intwa, Melder_offsetof (ooSTRUCT, x), sizeof (int) },
+#undef oo_INT32
+#define oo_INT32(x)  { L"" #x, intwa, Melder_offsetof (ooSTRUCT, x), sizeof (int32) },
 #undef oo_LONG
 #define oo_LONG(x)  { L"" #x, longwa, Melder_offsetof (ooSTRUCT, x), sizeof (long) },
 #undef oo_UBYTE
diff --git a/sys/oo_READ_BINARY.h b/sys/oo_READ_BINARY.h
index aa3e762..cd27af6 100644
--- a/sys/oo_READ_BINARY.h
+++ b/sys/oo_READ_BINARY.h
@@ -129,9 +129,9 @@
 
 #define oo_COLLECTION(Class,x,ItemClass,version)  \
 	{ \
-		long n = bingeti4 (f); \
+		int32_t n = bingeti4 (f); \
 		our x = Class##_create (); \
-		for (long i = 1; i <= n; i ++) { \
+		for (int32_t i = 1; i <= n; i ++) { \
 			long saveVersion = Thing_version; \
 			auto##ItemClass item = (ItemClass) Thing_new (ItemClass); \
 			Thing_version = version; \
diff --git a/sys/praat.cpp b/sys/praat.cpp
index dc19f49..453ca5a 100644
--- a/sys/praat.cpp
+++ b/sys/praat.cpp
@@ -1529,8 +1529,18 @@ void praat_run (void) {
 		Melder_assert ((double) dummy == 40000.0);
 		Melder_assert ((double) (int16_t) dummy == -25536.0);
 	}
+	{
+		int64_t dummy = 1000000000000;
+		if (! wcsequ (Melder_integer (dummy), L"1000000000000"))
+			Melder_fatal ("The number 1000000000000 is mistaken written on this machine as %ls", Melder_integer (dummy));
+	}
 	{ uint32_t dummy = 0xffffffff;
+		Melder_assert ((int64_t) dummy == 4294967295LL);
 		Melder_assert (wcsequ (Melder_integer (dummy), L"4294967295"));
+		Melder_assert (double (dummy) == 4294967295.0);
+	}
+	{ double dummy = 3000000000.0;
+		Melder_assert ((uint32_t) dummy == 3000000000);
 	}
 
 	if (sizeof (off_t) < 8)
diff --git a/sys/praat_logo.cpp b/sys/praat_logo.cpp
index 7f8b75a..9d1c9bd 100644
--- a/sys/praat_logo.cpp
+++ b/sys/praat_logo.cpp
@@ -35,7 +35,7 @@ static void logo_defaultDraw (Graphics g) {
 	Graphics_text (g, 0.5, 0.6, Melder_peekUtf8ToWcs (praatP.title));
 	Graphics_setFontStyle (g, 0);
 	Graphics_setFontSize (g, 12);
-	Graphics_text (g, 0.5, 0.25, L"\\s{Built on the} %%Praat shell%\\s{,\\co Paul Boersma, 1992-2012");
+	Graphics_text (g, 0.5, 0.25, L"\\s{Built on the} %%Praat shell%\\s{,© Paul Boersma, 1992-2015");
 }
 
 static struct {
@@ -102,7 +102,9 @@ void praat_showLogo (int autoPopDown) {
 		#define xstr(s) str(s)
 		#define str(s) #s
 		gtk_about_dialog_set_version (GTK_ABOUT_DIALOG (dialog), xstr (PRAAT_VERSION_STR));
-		gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG (dialog), "Copyright (C) 1992-" xstr(PRAAT_YEAR) " by Paul Boersma and David Weenink");
+		static const wchar_t *copyright = Melder_utf8ToWcs ("Copyright © 1992–" xstr(PRAAT_YEAR) " by Paul Boersma and David Weenink");
+		gtk_about_dialog_set_copyright (GTK_ABOUT_DIALOG (dialog),
+			Melder_peekWcsToUtf8 (copyright));
 		gtk_about_dialog_set_license (GTK_ABOUT_DIALOG (dialog), "GPL");
 		gtk_about_dialog_set_website (GTK_ABOUT_DIALOG (dialog), "http://www.praat.org");
 		//gtk_about_dialog_set_authors (GTK_ABOUT_DIALOG (dialog), authors);
diff --git a/sys/praat_objectMenus.cpp b/sys/praat_objectMenus.cpp
index 68137d8..f0b3439 100644
--- a/sys/praat_objectMenus.cpp
+++ b/sys/praat_objectMenus.cpp
@@ -367,7 +367,7 @@ FORM (praat_debug, L"Set debugging options", 0)
 	LABEL (L"", L"in unpredictable ways.")
 	INTEGER (L"Debug option", L"0")
 	OK
-SET_INTEGER (L"Tracing", Melder_getTracing ())
+SET_INTEGER (L"Tracing", Melder_isTracing)
 SET_INTEGER (L"Debug option", Melder_debug)
 DO
 	Melder_setTracing (GET_INTEGER (L"Tracing"));
diff --git a/sys/praat_version.h b/sys/praat_version.h
index 438a9dc..a62aacc 100644
--- a/sys/praat_version.h
+++ b/sys/praat_version.h
@@ -1,5 +1,5 @@
-#define PRAAT_VERSION_STR 5.4.04
-#define PRAAT_VERSION_NUM 5404
-#define PRAAT_YEAR 2014
-#define PRAAT_MONTH December
-#define PRAAT_DAY 28
+#define PRAAT_VERSION_STR 5.4.06
+#define PRAAT_VERSION_NUM 5406
+#define PRAAT_YEAR 2015
+#define PRAAT_MONTH February
+#define PRAAT_DAY 21
diff --git a/test/fon/data.praat b/test/fon/data.praat
index a03c850..fb6529e 100644
Binary files a/test/fon/data.praat and b/test/fon/data.praat differ
diff --git a/test/fon/soundFiles.praat b/test/fon/soundFiles.praat
index a3cb433..31b0344 100644
--- a/test/fon/soundFiles.praat
+++ b/test/fon/soundFiles.praat
@@ -56,15 +56,24 @@ procedure test32 .type$ .extension$ .duration
 		printline  't:4' seconds
 	endfor
 endproc
+Debug... no 18
 call test WAV wav 3
+Debug... no 0
 call test WAV wav 3
+Debug... no 0
 call test AIFF aiff 3
 call test AIFC aifc 3
 call test Next/Sun au 3
 call test NIST nist 3
 call test FLAC flac 3
+Debug... no 18
+call test WAV wav 30
+Debug... no 0
 call test WAV wav 30
 call test24 WAV wav 3
+Debug... no 18
+call test32 WAV wav 3
+Debug... no 0
 call test32 WAV wav 3
 
 procedure do
diff --git a/test/runAllTests.praat b/test/runAllTests.praat
index 3313255..d712323 100644
--- a/test/runAllTests.praat
+++ b/test/runAllTests.praat
@@ -1,23 +1,34 @@
 # Praat script runAlltests.praat
-# Paul Boersma, 6 May 2013
+# Paul Boersma, 31 December 2014
 #
 # This script runs all Praat scripts in its subdirectories.
 
-directories = Create Strings as directory list... directories .
+Text writing preferences: "try ASCII, then UTF-16"
+if macintosh
+	Text reading preferences: "try UTF-8, then MacRoman"
+elif windows
+	Text reading preferences: "try UTF-8, then Windows Latin-1"
+elif unix
+	Text reading preferences: "try UTF-8, then ISO Latin-1"
+else
+	exitScript: "Unknown operating system."
+endif
+
+directories = Create Strings as directory list: "directories", "."
 numberOfDirectories = Get number of strings
 for directory to numberOfDirectories
-printline 'directory'
-	select Strings directories
-	directory$ = Get string... directory
-	printline 'directory$'
+	appendInfoLine: directory
+	selectObject: directories
+	directory$ = Get string: directory
+	appendInfoLine: directory$
 	if directory$ <> "manually"
-		files = Create Strings as file list... files 'directory$'/*.praat
+		files = Create Strings as file list: "files", directory$ + "/*.praat"
 		numberOfFiles = Get number of strings
 		for file to numberOfFiles
-			select files
-			file$ = Get string... file
-			printline ### executing 'directory$'/'file$':
-			execute 'directory$'/'file$'
+			selectObject: files
+			file$ = Get string: file
+			appendInfoLine: "### executing ", directory$, "/", file$, ":"
+			runScript: directory$ + "/" + file$
 		endfor
 	endif
 endfor

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/debian-med/praat.git



More information about the debian-med-commit mailing list