--- takahashi-r.xul	2005-10-20 04:31:10.000000000 +0900
+++ takahashi.xul	2005-11-14 02:27:16.000000000 +0900
@@ -1,5 +1,10 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <!--
+	高橋メソッドなプレゼンツール in XUL リターンズ エクストラ
+	$Rev: 580 $
+	customized by nyam
+	http://nyam.info/
+
 	高橋メソッドなプレゼンツール in XUL リターンズ
 	made by Piro
 	http://piro.sakura.ne.jp/
@@ -414,6 +419,8 @@
 				</menu>
 			</menubar>
 			<toolbarseparator/>
+			<toolbarbutton label="Save" 
+				oncommand="Presentation.save();"/>
 			<toolbarbutton label="View"
 				oncommand="Presentation.toggleEditMode();"/>
 			<toolbarbutton oncommand="Presentation.reload();" label="Reload"/>
@@ -466,13 +473,43 @@
 
 	<key key="e" modifiers="accel" oncommand="Presentation.toggleEditMode();"/>
 	<key key="e" modifiers="accel,shift" oncommand="Presentation.toggleEvaMode();"/>
+
+	<key key="t" modifiers="accel" oncommand="Presentation.save();"/>
 </keyset>
 
 
 <script type="application/x-javascript"><![CDATA[
 
+HeaderCache =  function () {};
+HeaderCache.prototype = {
+	padding : ' > ',
+	cache : new Array(),
+	
+	setCache : function(level, value) {
+		value = value.replace(/(\r\n|[\r\n])/g, '');
+		this.cache.splice(level);
+		
+		var precache = this.getCacheString();
+		if (value != '') this.cache[level] = value;
+		
+		return precache;
+	},
+	getCache : function(level) {
+		return this.cache[level] || '';
+	},
+	getCacheString : function() {
+		return this.cache.join(this.padding);
+	},
+	
+	clear : function() {
+		this.cache.splice(0);
+	}
+}
+
 var Presentation = {
 
+	save_script : false,
+
 	size            : 9,
 	montaLabelImage : 'monta-label.png',
 
@@ -536,7 +573,15 @@
 
 		this.takahashi();
 	},
-
+	
+	createHbox : function (fragment)
+	{
+			fragment.appendChild(document.createElement('hbox'));
+			fragment.lastChild.setAttribute('align', 'center');
+			fragment.lastChild.setAttribute('pack', 'center');
+			return true;
+	},
+	
 	takahashi : function() {
 		if(!this.data[this.offset]){
 			this.offset = this.data.length-1;
@@ -596,7 +641,7 @@
 
 		var labelId = 0;
 
-		var lineRegExp = /^([^\[]+)?(\[\[em:(.+?):em\]\]|\[\[pre:((.+?):pre\]\])?|\[\[ima?ge? +src="([^"]+)" +width="([0-9]+)" +height="([0-9]+)"[^\]]*\]\]|\[\[(([^\|]+)?\||)([^\]]+)\]\]|\[([^\]]+)\])(.+)?/i;
+		var lineRegExp = /^([^\[]+)?(\[\[em:(.+?):em\]\]|\[\[pre:((.+?):pre\]\])?|\[\[sectiontitle\d:((.+?):sectiontitle\d\]\])?|\[\[ima?ge? +src="([^"]+)" +width="([0-9]+)" +height="([0-9]+)"[^\]]*\]\]|\[\[(([^\|]+)?\||)([^\]]+)\]\]|\[([^\]]+)\])(.+)?/i;
 
 		var emRegExp       = /^([^\[]+)?\[\[em:(.+?):em\]\]/i;
 		var preRegExp      = /^([^\[]+)?\[\[pre:(.+?):pre\]\]/i;
@@ -606,30 +651,40 @@
 		var linksRegExp    = /^([^\[]+)?\[\[(([^\|]+)?\||)([^\]]+)\]\]/;
 		var montaRegExp    = /^([^\[]+)?\[([^\]]+)\]/;
 
+		var sectionTitleRegExp      = /^([^\[]+)?\[\[sectiontitle(\d):(.+?):sectiontitle\2\]\]/i;
+		var sectionTitleStartRegExp = /^([^\[]+)?\[\[sectiontitle\d:(.*)/i;
+		var sectionTitleEndRegExp   = /^(.*?)(:sectiontitle(\d)\]\])/i;
+
 		var inPreBlock  = false;
 		var preContents = [];
+		var inSectionTitleBlock = false;
+		var sectionTitleContents = [];
+
 
-		var i,
+		var i, j,
 			max = text.length;
 
 		var fragment = document.createDocumentFragment();
 
 		for (i = 0; i < max; i++)
 		{
-			fragment.appendChild(document.createElement('hbox'));
-			fragment.lastChild.setAttribute('align', 'center');
-			fragment.lastChild.setAttribute('pack', 'center');
+//			fragment.appendChild(document.createElement('hbox'));
+//			fragment.lastChild.setAttribute('align', 'center');
+//			fragment.lastChild.setAttribute('pack', 'center');
 
 			line = text[i];
 			image_width  = 0;
 			image_height = 0;
 
+			var hboxCreated = false;
+
 			if (inPreBlock) {
 				if (preEndRegExp.test(line)) {
 					inPreBlock = false;
 					preContents.push(RegExp.$1);
 					line = line.substring((RegExp.$1+RegExp.$2).length);
 
+					hboxCreated = this.createHbox(fragment);
 					fragment.lastChild.appendChild(document.createElement('description'));
 					fragment.lastChild.lastChild.setAttribute('class', 'preformatted-text block');
 					fragment.lastChild.lastChild.appendChild(document.createTextNode(
@@ -648,16 +703,44 @@
 				}
 			}
 
+			if (inSectionTitleBlock) {
+				if (sectionTitleEndRegExp.test(line)) {
+					inSectionTitleBlock = false;
+					if (RegExp.$1 != '') sectionTitleContents.push(RegExp.$1);
+					line = line.substring((RegExp.$1+RegExp.$2).length);
+					
+					//alert("cont:" + sectionTitleContents.join('|'));
+					
+					var hboxCreated = this.createHbox(fragment);
+					var sectionTitleBox = fragment.lastChild.appendChild(document.createElement('vbox'));
+					//var sectionTitleBox = fragment.lastChild;
+					sectionTitleBox.setAttribute('class', 'section-title section-title-' + RegExp.$3);
+					
+					for (j=0; j<sectionTitleContents.length; j++) {
+						this.createHbox(sectionTitleBox);
+						//sectionTitleBox.appendChild(document.createElement('vbox'));
+						sectionTitleBox.lastChild.appendChild(document.createElement('description'));
+						sectionTitleBox.lastChild.lastChild.setAttribute('value', sectionTitleContents[j]);
+					}
+				}
+				else {
+					sectionTitleContents.push(line);
+					continue;
+				}
+			}
+			
 			while (line.match(lineRegExp))
 			{
 				if (RegExp.$1) {
+					hboxCreated = this.createHbox(fragment);
 					fragment.lastChild.appendChild(document.createElement('description'));
 					fragment.lastChild.lastChild.setAttribute('value', RegExp.$1);
 				}
 				newLine = line.substring((RegExp.$1+RegExp.$2).length);
-
+				
 				// Preformatted Text
 				if (preRegExp.test(line)) {
+					if (!hboxCreated) hboxCreated = this.createHbox(fragment);
 					fragment.lastChild.appendChild(document.createElement('description'));
 					fragment.lastChild.lastChild.setAttribute('value', RegExp.$2);
 					fragment.lastChild.lastChild.setAttribute('class', 'preformatted-text');
@@ -668,71 +751,89 @@
 					newLine = '';
 				}
 
-				// Emphasis
-				else if (emRegExp.test(line)) {
+				// Section Title
+				else if (sectionTitleRegExp.test(line)) {
+					if (!hboxCreated) hboxCreated = this.createHbox(fragment);
 					fragment.lastChild.appendChild(document.createElement('description'));
-					fragment.lastChild.lastChild.setAttribute('value', RegExp.$2);
-					fragment.lastChild.lastChild.setAttribute('class', 'em-text');
+					fragment.lastChild.lastChild.setAttribute('class', 'section-title section-title-' + RegExp.$2);
+					fragment.lastChild.lastChild.setAttribute('value', RegExp.$3);
 				}
-
-				// Images
-				else if (imagesRegExp.test(line)) {
-					fragment.lastChild.appendChild(document.createElement('image'));
-					image_src = RegExp.$2;
-					if (image_src.indexOf('http://') < 0 &&
-						image_src.indexOf('https://') < 0)
-						image_src = this.dataFolder+image_src;
-					fragment.lastChild.lastChild.setAttribute('src', image_src);
-					fragment.lastChild.lastChild.setAttribute('width', parseInt(RegExp.$3 || '0'));
-					fragment.lastChild.lastChild.setAttribute('height', parseInt(RegExp.$4 || '0'));
-					image_width  += parseInt(RegExp.$3 || '0');
-					image_height = Math.max(image_height, parseInt(RegExp.$4 || '0'));
-				}
-
-				// Links
-				else if (linksRegExp.test(line)) {
-					uri = RegExp.$4;
-					if (uri.indexOf('://') < 0)
-						uri = this.dataFolder+uri;
-					fragment.lastChild.appendChild(document.createElement('description'));
-					fragment.lastChild.lastChild.setAttribute('value', RegExp.$3 || RegExp.$4);
-					fragment.lastChild.lastChild.setAttribute('href', uri);
-					fragment.lastChild.lastChild.setAttribute('tooltiptext', uri);
-					fragment.lastChild.lastChild.setAttribute('statustext', uri);
-					fragment.lastChild.lastChild.setAttribute('class', 'link-text');
-
-					this.clickableNodes.push(fragment.lastChild.lastChild);
+				else if (sectionTitleStartRegExp.test(line)) {
+					inSectionTitleBlock = true;
+					if (RegExp.$2 != "") sectionTitleContents = [RegExp.$2];
+					newLine = '';
 				}
 
-				// Monta
-				else if (montaRegExp.test(line)) {
-					fragment.lastChild.appendChild(document.createElement('stack'));
-
-					fragment.lastChild.lastChild.appendChild(document.createElement('description'));
-					fragment.lastChild.lastChild.lastChild.setAttribute('value', RegExp.$2);
-					fragment.lastChild.lastChild.lastChild.setAttribute('class', 'monta-text');
-
-					fragment.lastChild.lastChild.appendChild(document.createElement('spacer'));
-					fragment.lastChild.lastChild.lastChild.setAttribute('flex', 1);
-					fragment.lastChild.lastChild.lastChild.setAttribute('class', 'monta-label');
-
-					fragment.lastChild.lastChild.lastChild.setAttribute('label-id', 'label-' + (++labelId));
-
-					if (!this.shownMontaLabels[this.offset] || !this.shownMontaLabels[this.offset]['label-'+labelId]) {
-						fragment.lastChild.lastChild.lastChild.setAttribute('monta-hidden', 'true');
-						this.standByMontaLabels[this.standByMontaLabels.length] = fragment.lastChild.lastChild.lastChild;
+				else {
+					if (!hboxCreated) hboxCreated = this.createHbox(fragment);
+				
+				// Emphasis
+					if (emRegExp.test(line)) {
+						fragment.lastChild.appendChild(document.createElement('description'));
+						fragment.lastChild.lastChild.setAttribute('value', RegExp.$2);
+						fragment.lastChild.lastChild.setAttribute('class', 'em-text');
 					}
-					else {
-						fragment.lastChild.lastChild.lastChild.setAttribute('monta-hidden', 'false');
+	
+					// Images
+					else if (imagesRegExp.test(line)) {
+						fragment.lastChild.appendChild(document.createElement('image'));
+						image_src = RegExp.$2;
+						if (image_src.indexOf('http://') < 0 &&
+							image_src.indexOf('https://') < 0)
+							image_src = this.dataFolder+image_src;
+						fragment.lastChild.lastChild.setAttribute('src', image_src);
+						fragment.lastChild.lastChild.setAttribute('width', parseInt(RegExp.$3 || '0'));
+						fragment.lastChild.lastChild.setAttribute('height', parseInt(RegExp.$4 || '0'));
+						image_width  += parseInt(RegExp.$3 || '0');
+						image_height = Math.max(image_height, parseInt(RegExp.$4 || '0'));
+					}
+	
+					// Links
+					else if (linksRegExp.test(line)) {
+						uri = RegExp.$4;
+						if (uri.indexOf('://') < 0)
+							uri = this.dataFolder+uri;
+						fragment.lastChild.appendChild(document.createElement('description'));
+						fragment.lastChild.lastChild.setAttribute('value', RegExp.$3 || RegExp.$4);
+						fragment.lastChild.lastChild.setAttribute('href', uri);
+						fragment.lastChild.lastChild.setAttribute('tooltiptext', uri);
+						fragment.lastChild.lastChild.setAttribute('statustext', uri);
+						fragment.lastChild.lastChild.setAttribute('class', 'link-text');
+	
+						this.clickableNodes.push(fragment.lastChild.lastChild);
+					}
+	
+					// Monta
+					else if (montaRegExp.test(line)) {
+						fragment.lastChild.appendChild(document.createElement('stack'));
+	
+						fragment.lastChild.lastChild.appendChild(document.createElement('description'));
+						fragment.lastChild.lastChild.lastChild.setAttribute('value', RegExp.$2);
+						fragment.lastChild.lastChild.lastChild.setAttribute('class', 'monta-text');
+	
+						fragment.lastChild.lastChild.appendChild(document.createElement('spacer'));
+						fragment.lastChild.lastChild.lastChild.setAttribute('flex', 1);
+						fragment.lastChild.lastChild.lastChild.setAttribute('class', 'monta-label');
+	
+						fragment.lastChild.lastChild.lastChild.setAttribute('label-id', 'label-' + (++labelId));
+	
+						if (!this.shownMontaLabels[this.offset] || !this.shownMontaLabels[this.offset]['label-'+labelId]) {
+							fragment.lastChild.lastChild.lastChild.setAttribute('monta-hidden', 'true');
+							this.standByMontaLabels[this.standByMontaLabels.length] = fragment.lastChild.lastChild.lastChild;
+						}
+						else {
+							fragment.lastChild.lastChild.lastChild.setAttribute('monta-hidden', 'false');
+						}
+	
+						this.clickableNodes.push(fragment.lastChild.lastChild.lastChild);
 					}
-
-					this.clickableNodes.push(fragment.lastChild.lastChild.lastChild);
 				}
-
+				
 				line = newLine;
 			}
 
 			if (line) {
+				if (!hboxCreated) this.createHbox(fragment);
 				fragment.lastChild.appendChild(document.createElement('description'));
 				fragment.lastChild.lastChild.setAttribute('value', line);
 			}
@@ -803,6 +904,32 @@
 		}
 	},
 
+	save : function() {
+		var uri;
+
+		if (this.save_script) {
+			uri = this.save_script + "?data=" + this.dataPath;
+		}
+		else {
+			uri = this.content.baseURI;
+		}
+		var request = new XMLHttpRequest();
+		request.open("POST", uri, false);
+		request.onerror = function() {
+			alert("リクエストエラー");
+		}
+		request.onload = function(resp) {
+			var r = resp.target;
+		if ( r.status == 200 )
+			alert("保存しました． Status:" + r.status + " " + r.statusText);
+		else
+			alert("保存に失敗しました．Status: " + r.status +
+					" " + r.statusText + "\n" + r.responseText);
+		}			   
+
+		request.send(this.textbox.value);
+	},
+
 	reload : function() {
 		var file = String(location.href).replace(/#.+$/, '');
 		if (this.dataPath != file) {
@@ -914,6 +1041,8 @@
 	toggleEditMode : function(){
 		this.deck.selectedIndex = this.deck.selectedIndex == 0 ? 1 : 0 ;
 		this.setHash('edit', this.deck.selectedIndex == 0 ? '' : 'edit' );
+		if (this.deck.selectedIndex == 0) this.canvas.focus()
+		else                              this.textbox.focus();
 	},
 	toggleEvaMode : function(){
 		var check = document.getElementById('toggleEva');
@@ -1262,6 +1391,15 @@
 		var footerRegExp  = /\b(FOOTER::)([^\n]*)\n?/i;
 		var chapter       = '';
 		var chapterRegExp = /\b(CHAPTER::)([^\n]*)\n?/i;
+		
+		var header_cache      = new HeaderCache();
+		var hchapterRegExp    = /\b(HCHAPTER::)\s*((.|\s)*)$/i;
+		var hsectionRegExp    = /\b(HSECTION::)\s*((.|\s)*)$/i;
+		var hsubsectionRegExp = /\b(HSUBSECTION::)\s*((.|\s)*)$/i;
+		var schapterRegExp    = /\b(SCHAPTER::)([^\n]*)\n?/i;
+		var ssectionRegExp    = /\b(SSECTION::)([^\n]*)\n?/i;
+		var ssubsectionRegExp = /\b(SSUBSECTION::)([^\n]*)\n?/i;
+
 		var lastChapter;
 
 		var imageMatchResults;
@@ -1284,14 +1422,18 @@
 				.replace(regexp[0], '')
 				.replace(regexp[1], '')
 				.replace(regexp[2], '\n');
-
+			
+			header = header_cache.getCacheString();
+			
 			this._data[i] = this._data[i].replace(titleRegExp, '')
 			if (String(RegExp.$1).toUpperCase() == 'TITLE::')
 				title = RegExp.$2 || '' ;
 
 			this._data[i] = this._data[i].replace(headerRegExp, '')
-			if (String(RegExp.$1).toUpperCase() == 'HEADER::')
+			if (String(RegExp.$1).toUpperCase() == 'HEADER::') {
 				header = RegExp.$2 || '' ;
+				header_cache = new HeaderCache();
+			}
 
 			this._data[i] = this._data[i].replace(footerRegExp, '')
 			if (String(RegExp.$1).toUpperCase() == 'FOOTER::')
@@ -1300,6 +1442,44 @@
 			this._data[i] = this._data[i].replace(chapterRegExp, '')
 			if (String(RegExp.$1).toUpperCase() == 'CHAPTER::')
 				chapter = RegExp.$2 || '' ;
+				
+			this._data[i] = this._data[i].replace(hchapterRegExp, '');
+			if (String(RegExp.$1).toUpperCase() == 'HCHAPTER::') {
+				this._data[i] = '[[SECTIONTITLE0:' + RegExp.$2 + ':SECTIONTITLE0]]';
+				header = header_cache.setCache(0, RegExp.$2);
+				chapter = header_cache.getCache(0);
+			}
+			
+			this._data[i] = this._data[i].replace(hsectionRegExp, '');
+			if (String(RegExp.$1).toUpperCase() == 'HSECTION::') {
+				this._data[i] = '[[SECTIONTITLE1:' + RegExp.$2 + ':SECTIONTITLE1]]';
+				header = header_cache.setCache(1, RegExp.$2);
+			}
+
+			this._data[i] = this._data[i].replace(hsubsectionRegExp, '');
+			if (String(RegExp.$1).toUpperCase() == 'HSUBSECTION::') {
+				this._data[i] = '[[SECTIONTITLE2:' + RegExp.$2 + ':SECTIONTITLE2]]';
+				header = header_cache.setCache(2, RegExp.$2);
+			}
+
+			this._data[i] = this._data[i].replace(schapterRegExp, '');
+			if (String(RegExp.$1).toUpperCase() == 'SCHAPTER::') {
+				header_cache.setCache(0, RegExp.$2);
+				header = header_cache.getCacheString();
+				chapter = header_cache.getCache(0);
+			}
+
+			this._data[i] = this._data[i].replace(ssectionRegExp, '');
+			if (String(RegExp.$1).toUpperCase() == 'SSECTION::') {
+				header_cache.setCache(1, RegExp.$2);
+				header = header_cache.getCacheString();
+			}
+
+			this._data[i] = this._data[i].replace(ssubsectionRegExp, '');
+			if (String(RegExp.$1).toUpperCase() == 'SSUBSECTION::') {
+				header_cache.setCache(2, RegExp.$2);
+				header = header_cache.getCacheString();
+			}
 
 			imageMatchResults = this._data[i].match(imagesRegExp);
 			if (imageMatchResults) {
@@ -1434,6 +1614,9 @@
 				param.match(/eva=(1|true|yes)/i))
 				this.toggleEvaMode();
 
+			if (param.match(/save=([^&;]+)/i))
+				this.save_script = unescape(RegExp.$1);
+
 			if (param.match(/data=([^&;]+)/i)) {
 				var path = unescape(RegExp.$1);
 				this.dataPath = path;
--- takahashi-r.css	2005-10-20 04:21:00.000000000 +0900
+++ takahashi.css	2005-11-14 02:27:16.000000000 +0900
@@ -279,4 +279,14 @@
 	position: absolute;
 	display: block;
 	z-index: 100;
-}
+}
+
+.section-title {
+	padding: 0.5em;
+	border: 10px dashed;
+	font-style: italic;
+}
+
+.section-title-0 { border-color: red; }
+.section-title-1 { border-color: blue; }
+.section-title-2 { border-color: gray; }

