Index: shadows/split.recipe
===================================================================
--- shadows/split.recipe	(revision 6802)
+++ shadows/split.recipe	(working copy)
@@ -5,6 +5,7 @@
 shadow: StyleSheetLayout.tiddler
 shadow: StyleSheetLocale.tiddler
 shadow: StyleSheetPrint.tiddler
+shadow: SystemSettings.tiddler
 shadow: PageTemplate.tiddler
 shadow: ViewTemplate.tiddler
 shadow: EditTemplate.tiddler
Index: shadows/SystemSettings.tiddler
===================================================================
--- shadows/SystemSettings.tiddler	(revision 0)
+++ shadows/SystemSettings.tiddler	(revision 0)
@@ -0,0 +1,29 @@
+<div title="SystemSettings">
+<pre>|''chkAnimate_cookie:''|false|
+|''chkAutoSave:''|false|
+|''chkBackstage_cookie:''|false|
+|''chkCaseSensitiveSearch:''|false|
+|''chkConfirmDelete:''|true|
+|''chkDisplayInstrumentation:''|false|
+|''chkForceMinorUpdate:''|false|
+|''chkGenerateAnRssFeed:''|false|
+|''chkHttpReadOnly:''|true|
+|''chkIncrementalSearch:''|true|
+|''chkInsertTabs:''|false|
+|''chkOpenInNewWindow:''|true|
+|''chkRegExpSearch:''|false|
+|''chkSaveBackups:''|true|
+|''chkSaveEmptyTemplate:''|false|
+|''chkSideBarTabs_cookie:''|false|
+|''chkSliderOptionsPanel_cookie:''|false|
+|''chkToggleLinks:''|false|
+|''chkUsePreForStorage:''|true|
+|''txtBackupFolder:''||
+|''txtEditorFocus:''|text|
+|''txtFileSystemCharSet:''|UTF-8|
+|''txtMainTab_cookie:''|More|
+|''txtMaxEditRows:''|30|
+|''txtMoreTab_cookie:''|Missing|
+|''txtTheme:''||
+|''txtUserName:''|YourName|</pre>
+</div>
\ No newline at end of file
Index: js/TiddlyWiki.js
===================================================================
--- js/TiddlyWiki.js	(revision 6802)
+++ js/TiddlyWiki.js	(working copy)
@@ -151,7 +151,7 @@
 	return textOut.join("");
 };
 
-TiddlyWiki.prototype.slicesRE = /(?:^([\'\/]{0,2})~?([\.\w]+)\:\1\s*([^\n]+)\s*$)|(?:^\|([\'\/]{0,2})~?([\.\w]+)\:?\4\|\s*([^\|\n]+)\s*\|$)/gm;
+TiddlyWiki.prototype.slicesRE = /(?:^([\'\/]{0,2})~?([\.\w]+)\:\1[\t\x20]*([^\n]*)[\t\x20]*$)|(?:^\|([\'\/]{0,2})~?([\.\w]+)\:?\4\|[\t\x20]*([^\|\n]*)[\t\x20]*\|$)/gm;
 
 // @internal
 TiddlyWiki.prototype.calcAllSlices = function(title)
Index: js/main.js
===================================================================
--- js/main.js	(revision 6802)
+++ js/main.js	(working copy)
@@ -33,13 +33,13 @@
 	story = new Story("tiddlerDisplay","tiddler");
 	addEvent(document,"click",Popup.onDocumentClick);
 	saveTest();
-	loadOptionsCookie();
 	for(var s=0; s<config.notifyTiddlers.length; s++)
 		store.addNotification(config.notifyTiddlers[s].name,config.notifyTiddlers[s].notify);
 	t1 = new Date();
 	loadShadowTiddlers();
 	t2 = new Date();
 	store.loadFromDiv("storeArea","store",true);
+	loadOptionsCookie();
 	t3 = new Date();
 	invokeParamifier(params,"onload");
 	t4 = new Date();
Index: js/Options.js
===================================================================
--- js/Options.js	(revision 6802)
+++ js/Options.js	(working copy)
@@ -4,8 +4,8 @@
 
 config.optionHandlers = {
 	'txt': {
-		get: function(name) {return encodeCookie(config.options[name].toString());},
-		set: function(name,value) {config.options[name] = decodeCookie(value);}
+		get: function(name) {return config.options[name].toString();},
+		set: function(name,value) {config.options[name] = value;}
 	},
 	'chk': {
 		get: function(name) {return config.options[name] ? "true" : "false";},
@@ -13,40 +13,130 @@
 	}
 };
 
-function loadOptionsCookie()
+function setOption(name,value)
 {
+	var optType = name.substr(0,3);
+	if(config.optionHandlers[optType] && config.optionHandlers[optType].set)
+		config.optionHandlers[optType].set(name,value);
+}
+
+// Gets the value of an option as a string. Most code should just read from config.options.* directly
+function getOption(name)
+{
+	var optType = name.substr(0,3);
+	if(config.optionHandlers[optType] && config.optionHandlers[optType].get)
+		return config.optionHandlers[optType].get(name);
+	else
+		return null;
+}
+
+//# Loads up config.options from cookies and SystemSettings
+function initialiseOptions()
+{
 	if(safeMode)
 		return;
+	loadSystemSettings();
+	loadCookies();
+}
+// Deprecated name for backwards compatibility
+var loadOptionsCookie = initialiseOptions;
+
+function loadCookies()
+{
+	var cookies = {};
 	var cookies = document.cookie.split(";");
 	for(var c=0; c<cookies.length; c++) {
 		var p = cookies[c].indexOf("=");
 		if(p != -1) {
 			var name = cookies[c].substr(0,p).trim();
 			var value = cookies[c].substr(p+1).trim();
-			var optType = name.substr(0,3);
-			if(config.optionHandlers[optType] && config.optionHandlers[optType].set)
-				config.optionHandlers[optType].set(name,value);
+			if(config.optionSource[name] == 'cookie')
+				setOption(name,decodeCookie(value));
 		}
 	}
 }
 
-function saveOptionCookie(name)
+function loadSystemSettings()
 {
+	var settings = store.calcAllSlices("SystemSettings");
+	for(var key in settings) {
+		var splitPos = key.indexOf('_');
+		var name = key;
+		var source = "setting";
+		if(splitPos !== -1) {
+			source = key.substr(splitPos+1);
+			name = key.substr(0,splitPos);
+		}
+		setOption(name,settings[key]);
+		config.optionSource[name] = source;
+	}
+}
+
+function onSystemSettingsChange()
+{
+	if(!startingUp) {
+		loadSystemSettings();
+	}
+}
+
+// Saves the named option in a cookie or SystemSettings as appropriate
+function saveOption(name)
+{
 	if(safeMode)
 		return;
-	var c = name + "=";
-	var optType = name.substr(0,3);
-	if(config.optionHandlers[optType] && config.optionHandlers[optType].get)
-		c += config.optionHandlers[optType].get(name);
+	if(config.optionSource[name] == 'cookie') {
+		if(store.getTiddlerSlice("SystemSettings",name + "_cookie") == getOption(name)) {
+			removeCookie(name);
+		} else {
+			saveCookie(name);
+		}
+	} else {
+		saveSystemSetting(name);
+	}
+}
+// Deprecated names for backwards compatibility
+var saveOptionCookie = saveOption;
+
+function saveCookie(name)
+{
+	var c = name + "=" + encodeCookie(getOption(name));
 	c += "; expires=Fri, 1 Jan 2038 12:00:00 UTC; path=/";
 	document.cookie = c;
 }
 
+function removeCookie(name)
+{
+	document.cookie = name + "=; expires=Thu, 01-Jan-1970 00:00:01 UTC; path=/;";
+}
+
+function saveSystemSetting(name)
+{
+	var settings = store.calcAllSlices("SystemSettings");
+	var key;
+	for(key in config.options) {
+		if(config.optionSource[key] == "setting") {
+			var value = getOption(key);
+			value = value == null ? "" : value;
+			if(settings[key] !== value)
+				settings[key] = value;
+		}
+	}
+	var text = [];
+	for(key in settings) {
+		text.push("|''%0:''|%1|".format([key,settings[key]]));
+	}
+	text.sort();
+	store.saveTiddler("SystemSettings","SystemSettings",text.join("\n"),"System",new Date());
+	autoSaveChanges();
+}
+
+//# Flatten cookies to ANSI character set by substituting html character entities for non-ANSI characters
 function encodeCookie(s)
 {
 	return escape(convertUnicodeToHtmlEntities(s));
 }
 
+//# Decode any html character entities to their unicode equivalent
 function decodeCookie(s)
 {
 	s = unescape(s);
@@ -54,7 +144,6 @@
 	return s.replace(re,function($0) {return String.fromCharCode(eval($0.replace(/[&#;]/g,"")));});
 }
 
-
 config.macros.option.genericCreate = function(place,type,opt,className,desc)
 {
 	var typeInfo = config.macros.option.types[type];
Index: js/Config.js
===================================================================
--- js/Config.js	(revision 6802)
+++ js/Config.js	(working copy)
@@ -63,6 +63,13 @@
 	};
 config.optionsDesc = {};
 
+//# config.optionSource["chkAnimate"] can be:
+//# 	cookie: the option gets stored in a cookie, with the default value coming from SystemSettings
+//#		volatile: the option isn't persisted at all, and reverts to the default specified in SystemSettings when the document is reloaded
+//#		setting: the option is stored in the SystemSettings tiddler
+//#	The default is "setting"
+config.optionSource = {};
+
 // Default tiddler templates
 var DEFAULT_VIEW_TEMPLATE = 1;
 var DEFAULT_EDIT_TEMPLATE = 2;
Index: js/Lingo.js
===================================================================
--- js/Lingo.js	(revision 6802)
+++ js/Lingo.js	(working copy)
@@ -462,6 +462,7 @@
 	StyleSheetLayout: "This shadow tiddler contains CSS definitions related to the layout of page elements. ''DO NOT EDIT THIS TIDDLER'', instead make your changes in the StyleSheet shadow tiddler",
 	StyleSheetLocale: "This shadow tiddler contains CSS definitions related to the translation locale",
 	StyleSheetPrint: "This shadow tiddler contains CSS definitions for printing",
+	SystemSettings: "This tiddler is used to store configuration options for this TiddlyWiki document",
 	TabAll: "This shadow tiddler contains the contents of the 'All' tab in the right-hand sidebar",
 	TabMore: "This shadow tiddler contains the contents of the 'More' tab in the right-hand sidebar",
 	TabMoreMissing: "This shadow tiddler contains the contents of the 'Missing' tab in the right-hand sidebar",
@@ -472,4 +473,3 @@
 	ToolbarCommands: "This shadow tiddler determines which commands are shown in tiddler toolbars",
 	ViewTemplate: "The HTML template in this shadow tiddler determines how tiddlers look"
 	});
-
Index: js/Refresh.js
===================================================================
--- js/Refresh.js	(revision 6802)
+++ js/Refresh.js	(working copy)
@@ -4,6 +4,7 @@
 
 //# List of notification functions to be called when certain tiddlers are changed or deleted
 config.notifyTiddlers = [
+	{name: "SystemSettings", notify: onSystemSettingsChange},
 	{name: "StyleSheetLayout", notify: refreshStyles},
 	{name: "StyleSheetColors", notify: refreshStyles},
 	{name: "StyleSheet", notify: refreshStyles},

