changeset 106:acdbb30fee7e

Port to D2. Most of the effort was dealing with immutable and const.
author Jordan Miner <jminer7@gmail.com>
date Mon, 17 Dec 2012 23:41:50 -0600
parents 97997a544ac0
children 2b710303990f
files build-debug.bat build-paths.bat build-release.bat dynamin/c/cairo.d dynamin/c/uniscribe.d dynamin/c/windows.d dynamin/core/benchmark.d dynamin/core/console.d dynamin/core/environment.d dynamin/core/event.d dynamin/core/file.d dynamin/core/global.d dynamin/core/list.d dynamin/core/settings.d dynamin/core/string.d dynamin/core/unix_console.d dynamin/core/unix_environment.d dynamin/core/windows_console.d dynamin/core/windows_environment.d dynamin/gui/basic_theme.d dynamin/gui/clipboard.d dynamin/gui/container.d dynamin/gui/control.d dynamin/gui/events.d dynamin/gui/file_dialog.d dynamin/gui/key.d dynamin/gui/layout.d dynamin/gui/list_box.d dynamin/gui/scroll_bar.d dynamin/gui/scrollable.d dynamin/gui/silver_theme.d dynamin/gui/theme.d dynamin/gui/window.d dynamin/gui/windows_clipboard.d dynamin/gui/windows_cursor.d dynamin/gui/windows_file_dialog.d dynamin/gui/windows_folder_dialog.d dynamin/gui/windows_theme.d dynamin/gui/windows_window.d dynamin/gui/x_clipboard.d dynamin/gui/x_file_dialog.d dynamin/gui/x_folder_dialog.d dynamin/gui/x_window.d dynamin/painting/color.d dynamin/painting/graphics.d dynamin/painting/text_layout.d dynamin/painting/windows_text_layout.d
diffstat 47 files changed, 447 insertions(+), 428 deletions(-) [+]
line wrap: on
line diff
--- a/build-debug.bat	Sat Nov 24 10:21:50 2012 -0600
+++ b/build-debug.bat	Mon Dec 17 23:41:50 2012 -0600
@@ -2,11 +2,11 @@
 
 call build-paths
 
-set ARGS=-DCPATH%DMD_DIR%\bin -T%OUT_FILE% -od%CD%\obj -full -D -Dd%CD%/docs standard.ddoc
+set ARGS=-DCPATH%DMD_DIR%\bin -T%OUT_FILE% -od%CD%\obj -full -D -Dd%CD%/docs standard.ddoc -I%TANGO_DIR%
 set MODE_ARGS=-debug -g -unittest
 
 @echo on
-%BUD_DIR%\bud -Xtango tango-user-dmd.lib %MAIN_FILE% cursors.res %ARGS% %MODE_ARGS%
+%BUD_DIR%\bud -Xtango %TANGO_DIR%\libtango-dmd.lib %MAIN_FILE% cursors.res %ARGS% %MODE_ARGS%
 @echo off
 if errorlevel 1 goto end
 
--- a/build-paths.bat	Sat Nov 24 10:21:50 2012 -0600
+++ b/build-paths.bat	Mon Dec 17 23:41:50 2012 -0600
@@ -1,5 +1,6 @@
 set DMD_DIR=C:\Files\dev\dmd
 set BUD_DIR=C:\Files\dev
+set TANGO_DIR=C:\Files\Projects\Tango
 set MAIN_FILE=tester.d
 set OUT_FILE=tester.exe
 
--- a/build-release.bat	Sat Nov 24 10:21:50 2012 -0600
+++ b/build-release.bat	Mon Dec 17 23:41:50 2012 -0600
@@ -2,11 +2,11 @@
 
 call build-paths
 
-set ARGS=-DCPATH%DMD_DIR%\bin -T%OUT_FILE% -od%CD%\obj -full -D -Dd%CD%/docs standard.ddoc
+set ARGS=-DCPATH%DMD_DIR%\bin -T%OUT_FILE% -od%CD%\obj -full -D -Dd%CD%/docs standard.ddoc -I%TANGO_DIR%
 set MODE_ARGS=-gui4.0 -release -inline -O
 
 @echo on
-%BUD_DIR%\bud -Xtango tango-user-dmd.lib %MAIN_FILE% cursors.res %ARGS% %MODE_ARGS%
+%BUD_DIR%\bud -Xtango %TANGO_DIR%\libtango-dmd.lib %MAIN_FILE% cursors.res %ARGS% %MODE_ARGS%
 @echo off
 if errorlevel 1 goto end
 
--- a/dynamin/c/cairo.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/c/cairo.d	Mon Dec 17 23:41:50 2012 -0600
@@ -19,9 +19,9 @@
 
 alias int cairo_bool_t;
 
-typedef void cairo_t;
+alias void cairo_t;
 
-typedef void cairo_surface_t;
+alias void cairo_surface_t;
 
 struct cairo_matrix_t {
 	double xx; double yx;
@@ -29,9 +29,9 @@
 	double x0; double y0;
 }
 
-typedef void cairo_pattern_t;
+alias void cairo_pattern_t;
 
-typedef void function(void* data) cairo_destroy_func_t;
+alias void function(void* data) cairo_destroy_func_t;
 
 struct cairo_user_data_key_t {
 	int unused;
@@ -71,9 +71,9 @@
 	CAIRO_CONTENT_COLOR_ALPHA = 0x3000
 }
 
-typedef cairo_status_t function(void* closure, char* data, uint length) cairo_write_func_t;
+alias cairo_status_t function(void* closure, char* data, uint length) cairo_write_func_t;
 
-typedef cairo_status_t function(void* closure, char* data, uint length) cairo_read_func_t;
+alias cairo_status_t function(void* closure, char* data, uint length) cairo_read_func_t;
 
 cairo_t* cairo_create(cairo_surface_t* target);
 
@@ -284,9 +284,9 @@
 
 void cairo_rectangle_list_destroy(cairo_rectangle_list_t* rectangle_list);
 
-typedef void cairo_scaled_font_t;
+alias void cairo_scaled_font_t;
 
-typedef void cairo_font_face_t;
+alias void cairo_font_face_t;
 
 struct cairo_glyph_t {
 	uint index;
@@ -349,7 +349,7 @@
 	CAIRO_HINT_METRICS_ON
 }
 
-typedef void cairo_font_options_t;
+alias void cairo_font_options_t;
 
 cairo_font_options_t* cairo_font_options_create();
 
--- a/dynamin/c/uniscribe.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/c/uniscribe.d	Mon Dec 17 23:41:50 2012 -0600
@@ -28,7 +28,7 @@
 
 extern(Windows):
 
-const int USPBUILD = 0400;
+//const int USPBUILD = octal!400;
 
 enum {
 	SCRIPT_UNDEFINED = 0
@@ -125,17 +125,17 @@
 }
 
 HRESULT ScriptItemize(
-	/*const*/ WCHAR* pwcInChars,
+	const(WCHAR)* pwcInChars,
 	int cInChars,
 	int cMaxItems,
-	/*const*/ SCRIPT_CONTROL* psControl,
-	/*const*/ SCRIPT_STATE* psState,
+	const(SCRIPT_CONTROL)* psControl,
+	const(SCRIPT_STATE)* psState,
 	SCRIPT_ITEM* pItems,
 	int* pcItems);
 
 HRESULT ScriptLayout(
 	int cRuns,
-	/*const*/ BYTE* pbLevel,
+	const(BYTE)* pbLevel,
 	int* piVisualToLogical,
 	int* piLogicalToVisual);
 
@@ -180,7 +180,7 @@
 HRESULT ScriptShape(
 	HDC hdc,
 	SCRIPT_CACHE* psc,
-	/*const*/ WCHAR* pwcChars,
+	const(WCHAR)* pwcChars,
 	int cChars,
 	int cMaxGlyphs,
 	SCRIPT_ANALYSIS* psa,
@@ -197,33 +197,33 @@
 HRESULT ScriptPlace(
 	HDC hdc,
 	SCRIPT_CACHE* psc,
-	/*const*/ WORD* pwGlyphs,
+	const(WORD)* pwGlyphs,
 	int cGlyphs,
-	/*const*/ SCRIPT_VISATTR* psva,
+	const(SCRIPT_VISATTR)* psva,
 	SCRIPT_ANALYSIS* psa,
 	int* piAdvance,
 	GOFFSET* pGoffset,
 	ABC* pABC);
 
 HRESULT ScriptTextOut(
-	/*const*/ HDC hdc,
+	const(HDC) hdc,
 	SCRIPT_CACHE* psc,
 	int x,
 	int y,
 	UINT fuOptions,
-	/*const*/ RECT* lprc,
-	/*const*/ SCRIPT_ANALYSIS* psa,
-	/*const*/ WCHAR* pwcReserved,
+	const(RECT)* lprc,
+	const(SCRIPT_ANALYSIS)* psa,
+	const(WCHAR)* pwcReserved,
 	int iReserved,
-	/*const*/ WORD* pwGlyphs,
+	const(WORD)* pwGlyphs,
 	int cGlyphs,
-	/*const*/ int* piAdvance,
-	/*const*/ int* piJustify,
-	/*const*/ GOFFSET* pGoffset);
+	const(int)* piAdvance,
+	const(int)* piJustify,
+	const(GOFFSET)* pGoffset);
 
 HRESULT ScriptJustify(
-	/*const*/ SCRIPT_VISATTR* psva,
-	/*const*/ int* piAdvance,
+	const(SCRIPT_VISATTR)* psva,
+	const(int)* piAdvance,
 	int cGlyphs,
 	int iDx,
 	int iMinKashida,
@@ -249,9 +249,9 @@
 }
 
 HRESULT ScriptBreak(
-	/*const*/ WCHAR* pwcChars,
+	const(WCHAR)* pwcChars,
 	int cChars,
-	/*const*/ SCRIPT_ANALYSIS* psa,
+	const(SCRIPT_ANALYSIS)* psa,
 	SCRIPT_LOGATTR* psla);
 
 HRESULT ScriptCPtoX(
@@ -259,40 +259,40 @@
 	BOOL fTrailing,
 	int cChars,
 	int cGlyphs,
-	/*const*/ WORD* pwLogClust,
-	/*const*/ SCRIPT_VISATTR* psva,
-	/*const*/ int* piAdvance,
-	/*const*/ SCRIPT_ANALYSIS* psa,
+	const(WORD)* pwLogClust,
+	const(SCRIPT_VISATTR)* psva,
+	const(int)* piAdvance,
+	const(SCRIPT_ANALYSIS)* psa,
 	int* piX);
 
 HRESULT ScriptXtoCP(
 	int iX,
 	int cChars,
 	int cGlyphs,
-	/*const*/ WORD* pwLogClust,
-	/*const*/ SCRIPT_VISATTR* psva,
-	/*const*/ int* piAdvance,
-	/*const*/ SCRIPT_ANALYSIS* psa,
+	const(WORD)* pwLogClust,
+	const(SCRIPT_VISATTR)* psva,
+	const(int)* piAdvance,
+	const(SCRIPT_ANALYSIS)* psa,
 	int* piCP,
 	int* piTrailing);
 
 HRESULT ScriptGetLogicalWidths(
-	/*const*/ SCRIPT_ANALYSIS* psa,
+	const(SCRIPT_ANALYSIS)* psa,
 	int cChars,
 	int cGlyphs,
-	/*const*/ int* piGlyphWidth,
-	/*const*/ WORD* pwLogClust,
-	/*const*/ SCRIPT_VISATTR* psva,
+	const(int)* piGlyphWidth,
+	const(WORD)* pwLogClust,
+	const(SCRIPT_VISATTR)* psva,
 	int* piDx);
 
 HRESULT ScriptApplyLogicalWidth(
-	/*const*/ int* piDx,
+	const(int)* piDx,
 	int cChars,
 	int cGlyphs,
-	/*const*/ WORD* pwLogClust,
-	/*const*/ SCRIPT_VISATTR* psva,
-	/*const*/ int* piAdvance,
-	/*const*/ SCRIPT_ANALYSIS* psa,
+	const(WORD)* pwLogClust,
+	const(SCRIPT_VISATTR)* psva,
+	const(int)* piAdvance,
+	const(SCRIPT_ANALYSIS)* psa,
 	ABC* pABC,
 	int* piJustify);
 
@@ -303,7 +303,7 @@
 HRESULT ScriptGetCMap(
 	HDC hdc,
 	SCRIPT_CACHE* psc,
-	/*const*/ WCHAR* pwcInChars,
+	const(WCHAR)* pwcInChars,
 	int cChars,
 	DWORD dwFlags,
 	WORD* pwOutGlyphs);
@@ -411,7 +411,7 @@
 
 HRESULT ScriptStringAnalyse(
 	HDC hdc,
-	/*const*/ void* pString,
+	const(void)* pString,
 	int cString,
 	int cGlyphs,
 	int iCharset,
@@ -419,9 +419,9 @@
 	int iReqWidth,
 	SCRIPT_CONTROL* psControl,
 	SCRIPT_STATE* psState,
-	/*const*/ int* piDx,
+	const(int)* piDx,
 	SCRIPT_TABDEF* pTabdef,
-	/*const*/ BYTE* pbInClass,
+	const(BYTE)* pbInClass,
 	SCRIPT_STRING_ANALYSIS* pssa);
 
 HRESULT ScriptStringFree(SCRIPT_STRING_ANALYSIS* pssa);
@@ -455,7 +455,7 @@
 	int iX,
 	int iY,
 	UINT uOptions,
-	/*const*/ RECT* prc,
+	const(RECT)* prc,
 	int iMinSel,
 	int iMaxSel,
 	BOOL fDisabled);
@@ -467,7 +467,7 @@
 }
 
 HRESULT ScriptIsComplex(
-    /*const*/ WCHAR* pwcInChars,
+    const(WCHAR)* pwcInChars,
     int cInChars,
     DWORD dwFlags);
 
@@ -498,7 +498,7 @@
 }
 
 HRESULT ScriptApplyDigitSubstitution(
-	/*const*/ SCRIPT_DIGITSUBSTITUTE* psds,
+	const(SCRIPT_DIGITSUBSTITUTE)* psds,
 	SCRIPT_CONTROL* psc,
 	SCRIPT_STATE* pss);
 
--- a/dynamin/c/windows.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/c/windows.d	Mon Dec 17 23:41:50 2012 -0600
@@ -17,8 +17,8 @@
 
 alias char*  LPSTR;
 alias wchar* LPWSTR;
-alias char*  LPCSTR;
-alias wchar* LPCWSTR;
+alias const(char)*  LPCSTR;
+alias const(wchar)* LPCWSTR;
 // unicode
 alias wchar   TCHAR;
 alias LPWSTR  LPTSTR;
@@ -112,7 +112,7 @@
 BYTE LOBYTE(WORD w) { return cast(BYTE)(w & 0xff); }
 BYTE HIBYTE(WORD w) { return cast(BYTE)(w >> 8); }
 LPWSTR MAKEINTRESOURCE(int i) { return cast(LPWSTR)cast(WORD)i; }
-BYTE GetRValue(DWORD rgb) { return LOBYTE(rgb); }
+BYTE GetRValue(DWORD rgb) { return LOBYTE(cast(WORD)rgb); }
 BYTE GetGValue(DWORD rgb) { return LOBYTE(cast(WORD)rgb >> 8); }
 BYTE GetBValue(DWORD rgb) { return LOBYTE(rgb >> 16); }
 
@@ -1366,7 +1366,7 @@
 	DWORD* lpNumberOfCharsWritten,
 	VOID* lpReserved);
 
-enum {
+enum : ushort {
 	FOREGROUND_BLUE      = 0x0001,
 	FOREGROUND_GREEN     = 0x0002,
 	FOREGROUND_RED       = 0x0004,
--- a/dynamin/core/benchmark.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/core/benchmark.d	Mon Dec 17 23:41:50 2012 -0600
@@ -30,17 +30,17 @@
 /**
  * name can be null
  */
-double benchmarkAndWrite(string name, int repetitions, void delegate() dg) {
+double benchmarkAndWrite(cstring name, int repetitions, void delegate() dg) {
 	double time = benchmark(repetitions, dg);
 	Stdout.format("{} took {:.2}ms.", name, time).newline; // TODO: verify :.2
 	return time;
 }
-double benchmarkAndWrite(string name, void delegate() dg) {
+double benchmarkAndWrite(cstring name, void delegate() dg) {
 	return benchmarkAndWrite(name, 1, dg);
 }
 
 /**
- * As the constructor calls the Start() method, the only time one would need
+ * As the constructor calls the start() method, the only time one would need
  * to is when reusing a Benchmark object.
  */
 class Benchmark {
@@ -54,7 +54,7 @@
 	long time() {
 		return _startTime-Environment.runningTime;
 	}
-	void writeTime(string opName) {
+	void writeTime(cstring opName) {
 		if(opName is null)
 			opName = "Benchmark";
 		Stdout.format("{} took {}ms.", opName, time).newline;
--- a/dynamin/core/console.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/core/console.d	Mon Dec 17 23:41:50 2012 -0600
@@ -49,9 +49,9 @@
  * The only functions that will work corectly when output or input have been
  * redirected are the following:
  * $(UL
-	 $(LI Write())
-	 $(LI WriteLine())
-	 $(LI ReadLine())
+	 $(LI write())
+	 $(LI writeLine())
+	 $(LI readLine())
  * )
  * On Windows, when writing to a console window, all functionality is
  * available except Bold, Italic, Underline, Strikethrough. Windows does
@@ -76,7 +76,7 @@
 //- Turning off echoing the key press that the user types when returning
 //  input without ENTER
 //- Writing a string, such as "23%", and then changing it to like "24%".
-//  Console.WriteBuffer(40) writes 40 spaces and returns a ConsoleBuffer object
+//  Console.writeBuffer(40) writes 40 spaces and returns a ConsoleBuffer object
 	/**
 	 * Sets whether or not writing to the standard output will be
 	 * buffered. By default, this is false, meaning that no buffering will
@@ -91,7 +91,7 @@
 	/**
 	 * Writes the specified text string to the console.
 	 */
-	void write(string s, ...) {
+	void write(cstring s, ...) {
 		Stdout.layout.convert(&Stdout.emit, _arguments, _argptr, s);
 	}
 	/**
@@ -99,7 +99,7 @@
 	 */
 	void writeLine() { Stdout.newline; }
 	/// ditto
-	void writeLine(string s, ...) {
+	void writeLine(cstring s, ...) {
 		Stdout.layout.convert(&Stdout.emit, _arguments, _argptr, s);
 		Stdout.newline;
 	}
@@ -108,14 +108,14 @@
 	 * will end in a newline, unless it was read from the last line in a text
 	 * file.
 	 */
-	string readLineRaw() { return Cin.copyln(true); }
+	mstring readLineRaw() { return Cin.copyln(true); }
 	/**
 	 * Reads a line of text from the console. The returned string does not
 	 * contain a newline.
 	 */
-	string readLine() { return Cin.copyln(false); }
+	mstring readLine() { return Cin.copyln(false); }
 	/// ditto
-	string readLine(string prompt, ...) {
+	mstring readLine(cstring prompt, ...) {
 		Stdout.layout.convert(&Stdout.emit, _arguments, _argptr, prompt);
 		return readLine();
 	}
@@ -123,9 +123,9 @@
 	 * reads a character, echoing it to the screen
 	 * TODO: not implemented
 	 */
-	string read() { return backend_read(); }
+	mstring read() { return backend_read(); }
 	/// ditto
-	string read(string prompt) {
+	mstring read(cstring prompt) {
 		write(prompt);
 		return backend_read();
 	}
@@ -133,9 +133,9 @@
 	 * reads a line without showing that line
 	 * TODO: not implemented
 	 */
-	string readLineHidden() { return backend_readLineHidden(); }
+	mstring readLineHidden() { return backend_readLineHidden(); }
 	/// ditto
-	string readLineHidden(string prompt) {
+	mstring readLineHidden(cstring prompt) {
 		write(prompt);
 		return backend_readLineHidden();
 	}
@@ -143,9 +143,9 @@
 	 * reads a character without showing it
 	 * TODO: not implemented
 	 */
-	string readHidden() { return backend_readHidden(); }
+	mstring readHidden() { return backend_readHidden(); }
 	/// ditto
-	string readHidden(string prompt) {
+	mstring readHidden(cstring prompt) {
 		write(prompt);
 		return backend_readHidden();
 	}
--- a/dynamin/core/environment.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/core/environment.d	Mon Dec 17 23:41:50 2012 -0600
@@ -102,7 +102,7 @@
 	auto startTime = Environment.runningTime;
 	assert(startTime > 0);
 	auto time = startTime;
-	const SAMPLE = 50;
+	enum SAMPLE = 50;
 	// makes sure that RunningTime does not go backwards
 	for(int i = 0; i < SAMPLE;) {
 		auto time2 = Environment.runningTime;
--- a/dynamin/core/event.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/core/event.d	Mon Dec 17 23:41:50 2012 -0600
@@ -94,7 +94,7 @@
 	void opAddAssign(Handler handler) {
 		if(!handler.funcptr) throw new Exception("handler cannot be null");
 		handlers.length = handlers.length + 1;
-		handlers[length-1] = handler;
+		handlers[$-1] = handler;
 		// TODO: use a list?
 		//handlers.add(handler);
 	}
@@ -106,7 +106,7 @@
 		}
 		Foo* f = new Foo;
 		f.handler = handler;
-		*this += &f.wrapper;
+		this += &f.wrapper;
 		// I really wish D could do this:
 		//this += (ArgsType e) { handler(); };
 	}
--- a/dynamin/core/file.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/core/file.d	Mon Dec 17 23:41:50 2012 -0600
@@ -14,12 +14,12 @@
 import tango.io.device.File;
 import tango.io.UnicodeFile;
 
-ubyte[] readFileBytes(string file) {
+ubyte[] readFileBytes(cstring file) {
 	return cast(ubyte[])File.get(file);
 	//scope f = new File(file);
 	//return cast(ubyte[])f.read();
 }
-string readFileText(string file) {
+mstring readFileText(cstring file) {
 	scope f = new UnicodeFile!(char)(file, Encoding.UTF_8);
 	return f.read();
 }
--- a/dynamin/core/global.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/core/global.d	Mon Dec 17 23:41:50 2012 -0600
@@ -43,21 +43,21 @@
  * The string used to separate lines.
  * This is "\r\n" under Windows and "\n" under Linux.
  */
-const string LineSeparator = FileConst.NewlineString;
+enum string LineSeparator = FileConst.NewlineString;
 /**
  * The string used to separate directories in a path.
  * This is "\\" under Windows and "/" under Linux.
  */
-const string DirSeparator = FileConst.PathSeparatorString;
+enum string DirSeparator = FileConst.PathSeparatorString;
 ///
-const char DirSeparatorChar = FileConst.PathSeparatorChar;
+enum char DirSeparatorChar = FileConst.PathSeparatorChar;
 /**
  * The string used to separate paths.
  * This is ";" under Windows and ":" under Linux
  */
-const string PathSeparator = FileConst.SystemPathString;
+enum string PathSeparator = FileConst.SystemPathString;
 ///
-const char PathSeparatorChar = FileConst.SystemPathChar;
+enum char PathSeparatorChar = FileConst.SystemPathChar;
 
 /**
  * Tests whether num1 and num2 are equal. They are considered equal
@@ -181,14 +181,14 @@
  * toRomanNumerals(194) == "CXCIV"
  * -----
  */
-string toRomanNumerals(int num) {
+mstring toRomanNumerals(int num) {
 	if(num > 3999 || num < 0)
-		throw new IllegalArgumentException("ToRomanNumerals():" ~
+		throw new IllegalArgumentException("toRomanNumerals():" ~
 			"highest convertable roman numeral is 3999");
 	static combos = [[0][0..0], [0], [0,0], [0,0,0], [0,1],
 	[1], [1,0], [1,0,0], [1,0,0,0], [0,2]];
 	static letters = "IVXLCDM";
-	string str = "";
+	mstring str;
 	int letterOffset = 0;
 	while(num > 0) {
 		foreach_reverse(int c; combos[num % 10])
@@ -211,7 +211,7 @@
 	assert(toRomanNumerals(3949) == "MMMCMXLIX");
 }
 
-int numeralToValue(char c) {
+private int numeralToValue(char c) {
 	switch(c) {
 	case 'I': case 'i': return 1;
 	case 'V': case 'v': return 5;
@@ -235,7 +235,7 @@
  * parseRomanNumerals("xxxxviiii") == 49
  * -----
  */
-int parseRomanNumerals(string str) {
+int parseRomanNumerals(cstring str) {
 	int num = 0;
 	int largestSoFar = 1;
 	foreach_reverse(c; str) {
@@ -250,7 +250,7 @@
 		}
 	}
 	if(num > 3999 || num < 0)
-		throw new IllegalArgumentException("ParseRomanNumerals():" ~
+		throw new IllegalArgumentException("parseRomanNumerals():" ~
 			"highest convertable roman numeral is 3999");
 	return num;
 }
@@ -283,10 +283,10 @@
  * byteCountToString(620_705_792) == "591 MB"
  * -----
  */
-string byteCountToString(ulong num) {
-	const factor = 1024;
+mstring byteCountToString(ulong num) {
+	enum factor = 1024;
 	//kilo, mega, giga, tera, peta, exa, zetta, yotta
-	char[][] units = [
+	string[] units = [
 	" bytes", " KB", " MB", " GB", " TB", " PB", " EB", " ZB", " YB"];
 	uint unitIndex = 0;
 	ulong div = factor;
@@ -297,9 +297,9 @@
 		++unitIndex;
 	}
 	//rem/1024 equals the fraction of unit
-	string str = to!(string)(num);
+	mstring str = to!(mstring)(num);
 	if(str.length < 3) {
-		str ~= "." ~ to!(string)(rem*10/factor);
+		str ~= "." ~ to!(mstring)(rem*10/factor);
 	}
 	str ~= units[unitIndex];
 	return str;
--- a/dynamin/core/list.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/core/list.d	Mon Dec 17 23:41:50 2012 -0600
@@ -45,7 +45,7 @@
 	uint _count;
 	static if(changeNotification)
 		void delegate(ListChangeType, T, T, uint) whenChanged;
-	const int DefaultCapacity = 16;
+	enum int DefaultCapacity = 16;
 public:
 	/**
 	 * Creates a list with the specified capacity.
@@ -112,12 +112,12 @@
 		return _data[0.._count];
 	}
 	/*string toString() {
-		string str = "[";
+		mstring str = "[";
 		if(Count > 0)
-			str ~= ToString(this[0]);
+			str ~= toString(this[0]);
 		foreach(item; this) {
 			str ~= ", ";
-			str ~= ToString(item);
+			str ~= toString(item);
 		}
 		str ~= "]";
 		return str;
@@ -127,7 +127,7 @@
 			return;
 		_data.length = max(neededCap, (capacity+1)*2);
 	}
-	T opIndex(uint index) {
+	ref T opIndex(uint index) {
 		return _data[0.._count][index];
 	}
 	void opIndexAssign(T item, uint index) {
@@ -198,7 +198,7 @@
 	//opEquals
 	//opSlice
 	//opSliceAssign
-	int opApply(int delegate(inout T item) dg) {
+	int opApply(int delegate(ref T item) dg) {
 		for(uint i = 0; i < _count; ++i) {
 			if(int result = dg(_data[i]))
 				return result;
@@ -207,7 +207,7 @@
 	}
 	//so you can do:
 	//foreach(i, item; list)
-	int opApply(int delegate(inout uint index, inout T item) dg) {
+	int opApply(int delegate(ref uint index, ref T item) dg) {
 		for(uint i = 0; i < _count; ++i) {
 			if(int result = dg(i, _data[i]))
 				return result;
@@ -217,7 +217,7 @@
 
 }
 unittest {
-	auto list = List!(char).fromArray("Hello, Mat");
+	auto list = List!(char).fromArray("Hello, Mat".dup);
 	list.add('t');
 	assert(list.data == "Hello, Matt");
 	assert(list.pop() == 't');
--- a/dynamin/core/settings.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/core/settings.d	Mon Dec 17 23:41:50 2012 -0600
@@ -35,15 +35,15 @@
 }
 }
 class Color2 {
-	Pixel32 ToPixel32() {
+	Pixel32 toPixel32() {
 		Pixel32 px;
 		return px;
 	}
-	string ToSetting() {
-		auto px = ToPixel32();
+	string toSetting() {
+		auto px = toPixel32();
 		return format("{}, {}, {}", px.R, px.G, px.B);
 	}
-	static Color2 FromSetting(string str) {
+	static Color2 fromSetting(cstring str) {
 		// allow "#AB00F2", "171, 0, 242"
 		return null;
 	}
@@ -64,7 +64,7 @@
 	// test saving to the file
 	auto settings = new Settings;
 	settings.loadFromString(test);
-	test = settings.saveToString();
+	test = settings.saveToString().idup;
 
 	// test reading from the file
 	settings = new Settings;
@@ -100,7 +100,7 @@
 		string section = MainSectionName;
 		bool inStartComment = true;
 		int lineNum = 0;
-		foreach(string line; input) {
+		foreach(line; input) {
 			lineNum++;
 			// check for a line with just whitespace
 			if(line.trim().length == 0)
@@ -111,7 +111,7 @@
 					line.trimLeft().startsWith("#")) {
 				if(inStartComment) {
 					comment.length = comment.length + 1;
-					comment[$-1] = line.trimLeft()[1..$].dup;
+					comment[$-1] = line.trimLeft()[1..$].idup;
 				}
 				continue;
 			}
@@ -121,7 +121,7 @@
 			if(line.startsWith("[")) {
 				if(!line.endsWith("]") || line.length < 3)
 					throw new Exception("Invalid section on line " ~ to!(string)(lineNum));
-				section = line[1..$-1].dup;
+				section = line[1..$-1].idup;
 				continue;
 			}
 
@@ -132,8 +132,8 @@
 					break;
 			if(eqIndex == line.length)
 				throw new Exception("Invalid format on line " ~ to!(string)(lineNum));
-			string value = line[eqIndex+1..$].unescape();
-			sections[section][line[0..eqIndex].dup] = value;
+			string value = cast(immutable)(line[eqIndex+1..$].unescape());
+			sections[section][line[0..eqIndex].idup] = value;
 		}
 	}
 	void saveToStream(OutputStream stream) {
@@ -147,22 +147,22 @@
 		}
 	}
 public:
-	const string MainSectionName = "Main";
+	enum string MainSectionName = "Main";
 	/**
 	 * Parses the specified file.
 	 */
-	void load(string file) {
+	void load(cstring file) {
 		scope f = new File(file);
 		loadFromStream(f);
 	}
-	void loadFromString(string str) {
-		scope a = new Array(str);
+	void loadFromString(cstring str) {
+		auto a = new Array(cast(void[])str);
 		loadFromStream(a);
 	}
-	string saveToString() {
+	mstring saveToString() {
 		scope a = new Array(256, 80);
 		saveToStream(a);
-		return cast(string)a.slice(a.readable);
+		return cast(mstring)a.slice(a.readable);
 	}
 	/**
 	 *
@@ -172,7 +172,7 @@
 	 * settings.get("TabSize", "RubyMode");
 	 * -----
 	 */
-	string get(string name, string section = MainSectionName) {
+	string get(cstring name, cstring section = MainSectionName) {
 		auto sect = section in sections;
 		if(sect) {
 			auto val = name in *sect;
@@ -226,7 +226,7 @@
 	else static if(is(T : long))
 		return cast(T)to!(T)(str);
 	else
-		return T.FromSetting(str);
+		return T.fromSetting(str);
 }
 
 /**
@@ -238,14 +238,14 @@
  */
 void setSetting(T)(Settings settings,
 		string name, T value, string section = Settings.MainSectionName) {
-	string str;
+	mstring str;
 	static if(is(T == bool))
 		str = value ? "true" : "false";
 	else static if(is(T : long))
-		str = to!(string)(value);
+		str = to!(mstring)(value);
 	else
-		str = T.ToSetting();
+		str = T.toSetting();
 
-	settings.Set(name, str, section);
+	settings.set(name, str, section);
 }
 
--- a/dynamin/core/string.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/core/string.d	Mon Dec 17 23:41:50 2012 -0600
@@ -24,22 +24,24 @@
 import dynamin.core.global;
 import dynamin.core.math;
 
-/// Defined as a char[]
-alias char[] string;
+/// Defined as char[]
+alias char[]        mstring;
+/// Defined as const(char)[]
+alias const(char)[] cstring;
 
 ///
-char* toCharPtr(char[] str) {
-	return (str~'\0').ptr;
+char* toCharPtr(cstring str) {
+	return (str~'\0').dup.ptr;
 }
 ///
-wchar* toWcharPtr(char[] str) {
+wchar* toWcharPtr(cstring str) {
 	return toString16(str~'\0').ptr;
 }
 
 /*
-string ToString(ulong num, uint base = 10) {
+string toString(ulong num, uint base = 10) {
 	if(base > 16)
-		throw new Exception("ToString() - radix more than 16");
+		throw new Exception("toString() - radix more than 16");
 	char[] digits = "0123456789abcdef";
 	string str;
 	ulong div = base;
@@ -76,15 +78,21 @@
 static this() {
 	formatter = new Layout!(char);
 }
-string format(char[] str, ...) {
-	return formatter.convert(_arguments, _argptr, str);
+string format(cstring str, ...) {
+	return formatter.convert(_arguments, _argptr, str).idup;
 }
 unittest {
 	assert(format("I am {}", 20) == "I am 20");
 }
 
 /**
- * Converts all lowercase characters in the specified string to uppercase.
+ * Converts all lowercase characters in the specified string to uppercase. Obviously, the
+ * conversion is not done in place, but in-place conversion can be accomplished by passing
+ * the same string as `buffer`.
+ *
+ * Do not use this function to normalize strings to the same case (like to compare them). Instead,
+ * use toUppercase(). See http://msdn.microsoft.com/en-us/library/bb386042%28v=vs.90%29.aspx.
+ *
  * Examples:
  * -----
  * "Bounce the ball.".upcase() == "BOUNCE THE BALL."
@@ -92,16 +100,21 @@
  * "æóëø".upcase() == "ÆÓËØ"
  * -----
  */
-string upcase(string str) {
+mstring upcase(cstring str, mstring buffer = null) { // TODO: use buffer
 	return toUpper(str);
 }
 unittest {
 	assert("Bounce the ball.".upcase() == "BOUNCE THE BALL.");
 	assert("Mañana".upcase() == "MAÑANA");
 	assert("æóëø".upcase() == "ÆÓËØ");
+	assert("σε".downcase() == "ΣΕ");
 }
+
 /**
- * Converts all uppercase characters in the specified string to lowercase.
+ * Converts all uppercase characters in the specified string to lowercase. Obviously, the
+ * conversion is not done in place, but in-place conversion can be accomplished by passing
+ * the same string as `buffer`.
+ *
  * Examples:
  * -----
  * "BoUnCe ThE BALL.".downcase() == "bounce the ball."
@@ -109,80 +122,87 @@
  * "ÆÓËØ".downcase() == "æóëø"
  * -----
  */
-string downcase(string str) {
+mstring downcase(cstring str, mstring buffer = null) { // TODO: use buffer
 	return toLower(str);
 }
 unittest {
 	assert("BoUnCe ThE BALL.".downcase() == "bounce the ball.");
 	assert("MAÑANA".downcase() == "mañana");
 	assert("ÆÓËØ".downcase() == "æóëø");
+	assert("ΣΕ".downcase() == "σε");
 }
 
 // TODO: make more use of delegates in these?
 // TODO; use templates so that these work with wchar and dchar?
-bool startsWith(string str, string subStr, int start = 0) {
+bool startsWith(cstring str, cstring subStr, int start = 0) {
 	if(start+subStr.length > str.length)
 		return false;
 	return str[start..start+subStr.length] == subStr;
 }
-bool endsWith(string str, string subStr) {
+bool endsWith(cstring str, cstring subStr) {
 	return endsWith(str, subStr, str.length);
 }
-bool endsWith(string str, string subStr, int start) {
+bool endsWith(cstring str, cstring subStr, int start) {
 	if(start-subStr.length < 0)
 		return false;
 	return str[str.length-subStr.length..str.length] == subStr;
 }
-int findLast(string str, string subStr) {
+int findLast(cstring str, cstring subStr) {
 	return findLast(str, subStr, str.length);
 }
-int findLast(string str, string subStr, int start) {
+int findLast(cstring str, cstring subStr, int start) {
 	for(int i = start-subStr.length; i >= 0; --i)
 		if(str[i..i+subStr.length] == subStr)
 			return i;
 	return -1;
 }
-int find(string str, string subStr, int start = 0) {
+int find(cstring str, cstring subStr, int start = 0) {
 	for(int i = start; i < str.length-subStr.length; ++i)
 		if(str[i..i+subStr.length] == subStr)
 			return i;
 	return -1;
 }
 
-string remove(string str, int start, int count = 1) {
-	return str[0..start] ~ str[start+count..str.length];
+mstring remove(cstring str, int start, int count = 1, mstring buffer = null) { // TODO: use buffer
+	// can't use concatenation because const(char)[] ~ const(char)[] is const(char)[]
+	//return str[0..start] ~ str[start+count..str.length];
+
+	mstring str2 = new char[str.length - count];
+	str2[0..start] = str[0..start];
+	str2[start..start + count] = str[start+count..str.length];
+	return str2;
 }
 // TODO: ?
 // split(string str, int delegate(string s) func)
 //string[] split(string str, string subStr) {
 //	return split(str, (string s) { return s.startsWith(subStr) ? subStr.length, : -1; };
 //}
-// TODO: return slices to string
+
+/// Returns slices.
 //split1("50=20=10", "=") -> ["50", "20=10"]
-string[] split1(string str, string subStr) {
+inout(char)[][] split1(inout(char)[] str, cstring subStr) {
 	if(subStr.length == 0)
 		return [str];
 	int index = find(str, subStr);
 	if(index == -1)
 		return [str];
-	string[] strs = new string[2];
-	strs[0] = str[0..index].dup;
-	strs[1] = str[index+subStr.length..str.length].dup;
+	auto strs = new inout(char)[][2];
+	strs[0] = str[0..index];
+	strs[1] = str[index+subStr.length..str.length];
 	return strs;
 }
-// TODO: return slices to string
 //split("50=20=10", "=") -> ["50", "20", "10"]
-string[] split(string str, string subStr) {
+inout(char)[][] split(inout(char)[] str, cstring subStr) {
 	if(subStr.length == 0)
 		return [str];
-	string[] strs;
+	inout(char)[][] strs;
 	int index, searchFrom;
 	int i = 0;
 	while(searchFrom < str.length) {
 		index = find(str, subStr, searchFrom);
 		if(index == -1) index = str.length;
 		strs.length = strs.length+1;
-		strs[i] = str[searchFrom..index].dup;
+		strs[i] = str[searchFrom..index];
 		++i;
 		searchFrom = index+subStr.length;
 	}
@@ -212,9 +232,9 @@
  * "\n\r\n".convertNewlines(Newline.Macintosh) == "\r\r"
  * -----
  */
-string convertNewlines(string str, Newline nl) {
+mstring convertNewlines(cstring str, Newline nl, mstring buffer = null) { // TODO: use buffer
 	string lineSep;
-	switch(nl) {
+	final switch(nl) {
 	case Newline.Cr:   lineSep = "\r";   break;
 	case Newline.Lf:   lineSep = "\n";   break;
 	case Newline.Crlf: lineSep = "\r\n"; break;
@@ -237,15 +257,15 @@
  * join(["aol.com", "join", "intro.html"], "/") == "aol.com/join/intro.html"
  * -----
  */
-string join(string[] strs, string sep) {
+mstring join(string[] strs, cstring sep) {
 	if(strs.length == 0)
-		return "";
+		return "".dup;
 	int len;
 	foreach(string s; strs)
 		len += s.length;
 	len += sep.length*(strs.length-1);
 
-	string newStr = new char[len];
+	mstring newStr = new char[len];
 	newStr[0..strs[0].length] = strs[0];
 	int start = strs[0].length;
 	for(int i = 1; i < strs.length; ++i) {
@@ -258,10 +278,10 @@
 	return newStr;
 }
 unittest {
-	// TODO: remove cast(string) when D has bugs fixed
+	// TODO: remove cast(mstring) when D has bugs fixed
 	assert(join(["10", "15", "17"], " - ") == "10 - 15 - 17");
 	assert(join(["789", "672", "484"], ",") == "789,672,484");
-	assert(join([cast(string)"aol.com", "join", "intro.html"], "/") == "aol.com/join/intro.html");
+	assert(join(["aol.com", "join", "intro.html"], "/") == "aol.com/join/intro.html");
 }
 
 /**
@@ -275,8 +295,8 @@
  * "Hi".times(0) == ""
  * -----
  */
-string times(string str, int n) {
-	string newStr = new char[n * str.length];
+mstring times(cstring str, int n) {
+	mstring newStr = new char[n * str.length];
 	for(int i = 0; i < newStr.length; i += str.length)
 		newStr[i..i+str.length] = str;
 	return newStr;
@@ -290,22 +310,22 @@
 
 // TODO: flesh out and make public
 struct sbuilder {
-	int Count;
-	string Data;
-	void Add(char c) {
-		if(Count + 1 > Data.length)
-			Data.length = (Data.length + 1) * 2;
-		Data[Count] = c;
-		++Count;
+	int count;
+	mstring data;
+	void add(char c) {
+		if(count + 1 > data.length)
+			data.length = (data.length + 1) * 2;
+		data[count] = c;
+		++count;
 	}
-	void Add(string str) {
-		if(Count + str.length > Data.length)
-			Data.length = max((Data.length + 1) * 2, Count + str.length);
-		Data[Count..Count+str.length] = str;
-		Count += str.length;
+	void add(cstring str) {
+		if(count + str.length > data.length)
+			data.length = max((data.length + 1) * 2, count + str.length);
+		data[count..count+str.length] = str;
+		count += str.length;
 	}
-	string ToString() {
-		return Data[0..Count].dup;
+	mstring toString() {
+		return data[0..count].dup;
 	}
 }
 /**
@@ -329,12 +349,12 @@
  * -----
  * Bug: If a search string has a length of zero, this method will go into an infinite loop.
  */
-string replace(string str, string[] searchStrs, string[] replacements) {
+mstring replace(cstring str, string[] searchStrs, string[] replacements) {
 	if(replacements.length == 1 && searchStrs.length > 1) {
 		string tmp = replacements[0];
 		replacements = new string[searchStrs.length];
-			foreach(i, dummy; searchStrs)
-				replacements[i] = tmp;
+		foreach(i, dummy; searchStrs)
+			replacements[i] = tmp;
 	}
 	if(searchStrs.length != replacements.length)
 		throw new IllegalArgumentException(
@@ -346,30 +366,30 @@
 			if(i+subStr.length <= str.length && str[i..i+subStr.length] == subStr) {
 				// skip the part of string that matched
 				i += subStr.length;
-				builder.Add(replacements[j]);
+				builder.add(replacements[j]);
 				continue loop;
 			}
 		}
-		builder.Add(str[i]);
+		builder.add(str[i]);
 		++i;
 	}
-	return builder.ToString();
+	return builder.toString();
 }
 /// ditto
-string replace(string str, string[] searchStrs, string replacement) {
+mstring replace(cstring str, string[] searchStrs, string replacement) {
 	return str.replace(searchStrs, [replacement]);
 }
 /// ditto
-string replace(string str, string searchStr, string replacement) {
+mstring replace(cstring str, string searchStr, string replacement) {
 	return str.replace([searchStr], [replacement]);
 }
 unittest {
-	assert("Mississippi".replace([cast(string)"is", "i"], [cast(string)"..", "*"]) == "M..s..s*pp*");
+	assert("Mississippi".replace(["is", "i"], ["..", "*"]) == "M..s..s*pp*");
 	assert("Mississippi".replace("ss", "...") == "Mi...i...ippi");
 	assert("Hello".replace("ll", "y") == "Heyo");
-	//assert("Hi".Replace(cast(string[])[], cast(string[])[]) == "Hi");
-	assert("Speaker".replace([cast(string)"ea", "e"], ":") == "Sp:k:r");
-	assert("Speaker".replace([cast(string)"e", "ea"], ":") == "Sp:ak:r");
+	//assert("Hi".replace(cast(mstring[])[], cast(mstring[])[]) == "Hi");
+	assert("Speaker".replace(["ea", "e"], ":") == "Sp:k:r");
+	assert("Speaker".replace(["e", "ea"], ":") == "Sp:ak:r");
 }
 
 /**
@@ -382,30 +402,30 @@
  * "Part1|Part2\r\n".escape("|\r\n", "|rn") == "Part1\\|Part2\\r\\n"
  * -----
  */
-string escape(string str, char[] chars, char[] escChars) {
+mstring escape(cstring str, const(char)[] chars, const(char)[] escChars) {
 	if(chars.length != escChars.length)
-		throw new IllegalArgumentException("Escape(): chars and escChars must be same length");
+		throw new IllegalArgumentException("escape(): chars and escChars must be same length");
 	sbuilder builder;
 	loop:
 	foreach(i, c; str) {
 		foreach(j, c2; chars) {
 			if(c == '\\') {   // always escape backslash
-				builder.Add('\\');
-				builder.Add('\\');
+				builder.add('\\');
+				builder.add('\\');
 				continue loop;
 			}
 			if(c == c2) {
-				builder.Add('\\');
-				builder.Add(escChars[j]);
+				builder.add('\\');
+				builder.add(escChars[j]);
 				continue loop;
 			}
 		}
-		builder.Add(c);
+		builder.add(c);
 	}
-	return builder.ToString();
+	return builder.toString();
 }
 /// ditto
-string escape(string str) {
+mstring escape(cstring str) {
 	return str.escape("\t\r\n", "trn");
 }
 unittest {
@@ -425,35 +445,35 @@
  * "test\\".unescape()
  * -----
  */
-string unescape(string str, char[] escChars, char[] chars) {
+mstring unescape(cstring str, const(char)[] escChars, const(char)[] chars) {
 	if(escChars.length != chars.length)
-		throw new IllegalArgumentException("Unescape(): escChars and chars must be same length");
+		throw new IllegalArgumentException("unescape(): escChars and chars must be same length");
 	sbuilder builder;
 	loop:
 	foreach(i, c; str) {
 		if(c == '\\') {
 			if(i == str.length-1)
-				throw new IllegalArgumentException("Unescape(): partial escape sequence at end of string");
+				throw new IllegalArgumentException("unescape(): partial escape sequence at end of string");
 			if(str[i+1] == '\\') {
-				builder.Add('\\');
+				builder.add('\\');
 				++i;
 				continue loop;
 			}
 			foreach(j, c2; escChars) {
 				if(str[i+1] == c2) {
-					builder.Add(chars[j]);
+					builder.add(chars[j]);
 					++i;
 					continue loop;
 				}
 			}
-			throw new IllegalArgumentException("Unescape(): invalid escape sequence");
+			throw new IllegalArgumentException("unescape(): invalid escape sequence");
 		}
-		builder.Add(str[i]);
+		builder.add(str[i]);
 	}
-	return builder.ToString();
+	return builder.toString();
 }
 /// ditto
-string unescape(string str) {
+mstring unescape(cstring str) {
 	return str.unescape("trn", "\t\r\n");
 }
 unittest {
@@ -475,12 +495,12 @@
  * "\t \n\r\f\v".removeWhitespace() == ""
  * -----
  */
-string removeWhitespace(string str) {
+mstring removeWhitespace(cstring str) {
 	sbuilder builder;
 	foreach(c; str)
 		if(!" \t\n\r\v\f".contains(c))
-			builder.Add(c);
-	return builder.ToString();
+			builder.add(c);
+	return builder.toString();
 }
 unittest {
 	assert("4a d2  7c 3f".removeWhitespace() == "4ad27c3f");
@@ -500,12 +520,12 @@
  * "".trim() == ""
  * -----
  */
-string trim(string str) {
+inout(char)[] trim(inout(char)[] str) {
 	int start = -1, end = str.length;
 	while( --end >= 0 && " \t\n\r\v\f".contains(str[end]) ) { }
 	end++;
 	if(end == 0) // means all whitespace
-		return "";
+		return str[0..0];
 	while(" \t\n\r\v\f".contains(str[++start])) { }
 	return str[start..end];
 }
@@ -528,7 +548,7 @@
  * "".trimLeft() == ""
  * -----
  */
-string trimLeft(string str) {
+cstring trimLeft(cstring str) {
 	int start = -1;
 	while(++start < str.length && " \t\n\r\v\f".contains(str[start])) { }
 	return str[start..$];
@@ -552,7 +572,7 @@
  * "".trimRight() == ""
  * -----
  */
-string trimRight(string str) {
+cstring trimRight(cstring str) {
 	int end = str.length;
 	while( --end >= 0 && " \t\n\r\v\f".contains(str[end]) ) { }
 	end++;
@@ -576,9 +596,9 @@
 	assert(".NET Framework".find("") == 0);
 	assert("Mississippi".findLast("ss") == 5);
 	assert("Mississippi".findLast("ss", 4) == 2);
-	assert("Jordan=20".split("=") == [cast(string)"Jordan", "20"]);
-	assert("Jordan".split("") == [cast(string)"Jordan"]);
-	assert("Jordan".split1("=") == [cast(string)"Jordan"]);
+	assert("Jordan=20".split("=") == ["Jordan", "20"]);
+	assert("Jordan".split("") == ["Jordan"]);
+	assert("Jordan".split1("=") == ["Jordan"]);
 }
 
 /*class Encoding {
--- a/dynamin/core/unix_console.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/core/unix_console.d	Mon Dec 17 23:41:50 2012 -0600
@@ -29,22 +29,22 @@
 	void backend_buffered(bool b) {
 		buffered = b;
 	}
-	void backend_write(string s) {
+	void backend_write(mstring s) {
 		/*fwrite(s.ptr, 1, s.length, stdout);
 		if(!buffered)
 			fflush(stdout);*/
 	}
-	string backend_readLineRaw() {
+	mstring backend_readLineRaw() {
 		/*uint size;
 		char* line;
 		auto numRead = getline(&line, &size, stdin);
 		scope(exit) free(line);
-		string str = new char[numRead];
+		mstring str = new char[numRead];
 		str[] = line[0..numRead];
 		return str;*/
 		return null;
 	}
-	string backend_read() {
+	mstring backend_read() {
 		return null;
 	}
 	// TODO: use this
@@ -53,20 +53,20 @@
 	//ts.c_lflag |= ICANON; // turns on waiting for a whole lines
 	//ts.c_lflag |= ECHO;   // turns on echoing
 	//tcsetattr(filedes, TCSAFLUSH, &ts);
-	string backend_readLineHidden() {
+	mstring backend_readLineHidden() {
 		system("stty -echo");
 		auto line = readLine();
 		system("stty echo");
 		return line;
 	}
-	string backend_readHidden() {
+	mstring backend_readHidden() {
 		return null;
 	}
 	void backend_clear() {
 		system("clear");
 	}
-	string backend_getColorStr(ConsoleColor c, bool fore) {
-		switch(c) {
+	mstring backend_getColorStr(ConsoleColor c, bool fore) {
+		final switch(c) {
 		case c.Black:      return fore ? "\x1b[30m" : "\x1b[40m";
 		case c.Silver:     return fore ? "\x1b[37m" : "\x1b[47m";
 		case c.Maroon:     return fore ? "\x1b[31m" : "\x1b[41m";
@@ -83,7 +83,6 @@
 		case c.Pink:       return fore ? "\x1b[95m" : "\x1b[105m";
 		case c.Yellow:     return fore ? "\x1b[93m" : "\x1b[103m";
 		case c.Cyan:       return fore ? "\x1b[96m" : "\x1b[106m";
-		default: assert(0);
 		}
 	}
 	void backend_foreColor(ConsoleColor color) {
--- a/dynamin/core/unix_environment.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/core/unix_environment.d	Mon Dec 17 23:41:50 2012 -0600
@@ -37,7 +37,7 @@
 	long backend_timevalToMs(timeval* tv) {
 		return tv.tv_sec*1000L+tv.tv_usec/1000;
 	}
-	const long timerSec = 31_536_000*5; // 31,536,000 seconds in 365 days
+	enum long timerSec = 31_536_000*5; // 31,536,000 seconds in 365 days
 	static this() {
 		itimerval itv;
 		itv.it_value.tv_sec = timerSec;
--- a/dynamin/core/windows_console.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/core/windows_console.d	Mon Dec 17 23:41:50 2012 -0600
@@ -29,7 +29,7 @@
 	void backend_buffered(bool b) {
 		buffered = b;
 	}
-	void backend_write(string s) {
+	void backend_write(mstring s) {
 		// the reasons for this function being slower than writef():
 		//  - partly the conversion overhead (UTF-8 -> UTF16 -> CP)
 		//  - partly because it is not buffered
@@ -51,7 +51,7 @@
 			printf("WriteFile() failed, error %d\n", GetLastError());+/
 
 	}
-	string backend_readLineRaw() {/+
+	mstring backend_readLineRaw() {/+
 		auto stdIn = GetStdHandle(-10);
 		// TODO: does not work if input is from a file!
 		// if reading from a file, a line can be very long...
@@ -69,24 +69,24 @@
 		return ToUtf8(wbuffer[0..numUsed]);+/
 		return null;
 	}
-	string backend_read() {
+	mstring backend_read() {
 		return null;
 	}
-	string backend_readLineHidden() {
+	mstring backend_readLineHidden() {
 		return null;
 	}
-	string backend_readHidden() {
+	mstring backend_readHidden() {
 		return null;
 	}
 	void backend_clear() {
 		system("cls");
 	}
-	uint backend_getColorFlags(ConsoleColor c, bool fore) {
-		uint i = fore ? FOREGROUND_INTENSITY : BACKGROUND_INTENSITY;
-		uint r = fore ? FOREGROUND_RED : BACKGROUND_RED;
-		uint g = fore ? FOREGROUND_GREEN : BACKGROUND_GREEN;
-		uint b = fore ? FOREGROUND_BLUE : BACKGROUND_BLUE;
-		switch(c) {
+	ushort backend_getColorFlags(ConsoleColor c, bool fore) {
+		ushort i = fore ? FOREGROUND_INTENSITY : BACKGROUND_INTENSITY;
+		ushort r = fore ? FOREGROUND_RED : BACKGROUND_RED;
+		ushort g = fore ? FOREGROUND_GREEN : BACKGROUND_GREEN;
+		ushort b = fore ? FOREGROUND_BLUE : BACKGROUND_BLUE;
+		final switch(c) {
 		case c.Black:      return 0;
 		case c.Silver:     return r | g | b;
 		case c.Maroon:     return r;
@@ -103,7 +103,6 @@
 		case c.Pink:       return r | b | i;
 		case c.Yellow:     return r | g | i;
 		case c.Cyan:       return g | b | i;
-		default: assert(0);
 		}
 	}
 	void backend_foreColor(ConsoleColor color) {
--- a/dynamin/core/windows_environment.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/core/windows_environment.d	Mon Dec 17 23:41:50 2012 -0600
@@ -36,7 +36,7 @@
 	long backend_runningTime() {
 		// NOTE: might be a faster way to do this...ProcessorTime is slow
 		// Use ProcessorTime to fix when timeGetTime() rolls over
-		const strayMs = 18_000_000; // 5 hours
+		enum strayMs = 18_000_000; // 5 hours
 		long pNow = processorTime;
 		long tNow = timeGetTime();
 		// pNow-startDiff would equal tNow except that:
--- a/dynamin/gui/basic_theme.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/basic_theme.d	Mon Dec 17 23:41:50 2012 -0600
@@ -27,19 +27,19 @@
  * - dark gray (70, 70, 70)
  */
 class BasicTheme : Theme {
-	string name() {
+	override string name() {
 		return "Basic";
 	}
 
-	void Window_paint(Window c, Graphics g) {
+	override void Window_paint(Window c, Graphics g) {
 		g.source = Color.White;
 		g.paint();
 	}
-	Size Button_bestSize(Button c) {
+	override Size Button_bestSize(Button c) {
 		return Size(60, 25);
 	}
 
-	void Button_paint(Button c, Graphics g) {
+	override void Button_paint(Button c, Graphics g) {
 		with(g) {
 			if(c.state == ButtonState.Pressed)
 				g.source = Color.Black;
@@ -62,7 +62,7 @@
 		}
 	}
 
-	void CheckBox_paint(CheckBox c, Graphics g) {
+	override void CheckBox_paint(CheckBox c, Graphics g) {
 		with(g) {
 			Point box = Point(2, cast(int)(c.height/2-6));
 			fontSize = 13;
@@ -88,7 +88,7 @@
 			}
 		}
 	}
-	void RadioButton_paint(CheckBox c, Graphics g) {
+	override void RadioButton_paint(CheckBox c, Graphics g) {
 		with(g) {
 			int radius = 6;
 			Point circle = Point(2, cast(int)(c.height/2-radius));
@@ -116,7 +116,7 @@
 		}
 	}
 
-	void ScrollBarTrack_paint(ScrollBarTrack c, Graphics g) {
+	override void ScrollBarTrack_paint(ScrollBarTrack c, Graphics g) {
 		if(c.state == ButtonState.Pressed)
 			g.paint();
 		else if(isOdd(cast(int)round(c.x)) || isOdd(cast(int)round(c.y)))
@@ -127,7 +127,7 @@
 				Color.Black, Color.White);
 	}
 
-	void ScrollBarThumb_paint(ScrollBarThumb c, Graphics g) {
+	override void ScrollBarThumb_paint(ScrollBarThumb c, Graphics g) {
 		with(g) {
 			source = Color.White;
 			paint();
@@ -137,20 +137,20 @@
 		}
 	}
 
-	double ScrollBar_size() {
+	override double ScrollBar_size() {
 		// TODO: all themes should get this from SystemGui.ScrollBarSize
 		return 18;
 	}
 
-	void ArrowButton_paint(ArrowButton c, Graphics g) {
+	override void ArrowButton_paint(ArrowButton c, Graphics g) {
 		Button_paint(c, g);
 	}
 
-	BorderSize Scrollable_borderSize(Scrollable c) {
+	override BorderSize Scrollable_borderSize(Scrollable c) {
 		return BorderSize(1, 1, 1, 1);
 	}
 
-	void Scrollable_paint(Scrollable c, Graphics g) {
+	override void Scrollable_paint(Scrollable c, Graphics g) {
 		g.source = Color.White;
 		g.paint();
 		g.source = Color.Black;
@@ -158,11 +158,11 @@
 		g.stroke();
 	}
 
-	BorderSize Notebook_borderSize(Notebook c) {
+	override BorderSize Notebook_borderSize(Notebook c) {
 		return BorderSize(1, 1, 1, 1);
 	}
-	void Tab_paint(TabPage page, Notebook c, Graphics g){}
-	void Notebook_paint(Notebook c, Graphics g){}
+	override void Tab_paint(TabPage page, Notebook c, Graphics g){}
+	override void Notebook_paint(Notebook c, Graphics g){}
 
 }
 
--- a/dynamin/gui/clipboard.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/clipboard.d	Mon Dec 17 23:41:50 2012 -0600
@@ -41,7 +41,7 @@
 	/**
 	 * Sets the data on the clipboard to the specified _text.
 	 */
-	void setText(string text) {
+	void setText(cstring text) {
 		backend_setText(text);
 	}
 	alias setText copyText;
@@ -49,7 +49,7 @@
 	 * Gets text from the clipboard. If the clipboard does not have any text
 	 * or has an empty string, null is returned.
 	 */
-	string getText() {
+	mstring getText() {
 		return backend_getText();
 	}
 	alias getText pasteText;
@@ -75,11 +75,11 @@
 	mixin SelectionBackend;
 public:
 	///
-	void setText(string text) {
+	void setText(cstring text) {
 		backend_setText(text);
 	}
 	///
-	string getText() {
+	mstring getText() {
 		return backend_getText();
 	}
 	///
--- a/dynamin/gui/container.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/container.d	Mon Dec 17 23:41:50 2012 -0600
@@ -438,15 +438,15 @@
 	///
 	ControlList children() { return _children; }
 	///
-	void add(Control child) { super.add(child); };
+	override void add(Control child) { super.add(child); };
 	///
-	void remove(Control child) { super.remove(child); };
+	override void remove(Control child) { super.remove(child); };
 	///
-	int opApply(int delegate(ref Control item) dg) {
+	override int opApply(int delegate(ref Control item) dg) {
 		return super.opApply(dg);
 	}
 	///
-	int opApply(int delegate(ref uint index, ref Control item) dg) {
+	override int opApply(int delegate(ref uint index, ref Control item) dg) {
 		return super.opApply(dg);
 	}
 }
--- a/dynamin/gui/control.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/control.d	Mon Dec 17 23:41:50 2012 -0600
@@ -557,12 +557,12 @@
 	/**
 	 * Gets or sets the text that this control shows.
 	 */
-	string text() { return _text.dup; }
+	string text() { return _text; }
 	/// ditto
 	void text(string str) {
 		if(_text == str)
 			return;
-		_text = str.dup;
+		_text = str;
 		repaint();
 		//TextChanged(EventArgs e) // TODO: add event
 	}
--- a/dynamin/gui/events.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/events.d	Mon Dec 17 23:41:50 2012 -0600
@@ -59,7 +59,7 @@
 	double y() { return _location.y; }
 	///
 	MouseButton button() { return _button; }
-	string toString() {
+	override string toString() {
 		return format("MouseEventArgs [x={}, y={}, button={}]",
 			x, y, _button);
 	}
@@ -95,7 +95,7 @@
 	bool scrollScreen() {
 		return _scrollScreen;
 	}
-	string toString() {
+	override string toString() {
 		return format("MouseTurnedEventArgs [scrollAmount={}, scrollScreen={}]",
 			_scrollAmount, _scrollScreen);
 	}
@@ -130,7 +130,7 @@
 	bool controlDown() { return _controlDown; }
 	// Returns true if the alt key is currently down and false otherwise.
 	bool altDown() { return _altDown; }
-	string toString() {
+	override string toString() {
 		return format("KeyEventArgs [key={}, repeat={}]", _key, _repeat);
 	}
 }
--- a/dynamin/gui/file_dialog.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/file_dialog.d	Mon Dec 17 23:41:50 2012 -0600
@@ -18,7 +18,7 @@
 	string name;
 	string[] extensions;
 	// ignored for now
-	bool delegate(string fileName) shouldShow;
+	bool delegate(cstring fileName) shouldShow;
 }
 
 /**
@@ -77,7 +77,7 @@
 	 * returns true for.
 	 * BUG: not implemented
 	 */
-	void addFilter(string name, string ext, bool delegate(string fileName) shouldShow) {
+	void addFilter(string name, string ext, bool delegate(cstring fileName) shouldShow) {
 		// TODO:
 		throw new Exception("addFilter(string, string, delegate) not implemented");
 		FileDialogFilter filter;
--- a/dynamin/gui/key.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/key.d	Mon Dec 17 23:41:50 2012 -0600
@@ -95,7 +95,7 @@
 	Alt     = 0x40000
 }
 
-const string[] keyStringTable = [
+enum string[] keyStringTable = [
 	"None", "Escape", "Tab", "Backspace", "Enter", "Space",
 	"Left Arrow", "Right Arrow", "Up Arrow", "Down Arrow",
 	"Insert", "Delete", "Home", "End", "Page Up", "Page Down",
@@ -122,7 +122,7 @@
 		return "Alt";
 	return keyStringTable[key];
 }
-Key toKey(string str) {
+Key toKey(mstring str) {
 	if(!str)
 		return Key.None;
 	foreach(i, s; keyStringTable)
--- a/dynamin/gui/layout.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/layout.d	Mon Dec 17 23:41:50 2012 -0600
@@ -34,7 +34,7 @@
 */
 
 enum LayoutType {
-	None, Table, Control, Filler, Spacer
+	Table, Control, Filler, Spacer
 }
 enum Elasticity {
 	No, Semi, Yes
@@ -84,7 +84,7 @@
 
 	//{{{ _elasticX()
 	private Elasticity _elasticX() {
-		switch(type) {
+		final switch(type) {
 		case LayoutType.Control:
 			return control.elasticX ? Elasticity.Yes : Elasticity.No;
 		case LayoutType.Table:
@@ -108,7 +108,7 @@
 	//}}}
 	//{{{ _elasticY()
 	private Elasticity _elasticY() {
-		switch(type) {
+		final switch(type) {
 		case LayoutType.Control:
 			return control.elasticY ? Elasticity.Yes : Elasticity.No;
 		case LayoutType.Table:
@@ -133,7 +133,7 @@
 
 	//{{{ _bestSize()
 	private Size _bestSize() {
-		switch(type) {
+		final switch(type) {
 		case LayoutType.Control:
 			return control.bestSize;
 		case LayoutType.Table:
@@ -150,7 +150,7 @@
 	//}}}
 	//{{{ _baseline()
 	private int _baseline() {
-		switch(type) {
+		final switch(type) {
 		case LayoutType.Control:
 			return control.baseline;
 		case LayoutType.Table:
@@ -170,7 +170,7 @@
 
 	//{{{ layout()
 	void layout(Rect rect) {
-		switch(type) {
+		final switch(type) {
 		case LayoutType.Control:
 			control.location = Point(rect.x, rect.y);
 			control.size = Size(rect.width, rect.height);
@@ -379,7 +379,7 @@
  * pretty sure it is a DMD bug, but I don't have time to make a testcase
  * for a bug that does not bother me.) This will work correctly:
  * -----
- * const char[] s = createLayout("V( b1 H(b2 b3) )");
+ * enum char[] s = createLayout("V( b1 H(b2 b3) )");
  * -----
  * Because then the function is interpreted at compile time with CTFE.
  */
@@ -427,11 +427,11 @@
 }
 
 // {{{ copied from Phobos
-char[] ctfeUintToString(uint u) {
+string ctfeUintToString(uint u) {
 	char[uint.sizeof * 3] buffer = void;
 	int ndigits;
-	char[] result;
-	char[] digits = "0123456789";
+	string result;
+	string digits = "0123456789";
 
 	ndigits = 0;
 	if (u < 10)
@@ -446,12 +446,11 @@
 			ndigits++;
 			buffer[buffer.length - ndigits] = cast(char)c;
 		}
-		result = new char[ndigits];
-		result[] = buffer[buffer.length - ndigits .. buffer.length];
+		result = buffer[$ - ndigits .. $].idup;
 	}
 	return result;
 }
-uint ctfeStringToUint(char[] s)
+uint ctfeStringToUint(string s)
 {
 	int length = s.length;
 
@@ -568,28 +567,28 @@
 
 unittest {
 	class FakeButton : Control {
-		Size bestSize() { return Size(80, 30); }
-		bool elasticX() { return false; }
-		bool elasticY() { return false; }
-		int baseline() { return 20; }
+		override Size bestSize() { return Size(80, 30); }
+		override bool elasticX() { return false; }
+		override bool elasticY() { return false; }
+		override int baseline() { return 20; }
 	}
 	class FakeTextBox : Control {
-		Size bestSize() { return Size(100, 20); }
-		bool elasticX() { return true; }
-		bool elasticY() { return false; }
-		int baseline() { return 18; }
+		override Size bestSize() { return Size(100, 20); }
+		override bool elasticX() { return true; }
+		override bool elasticY() { return false; }
+		override int baseline() { return 18; }
 	}
 	class FakeListBox : Control {
-		Size bestSize() { return Size(100, 300); }
-		bool elasticX() { return false; }
-		bool elasticY() { return true; }
-		int baseline() { return 15; }
+		override Size bestSize() { return Size(100, 300); }
+		override bool elasticX() { return false; }
+		override bool elasticY() { return true; }
+		override int baseline() { return 15; }
 	}
 	class FakeLabel : Control {
-		Size bestSize() { return Size(70, 15); }
-		bool elasticX() { return false; }
-		bool elasticY() { return false; }
-		int baseline() { return 13; }
+		override Size bestSize() { return Size(70, 15); }
+		override bool elasticX() { return false; }
+		override bool elasticY() { return false; }
+		override int baseline() { return 13; }
 	}
 	auto button1 = new FakeButton();
 	auto tb1 = new FakeTextBox();
--- a/dynamin/gui/list_box.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/list_box.d	Mon Dec 17 23:41:50 2012 -0600
@@ -23,7 +23,7 @@
  */
 class ListBox : Scrollable {
 protected:
-	List!(string, true) _items;
+	List!(mstring, true) _items;
 	int _selectedIndex = -1;
 
 	override void whenKeyDown(KeyEventArgs e) {
@@ -68,7 +68,7 @@
 	/// This event occurs after the selection has changed.
 	Event!(whenSelectionChanged) selectionChanged;
 
-	void whenListItemsChanged(ListChangeType, string, string, uint) {
+	void whenListItemsChanged(ListChangeType, mstring, mstring, uint) {
 		super.layout();
 		repaint();
 	}
@@ -76,7 +76,7 @@
 	///
 	this() {
 		selectionChanged.setUp(&whenSelectionChanged);
-		_items = new List!(string, true)(&whenListItemsChanged);
+		_items = new List!(mstring, true)(&whenListItemsChanged);
 
 		super();
 		_focusable = true;
@@ -84,7 +84,7 @@
 		backColor = WindowsTheme.getColor(5);
 	}
 	///
-	List!(string, true) items() {
+	List!(mstring, true) items() {
 		return _items;
 	}
 	///
--- a/dynamin/gui/scroll_bar.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/scroll_bar.d	Mon Dec 17 23:41:50 2012 -0600
@@ -238,24 +238,24 @@
 		_button2.direction = ArrowDirection.Right;
 	}
 protected:
-	void whenThumbMouseDown(MouseEventArgs e) {
+	override void whenThumbMouseDown(MouseEventArgs e) {
 		_thumbDragLoc = e.location.x;
 	}
-	void whenThumbMouseDragged(MouseEventArgs e) {
+	override void whenThumbMouseDragged(MouseEventArgs e) {
 		_thumb.state = ButtonState.Pressed;
 		thumbLocation = e.location.x + _thumb.location.x - _thumbDragLoc;
 	}
-	void putControl(Control c, double location, double size) {
+	override void putControl(Control c, double location, double size) {
 		c.location = [location, 0.0];
 		c.size = [size, height];
 	}
-	double breadth() { return height; }
-	double length() { return width; }
+	override double breadth() { return height; }
+	override double length() { return width; }
 	alias ScrollBar.thumbLocation thumbLocation;
-	double thumbLocation() { return _thumb.x; }
-	double thumbSize() { return _thumb.width; }
-	double trackStart() { return _track1.x; }
-	double trackEnd() { return _track2.x+_track2.width; }
+	override double thumbLocation() { return _thumb.x; }
+	override double thumbSize() { return _thumb.width; }
+	override double trackStart() { return _track1.x; }
+	override double trackEnd() { return _track2.x+_track2.width; }
 }
 ///
 class VScrollBar : ScrollBar {
@@ -264,23 +264,23 @@
 		_button2.direction = ArrowDirection.Down;
 	}
 protected:
-	void whenThumbMouseDown(MouseEventArgs e) {
+	override void whenThumbMouseDown(MouseEventArgs e) {
 		_thumbDragLoc = e.location.y;
 	}
-	void whenThumbMouseDragged(MouseEventArgs e) {
+	override void whenThumbMouseDragged(MouseEventArgs e) {
 		_thumb.state = ButtonState.Pressed;
 		thumbLocation = e.location.y + _thumb.location.y - _thumbDragLoc;
 	}
-	void putControl(Control c, double location, double size) {
+	override void putControl(Control c, double location, double size) {
 		c.location = [0.0, location];
 		c.size = [width, size];
 	}
-	double breadth() { return width; }
-	double length() { return height; }
+	override double breadth() { return width; }
+	override double length() { return height; }
 	alias ScrollBar.thumbLocation thumbLocation;
-	double thumbLocation() { return _thumb.y; }
-	double thumbSize() { return _thumb.height; }
-	double trackStart() { return _track1.y; }
-	double trackEnd() { return _track2.y+_track2.height; }
+	override double thumbLocation() { return _thumb.y; }
+	override double thumbSize() { return _thumb.height; }
+	override double trackStart() { return _track1.y; }
+	override double trackEnd() { return _track2.y+_track2.height; }
 }
 
--- a/dynamin/gui/scrollable.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/scrollable.d	Mon Dec 17 23:41:50 2012 -0600
@@ -230,7 +230,7 @@
 	 * Gets whether the horizontal scroll bar is currently shown.
 	 */
 	bool HScrollBarVisible() {
-		switch(_scrollBars) {
+		final switch(_scrollBars) {
 		case VisibleScrollBars.None:
 		case VisibleScrollBars.Vertical:
 			return false;
@@ -251,7 +251,7 @@
 	 * Gets whether the vertical scroll bar is currently shown.
 	 */
 	bool VScrollBarVisible() {
-		switch(_scrollBars) {
+		final switch(_scrollBars) {
 		case VisibleScrollBars.None:
 		case VisibleScrollBars.Horizontal:
 			return false;
--- a/dynamin/gui/silver_theme.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/silver_theme.d	Mon Dec 17 23:41:50 2012 -0600
@@ -28,15 +28,15 @@
  * - (150, 150, 150)
  */
 class SilverTheme : Theme {
-	string name() {
+	override string name() {
 		return "Silver";
 	}
 
-	void Window_paint(Window c, Graphics g) {
+	override void Window_paint(Window c, Graphics g) {
 		g.source = Color.Silver;
 		g.paint();
 	}
-	Size Button_bestSize(Button c) {
+	override Size Button_bestSize(Button c) {
 		return Size(70, 25);
 	}
 
@@ -74,7 +74,7 @@
 	}
 	//}}}
 
-	void Button_paint(Button c, Graphics g) {
+	override void Button_paint(Button c, Graphics g) {
 		with(g) {
 			drawButtonBack(g, 0, 0, c.width, c.height, c.state);
 			source = _black;
@@ -82,7 +82,7 @@
 		}
 	}
 
-	void CheckBox_paint(CheckBox c, Graphics g) {
+	override void CheckBox_paint(CheckBox c, Graphics g) {
 		with(g) {
 			Point box = Point(2, cast(int)(c.height/2-6));
 			fontSize = 13;
@@ -108,7 +108,7 @@
 			}
 		}
 	}
-	void RadioButton_paint(CheckBox c, Graphics g) {
+	override void RadioButton_paint(CheckBox c, Graphics g) {
 		with(g) {
 			int radius = 6;
 			Point circle = Point(2, cast(int)(c.height/2-radius));
@@ -136,7 +136,7 @@
 		}
 	}
 
-	void ScrollBarTrack_paint(ScrollBarTrack c, Graphics g) {
+	override void ScrollBarTrack_paint(ScrollBarTrack c, Graphics g) {
 		if(c.state == ButtonState.Pressed)
 			g.paint();
 		else if(isOdd(cast(int)round(c.x)) || isOdd(cast(int)round(c.y)))
@@ -147,7 +147,7 @@
 				Color.Black, Color.White);
 	}
 
-	void ScrollBarThumb_paint(ScrollBarThumb c, Graphics g) {
+	override void ScrollBarThumb_paint(ScrollBarThumb c, Graphics g) {
 		with(g) {
 			source = Color.White;
 			paint();
@@ -157,20 +157,20 @@
 		}
 	}
 
-	double ScrollBar_size() {
+	override double ScrollBar_size() {
 		// TODO: all themes should get this from SystemGui.ScrollBarSize
 		return 18;
 	}
 
-	void ArrowButton_paint(ArrowButton c, Graphics g) {
+	override void ArrowButton_paint(ArrowButton c, Graphics g) {
 		Button_paint(c, g);
 	}
 
-	BorderSize Scrollable_borderSize(Scrollable c) {
+	override BorderSize Scrollable_borderSize(Scrollable c) {
 		return BorderSize(1, 1, 1, 1);
 	}
 
-	void Scrollable_paint(Scrollable c, Graphics g) {
+	override void Scrollable_paint(Scrollable c, Graphics g) {
 		g.source = Color.White;
 		g.paint();
 		g.source = Color.Black;
@@ -178,15 +178,15 @@
 		g.stroke();
 	}
 
-	BorderSize Notebook_borderSize(Notebook c) {
+	override BorderSize Notebook_borderSize(Notebook c) {
 		return BorderSize(1, 1, 1, 1);
 	}
-	void Tab_paint(TabPage page, Notebook c, Graphics g){
+	override void Tab_paint(TabPage page, Notebook c, Graphics g){
 		g.translate(page.tabLocation);
 		g.drawText(page.text, 5, (page.tabSize.height-g.getTextExtents(page.text).height)/2);
 		g.translate(-page.tabLocation);
 	}
-	void Notebook_paint(Notebook c, Graphics g){}
+	override void Notebook_paint(Notebook c, Graphics g){}
 
 }
 
--- a/dynamin/gui/theme.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/theme.d	Mon Dec 17 23:41:50 2012 -0600
@@ -64,7 +64,7 @@
 	for(int i = 0; i < height; ++i) {
 		oddRow = i % squareSize2 < squareSize;
 		for(int j = 0; j < width; ++j) {
-			if(oddRow ^ j % squareSize2 < squareSize)
+			if(oddRow ^ (j % squareSize2 < squareSize))
 				data[j+i*width] = pixel1;
 			else
 				data[j+i*width] = pixel2;
--- a/dynamin/gui/window.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/window.d	Mon Dec 17 23:41:50 2012 -0600
@@ -443,7 +443,7 @@
 	}
 
 	alias Control.repaint repaint;
-	void repaint(Rect rect) {
+	override void repaint(Rect rect) {
 		if(!handleCreated)
 			return;
 		backend_repaint(rect);
@@ -485,7 +485,7 @@
 
 	// TODO: 1.0  MinSize -> contentMinSize  MaxSize -> contentMaxSize
 	alias Control.location location;
-	void location(Point pt) {
+	override void location(Point pt) {
 		super.location(pt);
 		if(!handleCreated)
 			return;
@@ -493,7 +493,7 @@
 	}
 
 	alias Control.size size;
-	void size(Size size) {
+	override void size(Size size) {
 		super.size(size);
 		_content.size = size - _borderSize;
 		if(!handleCreated)
@@ -502,7 +502,7 @@
 	}
 
 	alias Control.text text;
-	void text(string str) {
+	override void text(string str) {
 		super.text(str);
 		if(!handleCreated)
 			return;
@@ -529,7 +529,7 @@
 			rect = desktopRect;
 		}
 		Point newLoc = Point();
-		switch(pos) {
+		final switch(pos) {
 		case Position.TopLeft:
 		case Position.Left:
 		case Position.BottomLeft:
@@ -546,7 +546,7 @@
 			newLoc.x = rect.x + rect.width - width;
 			break;
 		}
-		switch(pos) {
+		final switch(pos) {
 		case Position.TopLeft:
 		case Position.Top:
 		case Position.TopRight:
--- a/dynamin/gui/windows_clipboard.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/windows_clipboard.d	Mon Dec 17 23:41:50 2012 -0600
@@ -14,7 +14,7 @@
 import Utf = tango.text.convert.Utf;
 
 template ClipboardBackend() {
-	void backend_setText(string text) {
+	void backend_setText(cstring text) {
 		if(!OpenClipboard(msgWnd))
 			return;
 		EmptyClipboard();
@@ -27,7 +27,7 @@
 		SetClipboardData(CF_UNICODETEXT, data);
 		CloseClipboard();
 	}
-	string backend_getText() {
+	mstring backend_getText() {
 		if(!OpenClipboard(msgWnd))
 			return null;
 		wchar* data = cast(wchar*)GetClipboardData(CF_UNICODETEXT);
@@ -48,9 +48,9 @@
 
 // Windows only has one clipboard
 template SelectionBackend() {
-	void backend_setText(string text) {
+	void backend_setText(cstring text) {
 	}
-	string backend_getText() {
+	mstring backend_getText() {
 		return null;
 	}
 	bool backend_containsText() {
--- a/dynamin/gui/windows_cursor.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/windows_cursor.d	Mon Dec 17 23:41:50 2012 -0600
@@ -32,7 +32,7 @@
 			Stdout.format("LoadImage() failed loading cursor {}", curRes).newline;
 		return new Cursor(hcur);
 	}
-	Cursor backend_getCursor(wchar[] name) {
+	Cursor backend_getCursor(const(wchar)[] name) {
 		HCURSOR hcur = LoadImage(GetModuleHandle(null), name.ptr,
 			IMAGE_CURSOR, 0, 0, LR_DEFAULTSIZE);
 		if(hcur is null)
--- a/dynamin/gui/windows_file_dialog.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/windows_file_dialog.d	Mon Dec 17 23:41:50 2012 -0600
@@ -20,13 +20,13 @@
 		//ofn.hwndOwner = ;
 
 		ensureAllFilesFilter();
-		string filterStr;
+		mstring filterStr;
 		foreach(filter; _filters) {
 			if(filter.shouldShow)
 				continue;
 			string[] exts = filter.extensions.dup;
 			if(exts.length == 0)
-				exts = [cast(string)"*.*"];
+				exts = ["*.*"];
 			else
 				for(int i = 0; i < exts.length; ++i)
 					exts[i] = "*." ~ exts[i];
@@ -71,8 +71,7 @@
 		for(index = filesBufferW.length; index > 0; --index)
 			if(filesBufferW[index-1] != 0)
 				break;
-		auto filesBuffer = Utf.toString(filesBufferW[0..index]);
-		scope(exit) delete filesBuffer;
+		auto filesBuffer = cast(immutable)Utf.toString(filesBufferW[0..index]);
 		if(filesBuffer.contains('\0')) { // multiple files
 			auto arr = filesBuffer.split("\0");
 			_folder = arr[0];
@@ -90,8 +89,8 @@
 			}
 		} else { //single file
 			assert(filesBuffer.contains('\\'));
-			_folder = filesBuffer[0..filesBuffer.findLast("\\")].dup;
-			_files = [filesBuffer.dup];
+			_folder = filesBuffer[0..filesBuffer.findLast("\\")];
+			_files = [filesBuffer];
 			maybeAddExt(_files[0]);
 		}
 
--- a/dynamin/gui/windows_folder_dialog.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/windows_folder_dialog.d	Mon Dec 17 23:41:50 2012 -0600
@@ -50,7 +50,7 @@
 				}
 				break;
 			}
-		_folder = Utf.toString(dirBuffer[0..index]);
+		_folder = cast(immutable)Utf.toString(dirBuffer[0..index]);
 		return DialogResult.OK;
 	}
 }
--- a/dynamin/gui/windows_theme.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/windows_theme.d	Mon Dec 17 23:41:50 2012 -0600
@@ -81,7 +81,7 @@
  */
 class WindowsTheme : Theme {
 version(Windows) {
-	static string defaultFont() { // TODO: rename
+	static mstring defaultFont() { // TODO: rename
 		NONCLIENTMETRICS ncMetrics;
 		ncMetrics.cbSize = NONCLIENTMETRICS.sizeof;
 		SystemParametersInfo(SPI_GETNONCLIENTMETRICS,
@@ -92,7 +92,7 @@
 }
 version(Windows) {
 	static void printSysColors() {
-		int[string] colors = [
+		int[mstring] colors = [
 		"COLOR_SCROLLBAR"[] : COLOR_SCROLLBAR,
 		"COLOR_BACKGROUND" : COLOR_BACKGROUND,
 		"COLOR_ACTIVECAPTION" : COLOR_ACTIVECAPTION,
@@ -153,12 +153,14 @@
 
 	//{{{ utility functions
 	int findUxState(Button c, int disabled, int normal, int hot, int pressed) {
-		if(c.state == ButtonState.Normal)
+		final switch(c.state) {
+		case ButtonState.Normal:
 			return normal;
-		else if(c.state == ButtonState.Hot)
+		case ButtonState.Hot:
 			return hot;
-		else if(c.state == ButtonState.Pressed)
+		case ButtonState.Pressed:
 			return pressed;
+		}
 	}
 
 	/// draws a classic check, which is 7 wide and 7 high
@@ -181,21 +183,21 @@
 	}
 	//}}}
 
-	string name() {
+	override string name() {
 		return "Windows";
 	}
 
-	void Window_paint(Window c, Graphics g) {
+	override void Window_paint(Window c, Graphics g) {
 		g.source = getColor(COLOR_3DFACE);
 		g.paint();
 	}
 	//{{{ Button
-	Size Button_bestSize(Button c) {
+	override Size Button_bestSize(Button c) {
 		// default button size is 17 points tall
 		return Size(75, 23);
 	}
 
-	void Button_paint(Button c, Graphics g) {
+	override void Button_paint(Button c, Graphics g) {
 version(Windows) {
 		if(Ux.isThemeActive()) {
 			auto uxState = findUxState(c, PBS_DISABLED, PBS_NORMAL, PBS_HOT, PBS_PRESSED);
@@ -231,7 +233,7 @@
 	//}}}
 
 	//{{{ CheckBox
-	void CheckBox_paint(CheckBox c, Graphics g) {
+	override void CheckBox_paint(CheckBox c, Graphics g) {
 version(Windows) {
 		if(Ux.isThemeActive()) {
 			int uxState;
@@ -277,7 +279,7 @@
 	//}}}
 
 	//{{{ RadioButton
-	void RadioButton_paint(CheckBox c, Graphics g) {
+	override void RadioButton_paint(CheckBox c, Graphics g) {
 version(Windows) {
 		if(Ux.isThemeActive()) {
 			int uxState;
@@ -305,11 +307,11 @@
 
 		g.rectangle(2, 2, 8, 8);
 		g.fill();
-		const double[][] outerLines = [
+		enum double[][] outerLines = [
 		[1.5, 8,   1.5, 10],  [0.5, 4,   0.5, 8],
 		[1.5, 2,   1.5, 4],   [2.0, 1.5,   4, 1.5],
 		[4.0, 0.5,   8, 0.5], [8.0, 1.5,   10, 1.5]];
-		const double[][] innerLines = [
+		enum double[][] innerLines = [
 		[2.5, 8,   2.5, 9],  [1.5, 4,   1.5, 8],
 		[2.5, 2,   2.5, 4],   [3.0, 2.5,   4, 2.5],
 		[4.0, 1.5,   8, 1.5], [8.0, 2.5,   10, 2.5]];
@@ -357,7 +359,7 @@
 	//}}}
 
 	//{{{ ScrollBar
-	void ScrollBarTrack_paint(ScrollBarTrack c, Graphics g) {
+	override void ScrollBarTrack_paint(ScrollBarTrack c, Graphics g) {
 version(Windows) {
 		if(Ux.isThemeActive()) {
 			auto uxState = findUxState(c, SCRBS_DISABLED, SCRBS_NORMAL, SCRBS_HOT, SCRBS_PRESSED);
@@ -380,7 +382,7 @@
 		c1, c2);
 	}
 
-	void ScrollBarThumb_paint(ScrollBarThumb c, Graphics g) {
+	override void ScrollBarThumb_paint(ScrollBarThumb c, Graphics g) {
 version(Windows) {
 		if(Ux.isThemeActive()) {
 			auto uxState = findUxState(c, SCRBS_DISABLED, SCRBS_NORMAL, SCRBS_HOT, SCRBS_PRESSED);
@@ -405,7 +407,7 @@
 			getColor(COLOR_3DHIGHLIGHT), getColor(COLOR_3DSHADOW));
 	}
 
-	double ScrollBar_size() {
+	override double ScrollBar_size() {
 		// TODO: all themes should get this from SystemGui.ScrollBarSize
 	version(Windows)
 		return GetSystemMetrics(SM_CXVSCROLL);
@@ -413,7 +415,7 @@
 		return 18;
 	}
 
-	void ArrowButton_paint(ArrowButton c, Graphics g) {
+	override void ArrowButton_paint(ArrowButton c, Graphics g) {
 version(Windows) {
 		if(Ux.isThemeActive()) {
 			int uxState;
@@ -446,11 +448,11 @@
 	//}}}
 
 	//{{{ Scrollable
-	BorderSize Scrollable_borderSize(Scrollable c) {
+	override BorderSize Scrollable_borderSize(Scrollable c) {
 		return BorderSize(2, 2, 2, 2);
 	}
 
-	void Scrollable_paint(Scrollable c, Graphics g) {
+	override void Scrollable_paint(Scrollable c, Graphics g) {
 version(Windows) {
 		if(Ux.isThemeActive()) {
 			Ux.drawBackground(g, Rect(0, 0, c.width, c.height), "EDIT", EP_EDITTEXT, ETS_NORMAL);
@@ -470,14 +472,14 @@
 	//}}}
 
 	//{{{ Notebook
-	BorderSize Notebook_borderSize(Notebook c) {
+	override BorderSize Notebook_borderSize(Notebook c) {
 version(Windows) {
 		if(Ux.isThemeActive())
 			return BorderSize(2, 2, 4, 4);
 }
 		return BorderSize(2, 2, 2, 2);
 	}
-	void Tab_paint(TabPage page, Notebook c, Graphics g) {
+	override void Tab_paint(TabPage page, Notebook c, Graphics g) {
 version(Windows) {
 		if(Ux.isThemeActive()) {
 			g.translate(page.tabLocation);
@@ -517,7 +519,7 @@
 		g.drawText(page.text, 5, (page.tabSize.height-g.getTextExtents(page.text).height)/2);
 		g.translate(-page.tabLocation);
 	}
-	void Notebook_paint(Notebook c, Graphics g) {
+	override void Notebook_paint(Notebook c, Graphics g) {
 version(Windows) {
 		if(Ux.isThemeActive()) {
 			//auto uxState = findUxState(c, PBS_DISABLED, PBS_NORMAL, PBS_HOT, PBS_PRESSED);
--- a/dynamin/gui/windows_window.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/windows_window.d	Mon Dec 17 23:41:50 2012 -0600
@@ -49,7 +49,7 @@
 	info.dwOSVersionInfoSize = OSVERSIONINFO.sizeof;
 	GetVersionEx(&info);
 	DWORD major, minor;
-	switch(ver) {
+	final switch(ver) {
 	case WindowsVersion.Windows95:    major = 4; minor = 0; break;
 	case WindowsVersion.Windows98:    major = 4; minor = 10; break;
 	case WindowsVersion.WindowsMe:    major = 4; minor = 90; break;
@@ -338,7 +338,7 @@
 				GetProcAddress(uxLib, "DrawThemeBackground");
 		}
 	}
-	HTHEME[string] cache;
+	HTHEME[mstring] cache;
 	// opens an HTHEME for the specified controlName and caches it
 	// next time, just returns the HTHEME from the cache
 	HTHEME getHTHEME(string controlName) {
@@ -515,15 +515,15 @@
 			cast(short)HIWORD(lParam)+c.borderSize.top, button);
 		func(args);
 	}
-	void snapSide(inout int sideToSnap, float side1, float side2) {
+	void snapSide(ref int sideToSnap, float side1, float side2) {
 		if(sideToSnap >= side1-c.snapDistance && sideToSnap <= side1+c.snapDistance)
 			sideToSnap = cast(int)side1;
 		if(sideToSnap >= side2-c.snapDistance && sideToSnap <= side2+c.snapDistance)
 			sideToSnap = cast(int)side2;
 	}
-	auto emptyFunc = (Rect snapRect) {};
+	void delegate(Rect snapRect) emptyFunc = (Rect snapRect) { };
 	// used to snap vertical sides, left and right
-	void snapVSide(inout int side, RECT* rect, void delegate(Rect snapRect) func = emptyFunc) {
+	void snapVSide(ref int side, RECT* rect, void delegate(Rect snapRect) func = emptyFunc) {
 		if(c.snapRects is null)
 			return;
 		foreach(snapRect; c.snapRects) {
@@ -534,7 +534,7 @@
 		}
 	}
 	// used to snap horizontal sides, top and bottom
-	void snapHSide(inout int side, RECT* rect, void delegate(Rect snapRect) func = emptyFunc) {
+	void snapHSide(ref int side, RECT* rect, void delegate(Rect snapRect) func = emptyFunc) {
 		if(c.snapRects is null)
 			return;
 		foreach(snapRect; c.snapRects) {
--- a/dynamin/gui/x_clipboard.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/x_clipboard.d	Mon Dec 17 23:41:50 2012 -0600
@@ -41,7 +41,7 @@
 
 }
 
-string backend_getSelText(XAtom sel, ref ClipboardData data) {
+mstring backend_getSelText(XAtom sel, ref ClipboardData data) {
 	XConvertSelection(display, sel, XA.UTF8_STRING, XA.DYNAMIN_SELECTION, msgWin, CurrentTime);
 	XSync(display, false);
 	auto start = Environment.runningTime;
@@ -66,7 +66,7 @@
 		scope(exit) XFree(propData);
 		XDeleteProperty(display, msgWin, selEv.property);
 
-		string str = new char[count];
+		mstring str = new char[count];
 		str[] = propData[0..count];
 		return str;
 	}
@@ -77,7 +77,7 @@
 	uint length; // number of bytes in data
 }
 // always called from the event thread...don't have to avoid static data
-void backend_setSelText(XAtom sel, string text, ref ClipboardData data) {
+void backend_setSelText(XAtom sel, cstring text, ref ClipboardData data) {
 	XSetSelectionOwner(display, sel, msgWin, CurrentTime);
 	data.target = XA.UTF8_STRING;
 	data.data = text.ptr;
@@ -88,10 +88,10 @@
 
 template ClipboardBackend() {
 	ClipboardData data; // make array when supporting multiple types (PNG & BMP)
-	void backend_setText(string text) {
+	void backend_setText(cstring text) {
 		backend_setSelText(XA.CLIPBOARD, text, data);
 	}
-	string backend_getText() {
+	mstring backend_getText() {
 		return backend_getSelText(XA.CLIPBOARD, data);
 	}
 	bool backend_containsText() {
@@ -101,10 +101,10 @@
 
 template SelectionBackend() {
 	ClipboardData data; // make array when supporting multiple types (PNG & BMP)
-	void backend_setText(string text) {
+	void backend_setText(cstring text) {
 		backend_setSelText(XA.PRIMARY, text, data);
 	}
-	string backend_getText() {
+	mstring backend_getText() {
 		return backend_getSelText(XA.PRIMARY, data);
 	}
 	bool backend_containsText() {
--- a/dynamin/gui/x_file_dialog.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/x_file_dialog.d	Mon Dec 17 23:41:50 2012 -0600
@@ -19,7 +19,7 @@
 		// gdk_x11_get_server_time             (GdkWindow *window)
 		// could be used in clipboard
 
-		string title = text ? text : (fileDialogType == Open ? "Open" : "Save");
+		mstring title = text ? text : (fileDialogType == Open ? "Open" : "Save");
 		auto dialog = gtk_file_chooser_dialog_new(toCharPtr(title), null,
 			fileDialogType == Open ?
 			GTK_FILE_CHOOSER_ACTION_OPEN : GTK_FILE_CHOOSER_ACTION_SAVE,
@@ -63,7 +63,7 @@
 			g_slist_free(gfilters);
 
 			auto list = gtk_file_chooser_get_filenames(dialog);
-			_files = new string[g_slist_length(list)];
+			_files = new mstring[g_slist_length(list)];
 			for(int i = 0; i < _files.length; ++i) {
 				auto d = cast(char*)list.data;
 				_files[i] = d[0..strlen(d)].dup;
--- a/dynamin/gui/x_folder_dialog.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/x_folder_dialog.d	Mon Dec 17 23:41:50 2012 -0600
@@ -16,7 +16,7 @@
 
 template FolderDialogBackend() {
 	DialogResult backend_showDialog() {
-		string title = text ? text : "Select Folder";
+		mstring title = text ? text : "Select Folder";
 		auto dialog = gtk_file_chooser_dialog_new(toCharPtr(title), null,
 			GTK_FILE_CHOOSER_ACTION_SELECT_FOLDER,
 			GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
--- a/dynamin/gui/x_window.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/gui/x_window.d	Mon Dec 17 23:41:50 2012 -0600
@@ -185,7 +185,7 @@
 		return x2 <= x1 + width1 && y2 <= y1 + height1 &&
 			x2 + width2 >= x1 && y2 + height2 >= y1;
 	}
-	void join(inout int x, inout int y, inout int width, inout int height,
+	void join(ref int x, ref int y, ref int width, ref int height,
 			int x2, int y2, int width2, int height2) {
 		auto minx = min(x, x2);
 		auto miny = min(y, y2);
@@ -695,7 +695,7 @@
 		backend_updateWM_NORMAL_HINTS();
 		backend_locationSizeToNative();
 	}
-	void backend_text(string str) {
+	void backend_text(mstring str) {
 		//auto tmp = str.ToCharPtr();
 		//XTextProperty strProperty;
 		//if(!XStringListToTextProperty(&tmp, 1, &strProperty))
--- a/dynamin/painting/color.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/painting/color.d	Mon Dec 17 23:41:50 2012 -0600
@@ -95,7 +95,7 @@
 		B = 255 - B;
 	}
 	string toUtf8() {
-		return format("Color [R={,3}, G={,3}, B={,3}]", R, G, B);
+		return format("Color [R={,3}, G={,3}, B={,3}]", R, G, B).idup;
 	}
 static:
 	Color opCall(ubyte a, ubyte r, ubyte g, ubyte b) {
--- a/dynamin/painting/graphics.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/painting/graphics.d	Mon Dec 17 23:41:50 2012 -0600
@@ -25,7 +25,7 @@
 	int _style = 0;
 	int _size;
 public:
-	this(string family_ = "", int size = 10, bool b = false, bool i = false, bool u = false) {
+	this(string family_ = null, int size = 10, bool b = false, bool i = false, bool u = false) {
 		this.family = family_;
 		this.size = size;
 		bold = b;
@@ -95,7 +95,7 @@
 	Color* opIndex(int x, int y) {
 		return _data + x+y*_width;
 	}
-	static Image load(string file) {
+	static Image load(cstring file) {
 		static if(false) {
 		auto img = new Image;
 		lodepng.PngInfo info;
@@ -192,9 +192,9 @@
 	Square
 }
 
-// cairo_copy_clip_rectangles  --> Rectangle[] ClipRectangles()
-// cairo_get_dash  --> Dashes()
-// cairo_get_color_stop_rgba  --> ColorStops()
+// cairo_copy_clip_rectangles  --> Rectangle[] clipRectangles()
+// cairo_get_dash  --> dashes()
+// cairo_get_color_stop_rgba  --> colorStops()
 /**
  * A Graphics object uses its source to draw on its target. Its target is set
  * when it is created, but its source can be changed whenever desired. For
@@ -382,12 +382,12 @@
 	 * Draws the inside of the current path.
 	 * Example:
 	 * -----
-	 * graphics.MoveTo(12.5, 14.5);
-	 * graphics.LineTo(123.5, 22.5);
-	 * graphics.LineTo(139.5, 108.5);
-	 * graphics.LineTo(49.5, 86.5);
-	 * graphics.ClosePath();
-	 * graphics.Fill();
+	 * graphics.moveTo(12.5, 14.5);
+	 * graphics.lineTo(123.5, 22.5);
+	 * graphics.lineTo(139.5, 108.5);
+	 * graphics.lineTo(49.5, 86.5);
+	 * graphics.closePath();
+	 * graphics.fill();
 	 * -----
 	 * $(IMAGE ../web/example_fill.png)
 	 */
@@ -457,7 +457,7 @@
 		cairo_select_font_face(cr, toCharPtr(f.family), f.italic, f.bold);
 	}
 	// TODO: if text is all ascii, do fast path with no uniscribe
-	void drawText(string text, double x, double y) {
+	void drawText(cstring text, double x, double y) {
 		auto extents = getFontExtents;
 		cairo_font_extents_t fextents;
 		cairo_font_extents(cr, &fextents);
@@ -466,7 +466,7 @@
 		checkStatus();
 	}
 	///
-	Size getTextExtents(string text) {
+	Size getTextExtents(cstring text) {
 		cairo_text_extents_t textents;
 		cairo_text_extents(cr, toCharPtr(text), &textents);
 		cairo_font_extents_t fextents;
@@ -545,7 +545,7 @@
 		cairo_set_fill_rule(cr, cast(cairo_fill_rule_t)rule);
 	}
 	/**
-	 * The temporary surface created will be the same size as the current clip. To speed up using this function, call Clip() to the area you will be drawing in.
+	 * The temporary surface created will be the same size as the current clip. To speed up using this function, call clip() to the area you will be drawing in.
 	 */
 	void pushGroup() {
 		cairo_push_group(cr);
@@ -554,8 +554,8 @@
 	//	cairo_pop_group(cr);
 	//}
 	/**
-	 * Terminates the redirection begun by a call to PushGroup() or
-	 * PushGroupWithContent() and installs the resulting pattern as the
+	 * Terminates the redirection begun by a call to pushGroup() or
+	 * pushGroupWithContent() and installs the resulting pattern as the
 	 * source pattern.
 	 */
 	void popGroupToSource() {
--- a/dynamin/painting/text_layout.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/painting/text_layout.d	Mon Dec 17 23:41:50 2012 -0600
@@ -638,7 +638,7 @@
 			return;
 		// NOTE: Do not use cropRight(). It is broken. It will cut off an ending code point even
 		// when it is a perfectly valid string. Thankfully, cropLeft() works.
-		if(cropLeft!(char)(text[index..$]).length != text.length-index)
+		if(cropLeft!(char)(cast(mstring)text[index..$]).length != text.length-index)
 			throw new Exception("index must be at a valid code point, not inside one");
 	}
 
--- a/dynamin/painting/windows_text_layout.d	Sat Nov 24 10:21:50 2012 -0600
+++ b/dynamin/painting/windows_text_layout.d	Mon Dec 17 23:41:50 2012 -0600
@@ -101,7 +101,7 @@
 		KoreanHangul       = getUniscribeScript("갠흯㉡");
 	}
 	// returns the Uniscribe script number (SCRIPT_ANALYSIS.eScript) from the specified sample text
-	static int getUniscribeScript(wchar[] sample) {
+	static int getUniscribeScript(const(wchar)[] sample) {
 		SCRIPT_ITEM[5] items;
 		int itemsProcessed;
 		HRESULT r = ScriptItemize(sample.ptr,
@@ -117,9 +117,9 @@
 	}
 
 	// adds fallback fonts to the specified fallbacks array
-	void getFontFallbacks(int script, wchar[][] fallbacks) {
+	void getFontFallbacks(int script, const(wchar)[][] fallbacks) {
 		int i = 0;
-		void addFallback(wchar[] str) {
+		void addFallback(const(wchar)[] str) {
 			fallbacks[i++] = str;
 		}
 		if(script == Latin || script == Greek || script == Cyrillic)
@@ -330,7 +330,7 @@
 			if(items[itemIndex+1].iCharPos == wstart)
 				itemIndex++;
 
-			levels.add(items[itemIndex].a.s.uBidiLevel.get());
+			levels.add(cast(BYTE)items[itemIndex].a.s.uBidiLevel.get());
 
 			cairo_matrix_t ctm;
 			cairo_get_matrix(cr, &ctm);