<!--{{{-->
<link rel='alternate' type='application/rss+xml' title='RSS' href='index.xml'/>
<!--}}}-->
Background: #fff
Foreground: #000
PrimaryPale: #8cf
PrimaryLight: #18f
PrimaryMid: #04b
PrimaryDark: #014
SecondaryPale: #ffc
SecondaryLight: #fe8
SecondaryMid: #db4
SecondaryDark: #841
TertiaryPale: #eee
TertiaryLight: #ccc
TertiaryMid: #999
TertiaryDark: #666
Error: #f88
/*{{{*/
body {background:[[ColorPalette::Background]]; color:[[ColorPalette::Foreground]];}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

hr {height:1px;}

a {text-decoration:none;}

dt {font-weight:bold;}

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

.txtOptionInput {width:11em;}

#contentWrapper .chkOptionInput {border:0;}

.externalLink {text-decoration:underline;}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

----
Also see AdvancedOptions
<<importTiddlers>>
In Socialtext Unplugged, the selected pages of your Socialtext workspace are displayed as individual "tiddlers" on the page. When the mouse passes over a tiddler a short toolbar menu appears at the top right. Use the commands here to manipulate that particular tiddler: notably closing and editting it. (You can double click on a tiddler as a shortcut to directly enter edit mode).

Over on the right hand side of the window are commands that affect the entire page, in particular "close all" which can be useful to clear the decks when many tiddlers are open at once.

The user is encouraged to ensure that they can SaveChanges before embarking on widespread editing.
Welcome to Socialtext Unplugged. This is a specially designed web page that you can use to view and edit your Socialtext content without having to be online to your Socialtext server.

There are three steps to using Socialtext Unplugged:
* First, learn how to SaveChanges to your local hard drive. This keeps your work safe even if you close your browser or have to reboot your computer
* Secondly, find out how to BrowseAndEdit your content while it is unplugged
* Thirdly, when you can reconnect to your Socialtext server, you can SyncChanges to save your unplugged changes to the server so that other people can see them too

You should also check your system meets the SystemRequirements.
Socialtext Unplugged lets you browse and edit your content while you're offline. When you make a change you need to SaveChanges to save the change to your local hard drive, before later performing a SyncChanges to synchronise the change back to the server.

The procedure for SaveChanges is slightly different for different browsers:
* SavingOnInternetExplorer
* SavingOnFireFox
* SavingOnSafari
* SavingOnOpera
You can save changes with any version of FireFox, and also many other browsers in the FireFox family, such as Camino on the Mac and MiniMo on mobile devices. The procedure is:
# Click the button labelled 'save changes' over in the right hand sidebar
# If prompted with an "Internet Security" dialog as follows, click the checkbox labelled "Remember this decision" and then the "Allow" button
## "A script from "file://" is requesting enhanced capabilities that are UNSAFE and could be used to compromise your machine or data..."
# You should then see a message at the top right of the window saying "Main TiddlyWiki file saved"
If you accidentally //deny// permission instead, you may need to UnravelFireFoxPermissions.
You can save changes with Internet Explorer versions 6 and 7, but not the earlier versions. The procedure is:
# Click the button labelled 'save changes' over in the right hand sidebar
# If prompted as follows, click "Yes":
## "An ActiveX control on this page might be unsafe to interact with other parts of the page. Do you want to allow this interaction?"
# You should then see a message at the top right of the window saying "Main TiddlyWiki file saved"
Note that there is currently [[a bug|http://trac.tiddlywiki.org/tiddlywiki/ticket/39]] that prevents Internet Explorer from saving correctly if you have specified a backup directory in AdvancedOptions.
To SaveChanges on Opera, see the instructions for using the TiddlySaver Java applet.
To SaveChanges on Safari, see the instructions for using the TiddlySaver Java applet.
<<search>><<closeAll>><<permaview>><<newTiddler 'New Tiddler' fields:'server.host:"https://saturn.ffzg.hr%2C%20saturn.ffzg.hr:443" server.workspace:"rot13" wikiformat:socialtext'>><<newJournal 'DD MMM YYYY' fields:'server.host:"https://saturn.ffzg.hr%2C%20saturn.ffzg.hr:443" server.workspace:"rot13" wikiformat:socialtext'>><<saveChanges>><<backstage sync>><<slider chkSliderOptionsPanel OptionsPanel 'options »' 'Change TiddlyWiki advanced options'>>
Dobrica Pavlinušić's random unstructured stuff
Socialtext Unplugged
https://saturn.ffzg.hr/rot13/
[[SocialtextScreenStyle]]
[[SocialtextStyleOverrides]]
[[Styles HorizontalMainMenu]]
<<sync>>
@@The user interface for synchronization is not finalized@@
To synchronize your changes back to the Socialtext server:
# click on [[Sync]] in the right-hand sidebar
<<tabs txtMoreTab Orphans 'Orphaned tiddlers' TabMoreOrphans Shadowed 'Shadowed tiddlers' TabMoreShadowed>>
Under FireFox, you can run into problems if you accidentally click 'Deny' on the permission request dialog, and have selected //Remember this decision//.

To reverse the effects, first locate the file {{{prefs.js}}} in your FireFox profile directory. Under Windows you'll find it at something like {{{C:\Documents and Settings\Jeremy\Application Data\Mozilla\Firefox\Profiles\o3dhupu6.default\prefs.js}}}, where {{{Jeremy}}} is the name of your windows profile and {{{o3dhupu6}}} will be a similar string of gobbledegook. On the Mac it'll be at {{{~/Library/Application Support/Firefox/Profiles/o3dhupu6.default/prefs.js}}} and on most versions of Linux, at {{{~/.mozilla/firefox/o3dhupu6.default/prefs.js}}}.

Open the file in a text editor and find the line {{{user_pref("capability.principal.codebase.p0.denied", "UniversalXPConnect");}}} and simply replace the word {{{denied}}} with {{{granted}}}.
//(Thanks to JonScully for figuring out this fix)//
<!--{{{-->
<div class='toolbar' macro='toolbar closeTiddler closeOthers +editTiddler references > fields syncing jump'></div>
<div class='workspace' id='st-page-wiki-title' macro='view socialtext.workspace'></div>
<div class='title' id='st-page-titletext' macro='view title'></div>
<div class='subtitle'>
Created on <span macro='view created date [[MMM DD, 0hh:0mm]]'></span>.
Updated by <span macro='view modifier link'></span>
on <span macro='view modified date [[MMM DD, 0hh:0mm]]'></span></div>
<div class='tagging' macro='tagging'></div>
<div class='tagged' macro='tags'></span></div>
<div class='viewer' macro='view text wikified'></div>
<div class='tagClear'></div>
<!--}}}-->
/***
To use, add {{{[[Styles HorizontalMainMenu]]}}} to your StyleSheet tiddler.
See http://www.w3schools.com/css/css_colors.asp for a color chart.
***/
/*{{{*/
#mainMenu {position:relative;left:auto;width:auto;text-align:left;line-height:normal;padding 0em 1em 0em 1em;font-size:normal;}
#mainMenu br {display:none;}
#mainMenu {background:#336699;}
#mainMenu {padding:2px;}
#mainMenu .button, #mainMenu .tiddlyLink {padding-left:0.5em;padding-right:0.5em;color:white;font-size:115%;}

#displayArea {
	margin-top:0;margin-right:20em;margin-bottom:0;margin-left:1em;
	padding-top:.1em;padding-bottom:.1em;
}
/*}}}*/
|''Type:''|socialtext|
|''URL:''|https://saturn.ffzg.hr%2C%20saturn.ffzg.hr:443 |
|''Workspace:''|rot13|
|''WorkspaceList:''||
|''Description:''|Dobrica Pavlinušić's random unstructured stuff|
The TiddlySaver Java applet allows TiddlyWiki from a {{{file://}}} URL to save changes Safari, Opera and other browsers.

It is a small file named [["TiddlySaver.jar"|TiddlySaver.jar]] that must be placed in the same directory as your TiddlyWiki file. Before you can use it, you need to give it the necessary privileges by editting your {{{.java.policy}}} file.

For Windows, the file will be at {{{C:\Documents and Settings\your-user-name\.java.policy}}}. Add the following lines (substituting the directory of your TiddlyWiki file as appropriate):
{{{
grant codeBase "file:${user.home}/My Documents/tiddlywiki-folder/*" {
  permission java.io.FilePermission "${user.home}${/}My Documents${/}tiddlywiki-folder${/}*", "read,write";
};
}}}
On Mac OS X, the file is found at {{{/Users/your-user-name/.java.policy}}}:
{{{
grant codeBase "file:${user.home}/Documents/tiddlywiki-folder/*" {
  permission java.io.FilePermission "${user.home}${/}Documents${/}tiddlywiki-folder${/}*", "read,write";
};
}}}
It can be tricky creating files whose name starts with a period, so you can use this [[pre-built .java.policy file|.java.policy]]. The same file is suitable for Macs too, just edit it and delete the "My " bit, leaving just "Documents". Make sure you save it in the right place for each operating system!

If you have trouble setting up the permissions correctly, you can try granting broader permissions to the applet like this:

{{{
grant codeBase "file://localhost/home/users/Desktop/
TiddlySaver.jar"
 { permission java.security.AllPermission; };
}}}

Note that there is currently [[a bug|http://trac.tiddlywiki.org/ticket/172]] that prevents TiddlySaver from working if you have specified a backup directory in AdvancedOptions.
/***
|''Name:''|SocialtextLocaleOverrides|
|''Description:''|Text changes for Socialtext|
***/

//{{{
merge(config.views.wikified.tag,{
	labelNoTags: "No Tags",
	labelTags: "Tags"});

merge(config.commands.references,{
	text: "incoming links",
	tooltip: "Show tiddlers that link to this one",
	popupNone: "No incoming links"});
//}}}
/***
|''Name:''|SocialtextTweaksPlugin|
|''Description:''|Allows changes to be synchronised with a Socialtext server|
|''Source:''|http://stunplugged.tiddlywiki.com/#SocialtextTweaksPlugin|
|''Author:''|JeremyRuston (jeremy (at) osmosoft (dot) com)|
|''Version:''|1.0.2|
|''Date:''|Jun 15, 2006|
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev|
|''License:''|[[BSD open source license]]|
|''~CoreVersion:''|2.2|

Make minor configuration tweaks specific to Socialtext Unplugged
***/

//{{{
// Ensure that the SocialtextTweaksPlugin is only installed once.
if(!version.extensions.SocialtextTweaksPlugin) {
version.extensions.SocialtextTweaksPlugin = {installed:true};
// Check version number of core code
if(version.major < 2 || (version.major == 2 && version.minor < 2))
	{alertAndThrow("SocialtextTweaksPlugin requires TiddlyWiki 2.2 or later.");}

merge(config.defaultCustomFields,{
	wikiformat:'socialtext',
	'server.host':'https://saturn.ffzg.hr%2C%20saturn.ffzg.hr:443'
});

config.options.chkSinglePageMode = true;
config.options.chkEnableAnimations = true;

} // end of "install only once"
//}}}
/***
|''Name:''|SocialtextFormatterPlugin|
|''Description:''|Allows Tiddlers to use [[Socialtext|http://www.socialtext.com/]] text formatting|
|''Author:''|Martin Budden (mjbudden (at) gmail (dot) com)|
|''Source:''|http://www.martinswiki.com/#SocialtextFormatterPlugin|
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/MartinBudden/formatters/SocialtextFormatterPlugin.js|
|''Version:''|0.9.4|
|''Date:''|Jan 21, 2007|
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev|
|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|''~CoreVersion:''|2.1.0|

This is the SocialtextFormatterPlugin, which allows you to insert Socialtext formated text into a TiddlyWiki.

The aim is not to fully emulate Socialtext, but to allow you to work with Socialtext content off-line and then resync the content with your Socialtext wiki later on, with the expectation that only minor edits will be required.

To use Socialtext format in a Tiddler, tag the Tiddler with SocialtextFormat or set the tiddler's {{{wikiformat}}} extended field to {{{socialtext}}}

Please report any defects you find at http://groups.google.co.uk/group/TiddlyWikiDev
***/

//{{{
// Ensure that the SocialtextFormatter Plugin is only installed once.
if(!version.extensions.SocialtextFormatterPlugin) {
version.extensions.SocialtextFormatterPlugin = {installed:true};

if(version.major < 2 || (version.major == 2 && version.minor < 1))
	{alertAndThrow('SocialtextFormatterPlugin requires TiddlyWiki 2.1 or later.');}

SocialtextFormatter = {}; // 'namespace' for local functions

wikify = function(source,output,highlightRegExp,tiddler)
{
	if(source && source != '') {
		var w = new Wikifier(source,getParser(tiddler),highlightRegExp,tiddler);
		var out = output;
		if(tiddler && (tiddler.isTagged(config.parsers.socialtextFormatter.formatTag) || (tiddler.fields.wikiformat==config.parsers.socialtextFormatter.format)) ) {
			var d1 = createTiddlyElement(output,'div','content-display-body','content-section-visible');
			var d2 = createTiddlyElement(d1,'div','wikipage');
			out = createTiddlyElement(d2,'div',null,'wiki');
		}
		var time1,time0 = new Date();
		w.subWikifyUnterm(out);
		if(tiddler && config.options.chkDisplayInstrumentation) {
			time1 = new Date();
			var t = tiddler ? tiddler.title : source.substr(0,10);
			displayMessage("Wikify '"+t+"' in " + (time1-time0) + " ms");
		}
	}
};

stDebug = function(out,str)
{
	createTiddlyText(out,str.replace(/\n/mg,'\\n').replace(/\r/mg,'RR'));
	createTiddlyElement(out,'br');
};

SocialtextFormatter.Tiddler_changed = Tiddler.prototype.changed;
Tiddler.prototype.changed = function()
{
	if((this.fields.wikiformat==config.parsers.socialtextFormatter.format) || this.isTagged(config.parsers.socialtextFormatter.formatTag)) {
		// update the links array, by checking for Socialtext format links
		this.links = [];
		var tiddlerLinkRegExp = /(?:\"(.*?)\" ?)?\[([^\]]*?)\]/mg;
		tiddlerLinkRegExp.lastIndex = 0;
		var match = tiddlerLinkRegExp.exec(this.text);
		while(match) {
			var link = match[2];
			this.links.pushUnique(link);
			match = tiddlerLinkRegExp.exec(this.text);
		}
	}/* else {
		return SocialtextFormatter.Tiddler_changed.apply(this,arguments);
	}*/
	this.linksUpdated = true;
};

SocialtextFormatter.wafl = function(w)
{
	this.lookaheadRegExp.lastIndex = w.matchStart;
	var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
	if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
		var lm2 = lookaheadMatch[2];
		switch(lookaheadMatch[1]) {
		case 'image':
			var img = createTiddlyElement(w.output,'img');
			img.src = w.tiddler.title + '/' + lm2;
			createTiddlyText(img,lm2);
			break;
		case 'file':
			var s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
			var a = createTiddlyElement(s,'a');
			a.href = w.tiddler.title + '/' + lm2;
			createTiddlyText(a,lm2);
			break;
		case 'link':
			s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
			a = createTiddlyElement(s,'a');
			var t = w.tiddler ? w.tiddler.title + ':' : '';
			a.setAttribute('href','#' + t + lm2);
			a.title = 'section link';
			createTiddlyText(a,lm2);
			break;
		case 'weblog':
			s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
			var text = lm2;
			var link = 'Weblog: ' + lm2;
			createTiddlyText(createTiddlyLink(s,link,false,null,w.isStatic),text);
			break;
		case 'section':
			a = createTiddlyElement(w.output,'a');// drop anchor
			t = w.tiddler ? w.tiddler.title + ':' : '';
			a.setAttribute('name',t + lm2);
			break;
		case 'date':
			createTiddlyText(w.output,lm2);
			break;
		case 'user':
			var oldSource = w.source;
			w.source = lm2;
			w.nextMatch = 0;
			w.subWikifyUnterm(w.output);
			w.source = oldSource;
			break;
// Shortcut expansions - not strictly syntax
		case 'google':
			s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
			a = createExternalLink(s,'http://www.google.com/search?q='+lm2);
			createTiddlyText(a,lm2);
			break;
		case 'fedex':
			s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
			a = createExternalLink(s,'http://www.fedex.com/Tracking?tracknumbers='+lm2);
			createTiddlyText(a,lm2);
			break;
		case 'map':
			s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
			a = createExternalLink(s,'http://maps.google.com/maps?q='+lm2);
			createTiddlyText(a,lm2);
			break;
		case 'wikipedia':
			s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
			a = createExternalLink(s,'http://en.wikipedia.org/wiki/'+lm2);
			createTiddlyText(a,lm2);
			break;
		case 'rt':
			s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
			a = createExternalLink(s,'http://rt.socialtext.net/Ticket/Display.html?id='+lm2);
			createTiddlyText(a,lm2);
			break;
		case 'stcal':
			s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
			a = createExternalLink(s,'https://calendar.socialtext.net:445/view_t.php?timeb=1&id=3&date='+lm2);
			createTiddlyText(a,lm2);
			break;
		case 'svn':
			s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
			a = createExternalLink(s,'https://repo.socialtext.net/listing.php?rev='+lm2+'sc=1');
			createTiddlyText(a,lm2);
			break;
		default:
			w.outputText(w.output,w.matchStart,w.nextMatch);
			return;
		}
		w.nextMatch = this.lookaheadRegExp.lastIndex;
	} else {
		w.outputText(w.output,w.matchStart,w.nextMatch);
	}
};

SocialtextFormatter.presence = function(w)
{
	this.lookaheadRegExp.lastIndex = w.matchStart;
	var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
	if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
		var p = lookaheadMatch[1];
		var text = lookaheadMatch[2];
		var link;
		var src;
		if(p=='aim') {
			link = 'aim:goim?screenname=' + text + '&message=hello';
			src = 'http://big.oscar.aol.com/sleepleft?on_url=http://www.aim.com/remote/gr/MNB_online.gif&amp;off_url=http://www.aim.com/remote/gr/MNB_offline.gif';
		} else if(p=='yahoo'||p=='ymsgr') {
			link = 'ymsgr:sendIM?'+text;
			src = 'http://opi.yahoo.com/online?u=chrislondonbridge&f=.gif';
		} else if(p=='skype'||p=='callto') {
			link = 'callto:'+text;
			src = 'http://goodies.skype.com/graphics/skypeme_btn_small_green.gif';
		} else if(p=='asap') {
			link = 'http://asap2.convoq.com/AsapLinks/Meet.aspx?l='+text;
			src = 'http://asap2.convoq.com/AsapLinks/Presence.aspx?l='+text;
		}
		var s = createTiddlyElement(w.output,'span',null,'nlw_phrase');
		var a = createExternalLink(s,link);
		var img = createTiddlyElement(a,'img');
		createTiddlyText(a,text);
		img.src = src;
		img.border='0';
		img.alt = '(' + lookaheadMatch[1] + ')';
		if(p=='aim') {
			img.width='11'; img.height='13';
		}
		w.nextMatch = this.lookaheadRegExp.lastIndex;
	}
};

config.formatterHelpers.singleCharFormat = function(w)
{
	this.lookaheadRegExp.lastIndex = w.matchStart;
	var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
	if(lookaheadMatch && lookaheadMatch.index == w.matchStart && lookaheadMatch[0].substr(lookaheadMatch[0].length-2,1) != ' ') {
		w.subWikifyTerm(createTiddlyElement(w.output,this.element),this.termRegExp);
	} else {
		w.outputText(w.output,w.matchStart,w.nextMatch);
	}
};

config.socialtext = {};
config.socialtext.formatters = [
{
	name: 'socialtextHeading',
	match: '^\\^{1,6} ?',
	termRegExp: /(\n+)/mg,
	handler: function(w)
	{
		var len = w.matchText.trim().length;
		var e = createTiddlyElement(w.output,'h' + len);
		var a = createTiddlyElement(e,'a');// drop anchor
		var t = w.tiddler ? w.tiddler.title + ':' : '';
		len = w.source.substr(w.nextMatch).indexOf('\n');
		a.setAttribute('name',t+w.source.substr(w.nextMatch,len));
		w.subWikifyTerm(e,this.termRegExp);
	}
},

{
	name: 'socialtextTable',
	match: '^\\|(?:(?:.|\n)*)\\|$',
	lookaheadRegExp: /^\|(?:(?:.|\n)*)\|$/mg,
	cellRegExp: /(?:\|(?:[^\|]*)\|)(\n|$)?/mg,
	cellTermRegExp: /((?:\x20*)\|)/mg,
	handler: function(w)
	{
		var table = createTiddlyElement(w.output,'table');
		var rowContainer = createTiddlyElement(table,'tbody');
		var prevColumns = [];
		w.nextMatch = w.matchStart;
		this.lookaheadRegExp.lastIndex = w.nextMatch;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		while(lookaheadMatch && lookaheadMatch.index == w.nextMatch) {
			var r = this.rowHandler(w,createTiddlyElement(rowContainer,'tr'),prevColumns);
			if(!r) {
				w.nextMatch++;
				break;
			}
			this.lookaheadRegExp.lastIndex = w.nextMatch;
			lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		}
	},
	rowHandler: function(w,e,prevColumns)
	{
		this.cellRegExp.lastIndex = w.nextMatch;
		var cellMatch = this.cellRegExp.exec(w.source);
		while(cellMatch && cellMatch.index == w.nextMatch) {
			w.nextMatch++;
			var cell = createTiddlyElement(e,'td');
			w.subWikifyTerm(cell,this.cellTermRegExp);
			if(cellMatch[1]) {
				// End of row
				w.nextMatch = this.cellRegExp.lastIndex;
				return true;
			}
			// Cell
			w.nextMatch--;
			this.cellRegExp.lastIndex = w.nextMatch;
			cellMatch = this.cellRegExp.exec(w.source);
		}
		return false;
	}
},

{
	name: 'socialtextList',
	match: '^[\\*#]+ ',
	lookaheadRegExp: /^([\*#])+ /mg,
	termRegExp: /(\n+)/mg,
	handler: function(w)
	{
		var stack = [w.output];
		var currLevel = 0, currType = null;
		var itemType = 'li';
		w.nextMatch = w.matchStart;
		this.lookaheadRegExp.lastIndex = w.nextMatch;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		while(lookaheadMatch && lookaheadMatch.index == w.nextMatch) {
			var listType = lookaheadMatch[1] == '*' ? 'ul' : 'ol';
			var listLevel = lookaheadMatch[0].length;
			w.nextMatch += listLevel;
			if(listLevel > currLevel) {
				for(var i=currLevel; i<listLevel; i++) {
					stack.push(createTiddlyElement(stack[stack.length-1],listType));
				}
			} else if(listLevel < currLevel) {
				for(i=currLevel; i>listLevel; i--) {
					stack.pop();
				}
			} else if(listLevel == currLevel && listType != currType) {
				stack.pop();
				stack.push(createTiddlyElement(stack[stack.length-1],listType));
			}
			currLevel = listLevel;
			currType = listType;
			var e = createTiddlyElement(stack[stack.length-1],itemType);
			w.subWikifyTerm(e,this.termRegExp);
			this.lookaheadRegExp.lastIndex = w.nextMatch;
			lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		}
	}
},

{
	name: 'socialtextQuoteByLine',
	match: '^>+',
	lookaheadRegExp: /^>+/mg,
	termRegExp: /(\n)/mg,
	element: 'blockquote',
	handler: function(w)
	{
		var stack = [w.output];
		var currLevel = 0;
		var newLevel = w.matchLength;
		var i;
		do {
			if(newLevel > currLevel) {
				for(i=currLevel; i<newLevel; i++) {
					stack.push(createTiddlyElement(stack[stack.length-1],this.element));
				}
			} else if(newLevel < currLevel) {
				for(i=currLevel; i>newLevel; i--) {
					stack.pop();
				}
			}
			currLevel = newLevel;
			w.subWikifyTerm(stack[stack.length-1],this.termRegExp);
			createTiddlyElement(stack[stack.length-1],'br');
			this.lookaheadRegExp.lastIndex = w.nextMatch;
			var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
			var matched = lookaheadMatch && lookaheadMatch.index == w.nextMatch;
			if(matched) {
				newLevel = lookaheadMatch[0].length;
				w.nextMatch += newLevel;
			}
		} while(matched);
	}
},

{
	name: 'socialtextRule',
	match: '^----+$\\n+',
	handler: function(w)
	{
		createTiddlyElement(w.output,'hr');
	}
},

{
	name: 'socialtextPreformatted',
	match: '^\\.pre\\s*\\n',
	lookaheadRegExp: /^.pre\s*\n((?:.|\n)*?)\n.pre\s*\n/mg,
	element: 'pre',
	handler: config.formatterHelpers.enclosedTextHelper
},

{
	name: 'socialtextHtml',
	match: '^\\.html',
	lookaheadRegExp: /\.html((?:.|\n)*?)\.html/mg,
	handler: function(w)
	{
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
			createTiddlyElement(w.output,'span').innerHTML = lookaheadMatch[1];
			w.nextMatch = this.lookaheadRegExp.lastIndex;
		}
	}
},

{
	name: 'macro',
	match: '<<',
	lookaheadRegExp: /<<([^>\s]+)(?:\s*)((?:[^>]|(?:>(?!>)))*)>>/mg,
	handler: function(w)
	{
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart && lookaheadMatch[1]) {
			w.nextMatch = this.lookaheadRegExp.lastIndex;
			invokeMacro(w.output,lookaheadMatch[1],lookaheadMatch[2],w,w.tiddler);
		}
	}
},

{
	name: 'socialtextExplicitLink',
	match: '(?:".*?" ?)?\\[',
	lookaheadRegExp: /(?:\"(.*?)\" ?)?\[([^\]]*?)\]/mg,
	handler: function(w)
	{
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
			var link = lookaheadMatch[2];
			var text = lookaheadMatch[1] ? lookaheadMatch[1] : link;
			createTiddlyText(createTiddlyLink(w.output,link,false,null,w.isStatic,w.tiddler),text);
			w.nextMatch = this.lookaheadRegExp.lastIndex;
		}
	}
},

{
	name: 'socialtextExternalLink',
	match: '(?:".*?" ?)?<[a-z]{2,8}:',
	lookaheadRegExp: /(?:\"(.*?)\" ?)?<([a-z]{2,8}:.*?)>/mg,
	imgRegExp: /\.(?:gif|ico|jpg|png)/g,
	handler: function(w)
	{
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
			var link = lookaheadMatch[2];
			var text = lookaheadMatch[1] ? lookaheadMatch[1] : link;
			this.imgRegExp.lastIndex = 0;
			if(this.imgRegExp.exec(link)) {
				var img = createTiddlyElement(w.output,'img');
				if(lookaheadMatch[1]) {
					img.title = text;
				}
				img.alt = text;
				img.src = link;
			} else {
				createTiddlyText(createExternalLink(w.output,link),text);
			}
			w.nextMatch = this.lookaheadRegExp.lastIndex;
		}
	}
},

{
	name: 'socialtextUrlLink',
	match: config.textPrimitives.urlPattern,
	handler: function(w)
	{
		w.outputText(createExternalLink(w.output,w.matchText),w.matchStart,w.nextMatch);
	}
},

{
	name: 'socialtextBold',
	match: '\\*(?![\\s\\*])',
	lookaheadRegExp: /\*(?!\s)(?:.*?)(?!\s)\*(?=[$\s\|\._\-,])/mg,
	termRegExp: /((?!\s)\*(?=[$\s\|\.\-_,]))/mg,
	element: 'strong',
	handler: config.formatterHelpers.singleCharFormat
},

{
	name: 'socialtextItalic',
	match: '_(?![\\s_])',
	lookaheadRegExp: /_(?!\s)(?:.*?)(?!\s)_(?=[$\s\|\.\*\-,])/mg,
	termRegExp: /((?!\s)_(?=[$\s\|\.\*\-,]))/mg,
	element: 'em',
	handler: config.formatterHelpers.singleCharFormat
},

{
	name: 'socialtextStrike',
	match: '-(?![\\s\\-])',
	lookaheadRegExp: /-(?!\s)(?:.*?)(?!\s)-(?=[$\s\|\.\*_,])/mg,
	termRegExp: /((?!\s)-(?=[$\s\|\.\*_,]))/mg,
	element: 'del',
	handler: config.formatterHelpers.singleCharFormat
},

{
	name: 'socialtextMonoSpaced',
	match: '`(?![\\s`])',
	lookaheadRegExp: /`(?!\s)(?:.*?)(?!\s)`(?=[$\s\.\*\-_,])/mg,
	termRegExp: /((?!\s)`(?=[$\s\.\*\-_,]))/mg,
	element: 'tt',
	handler: config.formatterHelpers.singleCharFormat
},

{
	name: 'socialtextParagraph',
	match: '\\n{2,}',
	handler: function(w)
	{
		createTiddlyElement(w.output,'p');
	}
},

{
	name: 'socialtextLineBreak',
	match: '\\n',
	handler: function(w)
	{
		createTiddlyElement(w.output,'br');
	}
},

{
	name: 'socialtextNoWiki',
	match: '\\{\\{',
	lookaheadRegExp: /\{\{((?:.|\n)*?)\}\}/mg,
	element: 'span',
	handler: config.formatterHelpers.enclosedTextHelper
},

{
	name: 'socialtextTrademark',
	match: '\\{tm\\}',
	handler: function(w)
	{
		createTiddlyElement(w.output,'span').innerHTML = '&trade;';
	}
},

{
	name: 'socialtextWafl',
	match: '\\{(?:[a-z]{2,16}): ?.*?\\}',
	lookaheadRegExp: /\{([a-z]{2,16}): ?(.*?)\}/mg,
	handler: SocialtextFormatter.wafl
},

{
	name: 'socialtextPresence',
	match: '(?:aim|yahoo|ymsgr|skype|callto|asap):\\w+',
	lookaheadRegExp: /(aim|yahoo|ymsgr|skype|callto|asap):(\w+)/mg,
	handler: SocialtextFormatter.presence
},

{
	name: 'socialtextMailTo',
	match: '[\\w\.]+@[\\w]+\.[\\w\.]+',
	lookaheadRegExp: /([\w\.]+@[\w]+\.[\w\.]+)/mg,
	handler: function(w)
	{
		this.lookaheadRegExp.lastIndex = w.matchStart;
		var lookaheadMatch = this.lookaheadRegExp.exec(w.source);
		if(lookaheadMatch && lookaheadMatch.index == w.matchStart) {
			var text = lookaheadMatch[1];
			createTiddlyText(createExternalLink(w.output,'mailto:'+text),text);
			w.nextMatch = this.lookaheadRegExp.lastIndex;
		}
	}
},

{
	name: 'socialtextHtmlEntitiesEncoding',
	match: '&#?[a-zA-Z0-9]{2,8};',
	handler: function(w)
	{
		createTiddlyElement(w.output,'span').innerHTML = w.matchText;
	}
}
];

config.parsers.socialtextFormatter = new Formatter(config.socialtext.formatters);
config.parsers.socialtextFormatter.format = 'socialtext';
config.parsers.socialtextFormatter.formatTag = 'SocialtextFormat';

} // end of 'install only once'
//}}}
/***
|''Name:''|SocialtextAdaptorPlugin|
|''Description:''|Adaptor for moving and converting data to and from Socialtext Wikis|
|''Author:''|Martin Budden (mjbudden (at) gmail (dot) com) and JeremyRuston (jeremy (at) osmosoft (dot) com)|
|''Source:''|http://www.martinswiki.com/#SocialtextAdaptorPlugin|
|''CodeRepository:''|http://svn.tiddlywiki.org/Trunk/contributors/MartinBudden/adaptors/SocialtextAdaptorPlugin.js|
|''Version:''|0.5.1|
|''Date:''|Feb 25, 2007|
|''Comments:''|Please make comments at http://groups.google.co.uk/group/TiddlyWikiDev|
|''License:''|[[Creative Commons Attribution-ShareAlike 2.5 License|http://creativecommons.org/licenses/by-sa/2.5/]]|
|''~CoreVersion:''|2.2.0|

Socialtext REST documentation is at:
http://www.eu.socialtext.net/st-rest-docs/index.cgi?socialtext_rest_documentation

***/

//{{{
if(!version.extensions.SocialtextAdaptorPlugin) {
version.extensions.SocialtextAdaptorPlugin = {installed:true};

function SocialtextAdaptor()
{
	this.host = null;
	this.workspace = null;
	return this;
}

SocialtextAdaptor.mimeType = 'text/x.socialtext-wiki';
SocialtextAdaptor.serverType = 'socialtext';
SocialtextAdaptor.serverParsingErrorMessage = "Error parsing result from server";
SocialtextAdaptor.errorInFunctionMessage = "Error in function SocialtextAdaptor.%0";

SocialtextAdaptor.prototype.setContext = function(context,userParams,callback)
{
	if(!context) context = {};
	context.userParams = userParams;
	if(callback) context.callback = callback;
	context.adaptor = this;
	if(!context.host)
		context.host = this.host;
	if(!context.workspace && this.workspace)
		context.workspace = this.workspace;
	return context;
};

SocialtextAdaptor.doHttpGET = function(uri,callback,params,headers,data,contentType,username,password)
{
	return doHttp('GET',uri,data,contentType,username,password,callback,params,headers);
};

SocialtextAdaptor.doHttpPOST = function(uri,callback,params,headers,data,contentType,username,password)
{
	return doHttp('POST',uri,data,contentType,username,password,callback,params,headers);
};

SocialtextAdaptor.fullHostName = function(host)
{
	if(!host)
		return '';
	if(!host.match(/:\/\//))
		host = 'http://' + host;
	if(host.substr(host.length-1) != '/')
		host = host + '/';
	return host;
};

SocialtextAdaptor.minHostName = function(host)
{
	return host ? host.replace(/^http:\/\//,'').replace(/\/$/,'') : '';
};

// Convert a page title to the normalized form used in uris
SocialtextAdaptor.normalizedTitle = function(title)
{
	var n = title.toLowerCase();
	n = n.replace(/\s/g,'_').replace(/\//g,'_').replace(/\./g,'_').replace(/:/g,'').replace(/\?/g,'');
	if(n.charAt(0)=='_')
		n = n.substr(1);
	return String(n);
};

// Convert a Socialtext date in YYYY-MM-DD hh:mm format into a JavaScript Date object
SocialtextAdaptor.dateFromEditTime = function(editTime)
{
	var dt = editTime;
	return new Date(Date.UTC(dt.substr(0,4),dt.substr(5,2)-1,dt.substr(8,2),dt.substr(11,2),dt.substr(14,2)));
};

SocialtextAdaptor.prototype.openHost = function(host,context,userParams,callback)
{
	this.host = SocialtextAdaptor.fullHostName(host);
	context = this.setContext(context,userParams,callback);
	if(context.callback) {
		context.status = true;
		window.setTimeout(function() {callback(context,userParams);},0);
	}
	return true;
};

SocialtextAdaptor.prototype.openWorkspace = function(workspace,context,userParams,callback)
{
	this.workspace = workspace;
	context = this.setContext(context,userParams,callback);
	if(context.callback) {
		context.status = true;
		window.setTimeout(function() {callback(context,userParams);},0);
	}
	return true;
};


SocialtextAdaptor.prototype.getWorkspaceList = function(context,userParams,callback)
{
	context = this.setContext(context,userParams,callback);
	var uriTemplate = '%0data/workspaces';
	var uri = uriTemplate.format([context.host]);
	var req = SocialtextAdaptor.doHttpGET(uri,SocialtextAdaptor.getWorkspaceListCallback,context,{'accept':'application/json'});
	return typeof req == 'string' ? req : true;
};

SocialtextAdaptor.getWorkspaceListCallback = function(status,context,responseText,uri,xhr)
{
	context.status = false;
	context.statusText = SocialtextAdaptor.errorInFunctionMessage.format(['getWorkspaceListCallback']);
	if(status) {
		try {
			eval('var info=' + responseText);
		} catch (ex) {
			context.statusText = exceptionText(ex,SocialtextAdaptor.serverParsingErrorMessage);
			if(context.callback)
				context.callback(context,context.userParams);
			return;
		}
		var list = [];
		for(var i=0; i<info.length; i++) {
			var item = {
				title:info[i].title,
				name:info[i].name,
				modified:SocialtextAdaptor.dateFromEditTime(info[i].modified_time)
				};
			list.push(item);
		}
		context.workspaces = list;
		context.status = true;
	} else {
		context.statusText = xhr.statusText;
	}
	if(context.callback)
		context.callback(context,context.userParams);
};

SocialtextAdaptor.prototype.getTiddlerList = function(context,userParams,callback)
{
	context = this.setContext(context,userParams,callback);
	var uriTemplate = '%0data/workspaces/%1/pages?order=newest';//!! ? or ;
	var uri = uriTemplate.format([context.host,context.workspace]);
	var req = SocialtextAdaptor.doHttpGET(uri,SocialtextAdaptor.getTiddlerListCallback,context,{'accept':'application/json'});
	return typeof req == 'string' ? req : true;
};


SocialtextAdaptor.getTiddlerListCallback = function(status,context,responseText,uri,xhr)
{
	context.status = false;
	context.statusText = SocialtextAdaptor.errorInFunctionMessage.format(['getTiddlerListCallback']);
	if(status) {
		try {
			eval('var info=' + responseText);
		} catch (ex) {
			context.statusText = exceptionText(ex,SocialtextAdaptor.serverParsingErrorMessage);
			if(context.callback)
				context.callback(context,context.userParams);
			return;
		}
		var list = [];
		for(var i=0; i<info.length; i++) {
			var tiddler = new Tiddler(info[i].name);
			tiddler.modified = SocialtextAdaptor.dateFromEditTime(info[i].last_edit_time);
			tiddler.modifier = info[i].last_editor;
			tiddler.tags = info[i].tags;
			tiddler.fields['server.page.id'] = info[i].page_id;
			tiddler.fields['server.page.name'] = info[i].name;
			tiddler.fields['server.page.revision'] = String(info[i].revision_id);
			list.push(tiddler);
		}
		context.tiddlers = list;
		context.status = true;
	} else {
		context.statusText = xhr.statusText;
	}
	if(context.callback)
		context.callback(context,context.userParams);
};

SocialtextAdaptor.prototype.generateTiddlerInfo = function(tiddler)
{
	var info = {};
	var host = this && this.host ? this.host : SocialtextAdaptor.fullHostName(tiddler.fields['server.host']);
	var workspace = this && this.workspace ? this.workspace : tiddler.fields['server.workspace'];
	uriTemplate = '%0%1/index.cgi?%2';
	info.uri = uriTemplate.format([host,workspace,SocialtextAdaptor.normalizedTitle(tiddler.title)]);
	return info;
};

SocialtextAdaptor.prototype.getTiddler = function(title,context,userParams,callback)
{
	return this.getTiddlerRevision(title,null,context,userParams,callback);
};

SocialtextAdaptor.prototype.getTiddlerRevision = function(title,revision,context,userParams,callback)
{
	context = this.setContext(context,userParams,callback);

	// request the page in json format to get the page attributes
	if(revision) {
		var uriTemplate = '%0data/workspaces/%1/pages/%2/revisions/%3';
		context.revision = revision;
	} else {
		uriTemplate = '%0data/workspaces/%1/pages/%2';
		context.revision = null;
	}
	uri = uriTemplate.format([context.host,context.workspace,SocialtextAdaptor.normalizedTitle(title),revision]);

	context.tiddler = new Tiddler(title);
	context.tiddler.fields.wikiformat = 'socialtext';
	context.tiddler.fields['server.host'] = SocialtextAdaptor.minHostName(context.host);
	context.tiddler.fields['server.workspace'] = context.workspace;
	var req = SocialtextAdaptor.doHttpGET(uri,SocialtextAdaptor.getTiddlerCallback,context,{'accept':'application/json'});
	return typeof req == 'string' ? req : true;
};


SocialtextAdaptor.getTiddlerCallback = function(status,context,responseText,uri,xhr)
{
	context.status = false;
	context.statusText = SocialtextAdaptor.errorInFunctionMessage.format(['getTiddlerCallback']);
	if(status) {
		try {
			eval('var info=' + responseText);
			context.tiddler.tags = info.tags;
			context.tiddler.fields['server.page.id'] = info.page_id;
			context.tiddler.fields['server.page.name'] = info.name;
			context.tiddler.fields['server.page.revision'] = String(info.revision_id);
			context.tiddler.modifier = info.last_editor;
			context.tiddler.modified = SocialtextAdaptor.dateFromEditTime(info.last_edit_time);
		} catch (ex) {
			context.statusText = exceptionText(ex,SocialtextAdaptor.serverParsingErrorMessage);
			if(context.callback)
				context.callback(context,context.userParams);
			return;
		}
		context.status = true;
	} else {
		context.statusText = xhr.statusText;
		if(context.callback)
			context.callback(context,context.userParams);
		return;
	}
	var uriTemplate = context.revision ? '%0data/workspaces/%1/pages/%2/revisions/%3' : '%0data/workspaces/%1/pages/%2';
	var host = SocialtextAdaptor.fullHostName(context.tiddler.fields['server.host']);
	var workspace = context.workspace ? context.workspace : context.tiddler.fields['server.workspace'];
	uri = uriTemplate.format([host,workspace,SocialtextAdaptor.normalizedTitle(context.tiddler.title),context.revision]);
	var req = SocialtextAdaptor.doHttpGET(uri,SocialtextAdaptor.getTiddlerCallback2,context,{'accept':SocialtextAdaptor.mimeType});
};

SocialtextAdaptor.getTiddlerCallback2 = function(status,context,responseText,uri,xhr)
{
	context.tiddler.text = responseText;
	if(status) {
		context.status = true;
	} else {
		context.status = false;
		context.statusText = xhr.statusText;
	}
	if(context.callback)
		context.callback(context,context.userParams);
};

SocialtextAdaptor.prototype.getTiddlerRevisionList = function(title,limit,context,userParams,callback)
{
	context = this.setContext(context,userParams,callback);

	var uriTemplate = '%0data/workspaces/%1/pages/%2/revisions?accept=application/json';
	if(!limit)
		limit = 5;
	var uri = uriTemplate.format([context.host,context.workspace,SocialtextAdaptor.normalizedTitle(title),limit]);

	var req = SocialtextAdaptor.doHttpGET(uri,SocialtextAdaptor.getTiddlerRevisionListCallback,context);
	return typeof req == 'string' ? req : true;
};

SocialtextAdaptor.getTiddlerRevisionListCallback = function(status,context,responseText,uri,xhr)
{
	context.status = false;
	if(status) {
		var content = null;
		try {
			eval('var info=' + responseText);
		} catch (ex) {
			context.statusText = exceptionText(ex,SocialtextAdaptor.serverParsingErrorMessage);
			if(context.callback)
				context.callback(context,context.userParams);
			return;
		}
		list = [];
		for(var i=0; i<info.length; i++) {
			var tiddler = new Tiddler(info[i].name);
			tiddler.modified = SocialtextAdaptor.dateFromEditTime(info[i].last_edit_time);
			tiddler.modifier = info[i].last_editor;
			tiddler.tags = info[i].tags;
			tiddler.fields['server.page.id'] = info[i].page_id;
			tiddler.fields['server.page.name'] = info[i].name;
			tiddler.fields['server.page.revision'] = info[i].revision_id;
			list.push(tiddler);
		}
		var sortField = 'server.page.revision';
		list.sort(function(a,b) {return a.fields[sortField] < b.fields[sortField] ? +1 : (a.fields[sortField] == b.fields[sortField] ? 0 : -1);});
		context.revisions = list;
		context.status = true;
	} else {
		context.statusText = xhr.statusText;
	}
	if(context.callback)
		context.callback(context,context.userParams);
};

SocialtextAdaptor.prototype.putTiddler = function(tiddler,context,userParams,callback)
{
	context = this.setContext(context,userParams,callback);
	context.tiddler = tiddler;
	context.title = tiddler.title;
	var uriTemplate = '%0data/workspaces/%1/pages/%2';
	var host = context.host ? context.host : SocialtextAdaptor.fullHostName(tiddler.fields['server.host']);
	var workspace = context.workspace ? context.workspace : tiddler.fields['server.workspace'];
	var uri = uriTemplate.format([host,workspace,tiddler.title,tiddler.text]);
	//var req = doHttp('POST',uri,tiddler.text,SocialtextAdaptor.mimeType,null,null,SocialtextAdaptor.putTiddlerCallback,context,{"X-Http-Method": "PUT"});
	var req = SocialtextAdaptor.doHttpPOST(uri,SocialtextAdaptor.putTiddlerCallback,context,{"X-Http-Method": "PUT"},tiddler.text,SocialtextAdaptor.mimeType);
	return typeof req == 'string' ? req : true;
};

SocialtextAdaptor.putTiddlerCallback = function(status,context,responseText,uri,xhr)
{
	if(status) {
		context.status = true;
	} else {
		context.status = false;
		context.statusText = xhr.statusText;
	}
	if(context.callback)
		context.callback(context,context.userParams);
};

SocialtextAdaptor.prototype.close = function()
{
	return true;
};

config.adaptors[SocialtextAdaptor.serverType] = SocialtextAdaptor;
} //# end of 'install only once'
//}}}
/***
SocialtextStyleOverrides
***/

/*{{{*/
.headerShadow {padding: 2em 0em .5em 1em;}
.headerForeground {padding: 2em 0em .5em 1em;}

#st-page-wiki-title {
	font-size: 80%;
}
.subtitle {
	font-style: italic;
	font-size 80%;
}

/* from #st-tags */
.tagged {
	border-color: #bbeebb;
	background-color: #f4fff4;
}

.tagged .listTitle {
	color: #595;
	font-weight: bold;
}

.tagged .button {
	color: #000;
}

.selected .tagged {
	background-color: ColorPalette::TertiaryLight;
	border: 1px solid ColorPalette::TertiaryMid;
}

/* from #st-incoming-links */
.tagging {
	border-color: #ebb;
	background-color: #fff4f4;
}

.tagging .listTitle {
	color: #b78;
	font-weight: bold;
}

.tagging .button {
	color: #999;
}

.selected .tagging {
	background-color: ColorPalette::TertiaryLight;
	border: 1px solid ColorPalette::TertiaryMid;
}

.tiddler {/* Tiddler body */
	border:1px solid #ccc;
	margin:0.5em;
	background:#fff;
	padding:0.5em;
}

.viewer blockquote {border-left: 0px solid}

.tiddlyLinkNonExisting {
	font-style: italic;
	border-bottom: 1px dashed;
}

.editor input, .editor textarea {
	background: #ffd;
	border-style: solid;
	border-color: #888 #ccc #ccc #888;
	border-width: 2px;
}

.tabContents {white-space: nowrap;}

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

#sidebar {
	position: absolute;
	right: 3px;
	width: 21em;
	font-size: .9em;
}

#sidebarOptions .button {
	border-color: #eee;
}

#sidebarTabs .tabContents {
	width: 20em;
	overflow: hidden;
}

.viewer tt {
	font-size: 1.2em;
	line-height: 1.4em;
}

ul {list-style-type: square;}
ul ul {list-style-type: circle;}

ol {list-style-type: decimal;}
ol ol {list-style-type: decimal;}
ol ol ol {list-style-type: decimal;}
ol ol ol ol {list-style-type: decimal;}
ol ol ol ol ol {list-style-type: decimal;}
ol ol ol ol ol ol {list-style-type: decimal;}

/*}}}*/
/***
SocialtextScreenStyle
http://www.eu.socialtext.net/static/2.0.0.1/css/st/screen.css
***/

/*{{{*/
body {
	font-family: Arial, sans-serif;
	color: #000;
	background: #eee;
	margin: 0;
}

/* Wiki Navigation */

.st-wiki-nav {
	clear: both;
	margin-left: 10px;
	margin-right: 10px;
}
.st-wiki-nav-content {
	background: url('../../images/st/wiki-nav/solid.gif') repeat-x left bottom;
	margin-left: 24px;
	margin-right: 24px;
	padding-top: 3px;
	min-height: 24px;
}
* html .st-wiki-nav-content {
	padding-bottom: 3px;
	height: 24px;
}

.st-wiki-nav-right {
	background: url('../../images/st/wiki-nav/right-round.gif') no-repeat bottom right;
}

.st-wiki-nav-left {
	background: url('../../images/st/wiki-nav/left-round.gif') no-repeat bottom left;
}

#st-home {
	float: left;
	margin-right: 60px;
	padding-top: 2px;
}

#st-home-link {
	color: white;
	text-decoration: none;
	font-weight: bold;
	font-family: Helvetica, sans-serif;
	font-size: 90%;
}

#st-editing-prefix-container {
	border-collapse: collapse;
	width: 100%;
	padding: 0px;
	margin: 0px;
	margin-bottom: -20px;
}

#st-editing-prefix-container tr td {
	margin: 0px;
	padding: 0px;
}

#st-editing-title {
	color: black;
	background-color: white;
	text-decoration: none;
	font-weight: bold;
	font-family: Helvetica, sans-serif;
	font-size: 90%;
	margin-bottom: 0.4em;
}

#st-wiki-title-invite {
	font-size: 50%;
	font-family: Helvetica, sans-serif;
}

#st-wiki-title-central-page-link {
	font-size: 50%;
	font-family: Helvetica, sans-serif;
}

#st-wiki-title-invite a {
	color: #00f;
}

#st-wiki-logo {
	text-align: center;
	clear: both;
}

#st-wiki-logo-image {
}

.st-wiki-nav-actions {
	float: right;
	color: black;
	font-size: 75%;
	padding-top: 3px;
}

.st-wiki-nav-actions a {
	padding: 2px;
	color: white;
	text-decoration: none;
	font-family: Helvetica, sans-serif;
}

/* Wiki Subnav */

#st-wiki-subnav {
	margin-top: 2px;
	font-size: 70%;
	font-weight: bold;
	font-family: Helvetica, sans-serif;
	color: #888;
}

#st-wiki-subnav a {
	padding: 2px;
	color: #008;
	text-decoration: none;
}

#st-wiki-subnav-right {
	float: right;
	margin-right: 6em;
}

#st-wiki-subnav-left {
	float: left;
	margin-left: 6em;
}
* html #st-wiki-subnav-left {
	margin-left: 3em;
}

/* Wiki Navigation Search Bar */

#st-search-form {
	margin: 0;
	padding: 0;
	padding-top: 1px;
}

#st-search-form .button-table {
	float: left;
	font-size: 79%;
	font-weight: bold;
	margin-left: 5px;
	margin-top: 1px;
}

#st-search-form #st-search-term {
	float: left;
	font-size: 60%;
}

/* Content Outline */

#st-content-border, #st-edit-border {
	position: relative;
	clear: both;
	margin-left: 3px;
	margin-right: 2px;
	margin-bottom: 0px;
	margin-top: 0px;
	border-bottom: 1px solid #eee;
}

#st-content-border-left, #st-edit-border-left {
	background: url('../../images/st/page-shadow/left.gif') left top repeat-y;
	position: relative;
}

#st-content-border-right, #st-edit-border-right {
	background: url('../../images/st/page-shadow/right.gif') right top repeat-y;
	position: relative;
}

#st-content-border-top, #st-edit-border-top {
	position: relative;
	background: url('../../images/st/page-shadow/top.gif') left top repeat-x;
}

#st-content-border-bottom, #st-edit-border-bottom {
	background: url('../../images/st/page-shadow/bottom.gif') left bottom repeat-x;
	position: relative;
}

#st-content-border-left-top, #st-edit-border-left-top {
	background: url('../../images/st/page-shadow/left-top.gif') left top no-repeat;
	position: relative;
}
#st-content-border-right-top, #st-edit-border-right-top {
	background: url('../../images/st/page-shadow/right-top.gif') right top no-repeat;
	position: relative;
}

#st-content-border-left-bottom, #st-edit-border-left-bottom {
	background: url('../../images/st/page-shadow/left-bottom.gif') left bottom no-repeat;
	position: relative;
}

#st-content-border-right-bottom, #st-edit-border-right-bottom {
	background: url('../../images/st/page-shadow/right-bottom.gif') right bottom no-repeat;
	padding-top: 5px;
	padding-bottom: 9px;
	position: relative;
}

* html #st-content-border-right-bottom, * html #st-edit-border-right-bottom {
	padding-top: 4px;
	padding-left: 7px;
	padding-right: 8px;
	position: relative;
}

.st-content-width-controller {
	width: 100%;
	position: relative;
	border-collapse: collapse;
}
.st-content-width-controller td {
	vertical-align: top;
}
.st-content {
	position: relative;
	background-color: white;
	margin-top: 0px;
	margin-left: 7px;
	margin-right: 8px;
	margin-bottom: -1px;
	border-left: 1px dotted #80a9f3;
	border-right: 1px dotted #80a9f3;
	border: 1px solid #80a9f3;
	padding: 6px 12px 12px 12px;
}
* html .st-content {
	margin-top: 0px;
	margin-left: 0px;
	margin-right: 0px;
}

/* This textarea is only for Safari. However, if we use display:none; here Safari ignores the .value operation in JS */
#st-raw-wikitext-textarea {
	width:1px;
	height:1px;
	margin:0;
	padding:0;
}

/* Action Buttons */
.button-table, .button-table tr td {
	border-collapse: collapse;
	margin: 0;
	padding: 0;
}
.button-rounded {
	background: url('../../images/st/grey-button/left-top-rounded.png') top left no-repeat;
	margin: 0;
}
.button-rounded-right-top {
	background: url('../../images/st/grey-button/right-top-rounded.png') top right no-repeat;
	margin: 0;
}
.button-rounded-left-bottom {
	background: url('../../images/st/grey-button/left-bottom-rounded.png') bottom left no-repeat;
	margin: 0;
}
.button-rounded-right-bottom {
	background: url('../../images/st/grey-button/right-bottom-rounded.png') bottom right no-repeat;
	margin: 0;
}
.button-straight {
	background: url('../../images/st/grey-button/left-top-straight.png') top left no-repeat;
	margin: 0;
}
.button-straight-right-top {
	background: url('../../images/st/grey-button/right-top-straight.png') top right no-repeat;
	margin: 0;
}
.button-straight-left-bottom {
	background: url('../../images/st/grey-button/left-bottom-straight.png') bottom left no-repeat;
	margin: 0;
}
.button-straight-right-bottom {
	background: url('../../images/st/grey-button/right-bottom-straight.png') bottom right no-repeat;
	margin: 0;
}
.button-content {
	font-size: 90%;
}
.button-content a {
	display: block;
	padding: 2px;
	padding-left: 10px;
	padding-right: 10px;
	font-family: Helvetica, Verdana, sans-serif;
	font-weight: bold;
	text-decoration: none;
	color: black;
}

.button-content input.submit {
	border: 0px;
	padding: 2px;
	padding-left: 10px;
	padding-right: 10px;
	font-family: Helvetica, Verdana, sans-serif;
	font-weight: bold;
	text-decoration: none;
	color: black;
	background-color: transparent;
}

/* Personal Homepage */

#st-homepage {
	background: white url('../../images/st/homepage/blue-fade.gif') top left no-repeat;
}

#st-homepage-layout {
	margin-top: 15px;
	clear: both;
	width: 100%;
	border-collapse: collapse;
}

#st-homepage-layout tr td.st-homepage-layout-cell {
	padding: 5px;
	vertical-align: top;
}

#st-homepage-layout-dashboard {
	width: 50%
}

#st-homepage-layout-notes {
	width: 50%;
}

#st-homepage-notes, #st-homepage-dashboard {
	text-align: left;
	width: 95%;
}

#st-user-greeting, #st-wiki-title {
	font-family: Helvetica, Verdana, sans-serif;
	font-size: 150%;
}
#st-wiki-title {
	margin-left: 5px;
}

#st-user-greeting {
	position: relative;
	text-align: right;
	float: right;
}

#st-group-notes-content, #st-personal-notes-content {
}

.st-homepage-section {
	margin-bottom: 15px;
}

#st-homepage-notes .st-homepage-section {
	background-color: white;
	border: 1px solid #aaa;
	padding: 15px;
}

.st-homepage-section-title {
	font-size: 110%;
	font-family: Helvetica, Verdana, sans-serif;
}

#st-homepage-notes .st-homepage-section-title {
	color: #aaa;
	text-decoration: underline;
}

.st-homepage-notes-edit-link {
	background: url('../../images/st/homepage/edit-icon.gif') no-repeat left top;
	display: block;
	text-indent: -2000px;
	height: 13px;
	width: 36px;
	text-decoration: none;
	padding:0;
}
* html .st-homepage-notes-edit-link {
	border:1px solid white;
}

.st-homepage-notes-edit {
	font-family: Verdana, sans-serif;
	font-size: 65%;
	float: right;
}

.st-homepage-notes-content {
	font-size: 85%;
	margin-top: 10px;
	padding-top: 0px;
	padding-bottom: 0px;
	font-family: Verdana, Helvetica, sans-serif;
}

#st-dyk {
	border-color: #cca !important;
	background-color: #ffe !important;
}

#st-dyk-title {
	color: #e4a020 !important;
	text-decoration: none !important;
}


/* Homepage Simple List */

#st-whats-new-title-link {
	background: url('../../images/st/homepage/icon-28-pages.gif') no-repeat left top;
}
#st-watchlist-title-link {
	background: url('../../images/st/homepage/icon-28-star.gif') no-repeat left top;
}
#st-wikis-title-link {
	background: url('../../images/st/homepage/icon-28-group.gif') no-repeat left top;
}
.st-homepage-simplelist-title-link {
	display: block;
	padding-left: 32px;
	min-height: 32px;
}
* html .st-homepage-simplelist-title-link {
	height: 32px;
}

.st-homepage-simplelist-title {
}

.st-homepage-simplelist-table {
	margin-left: 25px;
	border: 1px dashed #ddd;
	border-collapse: collapse;
	font-family: Verdana, Helvetica, sans-serif;
	font-size: 80%;
	width: 95%;
}

.st-homepage-simplelist-table td {
	padding: 2px;
}

.st-homepage-simplelist-table tr.st-homepage-simplelist-row-odd {
	background-color: #f3f7f7;
}

.st-homepage-simplelist-table tr.st-homepage-simplelist-row-even {
	background-color: white;
}

.st-homepage-simplelist-table a {
	color: #4f55dd;
	text-decoration: none;
}

.st-homepage-simplelist-table a:visited {
	color: #551a8b;
}

.st-homepage-simplelist-subleft {
	font-size: 80%;
	margin-left: 1em;
	color: #666;
}

.st-homepage-simplelist-right {
	width: 20%;
}

.st-homepage-simplelist-subright {
	font-size: 80%;
	color: #666;
}

.st-homepage-simplelist {
}

.st-homepage-simplelist-header {
	min-height: 35px;
}

.st-homepage-simplelist-header .button-table {
	float: right;
	margin-right: 15px;
	font-size: 95%;
}

.st-homepage-simplelist-header .button-table .button-content {
	padding: 1px;
}

.st-homepage-whatsnew-author, .st-homepage-whatsnew-date {
	color: #555;
}
.st-homepage-whatsnew-attribution {
	padding-left: 1em;
	font-size: 80%;
	color: #aaa;
}

/* Homepage Wikis List */

#st-wikis-title {
}

/* Data and Templates */

.st-jst-template, .st-json {
	display: none;
}

/* Page Sidebox Common Styles */

#st-page-boxes-toggle {
	position: relative;
	float: right;
	text-align: right;
	font-family: Verdana, Arial, sans-serif;
	font-weight: bold;
	font-size: 80%;
	margin-bottom: 0.7em;
}

#st-page-boxes-toggle-link {
	text-decoration: none;
}

#st-page-boxes-underlay {
	float: right;
	margin-top: -10px;
	margin-right: 10px;
	background: white;
	z-index: 198;
	clear: both;
	margin-left: 15px;
}
* html #st-page-boxes-underlay {
	margin-right: 4px;
}
#st-page-boxes {
	background: inherit;
	position: absolute;
	right: 23px;
	z-index: 199;
	margin-top: 15px;
	margin-left: 20px;
}
#st-page-boxes, #st-page-boxes-underlay {
	width: 225px;
	/* padding-left: 15px; */ /* Gives the white border effect, cwest dislikes it. */
}

.st-page-box {
	border: 1px solid black;
	padding: 5px;
	font-family: Verdana, Helvetica, sans-serif;
	font-size: 80%;
	margin-top: 15px;
}

.st-page-box-title {
	font-family: Helvetica, Verdana, sans-serif;
	font-weight: bold;
	margin-bottom: 10px;
}

.st-page-box-listing {
	margin: 0;
	padding: 0;
}

.st-page-box-listing-entry {
	display: block;
}

.st-page-boxes-nobacklinks {
	font-family: Verdana, Helvetica, sans-serif;
	font-size: 90%;
	color: #888;
}

.st-page-box-first {
	margin-top: 0px;
}

/* Page Display */

#st-page-content {
	clear: left;
	margin-top: 6px;
	margin-bottom: 0;
	padding-bottom: 0;
}

#st-page-content, #st-page-content td {
	font-family: Verdana, Helvetica, sans-serif;
	font-size: 90%;
}

#st-page-wiki-title {
	font-family: Helvetica, Verdana, sans-serif;
	font-size: 65%;
	font-weight: bold;
	color: #aaa;
	margin-bottom: 0.2em;
	margin-top: 0.1em;
	padding-top: 0;
}

#wiki {
	margin: 0;
	padding: 0;
}

#st-page-title {
}

#st-page-titletext, .st-page-title {
	font-family: Helvetica, Verdana, sans-serif;
	font-size: 150%;
	font-weight: bold;
	color: #888;
	border-bottom: 1px solid #888;
}

#st-newpage-pagename-edit {
	font-family: inherit;
	font-size: inherit;
	font-weight: inherit;
	color: #000;
	border: 1px solid black;
	padding-left: 0.3em;
	background-color: #ffd;
}

#st-page-details {
	font-style: italic;
	font-size: 75%;
	font-family: Georgia, serif;
	margin: 6px 10px 0 10px;
}

#st-page-details-feed-icon {
	vertical-align: middle;
	border: none;
}

#st-page-stats {
	float: right;
	vertical-align: middle;
}

#st-attribution {
	float: left;
	margin-bottom: 10px;
}

#st-page-editing-wysiwyg {
	background: #ffd;
	border-style: solid;
	border-color: #888 #ccc #ccc #888;
	border-width: 2px;
	width: 100%;
}

#st-page-editing-toolbar {
	margin-left: -6px;
	overflow: hidden;
	float: left;
	height: 25px;
}

#wikiwyg_wikitext_textarea {
	margin-top: 4px;
	background: #ffd;
	border-style: solid;
	border-color: #888 #ccc #ccc #888;
	border-width: 2px;
	width: 100%;
	font-family: monospace;
}

#st-page-maincontent {
}

#st-page-editing, #wikiwyg_wikitext_textarea {
}

#st-page-editing-pagebody-decoy, #st-page-editing-wysiwyg {
	display: none;
}

#st-editing-tools-edit {
	display: none;
}

#st-mode-wysiwyg-button
{
	font-size: 70%;
	margin-left: 4em;
}

#st-mode-wikitext-button
{
	font-size: 70%;
}

#st-edit-tips
{
	font-size: 70%;
}

.wikiwyg_button {
	background: #FFFFFF;
	border: 1px solid #FFFFFF;
	cursor: pointer;
	width: 20px;
	height: 20px;
	vertical-align: bottom;
}

.wikiwyg_button:hover {
	border: 1px outset;
}

.wikiwyg_button:active {
	border: 1px inset;
}

#wikiwyg_toolbar {
	display: none;
}

/* Sidebox Pagetools: Revisions, Watchlist */
#st-side-box-pagetools {
	border-collapse: collapse;
}

#st-rewind-norevisions {
	font-family: Helvetica, Arial, sans-serif;
	font-size: 11px;
	color: #777;
	text-decoration: none;
}

#st-side-box-pagetools a {
	font-family: Helvetica, Arial, sans-serif;
	font-size: 11px;
	color: #555;
	text-decoration: none;
}

/* Page View Tags/Incoming Links Sidebox */

#st-tags {
	background: #f4fff4;
	border-color: #bbeebb;
	color: #999;
}

#st-tags-title {
	color: #595;
}

#st-tags-addlink, #st-tags-addbutton {
	font-weight: bold;
}

#st-tags-listing {
	margin-bottom: 5px;
}

#st-tags-addinput, #st-tags-message, #st-tags-suggestion {
	display: none;
}

#st-tags-deletemessage {
	font-size: 90%;
	color: #555;
	display: none;
	margin-top: 0.5em;
	margin-bottom: 0.5em;
}

#st-tags-suggestion {
	margin-top: 2px;
}

.st-tags-level1 {
	font-size: 90%;
}

.st-tags-level2 {
	font-size: 100%;
}

.st-tags-level3 {
	font-size: 110%;
}

.st-tags-level4 {
	font-size: 120%;
}

.st-tags-level5 {
	font-size: 130%;
}

.st-tags-tagline .st-tags-tagdelete {
	text-decoration: none;
	color: #ccc;
}

.st-tags-tagline a {
	text-decoration: none;
	color: #444;
}

#st-tags-field {
	width: 95%;
}

#st-incoming-links {
	border-color: #ebb;
	background-color: #fff4f4;
}

#st-incoming-links-title {
	color: #b78;
}

#st-attachments {
	border-color: #bbe;
	background-color: #f4f4ff;
}

#st-attachments-uploadbutton, #st-attachments-managebutton {

}
#st-attachments-buttons-uploadbutton {
	margin: 0px;
	padding: 0px;
	padding-left: 2px;
}
#st-attachments-buttons-managebutton {
	margin: 0px;
	padding: 0px;
	padding-right: 2px;
}

#st-attachments-buttons td {
	padding-right: 3px;
	font-size: 99%;
}

#st-attachments-buttons {
	border-collapse: collapse;
	margin: 0px;
	padding: 0px;
	margin-top: 5px;
}

#st-attachments-title {
	color: #77b;
}

.st-attachments-line {
	width:100%;
	overflow:hidden;
}

/* Actions Bar */

#st-actions-bar-spacer {
	clear:both;
	height:0.5em;
	overflow:hidden;
}

#st-actions-bar-spacer-clear {
	clear:both;
	height:1px;
	overflow:hidden;
}


#st-actions-bar, #st-editing-tools-bar {
	margin-left: 30px !important;
	margin-right: 30px !important;
}

/* Footer */
#st-footer {
	margin-top: -8px;
	margin-bottom: 5px;
	clear: both;
}

/* Socialtext Attribution */

#st-socialtext-attribution {
	clear: both;
	text-align: center;
	font-size: 80%;
	font-family: Helvetica, sans-serif;
}

#st-socialtext-attribution-link {
	text-decoration: none;
}

#st-socialtext-attribution-image {
	border: 0;
}


/* Page Actions */

#st-edit-button-border-left-middle, #st-login-to-edit-button-border-left-middle {
	background: url('../../images/st/button-blue/left-middle.gif') left top repeat-y;
}
#st-edit-button-border-right-middle, #st-login-to-edit-button-border-right-middle {
	background: url('../../images/st/button-blue/right-middle.gif') right top repeat-y;
}

#st-edit-button-border-left-top, #st-login-to-edit-button-border-left-top {
	background: url('../../images/st/button-blue/left-top.gif') left top no-repeat;
}
#st-edit-button-border-right-top, #st-login-to-edit-button-border-right-top {
	background: url('../../images/st/button-blue/right-top.gif') right top no-repeat;
}

#st-edit-button-border-left-bottom, #st-login-to-edit-button-border-left-bottom {
	background: url('../../images/st/button-blue/left-bottom.gif') left bottom no-repeat;
}

#st-edit-button-border-right-bottom, #st-login-to-edit-button-border-right-bottom {
	background: url('../../images/st/button-blue/right-bottom.gif') right bottom no-repeat;
}

#st-edit-button-link, #st-login-to-edit-button-link {
}

#st-comment-button-border-left-middle {
	background: url('../../images/st/button-purple/left-middle.gif') left top repeat-y;
}

#st-comment-button-border-right-middle {
	background: url('../../images/st/button-purple/right-middle.gif') right top repeat-y;
}

#st-comment-button-border-left-top {
	background: url('../../images/st/button-purple/left-top.gif') left top no-repeat;
}

#st-comment-button-border-right-top {
	background: url('../../images/st/button-purple/right-top.gif') right top no-repeat;
}

#st-comment-button-border-left-bottom {
	background: url('../../images/st/button-purple/left-bottom.gif') left bottom no-repeat;
}

#st-comment-button-border-right-bottom {
	background: url('../../images/st/button-purple/right-bottom.gif') right bottom no-repeat;
}

#st-comment-button-link {
}

#st-save-button-border-left-middle {
	background: url('../../images/st/button-green/left-middle.gif') left top repeat-y;
}
#st-save-button-border-right-middle {
	background: url('../../images/st/button-green/right-middle.gif') right top repeat-y;
}

#st-save-button-border-left-top {
	background: url('../../images/st/button-green/left-top.gif') left top no-repeat;
}
#st-save-button-border-right-top {
	background: url('../../images/st/button-green/right-top.gif') right top no-repeat;
}

#st-save-button-border-left-bottom {
	background: url('../../images/st/button-green/left-bottom.gif') left bottom no-repeat;
}

#st-save-button-border-right-bottom {
	background: url('../../images/st/button-green/right-bottom.gif') right bottom no-repeat;
}

#st-save-button-link {
}

#st-preview-button-border-left-middle {
	background: url('../../images/st/button-gold/left-middle.gif') left top repeat-y;
}
#st-preview-button-border-right-middle {
	background: url('../../images/st/button-gold/right-middle.gif') right top repeat-y;
}

#st-preview-button-border-left-top {
	background: url('../../images/st/button-gold/left-top.gif') left top no-repeat;
}
#st-preview-button-border-right-top {
	background: url('../../images/st/button-gold/right-top.gif') right top no-repeat;
}

#st-preview-button-border-left-bottom {
	background: url('../../images/st/button-gold/left-bottom.gif') left bottom no-repeat;
}

#st-preview-button-border-right-bottom {
	background: url('../../images/st/button-gold/right-bottom.gif') right bottom no-repeat;
}

#st-preview-button-link {
}

#st-cancel-button-border-left-middle {
	background: url('../../images/st/button-crimson/left-middle.gif') left top repeat-y;
}
#st-cancel-button-border-right-middle {
	background: url('../../images/st/button-crimson/right-middle.gif') right top repeat-y;
}

#st-cancel-button-border-left-top {
	background: url('../../images/st/button-crimson/left-top.gif') left top no-repeat;
}
#st-cancel-button-border-right-top {
	background: url('../../images/st/button-crimson/right-top.gif') right top no-repeat;
}

#st-cancel-button-border-left-bottom {
	background: url('../../images/st/button-crimson/left-bottom.gif') left bottom no-repeat;
}

#st-cancel-button-border-right-bottom {
	background: url('../../images/st/button-crimson/right-bottom.gif') right bottom no-repeat;
}

#st-cancel-button-link {
}

#st-edit-more-button-border-left-middle {
	background: url('../../images/st/button-blue/left-middle.gif') left top repeat-y;
}
#st-edit-more-button-border-right-middle {
	background: url('../../images/st/button-blue/right-middle.gif') right top repeat-y;
}

#st-edit-more-button-border-left-top {
	background: url('../../images/st/button-blue/left-top.gif') left top no-repeat;
}
#st-edit-more-button-border-right-top {
	background: url('../../images/st/button-blue/right-top.gif') right top no-repeat;
}

#st-edit-more-button-border-left-bottom {
	background: url('../../images/st/button-blue/left-bottom.gif') left bottom no-repeat;
}

#st-edit-more-button-border-right-bottom {
	background: url('../../images/st/button-blue/right-bottom.gif') right bottom no-repeat;
}

#st-edit-more-button-link {
}

.st-page-action-button-link {
	min-height: 24px;
	min-width: 100px;
	text-align: center;
	font-family: Helvetica, Verdana, sans-serif;
	font-size: 90%;
	text-decoration: none;
	color: #fff;
	font-weight: bold;
	display: block;
	padding-top: 8px;
	padding-bottom: 0px;
	margin-bottom: -3px;
	width: 100%;
	margin-left: -2px;
}
* html .st-page-action-button-link {
	padding-top: 5px;
	padding-bottom: 0px;
	height: 24px;
}

.st-page-action-button {
	float: left;
	margin: 0;
	padding: 0;
	margin-right: 10px;
	min-height: 20px;
	border-collapse: collapse;
	width: 100px;
}

/* Attach File Interface */

#st-attachments-attachinterface {
	font-family: Helvetica, sans-serif;
	font-size: 90%;
	display: none;
	position: fixed;
	left: 0px;
	top: 0px;
	width: 100%;
	height: 100%;
	z-index: 2000;
	background-image: url('../../images/st/popup/bg.png');
}
#st-attachments-manageinterface {
	font-family: Helvetica, sans-serif;
	font-size: 90%;
	display: none;
	position: absolute;
	left: 0px;
	top: 0px;
	width: 100%;
	height: 100%;
	z-index: 2000;
	background-image: url('../../images/st/popup/bg.png');
}

* html #st-attachments-attachinterface {
	background-image: none;
}
* html #st-attachments-manageinterface {
	background-image: none;
}
* html .popup-overlay {
	background-image: url('../../images/st/popup/bg.png');
	background-color: #000;
	opacity: .70;
	position: absolute;
	left: 0px;
	top: 0px;
	width: 100%;
	height: 100%;
	z-index: 2001;
}

#st-attachments-attach-interface {
	z-index: 2002;
	background-color: #fff;
	color: #000;
	border: 4px solid #ccc;
	padding: 1em;
	width: 520px;
	margin-left: auto;
	margin-right: auto;
	margin-top: 10%;
	position: absolute;
	top: 0px;
}

* html #st-attachments-attach-interface {
}

#st-attachments-attach-formtarget {
	width: 0px;
	height: 0px;
	border: 0;
	padding: 0;
	margin: 0;
}

#st-attachments-attach-message {
	font-size: 90%;
	font-family: Verdana, Arial, Helvetica, Sans-Serif;
}

#st-attachments-attach-title {
	font-weight: bold;
	font-size: 120%;
}

#st-attachments-attach-close {
	float: right;
	margin-top: 6px;
}

#st-attachments-attach-uploadbutton {
	float: right;
	margin-right: 6px;
	margin-top: 6px;
	padding-bottom: 0;
}

#st-attachments-attach-fileprompt {
	margin: 0.2em 0 0.4em 0;
	padding-bottom: 0px;
}

#st-attachments-attach-submit {
	font-size: 90%;
	font-weight: bold;
}

#st-attachments-attach-filename {
	font-size: 90%;
}

#st-attachments-attach-uploadmessage {
	font-weight: bold;
	margin-bottom: 1em;
	display: none;
}

#st-attachments-attach-error {
	font-weight: bold;
	color: #f00;
	margin-bottom: 1em;
	display: none;
}

#st-attachments-attach-list {
	display: none;
	color: #666;
	font-size: 90%;
	margin-top: 1em;
	margin-bottom: 1em;
	border-top: 1px solid #4949BA;
	border-bottom: 1px solid #4949BA;
	background-color: #F5F5F5;
	padding: 3px;
}

.st-attachments-attach-listlabel {
	font-size: 90%;
	color: #4949BA;
}

/* Queue File Dialog */

#st-attachmentsqueue-interface {
	font-family: Helvetica, sans-serif;
	font-size: 90%;
	display: none;
	position: fixed;
	left: 0px;
	top: 0px;
	width: 100%;
	height: 100%;
	background-image: url('../../images/st/popup/bg.png'); /* Don't forget IE hack for ship! */
	z-index: 2000;
}

* html #st-attachmentsqueue-interface {
	background-image: none;
}

#st-attachmentsqueue-dialog {
	z-index: 2002;
	background-color: #fff;
	color: #000;
	border: 4px solid #ccc;
	padding: 1em;
	width: 530px;
	margin-left: auto;
	margin-right: auto;
	margin-top: 10%;
	position: absolute;
	top: 0px;
}

* html #st-attachmentsqueue-dialog {
}

#st-attachmentsqueue-fileprompt {
	margin-bottom: 0.4em;
	margin-top: 0;
	padding-bottom: 0;
}

#st-attachmentsqueue-title {
	font-weight: bold;
	font-size: 120%;
}

#st-attachmentsqueue-close {
	float: right;
	margin-top: 6px;
}

#st-attachmentsqueue-uploadbutton {
	float: right;
	margin-right: 6px;
	margin-top: 6px;
	padding-bottom: 0;
}

#st-attachmentsqueue-submit {
	font-size: 90%;
}

#st-attachmentsqueue-filename {
	font-size: 90%;
}

#st-attachmentsqueue-message {
	font-size: 90%;
	font-family: Verdana, Arial, Helvetica, Sans-Serif;
}

#st-attachmentsqueue-uploadmessage {
	font-weight: bold;
	margin-bottom: 1em;
	display: none;
}

#st-attachmentsqueue-error {
	font-weight: bold;
	color: #f00;
	margin-bottom: 1em;
	display: none;
}

#st-attachmentsqueue-list {
	display: none;
	color: #666;
	font-size: 90%;
	margin-top: 1em;
	margin-bottom: 1em;
	border-top: 1px solid #4949BA;
	border-bottom: 1px solid #4949BA;
	background-color: #F5F5F5;
	padding: 3px;
}

.st-attachmentsqueue-listlabel {
	font-size: 90%;
	color: #4949BA;
}

/* Lists */

tr.st-trbg-even, tr.st-trbg-even td{
	background-color: #f3f7f7;
}

tr.w-st-even-row, tr.w-st-even-row td {
	background-color: #f3f7f7;
}

.query-results-header-title, .query-results-header-last-edit-by {
	text-align: left;
}


.query-results-row-revisions {
	text-align: right;
}

.query-results-content {
	font-size: 85%;
	border-collapse: collapse;
	border: 1px dashed #ddd;
	border-left: 1px solid #ddd;
	border-right: 1px solid #ddd;
}

.query-results-row {
	border-collapse: collapse;
	border: 1px dashed #ddd;
	border-left: 1px solid #ddd;
	border-right: 1px solid #ddd;
}

.query-results-row a {
	text-decoration: underline;
	color: #00f;
}

.query-results-row td {
	font-family: Verdana;
	padding: 0.3em;
	border-left: 1px dashed #ddd;
	border-right: 1px dashed #ddd;
	border-top: 1px solid #ddd;
	border-bottom: 1px solid #ddd;
}

.query-results-header-row {
	border-collapse: collapse;
	border: 1px dashed #ddd;
	border-left: 1px solid #ddd;
	border-right: 1px solid #ddd;
}

.query-results-header-row a {
	text-decoration: underline;
	color: #00f;
}

.query-results-header-row th {
	font-family: Helvetica;
	padding: 0.3em;
	border-left: 1px dashed #ddd;
	border-right: 1px dashed #ddd;
	border-top: 1px solid #ddd;
	border-bottom: 1px solid #ddd;
}

div.st-actionbutton {
	float: left;
}

div#deleteme-st-actions-bar {
	clear: both;
	margin: 0.8em 20px 0.2em auto;
	padding: 0;
}

/* Manage File Interface */



#st-attachments-manage-interface {
	z-index: 2002;
	background-color: #fff;
	color: #000;
	border: 4px solid #ccc;
	padding: 1em;
	width: 520px;
	margin-left: auto;
	margin-right: auto;
	margin-top: 10%;
	position: absolute;
	top: 0px;
}

#st-attachments-manage-filetable {
	height: 150px;
	margin: 0;
	padding: 0;
	width: 100%;
	overflow: auto;
	border: 1px solid #ccc;
}

#st-attachments-manage-filelisting tbody td {
	font-size: 90%;
}
#st-attachments-manage-filelisting {
	width: 100%;
	border-collapse: collapse;
	border: 0;
	margin: 0;
	padding: 0;
}

#st-attachments-manage-fileheader {
	background: #ccc;
	font-weight: bold;
	border-bottom: 1px black solid;
}

#st-attachments-manage-close {
	float: right;
	margin-top: 3px;
	margin-right: -2px;
	font-weight: bold;
}

#st-attachments-manage-delete {
	margin-top: 3px;
	float: left;
	font-weight: bold;
}

.st-attachments-manage-filerow {
	border-bottom: 1px solid #ccc;
}

.row-odd {
	background-color: #eee;
}

.row-even {
	background-color: #fff;
}

.row-on {
	background-color: #009 !important;
	color: white !important;
}

.row-on a {
	color: #fff !important;
}

#st-attachments-manage-deletemessage {
	color: red;
}

/* Page tools icons */

#st-pagetools-print {
	background: url('../../images/st/pagetools/print.gif')
	left center no-repeat;
}

#st-pagetools-email {
	background: url('../../images/st/pagetools/email.gif')
	left center no-repeat;
}

#st-pagetools-tools {
	background: url('../../images/st/pagetools/tools.gif')
	left center no-repeat;
}

/*
 #st-pagetools-watch {
	background: url('../../images/st/pagetools/watch-blue.gif')
	left center no-repeat;
}
*/


/* *********** Settings *********** */

#st-settings-pane {
}
* html #settings-pane { font-size: 85%;}

.settings-start-table {
}
* html .settings-start-table { font-size: 90%;}

#st-settings-select {
	padding: 0px 10px 10px 10px;
	vertical-align: top;
	width: 1px;

	background-color: #eff1ec;
	border: none;
}

#st-settings-section {
	padding: 0px 10px 10px 10px;
	vertical-align: top;
}

.settings-top-header {
	margin-top: 1em;
	font-weight: bold;
	width: 15em;
}

.settings-header {
	margin-top: 1em;
	font-weight: bold;
}

.settings-selections {
	padding: 0px 0px 0px 20px;
	line-height: 1.5em;
}

.settings-selections a:visited, .settings-selections a:active {
	color: #0000ff;
}

.settings-link {
	clear: both;
	display: block;
}

.settings-section-left {
	text-align: right;
}

.settings-label {
	font-weight: bold;
}

.settings-help {
	color: #888;
}

.settings-comment {
}

.users-invite-message {
	padding: 0.5em 0.5em 0.5em 2em;
	background-color: #eee;
	/* This seems necessary to fix an IE bug that sometimes
		causes the text in this div to be invisible */
	z-index: 1000;
}

.workspace-entry-header {
	margin-top: .5em;
	font-weight: bold;
}

.workspace-entry {
	margin-left: 3em;
}

.workspace-entry-p {
	margin-top: .5em;
	margin-bottom: .75em;
}

.workspace-subentry {
	font-style: italic;
	font-weight: bold;
	margin-left: 1.5em;
}

.preferences-td {
	padding:.5em 0 1.5em 0;
}

.preferences-query {
	text-align: left;
}

.preference-radio {
	background-color: #cec;
}
.user-settings-listall-headings td {
	background-color: #eff3ef;
}

#st-settings-save {
	padding-bottom: 0.5em;
}

.standard-button-cancel {
	font-weight: bold;
	background-color: #71004b;

	border-left: 1px solid #aaa;
	border-top: 1px solid #aaa;
	border-bottom: 2px solid #333;
	border-right: 2px solid #333;
	color: #f4f3b9;
	width: 8em;
}

.standard-button-submit {
	font-weight: bold;
	background-color: #656084;

	border-left: 1px solid #aaa;
	border-top: 1px solid #aaa;
	border-bottom: 2px solid #333;
	border-right: 2px solid #333;
	color: #f4f3b9;
	width: 8em;
}

#st-settings {
	font-family: Verdana, Arial, Helvetica, Sans-Serif;
	font-size: 90%;
}


/* Listview Tabs */


#st-listview a:visited {
	color: #551a8b;
}
#st-listview-tabs ul {
	display: block;
	list-style: none outside;
	margin: 0 0 0 4em;
	padding: 0;
	font-family: Helvetica, Arial, Sans-serif;
	font-size: 80%;
}

#st-listview-tabs li {
	display: block;
	float: left;
	margin: 0 0.8em 0 0;
	padding: 3px 0.6em 0 0.6em;
	border: 1px solid #d8d8d8;
	border-bottom: 1px solid rgb(128, 169, 243);
	background-color: #f4f4f4;
	position: relative;
	bottom: -2px;
}

#st-listview-tabs li.spacer {
	margin: 0 0.8em 0 2em;
}

#st-listview-tabs a {
	color: #bbb;
	text-decoration: none;
}

#st-listview-tabs li.selected {
	background-color: #fff !important;
	border: 1px solid rgb(128, 169, 243) !important;
	border-bottom: 1px solid #fff !important;
	font-weight: bold !important;
}

#st-listview-tabs li.selected a {
	color: #000 !important;
}

/* Category List Display */

#st-category-display-links {
	margin-bottom: 1em;
	font-size: 90%;
}

#st-tag-listbody {
	font-family: Helvetica, Verdana, sans-serif;
}

/* Attachments List Display */

#st-attachments-list-body table.button-table {
	margin-top: 0.1em;
	font-size: 80%;
}


/* ********** PageTools Menu ************** */

div#st-editing-tools {
	float: left;
}

div#st-pagetools {
	z-index: 300;
	font-family: Helvetica, Verdana, sans-serif;
	font-size: 10px;
	float: right;
	margin: 18px 0 0 0em;
	color: #000;
	vertical-align: bottom;
	position: relative;
}

#st-pagetools a {
	text-decoration: none;
	color: black;
	padding-left: 17px;
}

#st-pagetools span {
	color: inherit;
	padding-left: 17px;
	vertical-align: top;
}

#st-pagetools span.st-watchlist-link {
	color: inherit;
	vertical-align: top;
}

.st-watchlist-link {
	cursor: pointer;
}

div#st-pagetools ul.level2 {
	z-index: 300;
	margin: 0;
	padding: 0;
	background: white;
	border: 1px solid #CCC;
	border-width: 0 1px;
}

div#st-pagetools li {
	position: relative;
	list-style: none;
	margin: 0;
	float: left;
	width: 7em;
	line-height: 11px;
}

div#st-pagetools ul ul li:hover {
	background: #BFE2FF;
}

div#st-pagetools li a {
	display: block;
	text-decoration: none;
}

div#st-pagetools>ul a {
	width: auto;
}

div#st-pagetools ul ul {
	position: absolute;
	width: auto;
	display: none;
}

div#st-pagetools ul ul li {
	line-height: 1.5em;
/*	width: 100%; */
	width: 14em;
}

.first {
	border-top: 1px solid #CCC;
}

.separator {
	border-bottom: 1px solid #CCC;
}

div#st-pagetools ul ul li a {
	border-bottom: 1px solid #CCC;
	padding-left: 15px;
	padding-right: 3px;
	margin-right: 3px;
	border: 0px;
}

div#st-pagetools li.submenu li.submenu:hover {
	z-index: 300;
	background-color: #BFE2FF;
}

div#st-pagetools ul.level1 li.submenu:hover ul.level2 {
	display:block;
}

div#st-pagetools ul.level2 {
	top: 1.0em;
	left: -9.5em;
}

/*

=head2 Revision List Display

Change these styles to update the page revision list.

*/

#st-revision-list-table {
	border-collapse: collapse;
	font-size: 85%;
	color: #000;
}

.st-page-title-decorator {
	color: #C80000;
}

.st-revision-header-emphasis {
	color: #C80000;
}

.st-revision-list-compare-button-row {
}

.st-revision-list-compare-button-cell {
	padding-top: 0.3em;
	text-align: center;
}

.st-revision-list-compare-button {
}

#st-revision-list-header-row {
}

#st-revision-list-header-select {
	padding: 6px 2px 2px 2px;
	text-align: center;
}

#st-revision-list-header-revision {
	padding: 6px 2px 2px 2px;
	text-align: left;
}

#st-revision-list-header-edited-by {
	padding: 6px 2px 2px 2px;
	text-align: center;
}

#st-revision-list-header-date {
	padding: 6px 2px 2px 2px;
	text-align: center;
}

.st-revision-list-row {
	border-collapse: collapse;
	border: 1px dashed #ddd;
	border-left: 1px solid #ddd;
	border-right: 1px solid #ddd;
}

.st-revision-list-row td {
	font-family: Verdana;
	padding: 0.3em;
	border-left: 1px dashed #ddd;
	border-right: 1px dashed #ddd;
	border-top: 1px solid #ddd;
	border-bottom: 1px solid #ddd;
}

.st-revision-list-row-select {
	padding: 3px 0 2px 0;
	text-align: center;
}

.st-revision-list-row-select-old {
}

.st-revision-list-row-select-new {
}

.st-revision-list-row-revision {
}

.st-revision-list-row-revision-link {
}

.st-revision-list-row-edited-by {
}

.st-revision-list-row-date {
}

/* Revision Menu */

#st-pagetools.st-revision-view-bar {
	float: left;
}

ul.st-revision-menu {
	list-style: none;
	margin: 0;
	padding: 0.2em;
	font-size: 80%;
}

ul.st-revision-menu li {
	float: left;
	padding: 0 0.4em 0 0.4em;
	border-right: thin solid #000000;
}

ul.st-revision-menu li.st-last {
	border-right: none;
}

#st-restore-revision-button {
	font-size: 80%;
}

/*

=head2 Revision Compare Display

When comparing two revisions of a page, these styles apply.

*/

#st-revision-compare-table {
	background-color: #f0f0f0;
}

#st-revision-compare-table td {
	background-color: white;
}

.st-revision-compare-old {
	background-color: #fdd;
	text-decoration: line-through;
}
.st-revision-compare-new {
	background-color: #dfd;
	font-weight: bold;
}

/* Weblog View */

#st-weblog {
	padding: 0;
}

#st-content-weblog-display-width-controller {
}
#st-content-weblog-display-width-controller-nav {
	width: 230px;
	margin-left: 15px;
	border-left: 5px solid #ddd;
	margin-top: -1px;
}

#st-weblog-content {
	font-family: Verdana, Helvetica, sans-serif;
	margin-top: -1px;
	margin-bottom: -1px;
	border-top: 1px solid #80a9f3;
	border-bottom: 1px solid #80a9f3;
}

#st-weblog-title {
	font-family: 'Trebuchet MS', Verdana, Helvetica, sans-serif;
	font-family: 'Times New Roman', serif;
	background-color: #80a9f3;
	color: #fff;
	font-size: 150%;
	font-weight: bold;
	padding: 0.2em;
	padding-left: 1em;
}

#st-weblog-wikititle {
	font-family: Helvetica, Verdana, sans-serif;
	font-style: italic;
	font-size: 40%;
	color: #fff;
	margin-bottom: 0.2em;
	margin-top: 0.1em;
	padding-top: 0;
}

#st-weblog-titletext {
	font-family: Helvetica, Verdana, sans-serif;
	font-weight: bold;
	color: #fff;
}

div.st-weblog-entry {
	margin-top: 0.2em;
	margin-bottom: 4.8em;
	padding: 0 1.5em 0 1.5em;
}

.st-page-title {
	clear: both;
}

div.st-weblog-entrytitle span.text {
	font-family: Helvetica, Verdana, sans-serif;
	font-size: 150%;
	font-weight: bold;
	color: #000;
}

.st-weblog-entrycontent {
	font-family: Verdana, Helvetica, sans-serif;
	font-size: 90%;
	border-bottom: 1px solid #888;
}

.st-weblog-byline {
	float: left;
	text-align: left;
	font-style: italic;
	font-size: 70%;
	font-family: Verdana, Helvetica, sans-serif;
}

.st-weblog-post-links {
	float: right;
	text-align: right;
	font-size: 70%;
	font-family: Verdana, Helvetica, sans-serif;
}

#st-weblog-archives, #st-weblog-navigation {
	position: relative;
	float: right;
	width: 230px;
}

#st-weblog-archives {
	margin-top: 15px;
	clear: right;
}

#st-weblog-archives-title, #st-weblog-navigation-title {
	margin-left: 15px;
	font-family: Helvetica, sans-serif;
	font-size: 95%;
	font-weight: bold;
	color: #999;
	border-bottom: 2px solid #f99;
	padding-bottom: 5px;
	padding-top: 5px;
	margin-bottom: 5px;
}

#st-weblog-navigation-content {
	margin-left: 15px;
	font-size: 80%;
}

#st-weblog-archives ul {
	margin: 0;
	padding: 0;
}

#st-weblog-archives ul li {
	/* list-type: none; */
	display: block;
	font-size: 80%;
	font-family: Helvetica, sans-serif;
	padding-left: 15px;
}

#st-weblog-newpost {
	padding: 0.5em 0.7em 0.3em 0.3em;
}

#st-weblog-newpost-button {
}

#st-weblog-actionbar-chooseweblog {
	float: right;
}

#st-weblog-postbyemail {
	font-size: 70%;
	font-family: Verdana, Helvetica, sans-serif;
	color: #def;
	padding-top: 0.4em;
}

#st-weblog-postbyemail-link {
	color: #00c;
}

.st-weblog-chooseprompt {
	font-size: 90%;
	font-family: Verdana, Helvetica, sans-serif;
	padding-right: 0.2em;
	color: #000;
}

.st-spacer {
	padding-right: 0.1em;
	padding-left: 0.1em;
}

.st-weblog-preventries {
	padding-bottom: 20px;
	clear: both;
}
.st-weblog-nextentries {
	clear: both;
}

div.st-weblog-entrynav {
	margin-top: 0.2em;
	margin-bottom: 1.8em;
	padding: 0;
}

span.st-weblog-previousentries, span.st-weblog-nextentries {
	font-size: 90%;
	font-family: Verdana, Helvetica, sans-serif;
	padding-left: 1em;
}

/* ******* Page Stats ******** */

#st-usagereport-navbar {
	font-size: 80%;
	padding: 0;
	margin: 0;
}

#st-usagereport-date {
	font-weight: bold;
	margin-top: 1em;
}

#st-page-usagereport h1 {
	font-size: 1.3em;
	font-weight: bold;
	margin-top: 1.2em;
	margin-bottom: 0.3em;
}

#st-page-usagereport h2 {
	font-size: 1.1em;
	font-weight: bold;
	margin-top: 0.8em;
	margin-bottom: 0.3em;
}

/* New Page */
#st-newpage-save, #st-newpage-duplicate {
	display: none;
	position: fixed;
	left: 0px;
	top: 0px;
	width: 100%;
	height: 100%;
	background: url('../../images/st/popup/bg.png'); /* Don't forget IE hack for ship! */
	z-index: 2000;
}

#st-newpage-save-interface {
	background-color: #fff;
	color: #000;
	border: 4px solid #ccc;
	padding: 0.5em;
	width: 450px;
	margin-left: auto;
	margin-right: auto;
	margin-top: 10%;
	position:absolute;
	top:0px;
	z-index:2003;
}

#st-newpage-duplicate-interface {
	background-color: #fff;
	color: #000;
	border: 4px solid #ccc;
	padding: 0.5em;
	width: 530px;
	margin-left: auto;
	margin-right: auto;
	margin-top: 10%;
	position:absolute;
	top:0px;
	z-index:2003;
}

#st-newpage-save-title, #st-newpage-duplicate-title {
	margin: 0;
	padding: 0;
	font-weight: bold;
	font-family: Helvetica, sans-serif;
	font-size: 100%;
}

#st-newpage-save-prompt, #st-newpage-duplicate-prompt {
	font-family: Helvetica, sans-serif;
	font-size: 90%;
	margin-bottom: 0.4em;
}

#st-newpage-save-buttons, #st-newpage-duplicate-buttons {
	margin-top: 0.8em;
	text-align: right;
}

.st-newpage-duplicate-option {
	font-family: Helvetica, sans-serif;
	font-size: 90%;
	margin: 0;
	padding: 0;
}

#st-newpage-duplicate-pagename {
	font-size: 90%;
}

.st-newpage-duplicate-emphasis {
	background-color: #FFFF00;
	font-weight: bold;
}

#st-newpage-save-field-pagename {
	margin-bottom: 0;
	margin-top: 0.2em;
	padding-bottom: 0;
	font-size: 90%;
}

#st-newpage-save-tip {
	margin-bottom: 0;
	margin-top: 1.2em;
	padding-bottom: 0;
	font-size: 75%;
	color: #888;
}

/* Wikitext Styling */

.wiki {
}

.wiki hr {
	margin-top: .4em;
	margin-bottom: .4em;
}

.wiki .short-rule {
	width: 25%;
}

.wiki .medium-rule {
	width: 50%
}

.wiki ul,
.wiki ol,
.wiki blockquote {
	margin-left: 2em;
	padding-left: 0em;
}

.wiki table {
	border-collapse: collapse;
}

.wiki td {
	border: 1px;
	border-style: solid;
	padding: .2em;
	vertical-align: top;
}

.wiki h1,
.wiki h2,
.wiki h3,
.wiki h4,
.wiki h5,
.wiki h6 {
	font-weight: bold;
	font-style: normal;
	margin-top: 0.1em;
	margin-bottom: 8px;
}

.wiki h1 {font-size: 200%;}
.wiki h2 {font-size: 170%;}
.wiki h3 {font-size: 145%;}
.wiki h4 {font-size: 125%;}
.wiki h5 {font-size: 110%;}
.wiki h6 {font-size: 100%;}

.wiki pre {
	background-color: #eee; /* XXX */
	margin-left: 1em;
	margin-right: 1em;
	padding: .2em;
}

.wiki .incipient {
	text-decoration: none;
	border-bottom: 1px dashed;
}

.wiki-include-title {
	background-color: #ccccff;
}

.wiki .wiki {
	position: relative;
	background-color: #ddddff;
	border: 1px solid #ccccff;
	padding: 3px;
}

.wafl_existence_error {
	color: rgb(200,0,0);
	border-bottom: 0.2em dashed rgb(200,0,0);
}

#st-edit-mode-container {
}

#st-edit-mode-view {
}

#st-page-editing-uploadbutton {
	z-index: 1500;
	float: left;
}

/* Comment UI */


body#st-commentui {
	background: #ffffff;
}

#st-commentui-container {
}

#st-commentui-container a:visited,
#st-commentui-container a:active {
	color: #00f;
}

#st-commentui-notetop {
}

#st-commentui-controls {
}

#st-commentui-savelink {
	background-color: #fffebd;
}

#st-commentui-cancellink {
}

#st-commentui-customfield {
}

#st-commentui-customfield .customfield-label {
}

#st-commentui-customfield .customfield-input {
}

#st-commentui-textarea {
	padding: 0;
	border-style: inset;
	border-width: thin;
	background-color: #ffd;
	color: black;
	width: 99%;
	height: 150px;
}

/*

=head2 Send Page by Email

Styles for the 'Send Page by Email' popup, accessed from the 'Email' dropdown
menu on the page bar.

*/

#email-page {
	background: #ffffff;
	font-size: 80%;
}

.email-page-row {
	clear: both;
}

.email-page-row-label {
	font-weight: bold;
	float: left;
	width: 5em;
	margin-left: 1.2em;
	margin-right: 1.2em;
	text-align: right;
}

.email-page-row-content {
	float: left;
	padding-bottom: 1.2em;
}

.email-page-user-select-column {
	float: left;
	padding-right: 1.2em;
	width: 14em;
}

#email-page-user-select-column-center {
	width: 10em;
}

.email-page-user-select-label {
	text-align: center;
}

#email-page-user-select-add-label {
	padding-top: 1em;
}

.email-page-user-select-button-group {
	padding-bottom: 2em;
}

.email-page-input {
	width: 120px;
	clear: both;
	display: block;
}


.email-page-select {
	width: 175px;
	font-size: x-small;
}

#email-page-error-message {
	text-align: center;
}

#email-page-buttons-container {
	clear: both;
}

#email-page-buttons {
	text-align: center;
}

.email-page-input-new {
	width: 175px;
}

/* System Status, Red with icon */

#st-system-status-alert {
	clear: both;
	width: 50%;
	margin-left: 25%;
	margin-top: 10px;
	padding: 5px;
	color: #c00;
	font-weight: bold;
	font-size: 80%;
	background: transparent url('../../images/st/system-message/important-note.gif') no-repeat 5px center;
	padding-left: 60px;
	min-height: 38px;
}
* html #st-system-status-alert {
	height: 38px;
}

/* System Status, Green */

#st-system-status {
	clear: both;
	text-align:center;
	width: 80%;
	margin-left: 10%;
	padding: 8px 0 3px 0;
	color: #0a0;
	font-family: Arial, Helvetica, sans-serif;
	font-size: 80%;
}

.socialtextLogo {
	text-align: center;
}
/*}}}*/
/***
|''Name:''|SparklinePlugin|
|''Description:''|Sparklines macro|
***/
//{{{
if(!version.extensions.SparklinePlugin) {
version.extensions.SparklinePlugin = {installed:true};

//--
//-- Sparklines
//--

config.macros.sparkline = {};
config.macros.sparkline.handler = function(place,macroName,params)
{
	var data = [];
	var min = 0;
	var max = 0;
	var v;
	for(var t=0; t<params.length; t++) {
		v = parseInt(params[t]);
		if(v < min)
			min = v;
		if(v > max)
			max = v;
		data.push(v);
	}
	if(data.length < 1)
		return;
	var box = createTiddlyElement(place,"span",null,"sparkline",String.fromCharCode(160));
	box.title = data.join(",");
	var w = box.offsetWidth;
	var h = box.offsetHeight;
	box.style.paddingRight = (data.length * 2 - w) + "px";
	box.style.position = "relative";
	for(var d=0; d<data.length; d++) {
		var tick = document.createElement("img");
		tick.border = 0;
		tick.className = "sparktick";
		tick.style.position = "absolute";
		tick.src = "data:image/gif,GIF89a%01%00%01%00%91%FF%00%FF%FF%FF%00%00%00%C0%C0%C0%00%00%00!%F9%04%01%00%00%02%00%2C%00%00%00%00%01%00%01%00%40%02%02T%01%00%3B";
		tick.style.left = d*2 + "px";
		tick.style.width = "2px";
		v = Math.floor(((data[d] - min)/(max-min)) * h);
		tick.style.top = (h-v) + "px";
		tick.style.height = v + "px";
		box.appendChild(tick);
	}
};


}
//}}}
/***
|''Name:''|CryptoFunctionsPlugin|
|''Description:''|Support for cryptographic functions|
***/
//{{{
if(!version.extensions.CryptoFunctionsPlugin) {
version.extensions.CryptoFunctionsPlugin = {installed:true};

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

}
//}}}
This is the home page for Dobrica Pavlinušić's random unstructured stuff.

Welcome to my new unsorted stuff site. If you are here to "learn about rot13"<http://en.wikipedia.org/wiki/ROT13> this might not be the right place.

If you are, however looking latest and/or unsorted snippets which didn't made to "my homepage"<http://www.rot13.org/~dpavlin/> or "blog"<http://blog.rot13.org/> you might be on right place.

| {search: category: projects} | {search: category: howto} | {recent_changes: rot13} |

{fetchrss: http://blog.rot13.org/index.xml}
I don't like MySQL for various resons, most important one being that I saw PostgreSQL early on and never looked back.

Here are few quick commands to ease my pain:

{toc: }

^ Number of rows in table

`select count(*) from table_name` is terrably slow in MySQL, so use "information schema"<http://dev.mysql.com/doc/refman/5.1/en/tables-table.html> to quickly have report...

.pre
mysql> select table_name,table_rows,avg_row_length,data_length
 from information_schema.tables
 where table_type = 'BASE TABLE'
 order by table_rows desc
 limit 10 ;
+-----------------+------------+----------------+-------------+
| table_name      | table_rows | avg_row_length | data_length |
+-----------------+------------+----------------+-------------+
| zebraqueue      |    2309022 |             87 |   200998912 | 
| sessions        |    1744788 |            675 |  1178402816 | 
| items           |     302540 |            126 |    38338560 | 
| biblio          |     268391 |            166 |    44646400 | 
| action_logs     |     225797 |            341 |    77168640 | 
| biblioitems     |     220004 |           8159 |  1795080192 | 
| items_print_log |     205559 |            104 |    21528576 | 
| statistics      |     130166 |             76 |     9977856 | 
| old_issues      |      43852 |             84 |     3686400 | 
| import_biblios  |      19352 |            136 |     2637824 | 
+-----------------+------------+----------------+-------------+
10 rows in set (1.90 sec)
.pre

^ Create grepable dump

Put every value in it's own line

.pre
mysqldump -u user -p database --extended-insert=0 > dump.sql
.pre

^ Poor man's graphs

.pre
mysql> select dateenrolled,count(*),rpad('',count(*) / 10,'*') from borrowers group by dateenrolled;
+--------------+----------+----------------------------------------------+
| dateenrolled | count(*) | rpad('',count(*) / 10,'*')                   |
+--------------+----------+----------------------------------------------+
| NULL         |       18 | **                                           | 
| 2008-04-03   |        1 |                                              | 
| 2008-04-17   |        1 |                                              | 
| 2008-05-28   |        1 |                                              | 
| 2008-06-05   |        1 |                                              | 
| 2008-06-12   |        3 |                                              | 
| 2008-07-28   |        1 |                                              | 
| 2008-10-17   |        1 |                                              | 
| 2008-10-20   |        1 |                                              | 
| 2008-10-21   |        1 |                                              | 
| 2008-10-27   |       11 | *                                            | 
| 2008-10-28   |        2 |                                              | 
| 2008-10-29   |        4 |                                              | 
| 2008-10-30   |        2 |                                              | 
| 2008-11-03   |        1 |                                              | 
| 2008-11-04   |        9 | *                                            | 
| 2008-11-06   |        7 | *                                            | 
| 2008-11-10   |       16 | **                                           | 
| 2008-11-11   |        1 |                                              | 
| 2008-11-13   |        1 |                                              | 
| 2008-11-14   |        4 |                                              | 
| 2008-11-17   |        1 |                                              | 
| 2008-11-20   |        1 |                                              | 
| 2008-11-26   |        1 |                                              | 
| 2008-12-02   |        1 |                                              | 
| 2008-12-19   |        2 |                                              | 
| 2009-01-07   |        2 |                                              | 
| 2009-03-16   |      301 | ******************************               | 
| 2009-03-17   |      365 | *************************************        | 
| 2009-03-18   |      439 | ******************************************** | 
| 2009-03-19   |      324 | ********************************             | 
| 2009-03-20   |      226 | ***********************                      | 
| 2009-03-23   |      105 | ***********                                  | 
+--------------+----------+----------------------------------------------+
33 rows in set (0.00 sec)
.pre

^ MySQL Koha utf-8 encoding

^^ connect

.pre
use DBI();

my $dbh = DBI->connect ('dbi:mysql:test_db', $username, $password, 
   {mysql_enable_utf8 => 1}
);
.pre

^ my.cnf performance optimization

* https://launchpad.net/mysql-tuning-primer
* https://launchpad.net/mysqltuner/
* http://github.com/rackerhacker/MySQLTuner-perl

^ Performance monitoring

.pre
./mk-query-digest --processlist localhost --interval 0.01
.pre

^ Linux tuning

.pre
# turn off readahead
hdparm -a 0 /dev/sdb

# noop/deadline better than cfq
echo noop > /sys/block/sdb/queue/scheduler
.pre
{toc: }

bigclive https://youtu.be/_zTqZ1edrsU

https://ellestfun.en.alibaba.com/product/60341087076-801987474/IONCARE_wholesale_top_selling_Clenaer_Deodorizer_refrigerator_aroma_diffuser.html

^ Technical Specifications:

1.Ozone concentration: About 4.0ppm in “High” mode (operates 30 minutes inside a 40L closed container)

2.Effective Range:“High” mode <250L “Low” mode <150L

3.Rating Voltage: DC4.5V

4.Power Supply: 3pcs 1.5V AA-size alkaline batteries

5.Power consumption: 0.5 watts

I measured:

3.7 V * 0.029 A = 0.107 W
4 V * 0.032 A = 0.128W

This is all below 4.5V, but is test for single 18650 cell.

6.Dimensions: H116 x D80 mm

7.Weight: 0.15kg

^ INCARE GH2128

MONIC FRESHENER & DEODORIZER FOR REFRIGERATORS, CLOSETS BATHROOMS

Instructions

^^ FUNCTIONS AND FEATURES

An innovative device utilizes ionic technology to generate ozone (O₂) & anions to purify the air thoroughly.

1. Neutralize stale and foul odors with fresh air inside refrigerators, closets, bathrooms and cars, etc.

2. Kill all kinds of bacteria to avoid the growth of mildew. 3. Very ideal for use in refrigerator to keep the foods fresh for longer time.

4. Built-in micro CPU intelligently controls the operation cycle & mode by one touch and indicates with the colored LED.

5. Operated by 3 AA batteries. Low voltage indicator reminds you of replacing batteries.

^^ HOW TO OPERATE

1. Remove the battery door on the bottom of the unit, install 3 pieces "AA" 1.5V high-quality alkaline batteries (purchase separately) according to the proper polarity, close with the battery door.

2. Press the "ON/OFF" button once and the power indicator lights up. You may feel a slight breeze from the top grilles, which means the machine on working.

3. Press the "ON/OFF" button again to turn off the unit.

4. Operating mode settings:

1) When the machine is turned on, press the "MODE" button to toggle the operating modes between HIGH and LOW.

2) When the HIGH mode is selected, the power indicator will light up in green and blink.

The machine firstly performs a continuous working for about 30 minutes,
and the power indicator will blink every 2 seconds.

Then the machine will go into a cycle of automatic I-minute's sterilization and deodorization in every 1 hour,
in the other time, the machine will go to sleep and the power indicator will blink every 10 seconds.

3) When the LOW mode is selected, the power indicator will light up in orange and blink.

The machine firstly performs a continuous working for about 20 minutes,
and the power indicator will blink every 2 seconds.

Then the machine will go into a cycle of automatic 40-seconds
sterization and deodorization in every 1 hour
in the other time the machine will go to sleep and the power indicator will blink every 10 seconds.

5. When the power indicator becomes red, this is the butto voltage indicator reminds you of replacing bateries.

^^ SPECIAL ATTENTION

When the machine used in the refrigerator.

1. Make sure to place it into the refrigerator companimens ofer than the freezing compartment.

2. Before taking it from the refrigerator, make sure to tum of is power first.

Due to the lower temperature of the refingerator when the machine comes in contact with the outside air
there will be water condensation on its body and inside, if the machine keeps working,
it maybe leads to the short circuit of the electic parts and corrode the metal parts even the batteries

3. When the indicator becomes red, it's time to change the betteries

Take the machine from the refrigerator, and then wrap it with a clean plastic bag.

Before replacing with the new batteries make sure the temperature of the machine casing raises to room temperature.

^^ CAUTION

1. Take out the batteries if leaving the unit idle for a long time.

2. Do not operate the unit in areas where flammable or combusite products or vapors may be present.

3. Keep the unit away from water.

4. Do not strongly shock the unit to avoid any stack of the inter parts of the unit.

Read and save these instructions
^ PICKit 2

^^ pk2cmd

.pre
pi@rpi2 ~ $ git clone https://github.com/psmay/pk2cmd
pi@rpi2 ~ $ cd pk2cmd/pk2cmd
pi@rpi2 ~/pk2cmd/pk2cmd $ make linux

pi@rpi2 ~/pk2cmd/pk2cmd $ ./pk2cmd -P
Auto-Detect: Found part PIC16F684.

# power on target from pickit 2
pi@rpi2 ~/pk2cmd/pk2cmd $ ./pk2cmd -PPIC16F684 -T
.pre

^^ serial

https://github.com/majenkotech/pk2serial
{file: PrintrBot_Plus_LC.diff}

Old 3D printer which never worked well.

DXF files: https://www.youmagine.com/designs/printrbot-lc-1302

https://web.archive.org/web/20130115210644/http://printrbot.com/shop/plus/

{toc: }

^ PrintrBot Plus LC

The Printrbot PLUS is the larger printrbot kit–containing an 8x8x8 build volume, laser cut birch construction, an assembled Ubis hot end, and 12mm Z-axis rods in an all-in-one kit. This kit also includes 1 lb of ABS filament.

This kit includes everything you need to build the printrbot PLUS:

* printrboard: all-in-one assembled electronics with integrated SD card slot (no soldering required)
* 5 NEMA 17 stepper motors complete with cable ends attached
* laser cut birch construction
* a few printed plastic parts (gears, etc)
* WOOD Extruder Kit
* hardware (8mm smooth rods, threaded rods, and bearings
** Z axis is 12mm smooth rods and 12 mm linear bearings )
* assembled Ubis hot end
* nuts, bolts, washers, zip ties
* laser cut print bed
* 8×8 heated bed
* misc assembled cables (no soldering required)
* 3 mechanical end stops (no soldering required)
* micro USB cable

^^ nozzle

The Getting Started Guide says that all Printrbots currently ship with 0.4mm nozzles.
The convention for identifying nozzles is based on notches (or "rings") cut into the sides (vertices) of the hexagonal brass "nut".
No notch = 0.5mm
1 notch = 0.4mm
2 notches = 0.35mm

^ info

Most of information about it vanished from internet so here is some overview:

* http://reprap.org/wiki/Printrbot
* http://reprap.org/wiki/Printrboard

* https://github.com/Printrbot/printrboard

Rev.B https://github.com/Printrbot/printrboard/releases/tag/revB

^ PrintrBoard pinout

Annotated headers from http://blog.think3dprint3d.com/2012/07/panelolu-with-printrboard.html

{image: Printrboard Headers.JPG}

^ serial

.pre
[Sun Mar 18 08:23:50 2018] usb 2-4.4: new full-speed USB device number 61 using xhci_hcd
[Sun Mar 18 08:23:50 2018] usb 2-4.4: New USB device found, idVendor=16c0, idProduct=0483
[Sun Mar 18 08:23:50 2018] usb 2-4.4: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[Sun Mar 18 08:23:50 2018] usb 2-4.4: Product: USB Serial
[Sun Mar 18 08:23:50 2018] usb 2-4.4: Manufacturer: Teensyduino
[Sun Mar 18 08:23:50 2018] usb 2-4.4: SerialNumber: 12345
[Sun Mar 18 08:23:50 2018] cdc_acm 2-4.4:1.0: ttyACM0: USB ACM device

dpavlin@nuc:~$ microcom p /dev/ttyACM0 
connected to /dev/ttyACM0
Escape character: Ctrl\
Type the escape character to get to the prompt.


start
echo:PowerUp
 Brown out Reset
Marlin: 1.0.0 RC2
echo: Last Updated: 2012-02-25 | Author: erik
echo: Free Memory: 4907  Pla




echo:SD init fail
workDir open failed
echo:Unknown command:"echo"
ok
echo:Unknown command:"SD init fail"
ok
echo:Unknown command:"workDir open failed"
ok
.pre

^ settings

https://github.com/Printrbot/Marlin

.pre
M501
echo:Stored settings retreived:
echo:Steps per unit:
echo:  M92 X62.11 Y64.67 Z2272.72 E536.00
echo:Maximum feedrates (mm/s):
echo:  M203 X60.00 Y60.00 Z2.00 E14.00
echo:Maximum Acceleration (mm/s2):
echo:  M201 X2000 Y2000 Z30 E10000
echo:Acceleration: S=acceleration, T=retract acceleration
echo:  M204 S3000.00 T3000.00
echo:Advanced variables: S=Min feedrate (mm/s), T=Min travel feedrate (mm/s), B=minimum segment time (ms), X=maximum xY jerk (mm/s),  Z=maximum Z jerk (mm/s)
echo:  M205 S0.00 T0.00 B20000 X20.00 Z0.40 E5.00
echo:PID settings:
echo:   M301 P22.20 I1.08 D114.00

M115
FIRMWARE_NAME:Marlin V1; Sprinter/grbl mashup for gen6 FIRMWARE_URL:http://www.mendel-parts.com PROTOCOL_VERSION:1.0 MACHINE_TYPE:Mendel EXTRUDER_COUNT:1

.pre

If this doesn't work, you can try `M503` which should display all settings without loading them from flash.

^ software bed leveler

* https://github.com/emard/zleveler

^ schematics

{file: Printrboard_RevB_Schematic150.png}

{file: Printrboard-schematics.pdf}

^ Marlin

* https://github.com/MarlinFirmware/Marlin
* http://marlinfw.org/meta/gcode/

.pre
dpavlin@nuc:/nuc/PrintrBot$ git clone https://github.com/dpavlin/Marlin

dpavlin@nuc:/nuc/PrintrBot$ cd Marlin/
.pre

^^ compile Marlin 1.1.8

https://github.com/dpavlin/Marlin/tree/PrintrBot_Plus_LC-1.1.8

.pre
dpavlin@nuc:/nuc/PrintrBot/Marlin$ git checkout PrintrBot_Plus_LC-1.1.8 

dpavlin@nuc:/nuc/PrintrBot/Marlin$ platformio run -e printrboard
Warning! Ignore unknown `envs_dir` option in `[platformio]` section

Processing printrboard (platform: teensy; board: teensy20pp; framework: arduino)
-----------------------------------------------------------------------------------------------------------------------
Verbose mode can be enabled via `-v, --verbose` option
PLATFORM: Teensy > Teensy++ 2.0
SYSTEM: AT90USB1286 16MHz 8KB RAM (127KB Flash)
.pre

^^ compile Marlin 1.1.9

different enviroment compared to 1.1.8?

.pre
dpavlin@nuc:/nuc/PrintrBot/Marlin$ git checkout PrintrBot_Plus_LC-1.1.9 

dpavlin@nuc:/nuc/PrintrBot/Marlin$ platformio run -e teensy20
.pre

^^ flashing

open boot jumper, press button

.pre
[Sun Apr 15 12:20:34 2018] usb 1-1.1: new full-speed USB device number 30 using xhci_hcd
[Sun Apr 15 12:20:34 2018] usb 1-1.1: unable to get BOS descriptor
[Sun Apr 15 12:20:34 2018] usb 1-1.1: New USB device found, idVendor=03eb, idProduct=2ffb
[Sun Apr 15 12:20:34 2018] usb 1-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[Sun Apr 15 12:20:34 2018] usb 1-1.1: Product: AT90USB128 DFU
[Sun Apr 15 12:20:34 2018] usb 1-1.1: Manufacturer: ATMEL
[Sun Apr 15 12:20:34 2018] usb 1-1.1: SerialNumber: 1.0.0


root@nuc:/nuc/PrintrBot/Marlin# apt-get install dfu-programmer


root@nuc:/nuc/PrintrBot/Marlin# dfu-programmer --targets 2>&1 | grep at90usb128
    at89c5132          at90usb1287        at90usb1286        at90usb1287-4k
    at90usb1286-4k     at90usb647         at90usb646         at90usb162

root@nuc:/nuc/PrintrBot/Marlin# dfu-programmer at90usb1286 dump --debug 99
     target: at90usb1286
    chip_id: 0x2ffb
  vendor_id: 0x03eb
    command: dump
      quiet: false
      debug: 99
device_type: AVR
------ command specific below ------

commands.c:625: dump 122880 bytes
atmel.c:579: atmel_read_flash( 0x7ffe83facaf0, 0x00000000, 0x0001e000, 0x564ef5df7000, 122880, false )
atmel.c:847: atmel_select_page( 0x7ffe83facaf0, 0 )
atmel.c:510: __atmel_read_page( 0x7ffe83facaf0, 0, 65536, 0x564ef5df7000, false )
atmel.c:537: result: -9
Unknown error.  Try enabling debug.
Failed to read 122880 bytes from device.



.pre

other useful debug levels are 100, 200, 300 - https://www.avrfreaks.net/forum/how-use-dfu-programmer

hmmm... can't backup firmware?

^^ flash firmware

.pre
dpavlin@nuc:/nuc/PrintrBot/Marlin$ dfu-programmer at90usb1286 erase
dpavlin@nuc:/nuc/PrintrBot/Marlin$ dfu-programmer at90usb1286 flash .pioenvs/printrboard/firmware.hex
Validating...
Flash did not validate. Did you erase first?

dpavlin@nuc:/nuc/PrintrBot/Marlin$ dfu-programmer at90usb1286 erase --debug 100
     target: at90usb1286
    chip_id: 0x2ffb
  vendor_id: 0x03eb
    command: erase
      quiet: false
      debug: 100
device_type: AVR
------ command specific below ------
   validate: true

commands.c:69: erase 122879 bytes
atmel.c:281: atmel_erase_flash( 0x7ffc5df9bff0, 4 )
atmel.c:671: atmel_blank_check( 0x7ffc5df9bff0, 0x00000000, 0x0001dfff )
atmel.c:847: atmel_select_page( 0x7ffc5df9bff0, 0 )
atmel.c:647: __atmel_blank_check_internal( 0x7ffc5df9bff0, 0x00000000, 0x0000ffff )
atmel.c:847: atmel_select_page( 0x7ffc5df9bff0, 1 )
atmel.c:647: __atmel_blank_check_internal( 0x7ffc5df9bff0, 0x00000000, 0x0000dfff )

.pre

^^ teensy setup pjrc

udev rule: https://www.pjrc.com/teensy/49-teensy.rules
loader: https://github.com/PaulStoffregen/teensy_loader_cli

^^ unlock chip using flip

It seems that chip is protected. However, trying to erase and program it did destry data in it (expect bootloader) for some reason, and it seem that dfu-programmer doesn't know how to work with protection features.

So, next step is to try atmel's flip under linux but this also doesn't work well.

* patch path to /dev/bus/usb/ - https://www.avrfreaks.net/forum/instructions-get-batchisp-working-ubuntu-lucid-1004?name=PNphpBB2&file=viewtopic&t=97673

.pre
root@nuc:/nuc/PrintrBot/flip.3.2.1# cat debian-install.sh 
sudo apt-get install openjdk-9-jre:i386 libusb-0.1-4:i386

root@nuc:/nuc/PrintrBot/flip.3.2.1# cat env.sh 
export JAVA_HOME=/usr/lib/jvm/java-9-openjdk-i386/
export FLIP_HOME=/nuc/PrintrBot/flip.3.2.1/bin/


root@nuc:/nuc/PrintrBot/flip.3.2.1# cd bin/
root@nuc:/nuc/PrintrBot/flip.3.2.1/bin# cp -apv libatlibusbdfu.so libatlibusbdfu.so.orig
root@nuc:/nuc/PrintrBot/flip.3.2.1/bin# sed 's/\/sys\/bus\/usb/\/dev\/bus\/usb/g' libatlibusbdfu.so.orig > libatlibusbdfu.so


# run from bin directory or it won't work (?!)

root@nuc:/nuc/PrintrBot/flip.3.2.1/bin# ./flip.sh

.pre

^ avrdude

made cable to convert 10 pin ICSP on usbasp to 6 pin ICSP on printrboard

http://reprap.org/wiki/Printrboard#Bootloaders

Pin 1 (not red wire on my harness because of re-wiring) is closest to the SD card slot.

.pre
root@nuc:/nuc/PrintrBot# avrdude -p usb1286 -c usbasp 

avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9782 (probably usb1287)

avrdude: safemode: Fuses OK (E:F3, H:99, L:5E)

avrdude done.  Thank you.
.pre

ok, factory bootloader

^^ fuses

.pre
# disable jtag
avrdude -c usbtiny -p at90usb1286 -U lfuse:w:0xde:m -U hfuse:w:0xdb:m -U efuse:w:0xf0:m

# enabled jtag
avrdude -c usbtiny -p at90usb1286 -U lfuse:w:0xDE:m -U hfuse:w:0x9B:m -U efuse:w:0xF0:m

root@nuc:/nuc/PrintrBot# avrdude -c usbtiny -p at90usb1286 -U lfuse:w:0xde:m -U hfuse:w:0xdb:m -U efuse:w:0xf0:m
avrdude: Error: Could not find USBtiny device (0x1781/0xc9f)

avrdude done.  Thank you.

root@nuc:/nuc/PrintrBot# avrdude -c usbasp -p at90usb1286 -U lfuse:w:0xde:m -U hfuse:w:0xdb:m -U efuse:w:0xf0:m

avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9782 (probably usb1287)
avrdude: reading input file "0xde"
avrdude: writing lfuse (1 bytes):

Writing |                                                    | 0% 0.00s ***failed;
Writing | ################################################## | 100% 0.06s

avrdude: 1 bytes of lfuse written
avrdude: verifying lfuse memory against 0xde:
avrdude: load data lfuse data from input file 0xde:
avrdude: input file 0xde contains 1 bytes
avrdude: reading on-chip lfuse data:

Reading | ################################################## | 100% 0.00s

avrdude: verifying ...
avrdude: verification error, first mismatch at byte 0x0000
         0x5e != 0xde
avrdude: verification error; content mismatch

avrdude: safemode: lfuse changed! Was de, and is now 5e
[Tue Apr 17 07:12:19 2018] usb 1-1.4: USB disconnect, device number 20
[Tue Apr 17 07:12:19 2018] usb 1-1.4: USB disconnect, device number 20
Would you like this fuse to be changed back? [y/n]
Would you like this fuse to be changed back? [y/n] n
avrdude: safemode: Fuses OK (E:F3, H:99, L:DE)

avrdude done.  Thank you.


root@nuc:/nuc/PrintrBot# avrdude -p usb1286 -c usbasp 

avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9782 (probably usb1287)

avrdude: safemode: Fuses OK (E:F3, H:99, L:5E)

avrdude done.  Thank you.

.pre

^^ flash bootloader

huh, hum, program bootloader anyway from http://blog.lincomatic.com/?p=548

.pre
root@nuc:/nuc/PrintrBot# avrdude -p usb1286 -c usbasp -U flash:w:BootloaderDFU.hex
.pre

power cycle, return jumper re-try programming fuses

.pre
root@nuc:/nuc/PrintrBot# avrdude -c usbasp -p at90usb1286 -U lfuse:w:0xDE:m -U hfuse:w:0x9B:m -U efuse:w:0xF0:m
.pre

^^ dfu programming works

re-try dfu programming

.pre
root@nuc:/nuc/PrintrBot# dfu-programmer at90usb1286 erase
root@nuc:/nuc/PrintrBot# dfu-programmer at90usb1286 flash Marlin/.pioenvs/printrboard/firmware.hex
Validating...
61322 bytes used (49.90%)


.pre

^^ avrdude programming

.pre
dpavlin@nuc:/nuc/PrintrBot/Marlin$ avrdude -c usbasp -p usb1286 -U flash:w:.pioenvs/printrboard/firmware.hex

avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: AVR device initialized and ready to accept instructions

Reading | ################################################## | 100% 0.00s

avrdude: Device signature = 0x1e9782 (probably usb1287)
avrdude: NOTE: "flash" memory has been specified, an erase cycle will be performed
         To disable this feature, specify the -D option.
avrdude: erasing chip
avrdude: warning: cannot set sck period. please check for usbasp firmware update.
avrdude: reading input file ".pioenvs/printrboard/firmware.hex"
avrdude: input file .pioenvs/printrboard/firmware.hex auto detected as Intel Hex
avrdude: writing flash (87280 bytes):

Writing | ################################################## | 100% 58.04s

avrdude: 87280 bytes of flash written
avrdude: verifying flash memory against .pioenvs/printrboard/firmware.hex:
avrdude: load data flash data from input file .pioenvs/printrboard/firmware.hex:
avrdude: input file .pioenvs/printrboard/firmware.hex auto detected as Intel Hex
avrdude: input file .pioenvs/printrboard/firmware.hex contains 87280 bytes
avrdude: reading on-chip flash data:

Reading | ################################################## | 100% 38.49s

avrdude: verifying ...
avrdude: 87280 bytes of flash verified

avrdude: safemode: Fuses OK (E:F0, H:9B, L:DE)

avrdude done.  Thank you.
.pre

^ RepRapDiscount Full Graphic Smart Controller

* http://reprap.org/wiki/RepRapDiscount_Full_Graphic_Smart_Controller

^^ pinouts

{file: printrboard-lcd-pinout.png}

{image: printrboard-lcd-pinout-800px.png}

^^ Marlin pinout

.pre
diff --git a/Marlin/pins_PRINTRBOARD.h b/Marlin/pins_PRINTRBOARD.h
index 42632d174..8146505a3 100644
--- a/Marlin/pins_PRINTRBOARD.h
+++ b/Marlin/pins_PRINTRBOARD.h
@@ -166,3 +166,19 @@
   #endif
 
 #endif // ULTRA_LCD && NEWPANEL
+
+// XXX dpavlin -- my pinout
+#define LCD_PINS_RS       9   // E1       JP11-11
+#define LCD_PINS_ENABLE   8   // E0       JP11-10
+#define LCD_PINS_D4       7   // D7       JP11-8
+#define LCD_PINS_D5       6   // D6       JP11-7
+#define LCD_PINS_D6       5   // D5       JP11-6
+#define LCD_PINS_D7       4   // D4       JP11-5
+
+#define BTN_EN1        10   // C0       JP11-12
+#define BTN_EN2        11   // C1       JP11-13
+#define BTN_ENC        12   // C2       JP11-14
+
+// display delays are added to
+// Marlin/ultralcd_st7920_u8glib_rrd.h
+
diff --git a/Marlin/ultralcd_st7920_u8glib_rrd.h b/Marlin/ultralcd_st7920_u8glib_rrd.h
index db6224e47..8474bef24 100644
--- a/Marlin/ultralcd_st7920_u8glib_rrd.h
+++ b/Marlin/ultralcd_st7920_u8glib_rrd.h
@@ -49,7 +49,7 @@
   #define CPU_ST7920_DELAY_1 DELAY_NS(0)
   #define CPU_ST7920_DELAY_2 DELAY_NS(0)
   #define CPU_ST7920_DELAY_3 DELAY_NS(50)
-#elif MB(3DRAG) || MB(K8200) || MB(K8400) || MB(SILVER_GATE)
+#elif MB(3DRAG) || MB(K8200) || MB(K8400) || MB(SILVER_GATE) || MB(PRINTRBOARD)
   #define CPU_ST7920_DELAY_1 DELAY_NS(0)
   #define CPU_ST7920_DELAY_2 DELAY_NS(188)
   #define CPU_ST7920_DELAY_3 DELAY_NS(0)
.pre

^ Hardware upgrade

^^ RAMPS1.4 LCD 12864

* RAMPS1.4 LCD 12864 Control Panel 3D Printer Smart Controller LCD Display $10
** https://www.aliexpress.com/item/1-pcs-RAMPS1-4-LCD-12864-Control-Panel-3D-Printer-Smart-Controller-LCD-Display-Free-Shipping/32312042967.html
** $10 - works well, needs custom cable, well worth it from usability perspective

^^ LM8UU

* 10pcs/lot LM8UU Ball Bearings 8mm Bushing For CNC 3D Printers Parts Rail Linear Long Rod Shaft Part 8mm*15mm*24mm Aluminum Bush
** https://www.aliexpress.com/item/10pcs-lot-LM8UU-Ball-Bearings-8mm-Bushing-For-CNC-3D-Printers-Parts-Rail-Linear-Long-Rod/32834729285.html
** $4.24 - NOT recomended, worse that original VXB.com -- seller specified brand as FYSETC, parts don't have any markings

^^ Y axis coupler

* 3D Printer Parts Accessory Stepper Motor Aluminum Alloy Z Axis Flexible Coupling Coupler Shaft Couplings 5mm*8mm*25mm
** https://www.aliexpress.com/item/10pcs-lot-LM8UU-Ball-Bearings-8mm-Bushing-For-CNC-3D-Printers-Parts-Rail-Linear-Long-Rod/32834729285.html
** $0.75 - NOT for Y axis, since they are flexible
* 3D Printer Blue Aluminum Alloy Coupler for 5 x 5mm/5 x 8mm Shaft for Stepper Motor Shaft
** https://www.aliexpress.com/item/3D-Printer-Blue-Aluminum-Alloy-Coupler-for-5-x-5mm-5-x-8mm-Shaft-for-Stepper/32854452012.html
** $0.71 - great, much better than 3d printed part

^^ belts and pulleys

* 2pcs GT2 20teeth 20 Teeth Bore 5mm/8mm Timing Alumium Pulley + 2Meters Rubber GT2-6mm Open Timing Belt Width 6mm for 3D Printer
** https://www.aliexpress.com/item/2Pcs-GT2-20teeth-20-Teeth-Bore-5mm-8mm-Timing-Alumium-Pulley-2Meters-Rubber-GT2-6mm-Open/32711078503.html
** $1.90 - great, pully nut doesn't interfere with clip which is holding glass since nut is flush as opposed to 3d printed part

^^ Y axes rod

* T8 Lead Screw OD 8mm Pitch 2mm Lead 2mm 150mm 200mm 250mm 300mm 350mm 400mm 500mm with Brass Nut for Reprap 3D Printer Z Axis
** 250mm with Nut
** https://www.aliexpress.com/item/T8-Lead-Screw-Rod-OD-8mm-Pitch-2mm-Lead-2mm-Length-150mm-500mm-Threaded-Rods-with/32760102869.html
** $5.14 x 2 - great, our rods where bent from out of box

Needs 3d printed adapter for nut to fit: https://www.thingiverse.com/thing:2963508

Nut is friction fit which I consider somewhat as safety feature, if I found problems with it, I will probably add a bit of ABS goo in holes to fix it in place

^^ bed leveling

self-made sensor from RFID card, paper clip and case intrusion switch, connected in parallel with z-axis switch (it has to be normally closed, so that trigger interrupts signal)

^ BL touch

* 1 Set Newest BL Touch Auto Bed Leveling Sensor 3D Touch Auto Leveling Sensor For Anet A8 3D Printer Improve Printing Precision
** https://www.aliexpress.com/store/product/1-Set-Newest-BL-Touch-Auto-Bed-Leveling-Sensor-3D-Touch-for-3D-Printer-Improve-Printing/3108017_32837521614.html

http://www.geeetech.com/wiki/index.php/3DTouch_Auto_Leveling_Sensor

pinout, right to left

| pin | wire color | board label |
| 5 | green | G |
| 4 | red | 5V |
| 3 | yellow | S |
| 2 | black | G |
| 1 | white | Z- |

Needs additional pin for servo control (S - servo)

^^ Marlin configuration

.pre
commit 18396a8cd25585d5d562d4345ed851b91fb58821 (HEAD -> PrintrBot_Plus_LC-1.1.9)
Author: Dobrica Pavlinusic <dpavlin@rot13.org>
Date:   Sat Sep 8 11:05:54 2018 +0200

    probe offset from extruder

diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index 438494220..aeed322a7 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -770,8 +770,8 @@
  *      O-- FRONT --+
  *    (0,0)
  */
-#define X_PROBE_OFFSET_FROM_EXTRUDER 10  // X offset: -left  +right  [of the nozzle]
-#define Y_PROBE_OFFSET_FROM_EXTRUDER 10  // Y offset: -front +behind [the nozzle]
+#define X_PROBE_OFFSET_FROM_EXTRUDER 35  // X offset: -left  +right  [of the nozzle]
+#define Y_PROBE_OFFSET_FROM_EXTRUDER 5   // Y offset: -front +behind [the nozzle]
 #define Z_PROBE_OFFSET_FROM_EXTRUDER 0   // Z offset: -below +above  [the nozzle]
 
 // Certain types of probes need to stay away from edges

commit 2329e561e0f2997e78495c249706e9ce62608293
Author: Dobrica Pavlinusic <dpavlin@rot13.org>
Date:   Sat Sep 8 10:51:07 2018 +0200

    enable bed leveling
    
    AUTO_BED_LEVELING_UBL doesn't seem to compile for me ATM

diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index 38e0c343b..438494220 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -969,7 +969,7 @@
  */
 //#define AUTO_BED_LEVELING_3POINT
 //#define AUTO_BED_LEVELING_LINEAR
-//#define AUTO_BED_LEVELING_BILINEAR
+#define AUTO_BED_LEVELING_BILINEAR
 //#define AUTO_BED_LEVELING_UBL
 //#define MESH_BED_LEVELING
 
@@ -1023,6 +1023,8 @@
   //#define FRONT_PROBE_BED_POSITION MIN_PROBE_EDGE
   //#define BACK_PROBE_BED_POSITION (Y_BED_SIZE - MIN_PROBE_EDGE)
 
+  #define RIGHT_PROBE_BED_POSITION 190 // dpavlin -- probe overhangs on the right
+
   // Probe along the Y axis, advancing X after each column
   //#define PROBE_Y_FIRST
 

commit b867a948cd3b64d69e900b99a1306631d62753df
Author: Dobrica Pavlinusic <dpavlin@rot13.org>
Date:   Sun Sep 2 08:40:52 2018 +0200

    added bltouch config and pin on e-stop

diff --git a/Marlin/Configuration.h b/Marlin/Configuration.h
index fd8463456..38e0c343b 100644
--- a/Marlin/Configuration.h
+++ b/Marlin/Configuration.h
@@ -721,7 +721,7 @@
 /**
  * The BLTouch probe uses a Hall effect sensor and emulates a servo.
  */
-//#define BLTOUCH
+#define BLTOUCH
 #if ENABLED(BLTOUCH)
   //#define BLTOUCH_DELAY 375   // (ms) Enable and increase if needed
 #endif
@@ -1909,7 +1909,7 @@
  * Set this manually if there are extra servos needing manual control.
  * Leave undefined or set to 0 to entirely disable the servo subsystem.
  */
-//#define NUM_SERVOS 3 // Servo index starts with 0 for M280 command
+#define NUM_SERVOS 1 // Servo index starts with 0 for M280 command
 
 // Delay (in milliseconds) before the next move will start, to give the servo time to reach its target angle.
 // 300ms is a good value but you can try less delay.
diff --git a/Marlin/pins_PRINTRBOARD.h b/Marlin/pins_PRINTRBOARD.h
index 8146505a3..a68802725 100644
--- a/Marlin/pins_PRINTRBOARD.h
+++ b/Marlin/pins_PRINTRBOARD.h
@@ -182,3 +182,9 @@
 // display delays are added to
 // Marlin/ultralcd_st7920_u8glib_rrd.h
 
+// bltouch - use e-stop for servo
+// dpavlin@nuc:/nuc/PrintrBot/Marlin$ grep E5 m43-pins.txt 
+// PIN:  37   Port: E5        <unused/unknown>            Input  = 1
+//
+#define SERVO0_PIN	37	// E5 E-STOP
+
.pre

^^ gcode for bl-touch

M280 P0 S10 ; pushes the pin down

M280 P0 S90 ; pulls the pin up

M280 P0 S120 ; Self test – keeps going until you do pin up/down or release alarm

M280 P0 S160 ; Release alarm

M420 V ; display bed leveling

.pre
Bilinear Leveling Grid:
      0      1      2
 0 +0.445 +0.402 +0.284
 1 -0.083 +0.013 +0.023
 2 -0.678 -0.432 -0.264

echo:Bed Leveling On 
echo:Fade Height Off
.pre

----

^ Notes for Ender 3 V1.1.3

* install sanguino board support in ardunino ide https://github.com/Lauszus/Sanguino
* turn on power supply when flashing if you didn't disconnect steppers or it won't get enough power
* burn boot loader using usbasp programmer from arduino ide to make arudino ide work for upload
^ PostmarketOS

<https://wiki.postmarketos.org/wiki/Google_Nexus_5_(lg-hammerhead>)

.pre
dpavlin@klin:/klin/postmarketos$ git clone https://gitlab.com/postmarketOS/pmbootstrap
dpavlin@klin:/klin/postmarketos$ cd pmbootstrap/

dpavlin@klin:/klin/postmarketos/pmbootstrap$ ./pmbootstrap.py init

#

./pmbootstrap.py install --no-fde


.pre
{toc}

ChinaChip CC1800-A

http://www.dingux.com/2011/03/running-code-on-ga330.html


^ dmesg

.pre
[164083.920115] usb 1-1: new high-speed USB device number 14 using ehci-pci
[164084.069506] usb 1-1: New USB device found, idVendor=07c4, idProduct=a4a5
[164084.069513] usb 1-1: New USB device strings: Mfr=0, Product=0, SerialNumber=1
[164084.069516] usb 1-1: SerialNumber: A00A00A00A00
[164084.075555] usb-storage 1-1:1.0: USB Mass Storage device detected
[164084.109544] usb-storage 1-1:1.0: Quirks match for vid 07c4 pid a4a5: 420
[164084.132100] scsi5 : usb-storage 1-1:1.0
[164085.142318] scsi 5:0:0:0: Direct-Access     ONDA MP4  PLAYER               PQ: 0 ANSI: 0
[164085.142774] scsi 5:0:0:1: Direct-Access     ONDA MP4  PLAYER               PQ: 0 ANSI: 0
[164085.143181] sd 5:0:0:0: Attached scsi generic sg1 type 0
[164085.143560] sd 5:0:0:1: Attached scsi generic sg2 type 0
[164085.143877] sd 5:0:0:0: [sdb] 16179200 512-byte logical blocks: (8.28 GB/7.71 GiB)
[164085.145277] sd 5:0:0:0: [sdb] Write Protect is off
[164085.145287] sd 5:0:0:0: [sdb] Mode Sense: 00 06 00 00
[164085.147025] sd 5:0:0:0: [sdb] Asking for cache data failed
[164085.147032] sd 5:0:0:0: [sdb] Assuming drive cache: write through
[164085.147930] sd 5:0:0:1: [sdc] Attached SCSI removable disk
[164085.152030]  sdb:
[164085.155629] sd 5:0:0:0: [sdb] Attached SCSI removable disk
.pre

^ firmware extracting

* tools from http://forum.xda-developers.com/showpost.php?p=28329544&postcount=1

.pre
dpavlin@x200:/x200/Onda-VX575HD/imgRePacker_W201_L100$ ./imgrepacker ../ftp.onda.cn/download/driver/oamp3/VX575HD/VX575HD_V1.02.img

        imgRePacker (version 1.00 linux)
        LiveSuit's firmware image unpacker/packer

        (c) RedScorpio, Moscow, 2012
            RedScorpio@land.ru

        ==========================[ START ]==========================

        --- Firmware unpacking ---

        File "../ftp.onda.cn/download/driver/oamp3/VX575HD/VX575HD_V1.02.img"   was read


        - image.cfg creating -
        image.cfg created
        Can't check "sys_config"

        - Files extracting -
        "eFex/sys_config.fex"           extracted
        "eFex/split_c43a2a92-a8ed-4f92-abdb-ca0d5d29666d.bin"           decrypted
        "eFex/tools.fex"                extracted
        "eFex/fes_1.fex"                extracted
        "eFex/fes_2.fex"                extracted
        "eFex/fes.fex"          extracted
        "eGon/Boot0.bin"                decrypted
        "eGon/Boot1.bin"                decrypted
        "eFex/HW_scan.axf"              decrypted
        "eFex/update_Boot0.axf"         decrypted
        "eFex/update_Boot1.axf"         decrypted
        "eFex/fet_restore.axf"          decrypted
        "eFex/magic_cr_start.fex"               extracted
        "eFex/magic_cr_end.fex"         extracted
        "eFex/magic_de_start.fex"               extracted
        "eFex/magic_de_end.fex"         extracted
        "eFex/fed_nand.axf"             decrypted
        "setup/zdisk.img"               decrypted
                - Internal image (zdisk.img) processing -
                - zdisk.cfg creating -
                zdisk.cfg created
        "eFex/verify.fex"               extracted
        "setup/rootfs.az"               extracted
                - AZXMAGIC processing (rootfs.az) -
                AZKey don't found in "rootfs.az" (use "/8600" key for packing)
                rootfs.az.iso.lzma created
        -------------------------------------------------------------
                Run XZ archivator (unpacking)
        -------------------------------------------------------------
                rootfs.az.iso created
        "setup/startup1.bmp"            extracted
        "setup/startup2.bmp"            extracted
        "setup/startup3.bmp"            extracted
        "setup/startup4.bmp"            extracted

        - Filelist.txt creating -
        Filelist.txt created

        ==========================[ STOP  ]==========================
.pre

^ firmware download and binwalk

.pre

dpavlin@x200:/x200/Onda-VX575HD$ wget -m ftp://ftp.onda.cn/download/driver/oamp3/VX575HD/VX575HD*.img
dpavlin@x200:/x200/Onda-VX575HD/ftp.onda.cn/download/driver/oamp3/VX575HD$ binwalk -B -H -G *.img

Scan Time:     2015-01-30 18:29:59
Target File:   VX575HD_VX585_FLASH_TOOLS.img
MD5 Checksum:  99b941b405409a829ada43eee3736532

DECIMAL       HEXADECIMAL     HEURISTIC ENTROPY ANALYSIS
--------------------------------------------------------------------------------
2048          0x800           Moderate entropy data, best guess: compressed, size: 17408, 102 low entropy blocks
34816         0x8800          High entropy data, best guess: encrypted, size: 65536, 0 low entropy blocks
105472        0x19C00         Moderate entropy data, best guess: compressed, size: 25600, 5 low entropy blocks
151552        0x25000         High entropy data, best guess: encrypted, size: 32768, 0 low entropy blocks
211968        0x33C00         High entropy data, best guess: encrypted, size: 21504, 0 low entropy blocks
236544        0x39C00         Moderate entropy data, best guess: compressed, size: 140288, 7 low entropy blocks
384000        0x5DC00         High entropy data, best guess: encrypted, size: 16384, 0 low entropy blocks
415744        0x65800         Moderate entropy data, best guess: compressed, size: 56320, 2 low entropy blocks
494592        0x78C00         Moderate entropy data, best guess: compressed, size: 56320, 2 low entropy blocks
579584        0x8D800         Moderate entropy data, best guess: compressed, size: 53248, 2 low entropy blocks
655360        0xA0000         High entropy data, best guess: encrypted, size: 9106432, 0 low entropy blocks
9782272       0x954400        High entropy data, best guess: encrypted, size: 13312, 0 low entropy blocks
9816064       0x95C800        High entropy data, best guess: encrypted, size: 13312, 0 low entropy blocks



.pre

* https://www.mp4nation.net/forum/onda-vx575hd-t10249.html
* https://www.mp4nation.net/forum/onda-vx575hd-t10249s30.html

VX575HD v1.02 beta version of the firmware 

Updated 2009-09-24
Support Type VX575HD

1. Add files to copy, paste, cut function; 
2. New e-book reading function of vertical screen; 
3. New Sleep off function; 
4. Added support for Traditional Chinese support

firmware download > ftp://ftp.onda.cn/download/driver/oamp3 ... _V1.02.img (right click > save as..)

livesuite download > ftp://ftp.onda.cn/download/driver/oamp3 ... veSuit.rar (right click > save as..)

Note: 
1. Firmware upgrade must upgrade tool, please download the firmware upgrade tool file. 
2. Firmware upgrade method, see the firmware upgrade tool documentation. 
3. Test version of the firmware, there may be BUG, only for experienced users to download a trial.
{file: Samsung_UExxEH45_53_ES55_57_58_U78A.pdf}

{file: Samsung шасси U71A, U71B.pdf}

{toc: }

^ service menu

https://wiki.samygo.tv/index.php?title=Service_Menu

Enter service menu: UE,LE models:[INFO] [MENU] [MUTE] [POWER]

This has to be pressed fast, within second or two. To disable sound, select HDMI input.

.pre
T-MST10PDEUC-2007.0
T-MST10PDEUS-1002
E-Manual:XTDVBEUE-1042

EDID SUCCESS
HDCP SUCCESS
CALIB: AV / COMP / PC / HDMI /
Option: 40A6AF0D,EU,5450,NONE
FactoryCS: 0x5ce5c95
T-MSXDEUCIP-1000

Onboot : 1003
SDAL-3.63.0.0
RFS:*X10P 0072
2016-04-01
FUNC-TAG-ERR

Type: 40A6AF0D
Model: UE40EH5450
Wired MAC ----
CIP SUCCESS
DRM : ----
Factory Data Ver : 216
EERC Version : 2124
DTP-AP-COMP-945-X10P_DEU-107
DTP-BP-HAL-0381-X10P_DEU-204-01
DTP-BP-0874-42
POP-FLA-12-0009.19
Date of purchase : 1/4/2019
.pre

Sigh, I did reset with default PIN 0000 before entering service menu, so counter and date is reset.

I also changed Control > Sub Option > RS-232 Jack -> Debug

^ Ex-Link Cable (service port TTL serial)

https://wiki.samygo.tv/index.php?title=Ex-Link_Cable_for_C/D/E_Series_and_BD_players

{image: 800px-TTL-232_E_pinout.jpg}

3.5mm jack "service" on TV:

* 1 - tip - Tx
* 2 - ring - Rx
* 3 - ring - GND

If you have TRRR jack, just use first three pins. Others are not connected to anything in TV.
To find ground pin check continuity between your jack breakout and USB connector. One you found
ground, pins from it towards tip are Rx and Tx.

I also measured Rx and Tx pins which where around 3.3V, so safe to connect to usb serial.

^^ dump of serial console

It's 115200 8n1 3.3V serial console:

{file: samsung-UE40EH5450-serial.txt.gz}

^ top-debug menu

https://wiki.samygo.tv/index.php?title=Top_Debug_Menu:_TDM

^^ Console unlock and TDM codes

MStar (Series 5 & 6):

1198282
20089999

Just blindly start typing numbers:

.pre
20089999
====================================
      [ TOP Debug Menu]
------------------------------------
  1  : SubSystem Print On/Off
  2  : Platform Print Setting
  3  : TD Print Setting
  4  : Performance Print Setting
  5  : Sdal Print Setting
  6  : Sdal Trace Setting
  11 : TD Debug
  12 : SubSystem DBG
  13 : SubSystem Info Print
  21 : Louvre Print Setting
  30 : Auto Lock DBG
------------------------------------
  70 : Jade Debug
  80 : PVR Debug
  81 : CSP debug
====================================
  99 : Exit
====================================
.pre

^ service manuals

http://tel-spb.ru/tv/samsung-ue40eh5450
^ pictures

^^ position of plastic clips to unclip after removing screws

{file: innobox-v80-case-clips-20210522_192312.jpg}

^^ top of board

{file: innobox-v80-top-20210522_192339.jpg}

^^ bottom of board

{file: innobox-v80-back-20210522_192256.jpg}

^ software version

Hardware version: 	 1.0
Active image: 	 2
Firmware image 1: 	 1.0.839
Firmware image 2: 	 1.1.966
Checksum of image 1: 	 34e4b3948d00a869d961283510a7eb08
Checksum of image 2: 	 a6e08754c908c237d1539cb143611697
Firmware bootloader: 	 1.9
CRC of bootloader: 	 a6e08754c908c237d1539cb143611697

^ serial

4 pins, pin 1 marked with triangle

1: TX
2: RX
3: GND
4: 3V3 (?)

^ serial output

(partial)

.pre
BGA IC
Xtal:1
DDR3 init.
DRAMC init done.
Calculate size.
DRAM size=128MB
Set new TRFC.

7512DRAMC V1.2.2 (0)


EN751221 at Fri Apr 16 11:48:25 CST 2021 version 1.9 free bootbase

Memory size 128MB

Set SPI Clock to 50 Mhz
spi_nand_probe: mfr_id=0xc8, dev_id=0x21
Using Flash ECC.
Detected SPI NAND Flash : _SPI_NAND_DEVICE_ID_F50L1G, Flash Size=0x8000000
bmt pool size: 81
BMT & BBT Init Success


>>>> [get_env_info] hw_id:InnboxV80_PW2
>>>> [set_gpio_define] g_hw_id:InnboxV80_PW2
Reset button GPIO is: 0
Press any key in 3 secs to enter boot command mode.
............................................................

Invalid Power GPIO, just return and don't turn on Power LED

NAND FLASH

>>>> CTC: boot_flag_addr: 53e0fff; flag: 1 version_addr:53e1000 version:1.9<FF><FF><FF><FF>

==> boot flag = 1
Decompress to 80002000 free_mem_ptr=80E00000 free_mem_ptr_end=807B0000
from slave
Uncompressing [LZMA] ...  done.
Initializing cgroup subsys cpuset
Initializing cgroup subsys cpu
Initializing cgroup subsys cpuacct
Linux version 3.18.21 (iskratel@2d7d74f016e9) (gcc version 4.6.3 (Buildroot 2015.08.1) ) #3 SMP Fri Apr 16 11:32:58 CST 2021
ISPRAM0: PA=00770000,Size=00010000,enabled
Config7: 0x80080500
memsize:120MB
EcoNet EN751221 SOC prom init
bootconsole [early0] enabled
CPU0 revision is: 00019558 (MIPS 34Kc)
Determined physical RAM map:
 memory: 077fe000 @ 00002000 (usable)
Wasting 64 bytes for tracking 2 unused pages
Zone ranges:
  Normal   [mem 0x00002000-0x077fffff]
Movable zone start for each node
Early memory node ranges
  node   0: [mem 0x00002000-0x077fffff]
Initmem setup node 0 [mem 0x00002000-0x077fffff]
Detected 1 available secondary CPU(s)
Primary instruction cache 64kB, VIPT, 4-way, linesize 32 bytes.
Primary data cache 32kB, 4-way, VIPT, cache aliases, linesize 32 bytes
PERCPU: Embedded 9 pages/cpu @810f3000 s5664 r8192 d23008 u36864
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 30478
Kernel command line:  es=1
PID hash table entries: 512 (order: -1, 2048 bytes)
Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
Writing ErrCtl register=0002e01a
Readback ErrCtl register=0002e01a
nmi base is 81124200
Memory: 110280K/122872K available (7640K kernel code, 1290K rwdata, 1624K rodata, 304K init, 551K bss, 12592K reserved)
SLUB: HWalign=32, Order=0-3, MinObjects=0, CPUs=2, Nodes=1
Hierarchical RCU implementation.
NR_IRQS:64

tc3162_time_init: Init bus timeout and watchdog
plat_set_irq_affinity: cpu 0
plat_set_irq_affinity: cpu 0 vpe_id 0
plat_set_irq_affinity: irq_vpe0 1 irq_vpe1 0, irq = 10
plat_set_irq_affinity: irq num 10
plat_set_irq_affinity: cpu 0
plat_set_irq_affinity: cpu 0 vpe_id 0
plat_set_irq_affinity: irq_vpe0 1 irq_vpe1 0, irq = 33
plat_set_irq_affinity: irq num 33
CPU frequency 900.00 MHz
plat_time_init: Entered, mips_timer_ack ptr is [80006dd4]
 Using 200.000 MHz high precision timer.
r4k_clockevent_init: setup_irq OK, irq is [31]
console [ttyS0] enabled
console [ttyS0] enabled
bootconsole [early0] disabled
bootconsole [early0] disabled
Calibrating delay loop... 597.60 BogoMIPS (lpj=2988032)
pid_max: default: 32768 minimum: 301
.pre

^ boot loader

.pre
bldr> ?

?                                   Print out help messages.
help                                Print out help messages.
go                                  Booting the linux kernel.
decomp                              Decompress kernel image to ram.
memrl <addr>                        Read a word from addr.
memwl <addr> <value>                Write a word to addr.
dump <addr> <len>                   Dump memory content.
jump <addr>                         Jump to addr.
flash <dst> <src> <len> <oob>       Write to flash from src to dst(oob: write nand oob if 1).
imginfo                             Show images info.
spinand_rwtest                      Flash Test
bdstore <flash dst> <bin src>       Do backdoor config store
bdshow                              Show backdoor config
bdswitch[1|0]                       Enable or disable backdoor function
ddrcalswitch[1|0]                   Enable or disable ddr calibration funciton
drambistswitch[0|1|2]               disable or enable, and quick or normal test
xmdm <addr> <len>                   Xmodem receive to addr.
miir <phyaddr> <reg>                Read ethernet phy reg.
miiw <phyaddr> <reg> <value>        Write ethernet phy reg.
cpufreq <freq num> / <m> <n>        Set CPU Freq <156~450>(freq has to be multiple of 6)
ipaddr <ip addr>                    Change modem's IP.
httpd                               Start Web Server
mtd
bldr> bdshow
back door config is not support NAND Flash
.pre
{file: ELM327QS.pdf}

{file: ELM327DSF.pdf}

{file: ELM327DS.pdf}

^ Connector position

* Chevrolet Kalos - right below steering wheel, vertically down
* Opel Vectra - take out astray, and connector is under it

^ OBDSim

* http://icculus.org/obdgpslogger/obdsim.html

.pre
ATZ
ELM327 v1.3a OBDGPSLogger
>0100
?
>0100
41 00 FF FF FF FE
>0105
41 05 BB
>0106
41 06 EE
>
.pre
USB [FX2LP] based logic analyzers

* http://www.triplespark.net/elec/periph/USB-FX2/eeprom/

^ Saleae / USBEE AX MINI

.pre
dpavlin@blue:~$ lsusb -d 0925:3881 
Bus 001 Device 022: ID 0925:3881 Lakeview Research Saleae Logic
.pre

http://dx.com/p/logic-analyzer-w-dupont-lines-and-usb-cable-for-scm-black-148945

http://www.epanorama.net/blog/2012/10/02/usbee-ax-clone/

http://www.jwandrews.co.uk/2011/12/saleae-logic-analyser-clone-teardown-and-reprogramming/

http://tubbutec.de/blog/adding-output-capability-to-a-10e-logic-analyser/

^^ Linux software

https://bitbucket.org/wump/usbee

https://blog.visucore.com/2010/5/27/usbee-sx-protocol-description

http://sigrok.org/wiki/Fx2lafw

http://www.drdobbs.com/embedded-systems/rocking-with-sigrok/240147198

^ USBee AX Pro

http://dx.com/p/usb-oscilloscope-and-logic-analyzer-93518

* https://blog.visucore.com/tags/usbee

* http://www.eeelec.com/xla/

^ CY7C68013 datasheets

* http://www.datasheetsite.com/datasheet/CY7C68013

^ Change usb id under Linux

http://gronlier.fr/blog/2014/07/usbee-ax-pro-reprogramming/

.pre
root@x200:/rest/cvs/fx2eeprom# apt-get install fxload

root@x200:/rest/cvs/fx2eeprom# git remote -v
origin  https://github.com/ribalda/fx2eeprom.git (fetch)
origin  https://github.com/ribalda/fx2eeprom.git (push)

root@x200:/rest/cvs/fx2eeprom# lsusb -d 08a9:0014
Bus 007 Device 010: ID 08a9:0014 CWAV Inc. USBee AX-Pro

root@x200:/rest/cvs/fx2eeprom# fxload -D /dev/bus/usb/007/010 -t fx2lp -I vend_ax.hex 

root@x200:/rest/cvs/fx2eeprom# sudo ./fx2eeprom r 0x08a9 0x0014 8 > eeprom.dat
Readed 8 bytes

root@x200:/rest/cvs/fx2eeprom# hexdump -C eeprom.dat 
00000000  c0 a9 08 14 00 00 1b 00

# edit usb id

root@x200:/rest/cvs/fx2eeprom# hexdump -C saleae.dat 
00000000  c0 25 09 81 38 00 1b 00                           

root@x200:/rest/cvs/fx2eeprom# sudo ./fx2eeprom w 0x08a9 0x0014 8 < saleae.dat 
Written 8 bytes

# unplug, re-plug usb dongle

root@x200:/rest/cvs/fx2eeprom# lsusb -d 0925:3881
Bus 007 Device 013: ID 0925:3881 Lakeview Research Saleae Logic


.pre
{toc: }

There are many on-line resources about RFID. However, most of them are not well suited for beginners. So, if you just got RFID reader (3M in this case) and want high-level overview of what it is and what it can do, you are out of luck.

Until now, that is. This guide should help you decide if RFID is right thing for your library and when you make choice to implement it, how to do it.

This document will describe my experience with 3M 810 reader using RFID 501: RFID Standards for Libraries {file: RFID_501.pdf}

^ RFID tag

Best way to think about RFID tags is like contact-less readable barcode.

Our particular tags come in two form: RFID stickers (to be placed on books) and plastic credit-card like cards (we use them for patrons).

Have in mind that established practice is to have different RFID systems for books and patrons (we are use same one). When we asked about using same system for books and patrons, we got reply: "we don't have experience with it".
In practice, we have problem with 3M selfcheck software in some special conditions where book reader have patron card in range it gets network connection error with SIP server.
Since normal configuration of selfcheck stations is to have two different systems for patrons and books this problem doesn't show up for other users.

Each tag has unique serial number (SID) assigned by manufacturer and used in RFID collision detection protocol. It looks like hexadecimal number starting with letter `E0` like this: `E00401003123AA26`.

It's best to think of SID as unique identifier of physical tag.
Your information system will have it's own ID (barcode?) for some item.
There are cases in which you might want to change physical tag sticker on book because it's damaged. In that case, you will change SID of that item, but not barcode (which is data programmed on tag itself).

Our initial idea was to use data programmed on chip for everything, and just ignore SIDs, but we found out that there is class of RFID devices which can read ONLY SID from chip (in our case it's photocopying system).
3M software does record SIDs to log file when programming chips, but that's all. It essential ignores it for all practical intends and purposes.

Chips have 7 blocks of user data on it, each block with 4 bytes which enables us to store 28 bytes of user specified data on each tag.

^^ blank tag

^^^ 3M Manufacturing Blank

Easiest case is blank tag, in which all data on chip is 0x55

.pre
0	55 55 55 55		blank tag
1	55 55 55 55
2	55 55 55 55
3	55 55 55 55
4	55 55 55 55
5	55 55 55 55
6	00 00 00 00 
.pre

^^^ Generic blank

Generic blank seems to erase only first three blocks with zeros:

.pre
00	00 00 00 00
01	00 00 00 00
02	00 00 00 00
.pre

while rest of tag will be unchanged *including rest of data on tag*

^^ programmed tag

Tags programmed with 3M software have following data layout on them:

.pre
0	04 is 00 tt		i [4 bit] = number of item in set	[1 .. i .. s]
					s [4 bit] = total items in set
					tt [8 bit] = item type

1	dd dd dd dd		dd [16 bytes] = barcode data
2	dd dd dd dd
3	dd dd dd dd
4	dd dd dd dd

5	bb bl ll ll		b [12 bit] = branch [unsigned]
				l [20 bit] = library [unsigned]
6	cc cc cc cc		c [32 bit] = custom signed integer
.pre

This basically means that your barcode or identifier of item or patron can have up to 16 characters (by default numeric, but you can extend that to handle alphanumeric and special character if you need that) and three integer values: branch `0 .. 4095`, library `0 .. 1048575` and custom data `-2147483648 .. 2147483647`.

You might want to use those values to uniquely identify your library and branch so that your RFID tags in books won't collide with other libraries.
If you leave decision just to providers of equipment, you might end up with 300000 tags which have plain and simple 0 in those fields. Guess which value will have tags of next library which that provider will have? My guess would be 0 also.

Writing correct numbers in that fields is not enough. If you want to use 3M software, you will also have to setup it to ignore all other tags which doesn't match your library and branch.

^^ security

There is also single byte called AFI or security which can be changed without accessing content of chip. This byte is also readable by more primitive RFID devices like doors to check if book have been checked out from library.

3M is using `0xD7` (215) value for secured items (door will beep) and `0xDA` (218) as unsecured. It seems that all other values are ignored.
(I would guess that other manufacturers are using different values)

As I mentioned before, since we don't have any special values in branch, library or custom field, we have situations in which patron cards get secured when patron walks by checkout counter and 3M software is left in checkout mode.
This triggers door to ring when patron passes which is not ideal.

^^ disable tag

3M software have option to disable tags. Initial examination showed that it's simply programming of tag with following content:

.pre
00	ff 00 00 00
01	00 00 00 00
02	00 00 00 00
03	00 00 00 00
04	00 00 00 00
05	00 00 00 00
06	00 00 00 00
.pre

and security set to `d7` (this might be value from tag before disabling it, I'll have to re-check this)

While 3M software will ignore tags programmed with this content, there is *not permanent disabling of tag* since it can be programmed using other software.

^ RFID reader device

Reader consists of several part:

* black pad - reader antenna
* reader - small box with micro controller and usb port
* software

Reader is recognized as USB serial device with it's own protocol on serial port. We are mostly interested in it's protocol and our ability to use reader and tags with our custom software.

At first, I assumed that protocol with RFID readers is some kind of standard.
After extensive search on Internet I wasn't able to find any documentation about this particular protocol (I even tried to compare it with existing open source implementations just to be sure).

So, only solution was to do clean-room reverse engineering, and using that technique I developed perl module which can talk with RFID reader which is available at http://svn.rot13.org/index.cgi/RFID

After initial reverse engineering of protocol I rewrote support for 3M and CPR reader which is available at https://github.com/dpavlin/Biblio-RFID

^ Related blog posts

{fetchrss: http://mjesec.ffzg.hr/~dpavlin/blog/mt/mt-search.cgi?tag=RFID&Template=feed&IncludeBlogs=1}

^ More information

If this was too geeky for you here is some additional materials:

* "RFID for libraries FAQ"<http://www.bibliotheca-rfid.com/faq>
* "RFID - overview of protocols, librfid implementation and passive sniffing"<http://events.ccc.de/congress/2005/fahrplan/events/769.en.html>

^ ISO standard

* ISO 15962.2004 - object identifier structure
* ISO 15693 - RFID (layer 2)
* ISO 18000 Part 3 Mode 1 - 13.56MHz
* "ISO/IEC JTC1/SC17/WG8"<http://www.incits.org/tc_home/b105htm/b105Doc2003/N03-140-WG8-Work-Project.htm>

^ ISO/IEC 14443, Proximity cards

The Standard series ISO/IEC 14443 consists of 4 parts, which are:

^^ ISO/IEC 14443-1 Physical characteristics

{file: 17n1363t.doc} {file: 17n1363b.doc}

^^ ISO/IEC 14443-2 Radio frequency power and signal interface

{file: 17n1522t.pdf} {file: 17n1522c.doc}

^^ ISO/IEC 14443-2/AMD2 Amendment 2: Bit rates of fc/64, fc/32 and fc/16

{file: 17n2343T.pdf} {file: 17n2343F.doc}

^^ ISO/IEC 14443-3 Initialization and anticollision

{file: 17n1531t.pdf} {file: 17n1531c.doc}

^^ ISO/IEC 14443-3 Amendment 1: Bit rates of fc/64, fc/32 and fc/16

{file: 17n2342T.pdf} {file: 17n2342F.doc}

^^ ISO/IEC 14443-4 Transmission protocol

{file: 17N1689T.pdf} {file: 17n1689c.doc}

^ ISO/IEC 15693, Vicinity cards

^^ ISO/IEC 15693-1 Physical characteristics

{file: 17n1355t.doc} {file: 17n1355b .doc}

^^ ISO/IEC 15693-2 Air interface and initialisation

{file: 17n1486.pdf} {file: 17n1486c.doc}

^^ ISO/IEC 15693-3 Anticollision and transmission protocol

{file: 17n1692t.pdf} {file: 17n1692c.doc}

^ ISO/IEC 10373-6, 10373-7, Test methods for the contactless integrated circuit(s) cards

^^ ISO/IEC 10373-6 Proximity cards

{file: 17n1695t.pdf} {file: 17n1695c.doc}

^^ ISO/IEC 10373-6/AMD1 Amendment 1: Additional PICC test methods

{file: 17n2258t.pdf} {file: 17n2258t.doc} {file: 17n2258C.doc}

^^ ISO/IEC 10373-6/AMD2 Amendment 2: Improved RF test methods

{file: 17n2225t.pdf} {file: 17n2225F.doc}

^^ ISO/IEC 10373-7 Vicinity cards

{file: 17n1697t.pdf} {file: 17n1697c.doc}

^ ISO/IEC 10536, Close-coupled cards

^^ ISO/IEC 10536-1 Physical characteristics

{file: 17n1480t.PDF} {file: 17n1480c.doc}
https://templates.blakadder.com/gosund_SP112_v3_4.html

GPIO #	Component
GPIO00 	Led1i
GPIO01 	None
GPIO02 	Led2i
GPIO03 	None
GPIO04 	HLWBL CF1
GPIO05 	BL0937 CF
GPIO09 	None
GPIO10 	None
GPIO12 	HLWBL SELi
GPIO13 	Relay2i
GPIO14 	Relay1
GPIO15 	None
GPIO16 	None
FLAG 	Button

.pre
{"NAME":"Gosund 112v3.4","GPIO":[56,0,57,0,132,134,0,0,131,30,21,0,0],"FLAG":4,"BASE":18}
.pre

after entering into interface following config is enabled:

.pre
{"NAME":"Gosund 112v3.4","GPIO":[320,0,321,0,2656,2720,0,0,2624,257,224,0,0,4800],"FLAG":0,"BASE":18}
.pre
^ downloads

* http://downloads.redpitaya.com/downloads/
* https://github.com/RedPitaya
* https://github.com/pavel-demin/red-pitaya-notes

^ boot

.pre
dpavlin@nuc:/nuc/RedPitaya$ dd if=red_pitaya_OS-beta.img of=/dev/sdb bs=1M
.pre

^ calibration

http://wiki.redpitaya.com/index.php?title=Analog_frontend_-_Inputs

.pre
root@rp-f04ac9:~# calib -r -v
FE_CH1_FS_G_HI = 49862422
FE_CH2_FS_G_HI = 49836223
FE_CH1_FS_G_LO = 902312499
FE_CH2_FS_G_LO = 897201488
FE_CH1_DC_offs = -176
FE_CH2_DC_offs = -175
BE_CH1_FS = 42812749
BE_CH2_FS = 43173870
BE_CH1_DC_offs = -25
BE_CH2_DC_offs = 9


.pre

---
* DDR ADC interface http://forum.redpitaya.com/viewtopic.php?f=7&t=317
{toc}

[8051] variant

* http://www.stcmcu.com/
* http://openhardware.ro/stc-mcu-software/

^ programming

^^ stcdude

* https://github.com/nekromant/stcdude
* http://ncrmnt.org/wp/tag/stcdude/

^^ stcgal

* https://github.com/grigorig/stcgal

.pre
dpavlin@x200:/rest/cvs/stcgal$ ./stcgal.py 
Waiting for MCU, please cycle power: done
WARNING: Unknown model F51F!
Target model:
  Name: UNKNOWN
  Magic: F51F
  Code flash: 62.0 KB
  EEPROM flash: 0.0 KB
Target frequency: 122.847 MHz
Target BSL version: 7.1T
Target options:
  reset_pin_enabled=False
  low_voltage_detect=True
  oscillator_stable_delay=4096
  power_on_reset_delay=long
  clock_gain=high
  clock_source=internal
  watchdog_por_enabled=False
  watchdog_stop_idle=True
  watchdog_prescale=32
  eeprom_erase_enabled=False
  bsl_pindetect_enabled=True
Disconnected!
.pre

^^ stc-isp

* https://github.com/van9ogh/stc-isp
datasheet: {file: dsm501.pdf}

DMS501A - 2mm pin pitch, DMS501B - 2.54 mm

5V, 90mA

1 minute stabilization after power up

sum time of low (0.7v) for measurement interval, divide by time

^ PINOUT I/O DESCRIPTION

| Pin number | Pin name | Description |
| #1 | Control | Vout 1 control |
| #2 | Vout 2 | Vout 2 output factory calibrated PWM output for density of particles over 1 �m. |
| #3 | Vcc | Positive power supply DC 5V |
| #4 | Vout 1 | Vout 1 output (PWM) |
| #5 | GND | Ground |

{image: dms501-5pins.png}

^^ control pin 1

resistor between pin 1 and ground (square pin on board) to control vout 1 output (pin 4)

| Resistor value | Description |
| open | Preset sensitivity (over 2.5 �m) |
| 47K | Half sensitivity (over 1.75 �m) |
| 18.2K | Equal sensitivity of Vout 2 (over 1 �m) |

^ arduino

* Nice library, but inside repository https://github.com/richardhmm/DIYRepo/tree/master/arduino/libraries/DSM501
* interrupt driven version https://github.com/Sovichea/dsm501-interrupt/

I tried both of them and on my module they don't report sane results when compared with other sensors.

^ platformio

https://primalcortex.wordpress.com/2020/05/23/an-esp8266-air-quality-monitor-based-on-the-dsm501a-dust-sensor/
https://github.com/fcgdam/ESP8266_AirQuality

.pre
dpavlin@nuc:/nuc/esp8266/ESP8266_AirQuality$ git remote -v
origin  https://github.com/fcgdam/ESP8266_AirQuality (fetch)
origin  https://github.com/fcgdam/ESP8266_AirQuality (push)

# edit config
dpavlin@nuc:/nuc/esp8266/ESP8266_AirQuality$ vi src/secrets.h

dpavlin@nuc:/nuc/esp8266/ESP8266_AirQuality$ pio run

dpavlin@nuc:/nuc/esp8266/ESP8266_AirQuality$ pio run -t upload --device-port /dev/ttyUSB2
.pre

Pins:

| Wemos D1 +5V | DSM501a +5V |
| Wemos D1 D6 | DSM501a PM 1.0 pin |
| Wemos D1 D5 | DSM501a PM 2.5 pin< |
| Wemos D1 GND | DSM501a GND pin |

^ description of similar sensor

https://github.com/opendata-stuttgart/meta/blob/master/files/ShinyeiPPD42NS_Deconstruction_TracyAllen.pdf

^ power supply

It really needs quiet power supply to get any readings which are not just noise.

{image: dsm501-schema.png}
^ Speed, hardware crypto

* http://lwn.net/Articles/269075/
From: Gélineau, Samuel - Montreal
Date: Thu, 1 Nov 2007 17:31:54 -0400

----

Hi,

Your svn2cvs testsuite failed on my machine, and I had to fix both the testsuite and the perl script. I assume it must have worked for you the last time you ran your testsuite, and I have no clue why. I`m using CVS 1.12.9.

.pre
 > cd svn2cvs/src
.pre

Running ./test.sh, the first abnormal behaviour I notice is at svn commit 14, "remove everything":

.pre
 ...
 + svn rm $svnco/dir/*
 D /dev/shm/test-svn-co/dir/bar
 D /dev/shm/test-svn-co/dir/baz
 D /dev/shm/test-svn-co/dir/keep
 D /dev/shm/test-svn-co/dir/keep-dir
 D /dev/shm/test-svn-co/dir/l1/bar
 D /dev/shm/test-svn-co/dir/l1/baz
 D /dev/shm/test-svn-co/dir/l1/l2/bar
 D /dev/shm/test-svn-co/dir/l1/l2/baz
 D /dev/shm/test-svn-co/dir/l1/l2/l3/bar
 D /dev/shm/test-svn-co/dir/l1/l2/l3/baz
 D /dev/shm/test-svn-co/dir/l1/l2/l3
 D /dev/shm/test-svn-co/dir/l1/l2
 D /dev/shm/test-svn-co/dir/l1
 D /dev/shm/test-svn-co/dir/skip_add
 D /dev/shm/test-svn-co/dir/with space
 + svn revert $svnco/dir/keep $svnco/dir/keep-dir/keep
 Reverted '/dev/shm/test-svn-co/dir/keep'
 Skipped '/dev/shm/test-svn-co/dir/keep-dir/keep'
 + svn commit -m 'remove everything' $svnco
 Deleting /dev/shm/test-svn-co/dir/bar
 Deleting /dev/shm/test-svn-co/dir/baz
 Deleting /dev/shm/test-svn-co/dir/keep-dir
 Deleting /dev/shm/test-svn-co/dir/l1
 Deleting /dev/shm/test-svn-co/dir/skip_add
 Deleting /dev/shm/test-svn-co/dir/with space

 Committed revision 14.
 ...
.pre

The interesting lines are:

.pre
 Skipped '/dev/shm/test-svn-co/dir/keep-dir/keep'
 ...
 Deleting /dev/shm/test-svn-co/dir/keep-dir
.pre

It`s obvious from the "svn revert" line that you never intended keep-dir to be deleted, yet it does gets deleted. I`m using svn 1.3.1 (r19032).

This time, the fix is in the testsuite itself:

.pre
 --- svn2cvs/src/test.sh 2007-11-01 19:41:19.000000000 +0000
 +++ svn2cvs/src/test.sh 2007-11-01 19:49:37.000000000 +0000
 @@ -145,7 +145,7 @@
 test

 svn rm $svn_co/dir/* || exit
 -svn revert $svn_co/dir/keep $svn_co/dir/keep-dir/keep
 +svn revert $svn_co/dir/keep $svn_co/dir/keep-dir{,/keep}
 svn commit -m "remove everything" $svn_co || exit

 test
.pre

The relevant commit in the new testsuite now runs as follows:

.pre
 ...
 + svn rm $svnco/dir/*
 D /dev/shm/test-svn-co/dir/bar
 D /dev/shm/test-svn-co/dir/baz
 D /dev/shm/test-svn-co/dir/keep
 D /dev/shm/test-svn-co/dir/keep-dir
 D /dev/shm/test-svn-co/dir/l1/bar
 D /dev/shm/test-svn-co/dir/l1/baz
 D /dev/shm/test-svn-co/dir/l1/l2/bar
 D /dev/shm/test-svn-co/dir/l1/l2/baz
 D /dev/shm/test-svn-co/dir/l1/l2/l3/bar
 D /dev/shm/test-svn-co/dir/l1/l2/l3/baz
 D /dev/shm/test-svn-co/dir/l1/l2/l3
 D /dev/shm/test-svn-co/dir/l1/l2
 D /dev/shm/test-svn-co/dir/l1
 D /dev/shm/test-svn-co/dir/skip_add
 D /dev/shm/test-svn-co/dir/with space
 + svn revert $svnco/dir/keep $svnco/dir/keep-dir $svnco/dir/keep-dir/keep
 Reverted '/dev/shm/test-svn-co/dir/keep'
 Reverted '/dev/shm/test-svn-co/dir/keep-dir'
 Skipped '/dev/shm/test-svn-co/dir/keep-dir/keep'
 + svn commit -m 'remove everything' $svnco
 Deleting /dev/shm/test-svn-co/dir/bar
 Deleting /dev/shm/test-svn-co/dir/baz
 Deleting /dev/shm/test-svn-co/dir/l1
 Deleting /dev/shm/test-svn-co/dir/skip_add
 Deleting /dev/shm/test-svn-co/dir/with space

 Committed revision 14.
 ...
.pre

This time, the "skip" is legitimate. The testsuite still fails, though:

.pre
 ...
 + diff -x '.svn*' -x CVS -urw $svnco/dir/ $cvsco/dir/
 Only in /dev/shm/test-cvs-co//dir/: l1
 Only in /dev/shm/test-cvs-co//dir/: with space
 + exit
.pre

It again failed at this problematic last commit, "remove everything":

.pre
 ...
 Starting after revision 13
 ## svn export --force -q -r 14 file:///dev/shm/test-svn-rep//dir /tmp/checkoutGGpuy/dir
 NOTICE: using /dir as directory for svn

 -------------------------------------------------------------------------------
 r 14| gelineaus | 2007-11-01T20:22:39.115442Z

 remove everything
 svn2cvs: D /dir/bar
 #### remove file: bar at ./svn2cvs.pl line 402.
 ## cvs -f -d /dev/shm/test-cvs-rep/ delete 'bar'
 cvs remove: scheduling `bar' for removal
 cvs remove: use `cvs commit' to remove this file permanently
 ## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'bar'
 /dev/shm/test-cvs-rep/dir/bar,v <-- bar
 new revision: delete; previous revision: 1.1
 svn2cvs: D /dir/with space
 WARNING: with space is not present in CVS, skipping...
 svn2cvs: D /dir/baz
 #### remove file: baz at ./svn2cvs.pl line 402.
 ## cvs -f -d /dev/shm/test-cvs-rep/ delete 'baz'
 cvs remove: scheduling `baz' for removal
 cvs remove: use `cvs commit' to remove this file permanently
 ## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'baz'
 /dev/shm/test-cvs-rep/dir/baz,v <-- baz
 new revision: delete; previous revision: 1.1
 svn2cvs: D /dir/l1
 WARNING: l1 is not present in CVS, skipping...
 svn2cvs: D /dir/skip_add
 #### remove file: skip_add at ./svn2cvs.pl line 402.
 ## cvs -f -d /dev/shm/test-cvs-rep/ delete 'skip_add'
 cvs remove: scheduling `skip_add' for removal
 cvs remove: use `cvs commit' to remove this file permanently
 ## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'skip_add'
 /dev/shm/test-cvs-rep/dir/skip_add,v <-- skip_add
 new revision: delete; previous revision: 1.1
 commit ignored, no files
 subversion revision 14 commited to CVS
 /dev/shm/test-cvs-rep/dir/.svnrev,v <-- .svnrev
 new revision: 1.15; previous revision: 1.14
 + update_all
 + update_svn
 + svn update /dev/shm/test-svn-co/
 At revision 14.
 + update_cvs
 + cd /dev/shm/test-cvs-co/
 + cvs -f update -d dir
 cvs update: Updating dir
 U dir/.svnrev
 cvs update: `dir/bar' is no longer in the repository
 cvs update: `dir/baz' is no longer in the repository
 cvs update: `dir/skip_add' is no longer in the repository
 cvs update: Updating dir/keep-dir
 cvs update: Updating dir/l1
 cvs update: Updating dir/l1/l2
 cvs update: Updating dir/l1/l2/l3
 cvs update: Updating dir/with space
 + cd-
 + diff -x '.svn*' -x CVS -urw /dev/shm/test-svn-co//dir/ /dev/shm/test-cvs-co//dir/
 Only in /dev/shm/test-cvs-co//dir/: l1
 Only in /dev/shm/test-cvs-co//dir/: with space
 + exit
.pre

The relevant lines are:

.pre
 ...
 svn2cvs: D /dir/with space
 WARNING: with space is not present in CVS, skipping...
 ...
 svn2cvs: D /dir/l1
 WARNING: l1 is not present in CVS, skipping...
 ...
 Only in /dev/shm/test-cvs-co//dir/: l1
 Only in /dev/shm/test-cvs-co//dir/: with space
 + exit
.pre

In other words, svn2cvs.pl cannot see directories and refuses to remove them. This is because of the in_entries() function, which does not consider lines describing directories. Here`s the fix:

.pre
 --- svn2cvs/src/svn2cvs.pl 2007-11-01 20:21:22.000000000 +0000
 +++ svn2cvs/src/svn2cvs.pl 2007-11-01 20:36:52.000000000 +0000
 @@ -263,6 +263,7 @@ sub in_entries($) {
 			|| return 0; #die "no entries file: $dir/CVS/Entries";
 		while (<$fh>) {
 			return 1 if (m{^/$file/});
 +			return 1 if (m{^D/$file/});
 		}
 		close($fh);
 		return 0;
.pre

But the problematic last commit _still_ fails:

.pre
 Starting after revision 13
 ## svn export --force -q -r 14 file:///dev/shm/test-svn-rep//dir /tmp/checkout1jkCl/dir
 NOTICE: using /dir as directory for svn

 -------------------------------------------------------------------------------
 r 14| gelineaus | 2007-11-01T20:53:32.113268Z

 remove everything
 svn2cvs: D /dir/bar
 #### remove file: bar at ./svn2cvs.pl line 403.
 ## cvs -f -d /dev/shm/test-cvs-rep/ delete 'bar'
 cvs remove: scheduling `bar' for removal
 cvs remove: use `cvs commit' to remove this file permanently
 ## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'bar'
 /dev/shm/test-cvs-rep/dir/bar,v <-- bar
 new revision: delete; previous revision: 1.1
 svn2cvs: D /dir/with space
 #### remove directory: with space at ./svn2cvs.pl line 383.
 #### entries(with space) => at ./svn2cvs.pl line 249.
 ## cvs -f -d /dev/shm/test-cvs-rep/ delete 'with space'
 cvs remove: Removing with space
 ## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'with space'
 cvs commit: Examining with space
 ## cvs -f -d /dev/shm/test-cvs-rep/ update -dP .
 cvs update: Updating .
 cvs update: Updating keep-dir
 cvs update: Updating l1
 cvs update: Updating l1/l2
 cvs update: Updating l1/l2/l3
 cvs update: Updating with space
 svn2cvs: D /dir/baz
 #### remove file: baz at ./svn2cvs.pl line 403.
 ## cvs -f -d /dev/shm/test-cvs-rep/ delete 'baz'
 cvs remove: scheduling `baz' for removal
 cvs remove: use `cvs commit' to remove this file permanently
 ## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'baz'
 /dev/shm/test-cvs-rep/dir/baz,v <-- baz
 new revision: delete; previous revision: 1.1
 svn2cvs: D /dir/l1
 #### remove directory: l1 at ./svn2cvs.pl line 383.
 #### entries recurse into: l1/l2 at ./svn2cvs.pl line 239, <$fh> line 3.
 #### entries recurse into: l1/l2/l3 at ./svn2cvs.pl line 239, <> line 3.
 #### entries(l1/l2/l3) => bar|baz at ./svn2cvs.pl line 249.
 #### entries(l1/l2) => bar|baz|l3/bar|l3/baz|l3 at ./svn2cvs.pl line 249.
 #### entries(l1) => bar|baz|l2/bar|l2/baz|l2/l3/bar|l2/l3/baz|l2/l3|l2 at ./svn2cvs.pl line 249.
 ## cvs -f -d /dev/shm/test-cvs-rep/ delete 'l1/bar'
 cvs remove: scheduling `l1/bar' for removal
 cvs remove: use `cvs commit' to remove this file permanently
 ## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'l1/bar'
 /dev/shm/test-cvs-rep/dir/l1/bar,v <-- bar
 new revision: delete; previous revision: 1.1
 ## cvs -f -d /dev/shm/test-cvs-rep/ delete 'l1/baz'
 cvs remove: scheduling `l1/baz' for removal
 cvs remove: use `cvs commit' to remove this file permanently
 ## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'l1/baz'
 /dev/shm/test-cvs-rep/dir/l1/baz,v <-- baz
 new revision: delete; previous revision: 1.1
 ## cvs -f -d /dev/shm/test-cvs-rep/ delete 'l1/l2/bar'
 cvs remove: scheduling `l1/l2/bar' for removal
 cvs remove: use `cvs commit' to remove this file permanently
 ## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'l1/l2/bar'
 /dev/shm/test-cvs-rep/dir/l1/l2/bar,v <-- bar
 new revision: delete; previous revision: 1.2
 ## cvs -f -d /dev/shm/test-cvs-rep/ delete 'l1/l2/baz'
 cvs remove: scheduling `l1/l2/baz' for removal
 cvs remove: use `cvs commit' to remove this file permanently
 ## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'l1/l2/baz'
 /dev/shm/test-cvs-rep/dir/l1/l2/baz,v <-- baz
 new revision: delete; previous revision: 1.2
 ## cvs -f -d /dev/shm/test-cvs-rep/ delete 'l1/l2/l3/bar'
 cvs remove: scheduling `l1/l2/l3/bar' for removal
 cvs remove: use `cvs commit' to remove this file permanently
 ## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'l1/l2/l3/bar'
 /dev/shm/test-cvs-rep/dir/l1/l2/l3/bar,v <-- bar
 new revision: delete; previous revision: 1.3
 ## cvs -f -d /dev/shm/test-cvs-rep/ delete 'l1/l2/l3/baz'
 cvs remove: scheduling `l1/l2/l3/baz' for removal
 cvs remove: use `cvs commit' to remove this file permanently
 ## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'l1/l2/l3/baz'
 /dev/shm/test-cvs-rep/dir/l1/l2/l3/baz,v <-- baz
 new revision: delete; previous revision: 1.3
 ## cvs -f -d /dev/shm/test-cvs-rep/ delete 'l1/l2/l3'
 cvs remove: Removing l1/l2/l3
 ## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'l1/l2/l3'
 cvs commit: Examining l1/l2/l3
 ## cvs -f -d /dev/shm/test-cvs-rep/ delete 'l1/l2'
 cvs remove: Removing l1/l2
 cvs remove: Removing l1/l2/l3
 ## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'l1/l2'
 cvs commit: Examining l1/l2
 cvs commit: Examining l1/l2/l3
 ## cvs -f -d /dev/shm/test-cvs-rep/ delete 'l1'
 cvs remove: Removing l1
 cvs remove: Removing l1/l2
 cvs remove: Removing l1/l2/l3
 ## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'l1'
 cvs commit: Examining l1
 cvs commit: Examining l1/l2
 cvs commit: Examining l1/l2/l3
 ## cvs -f -d /dev/shm/test-cvs-rep/ update -dP .
 cvs update: Updating .
 cvs update: Updating keep-dir
 cvs update: Updating l1
 cvs update: Updating l1/l2
 cvs update: Updating l1/l2/l3
 cvs update: Updating with space
 svn2cvs: D /dir/skip_add
 #### remove file: skip_add at ./svn2cvs.pl line 403.
 ## cvs -f -d /dev/shm/test-cvs-rep/ delete 'skip_add'
 cvs remove: scheduling `skip_add' for removal
 cvs remove: use `cvs commit' to remove this file permanently
 ## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'skip_add'
 /dev/shm/test-cvs-rep/dir/skip_add,v <-- skip_add
 new revision: delete; previous revision: 1.1
 commit ignored, no files
 subversion revision 14 commited to CVS
 /dev/shm/test-cvs-rep/dir/.svnrev,v <-- .svnrev
 new revision: 1.15; previous revision: 1.14
 + update_all
 + update_svn
 + svn update /dev/shm/test-svn-co/
 At revision 14.
 + update_cvs
 + cd /dev/shm/test-cvs-co/
 + cvs -f update -d dir
 cvs update: Updating dir
 U dir/.svnrev
 cvs update: `dir/bar' is no longer in the repository
 cvs update: `dir/baz' is no longer in the repository
 cvs update: `dir/skip_add' is no longer in the repository
 cvs update: Updating dir/keep-dir
 cvs update: Updating dir/l1
 cvs update: `dir/l1/bar' is no longer in the repository
 cvs update: `dir/l1/baz' is no longer in the repository
 cvs update: Updating dir/l1/l2
 cvs update: `dir/l1/l2/bar' is no longer in the repository
 cvs update: `dir/l1/l2/baz' is no longer in the repository
 cvs update: Updating dir/l1/l2/l3
 cvs update: `dir/l1/l2/l3/bar' is no longer in the repository
 cvs update: `dir/l1/l2/l3/baz' is no longer in the repository
 cvs update: Updating dir/with space
 + cd-
 + diff -x '.svn*' -x CVS -urw /dev/shm/test-svn-co//dir/ /dev/shm/test-cvs-co//dir/
 Only in /dev/shm/test-cvs-co//dir/: l1
 Only in /dev/shm/test-cvs-co//dir/: with space
 + exit
.pre

The relevant lines are:

.pre
 ...
 svn2cvs: D /dir/with space
 ## cvs -f -d /dev/shm/test-cvs-rep/ delete 'with space'
 cvs remove: Removing with space
 ## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'with space'
 ...
 ## cvs -f -d /dev/shm/test-cvs-rep/ delete 'l1'
 cvs remove: Removing l1
 cvs remove: Removing l1/l2
 cvs remove: Removing l1/l2/l3
 ## cvs -f -d /dev/shm/test-cvs-rep/ commit -m 'remove everything' 'l1'
 ...
 Only in /dev/shm/test-cvs-co//dir/: l1
 Only in /dev/shm/test-cvs-co//dir/: with space
 + exit
.pre

Thus cvs was asked to delete the directories, but didn`t. This is no surprise, since CVS was _designed_ not to remove directories. From the CVS manual:

> 7.3 Removing directories

> In concept, removing directories is somewhat similar to removing files--you want the directory to not exist in your current working directories, but you also want to be able to retrieve old releases in which the directory existed.

> The way that you remove a directory is to remove all the files in it. You don't remove the directory itself; there is no way to do that. Instead you specify the '-P' option to cvs update or cvs checkout, which will cause CVS to remove empty directories from working directories. (Note that cvs export always removes empty directories.) Probably the best way to do this is to always specify '-P'; if you want an empty directory then put a dummy file (for example '.keepme') in it to prevent '-P' from removing it.

> Note that '-P' is implied by the '-r' or '-D' options of checkout. This way, CVS will be able to correctly create the directory or not depending on whether the particular version you are checking out contains any files in that directory.

Thus the fix would be to automatically add a ".keepme" file upon directory creation, and to removed it (along with the other files in the directory) upon directory deletion. The testsuite also needs to be updated to use the "-P" flag. Thus, my last patch:

.pre
 diff -r -uprN svn2cvs/src/svn2cvs.pl svn2cvs/src/svn2cvs.pl
 --- svn2cvs/src/svn2cvs.pl 2007-11-01 20:36:52.000000000 +0000
 +++ svn2cvs/src/svn2cvs.pl 2007-11-01 21:06:04.000000000 +0000
 @@ -104,7 +104,8 @@ sub add_dir($$) {
 		next if in_entries($curr_dir);
 		next if ( -e "$curr_dir/CVS" );

 +		log_system( "touch '$curr_dir/.keepme'", "creation of .keepme file (to keep $curr_dir alive in CVS) failed" );
 -		log_system( "$cvs add '$curr_dir'", "cvs add of $curr_dir failed" );
 +		log_system( "$cvs add '$curr_dir' '$curr_dir/.keepme'", "cvs add of $curr_dir failed" );
 	}
 }

 diff -r -uprN svn2cvs/src/test.sh svn2cvs/src/test.sh
 --- svn2cvs/src/test.sh 2007-11-01 20:36:32.000000000 +0000
 +++ svn2cvs/src/test.sh 2007-11-01 21:06:39.000000000 +0000
 @@ -52,13 +52,13 @@ cd- || exit

 rm -Rf $cvs_co || exit
 mkdir $cvs_co || exit
 -cd $cvs_co && cvs -f co dir && cd- || exit
 +cd $cvs_co && cvs -f co -P dir && cd- || exit

 function svn2cvs() {
 	./svn2cvs.pl file://$svn_rep/dir $cvs_rep dir || exit
 }
 function update_cvs() {
 -	cd $cvs_co && cvs -f update -d dir && cd- || exit
 +	cd $cvs_co && cvs -f update -P -d dir && cd- || exit
 }
 function update_svn() {
 	svn update $svn_co || exit
 @@ -70,7 +70,7 @@ function update_all() {
 function test() {
 	svn2cvs
 	update_all
- 	diff -x .svn\* -x CVS -urw $svn_co/dir/ $cvs_co/dir/ || exit
 +	diff -x .svn\* -x CVS -x '\.keep' -urw $svn_co/dir/ $cvs_co/dir/ || exit
 }

 svn2cvs
.pre

And now the problematic test finally passes.

Hoping to be useful,

* Samuel Gélineau

----

This is one of best bug reports I ever received or actually read :-) It seems that "other projects also appriciate bug reports"<http://dev.eclipse.org/mhonarc/lists/aspectj-announce/msg00055.html> like:

* https://bugs.eclipse.org/bugs/show_bug.cgi?id=96111
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=98320
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=98592
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=99168
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=99228
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=100227
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=100260
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=102212
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=102357
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=104024
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=105181
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=106630
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=106634
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=106874
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=107059
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=107858
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=107898
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=108014
* https://bugs.eclipse.org/bugs/show_bug.cgi?id=104046
https://gregdavill.github.io/OrangeCrab/

https://github.com/gregdavill/OrangeCrab

.pre
[Mon Sep 14 13:46:12 2020] usb 2-2.3: new full-speed USB device number 8 using xhci_hcd
[Mon Sep 14 13:46:12 2020] usb 2-2.3: New USB device found, idVendor=1209, idProduct=5af0, bcdDevice= 1.01
[Mon Sep 14 13:46:12 2020] usb 2-2.3: New USB device strings: Mfr=1, Product=2, SerialNumber=0
[Mon Sep 14 13:46:12 2020] usb 2-2.3: Product: OrangeCrab r0.2 DFU Bootloader v3.1
[Mon Sep 14 13:46:12 2020] usb 2-2.3: Manufacturer: GsD

.pre

^ Microwatt with Linux on OrangeCrab

https://codeconstruct.com.au/docs/microwatt-orangecrab/

.pre
⦗OSS CAD Suite⦘ dpavlin@klin:/klin/FPGA/microwatt$ make microwatt.bit 2>&1 | tee ~/tmp/build1.txt

.pre
RD TC66/TC66C Type-C PD trigger USB-C Voltmeter ammeter voltage 2 way current meter multimeter PD charger battery USB Tester

https://www.aliexpress.com/item/32968303350.html

https://sigrok.org/wiki/RDTech_TC66C

https://www.youtube.com/watch?v=rOlhibDUJgs

bluetooth le range is very losy, it's about 30cm so you almost have to put Android phone on top of TC66C to make it work :-(

^ TC66C Reverse Engineering

https://ralimtek.com/reverse%20engineering/software/tc66c-reverse-engineering/

https://github.com/Ralim/TC66C

newer version: https://github.com/Ircama/TC66C

.pre
pi@rpi2 ~/TC66C $ git remote -v
origin  https://github.com/Ircama/TC66C (fetch)
origin  https://github.com/Ircama/TC66C (push)
pi@rpi2 ~/TC66C $ git branch -a
* keyboard_mgmt
  master
  remotes/origin/HEAD -> origin/master
  remotes/origin/keyboard_mgmt
  remotes/origin/master

pi@rpi2 ~/TC66C $ sudo apt install python3-curtsies

pi@rpi2 ~/TC66C $ sudo pip3 install bluepy

pi@rpi2 ~/TC66C $ sudo ./scan.py


.pre