&#26080;&#21452;&#24341;&#25806;&#22823;&#26434;&#28905; - &#26080;&#21452;&#24341;&#25806;&#23448;&#26041;&#35770;&#22363;:http://bbs.gamediy.net &#21508;&#31181;ACG,GalGame&#20449;&#24687;&#25910;&#38598;.

Welcome to TiddlyWiki created by Jeremy Ruston, Copyright © 2007 UnaMesa Association

    <!--{{{-->
    <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]];}

    .wizard .notChanged {background:transparent;}
    .wizard .changedLocally {background:#80ff80;}
    .wizard .changedServer {background:#8080ff;}
    .wizard .changedBoth {background:#ff8080;}
    .wizard .notFound {background:#ffff80;}
    .wizard .putToServer {background:#ff80ff;}
    .wizard .gotFromServer {background:#80ffff;}

    #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; width:90%; 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 [[ToolbarCommands::ViewToolbar]]'></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 [[ToolbarCommands::EditToolbar]]'></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 excludeLists'></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>>

    replace this content with information about ''your'' blog

    {{small{<<slider
    	{{config.options.chkOpenedSlider=false;"chkOpenedSlider";}}
    	AddANote##sliderSection
    	"add a note..."
    	{{"add a quick note to '"+tiddler.title+"'"}}
    >>}}}/%
    !sliderSection
    <<comment {{tiddler.title}}>>
    !end
    %/

    /***
    |Name|AdvancedOptionsPlugin|
    |Source|http://www.TiddlyTools.com/#AdvancedOptionsPlugin|
    |Documentation|http://www.TiddlyTools.com/#AdvancedOptionsPlugin|
    |Version|1.2.0|
    |Author|Eric Shulman|
    |License|http://www.TiddlyTools.com/#LegalStatements|
    |~CoreVersion|2.3|
    |Type|plugin|
    |Requires||
    |Overrides||
    |Options|##Configuration|
    |Description|automatically add plugin-defined options to the [[AdvancedOptions]] shadow tiddler|
    !!!!!Usage
    <<<
    At document startup, this plugin examines each tiddler tagged with <<tag systemConfig>> and looks for a tiddler slice named "Options" whose value refers to a tiddler section (or separate tiddler) that contains an 'advanced options control panel' for configuring that plugin's features and behavior.  For each plugin that contains an "Options" slice, a tabbed entry is automatically created in the [[AdvancedOptions]] shadow tiddler to display that plugin's control panel.

    As an optional fallback for backward-compatibility with plugin tiddlers that do not define the "Options" slice, this plugin will also look for a section heading named "Configuration" within those tiddlers, so that older plugins that define this section can automatically have their settings added to the [[AdvancedOptions]] tiddler without requiring the "Options" slice to be added.

    This plugin also extends the standard {{{<<option>>}}} macro syntax so you can directly set the internal value of a boolean or text option, without displaying a corresponding checkbox or input field control simply by appending {{{=value}}} syntax to the end of the option ID parameter:
    {{{
    <<option "txtSomeOption=some text">>
    <<option chkSomeOtherOption=true>> OR <<option chkSomeOtherOption=false>>
    }}}
    Example: {{{<<option chkAnimate=false>>}}}
    <<<
    !!!!!Configuration
    <<<
    <<option chkAdvancedOptions>> automatically add plugin-defined options to the [[AdvancedOptions]] shadow tiddler
    <<option chkAdvancedOptionsBackstage>> automatically add plugin-defined options to Backstage menu
    <<option chkAdvancedOptionsFallback>> use <<option txtAdvancedOptionsFallback>> section as a fallback for plugins that don't define an ~AdvancedOptions slice
    //note: these settings only take effect after reloading the document//
    <<<
    !!!!!Revisions
    <<<
    2009.07.23 [1.2.0] added support for enhanced {{{<<option id=value>>}}} 'direct assignment' syntax
    2008.05.09 [1.1.0] add "options" panel to backstage
    2008.04.08 [1.0.0] initial release
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.AdvancedOptionsPlugin= {major: 1, minor: 2, revision: 0, date: new Date(2009,7,23)};

    if (config.options.chkAdvancedOptions===undefined)
    	config.options.chkAdvancedOptions=true;
    if (config.options.chkAdvancedOptionsBackstage===undefined)
    	config.options.chkAdvancedOptionsBackstage=true;
    if (config.options.chkAdvancedOptionsFallback===undefined)
    	config.options.chkAdvancedOptionsFallback=true;
    if (config.options.txtAdvancedOptionsFallback===undefined)
    	config.options.txtAdvancedOptionsFallback="Configuration";
    if (config.optionsDesc) config.optionsDesc.chkAdvancedOptions=
    	"automatically add plugin-defined options to [[AdvancedOptions]]";
    //}}}
    //{{{
    var items=[];
    var fmt="[[%0 ]] [[view options for %0]] [[%1]]\n";
    var section=config.options.txtAdvancedOptionsFallback;
    var plugins=store.getTaggedTiddlers("systemConfig");
    for (var p=0; p<plugins.length; p++) {
    	var tid=plugins[p].title;
    	var settings=store.getTiddlerSlice(tid,"Options");
    	if (!settings && config.options.chkAdvancedOptionsFallback && store.getTiddlerText(tid+"##"+section))
    		settings="##"+section; // fallback handling for older plugins
    	if (settings&&settings.length) {
    		if (settings.substr(0,2)=="##") settings=tid+settings;
    		items.push(fmt.format([tid,settings]));
    	}
    }
    if (items.length) config.shadowTiddlers.PluginOptions=
    	"!![[Plugin-defined options|PluginManager]]\n>@@text-align:left;<<tabs '' \n"+items.join(' ')+">>@@";
    if (config.options.chkAdvancedOptions)
    	config.shadowTiddlers.AdvancedOptions+="{{smallform{{{wrap{<<tiddler PluginOptions>>}}}}}}";
    //}}}
    //{{{
    // // add "options" backstage task
    if (config.tasks && config.options.chkAdvancedOptionsBackstage) { // for TW2.2b3 or above
    	config.tasks.options = {
    		text: "options",
    		tooltip: "manage plugin-defined option settings",
    		content: "{{smallform{{{groupbox{{{wrap{<<tiddler PluginOptions>>}}}}}}\n{{groupbox small {<<options>>}}}}}}"
    	}
    	config.backstageTasks.splice(config.backstageTasks.indexOf("plugins")+1,0,"options");
    }
    //}}}
    //{{{
    config.macros.option.AOPsave_handler=config.macros.option.handler;
    config.macros.option.handler=function(place,macroName,params,wikifier,paramString,tiddler) {
    	var parts=params[0].split('=');
    	if (parts.length==1) return this.AOPsave_handler.apply(this,arguments);
    	var id=parts[0]; var val=(id.substr(0,3)=='txt')?parts[1]:(parts[1]=='true');
    	config.options[id]=val;
    }
    //}}}

    /%
    |Name|AutoRefresh|
    |Source|http://www.TiddlyTools.com/#AutoRefresh|
    |Version|0.6.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|script|
    |Requires|InlineJavascriptPlugin|
    |Overrides||
    |Description|enable/disable auto-refresh of selected content to force/prevent re-rendering when tiddler changes occur|

    usage:
    	<<tiddler AutoRefresh with: mode id>>

    where:
    	mode - (optional) is one of:
    		off (or disable) - prevent refresh of rendered content (except when PageTemplate is changed!)
    		on (or enable)- re-render content whenever corresponding tiddler source is changed
    		force - re-render content whenever ANY tiddler content is changes (or refreshDisplay() is triggered)
    	id - (optional)
    		is a unique DOM element identifier on which to operate.
    		If not specified, the current tiddler (or containing parent if not in a tiddler) is used.

    %/<script>
    	var here=story.findContainingTiddler(place);
    	if (here) { // in a tiddler, get containing viewer element
    		var here=place; while (here && here.className!='viewer') here=here.parentNode;
    		if (!here) return; // no 'viewer' element (perhaps a custom template?)
    	}
    	else here=place.parentNode; // not in a tiddler, use immediate parent container

    	// if DOM id param, get element by ID instead of using container
    	if ("$2"!="$"+"2") var here=document.getElementById("$2");

    	if (!here) return; // safety check

    	var mode="$1"; if (mode=="$"+"1") mode="on";

    	switch (mode.toLowerCase()) {
    		case 'on':
    		case 'enable':
    		case 'force':
    			var title=here.getAttribute("tiddler");
    			if (!title) { // find source tiddler title
    				var tid=story.findContainingTiddler(place);
    				if (!tid) return; // can't determine source tiddler
    				title=tid.getAttribute("tiddler");
    			}
    			here.setAttribute("tiddler",title);
    			here.setAttribute("refresh","content");
    			here.setAttribute("force",(mode=='force')?"true":"");
    			break;
    		case 'off':
    		case 'disable':
    			here.setAttribute("refresh","");
    			here.setAttribute("force","");
    			break;
    	}
    </script>

    /%
    URL: Enter a URL
    Description: enter a description
    Author: enter author/moderator info
    %/
    enter your notes here

    /%
    Description: enter a description here
    %/
    enter FAQ content here

    /%
    Description: enter a description here (for display in JournalViewer droplist)
    %/$1
    enter content here

    /%
    |Name|BookmarkList|
    |Source|http://www.TiddlyTools.com/#BookmarkList|
    |Version|1.0.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|script|
    |Requires|InlineJavascriptPlugin|
    |Overrides||
    |Description|generate MiniBrowser-compatible HR-separated list of tiddlers tagged with bookmark|

    Usage: <<miniBrowser BookmarkList>>

    %/<script>
    	var out=[];
    	var tids=store.getTaggedTiddlers("bookmark");
    	for (var i=0; i<tids.length; i++) {
    		var t=tids[i].title;
    		var d=store.getTiddlerSlice(t,"Description");
    		var u=store.getTiddlerSlice(t,"URL")
    		out.push("[[%0]] - %1\n%2".format([t,d,u]));
    	}
    	return out.join("\n----\n");
    </script>

    Tiddlers that are tagged with<<tag bookmark>>can be used to define ''~URLs, descriptions and author information for favorite websites''.

    Bookmark tiddlers are displayed using a custom BookmarkViewTemplate (requires use of TaggedTemplateTweak), which automatically embeds the website directly in the tiddler content using an HTML "IFRAME" element.  Most (but not all) of the bookmarks distributed with this TiddlyTools package refer to TiddlyWiki documents and are also tagged with<<tag systemServer>>, allowing them to be selected as import sources when using the TiddlyWiki standard ImportTiddlers function.

    To create additional bookmarks, simply copy the BlankBookmark tiddler, edit the URL, description, and author info, tag the new tiddler with<<tag bookmark>>and press 'done' to start viewing the remote URL.  Alternatively, you can add the following """<<newTiddler>>""" macro in your SideBarOptions (or any other tiddler) to insert a<<newTiddler label:'new bookmark' title:'NewBookmark' text:{{store.getTiddlerText('BlankBookmark','')}} tag:'bookmark' prompt:'create a bookmark tiddler'>>command into your document:
    {{{
    <<newTiddler label:'new bookmark' title:'NewBookmark' tag:'bookmark'
    	text:{{store.getTiddlerText('BlankBookmark','')}}>>
    }}}

    <!--{{{-->
    <!--
    |Name|BookmarkViewTemplate|
    |Source|http://www.TiddlyTools.com/#BookmarkViewTemplate|
    |Version||
    |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|template|
    |Requires|WikifyPlugin, TaggedTemplateTweak|
    |Overrides||
    |Description|custom template used to display tiddlers tagged with "Bookmark"|

    Usage:
    Create a tiddler tagged with "bookmark" (or "Bookmark") and enter URL, description and author using a 'slice table':
    	|URL:|Enter a URL|
    	|Description:|enter a description|
    	|Author:|enter author/moderator info|
    -->
    <span class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></span>
    <div class='toolbar' macro='tiddler RefreshCommand'></div>
    <span class='title' macro='view title'></span>
    <span macro='tiddler AddANote if:{{store.tiddlerExists(story.findContainingTiddler(place).getAttribute("tiddler")) && tiddler && tiddler.tags.containsAny(["annotate", "bookmark", "journal", "blog"])}} with: {{tiddler?tiddler.title:""}}'></span>
    <!-- OMIT
    <span class='subtitle' style='white-space:nowrap' macro='view modified date [[DDD, MMM DDth YYYY]]'></span>
    -->
    <div class='tagClear'></div>
    <div class='viewer'>
    	<div class='floatleft' macro='wikify "{{big{[[%0|%1]]}}}<br>" here::Description here::URL'></div>
    	<div class='toolbar'>
    		<a class='button' href='javascript:;'
    			onclick='window.history.go(-1);' title='go back one page'>back</a>
    		<a class='button' href='javascript:;'
    			onclick='window.history.go(+1);' title='go foward one page'>forward</a>
    		<a class='button' href='javascript:;'
    			onclick='var f=this.parentNode.parentNode.getElementsByTagName("iframe")[0];
    			f.src=f.src'
    			title='reload current page'>reload</a>
    		<a class='button' href='javascript:;'
    			onclick='var f=this.parentNode.parentNode.getElementsByTagName("iframe")[0];
    				var w=prompt("Enter a new frame width (use px, em, cm, in, or %)","100%");
    				if (!w||!w.length) return; if (!w.replace(/[0-9]*/,"").length) w+="px";
    				f.style.width=w;'
    			title='set frame width'>width</a>
    		<a class='button' href='javascript:;'
    			onclick='var f=this.parentNode.parentNode.getElementsByTagName("iframe")[0];
    				var h=prompt("Enter a new frame height (use px, em, cm, or in)","500");
    				if (!h||!h.length) return; if (!h.replace(/[0-9]*/,"").length) h+="px";
    				f.style.height=h;'
    			title='set frame height'>height</a>
    		<a class='button' href='javascript:;'
    			onclick='var f=this.parentNode.parentNode.getElementsByTagName("iframe")[0];
    				var show=f.style.display=="none";
    				f.style.display=show?"block":"none";
    				this.innerHTML=show?"hide":"show";'
    			title="toggle display of this frame (but DON'T reload content)">hide</a>
    	</div><div class='tagClear'
    		macro='wikify [[<html><iframe src="%0" height="500" width="100%" style="background:#fff"></iframe></html>]] here::URL'>
    	</div>
    	<div macro='view text wikified'></div>
    </div>
    <!--}}}-->

    /%
    |Name|BreadcrumbsCommand|
    |Source|http://www.TiddlyTools.com/#BreadcrumbsCommand|
    |Version|1.0.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|script|
    |Requires|BreadcrumbsPlugin|
    |Overrides||
    |Description|"crumbs" command displays current breadcrumbs list in a popup|

    %/<html><hide linebreaks><a href="javascript:;" class="button" title="tiddlers viewed during this session"
    	onclick="var p=Popup.create(this); if (!p) return;
    		var d=createTiddlyElement(p,'div');
    		d.style.whiteSpace='normal'; d.style.width='auto'; d.style.padding='2px';
    		wikify('\<\<breadcrumbs [[\<html\>\<hr\>\</html\>]] [[<br>]]\>\>',d);
    		Popup.show(p,false); event.cancelBubble = true; if (event.stopPropagation) event.stopPropagation();
    		return(false);"
    >$1</a></html>

    /***
    |Name|BreadcrumbsPlugin|
    |Author|Eric Shulman|
    |Source|http://www.TiddlyTools.com/#BreadcrumbsPlugin|
    |Documentation|http://www.TiddlyTools.com/#BreadcrumbsPluginInfo|
    |Version|2.1.0|
    |License|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
    |~CoreVersion|2.1|
    |Type|plugin|
    |Requires||
    |Overrides|Story.prototype.displayTiddler,TiddlyWiki.prototype.deleteTiddler|
    |Options|##Configuration|
    |Description|list/jump to tiddlers viewed during this session plus "back" button/macro|
    This plugin provides a list of links to all tiddlers opened during the session, creating a "trail of breadcrumbs" from one tiddler to the next, allowing you to quickly navigate to any previously viewed tiddler, or select 'home' to reset the display to the initial set of tiddlers that were open at the start of the session (i.e., when the document was loaded into the browser).
    !!!!!Documentation
    <<<
    see [[BreadcrumbsPluginInfo]]
    <<<
    !!!!!Configuration
    <<<
    <<option chkCreateDefaultBreadcrumbs>> automatically create breadcrumbs display (if needed)
    <<option chkShowBreadcrumbs>> show/hide breadcrumbs display
    <<option chkReorderBreadcrumbs>> re-order breadcrumbs when visiting a previously viewed tiddler
    <<option chkBreadcrumbsHideHomeLink>> omit 'Home' link from breadcrumbs display
    <<option chkBreadcrumbsSave>> prompt to save breadcrumbs when 'Home' link is pressed
    <<option chkShowStartupBreadcrumbs>> show breadcrumbs for 'startup' tiddlers
    <<option chkBreadcrumbsReverse>> show breadcrumbs in reverse order (most recent first)
    <<option chkBreadcrumbsLimit>> limit breadcrumbs display to {{twochar{<<option txtBreadcrumbsLimit>>}}} items
    <<option chkBreadcrumbsLimitOpenTiddlers>> limit open tiddlers to {{twochar{<<option txtBreadcrumbsLimitOpenTiddlers>>}}} items

    <<<
    !!!!!Revisions
    <<<
    2009.03.22 [2.1.0] added 'save breadcrumbs to tiddler' feature
    | Please see [[BreadcrumbsPluginInfo]] for previous revision details |
    2006.02.01 [1.0.0] initial release
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.BreadcrumbsPlugin= {major: 2, minor: 1, revision: 0, date: new Date("March 2, 2009")};

    var co=config.options; // abbreviation

    // show/hide display option (default is to SHOW breadcrumbs)
    if (co.chkShowBreadcrumbs===undefined) co.chkShowBreadcrumbs=true;

    // REORDER breadcrumbs when visiting previously viewed tiddler (default)
    if (co.chkReorderBreadcrumbs===undefined) co.chkReorderBreadcrumbs=true;

    // create default breadcrumbs display as needed (default is to CREATE)
    if (co.chkCreateDefaultBreadcrumbs===undefined) co.chkCreateDefaultBreadcrumbs=true;

    // show breadcrumbs for 'startup' tiddlers (default is FALSE = only show crumbs for tiddlers opened after startup)
    if (co.chkShowStartupBreadcrumbs===undefined) co.chkShowStartupBreadcrumbs=false;

    // show crumbs in reverse order (most recent first)
    if (co.chkBreadcrumbsReverse===undefined) co.chkBreadcrumbsReverse=false;

    // limit number of crumbs displayed
    if (co.chkBreadcrumbsLimit===undefined) co.chkBreadcrumbsLimit=false;
    if (co.txtBreadcrumbsLimit===undefined) co.txtBreadcrumbsLimit=5;

    // limit number of open tiddlers
    if (co.chkBreadcrumbsLimitOpenTiddlers===undefined) co.chkBreadcrumbsLimitOpenTiddlers=false;
    if (co.txtBreadcrumbsLimitOpenTiddlers===undefined) co.txtBreadcrumbsLimitOpenTiddlers=3;

    // omit home link from breadcrumbs display
    if (co.chkBreadcrumbsHideHomeLink===undefined) co.chkBreadcrumbsHideHomeLink=false;

    // prompt for 'save crumbs' when 'home' button is pressed
    if (co.chkBreadcrumbsSave===undefined) co.chkBreadcrumbsSave=false;

    config.macros.breadcrumbs =  {
    	crumbs: [], // the list of current breadcrumbs
    	askMsg: "Save current breadcrumbs before clearing?\nPress OK to save, or CANCEL to continue without saving.",
    	saveMsg: 'Enter the name of a tiddler in which to save the current breadcrumbs',
    	saveTitle: 'SavedBreadcrumbs',
    	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    		var area=createTiddlyElement(place,"span",null,"breadCrumbs",null);
    		area.setAttribute("homeSep",params[0]?params[0]:this.homeSeparator); // custom home separator
    		area.setAttribute("crumbSep",params[1]?params[1]:this.crumbSeparator); // custom crumb separator
    		this.render(area);
    	},
    	add: function (title) {
    		var thisCrumb = title;
    		var ind = this.crumbs.indexOf(thisCrumb);
    		if(ind === -1)
    			this.crumbs.push(thisCrumb);
    		else if (config.options.chkReorderBreadcrumbs)
    			this.crumbs.push(this.crumbs.splice(ind,1)[0]); // reorder crumbs
    		else
    			this.crumbs=this.crumbs.slice(0,ind+1); // trim crumbs
    		if (config.options.chkBreadcrumbsLimitOpenTiddlers)
    			this.limitOpenTiddlers();
    		this.refresh();
    		return false;
    	},
    	getAreas: function() {
    		var crumbAreas=[];
    		// find all DIVs with classname=="breadCrumbs"
    		// Note: use try/catch to avoid "Bad NPObject as private data" fatal error  caused when
    		// some versions of embedded QuickTime player element is accessed by hasClass() function.
    		var all=document.getElementsByTagName("*");
    		for (var i=0; i<all.length; i++)
    			try{ if (hasClass(all[i],"breadCrumbs")) crumbAreas.push(all[i]); } catch(e) {;}
    		// find single DIV w/fixed ID (backward compatibility)
    		var byID=document.getElementById("breadCrumbs")
    		if (byID && !hasClass(byID,"breadCrumbs")) crumbAreas.push(byID);
    		if (!crumbAreas.length && config.options.chkCreateDefaultBreadcrumbs) {
    			// no existing crumbs display areas... create one...
    			var defaultArea = createTiddlyElement(null,"span",null,"breadCrumbs",null);
    		 	defaultArea.style.display= "none";
    			var targetArea= document.getElementById("tiddlerDisplay");
    		 	targetArea.parentNode.insertBefore(defaultArea,targetArea);
    			crumbAreas.push(defaultArea);
    		}
    		return crumbAreas;
    	},
    	refresh: function() {
    		var crumbAreas=this.getAreas();
    		for (var i=0; i<crumbAreas.length; i++) {
    			crumbAreas[i].style.display = config.options.chkShowBreadcrumbs?"block":"none";
    			removeChildren(crumbAreas[i]);
    			this.render(crumbAreas[i]);
    		}
    	},
    	render: function(here) {
    		var co=config.options; var out=""
    		var homeSep=here.getAttribute("homeSep"); if (!homeSep) homeSep=this.homeSeparator;
    		var crumbSep=here.getAttribute("crumbSep"); if (!crumbSep) crumbSep=this.crumbSeparator;
    		if (!co.chkBreadcrumbsHideHomeLink) {
    			createTiddlyButton(here,"Home",null,this.home,"tiddlyLink tiddlyLinkExisting");
    			out+=homeSep;
    		}
    		for (c=0; c<this.crumbs.length; c++) // remove non-existing tiddlers from crumbs
    			if (!store.tiddlerExists(this.crumbs[c]) && !store.isShadowTiddler(this.crumbs[c]))
    				this.crumbs.splice(c,1);
    		var count=this.crumbs.length;
    		if (co.chkBreadcrumbsLimit && co.txtBreadcrumbsLimit<count) count=co.txtBreadcrumbsLimit;
    		var list=[];
    		for (c=this.crumbs.length-count; c<this.crumbs.length; c++) list.push('[['+this.crumbs[c]+']]');
    		if (co.chkBreadcrumbsReverse) list.reverse();
    		out+=list.join(crumbSep);
    		wikify(out,here);
    	},
    	home: function() {
    		var cmb=config.macros.breadcrumbs;
    		if (config.options.chkBreadcrumbsSave && confirm(cmb.askMsg)) cmb.saveCrumbs();
    		story.closeAllTiddlers(); restart();
    		cmb.crumbs = []; var crumbAreas=cmb.getAreas();
    		for (var i=0; i<crumbAreas.length; i++) crumbAreas[i].style.display = "none";
    		return false;
    	},
    	saveCrumbs: function() {
    		var tid=prompt(this.saveMsg,this.saveTitle); if (!tid||!tid.length) return; // cancelled by user
    		var t=store.getTiddler(tid);
    		if(t && !confirm(config.messages.overwriteWarning.format([tid]))) return;
    		var who=config.options.txtUserName;
    		var when=new Date();
    		var text='[['+this.crumbs.join(']]\n[[')+']]';
    		var tags=t?t.tags:[]; tags.pushUnique('story');
    		var fields=t?t.fields:{};
    		store.saveTiddler(tid,tid,text,who,when,tags,fields);
    		story.displayTiddler(null,tid);
    		story.refreshTiddler(tid,null,true);
    		displayMessage(tid+' has been '+(t?'updated':'created'));
    	},
    	limitOpenTiddlers: function() {
    		var limit=config.options.txtBreadcrumbsLimitOpenTiddlers; if (limit<1) limit=1;
    		for (c=this.crumbs.length-1; c>=0; c--) {
    			var tid=this.crumbs[c];
    			var elem=document.getElementById(story.idPrefix+tid);
    			if (elem) { // tiddler is displayed
    				if (limit <=0) { // display limit has been reached
    					if (elem.getAttribute("dirty")=="true") { // tiddler is being edited
    						var msg="'"+tid+"' is currently being edited.\n\n";
    						msg+="Press OK to save and close this tiddler\nor press Cancel to leave it opened";
    						if (confirm(msg)) { story.saveTiddler(tid); story.closeTiddler(tid); }
    					}
    					else
    						story.closeTiddler(this.crumbs[c]);
    				}
    				limit--;
    			}
    		}
    	}
    };
    if (config.macros.breadcrumbs.homeSeparator==undefined) // note: not a cookie
    	config.macros.breadcrumbs.homeSeparator=" | ";
    if (config.macros.breadcrumbs.crumbSeparator==undefined)  // note: not a cookie
    	config.macros.breadcrumbs.crumbSeparator=" > ";

    config.commands.previousTiddler = {
    	text: 'back',
    	tooltip: 'view the previous tiddler',
    	hideReadOnly: false,
    	dateFormat: 'DDD, MMM DDth YYYY hh:0mm:0ss',
    	handler: function(event,src,title) {
    		var here=story.findContainingTiddler(src); if (!here) return;
    		var crumbs=config.macros.breadcrumbs.crumbs;
    		if (crumbs.length>1) {
    			var crumb=crumbs[crumbs.length-2];
    			story.displayTiddler(here,crumb);
    		}
    		else
    			config.macros.breadcrumbs.home();
    		return false;
    	}
    };

    config.macros.previousTiddler= {
    	label: 'back',
    	prompt: 'view the previous tiddler',
    	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    		var label=params.shift(); if (!label) label=this.label;
    		var prompt=params.shift(); if (!prompt) prompt=this.prompt;
    		createTiddlyButton(place,label,prompt,function() {
    			var crumbs=config.macros.breadcrumbs.crumbs;
    			if (crumbs.length>1) {
    				var crumb=crumbs[crumbs.length-2];
    				story.displayTiddler(place,crumb);
    			}
    			else
    				config.macros.breadcrumbs.home();
    		});
    	}
    }

    // hijack story.displayTiddler() so crumbs can be refreshed when a tiddler is displayed
    if (Story.prototype.breadCrumbs_coreDisplayTiddler==undefined)
    	Story.prototype.breadCrumbs_coreDisplayTiddler=Story.prototype.displayTiddler;
    Story.prototype.displayTiddler = function(srcElement,tiddler,template,animate,slowly)
    {
    	var title=(tiddler instanceof Tiddler)?tiddler.title:tiddler;
    	this.breadCrumbs_coreDisplayTiddler.apply(this,arguments);
    	// if not displaying tiddler during document startup, then add it to the breadcrumbs
    	// note: 'startingUp' flag is a global, set/reset by the core init() function
    	if (!startingUp || config.options.chkShowStartupBreadcrumbs) config.macros.breadcrumbs.add(title);
    }

    // hijack store.removeTiddler() so crumbs can be refreshed when a tiddler is deleted
    if (TiddlyWiki.prototype.breadCrumbs_coreRemoveTiddler==undefined)
    	TiddlyWiki.prototype.breadCrumbs_coreRemoveTiddler=TiddlyWiki.prototype.removeTiddler;
    TiddlyWiki.prototype.removeTiddler= function(title)
    {
    	this.breadCrumbs_coreRemoveTiddler.apply(this,arguments);
    	config.macros.breadcrumbs.refresh();
    }
    //}}}

    /***
    |Name|CalendarPlugin|
    |Source|http://www.TiddlyTools.com/#CalendarPlugin|
    |Version|1.5.0|
    |Author|Eric Shulman|
    |Original Author|SteveRumsby|
    |License|unknown|
    |~CoreVersion|2.1|
    |Type|plugin|
    |Requires||
    |Overrides||
    |Options|##Configuration|
    |Description|display monthly and yearly calendars|
    NOTE: For //enhanced// date popup display, optionally install [[DatePlugin]] and [[ReminderMacros]]
    !!!Usage:
    <<<
    |{{{<<calendar>>}}}|full-year calendar for the current year|
    |{{{<<calendar year>>}}}|full-year calendar for the specified year|
    |{{{<<calendar year month>>}}}|one month calendar for the specified month and year|
    |{{{<<calendar thismonth>>}}}|one month calendar for the current month|
    |{{{<<calendar lastmonth>>}}}|one month calendar for last month|
    |{{{<<calendar nextmonth>>}}}|one month calendar for next month|
    |{{{<<calendar +n>>}}}<br>{{{<<calendar -n>>}}}|one month calendar for a month +/- 'n' months from now|
    <<<
    !!!Configuration:
    <<<
    |''First day of week:''<br>{{{config.options.txtCalFirstDay}}}|<<option txtCalFirstDay>>|(Monday = 0, Sunday = 6)|
    |''First day of weekend:''<br>{{{config.options.txtCalStartOfWeekend}}}|<<option txtCalStartOfWeekend>>|(Monday = 0, Sunday = 6)|

    <<option chkDisplayWeekNumbers>> Display week numbers //(note: Monday will be used as the start of the week)//
    |''Week number display format:''<br>{{{config.options.txtWeekNumberDisplayFormat }}}|<<option txtWeekNumberDisplayFormat >>|
    |''Week number link format:''<br>{{{config.options.txtWeekNumberLinkFormat }}}|<<option txtWeekNumberLinkFormat >>|
    <<<
    !!!Revisions
    <<<
    2009.04.31 [1.5.0] rewrote onClickCalendarDate() (popup handler) and added config.options.txtCalendarReminderTags.  Partial code reduction/cleanup.  Assigned true version number (1.5.0)
    2008.09.10 added '+n' (and '-n') param to permit display of relative months (e.g., '+6' means 'six months from now', '-3' means 'three months ago'.  Based on suggestion from Jean.
    2008.06.17 added support for config.macros.calendar.todaybg
    2008.02.27 in handler(), DON'T set hard-coded default date format, so that *customized* value (pre-defined in config.macros.calendar.journalDateFmt is used.
    2008.02.17 in createCalendarYear(), fix next/previous year calculation (use parseInt() to convert to numeric value).  Also, use journalDateFmt for date linking when NOT using [[DatePlugin]].
    2008.02.16 in createCalendarDay(), week numbers now created as TiddlyLinks, allowing quick creation/navigation to 'weekly' journals (based on request from Kashgarinn)
    2008.01.08 in createCalendarMonthHeader(), 'month year' heading is now created as TiddlyLink, allowing quick creation/navigation to 'month-at-a-time' journals
    2007.11.30 added 'return false' to onclick handlers (prevent IE from opening blank pages)
    2006.08.23 added handling for weeknumbers (code supplied by Martin Budden (see 'wn**' comment marks).  Also, incorporated updated by Jeremy Sheeley to add caching for reminders (see [[ReminderMacros]], if installed)
    2005.10.30 in config.macros.calendar.handler(), use 'tbody' element for IE compatibility.  Also, fix year calculation for IE's getYear() function (which returns '2005' instead of '105'). Also, in createCalendarDays(), use showDate() function (see [[DatePlugin]], if installed) to render autostyled date with linked popup.  Updated calendar stylesheet definition: use .calendar class-specific selectors, add text centering and margin settings
    2006.05.29 added journalDateFmt handling
    <<<
    !!!Code
    ***/
    //{{{
    version.extensions.CalendarPlugin= { major: 1, minor: 5, revision: 0, date: new Date(2009,5,31)};
    //}}}
    //{{{
    if(config.options.txtCalFirstDay == undefined)
    	config.options.txtCalFirstDay = 0;
    if(config.options.txtCalStartOfWeekend == undefined)
    	config.options.txtCalStartOfWeekend = 5;
    if(config.options.chkDisplayWeekNumbers == undefined)
    	config.options.chkDisplayWeekNumbers = false;
    if(config.options.chkDisplayWeekNumbers)
    	config.options.txtCalFirstDay = 0;
    if(config.options.txtWeekNumberDisplayFormat == undefined)
    	config.options.txtWeekNumberDisplayFormat = 'w0WW';
    if(config.options.txtWeekNumberLinkFormat == undefined)
    	config.options.txtWeekNumberLinkFormat = 'YYYY-w0WW';
    if(config.options.txtCalendarReminderTags == undefined)
    	config.options.txtCalendarReminderTags = 'reminder';

    config.macros.calendar = {
    	monthnames:['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'],
    	daynames:['M','T','W','T','F','S','S'],
    	todaybg:'#ccccff',
    	weekendbg:'#c0c0c0',
    	monthbg:'#e0e0e0',
    	holidaybg:'#ffc0c0',
    	journalDateFmt:'DD MMM YYYY',
    	monthdays:[31,28,31,30,31,30,31,31,30,31,30,31],
    	holidays:[ ] // for customization see [[CalendarPluginConfig]]
    };
    //}}}
    //{{{
    function calendarIsHoliday(date)
    {
    	var longHoliday = date.formatString('0DD/0MM/YYYY');
    	var shortHoliday = date.formatString('0DD/0MM');
    	for(var i = 0; i < config.macros.calendar.holidays.length; i++) {
    		if(   config.macros.calendar.holidays[i]==longHoliday
    		   || config.macros.calendar.holidays[i]==shortHoliday)
    			return true;
    	}
    	return false;
    }
    //}}}
    //{{{
    config.macros.calendar.handler = function(place,macroName,params) {
    	var calendar = createTiddlyElement(place, 'table', null, 'calendar', null);
    	var tbody = createTiddlyElement(calendar, 'tbody');
    	var today = new Date();
    	var year = today.getYear();
    	if (year<1900) year+=1900;

     	// get journal format from SideBarOptions (ELS 5/29/06 - suggested by MartinBudden)
    	var text = store.getTiddlerText('SideBarOptions');
    	var re = new RegExp('<<(?:newJournal)([^>]*)>>','mg'); var fm = re.exec(text);
    	if (fm && fm[1]!=null) { var pa=fm[1].readMacroParams(); if (pa[0]) this.journalDateFmt = pa[0]; }

    	var month=-1;
    	if (params[0] == 'thismonth') {
    		var month=today.getMonth();
    	} else if (params[0] == 'lastmonth') {
    		var month = today.getMonth()-1; if (month==-1) { month=11; year--; }
    	} else if (params[0] == 'nextmonth') {
    		var month = today.getMonth()+1; if (month>11) { month=0; year++; }
    	} else if (params[0]&&'+-'.indexOf(params[0].substr(0,1))!=-1) {
    		var month = today.getMonth()+parseInt(params[0]);
    		if (month>11) { year+=Math.floor(month/12); month%=12; };
    		if (month<0)  { year+=Math.floor(month/12); month=12+month%12; }
    	} else if (params[0]) {
    		year = params[0];
    		if(params[1]) month=parseInt(params[1])-1;
    		if (month>11) month=11; if (month<0) month=0;
    	}

    	if (month!=-1) {
    		cacheReminders(new Date(year, month, 1, 0, 0), 31);
    		createCalendarOneMonth(tbody, year, month);
    	} else {
    		cacheReminders(new Date(year, 0, 1, 0, 0), 366);
    		createCalendarYear(tbody, year);
    	}
    	window.reminderCacheForCalendar = null;
    }
    //}}}
    //{{{
    // cache used to store reminders while the calendar is being rendered
    // it will be renulled after the calendar is fully rendered.
    window.reminderCacheForCalendar = null;
    //}}}
    //{{{
    function cacheReminders(date, leadtime)
    {
    	if (window.findTiddlersWithReminders == null) return;
    	window.reminderCacheForCalendar = {};
    	var leadtimeHash = [];
    	leadtimeHash [0] = 0;
    	leadtimeHash [1] = leadtime;
    	var t = findTiddlersWithReminders(date, leadtimeHash, null, 1);
    	for(var i = 0; i < t.length; i++) {
    		//just tag it in the cache, so that when we're drawing days, we can bold this one.
    		window.reminderCacheForCalendar[t[i]['matchedDate']] = 'reminder:' + t[i]['params']['title'];
    	}
    }
    //}}}
    //{{{
    function createCalendarOneMonth(calendar, year, mon)
    {
    	var row = createTiddlyElement(calendar, 'tr');
    	createCalendarMonthHeader(calendar, row, config.macros.calendar.monthnames[mon]+' '+year, true, year, mon);
    	row = createTiddlyElement(calendar, 'tr');
    	createCalendarDayHeader(row, 1);
    	createCalendarDayRowsSingle(calendar, year, mon);
    }
    //}}}
    //{{{
    function createCalendarMonth(calendar, year, mon)
    {
    	var row = createTiddlyElement(calendar, 'tr');
    	createCalendarMonthHeader(calendar, row, config.macros.calendar.monthnames[mon]+' '+ year, false, year, mon);
    	row = createTiddlyElement(calendar, 'tr');
    	createCalendarDayHeader(row, 1);
    	createCalendarDayRowsSingle(calendar, year, mon);
    }
    //}}}
    //{{{
    function createCalendarYear(calendar, year)
    {
    	var row;
    	row = createTiddlyElement(calendar, 'tr');
    	var back = createTiddlyElement(row, 'td');
    	var backHandler = function() {
    		removeChildren(calendar);
    		createCalendarYear(calendar, parseInt(year)-1);
    		return false; // consume click
    	};
    	createTiddlyButton(back, '<', 'Previous year', backHandler);
    	back.align = 'center';
    	var yearHeader = createTiddlyElement(row, 'td', null, 'calendarYear', year);
    	yearHeader.align = 'center';
    	yearHeader.setAttribute('colSpan',config.options.chkDisplayWeekNumbers?22:19);//wn**
    	var fwd = createTiddlyElement(row, 'td');
    	var fwdHandler = function() {
    		removeChildren(calendar);
    		createCalendarYear(calendar, parseInt(year)+1);
    		return false; // consume click
    	};
    	createTiddlyButton(fwd, '>', 'Next year', fwdHandler);
    	fwd.align = 'center';
    	createCalendarMonthRow(calendar, year, 0);
    	createCalendarMonthRow(calendar, year, 3);
    	createCalendarMonthRow(calendar, year, 6);
    	createCalendarMonthRow(calendar, year, 9);
    }
    //}}}
    //{{{
    function createCalendarMonthRow(cal, year, mon)
    {
    	var row = createTiddlyElement(cal, 'tr');
    	createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon], false, year, mon);
    	createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon+1], false, year, mon);
    	createCalendarMonthHeader(cal, row, config.macros.calendar.monthnames[mon+2], false, year, mon);
    	row = createTiddlyElement(cal, 'tr');
    	createCalendarDayHeader(row, 3);
    	createCalendarDayRows(cal, year, mon);
    }
    //}}}
    //{{{
    function createCalendarMonthHeader(cal, row, name, nav, year, mon)
    {
    	var month;
    	if (nav) {
    		var back = createTiddlyElement(row, 'td');
    		back.align = 'center';
    		back.style.background = config.macros.calendar.monthbg;

    		var backMonHandler = function() {
    			var newyear = year;
    			var newmon = mon-1;
    			if(newmon == -1) { newmon = 11; newyear = newyear-1;}
    			removeChildren(cal);
    			cacheReminders(new Date(newyear, newmon , 1, 0, 0), 31);
    			createCalendarOneMonth(cal, newyear, newmon);
    			return false; // consume click
    		};
    		createTiddlyButton(back, '<', 'Previous month', backMonHandler);
    		month = createTiddlyElement(row, 'td', null, 'calendarMonthname')
    		createTiddlyLink(month,name,true);
    		month.setAttribute('colSpan', config.options.chkDisplayWeekNumbers?6:5);//wn**
    		var fwd = createTiddlyElement(row, 'td');
    		fwd.align = 'center';
    		fwd.style.background = config.macros.calendar.monthbg;

    		var fwdMonHandler = function() {
    			var newyear = year;
    			var newmon = mon+1;
    			if(newmon == 12) { newmon = 0; newyear = newyear+1;}
    			removeChildren(cal);
    			cacheReminders(new Date(newyear, newmon , 1, 0, 0), 31);
    			createCalendarOneMonth(cal, newyear, newmon);
    			return false; // consume click
    		};
    		createTiddlyButton(fwd, '>', 'Next month', fwdMonHandler);
    	} else {
    		month = createTiddlyElement(row, 'td', null, 'calendarMonthname', name)
    		month.setAttribute('colSpan',config.options.chkDisplayWeekNumbers?8:7);//wn**
    	}
    	month.align = 'center';
    	month.style.background = config.macros.calendar.monthbg;
    }
    //}}}
    //{{{
    function createCalendarDayHeader(row, num)
    {
    	var cell;
    	for(var i = 0; i < num; i++) {
    		if (config.options.chkDisplayWeekNumbers) createTiddlyElement(row, 'td');//wn**
    		for(var j = 0; j < 7; j++) {
    			var d = j + (config.options.txtCalFirstDay - 0);
    			if(d > 6) d = d - 7;
    			cell = createTiddlyElement(row, 'td', null, null, config.macros.calendar.daynames[d]);
    			if(d == (config.options.txtCalStartOfWeekend-0) || d == (config.options.txtCalStartOfWeekend-0+1))
    				cell.style.background = config.macros.calendar.weekendbg;
    		}
    	}
    }
    //}}}
    //{{{
    function createCalendarDays(row, col, first, max, year, mon) {
    	var i;
    	if (config.options.chkDisplayWeekNumbers){
    		if (first<=max) {
    			var ww = new Date(year,mon,first);
    			var td=createTiddlyElement(row, 'td');//wn**
    			var link=createTiddlyLink(td,ww.formatString(config.options.txtWeekNumberLinkFormat),false);
    			link.appendChild(document.createTextNode(
    				ww.formatString(config.options.txtWeekNumberDisplayFormat)));
    		}
    		else createTiddlyElement(row, 'td');//wn**
    	}
    	for(i = 0; i < col; i++)
    		createTiddlyElement(row, 'td');
    	var day = first;
    	for(i = col; i < 7; i++) {
    		var d = i + (config.options.txtCalFirstDay - 0);
    		if(d > 6) d = d - 7;
    		var daycell = createTiddlyElement(row, 'td');
    		var isaWeekend=((d==(config.options.txtCalStartOfWeekend-0)
    			|| d==(config.options.txtCalStartOfWeekend-0+1))?true:false);
    		if(day > 0 && day <= max) {
    			var celldate = new Date(year, mon, day);
    			// ELS 10/30/05 - use <<date>> macro's showDate() function to create popup
    			// ELS 05/29/06 - use journalDateFmt
    			if (window.showDate) showDate(daycell,celldate,'popup','DD',
    				config.macros.calendar.journalDateFmt,true, isaWeekend);
    			else {
    				if(isaWeekend) daycell.style.background = config.macros.calendar.weekendbg;
    				var title = celldate.formatString(config.macros.calendar.journalDateFmt);
    				if(calendarIsHoliday(celldate))
    					daycell.style.background = config.macros.calendar.holidaybg;
    				var now=new Date();
    				if ((now-celldate>=0) && (now-celldate<86400000)) // is today?
    					daycell.style.background = config.macros.calendar.todaybg;
    				if(window.findTiddlersWithReminders == null) {
    					var link = createTiddlyLink(daycell, title, false);
    					link.appendChild(document.createTextNode(day));
    				} else
    					var button = createTiddlyButton(daycell, day, title, onClickCalendarDate);
    			}
    		}
    		day++;
    	}
    }
    //}}}
    //{{{
    // Create a pop-up containing:
    // * a link to a tiddler for this date
    // * a 'new tiddler' link to add a reminder for this date
    // * links to current reminders for this date
    // NOTE: this code is only used if [[ReminderMacros]] is installed AND [[DatePlugin]] is //not// installed.
    function onClickCalendarDate(ev) { ev=ev||window.event;
    	var d=new Date(this.getAttribute('title')); var date=d.formatString(config.macros.calendar.journalDateFmt);
    	var p=Popup.create(this);  if (!p) return;
    	createTiddlyLink(createTiddlyElement(p,'li'),date,true);
    	var rem='\\n\\<\\<reminder day:%0 month:%1 year:%2 title: \\>\\>';
    	rem=rem.format([d.getDate(),d.getMonth()+1,d.getYear()+1900]);
    	var cmd="<<newTiddler label:[[new reminder...]] prompt:[[add a new reminder to '%0']]"
    		+" title:[[%0]] text:{{store.getTiddlerText('%0','')+'%1'}} tag:%2>>";
    	wikify(cmd.format([date,rem,config.options.txtCalendarReminderTags]),p);
    	createTiddlyElement(p,'hr');
    	var t=findTiddlersWithReminders(d,[0,31],null,1);
    	for(var i=0; i<t.length; i++) {
    		var link=createTiddlyLink(createTiddlyElement(p,'li'), t[i].tiddler, false);
    		link.appendChild(document.createTextNode(t[i]['params']['title']));
    	}
    	Popup.show(); ev.cancelBubble=true; if (ev.stopPropagation) ev.stopPropagation(); return false;
    }
    //}}}
    //{{{
    function calendarMaxDays(year, mon)
    {
    	var max = config.macros.calendar.monthdays[mon];
    	if(mon == 1 && (year % 4) == 0 && ((year % 100) != 0 || (year % 400) == 0)) max++;
    	return max;
    }
    //}}}
    //{{{
    function createCalendarDayRows(cal, year, mon)
    {
    	var row = createTiddlyElement(cal, 'tr');
    	var first1 = (new Date(year, mon, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
    	if(first1 < 0) first1 = first1 + 7;
    	var day1 = -first1 + 1;
    	var first2 = (new Date(year, mon+1, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
    	if(first2 < 0) first2 = first2 + 7;
    	var day2 = -first2 + 1;
    	var first3 = (new Date(year, mon+2, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
    	if(first3 < 0) first3 = first3 + 7;
    	var day3 = -first3 + 1;

    	var max1 = calendarMaxDays(year, mon);
    	var max2 = calendarMaxDays(year, mon+1);
    	var max3 = calendarMaxDays(year, mon+2);

    	while(day1 <= max1 || day2 <= max2 || day3 <= max3) {
    		row = createTiddlyElement(cal, 'tr');
    		createCalendarDays(row, 0, day1, max1, year, mon); day1 += 7;
    		createCalendarDays(row, 0, day2, max2, year, mon+1); day2 += 7;
    		createCalendarDays(row, 0, day3, max3, year, mon+2); day3 += 7;
    	}
    }
    //}}}
    //{{{
    function createCalendarDayRowsSingle(cal, year, mon)
    {
    	var row = createTiddlyElement(cal, 'tr');
    	var first1 = (new Date(year, mon, 1)).getDay() -1 - (config.options.txtCalFirstDay-0);
    	if(first1 < 0) first1 = first1+ 7;
    	var day1 = -first1 + 1;
    	var max1 = calendarMaxDays(year, mon);
    	while(day1 <= max1) {
    		row = createTiddlyElement(cal, 'tr');
    		createCalendarDays(row, 0, day1, max1, year, mon); day1 += 7;
    	}
    }
    //}}}
    //{{{
    setStylesheet('.calendar, .calendar table, .calendar th, .calendar tr, .calendar td { text-align:center; } .calendar, .calendar a { margin:0px !important; padding:0px !important; }', 'calendarStyles');
    //}}}

    // // override cookie settings for CalendarPlugin:
    //{{{
    config.options.txtCalFirstDay=6;
    config.options.txtCalStartOfWeekend=5;
    //}}}

    // // override internal default settings for CalendarPlugin:
    //{{{
    config.macros.calendar.journalDateFmt="DDD MMM 0DD YYYY";
    //}}}

    /***
    |Name|ClickifyPlugin|
    |Source|http://www.TiddlyTools.com/#ClickifyPlugin|
    |Documentation|http://www.TiddlyTools.com/#ClickifyPlugin|
    |Version|1.0.1|
    |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|re-compute parameters when a 'command link' macro is clicked|
    !!!!!Usage
    <<<
    Normally, when you use a //computed parameter// in a macro, it's value is determined when the macro is rendered.  The {{{<<clickify>>}}} macro can be used to force the macro parameters of an 'on-click' command link (such as created by the {{{<<newTiddler>>}}} macro) to be automatically re-computed when the command link is clicked, rather than when it is initially displayed.  This allows use of computed values that depend upon data that may change between the time the macro is rendered and when it's action is actually triggered by a click.

    To apply this extended processing to any macro that creates a command link, simply insert the 'clickify' keyword in front of the usual macro name, like this:
    {{{
    <<clickify macroName param param param ...>>
    }}}
    <<<
    !!!!!Example
    <<<
    When {{{<<newTiddler>>}}} is clicked, prompt for a title and set default text to current timestamp:
    {{{
    <<clickify newTiddler title:{{prompt('enter a title','NewTiddler')}} text:{{new Date()}}>>
    }}}
    ><<clickify newTiddler title:{{prompt('enter a title','NewTiddler')}} text:{{new Date()}}>>
    <<<
    !!!!!Revisions
    <<<
    2009.02.08 [1.0.1] make sure command link has been rendered before trying to modify it
    2009.01.25 [1.0.0] initial release
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.ClickifyPlugin={major: 1, minor: 0, revision: 1, date: new Date(2009,2,8)};
    config.macros.clickify={
    	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    		var cmd='<<'+paramString+'>>';
    		var e=createTiddlyElement(place,'span');
    		wikify(cmd.replace(/alert\(|prompt\(|confirm\(/g,'isNaN('),e);
    		var b=e.getElementsByTagName('a')[0]; if (!b) return;
    		b.setAttribute('cmd',cmd);
    		b.onclick=function(ev) {
    			var cmd=this.getAttribute('cmd');
    			var e=createTiddlyElement(this.parentNode,'span');
    			e.style.display='none';
    			wikify(cmd,e);
    			e.getElementsByTagName('a')[0].onclick();
    			this.parentNode.removeChild(e);
    		}
    	}
    }
    //}}}

    /***
    |Name|CollapseTiddlersPlugin|
    |Source|http://gensoft.revhost.net/Collapse.html|
    |Version|2008.10.05|
    |Author|Bradley Meck (modified by ELS)|
    |License|unknown|
    |~CoreVersion|2.1|
    |Type|plugin|
    |Requires|CollapsedTemplate|
    |Overrides||
    |Description|show/hide content of a tiddler while leaving tiddler title visible|

    |ELS 10/5/2008: collapseAll() and expandAll(): added "return false" to button handlers to prevent IE page transition |
    |ELS 3/6/2008: refactored code for size reduction, readability, and I18N/L10N-readiness.  Also added 'folded' flag to tiddler elements (for use by other plugins that need to know if tiddler is folded (e.g., [[SinglePageModePlugin]]) |
    |ELS 10/11/2007: moved [[FoldFirst]] inline script and converted to {{{<<foldFirst>>}}} macro. |
    |ELS 9/12/2007: suspend/resume SinglePageMode (SPM/TPM/BPM) when folding/unfolding tiddlers |
    |ELS 6/5/2007: add "return false" at the end of each command handler to prevent IE 'page transition' problem. |
    |ELS 3/30/2007: add a shadow definition for CollapsedTemplate.  Tweak ViewTemplate shadow so "fold/unfold" and "focus" toolbar items automatically appear when using default templates.  Remove error check for "CollapsedTemplate" existence, since shadow version will now always work as a fallback. |
    |ELS 2/24/2006: added fallback to "CollapsedTemplate" if "WebCollapsedTemplate" is not found |
    |ELS 2/6/2006: added check for 'readOnly' flag to use alternative "WebCollapsedTemplate" |

    ***/

    //{{{
    config.shadowTiddlers.CollapsedTemplate=
    	"<!--{{{-->\
    	<div class='toolbar' macro='toolbar expandTiddler collapseOthers closeTiddler closeOthers +editTiddler permalink references jump'></div>\
    	<div class='title' macro='view title'></div>\
    	<!--}}}-->";

    // automatically tweak shadow ViewTemplate to add "collapseTiddler collapseOthers" commands
    config.shadowTiddlers.ViewTemplate=config.shadowTiddlers.ViewTemplate.replace(/closeTiddler/,"collapseTiddler collapseOthers closeTiddler");

    config.commands.collapseTiddler = {
    	text: "收起",
    	tooltip: "收起当前文章",
    	collapsedTemplate: "CollapsedTemplate",
    	webCollapsedTemplate: "WebCollapsedTemplate",
    	handler: function(event,src,title) {
    		var e = story.findContainingTiddler(src); if (!e) return false;
    		// don't fold tiddlers that are being edited!
    		if(story.isDirty(e.getAttribute("tiddler"))) return false;
    		var t=config.commands.collapseTiddler.getCollapsedTemplate();
    		config.commands.collapseTiddler.saveTemplate(e);
    		config.commands.collapseTiddler.display(title,t);
    		e.setAttribute("folded","true");
    		return false;
    	},
    	getCollapsedTemplate: function() {
    		if (readOnly&&store.tiddlerExists(this.webCollapsedTemplate))
    			return this.webCollapsedTemplate;
    		else
    			return this.collapsedTemplate
    	},
    	saveTemplate: function(e) {
    		if (e.getAttribute("savedTemplate")==undefined)
    			e.setAttribute("savedTemplate",e.getAttribute("template"));

    	},
    	// fold/unfold tiddler with suspend/resume of single/top/bottom-of-page mode
    	display: function(title,t) {
    		var opt=config.options;
    		var saveSPM=opt.chkSinglePageMode; opt.chkSinglePageMode=false;
    		var saveTPM=opt.chkTopOfPageMode; opt.chkTopOfPageMode=false;
    		var saveBPM=opt.chkBottomOfPageMode; opt.chkBottomOfPageMode=false;
    		story.displayTiddler(null,title,t);
    		opt.chkBottomOfPageMode=saveBPM;
    		opt.chkTopOfPageMode=saveTPM;
    		opt.chkSinglePageMode=saveSPM;
    	}
    }

    config.commands.expandTiddler = {
    	text: "展开",
    	tooltip: "展开当前文章",
    	handler: function(event,src,title) {
    		var e = story.findContainingTiddler(src); if (!e) return false;
    		var t = e.getAttribute("savedTemplate");
    		config.commands.collapseTiddler.display(title,t);
    		e.setAttribute("folded","false");
    		return false;
    	}
    }

    config.macros.collapseAll = {
    	text: "collapse all",
    	tooltip: "Collapse all tiddlers",
    	handler: function(place,macroName,params,wikifier,paramString,tiddler){
    		createTiddlyButton(place,this.text,this.tooltip,function(){
    			story.forEachTiddler(function(title,tiddler){
    				if(story.isDirty(title)) return;
    				var t=config.commands.collapseTiddler.getCollapsedTemplate();

    				config.commands.collapseTiddler.saveTemplate(tiddler);
    				config.commands.collapseTiddler.display(title,t);
    				tiddler.folded=true;
    			});
    			return false;
    		})
    	}
    }

    config.macros.expandAll = {
    	text: "expand all",
    	tooltip: "Expand all tiddlers",
    	handler: function(place,macroName,params,wikifier,paramString,tiddler){
    		createTiddlyButton(place,this.text,this.tooltip,function(){
    			story.forEachTiddler(function(title,tiddler){
    				var t=config.commands.collapseTiddler.getCollapsedTemplate();
    				if(tiddler.getAttribute("template")!=t) return; // re-display only if collapsed
    				var t=tiddler.getAttribute("savedTemplate");
    				config.commands.collapseTiddler.display(title,t);
    				tiddler.folded=false;
    			});
    			return false;
    		})
    	}
    }

    config.commands.collapseOthers = {
    	text: "焦点",
    	tooltip: "展开当前文章,同时收起其他文章",
    	handler: function(event,src,title) {
    		var e = story.findContainingTiddler(src); if (!e) return false;
    		story.forEachTiddler(function(title,tiddler) {
    			if(story.isDirty(title)) return;
    			var t=config.commands.collapseTiddler.getCollapsedTemplate();
    			if (e==tiddler) t=e.getAttribute("savedTemplate");
    			config.commands.collapseTiddler.saveTemplate(tiddler);
    			config.commands.collapseTiddler.display(title,t);
    			tiddler.folded=(e!=tiddler);
    		})
    		return false;
    	}
    }

    // {{{<<foldFirst>>}}} macro forces tiddler to be folded when *initially* displayed.
    // Subsequent re-render does NOT re-fold tiddler, but closing/re-opening tiddler DOES cause it to fold first again.
    config.macros.foldFirst = {
    	handler: function(place,macroName,params,wikifier,paramString,tiddler){
    		var e=story.findContainingTiddler(place);
    		if (e.getAttribute("foldedFirst")=="true") return; // already been folded once
    		var title=e.getAttribute("tiddler")
    		var t=config.commands.collapseTiddler.getCollapsedTemplate();
    		config.commands.collapseTiddler.saveTemplate(e);
    		config.commands.collapseTiddler.display(title,t);
    		e.setAttribute("folded","true");
    		e.setAttribute("foldedFirst","true"); // only when tiddler is first rendered
    		return false;
    	}
    }
    //}}}

    <!--{{{-->
    <div class='toolbar' macro='toolbar [[ToolbarCommands::CollapsedToolbar]]'></div>
    <div class='title' macro='view title'></div>
    <!--}}}-->

    /***
    |Name|CommentPlugin|
    |Source|http://www.TiddlyTools.com/#CommentPlugin|
    |Documentation|http://www.TiddlyTools.com/#CommentPluginInfo|
    |Version|2.9.3|
    |Author|Eric Shulman|
    |License|http://www.TiddlyTools.com/#LegalStatements|
    |~CoreVersion|2.1|
    |Type|plugin|
    |Requires||
    |Overrides||
    |Description|automatically insert formatted comments into tiddler content|
    !!!!!Documentation
    >see [[CommentPluginInfo]]
    !!!!!Configuration
    >see [[CommentPluginInfo]]
    !!!!!Revisions
    <<<
    2009.04.10 [2.9.3] invoke autoSaveChanges() after adding a comment
    | please see [[CommentPluginInfo]] for previous revision details |
    2006.04.20 [1.0.0] initial release
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.CommentPlugin= {major: 2, minor: 9, revision: 3, date: new Date(2009,4,10)};

    config.macros.comment= {
    	marker: '/%'+'comment'+'%/',
    	fmt: "__''%subject%''__\n^^posted by %who% on %when%^^\n<<<\n%message%\n<<<\n",
    	datefmt: 'DDD, MMM DDth, YYYY at hh12:0mm:0ss am',
    	tags: '',
    	reverse: false,
    	handler: function(place,macroName,params,wikifier,paramstring,tiddler) {
    		var span=createTiddlyElement(place,'span');
    		var here=story.findContainingTiddler(place);
    		if (here) var tid=here.getAttribute('tiddler');  // containing tiddler title
    		span.setAttribute('here',tid);
    		var target=(params[0]&&params[0].length&&params[0]!='here')?params[0]:tid;  // target title
    		span.setAttribute('target',target);
    		var overwrite=(params[1]&&params[1].toLowerCase()=='overwrite'); if (overwrite) params.shift();
    		span.setAttribute('overwrite',overwrite?'true':'false');
    		var reverse=(params[1]&&params[1].toLowerCase()=='reverse'); if (reverse) params.shift();
    		span.setAttribute('reverse',(reverse||this.reverse)?'true':'false');
    		var marker=this.marker;
    		if (params[1]&&params[1].substr(0,7)=='marker:') {
    			var marker='/%'+params[1].substr(7)+'%/';
    			params.shift();
    		}
    		span.setAttribute('marker',marker);
    		var tags=(params[1]&&params[1].length)?params[1]:this.tags; // target tags
    		span.setAttribute('tags',tags);
    		var fmt=(params[2]&&params[2].length)?params[2]:this.fmt; // output format
    		span.setAttribute('fmt',fmt.unescapeLineBreaks());
    		var datefmt=(params[3]&&params[3].length)?params[3]:this.datefmt; // date format
    		span.setAttribute('datefmt',datefmt.unescapeLineBreaks());
    		var html=this.html;
    		html=html.replace(/%nosubject%/g,(fmt.indexOf('%subject%')==-1)?'none':'block');
    		html=html.replace(/%nomessage%/g,(fmt.indexOf('%message%')==-1)?'none':'block');
    		var subjtxt=''; var msgtxt='';
    		html=html.replace(/%subjtxt%/g,subjtxt);
    		html=html.replace(/%msgtxt%/g,msgtxt);
    		span.innerHTML=html;
    	},
    	html: "<form style='display:inline;margin:0;padding:0;'>\
    		<div style='display:%nosubject%'>\
    		subject:<br>\
    		<input type='text' name='subject' title='enter subject text' style='width:100%' value='%subjtxt%'>\
    		</div>\
    		<div style='display:%nomessage%'>\
    		message:<br>\
    		<textarea name='message' rows='7' title='enter message text' \
    			style='width:100%'>%msgtxt%</textarea>\
    		</div>\
    		<center>\
    		<i>Please enter your information and then press</i>\
    		<input type='button' value='post' onclick='\
    			var s=this.form.subject; var m=this.form.message;\
    			if (\"%nosubject%\"!=\"none\" && !s.value.length)\
    				{ alert(\"Please enter a subject\"); s.focus(); return false; }\
    			if (\"%nomessage%\"!=\"none\" && !m.value.length)\
    				{ alert(\"Please enter a message\"); m.focus(); return false; }\
    			var here=this.form.parentNode.getAttribute(\"here\");\
    			var reverse=this.form.parentNode.getAttribute(\"reverse\")==\"true\";\
    			var target=this.form.parentNode.getAttribute(\"target\");\
    			var marker=this.form.parentNode.getAttribute(\"marker\");\
    			var tags=this.form.parentNode.getAttribute(\"tags\").readBracketedList();\
    			var fmt=this.form.parentNode.getAttribute(\"fmt\");\
    			var datefmt=this.form.parentNode.getAttribute(\"datefmt\");\
    			var overwrite=this.form.parentNode.getAttribute(\"overwrite\")==\"true\";\
    			config.macros.comment.addComment(here,reverse,target,tags,fmt,datefmt,\
    				s.value,m.value,overwrite,marker);'>\
    		</center>\
    		</form>",
    	addComment: function(here,reverse,target,newtags,fmt,datefmt,subject,message,overwrite,marker) {
    		var UTC=new Date().convertToYYYYMMDDHHMMSSMMM();
    		var rand=Math.random().toString();
    		var who=config.options.txtUserName;
    		var when=new Date().formatString(datefmt);
    		target=target.replace(/%tiddler%/g,here);
    		target=target.replace(/%UTC%/g,UTC);
    		target=target.replace(/%random%/g,rand);
    		target=target.replace(/%who%/g,who);
    		target=target.replace(/%when%/g,when);
    		target=target.replace(/%subject%/g,subject);
    		var t=store.getTiddler(target);
    		var text=t?t.text:'';
    		var modifier=t?t.modifier:config.options.txtUserName;
    		var modified=t?t.modified:new Date();
    		var tags=t?t.tags:[];
    		for(var i=0; i<newtags.length; i++) tags.pushUnique(newtags[i]);
    		var fields=t?t.fields:{};
    		var out=fmt;
    		out=out.replace(/%tiddler%/g,here);
    		out=out.replace(/%UTC%/g,UTC);
    		out=out.replace(/%when%/g,when);
    		out=out.replace(/%who%/g,who);
    		out=out.replace(/%subject%/g,subject);
    		out=out.replace(/%message%/g,message);
    		var pos=text.indexOf(marker);
    		if (pos==-1) pos=text.length; // no marker - insert at end
    		else if (reverse) pos+=marker.length; // reverse order by inserting AFTER marker
    		var newtxt=overwrite?out:(text.substr(0,pos)+out+text.substr(pos));
    		store.saveTiddler(target,target,newtxt,modifier,modified,tags,fields);
    		autoSaveChanges();
    		if (document.getElementById(story.idPrefix+target))
    			story.refreshTiddler(target,DEFAULT_VIEW_TEMPLATE,true);
    		if (here!=target && document.getElementById(story.idPrefix+here))
    			story.refreshTiddler(here,DEFAULT_VIEW_TEMPLATE,true);
    	}
    };
    //}}}

    Enter contact information (email, web address, etc.)

    /***
    <<tiddler CookieManager>>
    ***/
    /***
    !!![[Baked cookies:|CookieManagerPlugin]]
    ^^Press {{smallform{<<cookieManager button>>}}} to save the current browser cookies... then hand-edit this section to customize the results.^^
    ***/

    // 0 cookies saved on 周三, 十一月 24th 2010 at 00:10:41 by Lance//
    //^^(edit/remove username check and/or individual option settings as desired)^^//
    //{{{
    if (config.options.txtUserName=="Lance") {
    }
    //}}}

    /***
    |Name|CookieManagerPlugin|
    |Source|http://www.TiddlyTools.com/#CookieManagerPlugin|
    |Version|2.4.0|
    |Author|Eric Shulman|
    |License|http://www.TiddlyTools.com/#LegalStatements|
    |~CoreVersion|2.1|
    |Type|plugin|
    |Requires||
    |Overrides||
    |Options|##Configuration|
    |Description|view/add/delete browser-based cookies and "bake" cookies to CookieJar tiddler for 'sticky' settings|
    !!!!!Usage
    <<<
    This plugin provides an interactive control panel that lets you select, view, modify, or delete any of the current values for TiddlyWiki options that have been stored as local, private, //browser cookies//.  You can also use the control panel to "bake cookies", which generates a set of javascript statements that assign hard-coded option values to the TiddlyWiki internal variables that correspond to the current browser cookie settings.  These hard-coded values are then stored in the [[CookieJar]] tiddler, which is tagged with<<tag systemConfig>> so that each time the document is loaded, the baked cookie settings will be automatically applied.

    When a set of baked cookies is added to the [[CookieJar]], it is automatically surrounded by a conditional test so that the hard-coded settings will only be applied for the username that was in effect when they were initially generated.  In this way, if you publish or share your document with others, //your// particular baked cookie settings are not automatically applied to others, so that their own browser-based cookie settings (if defined) will be applied as usual.

    Whenever you "bake cookies", new hard-coded javascript assignment statements are *appended* to the end of the [[CookieJar]].  However, any baked cookies that were previously generated and stored in the [[CookieJar]] are not automatically removed from the tiddler.  As a result, because the most recently baked cookie settings in the [[CookieJar]] are always the last to be processed, the values assigned by older baked cookies are immediately overridden by the values from the newest baked cookies, so that the newest values will be in effect when the CookieJar startup processing is completed.

    Each time you bake a new batch of cookies, it is recommended that you should review and hand-edit the [[CookieJar]] to remove any "stale cookies" or merge the old and new sets of baked cookies into a single block to simplify readability (as well as saving a little tiddler storage space).  Of course, you can also hand-edit the [[CookieJar]] tiddler at any time simply to remove a few individual //baked cookies// if they are no longer needed, and you can even delete the entire [[CookieJar]] tiddler and start fresh, if that is appropriate.  Please note that changing or deleting a baked cookie does not alter the current value of the corresponding option setting, and any changes you make to the [[CookieJar]] will only be applied after you have saved and reloaded the document in your browser.
    <<<
    !!!!!Examples
    <<<
    {{{<<cookieManager>>}}}
    {{smallform small center{
    @@display:block;width:35em;<<cookieManager>>@@}}}
    <<<
    !!!!!Configuration
    <<<
    <<option chkAllowBrowserCookies>> store ~TiddlyWiki option settings using private browser cookies
    <<option chkMonitorBrowserCookies>> monitor browser cookie activity (show a message whenever a cookie is set or deleted)
    <<option chkCookieManagerAddToAdvancedOptions>> display [[CookieManager]] in [[AdvancedOptions]]
    //note: this setting does not take effect until you reload the document//
    <<<
    !!!!!Revisions
    <<<
    2009.08.05 [2.4.0] changed CookieJar output format to support odd symbols in option names (e.g. '@')
    2008.09.14 [2.3.2] fixed handling for blocked cookies (was still allowing some blocked cookies to be set)
    2008.09.12 [2.3.1] added blocked[] array and allowBrowserCookie() test function for selective blocking of changes to browser cookies based on cookie name
    2008.09.08 [2.3.0] extensive code cleanup: defined removeCookie(), renamed cookies, added 'button' param for stand-alone "bake cookies" button, improved init of shadow [[CookieManager]] and [[CookieJar]] tiddlers for compatibility with new [[CookieSaverPlugin]].
    2008.07.11 [2.2.1] fixed recursion error in hijack for saveOptionCookie()
    2008.06.26 [2.2.0] added chkCookieManagerNoNewCookies option
    2008.06.05 [2.1.3] replaced hard-coded definition for "CookieJar" title with option variable
    2008.05.12 [2.1.2] add "cookies" task to backstage (moved from BackstageTasks)
    2008.04.09 [2.1.0] added options: chkCookieManagerAddToAdvancedOptions
    2008.04.08 [2.0.1] automatically include CookieManager control panel in AdvancedOptions shadow tiddler
    2007.08.02 [2.0.0] converted from inline script
    2007.04.29 [1.0.0] initial release
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.CookieManagerPlugin= {major: 2, minor: 3, revision: 1, date: new Date(2008,9,12)};
    //}}}
    //{{{
    config.macros.cookieManager = {
    	target:
    		config.options.txtCookieJar||"CookieJar",
    	blockedCookies:
    		[],
    	allowBrowserCookie: function(name) {
    		return true;
    	},
    	displayStatus: function(msg) {
    		if (config.options.chkMonitorBrowserCookies && !startingUp)
    			displayMessage("CookieManager: "+msg);
    	},
    	init: function() {
    		if (config.options.txtCookieJar===undefined)
    			config.options.txtCookieJar=this.target;
    		if (config.options.chkAllowBrowserCookies===undefined)
    			config.options.chkAllowBrowserCookies=true;
    		if (config.options.chkMonitorBrowserCookies===undefined)
    			config.options.chkMonitorBrowserCookies=false;

    		config.shadowTiddlers.CookieManager=
    			 "/***\n"
    			+"!!![[Browser cookies:|CookieManagerPlugin]] "
    			+"{{fine{<<option chkAllowBrowserCookies>>enable <<option chkMonitorBrowserCookies>>monitor}}}\n"
    			+"^^Review, modify, or delete browser cookies..."
    			+"To block specific cookies, see [[CookieManagerPluginConfig]].^^\n"
    			+"@@display:block;width:30em;{{smallform small{\n<<cookieManager>>}}}@@\n"
    			+"***/\n";

    		// add CookieManager to shadow CookieJar
    		var h="/***\n<<tiddler CookieManager>>\n***/\n";
    		var t=(config.shadowTiddlers[this.target]||"").replace(new RegExp(h.replace(/\*/g,'\\*'),''),'')
    		config.shadowTiddlers[this.target]=h+t;

    		if (config.options.chkCookieManagerAddToAdvancedOptions===undefined)
    			config.options.chkCookieManagerAddToAdvancedOptions=true;
    		if (config.options.chkCookieManagerAddToAdvancedOptions)
    			config.shadowTiddlers.AdvancedOptions+="\n!!CookieManager\n><<tiddler CookieManager>>";

    		// add "cookies" backstage task
    		if (config.tasks && !config.tasks.cookies) { // for TW2.2b3 or above
    			config.tasks.cookies = {
    				text: "cookies",
    				tooltip: "manage cookie-based option settings",
    				content: "{{groupbox{<<tiddler CookieManager>><<tiddler [["+this.target+"]]>>}}}"
    			}
    			config.backstageTasks.push("cookies");
    		}
    	},
    	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    		var span=createTiddlyElement(place,"span");
    		span.innerHTML=(params[0]&&params[0].toLowerCase()=="button")?this.button:this.panel;
    		this.setList(span.firstChild.list);
    	},
    	panel: '<form style="display:inline;margin:0;padding:0" onsubmit="return false"><!--\
    		--><select style="width:99%" name="list" \
    			onchange="this.form.val.value=this.value.length?config.options[this.value]:\'\';"><!--\
    		--></select><br>\
    		<input type="text" style="width:98%;margin:0;" name="val" title="enter an option value"><br>\
    		<input type="button" style="width:33%;margin:0;" value="get" title="refresh list" \
    			onclick="config.macros.cookieManager.setList(this.form.list);"><!--\
    		--><input type="button" style="width:33%;margin:0;" value="set" title="save cookie value" \
    			onclick="var cmc=config.macros.cookieManager;\
    				var opt=this.form.list.value; var v=this.form.val.value; \
    				var msg=opt+\' is a blocked cookie.  OK to proceed?\';\
    				if ((!cmc.blockedCookies.contains(opt) && cmc.allowBrowserCookie(opt))||confirm(msg)) {\
    					config.options[opt]=opt.substr(0,3)==\'txt\'?v:(v.toLowerCase()==\'true\'); \
    					saveOptionCookie(opt);config.macros.cookieManager.setList(this.form.list);\
    				}"><!--\
    		--><input type="button" style="width:33%;margin:0;" value="del" title="remove cookie" \
    			onclick="var cmc=config.macros.cookieManager; var opt=this.form.list.value; \
    				var msg=opt+\' is a blocked cookie.  OK to proceed?\';\
    				if ((!cmc.blockedCookies.contains(opt) && cmc.allowBrowserCookie(opt))||confirm(msg)) {\
    					removeCookie(this.form.list.value,true); \
    					cmc.setList(this.form.list);\
    				}"><br>\
    		<input type="button" style="width:50%;margin:0;" value="bake cookies" \
    			title="save current cookie-based option values into a tiddler" \
    			onclick="return config.macros.cookieManager.bake(this,false)"><!--\
    		--><input type="button" style="width:50%;margin:0;" value="bake all options" \
    			title="save ALL option values (including NON-COOKIE values) into a tiddler" \
    			onclick="return config.macros.cookieManager.bake(this,true)"><!--\
    		--></form>\
    	',
    	button: '<form style="display:inline;margin:0;padding:0" onsubmit="return false"><!--\
    		--><input type="button" style="margin:0;" value="bake cookies" \
    			title="save current browser-based cookie values into a tiddler" \
    			onclick="return config.macros.cookieManager.bake(this,false)"><!--\
    		--></form>\
    	',
    	getCookieList: function() {
    		var cookies = { };
    		if (document.cookie != "") {
    			var p = document.cookie.split("; ");
    			for (var i=0; i < p.length; i++) {
    				var pos=p[i].indexOf("=");
    				if (pos==-1) cookies[p[i]]="";
    				else cookies[p[i].substr(0,pos)]=unescape(p[i].slice(pos+1));
    			}
    		}
    		var opt=new Array(); for (var i in config.options) if (cookies[i]) opt.push(i); opt.sort();
    		return opt;
    	},
    	setList: function(list) {
    		if (!list) return false;
    		var opt=this.getCookieList();
    		var sel=list.selectedIndex;
    		while (list.options.length > 1) { list.options[1]=null; } // clear list (except for header item)
    		list.options[0]=new Option("There are "+opt.length+" cookies...","",false,false);
    		if (!opt.length) { list.form.val.value=""; return; } // no cookies
    		var c=1;
    		for(var i=0; i<opt.length; i++) {
    			var txt="";
    			if  (opt[i].substr(0,3)=="chk")
    				txt+="["+(config.options[opt[i]]?"\u221A":"_")+"] ";
    			txt+=opt[i];
    			list.options[c++]=new Option(txt,opt[i],false,false);
    		}
    		list.selectedIndex=sel>0?sel:0;
    		list.form.val.value=sel>0?config.options[list.options[sel].value]:"";
    	},
    	header:
    		"/***\n"
    		+"!!![[Baked cookies:|CookieManagerPlugin]]\n"
    		+"^^Press {{smallform{<<cookieManager button>>}}} to save the current browser cookies... "
    		+"then hand-edit this section to customize the results.^^\n"
    		+"***/\n",
    	format: function(name) {
    		if (name.substr(0,3)=='chk')
    			return '\tconfig.options["'+name+'"]='+(config.options[name]?'true;':'false;');
    		return '\tconfig.options["'+name+'"]="'+config.options[name]+'";';
    	},
    	bake: function(here,all) {
    		if (story.isDirty(this.target)) return false; // target is being hand-edited... do nothing
    		var text=store.getTiddlerText(this.target);
    		if (text.indexOf(this.header)==-1) {
    			text+=this.header;
    			displayMessage("CookieManager: added 'Baked Cookies' section to CookieJar");
    		}
    		var who=config.options.txtUserName;
    		var when=new Date();
    		var tags=['systemConfig'];
    		var tid=store.getTiddler(this.target)||store.saveTiddler(this.target,this.target,text,who,when,tags,{});
    		if (!tid) return false; // if no target... do nothing
    		if (all) {
    			var opts=new Array();
    			for (var i in config.options) if (i.substr(0,3)=='chk'||i.substr(0,3)=='txt') opts.push(i);
    			opts.sort();
    		}
    		else var opts=this.getCookieList();
    		var t=tid.text;
    		if (t.indexOf(this.header)==-1) t+=this.header;
    		t+='\n// '+opts.length+(all?' options':' cookies')+' saved ';
    		t+=when.formatString('on DDD, MMM DDth YYYY at 0hh:0mm:0ss');
    		t+=' by '+who+'//\n';
    		t+='//^^(edit/remove username check and/or individual option settings as desired)^^//\n';
    		t+='//{{{\n';
    		t+='if (config.options.txtUserName=="'+who+'") {\n';
    		for (i=0; i<opts.length; i++) t+=config.macros.cookieManager.format(opts[i])+"\n";
    		t+='}\n//}}}\n';
    		store.saveTiddler(this.target,this.target,t,who,when,tags,tid?tid.fields:{});
    		story.displayTiddler(story.findContainingTiddler(this),this.target);
    		story.refreshTiddler(this.target,null,true);
    		var msg=opts.length+(all?' options':' cookies')+' have been saved in '+this.target+'.  ';
    		msg+='Please review all stored settings.';
    		displayMessage(msg);
    		return false;
    	}
    }
    //}}}
    //{{{
    // Hijack saveOptionCookie() to add cookie blocking and monitoring messages
    config.macros.cookieManager.saveOptionCookie=saveOptionCookie;
    window.saveOptionCookie=function(name,force)
    {
    	var cmc=config.macros.cookieManager; // abbrev
    	if (force || ((config.options.chkAllowBrowserCookies || name=="chkAllowBrowserCookies")
    		&& !cmc.blockedCookies.contains(name) && cmc.allowBrowserCookie(name))) {
    		cmc.saveOptionCookie.apply(this,arguments);
    		cmc.displayStatus(name+"="+config.options[name]);
    	} else cmc.displayStatus("setting of '"+name+"' is blocked");
    }

    // if removeCookie() function is not defined by TW core, define it here.
    if (window.removeCookie===undefined) {
    	window.removeCookie=function(name) {
    		document.cookie = name+'=; expires=Thu, 01-Jan-1970 00:00:01 UTC; path=/;';
    	}
    }

    // ... and then hijack it to add cookie blocking and monitoring messages
    config.macros.cookieManager.removeCookie=removeCookie;
    window.removeCookie=function(name,force)
    {
    	var cmc=config.macros.cookieManager; // abbrev
    	if (!cmc.getCookieList().contains(name))
    		return; // not a current cookie!
    	if (force || ((config.options.chkAllowBrowserCookies || name=="chkAllowBrowserCookies")
    		&& !cmc.blockedCookies.contains(name) && cmc.allowBrowserCookie(name))) {
    		cmc.removeCookie.apply(this,arguments);
    		cmc.displayStatus("deleted "+name);
    	} else cmc.displayStatus("deletion of '"+name+"' is blocked");
    }
    //}}}

    /***
    |Name|CookieManagerPluginConfig|
    |Source|http://www.TiddlyTools.com/#CookieManagerPluginConfig|
    |Requires|CookieManagerPlugin|
    |Description|custom settings for [[CookieManagerPlugin]]|
    !!!!!Browser Cookie Configuration:
    ***/
    // // <<option chkAllowBrowserCookies>> store ~TiddlyWiki option settings using private browser cookies
    // // <<option chkMonitorBrowserCookies>> monitor browser cookie activity (shows a message whenever a cookie is updated)
    //{{{
    // default settings:
    config.options.chkAllowBrowserCookies=true;	// if FALSE, this blocks *all* cookies
    config.options.chkMonitorBrowserCookies=false;
    //}}}

    // // Individual cookie names can be prevented from being created, modified, or deleted in your browser's stored cookies by adding them to the {{{config.macros.cookieManager.blockedCookies}}} array:
    //{{{
    var bc=config.macros.cookieManager.blockedCookies; // abbreviation
    bc.push("txtMainTab");			// TiddlyWiki:  SideBarTabs
    bc.push("txtTOCSortBy");		// TiddlyTools: TableOfContentsPlugin
    bc.push("txtCatalogTab");		// TiddlyTools: ShowCatalog
    //}}}
    // // You can also define a javascript test function that determines whether or not any particular cookie name should be blocked or allowed.  The following function should return FALSE if the browser cookie should be blocked, or TRUE if changes to the cookie should be allowed:
    //{{{
    config.macros.cookieManager.allowBrowserCookie=function(name) {
    	// add tests based on specific cookie names and runtime conditions
    	return true;
    }
    //}}}

    /***
    |Name|CopyTiddlerPlugin|
    |Source|http://www.TiddlyTools.com/#CopyTiddlerPlugin|
    |Version|3.2.5|
    |Author|Eric Shulman|
    |License|http://www.TiddlyTools.com/#LegalStatements|
    |~CoreVersion|2.3|
    |Type|plugin|
    |Requires||
    |Overrides||
    |Description|Quickly create a copy of any existing tiddler|
    !!!Usage
    <<<
    The plugin automatically updates the default (shadow) ToolbarCommands definitions to insert the ''copyTiddler'' command, which will appear as ''copy'' when a tiddler is rendered.  If you are already using customized toolbar definitions, you will need to manually add the ''copyTiddler'' toolbar command to your existing ToolbarCommands tiddler, e.g.:
    {{{
    |EditToolbar|... copyTiddler ... |
    }}}
    When the ''copy'' command is selected, a new tiddler is created containing an exact copy of the current text/tags/fields, using a title of "{{{TiddlerName (n)}}}", where ''(n)'' is the next available number (starting with 1, of course).  If you copy while //editing// a tiddler, the current values displayed in the editor are used (including any changes you may have already made to those values), and the new tiddler is immediately opened for editing.

    The plugin also provides a macro that allows you to embed a ''copy'' command directly in specific tiddler content:
    {{{
    <<copyTiddler TidderName label:"..." prompt:"...">>
    }}}
    where
    * ''TiddlerName'' (optional)<br>specifies the //source// tiddler to be copied.  If omitted, the current containing tiddler (if any) will be copied.
    * ''label:"..."'' (optional)<br>specifies text to use for the embedded link (default="copy TiddlerName")
    * ''prompt:"..."'' (optional)<br>specifies mouseover 'tooltip' help text for link
    //Note: to use non-default label/prompt values with the current containing tiddler, use "" for the TiddlerName//
    <<<
    !!!Configuration
    <<<
    <<option chkCopyTiddlerDate>> use date/time from existing tiddler (otherwise, use current date/time)
    {{{<<option chkCopyTiddlerDate>>}}}
    <<<
    !!!Revisions
    <<<
    2009.06.08 [3.2.5] added option to use timestamp from source tiddler
    2009.03.09 [3.2.4] fixed IE-specific syntax error
    2009.03.02 [3.2.3] refactored code (again) to restore use of config.commands.copyTiddler.* custom settings
    2009.02.13 [3.2.2] in click(), fix calls to displayTiddler() to use current tiddlerElem and use getTiddlerText() to permit copying of shadow tiddler content
    2009.01.30 [3.2.1] fixed handling for copying field values when in edit mode
    2009.01.23 [3.2.0] refactored code and added {{{<<copyTiddler TiddlerName>>}}} macro
    2008.12.18 [3.1.4] corrected code for finding next (n) value when 'sparse' handling is in effect (thanks to RussThomas for identifying and diagnosing the problem)
    2008.11.14 [3.1.3] added optional 'sparse' setting (avoids 'filling in' missing numbers that may have been previously deleted)
    2008.11.14 [3.1.2] added optional 'zeroPad' setting
    2008.11.14 [3.1.1] moved hard-coded '(n)' regex into 'suffixPattern' object property so it can be customized
    2008.09.26 [3.1.0] changed new title generation to use '(n)' suffix instead of 'Copy of' prefix
    2008.05.20 [3.0.3] in handler, when copying from VIEW mode, create duplicate array from existing tags array before saving new tiddler.
    2007.12.19 [3.0.2] in handler, when copying from VIEW mode, duplicate custom fields before saving new tiddler. Thanks to bug report from Ken Girard.
    2007.09.26 [3.0.1] in handler, use findContainingTiddler(src) to get tiddlerElem (and title).  Allows 'copy' command to find correct tiddler when transcluded using {{{<<tiddler>>}}} macro or enhanced toolbar inclusion (see [[CoreTweaks]])
    2007.06.28 [3.0.0] complete re-write to handle custom fields and alternative view/edit templates
    2007.05.17 [2.1.2] use store.getTiddlerText() to retrieve tiddler content, so that SHADOW tiddlers can be copied correctly when in VIEW mode
    2007.04.01 [2.1.1] in copyTiddler.handler(), fix check for editor fields by ensuring that found field actually has edit=='text' attribute
    2007.02.05 [2.1.0] in copyTiddler.handler(), if editor fields (textfield and/or tagsfield) can't be found (i.e., tiddler is in VIEW mode, not EDIT mode), then get text/tags values from stored tiddler instead of active editor fields.  Allows use of COPY toolbar directly from VIEW mode (based on a request from LaurentCharles)
    2006.12.12 [2.0.0] completely rewritten so plugin just creates a new tiddler EDITOR with a copy of the current tiddler EDITOR contents, instead of creating the new tiddler in the STORE by copying the current tiddler values from the STORE.
    2005.xx.xx [1.0.0] original version by Tim Morgan
    <<<
    !!!Code
    ***/
    //{{{
    version.extensions.CopyTiddlerPlugin= {major: 3, minor: 2, revision: 5, date: new Date(2009,6,8)};

    // automatically tweak shadow EditTemplate to add 'copyTiddler' toolbar command (following 'cancelTiddler')
    config.shadowTiddlers.ToolbarCommands=config.shadowTiddlers.ToolbarCommands.replace(/cancelTiddler/,'cancelTiddler copyTiddler');

    if (config.options.chkCopyTiddlerDate===undefined) config.options.chkCopyTiddlerDate=false;

    config.commands.copyTiddler = {
    	text: 'copy',
    	hideReadOnly: true,
    	tooltip: 'Make a copy of this tiddler',
    	notitle: 'this tiddler',
    	prefix: '',
    	suffixText: ' (%0)',
    	suffixPattern: / \(([0-9]+)\)$/,
    	zeroPad: 0,
    	sparse: false,
    	handler: function(event,src,title)
    		{ return config.commands.copyTiddler.click(src,event); },
    	click: function(here,ev) {
    		var tiddlerElem=story.findContainingTiddler(here);
    		var template=tiddlerElem?tiddlerElem.getAttribute('template'):null;
    		var title=here.getAttribute('from');
    		if (!title || !title.length) {
    			if (!tiddlerElem) return false;
    			else title=tiddlerElem.getAttribute('tiddler');
    		}
    		var root=title.replace(this.suffixPattern,''); // title without suffix
    		// find last matching title
    		var last=title;
    		if (this.sparse) { // don't fill-in holes... really find LAST matching title
    			var tids=store.getTiddlers('title','excludeLists');
    			for (var t=0; t<tids.length; t++) if (tids[t].title.startsWith(root)) last=tids[t].title;
    		}
    		// get next number (increment from last matching title)
    		var n=1; var match=this.suffixPattern.exec(last); if (match) n=parseInt(match[1])+1;
    		var newTitle=this.prefix+root+this.suffixText.format([String.zeroPad(n,this.zeroPad)]);
    		// if not sparse mode, find the next hole to fill in...
    		while (store.tiddlerExists(newTitle)||document.getElementById(story.idPrefix+newTitle))
    			{ n++; newTitle=this.prefix+root+this.suffixText.format([String.zeroPad(n,this.zeroPad)]); }
    		if (!story.isDirty(title)) { // if tiddler is not being EDITED
    			// duplicate stored tiddler (if any)
    			var text=store.getTiddlerText(title,'');
    			var who=config.options.txtUserName;
    			var when=new Date();
    			var newtags=[]; var newfields={};
    			var tid=store.getTiddler(title); if (tid) {
    				if (config.options.chkCopyTiddlerDate) var when=tid.modified;
    				for (var t=0; t<tid.tags.length; t++) newtags.push(tid.tags[t]);
    				store.forEachField(tid,function(t,f,v){newfields[f]=v;},true);
    			}
    	                store.saveTiddler(newTitle,newTitle,text,who,when,newtags,newfields,true);
    			story.displayTiddler(tiddlerElem,newTitle,template);
    		} else {
    			story.displayTiddler(tiddlerElem,newTitle,template);
    			var fields=config.commands.copyTiddler.gatherFields(tiddlerElem); // get current editor fields
    			var newTiddlerElem=document.getElementById(story.idPrefix+newTitle);
    			for (var f=0; f<fields.length; f++) {  // set fields in new editor
    				if (fields[f].name=='title') fields[f].value=newTitle; // rename title in new tiddler
    				var fieldElem=config.commands.copyTiddler.findField(newTiddlerElem,fields[f].name);
    				if (fieldElem) {
    					if (fieldElem.getAttribute('type')=='checkbox')
    						fieldElem.checked=fields[f].value;
    					else
    						fieldElem.value=fields[f].value;
    				}
    			}
    		}
    		story.focusTiddler(newTitle,'title');
    		return false;
    	},
    	findField: function(tiddlerElem,field) {
    		var inputs=tiddlerElem.getElementsByTagName('input');
    		for (var i=0; i<inputs.length; i++) {
    			if (inputs[i].getAttribute('type')=='checkbox' && inputs[i].field == field) return inputs[i];
    			if (inputs[i].getAttribute('type')=='text' && inputs[i].getAttribute('edit') == field) return inputs[i];
    		}
    		var tas=tiddlerElem.getElementsByTagName('textarea');
    		for (var i=0; i<tas.length; i++) if (tas[i].getAttribute('edit') == field) return tas[i];
    		var sels=tiddlerElem.getElementsByTagName('select');
    		for (var i=0; i<sels.length; i++) if (sels[i].getAttribute('edit') == field) return sels[i];
    		return null;
    	},
    	gatherFields: function(tiddlerElem) { // get field names and values from current tiddler editor
    		var fields=[];
    		// get checkboxes and edit fields
    		var inputs=tiddlerElem.getElementsByTagName('input');
    		for (var i=0; i<inputs.length; i++) {
    			if (inputs[i].getAttribute('type')=='checkbox')
    				if (inputs[i].field) fields.push({name:inputs[i].field,value:inputs[i].checked});
    			if (inputs[i].getAttribute('type')=='text')
    				if (inputs[i].getAttribute('edit')) fields.push({name:inputs[i].getAttribute('edit'),value:inputs[i].value});
    		}
    		// get textareas (multi-line edit fields)
    		var tas=tiddlerElem.getElementsByTagName('textarea');
    		for (var i=0; i<tas.length; i++)
    			if (tas[i].getAttribute('edit')) fields.push({name:tas[i].getAttribute('edit'),value:tas[i].value});
    		// get selection lists (droplist or listbox)
    		var sels=tiddlerElem.getElementsByTagName('select');
    		for (var i=0; i<sels.length; i++)
    			if (sels[i].getAttribute('edit')) fields.push({name:sels[i].getAttribute('edit'),value:sels[i].value});
    		return fields;
    	}
    };
    //}}}
    // // MACRO DEFINITION
    //{{{
    config.macros.copyTiddler = {
    	label: 'copy',
    	prompt: 'Make a copy of %0',
    	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    		var title=params.shift();
    		params=paramString.parseParams('anon',null,true,false,false);
    		var label	=getParam(params,'label',this.label+(title?' '+title:''));
    		var prompt	=getParam(params,'prompt',this.prompt).format([title||this.notitle]);
    		var b=createTiddlyButton(place,label,prompt,
    			function(ev){return config.commands.copyTiddler.click(this,ev)});
    		b.setAttribute('from',title||'');
    	}
    };
    //}}}

    /***
    |Name|CoreTweaks|
    |Source|http://www.TiddlyTools.com/#CoreTweaks|
    |Version|use with TW2.4.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.2.0|
    |Type|plugin|
    |Requires||
    |Overrides|various|
    |Description|a small collection of overrides to TW core functions|
    This tiddler contains changes TW core functions to provide minor changes in standard features or behavior.  It is hoped that some of these tweaks may someday be added into the TW core, so that these adjustments will be available without needing these add-on definitions.
    >''Note: the changes contained in this tiddler are generally applicable for version 2.4.3 of TiddlyWiki.''
    >Please view [[CoreTweaksArchive]] for tweaks that may be used with earlier versions of TiddlyWiki.
    ***/
    //{{{
    // calculate TW version number - used to determine which tweaks should be applied
    var ver=version.major+version.minor/10+version.revision/100;
    //}}}
    /***
    ----

    ***/
    // // open tickets:
    // // {{block{
    /***
    !!!890 add conditional test to """<<tiddler>>""" macro
    ***/
    // // {{groupbox small{
    /***
    http://trac.tiddlywiki.org/ticket/890 - OPEN
    This tweak extends the {{{<<tiddler>>}}} macro syntax so you can include a javascript-based //test expression// to determine if the tiddler transclusion should be performed:
    {{{
    <<tiddler TiddlerName if:{{...}} with: param param etc.>>
    }}}
    If the test is ''true'', then the tiddler is transcluded as usual.  If the test is ''false'', then the transclusion is skipped and //no output is produced//.
    ***/
    //{{{
    config.macros.tiddler.if_handler = config.macros.tiddler.handler;
    config.macros.tiddler.handler = function(place,macroName,params,wikifier,paramString,tiddler)
    {
    	params = paramString.parseParams('name',null,true,false,true);
    	if (!getParam(params,'if',true)) return;
    	this.if_handler.apply(this,arguments);
    };
    //}}}
    // // }}}}}}// // {{block{
    /***
    !!!831 backslash-quoting for embedding newlines in 'line-mode' formats
    ***/
    // // {{groupbox small{
    /***
    http://trac.tiddlywiki.org/ticket/831 - OPEN
    This tweak pre-processes source content to convert 'double-backslash-newline' into {{{<br>}}} before wikify(), so that literal newlines can be embedded in line-mode wiki syntax (e.g., tables, bullets, etc.)
    ***/
    //{{{
    window.coreWikify = wikify;
    window.wikify = function(source,output,highlightRegExp,tiddler)
    {
    	if (source) arguments[0]=source.replace(/\\\\\n/mg,'<br>');
    	coreWikify.apply(this,arguments);
    }
    //}}}
    // // }}}}}}// // {{block{
    /***
    !!!829 """<<tag>>""" macro - sortby parameter
    ***/
    // // {{groupbox small{
    /***
    http://trac.tiddlywiki.org/ticket/829 - OPEN
    This tweak adds an optional 'sortby' parameter to the """<<tag tagname label tip sortby>>""" macro, as well as the """<<allTags excludeTag sortby>>""" macro used to generate the sidebar contents 'tags' list.  Specify the field on which the contents of each tag popup is to be sorted, with a '+' or '-' prefix to indicate ascending/descending order, respectively.

    Example: """<<tag systemConfig "plugins" "list plugins by date, most recent first" "-modified">>"""
    Try it: <<tag systemConfig "plugins" "list plugins by date, most recent first" "-modified">>

    Similarly, to change the sort order used by the popups from all tags shown in the sidebar contents, edit the [[TagTags]] shadow tiddler and enter: """<<allTags excludeLists -modified>>"""
    ***/
    //{{{
    // hijack tag handler() to add 'sortby' attribute to tag button
    config.macros.tag.CoreTweaksSortTags_handler=config.macros.tag.handler;
    config.macros.tag.handler = function(place,macroName,params)
    {
    	this.CoreTweaksSortTags_handler.apply(this,arguments);
    	var btn=place.lastChild;
    	if (params[3]) btn.setAttribute('sortby',params[3]);
    }

    // tweak <<allTags>> macro to add 'sortby' attribute to each tag button
    var fn=config.macros.allTags.handler;
    var lines=fn.toString().split('\n');
    lines.splice(lines.length-2,0,['if(params[1]) btn.setAttribute("sortby",params[1]);']);
    fn=lines.join('\n');
    eval('config.macros.allTags.handler='+fn);

    // tweak tag event handler to:
    // * use tag filtering (only if '[' is present in tag value)
    // * use optional 'sortby' attribute
    // * save 'sortby' value in 'open all' command (for displaying tiddlers in sorted order)
    var fn=onClickTag;
    fn=fn.toString().replace(
    	/store.getTaggedTiddlers\(tag\);/g,
    	'(tag.indexOf("[")==-1?store.getTaggedTiddlers(tag):store.filterTiddlers(tag));'
    	+'var sortby=this.getAttribute("sortby");'
    	+'if(sortby&&sortby.length) store.sortTiddlers(tagged,sortby);'
    );
    fn=fn.toString().replace(
    	/openAll.setAttribute\("tag",\s*tag\);/g,
    	'openAll.setAttribute("tag",tag); openAll.setAttribute("sortby",sortby);'
    );
    eval(fn);

    // tweak 'open all' event handler to use 'sortby' attribute
    var fn=onClickTagOpenAll;
    fn=fn.toString().replace(
    	/story.displayTiddlers\(this,\s*tiddlers\);/g,
    	'var sortby=this.getAttribute("sortby");'
    	+'if(sortby&&sortby.length) store.sortTiddlers(tiddlers,sortby);'
    	+'story.displayTiddlers(this,tiddlers);'
    );
    eval(fn);
    //}}}
    // // }}}}}}// // {{block{
    /***
    !!!824 ~WindowTitle - alternative to combined ~SiteTitle/~SiteSubtitle in window titlebar
    ***/
    // // {{groupbox small{
    /***
    http://trac.tiddlywiki.org/ticket/824 - OPEN
    This tweak allows definition of an optional [[WindowTitle]] tiddler that, when present, provides alternative text for display in the browser window's titlebar, instead of using the combined text content from [[SiteTitle]] and [[SiteSubtitle]] (which will still be displayed as usual in the TiddlyWiki document header area).

    Note: this ticket replaces http://trac.tiddlywiki.org/ticket/401 (closed), which proposed using a custom [[PageTitle]] tiddler for this purpose.  ''If you were using the previous '401 ~PageTitle' tweak, you will need to rename [[PageTitle]] to [[WindowTitle]] to continue to use your custom window title text''
    ***/
    //{{{
    config.shadowTiddlers.WindowTitle='<<tiddler SiteTitle>> - <<tiddler SiteSubtitle>>';
    window.getPageTitle=function() { return wikifyPlain('WindowTitle'); }
    store.addNotification('WindowTitle',refreshPageTitle); // so title stays in sync with tiddler changes
    //}}}
    // // }}}}}}// // {{block{
    /***
    !!!784 allow tiddler sections in TiddlyLinks to be used as anchor points for intra-tiddler scrolling.
    >http://trac.tiddlywiki.org/ticket/784 - OPEN - Please see separate [[SectionLinksPlugin]]
    !!!683 FireFox3 Import bug: 'browse' button replacement
    ***/
    // // {{groupbox small{
    /***
    http://trac.tiddlywiki.org/ticket/683 - OPEN
    The web standard 'type=file' input control that has been used as a local path/file picker for TiddlyWiki no longer works as expected in FireFox3, which has, for security reasons, limited javascript access to this control so that *no* local filesystem path information can be revealed, even when it is intentional and necessary, as it is with TiddlyWiki.  This tweak provides alternative HTML source that patches the backstage import panel.  It replaces the 'type=file' input control with a text+button combination of controls that invokes a system-native secure 'file-chooser' dialog box to provide TiddlyWiki with access to a complete path+filename so that TW functions properly locate user-selected local files.
    >Note: ''This tweak also requires http://trac.tiddlywiki.org/ticket/604 - cross-platform askForFilename()''
    ***/
    //{{{
    if (window.Components) {
    	var fixhtml='<input name="txtBrowse" style="width:30em"><input type="button" value="..."'
    		+' onClick="window.browseForFilename(this.previousSibling,true)">';
    	var cmi=config.macros.importTiddlers;
    	cmi.step1Html=cmi.step1Html.replace(/<input type='file' size=50 name='txtBrowse'>/,fixhtml);
    }

    merge(config.messages,{selectFile:'Please enter or select a file'}); // ready for I18N translation

    window.browseForFilename=function(target,mustExist) { // note: both params are optional
    	var msg=config.messages.selectFile;
    	if (target && target.title) msg=target.title; // use target field tooltip (if any) as dialog prompt text
    	// get local path for current document
    	var path=getLocalPath(document.location.href);
    	var p=path.lastIndexOf('/'); if (p==-1) p=path.lastIndexOf('\\'); // Unix or Windows
    	if (p!=-1) path=path.substr(0,p+1); // remove filename, leave trailing slash
    	var file=''
    	var result=window.askForFilename(msg,path,file,mustExist); // requires #604
    	if (target && result.length) // set target field and trigger handling
    		{ target.value=result; target.onchange(); }
    	return result;
    }
    //}}}
    // // }}}}}}// // {{block{
    /***
    !!!604 cross-platform askForFilename()
    ***/
    // // {{groupbox small{
    /***
    http://trac.tiddlywiki.org/ticket/604 - OPEN
    invokes a system-native secure 'file-chooser' dialog box to provide TiddlyWiki with access to a complete path+filename so that TW functions properly locate user-selected local files.
    ***/
    //{{{
    window.askForFilename=function(msg,path,file,mustExist) {
    	var r = window.mozAskForFilename(msg,path,file,mustExist);
    	if(r===null || r===false)
    		r = window.ieAskForFilename(msg,path,file,mustExist);
    	if(r===null || r===false)
    		r = window.javaAskForFilename(msg,path,file,mustExist);
    	if(r===null || r===false)
    		r = prompt(msg,path+file);
    	return r||'';
    }

    window.mozAskForFilename=function(msg,path,file,mustExist) {
    	if(!window.Components) return false;
    	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, mustExist?nsIFilePicker.modeOpen: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(ex) { displayMessage(ex.toString()); }
    	return result;
    }

    window.ieAskForFilename=function(msg,path,file,mustExist) {
    	if(!config.browser.isIE) return false;
    	try {
    		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;
    		return s.showOpen()?s.FileName:'';
    	}
    	catch(ex) { displayMessage(ex.toString()); }
    	return result;
    }

    window.javaAskForFilename=function(msg,path,file,mustExist) {
    	if(!document.applets['TiddlySaver']) return false;
    	// TBD: implement java-based askFile(...) function
    	try { return document.applets['TiddlySaver'].askFile(msg,path,file,mustExist); }
    	catch(ex) { displayMessage(ex.toString()); }
    }
    //}}}
    // // }}}}}}// // {{block{
    /***
    !!!657 wrap tabs onto multiple lines
    ***/
    // // {{groupbox small{
    /***
    http://trac.tiddlywiki.org/ticket/657 - OPEN
    This tweak inserts an extra space element following each tab, allowing them to wrap onto multiple lines if needed.
    ***/
    //{{{
    config.macros.tabs.handler = function(place,macroName,params)
    {
    	var cookie = params[0];
    	var numTabs = (params.length-1)/3;
    	var wrapper = createTiddlyElement(null,'div',null,'tabsetWrapper ' + cookie);
    	var tabset = createTiddlyElement(wrapper,'div',null,'tabset');
    	tabset.setAttribute('cookie',cookie);
    	var validTab = false;
    	for(var t=0; t<numTabs; t++) {
    		var label = params[t*3+1];
    		var prompt = params[t*3+2];
    		var content = params[t*3+3];
    		var tab = createTiddlyButton(tabset,label,prompt,this.onClickTab,'tab tabUnselected');
    		createTiddlyElement(tab,'span',null,null,' ',{style:'font-size:0pt;line-height:0px'}); // ELS
    		tab.setAttribute('tab',label);
    		tab.setAttribute('content',content);
    		tab.title = prompt;
    		if(config.options[cookie] == label)
    			validTab = true;
    	}
    	if(!validTab)
    		config.options[cookie] = params[1];
    	place.appendChild(wrapper);
    	this.switchTab(tabset,config.options[cookie]);
    };
    //}}}
    // // }}}}}}// // {{block{
    /***
    !!!628 hide 'no such macro' errors
    ***/
    // // {{groupbox small{
    /***
    http://trac.tiddlywiki.org/ticket/628 - OPEN
    When invoking a macro that is not defined, this tweak prevents the display of the 'error in macro... no such macro' message.  This is useful when rendering tiddler content or templates that reference macros that are defined by //optional// plugins that have not been installed in the current document.

    <<option chkHideMissingMacros>> hide 'no such macro' error messages
    ***/
    //{{{
    if (config.options.chkHideMissingMacros===undefined)
    	config.options.chkHideMissingMacros=false;

    window.coreTweaks_missingMacro_invokeMacro = window.invokeMacro;
    window.invokeMacro = function(place,macro,params,wikifier,tiddler) {
    	if (!config.macros[macro] || !config.macros[macro].handler)
    		if (config.options.chkHideMissingMacros) return;
    	window.coreTweaks_missingMacro_invokeMacro.apply(this,arguments);
    }
    //}}}
    // // }}}}}}// // {{block{
    /***
    !!!608/609/610 toolbars - toggles, separators and transclusion
    ***/
    // // {{groupbox small{
    /***
    http://trac.tiddlywiki.org/ticket/608 - OPEN (more/less toggle)
    http://trac.tiddlywiki.org/ticket/609 - OPEN (separators)
    http://trac.tiddlywiki.org/ticket/610 - OPEN (wikify tiddler/slice/section content)

    This combination tweak extends the """<<toolbar>>""" macro to add use of '<' to insert a 'less' menu command (the opposite of '>' == 'more'), as well as use of '*' to insert linebreaks and "!" to insert a vertical line separator between toolbar items.  In addition, this tweak add the ability to use references to tiddlernames, slices, or sections and render their content inline within the toolbar, allowing easy creation of new toolbar commands using TW content (such as macros, links, inline scripts, etc.)

    To produce a one-line style, with "less" at the end, use
    | ViewToolbar| foo bar baz > yabba dabba doo < |
    resulting in:
    {{{
    foo bar baz more
       and
    foo bar baz yabba dabba doo less
    }}}
    or to use the CoreTweaks? two-line style:
    | ViewToolbar| foo bar baz > < * yabba dabba doo |
    which would produce:
    {{{
    foo bar baz more
       and
    foo bar baz less
    yabba dabba doo
    }}}
    ''see [[ToolbarCommands]] for examples of how these features can be used''
    ***/
    //{{{
    merge(config.macros.toolbar,{
    	moreLabel: 'more\u25BC',
    	morePrompt: 'Show additional commands',
    	lessLabel: '\u25C4less',
    	lessPrompt: 'Hide additional commands',
    	separator: '|'
    });
    config.macros.toolbar.onClickMore = function(ev) {
    	var e = this.nextSibling;
    	e.style.display = 'inline'; // show menu
    	this.style.display = 'none'; // hide button
    	return false;
    };
    config.macros.toolbar.onClickLess = function(ev) {
    	var e = this.parentNode;
    	var m = e.previousSibling;
    	e.style.display = 'none'; // hide menu
    	m.style.display = 'inline'; // show button
    	return false;
    };
    config.macros.toolbar.handler = function(place,macroName,params,wikifier,paramString,tiddler) {
    	for(var t=0; t<params.length; t++) {
    		var c = params[t];
    		switch(c) {
    			case '!':  // ELS - SEPARATOR (added)
    				createTiddlyText(place,this.separator);
    				break;
    			case '*':  // ELS - LINEBREAK (added)
    				createTiddlyElement(place,'BR');
    				break;
    			case '<': // ELS - LESS COMMAND (added)
    				var btn = createTiddlyButton(place,
    					this.lessLabel,this.lessPrompt,config.macros.toolbar.onClickLess,'moreCommand');
    				break;
    			case '>':
    				var btn = createTiddlyButton(place,
    					this.moreLabel,this.morePrompt,config.macros.toolbar.onClickMore,'moreCommand');
    				var e = createTiddlyElement(place,'span',null,'moreCommand');
    				e.style.display = 'none';
    				place = e;
    				break;
    			default:
    				var theClass = '';
    				switch(c.substr(0,1)) {
    					case '+':
    						theClass = 'defaultCommand';
    						c = c.substr(1);
    						break;
    					case '-':
    						theClass = 'cancelCommand';
    						c = c.substr(1);
    						break;
    				}
    				if(c in config.commands)

    					this.createCommand(place,c,tiddler,theClass);
    				else { // ELS - WIKIFY TIDDLER/SLICE/SECTION (added)
    					if (c.substr(0,1)=='~') c=c.substr(1); // ignore leading ~
    					var txt=store.getTiddlerText(c);
    					if (txt) {
    						// trim any leading/trailing newlines
    						txt=txt.replace(/^\n*/,'').replace(/\n*$/,'');
    						// trim PRE format wrapper if any
    						txt=txt.replace(/^\{\{\{\n/,'').replace(/\n\}\}\}$/,'');
    						// render content into toolbar
    						wikify(txt,createTiddlyElement(place,'span'),null,tiddler);
    					}
    				} // ELS - end WIKIFY CONTENT
    				break;
    		}
    	}
    };
    //}}}
    // // }}}}}}// // {{block{
    /***
    !!!529 IE fixup - case-sensitive element lookup of tiddler elements
    ***/
    // // {{groupbox small{
    /***
    http://trac.tiddlywiki.org/ticket/529 - OPEN
    This tweak hijacks the standard browser function, document.getElementById(), to work-around the case-INsensitivity error in Internet Explorer (all versions up to and including IE7) //''Note: This tweak is only applied when using IE, and only for lookups of rendered tiddler elements within the containing 'tiddlerDisplay' element.''//
    ***/
    //{{{
    if (config.browser.isIE) {
    document.coreTweaks_coreGetElementById=document.getElementById;
    document.getElementById=function(id) {
    	var e=document.coreTweaks_coreGetElementById(id);
    	if (!e || !e.parentNode || e.parentNode.id!='tiddlerDisplay') return e;
    	for (var i=0; i<e.parentNode.childNodes.length; i++)
    		if (id==e.parentNode.childNodes[i].id) return e.parentNode.childNodes[i];
    	return null;
    };
    }
    //}}}
    // // }}}}}}// // {{block{
    /***
    !!!471 'creator' field for new tiddlers
    ***/
    // // {{groupbox small{
    /***
    http://trac.tiddlywiki.org/ticket/471 - OPEN
    This tweak HIJACKS the core's saveTiddler() function to automatically add a 'creator' field to a tiddler when it is FIRST created. You can use """<<view creator>>""" (or """<<view creator wikified>>""" if you prefer) to show this value embedded directly within the tiddler content, or {{{<span macro="view creator"></span>}}} in the ViewTemplate and/or EditTemplate to display the creator value in each tiddler.
    ***/
    //{{{
    // hijack saveTiddler()
    TiddlyWiki.prototype.CoreTweaks_creatorSaveTiddler=TiddlyWiki.prototype.saveTiddler;
    TiddlyWiki.prototype.saveTiddler=function(title,newTitle,newBody,modifier,modified,tags,fields)
    {
    	var existing=store.tiddlerExists(title);
    	var tiddler=this.CoreTweaks_creatorSaveTiddler.apply(this,arguments);
    	if (!existing) store.setValue(title,'creator',config.options.txtUserName);
    	return tiddler;
    }
    //}}}
    // // }}}}}}
    // // closed: won't fix //(leave as core tweaks)//
    // // {{block{
    /***
    !!!637 TiddlyLink tooltip - custom formatting
    ***/
    // // {{groupbox small{
    /***
    http://trac.tiddlywiki.org/ticket/637 - CLOSED: WON'T FIX
    This tweak modifies the tooltip format that appears when you mouseover a link to a tiddler.  It adds an option to control the date format, as well as displaying the size of the tiddler (in bytes)

    Tiddler link tooltip format:
    {{stretch{<<option txtTiddlerLinkTootip>>}}}
    ^^where: %0=title, %1=username, %2=modification date, %3=size in bytes, %4=description slice^^
    Tiddler link tooltip date format:
    {{stretch{<<option txtTiddlerLinkTooltipDate>>}}}
    ***/
    //{{{
    config.messages.tiddlerLinkTooltip='%0 - %1, %2 (%3 bytes) - %4';
    config.messages.tiddlerLinkTooltipDate='DDD, MMM DDth YYYY 0hh12:0mm AM';

    config.options.txtTiddlerLinkTootip=
    	config.options.txtTiddlerLinkTootip||config.messages.tiddlerLinkTooltip;
    config.options.txtTiddlerLinkTooltipDate=
    	config.options.txtTiddlerLinkTooltipDate||config.messages.tiddlerLinkTooltipDate;

    Tiddler.prototype.getSubtitle = function() {
    	var modifier = this.modifier;
    	if(!modifier) modifier = config.messages.subtitleUnknown;
    	var modified = this.modified;
    	if(modified) modified = modified.formatString(config.options.txtTiddlerLinkTooltipDate);
    	else modified = config.messages.subtitleUnknown;
    	var descr=store.getTiddlerSlice(this.title,'Description')||'';
    	return config.options.txtTiddlerLinkTootip.format([this.title,modifier,modified,this.text.length,descr]);
    };
    //}}}
    // // }}}}}}// // {{block{
    /***
    !!!607 add HREF link on permaview command
    ***/
    // // {{groupbox small{
    /***
    http://trac.tiddlywiki.org/ticket/607 - CLOSED: WON'T FIX
    This tweak automatically sets the HREF for the 'permaview' sidebar command link so you can use the 'right click' context menu for faster, easier bookmarking.  Note that this does ''not'' automatically set the permaview in the browser's current location URL... it just sets the HREF on the command link.  You still have to click the link to apply the permaview.
    ***/
    //{{{
    config.macros.permaview.handler = function(place)
    {
    	var btn=createTiddlyButton(place,this.label,this.prompt,this.onClick);
    	addEvent(btn,'mouseover',this.setHREF);
    	addEvent(btn,'focus',this.setHREF);
    };
    config.macros.permaview.setHREF = function(event){
    	var links = [];
    	story.forEachTiddler(function(title,element) {
    		links.push(String.encodeTiddlyLink(title));
    	});
    	var newURL=document.location.href;
    	var hashPos=newURL.indexOf('#');
    	if (hashPos!=-1) newURL=newURL.substr(0,hashPos);
    	this.href=newURL+'#'+encodeURIComponent(links.join(' '));
    }
    //}}}
    // // }}}}}}// // {{block{
    /***
    !!!458 add permalink-like HREFs on internal TiddlyLinks
    ***/
    // // {{groupbox small{
    /***
    http://trac.tiddlywiki.org/ticket/458 - CLOSED: WON'T FIX
    This tweak assigns a permalink-like HREF to internal Tiddler links (which normally do not have any HREF defined).  This permits the link's context menu (right-click) to include 'open link in another window/tab' command.  Based on a request from Dustin Spicuzza.
    ***/
    //{{{
    window.coreTweaks_createTiddlyLink=window.createTiddlyLink;
    window.createTiddlyLink=function(place,title,includeText,theClass,isStatic,linkedFromTiddler,noToggle)
    {
    	// create the core button, then add the HREF (to internal links only)
    	var link=window.coreTweaks_createTiddlyLink.apply(this,arguments);
    	if (!isStatic)
    		link.href=document.location.href.split('#')[0]+'#'+encodeURIComponent(String.encodeTiddlyLink(title));
    	return link;
    }
    //}}}
    // // }}}}}}
    // // <<foldHeadings>>

    /%
    ***** PLEASE DO NOT DELETE THIS CONTENT *****
    %/''~TiddlyBlog'' //document design and functionality created by://
    [[Eric L Shulman|http://about.unamesa.org/Eric+Shulman]] - [[TiddlyTools / ELS Design Studios|http://www.TiddlyTools.com]] ''//"Small Tools for Big Ideas!"&trade;//''
    with thanks to Paul Reiber of [[Reiber Labs|http://reiber.org]]

    /***
    |Name|[[DatePlugin]]|
    |Source|http://www.TiddlyTools.com/#DatePlugin|
    |Documentation|http://www.TiddlyTools.com/#DatePluginInfo|
    |Version|2.7.1|
    |Author|Eric Shulman|
    |License|http://www.TiddlyTools.com/#LegalStatements|
    |~CoreVersion|2.1|
    |Type|plugin|
    |Requires||
    |Overrides||
    |Options|##Configuration|
    |Description|formatted dates plus popup menu with 'journal' link, changes and (optional) reminders|
    This plugin provides a general approach to displaying formatted dates and/or links and popups that permit easy navigation and management of tiddlers based on their creation/modification dates.
    !!!!!Documentation
    >see [[DatePluginInfo]]
    !!!!!Configuration
    <<<
    <<option chkDatePopupHideCreated>> omit 'created' section from date popups
    <<option chkDatePopupHideChanged>> omit 'changed' section from date popups
    <<option chkDatePopupHideTagged>> omit 'tagged' section from date popups
    <<option chkDatePopupHideReminders>> omit 'reminders' section from date popups
    <<option chkShowJulianDate>> display Julian day number (1-365) below current date

    see [[DatePluginConfig]] for additional configuration settings, for use in calendar displays, including:
    *date formats
    *color-coded backgrounds
    *annual fixed-date holidays
    *weekends
    <<<
    !!!!!Revisions
    <<<
    2009.05.31 [2.7.1] in addRemindersToPopup(), 'new reminder....' command now uses {{{<<newTiddler>>}}} macro.  Also, general code reduction/cleanup.
    |please see [[DatePluginInfo]] for additional revision details|
    2005.10.30 [0.9.0] pre-release
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.DatePlugin= {major: 2, minor: 7, revision: 1, date: new Date(2009,5,31)};

    config.macros.date = {
    	format: 'YYYY.0MM.0DD', // default date display format
    	linkformat: 'YYYY.0MM.0DD', // 'dated tiddler' link format
    	linkedbg: '#babb1e', // 'babble'
    	todaybg: '#ffab1e', // 'fable'
    	weekendbg: '#c0c0c0', // 'cocoa'
    	holidaybg: '#ffaace', // 'face'
    	createdbg: '#bbeeff', // 'beef'
    	modifiedsbg: '#bbeeff', // 'beef'
    	remindersbg: '#c0ffee', // 'coffee'
    	weekend: [ 1,0,0,0,0,0,1 ], // [ day index values: sun=0, mon=1, tue=2, wed=3, thu=4, fri=5, sat=6 ],
    	holidays: [ '01/01', '07/04', '07/24', '11/24' ]
    		// NewYearsDay, IndependenceDay(US), Eric's Birthday (hooray!), Thanksgiving(US)
    };

    config.macros.date.handler = function(place,macroName,params)
    {
    	// default: display current date
    	var now =new Date();
    	var date=now;
    	var mode='display';
    	if (params[0]&&['display','popup','link'].contains(params[0].toLowerCase()))
    		{ mode=params[0]; params.shift(); }

    	if (!params[0] || params[0]=='today')
    		{ params.shift(); }
    	else if (params[0]=='filedate')
    		{ date=new Date(document.lastModified); params.shift(); }
    	else if (params[0]=='tiddler')
    		{ date=store.getTiddler(story.findContainingTiddler(place).id.substr(7)).modified; params.shift(); }
    	else if (params[0].substr(0,8)=='tiddler:')
    		{ var t; if ((t=store.getTiddler(params[0].substr(8)))) date=t.modified; params.shift(); }
    	else {
    		var y = eval(params.shift().replace(/Y/ig,(now.getYear()<1900)?now.getYear()+1900:now.getYear()));
    		var m = eval(params.shift().replace(/M/ig,now.getMonth()+1));
    		var d = eval(params.shift().replace(/D/ig,now.getDate()+0));
    		date = new Date(y,m-1,d);
    	}
    	// date format with optional custom override
    	var format=this.format; if (params[0]) format=params.shift();
    	var linkformat=this.linkformat; if (params[0]) linkformat=params.shift();
    	showDate(place,date,mode,format,linkformat);
    }

    window.showDate=showDate;
    function showDate(place,date,mode,format,linkformat,autostyle,weekend)
    {
    	mode	  =mode||'display';
    	format	  =format||config.macros.date.format;
    	linkformat=linkformat||config.macros.date.linkformat;

    	// format the date output
    	var title=date.formatString(format);
    	var linkto=date.formatString(linkformat);

    	// just show the formatted output
    	if (mode=='display') { place.appendChild(document.createTextNode(title)); return; }

    	// link to a 'dated tiddler'
    	var link = createTiddlyLink(place, linkto, false);
    	link.appendChild(document.createTextNode(title));
    	link.title = linkto;
    	link.date = date;
    	link.format = format;
    	link.linkformat = linkformat;

    	// if using a popup menu, replace click handler for dated tiddler link
    	// with handler for popup and make link text non-italic (i.e., an 'existing link' look)
    	if (mode=='popup') {
    		link.onclick = onClickDatePopup;
    		link.style.fontStyle='normal';
    	}
    	// format the popup link to show what kind of info it contains (for use with calendar generators)
    	if (autostyle) setDateStyle(place,link,weekend);
    }
    //}}}
    //{{{
    // NOTE: This function provides default logic for setting the date style when displayed in a calendar
    // To customize the date style logic, please see[[DatePluginConfig]]
    function setDateStyle(place,link,weekend) {
    	// alias variable names for code readability
    	var date=link.date;
    	var fmt=link.linkformat;
    	var linkto=date.formatString(fmt);
    	var cmd=config.macros.date;

    	if ((weekend!==undefined?weekend:isWeekend(date))&&(cmd.weekendbg!=''))
    		{ place.style.background = cmd.weekendbg; }
    	if (hasModifieds(date)||hasCreateds(date)||hasTagged(date,fmt))
    		{ link.style.fontStyle='normal'; link.style.fontWeight='bold'; }
    	if (hasReminders(date))
    		{ link.style.textDecoration='underline'; }
    	if (isToday(date))
    		{ link.style.border='1px solid black'; }
    	if (isHoliday(date)&&(cmd.holidaybg!=''))
    		{ place.style.background = cmd.holidaybg; }
    	if (hasCreateds(date)&&(cmd.createdbg!=''))
    		{ place.style.background = cmd.createdbg; }
    	if (hasModifieds(date)&&(cmd.modifiedsbg!=''))
    		{ place.style.background = cmd.modifiedsbg; }
    	if ((hasTagged(date,fmt)||store.tiddlerExists(linkto))&&(cmd.linkedbg!=''))
    		{ place.style.background = cmd.linkedbg; }
    	if (hasReminders(date)&&(cmd.remindersbg!=''))
    		{ place.style.background = cmd.remindersbg; }
    	if (isToday(date)&&(cmd.todaybg!=''))
    		{ place.style.background = cmd.todaybg; }
    	if (config.options.chkShowJulianDate) { // optional display of Julian date numbers
    		var m=[0,31,59,90,120,151,181,212,243,273,304,334];
    		var d=date.getDate()+m[date.getMonth()];
    		var y=date.getFullYear();
    		if (date.getMonth()>1 && (y%4==0 && y%100!=0) || y%400==0)
    			d++; // after February in a leap year
    		wikify('@@font-size:80%;<br>'+d+'@@',place);
    	}

    }
    //}}}
    //{{{
    function isToday(date) // returns true if date is today
    	{ var now=new Date(); return ((now-date>=0) && (now-date<86400000)); }
    function isWeekend(date) // returns true if date is a weekend
    	{ return (config.macros.date.weekend[date.getDay()]); }
    function isHoliday(date) // returns true if date is a holiday
    {
    	var longHoliday = date.formatString('0MM/0DD/YYYY');
    	var shortHoliday = date.formatString('0MM/0DD');
    	for(var i = 0; i < config.macros.date.holidays.length; i++) {
    		var holiday=config.macros.date.holidays[i];
    		if (holiday==longHoliday||holiday==shortHoliday) return true;
    	}
    	return false;
    }
    //}}}
    //{{{
    // Event handler for clicking on a day popup
    function onClickDatePopup(e) { e=e||window.event;
    	var p=Popup.create(this); if (!p) return false;
    	// always show dated tiddler link (or just date, if readOnly) at the top...
    	if (!readOnly || store.tiddlerExists(this.date.formatString(this.linkformat)))
    		createTiddlyLink(createTiddlyElement(p,'li'),this.date.formatString(this.linkformat),true);
    	else
    		createTiddlyText(createTiddlyElement(p,'li'),this.date.formatString(this.linkformat));
    	if (!config.options.chkDatePopupHideCreated)
    		addCreatedsToPopup(p,this.date,this.format);
    	if (!config.options.chkDatePopupHideChanged)
    		addModifiedsToPopup(p,this.date,this.format);
    	if (!config.options.chkDatePopupHideTagged)
    		addTaggedToPopup(p,this.date,this.linkformat);
    	if (!config.options.chkDatePopupHideReminders)
    		addRemindersToPopup(p,this.date,this.linkformat);
    	Popup.show(); e.cancelBubble=true; if(e.stopPropagation)e.stopPropagation(); return false;
    }
    //}}}
    //{{{
    function indexCreateds() // build list of tiddlers, hash indexed by creation date
    {
    	var createds= { };
    	var tiddlers = store.getTiddlers('title','excludeLists');
    	for (var t = 0; t < tiddlers.length; t++) {
    		var date = tiddlers[t].created.formatString('YYYY0MM0DD')
    		if (!createds[date])
    			createds[date]=new Array();
    		createds[date].push(tiddlers[t].title);
    	}
    	return createds;
    }
    function hasCreateds(date) // returns true if date has created tiddlers
    {
    	if (!config.macros.date.createds) config.macros.date.createds=indexCreateds();
    	return (config.macros.date.createds[date.formatString('YYYY0MM0DD')]!=undefined);
    }

    function addCreatedsToPopup(p,when,format)
    {
    	var force=(store.isDirty() && when.formatString('YYYY0MM0DD')==new Date().formatString('YYYY0MM0DD'));
    	if (force || !config.macros.date.createds) config.macros.date.createds=indexCreateds();
    	var indent=String.fromCharCode(160)+String.fromCharCode(160);
    	var createds = config.macros.date.createds[when.formatString('YYYY0MM0DD')];
    	if (createds) {
    		createds.sort();
    		var e=createTiddlyElement(p,'div',null,null,'created ('+createds.length+')');
    		for(var t=0; t<createds.length; t++) {
    			var link=createTiddlyLink(createTiddlyElement(p,'li'),createds[t],false);
    			link.appendChild(document.createTextNode(indent+createds[t]));
    		}
    	}
    }
    //}}}
    //{{{
    function indexModifieds() // build list of tiddlers, hash indexed by modification date
    {
    	var modifieds= { };
    	var tiddlers = store.getTiddlers('title','excludeLists');
    	for (var t = 0; t < tiddlers.length; t++) {
    		var date = tiddlers[t].modified.formatString('YYYY0MM0DD')
    		if (!modifieds[date])
    			modifieds[date]=new Array();
    		modifieds[date].push(tiddlers[t].title);
    	}
    	return modifieds;
    }
    function hasModifieds(date) // returns true if date has modified tiddlers
    {
    	if (!config.macros.date.modifieds) config.macros.date.modifieds = indexModifieds();
    	return (config.macros.date.modifieds[date.formatString('YYYY0MM0DD')]!=undefined);
    }

    function addModifiedsToPopup(p,when,format)
    {
    	var date=when.formatString('YYYY0MM0DD');
    	var force=(store.isDirty() && date==new Date().formatString('YYYY0MM0DD'));
    	if (force || !config.macros.date.modifieds) config.macros.date.modifieds=indexModifieds();
    	var indent=String.fromCharCode(160)+String.fromCharCode(160);
    	var mods = config.macros.date.modifieds[date];
    	if (mods) {
    		// if a tiddler was created on this date, don't list it in the 'changed' section
    		if (config.macros.date.createds && config.macros.date.createds[date]) {
    			var temp=[];
    			for(var t=0; t<mods.length; t++)
    				if (!config.macros.date.createds[date].contains(mods[t]))
    					temp.push(mods[t]);
    			mods=temp;
    		}
    		mods.sort();
    		var e=createTiddlyElement(p,'div',null,null,'changed ('+mods.length+')');
    		for(var t=0; t<mods.length; t++) {
    			var link=createTiddlyLink(createTiddlyElement(p,'li'),mods[t],false);
    			link.appendChild(document.createTextNode(indent+mods[t]));
    		}
    	}
    }
    //}}}
    //{{{
    function hasTagged(date,format) // returns true if date is tagging other tiddlers
    {
    	return store.getTaggedTiddlers(date.formatString(format)).length>0;
    }

    function addTaggedToPopup(p,when,format)
    {
    	var indent=String.fromCharCode(160)+String.fromCharCode(160);
    	var tagged=store.getTaggedTiddlers(when.formatString(format));
    	if (tagged.length) var e=createTiddlyElement(p,'div',null,null,'tagged ('+tagged.length+')');
    	for(var t=0; t<tagged.length; t++) {
    		var link=createTiddlyLink(createTiddlyElement(p,'li'),tagged[t].title,false);
    		link.appendChild(document.createTextNode(indent+tagged[t].title));
    	}
    }
    //}}}
    //{{{
    function indexReminders(date,leadtime) // build list of tiddlers with reminders, hash indexed by reminder date
    {
    	var reminders = { };
    	if(window.findTiddlersWithReminders!=undefined) { // reminder plugin is installed
    		var t = findTiddlersWithReminders(date, [0,leadtime], null, null, 1);
    		for(var i=0; i<t.length; i++) reminders[t[i].matchedDate]=true;
    	}
    	return reminders;
    }

    function hasReminders(date) // returns true if date has reminders
    {
    	if (window.reminderCacheForCalendar)
    		return window.reminderCacheForCalendar[date]; // use calendar cache
    	if (!config.macros.date.reminders)
    		config.macros.date.reminders = indexReminders(date,90); // create a 90-day leadtime reminder cache
    	return (config.macros.date.reminders[date]);
    }

    function addRemindersToPopup(p,when,format)
    {
    	if(window.findTiddlersWithReminders==undefined) return; // reminder plugin not installed

    	var indent = String.fromCharCode(160)+String.fromCharCode(160);
    	var reminders=findTiddlersWithReminders(when, [0,31],null,null,1);
    	createTiddlyElement(p,'div',null,null,'reminders ('+(reminders.length||'none')+')');
    	for(var t=0; t<reminders.length; t++) {
    		link = createTiddlyLink(createTiddlyElement(p,'li'),reminders[t].tiddler,false);
    		var diff=reminders[t].diff;
    		diff=(diff<1)?'Today':((diff==1)?'Tomorrow':diff+' days');
    		var txt=(reminders[t].params['title'])?reminders[t].params['title']:reminders[t].tiddler;
    		link.appendChild(document.createTextNode(indent+diff+' - '+txt));
    	}
    	if (readOnly) return;	// readonly... omit 'new reminder...' command
    	var rem='\\<\\<reminder day:%0 month:%1 year:%2 title:"Enter a reminder title here"\\>\\>';
    	rem=rem.format([when.getDate(),when.getMonth()+1,when.getYear()+1900]);
    	var cmd="<<newTiddler label:[["+indent+"new reminder...]] prompt:[[add a reminder to '%0']]"
    		+" title:[[%0]] text:{{var t=store.getTiddlerText('%0','');t+(t.length?'\\n':'')+'%1'}} tag:%2>>";
    	wikify(cmd.format([when.formatString(format),rem,config.options.txtCalendarReminderTags||'']),
    		createTiddlyElement(p,'li'));
    }
    //}}}

    /***
    |Name|DatePluginConfig|
    |Source|http://www.TiddlyTools.com/#DatePluginConfig|
    |Documentation|http://www.TiddlyTools.com/#DatePluginInfo|
    |Version|2.6.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|formats, background colors and other optional settings for DatePlugin|
    ***/
    // // Default popup content display options (can be overridden by cookies)
    //{{{
    if (config.options.chkDatePopupHideCreated===undefined)
    	config.options.chkDatePopupHideCreated=false;
    if (config.options.chkDatePopupHideChanged===undefined)
    	config.options.chkDatePopupHideChanged=false;
    if (config.options.chkDatePopupHideTagged===undefined)
    	config.options.chkDatePopupHideTagged=false;
    if (config.options.chkDatePopupHideReminders===undefined)
    	config.options.chkDatePopupHideReminders=false;
    //}}}

    // // show Julian date number below regular date
    //{{{
    if (config.options.chkShowJulianDate===undefined)
    	config.options.chkShowJulianDate=false;
    //}}}

    // // fixed-date annual holidays
    //{{{
    config.macros.date.holidays=[
    	"01/01", // NewYearsDay,
    	"07/04", // US Independence Day
    	"07/24"  // Eric's Birthday (hooray!)
    ];
    //}}}

    // // weekend map (1=weekend, 0=weekday)
    //{{{
    config.macros.date.weekend=[ 1,0,0,0,0,0,1 ]; // day index values: sun=0, mon=1, tue=2, wed=3, thu=4, fri=5, sat=6
    //}}}

    // // date display/link formats
    //{{{
    config.macros.date.format="YYYY.0MM.0DD"; // default date display format
    config.macros.date.linkformat="YYYY.0MM.0DD"; // 'dated tiddler' link format
    //}}}

    // // When displaying a calendar (see [[CalendarPlugin]]), you can customize the colors/styles that are applied to the calendar dates by modifying the values and/or functions below:
    //{{{
    // default calendar colors
    config.macros.date.weekendbg="#c0c0c0";
    config.macros.date.holidaybg="#ffaace";
    config.macros.date.createdbg="#bbeeff";
    config.macros.date.modifiedsbg="#bbeeff";
    config.macros.date.linkedbg="#babb1e";
    config.macros.date.remindersbg="#c0ffee";

    // apply calendar styles
    function setDateStyle(place,link,weekend) {
    	// alias variable names for code readability
    	var date=link.date;
    	var fmt=link.linkformat;
    	var linkto=date.formatString(fmt);
    	var cmd=config.macros.date;

    	if ((weekend!==undefined?weekend:isWeekend(date))&&(cmd.weekendbg!=""))
    		{ place.style.background = cmd.weekendbg; }
    	if (hasModifieds(date)||hasCreateds(date)||hasTagged(date,fmt))
    		{ link.style.fontStyle="normal"; link.style.fontWeight="bold"; }
    	if (hasReminders(date))
    		{ link.style.textDecoration="underline"; }
    	if (isToday(date))
    		{ link.style.border="1px solid black"; }
    	if (isHoliday(date)&&(cmd.holidaybg!=""))
    		{ place.style.background = cmd.holidaybg; }
    	if (hasCreateds(date)&&(cmd.createdbg!=""))
    		{ place.style.background = cmd.createdbg; }
    	if (hasModifieds(date)&&(cmd.modifiedsbg!=""))
    		{ place.style.background = cmd.modifiedsbg; }
    	if ((hasTagged(date,fmt)||store.tiddlerExists(linkto))&&(cmd.linkedbg!=""))
    		{ place.style.background = cmd.linkedbg; }
    	if (hasReminders(date)&&(cmd.remindersbg!=""))
    		{ place.style.background = cmd.remindersbg; }
    	if (isToday(date)&&(cmd.todaybg!=""))
    		{ place.style.background = cmd.todaybg; }
    	if (config.options.chkShowJulianDate) {
    		var m=[0,31,59,90,120,151,181,212,243,273,304,334];
    		var d=date.getDate()+m[date.getMonth()];
    		var y=date.getFullYear();
    		if (date.getMonth()>1 && (y%4==0 && y%100!=0) || y%400==0) d++; // after February in a leap year
    		wikify("@@font-size:80%;<br>"+d+"@@",place);
    	}
    }
    //}}}

    [[欢迎]] [tag[startup]] [[迷你浏览器]]

    TiddlyWiki TiddlyTools

    /***
    |Name|DisableWikiLinksPlugin|
    |Source|http://www.TiddlyTools.com/#DisableWikiLinksPlugin|
    |Version|1.6.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>>
    <<<
    !!!!!Revisions
    <<<
    2008.07.22 [1.6.0] hijack tiddler changed() method to filter disabled wiki words from internal links[] array (so they won't appear in the missing tiddlers list)
    2007.06.09 [1.5.0] added configurable txtDisableWikiLinksTag (default value: "excludeWikiWords") to allows selective disabling of automatic WikiWord links for any tiddler tagged with that value.
    2006.12.31 [1.4.0] in formatter, test for chkDisableNonExistingWikiLinks
    2006.12.09 [1.3.0] in formatter, test for excluded wiki words specified in DisableWikiLinksList
    2006.12.09 [1.2.2] fix logic in autoLinkWikiWords() (was allowing links TO shadow tiddlers, even when chkDisableWikiLinks is TRUE).
    2006.12.09 [1.2.1] revised logic for handling links in shadow content
    2006.12.08 [1.2.0] added hijack of Tiddler.prototype.autoLinkWikiWords so regular (non-bracketed) WikiWords won't be added to the missing list
    2006.05.24 [1.1.0] added option to NOT bypass automatic wikiword links when displaying default shadow content (default is to auto-link shadow content)
    2006.02.05 [1.0.1] wrapped wikifier hijack in init function to eliminate globals and avoid FireFox 1.5.0.1 crash bug when referencing globals
    2005.12.09 [1.0.0] initial release
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.DisableWikiLinksPlugin= {major: 1, minor: 6, revision: 0, date: new Date(2008,7,22)};

    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()
    {
    	// 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;
    }

    Tiddler.prototype.disableWikiLinks_changed = Tiddler.prototype.changed;
    Tiddler.prototype.changed = function()
    {
    	this.disableWikiLinks_changed.apply(this,arguments);
    	// remove excluded wiki words from links array
    	var t=store.getTiddlerText(config.options.txtDisableWikiLinksList,"").readBracketedList();
    	if (t.length) for (var i=0; i<t.length; i++)
    		if (this.links.contains(t[i]))
    			this.links.splice(this.links.indexOf(t[i]),1);
    };
    //}}}

    [[GettingStarted]]
    [[AdvancedOptions]]
    [[cookieJar]]
    ----
    <<tiddler ShowPopup with:
    	DocumentSetup##cookies ~CookieManager "view/modify option cookie settings" tiddlyLinkExisting auto sticky>>
    <<tiddler ShowPopup with:
    	DocumentSetup##tweaker ~TiddlerTweaker "view/modify tiddler values" tiddlyLinkExisting auto sticky>>
    ----
    <<tiddler ShowPopup with:
    	DocumentSetup##templates templates "list templates" tiddlyLinkExisting auto>>
    <<tiddler ShowPopup with:
    	DocumentSetup##stylesheets stylesheets "list stylesheets" tiddlyLinkExisting auto>>
    <<tiddler ShowPopup with:
    	DocumentSetup##menus menus "list menus" tiddlyLinkExisting auto>>/%
    !cookies
    {{center{
    [[Browser cookies:|CookieManagerPlugin]] {{fine{<<option chkAllowBrowserCookies>>enable <<option chkMonitorBrowserCookies>>monitor}}}
    {{fine{
    ----
    {{smallform small{<<cookieManager>>}}}
    }}}
    !tweaker
    {{smallform{
    <<tiddlerTweaker>>}}}
    !templates
    <<matchTags "%0" "<br>" sort:title template>>
    !stylesheets
    <<matchTags "%0" "<br>" sort:title stylesheet>>
    !menus
    <<matchTags "%0" "<br>" sort:title menu>>
    !end
    %/

    <!--{{{-->
    <div class='toolbar' macro='toolbar [[ToolbarCommands::EditToolbar]]'></div>
    <div class='title' macro='view title'></div>
    <div class='editor' macro='edit title'></div>
    <div macro='annotations'></div>
    <div macro='tiddler QuickEditToolbar with: show'></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 excludeLists'></span></div>
    <span macro='resizeEditor'></span>
    <!--}}}-->

    /***
    |Name|FAQViewerPlugin|
    |Source|http://www.TiddlyTools.com/#FAQViewerPlugin|
    |Version|1.4.3|
    |Author|Eric Shulman|
    |License|http://www.TiddlyTools.com/#LegalStatements|
    |~CoreVersion|2.1|
    |Type|plugin|
    |Requires||
    |Overrides||
    |Description|select and display FAQ tiddlers from a droplist, sorted by date|
    !!!!!Usage
    <<<
    {{{<<faqViewer startwith:TiddlerName tagname classname sortby dateformat>>}}}
    where:
    *''startwith:TiddlerName'' (optional)<br>
    *''tagname'' (optional)<br>specifies the set of tiddlers to include in the FAQ list (default='faq')
    *''classname'' (optional)<br>specifies a CSS class to be applied surrounding the FAQ tiddler content
    *''sortby'' (optional)<br>specifies the name of a tiddler field to sort by.  Use '+' or '-' as a prefix on the fieldname to indicate ascending or descending order, respectively (default='-modified').  You can also use the special keyword, ''Description'', to sort alphabetically based on the value of a slice named 'Description', that can be defined in each FAQ tiddler.  Note: if a particular FAQ tiddler has no description slice, the title of the tiddler is used as a fallback.
    *''dateformat'' (optional)<br>specifies the formatting for dates displayed in the list.  Use " " (a single space) to suppress the date display.
    examples:
    {{{<<faqViewer>>}}}
    {{smallform small{<<faqViewer>>}}}
    {{{<<faqViewer package outline +title " ">>}}}
    {{smallform small{<<faqViewer package outline +title " ">>}}}
    <<<
    !!!!!Revisions
    <<<
    2009.06.14 [1.4.3] moved html definition to tiddler section (saves space)
    2008.10.21 [1.4.2] removed animation (was interfering with 'overflow:scroll' CSS)
    2008.09.30 [1.4.1] corrected filter by tag handling broken in 1.4.0
    2008.09.29 [1.4.0] added optional 'startwith:TiddlerName' param
    2008.09.24 [1.3.1] added animation when opening/closing faq content panel
    2008.09.21 [1.3.0] sort by 'description' slice values.  also added 'previous' and 'next' buttons for sequential viewing of FAQ articles
    2008.09.20 [1.2.0] optional 'sortby' and 'dateformat' params
    2008.01.20 [1.1.0] support for alternative 'target' tag instead of 'faq' (default)
    2007.10.15 [1.0.0] converted to true plugin
    2007.02.01 [0.0.0] inline script
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.FAQViewerPlugin={major: 1, minor: 4, revision: 3, date: new Date(2009,6,14)};

    config.shadowTiddlers.FAQViewer='{{smallform{<<faqViewer>>}}}';

    config.macros.faqViewer= {
    	dateFormat:'YYYY.0MM.0DD 0hh:0mm - ',
    	startparam: 'startwith:',
    	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    		// create form
    		if (params[0]&&params[0].substr(0,this.startparam.length)==this.startparam)
    			{ var startwith=params[0].substr(this.startparam.length); params.shift(); }
    		var console=createTiddlyElement(place,'span');
    		console.innerHTML=store.getTiddlerText('FAQViewerPlugin##html').replace(/%classname%/,params[1]||'');
    		this.go(console.getElementsByTagName('form')[0],startwith, params[0],params[2],params[3]);
    	},
    	go: function(f,startwith,targetType,sortby,dateformat) {
    		var targetType=targetType||'faq';
    		var sortby=sortby||'-modified';
    		var dateformat=dateformat||this.dateFormat;
    		var datefield=sortby.indexOf('created')!=-1?'created':'modified';
    		f.targetType.value=targetType;
    		f.sortBy.value=sortby;
    		f.dateFmt.value=dateformat;
    		var lists=f.getElementsByTagName('select'); if (!lists.length) return;
    		var FAQList=lists[0]; var taglist=lists[1];
    		while (FAQList.options[0]) FAQList.options[0]=null; // empty FAQList
    		if (f.search.value!=f.search.defaultValue) var find=f.search.value;
    		var tiddlers=store.getTaggedTiddlers(targetType,'modified').reverse();
    		if (tiddlers && sortby) {
    			if (sortby.indexOf('escription')==-1)	// sort by tiddler field
    				tiddlers=store.sortTiddlers(tiddlers,sortby);
    			else
    				tiddlers.sort(function(a,b){	// sort by description slice (or title, if no slice)
    					var da=store.getTiddlerSlice(a.title,'Description')||a.title;
    					var db=store.getTiddlerSlice(b.title,'Description')||b.title;
    					return da==db?0:(da>db?+1:-1);
    				});
    		}
    		var matchcount=0; var tags=[]; var selectedIndex=0;
    		FAQList.options[0]=new Option('选择一个条目...','',false,false);
    		for (var i=0; i<tiddlers.length; i++) {
    			for (var t=0; t<tiddlers[i].tags.length; t++)
    				tags.pushUnique(tiddlers[i].tags[t]); // collect other tags
    			if (find && find.length && tiddlers[i].text.indexOf(find)==-1) continue;
    			if (taglist.value && taglist.value.length && !tiddlers[i].tags.contains(taglist.value)) continue;
    			matchcount++;
    			var d=store.getTiddlerSlice(tiddlers[i].title,'Description')||tiddlers[i].title;
    			d=tiddlers[i][datefield].formatString(dateformat)+d;
    			FAQList.options[FAQList.options.length]=new Option(d,tiddlers[i].title,false,false);
    			if (tiddlers[i].title==startwith) selectedIndex=i+1;
    		}
    		FAQList.options[0].text='选择一个条目... ['+tiddlers.length+' 条目'+(tiddlers.length!=1?'s':'');
    		if (find && find.length || taglist.value.length)
    			FAQList.options[0].text+=', '+matchcount+' match'+(matchcount!=1?'es':'');
    		FAQList.options[0].text+=']';
    		FAQList.selectedIndex=selectedIndex;
    		if (selectedIndex) config.macros.faqViewer.show(f,startwith);

    		if (!taglist.options.length) { // only load tag list the first time, since it doesn't change
    			while (taglist.options[0]) taglist.options[0]=null; // empty taglist
    			taglist.options[0]=new Option('利用tag过滤...','',false,false);
    			var tagcount=0;
    			for (var t=0; t<tags.length; t++) {
    				if (tags[t].toLowerCase()==targetType) continue;
    				if (tags[t].indexOf('exclude')!=-1) continue;
    				taglist.options[taglist.options.length]
    					=new Option(tags[t],tags[t],false,false);
    				tagcount++;
    			}
    			if (!tagcount) taglist.options[taglist.options.length]
    				=new Option('未发现可供分类的tag','',false,false);
    		}
    	},
    	show: function(f,v) {
    		var fmt=this.faqlayout;
    		if (store.getTaggedTiddlers(v).length) fmt=this.packagelayout;
    		var target=f.getElementsByTagName('div')[0];
    		removeChildren(target);
    		wikify(fmt.format([v]),target);
    		target.style.display='block';
    		f.prev.parentNode.style.display='block';
    		f.next.focus();
    		f.done.disabled=!v.length;
    	},
    	faqlayout:
    		'{{toolbar floatright fine{//now viewing: //[[%0]] &nbsp;}}}<<tiddler [[%0]]>>',
    	packagelayout:
    		'{{toolbar floatright fine{//now viewing: //[[%0]] &nbsp;}}}\n'
    			+'{{floatright borderleft fine{<<tagging [[%0]]>>}}}<<tiddler [[%0]]>>{{clear block{}}}'
    }
    //}}}
    /***
    //{{{
    !html
    <form onsubmit='return false;' style='display:inline;margin:0;padding:0;white-space:nowrap;'><!--
    --><input type='hidden' name='targetType' value='faq'><!--
    --><input type='hidden' name='sortBy' value='-modified'><!--
    --><input type='hidden' name='dateFmt' value='YYYY.0MM.0DD 0hh:0mm - '><!--
    --><select name='list' size=1 style='width:50%'
    	onchange='if (!this.value.length) this.form.done.onclick();
    		else config.macros.faqViewer.show(this.form,this.value);'><!--
    --></select><!--
    --><select name='taglist' size=1 style='width:12%'
    	title='list only items that have a specific category tag'
    	onchange='var f=this.form; f.done.onclick();
    		config.macros.faqViewer.go(f,"",f.targetType.value,f.sortBy.value,f.dateFmt.value)'><!--
    --></select><!--
    --><input type='text' name='search' value='输入要搜索的文本...' style='width:20%'
    	title='list only items that contain the search text (use blank to match all)'
    	onfocus='this.select()'
    	onkeyup=' if (event.keyCode==13) this.form.find.onclick();
    		if (!this.value.length) {this.value=this.defaultValue; this.select(); this.form.find.onclick();}'><!--
    --><input type='button' name='find' value='搜索' style='width:6%'
    	title='搜索'
    	onclick='var f=this.form; f.done.onclick();
    		config.macros.faqViewer.go(f,"",f.targetType.value,f.sortBy.value,f.dateFmt.value)'><!--
    --><input type='button' name='reset' value='重置' style='width:6%'
    	title='重置'
    	onclick='var f=this.form; f.done.onclick();
    		f.search.value=f.search.defaultValue; f.taglist.selectedIndex=0;
    		config.macros.faqViewer.go(f,"",f.targetType.value,f.sortBy.value,f.dateFmt.value)'><!--
    --><input type='button' name='done' value='完成' disabled style='width:6%'
    	title='隐藏当前的条目'
    	onclick='var target=this.form.getElementsByTagName("div")[0];
    		target.style.display="none"; removeChildren(target);
    		this.form.prev.parentNode.style.display="none";
    		this.form.list.selectedIndex=0; this.disabled=true;'><!--
    --><div class="%classname%" style="display:none;white-space:normal;"></div><!--
    --><span style='text-align:right;display:none;overflow:auto;'><!--
    --><input type='button' name='prev' value='&#x25C4 prev' style='float:left;font-size:80%;'
    	title='view previous item'
    	onclick='var f=this.form; var i=f.list.selectedIndex-1;
    		f.list.selectedIndex=i<0?f.list.length-1:i; f.list.onchange();'><!--
    --><input type='button' name='next' value='next &#x25BA;' style='float:right;font-size:80%;'
    	title='view next item'
    	onclick='var f=this.form; var i=f.list.selectedIndex+1;
    		f.list.selectedIndex=i>f.list.length-1?0:i; f.list.onchange();'><!--
    --></span><!--
    --></form>
    !end
    //}}}
    ***/

    <<tiddler AutoRefresh with: force>><<tiddler HideTiddlerBackground>><<tiddler HideTiddlerTags>>{{transparent smallform{<<faqViewer faq 'viewer scrollbars'>>}}}

    /***
    |FileDropPlugin|h
    |author : BradleyMeck|
    |version : 0.1.1|
    |date : Nov 13 2006|
    |usage : drag a file onto the TW to have it be made into a tiddler|
    |browser(s) supported : Mozilla|

    Note: this version has been 'tweaked' by Eric Shulman (http://www.TiddlyTools.com) to add suspend/resume notification handling to improve performance when multiple files are dropped at once.

    !Trouble Shooting
    *If the plugin does not seem to work, open up the page "about:config" (just type it in the address bar) and make sure @@color(blue):signed.applets.codebase_principal_support@@ is set to @@color(blue):true@@

    !Revisions
    *Multiple File Dropping API updated, to end all capturing events after yours return a value that makes if(myFunctionsReturnValue) evaluate to true
    *Added support for multiple file drop handlers
    **Use the config.macros.fileDrop.addEventListener(@@color(green):String Flavor@@, @@color(green):Function handler(nsiFile){}@@, @@color(green):Boolean addToFront@@) function
    ***Standard Flavor is "application/x-moz-file"
    ***addToFront gives your handler priority over all others at time of add
    *Old plugin would disallow drops of text vetween applications because it didn't check if the transfer was a file.

    !Example Handler
    *Adds simple file import control, add this to a tiddler tagged {{{systemConfig}}} to make file dropping work
    {{{
    config.macros.fileDrop.addEventListener("application/x-moz-file",function(nsiFile)
    {
     if(
        confirm("You have dropped the file \""+nsiFile.path+"\" onto the page, it will be imported as a tiddler. Is that ok?")
        )
     {
     var newDate = new Date();
     var title = prompt("what would you like to name the tiddler?");
     store.saveTiddler(title,title,loadFile(nsiFile.path),config.options.txtUserName,newDate,[]);
     }
     return true;
    })
    }}}

    !Example Handler without popups and opening the tiddler on load
    *Adds simple file import control, add this to a tiddler tagged {{{systemConfig}}} to make file dropping work
    {{{
    config.macros.fileDrop.addEventListener("application/x-moz-file",function(nsiFile)
    {
     var newDate = new Date();
     store.saveTiddler(nsiFile.path,nsiFile.path,loadFile(nsiFile.path),config.options.txtUserName,newDate,[]);
     story.displayTiddler(null,nsiFile.path)
     return true;
    })
    }}}
    !Code
    ***/

    //{{{
    config.macros.fileDrop = {version : {major : 0, minor : 0, revision: 1}};
    config.macros.fileDrop.customDropHandlers = [];

    config.macros.fileDrop.dragDropHandler = function(evt) {

     netscape.security.PrivilegeManager.enablePrivilege('UniversalXPConnect');
     // Load in the native DragService manager from the browser.
     var dragService = Components.classes["@mozilla.org/widget/dragservice;1"].getService(Components.interfaces.nsIDragService);

     // Load in the currently-executing Drag/drop session.
     var dragSession = dragService.getCurrentSession();

     // Create an instance of an nsITransferable object using reflection.
     var transferObject = Components.classes["@mozilla.org/widget/transferable;1"].createInstance();

     // Bind the object explicitly to the nsITransferable interface. We need to do this to ensure that
     // methods and properties are present and work as expected later on.
     transferObject = transferObject.QueryInterface(Components.interfaces.nsITransferable);

     // I've chosen to add only the x-moz-file MIME type. Any type can be added, and the data for that format
     // will be retrieved from the Drag/drop service.
     transferObject.addDataFlavor("application/x-moz-file");

     // Get the number of items currently being dropped in this drag/drop operation.
     var numItems = dragSession.numDropItems;
    // ELS 2007.12.03: performance improvement when dropping multiple files
    if (numItems>1) {
    	clearMessage();
    	displayMessage("Reading "+numItems+" files...");
    	store.suspendNotifications();
    }
     for (var i = 0; i < numItems; i++)
     {
     // Get the data for the given drag item from the drag session into our prepared
     // Transfer object.
     dragSession.getData(transferObject, i);

     // We need to pass in Javascript 'Object's to any XPConnect method which
     // requires OUT parameters. The out value will then be saved as a new
     // property called Object.value.
     var dataObj = {};
     var dropSizeObj = {};

    for(var ind = 0; ind < config.macros.fileDrop.customDropHandlers.length; ind++)
    {
      var item = config.macros.fileDrop.customDropHandlers[ind];
      if(dragSession.isDataFlavorSupported(item.flavor))
      {
        transferObject.getTransferData(item.flavor, dataObj, dropSizeObj);
        var droppedFile = dataObj.value.QueryInterface(Components.interfaces.nsIFile);
        // Display all of the returned parameters with an Alert dialog.
        var result = item.handler.call(item,droppedFile);
     // Since the event is handled, prevent it from going to a higher-level event handler.
    	 evt.stopPropagation();
    	 evt.preventDefault();
        if(result){break;}
      }
    }
     }
    // ELS 2007.12.03: performance improvement and feedback after dropping multiple files
    if (numItems>1) {
    	store.resumeNotifications();
    	store.notifyAll();
    	displayMessage(numItems+" files have been processed");
    }
    }

    if(!window.event)
    {
     // Register the event handler, and set the 'capture' flag to true so we get this event
     // before it bubbles up through the browser.
     window.addEventListener("dragdrop", config.macros.fileDrop.dragDropHandler , true);
    }

    config.macros.fileDrop.addEventListener = function(paramflavor,func,inFront)
    {
    var obj = {};
    obj.flavor = paramflavor;
    obj.handler = func;
    if(!inFront)
    {config.macros.fileDrop.customDropHandlers.push(obj);}
    else{config.macros.fileDrop.customDropHandlers.shift(obj);}
    }
    //}}}

    /***
    |Name|FileDropPluginConfig|
    |Source|http://www.TiddlyTools.com/#FileDropPluginConfig|
    |Version|1.5.1|
    |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|FileDropPlugin, AttachFilePlugin|
    |Overrides||
    |Options|##Configuration|
    |Description|Adds drag-and-drop handlers for creating binary attachments or directory lists|

    __TiddlyTools FileDrop+AttachFile extended handler:__
    * use just filename instead of whole path as tiddler title
    * check for existing tiddler and prompt for new name
    * handle folder drops (drops each file or creates a file list in a tiddler)
    * use AttachFilePlugin if MIME type is not text/plain
    * autotag created tiddlers (e.g., "temporary", "dropped", etc.)
    * option to suppress automatic display of newly created tiddlers
    * suspend/resume notifications when handling multiple files (performance improvement)
    !!!!!Configuration
    <<<
    <<option chkFileDropTrimFilename>> Omit file extensions from tiddler titles when creating new tiddlers
    &nbsp;&nbsp;{{{usage: <<option chkFileDropTrimFilename>> }}}
    <<option chkFileDropDisplay>> Automatically display newly created tiddlers
    &nbsp;&nbsp;{{{usage: <<option chkFileDropDisplay>> }}}
    Tag newly created tiddlers with: <<option txtFileDropTags>>
    &nbsp;&nbsp;{{{usage: <<option txtFileDropTags>>}}}

    __FileDrop+AttachFile configuration options:__
    <<option chkFileDropAttachLocalLink>> Include reference to local path/filename
    &nbsp;&nbsp;{{{usage: <<option chkFileDropAttachLocalLink>> }}}
    <<option chkFileDropAttachEncodeData>> Include binary file data as encoded "base64" text
    &nbsp;&nbsp;{{{usage: <<option chkFileDropAttachEncodeData>> }}}
    ...only if file is smaller than: <<option txtFileDropAttachDataLimit>> bytes
    &nbsp;&nbsp;{{{usage: <<option txtFileDropAttachDataLimit>>}}}

    See [[FileDropPlugin]] for more documentation on handler implementation specifics, including sample code for default drop handlers.
    <<<
    !!!!!Revisions
    <<<
    2008.08.11 [1.5.1] added chkFileDropAttachLocalLink option to allow suppression of local path/file link
    2007.01.01 [0.9.9] initial release with extensions for AttachFilePlugin
    <<<
    !!!!!Code
    ***/
    //{{{
    if (config.options.chkFileDropAttachEncodeData==undefined)
    	config.options.chkFileDropAttachEncodeData=true;
    if (config.options.chkFileDropAttachLocalLink==undefined)
    	config.options.chkFileDropAttachLocalLink=true;
    if (config.options.txtFileDropAttachDataLimit==undefined)
    	config.options.txtFileDropAttachDataLimit=32768;
    if (config.options.txtFileDropTags==undefined)
    	config.options.txtFileDropTags="";
    if (config.options.chkFileDropDisplay==undefined)
    	config.options.chkFileDropDisplay=true;
    if (config.options.chkFileDropTrimFilename==undefined)
    	config.options.chkFileDropTrimFilename=false;

    config.macros.fileDrop.addEventListener("application/x-moz-file",function(nsiFile)
    {
    	var header="Index of %0\n^^(as of %1)^^\n|!filename| !size | !modified |\n";
    	var item="|[[%0|%1]]| %2|%3|\n";
    	var footer="Total of %0 bytes in %1 files\n";

    	var now=new Date();
    	var files=[nsiFile];
    	if (nsiFile.isDirectory()) {
    		var folder=nsiFile.directoryEntries;
    		var files=[];
    		while (folder.hasMoreElements()) {
    			var f=folder.getNext().QueryInterface(Components.interfaces.nsILocalFile);
    			if (f instanceof Components.interfaces.nsILocalFile && !f.isDirectory()) files.push(f);
    		}
    		var msg=nsiFile.path.replace(/\\/g,"/")+"\n\n";
    		msg+="contains "+files.length+" files... ";
    		msg+="select OK to attach all files or CANCEL to create a list...";
    		if (!confirm(msg)) { // create a list in a tiddler
    			var title=nsiFile.leafName; // tiddler name is last directory name in path
    			while (title && title.length && store.tiddlerExists(title)) {
    				if (confirm(config.messages.overwriteWarning.format([title]))) break; // use existing title
    				title=prompt("Please enter a different tiddler title for this file",nsiFile.path.replace(/\\/g,"/"));
    			}
    			if (!title || !title.length) return true; // aborted by user... we're done!
    			var text=header.format([nsiFile.path.replace(/\\/g,"/"),now.toLocaleString()]);
    			var total=0;
    			for (var i=0; i<files.length; i++) { var f=files[i];
    				var name=f.leafName;
    				if (config.options.chkFileDropTrimFilename)
    					{ var p=name.split("."); if (p.length>1) p.pop(); name=p.join("."); }
    				var path="file:///"+f.path.replace(/\\/g,"/");
    				var size=f.fileSize; total+=size;
    				var when=new Date(f.lastModifiedTime).formatString("YYYY.0MM.0DD 0hh:0mm:0ss");
    				text+=item.format([name,path,size,when]);
    			}
    			text+=footer.format([total,files.length]);
    			var newtags=config.options.txtFileDropTags?config.options.txtFileDropTags.readBracketedList():[];
    			store.saveTiddler(null,title,text,config.options.txtUserName,now,newtags);
    			if (config.options.chkFileDropDisplay) story.displayTiddler(null,title);
    			return true;
    		}
    	}
    	if (files.length>1) store.suspendNotifications();
    	for (i=0; i<files.length; i++) {
    		var file=files[i];
    		if (file.isDirectory()) continue; // skip over nested directories
    		var type="text/plain";
    		var title=file.leafName; // tiddler name is file name
    		if (config.options.chkFileDropTrimFilename)
    			{ var p=title.split("."); if (p.length>1) p.pop(); title=p.join("."); }
    		var path=file.path;
    		var size=file.fileSize;
    		while (title && title.length && store.tiddlerExists(title)) {
    			if (confirm(config.messages.overwriteWarning.format([title]))) break; // use existing title
    			title=prompt("Please enter a different tiddler title for this file",path.replace(/\\/g,"/"));
    		}
    		if (!title || !title.length) continue; // cancelled by user... skip this file
    		if (config.macros.attach) {
    			type=config.macros.attach.getMIMEType(file.leafName,"");
    			if (!type.length)
    				type=prompt("Unrecognized file type.  Please enter a MIME type for this file","text/plain");
    			if (!type||!type.length) continue; // cancelled by user... skip this file
    		}
    		var newtags=config.options.txtFileDropTags?config.options.txtFileDropTags.readBracketedList():[];
    		if (type=="text/plain")
    			store.saveTiddler(null,title,loadFile(path),config.options.txtUserName,now,newtags);
    		else {
    			// only encode data if enabled and file is smaller than limit.  Default is 32768 (32K) bytes.
    			var embed=config.options.chkFileDropAttachEncodeData
    				&& file.fileSize<config.options.txtFileDropAttachDataLimit;
    			newtags.push("attachment"); newtags.push("excludeMissing");
    			var localfile="";
    			if (config.options.chkFileDropAttachLocalLink) {
    				// if file is in current document folder,
    				// remove path prefix and use relative reference
    				var localfile=path;
    				var h=document.location.href;
    				folder=getLocalPath(decodeURIComponent(h.substr(0,h.lastIndexOf("/")+1)));
    				if (localfile.substr(0,folder.length)==folder)
    					localfile='./'+localfile.substr(folder.length);
    			}
    			config.macros.attach.createAttachmentTiddler(path,
    				now.formatString(config.macros.timeline.dateFormat),
    				"attached by FileDropPlugin", newtags,
    				title, embed, config.options.chkFileDropAttachLocalLink, false,
    				localfile, "", type,!config.options.chkFileDropDisplay);
    		}
    		if (config.options.chkFileDropDisplay) story.displayTiddler(null,title);
    	}
    	if (files.length>1) { store.resumeNotifications(); store.notifyAll(); }
    	if (window.FFDEBUG) console.log(new Date()-now);
    	return true;
    })
    //}}}

    /%
    |Name|FoldOtherTiddlers|
    |Source|http://www.TiddlyTools.com/#FoldOtherTiddlers|
    |Version|1.0.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|script|
    |Requires||
    |Overrides||
    |Description|fold all other tiddlers when a tiddler is viewed - equivalent to pressing "focus" toolbar command|

    Usage: <<tiddler FoldOtherTiddlers>>

    %/<script>
    	if (!config.commands.collapseTiddler) return;
    	var here=story.findContainingTiddler(place); if (!here) return;
    	config.commands.collapseOthers.handler(null,here,here.getAttribute('tiddler'));
    </script>

    /***
    |Name|FramedLinksPlugin|
    |Source|http://www.TiddlyTools.com/#FramedLinksPlugin|
    |Version|1.1.1|
    |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|createExternalLink|
    |Options|##Configuration|
    |Description|clicking an external link opens an IFRAME following the link instead of opening a new tab/window|
    This plugin causes clicks on external links to be rendered as inline frames (~IFRAMEs) instead of opening new browser tabs/windows.
    !!!!!Usage
    <<<
    Use standard TiddlyWiki external link syntax into your tiddler content. If {{{chkFramedLinks}}} is enabled or the tiddler is tagged with 'framedLinks' (see Configuration), then whenever you click the external link an IFRAME will be dynamically added to the content.  Clicking on the link again removes the IFRAME.  Hold down any modifier (shift, control, or alt) while clicking a link ''temporarily'' bypasses the IFRAME handling and use the standard link handling behavior.
    <<<
    !!!!!Configuration
    <<<
    <<option chkFramedLinks>> display inline frames for all external links
    &nbsp; &nbsp; {{{<<option chkFramedLinks>>}}}
    <<option chkFramedLinksTag>> display inline frames for external links in tiddlers tagged with: <<option txtFramedLinksTag>>
    &nbsp; &nbsp; {{{<<option chkFramedLinksTag>> <<option txtFramedLinksTag>>}}}
    IFRAME size (CSS units: %, em, px, cm, in) - width: <<option txtFrameWidth>> height: <<option txtFrameHeight>>
    &nbsp; &nbsp; {{{<<option txtFrameWidth>> <<option txtFrameHeight>>}}}
    <<<
    !!!!!Examples
    <<<
    Try these links:
    *http://www.TiddlyWiki.com
    *http://www.TiddlyTools.com
    *http://groups.google.com/group/TiddlyWiki/topics
    <<<
    !!!!!Revisions
    <<<
    2008.11.14 [1.1.1] fixed handling for external links embedded in //shadow// tiddlers
    2008.09.13 [1.1.0] added support to selectively enable embedded IFRAMEs if the containing tiddler is tagged with 'framedLinks'
    2007.11.29 [1.0.5] added slider animation and improved CSS handling for IFRAME height/width to maximize display area
    2007.11.29 [1.0.0] initial release
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.FramedLinksPlugin= {major: 1, minor: 1, revision: 1, date: new Date(2008,11,14)};

    var co=config.options; // abbreviation
    if (co.chkFramedLinks==undefined) co.chkFramedLinks=false;
    if (co.chkFramedLinksTag==undefined) co.chkFramedLinksTag=true;
    if (co.txtFramedLinksTag==undefined) co.txtFramedLinksTag="framedLinks";
    if (co.txtFrameWidth==undefined) co.txtFrameWidth="100%";
    if (co.txtFrameHeight==undefined) co.txtFrameHeight="80%";

    window.framedLinks_createExternalLink=createExternalLink;
    window.createExternalLink=function(place,url)
    {
    	var link=this.framedLinks_createExternalLink.apply(this,arguments);
    	link.onclick=function(ev) { var e=ev?ev:window.event;
    		var co=config.options; // abbreviation
    		var here=story.findContainingTiddler(this);
    		if (here) var tid=store.getTiddler(here.getAttribute("tiddler"));
    		var enabled=co.chkFramedLinks || co.chkFramedLinksTag && tid && tid.isTagged(co.txtFramedLinksTag);
    		if (!enabled || e.ctrlKey || e.shiftKey || e.altKey) return; // BYPASS
    		var p=this.parentNode;
    		var f=this.nextSibling?this.nextSibling.firstChild:null; // get the IFRAME... maybe...
    		var w=co.txtFrameWidth; if (!w || !w.length) w="100%";
    		var h=co.txtFrameHeight; if (!h || !h.length) h="80%";
    		if (h.indexOf("%")) h=(findWindowHeight()*h.replace(/%/,"")/100)+"px"; // calc height as % of window
    		var showing=f && f.nodeName.toUpperCase()=="IFRAME"; // does IFRAME really exist?
    		var stretchCell=p.nodeName.toUpperCase()=="TD" && w.indexOf("%")!=-1 && w.replace(/%/,"")>=100;
    		if (!showing) { // create an iframe
    			link.style.display="block"; // force IFRAME onto line following link
    			if (stretchCell) { p.setAttribute("savedWidth",p.style.width); p.style.width="100%"; } // adjust TD so IFRAME stretches
    			var wrapper=createTiddlyElement(null,"span"); // wrapper for slider animation
    			wrapper.setAttribute("url",this.href); // for async loading of frame after animation completes
    			var f=createTiddlyElement(wrapper,"iframe"); // create IFRAME
    			f.style.backgroundColor="#fff"; f.style.width=w; f.style.height=h;
    			p.insertBefore(wrapper,this.nextSibling);
    			function loadURL(wrapper) { var f=wrapper.firstChild; var url=wrapper.getAttribute("url");
    				var d=f.contentDocument?f.contentDocument:(f.contentWindow?f.contentWindow.document:f.document);
    				d.open(); d.writeln("<html>connecting to "+url+"</html>"); d.close();
    				try { f.src=url; } // if the iframe can't handle the href
    				catch(e) { alert(e.description?e.description:e.toString()); } // ... then report the error
    				window.scrollTo(0,ensureVisible(wrapper));
    			}
    			if (!co.chkAnimate) loadURL(wrapper);
    			else {
    				var morph=new Slider(wrapper,true);
    				morph.callback=loadURL;
    				morph.properties.push({style: 'width', start: 0, end: 100, template: '%0%'});
    				anim.startAnimating(morph);
    			}
    		} else { // remove iframe
    			link.style.display="inline"; // restore link style
    			if (stretchCell) p.style.width=p.getAttribute("savedWidth"); // restore previous width of TD
    			if (!co.chkAnimate) p.removeChild(f.parentNode);
    			else {
    				var morph=new Slider(f.parentNode,false,false,"all");
    				morph.properties.push({style: 'width', start: 100, end: 0, template: '%0%'});
    				anim.startAnimating(morph);
    			}
    		}
    		e.cancelBubble=true; if (e.stopPropagation) e.stopPropagation(); return false;
    	}
    	return link;
    }
    //}}}

    <<tiddler {{"Hide"+"Tiddler"+"Background"}}>>''__The following [[setup instructions|GettingStarted]] outline the basic steps for configuring your personal tiddlyblog document:__''
    {{big{
    # get a copy{{normal{
    Begin by transferring a copy of this ~QuickStart&trade; document onto your own computer: {{big green{[[download now!|http://www.tiddlytools.com/download.php?file=quickstart/tiddlyblog.html]]}}}}}}
    # open local copy{{normal{
    After the file is saved to your filesystem, close ''//this//'' browser/tab window and ''open the //local// file you just saved''.}}}
    # set titles{{normal{
    Change content in SiteTitle, SiteSubtitle}}}
    # set content{{normal{
    Change content in [[Welcome]], [[About|AboutThisBlog]], [[Contact|ContactTheAuthor]], [[SiteNews]] and [[Credits]]}}}
    # set default tiddlers{{normal{
    Edit [[DefaultTiddlers]] to select which tiddlers will be displayed at startup.  The current definition is: {{block{<<wikify "{{{\n%0\n}}}\n" {{store.getTiddlerText("DefaultTiddlers")}}>>Note: the {{{[tag[startup]]}}} syntax automatically includes all tiddlers tagged with<<tag startup>>(if any).  This allows you to quickly add/remove individual tiddlers from the initial display simply by setting/clearing the<<tag startup>>tag on those tiddlers, rather than manually editing the list in DefaultTiddlers.
    }}}}}}
    # set styles //(optional)//{{normal{
    If desired, edit the StyleSheet to select your preferred background textures (if any), by changing the following syntax (near the end of the tiddler):{{block{
    <<<
    ''//plain://''
    {{{
    /* [[OFF_StyleSheetWood]] [[OFF_StyleSheetStone]] */
    }}}
    or ''//stone://''
    {{{
    /* [[OFF_StyleSheetWood]] */ [[StyleSheetStone]]
    }}}
    or ''//wood://''
    {{{
    [[StyleSheetWood]] /* [[OFF_StyleSheetStone]] */
    }}}
    Note: StyleSheetWood and StyleSheetStone use textured background images that are stored in tiddlers as //base64 text-encoded// {{{data:}}} ~URLs that are ''not currently supported by Internet Explorer'', which will display solid colors instead.
    <<<
    }}}}}}
    # set preferences //(optional)//{{normal{
    If desired, edit the [[cookieJar]] to add, remove, or adjust hard-coded plugin preferences (see individual plugins for details).  Current settings are:
    <<tiddler cookieJar>>}}}
    # set ~TiddlySpot ID //(optional)//{{normal{
    <<<
    If you are using ~TiddlySpot to host your document:
    # enter your ~TiddlySpot ID: <<option txtUploadUserName>>
    # press <html><hide linebreaks><input type="button" value="update" onclick="
    	var tid='TspotSetupPlugin';
    	var txt=store.getTiddlerText(tid); if (!txt) return;
    	if (!confirm('Are you sure you want to update \x22'+tid+'\x22?')) return;
    	txt=txt.replace(/ENTER_YOUR_ID_HERE/g,config.options.txtUploadUserName);
    	store.saveTiddler(tid,tid,txt,tid.modifier,tid.modified,tid.tags,tid.fields);
    	story.displayTiddler(story.findContainingTiddler(this),tid);
    "></html> to set the value into TspotSetupPlugin.
    # The change will take effect after you save-and-reload the //local// document.
    <<<
    }}}
    # remove samples{{normal{
    Delete the sample tiddlers (tagged with <<tag sample>>):<br><<list filter [tag[sample]]>>}}}
    # done{{normal{
    ''That's it!''... after you save-and-reload the document, your personal tiddlyblog will be ready to use.}}}
    }}}

    /***
    |Name|GotoPlugin|
    |Source|http://www.TiddlyTools.com/#GotoPlugin|
    |Documentation|http://www.TiddlyTools.com/#GotoPluginInfo|
    |Version|1.9.2|
    |Author|Eric Shulman|
    |License|http://www.TiddlyTools.com/#LegalStatements|
    |~CoreVersion|2.1|
    |Type|plugin|
    |Requires||
    |Overrides||
    |Description|view any tiddler by entering it's title - displays list of possible matches|
    ''View a tiddler by typing its title and pressing //enter//.''  As you type, a list of possible matches is displayed.  You can scroll-and-click (or use arrows+enter) to select/view a tiddler, or press escape to close the listbox to resume typing.  When the listbox is not displayed, pressing //escape// clears the current input.
    !!!Documentation
    >see [[GotoPluginInfo]]
    !!!Configuration
    <<<
    *Match titles only after {{twochar{<<option txtIncrementalSearchMin>>}}} or more characters are entered.<br>Use down-arrow to start matching with shorter input.  //Note: This option value is also set/used by [[SearchOptionsPlugin]]//.
    *To set the maximum height of the listbox, you can create a tiddler tagged with <<tag systemConfig>>, containing:
    //{{{
    config.macros.gotoTiddler.listMaxSize=10;  // change this number
    //}}}
    <<<
    !!!Revisions
    <<<
    2009.05.22 [1.9.2] use reverseLookup() for IncludePlugin
    |please see [[GotoPluginInfo]] for additional revision details|
    2006.05.05 [0.0.0] started
    <<<
    !!!Code
    ***/
    //{{{
    version.extensions.GotoPlugin= {major: 1, minor: 9, revision: 2, date: new Date(2009,5,22)};

    // automatically tweak shadow SideBarOptions to add <<gotoTiddler>> macro above <<search>>
    config.shadowTiddlers.SideBarOptions=config.shadowTiddlers.SideBarOptions.replace(/<<search>>/,"{{button{goto}}}\n<<gotoTiddler>><<search>>");

    if (config.options.txtIncrementalSearchMin===undefined) config.options.txtIncrementalSearchMin=3;

    config.macros.gotoTiddler= {
    	listMaxSize: 10,
    	listHeading: '发现 %0 个结果...',
    	searchItem: "查找 '%0'...",
    	handler:
    	function(place,macroName,params,wikifier,paramString,tiddler) {
    		var quiet	=params.contains("quiet");
    		var showlist	=params.contains("showlist");
    		var search	=params.contains("search");
    		params = paramString.parseParams("anon",null,true,false,false);
    		var instyle	=getParam(params,"inputstyle","");
    		var liststyle	=getParam(params,"liststyle","");
    		var filter	=getParam(params,"filter","");
    		var html=this.html;
    		var keyevent=window.event?"onkeydown":"onkeypress"; // IE event fixup for ESC handling
    		html=html.replace(/%keyevent%/g,keyevent);
    		html=html.replace(/%search%/g,search);
    		html=html.replace(/%quiet%/g,quiet);
    		html=html.replace(/%showlist%/g,showlist);
    		html=html.replace(/%display%/g,showlist?'block':'none');
    		html=html.replace(/%position%/g,showlist?'static':'absolute');
    		html=html.replace(/%instyle%/g,instyle);
    		html=html.replace(/%liststyle%/g,liststyle);
    		html=html.replace(/%filter%/g,filter);
    		if (config.browser.isIE) html=this.IEtableFixup.format([html]);
    		var span=createTiddlyElement(place,'span');
    		span.innerHTML=html; var form=span.getElementsByTagName("form")[0];
    		if (showlist) this.fillList(form.list,'',filter,search,0);
    	},
    	html:
    	'<form onsubmit="return false" style="display:inline;margin:0;padding:0">\
    		<input name=gotoTiddler type=text autocomplete="off" accesskey="G" style="%instyle%"\
    			title="Enter title text... ENTER=goto, SHIFT-ENTER=search for text, DOWN=select from list"\
    			onfocus="this.select(); this.setAttribute(\'accesskey\',\'G\');"\
    			%keyevent%="return config.macros.gotoTiddler.inputEscKeyHandler(event,this,this.form.list,%search%,%showlist%);"\
    			onkeyup="return config.macros.gotoTiddler.inputKeyHandler(event,this,%quiet%,%search%,%showlist%);">\
    		<select name=list style="display:%display%;position:%position%;%liststyle%"\
    			onchange="if (!this.selectedIndex) this.selectedIndex=1;"\
    			onblur="this.style.display=%showlist%?\'block\':\'none\';"\
    			%keyevent%="return config.macros.gotoTiddler.selectKeyHandler(event,this,this.form.gotoTiddler,%showlist%);"\
    			onclick="return config.macros.gotoTiddler.processItem(this.value,this.form.gotoTiddler,this,%showlist%);">\
    		</select><input name="filter" type="hidden" value="%filter%">\
    	</form>',
    	IEtableFixup:
    	"<table style='width:100%;display:inline;padding:0;margin:0;border:0;'>\
    		<tr style='padding:0;margin:0;border:0;'><td style='padding:0;margin:0;border:0;'>\
    		%0</td></tr></table>",
    	getItems:
    	function(list,val,filter) {
    		if (!list.cache || !list.cache.length || val.length<=config.options.txtIncrementalSearchMin) {
    			// starting new search, fetch and cache list of tiddlers/shadows/tags
    			list.cache=new Array();
    			if (filter.length) {
    				var fn=store.getMatchingTiddlers||store.getTaggedTiddlers;
    				var tiddlers=store.sortTiddlers(fn.apply(store,[filter]),'title');
    			} else
    				var tiddlers=store.reverseLookup('tags','excludeLists');
    			for(var t=0; t<tiddlers.length; t++) list.cache.push(tiddlers[t].title);
    			if (!filter.length) {
    				for (var t in config.shadowTiddlers) list.cache.pushUnique(t);
    				var tags=store.getTags();
    				for(var t=0; t<tags.length; t++) list.cache.pushUnique(tags[t][0]);
    			}
    		}
    		var found = [];
    		var match=val.toLowerCase();
    		for(var i=0; i<list.cache.length; i++)
    			if (list.cache[i].toLowerCase().indexOf(match)!=-1) found.push(list.cache[i]);
    		return found;
    	},
    	getItemSuffix:
    	function(t) {
    		if (store.tiddlerExists(t)) return "";  // tiddler
    		if (store.isShadowTiddler(t)) return " (shadow)"; // shadow
    		return " (tag)"; // tag
    	},
    	fillList:
    	function(list,val,filter,search,key) {
    		if (list.style.display=="none") return; // not visible... do nothing!
    		var indent='\xa0\xa0\xa0';
    		var found = this.getItems(list,val,filter); // find matching items...
    		found.sort(); // alpha by title
    		while (list.length > 0) list.options[0]=null; // clear list
    		var hdr=this.listHeading.format([found.length,found.length==1?"":"s"]);
    		list.options[0]=new Option(hdr,"",false,false);
    		for (var t=0; t<found.length; t++) list.options[list.length]=
    			new Option(indent+found[t]+this.getItemSuffix(found[t]),found[t],false,false);
    		if (search)
    			list.options[list.length]=new Option(this.searchItem.format([val]),"*",false,false);
    		list.size=(list.length<this.listMaxSize?list.length:this.listMaxSize); // resize list...
    		list.selectedIndex=key==38?list.length-1:key==40?1:0;
    	},
    	keyProcessed:
    	function(ev) { // utility function
    		ev.cancelBubble=true; // IE4+
    		try{event.keyCode=0;}catch(e){}; // IE5
    		if (window.event) ev.returnValue=false; // IE6
    		if (ev.preventDefault) ev.preventDefault(); // moz/opera/konqueror
    		if (ev.stopPropagation) ev.stopPropagation(); // all
    		return false;
    	},
    	inputEscKeyHandler:
    	function(event,here,list,search,showlist) {
    		if (event.keyCode==27) {
    			if (showlist) { // clear input, reset list
    				here.value=here.defaultValue;
    				this.fillList(list,'',here.form.filter.value,search,0);
    			}
    			else if (list.style.display=="none") // clear input
    				here.value=here.defaultValue;
    			else list.style.display="none"; // hide list
    			return this.keyProcessed(event);
    		}
    		return true; // key bubbles up
    	},
    	inputKeyHandler:
    	function(event,here,quiet,search,showlist) {
    		var key=event.keyCode;
    		var list=here.form.list;
    		var filter=here.form.filter;
    		// non-printing chars bubble up, except for a few:
    		if (key<48) switch(key) {
    			// backspace=8, enter=13, space=32, up=38, down=40, delete=46
    			case 8: case 13: case 32: case 38: case 40: case 46: break; default: return true;
    		}
    		// blank input... if down/enter... fall through (list all)... else, and hide or reset list
    		if (!here.value.length && !(key==40 || key==13)) {
    			if (showlist) this.fillList(here.form.list,'',here.form.filter.value,search,0);
    			else list.style.display="none";
    			return this.keyProcessed(event);
    		}
    		// hide list if quiet, or below input minimum (and not showlist)
    		list.style.display=(!showlist&&(quiet||here.value.length<config.options.txtIncrementalSearchMin))?'none':'block';
    		// non-blank input... enter=show/create tiddler, SHIFT-enter=search for text
    		if (key==13 && here.value.length) return this.processItem(event.shiftKey?'*':here.value,here,list,showlist);
    		// up or down key, or enter with blank input... shows and moves to list...
    		if (key==38 || key==40 || key==13) { list.style.display="block"; list.focus(); }
    		this.fillList(list,here.value,filter.value,search,key);
    		return true; // key bubbles up
    	},
    	selectKeyHandler:
    	function(event,list,editfield,showlist) {
    		if (event.keyCode==27) // escape... hide list, move to edit field
    			{ editfield.focus(); list.style.display=showlist?'block':'none'; return this.keyProcessed(event); }
    		if (event.keyCode==13 && list.value.length) // enter... view selected item
    			{ this.processItem(list.value,editfield,list,showlist); return this.keyProcessed(event); }
    		return true; // key bubbles up
    	},
    	processItem:
    	function(title,here,list,showlist) {
    		if (!title.length) return;
    		list.style.display=showlist?'block':'none';
    		if (title=="*")	{ story.search(here.value); return false; } // do full-text search
    		if (!showlist) here.value=title;
    		story.displayTiddler(null,title); // show selected tiddler
    		return false;
    	}
    }
    //}}}

    /***
    |Name|HTMLFormattingPlugin|
    |Source|http://www.TiddlyTools.com/#HTMLFormattingPlugin|
    |Documentation|http://www.TiddlyTools.com/#HTMLFormattingPluginInfo|
    |Version|2.4.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|'HTML' formatter|
    |Description|embed wiki syntax formatting inside of HTML content|
    The ~HTMLFormatting plugin allows you to ''mix wiki-style formatting syntax within HTML formatted content'' by extending the action of the standard TiddlyWiki formatting handler.
    !!!!!Documentation
    >see [[HTMLFormattingPluginInfo]]
    !!!!!Revisions
    <<<
    2009.01.05 [2.4.0] in wikifyTextNodes(), pass w.highlightRegExp and w.tiddler to wikify() so that search term highlighting and tiddler-relative macro processing will work
    | see [[HTMLFormattingPluginInfo]] for additional revision details |
    2005.06.26 [1.0.0] Initial Release (as code adaptation - pre-dates TiddlyWiki plugin architecture!!)
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.HTMLFormattingPlugin= {major: 2, minor: 4, revision: 0, date: new Date(2009,1,5)};

    // 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];
    			// if <nowiki> is present, just let browser handle it!
    			if (html.indexOf('<nowiki>')!=-1)
    				createTiddlyElement(w.output,"span").innerHTML=html;
    			else {
    				// if <hide linebreaks> is present, suppress wiki-style literal handling of newlines
    				if (html.indexOf('<hide linebreaks>')!=-1) html=html.replace(/\n/g,' ');
    				// remove all \r's added by IE textarea and mask newlines and macro brackets
    				html=html.replace(/\r/g,'').replace(/\n/g,'\\n').replace(/<</g,'%%(').replace(/>>/g,')%%');
    				// create span, let browser parse HTML
    				var e=createTiddlyElement(w.output,"span"); e.innerHTML=html;
    				// then re-render text nodes as wiki-formatted content
    				wikifyTextNodes(e,w);
    			}
    			w.nextMatch = this.lookaheadRegExp.lastIndex; // continue parsing
    		}
    	}
    }

    // wikify #text nodes that remain after HTML content is processed (pre-order recursion)
    function wikifyTextNodes(theNode,w)
    {
    	function unmask(s) { return s.replace(/\%%\(/g,'<<').replace(/\)\%%/g,'>>').replace(/\\n/g,'\n'); }
    	switch (theNode.nodeName.toLowerCase()) {
    		case 'style': case 'option': case 'select':
    			theNode.innerHTML=unmask(theNode.innerHTML);
    			break;
    		case 'textarea':
    			theNode.value=unmask(theNode.value);
    			break;
    		case '#text':
    			var txt=unmask(theNode.nodeValue);
    			var newNode=createTiddlyElement(null,"span");
    			theNode.parentNode.replaceChild(newNode,theNode);
    			wikify(txt,newNode,highlightHack,w.tiddler);
    			break;
    		default:
    			for (var i=0;i<theNode.childNodes.length;i++)
    				wikifyTextNodes(theNode.childNodes.item(i),w); // recursion
    			break;
    	}
    }
    //}}}

    /%
    |Name|HideTiddlerBackground|
    |Source|http://www.TiddlyTools.com/#HideTiddlerBackground|
    |Version|0.0.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|script|
    |Requires|InlineJavascriptPlugin|
    |Overrides||
    |Description|hide a tiddler's background and border (if any)|

    Usage: <<tiddler HideTiddlerBackground>>

    %/<script>
    	var t=story.findContainingTiddler(place);
    	if (!t || t.id=="HideTiddlerBackground") return;
    	var nodes=t.getElementsByTagName("*");
    	for (var i=0; i<nodes.length; i++) if (hasClass(nodes[i],"viewer")) {
    		var s=nodes[i].style;
    		s.backgroundImage="none";
    		s.backgroundColor="transparent"
    		s.borderColor="transparent";
    		s.borderWidth=0;
    		s.margin=0;
    		s.padding=0;
    		break;
    	}
    </script>

    /%
    |Name|HideTiddlerTags|
    |Source|http://www.TiddlyTools.com/#HideTiddlerTags|
    |Version|0.0.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|script|
    |Requires|InlineJavascriptPlugin|
    |Overrides||
    |Description|hide a tiddler's tagged/tagging display elements|

    Usage: <<tiddler HideTiddlerTags>>

    %/<script>
    	var t=story.findContainingTiddler(place);
    	if (!t || t.id=="tiddlerHideTiddlerTags") return;
    	var nodes=t.getElementsByTagName("div");
    	for (var i=0; i<nodes.length; i++)
    		if (hasClass(nodes[i],"tagged"))
    			nodes[i].style.display="none";
    </script>

    /%
    |Name|HideTiddlerTitle|
    |Source|http://www.TiddlyTools.com/#HideTiddlerTitle|
    |Version|0.0.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|script|
    |Requires|InlineJavascriptPlugin|
    |Overrides||
    |Description|hide a tiddler's title display elements (name, dates, and author)|

    Usage: <<tiddler HideTiddlerTitle>>

    %/<script>
    	var t=story.findContainingTiddler(place);
    	if (!t || t.id=="tiddlerHideTiddlerTitle") return;
    	var nodes=t.getElementsByTagName("*");
    	for (var i=0; i<nodes.length; i++)
    		if (hasClass(nodes[i],"title")||hasClass(nodes[i],"subtitle"))
    			nodes[i].style.display="none";
    </script>

    /***
    |Name|ImageSizePlugin|
    |Source|http://www.TiddlyTools.com/#ImageSizePlugin|
    |Version|1.2.1|
    |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,formatter|
    |Requires||
    |Overrides|'image' formatter|
    |Description|adds support for resizing images|
    This plugin adds optional syntax to scale an image to a specified width and height and/or interactively resize the image with the mouse.
    !!!!!Usage
    <<<
    The extended image syntax is:
    {{{
    [img(w+,h+)[...][...]]
    }}}
    where ''(w,h)'' indicates the desired width and height (in CSS units, e.g., px, em, cm, in, or %). Use ''auto'' (or a blank value) for either dimension to scale that dimension proportionally (i.e., maintain the aspect ratio). You can also calculate a CSS value 'on-the-fly' by using a //javascript expression// enclosed between """{{""" and """}}""". Appending a plus sign (+) to a dimension enables interactive resizing in that dimension (by dragging the mouse inside the image). Use ~SHIFT-click to show the full-sized (un-scaled) image. Use ~CTRL-click to restore the starting size (either scaled or full-sized).
    <<<
    !!!!!Examples
    <<<
    {{{
    [img(100px+,75px+)[images/meow2.jpg]]
    }}}
    [img(100px+,75px+)[images/meow2.jpg]]
    {{{
    [<img(34%+,+)[images/meow.gif]]
    [<img(21% ,+)[images/meow.gif]]
    [<img(13%+, )[images/meow.gif]]
    [<img( 8%+, )[images/meow.gif]]
    [<img( 5% , )[images/meow.gif]]
    [<img( 3% , )[images/meow.gif]]
    [<img( 2% , )[images/meow.gif]]
    [img(  1%+,+)[images/meow.gif]]
    }}}
    [<img(34%+,+)[images/meow.gif]]
    [<img(21% ,+)[images/meow.gif]]
    [<img(13%+, )[images/meow.gif]]
    [<img( 8%+, )[images/meow.gif]]
    [<img( 5% , )[images/meow.gif]]
    [<img( 3% , )[images/meow.gif]]
    [<img( 2% , )[images/meow.gif]]
    [img(  1%+,+)[images/meow.gif]]
    {{tagClear{
    }}}
    <<<
    !!!!!Revisions
    <<<
    2009.02.24 [1.2.1] cleanup width/height regexp, use '+' suffix for resizing
    2009.02.22 [1.2.0] added stretchable images
    2008.01.19 [1.1.0] added evaluated width/height values
    2008.01.18 [1.0.1] regexp for "(width,height)" now passes all CSS values to browser for validation
    2008.01.17 [1.0.0] initial release
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.ImageSizePlugin= {major: 1, minor: 2, revision: 1, date: new Date(2009,2,24)};
    //}}}
    //{{{
    var f=config.formatters[config.formatters.findByField("name","image")];
    f.match="\\[[<>]?[Ii][Mm][Gg](?:\\([^,]*,[^\\)]*\\))?\\[";
    f.lookaheadRegExp=/\[([<]?)(>?)[Ii][Mm][Gg](?:\(([^,]*),([^\)]*)\))?\[(?:([^\|\]]+)\|)?([^\[\]\|]+)\](?:\[([^\]]*)\])?\]/mg;
    f.handler=function(w) {
    	this.lookaheadRegExp.lastIndex = w.matchStart;
    	var lookaheadMatch = this.lookaheadRegExp.exec(w.source)
    	if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
    		var floatLeft=lookaheadMatch[1];
    		var floatRight=lookaheadMatch[2];
    		var width=lookaheadMatch[3];
    		var height=lookaheadMatch[4];
    		var tooltip=lookaheadMatch[5];
    		var src=lookaheadMatch[6];
    		var link=lookaheadMatch[7];

    		// Simple bracketted link
    		var e = w.output;
    		if(link) { // LINKED IMAGE
    			if (config.formatterHelpers.isExternalLink(link)) {
    				if (config.macros.attach && config.macros.attach.isAttachment(link)) {
    					// see [[AttachFilePluginFormatters]]
    					e = createExternalLink(w.output,link);
    					e.href=config.macros.attach.getAttachment(link);
    					e.title = config.macros.attach.linkTooltip + link;
    				} else
    					e = createExternalLink(w.output,link);
    			} else
    				e = createTiddlyLink(w.output,link,false,null,w.isStatic);
    			addClass(e,"imageLink");
    		}

    		var img = createTiddlyElement(e,"img");
    		if(floatLeft) img.align="left"; else if(floatRight) img.align="right";
    		if(width||height) {
    			var x=width.trim(); var y=height.trim();
    			var stretchW=(x.substr(x.length-1,1)=='+'); if (stretchW) x=x.substr(0,x.length-1);
    			var stretchH=(y.substr(y.length-1,1)=='+'); if (stretchH) y=y.substr(0,y.length-1);
    			if (x.substr(0,2)=="{{")
    				{ try{x=eval(x.substr(2,x.length-4))} catch(e){displayMessage(e.description||e.toString())} }
    			if (y.substr(0,2)=="{{")
    				{ try{y=eval(y.substr(2,y.length-4))} catch(e){displayMessage(e.description||e.toString())} }
    			img.style.width=x.trim(); img.style.height=y.trim();
    			config.formatterHelpers.addStretchHandlers(img,stretchW,stretchH);
    		}
    		if(tooltip) img.title = tooltip;

    		// GET IMAGE SOURCE
    		if (config.macros.attach && config.macros.attach.isAttachment(src))
    			src=config.macros.attach.getAttachment(src); // see [[AttachFilePluginFormatters]]
    		else if (config.formatterHelpers.resolvePath) { // see [[ImagePathPlugin]]
    			if (config.browser.isIE || config.browser.isSafari) {
    				img.onerror=(function(){
    					this.src=config.formatterHelpers.resolvePath(this.src,false);
    					return false;
    				});
    			} else
    				src=config.formatterHelpers.resolvePath(src,true);
    		}
    		img.src=src;
    		w.nextMatch = this.lookaheadRegExp.lastIndex;
    	}
    }

    config.formatterHelpers.addStretchHandlers=function(e,stretchW,stretchH) {
    	e.title=((stretchW||stretchH)?'DRAG=stretch/shrink, ':'')
    		+'SHIFT-CLICK=show full size, CTRL-CLICK=restore initial size';
    	e.statusMsg='width=%0, height=%1';
    	e.style.cursor='move';
    	e.originalW=e.style.width;
    	e.originalH=e.style.height;
    	e.minW=Math.max(e.offsetWidth/20,10);
    	e.minH=Math.max(e.offsetHeight/20,10);
    	e.stretchW=stretchW;
    	e.stretchH=stretchH;
    	e.onmousedown=function(ev) { var ev=ev||window.event;
    		this.sizing=true;
    		this.startX=!config.browser.isIE?ev.pageX:(ev.clientX+findScrollX());
    		this.startY=!config.browser.isIE?ev.pageY:(ev.clientY+findScrollY());
    		this.startW=this.offsetWidth;
    		this.startH=this.offsetHeight;
    		return false;
    	};
    	e.onmousemove=function(ev) { var ev=ev||window.event;
    		if (this.sizing) {
    			var s=this.style;
    			var currX=!config.browser.isIE?ev.pageX:(ev.clientX+findScrollX());
    			var currY=!config.browser.isIE?ev.pageY:(ev.clientY+findScrollY());
    			var newW=(currX-this.offsetLeft)/(this.startX-this.offsetLeft)*this.startW;
    			var newH=(currY-this.offsetTop )/(this.startY-this.offsetTop )*this.startH;
    			if (this.stretchW) s.width =Math.floor(Math.max(newW,this.minW))+'px';
    			if (this.stretchH) s.height=Math.floor(Math.max(newH,this.minH))+'px';
    			clearMessage(); displayMessage(this.statusMsg.format([s.width,s.height]));
    		}
    		return false;
    	};
    	e.onmouseup=function(ev) { var ev=ev||window.event;
    		if (ev.shiftKey) { this.style.width=this.style.height=''; }
    		if (ev.ctrlKey)  { this.style.width=this.originalW; this.style.height=this.originalH; }
    		this.sizing=false;
    		clearMessage();
    		return false;
    	};
    	e.onmouseout=function(ev) { var ev=ev||window.event;
    		this.sizing=false;
    		clearMessage();
    		return false;
    	};
    }
    //}}}

    /***
    |Name|InlineJavascriptPlugin|
    |Source|http://www.TiddlyTools.com/#InlineJavascriptPlugin|
    |Documentation|http://www.TiddlyTools.com/#InlineJavascriptPluginInfo|
    |Version|1.9.5|
    |Author|Eric Shulman|
    |License|http://www.TiddlyTools.com/#LegalStatements|
    |~CoreVersion|2.1|
    |Type|plugin|
    |Requires||
    |Overrides||
    |Description|Insert Javascript executable code directly into your tiddler content.|
    ''Call directly into TW core utility routines, define new functions, calculate values, add dynamically-generated TiddlyWiki-formatted output'' into tiddler content, or perform any other programmatic actions each time the tiddler is rendered.
    !!!!!Documentation
    >see [[InlineJavascriptPluginInfo]]
    !!!!!Revisions
    <<<
    2009.04.11 [1.9.5] pass current tiddler object into wrapper code so it can be referenced from within 'onclick' scripts
    2009.02.26 [1.9.4] in $(), handle leading '#' on ID for compatibility with JQuery syntax
    |please see [[InlineJavascriptPluginInfo]] for additional revision details|
    2005.11.08 [1.0.0] initial release
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.InlineJavascriptPlugin= {major: 1, minor: 9, revision: 5, date: new Date(2009,4,11)};

    config.formatters.push( {
    	name: "inlineJavascript",
    	match: "\\<script",
    	lookahead: "\\<script(?: src=\\\"((?:.|\\n)*?)\\\")?(?: label=\\\"((?:.|\\n)*?)\\\")?(?: title=\\\"((?:.|\\n)*?)\\\")?(?: key=\\\"((?:.|\\n)*?)\\\")?( show)?\\>((?:.|\\n)*?)\\</script\\>",

    	handler: 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 src=lookaheadMatch[1];
    			var label=lookaheadMatch[2];
    			var tip=lookaheadMatch[3];
    			var key=lookaheadMatch[4];
    			var show=lookaheadMatch[5];
    			var code=lookaheadMatch[6];
    			if (src) { // external script library
    				var script = document.createElement("script"); script.src = src;
    				document.body.appendChild(script); document.body.removeChild(script);
    			}
    			if (code) { // inline code
    				if (show) // display source in tiddler
    					wikify("{{{\n"+lookaheadMatch[0]+"\n}}}\n",w.output);
    				if (label) { // create 'onclick' command link
    					var link=createTiddlyElement(w.output,"a",null,"tiddlyLinkExisting",wikifyPlainText(label));
    					var fixup=code.replace(/document.write\s*\(/gi,'place.bufferedHTML+=(');
    					link.code="function _out(place,tiddler){"+fixup+"\n};_out(this,this.tiddler);"
    					link.tiddler=w.tiddler;
    					link.onclick=function(){
    						this.bufferedHTML="";
    						try{ var r=eval(this.code);
    							if(this.bufferedHTML.length || (typeof(r)==="string")&&r.length)
    								var s=this.parentNode.insertBefore(document.createElement("span"),this.nextSibling);
    							if(this.bufferedHTML.length)
    								s.innerHTML=this.bufferedHTML;
    							if((typeof(r)==="string")&&r.length) {
    								wikify(r,s,null,this.tiddler);
    								return false;
    							} else return r!==undefined?r:false;
    						} catch(e){alert(e.description||e.toString());return false;}
    					};
    					link.setAttribute("title",tip||"");
    					var URIcode='javascript:void(eval(decodeURIComponent(%22(function(){try{';
    					URIcode+=encodeURIComponent(encodeURIComponent(code.replace(/\n/g,' ')));
    					URIcode+='}catch(e){alert(e.description||e.toString())}})()%22)))';
    					link.setAttribute("href",URIcode);
    					link.style.cursor="pointer";
    					if (key) link.accessKey=key.substr(0,1); // single character only
    				}
    				else { // run script immediately
    					var fixup=code.replace(/document.write\s*\(/gi,'place.innerHTML+=(');
    					var c="function _out(place,tiddler){"+fixup+"\n};_out(w.output,w.tiddler);";
    					try	 { var out=eval(c); }
    					catch(e) { out=e.description?e.description:e.toString(); }
    					if (out && out.length) wikify(out,w.output,w.highlightRegExp,w.tiddler);
    				}
    			}
    			w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
    		}
    	}
    } )
    //}}}

    // // Backward-compatibility for TW2.1.x and earlier
    //{{{
    if (typeof(wikifyPlainText)=="undefined") window.wikifyPlainText=function(text,limit,tiddler) {
    	if(limit > 0) text = text.substr(0,limit);
    	var wikifier = new Wikifier(text,formatter,null,tiddler);
    	return wikifier.wikifyPlain();
    }
    //}}}

    // // GLOBAL FUNCTION: $(...) -- 'shorthand' convenience syntax for document.getElementById()
    //{{{
    if (typeof($)=='undefined') { function $(id) { return document.getElementById(id.replace(/^#/,'')); } }
    //}}}

    /***
    |''Name:''|LoadRemoteFileThroughProxy (previous LoadRemoteFileHijack)|
    |''Description:''|When the TiddlyWiki file is located on the web (view over http) the content of [[SiteProxy]] tiddler is added in front of the file url. If [[SiteProxy]] does not exist "/proxy/" is added. |
    |''Version:''|1.1.0|
    |''Date:''|mar 17, 2007|
    |''Source:''|http://tiddlywiki.bidix.info/#LoadRemoteFileHijack|
    |''Author:''|BidiX (BidiX (at) bidix (dot) info)|
    |''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
    |''~CoreVersion:''|2.2.0|
    ***/
    //{{{
    version.extensions.LoadRemoteFileThroughProxy = {
     major: 1, minor: 1, revision: 0,
     date: new Date("mar 17, 2007"),
     source: "http://tiddlywiki.bidix.info/#LoadRemoteFileThroughProxy"};

    if (!window.bidix) window.bidix = {}; // bidix namespace
    if (!bidix.core) bidix.core = {};

    bidix.core.loadRemoteFile = loadRemoteFile;
    loadRemoteFile = function(url,callback,params)
    {
     if ((document.location.toString().substr(0,4) == "http") && (url.substr(0,4) == "http")){
     url = store.getTiddlerText("SiteProxy", "/proxy/") + url;
     }
     return bidix.core.loadRemoteFile(url,callback,params);
    }
    //}}}

    {{groupbox{/%

    JOURNALS
    %/<<tiddler MainMenu##showList with: 日志 日志 日志查看器 "新建一篇日志"
    	[['新日志 - '+new Date().formatString('YYYY0MM0DD0hh0mm0ss')]] BlankJournal>>/%

    %/{{span{/% LIMITS RESIZER TO JUST THESE LISTBOXES

    BOOKMARKS
    %/<<tiddler MainMenu##showList with: bookmark 书签 迷你浏览器 "新建一个书签"
    	[['新书签']] BlankBookmark>>/%

    FAQs
    %/<<tiddler MainMenu##showList with: faq FAQs FAQ查看器 "输入FAQ的标题"
    	[['新FAQ']] BlankFAQ>>/%

    %/<<resizeListbox>>}}}/% ADDS RESIZER TO LISTBOXES
    %/}}}/% END GROUPBOX

    CALENDAR
    %/{{center big{
    <<slider chkShowCalendar [[MainMenu##calendarSlider]] "日历" "显示每天的更新内容">>}}}/%

    INFO LINKS
    %/{{center medium{[[关于本站|关于本站]] | [[联系作者|联系作者]]}}}/%

    SITE NEWS
    %/{{center fine italic{<hr>@@font-family:Trebuchet MS;<<QOTD SiteNews norandom 60000>>@@<hr>}}}/%

    TOGGLE SINGLEPAGE
    %/{{center fine{<<option chkSinglePageMode>> 一次只显示一篇帖子}}}/%

    HIDDEN SECTIONS

    !showList
    {{floatright{<script>
    	place.style.display=readOnly?'none':'inline';
    </script><<clickify newTiddler
    	text:{{ store.getTiddlerText('$6','').replace(/\$(xyzzy)?1/g,new Date().formatString('DDD, MMM DDth, YYYY hh12:0mm:0ss am')) }}
    	label:"add" title:{{prompt('$4',$5)}} tag:$1>>}}}''[[$2|$3]]''
    {{transparent{<<gotoTiddler showlist inputstyle:"font-size:85%;width:97%" liststyle:"font-size:85%;height:7em;width:99%;" filter:$1>>}}}
    !end

    !calendarSlider
    {{normal{{{center{<<calendar thismonth>>}}}}}}
    !end

    %/

    /***
    |Name|MatchTagsPlugin|
    |Source|http://www.TiddlyTools.com/#MatchTagsPlugin|
    |Documentation|http://www.TiddlyTools.com/#MatchTagsPluginInfo|
    |Version|2.0.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|'tag matching' with full boolean expressions (AND, OR, NOT, and nested parentheses)|
    !!!!!Documentation
    > see [[MatchTagsPluginInfo]]
    !!!!!Revisions
    <<<
    2008.09.04 [2.0.0] added "report" and "panel" options to generate formatted results and store in a tiddler.  Also, added config.macros.matchTags.formatList(place,fmt,sep) API to return formatted output for use with other plugins/scripts
    | please see [[MatchTagsPluginInfo]] for additional revision details |
    2008.02.28 [1.0.0] initial release
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.MatchTagsPlugin= {major: 2, minor: 0, revision: 0, date: new Date(2008,9,4)};

    // store.getMatchingTiddlers() processes boolean expressions for tag matching
    //    sortfield (optional) sets sort order for tiddlers - default=title
    //    tiddlers (optional) use alternative set of tiddlers (instead of current store)
    TiddlyWiki.prototype.getMatchingTiddlers = function(tagexpr,sortfield,tiddlers) {

    	var debug=config.options.chkDebug; // abbreviation
    	var cmm=config.macros.matchTags; // abbreviation
    	var r=[]; // results are an array of tiddlers
    	var tids=tiddlers||store.getTiddlers(sortfield||"title");
    	if (tiddlers && sortfield) store.sortTiddlers(tids,sortfield);
    	if (debug) displayMessage(cmm.msg1.format([tids.length]));

    	// try simple lookup to quickly find single tags or tags that
    	// contain boolean operators as literals, e.g. "foo and bar"
    	for (var t=0; t<tids.length; t++)
    		if (tids[t].isTagged(tagexpr)) r.pushUnique(tids[t]);
    	if (r.length) {
    		if (debug) displayMessage(cmm.msg4.format([r.length,tagexpr]));
    		return r;
    	}

    	// convert expression into javascript code with regexp tests,
    	// so that "tag1 AND ( tag2 OR NOT tag3 )" becomes
    	// "/\~tag1\~/.test(...) && ( /\~tag2\~/.test(...) || ! /\~tag3\~/.test(...) )"

    	// normalize whitespace, tokenize operators, delimit with "~"
    	var c=tagexpr.trim(); // remove leading/trailing spaces
    	c = c.replace(/\s+/ig," "); // reduce multiple spaces to single spaces
    	c = c.replace(/\(\s?/ig,"~(~"); // open parens
    	c = c.replace(/\s?\)/ig,"~)~"); // close parens
    	c = c.replace(/(\s|~)?&&(\s|~)?/ig,"~&&~"); // &&
    	c = c.replace(/(\s|~)AND(\s|~)/ig,"~&&~"); // AND
    	c = c.replace(/(\s|~)?\|\|(\s|~)?/ig,"~||~"); // ||
    	c = c.replace(/(\s|~)OR(\s|~)/ig,"~||~"); // OR
    	c = c.replace(/(\s|~)?!(\s|~)?/ig,"~!~"); // !
    	c = c.replace(/(^|~|\s)NOT(\s|~)/ig,"~!~"); // NOT
    	c = c.replace(/(^|~|\s)NOT~\(/ig,"~!~("); // NOT(
    	// change tag terms to regexp tests
    	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
    		if (t==config.macros.matchTags.untaggedKeyword)
    			terms[i]="tiddlertags=='~~'"; // 'untagged' tiddlers
    		else
    			terms[i]="/\\~"+t+"\\~/.test(tiddlertags)";
    	}
    	c=terms.join(" ");
    	if (debug) { displayMessage(cmm.msg2.format([tagexpr])); displayMessage(cmm.msg3.format([c])); }

    	// scan tiddlers for matches
    	for (var t=0; t<tids.length; t++) {
    	 	// assemble tags from tiddler into string "~tag1~tag2~tag3~"
    		var tiddlertags = "~"+tids[t].tags.join("~")+"~";
    		try { if(eval(c)) r.push(tids[t]); } // test tags
    		catch(e) { // error in test
    			displayMessage(cmm.msg2.format([tagexpr]));
    			displayMessage(cmm.msg3.format([c]));
    			displayMessage(e.toString());
    			break; // skip remaining tiddlers
    		}
    	}
    	if (debug) displayMessage(cmm.msg4.format([r.length,tagexpr]));
    	return r;
    }
    //}}}
    //{{{
    config.macros.matchTags = {
    	msg1: "scanning %0 input tiddlers",
    	msg2: "looking for '%0'",
    	msg3: "using expression: '%0'",
    	msg4: "found %0 tiddlers matching '%1'",
    	noMatch: "no matching tiddlers",
    	untaggedKeyword: "-",

    	untaggedLabel: "no tags",
    	untaggedPrompt: "show tiddlers with no tags",
    	defTiddler: "MatchingTiddlers",
    	defFormat: "%0",
    	defSeparator: "\n",
    	reportHeading: "Found %0 tiddlers tagged with: '{{{%1}}}'\n----\n",
    	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    		var mode=params[0]?params[0].toLowerCase():'';
    		if (mode=="inline")
    			params.shift();
    		if (mode=="report" || mode=="panel") {
    			params.shift();
    			var target=params.shift()||this.defTiddler;
    		}
    		if (mode=="popup") {
    			params.shift();
    			if (params[0]&&params[0].substr(0,6)=="label:") var label=params.shift().substr(6);
    			if (params[0]&&params[0].substr(0,7)=="prompt:") var prompt=params.shift().substr(7);
    		} else {
    			var fmt=(params.shift()||this.defFormat).unescapeLineBreaks();
    			var sep=(params.shift()||this.defSeparator).unescapeLineBreaks();
    		}
    		var sortBy="+title";
    		if (params[0]&&params[0].substr(0,5)=="sort:") sortBy=params.shift().substr(5);
    		var expr = params.join(" ");
    		if (mode!="panel" && (!expr||!expr.trim().length)) return;
    		if (expr==this.untaggedKeyword)
    			{ var label=this.untaggedLabel; var prompt=this.untaggedPrompt };
    		switch (mode) {
    			case "popup": this.createPopup(place,label,expr,prompt,sortBy); break;
    			case "panel": this.createPanel(place,expr,fmt,sep,sortBy,target); break;
    			case "report": this.createReport(target,expr,fmt,sep,sortBy); break;
    			case "inline": default: this.createInline(place,expr,fmt,sep,sortBy); break;
    		}
    	},
    	formatList: function(tids,fmt,sep) {
    		var out=[];
    		for (var t=0; t<tids.length; t++) {
    			var title="[["+tids[t].title+"]]";
    			var who=tids[t].modifier;
    			var when=tids[t].modified.toLocaleString();
    			var text=tids[t].text;
    			var first=tids[t].text.split("\n")[0];
    			var desc=store.getTiddlerSlice(tids[t].title,"description");
    			desc=desc||store.getTiddlerSlice(tids[t].title,"Description");
    			desc=desc||store.getTiddlerText(tids[t].title+"##description");
    			desc=desc||store.getTiddlerText(tids[t].title+"##Description");
    			out.push(fmt.format([title,who,when,text,first,desc]));
    		}
    		return out.join(sep);
    	},
    	createInline: function(place,expr,fmt,sep,sortBy) {
    		wikify(this.formatList(store.sortTiddlers(store.getMatchingTiddlers(expr),sortBy),fmt,sep),place);
    	},
    	createPopup: function(place,label,expr,prompt,sortBy) {
    		var btn=createTiddlyButton(place,
    			(label||expr).format([expr]),
    			(prompt||config.views.wikified.tag.tooltip).format([expr]),
    			function(ev){ return config.macros.matchTags.showPopup(this,ev||window.event); });
    		btn.setAttribute("sortBy",sortBy);
    		btn.setAttribute("expr",expr);
    	},
    	showPopup: function(here,ev) {
    		var p=Popup.create(here); if (!p) return false;
    		var tids=store.getMatchingTiddlers(here.getAttribute("expr"));
    		store.sortTiddlers(tids,here.getAttribute("sortBy"));
    		var list=[]; for (var t=0; t<tids.length; t++) list.push(tids[t].title);
    		if (!list.length) createTiddlyText(p,this.noMatch);
    		else {
    			var b=createTiddlyButton(createTiddlyElement(p,"li"),
    				config.views.wikified.tag.openAllText,
    				config.views.wikified.tag.openAllTooltip,
    				function() {
    					var list=this.getAttribute("list").readBracketedList();
    					story.displayTiddlers(null,tids);
    				});
    			b.setAttribute("list","[["+list.join("]] [[")+"]]");
    			createTiddlyElement(p,"hr");
    		}
    		var out=this.formatList(tids," &nbsp;%0&nbsp; ","\n"); wikify(out,p);
    		Popup.show(p,false);
    		ev.cancelBubble=true;
    		if(ev.stopPropagation) ev.stopPropagation();
    		return false;
    	},
    	createReport: function(target,expr,fmt,sep,sortBy) {
    		var tids=store.sortTiddlers(store.getMatchingTiddlers(expr),sortBy);
    		if (!tids.length) { displayMessage('no matches for: '+expr); return false; }
    		var msg=config.messages.overwriteWarning.format([target]);
    		if (store.tiddlerExists(target) && !confirm(msg)) return false;
    		var out=this.reportHeading.format([tids.length,expr])
    		out+=this.formatList(tids,fmt,sep);
    		store.saveTiddler(target,target,out,config.options.txtUserName,new Date(),[],{});
    		story.closeTiddler(target); story.displayTiddler(null,target);
    	},
    	createPanel: function(place,expr,fmt,sep,sortBy,tid) {
    		var html="<form style='display:inline'><!-- \
    			--><input type='text'    name='expr' style='width:55%' title='tag expression'><!-- \
    			--><input type='text'    name='fmt'  style='width:10%' title='list item format'><!-- \
    			--><input type='text'    name='sep'  style='width:5%'  title='list item separator'><!-- \
    			--><input type='text'    name='tid'  style='width:20%' title='target tiddler title'><!-- \
    			--><input type='button'  name='go'   style='width:8%'  value='go' onclick=\" \
    				var expr=this.form.expr.value; \
    				if (!expr.length) { alert('Enter a boolean tag expression'); return false; } \
    				var fmt=this.form.fmt.value; \
    				if (!fmt.length) { alert('Enter the list item output format'); return false; } \
    				var sep=this.form.sep.value.unescapeLineBreaks(); \
    				var tid=this.form.tid.value; \
    				if (!tid.length) { alert('Enter a target tiddler title'); return false; } \
    				config.macros.matchTags.createReport(tid,expr,fmt,sep,'title'); \
    				return false;\"> \
    			</form>";
    		var s=createTiddlyElement(place,"span"); s.innerHTML=html;
    		var f=s.getElementsByTagName("form")[0];
    		f.expr.value=expr; f.fmt.value=fmt; f.sep.value=sep.escapeLineBreaks(); f.tid.value=tid;
    	}
    };
    //}}}
    //{{{
    // SHADOW TIDDLER for displaying default panel input form
    config.shadowTiddlers.MatchTags="{{smallform{<<matchTags panel>>}}}";
    //}}}
    //{{{
    // TWEAK core filterTiddlers() for enhanced boolean matching in [tag[...]] syntax:
    // use getMatchingTiddlers instead getTaggedTiddlers
    var fn=TiddlyWiki.prototype.filterTiddlers;
    fn=fn.toString().replace(/getTaggedTiddlers/g,"getMatchingTiddlers");
    eval("TiddlyWiki.prototype.filterTiddlers="+fn);
    //}}}
    //{{{
    // REDEFINE core handler for enhanced boolean matching in tag:"..." paramifier
    // use filterTiddlers() instead of getTaggedTiddlers() to get list of tiddlers.
    config.paramifiers.tag = {
    	onstart: function(v) {
    		var tagged = store.filterTiddlers("[tag["+v+"]]");
    		story.displayTiddlers(null,tagged,null,false,null);
    	}
    };
    //}}}

    <<tiddler BookmarkList>>

    /***
    |Name|MiniBrowserPlugin|
    |Source|http://www.TiddlyTools.com/#MiniBrowserPlugin|
    |Documentation|http://www.TiddlyTools.com/#MiniBrowserPluginInfo|
    |Version|1.5.1|
    |Author|Eric Shulman|
    |License|http://www.TiddlyTools.com/#LegalStatements|
    |~CoreVersion|2.2|
    |Type|plugin|
    |Requires|PlayerPlugin (optional, recommended)|
    |Description|embedded browser-in-browser with favorites lists and media support|
    !!!!!Documentation
    >see [[MiniBrowserPluginInfo]]
    !!!!!Configuration
    >Default mini browser size:
    >width: <<option txtMiniBrowserWidth>> height: <<option txtMiniBrowserHeight>>
    !!!!!Revisions
    <<<
    2009.07.03 [1.5.1] added onclick handling to 'n of m' button.  also, if noedit mode, add line numbers to bookmarks droplist items
    2009.06.08 [1.5.0] added optional 'noedit' mode: replaces add/del/edit buttons with next/previous navigation.
    |see [[MiniBrowserPluginInfo]] for additional revision details|
    2007.10.15 [1.0.0] combined MiniBrowser and MediaCenter inline scripts and converted to true plugin
    2006.03.01 [0.0.0] inline script
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.MiniBrowserPlugin={major: 1, minor: 5, revision: 1, date: new Date(2009,7,3)};

    config.shadowTiddlers.MiniBrowser='<<miniBrowser>>';
    config.options.txtMiniBrowserWidth=config.options.txtMiniBrowserWidth||'100%';
    config.options.txtMiniBrowserHeight=config.options.txtMiniBrowserHeight||'480';
    config.macros.miniBrowser= {
    	favoritesList: 'MiniBrowserList',
    	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    		var noPlayer=params[0]&&params[0].toLowerCase()=='noplayer'; if (noPlayer) params.shift();
    		var noEdit  =params[0]&&params[0].toLowerCase()=='noedit';   if (noEdit)   params.shift();
    		var expand  =params[0]&&params[0].toLowerCase()=='expand';   if (expand)   params.shift();
    		var hideControls=params[0]&&params[0].toLowerCase()=='hidecontrols'; if (hideControls) params.shift();
    		var url=(params[0]&&!store.tiddlerExists(params[0]))?params.shift():'';
    		hideControls=hideControls&&url.length; // no initial URL, show controls anyway
    		if (!config.macros.player) noPlayer=true; // PlayerPlugin not installed
    		var w=config.options.txtMiniBrowserWidth;
    		var h=config.options.txtMiniBrowserHeight;

    		// create form
    		var guid=new Date().getTime()+Math.random().toString(); // globally unique ID
    		var html=store.getTiddlerText('MiniBrowserPlugin##html');
    		html=html.replace(/%id%/g,guid)
    			.replace(/%noplayer%/g,noPlayer?'true':'')
    			.replace(/%noedit%/g,noEdit||readOnly?'none':'inline')
    			.replace(/%shownav%/g,noEdit||readOnly?'inline':'none')
    			.replace(/%hidecontrols%/g,hideControls?'none':'block')
    			.replace(/%bookmarksize%/g,(expand?70:20)+'%')
    			.replace(/%urlsize%/g,(expand?69.5:20)+'%')
    			.replace(/%linebreak%/g,expand?'<br>':'')
    			.replace(/%favorites%/g,params[0]||config.macros.miniBrowser.favoritesList);
    		createTiddlyElement(place,'span').innerHTML=html;

    		// init form
    		function $(i){return document.getElementById(i)}; // abbrev
    		$('minibrowser_controls_'+guid).style.display=hideControls?'none':'block';
    		$('minibrowser_resize_'+guid).style.display=hideControls?'none':'block';
    		$('minibrowser_togglecontrols_'+guid).checked=!hideControls;
    		$('minibrowser_form_'+guid).url.value=url;
    		$('minibrowser_form_'+guid).w.value=w;
    		$('minibrowser_form_'+guid).h.value=h;
    		if (noPlayer) { // hide type list no PlayerPlugin
    			$('minibrowser_type_'+guid).style.display='none';
    			$('minibrowser_url_'+guid).style.width='36%';
    		}

    		// load bookmarks droplist from HR-separated tiddler contents
    		var b=$('minibrowser_bookmarks_'+guid);
    		while (b.options[1]) b.options[1]=null; // clear list but leave 'prompt' item
    		var p; while (p=params.shift()) this.getFavorites(b,p,noEdit); // load custom bookmarks
    		if (b.length<2) this.getFavorites(b,config.macros.miniBrowser.favoritesList,noEdit); // default list
    		$('minibrowser_nav_'+guid).value='1 out of '+b.length;

    		// load initial URL (if any)
    		var place=$('minibrowser_player_'+guid);
    		this.load(place,guid,'','',w,h,true,noPlayer);
    		this.go($('minibrowser_form_'+guid));
    	},
    	getFavorites: function(list,tid,noEdit) {
    		var txt=store.getTiddlerText(tid); if (!txt||!txt.trim().length) return;
    		txt=this.getWikifiedData(txt);
    		var parts=txt.split('\n----\n');
    		for (var p=0; p<parts.length; p++) {
    			var lines=parts[p].split('\n');
    			var label=lines.shift()||''; // 1st line=display text
    			var value=lines.shift()||''; // 2nd line=item value
    			var indent=value&&value.length?'\xa0\xa0':'';
    			var prefix=value.length&&noEdit?list.length+1+': ':'';
    			list.options[list.length]=new Option(prefix+indent+label,value,false,false);
    		}
    	},
    	getWikifiedData: // wikify content, then extract text WITH newlines and HRs included
    	function(txt) {
    		var e=createTiddlyElement(document.body,'div'); wikify(txt,e);
    		var breaks=e.getElementsByTagName('br');
    		for (var b=0; b<breaks.length; b++)
    			breaks[b].parentNode.insertBefore(document.createTextNode('\n'),breaks[b]);
    		var lines=e.getElementsByTagName('hr');
    		for (var l=0; l<lines.length; l++)
    			lines[l].parentNode.insertBefore(document.createTextNode('----\n'),lines[l]);
    		var items=e.getElementsByTagName('li');
    		for (var i=0; i<items.length; i++)
    			items[i].parentNode.insertBefore(document.createTextNode('\n'),items[i]);
    		var txt=getPlainText(e);
    		removeNode(e);
    		return txt.replace(/\r*/g,'').replace(/\n\n/g,'\n');
    	},
    	load: function(place,id,type,url,w,h,showcontrols,noPlayer) {
    		if (!noPlayer)
    			config.macros.player.loadURL(place,id,type,url,w,h,showcontrols);
    		else { // force IFRAME-only display
    			if (!place) place=document.getElementById(id).parentNode;
    			var fmt="<iframe name='%0' id='%1' src='%2' width='%3' height='%4' \
    				style='background:#fff;border:1px solid'></iframe>";
    			place.innerHTML=fmt.format([id,url,w,h]);
    		}
    	},
    	go: function(f) {
    		var url=f.url.value.trim();
    		if (!url.length) url=f.url.value=f.bookmarks.value.trim();
    		if (!url.length) { this.done(f); return false; }
    		var id=f.playerID.value;
    		document.getElementById('minibrowser_player_'+id).style.display='block';
    		document.getElementById('minibrowser_controls2_'+id).style.display='block';
    		this.load(null,id,f.type.value,f.url.value,f.w.value,f.h.value,f.ctrls.checked,f.noPlayer.value=='true');
    		var matched=false; for (var i=0; i<f.bookmarks.options.length; i++) // select matching bookmark
    			if (f.bookmarks.options[i].value==url) { f.bookmarks.selectedIndex=i; matched=true; break; }
    		if (!matched) f.bookmarks.selectedIndex=0;
    		f.done.disabled=false;
    		return false;
    	},
    	done: function(f) {
    		var id=f.playerID.value;
    		this.load(null,id,null,null,f.w.value,0,f.ctrls.checked,f.noPlayer.value=='true');
    		document.getElementById('minibrowser_player_'+id).style.display='none';
    		document.getElementById('minibrowser_controls2_'+id).style.display='none';
    		f.done.disabled=true;
    		return false;
    	},
    	fit: function(place) {
    		// fudge factor to account for the other controls + padding + borders.  ADJUST THIS VALUE TO FIT LAYOUT
    		var trim=89;
    		var t=story.findContainingTiddler(place);
    		if (!t) { t=place; while (t && t.className!='floatingPanel') t=t.parentNode; } if (!t) return;
    		var w='100%'; // horizontal stretching via CSS works, but vertical stretching doesn't... so:
    		var h=t.offsetHeight-trim; // workaround: get containing panel/tiddler height and subtract trim height
    		var f=place.form;
    		this.load(null,f.playerID.value,f.type.value,f.url.value,w,h,f.ctrls.checked,f.noPlayer.value=='true');
    		place.form.w.value=w; place.form.h.value=h; // update width/height input fields
    	},
    	add: function(place,title) {
    		var v=place.value; if (!v.length) return;
    		var d=prompt('Please enter a description for\n'+place.value); if (!d || !d.length) return;
    		var who=config.options.txtUserName;
    		var when=new Date();
    		var tid=store.getTiddler(title);
    		var txt='%0\n%1\n----\n%2'.format([d,v,tid?tid.text:'']);
    		store.saveTiddler(title,title,txt,who,when,tid?tid.tags:[],tid?tid.fields:{});
    		if (!tid) story.displayTiddler(story.findContainingTiddler(place),title);
    		else story.refreshTiddler(title,1,true);
    		var here=story.findContainingTiddler(place);
    		if (here) story.refreshTiddler(here.getAttribute('tiddler'),1,true);
    	},
    	del: function(place,title) {
    		var v=place.value; if (!v.length) return;
    		var d=place.options[place.selectedIndex].text; if (!d.length) return;
    		if (!confirm('Are you sure you want to remove this favorite?\n\n'+d+'\n'+v)) return;
    		var tid=store.getTiddler(title); if (!tid) return;
    		var who=config.options.txtUserName;
    		var when=new Date();
    		var pat='%0\n%1\n----\n'.format([d.replace(/\xa0/g,''),v]); var re=new RegExp(pat,'i');
    		var txt=tid.text.replace(re,'');
    		store.saveTiddler(title,title,txt,who,when,tid?tid.tags:[],tid?tid.fields:{});
    		story.refreshTiddler(title,1,true);
    		var here=story.findContainingTiddler(place);
    		if (here) story.refreshTiddler(here.getAttribute('tiddler'),1,true);
    	}
    }
    //}}}
    /***
    //{{{
    !html
    <form id='minibrowser_form_%id%' style='display:block;margin:0;padding:0' onsubmit='return config.macros.miniBrowser.go(this);'><!--
    --><nobr><input type='hidden' name='playerID' value='%id%'><input type='hidden' name='noPlayer' value='%noplayer%'><!--
    --><div id='minibrowser_controls_%id%' style='display:%hidecontrols%'><!--
    --><input type='button' value='<' title='back' style='width:3%'
    	onclick='try{window.frames["player_%id%"].history.go(-1)}catch(e){window.history.go(-1)}' ><!--
    --><input type='button' value='>' title='forward' style='width:3%'
    	onclick='try{window.frames["player_%id%"].history.go(+1)}catch(e){window.history.go(+1)}'><!--
    --><input type='button' value='+' title='refresh'style='width:3%'
    	onclick='try{window.frames["player_%id%"].location.reload()}catch(e){;}'><!--
    --><input type='button' value='x' title='stop'style='width:3%'
    	onclick='window.stop()'><!--
    --><select name='bookmarks' id='minibrowser_bookmarks_%id%' size='1' style='width:%bookmarksize%'
    	onchange='this.form.url.value=this.value;
    		this.form.nav.value="%0 out of %1".format([this.selectedIndex+1,this.length]);
    		this.form.nav.title="reload %0".format([this.options[this.selectedIndex].text]);
    		return config.macros.miniBrowser.go(this.form);'><!--
    --><option value=''>bookmarks...</option><!--
    --></select><!--
    --><span style='display:%noedit%'><!--
    --><input type='button' value='add' title='add URL to the bookmarks' style='width:6%'
    	favorites="%favorites%"
    	onclick='config.macros.miniBrowser.add(this.form.url,this.getAttribute("favorites"));'><!--
    --><input type='button' value='del' title='remove URL from the bookmarks' style='width:6%'
    	favorites="%favorites%"
    	onclick='config.macros.miniBrowser.del(this.form.bookmarks,this.getAttribute("favorites"));'><!--
    --><input type='button' value='edit' title='edit the bookmarks list' style='width:6%'
    	favorites="%favorites%"
    	onclick='story.displayTiddler(null,this.getAttribute("favorites"),2)'><!--
    --></span><!--
    --><span style='display:%shownav%'><!--
    --><input type='button' value='&#x25C4;' title='view previous bookmark' style='width:3%'
    	onclick='var b=document.getElementById("minibrowser_bookmarks_%id%");
    		b.selectedIndex=Math.max(b.selectedIndex-1,0); b.onchange();'><!--
    --><input name='nav' id='minibrowser_nav_%id%'
    	type='button' value='N out of MM' title='enter a bookmark number' style='width:12%'
    	onclick='var b=this.form.bookmarks;
    		var i=prompt("Enter a bookmark number (1-"+b.length+")",b.selectedIndex+1);
    		if (i && i<b.length) { b.selectedIndex=i-1; b.onchange(); }'><!--
    --><input type='button' value='&#x25BA;' title='view next bookmark' style='width:3%'
    	onclick='var b=document.getElementById("minibrowser_bookmarks_%id%");
    		b.selectedIndex=Math.min(b.selectedIndex+1,b.length); b.onchange();'><!--
    --></span><!--
    -->%linebreak%<!--
    --><select name='type' id='minibrowser_type_%id%' size='1' style='width:12%'
    	onchange='var opt=this.options; for (var i=0; i<opt.length; i++)
    		if (i==this.selectedIndex) opt[i].text=opt[i].text.replace(/\xa0\xa0/,"&radic;");
    		else opt[i].text=opt[i].text.replace(/&radic;/,"\xa0\xa0");
    		if (this.selectedIndex==0) opt[1].text=opt[1].text.replace(/\xa0\xa0/,"&radic;");'><!--
    --><option value=''>type...</option><!--
    --><option value=''>&radic; auto-detect</option><!--
    --><option value='iframe'>&nbsp;&nbsp; web page</option><!--
    --><option value='windows'>&nbsp;&nbsp; windows media</option><!--
    --><option value='realone'>&nbsp;&nbsp; real one</option><!--
    --><option value='quicktime'>&nbsp;&nbsp; quicktime</option><!--
    --><option value='flash'>&nbsp;&nbsp; flash</option><!--
    --><option value='image'>&nbsp;&nbsp; jpg/gif/png</option><!--
    --></select><!--
    --><input type='text' name='url' id='minibrowser_url_%id%' size='60' value='' style='width:%urlsize%'
    	onfocus='this.select()'><!--
    --><input type='submit' value='go' title='view URL' style='width:6%'><!--
    --><input type='button' value='open' title='open a separate tab/window' style='width:6%'
    	onclick='if (this.form.url.value.length) window.open(this.form.url.value)'><!--
    --><input type='button' value='done' name='done' disabled title='disconnect from URL' style='width:6%'
    	onclick='return config.macros.miniBrowser.done(this.form);'><!--
    --></div><!--
    --><div id='minibrowser_player_%id%' style='display:none;text-align:center'></div><!--
    --><span id='minibrowser_controls2_%id%' style='margin-top:2px;display:none;'><!--
    --><div id='minibrowser_resize_%id%' style='display:%hidecontrols%;float:right'><!--
    --> size: <input type='text' name='w' size='3' value='' style=''
    	onfocus='this.select()'><!--
    -->x<input type='text' name='h' size='3' value='' style=''
    	onfocus='this.select()'><!--
    --> <input type='submit' value='set' style='width:5em'
    	onclick='var f=this.form;
    		if(!f.w.value.trim().length) f.w.value=config.options.txtMiniBrowserWidth;
    		if(!f.h.value.trim().length) f.h.value=config.options.txtMiniBrowserHeight;
    		config.options.txtMiniBrowserWidth=f.w.value; config.options.txtMiniBrowserHeight=f.h.value;
    		saveOptionCookie("txtMiniBrowserWidth"); saveOptionCookie("txtMiniBrowserHeight");'><!--
    --><input type='submit' value='reset' style='width:5em'
    	onclick='var f=this.form; f.ctrls.checked=true; f.w.value="100%"; f.h.value="480";
    		config.options.txtMiniBrowserWidth=f.w.value; config.options.txtMiniBrowserHeight=f.h.value;
    		saveOptionCookie("txtMiniBrowserWidth"); saveOptionCookie("txtMiniBrowserHeight");'><!--
    --><input type='button' value='fit' title='resize player to fit containing window' style='width:5em'
    	onclick='config.macros.miniBrowser.fit(this)'><!--
    --></div><!--
    --> <input type='checkbox' name='ctrls' id='minibrowser_togglecontrols_%id%' title='toggle minibrowser controls' CHECKED
    	onclick='document.getElementById("minibrowser_controls_%id%").style.display=this.checked?"block":"none";
    		document.getElementById("minibrowser_resize_%id%").style.display=this.checked?"block":"none";'
    ><a href='' title='toggle minibrowser controls'
    	onclick='this.previousSibling.click();return false;'>show controls</a><!--
    --></span><!--
    --></nobr></form>
    !end
    //}}}
    ***/

    /***
    |Name|NestedSlidersPlugin|
    |Source|http://www.TiddlyTools.com/#NestedSlidersPlugin|
    |Documentation|http://www.TiddlyTools.com/#NestedSlidersPluginInfo|
    |Version|2.4.9|
    |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|show content in nest-able sliding/floating panels, without creating separate tiddlers for each panel's content|
    !!!!!Documentation
    >see [[NestedSlidersPluginInfo]]
    !!!!!Configuration
    <<<
    <<option chkFloatingSlidersAnimate>> allow floating sliders to animate when opening/closing
    >Note: This setting can cause 'clipping' problems in some versions of InternetExplorer.
    >In addition, for floating slider animation to occur you must also allow animation in general (see [[AdvancedOptions]]).
    <<<
    !!!!!Revisions
    <<<
    2008.11.15 - 2.4.9 in adjustNestedSlider(), don't make adjustments if panel is marked as 'undocked' (CSS class).  In onClickNestedSlider(), SHIFT-CLICK docks panel (see [[MoveablePanelPlugin]])
    |please see [[NestedSlidersPluginInfo]] for additional revision details|
    2005.11.03 - 1.0.0 initial public release.  Thanks to RodneyGomes, GeoffSlocock, and PaulPetterson for suggestions and experiments.
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.NestedSlidersPlugin= {major: 2, minor: 4, revision: 9, date: new Date(2008,11,15)};

    // options for deferred rendering of sliders that are not initially displayed
    if (config.options.chkFloatingSlidersAnimate===undefined)
    	config.options.chkFloatingSlidersAnimate=false; // avoid clipping problems in IE

    // default styles for 'floating' class
    setStylesheet(".floatingPanel { position:absolute; z-index:10; padding:0.5em; margin:0em; \
    	background-color:#eee; color:#000; border:1px solid #000; text-align:left; }","floatingPanelStylesheet");

    // if removeCookie() function is not defined by TW core, define it here.
    if (window.removeCookie===undefined) {
    	window.removeCookie=function(name) {
    		document.cookie = name+'=; expires=Thu, 01-Jan-1970 00:00:01 UTC; path=/;';
    	}
    }

    config.formatters.push( {
    	name: "nestedSliders",
    	match: "\\n?\\+{3}",
    	terminator: "\\s*\\={3}\\n?",
    	lookahead: "\\n?\\+{3}(\\+)?(\\([^\\)]*\\))?(\\!*)?(\\^(?:[^\\^\\*\\@\\[\\>]*\\^)?)?(\\*)?(\\@)?(?:\\{\\{([\\w]+[\\s\\w]*)\\{)?(\\[[^\\]]*\\])?(\\[[^\\]]*\\])?(?:\\}{3})?(\\#[^:]*\\:)?(\\>)?(\\.\\.\\.)?\\s*",
    	handler: function(w)
    		{
    			lookaheadRegExp = new RegExp(this.lookahead,"mg");
    			lookaheadRegExp.lastIndex = w.matchStart;
    			var lookaheadMatch = lookaheadRegExp.exec(w.source)
    			if(lookaheadMatch && lookaheadMatch.index == w.matchStart)
    			{
    				var defopen=lookaheadMatch[1];
    				var cookiename=lookaheadMatch[2];
    				var header=lookaheadMatch[3];
    				var panelwidth=lookaheadMatch[4];
    				var transient=lookaheadMatch[5];
    				var hover=lookaheadMatch[6];
    				var buttonClass=lookaheadMatch[7];
    				var label=lookaheadMatch[8];
    				var openlabel=lookaheadMatch[9];
    				var panelID=lookaheadMatch[10];
    				var blockquote=lookaheadMatch[11];
    				var deferred=lookaheadMatch[12];

    				// location for rendering button and panel
    				var place=w.output;

    				// default to closed, no cookie, no accesskey, no alternate text/tip
    				var show="none"; var cookie=""; var key="";
    				var closedtext=">"; var closedtip="";
    				var openedtext="<"; var openedtip="";

    				// extra "+", default to open
    				if (defopen) show="block";

    				// cookie, use saved open/closed state
    				if (cookiename) {
    					cookie=cookiename.trim().slice(1,-1);
    					cookie="chkSlider"+cookie;
    					if (config.options[cookie]==undefined)
    						{ config.options[cookie] = (show=="block") }
    					show=config.options[cookie]?"block":"none";
    				}

    				// parse label/tooltip/accesskey: [label=X|tooltip]
    				if (label) {
    					var parts=label.trim().slice(1,-1).split("|");
    					closedtext=parts.shift();
    					if (closedtext.substr(closedtext.length-2,1)=="=")
    						{ key=closedtext.substr(closedtext.length-1,1); closedtext=closedtext.slice(0,-2); }
    					openedtext=closedtext;
    					if (parts.length) closedtip=openedtip=parts.join("|");
    					else { closedtip="show "+closedtext; openedtip="hide "+closedtext; }
    				}

    				// parse alternate label/tooltip: [label|tooltip]
    				if (openlabel) {
    					var parts=openlabel.trim().slice(1,-1).split("|");
    					openedtext=parts.shift();
    					if (parts.length) openedtip=parts.join("|");
    					else openedtip="hide "+openedtext;
    				}

    				var title=show=='block'?openedtext:closedtext;
    				var tooltip=show=='block'?openedtip:closedtip;

    				// create the button
    				if (header) { // use "Hn" header format instead of button/link
    					var lvl=(header.length>5)?5:header.length;
    					var btn = createTiddlyElement(createTiddlyElement(place,"h"+lvl,null,null,null),"a",null,buttonClass,title);
    					btn.onclick=onClickNestedSlider;
    					btn.setAttribute("href","javascript:;");
    					btn.setAttribute("title",tooltip);
    				}
    				else
    					var btn = createTiddlyButton(place,title,tooltip,onClickNestedSlider,buttonClass);
    				btn.innerHTML=title; // enables use of HTML entities in label

    				// set extra button attributes
    				btn.setAttribute("closedtext",closedtext);
    				btn.setAttribute("closedtip",closedtip);
    				btn.setAttribute("openedtext",openedtext);
    				btn.setAttribute("openedtip",openedtip);
    				btn.sliderCookie = cookie; // save the cookiename (if any) in the button object
    				btn.defOpen=defopen!=null; // save default open/closed state (boolean)
    				btn.keyparam=key; // save the access key letter ("" if none)
    				if (key.length) {
    					btn.setAttribute("accessKey",key); // init access key
    					btn.onfocus=function(){this.setAttribute("accessKey",this.keyparam);}; // **reclaim** access key on focus
    				}
    				btn.setAttribute("hover",hover?"true":"false");
    				btn.onmouseover=function(ev) {
    					// optional 'open on hover' handling
    					if (this.getAttribute("hover")=="true" && this.sliderPanel.style.display=='none') {
    						document.onclick.call(document,ev); // close transients
    						onClickNestedSlider(ev); // open this slider
    					}
    					// mouseover on button aligns floater position with button
    					if (window.adjustSliderPos) window.adjustSliderPos(this.parentNode,this,this.sliderPanel);
    				}

    				// create slider panel
    				var panelClass=panelwidth?"floatingPanel":"sliderPanel";
    				if (panelID) panelID=panelID.slice(1,-1); // trim off delimiters
    				var panel=createTiddlyElement(place,"div",panelID,panelClass,null);
    				panel.button = btn; // so the slider panel know which button it belongs to
    				btn.sliderPanel=panel; // so the button knows which slider panel it belongs to
    				panel.defaultPanelWidth=(panelwidth && panelwidth.length>2)?panelwidth.slice(1,-1):"";
    				panel.setAttribute("transient",transient=="*"?"true":"false");
    				panel.style.display = show;
    				panel.style.width=panel.defaultPanelWidth;
    				panel.onmouseover=function(event) // mouseover on panel aligns floater position with button
    					{ if (window.adjustSliderPos) window.adjustSliderPos(this.parentNode,this.button,this); }

    				// render slider (or defer until shown)
    				w.nextMatch = lookaheadMatch.index + lookaheadMatch[0].length;
    				if ((show=="block")||!deferred) {
    					// render now if panel is supposed to be shown or NOT deferred rendering
    					w.subWikify(blockquote?createTiddlyElement(panel,"blockquote"):panel,this.terminator);
    					// align floater position with button
    					if (window.adjustSliderPos) window.adjustSliderPos(place,btn,panel);
    				}
    				else {
    					var src = w.source.substr(w.nextMatch);
    					var endpos=findMatchingDelimiter(src,"+++","===");
    					panel.setAttribute("raw",src.substr(0,endpos));
    					panel.setAttribute("blockquote",blockquote?"true":"false");
    					panel.setAttribute("rendered","false");
    					w.nextMatch += endpos+3;
    					if (w.source.substr(w.nextMatch,1)=="\n") w.nextMatch++;
    				}
    			}
    		}
    	}
    )

    function findMatchingDelimiter(src,starttext,endtext) {
    	var startpos = 0;
    	var endpos = src.indexOf(endtext);
    	// check for nested delimiters
    	while (src.substring(startpos,endpos-1).indexOf(starttext)!=-1) {
    		// count number of nested 'starts'
    		var startcount=0;
    		var temp = src.substring(startpos,endpos-1);
    		var pos=temp.indexOf(starttext);
    		while (pos!=-1)  { startcount++; pos=temp.indexOf(starttext,pos+starttext.length); }
    		// set up to check for additional 'starts' after adjusting endpos
    		startpos=endpos+endtext.length;
    		// find endpos for corresponding number of matching 'ends'
    		while (startcount && endpos!=-1) {
    			endpos = src.indexOf(endtext,endpos+endtext.length);
    			startcount--;
    		}
    	}
    	return (endpos==-1)?src.length:endpos;
    }
    //}}}
    //{{{
    window.onClickNestedSlider=function(e)
    {
    	if (!e) var e = window.event;
    	var theTarget = resolveTarget(e);
    	while (theTarget && theTarget.sliderPanel==undefined) theTarget=theTarget.parentNode;
    	if (!theTarget) return false;
    	var theSlider = theTarget.sliderPanel;
    	var isOpen = theSlider.style.display!="none";

    	// if SHIFT-CLICK, dock panel first (see [[MoveablePanelPlugin]])
    	if (e.shiftKey && config.macros.moveablePanel) config.macros.moveablePanel.dock(theSlider,e);

    	// toggle label
    	theTarget.innerHTML=isOpen?theTarget.getAttribute("closedText"):theTarget.getAttribute("openedText");
    	// toggle tooltip
    	theTarget.setAttribute("title",isOpen?theTarget.getAttribute("closedTip"):theTarget.getAttribute("openedTip"));

    	// deferred rendering (if needed)
    	if (theSlider.getAttribute("rendered")=="false") {
    		var place=theSlider;
    		if (theSlider.getAttribute("blockquote")=="true")
    			place=createTiddlyElement(place,"blockquote");
    		wikify(theSlider.getAttribute("raw"),place);
    		theSlider.setAttribute("rendered","true");
    	}

    	// show/hide the slider
    	if(config.options.chkAnimate && (!hasClass(theSlider,'floatingPanel') || config.options.chkFloatingSlidersAnimate))
    		anim.startAnimating(new Slider(theSlider,!isOpen,e.shiftKey || e.altKey,"none"));
    	else
    		theSlider.style.display = isOpen ? "none" : "block";

    	// reset to default width (might have been changed via plugin code)
    	theSlider.style.width=theSlider.defaultPanelWidth;

    	// align floater panel position with target button
    	if (!isOpen && window.adjustSliderPos) window.adjustSliderPos(theSlider.parentNode,theTarget,theSlider);

    	// if showing panel, set focus to first 'focus-able' element in panel
    	if (theSlider.style.display!="none") {
    		var ctrls=theSlider.getElementsByTagName("*");
    		for (var c=0; c<ctrls.length; c++) {
    			var t=ctrls[c].tagName.toLowerCase();
    			if ((t=="input" && ctrls[c].type!="hidden") || t=="textarea" || t=="select")
    				{ try{ ctrls[c].focus(); } catch(err){;} break; }
    		}
    	}
    	var cookie=theTarget.sliderCookie;
    	if (cookie && cookie.length) {
    		config.options[cookie]=!isOpen;
    		if (config.options[cookie]!=theTarget.defOpen) window.saveOptionCookie(cookie);
    		else window.removeCookie(cookie); // remove cookie if slider is in default display state
    	}

    	// prevent SHIFT-CLICK from being processed by browser (opens blank window... yuck!)
    	// prevent clicks *within* a slider button from being processed by browser
    	// but allow plain click to bubble up to page background (to close transients, if any)
    	if (e.shiftKey || theTarget!=resolveTarget(e))
    		{ e.cancelBubble=true; if (e.stopPropagation) e.stopPropagation(); }
    	Popup.remove(); // close open popup (if any)
    	return false;
    }
    //}}}
    //{{{
    // click in document background closes transient panels
    document.nestedSliders_savedOnClick=document.onclick;
    document.onclick=function(ev) { if (!ev) var ev=window.event; var target=resolveTarget(ev);

    	if (document.nestedSliders_savedOnClick)
    		var retval=document.nestedSliders_savedOnClick.apply(this,arguments);
    	// if click was inside a popup... leave transient panels alone
    	var p=target; while (p) if (hasClass(p,"popup")) break; else p=p.parentNode;
    	if (p) return retval;
    	// if click was inside transient panel (or something contained by a transient panel), leave it alone
    	var p=target; while (p) {
    		if ((hasClass(p,"floatingPanel")||hasClass(p,"sliderPanel"))&&p.getAttribute("transient")=="true") break;
    		p=p.parentNode;
    	}
    	if (p) return retval;
    	// otherwise, find and close all transient panels...
    	var all=document.all?document.all:document.getElementsByTagName("DIV");
    	for (var i=0; i<all.length; i++) {
    		 // if it is not a transient panel, or the click was on the button that opened this panel, don't close it.
    		if (all[i].getAttribute("transient")!="true" || all[i].button==target) continue;
    		// otherwise, if the panel is currently visible, close it by clicking it's button
    		if (all[i].style.display!="none") window.onClickNestedSlider({target:all[i].button})
    		if (!hasClass(all[i],"floatingPanel")&&!hasClass(all[i],"sliderPanel")) all[i].style.display="none";
    	}
    	return retval;
    };
    //}}}
    //{{{
    // adjust floating panel position based on button position
    if (window.adjustSliderPos==undefined) window.adjustSliderPos=function(place,btn,panel) {
    	if (hasClass(panel,"floatingPanel") && !hasClass(panel,"undocked")) {
    		// see [[MoveablePanelPlugin]] for use of 'undocked'
    		var rightEdge=document.body.offsetWidth-1;
    		var panelWidth=panel.offsetWidth;
    		var left=0;
    		var top=btn.offsetHeight;
    		if (place.style.position=="relative" && findPosX(btn)+panelWidth>rightEdge) {
    			left-=findPosX(btn)+panelWidth-rightEdge; // shift panel relative to button
    			if (findPosX(btn)+left<0) left=-findPosX(btn); // stay within left edge
    		}
    		if (place.style.position!="relative") {
    			var left=findPosX(btn);
    			var top=findPosY(btn)+btn.offsetHeight;
    			var p=place; while (p && !hasClass(p,'floatingPanel')) p=p.parentNode;
    			if (p) { left-=findPosX(p); top-=findPosY(p); }
    			if (left+panelWidth>rightEdge) left=rightEdge-panelWidth;
    			if (left<0) left=0;
    		}
    		panel.style.left=left+"px"; panel.style.top=top+"px";
    	}
    }
    //}}}
    //{{{
    // TW2.1 and earlier:
    // hijack Slider stop handler so overflow is visible after animation has completed
    Slider.prototype.coreStop = Slider.prototype.stop;
    Slider.prototype.stop = function()
    	{ this.coreStop.apply(this,arguments); this.element.style.overflow = "visible"; }

    // TW2.2+
    // hijack Morpher stop handler so sliderPanel/floatingPanel overflow is visible after animation has completed
    if (version.major+.1*version.minor+.01*version.revision>=2.2) {
    	Morpher.prototype.coreStop = Morpher.prototype.stop;
    	Morpher.prototype.stop = function() {
    		this.coreStop.apply(this,arguments);
    		var e=this.element;
    		if (hasClass(e,"sliderPanel")||hasClass(e,"floatingPanel")) {
    			// adjust panel overflow and position after animation
    			e.style.overflow = "visible";
    			if (window.adjustSliderPos) window.adjustSliderPos(e.parentNode,e.button,e);
    		}
    	};
    }
    //}}}

    /%
    |Name|NextTiddler|
    |Source|http://www.TiddlyTools.com/#NextTiddler|
    |Version|0.0.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|script|
    |Requires|InlineJavascriptPlugin|
    |Overrides||
    |Description|insert a link that, when clicked, closes the current tiddler and opens another one in its place|

    usage: <<tiddler NextTiddler with: NewTiddlerTitle linktext>>

    %/<script label="$2">
    	var tiddler=story.findContainingTiddler(place);
    	story.displayTiddler(tiddler,"$1");
    	story.closeTiddler(tiddler.getAttribute("tiddler")); // close self
    	return false;
    </script>

    <!--{{{-->
    <div class='header'  DISABLED_macro='gradient vert [[ColorPalette::PrimaryLight]] [[ColorPalette::PrimaryMid]]'>
    <div class='headerShadow'>
    <span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
    <span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
    </div>
    <div class='headerForeground'>
    <span class='siteTitle' refresh='content' tiddler='SiteTitle'></span>
    <span class='siteSubtitle' refresh='content' tiddler='SiteSubtitle'></span>
    </div>
    </div>
    <div id='siteNav' class='siteNav' refresh='content' force='true' tiddler='SiteNav'></div>
    <div id='breadCrumbs' class='breadCrumbs' style='font-size:80%;padding:0 1em;'></div>
    <div id='mainMenu'
    	<div refresh='content' force='true' tiddler='MainMenu'></div>
    </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='storyMenu' refresh='content' force='true' tiddler='StoryMenu'></div>
    <div id='tiddlerDisplay'></div>
    <div id='scrollToTop' style="position:fixed;z-index:1001;bottom:.3em;right:.3em;cursor:pointer;font-size:9pt;">
    	<a href="javascript:window.scrollTo(0,0)" title="scroll to top of page">&#x25b2;</a>
    </div>
    </div>
    <!--}}}-->

    /***
    |''Name:''|PasswordOptionPlugin|
    |''Description:''|Extends TiddlyWiki options with non encrypted password option.|
    |''Version:''|1.0.2|
    |''Date:''|Apr 19, 2007|
    |''Source:''|http://tiddlywiki.bidix.info/#PasswordOptionPlugin|
    |''Author:''|BidiX (BidiX (at) bidix (dot) info)|
    |''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
    |''~CoreVersion:''|2.2.0 (Beta 5)|
    ***/
    //{{{
    version.extensions.PasswordOptionPlugin = {
    	major: 1, minor: 0, revision: 2,
    	date: new Date("Apr 19, 2007"),
    	source: 'http://tiddlywiki.bidix.info/#PasswordOptionPlugin',
    	author: 'BidiX (BidiX (at) bidix (dot) info',
    	license: '[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D]]',
    	coreVersion: '2.2.0 (Beta 5)'
    };

    config.macros.option.passwordCheckboxLabel = "Save this password on this computer";
    config.macros.option.passwordInputType = "password"; // password | text
    setStylesheet(".pasOptionInput {width: 11em;}\n","passwordInputTypeStyle");

    merge(config.macros.option.types, {
    	'pas': {
    		elementType: "input",
    		valueField: "value",
    		eventName: "onkeyup",
    		className: "pasOptionInput",
    		typeValue: config.macros.option.passwordInputType,
    		create: function(place,type,opt,className,desc) {
    			// password field
    			config.macros.option.genericCreate(place,'pas',opt,className,desc);
    			// checkbox linked with this password "save this password on this computer"
    			config.macros.option.genericCreate(place,'chk','chk'+opt,className,desc);
    			// text savePasswordCheckboxLabel
    			place.appendChild(document.createTextNode(config.macros.option.passwordCheckboxLabel));
    		},
    		onChange: config.macros.option.genericOnChange
    	}
    });

    merge(config.optionHandlers['chk'], {
    	get: function(name) {
    		// is there an option linked with this chk ?
    		var opt = name.substr(3);
    		if (config.options[opt])
    			saveOptionCookie(opt);
    		return config.options[name] ? "true" : "false";
    	}
    });

    merge(config.optionHandlers, {
    	'pas': {
     		get: function(name) {
    			if (config.options["chk"+name]) {
    				return encodeCookie(config.options[name].toString());
    			} else {
    				return "";
    			}
    		},
    		set: function(name,value) {config.options[name] = decodeCookie(value);}
    	}
    });

    // need to reload options to load passwordOptions
    loadOptionsCookie();

    /*
    if (!config.options['pasPassword'])
    	config.options['pasPassword'] = '';

    merge(config.optionsDesc,{
    		pasPassword: "Test password"
    	});
    */
    //}}}

    /***
    |Name|PlayerPlugin|
    |Source|http://www.TiddlyTools.com/#PlayerPlugin|
    |Version|1.1.4|
    |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|Embed a media player in a tiddler|
    !!!!!Usage
    <<<
    {{{<<player [id=xxx] [type] [URL] [width] [height] [autoplay|true|false] [showcontrols|true|false] [extras]>>}}}

    ''id=xxx'' is optional, and specifies a unique identifier for each embedded player.  note: this is required if you intend to display more than one player at the same time.

    ''type'' is optional, and is one of the following: ''windows'', ''realone'', ''quicktime'', ''flash'', ''image'' or ''iframe''.  If the media type is not specified, the plugin automatically detects Windows, Real, QuickTime, Flash video or JPG/GIF images by matching known file extensions and/or specialized streaming-media transfer protocols (such as RTSP:).  For unrecognized media types, the plugin displays an error message.

    ''URL'' is the location of the media content

    ''width'' and ''height'' are the dimensions of the video display area (in pixels)

    ''autoplay'' or ''true'' or ''false'' is optional, and specifies whether the media content should begin playing as soon as it is loaded, or wait for the user to press the "play" button.  Default is //not// to autoplay.

    ''showcontrols'' or ''true'' or ''false'' is optional, and specifies whether the embedded media player should display its built-in control panel (e.g., play, pause, stop, rewind, etc), if any.  Default is to display the player controls.

    ''extras'' are optional //pairs// of parameters that can be passed to the embedded player, using the {{{<param name=xxx value=yyy>}}} HTML syntax.

    ''If you use [[AttachFilePlugin]] to encode and store a media file within your document, you can play embedded media content by using the title of the //attachment tiddler//'' as a parameter in place of the usual reference to an external URL.  When playing an attached media content, you should always explicitly specify the media type parameter, because the name used for the attachment tiddler may not contain a known file extension from which a default media type can be readily determined.
    <<<
    !!!!!Configuration
    <<<
    Default player size:
    width: <<option txtPlayerDefaultWidth>> height: <<option txtPlayerDefaultHeight>>
    <<<
    !!!!!Examples
    <<<
    +++[Windows Media]...
    Times Square Live Webcam
    {{{<<player id=1 http://www.earthcam.com/usa/newyork/timessquare/asx/tsq_stream.asx>>}}}
    <<player id=1 http://www.earthcam.com/usa/newyork/timessquare/asx/tsq_stream.asx>>
    ===
    +++[RealOne]...
    BBC London: Live and Recorded news
    {{{<<player id=2 http://www.bbc.co.uk/london/realmedia/news/tvnews.ram>>}}}
    <<player id=2 http://www.bbc.co.uk/london/realmedia/news/tvnews.ram>>
    ===
    +++[Quicktime]...
    America Free TV: Classic Comedy
    {{{<<player id=3 http://www.americafree.tv/unicast_mov/AmericaFreeTVComedy.mov>>}}}
    <<player id=3 http://www.americafree.tv/unicast_mov/AmericaFreeTVComedy.mov>>
    ===
    +++[Flash]...
    Asteroids arcade game
    {{{<<player id=4 http://www.80smusiclyrics.com/games/asteroids/asteroids.swf 400 300>>}}}
    <<player id=4 http://www.80smusiclyrics.com/games/asteroids/asteroids.swf 400 300>>
    Google Video
    {{{<<player id=5 flash http://video.google.com/googleplayer.swf?videoUrl=http%3A%2F%2Fvp.video.google.com%2Fvideodownload%3Fversion%3D0%26secureurl%3DoQAAAIVnUNP6GYRY8YnIRNPe4Uk5-j1q1MVpJIW4uyEFpq5Si0hcSDuig_JZcB9nNpAhbScm9W_8y_vDJQBw1DRdCVbXl-wwm5dyUiiStl_rXt0ATlstVzrUNC4fkgK_j7nmse7kxojRj1M3eo3jXKm2V8pQjWk97GcksMFFwg7BRAXmRSERexR210Amar5LYzlo9_k2AGUWPLyRhMJS4v5KtDSvNK0neL83ZjlHlSECYXyk%26sigh%3Dmpt2EOr86OAUNnPQ3b9Tr0wnDms%26begin%3D0%26len%3D429700%26docid%3D-914679554478687740&thumbnailUrl=http%3A%2F%2Fvideo.google.com%2FThumbnailServer%3Fcontentid%3De7e77162deb04c42%26second%3D5%26itag%3Dw320%26urlcreated%3D1144620753%26sigh%3DC3fqXPPS1tFiUqLzmkX3pdgYc2Y&playerId=-91467955447868774               400 326>>}}}
    <<player id=5 flash http://video.google.com/googleplayer.swf?videoUrl=http%3A%2F%2Fvp.video.google.com%2Fvideodownload%3Fversion%3D0%26secureurl%3DoQAAAIVnUNP6GYRY8YnIRNPe4Uk5-j1q1MVpJIW4uyEFpq5Si0hcSDuig_JZcB9nNpAhbScm9W_8y_vDJQBw1DRdCVbXl-wwm5dyUiiStl_rXt0ATlstVzrUNC4fkgK_j7nmse7kxojRj1M3eo3jXKm2V8pQjWk97GcksMFFwg7BRAXmRSERexR210Amar5LYzlo9_k2AGUWPLyRhMJS4v5KtDSvNK0neL83ZjlHlSECYXyk%26sigh%3Dmpt2EOr86OAUNnPQ3b9Tr0wnDms%26begin%3D0%26len%3D429700%26docid%3D-914679554478687740&thumbnailUrl=http%3A%2F%2Fvideo.google.com%2FThumbnailServer%3Fcontentid%3De7e77162deb04c42%26second%3D5%26itag%3Dw320%26urlcreated%3D1144620753%26sigh%3DC3fqXPPS1tFiUqLzmkX3pdgYc2Y&playerId=-91467955447868774               400 326>>
    YouTube Video
    {{{<<player id=6 flash http://www.youtube.com/v/OdT9z-JjtJk 400 300>>}}}
    <<player id=6 flash http://www.youtube.com/v/OdT9z-JjtJk 400 300>>
    ===
    +++[Still Images]...
    GIF (best for illustrations, animations, diagrams, etc.)
    {{{<<player id=7 image images/meow.gif auto auto>>}}}
    <<player id=7 image images/meow.gif auto auto>>
    JPG (best for photographs, scanned images, etc.)
    {{{<<player id=8 image images/meow2.jpg 200 150>>}}}
    <<player id=8 image images/meow2.jpg 200 150>>
    ===
    <<<
    !!!!!Revisions
    <<<
    2008.05.10 [1.1.4] in handlers(), immediately return if no params (prevents error in macro).  Also, refactored auto-detect code to make type mapping configurable.
    2007.10.15 [1.1.3] in loadURL(), add recognition for .PNG (still image), fallback to iframe for unrecognized media types
    2007.08.31 [1.1.2] added 'click-through' link for JPG/GIF images
    2007.06.21 [1.1.1] changed "hidecontrols" param to "showcontrols" and recognize true/false values in addition to 'showcontrols', added "autoplay" param (also recognize true/false values), allow "auto" as value for type param
    2007.05.22 [1.1.0] added support for type=="iframe" (displays src URL in an IFRAME)
    2006.12.06 [1.0.1] in handler(), corrected check for config.macros.attach (instead of config.macros.attach.getAttachment) so that player plugin will work when AttachFilePlugin is NOT installed.  (Thanks to Phillip Ehses for bug report)
    2006.11.30 [1.0.0] support embedded media content using getAttachment() API defined by AttachFilePlugin or AttachFilePluginFormatters.  Also added support for 'image' type to render JPG/GIF still images
    2006.02.26 [0.7.0] major re-write.  handles default params better.  create/recreate player objects via loadURL() API for use with interactive forms and scripts.
    2006.01.27 [0.6.0] added support for 'extra' macro params to pass through to object parameters
    2006.01.19 [0.5.0] Initial ALPHA release
    2005.12.23 [0.0.0] Started
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.PlayerPlugin= {major: 1, minor: 1, revision: 4, date: new Date(2008,5,10)};

    config.macros.player = {};
    config.macros.player.html = {};
    config.macros.player.handler= function(place,macroName,params) {
    	if (!params.length) return; // missing parameters - do nothing
    	var id=null;
    	if (params[0].substr(0,3)=="id=") id=params.shift().substr(3);
    	var type="";
    	if (!params.length) return; // missing parameters - do nothing
    	var p=params[0].toLowerCase();
    	if (p=="auto" || p=="windows" || p=="realone" || p=="quicktime" || p=="flash" || p=="image" || p=="iframe")
    		type=params.shift().toLowerCase();
    	var url=params.shift(); if (!url || !url.trim().length) url="";
    	if (url.length && config.macros.attach!=undefined) // if AttachFilePlugin is installed
    		if ((tid=store.getTiddler(url))!=null && tid.isTagged("attachment")) // if URL is attachment
    			url=config.macros.attach.getAttachment(url); // replace TiddlerTitle with URL
    	var width=params.shift();
    	var height=params.shift();
    	var autoplay=false;
    	if (params[0]=='autoplay'||params[0]=='true'||params[0]=='false')
    		autoplay=(params.shift()!='false');
    	var show=true;
    	if (params[0]=='showcontrols'||params[0]=='true'||params[0]=='false')
    		show=(params.shift()!='false');
    	var extras="";
    	while (params[0]!=undefined)
    		extras+="<param name='"+params.shift()+"' value='"+params.shift()+"'> ";
    	this.loadURL(place,id,type,url,width,height,autoplay,show,extras);
    }

    if (config.options.txtPlayerDefaultWidth==undefined) config.options.txtPlayerDefaultWidth="100%";
    if (config.options.txtPlayerDefaultHeight==undefined) config.options.txtPlayerDefaultHeight="480"; // can't use "100%"... player height doesn't stretch right :-(

    config.macros.player.typeMap={
    	windows: ['mms', '.asx', '.wvx', '.wmv', '.mp3'],
    	realone: ['rtsp', '.ram', '.rpm', '.rm', '.ra'],
    	quicktime: ['.mov', '.qt'],
    	flash: ['.swf', '.flv'],
    	image: ['.jpg', '.gif', '.png'],
    	iframe: ['.htm', '.html', '.shtml', '.php']
    };

    config.macros.player.loadURL=function(place,id,type,url,width,height,autoplay,show,extras) {

    	if (id==undefined) id="tiddlyPlayer";
    	if (!width) var width=config.options.txtPlayerDefaultWidth;
    	if (!height) var height=config.options.txtPlayerDefaultHeight;
    	if (url && (!type || !type.length || type=="auto")) { // determine type from URL
    		u=url.toLowerCase();
    		var map=config.macros.player.typeMap;
    		for (var t in map) for (var i=0; i<map[t].length; i++)
    			if (u.indexOf(map[t][i])!=-1) var type=t;
    	}
    	if (!type || !config.macros.player.html[type]) var type="none";
    	if (!url) var url="";
    	if (show===undefined) var show=true;
    	if (!extras) var extras="";
    	if (type=="none" && url.trim().length) type="iframe"; // fallback to iframe for unrecognized media types

    	// adjust parameter values for player-specific embedded HTML
    	switch (type) {
    		case "windows":
    			autoplay=autoplay?"1":"0"; // player-specific param value
    			show=show?"1":"0"; // player-specific param value
    			break;
    		case "realone":
    			autoplay=autoplay?"true":"false";
    			show=show?"block":"none";
    			height-=show?60:0; // leave room for controls
    			break;
    		case "quicktime":
    			autoplay=autoplay?"true":"false";
    			show=show?"true":"false";
    			break;
    		case "image":
    			show=show?"block":"none";
    			break;
    		case "iframe":
    			show=show?"block":"none";
    			break;
    	}

    	// create containing div for player HTML
    	// and add or replace player in TW DOM structure
    	var newplayer = document.createElement("div");
    	newplayer.playerType=type;
    	newplayer.setAttribute("id",id+"_div");
    	var existing = document.getElementById(id+"_div");
    	if (existing && !place) place=existing.parentNode;
    	if (!existing)
    		place.appendChild(newplayer);
    	else {
    		if (place==existing.parentNode) place.replaceChild(newplayer,existing)
    		else { existing.parentNode.removeChild(existing); place.appendChild(newplayer); }
    	}

    	var html=config.macros.player.html[type];
    	html=html.replace(/%i%/mg,id);
    	html=html.replace(/%w%/mg,width);
    	html=html.replace(/%h%/mg,height);
    	html=html.replace(/%u%/mg,url);
    	html=html.replace(/%a%/mg,autoplay);
    	html=html.replace(/%s%/mg,show);
    	html=html.replace(/%x%/mg,extras);
    	newplayer.innerHTML=html;
    }
    //}}}

    // // Player-specific API functions: isReady(id), isPlaying(id), toggleControls(id), showControls(id,flag)

    //{{{
    // status values:
    // Windows: 0=Undefined, 1=Stopped, 2=Paused, 3=Playing, 4=ScanForward, 5=ScanReverse
    //          6=Buffering, 7=Waiting, 8=MediaEnded, 9=Transitioning, 10=Ready, 11=Reconnecting
    // RealOne: 0=Stopped, 1=Contacting, 2=Buffering, 3=Playing, 4=Paused, 5=Seeking
    // QuickTime: 'Waiting', 'Loading', 'Playable', 'Complete', 'Error:###'
    // Flash: 0=Loading, 1=Uninitialized, 2=Loaded, 3=Interactive, 4=Complete
    config.macros.player.isReady=function(id)
    {
    	var d=document.getElementById(id+"_div"); if (!d) return false;
    	var p=document.getElementById(id); if (!p) return false;
    	if (d.playerType=='windows') return !((p.playState==0)||(p.playState==7)||(p.playState==9)||(p.playState==11));
    	if (d.playerType=='realone') return (p.GetPlayState()>1);
    	if (d.playerType=='quicktime') return !((p.getPluginStatus()=='Waiting')||(p.getPluginStatus()=='Loading'));
    	if (d.playerType=='flash') return (p.ReadyState>2);
    	return true;
    }
    config.macros.player.isPlaying=function(id)
    {
    	var d=document.getElementById(id+"_div"); if (!d) return false;
    	var p=document.getElementById(id); if (!p) return false;
    	if (d.playerType=='windows') return (p.playState==3);
    	if (d.playerType=='realone') return (p.GetPlayState()==3);
    	if (d.playerType=='quicktime') return (p.getPluginStatus()=='Complete');
    	if (d.playerType=='flash') return (p.ReadyState<4);
    	return false;
    }
    config.macros.player.showControls=function(id,flag) {
    	var d=document.getElementById(id+"_div"); if (!d) return false;
    	var p=document.getElementById(id); if (!p) return false;
    	if (d.playerType=='windows') { p.ShowControls=flag; p.ShowStatusBar=flag; }
    	if (d.playerType=='realone') { alert('show/hide controls not available'); }
    	if (d.playerType=='quicktime')      // if player not ready, retry in one second
    		{ if (this.isReady(id)) p.setControllerVisible(flag); else setTimeout('config.macros.player.showControls("'+id+'",'+flag+')',1000); }
    	if (d.playerType=='flash') { alert('show/hide controls not available'); }
    }
    config.macros.player.toggleControls=function(id) {
    	var d=document.getElementById(id+"_div"); if (!d) return false;
    	var p=document.getElementById(id); if (!p) return false;
    	if (d.playerType=='windows') var flag=!p.ShowControls;
    	if (d.playerType=='realone') var flag=true; // TBD
    	if (d.playerType=='quicktime') var flag=!p.getControllerVisible();
    	if (d.playerType=='flash') var flag=true; // TBD
    	this.showControls(id,flag);
    }
    config.macros.player.fullScreen=function(id) {
    	var d=document.getElementById(id+"_div"); if (!d) return false;
    	var p=document.getElementById(id); if (!p) return false;
    	if (d.playerType=='windows') p.DisplaySize=3;
    	if (d.playerType=='realone') p.SetFullScreen();
    	if (d.playerType=='quicktime') { alert('full screen not available'); }
    	if (d.playerType=='flash') { alert('full screen not available'); }
    }
    //}}}

    // // Player HTML

    //{{{
    // placeholder (no player)
    config.macros.player.html.none=' \
    	<table id="%i%" width="%w%" height="%h%" style="background-color:#111;border:0;margin:0;padding:0;"> \
    	<tr style="background-color:#111;border:0;margin:0;padding:0;"> \
    	<td width="%w%" height="%h%" style="background-color:#111;color:#ccc;border:0;margin:0;padding:0;text-align:center;"> \
    	&nbsp; \
    	%u% \
    	&nbsp; \
    	</td></tr></table>';
    //}}}

    //{{{
    // JPG/GIF/PNG still images
    config.macros.player.html.image='\
    	<a href="%u%" target="_blank"><img width="%w%" height="%h%" style="display:%s%;" src="%u%"></a>';
    //}}}

    //{{{
    // IFRAME web page viewer
    config.macros.player.html.iframe='\
    	<iframe id="%i%" width="%w%" height="%h%" style="display:%s%;background:#fff;" src="%u%"></iframe>';
    //}}}

    //{{{
    // Windows Media Player
    // v7.1 ID: classid=CLSID:6BF52A52-394A-11d3-B153-00C04F79FAA6
    // v9	ID: classid=CLSID:22d6f312-b0f6-11d0-94ab-0080c74c7e95
    config.macros.player.html.windows=' \
    	<object id="%i%" width="%w%" height="%h%" style="margin:0;padding:0;width:%w%;height:%h%px;" \
    		classid="CLSID:22d6f312-b0f6-11d0-94ab-0080c74c7e95" \
    		codebase="http://activex.microsoft.com/activex/controls/mplayer/en/nsmp2inf.cab#Version=6,4,5,715" \
    		align="baseline" border="0" \
    		standby="Loading Microsoft Windows Media Player components..." \
    		type="application/x-oleobject"> \
    		<param name="FileName" value="%u%"> <param name="ShowControls" value="%s%"> \
    		<param name="ShowPositionControls" value="1"> <param name="ShowAudioControls" value="1"> \
    		<param name="ShowTracker" value="1"> <param name="ShowDisplay" value="0"> \
    		<param name="ShowStatusBar" value="1"> <param name="AutoSize" value="1"> \
    		<param name="ShowGotoBar" value="0"> <param name="ShowCaptioning" value="0"> \
    		<param name="AutoStart" value="%a%"> <param name="AnimationAtStart" value="1"> \
    		<param name="TransparentAtStart" value="0"> <param name="AllowScan" value="1"> \
    		<param name="EnableContextMenu" value="1"> <param name="ClickToPlay" value="1"> \
    		<param name="InvokeURLs" value="1"> <param name="DefaultFrame" value="datawindow"> \
    		%x% \
    		<embed src="%u%" style="margin:0;padding:0;width:%w%;height:%h%px;" \
    			align="baseline" border="0" width="%w%" height="%h%" \
    			type="application/x-mplayer2" \
    			pluginspage="http://www.microsoft.com/windows/windowsmedia/download/default.asp" \
    			name="%i%" showcontrols="%s%" showpositioncontrols="1" \
    			showaudiocontrols="1" showtracker="1" showdisplay="0" \
    			showstatusbar="%s%" autosize="1" showgotobar="0" showcaptioning="0" \
    			autostart="%a%" autorewind="0" animationatstart="1" transparentatstart="0" \
    			allowscan="1" enablecontextmenu="1" clicktoplay="0" invokeurls="1" \
    			defaultframe="datawindow"> \
    		</embed> \
    	</object>';
    //}}}

    //{{{
    // RealNetworks' RealOne Player
    config.macros.player.html.realone=' \
    	<table width="%w%" style="border:0;margin:0;padding:0;"><tr style="border:0;margin:0;padding:0;"><td style="border:0;margin:0;padding:0;"> \
    	<object id="%i%" width="%w%" height="%h%" style="margin:0;padding:0;" \
    		CLASSID="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA"> \
    		<PARAM NAME="CONSOLE" VALUE="player"> \
    		<PARAM NAME="CONTROLS" VALUE="ImageWindow"> \
    		<PARAM NAME="AUTOSTART" Value="%a%"> \
    		<PARAM NAME="MAINTAINASPECT" Value="true"> \
    		<PARAM NAME="NOLOGO" Value="true"> \
    		<PARAM name="BACKGROUNDCOLOR" VALUE="#333333"> \
    		<PARAM NAME="SRC" VALUE="%u%"> \
    		%x% \
    		<EMBED width="%w%" height="%h%" controls="ImageWindow" type="audio/x-pn-realaudio-plugin" style="margin:0;padding:0;" \
    			name="%i%" \
    			src="%u%" \
    			console=player \
    			maintainaspect=true \
    			nologo=true \
    			backgroundcolor=#333333 \
    			autostart=%a%> \
    		</OBJECT> \
    	</td></tr><tr style="border:0;margin:0;padding:0;"><td style="border:0;margin:0;padding:0;"> \
    	<object id="%i%_controls" width="%w%" height="60" style="margin:0;padding:0;display:%s%" \
    		CLASSID="clsid:CFCDAA03-8BE4-11cf-B84B-0020AFBBCCFA"> \
    		<PARAM NAME="CONSOLE" VALUE="player"> \
    		<PARAM NAME="CONTROLS" VALUE="All"> \
    		<PARAM NAME="NOJAVA" Value="true"> \
    		<PARAM NAME="MAINTAINASPECT" Value="true"> \
    		<PARAM NAME="NOLOGO" Value="true"> \
    		<PARAM name="BACKGROUNDCOLOR" VALUE="#333333"> \
    		<PARAM NAME="SRC" VALUE="%u%"> \
    		%x% \
    		<EMBED WIDTH="%w%" HEIGHT="60" NOJAVA="true" type="audio/x-pn-realaudio-plugin" style="margin:0;padding:0;display:%s%" \
    			controls="All" \
    			name="%i%_controls" \
    			src="%u%" \
    			console=player \
    			maintainaspect=true \
    			nologo=true \
    			backgroundcolor=#333333> \
    		</OBJECT> \
    	</td></tr></table>';
    //}}}

    //{{{
    // QuickTime Player
    config.macros.player.html.quicktime=' \
    	<OBJECT ID="%i%" WIDTH="%w%" HEIGHT="%h%" style="margin:0;padding:0;" \
    		CLASSID="clsid:02BF25D5-8C17-4B23-BC80-D3488ABDDC6B" \
    		CODEBASE="http://www.apple.com/qtactivex/qtplugin.cab"> \
    		<PARAM name="SRC" VALUE="%u%"> \
    		<PARAM name="AUTOPLAY" VALUE="%a%"> \
    		<PARAM name="CONTROLLER" VALUE="%s%"> \
    		<PARAM name="BGCOLOR" VALUE="#333333"> \
    		<PARAM name="SCALE" VALUE="aspect"> \
    		<PARAM name="SAVEEMBEDTAGS" VALUE="true"> \
    		%x% \
    		<EMBED name="%i%" WIDTH="%w%" HEIGHT="%h%" style="margin:0;padding:0;" \
    			SRC="%u%" \
    			AUTOPLAY="%a%" \
    			SCALE="aspect" \
    			CONTROLLER="%s%" \
    			BGCOLOR="#333333" \
    			EnableJavaSript="true" \
    			PLUGINSPAGE="http://www.apple.com/quicktime/download/"> \
    		</EMBED> \
    	</OBJECT>';
    //}}}

    //{{{
    // Flash Player
    config.macros.player.html.flash='\
    	<object id="%i%" width="%w%" height="%h%" style="margin:0;padding:0;" \
    		classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" \
    		codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,29,0"> \
    		<param name="movie" value="%u%"> \
    		<param name="quality" value="high"> \
    		<param name="SCALE" value="exactfit"> \
    		<param name="bgcolor" value="333333"> \
    		%x% \
    		<embed name="%i%" src="%u%" style="margin:0;padding:0;" \
    			height="%h%" width="%w%" quality="high" \
    			pluginspage="http://www.macromedia.com/go/getflashplayer" \
    			type="application/x-shockwave-flash" scale="exactfit"> \
    		</embed> \
    	</object>';
    //}}}

    !! 什么是Python
    参见百度词条 http://baike.baidu.com/view/21087.htm

    !! Python资源
    [[下载 简明Python教程 | http://bbs.gamediy.net/job.php?action=download&aid=110]]

    This package provides a toolbar of interactive 'power tools' that you can use while editing a tiddler to quickly insert TiddlyWiki tiddler links, images, macros, etc. or common formatting sequences directly into tiddler content, as well as perform other functions (such as find/replace, sort, split, convert, etc.) that can be used to modify the current tiddler's source content in a variety of ways.

    <<tiddler QuickEditToolbar with: show>>
    !!!!!Installation:
    <<<
    Individual ~QuickEdit buttons are defined in separate tiddlers (e.g., [[QuickEdit_replace]]) that have also been //transcluded// into a single toolbar definition named [[QuickEditToolbar]].  You can edit this definition to add, remove, or rearrange the toolbar buttons to best suit your needs, and then embed the [[QuickEditToolbar]] tiddler into your document's [[EditTemplate]], like this:
    {{{
    <div macro='tiddler QuickEditToolbar'></div>
    }}}
    Next, in order to support some of the formatting 'shortcuts' provided by the toolbar, add a reference to the shortcuts CSS class definitions in your [[StyleSheet]]:
    {{{
    [[StyleSheetShortcuts]]
    }}}
    By default, the QuickEdit toolbar is hidden until you enable it by using the ''toggleQuickEdit'' command, which you can add to the ~EditToolbar definition in [[ToolbarCommands]]:
    {{{
    |EditToolbar|... toggleQuickEdit ...|
    }}}
    You can also toggle the ~QuickEdit toolbar display via a single checkbox option that can be added to [[SideBarOptions]] (or any other desired location):
    {{{
    <<option chkShowQuickEdit>> show QuickEdit toolbar
    }}}
    Note: You can 'hard-code' the ''chkShowQuickEdit'' setting, so that the toolbar will be //initially// displayed, by creating a tiddler (e.g., ConfigTweaks), tagged with <<tag systemConfig>>, containing:
    {{{
    config.options.chkShowQuickEdit=true;
    }}}
    Alternatively, if you want the toolbar to //always// be displayed, regardless of the option setting, you can add a special keyword, ''show'', to the [[EditTemplate]] syntax, like this:
    {{{
    <div macro='tiddler QuickEditToolbar with: show'></div>
    }}}
    <<<

    /***
    |Name|QuickEditPlugin|
    |Source|http://www.TiddlyTools.com/#QuickEditPlugin|
    |Documentation|http://www.TiddlyTools.com/#QuickEditPlugin|
    |Version|2.4.3|
    |Author|Eric Shulman|
    |License|http://www.TiddlyTools.com/#LegalStatements <br>and [[Creative Commons Attribution-ShareAlike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
    |~CoreVersion|2.1|
    |Type|plugin|
    |Requires||
    |Overrides||
    |Description|Support functions for ~QuickEdit package: styles, utility functions, and 'toggleQuickEdit' command|
    !!!!!Revisions
    <<<
    2009.06.11 [2.4.3] added keyup() function to abbreviate listbox handling for CR and ESC
    2009.05.07 [2.4.2] added processed() function to abbreviate event handler code
    2008.09.07 [2.4.1] added removeCookie() function for compatibility with [[CookieManagerPlugin]]
    2008.05.17 [2.4.0] copied code from StickyPopupPlugin to remove dependency
    2008.05.12 [2.3.0] added "toggleQuickEdit" command handler (replaces inline script command)
    2008.01.11 [2.2.0] converted from inline script
    2007.03.29 [1.0.0] initial release (as inline script)
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.QuickEditPlugin= {major: 2, minor: 4, revision: 3, date: new Date(2009,6,11)};

    // SET STYLESHEET
    setStylesheet("\
    .quickEdit a { border:2px outset ButtonFace; padding:0px 3px !important; \
    	-moz-border-radius:.5em; -webkit-border-radius:.5em; \
    	-moz-appearance:button !important; -webkit-appearance:push-button !important; \
    	background-color:ButtonFace; color:ButtonText !important;  \
    	line-height:200%; font-weight:normal; } \
    .quickEdit a:hover { border: 2px inset ButtonFace; background-color:ButtonFace; }\
    ", "quickEditStyles");

    // REMOVE COOKIE
    if (window.removeCookie===undefined) {
    	window.removeCookie=function(name) {
    		document.cookie = name+'=; expires=Thu, 01-Jan-1970 00:00:01 UTC; path=/;';
    	}
    }

    // UTILITY FUNCTIONS
    config.quickEdit = {
    	processed: function(ev) { ev=ev||window.event;
    		ev.cancelBubble=true;
    		if(ev.stopPropagation) ev.stopPropagation();
    		return false;
    	},
    	keyup: function(ev){ var k=(ev||window.event).keyCode;
    		if (k==13) this.onclick();
    		if (k==27) Popup.remove();
    	},
    	getField: function(where) {
    		var here=story.findContainingTiddler(where); if (!here) return null;
    		var e=story.getTiddlerField(here.getAttribute("tiddler"),"text");
    		if (e&&e.getAttribute("edit")=="text") return e;
    		return null;
    	},
    	setSelection: function(where,newtext) {
    		var e=this.getField(where); if (!e) return false;
    		e.focus(); replaceSelection(e,newtext);
    		return false;
    	},
    	wrapSelection: function(where,before,after) {
    		var e=this.getField(where); if (!e) return false;
    		e.focus(); replaceSelection(e,before+config.quickEdit.getSelection(e)+after);
    		return false;
    	},
    	getSelection: function(e) {
    		var seltext="";
    		if (e&&e.setSelectionRange)
    			seltext=e.value.substr(e.selectionStart,e.selectionEnd-e.selectionStart);
    		else if (document.selection) {
    			var range = document.selection.createRange();
    			if (range.parentElement()==e) seltext=range.text
    		}
    		return seltext;
    	},
    	promptForFilename: function(msg,path,file) {
    		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='jpg';
    				picker.defaultString=file;
    				picker.appendFilters(nsIFilePicker.filterAll|nsIFilePicker.filterImages);
    				if (picker.show()!=nsIFilePicker.returnCancel)
    					var result="file:///"+picker.file.persistentDescriptor.replace(/\\/g,'/');
    			}
    			catch(e) { alert('error during local file access: '+e.toString()) }
    		}
    		else { // IE
    			try { // XP only
    				var s = new ActiveXObject('UserAccounts.CommonDialog');
    				s.Filter='All files|*.*|JPG files|*.jpg|GIF files|*.gif|PNG files|*.png|';
    				s.FilterIndex=1; // default to JPG
    				s.InitialDir=path;
    				s.FileName=file;
    				if (s.showOpen()) var result=s.FileName;
    			}
    			catch(e) { var result=prompt(msg,path+file); } // fallback for non-XP IE
    		}
    		return result;
    	}
    }
    //}}}

    //{{{
    if (config.options.chkShowQuickEdit===undefined) config.options.chkShowQuickEdit=false;
    config.commands.toggleQuickEdit = {
    	hideReadOnly: true,
    	getText: function() { return config.options.chkShowQuickEdit?'\u221Aquickedit':'quickedit'; },

    	tooltip: 'show QuickEdit toolbar buttons',
    	handler: function(event,src,title) {
    		config.options.chkShowQuickEdit=!config.options.chkShowQuickEdit;
    		config.macros.option.propagateOption("chkShowQuickEdit","checked", config.options.chkShowQuickEdit,"input");
    		if (config.options.chkShowQuickEdit) saveOptionCookie("chkShowQuickEdit");
    		else removeCookie("chkShowQuickEdit");
    		src.innerHTML=config.commands.toggleQuickEdit.getText();
    		story.forEachTiddler(function(t,e){if (story.isDirty(t)) refreshElements(e);});
    		return false;
    	}
    };
    //}}}

    // // COPIED FROM [[StickyPopupPlugin]] TO ELIMINATE PLUGIN DEPENDENCY
    //{{{
    if (config.options.chkStickyPopups==undefined) config.options.chkStickyPopups=false;
    Popup.stickyPopup_onDocumentClick = function(ev)
    {
    	// if click is in a sticky popup, ignore it so popup will remain visible
    	var e = ev ? ev : window.event; var target = resolveTarget(e);
    	var p=target; while (p) {
    		if (hasClass(p,"popup") && (hasClass(p,"sticky")||config.options.chkStickyPopups)) break;
    		else p=p.parentNode;
    	}
    	if (!p) // not in sticky popup (or sticky popups disabled)... use normal click handling
    		Popup.onDocumentClick(ev);
    	return true;
    };
    try{removeEvent(document,"click",Popup.onDocumentClick);}catch(e){};
    try{addEvent(document,"click",Popup.stickyPopup_onDocumentClick);}catch(e){};
    //}}}

    /%
    |Name|QuickEditToolbar|
    |Source|http://www.TiddlyTools.com/#QuickEditToolbar|
    |Version|2.4.3|
    |Author|Eric Shulman|
    |License|http://www.TiddlyTools.com/#LegalStatements|
    |~CoreVersion|2.2|
    |Type|transclusion|
    |Requires|QuickEditPlugin|
    |Optional|QuickEdit_*|
    |Description|format/insert TiddlyWiki content using toolbar buttons|

    Usage:
    * install [[QuickEditPlugin]] (runtime support functions)

    * add the toolbar to [[EditTemplate]]:
    	<div macro='tiddler QuickEditToolbar with: show'></div>

    * 'show' (optional) forces the toolbar to always be displayed or,
      omit keyword and use <<option chkShowQuickEdit>> setting

    * selected QuickEdit buttons can also be added individually to the
      regular tiddler toolbar by adding references directly in [[EditTemplate]]:
    	<span class='toolbar' macro='tiddler QuickEdit_...'></span>

    * see [[QuickEditPackage]] for additional installation options

    %/<<tiddler HideTiddlerTags>>/%
    %/{{hidden fine center quickEdit{
    <<tiddler {{ // show/hide toolbar
    	var here=story.findContainingTiddler(place); if (here) var tid=here.getAttribute('tiddler');
    	var show='$1'!='$'+'1'||config.options.chkShowQuickEdit||tid=='QuickEditToolbar';
    	place.style.display=show?'block':'none';
    '';}}>>/%

    TOOLBAR DEFINITION - add, remove, or re-order items as desired:
    = = = = = = = = = =
    %/<<tiddler QuickEdit_replace>>/%
    %/<<tiddler QuickEdit_split>>/%
    %/<<tiddler QuickEdit_sort>>/%
    %/<<tiddler QuickEdit_convert>>/%
    %/ &nbsp;/% (SPACER)
    %/<<tiddler QuickEdit_link>>/%
    %/<<tiddler QuickEdit_insert>>/%
    %/<<tiddler QuickEdit_macro>>/%
    %/<<tiddler QuickEdit_image>>/%
    %/ &nbsp;/% (SPACER)
    %/<<tiddler QuickEdit_format>>/%
    %/<<tiddler QuickEdit_align>>/%
    %/<<tiddler QuickEdit_color>>/%
    %/<<tiddler QuickEdit_font>>/%
    %/ &nbsp;/% (SPACER)
    %/<<tiddler QuickEdit_custom>>/%
    %/}}}

    /%
    |Name|QuickEdit_align|
    |Source|http://www.TiddlyTools.com/#QuickEdit_align|
    |Version|2.4.3|
    |Author|Eric Shulman|
    |License|see http://www.TiddlyTools.com/#QuickEditPlugin|
    |Type|html|
    |Requires|QuickEditPlugin|
    |Description|quickedit - text alignment|

    Usage: see  http://www.TiddlyTools.com/#QuickEditToolbar

    %/<html><hide linebreaks><a href="javascript:;" class="tiddlyLink" tabindex="-1"
    title="align text"
    onclick="var p=Popup.create(this); if (!p) return false; p.className+=' sticky smallform';
    	var s=createTiddlyElement(p,'select'); s.button=this;
    	s.options[0]=new Option('select text alignment...','');
    	s.options[s.length]=new Option('left','left');
    	s.options[s.length-1].title='{{left{...}}}';
    	s.options[s.length]=new Option('center','center');
    	s.options[s.length-1].title='{{center{...}}}';
    	s.options[s.length]=new Option('right','right');
    	s.options[s.length-1].title='{{right{...}}}';
    	s.options[s.length]=new Option('justify','justify');
    	s.options[s.length-1].title='{{justify{...}}}';
    	s.options[s.length]=new Option('float left','floatleft');
    	s.options[s.length-1].title='{{floatleft{...}}}';
    	s.options[s.length]=new Option('float right','floatright');
    	s.options[s.length-1].title='{{floatright{...}}}';
    	s.size=s.length;
    	s.onclick=function(){ if (!this.value.length) return;
    		config.quickEdit.wrapSelection(this.button,'{{'+this.value+'{','}}}');
    		Popup.remove(); return false;
    	};
    	s.onkeyup=config.quickEdit.keyup;
    	Popup.show();
    	s.focus();
    	return config.quickEdit.processed(event);"
    >align</a></html>

    /%
    |Name|QuickEdit_color|
    |Source|http://www.TiddlyTools.com/#QuickEdit_color|
    |Version|2.4.3|
    |Author|Eric Shulman|
    |License|see http://www.TiddlyTools.com/#QuickEditPlugin|
    |Type|html|
    |Requires|QuickEditPlugin|
    |Description|quickedit - text/background color|

    Usage: see  http://www.TiddlyTools.com/#QuickEditToolbar

    %/<html><hide linebreaks><a href="javascript:;" class="tiddlyLink" tabindex="-1"
    title="text/background color - @@color:#RGB;background-color:#RGB;...@@"
    onclick="var p=Popup.create(this,null,'popup sticky smallform'); if (!p) return false;
     	p.style.padding='2px';
    	function hex(d) { return '0123456789ABCDEF'.substr(d,1); }
    	var fg=createTiddlyElement(p,'select'); fg.button=this;
    	fg.style.width='12em';
    	fg.options[0]=new Option('text color...','');
    	fg.options[1]=new Option('\xa0 or enter a value','_ask');
    	fg.options[2]=new Option('\xa0 or use default color','');
    	for (var r=0;r<16;r+=3) for (var g=0;g<16;g+=3) for (var b=0;b<16;b+=3) {
    		var label=hex(r)+hex(g)+hex(b);
    		fg.options[fg.length]=new Option(label,'#'+label);
    		fg.options[fg.length-1].style.color='#'+label;
    	}
    	fg.onchange=function(){ var val=this.value;
    		if (val=='_ask') { val=prompt('Enter a CSS color value');
    		if (!val||!val.length) return false; }
    		this.options[0].value=val; this.options[0].text=val.length?'text: '+val:'text color...';
    		var bg=this.nextSibling;
    		for (var i=3;i<bg.options.length;i++) bg.options[i].style.color=val;
    		var preview=this.nextSibling.nextSibling.nextSibling;
    		var t=config.quickEdit.getSelection(config.quickEdit.getField(this.button));
    		t=t.replace(/^@@(color\:.+;)?(background-color\:.+;)?/,'').replace(/@@$/,'');
    		if (!t.length) t='~AaBbCcDdEeFfGgHhIiJj 1234567890';
    		var fg=this.value; if (fg.length) fg='color:'+fg+';';
    		var bg=this.nextSibling.value; if (bg.length) bg='background-color:'+bg+';';
    		if (fg.length||bg.length) t='@@'+fg+bg+t+'@@';
    		removeChildren(preview); wikify(t,preview);
    		this.selectedIndex=0; return false;
    	};
    	var bg=createTiddlyElement(p,'select'); bg.button=this;
    	bg.style.width='12em';
    	bg.options[0]=new Option('background color...','');
    	bg.options[1]=new Option('\xa0 or enter a value','_ask');
    	bg.options[2]=new Option('\xa0 or use default color','');
    	for (var r=0;r<16;r+=3) for (var g=0;g<16;g+=3) for (var b=0;b<16;b+=3) {
    		var label=hex(15-r)+hex(15-g)+hex(15-b);
    		bg.options[bg.length]=new Option(label,'#'+label);
    		bg.options[bg.length-1].style.backgroundColor='#'+label;
    	}
    	bg.onchange=function(){ var val=this.value;
    		if (val=='_ask') { val=prompt('Enter a CSS color value');
    		if (!val||!val.length) return false; }
    		this.options[0].value=val;
    		this.options[0].text=val.length?'background: '+val:'background color...';
    		var fg=this.previousSibling;
    		for (var i=3;i<fg.options.length;i++) fg.options[i].style.backgroundColor=val;
    		var preview=this.nextSibling.nextSibling;
    		var t=config.quickEdit.getSelection(config.quickEdit.getField(this.button));
    		t=t.replace(/^@@(color\:.+;)?(background-color\:.+;)?/,'').replace(/@@$/,'');
    		if (!t.length) t='~AaBbCcDdEeFfGgHhIiJj 1234567890';
    		var fg=this.previousSibling.value; if (fg.length) fg='color:'+fg+';';
    		var bg=this.value; if (bg.length) bg='background-color:'+bg+';';
    		if (fg.length||bg.length) t='@@'+fg+bg+t+'@@';
    		removeChildren(preview); wikify(t,preview);
    		this.selectedIndex=0; return false;
    	};
    	var b=createTiddlyElement(p,'input',null,null,null,{type:'button'}); b.button=this;
    	b.value='ok'; b.style.width='4em';
    	b.onclick=function() {
    		var fg=this.previousSibling.previousSibling.value; if (fg.length) fg='color:'+fg+';';
    		var bg=this.previousSibling.value; if (bg.length) bg='background-color:'+bg+';';
    		var t=config.quickEdit.getSelection(config.quickEdit.getField(this.button));
    		t=t.replace(/^@@(color\:.+;)?(background-color\:.+;)?/,'').replace(/@@$/,'');
    		if (fg.length||bg.length) config.quickEdit.setSelection(this.button,'@@'+fg+bg+t+'@@');
    		Popup.remove(); return false;
    	};
    	var preview=createTiddlyElement(p,'div',null,'viewer'); var s=preview.style;
    	s.border='1px solid'; s.margin='2px'; s.width='24em'; s.padding='3px'; s.MozBorderRadius='3px';
    	s.overflow='hidden'; s.textAlign='center'; s.whiteSpace='normal';
    	var t=config.quickEdit.getSelection(config.quickEdit.getField(this));
    	wikify(t.length?t:'~AaBbCcDdEeFfGgHhIiJj 1234567890',preview);
    	Popup.show();
    	event.cancelBubble=true;if(event.stopPropagation)event.stopPropagation();return false;"
    >color</a></html>

    /%
    |Name|QuickEdit_convert|
    |Source|http://www.TiddlyTools.com/#QuickEdit_convert|
    |Version|2.4.3|
    |Author|Eric Shulman|
    |License|see http://www.TiddlyTools.com/#QuickEditPlugin|
    |Type|html|
    |Requires|QuickEditPlugin|
    |Description|quickedit - convert between comma/tab-separated and TW table format|

    Usage: see  http://www.TiddlyTools.com/#QuickEditToolbar

    %/<html><hide linebreaks><a href="javascript:;" class="tiddlyLink" tabindex="-1"
    title="convert between comma/tab-separated and TW table format"
    onclick="var e=config.quickEdit.getField(this);
    	if (e) e.focus(); var txt=config.quickEdit.getSelection(e);
    	if (txt.indexOf(',')+txt.indexOf('\t')+txt.indexOf('|')==-3) {
    		alert('Please select text containing tabs, commas, or TiddlyWiki table syntax.');
    		return false;
    	}
    	var p=Popup.create(this); if (!p) return false; p.className+=' sticky smallform';
    	var s=createTiddlyElement(p,'select'); s.button=this;
    	s.options[0]=new Option('select a converter...','');
    	if (txt.indexOf(',')!=-1) {
    		s.options[s.length]=new Option('commas -> table','commasToTable');
    		s.options[s.length]=new Option('commas -> tabs','commasToTabs');
    	}
    	if (txt.indexOf('\t')!=-1) {
    		s.options[s.length]=new Option('tabs -> table','tabsToTable');
    		s.options[s.length]=new Option('tabs -> commas','tabsToCommas');
    	}
    	if (txt.indexOf('|')!=-1) {
    		s.options[s.length]=new Option('table -> tabs','tableToTabs');
    		s.options[s.length]=new Option('table -> commas','tableToCommas');
    	}
    	s.size=s.length;
    	s.onclick=function(){ if (!this.value.length) return;
    	        var e=config.quickEdit.getField(this.button); if (!e) return false;
    		e.focus(); var txt=config.quickEdit.getSelection(e);
    		switch(this.value) {
    			case 'tabsToTable':
    				txt=txt.replace(/\t/g,'|').replace(/^|$/g,'|');
    				txt=txt.replace(/\n/g,'|\n|').replace(/^\|$/g,'');
    				break;
    			case 'tableToTabs':
    				txt=txt.replace(/\t/g,' ').replace(/\|/g,'\t');
    				txt=txt.replace(/^\t/g,'').replace(/\t$/g,'');
    				txt=txt.replace(/\n\t/g,'\n').replace(/\t\n/g,'\n');
    				break;
    			case 'commasToTable':
    				txt=txt.replace(/,/g,'|').replace(/^|$/g,'|');
    				txt=txt.replace(/\n/g,'|\n|').replace(/^\|$/g,'');
    				break;
    			case 'tableToCommas':
    				txt=txt.replace(/,/g,' ').replace(/\|/g,',');
    				txt=txt.replace(/^,/g,'').replace(/,$/g,'');
    				txt=txt.replace(/\n,/g,'\n').replace(/,\n/g,'\n');
    				break;
    			case 'tabsToCommas':
    				txt=txt.replace(/\t/g,',');
    				break;
    			case 'commasToTabs':
    				txt=txt.replace(/,/g,'\t');
    				break;
    		}
    		replaceSelection(e,txt);
    		Popup.remove(); return false;
    	};
    	s.onkeyup=config.quickEdit.keyup;
    	Popup.show();
    	s.focus();
    	return config.quickEdit.processed(event);"
    >convert</a></html>

    /%
    |Name|QuickEdit_custom|
    |Source|http://www.TiddlyTools.com/#QuickEdit_custom|
    |Version|2.4.3|
    |Author|Eric Shulman|
    |License|see http://www.TiddlyTools.com/#QuickEditPlugin|
    |Type|html|
    |Requires|QuickEditPlugin|
    |Description|quickedit - custom defined formats|

    Usage: see  http://www.TiddlyTools.com/#QuickEditToolbar

    !help
    Reminders:

    Custom formats are stored as an "HR-separated list" in [[QuickEdit_customList]], where the first line of each list item is the text 'label' to show in the droplist, followed by one or more lines of wiki content to be inserted into the tiddler source.

    Substitution markers can be used to dynamically insert values into the formatted output: $1 inserts the tiddler editor's current selected text. $[[message|default value]] interactively prompts for a value to be inserted. $[[message|$1]] uses the selected text as the default value. $[[message|{{javascript}}]] calculates the default value using javascript code.
    !end help

    %/<html><hide linebreaks><a href="javascript:;" class="tiddlyLink" tabindex="-1" title="custom defined formats"
    onclick="var p=Popup.create(this); if (!p) return false; p.className+=' sticky smallform';
    	var s=createTiddlyElement(p,'select'); s.button=this;
    	s.options[0]=new Option('select a custom format...','');
    	var items=store.getTiddlerText('QuickEdit_customList','').split('\n----\n');
    	for (var i=0; i<items.length; i++) {
    		if (!items[i].length) continue; var lines=items[i].split('\n');
    		var label=lines.shift(); var val=lines.join('\n');
    		s.options[s.length]=new Option(label,val); s.options[s.length-1].title=val;
    	}
    	s.options[s.length]=new Option('[Edit custom formats...]','_edit');
    	s.options[s.length-1].title='add/change custom format definitions...';
    	s.size=Math.min(s.length,15);
    	s.onclick=function(){ if (!this.value.length) return;
    		if (this.value=='_edit') {
    			alert(store.getTiddlerText('QuickEdit_custom##help'));
    			story.displayTiddler(story.findContainingTiddler(this.button),
    				'QuickEdit_customList',DEFAULT_EDIT_TEMPLATE);
    		} else {
    		        var e=config.quickEdit.getField(this.button); if (!e) return false;
    			e.focus(); var txt=config.quickEdit.getSelection(e);
    			replaceSelection(e, this.value.replace(/\$\x31/g,txt)
    				.replace(/\$\[\[[^\]]+\]\]/g, function(t){
    					x=t.substr(3,t.length-5).split('|');
    					var msg=x[0]; var def=x[1]||'';
    					if (def.startsWith('{{')) {
    						try{def=eval(def.substr(2,def.length-4))} catch(ex){showException(ex)}
    					}
    					return prompt(msg,def)||'';
    				})
    			);
    		}
    		Popup.remove(); return false;
    	};
    	s.onkeyup=config.quickEdit.keyup;
    	Popup.show();
    	s.focus();
    	return config.quickEdit.processed(event);"
    >custom</a></html>

    timestamp
    $[[enter a date|{{new Date().formatString('DDD, MMM DDth, YYYY hh12:0mm:0ssam')}}]]
    ----
    scrollbox
    @@display:block;height:10em;overflow:auto;$[[enter scrolling content|$1]]@@@@display:block;text-align:right;^^scroll for more...^^@@
    ----
    nested slider
    +++[$1]<<tiddler $1>>===
    ----
    big red
    @@font-size:36pt;color:red;$1@@
    ----

    /%
    |Name|QuickEdit_font|
    |Source|http://www.TiddlyTools.com/#QuickEdit_font|
    |Version|2.4.3|
    |Author|Eric Shulman|
    |License|see http://www.TiddlyTools.com/#QuickEditPlugin|
    |Type|html|
    |Requires|QuickEditPlugin|
    |Description|quickedit - select font family|

    Usage: see  http://www.TiddlyTools.com/#QuickEditToolbar

    %/<html><hide linebreaks><a href="javascript:;" class="tiddlyLink" tabindex="-1"
    title="set font-family CSS attribute - @@font-family:facename;...@@"
    onclick="var p=Popup.create(this); if (!p) return false; p.className+=' sticky smallform';
    	var s=createTiddlyElement(p,'select'); s.button=this;
    	s.options[0]=new Option('select a font family...','');
    	var fonts=store.getTiddlerText('QuickEdit_fontList','').split('\n');
    	for (var i=0; i<fonts.length; i++) {
    		if (!fonts[i].length) continue;
    		s.options[s.length]=new Option(fonts[i],fonts[i]);
    		s.options[s.length-1].style.fontFamily=fonts[i];
    	}
    	s.options[s.length]=new Option('[Edit font list...]','_edit');
    	s.options[s.length-1].title='enter fonts, one per line...';
    	s.size=Math.min(s.length,15);
    	s.onclick=function(){
    		if (this.value=='_edit')
    			story.displayTiddler(story.findContainingTiddler(this.button),'QuickEdit_fontList',DEFAULT_EDIT_TEMPLATE);
    		else
    			config.quickEdit.wrapSelection(this.button,'@@font-family:\x22'+this.value+'\x22;','@@');
    		Popup.remove(); return false;
    	};
    	s.onkeyup=config.quickEdit.keyup;
    	Popup.show();
    	s.focus();
    	return config.quickEdit.processed(event);"
    >font</a></html>

    Arial,helvetica,sans-serif
    Times New Roman,times,serif
    Courier,monospaced

    /%
    |Name|QuickEdit_format|
    |Source|http://www.TiddlyTools.com/#QuickEdit_format|
    |Version|2.4.3|
    |Author|Eric Shulman|
    |License|see http://www.TiddlyTools.com/#QuickEditPlugin|
    |Type|html|
    |Requires|QuickEditPlugin|
    |Description|quickedit - basic text formats, headings, blockquotes, etc.|

    Usage: see  http://www.TiddlyTools.com/#QuickEditToolbar

    %/<html><hide linebreaks><a href="javascript:;" class="tiddlyLink" tabindex="-1"
    title="plain text (remove ALL formatting)" accesskey="P"
    onclick="var e=config.quickEdit.getField(this); if (e) e.focus(); var txt=config.quickEdit.getSelection(e);
    	config.quickEdit.setSelection(e,wikifyPlainText(txt)); return false;"
    >&nbsp;~&nbsp;</a></html>/%

    %/<html><hide linebreaks><a href="javascript:;" class="tiddlyLink" tabindex="-1"
    title="''bold''" accesskey="B"
    onclick="config.quickEdit.wrapSelection(this,'\x27\x27','\x27\x27'); return false;"
    >&nbsp;B&nbsp;</a></html>/%

    %/<html><hide linebreaks><a href="javascript:;" class="tiddlyLink" tabindex="-1"
    title="//italics//" accesskey="I"
    onclick="config.quickEdit.wrapSelection(this,'//','//'); return false;"
    >&nbsp;I&nbsp;</a></html>/%

    %/<html><hide linebreaks><a href="javascript:;" class="tiddlyLink" tabindex="-1"
    title="__underline__" accesskey="U"
    onclick="config.quickEdit.wrapSelection(this,'__','__'); return false;"
    >&nbsp;U&nbsp;</a></html>/%

    %/<html><hide linebreaks><a href="javascript:;" class="tiddlyLink" tabindex="-1"
    title="--strikethrough--" accesskey="S"
    onclick="config.quickEdit.wrapSelection(this,'--','--'); return false;"
    >&nbsp;S&nbsp;</a></html>/%

    %/ &nbsp;/%  SPACER

    %/<html><hide linebreaks><a href="javascript:;" class="tiddlyLink" tabindex="-1"
    title="format text"
    onclick="var p=Popup.create(this); if (!p) return false; p.className+=' sticky smallform';
    	var s=createTiddlyElement(p,'select'); s.button=this;
    	s.options[0]=new Option('select text format...','');
    	s.options[s.length]=new Option('CSS class wrapper','{{$1{,}}},Enter a CSS classname');
    	s.options[s.length-1].title='CSS class wrapper - {{classname classname etc{...}}}';
    	s.options[s.length]=new Option('inline CSS styles','@@$1,@@,Enter CSS (attribute:value;attribute:value;...;)');
    	s.options[s.length-1].title='inline CSS styles - @@attr:value;attr:value;...@@';
    	s.options[s.length]=new Option('heading 1','\n!,\n');
    	s.options[s.length-1].title='H1 heading - !';
    	s.options[s.length]=new Option('heading 2','\n!!,\n');
    	s.options[s.length-1].title='H2 heading - !!';
    	s.options[s.length]=new Option('heading 3','\n!!!,\n');
    	s.options[s.length-1].title='H3 heading - !!!';
    	s.options[s.length]=new Option('heading 4','\n!!!!,\n');
    	s.options[s.length-1].title='H4 heading - !!!!';
    	s.options[s.length]=new Option('heading 5','\n!!!!!,\n');
    	s.options[s.length-1].title='H5 heading - !!!!!';
    	s.options[s.length]=new Option('blockquote','\n\<\<\<\n,\n\<\<\<\n');
    	s.options[s.length-1].title='indented blockquote - \<\<\<';
    	s.options[s.length]=new Option('monospaced','{{{,}}}');
    	s.options[s.length-1].title='inline monospaced text - {{{...}}}';
    	s.options[s.length]=new Option('plain text','\n{{{\n,\n}}}\n');
    	s.options[s.length-1].title='multi-line monospaced text box - {{{...}}}';
    	s.options[s.length]=new Option('superscript','^^,^^');
    	s.options[s.length-1].title='^^superscript^^';
    	s.options[s.length]=new Option('subscript','~~,~~');
    	s.options[s.length-1].title='~~subscript~~';
    	s.options[s.length]=new Option('HTML','<html>,<\x2fhtml>');
    	s.options[s.length-1].title='HTML syntax - <html>...<\x2fhtml>';
    	s.options[s.length]=new Option('comment','/%,%/');
    	s.options[s.length-1].title='comment (hidden content) - /%...%/';
    	s.size=s.length;
    	s.onclick=function(){ if (!this.value.length) return;
    		var parts=this.value.split(',');
    		var prefix=parts[0]; var suffix=parts[1]; var ask=parts[2];
    		if (ask) {
    			var val=prompt(ask); if (!val) { Popup.remove(); return false; }
    			prefix=prefix.replace(/\$1/g,val); suffix=suffix.replace(/\$1/g,val);
    		}
    		config.quickEdit.wrapSelection(this.button,prefix,suffix);
    		Popup.remove(); return false;
    	};
    	s.onkeyup=config.quickEdit.keyup;
    	Popup.show();
    	s.focus();
    	return config.quickEdit.processed(event);"
    >format</a></html>

    /%
    |Name|QuickEdit_image|
    |Source|http://www.TiddlyTools.com/#QuickEdit_image|
    |Version|2.4.3|
    |Author|Eric Shulman|
    |License|see http://www.TiddlyTools.com/#QuickEditPlugin|
    |Type|html|
    |Requires|QuickEditPlugin|
    |Description|quickedit - embed an image|

    Usage: see  http://www.TiddlyTools.com/#QuickEditToolbar

    %/<html><hide linebreaks><a href="javascript:;" class="tiddlyLink" tabindex="-1"
    	title="embed an image (jpg/gif/png) - [img[tooltip|URL]] or [img[tooltip|path/to/file.ext]]"
    	onclick="var fn=config.quickEdit.promptForFilename(
    		'Enter/select an image file',getLocalPath(document.location.href),'');
    	if (!fn) return false;  /* cancelled by user */
    	var h=document.location.href; var p=decodeURIComponent(h.substr(0,h.lastIndexOf('/')+1));
    	if (fn.startsWith(p)) fn=fn.substr(p.length); /* use RELATIVE path/filename.ext */
    	var tip=prompt('Enter a tooltip for this image',''); if (!tip) tip=''; else tip+='|';
    	return config.quickEdit.setSelection(this,'[img['+tip+fn+']]');"
    >image</a></html>

    /%
    |Name|QuickEdit_insert|
    |Source|http://www.TiddlyTools.com/#QuickEdit_insert|
    |Version|2.4.3|
    |Author|Eric Shulman|
    |License|see http://www.TiddlyTools.com/#QuickEditPlugin|
    |Type|html|
    |Requires|QuickEditPlugin|
    |Description|quickedit - insert content from another tiddler or external file|

    Usage: see  http://www.TiddlyTools.com/#QuickEditToolbar

    %/<html><hide linebreaks><a href="javascript:;" class="tiddlyLink" tabindex="-1"
    title="insert content from another tiddler or external file"
    onclick="var p=Popup.create(this); if (!p) return false; p.className+=' sticky smallform';

    	var s2=createTiddlyElement(p,'select'); s2.title='filter by tag';
    	s2.options[0]=new Option('filter by tag...','');
    	s2.options[s2.length]=new Option('[all tiddlers]','');
    	var tags=store.getTags();
    	for (var t=0; t<tags.length; t++) s2.options[s2.length]=new Option(tags[t][0],tags[t][0]);
    	s2.onchange=function(){
    		var tag=this.value;
    		var tids=tag.length?store.reverseLookup('tags',tag,true):store.reverseLookup('tags','excludeLists');
    		var list=this.nextSibling.nextSibling;
    		while (list.length) list.options[0]=null;
    		var prompt='select a tiddler or file...';
    		if (tag.length) prompt='select a tagged tiddler ['+tids.length+' matches]...';
    		list.options[0]=new Option(prompt,'');
    		if (!tag.length) list.options[list.length]=new Option('[browse for file...]','_file');
    		for (var t=0; t<tids.length; t++) {
    			list.options[list.length]=new Option(tids[t].title,tids[t].title);
    			list.options[list.length-1].title=tids[t].getSubtitle();
    		}
    		list.size=Math.min(list.length,10);
    		list.selectedIndex=0; list.focus();
    		this.style.width=list.offsetWidth+'px';
    		if (!tag.length) this.selectedIndex=0;
    	};
    	createTiddlyElement(p,'br');

    	var s=createTiddlyElement(p,'select'); s.button=this;
    	s.title='select a tiddler or file';
    	s.options[0]=new Option('select a tiddler or file...','');
    	s.options[s.length]=new Option('[browse for file...]','_file');
    	var tids=store.reverseLookup('tags','excludeLists');
    	for (var t=0; t<tids.length; t++) {
    		s.options[s.length]=new Option(tids[t].title,tids[t].title);
    		s.options[s.length-1].title=tids[t].getSubtitle();
    	}
    	s.size=Math.min(s.length,10);
    	s.onclick=function(){ if (!this.value.length) return false;
    		if (this.value=='_file') {
    			var fn=config.quickEdit.promptForFilename(
    				'Enter/select a text file',getLocalPath(document.location.href),'');
    			if (!fn) return false; /* cancelled by user */
    			var txt=loadFile(getLocalPath(fn));
    			if (!txt) { alert('Error: unable to read contents from \0027'+fn+'\0027'); return; }
    		}
    		else var txt=store.getTiddlerText(this.value);
    		if (!txt) {
    			displayMessage(this.value+' not found');
    			this.selectedIndex=0; this.focus();
    			return false;
    		}
    		config.quickEdit.setSelection(this.button,txt);
    		Popup.remove(); return false;
    	};
    	s.onkeyup=config.quickEdit.keyup;
    	Popup.show();
    	s2.style.width=s.offsetWidth+'px';
    	s.focus();
    	return config.quickEdit.processed(event);"
    >insert</a></html>

    /%
    |Name|QuickEdit_link|
    |Source|http://www.TiddlyTools.com/#QuickEdit_link|
    |Version|2.4.3|
    |Author|Eric Shulman|
    |License|see http://www.TiddlyTools.com/#QuickEditPlugin|
    |Type|html|
    |Requires|QuickEditPlugin|
    |Description|quickedit - link to tiddler or external file|

    Usage: see  http://www.TiddlyTools.com/#QuickEditToolbar

    %/<html><hide linebreaks><a href="javascript:;" class="tiddlyLink" tabindex="-1"
    title="add a link to a tiddler or external file - [[link text|TiddlerName]]"
    onclick="var p=Popup.create(this); if (!p) return false; p.className+=' sticky smallform';

    	var s2=createTiddlyElement(p,'select'); s2.title='filter by tag';
    	s2.options[0]=new Option('filter by tag...','');
    	s2.options[s2.length]=new Option('[all tiddlers]','');
    	var tags=store.getTags();
    	for (var t=0; t<tags.length; t++) s2.options[s2.length]=new Option(tags[t][0],tags[t][0]);
    	s2.onchange=function(){
    		var tag=this.value;
    		var tids=tag.length?store.reverseLookup('tags',tag,true):store.reverseLookup('tags','excludeLists');
    		var list=this.nextSibling.nextSibling;
    		while (list.length) list.options[0]=null;
    		var prompt='select a tiddler or file...';
    		if (tag.length) prompt='select a tagged tiddler ['+tids.length+' matches]...';
    		list.options[0]=new Option(prompt,'');
    		if (!tag.length) list.options[list.length]=new Option('[browse for file...]','_file');
    		for (var t=0; t<tids.length; t++) {
    			list.options[list.length]=new Option(tids[t].title,tids[t].title);
    			list.options[list.length-1].title=tids[t].getSubtitle();
    		}
    		list.size=Math.min(list.length,10);
    		list.selectedIndex=0; list.focus();
    		this.style.width=list.offsetWidth+'px';
    		if (!tag.length) this.selectedIndex=0;
    	};
    	createTiddlyElement(p,'br');

    	var s=createTiddlyElement(p,'select'); s.button=this;
    	s.title='select a tiddler or file';
    	s.options[0]=new Option('select a tiddler or file...','');
    	s.options[s.length]=new Option('[browse for file...]','_file');
    	var tids=store.reverseLookup('tags','excludeLists');
    	for (var t=0; t<tids.length; t++) {
    		s.options[s.length]=new Option(tids[t].title,tids[t].title);
    		s.options[s.length-1].title=tids[t].getSubtitle();
    	}
    	s.size=Math.min(s.length,10);
    	s.onclick=function(){ if (!this.value.length) return false;
    		var title=this.value; var txt=title;
    		if (title=='_file') {
    			title=config.quickEdit.promptForFilename('Select a file',
    				getLocalPath(document.location.href),'');
    			if (!title) { this.selectedIndex=0; this.focus(); return false; }
    			var txt=title.substr(title.lastIndexOf('/')+1);
    		}
    		var txt=prompt('Enter the text to display for this link',txt);
    		if (!txt) { this.selectedIndex=0; this.focus(); return false; }
    		config.quickEdit.setSelection(this.button,'[['+txt+'|'+title+']]');
    		Popup.remove(); return false;
    	};
    	s.onkeyup=config.quickEdit.keyup;
    	Popup.show();
    	s2.style.width=s.offsetWidth+'px';
    	s.focus();
    	return config.quickEdit.processed(event);"
    >link</a></html>

    /%
    |Name|QuickEdit_macro|
    |Source|http://www.TiddlyTools.com/#QuickEdit_macro|
    |Version|2.4.3|
    |Author|Eric Shulman|
    |License|see http://www.TiddlyTools.com/#QuickEditPlugin|
    |Type|html|
    |Requires|QuickEditPlugin|
    |Description|quickedit - embed a macro with 'guide text'|

    Usage: see  http://www.TiddlyTools.com/#QuickEditToolbar

    Note:
    Optional 'guideText' can be used to add suggested defaults/placeholders for specific macro parameters.
    Add guideText to your own plugin-defined macros using:
    	config.macros.macroName.guideText='guide text goes here';

    %/<<tiddler {{
    	/* define guide text for a few common TW core macros */
    	config.macros.edit.guideText='fieldname #rows';
    	config.macros.view.guideText='fieldname (link,wikified,date) format';
    	config.macros.slider.guideText='cookie TiddlerName label tooltip';
    	config.macros.option.guideText='(txtCookieName,chkCookieName)';
    	config.macros.tiddler.guideText='TiddlerName with: params...';
    	''; /* must return blank to suppress output */ }}>>/%

    %/<html><hide linebreaks><a href='javascript:;' class='tiddlyLink' tabindex='-1'
    title='add a macro - \<\<macroName ...\>\>'
    onclick="var p=Popup.create(this); if (!p) return false; p.className+=' sticky smallform';
    	var s=createTiddlyElement(p,'select'); s.button=this;
    	s.options[0]=new Option('select a macro...','');
    	var macros=[]; for (var m in config.macros) if (config.macros[m].handler) macros.push(m); macros.sort();
    	for (var i=0; i<macros.length; i++) { var m=macros[i];
    		var help=config.macros[m].guideText; if (!help) help=''; else help=' '+help;
    		s.options[s.length]=new Option(m,m+help);
    		s.options[s.length-1].title='\<\<'+m+help+'\>\>';
    	}
    	s.size=Math.min(s.length,15);
    	s.onclick=function(){ if (!this.value.length) return;
    		config.quickEdit.setSelection(this.button,'\<\<'+this.value+'\>\>');
    		Popup.remove(); return false;
    	};
    	s.onkeyup=config.quickEdit.keyup;
    	Popup.show();
    	s.focus();
    	return config.quickEdit.processed(event);"
    >macro</a></html>

    /%
    |Name|QuickEdit_replace|
    |Source|http://www.TiddlyTools.com/#QuickEdit_replace|
    |Version|2.4.3|
    |Author|Eric Shulman|
    |License|see http://www.TiddlyTools.com/#QuickEditPlugin|
    |Type|html|
    |Requires|QuickEditPlugin|
    |Description|quickedit - find/replace selected text with replacement text|

    Usage: see  http://www.TiddlyTools.com/#QuickEditToolbar

    %/<html><hide linebreaks><a href="javascript:;" class="tiddlyLink" tabindex="-1"
    title="find/replace selected text with replacement text"
    onclick="var here=story.findContainingTiddler(this); if (!here) return false;
    	var e=config.quickEdit.getField(here);
    	var s=config.quickEdit.getSelection(e);
    	var p=Popup.create(this,null,'popup sticky smallform'); if (!p) return false;
    	var t=createTiddlyElement(p,'input'); t.onfocus=function(){this.select()};
    	t.value=s.length?s:'enter target text';
    	var r=createTiddlyElement(p,'input'); r.onfocus=function(){this.select()};
    	r.value='enter replacement text';
    	var tid=here.getAttribute('tiddler');
    	var b=createTiddlyElement(p,'button',null,null,'?',{tid:tid});
    	b.style.width='2em';
    	b.title='FIND/FIND NEXT target text';
    	b.onclick=function(ev) { /* FIND */
    		var e=story.getTiddlerField(this.getAttribute('tid'),'text');
    		if (!e||e.getAttribute('edit')!='text') return;
    		var t=this.previousSibling.previousSibling;
    		e.focus();
    		if (e.setSelectionRange) { /* MOZ */
    			var newstart=e.value.indexOf(t.value,e.selectionStart+1);
    			if (newstart==-1) newstart=e.value.indexOf(t.value); /* wrap around */
    			if (newstart==-1) { alert('\u0022'+t.value+'\u0022 not found'); t.focus(); return; }
    			e.setSelectionRange(newstart,newstart+t.value.length);
    			var linecount=e.value.split('\n').length;
    			var thisline=e.value.substr(0,e.selectionStart).split('\n').length;
    			e.scrollTop=Math.floor((thisline-1-e.rows/2)*e.scrollHeight/linecount);
    		} else if (document.selection) { /* IE */
    			var range=document.selection.createRange();
    			if(range.parentElement()==e) {
    				range.collapse(false);
    				var found=false; try{found=range.findText(t.value,e.value.length,4)}catch(e){}
    				if (found) range.select();
    				else { alert('\u0022'+t.value+'\u0022 not found'); t.focus(); }
    			}
    		}
    	};
    	b=createTiddlyElement(p,'button',null,null,'=',{tid:tid});
    	b.style.width='2em';
    	b.title='REPLACE selected text';
    	b.onclick=function(ev) { /* REPLACE */
    		var e=story.getTiddlerField(this.getAttribute('tid'),'text');
    		if (!e||e.getAttribute('edit')!='text') return;
    		var t=this.previousSibling.previousSibling.previousSibling;
    		var r=this.previousSibling.previousSibling;
    		if (   (e.selectionStart!==undefined && e.selectionEnd==e.selectionStart)
    		    || (document.selection && document.selection.createRange().text==''))
    			this.previousSibling.click(); /* no selection... do FIND first */
    		if (   (e.selectionStart!==undefined && e.selectionEnd==e.selectionStart)
    		    || (document.selection && document.selection.createRange().text==''))
    			{ t.focus(); return; } /* still no selection... goto target input */
    		e.focus(); replaceSelection(e,r.value);
    	};
    	b=createTiddlyElement(p,'button',null,null,'+',{tid:tid});
    	b.style.width='2em';
    	b.title='REPLACE selected text AND FIND NEXT target text';
    	b.onclick=function(ev) { /* REPLACE and FIND NEXT */
    		this.previousSibling.click();
    		this.previousSibling.previousSibling.click();
    	};
    	b=createTiddlyElement(p,'button',null,null,'!',{tid:tid});
    	b.style.width='2em';
    	b.title='REPLACE ALL occurrences of target text';
    	b.onclick=function(ev) { /* REPLACE ALL */
    		var e=story.getTiddlerField(this.getAttribute('tid'),'text');
    		if (!e||e.getAttribute('edit')!='text') return;
    		var t=this.previousSibling.previousSibling.previousSibling.previousSibling.previousSibling;
    		var r=this.previousSibling.previousSibling.previousSibling.previousSibling;
    		if (!t.value.length) { alert('Please enter the target text'); t.focus(); return; }
    		var m='This will replace all occurences of:\n\n';
    		m+='\''+t.value+'\'\n\nwith:\n\n\''+r.value+'\'\n\nAre you sure?';
    		if (!confirm(m)) { r.focus(); r.select(); return; }
    		e.value=e.value.replace(new RegExp(t.value.escapeRegExp(),'gm'),r.value);
    		e.focus(); e.select(); Popup.remove();
    	};
    	Popup.show();
    	if (!s.length) {t.focus();t.select()} else {r.focus();r.select()}
    	event.cancelBubble=true;if(event.stopPropagation)event.stopPropagation();return false;"
    >replace</a></html>

    /%
    |Name|QuickEdit_sort|
    |Source|http://www.TiddlyTools.com/#QuickEdit_sort|
    |Version|2.4.3|
    |Author|Eric Shulman|
    |License|see http://www.TiddlyTools.com/#QuickEditPlugin|
    |Type|html|
    |Requires|QuickEditPlugin|
    |Description|quickedit - sort lines of text|

    Usage: see  http://www.TiddlyTools.com/#QuickEditToolbar

    %/<html><hide linebreaks><a href="javascript:;" class="tiddlyLink" tabindex="-1"
    title="sort lines of text"
    onclick="var p=Popup.create(this); if (!p) return false; p.className+=' sticky smallform';
    	var s=createTiddlyElement(p,'select'); s.button=this;
    	s.options[0]=new Option('select sort order...','');
    	s.options[s.length]=new Option('ascending','A');
    	s.options[s.length-1].title='ascending';
    	s.options[s.length]=new Option('descending','D');
    	s.options[s.length-1].title='descending';
    	s.size=s.length;
    	s.onclick=function(){ if (!this.value.length) return;
    		var e=config.quickEdit.getField(this.button); if (!e) return false;
    		var lines=config.quickEdit.getSelection(e).split('\n').sort();
    		if (this.value=='D') lines=lines.reverse();
    		replaceSelection(e,lines.join('\n'));
    		e.focus();
    		Popup.remove(); return false;
    	};
    	s.onkeyup=config.quickEdit.keyup;
    	Popup.show();
    	s.focus();
    	return config.quickEdit.processed(event);"
    >sort</a></html>

    /%
    |Name|QuickEdit_split|
    |Source|http://www.TiddlyTools.com/#QuickEdit_split|
    |Version|2.4.3|
    |Author|Eric Shulman|
    |License|see http://www.TiddlyTools.com/#QuickEditPlugin|
    |Type|html|
    |Requires|QuickEditPlugin|
    |Description|quickedit - move selection to new tiddler and insert link, embedded tiddler, or slider|

    Usage: see  http://www.TiddlyTools.com/#QuickEditToolbar

    Based on ideas originally developed by YannPerrin
    (http://yann.perrin.googlepages.com/twkd.html#easySlicer)

    %/<html><hide linebreaks><a href="javascript:;" class="tiddlyLink" tabindex="-1"
    title="move selection to new tiddler and insert link, embedded tiddler, or slider"
    onclick="var p=Popup.create(this); if (!p) return false; p.className+=' sticky smallform';
    	p.style.whiteSpace='nowrap';
    	var i=createTiddlyElement(p,'input');
    	i.defaultValue='Enter a new tiddler title';
    	i.onfocus=function(){this.select()};
    	var s=createTiddlyElement(p,'select'); s.button=this;
    	s.options[0]=new Option('select type...','');
    	s.options[0].title='select split type';
    	s.options[1]=new Option('link','link');
    	s.options[1].title='replace with [[TiddlerName]]';
    	s.options[2]=new Option('embed','embed');
    	s.options[2].title='replace with \<\<tiddler TiddlerName\>\>';
    	s.options[3]=new Option('slider','slider');
    	s.options[3].title='replace with \<\<slider \u0022\u0022 [[TiddlerName]] [[label]] [[tooltip]]\>\>';
    	s.onchange=function(){
    		if (s.previousSibling.value==s.previousSibling.defaultValue)
    			{ alert('A tiddler title is required'); s.selectedIndex=0; s.previousSibling.focus(); return false; }
    		var tid=s.previousSibling.value;
    		if (store.tiddlerExists(tid) && !confirm(config.messages.overwriteWarning.format([tid])))
    			{ s.previousSibling.focus(); return false; }
    		switch(s.value) {
    			case 'link':
    				var newtxt='[['+tid+']]';
    				break;
    			case 'embed':
    				var newtxt='\<\<tiddler [['+tid+']]\>\>';
    				break;
    			case 'slider':
    				var label=prompt('Enter a slider label',tid);
    				if (!label) { Popup.remove(); return false; }
    				var tip=prompt('Enter a slider tooltip',label);
    				if (!tip) { Popup.remove(); return false; }
    				var newtxt='\<\<slider \u0022\u0022 [['+tid+']] [['+label+']] [['+tip+']]\>\>';
    				break;
    		}
    		var txt=config.quickEdit.getSelection(config.quickEdit.getField(this.button));
    		store.saveTiddler(tid,tid,txt,config.options.txtUserName,new Date(),[],{});
    		story.displayTiddler(story.findContainingTiddler(this.button),tid);
    		config.quickEdit.setSelection(this.button,newtxt);
    		Popup.remove(); return false;
    	};
    	Popup.show();
    	event.cancelBubble=true;if(event.stopPropagation)event.stopPropagation();return false;"
    >split</a></html>

    /%
    |Name|QuickEdit_tiddler|
    |Source|http://www.TiddlyTools.com/#QuickEdit_tiddler|
    |Version|2.2.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.2|
    |Type|script|
    |Requires|QuickEditPlugin|
    |Overrides||
    |Description|definition for toolbar button that inserts content from another tiddler|

    Usage:
    QuickEditToolbar: <<tiddler QuickEdit_tiddler>>
    OR
    EditTemplate: <span class='toolbar' macro='tiddler QuickEdit_tiddler'></span>

    **** INSERT TIDDLER ****
    %/<html><hide linebreaks><a href="javascript:;" class="tiddlyLink"
    title="copy content from another tiddler"
    onclick="var p=Popup.create(this); if (!p) return false; p.className+=' sticky smallform';
    	var s=createTiddlyElement(p,'select'); s.button=this;
    	s.options[0]=new Option('select a tiddler...','');
    	s.onchange=function(){
    		var txt=store.getTiddlerText(this.value);
    		if (!txt) { displayMessage(this.value+' not found'); this.selectedIndex=0; this.focus(); return false; }
    		config.quickEdit.setSelection(this.button,txt);
    		Popup.remove(); return false;
    	};
    	var tids=store.getTiddlers('title');
    	for (var t=0; t<tids.length; t++) {
    		s.options[s.length]=new Option(tids[t].title,tids[t].title);
    		s.options[s.length-1].title=tids[t].getSubtitle();
    	}
    	var s=createTiddlyElement(p,'select');
    	s.options[0]=new Option('match tag...','');
    	s.onchange=function(){
    		var tag=this.value;
    		var tids=tag.length?store.getTaggedTiddlers(tag,'title'):store.getTiddlers('title');
    		var list=this.previousSibling;
    		while (list.length) list.options[0]=null;
    		var prompt='select a '+(tag.length?'tagged ':'')+'tiddler'+(tag.length?(' ['+tids.length+' matches]'):'')+'...';
    		list.options[0]=new Option(prompt,'');
    		for (var t=0; t<tids.length; t++) {
    			list.options[list.length]=new Option(tids[t].title,tids[t].title);
    			list.options[list.length-1].title=tids[t].getSubtitle();
    		}
    	};
    	var tags=store.getTags();
    	for (var t=0; t<tags.length; t++) s.options[s.length]=new Option(tags[t][0],tags[t][0]);
    	Popup.show(p,false);
    	event.cancelBubble=true;if(event.stopPropagation)event.stopPropagation();return false;"
    >tiddler</a></html>

    /***
    |Name|QuoteOfTheDayPlugin|
    |Source|http://www.TiddlyTools.com/#QuoteOfTheDayPlugin|
    |Documentation|http://www.TiddlyTools.com/#QuoteOfTheDayPluginInfo|
    |Version|1.4.1|
    |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|Display a randomly selected "quote of the day" from a list defined in a separate tiddler|

    !!!!!Documentation
    >see [[QuoteOfTheDayPluginInfo]]
    !!!!!Revisions
    <<<
    2008.03.21 [1.4.1] in showNextItem(), corrected handling for random selection so that //initial// index value will randomized correctly instead of always showing first item, even when randomizing.  Thanks to Riccardo Gherardi for finding this.
    | Please see [[QuoteOfTheDayPluginInfo]] for previous revision details |
    2005.10.21 [1.0.0] Initial Release.  Based on a suggestion by M.Russula
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.QuoteOfTheDayPlugin= {major: 1, minor: 4, revision: 1, date: new Date(2008,3,21)};
    config.macros.QOTD = {
    	clickTooltip: "click to view another item",
    	timerTooltip: "auto-timer stopped...  'mouseout' to restart timer",
    	timerClickTooltip: "auto-timer stopped...  click to view another item, or 'mouseout' to restart timer",
    	handler:
    	function(place,macroName,params) {
    		var tid=params.shift(); // source tiddler containing HR-separated quotes
    		var p=params.shift();
    		var click=true; // allow click for next item
    		var inline=false; // wrap in slider for animation effect
    		var random=true; // pick an item at random (default for "quote of the day" usage)
    		var folder=false; // use local filesystem folder list
    		var cookie=""; // default to no cookie
    		var next=0; // default to first item (or random item)
    		while (p) {
    			if (p.toLowerCase()=="noclick") var click=false;
    			if (p.toLowerCase()=="inline") var inline=true;
    			if (p.toLowerCase()=="norandom") var random=false;
    			if (p.toLowerCase().substr(0,7)=="cookie:") var cookie=p.substr(8);
    			if (!isNaN(p)) var delay=p;
    			p=params.shift();
    		}
    		if ((click||delay) && !inline) {
    			var panel = createTiddlyElement(null,"div",null,"sliderPanel");
    			panel.style.display="none";
    			place.appendChild(panel);
    			var here=createTiddlyElement(panel,click?"a":"span",null,"QOTD");
    		}
    		else
    			var here=createTiddlyElement(place,click?"a":"span",null,"QOTD");
    		here.id=(new Date()).convertToYYYYMMDDHHMMSSMMM()+Math.random().toString(); // unique ID
    		// get items from tiddler or file list
    		var list=store.getTiddlerText(tid,"");
    		if (!list||!list.length) { // not a tiddler... maybe an image directory?
    			var list=this.getImageFileList(tid);
    			if (!list.length) { // maybe relative path... fixup and try again
    				var h=document.location.href;
    				var p=getLocalPath(decodeURIComponent(h.substr(0,h.lastIndexOf("/")+1)));
    				var list=this.getImageFileList(p+tid);
    			}
    		}
    		if (!list||!list.length) return false; // no contents... nothing to display!
    		here.setAttribute("list",list);
    		if (delay) here.setAttribute("delay",delay);
    		here.setAttribute("random",random);
    		here.setAttribute("cookie",cookie);
    		if (click) {
    			here.title=this.clickTooltip
    			if (!inline) here.style.display="block";
    			here.setAttribute("href","javascript:;");
    			here.onclick=function(event)
    				{ config.macros.QOTD.showNextItem(this); }
    		}
    		if (config.options["txtQOTD_"+cookie]!=undefined) next=parseInt(config.options["txtQOTD_"+cookie]);
    		here.setAttribute("nextItem",next);
    		config.macros.QOTD.showNextItem(here);
    		if (delay) {
    			here.title=click?this.timerClickTooltip:this.timerTooltip
    			here.onmouseover=function(event)
    				{ clearTimeout(this.ticker); };
    			here.onmouseout=function(event)
    				{ this.ticker=setTimeout("config.macros.QOTD.tick('"+this.id+"')",this.getAttribute("delay")); };
    			here.ticker=setTimeout("config.macros.QOTD.tick('"+here.id+"')",delay);
    		}
    	},
    	tick: function(id) {
    		var here=document.getElementById(id); if (!here) return;
    		config.macros.QOTD.showNextItem(here);
    		here.ticker=setTimeout("config.macros.QOTD.tick('"+id+"')",here.getAttribute("delay"));
    	},
    	showNextItem:
    	function (here) {
    		// hide containing slider panel (if any)
    		var p=here.parentNode;
    		if (p.className=="sliderPanel") p.style.display = "none"
    		// get a new quote
    		var index=here.getAttribute("nextItem");
    		var items=here.getAttribute("list").split("\n----\n");
    		if (index<0||index>=items.length) index=0;
    		if (here.getAttribute("random")=="true") index=Math.floor(Math.random()*items.length);
    		var txt=items[index];
    		// re-render quote display element, and advance index counter
    		removeChildren(here); wikify(txt,here);
    		index++; here.setAttribute("nextItem",index);
    		var cookie=here.getAttribute("cookie");
    		if (cookie.length) {
    			config.options["txtQOTD_"+cookie]=index.toString();
    			saveOptionCookie("txtQOTD_"+cookie);
    		}
    		// redisplay slider panel (if any)
    		if (p.className=="sliderPanel") {
    			if(anim && config.options.chkAnimate)
    				anim.startAnimating(new Slider(p,true,false,"none"));
    			else p.style.display="block";
    		}
    	},
    	getImageFileList: function(cwd) { // returns HR-separated list of image files
    		function isImage(fn) {
    			var ext=fn.substr(fn.length-3,3).toLowerCase();
    			return ext=="jpg"||ext=="gif"||ext=="png";
    		}
    		var files=[];
    		if (config.browser.isIE) {
    			cwd=cwd.replace(/\//g,"\\");
    			// IE uses ActiveX to read filesystem info
    			var fso = new ActiveXObject("Scripting.FileSystemObject");
    			if(!fso.FolderExists(cwd)) return [];
    			var dir=fso.GetFolder(cwd);
    			for(var f=new Enumerator(dir.Files); !f.atEnd(); f.moveNext())
    				if (isImage(f.item().path)) files.push("[img[%0]]".format(["file:///"+f.item().path.replace(/\\/g,"/")]));
    		} else {
    			// FireFox (mozilla) uses "components" to read filesystem info
    			// get security access
    			if(!window.Components) return;
    			try { netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect"); }
    			catch(e) { alert(e.description?e.description:e.toString()); return []; }
    			// open/validate directory
    			var file=Components.classes["@mozilla.org/file/local;1"].createInstance(Components.interfaces.nsILocalFile);
    			try { file.initWithPath(cwd); } catch(e) { return []; }
    			if (!file.exists() || !file.isDirectory()) { return []; }
    			var folder=file.directoryEntries;
    			while (folder.hasMoreElements()) {
    				var f=folder.getNext().QueryInterface(Components.interfaces.nsILocalFile);
    				if (f instanceof Components.interfaces.nsILocalFile)
    					if (isImage(f.path)) files.push("[img[%0]]".format(["file:///"+f.path.replace(/\\/g,"/")]));
    			}
    		}
    		return files.join("\n----\n");
    	}
    }
    //}}}

    /***
    |Name|RearrangeTiddlersPlugin|
    |Source|http://www.TiddlyTools.com/#RearrangeTiddlersPlugin|
    |Version|2.0.0|
    |Author|Eric Shulman|
    |OriginalAuthor|Joe Raii|
    |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.refreshTiddler|
    |Description|drag tiddlers by title to re-order story column display|

    adapted from: http://www.cs.utexas.edu/~joeraii/dragn/#Draggable
    changes by ELS:
    * hijack refreshTiddler() instead of overridding createTiddler()
    * find title element by className instead of elementID
    * set cursor style via code instead of stylesheet
    * set tooltip help text
    * set tiddler "position:relative" when starting drag event, restore saved value when drag ends
    * update 2006.08.07: use getElementsByTagName("*") to find title element, even when it is 'buried' deep in tiddler DOM elements (due to custom template usage)
    * update 2007.03.01: use apply() to invoke hijacked core function
    * update 2008.01.13: only hijack core function once.  (allows for dynamic loading of plugin via bookmarklet)
    * update 2008.10.19: added onclick popup menu with 'move to top' and 'move to bottom' commands

    ***/
    //{{{

    if (Story.prototype.rearrangeTiddlersHijack_refreshTiddler===undefined) {
    Story.prototype.rearrangeTiddlersHijack_refreshTiddler = Story.prototype.refreshTiddler;
    Story.prototype.refreshTiddler = function(title,template)
    {
    	this.rearrangeTiddlersHijack_refreshTiddler.apply(this,arguments);
    	var theTiddler = document.getElementById(this.idPrefix + title); if (!theTiddler) return;
    	var theHandle;
    	var children=theTiddler.getElementsByTagName("*");
    	for (var i=0; i<children.length; i++) if (hasClass(children[i],"title")) { theHandle=children[i]; break; }
    	if (!theHandle) return theTiddler;

    	Drag.init(theHandle, theTiddler, 0, 0, null, null);
    	theHandle.style.cursor="move";
    	theHandle.title="drag title to re-arrange tiddlers, click for more options..."
    	theTiddler.onDrag = function(x,y,myElem) {
    		if (this.style.position!="relative")
    			{ this.savedstyle=this.style.position; this.style.position="relative"; }
    		y = myElem.offsetTop;
    		var next = myElem.nextSibling;
    		var prev = myElem.previousSibling;
    		if (next && y + myElem.offsetHeight > next.offsetTop + next.offsetHeight/2) {
    			myElem.parentNode.removeChild(myElem);
    			next.parentNode.insertBefore(myElem, next.nextSibling);//elems[pos+1]);
    			myElem.style["top"] = -next.offsetHeight/2+"px";
    		}
    		if (prev && y < prev.offsetTop + prev.offsetHeight/2) {
    			myElem.parentNode.removeChild(myElem);
    			prev.parentNode.insertBefore(myElem, prev);
    			myElem.style["top"] = prev.offsetHeight/2+"px";
    		}
    	};
    	theTiddler.onDragEnd = function(x,y,myElem) {
    		myElem.style["top"] = "0px";
    		if (this.savedstyle!=undefined)
    			this.style.position=this.savedstyle;
    	};
    	theHandle.onclick=function(ev) {
    		ev=ev||window.event;
    		var p=Popup.create(this); if (!p) return;
    		var b=createTiddlyButton(createTiddlyElement(p,"li"),
    			"\u25B2 move to top of column ","move this tiddler to the top of the story column",
    			function() {
    				var t=story.getTiddler(this.getAttribute("tid"));
    				t.parentNode.insertBefore(t,t.parentNode.firstChild); // move to top of column
    				window.scrollTo(0,ensureVisible(t));
    				return false;
    			});
    		b.setAttribute("tid",title);
    		var b=createTiddlyButton(createTiddlyElement(p,"li"),
    			"\u25BC move to bottom of column ","move this tiddler to the bottom of the story column",
    			function() {
    				var t=story.getTiddler(this.getAttribute("tid"));
    				t.parentNode.insertBefore(t,null); // move to bottom of column
    				window.scrollTo(0,ensureVisible(t));
    				return false;
    			});
    		b.setAttribute("tid",title);
    		Popup.show(p,false);
    		ev.cancelBubble=true; if (ev.stopPropagation) ev.stopPropagation(); return(false);
    	};
    	return theTiddler;
    }
    }

    /**************************************************
     * dom-drag.js
     * 09.25.2001
     * www.youngpup.net
     **************************************************
     * 10.28.2001 - fixed minor bug where events
     * sometimes fired off the handle, not the root.
     **************************************************/

    var Drag = {
    	obj:null,

    	init:
    	function(o, oRoot, minX, maxX, minY, maxY) {
    		o.onmousedown = Drag.start;
    		o.root = oRoot && oRoot != null ? oRoot : o ;
    		if (isNaN(parseInt(o.root.style.left))) o.root.style.left="0px";
    		if (isNaN(parseInt(o.root.style.top))) o.root.style.top="0px";
    		o.minX = typeof minX != 'undefined' ? minX : null;
    		o.minY = typeof minY != 'undefined' ? minY : null;
    		o.maxX = typeof maxX != 'undefined' ? maxX : null;
    		o.maxY = typeof maxY != 'undefined' ? maxY : null;
    		o.root.onDragStart = new Function();
    		o.root.onDragEnd = new Function();
    		o.root.onDrag = new Function();
    	},

    	start:
    	function(e) {
    		var o = Drag.obj = this;
    		e = Drag.fixE(e);
    		var y = parseInt(o.root.style.top);
    		var x = parseInt(o.root.style.left);
    		o.root.onDragStart(x, y, Drag.obj.root);
    		o.lastMouseX = e.clientX;
    		o.lastMouseY = e.clientY;
    		if (o.minX != null) o.minMouseX = e.clientX - x + o.minX;
    		if (o.maxX != null) o.maxMouseX = o.minMouseX + o.maxX - o.minX;
    		if (o.minY != null) o.minMouseY = e.clientY - y + o.minY;
    		if (o.maxY != null) o.maxMouseY = o.minMouseY + o.maxY - o.minY;
    		document.onmousemove = Drag.drag;
    		document.onmouseup = Drag.end;
    		Drag.obj.root.style["z-index"] = "10";
    		return false;
    	},

    	drag:
    	function(e) {
    		e = Drag.fixE(e);
    		var o = Drag.obj;
    		var ey = e.clientY;
    		var ex = e.clientX;
    		var y = parseInt(o.root.style.top);
    		var x = parseInt(o.root.style.left);
    		var nx, ny;
    		if (o.minX != null) ex = Math.max(ex, o.minMouseX);
    		if (o.maxX != null) ex = Math.min(ex, o.maxMouseX);
    		if (o.minY != null) ey = Math.max(ey, o.minMouseY);
    		if (o.maxY != null) ey = Math.min(ey, o.maxMouseY);
    		nx = x + (ex - o.lastMouseX);
    		ny = y + (ey - o.lastMouseY);
    		Drag.obj.root.style["left"] = nx + "px";
    		Drag.obj.root.style["top"] = ny + "px";
    		Drag.obj.lastMouseX = ex;
    		Drag.obj.lastMouseY = ey;
    		Drag.obj.root.onDrag(nx, ny, Drag.obj.root);
    		return false;
    	},

    	end:
    	function() {
    		document.onmousemove = null;
    		document.onmouseup = null;
    		Drag.obj.root.style["z-index"] = "0";
    		Drag.obj.root.onDragEnd(parseInt(Drag.obj.root.style["left"]), parseInt(Drag.obj.root.style["top"]), Drag.obj.root);
    		Drag.obj = null;
    	},

    	fixE:
    	function(e) {
    		if (typeof e == 'undefined') e = window.event;
    		if (typeof e.layerX == 'undefined') e.layerX = e.offsetX;
    		if (typeof e.layerY == 'undefined') e.layerY = e.offsetY;
    		return e;
    	}
    };
    //}}}

    <<tiddler HideTiddlerBackground>><<tiddler HideTiddlerTags>>{{transparent smallform{<<recentChanges 30>>}}}

    /***
    |Name|RecentChangesPlugin|
    |Source|http://www.TiddlyTools.com/#RecentChangesPlugin|
    |Version|2.2.0|
    |Author|Eric Shulman|
    |License|http://www.TiddlyTools.com/#LegalStatements|
    |~CoreVersion|2.1|
    |Type|plugin|
    |Requires||
    |Overrides||
    |Description|display droplist of recently changed tiddlers with goto, edit, and preview buttons|
    !!!!!Usage
    <<<
    The {{{<<recentChanges>>}}} macro displays a droplist of all tiddlers that have been changed within the last N days (default=10 days).
    {{{
    <<recentChanges>>
    <<recentChanges #ofdays summary noEdit previewheight previewclass>>
    }}}
    where:
    * #ofdays specifies the time limit for listing changed tiddlers.  Use 0 (zero) to list all tiddlers in the document.
    * ''summary'' is an optional keyword that outputs only the summary text (without the droplist or buttons)
    * ''noEdit'' is an optional keyword that hides the 'edit' button
    * previewheight is a CSS height measurement and sets the FIXED height of the tiddler preview area (default is 15em)
    * previewclass is any CSS classname, and can be used to apply custom styles to the preview area (default is to use the standard 'viewer' class)
    <<<
    !!!!!Examples
    <<<
    {{smallform{
    {{{<<recentChanges>>}}}
    <<recentChanges>>
    {{{<<recentChanges 30 summary>>}}}
    <<recentChanges 30 summary>>

    {{{<<recentChanges 30 noedit 10em groupbox>>}}}
    <<recentChanges 30 noedit 10em groupbox>>
    }}}
    <<<
    !!!!!Revisions
    <<<
    2009.07.02 [2.2.0] added optional 'noedit' keyword to hide 'edit' button
    2008.07.01 [2.1.0] added optional 'summary' keyword for simple text output
    2008.05.01 [2.0.1] fixup for titles with double-quotes
    2007.07.26 [2.0.0] re-written as plugin
    2006.10.02 [1.0.0] initial release (as inline script ShowRecentChanges)
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.RecentChangesPlugin= {major: 2, minor: 2, revision: 0, date: new Date(2009,7,2)};

    config.shadowTiddlers.RecentChanges='<recentChanges>>';

    config.macros.recentChanges = {
    	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    		var days=10; if (!isNaN(params[0])) days=parseInt(params[0]); // time limit in days (use 0 for all tiddlers)
    		var summary=params[1]&&params[1].toLowerCase()=='summary'; if (summary) params.shift();
    		var noedit=params[1]&&params[1].toLowerCase()=='noedit'; if (noedit) params.shift();
    		var height='15em'; if (params[1]) height=params[1]; // preview area fixed height
    		var previewclass='viewer'; if (params[2]) previewclass=params[2]; // preview area CSS class
    		var tiddlers=store.getTiddlers('modified','excludeLists').reverse();
    		var count=tiddlers.length;
    		if (days) {
    			var timelimit=(new Date()).getTime()-86400000*days;
    			for (var count=0; count<tiddlers.length && tiddlers[count].modified>timelimit; count++);
    		}
    		var s=count+' tiddlers have changed since ';
    		s+=new Date(timelimit).formatString('DDD, MMM DDth YYYY 0hh:0mm');
    		s+=' ('+days+' days ago)';
    		if (summary)
    			{ wikify(s,place); return; }
    		var opts='<option value="">'+s+'</option>';
    		for (var i=0; i<count; i++) { var t=tiddlers[i];
    			opts+='<option value="'+t.title.replace(/"/g,"&#x22;")+'">';
    			opts+=t.modified.formatString('YYYY.0MM.0DD 0hh:0mm')+' - '+t.title;
    			opts+='</option>';
    		}
    		var h=store.getTiddlerText('RecentChangesPlugin##html')
    		h=h.replace(/%options%/,opts);
    		h=h.replace(/%listwidth%/,noedit?79.5:69.5);
    		h=h.replace(/%noedit%/,noedit?'none':'inline');
    		createTiddlyElement(place,'div').innerHTML=h;
    		var preview=createTiddlyElement(place,'div',null,previewclass);
    		preview.style.display='none';
    		preview.style.whiteSpace='normal';
    		preview.style.overflow='auto';
    		preview.style.height=height;
    	}
    }
    //}}}
    /***
    //{{{
    !html
    <form><select size=1 name="list" style="width:%listwidth%%"
    	onchange="this.form.goto.disabled=this.form.edit.disabled=this.form.preview.disabled=!this.value.length;
    		var target=this.parentNode.parentNode.nextSibling; removeChildren(target);
    		if (!this.value.length)
    			{ target.style.display='none'; this.form.preview.value='preview'; }
    		else if (target.style.display=='block') {
    			wikify('<'+'<tiddler [['+this.value+']]>'+'>',target);
    			target.style.display='block';
    			this.form.preview.value='done';
    		}
    ">%options%</select><!--
    --><input type="button" name="goto" value="goto" disabled title="view selected tiddler" style="width:10%"
    	onclick="var target=this.parentNode.parentNode.nextSibling; removeChildren(target);
    		target.style.display='none'; this.form.preview.value='preview';
    		story.displayTiddler(story.findContainingTiddler(this),this.form.list.value);
    "><input type="button" name="edit" value="edit" disabled title="edit selected tiddler" style="width:10%;display:%noedit%"
    	onclick="var target=this.parentNode.parentNode.nextSibling; removeChildren(target);
    		target.style.display='none'; this.form.preview.value='preview';
    		story.displayTiddler(story.findContainingTiddler(this),this.form.list.value,DEFAULT_EDIT_TEMPLATE);
    "><input type="button" name="preview" value="preview" disabled title="show/hide tiddler preview" style="width:10%"
    	onclick="var target=this.parentNode.parentNode.nextSibling;
    		if (this.value=='preview') {
    			removeChildren(target);
    			wikify('<'+'<tiddler [['+this.form.list.value+']]>'+'>',target);
    			target.style.display=this.form.list.value.length?'block':'none'; this.value='done';
    		} else {
    			removeChildren(target);
    			target.style.display='none'; this.value='preview';
    		}
    "></form>
    !end
    //}}}
    ***/

    <script label="refresh" title="re-render this tiddler">
    		var here=story.findContainingTiddler(place); if (!here) return false;
    		story.refreshTiddler(here.getAttribute("tiddler"),null,true);
    </script><script>place.lastChild.className='button';</script>

    /%
    |Name|ReplaceTiddlerTitle|
    |Source|http://www.TiddlyTools.com/#ReplaceTiddlerTitle|
    |Version|1.0.1|
    |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|script|
    |Requires|InlineJavascriptPlugin|
    |Overrides||
    |Description|replace tiddler's title text with other content - may include wiki syntax|

    Usage:
    	<<tiddler ReplaceTiddlerTitle with: "new title text">>

    %/<script>
    	// get the tiddler element
    	var here=story.findContainingTiddler(place);
    	if (!here || here.getAttribute("tiddler")=="ReplaceTiddlerTitle") return; // don't change the title on the script itself!
    	var nodes=here.getElementsByTagName("*");
    	for (var i=0; i<nodes.length; i++)
    		if (hasClass(nodes[i],"title")) { removeChildren(nodes[i]); wikify("$1",nodes[i]); break; }
    </script>

    /%
    Description: This is a sample journal entry
    %/Tuesday, March 24th, 2009 5:59:16 pm

    This is a tiddlyblog journal entry.  The day and date were automatically inserted when the journal entry was first created.  Then I edited the //hidden// "Description: " text (for use in the JournalViewer's droplist) and added some content here for you to read.

    [[SampleJournal]]
    [[SampleBookmark]]
    [[SampleFAQ]]

    @@ <<slideShow cycle tag:slide1 sort:modified label:点击播放大赛作品幻灯片 tooltip:以幻灯片的方式展示所有参赛作品>> @@

    /***
    |Name|SaveAsPlugin|
    |Source|http://www.TiddlyTools.com/#SaveAsPlugin|
    |Documentation|http://www.TiddlyTools.com/#SaveAsPluginInfo|
    |Version|2.6.1|
    |Author|Eric Shulman|
    |License|http://www.TiddlyTools.com/#LegalStatements|
    |~CoreVersion|2.1|
    |Type|plugin|
    |Requires||
    |Overrides||
    |Description|Save current document to a different path/filename|
    Adds 'save as' command to 'backstage' menu and {{{<<saveAs>>}}} macro (to embed command link wherever you like).
    >//Note: This plugin replaces functionality previously provided by [[NewDocumentPlugin]], except for the HTML+CSS 'snapshot' feature, which has been moved to a separate [[SnapshotPlugin]].//
    !!!!!Documentation
    <<<
    see [[SaveAsPluginInfo]]
    <<<
    !!!!!Revisions
    <<<
    2009.08.04 [2.6.1] fixed handling when limit is omitted
    | Please see [[SaveAsPluginInfo]] for additional revision details |
    2006.02.03 [1.0.0] Created
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.SaveAsPlugin= {major: 2, minor: 6, revision: 1, date: new Date(2009,8,4)};

    config.macros.saveAs = {
    	label: 'save as...',
    	labelparam: 'label:',
    	prompt: 'Save current document to a different path/file',
    	promptparam: 'prompt:',
    	filePrompt: 'Please select or enter a target path/filename',
    	targetparam: 'target:',
    	defaultFilename: 'new.html',
    	filenameparam: 'filename:',
    	currfilekeyword: 'here',
    	typeparam: 'type:',
    	type_TW: 'tw', type_PS: 'ps', type_TX: 'tx', type_CS: 'cs', type_NF: 'nf', // file type tokens
    	type_map: { // map filetype param alternatives/abbreviations to token values
    		tiddlywiki:'tw', tw:'tw', wiki: 'tw',
    		purestore: 'ps', ps:'ps', store:'ps',
    		plaintext: 'tx', tx:'tx', text: 'tx',
    		comma:     'cs', cs:'cs', csv:  'cs',
    		newsfeed:  'nf', nf:'nf', xml:  'nf', rss:'nf'
    	},
    	limitparam: 'limit:',
    	replaceparam: 'replace',
    	mergeparam: 'merge',
    	quietparam: 'quiet',
    	openparam: 'open',
    	askParam: 'ask',
    	askMsg: "Enter a tag filter (use * for all tiddlers, 'none' for blank document)",
    	emptyParam: 'none',
    	confirmmsg: "Found %0 tiddlers matching\n\n'%1'\n\nPress OK to proceed",
    	mergeprompt: '%0\nalready contains tiddler definitions.\n'
    		+'\nPress OK to add new/revised tiddlers to current file contents.'
    		+'\nPress Cancel to completely replace file contents',
    	mergestatus: 'Merged %0 new/revised tiddlers and %1 existing tiddlers',
    	okmsg: '%0 tiddlers written to %1',
    	failmsg: 'An error occurred while creating %1',
    	filter: '',
    	handler: function(place,macroName,params) {
    		if ((params[0]||'').startsWith(this.labelparam))
    			var label=params.shift().substr(this.labelparam.length);
    		if ((params[0]||'').startsWith(this.promptparam))
    			var prompt=params.shift().substr(this.promptparam.length);
    		if ((params[0]||'').startsWith(this.targetparam))
    			var target=params.shift().substr(this.targetparam.length);
    		if ((params[0]||'').startsWith(this.filenameparam))
    			var filename=params.shift().substr(this.filenameparam.length);
    		if ((params[0]||'').startsWith(this.typeparam))
    			var filetype=this.type_map[params.shift().substr(this.typeparam.length).toLowerCase()];
    		if ((params[0]||'').startsWith(this.limitparam))
    			var limit=params.shift().substr(this.limitparam.length);
    		var q=((params[0]||'')==this.quietparam);   if (q) params.shift();
    		var o=((params[0]||'')==this.replaceparam); if (o) params.shift();
    		var m=((params[0]||'')==this.mergeparam);   if (m) params.shift();
    		var a=((params[0]||'')==this.openparam);    if (a) params.shift();
    		var btn=createTiddlyButton(place,label||this.label,prompt||this.prompt,
    			function(){ config.macros.saveAs.go( this.getAttribute('target'),
    				this.getAttribute('filename'), this.getAttribute('filetype'),
    				this.getAttribute('filter'), this.getAttribute('limit'),
    				this.getAttribute('quiet')=='true', this.getAttribute('overwrite')=='true',
    				this.getAttribute('merge')=='true', this.getAttribute('autoopen')=='true');
    				return false; }
    		);
    		if (target) btn.setAttribute('target',target);
    		if (filename) btn.setAttribute('filename',filename);
    		btn.setAttribute('filetype',filetype||this.type_TW);
    		btn.setAttribute('filter',params.join(' '));
    		btn.setAttribute('limit',limit||0);
    		btn.setAttribute('quiet',q?'true':'false');
    		btn.setAttribute('overwrite',o?'true':'false');
    		btn.setAttribute('merge',m?'true':'false');
    		btn.setAttribute('autoopen',a?'true':'false');
    	},
    	go: function(target,filename,filetype,filter,limit,quiet,overwrite,merge,autoopen) {
    		var cm=config.messages; // abbreviation
    		var cms=config.macros.saveAs; // abbreviation
    		if (window.location.protocol!='file:') // make sure we are local
    			{ displayMessage(cm.notFileUrlError); return; }

    		// get tidders, confirm filtered results
    		var tids=cms.selectTiddlers(filter);
    		if (tids===false) return; // cancelled by user
    		if (cms.filter!=cms.emptyParam && cms.filter.length && !quiet)
    			if (!confirm(cms.confirmmsg.format([tids.length,cms.filter]))) return;

    		// get target path/filename
    		if (!filetype) filetype=this.type_TW;
    		target=target||cms.getTarget(filename,filetype==this.type_TX?'txt':filetype==this.type_CS?'csv':'html');
    		if (!target) return; // cancelled by user

    		var link='file:///'+target.replace(/\\/g,'/');
    		var samefile=link==decodeURIComponent(window.location.href);
    		var p=getLocalPath(document.location.href);
    		if (samefile) {
    			if (config.options.chkSaveBackups) { var t=loadOriginal(p);if(t)saveBackup(p,t); }
    			if (config.options.chkGenerateAnRssFeed && saveRss instanceof Function) saveRss(p);
    		}
    		var notes='';
    		var total={val:0};
    		var out=this.assembleFile(target,filetype,tids,limit,notes,quiet,overwrite,merge,total);
    		var ok=saveFile(target,out);
    		if (ok && autoopen) {
    			if (!samefile) window.open(link).focus();
    			else { store.setDirty(false); window.location.reload(); }
    		}
    		if (!quiet || !(ok && autoopen))
    			displayMessage((ok?this.okmsg:this.failmsg).format([total.val,target]),link);
    	},
    	selectTiddlers: function(filter) {
    		var cms=config.macros.saveAs; // abbreviation
    		var tids=[]; cms.filter=filter||'';
    		if (filter==cms.emptyParam) tids=[];
    		if (filter==config.macros.saveAs.askParam) {
    			filter=prompt(config.macros.saveAs.askMsg,'');
    			if (!filter) return false;  // cancelled by user
    			cms.filter=filter=='*'?'':filter;
    		}
    		if (!filter||!filter.length||filter=='*') tids=store.getTiddlers('title');
    		else tids=store.filterTiddlers('[tag['+filter+']]');
    		return tids;
    	},
    	getTarget: function(defName,defExt) {
    		var cms=config.macros.saveAs; // abbreviation
    		// 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
    		if (!defName||!defName.length) { // use current filename as default
    			var p=getLocalPath(window.location.href);
    			var s=p.lastIndexOf('/'); if (s==-1) s=p.lastIndexOf('\\');
    			if (s!=-1) defName=p.substr(s+1);
    		}
    		var defFilename=(defName||cms.defaultFilename).replace(/.html$/,'.'+defExt);
    		var target=cms.askForFilename(cms.filePrompt,newPath,defFilename,defExt);
    		if (!target) return; // cancelled by user
    		// if specified file does not include a path, assemble fully qualified path and filename
    		var slashpos=target.lastIndexOf('/'); if (slashpos==-1) slashpos=target.lastIndexOf('\\');
    		if (slashpos==-1) target=target+(defName||cms.defaultFilename).replace(/.html$/,'.'+defExt);
    		return target;
    	},
    	askForFilename: function(msg,path,file,defExt) {
    		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=defExt||'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 { // XP/Vista only
    				var s = new ActiveXObject('UserAccounts.CommonDialog');
    				s.Filter='All files|*.*|Text files|*.txt|HTML files|*.htm;*.html|';
    				s.FilterIndex=(defExt=='txt')?2:3; // default to HTML files;
    				s.InitialDir=path;
    				s.FileName=file;
    				if (s.showOpen()) var result=s.FileName;
    			}
    			catch(e) { var result=prompt(msg,path+file); } // fallback for non-XP IE
    		}
    		return result;
    	},
    	plainTextHeader:
    		 'Source:\n\t%0\n'
    		+'Title:\n\t%1\n'
    		+'Subtitle:\n\t%2\n'
    		+'Created:\n\t%3 by %4\n'
    		+'Application:\n\tTiddlyWiki %5 / %6 %7\n\n',
    	plainTextTiddler:
    		'- - - - - - - - - - - - - - -\n'
    		+'|     title: %0\n'
    		+'|   created: %1\n'
    		+'|  modified: %2\n'
    		+'| edited by: %3\n'
    		+'|      tags: %4\n'
    		+'- - - - - - - - - - - - - - -\n'
    		+'%5\n',
    	plainTextFooter:
    		'',
    	newsFeedHeader:
    		 '<'+'?xml version="1.0"?'+'>\n'
    		+'<rss version="2.0">\n'
    		+'<channel>\n'
    		+'<title>%1</title>\n'
    		+'<link>%0</link>\n'
    		+'<description>%2</description>\n'
    		+'<language>en-us</language>\n'
    		+'<copyright>Copyright '+(new Date().getFullYear())+' %4</copyright>\n'
    		+'<pubDate>%3</pubDate>\n'
    		+'<lastBuildDate>%3</lastBuildDate>\n'
    		+'<docs>http://blogs.law.harvard.edu/tech/rss</docs>\n'
    		+'<generator>TiddlyWiki %5 / %6 %7</generator>\n',
    	newsFeedTiddler:
    		'\n%0\n',
    	newsFeedFooter:
    		'</channel></rss>',
    	pureStoreHeader:
    		 '<html><body>'
    		+'<style type="text/css">'
    		+'	#storeArea {display:block;margin:1em;}'
    		+'	#storeArea div {padding:0.5em;margin:1em;border:2px solid black;height:10em;overflow:auto;}'
    		+'	#pureStoreHeading {width:100%;text-align:left;background-color:#eeeeee;padding:1em;}'
    		+'</style>'
    		+'<div id="pureStoreHeading">'
    		+'	TiddlyWiki "PureStore" export file<br>'
    		+'	Source'+': <b>%0</b><br>'
    		+'	Title: <b>%1</b><br>'
    		+'	Subtitle: <b>%2</b><br>'
    		+'	Created: <b>%3</b> by <b>%4</b><br>'
    		+'	TiddlyWiki %5 / %6 %7<br>'
    		+'	Notes:<hr><pre>%8</pre>'
    		+'</div>'
    		+'<div id="storeArea">',
    	pureStoreTiddler:
    		'%0\n%1',
    	pureStoreFooter:
    		'</div><!--POST-BODY-START-->\n<!--POST-BODY-END--></body></html>',
    	assembleFile: function(target,filetype,tids,limit,notes,quiet,overwrite,merge,total) {
    		var revised='';
    		var now = new Date().toLocaleString();
    		var src=convertUnicodeToUTF8(document.location.href);
    		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 v=version.extensions.SaveAsPlugin; var pver = v.major+'.'+v.minor+'.'+v.revision;
    		var headerargs=[src,title,subtitle,now,user,twver,'SaveAsPlugin',pver,notes];
    		switch (filetype) {
    			case this.type_TX: // plain text
    				var header=this.plainTextHeader.format(headerargs);
    				var footer=this.plainTextFooter;
    				break;
    			case this.type_CS: // comma-separated
    				var fields={};
    				for (var i=0; i<tids.length; i++) for (var f in tids[i].fields) fields[f]=f;
    				var names=['title','created','modified','modifier','tags','text'];
    				for (var f in fields) names.push(f);
    				var header=names.join(',')+'\n';
    				var footer='';
    				break;
    			case this.type_NF: // news feed (XML)
    				headerargs[0]=store.getTiddlerText('SiteUrl','');
    				var header=this.newsFeedHeader.format(headerargs);
    				var footer=this.newsFeedFooter;
    				tids=store.sortTiddlers(tids,'-modified');
    				break;
    			case this.type_PS: // PureStore (no code)
    				var header=this.pureStoreHeader.format(headerargs);
    				var footer=this.pureStoreFooter;
    				break;
    			case this.type_TW: // full TiddlyWiki
    			default:
    				var currPath=getLocalPath(window.location.href);
    				var original=loadFile(currPath);
    				if (!original) { alert(config.messages.cantSaveError); return; }
    				var posDiv = locateStoreArea(original);
    				if (!posDiv) { alert(config.messages.invalidFileError.format([currPath])); return; }
    				var header = original.substr(0,posDiv[0]+startSaveArea.length)+'\n';
    				var footer = '\n'+original.substr(posDiv[1]);
    				break;
    		}
    		if (parseInt(limit)!=0) tids=tids.slice(0,limit);
    		var out=this.getData(target,filetype,tids,quiet,overwrite,merge,fields);
    		var revised = header+convertUnicodeToUTF8(out.join('\n'))+footer;
    		// if full TW, insert page title and language attr, and reset MARKUP blocks as needed...
    		if (filetype==this.type_TW) {
    			var newSiteTitle=convertUnicodeToUTF8(getPageTitle()).htmlEncode();
    			revised=revised.replaceChunk('<title'+'>','</title'+'>',' ' + newSiteTitle + ' ');
    			revised=updateLanguageAttribute(revised);
    			var titles=[]; for (var i=0; i<tids.length; i++) titles.push(tids[i].title);
    			revised=updateMarkupBlock(revised,'PRE-HEAD',
    				titles.contains('MarkupPreHead')? 'MarkupPreHead' :null);
    			revised=updateMarkupBlock(revised,'POST-HEAD',
    				titles.contains('MarkupPostHead')?'MarkupPostHead':null);
    			revised=updateMarkupBlock(revised,'PRE-BODY',
    				titles.contains('MarkupPreBody')? 'MarkupPreBody' :null);
    			revised=updateMarkupBlock(revised,'POST-SCRIPT',
    				titles.contains('MarkupPostBody')?'MarkupPostBody':null);
    		}
    		total.val=out.length;
    		return revised;
    	},
    	getData: function(target,filetype,tids,quiet,overwrite,merge,fields) {
    		// output selected tiddlers and gather list of titles (for use with merge)
    		var out=[]; var titles=[];
    		var url=store.getTiddlerText('SiteUrl','');
    		for (var i=0; i<tids.length; i++) {
    			out.push(this.formatItem(store,filetype,tids[i],url,fields));
    			titles.push(tids[i].title);
    		}
    		// if TW or PureStore format, ask to merge with existing tiddlers (if any)
    		if (filetype==this.type_TW || filetype==this.type_PS) {
    			if (overwrite) return out; // skip merge... forced overwrite
    			var txt=loadFile(target);
    			if (txt && txt.length) {
    				var remoteStore=new TiddlyWiki();
    				if (version.major+version.minor*.1+version.revision*.01<2.52) txt=convertUTF8ToUnicode(txt);
    				if (remoteStore.importTiddlyWiki(txt) && (merge||confirm(this.mergeprompt.format([target])))) {
    					var existing=remoteStore.getTiddlers('title');
    					for (var i=0; i<existing.length; i++)
    						if (!titles.contains(existing[i].title))
    							out.push(this.formatItem(remoteStore,filetype,existing[i],url));
    					if (!quiet) displayMessage(this.mergestatus.format([tids.length,out.length-tids.length]));
    				}
    			}
    		}
    		return out;
    	},
    	formatItem: function(s,f,t,u,fields) {
    		if (f==this.type_TW)
    			var r=s.getSaver().externalizeTiddler(s,t);
    		if (f==this.type_PS)
    			var r=this.pureStoreTiddler.format([t.title,s.getSaver().externalizeTiddler(s,t)]);
    		if (f==this.type_NF)
    			var r=this.newsFeedTiddler.format([t.saveToRss(u)]);
    		if (f==this.type_TX)
    			var r=this.plainTextTiddler.format([t.title, t.created.toLocaleString(), t.modified.toLocaleString(),
    				t.modifier, String.encodeTiddlyLinkList(t.tags), t.text]);
    		if (f==this.type_CS) {
    			function toCSV(t) { return '"'+t.replace(/"/g,'""')+'"'; } // always encode CSV
    			var out=[ toCSV(t.title), toCSV(t.created.toLocaleString()), toCSV(t.modified.toLocaleString()),
    				toCSV(t.modifier), toCSV(String.encodeTiddlyLinkList(t.tags)), toCSV(t.text) ];
    			for (var f in fields) out.push(toCSV(t.fields[f]||''));
    			var r=out.join(',');
    		}
    		return r||'';
    	}
    };
    //}}}
    //{{{
    // automatically add saveAs to backstage
    config.tasks.saveAs = {
    	text: 'saveAs',
    	tooltip: config.macros.saveAs.prompt,
    	action: function(){ clearMessage(); config.macros.saveAs.go(); }
    }
    config.backstageTasks.splice(config.backstageTasks.indexOf('save')+1,0,'saveAs');
    //}}}

    /%
    |Name|ScrollBox|
    |Source|http://www.TiddlyTools.com/#ScrollBox|
    |Version|1.0.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|transcluded wiki syntax|
    |Requires||
    |Overrides||
    |Description|display the contents of a tiddler in a fixed-height scrolling area|
    %//%

    Usage: <<tiddler ScrollBox with: TiddlerName height>>

    %/@@display:block;height:$2;overflow:auto;<<tiddler $1>>@@@@display:block;text-align:right;^^scroll for more...^^@@

    /***
    |Name|SearchOptionsPlugin|
    |Source|http://www.TiddlyTools.com/#SearchOptionsPlugin|
    |Documentation|http://www.TiddlyTools.com/#SearchOptionsPluginInfo|
    |Version|3.0.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|Story.prototype.search, TiddlyWiki.prototype.search, config.macros.search.onKeyPress|
    |Options|##Configuration|
    |Description|extend core search function with additional user-configurable options|
    Adds extra options to core search function including selecting which data items to search, enabling/disabling incremental key-by-key searches, and generating a ''list of matching tiddlers'' instead of immediately displaying all matches.  This plugin also adds syntax for rendering 'search links' within tiddler content to embed one-click searches using pre-defined 'hard-coded' search terms.
    !!!!!Documentation
    >see [[SearchOptionsPluginInfo]]
    !!!!!Configuration
    <<<
    Search in:
    <<option chkSearchTitles>> titles <<option chkSearchText>> text <<option chkSearchTags>> tags <<option chkSearchFields>> fields <<option chkSearchShadows>> shadows
    <<option chkSearchHighlight>> Highlight matching text in displayed tiddlers
    <<option chkSearchList>> Show list of matches
    <<option chkSearchListTiddler>> Write list to [[SearchResults]] tiddler
    <<option chkSearchTitlesFirst>> Show title matches first
    <<option chkSearchByDate>> Sort matching tiddlers by modification date (most recent first)
    <<option chkIncrementalSearch>> Incremental key-by-key search: {{twochar{<<option txtIncrementalSearchMin>>}}} or more characters,  {{threechar{<<option txtIncrementalSearchDelay>>}}} msec delay
    <<option chkSearchOpenTiddlers>> Search only in tiddlers that are currently displayed
    <<option chkSearchExcludeTags>> Exclude tiddlers tagged with: <<option txtSearchExcludeTags>>
    <<<
    !!!!!Revisions
    <<<
    2009.01.16 [3.0.5] added chkSearchOpenTiddlers option to limit searches to displayed tiddlers only
    |please see [[SearchOptionsPluginInfo]] for additional revision details|
    2005.10.18 [1.0.0] Initial Release
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.SearchOptionsPlugin= {major: 3, minor: 0, revision: 5, date: new Date(2009,1,16)};

    var co=config.options; // abbrev
    if (co.chkSearchTitles===undefined) co.chkSearchTitles=true;
    if (co.chkSearchText===undefined) co.chkSearchText=true;
    if (co.chkSearchTags===undefined) co.chkSearchTags=true;
    if (co.chkSearchFields===undefined) co.chkSearchFields=true;
    if (co.chkSearchTitlesFirst===undefined) co.chkSearchTitlesFirst=true;
    if (co.chkSearchList===undefined) co.chkSearchList=true;
    if (co.chkSearchHighlight===undefined) co.chkSearchHighlight=true;
    if (co.chkSearchListTiddler===undefined) co.chkSearchListTiddler=false;
    if (co.chkSearchByDate===undefined) co.chkSearchByDate=false;
    if (co.chkIncrementalSearch===undefined) co.chkIncrementalSearch=true;
    if (co.chkSearchShadows===undefined) co.chkSearchShadows=true;
    if (co.txtIncrementalSearchDelay===undefined) co.txtIncrementalSearchDelay=500;
    if (co.txtIncrementalSearchMin===undefined) co.txtIncrementalSearchMin=3;
    if (co.chkSearchOpenTiddlers===undefined) co.chkSearchOpenTiddlers=false;
    if (co.chkSearchExcludeTags===undefined) co.chkSearchExcludeTags=true;
    if (co.txtSearchExcludeTags===undefined) co.txtSearchExcludeTags="excludeSearch";
    if (config.macros.search.reportTitle==undefined)
    	config.macros.search.reportTitle="SearchResults"; // note: not a cookie!
    config.macros.search.label+="\xa0"; // a little bit of space just because it looks better
    //}}}
    // // searchLink: {{{[search[text to find]] OR [search[text to display|text to find]]}}}
    //{{{
    config.formatters.push( {
    	name: "searchLink",
    	match: "\\[search\\[",
    	lookaheadRegExp: /\[search\[(.*?)(?:\|(.*?))?\]\]/mg,
    	prompt: "search for: '%0'",
    	handler: function(w)
    	{
    		this.lookaheadRegExp.lastIndex = w.matchStart;
    		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
    		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
    			var label=lookaheadMatch[1];
    			var text=lookaheadMatch[2]||label;
    			var prompt=this.prompt.format([text]);
    			var btn=createTiddlyButton(w.output,label,prompt,
    				function(){story.search(this.getAttribute("searchText"))},"searchLink");
    			btn.setAttribute("searchText",text);
    			w.nextMatch = this.lookaheadRegExp.lastIndex;
    		}
    	}
    });
    //}}}
    // // incremental search uses option settings instead of hard-coded delay and minimum input values
    //{{{
    var fn=config.macros.search.onKeyPress;
    fn=fn.toString().replace(/500/g, "config.options.txtIncrementalSearchDelay||500");
    fn=fn.toString().replace(/> 2/g, ">=(config.options.txtIncrementalSearchMin||3)");
    eval("config.macros.search.onKeyPress="+fn);
    //}}}
    // // REPLACE story.search() for option to "show search results in a list"
    //{{{
    Story.prototype.search = function(text,useCaseSensitive,useRegExp)
    {
    	var co=config.options; // abbrev
    	var re=new RegExp(useRegExp ? text : text.escapeRegExp(),useCaseSensitive ? "mg" : "img");
    	if (config.options.chkSearchHighlight) highlightHack=re;
    	var matches = store.search(re,co.chkSearchByDate?"modified":"title","");
    	if (co.chkSearchByDate) matches=matches.reverse(); // most recent first
    	var q = useRegExp ? "/" : "'";
    	clearMessage();
    	if (!matches.length) {
    		if (co.chkSearchListTiddler) discardSearchResults();
    		displayMessage(config.macros.search.failureMsg.format([q+text+q]));
    	} else {
    		if (co.chkSearchList||co.chkSearchListTiddler)
    			reportSearchResults(text,matches);
    		else {
    			var titles = []; for(var t=0; t<matches.length; t++) titles.push(matches[t].title);
    			this.closeAllTiddlers(); story.displayTiddlers(null,titles);
    			displayMessage(config.macros.search.successMsg.format([matches.length, q+text+q]));
    		}
    	}
    	highlightHack = null;
    }
    //}}}
    // // REPLACE store.search() for enhanced searching/sorting options
    //{{{
    TiddlyWiki.prototype.search = function(searchRegExp,sortField,excludeTag)
    {
    	var co=config.options; // abbrev
    	var tids = this.reverseLookup("tags",excludeTag,false,sortField);
    	var opened=[]; story.forEachTiddler(function(tid,elem){opened.push(tid);});

    	// eliminate tiddlers tagged with excluded tags
    	if (co.chkSearchExcludeTags&&co.txtSearchExcludeTags.length) {
    		var ex=co.txtSearchExcludeTags.readBracketedList();
    		var temp=[]; for(var t=tids.length-1; t>=0; t--)
    			if (!tids[t].tags.containsAny(ex)) temp.push(tids[t]);
    		tids=temp;
    	}

    	// scan for matching titles first...
    	var results = [];
    	if (co.chkSearchTitles) {
    		for(var t=0; t<tids.length; t++) {
    			if (co.chkSearchOpenTiddlers && !opened.contains(tids[t].title)) continue;
    			if(tids[t].title.search(searchRegExp)!=-1) results.push(tids[t]);
    		}
    		if (co.chkSearchShadows)
    			for (var t in config.shadowTiddlers) {
    				if (co.chkSearchOpenTiddlers && !opened.contains(t)) continue;
    				if ((t.search(searchRegExp)!=-1) && !store.tiddlerExists(t))
    					results.push((new Tiddler()).assign(t,config.shadowTiddlers[t]));
    			}
    	}
    	// then scan for matching text, tags, or field data
    	for(var t=0; t<tids.length; t++) {
    		if (co.chkSearchOpenTiddlers && !opened.contains(tids[t].title)) continue;
    		if (co.chkSearchText && tids[t].text.search(searchRegExp)!=-1)
    			results.pushUnique(tids[t]);
    		if (co.chkSearchTags && tids[t].tags.join(" ").search(searchRegExp)!=-1)
    			results.pushUnique(tids[t]);
    		if (co.chkSearchFields && store.forEachField!=undefined)
    			store.forEachField(tids[t],
    				function(tid,field,val) {
    					if (val.search(searchRegExp)!=-1) results.pushUnique(tids[t]);
    				},
    				true); // extended fields only
    	}
    	// then check for matching text in shadows
    	if (co.chkSearchShadows)
    		for (var t in config.shadowTiddlers) {
    			if (co.chkSearchOpenTiddlers && !opened.contains(t)) continue;
    			if ((config.shadowTiddlers[t].search(searchRegExp)!=-1) && !store.tiddlerExists(t))
    				results.pushUnique((new Tiddler()).assign(t,config.shadowTiddlers[t]));
    		}

    	// if not 'titles first', or sorting by modification date,
    	// re-sort results to so titles, text, tag and field matches are mixed together
    	if(!sortField) sortField = "title";
    	var bySortField=function(a,b){
    		if(a[sortField]==b[sortField])return(0);else return(a[sortField]<b[sortField])?-1:+1;
    	}
    	if (!co.chkSearchTitlesFirst || co.chkSearchByDate) results.sort(bySortField);

    	return results;
    }
    //}}}
    // // HIJACK core {{{<<search>>}}} macro to add "report" and "simple inline" output
    //{{{
    config.macros.search.SOP_handler=config.macros.search.handler;
    config.macros.search.handler = function(place,macroName,params)
    {
    	// if "report", use SearchOptionsPlugin report generator for inline output
    	if (params[1]&&params[1].substr(0,6)=="report") {
    		var keyword=params[0];
    		var options=params[1].split("=")[1]; // split "report=option+option+..."
    		var heading=params[2]?params[2].unescapeLineBreaks():"";
    		var matches=store.search(new RegExp(keyword.escapeRegExp(),"img"),"title","excludeSearch");
    		if (matches.length) wikify(heading+window.formatSearchResults(keyword,matches,options),place);
    	} else if (params[1]) {
    		var keyword=params[0];
    		var heading=params[1]?params[1].unescapeLineBreaks():"";
    		var seperator=params[2]?params[2].unescapeLineBreaks():", ";
    		var matches=store.search(new RegExp(keyword.escapeRegExp(),"img"),"title","excludeSearch");
    		if (matches.length) {
    			var out=[];
    			for (var m=0; m<matches.length; m++) out.push("[["+matches[m].title+"]]");
    			wikify(heading+out.join(seperator),place);
    		}
    	} else
    		config.macros.search.SOP_handler.apply(this,arguments);
    };
    //}}}
    // // SearchResults panel handling
    //{{{
    setStylesheet(".searchResults { padding:1em 1em 0 1em; }","searchResults"); // matches std tiddler padding

    config.macros.search.createPanel=function(text,matches,body) {

    	function getByClass(e,c) { var d=e.getElementsByTagName("div");
    		for (var i=0;i<d.length;i++) if (hasClass(d[i],c)) return d[i]; }
    	var panel=createTiddlyElement(null,"div","searchPanel","searchPanel");
    	this.renderPanel(panel,text,matches,body);
    	var oldpanel=document.getElementById("searchPanel");
    	if (!oldpanel) { // insert new panel just above tiddlers
    		var da=document.getElementById("displayArea");
    		da.insertBefore(panel,da.firstChild);
    	} else { // if panel exists
    		var oldwrap=getByClass(oldpanel,"searchResults");
    		var newwrap=getByClass(panel,"searchResults");
    		// if no prior content, just insert new content
    		if (!oldwrap) oldpanel.insertBefore(newwrap,null);
    		else {	// swap search results content but leave containing panel intact
    			oldwrap.style.display='block'; // unfold wrapper if needed
    			var i=oldwrap.getElementsByTagName("input")[0]; // get input field
    			if (i) { var pos=this.getCursorPos(i); i.onblur=null; } // get cursor pos, ignore blur
    			oldpanel.replaceChild(newwrap,oldwrap);
    			panel=oldpanel; // use existing panel
    		}
    	}
    	this.showPanel(true,pos);
    	return panel;
    }

    config.macros.search.renderPanel=function(panel,text,matches,body) {

    	var wrap=createTiddlyElement(panel,"div",null,"searchResults");
    	wrap.onmouseover = function(e){ addClass(this,"selected"); }
    	wrap.onmouseout = function(e){ removeClass(this,"selected"); }
    	// create toolbar: "open all", "fold/unfold", "close"
    	var tb=createTiddlyElement(wrap,"div",null,"toolbar");
    	var b=createTiddlyButton(tb, "open all", "open all matching tiddlers", function() {
    		story.displayTiddlers(null,this.getAttribute("list").readBracketedList()); return false; },"button");
    	var list=""; for(var t=0;t<matches.length;t++) list+='[['+matches[t].title+']] ';
    	b.setAttribute("list",list);
    	var b=createTiddlyButton(tb, "fold", "toggle display of search results", function() {
    		config.macros.search.foldPanel(this); return false; },"button");
    	var b=createTiddlyButton(tb, "close", "dismiss search results",	function() {
    		config.macros.search.showPanel(false); return false; },"button");
    	createTiddlyText(createTiddlyElement(wrap,"div",null,"title"),"Search for: "+text); // title
    	wikify(body,createTiddlyElement(wrap,"div",null,"viewer")); // report
    	return panel;
    }

    config.macros.search.showPanel=function(show,pos) {
    	var panel=document.getElementById("searchPanel");
    	var i=panel.getElementsByTagName("input")[0];
    	i.onfocus=show?function(){config.macros.search.stayFocused(true);}:null;
    	i.onblur=show?function(){config.macros.search.stayFocused(false);}:null;
    	if (show && panel.style.display=="block") { // if shown, grab focus, restore cursor
    		if (i&&this.stayFocused()) { i.focus(); this.setCursorPos(i,pos); }
    		return;
    	}
    	if(!config.options.chkAnimate) {
    		panel.style.display=show?"block":"none";
    		if (!show) { removeChildren(panel); config.macros.search.stayFocused(false); }
    	} else {
    		var s=new Slider(panel,show,false,show?"none":"children");
    		s.callback=function(e,p){e.style.overflow="visible";}
    		anim.startAnimating(s);
    	}
    	return panel;
    }

    config.macros.search.foldPanel=function(button) {
    	var d=document.getElementById("searchPanel").getElementsByTagName("div");
    	for (var i=0;i<d.length;i++) if (hasClass(d[i],"viewer")) var v=d[i]; if (!v) return;
    	var show=v.style.display=="none";
    	if(!config.options.chkAnimate)
    		v.style.display=show?"block":"none";
    	else {
    		var s=new Slider(v,show,false,"none");
    		s.callback=function(e,p){e.style.overflow="visible";}
    		anim.startAnimating(s);
    	}
    	button.innerHTML=show?"fold":"unfold";
    	return false;
    }

    config.macros.search.stayFocused=function(keep) { // TRUE/FALSE=set value, no args=get value
    	if (keep===undefined) return this.keepReportInFocus;
    	this.keepReportInFocus=keep;
    	return keep
    }

    config.macros.search.getCursorPos=function(i) {
    	var s=0; var e=0; if (!i) return { start:s, end:e };
    	try {
    		if (i.setSelectionRange) // FF
    			{ s=i.selectionStart; e=i.selectionEnd; }
    		if (document.selection && document.selection.createRange) { // IE
    			var r=document.selection.createRange().duplicate();
    			var len=r.text.length; s=0-r.moveStart('character',-100000); e=s+len;
    		}
    	}catch(e){};
    	return { start:s, end:e };
    }
    config.macros.search.setCursorPos=function(i,pos) {
    	if (!i||!pos) return; var s=pos.start; var e=pos.end;
    	if (i.setSelectionRange) //FF
    		i.setSelectionRange(s,e);
    	if (i.createTextRange) // IE
    		{ var r=i.createTextRange(); r.collapse(true); r.moveStart("character",s); r.select(); }
    }
    //}}}
    // // SearchResults report generation
    // note: these functions are defined globally, so they can be more easily redefined to customize report formats//
    //{{{
    if (!window.reportSearchResults) window.reportSearchResults=function(text,matches)
    {
    	var cms=config.macros.search; // abbrev
    	var body=window.formatSearchResults(text,matches);
    	if (!config.options.chkSearchListTiddler) // show #searchResults panel
    		window.scrollTo(0,ensureVisible(cms.createPanel(text,matches,body)));
    	else { // write [[SearchResults]] tiddler
    		var title=cms.reportTitle;
    		var who=config.options.txtUserName;
    		var when=new Date();
    		var tags="excludeLists excludeSearch temporary";
    		var tid=store.getTiddler(title); if (!tid) tid=new Tiddler();
    		tid.set(title,body,who,when,tags);
    		store.addTiddler(tid);
    		story.closeTiddler(title);
    		story.displayTiddler(null,title);
    	}
    }

    if (!window.formatSearchResults) window.formatSearchResults=function(text,matches,opt)
    {
    	var body='';
    	var title=config.macros.search.reportTitle
    	var q = config.options.chkRegExpSearch ? "/" : "'";
    	if (!opt) var opt="all";
    	var parts=opt.split("+");
    	for (var i=0; i<parts.length; i++) { var p=parts[i].toLowerCase();
    		if (p=="again"||p=="all")   body+=window.formatSearchResults_again(text,matches);
    		if (p=="summary"||p=="all") body+=window.formatSearchResults_summary(text,matches);
    		if (p=="list"||p=="all")    body+=window.formatSearchResults_list(text,matches);
    		if (p=="buttons"||p=="all") body+=window.formatSearchResults_buttons(text,matches);
    	}
    	return body;
    }

    if (!window.formatSearchResults_again) window.formatSearchResults_again=function(text,matches)
    {
    	var title=config.macros.search.reportTitle
    	var body='';
    	// search again
    	body+='{{span{<<search "'+text.replace(/"/g,'&#x22;')+'">> /%\n';
    	body+='%/<html><input type="button" value="search again"';
    	body+=' onclick="var t=this.parentNode.parentNode.getElementsByTagName(\'input\')[0];';
    	body+=' config.macros.search.doSearch(t); return false;">';
    	body+=' <a href="javascript:;" onclick="';
    	body+=' var e=this.parentNode.nextSibling;';
    	body+=' var show=e.style.display!=\'block\';';
    	body+=' if(!config.options.chkAnimate) e.style.display=show?\'block\':\'none\';';
    	body+=' else anim.startAnimating(new Slider(e,show,false,\'none\'));';
    	body+=' return false;">options...</a>';
    	body+='</html>@@display:none;border-left:1px dotted;margin-left:1em;padding:0;padding-left:.5em;font-size:90%;/%\n';
    	body+='	%/<<option chkSearchTitles>>titles /%\n';
    	body+='	%/<<option chkSearchText>>text /%\n';
    	body+='	%/<<option chkSearchTags>>tags /%\n';
    	body+='	%/<<option chkSearchFields>>fields /%\n';
    	body+='	%/<<option chkSearchShadows>>shadows\n';
    	body+='	<<option chkCaseSensitiveSearch>>case-sensitive /%\n';
    	body+='	%/<<option chkRegExpSearch>>text patterns /%\n';
    	body+='	%/<<option chkSearchByDate>>sorted by date\n';
    	body+='	<<option chkSearchHighlight>> highlight matching text in displayed tiddlers\n';
    	body+='	<<option chkIncrementalSearch>>incremental key-by-key search: /%\n';
    	body+='	%/{{twochar{<<option txtIncrementalSearchMin>>}}} or more characters, /%\n';
    	body+='	%/{{threechar{<<option txtIncrementalSearchDelay>>}}} msec delay\n';
    	body+='	<<option chkSearchOpenTiddlers>> search only in tiddlers that are currently displayed\n';
    	body+='	<<option chkSearchExcludeTags>>exclude tiddlers tagged with:\n';
    	body+='	{{editor{<<option txtSearchExcludeTags>>}}}/%\n';
    	body+='%/@@}}}\n\n';
    	return body;
    }

    if (!window.formatSearchResults_summary) window.formatSearchResults_summary=function(text,matches)
    {
    	// summary: nn tiddlers found matching '...', options used
    	var body='';
    	var co=config.options; // abbrev
    	var title=config.macros.search.reportTitle
    	var q = co.chkRegExpSearch ? "/" : "'";
    	body+="''"+config.macros.search.successMsg.format([matches.length,q+"{{{"+text+"}}}"+q])+"''\n";
    	var opts=[];
    	if (co.chkSearchTitles) opts.push("titles");
    	if (co.chkSearchText) opts.push("text");
    	if (co.chkSearchTags) opts.push("tags");
    	if (co.chkSearchFields) opts.push("fields");
    	if (co.chkSearchShadows) opts.push("shadows");
    	if (co.chkSearchOpenTiddlers) body+="^^//search limited to displayed tiddlers only//^^\n";
    	body+="~~&nbsp; searched in "+opts.join(" + ")+"~~\n";
    	body+=(co.chkCaseSensitiveSearch||co.chkRegExpSearch?"^^&nbsp; using ":"")
    		+(co.chkCaseSensitiveSearch?"case-sensitive ":"")
    		+(co.chkRegExpSearch?"pattern ":"")
    		+(co.chkCaseSensitiveSearch||co.chkRegExpSearch?"matching^^\n":"");
    	return body;
    }

    if (!window.formatSearchResults_list) window.formatSearchResults_list=function(text,matches)
    {
    	// bullet list of links to matching tiddlers
    	var body='';
    	var pattern=co.chkRegExpSearch?text:text.escapeRegExp();
    	var sensitive=co.chkCaseSensitiveSearch?"mg":"img";
    	var link='{{tiddlyLinkExisting{<html><nowiki><a href="javascript:;" onclick="'
    		+'if(config.options.chkSearchHighlight)'
    		+'	highlightHack=new RegExp(\x27'+pattern+'\x27,\x27'+sensitive+'\x27);'
    		+'story.displayTiddler(null,\x27%0\x27);'
    		+'highlightHack = null; return false;'
    		+'" title="%2">%1</a></html>}}}';
    	for(var t=0;t<matches.length;t++) {
    		body+="* ";
    		if (config.options.chkSearchByDate)
    			body+=matches[t].modified.formatString('YYYY.0MM.0DD 0hh:0mm')+" ";
    		var title=matches[t].title;
    		var fixup=title.replace(/'/g,"\\x27").replace(/"/g,"\\x22");
    		var tid=store.getTiddler(title);
    		var tip=tid?tid.getSubtitle():''; tip=tip.replace(/"/g,"&quot;");
    		body+=link.format([fixup,title,tip])+'\n';
    	}
    	return body;
    }

    if (!window.formatSearchResults_buttons) window.formatSearchResults_buttons=function(text,matches)
    {
    	// embed buttons only if writing SearchResults to tiddler
    	if (!config.options.chkSearchListTiddler) return "";
    	// "open all" button
    	var title=config.macros.search.reportTitle;
    	var body="";
    	body+="@@diplay:block;<html><input type=\"button\" href=\"javascript:;\" "
    		+"onclick=\"story.displayTiddlers(null,[";
    	for(var t=0;t<matches.length;t++)
    		body+="'"+matches[t].title.replace(/\'/mg,"\\'")+"'"+((t<matches.length-1)?", ":"");
    	body+="],1);\" accesskey=\"O\" value=\"open all matching tiddlers\"></html> ";
    	// "discard SearchResults" button
    	body+="<html><input type=\"button\" href=\"javascript:;\" "
    		+"onclick=\"discardSearchResults()\" value=\"discard "+title+"\"></html>";
    	body+="@@\n";
    	return body;
    }

    if (!window.discardSearchResults) window.discardSearchResults=function()
    {
    	// remove the tiddler
    	story.closeTiddler(config.macros.search.reportTitle);
    	store.deleteTiddler(config.macros.search.reportTitle);
    	store.notify(config.macros.search.reportTitle,true);
    }
    //}}}

    /%
    !info
    |Name|ShowPopup|
    |Source|http://www.TiddlyTools.com/#ShowPopup|
    |Version|1.1.0|
    |Author|Eric Shulman|
    |License|http://www.TiddlyTools.com/#LegalStatements|
    |~CoreVersion|2.1|
    |Type|transcluded html|
    |Requires||
    |Overrides||
    |Description|display tiddler content in a TiddlyWiki popup panel|
    Usage:
    <<<
    {{{
    <<tiddler ShowPopup with: TiddlerName label tooltip buttonClass width popupClass>>
    }}}
    *{{{TiddlerName}}} is the title of the tiddler whose content is to be displayed
    *{{{label}}} is the text of the popup command
    *{{{tooltip}}} is the mouseover help text for the command
    *{{{buttonClass}}} is a CSS classname applied to the command text (default=button)
    *{{{width}}} is the width of the popup (using CSS measurements, default=auto)
    *{{{popupClass}}} is a CSS classname applied to the popup panel (default=none).  Use 'sticky' for persistent popups (requires  StickyPopupPlugin)
    <<<
    Example:
    <<<
    {{{
    <<tiddler ShowPopup with: ShowPopup [[Try this]] [[show this tiddler in a popup]]>>
    }}}
    <<tiddler ShowPopup with: ShowPopup [[Try this]] [[show this tiddler in a popup]]>>
    <<<
    !end

    !show
    <html><hide linebreaks>
    <a href="javascript:;" class="$4" title="$3" onclick="
    	var p=Popup.create(this);if(!p)return;p.className+=' $6';var t=store.getTiddlerText('$1','');
    	var d=createTiddlyElement(p,'div');var s=d.style;s.whiteSpace='normal';s.width='$5';s.padding='2px';wikify(t,d);
    	Popup.show();event.cancelBubble=true;if(event.stopPropagation)event.stopPropagation();return(false);
    ">$2</a></html>
    !end

    %/<<tiddler {{'ShowPopup##'+('$1'=='$'+'1'?'info':'show')}} with: [[$1]] [[$2]] [[$3]] [[$4]] [[$5]] [[$6]]>>

    <<closeAll>>/%
    %/<<permaview>>/%
    %/<<newTiddler>>/%
    %/<<newJournal "DD MMM YYYY" "journal">>/%
    %/<<saveChanges>>/%
    %/{{span{<<saveAs>><script>
    	place.style.display=(document.location.protocol!='file:')?'none':'inline';
    </script>}}}/%
    %/<<slider chkSliderOptionsPanel OptionsPanel "options »" "Change TiddlyWiki advanced options">>

    /***
    |Name|SinglePageModePlugin|
    |Source|http://www.TiddlyTools.com/#SinglePageModePlugin|
    |Documentation|http://www.TiddlyTools.com/#SinglePageModePluginInfo|
    |Version|2.9.6|
    |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.displayTiddler(), Story.prototype.displayTiddlers()|
    |Options|##Configuration|
    |Description|Show tiddlers one at a time with automatic permalink, or always open tiddlers at top/bottom of page.|
    This plugin allows you to configure TiddlyWiki to navigate more like a traditional multipage web site with only one tiddler displayed at a time.
    !!!!!Documentation
    >see [[SinglePageModePluginInfo]]
    !!!!!Configuration
    <<<
    <<option chkSinglePageMode>> Display one tiddler at a time
    ><<option chkSinglePagePermalink>> Automatically permalink current tiddler
    ><<option chkSinglePageKeepFoldedTiddlers>> Don't close tiddlers that are folded
    ><<option chkSinglePageKeepEditedTiddlers>> Don't close tiddlers that are being edited
    <<option chkTopOfPageMode>> Open tiddlers at the top of the page
    <<option chkBottomOfPageMode>> Open tiddlers at the bottom of the page
    <<option chkSinglePageAutoScroll>> Automatically scroll tiddler into view (if needed)

    Notes:
    * The "display one tiddler at a time" option can also be //temporarily// set/reset by including a 'paramifier' in the document URL: {{{#SPM:true}}} or {{{#SPM:false}}}.
    * If more than one display mode is selected, 'one at a time' display takes precedence over both 'top' and 'bottom' settings, and if 'one at a time' setting is not used, 'top of page' takes precedence over 'bottom of page'.
    * When using Apple's Safari browser, automatically setting the permalink causes an error and is disabled.
    <<<
    !!!!!Revisions
    <<<
    2008.10.17 [2.9.6] changed chkSinglePageAutoScroll default to false
    | Please see [[SinglePageModePluginInfo]] for previous revision details |
    2005.08.15 [1.0.0] Initial Release.  Support for BACK/FORWARD buttons adapted from code developed by Clint Checketts.
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.SinglePageModePlugin= {major: 2, minor: 9, revision: 6, date: new Date(2008,10,17)};
    //}}}
    //{{{
    config.paramifiers.SPM = { onstart: function(v) {
    	config.options.chkSinglePageMode=eval(v);
    	if (config.options.chkSinglePageMode && config.options.chkSinglePagePermalink && !config.browser.isSafari) {
    		config.lastURL = window.location.hash;
    		if (!config.SPMTimer) config.SPMTimer=window.setInterval(function() {checkLastURL();},1000);
    	}
    } };
    //}}}
    //{{{
    if (config.options.chkSinglePageMode==undefined)
    	config.options.chkSinglePageMode=false;
    if (config.options.chkSinglePagePermalink==undefined)
    	config.options.chkSinglePagePermalink=true;
    if (config.options.chkSinglePageKeepFoldedTiddlers==undefined)
    	config.options.chkSinglePageKeepFoldedTiddlers=false;
    if (config.options.chkSinglePageKeepEditedTiddlers==undefined)
    	config.options.chkSinglePageKeepEditedTiddlers=false;
    if (config.options.chkTopOfPageMode==undefined)
    	config.options.chkTopOfPageMode=false;
    if (config.options.chkBottomOfPageMode==undefined)
    	config.options.chkBottomOfPageMode=false;
    if (config.options.chkSinglePageAutoScroll==undefined)
    	config.options.chkSinglePageAutoScroll=false;
    //}}}
    //{{{
    config.SPMTimer = 0;
    config.lastURL = window.location.hash;
    function checkLastURL()
    {
    	if (!config.options.chkSinglePageMode)
    		{ window.clearInterval(config.SPMTimer); config.SPMTimer=0; return; }
    	if (config.lastURL == window.location.hash) return; // no change in hash
    	var tids=decodeURIComponent(window.location.hash.substr(1)).readBracketedList();
    	if (tids.length==1) // permalink (single tiddler in URL)
    		story.displayTiddler(null,tids[0]);
    	else { // restore permaview or default view
    		config.lastURL = window.location.hash;
    		if (!tids.length) tids=store.getTiddlerText("DefaultTiddlers").readBracketedList();
    		story.closeAllTiddlers();
    		story.displayTiddlers(null,tids);
    	}
    }

    if (Story.prototype.SPM_coreDisplayTiddler==undefined)
    	Story.prototype.SPM_coreDisplayTiddler=Story.prototype.displayTiddler;
    Story.prototype.displayTiddler = function(srcElement,tiddler,template,animate,slowly)
    {
    	var title=(tiddler instanceof Tiddler)?tiddler.title:tiddler;
    	var tiddlerElem=document.getElementById(story.idPrefix+title); // ==null unless tiddler is already displayed
    	var opt=config.options;
    	var single=opt.chkSinglePageMode && !startingUp;
    	var top=opt.chkTopOfPageMode && !startingUp;
    	var bottom=opt.chkBottomOfPageMode && !startingUp;
    	if (single) {
    		story.forEachTiddler(function(tid,elem) {
    			// skip current tiddler and, optionally, tiddlers that are folded.
    			if (	tid==title
    				|| (opt.chkSinglePageKeepFoldedTiddlers && elem.getAttribute("folded")=="true"))
    				return;
    			// if a tiddler is being edited, ask before closing
    			if (elem.getAttribute("dirty")=="true") {
    				if (opt.chkSinglePageKeepEditedTiddlers) return;
    				// if tiddler to be displayed is already shown, then leave active tiddler editor as is
    				// (occurs when switching between view and edit modes)
    				if (tiddlerElem) return;
    				// otherwise, ask for permission
    				var msg="'"+tid+"' is currently being edited.\n\n";
    				msg+="Press OK to save and close this tiddler\nor press Cancel to leave it opened";
    				if (!confirm(msg)) return; else story.saveTiddler(tid);
    			}
    			story.closeTiddler(tid);
    		});
    	}
    	else if (top)
    		arguments[0]=null;
    	else if (bottom)
    		arguments[0]="bottom";
    	if (single && opt.chkSinglePagePermalink && !config.browser.isSafari) {
    		window.location.hash = encodeURIComponent(String.encodeTiddlyLink(title));
    		config.lastURL = window.location.hash;
    		document.title = wikifyPlain("SiteTitle") + " - " + title;
    		if (!config.SPMTimer) config.SPMTimer=window.setInterval(function() {checkLastURL();},1000);
    	}
    	if (tiddlerElem && tiddlerElem.getAttribute("dirty")=="true") { // editing... move tiddler without re-rendering
    		var isTopTiddler=(tiddlerElem.previousSibling==null);
    		if (!isTopTiddler && (single || top))
    			tiddlerElem.parentNode.insertBefore(tiddlerElem,tiddlerElem.parentNode.firstChild);
    		else if (bottom)
    			tiddlerElem.parentNode.insertBefore(tiddlerElem,null);
    		else this.SPM_coreDisplayTiddler.apply(this,arguments); // let CORE render tiddler
    	} else
    		this.SPM_coreDisplayTiddler.apply(this,arguments); // let CORE render tiddler
    	var tiddlerElem=document.getElementById(story.idPrefix+title);
    	if (tiddlerElem&&opt.chkSinglePageAutoScroll) {
    		// scroll to top of page or top of tiddler
    		var isTopTiddler=(tiddlerElem.previousSibling==null);
    		var yPos=isTopTiddler?0:ensureVisible(tiddlerElem);
    		// if animating, defer scroll until after animation completes
    		var delay=opt.chkAnimate?config.animDuration+10:0;
    		setTimeout("window.scrollTo(0,"+yPos+")",delay);
    	}
    }

    if (Story.prototype.SPM_coreDisplayTiddlers==undefined)
    	Story.prototype.SPM_coreDisplayTiddlers=Story.prototype.displayTiddlers;
    Story.prototype.displayTiddlers = function() {
    	// suspend single/top/bottom modes when showing multiple tiddlers
    	var opt=config.options;
    	var saveSPM=opt.chkSinglePageMode; opt.chkSinglePageMode=false;
    	var saveTPM=opt.chkTopOfPageMode; opt.chkTopOfPageMode=false;
    	var saveBPM=opt.chkBottomOfPageMode; opt.chkBottomOfPageMode=false;
    	this.SPM_coreDisplayTiddlers.apply(this,arguments);
    	opt.chkBottomOfPageMode=saveBPM;
    	opt.chkTopOfPageMode=saveTPM;
    	opt.chkSinglePageMode=saveSPM;
    }
    //}}}

    {{floatright small{<<tiddler BreadcrumbsCommand with: crumbs>><<tiddler ToggleBreadcrumbs>>}}}{{small{
    Shift+Enter全文搜索:
    {{transparent{<<gotoTiddler
    	inputstyle:"width:97%;font-size:100%;border:2px inset #999;"
    	liststyle:"width:97%;font-size:100%;"
    	search
    >>}}}}}}

    熬夜必死 -- Lance
    ----
    淫者见淫,智者见智 -- 无名氏
    ----
    坑不在多,够深则名.妹不在萌,能推则灵. -- 无名氏
    ----
    吐槽就是我的生命。—— 黑衣少年
    ----
    男人变态有什么错！—— 黑衣少年
    ----
    为了萝莉，我愿化为修罗。—— 黑衣少年

    {{tiny{
    无双引擎官方论坛:http://bbs.gamediy.net
    <br>各种ACG,GalGame信息收集.}}}

    {{floatleft{无双引擎大杂烩}}}

    http://bbs.gamediy.net/

    /***
    |''Name:''|SlideShowPlugin|
    |''Description:''|Creates a slide show from any number of tiddlers|
    |''Author:''|Paulo Soares|
    |''Contributors:''|John P. Rouillard|
    |''Version:''|2.2.6|
    |''Date:''|2010-11-17|
    |''Source:''|http://www.math.ist.utl.pt/~psoares/addons.html|
    |''Documentation:''|[[SlideShowPlugin Documentation|SlideShowPluginDoc]]|
    |''License:''|[[Creative Commons Attribution-Share Alike 3.0 License|http://creativecommons.org/licenses/by-sa/3.0/]]|
    |''~CoreVersion:''|2.5.0|
    ***/
    //{{{
    if(!version.extensions.SlideShowPlugin) { //# ensure that the plugin is only installed once
    version.extensions.SlideShowPlugin = {installed: true};

    (function($) {
    config.macros.slideShow = {maxTOCLength: 30, separator:'-s-'};

    config.formatters.push( {
    	name: "SlideSeparator",
    	match: "^"+config.macros.slideShow.separator+"+$\\n?",
    	handler: function(w) {
    		createTiddlyElement(w.output,"hr",null,'slideSeparator');
    	}
    });

    config.macros.slideShow.text = {
      label: "slide show", tooltip: "Start slide show",
      quit: {label: "x", tooltip: "Quit the slide show"},
      firstSlide: {label: "<<", tooltip: "Go to first slide"},
      previous: {label: "<", tooltip: "Go back"},
      next: {label: ">", tooltip: "Advance"},
      lastSlide: {label: ">>", tooltip: "Go to last slide"},
      goto: {label: "Go to slide:"},
      resetClock: {tooltip: "Reset the clock"},
      overlay: "overlay"
    };

    config.macros.slideShow.handler = function(place,macroName,params,wikifier,paramString){
      var args = paramString.parseParams(null,null,false);
      this.label = getParam(args,"label",this.text.label);
      this.tooltip = getParam(args,"tooltip",this.text.tooltip);
      var onclick = function(){config.macros.slideShow.onClick(place,paramString); return false;};
      createTiddlyButton(place,this.label,this.tooltip,onclick);
      return false;
    }

    config.macros.slideShow.onClick = function(place,paramString) {
      var slide, cm = config.macros.slideShow;
      var title = story.findContainingTiddler(place);
      title = title ? title.getAttribute("tiddler") : null;
      var args = paramString.parseParams(null,null,false);
      title =  getParam(args,"tiddler",title);
      var argsArray = paramString.readMacroParams();
      this.single = ($.inArray('single',argsArray) > -1);
      this.clicks = ($.inArray('noClicks',argsArray) < 0);
      this.keyboard = ($.inArray('noKeyboard',argsArray) < 0);
      this.showAll = ($.inArray('showAll',argsArray) > -1);
      this.cycle = ($.inArray('cycle',argsArray) > -1);
      this.overlays = ($.inArray('noOverlays',argsArray) < 0);
      this.theme = getParam(args,"theme");
      this.tag = getParam(args,"tag");
      this.toc = getParam(args,"toc","headers");
      this.sort = getParam(args,"sort");
      this.clockFormat = getParam(args,"clockFormat",'0hh:0mm:0ss');
      this.auto = getParam(args,"auto",0);
      this.header = getParam(args,"header",title);
      this.footer = getParam(args,"footer","");
      this.clock = getParam(args,"clock");
      this.blocked = 0;
      if(this.clock){
        var startTime = new Date(0);
        this.clockCorrection=startTime.getTimezoneOffset()*60000;
        startTime = new Date();
        this.clockMultiplier = 1;
        this.clockInterval = 0;
        var clockType= parseFloat(this.clock);
        if(clockType < 0) {
          this.clockMultiplier = -1;
          this.clockInterval = -clockType*60000;
        } else if(clockType == 0){
          this.clockCorrection = 0;
          startTime = new Date(0);
        }
        this.clockStartTime=startTime.getTime();
      }
      this.slides = [];
      this.openTiddlers = [];
      $("#tiddlerDisplay > *").each(function(){cm.openTiddlers.push($(this).attr('tiddler'))});
      var count = 0;
      this.slideTOC=[];
      if(this.single){
        if(!store.tiddlerExists(title)) return;
        var newTiddler;
        var content = store.getTiddlerText(title).split(cm.separator);
        $.each(content, function(){
          count++;
          newTiddler = new Tiddler();
          newTiddler.title ="TempSlide" + count;
          newTiddler.tags[0] = "excludeLists";
          newTiddler.text = $.trim(this);
          newTiddler.fields['doNotSave']= true;
          store.addTiddler(newTiddler);
          cm.buildTOC(count,newTiddler.title);
          cm.slides.push(newTiddler.title);
        });
      } else {
        if(this.tag){
          var content = store.getTaggedTiddlers(this.tag,this.sort);
          $.each(content, function(){
            count++;
            cm.buildTOC(count,this.title);
            cm.slides.push(this.title);
          });
        } else {
          story.displayTiddler(null,title);
          var list = $('[tiddler='+title+']').find('.viewer').find('.tiddlyLinkExisting');
          $.each(list,function(){
            if(!$(this).parents().hasClass("exclude")){
              slide = $(this).attr('tiddlylink');
              count++;
              cm.buildTOC(count,slide);
              cm.slides.push(slide);
            }
          });
        }
      }
      this.nSlides = this.slides.length;
      if(this.nSlides==0) return false;
      clearMessage();
      this.toggleSlideStyles();
      if(!this.showAll){
        //Attach the key and mouse listeners
        if(this.keyboard && !$("#tiddlerDisplay").hasClass("noKeyboard")) $(document).keyup(cm.keys);
        if(this.clicks){
          $(document).mouseup(cm.clicker);
          document.oncontextmenu = function(){return false;}
        }
        if(this.clock) this.slideClock=setInterval(this.setClock, 1000);
        if(this.auto>0){
          this.autoAdvance=setInterval(cm.next, this.auto*1000);
        }
        this.showSlide(1);
      } else {
        story.closeAllTiddlers();
        story.displayTiddlers(null,this.slides);
        $(".tiddler").attr("ondblclick",null);
        $(document).keyup(cm.endSlideShow);
      }
      return false;
    }

    config.macros.slideShow.buildNavigator = function() {
      //Create the navigation bar
      var i, slidefooter = $("#controlBar")[0];
      if(!slidefooter) return;
      $(slidefooter).addClass("slideFooterOff noClicks");
      var navigator = createTiddlyElement(slidefooter,"SPAN","navigator");
      var buttonBar = createTiddlyElement(navigator,"SPAN","buttonBar");
      //Make it so that when the footer is hovered over the class will change to make it visible
      $(slidefooter).bind("mouseenter mouseleave", function(e){$(this).toggleClass("slideFooterOff");});
      //Create the control buttons for the navigation

      createTiddlyButton(buttonBar,this.text.firstSlide.label,this.text.firstSlide.tooltip,this.firstSlide,"button");
      createTiddlyButton(buttonBar,this.text.previous.label,this.text.previous.tooltip,this.previous,"button");
      createTiddlyButton(buttonBar,this.text.quit.label,this.text.quit.tooltip,this.endSlideShow,"button");
      createTiddlyButton(buttonBar,this.text.next.label,this.text.next.tooltip,this.next,"button");
      createTiddlyButton(buttonBar,this.text.lastSlide.label,this.text.lastSlide.tooltip,this.lastSlide,"button");
      if(this.clock){
        if(this.clock == 0){
           createTiddlyElement(navigator,"SPAN","slideClock");
        } else {
          createTiddlyButton(navigator," ",this.text.resetClock.tooltip,this.resetClock,"button","slideClock");
        }
        this.setClock();
      }
      var index = createTiddlyElement(slidefooter,"SPAN","slideCounter");
      index.onclick = this.toggleTOC;
      var toc = createTiddlyElement(slidefooter,"SPAN","toc");
      var tocLine;
      for(i=0; i<this.slideTOC.length; i++){
        $(toc).append(this.slideTOC[i][2]);
        tocLine = $(toc.lastChild);
        tocLine.addClass("tocLevel"+this.slideTOC[i][1]).css("cursor", "pointer").hover(function () {
            $(this).addClass("highlight");}, function () {
            $(this).removeClass("highlight");});
        tocLine.attr("slide",this.slideTOC[i][0]);
        tocLine.click(config.macros.slideShow.showSlideFromTOC);
      }
      //Input box to jump to specific slide
      var tocItem = createTiddlyElement(toc,"DIV","jumpItem",null,this.text.goto.label);
      var tocJumpInput = createTiddlyElement(tocItem,"INPUT","jumpInput");
      tocJumpInput.type="text";
      $(tocJumpInput).keyup(config.macros.slideShow.jumpToSlide);
    }

    //Used to shorten the TOC fields
    config.macros.slideShow.abbreviate = function(label){
      if(label.length>this.maxTOCLength) {
        var temp = new Array();
        temp = label.split(' ');
        label = temp[0];
        for(var j=1; j<temp.length; j++){
          if((label.length+temp[j].length)<=this.maxTOCLength){
            label += " " + temp[j];
          } else {
            label += " ...";
            break;
          }
        }
      }
      return label;
    }

    config.macros.slideShow.buildTOC = function(count,title) {
      var level = 1, text;
      switch(this.toc){
      case "headers":
        var frag = wikifyStatic(store.getTiddlerText(title));
        text = frag.replace(/<div class="comment">.*<\/div>/mg,"");
        var matches =  text.match(/<h[123456]>.*?<\/h[123456]>/mgi);
        if(matches){
          for (var j=0; j<matches.length; j++){
            level = matches[j].charAt(2);
            text = matches[j].replace(/<\/?h[123456]>/gi,"");
            text = this.abbreviate(text);
            this.slideTOC.push([count,level,"<div>"+text+"</div>"]);
          }
        }
        break;
      case "titles":
        text = this.abbreviate(title);
        this.slideTOC.push([count,level,"<div>"+text+"</div>"]);
      }
    }

    config.macros.slideShow.showSlideFromTOC = function(e) {
      var cm = config.macros.slideShow;
      var slide = parseInt(e.target.getAttribute('slide'));
      $("#toc").hide();
      cm.showSlide(slide);
      return false;
    }

    config.macros.slideShow.toggleTOC = function(){
      $("#toc").toggle();
      $("#jumpInput").focus().val('');
      return false;
    }

    config.macros.slideShow.isInteger = function(s){
      for (var i = 0; i < s.length; i++){
        // Check that current character is number
        var c = s.charAt(i);
        if (((c < "0") || (c > "9"))) return false;
      }
      // All characters are numbers
      return true;
    }

    config.macros.slideShow.jumpToSlide = function(e){
      var cm = config.macros.slideShow;
      if(e.which==13){
        var input= $("#jumpInput").val();
        if(cm.isInteger(input) && input>0 && input<=cm.nSlides){
          $("#toc").hide();
          cm.showSlide(input);
        } else  {$("#jumpInput").val('');}
      }
      return false;
    }

    config.macros.slideShow.toggleSlideStyles = function(){
      var contentWrapper = $('#contentWrapper');
      if(contentWrapper.hasClass("slideShowMode")){
        refreshPageTemplate();
        removeStyleSheet("SlideShowStyleSheet");
        if(this.theme) removeStyleSheet(this.theme);
      } else {
        $("#displayArea").prepend('<div id="slideBlanker" style="display:none"></div><div id="slideHeader">'+this.header+'</div><div id="slideFooter">'+this.footer+'</div><div id="controlBar"></div>');
        setStylesheet(store.getRecursiveTiddlerText("SlideShowStyleSheet"),"SlideShowStyleSheet");
        if(this.theme && store.tiddlerExists(this.theme)){setStylesheet(store.getRecursiveTiddlerText(this.theme),this.theme);}
        this.buildNavigator();
      }
      contentWrapper.toggleClass("slideShowMode");
      return false;
    }

    config.macros.slideShow.showSlide = function(n){
      if(this.cycle) {
        if(n>this.nSlides) {
          n = 1;
        } else if(n<1) {
          n = this.nSlides;
        }
      } else {
        if(n>this.nSlides || n<1) return;
      }
      story.closeAllTiddlers();
      if(this.clock=='-'){this.resetClock();}
      story.displayTiddler(null,String(this.slides[n-1]));
      $(".tiddler").attr("ondblclick",null);
      $("body").removeClass("slide"+this.curSlide);
      this.curSlide = n;
      $("body").addClass("slide"+this.curSlide);
      $("#slideCounter").text(this.curSlide+"/"+this.nSlides);
      if(this.overlays){
        var contents = $(".viewer *");
        this.numOverlays = 1;
        while(1){
          if(contents.hasClass(this.text.overlay+this.numOverlays)){
            this.numOverlays++;
          } else {break;}
        }
        this.numOverlays--;
        this.showOverlay(0);
      }
      return false;
    }

    config.macros.slideShow.showOverlay = function(n){
      var i, set, cm = config.macros.slideShow;
      if(!cm.overlays || cm.numOverlays == 0 || n<0 || n>cm.numOverlays){return;}
      for(i=1; i<n; i++){
        set = $(".viewer "+"."+cm.text.overlay+i);
        set.removeClass("currentOverlay nextOverlay");
        set.addClass("previousOverlay");
      }
      set = $(".viewer "+"."+cm.text.overlay+n);
      set.removeClass("previousOverlay nextOverlay");
      set.addClass("currentOverlay");
      for(i=n; i<config.macros.slideShow.numOverlays; i++){
        set = $(".viewer "+"."+cm.text.overlay+(i+1));
        set.removeClass("previousOverlay currentOverlay");
        set.addClass("nextOverlay");
      }
      cm.curOverlay = n;
    }

    config.macros.slideShow.firstSlide = function(){
      config.macros.slideShow.showSlide(1);
      return false;
    }

    config.macros.slideShow.lastSlide = function(){
      config.macros.slideShow.showSlide(config.macros.slideShow.nSlides);
      return false;
    }

    config.macros.slideShow.next = function(){
      var cm = config.macros.slideShow;
      if(!cm.overlays || cm.numOverlays == 0 || cm.curOverlay == cm.numOverlays) {
        cm.showSlide(cm.curSlide+1);
      } else {
        cm.showOverlay(cm.curOverlay+1);
      }
      return false;
    }

    config.macros.slideShow.previous = function(){
      var cm = config.macros.slideShow;
      if(!cm.overlays || cm.numOverlays == 0 || cm.curOverlay == 0) {
        cm.showSlide(cm.curSlide-1);
        cm.showOverlay(cm.numOverlays);
      } else {
        cm.showOverlay(cm.curOverlay-1);
      }
      return false;
    }

    config.macros.slideShow.endSlideShow=function(){
      var cm = config.macros.slideShow;
      if(cm.autoAdvance) {clearInterval(cm.autoAdvance);}
      if(cm.clock) clearInterval(cm.slideClock);
      story.closeAllTiddlers();
      cm.toggleSlideStyles();
      story.displayTiddlers(null,cm.openTiddlers);
      $(document).unbind();
      document.oncontextmenu =  function(){};
      $("body").removeClass("slide"+cm.curSlide);
      return false;
    }

    // 'keys' code adapted from S5 which in turn was adapted from MozPoint (http://mozpoint.mozdev.org/)
    config.macros.slideShow.keys = function(key) {
      var cm = config.macros.slideShow;
      switch(key.which) {
      case 32: // spacebar
        if(cm.auto>0 && cm.blocked==0){
          if(cm.autoAdvance){
            clearInterval(cm.autoAdvance);
            cm.autoAdvance = null;
          } else {
            cm.autoAdvance=setInterval(cm.next, cm.auto*1000);
          }
        } else {
          if(cm.blocked==0) cm.next();
        }
        break;
      case 34: // page down
        if(cm.blocked==0) cm.showSlide(cm.curSlide+1);
        break;
      case 39: // rightkey
        if(cm.blocked==0) cm.next();
        break;
      case 40: // downkey
        if(cm.blocked==0) cm.showOverlay(cm.numOverlays);
        break;
      case 33: // page up
        if(cm.blocked==0) cm.showSlide(cm.curSlide-1);
        break;
      case 37: // leftkey
        if(cm.blocked==0) cm.previous();
        break;
      case 38: // upkey
        if(cm.blocked==0) cm.showOverlay(0);
        break;
      case 36: // home
        if(cm.blocked==0) cm.firstSlide();
        break;
      case 35: // end
        if(cm.blocked==0) cm.lastSlide();
        break;
      case 27: // escape
        cm.endSlideShow();
        break;
      case 66: // B
        $("#slideBlanker").toggle();
        cm.blocked = (cm.blocked +1)%2;
        break;
      }
      return false;
    }

    config.macros.slideShow.clicker = function(e) {
      var cm = config.macros.slideShow;
      if(cm.blocked==1 || $(e.target).attr('href') || $(e.target).parents().andSelf().hasClass('noClicks')){
        return true;
      }
      if($("#toc").is(':visible')){
        cm.toggleTOC();
      } else {
        if((!e.which && e.button == 1) || e.which == 1) {
          cm.next();
        }
        if((!e.which && e.button == 2) || e.which == 3) {
          cm.previous();
        }
      }
      return false;
    }

    config.macros.slideShow.setClock = function(){
      var cm = config.macros.slideShow;
      var actualTime = new Date();
      var newTime = actualTime.getTime() - cm.clockStartTime;
      newTime = cm.clockMultiplier*newTime+cm.clockInterval+cm.clockCorrection;
      actualTime.setTime(newTime);
      newTime = actualTime.formatString(cm.clockFormat);
      $("#slideClock").text(newTime);
      return false;
    }

    config.macros.slideShow.resetClock = function(){
      var cm = config.macros.slideShow;
      if(cm.clock == 0) return;
      var time = new Date(0);
      if(cm.clockStartTime>time){
        var startTime = new Date();
        cm.clockStartTime=startTime.getTime();
      }
      return false;
    }

    config.shadowTiddlers.SlideShowStyleSheet="/*{{{*/\n.header, #mainMenu, #storyMenu, #siteNav, #breadCrumbs, #scrollToTop, #sidebar, #backstageButton, #backstageArea, .toolbar, .title, .subtitle, .tagging, .tagged, .tagClear, .comment{\n display:none !important\n}\n\n#slideBlanker{\n position: absolute;\n top: 0;\n left: 0;\n width: 100%;\n height: 100%;\n z-index: 90; \n background-color: #000;\n opacity: 0.9;\n filter: alpha(opacity=90)\n}\n\n.nextOverlay{\n visibility: hidden\n}\n\n.previousOverlay,.currentOverlay{\n visibility: visible\n}\n\n#displayArea{\n font-size: 250%;\n margin: 0 !important;\n padding: 0\n}\n\n#controlBar{\n position: fixed;\n bottom: 2px;\n right: 2px;\n width: 100%;\n text-align: right\n}\n\n#controlBar .button{\n margin: 0 0.25em;\n padding: 0 0.25em\n}\n\n#slideHeader{\n font-size: 200%;\n font-weight: bold\n}\n\n#slideFooter{\n position: fixed;\n bottom: 2px\n}\n\n.slideFooterOff #navigator{\n visibility: hidden\n}\n\n#slideClock{\n margin: 0 5px 0 5px\n}\n\n#slideCounter{\n cursor: pointer;\n color: #aaa\n}\n\n#toc{\n display: none;\n position: absolute;\n font-size: .75em;\n bottom: 2em;\n right: 0;\n background: #fff;\n border: 1px solid #000;\n text-align: left\n}\n\n#jumpItem{\n padding-left:0.25em\n}\n\n#jumpInput{\n margin-left: 0.25em;\n width: 3em\n}\n\n.tocLevel1{\n font-size: .8em\n}\n\n.tocLevel2{\n margin-left: 1em;\n font-size: .75em\n}\n\n.tocLevel3{\n margin-left: 2em;\n font-size: .7em\n}\n\n.tocLevel4{\n margin-left: 3em;\n font-size: .65em\n}\n\n.tocLevel5{\n margin-left: 4em;\n font-size: .6em\n}\n\n.tocLevel6{\n margin-left: 5em;\n font-size: .55em\n}\n/*}}}*/";

    config.shadowTiddlers.SlideShowPluginDoc="The documentation is available [[here|http://www.math.ist.utl.pt/~psoares/addons.html#SlideShowPluginDoc]].";
    })(jQuery)
    }
    //}}}

    /*{{{*/
    .header, #mainMenu, #storyMenu, #siteNav, #breadCrumbs, #scrollToTop, #sidebar, #backstageButton, #backstageArea, .toolbar, .title, .subtitle, .tagging, .tagged, .tagClear, .comment{
     display:none !important
    }

    #slideBlanker{
     position: absolute;
     top: 0;
     left: 0;
     width: 100%;
     height: 100%;
     z-index: 90;
     background-color: #000;
     opacity: 0.9;
     filter: alpha(opacity=90)
    }

    .nextOverlay{
     visibility: hidden
    }

    .previousOverlay,.currentOverlay{
     visibility: visible
    }

    #displayArea{
     font-size: 250%;
     margin: 0 !important;
     padding: 0
    }

    #controlBar{
     position: fixed;
     bottom: 2px;
     right: 2px;
     width: 100%;
     text-align: right
    }

    #controlBar .button{
     margin: 0 0.25em;
     padding: 0 0.25em
    }

    #slideHeader{
     display: none;
     font-size: 200%;
     font-weight: bold
    }

    #slideFooter{
     position: fixed;
     bottom: 2px
    }

    .slideFooterOff #navigator{
     visibility: hidden
    }

    #slideClock{
     margin: 0 5px 0 5px
    }

    #slideCounter{
     cursor: pointer;
     color: #aaa
    }

    #toc{
     display: none;
     position: absolute;
     font-size: .75em;
     bottom: 2em;
     right: 0;
     background: #fff;
     border: 1px solid #000;
     text-align: left
    }

    #jumpItem{
     padding-left:0.25em
    }

    #jumpInput{
     margin-left: 0.25em;
     width: 3em
    }

    .tocLevel1{
     font-size: .8em
    }

    .tocLevel2{
     margin-left: 1em;
     font-size: .75em
    }

    .tocLevel3{
     margin-left: 2em;
     font-size: .7em
    }

    .tocLevel4{
     margin-left: 3em;
     font-size: .65em
    }

    .tocLevel5{
     margin-left: 4em;
     font-size: .6em
    }

    .tocLevel6{
     margin-left: 5em;
     font-size: .55em
    }
    /*}}}*/

    /***
    |Name|SnapshotPlugin|
    |Source|http://www.TiddlyTools.com/#SnapshotPlugin|
    |Documentation|http://www.TiddlyTools.com/#SnapshotPluginInfo|
    |Version|1.2.0|
    |Author|Eric Shulman|
    |License|http://www.TiddlyTools.com/#LegalStatements|
    |~CoreVersion|2.1|
    |Type|plugin|
    |Requires||
    |Overrides||
    |Description|save or print HTML+CSS image of rendered document content|
    |Status|ALPHA - DO NOT DISTRIBUTE|
    This plugin provides a macro as well as tiddler toolbar commands to create a file or browser window containing the //rendered// CSS-and-HTML that is currently being displayed for selected elements of the current document.
    !!!!!Documentation
    >see [[SnapshotPluginInfo]]
    !!!!!Configuration
    <<<
    <<option chkSnapshotHTMLOnly>> output HTML only (omit CSS)
    <<<
    !!!!!Revisions
    <<<
    2009.06.04 [1.2.0] added handling in getSnap() so current form input values are shown in snapshots
    |please see [[SnapshotPluginInfo]] for additional revision details|
    2008.04.21 [1.0.0] initial release - derived from [[NewDocumentPlugin]] with many improvements...
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.SnapshotPlugin= {major: 1, minor: 2, revision: 0, date: new Date(2009,6,4)};

    if (config.options.chkSnapshotHTMLOnly===undefined) config.options.chkSnapshotHTMLOnly=false;

    config.macros.snapshot = {
    	snapLabel: "save a snapshot",
    	printLabel: "print a snapshot",
    	snapPrompt: "save an HTML image of rendered content",
    	printPrompt: "print an HTML image of rendered content",
    	hereID: "here",
    	viewerID: "viewer",
    	storyID: "story",
    	allID: "all",
    	askID: "ask",
    	askTiddlerID: "askTiddler",
    	askDOMID: "askDOM",
    	askMsg: "select an element...",
    	hereItem: "tiddler: '%0'",
    	viewerItem: "tiddler: '%0' (content only)",
    	storyItem: "story column",
    	allItem: "entire document",
    	tiddlerItem: "select a tiddler...",
    	IDItem: "select a DOM element by ID...",
    	HTMLItem: "[%0] output HTML only (omit CSS)",
    	fileMsg: "select or enter a target path/filename",
    	defaultFilename: "snapshot.html",
    	okmsg: "snapshot written to %0",
    	failmsg: "An error occurred while creating %0",
    	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    		var printing=params[0]&&params[0]=="print"; if (printing) params.shift();
    		params = paramString.parseParams("anon",null,true,false,false);
    		var id=getParam(params,"id","here");
    		var label=getParam(params,"label",printing?this.printLabel:this.snapLabel);
    		var prompt=getParam(params,"prompt",printing?this.printPrompt:this.snapPrompt);
    		var btn=createTiddlyButton(place,label,prompt, function(ev){
    			this.setAttribute("snapID",this.getAttribute("startID"));
    			config.macros.snapshot.go(this,ev)
    		});
    		btn.setAttribute("startID",id);
    		btn.setAttribute("snapID",id);
    		btn.setAttribute("printing",printing?"true":"false");
    		btn.setAttribute("HTMLOnly",config.options.chkSnapshotHTMLOnly?"true":"false");
    	},
    	go: function(here,ev) {
    		var cms=config.macros.snapshot; // abbreviation
    		var id=here.getAttribute("snapID");
    		var printing=here.getAttribute("printing")=="true";
    		var HTMLOnly=here.getAttribute("HTMLOnly")=="true";

    		if (id==cms.askID||id==cms.askTiddlerID||id==cms.askDOMID) {
    			cms.askForID(here,ev);
    		} else {
    			// get element
    			if (id==cms.storyID) id="tiddlerDisplay";
    			if (id==cms.allID) id="contentWrapper";
    			var snapElem=document.getElementById(id);
    			if (id==cms.hereID || id==cms.viewerID)
    				var snapElem=story.findContainingTiddler(here);
    			if (snapElem && hasClass(snapElem,"tiddler") && (id==cms.viewerID || HTMLOnly)) {
    				// find viewer class element within tiddler element
    				var nodes=snapElem.getElementsByTagName("*");
    				for (var i=0; i<nodes.length; i++)
    					if (hasClass(nodes[i],"viewer")) { snapElem=nodes[i]; break; }
    			}
    			if (!snapElem) // not in a tiddler or no viewer element or unknown ID
    				{ e.cancelBubble=true; if(e.stopPropagation)e.stopPropagation(); return(false); }
    			// write or print snapshot
    			var out=cms.getsnap(snapElem,id,printing,HTMLOnly);
    			if (printing) cms.printsnap(out); else cms.savesnap(out);
    		}
    		return false;
    	},
    	askForID: function(here,ev) {
    		var ev = ev ? ev : window.event;
    		var cms=config.macros.snapshot; // abbreviation
    		var id=here.getAttribute("snapID");
    		var indent='\xa0\xa0\xa0\xa0';
    		var p=Popup.create(here); if (!p) return false; p.className+=' sticky smallform';
    		var s=createTiddlyElement(p,'select'); s.button=here;
    		if (id==cms.askID) {
    			s.options[s.length]=new Option(cms.askMsg,cms.askID);
    			var tid=story.findContainingTiddler(here);
    			if(tid) {
    				var title=tid.getAttribute("tiddler");
    				if (here.getAttribute("HTMLOnly")!="true")
    					s.options[s.length]=new Option(indent+cms.hereItem.format([title]),cms.hereID);
    				s.options[s.length]=new Option(indent+cms.viewerItem.format([title]),cms.viewerID);
    			}
    			s.options[s.length]=new Option(indent+cms.tiddlerItem,cms.askTiddlerID);
    			s.options[s.length]=new Option(indent+cms.IDItem,cms.askDOMID);
    			s.options[s.length]=new Option(indent+cms.storyItem,"tiddlerDisplay");
    			s.options[s.length]=new Option(indent+cms.allItem,"contentWrapper");
    		}
    		if (id==cms.askDOMID) {
    			s.options[s.length]=new Option(cms.IDItem,cms.askDOMID);
    			var elems=document.getElementsByTagName("*");
    			var ids=[];
    			for (var i=0;i<elems.length;i++)
    				if (elems[i].id.length && elems[i].className!="animationContainer")
    					ids.push(elems[i].id);
    			ids.sort();
    			for (var i=0;i<ids.length;i++) s.options[s.length]=new Option(indent+ids[i],ids[i]);
    		}
    		if (id==cms.askTiddlerID) {
    			s.options[s.length]=new Option(cms.tiddlerItem,cms.askTiddlerID);
    			var elems=document.getElementsByTagName("div");
    			var ids=[];
    			for (var i=0;i<elems.length;i++) { var id=elems[i].id;
    				if (id.length && id.substr(0,story.idPrefix.length)==story.idPrefix && id!="tiddlerDisplay")
    					ids.push(id);
    			}
    			ids.sort();
    			for (var i=0;i<ids.length;i++) s.options[s.length]=new Option(indent+ids[i].substr(story.idPrefix.length),ids[i]);
    		}
    		s.options[s.length]=new Option(cms.HTMLItem.format([here.getAttribute("HTMLOnly")=="true"?"\u221a":"_"]),cms.HTMLItem);
    		s.onchange=function(ev){
    			var ev = ev ? ev : window.event;
    			var cms=config.macros.snapshot; // abbreviation
    			var here=this.button;
    			if (this.value==cms.HTMLItem) {
    				config.options.chkSnapshotHTMLOnly=!config.options.chkSnapshotHTMLOnly;
    				here.setAttribute("HTMLOnly",config.options.chkSnapshotHTMLOnly?"true":"false");
    				config.macros.option.propagateOption("chkSnapshotHTMLOnly","checked",
    					config.options.chkSnapshotHTMLOnly,"input");
    			} else
    				here.setAttribute("snapID",this.value);
    			config.macros.snapshot.go(here,ev);
    			return false;
    		};
    		Popup.show();
    		ev.cancelBubble=true;
    		if(ev.stopPropagation)ev.stopPropagation();
    		return false;
    	},
    	getpath: function() {
    		// get current path
    		var path=getLocalPath(window.location.href);
    		var slashpos=path.lastIndexOf("/");
    		if (slashpos==-1) slashpos=path.lastIndexOf("\\");
    		if (slashpos!=-1) path=path.substr(0,slashpos+1); // trim filename
    		return path;
    	},
    	getsnap: function(snapElem,id,printing,HTMLOnly) {
    		var cms=config.macros.snapshot; // abbreviation
    		var out='<head>\n';
    		if (printing)
    			out+='<base href="file:///'+cms.getpath().replace(/\\/g,'/')+'"></base>\n';
    		if (!HTMLOnly) {
    			var styles=document.getElementsByTagName('style');
    			var fmt='<style>\n/* stylesheet=%0 */\n%1\n\n</style>\n';
    			for(var i=0; i < styles.length; i++)
    				out+=fmt.format([styles[i].getAttribute('id'),styles[i].innerHTML]);
    		}
    		out+='</head>\n';

    		var elems=snapElem.getElementsByTagName('input');
    		for (var i=0; i<elems.length; i++) { var e=elems[i];
    			if (e.type=='text')		e.defaultValue=e.value;
    			if (e.type=='checkbox')	 	e.defaultChecked=e.checked;
    			if (e.type=='radiobutton')	e.defaultChecked=e.checked;
    		}
    		var elems=snapElem.getElementsByTagName('textarea');
    		for (var i=0; i<elems.length; i++)	elems[i].defaultValue=elems[i].value;

    		var fmt='<body>\n\n<div class="%0">%1</div>\n\n</body>\n';
    		out+=fmt.format([(id==cms.viewerID?'tiddler viewer':''),snapElem.innerHTML]);

    		return '<html>\n'+out+'</html>';
    	},
    	printsnap: function(out) {
    		var win=window.open("","_blank","");
    		win.document.open();
    		win.document.writeln(out);
    		win.document.close();
    		win.focus(); // bring to front
    		win.print(); // trigger print dialog
    	},
    	savesnap: function(out) {
    		var cms=config.macros.snapshot; // abbreviation
    		// make sure we are local
    		if (window.location.protocol!="file:")
    			{ alert(config.messages.notFileUrlError); return; }
    		var target=cms.askForFilename(cms.fileMsg,cms.getpath(),cms.defaultFilename);
    		if (!target) return; // cancelled by user
    		// if specified file does not include a path, assemble fully qualified path and filename
    		var slashpos=target.lastIndexOf("/");
    		if (slashpos==-1) slashpos=target.lastIndexOf("\\");
    		if (slashpos==-1) target=target+cms.defaultFilename;
    		var link="file:///"+target.replace(/\\/g,'/'); // link for message text
    		var ok=saveFile(target,convertUnicodeToUTF8(out));
    		var msg=ok?cms.okmsg.format([target]):cms.failmsg.format([target]);
    		clearMessage(); displayMessage(msg,link);
    	},
    	askForFilename: function(msg,path,file) {
    		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 { // XP/Vista 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) { var result=prompt(msg,path+file); } // fallback for non-XP IE
    		}
    		return result;
    	}
    };
    //}}}

    // // TOOLBAR DEFINITIONS
    //{{{
    config.commands.snapshotSave = {
    	text: "snap",
    	tooltip: config.macros.snapshot.snapPrompt,
    	handler: function(ev,src,title) {
    		src.setAttribute("snapID","ask");
    		src.setAttribute("printing","false");
    		src.setAttribute("HTMLOnly",config.options.chkSnapshotHTMLOnly?"true":"false");
    		config.macros.snapshot.go(src,ev);
    		return false;
    	}
    };
    config.commands.snapshotPrint = {
    	text: "print",
    	tooltip: config.macros.snapshot.printPrompt,
    	handler: function(ev,src,title) {
    		src.setAttribute("snapID","ask");
    		src.setAttribute("printing","true");
    		src.setAttribute("HTMLOnly",config.options.chkSnapshotHTMLOnly?"true":"false");
    		config.macros.snapshot.go(src,ev);
    		return false;
    	}
    };
    //}}}

    // // COPIED FROM [[StickyPopupPlugin]] TO ELIMINATE PLUGIN DEPENDENCY
    //{{{
    if (config.options.chkStickyPopups==undefined) config.options.chkStickyPopups=false;
    Popup.stickyPopup_onDocumentClick = function(ev)
    {
    	// if click is in a sticky popup, ignore it so popup will remain visible
    	var e = ev ? ev : window.event; var target = resolveTarget(e);
    	var p=target; while (p) {
    		if (hasClass(p,"popup") && (hasClass(p,"sticky")||config.options.chkStickyPopups)) break;
    		else p=p.parentNode;
    	}
    	if (!p) // not in sticky popup (or sticky popups disabled)... use normal click handling
    		Popup.onDocumentClick(ev);
    	return true;
    };
    try{removeEvent(document,"click",Popup.onDocumentClick);}catch(e){};
    try{addEvent(document,"click",Popup.stickyPopup_onDocumentClick);}catch(e){};
    //}}}

    {{center{
    {{floatleft{<<tiddler ToggleLeftSidebar>>}}}{{floatright{<<tiddler ToggleRightSidebar>>}}}/%
    %/ &nbsp; <<tag 日志 日志>><script>place.lastChild.className='tiddlyLinkExisting';</script>/%
    %/ &nbsp; <<tag bookmark 书签>><script>place.lastChild.className='tiddlyLinkExisting';</script>/%
    %/ &nbsp; <<tiddler ShowPopup with:
    	[[StoryMenu##changes]] "改动" "显示最近的改动" tiddlyLinkExisting 60em sticky>>/%
    %/ &nbsp; <<tiddler ShowPopup with:
    	[[StoryMenu##calendar]] "日历" "显示日历" tiddlyLinkExisting auto sticky>>/%
    %/ &nbsp; {{span{<script>
    	place.style.display==readOnly?'none':'inline';
    </script><<tiddler ShowPopup with:
    	[[DocumentSetup]] "setup" "configuration and setup" tiddlyLinkExisting auto>>/%
    %/}}}
    {{smallform{<<unsavedChanges panel>>}}}/%
    %/}}}/%
    !info
    [[about|AboutThisBlog]]
    [[contact|ContactTheAuthor]]
    [[credits|Credits]]
    !end
    !changes
    {{smallform{<<recentChanges 30>>}}}
    !end
    !calendar
    <<calendar thismonth>>
    !end
    %/

    /***
    |Name|StorySaverPlugin|
    |Source|http://www.TiddlyTools.com/#StorySaverPlugin|
    |Documentation|http://www.TiddlyTools.com/#StorySaverPluginInfo|
    |Version|1.7.1|
    |Author|Eric Shulman|
    |License|http://www.TiddlyTools.com/#LegalStatements|
    |~CoreVersion|2.1|
    |Type|plugin|
    |Requires|MarkupPostBody|
    |Overrides|confirmExit(), getParameters()|
    |Description|save/restore current tiddler view between browser sessions|
    Automatically save a list of currently viewed tiddlers (the 'story') in a local cookie, {{{txtSavedStory}}} and then open those tiddlers when the document is reloaded, so you can resume working from the same place you left off!!  Also, use {{{<<saveStory>>}}} and {{{<<openStory>>}}} macros to quickly save/re-display stories stored in tiddlers, using a command link, droplist, or popup display.
    !!!!!Documentation
    >see [[StorySaverPluginInfo]]
    !!!!!Configuration
    <<<
    <<option chkStoryAllowAdd>>include 'add a story' command in droplist/popup
    <<option chkStoryFold>>fold story tiddlers when opening a story (see [[CollapseTiddlersPlugin]])
    <<option chkStoryClose>>close other tiddlers when opening a story
    <<option chkStoryTop>>open story tiddlers at top of column
    <<option chkStoryBottom>>open story tiddlers at bottom of column
    <<<
    !!!!!Revisions
    <<<
    2009.07.27 [1.7.1] corrected test for {{{chkStoryAllowAdd}}} when rendering //list// output
    2009.07.27 [1.7.0] added options: {{{chkStoryAllowAdd=true}}}, {{{chkStoryTop=true}}}, and {{{chkStoryBottom=false}}}.  Also, autoscroll to first tiddler in story
    |please see [[StorySaverPluginInfo]] for additional revision details|
    2007.10.05 [1.0.0] initial release. Moved [[SetDefaultTiddlers]] inline script and rewrote as a {{{<<saveStory>>}}} macro.
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.StorySaverPlugin= {major: 1, minor: 7, revision: 1, date: new Date(2009,7,27)};
    //}}}
    // // ''save or clear story cookie on exit:''
    //{{{
    // if removeCookie() function is not defined by TW core, define it here.
    if (window.removeCookie===undefined) {
    	window.removeCookie=function(name) {
    		document.cookie = name+'=; expires=Thu, 01-Jan-1970 00:00:01 UTC; path=/;';
    	}
    }

    if (config.options.chkSaveStory==undefined) config.options.chkSaveStory=false;
    if (window.coreTweaks_confirmExit==undefined) {
    	window.coreTweaks_confirmExit=window.confirmExit;
    	window.confirmExit=function() {
    		if (config.options.chkSaveStory) { // save cookie
    			var links=[];
    			story.forEachTiddler(function(title,element){links.push('[['+title+']]');});
    			config.options.txtSavedStory=links.join(' ');
    			saveOptionCookie('txtSavedStory');
    		} else removeCookie('txtSavedStory');
    		return window.coreTweaks_confirmExit.apply(this,arguments);
    	}
    }
    //}}}
    /***
    ''apply saved story on startup:'' //important note: the following code is actually located in [[MarkupPostBody]].  This is because it needs to supercede the core's getParameters() function, which is called BEFORE plugins are loaded, preventing the normal plugin-based hijack method from working, while code loaded into [[MarkupPostBody]] will be processed as soon as the document is read, even before the TW main() function is invoked.//
    <<tiddler MarkupPostBody>>
    ***/
    // // MACRO definitions
    //{{{
    config.macros.saveStory = {
    	label: 'set default tiddlers',
    	defaultTiddler: 'DefaultTiddlers',
    	prompt: 'store a list of currently displayed tiddlers in another tiddler',
    	askMsg: 'Enter the name of a tiddler in which to save the current story:',
    	tag: 'story',
    	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    		var tid=params.shift()||'DefaultTiddlers';
    		var label=params.shift()||this.label;
    		var tip=params.shift()||this.prompt;
    		var btn=createTiddlyButton(place,label,tip,this.setTiddler,'button');
    		btn.setAttribute('tid',tid);
    		btn.setAttribute('extratags','[['+params.join(']] [[')+']]');
    	},
    	setTiddler: function() {
    		var cms=config.macros.saveStory; // abbrev
    		// get list of current open tiddlers
    		var tids=[];
    		story.forEachTiddler(function(title,element){tids.push('[['+title+']]')});
    		// get target tiddler
    		var tid=this.getAttribute('tid');
    		if (!tid || tid=='ask') {
    			tid=prompt(cms.askMsg,cms.defaultTiddler);
    			if (!tid || !tid.length) return; // cancelled by user
    		}
    		if(store.tiddlerExists(tid) && !confirm(config.messages.overwriteWarning.format([tid]))) return;
    		tids=tids.join('\n'); // separate tiddler links by newlines for easier reading
    		var t=store.getTiddler(tid); var tags=t?t.tags:[];
    		var extratags=this.getAttribute('extratags').readBracketedList();
    		for (var i=0; i<extratags.length; i++) tags.pushUnique(extratags[i]);
    		tags.pushUnique(cms.tag);
    		store.saveTiddler(tid,tid,tids,config.options.txtUserName,new Date(),tags,t?t.fields:null);
    		story.displayTiddler(null,tid);
    		story.refreshTiddler(tid,null,true);
    		displayMessage(tid+' has been '+(t?'updated':'created'));
    	}
    }
    //}}}

    //{{{
    if (config.options.chkStoryFold==undefined) config.options.chkStoryFold=true;
    if (config.options.chkStoryClose==undefined) config.options.chkStoryClose=true;
    if (config.options.chkStoryAllowAdd==undefined) config.options.chkStoryAllowAdd=true;
    if (config.options.chkStoryTop==undefined) config.options.chkStoryTop=true;
    if (config.options.chkStoryBottom==undefined) config.options.chkStoryBottom=false;

    config.macros.openStory = {
    	label: 'open story: %0',
    	prompt: 'open the set of tiddlers listed in: %0',
    	popuplabel: 'stories',
    	popupprompt: 'view a set of tiddlers',
    	tag: 'story',
    	selectprompt: 'select a story...',
    	optionsprompt: 'viewing options...',
    	foldcmd: '[%0] fold story',
    	foldprompt: 'fold story tiddlers when opening a story',
    	closecmd: '[%0] close others',
    	closeprompt: 'close other tiddlers when opening a story',
    	topcmd: '[%0] open at top',
    	topprompt: 'open story tiddlers at top of column',
    	bottomcmd: '[%0] open at bottom',
    	bottomprompt: 'open story tiddlers at bottom of column',
    	addcmd: 'add a story...',
    	addprompt: 'create a new story',
    	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    		if (params[0].toLowerCase()=='list') return this.createList(place,params);
    		else if (params[0].toLowerCase()=='popup') return this.createPopup(place,params);
    		else this.createButton(place,params);
    	},
    	showStory: function(tid,fold) {
    		var co=config.options; // abbrev
    		var tids=[];
    		var tagged=store.getTaggedTiddlers(tid,'title');
    		if (tagged.length) // if tiddler IS a tag, use tagged tiddlers as story
    			for (var t=0; t<tagged.length; t++) tids.push(tagged[t].title);
    		else { // get tiddler list from content
    			var t=store.getTiddler(tid);
    			if (t) { if (!t.linksUpdated) t.changed(); tids=t.links.slice(0); }
    		}
    		var template=null;
    		if (fold||co.chkStoryFold) template='CollapsedTemplate'; // see [[CollapseTiddlersPlugin]]
    		if (!store.tiddlerExists('CollapsedTemplate')) template=null;
    		if (co.chkStoryClose) story.closeAllTiddlers();
    		var pos='top'; var first=tids[0];
    		if (!story.isEmpty() && co.chkStoryBottom) { pos='bottom'; tids=tids.reverse(); }
    		story.displayTiddlers(pos,tids,template);
    		var cmd='var t=story.getTiddler("'+first+'");if(t)window.scrollTo(0,t.offsetTop);';
    		var delay=config.options.chkAnimate?config.animDuration+100:0;
    		setTimeout(cmd,delay);
    	},
    	createButton: function(place,params) {
    		var tid=params[0]||'';
    		var label=params[1]||this.label; label=label.format([tid]);
    		var tip=params[2]||this.prompt; tip=tip.format([tid]);
    		var fold=(params[3]&&(params[3].toLowerCase()=='fold'))||config.options.chkStoryFold;
    		var fn=function(){config.macros.openStory.showStory(this.getAttribute('tid'),this.getAttribute('fold'))};
    		var btn=createTiddlyButton(place,label,tip,fn,'button');
    		btn.setAttribute('tid',tid);
    		if (fold) btn.setAttribute('fold',fold);
    	},
    	createPopup: function(place,params) {
    		params.shift(); // discard 'popup' keyword
    		var label=params.shift()||this.popuplabel;
    		var tip=params.shift()||this.popupprompt;
    		var btn=createTiddlyButton(place,label,tip,this.showPopup,'button');
    		btn.setAttribute('filter',params.shift()||config.macros.openStory.tag);
    	},
    	showPopup: function(ev) { var e=ev||window.event;
    		var co=config.options; // abbrev
    		var cmo=config.macros.openStory; // abbrev
    		var indent='\xa0\xa0';
    		var p=Popup.create(this); if (!p) return false;
    		createTiddlyText(createTiddlyElement(p,'li'),cmo.selectprompt);
    		var stories=store.filterTiddlers('[tag['+this.getAttribute('filter')+']]');
    		for (var s=0; s<stories.length; s++) {
    			var label=indent+stories[s].title;
    			var tip=cmo.prompt.format([stories[s].title]);
    			var fn=function(){cmo.showStory(this.getAttribute('tid'))};
    			var btn=createTiddlyButton(createTiddlyElement(p,'li'),label,tip,fn,'button');
    			btn.setAttribute('tid',stories[s].title);
    		}
    		createTiddlyText(createTiddlyElement(p,'li'),cmo.optionsprompt);
    		if (store.tiddlerExists('CollapsedTemplate')) {
    			var label=indent+cmo.foldcmd.format([co.chkStoryFold?'x':'\xa0\xa0']);
    			var tip=cmo.foldprompt;
    			var fn=function(){ config.macros.option.propagateOption(
    				'chkStoryFold','checked',!config.options.chkStoryFold,'input'); };
    			var btn=createTiddlyButton(createTiddlyElement(p,'li'),label,tip,fn,'button');
    		}
    		var label=indent+cmo.closecmd.format([co.chkStoryClose?'x':'\xa0\xa0']);
    		var tip=indent+cmo.closeprompt;
    		var fn=function(){ config.macros.option.propagateOption(
    			'chkStoryClose','checked',!config.options.chkStoryClose,'input'); };
    		var btn=createTiddlyButton(createTiddlyElement(p,'li'),label,tip,fn,'button');
    		if (!co.chkStoryClose) {
    			var label=indent+cmo.topcmd.format([co.chkStoryTop?'x':'\xa0\xa0']);
    			var tip=indent+cmo.topprompt;
    			var fn=function(){
    				config.macros.option.propagateOption(
    					'chkStoryTop','checked',!config.options.chkStoryTop,'input');
    				config.macros.option.propagateOption(
    					'chkStoryBottom','checked',!config.options.chkStoryTop,'input');
    			};
    			var btn=createTiddlyButton(createTiddlyElement(p,'li'),label,tip,fn,'button');
    			var label=indent+cmo.bottomcmd.format([co.chkStoryBottom?'x':'\xa0\xa0']);
    			var tip=indent+cmo.botprompt;
    			var fn=function(){
    				config.macros.option.propagateOption(
    					'chkStoryBottom','checked',!config.options.chkStoryBottom,'input');
    				config.macros.option.propagateOption(
    					'chkStoryTop','checked',!config.options.chkStoryBottom,'input');
    			};
    			var btn=createTiddlyButton(createTiddlyElement(p,'li'),label,tip,fn,'button');
    		}
    		if (!readOnly && co.chkStoryAllowAdd) {
    			var label=cmo.addcmd;
    			var tip=cmo.addprompt;
    			var fn=config.macros.saveStory.setTiddler;
    			createTiddlyElement(createTiddlyElement(p,'li'),'hr');
    			var btn=createTiddlyButton(createTiddlyElement(p,'li'),label,tip,fn,'button');
    		}
    		Popup.show();
    		e.cancelBubble=true;if(e.stopPropagation)e.stopPropagation();
    		return false;
    	},
    	createList: function(place,params) {
    		var cmo=config.macros.openStory; // abbrev
    		var s=createTiddlyElement(place,'select',null,'storyListbox');
    		s.size=1;
    		s.onchange=function() {
    			if (this.value=='_fold') {
    				config.macros.option.propagateOption('chkStoryFold','checked',
    					!config.options.chkStoryFold,'input');
    				cmo.refreshList();
    			} else if (this.value=='_close') {
    				config.macros.option.propagateOption('chkStoryClose','checked',
    					!config.options.chkStoryClose,'input');
    				cmo.refreshList();
    			} else if (this.value=='_top') {
    				config.macros.option.propagateOption('chkStoryTop','checked',
    					!config.options.chkStoryTop,'input');
    				cmo.refreshList();
    			} else if (this.value=='_bottom') {
    				config.macros.option.propagateOption('chkStoryBottom','checked',
    					!config.options.chkStoryBottom,'input');
    				cmo.refreshList();
    			} else if (this.value=='_add')
    				config.macros.saveStory.setTiddler.apply(this,arguments);
    			else cmo.showStory(this.value);
    		}
    		params.shift(); // discard 'list' keyword
    		s.setAttribute('filter',params.shift()||cmo.tag);
    		setStylesheet('.storyListbox { width:100%; }', 'StorySaverStyles');
    		store.addNotification(null,this.refreshList); this.refreshList();
    		return;
    	},
    	refreshList: function() {
    		var cmo=config.macros.openStory; // abbrev
    		var indent='\xa0\xa0\xa0\xa0';
    		var lists=document.getElementsByTagName('select');
    		for (var i=0; i<lists.length; i++) { if (lists[i].className!='storyListbox') continue;
    			var here=lists[i];
    			var stories=store.filterTiddlers('[tag['+here.getAttribute('filter')+']]');
    			while (here.length) here.options[0]=null; // remove current list items
    			here.options[here.length]=new Option(cmo.selectprompt,'',true,true);
    			for (var s=0; s<stories.length; s++)
    				here.options[here.length]=new Option(indent+stories[s].title,stories[s].title);
    			if (!readOnly && config.options.chkStoryAllowAdd)
    				here.options[here.length]=new Option(cmo.addcmd,'_add');
    			here.options[here.length]=new Option(cmo.optionsprompt,'');
    			if (store.tiddlerExists('CollapsedTemplate')) {
    				var msg=cmo.foldcmd.format([config.options.chkStoryFold?'x':'\xa0\xa0']);
    				here.options[here.length]=new Option(indent+msg,'_fold');
    			}
    			var msg=cmo.closecmd.format([config.options.chkStoryClose?'x':'\xa0\xa0']);
    			here.options[here.length]=new Option(indent+msg,'_close',false,false);
    			if (!config.options.chkStoryClose) {
    				var msg=cmo.topcmd.format([config.options.chkStoryTop?'x':'\xa0\xa0']);
    				here.options[here.length]=new Option(indent+msg,'_top',false,false);
    				var msg=cmo.bottomcmd.format([config.options.chkStoryBottom?'x':'\xa0\xa0']);
    				here.options[here.length]=new Option(indent+msg,'_bottom',false,false);
    			}
    		}
    	}
    }
    //}}}

    /*{{{*/
    /* SHORTCUTS */
    [[StyleSheetShortcuts]]

    /* ADJUSTMENTS TO SHORTCUTS */
    .small	{ font-size:90%; line-height:120%; }
    .fine	{ font-size:80%; line-height:120%; }
    .tiny	{ font-size:70%; line-height:120%; }
    .groupbox { padding:.5em; border:1px solid gray; -moz-border-radius:.5em; -webkit-border-radius:.5em; }

    /* CUSTOM SHORTCUTS */
    .scroll		{ display:block; overflow:auto; width:auto; max-height:8em; padding-bottom:.5em; }
    .scroll ul	{ margin:0; }
    .scroll li	{ white-space:nowrap; }
    *[id="mainMenu"] .scroll li  /* MOZ ONLY */	{ margin-left:-2.5em; }

    /* ADJUSTMENTS TO STANDARD ELEMENTS */
    [[StyleSheetAdjustments]]

    /* ADJUSTMENTS TO CUSTOM ELEMENTS */
    .storyListbox	{ font-size:80%; }
    .siteNav	{ position:absolute;z-index:1;right:.5em;top:2em;width:14em; }
    .siteNav, .siteNav .button	{ color:#fff }
    .siteNav .button:hover	{ color:#009 }
    .siteNav input[type="checkbox"]	{ margin:0; }
    .calendar td { background-color:#eee; }
    .calendar td:hover { background-color:#fff !important; }

    /* BACKGROUND COLORS/TEXTURES */
    [[StyleSheetWuShuang]] /* [[OFF_StyleSheetStone]] */

    /*}}}*/

    /*{{{*/
    /* ADJUSTMENTS TO STANDARD ELEMENTS */
    .headerShadow, .headerForeground
    	{ padding-top:1em; white-space:nowrap; }
    #mainMenu
    	{ text-align:left; width:14em; padding:0.5em; }
    #mainMenu table, #mainMenu table td
    	{ border:1px solid #999; border-collapse:collapse; padding:.3em; }
    #displayArea
    	{ margin-left:16em; margin-right:15em; }
    .popup
    	{ max-height:40em; overflow:auto; -moz-border-radius:.5em; -webkit-border-radius:.5em; padding:.5em; }
    .popup li
    	{ white-space:nowrap; line-height:100%; }
    .toolbar
    	{ float:right; white-space:nowrap; }
    .viewer
    	{ border:1px solid gray; -moz-border-radius:.5em; -webkit-border-radius:.5em; padding:.5em; }
    .tiddler .subtitle
    	{ display:none; }
    .tagged
    	{ border:1px solid #999; -moz-border-radius:3px; -webkit-border-radius:3px; }
    .tagged
    	{ opacity:.7; }
    .selected .tagged
    	{ opacity:1; }
    .button, .tiddler .button
    	{ margin:0px; padding: 0px .3em; border:1px solid transparent; -moz-border-radius:3px; -webkit-border-radius:3px; }
    .button:hover
    	{ border:1px solid #999; }
    .editor textarea
    	{ font-family:monospace; }
    /*}}}*/

    /***
    |Name|StyleSheetShortcuts|
    |Source|http://www.TiddlyTools.com/#StyleSheetShortcuts|
    |Version||
    |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|CSS|
    |Requires||
    |Overrides||
    |Description|'convenience' classes for common formatting, alignment, boxes, tables, etc.|

    These 'style tweaks' can be easily included in other stylesheet tiddler so they can share a baseline look-and-feel that can then be customized to create a wide variety of 'flavors'.
    ***/
    /*{{{*/

    /* text alignments */
    .left
    	{ display:block;text-align:left; }
    .center
    	{ display:block;text-align:center; }
    .center table
    	{ margin:auto !important; }
    .right
    	{ display:block;text-align:right; }
    .justify
    	{ display:block;text-align:justify; }
    .indent
    	{ display:block;margin:0;padding:0;border:0;margin-left:2em; }
    .floatleft
    	{ float:left; }
    .floatright
    	{ float:right; }
    .valignTop, .valignTop table, .valignTop tbody, .valignTop th, .valignTop tr, .valignTop td
    	{ vertical-align:top; }
    .valignBottom, .valignBottom table, .valignBottom tbody, .valignBottom th, .valignBottom tr, .valignBottom td
    	{ vertical-align:bottom; }
    .clear
    	{ clear:both; }
    .wrap
    	{ white-space:normal; }
    .nowrap
    	{ white-space:nowrap; }
    .hidden
    	{ display:none; }
    .show
    	{ display:inline !important; }
    .span
    	{ display:span; }
    .block
    	{ display:block; }
    .relative
    	{ position:relative; }
    .absolute
    	{ position:absolute; }

    /* font sizes */
    .big
    	{ font-size:14pt;line-height:120% }
    .medium
    	{ font-size:12pt;line-height:120% }
    .normal
    	{ font-size:9pt;line-height:120% }
    .small
    	{ font-size:8pt;line-height:120% }
    .fine
    	{ font-size:7pt;line-height:120% }
    .tiny
    	{ font-size:6pt;line-height:120% }
    .larger
    	{ font-size:120%; }
    .smaller
    	{ font-size:80%; }

    /* font styles */
    .bold
    	{ font-weight:bold; }
    .italic
    	{ font-style:italic; }
    .underline
    	{ text-decoration:underline; }

    /* plain list items (no bullets or indent) */
    .nobullets li { list-style-type: none; margin-left:-2em; }

    /* multi-column tiddler content (not supported in Internet Explorer) */
    .twocolumns { display:block;
    	-moz-column-count:2; -moz-column-gap:1em; -moz-column-width:50%; /* FireFox */
    	-webkit-column-count:2; -webkit-column-gap:1em; -webkit-column-width:50%; /* Safari */
    	column-count:2; column-gap:1em; column-width:50%; /* Opera */
    }
    .threecolumns { display:block;
    	-moz-column-count:3; -moz-column-gap:1em; -moz-column-width:33%; /* FireFox */
    	-webkit-column-count:3; -webkit-column-gap:1em; -webkit-column-width:33%; /* Safari */
    	column-count:3; column-gap:1em; column-width:33%; /* Opera */
    }
    .fourcolumns { display:block;
    	-moz-column-count:4; -moz-column-gap:1em; -moz-column-width:25%; /* FireFox */
    	-webkit-column-count:4; -webkit-column-gap:1em; -webkit-column-width:25%; /* Safari */
    	column-count:4; column-gap:1em; column-width:25%; /* Opera */
    }

    /* show/hide browser-specific content for InternetExplorer vs. non-IE ("moz") browsers */
    *[class="ieOnly"]
    	{ display:none; } /* hide in moz (uses CSS selector) */
    * html .mozOnly, *:first-child+html .mozOnly
    	{ display: none; } /* hide in IE (uses IE6/IE7 CSS hacks) */

    /* borderless tables */
    .borderless, .borderless table, .borderless td, .borderless tr, .borderless th, .borderless tbody
    	{ border:0 !important; margin:0 !important; padding:0 !important; }
    .widetable, .widetable table
    	{ width:100%; }

    /* thumbnail images (fixed-sized scaled images) */
    .thumbnail img { height:5em !important; }

    /* stretchable images (auto-size to fit tiddler) */
    .stretch img { width:95%; }

    /* grouped content */
    .outline
    	{ display:block; padding:1em; -moz-border-radius:1em;-webkit-border-radius:1em; border:1px solid; }
    .menubox
    	{ display:block; padding:1em; -moz-border-radius:1em;-webkit-border-radius:1em; border:1px solid; background:#fff; color:#000; }
    .menubox .button, .menubox .tiddlyLinkExisting, .menubox .tiddlyLinkNonExisting
    	{ color:#009 !important; }
    .groupbox
    	{ display:block; padding:1em; -moz-border-radius:1em;-webkit-border-radius:1em; border:1px solid; background:#ffe; color:#000; }
    .groupbox a, .groupbox .button, .groupbox .tiddlyLinkExisting, .groupbox .tiddlyLinkNonExisting
    	{ color:#009 !important; }
    .groupbox code
    	{ color:#333 !important; }
    .borderleft
    	{ margin:0;padding:0;border:0;margin-left:1em; border-left:1px dotted; padding-left:.5em; }
    .borderright
    	{ margin:0;padding:0;border:0;margin-right:1em; border-right:1px dotted; padding-right:.5em; }
    .borderbottom
    	{ margin:0;padding:1px 0;border:0;border-bottom:1px dotted; margin-bottom:1px; padding-bottom:1px; }
    .bordertop
    	{ margin:0;padding:0;border:0;border-top:1px dotted; margin-top:1px; padding-top:1px; }

    /* scrolled content */
    .scrollbars { overflow:auto; }
    .height10em { height:10em; }
    .height15em { height:15em; }
    .height20em { height:20em; }
    .height25em { height:25em; }
    .height30em { height:30em; }
    .height35em { height:35em; }
    .height40em { height:40em; }

    /* compact form */
    .smallform
    	{ white-space:nowrap; }
    .smallform input, .smallform textarea, .smallform button, .smallform checkbox, .smallform radio, .smallform select
    	{ font-size:8pt; }

    /* stretchable edit fields and textareas (auto-size to fit tiddler) */
    .stretch input { width:99%; }
    .stretch textarea { width:99%; }

    /* compact input fields (limited to a few characters for entering percentages and other small values) */
    .onechar input   { width:1em; }
    .twochar input   { width:2em; }
    .threechar input { width:3em; }
    .fourchar input  { width:4em; }
    .fivechar input  { width:5em; }

    /* text colors */
    .white { color:#fff !important }
    .gray  { color:#999 !important }
    .black { color:#000 !important }
    .red   { color:#f66 !important }
    .green { color:#0c0 !important }
    .blue  { color:#99f !important }

    /* rollover highlighting */
    .mouseover
    	{color:[[ColorPalette::TertiaryLight]] !important;}
    .mouseover a
    	{color:[[ColorPalette::TertiaryLight]] !important;}
    .selected .mouseover
    	{color:[[ColorPalette::Foreground]] !important;}
    .selected .mouseover .button, .selected .mouseover a
    	{color:[[ColorPalette::PrimaryDark]] !important;}

    /* rollover zoom text */
    .zoomover
    	{ font-size:80% !important; }
    .selected .zoomover
    	{ font-size:100% !important; }

    /* [[ColorPalette]] text colors */
    .Background	{ color:[[ColorPalette::Background]];	 }
    .Foreground	{ color:[[ColorPalette::Foreground]];	 }
    .PrimaryPale	{ color:[[ColorPalette::PrimaryPale]];	 }
    .PrimaryLight	{ color:[[ColorPalette::PrimaryLight]];	 }
    .PrimaryMid	{ color:[[ColorPalette::PrimaryMid]];	 }
    .PrimaryDark	{ color:[[ColorPalette::PrimaryDark]];	 }
    .SecondaryPale	{ color:[[ColorPalette::SecondaryPale]]; }
    .SecondaryLight	{ color:[[ColorPalette::SecondaryLight]];}
    .SecondaryMid	{ color:[[ColorPalette::SecondaryMid]];	 }
    .SecondaryDark	{ color:[[ColorPalette::SecondaryDark]]; }
    .TertiaryPale	{ color:[[ColorPalette::TertiaryPale]];	 }
    .TertiaryLight	{ color:[[ColorPalette::TertiaryLight]]; }
    .TertiaryMid	{ color:[[ColorPalette::TertiaryMid]];	 }
    .TertiaryDark	{ color:[[ColorPalette::TertiaryDark]];	 }
    .Error		{ color:[[ColorPalette::Error]];	 }

    /* [[ColorPalette]] background colors */
    .BGBackground	  { background-color:[[ColorPalette::Background]];	}
    .BGForeground	  { background-color:[[ColorPalette::Foreground]];	}
    .BGPrimaryPale	  { background-color:[[ColorPalette::PrimaryPale]];	}
    .BGPrimaryLight	  { background-color:[[ColorPalette::PrimaryLight]];	}
    .BGPrimaryMid	  { background-color:[[ColorPalette::PrimaryMid]];	}
    .BGPrimaryDark	  { background-color:[[ColorPalette::PrimaryDark]];	}
    .BGSecondaryPale  { background-color:[[ColorPalette::SecondaryPale]]; 	}
    .BGSecondaryLight { background-color:[[ColorPalette::SecondaryLight]];	}
    .BGSecondaryMid	  { background-color:[[ColorPalette::SecondaryMid]];	}
    .BGSecondaryDark  { background-color:[[ColorPalette::SecondaryDark]]; 	}
    .BGTertiaryPale	  { background-color:[[ColorPalette::TertiaryPale]];	}
    .BGTertiaryLight  { background-color:[[ColorPalette::TertiaryLight]]; 	}
    .BGTertiaryMid	  { background-color:[[ColorPalette::TertiaryMid]];	}
    .BGTertiaryDark	  { background-color:[[ColorPalette::TertiaryDark]];	}
    .BGError	  { background-color:[[ColorPalette::Error]];	 	}
    /*}}}*/

    /*{{{*/
    /* BACKGROUND TEXTURES */
    .header
    	{ background-image: url('http://gamediy.net/data/web/bg/145.png'); background-color:#f8f8f8; }
    .headerForeground a
    	{ color:#edb; }
    body
    	{ background-image: url('http://gamediy.net/data/web/bg/1057.png'); background-color:#f8f8f8; }
    .viewer
    	{ background-image: url('http://gamediy.net/data/web/bg/129.png'); background-color:#ffe; }
    .viewer pre
    	{ border:1px solid; background-color:#ffe; }
    .groupbox
    	{ background-image: url('http://gamediy.net/data/web/bg/881.png'); background-color:#fff; }
    .siteNav, .siteNav .button
    	{ color:#fff }
    .siteNav .button:hover
    	{ color:#009 }
    .toolbar {color:[[ColorPalette::TertiaryMid]];}
    .toolbar a {color:[[ColorPalette::TertiaryMid]];}
    .selected .toolbar a {color:[[ColorPalette::Foreground]];}
    .selected .toolbar a:hover {color:[[ColorPalette::PrimaryDark]];}

    .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]]; background-image: url('http://gamediy.net/data/web/bg/129.png');}
    .tabContents .button {border:0;}

    /*}}}*/

    /***
    |Name|TabEditPlugin|
    |Created by|SaqImtiaz|
    |Location|http://tw.lewcid.org/#TabEditPlugin|
    |Version|0.32|
    |Requires|~TW2.x|

    !Description
    Makes editing of tabs easier.

    !Usage
    *Double click a tab to edit the source tiddler
    *Double click outside the tabset to edit the containing tiddler.

    !Demo
    TestTabs

    !History
    *28-04-06, v0.32 - fixed previous bug fix!
    *27-04-06, v0.31 - fixed conflicts with tabs created using PartTiddler.
    *26-04-06, v0.30 - first public release

    ***/

    //{{{

    //tab on double click event handler
    Story.prototype.onTabDblClick = function(e){
            if (!e) var e = window.event;
            var theTarget = resolveTarget(e);
            var title= this.getAttribute("source");
            if ((version.extensions.PartTiddlerPlugin)&&(title.indexOf("/")!=-1))
                     {if (!oldFetchTiddler.call(this, [title]))
                                  {return false;}}
            story.displayTiddler(theTarget,title,2,false,null)
            e.cancelBubble = true;
            if (e.stopPropagation) e.stopPropagation();
            return false;
            }

    config.macros.tabs.switchTab = function(tabset,tab)
    {
    	var cookie = tabset.getAttribute("cookie");
    	var theTab = null
    	var nodes = tabset.childNodes;
    	for(var t=0; t<nodes.length; t++)
    		if(nodes[t].getAttribute && nodes[t].getAttribute("tab") == tab)
    			{
    			theTab = nodes[t];
    			theTab.className = "tab tabSelected";
    			}
    		else
    			nodes[t].className = "tab tabUnselected"
    	if(theTab)
    		{
    		if(tabset.nextSibling && tabset.nextSibling.className == "tabContents")
    			tabset.parentNode.removeChild(tabset.nextSibling);
    		var tabContent = createTiddlyElement(null,"div",null,"tabContents",null);
    		tabset.parentNode.insertBefore(tabContent,tabset.nextSibling);
    		var contentTitle = theTab.getAttribute("content");

                    //set source attribute equal to title of tiddler displayed in tab
    		tabContent.setAttribute("source",contentTitle);
    		//add dbl click event
    		tabContent.ondblclick = story.onTabDblClick;

    		wikify(store.getTiddlerText(contentTitle),tabContent,null,store.getTiddler(contentTitle));
    		if(cookie)
    			{
    			config.options[cookie] = tab;
    			saveOptionCookie(cookie);
    			}
    		}
    }

    //}}}

    /***
    |Name|TaggedTemplateTweak|
    |Source|http://www.TiddlyTools.com/#TaggedTemplateTweak|
    |Documentation|http://www.TiddlyTools.com/#TaggedTemplateTweakInfo|
    |Version|1.6.0|
    |Author|Eric Shulman|
    |License|http://www.TiddlyTools.com/#LegalStatements|
    |~CoreVersion|2.1|
    |Type|plugin|
    |Requires||
    |Overrides|Story.prototype.chooseTemplateForTiddler()|
    |Description|use alternative ViewTemplate/EditTemplate for specific tiddlers|
    This plugin extends the core function, story.chooseTemplateForTiddler(), so that any given tiddler can be viewed and/or edited using alternatives to the standard tiddler templates.
    !!!!!Documentation
    >see [[TaggedTemplateTweakInfo]]
    !!!!!Revisions
    <<<
    2009.07.31 [1.6.0] added support for using custom field value as prefix
    | please see [[TaggedTemplateTweakInfo]] for previous revision details |
    2007.06.11 [1.0.0] initial release
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.TaggedTemplateTweak= {major: 1, minor: 6, revision: 0, date: new Date(2009,7,31)};

    if (!config.options.txtTemplateTweakFieldname)
    	config.options.txtTemplateTweakFieldname='template';

    Story.prototype.taggedTemplate_chooseTemplateForTiddler = Story.prototype.chooseTemplateForTiddler
    Story.prototype.chooseTemplateForTiddler = function(title,template)
    {
    	// get core template and split into theme and template name
    	var coreTemplate=this.taggedTemplate_chooseTemplateForTiddler.apply(this,arguments);
    	var theme=""; var template=coreTemplate;
    	var parts=template.split(config.textPrimitives.sectionSeparator);
    	if (parts[1]) { theme=parts[0]; template=parts[1]; }
    	else theme=config.options.txtTheme||""; // if theme is not specified
    	theme+=config.textPrimitives.sectionSeparator;

    	// look for template using title as prefix
    	if (!store.getTaggedTiddlers(title).length) { // if tiddler is not a tag
    		if (store.getTiddlerText(theme+title+template))
    			{ return theme+title+template; } // theme##TitleTemplate
    		if (store.getTiddlerText(title+template))
    			{ return title+template; }	 // TitleTemplate
    	}

    	// look for template using tags as prefix
    	var tiddler=store.getTiddler(title);
    	if (!tiddler) return coreTemplate; // tiddler doesn't exist... use core result
    	for (i=0; i<tiddler.tags.length; i++) {
    		var t=tiddler.tags[i]+template; // add tag prefix to template
    		var c=t.substr(0,1).toUpperCase()+t.substr(1); // capitalized for WikiWord title
    		if (store.getTiddlerText(theme+t))	{ return theme+t; } // theme##tagTemplate
    		if (store.getTiddlerText(theme+c))	{ return theme+c; } // theme##TagTemplate
    		if (store.getTiddlerText(t)) 		{ return t; }	    // tagTemplate
    		if (store.getTiddlerText(c))		{ return c; }	    // TagTemplate
    	}

    	// look for templates using custom field value as prefix
    	var v=store.getValue(title,config.options.txtTemplateTweakFieldname);
    	if (store.getTiddlerText(theme+v+template))
    		{ return theme+v+template; }	// theme##valueTemplate
    	if (store.getTiddlerText(v+template))
    		{ return v+template; }		// valueTemplate

    	// no match... use core result
    	return coreTemplate;
    }
    //}}}

    /***
    |Name|TextAreaPlugin|
    |Source|http://www.TiddlyTools.com/#TextAreaPlugin|
    |Documentation|http://www.TiddlyTools.com/#TextAreaPluginInfo|
    |Version|2.2.1|
    |Author|Eric Shulman|
    |License|http://www.TiddlyTools.com/#LegalStatements|
    |~CoreVersion|2.1|
    |Type|plugin|
    |Requires||
    |Overrides|Story.prototype.focusTiddler|
    |Options|##Configuration|
    |Description|Adds Find/Again keyboard search, autosize, and 'stretch bar' resize for textarea controls|
    !!!!!Documentation
    >see [[TextAreaPluginInfo]]
    !!!!!Configuration
    <<<
    <<option chkTextAreaExtensions>> use control-f (find), control-g (find again) inside text area
    <<option chkDisableAutoSelect>> place cursor at start of textarea instead of pre-selecting content
    <<option chkResizeEditor>> modify shadow EditTemplate to add resizeable text area (and autosize command)
    <<<
    !!!!!Revisions
    <<<
    2009.04.08 [2.2.1] added autosizeEditor macro to enable automatic autosizing without using toolbar command
    2009.04.06 [2.2.0] added resizeListbox macro definition and adjusted dragbar width calculation.
    |please see [[TextAreaPluginInfo]] for additional revision details|
    2006.01.22 [1.0.0] Moved from temporary "System Tweaks" tiddler into 'real' TextAreaPlugin tiddler.
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.TextAreaPlugin= {major: 2, minor: 2, revision: 1, date: new Date(2009,4,8)};

    if (config.options.chkTextAreaExtensions===undefined) config.options.chkTextAreaExtensions=true;
    if (config.options.chkDisableAutoSelect===undefined) config.options.chkDisableAutoSelect=true;
    if (config.options.chkResizeEditor===undefined) config.options.chkResizeEditor=true;

    // automatically tweak shadow EditTemplate to add "autosizeEditor" toolbar command
    if (config.options.chkResizeEditor)
    	config.shadowTiddlers.EditTemplate=config.shadowTiddlers.EditTemplate.replace(/deleteTiddler/,"deleteTiddler autosizeEditor");
    // automatically tweak shadow EditTemplate to add "resizeEditor" macro
    if (config.options.chkResizeEditor)
    	config.shadowTiddlers.EditTemplate+="<span macro='resizeEditor'></span>";

    // Put focus in a specified tiddler field
    Story.prototype.TextAreaExtensions_focusTiddler=Story.prototype.focusTiddler;
    Story.prototype.focusTiddler = function(title,field)
    {
    	this.TextAreaExtensions_focusTiddler.apply(this,arguments); // first call core
    	var e = this.getTiddlerField(title,field);
    	if (e && config.options.chkDisableAutoSelect) {
    		if (e.setSelectionRange) // FF
    			e.setSelectionRange(0,0);
    		else if (e.createTextRange) // IE
    			{ var r=e.createTextRange(); r.collapse(true); r.select(); }
    	}
    	if (e && config.options.chkTextAreaExtensions) addKeyDownHandlers(e);
    }
    //}}}

    //{{{
    function addKeyDownHandlers(e)
    {
    	// exit if not textarea or element doesn't allow selections
    	if (e.tagName.toLowerCase()!="textarea"||!e.setSelectionRange||e.initialized) return;

    	// utility function: exits keydown handler and prevents browser from processing the keystroke
    	var processed=function(ev) {
    		ev.cancelBubble=true; // IE4+
    		try{event.keyCode=0;}catch(e){}; // IE5
    		if (window.event) ev.returnValue=false; // IE6
    		if (ev.preventDefault) ev.preventDefault(); // moz/opera/konqueror
    		if (ev.stopPropagation) ev.stopPropagation(); // all
    		return false;
    	}
    	// capture keydown in edit field
    	e.saved_onkeydown=e.onkeydown; // save current keydown handler (if any)
    	e.onkeydown=function(ev) { if (!ev) var ev=window.event;
    		var key=ev.keyCode;
    		if (!key) {
    			var char=event.which?event.which:event.charCode;
    			if (char==102) key=70;
    			if (char==103) key=71;
    		}
    		// process CTRL-F (find matching text) or CTRL-G (find next match)
    		if (ev.ctrlKey && (key==70||key==71)) {

    			// prompt for text to find
    			var defFind=e.findText?e.findText:e.value.substring(e.selectionStart,e.selectionEnd);
    			if (key==70||!e.findText||!e.findText.length) // ctrl-f or no saved search text
    				{ var f=prompt("find:", defFind); e.focus(); if (f) e.findText=f; }
    			if (!e.findText||!e.findText.length) return processed(ev); //  if no search text, exit

    			// do case-insensitive match with 'wraparound'...  if not found, alert and exit
    			var newstart=e.value.toLowerCase().indexOf(e.findText.toLowerCase(),e.selectionStart+1);
    			if (newstart==-1) newstart=e.value.toLowerCase().indexOf(e.findText.toLowerCase());
    			if (newstart==-1) { alert("'"+e.findText+"' not found"); e.focus(); return processed(ev); }

    			// set new selection, scroll it into view, and report line position in status bar
    			e.setSelectionRange(newstart,newstart+e.findText.length);
    			var linecount=e.value.split('\n').length;
    			var thisline=e.value.substr(0,e.selectionStart).split('\n').length;
    			e.scrollTop=Math.floor((thisline-1-e.rows/2)*e.scrollHeight/linecount);
    			window.status="line: "+thisline+"/"+linecount;
    			return processed(ev);
    		}
    		if (e.saved_onkeydown) // call previous keydown handler (if any)
    			e.saved_onkeydown(ev);
    	}
    	e.initialized=true;
    }
    //}}}

    // // 'autosize' toolbar command
    //{{{
    config.commands.autosizeEditor = {
    	text: 'autosize',
    	tooltip: 'automatically adjust the editor height to fit the contents',
    	text_alt: '\u221Aautosize',
    	hideReadOnly: false,
    	handler: function(event,src,title) {
    		var here=story.findContainingTiddler(src); if (!here) return;
    		var ta=here.getElementsByTagName('textarea'); if (!ta) return;
    		for (i=0;i<ta.length;i++) {
    			// only autosize textareas actually used to edit tiddler fields
    			if (ta[i].getAttribute("edit")==undefined) continue;
    			ta[i].button=src;
    			if (!ta[i].maxed)
    				config.commands.autosizeEditor.on(ta[i]);
    			else
    				config.commands.autosizeEditor.off(ta[i],true);
    		}
    		return false;
    	},
    	on: function(e) {
    		if (e.maxed) return; // already autosizing!
    		if (e.savedheight==undefined)
    			e.savedheight=e.style.height;
    		if (e.savedkeyup==undefined) {
    			e.savedkeyup=e.onkeyup;
    			e.onkeyup=function(ev) {
    				if (!ev) var ev=window.event; var e=resolveTarget(ev);
    				e.style.height=e.scrollHeight+'px';
    				if (e.savedkeyup) e.savedkeyup();
    			}
    		}
    		// IE reports error: "not implemented" for onkeypress
    		if (!config.browser.isIE && e.savedkeypress==undefined) {
    			e.savedkeypress=e.onkeypress;
    			e.onkeypress=function(ev) {
    				if (!ev) var ev=window.event; var e=resolveTarget(ev);
    				if (ev.keyCode==33) { // PGUP
    					if (window.scrollByPages) window.scrollByPages(-1);
    					return false;
    				}
    				if (ev.keyCode==34) { // PGDN
    					if (window.scrollByPages) window.scrollByPages(1);
    					return false;
    				}
    				if (e.savedkeypress) e.savedkeypress();
    			}
    		}
    		e.style.height=e.scrollHeight+'px';
    		if (e.button) e.button.innerHTML=config.commands.autosizeEditor.text_alt;
    		e.maxed=true;
    	},
    	off: function(e,resetHeight) {
    		if (resetHeight) e.style.height=e.savedheight;
    		e.onkeyup=e.savedkeyup;
    		// IE reports error: "not implemented" for onkeypress
    		if (!config.browser.isIE) e.onkeypress=e.savedkeypress;
    		if (e.button) e.button.innerHTML=config.commands.autosizeEditor.text;
    		e.maxed=false;
    	}
    };

    config.macros.autosizeEditor={
    	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    		var here=story.findContainingTiddler(place); if (!here) return;
    		var ta=here.getElementsByTagName('textarea'); if (!ta) return;
    		for (i=0;i<ta.length;i++) {
    			// only autosize textareas actually used to edit tiddler fields
    			if (ta[i].getAttribute("edit")==undefined) continue;
    			config.commands.autosizeEditor.on(ta[i]);
    		}
    		return false;
    	}
    }
    //}}}

    // // grab-and-stretch handle
    //{{{
    config.macros.resizeEditor = { // add stretch bar to editor textarea
    	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    		var here=story.findContainingTiddler(place); if (!here) return;
    		var ta=here.getElementsByTagName('textarea');
    		if (ta) for (i=0;i<ta.length;i++) {
    			// only resize tiddler editor textareas
    			if (ta[i].getAttribute("edit")==undefined) continue;
    			new window.TextAreaResizer(ta[i]);
    		}
    	}
    }

    config.macros.resizeTiddler = { // add stretch bar to tiddler viewer element
    	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    		var here=story.findContainingTiddler(place); if (!here) return;
    		var elems=here.getElementsByTagName('div');
    		if (elems) for (i=0;i<elems.length;i++) if (hasClass(elems[i],'viewer')) break;
    		if (i<elems.length) new window.TextAreaResizer(elems[i]);
    	}
    }

    config.macros.resizeFrame = { // add stretch bar to iframes
    	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    		var here=story.findContainingTiddler(place); if (!here) return;
    		var fr=here.getElementsByTagName('iframe');
    		if (fr) for (i=0;i<fr.length;i++) new window.TextAreaResizer(fr[i]);
    	}
    }

    config.macros.resizeListbox = { // add stretch bar to listbox controls
    	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    		var here=story.findContainingTiddler(place); if (!here) here=place;
    		var fr=here.getElementsByTagName('select');
    		if (fr) for (i=0;i<fr.length;i++) new window.TextAreaResizer(fr[i]);
    	}
    }

    // TextAreaResizer script by Jason Johnston (jj@lojjic.net)
    // Created August 2003.  Use freely, but give me credit.
    // adds a handle below textareas that the user can drag with the mouse to resize the textarea.
    // MODIFIED by ELS for cross-browser (IE) compatibility, including:

    window.TextAreaResizer = function(elt) {
    	this.element = elt;
    	this.create();
    }
    window.TextAreaResizer.prototype = {
    	create : function() {
    		var elt = this.element;
    		var thisRef = this;
    		var h = this.handle = document.createElement("div");
    		h.style.height = "2px"; // was 4px... looked too fat!
    		h.style.overflow = "hidden"; // ELS: force IE to trim height to < 1em
    		var adjust=elt.nodeName=='textarea'?4:0;  // 4 pixels for textarea border edge
    //		h.style.width=(elt.offsetWidth-adjust)+"px";
    		h.style.width="auto";
    		h.style.backgroundColor = "#999"; // ELS: standard mid-tone (dark) gray
    		h.style.cursor = "s-resize";
    		h.title = "Drag to resize text box";
    		h.onmousedown=function(evt){thisRef.dragStart(evt)};
    		elt.parentNode.insertBefore(h, elt.nextSibling);
    	},
    	dragStart : function(evt) {
    		if (!evt) var evt=window.event;
    		this.dragStop(evt); // ELS: stop any current drag processing first
    		var thisRef = this;
    		this.dragStartY = evt.clientY;
    		this.dragStartH = this.element.offsetHeight;
    		document.savedmousemove=document.onmousemove;
    		document.onmousemove=this.dragMoveHdlr=function(evt){thisRef.dragMove(evt)};
    		document.savedmouseup=document.onmouseup;
    		document.onmouseup=this.dragStopHdlr=function(evt){thisRef.dragStop(evt)};
    	},
    	dragMove : function(evt) {
    		if (!evt) var evt=window.event;
    		// ELS: make sure height is at least 10px
    		var h=this.dragStartH+evt.clientY-this.dragStartY;
    		if (h<10) h=10; this.element.style.height=h+"px";
    		// ELS: match handle to textarea width (which may have changed due to document scrollbars)
    //		var adjust=this.element.nodeName.toLowerCase()=='textarea'?4:0; // 4 pixels for textarea
    //		this.handle.style.width=(this.element.offsetWidth-adjust)+"px";
    		// ELS: when manually resizing, disable autoresizing (without restoring saved height)
    		if (this.element.maxed!=undefined && this.element.maxed)
    			config.commands.autosizeEditor.off(this.element,false);
    	},
    	dragStop : function(evt) {
    		if (!evt) var evt=window.event;
    		document.onmousemove=(document.savedmousemove!=undefined)?document.savedmousemove:null;
    		document.onmousemove=(document.savedmouseup!=undefined)?document.savedmouseup:null;
    	},
    	destroy : function() {
    		var elt = this.element;
    		elt.parentNode.removeChild(this.handle);
    		elt.style.height = "";
    	}
    };
    //}}}

    <<tiddler HideTiddlerTags>><<tiddler HideTiddlerBackground>>{{transparent smallform{<<tiddlerTweaker>>}}}

    /***
    |Name|TiddlerTweakerPlugin|
    |Source|http://www.TiddlyTools.com/#TiddlerTweakerPlugin|
    |Version|2.4.2|
    |Author|Eric Shulman|
    |License|http://www.TiddlyTools.com/#LegalStatements|
    |~CoreVersion|2.1|
    |Type|plugin|
    |Requires||
    |Overrides||
    |Description|select multiple tiddlers and modify author, created, modified and/or tag values|
    ~TiddlerTweaker is a tool for TiddlyWiki authors.  It allows you to select multiple tiddlers from a listbox, either by direct interaction or automatically matching specific criteria.  You can then modify the creator, author, created, modified and/or tag values of those tiddlers using a compact set of form fields.  The values you enter into the fields simultantously overwrite the existing values in all tiddlers you have selected.
    !!!!!Usage
    <<<
    {{{<<tiddlerTweaker>>}}}
    {{smallform{<<tiddlerTweaker>>}}}
    By default, any tags you enter into the TiddlerTweaker will //replace// the existing tags in all the tiddlers you have selected.  However, you can also use TiddlerTweaker to quickly filter specified tags from the selected tiddlers, while leaving any other tags assigned to those tiddlers unchanged:
    >Any tag preceded by a "+" (plus) or "-" (minus), will be added or removed from the existing tags //instead of replacing the entire tag definition// of each tiddler (e.g., enter "-excludeLists" to remove that tag from all selected tiddlers.  When using this syntax, care should be taken to ensure that //every// tag is preceded by "+" or "-", to avoid inadvertently overwriting any other existing tags on the selected tiddlers.  (note: the "+" or "-" prefix on each tag value is NOT part of the tag value, and is only used by TiddlerTweaker to control how that tag value is processed)
    Important Notes:
    * Inasmuch as TiddlerTweaker is a 'power user' tool that can perform 'batch' functions (operating on many tiddlers at once), you should always have a recent backup of your document (or "save changes" just *before* tweaking the tiddlers), just in case you "shoot yourself in the foot".
    * The date and author information on any tiddlers you tweak will ONLY be updated if the corresponding  TiddlyTweaker checkboxes have been selected.  As a general rule, after using TiddlerTweaker, always ''//remember to save your document//'' when you are done, even though the tiddler timeline tab may not show any recently modified tiddlers.
    * Selecting and updating all tiddlers in a document can take a while.  Your browser may warn about an "unresponsive script".  Usually, if you allow it to continue, it should complete the processing... eventually.  Nonetheless, be sure to save your work before you begin tweaking lots of tiddlers, just in case something does get 'stuck'.
    <<<
    !!!!!Revisions
    <<<
    2009.06.26 [2.4.2] only add brackets around tags containing spaces
    2009.06.22 [2.4.1] in setFields(), add brackets around all tags shown tweaker edit field
    2009.03.30 [2.4.0] added 'sort by modifier'
    2009.01.22 [2.3.0] added support for text pattern find/replace
    2008.10.27 [2.2.3] in setTiddlers(), fixed Safari bug by replacing static Array.concat(...) with new Array().concat(...)
    2008.09.07 [2.2.2] added removeCookie() function for compatibility with [[CookieManagerPlugin]]
    2008.05.12 [2.2.1] replace built-in backstage "tweak" task with tiddler tweaker control panel (moved from BackstageTweaks)
    2008.01.13 [2.2.0] added "auto-selection" links: all, changed, tags, title, text
    2007.12.26 [2.1.0] added support for managing 'creator' custom field (see [[CoreTweaks]])
    2007.11.01 [2.0.3] added config.options.txtTweakerSortBy for cookie-based persistence of list display order preference setting.
    2007.09.28 [2.0.2] in settiddlers() and deltiddlers(), added suspend/resume notification handling (improves performance when operating on multiple tiddlers)
    2007.08.03 [2.0.1] added shadow definition for [[TiddlerTweaker]] tiddler for use as parameter references with {{{<<tiddler>>, <<slider>> or <<tabs>>}}} macros.
    2007.08.03 [2.0.0] converted from inline script
    2006.01.01 [1.0.0] initial release
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.TiddlerTweakerPlugin= {major: 2, minor: 4, revision: 1, date: new Date(2009,6,22)};

    // shadow tiddler
    config.shadowTiddlers.TiddlerTweaker="<<tiddlerTweaker>>";

    /// backstage task
    if (config.tasks) { // for TW2.2b3 or above
    	config.tasks.tweak.tooltip="review/modify tiddler internals: dates, authors, tags, etc.";
    	config.tasks.tweak.content="{{smallform small groupbox{<<tiddlerTweaker>>}}}";
    }

    if (config.options.txtTweakerSortBy==undefined) config.options.txtTweakerSortBy="modified";

    // if removeCookie() function is not defined by TW core, define it here.
    if (window.removeCookie===undefined) {
    	window.removeCookie=function(name) {
    		document.cookie = name+'=; expires=Thu, 01-Jan-1970 00:00:01 UTC; path=/;';
    	}
    }

    config.macros.tiddlerTweaker = {
    	html: '<form style="display:inline"><!--\
    		--><table style="padding:0;margin:0;border:0;width:100%"><tr valign="top" style="padding:0;margin:0;border:0"><!--\
    		--><td style="text-align:center;white-space:nowrap;width:99%;padding:0;margin:0;border:0"><!--\
    			--><font size=-2><div style="text-align:left;"><span style="float:right"><!--\
    			-->&nbsp; <a href="javascript:;" \
    				title="select all tiddlers"\
    				onclick="\
    				var f=this; while (f&&f.nodeName.toLowerCase()!=\'form\')f=f.parentNode;\
    				for (var t=0; t<f.list.options.length; t++)\
    					if (f.list.options[t].value.length) f.list.options[t].selected=true;\
    				config.macros.tiddlerTweaker.selecttiddlers(f.list);\
    				return false">all</a><!--\
    			-->&nbsp; <a href="javascript:;" \
    				title="select tiddlers that are new/changed since the last file save"\
    				onclick="\
    				var lastmod=new Date(document.lastModified);\
    				var f=this; while (f&&f.nodeName.toLowerCase()!=\'form\')f=f.parentNode;\
    				for (var t=0; t<f.list.options.length; t++) {\
    					var tid=store.getTiddler(f.list.options[t].value);\
    					f.list.options[t].selected=tid&&tid.modified>lastmod;\
    				}\
    				config.macros.tiddlerTweaker.selecttiddlers(f.list);\
    				return false">changed</a><!--\
    			-->&nbsp; <a href="javascript:;" \
    				title="select tiddlers with at least one matching tag"\
    				onclick="\
    				var t=prompt(\'Enter space-separated tags (match ONE)\');\
    				if (!t||!t.length) return false;\
    				var tags=t.readBracketedList();\
    				var f=this; while (f&&f.nodeName.toLowerCase()!=\'form\')f=f.parentNode;\
    				for (var t=0; t<f.list.options.length; t++) {\
    					f.list.options[t].selected=false;\
    					var tid=store.getTiddler(f.list.options[t].value);\
    					if (tid&&tid.tags.containsAny(tags)) f.list.options[t].selected=true;\
    				}\
    				config.macros.tiddlerTweaker.selecttiddlers(f.list);\
    				return false">tags</a><!--\
    			-->&nbsp; <a href="javascript:;" \
    				title="select tiddlers whose titles include matching text"\
    				onclick="\
    				var txt=prompt(\'Enter a title (or portion of a title) to match\');\
    				if (!txt||!txt.length) return false;\
    				var f=this; while (f&&f.nodeName.toLowerCase()!=\'form\')f=f.parentNode;\
    				for (var t=0; t<f.list.options.length; t++) {\
    					f.list.options[t].selected=f.list.options[t].value.indexOf(txt)!=-1;\
    				}\
    				config.macros.tiddlerTweaker.selecttiddlers(f.list);\
    				return false">titles</a><!--\
    			-->&nbsp; <a href="javascript:;" \
    				title="select tiddlers containing matching text"\
    				onclick="\
    				var txt=prompt(\'Enter tiddler text (content) to match\');\
    				if (!txt||!txt.length) return false;\
    				var f=this; while (f&&f.nodeName.toLowerCase()!=\'form\')f=f.parentNode;\
    				for (var t=0; t<f.list.options.length; t++) {\
    					var tt=store.getTiddlerText(f.list.options[t].value,\'\');\
    					f.list.options[t].selected=(tt.indexOf(txt)!=-1);\
    				}\
    				config.macros.tiddlerTweaker.selecttiddlers(f.list);\
    				return false">text</a> &nbsp;<!--\
    			--></span><span>select tiddlers</span><!--\
    			--></div><!--\
    			--></font><select multiple name=list size="11" style="width:99.99%" \
    				title="use click, shift-click and/or ctrl-click to select multiple tiddler titles" \
    				onclick="config.macros.tiddlerTweaker.selecttiddlers(this)" \
    				onchange="config.macros.tiddlerTweaker.setfields(this)"><!--\
    			--></select><br><!--\
    			-->show<input type=text size=1 value="11" \
    				onchange="this.form.list.size=this.value; this.form.list.multiple=(this.value>1);"><!--\
    			-->by<!--\
    			--><select name=sortby size=1 \
    				onchange="config.macros.tiddlerTweaker.init(this.form,this.value)"><!--\
    			--><option value="title">title</option><!--\
    			--><option value="size">size</option><!--\
    			--><option value="modified">modified</option><!--\
    			--><option value="created">created</option><!--\
    			--><option value="modifier">modifier</option><!--\
    			--></select><!--\
    			--><input type="button" value="refresh" \
    				onclick="config.macros.tiddlerTweaker.init(this.form,this.form.sortby.value)"<!--\
    			--> <input type="button" name="stats" disabled value="totals..." \
    				onclick="config.macros.tiddlerTweaker.stats(this)"><!--\
    		--></td><td style="white-space:nowrap;padding:0;margin:0;border:0;width:1%"><!--\
    			--><div style="text-align:left"><font size=-2>&nbsp;modify values</font></div><!--\
    			--><table border=0 style="width:100%;padding:0;margin:0;border:0;"><tr style="padding:0;border:0;"><!--\
    			--><td style="padding:1px;border:0;white-space:nowrap"><!--\
    				--><input type=checkbox name=settitle unchecked \
    					title="allow changes to tiddler title (rename tiddler)" \
    					onclick="this.form.title.disabled=!this.checked">title<!--\
    			--></td><td style="padding:1px;border:0;white-space:nowrap"><!--\
    				--><input type=text name=title size=35 style="width:98%" disabled><!--\
    			--></td></tr><tr style="padding:0;border:0;"><td style="padding:1px;border:0;white-space:nowrap"><!--\
    				--><input type=checkbox name=setcreator unchecked \
    					title="allow changes to tiddler creator" \
    					onclick="this.form.creator.disabled=!this.checked">created by<!--\
    			--></td><td style="padding:1px;border:0;white-space:nowrap"><!--\
    				--><input type=text name=creator size=35 style="width:98%" disabled><!--\
    			--></td></tr><tr style="padding:0;border:0;"><td style="padding:1px;border:0;white-space:nowrap"><!--\
    				--><input type=checkbox name=setwho unchecked \
    					title="allow changes to tiddler author" \
    					onclick="this.form.who.disabled=!this.checked">modified by<!--\
    			--></td><td style="padding:1px;border:0;white-space:nowrap"><!--\
    				--><input type=text name=who size=35 style="width:98%" disabled><!--\
    			--></td></tr><tr style="padding:0;border:0;"><td style="padding:1px;border:0;white-space:nowrap"><!--\
    				--><input type=checkbox name=setcdate unchecked \
    					title="allow changes to created date" \
    					onclick="var f=this.form; f.cm.disabled=f.cd.disabled=f.cy.disabled=f.ch.disabled=f.cn.disabled=!this.checked"><!--\
    				-->created on<!--\
    			--></td><td style="padding:1px;border:0;white-space:nowrap"><!--\
    				--><input type=text name=cm size=2 style="width:2em;padding:0;text-align:center" disabled><!--\
    				--> / <input type=text name=cd size=2 style="width:2em;padding:0;text-align:center" disabled><!--\
    				--> / <input type=text name=cy size=4 style="width:3em;padding:0;text-align:center" disabled><!--\
    				--> at <input type=text name=ch size=2 style="width:2em;padding:0;text-align:center" disabled><!--\
    				--> : <input type=text name=cn size=2 style="width:2em;padding:0;text-align:center" disabled><!--\
    			--></td></tr><tr style="padding:0;border:0;"><td style="padding:1px;border:0;white-space:nowrap"><!--\
    				--><input type=checkbox name=setmdate unchecked \
    					title="allow changes to modified date" \
    					onclick="var f=this.form; f.mm.disabled=f.md.disabled=f.my.disabled=f.mh.disabled=f.mn.disabled=!this.checked"><!--\
    				-->modified on<!--\
    			--></td><td style="padding:1px;border:0;white-space:nowrap"><!--\
    				--><input type=text name=mm size=2 style="width:2em;padding:0;text-align:center" disabled><!--\
    				--> / <input type=text name=md size=2 style="width:2em;padding:0;text-align:center" disabled><!--\
    				--> / <input type=text name=my size=4 style="width:3em;padding:0;text-align:center" disabled><!--\
    				--> at <input type=text name=mh size=2 style="width:2em;padding:0;text-align:center" disabled><!--\
    				--> : <input type=text name=mn size=2 style="width:2em;padding:0;text-align:center" disabled><!--\
    			--></td></tr><tr style="padding:0;border:0;"><td style="padding:1px;border:0;white-space:nowrap"><!--\
    				--><input type=checkbox name=replacetext unchecked\
    					title="find/replace matching text" \
    					onclick="this.form.pattern.disabled=this.form.replacement.disabled=!this.checked">replace text<!--\
    			--></td><td style="padding:1px;border:0;white-space:nowrap"><!--\
    				--><input type=text name=pattern size=15 value="" style="width:40%" disabled \
    					title="enter TEXT PATTERN (regular expression)"> with <!--\
    				--><input type=text name=replacement size=15 value="" style="width:40%" disabled \
    					title="enter REPLACEMENT TEXT"><!--\
    			--></td></tr><tr style="padding:0;border:0;"><td style="padding:1px;border:0;white-space:nowrap"><!--\
    				--><input type=checkbox name=settags checked \
    					title="allow changes to tiddler tags" \
    					onclick="this.form.tags.disabled=!this.checked">tags<!--\
    			--></td><td style="padding:1px;border:0;white-space:nowrap"><!--\
    				--><input type=text name=tags size=35 value="" style="width:98%" \
    					title="enter new tags or use \'+tag\' and \'-tag\' to add/remove tags from existing tags"><!--\
    			--></td></tr></table><!--\
    			--><div style="text-align:center"><!--\
    			--><nobr><input type=button name=display disabled style="width:32%" value="display tiddlers" \
    				onclick="config.macros.tiddlerTweaker.displaytiddlers(this)"><!--\
    			--> <input type=button name=del disabled style="width:32%" value="delete tiddlers" \
    				onclick="config.macros.tiddlerTweaker.deltiddlers(this)"><!--\
    			--> <input type=button name=set disabled style="width:32%" value="update tiddlers" \
    				onclick="config.macros.tiddlerTweaker.settiddlers(this)"></nobr><!--\
    			--></div><!--\
    		--></td></tr></table><!--\
    		--></form><span style="display:none"><!--content replaced by tiddler "stats"--></span>\
    	',
    	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    		var span=createTiddlyElement(place,"span");
    		span.innerHTML=this.html;
    		this.init(span.firstChild,config.options.txtTweakerSortBy);
    	},
    	init: function(f,sortby) { // initialize form controls
    		if (!f) return; // form might not be rendered yet...
    		while (f.list.options[0]) f.list.options[0]=null; // empty current list content
    		var tids=store.getTiddlers(sortby);
    		if (sortby=='size') // descending order
    			tids.sort(function(a,b) {return a.text.length > b.text.length ? -1 : (a.text.length == b.text.length ? 0 : +1);});
    		var who='';
    		for (i=0; i<tids.length; i++) { var t=tids[i];
    			var label=t.title; var value=t.title;
    			switch (sortby) {
    				case 'modified':
    				case 'created':
    					var t=tids[tids.length-i-1]; // reverse order
    					var when=t[sortby].formatString('YY.0MM.0DD 0hh:0mm ');
    					label=when+t.title;
    					value=t.title;
    					break;
    				case 'size':
    					label='['+t.text.length+'] '+label;
    					break;
    				case 'modifier':
    				case 'creator':
    					if (who!=t[sortby]) {
    						who=t[sortby];
    						f.list.options[f.list.length]=new Option('by '+who+':','',false,false);
    					}
    					label='\xa0\xa0\xa0'+label; // indent
    					break;
    			}
    			f.list.options[f.list.length]=new Option(label,value,false,false);
    		}
    		f.title.value=f.who.value=f.creator.value=f.tags.value="";
    		f.cm.value=f.cd.value=f.cy.value=f.ch.value=f.cn.value="";
    		f.mm.value=f.md.value=f.my.value=f.mh.value=f.mn.value="";
    		f.stats.disabled=f.set.disabled=f.del.disabled=f.display.disabled=true;
    		f.settitle.disabled=false;
    		config.options.txtTweakerSortBy=sortby; // remember current setting
    		f.sortby.value=sortby; // sync droplist selection with current setting
    		if (sortby!="modified") // non-default preference... save cookie
    			saveOptionCookie("txtTweakerSortBy");
    		else removeCookie("txtTweakerSortBy"); // default preference... clear cookie
    	},
    	selecttiddlers: function(here) { // enable/disable tweaker fields based on number of items selected
    		// count how many tiddlers are selected
    		var f=here.form; var list=f.list;
    		var c=0; for (i=0;i<list.length;i++) if (list.options[i].selected) c++;
    		if (c>1) f.title.disabled=true;
    		if (c>1) f.settitle.checked=false;
    		f.set.disabled=(c==0);
    		f.del.disabled=(c==0);
    		f.display.disabled=(c==0);
    		f.settitle.disabled=(c>1);
    		f.stats.disabled=(c==0);
    		var msg=(c==0)?'select tiddlers':(c+' tiddler'+(c!=1?'s':'')+' selected');
    		here.previousSibling.firstChild.firstChild.nextSibling.innerHTML=msg;
    		if (c) clearMessage(); else displayMessage("no tiddlers selected");
    	},
    	setfields: function(here) { // set tweaker edit fields from first selected tiddler
    		var f=here.form;
    		if (!here.value.length) {
    			f.title.value=f.who.value=f.creator.value=f.tags.value="";
    			f.cm.value=f.cd.value=f.cy.value=f.ch.value=f.cn.value="";
    			f.mm.value=f.md.value=f.my.value=f.mh.value=f.mn.value="";
    			return;
    		}
    		var tid=store.getTiddler(here.value); if (!tid) return;
    		f.title.value=tid.title;
    		f.who.value=tid.modifier;
    		f.creator.value=tid.fields['creator']||''; // custom field - might not exist
    		f.tags.value=tid.tags.map(function(t){return String.encodeTiddlyLink(t)}).join(' ');
    		var c=tid.created; var m=tid.modified;
    		f.cm.value=c.getMonth()+1;
    		f.cd.value=c.getDate();
    		f.cy.value=c.getFullYear();
    		f.ch.value=c.getHours();
    		f.cn.value=c.getMinutes();
    		f.mm.value=m.getMonth()+1;
    		f.md.value=m.getDate();
    		f.my.value=m.getFullYear();
    		f.mh.value=m.getHours();
    		f.mn.value=m.getMinutes();
    	},
    	settiddlers: function(here) {
    		var f=here.form; var list=f.list;
    		var tids=[];
    		for (i=0;i<list.length;i++) if (list.options[i].selected) tids.push(list.options[i].value);
    		if (!tids.length) { alert("please select at least one tiddler"); return; }
    		var cdate=new Date(f.cy.value,f.cm.value-1,f.cd.value,f.ch.value,f.cn.value);
    		var mdate=new Date(f.my.value,f.mm.value-1,f.md.value,f.mh.value,f.mn.value);
    		if (tids.length>1 && !confirm("Are you sure you want to update 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;
    			var title=!f.settitle.checked?tid.title:f.title.value;
    			var who=!f.setwho.checked?tid.modifier:f.who.value;
    			var text=tid.text;
    			if (f.replacetext.checked) text=text.replace(new RegExp(f.pattern.value,'mg'),f.replacement.value);
    			var tags=tid.tags;
    			if (f.settags.checked) {
    				var intags=f.tags.value.readBracketedList();
    				var addtags=[]; var deltags=[]; var reptags=[];
    				for (i=0;i<intags.length;i++) {
    					if (intags[i].substr(0,1)=='+')
    						addtags.push(intags[i].substr(1));
    					else if (intags[i].substr(0,1)=='-')
    						deltags.push(intags[i].substr(1));
    					else
    						reptags.push(intags[i]);
    				}
    				if (reptags.length)
    					tags=reptags;
    				if (addtags.length)
    					tags=new Array().concat(tags,addtags);
    				if (deltags.length)
    					for (i=0;i<deltags.length;i++)
    						{ var pos=tags.indexOf(deltags[i]); if (pos!=-1) tags.splice(pos,1); }
    			}
    			if (!f.setcdate.checked) cdate=tid.created;
    			if (!f.setmdate.checked) mdate=tid.modified;
    			store.saveTiddler(tid.title,title,text,who,mdate,tags,tid.fields);
    			if (f.setcreator.checked) store.setValue(tid.title,'creator',f.creator.value); // set creator
    			if (f.setcdate.checked) tid.assign(null,null,null,null,null,cdate); // set create date
    		}
    		store.resumeNotifications();
    		this.init(f,f.sortby.value);
    	},
    	displaytiddlers: function(here) {
    		var f=here.form; var list=f.list;
    		var tids=[];
    		for (i=0; i<list.length;i++) if (list.options[i].selected) tids.push(list.options[i].value);
    		if (!tids.length) { alert("please select at least one tiddler"); return; }
    		story.displayTiddlers(story.findContainingTiddler(f),tids)
    	},
    	deltiddlers: function(here) {
    		var f=here.form; var list=f.list;
    		var tids=[];
    		for (i=0;i<list.length;i++) if (list.options[i].selected) tids.push(list.options[i].value);
    		if (!tids.length) { alert("please select at least one tiddler"); return; }
    		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();
    		this.init(f,f.sortby.value);
    	},
    	stats: function(here) {
    		var f=here.form; var list=f.list; var tids=[]; var out=''; var tot=0;
    		var target=f.nextSibling;
    		for (i=0;i<list.length;i++) if (list.options[i].selected) tids.push(list.options[i].value);
    		if (!tids.length) { alert("please select at least one tiddler"); return; }
    		for (t=0;t<tids.length;t++) {
    			var tid=store.getTiddler(tids[t]); if (!tid) continue;
    			out+='[['+tid.title+']] '+tid.text.length+'\n'; tot+=tid.text.length;
    		}
    		var avg=tot/tids.length;
    		out=tot+' bytes in '+tids.length+' selected tiddlers ('+avg+' bytes/tiddler)\n<<<\n'+out+'<<<\n';
    		removeChildren(target);
    		target.innerHTML="<hr><font size=-2><a href='javascript:;' style='float:right' "
    			+"onclick='this.parentNode.parentNode.style.display=\"none\"'>close</a></font>";
    		wikify(out,target);
    		target.style.display="block";
    	}
    };
    //}}}

    /***
    |Name|TiddlyBlogSetupPlugin|
    |Source|http://www.TiddlyTools.com/quickstart/tiddlyblog#TiddlyBlogSetupPlugin|
    |Version|1.0.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|initialize tiddlyblog internal values|
    !!!!!Revisions
    <<<
    2009.03.26 [1.0.0] initial release
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.TiddlyBlogSetupPlugin= {major: 1, minor: 0, revision: 0, date: new Date(2009,3,26)};
    config.shadowTiddlers['SiteUrl']="http://www.TiddlyTools.com/quickstart/tiddlyblog.html";
    config.shadowTiddlers['PoweredByTiddlyBlog']="\n"
    	+"''powered by [[tiddlyblog|"+config.shadowTiddlers['SiteUrl']+"]]''\n"
    	+"//portable blogging...\n"
    	+"...anytime, anywhere!//";
    //}}}

    /%
    |Name|ToggleBreadcrumbs|
    |Source|http://www.TiddlyTools.com/#ToggleBreadcrumbs|
    |Version|0.0.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|script|
    |Requires|BreadcrumbsPlugin, InlineJavascriptPlugin|
    |Overrides||
    |Description|dynamically enable/disable BreadcrumbsPlugin display|
    %/<script>
    if (config.options.chkShowBreadcrumbs==undefined) config.options.chkShowBreadcrumbs=true;
    </script><<option chkShowBreadcrumbs>><script>
    	var chk=place.lastChild;
    	chk.coreOnChange=chk.onchange;
    	chk.onchange=function() {
    		if (this.coreOnChange) this.coreOnChange.apply(this,arguments);
    		this.checked=config.options.chkShowBreadcrumbs;
    		if (config.macros.breadcrumbs) config.macros.breadcrumbs.refresh();
    	};
    </script>

    /%
    |Name|ToggleFullScreen|
    |Source|http://www.TiddlyTools.com/#ToggleFullScreen|
    |Version|1.1.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|script|
    |Requires|InlineJavascriptPlugin|
    |Overrides||
    |Description|show/hide main menu, sidebar and page header|

    Usage:
    	<<tiddler ToggleFullScreen with: label altlabel>>
    		- displays 'onclick' command link that toggles full screen display mode
    	or
    	<<tiddler ToggleFullScreen##ON>>
    		- immediately sets full screen mode
    	or
    	<<tiddler ToggleFullScreen##OFF>>
    		- immediately resets full screen mode

    !ON
    <script> if (!config.options.chkFullScreen) window.toggleFullScreen(); </script>
    !end ON

    !OFF
    <script> if (config.options.chkFullScreen) window.toggleFullScreen(); </script>
    !end OFF

    %/<script>
    window.toggleFullScreen=function(here) {
    	config.options.chkFullScreen=!config.options.chkFullScreen;
    	var showmm=!config.options.chkFullScreen && config.options.chkShowLeftSidebar!==false;
    	var showsb=!config.options.chkFullScreen && config.options.chkShowRightSidebar!==false;
    	var showcrumbs=!config.options.chkFullScreen && config.options.chkShowBreadcrumbs!==false
    		&& config.macros.breadcrumbs && config.macros.breadcrumbs.crumbs.length;
    	var cw=document.getElementById('contentWrapper');
    	var da=document.getElementById('displayArea');
    	var mm=document.getElementById('mainMenu');
    	var sb=document.getElementById('sidebar');
    	var sm=document.getElementById('storyMenu');
    	var bc=document.getElementById('breadCrumbs');
    	var sn=document.getElementById('siteNav');
    	if (cw){
    		for (var i=0; i<cw.childNodes.length; i++)
    			if (hasClass(cw.childNodes[i],'header')) { var h=cw.childNodes[i]; break; }
    		if (h) h.style.display=!config.options.chkFullScreen?'block':'none';
    	}
    	if (mm) {
    		mm.style.display=showmm?'block':'none';
    		da.style.marginLeft=showmm?(config.options.txtDisplayAreaLeftMargin||''):'1em';
    	}
    	if (sb) {
    		sb.style.display=showsb?'block':'none';
    		da.style.marginRight=showsb?(config.options.txtDisplayAreaRightMargin||''):'1em';
    	}
    	if (sm)
    		sm.style.display=!config.options.chkFullScreen ?'block':'none';
    	if (bc)
    		bc.style.display=showcrumbs?'block':'none';
    	if (sn)
    		sn.style.display=!config.options.chkFullScreen?'block':'none';
    	var label=('$'+'1'=='$1')?'fullscreen':'$1';
    	var altlabel='$2'; if ('$'+'2'=='$2') altlabel=label;
    	if (typeof(here)!='undefined' && here!=window.place)
    		here.innerHTML=!config.options.chkFullScreen?label:altlabel;
    	var b=document.getElementById('restoreFromFullscreenButton');
    	if (b) removeNode(b);
    	else {
    		var b=createTiddlyElement(null,'span','restoreFromFullscreenButton','selected');
    		b.innerHTML='&loz;';
    		b.title='RESTORE: redisplay page header, menu and sidebar';
    		b.onclick=window.toggleFullScreen;
    		var s=b.style;
    		s.position='fixed'; s.top='.3em'; s.right='.3em'; s.zIndex='10001';
    		s.border='2px outset ButtonFace';
    		s.padding='0px 3px';
    		s.cursor='pointer';
    		s.fontSize='8pt';
    		s.backgroundColor='ButtonFace';
    		if (config.browser.isGecko) {
    			s.color='ButtonText !important';
    			s.MozAppearance='button';
    		}
    		document.body.insertBefore(b,null);
    	}
    	return false;
    };
    </script>/%

    %/<script label="$1" title="FULLSCREEN: toggle display of mainmenu, sidebar, and page header">
    	window.toggleFullScreen(place);
    	return false;
    </script><script>
    	place.lastChild.innerHTML=('$'+'1'=='$1')?'fullscreen':'$1';
    </script>

    /%
    |Name|ToggleLeftSidebar|
    |Source|http://www.TiddlyTools.com/#ToggleLeftSidebar|
    |Version|2.0.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|script|
    |Requires|InlineJavascriptPlugin|
    |Overrides||
    |Description|show/hide left sidebar (MainMenu)|

    Usage: <<tiddler ToggleLeftSidebar with: "label">>

    Config settings:
    	config.options.chkShowLeftSidebar (true)
    	config.options.txtToggleLeftSideBarLabelShow (►)
    	config.options.txtToggleLeftSideBarLabelHide (◄)

    %/<script label="$1" title="show/hide MainMenu content">
    	var co=config.options;
    	if (co.chkShowLeftSidebar=='undefined') co.chkShowLeftSidebar=true;
    	co.chkShowLeftSidebar=!co.chkShowLeftSidebar;
    	var mm=document.getElementById('mainMenu'); if (!mm) return;
    	mm.style.display=co.chkShowLeftSidebar?'block':'none';
    	document.getElementById('displayArea').style.marginLeft=co.chkShowLeftSidebar?'':'1em';
    	saveOptionCookie('chkShowLeftSidebar');
    	var labelShow=co.txtToggleLeftSideBarLabelShow||'&#x25BA;';
    	var labelHide=co.txtToggleLeftSideBarLabelHide||'&#x25C4;';
    	if (typeof(place)!='undefined' && '$1'=='$'+'1') {
    		place.innerHTML=co.chkShowLeftSidebar?labelHide:labelShow;
    		place.title=(co.chkShowLeftSidebar?'hide':'show')+' left sidebar';
    	}
    	var sm=document.getElementById('storyMenu'); if (sm) config.refreshers.content(sm);
    </script><script>
    	var co=config.options;
    	if (co.chkShowLeftSidebar=='undefined') co.chkShowLeftSidebar=true;
    	var mm=document.getElementById('mainMenu'); if (!mm) return;
    	mm.style.display=co.chkShowLeftSidebar?'block':'none';
    	document.getElementById('displayArea').style.marginLeft=co.chkShowLeftSidebar?'':'1em';
    	if ('$1'=='$'+'1') {
    		var labelShow=co.txtToggleLeftSideBarLabelShow||'&#x25BA;';
    		var labelHide=co.txtToggleLeftSideBarLabelHide||'&#x25C4;';
    		place.lastChild.innerHTML=co.chkShowLeftSidebar?labelHide:labelShow;
    		place.lastChild.title=(co.chkShowLeftSidebar?'hide':'show')+' left sidebar';
    	}
    </script>

    /%
    |Name|ToggleRightSidebar|
    |Source|http://www.TiddlyTools.com/#ToggleRightSidebar|
    |Version|2.0.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|script|
    |Requires|InlineJavascriptPlugin|
    |Overrides||
    |Description|show/hide right sidebar (MainMenu)|

    Usage: <<tiddler ToggleRightSidebar with: "label">>

    Config settings:
    	config.options.chkShowRightSidebar (true)
    	config.options.txtToggleRightSideBarLabelShow (◄)
    	config.options.txtToggleRightSideBarLabelHide (►)

    %/<script label="$1" title="show/hide right sidebar content">
    	var co=config.options;
    	if (co.chkShowRightSidebar=='undefined') co.chkShowRightSidebar=true;
    	co.chkShowRightSidebar=!co.chkShowRightSidebar;
    	var sb=document.getElementById('sidebar'); if (!sb) return;
    	sb.style.display=co.chkShowRightSidebar?'block':'none';
    	document.getElementById('displayArea').style.marginRight=co.chkShowRightSidebar?'':'1em';
    	saveOptionCookie('chkShowRightSidebar');
    	var labelShow=co.txtToggleRightSideBarLabelShow||'&#x25C4;';
    	var labelHide=co.txtToggleRightSideBarLabelHide||'&#x25BA;';
    	if (typeof(place)!='undefined' && '$1'=='$'+'1') {
    		place.innerHTML=co.chkShowRightSidebar?labelHide:labelShow;
    		place.title=(co.chkShowRightSidebar?'hide':'show')+' right sidebar';
    	}
    	var sm=document.getElementById('storyMenu'); if (sm) config.refreshers.content(sm);
    </script><script>
    	var co=config.options;
    	if (co.chkShowRightSidebar=='undefined') co.chkShowRightSidebar=true;
    	var sb=document.getElementById('sidebar'); if (!sb) return;
    	sb.style.display=co.chkShowRightSidebar?'block':'none';
    	document.getElementById('displayArea').style.marginRight=co.chkShowRightSidebar?'':'1em';
    	if ('$1'=='$'+'1') {
    		var labelShow=co.txtToggleRightSideBarLabelShow||'&#x25C4;';
    		var labelHide=co.txtToggleRightSideBarLabelHide||'&#x25BA;';
    		place.lastChild.innerHTML=co.chkShowRightSidebar?labelHide:labelShow;
    		place.lastChild.title=(co.chkShowRightSidebar?'hide':'show')+' right sidebar';
    	}
    </script>

    |~ViewToolbar|collapseTiddler collapseOthers RefreshCommand snapshotPrint closeTiddler closeOthers +editTiddler > < * fields permalink references jump|
    |~CollapsedToolbar|expandTiddler collapseOthers RefreshCommand snapshotPrint closeTiddler closeOthers +editTiddler > < * fields permalink references jump|
    |~EditToolbar|+saveTiddler -cancelTiddler copyTiddler deleteTiddler autosizeEditor|

    /***
    Description: Contains the stuff you need to use Tiddlyspot
    Note, you also need UploadPlugin, PasswordOptionPlugin and LoadRemoteFileThroughProxy
    from http://tiddlywiki.bidix.info for a complete working Tiddlyspot site.
    ***/
    //{{{

    // edit this if you are migrating sites or retrofitting an existing TW
    config.tiddlyspotSiteId = 'ENTER_YOUR_ID_HERE';

    // ADDITIONAL SETTINGS FOR DEFAULT USE OF <<upload>> WITHOUT PARAMS
    config.options.txtUploadStoreUrl='http://ENTER_YOUR_ID_HERE.tiddlyspot.com/store.cgi';
    config.options.txtUploadFilename='index.html';
    config.options.txtUploadBackupDir='.';
    config.options.txtUploadDir='.';
    config.options.txtUploadUserName='ENTER_YOUR_ID_HERE';

    // make it so you can by default see edit controls via http
    config.options.chkHttpReadOnly = false;
    window.readOnly = false; // make sure of it (for tw 2.2)
    window.showBackstage = true; // show backstage too

    // disable autosave in d3
    if (window.location.protocol != "file:")
    	config.options.chkGTDLazyAutoSave = false;

    // tweak shadow tiddlers to add upload button, password entry box etc
    with (config.shadowTiddlers) {
    	SiteUrl = 'http://'+config.tiddlyspotSiteId+'.tiddlyspot.com';
    	SideBarOptions = SideBarOptions.replace(/(<<saveChanges>>)/,"$1<<tiddler TspotSidebar>>");
    	OptionsPanel = OptionsPanel.replace(/^/,"<<tiddler TspotOptions>>");
    	DefaultTiddlers = DefaultTiddlers.replace(/^/,"[[WelcomeToTiddlyspot]] ");
    	MainMenu = MainMenu.replace(/^/,"[[WelcomeToTiddlyspot]] ");
    }

    // create some shadow tiddler content
    merge(config.shadowTiddlers,{

    'WelcomeToTiddlyspot':[
     "This document is a ~TiddlyWiki from tiddlyspot.com.  A ~TiddlyWiki is an electronic notebook that is great for managing todo lists, personal information, and all sorts of things.",
     "",
     "@@font-weight:bold;font-size:1.3em;color:#444; //What now?// &nbsp;&nbsp;@@ Before you can save any changes, you need to enter your password in the form below.  Then configure privacy and other site settings at your [[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]] (your control panel username is //" + config.tiddlyspotSiteId + "//).",
     "<<tiddler TspotControls>>",
     "See also GettingStarted.",
     "",
     "@@font-weight:bold;font-size:1.3em;color:#444; //Working online// &nbsp;&nbsp;@@ You can edit this ~TiddlyWiki right now, and save your changes using the \"save to web\" button in the column on the right.",
     "",
     "@@font-weight:bold;font-size:1.3em;color:#444; //Working offline// &nbsp;&nbsp;@@ A fully functioning copy of this ~TiddlyWiki can be saved onto your hard drive or USB stick.  You can make changes and save them locally without being connected to the Internet.  When you're ready to sync up again, just click \"upload\" and your ~TiddlyWiki will be saved back to tiddlyspot.com.",
     "",
     "@@font-weight:bold;font-size:1.3em;color:#444; //Help!// &nbsp;&nbsp;@@ Find out more about ~TiddlyWiki at [[TiddlyWiki.com|http://tiddlywiki.com]].  Also visit [[TiddlyWiki.org|http://tiddlywiki.org]] for documentation on learning and using ~TiddlyWiki. New users are especially welcome on the [[TiddlyWiki mailing list|http://groups.google.com/group/TiddlyWiki]], which is an excellent place to ask questions and get help.  If you have a tiddlyspot related problem email [[tiddlyspot support|mailto:support@tiddlyspot.com]].",
     "",
     "@@font-weight:bold;font-size:1.3em;color:#444; //Enjoy :)// &nbsp;&nbsp;@@ We hope you like using your tiddlyspot.com site.  Please email [[feedback@tiddlyspot.com|mailto:feedback@tiddlyspot.com]] with any comments or suggestions."
    ].join("\n"),

    'TspotControls':[
     "| tiddlyspot password:|<<option pasUploadPassword>>|",
     "| site management:|<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . .  " + config.tiddlyspotSiteId + ">>//(requires tiddlyspot password)//<br>[[control panel|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/controlpanel]], [[download (go offline)|http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download]]|",
     "| links:|[[tiddlyspot.com|http://tiddlyspot.com/]], [[FAQs|http://faq.tiddlyspot.com/]], [[blog|http://tiddlyspot.blogspot.com/]], email [[support|mailto:support@tiddlyspot.com]] & [[feedback|mailto:feedback@tiddlyspot.com]], [[donate|http://tiddlyspot.com/?page=donate]]|"
    ].join("\n"),

    'TspotSidebar':[
     "<<upload http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/store.cgi index.html . .  " + config.tiddlyspotSiteId + ">><html><a href='http://" + config.tiddlyspotSiteId + ".tiddlyspot.com/download' class='button'>download</a></html>"
    ].join("\n"),

    'TspotOptions':[
     "tiddlyspot password:",
     "<<option pasUploadPassword>>",
     ""
    ].join("\n")

    });
    //}}}

    /***
    |Name|UnsavedChangesPlugin|
    |Source|http://www.TiddlyTools.com/#UnsavedChangesPlugin|
    |Version|3.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|TiddlyWiki.prototype.setDirty,store.saveTiddler,store.removeTiddler|
    |Description|show droplist of tiddlers that have changed since the last time the document was saved|
    Display a list of tiddlers that have been changed since the last time the document was saved.  The list includes all new/modified tiddlers as well as those changed with "minor edits" enabled and any tiddlers that you import during the session, regardless of their modification date.
    !!!!!Usage
    <<<
    {{{
    <<unsavedChanges panel>> or <<unsavedChanges>>
    }}}
    {{indent{
    the ''panel'' keyword displays a 'control panel' interface containing a droplist of unsaved tiddlers and a 'goto' button, along with a command link to 'save changes'.  Depending upon what other plugins are installed, several additional elements will also be displayed: When [[NestedSlidersPlugin]] is installed, the entire control panel is contained within a ''SLIDER''.  When [[LoadTiddlersPlugin]] is installed, a ''REVERT'' button is added.  When [[SaveAsPlugin]] is installed, a ''SAVE AS'' link is added.  When [[UploadPlugin]] is installed, an ''UPLOAD'' (or ''save to web'') link is added.  When [[TrashPlugin]] is installed and there are tiddlers tagged with<<tag Trash>>, an ''EMPTY TRASH'' link is added.
    }}}
    {{{
    <<unsavedChanges list separator>>
    }}}
    {{indent{
    the ''list'' keyword displays a simple space-separated list of unsaved tiddlers without any other command links.  You can specify an optional ''separator'' value that can be used in place of the default space character.  For example, you can specify {{{"<br>"}}} as the separator in order to display each link, one per line.
    }}}
    {{{
    <<unsavedChanges command label tip>>
    }}}
    {{indent{
    the ''command'' keyword displays a single 'command link' that, when clicked, displays a ~TiddlyWiki popup containing the list of unsaved tiddlers, the 'save changes' command and, depending upon what other plugins are installed, additional commands for 'save as', 'upload', and 'empty trash' (similar to the panel display described above).

    You can specify optional ''label'' and ''tip'' parameters in the macro to customize the command link text and tooltip.  The default label for the command link is: "There %1 %0 unsaved tiddler%2...", where:
    * %0 is automatically replaced with the number of unsaved changes
    * %1 is either "is" (if changes=1) or "are" (if changes>1)
    * %2 is either blank (if changes=1) or "s" (if changes>1)
    resulting in the text: //"There is 1 unsaved tiddler...", "There are 2 unsaved tiddlers...", etc.//
    }}}
    <<<
    !!!!!Examples
    <<<
    ^^//note: the following examples will not display any output unless you have already created/modified tiddlers in the current document.//^^
    {{{<<unsavedChanges>>}}}
    <<unsavedChanges>>
    ----
    {{{<<unsavedChanges command>>}}}
    <<unsavedChanges command>>
    ----
    {{{<<unsavedChanges list>>}}}
    <<unsavedChanges list>>
    ----
    {{{<<unsavedChanges list "<br>">>}}}
    <<unsavedChanges list "<br>">>
    <<<
    !!!!!Revisions
    <<<
    2009.03.02 [3.3.3] fix handling for titles that contain HTML special chars (lt,gt,quot,amp)
    2008.09.02 [3.3.2] cleanup popup list output generation and added timestamps/sizes to popup display
    2008.08.23 [3.3.1] added optional custom 'label' and 'tip' params to 'command' mode and defined default values for mode, label, tip, and separator as object properties for I18N/L10N-readiness.
    2008.08.21 [3.3.0] complete re-write of rendering and refresh processing to support multiple instances and automatic self-refresh (no longer depends upon core refresh notifications)
    2008.08.21 [3.2.0] added 'command' option for link+popup as alternative to 'control panel' interface
    2008.04.22 [3.1.2] use SaveAsPlugin instead of obsolete NewDocumentPlugin to add "save as" link
    2007.12.22 [3.1.1] hijack removeTiddler() instead of low-level deleteTiddler() to correct tracking and refresh handling issues.  in saveTiddler(), check for 'tiddler rename' (title!=newtitle) and adjust list accordingly.
    2007.12.21 [3.1.0] added support for {{{<<unsavedChanges list separator>>}}} usage to unsaved tiddlers as a simple list of links, embedded in tiddler content (e.g., [[MainMenu]])
    2007.12.20 [3.0.0] rewrite to track ALL changed tiddlers, including imports and minor edits, regardless of saved modification dates.  Also, rewrote display logic to directly refresh macro output instead of triggering a page refresh.  The entire process is MUCH more efficient now.
    2007.08.02 [2.0.0] converted from inline script
    2007.01.01 [1.0.0] initial release
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.UnsavedChangesPlugin= {major: 3, minor: 3, revision: 3, date: new Date(2009,3,2)};

    config.macros.unsavedChanges = {
    	changed: [], // list of currently unsaved tiddler titles
    	defMode: "panel",
    	defSep: " ",
    	defLabel: "There %1 %0 unsaved tiddler%2...",
    	defTip: "view a list of unsaved tiddler changes",
    	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    		var wrapper=createTiddlyElement(place,"span",null,"unsavedChanges");
    		wrapper.setAttribute("mode",params[0]||this.defMode);
    		wrapper.setAttribute("sep",params[1]||this.defSep); // for 'list' mode
    		wrapper.setAttribute("label",params[1]||this.defLabel); // for 'command' mode
    		wrapper.setAttribute("tip",params[2]||this.defTip); // for 'command' mode
    		this.render(wrapper);
    	},
    	render: function(wrapper) {
    		removeChildren(wrapper); // make sure its empty
    		if (!this.changed.length) return; // no changes = no output
    		switch (wrapper.getAttribute("mode")) {
    			case "command": this.command(wrapper); break;
    			case "list": this.list(wrapper); break;
    			case "panel": default: this.panel(wrapper); break;
    		}
    	},
    	refresh: function() {
    		var wrappers=document.getElementsByTagName("span");
    		for (var w=0; w<wrappers.length; w++)
    			if (hasClass(wrappers[w],"unsavedChanges"))
    				this.render(wrappers[w]);
    	},
    	list: function(place) { // show simple list of unsaved tiddlers
    		wikify("[["+this.changed.join("]]"+place.getAttribute("sep")+"[[")+"]]",place);
    	},
    	command: function(place) { // show command link with popup list
    		var c=this.changed.length;
    		var txt=place.getAttribute("label").format([c,c==1?'is':'are',c==1?'':'s']);
    		var tip=place.getAttribute("tip");
    		var action=function(ev) { if (!ev) var ev=window.event;
    			var p=Popup.create(this); if (!p) return false;
    			var d=createTiddlyElement(p,"div");
    			d.style.whiteSpace="normal"; d.style.width="auto"; d.style.padding="2px";
    			// gather pretty links for changed tiddlers
    			var list=[]; var item=" &nbsp;[[%1 - %0 (%2 bytes)|%0]]&nbsp; ";
    			for (var i=config.macros.unsavedChanges.changed.length-1; i>=0; i--) {
    				var tid=store.getTiddler(config.macros.unsavedChanges.changed[i]);
    				if (!tid) continue;
    				var when=tid.modified.formatString('YYYY.0MM.0DD 0hh:0mm:0ss');
    				list.push(item.format([tid.title,when,tid.text.length]));
    			}
    			wikify("@@white-space:nowrap;"+list.join("<br>")+"@@",d);
    			if (!readOnly) {
    				var t="\n----\n";
    				t+="@@white-space:nowrap;display:block;text-align:center; &nbsp;";
    				t+="<<saveChanges>>";
    				t+=config.macros.saveAs?" | <<saveAs>>":"";
    				t+=config.macros.upload?" | <<upload>>":"";
    				t+=(config.macros.emptyTrash&&store.getTaggedTiddlers("Trash").length)?" | <<emptyTrash>>":"";
    				t+="&nbsp; @@";
    				wikify(t,d);
    			}
    			Popup.show(p,false);
    			ev.cancelBubble=true; if(ev.stopPropagation)ev.stopPropagation();
    			return(false);
    		}
    		createTiddlyButton(place,txt,tip,action,"button");
    	},
    	panel: function(place) { // show composite droplist+buttons+commands
    		// gather changed tiddlers (in reverse order by date - most recent first)
    		var tids=[]; for (var i=this.changed.length-1; i>=0; i--)
    			{ var t=store.getTiddler(this.changed[i]); if (t) tids.push(t); }
    		tids.sort(function(a,b){return a.modified<b.modified?-1:(a.modified==b.modified?0:1);});
    		// generate droplist items
     		var list=[]; var item='<option value="%0">%1 - %0 (%2 bytes)</option>';
    		for (var i=tids.length-1; i>=0; i--) {
    			var when=tids[i].modified.formatString('YYYY.0MM.0DD 0hh:0mm:0ss');
    			list.push(item.format([tids[i].title.htmlEncode(),when,tids[i].text.length]));
    		}
    		// display droplist, buttons, and command links
    		var out=''; var c=this.changed.length;
    		var NSP=config.formatters.findByField("name","nestedSliders");
    		var summary=this.defLabel.format([c,c==1?'is':'are',c==1?'':'s'])
    		out+=NSP?'+++(unsaved)['+summary+'|'+this.defTip+']...':(summary+"\n");
    		out+='<html><form style="display:inline"><!--\
    			--><select size="1" name="list" \
    				title="select a tiddler to view" \
    				onchange="var v=this.value; if (v.length) story.displayTiddler(null,v);"><!--\
    			-->'+list.join('')+'<!--\
    			--></select><!--\
    			--><input type="button" value="goto" onclick="this.form.list.onchange();">';
    		if (config.macros.loadTiddlers)  {
    			out+='<input type="button" value="revert" \
    				title="import the last saved version of this tiddler" \
    				onclick="var v=this.form.list.value; if (!v.length) return; \
    					var t=\'<\'+\'<loadTiddlers [[tiddler:\'+v+\']] \'; \
    					t+=document.location.href; \
    					t+=\' confirm force noreport>\'+\'>\'; \
    					var e=document.getElementById(\'executeRevert\'); \
    					if (e) e.parentNode.removeChild(e); \
    					e=document.createElement(\'span\'); \
    					e.id=\'executeRevert\'; \
    					wikify(t,e);">';
    		}
    		out+='</form></html>';
    		if (!readOnly) {
    			out+='\n{{small nowrap{';
    			out+="<<saveChanges>>";
    			out+=config.macros.saveAs?" | <<saveAs>>":"";
    			out+=config.macros.upload?" | <<upload>>":"";
    			out+=(config.macros.emptyTrash&&store.getTaggedTiddlers("Trash").length)?" | <<emptyTrash>>":"";
    			out+='}}}';
    		}
    		out+=NSP?'===':'';
    		wikify(out,place);
    	}
    };

    // hijack store.saveTiddler() to track changes to tiddlers
    if (store.showUnsaved_saveTiddler==undefined) {
    	store.showUnsaved_saveTiddler=store.saveTiddler;
    	store.saveTiddler=function(title,newtitle) {
    		if (title!=newtitle) {
    			var i=config.macros.unsavedChanges.changed.indexOf(title);
    			if (i!=-1) config.macros.unsavedChanges.changed.splice(i,1); // remove old from list
    		}
    		var i=config.macros.unsavedChanges.changed.indexOf(newtitle);
    		if (i!=-1) config.macros.unsavedChanges.changed.splice(i,1); // remove new title from list
    		config.macros.unsavedChanges.changed.push(newtitle); // add new title to END of list
    		var t=this.showUnsaved_saveTiddler.apply(this,arguments);
    		if (!this.notificationLevel) config.macros.unsavedChanges.refresh();
    		return t;
    	}
    }

    // hijack store.removeTiddler() to track changes to tiddlers
    if (store.showUnsaved_removeTiddler==undefined) {
    	store.showUnsaved_removeTiddler=store.removeTiddler;
    	store.removeTiddler=function(title) {
    		var i=config.macros.unsavedChanges.changed.indexOf(title);
    		if (i!=-1) config.macros.unsavedChanges.changed.splice(i,1); // remove from list
    		this.showUnsaved_removeTiddler.apply(this,arguments);
    		if (!this.notificationLevel) config.macros.unsavedChanges.refresh();
    	}
    }

    // hijack store.setDirty() function to reset change list after file save
    // note: do NOT hijack the prototype function.  This hijack should only be applied to
    // the main 'store' instance only (i.e., don't refresh when loading temporary store
    // as part of ImportTiddlers processing)
    if (store.showUnsaved_setDirty==undefined) {
    	store.showUnsaved_setDirty=store.setDirty;
    	store.setDirty = function(flag) {
    		var refresh=this.isDirty() && !flag; // 'dirty' to 'clean', force a refresh...
    		this.showUnsaved_setDirty.apply(this,arguments); // but change the flag first.
    		if (refresh) {
    			config.macros.unsavedChanges.changed=[]; // clear changed list
    			config.macros.unsavedChanges.refresh();
    		}
    	}
    }
    //}}}

    | !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |
    | 24/11/2010 15:46:50 | Lance | [[wsdzh.html|file:///E:/LiveMeshShare/notes/wsdzh.html]] | [[SaveTiddlyWiki.php|http://bbs.gamediy.net/SaveTiddlyWiki.php]] | . | [[wsdzh.html | http://bbs.gamediy.net/wsdzh.html]] |  | failed |
    | 24/11/2010 15:47:15 | Lance | [[wsdzh.html|file:///E:/LiveMeshShare/notes/wsdzh.html]] | [[SaveTiddlyWiki.php|http://bbs.gamediy.net/SaveTiddlyWiki.php]] | . | [[wsdzh.html | http://bbs.gamediy.net/wsdzh.html]] |  | failed |
    | 24/11/2010 15:49:46 | Lance | [[wsdzh.html|file:///E:/LiveMeshShare/notes/wsdzh.html]] | [[SaveTiddlyWiki.php|http://bbs.gamediy.net/SaveTiddlyWiki.php]] | . | [[wsdzh.html | http://bbs.gamediy.net/wsdzh.html]] |  | failed |

    /***
    |''Name:''|UploadPlugin|
    |''Description:''|Save to web a TiddlyWiki|
    |''Version:''|4.1.3|
    |''Date:''|Feb 24, 2008|
    |''Source:''|http://tiddlywiki.bidix.info/#UploadPlugin|
    |''Documentation:''|http://tiddlywiki.bidix.info/#UploadPluginDoc|
    |''Author:''|BidiX (BidiX (at) bidix (dot) info)|
    |''License:''|[[BSD open source license|http://tiddlywiki.bidix.info/#%5B%5BBSD%20open%20source%20license%5D%5D ]]|
    |''~CoreVersion:''|2.2.0|
    |''Requires:''|PasswordOptionPlugin|
    ***/
    //{{{
    version.extensions.UploadPlugin = {
    	major: 4, minor: 1, revision: 3,
    	date: new Date("Feb 24, 2008"),
    	source: 'http://tiddlywiki.bidix.info/#UploadPlugin',
    	author: 'BidiX (BidiX (at) bidix (dot) info',
    	coreVersion: '2.2.0'
    };

    //
    // Environment
    //

    if (!window.bidix) window.bidix = {}; // bidix namespace
    bidix.debugMode = false;	// true to activate both in Plugin and UploadService

    //
    // Upload Macro
    //

    config.macros.upload = {
    // default values
    	defaultBackupDir: '',	//no backup
    	defaultStoreScript: "store.php",
    	defaultToFilename: "index.html",
    	defaultUploadDir: ".",
    	authenticateUser: true	// UploadService Authenticate User
    };

    config.macros.upload.label = {
    	promptOption: "Save and Upload this TiddlyWiki with UploadOptions",
    	promptParamMacro: "Save and Upload this TiddlyWiki in %0",
    	saveLabel: "save to web",
    	saveToDisk: "save to disk",
    	uploadLabel: "upload"
    };

    config.macros.upload.messages = {
    	noStoreUrl: "No store URL in parmeters or options",
    	usernameOrPasswordMissing: "Username or password missing"
    };

    config.macros.upload.handler = function(place,macroName,params) {
    	if (readOnly)
    		return;
    	var label;
    	if (document.location.toString().substr(0,4) == "http")
    		label = this.label.saveLabel;
    	else
    		label = this.label.uploadLabel;
    	var prompt;
    	if (params[0]) {
    		prompt = this.label.promptParamMacro.toString().format([this.destFile(params[0],
    			(params[1] ? params[1]:bidix.basename(window.location.toString())), params[3])]);
    	} else {
    		prompt = this.label.promptOption;
    	}
    	createTiddlyButton(place, label, prompt, function() {config.macros.upload.action(params);}, null, null, this.accessKey);
    };

    config.macros.upload.action = function(params)
    {
    		// for missing macro parameter set value from options
    		if (!params) params = {};
    		var storeUrl = params[0] ? params[0] : config.options.txtUploadStoreUrl;
    		var toFilename = params[1] ? params[1] : config.options.txtUploadFilename;
    		var backupDir = params[2] ? params[2] : config.options.txtUploadBackupDir;
    		var uploadDir = params[3] ? params[3] : config.options.txtUploadDir;
    		var username = params[4] ? params[4] : config.options.txtUploadUserName;
    		var password = config.options.pasUploadPassword; // for security reason no password as macro parameter
    		// for still missing parameter set default value
    		if ((!storeUrl) && (document.location.toString().substr(0,4) == "http"))
    			storeUrl = bidix.dirname(document.location.toString())+'/'+config.macros.upload.defaultStoreScript;
    		if (storeUrl.substr(0,4) != "http")
    			storeUrl = bidix.dirname(document.location.toString()) +'/'+ storeUrl;
    		if (!toFilename)
    			toFilename = bidix.basename(window.location.toString());
    		if (!toFilename)
    			toFilename = config.macros.upload.defaultToFilename;
    		if (!uploadDir)
    			uploadDir = config.macros.upload.defaultUploadDir;
    		if (!backupDir)
    			backupDir = config.macros.upload.defaultBackupDir;
    		// report error if still missing
    		if (!storeUrl) {
    			alert(config.macros.upload.messages.noStoreUrl);
    			clearMessage();
    			return false;
    		}
    		if (config.macros.upload.authenticateUser && (!username || !password)) {
    			alert(config.macros.upload.messages.usernameOrPasswordMissing);
    			clearMessage();
    			return false;
    		}
    		bidix.upload.uploadChanges(false,null,storeUrl, toFilename, uploadDir, backupDir, username, password);
    		return false;
    };

    config.macros.upload.destFile = function(storeUrl, toFilename, uploadDir)
    {
    	if (!storeUrl)
    		return null;
    		var dest = bidix.dirname(storeUrl);
    		if (uploadDir && uploadDir != '.')
    			dest = dest + '/' + uploadDir;
    		dest = dest + '/' + toFilename;
    	return dest;
    };

    //
    // uploadOptions Macro
    //

    config.macros.uploadOptions = {
    	handler: function(place,macroName,params) {
    		var wizard = new Wizard();
    		wizard.createWizard(place,this.wizardTitle);
    		wizard.addStep(this.step1Title,this.step1Html);
    		var markList = wizard.getElement("markList");
    		var listWrapper = document.createElement("div");
    		markList.parentNode.insertBefore(listWrapper,markList);
    		wizard.setValue("listWrapper",listWrapper);
    		this.refreshOptions(listWrapper,false);
    		var uploadCaption;
    		if (document.location.toString().substr(0,4) == "http")
    			uploadCaption = config.macros.upload.label.saveLabel;
    		else
    			uploadCaption = config.macros.upload.label.uploadLabel;

    		wizard.setButtons([
    				{caption: uploadCaption, tooltip: config.macros.upload.label.promptOption,
    					onClick: config.macros.upload.action},
    				{caption: this.cancelButton, tooltip: this.cancelButtonPrompt, onClick: this.onCancel}

    			]);
    	},
    	options: [
    		"txtUploadUserName",
    		"pasUploadPassword",
    		"txtUploadStoreUrl",
    		"txtUploadDir",
    		"txtUploadFilename",
    		"txtUploadBackupDir",
    		"chkUploadLog",
    		"txtUploadLogMaxLine"
    	],
    	refreshOptions: function(listWrapper) {
    		var opts = [];
    		for(i=0; i<this.options.length; i++) {
    			var opt = {};
    			opts.push();
    			opt.option = "";
    			n = this.options[i];
    			opt.name = n;
    			opt.lowlight = !config.optionsDesc[n];
    			opt.description = opt.lowlight ? this.unknownDescription : config.optionsDesc[n];
    			opts.push(opt);
    		}
    		var listview = ListView.create(listWrapper,opts,this.listViewTemplate);
    		for(n=0; n<opts.length; n++) {
    			var type = opts[n].name.substr(0,3);
    			var h = config.macros.option.types[type];
    			if (h && h.create) {
    				h.create(opts[n].colElements['option'],type,opts[n].name,opts[n].name,"no");
    			}
    		}

    	},
    	onCancel: function(e)
    	{
    		backstage.switchTab(null);
    		return false;
    	},

    	wizardTitle: "Upload with options",
    	step1Title: "These options are saved in cookies in your browser",
    	step1Html: "<input type='hidden' name='markList'></input><br>",
    	cancelButton: "Cancel",
    	cancelButtonPrompt: "Cancel prompt",
    	listViewTemplate: {
    		columns: [
    			{name: 'Description', field: 'description', title: "Description", type: 'WikiText'},
    			{name: 'Option', field: 'option', title: "Option", type: 'String'},
    			{name: 'Name', field: 'name', title: "Name", type: 'String'}
    			],
    		rowClasses: [
    			{className: 'lowlight', field: 'lowlight'}
    			]}
    };

    //
    // upload functions
    //

    if (!bidix.upload) bidix.upload = {};

    if (!bidix.upload.messages) bidix.upload.messages = {
    	//from saving
    	invalidFileError: "The original file '%0' does not appear to be a valid TiddlyWiki",
    	backupSaved: "Backup saved",
    	backupFailed: "Failed to upload backup file",
    	rssSaved: "RSS feed uploaded",
    	rssFailed: "Failed to upload RSS feed file",
    	emptySaved: "Empty template uploaded",
    	emptyFailed: "Failed to upload empty template file",
    	mainSaved: "Main TiddlyWiki file uploaded",
    	mainFailed: "Failed to upload main TiddlyWiki file. Your changes have not been saved",
    	//specific upload
    	loadOriginalHttpPostError: "Can't get original file",
    	aboutToSaveOnHttpPost: 'About to upload on %0 ...',
    	storePhpNotFound: "The store script '%0' was not found."
    };

    bidix.upload.uploadChanges = function(onlyIfDirty,tiddlers,storeUrl,toFilename,uploadDir,backupDir,username,password)
    {
    	var callback = function(status,uploadParams,original,url,xhr) {
    		if (!status) {
    			displayMessage(bidix.upload.messages.loadOriginalHttpPostError);
    			return;
    		}
    		if (bidix.debugMode)
    			alert(original.substr(0,500)+"\n...");
    		// Locate the storeArea div's
    		var posDiv = locateStoreArea(original);
    		if((posDiv[0] == -1) || (posDiv[1] == -1)) {
    			alert(config.messages.invalidFileError.format([localPath]));
    			return;
    		}
    		bidix.upload.uploadRss(uploadParams,original,posDiv);
    	};

    	if(onlyIfDirty && !store.isDirty())
    		return;
    	clearMessage();
    	// save on localdisk ?
    	if (document.location.toString().substr(0,4) == "file") {
    		var path = document.location.toString();
    		var localPath = getLocalPath(path);
    		saveChanges();
    	}
    	// get original
    	var uploadParams = new Array(storeUrl,toFilename,uploadDir,backupDir,username,password);
    	var originalPath = document.location.toString();
    	// If url is a directory : add index.html
    	if (originalPath.charAt(originalPath.length-1) == "/")
    		originalPath = originalPath + "index.html";
    	var dest = config.macros.upload.destFile(storeUrl,toFilename,uploadDir);
    	var log = new bidix.UploadLog();
    	log.startUpload(storeUrl, dest, uploadDir,  backupDir);
    	displayMessage(bidix.upload.messages.aboutToSaveOnHttpPost.format([dest]));
    	if (bidix.debugMode)
    		alert("about to execute Http - GET on "+originalPath);
    	var r = doHttp("GET",originalPath,null,null,username,password,callback,uploadParams,null);
    	if (typeof r == "string")
    		displayMessage(r);
    	return r;
    };

    bidix.upload.uploadRss = function(uploadParams,original,posDiv)
    {
    	var callback = function(status,params,responseText,url,xhr) {
    		if(status) {
    			var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
    			displayMessage(bidix.upload.messages.rssSaved,bidix.dirname(url)+'/'+destfile);
    			bidix.upload.uploadMain(params[0],params[1],params[2]);
    		} else {
    			displayMessage(bidix.upload.messages.rssFailed);
    		}
    	};
    	// do uploadRss
    	if(config.options.chkGenerateAnRssFeed) {
    		var rssPath = uploadParams[1].substr(0,uploadParams[1].lastIndexOf(".")) + ".xml";
    		var rssUploadParams = new Array(uploadParams[0],rssPath,uploadParams[2],'',uploadParams[4],uploadParams[5]);
    		var rssString = generateRss();
    		// no UnicodeToUTF8 conversion needed when location is "file" !!!
    		if (document.location.toString().substr(0,4) != "file")
    			rssString = convertUnicodeToUTF8(rssString);
    		bidix.upload.httpUpload(rssUploadParams,rssString,callback,Array(uploadParams,original,posDiv));
    	} else {
    		bidix.upload.uploadMain(uploadParams,original,posDiv);
    	}
    };

    bidix.upload.uploadMain = function(uploadParams,original,posDiv)
    {
    	var callback = function(status,params,responseText,url,xhr) {
    		var log = new bidix.UploadLog();
    		if(status) {
    			// if backupDir specified
    			if ((params[3]) && (responseText.indexOf("backupfile:") > -1))  {
    				var backupfile = responseText.substring(responseText.indexOf("backupfile:")+11,responseText.indexOf("\n", responseText.indexOf("backupfile:")));
    				displayMessage(bidix.upload.messages.backupSaved,bidix.dirname(url)+'/'+backupfile);
    			}
    			var destfile = responseText.substring(responseText.indexOf("destfile:")+9,responseText.indexOf("\n", responseText.indexOf("destfile:")));
    			displayMessage(bidix.upload.messages.mainSaved,bidix.dirname(url)+'/'+destfile);
    			store.setDirty(false);
    			log.endUpload("ok");
    		} else {
    			alert(bidix.upload.messages.mainFailed);
    			displayMessage(bidix.upload.messages.mainFailed);
    			log.endUpload("failed");
    		}
    	};
    	// do uploadMain
    	var revised = bidix.upload.updateOriginal(original,posDiv);
    	bidix.upload.httpUpload(uploadParams,revised,callback,uploadParams);
    };

    bidix.upload.httpUpload = function(uploadParams,data,callback,params)
    {
    	var localCallback = function(status,params,responseText,url,xhr) {
    		url = (url.indexOf("nocache=") < 0 ? url : url.substring(0,url.indexOf("nocache=")-1));
    		if (xhr.status == 404)
    			alert(bidix.upload.messages.storePhpNotFound.format([url]));
    		if ((bidix.debugMode) || (responseText.indexOf("Debug mode") >= 0 )) {
    			alert(responseText);
    			if (responseText.indexOf("Debug mode") >= 0 )
    				responseText = responseText.substring(responseText.indexOf("\n\n")+2);
    		} else if (responseText.charAt(0) != '0')
    			alert(responseText);
    		if (responseText.charAt(0) != '0')
    			status = null;
    		callback(status,params,responseText,url,xhr);
    	};
    	// do httpUpload
    	var boundary = "---------------------------"+"AaB03x";
    	var uploadFormName = "UploadPlugin";
    	// compose headers data
    	var sheader = "";
    	sheader += "--" + boundary + "\r\nContent-disposition: form-data; name=\"";
    	sheader += uploadFormName +"\"\r\n\r\n";
    	sheader += "backupDir="+uploadParams[3] +
    				";user=" + uploadParams[4] +
    				";password=" + uploadParams[5] +
    				";uploaddir=" + uploadParams[2];
    	if (bidix.debugMode)
    		sheader += ";debug=1";
    	sheader += ";;\r\n";
    	sheader += "\r\n" + "--" + boundary + "\r\n";
    	sheader += "Content-disposition: form-data; name=\"userfile\"; filename=\""+uploadParams[1]+"\"\r\n";
    	sheader += "Content-Type: text/html;charset=UTF-8" + "\r\n";
    	sheader += "Content-Length: " + data.length + "\r\n\r\n";
    	// compose trailer data
    	var strailer = new String();
    	strailer = "\r\n--" + boundary + "--\r\n";
    	data = sheader + data + strailer;
    	if (bidix.debugMode) alert("about to execute Http - POST on "+uploadParams[0]+"\n with \n"+data.substr(0,500)+ " ... ");
    	var r = doHttp("POST",uploadParams[0],data,"multipart/form-data; ;charset=UTF-8; boundary="+boundary,uploadParams[4],uploadParams[5],localCallback,params,null);
    	if (typeof r == "string")
    		displayMessage(r);
    	return r;
    };

    // same as Saving's updateOriginal but without convertUnicodeToUTF8 calls
    bidix.upload.updateOriginal = function(original, posDiv)
    {
    	if (!posDiv)
    		posDiv = locateStoreArea(original);
    	if((posDiv[0] == -1) || (posDiv[1] == -1)) {
    		alert(config.messages.invalidFileError.format([localPath]));
    		return;
    	}
    	var revised = original.substr(0,posDiv[0] + startSaveArea.length) + "\n" +
    				store.allTiddlersAsHtml() + "\n" +
    				original.substr(posDiv[1]);
    	var newSiteTitle = getPageTitle().htmlEncode();
    	revised = revised.replaceChunk("<title"+">","</title"+">"," " + newSiteTitle + " ");
    	revised = updateMarkupBlock(revised,"PRE-HEAD","MarkupPreHead");
    	revised = updateMarkupBlock(revised,"POST-HEAD","MarkupPostHead");
    	revised = updateMarkupBlock(revised,"PRE-BODY","MarkupPreBody");
    	revised = updateMarkupBlock(revised,"POST-SCRIPT","MarkupPostBody");
    	return revised;
    };

    //
    // UploadLog
    //
    // config.options.chkUploadLog :
    //		false : no logging
    //		true : logging
    // config.options.txtUploadLogMaxLine :
    //		-1 : no limit
    //      0 :  no Log lines but UploadLog is still in place
    //		n :  the last n lines are only kept
    //		NaN : no limit (-1)

    bidix.UploadLog = function() {
    	if (!config.options.chkUploadLog)
    		return; // this.tiddler = null
    	this.tiddler = store.getTiddler("UploadLog");
    	if (!this.tiddler) {
    		this.tiddler = new Tiddler();
    		this.tiddler.title = "UploadLog";
    		this.tiddler.text = "| !date | !user | !location | !storeUrl | !uploadDir | !toFilename | !backupdir | !origin |";
    		this.tiddler.created = new Date();
    		this.tiddler.modifier = config.options.txtUserName;
    		this.tiddler.modified = new Date();
    		store.addTiddler(this.tiddler);
    	}
    	return this;
    };

    bidix.UploadLog.prototype.addText = function(text) {
    	if (!this.tiddler)
    		return;
    	// retrieve maxLine when we need it
    	var maxLine = parseInt(config.options.txtUploadLogMaxLine,10);
    	if (isNaN(maxLine))
    		maxLine = -1;
    	// add text
    	if (maxLine != 0)
    		this.tiddler.text = this.tiddler.text + text;
    	// Trunck to maxLine
    	if (maxLine >= 0) {
    		var textArray = this.tiddler.text.split('\n');
    		if (textArray.length > maxLine + 1)
    			textArray.splice(1,textArray.length-1-maxLine);
    			this.tiddler.text = textArray.join('\n');
    	}
    	// update tiddler fields
    	this.tiddler.modifier = config.options.txtUserName;
    	this.tiddler.modified = new Date();
    	store.addTiddler(this.tiddler);
    	// refresh and notifiy for immediate update
    	story.refreshTiddler(this.tiddler.title);
    	store.notify(this.tiddler.title, true);
    };

    bidix.UploadLog.prototype.startUpload = function(storeUrl, toFilename, uploadDir,  backupDir) {
    	if (!this.tiddler)
    		return;
    	var now = new Date();
    	var text = "\n| ";
    	var filename = bidix.basename(document.location.toString());
    	if (!filename) filename = '/';
    	text += now.formatString("0DD/0MM/YYYY 0hh:0mm:0ss") +" | ";
    	text += config.options.txtUserName + " | ";
    	text += "[["+filename+"|"+location + "]] |";
    	text += " [[" + bidix.basename(storeUrl) + "|" + storeUrl + "]] | ";
    	text += uploadDir + " | ";
    	text += "[[" + bidix.basename(toFilename) + " | " +toFilename + "]] | ";
    	text += backupDir + " |";
    	this.addText(text);
    };

    bidix.UploadLog.prototype.endUpload = function(status) {
    	if (!this.tiddler)
    		return;
    	this.addText(" "+status+" |");
    };

    //
    // Utilities
    //

    bidix.checkPlugin = function(plugin, major, minor, revision) {
    	var ext = version.extensions[plugin];
    	if (!
    		(ext  &&
    			((ext.major > major) ||
    			((ext.major == major) && (ext.minor > minor))  ||
    			((ext.major == major) && (ext.minor == minor) && (ext.revision >= revision))))) {
    			// write error in PluginManager
    			if (pluginInfo)
    				pluginInfo.log.push("Requires " + plugin + " " + major + "." + minor + "." + revision);
    			eval(plugin); // generate an error : "Error: ReferenceError: xxxx is not defined"
    	}
    };

    bidix.dirname = function(filePath) {
    	if (!filePath)
    		return;
    	var lastpos;
    	if ((lastpos = filePath.lastIndexOf("/")) != -1) {
    		return filePath.substring(0, lastpos);
    	} else {
    		return filePath.substring(0, filePath.lastIndexOf("\\"));
    	}
    };

    bidix.basename = function(filePath) {
    	if (!filePath)
    		return;
    	var lastpos;
    	if ((lastpos = filePath.lastIndexOf("#")) != -1)
    		filePath = filePath.substring(0, lastpos);
    	if ((lastpos = filePath.lastIndexOf("/")) != -1) {
    		return filePath.substring(lastpos + 1);
    	} else
    		return filePath.substring(filePath.lastIndexOf("\\")+1);
    };

    bidix.initOption = function(name,value) {
    	if (!config.options[name])
    		config.options[name] = value;
    };

    //
    // Initializations
    //

    // require PasswordOptionPlugin 1.0.1 or better
    bidix.checkPlugin("PasswordOptionPlugin", 1, 0, 1);

    // styleSheet
    setStylesheet('.txtUploadStoreUrl, .txtUploadBackupDir, .txtUploadDir {width: 22em;}',"uploadPluginStyles");

    //optionsDesc
    merge(config.optionsDesc,{
    	txtUploadStoreUrl: "Url of the UploadService script (default: store.php)",
    	txtUploadFilename: "Filename of the uploaded file (default: in index.html)",
    	txtUploadDir: "Relative Directory where to store the file (default: . (downloadService directory))",
    	txtUploadBackupDir: "Relative Directory where to backup the file. If empty no backup. (default: ''(empty))",
    	txtUploadUserName: "Upload Username",
    	pasUploadPassword: "Upload Password",
    	chkUploadLog: "do Logging in UploadLog (default: true)",
    	txtUploadLogMaxLine: "Maximum of lines in UploadLog (default: 10)"
    });

    // Options Initializations
    bidix.initOption('txtUploadStoreUrl','');
    bidix.initOption('txtUploadFilename','');
    bidix.initOption('txtUploadDir','');
    bidix.initOption('txtUploadBackupDir','');
    bidix.initOption('txtUploadUserName','');
    bidix.initOption('pasUploadPassword','');
    bidix.initOption('chkUploadLog',true);
    bidix.initOption('txtUploadLogMaxLine','10');

    // Backstage
    merge(config.tasks,{
    	uploadOptions: {text: "upload", tooltip: "Change UploadOptions and Upload", content: '<<uploadOptions>>'}
    });
    config.backstageTasks.push("uploadOptions");

    //}}}

    <!--{{{-->
    <div class='toolbar' macro='toolbar [[ToolbarCommands::ViewToolbar]]'></div>
    <span class='title' macro='view title'></span>
    <span macro='tiddler AddANote if:{{!readOnly && store.tiddlerExists(story.findContainingTiddler(place).getAttribute("tiddler")) && tiddler && tiddler.tags.containsAny(["annotate", "bookmark", "journal", "blog"])}} with: {{tiddler?tiddler.title:""}}'></span>
    <div class='subtitle fine'><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='tagClear'></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' style='line-height:100%;margin-top:.5em;'><a href="javascript:;"
    	onclick="window.scrollTo(0,ensureVisible(story.findContainingTiddler(this)));return false;"
    	onmouseover="this.title='scroll to top of '+story.findContainingTiddler(this).getAttribute('tiddler')">&#x25b2;</a>
    </div>
    <div class='tagClear'></div>
    <!--}}}-->

    /***
    |Name|WikifyPlugin|
    |Source|http://www.TiddlyTools.com/#WikifyPlugin|
    |Documentation|http://www.TiddlyTools.com/#WikifyPluginInfo|
    |Version|1.1.4|
    |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|substitute fields, slices, or computed values into a wiki-syntax format string and render results dynamically|
    The {{{<<wikify>>}}} macro allows you to easily retrieve values from custom tiddler fields, tiddler slices, computed values (using javascript) or just plain old literals, and assemble them into small bits of generated wiki-syntax text content that can be rendered directly into a tiddler, or used in the ViewTemplate or EditTemplate to add dynamically-generated content to each tiddler.

    The {{{<<wikiCalc>>}}} macro performs the same processing as {{{<<wikify>>}}} and, in addition, passes the assembled text content through javascript's {{{eval()}}} function before rendering the results.  This allows you to, for example, construct and compute mathematical expressions that use input values extracted from tiddler fields or slices.
    !!!!!Documentation
    > see [[WikifyPluginInfo]]
    !!!!!Revisions
    <<<
    2009.03.29 [1.1.4] in handler(), pass 'tiddler' value to wikify() to fix macro errors in rendered content
    |please see [[WikifyPluginInfo]] for additional revision details|
    2007.06.22 [1.0.0] initial release
    <<<
    !!!!!Code
    ***/
    //{{{
    version.extensions.WikifyPlugin= {major: 1, minor: 1, revision: 4, date: new Date(2009,3,29)};

    config.macros.wikify={
    	handler: function(place,macroName,params,wikifier,paramString,tiddler) {
    		var fmt=params.shift();
    		var values=[];
    		var out="";
    		if (!fmt.match(/\%[0-9]/g) && params.length) // format has no markers, just join all params with spaces
    			out=fmt+" "+params.join(" ");
    		else { // format param has markers, get values and perform substitution
    			while (p=params.shift()) values.push(this.getFieldReference(place,p));
    			out=fmt.format(values);
    		}
    		if (macroName=="wikiCalc") out=eval(out).toString();
    		wikify(out.unescapeLineBreaks(),place,null,tiddler);
    	},
    	getFieldReference: function(place,p) { // "slicename::tiddlername" or "fieldname@tiddlername" or "fieldname"
    		if (typeof p != "string") return p; // literal non-string value... just return it...
    		var parts=p.split(config.textPrimitives.sliceSeparator);
    		if (parts.length==2) {// maybe a slice reference?
    			var tid=parts[0]; var slice=parts[1];
    			if (!tid || !tid.length || tid=="here") { // no target (or "here"), use containing tiddler
    				tid=story.findContainingTiddler(place);
    				if (tid) tid=tid.getAttribute("tiddler")
    				else tid="SiteSlices"; // fallback for 'non-tiddler' areas (e.g, header, sidebar, etc.)
    			}
    			var val=store.getTiddlerSlice(tid,slice);  // get tiddler slice value
    		}
    		if (val==undefined) {// not a slice, or slice not found, maybe a field reference?
    			var parts=p.split("@");
    			var field=parts[0];
    			if (!field || !field.length) field="checked"; // missing fieldname, fallback: checked@tiddlername
    			var tid=parts[1];
    			if (!tid || !tid.length || tid=="here") { // no target (or "here"), use containing tiddler
    				tid=story.findContainingTiddler(place);
    				if (tid) tid=tid.getAttribute("tiddler")
    				else tid="SiteFields"; // fallback for 'non-tiddler' areas (e.g, header, sidebar, etc.)
    			}
    			var val=store.getValue(tid,field);
    		}
    		// not a slice or field, or slice/field not found... return value unchanged
    		return val===undefined?p:val;
    	}
    }
    //}}}
    //{{{
    // define alternative macroName for triggering pre-rendering call to eval()
    config.macros.wikiCalc=config.macros.wikify;
    //}}}

    ! config.txt (设置.txt) 详解
    config.txt中主要设置游戏中的一些默认值.由于所有值都有预设值,所以即使该文件完全为空,游戏也能正常运行...

    !! 一般设置

    !!! 游戏名称(gameTitle)
    设置游戏名称.预设为空.

    !!! 窗口宽度(winWidth)
    设置游戏窗口宽度.预设为 800

    !!! 窗口高度(winHeight)
    设置游戏窗口高度.预设为 600

    !!! 全屏模式(fullscreen)
    启动时是否全屏显示.0为窗口模式,1为全屏模式.预设为 0

    !!! 光标(cursorFile)
    设置游戏中要用的光标.支持.cur和.ani文件格式

    !! 文本字体相关

    !!! 文本字体(textFont)
    游戏中使用的文本字体,格式为 ('字体名', 字体大小).预设值为 ('微软雅黑', 22)
    WEB版中该设置无效果

    !!! 文本颜色(textColor)
    游戏中使用的默认字体颜色.预设值为 (255,255,255)
    注意这个设置只能影响默认角色和分支菜单里面的文字颜色,因为每个角色都可以自定义文字颜色.

    !! 文本框相关

    !!! 文本框Y(textBoxY)
    主文本框Y坐标.预设值为 590 (下边沿距离窗口为10像素)
    主文本框X坐标预设为居中.
    注意每个角色可以定义自己的文本框位置.

    !!! 文本框背景图(textBoxImage)
    主文本框的背景图.预设值为 '界面\\对话框1.png'.注意每个角色可以定义自己的文本框背景图.

    !!! 名称框背景图(nameBoxImage)
    角色名称的背景图.预设值为 '界面\\名称框1.png'

    !! 分支菜单相关

    !!! 菜单Y(menuY)
    分支菜单第一个选项上边沿的Y坐标.预设为200

    !!! 菜单Y间距(menuYGap)
    分支菜单在Y方向之间的间距.预设为20

    !!! 菜单背景图(menuImage)
    分支菜单的背景图.预设为 '界面\\选项框1.png'

    !! 系统设置相关

    !!! 允许回退(allowRollback)
    默认值为True,即默认允许回退.使用
    allowRollback = False
    来屏蔽回退功能

    !!! 自动过渡(autoTransition)
    对背景和立绘的切换使用平滑过渡.默认过渡时间为0.1秒.
    可以调整该值以获得最满意的效果.设置为0会关闭自动平滑过渡功能.

    !!! 音乐自动过渡(musicAutoTransition)
    对背景音乐使用渐变.默认渐变时间为1秒.
    可以调整该值以获得最满意的效果.设置为0会关闭音乐自动过渡功能.

    ----
    +++[展开示例config.txt文件]>
    游戏名称 = "我的超级大坑"

    窗口宽度 = 800
    窗口高度 = 600

    文本字体 = ("黑体", 22)
    文本颜色 = (0,0,0)

    文本框背景图 = "界面\\对话框1.png"
    名称框背景图 = "界面\\名称框1.png"
    菜单背景图 = "界面\\选项框1.png"
    菜单Y = 40

    允许回退 = True

    光标 = "系统\\cursor.ani"
    ===

    //{{{

    // set readOnly to true or false in each of the following lines...
    readOnly=false; // default for all visitors
    if (document.location.protocol=='file:') readOnly=false; // local editing
    if (config.options.txtUserName=='ENTER_YOUR_NAME_HERE') readOnly=false; // you!

    config.options.txtMaxEditRows="20"; // TW core option
    config.options.chkInsertTabs=true; // TW core option
    config.options.chkShowLeftSidebar=true; // ToggleLeftSidebar
    config.options.chkShowRightSidebar=false; // ToggleRightSidebar
    config.options.chkStoryFold=true; // StorySaverPlugin
    //}}}

    /***
    |''Name:''|zh-HansTranslationPlugin|
    |''Description:''|Translation of TiddlyWiki into Simply Chinese|
    |''Source:''|http://tiddlywiki-zh.googlecode.com/svn/trunk/|
    |''Subversion:''|http://svn.tiddlywiki.org/Trunk/association/locales/core/zh-Hans/locale.zh-Hans.js|
    |''Author:''|BramChen (bram.chen (at) gmail (dot) com)|
    |''Version:''|2.4.1|
    |''Date:''|Jul 28, 2008|
    |''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.4.1|
    ***/

    //{{{
    // --
    // -- Translateable strings
    // --

    // Strings in "double quotes" should be translated; strings in 'single quotes' should be left alone

    config.locale = 'zh-Hans'; // W3C language tag
    config.options.txtFileSystemCharSet = 'GBK';

    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>>'},
    	upgrade: {text: "更新", tooltip: "更新 TiddlyWiki 核心程序", content: '<<upgrade>>'},
    	plugins: {text: "插件管理", tooltip: "管理已安装的插件", content: '<<plugins>>'}
    });

    merge(config.optionsDesc,{
    	txtUserName: "编辑文章所使用之作者署名",
    	chkRegExpSearch: "启用正则式查找",
    	chkCaseSensitiveSearch: "查找时，区分大小写",
    	chkIncrementalSearch: "随打即找搜寻",
    	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'",
    	upgradeDone: "已更新至 %0 版\n\n点击 '确定' 重新载入更新后的 TiddlyWiki"});

    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 = ["一", "二", "三", "四", "五", "六", "七", "八", "九", "十", "十一", "十二"];
    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: 'systemConfigDisable', 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: "正在取得可用之文章清单",
    	errorGettingTiddlerList: "取得文章清单时发生错误，请点选“取消”后重试。",
    	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.upgrade,{
    	wizardTitle: "更新 TiddlyWiki 核心程序",
    	step1Title: "更新或修补此 TiddlyWiki 至最新版本",
    	step1Html: "您将更新至最新版本的 TiddlyWiki 核心程序 (自 <a href='%0' class='externalLink' target='_blank'>%1</a>)。 在更新过程中，您的资料将被保留。<br><br>请注意：更新核心可能不相容于其他套件。若对更新的档案有问题，详见 <a href='http://www.tiddlywiki.org/wiki/CoreUpgrades' class='externalLink' target='_blank'>http://www.tiddlywiki.org/wiki/CoreUpgrades</a>",
    	errorCantUpgrade: "j无法更新此 TiddlyWiki. 您只能自本机端的 TiddlyWiki 文件执行更新程序",
    	errorNotSaved: "执行更新之前，请先保存变更",
    	step2Title: "确认更新步骤",
    	step2Html_downgrade: "您的 TiddlyWiki 将自 %1 版降级至 %0版<br><br>不建议降级至较旧的版本。",
    	step2Html_restore: "此 TiddlyWiki 核心已是最新版 (%0)。<br><br>您可以继续更新作业以确认核心程式未曾毁损。",
    	step2Html_upgrade: "您的 TiddlyWiki 将自 %1 版更新至 %0 版",	upgradeLabel: "更新",
    	upgradePrompt: "准备更新作业",
    	statusPreparingBackup: "准备备份中",
    	statusSavingBackup: "正在备份文件",
    	errorSavingBackup: "备份文件时发生问题",
    	statusLoadingCore: "核心程序载入中",
    	errorLoadingCore: "载入核心程序时，发生错误",
    	errorCoreFormat: "新版核心程序发生错误",
    	statusSavingCore: "正在保存新版核心程序",
    	statusReloadingCore: "新版核心程式载入中",
    	startLabel: "开始",
    	startPrompt: "开始更新作业",
    	cancelLabel: "取消",
    	cancelPrompt: "取消更新作业",
    	step3Title: "已取消更新作业",
    	step3Html: "您已取消更新作业"
    	});

    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>',
    	syncLabel: "同步",
    	syncPrompt: "同步更新这些文章",
    	hasChanged: "已更动",
    	hasNotChanged: "未更动",
    	syncStatusList: {
    		none: {text: "...", display:null, className:'notChanged'},
    		changedServer: {text: "服务器资料已更动", display:null, className:'changedServer'},
    		changedLocally: {text: "本机资料已更动", display:null, className:'changedLocally'},
    		changedBoth: {text: "已同时更新本机与服务器上的资料", display:null, className:'changedBoth'},
    		notFound: {text: "服务器无此资料", className:'notFound'},
    		putToServer: {text: "已储存更新资料至服务器", display:null, className:'putToServer'},
    		gotFromServer: {text: "已从服务器撷取更新资料", display:null, className:'gotFromServer'}
    		}
    	});

    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© 2008 [[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 "偏好设置 \u00bb" "变更 TiddlyWiki 选项">>',
    	SideBarTabs: '<<tabs txtMainTab "最近更新" "依更新日期排序" TabTimeline "全部" "所有文章" TabAll "分类" "所有标签" TabTags "更多" "其他" TabMore>>',
    	StyleSheet: '[[StyleSheetLocale]]',
    	TabMore: '<<tabs txtMoreTab "未完成" "内容空白的文章" TabMoreMissing "未引用" "未被引用的文章" TabMoreOrphans "默认文章" "默认的影子文章" TabMoreShadowed>>',
    	ToolbarCommands: "|~ViewToolbar|closeTiddler closeOthers +editTiddler > fields syncing permalink references jump|\n|~EditToolbar|+saveTiddler -cancelTiddler deleteTiddler|"});

    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: "此默认文章的内容，为于屏幕右侧的“最近更新”页签的内容",
    	ToolbarCommands: "此默认文章的内容，为显示于文章工具列之命令",
    	ViewTemplate: "此默认文章里的 HTML template 决定文章显示的样子"
    	});
    //}}}

    !!!!下一个圣诞
    介绍:http://bbs.gamediy.net/read.php?tid=803
    下载:http://gamediy.net/data/games/ds1/XiaYiGeShenDan.exe
    [img(320px,)[http://bbs.gamediy.net/attachment/Mon_1008/13_164_d1e4d913327ab76.jpg]]

    收录无双引擎及相关ACG资讯

    !!!!再见的日子
    介绍:http://bbs.gamediy.net/read.php?tid=3527
    下载:http://gamediy.net/data/games/ds1/ZaiJianDeRiZi.exe

    !!!!子虚赋
    [[WEB版 | http://ws.gamediy.net/?game=http://bbs.gamediy.net/job.php?action=download&aid=334]]
    介绍:http://bbs.gamediy.net/read.php?tid=3384
    下载:http://gamediy.net/data/games/ds1/ZiXuFu.exe
    [img(320px,)[http://bbs.gamediy.net/attachment/Mon_1007/13_312_0956c06916364df.png]]
    [img(320px,)[http://bbs.gamediy.net/attachment/Mon_1007/13_312_8ad48172127b55d.png]][img(320px,)[http://bbs.gamediy.net/attachment/Mon_1007/13_312_476b9e7898f2b8d.jpg]]
    [img(320px,)[http://bbs.gamediy.net/attachment/Mon_1007/13_312_ea109e5b0333637.jpg]][img(320px,)[http://bbs.gamediy.net/attachment/Mon_1007/13_312_41ddaca87954e85.png]]

    !!!!幻灵社
    [[WEB版 | http://ws.gamediy.net/?game=http://bbs.gamediy.net/job.php?action=download&aid=333]]
    介绍:http://bbs.gamediy.net/read.php?tid=3367
    下载:http://gamediy.net/data/games/ds1/HuanLinShe.exe
    [img(320px,)[http://img013.photo.21cn.com/photos/album/20100824/o/BAF98F5F0570EA5B1DBC0F725ACE5685.jpg]][img(320px,)[http://img013.photo.21cn.com/photos/album/20100824/o/012A3C886C6F1E9C4735CD2D2D4B241A.jpg]]

    论坛: http://bbs.gamediy.net/thread.php?fid=17

    这是万丈深渊的第一铲！——黑衣少年（相关资料整合，进度汇报楼）

    管理提醒: 本帖被 黑衣少年 执行置顶操作(2010-11-03)
    是坚信能够寻找到药物获得大团圆？还是趁早舍弃自己的伪善反而能够拯救最多的人？博弈和谜团在此纠缠……                 by 八月寒

    世界观：

    2012世界末日来到，人类为了存活建造了方舟。
    由于正确的预判提前预知了灾难的来临，
    在全世界建成了名为“方舟”的避难所，让全人类躲过这次浩劫。
    但是人类犯了两个错误：
    首先，科学家们太过于相信玛雅人的历法，而没有预估到灾难发生时间的误差。在人们毫无防备的时候，末日降临了。
    而更致命的是，人们太小看了末日的威力。
    原本计算得出的结论是能够致人死亡的宇宙射线会持续在全地球范围照射5天。
    但是末日到来之后根据现状得知，这种状态将会持续10天。
    【而在这10天里，不存在任何离开方舟的方法。】
    问题是，方舟内的某种生存必需品，即某种抵抗辐射的药物，每人只携带了5天份。
    现在的情况是，某一艘方舟里面，有着男主角和其他九个人。

    人物简介：

    白思贤——男主角。重点高中阳湾中学的一年级学生。性格温和乐天，但是有些我行我素，很少顾及他人的议论。总是喜欢用一种置身事外的态度观察和对待各种事情，不过其实内心是一个善良而温柔的烂好人。在感情问题上，是迟钝到无可救药的木头。

    黄彦麟——白思贤的损友兼高中同班同学。无可救药的笨蛋。擅长吐槽，同时也擅长装傻，虽然说完全无法确定他是在装傻还是真的傻……非常热血，认真起来的时候经常会做出一些让人意想不到的事情。

    南芝——白思贤的青梅竹马。同时也是阳湾中学的学生。典型的嘴硬心软型角色，稍微有些喜欢欺负人。对白思贤一直有着朦朦胧胧的好感，不过死活不愿意承认。在危险中比起自己，更优先考虑白思贤的安危。

    林劭丞——电脑公司的职员，有着一个幸福的家庭，因而脸上经常挂着微笑。他是一位待人和善的大叔。他在末日降临时幸运地躲进了白思贤所在的方舟。

    郭兰——林劭丞的妻子，职业是医生。白思贤在进入方舟的时候因为被照射了过量的宇宙射线而生命危急的时候是她进行的紧急处理，因此对白思贤来说是救命恩人一样的存在。虽然是职业女性，性格却是非常传统的全身心为家庭奉献的类型。和林劭丞的感情很好。她在末日降临时幸运地躲进了白思贤所在的方舟。

    林蔷——林劭丞和郭兰的女儿。活泼开朗天真可爱自来熟。她在末日降临时幸运地躲进了白思贤所在的方舟。

    舒羽——初中三年级学生，梦想是成为职业歌唱家的少女。目前担任校内业余乐队的歌手。容易害羞，有时甚至会因为太过腼腆而不能好好表达自己的意思。是一个很固执的人，对于决定了的事情，就会全心全意地去做。她在末日降临时幸运地躲进了白思贤所在的方舟。

    袁紫藤——初中三年级学生，舒羽的同学兼好友。校内业余乐队的吉他手，同时也是该乐队的经理人。她是国内著名家族企业源澄集团的董事长的独生女，也是财团唯一的继承人。特殊的身份和接受的教育使得她形成了不爱接近别人，不信任他人的带刺性格，特别是对男性有着强烈的恐惧。她在末日降临时幸运地躲进了白思贤所在的方舟。

    严晓乐——初中三年级学生，舒羽和袁紫藤的同学兼好友。校内业余乐队的鼓手，同时也是勤务工。她是一个很有活力的女孩，在团队中总是充当着开心果的角色。因为大大咧咧的性格，曾经被人说是“像个男孩子一样”，不过本人对此非常在意。她在末日降临时幸运地躲进了白思贤所在的方舟。

    以及原本获悉会上船，但是【到这时为止】却没有任何人发现其存在的，未知人物X。

    共通剧情概要：
    2012年12月13号（周四）下午，在所有人的预料之外，末日提前发生了。
    运气不错的男主角一行人捡回了一条命，逃进了一艘方舟。
    这艘原本预计能够容纳500人的船上，结果只有9人幸运登船了。这些幸存者们在船上度过了一段和乐融融的美好时光。互相自我介绍，畅谈未来梦想。【这时候顺便让读者了解一下人物性格XD】

    在闲谈中大家提到，曾经有新闻报道过之前有人提前入住不是自己被分配到的方舟，而这个怪人入住的方舟正是大家所在的这艘。然而不知为何，这人却从未在大家面前露过面。
    在莫名的疑惑的氛围里度过了一段平静的时间之后船上响起警报，告知所有人末日引起的辐射时间将从5天延长为10天。关于药物，播音员断言那是为了每天能够活下去的最低程度的保障，而因不可抗力造成缺少的部分，“无法详细说明，但是只要大家努力，可以保证一定会有解决的办法”。之后信号就中断了。
    大家经讨论后推测，可能是指船上某处还有备用的药物，而由于各艘船具体情况不同而由于信号的时间限制无法详细说明。所以大家就决定在船里寻找药物或者可以用的替代品。【而当大家发现这船里面的许多地方有武器的时候，虽然没有人说出来，但是心里都对“只要努力，保证一定会有解决的办法”有了另一种解释的方法。 】

    由于大家都对寻找备用的药物还抱有着希望，所以不准备动那些武器。但是这个时候有人提到了那个从来没有露过面的人x。因此，即使会破坏互相的信任，也都拿起了武器。

    至此共通部分结束。

    目前进度：大家畅谈未来梦想
    TXT文本大小：19039字节
    最后更新：2010年11月3日

    http://gamediy.net/wiki/doc/manual
    [[无双基础视频教程 | http://gamediy.net/wiki/doc/video]]
    [[下载最新版本的无双引擎 | http://code.google.com/p/wushuang/downloads/list]]

    !! 1 设计理念

    无双引擎是一款游戏制作工具.它现阶段的目标是使用者不需要掌握任何编程语言或外语,就可以轻松地制作出电子小说式AVG游戏.

    !! 2 制作思路

    无双引擎的目标是尽可能地降低电子小说的制作门槛,但这并不意味着制作电子小说从此就可以很轻松.一个时长为半小时的电子小说
    可能就会有上万字,多个分支情节以及结局.构造这样的非线性的故事情节显然不是容易的事情.而无双引擎的优势在于她可以使你
    快速试验自己的想法.只需要有个大概的背景设定,两三个角色,你就可以开始录入剧本并查看最终游戏效果.你可以在游戏尚未完成时
    就将她发布出来,也可以以续集的形式来发布后续版本.总之,”尽早发布”和”频繁发布”,是保证一个游戏项目生命力的绝佳手段.

    无双引擎自带有很多游戏示例，这些游戏示例的剧本都是很好的上手指南，可以通过修改现有剧本来快速地上手无双使用。

    !! 3 基础介绍

    !!! 3.1 目录结构

    无双引擎的主要目录结构如下：

    -游戏根目录
     |
     |_ images (保存图片文件,可以内建中文子目录)
     |
     |_ musics (保存声音文件,可以内建中文子目录)
     |
     |_ codes  (保存代码文件,主要为自定义界面)
     |
     |_ script (保存游戏剧本,剧本会根据文件名排序来逐个解析)
     |
     |_ config.txt  (配置文件)

    主要的游戏相关数据文件都保存在游戏目录中。当游戏目录中只有一个游戏时，会直接启动这个游戏。在加载图片和音乐时，
    会先在游戏目录中的相应文件夹查找文件，查找不到才会去根目录下的图片音乐目录中去查找，仍然找不到的话会有错误提示。
    这样一来,”游戏目录”下的每个子目录都包含了一个游戏的所有数据,可以单独发布.如果玩过模拟器的话,可以把游戏目录下的每个
    子目录理解为一个ROM.由于我设想中的AVG游戏都比较短小,并且可能以续集的形式持续发布,那么采用这种目录结构可以减小
    每个游戏的下载量.假如把图片音乐都放到根目录的话,发布续集更是只需要发布剧本和设置这两个txt文件就可以了,更新很方便!
    每个游戏必须至少有 剧本.txt 和 设置.txt 这两个文件

    !!! 3.2 剧本结构

    剧本目前由初始化和剧情两部分构成。

    !!!! 3.2.1 初始化部分

    初始化主要用来定义剧情中需要用到的图片和音乐文件，相当于给图片和音乐文件起一个”别名”，
    这样以后使用这些图片音乐文件时，就可以只使用别名。当需要替换资源文件时，也只需要修改
    初始化中相应的部分，剧情部分的别名无需改动，非常方便。
    初始化部分还可以定义一些”全局变量”,来控制游戏运行状态,相关文档内容会随着高级游戏系统
    如角色属性,背包系统的开发而逐步添加.

    !!!! 3.2.2 剧情部分

    剧情部分由一个或多个标签组成.标签可以作为剧情的章节,场景的描述等等来理解.剧情的分支
    可以通过”分支菜单”,”如果”指令以及”全局变量”来控制.标签的末尾一般应该设置”跳转”指令,
    否则会继续执行下一个相邻的标签内容.剧本中可用的指令,请参考命令详解.

    剧本中至少需要有一个”开始”标签和一句台词
    剧本格式必须严格遵守缩进.推荐使用两个空格键来缩进.不能使用Tab键缩进.
    剧本中的控制类标点符号,如 : ” = == 等,必须用英文半角标点符号

    !!! 3.3 配置文件

    设置.txt(config.txt) 中可以设置游戏的基本属性，如游戏名称，窗口大小，字体，文本框背景图等等.查看设置.txt (config.txt) 说明可以得到更多信息.

    !! 4 命令详解

    命令目前提供简体,繁体和英文三种版本,具体对照请参见简繁英命令对照表.下面主要针对简体版命令进行讲解.

    !!! 4.1 图形相关命令

    !!!! 4.1.1 "图片"命令

    格式: 图片 组名 标记名 = “图片链接”
    图片命令的主要作用是给一个图片打上标签,这样在后续剧本中就可以方便地显示该图片.如:

    图片 无双 高兴 = "无双_高兴.png"
    其中 无双 可以理解为组,而 高兴 可以理解为具体动作.当显示组中的某个动作时,其他动作会自动隐藏,这样可以简化剧本的编写,
    因为通常我们都不需要两个 无双 显示在屏幕上.

    !!!! 4.1.2 "显示"命令

    格式: 显示 组名 标记名 位置 X坐标 Z坐标
    显示命令用来显示一个图片,用法如下:

    显示 无双 高兴
    显示 无双 高兴 左 50
    显示 无双 高兴 左 50 10
    显示 背景 街景 中 0 -10
    图片的坐标定位只有三个,即 左 中 右.默认图片会在中间显示,如果想显示在左或右,可以再加一个X坐标(如50)来控制图片相对于
    窗口左边框或右边框的距离.
    如果还想控制图片的遮挡关系,可以再加一个Z坐标(如10).Z坐标大的图片会挡住Z坐标小的图片.
    如果Z坐标相同,后显示的图片会挡住先显示的图片.

    显示命令会记忆上次图片的坐标位置,这样不用反复输入左右和坐标,很方便!
    也就是说,假如你已经使用了
    显示 背景 街景 中 0 -10
    来显示背景后,下次切换背景时,只需要输入

    显示 背景 侦探社
    所有坐标信息都会自动使用上次的设定

    !!!! 4.1.3 "说话"命令

    由于说话在AVG中的比重相当大,所以它被设计成了默认指令,无需输入其他前缀,只需要双引号”“就可以,如:

    "大家好!我是无双!"
    注意引号必须是半角英文标点符号

    1.如果想利用不同的字体或角色名来区分发言人,请参阅 角色定义详解
    2.引号内没有内容时文本框会自动隐藏,这个技巧可以用在需要全屏展示CG事件的地方.

    !!!! 4.1.4 "隐藏"命令

    隐藏命令用来隐藏一个图片,用法如下:

    隐藏 无双
    隐藏命令不需要指明当前显示的具体动作,很方便!

    !!!! 4.1.5 "清屏"命令

    清屏命令可以用来清除已经绘制的所有图片.在它后面可以接一个图片描述,一般用来加载新背景图,如:

    清屏 背景 都市
    相当于

    清屏
    显示 背景 都市

    !!!! 4.1.6 "视频"命令

    用来定义一段视频,定义好后就可以像图片一样来使用视频了.用法如下:

    视频 组名 标记名 视频宽度 视频高度 音量 循环/不循环 = '视频\\XT4.wmv'
    视频 心跳4 宣传片 236 136 0 循环 = '视频\\XT4.wmv'
    其中音量范围为0至100.定义好后就可以用

    显示 心跳4 宣传片
    来显示这段视频了.
    小窍门:可以用 @休息(视频长度) 来使视频播放完成后才继续游戏.

    !!!! 4.1.7 "多图动画"命令

    可以用多张图片反复播放来形成动画效果.用法如下:

    多图动画 组名 标记名 动画速度 循环/不循环 = 路径名
    多图动画 风车 低速转动 0.3 =  "其他\\风车"
    然后就可以用

    显示 风车 低速转动
    来显示刚才的多图动画了.显示顺序按路径中的文件名排序.

    {{groupbox{
     特别注意:图片 视频 多图动画 等定义的 “组名” 其实是全局变量,其他的全局变量都不能和它们重复,否则会报错.比如:

    >   图片 无双 高兴 = "无双_高兴.png"
    >   ........
    >   @无双 = 100        # 错误! 组名 无双 被重复定义!
    }}}

    !!! 4.2 音效相关命令

    !!!! 4.2.1 "音乐"命令

    音乐命令可以播放一个之前定义好的声音文件,如:

    @无双主题音乐 = "无双主题音乐.ogg"
    音乐 无双主题音乐
    调用'音乐'会停止当前正在播放的音乐.音乐结束后会循环播放

    !!!! 4.2.2 "音效"命令

    音效命令和音乐命令的区别在于,音效不会循环,也不会打断当前正在播放的其他音乐音效语音,如:

    @敲门声 = "敲门声.ogg"
    音效 敲门声

    !!!! 4.2.3 "语音"命令

    语音命令的特点在于,语音不会循环,也不会打断当前正在播放的其他音乐音效,但会打断当前正在播放的语音.
    这样快进的时候可以保证语音和文本的同步,不会出现文本已经更新时,新旧语音错误混合的情况.

    @台词2_1 = "台词2_1.ogg"
    语音 台词2_1
    "这句应该是台词2_1的文本内容"

    !!!! 4.2.4 "静音"命令

    静音命令会停止当前播放的所有音乐

    !!! 4.3 控制逻辑相关命令

    !!!! 4.3.1 "标签"命令

    标签命令主要和跳到命令配合,来实现分支剧情.每个游戏中至少需要有一个”开始”标签

    标签 开始:
    注意标签名后要加冒号,该标签下的后续剧情文本必须缩进

    !!!! 4.3.2 "跳到"命令

    跳到命令主要和标签命令配合,来实现分支剧情,如:

    跳到 结束

    !!!! 4.3.3 "分支菜单"命令

    分支菜单命令是实现分支的主要手段,也是目前唯一给用户提供选项的方式,如:

    分支菜单:
      "这个是选项1,会显示在菜单上":
        "如果你选了选项1,就会显示这一行"
      "这个是选项2,也会显示在菜单上":
        "如果你选了选项2,就会显示这一行"

    !!!! 4.3.4 "如果"命令和单行Python命令

    如果命令其实就是普通编程语言中的if,如果你觉得”如果”命令难以理解的话,完全可以不去用它.
    单行Python命令听起来更为深奥.如果在行首加了'@'符号的话,该行就变成了”单行Python指令”,如:

    @我困了 = True
    如果 我困了:
      跳到 睡觉

    显示 无双 熊猫眼
    "哈,再玩会儿~"
    标签 睡觉:
      显示 无双 极度困倦
      "这下真该睡了..."
      "ZZZZZZZZZZZZZZZzzzzzzzzzzzz"
    虽然@和Python对于制作电子小说来说并不是必须的,但为了实现复杂的游戏逻辑,掌握一些Python的使用也很有益处,
    可以参考无双自带教程”教程 - 邪恶的@”.

    !! 5 进阶教程

    从这里开始,将完全是邪恶的Python的天下! 请确定你有足够的实力!
    好吧,开个玩笑,其实Python也是很简单的东西,尤其是中文化后

    !!! 5.1 "角色"的定义

    “角色”在无双引擎中,主要用来定义对话框中的各种外观效果.包括要显示的角色名,文本字体颜色,左边图,文本框底图等等内容.
    关于角色的详细定义,请参考角色定义详解

    !!! 5.2 界面制作

    请参阅 界面系统

    !!! 5.3 图片动画与特效

    利用很简单的指令,就可以在无双引擎中实现图片动画及各种效果,如负片,黑白化,模糊等等,详见图片动画与特效.

    !!! 5.4 关键帧动画

    关键帧动画是一个很强大的动画制作功能,利用它可以实现很多华丽的演出效果,例如烟雾特效,立绘眨眼说话,背景放大等待,具体请参见关键帧动画详解.

    !!! 5.5 "好感度"及其他游戏功能

    利用强大的Python语言,可以很轻松地实现很多游戏功能.基于全局变量实现的”好感度”就是其中之一,具体请参见"好感度"及其他.

    !!! 5.6 API手册

    在界面制作中,大家已经接触到了一些无双提供的供Python代码调用的API,这里介绍其他API ,具体请参见API手册.

    !! 附录

    <<slider sliZhiLinDuiZhao 简繁英指令对照表 "点击展开简繁英指令对照表">>

    /%
    Description: 无双大杂烩项目启动
    %/周三, 十一月 24th, 2010 12:31:18 上午

    希望能涵盖无双引擎相关的所有信息,并且能离线浏览.顺带保存一些其他ACG相关的文档.
    也是大项目啊,希望不要坑掉...

    /%
    URL: http://bbs.gamediy.net
    Description: 无双引擎官方论坛
    %/

    !! 哪里可以下载到最新版本的无双引擎?
    [[下载最新版本的无双引擎 | http://code.google.com/p/wushuang/downloads/list]]

    !! 我应该如何上手?
    对照[[文档|无双基础教程]]阅读剧本吧.另外也可以看看[[视频教程|http://gamediy.net/wiki/doc/video]].

    !! 图片文件都支持哪些格式?
    图片文件目前支持PNG,JPG,GIF,TIF,BMP等主流图片格式.推荐使用PNG格式.

    !! 音频文件都支持哪些格式?
    音频文件目前支持mp3,mp2,mp1,ogg,wav,aiff,midi。
    推荐使用mp3格式,和web版兼容.

    !! 视频文件都支持哪些格式?
    无双引擎并没有内嵌视频解码器,而是调用目标电脑上已经安装的解码器.
    所以假如目标机器已经安装了暴风影音之类的工具的话,基本上所有格式都支持.
    最保险而又压缩率高的格式是wmv格式.

    !! 无双引擎支持哪些解析度(分辨率)?
    理论上各种解析度都支持,可以在[[设置.txt|config.txt 详解]]中通过 窗口宽度
    和 窗口高度 来控制.请注意,素材的解析度应该和窗口大小对应.

    !! 我还是没明白@是干嘛的……汗
    @是单行Python语句。理论上@后面可以跟任何Python语句，不过目前只用于简单的变量赋值，
    这个变量就可以在后面使用，用于条件判断，或者音效文件命名等等.请参见教程[[ 邪恶的@ | http://gamediy.net/data/wsdoc_at.swf ]]

    !! 如何支持"好感度"或者类似的系统?
    好感度其实就是一个简单的全局变量,通过各种分支菜单可以对这个变量做加减,然后再用 如果 等指令对这个变量的值做判断,以进入不同的游戏分支.
    全局变量的用法可以参考现有剧本.(如"我和小绿的故事")

    !! 文本框能否改变大小？
    可以改，改文本框背景图就相当于改大小，可以在角色中设置文本框背景图,具体参考[[角色定义详解|http://gamediy.net/wiki/doc/character]]

    !! 游戏是否支持全屏显示?
    可以通过右键菜单->系统设置->切换全屏 来切换全屏模式.也可以在[[设置.txt|config.txt 详解]]中设置 全屏模式=1 来使得游戏默认以全屏方式运行.

    !! 为什么不能用ctrl键自动跳过?
    由于内部实现的原因,自动跳过键设成了Page Down/Enter,以及鼠标滚轮下滚,当然也可以利用右键菜单上的"快速略过".

    !! 我还有问题怎么办?

    上[[论坛|http://bbs.gamediy.net]]提问.假如开发人员在线的话,也可以使用在线答疑系统.

    /%
    URL: http://gamediy.net/wiki/ws/webgame
    Description: WEB游戏索引
    %/

    /%
    URL: http://gamediy.net/wiki/doc/manual
    Description: 无双引擎在线文档
    %/

    <<tabs txtWuShuangDocs
    基础教程 "无双引擎入门教程" 无双基础教程
    config.txt "config.txt(设置.txt)详解" [[config.txt 详解]]
    指令对照表 "简繁英指令对照表" 简繁英指令对照表
    Python "Python相关内容" [[Python FAQ]]
    FAQ "无双引擎FAQ" 无双引擎FAQ
    >>

    !!! 无双游戏作品发布区: http://bbs.gamediy.net/thread.php?fid=4

    !!! 无双引擎游戏合集 卷一
    长篇 - 所向往的风雅
    短篇 - 羁之校园
    短篇 - 双生
    [[点击下载 | http://gamediy.net/data/games/WuShuang_Vol1.exe]]

    !!! 无双引擎游戏合集 卷二
    中篇 - 0零0
    中篇 - magenta fairytale
    中篇 - 通天塔
    短篇 - 三上智也的扭曲一天
    短篇 - 仓成武和茜崎空的幸福生活
    短篇 - 丸子后援团_追逐计划
    短篇 - 夜物语
    短篇 - 恋姬无双
    短篇 - 我和小绿的故事
    短篇 - 激狂映画
    [[点击下载 | http://gamediy.net/data/games/WuShuang_Vol2.exe]]

    <<tabs txtDaKengs
    通天塔 "八月寒的大坑" 通天塔首页
    方舟 "黑衣少年的大坑" 方舟首页
    艾莉卡不曾盛开 "银月幽若的大坑" 艾莉卡不曾盛开首页
    神秘SLG "冬叔的大坑" 神秘SLG首页
    >>

    <<tabs txtDaZaHui
    无双游戏大坑 "进行中的无双游戏项目" 无双游戏大坑
    无双游戏大赛 "无双游戏大赛的相关信息" 无双游戏大赛
    无双游戏大全 "介绍所有利用无双引擎制作的游戏" 无双游戏大全
    无双游戏达人 "介绍无双游戏项目制作团队" 无双游戏达人
    无双文档大全 "无双引擎的文档库" 无双文档大全
    >>

    论坛: http://bbs.gamediy.net/thread.php?fid=13

    !首届无双游戏大赛圆满结束!

    !! 参赛作品列表
    本次大赛共收到8份有效参赛作品。下面是作品列表（排名以拼音为序）：

    @@ <<slideShow cycle tag:slide1 sort:modified label:点击播放大赛作品幻灯片 tooltip:以幻灯片的方式展示所有参赛作品>> @@

    <<tiddler 穿越时空的思念>>

    <<tiddler 风之诱捕>>

    <<tiddler 幻灵社>>

    <<tiddler 零时>>

    <<tiddler 藤原雅的生日剧场>>

    <<tiddler 下一个圣诞>>

    <<tiddler 再见的日子>>

    <<tiddler 子虚赋>>

    !!各奖项提名及最终获奖情况

    !!!最佳原画提名
    穿越时空的思念
    幻灵社
    零时
    下一个圣诞
    子虚赋

    ''最佳原画奖项得主:子虚赋'' [[试玩WEB版本 | http://ws.gamediy.net/?game=http://bbs.gamediy.net/job.php?action=download&aid=334]]

    !!最佳剧本提名
    穿越时空的思念
    幻灵社
    零时
    下一个圣诞
    再见的日子

    ''最佳剧本奖项得主:幻灵社'' [[试玩WEB版本 | http://ws.gamediy.net/?game=http://bbs.gamediy.net/job.php?action=download&aid=333]]

    !!最佳配音提名
    穿越时空的思念
    藤原雅的生日剧场——所追寻的风雅

    ''最佳配音奖项得主:空缺...''

    !!最佳游戏系统提名
    风之诱捕~一日限定
    子虚赋

    ''最佳游戏系统奖项得主:风之诱捕~一日限定''

    !!最佳游戏提名
    穿越时空的思念
    幻灵社
    零时
    下一个圣诞

    ''最佳游戏奖项得主:空缺...''

    这里将展示各个无双游戏制作组的情况

    <<tiddler AutoRefresh with: force>><<tiddler HideTiddlerBackground>><<tiddler HideTiddlerTags>>{{transparent smallform{<<faqViewer 日志 'viewer scrollbars' -title>>}}}

    欢迎使用无双引擎大杂烩,这里提供各种无双引擎文档资料,ACG相关资讯.
    所有内容都包含在一个html文件中,可以离线使用!(除了书签...好吧,这个算吐槽么...)
    离线版的优势在于全文检索速度很快.
    另外大家也可以尝试编辑这个大杂烩,并把修改过的文件发给我,(lance [at] gamediy [dot] net)
    这样更新后的大杂烩就会包括你的大作了!

    本作实在是太神秘了,以至于资料都很少,目前只有一个WEB版本试玩

    [[在新窗口中打开试玩 | http://ws.gamediy.net/?game=http://bbs.gamediy.net/job.php?action=download&aid=354]]

    !!!!穿越时空的思念
    介绍:http://bbs.gamediy.net/read.php?tid=3382
    下载:http://gamediy.net/data/games/ds1/ChuanYueShiKongDeSiNian.exe
    [img(320px,)[http://bbs.gamediy.net/attachment/Mon_1007/13_435_ee7b2b098fabbc1.png]][img(320px,)[http://bbs.gamediy.net/attachment/Mon_1007/13_435_d18aab5903d789b.png]]

    !! 基本指令对照表
    |! 简体  |! 繁體  |! 英文  |!备注 |
    |  图片  |  圖片  |  image  |  只能出现在初始化部分  |
    |  显示  |  顯示  |  show  |  英文定坐标用left,right,center  |
    |  隐藏  |  隱藏  |  hide  | |
    |  清屏  |  清屏  |  clear  |  简体繁体一致  |
    |  视频  |  視頻  |  video  | |
    |  多图动画  |  多圖動畫  |  multipage  |  |
    |  音乐  |  音樂  |  music  | |
    |  音效  |  音效  |  sound  |  简体繁体一致  |
    |  语音  |  語音  |  speech  | |
    |  静音  |  靜音  |  mute  | |
    |  初始化  |  初始化  |  init  |  简体繁体一致  |
    |  标签  |  標簽  |  label  | |
    |  跳到  |  跳到  |  jump  |  简体繁体一致  |
    |  分支菜单  |  分支菜單  |  menu  |  实现分支的主要手段  |
    |  如果  |  如果  |  if  |  简体繁体一致  |
    |  否则如果  |  否則如果  |  elif  | |
    |  否则  |  否則  |  else  | |
    |  代码  |  代碼  |  python  | |

    !! 主要术语对照表
    |! 简体  |!繁體   |!英文  |!备注 |
    |  锚点  |  錨點  |  anchor  | |
    |  对齐  |  對齊  |  align  | |
    |  透明度  |  透明度  |  alpha  | |
    |  文本  |  文本  |  text  | |
    |  宽  |  寬  |  width  | |
    |  高  |  高  |  height  | |
    |  半径  |  半徑  |  radius  | |
    |  模式  |  模式  |  mode  | |
    |  返回值  |  返回值  |  value  | |
    |  激活  |  激活  |  active  | |
    |  名称  |  名稱  |  name  | |
    |  标记  |  標記  |  tag  | |
    |  替换  |  替換  |  replace  | |
    |  追加  |  追加  |  append  | |
    |  多行  |  多行  |  multiline  | |
    |  背景图  |  背景圖  |  bgImage  | |
    |  普通  |  普通  |  normal  | |
    |  颜色  |  顔色  |  color  | |
    |  背景色  |  背景色  |  bgColor  | |
    |  字体色  |  字體色  |  fontColor  | |
    |  悬浮音效  |  懸浮音效  |  hoverSound  | 按钮专用 |
    |  点击音效  |  點擊音效  |  clickSound  | 按钮专用 |
    |  开始  |  開始  |  start  | |

    !! 锚点系统对照表
    |! 简体 |!繁體 |!英文 |!备注 |
    |  左  |  左  |  LEFT  | |
    |  中  |  中  |  CENTER  | |
    |  右  |  右  |  RIGHT  | |
    |  左上  |  左上  |  NW  | |
    |  中上  |  中上  |  N  | |
    |  右上  |  右上  |  NE  | |
    |  左中  |  左中  |  W  | |
    |  中中  |  中中  |  CENTER  | |
    |  右中  |  右中  |  E  | |
    |  左下  |  左下  |  SW  | |
    |  中下  |  中下  |  S  | |
    |  右下  |  右下  |  SE  | |

    !! 图片动画与特效系统对照表
    |! 简体  |!繁體   |!英文   |!备注 |
    |  淡入  |  淡入  |  FadeIn  | |
    |  淡出  |  淡出  |  FadeOut  | |
    |  移至  |  移至  |  MoveTo  | |
    |  黑白化  |  黑白化  |  FX_GrayScale  | |
    |  负片化  |  負片化  |  FX_Negative  | |
    |  线稿化  |  線稿化  |  FX_Edge  | |
    |  浮雕化  |  浮雕化  |  FX_Emboss  | |
    |  模糊化  |  模糊化  |  FX_Blur  | |
    |  毛玻璃化  |  毛玻璃化  |  FX_Jitter  | |
    |  膨胀化  |  膨脹化  |  FX_Dilate  | |
    |  腐蚀化  |  腐蝕化  |  FX_Erode  | |
    |  噪点化  |  噪點化  |  FX_Noise  | |
    |  偏色化  |  偏色化  |  FX_ShiftRGB  | |
    |  复原化  |  複原化  |  FX_Reset  | |
    |  完成动画  |  完成動畫  |  FinishAnim  | |

    无双引擎QQ群: 21750804
    电子邮箱:lance [at] gamediy [dot] net

    论坛: http://bbs.gamediy.net/thread.php?fid=18

    《Erica never be in bloom——艾莉卡不曾盛开》游戏介绍+应援

    嘛，我终于还是决定开这个大坑了……远目……
    虽然不知道啥时能填完不过嗯……2012世界毁灭之前会有希望么（啥）

    游戏名称：《Erica never be in bloom——艾莉卡不曾盛开》
    游戏类型：乙女向全年龄AVG
    制作团队：银月幽若（剧本，程序）、Eero（美工）
    开发引擎：无双引擎
    游戏语言：简体中文
    作品取向：稍有虐心的治愈故事

    故事简介：

    直到现在也依然后悔着，
    为什么，自己是如此无力、渺小的存在……
    如果，当初拥有“力量”，
    是不是，就能够守护住没能守护的东西……

    陆筱然是一名普通的高二女生，却过着无比艰辛的生活。父母自幼离异，很小的时候开始便独自一人生活；老师与同学的排挤，让她不得不封闭自己的心灵。她的身边，只有唯一的好友姚思岚一直在支持，鼓励着她，也多亏如此她才能够保持自我。

    忽然出现的异形生物，唤醒了曾经痛苦的过往。年幼的她，没有在这些异形面前守护住自己最重要的那个人，因为，她没有力量。迷之异国美少年琉亚希斯，在出手救了深陷险境的陆筱然的同时，却也对她怀有异样的敌意。学院风云人物的黎诺，不意间与陆筱然有了交集，原来他也与出现的异形有着千丝万缕的联系。唯一知道当年事情真相的好友姚思岚，一如既往地在陆筱然的身边支持着她，然而这份感情却不知何时慢慢变质。活泼开朗的可爱少年姚梓欣，一直被视为弟弟的存在，他的坚强却无意间拯救了陆筱然的心……

    在命运的漩涡中，他们到底该何去何从？该如何选择，又该如何面对？艾莉卡，欧石楠的别称，它的花语为孤独，背叛与幸福的爱情。曾经与最重要的那个人一起种下的花朵，从未盛开过。不过，这也是理所当然的，因为，谁让自己在那个时候，背叛了他的信赖，将他一个人孤零零地扔下了呢……

    人物简介：

    陆筱然：本作女主，17岁。平日里看上去像个问题儿童，但那也只是因为周围人的恶意所以披上了厚厚的外壳用来保护自己，实际上却是个坦率又可爱的少女，爱好动漫游戏。因为年幼时没能守护住最重要的人的遗憾，一直活在悔恨当中，所以在同样的异形再次出现的时候，即使没有力量，她也选择了与之战斗。

    琉亚希斯·奇里特·弗拉雷米兹：17岁，在陆筱然碰到异形时拯救了她的神秘美少年。据说是英国某名门贵族子弟，拥有不可思议的能瞬间秒杀异形的强大力量，关于异形的事情也非常了解。对陆筱然抱有莫名敌意，处处针对于她，却屡次在她遇到危险的时候出手相救，行为可谓矛盾至极，总之是个浑身都是谜的人物。

    黎诺：18岁，与陆筱然同一个学校的学长，因有着俊美的外表，优秀的成绩与冷酷的个性成为学园的风云人物，让很多女生趋之若鹜。与琉亚希斯一样，他也拥有剿灭异形的力量，偶然间与陆筱然有了交集。虽然外表冷酷，却总是不经意间流露出温柔的一面，似乎过去也曾经有过痛苦的回忆。

    姚思岚：17岁，陆筱然的至交好友，两人的孽缘从初中开始。是个知性冷静的美少女，偶尔流露出腹黑的一面，总是把陆筱然吃的死死的。她也是唯一一个一直在陆筱然身边支持，鼓励她的人，知道陆筱然几乎所有的秘密。可以说她的存在至关重要，如果不是她，陆筱然恐怕早就不能维持自我。

    姚梓欣：15岁，姚思岚的弟弟，是个开朗活泼的可爱少年。因为陆筱然经常去姚思岚的家里的关系，与他也很熟识。同样喜欢动漫游戏的两人很有共同话题，经常在联机游戏上和游戏厅里杀个天昏地暗你死我活。看似是个天真孩子的他，却总是流露出小大人般成熟的一面，同样拥有某种特殊能力，只是无法对异形造成伤害，只能牵制它们。

    制作博客见此，里面会有些有趣的东西：http://1643056.5sing.com/log.aspx

    应援LOGO见此，想要应援者可随意取用

    [img[http://bbs.gamediy.net/attachment/Mon_1011/18_314_08074df21d3231e.jpg]]
    [img[http://bbs.gamediy.net/attachment/Mon_1011/18_314_947cf51d8410327.jpg]]
    [img[http://bbs.gamediy.net/attachment/Mon_1011/18_314_2cf953556b9f8b8.jpg]]
    [img[http://bbs.gamediy.net/attachment/Mon_1011/18_314_1c4c126f7bc0664.jpg]]
    [img[http://bbs.gamediy.net/attachment/Mon_1011/18_314_d6bccf08f8146cf.jpg]]
    [img[http://bbs.gamediy.net/attachment/Mon_1011/18_314_a59379290d42aa8.jpg]]
    [img[http://bbs.gamediy.net/attachment/Mon_1011/18_314_728e8c6a6a553a2.jpg]]

    !!!!藤原雅的生日剧场——所追寻的风雅
    介绍:http://bbs.gamediy.net/read.php?tid=2523
    下载:http://gamediy.net/data/games/ds1/Miyabi.exe

    <<tiddler AutoRefresh with: force>><<tiddler HideTiddlerBackground>><<tiddler HideTiddlerTags>>{{transparent smallform{<<miniBrowser MiniBrowserFavorites>>}}}

    《通天塔》起源

    虽然是个不像是能完成的大坑，但是纯粹为了留下点什么，简单介绍下为什么会诞生《通天塔》这个故事

    这个游戏最初的起源要追溯到大约5年以前某寒还在上高中时制造的深坑

    那个坑甚至连名字也没有，但是占用了还是高中生的某寒满满3个练习本

    与游戏本身的无厘头风格完全不同的是，那个深坑是非常、非常、非常正统的魔幻故事

    有着很传统的魔法体系，很通俗的剑与魔法的世界观

    而且像童话一般有非常传统的主角们（将军之子、王子、公主等）

    那个时候某寒从来不怕题材俗烂，最乐意的就是在看起来很俗的题材里面发掘新意

    故事的开始：国王被刺，将军之子奉命带着王子和公主离开政局行将崩溃的国家开始了流浪，并寻找事件真相的旅程。

    故事的结尾：挖掘出来的并非真相，而主角们则因为误解和偏见站在了对立面，彼此的道路越来越远——此后开始了第二部剧情

    第二部后面还有第三部，第三部后面还有第四部，第四部结束了

    然后这个作品实际只是第一部开了个头而已！——某寒挖坑不会填的能耐在那个时候就体现出来了。

    关于这个故事的开头虽然是手写的，但是后来某寒将开头中的开头打成了文字，在这里可以看见：

    http://formywholelife.ycool.com/post.2807211.html

    不论是那时还是现在，其实文笔都不咋的，有的就是毫无联系的海量的想法，没空的人请不要看了，

    说了这么多还是没说到《通天塔》和这个最初的作品的联系，因为中间还有一道关系……

    没错，正如大家所见，某寒那传奇般的挖坑能力，在那个魔法故事只开了一个头的时候，以黑衣少年和八月寒为主角的外传故事就已经诞生了……

    外传故事并非发生在那个正统的魔法世界，而是发生在我们的现实世界

    以八月寒为首的野心家和以黑衣少年为首的冒险家们开始了寻找传说中的魔法世界的蛛丝马迹的旅程

    而作为主角的黑衣少年和八月寒都是大学中退的年龄，而那个故事开头所奠定的世界观，则成为了本游戏《通天塔》创意的来源

    http://formywholelife.ycool.com/post.3225105.html

    这个世界观其实会在《通天塔》今后的剧情里提及

    《通天塔》严格上来说和前面所提到的一切它的创意来源并没有承接关系，是独立的故事

    型式从小说变成了AVG游戏，主角黑衣少年的年龄也从21岁大学肄业退回了16岁高一入学，变成了校园故事

    虽然完全可以当作是“只有序章和前几章的没有名字的大坑的只有前几节的外传大坑的只有第一天多一点剧情的前传大坑”

    但果然为了减轻坑的负担压力，还是把《通天塔》这个AVG坑独立出来好了，也可以尽量避免这个游戏会没有结局……（因为衔接上另一个大坑就不能结局了啊！）

    高中时代，哪怕是高三的时候，某寒和黑衣少年也依旧能够挤出大把的时间来实现创作的梦想

    现在都工作了，没有时间来填坑，甚至挖坑的时间都没有了

    这个磨洋工的游戏《通天塔》就是用来纪念那美好的高中时代吧！

    还在念高中的和刚刚毕业的小盆友们，要珍惜时光哦，否则会变得跟某寒一样大叔噢～（谁会变得跟你一样啊！）

    论坛: http://bbs.gamediy.net/thread.php?fid=16
    <<tiddler [[通天塔 起源]]>>

    !!!!零时
    介绍:http://bbs.gamediy.net/read.php?tid=3051
    下载:http://gamediy.net/data/games/ds1/LinShi.exe
    [img(320px,)[http://bbs.gamediy.net/attachment/Mon_1004/13_238_f1c102e6238e3da.jpg]][img(320px,)[http://bbs.gamediy.net/attachment/Mon_1004/13_238_b974cceadb7608f.jpg]]

    !!!!风之诱捕~一日限定
    介绍:http://bbs.gamediy.net/read.php?tid=2543
    下载:http://gamediy.net/data/games/ds1/FengDeYouBu.exe
    [img(320px,)[http://bbs.gamediy.net/attachment/Mon_1007/13_641_2c68a235eb65b4b.jpg]]