laforge-slides/2017/bbs_early_internet-34c3/bbs_early_internet.html

5436 lines
129 KiB
HTML
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" lang="en" xml:lang="en">
<head>
<title>BBSs and Early Internet Access in Germany</title>
<meta http-equiv="Content-Type" content="application/xhtml+xml; charset=UTF-8" />
<meta name="copyright" content="Copyright &#169; 2017 by Harald Welte (License: CC-BY-SA)" />
<meta name="generator" content="AsciiDoc 8.6.10" />
<style type="text/css">
/* Shared CSS for AsciiDoc xhtml11 and html5 backends */
/* Default font. */
body {
font-family: Georgia,serif;
}
/* Title font. */
h1, h2, h3, h4, h5, h6,
div.title, caption.title,
thead, p.table.header,
#toctitle,
#author, #revnumber, #revdate, #revremark,
#footer {
font-family: Arial,Helvetica,sans-serif;
}
body {
margin: 1em 5% 1em 5%;
}
a {
color: blue;
text-decoration: underline;
}
a:visited {
color: fuchsia;
}
em {
font-style: italic;
color: navy;
}
strong {
font-weight: bold;
color: #083194;
}
h1, h2, h3, h4, h5, h6 {
color: #527bbd;
margin-top: 1.2em;
margin-bottom: 0.5em;
line-height: 1.3;
}
h1, h2, h3 {
border-bottom: 2px solid silver;
}
h2 {
padding-top: 0.5em;
}
h3 {
float: left;
}
h3 + * {
clear: left;
}
h5 {
font-size: 1.0em;
}
div.sectionbody {
margin-left: 0;
}
hr {
border: 1px solid silver;
}
p {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
ul, ol, li > p {
margin-top: 0;
}
ul > li { color: #aaa; }
ul > li > * { color: black; }
.monospaced, code, pre {
font-family: "Courier New", Courier, monospace;
font-size: inherit;
color: navy;
padding: 0;
margin: 0;
}
pre {
white-space: pre-wrap;
}
#author {
color: #527bbd;
font-weight: bold;
font-size: 1.1em;
}
#email {
}
#revnumber, #revdate, #revremark {
}
#footer {
font-size: small;
border-top: 2px solid silver;
padding-top: 0.5em;
margin-top: 4.0em;
}
#footer-text {
float: left;
padding-bottom: 0.5em;
}
#footer-badges {
float: right;
padding-bottom: 0.5em;
}
#preamble {
margin-top: 1.5em;
margin-bottom: 1.5em;
}
div.imageblock, div.exampleblock, div.verseblock,
div.quoteblock, div.literalblock, div.listingblock, div.sidebarblock,
div.admonitionblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
div.admonitionblock {
margin-top: 2.0em;
margin-bottom: 2.0em;
margin-right: 10%;
color: #606060;
}
div.content { /* Block element content. */
padding: 0;
}
/* Block element titles. */
div.title, caption.title {
color: #527bbd;
font-weight: bold;
text-align: left;
margin-top: 1.0em;
margin-bottom: 0.5em;
}
div.title + * {
margin-top: 0;
}
td div.title:first-child {
margin-top: 0.0em;
}
div.content div.title:first-child {
margin-top: 0.0em;
}
div.content + div.title {
margin-top: 0.0em;
}
div.sidebarblock > div.content {
background: #ffffee;
border: 1px solid #dddddd;
border-left: 4px solid #f0f0f0;
padding: 0.5em;
}
div.listingblock > div.content {
border: 1px solid #dddddd;
border-left: 5px solid #f0f0f0;
background: #f8f8f8;
padding: 0.5em;
}
div.quoteblock, div.verseblock {
padding-left: 1.0em;
margin-left: 1.0em;
margin-right: 10%;
border-left: 5px solid #f0f0f0;
color: #888;
}
div.quoteblock > div.attribution {
padding-top: 0.5em;
text-align: right;
}
div.verseblock > pre.content {
font-family: inherit;
font-size: inherit;
}
div.verseblock > div.attribution {
padding-top: 0.75em;
text-align: left;
}
/* DEPRECATED: Pre version 8.2.7 verse style literal block. */
div.verseblock + div.attribution {
text-align: left;
}
div.admonitionblock .icon {
vertical-align: top;
font-size: 1.1em;
font-weight: bold;
text-decoration: underline;
color: #527bbd;
padding-right: 0.5em;
}
div.admonitionblock td.content {
padding-left: 0.5em;
border-left: 3px solid #dddddd;
}
div.exampleblock > div.content {
border-left: 3px solid #dddddd;
padding-left: 0.5em;
}
div.imageblock div.content { padding-left: 0; }
span.image img { border-style: none; vertical-align: text-bottom; }
a.image:visited { color: white; }
dl {
margin-top: 0.8em;
margin-bottom: 0.8em;
}
dt {
margin-top: 0.5em;
margin-bottom: 0;
font-style: normal;
color: navy;
}
dd > *:first-child {
margin-top: 0.1em;
}
ul, ol {
list-style-position: outside;
}
ol.arabic {
list-style-type: decimal;
}
ol.loweralpha {
list-style-type: lower-alpha;
}
ol.upperalpha {
list-style-type: upper-alpha;
}
ol.lowerroman {
list-style-type: lower-roman;
}
ol.upperroman {
list-style-type: upper-roman;
}
div.compact ul, div.compact ol,
div.compact p, div.compact p,
div.compact div, div.compact div {
margin-top: 0.1em;
margin-bottom: 0.1em;
}
tfoot {
font-weight: bold;
}
td > div.verse {
white-space: pre;
}
div.hdlist {
margin-top: 0.8em;
margin-bottom: 0.8em;
}
div.hdlist tr {
padding-bottom: 15px;
}
dt.hdlist1.strong, td.hdlist1.strong {
font-weight: bold;
}
td.hdlist1 {
vertical-align: top;
font-style: normal;
padding-right: 0.8em;
color: navy;
}
td.hdlist2 {
vertical-align: top;
}
div.hdlist.compact tr {
margin: 0;
padding-bottom: 0;
}
.comment {
background: yellow;
}
.footnote, .footnoteref {
font-size: 0.8em;
}
span.footnote, span.footnoteref {
vertical-align: super;
}
#footnotes {
margin: 20px 0 20px 0;
padding: 7px 0 0 0;
}
#footnotes div.footnote {
margin: 0 0 5px 0;
}
#footnotes hr {
border: none;
border-top: 1px solid silver;
height: 1px;
text-align: left;
margin-left: 0;
width: 20%;
min-width: 100px;
}
div.colist td {
padding-right: 0.5em;
padding-bottom: 0.3em;
vertical-align: top;
}
div.colist td img {
margin-top: 0.3em;
}
@media print {
#footer-badges { display: none; }
}
#toc {
margin-bottom: 2.5em;
}
#toctitle {
color: #527bbd;
font-size: 1.1em;
font-weight: bold;
margin-top: 1.0em;
margin-bottom: 0.1em;
}
div.toclevel0, div.toclevel1, div.toclevel2, div.toclevel3, div.toclevel4 {
margin-top: 0;
margin-bottom: 0;
}
div.toclevel2 {
margin-left: 2em;
font-size: 0.9em;
}
div.toclevel3 {
margin-left: 4em;
font-size: 0.9em;
}
div.toclevel4 {
margin-left: 6em;
font-size: 0.9em;
}
span.aqua { color: aqua; }
span.black { color: black; }
span.blue { color: blue; }
span.fuchsia { color: fuchsia; }
span.gray { color: gray; }
span.green { color: green; }
span.lime { color: lime; }
span.maroon { color: maroon; }
span.navy { color: navy; }
span.olive { color: olive; }
span.purple { color: purple; }
span.red { color: red; }
span.silver { color: silver; }
span.teal { color: teal; }
span.white { color: white; }
span.yellow { color: yellow; }
span.aqua-background { background: aqua; }
span.black-background { background: black; }
span.blue-background { background: blue; }
span.fuchsia-background { background: fuchsia; }
span.gray-background { background: gray; }
span.green-background { background: green; }
span.lime-background { background: lime; }
span.maroon-background { background: maroon; }
span.navy-background { background: navy; }
span.olive-background { background: olive; }
span.purple-background { background: purple; }
span.red-background { background: red; }
span.silver-background { background: silver; }
span.teal-background { background: teal; }
span.white-background { background: white; }
span.yellow-background { background: yellow; }
span.big { font-size: 2em; }
span.small { font-size: 0.6em; }
span.underline { text-decoration: underline; }
span.overline { text-decoration: overline; }
span.line-through { text-decoration: line-through; }
div.unbreakable { page-break-inside: avoid; }
/*
* xhtml11 specific
*
* */
div.tableblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
div.tableblock > table {
border: 3px solid #527bbd;
}
thead, p.table.header {
font-weight: bold;
color: #527bbd;
}
p.table {
margin-top: 0;
}
/* Because the table frame attribute is overriden by CSS in most browsers. */
div.tableblock > table[frame="void"] {
border-style: none;
}
div.tableblock > table[frame="hsides"] {
border-left-style: none;
border-right-style: none;
}
div.tableblock > table[frame="vsides"] {
border-top-style: none;
border-bottom-style: none;
}
/*
* html5 specific
*
* */
table.tableblock {
margin-top: 1.0em;
margin-bottom: 1.5em;
}
thead, p.tableblock.header {
font-weight: bold;
color: #527bbd;
}
p.tableblock {
margin-top: 0;
}
table.tableblock {
border-width: 3px;
border-spacing: 0px;
border-style: solid;
border-color: #527bbd;
border-collapse: collapse;
}
th.tableblock, td.tableblock {
border-width: 1px;
padding: 4px;
border-style: solid;
border-color: #527bbd;
}
table.tableblock.frame-topbot {
border-left-style: hidden;
border-right-style: hidden;
}
table.tableblock.frame-sides {
border-top-style: hidden;
border-bottom-style: hidden;
}
table.tableblock.frame-none {
border-style: hidden;
}
th.tableblock.halign-left, td.tableblock.halign-left {
text-align: left;
}
th.tableblock.halign-center, td.tableblock.halign-center {
text-align: center;
}
th.tableblock.halign-right, td.tableblock.halign-right {
text-align: right;
}
th.tableblock.valign-top, td.tableblock.valign-top {
vertical-align: top;
}
th.tableblock.valign-middle, td.tableblock.valign-middle {
vertical-align: middle;
}
th.tableblock.valign-bottom, td.tableblock.valign-bottom {
vertical-align: bottom;
}
/*
* manpage specific
*
* */
body.manpage h1 {
padding-top: 0.5em;
padding-bottom: 0.5em;
border-top: 2px solid silver;
border-bottom: 2px solid silver;
}
body.manpage h2 {
border-style: none;
}
body.manpage div.sectionbody {
margin-left: 3em;
}
@media print {
body.manpage div#toc { display: none; }
}
/* slidy.css
Copyright (c) 2005-2010 W3C (MIT, ERCIM, Keio), All Rights Reserved.
W3C liability, trademark, document use and software licensing
rules apply, see:
http://www.w3.org/Consortium/Legal/copyright-documents
http://www.w3.org/Consortium/Legal/copyright-software
*/
/*
SJR: 2010-09-29: Modified for AsciiDoc slidy backend.
Mostly just commented out stuff that is handled by AsciiDoc's CSS files.
*/
body
{
margin: 0 0 0 0;
padding: 0 0 0 0;
width: 100%;
height: 100%;
color: black;
background-color: white;
/*
font-family: "Gill Sans MT", "Gill Sans", GillSans, sans-serif;
*/
font-size: 14pt;
}
div.toolbar {
position: fixed; z-index: 200;
top: auto; bottom: 0; left: 0; right: 0;
height: 1.2em; text-align: right;
padding-left: 1em;
padding-right: 1em;
font-size: 60%;
color: red;
background-color: rgb(240,240,240);
border-top: solid 1px rgb(180,180,180);
}
div.toolbar span.copyright {
color: black;
margin-left: 0.5em;
}
div.initial_prompt {
position: absolute;
z-index: 1000;
bottom: 1.2em;
width: 90%;
background-color: rgb(200,200,200);
opacity: 0.35;
background-color: rgb(200,200,200, 0.35);
cursor: pointer;
}
div.initial_prompt p.help {
text-align: center;
}
div.initial_prompt p.close {
text-align: right;
font-style: italic;
}
div.slidy_toc {
position: absolute;
z-index: 300;
width: 60%;
max-width: 30em;
height: 30em;
overflow: auto;
top: auto;
right: auto;
left: 4em;
bottom: 4em;
padding: 1em;
background: rgb(240,240,240);
border-style: solid;
border-width: 2px;
font-size: 60%;
}
div.slidy_toc .toc_heading {
text-align: center;
width: 100%;
margin: 0;
margin-bottom: 1em;
border-bottom-style: solid;
border-bottom-color: rgb(180,180,180);
border-bottom-width: 1px;
}
div.slide {
z-index: 20;
margin: 0 0 0 0;
padding-top: 0;
padding-bottom: 0;
padding-left: 20px;
padding-right: 20px;
border-width: 0;
clear: both;
top: 0;
bottom: 0;
left: 0;
right: 0;
line-height: 120%;
background-color: transparent;
}
div.background {
display: none;
}
div.handout {
margin-left: 20px;
margin-right: 20px;
}
div.slide.titlepage {
text-align: center;
}
div.slide.titlepage.h1 {
padding-top: 10%;
}
div.slide h1 {
padding-left: 0;
padding-right: 20pt;
padding-top: 4pt;
padding-bottom: 4pt;
margin-top: 0;
margin-left: 0;
margin-right: 60pt;
margin-bottom: 0.5em;
display: block;
font-size: 160%;
line-height: 1.2em;
background: transparent;
}
div.toc {
position: absolute;
top: auto;
bottom: 4em;
left: 4em;
right: auto;
width: 60%;
max-width: 30em;
height: 30em;
border: solid thin black;
padding: 1em;
background: rgb(240,240,240);
color: black;
z-index: 300;
overflow: auto;
display: block;
visibility: visible;
}
div.toc-heading {
width: 100%;
border-bottom: solid 1px rgb(180,180,180);
margin-bottom: 1em;
text-align: center;
}
/*
pre {
font-size: 80%;
font-weight: bold;
line-height: 120%;
padding-top: 0.2em;
padding-bottom: 0.2em;
padding-left: 1em;
padding-right: 1em;
border-style: solid;
border-left-width: 1em;
border-top-width: thin;
border-right-width: thin;
border-bottom-width: thin;
border-color: #95ABD0;
color: #00428C;
background-color: #E4E5E7;
}
*/
/*
li pre { margin-left: 0; }
blockquote { font-style: italic }
img { background-color: transparent }
p.copyright { font-size: smaller }
*/
.center { text-align: center }
.footnote { font-size: smaller; margin-left: 2em; }
/*
a img { border-width: 0; border-style: none }
*/
a:visited { color: navy }
a:link { color: navy }
a:hover { color: red; text-decoration: underline }
a:active { color: red; text-decoration: underline }
a {text-decoration: none}
.navbar a:link {color: white}
.navbar a:visited {color: yellow}
.navbar a:active {color: red}
.navbar a:hover {color: red}
/*
ul { list-style-type: square; }
ul ul { list-style-type: disc; }
ul ul ul { list-style-type: circle; }
ul ul ul ul { list-style-type: disc; }
li { margin-left: 0.5em; margin-top: 0.5em; }
li li { font-size: 85%; font-style: italic }
li li li { font-size: 85%; font-style: normal }
*/
div dt
{
margin-left: 0;
margin-top: 1em;
margin-bottom: 0.5em;
font-weight: bold;
}
div dd
{
margin-left: 2em;
margin-bottom: 0.5em;
}
/*
p,pre,ul,ol,blockquote,h2,h3,h4,h5,h6,dl,table {
margin-left: 1em;
margin-right: 1em;
}
*/
p.subhead { font-weight: bold; margin-top: 2em; }
.smaller { font-size: smaller }
.bigger { font-size: 130% }
/*
td,th { padding: 0.2em }
*/
ul {
margin: 0.5em 1.5em 0.5em 1.5em;
padding: 0;
}
ol {
margin: 0.5em 1.5em 0.5em 1.5em;
padding: 0;
}
ul { list-style-type: square; }
ul ul { list-style-type: disc; }
ul ul ul { list-style-type: circle; }
ul ul ul ul { list-style-type: disc; }
/*
ul li {
list-style: square;
margin: 0.1em 0em 0.6em 0;
padding: 0 0 0 0;
line-height: 140%;
}
ol li {
margin: 0.1em 0em 0.6em 1.5em;
padding: 0 0 0 0px;
line-height: 140%;
list-style-type: decimal;
}
li ul li {
font-size: 85%;
font-style: italic;
list-style-type: disc;
background: transparent;
padding: 0 0 0 0;
}
li li ul li {
font-size: 85%;
font-style: normal;
list-style-type: circle;
background: transparent;
padding: 0 0 0 0;
}
li li li ul li {
list-style-type: disc;
background: transparent;
padding: 0 0 0 0;
}
li ol li {
list-style-type: decimal;
}
li li ol li {
list-style-type: decimal;
}
*/
/*
setting class="outline" on ol or ul makes it behave as an
ouline list where blocklevel content in li elements is
hidden by default and can be expanded or collapsed with
mouse click. Set class="expand" on li to override default
*/
ol.outline li:hover { cursor: pointer }
ol.outline li.nofold:hover { cursor: default }
ul.outline li:hover { cursor: pointer }
ul.outline li.nofold:hover { cursor: default }
ol.outline { list-style:decimal; }
ol.outline ol { list-style-type:lower-alpha }
ol.outline li.nofold {
padding: 0 0 0 20px;
background: transparent url(../graphics/nofold-dim.gif) no-repeat 0px 0.5em;
}
ol.outline li.unfolded {
padding: 0 0 0 20px;
background: transparent url(../graphics/fold-dim.gif) no-repeat 0px 0.5em;
}
ol.outline li.folded {
padding: 0 0 0 20px;
background: transparent url(../graphics/unfold-dim.gif) no-repeat 0px 0.5em;
}
ol.outline li.unfolded:hover {
padding: 0 0 0 20px;
background: transparent url(../graphics/fold.gif) no-repeat 0px 0.5em;
}
ol.outline li.folded:hover {
padding: 0 0 0 20px;
background: transparent url(../graphics/unfold.gif) no-repeat 0px 0.5em;
}
ul.outline li.nofold {
padding: 0 0 0 20px;
background: transparent url(../graphics/nofold-dim.gif) no-repeat 0px 0.5em;
}
ul.outline li.unfolded {
padding: 0 0 0 20px;
background: transparent url(../graphics/fold-dim.gif) no-repeat 0px 0.5em;
}
ul.outline li.folded {
padding: 0 0 0 20px;
background: transparent url(../graphics/unfold-dim.gif) no-repeat 0px 0.5em;
}
ul.outline li.unfolded:hover {
padding: 0 0 0 20px;
background: transparent url(../graphics/fold.gif) no-repeat 0px 0.5em;
}
ul.outline li.folded:hover {
padding: 0 0 0 20px;
background: transparent url(../graphics/unfold.gif) no-repeat 0px 0.5em;
}
/* for slides with class "title" in table of contents */
a.titleslide { font-weight: bold; font-style: italic }
/*
hide images for work around for save as bug
where browsers fail to save images used by CSS
*/
img.hidden { display: none; visibility: hidden }
div.initial_prompt { display: none; visibility: hidden }
div.slide {
visibility: visible;
position: inherit;
}
div.handout {
border-top-style: solid;
border-top-width: thin;
border-top-color: black;
}
@media screen {
.hidden { display: none; visibility: visible }
div.slide.hidden { display: block; visibility: visible }
div.handout.hidden { display: block; visibility: visible }
div.background { display: none; visibility: hidden }
body.single_slide div.initial_prompt { display: block; visibility: visible }
body.single_slide div.background { display: block; visibility: visible }
body.single_slide div.background.hidden { display: none; visibility: hidden }
body.single_slide .invisible { visibility: hidden }
body.single_slide .hidden { display: none; visibility: hidden }
body.single_slide div.slide { position: absolute }
body.single_slide div.handout { display: none; visibility: hidden }
}
@media print {
.hidden { display: block; visibility: visible }
/*
div.slide pre { font-size: 60%; padding-left: 0.5em; }
*/
div.toolbar { display: none; visibility: hidden; }
div.slidy_toc { display: none; visibility: hidden; }
div.background { display: none; visibility: hidden; }
div.slide { page-break-before: always }
/* :first-child isn't reliable for print media */
div.slide.first-slide { page-break-before: avoid }
}
/* SJR: AsciiDoc slidy backend tweaks */
ol, ul {
margin: 0.8em 1.5em 0.8em 1.8em;
}
li > ul, li > ol {
margin-top: 0.5em;
}
.outline > li.folded,
.outline > li.unfolded {
color: #527bbd;
}
ul > li{ color: #aaa; }
ul > li > *, ol > li > * { color: black; }
li {
margin-top: 0.5em;
margin-bottom: 0.5em;
}
div.change_topic {
display: flex;
align-items: center;
justify-content: center;
}
div.change_topic h1 {
text-align: center;
border-bottom-width: 0px;
}
div.gimmick_right img {
float: right;
}
div.qanda ol {
list-style-type: none;
}
.monospaced, code, pre {
color: black;
font-weight: bold;
}
div.quoteblock, div.verseblock {
color: black;
}
em {
color: black;
}
</style>
<script type="text/javascript">
/*<![CDATA[*/
/* slidy.js
Copyright (c) 2005-2010 W3C (MIT, ERCIM, Keio), All Rights Reserved.
W3C liability, trademark, document use and software licensing
rules apply, see:
http://www.w3.org/Consortium/Legal/copyright-documents
http://www.w3.org/Consortium/Legal/copyright-software
*/
// the slidy object implementation
var w3c_slidy = {
// classify which kind of browser we're running under
ns_pos: (typeof window.pageYOffset!='undefined'),
khtml: ((navigator.userAgent).indexOf("KHTML") >= 0 ? true : false),
opera: ((navigator.userAgent).indexOf("Opera") >= 0 ? true : false),
ipad: ((navigator.userAgent).indexOf("iPad") >= 0 ? true : false),
iphone: ((navigator.userAgent).indexOf("iPhone") >= 0 ? true : false),
ie: (typeof document.all != "undefined" && !this.opera),
ie6: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 6") != -1),
ie7: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 7") != -1),
ie8: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 8") != -1),
ie9: (!this.ns_pos && navigator.userAgent.indexOf("MSIE 9") != -1),
keyboardless: (this.ipad || this.iphone),
// are we running as XHTML? (doesn't work on Opera)
is_xhtml: /xml/.test(document.contentType),
slide_number: 0, // integer slide count: 0, 1, 2, ...
slide_number_element: null, // element containing slide number
slides: [], // set to array of slide div's
notes: [], // set to array of handout div's
backgrounds: [], // set to array of background div's
toolbar: null, // element containing toolbar
title: null, // document title
last_shown: null, // last incrementally shown item
eos: null, // span element for end of slide indicator
toc: null, // table of contents
outline: null, // outline element with the focus
selected_text_len: 0, // length of drag selection on document
view_all: 0, // 1 to view all slides + handouts
want_toolbar: true, // user preference to show/hide toolbar
mouse_click_enabled: true, // enables left click for next slide
scroll_hack: 0, // IE work around for position: fixed
disable_slide_click: false, // used by clicked anchors
lang: "en", // updated to language specified by html file
help_anchor: null, // used for keyboard focus hack in showToolbar()
help_page: "http://www.w3.org/Talks/Tools/Slidy2/help/help.html",
help_text: "Navigate with mouse click, space bar, Cursor Left/Right, " +
"or Pg Up and Pg Dn. Use S and B to change font size.",
size_index: 0,
size_adjustment: 0,
sizes: new Array("10pt", "12pt", "14pt", "16pt", "18pt", "20pt",
"22pt", "24pt", "26pt", "28pt", "30pt", "32pt"),
// needed for efficient resizing
last_width: 0,
last_height: 0,
// Needed for cross browser support for relative width/height on
// object elements. The work around is to save width/height attributes
// and then to recompute absolute width/height dimensions on resizing
objects: [],
// attach initialiation event handlers
set_up: function () {
var init = function() { w3c_slidy.init(); };
if (typeof window.addEventListener != "undefined")
window.addEventListener("load", init, false);
else
window.attachEvent("onload", init);
},
hide_slides: function () {
if (document.body && !w3c_slidy.initialized)
document.body.style.visibility = "hidden";
else
setTimeout(w3c_slidy.hide_slides, 50);
},
// hack to persuade IE to compute correct document height
// as needed for simulating fixed positioning of toolbar
ie_hack: function () {
window.resizeBy(0,-1);
window.resizeBy(0, 1);
},
init: function () {
//alert("slidy starting test 10");
document.body.style.visibility = "visible";
w3c_slidy_i18n.init();
this.add_toolbar();
this.wrap_implicit_slides();
this.collect_slides();
this.collect_notes();
this.collect_backgrounds();
this.objects = document.body.getElementsByTagName("object");
this.patch_anchors();
this.slide_number = this.find_slide_number(location.href);
window.offscreenbuffering = true;
this.size_adjustment = this.find_size_adjust();
this.time_left = this.find_duration();
this.hide_image_toolbar(); // suppress IE image toolbar popup
this.init_outliner(); // activate fold/unfold support
this.title = document.title;
// work around for opera bug
this.is_xhtml = (document.body.tagName == "BODY" ? false : true);
if (this.slides.length > 0)
{
var slide = this.slides[this.slide_number];
if (this.slide_number > 0)
{
this.set_visibility_all_incremental("visible");
this.last_shown = this.previous_incremental_item(null);
this.set_eos_status(true);
}
else
{
this.last_shown = null;
this.set_visibility_all_incremental("hidden");
this.set_eos_status(!this.next_incremental_item(this.last_shown));
}
this.set_location();
this.add_class(this.slides[0], "first-slide");
w3c_slidy.show_slide(slide);
}
this.toc = this.table_of_contents();
this.add_initial_prompt();
// bind event handlers without interfering with custom page scripts
// Tap events behave too weirdly to support clicks reliably on
// iPhone and iPad, so exclude these from click handler
if (!this.keyboardless)
this.add_listener(document.body, "click", this.mouse_button_click);
this.add_listener(document, "keydown", this.key_down);
this.add_listener(document, "keypress", this.key_press);
this.add_listener(window, "resize", this.resized);
this.add_listener(window, "scroll", this.scrolled);
this.add_listener(window, "unload", this.unloaded);
if (!document.body.onclick)
document.body.onclick = function () { };
this.single_slide_view();
//this.set_location();
this.resized();
if (this.ie7)
setTimeout(w3c_slidy.ie_hack, 100);
this.show_toolbar();
// for back button detection
setInterval(function () { w3c_slidy.check_location(); }, 200);
w3c_slidy.initialized = true;
},
// create div element with links to each slide
table_of_contents: function () {
var toc = this.create_element("div");
this.add_class(toc, "slidy_toc hidden");
//toc.setAttribute("tabindex", "0");
var heading = this.create_element("div");
this.add_class(heading, "toc-heading");
heading.innerHTML = "Table of Contents".localize();
toc.appendChild(heading);
var previous = null;
for (var i = 0; i < this.slides.length; ++i)
{
var title = this.has_class(this.slides[i], "title");
var num = document.createTextNode((i + 1) + ". ");
toc.appendChild(num);
var a = this.create_element("a");
a.setAttribute("href", "#(" + (i+1) + ")");
if (title)
this.add_class(a, "titleslide");
var name = document.createTextNode(this.slide_name(i));
a.appendChild(name);
a.onclick = w3c_slidy.toc_click;
a.onkeydown = w3c_slidy.toc_keydown;
a.previous = previous;
if (previous)
previous.next = a;
toc.appendChild(a);
if (i == 0)
toc.first = a;
if (i < this.slides.length - 1)
{
var br = this.create_element("br");
toc.appendChild(br);
}
previous = a;
}
toc.focus = function () {
if (this.first)
this.first.focus();
}
toc.onmouseup = w3c_slidy.mouse_button_up;
toc.onclick = function (e) {
e||(e=window.event);
if (w3c_slidy.selected_text_len <= 0)
w3c_slidy.hide_table_of_contents();
w3c_slidy.stop_propagation(e);
if (e.cancel != undefined)
e.cancel = true;
if (e.returnValue != undefined)
e.returnValue = false;
return false;
};
document.body.insertBefore(toc, document.body.firstChild);
return toc;
},
is_shown_toc: function () {
return !w3c_slidy.has_class(w3c_slidy.toc, "hidden");
},
show_table_of_contents: function () {
w3c_slidy.remove_class(w3c_slidy.toc, "hidden");
var toc = w3c_slidy.toc;
toc.focus();
if (w3c_slidy.ie7 && w3c_slidy.slide_number == 0)
setTimeout(w3c_slidy.ie_hack, 100);
},
hide_table_of_contents: function () {
w3c_slidy.add_class(w3c_slidy.toc, "hidden");
if (!w3c_slidy.opera)
w3c_slidy.help_anchor.focus();
},
toggle_table_of_contents: function () {
if (w3c_slidy.is_shown_toc())
w3c_slidy.hide_table_of_contents();
else
w3c_slidy.show_table_of_contents();
},
// called on clicking toc entry
toc_click: function (e) {
if (!e)
e = window.event;
var target = w3c_slidy.get_target(e);
if (target && target.nodeType == 1)
{
var uri = target.getAttribute("href");
if (uri)
{
//alert("going to " + uri);
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = w3c_slidy.find_slide_number(uri);
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.last_shown = null;
w3c_slidy.set_location();
w3c_slidy.set_visibility_all_incremental("hidden");
w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
w3c_slidy.show_slide(slide);
//target.focus();
try
{
if (!w3c_slidy.opera)
w3c_slidy.help_anchor.focus();
}
catch (e)
{
}
}
}
w3c_slidy.hide_table_of_contents(e);
if (w3c_slidy.ie7) w3c_slidy.ie_hack();
w3c_slidy.stop_propagation(e);
return w3c_slidy.cancel(e);
},
// called onkeydown for toc entry
toc_keydown: function (event) {
var key;
if (!event)
var event = window.event;
// kludge around NS/IE differences
if (window.event)
key = window.event.keyCode;
else if (event.which)
key = event.which;
else
return true; // Yikes! unknown browser
// ignore event if key value is zero
// as for alt on Opera and Konqueror
if (!key)
return true;
// check for concurrent control/command/alt key
// but are these only present on mouse events?
if (event.ctrlKey || event.altKey)
return true;
if (key == 13)
{
var uri = this.getAttribute("href");
if (uri)
{
//alert("going to " + uri);
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = w3c_slidy.find_slide_number(uri);
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.last_shown = null;
w3c_slidy.set_location();
w3c_slidy.set_visibility_all_incremental("hidden");
w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
w3c_slidy.show_slide(slide);
//target.focus();
try
{
if (!w3c_slidy.opera)
w3c_slidy.help_anchor.focus();
}
catch (e)
{
}
}
w3c_slidy.hide_table_of_contents();
if (self.ie7)
w3c_slidy.ie_hack();
return w3c_slidy.cancel(event);
}
if (key == 40 && this.next)
{
this.next.focus();
return w3c_slidy.cancel(event);
}
if (key == 38 && this.previous)
{
this.previous.focus();
return w3c_slidy.cancel(event);
}
return true;
},
// ### OBSOLETE ###
before_print: function () {
this.show_all_slides();
this.hide_toolbar();
alert("before print");
},
// ### OBSOLETE ###
after_print: function () {
if (!this.view_all)
{
this.single_slide_view();
this.show_toolbar();
}
alert("after print");
},
// ### OBSOLETE ###
print_slides: function () {
this.before_print();
window.print();
this.after_print();
},
// ### OBSOLETE ?? ###
toggle_view: function () {
if (this.view_all)
{
this.single_slide_view();
this.show_toolbar();
this.view_all = 0;
}
else
{
this.show_all_slides();
this.hide_toolbar();
this.view_all = 1;
}
},
// prepare for printing ### OBSOLETE ###
show_all_slides: function () {
this.remove_class(document.body, "single_slide");
this.set_visibility_all_incremental("visible");
},
// restore after printing ### OBSOLETE ###
single_slide_view: function () {
this.add_class(document.body, "single_slide");
this.set_visibility_all_incremental("visible");
this.last_shown = this.previous_incremental_item(null);
},
// suppress IE's image toolbar pop up
hide_image_toolbar: function () {
if (!this.ns_pos)
{
var images = document.getElementsByTagName("IMG");
for (var i = 0; i < images.length; ++i)
images[i].setAttribute("galleryimg", "no");
}
},
unloaded: function (e) {
//alert("unloaded");
},
// Safari and Konqueror don't yet support getComputedStyle()
// and they always reload page when location.href is updated
is_KHTML: function () {
var agent = navigator.userAgent;
return (agent.indexOf("KHTML") >= 0 ? true : false);
},
// find slide name from first h1 element
// default to document title + slide number
slide_name: function (index) {
var name = null;
var slide = this.slides[index];
var heading = this.find_heading(slide);
if (heading)
name = this.extract_text(heading);
if (!name)
name = this.title + "(" + (index + 1) + ")";
name.replace(/\&/g, "&amp;");
name.replace(/\</g, "&lt;");
name.replace(/\>/g, "&gt;");
return name;
},
// find first h1 element in DOM tree
find_heading: function (node) {
if (!node || node.nodeType != 1)
return null;
if (node.nodeName == "H1" || node.nodeName == "h1")
return node;
var child = node.firstChild;
while (child)
{
node = this.find_heading(child);
if (node)
return node;
child = child.nextSibling;
}
return null;
},
// recursively extract text from DOM tree
extract_text: function (node) {
if (!node)
return "";
// text nodes
if (node.nodeType == 3)
return node.nodeValue;
// elements
if (node.nodeType == 1)
{
node = node.firstChild;
var text = "";
while (node)
{
text = text + this.extract_text(node);
node = node.nextSibling;
}
return text;
}
return "";
},
// find copyright text from meta element
find_copyright: function () {
var name, content;
var meta = document.getElementsByTagName("meta");
for (var i = 0; i < meta.length; ++i)
{
name = meta[i].getAttribute("name");
content = meta[i].getAttribute("content");
if (name == "copyright")
return content;
}
return null;
},
find_size_adjust: function () {
var name, content, offset;
var meta = document.getElementsByTagName("meta");
for (var i = 0; i < meta.length; ++i)
{
name = meta[i].getAttribute("name");
content = meta[i].getAttribute("content");
if (name == "font-size-adjustment")
return 1 * content;
}
return 1;
},
// <meta name="duration" content="20" /> for 20 minutes
find_duration: function () {
var name, content, offset;
var meta = document.getElementsByTagName("meta");
for (var i = 0; i < meta.length; ++i)
{
name = meta[i].getAttribute("name");
content = meta[i].getAttribute("content");
if (name == "duration")
return 60000 * content;
}
return null;
},
replace_by_non_breaking_space: function (str) {
for (var i = 0; i < str.length; ++i)
str[i] = 160;
},
// ### CHECK ME ### is use of "li" okay for text/html?
// for XHTML do we also need to specify namespace?
init_outliner: function () {
var items = document.getElementsByTagName("li");
for (var i = 0; i < items.length; ++i)
{
var target = items[i];
if (!this.has_class(target.parentNode, "outline"))
continue;
target.onclick = this.outline_click;
/* ### more work needed for IE6
if (!this.ns_pos)
{
target.onmouseover = this.hover_outline;
target.onmouseout = this.unhover_outline;
}
*/
if (this.foldable(target))
{
target.foldable = true;
target.onfocus = function () {w3c_slidy.outline = this;};
target.onblur = function () {w3c_slidy.outline = null;};
if (!target.getAttribute("tabindex"))
target.setAttribute("tabindex", "0");
if (this.has_class(target, "expand"))
this.unfold(target);
else
this.fold(target);
}
else
{
this.add_class(target, "nofold");
target.visible = true;
target.foldable = false;
}
}
},
foldable: function (item) {
if (!item || item.nodeType != 1)
return false;
var node = item.firstChild;
while (node)
{
if (node.nodeType == 1 && this.is_block(node))
return true;
node = node.nextSibling;
}
return false;
},
// ### CHECK ME ### switch to add/remove "hidden" class
fold: function (item) {
if (item)
{
this.remove_class(item, "unfolded");
this.add_class(item, "folded");
}
var node = item ? item.firstChild : null;
while (node)
{
if (node.nodeType == 1 && this.is_block(node)) // element
{
w3c_slidy.add_class(node, "hidden");
}
node = node.nextSibling;
}
item.visible = false;
},
// ### CHECK ME ### switch to add/remove "hidden" class
unfold: function (item) {
if (item)
{
this.add_class(item, "unfolded");
this.remove_class(item, "folded");
}
var node = item ? item.firstChild : null;
while (node)
{
if (node.nodeType == 1 && this.is_block(node)) // element
{
w3c_slidy.remove_class(node, "hidden");
}
node = node.nextSibling;
}
item.visible = true;
},
outline_click: function (e) {
if (!e)
e = window.event;
var rightclick = false;
var target = w3c_slidy.get_target(e);
while (target && target.visible == undefined)
target = target.parentNode;
if (!target)
return true;
if (e.which)
rightclick = (e.which == 3);
else if (e.button)
rightclick = (e.button == 2);
if (!rightclick && target.visible != undefined)
{
if (target.foldable)
{
if (target.visible)
w3c_slidy.fold(target);
else
w3c_slidy.unfold(target);
}
w3c_slidy.stop_propagation(e);
e.cancel = true;
e.returnValue = false;
}
return false;
},
add_initial_prompt: function () {
var prompt = this.create_element("div");
prompt.setAttribute("class", "initial_prompt");
var p1 = this.create_element("p");
prompt.appendChild(p1);
p1.setAttribute("class", "help");
if (this.keyboardless)
p1.innerHTML = "Tap footer to move to next slide";
else
p1.innerHTML = "Space or Right Arrow to move to next " +
"slide, click help below for more details";
this.add_listener(prompt, "click", function (e) {
document.body.removeChild(prompt);
w3c_slidy.stop_propagation(e);
if (e.cancel != undefined)
e.cancel = true;
if (e.returnValue != undefined)
e.returnValue = false;
return false;
});
document.body.appendChild(prompt);
this.initial_prompt = prompt;
setTimeout(function() {document.body.removeChild(prompt);}, 5000);
},
add_toolbar: function () {
var counter, page;
this.toolbar = this.create_element("div");
this.toolbar.setAttribute("class", "toolbar");
// a reasonably behaved browser
if (this.ns_pos || !this.ie6)
{
var right = this.create_element("div");
right.setAttribute("style", "float: right; text-align: right");
counter = this.create_element("span")
counter.innerHTML = "slide".localize() + " n/m";
right.appendChild(counter);
this.toolbar.appendChild(right);
var left = this.create_element("div");
left.setAttribute("style", "text-align: left");
// global end of slide indicator
this.eos = this.create_element("span");
this.eos.innerHTML = "* ";
left.appendChild(this.eos);
var help = this.create_element("a");
help.setAttribute("href", this.help_page);
help.setAttribute("title", this.help_text.localize());
help.innerHTML = "help?".localize();
left.appendChild(help);
this.help_anchor = help; // save for focus hack
var gap1 = document.createTextNode(" ");
left.appendChild(gap1);
var contents = this.create_element("a");
contents.setAttribute("href", "javascript:w3c_slidy.toggle_table_of_contents()");
contents.setAttribute("title", "table of contents".localize());
contents.innerHTML = "contents?".localize();
left.appendChild(contents);
var gap2 = document.createTextNode(" ");
left.appendChild(gap2);
var copyright = this.find_copyright();
if (copyright)
{
var span = this.create_element("span");
span.className = "copyright";
span.innerHTML = copyright;
left.appendChild(span);
}
this.toolbar.setAttribute("tabindex", "0");
this.toolbar.appendChild(left);
}
else // IE6 so need to work around its poor CSS support
{
this.toolbar.style.position = (this.ie7 ? "fixed" : "absolute");
this.toolbar.style.zIndex = "200";
this.toolbar.style.width = "99.9%";
this.toolbar.style.height = "1.2em";
this.toolbar.style.top = "auto";
this.toolbar.style.bottom = "0";
this.toolbar.style.left = "0";
this.toolbar.style.right = "0";
this.toolbar.style.textAlign = "left";
this.toolbar.style.fontSize = "60%";
this.toolbar.style.color = "red";
this.toolbar.borderWidth = 0;
this.toolbar.className = "toolbar";
this.toolbar.style.background = "rgb(240,240,240)";
// would like to have help text left aligned
// and page counter right aligned, floating
// div's don't work, so instead use nested
// absolutely positioned div's.
var sp = this.create_element("span");
sp.innerHTML = "&nbsp;&nbsp;*&nbsp;";
this.toolbar.appendChild(sp);
this.eos = sp; // end of slide indicator
var help = this.create_element("a");
help.setAttribute("href", this.help_page);
help.setAttribute("title", this.help_text.localize());
help.innerHTML = "help?".localize();
this.toolbar.appendChild(help);
this.help_anchor = help; // save for focus hack
var gap1 = document.createTextNode(" ");
this.toolbar.appendChild(gap1);
var contents = this.create_element("a");
contents.setAttribute("href", "javascript:toggleTableOfContents()");
contents.setAttribute("title", "table of contents".localize());
contents.innerHTML = "contents?".localize();
this.toolbar.appendChild(contents);
var gap2 = document.createTextNode(" ");
this.toolbar.appendChild(gap2);
var copyright = this.find_copyright();
if (copyright)
{
var span = this.create_element("span");
span.innerHTML = copyright;
span.style.color = "black";
span.style.marginLeft = "0.5em";
this.toolbar.appendChild(span);
}
counter = this.create_element("div")
counter.style.position = "absolute";
counter.style.width = "auto"; //"20%";
counter.style.height = "1.2em";
counter.style.top = "auto";
counter.style.bottom = 0;
counter.style.right = "0";
counter.style.textAlign = "right";
counter.style.color = "red";
counter.style.background = "rgb(240,240,240)";
counter.innerHTML = "slide".localize() + " n/m";
this.toolbar.appendChild(counter);
}
// ensure that click isn't passed through to the page
this.toolbar.onclick =
function (e) {
if (!e)
e = window.event;
var target = e.target;
if (!target && e.srcElement)
target = e.srcElement;
// work around Safari bug
if (target && target.nodeType == 3)
target = target.parentNode;
w3c_slidy.stop_propagation(e);
if (target && target.nodeName.toLowerCase() != "a")
w3c_slidy.mouse_button_click(e);
};
this.slide_number_element = counter;
this.set_eos_status(false);
document.body.appendChild(this.toolbar);
},
// wysiwyg editors make it hard to use div elements
// e.g. amaya loses the div when you copy and paste
// this function wraps div elements around implicit
// slides which start with an h1 element and continue
// up to the next heading or div element
wrap_implicit_slides: function () {
var i, heading, node, next, div;
var headings = document.getElementsByTagName("h1");
if (!headings)
return;
for (i = 0; i < headings.length; ++i)
{
heading = headings[i];
if (heading.parentNode != document.body)
continue;
node = heading.nextSibling;
div = document.createElement("div");
this.add_class(div, "slide");
document.body.replaceChild(div, heading);
div.appendChild(heading);
while (node)
{
if (node.nodeType == 1 && // an element
(node.nodeName == "H1" ||
node.nodeName == "h1" ||
node.nodeName == "DIV" ||
node.nodeName == "div"))
break;
next = node.nextSibling;
node = document.body.removeChild(node);
div.appendChild(node);
node = next;
}
}
},
// return new array of all slides
collect_slides: function () {
var slides = new Array();
var divs = document.body.getElementsByTagName("div");
for (var i = 0; i < divs.length; ++i)
{
div = divs.item(i);
if (this.has_class(div, "slide"))
{
// add slide to collection
slides[slides.length] = div;
// hide each slide as it is found
this.add_class(div, "hidden");
// add dummy <br/> at end for scrolling hack
var node1 = document.createElement("br");
div.appendChild(node1);
var node2 = document.createElement("br");
div.appendChild(node2);
}
else if (this.has_class(div, "background"))
{ // work around for Firefox SVG reload bug
// which otherwise replaces 1st SVG graphic with 2nd
div.style.display = "block";
}
}
this.slides = slides;
},
// return new array of all <div class="handout">
collect_notes: function () {
var notes = new Array();
var divs = document.body.getElementsByTagName("div");
for (var i = 0; i < divs.length; ++i)
{
div = divs.item(i);
if (this.has_class(div, "handout"))
{
// add note to collection
notes[notes.length] = div;
// and hide it
this.add_class(div, "hidden");
}
}
this.notes = notes;
},
// return new array of all <div class="background">
// including named backgrounds e.g. class="background titlepage"
collect_backgrounds: function () {
var backgrounds = new Array();
var divs = document.body.getElementsByTagName("div");
for (var i = 0; i < divs.length; ++i)
{
div = divs.item(i);
if (this.has_class(div, "background"))
{
// add background to collection
backgrounds[backgrounds.length] = div;
// and hide it
this.add_class(div, "hidden");
}
}
this.backgrounds = backgrounds;
},
// set click handlers on all anchors
patch_anchors: function () {
var self = w3c_slidy;
var handler = function (event) {
// compare this.href with location.href
// for link to another slide in this doc
if (self.page_address(this.href) == self.page_address(location.href))
{
// yes, so find new slide number
var newslidenum = self.find_slide_number(this.href);
if (newslidenum != self.slide_number)
{
var slide = self.slides[self.slide_number];
self.hide_slide(slide);
self.slide_number = newslidenum;
slide = self.slides[self.slide_number];
self.show_slide(slide);
self.set_location();
}
}
else if (this.target == null)
location.href = this.href;
this.blur();
self.disable_slide_click = true;
};
var anchors = document.body.getElementsByTagName("a");
for (var i = 0; i < anchors.length; ++i)
{
if (window.addEventListener)
anchors[i].addEventListener("click", handler, false);
else
anchors[i].attachEvent("onclick", handler);
}
},
// ### CHECK ME ### see which functions are invoked via setTimeout
// either directly or indirectly for use of w3c_slidy vs this
show_slide_number: function () {
var timer = w3c_slidy.get_timer();
w3c_slidy.slide_number_element.innerHTML = timer + "slide".localize() + " " +
(w3c_slidy.slide_number + 1) + "/" + w3c_slidy.slides.length;
},
// every 200mS check if the location has been changed as a
// result of the user activating the Back button/menu item
// doesn't work for Opera < 9.5
check_location: function () {
var hash = location.hash;
if (w3c_slidy.slide_number > 0 && (hash == "" || hash == "#"))
w3c_slidy.goto_slide(0);
else if (hash.length > 2 && hash != "#("+(w3c_slidy.slide_number+1)+")")
{
var num = parseInt(location.hash.substr(2));
if (!isNaN(num))
w3c_slidy.goto_slide(num-1);
}
if (w3c_slidy.time_left && w3c_slidy.slide_number > 0)
{
w3c_slidy.show_slide_number();
if (w3c_slidy.time_left > 0)
w3c_slidy.time_left -= 200;
}
},
get_timer: function () {
var timer = "";
if (w3c_slidy.time_left)
{
var mins, secs;
secs = Math.floor(w3c_slidy.time_left/1000);
mins = Math.floor(secs / 60);
secs = secs % 60;
timer = (mins ? mins+"m" : "") + secs + "s ";
}
return timer;
},
// this doesn't push location onto history stack for IE
// for which a hidden iframe hack is needed: load page into
// the iframe with script that set's parent's location.hash
// but that won't work for standalone use unless we can
// create the page dynamically via a javascript: URL
set_location: function () {
var uri = w3c_slidy.page_address(location.href);
var hash = "#(" + (w3c_slidy.slide_number+1) + ")";
if (w3c_slidy.slide_number >= 0)
uri = uri + hash;
if (w3c_slidy.ie && !w3c_slidy.ie8)
w3c_slidy.push_hash(hash);
if (uri != location.href) // && !khtml
location.href = uri;
if (this.khtml)
hash = "(" + (w3c_slidy.slide_number+1) + ")";
if (!this.ie && location.hash != hash && location.hash != "")
location.hash = hash;
document.title = w3c_slidy.title + " (" + (w3c_slidy.slide_number+1) + ")";
w3c_slidy.show_slide_number();
},
page_address: function (uri) {
var i = uri.indexOf("#");
if (i < 0)
i = uri.indexOf("%23");
// check if anchor is entire page
if (i < 0)
return uri; // yes
return uri.substr(0, i);
},
// only used for IE6 and IE7
on_frame_loaded: function (hash) {
location.hash = hash;
var uri = w3c_slidy.page_address(location.href);
location.href = uri + hash;
},
// history hack with thanks to Bertrand Le Roy
push_hash: function (hash) {
if (hash == "") hash = "#(1)";
window.location.hash = hash;
var doc = document.getElementById("historyFrame").contentWindow.document;
doc.open("javascript:'<html></html>'");
// PWL modified this string literal to break the close script tag
// which otherwise gets parsed when incorporated
doc.write("<html><head><script type=\"text/javascript\">window.parent.w3c_slidy.on_frame_loaded('"+
(hash) + "');</" + "script></head><body>hello mum</body></html>");
doc.close();
},
// find current slide based upon location
// first find target anchor and then look
// for associated div element enclosing it
// finally map that to slide number
find_slide_number: function (uri) {
// first get anchor from page location
var i = uri.indexOf("#");
// check if anchor is entire page
if (i < 0)
return 0; // yes
var anchor = unescape(uri.substr(i+1));
// now use anchor as XML ID to find target
var target = document.getElementById(anchor);
if (!target)
{
// does anchor look like "(2)" for slide 2 ??
// where first slide is (1)
var re = /\((\d)+\)/;
if (anchor.match(re))
{
var num = parseInt(anchor.substring(1, anchor.length-1));
if (num > this.slides.length)
num = 1;
if (--num < 0)
num = 0;
return num;
}
// accept [2] for backwards compatibility
re = /\[(\d)+\]/;
if (anchor.match(re))
{
var num = parseInt(anchor.substring(1, anchor.length-1));
if (num > this.slides.length)
num = 1;
if (--num < 0)
num = 0;
return num;
}
// oh dear unknown anchor
return 0;
}
// search for enclosing slide
while (true)
{
// browser coerces html elements to uppercase!
if (target.nodeName.toLowerCase() == "div" &&
this.has_class(target, "slide"))
{
// found the slide element
break;
}
// otherwise try parent element if any
target = target.parentNode;
if (!target)
{
return 0; // no luck!
}
};
for (i = 0; i < slides.length; ++i)
{
if (slides[i] == target)
return i; // success
}
// oh dear still no luck
return 0;
},
previous_slide: function (incremental) {
if (!w3c_slidy.view_all)
{
var slide;
if ((incremental || w3c_slidy.slide_number == 0) && w3c_slidy.last_shown != null)
{
w3c_slidy.last_shown = w3c_slidy.hide_previous_item(w3c_slidy.last_shown);
w3c_slidy.set_eos_status(false);
}
else if (w3c_slidy.slide_number > 0)
{
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = w3c_slidy.slide_number - 1;
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.set_visibility_all_incremental("visible");
w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null);
w3c_slidy.set_eos_status(true);
w3c_slidy.show_slide(slide);
}
w3c_slidy.set_location();
if (!w3c_slidy.ns_pos)
w3c_slidy.refresh_toolbar(200);
}
},
next_slide: function (incremental) {
if (!w3c_slidy.view_all)
{
var slide, last = w3c_slidy.last_shown;
if (incremental || w3c_slidy.slide_number == w3c_slidy.slides.length - 1)
w3c_slidy.last_shown = w3c_slidy.reveal_next_item(w3c_slidy.last_shown);
if ((!incremental || w3c_slidy.last_shown == null) &&
w3c_slidy.slide_number < w3c_slidy.slides.length - 1)
{
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = w3c_slidy.slide_number + 1;
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.last_shown = null;
w3c_slidy.set_visibility_all_incremental("hidden");
w3c_slidy.show_slide(slide);
}
else if (!w3c_slidy.last_shown)
{
if (last && incremental)
w3c_slidy.last_shown = last;
}
w3c_slidy.set_location();
w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
if (!w3c_slidy.ns_pos)
w3c_slidy.refresh_toolbar(200);
}
},
// to first slide with nothing revealed
// i.e. state at start of presentation
first_slide: function () {
if (!w3c_slidy.view_all)
{
var slide;
if (w3c_slidy.slide_number != 0)
{
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = 0;
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.last_shown = null;
w3c_slidy.set_visibility_all_incremental("hidden");
w3c_slidy.show_slide(slide);
}
w3c_slidy.set_eos_status(
!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
w3c_slidy.set_location();
}
},
// goto last slide with everything revealed
// i.e. state at end of presentation
last_slide: function () {
if (!w3c_slidy.view_all)
{
var slide;
w3c_slidy.last_shown = null; //revealNextItem(lastShown);
if (w3c_slidy.last_shown == null &&
w3c_slidy.slide_number < w3c_slidy.slides.length - 1)
{
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = w3c_slidy.slides.length - 1;
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.set_visibility_all_incremental("visible");
w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null);
w3c_slidy.show_slide(slide);
}
else
{
w3c_slidy.set_visibility_all_incremental("visible");
w3c_slidy.last_shown = w3c_slidy.previous_incremental_item(null);
}
w3c_slidy.set_eos_status(true);
w3c_slidy.set_location();
}
},
// ### check this and consider add/remove class
set_eos_status: function (state) {
if (this.eos)
this.eos.style.color = (state ? "rgb(240,240,240)" : "red");
},
// first slide is 0
goto_slide: function (num) {
//alert("going to slide " + (num+1));
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.slide_number = num;
slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.last_shown = null;
w3c_slidy.set_visibility_all_incremental("hidden");
w3c_slidy.set_eos_status(!w3c_slidy.next_incremental_item(w3c_slidy.last_shown));
document.title = w3c_slidy.title + " (" + (w3c_slidy.slide_number+1) + ")";
w3c_slidy.show_slide(slide);
w3c_slidy.show_slide_number();
},
show_slide: function (slide) {
this.sync_background(slide);
window.scrollTo(0,0);
this.remove_class(slide, "hidden");
},
hide_slide: function (slide) {
this.add_class(slide, "hidden");
},
// show just the backgrounds pertinent to this slide
// when slide background-color is transparent
// this should now work with rgba color values
sync_background: function (slide) {
var background;
var bgColor;
if (slide.currentStyle)
bgColor = slide.currentStyle["backgroundColor"];
else if (document.defaultView)
{
var styles = document.defaultView.getComputedStyle(slide,null);
if (styles)
bgColor = styles.getPropertyValue("background-color");
else // broken implementation probably due Safari or Konqueror
{
//alert("defective implementation of getComputedStyle()");
bgColor = "transparent";
}
}
else
bgColor == "transparent";
if (bgColor == "transparent" ||
bgColor.indexOf("rgba") >= 0 ||
bgColor.indexOf("opacity") >= 0)
{
var slideClass = this.get_class_list(slide);
for (var i = 0; i < this.backgrounds.length; i++)
{
background = this.backgrounds[i];
var bgClass = this.get_class_list(background);
if (this.matching_background(slideClass, bgClass))
this.remove_class(background, "hidden");
else
this.add_class(background, "hidden");
}
}
else // forcibly hide all backgrounds
this.hide_backgrounds();
},
hide_backgrounds: function () {
for (var i = 0; i < this.backgrounds.length; i++)
{
background = this.backgrounds[i];
this.add_class(background, "hidden");
}
},
// compare classes for slide and background
matching_background: function (slideClass, bgClass) {
var i, count, pattern, result;
// define pattern as regular expression
pattern = /\w+/g;
// check background class names
result = bgClass.match(pattern);
for (i = count = 0; i < result.length; i++)
{
if (result[i] == "hidden")
continue;
if (result[i] == "background")
continue;
++count;
}
if (count == 0) // default match
return true;
// check for matches and place result in array
result = slideClass.match(pattern);
// now check if desired name is present for background
for (i = count = 0; i < result.length; i++)
{
if (result[i] == "hidden")
continue;
if (this.has_token(bgClass, result[i]))
return true;
}
return false;
},
resized: function () {
var width = 0;
if ( typeof( window.innerWidth ) == 'number' )
width = window.innerWidth; // Non IE browser
else if (document.documentElement && document.documentElement.clientWidth)
width = document.documentElement.clientWidth; // IE6
else if (document.body && document.body.clientWidth)
width = document.body.clientWidth; // IE4
var height = 0;
if ( typeof( window.innerHeight ) == 'number' )
height = window.innerHeight; // Non IE browser
else if (document.documentElement && document.documentElement.clientHeight)
height = document.documentElement.clientHeight; // IE6
else if (document.body && document.body.clientHeight)
height = document.body.clientHeight; // IE4
if (height && (width/height > 1.05*1024/768))
{
width = height * 1024.0/768;
}
// IE fires onresize even when only font size is changed!
// so we do a check to avoid blocking < and > actions
if (width != w3c_slidy.last_width || height != w3c_slidy.last_height)
{
if (width >= 1100)
w3c_slidy.size_index = 5; // 4
else if (width >= 1000)
w3c_slidy.size_index = 4; // 3
else if (width >= 800)
w3c_slidy.size_index = 3; // 2
else if (width >= 600)
w3c_slidy.size_index = 2; // 1
else if (width)
w3c_slidy.size_index = 0;
// add in font size adjustment from meta element e.g.
// <meta name="font-size-adjustment" content="-2" />
// useful when slides have too much content ;-)
if (0 <= w3c_slidy.size_index + w3c_slidy.size_adjustment &&
w3c_slidy.size_index + w3c_slidy.size_adjustment < w3c_slidy.sizes.length)
w3c_slidy.size_index = w3c_slidy.size_index + w3c_slidy.size_adjustment;
// enables cross browser use of relative width/height
// on object elements for use with SVG and Flash media
w3c_slidy.adjust_object_dimensions(width, height);
if (document.body.style.fontSize != w3c_slidy.sizes[w3c_slidy.size_index])
{
document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index];
}
w3c_slidy.last_width = width;
w3c_slidy.last_height = height;
// force reflow to work around Mozilla bug
if (w3c_slidy.ns_pos)
{
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.show_slide(slide);
}
// force correct positioning of toolbar
w3c_slidy.refresh_toolbar(200);
}
},
scrolled: function () {
if (w3c_slidy.toolbar && !w3c_slidy.ns_pos && !w3c_slidy.ie7)
{
w3c_slidy.hack_offset = w3c_slidy.scroll_x_offset();
// hide toolbar
w3c_slidy.toolbar.style.display = "none";
// make it reappear later
if (w3c_slidy.scrollhack == 0 && !w3c_slidy.view_all)
{
setTimeout(function () {w3c_slidy.show_toolbar(); }, 1000);
w3c_slidy.scrollhack = 1;
}
}
},
hide_toolbar: function () {
w3c_slidy.add_class(w3c_slidy.toolbar, "hidden");
window.focus();
},
// used to ensure IE refreshes toolbar in correct position
refresh_toolbar: function (interval) {
if (!w3c_slidy.ns_pos && !w3c_slidy.ie7)
{
w3c_slidy.hide_toolbar();
setTimeout(function () {w3c_slidy.show_toolbar(); }, interval);
}
},
// restores toolbar after short delay
show_toolbar: function () {
if (w3c_slidy.want_toolbar)
{
w3c_slidy.toolbar.style.display = "block";
if (!w3c_slidy.ns_pos)
{
// adjust position to allow for scrolling
var xoffset = w3c_slidy.scroll_x_offset();
w3c_slidy.toolbar.style.left = xoffset;
w3c_slidy.toolbar.style.right = xoffset;
// determine vertical scroll offset
//var yoffset = scrollYOffset();
// bottom is doc height - window height - scroll offset
//var bottom = documentHeight() - lastHeight - yoffset
//if (yoffset > 0 || documentHeight() > lastHeight)
// bottom += 16; // allow for height of scrollbar
w3c_slidy.toolbar.style.bottom = 0; //bottom;
}
w3c_slidy.remove_class(w3c_slidy.toolbar, "hidden");
}
w3c_slidy.scrollhack = 0;
// set the keyboard focus to the help link on the
// toolbar to ensure that document has the focus
// IE doesn't always work with window.focus()
// and this hack has benefit of Enter for help
try
{
if (!w3c_slidy.opera)
w3c_slidy.help_anchor.focus();
}
catch (e)
{
}
},
// invoked via F key
toggle_toolbar: function () {
if (!w3c_slidy.view_all)
{
if (w3c_slidy.has_class(w3c_slidy.toolbar, "hidden"))
{
w3c_slidy.remove_class(w3c_slidy.toolbar, "hidden")
w3c_slidy.want_toolbar = 1;
}
else
{
w3c_slidy.add_class(w3c_slidy.toolbar, "hidden")
w3c_slidy.want_toolbar = 0;
}
}
},
scroll_x_offset: function () {
if (window.pageXOffset)
return self.pageXOffset;
if (document.documentElement &&
document.documentElement.scrollLeft)
return document.documentElement.scrollLeft;
if (document.body)
return document.body.scrollLeft;
return 0;
},
scroll_y_offset: function () {
if (window.pageYOffset)
return self.pageYOffset;
if (document.documentElement &&
document.documentElement.scrollTop)
return document.documentElement.scrollTop;
if (document.body)
return document.body.scrollTop;
return 0;
},
// looking for a way to determine height of slide content
// the slide itself is set to the height of the window
optimize_font_size: function () {
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
//var dh = documentHeight(); //getDocHeight(document);
var dh = slide.scrollHeight;
var wh = getWindowHeight();
var u = 100 * dh / wh;
alert("window utilization = " + u + "% (doc "
+ dh + " win " + wh + ")");
},
// from document object
get_doc_height: function (doc) {
if (!doc)
doc = document;
if (doc && doc.body && doc.body.offsetHeight)
return doc.body.offsetHeight; // ns/gecko syntax
if (doc && doc.body && doc.body.scrollHeight)
return doc.body.scrollHeight;
alert("couldn't determine document height");
},
get_window_height: function () {
if ( typeof( window.innerHeight ) == 'number' )
return window.innerHeight; // Non IE browser
if (document.documentElement && document.documentElement.clientHeight)
return document.documentElement.clientHeight; // IE6
if (document.body && document.body.clientHeight)
return document.body.clientHeight; // IE4
},
document_height: function () {
var sh, oh;
sh = document.body.scrollHeight;
oh = document.body.offsetHeight;
if (sh && oh)
{
return (sh > oh ? sh : oh);
}
// no idea!
return 0;
},
smaller: function () {
if (w3c_slidy.size_index > 0)
{
--w3c_slidy.size_index;
}
w3c_slidy.toolbar.style.display = "none";
document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index];
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.show_slide(slide);
setTimeout(function () {w3c_slidy.show_toolbar(); }, 50);
},
bigger: function () {
if (w3c_slidy.size_index < w3c_slidy.sizes.length - 1)
{
++w3c_slidy.size_index;
}
w3c_slidy.toolbar.style.display = "none";
document.body.style.fontSize = w3c_slidy.sizes[w3c_slidy.size_index];
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
w3c_slidy.hide_slide(slide);
w3c_slidy.show_slide(slide);
setTimeout(function () {w3c_slidy.show_toolbar(); }, 50);
},
// enables cross browser use of relative width/height
// on object elements for use with SVG and Flash media
// with thanks to Ivan Herman for the suggestion
adjust_object_dimensions: function (width, height) {
for( var i = 0; i < w3c_slidy.objects.length; i++ )
{
var obj = this.objects[i];
var mimeType = obj.getAttribute("type");
if (mimeType == "image/svg+xml" || mimeType == "application/x-shockwave-flash")
{
if ( !obj.initialWidth )
obj.initialWidth = obj.getAttribute("width");
if ( !obj.initialHeight )
obj.initialHeight = obj.getAttribute("height");
if ( obj.initialWidth && obj.initialWidth.charAt(obj.initialWidth.length-1) == "%" )
{
var w = parseInt(obj.initialWidth.slice(0, obj.initialWidth.length-1));
var newW = width * (w/100.0);
obj.setAttribute("width",newW);
}
if ( obj.initialHeight &&
obj.initialHeight.charAt(obj.initialHeight.length-1) == "%" )
{
var h = parseInt(obj.initialHeight.slice(0, obj.initialHeight.length-1));
var newH = height * (h/100.0);
obj.setAttribute("height", newH);
}
}
}
},
// needed for Opera to inhibit default behavior
// since Opera delivers keyPress even if keyDown
// was cancelled
key_press: function (event) {
if (!event)
event = window.event;
if (!w3c_slidy.key_wanted)
return w3c_slidy.cancel(event);
return true;
},
// See e.g. http://www.quirksmode.org/js/events/keys.html for keycodes
key_down: function (event) {
var key;
w3c_slidy.key_wanted = true;
if (!event)
event = window.event;
// kludge around NS/IE differences
if (window.event)
key = window.event.keyCode;
else if (event.which)
key = event.which;
else
return true; // Yikes! unknown browser
// ignore event if key value is zero
// as for alt on Opera and Konqueror
if (!key)
return true;
// check for concurrent control/command/alt key
// but are these only present on mouse events?
if (event.ctrlKey || event.altKey || event.metaKey)
return true;
// dismiss table of contents if visible
if (w3c_slidy.is_shown_toc() && key != 9 && key != 16 && key != 38 && key != 40)
{
w3c_slidy.hide_table_of_contents();
if (key == 27 || key == 84 || key == 67)
return w3c_slidy.cancel(event);
}
if (key == 34) // Page Down
{
if (w3c_slidy.view_all)
return true;
w3c_slidy.next_slide(false);
return w3c_slidy.cancel(event);
}
else if (key == 33) // Page Up
{
if (w3c_slidy.view_all)
return true;
w3c_slidy.previous_slide(false);
return w3c_slidy.cancel(event);
}
else if (key == 32) // space bar
{
w3c_slidy.next_slide(true);
return w3c_slidy.cancel(event);
}
else if (key == 37) // Left arrow
{
w3c_slidy.previous_slide(!event.shiftKey);
return w3c_slidy.cancel(event);
}
else if (key == 36) // Home
{
w3c_slidy.first_slide();
return w3c_slidy.cancel(event);
}
else if (key == 35) // End
{
w3c_slidy.last_slide();
return w3c_slidy.cancel(event);
}
else if (key == 39) // Right arrow
{
w3c_slidy.next_slide(!event.shiftKey);
return w3c_slidy.cancel(event);
}
else if (key == 13) // Enter
{
if (w3c_slidy.outline)
{
if (w3c_slidy.outline.visible)
w3c_slidy.fold(w3c_slidy.outline);
else
w3c_slidy.unfold(w3c_slidy.outline);
return w3c_slidy.cancel(event);
}
}
else if (key == 188) // < for smaller fonts
{
w3c_slidy.smaller();
return w3c_slidy.cancel(event);
}
else if (key == 190) // > for larger fonts
{
w3c_slidy.bigger();
return w3c_slidy.cancel(event);
}
else if (key == 189 || key == 109) // - for smaller fonts
{
w3c_slidy.smaller();
return w3c_slidy.cancel(event);
}
else if (key == 187 || key == 191 || key == 107) // = + for larger fonts
{
w3c_slidy.bigger();
return w3c_slidy.cancel(event);
}
else if (key == 83) // S for smaller fonts
{
w3c_slidy.smaller();
return w3c_slidy.cancel(event);
}
else if (key == 66) // B for larger fonts
{
w3c_slidy.bigger();
return w3c_slidy.cancel(event);
}
else if (key == 90) // Z for last slide
{
w3c_slidy.last_slide();
return w3c_slidy.cancel(event);
}
else if (key == 70) // F for toggle toolbar
{
w3c_slidy.toggle_toolbar();
return w3c_slidy.cancel(event);
}
else if (key == 65) // A for toggle view single/all slides
{
w3c_slidy.toggle_view();
return w3c_slidy.cancel(event);
}
else if (key == 75) // toggle action of left click for next page
{
w3c_slidy.mouse_click_enabled = !w3c_slidy.mouse_click_enabled;
var alert_msg = (w3c_slidy.mouse_click_enabled ?
"enabled" : "disabled") + " mouse click advance";
alert(alert_msg.localize());
return w3c_slidy.cancel(event);
}
else if (key == 84 || key == 67) // T or C for table of contents
{
if (w3c_slidy.toc)
w3c_slidy.toggle_table_of_contents();
return w3c_slidy.cancel(event);
}
else if (key == 72) // H for help
{
window.location = w3c_slidy.help_page;
return w3c_slidy.cancel(event);
}
//else alert("key code is "+ key);
return true;
},
// safe for both text/html and application/xhtml+xml
create_element: function (name) {
if (this.xhtml && (typeof document.createElementNS != 'undefined'))
return document.createElementNS("http://www.w3.org/1999/xhtml", name)
return document.createElement(name);
},
get_element_style: function (elem, IEStyleProp, CSSStyleProp) {
if (elem.currentStyle)
{
return elem.currentStyle[IEStyleProp];
}
else if (window.getComputedStyle)
{
var compStyle = window.getComputedStyle(elem, "");
return compStyle.getPropertyValue(CSSStyleProp);
}
return "";
},
// the string str is a whitespace separated list of tokens
// test if str contains a particular token, e.g. "slide"
has_token: function (str, token) {
if (str)
{
// define pattern as regular expression
var pattern = /\w+/g;
// check for matches
// place result in array
var result = str.match(pattern);
// now check if desired token is present
for (var i = 0; i < result.length; i++)
{
if (result[i] == token)
return true;
}
}
return false;
},
get_class_list: function (element) {
if (typeof element.className != 'undefined')
return element.className;
return element.getAttribute("class");
},
has_class: function (element, name) {
if (element.nodeType != 1)
return false;
var regexp = new RegExp("(^| )" + name + "\W*");
if (typeof element.className != 'undefined')
return regexp.test(element.className);
return regexp.test(element.getAttribute("class"));
},
remove_class: function (element, name) {
var regexp = new RegExp("(^| )" + name + "\W*");
var clsval = "";
if (typeof element.className != 'undefined')
{
clsval = element.className;
if (clsval)
{
clsval = clsval.replace(regexp, "");
element.className = clsval;
}
}
else
{
clsval = element.getAttribute("class");
if (clsval)
{
clsval = clsval.replace(regexp, "");
element.setAttribute("class", clsval);
}
}
},
add_class: function (element, name) {
if (!this.has_class(element, name))
{
if (typeof element.className != 'undefined')
element.className += " " + name;
else
{
var clsval = element.getAttribute("class");
clsval = clsval ? clsval + " " + name : name;
element.setAttribute("class", clsval);
}
}
},
// HTML elements that can be used with class="incremental"
// note that you can also put the class on containers like
// up, ol, dl, and div to make their contents appear
// incrementally. Upper case is used since this is what
// browsers report for HTML node names (text/html).
incremental_elements: null,
okay_for_incremental: function (name) {
if (!this.incremental_elements)
{
var inclist = new Array();
inclist["p"] = true;
inclist["pre"] = true;
inclist["li"] = true;
inclist["blockquote"] = true;
inclist["dt"] = true;
inclist["dd"] = true;
inclist["h2"] = true;
inclist["h3"] = true;
inclist["h4"] = true;
inclist["h5"] = true;
inclist["h6"] = true;
inclist["span"] = true;
inclist["address"] = true;
inclist["table"] = true;
inclist["tr"] = true;
inclist["th"] = true;
inclist["td"] = true;
inclist["img"] = true;
inclist["object"] = true;
this.incremental_elements = inclist;
}
return this.incremental_elements[name.toLowerCase()];
},
next_incremental_item: function (node) {
var br = this.is_xhtml ? "br" : "BR";
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
for (;;)
{
node = w3c_slidy.next_node(slide, node);
if (node == null || node.parentNode == null)
break;
if (node.nodeType == 1) // ELEMENT
{
if (node.nodeName == br)
continue;
if (w3c_slidy.has_class(node, "incremental")
&& w3c_slidy.okay_for_incremental(node.nodeName))
return node;
if (w3c_slidy.has_class(node.parentNode, "incremental")
&& !w3c_slidy.has_class(node, "non-incremental"))
return node;
}
}
return node;
},
previous_incremental_item: function (node) {
var br = this.is_xhtml ? "br" : "BR";
var slide = w3c_slidy.slides[w3c_slidy.slide_number];
for (;;)
{
node = w3c_slidy.previous_node(slide, node);
if (node == null || node.parentNode == null)
break;
if (node.nodeType == 1)
{
if (node.nodeName == br)
continue;
if (w3c_slidy.has_class(node, "incremental")
&& w3c_slidy.okay_for_incremental(node.nodeName))
return node;
if (w3c_slidy.has_class(node.parentNode, "incremental")
&& !w3c_slidy.has_class(node, "non-incremental"))
return node;
}
}
return node;
},
// set visibility for all elements on current slide with
// a parent element with attribute class="incremental"
set_visibility_all_incremental: function (value) {
var node = this.next_incremental_item(null);
if (value == "hidden")
{
while (node)
{
w3c_slidy.add_class(node, "invisible");
node = w3c_slidy.next_incremental_item(node);
}
}
else // value == "visible"
{
while (node)
{
w3c_slidy.remove_class(node, "invisible");
node = w3c_slidy.next_incremental_item(node);
}
}
},
// reveal the next hidden item on the slide
// node is null or the node that was last revealed
reveal_next_item: function (node) {
node = w3c_slidy.next_incremental_item(node);
if (node && node.nodeType == 1) // an element
w3c_slidy.remove_class(node, "invisible");
return node;
},
// exact inverse of revealNextItem(node)
hide_previous_item: function (node) {
if (node && node.nodeType == 1) // an element
w3c_slidy.add_class(node, "invisible");
return this.previous_incremental_item(node);
},
// left to right traversal of root's content
next_node: function (root, node) {
if (node == null)
return root.firstChild;
if (node.firstChild)
return node.firstChild;
if (node.nextSibling)
return node.nextSibling;
for (;;)
{
node = node.parentNode;
if (!node || node == root)
break;
if (node && node.nextSibling)
return node.nextSibling;
}
return null;
},
// right to left traversal of root's content
previous_node: function (root, node) {
if (node == null)
{
node = root.lastChild;
if (node)
{
while (node.lastChild)
node = node.lastChild;
}
return node;
}
if (node.previousSibling)
{
node = node.previousSibling;
while (node.lastChild)
node = node.lastChild;
return node;
}
if (node.parentNode != root)
return node.parentNode;
return null;
},
previous_sibling_element: function (el) {
el = el.previousSibling;
while (el && el.nodeType != 1)
el = el.previousSibling;
return el;
},
next_sibling_element: function (el) {
el = el.nextSibling;
while (el && el.nodeType != 1)
el = el.nextSibling;
return el;
},
first_child_element: function (el) {
var node;
for (node = el.firstChild; node; node = node.nextSibling)
{
if (node.nodeType == 1)
break;
}
return node;
},
first_tag: function (element, tag) {
var node;
if (!this.is_xhtml)
tag = tag.toUpperCase();
for (node = element.firstChild; node; node = node.nextSibling)
{
if (node.nodeType == 1 && node.nodeName == tag)
break;
}
return node;
},
hide_selection: function () {
if (window.getSelection) // Firefox, Chromium, Safari, Opera
{
var selection = window.getSelection();
if (selection.rangeCount > 0)
{
var range = selection.getRangeAt(0);
range.collapse (false);
}
}
else // Internet Explorer
{
var textRange = document.selection.createRange ();
textRange.collapse (false);
}
},
get_selected_text: function () {
try
{
if (window.getSelection)
return window.getSelection().toString();
if (document.getSelection)
return document.getSelection().toString();
if (document.selection)
return document.selection.createRange().text;
}
catch (e)
{
}
return "";
},
// make note of length of selected text
// as this evaluates to zero in click event
mouse_button_up: function (e) {
w3c_slidy.selected_text_len = w3c_slidy.get_selected_text().length;
},
// right mouse button click is reserved for context menus
// it is more reliable to detect rightclick than leftclick
mouse_button_click: function (e) {
var rightclick = false;
var leftclick = false;
var middleclick = false;
var target;
if (!e)
var e = window.event;
if (e.target)
target = e.target;
else if (e.srcElement)
target = e.srcElement;
// work around Safari bug
if (target.nodeType == 3)
target = target.parentNode;
if (e.which) // all browsers except IE
{
leftclick = (e.which == 1);
middleclick = (e.which == 2);
rightclick = (e.which == 3);
}
else if (e.button)
{
// Konqueror gives 1 for left, 4 for middle
// IE6 gives 0 for left and not 1 as I expected
if (e.button == 4)
middleclick = true;
// all browsers agree on 2 for right button
rightclick = (e.button == 2);
}
else leftclick = true;
/*
alert("you clicked over a " + target.nodeName + " element\n" +
"w3c_slidy.mouse_click_enabled = " + w3c_slidy.mouse_click_enabled + "\n" +
"leftclick = " + leftclick + "\n" +
"selected text length = " + w3c_slidy.selected_text_len);
//alert("selected text length = " + w3c_slidy.selected_text_len);
*/
if (w3c_slidy.selected_text_len > 0)
{
w3c_slidy.stop_propagation(e);
e.cancel = true;
e.returnValue = false;
return false;
}
// dismiss table of contents
w3c_slidy.hide_table_of_contents();
// check if target is something that probably want's clicks
// e.g. a, embed, object, input, textarea, select, option
var tag = target.nodeName.toLowerCase();
if (w3c_slidy.mouse_click_enabled && leftclick &&
tag != "a" &&
tag != "embed" &&
tag != "object" &&
tag != "video" &&
tag != "input" &&
tag != "textarea" &&
tag != "select" &&
tag != "option" &&
!target.onclick)
{
w3c_slidy.next_slide(true);
w3c_slidy.stop_propagation(e);
e.cancel = true;
e.returnValue = false;
return false;
}
},
get_key: function (e)
{
var key;
// kludge around NS/IE differences
if (typeof window.event != "undefined")
key = window.event.keyCode;
else if (e.which)
key = e.which;
return key;
},
get_target: function (e) {
var target;
if (!e)
e = window.event;
if (e.target)
target = e.target;
else if (e.srcElement)
target = e.srcElement;
if (target.nodeType != 1)
target = target.parentNode;
return target;
},
// does display property provide correct defaults?
is_block: function (elem) {
var tag = elem.nodeName.toLowerCase();
return tag == "ol" || tag == "ul" || tag == "p" ||
tag == "li" || tag == "table" || tag == "pre" ||
tag == "h1" || tag == "h2" || tag == "h3" ||
tag == "h4" || tag == "h5" || tag == "h6" ||
tag == "blockquote" || tag == "address";
},
add_listener: function (element, event, handler) {
if (window.addEventListener)
element.addEventListener(event, handler, false);
else
element.attachEvent("on"+event, handler);
},
// used to prevent event propagation from field controls
stop_propagation: function (event) {
event = event ? event : window.event;
event.cancelBubble = true; // for IE
if (event.stopPropagation)
event.stopPropagation();
return true;
},
cancel: function (event) {
if (event)
{
event.cancel = true;
event.returnValue = false;
if (event.preventDefault)
event.preventDefault();
}
w3c_slidy.key_wanted = false;
return false;
}
};
// for each language define an associative array
// and also the help text which is longer
var w3c_slidy_i18n = {
strings_es: {
"slide":"pág.",
"help?":"Ayuda",
"contents?":"Índice",
"table of contents":"tabla de contenidos",
"Table of Contents":"Tabla de Contenidos",
"restart presentation":"Reiniciar presentación",
"restart?":"Inicio"
},
help_es:
"Utilice el ratón, barra espaciadora, teclas Izda/Dcha, " +
"o Re pág y Av pág. Use S y B para cambiar el tamaño de fuente.",
strings_ca: {
"slide":"pàg..",
"help?":"Ajuda",
"contents?":"Índex",
"table of contents":"taula de continguts",
"Table of Contents":"Taula de Continguts",
"restart presentation":"Reiniciar presentació",
"restart?":"Inici"
},
help_ca:
"Utilitzi el ratolí, barra espaiadora, tecles Esq./Dta. " +
"o Re pàg y Av pàg. Usi S i B per canviar grandària de font.",
strings_cs: {
"slide":"snímek",
"help?":"nápověda",
"contents?":"obsah",
"table of contents":"obsah prezentace",
"Table of Contents":"Obsah prezentace",
"restart presentation":"znovu spustit prezentaci",
"restart?":"restart"
},
help_cs:
"Prezentaci můžete procházet pomocí kliknutí myši, mezerníku, " +
"šipek vlevo a vpravo nebo kláves PageUp a PageDown. Písmo se " +
"dá zvětšit a zmenšit pomocí kláves B a S.",
strings_nl: {
"slide":"pagina",
"help?":"Help?",
"contents?":"Inhoud?",
"table of contents":"inhoudsopgave",
"Table of Contents":"Inhoudsopgave",
"restart presentation":"herstart presentatie",
"restart?":"Herstart?"
},
help_nl:
"Navigeer d.m.v. het muis, spatiebar, Links/Rechts toetsen, " +
"of PgUp en PgDn. Gebruik S en B om de karaktergrootte te veranderen.",
strings_de: {
"slide":"Seite",
"help?":"Hilfe",
"contents?":"Übersicht",
"table of contents":"Inhaltsverzeichnis",
"Table of Contents":"Inhaltsverzeichnis",
"restart presentation":"Präsentation neu starten",
"restart?":"Neustart"
},
help_de:
"Benutzen Sie die Maus, Leerschlag, die Cursortasten links/rechts oder " +
"Page up/Page Down zum Wechseln der Seiten und S und B für die Schriftgrösse.",
strings_pl: {
"slide":"slajd",
"help?":"pomoc?",
"contents?":"spis treści?",
"table of contents":"spis treści",
"Table of Contents":"Spis Treści",
"restart presentation":"Restartuj prezentację",
"restart?":"restart?"
},
help_pl:
"Zmieniaj slajdy klikając myszą, naciskając spację, strzałki lewo/prawo" +
"lub PgUp / PgDn. Użyj klawiszy S i B, aby zmienić rozmiar czczionki.",
strings_fr: {
"slide":"page",
"help?":"Aide",
"contents?":"Index",
"table of contents":"table des matières",
"Table of Contents":"Table des matières",
"restart presentation":"Recommencer l'exposé",
"restart?":"Début"
},
help_fr:
"Naviguez avec la souris, la barre d'espace, les flèches " +
"gauche/droite ou les touches Pg Up, Pg Dn. Utilisez " +
"les touches S et B pour modifier la taille de la police.",
strings_hu: {
"slide":"oldal",
"help?":"segítség",
"contents?":"tartalom",
"table of contents":"tartalomjegyzék",
"Table of Contents":"Tartalomjegyzék",
"restart presentation":"bemutató újraindítása",
"restart?":"újraindítás"
},
help_hu:
"Az oldalak közti lépkedéshez kattintson az egérrel, vagy " +
"használja a szóköz, a bal, vagy a jobb nyíl, illetve a Page Down, " +
"Page Up billentyűket. Az S és a B billentyűkkel változtathatja " +
"a szöveg méretét.",
strings_it: {
"slide":"pag.",
"help?":"Aiuto",
"contents?":"Indice",
"table of contents":"indice",
"Table of Contents":"Indice",
"restart presentation":"Ricominciare la presentazione",
"restart?":"Inizio"
},
help_it:
"Navigare con mouse, barra spazio, frecce sinistra/destra o " +
"PgUp e PgDn. Usare S e B per cambiare la dimensione dei caratteri.",
strings_el: {
"slide":"σελίδα",
"help?":"βοήθεια;",
"contents?":"περιεχόμενα;",
"table of contents":"πίνακας περιεχομένων",
"Table of Contents":"Πίνακας Περιεχομένων",
"restart presentation":"επανεκκίνηση παρουσίασης",
"restart?":"επανεκκίνηση;"
},
help_el:
"Πλοηγηθείτε με το κλίκ του ποντικιού, το space, τα βέλη αριστερά/δεξιά, " +
"ή Page Up και Page Down. Χρησιμοποιήστε τα πλήκτρα S και B για να αλλάξετε " +
"το μέγεθος της γραμματοσειράς.",
strings_ja: {
"slide":"スライド",
"help?":"ヘルプ",
"contents?":"目次",
"table of contents":"目次を表示",
"Table of Contents":"目次",
"restart presentation":"最初から再生",
"restart?":"最初から"
},
help_ja:
"マウス左クリック ・ スペース ・ 左右キー " +
"または Page Up ・ Page Downで操作 S ・ Bでフォントサイズ変更",
strings_zh: {
"slide":"幻灯片",
"help?":"帮助?",
"contents?":"内容?",
"table of contents":"目录",
"Table of Contents":"目录",
"restart presentation":"重新启动展示",
"restart?":"重新启动?"
},
help_zh:
"用鼠标点击, 空格条, 左右箭头, Pg Up 和 Pg Dn 导航. " +
"用 S, B 改变字体大小.",
strings_ru: {
"slide":"слайд",
"help?":"помощь?",
"contents?":"содержание?",
"table of contents":"оглавление",
"Table of Contents":"Оглавление",
"restart presentation":"перезапустить презентацию",
"restart?":"перезапуск?"
},
help_ru:
"Перемещайтесь кликая мышкой, используя клавишу пробел, стрелки" +
"влево/вправо или Pg Up и Pg Dn. Клавиши S и B меняют размер шрифта.",
strings_sv: {
"slide":"sida",
"help?":"hjälp",
"contents?":"innehåll",
"table of contents":"innehållsförteckning",
"Table of Contents":"Innehållsförteckning",
"restart presentation":"visa presentationen från början",
"restart?":"börja om"
},
help_sv:
"Bläddra med ett klick med vänstra musknappen, mellanslagstangenten, " +
"vänster- och högerpiltangenterna eller tangenterna Pg Up, Pg Dn. " +
"Använd tangenterna S och B för att ändra textens storlek.",
// each such language array is declared in the localize array
// which is set on string prototype and used as in "foo".localize();
localize: {
"es":this.strings_es,
"ca":this.strings_ca,
"cs":this.strings_cs,
"nl":this.strings_nl,
"de":this.strings_de,
"pl":this.strings_pl,
"fr":this.strings_fr,
"hu":this.strings_hu,
"it":this.strings_it,
"el":this.strings_el,
"jp":this.strings_ja,
"zh":this.strings_zh,
"ru":this.strings_ru,
"sv":this.strings_sv
},
init: function () {
var i18n = w3c_slidy_i18n;
var help_text = w3c_slidy.help_text;
i18n.strings_es[help_text] = i18n.help_es;
i18n.strings_ca[help_text] = i18n.help_ca;
i18n.strings_cs[help_text] = i18n.help_cs;
i18n.strings_nl[help_text] = i18n.help_nl;
i18n.strings_de[help_text] = i18n.help_de;
i18n.strings_pl[help_text] = i18n.help_pl;
i18n.strings_fr[help_text] = i18n.help_fr;
i18n.strings_hu[help_text] = i18n.help_hu;
i18n.strings_it[help_text] = i18n.help_it;
i18n.strings_el[help_text] = i18n.help_el;
i18n.strings_ja[help_text] = i18n.help_ja;
i18n.strings_zh[help_text] = i18n.help_zh;
i18n.strings_ru[help_text] = i18n.help_ru;
i18n.strings_sv[help_text] = i18n.help_sv;
w3c_slidy.lang = document.body.parentNode.getAttribute("lang");
if (!w3c_slidy.lang)
w3c_slidy.lang = document.body.parentNode.getAttribute("xml:lang");
if (!w3c_slidy.lang)
w3c_slidy.lang = "en";
// add localize method to all strings
// for use as in "contents".localize()
String.prototype.localize = function() {
if (this == "")
return this;
// try full language code, e.g. en-US
var s, lookup = w3c_slidy_i18n.localize[w3c_slidy.lang];
if (lookup)
{
s = lookup[this];
if (s)
return s;
}
// strip country code suffix, e.g.
// try en if undefined for en-US
var lg = w3c_slidy.lang.split("-");
if (lg.length > 1)
{
lookup = w3c_slidy_i18n.localize[lg[0]];
if (lookup)
{
s = lookup[this];
if (s)
return s;
}
}
// otherwise string as is
return this;
};
}
};
// hack for back button behavior
if (w3c_slidy.ie6 || w3c_slidy.ie7)
{
document.write("<iframe id='historyFrame' " +
"src='javascript:\"<html"+"></"+"html>\"' " +
"height='1' width='1' " +
"style='position:absolute;left:-800px'></iframe>");
}
// attach event listeners for initialization
w3c_slidy.set_up();
// hide the slides as soon as body element is available
// to reduce annoying screen mess before the onload event
setTimeout(w3c_slidy.hide_slides, 50);
/*]]>*/
</script>
</head>
<body class="article" style="max-width:45em">
<div id="header" class="slide">
<h1>BBSs and Early Internet Access in Germany</h1>
<span id="author">Harald Welte &lt;laforge@gnumonks.org&gt;</span><br />
</div>
<div class="sect1 slide">
<h1 id="_introduction">Introduction</h1>
<div class="sectionbody" style="max-width:45em">
<ul class=" incremental">
<li>
<span>
this is not a high-tech talk
</span>
</li>
<li>
<span>
way fewer acronyms than in mots of my other talks
</span>
</li>
<li>
<span>
I didn&#8217;t invent any of the technologies covered
</span>
</li>
<li>
<span>
I didn&#8217;t write any of the software covered
</span>
</li>
<li>
<span>
Just a mere user and operator/sysadming
</span>
</li>
<li>
<span>
.. this is the world I grew up in (age 11 onwards)
</span>
</li>
<li>
<span>
very limited information available in literature and on the WWW
</span>
</li>
<li>
<span>
lots of younger members of our community lack this history
</span>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_circuit_switched_telephony">Circuit Switched Telephony</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
Telephony from 1876 until ~ 1988
</span>
</li>
<li>
<span>
Analog voice circuit 300-3000 Hz
</span>
</li>
<li>
<span>
Dial-up connection between A and B party
</span>
</li>
<li>
<span>
Copper wires physically switched at intermediate telephone exchange
</span>
</li>
<li>
<span>
Voice signal possibly amplified in the path
</span>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_hardware">Hardware</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
Telephone
</span>
</li>
<li>
<span>
Copper wire[s]
</span>
</li>
<li>
<span>
Telephone Exchange[s]
</span>
</li>
</ul>
<div class="paragraph"><p><span class="image">
<img src="images/pots_fig10.2.png" alt="images/pots_fig10.2.png" width="80%" />
</span></p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_phone_charges">Phone Charges</h1>
<div class="sectionbody" style="max-width:45em">
<div class="paragraph"><p>In Germany during the 80ies and 90ies</p></div>
<ul class="">
<li>
<span>
even local calls were metered / charged
</span>
</li>
<li>
<span>
flat rates didn&#8217;t exist
</span>
</li>
<li>
<span>
various zones between local and long distance
</span>
</li>
<li>
<span>
not many people could afford long distance BBSing
</span>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_acoustic_coupler">Acoustic Coupler</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
First devices to transmit bits as audible tones over telephone
</span>
</li>
<li>
<span>
User manually dialled phone number like voice call
</span>
</li>
<li>
<span>
After call was established, both sides put receiver into coupler
</span>
</li>
</ul>
<div class="paragraph"><p><span class="image">
<img src="images/accoustic_coupler.jpg" alt="images/accoustic_coupler.jpg" width="60%" />
</span></p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_modems">Modems</h1>
<div class="sectionbody" style="max-width:45em">
<div class="paragraph"><p>Automation of the acoustic coupler</p></div>
<ul class="">
<li>
<span>
Avoid <em>air gap</em> speaker/microphone path
</span>
</li>
<li>
<span>
directly generate/receive tones on phone line
</span>
</li>
<li>
<span>
directly dial the phone number / answer the line
</span>
</li>
</ul>
<div class="paragraph"><p><span class="image">
<img src="images/analogm.png" alt="images/analogm.png" width="80%" />
</span></p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_modems_2">Modems</h1>
<div class="sectionbody" style="max-width:45em">
<div class="paragraph"><p><span class="image">
<img src="images/Modems.jpg" alt="images/Modems.jpg" width="50%" />
</span></p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_modem_speeds_standards">Modem Speeds / Standards</h1>
<div class="sectionbody" style="max-width:45em">
<div class="tableblock">
<table rules="all"
width="50%"
frame="border"
cellspacing="0" cellpadding="4">
<col width="33%" />
<col width="33%" />
<col width="33%" />
<thead>
<tr>
<th align="left" valign="top">Standard</th>
<th align="left" valign="top">Rate (bps)</th>
<th align="left" valign="top">Year created</th>
</tr>
</thead>
<tbody>
<tr>
<td align="left" valign="top"><p class="table">V.21</p></td>
<td align="left" valign="top"><p class="table">300</p></td>
<td align="left" valign="top"><p class="table">1962*</p></td>
</tr>
<tr>
<td align="left" valign="top"><p class="table">V.22</p></td>
<td align="left" valign="top"><p class="table">1200</p></td>
<td align="left" valign="top"><p class="table">1980*</p></td>
</tr>
<tr>
<td align="left" valign="top"><p class="table">V.22bis</p></td>
<td align="left" valign="top"><p class="table">2400</p></td>
<td align="left" valign="top"><p class="table">1984*</p></td>
</tr>
<tr>
<td align="left" valign="top"><p class="table">V.32</p></td>
<td align="left" valign="top"><p class="table">9600</p></td>
<td align="left" valign="top"><p class="table">1984*</p></td>
</tr>
<tr>
<td align="left" valign="top"><p class="table">V.32bis</p></td>
<td align="left" valign="top"><p class="table">14400</p></td>
<td align="left" valign="top"><p class="table">1991</p></td>
</tr>
<tr>
<td align="left" valign="top"><p class="table">V.32ter</p></td>
<td align="left" valign="top"><p class="table">19200</p></td>
<td align="left" valign="top"><p class="table">1993</p></td>
</tr>
<tr>
<td align="left" valign="top"><p class="table">V.34</p></td>
<td align="left" valign="top"><p class="table">28000</p></td>
<td align="left" valign="top"><p class="table">1994</p></td>
</tr>
<tr>
<td align="left" valign="top"><p class="table">V.34bis</p></td>
<td align="left" valign="top"><p class="table">33600</p></td>
<td align="left" valign="top"><p class="table">1996</p></td>
</tr>
<tr>
<td align="left" valign="top"><p class="table">V.90</p></td>
<td align="left" valign="top"><p class="table">56000</p></td>
<td align="left" valign="top"><p class="table">1998</p></td>
</tr>
</tbody>
</table>
</div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_bbss">BBSs</h1>
<div class="sectionbody" style="max-width:45em">
<div class="paragraph"><p>What&#8217;s a BBS?</p></div>
<ul class="">
<li>
<span>
Computer with Modem accepting incoming calls
</span>
</li>
<li>
<span>
offering interactive service to users who dial in
</span>
</li>
</ul>
<div class="paragraph"><p>To operate a BBS, you had to have</p></div>
<ul class="">
<li>
<span>
a separate/dedicated computer
</span>
<ul class="">
<li>
<span>
most BBS software predated/predates multi-tasking OSs
</span>
</li>
</ul>
</li>
<li>
<span>
running 24/7
</span>
</li>
<li>
<span>
attached to separate / dedicated phone line
</span>
</li>
</ul>
<div class="paragraph"><p>To use a BBS, you</p></div>
<ul class="">
<li>
<span>
power your computer when using it
</span>
</li>
<li>
<span>
can share your regular phone line with the modem
</span>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_content">Content</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
bulletin boards / message boards
</span>
</li>
<li>
<span>
live chat with sysop (or other users in multi-line BBS)
</span>
</li>
<li>
<span>
multi-user games (text based!)
</span>
</li>
<li>
<span>
file areas / downloads
</span>
</li>
<li>
<span>
ASCII / ANSI artwork
</span>
</li>
</ul>
<div class="paragraph"><p><span class="image">
<img src="images/dosbox-telemate-login.png" alt="images/dosbox-telemate-login.png" width="50%" />
</span></p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_technology_software">Technology/Software</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
Both sides: Computer + Modem
</span>
</li>
<li>
<span>
BBS Side Software
</span>
<ul class="">
<li>
<span>
BBS Software
</span>
</li>
<li>
<span>
often extended by "doors" (external programs, think of CGI in Web)
</span>
</li>
</ul>
</li>
<li>
<span>
User Side Software
</span>
<ul class="">
<li>
<span>
Terminal Program (e.g. TELIX, Telemate for DOS)
</span>
</li>
</ul>
</li>
</ul>
<div class="paragraph"><p><span class="image">
<img src="images/telemate.jpg" alt="images/telemate.jpg" width="50%" />
</span></p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_demo">Demo</h1>
<div class="sectionbody" style="max-width:45em">
<div class="paragraph"><p>Time for a demo</p></div>
<div class="admonitionblock">
<table><tr>
<td class="icon">
<div class="title">Note</div>
</td>
<td class="content">I&#8217;m using telnet instead of modem/dialup (POTS lines hard to find these days)</td>
</tr></table>
</div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_the_bbs_protocol_stack">The "BBS Protocol Stack"</h1>
<div class="sectionbody" style="max-width:45em">
<div class="paragraph"><p>In the spirit of protocol stack diagrams&#8230;</p></div>
<div class="paragraph"><p><span class="image">
<img src="images/bbs-protocol_stack.svg" alt="images/bbs-protocol_stack.svg" width="80%" />
</span></p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_curiosity_vector_graphics">Curiosity: Vector Graphics</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
BBSs were typically all Text, mostly ANSI CP437 charset
</span>
</li>
<li>
<span>
RIP (Remote Imaging Protocol) / RIPscrip introduced vector graphics
</span>
<ul class="">
<li>
<span>
RIPscrip introduced in 1992 (by TeleGrafix)
</span>
<ul class="">
<li>
<span>
Commands like &#8220;!|w00001B0M10&#8221; to draw vector graphics over Modem
</span>
</li>
</ul>
</li>
<li>
<span>
RIPterm as terminal program for EGA (640x350)
</span>
</li>
</ul>
</li>
</ul>
<div class="paragraph"><p><span class="image">
<img src="images/Nouveau.png" alt="images/Nouveau.png" />
</span></p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_isolated_bbss">Isolated BBSs</h1>
<div class="sectionbody" style="max-width:45em">
<div class="paragraph"><p>To participate in bulletin/message boards</p></div>
<ul class="">
<li>
<span>
Users log in at different times
</span>
</li>
<li>
<span>
BBS is busy while a user is logged in
</span>
</li>
<li>
<span>
Multiple modems / phone lines is one (expensive) option to scale
</span>
</li>
<li>
<span>
Time limit per User (minutes/day) often used
</span>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_points_offline_messages">Points / Offline Messages</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
Users don&#8217;t read/write interactively during active modem call
</span>
</li>
<li>
<span>
Messages get written offline and compressed/batched during short call
</span>
</li>
</ul>
<div class="paragraph"><p>Advantages:</p></div>
<ul class="">
<li>
<span>
lower cost (shorter phone calls, metered!)
</span>
</li>
<li>
<span>
shorter connection per user
</span>
</li>
<li>
<span>
BBS can scale to more users this way
</span>
</li>
</ul>
<div class="paragraph"><p><span class="image">
<img src="images/xpmenu.gif" alt="images/xpmenu.gif" width="60%" />
</span></p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_bbs_networks_store_forward">BBS networks (store + forward)</h1>
<div class="sectionbody" style="max-width:45em">
<div class="paragraph"><p>As opposed to individual BBSs with isolated communities&#8230;</p></div>
<div class="paragraph"><p>Idea: Replicate bulletin / message boards between independent BBSs, for</p></div>
<ul class="">
<li>
<span>
scalability in number of users
</span>
</li>
<li>
<span>
scalability in geographic scope
</span>
<ul class="">
<li>
<span>
most users will prefer least-expensive local calls to long-distance
</span>
</li>
</ul>
</li>
<li>
<span>
efficient transport over long distance due to routing/forwarding of compressed batches
</span>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_bbs_network_technology_examples">BBS network technology (examples)</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
FIDO (Netmail + Echomail)
</span>
<ul class="">
<li>
<span>
Othernets like TrekNet, GerNet using same FTN technology
</span>
</li>
</ul>
</li>
<li>
<span>
Z-Netz (Mail + News)
</span>
<ul class="">
<li>
<span>
T-Netz, CL-Netz
</span>
</li>
</ul>
</li>
<li>
<span>
UUCP (Usenet Mail + News)
</span>
<ul class="">
<li>
<span>
Often only way to access "Internet" before IP access was available
</span>
</li>
</ul>
</li>
<li>
<span>
MausNet - Münster Apple User Service
</span>
<ul class="">
<li>
<span>
used by up to 120 BBSs in DE / AT / CH
</span>
</li>
</ul>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_example_fidonet">Example: FIDOnet</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
Starts in 1984 with two BBSs
</span>
</li>
<li>
<span>
Initial technological limit of 250 nodes reached in 1985
</span>
</li>
<li>
<span>
Hierarchic, Regional routing/Addressing introduced in 1986
</span>
<ul class="">
<li>
<span>
<em>Nodelist</em> defines all nodes of the network + hierarchy
</span>
</li>
</ul>
</li>
<li>
<span>
Addresses like <strong>Harald Welte @ 2:2490/1343</strong>
</span>
</li>
<li>
<span>
Up to 39,000 nodes in 1996, estimated 2 Million users world-wide
</span>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_example_z_netz">Example: Z-Netz</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
Started as Zerberus-Netz implemented in Zerberus Software
</span>
</li>
<li>
<span>
Later renamed to Z-Netz as the ZConnect protocol was implemented in other software
</span>
<ul class="">
<li>
<span>
Standards defined based on perceived complexity of RFCs and Usenet/UUCP
</span>
</li>
</ul>
</li>
<li>
<span>
CrossPoint (DOS) most popular point software for ZConnect
</span>
</li>
<li>
<span>
Addresses like <strong>H.WELTE@SILVER</strong>, later <strong>H.WELTE@SILVER.zer</strong>
</span>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_example_usenet">Example: UseNet</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
Established in 1980 in the US
</span>
</li>
<li>
<span>
Uses UUCP (Unix-to-Unix-Copy) as transport mechanism over Modems
</span>
<ul class="">
<li>
<span>
UUCP was created in the 1970ies and used to copy files, including Internet Mail
</span>
</li>
</ul>
</li>
<li>
<span>
Usenet News format (RFC850) designed very similar to Internet Mail (RFC822)
</span>
</li>
<li>
<span>
Hierarchy of News Groups that gets replicated / flooded across the network, e.g.
</span>
<ul class="">
<li>
<span>
comp.* — Discussion of computer-related topics like &#8220;comp.lang.c++&#8221;
</span>
</li>
<li>
<span>
sci.* — Discussion of scientific subjects
</span>
</li>
</ul>
</li>
<li>
<span>
Routing defined in route maps
</span>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_curiosity_floppy_poll_point">Curiosity: Floppy Poll/Point</h1>
<div class="sectionbody" style="max-width:45em">
<ul class=" incremental">
<li>
<span>
Not everyone had a phone line in the 1990ies
</span>
<ul class="">
<li>
<span>
particularly Eastern Germany had big lack of phone lines
</span>
</li>
</ul>
</li>
<li>
<span>
Some people thus exchanged daily floppies in envelopes and mailed them as postal letters
</span>
</li>
<li>
<span>
Messages arrived about one day later, but with 1-2 days latency even inside the dial-up store-and-forward network, it hardly matters
</span>
</li>
</ul>
<div class="paragraph"><p><span class="image">
<img src="images/floppy-disk-1219954_640.png" alt="images/floppy-disk-1219954_640.png" width="30%" />
</span></p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_internet">Internet</h1>
<div class="sectionbody" style="max-width:45em">
<div class="paragraph"><p>Early ways to access Internet:</p></div>
<ul class="">
<li>
<span>
Mail/News via UUCP (as stated earlier)
</span>
</li>
<li>
<span>
Dial-Up Modem to a TTY of a Unix machine connected to TCP/IP
</span>
<ul class="">
<li>
<span>
Often workstations at universities. You could then run FTP, IRC, telnet, Gopher on the test console
</span>
</li>
</ul>
</li>
<li>
<span>
ftp-mailers
</span>
<ul class="">
<li>
<span>
a FTP client running on a remote machine, whose input/output is used by e-mail
</span>
</li>
<li>
<span>
you send a mail with "ftp ftp.sun.com" and "ls"
</span>
</li>
<li>
<span>
hours or days later you get the list of files
</span>
</li>
<li>
<span>
you respond with cd / get / &#8230;
</span>
</li>
<li>
<span>
hours later you get the file as batch of UUencoded mails
</span>
</li>
</ul>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_internet_with_slip">Internet with SLIP</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
if you had dial-up access to a Unix box
</span>
</li>
<li>
<span>
you could run SLIP on both sides, transporting IP over the modem line
</span>
<ul class="">
<li>
<span>
Result: IP. At home. In your apartment !!1!
</span>
</li>
</ul>
</li>
<li>
<span>
later superseded by PPP (auto-configuration, authentication, compression, &#8230;)
</span>
</li>
</ul>
<div class="paragraph"><p>Popular software stack looked like:</p></div>
<ul class="">
<li>
<span>
Windows 3.11 + Trumpet Winsock (Windows didn&#8217;t have TCP/IP!)
</span>
</li>
<li>
<span>
NCSA Mosaic as web-1.0 browser (1993 onwards)
</span>
</li>
</ul>
<div class="paragraph"><p><span class="image">
<img src="images/mosaic.jpg" alt="images/mosaic.jpg" />
</span></p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_internet_on_pcs_before_linux">Internet on PCs before Linux</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
if you didn&#8217;t have a 386 or if Linux didn&#8217;t exist yet
</span>
</li>
<li>
<span>
there was KA9Q NOS
</span>
<ul class="">
<li>
<span>
Implementation of TCP/IP, SLIP, PPP for CP/M and DOS
</span>
</li>
<li>
<span>
POP3 + SMTP server + client, IP routing, telnet, ARP, etc.
</span>
</li>
</ul>
</li>
<li>
<span>
you could run SLIP on both sides, transporting IP over the modem line
</span>
<ul class="">
<li>
<span>
Result: IP. At home. In your apartment !!1!
</span>
</li>
</ul>
</li>
<li>
<span>
later superseded by PPP (auto-configuration, authentication, compression, &#8230;)
</span>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_isdn">ISDN</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
Digital Circuit-Switched Telephony Network
</span>
<ul class="">
<li>
<span>
Transport of Digital Voice (PCM) audio and transparent digital data
</span>
</li>
</ul>
</li>
<li>
<span>
Germany
</span>
<ul class="">
<li>
<span>
1989 put in operation
</span>
</li>
<li>
<span>
Until 1993 German 1TR6 system
</span>
</li>
<li>
<span>
From 1994 European E-DSS1
</span>
</li>
<li>
<span>
Hugely popularized from 1995 by subsidies
</span>
</li>
</ul>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_isdn_terminal_adapter">ISDN Terminal Adapter</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
ISDN is an all-digital network
</span>
</li>
<li>
<span>
No modulator / demodulator required
</span>
</li>
<li>
<span>
Instead, so-called <em>terminal adapter</em>
</span>
</li>
<li>
<span>
Speeds: 64000 (single B-channel) or 128000 (both B-channels)
</span>
</li>
<li>
<span>
V.110 as adaptation to do async serial over sync ISDN (1988)
</span>
</li>
</ul>
<div class="paragraph"><p><span class="image">
<img src="images/isdn.jpg" alt="images/isdn.jpg" width="50%" />
</span></p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_how_to_get_internet_access">How to get Internet Access?</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
Hard to access in early/mid 1990ies outside of academia
</span>
</li>
<li>
<span>
Almost no commercial ISPs (XLink, EUnet) - and very expensive
</span>
</li>
<li>
<span>
Grass-Roots groups of enthusiasts established themselves
</span>
</li>
<li>
<span>
Kommunikationsnetz Franken e.V. (KNF, &#8220;franken.de&#8221;) one of them
</span>
<ul class="">
<li>
<span>
dial-up UUCP and shortly later IP for personal, non-commercial users
</span>
</li>
<li>
<span>
POPs in Nürnberg, Fürth, Erlangen, Forchheim, Würzburg, Regensburg, &#8230;
</span>
</li>
<li>
<span>
Every user got 6 static IP addresses routed to wherever he dialed in (OSPF!)
</span>
</li>
<li>
<span>
served ~ 800 users / members at peak
</span>
</li>
</ul>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_individual_network_in_e_v">Individual Network (IN) e.V.</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
Umbrella Association established in 1992
</span>
<ul class="">
<li>
<span>
Goal to help regional member associations with negotiating framework contracts
</span>
</li>
<li>
<span>
Actual technical access via WiN/DFN, XLink, EUnet
</span>
</li>
<li>
<span>
Regional Member Associations include Oche, Augusta, Escape, IN-Berlin, Hanse, INKA, Toppoint, muc.de, IN-Passau, ThurNet, MAUS, CL-Net and many more
</span>
</li>
<li>
<span>
IN members served more than 300,000 users at one point
</span>
</li>
<li>
<span>
Dissolved in 2000, when
</span>
<ul class="">
<li>
<span>
commercial ISPs were widespread, and
</span>
</li>
<li>
<span>
remaining IN member organizations could get decent connectivity with IN e.V.
</span>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_internet_2">Internet</h1>
<div class="sectionbody" style="max-width:45em">
<div class="paragraph"><p>With packet-switched TCP-IP</p></div>
<ul class="">
<li>
<span>
you just needed to dial one number
</span>
</li>
<li>
<span>
and then access systems world-wide
</span>
</li>
</ul>
<div class="paragraph"><p>This brought new purpose to leased lines</p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_analog_leased_lines">Analog Leased Lines</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
Telephone operator permanently interconnects wires at exchange
</span>
</li>
<li>
<span>
No signaling (dial tone, ring tone etc)
</span>
</li>
<li>
<span>
Requires modems with special capabilities
</span>
<ul class="">
<li>
<span>
ATA without an incoming ring first
</span>
</li>
<li>
<span>
ATD without a dial tone first
</span>
</li>
</ul>
</li>
<li>
<span>
In Germany: "Analog G" of Post/Telekom
</span>
<ul class="">
<li>
<span>
I finally could afford one in 1998
</span>
</li>
<li>
<span>
900 DM installation cost
</span>
</li>
</ul>
</li>
<li>
<span>
180 DM per month (60 DM per hop)
</span>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_hub_nbg_franken_de_1998">hub-nbg.franken.de, 1998</h1>
<div class="sectionbody" style="max-width:45em">
<div class="paragraph"><p><span class="image">
<img src="images/pict3_Lg.jpg" alt="images/pict3_Lg.jpg" />
</span></p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_hub_nbg_franken_de_1998_2">hub-nbg.franken.de, 1998</h1>
<div class="sectionbody" style="max-width:45em">
<div class="paragraph"><p><span class="image">
<img src="images/pict4_Lg.jpg" alt="images/pict4_Lg.jpg" />
</span></p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_isdn_leased_lines_spv">ISDN Leased Lines "SPV"</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
Not really a leased line
</span>
</li>
<li>
<span>
Basically only "flat rate calls" to one specific (fixed) destination
</span>
</li>
<li>
<span>
Available in national 1TR6 only
</span>
<ul class="">
<li>
<span>
some of them operated until 2006
</span>
</li>
</ul>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_abusing_analog_lines_part_1">Abusing Analog Lines, Part 1</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
ICU-T
</span>
<ul class="">
<li>
<span>
inverse of ISDN NTBA
</span>
</li>
<li>
<span>
ISDN BRI (2x64k + 16k) over 12km of telephone line
</span>
</li>
</ul>
</li>
<li>
<span>
Special ISDN routers without signaling to use even 16k D-channel for data!
</span>
</li>
</ul>
<div class="paragraph"><p>Easy upgrade to get performance of a leased ISDN line out of an Analog-G</p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_leased_lines_at_knf_1997_1998">Leased Lines at KNF, 1997/1998</h1>
<div class="sectionbody" style="max-width:45em">
<div class="imageblock graphviz">
<div class="content">
<img src="bbs_early_internet__1.png" alt="bbs_early_internet__1.png" />
</div>
</div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_hub_fue_franken_de_undated">hub-fue.franken.de, undated</h1>
<div class="sectionbody" style="max-width:45em">
<div class="paragraph"><p><span class="image">
<img src="images/hub-fue-03_Lg.jpg" alt="images/hub-fue-03_Lg.jpg" />
</span></p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_hub_fue_franken_de_undated_2">hub-fue.franken.de, undated</h1>
<div class="sectionbody" style="max-width:45em">
<div class="paragraph"><p><span class="image">
<img src="images/hub-fue-04_Lg.jpg" alt="images/hub-fue-04_Lg.jpg" />
</span></p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_abusing_analog_lines_part_2">Abusing Analog Lines, Part 2</h1>
<div class="sectionbody" style="max-width:45em">
<div class="paragraph"><p>When the first DSL modems became available in the US</p></div>
<ul class="">
<li>
<span>
we imported some Ascend DSLpipe
</span>
</li>
<li>
<span>
with some firmwares, they could be used back-to-back (without DSLAM)
</span>
</li>
<li>
<span>
suddenly we could get speeds of 2.3 MBps over analog lines
</span>
<ul class="">
<li>
<span>
if they were not too long
</span>
</li>
<li>
<span>
if they didn&#8217;t have in-line inductors
</span>
</li>
</ul>
</li>
<li>
<span>
soon less expensive alternatives came up Pairgain (2000)
</span>
</li>
</ul>
<div class="paragraph"><p><span class="image">
<img src="images/ascend.jpg" alt="images/ascend.jpg" width="50%" />
</span></p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_from_online_bistro_to_internet_cafe">From Online Bistro to Internet Cafe</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
Falken&#8217;s Maze was an <em>Online Bistro</em> established in the 1990ies
</span>
<ul class="">
<li>
<span>
I became a regular around 1994
</span>
</li>
</ul>
</li>
<li>
<span>
initially had four DOS PCs, each with a Modem, dedicated phone line and a call charge meter
</span>
<ul class="">
<li>
<span>
you could go there, eat + drink and use the PCs to log into BBSs
</span>
</li>
</ul>
</li>
<li>
<span>
quickly became preferred meeting point of various nerds, BBS users, SYSOP meetings, etc.
</span>
</li>
<li>
<span>
PCs were networked with 10base2 and NetWare (DOOM!)
</span>
</li>
<li>
<span>
people started to dial into CompuServe, AOL, etc.
</span>
</li>
<li>
<span>
Internet became more popular, Falken&#8217;s Maze started subsidiary in Nuernberg
</span>
<ul class="">
<li>
<span>
ISDN SPV was used as Internet uplink
</span>
</li>
</ul>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_summary">Summary</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
The first decade[s] of wide-area electronics communications
</span>
<ul class="">
<li>
<span>
were powered by a community of enthusiasts
</span>
</li>
<li>
<span>
largely motivated by non-commercial motives
</span>
</li>
<li>
<span>
without much corporate or government influence
</span>
</li>
</ul>
</li>
<li>
<span>
BBS community / culture is a distinct sub-culture.
</span>
<ul class="">
<li>
<span>
different norms than HAM radio, Hackers, Free Software, but some of overlap
</span>
</li>
</ul>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_conclusions">Conclusions</h1>
<div class="sectionbody" style="max-width:45em">
<div class="paragraph"><p>In the BBS days</p></div>
<ul class="">
<li>
<span>
networks were distributed, without single point of failure
</span>
</li>
<li>
<span>
infrastructure <strong>owned and operated by its users</strong>
</span>
</li>
<li>
<span>
connection speeds were largely symmetric
</span>
</li>
<li>
<span>
no data center vs. consumer separation with asymmetric speeds
</span>
</li>
</ul>
<div class="paragraph"><p>This autonomy and de-centralization has been lost in the Internet age</p></div>
</div>
</div>
<div class="sect1 slide">
<h1 id="_further_reading">Further Reading</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
<a href="http://telnetbbsguide.com/">http://telnetbbsguide.com/</a>
</span>
<ul class="">
<li>
<span>
list of active telnet BBSs
</span>
</li>
</ul>
</li>
<li>
<span>
<a href="http://qodem.sourceforge.net/">http://qodem.sourceforge.net/</a>
</span>
<ul class="">
<li>
<span>
FOSS multi-platform terminal program
</span>
</li>
</ul>
</li>
<li>
<span>
<a href="http://artscene.textfiles.com/ansi/">http://artscene.textfiles.com/ansi/</a>
</span>
<ul class="">
<li>
<span>
Archive of ANSI Artwork
</span>
</li>
</ul>
</li>
<li>
<span>
<a href="https://artpacks.org/">https://artpacks.org/</a>
</span>
<ul class="">
<li>
<span>
Another Archive of ANSI Artwork
</span>
</li>
</ul>
</li>
<li>
<span>
<a href="http://www.filegate.net/nodelist/">http://www.filegate.net/nodelist/</a>
</span>
<ul class="">
<li>
<span>
FIDO nodelist of 2017
</span>
</li>
</ul>
</li>
<li>
<span>
<a href="http://www.ka9q.net/code/ka9qnos/">http://www.ka9q.net/code/ka9qnos/</a>
</span>
<ul class="">
<li>
<span>
Phil Karn&#8217;s page on KA9Q NOS
</span>
</li>
</ul>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_thanks">Thanks</h1>
<div class="sectionbody" style="max-width:45em">
<ul class="">
<li>
<span>
my uncle for giving me his old Olivetti acoustic coupler in 1990
</span>
</li>
<li>
<span>
Josef Groll, SysOp of SILVER.zer / SILVER.nbg.sub.org
</span>
</li>
<li>
<span>
Max Riegel, Martin Bokaemper, Joerg Kinzebach and KNF crew
</span>
</li>
<li>
<span>
Reinhold "unhold" Pretscher for Falken&#8217;s Maze
</span>
</li>
<li>
<span>
All sotware developers of BBS related software
</span>
</li>
<li>
<span>
All SysOps that made the BBS community possible
</span>
</li>
</ul>
</div>
</div>
<div class="sect1 slide">
<h1 id="_eof">EOF</h1>
<div class="sectionbody" style="max-width:45em">
<div class="paragraph"><p>NO CARRIER</p></div>
</div>
</div>
</body>
</html>