toBala KM King


Requires Javascript.
Linux 系統概論- 學習筆記本 - V1.2 (2010/06/01)
<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml'/>
<!--}}}-->
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

a {color:[[ColorPalette::PrimaryMid]];}
a:hover {background-color:[[ColorPalette::PrimaryMid]]; color:[[ColorPalette::Background]];}
a img {border:0;}

h1,h2,h3,h4,h5,h6 {color:[[ColorPalette::SecondaryDark]]; background:transparent;}
h1 {border-bottom:2px solid [[ColorPalette::TertiaryLight]];}
h2,h3 {border-bottom:1px solid [[ColorPalette::TertiaryLight]];}

.button {color:[[ColorPalette::PrimaryDark]]; border:1px solid [[ColorPalette::Background]];}
.button:hover {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::SecondaryLight]]; border-color:[[ColorPalette::SecondaryMid]];}
.button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::SecondaryDark]];}

.header {background:[[ColorPalette::PrimaryMid]];}
.headerShadow {color:[[ColorPalette::Foreground]];}
.headerShadow a {font-weight:normal; color:[[ColorPalette::Foreground]];}
.headerForeground {color:[[ColorPalette::Background]];}
.headerForeground a {font-weight:normal; color:[[ColorPalette::PrimaryPale]];}

.tabSelected{color:[[ColorPalette::PrimaryDark]];
	background:[[ColorPalette::TertiaryPale]];
	border-left:1px solid [[ColorPalette::TertiaryLight]];
	border-top:1px solid [[ColorPalette::TertiaryLight]];
	border-right:1px solid [[ColorPalette::TertiaryLight]];
}
.tabUnselected {color:[[ColorPalette::Background]]; background:[[ColorPalette::TertiaryMid]];}
.tabContents {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::TertiaryPale]]; border:1px solid [[ColorPalette::TertiaryLight]];}
.tabContents .button {border:0;}

#sidebar {}
#sidebarOptions input {border:1px solid [[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel {background:[[ColorPalette::PrimaryPale]];}
#sidebarOptions .sliderPanel a {border:none;color:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:hover {color:[[ColorPalette::Background]]; background:[[ColorPalette::PrimaryMid]];}
#sidebarOptions .sliderPanel a:active {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::Background]];}

.wizard {background:[[ColorPalette::PrimaryPale]]; border:1px solid [[ColorPalette::PrimaryMid]];}
.wizard h1 {color:[[ColorPalette::PrimaryDark]]; border:none;}
.wizard h2 {color:[[ColorPalette::Foreground]]; border:none;}
.wizardStep {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];
	border:1px solid [[ColorPalette::PrimaryMid]];}
.wizardStep.wizardStepDone {background:[[ColorPalette::TertiaryLight]];}
.wizardFooter {background:[[ColorPalette::PrimaryPale]];}
.wizardFooter .status {background:[[ColorPalette::PrimaryDark]]; color:[[ColorPalette::Background]];}
.wizard .button {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryLight]]; border: 1px solid;
	border-color:[[ColorPalette::SecondaryPale]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryDark]] [[ColorPalette::SecondaryPale]];}
.wizard .button:hover {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Background]];}
.wizard .button:active {color:[[ColorPalette::Background]]; background:[[ColorPalette::Foreground]]; border: 1px solid;
	border-color:[[ColorPalette::PrimaryDark]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryPale]] [[ColorPalette::PrimaryDark]];}

#messageArea {border:1px solid [[ColorPalette::SecondaryMid]]; background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]];}
#messageArea .button {color:[[ColorPalette::PrimaryMid]]; background:[[ColorPalette::SecondaryPale]]; border:none;}

.popupTiddler {background:[[ColorPalette::TertiaryPale]]; border:2px solid [[ColorPalette::TertiaryMid]];}

.popup {background:[[ColorPalette::TertiaryPale]]; color:[[ColorPalette::TertiaryDark]]; border-left:1px solid [[ColorPalette::TertiaryMid]]; border-top:1px solid [[ColorPalette::TertiaryMid]]; border-right:2px solid [[ColorPalette::TertiaryDark]]; border-bottom:2px solid [[ColorPalette::TertiaryDark]];}
.popup hr {color:[[ColorPalette::PrimaryDark]]; background:[[ColorPalette::PrimaryDark]]; border-bottom:1px;}
.popup li.disabled {color:[[ColorPalette::TertiaryMid]];}
.popup li a, .popup li a:visited {color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border: none;}
.popup li a:active {background:[[ColorPalette::SecondaryPale]]; color:[[ColorPalette::Foreground]]; border: none;}
.popupHighlight {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
.listBreak div {border-bottom:1px solid [[ColorPalette::TertiaryDark]];}

.tiddler .defaultCommand {font-weight:bold;}

.shadow .title {color:[[ColorPalette::TertiaryDark]];}

.title {color:[[ColorPalette::SecondaryDark]];}
.subtitle {color:[[ColorPalette::TertiaryDark]];}

.toolbar {color:[[ColorPalette::PrimaryMid]];}
.toolbar a {color:[[ColorPalette::TertiaryLight]];}
.selected .toolbar a {color:[[ColorPalette::TertiaryMid]];}
.selected .toolbar a:hover {color:[[ColorPalette::Foreground]];}

.tagging, .tagged {border:1px solid [[ColorPalette::TertiaryPale]]; background-color:[[ColorPalette::TertiaryPale]];}
.selected .tagging, .selected .tagged {background-color:[[ColorPalette::TertiaryLight]]; border:1px solid [[ColorPalette::TertiaryMid]];}
.tagging .listTitle, .tagged .listTitle {color:[[ColorPalette::PrimaryDark]];}
.tagging .button, .tagged .button {border:none;}

.footer {color:[[ColorPalette::TertiaryLight]];}
.selected .footer {color:[[ColorPalette::TertiaryMid]];}

.sparkline {background:[[ColorPalette::PrimaryPale]]; border:0;}
.sparktick {background:[[ColorPalette::PrimaryDark]];}

.error, .errorButton {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::Error]];}
.warning {color:[[ColorPalette::Foreground]]; background:[[ColorPalette::SecondaryPale]];}
.lowlight {background:[[ColorPalette::TertiaryLight]];}

.zoomer {background:none; color:[[ColorPalette::TertiaryMid]]; border:3px solid [[ColorPalette::TertiaryMid]];}

.imageLink, #displayArea .imageLink {background:transparent;}

.annotation {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; border:2px solid [[ColorPalette::SecondaryMid]];}

.viewer .listTitle {list-style-type:none; margin-left:-2em;}
.viewer .button {border:1px solid [[ColorPalette::SecondaryMid]];}
.viewer blockquote {border-left:3px solid [[ColorPalette::TertiaryDark]];}

.viewer table, table.twtable {border:2px solid [[ColorPalette::TertiaryDark]];}
.viewer th, .viewer thead td, .twtable th, .twtable thead td {background:[[ColorPalette::SecondaryMid]]; border:1px solid [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::Background]];}
.viewer td, .viewer tr, .twtable td, .twtable tr {border:1px solid [[ColorPalette::TertiaryDark]];}

.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}
.viewer code {color:[[ColorPalette::SecondaryDark]];}
.viewer hr {border:0; border-top:dashed 1px [[ColorPalette::TertiaryDark]]; color:[[ColorPalette::TertiaryDark]];}

.highlight, .marked {background:[[ColorPalette::SecondaryLight]];}

.editor input {border:1px solid [[ColorPalette::PrimaryMid]];}
.editor textarea {border:1px solid [[ColorPalette::PrimaryMid]]; width:100%;}
.editorFooter {color:[[ColorPalette::TertiaryMid]];}

#backstageArea {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::TertiaryMid]];}
#backstageArea a {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstageArea a:hover {background:[[ColorPalette::SecondaryLight]]; color:[[ColorPalette::Foreground]]; }
#backstageArea a.backstageSelTab {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}
#backstageButton a {background:none; color:[[ColorPalette::Background]]; border:none;}
#backstageButton a:hover {background:[[ColorPalette::Foreground]]; color:[[ColorPalette::Background]]; border:none;}
#backstagePanel {background:[[ColorPalette::Background]]; border-color: [[ColorPalette::Background]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]] [[ColorPalette::TertiaryDark]];}
.backstagePanelFooter .button {border:none; color:[[ColorPalette::Background]];}
.backstagePanelFooter .button:hover {color:[[ColorPalette::Foreground]];}
#backstageCloak {background:[[ColorPalette::Foreground]]; opacity:0.6; filter:'alpha(opacity:60)';}
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0em 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0em 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0em 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 .3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0em 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0em 0em 0em; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0em;}
.wizardFooter .status {padding:0em 0.4em 0em 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em 0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0em; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em 0.2em 0.2em 0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em 0.2em 0.2em 0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em 1em 1em 1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0em;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0em 0em 0.5em;}
.tab {margin:0em 0em 0em 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0em 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0em 1em;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0em 0.25em; padding:0em 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0em; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px 1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0em; right:0em;}
#backstageButton a {padding:0.1em 0.4em 0.1em 0.4em; margin:0.1em 0.1em 0.1em 0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; margin:0em 3em 0em 3em; padding:1em 1em 1em 1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em 0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
/***
StyleSheet for use when a translation requires any css style changes.
This StyleSheet can be used directly by languages such as Chinese, Japanese and Korean which need larger font sizes.
***/
/*{{{*/
body {font-size:0.8em;}
#sidebarOptions {font-size:1.05em;}
#sidebarOptions a {font-style:normal;}
#sidebarOptions .sliderPanel {font-size:0.95em;}
.subtitle {font-size:0.8em;}
.viewer table.listView {font-size:0.95em;}
/*}}}*/
/*{{{*/
@media print {
#mainMenu, #sidebar, #messageArea, .toolbar, #backstageButton, #backstageArea {display: none ! important;}
#displayArea {margin: 1em 1em 0em 1em;}
/* Fixes a feature in Firefox 1.5.0.2 where print preview displays the noscript content */
noscript {display:none;}
}
/*}}}*/
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>
<div id='mainMenu' refresh='content' tiddler='MainMenu'></div>
<div id='sidebar'>
<div id='sidebarOptions' refresh='content' tiddler='SideBarOptions'></div>
<div id='sidebarTabs' refresh='content' force='true' tiddler='SideBarTabs'></div>
</div>
<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlerDisplay'></div>
</div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler > fields syncing permalink references jump'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<!--}}}-->
To get started with this blank TiddlyWiki, you'll need to modify the following tiddlers:
* SiteTitle & SiteSubtitle: The title and subtitle of the site, as shown above (after saving, they will also appear in the browser title bar)
* MainMenu: The menu (usually on the left)
* DefaultTiddlers: Contains the names of the tiddlers that you want to appear when the TiddlyWiki is opened
You'll also need to enter your username for signing your edits: <<option txtUserName>>
These InterfaceOptions for customising TiddlyWiki are saved in your browser

Your username for signing your edits. Write it as a WikiWord (eg JoeBloggs)

<<option txtUserName>>
<<option chkSaveBackups>> SaveBackups
<<option chkAutoSave>> AutoSave
<<option chkRegExpSearch>> RegExpSearch
<<option chkCaseSensitiveSearch>> CaseSensitiveSearch
<<option chkAnimate>> EnableAnimations

----
Also see AdvancedOptions
<<importTiddlers>>
Revision 3497
&nbsp;
__{{item1{學習筆記本簡介}}}__
這是一個由單網頁 (HTML, CSS, JavaScript) 所建構的資訊工作平台 (Platform), 在這平台中你可以輕鬆的處理各式各樣資訊, 例如 網頁(XHTML), 可縮放向量圖形 (SVG), 數學標籤語言 (MathML), 同步多媒體集成語言 (SMIL), PDF 等, 並以 [標籤分類] 方式, 有效的將平台中的資訊, 轉換成個人知識庫.

學習筆記本 有提供 Wiki 語法, 可使妳快速產生網頁資訊, 更可以作為 Ajax 及 Java 程設人員的開發平台 (首創), 至於多媒體的展示能力更不在話下, 因這平台本體就是網頁, 當然可輕易展示圖片, 影片, 音樂 (JPG, GIF, AVI, WAV,..). 相信由這平台的實作, 你可以感覺單網頁平台所創造的資訊力 (force) 是無限的, 在下一個版本 (2.0) 已計劃整合 ''SQLite'', 這可使得 ''學習筆記本'' 大大提升其執行效率及文章儲存容量

__''@@font-size:14px;系統需求@@''__
|硬體|CPU : P4+, 記憶體 : 512 MB+|
|瀏覽器|Firefox 2.0+, IE 6.0+, Safari 3.1+|
|作業系統|Windows 2000/XP/Vista, Mac OS X|

__''@@font-size:14px;核心技術@@''__
學習筆記本核心技術是來自於 [[TiddlyWiki|http://www.tiddlywiki.com/]], 並與 TiddlyWiki 採用相同授權方式 (BSD OpenSourceLicense)

__{{item1{下載學習筆記本}}}__
點選 [[這裡|http://tbala.net/download/toBalaKMKNotepad.zip]] 下載大約 9 MB 的壓縮檔 (toBalaKMKNotepad.zip)

__{{item1{安裝與啟動學習筆記本}}}__
你只需將下載的壓縮檔 (toBalaKMKNotepad.zip) 解壓縮至資料磁碟機 (建議 USB 隨身碟), 這時你會看到ㄧ個名為 toBalaKMKNotepad 的資料夾,
在資料夾中快點二下 toBalaKMKNotepad.html, 系統會使用預設瀏覽器將之開啟 (目前只支援 IE 5.5+, Firefox 1.5+, Safari 3.1+)

''[注意]'' 切勿將壓縮檔 toBalaKMKNotepad.zip 解壓縮至 ''[桌面]'' 或 ''[名稱中有空白字元的目錄]'', 這樣操作會造成 ''學習筆記本'' 無法正常工作. 在 toBalaKMKNotepad 資料夾中, 存在的某些 .exe 檔 (tbsys.exe, tbjava.exe, tbjavac.exe), 會被防毒軟體誤判為病毒並隔離, 請自行設定防毒軟體, 將這些檔案視為安全檔案.

__{{item1{學習筆記本的目錄結構}}}__
{{{
toBalaKMKNotepad
       |--- img                   儲存圖檔 (png, jpg,...)
       |
       |--- movie                儲存影音檔 (avi, mov,...)
       |
       |--- music               儲存音樂檔 (mp3, mp4, wav...)
       |
       |--- documents         儲存各式文件檔 (pdf, text, doc,...)
       |
       |--- tools                 儲存隨身應用軟體 (zoomIt, Inkscape, hfs,...)
       |
       |--- ajax                  儲存 Ajax 程設人員的工具及程式 (HTML, CSS, JavaScript)
       |
       |--- java                   儲存 Java 程設人員所需的工具及程式 (J2SE, Tomcat,..)
       |
       |--- xml                   儲存各式 XML 標準資訊檔 (SVG, XHTML, MathML, ODF,...)
       |
       |--- db                     儲存 SQLite 所建立的資料庫
       |
       |--- jslib                   儲存 Ajax Framework
}}}

__{{item1{學習筆記本 - 版本記錄}}}__

''@@color:red;[V1.1 - 2008/09/30]@@''
1. 將 ImportTiddlersPlugin 更新為 4.3.3
2. toBalaJava 巨集升級為 toBalaJava2 巨集
3. toBalaAjax 巨集加入 [網頁文字編輯] 功能
4. toBalaFlashPlayer 巨集升級為 toBalaSWF2 巨集 (使用 SWFObject 2.1)
5. 新增 [更新土芭樂巨集程式碼] 按鈕
6. 新增 [匯出文章] 功能按鈕 (ExportTiddlersPlugin) 
7. 新增 toBalaBackup 巨集, 備份指定文章
8. 新增 toBalaCoreBackup 巨集, 備份 "土芭樂巨集" 程式
9. 修改 toBalaLIB 程式庫 (getMainTree, TagDigg, getTiddlerDIV)
10. 將 [版面管理員] 改版為 [控制台]

__{{item1{筆記本設定 (設定將存於瀏覽器 Cookies 中)}}}__

請簽名 <<option txtUserName>>
<<option chkGenerateAnRssFeed>> 儲存變更時,也儲存 RSS feed

__{{item1{版面設定 (設定將存於筆記本中)}}}__
<<toBalaManager>>

__{{item1{筆記本備份 (設定將存於瀏覽器 Cookies 中)}}}__
{{op1{1. 資訊樹}}}
備份檔名 : <<option txtBalaBackupFileName>>
備份主標籤 : <<option txtBalaTreeBody>>
其它備份文章 : <<option txtBalaBackupOthers>>

<<toBalaBackup "NotepadBackup.html">>

{{op1{2. 土芭樂巨集}}}
備份檔名 : <<option txtBalaCoreBackupFileName>>
其它備份文章 : <<option txtBalaCoreBackupOthers>>

<<toBalaCoreBackup "toBalaCoreMacro.html">>

__{{item1{巨集管理}}}__

<<loadTiddlers "label:檢查更新土芭樂巨集" http://tbala.net/x/toBalaMacro.html updates quiet>>





























///%

Linux 系統概論- 學習筆記本

V1.1 (2010/06/01)

<<tagsTree menu "" 1 4 index label>>
<<tagsTree twcms "" 1 4 index label>>
<<tagsTree linux0101 "" 1 4 index label>>
<<tagsTree linux0102 "" 1 4 index label>>
<<tagsTree linux0103 "" 1 4 index label>>
<<tagsTree linux0104 "" 1 4 index label>>
<<tagsTree linux0105 "" 1 4 index label>>
<<tagsTree linux0106 "" 1 4 index label>>
<<tagsTree KMKConfig "" 1 4 index label>>

 [[首頁]] | [[土芭樂 3.0 - 數位新思路|http://tbala.net/]]  | [[TiddlyWiki 練功坊|http://tiddlywiki.tbala.net/]] | [[匯入文章]]  | [[匯出文章]]  |  &nbsp;&nbsp;<<toBalaRun "Java-CMD.bat" "" "命令提示視窗">>&nbsp;&nbsp;<<newTiddler label:"新增文章">>&nbsp;&nbsp;<<closeAll>>&nbsp;&nbsp;<<saveChanges>> 
//%/
本文網址 : http://www.ithome.com.tw/itadm/article.php?c=63845

領導 IBM 物聯網技術研發的IBM 院士王雲認為,能夠分析並提供優化的資料才能展現物聯網的價值。特別是物聯網可提供更即時的數據,分析所產生的資料也比過去更有價值

重 點
● 物聯網將帶動分散式運算中心興起
● RFID協助供應鏈型的物聯網應用

領導IBM物聯網技術研發的院士王雲認為,多數人以為建立感應裝置收集訊息是物聯網最重要的事,其實,物聯網真正的價值是在如何分析資料並能加以運用分析的結果。為了分析這些透過物聯網收集來的大量而格式多元的資訊,也會帶動分散式小型運算中心的興起。

整個IBM有20多萬名技術人員,但僅有不到100位可以晉身院士,而王雲是唯一來自臺灣的IBM院士。他是DB2專家,擁有超過40個資料庫優化相關的美國專利。隨著物聯網越來越仰賴資料庫分析技術,王雲也就成為IBM物聯網技術的領導者。

物聯網技術是一套連結實體世界各種物體的網路,這些物體可以透過物聯網彼此互通訊息。然而,王雲指出,實體世界中的各種人事時地物資料進入物聯網後,開始出現資料氾濫的問題。因此,比起建立感應裝置收集各種訊息,他認為,將這些訊息做有價值的運用更重要,所以,分析並產生優化過的訊息才是物聯網的重要目標。

舉例來說,當一個人拿著手機進入博物館參觀,物聯網可以將每個藝術品的資料藉由手機傳送給參觀者,但真正有價值的訊息是要能夠利用手機提供的導覽訊息來分析出參觀者的喜好,並向他推薦最值得參觀的藝術品、其所處的位置、參觀完所需的總體時間等等,甚至當參觀者反應參觀時間僅有30分鐘時,也可立即挑選出最適合優先參觀的藝術品。

物聯網根據即時訊息的分析具高應用價值
王雲認為,物聯網的資料分析方式跟過去最大的不同就在於,傳統的資料分析必須根據經驗或歷史資料來推估,但物聯網則是根據即時訊息進行分析,其應用價值更高。

此外,透過物聯網收集的資料格式與數量也和過去大不相同。王雲解釋,過去資料庫為了企業需求而收集的資料格式,多半都是數字以及描述相關數值的文字,然而物聯網則是針對個人來蒐集資訊,內容格式就會偏重文檔、視訊、圖像、影音等,蒐集到的資料數量也會大幅增加。

為了應付物聯網這種大量複雜資料以及不斷輸入資料的特性,王雲表示,必須仰賴多層處理架構的運算方式,將資料上傳到大型資料中心變得較不經濟,取而代之的是利用小型基地臺,如電信公司的基地臺,來做局部的運算,以減輕網路與終端設備的負擔。

王雲表示,物聯網目前發展出三種應用,第一種是隨著RFID技術發展所形成的供應鏈應用,像是原料供應、製造、運輸、零售經銷的過程等,這些應用通常都藉由RFID來確保商品的製程、運送過程與零售庫存等,都更易於管理。第二種則是專業化的應用,如智能電網或是水庫資源分配等,這類應用則通常必須收集大量自然資源的資料,利用分析後的資料來平衡供需關係。第三種是新興的應用,例如政府公部門的路燈、道路系統等。

雖然現在已經有實際運用物聯網技術的案例,但王雲認為,仍需要更多時間,才會有更大規模的應用。因為,像是RFID、或是智能電網的建置費用都偏高,王雲解釋,新技術取代舊技術的因素很多,其中,價格與成本的因素則必須靠時間來降低其影響性。

王雲還進一步分析臺灣發展物聯網的關鍵是在產業技術轉變。過去IC晶片的技術著重在資訊處理效能,但未來IC晶片的技術也要能夠具有接收感應的功能,比如去感應濕度、溫度、速度等,將有助於發展智能監控應用。
官方網站 : http://knopper.net/knoppix/index-en.html
中文網站 : http://knoppix.tnc.edu.tw

KNOPPIX 是由德國程式設計師克勞斯 (Klaus Knopper) 設計的,他把他的姓 Knopper 和 Linux 結合在一起稱為「KNOPPIX」。在最近兩年來,Linux 系統的 X-Window 介面已經設計得非常完善與實用,而且在介面的美化上並不輸給 Windows 系統,例如目前知名的 RedHat Linux、Mandrake Linux, 由於 Linux 系統在安裝上並不像 Windows 系統那麼方便,外人總是誤解「Linux安裝不方便、介面不好用」而排拒 Linux,因此 Klaus 特別把 KDE 版的 Linux 改寫成速成光碟版,使用者只要把 KNOPPIX 光碟放入 光碟機中,開機時更改成從光碟開機,就可以使用 Linux,省去安裝 Linux 的麻煩,而且不會對主機現有硬碟造成任何影響。

   KNOPPIX 是以自由軟體 Linux 的 Debian 套件為主幹,不必安裝,免用硬碟,直接在光碟上執行完整的 Linux 作業系統,它既可以用來當桌上工作站用,也可以用來當網路伺服主機。KNOPPIX 是使用特殊的壓縮技術,將約 2GB 的檔案壓縮在一片700MB 的光碟上,另外透過一支內附的小程式,還可以將光碟上的系統安裝到硬碟中。KNOPPIX 在 2000 年時初步完成,今年是第三版,可以從網路上下載 ISO 檔自行燒錄成光碟,並且允許自由散佈與修改。

[img[img/linux/knoppix-5.3.1-06.png]]
<<toBalaNotes "knoppix">>
{{op1{Linux  Live CD 重要網站}}}
1. DistroWatch : http://distrowatch.com/index.php?dataspan=4
2. OSDisc : http://www.osdisc.com/cgi-bin/view.cgi/index.html?ad=distrowatch
3. LiveCD News : http://www.livecdnews.com/



///%knoppix
//%/
維基百科 : http://en.wikipedia.org/wiki/Linux

{{item1{Linux 的由來}}}
<html><img src="img/linux/705px-Unix_history.svg.png" style="width:80%;height: 80%;"/></html>

{{op1{Linux 的發展}}}
1970年,AT&T 貝爾實驗室的 Kenneth Thompson、Dennis Ritchie 和其他人開始在一台較老的 PDP-7 上開發一個小型的操作系統。不久這個操作系統被命名為 Unix,是對此前一個叫做 MULTICS 的操作系統項目的雙關語。在1972-1973 年,系統被重新用 C 語言改寫了,這是一個很有眼光的不尋常的舉動:這個決定使 Unix 成為第一個可以脫離其原始硬件而存在的被廣泛應用的操作系統。其它的新方法也不斷被加入 Unix,一部分原因是貝爾實驗室與學術界的良好協作。1979年,Unix 的“第七版”(V7)發布了,它是所有現存 Unix 系統的鼻祖。

AT&T 把 Unix 繼續的改良,發展出了後來的 System V。而在美國加州大學的柏克萊分校,另一種的 Unix 也在發展,它叫做 BSD,BSD Unix 的加入是 Unix 史上很重要的一個里程碑,BSD 加入了 TCP/IP 的網路功能,和一個已經變成 Unix 標準必備的程式: vi。 

Linux 是在1991年八月,芬蘭的大學生 Linus Torvalds 宣佈他正在發展一套不用錢的作業系統,揭開了 Linux 的序幕,他開始將 ''bash (一種shell,類似 command.com)、 gcc (C 的編譯器) 這兩個軟體移植到 Linux 上'',1991 年 9 月,他開始對外散佈他寫好的原始程式碼,Linux 便誕生了。由於 Linus 本人大力的推廣,Linux 便快速的發展,完全公開的程式碼,使任何人的都可以發展 Linux 的應用程式,使 Linux 功能越來越強大,由於是免費的,使越來越多人使用 Linux 這套作業系統。

{{item1{Distinguished Engineer (傑出工程師)}}}
{{op1{1. Unix 發明人}}}
[img[img/225px-Ken_n_dennis.jpg]]
''肯·湯普遜(左)與丹尼斯·里奇''

1943 年湯普遜出生於美國紐奧良。1960年就讀加州大學博克萊分校主修電力工程,取得了電子工程碩士的學位。1966年加入了貝爾實驗室。湯普遜參與了貝爾實驗室與麻省理工學院以及通用電力公司聯合開發的一套多使用者分時作業系統,名叫Multics,同時他自己用寫的一個「star travel」遊戲可執行於Multics之上。貝爾實驗室後來撤出Multics計劃。湯普遜只好找到一台老式PDP-7機器,重寫了他的「star travel」遊戲。

在開發Multics的期間,湯普遜創造出了名為Bon的程式語言。湯普遜花了一個月的時間開發了全新的作業系統,''UNiplexed Information and Computing System(UNICS)'',可執行於PDP-7機器之上,後來改稱為 ''UNIX''。第一版的Unix就是基於B語言來開發的。Bon語言在進行系統編程時不夠強大,所以Thompson和Ritchie對其進行了改造,並與1971年共同發明了C語言。1973年Thompson 和Ritchie用C語言重寫了UNIX。安裝於PDP-11的機器之上。

1983 年,美國計算機協會將杜林獎授予湯普遜與丹尼斯。

''Thompson also developed UTF-8'' (a widely used character encoding scheme) together with Rob Pike in 1992.

''In late 2000, Thompson retired from Bell Labs. He worked at Entrisphere, Inc as a fellow until 2006 and now works at Google as a Distinguished Engineer (傑出工程師)''.

{{op1{2. 自由軟體精神領袖 (GNU)}}}
[img[img/RichardMatthewStallman.jpg]]
''理查·斯托曼在挪威奧斯陸,2009年''

理查·馬修·斯托曼(Richard Matthew Stallman,簡稱 rms,1953年3月16日-)是美國自由軟體運動的精神領袖、GNU計劃以及自由軟體基金會(Free Software Foundation)的創立者。作為一個著名的駭客,他的主要成就包括 ''Emacs'' 及後來的 ''GNU Emacs'',''GNU C 編譯器'' 及''GNU 除錯器''。他所寫作的 GNU 通用公共許可證(GNU GPL)是世上最廣為採用的自由軟體許可證,為''copyleft 觀念'' 開拓出一條嶄新的道路。

1990 年代中期,斯托曼把他大部時間花在作為一個政治運動者,為自由軟體辯護,對抗軟體專利及版權法的擴張。他仍在程式設計方面奉獻的心力都放在 GNU Emacs。他的演講當中大約半數有收入,這讓他能夠養活自己。

''經歷''
斯托曼1953年出生於美國紐約曼哈頓地區的猶太人家庭,1971年進入哈佛大學學習,同年受聘於麻省理工學院人工智慧實驗室(AI Laboratory),成為一名職業駭客。

在AI實驗室工作期間,斯托曼開發了多種今後影響深遠的軟體,其中最著名的就是Emacs。斯托曼在 AI是一名典型的駭客,是整個駭客文化的一份子。

然而進入八十年代後,駭客社群在軟體工業商業化的強大壓力下日漸土崩瓦解,甚至連AI實驗室的許多駭客也組成了Symbolic公司,試圖以專利軟體來取代實驗室中駭客文化的產物——可自由流通的軟體。

斯托曼對此感到氣憤與無奈。在對Symbolic進行了一段時間的抗爭後,他於1985年發表了著名的GNU宣言(GNU Manifesto),正式宣布要開始進行一項宏偉的計劃:創造一套完全自由,兼容於 Unix 的作業系統GNU(GNU's Not Unix!)。之後他又建立了自由軟體基金會來協助該計劃。

他於1989 年與一群律師起草了廣為使用的GNU通用公共協議證書(GNU General Public License, GNU GPL),創造性地提出了「Copyleft」的概念。 同時,GNU計劃中除了最關鍵的 Hurd 作業系統核心之外,其他絕大多數軟體已經完成。

''自由軟體基金會網址'' : http://www.fsf.org/

{{op1{3. Linux 發明人}}}
[img[img/Torvalds.jpeg]]

林納斯·本納第克特·托瓦茲(Linus Benedict Torvalds, 1969年12月28日-),當今世界最著名的電腦程式設計師、駭客之一。Linux核心的發明人及該計劃的合作者。托瓦茲利用個人時間及器材創造出了這套當今全球最流行的作業系統核心(之一)。

托瓦茲出生於芬蘭赫爾辛基市。父親尼爾斯·托瓦茲(Nils Torvalds)是一名活躍的共產主義者及電台記者。托瓦茲家族屬於在芬蘭佔 6%的少數民族芬蘭瑞典人。他畢業於赫爾辛基大學計算機科學系,1997年至2003年在美國加州矽谷任職於全美達公司(Transmeta Corporation)參與該公司晶片的code morph技術研發。後受聘於開源碼發展實驗室(OSDL : Open Source Development Labs, Inc),全力開發 Linux 核心。現任職於 Linux 基金會。

Linux 基金會網址 : http://www.linuxfoundation.org/
Linus Torvalds 的網址 : http://www.cs.helsinki.fi/u/torvalds/

<<toBalaNotes "linux">>



///%linux
//%/

''參考文章''
1. MeeGo手機版開放社群預覽
http://www.runpc.com.tw/news.aspx?id=100627

MeeGo 官方網址 : http://meego.com/

MeeGo 是一個基於 Linux 的行動作業系統計劃,它於2010年 2月的全球行動通訊大會中宣佈  ,主要的推動者為諾基亞與英特爾。

它將結合諾基亞 Maemo 中基於 Qt 的用戶介面及英特爾Moblin的核心軟體平台。 相容性方面,MeeGo將支援英特爾的 AppUp 及諾基亞的 Ovi 數位發行平台。 MeeGo 將同時支援 ARM 和 x86 的處理器。

''版本歷史''
Intel Developer Forum 2010 中宣佈,MeeGo 以六個月作為發佈周期。2010年5月26日開始提供 Netbook 版本的下載。 2010年5月27日,MeeGO官 方正式發布 v1.0 小筆電體驗版和 N900 版 MeeGo v1.0 Core Software 平台。

{{item1{MeeGo Software Architecture Overview}}}
本文網址 : http://meego.com/developers/meego-architecture

The MeeGo platform has been carefully created to provide the components necessary for the best device user experience. As shown in the MeeGo Reference Architecture Overview diagram below, the MeeGo architecture is divided into three layers:

* The MeeGo OS Base layer contains the Linux kernel and core services along with the Hardware Adaptation Software required to adapt MeeGo to support various hardware architectures.
* The MeeGo OS Middleware layer provides a hardware and usage model independent API for building both native applications and web run time applications.
* The MeeGo User Experience layer provides reference user experiences for multiple platform segments; the initial MeeGo release will contain reference user experiences for handhelds and netbooks and additional platform segments will be supported over time.

[img[img/MeeGoArch1.png]]

<<toBalaNotes "meego">>


///%meego
//%/
For this "List" task we don't use the default action "addToList" (that simply adds all selected items to the list) but create the list using the "write" action and refer to the build-in variable "index" that is incremented for every tiddler being processed.
{{{
<<forEachTiddler
    where
        'tiddler.tags.contains("Notes")'
    write
        '(index < 10) ? "* [["+tiddler.title+"]]\n" : ""'
>>
}}}
In the write parameter there is a conditional output: when we are processing the tiddlers 0 to 9 it will write a line with:

 {{{* [[theTiddlerName]]}}}

Tiddler 10 and the following ones will generate no output (as the empty string is specified).

''//Result://''
<<forEachTiddler
    where
        'tiddler.tags.contains("Notes")'
    write
        '(index < 10) ? "* [["+tiddler.title+"]]\n" : ""'
>>
<<forEachTiddler 
 where
   'tiddler.tags.contains("toBalaMacro")'
>>
''德源科技''
http://twarm.com/commerce/index.php?cPath=105_79_142&sid=f27dd3868cf14bd6881f87d715bb8853

{{item1{ARM11 Mini6410}}}
http://twarm.com/commerce/product_info.php?cPath=105_79_142&products_id=1487

[img[img/mini6410layout.jpg]]

{{item1{威盛 GMB 聯盟 (GLOBAL MOBILITY BAZAAR) 簡介}}}
威盛 GMB 聯盟網址 : http://gmb.via.com.tw/resource/jsp/AboutGMB/GMB-about.jsp
隨著全球消費者對於行動裝置的關注與日俱增,越來越多的 IT 業者投入相關產品的製造,這樣的趨勢,也顯示了各式的超行動設備逐漸取代傳統的 PC,成為未來 x86 平台中的主流。不過除了少數業者挾著既有傳統產業資源之外,大多數的業者往往受限於本身資源的不足、在產品研發與技術取得能力有所限制下,使得這些產品無法充分滿足消費者的需求,無法達到事倍功半的效果。

為了改善行動裝置業者所面臨的窘境,並整合各家業者的力量與資源,提供全世界消費者更佳的產品與服務,行動裝置處理器大廠威盛電子正式成立了威盛 GMB 聯盟(Global Mobility Bazaar),秉持 VIA C7-M/ VIA Nano 處理器長期以來追求節能環保的理念,提供一個架構幫助客戶在短期內輕易設計出具有完整解決方案的小型筆電並上市銷售。威盛 GMB 聯盟 (Global Mobility Bazaar) 整合這些分散的力量來面對這個變化快速的市場,讓新產品能夠在第一時間推出,滿足消費者在教育、行動商務與通信的需求透過此聯盟策略性結合軟、硬體供應商來提供即時切入市場的方案並創造更廣大的市場商機,產生 1+1>2 的綜效。

{{item1{Life Computer}}}
網址 : [[mini-itx|http://www.mini-itx.com/]]

{{op1{以微型主機版 (mini-itx, nano-itx) 為主, 建構各式各樣微型電腦, 提供 “光碟” 或 “CF 卡” 開機.}}}

<html><img src="img/linux/embedded.png" style="width:70%;height: 70%;"/></html>
|[img[img/linux/r2d2pc0001.jpg]]|[img[img/linux/carrier-0024.jpg]]|
<<toBalaNotes "embedded">>

{{item1{eBox-4300}}}
網址 : http://www.embeddedpc.net/eBox4300/tabid/190/Default.aspx

[img[img/eBox2300.jpg]]
''規格''
{{{
- Fan-less Design
- VESA mounting support
- VIA Eden ULV 500MHz
- 512MB DDR2
- 10/100Mbps LAN
- CF Slot
- 3 x USB 2.0 ports
- Mini PCI Socket
- Wireless LAN (optional)
- 2 x RS-232 ports
- AC97 2.2 Audio
- Size 115*115*35 mm
- Weight 505g
}}}

{{item1{Advanced RISC Machine : ARM}}}
ARM 網址 : http://www.arm.com/
ARM 維基百科 : http://zh.wikipedia.org/w/index.php?title=ARM%E6%9E%B6%E6%A7%8B&variant=zh-tw

ARM 架構,過去稱作進階精簡指令集機器(Advanced RISC Machine,更早稱作:Acorn RISC Machine),是一個 32 位元精簡指令集(RISC)處理器架構,其廣泛地使用在許多嵌入式系統設計。由於節能的特點,ARM 處理器非常適用於行動通訊領域,符合其主要設計目標為低耗電的特性。

在今日,ARM 家族佔了所有 32 位元嵌入式處理器 75% 的比例,使它成為佔全世界最多數的 32 位元架構之一。ARM 處理器可以在很多消費性電子產品上看到,從可攜式裝置(PDA、行動電話、多媒體播放器、掌上型電玩,和計算機)到電腦週邊設備(硬碟、桌上型路由器)甚至在飛彈的彈載計算機等軍用設施中都有他的存在。在此還有一些基於 ARM 設計的衍伸產品,重要產品還包括 Marvell 的 XScale 架構和德州儀器的 OMAP 系列。

{{op1{HYKJ-2410 主板}}}
HYKJ-2410 主板是一款基於 ARM9 處理器的嵌入式工業計算機主板,採用標準的 90mm×96mmPC104 架構,使用三星 S3C2410 作為核心處理器,預裝 UCOS 操作係統,自主開發的顯示控制係統可支持模擬屏顯示,適合於用戶開發高性能工業控制設備或終端。

整個模塊具有高性能,高集成度,低功耗,工作時不發熱等特點。它結構緊湊,體積小,安裝使用方便,不但支持 PC104 總線擴展,而且可驅動模擬屏,與 X86 主板相比功耗更低,可靠度更高,同時還可大大降低用戶的生產成本。 

[img[img/linux/HYKJ-2410.jpg]]

''ARM11 Mini6410''
網址 : http://twarm.com/commerce/product_info.php?cPath=105_79_142&products_id=1479

[img[img/mini6410layout.jpg]]
<<toBalaNotes "arm">>



///%embedded
//%/

///%arm
//%/
<<forEachTiddler
    script '
        window.fetItemsPerPage = 20;

        function getHeader(context,count) {
            if (!window.fetStartIndex || window.fetStartIndex < 0) 
                window.fetStartIndex = 0;

            // ensure not to page behind the last page
            if (window.fetStartIndex >= count)
                window.fetStartIndex = Math.min(Math.max(window.fetStartIndex-window.fetItemsPerPage,0),count-1);

            createTiddlyButton(context.place,"<",null,
                    function(e) {
                        window.fetStartIndex -= window.fetItemsPerPage;
                        story.refreshTiddler(context.viewerTiddler.title,null,true);
                    });
            createTiddlyButton(context.place,">",null,
                    function(e) {
                        window.fetStartIndex += window.fetItemsPerPage;
                        story.refreshTiddler(context.viewerTiddler.title,null,true);
                    });

            var startNo = window.fetStartIndex+1;
            var endNo = Math.min(count,window.fetStartIndex+window.fetItemsPerPage);

            return "("+startNo+" - "+endNo+ " of "+ count + " items)\n";
        }
    '

    write
            '(index >= window.fetStartIndex) && (index < window.fetStartIndex + 20) ? "* [["+tiddler.title+"]]\n" : ""'

        begin
            'getHeader(context,count)'
>>

// /%
With a little scripting you can use the ~ForEachTiddlerPlugin to display the result "by pages". I.e. you don't display the full result list, but (e.g.) 10 at a time. 
Using a "pagewise" display may be useful when the result may get very large. This way you avoid scrolling the window to see the result. It also speeds up things since less items need to be display at a time.

''Code''
{{{
<<forEachTiddler
    script '
        window.fetItemsPerPage = 10;

        function getHeader(context,count) {
            if (!window.fetStartIndex || window.fetStartIndex < 0) 
                window.fetStartIndex = 0;

            // ensure not to page behind the last page
            if (window.fetStartIndex >= count)
                window.fetStartIndex = Math.min(Math.max(window.fetStartIndex-window.fetItemsPerPage,0),count-1);

            createTiddlyButton(context.place,"<",null,
                    function(e) {
                        window.fetStartIndex -= window.fetItemsPerPage;
                        story.refreshTiddler(context.viewerTiddler.title,null,true);
                    });
            createTiddlyButton(context.place,">",null,
                    function(e) {
                        window.fetStartIndex += window.fetItemsPerPage;
                        story.refreshTiddler(context.viewerTiddler.title,null,true);
                    });

            var startNo = window.fetStartIndex+1;
            var endNo = Math.min(count,window.fetStartIndex+window.fetItemsPerPage);

            return "("+startNo+" - "+endNo+ " of "+ count + " items)\n";
        }
    '

    write
            '(index >= window.fetStartIndex) && (index < window.fetStartIndex + 10) ? "* [["+tiddler.title+"]]\n" : ""'

        begin
            'getHeader(context,count)'
>>
}}}
// %/
感謝你使用土芭樂知識王 - 學習筆記本, 首先請你根據以下設定程序, 設定此筆記本的版面
__{{item1{修改筆記本主標題 (SiteTitle) 及 次標題 (SiteSubTitle)}}}__
1. 展開左邊選單中的 ''[知識王管理]'' 項目
2. 點選 ''[版面管理員]'', 然後設定平台標題文字

<<toBalaSWF2 "movie/KMKTitle.swf" "820" "610" "教學影片 - 修改筆記本標題文字">>

__{{item1{產生主選單樹狀文章架構}}}__
1. 展開左邊選單中的 ''[知識王管理]'' 項目
2. 點選 ''[版面管理員]'', 然後設定資訊樹架構

<<toBalaSWF2 "movie/KMKTree.swf" "820" "610" "教學影片 - 產生主選單樹狀文章架構">>

''[注意]'' 執行完上述二項設定, 記得點選工具列中的 ''[儲存變更]'' 按鈕, 儲存你的設定並重新載入

<<toBalaNotes "setup">>


///%setup
//%/
<html><img src="img/linux/linux01.png" style="width:70%;height: 70%;"/></html>

<<toBalaNotes "dist">>
{{item1{Debian}}} 
Debian is a volunteer project to develop a GNU/Linux distribution. Debian was started more than a decade ago and has since grown to comprise more than 1000 members with official developer status and many more volunteers and contributors. It has expanded to encompass over 20,000 "packages" of free and open source applications and documentation. 

Debian 官方網站 : http://www.debian.org/

{{item1{Ubuntu}}}
Ubuntu 是一套由社群開發的作業系統,適用於筆記型電腦,桌上型電腦和伺服器。無論您在家中,在學校或是在工作中使用,Ubuntu 提供了您所需要的程式,從文字處理,電子郵件程式到網頁伺服器,程式設計工具,應有盡有。

Ubuntu 永久免費,您無需支付授權費用;您可以自由下載、使用、與您的同伴分享 Ubuntu,而毫無任何代價。

我們 每六個月推出一套新的 ''桌面版本'' 和 ''伺服器版本'';您將可以享受到自由軟體世界所提供的最新、最好的程式。

Ubuntu 的安全性考慮深遠,您可以在至少 18 個月的期間為 ''桌面版本'' 和 ''伺服器版本'' 取得免費安全性更新,若使用長時間支援 (LTS) 版本您將會有至少 ''三年'' 的桌面版本支援 以及 ''五年'' 的伺服器版本支援。長時間支援版本無須額外費用,我們在相同自由的條件下努力為每個人製作。升級到最新版本的 Ubuntu 也是免費的。

官方網站 : http://www.ubuntu.com/

{{item1{ Fedora/Red Hat}}}
The Fedora operating system is an RPM-based, general purpose Linux distribution, developed by the community-supported Fedora Project and sponsored by Red Hat. Fedora's mission statement is: "Fedora is about the rapid progress of Free and Open Source software."

One of Fedora's main objectives is not only to contain free and open source software, but also to be on the leading edge of such technologies. Also, developers in Fedora prefer to make upstream changes instead of applying fixes specifically for Fedora — this ensures that updates are available to all Linux distributions.

Fedora 官方網站 : http://fedoraproject.org/

{{item1{CentOS}}}
官方網站 : http://www.centos.org/

CentOS(Community ENTerprise Operating System)是 Linux 發行版之一,它是來自於 Red Hat Enterprise Linux 依照開放原始碼規定釋出的原始碼所編譯而成。由於出自同樣的原始碼,因此有些要求高度穩定性的伺服器以 CentOS 替代商業版的 Red Hat Enterprise Linux 使用。兩者的不同,在於 CentOS 並不包含封閉原始碼軟體。

<<toBalaNotes "dist">>

{{item1{Linux 教育訓練}}}

{{op1{1. Red Hat}}}
''恆逸資訊''
http://edu.uuu.com.tw/events/070515/01.htm

''聯成電腦''
http://www.lccnet.com.tw/zsergb026-test/linux/linux.htm

{{op1{2. LPIC 認證}}}
''資策會數位教育研究所''
http://www.iiiedu.org.tw/taipei/course/course.htm

{{op1{3. Ubuntu}}}
''奇科電腦 (Ubuntu Linux全亞洲唯一授權教育訓練中心)''
http://webapps.ubuntu.com/partners/training/ 

{{op1{4. SUSE}}}
''巨匠電腦''
http://www.pcschool.com.tw/campus/course/Default.aspx

///%dist
//%/
Live USB 是USB 隨身碟或 USB 硬碟,裡面含有完整的作業系統,可以被用來開機(booting)。Live USB 很像 Live CD,但基本上有能力存取設定,而且可以把軟體安裝回 USB 裝置上。像 Live CD 一樣,Live USB 可以使用在嵌入式系統系統管理(embedded systems system administration),資料還原(data recovery),或是不需要把作業系統安裝到主機硬碟(local hard disk drive)裡的測試。許多作業系統,包含微軟的 Windows XP Embedded 和許多 Linux 套件和 BSD 可以被安裝在隨身碟上使用。

[img[img/linux/280px-Live_USB_ubuntu.png]]

{{item1{Live USB 使用型式}}}
1. Live CD derived
{{{
The first type of live USB is created by simply taking the ISO image file from a live CD distribution and placing it on USB storage device and then making it bootable. 
}}}
2. Full install (完整安裝)

3. 直接使用 
{{{
系統的修改及資料的管理均存於啟動的 USB 硬碟中
}}}
<<toBalaNotes "liveusb">>




///%liveusb
//%/
官方網站:http://www.tiddlywiki.com/

|Jeremy Ruston[img[img/Jeremy.jpg]] |<< @@font-size:16pt;color:#00f;line-height:25pt;~TiddlyWiki is a single-file, self-contained wiki for managing micro-content, written in ~JavaScript.@@|
|borderless|k

{{item1{It's a single file}}}
<nowiki>A complete TiddlyWiki is stored in a single file on your computer, and thus belongs to the class of Single Page Applications. That makes it super-easy to move your TiddlyWiki around on a USB stick or by emailing it to yourself. 
</nowiki>

{{item1{It's self-contained}}}
<nowiki>The single file that is a TiddlyWiki contains not only all of your data, but all the machinery to edit and manuipulate it. All you need is a modern web browser, like Mozilla Firefox or Microsoft Internet Explorer. You don't need to have any other special programs installed on your computer, and you don't need to be connected to the Internet. The same TiddlyWiki file will work on just about any computer: Windows PCs, Apple Macs, Linux and BSD boxes.. 
</nowiki>

{{item1{It's a wiki}}}
<nowiki>A wiki is a collection of web pages, like a normal web site, except that every page can be edited, easily and immediately. Wiki systems are often used to collaboratively manage documention for large projects, and also sometimes used by a single user as a kind of personal notebook. 
</nowiki>

{{item1{It manages micro-content}}}
<nowiki>Most web sites and wikis manage information as pages. TiddlyWiki is different -- it saves your stuff in smaller chunks (each chunk is called a 'tiddler'). Information in small chunks like this is called 'micro-content', and once you start usingTiddlyWiki, you realise that micro-content is a natural fit to a lot of the stuff you deal with every day. 
</nowiki>

<<toBalaNotes "TiddlyWiki">>


///%TiddlyWiki
//%/
''參考文章''
下一波資訊發展浪潮:物聯網時代即將降臨
http://mag.udn.com/mag/digital/storypage.jsp?f_ART_ID=244781

本文網址 : http://big5.ce.cn/cysc/communications/yjdt/201005/25/t20100525_20396008.shtml

“物聯網”、“嵌入式技術”、“傳感技術”、“智慧家居”、“泛在網路”……這些看上去熟悉又陌生的專有名詞將使我們的生活發生怎樣的變化?當語言不再是人類特有,所有物與物、物與人之間都可以通過電腦、互聯網進行立體對話,世界又將發生怎樣的變化?

早上醒來,躺在床上用手機發條指令,麵包機、煮蛋器可自動為你做好早點;進入辦公區,刷刷門卡,所有需要的照明設備便可自動亮起;晚上回家,空調可提前開啟為你驅寒降暑;外出逛街,GPS等手持設備可為你蒐羅附近最新的促銷資訊,並將商場的營業時間、目的路線、特色資訊統統發到你的手機上……當周圍所有的物品都與電腦和互聯網連接,實現上述“幻想”將變得再簡單不過。

''何為物聯網?''

顧名思義,從字面意義上看,物聯網是將所有物體借助一定的系統、設備廣泛連接在一起而形成的巨大網路。物聯網的英文名稱為“The internet of things”,這其中包含兩種意思。一是,物聯網的核心和基礎依然是互聯網。物聯網是在互聯網基礎上的一種延伸和拓展,比互聯網擁有更廣泛的應用範圍,但脫離了互聯網,物聯網也便成了”無米之炊“。二是物聯網的用戶端延伸和擴展到了所有的物品與物品之間,進行資訊的傳遞、交換和通信。因此,物聯網還需要依靠射頻識別(RFID)裝置、紅外感應器、全球定位系統、鐳射掃描器等資訊傳感設備,按照約定的協議,把物品和互聯網連接起來,交換資訊實時通信,以實現智慧化之別、定位、跟蹤、監控和管理。

物聯網與泛在網、傳感網一樣,都不是新興名詞,只是隨著互聯網應用的快速普及和國家對物聯網、嵌入式技術的不斷重視,正在從實驗室逐漸走進尋常百姓家,形成“你中有我、我中有你“的密切關係。

從通信對象及技術的覆蓋範圍上來看,泛在網路包含物聯網,物聯網包含感測器網;感測器網是實現數據資訊採集的一種末端網路;物聯網除了包括感測器網外,還包括自組網、電子標簽網、M2M等。但這幾種概念都有一個共同的特性,即需要在物體上安裝電腦軟體,完成吸收、傳遞、反饋資訊的全過程

以我們日常使用的家用電器產品為例,在物聯網時代,電視將不僅僅用來觀看電視節目、瀏覽網頁,甚至可以充當家庭網路的控制平臺,在螢幕上對冰箱的保鮮溫度、耗電功率進行調控,對洗衣機的工作模式、水溫水量、開閉時間進行設定,並與家庭多媒體設備互聯互通,一鍵輕觸,即可播放提前設定好的音樂、電視電影,置身於世外桃源般的家庭影音世界。

''網羅天地''

物聯網描繪的是一個充滿智慧化的世界,在個世界裏,物品對人、物品之間的服務功能都將發生質的飛躍,並帶動各種新興產業的發展的進步。

物聯網是從廣義對物物相連的宏大前景所做的精煉概括,但在實際應用中需要紛繁複雜的各種系統的支援,嵌入式系統應用便是目前最重要的實現模式。嵌入式系統是以應用為中心、以電腦技術為基礎、軟體硬體可裁剪、適應應用系統對功能可靠性、成本、體積、功耗嚴格要求的專用電腦系統。這套系統的功能與電腦中的Windows、Linux等原理類似,但在應用範圍上更加龐大。Windows系統僅限于電腦終端本身,而嵌入式應用系統則適用於所有可以想像的能夠內嵌軟體系統的萬事萬物,家電產品也只是其中很小的一部分。

在這方面,以坂村健為代表的日本嵌入式系統開發團隊已經走在了世界前列。短信寶空調器、神經模糊控制洗衣機、只能控制的造紙生產線、電腦繡花機、多功能包裝機械等應用嵌入式技術的產品不斷涌現。據坂村健介紹,日本裝有嵌入式系統的電腦佔比已達60%。而在我國,家電、食品等行業的嵌入式技術應用開始慢慢不如正軌。就在前不久,海爾發佈了世界上首臺物聯網冰箱,不僅可以儲存食物,還可與網路連接,實現冰箱與冰箱裏的食品進行對話的功能。

這些都僅僅是一個開始。按照坂村健的理想,在物聯網普及的未來,萬物都可以通過嵌入式系統“開口說話“,傳遞資訊,讓整個地球變得”更加智慧 “。坂村健的物聯夢已經延續了30年。今日,坂村健攜手中國中國科學院計算技術研究所、中國家用電器研究院組建了中國輕工業聯合會嵌入式系統應用委員會,希望在中國這個擁有14億人口的新興大國中實現嵌入式系統、泛在網路的全面普及,讓更多的中國消費者感受到物聯網所帶來的更加智慧化、科技化、人性化的網路革命。 

<<toBalaNotes "1">>


///%1
//%/
{{{
<<forEachTiddler
    where
        'tiddler.tags.contains("plugin")'
    write
        '""'
        end 'count+" Tiddlers found\n"'
        none '"No Tiddlers found\n"'
>>
}}}
The macro writes an empty string for every tiddler tagged "basic", i.e. it writes nothing. 

Just at the end it writes the number of found tiddlers (using the ''end'' feature of the ForEachTiddler macro) or "No Tiddler found" if no tiddler is tagged with "basic"  (using the ''none'' parameter) .

''//Result://''
<<forEachTiddler
    where
        'tiddler.tags.contains("plugin")'
    write
        '""'
        end 'count+" Tiddlers found\n"'
        none '"No Tiddlers found\n"'
>>
''參考文章''
1. ARM聯盟宣佈成立Linaro
http://www.linuxpilot.com/industry/news/kiji/20100606
2. Linaro誕生 Linux平台大戰白熱化 ?
http://www.eettaiwan.com/ART_8800608863_676964_NT_25ea892d.HTM

官方網址 : http://www.linaro.org/

英國IC 設計公司安謀(ARM Holdings Plc)2日發布新聞稿宣布,該公司與飛思卡爾半導體(Freescale Semiconductor)、IBM、三星電子(Samsung  Electronics)、ST-Ericsson與德州儀器(Texas Instruments Incorporated)攜手成立非營利的開放原始碼軟體工程公司「Linaro」,主要目的在活絡開放原始碼的創新事業,以便迎接下一波「持續連線、隨時開機(always-connected, always-on)」的運算時代來臨。根據新聞稿,Linaro將幫助程式開發商與硬體製造商提供消費者更多選擇、更多感應裝置以及更多樣化的Linux系統應用程式。

安謀指出,Linaro 將集業界領導電子廠商的專業,加速Linux開發商對系統單晶片 (SoC) 的開發速度;能夠持續連線、隨時開機的電子裝置需要複雜的SoC才能達成消費者要求的運算效能與低耗電量。

根據新聞稿,Linaro 將對開放原始碼計畫投入資源,而這些計畫之後則可運用於 Android、LiMo、MeeGo、Ubuntu與 webOS等基於 Linux 系統產品推廣。此外,Linaro也計畫每6個月釋出獲得多種 SoC 驗證的最佳化工具、核心原始碼(kernel) 以及中介軟體(Middleware),以便為通路商、開發商提供穩定且最佳化的基礎。

Linaro的軟體與工具平台將適用於多種市場,可縮短智慧型手機、平板電腦、數位電視、車內娛樂與企業設備等產品的上市時間。安謀指出,Linaro的首批軟體與工具預定將在2010年11月釋出,並將為最新款ARM CortexTM-A系列處理器提供最佳化程式。
{{op1{Linux Kernel 相關網站}}}
[[1. Linux Kernel Archives, the official kernel repository|http://www.kernel.org]]
[[2. Linux 核心發展|http://www.linux.org]]

The ''Linux kernel'' is a Unix-like operating system kernel. It is the namesake of the Linux family of operating systems. Released under the GNU General Public License (GPL) and developed by contributors worldwide, Linux is one of the most prominent examples of free and open source software.

{{op1{Linux Kernel 功能架構圖}}}
<html><img src="img/Linux_kernel_map.png" style="width:95%;height: 95%;"/></html>

{{item1{Linux Kernel 內核 2.6.33 正式版發佈 (2010 年 02 月 25 日)}}}
Linus Torvalds 今天終於發佈了Linux Kernel 系統內核的最新穩定版本 2.6.33,距離上一個 2.6.32 又是三個月過去了。

Linux Kernel 2.6.33 的開發歷經七個 RC 候選版,新特性方面帶來了 Nouveau DRM GPU 代碼、大量的 Radeon KMS 改進、新的VMware DRM、高級 Linux 音頻架構(ALSA) 改進、支援 AMD K10 處理器散熱檢控、大量的新驅動程式,等等等等。

根據此前對 RC 版本的測試,Linux Kernel 2.6.33 的 EXT4 文件系統又有所降低,不過 Btrfs 文件系統性能有所提升。

<<toBalaNotes "kernel">>

{{op1{Linux 核心版本代號 (uname  -r)}}}
在核心版本中,要注意到 第二個數字,就是 次版本的號碼。如果它是一個奇數的話,那這個版本是實驗性的版本。如果它是一個偶數﹐基本上﹐該版本已經獲得一定程度的測試和肯定﹐已趨於穩定和可靠的狀態。

{{op1{Stable version history}}}
{{{
 Version 1.0 of March 1994 supported only single-processor i386 machines. 
 Version 1.2 of March 1995 added support for Alpha, Sparc and MIPS. 
 Version 2.0 of June 1996 included SMP support and added support for more processors. 
 Version 2.2 of January 1999 (The Wonderful World of Linux 2.2). 
 Version 2.4.0 of January 2001[37] 
 CPU support: Hewlett-Packard's PA-RISC processor, Axis Communications' ETRAX CRIS ("Code Reduced Instruction Set") processors 
 added ISA Plug-and-Play 
 added USB and PC Card support 
 2.4.6: added Bluetooth support 
 Filesystem and data storage 
 added Logical Volume Manager (LVM) version 1 
 support for RAID devices 
 2.4.15: Support for InterMezzo filesystem were added. 

 Version 2.6 - current (December 17, 2003 to the present)[38] 
 integrated uClinux (for microcontrollers) [citation needed] 
 CPU support: with support for Hitachi's H8/300 series, the NEC v850, and Motorola's embedded m68k processors, NUMA support, support for NCR's Voyager architecture, support for Intel's hyperthreading and Physical Address Extension (PAE) 
 integrated the ALSA sound driver 
 OS support: 
 Improved APIC support. 
 Increased the maximum number of users and groups each from 65,536 (= 216) to 4,294,967,296 (232). 
 Increased the maximum number of process ids from 32,768 (= 215) to 1,073,741,824 (230). 
 Increased the maximum number of device types (major device) from 255 to 4095 and the maximum number of devices of each type (minor device) from 255 to more than a million. 
 Improved 64-bit support and filesystems of up to 16 terabytes on common hardware. 
 Improvements to the "overall responsiveness" for interactive processes (the kernel became fully pre-emptible and the I/O scheduler was rewritten). 
 Support for futexes, a rewrite of threading infrastructure to allow the Native POSIX Thread Library (NPTL) to be used. 
 An improved module loader. 
 User-mode Linux integration. 
 2.6.11 Infiniband support 
 Storage Support: 
 LVM version 2 
 support for SGI's XFS filesystem. 
 A new "system filesystem" called sysfs, destined to relieve procfs of its system related information. 
 2.6.2 ATA over Ethernet support 
 2.6.12 (17 June 2005) iSCSI support 
 2.6.13 inotify support 
 2.6.14 9P support 
 2.6.14 FUSE support 
 2.6.17 Online reshaping of software raid5/6 
}}}


///%kernel
//%/
以 Linux Kernel 為核心, 再整合各式各樣的系統管理程式及應用程式, 組成一套完整的作業系統, 這樣的組合稱之為 Linux 發行套件. 
{{{
- Kernel
- Shell (bash,…)
- Command & GNU Tools (nano, gcc, g++, make,…)
- X Window
- Window Manager
- Desktop Environment
}}}
<<toBalaNotes "dist">>
{{item1{Kernel}}}
負責行程排程 (process scheduling), 虛擬記憶體 (Virtual memory), 檔案系統 (file management) 及 I/O 裝置的管理

{{item1{shell}}}
GNU Bourne again shell (bash) 是 linux 系統最普遍的 shell,bash 提供許多先進功能,如作業控制 (job control),命令歷程 (command history) , 檔名自動補齊 (filename completion) 等。

{{item1{Command & GNU Tools}}}
大多數的 linux 基本公用程式都是GNU 軟體,所以有許多 linux 發行套件,聲稱自己是 standard GNU/linux components (例如 ByzantineOS)

LINUX 系統最為通用的編譯器為 GCC(GNU Compiler collection),它可以編譯 c,c++,objective c。利用 GCC 可以開發出許多 linux 應用程式,還可以透過 CVS 達到協同開發。

BusyBox 網址 : http://www.busybox.net/about.html
GNU Tools 網址 : http://directory.fsf.org/GNU/

{{item1{X Window}}}
X Window 維基百科 : http://zh.wikipedia.org/zh-tw/X_Window%E7%B3%BB%E7%B5%B1

X 視窗系統(X Window System,也常稱為 X11 或 X)是一種以點陣圖方式顯示的軟體視窗系統。最初是1984年麻省理工學院的研究,之後變成 UNIX、類UNIX、以及 OpenVMS 等作業系統所一致適用的標準化軟體工具套件及顯示架構的運作協定。X Window系统透過軟體工具及架構協定來建立作業系統所用的圖形使用者介面,此後則逐漸擴展適用到各形各色的其他作業系統上。現在幾乎所有的作業系統都能支援與使用X。更重要的是,今日知名的桌面環境——GNOME 和 KDE 也都是以 X Window 系统為基礎建構成的。

由於 X 只是工具套件及架構規範,本身並無實際參與運作的實體,所以必須有人依據此標準進行開發撰寫。如此才有真正可用、可執行的實體,始可稱為實現體。目前依據X的規範架構所開發撰寫成的實現體中,''以 X.Org 最為普遍且最受歡迎''。X.Org 所用的協定版本,X11,是在1987 年9月所發佈。而今最新的參考實作(參考性、示範性的實作體)版本則是X11 Release 7.5(簡稱:X11R7.5),而此專案由X.Org基金會所領導,且是以MIT授權和相似的授權許可的自由軟體。[1]

[img[img/x_client_sever.png]]

XFree86 網址 : http://www.xfree86.org
X.org 網址 : http://www.x.org

{{item1{X Window Manager}}}
X Window Manager 維基百科 : http://en.wikipedia.org/wiki/X_window_manager

X 視窗管理器是 X Window 系統中,用來控管視窗外觀和放置方式的電腦軟體視窗系統,主要用於 ''類 Unix 系統''。

X 視窗管理器和蘋果公司的 Macintosh 和微軟公司的 Windows 的操作環境不同。後兩者都有長期固定的用戶界面和操作模式,而這些都是由開發商決定的,一旦選定無法更換或者只能作微小調整。X 視窗管理器是一個完全開放的,和圖像顯示軟體無關的用戶界面。用戶可以自由決定採用自己喜愛的第三方提供的窗口管理器。這些管理器可以擁有完全不同的
{{{
* 外觀和功能的可配置性
  - 用於啟動程序或者改變選項的文本化的菜單
  - 停靠欄或者是其他圖形化的啟動程序的樣式
  - 多桌面、虛擬桌面(比顯示器尺寸要大的桌面)和用於切換桌面的桌面切換器

* 和桌面環境的整合程度。提供更加完整的用戶界面、系統軟體和應用程序。
}}}

Fluxbox 網址 : http://www.fluxbox.org/

<<toBalaNotes "2">>

{{item1{桌面環境 (Desktop environment)}}}
{{{
1. K Desktop Environment (KDE)
2. GNOME
}}}

桌面環境除了提供應用工具外,還必須提供程式之間的 ''資料交換機制'' 以及 ''發展的程式庫'',另外還負責 ''檔案系統管理'',''系統環境的設定''。GNOME 是以自行開發的 GTK (GNU Tool kit) 程式庫,來開發所屬的應用工具

GNOME 網站: http://www.gnome.org
佈景主題下載:http://gtk.themes.org

K Desktop Environment  網站 : http://www.kde.org/

<<toBalaNotes "3">>
///%dist
//%/

///%2
//%/

///%3
//%/
''參考網站''
1. The LiveCD List
http://www.livecdlist.com/
2. DistroWatch.com
http://distrowatch.com/index.php?dataspan=4

Several Live Cds are dedicated to specific type of applications according to the requirements of thematic (主題的) user communities. These CDs are tailored to the needs of the applications in subject including general knowledge, tutorial, specifications and trial data too. Most important topics are the following:
@@font-size:14px;
* Live Cds dedicated to CAD
* Live Cds dedicated to Education
* Live Cds dedicated to GIS
* Live Cds dedicated to Games
* Live Cds dedicated to IT administration
* Live Cds dedicated to Medical Issues
* Live Cds dedicated to Media
* Live Cds dedicated to Robotics
* Live Cds dedicated to Sciences
@@
Some of these topics covers sub topics, e.g. IT administration breaks down to firewall, rescue, security, etc. type of Lice CDs. In some cases a particular LiveDVD covers more then one topics.

''[練習]'' 請尋找最小的 Live CD

<<toBalaNotes "livecd">>

{{item1{SliTaz}}}
網站 : http://www.slitaz.org/en/about/

SliTaz GNU/Linux is a free operating system working completely in memory from removeable media such as a cdrom or USB key. It is light, speedy and fully installable on a hard drive. SliTaz is distributed in the form of a LiveCD that you can easily burn to a cdrom and boot from. When the system is running you can eject the LiveCD and use your CD drive for other tasks. The Live system provides a fully-featured, working graphical distro and lets you keep your data and personal settings on persistent media. The system can be extended with the Tazpkg package manager and security updates are provided for the cooking and stable versions. 

///%livecd
//%/

''參考文章''
1. IBM Mote Runner : http://www.zurich.ibm.com/moterunner/
2. IBM Mote Runner SDK : http://www.alphaworks.ibm.com/tech/moterunner
3. MEMSIC : http://memsic.com/products/wireless-sensor-networks/wireless-modules.html

TinyOS 維基百科 : http://zh.wikipedia.org/zh-tw/TinyOS
TinyOS 官方網站 : http://www.tinyos.net/

TinyOS 是一款自由和開源的基於元件(component-based)的作業系統和平台,它主要針對無線感測器網路(WSN, wireless sensor network)。TinyOS是用nesC程式編寫的嵌入式作業系統,其作為一系列合作項目的結果。 它的首先出現是做為 UC Berkeley和 Intel Research 合作實驗室的傑作,用來嵌入智慧微塵當中,之後慢慢演變成一個國際合作項目,即 TinyOS 聯盟。

TinyOS應用程式是用nesC編寫,它是C programming language的一個分支對於感知網路的內部記憶體限制問題作了最佳化。它的補充工具主要來自於Java形式和shell script的front-ends。其他的相關的函式庫和工具,例如NesC編譯器和Atmel AVRbinutils toolchains,大部分用C編寫。

TinyOS程式由基於元件的軟體工程software component建構,它們中一些表現了硬體的抽象概念, 元件用介面互相連線。TinyOS為普通的抽象描述(abstractions)提供了介面和元件,例如資料包通訊(packet communication),路由,感知(sensing),行為(actuation)和儲存。

TinyOS完全的non-blocking:它配備了一個單獨的堆疊。因此所有的持續超過幾百微秒I/O操作都以非同步進行並且帶有回叫功能(callback)。為了使原生的編譯器更加出色地最佳化交叉呼叫邊界(optimize across call boundaries),TinyOS用nesC的特性去連線這些回叫,叫作事件(events)。non- blocking系統可以讓TinyOS在單一記憶體下保持高度的協同性(concurrency)。它強迫程式用stitching together many small event handlers的方法編寫複合邏輯。為了支援更高的計算量,TinyOS提供了任務(tasks),其比Deferred Procedure Call and interrupt handler bottom halves小。

一個TinyOS組建可以發布一個任務,作業系統可以把它排入列表以待之後執行。任務是沒有優先權的並且按照FIFO執行。 這個簡單的協同模型是典型的滿足了以I/O為中心的應用,但這樣的模型對於CPU負荷重的應用程式來說不是太好的,因為它會導致向OS多次提出執行緒間協同處理的請求(but its difficulty with CPU-heavy applications has led to several proposals for incorporating threads into the OS.)。

TinyOS代碼與程式代碼進行靜態連線,然後用GNU toolchain。編譯到一個小的二進制系統中。 它的聯盟為TinyOS的應用,提供完整的開發平台。
<<toBalaNotes "tinyos">>


///%tinyos
//%/
''參考文章''
1. Booting Linux with U-Boot on QEMU ARM
http://balau82.wordpress.com/2010/04/12/booting-linux-with-u-boot-on-qemu-arm/

''Qemu'' 是個相當不錯的模擬器,它不只可以模擬 x86,還可模擬 arm。最近找了很多相關的資料,發現目前已經有很多人寫了不錯的教學,而且 qemu 支援的 arm 平台 [ARM System emulator] 也相當多。但重點是 qemu 並非所有 arm 的平台都支援,所以或許可以找找 patch 或自己試著修改看看,才能符合自己的平台。

[[OPENCSL|http://opencsl.openfoundry.org/]] 這個網站相當不錯,初學者可以很快做出一個 "ARM Integrator" (ARMB26EJ-S 的架構)的模擬器。另外是 [[OpenMoko|http://wiki.openmoko.org/wiki/OpenMoko_under_QEMU]],目前已有修改過後的 qemu,跑出來就跟真的環境一樣。然後 [[Linux on Palm 5|http://orzlab.blogspot.com/2007/06/palm-5linux.html]] 也有修改後的模擬器,都可以實際跑起來。

<<toBalaNotes "arm">>

{{item1{實作}}}

{{op1{1. 啟動 embdLinux}}}
1. 在 embdLinux 目錄中, 快點二下 arm.bat
2. 輸入 root,  不須輸入密碼, 登入後如下圖 : 

[img[img/linux/arm.png]]

{{op1{2. embdLinux 內建命令 (Busybox)}}}

[img[img/linux/arm1.png]]

''BUSYBOX 網址'' : http://www.busybox.net/

<<toBalaNotes "busybox">>

///%arm
//%/

///%busybox
//%/
<<forEachTiddler 
 where
   'tiddler.tags.contains("toBala")'
>>
Moblin 官方網站 : http://moblin.org/documentation/moblin-overview

The Moblin Architecture is designed to support multiple platforms and usage models ranging from Netbooks to Mobile Internet Devices (MID), to various embedded usage models, such as the In Vehicle Infotainment systems. The central piece of the architecture is the common layer we call "Moblin Core", a hardware and usage model independent layer that provides one uniform way to develop such devices. Underneath the Moblin Core sits the Linux kernel and device drivers specific to the hardware platform, and above the Moblin Core are the specific user interface and user interaction model for the target device.

{{item1{開始安裝}}}

1. [[下載 Moblin Live Image|http://moblin.org/documentation/test-drive-moblin]] (moblin-netbook-beta-20090524-001.1.img)

2. Byte-copy the image to a USB drive or burn to CD.
使用 UNetbootin 工具, 將下載的 image 寫入 USB 硬碟中, 如下圖 :

[img[img/linux/UNetbootin.png]]

3. Boot the image on your netbook, MID, or PC.

{{item1{List of tested platforms}}}
The following platforms have booted successfully with the Moblin v2 beta image.
{{{
Acer Aspire One (ZG5)
Asus EeePC 901, 1000, 1000H
Dell Inspiron 910
MSI Wind
Lenovo S10
Samsung NC10
HP mini 1010 and 1120NR (wired networking only)
}}}

<<toBalaNotes "luinstall">>


///%luinstall
//%/
<<timeline>>
本文網址 : http://122.11.55.148/gate/big5/www.hqew.com/info/?action-viewnews-itemid-169349

據國外媒體報道,近日有傳聞稱,歐洲晶片生産商英飛淩和ARM已經成為被收購的目標,其中英特爾有意收購英飛淩,而蘋果可能收購ARM。兩家公司,英飛淩在有線、無線終端設備、汽車電子、工業控制及智慧卡晶片、能源行業有著多年的積累和資源,ARM則是英特爾最強勁的競爭對手,有別於後者晶片設計、生産、銷售一體化的思路,以提供晶片架構的商業模式贏得了市場的認可。

據了解,英飛淩和意法半導體均為蘋果産品的晶片提供商,同時蘋果還在産品中使用ARM的晶片設計。一系列的收購傳聞雖然尚未成為事實,但英特爾對嵌入式晶片市場的覬覦和猛攻,以及谷歌、蘋果對晶片自主控制權的躍躍欲試,很可能在全球晶片領域引發新一輪的洗牌,洗牌的背後必然帶來收購兼併的連鎖反應。

''晶片領域整合戰開拔''

實際上,這種傳言並非空穴來風,英特爾一直在嵌入式晶片領域試圖突破,英飛淩可能是合適的選擇,相比,蘋果iPhone一直採納的是ARM架構的晶片,剛剛上市的平板電腦iPad就是採用了PASemi研發的A4晶片,同樣基於ARMCortex-A8的SoC方案。

傳言出現後,英飛淩和ARM股價大幅上漲,甚至言之鑿鑿的消息稱蘋果收購ARM的交易價格可能高達80億美元,而且蘋果現金儲備超過400億美元,完全有能力收購ARM。業界專家對這一交易眾説紛紜。不過,由於ARM運營上採取了架構授權方案,三星、高通等晶片設計廠商都基於ARM推出了晶片解決方案,蘋果收購可能會影響其與下游間的合作關係。

ARM 保持獨立性更利於其自身的發展和成長,況且,ARM目前發展勢頭良好,如日中天,能否選擇在這個時機出售也是個未知數。另外,這一交易可能需要經過美國反壟斷審查。

僅是英特爾和蘋果志在晶片領域,谷歌也按捺不住晶片控制欲的衝動。昨日消息透露,谷歌近期收購了一家名為Agnilux的晶片公司,這家公司的創始人及部分團隊則來自蘋果2008年收購的PASemi公司,而這家公司生産的晶片A4已應用在蘋果平板電腦iPad身上,谷歌之舉大有挖蘋果墻角的嫌疑。

''蘋果谷歌加速晶片領域洗牌''

德國投資銀行MerckFinck的分析師蒂奧基茨(TheoKitz)並不認同溫德遜的觀點。他説:“英特爾有必要收購英飛淩,最起碼可以在市場份額方面佔據優勢。英飛淩的市場表現不錯,並且從去年的金融危機中起死回生,現在已經適應了節能和可再生等行業發展的大趨勢。”

儘管這一消息並沒有得到兩家公司證實,但收購ARM可以使蘋果在兩方面收益。首先,蘋果將獲得更多的晶片技術,對手機處理器的開發有更大的控制權。其次,蘋果可以阻止競爭對手使用ARM的技術,例如Android手機。而且事實上,蘋果早在八、九十年代,就一直走獨立CPU開發路線,採用了的是與IBM合作開發的POWERPC晶片,而後逐漸轉向了英特爾晶片陣營,但喬布斯主導晶片設計的野心始終未變,一直期望東山再起。

蘋果與谷歌進入晶片領域可能會打破過去的平衡格局,蘋果、谷歌、英特爾三方正逐漸向對方的市場滲透,谷歌基於linux技術的android系統在全球市場正勢如破竹,與蘋果的iphoneOS産生正面衝突,英特爾也聯合諾基亞發佈了MEEgo作業系統,並試圖將該平臺放到了MID、上網本、筆記本、車載等各種移動設備上,但讓英特爾産生不安的是蘋果和谷歌都對晶片領域虎視耽耽,畢竟軟體應用環境離不開晶片的支援。

''物聯網時代的晶片棋局''

物聯網,將各種資訊傳感設備,如RFID裝置、紅外感測器、GPS系統、鐳射掃描其等裝置與網際網路結合起來,形成一個巨大的網路,在多個領域發揮作用,2015年將會有150億台接入網際網路的嵌入式設備,而每台設備都具有智慧化的功能,帶有晶片和操作平臺,能實現與其他設備間的無縫通信和數據交換。相比,主宰了幾十年的PC、筆記本市場正逐步走向飽和,被眼花繚亂的嵌入式設備所取代。

英特爾顯然明白這個道理,其強大但耗電的通用CPU戰略已完全不適用了,走嵌入式市場公認的SoC道路成為必然。比如在近日舉辦的英特爾IDF上,英特爾的“瘦身”策略非常清晰:針對不同的市場會有不同的SoC。比如針對手機和MID市場有Moorestown、針對TV和機頂盒等消費電子市場有

CE4100、針對車載/IP電話/網關市場有TunnelCreek,未來還會開發針對其他嵌入式市場的SoC。目的則是推出適用不用應用環境的晶片。

可以預見,2010年全球晶片領域必將發生顛覆性的事件,或為巨頭間的兼併整合,或為新介入者的攻城掠寨,英特爾、AMD、英飛淩、德州儀器、意法半導體、飛思卡爾、三星、東芝、聯發科、高通等全球排名靠前的晶片半導體廠商,面對消費電子終端不斷衍生變化的環境,以及無處不在的互聯時代的到來,必然會發生一場“地震”。
{{{
在 [學習筆記本] 的文章中可直接寫入 HTML 網頁, 本文範例使用 &lt;embed&gt; 顯示外部網站中的 Flash 檔, 內容如下

<html>
<body>  
<div class='widget-content'>
<embed quality="high" align="right" type="application/octet-stream" height="100%" src="http://imgfree.21cn.com/free/flash/17.swf" style="LEFT: 0px; WIDTH: 100%;  HEIGHT: 100%" width="100%" wmode="transparent"></embed>
</div>
</body>
</html>
}}}
__{{item1{文章建立與 Wiki 語法}}}__
1. 點選工具列中的 [''新增文章''] 按鈕, 開始編輯文章

2. 輸入以下文字, 輸入完成後, 請點選 [''完成''] 按鈕
{{{
我的第一篇文章
|Item1|Item2|
}}}
3. 結果如下 : 

我的第一篇文章
|Item1|Item2|

4. 點選工具列中的 [''儲存變更''] 按鈕, 儲存新增文章

''[注意]'' 切勿點選瀏覽器 (IE, Firefox,..) 的 [檔案][另存新檔] 按鈕, 儲存整個網頁. 完整 Wiki 語法請參考 [[Tiddlywiki 練功坊|http://tiddlywiki.tbala.net]]

__{{item1{文章的刪除}}}__
1. 點選欲刪除的文章

2. 點選 [編輯] 按鈕, 進入編輯模式

3. 點選 [刪除] 按鈕, 然後點選 [確定] 按鈕, 進行刪除

<<toBalaNotes "wiki">>


///%wiki
//%/
{{item1{Google Chromium 專案}}}
官方網站 : http://www.chromium.org/

The ''Chromium projects'' include ''Chromium'' and ''Chromium OS'', the open-source projects behind the Google Chrome  browser and Google Chrome OS, respectively. This site houses the documentation and code related to the Chromium projects and is intended for developers interested in learning about and contributing to the open-source projects.

{{item1{Chromium (專為設計 Chrome 瀏覽器而成立的專案)}}}
Chromium is an open-source browser project that aims to build a safer, faster, and more stable way for all Internet users to experience the web. This site contains design documents, architecture overviews, testing information, and more to help you learn to build and work with the Chromium source code.

''[註]'' 「Chromium」是個開放原始碼的瀏覽器計畫,而「Google Chrome 瀏覽器」則是依據此計畫發展而來的

{{item1{Chromium OS}}}
Chromium OS is an open-source project that aims to provide a fast, simple, and more secure computing experience for people who spend most of their time on the web.  Learn more about the project goals, obtain the latest build, and learn how you can get involved, submit code, and file bugs.

''Chromium OS Software Architecture Overview''
本文網址 : http://www.chromium.org/chromium-os/chromiumos-design-docs/software-architecture

* The Chromium-based browser and the window manager
* System-level software and user-land services: the kernel, drivers, connection manager, and so on
* Firmware 

[img[img/ChromiumOSOverview.png]]

<<toBalaNotes "1">>

///%1
//%/
{{item1{mokaFive LivePCs}}}
mokaFive LivePCs contain everything needed to run a virtual computer — an operating system and a set of applications. You can use LivePCs on your desktop, or you can take them with you on a portable USB drive. You can create and share your own LivePCs, or use the public LivePCs created by others in our LivePC Library™.

官方網站 : http://www.mokafive.com
<<toBalaNotes "moka5">>

///%moka5
//%/
''參考文章''
1. Running a XubunTOS Virtual Machine Image in VMware Player
http://docs.tinyos.net/index.php/Running_a_XubunTOS_Virtual_Machine_Image_in_VMware_Player

下載 XubunTOS : http://sing.stanford.edu/tinyos/dists/xubuntos-2.1-vm.tar.gz

{{item1{實作步驟}}}
1. 解壓縮 xubuntos-2.1-vm.tar.gz
2. 啟動 VMware Workstation 
3. 開啟 Xubuntos 2.1 虛擬主機
4. 登入系統

帳號 : xubuntos
密碼 : tinyos. 

5. 啟動終端機, 輸入以下命令 :
[img[img/Xubuntos21.png]]

<<toBalaNotes "xubuntos">>





///%xubuntos
//%/
The following macro call exports all tiddlers to a text file "c:/~MyTiddlyWikiExport.txt", using a customized format.
{{{
<<forEachTiddler
 script 'function getSortedTagsText(tiddler) {var tags = tiddler.tags; if (!tags) return ""; tags.sort(); var result = ""; for (var i = 0; i < tags.length;i++) {result += tags[i]+ " ";} return result;} function writeTiddler(tiddler) {return "==== "+tiddler.title+"=========================\nTags: "+ getSortedTagsText(tiddler)+"\nModified: "+tiddler.modified.convertToYYYYMMDDHHMM()+"\nModifier: "+tiddler.modifier+"\n--------------------------------------------------\n"+tiddler.text+"\n--------------------------------------------------\n(End of "+tiddler.title+")\n\n\n\n"}'
 write 
 'writeTiddler(tiddler)' 
 toFile 'file:///c:/MyTiddlyWikiExport.txt' withLineSeparator '\r\n'
>>
}}}
For better readablility here the script text in a nicer layout:
{{{
function getSortedTagsText(tiddler) {
 var tags = tiddler.tags; 
 if (!tags) 
 return ""; 
 tags.sort(); 
 var result = ""; 
 for (var i = 0; i < tags.length;i++) {
 result += tags[i]+ " ";
 } 
 return result;
} 

function writeTiddler(tiddler) {
 return "==== "+tiddler.title+"=========================\n"+
 "Tags: "+ getSortedTagsText(tiddler)+"\n"+
 "Modified: "+tiddler.modified.convertToYYYYMMDDHHMM()+"\n"+
 "Modifier: "+tiddler.modifier+"\n"+
 "--------------------------------------------------\n"+
 tiddler.text+"\n"+
 "--------------------------------------------------\n"
 "(End of "+tiddler.title+")\n\n\n\n"
}
}}}

<<forEachTiddler
 script 'function getSortedTagsText(tiddler) {var tags = tiddler.tags; if (!tags) return ""; tags.sort(); var result = ""; for (var i = 0; i < tags.length;i++) {result += tags[i]+ " ";} return result;} function writeTiddler(tiddler) {return "==== "+tiddler.title+"=========================\nTags: "+ getSortedTagsText(tiddler)+"\nModified: "+tiddler.modified.convertToYYYYMMDDHHMM()+"\nModifier: "+tiddler.modifier+"\n--------------------------------------------------\n"+tiddler.text+"\n--------------------------------------------------\n(End of "+tiddler.title+")\n\n\n\n"}'
 write 
 'writeTiddler(tiddler)' 
 toFile 'file:///c:/MyTiddlyWikiExport.txt' withLineSeparator '\r\n'
>>
土芭樂 Live CD ,則將 DSL Live CD 加以進化,使之蛻變,並提供:
1、高安全性作業系統(不怕中毒)、免安裝防毒軟體
2、作業系統無痛升級(只需換光碟片)
3、隨拿即用 Web 2.0 網站包(不需安裝)- Joomla、XOOPS、Discuz、MediaWiki
4、網站備份與移機,快速簡便(一行 tar 指令即可搞定,不需安裝備份軟體)

土芭樂 Live CD 網址 :  http://tbala.net/joomla/
DSL Live CD 網址 : http://www.damnsmalllinux.org/ (2008 ~ 2010 歇息中)
Damn Small Linux: Still Damn Fun (DSL 重要文章) : http://www.osnews.com/story/24936/Damn_Small_Linux_Still_Damn_Fun
<<toBalaNotes "tblivecd">>



///%tblivecd
//%/
<<forEachTiddler 
 where
   'tiddler.tags.contains("plugin")'
>>
<<forEachTiddler 
 where
 'tiddler.tags.length == 0'
>>
''參考文章''
1. Comparison of command shells
http://en.wikipedia.org/wiki/Comparison_of_computer_shells

{{item1{什麼是 Shell ?}}}
''Shell 是一種具備特殊功能的程式,它是介於 使用者 和 UNIX/Linux 作業系統之核心程式 (kernel) 間的一個文字介面''。為什麼我們說 shell 是一種介於 系統核心程式 與 使用者 間的仲介者呢?讀過作業系統概論的讀者們都知道作業系統是一個系統資源的管理者與分配者,當您有需求時,您得向系統提出;從作業系統的角度來看,它也必須防止使用者因為錯誤的操作而造成系統的傷害?眾所周知,對電腦下命令得透過 命令(command) 或是 程式 (program);程式有編譯器 (compiler) 將程式轉為二進位碼,可是命令呢?其實 shell 也是一支程式,它由輸入設備讀取命令,再將其轉為電腦可以瞭解的機械碼,然後執行它。

各種作業系統都有它自己的 shell,以 DOS 為例,它的 shell 就是 command.com 檔案。如同 DOS 下有 NDOS,4DOS,DRDOS 等不同的命令解譯程式可以取代標準的 command.com ,UNIX 下除了 Bourne shell(/bin/sh) 外還有 C shell(/bin/csh)、Korn shell(/bin/ksh)、Bourne again shell(/bin/bash)、Tenex C shell(tcsh) … 等其他的 shell。UNIX/Linux 將 shell 獨立於核心程式之外,使得它就如同一般的應用程式,可以在不影響作業系統本身的情況下進行修改、更新版本或是添加新的功能。

{{item1{Shell 的啟動}}}
在系統起動的時候,核心程式會被載入記憶體,負責管理系統的工作,直到系統關閉為止。它建立並控制著處理程式,管理記憶體、檔案系統、通訊等等。而其他的程式,包括 shell 程式,都存放在磁片中。核心程式將它們載入記憶體,執行它們,並且在它們中止後清理系統。Shell 是一個公用程式,它在您登入時起動。藉由解譯使用者輸入的命令(由命令列或命令檔案),Shell 提供使用者和核心程式產生交談的功能。

當您登入 (login) 時,一個交談式的 shell 會跟著起動,並提示您輸入命令。在您鍵入一個命令後,接著就是 shell 的工作了,它會進行:

''1. 命令列語法分析''

''2. 處理萬用字元(wildcards)、轉向(redirection)、管線(pipes) 與 工作控制(job control)''

''3. 搜尋並執行命令''

當您剛開始學 UNIX/Linux 系統時,您大部份的時間會花在於 提示符號(prompt) 下執行命令。

如果您經常會輸入一組相同形式的命令,您可能會想要自動執行那些工作。如此,您可以將一些命令放入一個檔案(稱為命令檔案,script),然後執行該檔案。一個shell 命令檔案很像是 DOS 下的批次檔案(如 Autoexec.bat):它把一連串的 UNIX 命令存入一個檔案,然後執行該檔案。較成熟的命令檔案還支持若干現代程式語言的控制結構,譬如說能做條件判斷、迴圈、檔案測試、傳送參數等。要寫著寫命令檔案,不僅要學習程式設計的結構和技巧,而且對 UNIX/Linux 公用程式及如何運作需有深入的瞭解。有些公用程式的功能非常強大(例如 grep、sed 和awk),它們常被用於命令檔案來操控命令輸出和檔案。在您對那些工具和程式設計結構變得熟悉之後,您就可以開始寫命令檔案。當由命令檔案執行命令時,此刻,您就已經把 shell 當做程式語言使用了。

{{item1{細說 Shell 的生平}}}
第一個有重要意義的,標準的 UNIX shell 是 V7(AT&T的第七版) UNIX,在1979 年底被提出,且以它的創造者 Stephen Bourne 來命名。Bourne shell 是以 Algol 這種語言為基礎來設計,主要被用來做自動化系統管理工作。雖然 Bourne shell 以簡單和速度而受歡迎,但它缺少許多交談性使用的特色,例如歷程、別名和工作控制。

C shell 是在 加州大學柏克來分校 於 70 年代末期發展而成,而以 2BSD UNIX 的部分發行。這個 shell 主要是由 Bill Joy 寫成,提供了一些在標準 Bourne shell 所看不到的額外特色。C shell 是以 C 程式語言 作為基礎,且它被用來當程式語言時,能共用類似的語法。它也提供在交談式運用上的改進,例如命令列歷程、別名和工作控制。因為 C shell 是在大型機器上設計出來,且增加了一些額外功能,所以 C shell 有在小型機器上跑得較慢,即使在大型機器上跟 Bourne shell 比起來也顯得緩慢。

有了 Bourne shell 和 C shell 之後,UNIX 使用者就有了選擇,且爭論那一個 shell 較好。AT&T 的 David Korn 在 80 年代中期發明了 Korn shell,在 1986 年發行且在 1988 年成為正式的部分 SVR4 UNIX。Korn shell 實際上是 Bourne shell 的超集合,且不只可在 UNIX 系統上執行,同時也可在 OS/2、VMS、和 DOS上執行。它提供了和 Bourne shell 向上相容的能力,且增加了許多在 C shell 上受歡迎的特色,更增加了速度和效率。 Korn shell 已歷經許多修正版,要找尋您使用的是那一個版本可在 ksh 提示符號下按 Ctrl-v 鍵。

{{item1{三種主要的 Shell 與其分身}}}
在大部份的 UNIX 系統,三種著名且廣被支援的 shell 是 ''Bourne shell'' (AT&T shell,在 Linux 下是 BASH)、''C shell'' (Berkeley shell,在 Linux 下是 TCSH )和 ''Korn shell'' (Bourne shell的超集合)。這三種 shell 在 交談(interactive) 模式下的表現相當類似,但作為命令檔案語言時,在語法和執行效率上就有些不同了。

''1. Bourne shell'' 是標準的 UNIX shell,以前常被用來做為管理系統之用。大部份的系統管理命令檔案,例如 rc start、stop 與shutdown 都是Bourne shell 的命令檔案,且在單一使用者模式(single user mode)下以 root 簽入時它常被系統管理者使用。Bourne shell 是由 AT&T 發展的,以簡潔、快速著名。 ''Bourne shell 提示符號的預設值是 $''。

''2. C shell'' 是柏克萊大學(Berkeley)所開發的,且加入了一些新特性,如命令列歷程(history)、別名(alias)、內建算術、檔案名完成 (filename completion)、和工作控制(job control)。對於常在交談模式下執行 shell 的使用者而言,他們較喜愛使用 C shell;但對於系統管理者而言,則較偏好以 Bourne shell 來做命令檔案,因為 Bourne shell 命令檔案比 C shell 命令檔案來的簡單及快速。''C shell 提示符號的預設值是 %''。

''3. Korn shell'' 是Bourne shell 的超集合(superset),由 AT&T 的 David Korn 所開發。它增加了一些特色,比 C shell 更為先進。Korn shell 的特色包括了可編輯的歷程、別名、函式、正規運算式萬用字元(regular expression wildcard)、內建算術、工作控制(job control)、共作處理(coprocessing)、和特殊的除錯功能。Bourne shell 幾乎和 Korn shell 完全向上相容(upward compatible),所以在 Bourne shell 下開發的程式仍能在 Korn shell 上執行。''Korn shell 提示符號的預設值也是 $''。在 Linux 系統使用的 Korn shell 叫做 pdksh,它是指 Public Domain Korn Shell。

除了執行效率稍差外,Korn shell 在許多方面都比 Bourne shell 為佳;但是,若將 Korn shell 與 C shell 相比就很困難,因為二者在許多方面都各有所長,就效率和容易使用上看,Korn shell 是優於 C shell,相信許多使用者對於 C Shell 的執行效率都有負面的印象。

在shell 的語法方面,Korn shell 是比較接近一般程式語言,而且它具有副程式的功能及提供較多的資料型態。至於 Bourne shell,它所擁有的資料型態是三種 shell 中最少的,僅提供字串變數和布林型態。在整體考量下 Korn shell 是三者中表現最佳者,其次為 C shell,最後才是 Bourne shell,但是在實際使用中仍有其他應列入考慮的因素,如速度是最重要的選擇時,很可能應該採用 Bourne shell,因它是最基本的 shell,執行的速度最快。

{{item1{tcsh}}}
tcsh 是近幾年崛起的一個免費軟體(Linux 下的C shell 其實就是使用 tcsh)執行,它雖然不是 UNIX 的標準配備,但是從許多地方您都可以下載到它。如果您是 C shell 的擁護者,筆者建議不妨試試 tcsh,因為您至少可以將它當作是 C shell 來使用。如果您願意花點時間學習,您還可以享受許多它新增的優越功能,例如:
{{{
1. tcsh 提供了一個命令列(command line)編輯程式。

2. 提供了命令列補全功能。

3. 提供了拼字更正功能。它能夠自動檢測並且更正在命令列拼錯的命令或是單字。

4. 危險命令偵測並提醒的功能,避免您一個不小心執行了rm* 這種殺傷力極大的命令。

5. 提供常用命令的快捷方式(shortcut)。
}}}

{{item1{bash}}}
bash 對 Bourne shell 是向下相容(backward compatible),並融入許多 C shell 與 Korn shell 的功能。這些功能其實 C shell(當然也包括了tcsh)都有,只是過去 Bourne shell 都未支持。以下筆者將介紹 bash 六點重要的改進(詳細的使用說明筆者會在以後的章節介紹):

1. 工作控制(job contorl)。bash 支援了關於工作的訊號與指令,本章稍後會提及。

2. 別名功能(aliases)。alias 命令是用來為一個命令建立另一個名稱,它的運作就像一個宏,展開成為它所代表的命令。別名並不會替代掉命令的名稱,它只是賦予那個命令另一個名字。

3. 命令歷程(command history)。BASH shell 加入了 C shell 所提供的命令歷程功能,它以 history 工具程式記錄了最近您執行過的命令。命令是由 1 開始編號,預設值為 500。history 工具程式是一種短期記憶,記錄您最近所執行的命令。要看看這些命令,您可以在命令列鍵入 history,如此將會顯示最近執行過之命令的清單,並在前方加上編號。

這些命令在技術上每個都稱為一個事件。事件描述的是一個已經採取的行動(已經被執行的命令)。事件是依照執行的順序而編號,越近的事件其編號碼越大,這些事件都是以它的編號或命令的開頭字元來辨認的。history 工具程式讓您參照一個先前發生過的事件,將它放在命令列上並允許您執行它。最簡單的方法是用上下鍵一次放一個歷程事件在您的命令列上;您並不需要先用 history 顯示清單。按一次向上鍵會將最後一個歷程事件放在您的命令列上,再按一次會放入下一個歷程事件。按向下鍵則會將前一個事件放在命令列上。

4. 命令列編輯程式。BASH shell 命令列編輯能力是內建的,讓您輕鬆地在執行之前修改您輸入的命令。若是您在輸入命令時拼錯了字,您不需重新輸入整個命令,只需在執行命令之前使用編輯功能糾正錯誤即可。這尤其適合於使用冗長的路徑名稱當作參數的命令時。命令列編輯作業是 Emacs 編輯命令的一部份。您可以用 Ctrl-F 或向右鍵往前移一個字元,Ctrl-b 或向左鍵往回移一個字元。Ctrl-d 或DEL 鍵會刪除游標目前所在處的字元。要增加文字的話,您只需要將游標移到您要插入文字的地方並鍵入新字元即可。無論何時,您都可以按 ENTER 鍵執行命令。

5. 允許使用者自訂按鍵。

6. 提供更豐富的變數型態、命令與控制結構至 shell 中。

bash 與 tcsh 一樣可以從許多網站上免費下載,它們的性質也十分類似,都是整合其前一代的產品然後增添新的功能,這些新增的功能主要都著重在強化 shell 的程式設計能力以及讓使用者能夠自行定義自己偏好的作業環境。除了上述的五種 shell 之外,zsh 也是一個廣為 UNIX 程式設計人員與進階使用者所採用的 shell,zsh 基本上也是 Bourne shell 功能的擴充。

<<toBalaNotes "shell">>

///%shell
//%/
※本文內容取自台南市長安國小校長/陳聖謨的『小學生的學習檔案』一文
來源網站網址:http://sparc2.nhltc.edu.tw/~publish/31homepage/17.htm

傳統的紙筆測驗雖然具有簡便速效的優點,然而許多教育人員也大多相信測驗分數並不能代表學生真正的學習表現,也無法瞭解學生在學習過程中的進步情形。例如最典型的標準化成就測驗,就招致了:不能激勵學生學習、預測學生的學習發展效果不佳、窄化了所學的範圍、僅能評定表面的知識等等批評。

因此在九十年代之後,真實性評量 (authentic assessment) 與實作性評量 (performance assessment) 的理念相繼崛起,其中最受到矚目的要算是以檔案形式來顯現學生的學習表現,因為檔案可以激發學生主動學習的動機,並展現學生在各方面學習的進步情形,在美國,使用學生的學習檔案,已成為教學與評鑑的重要趨勢。

學生所建構的學習檔案是指學生在某一期間當中,各種學習的代表作品或其所展現的能力,故檔案是學生在某個領域的學習過程與學習成就所彙編選錄而成的專輯。其內容包含了學生的寫作品,研究報告,閱讀過書目表,口說閱讀的錄音帶,學生的自我評鑑,檢核表;插畫,手工作品代表,平時測驗成績,教師平時觀察評語,父母評語,閱讀心得,對檔案內容的反省評論及檔案內容的次序一覽表等等。從檔案內容,可以看出學生的努力、進步與成就的情形。

使用學習檔案,可結合學生在學習過程的學習記錄與成果的展現,等於兼具了教學與評鑑的效果。

    * 就教師而言,教師可透過學生學習檔案的檢閱,可以全面瞭解學生的學習狀況,並作為個別學習輔導、親師溝通或學年成績通知之用。
    * 就學生而言,可使學生的建構檔案的過程當中,自我監控、自我激勵、交互切磋,有益於其良好學習態度的養成,並獲得有效的學習策略。

雖然檔案的建立需要特別的努力與時間,事實上,其整體效益還是相當值得的。「凡學過必留下痕跡」。隨著多元評量運動的興起與學校本位經營的趨勢下,在學校推展以檔案的方式作為評量方法,或建立全校性學生學習檔案的措施,相信對學生學習表現的評量將更為具體,師生互動也將更為密切直接。

這種具有合作參與,教學並重,過程結果兼具的學習與評量方式,相信將會是教育改革浪潮中的相當具體的實踐行動。


!相關網站
1. 大安高工 - 學習檔案製作網站 : http://210.70.131.3/efiles/main.asp?item=3
2. 北一女中社區化資訊網站 : http://203.64.52.1/~community/92/learnfile.html
有鑒於無線通訊及微機電等技術的漸趨成熟,無線網路的發展,除了朝向高頻寬的應用外,人類生活環境中也將逐漸佈置大量、微小、便宜而低耗電的計算及通訊裝置,以便享受更即時及智慧型之服務,資策會網路多媒體研究所近年來即積極致力於環境感知電腦技術(Context Aware Computing)以及無所不在寬頻網路(Ubiquitous Broadband Networks)的研究,特別是在開發無線感測器網路(Wireless Sensor Network)平台的開發與應用,已經有豐富的成果,將進一步協助業界進行各項產品之開發發。

  隸屬網多所的先進行動技術中心團隊更於日前,在德國萊因(TUV Rheinland)的協助之下,正式通過ZigBee Compliant Platform (ZCP)認證測試,使得資策會成為台灣及全亞洲第一家獲得此殊榮的組織。除了ZCP之外,資策會團隊也於今年7月12日,在日本橫濱參加ZigBee聯盟主辦的相容性測試大會(ZigFest),順利與多家國際大廠完成互通性測試,兩項測試與認證的結果,更代表資策會業已成為我國ZigBee技術上競逐國際舞台的新標竿。

  ZigBee無線傳輸技術的特性,特別適合傳遞少量資訊,例如控制(Control) 或是事件(Events)的資料傳遞應用,在諸多領域可作應用,例如在工業自動化中,設備控制訊號傳遞以及儀器資料收集,家庭監控如空調系統的溫度控制器、燈光、窗簾的自動控制與火警等各類安全偵測器的無線傳輸,此外,老年人與行動不便者的緊急呼叫器或是各類生理監測資料收集,或是電視與音響的萬用遙控器,無線鍵盤、滑鼠、搖桿等週邊控制,應用市場可以說是非常的廣泛,因此ZigBee聯盟預計ZigBee產品市場到2007年將增至13億美元。

  根據ZigBee聯盟規定,所有ZigBee產品,包含晶片(IEEE 802.15.4 PHY與MAC)、通訊協定(ZigBee Protocol),以及終端產品(例如ZigBee滑鼠),都需要通過認證與互通測試的要求,也就是說業者要發展ZigBee終端產品,一定要取得 ZCP認證,目前全球只有TUV及NTS(National Technical Systems)這兩家實驗室為ZigBee聯盟所指定的完整測試服務授權廠商。因此,資策會率先投入ZigBee軟體技術開發,並獲得國際聯盟認證的肯定,除了可以提供國內業者在ZigBee通訊協定以及各項相關產品開發的協助之外,在產品的認證與測試階段,也能夠給予相當多的協助,大大縮短業者開發產品的時間,降低產品研發的成本與快速提升業者競爭力。

  由於ZigBee規格與測試標準的變化快速,業界在研發相關產品前必先瞭解最新資訊,以掌握未來發展的方向,資策會擬將ZigBee的開發成果,以及豐富的測試經驗,與國內相關業者分享,並提供完整的驗證與測試解決方案建議,協助業者與國際技術接軌,一同為台灣的無線感測網路應用產業而努力。
 
''關於 ZigBee Compliant Platform (ZCP)''
 
  ZigBee聯盟一共規定三種層級的認證規格。第一層級是IEEE 802.15.4 實體層(PHY)與媒體存取層(MAC)認證,主要與ZigBee RF晶片功能有關;第二個層級為ZCP,與ZigBee RF晶片、微處理器以及ZigBee通訊協定有關,主要測試標地為ZigBee通訊協定,包含其網路層、應用層與安全層等功能,但要測試ZCP的前提是所使用的ZigBee RF晶片組必須先通過IEEE 802.15.4 實體層(PHY)與媒體存取層(MAC)認證;第三個層級是ZigBee Logo 認證,主要測試終端產品應用程式(Profile),但要測試ZigBee Logo 認證的前提是必須要使用通過ZCP的軟硬體平台。其嚴謹的認證過程就是為了確保將來各種ZigBee產品的能夠順利達到互通性的要求。
 
''關於 ZigBee''

ZigBee 是一種短距離無線通訊標準,由ZigBee Alliance所主導的ZigBee標準,則定義了網路層(Network Layer)、安全層(Security Layer)、應用層(Application Layer)以及各種應用產品的Profile,其最大優勢在於低成本、低耗電量及應用範圍廣泛,ZigBee一詞來源于蜜蜂(Bee),蜜蜂看似隨意地在跳字形舞,但實際上確將有花和蜂蜜的地方正確地傳達給其他蜜蜂,ZigBee正是採用了這樣的通訊方式,特別是在所謂的無線感測網路(Wireless Sensor Network)的應用裡,例如建築物的能源監控、氣候及地震監督、生態環境追蹤、庫存管理、居家照護、物流車隊調配等,應用層面非常廣泛。強調以低耗電、低成本切入產業自動化控制、能源監控、機電控制、照明系統管控、家庭安全和RF遙控等領域。
 
關於 http://zigbee.iii.org.tw
 
此網站為資策會網多所製作並提供ZigBee相關技術討論與訊息分享的園地,藉以作為網多所與台灣業學界在ZigBee技術的交流平台。
官方網址 : http://code.google.com/intl/en/android/

{{item1{Android Architecture}}}
本文網址 : http://developer.android.com/guide/basics/what-is-android.html

The following diagram shows the major components of the Android operating system. Each section is described in more detail below.

[img[img/android-system-architecture.jpg]]

<<toBalaNotes "1">>

///%1
//%/
<<list shadowed>>
<<forEachTiddler
    where
       'tiddler.tags.contains("文章整理")'

    sortBy
       'tiddler.title.toUpperCase()'

    write '" [["+tiddler.title+" ]] \"view ["+tiddler.title+"]\" [["+tiddler.title+"]] "'

        begin '"<<tabs txtMyAutoTab "'

        end '">"+">"'

        none '"//No tiddler tagged with \"文章整理\"//"'
>>
''參考文章''
1. Linux 虛擬機器-QEMU 初體驗
http://daydreamer.idv.tw/rewrite.php/read-19.html

''List of Linux Live CDs''
http://www.livecdlist.com/

{{item1{QEMU Machine Emulator}}}
''QEMU 官方網站: http://wiki.qemu.org/Index.html''

QEMU 是一套由 Fabrice Bellard 所編寫的 模擬作業系統 的 自由軟體。它與 Bochs﹐PearPC 近似,但其具有某些後兩者所不具備的特性,如高速度及跨平臺的特性。經由 kqemu 這個 非自由 的加速器,QEMU 能模擬至接近真實電腦的速度。

QEMU有兩種主要運作模式:
{{{
- User mode 模擬模式,亦即是使用者模式。QEMU 能啟動那些為不同中央處理器編譯的 Linux 程序。而 Wine 及 Dosemu 是其主要目標。 
- System mode 模擬模式,亦即是系統模式。QEMU 能模擬整個電腦系統,包括中央處理器及其他週邊設備。它使得為系統 源代碼 進行測試及除錯工作變得容易。它亦能用來在一部主機上虛擬數部不同虛擬電腦。 
}}}
QEMU 的主體部份是在 LGPL 下發布的,而其系統模式模擬則是在GPL 下發布;而 kqemu 這個加速器則是在免費但閉源的條件下發布的。使用 kqemu 可使 QEMU 能模擬至接近實機速度,但其在虛擬的操作系統是視窗 98 或以下的情況下是無用的。

<<toBalaNotes "qemu">>
{{op1{QEMU's 實際使用的例子}}}
以下的指令可以建立一個 500MB 大小的 “qcow” 格式的硬碟映像檔。
{{{
C:\>qemu-img  create -f qcow c.img 500M 
}}}
而以下的指令會使虛擬機器在128MB記憶體,使用 c.img 這個用以上介紹的指令所建立的硬碟映像檔及以linux.iso為光碟映像檔的情況下運行。注意,如果閣下使用實體光碟機,請將  -cdrom linux.iso 這個參數變為 -cdrom /dev/cdrom 或您所用的光碟機
{{{
qemu -hda c.img  -cdrom linux.iso  -boot d  -m 128  -enable-audio  -localtime 
}}}
如果閣下想預設使用全螢幕啟動子作業系統,可作以上指令後再加上 “-full-screen” 這個參數,如想在運行時離開全螢幕,請使用組合鍵 Ctrl-Alt-F 便可。

{{op1{指定 iso 檔給QEMU, 並指定以光碟開機}}}
{{{
qemu -L . -m 256 -enable-audio -localtime -hda hd.img -cdrom d:DLsarge-i386-businesscard.iso -boot d

-L 指定運行啟始目錄(BIOS位置)

-m 指定記憶體大小

-hda 指定 C 磁碟機使用剛剛建立好的 hd.img

-cdrom 指定光碟機內放的 CD 是 toBala 的可開機 ISO 檔

-boot 指定電腦的開機方式, a=磁片開機, c=硬碟開機, d=光碟開機
}}}

{{item1{啟動 Live CD}}}
直接將 ISO 檔案載入執行 (Live CD), 沒設定 -L 參數,將無法載入 BIOS 而得到 qemu: could not load PC bios '/c/Program Files/Qemu/bios.bin' 的錯誤訊息
{{{
qemu -cdrom PUD-0.4.6.6.iso -m 256 -L ./
}}}

''將 qemu 執行的視窗隱藏''

可以使用 CMDOW 來隱藏命令提示視窗,將 cmdow 指令寫在 qemu 執行前即可,例
{{{
cd \qemu
cmdow /run /hid qemu -kernel-kqemu -hda freebsd.img  -m 128 -L ./
}}}
如此就會只剩下虛擬系統的視窗畫面。

{{item1{啟動 toBala Live CD}}}
1. 在 linux2008\embdLinux 目錄中, 快點二下 dsl-tobala.bat

[img[img/linux/livecd01.png]]

2. 上圖中直接按 Enter, 登入後如下圖 : 

<html><img src="img/linux/livecd02.png" style="width:90%;height: 90%;"/></html>

<<toBalaNotes "livecd">>

{{op1{練習 : 使用 VMware Workstation 製作一個啟動 ubuntu-9.04-desktop-i386.iso 的虛擬主機}}}

<<toBalaSWF2 "movie/ubuntu9.04/ubuntuLiveCD.swf" "820" "610" "教學影片 - 啟動 ubuntu-9.04 Live CD">>

{{op1{dsl-tobala.bat 內容}}}
{{{
REM Start qemu on windows.
@ECHO OFF

cmdow /run /hid qemu0.10.5\qemu.exe -L qemu0.10.5\ -net nic -net user -no-kqemu -m 256 -localtime -hda .\tobala.img -cdrom .\LiveCD\DSL3-tBALA01-GCC.iso -boot d
CLS
EXIT

rem -L 指定運行啟始目錄(BIOS位置)
rem -m 指定記憶體大小
rem -hda 指定 C 磁碟機使用剛剛建立好的 hd.img
rem -cdrom 指定光碟機內放的 CD 是 toBala 的可開機 ISO 檔
rem -boot 指定電腦的開機方式, a=磁片開機, c=硬碟開機, d=光碟開機
}}}

///%livecd
//%/

///%qemu
//%/
今天(4/22)是世界地球日,資策會應景舉辦了智慧綠建築研討會,首度實地展示導入ZigBee感測網路的建築節能技術。

資策會將這套技術稱為「智慧建築外層(Smart Skin)整合性解決方案」,是以ZigBee網路為基礎,以無線感測裝置偵測室內、外環境改變,並自動進行各種節能控制。此技術已技轉相關業者,並導入於北市仁愛路上的富邦福安紀念館辦公大樓,標榜與同級綠建築相比可省下12%電費。

該建築室內、外總共設置約100個感測器,以ZigBee無線網路串連,提供包括光線、溫度、溼度、二氧化碳(CO2)、風速等氣候資訊,並在頂樓設有小型氣象資訊站,提供後台進行各種節能控制。例如:當偵測到室內二氧化碳濃度過高,系統會以室外氣候條件來判斷是否開窗通風,並以風塔效應來為整棟大樓降溫。

另外,照明感測系統是偵測室外光線,若非直射光線並有足夠照明效果,就會引進自然採光,並與室內燈具自動搭配;若日曬嚴重時,會自動啟動遮陽窗帘,以節約空調用電。針對溼度控制,也設有自動水霧機。

ZigBee技術是所有這些環境感測器傳輸資訊的基礎。其為無線傳輸技術的一種,符合IEEE 802.15.4標準,工作頻率為868MHz、915MHz或2.4GHz。有低成本、低耗電、雙向傳輸、感測網路功能的特色,特別適合在小範圍內配置大量結點。

資策會網多所組長吳建明表示,該所推動ZigBee感測網路技術將近三年,約一年前開始建置的許多實用化方案,最近開始陸續啟用,包括故宮、經濟部會議室、民生社區、台北港等。  
BlackBerry 官網 : http://na.blackberry.com

{{item1{BlackBerry OS}}}
BlackBerry OS is a proprietary mobile operating system, developed by Research In Motion for its BlackBerry line of smartphone handheld devices. The operating system provides multitasking and supports specialized input devices that have been adopted by RIM for use in its handhelds, particularly the trackwheel, trackball, and most recently, the trackpad and touchscreen.

The BlackBerry platform is perhaps best known for its native support for corporate email, through MIDP 1.0 and, more recently, a subset of MIDP 2.0, which allows complete wireless activation and synchronization with Microsoft Exchange, Lotus Domino, or Novell GroupWise email, calendar, tasks, notes, and contacts, when used in conjunction with BlackBerry Enterprise Server. The operating system also supports WAP 1.2.

Updates to the operating system may be automatically available from wireless carriers that support the BlackBerry OTASL (over the air software loading) service.

Third-party developers can write software using the available BlackBerry API (application programming interface) classes, although applications that make use of certain functionality must be digitally signed.

<<toBalaNotes "1">>



///%1
//%/

在文章中使用 [巨集] 可獲得更多資訊運作功能, 例如: 以標籤來排序文章, 將過濾過文章寫入外部文字檔

巨集使用格式如下 : 
{{{
<<macroName [parameters]>>
}}}

<<toBalaNotes "macro">>


///%macro
//%/
|!巨集名稱|!說明|!語法|
|allTags|List all Tags in a Tiddler|{{{<}}}{{{<allTags>>}}}|
|closeAll|Close all displayed Tiddlers|{{{<}}}{{{<closeAll>>}}}|
|list all|List all Tiddlers in a Tiddler|{{{<}}}{{{<list all>>}}}|
|list missing|List all Missing Tiddlers in a Tiddler|{{{<}}}{{{<list missing>>}}}|
|list orphans|List all orphaned Tiddlers in a Tiddler|{{{<}}}{{{<list orphans>>}}}|
|newJournal|Create new date & Time stamped Tiddler|{{{<}}}{{{<newJournal>>}}}|
|newTiddler|Create new Tiddler|{{{<}}}{{{<newTiddler>>}}}|
|permaview|URL link for all open Tiddlers|{{{<}}}{{{<permaview>>}}}|
|saveChanges |Save all ~TiddlyWiki changes|{{{<}}}{{{<saveChanges>>}}}|
|search|Display a Search box|{{{<}}}{{{<search>>}}}|
|slider|Display a Slider|{{{<}}}{{{<slider sliderID sliderTiddler sliderLabel>>}}}|
|tabs|Display Tabbed content|{{{<}}}{{{<tabs indentifier tabLabel tabName Tiddler>>}}}|
|tag|Display a Tag ~PopUp|{{{<}}}{{{<tag tagName>>}}}|
|tiddler|Display inline contents of a Tiddler|{{{<}}}{{{<tiddler Tiddler>>}}}|
|timeline|Display Timeline in a Tiddler|{{{<}}}{{{<timeline>>}}}|
|today|Dusplay Today's Date|{{{<}}}{{{<today>>}}}|
|version|Display ~TiddlyWiki's version|{{{<}}}{{{<version>>}}}|

<<toBalaNotes "buildin">>


///%buildin
//%/
{{item1{newTiddler 巨集使用格式說明}}}
{{{

<<newTiddler  label:"新增網頁"  tag:"HTML"   template:"HTMLEditTemplate"  title:"新增網頁">>

label:"新增網頁"  --->  按鈕名稱
tag:"HTML"  ---->  新文章的標籤
template:"HTMLEditTemplate"  ---->  新文章建立使用的 Template
title:"新增網頁"  ----> 新文章的 Title
}}}

{{op1{範例}}}
新增ㄧ篇標題為 Ajax 的文章, 使用格式如下 :
{{{
<<newTiddler label:"新增 Ajax 文章" title:"Ajax" tag:"Ajax" text:"/*{{{*/  /*}}}*/">>
}}}

__{{op1{實作範例}}}__

<<newTiddler label:"新增 Ajax 文章" title:"Ajax" tag:"Ajax" text:"/*{{{*/  /*}}}*/">>
{{{

include 巨集的使用格式說明

載入指定的 TiddlyWiki 網頁, 而不顯示 include 巨集命令 (hide:true)
<<include "tBalaTech-DSL1209.html" hide: true>>

顯示載入TiddlyWiki 網頁中的 Tiddler
<<tiddler '何謂 permaview ?'>>

}}}

!使用說明
{{{
1. 規劃標籤名
2. 根據 "標籤名" 產生 [編輯] 與 [顯示] 的 Template

    例如 : 標籤名為 HTML, 那麼二個 Template 的名稱為 HTMLEditTemplate, HTMLViewTemplate,
              以後只要文章的標籤有 HTML, 便會自動套用這二個 Template

3. 將以下巨集命令加入 ToolBar 文章中

    <<newTiddler  label:"新增網頁"    tag:"HTML"     template:"HTMLEditTemplate"   title:"新增網頁">>
                              ^                ^                      ^                           ^
                         按鈕名稱        新文章的標籤      新文章第一次使用的 Template     新文章的 Title

    * 必須要安裝 TaggedTemplateTweak 這個插件, 才有以上功能

}}}

請點選以下按鈕, 測試 easyEdit 功能

<<newTiddler label:新增網頁 tag:"HTML" template:"HTMLEditTemplate" title:"新增網頁">>


!HTMLEditTemplate
{{{
<div class='toolbar' macro='toolbar +saveTiddler  -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='easyEdit text'></div>
                                      ^
                                 這是重點

<div class='editor' macro='edit tags'></div>
<div class='editorFooter'>
<span macro='message views.editor.tagPrompt'></span>
<span macro='tagChooser'></span>
</div>
}}}

!HTMLViewTemplate
{{{
<div class='toolbar' macro='toolbar closeTiddler closeOthers +easyEdit > fields syncing permalink references jump'></div>
                                                                    ^
                                                                這是重點
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
}}}
''horizontal:''
{{{
* menu #1
** [[item #1-1]]
** [[item #1-2]]
** [[item #1-3]]
* menu #2
** [[item #2-1]]
** [[item #2-2]]
** [[menu #2-3]]
* menu #3
** [[item #2-1]]
** [[item #2-2]]
** [[menu #2-3]]
<<dropMenu>>
}}}
* menu #1
** [[item #1-1]]
** [[item #1-2]]
** [[item #1-3]]
* menu #2
** [[item #2-1]]
** [[item #2-2]]
** [[menu #2-3]]
* menu #3
** [[item #2-1]]
** [[item #2-2]]
** [[menu #2-3]]
<<dropMenu>>

''vertical:''
{{{
* menu #1
** [[item #1-1]]
** [[item #1-2]]
** [[item #1-3]]
* menu #2
** [[item #2-1]]
** [[item #2-2]]
** [[menu #2-3]]
<<dropMenu vertical>>
}}}

* menu #1
** [[item #1-1]]
** [[item #1-2]]
** [[item #1-3]]
* menu #2
** [[item #2-1]]
** [[item #2-2]]
** [[menu #2-3]]
<<dropMenu vertical>>


/% %/
/***
|<html><a name="Top"/></html>''Name:''|PartTiddlerPlugin|
|''Version:''|1.0.9 (2007-07-14)|
|''Source:''|http://tiddlywiki.abego-software.de/#PartTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license]]|
|''CoreVersion:''|2.1.3|
|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|
!Table of Content<html><a name="TOC"/></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Description',null, event)">Description, Syntax</a></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Applications',null, event)">Applications</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('LongTiddler',null, event)">Refering to Paragraphs of a Longer Tiddler</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Citation',null, event)">Citation Index</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('TableCells',null, event)">Creating "multi-line" Table Cells</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Tabs',null, event)">Creating Tabs</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Sliders',null, event)">Using Sliders</a></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Revisions',null, event)">Revision History</a></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Code',null, event)">Code</a></html>
!Description<html><a name="Description"/></html>
With the {{{<part aPartName> ... </part>}}} feature you can structure your tiddler text into separate (named) parts. 
Each part can be referenced as a "normal" tiddler, using the "//tiddlerName//''/''//partName//" syntax (e.g. "About/Features").  E.g. you may create links to the parts (e.g. {{{[[Quotes/BAX95]]}}} or {{{[[Hobbies|AboutMe/Hobbies]]}}}), use it in {{{<<tiddler...>>}}} or {{{<<tabs...>>}}} macros etc.


''Syntax:'' 
|>|''<part'' //partName// [''hidden''] ''>'' //any tiddler content// ''</part>''|
|//partName//|The name of the part. You may reference a part tiddler with the combined tiddler name "//nameOfContainerTidder//''/''//partName//. <<br>>If you use a partName containing spaces you need to quote it (e.g. {{{"Major Overview"}}} or {{{[[Shortcut List]]}}}).|
|''hidden''|When defined the content of the part is not displayed in the container tiddler. But when the part is explicitly referenced (e.g. in a {{{<<tiddler...>>}}} macro or in a link) the part's content is displayed.|
|<html><i>any&nbsp;tiddler&nbsp;content</i></html>|<html>The content of the part.<br>A part can have any content that a "normal" tiddler may have, e.g. you may use all the formattings and macros defined.</html>|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!Applications<html><a name="Applications"/></html>
!!Refering to Paragraphs of a Longer Tiddler<html><a name="LongTiddler"/></html>
Assume you have written a long description in a tiddler and now you want to refer to the content of a certain paragraph in that tiddler (e.g. some definition.) Just wrap the text with a ''part'' block, give it a nice name, create a "pretty link" (like {{{[[Discussion Groups|Introduction/DiscussionGroups]]}}}) and you are done.

Notice this complements the approach to first writing a lot of small tiddlers and combine these tiddlers to one larger tiddler in a second step (e.g. using the {{{<<tiddler...>>}}} macro). Using the ''part'' feature you can first write a "classic" (longer) text that can be read "from top to bottom" and later "reuse" parts of this text for some more "non-linear" reading.

<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!!Citation Index<html><a name="Citation"/></html>
Create a tiddler "Citations" that contains your "citations". 
Wrap every citation with a part and a proper name. 

''Example''
{{{
<part BAX98>Baxter, Ira D. et al: //Clone Detection Using Abstract Syntax Trees.// 
in //Proc. ICSM//, 1998.</part>

<part BEL02>Bellon, Stefan: //Vergleich von Techniken zur Erkennung duplizierten Quellcodes.// 
Thesis, Uni Stuttgart, 2002.</part>

<part DUC99>Ducasse, Stéfane et al: //A Language Independent Approach for Detecting Duplicated Code.// 
in //Proc. ICSM//, 1999.</part>
}}}

You may now "cite" them just by using a pretty link like {{{[[Citations/BAX98]]}}} or even more pretty, like this {{{[[BAX98|Citations/BAX98]]}}}.

<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!!Creating "multi-line" Table Cells<html><a name="TableCells"/></html>
You may have noticed that it is hard to create table cells with "multi-line" content. E.g. if you want to create a bullet list inside a table cell you cannot just write the bullet list
{{{
* Item 1
* Item 2
* Item 3
}}}
into a table cell (i.e. between the | ... | bars) because every bullet item must start in a new line but all cells of a table row must be in one line.

Using the ''part'' feature this problem can be solved. Just create a hidden part that contains the cells content and use a {{{<<tiddler >>}}} macro to include its content in the table's cell.

''Example''
{{{
|!Subject|!Items|
|subject1|<<tiddler ./Cell1>>|
|subject2|<<tiddler ./Cell2>>|

<part Cell1 hidden>
* Item 1
* Item 2
* Item 3
</part>
...
}}}

Notice that inside the {{{<<tiddler ...>>}}} macro you may refer to the "current tiddler" using the ".".

BTW: The same approach can be used to create bullet lists with items that contain more than one line.

<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!!Creating Tabs<html><a name="Tabs"/></html>
The build-in {{{<<tabs ...>>}}} macro requires that you defined an additional tiddler for every tab it displays. When you want to have "nested" tabs you need to define a tiddler for the "main tab" and one for every tab it contains. I.e. the definition of a set of tabs that is visually displayed at one place is distributed across multiple tiddlers.

With the ''part'' feature you can put the complete definition in one tiddler, making it easier to keep an overview and maintain the tab sets.

''Example''
The standard tabs at the sidebar are defined by the following eight tiddlers:
* SideBarTabs
* TabAll
* TabMore
* TabMoreMissing
* TabMoreOrphans
* TabMoreShadowed
* TabTags
* TabTimeline

Instead of these eight tiddlers one could define the following SideBarTabs tiddler that uses the ''part'' feature:
{{{
<<tabs txtMainTab 
    Timeline Timeline SideBarTabs/Timeline 
    All 'All tiddlers' SideBarTabs/All 
    Tags 'All tags' SideBarTabs/Tags 
    More 'More lists' SideBarTabs/More>>
<part Timeline hidden><<timeline>></part>
<part All hidden><<list all>></part>
<part Tags hidden><<allTags>></part>
<part More hidden><<tabs txtMoreTab 
    Missing 'Missing tiddlers' SideBarTabs/Missing 
    Orphans 'Orphaned tiddlers' SideBarTabs/Orphans 
    Shadowed 'Shadowed tiddlers' SideBarTabs/Shadowed>></part>
<part Missing hidden><<list missing>></part>
<part Orphans hidden><<list orphans>></part>
<part Shadowed hidden><<list shadowed>></part>
}}}

Notice that you can easily "overwrite" individual parts in separate tiddlers that have the full name of the part.

E.g. if you don't like the classic timeline tab but only want to see the 100 most recent tiddlers you could create a tiddler "~SideBarTabs/Timeline" with the following content:
{{{
<<forEachTiddler 
		sortBy 'tiddler.modified' descending 
		write '(index < 100) ? "* [["+tiddler.title+"]]\n":""'>>
}}}
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!!Using Sliders<html><a name="Sliders"/></html>
Very similar to the build-in {{{<<tabs ...>>}}} macro (see above) the {{{<<slider ...>>}}} macro requires that you defined an additional tiddler that holds the content "to be slid". You can avoid creating this extra tiddler by using the ''part'' feature

''Example''
In a tiddler "About" we may use the slider to show some details that are documented in the tiddler's "Details" part.
{{{
...
<<slider chkAboutDetails About/Details details "Click here to see more details">>
<part Details hidden>
To give you a better overview ...
</part>
...
}}}

Notice that putting the content of the slider into the slider's tiddler also has an extra benefit: When you decide you need to edit the content of the slider you can just doubleclick the content, the tiddler opens for editing and you can directly start editing the content (in the part section). In the "old" approach you would doubleclick the tiddler, see that the slider is using tiddler X, have to look for the tiddler X and can finally open it for editing. So using the ''part'' approach results in a much short workflow.

<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!Revision history<html><a name="Revisions"/></html>
* v1.0.9 (2007-07-14)
** Bugfix: Error when using the SideBarTabs example and switching between "More" and "Shadow". Thanks to cmari for reporting the issue.
* v1.0.8 (2007-06-16)
** Speeding up display of tiddlers containing multiple pard definitions. Thanks to Paco Rivière for reporting the issue.
** Support "./partName" syntax inside <<tabs ...>> macro
* v1.0.7 (2007-03-07)
** Bugfix: <<tiddler "./partName">> does not always render correctly after a refresh (e.g. like it happens when using the "Include" plugin). Thanks to Morris Gray for reporting the bug.
* v1.0.6 (2006-11-07)
** Bugfix: cannot edit tiddler when UploadPlugin by Bidix is installed. Thanks to José Luis González Castro for reporting the bug.
* v1.0.5 (2006-03-02)
** Bugfix: Example with multi-line table cells does not work in IE6. Thanks to Paulo Soares for reporting the bug.
* v1.0.4 (2006-02-28)
** Bugfix: Shadow tiddlers cannot be edited (in TW 2.0.6). Thanks to Torsten Vanek for reporting the bug.
* v1.0.3 (2006-02-26)
** Adapt code to newly introduced Tiddler.prototype.isReadOnly() function (in TW 2.0.6). Thanks to Paulo Soares for reporting the problem.
* v1.0.2 (2006-02-05)
** Also allow other macros than the "tiddler" macro use the "." in the part reference (to refer to "this" tiddler)
* v1.0.1 (2006-01-27)
** Added Table of Content for plugin documentation. Thanks to RichCarrillo for suggesting.
** Bugfix: newReminder plugin does not work when PartTiddler is installed. Thanks to PauloSoares for reporting.
* v1.0.0 (2006-01-25)
** initial version

使用 toBalaSWF2 巨集, 來撥放指定的 Flash 檔, 命令格式如下 :
{{{
<<toBalaSWF2 "movie/infotree.swf" "820" "610">>
}}}

{{item1{實作範例 : winzip 的安裝}}}

<<toBalaSWF2 "movie/winzip.swf" "820" "610" "winzip 的安裝影片">>

<<toBalaNotes "flash">>


///%flash
//%/
{{item1{可縮放向量圖形 - Scalable Vector Graphics (SVG)}}}

SVG 是基於可擴展標記語言(XML),用於描述二維向量圖形的一種圖形格式。SVG 由 W3C 制定,是一個開放標準。

__{{op1{Inkscape SVG 圖形編輯器}}}__
官方網站 : http://www.inkscape.org/index.php
Inkscape 是一套以自由軟體方式發佈與使用的向量圖形編輯器,該套軟體的開發目標是成為一套強力的繪圖工具軟體,且能完全遵循與支援 XML、SVG、CSS 等開放性的標準格式,此外 Inkscape 同時也是一套跨平臺性的應用程式,針對不同的作業系統它都有能搭配對應執行的版本,如 Windows 版、Mac OS X 版、Linux 版、以及類 UNIX 版等作業系統,不過主要仍是以 Linux 為開發平臺。

Inkscape 開始於 2003 年,最初是向量繪圖編輯器:Sodipodi 的一個分支、分線發展(fork),當時的 Inkscape 尚未具備太多商業版向量編輯器才有的功效特點,不過卻廣泛適合各類的應用。Inkscape 雖支援 SVG、CSS 等標準,然仍尚未支援完全;其中較重要的SVG 濾鏡效果(SVG filter effect)、動畫、SVG 字型等都還未能實現。而自 2006 年起 Inkscape 的發展逐漸積極活躍,如今正不斷加入新的特點與機制功效。

__{{op1{教學影片}}}__
1. Inkscape 下載 <<toBalaSWF2 "movie/downloadinkscape.swf" "820" "610" "影片">>

2. Inkscape 安裝 <<toBalaSWF2 "movie/installinkscape.swf" "820" "610" "影片">>

3. 製作隨身版 Inkscape <<toBalaSWF2 "movie/portableinkscape.swf" "820" "610" "影片">>
&nbsp;&nbsp;&nbsp;&nbsp;這步驟只是將安裝完成的 Inkscape 目錄, 完整複製到隨身裝置 (USB 隨身碟), 然後將 Inkscape 從本機移除

4. 編輯 SVG 檔 <<toBalaSWF2 "movie/createsvg.swf" "820" "610" "影片">>
&nbsp;&nbsp;&nbsp;&nbsp;如何操作 Inkscape, 請參考 [[李銘偉老師 Inkscape 的實例教學|http://163.32.161.9/maylike/teach/inkscape/index.htm]]

5. 在 [學習筆記本] 的文章中顯示 SVG 圖檔 <<toBalaSWF2 "movie/tiddlersvg.swf" "820" "610" "影片">>
&nbsp;&nbsp;&nbsp;&nbsp;利用 Inkscape 產生的 SVG 檔, 請儲存至 toBalaKMKNotepad\img\svg 目錄中, 然後在[學習筆記本] 的文章中, 使用以下的 HTML 標籤來顯示 SVG 檔
{{{
<html>
<object data="img/svg/JavaSecurity.svg" TYPE="image/svg+xml" width="505" height="355" align="center">
  <a href="svg/JavaSecurity.svg">Java security Model</a>
</object>
</html>
}}}

__{{op1{參考網站}}}__
[[運用 Inkscape 所創作出來的線上圖集|http://inkscape.deviantart.com/favourites]]

<<toBalaNotes "svg">>


 

///%svg
//%/

|Jesse James Garrett[img[img/headshot_garrett.jpg]] |<< @@font-size:16pt;color:#00f;line-height:25pt;Ajax 由 HTML、JavaScript™ 技術、DHTML、XMLHttpRequest 物件和 DOM 組成,這一傑出的方法可以將笨拙的 Web 介面轉化成互動性的 Ajax 應用程式@@|
|borderless|k

{{item1{老技術,新技巧}}}

在談到 Ajax 時,實際上涉及到多種技術,要靈活地運用它必須深入瞭解這些不同的技術。好消息是您可能已經非常熟悉其中的大部分技術,更好的是這些技術都很容易學習,並不像完整的程式語言(如 Java 或 Ruby)那樣困難。
	
{{op1{Ajax 的定義}}}

順便說一下,Ajax 是 Asynchronous JavaScript and XML(以及 DHTML 等)的縮寫, 這個縮寫是 Adaptive Path 的 Jesse James Garrett 發明的

下面是 Ajax 應用程式所用到的基本技術:

    * HTML 用於建立 Web 表單並確認應用程式其他部分使用的欄位。
    * JavaScript 程式碼是執行 Ajax 應用程式的核心程式碼,幫助改進與伺服器應用程式的通訊。
    * DHTML 或 Dynamic HTML,用於動態更新表單。我們將使用 div、span 和其他動態 HTML 元素來標記 HTML。
    * 文件物件模型 DOM 用於(透過 JavaScript 程式碼)處理 HTML 結構和(某些情況下)伺服器返回的 XML。
    * XMLHttpRequest 通訊物件, 負責與後端伺服系統交換 XML, JSON, Text 等資料


{{item1{Ajax 程式撰寫與執行}}}
在學習筆記本中, 妳可以使用以下巨集, 來實作 Ajax 程式設計
{{{
<<toBalaAjax "ajax\AjaxCall.htm" "700" "450">>
}}}

__{{op1{參考文章}}}__
點選 [[toBalaAjax - Ajax 程式設計]] 或 [[toBalaAjax - 使用 XMLHTTP 物件]]


{{item1{Ajax Framework}}}
在學習筆記本中, 指定 jslib 目錄儲存 Ajax Framework (MooTools, jQuery, Dojo, Prototype,...)

__{{op1{jQuery}}}__
官方網站 : http://jquery.com/
jQuery 是一個快速又 簡潔的JavaScript程式庫, 簡化了讓你在HTML文件裡面尋找DOM物件, 處理事件, 製作動畫, 和處理Ajax互動的過程 jQuery 是來改變你撰寫 JavaScript 的方式 

參考網站 : [[優秀 jQuery 插件17個|http://ka-yue.com/blog/useful-jquery-plugin]]

__{{op1{MooTools}}}__
官方網站 : http://mootools.net/
MooTools is a compact, modular, Object-Oriented JavaScript framework designed for the intermediate to advanced JavaScript developer. It allows you to write powerful, flexible, and cross-browser code with its elegant, well documented, and coherent API.

__{{op1{Prototype}}}__
官方網站 : http://www.prototypejs.org/
Prototype is a JavaScript Framework that aims to ease development of dynamic web applications. Featuring a unique, easy-to-use toolkit for class-driven development and the nicest Ajax library around, Prototype is quickly becoming the codebase of choice for web application developers everywhere.

__{{op1{Dojo}}}__
官方網站 : http://dojotoolkit.org/
Dojo is an Open Source DHTML toolkit written in JavaScript. It builds on several contributed code bases (nWidgets, Burstlib, f(m)), which is why we refer to it sometimes as a "unified" toolkit. Dojo aims to solve some long-standing historical problems with DHTML which prevented mass adoption of dynamic web application development.

Dojo allows you to easily build dynamic capabilities into web pages and any other environment that supports JavaScript sanely. You can use the components that Dojo provides to make your web sites more usable, responsive, and functional. With Dojo you can build degradable user interfaces more easily, prototype interactive widgets quickly, and animate transitions. You can use the lower-level APIs and compatibility layers from Dojo to write portable JavaScript and simplify complex scripts. Dojo's event system, I/O APIs, and generic language enhancement form the basis of a powerful programming environment. You can use the Dojo build tools to write command-line unit-tests for your JavaScript code. The Dojo build process helps you optimize your JavaScript for deployment by grouping sets of files together and reuse those groups through "profiles".

Dojo does all of these things by layering capabilities onto a very small core which provides the package system and little else. When you write scripts with Dojo, you can include as little or as much of the available APIs as you need to suit your needs. Dojo provides multiple points of entry, interpreter independence, forward looking APIs, and focuses on reducing barriers to adoption.

<<toBalaNotes "ajaxframework">>



///%ajaxframework
//%/
&nbsp;
學習筆記本並沒有內建 J2SE 開發平台, 如要啟用 [學習筆記本] 的 Java 開發功能, 請自行依照以下操作步驟, 安裝 J2SE 開發平台

{{item1{建置 J2SE 開發平台}}}
1. 下載 JDK
&nbsp;&nbsp;&nbsp;&nbsp;請連接至 http://java.sun.com/javase/downloads/?intcmp=1281 下載 JDK

&nbsp;&nbsp;<<toBalaSWF2 "movie/JDK6_U2_Downlaod.swf" "820" "610" "教學影片 - 下載 JDK 1.6 Update 2">>

2. 安裝 JDK
&nbsp;&nbsp;&nbsp;&nbsp;- 執行安裝檔 (jdk-6u2-windows-i586-p.exe)
&nbsp;&nbsp;&nbsp;&nbsp;- JDK 版權宣告 (按下 Yes 即可)
&nbsp;&nbsp;&nbsp;&nbsp;- 選擇安裝項目(不要安裝 Demos, Java Sources, Java 2 Runtime Environment  這三個項目), 
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;並自行指定 ''安裝目錄'', 例如 : d:\jdk1.6.0_02

&nbsp;&nbsp;<<toBalaSWF2 "movie/Install_JDKU2.swf" "820" "610" "教學影片 - 安裝 JDK 1.6 Update 2">>

3. 將安裝好的 JDK 目錄 (d:\jdk1.6.0_02) 複製至 ''toBalaKMKNotepad\java'' 目錄中

4. 修改 ''toBalaKMKNotepad'' 目錄中的 ''jdkconfig.bat'' 批次檔, 如下 :
{{{
set JAVA_HOME=%CD%\java\jdk1.6.0_02
set JRE_HOME=%CD%\java\jdk1.6.0_02
}}}

5. 從視窗系統的 [控制台] 將安裝好的 JDK 移除

6. 啟動 [學習筆記本], 點選 [[toBalaJava2 - 編譯及執行 java 程式]] 進行測試


{{item1{撰寫, 編譯及執行 Java 程式}}}

1. 點選工具列中的 ''[新增文章]'' 按鈕

2. 輸入文章 ''[抬頭]'', 然後在文字區輸入以下 ''[巨集]'' 命令, 最後點選 ''[完成]''
{{{
<<toBalaJava2 "java\scjp\hello.java">>
}}}

3. 點選 ''[程式編輯]'' 按鈕, 然後輸入以下 Java 程式
{{{
public class hello {
   public static void main(String []  argv){
      System.out.println("Hi Guru");
   }
}
}}}

4. 點選 ''[編譯程式]'' 及 ''[執行程式]'' 按鈕

<<toBalaNotes "java2">>


///%java2
//%/
{{item1{SQLite 簡介}}}
官方網站 : http://www.sqlite.org/

SQL 資料庫系統是程式設計師的好幫手,對於大量的資料處理上是絕對不可或缺的。不過,如果稍微少一點的資料呢?

比如說:
{{{
    * 你有幾萬筆的資料,以後也不太會增加。
    * 你的程式可能只有單機使用,
    * 就算可以上網,你也不想就為了這個程式來架一個資料庫。
    * 這個應用程式沒有多人一起使用的需求。 
}}}
諸如此類的狀況,也許您也曾經遇到過。通常您有幾種作法:
{{{
    * 累一點,在同一台機器上架個資料庫系統。
    * 找個小型的資料庫系統,像是 GDBM,Windows 的Registry,Access,或是乾脆用 CSV 格式的文字檔。 
}}}
第一種方法,對於使用者來說可能會是個大問題。因為不是每個使用者都懂得,而且願意架設一個資料庫系統在自己的電腦上。甚至他的電腦夠不夠力跑一個資料庫系統都是問題。第二種方法,是許多人常用的方式,尤其在 Windows 系統下面,許多人常常用Registry 來作為軟體的資料庫。不過,話說回來,少掉了 SQL 的幫助,很多資料處理的功能都要自己來作,對於程式設計師來說真的是很累。

其實,還有另外一種折衷的方案,就是使用 ~SQLite 這樣的嵌入式資料庫。對於程式設計師來說,使用這樣的資料庫,與使用一般的 SQL 資料庫差異不大。一 般的 ~SQL92 語法都可以使用。而且不用架設任何系統起來,只要在編譯程式時把 ~SQLite 的程式庫一併編入。

而且 ~SQLite 的資料庫都是單一的檔案。 所以,要將軟體安裝到使用者的電腦上是再簡單不過的事情。

下面就來看看 ~SQLite 網站上對於這個嵌入式資料庫的介紹: ~SQLite 是一個很小的 C 語言程式庫。這個程式庫本身就完全包含資料庫引擎的功能,而且可以嵌入至其他程式中,完全不用額外的設定。其特性如下:
{{{
    * 支援 ACID (Atomic, Consistent, Isolated, Durable) 交易。
    * 零組態設定(Zero-configuration),無須管理者的設定及管理。
    * 支援大部分 ~SQL92 的語法。
    * 資料庫存在於一個單一的檔案中。
    * 資料庫系統所在機器的位元組順序( Byte order) 無關。
    * 支援大小至 2 terabytes (2^41 bytes)。
    * 極小的記憶體需求:小於 3 萬行的 C 語言程式碼。小於 250KB 的程式空間。
    * 大部分的資料庫操作皆快於一般流行的資料庫系統。
    * 簡單易用的 API。
    * 支援 TCL。也有其他語言的支援可用。
    * 註解詳細的程式碼,以及超過 90% 的測試。
    * 程式庫自己包含完整的功能,無須其他額外的程式或程式庫。
    * 程式碼版權為 public domain。任何用途皆可免費使用。 
}}}
在與其他的開發工具連結方面,~SQLite 幾乎可以在目前所有的主流開發工具,平台,程式語言上面使用:
{{{
    * BASIC
    * C/C++
    * ODBC
    * Java
    * JavaScript
    * .Net framework
    * Perl
    * PHP
    * Python
    * Ruby
}}}
而在作業系統支援上,除了目前大部分的 PC/NB 所使用的作業系統,如 Windows, Linux, ~FreeBSD, OS/2 ...等。在嵌入式系統上也有支援,如 Embedded 系統使用的 Linux, Win CE 及 Symbian 等等。 


{{item1{SQLite 實作說明}}}

You need to put all your sqlite shell commands in one file, say sqlitecmds.txt. This includes the dot commands and the SQL statements. So sqlitecmds.txt contains:
{{{
    .output testfile.txt
    select * from readcode where read_code glob 'G2*';
}}}
Then you need to put your DOS shell commands in another file, say readcode.bat. This file will contain the commnad to run sqlite and redirect its input to the file of sqlite commnads above. So readcode.bat contains:
{{{
    cd c:\test\ReadCodes
    c:\test\Program\sqlite3 c:\test\ReadCodes\ReadCode.db < sqlitecmds.txt
}}}
Then you tell the DOS shell (actually cmd.exe) to run the commands in your readcode.bat file by typing the batch file name at the command prompt.
{{{
    C:\>readcode
}}}
<nowiki>
This will execute your batch file commands, which will run the sqlite shell program, which will read and execute the commands in the sqlite commands file, which will write its output to the file testfile.txt in the current directory (which will be C:\test\ReadCodes).
</nowiki>



''__@@font-size:14px;產生 t1 資料表@@__''

<<toBalaFile "db\createTable.txt">><<toBalaRun "tbsqlite.exe"  "db\test.db db\createTable.txt"  "產生 t1 資料表"  "">>

''__@@font-size:14px;新增記錄@@__''

<<toBalaFile "db\insert.txt">><<toBalaRun "tbsqlite.exe"  "db\test.db db\insert.txt"  "新增記錄"  "">>

''__@@font-size:14px;查詢記錄@@__''

<<toBalaFile "db\query.txt">><<toBalaRun "tbsqlite.exe"  "db\test.db db\query.txt"  "查詢記錄"  "">>

''__@@font-size:14px;刪除記錄@@__''

<<toBalaFile "db\delete.txt">><<toBalaRun "tbsqlite.exe"  "db\test.db db\delete.txt"  "刪除記錄"  "">>

''__@@font-size:14px;刪除 t1 資料表@@__''

<<toBalaFile "db\dropTable.txt">><<toBalaRun "tbsqlite.exe"  "db\test.db db\dropTable.txt"  "刪除 t1 資料表"  "">>



{{item1{tbsqlite.bat 批次檔}}}
{{{
@echo off

REM 取得這個 Batch File 的目錄
set toBalaPath=%~p0

REM 取得這個 Batch File 的磁碟代號
set toBalaDrv=%~d0

REM 轉換磁碟及目錄
call %toBalaDrv%
cd %toBalaPath%

REM 設定環境變數
REM -----------------
set PATH=.;%CD%\tools;%CD%\tools\cmdtools;%PATH%

REM 執行 sqlite3 命令
REM ------------------
if "%~x0" == ".bat" goto n1
echo ^<head^> >%0.htm
echo ^<meta http-equiv="Content-Type" content="text/html; charset=utf-8"^> >>%0.htm
echo ^</head^> >>%0.htm
echo ^<body^> >>%0.htm
echo sqlite3  -html -header %1 ^< %2 >>%0.htm
echo ^<hr^> >>%0.htm 
echo ^<table style='font-size:12px' border="1" align="left"^> >>%0.htm
goto n2

:n1
echo 執行中, 請稍待 (檔案 : sqlite3 %1 ^< %2) 
echo. >%0.htm

:n2
sqlite3 -html -header %1  < %2  >> %0.htm 2>&1

REM 處理執行訊息
REM -------------------
if "%~x0" == ".bat" goto s1
echo ^</table^> >>%0.htm
echo ^</body^> >>%0.htm
exit

:s1
type %0.htm
echo.
echo 執行完成
echo.
pause
exit
}}}

///%db\createTable.txt
create table t1 (t1key INTEGER PRIMARY KEY,data TEXT,num double,timeEnter DATE);
//%/

///%db\insert.txt
insert into t1 (data,num) values ('This is sample data',3);
insert into t1 (data,num) values ('More sample data',6);
insert into t1 (data,num) values ('中文測試',9);
//%/

///%db\query.txt
select * from t1;
//%/

///%db\delete.txt
delete from t1;
//%/

///%db\dropTable.txt
drop table t1;
//%/

本文網址 : http://www.zdnet.com.tw/news/ce/0,2000085674,20142174,00.htm

ZDNET新聞專區:陳奭璁輯 2009/10/21 11:27:02
[img[img/linux/nook_front_view.jpg]]
(以下內容是直接從記者會現場的發表會編輯而成)

Barnes & Noble週二正式跨足電子書閱讀器事業,推出Nook,售價259美元,採e-ink顯示器,特色是還有第二個彩色觸控螢幕。

‧Nook支援PDF,採AT&T無線網路;

‧可選擇5種字型、2GB內建記憶體,有Micro SD記憶體插槽;

‧用戶可放入照片、音樂或個人文件;

‧採用Android與觸控螢幕的意義在於未來可加入新功能。

‧裡面有個「LendMe」功能,你可跟別的Nook用戶借書,最高兩個禮拜借期。

‧Nook會在B&N旗下4萬間零售書店展示銷售(假期旺季開賣)。

‧預售目前已經展開,但要從11月底才會寄出,售價259美元;

‧機器沒有內建瀏覽器,公司的說法是在e-ink上配置瀏覽器的效果不佳;

‧Nook可支援PDF與ePub格式,以及早期的Fictionwise,但無法讀取微軟Word;

‧Wi-Fi「目前」僅限在B&N店內使用,作串流與索取免費內容。

‧觸控螢幕採電容式,類似於iPhone,

‧借書規則跟實體借書一樣,若你把書借給別人,你自己就不能看。

‧B&N表示會開發e-Reader應用供其他Android裝置使用,同時也打算支援Windows Mobile;

‧B&N表示,已經跟出版商洽談,讓用戶購買實體書本時,也可連帶取得數位版本。

Background: #fff
Foreground: #000
PrimaryPale: #fc8
PrimaryLight: #f81
PrimaryMid: #b40
PrimaryDark: #410
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/***
|''Name:''|CryptoFunctionsPlugin|
|''Description:''|Support for cryptographic functions|
***/
//{{{
if(!version.extensions.CryptoFunctionsPlugin) {
version.extensions.CryptoFunctionsPlugin = {installed:true};

//--
//-- Crypto functions and associated conversion routines
//--

// Crypto "namespace"
function Crypto() {}

// Convert a string to an array of big-endian 32-bit words
Crypto.strToBe32s = function(str)
{
	var be = Array();
	var len = Math.floor(str.length/4);
	var i, j;
	for(i=0, j=0; i<len; i++, j+=4) {
		be[i] = ((str.charCodeAt(j)&0xff) << 24)|((str.charCodeAt(j+1)&0xff) << 16)|((str.charCodeAt(j+2)&0xff) << 8)|(str.charCodeAt(j+3)&0xff);
	}
	while (j<str.length) {
		be[j>>2] |= (str.charCodeAt(j)&0xff)<<(24-(j*8)%32);
		j++;
	}
	return be;
};

// Convert an array of big-endian 32-bit words to a string
Crypto.be32sToStr = function(be)
{
	var str = "";
	for(var i=0;i<be.length*32;i+=8)
		str += String.fromCharCode((be[i>>5]>>>(24-i%32)) & 0xff);
	return str;
};

// Convert an array of big-endian 32-bit words to a hex string
Crypto.be32sToHex = function(be)
{
	var hex = "0123456789ABCDEF";
	var str = "";
	for(var i=0;i<be.length*4;i++)
		str += hex.charAt((be[i>>2]>>((3-i%4)*8+4))&0xF) + hex.charAt((be[i>>2]>>((3-i%4)*8))&0xF);
	return str;
};

// Return, in hex, the SHA-1 hash of a string
Crypto.hexSha1Str = function(str)
{
	return Crypto.be32sToHex(Crypto.sha1Str(str));
};

// Return the SHA-1 hash of a string
Crypto.sha1Str = function(str)
{
	return Crypto.sha1(Crypto.strToBe32s(str),str.length);
};

// Calculate the SHA-1 hash of an array of blen bytes of big-endian 32-bit words
Crypto.sha1 = function(x,blen)
{
	// Add 32-bit integers, wrapping at 32 bits
	add32 = function(a,b)
	{
		var lsw = (a&0xFFFF)+(b&0xFFFF);
		var msw = (a>>16)+(b>>16)+(lsw>>16);
		return (msw<<16)|(lsw&0xFFFF);
	};
	// Add five 32-bit integers, wrapping at 32 bits
	add32x5 = function(a,b,c,d,e)
	{
		var lsw = (a&0xFFFF)+(b&0xFFFF)+(c&0xFFFF)+(d&0xFFFF)+(e&0xFFFF);
		var msw = (a>>16)+(b>>16)+(c>>16)+(d>>16)+(e>>16)+(lsw>>16);
		return (msw<<16)|(lsw&0xFFFF);
	};
	// Bitwise rotate left a 32-bit integer by 1 bit
	rol32 = function(n)
	{
		return (n>>>31)|(n<<1);
	};

	var len = blen*8;
	// Append padding so length in bits is 448 mod 512
	x[len>>5] |= 0x80 << (24-len%32);
	// Append length
	x[((len+64>>9)<<4)+15] = len;
	var w = Array(80);

	var k1 = 0x5A827999;
	var k2 = 0x6ED9EBA1;
	var k3 = 0x8F1BBCDC;
	var k4 = 0xCA62C1D6;

	var h0 = 0x67452301;
	var h1 = 0xEFCDAB89;
	var h2 = 0x98BADCFE;
	var h3 = 0x10325476;
	var h4 = 0xC3D2E1F0;

	for(var i=0;i<x.length;i+=16) {
		var j,t;
		var a = h0;
		var b = h1;
		var c = h2;
		var d = h3;
		var e = h4;
		for(j = 0;j<16;j++) {
			w[j] = x[i+j];
			t = add32x5(e,(a>>>27)|(a<<5),d^(b&(c^d)),w[j],k1);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=16;j<20;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),d^(b&(c^d)),w[j],k1);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=20;j<40;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k2);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=40;j<60;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),(b&c)|(d&(b|c)),w[j],k3);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}
		for(j=60;j<80;j++) {
			w[j] = rol32(w[j-3]^w[j-8]^w[j-14]^w[j-16]);
			t = add32x5(e,(a>>>27)|(a<<5),b^c^d,w[j],k4);
			e=d; d=c; c=(b>>>2)|(b<<30); b=a; a = t;
		}

		h0 = add32(h0,a);
		h1 = add32(h1,b);
		h2 = add32(h2,c);
		h3 = add32(h3,d);
		h4 = add32(h4,e);
	}
	return Array(h0,h1,h2,h3,h4);
};


}
//}}}
首頁
/***
|''Name:''|DeprecatedFunctionsPlugin|
|''Description:''|Support for deprecated functions removed from core|
***/
//{{{
if(!version.extensions.DeprecatedFunctionsPlugin) {
version.extensions.DeprecatedFunctionsPlugin = {installed:true};

//--
//-- Deprecated code
//--

// @Deprecated: Use createElementAndWikify and this.termRegExp instead
config.formatterHelpers.charFormatHelper = function(w)
{
	w.subWikify(createTiddlyElement(w.output,this.element),this.terminator);
};

// @Deprecated: Use enclosedTextHelper and this.lookaheadRegExp instead
config.formatterHelpers.monospacedByLineHelper = function(w)
{
	var lookaheadRegExp = new RegExp(this.lookahead,"mg");
	lookaheadRegExp.lastIndex = w.matchStart;
	var lookaheadMatch = lookaheadRegExp.exec(w.source);
	if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
		var text = lookaheadMatch[1];
		if(config.browser.isIE)
			text = text.replace(/\n/g,"\r");
		createTiddlyElement(w.output,"pre",null,null,text);
		w.nextMatch = lookaheadRegExp.lastIndex;
	}
};

// @Deprecated: Use <br> or <br /> instead of <<br>>
config.macros.br = {};
config.macros.br.handler = function(place)
{
	createTiddlyElement(place,"br");
};

// Find an entry in an array. Returns the array index or null
// @Deprecated: Use indexOf instead
Array.prototype.find = function(item)
{
	var i = this.indexOf(item);
	return i == -1 ? null : i;
};

// Load a tiddler from an HTML DIV. The caller should make sure to later call Tiddler.changed()
// @Deprecated: Use store.getLoader().internalizeTiddler instead
Tiddler.prototype.loadFromDiv = function(divRef,title)
{
	return store.getLoader().internalizeTiddler(store,this,title,divRef);
};

// Format the text for storage in an HTML DIV
// @Deprecated Use store.getSaver().externalizeTiddler instead.
Tiddler.prototype.saveToDiv = function()
{
	return store.getSaver().externalizeTiddler(store,this);
};

// @Deprecated: Use store.allTiddlersAsHtml() instead
function allTiddlersAsHtml()
{
	return store.allTiddlersAsHtml();
}

// @Deprecated: Use refreshPageTemplate instead
function applyPageTemplate(title)
{
	refreshPageTemplate(title);
}

// @Deprecated: Use story.displayTiddlers instead
function displayTiddlers(srcElement,titles,template,unused1,unused2,animate,unused3)
{
	story.displayTiddlers(srcElement,titles,template,animate);
}

// @Deprecated: Use story.displayTiddler instead
function displayTiddler(srcElement,title,template,unused1,unused2,animate,unused3)
{
	story.displayTiddler(srcElement,title,template,animate);
}

// @Deprecated: Use functions on right hand side directly instead
var createTiddlerPopup = Popup.create;
var scrollToTiddlerPopup = Popup.show;
var hideTiddlerPopup = Popup.remove;

// @Deprecated: Use right hand side directly instead
var regexpBackSlashEn = new RegExp("\\\\n","mg");
var regexpBackSlash = new RegExp("\\\\","mg");
var regexpBackSlashEss = new RegExp("\\\\s","mg");
var regexpNewLine = new RegExp("\n","mg");
var regexpCarriageReturn = new RegExp("\r","mg");

}
//}}}
/***
|Name|DisableWikiLinksPlugin|
|Source|http://www.TiddlyTools.com/#DisableWikiLinksPlugin|
|Version|1.5.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Tiddler.prototype.autoLinkWikiWords, 'wikiLink' formatter|
|Options|##Configuration|
|Description|selectively disable TiddlyWiki's automatic ~WikiWord linking behavior|
This plugin allows you to disable TiddlyWiki's automatic ~WikiWord linking behavior, so that WikiWords embedded in tiddler content will be rendered as regular text, instead of being automatically converted to tiddler links.  To create a tiddler link when automatic linking is disabled, you must enclose the link text within {{{[[...]]}}}.
!!!!!Usage
<<<
You can block automatic WikiWord linking behavior for any specific tiddler by ''tagging it with<<tag excludeWikiWords>>'' (see configuration below) or, check a plugin option to disable automatic WikiWord links to non-existing tiddler titles, while still linking WikiWords that correspond to existing tiddlers titles or shadow tiddler titles.  You can also block specific selected WikiWords from being automatically linked by listing them in [[DisableWikiLinksList]] (see configuration below), separated by whitespace.  This tiddler is optional and, when present, causes the listed words to always be excluded, even if automatic linking of other WikiWords is being permitted.  

Note: WikiWords contained in default ''shadow'' tiddlers will be automatically linked unless you select an additional checkbox option lets you disable these automatic links as well, though this is not recommended, since it can make it more difficult to access some TiddlyWiki standard default content (such as AdvancedOptions or SideBarTabs)
<<<
!!!!!Configuration
<<<
<<option chkDisableWikiLinks>> Disable ALL automatic WikiWord tiddler links
<<option chkAllowLinksFromShadowTiddlers>> ... except for WikiWords //contained in// shadow tiddlers
<<option chkDisableNonExistingWikiLinks>> Disable automatic WikiWord links for non-existing tiddlers
Disable automatic WikiWord links for words listed in: <<option txtDisableWikiLinksList>>
Disable automatic WikiWord links for tiddlers tagged with: <<option txtDisableWikiLinksTag>>
<<<
!!!!!Code
***/
//{{{
version.extensions.disableWikiLinks= {major: 1, minor: 5, revision: 0, date: new Date(2007,6,9)};

if (config.options.chkDisableNonExistingWikiLinks==undefined) config.options.chkDisableNonExistingWikiLinks= false;
if (config.options.chkDisableWikiLinks==undefined) config.options.chkDisableWikiLinks=false;
if (config.options.txtDisableWikiLinksList==undefined) config.options.txtDisableWikiLinksList="DisableWikiLinksList";
if (config.options.chkAllowLinksFromShadowTiddlers==undefined) config.options.chkAllowLinksFromShadowTiddlers=true;
if (config.options.txtDisableWikiLinksTag==undefined) config.options.txtDisableWikiLinksTag="excludeWikiWords";

// find the formatter for wikiLink and replace handler with 'pass-thru' rendering
initDisableWikiLinksFormatter();
function initDisableWikiLinksFormatter() {
	for (var i=0; i<config.formatters.length && config.formatters[i].name!="wikiLink"; i++);
	config.formatters[i].coreHandler=config.formatters[i].handler;
	config.formatters[i].handler=function(w) {
		// supress any leading "~" (if present)
		var skip=(w.matchText.substr(0,1)==config.textPrimitives.unWikiLink)?1:0;
		var title=w.matchText.substr(skip);
		var exists=store.tiddlerExists(title);
		var inShadow=w.tiddler && store.isShadowTiddler(w.tiddler.title);

		// check for excluded Tiddler
		if (w.tiddler && w.tiddler.isTagged(config.options.txtDisableWikiLinksTag))
			{ w.outputText(w.output,w.matchStart+skip,w.nextMatch); return; }
		
		// check for specific excluded wiki words
		var t=store.getTiddlerText(config.options.txtDisableWikiLinksList)
		if (t && t.length && t.indexOf(w.matchText)!=-1)
			{ w.outputText(w.output,w.matchStart+skip,w.nextMatch); return; }

		// if not disabling links from shadows (default setting)
		if (config.options.chkAllowLinksFromShadowTiddlers && inShadow)
			return this.coreHandler(w);

		// check for non-existing non-shadow tiddler
		if (config.options.chkDisableNonExistingWikiLinks && !exists)
			{ w.outputText(w.output,w.matchStart+skip,w.nextMatch); return; }

		// if not enabled, just do standard WikiWord link formatting
		if (!config.options.chkDisableWikiLinks)
			return this.coreHandler(w);

		// just return text without linking
		w.outputText(w.output,w.matchStart+skip,w.nextMatch)
	}
}

Tiddler.prototype.coreAutoLinkWikiWords = Tiddler.prototype.autoLinkWikiWords;
Tiddler.prototype.autoLinkWikiWords = function()
{
	// DEBUG alert("processing: "+this.title);
	// if all automatic links are not disabled, just return results from core function
	if (!config.options.chkDisableWikiLinks)
		return this.coreAutoLinkWikiWords.apply(this,arguments);
	return false;
}
//}}}
/*{{{*/
 
/*}}}*/
/*{{{*/
a {color:#0044BB;font-weight:bold}
/*}}}*/
<!--{{{-->
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='easyEdit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<!--}}}-->
<!--{{{-->
<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='edit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<!--}}}-->
/***
|Name|ExportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ExportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ExportTiddlersPluginInfo|
|Version|2.7.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Description|select and extract tiddlers from your ~TiddlyWiki documents and save them to a separate file|
ExportTiddlersPlugin lets you select and extract tiddlers from your ~TiddlyWiki documents using interactive control panel lets you specify a destination, and then select which tiddlers to export. Tiddler data can be output as complete, stand-alone TiddlyWiki documents, or just the selected tiddlers ("~PureStore" format -- smaller files!) that can be imported directly into another ~TiddlyWiki, or as an ~RSS-compatible XML file that can be published for RSS syndication.
!!!!!Documentation
>see [[ExportTiddlersPluginInfo]]
!!!!!Code
***/
//{{{
// version
version.extensions.exportTiddlers = {major: 2, minor: 7, revision: 0, date: new Date(2008,5,27)};

// default shadow definition
config.shadowTiddlers.ExportTiddlers="<<exportTiddlers inline>>";

// add 'export' backstage task (following built-in import task)
if (config.tasks) { // TW2.2 or above
	config.tasks.exportTask = {
		text:"export",
		tooltip:"Export selected tiddlers to another file",
		content:"<<exportTiddlers inline>>"
	}
	config.backstageTasks.splice(config.backstageTasks.indexOf("importTask")+1,0,"exportTask");
}

// macro handler
config.macros.exportTiddlers = {
	label: "export tiddlers",
	prompt: "Copy selected tiddlers to an export document",
	newdefault: "export.html",
	datetimefmt: "0MM/0DD/YYYY 0hh:0mm:0ss" // for "filter date/time" edit fields
};

config.macros.exportTiddlers.handler = function(place,macroName,params) {
	if (params[0]!="inline")
		{ createTiddlyButton(place,this.label,this.prompt,onClickExportMenu); return; }
	var panel=createExportPanel(place);
	panel.style.position="static";
	panel.style.display="block";
}

function createExportPanel(place) {
	var panel=document.getElementById("exportPanel");
	if (panel) { panel.parentNode.removeChild(panel); }
	setStylesheet(config.macros.exportTiddlers.css,"exportTiddlers");
	panel=createTiddlyElement(place,"span","exportPanel",null,null)
	panel.innerHTML=config.macros.exportTiddlers.html;
	exportInitFilter();
	refreshExportList(0);
	var fn=document.getElementById("exportFilename");
	if (window.location.protocol=="file:" && !fn.value.length) {
		// get new target path/filename
		var newPath=getLocalPath(window.location.href);
		var slashpos=newPath.lastIndexOf("/"); if (slashpos==-1) slashpos=newPath.lastIndexOf("\\"); 
		if (slashpos!=-1) newPath=newPath.substr(0,slashpos+1); // trim filename
		fn.value=newPath+config.macros.exportTiddlers.newdefault;
	}
	return panel;
}

function onClickExportMenu(e)
{
	if (!e) var e = window.event;
	var parent=resolveTarget(e).parentNode;
	var panel = document.getElementById("exportPanel");
	if (panel==undefined || panel.parentNode!=parent)
		panel=createExportPanel(parent);
	var isOpen = panel.style.display=="block";
	if(config.options.chkAnimate)
		anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,"none"));
	else
		panel.style.display = isOpen ? "none" : "block" ;
	if (panel.style.display!="none") { // update list and set focus when panel is made visible
		refreshExportList(0);
		var fn=document.getElementById("exportFilename"); fn.focus(); fn.select();
	}
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();
	return(false);
}
//}}}

// // IE needs explicit scoping for functions called by browser events
//{{{
window.onClickExportMenu=onClickExportMenu;
window.onClickExportButton=onClickExportButton;
window.exportShowFilterFields=exportShowFilterFields;
window.refreshExportList=refreshExportList;
//}}}

// // CSS for floating export control panel
//{{{
config.macros.exportTiddlers.css = '\
#exportPanel {\
	display: none; position:absolute; z-index:12; width:45em; right:105%; top:6em;\
	background-color: #eee; color:#000; font-size: 10pt; line-height:110%;\
	border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\
	padding: 0.5em; margin:0em; -moz-border-radius:1em;\
}\
#exportPanel a, #exportPanel td a { color:#009; display:inline; margin:0px; padding:1px; }\
#exportPanel table { width:100%; border:0px; padding:0px; margin:0px; font-size:10pt; line-height:110%; background:transparent; }\
#exportPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }\
#exportPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }\
#exportPanel select { width:98%;margin:0px;font-size:10pt;line-height:110%;}\
#exportPanel input  { width:98%;padding:0px;margin:0px;font-size:10pt;line-height:110%; }\
#exportPanel textarea  { width:98%;padding:0px;margin:0px;overflow:auto;font-size:10pt; }\
#exportPanel .box { border:1px solid black; padding:3px; margin-bottom:5px; background:#f8f8f8; -moz-border-radius:5px; }\
#exportPanel .topline { border-top:2px solid black; padding-top:3px; margin-bottom:5px; }\
#exportPanel .rad { width:auto;border:0 }\
#exportPanel .chk { width:auto;border:0 }\
#exportPanel .btn { width:auto; }\
#exportPanel .btn1 { width:98%; }\
#exportPanel .btn2 { width:48%; }\
#exportPanel .btn3 { width:32%; }\
#exportPanel .btn4 { width:24%; }\
#exportPanel .btn5 { width:19%; }\
';
//}}}

// // HTML for export control panel interface
//{{{
config.macros.exportTiddlers.html = '\
<!-- target path/file  -->\
<div>\
export to path/filename:<br>\
<input type="text" id="exportFilename" size=40 style="width:93%"><input \
	type="button" id="exportBrowse" value="..." title="select or enter a local folder/file..." style="width:5%" \
	onclick="var fn=window.promptForExportFilename(this); if (fn.length) this.previousSibling.value=fn; ">\
</div>\
\
<!-- output format -->\
<div>\
output file format:\
<select id="exportFormat" size=1>\
<option value="TW">TiddlyWiki document (includes core code)</option>\
<option value="DIV">TiddlyWiki "PureStore" file (tiddler data only)</option>\
<option value="XML">XML (for RSS newsfeed)</option>\
</select>\
</div>\
\
<!-- notes -->\
<div>\
notes:<br>\
<textarea id="exportNotes" rows=3 cols=40 style="height:4em;margin-bottom:5px;" onfocus="this.select()"></textarea> \
</div>\
\
<!-- list of tiddlers -->\
<table><tr align="left"><td>\
	select:\
	<a href="JavaScript:;" id="exportSelectAll"\
		onclick="onClickExportButton(this)" title="select all tiddlers">\
		&nbsp;all&nbsp;</a>\
	<a href="JavaScript:;" id="exportSelectChanges"\
		onclick="onClickExportButton(this)" title="select tiddlers changed since last save">\
		&nbsp;changes&nbsp;</a> \
	<a href="JavaScript:;" id="exportSelectOpened"\
		onclick="onClickExportButton(this)" title="select tiddlers currently being displayed">\
		&nbsp;opened&nbsp;</a> \
	<a href="JavaScript:;" id="exportSelectRelated"\
		onclick="onClickExportButton(this)" title="select all tiddlers related (by link or transclusion) to the currently selected tiddlers">\
		&nbsp;related&nbsp;</a> \
	<a href="JavaScript:;" id="exportToggleFilter"\
		onclick="onClickExportButton(this)" title="show/hide selection filter">\
		&nbsp;filter&nbsp;</a>  \
</td><td align="right">\
	<a href="JavaScript:;" id="exportListSmaller"\
		onclick="onClickExportButton(this)" title="reduce list size">\
		&nbsp;&#150;&nbsp;</a>\
	<a href="JavaScript:;" id="exportListLarger"\
		onclick="onClickExportButton(this)" title="increase list size">\
		&nbsp;+&nbsp;</a>\
</td></tr></table>\
<select id="exportList" multiple size="20" style="margin-bottom:5px;"\
	onchange="refreshExportList(this.selectedIndex)">\
</select><br>\
</div><!--box-->\
\
<!-- selection filter -->\
<div id="exportFilterPanel" style="display:none">\
<table><tr align="left"><td>\
	selection filter\
</td><td align="right">\
	<a href="JavaScript:;" id="exportHideFilter"\
		onclick="onClickExportButton(this)" title="hide selection filter">hide</a>\
</td></tr></table>\
<div class="box">\
<input type="checkbox" class="chk" id="exportFilterStart" value="1"\
	onclick="exportShowFilterFields(this)"> starting date/time<br>\
<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">\
	<select size=1 id="exportFilterStartBy" onchange="exportShowFilterFields(this);">\
		<option value="0">today</option>\
		<option value="1">yesterday</option>\
		<option value="7">a week ago</option>\
		<option value="30">a month ago</option>\
		<option value="site">SiteDate</option>\
		<option value="file">file date</option>\
		<option value="other">other (mm/dd/yyyy hh:mm)</option>\
	</select>\
</td><td width="50%">\
	<input type="text" id="exportStartDate" onfocus="this.select()"\
		onchange="document.getElementById(\'exportFilterStartBy\').value=\'other\';">\
</td></tr></table>\
<input type="checkbox" class="chk" id="exportFilterEnd" value="1"\
	onclick="exportShowFilterFields(this)"> ending date/time<br>\
<table cellpadding="0" cellspacing="0"><tr valign="center"><td width="50%">\
	<select size=1 id="exportFilterEndBy" onchange="exportShowFilterFields(this);">\
		<option value="0">today</option>\
		<option value="1">yesterday</option>\
		<option value="7">a week ago</option>\
		<option value="30">a month ago</option>\
		<option value="site">SiteDate</option>\
		<option value="file">file date</option>\
		<option value="other">other (mm/dd/yyyy hh:mm)</option>\
	</select>\
</td><td width="50%">\
	<input type="text" id="exportEndDate" onfocus="this.select()"\
		onchange="document.getElementById(\'exportFilterEndBy\').value=\'other\';">\
</td></tr></table>\
<input type="checkbox" class="chk" id=exportFilterTags value="1"\
	onclick="exportShowFilterFields(this)"> match tags<br>\
<input type="text" id="exportTags" onfocus="this.select()">\
<input type="checkbox" class="chk" id=exportFilterText value="1"\
	onclick="exportShowFilterFields(this)"> match titles/tiddler text<br>\
<input type="text" id="exportText" onfocus="this.select()">\
</div> <!--box-->\
</div> <!--panel-->\
\
<!-- action buttons -->\
<div style="text-align:center">\
<input type=button class="btn4" onclick="onClickExportButton(this)"\
	id="exportFilter" value="apply filter">\
<input type=button class="btn4" onclick="onClickExportButton(this)"\
	id="exportStart" value="export tiddlers">\
<input type=button class="btn4" onclick="onClickExportButton(this)"\
	id="exportDelete" value="delete tiddlers">\
<input type=button class="btn4" onclick="onClickExportButton(this)"\
	id="exportClose" value="close">\
</div><!--center-->\
';
//}}}

// // initialize interface

// // exportInitFilter()
//{{{
function exportInitFilter() {
	// start date
	document.getElementById("exportFilterStart").checked=false;
	document.getElementById("exportStartDate").value="";
	// end date
	document.getElementById("exportFilterEnd").checked=false;
	document.getElementById("exportEndDate").value="";
	// tags
	document.getElementById("exportFilterTags").checked=false;
	document.getElementById("exportTags").value="";
	// text
	document.getElementById("exportFilterText").checked=false;
	document.getElementById("exportText").value="";
	// show/hide filter input fields
	exportShowFilterFields();
}
//}}}

// // exportShowFilterFields(which)
//{{{
function exportShowFilterFields(which) {
	var show;

	show=document.getElementById('exportFilterStart').checked;
	document.getElementById('exportFilterStartBy').style.display=show?"block":"none";
	document.getElementById('exportStartDate').style.display=show?"block":"none";
	var val=document.getElementById('exportFilterStartBy').value;
	document.getElementById('exportStartDate').value
		=getFilterDate(val,'exportStartDate').formatString(config.macros.exportTiddlers.datetimefmt);
	 if (which && (which.id=='exportFilterStartBy') && (val=='other'))
		document.getElementById('exportStartDate').focus();

	show=document.getElementById('exportFilterEnd').checked;
	document.getElementById('exportFilterEndBy').style.display=show?"block":"none";
	document.getElementById('exportEndDate').style.display=show?"block":"none";
	var val=document.getElementById('exportFilterEndBy').value;
	document.getElementById('exportEndDate').value
		=getFilterDate(val,'exportEndDate').formatString(config.macros.exportTiddlers.datetimefmt);
	 if (which && (which.id=='exportFilterEndBy') && (val=='other'))
		document.getElementById('exportEndDate').focus();

	show=document.getElementById('exportFilterTags').checked;
	document.getElementById('exportTags').style.display=show?"block":"none";

	show=document.getElementById('exportFilterText').checked;
	document.getElementById('exportText').style.display=show?"block":"none";
}
//}}}

// // onClickExportButton(which): control interactions
//{{{
function onClickExportButton(which)
{
	// DEBUG alert(which.id);
	var theList=document.getElementById('exportList'); if (!theList) return;
	var count = 0;
	var total = store.getTiddlers('title').length;
	switch (which.id)
		{
		case 'exportFilter':
			count=filterExportList();
			var panel=document.getElementById('exportFilterPanel');
			if (count==-1) { panel.style.display='block'; break; }
			document.getElementById("exportStart").disabled=(count==0);
			document.getElementById("exportDelete").disabled=(count==0);
			clearMessage(); displayMessage("filtered "+formatExportMessage(count,total));
			if (count==0) { alert("No tiddlers were selected"); panel.style.display='block'; }
			break;
		case 'exportStart':
			exportTiddlers();
			break;
		case 'exportDelete':
			exportDeleteTiddlers();
			break;
		case 'exportHideFilter':
		case 'exportToggleFilter':
			var panel=document.getElementById('exportFilterPanel')
			panel.style.display=(panel.style.display=='block')?'none':'block';
			break;
		case 'exportSelectChanges':
			var lastmod=new Date(document.lastModified);
			for (var t = 0; t < theList.options.length; t++) {
				if (theList.options[t].value=="") continue;
				var tiddler=store.getTiddler(theList.options[t].value); if (!tiddler) continue;
				theList.options[t].selected=(tiddler.modified>lastmod);
				count += (tiddler.modified>lastmod)?1:0;
			}
			document.getElementById("exportStart").disabled=(count==0);
			document.getElementById("exportDelete").disabled=(count==0);
			clearMessage(); displayMessage(formatExportMessage(count,total));
			if (count==0) alert("There are no unsaved changes");
			break;
		case 'exportSelectAll':
			for (var t = 0; t < theList.options.length; t++) {
				if (theList.options[t].value=="") continue;
				theList.options[t].selected=true;
				count += 1;
			}
			document.getElementById("exportStart").disabled=(count==0);
			document.getElementById("exportDelete").disabled=(count==0);
			clearMessage(); displayMessage(formatExportMessage(count,count));
			break;
		case 'exportSelectOpened':
			for (var t = 0; t < theList.options.length; t++) theList.options[t].selected=false;
			var tiddlerDisplay = document.getElementById("tiddlerDisplay"); // for TW2.1-
			if (!tiddlerDisplay) tiddlerDisplay = document.getElementById("storyDisplay"); // for TW2.2+
			for (var t=0;t<tiddlerDisplay.childNodes.length;t++) {
				var tiddler=tiddlerDisplay.childNodes[t].id.substr(7);
				for (var i = 0; i < theList.options.length; i++) {
					if (theList.options[i].value!=tiddler) continue;
					theList.options[i].selected=true; count++; break;
				}
			}
			document.getElementById("exportStart").disabled=(count==0);
			document.getElementById("exportDelete").disabled=(count==0);
			clearMessage(); displayMessage(formatExportMessage(count,total));
			if (count==0) alert("There are no tiddlers currently opened");
			break;
		case 'exportSelectRelated':
			// recursively build list of related tiddlers
			function getRelatedTiddlers(tid,tids) {
				var t=store.getTiddler(tid); if (!t || tids.contains(tid)) return tids;
				tids.push(t.title);
				if (!t.linksUpdated) t.changed();
				for (var i=0; i<t.links.length; i++)
					if (t.links[i]!=tid) tids=getRelatedTiddlers(t.links[i],tids);
				return tids;
			}
			// for all currently selected tiddlers, gather up the related tiddlers (including self) and select them as well
			var tids=[];
			for (var i=0; i<theList.options.length; i++)
				if (theList.options[i].selected) tids=getRelatedTiddlers(theList.options[i].value,tids);
			// select related tiddlers (includes original selected tiddlers)
			for (var i=0; i<theList.options.length; i++)
				theList.options[i].selected=tids.contains(theList.options[i].value);
			clearMessage(); displayMessage(formatExportMessage(tids.length,total));
			break;
		case 'exportListSmaller':	// decrease current listbox size
			var min=5;
			theList.size-=(theList.size>min)?1:0;
			break;
		case 'exportListLarger':	// increase current listbox size
			var max=(theList.options.length>25)?theList.options.length:25;
			theList.size+=(theList.size<max)?1:0;
			break;
		case 'exportClose':
			document.getElementById('exportPanel').style.display='none';
			break;
		}
}
//}}}

// // promptForFilename(msg,path,file) uses platform/browser specific functions to get local filespec
//{{{
window.promptForExportFilename=function(here)
{
	var msg=here.title; // use tooltip as dialog box message
	var path=getLocalPath(document.location.href);
	var slashpos=path.lastIndexOf("/"); if (slashpos==-1) slashpos=path.lastIndexOf("\\"); 
	if (slashpos!=-1) path = path.substr(0,slashpos+1); // remove filename from path, leave the trailing slash
	var file=config.macros.exportTiddlers.newdefault;
	var result="";
	if(window.Components) { // moz
		try {
			netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
			var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
			var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
			picker.init(window, msg, nsIFilePicker.modeSave);
			var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
			thispath.initWithPath(path);
			picker.displayDirectory=thispath;
			picker.defaultExtension='html';
			picker.defaultString=file;
			picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
			if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
		}
		catch(e) { alert('error during local file access: '+e.toString()) }
	}
	else { // IE
		try { // XPSP2 IE only
			var s = new ActiveXObject('UserAccounts.CommonDialog');
			s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|';
			s.FilterIndex=3; // default to HTML files;
			s.InitialDir=path;
			s.FileName=file;
			if (s.showOpen()) var result=s.FileName;
		}
		catch(e) {  // fallback
			var result=prompt(msg,path+file);
		}
	}
	return result;
}
//}}}

// // list display
//{{{
function formatExportMessage(count,total)
{
	var txt=total+' tiddler'+((total!=1)?'s':'')+" - ";
	txt += (count==0)?"none":(count==total)?"all":count;
	txt += " selected for export";
	return txt;
}

function refreshExportList(selectedIndex)
{
	var theList  = document.getElementById("exportList");
	var sort;
	if (!theList) return;
	// get the sort order
	if (!selectedIndex)   selectedIndex=0;
	if (selectedIndex==0) sort='modified';
	if (selectedIndex==1) sort='title';
	if (selectedIndex==2) sort='modified';
	if (selectedIndex==3) sort='modifier';
	if (selectedIndex==4) sort='tags';

	// unselect headings and count number of tiddlers actually selected
	var count=0;
	for (var t=5; t < theList.options.length; t++) {
		if (!theList.options[t].selected) continue;
		if (theList.options[t].value!="")
			count++;
		else { // if heading is selected, deselect it, and then select and count all in section
			theList.options[t].selected=false;
			for ( t++; t<theList.options.length && theList.options[t].value!=""; t++) {
				theList.options[t].selected=true;
				count++;
			}
		}
	}

	// disable "export" and "delete" buttons if no tiddlers selected
	document.getElementById("exportStart").disabled=(count==0);
	document.getElementById("exportDelete").disabled=(count==0);
	// show selection count
	var tiddlers = store.getTiddlers('title');
	if (theList.options.length) { clearMessage(); displayMessage(formatExportMessage(count,tiddlers.length)); }

	// if a [command] item, reload list... otherwise, no further refresh needed
	if (selectedIndex>4)  return;

	// clear current list contents
	while (theList.length > 0) { theList.options[0] = null; }
	// add heading and control items to list
	var i=0;
	var indent=String.fromCharCode(160)+String.fromCharCode(160);
	theList.options[i++]=
		new Option(tiddlers.length+" tiddlers in document", "",false,false);
	theList.options[i++]=
		new Option(((sort=="title"        )?">":indent)+' [by title]', "",false,false);
	theList.options[i++]=
		new Option(((sort=="modified")?">":indent)+' [by date]', "",false,false);
	theList.options[i++]=
		new Option(((sort=="modifier")?">":indent)+' [by author]', "",false,false);
	theList.options[i++]=
		new Option(((sort=="tags"	)?">":indent)+' [by tags]', "",false,false);
	// output the tiddler list
	switch(sort)
		{
		case "title":
			for(var t = 0; t < tiddlers.length; t++)
				theList.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);
			break;
		case "modifier":
		case "modified":
			var tiddlers = store.getTiddlers(sort);
			// sort descending for newest date first
			tiddlers.sort(function (a,b) {if(a[sort] == b[sort]) return(0); else return (a[sort] > b[sort]) ? -1 : +1; });
			var lastSection = "";
			for(var t = 0; t < tiddlers.length; t++)
				{
				var tiddler = tiddlers[t];
				var theSection = "";
				if (sort=="modified") theSection=tiddler.modified.toLocaleDateString();
				if (sort=="modifier") theSection=tiddler.modifier;
				if (theSection != lastSection)
					{
					theList.options[i++] = new Option(theSection,"",false,false);
					lastSection = theSection;
					}
				theList.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);
				}
			 break;
		case "tags":
			var theTitles = {}; // all tiddler titles, hash indexed by tag value
			var theTags = new Array();
			for(var t=0; t<tiddlers.length; t++) {
				var title=tiddlers[t].title;
				var tags=tiddlers[t].tags;
				if (!tags || !tags.length) {
					if (theTitles["untagged"]==undefined) { theTags.push("untagged"); theTitles["untagged"]=new Array(); }
					theTitles["untagged"].push(title);
				}
				else for(var s=0; s<tags.length; s++) {
					if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }
					theTitles[tags[s]].push(title);
				}
			}
			theTags.sort();
			for(var tagindex=0; tagindex<theTags.length; tagindex++) {
				var theTag=theTags[tagindex];
				theList.options[i++]=new Option(theTag,"",false,false);
				for(var t=0; t<theTitles[theTag].length; t++)
					theList.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);
			}
			break;
		}
	theList.selectedIndex=selectedIndex;		  // select current control item
	document.getElementById("exportStart").disabled=true;
	document.getElementById("exportDelete").disabled=true;
	clearMessage(); displayMessage(formatExportMessage(0,tiddlers.length));
}
//}}}

// // list filtering
//{{{
function getFilterDate(val,id)
{
	var result=0;
	switch (val) {
		case 'site':
			var timestamp=store.getTiddlerText("SiteDate");
			if (!timestamp) timestamp=document.lastModified;
			result=new Date(timestamp);
			break;
		case 'file':
			result=new Date(document.lastModified);
			break;
		case 'other':
			result=new Date(document.getElementById(id).value);
			break;
		default: // today=0, yesterday=1, one week=7, two weeks=14, a month=31
			var now=new Date(); var tz=now.getTimezoneOffset()*60000; now-=tz;
			var oneday=86400000;
			if (id=='exportStartDate')
				result=new Date((Math.floor(now/oneday)-val)*oneday+tz);
			else
				result=new Date((Math.floor(now/oneday)-val+1)*oneday+tz-1);
			break;
	}
	// DEBUG alert('getFilterDate('+val+','+id+')=='+result+"\nnow="+now);
	return result;
}

function filterExportList()
{
	var theList  = document.getElementById("exportList"); if (!theList) return -1;

	var filterStart=document.getElementById("exportFilterStart").checked;
	var val=document.getElementById("exportFilterStartBy").value;
	var startDate=getFilterDate(val,'exportStartDate');

	var filterEnd=document.getElementById("exportFilterEnd").checked;
	var val=document.getElementById("exportFilterEndBy").value;
	var endDate=getFilterDate(val,'exportEndDate');

	var filterTags=document.getElementById("exportFilterTags").checked;
	var tags=document.getElementById("exportTags").value;

	var filterText=document.getElementById("exportFilterText").checked;
	var text=document.getElementById("exportText").value;

	if (!(filterStart||filterEnd||filterTags||filterText)) {
		alert("Please set the selection filter");
		document.getElementById('exportFilterPanel').style.display="block";
		return -1;
	}
	if (filterStart&&filterEnd&&(startDate>endDate)) {
		var msg="starting date/time:\n"
		msg+=startDate.toLocaleString()+"\n";
		msg+="is later than ending date/time:\n"
		msg+=endDate.toLocaleString()
		alert(msg);
		return -1;
	}

	// if filter by tags, set up conditional expression
	if (filterTags) {
		var all = store.getTags(); // get list of all tags
		for (var i=0; i<all.length; i++) all[i]=all[i][0]; // remove tag counts
		// convert "tag1 AND ( tag2 OR NOT tag3 )"
		// into javascript expression containing regexp tests:
		// "/\~tag1\~/.test(...) && ( /\~tag2\~/.test(...) || ! /\~tag2\~/.test(...) )"
		var c=tags;
		c = c.replace(/[\[\]]/g,""); // remove [[...]] quoting around tagvalues
		// change AND/OR/NOT/parens to javascript operators and delimit terms with "~"
		c = c.replace(/\sand\s/ig,"~&&~");
		c = c.replace(/\sor\s/ig,"~||~");
		c = c.replace(/(\s)?not([\s\(])/ig,"~!~$2");
		c = c.replace(/([\(\)])/ig,"~$1~");
		// change existing tags to regexp tests and non-existing tags to "false"
		var terms=c.split("~");
		for (var i=0; i<terms.length; i++) { var t=terms[i];
			if (/(&&)|(\|\|)|[!\(\)]/.test(t) || t=="") continue; // skip operators/parens/spaces
			terms[i]=!all.contains(t)?"false":("/\\~"+t+"\\~/.test(tiddlertags)");
		}
		c=terms.join(" ");
	}
	function matchTags(t,c) {
		if (!c||!c.trim().length) return false;
		// assemble tags from tiddler into string "~tag1~tag2~tag3~"
		var tiddlertags = "~"+t.tags.join("~")+"~";
		// eval string against boolean test expression
		try { if(eval(c)) return true; }
		catch(e) { displayMessage(e.toString()); }
		return false;
	}
	
	// scan list and select tiddlers that match all applicable criteria
	var total=0;
	var count=0;
	for (var i=0; i<theList.options.length; i++) {
		// get item, skip non-tiddler list items (section headings)
		var opt=theList.options[i]; if (opt.value=="") continue;
		// get tiddler, skip missing tiddlers (this should NOT happen)
		var tiddler=store.getTiddler(opt.value); if (!tiddler) continue; 
		var sel=true;
		if ( (filterStart && tiddler.modified<startDate)
		|| (filterEnd && tiddler.modified>endDate)
		|| (filterTags && !matchTags(tiddler,c))
		|| (filterText && (tiddler.text.indexOf(text)==-1) && (tiddler.title.indexOf(text)==-1)))
			sel=false;
		opt.selected=sel;
		count+=sel?1:0;
		total++;
	}
	return count;
}
//}}}

// // OUTPUT FORMATTING AND FILE I/O
//{{{
function exportTWHeader()
{
	// get the TiddlyWiki core code source
	var sourcefile=getLocalPath(document.location.href);
	var source=loadFile(sourcefile);
	if(source==null) { alert(config.messages.cantSaveError); return null; }
	// reset existing HTML source markup
	source=updateMarkupBlock(source,"PRE-HEAD");
	source=updateMarkupBlock(source,"POST-HEAD");
	source=updateMarkupBlock(source,"PRE-BODY");
	source=updateMarkupBlock(source,"POST-BODY");
	// find store area
	var posOpeningDiv=source.indexOf(startSaveArea);
	var posClosingDiv=source.lastIndexOf(endSaveArea);
	if((posOpeningDiv==-1)||(posClosingDiv==-1))
		{ alert(config.messages.invalidFileError.format([sourcefile])); return; }
	// return everything up to store area
	return source.substr(0,posOpeningDiv+startSaveArea.length);
}

function exportTWFooter()
{
	// get the TiddlyWiki core code source
	var sourcefile=getLocalPath(document.location.href);
	var source=loadFile(sourcefile);
	if(source==null) { alert(config.messages.cantSaveError); return null; }
	// reset existing HTML source markup
	source=updateMarkupBlock(source,"PRE-HEAD");
	source=updateMarkupBlock(source,"POST-HEAD");
	source=updateMarkupBlock(source,"PRE-BODY");
	source=updateMarkupBlock(source,"POST-BODY");
	// find store area
	var posOpeningDiv=source.indexOf(startSaveArea);
	var posClosingDiv=source.lastIndexOf(endSaveArea);
	if((posOpeningDiv==-1)||(posClosingDiv==-1))
		{ alert(config.messages.invalidFileError.format([sourcefile])); return; }
	// return everything after store area
	return source.substr(posClosingDiv);
}

function exportDIVHeader()
{
	var out=[];
	var now = new Date();
	var title = convertUnicodeToUTF8(wikifyPlain("SiteTitle").htmlEncode());
	var subtitle = convertUnicodeToUTF8(wikifyPlain("SiteSubtitle").htmlEncode());
	var user = convertUnicodeToUTF8(config.options.txtUserName.htmlEncode());
	var twver = version.major+"."+version.minor+"."+version.revision;
	var pver = version.extensions.exportTiddlers.major+"."
		+version.extensions.exportTiddlers.minor+"."+version.extensions.exportTiddlers.revision;
	out.push("<html><body>");
	out.push("<style type=\"text/css\">");
	out.push("#storeArea {display:block;margin:1em;}");
	out.push("#storeArea div");
	out.push("{padding:0.5em;margin:1em;border:2px solid black;height:10em;overflow:auto;}");
	out.push("#javascriptWarning");
	out.push("{width:100%;text-align:left;background-color:#eeeeee;padding:1em;}");
	out.push("</style>");
	out.push("<div id=\"javascriptWarning\">");
	out.push("TiddlyWiki export file<br>");
	out.push("Source"+": <b>"+convertUnicodeToUTF8(document.location.href)+"</b><br>");
	out.push("Title: <b>"+title+"</b><br>");
	out.push("Subtitle: <b>"+subtitle+"</b><br>");
	out.push("Created: <b>"+now.toLocaleString()+"</b> by <b>"+user+"</b><br>");
	out.push("TiddlyWiki "+twver+" / "+"ExportTiddlersPlugin "+pver+"<br>");
	out.push("Notes:<hr><pre>"+document.getElementById("exportNotes").value.replace(/\n/g,"<br>")+"</pre>");
	out.push("</div>");
	out.push("<div id=\"storeArea\">");
	return out;
}

function exportDIVFooter()
{
	return ["</div><!--POST-BODY-START-->\n<!--POST-BODY-END--></body></html>"];
}

function exportXMLHeader()
{
	var out=[];
	var now = new Date();
	var u = store.getTiddlerText("SiteUrl",null);
	var title = convertUnicodeToUTF8(wikifyPlain("SiteTitle").htmlEncode());
	var subtitle = convertUnicodeToUTF8(wikifyPlain("SiteSubtitle").htmlEncode());
	var user = convertUnicodeToUTF8(config.options.txtUserName.htmlEncode());
	var twver = version.major+"."+version.minor+"."+version.revision;
	var pver = version.extensions.exportTiddlers.major+"."
		+version.extensions.exportTiddlers.minor+"."+version.extensions.exportTiddlers.revision;
	out.push("<" + "?xml version=\"1.0\"?" + ">");
	out.push("<rss version=\"2.0\">");
	out.push("<channel>");
	out.push("<title>" + title + "</title>");
	if(u) out.push("<link>" + convertUnicodeToUTF8(u.htmlEncode()) + "</link>");
	out.push("<description>" + subtitle + "</description>");
	out.push("<language>en-us</language>");
	out.push("<copyright>Copyright " + now.getFullYear() + " " + user + "</copyright>");
	out.push("<pubDate>" + now.toGMTString() + "</pubDate>");
	out.push("<lastBuildDate>" + now.toGMTString() + "</lastBuildDate>");
	out.push("<docs>http://blogs.law.harvard.edu/tech/rss</docs>");
	out.push("<generator>TiddlyWiki "+twver+" plus ExportTiddlersPlugin "+pver+"</generator>");
	return out;
}

function exportXMLFooter()
{
	return ["</channel></rss>"];
}

function exportData(target,list,fmt)
{
	function getData(s,f,t) { var r="";
		switch (f) {
			case "TW": r=s.getSaver().externalizeTiddler(s,t); break;
			case "DIV": r=t.title+"\n"+s.getSaver().externalizeTiddler(s,t); break;
			case "XML": r=t.saveToRss(store.getTiddlerText("SiteUrl","")); break;
		}
		return convertUnicodeToUTF8(r);
	}

	var out=[]; var tids=[];
	// get selected tiddlers
	for (var i=0; i<list.options.length; i++) {
		var opt=list.options[i]; if (!opt.selected||!opt.value.length) continue;
		var tid=store.getTiddler(opt.value); if (!tid) continue;
		tids.push(tid.title);
		out.push(getData(store,fmt,tid));
	}
	var count=out.length;
	// merge with existing tiddlers
	var text=loadFile(target);
	if (text && text.length) {
		var msg=target+"\nalready contains tiddler definitions.\n";
		msg+="\nPress OK to add new/revised tiddlers to current file contents.";
		msg+="\nPress Cancel to completely replace file contents";
		var remoteStore=new TiddlyWiki();
		if (remoteStore.importTiddlyWiki(text) && confirm(msg)) {
			var existing=remoteStore.getTiddlers("title");
			for (var i=0; i<existing.length; i++)
				if (!tids.contains(existing[i].title))
					out.push(getData(remoteStore,fmt,existing[i]));
			var msg="Merged %0 new/revised tiddlers and %1 existing tiddlers";
			displayMessage(msg.format([count,out.length-count]));
		}
	}
	return out;
}
//}}}

// // exportTiddlers(): output selected data to local file
//{{{
function exportTiddlers()
{
	clearMessage();
	var list  = document.getElementById("exportList"); if (!list) return;
	var fmt = document.getElementById("exportFormat").value;
	var target = document.getElementById("exportFilename").value.trim();
	if (!target.length) {
		displayMessage("A local target path/filename is required",target);
		return;
	}
	switch (fmt) {
		case "TW":	var head=exportTWHeader(); break;
		case "DIV":	var head=exportDIVHeader(); break;
		case "XML":	var head=exportXMLHeader(); break;
	}
	var theData=exportData(target,list,fmt);
	var c=theData.length;
	switch (fmt) {
		case "TW":	var foot=exportTWFooter(); break;
		case "DIV":	var foot=exportDIVFooter(); break;
		case "XML":	var foot=exportXMLFooter(); break;
	}
	var out=[]; var txt=out.concat(head,theData,foot).join("\n");
	var msg="An error occurred while saving to "+target;
	if (saveFile(target,txt)) msg=c+" tiddler"+((c!=1)?"s":"")+" written to "+target;
	displayMessage(msg,"file:///"+target);
}
//}}}

// // exportDeleteTiddlers(): delete selected tiddlers from file
//{{{
function exportDeleteTiddlers()
{
	var list=document.getElementById("exportList"); if (!list) return;
	var tids=[];
	for (i=0;i<list.length;i++)
		if (list.options[i].selected && list.options[i].value.length)
			tids.push(list.options[i].value);
	if (!confirm("Are you sure you want to delete these tiddlers:\n\n"+tids.join(', '))) return;
	store.suspendNotifications();
	for (t=0;t<tids.length;t++) {
		var tid=store.getTiddler(tids[t]); if (!tid) continue;
		if (tid.tags.contains("systemConfig"))
			if (!confirm("'"+tid.title+"' is tagged with 'systemConfig'.\n\nRemoving this tiddler may cause unexpected results.  Are you sure?"))
				continue;
		store.removeTiddler(tid.title);
		story.closeTiddler(tid.title);
	}
	store.resumeNotifications();
	alert(tids.length+" tiddlers deleted");
	refreshExportList(0); // reload listbox
	store.notifyAll(); // update page display
}
//}}}
/***
|''Name:''|FieldsEditorPlugin|
|''Description:''|//create//, //edit//, //view// and //delete// commands in toolbar <<toolbar fields>>.|
|''Version:''|1.0.2|
|''Date:''|Dec 21,2007|
|''Source:''|http://visualtw.ouvaton.org/VisualTW.html|
|''Author:''|Pascal Collin|
|''License:''|[[BSD open source license|License]]|
|''~CoreVersion:''|2.2.0|
|''Browser:''|Firefox 2.0; InternetExplorer 6.0, others|
!Demo:
On [[homepage|http://visualtw.ouvaton.org/VisualTW.html]], see [[FieldEditor example]]
!Installation:
*import this tiddler from [[homepage|http://visualtw.ouvaton.org/VisualTW.html]] (tagged as systemConfig)
*save and reload
*optionnaly : add the following css text in your StyleSheet : {{{#popup tr.fieldTableRow td {padding:1px 3px 1px 3px;}}}}
!Code
***/

//{{{

config.commands.fields.handlePopup = function(popup,title) {
	var tiddler = store.fetchTiddler(title);
	if(!tiddler)
		return;
	var fields = {};
	store.forEachField(tiddler,function(tiddler,fieldName,value) {fields[fieldName] = value;},true);
	var items = [];
	for(var t in fields) {
		var editCommand = "<<untiddledCall editFieldDialog "+escape(title)+" "+escape(t)+">>";
		var deleteCommand = "<<untiddledCall deleteField "+escape(title)+" "+escape(t)+">>";
		var renameCommand = "<<untiddledCall renameField "+escape(title)+" "+escape(t)+">>";
		items.push({field: t,value: fields[t], actions: editCommand+renameCommand+deleteCommand});
	}
	items.sort(function(a,b) {return a.field < b.field ? -1 : (a.field == b.field ? 0 : +1);});
	var createNewCommand = "<<untiddledCall createField "+escape(title)+">>";
	items.push({field : "", value : "", actions:createNewCommand });
	if(items.length > 0)
		ListView.create(popup,items,this.listViewTemplate);
	else
		createTiddlyElement(popup,"div",null,null,this.emptyText);
}

config.commands.fields.listViewTemplate = {
	columns: [
		{name: 'Field', field: 'field', title: "Field", type: 'String'},
		{name: 'Actions', field: 'actions', title: "Actions", type: 'WikiText'},
		{name: 'Value', field: 'value', title: "Value", type: 'WikiText'}
	],
	rowClasses: [
			{className: 'fieldTableRow', field: 'actions'}
	],
	buttons: [	//can't use button for selected then delete, because click on checkbox will hide the popup
	]
}

config.macros.untiddledCall = {  // when called from listview, tiddler is unset, so we need to pass tiddler as parameter
	handler : function(place,macroName,params,wikifier,paramString) {
		var macroName = params.shift();
		if (macroName) var macro = config.macros[macroName];
		var title = params.shift();
		if (title) var tiddler = store.getTiddler(unescape(title));
		if (macro) macro.handler(place,macroName,params,wikifier,paramString,tiddler);		
	}
}

config.macros.deleteField = {
	handler : function(place,macroName,params,wikifier,paramString,tiddler) {
		if(!readOnly && params[0]) {
			fieldName = unescape(params[0]);
			var btn = createTiddlyButton(place,"delete", "delete "+fieldName,this.onClickDeleteField);
			btn.setAttribute("title",tiddler.title);
			btn.setAttribute("fieldName", fieldName);
		}
	},
	onClickDeleteField : function() {
		var title=this.getAttribute("title");
		var fieldName=this.getAttribute("fieldName");
		var tiddler = store.getTiddler(title);
		if (tiddler && fieldName && confirm("delete field " + fieldName+" from " + title +" tiddler ?")) {
			delete tiddler.fields[fieldName];
			store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields);
			story.refreshTiddler(title,"ViewTemplate",true);
		}
		return false;
	}
}

config.macros.createField = {
	handler : function(place,macroName,params,wikifier,paramString,tiddler) {
		if(!readOnly) {
			var btn = createTiddlyButton(place,"create new", "create a new field",this.onClickCreateField);
			btn.setAttribute("title",tiddler.title);
		}
	},
	onClickCreateField : function() {
		var title=this.getAttribute("title");
		var tiddler = store.getTiddler(title);
		if (tiddler) {
			var fieldName = prompt("Field name","");
			if (store.getValue(tiddler,fieldName)) {
				window.alert("This field already exists.");
			}
			else if (fieldName) {
				var v = prompt("Field value","");
				tiddler.fields[fieldName]=v;
				store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields);
				story.refreshTiddler(title,"ViewTemplate",true);
			}
		}
		return false;
	}
}

config.macros.editFieldDialog = {
	handler : function(place,macroName,params,wikifier,paramString,tiddler) {
		if(!readOnly && params[0]) {
			fieldName = unescape(params[0]);
			var btn = createTiddlyButton(place,"edit", "edit this field",this.onClickEditFieldDialog);
			btn.setAttribute("title",tiddler.title);
			btn.setAttribute("fieldName", fieldName);
		}
	},
	onClickEditFieldDialog : function() {
		var title=this.getAttribute("title");
		var tiddler = store.getTiddler(title);
		var fieldName=this.getAttribute("fieldName");
		if (tiddler && fieldName) {
			var value = tiddler.fields[fieldName];
			value = value ? value : "";
			var lines = value.match(/\n/mg);
			lines = lines ? true : false;
			if (!lines || confirm("This field contains more than one line. Only the first line will be kept if you edit it here. Proceed ?")) {
				var v = prompt("Field value",value);
				tiddler.fields[fieldName]=v;
				store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields);
				story.refreshTiddler(title,"ViewTemplate",true);
			}
		}
		return false;
	}
}

config.macros.renameField = {
	handler : function(place,macroName,params,wikifier,paramString,tiddler) {
		if(!readOnly && params[0]) {
			fieldName = unescape(params[0]);
			var btn = createTiddlyButton(place,"rename", "rename "+fieldName,this.onClickRenameField);
			btn.setAttribute("title",tiddler.title);
			btn.setAttribute("fieldName", fieldName);
		}
	},
	onClickRenameField : function() {
		var title=this.getAttribute("title");
		var fieldName=this.getAttribute("fieldName");
		var tiddler = store.getTiddler(title);
		if (tiddler && fieldName) {
			var newName = prompt("Rename " + fieldName + " as ?", fieldName);
			if (newName) {
				tiddler.fields[newName]=tiddler.fields[fieldName];
				delete tiddler.fields[fieldName];
				store.saveTiddler(tiddler.title,tiddler.title,tiddler.text,tiddler.modifier,tiddler.modified,tiddler.tags,tiddler.fields);
				story.refreshTiddler(title,"ViewTemplate",true);
			}
		}
		return false;
	}
}

config.shadowTiddlers.StyleSheetFieldsEditor = "/*{{{*/\n";
config.shadowTiddlers.StyleSheetFieldsEditor += ".fieldTableRow td {padding : 1px 3px}\n";
config.shadowTiddlers.StyleSheetFieldsEditor += ".fieldTableRow .button {border:0; padding : 0 0.2em}\n";
config.shadowTiddlers.StyleSheetFieldsEditor +="/*}}}*/";
store.addNotification("StyleSheetFieldsEditor", refreshStyles);

//}}}
/***
|''Name:''|ForEachTiddlerPlugin|
|''Version:''|1.0.8 (2007-04-12)|
|''Source:''|http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]|
|''Copyright:''|&copy; 2005-2007 [[abego Software|http://www.abego-software.de]]|
|''TiddlyWiki:''|1.2.38+, 2.0|
|''Browser:''|Firefox 1.0.4+; Firefox 1.5; InternetExplorer 6.0|
!Description

Create customizable lists, tables etc. for your selections of tiddlers. Specify the tiddlers to include and their order through a powerful language.

''Syntax:'' 
|>|{{{<<}}}''forEachTiddler'' [''in'' //tiddlyWikiPath//] [''where'' //whereCondition//] [''sortBy'' //sortExpression// [''ascending'' //or// ''descending'']] [''script'' //scriptText//] [//action// [//actionParameters//]]{{{>>}}}|
|//tiddlyWikiPath//|The filepath to the TiddlyWiki the macro should work on. When missing the current TiddlyWiki is used.|
|//whereCondition//|(quoted) JavaScript boolean expression. May refer to the build-in variables {{{tiddler}}} and  {{{context}}}.|
|//sortExpression//|(quoted) JavaScript expression returning "comparable" objects (using '{{{<}}}','{{{>}}}','{{{==}}}'. May refer to the build-in variables {{{tiddler}}} and  {{{context}}}.|
|//scriptText//|(quoted) JavaScript text. Typically defines JavaScript functions that are called by the various JavaScript expressions (whereClause, sortClause, action arguments,...)|
|//action//|The action that should be performed on every selected tiddler, in the given order. By default the actions [[addToList|AddToListAction]] and [[write|WriteAction]] are supported. When no action is specified [[addToList|AddToListAction]]  is used.|
|//actionParameters//|(action specific) parameters the action may refer while processing the tiddlers (see action descriptions for details). <<tiddler [[JavaScript in actionParameters]]>>|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|

See details see [[ForEachTiddlerMacro]] and [[ForEachTiddlerExamples]].

!Code
***/
//{{{

	
//============================================================================
//============================================================================
//		   ForEachTiddlerPlugin
//============================================================================
//============================================================================

// Only install once
if (!version.extensions.ForEachTiddlerPlugin) {

if (!window.abego) window.abego = {};

version.extensions.ForEachTiddlerPlugin = {
	major: 1, minor: 0, revision: 8, 
	date: new Date(2007,3,12), 
	source: "http://tiddlywiki.abego-software.de/#ForEachTiddlerPlugin",
	licence: "[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]",
	copyright: "Copyright (c) abego Software GmbH, 2005-2007 (www.abego-software.de)"
};

// For backward compatibility with TW 1.2.x
//
if (!TiddlyWiki.prototype.forEachTiddler) {
	TiddlyWiki.prototype.forEachTiddler = function(callback) {
		for(var t in this.tiddlers) {
			callback.call(this,t,this.tiddlers[t]);
		}
	};
}

//============================================================================
// forEachTiddler Macro
//============================================================================

version.extensions.forEachTiddler = {
	major: 1, minor: 0, revision: 8, date: new Date(2007,3,12), provider: "http://tiddlywiki.abego-software.de"};

// ---------------------------------------------------------------------------
// Configurations and constants 
// ---------------------------------------------------------------------------

config.macros.forEachTiddler = {
	 // Standard Properties
	 label: "forEachTiddler",
	 prompt: "Perform actions on a (sorted) selection of tiddlers",

	 // actions
	 actions: {
		 addToList: {},
		 write: {}
	 }
};

// ---------------------------------------------------------------------------
//  The forEachTiddler Macro Handler 
// ---------------------------------------------------------------------------

config.macros.forEachTiddler.getContainingTiddler = function(e) {
	while(e && !hasClass(e,"tiddler"))
		e = e.parentNode;
	var title = e ? e.getAttribute("tiddler") : null; 
	return title ? store.getTiddler(title) : null;
};

config.macros.forEachTiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
	// config.macros.forEachTiddler.traceMacroCall(place,macroName,params,wikifier,paramString,tiddler);

	if (!tiddler) tiddler = config.macros.forEachTiddler.getContainingTiddler(place);
	// --- Parsing ------------------------------------------

	var i = 0; // index running over the params
	// Parse the "in" clause
	var tiddlyWikiPath = undefined;
	if ((i < params.length) && params[i] == "in") {
		i++;
		if (i >= params.length) {
			this.handleError(place, "TiddlyWiki path expected behind 'in'.");
			return;
		}
		tiddlyWikiPath = this.paramEncode((i < params.length) ? params[i] : "");
		i++;
	}

	// Parse the where clause
	var whereClause ="true";
	if ((i < params.length) && params[i] == "where") {
		i++;
		whereClause = this.paramEncode((i < params.length) ? params[i] : "");
		i++;
	}

	// Parse the sort stuff
	var sortClause = null;
	var sortAscending = true; 
	if ((i < params.length) && params[i] == "sortBy") {
		i++;
		if (i >= params.length) {
			this.handleError(place, "sortClause missing behind 'sortBy'.");
			return;
		}
		sortClause = this.paramEncode(params[i]);
		i++;

		if ((i < params.length) && (params[i] == "ascending" || params[i] == "descending")) {
			 sortAscending = params[i] == "ascending";
			 i++;
		}
	}

	// Parse the script
	var scriptText = null;
	if ((i < params.length) && params[i] == "script") {
		i++;
		scriptText = this.paramEncode((i < params.length) ? params[i] : "");
		i++;
	}

	// Parse the action. 
	// When we are already at the end use the default action
	var actionName = "addToList";
	if (i < params.length) {
	   if (!config.macros.forEachTiddler.actions[params[i]]) {
			this.handleError(place, "Unknown action '"+params[i]+"'.");
			return;
		} else {
			actionName = params[i]; 
			i++;
		}
	} 
	
	// Get the action parameter
	// (the parsing is done inside the individual action implementation.)
	var actionParameter = params.slice(i);


	// --- Processing ------------------------------------------
	try {
		this.performMacro({
				place: place, 
				inTiddler: tiddler,
				whereClause: whereClause, 
				sortClause: sortClause, 
				sortAscending: sortAscending, 
				actionName: actionName, 
				actionParameter: actionParameter, 
				scriptText: scriptText, 
				tiddlyWikiPath: tiddlyWikiPath});

	} catch (e) {
		this.handleError(place, e);
	}
};

// Returns an object with properties "tiddlers" and "context".
// tiddlers holds the (sorted) tiddlers selected by the parameter,
// context the context of the execution of the macro.
//
// The action is not yet performed.
//
// @parameter see performMacro
//
config.macros.forEachTiddler.getTiddlersAndContext = function(parameter) {

	var context = config.macros.forEachTiddler.createContext(parameter.place, parameter.whereClause, parameter.sortClause, parameter.sortAscending, parameter.actionName, parameter.actionParameter, parameter.scriptText, parameter.tiddlyWikiPath, parameter.inTiddler);

	var tiddlyWiki = parameter.tiddlyWikiPath ? this.loadTiddlyWiki(parameter.tiddlyWikiPath) : store;
	context["tiddlyWiki"] = tiddlyWiki;
	
	// Get the tiddlers, as defined by the whereClause
	var tiddlers = this.findTiddlers(parameter.whereClause, context, tiddlyWiki);
	context["tiddlers"] = tiddlers;

	// Sort the tiddlers, when sorting is required.
	if (parameter.sortClause) {
		this.sortTiddlers(tiddlers, parameter.sortClause, parameter.sortAscending, context);
	}

	return {tiddlers: tiddlers, context: context};
};

// Returns the (sorted) tiddlers selected by the parameter.
//
// The action is not yet performed.
//
// @parameter see performMacro
//
config.macros.forEachTiddler.getTiddlers = function(parameter) {
	return this.getTiddlersAndContext(parameter).tiddlers;
};

// Performs the macros with the given parameter.
//
// @param parameter holds the parameter of the macro as separate properties.
//				  The following properties are supported:
//
//						place
//						whereClause
//						sortClause
//						sortAscending
//						actionName
//						actionParameter
//						scriptText
//						tiddlyWikiPath
//
//					All properties are optional. 
//					For most actions the place property must be defined.
//
config.macros.forEachTiddler.performMacro = function(parameter) {
	var tiddlersAndContext = this.getTiddlersAndContext(parameter);

	// Perform the action
	var actionName = parameter.actionName ? parameter.actionName : "addToList";
	var action = config.macros.forEachTiddler.actions[actionName];
	if (!action) {
		this.handleError(parameter.place, "Unknown action '"+actionName+"'.");
		return;
	}

	var actionHandler = action.handler;
	actionHandler(parameter.place, tiddlersAndContext.tiddlers, parameter.actionParameter, tiddlersAndContext.context);
};

// ---------------------------------------------------------------------------
//  The actions 
// ---------------------------------------------------------------------------

// Internal.
//
// --- The addToList Action -----------------------------------------------
//
config.macros.forEachTiddler.actions.addToList.handler = function(place, tiddlers, parameter, context) {
	// Parse the parameter
	var p = 0;

	// Check for extra parameters
	if (parameter.length > p) {
		config.macros.forEachTiddler.createExtraParameterErrorElement(place, "addToList", parameter, p);
		return;
	}

	// Perform the action.
	var list = document.createElement("ul");
	place.appendChild(list);
	for (var i = 0; i < tiddlers.length; i++) {
		var tiddler = tiddlers[i];
		var listItem = document.createElement("li");
		list.appendChild(listItem);
		createTiddlyLink(listItem, tiddler.title, true);
	}
};

abego.parseNamedParameter = function(name, parameter, i) {
	var beginExpression = null;
	if ((i < parameter.length) && parameter[i] == name) {
		i++;
		if (i >= parameter.length) {
			throw "Missing text behind '%0'".format([name]);
		}
		
		return config.macros.forEachTiddler.paramEncode(parameter[i]);
	}
	return null;
}

// Internal.
//
// --- The write Action ---------------------------------------------------
//
config.macros.forEachTiddler.actions.write.handler = function(place, tiddlers, parameter, context) {
	// Parse the parameter
	var p = 0;
	if (p >= parameter.length) {
		this.handleError(place, "Missing expression behind 'write'.");
		return;
	}

	var textExpression = config.macros.forEachTiddler.paramEncode(parameter[p]);
	p++;

	// Parse the "begin" option
	var beginExpression = abego.parseNamedParameter("begin", parameter, p);
	if (beginExpression !== null) 
		p += 2;
	var endExpression = abego.parseNamedParameter("end", parameter, p);
	if (endExpression !== null) 
		p += 2;
	var noneExpression = abego.parseNamedParameter("none", parameter, p);
	if (noneExpression !== null) 
		p += 2;

	// Parse the "toFile" option
	var filename = null;
	var lineSeparator = undefined;
	if ((p < parameter.length) && parameter[p] == "toFile") {
		p++;
		if (p >= parameter.length) {
			this.handleError(place, "Filename expected behind 'toFile' of 'write' action.");
			return;
		}
		
		filename = config.macros.forEachTiddler.getLocalPath(config.macros.forEachTiddler.paramEncode(parameter[p]));
		p++;
		if ((p < parameter.length) && parameter[p] == "withLineSeparator") {
			p++;
			if (p >= parameter.length) {
				this.handleError(place, "Line separator text expected behind 'withLineSeparator' of 'write' action.");
				return;
			}
			lineSeparator = config.macros.forEachTiddler.paramEncode(parameter[p]);
			p++;
		}
	}
	
	// Check for extra parameters
	if (parameter.length > p) {
		config.macros.forEachTiddler.createExtraParameterErrorElement(place, "write", parameter, p);
		return;
	}

	// Perform the action.
	var func = config.macros.forEachTiddler.getEvalTiddlerFunction(textExpression, context);
	var count = tiddlers.length;
	var text = "";
	if (count > 0 && beginExpression)
		text += config.macros.forEachTiddler.getEvalTiddlerFunction(beginExpression, context)(undefined, context, count, undefined);
	
	for (var i = 0; i < count; i++) {
		var tiddler = tiddlers[i];
		text += func(tiddler, context, count, i);
	}
	
	if (count > 0 && endExpression)
		text += config.macros.forEachTiddler.getEvalTiddlerFunction(endExpression, context)(undefined, context, count, undefined);

	if (count == 0 && noneExpression) 
		text += config.macros.forEachTiddler.getEvalTiddlerFunction(noneExpression, context)(undefined, context, count, undefined);
		

	if (filename) {
		if (lineSeparator !== undefined) {
			lineSeparator = lineSeparator.replace(/\\n/mg, "\n").replace(/\\r/mg, "\r");
			text = text.replace(/\n/mg,lineSeparator);
		}
		saveFile(filename, convertUnicodeToUTF8(text));
	} else {
		var wrapper = createTiddlyElement(place, "span");
		wikify(text, wrapper, null/* highlightRegExp */, context.inTiddler);
	}
};


// ---------------------------------------------------------------------------
//  Helpers
// ---------------------------------------------------------------------------

// Internal.
//
config.macros.forEachTiddler.createContext = function(placeParam, whereClauseParam, sortClauseParam, sortAscendingParam, actionNameParam, actionParameterParam, scriptText, tiddlyWikiPathParam, inTiddlerParam) {
	return {
		place : placeParam, 
		whereClause : whereClauseParam, 
		sortClause : sortClauseParam, 
		sortAscending : sortAscendingParam, 
		script : scriptText,
		actionName : actionNameParam, 
		actionParameter : actionParameterParam,
		tiddlyWikiPath : tiddlyWikiPathParam,
		inTiddler : inTiddlerParam, // the tiddler containing the <<forEachTiddler ...>> macro call.
		viewerTiddler : config.macros.forEachTiddler.getContainingTiddler(placeParam) // the tiddler showing the forEachTiddler result
	};
};

// Internal.
//
// Returns a TiddlyWiki with the tiddlers loaded from the TiddlyWiki of 
// the given path.
//
config.macros.forEachTiddler.loadTiddlyWiki = function(path, idPrefix) {
	if (!idPrefix) {
		idPrefix = "store";
	}
	var lenPrefix = idPrefix.length;
	
	// Read the content of the given file
	var content = loadFile(this.getLocalPath(path));
	if(content === null) {
		throw "TiddlyWiki '"+path+"' not found.";
	}
	
	var tiddlyWiki = new TiddlyWiki();

	// Starting with TW 2.2 there is a helper function to import the tiddlers
	if (tiddlyWiki.importTiddlyWiki) {
		if (!tiddlyWiki.importTiddlyWiki(content))
			throw "File '"+path+"' is not a TiddlyWiki.";
		tiddlyWiki.dirty = false;
		return tiddlyWiki;
	}
	
	// The legacy code, for TW < 2.2
	
	// Locate the storeArea div's
	var posOpeningDiv = content.indexOf(startSaveArea);
	var posClosingDiv = content.lastIndexOf(endSaveArea);
	if((posOpeningDiv == -1) || (posClosingDiv == -1)) {
		throw "File '"+path+"' is not a TiddlyWiki.";
	}
	var storageText = content.substr(posOpeningDiv + startSaveArea.length, posClosingDiv);
	
	// Create a "div" element that contains the storage text
	var myStorageDiv = document.createElement("div");
	myStorageDiv.innerHTML = storageText;
	myStorageDiv.normalize();
	
	// Create all tiddlers in a new TiddlyWiki
	// (following code is modified copy of TiddlyWiki.prototype.loadFromDiv)
	var store = myStorageDiv.childNodes;
	for(var t = 0; t < store.length; t++) {
		var e = store[t];
		var title = null;
		if(e.getAttribute)
			title = e.getAttribute("tiddler");
		if(!title && e.id && e.id.substr(0,lenPrefix) == idPrefix)
			title = e.id.substr(lenPrefix);
		if(title && title !== "") {
			var tiddler = tiddlyWiki.createTiddler(title);
			tiddler.loadFromDiv(e,title);
		}
	}
	tiddlyWiki.dirty = false;

	return tiddlyWiki;
};


	
// Internal.
//
// Returns a function that has a function body returning the given javaScriptExpression.
// The function has the parameters:
// 
//	 (tiddler, context, count, index)
//
config.macros.forEachTiddler.getEvalTiddlerFunction = function (javaScriptExpression, context) {
	var script = context["script"];
	var functionText = "var theFunction = function(tiddler, context, count, index) { return "+javaScriptExpression+"}";
	var fullText = (script ? script+";" : "")+functionText+";theFunction;";
	return eval(fullText);
};

// Internal.
//
config.macros.forEachTiddler.findTiddlers = function(whereClause, context, tiddlyWiki) {
	var result = [];
	var func = config.macros.forEachTiddler.getEvalTiddlerFunction(whereClause, context);
	tiddlyWiki.forEachTiddler(function(title,tiddler) {
		if (func(tiddler, context, undefined, undefined)) {
			result.push(tiddler);
		}
	});
	return result;
};

// Internal.
//
config.macros.forEachTiddler.createExtraParameterErrorElement = function(place, actionName, parameter, firstUnusedIndex) {
	var message = "Extra parameter behind '"+actionName+"':";
	for (var i = firstUnusedIndex; i < parameter.length; i++) {
		message += " "+parameter[i];
	}
	this.handleError(place, message);
};

// Internal.
//
config.macros.forEachTiddler.sortAscending = function(tiddlerA, tiddlerB) {
	var result = 
		(tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue) 
			? 0
			: (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)
			   ? -1 
			   : +1; 
	return result;
};

// Internal.
//
config.macros.forEachTiddler.sortDescending = function(tiddlerA, tiddlerB) {
	var result = 
		(tiddlerA.forEachTiddlerSortValue == tiddlerB.forEachTiddlerSortValue) 
			? 0
			: (tiddlerA.forEachTiddlerSortValue < tiddlerB.forEachTiddlerSortValue)
			   ? +1 
			   : -1; 
	return result;
};

// Internal.
//
config.macros.forEachTiddler.sortTiddlers = function(tiddlers, sortClause, ascending, context) {
	// To avoid evaluating the sortClause whenever two items are compared 
	// we pre-calculate the sortValue for every item in the array and store it in a 
	// temporary property ("forEachTiddlerSortValue") of the tiddlers.
	var func = config.macros.forEachTiddler.getEvalTiddlerFunction(sortClause, context);
	var count = tiddlers.length;
	var i;
	for (i = 0; i < count; i++) {
		var tiddler = tiddlers[i];
		tiddler.forEachTiddlerSortValue = func(tiddler,context, undefined, undefined);
	}

	// Do the sorting
	tiddlers.sort(ascending ? this.sortAscending : this.sortDescending);

	// Delete the temporary property that holds the sortValue.	
	for (i = 0; i < tiddlers.length; i++) {
		delete tiddlers[i].forEachTiddlerSortValue;
	}
};


// Internal.
//
config.macros.forEachTiddler.trace = function(message) {
	displayMessage(message);
};

// Internal.
//
config.macros.forEachTiddler.traceMacroCall = function(place,macroName,params) {
	var message ="<<"+macroName;
	for (var i = 0; i < params.length; i++) {
		message += " "+params[i];
	}
	message += ">>";
	displayMessage(message);
};


// Internal.
//
// Creates an element that holds an error message
// 
config.macros.forEachTiddler.createErrorElement = function(place, exception) {
	var message = (exception.description) ? exception.description : exception.toString();
	return createTiddlyElement(place,"span",null,"forEachTiddlerError","<<forEachTiddler ...>>: "+message);
};

// Internal.
//
// @param place [may be null]
//
config.macros.forEachTiddler.handleError = function(place, exception) {
	if (place) {
		this.createErrorElement(place, exception);
	} else {
		throw exception;
	}
};

// Internal.
//
// Encodes the given string.
//
// Replaces 
//	 "$))" to ">>"
//	 "$)" to ">"
//
config.macros.forEachTiddler.paramEncode = function(s) {
	var reGTGT = new RegExp("\\$\\)\\)","mg");
	var reGT = new RegExp("\\$\\)","mg");
	return s.replace(reGTGT, ">>").replace(reGT, ">");
};

// Internal.
//
// Returns the given original path (that is a file path, starting with "file:")
// as a path to a local file, in the systems native file format.
//
// Location information in the originalPath (i.e. the "#" and stuff following)
// is stripped.
// 
config.macros.forEachTiddler.getLocalPath = function(originalPath) {
	// Remove any location part of the URL
	var hashPos = originalPath.indexOf("#");
	if(hashPos != -1)
		originalPath = originalPath.substr(0,hashPos);
	// Convert to a native file format assuming
	// "file:///x:/path/path/path..." - pc local file --> "x:\path\path\path..."
	// "file://///server/share/path/path/path..." - FireFox pc network file --> "\\server\share\path\path\path..."
	// "file:///path/path/path..." - mac/unix local file --> "/path/path/path..."
	// "file://server/share/path/path/path..." - pc network file --> "\\server\share\path\path\path..."
	var localPath;
	if(originalPath.charAt(9) == ":") // pc local file
		localPath = unescape(originalPath.substr(8)).replace(new RegExp("/","g"),"\\");
	else if(originalPath.indexOf("file://///") === 0) // FireFox pc network file
		localPath = "\\\\" + unescape(originalPath.substr(10)).replace(new RegExp("/","g"),"\\");
	else if(originalPath.indexOf("file:///") === 0) // mac/unix local file
		localPath = unescape(originalPath.substr(7));
	else if(originalPath.indexOf("file:/") === 0) // mac/unix local file
		localPath = unescape(originalPath.substr(5));
	else // pc network file
		localPath = "\\\\" + unescape(originalPath.substr(7)).replace(new RegExp("/","g"),"\\");	
	return localPath;
};

// ---------------------------------------------------------------------------
// Stylesheet Extensions (may be overridden by local StyleSheet)
// ---------------------------------------------------------------------------
//
setStylesheet(
	".forEachTiddlerError{color: #ffffff;background-color: #880000;}",
	"forEachTiddler");

//============================================================================
// End of forEachTiddler Macro
//============================================================================


//============================================================================
// String.startsWith Function
//============================================================================
//
// Returns true if the string starts with the given prefix, false otherwise.
//
version.extensions["String.startsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.startsWith = function(prefix) {
	var n =  prefix.length;
	return (this.length >= n) && (this.slice(0, n) == prefix);
};



//============================================================================
// String.endsWith Function
//============================================================================
//
// Returns true if the string ends with the given suffix, false otherwise.
//
version.extensions["String.endsWith"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.endsWith = function(suffix) {
	var n = suffix.length;
	return (this.length >= n) && (this.right(n) == suffix);
};


//============================================================================
// String.contains Function
//============================================================================
//
// Returns true when the string contains the given substring, false otherwise.
//
version.extensions["String.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
String.prototype.contains = function(substring) {
	return this.indexOf(substring) >= 0;
};

//============================================================================
// Array.indexOf Function
//============================================================================
//
// Returns the index of the first occurance of the given item in the array or 
// -1 when no such item exists.
//
// @param item [may be null]
//
version.extensions["Array.indexOf"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.indexOf = function(item) {
	for (var i = 0; i < this.length; i++) {
		if (this[i] == item) {
			return i;
		}
	}
	return -1;
};

//============================================================================
// Array.contains Function
//============================================================================
//
// Returns true when the array contains the given item, otherwise false. 
//
// @param item [may be null]
//
version.extensions["Array.contains"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.contains = function(item) {
	return (this.indexOf(item) >= 0);
};

//============================================================================
// Array.containsAny Function
//============================================================================
//
// Returns true when the array contains at least one of the elements 
// of the item. Otherwise (or when items contains no elements) false is returned.
//
version.extensions["Array.containsAny"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.containsAny = function(items) {
	for(var i = 0; i < items.length; i++) {
		if (this.contains(items[i])) {
			return true;
		}
	}
	return false;
};


//============================================================================
// Array.containsAll Function
//============================================================================
//
// Returns true when the array contains all the items, otherwise false.
// 
// When items is null false is returned (even if the array contains a null).
//
// @param items [may be null] 
//
version.extensions["Array.containsAll"] = {major: 1, minor: 0, revision: 0, date: new Date(2005,11,20), provider: "http://tiddlywiki.abego-software.de"};
//
Array.prototype.containsAll = function(items) {
	for(var i = 0; i < items.length; i++) {
		if (!this.contains(items[i])) {
			return false;
		}
	}
	return true;
};


} // of "install only once"

// Used Globals (for JSLint) ==============
// ... DOM
/*global 	document */
// ... TiddlyWiki Core
/*global 	convertUnicodeToUTF8, createTiddlyElement, createTiddlyLink, 
			displayMessage, endSaveArea, hasClass, loadFile, saveFile, 
			startSaveArea, store, wikify */
//}}}


/***
!Licence and Copyright
Copyright (c) abego Software ~GmbH, 2005 ([[www.abego-software.de|http://www.abego-software.de]])

Redistribution and use in source and binary forms, with or without modification,
are permitted provided that the following conditions are met:

Redistributions of source code must retain the above copyright notice, this
list of conditions and the following disclaimer.

Redistributions in binary form must reproduce the above copyright notice, this
list of conditions and the following disclaimer in the documentation and/or other
materials provided with the distribution.

Neither the name of abego Software nor the names of its contributors may be
used to endorse or promote products derived from this software without specific
prior written permission.

THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
DAMAGE.
***/
<!--{{{-->
<div class='toolbar' macro='toolbar +saveTiddler  -cancelTiddler deleteTiddler'></div>
<div class='title' macro='view title'></div>
<div class='editor' macro='edit title'></div>
<div macro='annotations'></div>
<div class='editor' macro='easyEdit text'></div>
<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>
<!--}}}-->
/***
|Name|HTMLFormattingPlugin|
|Source|http://www.TiddlyTools.com/#HTMLFormattingPlugin|
|Documentation|http://www.TiddlyTools.com/#HTMLFormattingPluginInfo|
|Version|2.1.5|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|'HTML' formatter|
|Description|embed wiki syntax formatting inside of HTML content|
The shorthand Wiki-style formatting syntax of ~TiddlyWiki is very convenient and enables most content to be reasonably well presented. However, there are times when tried-and-true HTML formatting syntax allows more more precise control of the content display.  When HTML formatting syntax is embedded within a tiddler (in between {{{<}}}{{{html>}}} and {{{<}}}{{{/html>}}} markers) TiddlyWiki passes this content to the browser for processing as 'native' HTML.  However, TiddlyWiki does not also process the HTML source content for any embedded wiki-formatting syntax it may contain.  This means that while you can use HTML formatted content, you cannot mix wiki-formatted content within the HTML formatting.

The ~HTMLFormatting plugin allows you to freely ''mix wiki-style formatting syntax within HTML formatted content'' by extending the action of the standard TiddlyWiki formatting handler.
!!!!!Documentation
>see [[HTMLFormattingPluginInfo]]
!!!!!Revisions
<<<
2008.01.08 [*.*.*] plugin size reduction: documentation moved to HTMLFormattingInfo
2007.12.04 [*.*.*] update for TW2.3.0: replaced deprecated core functions, regexps, and macros
2007.06.14 [2.1.5] in formatter, removed call to e.normalize().  Creates an INFINITE RECURSION error in Safari!!!!
2006.09.10 [2.1.4] update formatter for 2.1 compatibility (use this.lookaheadRegExp instead of temp variable)
2006.05.28 [2.1.3] in wikifyTextNodes(), decode the *value* of TEXTAREA nodes, but don't wikify() its children.  (thanks to "ayj" for bug report)
2006.02.19 [2.1.2] in wikifyTextNodes(), put SPAN element into tiddler DOM (replacing text node), BEFORE wikifying the text content.  This ensures that the 'place' passed to any macros is correctly defined when the macro is evaluated, so that calls to story.findContainingTiddler(place) will work as expected. (Thanks for bug report from GeoffSlocock)
2006.02.05 [2.1.1] wrapped wikifier hijack in init function to eliminate globals and avoid FireFox 1.5.0.1 crash bug when referencing globals
2005.12.01 [2.1.0] don't wikify #TEXT nodes inside SELECT and TEXTAREA elements
2005.11.06 [2.0.1] code cleanup
2005.10.31 [2.0.0] replaced hijack wikify() with hijack config.formatters["html"] and simplified recursive WikifyTextNodes() code
2005.10.09 [1.0.2] combined documentation and code into a single tiddler
2005.08.05 [1.0.1] moved HTML and CSS definitions into plugin code instead of using separate tiddlers
2005.07.26 [1.0.1] Re-released as a plugin. Added <{{{html}}}>...</{{{nohtml}}}> and <{{{hide newlines}}}> handling
2005.06.26 [1.0.0] Initial Release (as code adaptation - pre-dates TiddlyWiki plugin architecture!!)
<<<
!!!!!Code
***/
//{{{
version.extensions.HTMLFormatting = {major: 2, minor: 1, revision: 5, date: new Date(2007,6,14)};

// find the formatter for HTML and replace the handler
initHTMLFormatter();
function initHTMLFormatter()
{
	for (var i=0; i<config.formatters.length && config.formatters[i].name!="html"; i++);
	if (i<config.formatters.length)	config.formatters[i].handler=function(w) {
		if (!this.lookaheadRegExp)  // fixup for TW2.0.x
			this.lookaheadRegExp = new RegExp(this.lookahead,"mg");
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
			var html=lookaheadMatch[1];
			// optionally suppress wiki-style literal handling of newlines
			// strip any carriage returns added by Internet Explorer's textarea edit field
			// encode newlines as \n so Internet Explorer's HTML parser won't eat them
			// encode macro brackets (<< and >>) so HTML parser won't eat them
			if (html.indexOf('<hide linebreaks>')!=-1) html=html.replace(/\n/g,' ');
			html=html.replace(/\r/g,'');
			html=html.replace(/\n/g,'\\n');
			html=html.replace(/<</g,'%%(').replace(/>>/g,')%%');
			// create span to hold HTML
			// parse HTML and normalize the results
			// walk node tree and call wikify() on each text node
			var e = createTiddlyElement(w.output,"span");
			e.innerHTML=html;
			// REMOVED: e.normalize();  // THIS CAUSED INFINITE RECURSION IN SAFARI
			wikifyTextNodes(e);
			// advance to next parse position
			w.nextMatch = this.lookaheadRegExp.lastIndex;
		}
	}
}

// wikify text nodes remaining after HTML content is processed (pre-order recursion)
function wikifyTextNodes(theNode)
{
	// textarea node doesn't get wikified, just decoded... 
	if (theNode.nodeName.toLowerCase()=='textarea')
		theNode.value=theNode.value.replace(/\%%\(/g,'<<').replace(/\)\%%/g,'>>').replace(/\\n/g,'\n');
	else for (var i=0;i<theNode.childNodes.length;i++) {
		var theChild=theNode.childNodes.item(i);
		if (theChild.nodeName.toLowerCase()=='option') continue;
		if (theChild.nodeName.toLowerCase()=='select') continue;
		wikifyTextNodes(theChild);
		if (theChild.nodeName=='#text') {
			var txt=theChild.nodeValue;
			// decode macro brackets and newlines
			txt=txt.replace(/\%%\(/g,'<<').replace(/\)\%%/g,'>>').replace(/\\n/g,'\n');
			// replace text node with wikified() span
			var newNode=createTiddlyElement(null,"span");
			theNode.replaceChild(newNode,theChild);
			wikify(txt,newNode);
		}
	}
}
//}}}
<!--{{{-->
<div class='toolbar' macro='toolbar closeTiddler closeOthers +easyEdit > fields syncing permalink references jump'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>

<!--
<div class='tagging' macro='tagging'></div>
-->
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
本文網址 : http://www.zdnet.com.tw/news/software/0,2000085678,20142180,00.htm

ZDNET 新聞專區:Dave Rosenberg  2009/10/21 12:53:01

IBM 與 Ubuntu Linux 幕後推手 Canonical 公司周二宣布,將聯手推動一套結合雲端與 Linux 的桌上型電腦軟體,瞄準小筆電(Netbooks) 與低階 PC 市場。

對癡癡等待 PC 版 Linux 來臨的使用者而言,IBM 與 Canonical 推出的解決方案或許正能投其所好,從必須持續升級 Windows 作業系統的命運中解套。

這套「IBM 智慧工作用戶端軟體」(IBM Client for Smart Work)9月在非洲率先推出,起初專攻新興市場。後來IBM發現,美國和其他市場對這項產品也有興趣,因為這些市場的一些消費者擁有日益老舊的PC,而他們升級至新版Windows作業系統的意願又很低。

美國版的「IBM智慧工作用戶端軟體」內含許多 IBM 產品,包括 Lotus Symphony 的文書處理與試算表軟體、Lotus Notes或LotusLive iNotes 的電子郵件軟體,以及  LotusLive.com的協作工具。和先前推出的方案一樣,這套軟體也在Ubuntu Linux的作業環境下執行。

IBM Linux與開放原始碼事業部副總裁Bob Sutor表示,IBM的目標不在於順便汰舊換新的客戶,而是瞄準那些希望能擺脫PC作業系統與軟體升級周而復始宿命的客戶。

這項新方案有幾點值得注意:

‧IBM與Canonical聯手把Linux引進PC桌面,提供可能被視為次世代精簡型用戶端(thin-client)的解決方案,也就是一方面倚賴雲端服務,但仍採用正規的作業系統,而不是只在網頁瀏覽器的環境下運作。

‧IBM搶攻Windows客層,但採用的策略是該公司擅長的競合(co-opetition)模式。如此一來,不論最後是誰贏得了桌面大戰,IBM都毫髮無傷。Canonical將建立供應這項解決方案的管道,而不是要求個人或企業自行佈署。

‧IBM最近動作頻頻,先是推出架構在雲端上的電子郵件與協作套餐軟體,以迎戰Google Apps,如今又把矛頭直接對準微軟的作業系統。(唐慧文譯)
/***
|Name|ImportTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#ImportTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#ImportTiddlersPluginInfo|
|Version|4.3.3|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|config.macros.importTiddlers.handler|
|Description|interactive controls for import/export with filtering.|
This plugin lets you selectively combine tiddlers from any two TiddlyWiki documents.  An interactive control panel lets you pick a document to import from, and then select which tiddlers to import, with prompting for skip, rename, merge or replace actions when importing tiddlers that match existing titles.  Automatically add tags to imported tiddlers so they are easy to find later on.  Generates a detailed report of import 'history' in ImportedTiddlers.
***/
// // ''MACRO DEFINITION''
//{{{
// Version
version.extensions.importTiddlers = {major: 4, minor: 3, revision: 3, date: new Date(2008,8,12)};

// add ImportTiddlerPlugin controls to built-in backstage import task
if (config.tasks) { // TW2.2 or above
	config.tasks.importTask.content="<<tiddler ImportTiddlers>>"
}

// IE needs explicit global scoping for functions/vars called from browser events
window.onClickImportButton=onClickImportButton;
window.refreshImportList=refreshImportList;

// default cookie/option values
if (!config.options.chkImportReport) config.options.chkImportReport=true;

// default shadow definition
config.shadowTiddlers.ImportTiddlers="Use ~TiddlyWiki built-in importer (below) or, ";
config.shadowTiddlers.ImportTiddlers+="<<importTiddlers link 'Use ImportTiddlersPlugin control panel...'>>\n";
config.shadowTiddlers.ImportTiddlers+="<<importTiddlers core>>";

merge(config.macros.importTiddlers,{
	label: "import tiddlers",
	prompt: "Copy tiddlers from another document",
	openMsg: "Opening %0",
	openErrMsg: "Could not open %0 - error=%1",
	readMsg: "Read %0 bytes from %1",
	foundMsg: "Found %0 tiddlers in %1",
	filterMsg: "Filtered %0 tiddlers matching '%1'",
	summaryMsg: "%0 tiddler%1 in the list",
	summaryFilteredMsg: "%0 of %1 tiddler%2 in the list",
	plural: "s are",
	single: " is",
	countMsg: "%0 tiddlers selected for import",
	processedMsg: "Processed %0 tiddlers",
	importedMsg: "Imported %0 of %1 tiddlers from %2",
	loadText: "please load a document...",
	closeText: "close",	// text for close button when file is loaded
	doneText: "done",	// text for close button when file is not loaded
	startText: "import",	// text for import button
	stopText: "stop",	// text for import button while importing
	local: true,		// default to import from local file
	src: "",		// path/filename or URL of document to import (retrieved from SiteUrl tiddler)
	proxy: "",		// URL for remote proxy script (retrieved from SiteProxy tiddler)
	useProxy: false,	// use specific proxy script in front of remote URL
	inbound: null,		// hash-indexed array of tiddlers from other document
	newTags: "",		// text of tags added to imported tiddlers
	addTags: true,		// add new tags to imported tiddlers
	listsize: 10,		// # of lines to show in imported tiddler list
	importTags: true,	// include tags from remote source document when importing a tiddler
	keepTags: true,		// retain existing tags when replacing a tiddler
	sync: false,		// add 'server' fields to imported tiddlers (for sync function)
	lastFilter: "",		// most recent filter (URL hash) applied
	lastAction: null,	// most recent collision button performed
	index: 0,		// current processing index in import list
	sort: ""		// sort order for imported tiddler listbox
});

if (config.macros.importTiddlers.coreHandler==undefined)
	config.macros.importTiddlers.coreHandler=config.macros.importTiddlers.handler; // save built-in handler
config.macros.importTiddlers.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
	if (!params[0] || params[0].toLowerCase()=='core') { // default to built in
		if (config.macros.importTiddlers.coreHandler)
			config.macros.importTiddlers.coreHandler.apply(this,arguments);
		else 
			createTiddlyButton(place,this.label,this.prompt,onClickImportMenu);
	} else if (params[0]=='link') { // show link to floating panel
		createTiddlyButton(place,params[1]||this.label,params[2]||this.prompt,onClickImportMenu);
	} else if (params[0]=='inline') {// show panel as INLINE tiddler content
		createImportPanel(place);
		document.getElementById("importPanel").style.position="static";
		document.getElementById("importPanel").style.display="block";
	} else if (config.macros.loadTiddlers)
		config.macros.loadTiddlers.handler(place,macroName,params); // any other params: loadtiddlers
}

// // ''INTERFACE DEFINITION''
// // Handle link click to create/show/hide control panel
//{{{
function onClickImportMenu(e)
{
	if (!e) var e = window.event;
	var parent=resolveTarget(e).parentNode;
	var panel = document.getElementById("importPanel");
	if (panel==undefined || panel.parentNode!=parent)
		panel=createImportPanel(parent);
	var isOpen = panel.style.display=="block";
	if(config.options.chkAnimate)
		anim.startAnimating(new Slider(panel,!isOpen,e.shiftKey || e.altKey,"none"));
	else
		panel.style.display = isOpen ? "none" : "block" ;
	e.cancelBubble = true;
	if (e.stopPropagation) e.stopPropagation();
	return(false);
}
//}}}

// // Create control panel: HTML, CSS
//{{{
function createImportPanel(place) {
	var cmi=config.macros.importTiddlers; // abbreviation
	var panel=document.getElementById("importPanel");
	if (panel) { panel.parentNode.removeChild(panel); }
	setStylesheet(cmi.css,"importTiddlers");
	panel=createTiddlyElement(place,"span","importPanel",null,null)
	panel.innerHTML=cmi.html;
	refreshImportList();
	var siteURL=store.getTiddlerText("SiteUrl"); if (!siteURL) siteURL="";
	document.getElementById("importSourceURL").value=siteURL;
	cmi.src=siteURL;
	var siteProxy=store.getTiddlerText("SiteProxy"); if (!siteProxy) siteProxy="SiteProxy";
	document.getElementById("importSiteProxy").value=siteProxy;
	cmi.proxy=siteProxy;
	if (config.browser.isGecko) { // FF3 FIXUP
		document.getElementById("fileImportSource").style.display="none";
		document.getElementById("importLocalPanelFix").style.display="block";
	}
	return panel;
}
//}}}

// // CSS
//{{{
config.macros.importTiddlers.css = '\
#importPanel {\
	display: none; position:absolute; z-index:11; width:45em; right:105%; top:3em;\
	background-color: #eee; color:#000; font-size: 10pt; line-height:110%;\
	border:1px solid black; border-bottom-width: 3px; border-right-width: 3px;\
	padding: 0.5em; margin:0em; -moz-border-radius:1em;\
}\
#importPanel a, #importPanel td a { color:#009; display:inline; margin:0px; padding:1px; }\
#importPanel table { width:100%; border:0px; padding:0px; margin:0px; font-size:10pt; line-height:110%; background:transparent; }\
#importPanel tr { border:0px;padding:0px;margin:0px; background:transparent; }\
#importPanel td { color:#000; border:0px;padding:0px;margin:0px; background:transparent; }\
#importPanel select { width:100%;margin:0px;font-size:10pt;line-height:110%;}\
#importPanel input  { width:98%;padding:0px;margin:0px;font-size:10pt;line-height:110%}\
#importPanel .box { border:1px solid #000; background-color:#eee; padding:3px 5px; margin-bottom:5px; -moz-border-radius:5px;}\
#importPanel .topline { border-top:1px solid #999; padding-top:2px; margin-top:2px; }\
#importPanel .rad { width:auto; }\
#importPanel .chk { width:auto; margin:1px;border:0; }\
#importPanel .btn { width:auto; }\
#importPanel .btn1 { width:98%; }\
#importPanel .btn2 { width:48%; }\
#importPanel .btn3 { width:32%; }\
#importPanel .btn4 { width:23%; }\
#importPanel .btn5 { width:19%; }\
#importPanel .importButton { padding: 0em; margin: 0px; font-size:10pt; }\
#importPanel .importListButton { padding:0em 0.25em 0em 0.25em; color: #000000; display:inline }\
#backstagePanel #importPanel { left:10%; right:auto; }\
';
//}}}

// // HTML 
//{{{
config.macros.importTiddlers.html = '\
<!-- source and report -->\
<table><tr><td align=left>\
	import from\
	<input type="radio" class="rad" name="importFrom" id="importFromFile" value="file" CHECKED\
		onclick="onClickImportButton(this,event)" title="show file controls"> local file\
	<input type="radio" class="rad" name="importFrom" id="importFromWeb"  value="http"\
		onclick="onClickImportButton(this,event)" title="show web controls"> web server\
</td><td align=right>\
	<input type=checkbox class="chk" id="chkImportReport" checked\
		onClick="config.options[\'chkImportReport\']=this.checked;"> create report\
</td></tr></table>\
\
<div class="box" id="importSourcePanel" style="margin:.5em">\
<div id="importLocalPanel" style="display:block;margin-bottom:2px;"><!-- import from local file  -->\
enter or browse for source path/filename<br>\
<input type="file" id="fileImportSource" size=57 style="width:100%"\
	onKeyUp="config.macros.importTiddlers.src=this.value"\
	onChange="config.macros.importTiddlers.src=this.value;document.getElementById(\'importLoad\').onclick()">\
<div id="importLocalPanelFix" style="display:none"><!-- FF3 FIXUP -->\
	<input type="text" id="fileImportSourceFix" style="width:90%"\
		title="Enter a path/file to import"\
		onKeyUp="config.macros.importTiddlers.src=this.value"\
		onChange="config.macros.importTiddlers.src=this.value; document.getElementById(\'importLoad\').onclick()">\
	<input type="button" id="fileImportSourceFixButton" style="width:7%" value="..."\
		title="Select a path/file to import"\
		onClick="var r=config.macros.importTiddlers.askForFilename(this); if (!r||!r.length) return;\
			document.getElementById(\'fileImportSourceFix\').value=r;\
			config.macros.importTiddlers.src=r;\
			document.getElementById(\'importLoad\').onclick()">\
</div><!--end FF3 FIXUP-->\
</div><!--end local-->\
<div id="importHTTPPanel" style="display:none;margin-bottom:2px;"><!-- import from http server -->\
<table><tr><td align=left>\
	enter a URL or <a href="javascript:;" id="importSelectFeed"\
		onclick="onClickImportButton(this,event)" title="select a pre-defined \'systemServer\' URL">\
		select a server</a><br>\
</td><td align=right>\
	<input type="checkbox" class="chk" id="importUsePassword"\
		onClick="config.macros.importTiddlers.usePassword=this.checked;\
			config.macros.importTiddlers.showPanel(\'importIDPWPanel\',this.checked,true);">password\
	<input type="checkbox" class="chk" id="importUseProxy"\
		onClick="config.macros.importTiddlers.useProxy=this.checked;\
			config.macros.importTiddlers.showPanel(\'importSiteProxy\',this.checked,true);">proxy\
</td></tr></table>\
<input type="text" id="importSiteProxy" style="display:none;margin-bottom:1px" onfocus="this.select()" value="SiteProxy"\
	onKeyUp="config.macros.importTiddlers.proxy=this.value"\
	onChange="config.macros.importTiddlers.proxy=this.value;">\
<input type="text" id="importSourceURL" onfocus="this.select()" value="SiteUrl"\
	onKeyUp="config.macros.importTiddlers.src=this.value"\
	onChange="config.macros.importTiddlers.src=this.value;">\
<div id="importIDPWPanel" style="text-align:center;margin-top:2px;display:none";>\
username: <input type=text id="txtImportID" style="width:25%" \
	onChange="config.options.txtRemoteUsername=this.value;">\
 password: <input type=password id="txtImportPW" style="width:25%" \
	onChange="config.options.txtRemotePassword=this.value;">\
</div><!--end idpw-->\
</div><!--end http-->\
</div><!--end source-->\
\
<div class="box" id="importSelectPanel" style="display:none;margin:.5em;">\
<table><tr><td align=left>\
select:\
<a href="javascript:;" id="importSelectAll"\
	onclick="onClickImportButton(this);return false;" title="SELECT all tiddlers">\
	all</a>\
&nbsp;<a href="javascript:;" id="importSelectNew"\
	onclick="onClickImportButton(this);return false;" title="SELECT tiddlers not already in destination document">\
	added</a>\
&nbsp;<a href="javascript:;" id="importSelectChanges"\
	onclick="onClickImportButton(this);return false;" title="SELECT tiddlers that have been updated in source document">\
	changes</a>\
&nbsp;<a href="javascript:;" id="importSelectDifferences"\
	onclick="onClickImportButton(this);return false;" title="SELECT tiddlers that have been added or are different from existing tiddlers">\
	differences</a>\
</td><td align=right>\
<a href="javascript:;" id="importListSmaller"\
	onclick="onClickImportButton(this);return false;" title="SHRINK list size">\
	&nbsp;&#150;&nbsp;</a>\
<a href="javascript:;" id="importListLarger"\
	onclick="onClickImportButton(this);return false;" title="GROW list size">\
	&nbsp;+&nbsp;</a>\
<a href="javascript:;" id="importListMaximize"\
	onclick="onClickImportButton(this);return false;" title="MAXIMIZE/RESTORE list size">\
	&nbsp;=&nbsp;</a>\
</td></tr></table>\
<select id="importList" size=20 multiple\
	onchange="setTimeout(\'refreshImportList(\'+this.selectedIndex+\')\',1)">\
	<!-- NOTE: delay refresh so list is updated AFTER onchange event is handled -->\
</select>\
<div style="text-align:center">\
	<a href="javascript:;"\
		title="click for help using filters..."\
		onclick="alert(\'A filter consists of one or more space-separated combinations of:\\n\\ntiddler titles\\ntag:[[tagvalue]]\\ntag:[[tag expression]] (requires MatchTagsPlugin)\\nstory:[[TiddlerName]]\\nsearch:[[searchtext]]\\n\\nUse a blank filter for all tiddlers.\')"\
	>filter</a>\
	<input type="text" id="importLastFilter" style="margin-bottom:1px; width:65%"\
		title="Enter a combination of one or more filters. Use a blank filter for all tiddlers."\
		onfocus="this.select()" value=""\
		onKeyUp="config.macros.importTiddlers.lastFilter=this.value"\
		onChange="config.macros.importTiddlers.lastFilter=this.value;">\
	<input type="button" id="importApplyFilter" style="width:20%" value="apply"\
		title="filter list of tiddlers to include only those that match certain criteria"\
		onclick="onClickImportButton(this)">\
	</div>\
</div><!--end select-->\
\
<div class="box" id="importOptionsPanel" style="text-align:center;margin:.5em;display:none;">\
	apply tags: <input type=checkbox class="chk" id="chkImportTags" checked\
		onClick="config.macros.importTiddlers.importTags=this.checked;">from source&nbsp;\
	<input type=checkbox class="chk" id="chkKeepTags" checked\
		onClick="config.macros.importTiddlers.keepTags=this.checked;">keep existing&nbsp;\
	<input type=checkbox class="chk" id="chkAddTags" \
		onClick="config.macros.importTiddlers.addTags=this.checked;\
			config.macros.importTiddlers.showPanel(\'txtNewTags\',this.checked,true);\
			if (this.checked) document.getElementById(\'txtNewTags\').focus();">add tags<br>\
	<input type=text id="txtNewTags" style="margin-top:4px;display:none;" size=15\ onfocus="this.select()" \
		title="enter tags to be added to imported tiddlers" \
		onKeyUp="config.macros.importTiddlers.newTags=this.value;\
		document.getElementById(\'chkAddTags\').checked=this.value.length>0;" autocomplete=off>\
	<nobr><input type=checkbox class="chk" id="chkSync" \
		onClick="config.macros.importTiddlers.sync=this.checked;">\
		link imported tiddlers to source document (for sync later)</nobr>\
</div><!--end options-->\
\
<div id="importButtonPanel" style="text-align:center">\
	<input type=button id="importLoad"	class="importButton btn3" value="open"\
		title="load listbox with tiddlers from source document"\
		onclick="onClickImportButton(this)">\
	<input type=button id="importOptions"	class="importButton btn3" value="options..."\
		title="set options for tags, sync, etc."\
		onclick="onClickImportButton(this)">\
	<input type=button id="importStart"	class="importButton btn3" value="import"\
		title="start/stop import of selected source tiddlers into current document"\
		onclick="onClickImportButton(this)">\
	<input type=button id="importClose"	class="importButton btn3" value="done"\
		title="clear listbox or hide control panel"\
		onclick="onClickImportButton(this)">\
</div>\
\
<div class="none" id="importCollisionPanel" style="display:none;margin:.5em 0 .5em .5em;">\
	<table><tr><td style="width:65%" align="left">\
		<table><tr><td align=left>\
			tiddler already exists:\
		</td><td align=right>\
			<input type=checkbox class="chk" id="importApplyToAll" \
			onclick="document.getElementById(\'importRename\').disabled=this.checked;"\
			checked>apply to all\
		</td></tr></table>\
		<input type=text id="importNewTitle" size=15 autocomplete=off">\
	</td><td style="width:34%" align="center">\
		<input type=button id="importMerge"\
			class="importButton" style="width:47%" value="merge"\
			title="append the incoming tiddler to the existing tiddler"\
			onclick="onClickImportButton(this)"><!--\
		--><input type=button id="importSkip"\
			class="importButton" style="width:47%" value="skip"\
			title="do not import this tiddler"\
			onclick="onClickImportButton(this)"><!--\
		--><br><input type=button id="importRename"\
			class="importButton" style="width:47%" value="rename"\
			title="rename the incoming tiddler"\
			onclick="onClickImportButton(this)"><!--\
		--><input type=button id="importReplace"\
			class="importButton" style="width:47%" value="replace"\
			title="discard the existing tiddler"\
			onclick="onClickImportButton(this)">\
	</td></tr></table>\
</div><!--end collision-->\
';
//}}}

// // Control interactions
//{{{
function onClickImportButton(which,event)
{
	var cmi=config.macros.importTiddlers; // abbreviation

	var list = document.getElementById('importList');
	if (!list) return;
	var thePanel = document.getElementById('importPanel');
	var theCollisionPanel = document.getElementById('importCollisionPanel');
	var theNewTitle = document.getElementById('importNewTitle');
	var count=0;
	switch (which.id)
		{
		case 'importFromFile':	// show local panel
		case 'importFromWeb':	// show HTTP panel
			cmi.local=(which.id=='importFromFile');
			cmi.showPanel('importLocalPanel',cmi.local);
			cmi.showPanel('importHTTPPanel',!cmi.local);
			break;
		case 'importOptions':	// show/hide options panel
			cmi.showPanel('importOptionsPanel',document.getElementById('importOptionsPanel').style.display=='none');
			break;
		case 'fileImportSource':
		case 'importLoad':		// load import source into hidden frame
			importReport();		// if an import was in progress, generate a report
			cmi.inbound=null;	// clear the imported tiddler buffer
			refreshImportList();	// reset/resize the listbox
			if (cmi.src=="") break;
			// Load document, read it's DOM and fill the list
			cmi.loadRemoteFile(cmi.src,cmi.filterTiddlerList);
			break;
		case 'importSelectFeed':	// select a pre-defined systemServer feed URL
			var p=Popup.create(which); if (!p) return;
			var tids=store.getTaggedTiddlers('systemServer');
			if (!tids.length)
				createTiddlyText(createTiddlyElement(p,'li'),'no pre-defined server feeds');
			for (var t=0; t<tids.length; t++) {
				var u=store.getTiddlerSlice(tids[t].title,"URL");
				var d=store.getTiddlerSlice(tids[t].title,"Description");
				if (!d||!d.length) d=store.getTiddlerSlice(tids[t].title,"description");
				if (!d||!d.length) d=u;
				createTiddlyButton(createTiddlyElement(p,'li'),tids[t].title,d,
					function(){
						var u=this.getAttribute('url');
						document.getElementById('importSourceURL').value=u;
						config.macros.importTiddlers.src=u;
						document.getElementById('importLoad').onclick();
					},
					null,null,null,{url:u});
			}
			Popup.show(p,false);
			event.cancelBubble = true;
			if (event.stopPropagation) event.stopPropagation();
			return(false);
			// create popup with feed list
			// onselect, insert feed URL into input field.
			break;
		case 'importSelectAll':		// select all tiddler list items (i.e., not headings)
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				if (list.options[t].value=="") continue;
				list.options[t].selected=true;
				count++;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			document.getElementById('importStart').disabled=!count;
			break;
		case 'importSelectNew':		// select tiddlers not in current document
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				list.options[t].selected=false;
				if (list.options[t].value=="") continue;
				list.options[t].selected=!store.tiddlerExists(list.options[t].value);
				count+=list.options[t].selected?1:0;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			document.getElementById('importStart').disabled=!count;
			break;
		case 'importSelectChanges':		// select tiddlers that are updated from existing tiddlers
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				list.options[t].selected=false;
				if (list.options[t].value==""||!store.tiddlerExists(list.options[t].value)) continue;
				for (var i=0; i<cmi.inbound.length; i++) // find matching inbound tiddler
					{ var inbound=cmi.inbound[i]; if (inbound.title==list.options[t].value) break; }
				list.options[t].selected=(inbound.modified-store.getTiddler(list.options[t].value).modified>0); // updated tiddler
				count+=list.options[t].selected?1:0;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			document.getElementById('importStart').disabled=!count;
			break;
		case 'importSelectDifferences':		// select tiddlers that are new or different from existing tiddlers
			importReport();		// if an import was in progress, generate a report
			for (var t=0,count=0; t < list.options.length; t++) {
				list.options[t].selected=false;
				if (list.options[t].value=="") continue;
				if (!store.tiddlerExists(list.options[t].value)) { list.options[t].selected=true; count++; continue; }
				for (var i=0; i<cmi.inbound.length; i++) // find matching inbound tiddler
					{ var inbound=cmi.inbound[i]; if (inbound.title==list.options[t].value) break; }
				list.options[t].selected=(inbound.modified-store.getTiddler(list.options[t].value).modified!=0); // changed tiddler
				count+=list.options[t].selected?1:0;
			}
			clearMessage(); displayMessage(cmi.countMsg.format([count]));
			document.getElementById('importStart').disabled=!count;
			break;
		case 'importApplyFilter':	// filter list to include only matching tiddlers
			importReport();		// if an import was in progress, generate a report
			clearMessage();
			if (!cmi.all) // no tiddlers loaded = "0 selected"
				{ displayMessage(cmi.countMsg.format([0])); return false; }
			var hash=document.getElementById('importLastFilter').value;
			cmi.inbound=cmi.filterByHash("#"+hash,cmi.all);
			refreshImportList();	// reset/resize the listbox
			break;
		case 'importStart':		// initiate the import processing
			importReport();		// if an import was in progress, generate a report
			document.getElementById('importApplyToAll').checked=false;
			document.getElementById('importStart').value=cmi.stopText;
			if (cmi.index>0) cmi.index=-1; // stop processing
			else cmi.index=importTiddlers(0); // or begin processing
			importStopped();
			break;
		case 'importClose':		// unload imported tiddlers or hide the import control panel
			// if imported tiddlers not loaded, close the import control panel
			if (!cmi.inbound) { thePanel.style.display='none'; break; }
			importReport();		// if an import was in progress, generate a report
			cmi.inbound=null;	// clear the imported tiddler buffer
			refreshImportList();	// reset/resize the listbox
			break;
		case 'importSkip':	// don't import the tiddler
			cmi.lastAction=which;
			var theItem	= list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported = cmi.inbound[j];
			theImported.status='skipped after asking';			// mark item as skipped
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index+1);	// resume with NEXT item
			importStopped();
			break;
		case 'importRename':		// change name of imported tiddler
			cmi.lastAction=which;
			var theItem		= list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported		= cmi.inbound[j];
			theImported.status	= 'renamed from '+theImported.title;	// mark item as renamed
			theImported.set(theNewTitle.value,null,null,null,null);		// change the tiddler title
			theItem.value		= theNewTitle.value;			// change the listbox item text
			theItem.text		= theNewTitle.value;			// change the listbox item text
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index);	// resume with THIS item
			importStopped();
			break;
		case 'importMerge':	// join existing and imported tiddler content
			cmi.lastAction=which;
			var theItem	= list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported	= cmi.inbound[j];
			var theExisting	= store.getTiddler(theItem.value);
			var theText	= theExisting.text+'\n----\n^^merged from: ';
			theText		+='[['+cmi.src+'#'+theItem.value+'|'+cmi.src+'#'+theItem.value+']]^^\n';
			theText		+='^^'+theImported.modified.toLocaleString()+' by '+theImported.modifier+'^^\n'+theImported.text;
			var theDate	= new Date();
			var theTags	= theExisting.getTags()+' '+theImported.getTags();
			theImported.set(null,theText,null,theDate,theTags);
			theImported.status   = 'merged with '+theExisting.title;	// mark item as merged
			theImported.status  += ' - '+theExisting.modified.formatString("MM/DD/YYYY 0hh:0mm:0ss");
			theImported.status  += ' by '+theExisting.modifier;
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index);	// resume with this item
			importStopped();
			break;
		case 'importReplace':		// substitute imported tiddler for existing tiddler
			cmi.lastAction=which;
			var theItem		  = list.options[cmi.index];
			for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==theItem.value) break;
			var theImported     = cmi.inbound[j];
			var theExisting	  = store.getTiddler(theItem.value);
			theImported.status  = 'replaces '+theExisting.title;		// mark item for replace
			theImported.status += ' - '+theExisting.modified.formatString("MM/DD/YYYY 0hh:0mm:0ss");
			theImported.status += ' by '+theExisting.modifier;
			theCollisionPanel.style.display='none';
			cmi.index=importTiddlers(cmi.index);	// resume with THIS item
			importStopped();
			break;
		case 'importListSmaller':		// decrease current listbox size, minimum=5
			if (list.options.length==1) break;
			list.size-=(list.size>5)?1:0;
			cmi.listsize=list.size;
			break;
		case 'importListLarger':		// increase current listbox size, maximum=number of items in list
			if (list.options.length==1) break;
			list.size+=(list.size<list.options.length)?1:0;
			cmi.listsize=list.size;
			break;
		case 'importListMaximize':	// toggle listbox size between current and maximum
			if (list.options.length==1) break;
			list.size=(list.size==list.options.length)?cmi.listsize:list.options.length;
			break;
		}
}
//}}}

// // toggle panel
//{{{
config.macros.importTiddlers.showPanel=function(place,show,skipAnim) {
	if (typeof place == "string") var place=document.getElementById(place);
	if (!place||!place.style) return;
	if(!skipAnim && anim && config.options.chkAnimate) anim.startAnimating(new Slider(place,show,false,"none"));
	else place.style.display=show?"block":"none";
}
//}}}

// // refresh listbox
//{{{
function refreshImportList(selectedIndex)
{
	var cmi=config.macros.importTiddlers; // abbreviation

	var list  = document.getElementById("importList");
	if (!list) return;
	// if nothing to show, reset list content and size
	if (!cmi.inbound) 
	{
		while (list.length > 0) { list.options[0] = null; }
		list.options[0]=new Option(cmi.loadText,"",false,false);
		list.size=cmi.listsize;

		// toggle buttons and panels
		document.getElementById('importLoad').disabled=false;
		document.getElementById('importLoad').style.display='inline';
		document.getElementById('importStart').disabled=true;
		document.getElementById('importOptions').disabled=true;
		document.getElementById('importOptions').style.display='none';
		document.getElementById('fileImportSource').disabled=false;
		document.getElementById('importFromFile').disabled=false;
		document.getElementById('importFromWeb').disabled=false;
		document.getElementById('importStart').value=cmi.startText;
		document.getElementById('importClose').value=cmi.doneText;
		document.getElementById('importSelectPanel').style.display='none';
		document.getElementById('importOptionsPanel').style.display='none';
		return;
	}
	// there are inbound tiddlers loaded...
	// toggle buttons and panels
	document.getElementById('importLoad').disabled=true;
	document.getElementById('importLoad').style.display='none';
	document.getElementById('importOptions').style.display='inline';
	document.getElementById('importOptions').disabled=false;
	document.getElementById('fileImportSource').disabled=true;
	document.getElementById('importFromFile').disabled=true;
	document.getElementById('importFromWeb').disabled=true;
	document.getElementById('importClose').value=cmi.closeText;
	if (document.getElementById('importSelectPanel').style.display=='none')
		cmi.showPanel('importSelectPanel',true);

	// get the sort order
	if (!selectedIndex)   selectedIndex=0;
	if (selectedIndex==0) cmi.sort='title';		// heading
	if (selectedIndex==1) cmi.sort='title';
	if (selectedIndex==2) cmi.sort='modified';
	if (selectedIndex==3) cmi.sort='tags';
	if (selectedIndex>3) {
		// display selected tiddler count
		for (var t=0,count=0; t < list.options.length; t++) {
			if (!list.options[t].selected) continue;
			if (list.options[t].value!="")
				count+=1;
			else { // if heading is selected, deselect it, and then select and count all in section
				list.options[t].selected=false;
				for ( t++; t<list.options.length && list.options[t].value!=""; t++) {
					list.options[t].selected=true;
					count++;
				}
			}
		}
		clearMessage(); displayMessage(cmi.countMsg.format([count]));
	}
	document.getElementById('importStart').disabled=!count;
	if (selectedIndex>3) return; // no refresh needed

	// get the alphasorted list of tiddlers
	var tiddlers=cmi.inbound;
	tiddlers.sort(function (a,b) {if(a['title'] == b['title']) return(0); else return (a['title'] < b['title']) ? -1 : +1; });
	// clear current list contents
	while (list.length > 0) { list.options[0] = null; }
	// add heading and control items to list
	var i=0;
	var indent=String.fromCharCode(160)+String.fromCharCode(160);
	if (cmi.all.length==tiddlers.length)
		var summary=cmi.summaryMsg.format([tiddlers.length,(tiddlers.length!=1)?cmi.plural:cmi.single]);
	else
		var summary=cmi.summaryFilteredMsg.format([tiddlers.length,cmi.all.length,(cmi.all.length!=1)?cmi.plural:cmi.single]);
	list.options[i++]=new Option(summary,"",false,false);
	list.options[i++]=new Option(((cmi.sort=="title"   )?">":indent)+' [by title]',"",false,false);
	list.options[i++]=new Option(((cmi.sort=="modified")?">":indent)+' [by date]',"",false,false);
	list.options[i++]=new Option(((cmi.sort=="tags")?">":indent)+' [by tags]',"",false,false);
	// output the tiddler list
	switch(cmi.sort) {
		case "title":
			for(var t = 0; t < tiddlers.length; t++)
				list.options[i++] = new Option(tiddlers[t].title,tiddlers[t].title,false,false);
			break;
		case "modified":
			// sort descending for newest date first
			tiddlers.sort(function (a,b) {if(a['modified'] == b['modified']) return(0); else return (a['modified'] > b['modified']) ? -1 : +1; });
			var lastSection = "";
			for(var t = 0; t < tiddlers.length; t++) {
				var tiddler = tiddlers[t];
				var theSection = tiddler.modified.toLocaleDateString();
				if (theSection != lastSection) {
					list.options[i++] = new Option(theSection,"",false,false);
					lastSection = theSection;
				}
				list.options[i++] = new Option(indent+indent+tiddler.title,tiddler.title,false,false);
			}
			break;
		case "tags":
			var theTitles = {}; // all tiddler titles, hash indexed by tag value
			var theTags = new Array();
			for(var t=0; t<tiddlers.length; t++) {
				var title=tiddlers[t].title;
				var tags=tiddlers[t].tags;
				if (!tags || !tags.length) {
					if (theTitles["untagged"]==undefined) { theTags.push("untagged"); theTitles["untagged"]=new Array(); }
					theTitles["untagged"].push(title);
				}
				else for(var s=0; s<tags.length; s++) {
					if (theTitles[tags[s]]==undefined) { theTags.push(tags[s]); theTitles[tags[s]]=new Array(); }
					theTitles[tags[s]].push(title);
				}
			}
			theTags.sort();
			for(var tagindex=0; tagindex<theTags.length; tagindex++) {
				var theTag=theTags[tagindex];
				list.options[i++]=new Option(theTag,"",false,false);
				for(var t=0; t<theTitles[theTag].length; t++)
					list.options[i++]=new Option(indent+indent+theTitles[theTag][t],theTitles[theTag][t],false,false);
			}
			break;
		}
	list.selectedIndex=selectedIndex;		  // select current control item
	if (list.size<cmi.listsize) list.size=cmi.listsize;
	if (list.size>list.options.length) list.size=list.options.length;
}

config.macros.importTiddlers.filterTiddlerList=function(success,params,txt,src,xhr) {
	var cmi=config.macros.importTiddlers; // abbreviation
	var src=src.replace(/%20/g," ");
	if (!success) { displayMessage(cmi.openErrMsg.format([src,xhr.status])); return; }
	cmi.all = cmi.readTiddlersFromHTML(txt);
	var count=cmi.all?cmi.all.length:0;
	var querypos=src.lastIndexOf("?"); if (querypos!=-1) src=src.substr(0,querypos);
	displayMessage(cmi.foundMsg.format([count,src]));
	cmi.inbound=cmi.filterByHash(params,cmi.all); // use full URL including hash (if any)
	document.getElementById("importLastFilter").value=cmi.lastFilter;
	window.refreshImportList(0);
}

config.macros.importTiddlers.filterByHash=function(src,tiddlers)
{
	var hashpos=src.lastIndexOf("#"); if (hashpos==-1) return tiddlers;
	var hash=src.substr(hashpos+1); if (!hash.length) return tiddlers;
	var tids=[];
	var params=hash.parseParams("anon",null,true,false,false);
	for (var p=1; p<params.length; p++) {
		switch (params[p].name) {
			case "anon":
			case "open":
				tids.pushUnique(params[p].value);
				break;
			case "tag":
				if (store.getMatchingTiddlers) { // for boolean expressions - see MatchTagsPlugin
					var r=store.getMatchingTiddlers(params[p].value,null,tiddlers);
					for (var t=0; t<r.length; t++) tids.pushUnique(r[t].title);
				} else for (var t=0; t<tiddlers.length; t++)
					if (tiddlers[t].isTagged(params[p].value))
						tids.pushUnique(tiddlers[t].title);
				break;
			case "story":
				for (var t=0; t<tiddlers.length; t++)
					if (tiddlers[t].title==params[p].value) {
						tiddlers[t].changed();
						for (var s=0; s<tiddlers[t].links.length; s++)
							tids.pushUnique(tiddlers[t].links[s]);
						break;
					}
				break;
			case "search":
				for (var t=0; t<tiddlers.length; t++)
					if (tiddlers[t].text.indexOf(params[p].value)!=-1)
						tids.pushUnique(tiddlers[t].title);
				break;
		}
	}
	var matches=[];
	for (var t=0; t<tiddlers.length; t++)
		if (tids.contains(tiddlers[t].title))
			matches.push(tiddlers[t]);
	displayMessage(config.macros.importTiddlers.filterMsg.format([matches.length,hash]));
	config.macros.importTiddlers.lastFilter=hash;
	return matches;
}
//}}}

// // re-entrant processing for handling import with interactive collision prompting
//{{{
function importTiddlers(startIndex)
{
	var cmi=config.macros.importTiddlers; // abbreviation

	if (!cmi.inbound) return -1;

	var list = document.getElementById('importList');
	if (!list) return;
	var t;
	// if starting new import, reset import status flags
	if (startIndex==0)
		for (var t=0;t<cmi.inbound.length;t++)
			cmi.inbound[t].status="";
	for (var i=startIndex; i<list.options.length; i++)
		{
		// if list item is not selected or is a heading (i.e., has no value), skip it
		if ((!list.options[i].selected) || ((t=list.options[i].value)==""))
			continue;
		for (var j=0;j<cmi.inbound.length;j++)
			if (cmi.inbound[j].title==t) break;
		var inbound = cmi.inbound[j];
		var theExisting = store.getTiddler(inbound.title);
		// avoid redundant import for tiddlers that are listed multiple times (when 'by tags')
		if (inbound.status=="added")
			continue;
		// don't import the "ImportedTiddlers" history from the other document...
		if (inbound.title=='ImportedTiddlers')
			continue;
		// if tiddler exists and import not marked for replace or merge, stop importing
		if (theExisting && (inbound.status.substr(0,7)!="replace") && (inbound.status.substr(0,5)!="merge"))
			return i;
		// assemble tags (remote + existing + added)
		var newTags = "";
		if (cmi.importTags)
			newTags+=inbound.getTags()	// import remote tags
		if (cmi.keepTags && theExisting)
			newTags+=" "+theExisting.getTags(); // keep existing tags
		if (cmi.addTags && cmi.newTags.trim().length)
			newTags+=" "+cmi.newTags; // add new tags
		inbound.set(null,null,null,null,newTags.trim());
		// set the status to 'added' (if not already set by the 'ask the user' UI)
		inbound.status=(inbound.status=="")?'added':inbound.status;
		// set sync fields
		if (cmi.sync) {
			if (!inbound.fields) inbound.fields={}; // for TW2.1.x backward-compatibility
			inbound.fields["server.page.revision"]=inbound.modified.convertToYYYYMMDDHHMM();
			inbound.fields["server.type"]="file";
			inbound.fields["server.host"]=(cmi.local?"file://":"")+cmi.src;
		}
		// do the import!
		store.suspendNotifications();
		store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, inbound.tags, inbound.fields, true, inbound.created);
                store.fetchTiddler(inbound.title).created = inbound.created; // force creation date to imported value (needed for TW2.1.x and earlier)
		store.resumeNotifications();
		}
	return(-1);	// signals that we really finished the entire list
}
//}}}

//{{{
function importStopped()
{
	var cmi=config.macros.importTiddlers; // abbreviation
	var list = document.getElementById('importList');
	var theNewTitle = document.getElementById('importNewTitle');
	if (!list) return;
	if (cmi.index==-1){ 
		document.getElementById('importStart').value=cmi.startText;
		importReport();		// import finished... generate the report
	} else {
		// import collision...
		// show the collision panel and set the title edit field
		document.getElementById('importStart').value=cmi.stopText;
		cmi.showPanel('importCollisionPanel',true);
		theNewTitle.value=list.options[cmi.index].value;
		if (document.getElementById('importApplyToAll').checked
			&& cmi.lastAction
			&& cmi.lastAction.id!="importRename") {
			onClickImportButton(cmi.lastAction);
		}
	}
}
//}}}

// // ''REPORT GENERATOR''
//{{{
function importReport()
{
	var cmi=config.macros.importTiddlers; // abbreviation
	if (!cmi.inbound) return;

	// if import was not completed, the collision panel will still be open... close it now.
	var panel=document.getElementById('importCollisionPanel'); if (panel) panel.style.display='none';

	// get the alphasorted list of tiddlers
	var tiddlers = cmi.inbound;
	// gather the statistics
	var count=0; var total=0;
	for (var t=0; t<tiddlers.length; t++) {
		if (!tiddlers[t].status || !tiddlers[t].status.trim().length) continue;
		if (tiddlers[t].status.substr(0,7)!="skipped") count++;
		total++;
	}
	// generate a report
	if (total) displayMessage(cmi.processedMsg.format([total]));
	if (count && config.options.chkImportReport) {
		// get/create the report tiddler
		var theReport = store.getTiddler('ImportedTiddlers');
		if (!theReport) { theReport= new Tiddler(); theReport.title = 'ImportedTiddlers'; theReport.text  = ""; }
		// format the report content
		var now = new Date();
		var newText = "On "+now.toLocaleString()+", "+config.options.txtUserName
		newText +=" imported "+count+" tiddler"+(count==1?"":"s")+" from\n[["+cmi.src+"|"+cmi.src+"]]:\n";
		if (cmi.addTags && cmi.newTags.trim().length)
			newText += "imported tiddlers were tagged with: \""+cmi.newTags+"\"\n";
		newText += "<<<\n";
		for (var t=0; t<tiddlers.length; t++) if (tiddlers[t].status) newText += "#[["+tiddlers[t].title+"]] - "+tiddlers[t].status+"\n";
		newText += "<<<\n";
		// update the ImportedTiddlers content and show the tiddler
		theReport.text	 = newText+((theReport.text!="")?'\n----\n':"")+theReport.text;
		theReport.modifier = config.options.txtUserName;
		theReport.modified = new Date();
                store.saveTiddler(theReport.title, theReport.title, theReport.text, theReport.modifier, theReport.modified, theReport.tags, theReport.fields);
		story.displayTiddler(null,theReport.title,1,null,null,false);
		story.refreshTiddler(theReport.title,1,true);
	}

	// reset status flags
	for (var t=0; t<cmi.inbound.length; t++) cmi.inbound[t].status="";

	// mark document as dirty and let display update as needed
	if (count) { store.setDirty(true); store.notifyAll(); }

	// always show final message when tiddlers were actually loaded
	if (count) displayMessage(cmi.importedMsg.format([count,tiddlers.length,cmi.src.replace(/%20/g," ")]));
}
//}}}

// // File and XMLHttpRequest I/O
//{{{
config.macros.importTiddlers.askForFilename=function(here) {
	var msg=here.title; // use tooltip as dialog box message
	var path=getLocalPath(document.location.href);
	var slashpos=path.lastIndexOf("/"); if (slashpos==-1) slashpos=path.lastIndexOf("\\"); 
	if (slashpos!=-1) path = path.substr(0,slashpos+1); // remove filename from path, leave the trailing slash
	var file="";
	var result="";
	if(window.Components) { // moz
		try {
			netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
			var nsIFilePicker = window.Components.interfaces.nsIFilePicker;
			var picker = Components.classes['@mozilla.org/filepicker;1'].createInstance(nsIFilePicker);
			picker.init(window, msg, nsIFilePicker.modeOpen);
			var thispath = Components.classes['@mozilla.org/file/local;1'].createInstance(Components.interfaces.nsILocalFile);
			thispath.initWithPath(path);
			picker.displayDirectory=thispath;
			picker.defaultExtension='html';
			picker.defaultString=file;
			picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterText|nsIFilePicker.filterHTML);
			if (picker.show()!=nsIFilePicker.returnCancel) var result=picker.file.persistentDescriptor;
		}
		catch(e) { alert('error during local file access: '+e.toString()) }
	}
	else { // IE
		try { // XPSP2 IE only
			var s = new ActiveXObject('UserAccounts.CommonDialog');
			s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|';
			s.FilterIndex=3; // default to HTML files;
			s.InitialDir=path;
			s.FileName=file;
			if (s.showOpen()) var result=s.FileName;
		}
		catch(e) {  // fallback
			var result=prompt(msg,path+file);
		}
	}
	return result;
}

config.macros.importTiddlers.loadRemoteFile = function(src,callback) {
	if (src==undefined || !src.length) return null; // filename is required
	var original=src; // URL as specified
	var hashpos=src.indexOf("#"); if (hashpos!=-1) src=src.substr(0,hashpos); // URL with #... suffix removed (needed for IE)
	clearMessage();
	displayMessage(this.openMsg.format([src.replace(/%20/g," ")]));
	if (src.substr(0,5)!="http:" && src.substr(0,5)!="file:") { // if not a URL, read from local filesystem
		var txt=loadFile(src);
		if (!txt) { // file didn't load, might be relative path.. try fixup
			var pathPrefix=document.location.href;  // get current document path and trim off filename
			var slashpos=pathPrefix.lastIndexOf("/"); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf("\\"); 
			if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
			src=pathPrefix+src;
			if (pathPrefix.substr(0,5)!="http:") src=getLocalPath(src);
			var txt=loadFile(src);
		}
		if (!txt) { // file still didn't load, report error
			displayMessage(config.macros.importTiddlers.openErrMsg.format([src.replace(/%20/g," "),"(filesystem error)"]));
		} else {
			displayMessage(config.macros.importTiddlers.readMsg.format([txt.length,src.replace(/%20/g," ")]));
			if (callback) callback(true,original,convertUTF8ToUnicode(txt),src,null);
		}
	} else {
		var name=config.options.txtRemoteUsername; var pass=config.options.txtRemotePassword;
		var xhr=doHttp("GET",src,null,null,name,pass,callback,original,null)
		if (!xhr) displayMessage(config.macros.importTiddlers.openErrMsg.format([src,"(XMLHTTPRequest error)"]));
	}
}

config.macros.importTiddlers.readTiddlersFromHTML=function(html)
{
	var remoteStore=new TiddlyWiki();
	remoteStore.importTiddlyWiki(html);
	return remoteStore.getTiddlers("title");	
}
//}}}
/***
|''Name:''|IntelliTaggerPlugin|
|''Version:''|1.0.2 (2007-07-25)|
|''Type:''|plugin|
|''Source:''|http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin|
|''Author:''|Udo Borkowski (ub [at] abego-software [dot] de)|
|''Documentation:''|[[IntelliTaggerPlugin Documentation]]|
|''~SourceCode:''|[[IntelliTaggerPlugin SourceCode]]|
|''Licence:''|[[BSD open source license (abego Software)]]|
|''~CoreVersion:''|2.0.8|
|''Browser:''|Firefox 1.5.0.2 or better|
***/
/***
!Version History
* 1.0.2 (2007-07-25): 
** Feature: "Return" key may be used to accept first tag suggestion (beside "Alt-1")
** Bugfix: Keyboard shortcuts (Alt+3 etc.) shifted
* 1.0.1 (2007-05-18): Improvement: Speedup when using TiddlyWikis with many tags
* 1.0.0 (2006-04-26): Initial release

***/
// /%
if(!version.extensions.IntelliTaggerPlugin){if(!window.abego){window.abego={};}if(!abego.internal){abego.internal={};}abego.alertAndThrow=function(s){alert(s);throw s;};if(version.major<2){abego.alertAndThrow("Use TiddlyWiki 2.0.8 or better to run the IntelliTagger Plugin.");}version.extensions.IntelliTaggerPlugin={major:1,minor:0,revision:2,date:new Date(2007,6,25),type:"plugin",source:"http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin",documentation:"[[IntelliTaggerPlugin Documentation]]",sourcecode:"[[IntelliTaggerPlugin SourceCode]]",author:"Udo Borkowski (ub [at] abego-software [dot] de)",licence:"[[BSD open source license (abego Software)]]",tiddlywiki:"Version 2.0.8 or better",browser:"Firefox 1.5.0.2 or better"};abego.createEllipsis=function(_2){var e=createTiddlyElement(_2,"span");e.innerHTML="&hellip;";};abego.isPopupOpen=function(_4){return _4&&_4.parentNode==document.body;};abego.openAsPopup=function(_5){if(_5.parentNode!=document.body){document.body.appendChild(_5);}};abego.closePopup=function(_6){if(abego.isPopupOpen(_6)){document.body.removeChild(_6);}};abego.getWindowRect=function(){return {left:findScrollX(),top:findScrollY(),height:findWindowHeight(),width:findWindowWidth()};};abego.moveElement=function(_7,_8,_9){_7.style.left=_8+"px";_7.style.top=_9+"px";};abego.centerOnWindow=function(_a){if(_a.style.position!="absolute"){throw "abego.centerOnWindow: element must have absolute position";}var _b=abego.getWindowRect();abego.moveElement(_a,_b.left+(_b.width-_a.offsetWidth)/2,_b.top+(_b.height-_a.offsetHeight)/2);};abego.isDescendantOrSelf=function(_c,e){while(e){if(_c==e){return true;}e=e.parentNode;}return false;};abego.toSet=function(_e){var _f={};for(var i=0;i<_e.length;i++){_f[_e[i]]=true;}return _f;};abego.filterStrings=function(_11,_12,_13){var _14=[];for(var i=0;i<_11.length&&(_13===undefined||_14.length<_13);i++){var s=_11[i];if(s.match(_12)){_14.push(s);}}return _14;};abego.arraysAreEqual=function(a,b){if(!a){return !b;}if(!b){return false;}var n=a.length;if(n!=b.length){return false;}for(var i=0;i<n;i++){if(a[i]!=b[i]){return false;}}return true;};abego.moveBelowAndClip=function(_1b,_1c){if(!_1c){return;}var _1d=findPosX(_1c);var _1e=findPosY(_1c);var _1f=_1c.offsetHeight;var _20=_1d;var _21=_1e+_1f;var _22=findWindowWidth();if(_22<_1b.offsetWidth){_1b.style.width=(_22-100)+"px";}var _23=_1b.offsetWidth;if(_20+_23>_22){_20=_22-_23-30;}if(_20<0){_20=0;}_1b.style.left=_20+"px";_1b.style.top=_21+"px";_1b.style.display="block";};abego.compareStrings=function(a,b){return (a==b)?0:(a<b)?-1:1;};abego.sortIgnoreCase=function(arr){var _27=[];var n=arr.length;for(var i=0;i<n;i++){var s=arr[i];_27.push([s.toString().toLowerCase(),s]);}_27.sort(function(a,b){return (a[0]==b[0])?0:(a[0]<b[0])?-1:1;});for(i=0;i<n;i++){arr[i]=_27[i][1];}};abego.getTiddlerField=function(_2d,_2e,_2f){var _30=document.getElementById(_2d.idPrefix+_2e);var e=null;if(_30!=null){var _32=_30.getElementsByTagName("*");for(var t=0;t<_32.length;t++){var c=_32[t];if(c.tagName.toLowerCase()=="input"||c.tagName.toLowerCase()=="textarea"){if(!e){e=c;}if(c.getAttribute("edit")==_2f){e=c;}}}}return e;};abego.setRange=function(_35,_36,end){if(_35.setSelectionRange){_35.setSelectionRange(_36,end);var max=0+_35.scrollHeight;var len=_35.textLength;var top=max*_36/len,bot=max*end/len;_35.scrollTop=Math.min(top,(bot+top-_35.clientHeight)/2);}else{if(_35.createTextRange!=undefined){var _3b=_35.createTextRange();_3b.collapse();_3b.moveEnd("character",end);_3b.moveStart("character",_36);_3b.select();}else{_35.select();}}};abego.internal.TagManager=function(){var _3c=null;var _3d=function(){if(_3c){return;}_3c={};store.forEachTiddler(function(_3e,_3f){for(var i=0;i<_3f.tags.length;i++){var tag=_3f.tags[i];var _42=_3c[tag];if(!_42){_42=_3c[tag]={count:0,tiddlers:{}};}_42.tiddlers[_3f.title]=true;_42.count+=1;}});};var _43=TiddlyWiki.prototype.saveTiddler;TiddlyWiki.prototype.saveTiddler=function(_44,_45,_46,_47,_48,_49){var _4a=this.fetchTiddler(_44);var _4b=_4a?_4a.tags:[];var _4c=(typeof _49=="string")?_49.readBracketedList():_49;_43.apply(this,arguments);if(!abego.arraysAreEqual(_4b,_4c)){abego.internal.getTagManager().reset();}};var _4d=TiddlyWiki.prototype.removeTiddler;TiddlyWiki.prototype.removeTiddler=function(_4e){var _4f=this.fetchTiddler(_4e);var _50=_4f&&_4f.tags.length>0;_4d.apply(this,arguments);if(_50){abego.internal.getTagManager().reset();}};this.reset=function(){_3c=null;};this.getTiddlersWithTag=function(tag){_3d();var _52=_3c[tag];return _52?_52.tiddlers:null;};this.getAllTags=function(_53){_3d();var _54=[];for(var i in _3c){_54.push(i);}for(i=0;_53&&i<_53.length;i++){_54.pushUnique(_53[i],true);}abego.sortIgnoreCase(_54);return _54;};this.getTagInfos=function(){_3d();var _56=[];for(var _57 in _3c){_56.push([_57,_3c[_57]]);}return _56;};var _58=function(a,b){var a1=a[1];var b1=b[1];var d=b[1].count-a[1].count;return d!=0?d:abego.compareStrings(a[0].toLowerCase(),b[0].toLowerCase());};this.getSortedTagInfos=function(){_3d();var _5e=this.getTagInfos();_5e.sort(_58);return _5e;};this.getPartnerRankedTags=function(_5f){var _60={};for(var i=0;i<_5f.length;i++){var _62=this.getTiddlersWithTag(_5f[i]);for(var _63 in _62){var _64=store.getTiddler(_63);if(!(_64 instanceof Tiddler)){continue;}for(var j=0;j<_64.tags.length;j++){var tag=_64.tags[j];var c=_60[tag];_60[tag]=c?c+1:1;}}}var _68=abego.toSet(_5f);var _69=[];for(var n in _60){if(!_68[n]){_69.push(n);}}_69.sort(function(a,b){var d=_60[b]-_60[a];return d!=0?d:abego.compareStrings(a.toLowerCase(),b.toLowerCase());});return _69;};};abego.internal.getTagManager=function(){if(!abego.internal.gTagManager){abego.internal.gTagManager=new abego.internal.TagManager();}return abego.internal.gTagManager;};(function(){var _6e=2;var _6f=1;var _70=30;var _71;var _72;var _73;var _74;var _75;var _76;if(!abego.IntelliTagger){abego.IntelliTagger={};}var _77=function(){return _72;};var _78=function(tag){return _75[tag];};var _7a=function(s){var i=s.lastIndexOf(" ");return (i>=0)?s.substr(0,i):"";};var _7d=function(_7e){var s=_7e.value;var len=s.length;return (len>0&&s[len-1]!=" ");};var _81=function(_82){var s=_82.value;var len=s.length;if(len>0&&s[len-1]!=" "){_82.value+=" ";}};var _85=function(tag,_87,_88){if(_7d(_87)){_87.value=_7a(_87.value);}story.setTiddlerTag(_88.title,tag,0);_81(_87);abego.IntelliTagger.assistTagging(_87,_88);};var _89=function(n){if(_76&&_76.length>n){return _76[n];}return (_74&&_74.length>n)?_74[n]:null;};var _8b=function(n,_8d,_8e){var _8f=_89(n);if(_8f){_85(_8f,_8d,_8e);}};var _90=function(_91){var pos=_91.value.lastIndexOf(" ");var _93=(pos>=0)?_91.value.substr(++pos,_91.value.length):_91.value;return new RegExp(_93.escapeRegExp(),"i");};var _94=function(_95,_96){var _97=0;for(var i=0;i<_95.length;i++){if(_96[_95[i]]){_97++;}}return _97;};var _99=function(_9a,_9b,_9c){var _9d=1;var c=_9a[_9b];for(var i=_9b+1;i<_9a.length;i++){if(_9a[i][1].count==c){if(_9a[i][0].match(_9c)){_9d++;}}else{break;}}return _9d;};var _a0=function(_a1,_a2){var _a3=abego.internal.getTagManager().getSortedTagInfos();var _a4=[];var _a5=0;for(var i=0;i<_a3.length;i++){var c=_a3[i][1].count;if(c!=_a5){if(_a2&&(_a4.length+_99(_a3,i,_a1)>_a2)){break;}_a5=c;}if(c==1){break;}var s=_a3[i][0];if(s.match(_a1)){_a4.push(s);}}return _a4;};var _a9=function(_aa,_ab){return abego.filterStrings(abego.internal.getTagManager().getAllTags(_ab),_aa);};var _ac=function(){if(!_71){return;}var _ad=store.getTiddlerText("IntelliTaggerMainTemplate");if(!_ad){_ad="<b>Tiddler IntelliTaggerMainTemplate not found</b>";}_71.innerHTML=_ad;applyHtmlMacros(_71,null);refreshElements(_71,null);};var _ae=function(e){if(!e){var e=window.event;}var tag=this.getAttribute("tag");if(_73){_73.call(this,tag,e);}return false;};var _b2=function(_b3){createTiddlyElement(_b3,"span",null,"tagSeparator"," | ");};var _b4=function(_b5,_b6,_b7,_b8,_b9){if(!_b6){return;}var _ba=_b8?abego.toSet(_b8):{};var n=_b6.length;var c=0;for(var i=0;i<n;i++){var tag=_b6[i];if(_ba[tag]){continue;}if(c>0){_b2(_b5);}if(_b9&&c>=_b9){abego.createEllipsis(_b5);break;}c++;var _bf="";var _c0=_b5;if(_b7<10){_c0=createTiddlyElement(_b5,"span",null,"numberedSuggestion");_b7++;var key=_b7<10?""+(_b7):"0";createTiddlyElement(_c0,"span",null,"suggestionNumber",key+") ");var _c2=_b7==1?"Return or ":"";_bf=" (Shortcut: %1Alt-%0)".format([key,_c2]);}var _c3=config.views.wikified.tag.tooltip.format([tag]);var _c4=(_78(tag)?"Remove tag '%0'%1":"Add tag '%0'%1").format([tag,_bf]);var _c5="%0; Shift-Click: %1".format([_c4,_c3]);var btn=createTiddlyButton(_c0,tag,_c5,_ae,_78(tag)?"currentTag":null);btn.setAttribute("tag",tag);}};var _c7=function(){if(_71){window.scrollTo(0,ensureVisible(_71));}if(_77()){window.scrollTo(0,ensureVisible(_77()));}};var _c8=function(e){if(!e){var e=window.event;}if(!_71){return;}var _cb=resolveTarget(e);if(_cb==_77()){return;}if(abego.isDescendantOrSelf(_71,_cb)){return;}abego.IntelliTagger.close();};addEvent(document,"click",_c8);var _cc=Story.prototype.gatherSaveFields;Story.prototype.gatherSaveFields=function(e,_ce){_cc.apply(this,arguments);var _cf=_ce.tags;if(_cf){_ce.tags=_cf.trim();}};var _d0=function(_d1){story.focusTiddler(_d1,"tags");var _d2=abego.getTiddlerField(story,_d1,"tags");if(_d2){var len=_d2.value.length;abego.setRange(_d2,len,len);window.scrollTo(0,ensureVisible(_d2));}};var _d4=config.macros.edit.handler;config.macros.edit.handler=function(_d5,_d6,_d7,_d8,_d9,_da){_d4.apply(this,arguments);var _db=_d7[0];if((_da instanceof Tiddler)&&_db=="tags"){var _dc=_d5.lastChild;_dc.onfocus=function(e){abego.IntelliTagger.assistTagging(_dc,_da);setTimeout(function(){_d0(_da.title);},100);};_dc.onkeyup=function(e){if(!e){var e=window.event;}if(e.altKey&&!e.ctrlKey&&!e.metaKey&&(e.keyCode>=48&&e.keyCode<=57)){_8b(e.keyCode==48?9:e.keyCode-49,_dc,_da);}else{if(e.ctrlKey&&e.keyCode==32){_8b(0,_dc,_da);}}if(!e.ctrlKey&&(e.keyCode==13||e.keyCode==10)){_8b(0,_dc,_da);}setTimeout(function(){abego.IntelliTagger.assistTagging(_dc,_da);},100);return false;};_81(_dc);}};var _e0=function(e){if(!e){var e=window.event;}var _e3=resolveTarget(e);var _e4=_e3.getAttribute("tiddler");if(_e4){story.displayTiddler(_e3,_e4,"IntelliTaggerEditTagsTemplate",false);_d0(_e4);}return false;};var _e5=config.macros.tags.handler;config.macros.tags.handler=function(_e6,_e7,_e8,_e9,_ea,_eb){_e5.apply(this,arguments);abego.IntelliTagger.createEditTagsButton(_eb,createTiddlyElement(_e6.lastChild,"li"));};var _ec=function(){if(_71&&_72&&!abego.isDescendantOrSelf(document,_72)){abego.IntelliTagger.close();}};setInterval(_ec,100);abego.IntelliTagger.displayTagSuggestions=function(_ed,_ee,_ef,_f0,_f1){_74=_ed;_75=abego.toSet(_ee);_76=_ef;_72=_f0;_73=_f1;if(!_71){_71=createTiddlyElement(document.body,"div",null,"intelliTaggerSuggestions");_71.style.position="absolute";}_ac();abego.openAsPopup(_71);if(_77()){var w=_77().offsetWidth;if(_71.offsetWidth<w){_71.style.width=(w-2*(_6e+_6f))+"px";}abego.moveBelowAndClip(_71,_77());}else{abego.centerOnWindow(_71);}_c7();};abego.IntelliTagger.assistTagging=function(_f3,_f4){var _f5=_90(_f3);var s=_f3.value;if(_7d(_f3)){s=_7a(s);}var _f7=s.readBracketedList();var _f8=_f7.length>0?abego.filterStrings(abego.internal.getTagManager().getPartnerRankedTags(_f7),_f5,_70):_a0(_f5,_70);abego.IntelliTagger.displayTagSuggestions(_a9(_f5,_f7),_f7,_f8,_f3,function(tag,e){if(e.shiftKey){onClickTag.call(this,e);}else{_85(tag,_f3,_f4);}});};abego.IntelliTagger.close=function(){abego.closePopup(_71);_71=null;return false;};abego.IntelliTagger.createEditTagsButton=function(_fb,_fc,_fd,_fe,_ff,id,_101){if(!_fd){_fd="[edit]";}if(!_fe){_fe="Edit the tags";}if(!_ff){_ff="editTags";}var _102=createTiddlyButton(_fc,_fd,_fe,_e0,_ff,id,_101);_102.setAttribute("tiddler",(_fb instanceof Tiddler)?_fb.title:String(_fb));return _102;};abego.IntelliTagger.getSuggestionTagsMaxCount=function(){return 100;};config.macros.intelliTagger={label:"intelliTagger",handler:function(_103,_104,_105,_106,_107,_108){var _109=_107.parseParams("list",null,true);var _10a=_109[0]["action"];for(var i=0;_10a&&i<_10a.length;i++){var _10c=_10a[i];var _10d=config.macros.intelliTagger.subhandlers[_10c];if(!_10d){abego.alertAndThrow("Unsupported action '%0'".format([_10c]));}_10d(_103,_104,_105,_106,_107,_108);}},subhandlers:{showTags:function(_10e,_10f,_110,_111,_112,_113){_b4(_10e,_74,_76?_76.length:0,_76,abego.IntelliTagger.getSuggestionTagsMaxCount());},showFavorites:function(_114,_115,_116,_117,_118,_119){_b4(_114,_76,0);},closeButton:function(_11a,_11b,_11c,_11d,_11e,_11f){var _120=createTiddlyButton(_11a,"close","Close the suggestions",abego.IntelliTagger.close);},version:function(_121){var t="IntelliTagger %0.%1.%2".format([version.extensions.IntelliTaggerPlugin.major,version.extensions.IntelliTaggerPlugin.minor,version.extensions.IntelliTaggerPlugin.revision]);var e=createTiddlyElement(_121,"a");e.setAttribute("href","http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin");e.innerHTML="<font color=\"black\" face=\"Arial, Helvetica, sans-serif\">"+t+"<font>";},copyright:function(_124){var e=createTiddlyElement(_124,"a");e.setAttribute("href","http://tiddlywiki.abego-software.de");e.innerHTML="<font color=\"black\" face=\"Arial, Helvetica, sans-serif\">&copy; 2006-2007 <b><font color=\"red\">abego</font></b> Software<font>";}}};})();config.shadowTiddlers["IntelliTaggerStyleSheet"]="/***\n"+"!~IntelliTagger Stylesheet\n"+"***/\n"+"/*{{{*/\n"+".intelliTaggerSuggestions {\n"+"\tposition: absolute;\n"+"\twidth: 600px;\n"+"\n"+"\tpadding: 2px;\n"+"\tlist-style: none;\n"+"\tmargin: 0;\n"+"\n"+"\tbackground: #eeeeee;\n"+"\tborder: 1px solid DarkGray;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .currentTag   {\n"+"\tfont-weight: bold;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .suggestionNumber {\n"+"\tcolor: #808080;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .numberedSuggestion{\n"+"\twhite-space: nowrap;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .intelliTaggerFooter {\n"+"\tmargin-top: 4px;\n"+"\tborder-top-width: thin;\n"+"\tborder-top-style: solid;\n"+"\tborder-top-color: #999999;\n"+"}\n"+".intelliTaggerSuggestions .favorites {\n"+"\tborder-bottom-width: thin;\n"+"\tborder-bottom-style: solid;\n"+"\tborder-bottom-color: #999999;\n"+"\tpadding-bottom: 2px;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .normalTags {\n"+"\tpadding-top: 2px;\n"+"}\n"+"\n"+".intelliTaggerSuggestions .intelliTaggerFooter .button {\n"+"\tfont-size: 10px;\n"+"\n"+"\tpadding-left: 0.3em;\n"+"\tpadding-right: 0.3em;\n"+"}\n"+"\n"+"/*}}}*/\n";config.shadowTiddlers["IntelliTaggerMainTemplate"]="<!--\n"+"{{{\n"+"-->\n"+"<div class=\"favorites\" macro=\"intelliTagger action: showFavorites\"></div>\n"+"<div class=\"normalTags\" macro=\"intelliTagger action: showTags\"></div>\n"+"<!-- The Footer (with the Navigation) ============================================ -->\n"+"<table class=\"intelliTaggerFooter\" border=\"0\" width=\"100%\" cellspacing=\"0\" cellpadding=\"0\"><tbody>\n"+"  <tr>\n"+"\t<td align=\"left\">\n"+"\t\t<span macro=\"intelliTagger action: closeButton\"></span>\n"+"\t</td>\n"+"\t<td align=\"right\">\n"+"\t\t<span macro=\"intelliTagger action: version\"></span>, <span macro=\"intelliTagger action: copyright \"></span>\n"+"\t</td>\n"+"  </tr>\n"+"</tbody></table>\n"+"<!--\n"+"}}}\n"+"-->\n";config.shadowTiddlers["IntelliTaggerEditTagsTemplate"]="<!--\n"+"{{{\n"+"-->\n"+"<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler'></div>\n"+"<div class='title' macro='view title'></div>\n"+"<div class='tagged' macro='tags'></div>\n"+"<div class='viewer' macro='view text wikified'></div>\n"+"<div class='toolbar' macro='toolbar +saveTiddler -cancelTiddler'></div>\n"+"<div class='editor' macro='edit tags'></div><div class='editorFooter'><span macro='message views.editor.tagPrompt'></span><span macro='tagChooser'></span></div>\n"+"<!--\n"+"}}}\n"+"-->\n";config.shadowTiddlers["BSD open source license (abego Software)"]="See [[Licence|http://tiddlywiki.abego-software.de/#%5B%5BBSD%20open%20source%20license%5D%5D]].";config.shadowTiddlers["IntelliTaggerPlugin Documentation"]="[[Documentation on abego Software website|http://tiddlywiki.abego-software.de/doc/IntelliTagger.pdf]].";config.shadowTiddlers["IntelliTaggerPlugin SourceCode"]="[[Plugin source code on abego Software website|http://tiddlywiki.abego-software.de/archive/IntelliTaggerPlugin/Plugin-IntelliTagger-src.1.0.2.js]]\n";(function(){var _126=restart;restart=function(){setStylesheet(store.getTiddlerText("IntelliTaggerStyleSheet"),"IntelliTaggerStyleSheet");_126.apply(this,arguments);};})();}
// %/
/***
|''Name:''|IntelliTagsEditCommandPlugin|
|''Version:''|1.0.0 (2007-10-03)|
|''Type:''|plugin|
|''Description:''|A command for your tiddler's toolbar to directly edit the tiddler's tags using the IntelliTaggerPlugin, without switching to "edit mode".|
|''Source:''|http://tiddlywiki.abego-software.de/#IntelliTagsEditCommandPlugin|
|''Requires:''|IntelliTaggerPlugin http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin|
|''Author:''|Udo Borkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license (abego Software)]]|
|''~CoreVersion:''|2.0.8|
|''Browser:''|Firefox 1.5.0.2 or better|
***/
/***
!Using the "IntelliTagsEditCommandPlugin"
Add the command {{{intelliTagsEdit}}} into the 'macro' attribute of the 'toolbar' {{{<div...>}}} in your ViewTemplate.

''Example:''
{{{
<div class='toolbar' 
        macro='toolbar -closeTiddler closeOthers +editTiddler intelliTagsEdit permalink references jump'>
</div>
}}}

This adds a "tags" button to the toolbar of the tiddlers (next to the ''edit'' button). Pressing the "tags" button will open the input field for the tiddler's tags and let you edit the tags with all the [[IntelliTaggerPlugin|http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin]] features.
***/
/***
!Source Code
***/
//{{{
(function(){

if (!version.extensions.IntelliTaggerPlugin)
    throw Error("IntelliTagsEditCommandPlugin requires the IntelliTaggerPlugin (http://tiddlywiki.abego-software.de/#IntelliTaggerPlugin)");

if (config.commands.intelliTagsEdit) 
    return;

config.commands.intelliTagsEdit = {
	text: "tags",
	tooltip: "edit the tags"
};

config.commands.intelliTagsEdit.handler = function(event,src,title) {
	var button = abego.IntelliTagger.createEditTagsButton(title, null, "tags", "edit the tags");
	button.onclick(event);
	return false;
};

})();
//}}}
/***
|Name|LoadTiddlersPlugin|
|Source|http://www.TiddlyTools.com/#LoadTiddlersPlugin|
|Documentation|http://www.TiddlyTools.com/#LoadTiddlersPluginInfo|
|Version|3.6.2|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides||
|Options|##Configuration|
|Description|macro for automated updates or one-click installations of tiddlers from remote sources|
***/
//{{{
version.extensions.loadTiddlers = {major: 3, minor: 6, revision: 2, date: new Date(2008,8,5)};

config.macros.loadTiddlers = {
	label: "",
	tip: "add/update tiddlers from '%0'",
	lockedTag: "noReload",	// if existing tiddler has this tag value, don't overwrite it, even if inbound tiddler is newer
	askMsg: "Please enter a local path/filename or a remote URL",
	openMsg: "Opening %0",
	openErrMsg: "Could not open %0 - error=%1",
	readMsg: "Read %0 bytes from %1",
	foundMsg: "Found %0 tiddlers in %1",
	nochangeMsg: "'%0' is up-to-date... skipped.",
	lockedMsg: "'%0' is tagged '%1'... skipped.",
	skippedMsg: "skipped (cancelled by user)",
	loadedMsg: "Loaded %0 of %1 tiddlers from %2",
	reportTitle: "ImportedTiddlers",
	warning: "Warning!!  Processing '%0' as a systemConfig (plugin) tiddler may produce unexpected results! Are you sure you want to proceed?",
	handler: function(place,macroName,params) {
		var label=(params[0] && params[0].substr(0,6)=='label:')?params.shift().substr(6):this.label;
		var tip=(params[0] && params[0].substr(0,7)=='prompt:')?params.shift().substr(7):this.tip;
		var filter="updates";
		if (params[0] && (params[0]=='all' || params[0]=='new' || params[0]=='changes' || params[0]=='updates'
			|| params[0].substr(0,8)=='tiddler:' || params[0].substr(0,4)=='tag:'))
			filter=params.shift();
		var src=params.shift(); if (!src || !src.length) return; // filename is required
		var quiet=(params[0]=="quiet"); if (quiet) params.shift();
		var ask=(params[0]=="confirm"); if (ask) params.shift();
		var force=(params[0]=="force"); if (force) params.shift();
		var init=(params[0]=="init"); if (init) params.shift();
		var noreport=(params[0]=="noreport"); if (noreport) params.shift();
		this.newTags=[]; if (params[0]) this.newTags=params; // any remaining params are used as "autotags"
		if (label.trim().length) {
			// link triggers load tiddlers from another file/URL and then applies filtering rules to add/replace tiddlers in the store
			createTiddlyButton(place,label.format([src.replace(/%20/g," ")]),tip.format([src.replace(/%20/g," ")]), function() {
				if (src=="ask") src=prompt(this.askMsg);
				config.macros.loadTiddlers.loadFile(src,config.macros.loadTiddlers.doImport,{quiet:quiet,ask:ask,filter:filter,force:force,init:init,noreport:noreport});
			})
		}
		else {
			// load tiddlers from another file/URL and then apply filtering rules to add/replace tiddlers in the store
			if (src=="ask") src=prompt(this.askMsg);
			config.macros.loadTiddlers.loadFile(src,config.macros.loadTiddlers.doImport,{quiet:quiet,ask:ask,filter:filter,force:force,init:init,noreport:noreport});
		}
	},
	loadFile: function(src,callback,params) {
		var quiet=params.quiet;
		if (src==undefined || !src.length) return null; // filename is required
		if (!quiet) clearMessage();
		if (!quiet) displayMessage(this.openMsg.format([src.replace(/%20/g," ")]));
		if (src.substr(0,5)!="http:" && src.substr(0,5)!="file:") { // if not a URL, read from local filesystem
			var txt=loadFile(src);
			if (!txt) { // file didn't load, might be relative path.. try fixup
				var pathPrefix=document.location.href;  // get current document path and trim off filename
				var slashpos=pathPrefix.lastIndexOf("/"); if (slashpos==-1) slashpos=pathPrefix.lastIndexOf("\\"); 
				if (slashpos!=-1 && slashpos!=pathPrefix.length-1) pathPrefix=pathPrefix.substr(0,slashpos+1);
				src=pathPrefix+src;
				if (pathPrefix.substr(0,5)!="http:") src=getLocalPath(src);
				var txt=loadFile(src);
			}
			if (!txt) { // file still didn't load, report error
				if (!quiet) displayMessage(this.openErrMsg.format([src.replace(/%20/g," "),"(unknown)"]));
			} else {
				if (!quiet) displayMessage(this.readMsg.format([txt.length,src.replace(/%20/g," ")]));
				if (callback) callback(true,params,convertUTF8ToUnicode(txt),src,null);
			}
		} else {
			var name=config.options.txtRemoteUsername; var pass=config.options.txtRemotePassword;
			var x=doHttp("GET",src,null,null,name,pass,callback,params,null);
		}
	},
	readTiddlersFromHTML: function(html) {
		// for TW2.2+
		if (TiddlyWiki.prototype.importTiddlyWiki!=undefined) {
			var remoteStore=new TiddlyWiki();
			remoteStore.importTiddlyWiki(html);
			return remoteStore.getTiddlers("title");	
		}
	},
	doImport: function(status,params,html,src,xhr) {
		var quiet=params.quiet;
		var ask=params.ask;
		var filter=params.filter;
		var force=params.force;
		var init=params.init;
		var noreport=params.noreport;
		var tiddlers = config.macros.loadTiddlers.readTiddlersFromHTML(html);
		var count=tiddlers?tiddlers.length:0;
		var querypos=src.lastIndexOf("?"); if (querypos!=-1) src=src.substr(0,querypos);
		if (!quiet) displayMessage(config.macros.loadTiddlers.foundMsg.format([count,src.replace(/%20/g," ")]));
		store.suspendNotifications();
		var count=0;
		if (tiddlers) for (var t=0;t<tiddlers.length;t++) {
			var inbound = tiddlers[t];
			var theExisting = store.getTiddler(inbound.title);
			if (inbound.title==config.macros.loadTiddlers.reportTitle)
				continue; // skip "ImportedTiddlers" history from the other document...
			if (theExisting && theExisting.tags.contains(config.macros.loadTiddlers.lockedTag)) {
				if (!quiet) displayMessage(config.macros.loadTiddlers.lockedMsg.format([theExisting.title,config.macros.loadTiddlers.lockedTag]));
				continue; // skip existing tiddler if tagged with 'noReload'
			}
			// apply the all/new/changes/updates filter (if any)
			if (filter && filter!="all") {
				if ((filter=="new") && theExisting) // skip existing tiddlers
					continue;
				if ((filter=="changes") && !theExisting) // skip new tiddlers
					continue;
				if ((filter.substr(0,4)=="tag:") && inbound.tags.indexOf(filter.substr(4))==-1) // must match specific tag value
					continue;
				if ((filter.substr(0,8)=="tiddler:") && inbound.title!=filter.substr(8)) // must match specific tiddler name
					continue;
				if (!force && store.tiddlerExists(inbound.title) && ((theExisting.modified.getTime()-inbound.modified.getTime())>=0))
					{ if (!quiet) displayMessage(config.macros.loadTiddlers.nochangeMsg.format([inbound.title])); continue; }
			}
			// get confirmation if required
			if (ask && !confirm((theExisting?"Update":"Add")+" tiddler '"+inbound.title+"'\nfrom "+src.replace(/%20/g," ")+"\n\nOK to proceed?"))
				{ tiddlers[t].status=config.macros.loadTiddlers.skippedMsg; continue; }
			// DO IT!
			var tags=Array.concat(inbound.tags,config.macros.loadTiddlers.newTags);
	                store.saveTiddler(inbound.title, inbound.title, inbound.text, inbound.modifier, inbound.modified, tags, inbound.fields, true, inbound.created);
	                store.fetchTiddler(inbound.title).created = inbound.created; // force creation date to imported value - needed for TW2.1.3 or earlier
			tiddlers[t].status=theExisting?"updated":"added"
			if (init && tags.contains("systemConfig") && !tags.contains("systemConfigDisable")) {
				var ok=true;
				if (ask||!quiet) ok=confirm(config.macros.loadTiddlers.warning.format([inbound.title]))
				if (ok) { // run the plugin
					try { window.eval(inbound); tiddlers[t].status+=" (plugin initialized)"; }
					catch(ex) { displayMessage(config.messages.pluginError.format([exceptionText(ex)])); }
				}
			}
			count++;
		}
		store.resumeNotifications();
		if (count) {
			// refresh display
			store.setDirty(true); store.notifyAll();
			// generate a report
			if (!noreport) config.macros.loadTiddlers.report(src,tiddlers,count,quiet);
		}
		// always show final message when tiddlers were actually loaded
		if (!quiet||count) displayMessage(config.macros.loadTiddlers.loadedMsg.format([count,tiddlers.length,src.replace(/%20/g," ")]));
	},
	report: function(src,tiddlers,count,quiet) {
		// format the new report content
		var newText = "On "+(new Date()).toLocaleString()+", ";
		newText += config.options.txtUserName+" loaded "+count+" tiddlers ";
		newText += "from\n[["+src+"|"+src+"]]:\n";
		newText += "<<<\n";
		for (var t=0; t<tiddlers.length; t++)
			if (tiddlers[t].status)
				newText += "#[["+tiddlers[t].title+"]] - "+tiddlers[t].status+"\n";
		newText += "<<<\n";
		// get current report (if any)
		var title=config.macros.loadTiddlers.reportTitle;
		var currText="";
		var theReport = store.getTiddler(title);
		if (theReport) currText=((theReport.text!="")?'\n----\n':"")+theReport.text;
		// update the ImportedTiddlers content and show the tiddler
		store.saveTiddler(title, title, newText+currText, config.options.txtUserName, new Date(), theReport?theReport.tags:null, theReport?theReport.fields:null);
		if (!quiet) { story.displayTiddler(null,title,1,null,null,false); story.refreshTiddler(title,1,true); }
	}
}
//}}}
<<tagsTree menu "" 1 4 index label>>
<<tagsTree twcms "" 1 4 index label>>
<<tagsTree linux0101 "" 1 4 index label>>
<<tagsTree linux0102 "" 1 4 index label>>
<<tagsTree linux0103 "" 1 4 index label>>
<<tagsTree linux0104 "" 1 4 index label>>
<<tagsTree linux0105 "" 1 4 index label>>
<<tagsTree linux0106 "" 1 4 index label>>
<<tagsTree KMKConfig "" 1 4 index label>>
<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml'/>
<!--}}}-->

<!--{{{-->
<style type="text/css">
#contentWrapper {display:none;}
</style>

<div id="SplashScreen" style="border: 3px solid #ccc; display: block; text-align: center; width: 320px; margin: 100px auto; padding: 50px; color:#000; font-size: 28px; font-family:Tahoma; background-color:#eee;">
<b>toBala KM King</b><br><br><img src="loader.gif"><br>
<span style="font-size: 14px; color:red;">Requires Javascript.</span>
</div>
<!--}}}-->
這些設定將暫存於瀏覽器
請簽名<<option txtUserName>>
 (範例:WikiWord)

 <<option chkSaveBackups>> 儲存備份
 <<option chkAutoSave>> 自動儲存
 <<option chkRegExpSearch>> 正規式搜尋
 <<option chkCaseSensitiveSearch>> 區分大小寫搜尋
 <<option chkAnimate>> 使用動畫顯示
----
 [[進階選項|AdvancedOptions]]
<!--{{{-->
<div class='header' macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
<div class='headerShadow'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
<div class='headerForeground'>
<span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>&nbsp;
<span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
</div>
</div>

<div id='toolBar' refresh='content' force='true' tiddler='toBalaToolBar'></div>
<div id='mainMenu' refresh='content' force='true' tiddler='MainMenu'></div>

<div id='displayArea'>
<div id='messageArea'></div>
<div id='tiddlersBar' refresh='none' ondblclick='config.macros.tiddlersBar.onTiddlersBarAction(event)'></div>
<div id='tiddlerDisplay'></div>
</div>

<iframe id='ApplicationArea' width='100%' height='100%'></iframe>
<!--}}}-->
//{{{
//============================================================================
//                           PartTiddlerPlugin

// Ensure that the PartTiddler Plugin is only installed once.
//
if (!version.extensions.PartTiddlerPlugin) {

version.extensions.PartTiddlerPlugin = {
    major: 1, minor: 0, revision: 9,
    date: new Date(2007, 6, 14), 
    type: 'plugin',
    source: "http://tiddlywiki.abego-software.de/#PartTiddlerPlugin"
};

if (!window.abego) window.abego = {};
if (version.major < 2) alertAndThrow("PartTiddlerPlugin requires TiddlyWiki 2.0 or newer.");

//============================================================================
// Common Helpers

// Looks for the next newline, starting at the index-th char of text. 
//
// If there are only whitespaces between index and the newline 
// the index behind the newline is returned, 
// otherwise (or when no newline is found) index is returned.
//
var skipEmptyEndOfLine = function(text, index) {
	var re = /(\n|[^\s])/g;
	re.lastIndex = index;
	var result = re.exec(text);
	return (result && text.charAt(result.index) == '\n') 
			? result.index+1
			: index;
}


//============================================================================
// Constants

var partEndOrStartTagRE = /(<\/part>)|(<part(?:\s+)((?:[^>])+)>)/mg;
var partEndTagREString = "<\\/part>";
var partEndTagString = "</part>";

//============================================================================
// Plugin Specific Helpers

// Parse the parameters inside a <part ...> tag and return the result.
//
// @return [may be null] {partName: ..., isHidden: ...}
//
var parseStartTagParams = function(paramText) {
	var params = paramText.readMacroParams();
	if (params.length == 0 || params[0].length == 0) return null;
	
	var name = params[0];
	var paramsIndex = 1;
	var hidden = false;
	if (paramsIndex < params.length) {
		hidden = params[paramsIndex] == "hidden";
		paramsIndex++;
	}
	
	return {
		partName: name, 
		isHidden: hidden
	};
}

// Returns the match to the next (end or start) part tag in the text, 
// starting the search at startIndex.
// 
// When no such tag is found null is returned, otherwise a "Match" is returned:
// [0]: full match
// [1]: matched "end" tag (or null when no end tag match)
// [2]: matched "start" tag (or null when no start tag match)
// [3]: content of start tag (or null if no start tag match)
//
var findNextPartEndOrStartTagMatch = function(text, startIndex) {
	var re = new RegExp(partEndOrStartTagRE);
	re.lastIndex = startIndex;
	var match = re.exec(text);
	return match;
}

//============================================================================
// Formatter

// Process the <part ...> ... </part> starting at (w.source, w.matchStart) for formatting.
//
// @return true if a complete part section (including the end tag) could be processed, false otherwise.
//
var handlePartSection = function(w) {
	var tagMatch = findNextPartEndOrStartTagMatch(w.source, w.matchStart);
	if (!tagMatch) return false;
	if (tagMatch.index != w.matchStart || !tagMatch[2]) return false;

	// Parse the start tag parameters
	var arguments = parseStartTagParams(tagMatch[3]);
	if (!arguments) return false;
	
	// Continue processing
	var startTagEndIndex = skipEmptyEndOfLine(w.source, tagMatch.index + tagMatch[0].length);
	var endMatch = findNextPartEndOrStartTagMatch(w.source, startTagEndIndex);
	if (endMatch && endMatch[1]) {
		if (!arguments.isHidden) {
			w.nextMatch = startTagEndIndex;
			w.subWikify(w.output,partEndTagREString);
		}
		w.nextMatch = skipEmptyEndOfLine(w.source, endMatch.index + endMatch[0].length);
		
		return true;
	}
	return false;
}

config.formatters.push( {
    name: "part",
    match: "<part\\s+[^>]+>",
	
	handler: function(w) {
		if (!handlePartSection(w)) {
			w.outputText(w.output,w.matchStart,w.matchStart+w.matchLength);
		}
	}
} )

//============================================================================
// Extend "fetchTiddler" functionality to also recognize "part"s of tiddlers 
// as tiddlers.

var currentParent = null; // used for the "." parent (e.g. in the "tiddler" macro)

// Return the match to the first <part ...> tag of the text that has the
// requrest partName.
//
// @return [may be null]
//
var findPartStartTagByName = function(text, partName) {
	var i = 0;
	
	while (true) {
		var tagMatch = findNextPartEndOrStartTagMatch(text, i);
		if (!tagMatch) return null;

		if (tagMatch[2]) {
			// Is start tag
	
			// Check the name
			var arguments = parseStartTagParams(tagMatch[3]);
			if (arguments && arguments.partName == partName) {
				return tagMatch;
			}
		}
		i = tagMatch.index+tagMatch[0].length;
	}
}

// Return the part "partName" of the given parentTiddler as a "readOnly" Tiddler 
// object, using fullName as the Tiddler's title. 
//
// All remaining properties of the new Tiddler (tags etc.) are inherited from 
// the parentTiddler.
// 
// @return [may be null]
//
var getPart = function(parentTiddler, partName, fullName) {
	var text = parentTiddler.text;
	var startTag = findPartStartTagByName(text, partName);
	if (!startTag) return null;
	
	var endIndexOfStartTag = skipEmptyEndOfLine(text, startTag.index+startTag[0].length);
	var indexOfEndTag = text.indexOf(partEndTagString, endIndexOfStartTag);

	if (indexOfEndTag >= 0) {
		var partTiddlerText = text.substring(endIndexOfStartTag,indexOfEndTag);
		var partTiddler = new Tiddler();
		partTiddler.set(
						fullName,
						partTiddlerText,
						parentTiddler.modifier,
						parentTiddler.modified,
						parentTiddler.tags,
						parentTiddler.created);
		partTiddler.abegoIsPartTiddler = true;
		return partTiddler;
	}
	
	return null;
}

// Hijack the store.fetchTiddler to recognize the "part" addresses.
//
var hijackFetchTiddler = function() {
	var oldFetchTiddler = store.fetchTiddler ;
	store.fetchTiddler = function(title) {
		var result = oldFetchTiddler.apply(this, arguments);
		if (!result && title) {
			var i = title.lastIndexOf('/');
			if (i > 0) {
				var parentName = title.substring(0, i);
				var partName = title.substring(i+1);
				var parent = (parentName == ".") 
						? store.resolveTiddler(currentParent)
						: oldFetchTiddler.apply(this, [parentName]);
				if (parent) {
					return getPart(parent, partName, parent.title+"/"+partName);
				}
			}
		}
		return result;	
	};
};

// for debugging the plugin is not loaded through the systemConfig mechanism but via a script tag. 
// At that point in the "store" is not yet defined. In that case hijackFetchTiddler through the restart function.
// Otherwise hijack now.
if (!store) {
	var oldRestartFunc = restart;
	window.restart = function() {
		hijackFetchTiddler();
		oldRestartFunc.apply(this,arguments);
	};
} else
	hijackFetchTiddler();




// The user must not edit a readOnly/partTiddler
//

config.commands.editTiddler.oldIsReadOnlyFunction = Tiddler.prototype.isReadOnly;

Tiddler.prototype.isReadOnly = function() {
	// Tiddler.isReadOnly was introduced with TW 2.0.6.
	// For older version we explicitly check the global readOnly flag
	if (config.commands.editTiddler.oldIsReadOnlyFunction) {
		if (config.commands.editTiddler.oldIsReadOnlyFunction.apply(this, arguments)) return true;
	} else {
		if (readOnly) return true;
	}

	return this.abegoIsPartTiddler;
}

config.commands.editTiddler.handler = function(event,src,title)
{
	var t = store.getTiddler(title);
	// Edit the tiddler if it either is not a tiddler (but a shadowTiddler)
	// or the tiddler is not readOnly
	if(!t || !t.abegoIsPartTiddler)
		{
		clearMessage();
		story.displayTiddler(null,title,DEFAULT_EDIT_TEMPLATE);
		story.focusTiddler(title,"text");
		return false;
		}
}

// To allow the "./partName" syntax in macros we need to hijack 
// the invokeMacro to define the "currentParent" while it is running.
// 
var oldInvokeMacro = window.invokeMacro;
function myInvokeMacro(place,macro,params,wikifier,tiddler) {
	var oldCurrentParent = currentParent;
	if (tiddler) currentParent = tiddler;
	try {
		oldInvokeMacro.apply(this, arguments);
	} finally {
		currentParent = oldCurrentParent;
	}
}
window.invokeMacro = myInvokeMacro;

// To correctly support the "./partName" syntax while refreshing we need to hijack 
// the config.refreshers.tiddlers to define the "currentParent" while it is running.
// 
(function() {
	var oldTiddlerRefresher= config.refreshers.tiddler;
	config.refreshers.tiddler = function(e,changeList) {
		var oldCurrentParent = currentParent;
		try {
			currentParent = e.getAttribute("tiddler");
			return oldTiddlerRefresher.apply(this,arguments);
		} finally {
			currentParent = oldCurrentParent;
		}
	};
})();

// Support "./partName" syntax inside <<tabs ...>> macro
(function() {
	var extendRelativeNames = function(e, title) {
		var nodes = e.getElementsByTagName("a");
		for(var i=0; i<nodes.length; i++) {
			var node = nodes[i];
			var s = node.getAttribute("content");
			if (s && s.indexOf("./") == 0)
				node.setAttribute("content",title+s.substr(1));
		}
	};
	var oldHandler = config.macros.tabs.handler;
	config.macros.tabs.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
		var result = oldHandler.apply(this,arguments);
		if (tiddler)
			extendRelativeNames(place, tiddler.title);
		return result;
	};
})();

// Scroll the anchor anchorName in the viewer of the given tiddler visible.
// When no tiddler is defined use the tiddler of the target given event is used.
window.scrollAnchorVisible = function(anchorName, tiddler, evt) {
	var tiddlerElem = null;
	if (tiddler) {
		tiddlerElem = document.getElementById(story.idPrefix + tiddler);
	}
	if (!tiddlerElem && evt) {
		var target = resolveTarget(evt);
		tiddlerElem = story.findContainingTiddler(target);
	}
	if (!tiddlerElem) return;

	var children = tiddlerElem.getElementsByTagName("a");
	for (var i = 0; i < children.length; i++) {
		var child = children[i];
		var name = child.getAttribute("name");
		if (name == anchorName) {
			var y = findPosY(child);
			window.scrollTo(0,y);
			return;
		}
	}
}

} // of "install only once"
//}}}
<<tabs txtMainTab "最近更新" "依更新日期排序" TabTimeline "分類" "所有標籤" TabTags "設定文章" "說所有設定文章" TabMoreShadowed>>
V1.2 (2010/06/01)
Linux 系統概論- 學習筆記本
/***
|''Name:''|SparklinePlugin|
|''Description:''|Sparklines macro|
***/
//{{{
if(!version.extensions.SparklinePlugin) {
version.extensions.SparklinePlugin = {installed:true};

//--
//-- Sparklines
//--

config.macros.sparkline = {};
config.macros.sparkline.handler = function(place,macroName,params)
{
	var data = [];
	var min = 0;
	var max = 0;
	var v;
	for(var t=0; t<params.length; t++) {
		v = parseInt(params[t]);
		if(v < min)
			min = v;
		if(v > max)
			max = v;
		data.push(v);
	}
	if(data.length < 1)
		return;
	var box = createTiddlyElement(place,"span",null,"sparkline",String.fromCharCode(160));
	box.title = data.join(",");
	var w = box.offsetWidth;
	var h = box.offsetHeight;
	box.style.paddingRight = (data.length * 2 - w) + "px";
	box.style.position = "relative";
	for(var d=0; d<data.length; d++) {
		var tick = document.createElement("img");
		tick.border = 0;
		tick.className = "sparktick";
		tick.style.position = "absolute";
		tick.src = "data:image/gif,GIF89a%01%00%01%00%91%FF%00%FF%FF%FF%00%00%00%C0%C0%C0%00%00%00!%F9%04%01%00%00%02%00%2C%00%00%00%00%01%00%01%00%40%02%02T%01%00%3B";
		tick.style.left = d*2 + "px";
		tick.style.width = "2px";
		v = Math.floor(((data[d] - min)/(max-min)) * h);
		tick.style.top = (h-v) + "px";
		tick.style.height = v + "px";
		box.appendChild(tick);
	}
};


}
//}}}
/***

''Inspired by [[TiddlyPom|http://www.warwick.ac.uk/~tuspam/tiddlypom.html]]''

|Name|SplashScreenPlugin|
|Created by|SaqImtiaz|
|Location|http://tw.lewcid.org/#SplashScreenPlugin|
|Version|0.21 |
|Requires|~TW2.08+|
!Description:
Provides a simple splash screen that is visible while the TW is loading.

!Installation
Copy the source text of this tiddler to your TW in a new tiddler, tag it with systemConfig and save and reload. The SplashScreen will now be installed and will be visible the next time you reload your TW.

!Customizing
Once the SplashScreen has been installed and you have reloaded your TW, the splash screen html will be present in the MarkupPreHead tiddler. You can edit it and customize to your needs.

!History
* 20-07-06 : version 0.21, modified to hide contentWrapper while SplashScreen is displayed.
* 26-06-06 : version 0.2, first release

!Code
***/
//{{{
var old_lewcid_splash_restart=restart;

restart = function()
{   if (document.getElementById("SplashScreen"))
        document.getElementById("SplashScreen").style.display = "none";
      if (document.getElementById("contentWrapper"))
        document.getElementById("contentWrapper").style.display = "block";
    
    old_lewcid_splash_restart();
   
    if (splashScreenInstall)
       {if(config.options.chkAutoSave)
			{saveChanges();}
        displayMessage("TW SplashScreen has been installed, please save and refresh your TW.");
        }
}


var oldText = store.getTiddlerText("MarkupPreHead");
if (oldText.indexOf("SplashScreen")==-1)
   {var siteTitle = store.getTiddlerText("SiteTitle");
   var splasher='\n\n<style type="text/css">#contentWrapper {display:none;}</style><div id="SplashScreen" style="border: 3px solid #ccc; display: block; text-align: center; width: 320px; margin: 100px auto; padding: 50px; color:#000; font-size: 28px; font-family:Tahoma; background-color:#eee;"><b>'+siteTitle +'</b> is loading<blink> ...</blink><br><br><span style="font-size: 14px; color:red;">Requires Javascript.</span></div>';
   if (! store.tiddlerExists("MarkupPreHead"))
       {var myTiddler = store.createTiddler("MarkupPreHead");}
   else
      {var myTiddler = store.getTiddler("MarkupPreHead");}
      myTiddler.set(myTiddler.title,oldText+splasher,config.options.txtUserName,null,null);
      store.setDirty(true);
      var splashScreenInstall = true;
}
//}}}
/*{{{*/

/* 應用模式的樣式設定 */
#ApplicationArea {display:none;width:100px;height:100%;}


/* option 巨集文字欄位的長度 */
.txtOptionInput {width:40em;}


/* 主要項目樣式 

    在 Tiddler 中的使用格式如下 :
    {{item1{Item description}}}

*/
.item1{
 line-height:28px;
 font-weight:bold; 
 font-size:14px;
 border-left: 10px solid blue;
 margin:0px 0px 0px 0px;
 padding: 0px 0px 0px 3px;
 background-color:transparent;
}

/* 實作項目樣式 

    在 Tiddler 中的使用格式如下 :
    {{op1{operation description}}}

*/
.op1{
 line-height:28px;
 font-weight:bold; 
 font-size:14px;
 margin:0px 0px 0px 0px;
 padding: 0px 0px 0px 0px;
 background-color:transparent;
}


/*
Making preformated <pre> text wrap in CSS3, Mozilla, Opera and IE

word-wrap: break-word; - 視窗邊界換行,僅 IE 支援。也可以用 word-brak: break-all; 但不會保持英文單字的完整性。
white-space: pre; - 對某標籤作預先格式化,所有標準瀏覽器皆支援。
white-space: -moz-pre-wrap; - 預先格式化,但在元素邊界換行,僅 Mozilla (Firefox) 支援。
white-space: pre-wrap; - 預先格式化,但在元素邊界換行,僅 Opera 支援。
*/
.viewer pre {
  font-size:12px;
  white-space: pre-wrap;       /* css-3 */
  white-space: -moz-pre-wrap;  /* Mozilla, since 1999 */
  white-space: -pre-wrap;      /* Opera 4-6 */
  white-space: -o-pre-wrap;    /* Opera 7 */
  word-wrap: break-word;       /* Internet Explorer 5.5+ */
}
.viewer pre {border:1px solid [[ColorPalette::SecondaryLight]]; background:[[ColorPalette::SecondaryPale]];}


/*
無框線表格樣式設定, 以下是使用範例:

|!Col1|!Col2|!Col3|
|r1c1| r1r2c2 |r1c3|
|r2c1|~|r2c3|
|borderless|k    // 使用格式

*/
.borderless, .borderless table, .borderless td, .borderless tr, .borderless th, .borderless tbody { 
   border:0 !important; margin:0 !important; padding:2px !important; 
   td.vertical-align:top !important;margin-left: auto !important; 
   margin-right: auto !important;
}

.externalLink {text-decoration:none}

#toolBar { 
 background-color: #eee; 
 color:#ccc;
 width: auto;
 text-align:left;
 padding: 0.4em 0.6em 0.4em 0.6em;
}

h1,h2,h3 {padding-bottom:1px; margin-top:0.1em;margin-bottom:0.1em;}
h4,h5,h6 {margin-top:0.1em;}
h1 {font-size:1.2em;}
h2 {font-size:1.0em;}
h3 {font-size:1.0em;}
h4 {font-size:0.8em;}
h5 {font-size:.0.8em;}

.headerShadow {position:relative; padding:2.0em 0em 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:2.0em 0em 1em 1em; left:0px; top:0px;}

#mainMenu {
position:absolute; left:0; width:15.5em; text-align:left; line-height:1.2em; 
padding:1.0em 0.5em 0.2em 0.5em; font-size:1em;
}

#displayArea {margin:1em 1em 0em 17em;}

/*
 toBalaFile 巨集的 Style 設定
*/
.toBalaFile {background:#fff; border:0px solid #ccc; padding:1px 7px 1px 3px; margin:2px;}
.toBalaFileEdit {border:1px solid #841;padding:2px;margin:2px 5px 2px 5px;}
.toBalaFileCancel {border:1px solid #841;padding:2px;margin:2px 5px 2px 5px;}
.toBalaFileToolBar {background:#fff;border-bottom: 3px solid #841;padding:3px 0px 5px 0px;margin:5px 0px 0px 5px;}
.toBalaFileSave {border:1px solid #841;padding:2px;margin:2px 5px 2px 5px;}

/*}}}*/
/*{{{*/
/***** LAYOUT STYLES -  DO NOT EDIT! *****/
ul.suckerfish, ul.suckerfish ul {
	margin: 0;
	padding: 0;
	list-style: none;
	line-height:1.4em;
}

ul.suckerfish  li {
	display: inline-block; 
	display: block;
	float: left; 
}

ul.suckerfish li ul {
	position: absolute;
	left: -999em;
}

ul.suckerfish li:hover ul, ul.suckerfish li.sfhover ul {
	left: auto;
}

ul.suckerfish ul li {
	float: none;
	border-right: 0;
	border-left:0;
}

ul.suckerfish a, ul.suckerfish a:hover {
	display: block;
}

ul.suckerfish li a.tiddlyLink, ul.suckerfish li a, #mainMenu ul.suckerfish li a {font-weight:bold;}
/**** END LAYOUT STYLES *****/


/**** COLORS AND APPEARANCE - DEFAULT *****/
ul.suckerfish li a {
	padding: 0.5em 1.5em;
	color: #FFF;
	background: #0066aa;
	border-bottom: 0;
	font-weight:bold;
}

ul.suckerfish li:hover a, ul.suckerfish li.sfhover a{
	background: #00558F;
}

ul.suckerfish li:hover ul a, ul.suckerfish li.sfhover ul a{
	color: #000;
	background: #eff3fa;
	border-top:1px solid #FFF;
}

ul.suckerfish ul li a:hover {
	background: #e0e8f5;
}

ul.suckerfish li a{
	width:9em;
}

ul.suckerfish ul li a, ul.suckerfish ul li a:hover{
	display:inline-block;
	width:9em;
}

ul.suckerfish li {
	border-left: 1px solid #00558F;
}
/***** END COLORS AND APPEARANCE - DEFAULT *****/


/***** LAYOUT AND APPEARANCE: VERTICAL *****/
ul.suckerfish.vertical li{
	width:10em;
	border-left: 0px solid #00558f;
}

ul.suckerfish.vertical ul li, ul.suckerfish.vertical li a, ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a {
	border-left: 0.8em solid #00558f;
}

ul.suckerfish.vertical li a, ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a,  ul.suckerfish.vertical li.sfhover a:hover{
	width:8em;
}

ul.suckerfish.vertical {
	width:10em; text-align:left;
	float:left;
}

ul.suckerfish.vertical li a {
	padding: 0.5em 1em 0.5em 1em;
	border-top:1px solid  #fff;
}

ul.suckerfish.vertical, ul.suckerfish.vertical ul {
	line-height:1.4em;
}

ul.suckerfish.vertical li:hover ul, ul.suckerfish.vertical li.sfhover ul { 
	margin: -2.4em 0 0 10.9em;
}

ul.suckerfish.vertical li:hover ul li a, ul.suckerfish.vertical li.sfhover ul li a {
	border: 0px solid #FFF;
}

ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a{
	padding-right:1.1em;
}

ul.suckerfish.vertical li:hover ul li, ul.suckerfish.vertical li.sfhover ul li {
	border-bottom:1px solid  #fff;
}

/***** END LAYOUT AND APPEARANCE: VERTICAL *****/
/*}}}*/
/*{{{*/
* html .tiddler {height:1%;}

body {font-size:.75em; font-family:arial,helvetica; margin:0; padding:0;}

h1,h2,h3,h4,h5,h6 {font-weight:bold; text-decoration:none;}
h1,h2,h3 {padding-bottom:1px; margin-top:1.2em;margin-bottom:0.3em;}
h4,h5,h6 {margin-top:1em;}
h1 {font-size:1.35em;}
h2 {font-size:1.25em;}
h3 {font-size:1.1em;}
h4 {font-size:1em;}
h5 {font-size:.9em;}

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

ol {list-style-type:decimal;}
ol ol {list-style-type:lower-alpha;}
ol ol ol {list-style-type:lower-roman;}
ol ol ol ol {list-style-type:decimal;}
ol ol ol ol ol {list-style-type:lower-alpha;}
ol ol ol ol ol ol {list-style-type:lower-roman;}
ol ol ol ol ol ol ol {list-style-type:decimal;}

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

.indent {margin-left:3em;}
.outdent {margin-left:3em; text-indent:-3em;}
code.escaped {white-space:nowrap;}

.tiddlyLinkExisting {font-weight:bold;}
.tiddlyLinkNonExisting {font-style:italic;}

/* the 'a' is required for IE, otherwise it renders the whole tiddler in bold */
a.tiddlyLinkNonExisting.shadow {font-weight:bold;}

#mainMenu .tiddlyLinkExisting,
	#mainMenu .tiddlyLinkNonExisting,
	#sidebarTabs .tiddlyLinkNonExisting {font-weight:normal; font-style:normal;}
#sidebarTabs .tiddlyLinkExisting {font-weight:bold; font-style:normal;}

.header {position:relative;}
.header a:hover {background:transparent;}
.headerShadow {position:relative; padding:4.5em 0em 1em 1em; left:-1px; top:-1px;}
.headerForeground {position:absolute; padding:4.5em 0em 1em 1em; left:0px; top:0px;}

.siteTitle {font-size:3em;}
.siteSubtitle {font-size:1.2em;}

#mainMenu {position:absolute; left:0; width:10em; text-align:right; line-height:1.6em; padding:1.5em 0.5em 0.5em 0.5em; font-size:1.1em;}

#sidebar {position:absolute; right:3px; width:16em; font-size:.9em;}
#sidebarOptions {padding-top:0.3em;}
#sidebarOptions a {margin:0em 0.2em; padding:0.2em 0.3em; display:block;}
#sidebarOptions input {margin:0.4em 0.5em;}
#sidebarOptions .sliderPanel {margin-left:1em; padding:0.5em; font-size:.85em;}
#sidebarOptions .sliderPanel a {font-weight:bold; display:inline; padding:0;}
#sidebarOptions .sliderPanel input {margin:0 0 .3em 0;}
#sidebarTabs .tabContents {width:15em; overflow:hidden;}

.wizard {padding:0.1em 1em 0em 2em;}
.wizard h1 {font-size:2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizard h2 {font-size:1.2em; font-weight:bold; background:none; padding:0em 0em 0em 0em; margin:0.4em 0em 0.2em 0em;}
.wizardStep {padding:1em 1em 1em 1em;}
.wizard .button {margin:0.5em 0em 0em 0em; font-size:1.2em;}
.wizardFooter {padding:0.8em 0.4em 0.8em 0em;}
.wizardFooter .status {padding:0em 0.4em 0em 0.4em; margin-left:1em;}
.wizard .button {padding:0.1em 0.2em 0.1em 0.2em;}

#messageArea {position:fixed; top:2em; right:0em; margin:0.5em; padding:0.5em; z-index:2000; _position:absolute;}
.messageToolbar {display:block; text-align:right; padding:0.2em 0.2em 0.2em 0.2em;}
#messageArea a {text-decoration:underline;}

.tiddlerPopupButton {padding:0.2em 0.2em 0.2em 0.2em;}
.popupTiddler {position: absolute; z-index:300; padding:1em 1em 1em 1em; margin:0;}

.popup {position:absolute; z-index:300; font-size:.9em; padding:0; list-style:none; margin:0;}
.popup .popupMessage {padding:0.4em;}
.popup hr {display:block; height:1px; width:auto; padding:0; margin:0.2em 0em;}
.popup li.disabled {padding:0.4em;}
.popup li a {display:block; padding:0.4em; font-weight:normal; cursor:pointer;}
.listBreak {font-size:1px; line-height:1px;}
.listBreak div {margin:2px 0;}

.tabset {padding:1em 0em 0em 0.5em;}
.tab {margin:0em 0em 0em 0.25em; padding:2px;}
.tabContents {padding:0.5em;}
.tabContents ul, .tabContents ol {margin:0; padding:0;}
.txtMainTab .tabContents li {list-style:none;}
.tabContents li.listLink { margin-left:.75em;}

#contentWrapper {display:block;}
#splashScreen {display:none;}

#displayArea {margin:1em 17em 0em 14em;}

.toolbar {text-align:right; font-size:.9em;}

.tiddler {padding:1em 1em 0em 1em;}

.missing .viewer,.missing .title {font-style:italic;}

.title {font-size:1.6em; font-weight:bold;}

.missing .subtitle {display:none;}
.subtitle {font-size:1.1em;}

.tiddler .button {padding:0.2em 0.4em;}

.tagging {margin:0.5em 0.5em 0.5em 0; float:left; display:none;}
.isTag .tagging {display:block;}
.tagged {margin:0.5em; float:right;}
.tagging, .tagged {font-size:0.9em; padding:0.25em;}
.tagging ul, .tagged ul {list-style:none; margin:0.25em; padding:0;}
.tagClear {clear:both;}

.footer {font-size:.9em;}
.footer li {display:inline;}

.annotation {padding:0.5em; margin:0.5em;}

* html .viewer pre {width:99%; padding:0 0 1em 0;}
.viewer {line-height:1.4em; padding-top:0.5em;}
.viewer .button {margin:0em 0.25em; padding:0em 0.25em;}
.viewer blockquote {line-height:1.5em; padding-left:0.8em;margin-left:2.5em;}
.viewer ul, .viewer ol {margin-left:0.5em; padding-left:1.5em;}

.viewer table, table.twtable {border-collapse:collapse; margin:0.8em 1.0em;}
.viewer th, .viewer td, .viewer tr,.viewer caption,.twtable th, .twtable td, .twtable tr,.twtable caption {padding:3px;}
table.listView {font-size:0.85em; margin:0.8em 1.0em;}
table.listView th, table.listView td, table.listView tr {padding:0px 3px 0px 3px;}

.viewer pre {padding:0.5em; margin-left:0.5em; font-size:1.2em; line-height:1.4em; overflow:auto;}
.viewer code {font-size:1.2em; line-height:1.4em;}

.editor {font-size:1.1em;}
.editor input, .editor textarea {display:block; width:100%; font:inherit;}
.editorFooter {padding:0.25em 0em; font-size:.9em;}
.editorFooter .button {padding-top:0px; padding-bottom:0px;}

.fieldsetFix {border:0; padding:0; margin:1px 0px 1px 0px;}

.sparkline {line-height:1em;}
.sparktick {outline:0;}

.zoomer {font-size:1.1em; position:absolute; overflow:hidden;}
.zoomer div {padding:1em;}

* html #backstage {width:99%;}
* html #backstageArea {width:99%;}
#backstageArea {display:none; position:relative; overflow: hidden; z-index:150; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageToolbar {position:relative;}
#backstageArea a {font-weight:bold; margin-left:0.5em; padding:0.3em 0.5em 0.3em 0.5em;}
#backstageButton {display:none; position:absolute; z-index:175; top:0em; right:0em;}
#backstageButton a {padding:0.1em 0.4em 0.1em 0.4em; margin:0.1em 0.1em 0.1em 0.1em;}
#backstage {position:relative; width:100%; z-index:50;}
#backstagePanel {display:none; z-index:100; position:absolute; margin:0em 3em 0em 3em; padding:1em 1em 1em 1em;}
.backstagePanelFooter {padding-top:0.2em; float:right;}
.backstagePanelFooter a {padding:0.2em 0.4em 0.2em 0.4em;}
#backstageCloak {display:none; z-index:20; position:absolute; width:100%; height:100px;}

.whenBackstage {display:none;}
.backstageVisible .whenBackstage {display:block;}
/*}}}*/
<<tabs txtMoreTab "未完成" "內容空白的文章" TabMoreMissing "未引用" "未被引用的文章" TabMoreOrphans "預設文章" "已預設內容的隱藏文章" TabMoreShadowed>>
<<list shadowed>>
<<allTags excludeLists>>
<<timeline>>
/***
|Name|TaggedTemplateTweak|
|Source|http://www.TiddlyTools.com/#TaggedTemplateTweak|
|Version|1.1.0|
|Author|Eric Shulman - ELS Design Studios|
|License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|~CoreVersion|2.1|
|Type|plugin|
|Requires||
|Overrides|Story.prototype.chooseTemplateForTiddler()|
|Description|use alternative ViewTemplate/EditTemplate for tiddler's tagged with specific tag values|
The core function, "story.chooseTemplateForTiddler(title,template)" is essentially a "pass-thru" that returns the same template it was given, and is provided by the core so that plugins can customize the template selection logic to select alternative templates, based on whatever programmatic criteria is appropriate.  This tweak extends story.chooseTemplateForTiddler() so that ''whenever a tiddler is marked with a specific tag value, it can be viewed and/or edited using alternatives to the standard tiddler templates.'' 
!!!!!Usage
<<<
Each alternative template is associated with a specific tiddler tag value by using that tag value as a prefix added to the standard TiddlyWiki template titles, [[ViewTemplate]] and [[EditTemplate]].

For example, any tiddlers that are tagged with ''<<tag media>>'' will look for alternative templates named [[mediaViewTemplate]] and [[mediaEditTemplate]].  Additionally, in order to find templates that have proper WikiWord tiddler titles (e.g., [[MediaViewTemplate]] and [[MediaEditTemplate]]), the plugin will also attempt to use a capitalized form of the tag value (e.g., ''Media'') as a prefix.  //This capitalization is for comparison purposes only and will not alter the actual tag values that are stored in the tiddler.//

If no matching alternative template can be found by using //any// of the tiddler's tags (either "as-is" or capitalized), the tiddler defaults to using the appropriate standard [[ViewTemplate]] or [[EditTemplate]] definition.

''To add your own custom templates:''
>First, decide upon a suitable tag keyword to uniquely identify your custom templates and create custom view and/or edit templates using that keyword as a prefix (e.g., "KeywordViewTemplate" and "KeywordEditTemplate").  Then, simply create a tiddler and tag it with your chosen keyword... that's it!  As long as the tiddler is tagged with your keyword, it will be displayed using the corresponding alternative templates.  If you remove the tag or rename/delete the alternative templates, the tiddler will revert to using the standard viewing and editing templates.
<<<
!!!!!Examples
<<<
|Sample tiddler| tag | view template | edit template |
|[[MediaSample - QuickTime]]| <<tag media>> | [[MediaViewTemplate]] | [[MediaEditTemplate]] |
|[[MediaSample - Windows]]| <<tag media>> | [[MediaViewTemplate]] | [[MediaEditTemplate]] |
|[[CDSample]]| <<tag CD>> | [[CDViewTemplate]] | [[CDEditTemplate]] |
|<<newTiddler label:"create new task..." title:SampleTask tag:task text:"Type some text and then press DONE to view the task controls">> | <<tag task>> | [[TaskViewTemplate]] | [[EditTemplate]] |

//(note: if these samples are not present in your document, please visit// http://www.TiddlyTools.com/ //to view these sample tiddlers on-line)//
<<<
!!!!!Revisions
<<<
2007.06.23 [1.1.0] re-written to use automatic 'tag prefix' search instead of hard coded check for each tag.  Allows new custom tags to be used without requiring code changes to this plugin.
2007.06.11 [1.0.0] initial release
<<<
!!!!!Code
***/
//{{{
version.extensions.taggedTemplate= {major: 1, minor: 1, revision: 0, date: new Date(2007,6,18)};
Story.prototype.taggedTemplate_chooseTemplateForTiddler = Story.prototype.chooseTemplateForTiddler
Story.prototype.chooseTemplateForTiddler = function(title,template)
{
	// get default template from core
	var template=this.taggedTemplate_chooseTemplateForTiddler.apply(this,arguments);

	// if the tiddler to be rendered doesn't exist yet, just return core result
	var tiddler=store.getTiddler(title); if (!tiddler) return template;

	// look for template whose prefix matches a tag on this tiddler
	for (t=0; t<tiddler.tags.length; t++) {
		var tag=tiddler.tags[t];
		if (store.tiddlerExists(tag+template)) { template=tag+template; break; }
		// try capitalized tag (to match WikiWord template titles)
		var cap=tag.substr(0,1).toUpperCase()+tag.substr(1);
		if (store.tiddlerExists(cap+template)) { template=cap+template; break; }
	}

	return template;
}
//}}}
/***
|''Name:''|~TaggerPlugin|
|''Version:''|1.0.1 (2006-06-01)|
|''Source:''|http://tw.lewcid.org//#TaggerPlugin|
|''Author:''|SaqImtiaz|
|''Description:''|Provides a drop down listing current tiddler tags, and allowing toggling of tags.|
|''Documentation:''|[[TaggerPluginDocumentation]]|
|''Source Code:''|[[TaggerPluginSource]]|
|''~TiddlyWiki:''|Version 2.0.8 or better|
***/
// /%
config.tagger={defaults:{label:"Tags: ",tooltip:"Manage tiddler tags",taglist:"true",excludeTags:"",notags:"tiddler has no tags",aretags:"current tiddler tags:",toggletext:"add tags:"}};config.macros.tagger={};config.macros.tagger.arrow=(document.all?"▼":"▾");config.macros.tagger.handler=function(_1,_2,_3,_4,_5,_6){var _7=config.tagger.defaults;var _8=_5.parseParams("tagman",null,true);var _9=((_8[0].label)&&(_8[0].label[0])!=".")?_8[0].label[0]+this.arrow:_7.label+this.arrow;var _a=((_8[0].tooltip)&&(_8[0].tooltip[0])!=".")?_8[0].tooltip[0]:_7.tooltip;var _b=((_8[0].taglist)&&(_8[0].taglist[0])!=".")?_8[0].taglist[0]:_7.taglist;var _c=((_8[0].exclude)&&(_8[0].exclude[0])!=".")?(_8[0].exclude[0]).readBracketedList():_7.excludeTags.readBracketedList();if((_8[0].source)&&(_8[0].source[0])!="."){var _d=_8[0].source[0];}if(_d&&!store.getTiddler(_d)){return false;}var _e=function(e){if(!e){var e=window.event;}var _11=Popup.create(this);var _12=store.getTags();var _13=new Array();for(var i=0;i<_12.length;i++){_13.push(_12[i][0]);}if(_d){var _15=store.getTiddler(_d);_13=_15.tags.sort();}var _16=_6.tags.sort();var _17=function(_18,_19,_1a){var sp=createTiddlyElement(createTiddlyElement(_11,"li"),"span",null,"tagger");var _1c=createTiddlyButton(sp,_18,_1a+" '"+_19+"'",taggerOnToggle,"button","toggleButton");_1c.setAttribute("tiddler",_6.title);_1c.setAttribute("tag",_19);insertSpacer(sp);if(window.createTagButton_orig_mptw){createTagButton_orig_mptw(sp,_19)}else{createTagButton(sp,_19);}};createTiddlyElement(_11,"li",null,"listTitle",(_6.tags.length==0?_7.notags:_7.aretags));for(var t=0;t<_16.length;t++){_17("[x]",_16[t],"remove tag ");}createTiddlyElement(createTiddlyElement(_11,"li"),"hr");if(_b!="false"){createTiddlyElement(_11,"li",null,"listTitle",_7.toggletext);for(var i=0;i<_13.length;i++){if(!_6.tags.contains(_13[i])&&!_c.contains(_13[i])){_17("[ ]",_13[i],"add tag ");}}createTiddlyElement(createTiddlyElement(_11,"li"),"hr");}var _1f=createTiddlyButton(createTiddlyElement(_11,"li"),("Create new tag"),null,taggerOnToggle);_1f.setAttribute("tiddler",_6.title);if(_d){_1f.setAttribute("source",_d);}Popup.show(_11,false);e.cancelBubble=true;if(e.stopPropagation){e.stopPropagation();}return (false);};createTiddlyButton(_1,_9,_a,_e,"button","taggerDrpBtn");};window.taggerOnToggle=function(e){var tag=this.getAttribute("tag");var _22=this.getAttribute("tiddler");var _23=store.getTiddler(_22);if(!tag){var _24=prompt("Enter new tag:","");if(_24!=""&&_24!=null){var tag=_24;if(this.getAttribute("source")){var _26=store.getTiddler(this.getAttribute("source"));_26.tags.pushUnique(_24);}}else{return false;}}if(!_23||!_23.tags){store.saveTiddler(_22,_22,"",config.options.txtUserName,new Date(),tag);}else{if(_23.tags.find(tag)==null){_23.tags.push(tag);}else{if(!_24){_23.tags.splice(_23.tags.find(tag),1);}}store.saveTiddler(_23.title,_23.title,_23.text,_23.modifier,_23.modified,_23.tags);}story.refreshTiddler(_22,null,true);if(config.options.chkAutoSave){saveChanges();}return false;};setStylesheet(".tagger a.button {font-weight: bold;display:inline; padding:0px;}\n"+".tagger #toggleButton {padding-left:2px; padding-right:2px; margin-right:1px; font-size:110%;}\n"+"#nestedtagger {background:#2E5ADF; border: 1px solid #0331BF;}\n"+".popup .listTitle {color:#000;}\n"+"","TaggerStyles");window.lewcidTiddlerSwapTag=function(_27,_28,_29){for(var i=0;i<_27.tags.length;i++){if(_27.tags[i]==_28){_27.tags[i]=_29;return true;}}return false;};window.lewcidRenameTag=function(e){var tag=this.getAttribute("tag");var _2d=prompt("Rename tag '"+tag+"' to:",tag);if((_2d==tag)||(_2d==null)){return false;}if(store.tiddlerExists(_2d)){if(confirm(config.messages.overwriteWarning.format([_2d.toString()]))){story.closeTiddler(_2d,false,false);}else{return null;}}tagged=store.getTaggedTiddlers(tag);if(tagged.length!=0){for(var j=0;j<tagged.length;j++){lewcidTiddlerSwapTag(tagged[j],tag,_2d);}}if(store.tiddlerExists(tag)){store.saveTiddler(tag,_2d);}if(document.getElementById("tiddler"+tag)){var _2f=document.getElementById(story.idPrefix+tag);var _30=story.positionTiddler(_2f);var _31=document.getElementById(story.container);story.closeTiddler(tag,false,false);story.createTiddler(_31,_30,_2d,null);story.saveTiddler(_2d);}if(config.options.chkAutoSave){saveChanges();}return false;};window.onClickTag=function(e){if(!e){var e=window.event;}var _34=resolveTarget(e);var _35=(!isNested(_34));if((Popup.stack.length>1)&&(_35==true)){Popup.removeFrom(1);}else{if(Popup.stack.length>0&&_35==false){Popup.removeFrom(0);}}var _36=(_35==false)?"popup":"nestedtagger";var _37=createTiddlyElement(document.body,"ol",_36,"popup",null);Popup.stack.push({root:this,popup:_37});var tag=this.getAttribute("tag");var _39=this.getAttribute("tiddler");if(_37&&tag){var _3a=store.getTaggedTiddlers(tag);var _3b=[];var li,r;for(r=0;r<_3a.length;r++){if(_3a[r].title!=_39){_3b.push(_3a[r].title);}}var _3d=config.views.wikified.tag;if(_3b.length>0){var _3e=createTiddlyButton(createTiddlyElement(_37,"li"),_3d.openAllText.format([tag]),_3d.openAllTooltip,onClickTagOpenAll);_3e.setAttribute("tag",tag);createTiddlyElement(createTiddlyElement(_37,"li"),"hr");for(r=0;r<_3b.length;r++){createTiddlyLink(createTiddlyElement(_37,"li"),_3b[r],true);}}else{createTiddlyText(createTiddlyElement(_37,"li",null,"disabled"),_3d.popupNone.format([tag]));}createTiddlyElement(createTiddlyElement(_37,"li"),"hr");var h=createTiddlyLink(createTiddlyElement(_37,"li"),tag,false);createTiddlyText(h,_3d.openTag.format([tag]));createTiddlyElement(createTiddlyElement(_37,"li"),"hr");var _40=createTiddlyButton(createTiddlyElement(_37,"li"),("Rename tag '"+tag+"'"),null,lewcidRenameTag);_40.setAttribute("tag",tag);}Popup.show(_37,false);e.cancelBubble=true;if(e.stopPropagation){e.stopPropagation();}return (false);};if(!window.isNested){window.isNested=function(e){while(e!=null){var _42=document.getElementById("contentWrapper");if(_42==e){return true;}e=e.parentNode;}return false;};}config.shadowTiddlers.TaggerPluginDocumentation="The documentation is available [[here.|http://tw.lewcid.org/#TaggerPluginDocumentation]]";config.shadowTiddlers.TaggerPluginSource="The uncompressed source code is available [[here.|http://tw.lewcid.org/#TaggerPluginSource]]";
// %/
/***
|''Name:''|TagsTreePlugin|
|''Description:''|Displays tags hierachy as a tree of tagged tiddlers.<br>Can be used to create dynamic outline navigation.|
|''Version:''|1.0.1|
|''Date:''|Jan 04,2008|
|''Source:''|http://visualtw.ouvaton.org/VisualTW.html|
|''Author:''|Pascal Collin|
|''License:''|[[BSD open source license|License]]|
|''~CoreVersion:''|2.1.0|
|''Browser:''|Firefox 2.0; InternetExplorer 6.0|
!Demo
On the plugin [[homepage|http://visualtw.ouvaton.org/VisualTW.html]] :
*Try to tag some <<newTiddler>> with a tag displayed in the menu and edit MainMenu.
*Look at some tags like [[Plugins]] or [[menu]].
!Installation
#import the plugin,
#save and reload,
#optionally, edit TagsTreeStyleSheet.
! Usage
{{{<<tagsTree>>}}} macro accepts the following //optional// parameters.
|!#|!parameter|!description|!by default|
|1|{{{root}}}|Uses {{{root}}} tag as tree root|- In a //tiddler// content or template : uses the tiddler as root tag.<br>- In the //page// content or template (by ex MainMenu) : displays all untagged tags.|
|2|{{{excludeTag}}}|Excludes all such tagged tiddlers from the tree|Uses default excludeLists tag|
|3|{{{level}}}|Expands nodes until level {{{level}}}.<br>Value {{{0}}} hides expand/collapse buttons.|Nodes are collapsed on first level|
|4|{{{depth}}}|Hierachy depth|6 levels depth (H1 to H6 header styles)|
|5|{{{sortField}}}|Alternate sort field. By example : "index".|Sorts tags and tiddlers alphabetically (on their title)|
|6|{{{labelField}}}|Alertnate label field. By example : "label".|Displays tiddler's title|

!Useful addons
*[[FieldsEditorPlugin]] : //create//, //edit//, //view// and //delete// commands in toolbar <<toolbar fields>>.
*[[TaggerPlugin]] : Provides a drop down listing current tiddler tags, and allowing toggling of tags.
!Advanced Users
You can change the global defaults for TagsTreePlugin, like default {{{level}}} value or level styles, by editing or overriding the first config.macros.tagsTree attributes below.
!Code
***/
//{{{
config.macros.tagsTree = {
	expand : "+",
	collapse : "–",
	depth : 6,
	level : 1,
	sortField : "",	
	labelField : "",
	styles : ["h1","h2","h3","h4","h5","h6"],
	trees : {}
}

config.macros.tagsTree.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
	var root = params[0] ? params[0] : (tiddler ? tiddler.title : null);
	var excludeTag = params[1] ? params[1] : "excludeTagsTree";
	var level = params[2] ? params[2] : config.macros.tagsTree.level;
	var depth = params[3] ? params[3] : config.macros.tagsTree.depth;
	var sortField = params[4] ? params[4] : config.macros.tagsTree.sortField;
	var labelField = params[5] ? params[5] : config.macros.tagsTree.labelField;
	var showButtons = (level>0);
	var id = config.macros.tagsTree.getId(place);
	if (config.macros.tagsTree.trees[id]==undefined) config.macros.tagsTree.trees[id]={};
	config.macros.tagsTree.createSubTree(place,id,root,excludeTag,[],level>0 ? level : 1,depth, sortField, labelField,showButtons);
}

config.macros.tagsTree.createSubTree = function(place, id, root, excludeTag, ancestors, level, depth, sortField, labelField,showButtons){
	var childNodes = root ? this.getChildNodes(root, ancestors) : this.getRootTags(excludeTag);
	var isOpen = (level>0) || (!showButtons);
	if (root && this.trees[id][root]!=undefined) isOpen = this.trees[id][root]; 
	if (root && ancestors.length) {
		var t = store.getTiddler(root);
		if (childNodes.length && depth>0) {
			var wrapper = createTiddlyElement(place , this.styles[Math.min(Math.max(ancestors.length,1),6)-1],null,"branch");
			if (showButtons) {
				b = createTiddlyButton(wrapper, isOpen ? config.macros.tagsTree.collapse : config.macros.tagsTree.expand, null, config.macros.tagsTree.onClick);
				b.setAttribute("treeId",id);
				b.setAttribute("tiddler",root);					
			}
			createTiddlyText(createTiddlyLink(wrapper, root),t&&labelField ? t.fields[labelField] ? t.fields[labelField] : root : root);
		}
		else 
			createTiddlyText(createTiddlyLink(place, root,false,"leaf"),t&&labelField ? t.fields[labelField] ? t.fields[labelField] : root : root);
	}
	if (childNodes.length && depth) {
		var d = createTiddlyElement(place,"div",null,"subtree");
		d.style.display= isOpen ? "block" : "none";
		if (sortField)
			childNodes.sort(function(a, b){
				var fa=a.fields[sortField];
				var fb=b.fields[sortField];
				return (fa==undefined && fb==undefined) ? a.title < b.title ? -1 : a.title > b.title ? 1 : 0 : (fa==undefined && fb!=undefined) ? 1 :(fa!=undefined && fb==undefined) ? -1 : fa < fb ? -1 : fa > fb ? 1 : 0;
			})
		for (var cpt=0; cpt<childNodes.length; cpt++)
			this.createSubTree(d, id, childNodes[cpt].title, excludeTag, ancestors.concat(root), level-1, depth-1, sortField, labelField, showButtons);	
	}	
}

config.macros.tagsTree.onClick = function(e){
	var id = this.getAttribute("treeId");
	var tiddler = this.getAttribute("tiddler");	
	var n = this.parentNode.nextSibling;
	var isOpen = n.style.display != "none";
	if(config.options.chkAnimate && anim && typeof Slider == "function")
		anim.startAnimating(new Slider(n,!isOpen,null,"none"));
	else
		n.style.display = isOpen ? "none" : "block";
	this.firstChild.nodeValue = isOpen ? config.macros.tagsTree.expand : config.macros.tagsTree.collapse;
	config.macros.tagsTree.trees[id][tiddler]=!isOpen;
	return false;
}

config.macros.tagsTree.getChildNodes = function(root ,ancestors){
	var childs = store.getTaggedTiddlers(root);
	var result = new Array();
	for (var cpt=0; cpt<childs.length; cpt++)
		if (childs[cpt].title!=root && ancestors.indexOf(childs[cpt].title)==-1) result.push(childs[cpt]);
	return result;
}

config.macros.tagsTree.getRootTags = function(excludeTag){
	var tags = store.getTags(excludeTag);
	tags.sort(function(a,b) {return a[0].toLowerCase() < b[0].toLowerCase() ? -1 : (a[0].toLowerCase() == b[0].toLowerCase() ? 0 : +1);});
	var result = new Array();
	for (var cpt=0; cpt<tags.length; cpt++) {
		var t = store.getTiddler(tags[cpt][0]);
		if (!t || t.tags.length==0) result.push(t ? t : {title:tags[cpt][0],fields:{}});
	}
	return result;
}

config.macros.tagsTree.getId = function(element){
	while (!element.id && element.parentNode) element=element.parentNode;
	return element.id ? element.id : "<html>";
}

config.shadowTiddlers.TagsTreeStyleSheet = "/*{{{*/\n";
config.shadowTiddlers.TagsTreeStyleSheet +=".leaf, .subtree {display:block; margin-left : 0.5em}\n";
config.shadowTiddlers.TagsTreeStyleSheet +=".subtree {margin-bottom:0.5em}\n";
config.shadowTiddlers.TagsTreeStyleSheet +="#mainMenu {text-align:left}\n";
config.shadowTiddlers.TagsTreeStyleSheet +=".branch .button {border:1px solid #DDD; color:#AAA;font-size:9px;padding:0 2px;margin-right:0.3em;vertical-align:middle;text-align:center;}\n";
config.shadowTiddlers.TagsTreeStyleSheet +="/*}}}*/";

store.addNotification("TagsTreeStyleSheet", refreshStyles); 

config.shadowTiddlers.MainMenu="<<tagsTree>>"

config.shadowTiddlers.PageTemplate = config.shadowTiddlers.PageTemplate.replace(/id='mainMenu' refresh='content' /,"id='mainMenu' refresh='content' force='true' ")

//}}}
/*{{{*/
.leaf, .subtree {display:block}

/* 設定 Tree 第一層的 left margin */ 
#mainMenu>.subtree {margin-left:0em}

.leaf {margin-left:0.2em; margin-bottom:0.2em; color:navy;}
.subtree {margin-left:0.8em;}

.branch .button {
   border:1px solid #DDD; color:#999;
   font-size:10px;padding:0 4px;
   margin-right:0.5em;
   vertical-align:middle;text-align:center;
}

/*}}}*/
/***
|''Name:''|TiddlersBarPlugin|
|''Description:''|A bar to switch between tiddlers through tabs (like browser tabs bar).|
|''Version:''|1.2.5|
|''Date:''|Jan 18,2008|
|''Source:''|http://visualtw.ouvaton.org/VisualTW.html|
|''Author:''|Pascal Collin|
|''License:''|[[BSD open source license|License]]|
|''~CoreVersion:''|2.1.0|
|''Browser:''|Firefox 2.0; InternetExplorer 6.0, others|
!Tips
*Doubleclick on the tiddlers bar (where there is no tab) create a new tiddler.
*Tabs include a button to close {{{x}}} or save {{{!}}} their tiddler.
*By default, click on the current tab close all others tiddlers.
!Configuration options 
<<option chkDisableTabsBar>> Disable the tabs bar (to print, by example).
<<option chkHideTabsBarWhenSingleTab >> Automatically hide the tabs bar when only one tiddler is displayed. 
<<option txtSelectedTiddlerTabButton>> ''selected'' tab command button.
<<option txtPreviousTabKey>> previous tab access key.
<<option txtNextTabKey>> next tab access key.
!Code
***/
//{{{
config.options.chkDisableTabsBar = config.options.chkDisableTabsBar ? config.options.chkDisableTabsBar : false;
config.options.chkHideTabsBarWhenSingleTab  = config.options.chkHideTabsBarWhenSingleTab  ? config.options.chkHideTabsBarWhenSingleTab  : false;
config.options.txtSelectedTiddlerTabButton = config.options.txtSelectedTiddlerTabButton ? config.options.txtSelectedTiddlerTabButton : "closeOthers";
config.options.txtPreviousTabKey = config.options.txtPreviousTabKey ? config.options.txtPreviousTabKey : "";
config.options.txtNextTabKey = config.options.txtNextTabKey ? config.options.txtNextTabKey : "";
config.macros.tiddlersBar = {
	tooltip : "see ",
	tooltipClose : "click here to close this tab",
	tooltipSave : "click here to save this tab",
	promptRename : "Enter tiddler new name",
	currentTiddler : "",
	previousState : false,
	previousKey : config.options.txtPreviousTabKey,
	nextKey : config.options.txtNextTabKey,	
	tabsAnimationSource : null, //use document.getElementById("tiddlerDisplay") if you need animation on tab switching.
	handler: function(place,macroName,params) {
		var previous = null;
		if (config.macros.tiddlersBar.isShown())
			story.forEachTiddler(function(title,e){
				if (title==config.macros.tiddlersBar.currentTiddler){
					var d = createTiddlyElement(null,"span",null,"tab tabSelected");
					config.macros.tiddlersBar.createActiveTabButton(d,title);
					if (previous && config.macros.tiddlersBar.previousKey) previous.setAttribute("accessKey",config.macros.tiddlersBar.nextKey);
					previous = "active";
				}
				else {
					var d = createTiddlyElement(place,"span",null,"tab tabUnselected");
					var btn = createTiddlyButton(d,title,config.macros.tiddlersBar.tooltip + title,config.macros.tiddlersBar.onSelectTab);
					btn.setAttribute("tiddler", title);
					if (previous=="active" && config.macros.tiddlersBar.nextKey) btn.setAttribute("accessKey",config.macros.tiddlersBar.previousKey);
					previous=btn;
				}
				var isDirty =story.isDirty(title);
				var c = createTiddlyButton(d,isDirty ?"!":"x",isDirty?config.macros.tiddlersBar.tooltipSave:config.macros.tiddlersBar.tooltipClose, isDirty ? config.macros.tiddlersBar.onTabSave : config.macros.tiddlersBar.onTabClose,"tabButton");
				c.setAttribute("tiddler", title);
				if (place.childNodes) {
					place.insertBefore(document.createTextNode(" "),place.firstChild); // to allow break line here when many tiddlers are open
					place.insertBefore(d,place.firstChild); 
				}
				else place.appendChild(d);
			})
	}, 
	refresh: function(place,params){
		removeChildren(place);
		config.macros.tiddlersBar.handler(place,"tiddlersBar",params);
		if (config.macros.tiddlersBar.previousState!=config.macros.tiddlersBar.isShown()) {
			story.refreshAllTiddlers();
			if (config.macros.tiddlersBar.previousState) story.forEachTiddler(function(t,e){e.style.display="";});
			config.macros.tiddlersBar.previousState = !config.macros.tiddlersBar.previousState;
		}
	},
	isShown : function(){
		if (config.options.chkDisableTabsBar) return false;
		if (!config.options.chkHideTabsBarWhenSingleTab) return true;
		var cpt=0;
		story.forEachTiddler(function(){cpt++});
		return (cpt>1);
	},
	selectNextTab : function(){  //used when the current tab is closed (to select another tab)
		var previous="";
		story.forEachTiddler(function(title){
			if (!config.macros.tiddlersBar.currentTiddler) {
				story.displayTiddler(null,title);
				return;
			}
			if (title==config.macros.tiddlersBar.currentTiddler) {
				if (previous) {
					story.displayTiddler(null,previous);
					return;
				}
				else config.macros.tiddlersBar.currentTiddler=""; 	// so next tab will be selected
			}
			else previous=title;
			});		
	},
	onSelectTab : function(e){
		var t = this.getAttribute("tiddler");
		if (t) story.displayTiddler(null,t);
		return false;
	},
	onTabClose : function(e){
		var t = this.getAttribute("tiddler");
		if (t) {
			if(story.hasChanges(t) && !readOnly) {
				if(!confirm(config.commands.cancelTiddler.warning.format([t])))
				return false;
			}
			story.closeTiddler(t);
		}
		return false;
	},
	onTabSave : function(e) {
		var t = this.getAttribute("tiddler");
		if (!e) e=window.event;
		if (t) config.commands.saveTiddler.handler(e,null,t);
		return false;
	},
	onSelectedTabButtonClick : function(event,src,title) {
		var t = this.getAttribute("tiddler");
		if (!event) event=window.event;
		if (t && config.options.txtSelectedTiddlerTabButton && config.commands[config.options.txtSelectedTiddlerTabButton])
			config.commands[config.options.txtSelectedTiddlerTabButton].handler(event, src, t);
		return false;
	},
	onTiddlersBarAction: function(event) {
		var source = event.target ? event.target.id : event.srcElement.id; // FF uses target and IE uses srcElement;
		if (source=="tiddlersBar") story.displayTiddler(null,'New Tiddler',DEFAULT_EDIT_TEMPLATE,false,null,null);
	},
	createActiveTabButton : function(place,title) {
		if (config.options.txtSelectedTiddlerTabButton && config.commands[config.options.txtSelectedTiddlerTabButton]) {
			var btn = createTiddlyButton(place, title, config.commands[config.options.txtSelectedTiddlerTabButton].tooltip ,config.macros.tiddlersBar.onSelectedTabButtonClick);
			btn.setAttribute("tiddler", title);
		}
		else
			createTiddlyText(place,title);
	}
}

story.coreCloseTiddler = story.coreCloseTiddler? story.coreCloseTiddler : story.closeTiddler;
story.coreDisplayTiddler = story.coreDisplayTiddler ? story.coreDisplayTiddler : story.displayTiddler;

story.closeTiddler = function(title,animate,unused) {
	if (title==config.macros.tiddlersBar.currentTiddler)
		config.macros.tiddlersBar.selectNextTab();
	story.coreCloseTiddler(title,false,unused); //disable animation to get it closed before calling tiddlersBar.refresh
	var e=document.getElementById("tiddlersBar");
	if (e) config.macros.tiddlersBar.refresh(e,null);
}

story.displayTiddler = function(srcElement,tiddler,template,animate,unused,customFields,toggle){
	story.coreDisplayTiddler(config.macros.tiddlersBar.tabsAnimationSource,tiddler,template,animate,unused,customFields,toggle);
	var title = (tiddler instanceof Tiddler)? tiddler.title : tiddler;  
	if (config.macros.tiddlersBar.isShown()) {
		story.forEachTiddler(function(t,e){
			if (t!=title) e.style.display="none";
			else e.style.display="";
		})
		config.macros.tiddlersBar.currentTiddler=title;
	}
	var e=document.getElementById("tiddlersBar");
	if (e) config.macros.tiddlersBar.refresh(e,null);
}

var coreRefreshPageTemplate = coreRefreshPageTemplate ? coreRefreshPageTemplate : refreshPageTemplate;
refreshPageTemplate = function(title) {
	coreRefreshPageTemplate(title);
	if (config.macros.tiddlersBar) config.macros.tiddlersBar.refresh(document.getElementById("tiddlersBar"));
}

//ensureVisible=function (e) {return 0} //disable bottom scrolling (not useful now)

config.shadowTiddlers.StyleSheetTiddlersBar = "/*{{{*/\n";
config.shadowTiddlers.StyleSheetTiddlersBar += "#tiddlersBar .button {border:0}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += "#tiddlersBar .tab {white-space:nowrap}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += "#tiddlersBar {padding : 1em 0.5em 2px 0.5em}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += ".tabUnselected .tabButton, .tabSelected .tabButton {padding : 0 2px 0 2px; margin: 0 0 0 4px;}\n";
config.shadowTiddlers.StyleSheetTiddlersBar += ".tiddler, .tabContents {border:1px [[ColorPalette::TertiaryPale]] solid;}\n";
config.shadowTiddlers.StyleSheetTiddlersBar +="/*}}}*/";
store.addNotification("StyleSheetTiddlersBar", refreshStyles);

config.refreshers.none = function(){return true;}
config.shadowTiddlers.PageTemplate=config.shadowTiddlers.PageTemplate.replace(/<div id='tiddlerDisplay'><\/div>/m,"<div id='tiddlersBar' refresh='none' ondblclick='config.macros.tiddlersBar.onTiddlersBarAction(event)'></div>\n<div id='tiddlerDisplay'></div>");

//}}}
本文網址 : http://www.ithome.com.tw/itadm/article.php?c=64133

下一版Ubuntu 11.04的圖形使用者介面將由目前的GNOME改成10.10小筆電版所用的Unity介面。

根據外電報導,Ubuntu創辦人Mark Shuttleworth在周一(10/25)舉辦的Ubuntu開發者高峰會中宣佈,下一版Ubuntu 11.04的圖形使用者介面將由目前的GNOME改成10.10小筆電版所用的Unity介面。Mark Shuttleworth宣稱是因為使用者希望Unity介面成為Ubuntu標準介面才會如此決定。

不過使用Unity介面的前提是電腦能支援3D繪圖,如果電腦無法支援3D圖形功能,Ubuntu將會使用GNOME作為圖形介面。當然,在安裝時使用者仍可以自定選用GNOME為使用者介面。而針對GNOME及KDE所寫的程式亦可在Unity介面下執行。Mark Shuttleworth表示,兩者都是GNOME的外殼,只是外觀不同而已,Ubuntu不會拋棄GNOME。

GNOME 3.0將採用的GNOME Shell與Unity均使用MeeGO延伸出來的圖形程式庫Clutter來開發,因此具有一定的相容程度。

不過Mark Shuttleworth在國外媒體訪問中承認,仍須開發人員投入大量的工作之後才能把Unity介面移植到桌上型電腦。除了要針對桌上型電腦最佳化之外,由於Mark Shuttleworth認為將來的筆電都將整合觸控的功能,因此最新版的Ubuntu將加入多點觸控的功能uTouch到Unity介面。(編譯/沈經) 
<!--{{{-->
<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler > fields syncing permalink references jump'></div>
<div class='title' macro='view title'></div>
<div class='subtitle'><span macro='view modifier link'></span>, <span macro='view modified date'></span> (<span macro='message views.wikified.createdPrompt'></span> <span macro='view created date'></span>)</div>

<!--
<div class='tagging' macro='tagging'></div>
-->
<div class='tagged' macro='tags'></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
/***
|''Name:''|abego.IncludePlugin|
|''Version:''|1.0.0 (2007-02-08)|
|''Type:''|plugin|
|''Source:''|http://tiddlywiki.abego-software.de/#IncludePlugin|
|''Author:''|Udo Borkowski (ub [at] abego-software [dot] de)|
|''Documentation:''|[[IncludePlugin Documentation|http://tiddlywiki.abego-software.de/#%5B%5BIncludePlugin%20Documentation%5D%5D]]|
|''Community:''|([[del.icio.us|http://del.icio.us/post?url=http://tiddlywiki.abego-software.de/index.html%23IncludePlugin]]) ([[Support|http://groups.google.com/group/TiddlyWiki]])|
|''Copyright:''|&copy; 2007 [[abego Software|http://www.abego-software.de]]|
|''Licence:''|[[BSD open source license (abego Software)|http://www.abego-software.de/legal/apl-v10.html]]|
|''~CoreVersion:''|2.1.3|
|''Browser:''|Firefox 1.5.0.9 or better; Internet Explorer 6.0|
***/
//{{{

// Ensure the global abego namespace is set up.
if (!window.abego) window.abego = {};

var invokeLater = function(func, delay, priority) {
	return abego.invokeLater ? abego.invokeLater(func, delay, priority) : setTimeout(func,delay);
};

// Asynchronously load the given (local or remote) file.
// 
// @param url 		either an URL or a local file path to a file
//					Examples:
//						* http://www.abego-software.de/index.html
//						* file:///C:/abegoWebSite-Copy/index.html
//						* C:\abegoWebSite-Copy\index.html    (for Windows machines)
//							(Notice: backslashes in JavaScript string constants must be escaped, 
//							 i.e. the last example must be written as: "C:\\abegoWebSite-Copy\\index.html"
//							 when "hardcoded" in JavaScript source code)
// 
// @param callback 
//					function(content,url,params,errorMessage) 
//					called at the end of the operation. 
//					On success content holds the content of the loaded file. 
//					On error content is undefined and errorMessage holds an error message. 
//					params is the params passed into abego.loadFile.
//
// @param params 	passed through to the callback function
// 
abego.loadFile = function(url,callback,params) {

	var onLoad = function(status,params,responseText,url,xhr) {
		return status 
				? callback(responseText, url, params)
				: callback(undefined, url, params, "Error loading %0".format([url]));
	};
	
	// Make sure the URL is a real URL, with protocol prefix etc.
	if (url.search(/^((http(s)?)|(file)):/) != 0) {
		
		// no protocol specified. 
		if (url.search(/^((.\:\\)|(\\\\)|(\/))/) == 0) {
			// "url" is an "absolute" path to a local file. Prefix it with file://
			url = "file://"+url;
			
		} else {
			// "url" is a "relative" URL. Make it absolute
			
			// prefix the url with the directory containing the current document
			// (This also includes the protocol prefix)
			var documentPath = document.location.toString();
			var i = documentPath.lastIndexOf("/");
			url = documentPath.substr(0,i+1)+url;
		}
		// replace every \ by a /, to cover Windows style pathes
		url = url.replace(/\\/mg,"/");
	}
	
	loadRemoteFile(url,onLoad,params);

};

// Asynchronously load the given (local or remote) TiddlyWiki store.
// 
// @param url 		either an URL or a local file path to a TiddlyWiki file (absolute or relative)
//					Examples:
//						* http://www.abego-software.de/index.html
//						* file:///C:/abegoWebSite-Copy/index.html
//						* include/beta.html
//						* C:\abegoWebSite-Copy\index.html    (for Windows machines)
//							(Notice: backslashes in JavaScript string constants must be escaped, 
//							 i.e. the last example must be written as: "C:\\abegoWebSite-Copy\\index.html"
//							 when "hardcoded" in JavaScript source code)
// 
// @param callbackWithStore 
//					function(theStore,url,params,errorMessage) 
//					called at the end of the operation. 
//					On success theStore holds the loaded store (a TiddlyWiki object). 
//					On error theStore is undefined and errorMessage holds an error message. 
//					params is the params passed into abego.loadTiddlyWikiStore
//
// @param params 	passed through to the callbackWithStore
//
// @progress		[optional] function(message, sender, state, url, params) called in various situations during the operation,
//								typically used to show "the progress" of the operation.
//								sender: the constant "abego.loadTiddlyWikiStore"
//								state: one of these: "Started", "Processing", "Done", "Failed"
//									"Processing" means the data has been received and in now processed.
// 
abego.loadTiddlyWikiStore = function(url,callbackWithStore,params,progress) {
	
	var sendProgress = function(message, state) {
		if (progress)
			progress(message,"abego.loadTiddlyWikiStore",state,url,params);
	};
	
	// Load contents of a TiddlyWiki from a string
	//# Returns null on success, an error message otherwise.
	//# based on code from TiddlyWiki 2.2 alpha
	var importTiddlyWiki = function(store,text)
	{
		// Crack out the content - will be refactored to share code with saveChanges()
		var posOpeningDiv = text.indexOf(startSaveArea);
		var limitClosingDiv = text.indexOf("<!--POST-BODY-END--"+">");
		var posClosingDiv = text.lastIndexOf(endSaveArea,limitClosingDiv == -1 ? text.length : limitClosingDiv);
		if((posOpeningDiv == -1) || (posClosingDiv == -1))
			return config.messages.invalidFileError.format([url]);
		var content = "<html><body>" + text.substring(posOpeningDiv,posClosingDiv + endSaveArea.length) + "</body></html>";
		// Create the iframe
		var iframe = document.createElement("iframe");
		iframe.style.display = "none";
		document.body.appendChild(iframe);
		var doc = iframe.document;
		if(iframe.contentDocument)
			doc = iframe.contentDocument; // For NS6
		else if(iframe.contentWindow)
			doc = iframe.contentWindow.document; // For IE5.5 and IE6
		// Put the content in the iframe
		doc.open();
		doc.writeln(content);
		doc.close();
		// Load the content into a TiddlyWiki() object
		var storeArea = doc.getElementById("storeArea");
		store.loadFromDiv(storeArea,"store");
		// Get rid of the iframe
		iframe.parentNode.removeChild(iframe);
		return null;
	};
	
	var sendError = function(message) {
		sendProgress("Error when loading %0".format([url]),"Failed");
		callbackWithStore(undefined, url,params, message);
		return message;
	};
	
	var sendStore = function(store) {
		sendProgress("Loaded %0".format([url]),"Done");
		callbackWithStore(store, url, params);
		return null;
	};
	
	
	var callback = function(content,theURL,params,errorMessage) {
		if (content === undefined) {
			sendError(errorMessage);
			return;
		}
		
		sendProgress("Processing %0".format([url]),"Processing");
		var orig_invalidFileError = config.messages.invalidFileError;
		config.messages.invalidFileError = "The file '%0' does not appear to be a valid TiddlyWiki file";
		try {
			// Load the content into a TiddlyWiki() object
			var importStore = new TiddlyWiki();
			var errorText = importTiddlyWiki(importStore,content);
			if (errorText)
				sendError(errorText);
			else
				sendStore(importStore);

		} catch (ex) {
			sendError(exceptionText(ex));
		} finally {
			config.messages.invalidFileError = orig_invalidFileError;
		}
	};
	
	sendProgress("Start loading %0".format([url]),"Started");
	abego.loadFile(url,callback,params);
};


//==============================================================================
// Include Plugin 

(function(){

// only install once
if (abego.TiddlyWikiIncluder) return;


// --------------------------------------------------
// Constants

var WAITING = "waiting";
var LOADING = "loading";

var ANI_DURATION_HIDE_STATE = 1000;

var REFRESH_PRIORITY = -200;
var ANIMATION_PRIORITY = -100;
var UPDATE_STATE_PRIORITY = -300;

// --------------------------------------------------
// Variables

var useInclude;
var includes = []; // [] of Strings. the urls of the stores to include, in the sequence of the calls.
var includedStores = {}; // url(String) -> TiddlyWiki or String; when not (yet) loaded a status or error string.
var pendingOnLoadURLs = []; // [] of String. a list of urls that should be passed with the next "notifyListeners".
var refreshTiddlyWikiTimerID; // for delayed refresh
var listeners = [];
var progress;

// --------------------------------------------------
// Helper functions

var isIncludeEnabled = function() {
	if (useInclude === undefined)
		useInclude = config.options.chkUseInclude === undefined || config.options.chkUseInclude;
	return useInclude;
};

var getMissingIncludeMsg = function(url) {
	return "No include specified for %0".format([url])
};

// Called after one or more included TiddlyWikis are loaded
//
var notifyListeners = function() {
	var urls = pendingOnLoadURLs;
	pendingOnLoadURLs = [];
	if (urls.length) {
		for (var i= 0; i < listeners.length; i++)
			listeners[i](urls);
	}
};

var idleCount; // Reset to 0 when the system is "not idle", incremented inside refreshTiddlyWiki

var refreshTiddlyWiki = function() {
	// To avoid to much refreshing/flickering don't refresh immediately 
	// but wait until the system was idle for a certain time.
	
	if (refreshTiddlyWikiTimerID !== undefined) clearInterval(refreshTiddlyWikiTimerID);
	
	idleCount = 0;
	
	var sendDone = function() {
		abego.TiddlyWikiIncluder.sendProgress("","","Done");
	};
	
	refreshTiddlyWikiTimerID = setInterval(function() {
		idleCount++;
		if (idleCount <= 10)
			return;
			
		clearInterval(refreshTiddlyWikiTimerID);
		refreshTiddlyWikiTimerID = undefined;
			
		abego.TiddlyWikiIncluder.sendProgress("Refreshing...","","");
		refreshDisplay();
		invokeLater(sendDone,0,REFRESH_PRIORITY);
	},0);
};

// Calls callback for every loaded store and returns the first non-false/null.. value returned by callback.
//
// @param callback  function(store, url)
//
var forEachLoadedStore = function(callback) {
	var result;
	for (var i = 0; i < includes.length; i++) {
		var theStore = abego.TiddlyWikiIncluder.getStore(includes[i]);
		if (theStore && (result = callback(theStore, includes[i])))
			return result;
	}
};

var attachToStore = function() {
	if (!window.store)
		return invokeLater(attachToStore,100);
		
	var orig_fetchTiddler = store.fetchTiddler;
	
	store.fetchTiddler = function(title) {
		var t = orig_fetchTiddler.apply(this,arguments);
		if (t) return t;
		
		// When there is a shadowtiddler with that name done look for
		// any included tiddler since these would hide the shadow
		if (config.shadowTiddlers[title] !== undefined) return undefined;
		
		// Don't look for the "New Tiddler" tiddler in the included TiddlyWikis,
		// since returning such a tiddler (that is readonly) will make it impossible
		// in the Main TiddlyWiki to create new tiddlers.
		if (title == config.macros.newTiddler.title) return undefined;

		return forEachLoadedStore(
				function(theStore, url) {
					var t = theStore.fetchTiddler(title);
					if (t) 
						t.includeURL = url;
					return t;
				});
	};

	// We also refresh TiddlyWiki to reflect the new included Tiddlers (if we have any).
	if (includes.length)
		refreshTiddlyWiki();
};

var includeFromIncludeList = function() {
	if (!window.store)
		return invokeLater(includeFromIncludeList,100);
		
	var includeListText = store.getTiddlerText("IncludeList");
	if (includeListText) 
		wikify(includeListText,document.createElement("div"));
};

var getFunctionUsingForReallyEachTiddler = function(func) {
	var wrapper = function() {
		var orig_forEachTiddler = store.forEachTiddler;

		var forEachTiddlerWithIncludes = function(callback) {
			var done = {};
			var includeURL;

			var callbackWrapper = function(title, tiddler) {
				// ensure every title is only processed once
				if (done[title]) 
					return;
				done[title] = 1;
				
				// for "included tiddlers" set the includeURL;
				if (includeURL)
					tiddler.includeURL = includeURL;
				
				callback.apply(this,arguments);
			};
			
			// forEachTiddler over the original tiddlers
			orig_forEachTiddler.call(store, callbackWrapper);
			
			// add all shadowTiddler titles to done 
			// (to avoid an included store hides a shadow tiddler)
			for (var n in config.shadowTiddlers)
				done[n] = 1;

			// add all the "New Tiddler" tiddlerto done 
			// (to avoid an included store (with "New Tiddler") makes it impossible to create new tiddlers)
			done[config.macros.newTiddler.title] = 1;

			// forEachTiddler over every included store
			forEachLoadedStore(
					function(theStore, url) {
						includeURL = url;
						theStore.forEachTiddler(callbackWrapper);
					});
		};
		
		store.forEachTiddler = forEachTiddlerWithIncludes;
		try {
			return func.apply(this,arguments);
		} finally {
			store.forEachTiddler = orig_forEachTiddler;
		}
	};
	
	return wrapper;
};

var useForReallyEachTiddler = function(object,property) {
	return object[property] = getFunctionUsingForReallyEachTiddler(object[property]);
};


//================================================================================
// abego.TiddlyWikiIncluder

abego.TiddlyWikiIncluder = {};

abego.TiddlyWikiIncluder.setProgressFunction = function(func) {
	progress = func;
};

abego.TiddlyWikiIncluder.getProgressFunction = function(func) {
	return progress;
};

abego.TiddlyWikiIncluder.sendProgress = function(message, sender, state) {
	if (progress)
		progress.apply(this,arguments);
};


// Called when an included TiddlyWiki could not be loaded.
//
// By default an error message is displayed.
//
abego.TiddlyWikiIncluder.onError = function(url, errorMessage) {
	displayMessage("Error when including '%0':\n%1".format([url, errorMessage]));
};


// Returns true when there are "pending" includes, i.e. TiddlyWiki that are not yet loaded.
//
// A TiddlyWiki that failed loading is not pending.
//
abego.TiddlyWikiIncluder.hasPendingIncludes = function() {
	for (var i = 0; i < includes.length; i++) {
		var state = abego.TiddlyWikiIncluder.getState(includes[i]);
		if (state == WAITING || state == LOADING)
			return true;
	}
	return false;
};


// @return [] of Strings, the URLs of the includes
//
abego.TiddlyWikiIncluder.getIncludes = function() {
	return includes.slice();
};


// @return [may be null] a state/error text of the store with the given URL, or null when the store is already loaded
//
abego.TiddlyWikiIncluder.getState = function(url) {
	var s = includedStores[url];
	if (!s)
		return getMissingIncludeMsg(url);
	return typeof s == "string" ? s : null;
};


// @return [may be null] the (TiddlyWiki) store  with the given URL, null if not (yet) loaded.
//
abego.TiddlyWikiIncluder.getStore = function(url) {
	var s = includedStores[url];
	if (!s)
		return getMissingIncludeMsg(url);
	return s instanceof TiddlyWiki ? s : null;
};


// Includes the (local or remote) TiddlyWiki store with the given url.
// 
// stores with urls already already included are ignored.
//
// @param url	see url@abego.loadTiddlyWikiStore
// @param delayMilliSeconds [optional] if defined loading starts delayMilliSeconds later, otherwise "immediately"
//
abego.TiddlyWikiIncluder.include = function(url, delayMilliSeconds) {
	if (!isIncludeEnabled() || includedStores[url])
		return;
	var self = this;
	
	includes.push(url);
	includedStores[url] = WAITING;

	var loadStoreCallback = function(theStore,urlInCallback,params,errorMessage) {
		if (theStore === undefined) {
			includedStores[url] = errorMessage;
			self.onError(url, errorMessage);
			return;
		}
		includedStores[url] = theStore;
		pendingOnLoadURLs.push(url);
		invokeLater(notifyListeners);
	};
	
	var loadStore = function() {
		includedStores[url] = LOADING;
		abego.loadTiddlyWikiStore(url,loadStoreCallback,null,progress);
	};
	
	if (delayMilliSeconds)
		invokeLater(loadStore, delayMilliSeconds);
	else
		loadStore();
};


// iterates over all tiddlers of "the store" and all tiddlers of included (and loaded) stores
//
abego.TiddlyWikiIncluder.forReallyEachTiddler = function(callback) {
	var caller = function() {
		store.forEachTiddler(callback);
	};
	
	getFunctionUsingForReallyEachTiddler(caller).call(store);
};


// function abego.TiddlyWikiIncluder.getFunctionUsingForReallyEachTiddler(func)
//
// Returns a function that behaves as func, but every call to store.forEachTiddler will actually 
// be a call to forReallyEachTiddler, i.e. iterate over the tiddlers the main store and of the 
// included TiddlyWikis
//
// @return the patched function
//
abego.TiddlyWikiIncluder.getFunctionUsingForReallyEachTiddler = getFunctionUsingForReallyEachTiddler;


// function abego.TiddlyWikiIncluder.useForReallyEachTiddler(object,property)
//
// Patches the function hold in the given property of the object in such a way that every call
// to store.forEachTiddler will actually be a call to forReallyEachTiddler, i.e. iterate over the
// tiddlers the main staire and of the included TiddlyWikis
//
// @param object
// @param property the name of the property of the object containing the function to be patched.
// @return the patched function
//
abego.TiddlyWikiIncluder.useForReallyEachTiddler = useForReallyEachTiddler;


// Add a listener function to the TiddlyWikiIncluder.
//
// @param listener function(urls)
//							url: [] of Strings, containing the urls of the TiddlyWiki just included
//									(see url@abego.TiddlyWikiIncluder.include)
//						called whenever one or more TiddlyWiki store are successfully included.
//
abego.TiddlyWikiIncluder.addListener = function(listener) {
	listeners.push(listener);
};

// -------------------------------------------------------------------------------
// TiddlyWikiIncluder initialization code

abego.TiddlyWikiIncluder.addListener(refreshTiddlyWiki);

//----------------------------------------------------------------------------
// Options Support

if (config.options.chkUseInclude === undefined) config.options.chkUseInclude = true;

config.shadowTiddlers.AdvancedOptions += "\n<<option chkUseInclude>> Include ~TiddlyWikis (IncludeList | IncludeState | [[help|http://tiddlywiki.abego-software.de/#%5B%5BIncludePlugin%20Documentation%5D%5D]])\n^^(Reload this ~TiddlyWiki to make changes become effective)^^";
config.shadowTiddlers.IncludeState = "<<includeState>>";

//================================================================================
// Default Progress Handling for abego.TiddlyWikiIncluder

var showAnimated = function(e, showing, duration) {
	if (!anim || !abego.ShowAnimation) {
		e.style.display = showing ? "block" : "none";
		return;
	}
	
	anim.startAnimating(new abego.ShowAnimation(e,showing,duration));
};

abego.TiddlyWikiIncluder.getDefaultProgressFunction = function() {

	setStylesheet(
		".includeProgressState{\n"+
		"background-color:#FFCC00;\n"+
		"position:absolute;\n"+
		"right:0.2em;\n"+
		"top:0.2em;\n"+
		"width:7em;\n"+
		"padding-left:0.2em;\n"+
		"padding-right:0.2em\n"+
		"}\n",
		"abegoInclude");

	var createStateElem = function() {
		var e = document.createElement("div");
		e.className = "includeProgressState";
		e.style.display = "none";
		document.body.appendChild(e);
		return e;
	};
	
	var stateElem = createStateElem();


	var showState = function(message) {
		removeChildren(stateElem);
		createTiddlyText(stateElem,message);
		showAnimated(stateElem,true,0);
	};

	var hideState = function() {
		// hide the state the next idle time 
		invokeLater(function() {
			showAnimated(stateElem,false,ANI_DURATION_HIDE_STATE);
		},100,ANIMATION_PRIORITY);
	};
	
	var myProgressFunction = function(message, sender, state, url, params) {
		
		if (state == "Done" || state == "Failed") {
			hideState();
			return;
		}
		
		if (sender == "abego.loadTiddlyWikiStore") {
			idleCount = 0;
			if (state == "Processing")
				showState("Including...");
		} else {
			showState(message);
		}
	};
	return myProgressFunction;
};

abego.TiddlyWikiIncluder.setProgressFunction(abego.TiddlyWikiIncluder.getDefaultProgressFunction());


//================================================================================
// The "include" macro
//
// Syntax: <<include {url}* [delay: {milliSeconds}] [hide: true] >>
//

config.macros.include = {};
config.macros.include.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
    params = paramString.parseParams("url",null,true,false,true); // allowEval, cascadeDefaults, names allowed
	var delay = parseInt(getParam(params,"delay","0"));
	var urls = params[0]["url"];
	var hide = getFlag(params, "hide", false);
	if (!hide)
		createTiddlyText(createTiddlyElement(place,"code"),wikifier.source.substring(wikifier.matchStart, wikifier.nextMatch));
	for (var i = 0; urls && i < urls.length; i++)
		abego.TiddlyWikiIncluder.include(urls[i],delay);
};


//================================================================================
// The "includeState" macro
//
// Syntax: <<includeState>>

config.macros.includeState = {};
config.macros.includeState.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
	var getFullState = function () {
		var s = "";
		var includes = abego.TiddlyWikiIncluder.getIncludes();
		if (!includes.length)
			return "{{noIncludes{\nNo includes or 'include' is disabled (see AdvancedOptions)\n}}}\n";
			
		s += "|!Address|!State|\n";
		for (var i = 0; i < includes.length; i++) {
			var inc = includes[i];
			s += "|{{{"+inc+"}}}|";
			var t = abego.TiddlyWikiIncluder.getState(inc);
			s += t ? "{{{"+t+"}}}" : "included";
			s += "|\n"
		}
		s += "|includeState|k\n";
		return s;
	};
	
	var updateState = function(){
		removeChildren(div);
		wikify(getFullState(),div);
		if (abego.TiddlyWikiIncluder.hasPendingIncludes())
			invokeLater(updateState,500,UPDATE_STATE_PRIORITY);
	};

	var div = createTiddlyElement(place,"div");
	
	invokeLater(updateState,0,UPDATE_STATE_PRIORITY);
};

//================================================================================
// Tiddler extension/modification

var orig_Tiddler_isReadOnly = Tiddler.prototype.isReadOnly;

// Includes tiddlers are readonly.
Tiddler.prototype.isReadOnly = function() {
	return orig_Tiddler_isReadOnly.apply(this,arguments) || this.isIncluded();
}

Tiddler.prototype.isIncluded = function() {
	return this.includeURL != undefined;
};

Tiddler.prototype.getIncludeURL = function() {
	return this.includeURL;
};


//================================================================================
// TiddlyWiki modifications

// In some TiddlyWiki functions the "forEachTiddler" should work on all tiddlers, also those from 
// included store. (E.g. TiddlyWiki.prototype.getTags)
//
// But not for all (e.g. TiddlyWiki.prototype.getTiddlers is used for saving, but only the "own" tiddlers should be saved)
//
// Therefore explicitly list the functions that should be "wrapped" to use the "forReallyEachTiddler".
//
var tiddlyWikiFunctionsUsingForReallyEachTiddler = {
	getMissingLinks: 1, getOrphans: 1,getTags:1, reverseLookup: 1, updateTiddlers: 1};
	
for (var n in tiddlyWikiFunctionsUsingForReallyEachTiddler)
	useForReallyEachTiddler(TiddlyWiki.prototype,n);


//================================================================================
// Make IntelliTagger "Include-aware"

var patchIntelliTagger = function() {
	if (abego.IntelliTagger)
		useForReallyEachTiddler(abego.IntelliTagger,"assistTagging");
};

//================================================================================
// Perform plugin startup tasks

attachToStore();
invokeLater(includeFromIncludeList,100);
invokeLater(patchIntelliTagger,100);

})();

//}}}
/***
|''Name:''|easyEditPlugin|
|''Description:''|Lite and extensible Wysiwyg editor for TiddlyWiki.|
|''Version:''|1.3.3|
|''Date:''|Dec 21,2007|
|''Source:''|http://visualtw.ouvaton.org/VisualTW.html|
|''Author:''|Pascal Collin|
|''License:''|[[BSD open source license|License]]|
|''~CoreVersion:''|2.1.0|
|''Browser:''|Firefox 2.0; InternetExplorer 6.0|
!Installation
#import the plugin,
#save and reload,
#use the <<toolbar easyEdit>> button in the tiddler's toolbar (in default ViewTemplate) or add {{{easyEdit}}} command in your own toolbar.
! Useful Addons
*[[HTMLFormattingPlugin|http://www.tiddlytools.com/#HTMLFormattingPlugin]] to embed wiki syntax in html tiddlers.<<br>>//__Tips__ : When this plugin is installed, you can use anchor syntax to link tiddlers in wysiwyg mode (example : #example). Anchors are converted back and from wiki syntax when editing.//
*[[TaggedTemplateTweak|http://www.TiddlyTools.com/#TaggedTemplateTweak]] to use alternative ViewTemplate/EditTemplate for tiddler's tagged with specific tag values.
!Configuration
|Buttons in the toolbar (empty = all).<<br>>//Example : bold,underline,separator,forecolor//<<br>>The buttons will appear in this order.| <<option txtEasyEditorButtons>>|
|EasyEditor default height | <<option txtEasyEditorHeight>>|
|Stylesheet applied to the edited richtext |[[EasyEditDocStyleSheet]]|
|Template called by the {{{write}}} button |[[EasyEditTemplate]]|
!How to extend EasyEditor
*To add your own buttons, add some code like the following in a systemConfig tagged tiddler (//use the prompt attribute only if there is a parameter//) :
**{{{EditorToolbar.buttons.heading = {label:"H", toolTip : "Set heading level", prompt: "Enter heading level"};}}} 
**{{{EditorToolbar.buttonsList +=",heading";}}}
*To get the list of all possible commands, see the documentation of the [[Gecko built-in rich text editor|http://developer.mozilla.org/en/docs/Midas]] or the [[IE command identifiers|http://msdn2.microsoft.com/en-us/library/ms533049.aspx]].
*To go further in customization, see [[Link button|EasyEditPlugin-LinkButton]] as an example.
!Code
***/

//{{{

var geckoEditor={};
var IEeditor={};

config.options.txtEasyEditorHeight = config.options.txtEasyEditorHeight ? config.options.txtEasyEditorHeight : "500px";
config.options.txtEasyEditorButtons = config.options.txtEasyEditorButtons ? config.options.txtEasyEditorButtons : "";

// TW2.1.x compatibility
config.browser.isGecko = config.browser.isGecko ? config.browser.isGecko : (config.userAgent.indexOf("gecko") != -1); 
config.macros.annotations = config.macros.annotations ? config.macros.annotations : {handler : function() {}}


// EASYEDITOR MACRO

config.macros.easyEdit = {
	handler : function(place,macroName,params,wikifier,paramString,tiddler) {
		var field = params[0];
		var height = params[1] ? params[1] : config.options.txtEasyEditorHeight;
		var editor = field ? new easyEditor(tiddler,field,place,height) : null;
	},
	gather: function(element){
		var iframes = element.getElementsByTagName("iframe");
		if (iframes.length!=1) return null
		var text = "<html>"+iframes[0].contentWindow.document.body.innerHTML+"</html>";
		text = config.browser.isGecko ? geckoEditor.postProcessor(text) : (config.browser.isIE ? IEeditor.postProcessor(text) : text);
		return text;
	}
}

// EASYEDITOR CLASS

function easyEditor(tiddler,field,place,height) {
	this.tiddler = tiddler;
	this.field = field;
	this.browser = config.browser.isGecko ? geckoEditor : (config.browser.isIE ? IEeditor : null);
	this.wrapper = createTiddlyElement(place,"div",null,"easyEditor");
	this.wrapper.setAttribute("easyEdit",this.field);
	this.iframe = createTiddlyElement(null,"iframe");
	this.browser.setupFrame(this.iframe,height,contextualCallback(this,this.onload));
	this.wrapper.appendChild(this.iframe);
}

easyEditor.prototype.onload = function(){
	this.editor = this.iframe.contentWindow;
	this.doc = this.editor.document;
	if (!this.browser.isDocReady(this.doc)) return null;
	
	if (!this.tiddler.isReadOnly() && this.doc.designMode.toLowerCase()!="on") {
		this.doc.designMode = "on";
		if (this.browser.reloadOnDesignMode) return false;	// IE fire readystatechange after designMode change
	}
	
	var internalCSS = store.getTiddlerText("EasyEditDocStyleSheet");
	setStylesheet(internalCSS,"EasyEditDocStyleSheet",this.doc);
	this.browser.initContent(this.doc,store.getValue(this.tiddler,this.field));

	var barElement=createTiddlyElement(null,"div",null,"easyEditorToolBar");
	this.wrapper.insertBefore(barElement,this.wrapper.firstChild);
	this.toolbar = new EditorToolbar(this.doc,barElement,this.editor);

	this.browser.plugEvents(this.doc,contextualCallback(this,this.scheduleButtonsRefresh));
	this.editor.focus();
}

easyEditor.SimplePreProcessoror = function(text) {
	var re = /^<html>(.*)<\/html>$/m;
	var htmlValue = re.exec(text);
	var value = (htmlValue && (htmlValue.length>0)) ? htmlValue[1] : text;
	return value;
}

easyEditor.prototype.scheduleButtonsRefresh=function() { //doesn't refresh buttons state when rough typing
	if (this.nextUpdate) window.clearTimeout(this.nextUpdate);
	this.nextUpdate = window.setTimeout(contextualCallback(this.toolbar,EditorToolbar.onUpdateButton),easyEditor.buttonDelay);
}

easyEditor.buttonDelay = 200;

// TOOLBAR CLASS

function EditorToolbar(target,parent,window){
	this.target = target;
	this.window=window;
	this.elements={};
	var row = createTiddlyElement(createTiddlyElement(createTiddlyElement(parent,"table"),"tbody"),"tr");
	var buttons = (config.options.txtEasyEditorButtons ? config.options.txtEasyEditorButtons : EditorToolbar.buttonsList).split(",");
	for(var cpt = 0; cpt < buttons.length; cpt++){
		var b = buttons[cpt];
		var button = EditorToolbar.buttons[b];
		if (button) {
			if (button.separator)
				createTiddlyElement(row,"td",null,"separator").innerHTML+="&nbsp;";
			else {
				var cell=createTiddlyElement(row,"td",null,b+"Button");
				if (button.onCreate) button.onCreate.call(this, cell, b);
				else EditorToolbar.createButton.call(this, cell, b);
			}
		}
	}
}

EditorToolbar.createButton = function(place,name){
	this.elements[name] = createTiddlyButton(place,EditorToolbar.buttons[name].label,EditorToolbar.buttons[name].toolTip,contextualCallback(this,EditorToolbar.onCommand(name)),"button");
}

EditorToolbar.onCommand = function(name){
	var button = EditorToolbar.buttons[name];
	return function(){
		var parameter = false;
		if (button.prompt) {
			var parameter = this.target.queryCommandValue(name);
			parameter = prompt(button.prompt,parameter);
		}
		if (parameter != null) {
			this.target.execCommand(name, false, parameter);
			EditorToolbar.onUpdateButton.call(this);
		}
		return false;
	}
}

EditorToolbar.getCommandState = function(target,name){
	try {return target.queryCommandState(name)}
	catch(e){return false}
}

EditorToolbar.onRefreshButton = function (name){
	if (EditorToolbar.getCommandState(this.target,name)) addClass(this.elements[name].parentNode,"buttonON");
	else removeClass(this.elements[name].parentNode,"buttonON");
	this.window.focus();
}

EditorToolbar.onUpdateButton = function(){
	for (b in this.elements) 
		if (EditorToolbar.buttons[b].onRefresh) EditorToolbar.buttons[b].onRefresh.call(this,b);
		else EditorToolbar.onRefreshButton.call(this,b);
}

EditorToolbar.buttons = {
	separator : {separator : true},
	bold : {label:"B", toolTip : "Bold"},
	italic : {label:"I", toolTip : "Italic"},
	underline : {label:"U", toolTip : "Underline"},
	strikethrough : {label:"S", toolTip : "Strikethrough"},
	insertunorderedlist : {label:"\u25CF", toolTip : "Unordered list"},
	insertorderedlist : {label:"1.", toolTip : "Ordered list"},
	justifyleft : {label:"[\u2261", toolTip : "Align left"},
	justifyright : {label:"\u2261]", toolTip : "Align right"},
	justifycenter : {label:"\u2261", toolTip : "Align center"},
	justifyfull : {label:"[\u2261]", toolTip : "Justify"},
	removeformat : {label:"\u00F8", toolTip : "Remove format"},
	fontsize : {label:"\u00B1", toolTip : "Set font size", prompt: "Enter font size"},
	forecolor : {label:"C", toolTip : "Set font color", prompt: "Enter font color"},
	fontname : {label:"F", toolTip : "Set font name", prompt: "Enter font name"},
	heading : {label:"H", toolTip : "Set heading level", prompt: "Enter heading level (example : h1, h2, ...)"},
	indent : {label:"\u2192[", toolTip : "Indent paragraph"},
	outdent : {label:"[\u2190", toolTip : "Outdent paragraph"},
	inserthorizontalrule : {label:"\u2014", toolTip : "Insert an horizontal rule"},
	insertimage : {label:"\u263C", toolTip : "Insert image", prompt: "Enter image url"}
}

EditorToolbar.buttonsList = "bold,italic,underline,strikethrough,separator,increasefontsize,decreasefontsize,fontsize,forecolor,fontname,separator,removeformat,separator,insertparagraph,insertunorderedlist,insertorderedlist,separator,justifyleft,justifyright,justifycenter,justifyfull,indent,outdent,separator,heading,separator,inserthorizontalrule,insertimage";

if (config.browser.isGecko) {
	EditorToolbar.buttons.increasefontsize = {onCreate : EditorToolbar.createButton, label:"A", toolTip : "Increase font size"};
	EditorToolbar.buttons.decreasefontsize = {onCreate : EditorToolbar.createButton, label:"A", toolTip : "Decrease font size"};
	EditorToolbar.buttons.insertparagraph = {label:"P", toolTip : "Format as paragraph"};
}

// GECKO (FIREFOX, ...) BROWSER SPECIFIC METHODS

geckoEditor.setupFrame = function(iframe,height,callback) {
	iframe.setAttribute("style","width: 100%; height:" + height);
	iframe.addEventListener("load",callback,true);
}

geckoEditor.plugEvents = function(doc,onchange){
	doc.addEventListener("keyup", onchange, true);
	doc.addEventListener("keydown", onchange, true);
	doc.addEventListener("click", onchange, true);
}

geckoEditor.postProcessor = function(text){return text};

geckoEditor.preProcessor = function(text){return easyEditor.SimplePreProcessoror(text)}

geckoEditor.isDocReady = function() {return true;}

geckoEditor.reloadOnDesignMode=false;

geckoEditor.initContent = function(doc,content){
	if (content) doc.execCommand("insertHTML",false,geckoEditor.preProcessor(content));
}

// INTERNET EXPLORER BROWSER SPECIFIC METHODS
	
IEeditor.setupFrame = function(iframe,height,callback) {
	iframe.width="99%";  //IE displays the iframe at the bottom if 100%. CSS layout problem ? I don't know. To be studied...
	iframe.height=height.toString();
	iframe.attachEvent("onreadystatechange",callback);
}

IEeditor.plugEvents = function(doc,onchange){
	doc.attachEvent("onkeyup", onchange);
	doc.attachEvent("onkeydown", onchange);
	doc.attachEvent("onclick", onchange);
}

IEeditor.isDocReady = function(doc){
	if (doc.readyState!="complete") return false;
	if (!doc.body) return false;
	return (doc && doc.getElementsByTagName && doc.getElementsByTagName("head") && doc.getElementsByTagName("head").length>0);
}

IEeditor.postProcessor = function(text){return text};

IEeditor.preProcessor = function(text){return easyEditor.SimplePreProcessoror(text)}

IEeditor.reloadOnDesignMode=true;

IEeditor.initContent = function(doc,content){
	if (content) doc.body.innerHTML=IEeditor.preProcessor(content);
}
	
function contextualCallback(obj,func){
    return function(){return func.call(obj)}
}
	
Story.prototype.previousGatherSaveEasyEdit = Story.prototype.previousGatherSaveEasyEdit ? Story.prototype.previousGatherSaveEasyEdit : Story.prototype.gatherSaveFields; // to avoid looping if this line is called several times
Story.prototype.gatherSaveFields = function(e,fields){
	if(e && e.getAttribute) {
		var f = e.getAttribute("easyEdit");
		if(f){
			var newVal = config.macros.easyEdit.gather(e);
			if (newVal) fields[f] = newVal;
		}
		this.previousGatherSaveEasyEdit(e, fields);
	}
}

config.commands.easyEdit={
	text: "編輯網頁",
	tooltip: "Edit this tiddler in wysiwyg mode",
	readOnlyText: "檢視",
	readOnlyTooltip: "View the source of this tiddler",
	handler : function(event,src,title) {
		clearMessage();
		var tiddlerElem = document.getElementById(story.idPrefix + title);
		var fields = tiddlerElem.getAttribute("tiddlyFields");
		story.displayTiddler(null,title,"EasyEditTemplate",false,null,fields);
		return false;
	}
}

config.shadowTiddlers.ViewTemplate = config.shadowTiddlers.ViewTemplate.replace(/\+editTiddler/,"+editTiddler easyEdit");

config.shadowTiddlers.EasyEditTemplate = config.shadowTiddlers.EditTemplate.replace(/macro='edit text'/,"macro='easyEdit text'");

config.shadowTiddlers.EasyEditToolBarStyleSheet = "/*{{{*/\n";
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar {font-size:0.8em}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".editor iframe {border:1px solid #DDD}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar td{border:1px solid #888; padding:2px 1px 2px 1px; vertical-align:middle}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar td.separator{border:0}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .button{border:0;color:#444}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .buttonON{background-color:#EEE}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar {margin:0.25em 0}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .boldButton {font-weight:bold}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .italicButton .button {font-style:italic;padding-right:0.65em}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .underlineButton .button {text-decoration:underline}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .strikeButton .button {text-decoration:line-through}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .unorderedListButton {margin-left:0.7em}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .justifyleftButton .button {padding-left:0.1em}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .justifyrightButton .button {padding-right:0.1em}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .justifyfullButton .button, .easyEditorToolBar .indentButton .button, .easyEditorToolBar .outdentButton .button {padding-left:0.1em;padding-right:0.1em}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .increasefontsizeButton .button {padding-left:0.15em;padding-right:0.15em; font-size:1.3em; line-height:0.75em}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .decreasefontsizeButton .button {padding-left:0.4em;padding-right:0.4em; font-size:0.8em;}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .forecolorButton .button {color:red;}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet += ".easyEditorToolBar .fontnameButton .button {font-family:serif}\n" ;
config.shadowTiddlers.EasyEditToolBarStyleSheet +="/*}}}*/";

store.addNotification("EasyEditToolBarStyleSheet", refreshStyles); 

config.shadowTiddlers.EasyEditDocStyleSheet = "/*{{{*/\n \n/*}}}*/";
if (config.annotations) config.annotations.EasyEditDocStyleSheet = "This stylesheet is applied when editing a text with the wysiwyg easyEditor";

//}}}
/***
!Link button add-on
***/
//{{{
EditorToolbar.createLinkButton = function(place,name) {
	this.elements[name] = createTiddlyButton(place,EditorToolbar.buttons[name].label,EditorToolbar.buttons[name].toolTip,contextualCallback(this,EditorToolbar.onInputLink()),"button");
}

EditorToolbar.onInputLink = function() {
	return function(){
		var browser = config.browser.isGecko ? geckoEditor : (config.browser.isIE ? IEeditor : null);
		var value = browser ? browser.getLink(this.target) : "";
		value = prompt(EditorToolbar.buttons["createlink"].prompt,value);
		if (value) browser.doLink(this.target,value);
		else if (value=="") this.target.execCommand("unlink", false, value);
		EditorToolbar.onUpdateButton.call(this);
		return false;
	}
}

EditorToolbar.buttonsList += ",separator,createlink";

EditorToolbar.buttons.createlink = {onCreate : EditorToolbar.createLinkButton, label:"L", toolTip : "Set link", prompt: "Enter link url"};


geckoEditor.getLink=function(doc){
	var range=doc.defaultView.getSelection().getRangeAt(0);
	var container = range.commonAncestorContainer;
	var node = (container.nodeType==3) ? container.parentNode : range.startContainer.childNodes[range.startOffset];
	if (node && node.tagName=="A") {
		var r=doc.createRange();
		r.selectNode(node);
		doc.defaultView.getSelection().addRange(r);
		return (node.getAttribute("tiddler") ? "#"+node.getAttribute("tiddler") : node.href);
	}
	else return (container.nodeType==3 ? "#"+container.textContent.substr(range.startOffset, range.endOffset-range.startOffset).replace(/ $/,"") : "");
}

geckoEditor.doLink=function(doc,link){ // store tiddler in a temporary attribute to avoid url encoding of tiddler's name
	var pin = "href"+Math.random().toString().substr(3);
	doc.execCommand("createlink", false, pin);
	var isTiddler=(link.charAt(0)=="#");
	var node = doc.defaultView.getSelection().getRangeAt(0).commonAncestorContainer;
	var links= (node.nodeType!=3) ? node.getElementsByTagName("a") : [node.parentNode];
	for (var cpt=0;cpt<links.length;cpt++) 
			if (links[cpt].href==pin){
				links[cpt].href=isTiddler ? "javascript:;" : link; 
				links[cpt].setAttribute("tiddler",isTiddler ? link.substr(1) : "");
			}
}

geckoEditor.beforeLinkPostProcessor = geckoEditor.beforelinkPostProcessor ? geckoEditor.beforelinkPostProcessor : geckoEditor.postProcessor;
geckoEditor.postProcessor = function(text){
	return geckoEditor.beforeLinkPostProcessor(text).replace(/<a tiddler="([^"]*)" href="javascript:;">(.*?)(?:<\/a>)/gi,"[[$2|$1]]").replace(/<a tiddler="" href="/gi,'<a href="');
}

geckoEditor.beforeLinkPreProcessor = geckoEditor.beforeLinkPreProcessor ? geckoEditor.beforeLinkPreProcessor : geckoEditor.preProcessor
geckoEditor.preProcessor = function(text){
	return geckoEditor.beforeLinkPreProcessor(text).replace(/\[\[([^|\]]*)\|([^\]]*)]]/g,'<a tiddler="$2" href="javascript:;">$1</a>');
}


IEeditor.getLink=function(doc){
	var node=doc.selection.createRange().parentElement();
	if (node.tagName=="A") return node.href;
	else return (doc.selection.type=="Text"? "#"+doc.selection.createRange().text.replace(/ $/,"") :"");
}

IEeditor.doLink=function(doc,link){
	doc.execCommand("createlink", false, link);
}

IEeditor.beforeLinkPreProcessor = IEeditor.beforeLinkPreProcessor ? IEeditor.beforeLinkPreProcessor : IEeditor.preProcessor
IEeditor.preProcessor = function(text){
	return IEeditor.beforeLinkPreProcessor(text).replace(/\[\[([^|\]]*)\|([^\]]*)]]/g,'<a ref="#$2">$1</a>');
}

IEeditor.beforeLinkPostProcessor = IEeditor.beforelinkPostProcessor ? IEeditor.beforelinkPostProcessor : IEeditor.postProcessor;
IEeditor.postProcessor = function(text){
	return IEeditor.beforeLinkPostProcessor(text).replace(/<a href="#([^>]*)">([^<]*)<\/a>/gi,"[[$2|$1]]");
}

IEeditor.beforeLinkInitContent = IEeditor.beforeLinkInitContent ? IEeditor.beforeLinkInitContent : IEeditor.initContent;
IEeditor.initContent = function(doc,content){
	IEeditor.beforeLinkInitContent(doc,content);
	var links=doc.body.getElementsByTagName("A");
	for (var cpt=0; cpt<links.length; cpt++) {
		links[cpt].href=links[cpt].ref; //to avoid IE conversion of relative URLs to absolute
		links[cpt].removeAttribute("ref");	
	}
}

config.shadowTiddlers.EasyEditToolBarStyleSheet += "\n/*{{{*/\n.easyEditorToolBar .createlinkButton .button {color:blue;text-decoration:underline;}\n/*}}}*/";

config.shadowTiddlers.EasyEditDocStyleSheet += "\n/*{{{*/\na {color:#0044BB;font-weight:bold}\n/*}}}*/";

//}}}
//{{{
//============================================================================
// getCreateDate Function
//============================================================================
//
// Returns the "create date" as generated by the AutoTaggerPlugin
// (http://www.TiddlyTools.com/#AutoTaggerPlugin).
// The create date must be stored in the default format "YYYY.0MM.0DD".
//
// @return [may be null] the create date (as a String) or null if no create 
// date is found.
//
version.extensions.getCreateDate = {major: 1, minor: 0, revision: 0, 
 date: new Date(2005,11,21), 
 provider: "http://tiddlywiki.abego-software.de"};
//
function getCreateDate(tiddler) {
 if (!tiddler || !tiddler.tags) {
 return null;
 }

 for(var i = 0; i < tiddler.tags.length; i++) {
 var matches = tiddler.tags[i].match(/^[0-9]{4}\.[0-9]{2}\.[0-9]{2}$/);
 if (matches && matches.length > 0) {
 return matches[0];
 }
 }
 return null;
}

//}}}
/***
|''Name:''|zh-HantTranslationPlugin|
|''Description:''|Translation of TiddlyWiki into Traditional Chinese|
|''Source:''|http://tiddlywiki-zh.googlecode.com/svn/trunk/|
|''Subversion:''|http://svn.tiddlywiki.org/Trunk/association/locales/core/zh-Hant/locale.zh-Hant.js|
|''Author:''|BramChen (bram.chen (at) gmail (dot) com)|
|''Version:''|2.2.6|
|''Date:''|Dec 01, 2007|
|''Comments:''|Please make comments at http://groups-beta.google.com/group/TiddlyWiki-zh/|
|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|''~CoreVersion:''|2.2.0|
***/

//{{{
// --
// -- Translateable strings
// --

// Strings in "double quotes" should be translated; strings in 'single quotes' should be left alone

config.locale = 'zh-Hant'; // W3C language tag

if (config.options.txtUserName == 'YourName' || !config.options.txtUserName) // do not translate this line, but do translate the next line
	merge(config.options,{txtUserName: "YourName"});

merge(config.tasks,{
	save: {text: "儲存", tooltip: "儲存變更至此 TiddlyWiki", action: saveChanges},
	sync: {text: "同步", tooltip: "將你的資料內容與外部伺服器與檔案同步", content: '<<sync>>'},
	importTask: {text: "導入", tooltip: "自其他檔案或伺服器導入文章或套件", content: '<<importTiddlers>>'},
	tweak: {text: "選項", tooltip: "改變此 TiddlyWiki 的顯示與行為的設定", content: '<<options>>'},
	plugins: {text: "套件管理", tooltip: "管理已安裝的套件", content: '<<plugins>>'}
});

merge(config.optionsDesc,{
	txtUserName: "編輯文章所使用之作者署名",
	chkRegExpSearch: "啟用正規式搜尋",
	chkCaseSensitiveSearch: "搜尋時,區分大小寫",
	chkAnimate: "使用動畫顯示",
	chkSaveBackups: "儲存變更前,保留備份檔案",
	chkAutoSave: "自動儲存變更",
	chkGenerateAnRssFeed: "儲存變更時,也儲存 RSS feed",
	chkSaveEmptyTemplate: "儲存變更時,也儲存空白範本",
	chkOpenInNewWindow: "於新視窗開啟連結",
	chkToggleLinks: "點擊已開啟文章將其關閉",
	chkHttpReadOnly: "非本機瀏覽文件時,隱藏編輯功能",
	chkForceMinorUpdate: "修改文章時,不變更作者名稱與日期時間",
	chkConfirmDelete: "刪除文章前須確認",
	chkInsertTabs: "使用 tab 鍵插入定位字元,而非跳至下一個欄位",
	txtBackupFolder: "存放備份檔案的資料夾",
	txtMaxEditRows: "編輯模式中顯示列數",
	txtFileSystemCharSet: "指定儲存文件所在之檔案系統之字集 (僅適用於 Firefox/Mozilla only)"});

// Messages
merge(config.messages,{
	customConfigError: "套件載入發生錯誤,詳細請參考 PluginManager",
	pluginError: "發生錯誤: %0",
	pluginDisabled: "未執行,因標籤設為 'systemConfigDisable'",
	pluginForced: "已執行,因標籤設為 'systemConfigForce'",
	pluginVersionError: "未執行,套件需較新版本的 TiddlyWiki",
	nothingSelected: "尚未作任何選擇,至少需選擇一項",
	savedSnapshotError: "此 TiddlyWiki 未正確存檔,詳見 http://www.tiddlywiki.com/#DownloadSoftware",
	subtitleUnknown: "(未知)",
	undefinedTiddlerToolTip: "'%0' 尚無內容",
	shadowedTiddlerToolTip: "'%0' 尚無內容, 但已定義隱藏的預設值",
	tiddlerLinkTooltip: "%0 - %1, %2",
	externalLinkTooltip: "外部連結至 %0",
	noTags: "未設定標籤的文章",
	notFileUrlError: "須先將此 TiddlyWiki 存至檔案,才可儲存變更",
	cantSaveError: "無法儲存變更。可能的原因有:\n- 你的瀏覽器不支援此儲存功能(Firefox, Internet Explorer, Safari and Opera 經適當設定後可儲存變更)\n- 也可能是你的 TiddlyWiki 檔名包含不合法的字元所致。\n- 或是 TiddlyWiki 文件被改名或搬移。",
	invalidFileError: " '%0' 非有效之 TiddlyWiki 文件",
	backupSaved: "已儲存備份",
	backupFailed: "無法儲存備份",
	rssSaved: "RSS feed 已儲存",
	rssFailed: "無法儲存 RSS feed ",
	emptySaved: "已儲存範本",
	emptyFailed: "無法儲存範本",
	mainSaved: "主要的TiddlyWiki已儲存",
	mainFailed: "無法儲存主要 TiddlyWiki,所作的改變未儲存",
	macroError: "巨集 <<\%0>> 執行錯誤",
	macroErrorDetails: "執行巨集 <<\%0>> 時,發生錯誤 :\n%1",
	missingMacro: "無此巨集",
	overwriteWarning: "'%0' 已存在,[確定]覆寫之",
	unsavedChangesWarning: "注意! 尚未儲存變更\n\n[確定]存檔,或[取消]放棄存檔?",
	confirmExit: "--------------------------------\n\nTiddlyWiki 以更改內容尚未儲存,繼續的話將遺失這些更動\n\n--------------------------------",
	saveInstructions: "SaveChanges",
	unsupportedTWFormat: "未支援此 TiddlyWiki 格式:'%0'",
	tiddlerSaveError: "儲存文章 '%0' 時,發生錯誤。",
	tiddlerLoadError: "載入文章 '%0' 時,發生錯誤。",
	wrongSaveFormat: "無法使用格式 '%0' 儲存,請使用標准格式存放",
	invalidFieldName: "無效的欄位名稱:%0",
	fieldCannotBeChanged: "無法變更欄位:'%0'",
	loadingMissingTiddler: "正從伺服器 '%1' 的:\n\n工作區 '%3' 中的 '%2' 擷取文章 '%0'"});

merge(config.messages.messageClose,{
	text: "關閉",
	tooltip: "關閉此訊息"});

config.messages.backstage = {
	open: {text: "控制台", tooltip: "開啟控制台執行編寫工作"},
	close: {text: "關閉", tooltip: "關閉控制台"},
	prompt: "控制台:",
	decal: {
		edit: {text: "編輯", tooltip: "編輯 '%0'"}
	}
};

config.messages.listView = {
	tiddlerTooltip: "檢視全文",
	previewUnavailable: "(無法預覽)"
};

config.messages.dates.months = ["一月", "二月", "三月", "四月", "五月", "六月", "七月", "八月", "九月", "十月", "十一月", "十二月"];
config.messages.dates.days = ["星期日", "星期一","星期二", "星期三", "星期四", "星期五", "星期六"];
// config.messages.dates.shortMonths = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
config.messages.dates.shortMonths = ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"];
// config.messages.dates.shortDays = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
config.messages.dates.shortDays = ["日", "一","二", "三", "四", "五", "六"];
// suffixes for dates, eg "1st","2nd","3rd"..."30th","31st"
config.messages.dates.daySuffixes = ["st","nd","rd","th","th","th","th","th","th","th",
		"th","th","th","th","th","th","th","th","th","th",
		"st","nd","rd","th","th","th","th","th","th","th",
		"st"];
config.messages.dates.am = "上午";
config.messages.dates.pm = "下午";

merge(config.messages.tiddlerPopup,{ 
	});

merge(config.views.wikified.tag,{
	labelNoTags: "未設標籤",
	labelTags: "標籤: ",
	openTag: "開啟標籤 '%0'",
	tooltip: "顯示標籤為 '%0' 的文章",
	openAllText: "開啟以下所有文章",
	openAllTooltip: "開啟以下所有文章",
	popupNone: "僅此文標籤為 '%0'"});

merge(config.views.wikified,{
	defaultText: "",
	defaultModifier: "(未完成)",
	shadowModifier: "(預設)",
	dateFormat: "YYYY年0MM月0DD日",
	createdPrompt: "建立於"});

merge(config.views.editor,{
	tagPrompt: "設定標籤之間以空白區隔,[[標籤含空白時請使用雙中括弧]],或點選現有之標籤加入",
	defaultText: ""});

merge(config.views.editor.tagChooser,{
	text: "標籤",
	tooltip: "點選現有之標籤加至本文章",
	popupNone: "未設定標籤",
	tagTooltip: "加入標籤 '%0'"});

merge(config.messages,{
	sizeTemplates:
		[
		{unit: 1024*1024*1024, template: "%0\u00a0GB"},
		{unit: 1024*1024, template: "%0\u00a0MB"},
		{unit: 1024, template: "%0\u00a0KB"},
		{unit: 1, template: "%0\u00a0B"}
		]});

merge(config.macros.search,{
	label: " 尋找",
	prompt: "搜尋本 Wiki",
	accessKey: "F",
	successMsg: " %0 篇符合條件: %1",
	failureMsg: " 無符合條件: %0"});

merge(config.macros.tagging,{
	label: "引用標籤:",
	labelNotTag: "無引用標籤",
	tooltip: "列出標籤為 '%0' 的文章"});

merge(config.macros.timeline,{
	dateFormat: "YYYY年0MM月0DD日"});

merge(config.macros.allTags,{
	tooltip: "顯示文章- 標籤為'%0'",
	noTags: "沒有標籤"});

config.macros.list.all.prompt = "依字母排序";
config.macros.list.missing.prompt = "被引用且內容空白的文章";
config.macros.list.orphans.prompt = "未被引用的文章";
config.macros.list.shadowed.prompt = "這些隱藏的文章已預設內容";
config.macros.list.touched.prompt = "自下載或新增後被修改過的文章"; 

merge(config.macros.closeAll,{
	label: "全部關閉",
	prompt: "關閉所有開啟中的 tiddler (編輯中除外)"});

merge(config.macros.permaview,{
	label: "引用連結",
	prompt: "可存取現有開啟之文章的連結位址"});

merge(config.macros.saveChanges,{
	label: "儲存變更",
	prompt: "儲存所有文章,產生新的版本",
	accessKey: "S"});

merge(config.macros.newTiddler,{
	label: "新增文章",
	prompt: "新增 tiddler",
	title: "新增文章",
	accessKey: "N"});

merge(config.macros.newJournal,{
	label: "新增日誌",
	prompt: "新增 jounal",
	accessKey: "J"});

merge(config.macros.options,{
	wizardTitle: "增訂的進階選項",
	step1Title: "增訂的選項儲存於瀏覽器的 cookies",
	step1Html: "<input type='hidden' name='markList'></input><br><input type='checkbox' checked='false' name='chkUnknown'>顯示未知選項</input>",
	unknownDescription: "//(未知)//",
	listViewTemplate: {
		columns: [
			{name: 'Option', field: 'option', title: "選項", type: 'String'},
			{name: 'Description', field: 'description', title: "說明", type: 'WikiText'},
			{name: 'Name', field: 'name', title: "名稱", type: 'String'}
			],
		rowClasses: [
			{className: 'lowlight', field: 'lowlight'}
			]}
	});

merge(config.macros.plugins,{
	wizardTitle: "擴充套件管理",
	step1Title: "- 已載入之套件",
	step1Html: "<input type='hidden' name='markList'></input>", // DO NOT TRANSLATE
	skippedText: "(此套件因剛加入,故尚未執行)",
	noPluginText: "未安裝套件",
	confirmDeleteText: "確認是否刪除此文章:\n\n%0",
	removeLabel: "移除 systemConfig 標籤",
	removePrompt: "移除 systemConfig 標籤",
	deleteLabel: "刪除",
	deletePrompt: "永遠刪除所選",

	listViewTemplate : {
		columns: [
			{name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'},
			{name: 'Tiddler', field: 'tiddler', title: "套件", type: 'Tiddler'},
			{name: 'Size', field: 'size', tiddlerLink: 'size', title: "大小", type: 'Size'},
			{name: 'Forced', field: 'forced', title: "強制執行", tag: 'systemConfigForce', type: 'TagCheckbox'},
			{name: 'Disabled', field: 'disabled', title: "停用", tag: 'systemConfigDisable', type: 'TagCheckbox'},
			{name: 'Executed', field: 'executed', title: "已載入", type: "Boolean", trueText: "是", falseText: "否"},
			{name: 'Startup Time', field: 'startupTime', title: "載入時間", type: 'String'},
			{name: 'Error', field: 'error', title: "載入狀態", type: 'Boolean', trueText: "錯誤", falseText: "正常"},
			{name: 'Log', field: 'log', title: "紀錄", type: 'StringList'}
			],
		rowClasses: [
			{className: 'error', field: 'error'},
			{className: 'warning', field: 'warning'}
			]}
	});

merge(config.macros.toolbar,{
	moreLabel: "其他",
	morePrompt: "顯示更多工具命令"});
	
merge(config.macros.refreshDisplay,{
	label: "刷新",
	prompt: "刷新此 TiddlyWiki 顯示"
	});
	
merge(config.macros.importTiddlers,{
	readOnlyWarning: "TiddlyWiki 於唯讀模式下,不支援導入文章。請由本機(file://)開啟 TiddlyWiki 文件",
	wizardTitle: "自其他檔案或伺服器導入文章",
	step1Title: "步驟一:指定伺服器或來源文件",
	step1Html: "指定伺服器類型:<select name='selTypes'><option value=''>選取...</option></select><br>請輸入網址或路徑:<input type='text' size=50 name='txtPath'><br>...或選擇來源文件:<input type='file' size=50 name='txtBrowse'><br><hr>...或選擇指定的饋入來源:<select name='selFeeds'><option value=''>選取...</option></select>",
	openLabel: "開啟",
	openPrompt: "開啟檔案或",
	openError: "讀取來源文件時發生錯誤",
	statusOpenHost: "正與伺服器建立連線",
	statusGetWorkspaceList: "正在取得可用之文章清單",
	step2Title: "步驟二:選擇工作區",
	step2Html: "輸入工作區名稱:<input type='text' size=50 name='txtWorkspace'><br>...或選擇工作區:<select name='selWorkspace'><option value=''>選取...</option></select>",
	cancelLabel: "取消",
	cancelPrompt: "取消本次導入動作",
	statusOpenWorkspace: "正在開啟工作區",
	statusGetTiddlerList: "正在取得可用之文章清單",
	step3Title: "步驟三:選擇欲導入之文章",
	step3Html: "<input type='hidden' name='markList'></input><br><input type='checkbox' checked='true' name='chkSync'>保持這些文章與伺服器的連結,便於同步後續的變更。</input><br><input type='checkbox' name='chkSave'>儲存此伺服器的詳細資訊於標籤為 'systemServer' 的文章名為:</input> <input type='text' size=25 name='txtSaveTiddler'>", 
	importLabel: "導入",
	importPrompt: "導入所選文章",
	confirmOverwriteText: "確定要覆寫這些文章:\n\n%0",
	step4Title: "步驟四:正在導入%0 篇文章",
	step4Html: "<input type='hidden' name='markReport'></input>", // DO NOT TRANSLATE
	doneLabel: "完成",
	donePrompt: "關閉",
	statusDoingImport: "正在導入文章 ...",
	statusDoneImport: "所選文章已導入",
	systemServerNamePattern: "%2 位於 %1",
	systemServerNamePatternNoWorkspace: "%1",
	confirmOverwriteSaveTiddler: "此 tiddler '%0' 已經存在。點擊「確定」以伺服器上料覆寫之,或「取消」不變更後離開",
	serverSaveTemplate: "|''Type:''|%0|\n|''網址:''|%1|\n|''工作區:''|%2|\n\n此文為自動產生紀錄伺服器之相關資訊。",
	serverSaveModifier: "(系統)",

	listViewTemplate: {
		columns: [
			{name: 'Selected', field: 'Selected', rowName: 'title', type: 'Selector'},
			{name: 'Tiddler', field: 'tiddler', title: "文章", type: 'Tiddler'},
			{name: 'Size', field: 'size', tiddlerLink: 'size', title: "大小", type: 'Size'},
			{name: 'Tags', field: 'tags', title: "標籤", type: 'Tags'}
			],
		rowClasses: [
			]}
	});

merge(config.macros.sync,{
	listViewTemplate: {
		columns: [
			{name: 'Selected', field: 'selected', rowName: 'title', type: 'Selector'},
			{name: 'Tiddler', field: 'tiddler', title: "文章", type: 'Tiddler'},
			{name: 'Server Type', field: 'serverType', title: "伺服器類型", type: 'String'},
			{name: 'Server Host', field: 'serverHost', title: "伺服器主機", type: 'String'},
			{name: 'Server Workspace', field: 'serverWorkspace', title: "伺服器工作區", type: 'String'},
			{name: 'Status', field: 'status', title: "同步情形", type: 'String'},
			{name: 'Server URL', field: 'serverUrl', title: "伺服器網址", text: "View", type: 'Link'}
			],
		rowClasses: [
			],
		buttons: [
			{caption: "同步更新這些文章", name: 'sync'}
			]},
	wizardTitle: "將你的資料內容與外部伺服器與檔案同步",
	step1Title: "選擇欲同步的文章",
	step1Html: '<input type="hidden" name="markList"></input>', // DO NOT TRANSLATE
	syncLabel: "同步",
	syncPrompt: "同步更新這些文章",
	hasChanged: "已更動",
	hasNotChanged: "未更動",
	syncStatusList: {
		none: {text: "...", color: 'transparent'},
		changedServer: {text: "伺服器資料已更動", color: '#80ff80'},
		changedLocally: {text: "本機資料已更動", color: '#80ff80'},
		changedBoth: {text: "已同時更新本機與伺服器上的資料", color: '#ff8080'},
		notFound: {text: "伺服器無此資料", color: '#ffff80'},
		putToServer: {text: "已儲存更新資料至伺服器", color: '#ff80ff'},
		gotFromServer: {text: "已從伺服器擷取更新資料", color: '#80ffff'}
		}
	});

merge(config.macros.annotations,{
	});

merge(config.commands.closeTiddler,{
	text: "關閉",
	tooltip: "關閉本文"});

merge(config.commands.closeOthers,{
	text: "關閉其他",
	tooltip: "關閉其他文章"});

merge(config.commands.editTiddler,{
	text: "編輯",
	tooltip: "編輯本文",
	readOnlyText: "檢視",
	readOnlyTooltip: "檢視本文之原始內容"});

merge(config.commands.saveTiddler,{
	text: "完成",
	tooltip: "確定修改"});

merge(config.commands.cancelTiddler,{
	text: "取消",
	tooltip: "取消修改",
	warning: "確定取消對 '%0' 的修改嗎?",
	readOnlyText: "完成",
	readOnlyTooltip: "返回正常顯示模式"});

merge(config.commands.deleteTiddler,{
	text: "刪除",
	tooltip: "刪除文章",
	warning: "確定刪除 '%0'?"});

merge(config.commands.permalink,{
	text: "引用連結",
	tooltip: "本文引用連結"});

merge(config.commands.references,{
	text: "引用",
	tooltip: "引用本文的文章",
	popupNone: "本文未被引用"});

merge(config.commands.jump,{
	text: "捲頁",
	tooltip: "捲頁至其他已開啟的文章"});

merge(config.commands.syncing,{
	text: "同步",
	tooltip: "本文章與伺服器或其他外部檔案的同步資訊",
	currentlySyncing: "<div>同步類型:<span class='popupHighlight'>'%0'</span></"+"div><div>與伺服器:<span class='popupHighlight'>%1 同步</span></"+"div><div>工作區:<span class='popupHighlight'>%2</span></"+"div>", // Note escaping of closing <div> tag
	notCurrentlySyncing: "無進行中的同步動作",
	captionUnSync: "停止同步此文章",
	chooseServer: "與其他伺服器同步此文章:",
	currServerMarker: "\u25cf ",
	notCurrServerMarker: "  "});

merge(config.commands.fields,{
	text: "欄位",
	tooltip: "顯示此文章的擴充資訊",
	emptyText: "此文章沒有擴充欄位",
	listViewTemplate: {
		columns: [
			{name: 'Field', field: 'field', title: "擴充欄位", type: 'String'},
			{name: 'Value', field: 'value', title: "內容", type: 'String'}
			],
		rowClasses: [
			],
		buttons: [
			]}});

merge(config.shadowTiddlers,{
	DefaultTiddlers: "GettingStarted",
	GettingStarted: "使用此 TiddlyWiki 的空白範本之前,請先修改以下預設文章:\n* SiteTitle 及 SiteSubtitle:網站的標題和副標題,顯示於頁面上方<br />(在儲存變更後,將顯示於瀏覽器視窗的標題列)。\n* MainMenu:主選單(通常在頁面左側)。\n* DefaultTiddlers:內含一些文章的標題,可於載入TiddlyWiki 後的預設開啟。\n請輸入您的大名,作為所建立/ 編輯的文章署名:<<option txtUserName>>",
	MainMenu: "[[使用說明|GettingStarted]]\n\n\n^^~TiddlyWiki 版本:<<version>>\n© 2007 [[UnaMesa|http://www.unamesa.org/]]^^",
	OptionsPanel: "這些設定將暫存於瀏覽器\n請簽名<<option txtUserName>>\n (範例:WikiWord)\n\n <<option chkSaveBackups>> 儲存備份\n <<option chkAutoSave>> 自動儲存\n <<option chkRegExpSearch>> 正規式搜尋\n <<option chkCaseSensitiveSearch>> 區分大小寫搜尋\n <<option chkAnimate>> 使用動畫顯示\n----\n [[進階選項|AdvancedOptions]]",
	SiteTitle: "我的 TiddlyWiki",
	SiteSubtitle: "一個可重複使用的個人網頁式筆記本",
	SiteUrl: 'http://www.tiddlywiki.com/',
	SideBarOptions: '<<search>><<closeAll>><<permaview>><<newTiddler>><<newJournal " YYYY年0MM月0DD日" "日誌">><<saveChanges>><<slider chkSliderOptionsPanel OptionsPanel  "偏好設定 »" "變更 TiddlyWiki 選項">>',
	SideBarTabs: '<<tabs txtMainTab "最近更新" "依更新日期排序" TabTimeline "全部" "所有文章" TabAll "分類" "所有標籤" TabTags "更多" "其他" TabMore>>',
	StyleSheet: '[[StyleSheetLocale]]',
	TabMore: '<<tabs txtMoreTab "未完成" "內容空白的文章" TabMoreMissing "未引用" "未被引用的文章" TabMoreOrphans "預設文章" "已預設內容的隱藏文章" TabMoreShadowed>>'});

merge(config.annotations,{
	AdvancedOptions: "此預設文章可以存取一些進階選項。",
	ColorPalette: "此預設文章裡的設定值,將決定 ~TiddlyWiki 使用者介面的配色。",
	DefaultTiddlers: "當 ~TiddlyWiki 在瀏覽器中開啟時,此預設文章裡列出的文章,將被自動顯示。",
	EditTemplate: "此預設文章裡的 HTML template 將決定文章進入編輯模式時的顯示版面。",
	GettingStarted: "此預設文章提供基本的使用說明。",
	ImportTiddlers: "此預設文章提供存取導入中的文章。",
	MainMenu: "此預設文章的內容,為於螢幕左側主選單的內容",
	MarkupPreHead: "此文章的內容將加至 TiddlyWiki 文件的 <head> 段落的起始",
	MarkupPostHead: "此文章的內容將加至 TiddlyWiki 文件的 <head> 段落的最後",
	MarkupPreBody: "此文章的內容將加至 TiddlyWiki 文件的 <body> 段落的起始",
	MarkupPostBody: "此文章的內容將加至 TiddlyWiki 文件的 <body> 段落的最後,於 script 區塊之前",
	OptionsPanel: "此預設文章的內容,為於螢幕右側副選單中的選項面板裡的內容",
	PageTemplate: "此預設文章裡的 HTML template 決定的 ~TiddlyWiki 主要的版面配置",
	PluginManager: "此預設文章提供存取套件管理員",
	SideBarOptions: "此預設文章的內容,為於螢幕右側副選單中選項面板裡的內容",
	SideBarTabs: "此預設文章的內容,為於螢幕右側副選單中的頁籤面板裡的內容",
	SiteSubtitle: "此預設文章的內容為頁面的副標題",
	SiteTitle: "此預設文章的內容為頁面的主標題",
	SiteUrl: "此預設文章的內容須設定為文件發佈時的完整網址",
	StyleSheetColors: "此預設文章內含的 CSS 規則,為相關的頁面元素的配色。''勿修改此文'',請於 StyleSheet 中作增修。",
	StyleSheet: "此預設文章內容可包含 CSS 規則",
	StyleSheetLayout: "此預設文章內含的 CSS 規則,為相關的頁面元素的版面配置。''勿修改此文'',請於 StyleSheet 中作增修。",
	StyleSheetLocale: "此預設文章內含的 CSS 規則,可依翻譯語系做適當調整",
	StyleSheetPrint: "此預設文章內含的 CSS 規則,用於列印時的樣式",
	TabAll: "此預設文章的內容,為於螢幕右側副選單中的「全部」頁籤的內容",
	TabMore: "此預設文章的內容,為於螢幕右側副選單中的「更多」頁籤的內容",
	TabMoreMissing: "此預設文章的內容,為於螢幕右側副選單中的「未完成」頁籤的內容",
	TabMoreOrphans: "此預設文章的內容,為於螢幕右側副選單中的「未引用」頁籤的內容",
	TabMoreShadowed: "此預設文章的內容,為於螢幕右側副選單中的「預設文章」頁籤的內容",
	TabTags: "此預設文章的內容,為於螢幕右側副選單中的「分類」頁籤的內容",
	TabTimeline: "此預設文章的內容,為於螢幕右側副選單中的「最近更新」頁籤的內容",
	ViewTemplate: "此預設文章裡的 HTML template 決定文章顯示的樣子"
	});
//}}}
/***
|Name|ShowUpdatesPlugin|
|Created by|SaqImtiaz|
|Version|0.2 |
|Requires|~TW2.x|
!!!Description:
Allows you to list tiddlers that have changed since the users last visit. You can list only all changed tiddlers, or filter them to only show tiddlers that have or do not have a specific tag. By default a simple list of the titles of changed tiddlers is created. However, using an extremely versatile syntax you can provide a custom template for the generated text.

!!!Installation:
Copy the contents of this tiddler to your TW, tag with systemConfig, save and reload your TW.

!!!Syntax:
{{{<<showUpdates>>}}}
additional optional params:
{{{<showUpdates excludeTag:TagToExclude onlyTag:TagToList maxEntries:10 write:CustomWriteParameter >>}}}
excludeTag: ~TagToExclude
onlyTag: ~TagToList
maxEntries: max number of entries displayed when there are no updates. (default is 10, which can be changed in the config.macros.showUpdates.settings part of the code)
write: if a write parameter is not provided, an un-numbered list of the updates is generated. Alternatively, you can specify a custom 'template' for the text generated. The syntax for the write parameter is identical to that of the forEachTiddler macro. Additonal documentation on this syntax will be provided soon.
Some of the variables available in the write parameter are 'index', 'count' and 'lastVisit' where lastVisit is the date of the last visit in the format YYYYMMDDHHMM. Also areUpdates is a boolean that is true if there are new updates since the users last visit.

!!!To Do:
*refactor code to facilitate translations
*a streamlined version without the custom write parameter


!!!Code
***/
//{{{
window.lewcidLastVisit = '';
window.old_lewcid_whatsnew_restart = window.restart;
window.restart = function()
{
        if(config.options.txtLastVisit)
                 lewcidLastVisit= config.options.txtLastVisit;
        config.options.txtLastVisit = (new Date()).convertToYYYYMMDDHHMM();
        saveOptionCookie('txtLastVisit');
        window.old_lewcid_whatsnew_restart();
}

TiddlyWiki.prototype.lewcidGetTiddlers = function(field,excludeTag,includeTag,updatesOnly)
{
              var results = [];
              this.forEachTiddler(function(title,tiddler)
                      {
                      if(excludeTag == undefined || !tiddler.isTagged(excludeTag))
                                    if(includeTag == undefined ||  tiddler.isTagged(includeTag))
                                            if ( updatesOnly == false || tiddler.modified.convertToYYYYMMDDHHMM()>lewcidLastVisit)
                                                  results.push(tiddler);
                      });
              if(field)
                  results.sort(function (a,b) {if(a[field] == b[field]) return(0); else return (a[field] < b[field]) ? -1 : +1; });
              return results;
}

config.macros.showUpdates={};
config.macros.showUpdates.settings =
{
         maxEntries: 10  //max items to show, if there are no updates since last visit
}

config.macros.showUpdates.handler = function(place,macroName,params,wikifier,paramString,tiddler)
{
          var args = paramString.parseParams("list",null,true);
          var write = getParam(args, "write", undefined);
          var onlyTag = getParam(args, "onlyTag", undefined);
          var excludeTag = getParam(args, "excludeTag", undefined);
          var sortBy = "modified";
          var maxEntries = getParam(args,"maxEntries",this.settings.maxEntries);

          if (lewcidLastVisit) 
                {var tiddlers = store.lewcidGetTiddlers(sortBy,excludeTag,onlyTag,true);
                 var areUpdates = tiddlers.length>0? true:false;}

          //if (!lewcidLastVisit)
          //     {var countLine = "!!最近的更新:";
                  var tiddlers = store.lewcidGetTiddlers(sortBy,excludeTag,onlyTag,false);
                  var areUpdates = false;
          //     }
          //else if (tiddlers.length == 0)
          //     {var countLine = "!!@@color:red;上次拜訪後, 沒有任何更新 " + (Date.convertFromYYYYMMDDHHMM(lewcidLastVisit)).formatString(" (DD/MM/YY)") + "@@\n!!最近的更新:";
         //      var tiddlers = store.lewcidGetTiddlers(sortBy,excludeTag,onlyTag,false);}
         // else
         //      {var countLine ="!!@@ 自從上次拜訪後, 共有 "+ tiddlers.length +" 更新 " + (Date.convertFromYYYYMMDDHHMM(lewcidLastVisit)).formatString(" (DD/MM/YY)") + "@@";}

          tiddlers = tiddlers.reverse();
          var lastVisit = lewcidLastVisit? lewcidLastVisit:undefined;
          var count = areUpdates == true? tiddlers.length : maxEntries;
          var sp = createTiddlyElement(place,"span","showUpdates");
          if (write==undefined)
                 {
                  //wikify(countLine,sp);
                  var list = createTiddlyElement(sp,"ul");
                  for (var i = 0; i < count; i++)
                          {
                           var tiddler = tiddlers[i];
                           createTiddlyLink(createTiddlyElement(list,"li"), tiddler.title, true);
                          }
                 }
          else
                {
                 var list = '';
                 for (var index = 0; index < count; index++) {
                 var tiddler = tiddlers[index];
                 list += eval(write); }
                 wikify(list, sp);
                }
}
//}}}
/***
|''巨集名稱:''|toBalaAjax|
|''版本:''|2.1 (2008-06-28)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''| |
***/

//{{{
config.macros.toBalaAjax={
	
	editLabel: "編輯網頁",
	editTip: "編輯網頁",
        saveLabel: "儲存網頁",
	saveTip: "儲存網頁",
        openLabel: "檢視網頁",
	openTip: "檢視網頁",
        cancelLabel: "取消編輯",
	cancelTip: "取消編輯",
    
	GUIEditButtonOnclick: function(e,xtiddler,xbox,xfname,xx,yy) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }

            removeChildren(xbox);

            var boxtool = createTiddlyElement(xbox,"div",null,"toBalaFileToolBar",null,null);
            var boxtext = createTiddlyElement(xbox,"textarea",null,null,null,null);
            wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+xfname+"</nowiki>@@ ",boxtool);

            createTiddlyButton(boxtool,this.saveLabel,this.saveTip,
                            function(e) { config.macros.toBalaAjax.GUISaveButtonOnclick(e,xtiddler,xbox,xfname,boxtext,xx,yy); },
                            "toBalaFileSave",null,null);
	    createTiddlyButton(boxtool,this.cancelLabel,this.cancelTip,
                            function(e) { config.macros.toBalaAjax.GUICancelButtonOnclick(e,xtiddler,xbox,xfname,xx,yy); },
                            "toBalaFileCancel",null,null);

            // alert(xtitle+":"+xx+":"+yy);
            boxtext.setAttribute("rows",20);
            boxtext.setAttribute("cols",88);
            boxtext.value = xtiddler.text.substring(xx,yy);
        },

	GUISaveButtonOnclick: function(e,xtiddler1,xbox1,xfname1,boxtext1,xx1,yy1) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }
 
            removeChildren(xbox1);
            var xtext=boxtext1.value;
            if (config.browser.isIE) {              
               xtext=xtext.replace(/\r/g,"");   // 請看最後的註解
            }
            var toptext=xtiddler1.text.substring(0,xx1);
            var bottomtext=xtiddler1.text.substring(yy1);
            xtext = (xtext.charAt(xtext.length-1) == "\n" ? xtext : xtext+"\n");
            xtiddler1.text=toptext+xtext+bottomtext;

            story.refreshTiddler(xtiddler1.title,null,true);
            saveChanges(false);              // 參數 false, 代表不管 Dirty 與否, 均要執行存檔動作

            var baseDIR = getLocalPath(document.URL);
  
            if (config.browser.isWindows) {
                var baseDIR = baseDIR.replace(/\//g,"");
                var x = baseDIR.lastIndexOf("\\");
             } else {
                var x = baseDIR.lastIndexOf("/");
             }

            baseDIR = baseDIR.substr(0,x+1);

            var s = saveFile(baseDIR+ (config.browser.isWindows ? xfname1 : xfname1.replace(/\\/g,"\/")), 
                                          convertUnicodeToUTF8(boxtext1.value));
            if (!s) {
               alert("存檔失敗");
            }
        },

	GUICancelButtonOnclick: function(e,xtiddler1,xbox1,xfname1,xx1,yy1) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }

            removeChildren(xbox1);

            var boxtool = createTiddlyElement(xbox1,"div",null,"toBalaFileToolBar",null,null);
            wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+xfname1+"</nowiki>@@ ",boxtool);

	    createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaAjax.GUIEditButtonOnclick(e,xtiddler1,xbox1,xfname1,xx1,yy1);},
                            "toBalaFileEdit",null,null);

	    createTiddlyButton(boxtool,this.openLabel,this.openTip,
                            function(e) { config.macros.toBalaAjax.openHTML(e,params[0],xwidth,xheight);},
                            "toBalaFileEdit",null,null);

             var boxarea = createTiddlyElement(xbox1,"div",null,null,null,null);
	     wikify("{{{\n"+xtiddler1.text.substring(xx1,yy1-1)+"\n}}}",boxarea);
        },

        openHTML: function(ev,xf,xw,xh) {

               if (config.browser.isIE) {
                  window.event.cancelBubble=true;
               } else {  
                  ev.cancelBubble=true;   
               if (ev.stopPropagation)  
                  ev.stopPropagation();
               }

               // 將視窗置中
               var winl = (screen.width-xw)/2;
               var wint = (screen.height-xh)/2;
               if (winl < 0) winl = 0;
               if (wint < 0) wint = 0;
               var settings = 'scrollbars=yes, resizable=yes, height='  + xh +  ', width=' + xw  + ',top='  + wint  + ',left='  + winl;

               xf=xf.replace(/\\/mg,"/");

               // alert(xf+":"+settings);
               var xwin=window.open(xf,"HTMLWIN",settings);
               xwin.window.focus();
        },

	handler : function(place,macroName,params,wikifier,paramString,tiddler){

                if (!params[0]) {
                  alert("請給檔名");
                  return;
                } 

                var xwidth = params[1] || 550;
                var xheight = params[2] || 400;

		var xtext=store.getTiddlerText(tiddler.title);
                var x1=xtext.indexOf("/"+"/"+"/"+"%" + params[0]);

                // 自動產生 TiddlyWiki 備註
                if (x1 == -1) { 
                   xtext=xtext+"\n\n/"+"/"+"/"+"%" + params[0] + "\n" + "/"+"/"+"%"+"/";
                   tiddler.text=xtext; 
                   story.refreshTiddler(tiddler.title,null,true); // 這個 Tiddler 會重新顯示, 也就是 handler 會再被執行一次
                   //saveChanges(false);
                 }
                var x2=xtext.indexOf("/"+"/"+"%"+"/",x1);
                x1=x1+params[0].length+5;

		var box = createTiddlyElement(place,"div",tiddler.title+"-"+x1,"toBalaFile",null,null);
                var boxtool = createTiddlyElement(box,"div",null,"toBalaFileToolBar",null,null);
                wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+params[0]+"</nowiki>@@ ",boxtool);

                var boxtext = createTiddlyElement(box,"div",null,null,null,null);
		wikify("{{{\n"+xtext.substring(x1,x2-1)+"\n}}}",boxtext);

                if (readOnly) {
                   return;
                }
		createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaAjax.GUIEditButtonOnclick(e,tiddler,box,params[0],x1,x2);},
                            "toBalaFileEdit",null,null);

		createTiddlyButton(boxtool,this.openLabel,this.openTip,
                            function(e) { config.macros.toBalaAjax.openHTML(e,params[0],xwidth,xheight);},
                            "toBalaFileEdit",null,null);
	}		
};

/*
HTML 的 textarea 標籤, 對於換行在不同的瀏覽器有不同的處理方式

As you may know, the humble line break actually has three forms depending on which operating system is doing the breaking. On Unix machines, a single newline character ‘\n’ does the job. On Macs, a carriage return ‘\r’ is used. DOS and Windows use both: ‘\r\n’. It’s one of those relatively subtle issues that can bite you hard if you don’t know what to look out for.
*/

//}}}
{{item1{使用格式}}}
{{{
<<toBalaAjax  "ajax\html\testAjax.htm">>
}}}

{{item1{實作範例}}}
<<toBalaAjax "ajax\html\testAjax.htm">>

///%ajax\html\testAjax.htm
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf8">
</head>

<body>
<h2 align=center>顯示網頁載入時間的警告視窗</h2>
<hr>

<script>
today = new Date();			// 產生日期物件
hour = today.getHours();		// 取得時數
minute = today.getMinutes();		// 取得分數
second = today.getSeconds();		// 取得秒數
string = "網頁載入時間是"+hour+"點"+minute+"分"+second+"秒";	// 連接字串
</script>
<a href="javascript:alert(string)">網頁載入時間</a>

<hr>
</body>
</html>
//%/
<<toBalaAjax "ajax\AjaxCall.htm" "700" "450">>

///%ajax\AjaxCall.htm
<!-- 
程式名稱 : AjaxCall.html
程式描述 : Call XMLHTTP Object
適用瀏覽器 : Firefox 2.0,IE 5.5
參考文件 : 
-->
<html>
	
<head>
	
<meta http-equiv="Expires" content="0">
<meta http-equiv="Content-Type" content="text/html; charset=utf8">

<script>
var xmlhttp
function show(){
 
 if (window.XMLHttpRequest) {
    netscape.security.PrivilegeManager.enablePrivilege("UniversalBrowserRead");
    xmlhttp = new XMLHttpRequest();    
 }
 else if (window.ActiveXObject){ 
    try {
          xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
         }
    catch (e){
      try{
         xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
        }
      catch (e){}
    }
 }

 xmlhttp.open(document.getElementById("c").value,document.getElementById("u").value,false);
 xmlhttp.send("");
 if (parseInt(xmlhttp.status)>300){
     alert(xmlhttp.status);
 }
 else {
  document.getElementById("h").innerHTML=xmlhttp.getAllResponseHeaders();
  
  if (xmlhttp.getResponseHeader("Content-Type") == "text/xml"){
  	 xmlobj=xmlhttp.responseXML;
     document.getElementById("x").innerHTML=xmlobj.getElementsByTagName('app')[0].firstChild.nodeValue;
  }
  else{
  	 document.getElementById("x").innerHTML="";
     var testFrame = document.getElementById("myFrame");
     var doc = testFrame.contentDocument;
     if (doc == undefined || doc == null)
        doc = testFrame.contentWindow.document;
     doc.open();
     doc.write(xmlhttp.responseText);
	 doc.close(); 
  }  
 }
}
</script>
</head>

<style type="text/css">
body {
 background-color:white;
}
</style>

<body>
<h2>Ajax 測試程式 (使用本機的瀏覽器以 "開啟檔案" 方式執行)</h2>
<hr>
Method: <input id="c" value="GET" style="width: 100px;" type="text"><span> (要大寫) </span><br> 
URL: <input style="width: 250px;" id="u" value="http://" type="text"><br>

<button onclick="show();">傳送命令</button>
<hr>

<b>Response Header</b>
<pre id="h"></pre>

<b>Response XML</b>
<pre id="x"></pre>

<b>Response HTML</b><br>
<iframe id="myFrame" height="30%" width="100%"></iframe>

</body>
</html>

<!--
HTTP Methods
-------------
HTTP defines eight methods (sometimes referred to as "verbs") indicating the desired 
action to be performed on the identified resource.

HEAD
    Asks for the response identical to the one that would correspond to a GET request, 
    but without the response body. This is useful for retrieving meta-information 
	written in response headers, without having to transport the entire content.
GET
    Requests a representation of the specified resource. By far the most common method
	used on the Web today. Should not be used for operations that cause side-effects 
	(using it for actions in web applications is a common mis-use). See 'safe methods' 
	below.
POST
    Submits data to be processed (e.g. from an HTML form) to the identified resource. 
	The data is included in the body of the request. This may result in the creation 
	of a new resource or the updates of existing resources or both.
PUT
    Uploads a representation of the specified resource.
DELETE
    Deletes the specified resource.
TRACE
    Echoes back the received request, so that a client can see what intermediate 
	servers are adding or changing in the request.
OPTIONS
    Returns the HTTP methods that the server supports. This can be used to check the 
	functionality of a web server.
CONNECT
    For use with a proxy that can change to being an SSL tunnel.


WebDAV added the following methods to HTTP:

    * PROPFIND — Used to retrieve properties, persisted as XML, from a resource. 
	             It is also overloaded to allow one to retrieve the collection 
				 structure (a.k.a. directory hierarchy) of a remote system.
    * PROPPATCH — Used to change and delete multiple properties on a resource 
	              in a single atomic act.
    * MKCOL — Used to create collections (a.k.a. directory).
    * COPY — Used to copy a resource from one URI to another.
    * MOVE — Used to move a resource from one URI to another.
    * LOCK — Used to put a lock on a resource. WebDAV supports both shared and 
	         exclusive locks.
    * UNLOCK — To remove a lock from a resource.

-->
//%/
/***
|''巨集名稱:''|toBalaApp|
|''版本:''|2.1 (2008-10-2)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''| |
***/
//{{{
config.macros.toBalaApp={
       mode:"open",

       handler : function(place,macroName,params,wikifier,paramString,tiddler){
                if (!params[0]) {
                  alert("請給檔名");
                  return;
                } 
		createTiddlyButton(place,"應用模式","應用模式", function(e) { config.macros.toBalaApp.onClick(params[0]); } );

                /* 下式的寫法, 在執行 handler 的同時也會執行 onClick, 這樣的執行方式不對, 所以請使用上式
                     createTiddlyButton(place,"應用模式","應用模式",this.onClick(params[0]));
                */ 
	},
       onClick : function(xapp) {
            // alert(this.mode+":"+xapp);
            if (this.mode=="open"){
               this.mode="close";
               document.getElementById("displayArea").style.display="none";
               document.getElementById("mainMenu").style.display="none";
               document.getElementById("ApplicationArea").style.display="block";
               document.getElementById("ApplicationArea").style.width="99.6%";
               document.getElementById("ApplicationArea").style.height=(window.screen.availHeight-200)+"px";
               document.getElementById("ApplicationArea").src=xapp;               
               return false;
            } else {
               this.mode="open";
               document.getElementById("displayArea").style.display="block";
               document.getElementById("mainMenu").style.display="block";
               document.getElementById("ApplicationArea").style.display="none";
               document.getElementById("ApplicationArea").src="";   
               return  false;
            }
        }	
};

//}}}
/***
|''巨集名稱:''|toBalaBackup|
|''版本:''|1.0 (2008-09-12)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0|
|''使用文件''| &lt;&lt;toBalaBackup '備份檔名'  '樹幹名'  '文章,文章,文章'&gt;&gt;|
***/

//{{{
// 自定的巨集變數, 開頭前三個字如為 txt, 結合 option 巨集會以文字欄處理, 前三個字如為 chk, 結合 option 巨集會以 checkbox 欄處理
config.options.txtBalaBackupFileName = config.options.txtBalaBackupFileName ? config.options.txtBalaBackupFileName : "toBalaBackup.html";
config.options.txtBalaTreeBody = config.options.txtBalaTreeBody ? config.options.txtBalaTreeBody : "";
config.options.txtBalaBackupOthers = config.options.txtBalaBackupOthers ? config.options.txtBalaBackupOthers : "首頁,MainMenu,SiteTitle,SiteSubtitle,00-控制台,StyleSheet";

config.macros.toBalaBackup = {};
config.macros.toBalaBackup.handler = function(place,macroName,params,wikifier,paramString,tiddler){

  if (readOnly) {
     return;
  }

  if (!params[0] && config.options.txtBalaBackupFileName == "") {
     alert("請給檔名");
     return;
  }
  var tbName = config.options.txtBalaBackupFileName != "" ? config.options.txtBalaBackupFileName : params[0];   // 備份檔名
  var tbTag = config.options.txtBalaTreeBody != "" ? config.options.txtBalaTreeBody : params[1] ;            // 備份主標籤
  var tbTD = config.options.txtBalaBackupOthers != "" ? config.options.txtBalaBackupOthers : params[2];      // 其它備份文章
  var label = params[3] || "備份資訊樹文章";
  var tooltip = params[4] || "備份資訊樹文章 : " + tbName;

  createTiddlyButton(place, label, tooltip,
       function(e) { config.macros.toBalaBackup.save(e, tbName, tbTag, tbTD); },
       null, null, null);
}

config.macros.toBalaBackup.save = function(ev,xfname,xtag, xtd) {

  if (config.browser.isIE) {
     window.event.cancelBubble=true;
  } else {  
     ev.cancelBubble = true;   
     if (ev.stopPropagation)  
        ev.stopPropagation();
  }

  var baseDIR = getLocalPath(document.URL);
  //alert(baseDIR);
  
   if (config.browser.isWindows) {
      var baseDIR = baseDIR.replace(/\//g,"");
      var x = baseDIR.lastIndexOf("\\");
   } else {
      var x = baseDIR.lastIndexOf("/");
   }

   baseDIR = baseDIR.substr(0,x+1);
   //alert(baseDIR);

   toBala.AllTiddlers = "";
   // 呼叫 toBalaLIB 的 getMainTree() 方法, 取出資訊樹的樹幹及所有文章抬頭
   if (xtag!="") {
      var tbTempArr = toBala.getMainTree(xtag);

      for(var i=0; i<tbTempArr.length; ++i)
           toBala.TagDigg(tbTempArr[i]);
   }

   // 取出資訊樹所有文章的 DIV 內容
   var tbText='<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /><body>\n<div id="storeArea">';
   if (toBala.AllTiddlers!="") {
      var tbArr = toBala.AllTiddlers.split(",");
      for(i=0;i<tbArr.length;++i){
         if (tbArr[i])
            tbText = tbText+ "\n" + toBala.getTiddlerDIV(tbArr[i]);
      }
   }
   // 取出指定文章的 DIV 內容
   if (xtd!=""){
      tbArr = xtd.split(",");
      for(i=0;i<tbArr.length;++i)
          tbText = tbText+ "\n" + toBala.getTiddlerDIV(tbArr[i]);
   }
   tbText = tbText + "</div></body></html>";

   var s = saveFile(baseDIR+ (config.browser.isWindows?xfname:xfname.replace(/\\/g,"\/")), convertUnicodeToUTF8(tbText));
   if (s) {
      saveChanges(true);
      alert("備份完成");
   } else {
      alert("備份失敗");
   }
}
//}}}
config.options.chkAutoSave=false;
config.options.chkSaveBackups=false;
config.options.txtUserName="toBala";
config.options.txtMaxEditRows=50;
config.options.chkHttpReadOnly=true;

config.options.chkHideTabsBarWhenSingleTab=true;

config.options.chkDisableWikiLinks=true;
config.options.chkAllowLinksFromShadowTiddlers=true;
config.options.chkDisableNonExistingWikiLinks=true;
/***
|''巨集名稱:''|toBalaCoreBackup|
|''版本:''|1.0 (2008-09-12)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0|
|''使用文件''| &lt;&lt;toBalaCoreBackup '備份檔名' '文章,文章,文章'&gt;&gt;|
***/

//{{{
// 自定的巨集變數, 開頭前三個字如為 txt, 結合 option 巨集會以文字欄處理, 前三個字如為 chk, 結合 option 巨集會以 checkbox 欄處理
config.options.txtBalaCoreBackupFileName = config.options.txtBalaCoreBackupFileName ? config.options.txtBalaCoreBackupFileName : "toBalaMacro.html";
config.options.txtBalaCoreBackupOthers = config.options.txtBalaCoreBackupOthers ? config.options.txtBalaCoreBackupOthers : "";

config.macros.toBalaCoreBackup = {};
config.macros.toBalaCoreBackup.handler = function(place,macroName,params,wikifier,paramString,tiddler){

  if (readOnly) {
     return;
  }

  if (!params[0] && config.options.txtBalaCoreBackupFileName == "") {
     alert("請給檔名");
     return;
  }
  var tbName = params[0] || config.options.txtBalaCoreBackupFileName;          // toBala 巨集備份檔名
  var tbTD = params[1] || config.options.txtBalaCoreBackupOthers;            // 其它備份文章
  var label = params[2] || "備份 toBala 巨集";
  var tooltip = params[3] || "備份 toBala 巨集 : " + tbName;

  createTiddlyButton(place, label, tooltip,
       function(e) { config.macros.toBalaCoreBackup.save(e, tbName, tbTD); },
       null, null, null);
}

config.macros.toBalaCoreBackup.save = function(ev,xfname, xtd) {

  if (config.browser.isIE) {
     window.event.cancelBubble=true;
  } else {  
     ev.cancelBubble = true;   
     if (ev.stopPropagation)  
        ev.stopPropagation();
  }

  var baseDIR = getLocalPath(document.URL);
  //alert(baseDIR);
  
   if (config.browser.isWindows) {
      var baseDIR = baseDIR.replace(/\//g,"");
      var x = baseDIR.lastIndexOf("\\");
   } else {
      var x = baseDIR.lastIndexOf("/");
   }

   baseDIR = baseDIR.substr(0,x+1);
   // alert(baseDIR);

   // 取出所有 toBala 巨集的 DIV 內容
   var tbT2 = store.getTaggedTiddlers("toBala");
   var tbText='<html><head><meta http-equiv="Content-Type" content="text/html;charset=UTF-8" /></head>';
   tbText = tbText + '<body>\n<div id="storeArea">';
   for (var i=0; i<tbT2.length; ++i) {
        tbText = tbText+ "\n" + toBala.getTiddlerDIV(tbT2[i].title);
   }

   // 取出指定文章的 DIV 內容
   if (xtd!=""){
      tbArr = xtd.split(",");
      for(i=0;i<tbArr.length;++i)
          tbText = tbText+ "\n" + toBala.getTiddlerDIV(tbArr[i]);
   }
   tbText = tbText + "</div></body></html>";

   var s = saveFile(baseDIR+ (config.browser.isWindows?xfname:xfname.replace(/\\/g,"\/")), convertUnicodeToUTF8(tbText));
   if (s) {
      saveChanges(true);
      alert("備份完成");
   } else {
      alert("備份失敗");
   }
}
//}}}
/***
|''巨集名稱:''|toBalaFile|
|''版本:''|1.0 (2008-05-09)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''||
***/

//{{{
config.macros.toBalaFile={
	
	editLabel: "編輯",
	editTip: "編輯",
        saveLabel: "儲存",
	saveTip: "儲存",
        cancelLabel: "取消",
	cancelTip: "取消",
    
	GUIEditButtonOnclick: function(e,xtiddler,xbox,xfname,xx,yy) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }

            removeChildren(xbox);

            var boxtool = createTiddlyElement(xbox,"div",null,"toBalaFileToolBar",null,null);
            var boxtext = createTiddlyElement(xbox,"textarea",null,null,null,null);
            wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+xfname+"</nowiki>@@ ",boxtool);

            createTiddlyButton(boxtool,this.saveLabel,this.saveTip,
                            function(e) { config.macros.toBalaFile.GUISaveButtonOnclick(e,xtiddler,xbox,xfname,boxtext,xx,yy); },
                            "toBalaFileSave",null,null);
	    createTiddlyButton(boxtool,this.cancelLabel,this.cancelTip,
                            function(e) { config.macros.toBalaFile.GUICancelButtonOnclick(e,xtiddler,xbox,xfname,xx,yy); },
                            "toBalaFileCancel",null,null);

            // alert(xtitle+":"+xx+":"+yy);
            boxtext.setAttribute("rows",20);
            boxtext.setAttribute("cols",88);
            boxtext.value = xtiddler.text.substring(xx,yy);
        },

	GUISaveButtonOnclick: function(e,xtiddler1,xbox1,xfname1,boxtext1,xx1,yy1) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }
 
            removeChildren(xbox1);
            var xtext=boxtext1.value;
            if (config.browser.isIE) {              
               xtext=xtext.replace(/\r/g,"");   // 請看最後的註解
            }
            var toptext=xtiddler1.text.substring(0,xx1);
            var bottomtext=xtiddler1.text.substring(yy1);
            xtext = (xtext.charAt(xtext.length-1) == "\n" ? xtext : xtext+"\n");
            xtiddler1.text=toptext+xtext+bottomtext;

            story.refreshTiddler(xtiddler1.title,null,true);
            saveChanges(false);              // 參數 false, 代表不管 Dirty 與否, 均要執行存檔動作

            var baseDIR = getLocalPath(document.URL);
  
            if (config.browser.isWindows) {
                var baseDIR = baseDIR.replace(/\//g,"");
                var x = baseDIR.lastIndexOf("\\");
             } else {
                var x = baseDIR.lastIndexOf("/");
             }

            baseDIR = baseDIR.substr(0,x+1);

            var s = saveFile(baseDIR+ (config.browser.isWindows ? xfname1 : xfname1.replace(/\\/g,"\/")), 
                                          convertUnicodeToUTF8(boxtext1.value));
            if (!s) {
               alert("存檔失敗");
            }
        },

	GUICancelButtonOnclick: function(e,xtiddler1,xbox1,xfname1,xx1,yy1) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }

            removeChildren(xbox1);

            var boxtool = createTiddlyElement(xbox1,"div",null,"toBalaFileToolBar",null,null);
            wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+xfname1+"</nowiki>@@ ",boxtool);

	    createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaFile.GUIEditButtonOnclick(e,xtiddler1,xbox1,xfname1,xx1,yy1);},
                            "toBalaFileEdit",null,null);

             var boxarea = createTiddlyElement(xbox1,"div",null,null,null,null);
	     wikify("{{{\n"+xtiddler1.text.substring(xx1,yy1-1)+"\n}}}",boxarea);
        },

	handler : function(place,macroName,params,wikifier,paramString,tiddler){

                if (!params[0]) {
                  alert("請給檔名");
                  return;
                } 

		var xtext=store.getTiddlerText(tiddler.title);
                var x1=xtext.indexOf("/"+"/"+"/"+"%" + params[0]);

                // 自動產生 TiddlyWiki 備註
                if (x1 == -1) { 
                   xtext=xtext+"\n\n/"+"/"+"/"+"%" + params[0] + "\n" + "/"+"/"+"%"+"/";
                   tiddler.text=xtext; 
                   story.refreshTiddler(tiddler.title,null,true); // 這個 Tiddler 會重新顯示, 也就是 handler 會再被執行一次
                   //saveChanges(false);
                 }
                var x2=xtext.indexOf("/"+"/"+"%"+"/",x1);
                x1=x1+params[0].length+5;

		var box = createTiddlyElement(place,"div",tiddler.title+"-"+x1,"toBalaFile",null,null);
                var boxtool = createTiddlyElement(box,"div",null,"toBalaFileToolBar",null,null);
                wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+params[0]+"</nowiki>@@ ",boxtool);

                var boxtext = createTiddlyElement(box,"div",null,null,null,null);
		wikify("{{{\n"+xtext.substring(x1,x2-1)+"\n}}}",boxtext);

                if (readOnly) {
                   return;
                }
		createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaFile.GUIEditButtonOnclick(e,tiddler,box,params[0],x1,x2);},
                            "toBalaFileEdit",null,null);
	}		
};

/*
HTML 的 textarea 標籤, 對於換行在不同的瀏覽器有不同的處理方式

As you may know, the humble line break actually has three forms depending on which operating system is doing the breaking. On Unix machines, a single newline character ‘\n’ does the job. On Macs, a carriage return ‘\r’ is used. DOS and Windows use both: ‘\r\n’. It’s one of those relatively subtle issues that can bite you hard if you don’t know what to look out for.
*/

//}}}
在文章中使用 toBalaFile 巨集, 可將巨集中所編輯的文字, 存入指定的檔案, 請看以下使用格式
{{{
<<toBalaFile "ajax\html\hello.htm">>

此巨集以 UTF-8 編碼, 儲存檔文字到檔案
}}}

__{{op1{實作範例}}}__
<<toBalaFile "ajax\html\hello.htm">>

///%ajax\html\hello.htm
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf8">
</head>

<body>
<h2 align=center>利用 JavaScript 來印出 "Hello World!"</h2>
<hr>
<script language="javascript">
	str = "Hello World!";
	document.write(str);
</script>
<hr>
</body>
</html>
//%/
{{item1{說明}}}
{{{

<<toBalaFile "檔名">>

}}}
{{item1{範例}}}
<<toBalaFile "xml\abc.xml">>


///%xml\abc.xml
<?xml version='1.0'?>
<root>
  <marble color="red"/>
  <marble color='red'/>
</root> 
//%/
/***
|''巨集名稱:''|toBalaFlashPlayer|
|''版本:''|1.0 (2008-03-06)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''| |
***/
//{{{
config.macros.toBalaFlashPlayer = {};

config.macros.toBalaFlashPlayer.handler = function(place,macroName,params,wikifier,paramString,tiddler){

  var xname = params[0] || tiddler.title;
  var label = params[1] || "撥放 " + xname;
  var xwidth = params[2] || 600;
  var xheight = params[3] || 450;

  createTiddlyButton(place, label, label,
       function(e) { config.macros.toBalaFlashPlayer.show(e, xname, xwidth, xheight); },
       null, null, null);
}

config.macros.toBalaFlashPlayer.show = function(ev,fname,xw,xh) {

  if (config.browser.isIE) {
     window.event.cancelBubble=true;
  } else {  
     ev.cancelBubble = true;   
     if (ev.stopPropagation)  
        ev.stopPropagation();
  }

  if (config.browser.isIE)
     var URLtext = document.URL.replace(/\\/g,"\/");
  else 
     var URLtext = document.URL;
  //alert(URLtext);

  var x = URLtext.lastIndexOf("/");
  var baseDIR = URLtext.substr(0,x);
  var jsDIR = '<script type="text/javascript" src="' + baseDIR + '/jslib/swfobject/swfobject.js"></script>'
  //alert(jsDIR);

  var generator=window.open('','name','height=' + xh +',width=' + xw);
  generator.document.open();
  generator.document.write('<html><head><title>toBala Flash Player</title>');
  generator.document.write(jsDIR);
  generator.document.write('</head><body>');
  generator.document.write('<div id="flashTag" style="width:'+(xw-5)+'px;height:'+(xh-5)+'px;overflow:auto"></div>');
  generator.document.write('<script type="text/javascript">');
  generator.document.write('var xo = new SWFObject("' + baseDIR + '/' + fname + '","mymovie","'+(xw-5)+'","'+(xh-5)+'","8", "#336699");');
  //generator.document.write('xo.addParam("wmode", "transparent");');
  generator.document.write('xo.write("flashTag");');
  generator.document.write('</script>');
  generator.document.write('</body></html>');
  generator.document.close();

}
//}}}
使用 toBalaFlashPlayer 巨集, 來撥放指定的 Flash 檔, 命令格式如下 :
{{{
<<toBalaFlashPlayer "movie/infotree.swf" "" "820" "610">>
}}}

{{item1{實作範例 : winzip 的安裝}}}

<<toBalaFlashPlayer "movie/winzip.swf" "" "800" "580">>
/***
|''巨集名稱:''|toBalaHTML|
|''版本:''|1.0 (2008-03-18)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''|&lt;&lt;toBalaHTML  title  filename  label  tooltip  width  height&gt;&gt; |
***/

//{{{
config.macros.toBalaHTML = {};

config.macros.toBalaHTML.handler = function(place,macroName,params,wikifier,paramString,tiddler){

  var title = params[0] || tiddler.title;
  var xfname = params[1] || "";          // 外部檔名
  var label = params[2] || "測試網頁";
  var tooltip = params[3] || "開啟另一個視窗, 檢視網頁";
  var xwidth = params[4] || 550;
  var xheight = params[5] || 400;

  createTiddlyButton(place, label, tooltip,
       function(e) { config.macros.toBalaHTML.show(e,title,xfname,xwidth,xheight); },
       null, null, null);
}

config.macros.toBalaHTML.show = function(ev,xtitle,xf,xw,xh) {

  if (config.browser.isIE) {
     window.event.cancelBubble=true;
  } else {  
     ev.cancelBubble=true;   
     if (ev.stopPropagation)  
        ev.stopPropagation();
  }

  // 將視窗置中
  var winl = (screen.width-xw)/2;
  var wint = (screen.height-xh)/2;
  if (winl < 0) winl = 0;
  if (wint < 0) wint = 0;
  var settings = 'height='  + xh +  ', width=' + xw  + ',top='  + wint  + ',left='  + winl;

  if (xf != "") {

     xf=xf.replace(/\\/mg,"/");

     // alert(xf+":"+settings);
     var xwin=window.open(xf,"HTMLWIN",settings);
     xwin.window.focus();

  } else {
    // alert(store.getTiddlerText(xtitle));
    xtext=store.getTiddlerText(xtitle);

    x1=xtext.indexOf("/*{{{*/");
    x2=xtext.indexOf("/*}}}*/");
    // alert(xtext.substring(x1+8,x2));
    xtext = xtext.substring(x1+8,x2);

    var xwin=window.open('','',settings);
    xwin.document.open();
    xwin.document.write(xtext);
    xwin.document.close();
  }
}
/*
window.open() 參數
----------------------------------------------
* width:定義新視窗的寬度。
* height:定義新視窗的高度。
* resizable:能否讓用戶調整視窗大小,可能的設定值為:yes或no(或者1與0)。
* menubar:是否要顯示主功能表,可能的設定值為:yes或no。
* toolbar:是否要顯示「標準按鈕」工具列,可能的設定值為:yes或no。
* location:是否要顯示網址欄位,可能的設定值為:yes或no。
* scrollbars:能否顯示捲軸,可能的設定值為:yes或no。
* status:是否要呈現狀態列,可能的設定值為:yes或no。
* directories:是否要呈現額外的按鈕(例如:「連結」列,以及「標準按鈕」以外的其他按鈕),可能的設定值為:yes或no。
* copyhistory:是否要複製原有瀏覽器視窗的瀏覽歷程(history),可能的設定值為:yes或no。
* fullscreen:是否要以全螢幕方式開啟新視窗(適用於IE瀏覽器),可能的設定值為:yes或no。
*/
//}}}
{{item1{你可以直接載入已存在的網頁檔, 巨集如下 :}}}
{{{
<<toBalaHTML "" "ajax\html\iframe.htm" "顯示外部檔案: ajax\html\iframe.htm">>
}}}

<<toBalaHTML "" "ajax\html\iframe.htm">>

{{item1{你可以直接載入存在 tiddler 的網頁文字, 巨集如下 :}}}
{{{
<<toBalaHTML "" "" "網頁顯示 : 直接載入以下網頁文字">>
}}}

<<toBalaHTML "" "" "網頁顯示 : 直接載入以下網頁文字">>
/*{{{*/
<html>
<head>
<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=utf-8">
</head>

<style>
body {color:red;background-color: yellow}
</style>

<body>
<h2 align=center>印出 "Hello World!"</h2>
</body>
</html>
/*}}}*/
<<toBalaHTML "" "ajax/html/e4x.htm" "網頁測試 : ajax/html/e4x.htm">><<toBalaFile "ajax\html\e4x.htm">>

///%ajax\html\e4x.htm
<html>
<script type="text/javascript;e4x=1">
      myquestion = <question>          
      <display>Is it animal, vegetable, or mineral?</display>              
      <answerOption>Animal</answerOption>
      <answerOption>Vegetable</answerOption>
      <answerOption>Mineral</answerOption>
      </question>;
      alert("The question is '" + myquestion.display + "'");             
</script>
</html>
//%/
這範例程式可在 IE, Firefox, Opera  等瀏覽器中執行

<<toBalaHTML "" "ajax\html\contentEditableFF.htm">><<toBalaFile "ajax\html\contentEditableFF.htm">>

///%ajax\html\contentEditableFF.htm
<body>
<iFrame id="jia" src="about:blank"></iFrame>  
<script>  
  // window.onload   =   function(){  
  var jia = document.getElementById("jia");  
  jia.contentWindow.document.designMode="on";  
  jia.contentWindow.document.contentEditable=true;  
  jia.contentWindow.document.open();  
  jia.contentWindow.document.write("<html><head></head><body></body></html>");  
  jia.contentWindow.document.close();  
  // }  
</script>
</body>
//%/
必須關閉瀏覽器 [阻檔 POPUP 視窗] 功能, 以下程式才能執行

<<toBalaHTML "" "ajax\html\popup.htm">><<toBalaFile "ajax\html\popup.htm">>


///%ajax\html\popup.htm
<html>
<head>
<script type="text/javascript">
function show_popup()
{
   var p=window.createPopup();
   var pbody=p.document.body;
   pbody.style.backgroundColor="lime";
   pbody.style.border="solid black 1px";
   pbody.innerHTML="This is a pop-up! Click outside to close.";
   p.show(150,150,200,50,document.body);
}
</script>
</head>

<body>
<button onclick="show_popup()">Create pop-up!</button>
</body>

</html>
//%/
/***
|''巨集名稱:''|toBalaJava|
|''版本:''|1.0 (2008-04-01)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''|toBalaRun|
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''|&lt;&lt;toBalaJava  "程式檔名"  "前置編譯參數"  "前置執行參數"  "後置執行參數" "按鈕提示資訊" "按鈕提示資訊"&gt;&gt; |
***/

//{{{
config.macros.toBalaJava = {};

config.macros.toBalaJava.handler = function(place,macroName,params,wikifier,paramString,tiddler){

  if (readOnly) {
     return;
  }

  if (!params[0].match(".java")) {
     alert("請給檔名或副檔名錯誤");
     return;
  }

  // 程式檔名
  var xfname = params[0]; 

  // 前置編譯參數 
  var cprearg = params[1] || "";

  // 前置執行參數 
  var eprearg = params[2] || "";

  // 後置執行參數 
  var postarg = params[3] || "";

  var cargs = (cprearg=="" ? "":cprearg+" ") + xfname;
  //alert(cargs);

  var p = xfname.indexOf(".java");
  yfname=xfname.substring(0,p);
  p=yfname.lastIndexOf("\\");
  yfname=yfname.substring(p+1,yfname.length);

  var rargs = (eprearg==""?"":eprearg+" ") + yfname + (postarg==""?"":" "+postarg);
  //alert(rargs);

  // 按鈕提示資訊
  var clabel = params[4] || "翻譯程式 :" + xfname;
  var rlabel = params[5] || "執行程式 :" + yfname;

  // 翻譯程式
  createTiddlyButton(place, clabel, clabel,
       function(e) { config.macros.toBalaRun.cmd(e,"tbjavac.exe",cargs,"yes"); },
       null, null, null);

  // 執行程式
  createTiddlyButton(place, rlabel, rlabel,
       function(e) { config.macros.toBalaRun.cmd(e,"tbjava.exe",rargs,"yes"); },
       null, null, null);
}
//}}}
/***
|''巨集名稱:''|toBalaJava2|
|''版本:''|1.1 (2008-07-02)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''|toBalaRun|
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''|&lt;&lt;toBalaJava2 "程式檔名" "前置編譯參數" "前置執行參數" "後置執行參數"&gt;&gt;|
***/

//{{{
config.macros.toBalaJava2={
	
	editLabel: "程式編輯",
	editTip: "程式編輯",
	compileLabel: "編譯程式",
	compileTip: "編譯程式",
	runLabel: "執行程式",
	runTip: "執行程式",
        saveLabel: "儲存程式",
	saveTip: "儲存程式",
        cancelLabel: "取消編輯",
	cancelTip: "取消編輯",

	GUIEditButtonOnclick: function(e,xtiddler,xbox,xfname1,xx,yy) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }

            removeChildren(xbox);

            var boxtool = createTiddlyElement(xbox,"div",null,"toBalaFileToolBar",null,null);
            var boxtext = createTiddlyElement(xbox,"textarea",null,null,null,null);
            wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+xfname1+"</nowiki>@@ ",boxtool);

            createTiddlyButton(boxtool,this.saveLabel,this.saveTip,
                            function(e) { config.macros.toBalaJava2.GUISaveButtonOnclick(e,xtiddler,xbox,xfname1,boxtext,xx,yy); },
                            "toBalaFileSave",null,null);
	    createTiddlyButton(boxtool,this.cancelLabel,this.cancelTip,
                            function(e) { config.macros.toBalaJava2.GUICancelButtonOnclick(e,xtiddler,xbox,xx,yy); },
                            "toBalaFileCancel",null,null);

            // alert(xtitle+":"+xx+":"+yy);
            boxtext.setAttribute("rows",20);
            boxtext.setAttribute("cols",88);
            boxtext.value = xtiddler.text.substring(xx,yy);
        },

	GUISaveButtonOnclick: function(e,xtiddler1,xbox1,xfname2,boxtext1,xx1,yy1) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }
 
            removeChildren(xbox1);
            var xtext=boxtext1.value;
            if (config.browser.isIE) {              
               xtext=xtext.replace(/\r/g,"");   // 請看最後的註解
            }
            var toptext=xtiddler1.text.substring(0,xx1);
            var bottomtext=xtiddler1.text.substring(yy1);
            xtext = (xtext.charAt(xtext.length-1) == "\n" ? xtext : xtext+"\n");
            xtiddler1.text=toptext+xtext+bottomtext;

            story.refreshTiddler(xtiddler1.title,null,true);
            saveChanges(false);              // 參數 false, 代表不管 Dirty 與否, 均要執行存檔動作

            var baseDIR = getLocalPath(document.URL);
  
            if (config.browser.isWindows) {
                var baseDIR = baseDIR.replace(/\//g,"");
                var x = baseDIR.lastIndexOf("\\");
             } else {
                var x = baseDIR.lastIndexOf("/");
             }

            baseDIR = baseDIR.substr(0,x+1);

            var s = saveFile(baseDIR+ (config.browser.isWindows ? xfname2 : xfname2.replace(/\\/g,"\/")), 
                                          convertUnicodeToUTF8(boxtext1.value));
            if (!s) {
               alert("存檔失敗");
            }
        },

	GUICancelButtonOnclick: function(e,xtiddler1,xbox1,xx1,yy1) {

            if (config.browser.isIE) {
               window.event.cancelBubble=true;
            } else {  
               e.cancelBubble = true;   
               if (e.stopPropagation)  
                  e.stopPropagation();
            }

            removeChildren(xbox1);
            story.refreshTiddler(xtiddler1.title,null,true);
        },

	handler : function(place,macroName,params,wikifier,paramString,tiddler){

              if (!params[0].match(".java")) {
                 alert("請給檔名或副檔名錯誤");
                 return;
              }

              // 程式檔名
              var xfname = params[0]; 

              // javac 編譯參數 
              var cprearg = params[1] || "";

              // java 執行參數 
              var eprearg = params[2] || "";

              // 你的程式執行參數 
              var postarg = params[3] || "";

              var cargs = (cprearg=="" ? "":cprearg+" ") + xfname;
              //alert(cargs);

              var p = xfname.indexOf(".java");
              yfname=xfname.substring(0,p);
              p=yfname.lastIndexOf("\\");
              yfname=yfname.substring(p+1,yfname.length);

              var rargs = (eprearg==""?"":eprearg+" ") + yfname + (postarg==""?"":" "+postarg);
              //alert(rargs);

	      var xtext=store.getTiddlerText(tiddler.title);

              // 取得程式段的起始位址
              var x1=xtext.indexOf("/"+"/"+"/"+"%" + xfname);

                // 自動產生程式段 (TiddlyWiki 備註)
                if (x1 == -1) { 
                   xtext=xtext+"\n\n/"+"/"+"/"+"%" + xfname + "\n" + "/"+"/"+"%"+"/";
                   tiddler.text=xtext; 
                   story.refreshTiddler(tiddler.title,null,true); // 這個 Tiddler 會重新顯示, 也就是 handler 會再被執行一次
                   //saveChanges(false);
                 }
                var x2=xtext.indexOf("/"+"/"+"%"+"/",x1);
                x1=x1+params[0].length+5;

		var box = createTiddlyElement(place,"div",tiddler.title+"-"+x1,"toBalaFile",null,null);
                var boxtool = createTiddlyElement(box,"div",null,"toBalaFileToolBar",null,null);
                wikify("@@color:#841;border:2px dotted #841;padding:2px;檔案 : <nowiki>"+xfname+"</nowiki>@@ ",boxtool);

                var boxtext = createTiddlyElement(box,"div",null,null,null,null);
		wikify("{{{\n"+xtext.substring(x1,x2-1)+"\n}}}",boxtext);

                if (readOnly) {
                   return;
                }

                // 編輯程式
		createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaJava2.GUIEditButtonOnclick(e,tiddler,box,xfname,x1,x2);},
                            "toBalaFileEdit",null,null);

                // 翻譯程式
		createTiddlyButton(boxtool,this.compileLabel,this.compileTip,
                            function(e) { config.macros.toBalaRun.cmd(e,"tbjavac.exe",cargs,"yes"); },
                            "toBalaFileEdit",null,null);

                // 執行程式
                if (xtext.substring(x1,x2-1).indexOf("main") != -1) {
		       createTiddlyButton(boxtool,this.runLabel,this.runTip,
                            function(e) { config.macros.toBalaRun.cmd(e,"tbjava.exe",rargs,"yes");},
                            "toBalaFileEdit",null,null);
                }
	}		
};

/*
HTML 的 textarea 標籤, 對於換行在不同的瀏覽器有不同的處理方式

As you may know, the humble line break actually has three forms depending on which operating system is doing the breaking. On Unix machines, a single newline character ‘\n’ does the job. On Macs, a carriage return ‘\r’ is used. DOS and Windows use both: ‘\r\n’. It’s one of those relatively subtle issues that can bite you hard if you don’t know what to look out for.
*/

//}}}
{{item1{程式範例}}} 
{{{
使用 toBalaJava2 巨集, 撰寫, 編譯及執行 Java 程式, 命令格式如下 :

<<toBalaJava2 "java\hello.java" "" "">>
}}}
<<toBalaJava2 "java\hello.java" "" "">>

{{item1{程式範例 : 輸入 [編譯] 及 [執行] 參數}}}
{{{
使用 toBalaJava2 巨集, 編譯及執行 Java 程式, 命令格式如下 :
<<toBalaJava2 "java\assertion.java" "-source 1.4" "-ea">>

"-source 1.4" 是編譯參數
"-ea" 是執行參數
}}}
<<toBalaJava2 "java\assertion.java" "-source 1.4" "-ea">>

{{item1{程式範例 : 輸入程式參數}}}
{{{
使用 toBalaJava2 巨集, 編譯及執行 Java 程式, 命令格式如下 :

<<toBalaJava2 "java\args.java" "" "" "aa bb cc">>
}}}
<<toBalaJava2 "java\args.java" "" "" "aa bb cc">>


///%java\hello.java
public class hello {
  public static void main(String[] args){
     System.out.println("大家好好");
  }
}
//%/

///%java\assertion.java
class assertion {
  public static void main(String[] args){
    int i=-11;
    if (i%3==0) 
      { System.out.println("0"); }
    else if (i%3==1) 
      { System.out.println("1"); }
    else {
      assert((i%3)==2):i;
    }
  }
}
//%/

///%java\args.java
public class args {
  public static void main(String[] args) {
    for(int i=0; i < args.length ; ++i) 
      System.out.println(args[i]);
  }
} 
//%/
//{{{
if (!window.toBala) window.toBala = {};

toBala.AllTiddlers = "";
toBala.CoreTiddlers = "";

// 讀取資訊樹的架構
toBala.getMainTree = function(xstr) {
    var tbATree = new Array();
    var tbMMenu = new Array();
    var tbTemp = new Array();

    var xtext=store.getTiddlerText("MainMenu");
    tbMMenu = xtext.split("\n");

    for (var i=0,j=0; i<tbMMenu.length; ++i) {
       tbTemp = tbMMenu[i].split(" ");
       if (tbTemp[1] && tbTemp[1].indexOf(xstr) != -1) {
          tbATree[j] = tbTemp[1];
          ++j;
       }
    }
    return tbATree;
};

// 讀取資訊樹幹的所有文章
toBala.TagDigg = function(tbTag) {

   toBala.AllTiddlers = (toBala.AllTiddlers == "" ? tbTag : toBala.AllTiddlers + "," + tbTag);    

   var tbT2 = store.getTaggedTiddlers(tbTag);
   if (tbT2) {
      for (var i=0; i<tbT2.length; ++i) 
         toBala.TagDigg(tbT2[i].title);
   }
   return;
};

// 讀出 Tiddler 所有內容, 也就是 DIV 標籤內容
toBala.getTiddlerDIV = function(tbT) {
    var tiddler = store.getTiddler(tbT)
    if (!tiddler)
       return "";
   
    var usePre = config.options.chkUsePreForStorage;
    var created = tiddler.created.convertToYYYYMMDDHHMM();
    var modified = tiddler.modified.convertToYYYYMMDDHHMM();
    var vdate = version.date.convertToYYYYMMDDHHMM();
    var attributes = tiddler.modifier ? ' modifier="' + tiddler.modifier.htmlEncode() + '"' : "";
    attributes += (usePre && modified == created) ? "" : ' modified="' + modified +'"';
    attributes += (usePre && created == vdate) ? "" :' created="' + created + '"';
    var tags = tiddler.getTags();
    if (!usePre || tags)
       attributes += ' tags="' + tags.htmlEncode() + '"';

    return ('<div %0="%1"%2>%3</'+'div>').format([
	usePre ? "title" : "tiddler",
	tiddler.title.htmlEncode(),
	attributes,
	usePre ? "\n<pre>" + tiddler.text.htmlEncode() + "</pre>\n" : tiddler.text.escapeLineBreaks().htmlEncode()
	]);
}
//}}}
/***
|''巨集名稱:''|toBalaManager|
|''版本:''|1.0 (2008-09-05)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''~TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''||
***/
//{{{
config.macros.toBalaManager={
	preText: "",
	save: function(e,ytiddler,yform) {

            //for (var i=0,str="";i<yform.elements.length;++i){
            //  str=str+yform.elements[i].type+":"+yform.elements[i].tagName+":"+yform.elements[i].value;
            //}
            //alert(str);  
      
            // 設定主標題
            var xt = store.getTiddler("SiteTitle");  
            xt.text=  yform.elements[0].value;

            // 設定次標題
            var xt = store.getTiddler("SiteSubtitle");  
            xt.text=  yform.elements[1].value;

            // 設定 MainMenu
            var xt = store.getTiddler("MainMenu");  
            xt.text=  yform.elements[2].value;

            // 設定 ToolBar
            var xt = store.getTiddler("toBalaToolBar");  
            xt.text=  yform.elements[3].value;

            // 備份 SiteTitle, SiteSubtitle, ToolBar, MainMenu  
            ytiddler.text=preText; 
            saveChanges(false);   // 參數 false, 代表不管 Dirty 與否, 均要執行存檔動作
        },

	handler : function(place,macroName,params,wikifier,paramString,tiddler){

                if (!readOnly) {
		    createTiddlyButton(place,"儲存設定","儲存設定",
                          function(e) { config.macros.toBalaManager.save(e,tiddler,xform); },
                          "toBalaManagerSave",null,null);
                }

		var xform = createTiddlyElement(place,"form",tiddler.title+"-form","toBalaManager",null,null);
                // 讀取主標題
                var xlabel1 = createTiddlyElement(xform,"label",null,"",null,null);
		wikify("''主標題 (~SiteTitle) :  ''",xlabel1);
                var xtitle1 = createTiddlyElement(xform,"input",null,"xManagerMT",null,null);
                var xt = store.getTiddler("SiteTitle");   
		xtitle1.value=xt.text;
		wikify("\n\n",xform);

                // 讀取次標題
                var xlabel2 = createTiddlyElement(xform,"label",null,"",null,null);
                wikify("''次標題 (~SiteSubtitle) :  ''",xlabel2);
                var xtitle2 = createTiddlyElement(xform,"input",null,"xManagerST",null,null);
                var xt = store.getTiddler("SiteSubtitle");   
		xtitle2.value=xt.text;
		wikify("\n\n",xform);

                // 讀取 MainMenu
                var xlabel4 = createTiddlyElement(xform,"label",null,"",null,null);
                wikify("''資訊樹 (TagsTree)''",xlabel4);
		wikify("\n",xform);
                var xmm = createTiddlyElement(xform,"textarea",null,"xManagerMM",null,null);
                var xt = store.getTiddler("MainMenu");   
                xmm.value=xt.text;
		wikify("\n\n",xform);

                // 讀取 ToolBar
                var xlabel3 = createTiddlyElement(xform,"label",null,"",null,null);
                wikify("''工具列 (~ToolBar)''",xlabel3);
		wikify("\n",xform);
                var xtb = createTiddlyElement(xform,"textarea",null,"xManagerTB",null,null);
                var xt = store.getTiddler("toBalaToolBar");   
                xtb.value=xt.text;
		wikify("\n\n",xform);

                // 備份 SiteTitle, SiteSubtitle, ToolBar, MainMenu
	        var xtext=store.getTiddlerText(tiddler.title);
                var x1 = xtext.indexOf("/"+"/"+"/"+"%");
                xtext = ( x1 == -1 ? xtext : xtext.substring(0,x1) );

                preText=xtext+"\n\n/"+"/"+"/"+"%" ;
                preText=preText+"\n\n"+xtitle1.value;
                preText=preText+"\n\n"+xtitle2.value;
                preText=preText+"\n\n"+xmm.value;
                preText=preText+"\n\n"+xtb.value;
                preText=preText+"\n" + "/"+"/"+"%"+"/";

	}		
};

setStylesheet(".toBalaManager {background:#eee; font-size:12px;border:1px solid #ccc; padding:2px; margin:5px;}\n"+
".xManagerMT {width:550px;height:25px;}\n" +
".xManagerST {width:550px;height:25px;}\n" +
".xManagerTB {width:680px;height:100px;}\n" +
".xManagerMM {width:680px;height:240px;}\n" +
".toBalaManagerSave {border:1px solid #ccc;font-size:14px;padding:2px;margin-left:4px;margin-bottom:2px;}\n" ,
"toBalaManagerStyles");
//}}}
/***
|''巨集名稱:''|toBalaNotes|
|''版本:''|1.1 (2010-03-29)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''||
***/

//{{{
config.macros.toBalaNotes={
	
	editLabel: "編輯",
	editTip: "編輯",
        saveLabel: "儲存",
	saveTip: "儲存",
        cancelLabel: "取消",
	cancelTip: "取消",
        heading: "@@font-size:12px;color:#841;註解@@",
    
	GUIEditButtonOnclick: function(e,xtiddler,xbox,xx,yy) {
            removeChildren(xbox);

            var boxtool = createTiddlyElement(xbox,"div",null,"toBalaNotesToolBar",null,null);
            var boxtext = createTiddlyElement(xbox,"textarea",null,null,null,null);
	    wikify(this.heading+" : ",boxtool);

            // alert(xtitle+":"+xx+":"+yy);
            boxtext.setAttribute("rows",15);
            boxtext.setAttribute("cols",88);

            xstr=xtiddler.text.substring(xx,yy).replace(/&lt;/g, "<");
            xstr=xstr.replace(/&gt;/g, ">");
            xstr=xstr.replace(/&#123;/g, "{");
            xstr=xstr.replace(/&#125;/g, "}"); 
            boxtext.value = xstr;

            createTiddlyButton(boxtool,this.saveLabel,this.saveTip,
                            function(e) { config.macros.toBalaNotes.GUISaveButtonOnclick(e,xtiddler,xbox,boxtext,xx,yy); },
                            "toBalaNotesSave",null,null);
	    createTiddlyButton(boxtool,this.cancelLabel,this.cancelTip,
                            function(e) { config.macros.toBalaNotes.GUICancelButtonOnclick(e,xtiddler,xbox,xx,yy); },
                            "toBalaNotesCancel",null,null);
        },

	GUISaveButtonOnclick: function(e,xtiddler1,xbox1,boxtext1,xx1,yy1) {
            removeChildren(xbox1);
            toptext=xtiddler1.text.substring(0,xx1);
            bottomtext=xtiddler1.text.substring(yy1);

            xstr=boxtext1.value.replace(/\</g, "&lt;");
            xstr=xstr.replace(/>/g, "&gt;");
            xstr=xstr.replace(/{/g, "&#123;");
            xstr=xstr.replace(/}/g, "&#125;");
            xstr=xstr.replace(/\/\/%\//g, "");
            xstr=xstr.replace(/\/\/\/%/g, "");
            xtiddler1.text=toptext+xstr+bottomtext;

            yy1=xtiddler1.text.indexOf("/"+"/"+"%"+"/",xx1);

            var boxtool = createTiddlyElement(xbox1,"div",null,"toBalaNotesToolBar",null,null);
	    wikify(this.heading+" : ",boxtool);

	    createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaNotes.GUIEditButtonOnclick(e,xtiddler1,xbox1,xx1,yy1);},
                            "toBalaNotesEdit",null,null);

             var boxarea = createTiddlyElement(xbox1,"div",null,null,null,null); 
             boxarea.innerHTML="<pre id='toBalaNotesText'>"+xstr+"</pre>";
	     // wikify("<nowiki>"+xtiddler1.text.substring(xx1,yy1)+"</nowiki>",boxarea);
             saveChanges(false);   // 參數 false, 代表不管 Dirty 與否, 均要執行存檔動作
             clearMessage();
        },

	GUICancelButtonOnclick: function(e,xtiddler1,xbox1,xx1,yy1) {
            removeChildren(xbox1);

            var boxtool = createTiddlyElement(xbox1,"div",null,"toBalaNotesToolBar",null,null);
	    wikify(this.heading+" : ",boxtool);

	    createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaNotes.GUIEditButtonOnclick(e,xtiddler1,xbox1,xx1,yy1);},
                            "toBalaNotesEdit",null,null);

             var boxarea = createTiddlyElement(xbox1,"div",null,null,null,null);
             boxarea.innerHTML="<pre id='toBalaNotesText'>"+xtiddler1.text.substring(xx1,yy1)+"</pre>";
	     //wikify("<nowiki>"+xtiddler1.text.substring(xx1,yy1)+"</nowiki>",boxarea);
        },

	handler : function(place,macroName,params,wikifier,paramString,tiddler){

		var xtext=store.getTiddlerText(tiddler.title);
                var x1=xtext.indexOf("/"+"/"+"/"+"%" + params[0]);

                // 自動產生 TiddlyWiki 備註
                if (x1 == -1) { 
                   xtext=xtext+"\n\n/"+"/"+"/"+"%" + params[0] + "\n" + "/"+"/"+"%"+"/";
                   tiddler.text=xtext; 
                   story.refreshTiddler(tiddler.title,null,true);
                   saveChanges(false);     // 參數 false, 代表不管 Dirty 與否, 均要執行存檔動作
                   clearMessage();
                   return;
                 }
                var x2=xtext.indexOf("/"+"/"+"%"+"/",x1);
                x1=x1+params[0].length+5;

		var box = createTiddlyElement(place,"div",tiddler.title+"-"+x1,"toBalaNotes",null,null);
                var boxtool = createTiddlyElement(box,"div",null,"toBalaNotesToolBar",null,null);
		wikify(this.heading+" : ",boxtool);

                var boxtext = createTiddlyElement(box,"div",null,null,null,null);
                boxtext.innerHTML="<pre id='toBalaNotesText'>"+xtext.substring(x1,x2)+"</pre>";
		// wikify("<nowiki>"+xtext.substring(x1,x2)+"</nowiki>",boxtext);

                if (readOnly) {
                   return;
                }

		createTiddlyButton(boxtool,this.editLabel,this.editTip,
                            function(e) { config.macros.toBalaNotes.GUIEditButtonOnclick(e,tiddler,box,x1,x2);},
                            "toBalaNotesEdit",null,null);
	}		
};

setStylesheet(".toBalaNotes {background:#eee; border:1px solid #ccc; padding:2px; margin:5px;}\n"+
".toBalaNotesEdit {border:1px solid #ccc;padding:2px;margin-top:2px;margin-bottom:2px;}\n" +
".toBalaNotesCancel {border:1px solid #ccc;padding:2px;margin-top:2px;margin-right:2px;margin-bottom:2px;}\n" +
".toBalaNotesToolBar {border-bottom: 2px dotted #556b2f;padding:1px 0px 5px 0px;margin:1px;}\n" +
".toBalaNotesSave {border:1px solid #ccc;padding:2px;margin-top:2px;margin-right:2px;margin-bottom:2px;}\n"+
"#toBalaNotesText {background-color:#eee;border:none;margin:1px;padding:0px}\n",
"toBalaNotesStyles");
//}}}
在文章中使用 toBalaNotes 巨集, 可在文章中加入備註, 請看以下使用說明

{{item1{使用格式}}}
{{{
<<toBalaNotes "test">>

"test" 代表備註識別字串

[註] 一篇文章中可以存在多個備註
}}}

<<toBalaNotes "test">>

///%test
//%/
/***
|''巨集名稱:''|toBalaRun|
|''版本:''|1.0 (2008-04-01)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''| |
***/

//{{{
config.macros.toBalaRun = {};
config.macros.toBalaRun.handler = function(place,macroName,params,wikifier,paramString,tiddler){

  if (readOnly) {
     return;
  }

  if (!params[0]) {
     alert("請給檔名");
     return;
  }
  var fname = params[0];                //  執行檔名
  var varg = params[1] || "";             //  執行參數
  var label = params[2] || "執行 : "+fname + " " + varg;
  var tooltip = params[3] || "執行檔名 : "+fname + " " + varg;
  var result = params[4] || "yes";

  window.status="";
  createTiddlyButton(place, label, tooltip,
       function(e) { config.macros.toBalaRun.cmd(e,fname,varg,result); },
       null, null, null);
}

config.macros.toBalaRun.cmd = function(ev,xfname,xarg,xresult) {

  if (!xfname.match(".bat")) {
      //var xwin = toBala.showMsg("<h1>執行中, 請稍後</h1>",250,50);
      window.status = xfname + " " + xarg + " 執行中, 請稍後";
  }

  if (config.browser.isIE) {
     window.event.cancelBubble=true;
  } else {  
     ev.cancelBubble = true;   
     if (ev.stopPropagation)  
        ev.stopPropagation();
  }

  var baseDIR = getLocalPath(document.URL);
  //alert(baseDIR);

   if (config.browser.isWindows) {
      var baseDIR = baseDIR.replace(/\//g,"");
      var x = baseDIR.lastIndexOf("\\");
      xfname = "\\" + xfname.replace(/\//g,"\\");
      xarg = xarg.replace(/\//g,"\\");
   } else {
      var x = baseDIR.lastIndexOf("/");
      xfname = "/" + xfname.replace(/\\/g,"/");
      xarg = xarg.replace(/\\/g,"/");
   }

   baseDIR = baseDIR.substr(0,x);
   //alert(baseDIR);

   if (config.browser.isIE) {
	var theShell = new ActiveXObject("WScript.Shell");
	if (theShell) {
            var runstr = baseDIR + xfname + " " + xarg;
            // alert(runstr);
	    try {
	        theShell.run(runstr,1, (xresult == "yes" ? true:false));
	    } catch (e) {
                try {          //  執行系統命令
                    var runstr = xfname.substring(1)+ " " + xarg;
                    theShell.run(runstr,1, (xresult == "yes" ? true:false));
                } catch(e) {
                   if (!xfname.match(".bat")) 
                      window.status="";
		   displayMessage("執行失敗 :" + runstr);
		   return;
                }
	    }
	} 
   } else if (config.browser.isGecko) { 
	netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
        var file = Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);

        try {
           var runstr = baseDIR +xfname; 
           // alert(runstr);
           file.initWithPath(runstr);
        }catch (e) {
           if (!xfname.match(".bat")) 
              window.status="";
           displayMessage("執行字串格式錯誤 : " + runstr);
           return;
        }

	try {
	   var process = Components.classes['@mozilla.org/process/util;1'].createInstance(Components.interfaces.nsIProcess);
           var Aargs = xarg.split(" ");
           // alert(Aargs);
           process.init(file);
           process.run((xresult == "yes" ? true:false), Aargs, Aargs.length);
	} catch (e) {
            try {    //  執行系統命令
                runstr=xfname.substring(1);
                file.initWithPath(runstr);
                process.init(file);
                process.run((xresult == "yes" ? true:false), Aargs, Aargs.length);
            } catch (e) {
                if (!xfname.match(".bat")) 
                    window.status="";
	        displayMessage("執行失敗 : " + runstr);
                return;
            }
	}
   }
   // 顯示執行結果
   if ( !xfname.match(".bat") && !xfname.match(".sh") && xresult == "yes") {
      window.status="";
      xf = baseDIR+xfname+".htm"
      // alert(xf);
      var xh = 400;
      var xw = 780;
      var winl = (screen.width-xw)/2;
      var wint = (screen.height-xh)/2;
      if (winl < 0) winl = 0;
      if (wint < 0) wint = 0;
      var settings = 'height='  + xh +  ', width=' + xw  + ',top='  + wint  + ',left='  + winl + ',scrollbars=yes';
      var ywin=window.open("file:///"+xf,"HTMLWIN",settings);
   }
}
//}}}
在文章中使用 toBalaRun 巨集, 可執行系統中的 ''命令'', ''批次檔'', 請看以下使用說明

{{item1{使用格式}}}

__在 Windows 系統中, 啟動 tbsys.bat  批次檔__
{{{
<<toBalaRun "tbsys.bat"  ""  "System Info (batch)">>
}}}
<<toBalaRun "tbsys.bat" "" "System Info (batch)">>


__在 Windows 系統中, 因執行 exe 檔, 執行後會自動開啟一個 [執行結果視窗]__
{{{
<<toBalaRun  "tbsys.exe"  ""  "System Info (exe)">>
}}}
<<toBalaRun "tbsys.exe" "" "System Info (exe)">>

__在 Mac OS X 系統中, 啟動 ~TextEdit 應用程式, 因最後一個參數是 "no", 所以不會開啟一個 [執行結果視窗] __
{{{
<<toBalaRun "/usr/bin/open"  "-a /Applications/TextEdit.app"  ""  ""  "no">>
}}}
<<toBalaRun "/usr/bin/open" "-a /Applications/TextEdit.app" "" "" "no">>


{{item1{tbsys.bat 批次檔內容}}}
{{{
@echo off

REM 取得這個 Batch File 的目錄
set toBalaPath=%~p0

REM 取得這個 Batch File 的磁碟代號
set toBalaDrv=%~d0

REM 轉換磁碟及目錄
call %toBalaDrv%
cd %toBalaPath%

REM 設定環境變數
REM -----------------
set JAVA_HOME=%cd%\jdk1.6.0_05
set CLASSPATH=.;%cd%\jaxp;%cd%\java;%cd%\scjp
set CLASSPATH=%cd%\apache\xalan-j_2_7_1\xalan.jar;%CLASSPATH%
set CLASSPATH=%cd%\apache\xerces-2_9_1\xercesImpl.jar;%CLASSPATH%
set PATH=.;%JAVA_HOME%\bin;%JAVA_HOME%\jre\bin;%cd%\cmdtools;%PATH%


REM 執行 java 命令
REM ------------------
if "%~x0" == ".bat" goto n1
echo ^<head^> >%0.htm
echo ^<meta http-equiv="Content-Type" content="text/html; charset=big5"^> >>%0.htm
echo ^</head^> >>%0.htm
echo ^<body^> >>%0.htm
echo 執行檔案 : %1 >>%0.htm
echo ^<hr^> >>%0.htm 
echo ^<pre style='font-size:12px'^> >>%0.htm
goto n2
:n1
echo 執行中, 請稍待 (檔案 : %1) 
echo. >%0.htm
:n2

gettype >> %0.htm 2>&1
echo.
ipconfig /all >> %0.htm 2>&1

REM 處理執行訊息
REM -------------------
if "%~x0" == ".bat" goto s1
echo ^</pre^> >>%0.htm
echo ^</body^> >>%0.htm
rem convertZ\convertz /i:big5 /o:utf8 %0.msg %0.htm
exit
:s1
type %0.htm
echo.
echo 執行完成
echo.
pause
}}}

{{item1{Quick Batch File Compiler - 將 Batch 檔轉換成 exe 檔}}}
Quick Batch File Compiler convert your batch files into actual program (.EXE format) in one click. This program may be run on Windows 2000/2003/XP/Vista without any limitations. An .EXE file is much harder to casually reverse-engineer, so this could be a way to conceal a particular batch file's operations from an end user. Content of your batch file will be encrypted and protected from changes.

Quick Batch File Compiler also lets you set various resources in the .EXE file, such as its description, the company name, version information and even the application icon. In additional, you may include any files to compiled exe file and use it during execution. 

網址 : http://www.abyssmedia.com/quickbfc/index.shtml
<<toBalaFile "xml\dtd01.xml">><<toBalaRun "java\jaxp\JAXPDTD.bat" "xml\dtd01.xml" "檢核">>

----

<<toBalaFile "xml\dtd02.xml">><<toBalaRun "java\jaxp\JAXPDTD.bat" "xml\dtd02.xml" "檢核">>


///%xml\dtd01.xml
<?xml version="1.0" encoding="big5"?>
<!DOCTYPE PersonData [
  <!ELEMENT PersonData (name,spouse)>
  <!ELEMENT name (#PCDATA)>
  <!ELEMENT spouse (#PCDATA)>
]>
<PersonData>
    <spouse>Teley</spouse>
    <name>Ryan</name>
</PersonData>
//%/

///%xml\dtd02.xml
<?xml version="1.0"?>
<!DOCTYPE user [
  <!ELEMENT user (name+,e-mail*,title?)>
  <!ELEMENT name (#PCDATA)>
  <!ELEMENT e-mail (#PCDATA)>
  <!ELEMENT title (#PCDATA)>
]>
<user>
  <name>Austin Sours</name>
  <e-mail>xchen@cmt.com.tw</e-mail>
  <e-mail>aaa@x,y,z</e-mail>
</user>
//%/
<<toBalaFile "xml\well01.xml">><<toBalaRun "java\jaxp\JAXPWell.bat" "xml\well01.xml" "檢核">>

----

<<toBalaFile "xml\well02.xml">><<toBalaRun "java\jaxp\JAXPWell.bat" "xml\well02.xml" "檢核">>


///%xml\well01.xml
<root>
  <marble color="red"/>
  <marble color='red'/>
</root>
//%/

///%xml\well02.xml
<first_tag>
  <second_tag>
     <third_tag>Contents of third tag
  </second_tag>
</First_tag>
//%/
<<toBalaFile "xml\stype.xsd">>


<<toBalaFile "xml\stype.xml">><<toBalaRun "java\jaxp\JAXPSchema.bat" "xml\stype.xml xml\stype.xsd" "檢核">>


///%xml\stype.xsd
<?xml version="1.0"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" 
                  targetNamespace="http://xsdtesting">
    <xs:element name="author" type="xs:date"/>
</xs:schema>
//%/

///%xml\stype.xml
<?xml version="1.0"?>
<x:author xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
          xmlns:x="http://xsdtesting"
          xsi:schemaLocation="http://xsdtesting stype.xsd">
123.5
</x:author>
//%/
<<toBalaFile "xml\deftemp.xml">>
DOM Tree
----------------
{{{
       .
       |
       |--- <?xml-stylesheet  type="text/xsl"  .... ?>   
       |--- <root>
                |
                |--- <text>
                |
                |
                |--- <text>
                |
                |
                |--- <!-- abcd --> 

}}}


<<toBalaFile "xml\deftemp.xsl">><<toBalaRun "java\jaxp\JAXPXSLT.bat" "xml\deftemp.xml xml\deftemp.xsl" "轉換">>


///%xml\deftemp.xml
<?xml version="1.0"?>
<?xml-stylesheet type="text/xsl" href="deftemp.xsl"?>
<root>
  <text>
    Roses are <color>red</color>, violets are <color>blue</color>.
  </text>
  <text>
    My <color>green</color> and <color id="xxx">yellow</color> 
    sweater is just the right hue.
    <?name type="bebo"?>
  </text>
  <!-- abcd -->
</root>
//%/

///%xml\deftemp.xsl
<?xml version="1.0"?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> 

<!-- <xsl:template match="*|/">
</xsl:template>  -->

<!-- <xsl:template match="processing-instruction()">
  PI : <xsl:value-of select="."/>
</xsl:template> -->

<!-- <xsl:template match="root"/> -->

</xsl:stylesheet>
//%/
{{item1{ZoomIt v1.8}}}
By Mark Russinovich
Published: March 10, 2008
網址 : http://technet.microsoft.com/zh-tw/sysinternals/bb897434(en-us).aspx

__''Introduction''__
~ZoomIt is screen zoom and annotation tool for technical presentations that include application demonstrations. ~ZoomIt runs unobtrusively in the tray and activates with customizable hotkeys to zoom in on an area of the screen, move around while zoomed, and draw on the zoomed image. I wrote ~ZoomIt to fit my specific needs and use it in all my presentations.

~ZoomIt works on all versions of Windows and you can use pen input for ~ZoomIt drawing on tablet ~PCs.

__''Using ~ZoomIt''__
The first time you run ~ZoomIt it presents a configuration dialog that describes ~ZoomIt's behavior, let's you specify alternate hotkeys for zooming and for entering drawing mode without zooming, and customize the drawing pen color and size. I use the draw-without-zoom option to annotate the screen at its native resolution, for example. ~ZoomIt also includes a break timer feature that remains active even when you tab away from the timer window and allows you to return to the timer window by clicking on the ~ZoomIt tray icon.

點選 <<toBalaRun "tbzoomit.bat" "" "ZoomIt v1.8" "" "no">> 啟動 Zoomit

{{item1{tbzoomit.bat 程式碼}}}
{{{
@echo off

REM 取得這個 Batch File 的目錄
set toBalaPath=%~p0

REM 取得這個 Batch File 的磁碟代號
set toBalaDrv=%~d0

REM 轉換磁碟及目錄
call %toBalaDrv%
cd %toBalaPath%

REM 設定環境變數
REM -----------------
set PATH=.;%cd%\tools;%cd%\tools\cmdtools;%PATH%
start /B zoomit.exe
exit

}}}
網址 : http://freemind.sourceforge.net/wiki/index.php/Main_Page

~FreeMind is a premier free mind-mapping (http://en.wikipedia.org/wiki/Mind_map) software written in Java. The recent development has hopefully turned it into high productivity tool. We are proud that the operation and navigation of ~FreeMind is faster than that of MindManager because of one-click "fold / unfold" and "follow link" operations.

So you want to write a completely new metaphysics? Why don't you use ~FreeMind? You have a tool at hand that remarkably resembles the tray slips of Robert Pirsig, described in his sequel to Zen and the Art of Motorcycle Maintenance called Lila. Do you want to refactor your essays in a similar way you would refactor software? Or do you want to keep personal knowledge base, which is easy to manage? Why don't you try ~FreeMind? Do you want to prioritize, know where you are, where you've been and where you are heading, as Stephen Covey would advise you? Have you tried FreeMind to keep track of all the things that are needed for that? 

Mac OS X 系統請點選以下按鈕

<<toBalaRun "java/freemind/freemind.sh"  ""  "啟動心智圖編輯器">>


Windows 系統請點選以下按鈕

<<toBalaRun "tbfreemind.bat"  ""  "啟動心智圖編輯器">>
/***
|''巨集名稱:''|toBalaSWF2|
|''版本:''|1.1 (2008-09-30)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''| |
***/
//{{{
config.macros.toBalaSWF2 = {};

config.macros.toBalaSWF2.handler = function(place,macroName,params,wikifier,paramString,tiddler){

  var xname = params[0] || tiddler.title;
  var xwidth = params[1] || 600;
  var xheight = params[2] || 450;
  var label = params[3] || "撥放 : " + xname;

  createTiddlyButton(place, label, label,
       function(e) { config.macros.toBalaSWF2.show(e, xname, xwidth, xheight); },
       null, null, null);
}

config.macros.toBalaSWF2.show = function(ev,fname,xw,xh) {

  if (config.browser.isIE) {
     window.event.cancelBubble=true;
  } else {  
     ev.cancelBubble = true;   
     if (ev.stopPropagation)  
        ev.stopPropagation();
  }

  if (config.browser.isIE)
     var URLtext = document.URL.replace(/\\/g,"\/");
  else 
     var URLtext = document.URL;
  //alert(URLtext);

  var x = URLtext.lastIndexOf("/");
  var baseDIR = URLtext.substr(0,x);
  //alert(jsDIR);

  // 將視窗置中
  var winl = (screen.width-xw)/2;
  var wint = (screen.height-xh)/2;
  if (winl < 0) winl = 0;
  if (wint < 0) wint = 0;
  var settings = 'scrollbars=yes, resizable=yes, height='  + xh +  ', width=' + xw  + ',top='  + wint  + ',left='  + winl;
  var gen=window.open('',"_blank",settings);

  gen.document.open();
  gen.document.write("<html>");
  gen.document.write("<head>");
  gen.document.write("  <title>toBalaSWF2 : " + fname + "</title>");
  gen.document.write("  <script type='text/javascript' src='" + baseDIR + "/jslib/swfobject21/swfobject.js'></script>");
  gen.document.write("  <script type='text/javascript'>");
  gen.document.write("     swfobject.embedSWF('" + baseDIR + '/' + fname + "', 'mySWF21', '" + xw + "','" + xh + "', '9.0.0');");
  gen.document.write("  </script>");
  gen.document.write("</head>");
  gen.document.write("<body style='margin:0;padding:0'>");
  gen.document.write("  <div style='margin:0;padding:0;" +"width:" + (xw+2) +";height:" + (xh+2) +"' id='mySWF21'>");
  gen.document.write("    <p>無法撥放</p>");
  gen.document.write("  </div>");
  gen.document.write("</body>");
  gen.document.write("</html>");

  gen.document.close();
}
//}}}
/***
|''巨集名稱:''|toBalaTest|
|''版本:''|1.0 (2010-04-02)|
|''原始檔:''||
|''作者:''|Sung-Lin CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''||
***/

//{{{
config.macros.toBalaTest = {
  handler :  function(place,macroName,params,wikifier,paramString,tiddler) {

     var label = params[0] || "測試開始";
     var tooltip = params[1] || "開啟一個測試視窗";

     if (!params[2]) {
        alert("請給題庫名稱");
        return;
     } 
    
     if (!params[3]) {
        alert("請給題數");
        return;
     } 

     var xSubject = params[2];
     var xNumber = params[3];
     var xwidth = params[4] || 550;
     var xheight = params[5] || 400;
     var xcw = params[6] || "100%";
     var xch = params[7] || "100%";

     // 取出考題
     var xtext=store.getTiddlerText(tiddler.title);
     var x1=xtext.indexOf("/"+"/"+"/"+"%" + xSubject);
     x1=x1+ xSubject.length + 5;
     var x2=xtext.indexOf("/"+"/"+"%"+"/",x1);
     var xContent = xtext.substring(x1,x2);

     // 轉換成考題陣列
     var myTest = eval(xContent);

     // 打亂考題
     var tn=myTest.length;
     for(i=1;i<=500;i++) {
        j = Math.floor(Math.random() * tn);
        k = Math.floor(Math.random() * tn);
       
        var op;
        for (op in myTest[j])
           myTest[tn-1][op]=myTest[j][op];

        for (op in myTest[k])
           myTest[j][op]=myTest[k][op];

        for (op in myTest[tn-1])
           myTest[k][op]=myTest[tn-1][op];
     }

     // 確認題數
     xNumber = (xNumber<=myTest.length)? xNumber : myTest.length;

     // 將考題轉成網頁
     var xText="",i;
     for(i=1;i<=xNumber;++i) {
        xText=xText + "<div id='"+xSubject+i+"' style='position:absolute;left:10px;top:10px;visibility:hidden;'>";
        xText=xText + "第 " + i + "/" + xNumber + " 題" + "&nbsp;&nbsp;<input type='text' id='xTest_Input"+ i + "'/>";
        xText=xText + "&nbsp;<button onclick='xUp();'>上一題</button>&nbsp;<button onclick='xDown();'>下一題</button>";
        xText=xText + "&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<button onclick='xScore();'>結束</button>&nbsp;";
        xText=xText + "<span style='visibility:hidden;color:red;' id='xTest_Answer"+i+"'>"+myTest[i][1]+"</span>";
        xText=xText + "<br/><br/><img style='border:1px solid black' src='"+myTest[i][0]+"' width='"+xcw+"' height='"+xch+"'/>";
        xText=xText + "</div>";
     }

     // 操作按鈕程式製作
     xText = xText + "<script>";
     xText = xText + "var xNumber=1, xNumberMax="+ xNumber +";var xSub='"+xSubject+"';";
     xText = xText + "document.getElementById(xSub+xNumber).style.visibility=''; ";
     xText = xText + "function xUp() { if (xNumber>1) {xNumber--;";
     xText = xText + "        document.getElementById(xSub+xNumber).style.visibility=''; ";
     xText = xText + "        document.getElementById(xSub+(xNumber+1)).style.visibility='hidden';} }";
     xText = xText + "function xDown() { if (xNumber<xNumberMax) {xNumber++;";
     xText = xText + "         document.getElementById(xSub+xNumber).style.visibility=''; ";
     xText = xText + "         document.getElementById(xSub+(xNumber-1)).style.visibility='hidden';} }";
     xText = xText + "function xScore() { var xc=0; var xA='';";
     xText = xText + "    for (i=1; i<=xNumberMax; ++i) {";
     xText = xText + "         xA=document.getElementById('xTest_Answer'+i).innerHTML.toLowerCase();";
     xText = xText + "         if (xA==document.getElementById('xTest_Input'+i).value.toLowerCase()) {"; 
     xText = xText + "            xc++;document.getElementById('xTest_Answer'+i).style.visibility='hidden' }";
     xText = xText + "         else { document.getElementById('xTest_Answer'+i).style.visibility=''; }";
     xText = xText + "    }";
     xText = xText + "    alert('共 ' + xNumberMax +' 題 : 答對 '+ xc +' 題'); }";
     xText = xText + "</script>";

     createTiddlyButton(place, label, tooltip,
         function(e) { config.macros.toBalaTest.run(e,xText,xwidth,xheight); },
         null, null, null);
  },

  run : function(ev,xct,xw,xh) {

     if (config.browser.isIE) {
        window.event.cancelBubble=true;
     } else {  
        ev.cancelBubble=true;   
        if (ev.stopPropagation)  
           ev.stopPropagation();
     }

     // 將視窗置中
     var winl = (screen.width-xw)/2;
     var wint = (screen.height-xh)/6;
     if (winl < 0) winl = 0;
     if (wint < 0) wint = 0;
     var settings = 'height='  + xh +  ', width=' + xw  + ',top='  + wint  + ',left='  + winl + ',scrollbars=yes';

     // 顯示考題網頁
     var xTest="<html><body style='color:black;font-size=36px;font-weight:bold'>" + xct + "</body></html>";

     // 開啟測試視窗
     var xwin=window.open('','',settings);
     xwin.document.open();
     xwin.document.write(xTest);
     xwin.document.close();
  } 
};
/*
利用 eval() 來將 JSON 字串轉成物件,不過字串的前後記得要加上刮號 (),這是用來告知 Javascript Interpreter 這是個物件描述,不是要執行的 statement。

但是呼叫 eval() 是危險的,因為他會執行任何字串中的 Javascript 程式碼,容易有 XSS 攻擊的危險,所以一般都建議引用官網上所提供的 parser - http://www.json.org/json.js 。
*/
//}}}
 [[首頁]] | [[土芭樂 3.0 - 數位新思路|http://tbala.net/]]  | [[TiddlyWiki 練功坊|http://tiddlywiki.tbala.net/]] | [[匯入文章]]  | [[匯出文章]]  |  &nbsp;&nbsp;<<toBalaRun "Java-CMD.bat" "" "命令提示視窗">>&nbsp;&nbsp;<<newTiddler label:"新增文章">>&nbsp;&nbsp;<<closeAll>>&nbsp;&nbsp;<<saveChanges>> 
/***
|''巨集名稱:''|toBalaWrite|
|''版本:''|1.0 (2008-09-01)|
|''原始檔:''||
|''作者:''|S L CHEN|
|''授權:''|BSD|
|''倚賴''||
|''TiddlyWiki 適用版本''|2.3+|
|''適用瀏覽器''|Firefox 1.5+, IE 6.0+|
|''使用語法''| |
***/

//{{{
config.macros.toBalaWrite = {};
config.macros.toBalaWrite.handler = function(place, macroName, params, wikifier, paramString, tiddler) {
	var title = params[0];
	if (title == tiddler.title) {
            title = "Error: Can't use the same tiddler from which the macro is called (infinite recursion)!";
            alert(title);
            return;
	}
	var tiddler = store.getTiddler(title);
        var contents = tiddler.text;
	wikify(contents, place);
}
//}}}
/***
|''Name:''|DropDownMenuPlugin|
|''Description:''|Create dropdown menus from unordered lists|
|''Author:''|Saq Imtiaz ( lewcid@gmail.com )|
|''Source:''|http://tw.lewcid.org/#DropDownMenuPlugin|
|''Code Repository:''|http://tw.lewcid.org/svn/plugins|
|''Version:''|2.1|
|''Date:''|11/04/2007|
|''License:''|[[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''~CoreVersion:''|2.2.5|

!!Usage:
* create a two-level unordered list using wiki syntax, and place {{{<<dropMenu>>}}} on the line after it.
* to create a vertical menu use {{{<<dropMenu vertical>>}}} instead.
* to assign custom classes to the list, just pass them as parameters to the macro {{{<<dropMenu className1 className2 className3>>}}}

!!Features:
*Supports just a single level of drop-downs, as anything more usually provides a poor experience for the user.
* Very light weight, about 1.5kb of JavaScript and 4kb of CSS.
* Comes with two built in css 'themes', the default horizontal and vertical. 

!!Customizing:
* to customize the appearance of the menu's, you can either add a custom class as described above or, you can edit the CSS via the StyleSheetDropDownMenu shadow tiddler.


***/
// /%
//!BEGIN-PLUGIN-CODE
config.macros.dropMenu={

	dropdownchar: "\u25bc",

	handler : function(place,macroName,params,wikifier,paramString,tiddler){
		list = findRelated(place.lastChild,"UL","tagName","previousSibling");
		if (!list)
			return;
		addClass(list,"suckerfish");
		if (params.length){
			addClass(list,paramString);
		}
		this.fixLinks(list);
	},
	
	fixLinks : function(el){
		var els = el.getElementsByTagName("li");
		for(var i = 0; i < els.length; i++) {
			if(els[i].getElementsByTagName("ul").length>0){
				var link = findRelated(els[i].firstChild,"A","tagName","nextSibling");
				if(!link){
					var ih = els[i].firstChild.data;
					els[i].removeChild(els[i].firstChild);
					var d = createTiddlyElement(null,"a",null,null,ih+this.dropdownchar,{href:"javascript:;"});
					els[i].insertBefore(d,els[i].firstChild);
				}
				else{
					link.firstChild.data = link.firstChild.data + this.dropdownchar;
					removeClass(link,"tiddlyLinkNonExisting");
				}
			}
			els[i].onmouseover = function() {
				addClass(this, "sfhover");
			};
			els[i].onmouseout = function() {
				removeClass(this, "sfhover");
			};
		}
	}	
};

config.shadowTiddlers["StyleSheetDropDownMenuPlugin"] = 
	 "/*{{{*/\n"+
	 "/***** LAYOUT STYLES -  DO NOT EDIT! *****/\n"+
	 "ul.suckerfish, ul.suckerfish ul {\n"+
	 "	margin: 0;\n"+
	 "	padding: 0;\n"+
	 "	list-style: none;\n"+
	 "	line-height:1.4em;\n"+
	 "}\n\n"+
	 "ul.suckerfish  li {\n"+
	 "	display: inline-block; \n"+
	 "	display: block;\n"+
	 "	float: left; \n"+
	 "}\n\n"+
	 "ul.suckerfish li ul {\n"+
	 "	position: absolute;\n"+
	 "	left: -999em;\n"+
	 "}\n\n"+
	 "ul.suckerfish li:hover ul, ul.suckerfish li.sfhover ul {\n"+
	 "	left: auto;\n"+
	 "}\n\n"+
	 "ul.suckerfish ul li {\n"+
	 "	float: none;\n"+
	 "	border-right: 0;\n"+
	 "	border-left:0;\n"+
	 "}\n\n"+
	 "ul.suckerfish a, ul.suckerfish a:hover {\n"+
	 "	display: block;\n"+
	 "}\n\n"+
	 "ul.suckerfish li a.tiddlyLink, ul.suckerfish li a, #mainMenu ul.suckerfish li a {font-weight:bold;}\n"+
	 "/**** END LAYOUT STYLES *****/\n"+
	 "\n\n"+
	 "/**** COLORS AND APPEARANCE - DEFAULT *****/\n"+
	 "ul.suckerfish li a {\n"+
	 "	padding: 0.5em 1.5em;\n"+
	 "	color: #FFF;\n"+
	 "	background: #0066aa;\n"+
	 "	border-bottom: 0;\n"+
	 "	font-weight:bold;\n"+
	 "}\n\n"+
	 "ul.suckerfish li:hover a, ul.suckerfish li.sfhover a{\n"+
	 "	background: #00558F;\n"+
	 "}\n\n"+
	 "ul.suckerfish li:hover ul a, ul.suckerfish li.sfhover ul a{\n"+
	 "	color: #000;\n"+
	 "	background: #eff3fa;\n"+
	 "	border-top:1px solid #FFF;\n"+
	 "}\n\n"+
	 "ul.suckerfish ul li a:hover {\n"+
	 "	background: #e0e8f5;\n"+
	 "}\n\n"+
	 "ul.suckerfish li a{\n"+
	 "	width:9em;\n"+
	 "}\n\n"+
	 "ul.suckerfish ul li a, ul.suckerfish ul li a:hover{\n"+
	 "	display:inline-block;\n"+
	 "	width:9em;\n"+
	 "}\n\n"+
	 "ul.suckerfish li {\n"+
	 "	border-left: 1px solid #00558F;\n"+
	 "}\n"+
	 "/***** END COLORS AND APPEARANCE - DEFAULT *****/\n"+
	 "\n\n"+
	 "/***** LAYOUT AND APPEARANCE: VERTICAL *****/\n"+
	 "ul.suckerfish.vertical li{\n"+
	 "	width:10em;\n"+
	 "	border-left: 0px solid #00558f;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical ul li, ul.suckerfish.vertical li a, ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a {\n"+
	 "	border-left: 0.8em solid #00558f;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical li a, ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a,  ul.suckerfish.vertical li.sfhover a:hover{\n"+
	 "	width:8em;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical {\n"+
	 "	width:10em; text-align:left;\n"+
	 "	float:left;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical li a {\n"+
	 "	padding: 0.5em 1em 0.5em 1em;\n"+
	 "	border-top:1px solid  #fff;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical, ul.suckerfish.vertical ul {\n"+
	 "	line-height:1.4em;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical li:hover ul, ul.suckerfish.vertical li.sfhover ul { \n"+
	 "	margin: -2.4em 0 0 10.9em;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical li:hover ul li a, ul.suckerfish.vertical li.sfhover ul li a {\n"+
	 "	border: 0px solid #FFF;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical li:hover a, ul.suckerfish.vertical li.sfhover a{\n"+
	 "	padding-right:1.1em;\n"+
	 "}\n\n"+
	 "ul.suckerfish.vertical li:hover ul li, ul.suckerfish.vertical li.sfhover ul li {\n"+
	 "	border-bottom:1px solid  #fff;\n"+
	 "}\n\n"+
	 "/***** END LAYOUT AND APPEARANCE: VERTICAL *****/\n"+
	 "/*}}}*/";
store.addNotification("StyleSheetDropDownMenuPlugin",refreshStyles);
//!END-PLUGIN-CODE
// %/

<<importTiddlers inline>>
<<exportTiddlers inline>>
/***
|''Name:''|LaunchApplicationPlugin|
|''Author:''|Lyall Pearce|
|''Source:''|http://www.Remotely-Helpful.com/TiddlyWiki/LaunchApplication.html|
|''License:''|[[Creative Commons Attribution-Share Alike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
|''Version:''|1.4.0|
|''~CoreVersion:''|2.3.0|
|''Requires:''| |
|''Overrides:''| |
|''Description:''|Launch an application from within TiddlyWiki using a button|
!!!!!Usage
<<<
{{{<<LaunchApplication "buttonLabel" "tooltip" "application" ["arguments" ...]>>}}}
{{{<<LaunchApplicationButton "buttonLabel" "tooltip" "application" ["arguments" ...]>>}}}
{{{<<LaunchApplicationLink "buttonLabel" "tooltip" "application" ["arguments" ...]>>}}}
* buttonLabel is anything you like
* tooltip is anything you like
* application is a path to the executable (which is Operating System dependant)
* arguments is any command line arguments the application requires.
* You must supply relative path from the location of the TiddlyWiki OR a fully qualified path
* Forward slashes works fine for Windows

{{{<<LaunchApplication...>>}}} functions the same as {{{<<LaunchApplicationButton...>>}}}

eg.

{{{
<<LaunchApplicationButton "Emacs" "Linux Emacs" "file:///usr/bin/emacs">>
}}}
<<LaunchApplicationButton "Emacs" "Linux Emacs" "file:///usr/bin/emacs">>

{{{
<<LaunchApplicationLink "LocalProgram" "Program relative to Tiddly html file" "localDir/bin/emacs">>
}}}
<<LaunchApplicationLink "LocalProgram" "Program relative to Tiddly html file" "localDir/bin/emacs">>
					     
{{{
<<LaunchApplicationButton "Open Notepad" "Text Editing" "file:///e:/Windows/notepad.exe">>
}}}
<<LaunchApplicationButton "Open Notepad" "Text Editing" "file:///e:/Windows/notepad.exe">>

{{{
<<LaunchApplicationLink "C Drive" "Folder" "file:///c:/">>
}}}
<<LaunchApplicationLink "C Drive" "Folder" "file:///c:/">>


!!!!!Revision History
* 1.1.0 - leveraged some tweaks from from Bradly Meck's version (http://bradleymeck.tiddlyspot.com/#LaunchApplicationPlugin) and the example text.
* 1.2.0 - Make launching work in Linux too and use displayMessage() to give diagnostics/status info.
* 1.3.0 - execute programs relative to TiddlyWiki html file plus fix to args for firefox.
* 1.3.1 - parameters to the macro are properly parsed, allowing dynamic paramters using {{{ {{javascript}} }}} notation.
* 1.4.0 - updated core version and fixed empty tooltip and added launch link capability
***/
本文網址 : http://www.zdnet.com.tw/news/web/0,2000085679,20145325,00.htm

ZDNET新聞專區:Ina Fried 2010/05/04 12:14:02
微軟的瀏覽器市場佔有率持續滑落,最新統計的4月份,IE使用者比率已跌破60%。

根據Net Applications的統計,今年4月IE市佔率從3月份的60.65%進一步降至59.95%。收穫最大的是Google Chrome,從6.13%升至6.73%,而Firefox微幅增加約0.1個百分點,達24.59%。

IE流失使用者給Google和Mozilla,已是持續數年的市場趨勢。2008年5月時,微軟的市佔率還有75.94%,而Firefox只有 18.3%,Google Chrome甚至尚未問世。

即使在1年前,微軟的市佔率仍比現在高出8個百分點。之後,Google、Mozilla和蘋果,全都進一步蠶食IE的市場。

微軟已表明將提升其瀏覽器市場的競爭力。今年3月的Mix 2010活動,微軟便發佈Internet Explorer 9的技術預覽。新版的瀏覽器將利用一項Windows PC的繪圖效能,輔助圖像和文字的呈現。但最近外界對IE9的注意,是微軟宣布新版瀏覽器內建的HTML 5影音支援,將只限H.264編/解碼器。

微軟的IE總經理Dean Hachamovitch 3日在公司部落格回應外界的批評。他說H.264與其他格式相比,能提供一個「更確定的」路徑。

他表示:「相較於其他選擇,H.264在PC及行動裝置保有強大的硬體支援,和世界各地許多消費者電器產品的採用。還有絕佳的影音品質、大規模的既有應用、可用的工具和內容授權體系,與整體產業的推動—每一項都是構成我們的觀點的重要因素。…對許多在這個領域握有專利的公司而言,H.264也在合法權利方面,提供最好的確定性。」(陳智文/譯)
本文網址 : http://www.ithome.com.tw/itadm/article.php?c=64838
文/陳曉莉 (編譯) 2010-12-02

原本對 Linux 貢獻度只有 1.0% 的 Nokia,一年來突然躍升到 2.3%,並進入貢獻度前十大排行榜,而原本未出現在前三十排行榜的三星電子今年則貢獻了 0.6%的程式。

[img[img/linuxadd.jpg]]

Linux基金會於本周發表Linux核心開發的年度報告,該報告主要公布Linux核心一年來的發展狀況,除了宣布Linux核心程式增加了150萬行以外,並發現今年有來自全球行動/消費性電子產品及嵌入技術的業者加入了Linux核心開發領域,包括Nokia、三星電子、AMD及德州儀器等。

Linux基金會平均每二至三個月就會更新一次Linux核心版本,全球的Linux社群或業者皆可貢獻相關技術,其中有7成的貢獻是來自於前十大業者,包括紅帽(12.4%)、Novell(7.0%)、IBM(6.9%)、Intel(5.8%)、甲骨文(2.3%)或Linux基金會(1.3%)本身等,都是支持Linux的知名業者。該基金會僅列出貢獻度達到0.6%的30家業者,並強調還有超過500家有貢獻的業者未入列。

不過,該報告指出,自於去年6月發表Linux 2.6.30版核心後,該貢獻版圖就有些變動。例如原本貢獻度只有1.0%的Nokia,一年來突然躍升到2.3%,並進入貢獻度前十大排行榜,而原本未出現在前三十排行榜的三星電子今年則貢獻了0.6%的程式,AMD的貢獻度則自0.8%大幅成長至1.7%,德州儀器也從排行榜外成長到1.5%。

Linux基金會認為,嵌入式或行動業者強化對Linux核心的開發與支持彰顯出Linux在這些市場愈來愈重要。不同的業者發現改善Linux核心有助於市場競爭,例如IBM、HP或Intel等業者是為了確保Linux可在他們的硬體上運行無礙;而紅帽或Novell等業者則是想打造更強大的 Linux平台;至於Sony、Nokia或三星等業者則是將Linux視為行動電話或電視的元件,參與Linux核心的開發可確保Linux在未來的產品中成為可靠的基礎。

Linux基金會並未分析該變動是否與Google Android平台有關,Google採用Linux打造的Android行動平台風靡了全球市場,多家分析機構皆預言數年內Android就會成為全球最受歡迎的行動平台。不過,在該份報告中,Google對Linux核心的貢獻度是從0.8%下滑至0.7%。(編譯/陳曉莉)
用Google搜尋「永遠的真田幸村」時,你會找到將近7萬筆資料,這個具有一定知名度的部落格作者是林昌明。他目前在一家產業分析機構,從事新科技與電子產業分析的工作,在此之前,他還當過 PChome Online資訊人員與PChome雜誌的技術編輯。2004年11月,他創辦了非營利部落格平臺「優格網(yblog)」,在2007年時,Ubuntu的7.04版開始逐漸風行,而林昌明也因維護網站需求,而開始接觸到Linux,自此便喜愛上這種作業系統,而且更進一步的積極推廣這套作業系統。

因為撰寫文章而進入產業研究機構
從2004年11月開始,林昌明便開始撰寫部落格文章,每天都沒有間斷,持續至今已經累積2,100多篇,算一算平均每天都超過一篇文章的產量。而且部落格的內容包羅萬象,包括政治、經濟、IT產業,或者對任何事物的見解與看法。也因為有著獨到的見解,以及產業分析能力,在2006年,他被一家產業研究機構網羅,正式的開始分析與研究網路科技、電子產業等。

從事這樣的工作,他認為就像學生做報告一樣,只是寫出的內容需更有商業的價值,且驗收對象,不再是指導教授或老師,而是交給企業參考或者政府機關,提供他們市場趨勢,或者分析過去的相關資料。

由於大學時期,他所就讀的是臺北大學公共行政學系夜間部,因此白天在PChome Online擔任資訊人員,累積了一些IT的相關經驗,後來轉任Pchome雜誌的技術編輯。

擔任這項職務的時候,除了花很多的時間在測試產品之外,還需要與廠商接洽、訪談,這段過程讓他能得到產品以外,以及個人用戶以外的豐富資訊。

進入產業研究機構之後,所接觸到的對象更多元,從原本的IT系統廠商轉換成製造商,也因此獲得更多的財經資訊。因為這樣的轉變,他認為自己的視野更加寬闊,而且對於產品從生產、製造到銷售等過程等相關情報,能全部融合,使他可以有更完整的認知。因此他在看事情的時候,總是可以從不同的角度切入,提供獨到的觀點。

例如,近日吵得火熱的美國牛肉進口事件,他便在一片反對進口的聲浪中,提出了不一樣的想法,他自認能夠客觀的蒐集各方資訊,不會在人云亦云的環境中,被大眾的聲音淹沒自己的想法。

成立非營利部落格平臺:優格網
在2004年11月,他與幾名夥伴共同成立了非營利部落格平臺優格網(yblog),其實他剛開始成立優格網的時候,曾嘗試過一個人獨自建立,不過發現一個人其實並不是那麼容易完成所有事情,於是與幾個朋友共同合作建立。因為人手充足,因此他們分工合作,一人負責程式,另一人則負責資料庫等其他工作,他發現各司其職之後,其實並沒有想像中的複雜,順利將網站建置起來,還成為Collablog這個CMS系統的示範平臺。

成立優格網之後,他也持續在部落格「永遠的真田幸村」上撰寫文章,由於題材豐富,觀點客觀,因此有許多的網友都很喜歡看他的文章。不過也因為題材豐富,類型廣泛,曾經引起不小的爭議,例如在2008年關於山達基教派的相關文章,在部落格上引起不小的爭執。

積極推廣Ubuntu Linux
當他在PChome Online工作時,因為維護網站而開始接觸RedHat Linux,一段時間之後,自然而然就熟悉了這個作業系統。在2006年10月,Ubuntu 6.10發布,他也嘗試著使用Ubuntu的Desktop版本,而且在下個版本7.04版一發布,他便在個人電腦以及伺服器使用Ubuntu,將自己的電腦環境完全改成Ubuntu Linux。

將全部的使用環境都改用Ubuntu之後,林昌明發現到使用Linux系統的效率,以及可以替代Windows 作業系統的可行性,於是在他所建立的網站以及部落格,大力推廣使用這個作業系統。

為甚麼會如此執著於Linux呢?林昌明表示,剛開始要架設網站的時候,實際測試過各種平臺,他發現,同樣的網站內容、資料庫與硬體,在Linux平臺上的執行效能總是比Windows還要好,執行速度也較快,因此他便決定使用Linux作業系統。

認為應從小了解「電腦不是只有一種選擇」
林昌明對Linux的推崇,不僅是在部落格上大力宣揚,他也參與過Ubuntu中文化的工作,實際為Linux普及出一份心力。他認為,資訊環境不應該被制約在微軟的框架下,因為現實環境中除了微軟架構的作業系統之外,其實還有多種作業系統可以選擇。許多人無法接受不同的作業系統,就是因為已經認定電腦或者作業系統,就等於Windows,而拒絕或者無法更改習慣。

在他努力的推廣之下,他的家人現在也都以Ubuntu為作業系統,他也以他太太的使用經驗為例子,在部落格上介紹她使用Ubuntu的經驗,以及各種便利性,證明這套作業系統確實可以替代生活中的Windows作業系統。

雖然林昌明一家現在都使用Ubuntu取代Windows,不過他在推廣這種作業系統的過程中,還是遭遇到不少挫折。他認為這些阻礙主要有兩個原因:對微軟系統的依賴性,以及使用容易度的質疑。

林昌明表示,由於許多企業擁有ERP、EIP等系統,這些都是基於Windows作業系統開發的套裝軟體,並無法在Windows以外的環境下執行,而且因為微軟的作業系統佔有大多數的市場,許多的網頁也都僅支援IE瀏覽器,雖然在Linux可以使用如VirtualBox等虛擬化工具軟體等解決,不過仍有許多情況是無法解決的。另外,對不同作業系統的使用容易度產生質疑,也是多數人無法接受Windows以外作業系統的原因,通常沒有接觸過 Linux Desktop版本的人,都會覺得很難學會操作,或者是因為剛接觸而不熟悉,很快就退卻了。

推廣Linux的阻礙:電腦的使用習慣難以更改
最近,他與幾名認識的部落客,都升格當了爸爸,林昌明在部落格有感而發的發表了一篇<兒童學電腦應該從Linux發行版開始>,還計畫要成立兒童學習Linux的網站,希望讓小朋友從小就了解「電腦是有很多種選擇的」。

他認為,如果等小朋友長大之後,再來認識Windows以外的作業系統,就如同駭客任務(Matrix)中,還要面臨著選擇紅色(真相)或藍色膠囊(繼續相信你相信的),屆時再來做出選擇或了解真相,是很累的事情。

因此他建議,應該從小開始,就讓他們使用Linux,而且Ubuntu Linux的發行版本中,現在還有教育版本的Edubuntu,裡頭包含語言、數學、物理與化學等,非常適合小朋友學習各種知識,而且也可以學習電腦知識。文⊙林柏凱 

IT人物─林昌明

●1978年生
●學經歷:畢業於臺北大學公共行政學系,曾任PChome Online資訊人員與PChome雜誌技術編輯,目前任職於某產業研究機構,針對新科技與電子產業的資料分析與報告
●成立網站:優格網:http://yblog.org
●個人部落格:http://yblog.org/ivan/

本文網址 : http://www.zdnet.com.tw/news/software/0,2000085678,20142330,00.htm

ZDNet新聞專區:Stephen Shankland  2009/10/27 12:42:01

[img[img/Mark_Shuttleworth.jpg]]

Canonical CEO Mark Shuttleworth

除了 Snow Leopard 和 Windows 7 之外,還有一種作業系統也將進行重大更新:Ubuntu Linux。Canonical 公司計畫在 29 日發佈 "Karmic Koala" 版,同時將桌面和伺服器版往雲端推進一大步。

雲端運算是目前最熱門的科技詞彙,而 Canonical 執行長 Mark Shuttleworth 顯然對這個名詞的濫用相當不滿:「讓我難過的是『雲端』一詞已被用來形容任何有網路連線的東西,包括某些其實非常類似內部 IT  的東西。」然而Ubuntu 的雲端,絕不是掛羊頭賣狗肉。

Ubuntu 9.10 伺服器版內建的 Ubuntu Enterprise Cloud,是奠基於 Eucalyptus 之上的技術。Amazon Web Services(AWS),是以隨付即用模式,透過網路提供的運算基礎設施集合,也是目前最大型的雲段運算服務之一,而 Eucalyptus 部署了當中許多功能,以便企業利用同樣的服務,建立他們自己的「私人雲端」。

桌面版 Ubuntu 的雲端,是一項名為 Ubuntu One 的服務。Ubuntu 使用者可同步化儲存在不同主機的資料,並在中央服務製作備份。2GB 以內的儲存空間免費,50GB 的月費 10 美元。

Ubuntu 相當受到熟悉 Linux 的技術人士歡迎,但也面臨挑戰。在伺服器面,Red Hat 仍居主導位置。至於桌電和筆電,Linux 仍打不進 Windows 或 Mac OS X 等主流市場。

整體而言,Shuttleworth 仍感樂觀。消費者市場成長的一大關鍵是電腦製造商,這方面他認為該公司已有進展。戴爾有提供 Ubuntu電腦,IBM 也在上週發表一套結合 Ubuntu 與 Lotus 的辦公軟體,名為 IBM Client for Smart Work。

Shuttleworth 認為,Linux 無法用微軟定義桌面軟體的方式,搶進 PC 作業系統市場。更好的方法,是抓住新市場的契機,如Chrome OS 和 Moblin。Google 希望利用 Chrome 瀏覽器和 Chrome OS,將作業系統推到幕後,應用軟體則移至網路執行。Shuttleworth 認為 Chrome OS 提供的技術支援,如無線連網硬體等,將有助其他的Linux計畫。

線上儲存服務 Ubuntu One,也能為該公司在消費者作業系統面,創造少許營收。

Shuttleworth 說:「把它想成一個在空中的硬碟,能複製多台主機的內容。我們的使用者大都是專業人士,他們有一台以上的PC,且通常必須和許多散佈在各處的資料奮戰。」資料同步也是一項能夠超越 Linux 的服務。他說:「我們預期這部分將擴及所有Ubuntu 裝置,最終或可拓展到其他平台。」

但 Linux 最成功的市場還是伺服器。在那裡,Linux 被視為 Unix 家族的分支。而 Canonical 希望用 Ubuntu Enterprise Cloud 技術一舉超前。AWS Elastic Compute Cloud(EC2),可供存取單純的運算效能,讓顧客執行本身作業系統的軟體。那些伺服器可儲存資料在 AWS 的 Simple Storage Service(S3),並利用其他 AWS 服務。所有費用均以處理效能的使用量、所需的儲存空間,和用到的網路功能為計算基準。

Ubuntu Enterprise Cloud,是針對希望在本身的伺服器得到類似服務的顧客。該軟體介面仿照 AWS 的 EC2 和 S3,因此,至少在原則上,若某項服務超過組織內部運算容量的負載,多出的部分可直接溢往 Amazon 的基礎設施。

Shuttleworth 說:「原則上,我們的目標是提供API(應用程式介面)相容性。」最後,當這類服務達到大規模市場,管理的標準自會出現。他表示:「我們認為最後會有一個普遍適用的 IETF(網際網路工程任務團隊)管理協定。」(陳智文/譯)

/***
|<html><a name="Top"/></html>''Name:''|PartTiddlerPlugin|
|''Version:''|1.0.9 (2007-07-14)|
|''Source:''|http://tiddlywiki.abego-software.de/#PartTiddlerPlugin|
|''Author:''|UdoBorkowski (ub [at] abego-software [dot] de)|
|''Licence:''|[[BSD open source license]]|
|''CoreVersion:''|2.1.3|
|''Browser:''|Firefox 1.0.4+; InternetExplorer 6.0|
!Table of Content<html><a name="TOC"/></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Description',null, event)">Description, Syntax</a></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Applications',null, event)">Applications</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('LongTiddler',null, event)">Refering to Paragraphs of a Longer Tiddler</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Citation',null, event)">Citation Index</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('TableCells',null, event)">Creating "multi-line" Table Cells</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Tabs',null, event)">Creating Tabs</a></html>
** <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Sliders',null, event)">Using Sliders</a></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Revisions',null, event)">Revision History</a></html>
* <html><a href="javascript:;" onclick="window.scrollAnchorVisible('Code',null, event)">Code</a></html>
!Description<html><a name="Description"/></html>
With the {{{<part aPartName> ... </part>}}} feature you can structure your tiddler text into separate (named) parts. 
Each part can be referenced as a "normal" tiddler, using the "//tiddlerName//''/''//partName//" syntax (e.g. "About/Features").  E.g. you may create links to the parts (e.g. {{{[[Quotes/BAX95]]}}} or {{{[[Hobbies|AboutMe/Hobbies]]}}}), use it in {{{<<tiddler...>>}}} or {{{<<tabs...>>}}} macros etc.


''Syntax:'' 
|>|''<part'' //partName// [''hidden''] ''>'' //any tiddler content// ''</part>''|
|//partName//|The name of the part. You may reference a part tiddler with the combined tiddler name "//nameOfContainerTidder//''/''//partName//. <<br>>If you use a partName containing spaces you need to quote it (e.g. {{{"Major Overview"}}} or {{{[[Shortcut List]]}}}).|
|''hidden''|When defined the content of the part is not displayed in the container tiddler. But when the part is explicitly referenced (e.g. in a {{{<<tiddler...>>}}} macro or in a link) the part's content is displayed.|
|<html><i>any&nbsp;tiddler&nbsp;content</i></html>|<html>The content of the part.<br>A part can have any content that a "normal" tiddler may have, e.g. you may use all the formattings and macros defined.</html>|
|>|~~Syntax formatting: Keywords in ''bold'', optional parts in [...]. 'or' means that exactly one of the two alternatives must exist.~~|
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!Applications<html><a name="Applications"/></html>
!!Refering to Paragraphs of a Longer Tiddler<html><a name="LongTiddler"/></html>
Assume you have written a long description in a tiddler and now you want to refer to the content of a certain paragraph in that tiddler (e.g. some definition.) Just wrap the text with a ''part'' block, give it a nice name, create a "pretty link" (like {{{[[Discussion Groups|Introduction/DiscussionGroups]]}}}) and you are done.

Notice this complements the approach to first writing a lot of small tiddlers and combine these tiddlers to one larger tiddler in a second step (e.g. using the {{{<<tiddler...>>}}} macro). Using the ''part'' feature you can first write a "classic" (longer) text that can be read "from top to bottom" and later "reuse" parts of this text for some more "non-linear" reading.

<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!!Citation Index<html><a name="Citation"/></html>
Create a tiddler "Citations" that contains your "citations". 
Wrap every citation with a part and a proper name. 

''Example''
{{{
<part BAX98>Baxter, Ira D. et al: //Clone Detection Using Abstract Syntax Trees.// 
in //Proc. ICSM//, 1998.</part>

<part BEL02>Bellon, Stefan: //Vergleich von Techniken zur Erkennung duplizierten Quellcodes.// 
Thesis, Uni Stuttgart, 2002.</part>

<part DUC99>Ducasse, Stéfane et al: //A Language Independent Approach for Detecting Duplicated Code.// 
in //Proc. ICSM//, 1999.</part>
}}}

You may now "cite" them just by using a pretty link like {{{[[Citations/BAX98]]}}} or even more pretty, like this {{{[[BAX98|Citations/BAX98]]}}}.

<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!!Creating "multi-line" Table Cells<html><a name="TableCells"/></html>
You may have noticed that it is hard to create table cells with "multi-line" content. E.g. if you want to create a bullet list inside a table cell you cannot just write the bullet list
{{{
* Item 1
* Item 2
* Item 3
}}}
into a table cell (i.e. between the | ... | bars) because every bullet item must start in a new line but all cells of a table row must be in one line.

Using the ''part'' feature this problem can be solved. Just create a hidden part that contains the cells content and use a {{{<<tiddler >>}}} macro to include its content in the table's cell.

''Example''
{{{
|!Subject|!Items|
|subject1|<<tiddler ./Cell1>>|
|subject2|<<tiddler ./Cell2>>|

<part Cell1 hidden>
* Item 1
* Item 2
* Item 3
</part>
...
}}}

Notice that inside the {{{<<tiddler ...>>}}} macro you may refer to the "current tiddler" using the ".".

BTW: The same approach can be used to create bullet lists with items that contain more than one line.

<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!!Creating Tabs<html><a name="Tabs"/></html>
The build-in {{{<<tabs ...>>}}} macro requires that you defined an additional tiddler for every tab it displays. When you want to have "nested" tabs you need to define a tiddler for the "main tab" and one for every tab it contains. I.e. the definition of a set of tabs that is visually displayed at one place is distributed across multiple tiddlers.

With the ''part'' feature you can put the complete definition in one tiddler, making it easier to keep an overview and maintain the tab sets.

''Example''
The standard tabs at the sidebar are defined by the following eight tiddlers:
* SideBarTabs
* TabAll
* TabMore
* TabMoreMissing
* TabMoreOrphans
* TabMoreShadowed
* TabTags
* TabTimeline

Instead of these eight tiddlers one could define the following SideBarTabs tiddler that uses the ''part'' feature:
{{{
<<tabs txtMainTab 
    Timeline Timeline SideBarTabs/Timeline 
    All 'All tiddlers' SideBarTabs/All 
    Tags 'All tags' SideBarTabs/Tags 
    More 'More lists' SideBarTabs/More>>
<part Timeline hidden><<timeline>></part>
<part All hidden><<list all>></part>
<part Tags hidden><<allTags>></part>
<part More hidden><<tabs txtMoreTab 
    Missing 'Missing tiddlers' SideBarTabs/Missing 
    Orphans 'Orphaned tiddlers' SideBarTabs/Orphans 
    Shadowed 'Shadowed tiddlers' SideBarTabs/Shadowed>></part>
<part Missing hidden><<list missing>></part>
<part Orphans hidden><<list orphans>></part>
<part Shadowed hidden><<list shadowed>></part>
}}}

Notice that you can easily "overwrite" individual parts in separate tiddlers that have the full name of the part.

E.g. if you don't like the classic timeline tab but only want to see the 100 most recent tiddlers you could create a tiddler "~SideBarTabs/Timeline" with the following content:
{{{
<<forEachTiddler 
		sortBy 'tiddler.modified' descending 
		write '(index < 100) ? "* [["+tiddler.title+"]]\n":""'>>
}}}
<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!!Using Sliders<html><a name="Sliders"/></html>
Very similar to the build-in {{{<<tabs ...>>}}} macro (see above) the {{{<<slider ...>>}}} macro requires that you defined an additional tiddler that holds the content "to be slid". You can avoid creating this extra tiddler by using the ''part'' feature

''Example''
In a tiddler "About" we may use the slider to show some details that are documented in the tiddler's "Details" part.
{{{
...
<<slider chkAboutDetails About/Details details "Click here to see more details">>
<part Details hidden>
To give you a better overview ...
</part>
...
}}}

Notice that putting the content of the slider into the slider's tiddler also has an extra benefit: When you decide you need to edit the content of the slider you can just doubleclick the content, the tiddler opens for editing and you can directly start editing the content (in the part section). In the "old" approach you would doubleclick the tiddler, see that the slider is using tiddler X, have to look for the tiddler X and can finally open it for editing. So using the ''part'' approach results in a much short workflow.

<html><sub><a href="javascript:;" onclick="window.scrollAnchorVisible('Top',null, event)">[Top]</sub></a></html>

!Revision history<html><a name="Revisions"/></html>
* v1.0.9 (2007-07-14)
** Bugfix: Error when using the SideBarTabs example and switching between "More" and "Shadow". Thanks to cmari for reporting the issue.
* v1.0.8 (2007-06-16)
** Speeding up display of tiddlers containing multiple pard definitions. Thanks to Paco Rivière for reporting the issue.
** Support "./partName" syntax inside <<tabs ...>> macro
* v1.0.7 (2007-03-07)
** Bugfix: <<tiddler "./partName">> does not always render correctly after a refresh (e.g. like it happens when using the "Include" plugin). Thanks to Morris Gray for reporting the bug.
* v1.0.6 (2006-11-07)
** Bugfix: cannot edit tiddler when UploadPlugin by Bidix is installed. Thanks to José Luis González Castro for reporting the bug.
* v1.0.5 (2006-03-02)
** Bugfix: Example with multi-line table cells does not work in IE6. Thanks to Paulo Soares for reporting the bug.
* v1.0.4 (2006-02-28)
** Bugfix: Shadow tiddlers cannot be edited (in TW 2.0.6). Thanks to Torsten Vanek for reporting the bug.
* v1.0.3 (2006-02-26)
** Adapt code to newly introduced Tiddler.prototype.isReadOnly() function (in TW 2.0.6). Thanks to Paulo Soares for reporting the problem.
* v1.0.2 (2006-02-05)
** Also allow other macros than the "tiddler" macro use the "." in the part reference (to refer to "this" tiddler)
* v1.0.1 (2006-01-27)
** Added Table of Content for plugin documentation. Thanks to RichCarrillo for suggesting.
** Bugfix: newReminder plugin does not work when PartTiddler is installed. Thanks to PauloSoares for reporting.
* v1.0.0 (2006-01-25)
** initial version

本文網址 : http://www.zdnet.com.tw/enterprise/blog/0,2000085759,20145471,00.htm

洪朝貴 2010/05/14 05:00:00

我國政府推動科技的著眼點很有趣。我們採取的是 產值觀點 ,而不是 應用觀點 。這個觀點下的科技政策,套在教育上,特別突顯出 「追逐手段,丟棄目的」 的嚴重問題。

以我所熟悉的自由軟體為例,早就重複呼籲:停止淘金美夢方能發現真正價值 ;不過到現在,自由軟體的經費仍舊由經濟部工業局而不是審計部或研考會主導。又以雲端為例, 吳院長大談產值 ;但是導入雲端運算,對消費者而言,真實價值到底在那裡呢?不過如果他聽到先導的實驗替代方案,很有價值,卻沒多少產值,那麼相信這也很難引起他的興趣。因為政績靠產值,而不靠實用價值來呈現。

院長管的事太龐雜,很難講出精確的價值;那麼就只談教育吧。以電子書包為例,政策委員、立法 委員 趙麗雲 和 電 子書包發展促進會楊重和會長 的觀點,都是產值。該促進會成員包含國科會與 「教育界」 (不知道是大學資訊科系為主,還是中小學老師為主?),所以即便不是政府單位,相信對於政府也有極重大的影響力。當然,同樣是 資訊專家 ,如果看到的 產值受惠者 不同,那麼建議導入的科技也就不同。從 數位內容產業推動者 的觀點來看,iPad 比電子書包更適合導入教育界 。

我來補充為什麼:目前一般人所想像的數位內容產業,其產值繫於 遙控數位枷鎖 的完封性;而遙控數位枷鎖 則需要集權架構來支撐 。因為一般 PC 所做的電子書包,有豐富的競爭生態;而單一廠商可以主導一切的 iPad,對於傳統想像的數位內容產業比較友善。(附帶一提:注意力經濟模式下的數位內容產業,並不需要遙控數位枷鎖;不過那是另一個話題。)

用產值觀點看教育,意見最大聲的是產業界 -- 包含產官學界的 資訊專家 。他們關心的對象,是 資訊產業的產值與受惠者 ,而不是教育。

不該用產值觀點看教育? 那麼應該改用什麼觀點來看呢? 我有一個簡單的建議:試著改用教育觀點來看教育如何? 如果邀請 教育專家 ,根據不同的 教育情境 (例如小學、高中數學、自閉症、公民與道德、...),而提出不同的導入建議,不是比較合理嗎? 為什麼政府的這些重大科技政策決策過程當中,都聽不見教育專家及第一線老師的聲音呢?

事實上,就連 關心教育 的資訊專家的意見,也被完全忽略。MIT 媒體實驗室的 OLPC 計畫,其實正是小筆電的先驅。數位科技如何幫助教育? OLPC 計畫主持人 Nicholas Negroponte 認為:「... 小孩子應該創作、溝通、探索、分享...」 。他看到的重點不是那一個廠牌型號的硬體,而是小孩子 溝通、合作的自主學習模式 :

    [OLPC 的] 網狀網路 (Mesh Network) 技術,其重點不在於網路技術本身,而在於它鼓勵合作 -- 孩子們互相學習、孩子們分享,...

網路讓參與、分享、討論變得很容易。Web 2.0 現象、長尾現象、Read-Write-Web、參與式的文化 、... 這些真正改變世界的強大力量,來自於 使用者參與主導 的新型態使用文化,而不是來自於那一個廠牌那一個型號的特定硬體技術。把這些預計投入硬體技術的資源省下來,改用百分之一的資源投入教育部鴨子划水辛苦推動的創用 CC 之類 改變使用文化 的領域,對於教育的貢獻會大得多。

更進一步,決策過程也可以採用真正改變世界的新方式。重點不是我一個人決策局外人的建議;重點更不是 OLPC 成品本身。政府制定這些政策時,應該將 決策過程公開透明化 ,透過網路討論/推薦議題的方式,邀請原本被排除在決策之外的所有民眾,特別是教育專家、第一線的老師、家長共同參與意見。讓消費者與使用者表達他們想購買什麼樣的產品 -- 很可能也應該是非常多樣、長尾、小眾的需求 (OLPC 或任何廠牌的產品都只是其中的一部分) -- 而不是由少數廠商關係良好的 資訊專家 來幫大家決定國家應該拿納稅人的錢替納稅人買什麼樣的產品,這樣才能夠做出真正有意義的 「科技融入教育」 決策。

Negroponte 在一場 檢討 OLPC 推動成效、分享推廣經驗的演講 上提到:直接培力使用者 -- 小朋友,不是老師 -- 帶來令人驚豔的經驗。全球各地的小朋友,用 OLPC 這麼低階便宜的電腦,透過同儕分享學習,竟然不只自學,還能教他們的父母親許多事。且讓我用他演講裡面的一些話來結尾:

    你可以把電腦放進教室。你可以建一間電腦教室。但這些事情都無關宏旨。
    ...
    [原來 OLPC 最大的阻力不是貪污的政府或是物流] 原來最大的阻力,是在正常的商業洪流之下逆流而上 -- 那種來自行銷部門、對教育議題天真無知的觀點。
    ...
    [我自問:] 我做的事情,一般的商業力量會進來做嗎? 如果會,那麼我就不做了。如果一般的商業力量本來就會進來,那麼這裡就不需要我了。
    ...
    我們要做的事情,與商業力量垂直;要推動商業力量改變方向。

哦,對了,他提到促成 OLPC 的許多關鍵人物,是政府官員/公務員。為了臺灣的下一代,我們的政府官員/公務員是否願意聽聽 MIT 教授的建議,是否有勇氣做一些 「一般的商業力量本來不會做的事」、有遠見可以 「推動商業力量改變方向」? 是否願意改用教育觀點來看教育? 或者,我們就是不愛 MIT,就只愛聽談論產值的大型壟斷企業的聲音,堅持用 [資訊產業的] 產值觀點來看教育? 歷史對我們這一代產官學利益結構所做出的最終決定,將會有所記錄與評論。

作者洪朝貴,現任朝陽科技大學資訊管理系副教授,長期推廣自由軟體並關心資訊社會的人權議題。他覺得人生苦短,有趣有意義的好玩事太多了,不值得浪費在「為了升等而寫論文」上面。






前些日子和異塵兄在討論 螢幕截圖是用 JPG 格式來存好呢,或是用 PNG 格式比較好?基於科學的精神,上網找了一下,Wikipedia 果然敘述的鉅細靡遺,PNG 和 JPG 優缺點分析如下:

JPEG can produce a smaller file than PNG for photographic (and photo-like) images since it uses a lossy encoding method specifically designed for photographic image data. Using PNG instead of a high-quality JPEG for such images would result in a large increase in filesize (often 5-10 times) with negligible gain in quality.

JPEG 在面對自然影像的時候,由於是採用失真壓縮演算法,因此壓縮率比 PNG 還要大。簡單來說,如果一張 風景照片 你用 JPG 來存,需要 1MB 的話,用 PNG 就要 5MB~10MB,雖然 PNG 檔案較大但是在視覺品質上面並沒有顯著的優越。

PNG is a better choice than JPEG for storing images that contain text, line art, or other images with sharp transitions. Where an image contains both sharp transitions and photographic parts a choice must be made between the large but sharp PNG and a small JPEG with artifacts around sharp transitions. JPEG also does not support transparency.

PNG 在處理包含文字、線條和明顯輪廓的影像 則較 JPG 來的優越,當影像有明顯輪廓邊緣,JPG 的失真演算法在處理這種邊緣上就會產生瑕疵,PNG 採用無失真演算法,因此影像品質較佳。

JPEG is a poor choice for storing images that require further editing as it suffers from generation loss, whereas lossless formats do not. This makes PNG useful for saving temporary photographs that require successive editing. When the photograph is ready to be distributed, it can then be saved as a JPEG, and this limits the information loss to just one generation.

若影像儲存在未來是需要更進一步的編輯修改的話則 PNG 是比較好的選擇,若是用 JPG 不斷的存取編輯,那麼圖像的品質就越來越差了。當影像已經編輯完畢準備散發傳播的話,JPG 則可以幫你縮小體積,卻不損失太多的畫質。

因此,寫 Blog 用的電腦視窗截圖,全面改用 PNG 吧,因為面對 這種 文字、線條和輪廓明顯的圖像,PNG 的檔案其實不會比 JPG 大多少,有時候可能還比較小呢 :)

圖像及引述文字來源 @ http://en.wikipedia.org/wiki/Portable_Network_Graphics#Comparison_with
&nbsp;&nbsp;&nbsp;''我的最新文章''
<<showUpdates excludeTag:excludeLists write:'(index < 10) ? "|"+(index+1)+"|"+ tiddler.modified.formatString("YYYY-0MM-0DD")+ "|[[" + tiddler.title+"]]|"+tiddler.tags+"|\n" : ""'>>