]> gitweb.factorcode.org Git - factor.git/commitdiff
Merge branch 'master' of git://factorcode.org/git/factor into unicode
authorDaniel Ehrenberg <ehrenbed@carleton.edu>
Sat, 8 Mar 2008 00:51:03 +0000 (18:51 -0600)
committerDaniel Ehrenberg <ehrenbed@carleton.edu>
Sat, 8 Mar 2008 00:51:03 +0000 (18:51 -0600)
229 files changed:
core/bootstrap/primitives.factor
core/hashtables/hashtables.factor
core/inference/known-words/known-words.factor
core/io/binary/binary.factor [changed mode: 0644->0755]
core/io/files/files-docs.factor
core/io/files/files.factor
core/io/io-tests.factor [changed mode: 0644->0755]
core/io/streams/c/c-tests.factor
core/io/streams/c/c.factor
core/mirrors/mirrors-docs.factor [changed mode: 0644->0755]
core/mirrors/mirrors-tests.factor [changed mode: 0644->0755]
core/mirrors/mirrors.factor
core/slots/slots.factor
core/system/system-tests.factor
core/system/system.factor
core/words/words-tests.factor
extra/alarms/alarms.factor
extra/builder/builder.factor
extra/builder/release/release.factor
extra/builder/test/test.factor
extra/builder/util/util.factor
extra/calendar/format/format.factor
extra/db/db.factor
extra/db/sqlite/lib/lib.factor
extra/db/sqlite/sqlite-tests.factor
extra/db/sqlite/sqlite.factor
extra/db/sqlite/test.db [deleted file]
extra/db/tuples/tuples-tests.factor
extra/db/tuples/tuples.factor
extra/db/types/types.factor
extra/destructors/destructors-docs.factor
extra/destructors/destructors-tests.factor
extra/destructors/destructors.factor
extra/editors/jedit/jedit.factor
extra/farkup/farkup-tests.factor
extra/fry/fry-docs.factor [new file with mode: 0755]
extra/furnace/authors.txt [deleted file]
extra/furnace/furnace-tests.factor [deleted file]
extra/furnace/furnace.factor [deleted file]
extra/furnace/sessions/authors.txt [deleted file]
extra/furnace/sessions/sessions.factor [deleted file]
extra/furnace/summary.txt [deleted file]
extra/furnace/tags.txt [deleted file]
extra/furnace/validator/authors.txt [deleted file]
extra/furnace/validator/validator-tests.factor [deleted file]
extra/furnace/validator/validator.factor [deleted file]
extra/help/markup/markup.factor
extra/help/stylesheet/stylesheet.factor [changed mode: 0644->0755]
extra/html/parser/analyzer/analyzer.factor
extra/http/client/client-tests.factor
extra/http/client/client.factor
extra/http/http-tests.factor
extra/http/server/actions/actions-tests.factor
extra/http/server/actions/actions.factor
extra/http/server/auth/basic/basic.factor [new file with mode: 0755]
extra/http/server/auth/login/login.factor [new file with mode: 0755]
extra/http/server/auth/login/login.fhtml [new file with mode: 0755]
extra/http/server/auth/providers/assoc/assoc-tests.factor [new file with mode: 0755]
extra/http/server/auth/providers/assoc/assoc.factor [new file with mode: 0755]
extra/http/server/auth/providers/db/db-tests.factor [new file with mode: 0755]
extra/http/server/auth/providers/db/db.factor [new file with mode: 0755]
extra/http/server/auth/providers/null/null.factor [new file with mode: 0755]
extra/http/server/auth/providers/providers.factor [new file with mode: 0755]
extra/http/server/cgi/cgi.factor
extra/http/server/components/components.factor [new file with mode: 0755]
extra/http/server/crud/crud.factor [new file with mode: 0644]
extra/http/server/db/db.factor
extra/http/server/server.factor
extra/http/server/sessions/sessions-tests.factor
extra/http/server/sessions/sessions.factor
extra/http/server/static/static.factor
extra/http/server/templating/authors.txt [deleted file]
extra/http/server/templating/fhtml/authors.txt [new file with mode: 0644]
extra/http/server/templating/fhtml/fhtml-tests.factor [new file with mode: 0755]
extra/http/server/templating/fhtml/fhtml.factor [new file with mode: 0755]
extra/http/server/templating/fhtml/test/bug.fhtml [new file with mode: 0644]
extra/http/server/templating/fhtml/test/bug.html [new file with mode: 0644]
extra/http/server/templating/fhtml/test/example.fhtml [new file with mode: 0644]
extra/http/server/templating/fhtml/test/example.html [new file with mode: 0644]
extra/http/server/templating/fhtml/test/stack.fhtml [new file with mode: 0644]
extra/http/server/templating/fhtml/test/stack.html [new file with mode: 0644]
extra/http/server/templating/templating-tests.factor [deleted file]
extra/http/server/templating/templating.factor [deleted file]
extra/http/server/templating/test/bug.fhtml [deleted file]
extra/http/server/templating/test/bug.html [deleted file]
extra/http/server/templating/test/example.fhtml [deleted file]
extra/http/server/templating/test/example.html [deleted file]
extra/http/server/templating/test/stack.fhtml [deleted file]
extra/http/server/templating/test/stack.html [deleted file]
extra/http/server/validators/validators-tests.factor [new file with mode: 0644]
extra/http/server/validators/validators.factor [new file with mode: 0644]
extra/http/test/foo.html [new file with mode: 0644]
extra/io/launcher/authors.txt
extra/io/launcher/launcher-docs.factor
extra/io/launcher/launcher.factor
extra/io/nonblocking/nonblocking.factor
extra/io/server/server.factor
extra/io/sockets/sockets.factor
extra/io/unix/files/files.factor
extra/io/unix/kqueue/kqueue.factor
extra/io/unix/launcher/launcher-tests.factor
extra/io/unix/launcher/launcher.factor
extra/io/unix/sockets/sockets.factor
extra/io/windows/ce/ce.factor
extra/io/windows/files/files.factor
extra/io/windows/launcher/launcher.factor
extra/io/windows/nt/launcher/launcher-tests.factor [new file with mode: 0755]
extra/io/windows/nt/launcher/launcher.factor
extra/io/windows/nt/launcher/test/env.factor [new file with mode: 0755]
extra/io/windows/nt/launcher/test/stderr.factor [new file with mode: 0755]
extra/io/windows/nt/nt.factor
extra/io/windows/nt/pipes/pipes.factor
extra/io/windows/nt/sockets/sockets.factor
extra/ldap/ldap-tests.factor
extra/ldap/libldap/libldap.factor
extra/logging/analysis/analysis.factor
extra/logging/insomniac/insomniac.factor
extra/namespaces/lib/lib.factor
extra/openssl/libssl/libssl.factor
extra/pdf/libhpdf/libhpdf.factor
extra/pdf/pdf-tests.factor
extra/pdf/test/font_test.pdf [deleted file]
extra/peg/peg-docs.factor
extra/peg/peg.factor
extra/peg/search/search-tests.factor
extra/random-tester/safe-words/safe-words.factor
extra/regexp2/regexp2-tests.factor [new file with mode: 0644]
extra/regexp2/regexp2.factor [new file with mode: 0644]
extra/sequences/lib/lib.factor
extra/singleton/authors.txt [new file with mode: 0644]
extra/singleton/singleton-docs.factor [new file with mode: 0644]
extra/singleton/singleton.factor [new file with mode: 0644]
extra/slides/slides.factor
extra/smtp/smtp-tests.factor
extra/smtp/smtp.factor
extra/tools/deploy/backend/backend.factor
extra/tools/disassembler/disassembler.factor
extra/unicode/categories/categories.factor
extra/unix/stat/stat.factor
extra/unix/unix.factor
extra/webapps/callback/authors.txt [deleted file]
extra/webapps/callback/callback.factor [deleted file]
extra/webapps/continuation/authors.txt [deleted file]
extra/webapps/continuation/continuation.factor [deleted file]
extra/webapps/continuation/examples/authors.txt [deleted file]
extra/webapps/continuation/examples/examples.factor [deleted file]
extra/webapps/fjsc/authors.txt [deleted file]
extra/webapps/fjsc/fjsc.factor [deleted file]
extra/webapps/fjsc/head.furnace [deleted file]
extra/webapps/fjsc/repl.furnace [deleted file]
extra/webapps/fjsc/resources/repl.js [deleted file]
extra/webapps/fjsc/resources/termlib/faq.html [deleted file]
extra/webapps/fjsc/resources/termlib/index.html [deleted file]
extra/webapps/fjsc/resources/termlib/multiterm_test.html [deleted file]
extra/webapps/fjsc/resources/termlib/parser_sample.html [deleted file]
extra/webapps/fjsc/resources/termlib/readme.txt [deleted file]
extra/webapps/fjsc/resources/termlib/term_styles.css [deleted file]
extra/webapps/fjsc/resources/termlib/termlib.js [deleted file]
extra/webapps/fjsc/resources/termlib/termlib_parser.js [deleted file]
extra/webapps/fjsc/summary.txt [deleted file]
extra/webapps/fjsc/tags.txt [deleted file]
extra/webapps/help/authors.txt [deleted file]
extra/webapps/help/help.factor [deleted file]
extra/webapps/numbers/authors.txt [deleted file]
extra/webapps/numbers/numbers.factor [deleted file]
extra/webapps/pastebin/annotate-paste.furnace [deleted file]
extra/webapps/pastebin/annotation.furnace [deleted file]
extra/webapps/pastebin/authors.txt [deleted file]
extra/webapps/pastebin/footer.furnace [deleted file]
extra/webapps/pastebin/header.furnace [deleted file]
extra/webapps/pastebin/modes.furnace [deleted file]
extra/webapps/pastebin/new-paste.furnace [deleted file]
extra/webapps/pastebin/paste-list.furnace [deleted file]
extra/webapps/pastebin/paste-summary.furnace [deleted file]
extra/webapps/pastebin/pastebin.factor [deleted file]
extra/webapps/pastebin/show-paste.furnace [deleted file]
extra/webapps/pastebin/style.css [deleted file]
extra/webapps/pastebin/syntax.furnace [deleted file]
extra/webapps/planet/authors.txt [deleted file]
extra/webapps/planet/planet.factor [deleted file]
extra/webapps/planet/planet.furnace [deleted file]
extra/webapps/planet/style.css [deleted file]
extra/windows/time/time-tests.factor
misc/macos-release.sh [deleted file]
misc/source-release.sh [deleted file]
misc/windows-release.sh [deleted file]
unmaintained/sniffer/io/bsd/bsd.factor
unmaintained/webapps/fjsc/authors.txt [new file with mode: 0644]
unmaintained/webapps/fjsc/fjsc.factor [new file with mode: 0755]
unmaintained/webapps/fjsc/head.furnace [new file with mode: 0644]
unmaintained/webapps/fjsc/repl.furnace [new file with mode: 0644]
unmaintained/webapps/fjsc/resources/repl.js [new file with mode: 0644]
unmaintained/webapps/fjsc/resources/termlib/faq.html [new file with mode: 0644]
unmaintained/webapps/fjsc/resources/termlib/index.html [new file with mode: 0644]
unmaintained/webapps/fjsc/resources/termlib/multiterm_test.html [new file with mode: 0644]
unmaintained/webapps/fjsc/resources/termlib/parser_sample.html [new file with mode: 0644]
unmaintained/webapps/fjsc/resources/termlib/readme.txt [new file with mode: 0644]
unmaintained/webapps/fjsc/resources/termlib/term_styles.css [new file with mode: 0644]
unmaintained/webapps/fjsc/resources/termlib/termlib.js [new file with mode: 0644]
unmaintained/webapps/fjsc/resources/termlib/termlib_parser.js [new file with mode: 0644]
unmaintained/webapps/fjsc/summary.txt [new file with mode: 0644]
unmaintained/webapps/fjsc/tags.txt [new file with mode: 0644]
unmaintained/webapps/help/authors.txt [new file with mode: 0755]
unmaintained/webapps/help/help.factor [new file with mode: 0644]
unmaintained/webapps/numbers/authors.txt [new file with mode: 0755]
unmaintained/webapps/numbers/numbers.factor [new file with mode: 0644]
unmaintained/webapps/pastebin/annotate-paste.furnace [new file with mode: 0755]
unmaintained/webapps/pastebin/annotation.furnace [new file with mode: 0755]
unmaintained/webapps/pastebin/authors.txt [new file with mode: 0755]
unmaintained/webapps/pastebin/footer.furnace [new file with mode: 0644]
unmaintained/webapps/pastebin/header.furnace [new file with mode: 0644]
unmaintained/webapps/pastebin/modes.furnace [new file with mode: 0644]
unmaintained/webapps/pastebin/new-paste.furnace [new file with mode: 0755]
unmaintained/webapps/pastebin/paste-list.furnace [new file with mode: 0644]
unmaintained/webapps/pastebin/paste-summary.furnace [new file with mode: 0644]
unmaintained/webapps/pastebin/pastebin.factor [new file with mode: 0755]
unmaintained/webapps/pastebin/show-paste.furnace [new file with mode: 0755]
unmaintained/webapps/pastebin/style.css [new file with mode: 0644]
unmaintained/webapps/pastebin/syntax.furnace [new file with mode: 0755]
unmaintained/webapps/planet/authors.txt [new file with mode: 0755]
unmaintained/webapps/planet/planet.factor [new file with mode: 0755]
unmaintained/webapps/planet/planet.furnace [new file with mode: 0644]
unmaintained/webapps/planet/style.css [new file with mode: 0644]
vm/io.c
vm/io.h
vm/os-unix.c
vm/os-windows.c
vm/primitives.c
vm/run.h

index f3f233ea0b8c8847c96097db81ba85b33d863438..aeb5ec1d829f7d634cb6412543ef6b90549ed146 100755 (executable)
@@ -78,6 +78,7 @@ call
     "strings"
     "strings.private"
     "system"
+    "system.private"
     "threads.private"
     "tools.profiler.private"
     "tuples"
@@ -274,7 +275,7 @@ define-builtin
     }
     {
         { "object" "kernel" }
-        "?"
+        "compiled?"
         { "compiled?" "words" }
         f
     }
@@ -623,6 +624,7 @@ builtins get num-tags get tail f union-class define-class
     { "fopen" "io.streams.c" }
     { "fgetc" "io.streams.c" }
     { "fread" "io.streams.c" }
+    { "fputc" "io.streams.c" }
     { "fwrite" "io.streams.c" }
     { "fflush" "io.streams.c" }
     { "fclose" "io.streams.c" }
@@ -645,7 +647,8 @@ builtins get num-tags get tail f union-class define-class
     { "innermost-frame-scan" "kernel.private" }
     { "set-innermost-frame-quot" "kernel.private" }
     { "call-clear" "kernel" }
-    { "(os-envs)" "system" }
+    { "(os-envs)" "system.private" }
+    { "(set-os-envs)" "system.private" }
     { "resize-byte-array" "byte-arrays" }
     { "resize-bit-array" "bit-arrays" }
     { "resize-float-array" "float-arrays" }
index 359bedd0416b06cceacfacdf223bdd2e3663b3ed..7d8c6f0b5f85299491fcb27e430b61efcf095ff5 100755 (executable)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2005, 2007 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays kernel kernel.private slots.private math assocs
-math.private sequences sequences.private vectors ;
+       math.private sequences sequences.private vectors ;
 IN: hashtables
 
 <PRIVATE
@@ -16,15 +16,16 @@ IN: hashtables
     2 fixnum+fast over wrap ; inline
 
 : (key@) ( key keys i -- array n ? )
-    3dup swap array-nth dup ((tombstone)) eq? [
-        2drop probe (key@)
-    ] [
-        dup ((empty)) eq? [
-            3drop nip f f
-        ] [
-            = [ rot drop t ] [ probe (key@) ] if
-        ] if
-    ] if ; inline
+    3dup swap array-nth
+    dup ((empty)) eq?
+      [ 3drop nip f f ]
+      [
+        =
+          [ rot drop t ]
+          [ probe (key@) ]
+        if
+      ]
+    if ; inline
 
 : key@ ( key hash -- array n ? )
     hash-array 2dup hash@ (key@) ; inline
index 8e8251ff620937eb84c56258330ef53bb2bd8271..235c2924bb3dda31bb465fee4cacfd78b518afff 100755 (executable)
@@ -10,7 +10,8 @@ namespaces.private parser prettyprint quotations
 quotations.private sbufs sbufs.private sequences
 sequences.private slots.private strings strings.private system
 threads.private tuples tuples.private vectors vectors.private
-words words.private assocs inspector compiler.units ;
+words words.private assocs inspector compiler.units
+system.private ;
 IN: inference.known-words
 
 ! Shuffle words
@@ -538,6 +539,8 @@ set-primitive-effect
 
 \ fwrite { string alien } { } <effect> set-primitive-effect
 
+\ fputc { object alien } { } <effect> set-primitive-effect
+
 \ fread { integer string } { object } <effect> set-primitive-effect
 
 \ fflush { alien } { } <effect> set-primitive-effect
@@ -595,6 +598,8 @@ set-primitive-effect
 
 \ (os-envs) { } { array } <effect> set-primitive-effect
 
+\ (set-os-envs) { array } { } <effect> set-primitive-effect
+
 \ do-primitive [ \ do-primitive no-effect ] "infer" set-word-prop
 
 \ dll-valid? { object } { object } <effect> set-primitive-effect
old mode 100644 (file)
new mode 100755 (executable)
index c4d3abe..9f6231b
@@ -10,7 +10,7 @@ IN: io.binary
 
 : nth-byte ( x n -- b ) -8 * shift mask-byte ; inline
 
-: >le ( x n -- str ) [ nth-byte ] with "" map-as ;
+: >le ( x n -- str ) [ nth-byte ] with B{ } map-as ;
 : >be ( x n -- str ) >le dup reverse-here ;
 
 : d>w/w ( d -- w1 w2 )
index f68d5eafbd975bb99f0ec0055e1fc3f2fdaec248..9609cd123b9b869862bdb27ab790acaac2ef7a1a 100755 (executable)
@@ -89,7 +89,6 @@ ARTICLE: "io.files" "Basic file operations"
 { $subsection "fs-meta" }
 { $subsection "directories" }
 { $subsection "delete-move-copy" }
-{ $subsection "unique" }
 { $see-also "os" } ;
 
 ABOUT: "io.files"
index a2b640e2673cb0ad58f0fc4face1d395b394e1cc..f740d1dc21c4cea9a00f7c52553e9490f8f8b0a0 100755 (executable)
@@ -71,6 +71,7 @@ TUPLE: no-parent-directory path ;
 TUPLE: file-info type size permissions modified ;
 
 HOOK: file-info io-backend ( path -- info )
+HOOK: link-info io-backend ( path -- info )
 
 SYMBOL: +regular-file+
 SYMBOL: +directory+
old mode 100644 (file)
new mode 100755 (executable)
index 8b5e763..22c942d
@@ -1,5 +1,6 @@
 USING: arrays io io.files kernel math parser strings system
-tools.test words namespaces io.encodings.ascii io.encodings.binary ;
+tools.test words namespaces io.encodings.latin1
+io.encodings.binary ;
 IN: io.tests
 
 [ f ] [
@@ -8,7 +9,7 @@ IN: io.tests
 ] unit-test
 
 : <resource-reader> ( resource -- stream )
-    resource-path binary <file-reader> ;
+    resource-path latin1 <file-reader> ;
 
 [
     "This is a line.\rThis is another line.\r"
@@ -31,10 +32,10 @@ IN: io.tests
 
 ! [ ] [ "123" write 9000 CHAR: x <string> write flush ] unit-test
 
-[ "" ] [
+[
     "/core/io/test/binary.txt" <resource-reader>
     [ 0.2 read ] with-stream
-] unit-test
+] must-fail
 
 [
     {
index 6c7e57cabb025e60ee6c6e75f9224cb522739044..321cad4d1964725bf3a3aa0b7b70950156fbefcc 100755 (executable)
@@ -1,4 +1,5 @@
-USING: tools.test io.files io io.streams.c io.encodings.ascii ;
+USING: tools.test io.files io io.streams.c
+io.encodings.ascii strings ;
 IN: io.streams.c.tests
 
 [ "hello world" ] [
@@ -7,4 +8,5 @@ IN: io.streams.c.tests
     ] with-file-writer
 
     "test.txt" temp-file "rb" fopen <c-reader> contents
+    >string
 ] unit-test
index de49e0dfe63e96f01ede8bfbd799e78d922b2850..372acbe0c1e2ebfa418009457ef1ffac042bdce2 100755 (executable)
@@ -1,9 +1,8 @@
 ! Copyright (C) 2004, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel kernel.private namespaces io io.encodings
-strings sequences math generic threads.private classes
-io.backend io.streams.duplex io.files continuations
-io.encodings.utf8 ;
+sequences math generic threads.private classes io.backend
+io.streams.duplex io.files continuations byte-arrays ;
 IN: io.streams.c
 
 TUPLE: c-writer handle ;
@@ -11,10 +10,10 @@ TUPLE: c-writer handle ;
 C: <c-writer> c-writer
 
 M: c-writer stream-write1
-    >r 1string r> stream-write ;
+    c-writer-handle fputc ;
 
 M: c-writer stream-write
-    >r >string r> c-writer-handle fwrite ;
+    c-writer-handle fwrite ;
 
 M: c-writer stream-flush
     c-writer-handle fflush ;
@@ -27,7 +26,7 @@ TUPLE: c-reader handle ;
 C: <c-reader> c-reader
 
 M: c-reader stream-read
-    >r >fixnum r> c-reader-handle fread ;
+    c-reader-handle fread ;
 
 M: c-reader stream-read-partial
     stream-read ;
@@ -43,7 +42,7 @@ M: c-reader stream-read1
     ] if ;
 
 M: c-reader stream-read-until
-    [ swap read-until-loop ] "" make swap
+    [ swap read-until-loop ] B{ } make swap
     over empty? over not and [ 2drop f f ] when ;
 
 M: c-reader dispose
@@ -76,4 +75,6 @@ M: object (file-appender)
     #! print stuff from contexts where the I/O system would
     #! otherwise not work (tools.deploy.shaker, the I/O
     #! multiplexer thread).
-    "\r\n" append stdout-handle fwrite stdout-handle fflush ;
+    "\r\n" append >byte-array
+    stdout-handle fwrite
+    stdout-handle fflush ;
old mode 100644 (file)
new mode 100755 (executable)
index ae40c85..8da9e9d
@@ -20,7 +20,7 @@ HELP: object-slots
 HELP: mirror
 { $class-description "An associative structure which wraps an object and presents itself as a mapping from slot names to the object's slot values. Mirrors are used to build reflective developer tools."
 $nl
-"Mirrors are mutable, however new keys cannot be inserted and keys cannot be deleted, only values of existing keys can be changed."
+"Mirrors are mutable, however new keys cannot be inserted, only values of existing keys can be changed. Deleting a key has the effect of setting its value to " { $link f } "."
 $nl
 "Mirrors are created by calling " { $link <mirror> } " or " { $link make-mirror } "." } ;
 
@@ -33,7 +33,7 @@ HELP: <mirror>
         "TUPLE: circle center radius ;"
         "C: <circle> circle"
         "{ 100 50 } 15 <circle> <mirror> >alist ."
-        "{ { circle-center { 100 50 } } { circle-radius 15 } }"
+        "{ { \"center\" { 100 50 } } { \"radius\" 15 } }"
     }
 } ;
 
@@ -47,5 +47,5 @@ $nl
 "Enumerations are mutable; note that deleting a key calls " { $link delete-nth } ", which results in all subsequent elements being shifted down." } ;
 
 HELP: make-mirror
-{ $values { "obj" object } { "assoc" "an assoc" } }
+{ $values { "obj" object } { "assoc" assoc } }
 { $description "Creates an assoc which reflects the internal structure of the object." } ;
old mode 100644 (file)
new mode 100755 (executable)
index 863c4ba..8f2964b
@@ -5,12 +5,12 @@ TUPLE: foo bar baz ;
 
 C: <foo> foo
 
-[ { foo-bar foo-baz } ] [ 1 2 <foo> <mirror> keys ] unit-test
+[ { "bar" "baz" } ] [ 1 2 <foo> <mirror> keys ] unit-test
 
-[ 1 t ] [ \ foo-bar 1 2 <foo> <mirror> at* ] unit-test
+[ 1 t ] [ "bar" 1 2 <foo> <mirror> at* ] unit-test
 
 [ f f ] [ "hi" 1 2 <foo> <mirror> at* ] unit-test
 
 [ 3 ] [
-    3 \ foo-baz 1 2 <foo> [ <mirror> set-at ] keep foo-baz
+    3 "baz" 1 2 <foo> [ <mirror> set-at ] keep foo-baz
 ] unit-test
index af540ef86c686d711fa55dcf78988cd8990798e0..8f12bbb2f4120c04a8aee1da8305b80e85e4c8de 100755 (executable)
@@ -21,12 +21,14 @@ TUPLE: mirror object slots ;
 : >mirror< ( mirror -- obj slots )
     dup mirror-object swap mirror-slots ;
 
+: mirror@ ( slot-name mirror -- obj slot-spec )
+    >mirror< swapd slot-named ;
+
 M: mirror at*
-    >mirror< swapd slot-of-reader
-    dup [ slot-spec-offset slot t ] [ 2drop f f ] if ;
+    mirror@ dup [ slot-spec-offset slot t ] [ 2drop f f ] if ;
 
 M: mirror set-at ( val key mirror -- )
-    >mirror< swapd slot-of-reader dup [
+    mirror@ dup [
         dup slot-spec-writer [
             slot-spec-offset set-slot
         ] [
@@ -42,7 +44,7 @@ M: mirror delete-at ( key mirror -- )
 M: mirror >alist ( mirror -- alist )
     >mirror<
     [ [ slot-spec-offset slot ] with map ] keep
-    [ slot-spec-reader ] map swap 2array flip ;
+    [ slot-spec-name ] map swap 2array flip ;
 
 M: mirror assoc-size mirror-slots length ;
 
index 40f0dd3da1d4e339319addc73d1c0a5d55c28259..92d22247bdb0386104b8e5deb6debd781eb21c24 100755 (executable)
@@ -110,3 +110,6 @@ PREDICATE: word slot-writer "writing" word-prop >boolean ;
 
 : slot-of-writer ( writer specs -- spec/f )
     [ slot-spec-writer eq? ] with find nip ;
+
+: slot-named ( string specs -- spec/f )
+    [ slot-spec-name = ] with find nip ;
index 296f5424180c0ab8def498216fa6585daa324f36..ad0e5e07cb081484a46c19e9ee6cf21b2de322f6 100755 (executable)
@@ -1,6 +1,17 @@
-USING: math tools.test system prettyprint ;
+USING: math tools.test system prettyprint namespaces kernel ;
 IN: system.tests
 
 [ t ] [ cell integer? ] unit-test
 [ t ] [ bootstrap-cell integer? ] unit-test
-[ ] [ os-envs . ] unit-test
+
+wince? [
+    [ ] [ os-envs . ] unit-test
+] unless
+
+unix? [
+    [ ] [ os-envs "envs" set ] unit-test
+    [ ] [ { { "A" "B" } } set-os-envs ] unit-test
+    [ "B" ] [ "A" os-env ] unit-test
+    [ ] [ "envs" get set-os-envs ] unit-test
+    [ t ] [ os-envs "envs" get = ] unit-test
+] when
index 4500720058537aad9d9ac5313b32fe5f4b4344c1..58abd4be2f9de88f2fed8f6a488ad041b553200b 100755 (executable)
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 IN: system
 USING: kernel kernel.private sequences math namespaces
-splitting assocs ;
+splitting assocs system.private ;
 
 : cell ( -- n ) 7 getenv ; foldable
 
@@ -59,3 +59,6 @@ splitting assocs ;
 
 : os-envs ( -- assoc )
     (os-envs) [ "=" split1 ] H{ } map>assoc ;
+
+: set-os-envs ( assoc -- )
+    [ "=" swap 3append ] { } assoc>map (set-os-envs) ;
index 06f3c7a7827d713d1649aef9f9081c43c3c2dfaa..4d9933147b970885313121612958a78e69b1fed4 100755 (executable)
@@ -141,7 +141,11 @@ SYMBOL: quot-uses-b
 
 [ { + } ] [ \ quot-uses-b uses ] unit-test
 
-[ "IN: words.tests FORGET: undef-test : undef-test ; << undef-test >>" eval ]
+"undef-test" "words.tests" lookup [
+    [ forget ] with-compilation-unit
+] when*
+
+[ "IN: words.tests : undef-test ; << undef-test >>" eval ]
 [ [ undefined? ] is? ] must-fail-with
 
 [ ] [
index 1ccfdcbd3004aa28cfc0a807fae7ab1c7b254ef6..55a66c52318f3d3df1e828bd3107b2b5e04cdfe8 100755 (executable)
@@ -85,5 +85,8 @@ PRIVATE>
 : later ( quot dt -- alarm )
     from-now f add-alarm ;
 
+: every ( quot dt -- alarm )
+    [ from-now ] keep add-alarm ;
+
 : cancel-alarm ( alarm -- )
     alarm-entry [ alarms get-global heap-delete ] if-box? ;
index 92cd5f5241d26397b86426b199e888fe0cbfd259..747f0cd1e5375001f4117ec242b6ab9938ec25e0 100644 (file)
@@ -2,6 +2,7 @@
 USING: kernel namespaces sequences splitting system combinators continuations
        parser io io.files io.launcher io.sockets prettyprint threads
        bootstrap.image benchmark vars bake smtp builder.util accessors
+       io.encodings.utf8
        calendar
        builder.common
        builder.benchmark
@@ -35,20 +36,20 @@ IN: builder
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 : git-id ( -- id )
-  { "git" "show" } <process-stream> [ readln ] with-stream " " split second ;
+  { "git" "show" } utf8 <process-stream>
+  [ readln ] with-stream " " split second ;
 
-: record-git-id ( -- ) git-id "../git-id" [ . ] with-file-writer ;
+: record-git-id ( -- ) git-id "../git-id" utf8 [ . ] with-file-writer ;
 
-: do-make-clean ( -- desc ) { "make" "clean" } try-process ;
+: do-make-clean ( -- ) { "make" "clean" } try-process ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 : make-vm ( -- desc )
-  <process*>
-    { "make" }       >>arguments
+  <process>
+    { "make" }       >>command
     "../compile-log" >>stdout
-    +stdout+         >>stderr
-  >desc ;
+    +stdout+         >>stderr ;
 
 : do-make-vm ( -- )
   make-vm [ "vm compile error" print "../compile-log" cat ] run-or-bail ;
@@ -65,13 +66,12 @@ IN: builder
   { "./factor" { "-i=" my-boot-image-name } "-no-user-init" } to-strings ;
 
 : bootstrap ( -- desc )
-  <process*>
-    bootstrap-cmd >>arguments
+  <process>
+    bootstrap-cmd >>command
     +closed+      >>stdin
     "../boot-log" >>stdout
     +stdout+      >>stderr
-    20 minutes    >>timeout
-  >desc ;
+    20 minutes    >>timeout ;
 
 : do-bootstrap ( -- )
   bootstrap [ "Bootstrap error" print "../boot-log" cat ] run-or-bail ;
@@ -80,13 +80,12 @@ IN: builder
   { "./factor" "-run=builder.test" } to-strings ;
 
 : builder-test ( -- desc )
-  <process*>
-    builder-test-cmd >>arguments
+  <process>
+    builder-test-cmd >>command
     +closed+         >>stdin
     "../test-log"    >>stdout
     +stdout+         >>stderr
-    45 minutes       >>timeout
-  >desc ;
+    45 minutes       >>timeout ;
 
 : do-builder-test ( -- )
   builder-test [ "Test error" print "../test-log" 100 cat-n ] run-or-bail ;
@@ -103,7 +102,7 @@ SYMBOL: build-status
 
   enter-build-dir
 
-  "report"
+  "report" utf8
     [
       "Build machine:   " write host-name print
       "CPU:             " write cpu       print
index 849d1a54a30793c85fd0476a22017f3a06014dd6..f0cf0ee1130ce4019c7853abfb3d21ffa80ce72e 100644 (file)
@@ -19,7 +19,7 @@ IN: builder.release
   {
     "boot.x86.32.image"
     "boot.x86.64.image"
-    "boot.macosx-ppc.boot"
+    "boot.macosx-ppc.image"
     "vm"
     "temp"
     "logs"
index c664941132abfebde838998e607c8afbd7705432..d03be0781a709319e309885f4eb39497aebf532e 100644 (file)
@@ -6,22 +6,24 @@ USING: kernel namespaces sequences assocs builder continuations
        prettyprint
        tools.browser
        tools.test
+       io.encodings.utf8
        bootstrap.stage2 benchmark builder.util ;
 
 IN: builder.test
 
 : do-load ( -- )
-  try-everything keys "../load-everything-vocabs" [ . ] with-file-writer ;
+  try-everything keys "../load-everything-vocabs" utf8 [ . ] with-file-writer ;
 
 : do-tests ( -- )
-  run-all-tests keys "../test-all-vocabs" [ . ] with-file-writer ;
+  run-all-tests keys "../test-all-vocabs" utf8 [ . ] with-file-writer ;
 
-: do-benchmarks ( -- ) run-benchmarks "../benchmarks" [ . ] with-file-writer ;
+: do-benchmarks ( -- )
+  run-benchmarks "../benchmarks" utf8 [ . ] with-file-writer ;
 
 : do-all ( -- )
-  bootstrap-time get   "../boot-time" [ . ] with-file-writer
-  [ do-load  ] runtime "../load-time" [ . ] with-file-writer
-  [ do-tests ] runtime "../test-time" [ . ] with-file-writer
+  bootstrap-time get   "../boot-time" utf8 [ . ] with-file-writer
+  [ do-load  ] runtime "../load-time" utf8 [ . ] with-file-writer
+  [ do-tests ] runtime "../test-time" utf8 [ . ] with-file-writer
   do-benchmarks ;
 
 MAIN: do-all
\ No newline at end of file
index 9682fc1346e94e62c53437ede72cbbf53bfd9c02..82514ca43d8cb26c7b5ed640ea1087279672b1ca 100644 (file)
@@ -4,6 +4,7 @@ USING: kernel words namespaces classes parser continuations
        math math.parser
        combinators sequences splitting quotations arrays strings tools.time
        sequences.deep new-slots accessors assocs.lib
+       io.encodings.utf8
        combinators.cleave bake calendar calendar.format ;
 
 IN: builder.util
@@ -14,7 +15,7 @@ IN: builder.util
 
 : minutes>ms ( min -- ms ) 60 * 1000 * ;
 
-: file>string ( file -- string ) [ stdio get contents ] with-file-reader ;
+: file>string ( file -- string ) utf8 [ stdio get contents ] with-file-reader ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
@@ -39,18 +40,18 @@ DEFER: to-strings
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-TUPLE: process* arguments stdin stdout stderr timeout ;
+TUPLE: process* arguments stdin stdout stderr timeout ;
 
-: <process*> process* construct-empty ;
+: <process*> process* construct-empty ;
 
-: >desc ( process* -- desc )
-  H{ } clone
-    over arguments>> [ +arguments+ swap put-at ] when*
-    over stdin>>     [ +stdin+     swap put-at ] when*
-    over stdout>>    [ +stdout+    swap put-at ] when*
-    over stderr>>    [ +stderr+    swap put-at ] when*
-    over timeout>>   [ +timeout+   swap put-at ] when*
-  nip ;
+: >desc ( process* -- desc )
+  H{ } clone
+    over arguments>> [ +arguments+ swap put-at ] when*
+    over stdin>>     [ +stdin+     swap put-at ] when*
+    over stdout>>    [ +stdout+    swap put-at ] when*
+    over stderr>>    [ +stderr+    swap put-at ] when*
+    over timeout>>   [ +timeout+   swap put-at ] when*
+  nip ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
@@ -69,9 +70,9 @@ TUPLE: process* arguments stdin stdout stderr timeout ;
 : milli-seconds>time ( n -- string )
   1000 /i 60 /mod >r 60 /mod r> 3array [ pad-00 ] map ":" join ;
 
-: eval-file ( file -- obj ) file-contents eval ;
+: eval-file ( file -- obj ) utf8 file-contents eval ;
 
-: cat ( file -- ) file-contents print ;
+: cat ( file -- ) utf8 file-contents print ;
 
 : run-or-bail ( desc quot -- )
   [ [ try-process ] curry   ]
@@ -96,7 +97,7 @@ USING: bootstrap.image bootstrap.image.download io.streams.null ;
   if ;
 
 : cat-n ( file n -- )
-  [ file-lines ] [ ] bi*
+  [ utf8 file-lines ] [ ] bi*
   maybe-tail*
   [ print ] each ;
 
@@ -104,7 +105,7 @@ USING: bootstrap.image bootstrap.image.download io.streams.null ;
 
 USE: prettyprint
 
-: to-file ( object file -- ) [ . ] with-file-writer ;
+: to-file ( object file -- ) utf8 [ . ] with-file-writer ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
index 75ceea8ea2cd08f30aab7a9be5ad2003a946a1c7..89e09e0d0cd3003cdd3aab2168cf3fbd11d886a7 100755 (executable)
@@ -36,8 +36,12 @@ M: timestamp year. ( timestamp -- )
 \r
 : pad-00 number>string 2 CHAR: 0 pad-left ;\r
 \r
+: pad-0000 number>string 4 CHAR: 0 pad-left ;\r
+\r
 : write-00 pad-00 write ;\r
 \r
+: write-0000 pad-0000 write ;\r
+\r
 : (timestamp>string) ( timestamp -- )\r
     dup day-of-week day-abbreviations3 nth write ", " write\r
     dup day>> number>string write bl\r
@@ -107,24 +111,68 @@ M: timestamp year. ( timestamp -- )
         60 / + *\r
     ] if ;\r
 \r
+: read-ymd ( -- y m d )\r
+    read-0000 "-" expect read-00 "-" expect read-00 ;\r
+\r
+: read-hms ( -- h m s )\r
+    read-00 ":" expect read-00 ":" expect read-00 ;\r
+\r
 : (rfc3339>timestamp) ( -- timestamp )\r
-    read-0000 ! year\r
-    "-" expect\r
-    read-00 ! month\r
-    "-" expect\r
-    read-00 ! day\r
+    read-ymd\r
     "Tt" expect\r
-    read-00 ! hour\r
-    ":" expect\r
-    read-00 ! minute\r
-    ":" expect\r
-    read-00 ! second\r
+    read-hms\r
     read-rfc3339-gmt-offset ! timezone\r
     <timestamp> ;\r
 \r
 : rfc3339>timestamp ( str -- timestamp )\r
     [ (rfc3339>timestamp) ] with-string-reader ;\r
 \r
+: (ymdhms>timestamp) ( -- timestamp )\r
+    read-ymd " " expect read-hms 0 <timestamp> ;\r
+\r
+: ymdhms>timestamp ( str -- timestamp )\r
+    [ (ymdhms>timestamp) ] with-string-reader ;\r
+\r
+: (hms>timestamp) ( -- timestamp )\r
+    f f f read-hms f <timestamp> ;\r
+\r
+: hms>timestamp ( str -- timestamp )\r
+    [ (hms>timestamp) ] with-string-reader ;\r
+\r
+: (ymd>timestamp) ( -- timestamp )\r
+    read-ymd f f f f <timestamp> ;\r
+\r
+: ymd>timestamp ( str -- timestamp )\r
+    [ (ymd>timestamp) ] with-string-reader ;\r
+\r
+: (timestamp>ymd) ( timestamp -- )\r
+    dup timestamp-year write-0000\r
+    "-" write\r
+    dup timestamp-month write-00\r
+    "-" write\r
+    timestamp-day write-00 ;\r
+\r
+: timestamp>ymd ( timestamp -- str )\r
+    [ (timestamp>ymd) ] with-string-writer ;\r
+\r
+: (timestamp>hms)\r
+    dup timestamp-hour write-00\r
+    ":" write\r
+    dup timestamp-minute write-00\r
+    ":" write\r
+    timestamp-second >integer write-00 ;\r
+\r
+: timestamp>hms ( timestamp -- str )\r
+    [ (timestamp>hms) ] with-string-writer ;\r
+\r
+: timestamp>ymdhms ( timestamp -- str )\r
+    >gmt\r
+    [\r
+        dup (timestamp>ymd)\r
+        " " write\r
+        (timestamp>hms)\r
+    ] with-string-writer ;\r
+\r
 : file-time-string ( timestamp -- string )\r
     [\r
         [ month>> month-abbreviations nth write ] keep bl\r
index e834144d0c2d603603f30e66a85587c4cc6ea993..170d9a60f12f1723fa08b3b850e2814b7225f403 100755 (executable)
@@ -34,7 +34,7 @@ HOOK: db-close db ( handle -- )
 TUPLE: statement handle sql in-params out-params bind-params bound? ;
 TUPLE: simple-statement ;
 TUPLE: prepared-statement ;
-TUPLE: result-set sql params handle n max ;
+TUPLE: result-set sql in-params out-params handle n max ;
 : <statement> ( sql in out -- statement )
     { (>>sql) (>>in-params) (>>out-params) } statement construct ;
 
@@ -47,6 +47,7 @@ GENERIC: query-results ( query -- result-set )
 GENERIC: #rows ( result-set -- n )
 GENERIC: #columns ( result-set -- n )
 GENERIC# row-column 1 ( result-set n -- obj )
+GENERIC# row-column-typed 1 ( result-set n -- sql )
 GENERIC: advance-row ( result-set -- )
 GENERIC: more-rows? ( result-set -- ? )
 
@@ -67,13 +68,16 @@ GENERIC: more-rows? ( result-set -- ? )
     0 >>n drop ;
 
 : <result-set> ( query handle tuple -- result-set )
-    >r >r { sql>> in-params>> } get-slots r>
-    { (>>sql) (>>params) (>>handle) } result-set
+    >r >r { sql>> in-params>> out-params>> } get-slots r>
+    { (>>sql) (>>in-params) (>>out-params) (>>handle) } result-set
     construct r> construct-delegate ;
 
 : sql-row ( result-set -- seq )
     dup #columns [ row-column ] with map ;
 
+: sql-row-typed ( result-set -- seq )
+    dup #columns [ row-column-typed ] with map ;
+
 : query-each ( statement quot -- )
     over more-rows? [
         [ call ] 2keep over advance-row query-each
index 648d8493dcb64925176ae3f07e8fcc46472261de..f11f1e2ba634722579e5033061c4d544b62e5994 100755 (executable)
@@ -2,7 +2,9 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien.c-types arrays assocs kernel math math.parser
 namespaces sequences db.sqlite.ffi db combinators
-continuations db.types ;
+continuations db.types calendar.format serialize
+io.streams.string byte-arrays ;
+USE: tools.walker
 IN: db.sqlite.lib
 
 : sqlite-error ( n -- * )
@@ -55,6 +57,10 @@ IN: db.sqlite.lib
 : sqlite-bind-null ( handle i -- )
     sqlite3_bind_null sqlite-check-result ;
 
+: sqlite-bind-blob ( handle i byte-array -- )
+    dup length SQLITE_TRANSIENT
+    sqlite3_bind_blob sqlite-check-result ;
+
 : sqlite-bind-text-by-name ( handle name text -- )
     parameter-index sqlite-bind-text ;
 
@@ -67,20 +73,32 @@ IN: db.sqlite.lib
 : sqlite-bind-double-by-name ( handle name double -- )
     parameter-index sqlite-bind-double ;
 
+: sqlite-bind-blob-by-name ( handle name blob -- )
+    parameter-index sqlite-bind-blob ;
+
 : sqlite-bind-null-by-name ( handle name obj -- )
     parameter-index drop sqlite-bind-null ;
 
 : sqlite-bind-type ( handle key value type -- )
+    over [ drop NULL ] unless
     dup array? [ first ] when
     {
         { INTEGER [ sqlite-bind-int-by-name ] }
-        { BIG_INTEGER [ sqlite-bind-int64-by-name ] }
+        { BIG-INTEGER [ sqlite-bind-int64-by-name ] }
         { TEXT [ sqlite-bind-text-by-name ] }
         { VARCHAR [ sqlite-bind-text-by-name ] }
         { DOUBLE [ sqlite-bind-double-by-name ] }
-        { TIMESTAMP [ sqlite-bind-double-by-name ] }
+        { DATE [ sqlite-bind-text-by-name ] }
+        { TIME [ sqlite-bind-text-by-name ] }
+        { DATETIME [ sqlite-bind-text-by-name ] }
+        { TIMESTAMP [ sqlite-bind-text-by-name ] }
+        { BLOB [ sqlite-bind-blob-by-name ] }
+        { FACTOR-BLOB [
+            [ serialize ] with-string-writer >byte-array
+            sqlite-bind-blob-by-name
+        ] }
         { +native-id+ [ sqlite-bind-int-by-name ] }
-        { NULL [ sqlite-bind-null-by-name ] }
+        { NULL [ sqlite-bind-null-by-name ] }
         [ no-sql-type ]
     } case ;
 
@@ -93,21 +111,38 @@ IN: db.sqlite.lib
 : sqlite-#columns ( query -- int )
     sqlite3_column_count ;
 
-! TODO
 : sqlite-column ( handle index -- string )
     sqlite3_column_text ;
 
+: sqlite-column-blob ( handle index -- byte-array/f )
+    [ sqlite3_column_bytes ] 2keep
+    pick zero? [
+        3drop f
+    ] [
+        sqlite3_column_blob swap memory>byte-array
+    ] if ;
+
 : sqlite-column-typed ( handle index type -- obj )
+    dup array? [ first ] when
     {
+        { +native-id+ [ sqlite3_column_int64 ] }
         { INTEGER [ sqlite3_column_int ] }
-        { BIG_INTEGER [ sqlite3_column_int64 ] }
+        { BIG-INTEGER [ sqlite3_column_int64 ] }
         { TEXT [ sqlite3_column_text ] }
+        { VARCHAR [ sqlite3_column_text ] }
         { DOUBLE [ sqlite3_column_double ] }
-        { TIMESTAMP [ sqlite3_column_double ] }
+        { DATE [ sqlite3_column_text dup [ ymd>timestamp ] when ] }
+        { TIME [ sqlite3_column_text dup [ hms>timestamp ] when ] }
+        { TIMESTAMP [ sqlite3_column_text dup [ ymdhms>timestamp ] when ] }
+        { DATETIME [ sqlite3_column_text dup [ ymdhms>timestamp ] when ] }
+        { BLOB [ sqlite-column-blob ] }
+        { FACTOR-BLOB [
+            sqlite-column-blob [ deserialize ] with-string-reader
+        ] }
+        ! { NULL [ 2drop f ] }
         [ no-sql-type ]
     } case ;
 
-! TODO
 : sqlite-row ( handle -- seq )
     dup sqlite-#columns [ sqlite-column ] with map ;
 
index 08139610a05d2a9e69e0d06075931ce18a885108..b30cb4ba80f3d7bb1fb528db68cfa669f74706f9 100755 (executable)
@@ -3,7 +3,7 @@ prettyprint tools.test db.sqlite db sequences
 continuations db.types db.tuples unicode.case ;
 IN: db.sqlite.tests
 
-: db-path "extra/db/sqlite/test.db" resource-path ;
+: db-path "test.db" temp-file ;
 : test.db db-path sqlite-db ;
 
 [ ] [ [ db-path delete-file ] ignore-errors ] unit-test
index 62f5717c84e494996d01feb09c2c8233b9845d0d..d0bf721aa75b5322162f90da8ead3e52abc7f7aa 100755 (executable)
@@ -5,7 +5,7 @@ hashtables io.files kernel math math.parser namespaces
 prettyprint sequences strings tuples alien.c-types
 continuations db.sqlite.lib db.sqlite.ffi db.tuples
 words combinators.lib db.types combinators tools.walker
-combinators.cleave io ;
+combinators.cleave io namespaces.lib ;
 IN: db.sqlite
 
 TUPLE: sqlite-db path ;
@@ -80,8 +80,9 @@ M: sqlite-result-set #columns ( result-set -- n )
 M: sqlite-result-set row-column ( result-set n -- obj )
     >r result-set-handle r> sqlite-column ;
 
-M: sqlite-result-set row-column-typed ( result-set n type -- obj )
-    >r result-set-handle r> sqlite-column-typed ;
+M: sqlite-result-set row-column-typed ( result-set n -- obj )
+    dup pick result-set-out-params nth sql-spec-type
+    >r >r result-set-handle r> r> sqlite-column-typed ;
 
 M: sqlite-result-set advance-row ( result-set -- )
     [ result-set-handle sqlite-next ] keep
@@ -141,6 +142,10 @@ M: sqlite-db <insert-assigned-statement> ( tuple -- statement )
     " where " 0%
     find-primary-key dup sql-spec-column-name 0% " = " 0% bind% ;
 
+: where-clause ( specs -- )
+    " where " 0%
+    [ " and " 0% ] [ dup sql-spec-column-name 0% " = " 0% bind% ] interleave ;
+
 M: sqlite-db <update-tuple-statement> ( class -- statement )
     [
         "update " 0%
@@ -173,14 +178,7 @@ M: sqlite-db <select-by-slots-statement> ( tuple class -- statement )
 
         " from " 0% 0%
         [ sql-spec-slot-name swap get-slot-named ] with subset
-        dup empty? [
-            drop
-        ] [
-            " where " 0%
-            [ ", " 0% ]
-            [ dup sql-spec-column-name 0% " = " 0% bind% ] interleave
-        ] if
-        ";" 0%
+        dup empty? [ drop ] [ where-clause ] if ";" 0%
     ] sqlite-make ;
 
 M: sqlite-db modifier-table ( -- hashtable )
@@ -209,8 +207,13 @@ M: sqlite-db type-table ( -- assoc )
         { INTEGER "integer" }
         { TEXT "text" }
         { VARCHAR "text" }
+        { DATE "date" }
+        { TIME "time" }
+        { DATETIME "datetime" }
         { TIMESTAMP "timestamp" }
         { DOUBLE "real" }
+        { BLOB "blob" }
+        { FACTOR-BLOB "blob" }
     } ;
 
 M: sqlite-db create-type-table
diff --git a/extra/db/sqlite/test.db b/extra/db/sqlite/test.db
deleted file mode 100644 (file)
index e483c47..0000000
Binary files a/extra/db/sqlite/test.db and /dev/null differ
index 517f8bcc36a60ca0f9048072fcb531bcc679c462..5913f053da1cc417cd3b9928eab98e54c74238f8 100755 (executable)
@@ -1,40 +1,47 @@
 ! Copyright (C) 2008 Doug Coleman.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: io.files kernel tools.test db db.tuples
-db.types continuations namespaces db.postgresql math
-prettyprint tools.walker db.sqlite ;
+db.types continuations namespaces math
+prettyprint tools.walker db.sqlite calendar
+math.intervals ;
 IN: db.tuples.tests
 
-TUPLE: person the-id the-name the-number the-real ;
-: <person> ( name age real -- person )
+TUPLE: person the-id the-name the-number the-real ts date time blob ;
+: <person> ( name age real ts date time blob -- person )
     {
         set-person-the-name
         set-person-the-number
         set-person-the-real
+        set-person-ts
+        set-person-date
+        set-person-time
+        set-person-blob
     } person construct ;
 
-: <assigned-person> ( id name number the-real -- obj )
+: <assigned-person> ( id name age real ts date time blob -- person )
     <person> [ set-person-the-id ] keep ;
 
-SYMBOL: the-person1
-SYMBOL: the-person2
+SYMBOL: person1
+SYMBOL: person2
+SYMBOL: person3
+SYMBOL: person4
 
 : test-tuples ( -- )
     [ person drop-table ] [ drop ] recover
     [ ] [ person create-table ] unit-test
     [ person create-table ] must-fail
     
-    [ ] [ the-person1 get insert-tuple ] unit-test
+    [ ] [ person1 get insert-tuple ] unit-test
 
-    [ 1 ] [ the-person1 get person-the-id ] unit-test
+    [ 1 ] [ person1 get person-the-id ] unit-test
 
-    200 the-person1 get set-person-the-number
+    200 person1 get set-person-the-number
 
-    [ ] [ the-person1 get update-tuple ] unit-test
+    [ ] [ person1 get update-tuple ] unit-test
 
     [ T{ person f 1 "billy" 200 3.14 } ]
     [ T{ person f 1 } select-tuple ] unit-test
-    [ ] [ the-person2 get insert-tuple ] unit-test
+    [ ] [ person2 get insert-tuple ] unit-test
     [
         {
             T{ person f 1 "billy" 200 3.14 }
@@ -48,9 +55,33 @@ SYMBOL: the-person2
         }
     ] [ T{ person f } select-tuples ] unit-test
 
+    [
+        {
+            T{ person f 2 "johnny" 10 3.14 }
+        }
+    ] [ T{ person f f f 10 3.14 } select-tuples ] unit-test
 
-    [ ] [ the-person1 get delete-tuple ] unit-test
+
+    [ ] [ person1 get delete-tuple ] unit-test
     [ f ] [ T{ person f 1 } select-tuple ] unit-test
+
+    [ ] [ person3 get insert-tuple ] unit-test
+
+    [
+        T{
+            person
+            f
+            3
+            "teddy"
+            10
+            3.14
+            T{ timestamp f 2008 3 5 16 24 11 0 }
+            T{ timestamp f 2008 11 22 f f f f }
+            T{ timestamp f f f f 12 34 56 f }
+            B{ 115 116 111 114 101 105 110 97 98 108 111 98 }
+        }
+    ] [ T{ person f 3 } select-tuple ] unit-test
+
     [ ] [ person drop-table ] unit-test ;
 
 : make-native-person-table ( -- )
@@ -67,9 +98,14 @@ SYMBOL: the-person2
         { "the-name" "NAME" { VARCHAR 256 } +not-null+ }
         { "the-number" "AGE" INTEGER { +default+ 0 } }
         { "the-real" "REAL" DOUBLE { +default+ 0.3 } }
+        { "ts" "TS" TIMESTAMP }
+        { "date" "D" DATE }
+        { "time" "T" TIME }
+        { "blob" "B" BLOB }
     } define-persistent
-    "billy" 10 3.14 <person> the-person1 set
-    "johnny" 10 3.14 <person> the-person2 set ;
+    "billy" 10 3.14 f f f f <person> person1 set
+    "johnny" 10 3.14 f f f f <person> person2 set
+    "teddy" 10 3.14 "2008-03-05 16:24:11" "2008-11-22" "12:34:56" B{ 115 116 111 114 101 105 110 97 98 108 111 98 } <person> person3 set ;
 
 : assigned-person-schema ( -- )
     person "PERSON"
@@ -78,10 +114,14 @@ SYMBOL: the-person2
         { "the-name" "NAME" { VARCHAR 256 } +not-null+ }
         { "the-number" "AGE" INTEGER { +default+ 0 } }
         { "the-real" "REAL" DOUBLE { +default+ 0.3 } }
+        { "ts" "TS" TIMESTAMP }
+        { "date" "D" DATE }
+        { "time" "T" TIME }
+        { "blob" "B" BLOB }
     } define-persistent
-    1 "billy" 10 3.14 <assigned-person> the-person1 set
-    2 "johnny" 10 3.14 <assigned-person> the-person2 set ;
-
+    1 "billy" 10 3.14 f f f f <assigned-person> person1 set
+    2 "johnny" 10 3.14 f f f f <assigned-person> person2 set
+    3 "teddy" 10 3.14 "2008-03-05 16:24:11" "2008-11-22" "12:34:56" B{ 115 116 111 114 101 105 110 97 98 108 111 98 } <assigned-person> person3 set ;
 
 TUPLE: paste n summary author channel mode contents timestamp annotations ;
 TUPLE: annotation n paste-id summary author mode contents ;
@@ -118,14 +158,54 @@ TUPLE: annotation n paste-id summary author mode contents ;
     ! [ ] [ annotation create-table ] unit-test
 ! ] with-db
 
-
 : test-sqlite ( quot -- )
-    >r "tuples-test.db" resource-path sqlite-db r> with-db ;
+    >r "tuples-test.db" temp-file sqlite-db r> with-db ;
 
-: test-postgresql ( -- )
-    >r { "localhost" "postgres" "" "factor-test" } postgresql-db r> with-db ;
+: test-postgresql ( -- )
+!    >r { "localhost" "postgres" "" "factor-test" } postgresql-db r> with-db ;
 
 [ native-person-schema test-tuples ] test-sqlite
 [ assigned-person-schema test-tuples ] test-sqlite
 
-! [ make-native-person-table ] test-sqlite
+TUPLE: serialize-me id data ;
+
+: test-serialize ( -- )
+    serialize-me "SERIALIZED"
+    {
+        { "id" "ID" +native-id+ }
+        { "data" "DATA" FACTOR-BLOB }
+    } define-persistent
+    [ serialize-me drop-table ] [ drop ] recover
+    [ ] [ serialize-me create-table ] unit-test
+
+    [ ] [ T{ serialize-me f f H{ { 1 2 } } } insert-tuple ] unit-test
+    [
+        { T{ serialize-me f 1 H{ { 1 2 } } } }
+    ] [ T{ serialize-me f 1 } select-tuples ] unit-test ;
+
+! [ test-serialize ] test-sqlite
+
+TUPLE: exam id name score ; 
+
+: test-ranges ( -- )
+    exam "EXAM"
+    {
+        { "id" "ID" +native-id+ }
+        { "name" "NAME" TEXT }
+        { "score" "SCORE" INTEGER }
+    } define-persistent
+    [ exam drop-table ] [ drop ] recover
+    [ ] [ exam create-table ] unit-test
+
+    [ ] [ T{ exam f f "Kyle" 100 } insert-tuple ] unit-test
+    [ ] [ T{ exam f f "Stan" 80 } insert-tuple ] unit-test
+    [ ] [ T{ exam f f "Kenny" 60 } insert-tuple ] unit-test
+    [ ] [ T{ exam f f "Cartman" 41 } insert-tuple ] unit-test
+
+    [
+        T{ exam f 3 "Kenny" 60 }
+        T{ exam f 4 "Cartman" 41 }
+    ] [ T{ exam f 4 f T{ interval f { 0 t } { 70 t } } } select-tuples ] unit-test
+    ;
+
+! [ test-ranges ] test-sqlite
index d61fe8135ee97a71c47b3dd4d8103bedcb73187b..32055ccedc35b84795238362e3f6678cbc709ce2 100755 (executable)
@@ -37,27 +37,24 @@ HOOK: <delete-tuples-statement> db ( class -- obj )
 
 HOOK: <select-by-slots-statement> db ( tuple -- tuple )
 
-HOOK: row-column-typed db ( result-set n type -- sql )
 HOOK: insert-tuple* db ( tuple statement -- )
 
 : resulting-tuple ( row out-params -- tuple )
     dup first sql-spec-class construct-empty [
         [
-            >r [ sql-spec-type sql-type>factor-type ] keep
-            sql-spec-slot-name r> set-slot-named
+            >r sql-spec-slot-name r> set-slot-named
         ] curry 2each
     ] keep ;
 
 : query-tuples ( statement -- seq )
     [ statement-out-params ] keep query-results [
-        [ sql-row swap resulting-tuple ] with query-map
+        [ sql-row-typed swap resulting-tuple ] with query-map
     ] with-disposal ;
  
 : query-modify-tuple ( tuple statement -- )
-    [ query-results [ sql-row ] with-disposal ] keep
+    [ query-results [ sql-row-typed ] with-disposal ] keep
     statement-out-params rot [
-        >r [ sql-spec-type sql-type>factor-type ] keep
-        sql-spec-slot-name r> set-slot-named
+        >r sql-spec-slot-name r> set-slot-named
     ] curry 2each ;
 
 : sql-props ( class -- columns table )
index c84b23c50f274794837f3c36014f5cb9c2f2b283..023c72cd2d08e9641641a480b5b8a8f317eeac96 100755 (executable)
@@ -3,7 +3,8 @@
 USING: arrays assocs db kernel math math.parser
 sequences continuations sequences.deep sequences.lib
 words namespaces tools.walker slots slots.private classes
-mirrors tuples combinators ;
+mirrors tuples combinators calendar.format serialize
+io.streams.string ;
 IN: db.types
 
 HOOK: modifier-table db ( -- hash )
@@ -60,14 +61,19 @@ SYMBOL: +has-many+
 : relation? ( spec -- ? ) [ +has-many+ = ] deep-find ;
 
 SYMBOL: INTEGER
-SYMBOL: BIG_INTEGER
+SYMBOL: BIG-INTEGER
 SYMBOL: DOUBLE
 SYMBOL: REAL
 SYMBOL: BOOLEAN
 SYMBOL: TEXT
 SYMBOL: VARCHAR
-SYMBOL: TIMESTAMP
 SYMBOL: DATE
+SYMBOL: TIME
+SYMBOL: DATETIME
+SYMBOL: TIMESTAMP
+SYMBOL: BLOB
+SYMBOL: FACTOR-BLOB
+SYMBOL: NULL
 
 : spec>tuple ( class spec -- tuple )
     [ ?first3 ] keep 3 ?tail*
@@ -80,15 +86,6 @@ SYMBOL: DATE
     } sql-spec construct
     dup normalize-spec ;
 
-: sql-type-hash ( -- assoc )
-    H{
-        { INTEGER "integer" }
-        { TEXT "text" }
-        { VARCHAR "varchar" }
-        { DOUBLE "real" }
-        { TIMESTAMP "timestamp" }
-    } ;
-
 TUPLE: no-sql-type ;
 : no-sql-type ( -- * ) T{ no-sql-type } throw ;
 
@@ -156,33 +153,6 @@ TUPLE: no-sql-modifier ;
     [ lookup-modifier ] map " " join
     dup empty? [ " " swap append ] unless ;
 
-SYMBOL: building-seq 
-: get-building-seq ( n -- seq )
-    building-seq get nth ;
-
-: n, get-building-seq push ;
-: n% get-building-seq push-all ;
-: n# >r number>string r> n% ;
-
-: 0, 0 n, ;
-: 0% 0 n% ;
-: 0# 0 n# ;
-: 1, 1 n, ;
-: 1% 1 n% ;
-: 1# 1 n# ;
-: 2, 2 n, ;
-: 2% 2 n% ;
-: 2# 2 n# ;
-
-: nmake ( quot exemplars -- seqs )
-    dup length dup zero? [ 1+ ] when
-    [
-        [
-            [ drop 1024 swap new-resizable ] 2map
-            [ building-seq set call ] keep
-        ] 2keep >r [ like ] 2map r> firstn 
-    ] with-scope ;
-
 HOOK: bind% db ( spec -- )
 
 TUPLE: no-slot-named ;
@@ -210,15 +180,3 @@ TUPLE: no-slot-named ;
         >r dup sql-spec-type swap sql-spec-slot-name r>
         get-slot-named swap
     ] curry { } map>assoc ;
-
-: sql-type>factor-type ( obj type -- obj )
-    dup array? [ first ] when
-    {
-        { +native-id+ [ string>number ] }
-        { INTEGER [ string>number ] }
-        { DOUBLE [ string>number ] }
-        { REAL [ string>number ] }
-        { TEXT [ ] }
-        { VARCHAR [ ] }
-        [ "no conversion from sql type to factor type" throw ]
-    } case ;
index 4c51e7ddfbc72ff9265c570da6093e22b5801cf6..f96931c412920ad5f255b2045242e2f8918aef2b 100755 (executable)
@@ -1,4 +1,4 @@
-USING: help.markup help.syntax libc kernel ;
+USING: help.markup help.syntax libc kernel continuations ;
 IN: destructors
 
 HELP: free-always
@@ -23,7 +23,7 @@ HELP: close-later
 
 HELP: with-destructors
 { $values { "quot" "a quotation" } }
-{ $description "Calls a quotation within a new dynamic scope.  This quotation may register destructors, on any object, by wrapping the object in a destructor and implementing " { $link destruct } " on that object type.  After the quotation finishes, if an error was thrown, all destructors are called and the error is then rethrown.  However, if the quotation was successful, only those destructors created with an 'always cleanup' flag will be destroyed." }
+{ $description "Calls a quotation within a new dynamic scope.  This quotation may register destructors, on any object, by wrapping the object in a destructor and implementing " { $link dispose } " on that object type.  After the quotation finishes, if an error was thrown, all destructors are called and the error is then rethrown.  However, if the quotation was successful, only those destructors created with an 'always cleanup' flag will be destroyed." }
 { $notes "Destructors are not allowed to throw exceptions.  No exceptions." }
 { $examples
     { $code "[ 10 malloc free-always ] with-destructors" }
index 09b4ccc35757c792f296aeea86aa9c634e1f70b9..147e1836881585f978b55a6b3a0b9b60005c3374 100755 (executable)
@@ -9,7 +9,7 @@ TUPLE: dummy-destructor obj ;
 
 C: <dummy-destructor> dummy-destructor
 
-M: dummy-destructor destruct ( obj -- )
+M: dummy-destructor dispose ( obj -- )
     dummy-destructor-obj t swap set-dummy-obj-destroyed? ;
 
 : destroy-always
index 0f8ec3af84939c67d9145952864e9bfd9c1cad9a..b2561c74395af64d16c2392b2c43da1ea36cdf10 100755 (executable)
@@ -4,18 +4,16 @@ USING: continuations io.backend libc kernel namespaces
 sequences system vectors ;
 IN: destructors
 
-GENERIC: destruct ( obj -- )
-
 SYMBOL: error-destructors
 SYMBOL: always-destructors
 
 TUPLE: destructor object destroyed? ;
 
-M: destructor destruct
+M: destructor dispose
     dup destructor-destroyed? [
         drop
     ] [
-        dup destructor-object destruct
+        dup destructor-object dispose 
         t swap set-destructor-destroyed?
     ] if ;
 
@@ -29,10 +27,10 @@ M: destructor destruct
     <destructor> always-destructors get push ;
 
 : do-always-destructors ( -- )
-    always-destructors get [ destruct ] each ;
+    always-destructors get [ dispose ] each ;
 
 : do-error-destructors ( -- )
-    error-destructors get [ destruct ] each ;
+    error-destructors get [ dispose ] each ;
 
 : with-destructors ( quot -- )
     [
@@ -47,7 +45,7 @@ TUPLE: memory-destructor alien ;
 
 C: <memory-destructor> memory-destructor
 
-M: memory-destructor destruct ( obj -- )
+M: memory-destructor dispose ( obj -- )
     memory-destructor-alien free ;
 
 : free-always ( alien -- )
@@ -63,7 +61,7 @@ C: <handle-destructor> handle-destructor
 
 HOOK: destruct-handle io-backend ( obj -- )
 
-M: handle-destructor destruct ( obj -- )
+M: handle-destructor dispose ( obj -- )
     handle-destructor-alien destruct-handle ;
 
 : close-always ( handle -- )
@@ -79,7 +77,7 @@ C: <socket-destructor> socket-destructor
 
 HOOK: destruct-socket io-backend ( obj -- )
 
-M: socket-destructor destruct ( obj -- )
+M: socket-destructor dispose ( obj -- )
     socket-destructor-alien destruct-socket ;
 
 : close-socket-always ( handle -- )
index ed579dde42b838e3d704f2e9bd70345ca939a589..3ce2c4019242db492235b64b15b40a9a979c59d8 100644 (file)
@@ -1,9 +1,10 @@
-! Copyright (C) 2004, 2007 Slava Pestov.
+! Copyright (C) 2004, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays definitions io kernel math
 namespaces parser prettyprint sequences strings words
-editors io.files io.sockets io.streams.string io.binary
-math.parser io.encodings.ascii ;
+editors io.files io.sockets io.streams.byte-array io.binary
+math.parser io.encodings.ascii io.encodings.binary
+io.encodings.utf8 ;
 IN: editors.jedit
 
 : jedit-server-info ( -- port auth )
@@ -14,17 +15,17 @@ IN: editors.jedit
     ] with-file-reader ;
 
 : make-jedit-request ( files -- code )
-    [
+    utf8 [
         "EditServer.handleClient(false,false,false," write
         cwd pprint
         "," write
         "new String[] {" write
         [ pprint "," write ] each
         "null});\n" write
-    ] with-string-writer ;
+    ] with-byte-writer ;
 
 : send-jedit-request ( request -- )
-    jedit-server-info swap "localhost" swap <inet> <client> [
+    jedit-server-info "localhost" rot <inet> binary <client> [
         4 >be write
         dup length 2 >be write
         write
index 2e0d9832b0f6f594d85c20ee3f45f89d6bea83cf..f4b3025fcd2b93eebb306871f2b5aa6c6c0bffdf 100755 (executable)
@@ -42,3 +42,7 @@ IN: farkup.tests
 
 [ "<p><strong>foo</strong>\n</p><h1>aheading</h1>\n<p>adfasd</p>" ]
 [ "*foo*\n=aheading=\nadfasd" convert-farkup ] unit-test
+
+[ "<p>=foo\n</p>" ] [ "=foo\n" convert-farkup ] unit-test
+[ "<h1>foo</h1>\n" ] [ "=foo=\n" convert-farkup ] unit-test
+[ "<p>lol</p><h1>foo</h1>\n" ] [ "lol=foo=\n" convert-farkup ] unit-test
diff --git a/extra/fry/fry-docs.factor b/extra/fry/fry-docs.factor
new file mode 100755 (executable)
index 0000000..31b544d
--- /dev/null
@@ -0,0 +1,108 @@
+USING: help.markup help.syntax quotations kernel ;\r
+IN: fry\r
+\r
+HELP: ,\r
+{ $description "Fry specifier. Inserts a literal value into the fried quotation." } ;\r
+\r
+HELP: @\r
+{ $description "Fry specifier. Splices a quotation into the fried quotation." } ;\r
+\r
+HELP: _\r
+{ $description "Fry specifier. Shifts all fry specifiers to the left down by one stack position." } ;\r
+\r
+HELP: fry\r
+{ $values { "quot" quotation } { "quot'" quotation } }\r
+{ $description "Outputs a quotation that when called, fries " { $snippet "quot" } " by taking values from the stack and substituting them in." }\r
+{ $notes "This word is used to implement " { $link POSTPONE: '[ } "; the following two lines are equivalent:"\r
+    { $code "[ X ] fry call" "'[ X ]" }\r
+} ;\r
+\r
+HELP: '[\r
+{ $syntax "code... ]" }\r
+{ $description "Literal fried quotation. Expands into code which takes values from the stack and substituting them in." } ;\r
+\r
+ARTICLE: "fry.examples" "Examples of fried quotations"\r
+"Conceptually, " { $link fry } " is tricky however the general idea is easy to grasp once presented with examples."\r
+$nl\r
+"If a quotation does not contain any fry specifiers, then " { $link POSTPONE: '[ } " behaves just like " { $link POSTPONE: [ } ":"\r
+{ $code "{ 10 20 30 } '[ . ] each" }\r
+"Occurrences of " { $link , } " on the left map directly to " { $link curry } ". That is, the following three lines are equivalent:"\r
+{ $code \r
+    "{ 10 20 30 } 5 '[ , + ] map"\r
+    "{ 10 20 30 } 5 [ + ] curry map"\r
+    "{ 10 20 30 } [ 5 + ] map"\r
+}\r
+"Occurrences of " { $link , } " in the middle of a quotation map to more complex quotation composition patterns. The following three lines are equivalent:"\r
+{ $code \r
+    "{ 10 20 30 } 5 '[ 3 , / ] map"\r
+    "{ 10 20 30 } 5 [ 3 ] swap [ / ] curry compose map"\r
+    "{ 10 20 30 } [ 3 5 / ] map"\r
+}\r
+"Occurrences of " { $link @ } " are simply syntax sugar for " { $snippet ", call" } ". The following three lines are equivalent:"\r
+{ $code \r
+    "{ 10 20 30 } [ sq ] '[ @ . ] map"\r
+    "{ 10 20 30 } [ sq ] [ . ] compose map"\r
+    "{ 10 20 30 } [ sq . ] map"\r
+}\r
+"The " { $link , } " and " { $link @ } " specifiers may be freely mixed:"\r
+{ $code\r
+    "{ 8 13 14 27 } [ even? ] 5 [ @ dup , ? ] map"\r
+    "{ 8 13 14 27 } [ even? ] 5 [ dup ] swap [ ? ] curry 3compose map"\r
+    "{ 8 13 14 27 } [ even? dup 5 ? ] map"\r
+}\r
+"Occurrences of " { $link _ } " have the effect of enclosing all code to their left with " { $link >r } " and " { $link r> } ":"\r
+{ $code \r
+    "{ 10 20 30 } 1 '[ , _ / ] map"\r
+    "{ 10 20 30 } 1 [ swap / ] curry map"\r
+    "{ 10 20 30 } [ 1 swap / ] map"\r
+}\r
+"For any quotation body " { $snippet "X" } ", the following two are equivalent:"\r
+{ $code\r
+    "[ >r X r> ]"\r
+    "[ X _ ]"\r
+}\r
+"Here are some built-in combinators rewritten in terms of fried quotations:"\r
+{ $table\r
+    { { $link literalize } { $snippet ": literalize '[ , ] ;" } }\r
+    { { $link slip } { $snippet ": slip '[ @ , ] call ;" } }\r
+    { { $link dip } { $snippet ": dip '[ @ _ ] call ;" } }\r
+    { { $link curry } { $snippet ": curry '[ , @ ] ;" } }\r
+    { { $link with } { $snippet ": with swapd '[ , _ @ ] ;" } }\r
+    { { $link compose } { $snippet ": compose '[ @ @ ] ;" } }\r
+    { { $link 2apply } { $snippet ": 2apply tuck '[ , @ , @ ] call ;" } }\r
+} ;\r
+\r
+ARTICLE: "fry.philosophy" "Fried quotation philosophy"\r
+"Fried quotations generalize quotation-building words such as " { $link curry } " and " { $link compose } "."\r
+$nl\r
+"There is a mapping from fried quotations to lexical closures as defined in the " { $vocab-link "locals" } " vocabulary. Namely, a fried quotation is equivalent to a ``let'' form where each local binding is only used once, and bindings are used in the same order in which they are defined. The following two lines are equivalent:"\r
+{ $code\r
+    "'[ 3 , + 4 , / ]"\r
+    "[let | a [ ] b [ ] | [ 3 a + 4 b / ] ]"\r
+}\r
+"The " { $link _ } " fry specifier has no direct analogue in " { $vocab-link "locals" } ", however closure conversion together with the " { $link dip } " combinator achieve the same effect:"\r
+{ $code\r
+    "'[ , 2 + , * _ / ]"\r
+    "[let | a [ ] b [ ] | [ [ a 2 + b * ] dip / ] ]"\r
+} ;\r
+\r
+ARTICLE: "fry.limitations" "Fried quotation limitations"\r
+"As with " { $link "locals" } ", fried quotations cannot contain " { $link >r } " and " { $link r> } ". Unlike " { $link "locals" } ", using " { $link dip } " is not a suitable workaround since unlike closure conversion, fry conversion is not recursive, and so the quotation passed to " { $link dip } " cannot contain fry specifiers." ;\r
+\r
+ARTICLE: "fry" "Fried quotations"\r
+"A " { $emphasis "fried quotation" } " differs from a literal quotation in that when it is evaluated, instead of just pushing itself on the stack, it consumes zero or more stack values and inserts them into the quotation."\r
+$nl\r
+"Fried quotations are denoted with a special parsing word:"\r
+{ $subsection POSTPONE: '[ }\r
+"Fried quotations contain zero or more " { $emphasis "fry specifiers" } ":"\r
+{ $subsection , }\r
+{ $subsection @ }\r
+{ $subsection _ }\r
+"When a fried quotation is being evaluated, values are consumed from the stack and spliced into the quotation from right to left."\r
+{ $subsection "fry.examples" }\r
+{ $subsection "fry.philosophy" }\r
+{ $subsection "fry.limitations" }\r
+"Quotations can also be fried without using a parsing word:"\r
+{ $subsection fry } ;\r
+\r
+ABOUT: "fry"\r
diff --git a/extra/furnace/authors.txt b/extra/furnace/authors.txt
deleted file mode 100644 (file)
index f372b57..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Slava Pestov
-Doug Coleman
diff --git a/extra/furnace/furnace-tests.factor b/extra/furnace/furnace-tests.factor
deleted file mode 100755 (executable)
index d8124d1..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-USING: kernel sequences namespaces math tools.test furnace furnace.validator ;
-IN: furnace.tests
-
-TUPLE: test-tuple m n ;
-
-[ H{ { "m" 3 } { "n" 2 } } ]
-[
-    [ T{ test-tuple f 3 2 } explode-tuple ] H{ } make-assoc
-] unit-test
-
-[
-    { 3 }
-] [
-    H{ { "n" "3" } } { { "n" v-number } }
-    [ action-param drop ] with map
-] unit-test
-
-: foo ;
-
-\ foo { { "foo" "2" v-default } { "bar" v-required } } define-action
-
-[ t ] [ [ 1 2 foo ] action-call? ] unit-test
-[ f ] [ [ 2 + ] action-call? ] unit-test
-
-[
-    { "2" "hello" }
-] [
-    [
-        H{
-            { "bar" "hello" }
-        } \ foo query>seq
-    ] with-scope
-] unit-test
-
-[
-    H{ { "foo" "1" } { "bar" "2" } }
-] [
-    { "1" "2" } \ foo quot>query
-] unit-test
-
-[
-    "/responder/furnace.tests/foo?foo=3"
-] [
-    [
-        [ "3" foo ] quot-link
-    ] with-scope
-] unit-test
diff --git a/extra/furnace/furnace.factor b/extra/furnace/furnace.factor
deleted file mode 100755 (executable)
index 851e1e6..0000000
+++ /dev/null
@@ -1,217 +0,0 @@
-! Copyright (C) 2006, 2008 Slava Pestov, Doug Coleman
-! See http://factorcode.org/license.txt for BSD license.
-USING: arrays assocs calendar debugger furnace.sessions
-furnace.validator hashtables heaps html.elements http
-http.server.responders http.server.templating io.files kernel
-math namespaces quotations sequences splitting words strings
-vectors webapps.callback continuations tuples classes vocabs
-html io io.encodings.binary ;
-IN: furnace
-
-: code>quotation ( word/quot -- quot )
-    dup word? [ 1quotation ] when ;
-
-SYMBOL: default-action
-SYMBOL: template-path
-
-: render-template ( template -- )
-    template-path get swap path+
-    ".furnace" append resource-path
-    run-template-file ;
-
-: define-action ( word hash -- )
-    over t "action" set-word-prop
-    "action-params" set-word-prop ;
-
-: define-form ( word1 word2 hash -- )
-    dupd define-action
-    swap code>quotation "form-failed" set-word-prop ;
-
-: default-values ( word hash -- )
-    "default-values" set-word-prop ;
-
-SYMBOL: request-params
-SYMBOL: current-action
-SYMBOL: validators-errored
-SYMBOL: validation-errors
-
-: build-url ( str query-params -- newstr )
-    [
-        over %
-        dup assoc-empty? [
-            2drop
-        ] [
-            CHAR: ? rot member? "&" "?" ? %
-            assoc>query %
-        ] if
-    ] "" make ;
-
-: action-link ( query action -- url )
-    [
-        "/responder/" %
-        dup word-vocabulary "webapps." ?head drop %
-        "/" %
-        word-name %
-    ] "" make swap build-url ;
-
-: action-param ( hash paramsepc -- obj error/f )
-    unclip rot at swap >quotation apply-validators ;
-
-: query>seq ( hash word -- seq )
-    "action-params" word-prop [
-        dup first -rot
-        action-param [
-            t validators-errored >session
-            rot validation-errors session> set-at
-        ] [
-            nip
-        ] if*
-    ] with map ;
-
-: lookup-session ( hash -- session )
-    "furnace-session-id" over at get-session
-    [ ] [ new-session "furnace-session-id" roll set-at ] ?if ;
-
-: quot>query ( seq action -- hash )
-    >r >array r> "action-params" word-prop
-    [ first swap 2array ] 2map >hashtable ;
-
-PREDICATE: word action "action" word-prop ;
-
-: action-call? ( quot -- ? )
-    >vector dup pop action? >r [ word? not ] all? r> and ;
-
-: unclip* dup 1 head* swap peek ;
-
-: quot-link ( quot -- url )
-    dup action-call? [
-        unclip* [ quot>query ] keep action-link
-    ] [
-        t register-html-callback
-    ] if ;
-
-: replace-variables ( quot -- quot )
-    [ dup string? [ request-params session> at ] when ] map ;
-
-: furnace-session-id ( -- hash )
-    "furnace-session-id" request-params session> at
-    "furnace-session-id" associate ;
-
-: redirect-to-action ( -- )
-    current-action session>
-    "form-failed" word-prop replace-variables
-    quot-link furnace-session-id build-url permanent-redirect ;
-
-: if-form-page ( if then -- )
-    current-action session> "form-failed" word-prop -rot if ;
-
-: do-action
-    current-action session> [ query>seq ] keep add >quotation call ;
-
-: process-form ( -- )
-    H{ } clone validation-errors >session
-    request-params session> current-action session> query>seq
-    validators-errored session> [
-        drop redirect-to-action
-    ] [
-        current-action session> add >quotation call
-    ] if ;
-
-: page-submitted ( -- )
-    [ process-form ] [ request-params session> do-action ] if-form-page ;
-
-: action-first-time ( -- )
-    request-params session> current-action session>
-    [ "default-values" word-prop swap union request-params >session ] keep
-    request-params session> do-action ;
-
-: page-not-submitted ( -- )
-    [ redirect-to-action ] [ action-first-time ] if-form-page ;
-
-: setup-call-action ( hash word -- )
-    over lookup-session session set
-    current-action >session
-    request-params session> swap union
-    request-params >session
-    f validators-errored >session ;
-
-: call-action ( hash word -- )
-    setup-call-action
-    "furnace-form-submitted" request-params session> at
-    [ page-submitted ] [ page-not-submitted ] if ;
-
-: responder-vocab ( str -- newstr )
-    "webapps." swap append ;
-
-: lookup-action ( str webapp -- word )
-    responder-vocab lookup dup [
-        dup "action" word-prop [ drop f ] unless
-    ] when ;
-
-: truncate-url ( str -- newstr )
-    CHAR: / over index [ head ] when* ;
-
-: parse-action ( str -- word/f )
-    dup empty? [ drop default-action get ] when
-    truncate-url "responder" get lookup-action ;
-
-: service-request ( hash str -- )
-    parse-action [
-        [ call-action ] [ <pre> print-error </pre> ] recover
-    ] [
-        "404 no such action: " "argument" get append httpd-error
-    ] if* ;
-
-: service-get
-    "query" get swap service-request ;
-
-: service-post
-    "response" get swap service-request ;
-
-: web-app ( name defaul path -- )
-    [
-        template-path set
-        default-action set
-        "responder" set
-        [ service-get ] "get" set
-        [ service-post ] "post" set
-    ] make-responder ;
-
-: explode-tuple ( tuple -- )
-    dup tuple-slots swap class "slot-names" word-prop
-    [ set ] 2each ;
-
-SYMBOL: model
-
-: with-slots ( model quot -- )
-    [
-        >r [ dup model set explode-tuple ] when* r> call
-    ] with-scope ;
-
-: render-component ( model template -- )
-    swap [ render-template ] with-slots ;
-
-: browse-webapp-source ( vocab -- )
-    <a vocab browser-link-href =href a>
-        "Browse source" write
-    </a> ;
-
-: send-resource ( name -- )
-    template-path get swap path+ resource-path binary <file-reader>
-    stdio get stream-copy ;
-
-: render-link ( quot name -- )
-    <a swap quot-link =href a> write </a> ;
-
-: session-var ( str -- newstr )
-    request-params session> at ;
-
-: render ( str -- )
-    request-params session> at [ write ] when* ;
-
-: render-error ( str error-str -- )
-    swap validation-errors session> at validation-error? [
-        write
-    ] [
-        drop
-    ] if ;
diff --git a/extra/furnace/sessions/authors.txt b/extra/furnace/sessions/authors.txt
deleted file mode 100755 (executable)
index 7c1b2f2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Doug Coleman
diff --git a/extra/furnace/sessions/sessions.factor b/extra/furnace/sessions/sessions.factor
deleted file mode 100755 (executable)
index cf03fee..0000000
+++ /dev/null
@@ -1,50 +0,0 @@
-USING: assocs calendar init kernel math.parser
-namespaces random boxes alarms combinators.lib ;
-IN: furnace.sessions
-
-SYMBOL: sessions
-
-: timeout ( -- dt ) 20 minutes ;
-
-[
-    H{ } clone sessions set-global
-] "furnace.sessions" add-init-hook
-
-: new-session-id ( -- str )
-    [ 4 big-random >hex ]
-    [ sessions get-global key? not ] generate ;
-
-TUPLE: session id namespace alarm user-agent ;
-
-: cancel-timeout ( session -- )
-    session-alarm ?box [ cancel-alarm ] [ drop ] if ;
-
-: delete-session ( session -- )
-    sessions get-global delete-at*
-    [ cancel-timeout ] [ drop ] if ;
-
-: touch-session ( session -- )
-    dup cancel-timeout
-    dup [ session-id delete-session ] curry timeout later
-    swap session-alarm >box ;
-
-: <session> ( id -- session )
-    H{ } clone <box> f session construct-boa ;
-
-: new-session ( -- session id )
-    new-session-id [
-        dup <session> [
-            [ sessions get-global set-at ] keep
-            touch-session
-        ] keep
-    ] keep ;
-
-: get-session ( id -- session/f )
-    sessions get-global at*
-    [ dup touch-session ] when ;
-
-: session> ( str -- obj )
-    session get session-namespace at ;
-
-: >session ( value key -- )
-    session get session-namespace set-at ;
diff --git a/extra/furnace/summary.txt b/extra/furnace/summary.txt
deleted file mode 100755 (executable)
index 5696506..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Action-based web framework
diff --git a/extra/furnace/tags.txt b/extra/furnace/tags.txt
deleted file mode 100644 (file)
index 0aef4fe..0000000
+++ /dev/null
@@ -1 +0,0 @@
-enterprise
diff --git a/extra/furnace/validator/authors.txt b/extra/furnace/validator/authors.txt
deleted file mode 100755 (executable)
index 7c1b2f2..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Doug Coleman
diff --git a/extra/furnace/validator/validator-tests.factor b/extra/furnace/validator/validator-tests.factor
deleted file mode 100644 (file)
index e84e57b..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-IN: furnace.validator.tests
-USING: kernel sequences tools.test furnace.validator furnace ;
-
-[
-    123 f
-] [
-    H{ { "foo" "123" } } { "foo" v-number } action-param
-] unit-test
-
-: validation-fails
-    [ action-param nip not ] append [ f ] swap unit-test ;
-
-[ H{ { "foo" "12X3" } } { "foo" v-number } ] validation-fails
-
-[ H{ { "foo" "" } } { "foo" 4 v-min-length } ] validation-fails
-
-[ "ABCD" f ]
-[ H{ { "foo" "ABCD" } } { "foo" 4 v-min-length } action-param ]
-unit-test
-
-[ H{ { "foo" "ABCD" } } { "foo" 2 v-max-length } ]
-validation-fails
-
-[ "AB" f ]
-[ H{ { "foo" "AB" } } { "foo" 2 v-max-length } action-param ]
-unit-test
-
-[ "AB" f ]
-[ H{ { "foo" f } } { "foo" "AB" v-default } action-param ]
-unit-test
diff --git a/extra/furnace/validator/validator.factor b/extra/furnace/validator/validator.factor
deleted file mode 100644 (file)
index 698c77f..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-! Copyright (C) 2006 Slava Pestov
-! See http://factorcode.org/license.txt for BSD license.
-USING: kernel continuations sequences math namespaces math.parser ;
-IN: furnace.validator
-
-TUPLE: validation-error reason ;
-
-: apply-validators ( string quot -- obj error/f )
-    [
-        call f
-    ] [
-        dup validation-error? [ >r 2drop f r> ] [ rethrow ] if
-    ] recover ;
-
-: validation-error ( msg -- * )
-    \ validation-error construct-boa throw ;
-
-: v-default ( obj value -- obj )
-    over empty? [ nip ] [ drop ] if ;
-
-: v-required ( str -- str )
-    dup empty? [ "required" validation-error ] when ;
-
-: v-min-length ( str n -- str )
-    over length over < [
-        [ "must be at least " % # " characters" % ] "" make
-        validation-error
-    ] [
-        drop
-    ] if ;
-
-: v-max-length ( str n -- str )
-    over length over > [
-        [ "must be no more than " % # " characters" % ] "" make
-        validation-error
-    ] [
-        drop
-    ] if ;
-
-: v-number ( str -- n )
-    string>number [
-        "must be a number" validation-error
-    ] unless* ;
index 32e29db7dbb6b1a6f68efbd6965e8f4fc403aa1b..d81e9cd81e4e01f7d17be8af768c68a7013b39a7 100755 (executable)
@@ -1,4 +1,4 @@
-! Copyright (C) 2005, 2007 Slava Pestov.
+! Copyright (C) 2005, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: arrays definitions generic io kernel assocs hashtables
 namespaces parser prettyprint sequences strings io.styles
@@ -42,9 +42,9 @@ M: f print-element drop ;
     [ print-element ] with-style ;
 
 : with-default-style ( quot -- )
-    default-style get [
+    default-span-style get [
         last-element off
-        default-style get swap with-nesting
+        default-block-style get swap with-nesting
     ] with-style ; inline
 
 : print-content ( element -- )
old mode 100644 (file)
new mode 100755 (executable)
index 3c5271d..945d9a4
@@ -3,13 +3,17 @@
 USING: io.styles namespaces ;
 IN: help.stylesheet
 
-SYMBOL: default-style
+SYMBOL: default-span-style
 H{
     { font "sans-serif" }
     { font-size 12 }
     { font-style plain }
+} default-span-style set-global
+
+SYMBOL: default-block-style
+H{
     { wrap-margin 500 }
-} default-style set-global
+} default-block-style set-global
 
 SYMBOL: link-style
 H{
index fca15d9b07c3be4dffa1cc075a0780688c0cce5d..1a60390f64b346ec5815c16212f8efe9195539d5 100755 (executable)
@@ -1,8 +1,44 @@
 USING: assocs html.parser kernel math sequences strings ascii
-arrays shuffle unicode.case namespaces splitting
-http.server.responders ;
+arrays shuffle unicode.case namespaces splitting http
+sequences.lib ;
 IN: html.parser.analyzer
 
+: (find-relative)
+    [ >r + dup r> ?nth* [ 2drop f f ] unless ] [ 2drop f ] if ;
+
+: find-relative ( seq quot n -- i elt )
+    >r over [ find drop ] dip r> swap pick
+    (find-relative) ;
+
+: (find-all) ( n seq quot -- )
+    2dup >r >r find* [
+        dupd 2array , 1+ r> r> (find-all)
+    ] [
+        r> r> 3drop
+    ] if* ;
+
+: find-all ( seq quot -- alist )
+    [ 0 -rot (find-all) ] { } make ;
+
+: (find-nth) ( offset seq quot n count -- obj )
+    >r >r [ find* ] 2keep 4 npick [
+        r> r> 1+ 2dup <= [
+            4drop
+        ] [
+            >r >r >r >r drop 1+ r> r> r> r>
+            (find-nth)
+        ] if
+    ] [
+        2drop r> r> 2drop
+    ] if ;
+
+: find-nth ( seq quot n -- i elt )
+    0 -roll 0 (find-nth) ;
+
+: find-nth-relative ( seq quot n offest -- i elt )
+    >r [ find-nth ] 3keep 2drop nip r> swap pick
+    (find-relative) ;
+
 : remove-blank-text ( vector -- vector' )
     [
         dup tag-name text = [
@@ -52,29 +88,33 @@ IN: html.parser.analyzer
     >r >lower r>
     [ tag-attributes at over = ] with find rot drop ;
 
-: find-between ( i/f tag/f vector -- vector )
+: find-between* ( i/f tag/f vector -- vector )
     pick integer? [
-        rot 1+ tail-slice
+        rot tail-slice
         >r tag-name r>
-        [ find-matching-close drop ] keep swap head
+        [ find-matching-close drop 1+ ] keep swap head
     ] [
         3drop V{ } clone
     ] if ;
+    
+: find-between ( i/f tag/f vector -- vector )
+    find-between* dup length 3 >= [
+        [ 1 tail-slice 1 head-slice* ] keep like
+    ] when ;
+
+: find-between-first ( string vector -- vector' )
+    [ find-first-name ] keep find-between ;
+
+: tag-link ( tag -- link/f )
+    tag-attributes [ "href" swap at ] [ f ] if* ;
 
 : find-links ( vector -- vector )
     [ tag-name "a" = ] subset
-    [ tag-attributes "href" swap at ] map
-    [ ] subset ;
+    [ tag-link ] subset ;
 
-: (find-all) ( n seq quot -- )
-    2dup >r >r find* [
-        dupd 2array , 1+ r> r> (find-all)
-    ] [
-        r> r> 3drop
-    ] if* ;
 
-: find-all ( seq quot -- alist )
-    [ 0 -rot (find-all) ] { } make ;
+: find-by-text ( seq quot -- tag )
+    [ dup tag-name text = ] swap compose find drop ;
 
 : find-opening-tags-by-name ( name seq -- seq )
     [ [ tag-name = ] keep tag-closing? not and ] with find-all ;
@@ -82,8 +122,8 @@ IN: html.parser.analyzer
 : href-contains? ( str tag -- ? )
     tag-attributes "href" swap at* [ subseq? ] [ 2drop f ] if ;
 
-: query>hash* ( str -- hash )
-    "?" split1 nip query>hash ;
+: query>assoc* ( str -- hash )
+    "?" split1 nip query>assoc ;
 
 ! clear "http://fark.com" http-get parse-html find-links [ "go.pl" swap start ] subset [ "=" split peek ] map
 
@@ -91,5 +131,5 @@ IN: html.parser.analyzer
 ! "a" over find-opening-tags-by-name
 ! [ nip "shipposition.phtml?call=GBTT" swap href-contains? ] assoc-subset
 ! first first 8 + over nth
-! tag-attributes "href" swap at query>hash*
+! tag-attributes "href" swap at query>assoc*
 ! "lat" over at "lon" rot at
index 4fca1697a5d8fbf9ad283197d67022e39ff4ea18..661f63ab599f8fa4d470fc6369f9532d2c20bb1a 100755 (executable)
@@ -23,6 +23,5 @@ tuple-syntax namespaces ;
     [
         "http://www.apple.com/index.html"
         <get-request>
-        request-with-url
     ] with-scope
 ] unit-test
index f7a160017ac0cd9d8b27fc4b610252eebb1e0abc..f011ff537eecdef7c77903b89867b1fa7999ca9d 100755 (executable)
@@ -2,75 +2,80 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: assocs http kernel math math.parser namespaces sequences
 io io.sockets io.streams.string io.files io.timeouts strings
-splitting calendar continuations accessors vectors io.encodings.binary ;
+splitting calendar continuations accessors vectors io.encodings.latin1
+io.encodings.binary ;
 IN: http.client
 
+DEFER: http-request
+
+<PRIVATE
+
 : parse-url ( url -- resource host port )
     "http://" ?head [ "Only http:// supported" throw ] unless
     "/" split1 [ "/" swap append ] [ "/" ] if*
     swap parse-host ;
 
-<PRIVATE
-
 : store-path ( request path -- request )
     "?" split1 >r >>path r> dup [ query>assoc ] when >>query ;
 
-! This is all pretty complex because it needs to handle
-! HTTP redirects, which might be absolute or relative
 : request-with-url ( url request -- request )
-    clone dup "request" set
     swap parse-url >r >r store-path r> >>host r> >>port ;
 
-DEFER: (http-request)
-
+! This is all pretty complex because it needs to handle
+! HTTP redirects, which might be absolute or relative
 : absolute-redirect ( url -- request )
-    "request" get request-with-url ;
+    request get request-with-url ;
 
 : relative-redirect ( path -- request )
-    "request" get swap store-path ;
+    request get swap store-path ;
 
 : do-redirect ( response -- response stream )
     dup response-code 300 399 between? [
+        stdio get dispose
         header>> "location" swap at
         dup "http://" head? [
             absolute-redirect
         ] [
             relative-redirect
-        ] if "GET" >>method (http-request)
+        ] if "GET" >>method http-request
     ] [
         stdio get
     ] if ;
 
-: (http-request) ( request -- response stream )
-    dup host>> over port>> <inet> <client> stdio set
-    dup "r" set-global  write-request flush read-response
-    do-redirect ;
+: request-addr ( request -- addr )
+    dup host>> swap port>> <inet> ;
+
+: close-on-error ( stream quot -- )
+    [ with-stream* ] curry [ ] pick [ dispose ] curry cleanup ;
+    inline
 
 PRIVATE>
 
-: http-request ( url request -- response stream )
-    [
-        request-with-url
+: http-request ( request -- response stream )
+    dup request [
+        dup request-addr latin1 <client>
+        1 minutes over set-timeout
         [
-            (http-request)
-            1 minutes over set-timeout
-        ] [ ] [ stdio get dispose ] cleanup
-    ] with-scope ;
+            write-request flush
+            read-response
+            do-redirect
+        ] close-on-error
+    ] with-variable ;
 
-: <get-request> ( -- request )
-    <request> "GET" >>method ;
+: <get-request> ( url -- request )
+    <request> request-with-url "GET" >>method ;
 
 : http-get-stream ( url -- response stream )
     <get-request> http-request ;
 
 : success? ( code -- ? ) 200 = ;
 
-: check-response ( response stream -- stream )
-    swap code>> success?
-    [ dispose "HTTP download failed" throw ] unless ;
+: check-response ( response -- )
+    code>> success?
+    [ "HTTP download failed" throw ] unless ;
 
 : http-get ( url -- string )
-    http-get-stream check-response contents ;
+    http-get-stream contents swap check-response ;
 
 : download-name ( url -- name )
     file-name "?" split1 drop "/" ?tail drop ;
@@ -83,12 +88,13 @@ PRIVATE>
 : download ( url -- )
     dup download-name download-to ;
 
-: <post-request> ( content-type content -- request )
+: <post-request> ( content-type content url -- request )
     <request>
+    request-with-url
     "POST" >>method
     swap >>post-data
     swap >>post-data-type ;
 
 : http-post ( content-type content url -- response string )
     #! The content is URL encoded for you.
-    -rot url-encode <post-request> http-request contents ;
+    >r url-encode r> <post-request> http-request contents ;
index b706f34d13c298753f4b147da7148cb7745c6229..16be0d026df0dfd828a8e2bb9203e69629248fa6 100755 (executable)
@@ -127,3 +127,30 @@ read-response-test-1' 1array [
     "rmid=732423sdfs73242; path=/; domain=.example.net; expires=Fri, 31-Dec-2010 23:59:59 GMT"
     dup parse-cookies unparse-cookies =
 ] unit-test
+
+! Live-fire exercise
+USING: http.server http.server.static http.server.actions
+http.client io.server io.files io accessors namespaces threads
+io.encodings.ascii ;
+
+[ ] [
+    [
+        <dispatcher>
+        <action>
+            [ stop-server "text/html" <content> [ "Goodbye" write ] >>body ] >>get
+        "quit" add-responder
+        "extra/http/test" resource-path <static> >>default
+        default-host set
+
+        [ 1237 httpd ] "HTTPD test" spawn drop
+    ] with-scope
+] unit-test
+
+[ t ] [
+    "extra/http/test/foo.html" resource-path ascii file-contents
+    "http://localhost:1237/foo.html" http-get =
+] unit-test
+
+[ "Goodbye" ] [
+    "http://localhost:1237/quit" http-get
+] unit-test
index 2d74e92e861120491fb1744340b112c67c697760..13089ae6e83adc06e2e2b344cb4f19b8420f01e7 100644 (file)
@@ -1,11 +1,12 @@
 IN: http.server.actions.tests
 USING: http.server.actions tools.test math math.parser
 multiline namespaces http io.streams.string http.server
-sequences ;
+sequences accessors ;
 
-[ + ]
-{ { "a" [ string>number ] } { "b" [ string>number ] } }
-"GET" <action> "action-1" set
+<action>
+    [ "a" get "b" get + ] >>get
+    { { "a" [ string>number ] } { "b" [ string>number ] } } >>get-params
+"action-1" set
 
 STRING: action-request-test-1
 GET http://foo/bar?a=12&b=13 HTTP/1.1
@@ -19,9 +20,10 @@ blah
     "action-1" get call-responder
 ] unit-test
 
-[ "X" <repetition> concat append ]
-{ { +path+ [ ] } { "xxx" [ string>number ] } }
-"POST" <action> "action-2" set
+<action>
+    [ +path+ get "xxx" get "X" <repetition> concat append ] >>post
+    { { +path+ [ ] } { "xxx" [ string>number ] } } >>post-params
+"action-2" set
 
 STRING: action-request-test-2
 POST http://foo/bar/baz HTTP/1.1
index feb16a4488c13edb4c94f2ae35c75afd83f2cacd..5e5b7a956303a87f9d1cf1ab038f9dd90e43007e 100755 (executable)
@@ -1,14 +1,18 @@
 ! Copyright (C) 2008 Slava Pestov.\r
 ! See http://factorcode.org/license.txt for BSD license.\r
 USING: accessors new-slots sequences kernel assocs combinators\r
-http.server http hashtables namespaces ;\r
+http.server http.server.validators http hashtables namespaces ;\r
 IN: http.server.actions\r
 \r
 SYMBOL: +path+\r
 \r
-TUPLE: action quot params method ;\r
+TUPLE: action get get-params post post-params revalidate ;\r
 \r
-C: <action> action\r
+: <action>\r
+    action construct-empty\r
+    [ <400> ] >>get\r
+    [ <400> ] >>post\r
+    [ <400> ] >>revalidate ;\r
 \r
 : extract-params ( request path -- assoc )\r
     >r dup method>> {\r
@@ -16,15 +20,22 @@ C: <action> action
         { "POST" [ post-data>> query>assoc ] }\r
     } case r> +path+ associate union ;\r
 \r
-: push-params ( assoc action -- ... )\r
-    params>> [ first2 >r swap at r> call ] with each ;\r
+: action-params ( request path param -- error? )\r
+    -rot extract-params validate-params ;\r
+\r
+: get-action ( request path -- response )\r
+    action get get-params>> action-params\r
+    [ <400> ] [ action get get>> call ] if ;\r
+\r
+: post-action ( request path -- response )\r
+    action get post-params>> action-params\r
+    [ action get revalidate>> ] [ action get post>> ] if call ;\r
 \r
 M: action call-responder ( request path action -- response )\r
-    pick request set\r
-    pick method>> over method>> = [\r
-        >r extract-params r>\r
-        [ push-params ] keep\r
-        quot>> call\r
-    ] [\r
-        3drop <400>\r
-    ] if ;\r
+    action set\r
+    over request set\r
+    over method>>\r
+    {\r
+        { "GET" [ get-action ] }\r
+        { "POST" [ post-action ] }\r
+    } case ;\r
diff --git a/extra/http/server/auth/basic/basic.factor b/extra/http/server/auth/basic/basic.factor
new file mode 100755 (executable)
index 0000000..2ea74fe
--- /dev/null
@@ -0,0 +1,41 @@
+! Copyright (c) 2007 Chris Double.\r
+! See http://factorcode.org/license.txt for BSD license.\r
+USING: accessors new-slots quotations assocs kernel splitting\r
+base64 html.elements io combinators http.server\r
+http.server.auth.providers http.server.auth.providers.null\r
+http sequences ;\r
+IN: http.server.auth.basic\r
+\r
+TUPLE: basic-auth responder realm provider ;\r
+\r
+C: <basic-auth> basic-auth\r
+\r
+: authorization-ok? ( provider header -- ? )\r
+    #! Given the realm and the 'Authorization' header,\r
+    #! authenticate the user.\r
+    dup [\r
+        " " split1 swap "Basic" = [\r
+            base64> ":" split1 spin check-login\r
+        ] [\r
+            2drop f\r
+        ] if\r
+    ] [\r
+        2drop f\r
+    ] if ;\r
+\r
+: <401> ( realm -- response )\r
+    401 "Unauthorized" <trivial-response>\r
+    "Basic realm=\"" rot "\"" 3append\r
+    "WWW-Authenticate" set-header\r
+    [\r
+        <html> <body>\r
+            "Username or Password is invalid" write\r
+        </body> </html>\r
+    ] >>body ;\r
+\r
+: logged-in? ( request responder -- ? )\r
+    provider>> swap "authorization" header authorization-ok? ;\r
+\r
+M: basic-auth call-responder ( request path responder -- response )\r
+    pick over logged-in?\r
+    [ responder>> call-responder ] [ 2nip realm>> <401> ] if ;\r
diff --git a/extra/http/server/auth/login/login.factor b/extra/http/server/auth/login/login.factor
new file mode 100755 (executable)
index 0000000..e2f9a36
--- /dev/null
@@ -0,0 +1,69 @@
+! Copyright (c) 2008 Slava Pestov\r
+! See http://factorcode.org/license.txt for BSD license.\r
+USING: accessors new-slots quotations assocs kernel splitting\r
+base64 html.elements io combinators http.server\r
+http.server.auth.providers http.server.actions\r
+http.server.sessions http.server.templating.fhtml http sequences\r
+io.files namespaces ;\r
+IN: http.server.auth.login\r
+\r
+TUPLE: login-auth responder provider ;\r
+\r
+C: (login-auth) login-auth\r
+\r
+SYMBOL: logged-in?\r
+SYMBOL: provider\r
+SYMBOL: post-login-url\r
+\r
+: login-page ( -- response )\r
+    "text/html" <content> [\r
+        "extra/http/server/auth/login/login.fhtml"\r
+        resource-path run-template-file\r
+    ] >>body ;\r
+\r
+: <login-action>\r
+    <action>\r
+        [ login-page ] >>get\r
+\r
+        {\r
+            { "name" [ ] }\r
+            { "password" [ ] }\r
+        } >>post-params\r
+        [\r
+            "password" get\r
+            "name" get\r
+            provider sget check-login [\r
+                t logged-in? sset\r
+                post-login-url sget <permanent-redirect>\r
+            ] [\r
+                login-page\r
+            ] if\r
+        ] >>post ;\r
+\r
+: <logout-action>\r
+    <action>\r
+        [\r
+            f logged-in? sset\r
+            request get "login" <permanent-redirect>\r
+        ] >>post ;\r
+\r
+M: login-auth call-responder ( request path responder -- response )\r
+    logged-in? sget\r
+    [ responder>> call-responder ] [\r
+        pick method>> "GET" = [\r
+            nip\r
+            provider>> provider sset\r
+            dup request-url post-login-url sset\r
+            "login" f session-link <permanent-redirect>\r
+        ] [\r
+            3drop <400>\r
+        ] if\r
+    ] if ;\r
+\r
+: <login-auth> ( responder provider -- auth )\r
+        (login-auth)\r
+        <dispatcher>\r
+            swap >>default\r
+            <login-action> "login" add-responder\r
+            <logout-action> "logout" add-responder\r
+    <cookie-sessions> ;\r
diff --git a/extra/http/server/auth/login/login.fhtml b/extra/http/server/auth/login/login.fhtml
new file mode 100755 (executable)
index 0000000..9bb1438
--- /dev/null
@@ -0,0 +1,25 @@
+<html>\r
+<body>\r
+<h1>Login required</h1>\r
+\r
+<form method="POST" action="login">\r
+<table>\r
+\r
+<tr>\r
+<td>User name:</td>\r
+<td><input name="name" /></td>\r
+</tr>\r
+\r
+<tr>\r
+<td>Password:</td>\r
+<td><input type="password" name="password" /></td>\r
+</tr>\r
+\r
+</table>\r
+\r
+<input type="submit" value="Log in" />\r
+\r
+</form>\r
+\r
+</body>\r
+</html>\r
diff --git a/extra/http/server/auth/providers/assoc/assoc-tests.factor b/extra/http/server/auth/providers/assoc/assoc-tests.factor
new file mode 100755 (executable)
index 0000000..3270fe0
--- /dev/null
@@ -0,0 +1,18 @@
+IN: http.server.auth.providers.assoc.tests\r
+USING: http.server.auth.providers \r
+http.server.auth.providers.assoc tools.test\r
+namespaces ;\r
+\r
+<assoc-auth-provider> "provider" set\r
+\r
+"slava" "provider" get new-user\r
+\r
+[ "slava" "provider" get new-user ] [ user-exists? ] must-fail-with\r
+\r
+[ f ] [ "fdasf" "slava" "provider" get check-login ] unit-test\r
+\r
+[ "xx" "blah" "provider" get set-password ] [ no-such-user? ] must-fail-with\r
+\r
+"fdasf" "slava" "provider" get set-password\r
+\r
+[ t ] [ "fdasf" "slava" "provider" get check-login ] unit-test\r
diff --git a/extra/http/server/auth/providers/assoc/assoc.factor b/extra/http/server/auth/providers/assoc/assoc.factor
new file mode 100755 (executable)
index 0000000..d57be62
--- /dev/null
@@ -0,0 +1,23 @@
+! Copyright (C) 2008 Slava Pestov.\r
+! See http://factorcode.org/license.txt for BSD license.\r
+IN: http.server.auth.providers.assoc\r
+USING: new-slots accessors assocs kernel\r
+http.server.auth.providers ;\r
+\r
+TUPLE: assoc-auth-provider assoc ;\r
+\r
+: <assoc-auth-provider> ( -- provider )\r
+    H{ } clone assoc-auth-provider construct-boa ;\r
+\r
+M: assoc-auth-provider check-login\r
+    assoc>> at = ;\r
+\r
+M: assoc-auth-provider new-user\r
+    assoc>>\r
+    2dup key? [ drop user-exists ] when\r
+    t -rot set-at ;\r
+\r
+M: assoc-auth-provider set-password\r
+    assoc>>\r
+    2dup key? [ drop no-such-user ] unless\r
+    set-at ;\r
diff --git a/extra/http/server/auth/providers/db/db-tests.factor b/extra/http/server/auth/providers/db/db-tests.factor
new file mode 100755 (executable)
index 0000000..c4682c2
--- /dev/null
@@ -0,0 +1,25 @@
+IN: http.server.auth.providers.db.tests\r
+USING: http.server.auth.providers\r
+http.server.auth.providers.db tools.test\r
+namespaces db db.sqlite db.tuples continuations\r
+io.files ;\r
+\r
+db-auth-provider "provider" set\r
+\r
+"auth-test.db" temp-file sqlite-db [\r
+    \r
+    [ user drop-table ] ignore-errors\r
+    [ user create-table ] ignore-errors\r
+\r
+    "slava" "provider" get new-user\r
+\r
+    [ "slava" "provider" get new-user ] [ user-exists? ] must-fail-with\r
+\r
+    [ f ] [ "fdasf" "slava" "provider" get check-login ] unit-test\r
+\r
+    [ "xx" "blah" "provider" get set-password ] [ no-such-user? ] must-fail-with\r
+\r
+    "fdasf" "slava" "provider" get set-password\r
+\r
+    [ t ] [ "fdasf" "slava" "provider" get check-login ] unit-test\r
+] with-db\r
diff --git a/extra/http/server/auth/providers/db/db.factor b/extra/http/server/auth/providers/db/db.factor
new file mode 100755 (executable)
index 0000000..9583122
--- /dev/null
@@ -0,0 +1,53 @@
+! Copyright (C) 2008 Slava Pestov.\r
+! See http://factorcode.org/license.txt for BSD license.\r
+USING: db db.tuples db.types new-slots accessors\r
+http.server.auth.providers kernel ;\r
+IN: http.server.auth.providers.db\r
+\r
+TUPLE: user name password ;\r
+\r
+: <user> user construct-empty ;\r
+\r
+user "USERS"\r
+{\r
+    { "name" "NAME" { VARCHAR 256 } +assigned-id+ }\r
+    { "password" "PASSWORD" { VARCHAR 256 } +not-null+ }\r
+} define-persistent\r
+\r
+: init-users-table ( -- )\r
+    user create-table ;\r
+\r
+TUPLE: db-auth-provider ;\r
+\r
+: db-auth-provider T{ db-auth-provider } ;\r
+\r
+M: db-auth-provider check-login\r
+    drop\r
+    <user>\r
+    swap >>name\r
+    swap >>password\r
+    select-tuple >boolean ;\r
+\r
+M: db-auth-provider new-user\r
+    drop\r
+    [\r
+        <user>\r
+        swap >>name\r
+\r
+        dup select-tuple [ name>> user-exists ] when\r
+\r
+        "unassigned" >>password\r
+\r
+        insert-tuple\r
+    ] with-transaction ;\r
+\r
+M: db-auth-provider set-password\r
+    drop\r
+    [\r
+        <user>\r
+        swap >>name\r
+\r
+        dup select-tuple [ ] [ no-such-user ] ?if\r
+\r
+        swap >>password update-tuple\r
+    ] with-transaction ;\r
diff --git a/extra/http/server/auth/providers/null/null.factor b/extra/http/server/auth/providers/null/null.factor
new file mode 100755 (executable)
index 0000000..7021119
--- /dev/null
@@ -0,0 +1,14 @@
+! Copyright (C) 2008 Slava Pestov.\r
+! See http://factorcode.org/license.txt for BSD license.\r
+USING: http.server.auth.providers kernel ;\r
+IN: http.server.auth.providers.null\r
+\r
+TUPLE: null-auth-provider ;\r
+\r
+: null-auth-provider T{ null-auth-provider } ;\r
+\r
+M: null-auth-provider check-login 3drop f ;\r
+\r
+M: null-auth-provider new-user 3drop f ;\r
+\r
+M: null-auth-provider set-password 3drop f ;\r
diff --git a/extra/http/server/auth/providers/providers.factor b/extra/http/server/auth/providers/providers.factor
new file mode 100755 (executable)
index 0000000..1e0fd33
--- /dev/null
@@ -0,0 +1,18 @@
+! Copyright (C) 2008 Slava Pestov.\r
+! See http://factorcode.org/license.txt for BSD license.\r
+USING: kernel ;\r
+IN: http.server.auth.providers\r
+\r
+GENERIC: check-login ( password user provider -- ? )\r
+\r
+GENERIC: new-user ( user provider -- )\r
+\r
+GENERIC: set-password ( password user provider -- )\r
+\r
+TUPLE: user-exists name ;\r
+\r
+: user-exists ( name -- * ) \ user-exists construct-boa throw ;\r
+\r
+TUPLE: no-such-user name ;\r
+\r
+: no-such-user ( name -- * ) \ no-such-user construct-boa throw ;\r
index 9950a9a4a4b120408d428d819383d77d0efc896e..cce3e5402df6e89e62c7e6822a1658028908b530 100755 (executable)
@@ -41,18 +41,17 @@ IN: http.server.cgi
         ] when\r
     ] H{ } make-assoc ;\r
 \r
-: cgi-descriptor ( name -- desc )\r
-    [\r
-        dup 1array +arguments+ set\r
-        cgi-variables +environment+ set\r
-    ] H{ } make-assoc ;\r
+: <cgi-process> ( name -- desc )\r
+    <process>\r
+        over 1array >>command\r
+        swap cgi-variables >>environment ;\r
     \r
 : serve-cgi ( name -- response )\r
     <raw-response>\r
     200 >>code\r
     "CGI output follows" >>message\r
     swap [\r
-        stdio get swap cgi-descriptor <process-stream> [\r
+        stdio get swap <cgi-process> <process-stream> [\r
             post? [\r
                 request get post-data>> write flush\r
             ] when\r
diff --git a/extra/http/server/components/components.factor b/extra/http/server/components/components.factor
new file mode 100755 (executable)
index 0000000..f14b766
--- /dev/null
@@ -0,0 +1,125 @@
+! Copyright (C) 2008 Slava Pestov
+! See http://factorcode.org/license.txt for BSD license.
+USING: new-slots html.elements http.server.validators
+accessors namespaces kernel io farkup math.parser assocs
+classes words tuples arrays sequences io.files
+http.server.templating.fhtml splitting mirrors ;
+IN: http.server.components
+
+SYMBOL: components
+
+TUPLE: component id ;
+
+: component ( name -- component )
+    dup components get at
+    [ ] [ "No such component: " swap append throw ] ?if ;
+
+GENERIC: validate* ( string component -- result )
+GENERIC: render-view* ( value component -- )
+GENERIC: render-edit* ( value component -- )
+GENERIC: render-error* ( reason value component -- )
+
+SYMBOL: values
+
+: value values get at ;
+
+: render-view ( component -- )
+    dup id>> value swap render-view* ;
+
+: render-error ( error -- )
+    <span "error" =class span> write </span> ;
+
+: render-edit ( component -- )
+    dup id>> value dup validation-error? [
+        dup reason>> swap value>> rot render-error*
+    ] [
+        swap render-edit*
+    ] if ;
+
+: <component> ( id string -- component )
+    >r \ component construct-boa r> construct-delegate ; inline
+
+TUPLE: string min max ;
+
+: <string> ( id -- component ) string <component> ;
+
+M: string validate*
+    [ min>> v-min-length ] keep max>> v-max-length ;
+
+M: string render-view*
+    drop write ;
+
+: render-input
+    <input "text" =type id>> dup =id =name =value input/> ;
+
+M: string render-edit*
+    render-input ;
+
+M: string render-error*
+    render-input render-error ;
+
+TUPLE: text ;
+
+: <text> ( id -- component ) <string> text construct-delegate ;
+
+: render-textarea
+    <textarea id>> dup =id =name textarea> write </textarea> ;
+
+M: text render-edit*
+    render-textarea ;
+
+M: text render-error*
+    render-textarea render-error ;
+
+TUPLE: farkup ;
+
+: <farkup> ( id -- component ) <text> farkup construct-delegate ;
+
+M: farkup render-view*
+    drop string-lines "\n" join convert-farkup write ;
+
+TUPLE: number min max ;
+
+: <number> ( id -- component ) number <component> ;
+
+M: number validate*
+    >r v-number r> [ min>> v-min-value ] keep max>> v-max-value ;
+
+M: number render-view*
+    drop number>string write ;
+
+M: number render-edit*
+    >r number>string r> render-input ;
+
+M: number render-error*
+    render-input render-error ;
+
+: with-components ( tuple components quot -- )
+    [
+        >r components set
+        dup make-mirror values set
+        tuple set
+        r> call
+    ] with-scope ; inline
+
+TUPLE: form view-template edit-template components ;
+
+: <form> ( id view-template edit-template -- form )
+    V{ } clone form construct-boa
+    swap \ component construct-boa
+    over set-delegate ;
+
+: add-field ( form component -- form )
+    dup id>> pick components>> set-at ;
+
+M: form render-view* ( value form -- )
+    dup components>>
+    swap view-template>>
+    [ resource-path run-template-file ] curry
+    with-components ;
+
+M: form render-edit* ( value form -- )
+    dup components>>
+    swap edit-template>>
+    [ resource-path run-template-file ] curry
+    with-components ;
diff --git a/extra/http/server/crud/crud.factor b/extra/http/server/crud/crud.factor
new file mode 100644 (file)
index 0000000..099ded2
--- /dev/null
@@ -0,0 +1,13 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+IN: http.server.crud
+USING: kernel namespaces db.tuples math.parser
+http.server.actions accessors ;
+
+: by-id ( class -- tuple )
+    construct-empty "id" get >>id ;
+
+: <delete-action> ( class -- action )
+    <action>
+        { { "id" [ string>number ] } } >>post-params
+        swap [ by-id delete-tuple f ] curry >>post ;
index 4baee5f02b21f09c58b9dca99162f98bb80195a4..511921ce06dcc33c7f57a6af40bb85e8ba6ae904 100755 (executable)
@@ -1,14 +1,18 @@
 ! Copyright (C) 2008 Slava Pestov.\r
 ! See http://factorcode.org/license.txt for BSD license.\r
 USING: db http.server kernel new-slots accessors\r
-continuations namespaces ;\r
+continuations namespaces destructors ;\r
 IN: http.server.db\r
 \r
 TUPLE: db-persistence responder db params ;\r
 \r
 C: <db-persistence> db-persistence\r
 \r
+: connect-db ( db-persistence -- )\r
+    dup db>> swap params>> make-db\r
+    dup db set\r
+    dup db-open\r
+    add-always-destructor ;\r
+\r
 M: db-persistence call-responder\r
-    dup db>> over params>> make-db dup db-open [\r
-        db set responder>> call-responder\r
-    ] with-disposal ;\r
+    dup connect-db responder>> call-responder ;\r
index a003f1c422d9bbd2be33198fcd63d38127b74f33..133783114d7e4b1a35aaec7ffc932e7377208efe 100755 (executable)
@@ -4,7 +4,7 @@ USING: assocs kernel namespaces io io.timeouts strings splitting
 threads http sequences prettyprint io.server logging calendar
 new-slots html.elements accessors math.parser combinators.lib
 vocabs.loader debugger html continuations random combinators
-io.encodings.latin1  ;
+destructors io.encodings.latin1 ;
 IN: http.server
 
 GENERIC: call-responder ( request path responder -- response )
@@ -136,7 +136,7 @@ SYMBOL: development-mode
     swap method>> "HEAD" =
     [ drop ] [ write-response-body ] if ;
 
-: do-request ( request -- request )
+: do-request ( request -- response )
     [
         dup dup path>> over host>>
         find-virtual-host call-responder
@@ -150,13 +150,18 @@ LOG: httpd-hit NOTICE
 : log-request ( request -- )
     { method>> host>> path>> } map-exec-with httpd-hit ;
 
-: handle-client ( -- )
-    default-timeout
+: ?refresh-all ( -- )
     development-mode get-global
-    [ global [ refresh-all ] bind ] when
-    read-request
-    dup log-request
-    do-request do-response ;
+    [ global [ refresh-all ] bind ] when ;
+
+: handle-client ( -- )
+    [
+        default-timeout
+        ?refresh-all
+        read-request
+        dup log-request
+        do-request do-response
+    ] with-destructors ;
 
 : httpd ( port -- )
     internet-server "http.server"
index 4c21ba3c8d7fd979a5c3f8c81f77ccec131f5fa4..d771737c73e62e0cdac06ffdd240516f0295b711 100755 (executable)
@@ -4,6 +4,12 @@ kernel accessors ;
 \r
 : with-session \ session swap with-variable ; inline\r
 \r
+TUPLE: foo ;\r
+\r
+C: <foo> foo\r
+\r
+M: foo init-session drop 0 "x" sset ;\r
+\r
 "1234" f <session> [\r
     [ ] [ 3 "x" sset ] unit-test\r
     \r
@@ -18,8 +24,7 @@ kernel accessors ;
 [ t ] [ f <cookie-sessions> cookie-sessions? ] unit-test\r
 \r
 [ ] [\r
-    f <url-sessions>\r
-        [ 0 "x" sset ] >>init\r
+    <foo> <url-sessions>\r
     "manager" set\r
 ] unit-test\r
 \r
index 2977e5938d7ef45a1972853e153dc9fc00aaab98..d7fed6bb64568a5676d82ec511a1700014c60360 100755 (executable)
@@ -11,6 +11,8 @@ IN: http.server.sessions
 
 GENERIC: init-session ( responder -- )
 
+M: dispatcher init-session drop ;
+
 TUPLE: session-manager responder sessions ;
 
 : <session-manager> ( responder class -- responder' )
index 8d47d38eb1cd2ee464ebd830b53131ceecd8b2bd..93eb51ce4e27690b2111aabbaeeffafcf56144e5 100755 (executable)
@@ -3,7 +3,7 @@
 USING: calendar html io io.files kernel math math.parser http\r
 http.server namespaces parser sequences strings assocs\r
 hashtables debugger http.mime sorting html.elements logging\r
-calendar.format new-slots accessors ;\r
+calendar.format new-slots accessors io.encodings.binary ;\r
 IN: http.server.static\r
 \r
 SYMBOL: responder\r
@@ -33,7 +33,7 @@ TUPLE: file-responder root hook special ;
         <content>\r
         over file-length "content-length" set-header\r
         over file-http-date "last-modified" set-header\r
-        swap [ <file-reader> stdio get stream-copy ] curry >>body\r
+        swap [ binary <file-reader> stdio get stream-copy ] curry >>body\r
     ] <file-responder> ;\r
 \r
 : serve-static ( filename mime-type -- response )\r
diff --git a/extra/http/server/templating/authors.txt b/extra/http/server/templating/authors.txt
deleted file mode 100644 (file)
index b47eafb..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Slava Pestov
-Matthew Willis
diff --git a/extra/http/server/templating/fhtml/authors.txt b/extra/http/server/templating/fhtml/authors.txt
new file mode 100644 (file)
index 0000000..b47eafb
--- /dev/null
@@ -0,0 +1,2 @@
+Slava Pestov
+Matthew Willis
diff --git a/extra/http/server/templating/fhtml/fhtml-tests.factor b/extra/http/server/templating/fhtml/fhtml-tests.factor
new file mode 100755 (executable)
index 0000000..4065473
--- /dev/null
@@ -0,0 +1,17 @@
+USING: io io.files io.streams.string io.encodings.utf8
+http.server.templating.fhtml kernel tools.test sequences ;
+IN: http.server.templating.fhtml.tests
+
+: test-template ( path -- ? )
+    "extra/http/server/templating/fhtml/test/" swap append
+    [
+        ".fhtml" append resource-path
+        [ run-template-file ] with-string-writer
+    ] keep
+    ".html" append resource-path utf8 file-contents = ;
+
+[ t ] [ "example" test-template ] unit-test
+[ t ] [ "bug" test-template ] unit-test
+[ t ] [ "stack" test-template ] unit-test
+
+[ ] [ "<%\n%>" parse-template drop ] unit-test
diff --git a/extra/http/server/templating/fhtml/fhtml.factor b/extra/http/server/templating/fhtml/fhtml.factor
new file mode 100755 (executable)
index 0000000..3dcd23b
--- /dev/null
@@ -0,0 +1,106 @@
+! Copyright (C) 2005 Alex Chapman
+! Copyright (C) 2006, 2007 Slava Pestov
+! See http://factorcode.org/license.txt for BSD license.
+USING: continuations sequences kernel parser namespaces io
+io.files io.streams.string html html.elements
+source-files debugger combinators math quotations generic
+strings splitting accessors http.server.static http.server
+assocs io.encodings.utf8 ;
+
+IN: http.server.templating.fhtml
+
+: templating-vocab ( -- vocab-name ) "http.server.templating.fhtml" ;
+
+! See apps/http-server/test/ or libs/furnace/ for template usage
+! examples
+
+! We use a custom lexer so that %> ends a token even if not
+! followed by whitespace
+TUPLE: template-lexer ;
+
+: <template-lexer> ( lines -- lexer )
+    <lexer> template-lexer construct-delegate ;
+
+M: template-lexer skip-word
+    [
+        {
+            { [ 2dup nth CHAR: " = ] [ drop 1+ ] }
+            { [ 2dup swap tail-slice "%>" head? ] [ drop 2 + ] }
+            { [ t ] [ f skip ] }
+        } cond
+    ] change-column ;
+
+DEFER: <% delimiter
+
+: check-<% ( lexer -- col )
+    "<%" over lexer-line-text rot lexer-column start* ;
+
+: found-<% ( accum lexer col -- accum )
+    [
+        over lexer-line-text
+        >r >r lexer-column r> r> subseq parsed
+        \ write-html parsed
+    ] 2keep 2 + swap set-lexer-column ;
+
+: still-looking ( accum lexer -- accum )
+    [
+        dup lexer-line-text swap lexer-column tail
+        parsed \ print-html parsed
+    ] keep next-line ;
+
+: parse-%> ( accum lexer -- accum )
+    dup still-parsing? [
+        dup check-<%
+        [ found-<% ] [ [ still-looking ] keep parse-%> ] if*
+    ] [
+        drop
+    ] if ;
+
+: %> lexer get parse-%> ; parsing
+
+: parse-template-lines ( lines -- quot )
+    <template-lexer> [
+        V{ } clone lexer get parse-%> f (parse-until)
+    ] with-parser ;
+
+: parse-template ( string -- quot )
+    [
+        use [ clone ] change
+        templating-vocab use+
+        string-lines parse-template-lines
+    ] with-scope ;
+
+: eval-template ( string -- ) parse-template call ;
+
+: html-error. ( error -- )
+    <pre> error. </pre> ;
+
+: run-template-file ( filename -- )
+    [
+        [
+            "quiet" on
+            parser-notes off
+            templating-vocab use+
+            ! so that reload works properly
+            dup source-file file set
+            ?resource-path utf8 file-contents
+            [ eval-template ] [ html-error. drop ] recover
+        ] with-file-vocabs
+    ] curry assert-depth ;
+
+: run-relative-template-file ( filename -- )
+    file get source-file-path parent-directory
+    swap path+ run-template-file ;
+
+: template-convert ( infile outfile -- )
+    utf8 [ run-template-file ] with-file-writer ;
+
+! file responder integration
+: serve-fhtml ( filename -- response )
+    "text/html" <content>
+    swap [ run-template-file ] curry >>body ;
+
+: enable-fhtml ( responder -- responder )
+    [ serve-fhtml ]
+    "application/x-factor-server-page"
+    pick special>> set-at ;
diff --git a/extra/http/server/templating/fhtml/test/bug.fhtml b/extra/http/server/templating/fhtml/test/bug.fhtml
new file mode 100644 (file)
index 0000000..cb66599
--- /dev/null
@@ -0,0 +1,5 @@
+<%
+    USING: prettyprint ;
+    ! Hello world
+    5 pprint
+%>
diff --git a/extra/http/server/templating/fhtml/test/bug.html b/extra/http/server/templating/fhtml/test/bug.html
new file mode 100644 (file)
index 0000000..51d7b8d
--- /dev/null
@@ -0,0 +1,2 @@
+5
+
diff --git a/extra/http/server/templating/fhtml/test/example.fhtml b/extra/http/server/templating/fhtml/test/example.fhtml
new file mode 100644 (file)
index 0000000..211f44a
--- /dev/null
@@ -0,0 +1,8 @@
+<% USING: math ; %>
+
+<html>
+    <head><title>Simple Embedded Factor Example</title></head>
+    <body>
+        <% 5 [ %><p>I like repetition</p><% ] times %>
+    </body>
+</html>
diff --git a/extra/http/server/templating/fhtml/test/example.html b/extra/http/server/templating/fhtml/test/example.html
new file mode 100644 (file)
index 0000000..9bf4a08
--- /dev/null
@@ -0,0 +1,9 @@
+
+
+<html>
+    <head><title>Simple Embedded Factor Example</title></head>
+    <body>
+        <p>I like repetition</p><p>I like repetition</p><p>I like repetition</p><p>I like repetition</p><p>I like repetition</p>
+    </body>
+</html>
+
diff --git a/extra/http/server/templating/fhtml/test/stack.fhtml b/extra/http/server/templating/fhtml/test/stack.fhtml
new file mode 100644 (file)
index 0000000..399711a
--- /dev/null
@@ -0,0 +1 @@
+The stack: <% USING: prettyprint ;  .s %>
diff --git a/extra/http/server/templating/fhtml/test/stack.html b/extra/http/server/templating/fhtml/test/stack.html
new file mode 100644 (file)
index 0000000..ee923a6
--- /dev/null
@@ -0,0 +1,2 @@
+The stack: 
+
diff --git a/extra/http/server/templating/templating-tests.factor b/extra/http/server/templating/templating-tests.factor
deleted file mode 100644 (file)
index dcc78ea..0000000
+++ /dev/null
@@ -1,17 +0,0 @@
-USING: io io.files io.streams.string http.server.templating kernel tools.test
-    sequences io.encodings.utf8 ;
-IN: http.server.templating.tests
-
-: test-template ( path -- ? )
-    "extra/http/server/templating/test/" swap append
-    [
-        ".fhtml" append resource-path
-        [ run-template-file ] with-string-writer
-    ] keep
-    ".html" append resource-path utf8 file-contents = ;
-
-[ t ] [ "example" test-template ] unit-test
-[ t ] [ "bug" test-template ] unit-test
-[ t ] [ "stack" test-template ] unit-test
-
-[ ] [ "<%\n%>" parse-template drop ] unit-test
diff --git a/extra/http/server/templating/templating.factor b/extra/http/server/templating/templating.factor
deleted file mode 100755 (executable)
index 8cf35a5..0000000
+++ /dev/null
@@ -1,106 +0,0 @@
-! Copyright (C) 2005 Alex Chapman
-! Copyright (C) 2006, 2007 Slava Pestov
-! See http://factorcode.org/license.txt for BSD license.
-USING: continuations sequences kernel parser namespaces io
-io.files io.streams.string html html.elements
-source-files debugger combinators math quotations generic
-strings splitting accessors http.server.static http.server
-assocs io.encodings.utf8 ;
-
-IN: http.server.templating
-
-: templating-vocab ( -- vocab-name ) "http.server.templating" ;
-
-! See apps/http-server/test/ or libs/furnace/ for template usage
-! examples
-
-! We use a custom lexer so that %> ends a token even if not
-! followed by whitespace
-TUPLE: template-lexer ;
-
-: <template-lexer> ( lines -- lexer )
-    <lexer> template-lexer construct-delegate ;
-
-M: template-lexer skip-word
-    [
-        {
-            { [ 2dup nth CHAR: " = ] [ drop 1+ ] }
-            { [ 2dup swap tail-slice "%>" head? ] [ drop 2 + ] }
-            { [ t ] [ f skip ] }
-        } cond
-    ] change-column ;
-
-DEFER: <% delimiter
-
-: check-<% ( lexer -- col )
-    "<%" over lexer-line-text rot lexer-column start* ;
-
-: found-<% ( accum lexer col -- accum )
-    [
-        over lexer-line-text
-        >r >r lexer-column r> r> subseq parsed
-        \ write-html parsed
-    ] 2keep 2 + swap set-lexer-column ;
-
-: still-looking ( accum lexer -- accum )
-    [
-        dup lexer-line-text swap lexer-column tail
-        parsed \ print-html parsed
-    ] keep next-line ;
-
-: parse-%> ( accum lexer -- accum )
-    dup still-parsing? [
-        dup check-<%
-        [ found-<% ] [ [ still-looking ] keep parse-%> ] if*
-    ] [
-        drop
-    ] if ;
-
-: %> lexer get parse-%> ; parsing
-
-: parse-template-lines ( lines -- quot )
-    <template-lexer> [
-        V{ } clone lexer get parse-%> f (parse-until)
-    ] with-parser ;
-
-: parse-template ( string -- quot )
-    [
-        use [ clone ] change
-        templating-vocab use+
-        string-lines parse-template-lines
-    ] with-scope ;
-
-: eval-template ( string -- ) parse-template call ;
-
-: html-error. ( error -- )
-    <pre> error. </pre> ;
-
-: run-template-file ( filename -- )
-    [
-        [
-            "quiet" on
-            parser-notes off
-            templating-vocab use+
-            ! so that reload works properly
-            dup source-file file set
-            ?resource-path utf8 file-contents
-            [ eval-template ] [ html-error. drop ] recover
-        ] with-file-vocabs
-    ] curry assert-depth ;
-
-: run-relative-template-file ( filename -- )
-    file get source-file-path parent-directory
-    swap path+ run-template-file ;
-
-: template-convert ( infile outfile -- )
-    utf8 [ run-template-file ] with-file-writer ;
-
-! file responder integration
-: serve-fhtml ( filename -- response )
-    "text/html" <content>
-    swap [ run-template-file ] curry >>body ;
-
-: enable-fhtml ( responder -- responder )
-    [ serve-fhtml ]
-    "application/x-factor-server-page"
-    pick special>> set-at ;
diff --git a/extra/http/server/templating/test/bug.fhtml b/extra/http/server/templating/test/bug.fhtml
deleted file mode 100644 (file)
index cb66599..0000000
+++ /dev/null
@@ -1,5 +0,0 @@
-<%
-    USING: prettyprint ;
-    ! Hello world
-    5 pprint
-%>
diff --git a/extra/http/server/templating/test/bug.html b/extra/http/server/templating/test/bug.html
deleted file mode 100644 (file)
index 51d7b8d..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-5
-
diff --git a/extra/http/server/templating/test/example.fhtml b/extra/http/server/templating/test/example.fhtml
deleted file mode 100644 (file)
index 211f44a..0000000
+++ /dev/null
@@ -1,8 +0,0 @@
-<% USING: math ; %>
-
-<html>
-    <head><title>Simple Embedded Factor Example</title></head>
-    <body>
-        <% 5 [ %><p>I like repetition</p><% ] times %>
-    </body>
-</html>
diff --git a/extra/http/server/templating/test/example.html b/extra/http/server/templating/test/example.html
deleted file mode 100644 (file)
index 9bf4a08..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-
-
-<html>
-    <head><title>Simple Embedded Factor Example</title></head>
-    <body>
-        <p>I like repetition</p><p>I like repetition</p><p>I like repetition</p><p>I like repetition</p><p>I like repetition</p>
-    </body>
-</html>
-
diff --git a/extra/http/server/templating/test/stack.fhtml b/extra/http/server/templating/test/stack.fhtml
deleted file mode 100644 (file)
index 399711a..0000000
+++ /dev/null
@@ -1 +0,0 @@
-The stack: <% USING: prettyprint ;  .s %>
diff --git a/extra/http/server/templating/test/stack.html b/extra/http/server/templating/test/stack.html
deleted file mode 100644 (file)
index ee923a6..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-The stack: 
-
diff --git a/extra/http/server/validators/validators-tests.factor b/extra/http/server/validators/validators-tests.factor
new file mode 100644 (file)
index 0000000..ff68dcf
--- /dev/null
@@ -0,0 +1,4 @@
+IN: http.server.validators.tests
+USING: kernel sequences tools.test http.server.validators ;
+
+[ t t ] [ "foo" [ v-number ] with-validator >r validation-error? r> ] unit-test
diff --git a/extra/http/server/validators/validators.factor b/extra/http/server/validators/validators.factor
new file mode 100644 (file)
index 0000000..03beb8c
--- /dev/null
@@ -0,0 +1,64 @@
+! Copyright (C) 2006, 2008 Slava Pestov
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel continuations sequences math namespaces
+math.parser assocs new-slots ;
+IN: http.server.validators
+
+TUPLE: validation-error value reason ;
+
+: validation-error ( value reason -- * )
+    \ validation-error construct-boa throw ;
+
+: with-validator ( string quot -- result error? )
+    [ f ] compose curry
+    [ dup validation-error? [ t ] [ rethrow ] if ] recover ; inline
+
+: validate-param ( name validator assoc -- error? )
+    swap pick
+    >r >r at r> with-validator swap r> set ;
+
+: validate-params ( validators assoc -- error? )
+    [ validate-param ] curry { } assoc>map [ ] contains? ;
+
+: v-default ( str def -- str )
+    over empty? spin ? ;
+
+: v-required ( str -- str )
+    dup empty? [ "required" validation-error ] when ;
+
+: v-min-length ( str n -- str )
+    over length over < [
+        [ "must be at least " % # " characters" % ] "" make
+        validation-error
+    ] [
+        drop
+    ] if ;
+
+: v-max-length ( str n -- str )
+    over length over > [
+        [ "must be no more than " % # " characters" % ] "" make
+        validation-error
+    ] [
+        drop
+    ] if ;
+
+: v-number ( str -- n )
+    dup string>number [ ] [
+        "must be a number" validation-error
+    ] ?if ;
+
+: v-min-value ( str n -- str )
+    2dup < [
+        [ "must be at least " % # ] "" make
+        validation-error
+    ] [
+        drop
+    ] if ;
+
+: v-max-value ( str n -- str )
+    2dup > [
+        [ "must be no more than " % # ] "" make
+        validation-error
+    ] [
+        drop
+    ] if ;
diff --git a/extra/http/test/foo.html b/extra/http/test/foo.html
new file mode 100644 (file)
index 0000000..2638986
--- /dev/null
@@ -0,0 +1 @@
+<html><head><title>Hello</title></head><body>HTTPd test</body></html>
index 7c1b2f22790bfdca05f14a555a40b7eaa3ce2abd..56741201965fd1ac8e400094bb30d47ac3e97260 100644 (file)
@@ -1 +1,2 @@
 Doug Coleman
+Slava Pestov
index 0e50fd642a6b891d26a3f1cee518542ac17a488b..01da3bf64f395d6a0453c582340b637c4ec4f81b 100755 (executable)
@@ -4,102 +4,71 @@ USING: help.markup help.syntax quotations kernel io math
 calendar ;
 IN: io.launcher
 
-HELP: +command+
-{ $description "Launch descriptor key. A command line string, to be processed by the system's shell." } ;
+ARTICLE: "io.launcher.command" "Specifying a command"
+"The " { $snippet "command" } " slot of a " { $link process } " can contain either a string or a sequence of strings. In the first case, the string is processed in an operating system-specific manner. In the second case, the first element is a program name and the remaining elements are passed to the program as command-line arguments." ;
 
-HELP: +arguments+
-{ $description "Launch descriptor key. A sequence of command line argument strings. The first element is the program to launch and the remaining arguments are passed to the program without further processing." } ;
+ARTICLE: "io.launcher.detached" "Running processes in the background"
+"By default, " { $link run-process } " waits for the process to complete. To run a process without waiting for it to finish, set the " { $snippet "detached" } " slot of a " { $link process } ", or use the following word:"
+{ $subsection run-detached } ;
 
-HELP: +detached+
-{ $description "Launch descriptor key. A boolean indicating whether " { $link run-process } " will return immediately, rather than wait for the program to complete."
+ARTICLE: "io.launcher.environment" "Setting environment variables"
+"The " { $snippet "environment" } " slot of a " { $link process } " contains an association mapping environment variable names to values. The interpretation of environment variables is operating system-specific."
 $nl
-"Default value is " { $link f } "." }
-{ $notes "Cannot be used with " { $link <process-stream> } "." }
-{ $see-also run-detached } ;
-
-HELP: +environment+
-{ $description "Launch descriptor key. An association mapping strings to strings, specifying environment variables to set for the spawned process. The association is combined with the current environment using the operation specified by the " { $link +environment-mode+ } " launch descriptor key."
+"The " { $snippet "environment-mode" } " slot controls how the environment of the current Factor instance is composed with the value of the " { $snippet "environment" } " slot:"
+{ $subsection +prepend-environment+ }
+{ $subsection +replace-environment+ }
+{ $subsection +append-environment+ }
+"The default value is " { $link +append-environment+ } "." ;
+
+ARTICLE: "io.launcher.redirection" "Input/output redirection"
+"On all operating systems except for Windows CE, the default input/output/error streams can be redirected."
 $nl
-"Default value is an empty association." } ;
-
-HELP: +environment-mode+
-{ $description "Launch descriptor key. Must equal of the following:"
-    { $list
-        { $link +prepend-environment+ }
-        { $link +replace-environment+ }
-        { $link +append-environment+ }
-    }
-"Default value is " { $link +append-environment+ } "."
-} ;
-
-HELP: +stdin+
-{ $description "Launch descriptor key. Must equal one of the following:"
-    { $list
-        { { $link f } " - standard input is either inherited from the current process, or is a " { $link <process-stream> } " pipe" }
-        { { $link +inherit+ } " - standard input is inherited from the current process" }
-        { { $link +closed+ } " - standard input is closed" }
-        { "a path name - standard input is read from the given file, which must exist" }
-        { "a file stream or a socket - standard input is read from the given stream, which must be closed after the process has been started" }
-    }
-} ;
-
-HELP: +stdout+
-{ $description "Launch descriptor key. Must equal one of the following:"
-    { $list
-        { { $link f } " - standard output is either inherited from the current process, or is a " { $link <process-stream> } " pipe" }
-        { { $link +inherit+ } " - standard output is inherited from the current process" }
-        { { $link +closed+ } " - standard output is closed" }
-        { "a path name - standard output is written to the given file, which is overwritten if it already exists" }
-        { "a file stream or a socket - standard output is written to the given stream, which must be closed after the process has been started" }
-    }
-} ;
-
-HELP: +stderr+
-{ $description "Launch descriptor key. Must equal one of the following:"
-    { $list
-        { { $link f } " - standard error is inherited from the current process" }
-        { { $link +inherit+ } " - same as above" }
-        { { $link +stdout+ } " - standard error is merged with standard output" }
-        { { $link +closed+ } " - standard error is closed" }
-        { "a path name - standard error is written to the given file, which is overwritten if it already exists" }
-        { "a file stream or a socket - standard error is written to the given stream, which must be closed after the process has been started" }
-    }
+"To specify redirection, set the " { $snippet "stdin" } ", " { $snippet "stdout" } " and " { $snippet "stderr" } " slots of a " { $link process } " to one of the following values:"
+{ $list
+    { { $link f } " - default value; the stream is either inherited from the current process, or is a " { $link <process-stream> } " pipe" }
+    { { $link +inherit+ } " - the stream is inherited from the current process, overriding a " { $link <process-stream> } " pipe" }
+    { { $link +closed+ } " - the stream is closed; reads will return end of file and writes will fails" }
+    { { $link +stdout+ } " - a special value for the " { $snippet "stderr" } " slot only, indicating that the standard output and standard error streams should be merged" }
+    { "a path name - the stream is sent to the given file, which must exist for input and is created automatically on output" }
+    { "a file stream or a socket - the stream is connected to the given Factor stream, which cannot be used again from within Factor and must be closed after the process has been started" }
 } ;
 
 HELP: +closed+
-{ $description "Possible value for " { $link +stdin+ } ", " { $link +stdout+ } ", and " { $link +stderr+ } " launch descriptors." } ;
+{ $description "Possible value for the " { $snippet "stdin" } ", " { $snippet "stdout" } ", and " { $snippet "stderr" } " slots of a " { $link process } "." } ;
 
 HELP: +inherit+
-{ $description "Possible value for " { $link +stdin+ } ", " { $link +stdout+ } ", and " { $link +stderr+ } " launch descriptors." } ;
+{ $description "Possible value for the " { $snippet "stdin" } ", " { $snippet "stdout" } ", and " { $snippet "stderr" } " slots of a " { $link process } "." } ;
+
+HELP: +stdout+
+{ $description "Possible value for the " { $snippet "stderr" } " slot of a " { $link process } "." } ;
 
 HELP: +prepend-environment+
-{ $description "Possible value of " { $link +environment-mode+ } " launch descriptor key. The child process environment consists of the value of the " { $link +environment+ } " key together with the current environment, with entries from the current environment taking precedence."
+{ $description "Possible value of " { $snippet "environment-mode" } " slot of a " { $link process } "."
+$nl
+"If this value is set, the child process environment consists of the value of the " { $snippet "environment" } " slot together with the current environment, with entries from the current environment taking precedence."
 $nl
 "This is used in situations where you want to spawn a child process with some default environment variables set, but allowing the user to override these defaults by changing the environment before launching Factor." } ;
 
 HELP: +replace-environment+
-{ $description "Possible value of " { $link +environment-mode+ } " launch descriptor key. The child process environment consists of the value of the " { $link +environment+ } " key."
+{ $description "Possible value of " { $snippet "environment-mode" } " slot of a " { $link process } "."
+$nl
+"The child process environment consists of the value of the " { $snippet "environment" } " slot."
 $nl
 "This is used in situations where you want full control over a child process environment, perhaps for security or testing." } ;
 
 HELP: +append-environment+
-{ $description "Possible value of " { $link +environment-mode+ } " launch descriptor key. The child process environment consists of the current environment together with the value of the " { $link +environment+ } " key, with entries from the " { $link +environment+ } " key taking precedence."
+{ $description "Possible value of " { $snippet "environment-mode" } " slot of a " { $link process } "."
+$nl
+"The child process environment consists of the current environment together with the value of the " { $snippet "environment" } " key, with entries from the " { $snippet "environment" } " key taking precedence."
 $nl
 "This is used in situations where you want a spawn child process with some overridden environment variables." } ;
 
-HELP: +timeout+
-{ $description "Launch descriptor key. If set to a " { $link duration } ", specifies a maximum running time for the process. If the process runs longer than this time, it will be killed." } ;
-
-HELP: default-descriptor
-{ $description "Association storing default values for launch descriptor keys." } ;
-
-HELP: with-descriptor
-{ $values { "desc" "a launch descriptor" } { "quot" quotation } } 
-{ $description "Calls the quotation in a dynamic scope where keys from " { $snippet "desc" } " can be read as variables, and any keys not supplied assume their default value as set in " { $link default-descriptor } "." } ;
+ARTICLE: "io.launcher.timeouts" "Process run-time timeouts"
+"The " { $snippet "timeout" } " slot of a " { $link process } " can be set to a " { $link duration } " specifying a maximum running time for the process. If " { $link wait-for-process } " is called and the process does not exit before the duration expires, it will be killed." ;
 
 HELP: get-environment
-{ $values { "env" "an association" } }
-{ $description "Combines the current environment with the value of " { $link +environment+ } " using " { $link +environment-mode+ } "." } ;
+{ $values { "process" process } { "env" "an association" } }
+{ $description "Combines the current environment with the value of the " { $snippet "environment" } " slot of the " { $link process } " using the " { $snippet "environment-mode" } " slot." } ;
 
 HELP: current-process-handle
 { $values { "handle" "a process handle" } }
@@ -110,20 +79,16 @@ HELP: run-process*
 { $contract "Launches a process using the launch descriptor." }
 { $notes "User code should call " { $link run-process } " instead." } ;
 
-HELP: >descriptor
-{ $values { "desc" "a launch descriptor" } { "desc" "a launch descriptor" } }
-{ $description "Creates a launch descriptor from an object. See " { $link "io.launcher.descriptors" } " for details." } ;
-
 HELP: run-process
 { $values { "desc" "a launch descriptor" } { "process" process } }
-{ $description "Launches a process. The object can either be a string, a sequence of strings or a launch descriptor. See " { $link "io.launcher.descriptors" } " for details." }
+{ $description "Launches a process. The object can either be a string, a sequence of strings or a " { $link process } ". See " { $link "io.launcher.descriptors" } " for details." }
 { $notes "The output value can be passed to " { $link wait-for-process } " to get an exit code." } ;
 
 HELP: run-detached
 { $values { "desc" "a launch descriptor" } { "process" process } }
-{ $contract "Launches a process without waiting for it to complete. The object can either be a string, a sequence of strings or a launch descriptor. See " { $link "io.launcher.descriptors" } " for details." }
+{ $contract "Launches a process without waiting for it to complete. The object can either be a string, a sequence of strings or a " { $link process } ". See " { $link "io.launcher.descriptors" } " for details." }
 { $notes
-    "This word is functionally identical to passing a launch descriptor to " { $link run-process } " having the " { $link +detached+ } " key set."
+    "This word is functionally identical to passing a " { $link process } " to " { $link run-process } " having the " { $snippet "detached" } " slot set."
     $nl
     "The output value can be passed to " { $link wait-for-process } " to get an exit code."
 } ;
@@ -147,11 +112,11 @@ HELP: kill-process*
 { $notes "User code should call " { $link kill-process } " intead." } ;
 
 HELP: process
-{ $class-description "A class representing an active or finished process."
-$nl
-"Processes are output by " { $link run-process } " and " { $link run-detached } ", and are stored in the " { $link process-stream-process } " slot of " { $link process-stream } " instances."
-$nl
-"Processes can be passed to " { $link wait-for-process } "." } ;
+{ $class-description "A class representing a process. Instances are created by calling " { $link <process> } "." } ;
+
+HELP: <process>
+{ $values { "process" process } }
+{ $description "Creates a new, empty process. It must be filled in before being passed to " { $link run-process } "." } ;
 
 HELP: process-stream
 { $class-description "A bidirectional stream for interacting with a running process. Instances are created by calling " { $link <process-stream> } ". The " { $link process-stream-process } " slot holds a " { $link process } " instance." } ;
@@ -161,8 +126,7 @@ HELP: <process-stream>
   { "desc" "a launch descriptor" }
   { "encoding" "an encoding descriptor" }
   { "stream" "a bidirectional stream" } }
-{ $description "Launches a process and redirects its input and output via a pair of pipes which may be read and written as a stream of the given encoding." }
-{ $notes "Closing the stream will block until the process exits." } ;
+{ $description "Launches a process and redirects its input and output via a pair of pipes which may be read and written as a stream of the given encoding." } ;
 
 HELP: with-process-stream
 { $values
@@ -176,41 +140,82 @@ HELP: wait-for-process
 { $description "If the process is still running, waits for it to exit, otherwise outputs the exit code immediately. Can be called multiple times on the same process." } ;
 
 ARTICLE: "io.launcher.descriptors" "Launch descriptors"
-"Words which launch processes can take either a command line string, a sequence of command line arguments, or an assoc:"
-{ $list
-    { "strings are wrapped in an assoc with a single " { $link +command+ } " key" }
-    { "sequences of strings are wrapped in an assoc with a single " { $link +arguments+ } " key" }
-    { "associations can be passed in, which allows finer control over launch parameters" }
-}
-"The associations can contain the following keys:"
-{ $subsection +command+ }
-{ $subsection +arguments+ }
-{ $subsection +detached+ }
-{ $subsection +environment+ }
-{ $subsection +environment-mode+ }
-{ $subsection +timeout+ }
-{ $subsection +stdin+ }
-{ $subsection +stdout+ }
-{ $subsection +stderr+ } ;
-
-ARTICLE: "io.launcher" "Launching OS processes"
-"The " { $vocab-link "io.launcher" } " vocabulary implements cross-platform process launching."
-{ $subsection "io.launcher.descriptors" }
-"The following words are used to launch processes:"
+"Words which launch processes can take either a command line string, a sequence of command line arguments, or a " { $link process } "."
+$nl
+"Strings and string arrays are wrapped in a new empty " { $link process } " with the " { $snippet "command" } " slot set. This covers basic use-cases where no launch parameters need to be set."
+$nl
+"A " { $link process } " instance can be created directly and passed to launching words for more control. It must be a fresh instance which has never been spawned before. To spawn a process several times from the same descriptor, " { $link clone } " the descriptor first." ;
+
+ARTICLE: "io.launcher.lifecycle" "The process lifecycle"
+"A freshly instantiated " { $link process } " represents a set of launch parameters."
+{ $subsection process }
+{ $subsection <process> }
+"Words for launching processes take a fresh process which has never been started before as input, and output a copy as output."
+{ $subsection process-started? }
+"The " { $link process } " instance output by launching words contains all original slot values in addition to the " { $snippet "handle" } " slot, which indicates the process is currently running."
+{ $subsection process-running? }
+"It is possible to wait for a process to exit:"
+{ $subsection wait-for-process }
+"A running process can also be killed:"
+{ $subsection kill-process } ;
+
+ARTICLE: "io.launcher.launch" "Launching processes"
+"Launching processes:"
 { $subsection run-process }
-{ $subsection run-detached }
 { $subsection try-process }
-"Stopping processes:"
-{ $subsection kill-process }
-"Finding the current process handle:"
-{ $subsection current-process-handle }
 "Redirecting standard input and output to a pipe:"
 { $subsection <process-stream> }
-{ $subsection with-process-stream }
-"A class representing an active or finished process:"
-{ $subsection process }
-"Waiting for a process to end, or getting the exit code of a finished process:"
-{ $subsection wait-for-process }
-"Processes support the " { $link "io.timeouts" } "; the timeout specifies an upper bound on the running time of the process." ;
+{ $subsection with-process-stream } ;
+
+ARTICLE: "io.launcher.examples" "Launcher examples"
+"Starting a command and waiting for it to finish:"
+{ $code
+    "\"ls /etc\" run-process"
+}
+"Starting a program in the background:"
+{ $code
+    "{ \"emacs\" \"foo.txt\" } run-detached"
+}
+"Running a command, throwing an exception if it exits unsuccessfully:"
+{ $code
+    "\"make clean all\" try-process"
+}
+"Running a command, throwing an exception if it exits unsuccessfully or if it takes too long to run:"
+{ $code
+    "<process>"
+    "    \"make test\" >>command"
+    "    5 minutes >>timeout"
+    "try-process"
+}
+"Running a command, throwing an exception if it exits unsuccessfully, and redirecting output and error messages to a log file:"
+{ $code
+    "<process>"
+    "    \"make clean all\" >>command"
+    "    \"log.txt\" >>stdout"
+    "    +stdout+ >>stderr"
+    "try-process"
+}
+"Running a command, appending error messages to a log file, and reading the output for further processing:"
+{ $code
+    "\"log.txt\" <file-appender> ["
+    "    <process>"
+    "        swap >>stderr"
+    "        \"report\" >>command"
+    "    ascii <process-stream> lines sort reverse [ print ] each"
+    "] with-disposal"
+} ;
+
+ARTICLE: "io.launcher" "Operating system processes"
+"The " { $vocab-link "io.launcher" } " vocabulary implements cross-platform process launching."
+{ $subsection "io.launcher.examples" }
+{ $subsection "io.launcher.descriptors" }
+{ $subsection "io.launcher.launch" }
+"Advanced topics:"
+{ $subsection "io.launcher.lifecycle" }
+{ $subsection "io.launcher.command" }
+{ $subsection "io.launcher.detached" }
+{ $subsection "io.launcher.environment" }
+{ $subsection "io.launcher.redirection" }
+{ $subsection "io.launcher.timeouts" } ;
 
 ABOUT: "io.launcher"
index ea5c58a3d305d5662b6b4f844a41700c7b61bce2..08f5160a61f5ca1133f198c9a7d7787579dcaee0 100755 (executable)
@@ -3,68 +3,71 @@
 USING: io io.backend io.timeouts system kernel namespaces
 strings hashtables sequences assocs combinators vocabs.loader
 init threads continuations math io.encodings io.streams.duplex
-io.nonblocking ;
+io.nonblocking new-slots accessors ;
 IN: io.launcher
 
+
+TUPLE: process
+
+command
+detached
+
+environment
+environment-mode
+
+stdin
+stdout
+stderr
+
+timeout
+
+handle status
+killed ;
+
+SYMBOL: +closed+
+SYMBOL: +inherit+
+SYMBOL: +stdout+
+
+SYMBOL: +prepend-environment+
+SYMBOL: +replace-environment+
+SYMBOL: +append-environment+
+
+: <process> ( -- process )
+    process construct-empty
+    H{ } clone >>environment
+    +append-environment+ >>environment-mode ;
+
+: process-started? ( process -- ? )
+    dup handle>> swap status>> or ;
+
+: process-running? ( process -- ? )
+    process-handle >boolean ;
+
 ! Non-blocking process exit notification facility
 SYMBOL: processes
 
 [ H{ } clone processes set-global ] "io.launcher" add-init-hook
 
-TUPLE: process handle status killed? timeout ;
-
 HOOK: register-process io-backend ( process -- )
 
 M: object register-process drop ;
 
-: <process> ( handle -- process )
-    f f f process construct-boa
+: process-started ( process handle -- )
+    >>handle
     V{ } clone over processes get set-at
-    dup register-process ;
+    register-process ;
 
 M: process equal? 2drop f ;
 
 M: process hashcode* process-handle hashcode* ;
 
-: process-running? ( process -- ? ) process-status not ;
-
-SYMBOL: +command+
-SYMBOL: +arguments+
-SYMBOL: +detached+
-SYMBOL: +environment+
-SYMBOL: +environment-mode+
-SYMBOL: +stdin+
-SYMBOL: +stdout+
-SYMBOL: +stderr+
+: pass-environment? ( process -- ? )
+    dup environment>> assoc-empty? not
+    swap environment-mode>> +replace-environment+ eq? or ;
 
-SYMBOL: +timeout+
-
-SYMBOL: +prepend-environment+
-SYMBOL: +replace-environment+
-SYMBOL: +append-environment+
-
-SYMBOL: +closed+
-SYMBOL: +inherit+
-
-: default-descriptor
-    H{
-        { +command+ f }
-        { +arguments+ f }
-        { +detached+ f }
-        { +environment+ H{ } }
-        { +environment-mode+ +append-environment+ }
-    } ;
-
-: with-descriptor ( desc quot -- )
-    default-descriptor [ >r clone r> bind ] bind ; inline
-
-: pass-environment? ( -- ? )
-    +environment+ get assoc-empty? not
-    +environment-mode+ get +replace-environment+ eq? or ;
-
-: get-environment ( -- env )
-    +environment+ get
-    +environment-mode+ get {
+: get-environment ( process -- env )
+    dup environment>>
+    swap environment-mode>> {
         { +prepend-environment+ [ os-envs union ] }
         { +append-environment+ [ os-envs swap union ] }
         { +replace-environment+ [ ] }
@@ -73,78 +76,81 @@ SYMBOL: +inherit+
 : string-array? ( obj -- ? )
     dup sequence? [ [ string? ] all? ] [ drop f ] if ;
 
-: >descriptor ( desc -- desc )
-    {
-        { [ dup string? ] [ +command+ associate ] }
-        { [ dup string-array? ] [ +arguments+ associate ] }
-        { [ dup assoc? ] [ >hashtable ] }
-    } cond ;
+GENERIC: >process ( obj -- process )
+
+M: process >process
+    dup process-started? [
+        "Process has already been started once" throw
+    ] when
+    clone ;
+
+M: object >process <process> swap >>command ;
 
 HOOK: current-process-handle io-backend ( -- handle )
 
-HOOK: run-process* io-backend ( desc -- handle )
+HOOK: run-process* io-backend ( process -- handle )
 
 : wait-for-process ( process -- status )
     [
-        dup process-handle
+        dup handle>>
         [
             dup [ processes get at push ] curry
             "process" suspend drop
         ] when
-        dup process-killed?
-        [ "Process was killed" throw ] [ process-status ] if
+        dup killed>>
+        [ "Process was killed" throw ] [ status>> ] if
     ] with-timeout ;
 
-: run-process ( desc -- process )
-    >descriptor
-    dup run-process*
-    +timeout+ pick at [ over set-timeout ] when*
-    +detached+ rot at [ dup wait-for-process drop ] unless ;
-
 : run-detached ( desc -- process )
-    >descriptor H{ { +detached+ t } } union run-process ;
+    >process
+    dup dup run-process* process-started
+    dup timeout>> [ over set-timeout ] when* ;
+
+: run-process ( desc -- process )
+    run-detached
+    dup detached>> [ dup wait-for-process drop ] unless ;
 
 TUPLE: process-failed code ;
 
 : process-failed ( code -- * )
     \ process-failed construct-boa throw ;
 
-: try-process ( desc -- )
+: try-process ( command/process -- )
     run-process wait-for-process dup zero?
     [ drop ] [ process-failed ] if ;
 
 HOOK: kill-process* io-backend ( handle -- )
 
 : kill-process ( process -- )
-    t over set-process-killed?
-    process-handle [ kill-process* ] when* ;
+    t >>killed
+    handle>> [ kill-process* ] when* ;
 
-M: process timeout process-timeout ;
+M: process timeout timeout>> ;
 
 M: process set-timeout set-process-timeout ;
 
 M: process timed-out kill-process ;
 
-HOOK: (process-stream) io-backend ( desc -- in out process )
+HOOK: (process-stream) io-backend ( process -- handle in out )
 
 TUPLE: process-stream process ;
 
 : <process-stream> ( desc encoding -- stream )
-    swap >descriptor
-    [ (process-stream) >r rot <encoder-duplex> r> ] keep
-    +timeout+ swap at [ over set-timeout ] when*
-    { set-delegate set-process-stream-process }
-    process-stream construct ;
+    >r >process dup dup (process-stream)
+    >r >r process-started process-stream construct-boa
+    r> r> <reader&writer> r> <encoder-duplex>
+    over set-delegate ;
 
 : with-process-stream ( desc quot -- status )
     swap <process-stream>
     [ swap with-stream ] keep
-    process-stream-process wait-for-process ; inline
+    process>> wait-for-process ; inline
 
-: notify-exit ( status process -- )
-    [ set-process-status ] keep
+: notify-exit ( process status -- )
+    >>status
     [ processes get delete-at* drop [ resume ] each ] keep
-    f swap set-process-handle ;
+    f >>handle
+    drop ;
 
 GENERIC: underlying-handle ( stream -- handle )
 
index b0ce1fcc12a9a9d62ffff9afd650c78237c56fca..6eee3739d9d2ab8db027c7670163dfa4ae4df239 100755 (executable)
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 IN: io.nonblocking
 USING: math kernel io sequences io.buffers io.timeouts generic
-sbufs system io.streams.duplex io.encodings
+byte-vectors system io.streams.duplex io.encodings
 io.backend continuations debugger classes byte-arrays namespaces
 splitting dlists assocs io.encodings.binary ;
 
@@ -71,7 +71,7 @@ GENERIC: (wait-to-read) ( port -- )
 M: input-port stream-read1
     dup wait-to-read1 [ buffer-pop ] unless-eof ;
 
-: read-step ( count port -- string/f )
+: read-step ( count port -- byte-array/f )
     [ wait-to-read ] 2keep
     [ dupd buffer> ] unless-eof nip ;
 
@@ -90,10 +90,10 @@ M: input-port stream-read
     >r 0 max >fixnum r>
     2dup read-step dup [
         pick over length > [
-            pick <sbuf>
+            pick <byte-vector>
             [ push-all ] keep
             [ read-loop ] keep
-            "" like
+            B{ } like
         ] [
             2nip
         ] if
@@ -101,7 +101,7 @@ M: input-port stream-read
         2nip
     ] if ;
 
-: read-until-step ( separators port -- string/f separator/f )
+: read-until-step ( separators port -- byte-array/f separator/f )
     dup wait-to-read1
     dup port-eof? [
         f swap set-port-eof? drop f f
@@ -109,7 +109,7 @@ M: input-port stream-read
         buffer-until
     ] if ;
 
-: read-until-loop ( seps port sbuf -- separator/f )
+: read-until-loop ( seps port byte-vector -- separator/f )
     2over read-until-step over [
         >r over push-all r> dup [
             >r 3drop r>
@@ -120,18 +120,20 @@ M: input-port stream-read
         >r 2drop 2drop r>
     ] if ;
 
-M: input-port stream-read-until ( seps port -- str/f sep/f )
+M: input-port stream-read-until ( seps port -- byte-array/f sep/f )
     2dup read-until-step dup [
         >r 2nip r>
     ] [
         over [
-            drop >sbuf [ read-until-loop ] keep "" like swap
+            drop >byte-vector
+            [ read-until-loop ] keep
+            B{ } like swap
         ] [
             >r 2nip r>
         ] if
     ] if ;
 
-M: input-port stream-read-partial ( max stream -- string/f )
+M: input-port stream-read-partial ( max stream -- byte-array/f )
     >r 0 max >fixnum r> read-step ;
 
 : can-write? ( len writer -- ? )
@@ -169,7 +171,7 @@ M: port dispose
     [ dup port-type >r closed over set-port-type r> close-port ]
     if ;
 
-TUPLE: server-port addr client encoding ;
+TUPLE: server-port addr client client-addr encoding ;
 
 : <server-port> ( handle addr encoding -- server )
     rot f server-port <port>
index 4267f7d1e8ae788c6875c84c948c39c26c500ca7..0b7e62690803041518dade0e586c489b1cffcc84 100755 (executable)
@@ -40,11 +40,11 @@ PRIVATE>
     f swap t resolve-host ;
 
 : with-server ( seq service encoding quot -- )
-    V{ } clone [
-        swap servers [
+    V{ } clone servers [
+        [
             [ server-loop ] 2curry with-logging
-        ] with-variable
-    ] 3curry curry parallel-each ; inline
+        ] 3curry parallel-each
+    ] with-variable ; inline
 
 : stop-server ( -- )
     servers get [ dispose ] each ;
index c10d7e963c2a3ac00ca048fbda2c507c47e51324..1dc7f4883d9635f2f905c0bf4fdd7c1d30a11205 100755 (executable)
@@ -33,17 +33,19 @@ M: array client* [ (client) 2array ] attempt-all first2 ;
 M: object client* (client) ;
 
 : <client> ( addrspec encoding -- stream )
-    over client* rot <encoder-duplex> <client-stream> ;
+    >r client* r> <encoder-duplex> ;
 
 HOOK: (server) io-backend ( addrspec -- handle )
 
 : <server> ( addrspec encoding -- server )
     >r [ (server) ] keep r> <server-port> ;
 
-HOOK: (accept) io-backend ( server -- stream-in stream-out )
+HOOK: (accept) io-backend ( server -- addrspec handle )
 
 : accept ( server -- client )
-    [ (accept) ] keep server-port-encoding <encoder-duplex> ;
+    [ (accept) dup <reader&writer> ] keep
+    server-port-encoding <encoder-duplex>
+    <client-stream> ;
 
 HOOK: <datagram> io-backend ( addrspec -- datagram )
 
index f6b0fe7ce6c7511c7f8097ed3fd2dcd1fc8882ec..1d472c19a3f76abdf8b99ee1d73cc71ef11c3055 100755 (executable)
@@ -90,3 +90,12 @@ M: unix-io file-info ( path -- info )
         [ stat-st_mtim timespec-sec seconds unix-1970 time+ ]
     } cleave
     \ file-info construct-boa ;
+
+M: unix-io link-info ( path -- info )
+    lstat* {
+        [ stat>type ]
+        [ stat-st_size ]
+        [ stat-st_mode ]
+        [ stat-st_mtim timespec-sec seconds unix-1970 time+ ]
+    } cleave
+    \ file-info construct-boa ;
index 60e3754ec6a4fee8910ce033a82dbb3989ced79d..97b186edf385344de0bbabce3a47845a7cd398f7 100755 (executable)
@@ -31,7 +31,8 @@ M: output-task io-task-filter drop EVFILT_WRITE ;
     swap io-task-filter over set-kevent-filter ;
 
 : register-kevent ( kevent mx -- )
-    mx-fd swap 1 f 0 f kevent io-error ;
+    mx-fd swap 1 f 0 f kevent
+    0 < [ err_no ESRCH = [ (io-error) ] unless ] when ;
 
 M: kqueue-mx register-io-task ( task mx -- )
     over EV_ADD make-kevent over register-kevent
@@ -53,7 +54,7 @@ M: kqueue-mx unregister-io-task ( task mx -- )
 
 : kevent-proc-task ( pid -- )
     dup wait-for-pid swap find-process
-    dup [ notify-exit ] [ 2drop ] if ;
+    dup [ swap notify-exit ] [ 2drop ] if ;
 
 : handle-kevent ( mx kevent -- )
     dup kevent-ident swap kevent-filter {
index c24d5c7c9ed8aad7dd83ccca7841656916e07548..aa54d3ec9435594d3fa9d53343bf72964d48b8be 100644 (file)
@@ -1,6 +1,7 @@
 IN: io.unix.launcher.tests
 USING: io.files tools.test io.launcher arrays io namespaces
-continuations math io.encodings.ascii ;
+continuations math io.encodings.ascii io.encodings.latin1
+accessors kernel sequences ;
 
 [ ] [
     [ "launcher-test-1" temp-file delete-file ] ignore-errors
@@ -20,10 +21,10 @@ continuations math io.encodings.ascii ;
 ] unit-test
 
 [ ] [
-    [
-        "echo Hello" +command+ set
-        "launcher-test-1" temp-file +stdout+ set
-    ] { } make-assoc try-process
+    <process>
+        "echo Hello" >>command
+        "launcher-test-1" temp-file >>stdout
+    try-process
 ] unit-test
 
 [ "Hello\n" ] [
@@ -34,12 +35,12 @@ continuations math io.encodings.ascii ;
 ] unit-test
 
 [ "" ] [
-    [
+    <process>
         "cat"
         "launcher-test-1" temp-file
-        2array +arguments+ set
-        +inherit+ +stdout+ set
-    ] { } make-assoc ascii <process-stream> contents
+        2array >>command
+        +inherit+ >>stdout
+    ascii <process-stream> contents
 ] unit-test
 
 [ ] [
@@ -47,11 +48,11 @@ continuations math io.encodings.ascii ;
 ] unit-test
 
 [ ] [
-    [
-        "cat" +command+ set
-        +closed+ +stdin+ set
-        "launcher-test-1" temp-file +stdout+ set
-    ] { } make-assoc try-process
+    <process>
+        "cat" >>command
+        +closed+ >>stdin
+        "launcher-test-1" temp-file >>stdout
+    try-process
 ] unit-test
 
 [ "" ] [
@@ -64,10 +65,10 @@ continuations math io.encodings.ascii ;
 [ ] [
     2 [
         "launcher-test-1" temp-file ascii <file-appender> [
-            [
-                +stdout+ set
-                "echo Hello" +command+ set
-            ] { } make-assoc try-process
+            <process>
+                swap >>stdout
+                "echo Hello" >>command
+            try-process
         ] with-disposal
     ] times
 ] unit-test
@@ -78,3 +79,19 @@ continuations math io.encodings.ascii ;
     2array
     ascii <process-stream> contents
 ] unit-test
+
+[ t ] [
+    <process>
+        "env" >>command
+        { { "A" "B" } } >>environment
+    latin1 <process-stream> lines
+    "A=B" swap member?
+] unit-test
+
+[ { "A=B" } ] [
+    <process>
+        "env" >>command
+        { { "A" "B" } } >>environment
+        +replace-environment+ >>environment-mode
+    latin1 <process-stream> lines
+] unit-test
index e79ca43e336bfac4be76bd4591fee835b6e3ff38..7b4831a2c5d5fa2aae2e622731418a25364b8f86 100755 (executable)
@@ -4,14 +4,14 @@ USING: io io.backend io.launcher io.nonblocking io.unix.backend
 io.unix.files io.nonblocking sequences kernel namespaces math
 system alien.c-types debugger continuations arrays assocs
 combinators unix.process strings threads unix
-io.unix.launcher.parser io.encodings.latin1 ;
+io.unix.launcher.parser io.encodings.latin1 accessors new-slots ;
 IN: io.unix.launcher
 
 ! Search unix first
 USE: unix
 
-: get-arguments ( -- seq )
-    +command+ get [ tokenize-command ] [ +arguments+ get ] if* ;
+: get-arguments ( process -- seq )
+    command>> dup string? [ tokenize-command ] when ;
 
 : assoc>env ( assoc -- env )
     [ "=" swap 3append ] { } assoc>map ;
@@ -44,28 +44,27 @@ USE: unix
 
 : ?closed dup +closed+ eq? [ drop "/dev/null" ] when ;
 
-: setup-redirection ( -- )
-    +stdin+ get ?closed read-flags 0 redirect
-    +stdout+ get ?closed write-flags 1 redirect
-    +stderr+ get dup +stdout+ eq?
+: setup-redirection ( process -- process )
+    dup stdin>> ?closed read-flags 0 redirect
+    dup stdout>> ?closed write-flags 1 redirect
+    dup stderr>> dup +stdout+ eq?
     [ drop 1 2 dup2 io-error ] [ ?closed write-flags 2 redirect ] if ;
 
-: spawn-process ( -- )
+: spawn-process ( process -- * )
     [
         setup-redirection
-        get-arguments
-        pass-environment?
-        [ get-environment assoc>env exec-args-with-env ]
-        [ exec-args-with-path ] if
-        io-error
-    ] [ error. :c flush ] recover 1 exit ;
+        dup pass-environment? [
+            dup get-environment set-os-envs
+        ] when
+
+        get-arguments exec-args-with-path
+        (io-error)
+    ] [ 255 exit ] recover ;
 
 M: unix-io current-process-handle ( -- handle ) getpid ;
 
-M: unix-io run-process* ( desc -- pid )
-    [
-        [ spawn-process ] [ ] with-fork <process>
-    ] with-descriptor ;
+M: unix-io run-process* ( process -- pid )
+    [ spawn-process ] curry [ ] with-fork ;
 
 M: unix-io kill-process* ( pid -- )
     SIGTERM kill io-error ;
@@ -78,21 +77,15 @@ M: unix-io kill-process* ( pid -- )
     2dup first close second close
     >r first 0 dup2 drop r> second 1 dup2 drop ;
 
-: spawn-process-stream ( -- in out pid )
-    open-pipe open-pipe [
-        setup-stdio-pipe
-        spawn-process
-    ] [
-        -rot 2dup second close first close
-    ] with-fork first swap second rot <process> ;
-
 M: unix-io (process-stream)
-    [
-        spawn-process-stream >r <reader&writer> r>
-    ] with-descriptor ;
+    >r open-pipe open-pipe r>
+    [ >r setup-stdio-pipe r> spawn-process ] curry
+    [ -rot 2dup second close first close ]
+    with-fork
+    first swap second ;
 
 : find-process ( handle -- process )
-    processes get swap [ nip swap process-handle = ] curry
+    processes get swap [ nip swap handle>> = ] curry
     assoc-find 2drop ;
 
 ! Inefficient process wait polling, used on Linux and Solaris.
@@ -103,7 +96,7 @@ M: unix-io (process-stream)
         2drop t
     ] [
         find-process dup [
-            >r *int WEXITSTATUS r> notify-exit f
+            swap *int WEXITSTATUS notify-exit f
         ] [
             2drop f
         ] if
index 2af77e83c407805804aeedb4072687ea83fc81e0..bd7dfd9ce18802a26f3dfc9581a3adaced115c37 100755 (executable)
@@ -42,7 +42,7 @@ M: connect-task do-io-task
 : wait-to-connect ( port -- )
     [ <connect-task> add-io-task ] with-port-continuation drop ;
 
-M: unix-io (client) ( addrspec -- stream )
+M: unix-io (client) ( addrspec -- client-in client-out )
     dup make-sockaddr/size >r >r
     protocol-family SOCK_STREAM socket-fd
     dup r> r> connect
@@ -71,10 +71,10 @@ TUPLE: accept-task ;
     dup <c-object> [ swap heap-size <int> accept ] keep ; inline
 
 : do-accept ( port fd sockaddr -- )
-    rot [
-        server-port-addr parse-sockaddr
-        swap dup <reader&writer> <duplex-stream> <client-stream>
-    ] keep set-server-port-client ;
+    rot
+    [ server-port-addr parse-sockaddr ] keep
+    [ set-server-port-client-addr ] keep
+    set-server-port-client ;
 
 M: accept-task do-io-task
     io-task-port dup accept-sockaddr
@@ -95,13 +95,13 @@ M: unix-io (server) ( addrspec -- handle )
     SOCK_STREAM server-fd
     dup 10 listen zero? [ dup close (io-error) ] unless ;
 
-M: unix-io (accept) ( server -- client-in client-out )
+M: unix-io (accept) ( server -- addrspec handle )
     #! Wait for a client connection.
     dup check-server-port
     dup wait-to-accept
     dup pending-error
-    server-port-client
-    { duplex-stream-in duplex-stream-out } get-slots ;
+    dup server-port-client-addr
+    swap server-port-client ;
 
 ! Datagram sockets - UDP and Unix domain
 M: unix-io <datagram>
index a5e0cb6b4a5a9933afab963071a747dee3b099e9..878f5899f6426735444aca43b7a037b9d0cdbfa3 100755 (executable)
@@ -3,4 +3,5 @@ io.windows.ce.files io.windows.ce.sockets io.windows.ce.launcher
 namespaces io.windows.mmap ;
 IN: io.windows.ce
 
+USE: io.windows.files
 T{ windows-ce-io } set-io-backend
index fdd574d00e2c0255a0b709dfcd2af6b4ebd1fa17..d107f80723d144df660f53a0b772fd839fabceb2 100644 (file)
@@ -50,17 +50,20 @@ SYMBOL: +encrypted+
         { +encrypted+ FILE_ATTRIBUTE_ENCRYPTED }
     } get-flags ;
 
+: win32-file-type ( n -- symbol )
+    FILE_ATTRIBUTE_DIRECTORY mask? +directory+ +regular-file+ ? ;
+
 : WIN32_FIND_DATA>file-info
     {
-        [ WIN32_FIND_DATA-dwFileAttributes win32-file-attributes ]
+        [ WIN32_FIND_DATA-dwFileAttributes win32-file-type ]
         [
             [ WIN32_FIND_DATA-nFileSizeLow ]
             [ WIN32_FIND_DATA-nFileSizeHigh ] bi >64bit
         ]
         [ WIN32_FIND_DATA-dwFileAttributes ]
-        [
-            WIN32_FIND_DATA-ftLastWriteTime FILETIME>timestamp
-        ]
+        ! [ WIN32_FIND_DATA-ftCreationTime FILETIME>timestamp ]
+        [ WIN32_FIND_DATA-ftLastWriteTime FILETIME>timestamp ]
+        ! [ WIN32_FIND_DATA-ftLastAccessTime FILETIME>timestamp ]
     } cleave
     \ file-info construct-boa ;
 
@@ -73,16 +76,15 @@ SYMBOL: +encrypted+
 
 : BY_HANDLE_FILE_INFORMATION>file-info
     {
-        [ BY_HANDLE_FILE_INFORMATION-dwFileAttributes win32-file-attributes ]
+        [ BY_HANDLE_FILE_INFORMATION-dwFileAttributes win32-file-type ]
         [
             [ BY_HANDLE_FILE_INFORMATION-nFileSizeLow ]
             [ BY_HANDLE_FILE_INFORMATION-nFileSizeHigh ] bi >64bit
         ]
         [ BY_HANDLE_FILE_INFORMATION-dwFileAttributes ]
-        [
-            BY_HANDLE_FILE_INFORMATION-ftLastWriteTime
-            FILETIME>timestamp
-        ]
+        ! [ BY_HANDLE_FILE_INFORMATION-ftCreationTime FILETIME>timestamp ]
+        [ BY_HANDLE_FILE_INFORMATION-ftLastWriteTime FILETIME>timestamp ]
+        ! [ BY_HANDLE_FILE_INFORMATION-ftLastAccessTime FILETIME>timestamp ]
     } cleave
     \ file-info construct-boa ;
 
index 708dc1dc389f6b0d00e6736593f438621a88e312..b09d867e10efbd9bd450cf5cedb82e7ba64947ff 100755 (executable)
@@ -5,7 +5,7 @@ io.windows io.windows.nt.pipes libc io.nonblocking
 io.streams.duplex windows.types math windows.kernel32 windows
 namespaces io.launcher kernel sequences windows.errors assocs
 splitting system threads init strings combinators
-io.backend ;
+io.backend new-slots accessors ;
 IN: io.windows.launcher
 
 TUPLE: CreateProcess-args
@@ -22,30 +22,25 @@ TUPLE: CreateProcess-args
        stdout-pipe stdin-pipe ;
 
 : default-CreateProcess-args ( -- obj )
-    0
+    CreateProcess-args construct-empty
+    0 >>dwCreateFlags
     "STARTUPINFO" <c-object>
-    "STARTUPINFO" heap-size over set-STARTUPINFO-cb
-    "PROCESS_INFORMATION" <c-object>
-    TRUE
-    {
-        set-CreateProcess-args-dwCreateFlags
-        set-CreateProcess-args-lpStartupInfo
-        set-CreateProcess-args-lpProcessInformation
-        set-CreateProcess-args-bInheritHandles
-    } \ CreateProcess-args construct ;
+    "STARTUPINFO" heap-size over set-STARTUPINFO-cb >>lpStartupInfo
+    "PROCESS_INFORMATION" <c-object> >>lpProcessInformation
+    TRUE >>bInheritHandles ;
 
 : call-CreateProcess ( CreateProcess-args -- )
     {
-        CreateProcess-args-lpApplicationName
-        CreateProcess-args-lpCommandLine
-        CreateProcess-args-lpProcessAttributes
-        CreateProcess-args-lpThreadAttributes
-        CreateProcess-args-bInheritHandles
-        CreateProcess-args-dwCreateFlags
-        CreateProcess-args-lpEnvironment
-        CreateProcess-args-lpCurrentDirectory
-        CreateProcess-args-lpStartupInfo
-        CreateProcess-args-lpProcessInformation
+        lpApplicationName>>
+        lpCommandLine>>
+        lpProcessAttributes>>
+        lpThreadAttributes>>
+        bInheritHandles>>
+        dwCreateFlags>>
+        lpEnvironment>>
+        lpCurrentDirectory>>
+        lpStartupInfo>>
+        lpProcessInformation>>
     } get-slots CreateProcess win32-error=0/f ;
 
 : escape-argument ( str -- newstr )
@@ -54,66 +49,64 @@ TUPLE: CreateProcess-args
 : join-arguments ( args -- cmd-line )
     [ escape-argument ] map " " join ;
 
-: app-name/cmd-line ( -- app-name cmd-line )
-    +command+ get [
+: app-name/cmd-line ( process -- app-name cmd-line )
+    command>> dup string? [
         " " split1
     ] [
-        +arguments+ get unclip swap join-arguments
-    ] if* ;
+        unclip swap join-arguments
+    ] if ;
 
-: cmd-line ( -- cmd-line )
-    +command+ get [ +arguments+ get join-arguments ] unless* ;
+: cmd-line ( process -- cmd-line )
+    command>> dup string? [ join-arguments ] unless ;
 
-: fill-lpApplicationName
-    app-name/cmd-line
-    pick set-CreateProcess-args-lpCommandLine
-    over set-CreateProcess-args-lpApplicationName ;
+: fill-lpApplicationName ( process args -- process args )
+    over app-name/cmd-line
+    >r >>lpApplicationName
+    r> >>lpCommandLine ;
 
-: fill-lpCommandLine
-    cmd-line over set-CreateProcess-args-lpCommandLine ;
+: fill-lpCommandLine ( process args -- process args )
+    over cmd-line >>lpCommandLine ;
 
-: fill-dwCreateFlags
+: fill-dwCreateFlags ( process args -- process args )
     0
-    pass-environment? [ CREATE_UNICODE_ENVIRONMENT bitor ] when
-    +detached+ get winnt? and [ DETACHED_PROCESS bitor ] when
-    over set-CreateProcess-args-dwCreateFlags ;
+    pick pass-environment? [ CREATE_UNICODE_ENVIRONMENT bitor ] when
+    pick detached>> winnt? and [ DETACHED_PROCESS bitor ] when
+    >>dwCreateFlags ;
 
-: fill-lpEnvironment
-    pass-environment? [
+: fill-lpEnvironment ( process args -- process args )
+    over pass-environment? [
         [
-            get-environment
-            [ "=" swap 3append string>u16-alien % ] assoc-each
+            over get-environment
+            [ swap % "=" % % "\0" % ] assoc-each
             "\0" %
-        ] { } make >c-ushort-array
-        over set-CreateProcess-args-lpEnvironment
+        ] "" make >c-ushort-array
+        >>lpEnvironment
     ] when ;
 
-: fill-startup-info
-    dup CreateProcess-args-lpStartupInfo
-    STARTF_USESTDHANDLES swap set-STARTUPINFO-dwFlags ;
+: fill-startup-info ( process args -- process args )
+    STARTF_USESTDHANDLES over lpStartupInfo>> set-STARTUPINFO-dwFlags ;
 
-HOOK: fill-redirection io-backend ( args -- args )
+HOOK: fill-redirection io-backend ( process args -- )
 
-M: windows-ce-io fill-redirection ;
+M: windows-ce-io fill-redirection 2drop ;
 
-: make-CreateProcess-args ( -- args )
+: make-CreateProcess-args ( process -- args )
     default-CreateProcess-args
     wince? [ fill-lpApplicationName ] [ fill-lpCommandLine ] if
     fill-dwCreateFlags
     fill-lpEnvironment
-    fill-startup-info ;
+    fill-startup-info
+    nip ;
 
 M: windows-io current-process-handle ( -- handle )
     GetCurrentProcessId ;
 
-M: windows-io run-process* ( desc -- handle )
+M: windows-io run-process* ( process -- handle )
     [
-        [
-            make-CreateProcess-args
-            fill-redirection
-            dup call-CreateProcess
-            CreateProcess-args-lpProcessInformation <process>
-        ] with-descriptor
+        dup make-CreateProcess-args
+        tuck fill-redirection
+        dup call-CreateProcess
+        lpProcessInformation>>
     ] with-destructors ;
 
 M: windows-io kill-process* ( handle -- )
@@ -134,7 +127,7 @@ M: windows-io kill-process* ( handle -- )
 : process-exited ( process -- )
     dup process-handle exit-code
     over process-handle dispose-process
-    swap notify-exit ;
+    notify-exit ;
 
 : wait-for-processes ( processes -- ? )
     keys dup
diff --git a/extra/io/windows/nt/launcher/launcher-tests.factor b/extra/io/windows/nt/launcher/launcher-tests.factor
new file mode 100755 (executable)
index 0000000..fac6471
--- /dev/null
@@ -0,0 +1,131 @@
+IN: io.windows.launcher.nt.tests\r
+USING: io.launcher tools.test calendar accessors\r
+namespaces kernel system arrays io io.files io.encodings.ascii\r
+sequences parser assocs hashtables ;\r
+\r
+[ ] [\r
+    <process>\r
+        "notepad" >>command\r
+        1/2 seconds >>timeout\r
+    "notepad" set\r
+] unit-test\r
+\r
+[ f ] [ "notepad" get process-running? ] unit-test\r
+\r
+[ f ] [ "notepad" get process-started? ] unit-test\r
+\r
+[ ] [ "notepad" [ run-detached ] change ] unit-test\r
+\r
+[ "notepad" get wait-for-process ] must-fail\r
+\r
+[ t ] [ "notepad" get killed>> ] unit-test\r
+\r
+[ f ] [ "notepad" get process-running? ] unit-test\r
+\r
+[ ] [\r
+    <process>\r
+        vm "-quiet" "-run=hello-world" 3array >>command\r
+        "out.txt" temp-file >>stdout\r
+    try-process\r
+] unit-test\r
+\r
+[ "Hello world" ] [\r
+    "out.txt" temp-file ascii file-lines first\r
+] unit-test\r
+\r
+[ ] [\r
+    <process>\r
+        vm "-run=listener" 2array >>command\r
+        +closed+ >>stdin\r
+    try-process\r
+] unit-test\r
+\r
+[ ] [\r
+    "extra/io/windows/nt/launcher/test" resource-path [\r
+        <process>\r
+            vm "-script" "stderr.factor" 3array >>command\r
+            "out.txt" temp-file >>stdout\r
+            "err.txt" temp-file >>stderr\r
+        try-process\r
+    ] with-directory\r
+] unit-test\r
+\r
+[ "output" ] [\r
+    "out.txt" temp-file ascii file-lines first\r
+] unit-test\r
+\r
+[ "error" ] [\r
+    "err.txt" temp-file ascii file-lines first\r
+] unit-test\r
+\r
+[ ] [\r
+    "extra/io/windows/nt/launcher/test" resource-path [\r
+        <process>\r
+            vm "-script" "stderr.factor" 3array >>command\r
+            "out.txt" temp-file >>stdout\r
+            +stdout+ >>stderr\r
+        try-process\r
+    ] with-directory\r
+] unit-test\r
+\r
+[ "outputerror" ] [\r
+    "out.txt" temp-file ascii file-lines first\r
+] unit-test\r
+\r
+[ "output" ] [\r
+    "extra/io/windows/nt/launcher/test" resource-path [\r
+        <process>\r
+            vm "-script" "stderr.factor" 3array >>command\r
+            "err2.txt" temp-file >>stderr\r
+        ascii <process-stream> lines first\r
+    ] with-directory\r
+] unit-test\r
+\r
+[ "error" ] [\r
+    "err2.txt" temp-file ascii file-lines first\r
+] unit-test\r
+\r
+[ t ] [\r
+    "extra/io/windows/nt/launcher/test" resource-path [\r
+        <process>\r
+            vm "-script" "env.factor" 3array >>command\r
+        ascii <process-stream> contents\r
+    ] with-directory eval\r
+\r
+    os-envs =\r
+] unit-test\r
+\r
+[ t ] [\r
+    "extra/io/windows/nt/launcher/test" resource-path [\r
+        <process>\r
+            vm "-script" "env.factor" 3array >>command\r
+            +replace-environment+ >>environment-mode\r
+            os-envs >>environment\r
+        ascii <process-stream> contents\r
+    ] with-directory eval\r
+    \r
+    os-envs =\r
+] unit-test\r
+\r
+[ "B" ] [\r
+    "extra/io/windows/nt/launcher/test" resource-path [\r
+        <process>\r
+            vm "-script" "env.factor" 3array >>command\r
+            { { "A" "B" } } >>environment\r
+        ascii <process-stream> contents\r
+    ] with-directory eval\r
+\r
+    "A" swap at\r
+] unit-test\r
+\r
+[ f ] [\r
+    "extra/io/windows/nt/launcher/test" resource-path [\r
+        <process>\r
+            vm "-script" "env.factor" 3array >>command\r
+            { { "HOME" "XXX" } } >>environment\r
+            +prepend-environment+ >>environment-mode\r
+        ascii <process-stream> contents\r
+    ] with-directory eval\r
+\r
+    "HOME" swap at "XXX" =\r
+] unit-test\r
index 500a2b0d1fbc47a74f3334c6736ca499b894f85b..c342b2ee9a5e8c9296da0771b4d4a32f3cfcf2ff 100755 (executable)
@@ -5,7 +5,7 @@ io.windows libc io.nonblocking io.streams.duplex windows.types
 math windows.kernel32 windows namespaces io.launcher kernel
 sequences windows.errors assocs splitting system strings
 io.windows.launcher io.windows.nt.pipes io.backend
-combinators shuffle ;
+combinators shuffle accessors locals ;
 IN: io.windows.nt.launcher
 
 : duplicate-handle ( handle -- handle' )
@@ -31,13 +31,12 @@ IN: io.windows.nt.launcher
 : redirect-closed ( default obj access-mode create-mode -- handle )
     drop 2nip null-pipe ;
 
-: redirect-file ( default path access-mode create-mode -- handle )
-    >r >r >r drop r>
-    normalize-pathname
-    r> ! access-mode
+:: redirect-file ( default path access-mode create-mode -- handle )
+    path normalize-pathname
+    access-mode
     share-mode
     security-attributes-inherit
-    r> ! create-mode
+    create-mode
     FILE_ATTRIBUTE_NORMAL ! flags and attributes
     f ! template file
     CreateFile dup invalid-handle? dup close-later ;
@@ -60,24 +59,25 @@ IN: io.windows.nt.launcher
     } cond ;
 
 : default-stdout ( args -- handle )
-    CreateProcess-args-stdout-pipe dup [ pipe-out ] when ;
+    stdout-pipe>> dup [ pipe-out ] when ;
 
-: redirect-stdout ( args -- handle )
+: redirect-stdout ( process args -- handle )
     default-stdout
-    +stdout+ get
+    swap stdout>>
     GENERIC_WRITE
     CREATE_ALWAYS
     redirect
     STD_OUTPUT_HANDLE GetStdHandle or ;
 
-: redirect-stderr ( args -- handle )
-    +stderr+ get +stdout+ eq? [
-        CreateProcess-args-lpStartupInfo
+: redirect-stderr ( process args -- handle )
+    over stderr>> +stdout+ eq? [
+        lpStartupInfo>>
         STARTUPINFO-hStdOutput
+        nip
     ] [
         drop
         f
-        +stderr+ get
+        swap stderr>>
         GENERIC_WRITE
         CREATE_ALWAYS
         redirect
@@ -85,11 +85,11 @@ IN: io.windows.nt.launcher
     ] if ;
 
 : default-stdin ( args -- handle )
-    CreateProcess-args-stdin-pipe dup [ pipe-in ] when ;
+    stdin-pipe>> dup [ pipe-in ] when ;
 
-: redirect-stdin ( args -- handle )
+: redirect-stdin ( process args -- handle )
     default-stdin
-    +stdin+ get
+    swap stdin>>
     GENERIC_READ
     OPEN_EXISTING
     redirect
@@ -97,48 +97,42 @@ IN: io.windows.nt.launcher
 
 : add-pipe-dtors ( pipe -- )
     dup
-    pipe-in close-later
-    pipe-out close-later ;
+    in>> close-later
+    out>> close-later ;
 
-: fill-stdout-pipe
+: fill-stdout-pipe ( args -- args )
     <unique-incoming-pipe>
     dup add-pipe-dtors
     dup pipe-in f set-inherit
-    over set-CreateProcess-args-stdout-pipe ;
+    >>stdout-pipe ;
 
-: fill-stdin-pipe
+: fill-stdin-pipe ( args -- args )
     <unique-outgoing-pipe>
     dup add-pipe-dtors
     dup pipe-out f set-inherit
-    over set-CreateProcess-args-stdin-pipe ;
+    >>stdin-pipe ;
 
-M: windows-nt-io fill-redirection
-    dup CreateProcess-args-lpStartupInfo
-    over redirect-stdout over set-STARTUPINFO-hStdOutput
-    over redirect-stderr over set-STARTUPINFO-hStdError
-    over redirect-stdin over set-STARTUPINFO-hStdInput
-    drop ;
+M: windows-nt-io fill-redirection ( process args -- )
+    [ 2dup redirect-stdout ] keep lpStartupInfo>> set-STARTUPINFO-hStdOutput
+    [ 2dup redirect-stderr ] keep lpStartupInfo>> set-STARTUPINFO-hStdError
+    [ 2dup redirect-stdin  ] keep lpStartupInfo>> set-STARTUPINFO-hStdInput
+    2drop ;
 
 M: windows-nt-io (process-stream)
     [
-        [
-            make-CreateProcess-args
+        dup make-CreateProcess-args
 
-            fill-stdout-pipe
-            fill-stdin-pipe
+        fill-stdout-pipe
+        fill-stdin-pipe
 
-            fill-redirection
+        tuck fill-redirection
 
-            dup call-CreateProcess
+        dup call-CreateProcess
 
-            dup CreateProcess-args-stdin-pipe pipe-in CloseHandle drop
-            dup CreateProcess-args-stdout-pipe pipe-out CloseHandle drop
+        dup stdin-pipe>> pipe-in CloseHandle drop
+        dup stdout-pipe>> pipe-out CloseHandle drop
 
-            dup CreateProcess-args-stdout-pipe pipe-in
-            over CreateProcess-args-stdin-pipe pipe-out
-
-            [ f <win32-file> ] 2apply <reader&writer>
-
-            rot CreateProcess-args-lpProcessInformation <process>
-        ] with-destructors
-    ] with-descriptor ;
+        dup lpProcessInformation>>
+        over stdout-pipe>> in>> f <win32-file>
+        rot stdin-pipe>> out>> f <win32-file>
+    ] with-destructors ;
diff --git a/extra/io/windows/nt/launcher/test/env.factor b/extra/io/windows/nt/launcher/test/env.factor
new file mode 100755 (executable)
index 0000000..a0015f7
--- /dev/null
@@ -0,0 +1,3 @@
+USE: system\r
+USE: prettyprint\r
+os-envs .\r
diff --git a/extra/io/windows/nt/launcher/test/stderr.factor b/extra/io/windows/nt/launcher/test/stderr.factor
new file mode 100755 (executable)
index 0000000..0b97387
--- /dev/null
@@ -0,0 +1,5 @@
+USE: io\r
+USE: namespaces\r
+\r
+"output" write flush\r
+"error" stderr get stream-write stderr get stream-flush\r
index be57a398a2e82fc7c537c543857573cc83adaf5b..9bc587e00e7513a2f40154ed29376844548a9864 100755 (executable)
@@ -9,6 +9,7 @@ USE: io.windows.nt.launcher
 USE: io.windows.nt.monitors
 USE: io.windows.nt.sockets
 USE: io.windows.mmap
+USE: io.windows.files
 USE: io.backend
 
 T{ windows-nt-io } set-io-backend
index 9591063609c403f48da5566cabe254a07d4bb532..eb6dae2a0a0e65a40ea6cecfaf80fb78f5391b0a 100755 (executable)
@@ -3,7 +3,7 @@
 USING: alien alien.c-types arrays destructors io io.windows libc
 windows.types math windows.kernel32 windows namespaces kernel
 sequences windows.errors assocs math.parser system random
-combinators ;
+combinators new-slots accessors ;
 IN: io.windows.nt.pipes
 
 ! This code is based on
@@ -42,8 +42,8 @@ TUPLE: pipe in out ;
 
 : close-pipe ( pipe -- )
     dup
-    pipe-in CloseHandle drop
-    pipe-out CloseHandle drop ;
+    in>> CloseHandle drop
+    out>> CloseHandle drop ;
 
 : <incoming-pipe> ( name -- pipe )
     PIPE_ACCESS_INBOUND GENERIC_WRITE <pipe> ;
@@ -70,13 +70,13 @@ TUPLE: pipe in out ;
 ! /dev/null simulation
 : null-input ( -- pipe )
     <unique-outgoing-pipe>
-    dup pipe-out CloseHandle drop
-    pipe-in ;
+    dup out>> CloseHandle drop
+    in>> ;
 
 : null-output ( -- pipe )
     <unique-incoming-pipe>
-    dup pipe-in CloseHandle drop
-    pipe-out ;
+    dup in>> CloseHandle drop
+    out>> ;
 
 : null-pipe ( mode -- pipe )
     {
index 7af7df9bef7a3994a1e74bfe2c99c2aedcd93734..a63a533ba12c6b27a30a0598ea245016254f1538 100755 (executable)
@@ -45,13 +45,12 @@ TUPLE: ConnectEx-args port
     "stdcall" alien-indirect drop
     winsock-error-string [ throw ] when* ;
 
-: connect-continuation ( ConnectEx -- )
-    dup ConnectEx-args-lpOverlapped*
-    swap ConnectEx-args-port duplex-stream-in
-    [ save-callback ] 2keep
+: connect-continuation ( ConnectEx port -- )
+    >r ConnectEx-args-lpOverlapped* r>
+    2dup save-callback
     get-overlapped-result drop ;
 
-M: windows-nt-io (client) ( addrspec -- duplex-stream )
+M: windows-nt-io (client) ( addrspec -- client-in client-out )
     [
         \ ConnectEx-args construct-empty
         over make-sockaddr/size pick init-connect
@@ -61,14 +60,8 @@ M: windows-nt-io (client) ( addrspec -- duplex-stream )
         dup ConnectEx-args-s* INADDR_ANY roll bind-socket
         dup (ConnectEx)
 
-        dup ConnectEx-args-s* <win32-socket>
-        dup <reader&writer> <duplex-stream>
-        over set-ConnectEx-args-port
-
-        dup connect-continuation
-        ConnectEx-args-port
-        [ duplex-stream-in pending-error ] keep
-        [ duplex-stream-out pending-error ] keep
+        dup ConnectEx-args-s* <win32-socket> dup <reader&writer>
+        >r [ connect-continuation ] keep [ pending-error ] keep r>
     ] with-destructors ;
 
 TUPLE: AcceptEx-args port
@@ -118,17 +111,15 @@ TUPLE: AcceptEx-args port
         ] keep *void*
     ] keep AcceptEx-args-port server-port-addr parse-sockaddr ;
 
-: accept-continuation ( AcceptEx -- client )
+: accept-continuation ( AcceptEx -- addrspec client )
     [ make-accept-continuation ] keep
     [ check-accept-error ] keep
     [ extract-remote-host ] keep
     ! addrspec AcceptEx
-    [
-        AcceptEx-args-sAcceptSocket* add-completion
-    ] keep
+    [ AcceptEx-args-sAcceptSocket* add-completion ] keep
     AcceptEx-args-sAcceptSocket* <win32-socket> ;
 
-M: windows-nt-io (accept) ( server -- client-in client-out )
+M: windows-nt-io (accept) ( server -- addrspec handle )
     [
         [
             dup check-server-port
@@ -137,8 +128,6 @@ M: windows-nt-io (accept) ( server -- client-in client-out )
             [ ((accept)) ] keep
             [ accept-continuation ] keep
             AcceptEx-args-port pending-error
-            dup duplex-stream-in pending-error
-            dup duplex-stream-out pending-error
         ] with-timeout
     ] with-destructors ;
 
index e4338615cedadf6aecac2f23b64eaf095cb5327a..42e51c782a7d2a127e53041181448ebeae1a181d 100644 (file)
@@ -5,10 +5,12 @@ tools.test ;
 
 get-ldp LDAP_OPT_PROTOCOL_VERSION LDAP_VERSION3 <int> set-option
 
-[ B{ 0 0 0 3 } ] [ 
+[ 3 ] [ 
     get-ldp LDAP_OPT_PROTOCOL_VERSION "int*" <c-object> [ get-option ] keep
+    *int
 ] unit-test
 
+[
 get-ldp "cn=jimbob,dc=example,dc=com" "secret" [
 
     ! get-ldp "dc=example,dc=com" LDAP_SCOPE_ONELEVEL "(objectclass=*)" f 0
@@ -52,3 +54,4 @@ get-ldp "cn=jimbob,dc=example,dc=com" "secret" [
     get-ldp get-message next-message msgtype result-type
 
 ] with-bind
+] drop
index 492aed1a546c3a1d83f147d6d533405ac8da3925..ae613bd461009fab3b25a29a0d6c96af8bbc102f 100755 (executable)
@@ -9,11 +9,11 @@ USING: alien alien.syntax combinators kernel system ;
 
 IN: ldap.libldap
 
-"libldap" {
+<< "libldap" {
     { [ win32? ] [ "libldap.dll" "stdcall" ] }
     { [ macosx? ] [ "libldap.dylib" "cdecl" ] }
     { [ unix? ] [ "$LD_LIBRARY_PATH/libldap.so" "cdecl" ] }
-} cond add-library
+} cond add-library >>
  
 : LDAP_VERSION1     1 ; inline
 : LDAP_VERSION2     2 ; inline 
index b530c09b22a564f389bfc08448c54ad2083e0f9d..e2c77377ac7f4193777d64fa28af0dde5d2770e0 100755 (executable)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2008 Slava Pestov.\r
 ! See http://factorcode.org/license.txt for BSD license.\r
 USING: kernel sequences namespaces words assocs logging sorting\r
-prettyprint io io.styles strings logging.parser ;\r
+prettyprint io io.styles strings logging.parser calendar.format ;\r
 IN: logging.analysis\r
 \r
 SYMBOL: word-names\r
@@ -42,16 +42,14 @@ SYMBOL: message-histogram
     ] tabular-output ;\r
 \r
 : log-entry.\r
-    [\r
-        dup first [ write ] with-cell\r
-        dup second [ pprint ] with-cell\r
-        dup third [ write ] with-cell\r
-        fourth "\n" join [ write ] with-cell\r
-    ] with-row ;\r
+    "====== " write\r
+    dup first (timestamp>string) bl\r
+    dup second pprint bl\r
+    dup third write nl\r
+    fourth "\n" join print ;\r
 \r
 : errors. ( errors -- )\r
-    standard-table-style\r
-    [ [ log-entry. ] each ] tabular-output ;\r
+    [ log-entry. ] each ;\r
 \r
 : analysis. ( errors word-histogram message-histogram -- )\r
     "==== INTERESTING MESSAGES:" print nl\r
index 0294085eda4fcb793d351c3c6c35408bd9a67779..dfd7f430d2e3d4a8fafdabe6522ad47defb1eee4 100755 (executable)
@@ -1,8 +1,9 @@
 ! Copyright (C) 2008 Slava Pestov.\r
 ! See http://factorcode.org/license.txt for BSD license.\r
-USING: logging.analysis logging.server logging smtp io.sockets\r
-kernel io.files io.streams.string namespaces raptor.cron assocs\r
-io.encodings.utf8 ;\r
+USING: logging.analysis logging.server logging smtp kernel\r
+io.files io.streams.string namespaces alarms assocs\r
+io.encodings.utf8 accessors calendar qualified ;\r
+QUALIFIED: io.sockets\r
 IN: logging.insomniac\r
 \r
 SYMBOL: insomniac-smtp-host\r
@@ -25,17 +26,20 @@ SYMBOL: insomniac-recipients
     ] with-scope ; inline\r
 \r
 : email-subject ( service -- string )\r
-    [ "[INSOMNIAC] " % % " on " % host-name % ] "" make ;\r
+    [\r
+        "[INSOMNIAC] " % % " on " % io.sockets:host-name %\r
+    ] "" make ;\r
 \r
 : (email-log-report) ( service word-names -- )\r
     [\r
-        over >r\r
-        ?analyze-log dup [\r
-            r> email-subject\r
-            insomniac-recipients get\r
-            insomniac-sender get\r
-            send-simple-message\r
-        ] [ r> 2drop ] if\r
+        dupd ?analyze-log dup [\r
+            <email>\r
+                swap >>body\r
+                insomniac-recipients get >>to\r
+                insomniac-sender get >>from\r
+                swap email-subject >>subject\r
+            send\r
+        ] [ 2drop ] if\r
     ] with-insomniac-smtp ;\r
 \r
 \ (email-log-report) NOTICE add-error-logging\r
@@ -44,6 +48,5 @@ SYMBOL: insomniac-recipients
     "logging.insomniac" [ (email-log-report) ] with-logging ;\r
 \r
 : schedule-insomniac ( service word-names -- )\r
-    { 25 } { 6 } f f f <when> -rot [\r
-        [ email-log-report ] assoc-each rotate-logs\r
-    ] 2curry schedule ;\r
+    [ [ email-log-report ] assoc-each rotate-logs ] 2curry\r
+    1 days every drop ;\r
index 528e770558d12ecfa51814eaf34d6e33a2a0af3f..8e7af02597bb0699fdd062ed437738dda0cd59f2 100644 (file)
@@ -2,7 +2,7 @@
 ! USING: kernel quotations namespaces sequences assocs.lib ;
 
 USING: kernel namespaces namespaces.private quotations sequences
-       assocs.lib ;
+       assocs.lib math.parser math sequences.lib ;
 
 IN: namespaces.lib
 
@@ -17,3 +17,30 @@ IN: namespaces.lib
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 : set* ( val var -- ) namestack* set-assoc-stack ;
+
+SYMBOL: building-seq 
+: get-building-seq ( n -- seq )
+    building-seq get nth ;
+
+: n, get-building-seq push ;
+: n% get-building-seq push-all ;
+: n# >r number>string r> n% ;
+
+: 0, 0 n, ;
+: 0% 0 n% ;
+: 0# 0 n# ;
+: 1, 1 n, ;
+: 1% 1 n% ;
+: 1# 1 n# ;
+: 2, 2 n, ;
+: 2% 2 n% ;
+: 2# 2 n# ;
+
+: nmake ( quot exemplars -- seqs )
+    dup length dup zero? [ 1+ ] when
+    [
+        [
+            [ drop 1024 swap new-resizable ] 2map
+            [ building-seq set call ] keep
+        ] 2keep >r [ like ] 2map r> firstn 
+    ] with-scope ;
index 29016f6d57046c40b0a4e5c52138775a4c19b508..8d1b3b524704364f8f6ac8d0aa756d9bbfe07daa 100644 (file)
@@ -9,11 +9,11 @@ USING: alien alien.syntax combinators kernel system ;
 
 IN: openssl.libssl
 
-"libssl" {
+<< "libssl" {
     { [ win32? ] [ "ssleay32.dll" "stdcall" ] }
     { [ macosx? ] [ "libssl.dylib" "cdecl" ] }
     { [ unix? ] [ "$LD_LIBRARY_PATH/libssl.so" "cdecl" ] }
-} cond add-library
+} cond add-library >>
 
 : X509_FILETYPE_PEM       1 ; inline
 : X509_FILETYPE_ASN1      2 ; inline
index 85ccc70c25a86567bb4b741f5988b2c6e76b0eda..a40b7cddeed165c3c81d51c7bb0f44a3fd5be0b8 100644 (file)
@@ -9,11 +9,11 @@ USING: alien alien.syntax combinators system ;
 
 IN: pdf.libhpdf
 
-"libhpdf" {
+<< "libhpdf" {
     { [ win32? ] [ "libhpdf.dll" "stdcall" ] }
     { [ macosx? ] [ "libhpdf.dylib" "cdecl" ] }
     { [ unix? ] [ "$LD_LIBRARY_PATH/libhpdf.so" "cdecl" ] }
-} cond add-library
+} cond add-library >>
 
 ! compression mode
 : HPDF_COMP_NONE      HEX: 00 ; inline ! No contents are compressed
index dc42874d2a6c1a71c1a5bf9c0d1b28ad6bde0e55..097f671d9af67ad6d565782c3db2f6136a688c02 100644 (file)
@@ -92,6 +92,6 @@ SYMBOL: twidth
 
     ] with-text
 
-    "extra/pdf/test/font_test.pdf" resource-path save-to-file
+    "font_test.pdf" temp-file save-to-file
 
 ] with-pdf
diff --git a/extra/pdf/test/font_test.pdf b/extra/pdf/test/font_test.pdf
deleted file mode 100644 (file)
index 4360cf3..0000000
+++ /dev/null
@@ -1,300 +0,0 @@
-%PDF-1.3
-%·¾­ª
-1 0 obj
-<<
-/Type /Catalog
-/Pages 2 0 R
->>
-endobj
-2 0 obj
-<<
-/Type /Pages
-/Kids [ 4 0 R ]
-/Count 1
->>
-endobj
-3 0 obj
-<<
-/Producer (Haru\040Free\040PDF\040Library\0402.0.8)
->>
-endobj
-4 0 obj
-<<
-/Type /Page
-/MediaBox [ 0 0 595 841 ]
-/Contents 5 0 R
-/Resources <<
-/ProcSet [ /PDF /Text /ImageB /ImageC /ImageI ]
-/Font <<
-/F1 7 0 R
-/F2 8 0 R
-/F3 9 0 R
-/F4 10 0 R
-/F5 11 0 R
-/F6 12 0 R
-/F7 13 0 R
-/F8 14 0 R
-/F9 15 0 R
-/F10 16 0 R
-/F11 17 0 R
-/F12 18 0 R
-/F13 19 0 R
-/F14 20 0 R
->>
->>
-/Parent 2 0 R
->>
-endobj
-5 0 obj
-<<
-/Length 6 0 R
->>
-stream\r
-1 w
-50 50 495 731 re
-S
-/F1 24 Tf
-BT
-238.148 791 Td
-(Font\040Demo) Tj
-ET
-BT
-/F1 16 Tf
-60 761 Td
-(\074Standard\040Type1\040font\040samples\076) Tj
-ET
-BT
-60 736 Td
-/F2 9 Tf
-(Courier) Tj
-0 -18 Td
-/F2 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F3 9 Tf
-(Courier-Bold) Tj
-0 -18 Td
-/F3 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F4 9 Tf
-(Courier-Oblique) Tj
-0 -18 Td
-/F4 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F5 9 Tf
-(Courier-BoldOblique) Tj
-0 -18 Td
-/F5 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F1 9 Tf
-(Helvetica) Tj
-0 -18 Td
-/F1 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F6 9 Tf
-(Helvetica-Bold) Tj
-0 -18 Td
-/F6 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F7 9 Tf
-(Helvetica-Oblique) Tj
-0 -18 Td
-/F7 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F8 9 Tf
-(Helvetica-BoldOblique) Tj
-0 -18 Td
-/F8 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F9 9 Tf
-(Times-Roman) Tj
-0 -18 Td
-/F9 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F10 9 Tf
-(Times-Bold) Tj
-0 -18 Td
-/F10 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F11 9 Tf
-(Times-Italic) Tj
-0 -18 Td
-/F11 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F12 9 Tf
-(Times-BoldItalic) Tj
-0 -18 Td
-/F12 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F13 9 Tf
-(Symbol) Tj
-0 -18 Td
-/F13 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-/F14 9 Tf
-(ZapfDingbats) Tj
-0 -18 Td
-/F14 20 Tf
-(abcdefgABCDEFG12345!\043$\045&+-@?) Tj
-0 -20 Td
-ET
-
-endstream
-endobj
-6 0 obj
-1517
-endobj
-7 0 obj
-<<
-/Type /Font
-/BaseFont /Helvetica
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-8 0 obj
-<<
-/Type /Font
-/BaseFont /Courier
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-9 0 obj
-<<
-/Type /Font
-/BaseFont /Courier-Bold
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-10 0 obj
-<<
-/Type /Font
-/BaseFont /Courier-Oblique
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-11 0 obj
-<<
-/Type /Font
-/BaseFont /Courier-BoldOblique
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-12 0 obj
-<<
-/Type /Font
-/BaseFont /Helvetica-Bold
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-13 0 obj
-<<
-/Type /Font
-/BaseFont /Helvetica-Oblique
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-14 0 obj
-<<
-/Type /Font
-/BaseFont /Helvetica-BoldOblique
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-15 0 obj
-<<
-/Type /Font
-/BaseFont /Times-Roman
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-16 0 obj
-<<
-/Type /Font
-/BaseFont /Times-Bold
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-17 0 obj
-<<
-/Type /Font
-/BaseFont /Times-Italic
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-18 0 obj
-<<
-/Type /Font
-/BaseFont /Times-BoldItalic
-/Subtype /Type1
-/Encoding /StandardEncoding
->>
-endobj
-19 0 obj
-<<
-/Type /Font
-/BaseFont /Symbol
-/Subtype /Type1
->>
-endobj
-20 0 obj
-<<
-/Type /Font
-/BaseFont /ZapfDingbats
-/Subtype /Type1
->>
-endobj
-xref
-0 21
-0000000000 65535 f\r
-0000000015 00000 n\r
-0000000064 00000 n\r
-0000000123 00000 n\r
-0000000196 00000 n\r
-0000000518 00000 n\r
-0000002089 00000 n\r
-0000002109 00000 n\r
-0000002207 00000 n\r
-0000002303 00000 n\r
-0000002404 00000 n\r
-0000002509 00000 n\r
-0000002618 00000 n\r
-0000002722 00000 n\r
-0000002829 00000 n\r
-0000002940 00000 n\r
-0000003041 00000 n\r
-0000003141 00000 n\r
-0000003243 00000 n\r
-0000003349 00000 n\r
-0000003417 00000 n\r
-trailer
-<<
-/Root 1 0 R
-/Info 3 0 R
-/Size 21
->>
-startxref
-3491
-%%EOF
index 6dff95c8293c93f9c19d321a46b850a12853f5d5..9ad375ea042912373ea8770ca1dd575d175c4a60 100644 (file)
@@ -135,9 +135,10 @@ HELP: hide
 \r
 HELP: delay\r
 { $values \r
+  { "quot" "a quotation" } \r
   { "parser" "a parser" } \r
 }\r
 { $description \r
     "Delays the construction of a parser until it is actually required to parse. This " \r
     "allows for calling a parser that results in a recursive call to itself. The quotation "\r
-    "should return the constructed parser." } ;
\ No newline at end of file
+    "should return the constructed parser." } ;\r
index 01decc2c8118d5c6be0422f47ee18720ad311d09..16cf40f8842a7e8c6cbead7015ec3d89d08de3f3 100755 (executable)
@@ -358,7 +358,7 @@ MEMO: sp ( parser -- parser )
 MEMO: hide ( parser -- parser )
   [ drop ignore ] action ;
 
-MEMO: delay ( parser -- parser )
+MEMO: delay ( quot -- parser )
   delay-parser construct-boa init-parser ;
 
 : PEG:
index c65001be098dfaf07cdd3cecc4e7694941e9dbb9..b22a5ef0d0da6a0f258ac48e142948e616680099 100755 (executable)
@@ -1,7 +1,8 @@
 ! Copyright (C) 2007 Chris Double.
 ! See http://factorcode.org/license.txt for BSD license.
 !
-USING: kernel math math.parser arrays tools.test peg peg.search ;
+USING: kernel math math.parser arrays tools.test peg peg.parsers
+peg.search ;
 IN: peg.search.tests
 
 { V{ 123 456 } } [
index ab528786bbd7658b85b2f10a3093ea27206145f7..f7eac4c32db6f603d7c48327b7cbaa4e09a1c08c 100755 (executable)
@@ -54,7 +54,6 @@ IN: random-tester.safe-words
 
 : method-words
     {
-        method-def
         forget-word
     } ;
 
diff --git a/extra/regexp2/regexp2-tests.factor b/extra/regexp2/regexp2-tests.factor
new file mode 100644 (file)
index 0000000..1fb3f61
--- /dev/null
@@ -0,0 +1,5 @@
+USING: kernel peg regexp2 sequences tools.test ;
+IN: regexp2.tests
+
+[ T{ parse-result f T{ slice f 3 3 "056" } 46 } ]
+    [ "056" 'octal' parse ] unit-test
diff --git a/extra/regexp2/regexp2.factor b/extra/regexp2/regexp2.factor
new file mode 100644 (file)
index 0000000..e62eb76
--- /dev/null
@@ -0,0 +1,262 @@
+USING: assocs combinators.lib kernel math math.parser
+namespaces peg unicode.case sequences unicode.categories
+memoize peg.parsers ;
+USE: io
+USE: tools.walker
+IN: regexp2
+
+<PRIVATE
+    
+SYMBOL: ignore-case?
+
+: char=-quot ( ch -- quot )
+    ignore-case? get
+    [ ch>upper [ swap ch>upper = ] ] [ [ = ] ] if
+    curry ;
+    
+: char-between?-quot ( ch1 ch2 -- quot )
+    ignore-case? get
+    [ [ ch>upper ] 2apply [ >r >r ch>upper r> r> between? ] ]
+    [ [ between? ] ]
+    if 2curry ;
+    
+: or-predicates ( quots -- quot )
+    [ \ dup add* ] map [ [ t ] ] f short-circuit \ nip add ;
+
+: literal-action [ nip ] curry action ;
+
+: delay-action [ curry ] curry action ;
+    
+PRIVATE>
+
+: ascii? ( n -- ? )
+    0 HEX: 7f between? ;
+    
+: octal-digit? ( n -- ? ) 
+    CHAR: 0 CHAR: 7 between? ;
+
+: hex-digit? ( n -- ? )
+    {
+        [ dup digit? ]
+        [ dup CHAR: a CHAR: f between? ]
+        [ dup CHAR: A CHAR: F between? ]
+    } || nip ;
+
+: control-char? ( n -- ? )
+    { [ dup 0 HEX: 1f between? ] [ dup HEX: 7f = ] } || nip ;
+
+: punct? ( n -- ? )
+    "!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~" member? ;
+
+: c-identifier-char? ( ch -- ? )
+    { [ dup alpha? ] [ dup CHAR: _ = ] } || nip ;
+
+: java-blank? ( n -- ? )
+    {
+        CHAR: \s
+        CHAR: \t CHAR: \n CHAR: \r
+        HEX: c HEX: 7 HEX: 1b
+    } member? ;
+
+: java-printable? ( n -- ? )
+    { [ dup alpha? ] [ dup punct? ] } || nip ;
+
+MEMO: 'ordinary-char' ( -- parser )
+    [ "\\^*+?|(){}[$" member? not ] satisfy
+    [ char=-quot ] action ;
+
+MEMO: 'octal-digit' ( -- parser ) [ octal-digit? ] satisfy ;
+
+MEMO: 'octal' ( -- parser )
+    "0" token hide 'octal-digit' 1 3 from-m-to-n 2seq
+    [ first oct> ] action ;
+
+MEMO: 'hex-digit' ( -- parser ) [ hex-digit? ] satisfy ;
+
+MEMO: 'hex' ( -- parser )
+    "x" token hide 'hex-digit' 2 exactly-n 2seq
+    "u" token hide 'hex-digit' 6 exactly-n 2seq 2choice
+    [ first hex> ] action ;
+
+: satisfy-tokens ( assoc -- parser )
+    [ >r token r> literal-action ] { } assoc>map choice ;
+
+MEMO: 'simple-escape-char' ( -- parser )
+    {
+        { "\\" CHAR: \\ }
+        { "t"  CHAR: \t }
+        { "n"  CHAR: \n }
+        { "r"  CHAR: \r }
+        { "f"  HEX: c   }
+        { "a"  HEX: 7   }
+        { "e"  HEX: 1b  }
+    } [ char=-quot ] assoc-map satisfy-tokens ;
+
+MEMO: 'predefined-char-class' ( -- parser )
+    {   
+        { "d" [ digit? ] } 
+        { "D" [ digit? not ] }
+        { "s" [ java-blank? ] } 
+        { "S" [ java-blank? not ] }
+        { "w" [ c-identifier-char? ] } 
+        { "W" [ c-identifier-char? not ] }
+    } satisfy-tokens ;
+
+MEMO: 'posix-character-class' ( -- parser )
+    {   
+        { "Lower" [ letter? ] }
+        { "Upper" [ LETTER? ] }
+        { "ASCII" [ ascii? ] }
+        { "Alpha" [ Letter? ] }
+        { "Digit" [ digit? ] }
+        { "Alnum" [ alpha? ] }
+        { "Punct" [ punct? ] }
+        { "Graph" [ java-printable? ] }
+        { "Print" [ java-printable? ] }
+        { "Blank" [ " \t" member? ] }
+        { "Cntrl" [ control-char? ] }
+        { "XDigit" [ hex-digit? ] }
+        { "Space" [ java-blank? ] }
+    } satisfy-tokens "p{" "}" surrounded-by ;
+
+MEMO: 'simple-escape' ( -- parser )
+    [
+        'octal' ,
+        'hex' ,
+        "c" token hide [ LETTER? ] satisfy 2seq ,
+        any-char ,
+    ] choice* [ char=-quot ] action ;
+
+MEMO: 'escape' ( -- parser )
+    "\\" token hide [
+        'simple-escape-char' ,
+        'predefined-char-class' ,
+        'posix-character-class' ,
+        'simple-escape' ,
+    ] choice* 2seq ;
+
+MEMO: 'any-char' ( -- parser )
+    "." token [ drop t ] literal-action ;
+
+MEMO: 'char' ( -- parser )
+    'any-char' 'escape' 'ordinary-char' 3choice [ satisfy ] action ;
+
+DEFER: 'regexp'
+
+TUPLE: group-result str ;
+
+C: <group-result> group-result
+
+MEMO: 'non-capturing-group' ( -- parser )
+    "?:" token hide 'regexp' ;
+
+MEMO: 'positive-lookahead-group' ( -- parser )
+    "?=" token hide 'regexp' [ ensure ] action ;
+
+MEMO: 'negative-lookahead-group' ( -- parser )
+    "?!" token hide 'regexp' [ ensure-not ] action ;
+
+MEMO: 'simple-group' ( -- parser )
+    'regexp' [ [ <group-result> ] action ] action ;
+
+MEMO: 'group' ( -- parser )
+    [
+        'non-capturing-group' ,
+        'positive-lookahead-group' ,
+        'negative-lookahead-group' ,
+        'simple-group' ,
+    ] choice* "(" ")" surrounded-by ;
+
+MEMO: 'range' ( -- parser )
+    any-char "-" token hide any-char 3seq
+    [ first2 char-between?-quot ] action ;
+
+MEMO: 'character-class-term' ( -- parser )
+    'range'
+    'escape'
+    [ "\\]" member? not ] satisfy [ char=-quot ] action
+    3choice ;
+
+MEMO: 'positive-character-class' ( -- parser )
+    ! todo
+    "]" token [ CHAR: ] = ] literal-action 'character-class-term' repeat0 2seq 
+    'character-class-term' repeat1 2choice [ or-predicates ] action ;
+
+MEMO: 'negative-character-class' ( -- parser )
+    "^" token hide 'positive-character-class' 2seq
+    [ [ not ] append ] action ;
+
+MEMO: 'character-class' ( -- parser )
+    'negative-character-class' 'positive-character-class' 2choice
+    "[" "]" surrounded-by [ satisfy ] action ;
+
+MEMO: 'escaped-seq' ( -- parser )
+    any-char repeat1
+    [ ignore-case? get token ] action "\\Q" "\\E" surrounded-by ;
+    
+MEMO: 'break' ( quot -- parser )
+    satisfy ensure
+    epsilon just 2choice ;
+    
+MEMO: 'break-escape' ( -- parser )
+    "$" token [ "\r\n" member? ] 'break' literal-action
+    "\\b" token [ blank? ] 'break' literal-action
+    "\\B" token [ blank? not ] 'break' literal-action
+    "\\z" token epsilon just literal-action 4choice ;
+    
+MEMO: 'simple' ( -- parser )
+    [
+        'escaped-seq' ,
+        'break-escape' ,
+        'group' ,
+        'character-class' ,
+        'char' ,
+    ] choice* ;
+
+MEMO: 'exactly-n' ( -- parser )
+    'integer' [ exactly-n ] delay-action ;
+
+MEMO: 'at-least-n' ( -- parser )
+    'integer' "," token hide 2seq [ at-least-n ] delay-action ;
+
+MEMO: 'at-most-n' ( -- parser )
+    "," token hide 'integer' 2seq [ at-most-n ] delay-action ;
+
+MEMO: 'from-m-to-n' ( -- parser )
+    'integer' "," token hide 'integer' 3seq
+    [ first2 from-m-to-n ] delay-action ;
+
+MEMO: 'greedy-interval' ( -- parser )
+    'exactly-n' 'at-least-n' 'at-most-n' 'from-m-to-n' 4choice ;
+
+MEMO: 'interval' ( -- parser )
+    'greedy-interval'
+    'greedy-interval' "?" token hide 2seq [ "reluctant {}" print ] action
+    'greedy-interval' "+" token hide 2seq [ "possessive {}" print ] action
+    3choice "{" "}" surrounded-by ;
+
+MEMO: 'repetition' ( -- parser )
+    [
+        ! Possessive
+        ! "*+" token [ <!*> ] literal-action ,
+        ! "++" token [ <!+> ] literal-action ,
+        ! "?+" token [ <!?> ] literal-action ,
+        ! Reluctant
+        ! "*?" token [ <(*)> ] literal-action ,
+        ! "+?" token [ <(+)> ] literal-action ,
+        ! "??" token [ <(?)> ] literal-action ,
+        ! Greedy
+        "*" token [ repeat0 ] literal-action ,
+        "+" token [ repeat1 ] literal-action ,
+        "?" token [ optional ] literal-action ,
+    ] choice* ;
+
+MEMO: 'dummy' ( -- parser )
+    epsilon [ ] literal-action ;
+
+! todo -- check the action
+! MEMO: 'term' ( -- parser )
+    ! 'simple'
+    ! 'repetition' 'interval' 'dummy' 3choice 2seq [ first2 call ] action
+    ! <!+> [ <and-parser> ] action ;
+
index c02932a020b389bd368f6b0076560fa321d6c794..050de0ae1c41671cbe053b6ca04d4f1ff7cf0e0f 100755 (executable)
@@ -140,13 +140,13 @@ PRIVATE>
 : strings ( alphabet length -- seqs )
     >r dup length r> number-strings map-alphabet ;
 
-: nths ( nths seq -- subseq )
-    ! nths is a sequence of ones and zeroes
+: switches ( seq1 seq -- subseq )
+    ! seq1 is a sequence of ones and zeroes
     >r [ length ] keep [ nth 1 = ] curry subset r>
     [ nth ] curry { } map-as ;
 
 : power-set ( seq -- subsets )
-    2 over length exact-number-strings swap [ nths ] curry map ;
+    2 over length exact-number-strings swap [ switches ] curry map ;
 
 : push-either ( elt quot accum1 accum2 -- )
     >r >r keep swap r> r> ? push ; inline
@@ -214,3 +214,9 @@ PRIVATE>
 
 : attempt-each ( seq quot -- result )
     (each) iterate-prep (attempt-each-integer) ; inline
+
+: ?nth* ( n seq -- elt/f ? )
+    2dup bounds-check? [ nth-unsafe t ] [ 2drop f f ] if ; flushable
+
+: nths ( indices seq -- seq' )
+    [ swap nth ] with map ;
diff --git a/extra/singleton/authors.txt b/extra/singleton/authors.txt
new file mode 100644 (file)
index 0000000..7c1b2f2
--- /dev/null
@@ -0,0 +1 @@
+Doug Coleman
diff --git a/extra/singleton/singleton-docs.factor b/extra/singleton/singleton-docs.factor
new file mode 100644 (file)
index 0000000..b87c557
--- /dev/null
@@ -0,0 +1,14 @@
+USING: help.markup help.syntax ;
+IN: singleton
+
+HELP: SINGLETON:
+{ $syntax "SINGLETON: class"
+} { $values
+    { "class" "a new tuple class to define" }
+} { $description
+    "Defines a new tuple class with membership predicate name? and a default empty constructor that is the class name itself."
+} { $examples
+    { $example "SINGLETON: foo\nfoo ." "T{ foo f }" }
+} { $see-also
+    POSTPONE: TUPLE:
+} ;
diff --git a/extra/singleton/singleton.factor b/extra/singleton/singleton.factor
new file mode 100644 (file)
index 0000000..b745e8f
--- /dev/null
@@ -0,0 +1,10 @@
+! Copyright (C) 2007 Doug Coleman.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel parser quotations prettyprint tuples words ;
+IN: singleton
+
+: SINGLETON:
+    CREATE-CLASS
+    dup { } define-tuple-class
+    dup unparse create-in reset-generic
+    dup construct-empty 1quotation define ; parsing
index a0065d6fe3d2aade15a97bb478ee4f95902e5d88..b58253381cb1085eac99a0c82ff8818a0d70be11 100755 (executable)
@@ -6,10 +6,14 @@ IN: slides
 
 : stylesheet
     H{
-        { default-style
+        { default-span-style
             H{
                 { font "sans-serif" }
                 { font-size 36 }
+            }
+        }
+        { default-block-style
+            H{
                 { wrap-margin 1000 }
             }
         }
index c1afeced3d8f314b7a004be185d0b022febe7382..76ceaceea4e72abccbadf9c4f338e4a4a7b35fb0 100755 (executable)
@@ -1,5 +1,6 @@
 USING: smtp tools.test io.streams.string threads
-smtp.server kernel sequences namespaces logging ;
+smtp.server kernel sequences namespaces logging accessors
+assocs sorting ;
 IN: smtp.tests
 
 { 0 0 } [ [ ] with-smtp-connection ] must-infer-as
@@ -12,7 +13,7 @@ IN: smtp.tests
 [ { "hello" "." "world" } validate-message ] must-fail
 
 [ "hello\r\nworld\r\n.\r\n" ] [
-    { "hello" "world" } [ send-body ] with-string-writer
+    "hello\nworld" [ send-body ] with-string-writer
 ] unit-test
 
 [ "500 syntax error" check-response ] must-fail
@@ -38,62 +39,44 @@ IN: smtp.tests
 ] must-fail
 
 [
-    V{
-        { "To" "Slava <slava@factorcode.org>, Ed <dharmatech@factorcode.org>" }
+    {
         { "From" "Doug <erg@factorcode.org>" }
         { "Subject" "Factor rules" }
+        { "To" "Slava <slava@factorcode.org>, Ed <dharmatech@factorcode.org>" }
     }
     { "slava@factorcode.org" "dharmatech@factorcode.org" }
     "erg@factorcode.org"
 ] [
-    "Factor rules"
-    {
-        "Slava <slava@factorcode.org>"
-        "Ed <dharmatech@factorcode.org>"
-    }
-    "Doug <erg@factorcode.org>"
-    simple-headers >r >r 2 head* r> r>
-] unit-test
-
-[
-    {
-        "To: Slava <slava@factorcode.org>, Ed <dharmatech@factorcode.org>"
-        "From: Doug <erg@factorcode.org>"
-        "Subject: Factor rules"
-        f
-        f
-        ""
-        "Hi guys"
-        "Bye guys"
-    }
-    { "slava@factorcode.org" "dharmatech@factorcode.org" }
-    "erg@factorcode.org"
-] [
-    "Hi guys\nBye guys"
-    "Factor rules"
-    {
-        "Slava <slava@factorcode.org>"
-        "Ed <dharmatech@factorcode.org>"
-    }
-    "Doug <erg@factorcode.org>"
-    prepare-simple-message
-    >r >r f 3 pick set-nth f 4 pick set-nth r> r>
+    <email>
+        "Factor rules" >>subject
+        {
+            "Slava <slava@factorcode.org>"
+            "Ed <dharmatech@factorcode.org>"
+        } >>to
+        "Doug <erg@factorcode.org>" >>from
+    prepare
+    dup headers>> >alist sort-keys [
+        drop { "Date" "Message-Id" } member? not
+    ] assoc-subset
+    over to>>
+    rot from>>
 ] unit-test
 
 [ ] [ [ 4321 smtp-server ] in-thread ] unit-test
 
 [ ] [
     [
+        "localhost" smtp-host set
         4321 smtp-port set
 
-        "Hi guys\nBye guys"
-        "Factor rules"
-        {
-            "Slava <slava@factorcode.org>"
-            "Ed <dharmatech@factorcode.org>"
-        }
-        "Doug <erg@factorcode.org>"
-
-        send-simple-message
+        <email>
+            "Hi guys\nBye guys" >>body
+            "Factor rules" >>subject
+            {
+                "Slava <slava@factorcode.org>"
+                "Ed <dharmatech@factorcode.org>"
+            } >>to
+            "Doug <erg@factorcode.org>" >>from
+        send
     ] with-scope
-] unit-test
\ No newline at end of file
+] unit-test
index bbec129ef61cc2990303cc28380e983236172f7f..b23d5e37987eadbe431e01e83e12a56abd586f15 100755 (executable)
@@ -3,8 +3,8 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: namespaces io io.timeouts kernel logging io.sockets
 sequences combinators sequences.lib splitting assocs strings
-math.parser random system calendar io.encodings.ascii calendar.format ;
-
+math.parser random system calendar io.encodings.ascii
+calendar.format new-slots accessors ;
 IN: smtp
 
 SYMBOL: smtp-domain
@@ -49,6 +49,7 @@ SYMBOL: esmtp           t esmtp set-global
     "." over member? [ "Message cannot contain . on a line by itself" throw ] when ;
 
 : send-body ( body -- )
+    string-lines
     validate-message
     [ write crlf ] each
     "." write crlf ;
@@ -89,28 +90,36 @@ LOG: smtp-response DEBUG
 
 : get-ok ( -- ) flush receive-response check-response ;
 
-: send-raw-message ( body to from -- )
-    [
-        helo get-ok
-        mail-from get-ok
-        [ rcpt-to get-ok ] each
-        data get-ok
-        send-body get-ok
-        quit get-ok
-    ] with-smtp-connection ;
-
 : validate-header ( string -- string' )
     dup [ "\r\n" member? ] contains?
     [ "Invalid header string: " swap append throw ] when ;
 
-: prepare-header ( key value -- )
+: write-header ( key value -- )
     swap
-    validate-header %
-    ": " %
-    validate-header % ;
+    validate-header write
+    ": " write
+    validate-header write
+    crlf ;
+
+: write-headers ( assoc -- )
+    [ write-header ] assoc-each ;
+
+TUPLE: email from to subject headers body ;
 
-: prepare-headers ( assoc -- )
-    [ [ prepare-header ] "" make , ] assoc-each ;
+M: email clone
+    (clone) [ clone ] change-headers ;
+
+: (send) ( email -- )
+    [
+        helo get-ok
+        dup from>> mail-from get-ok
+        dup to>> [ rcpt-to get-ok ] each
+        data get-ok
+        dup headers>> write-headers
+        crlf
+        body>> send-body get-ok
+        quit get-ok
+    ] with-smtp-connection ;
 
 : extract-email ( recepient -- email )
     #! This could be much smarter.
@@ -127,30 +136,25 @@ LOG: smtp-response DEBUG
         ">" %
     ] "" make ;
 
-: simple-headers ( subject to from -- headers to from )
-    [
-        >r dup ", " join "To" set [ extract-email ] map r>
-        dup "From" set extract-email
-        rot "Subject" set
-        now timestamp>rfc822-string "Date" set
-        message-id "Message-Id" set
-    ] { } make-assoc -rot ;
-
-: prepare-message ( body headers -- body' )
-    [
-        prepare-headers
-        "" ,
-        dup string? [ string-lines ] when %
-    ] { } make ;
+: set-header ( email value key -- email )
+    pick headers>> set-at ;
 
-: prepare-simple-message ( body subject to from -- body' to from )
-    simple-headers >r >r prepare-message r> r> ;
+: prepare ( email -- email )
+    clone
+    dup from>> "From" set-header
+    [ extract-email ] change-from
+    dup to>> ", " join "To" set-header
+    [ [ extract-email ] map ] change-to
+    dup subject>> "Subject" set-header
+    now timestamp>rfc822-string "Date" set-header
+    message-id "Message-Id" set-header ;
 
-: send-message ( body headers to from -- )
-    >r >r prepare-message r> r> send-raw-message ;
+: <email> ( -- email )
+    email construct-empty
+    H{ } clone >>headers ;
 
-: send-simple-message ( body subject to from -- )
-    prepare-simple-message send-raw-message ;
+: send ( email -- )
+    prepare (send) ;
 
 ! Dirk's old AUTH CRAM-MD5 code. I don't know anything about
 ! CRAM MD5, and the old code didn't work properly either, so here
@@ -171,13 +175,3 @@ LOG: smtp-response DEBUG
 !     (cram-md5-auth) "\r\n" append get-ok ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-
-USE: new-slots
-
-TUPLE: email from to subject body ;
-
-: <email> ( -- email ) email construct-empty ;
-
-: send ( email -- )
-  { email-body email-subject email-to email-from } get-slots
-  send-simple-message ;
index bcdc0f806fdc7ebc0484b6ff086456d69f0898f0..6e8a231b81f475d2193c8596c3ea177b7cf7ed3b 100755 (executable)
@@ -6,7 +6,7 @@ continuations math definitions mirrors splitting parser classes
 inspector layouts vocabs.loader prettyprint.config prettyprint
 debugger io.streams.c io.streams.duplex io.files io.backend
 quotations io.launcher words.private tools.deploy.config
-bootstrap.image io.encodings.utf8 ;
+bootstrap.image io.encodings.utf8 accessors ;
 IN: tools.deploy.backend
 
 : (copy-lines) ( stream -- )
@@ -17,11 +17,11 @@ IN: tools.deploy.backend
     [ (copy-lines) ] with-disposal ;
 
 : run-with-output ( arguments -- )
-    [
-        +arguments+ set
-        +stdout+ +stderr+ set
-    ] H{ } make-assoc utf8 <process-stream>
-    dup duplex-stream-out dispose
+    <process>
+        swap >>command
+        +stdout+ >>stderr
+        +closed+ >>stdin
+    utf8 <process-stream>
     dup copy-lines
     process-stream-process wait-for-process zero? [
         "Deployment failed" throw
index 647b02baa56b981669eecba44719a857d854e0e3..1e003dcf69fad8a7c3b62c30220b454198cd6e1f 100755 (executable)
@@ -2,7 +2,7 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: io.files io words alien kernel math.parser alien.syntax
 io.launcher system assocs arrays sequences namespaces qualified
-system math generator.fixup io.encodings.ascii ;
+system math generator.fixup io.encodings.ascii accessors ;
 IN: tools.disassembler
 
 : in-file "gdb-in.txt" temp-file ;
@@ -23,11 +23,11 @@ M: pair make-disassemble-cmd
     ] with-file-writer ;
 
 : run-gdb ( -- lines )
-    [
-        +closed+ +stdin+ set
-        out-file +stdout+ set
-        [ "gdb" , "-x" , in-file , "-batch" , ] { } make +arguments+ set
-    ] { } make-assoc try-process
+    <process>
+        +closed+ >>stdin
+        out-file >>stdout
+        [ "gdb" , "-x" , in-file , "-batch" , ] { } make >>command
+    try-process
     out-file ascii file-lines ;
 
 : tabs>spaces ( str -- str' )
index e5f157463dec6b32cb47241000ac803b0f68687d..4ba96fb9c48bf1b9aab1f0afc45d75b70c44c298 100644 (file)
@@ -1,7 +1,7 @@
 USING: unicode.syntax ;
 IN: unicode.categories
 
-CATEGORY: blank Zs Zl Zp ;
+CATEGORY: blank Zs Zl Zp \r\n ;
 CATEGORY: letter Ll ;
 CATEGORY: LETTER Lu ;
 CATEGORY: Letter Lu Ll Lt Lm Lo ;
index 204321f30cbe097876c995edf74fdfeb580cef0e..6d60caf9872546bb71fdce3585210b0815a2ba62 100644 (file)
@@ -74,3 +74,8 @@ FUNCTION: int mkdir ( char* path, mode_t mode ) ;
   "stat" <c-object> dup >r
     stat check-status
   r> ;
+
+: lstat* ( pathname -- stat )
+  "stat" <c-object> dup >r
+    lstat check-status
+  r> ;
index 9cc8552f986ef868bc0dfcf4ce9a0f79846b7b3a..e1d49b8c6cf2af2af80c1f9005a021c0769ec0ba 100755 (executable)
@@ -21,6 +21,7 @@ TYPEDEF: ulong size_t
 
 : MAP_FAILED -1 <alien> ; inline
 
+: ESRCH 3 ; inline
 : EEXIST 17 ; inline
 
 ! ! ! Unix functions
diff --git a/extra/webapps/callback/authors.txt b/extra/webapps/callback/authors.txt
deleted file mode 100755 (executable)
index a8fb961..0000000
+++ /dev/null
@@ -1,2 +0,0 @@
-Chris Double
-Slava Pestov
diff --git a/extra/webapps/callback/callback.factor b/extra/webapps/callback/callback.factor
deleted file mode 100644 (file)
index 6bdc84b..0000000
+++ /dev/null
@@ -1,126 +0,0 @@
-! Copyright (C) 2004 Chris Double.
-! Copyright (C) 2006 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: html http http.server.responders io kernel math
-namespaces prettyprint continuations random system sequences
-assocs ;
-IN: webapps.callback
-
-#! Name of the variable holding the continuation used to exit
-#! back to the httpd responder.
-SYMBOL: exit-continuation 
-
-#! Tuple to hold global request data. This gets passed to
-#! the continuation when resumed so it can restore things
-#! like 'stdio' so it writes to the correct socket. 
-TUPLE: request stream exitcc method url raw-query query header response ;
-
-: <request> ( -- request )
-  stdio get
-  exit-continuation get
-  "method" get
-  "request" get
-  "raw-query" get
-  "query" get
-  "header" get
-  "response" get
-  request construct-boa ;
-
-: restore-request ( -- )
-  request get 
-  dup request-stream stdio set 
-  dup request-method "method" set 
-  dup request-raw-query "raw-query" set 
-  dup request-query "query" set 
-  dup request-header "header" set 
-  dup request-response "response" set 
-  request-exitcc exit-continuation set ;
-
-: update-request ( request new-request -- )
-  [ request-stream over set-request-stream ] keep 
-  [ request-method over set-request-method ] keep 
-  [ request-url over set-request-url ] keep 
-  [ request-raw-query over set-request-raw-query ] keep 
-  [ request-query over set-request-query ] keep 
-  [ request-header over set-request-header ] keep 
-  [ request-response over set-request-response ] keep 
-  request-exitcc swap set-request-exitcc ;
-  
-: with-exit-continuation ( quot -- ) 
-    #! Call the quotation with the variable exit-continuation bound 
-    #! such that when the exit continuation is called, computation 
-    #! will resume from the end of this 'with-exit-continuation' call. 
-    [ 
-        exit-continuation set call exit-continuation get continue
-    ] callcc0 drop ;
-
-: expiry-timeout ( -- ms ) 900 1000 * ;
-
-: get-random-id ( -- id ) 
-    #! Generate a random id to use for continuation URL's
-    4 big-random unparse ;
-
-: callback-table ( -- <hashtable> ) 
-    #! Return the global table of continuations
-    \ callback-table get-global ;
-
-: reset-callback-table ( -- ) 
-    #! Create the initial global table
-    H{ } clone \ callback-table set-global ;
-
-reset-callback-table
-
-#! Tuple for holding data related to a callback.
-TUPLE: item quot expire? request id  time-added ;
-
-: <item> ( quot expire? request id -- item )
-    millis item construct-boa ;
-
-: expired? ( item -- ? )
-    #! Return true if the callback item is expirable
-    #! and has expired (ie. was added to the table more than
-    #! timeout milliseconds ago).
-    [ item-time-added expiry-timeout + millis < ] keep
-    item-expire? and ;
-
-: expire-callbacks ( -- )
-    #! Expire all continuations in the continuation table
-    #! if they are 'timeout-seconds' old (ie. were added
-    #! more than 'timeout-seconds' ago.
-    callback-table clone [
-        expired? [ callback-table delete-at ] [ drop ] if
-    ] assoc-each ;
-
-: id>url ( id -- string )
-    #! Convert the continuation id to an URL suitable for
-    #! embedding in an HREF or other HTML.
-    "/responder/callback/?id=" swap url-encode append ;
-
-: register-callback ( quot expire? -- url ) 
-    #! Store a continuation in the table and associate it with
-    #! a random id. That continuation will be expired after
-    #! a certain period of time if 'expire?' is true.  
-    request get get-random-id [ <item> ] keep
-    [ callback-table set-at ] keep
-    id>url ;
-
-: register-html-callback ( quot expire? -- url )
-    >r [ serving-html ] swap append r> register-callback ;
-
-: callback-responder ( -- )   
-    expire-callbacks
-    "id" query-param callback-table at [
-        [
-          dup item-request [
-            <request> update-request
-          ] when*
-          item-quot call 
-          exit-continuation get continue 
-        ] with-exit-continuation drop
-    ] [
-        "404 Callback not available" httpd-error
-    ] if* ;
-
-global [
-    "callback" [ callback-responder ] add-simple-responder
-] bind
diff --git a/extra/webapps/continuation/authors.txt b/extra/webapps/continuation/authors.txt
deleted file mode 100755 (executable)
index 44b06f9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Chris Double
diff --git a/extra/webapps/continuation/continuation.factor b/extra/webapps/continuation/continuation.factor
deleted file mode 100644 (file)
index 6b6838d..0000000
+++ /dev/null
@@ -1,151 +0,0 @@
-! Copyright (C) 2004 Chris Double.
-! See http://factorcode.org/license.txt for BSD license.
-
-USING: http math namespaces io strings kernel html html.elements
-hashtables continuations quotations parser generic sequences
-webapps.callback http.server.responders ;
-IN: webapps.continuation
-
-#! Used inside the session state of responders to indicate whether the
-#! next request should use the post-refresh-get pattern. It is set to
-#! true after each request.
-SYMBOL: post-refresh-get?
-
-: >callable ( quot|interp|f -- interp )
-    dup continuation? [
-        [ continue ] curry
-    ] when ;
-
-: forward-to-url ( url -- )
-    #! When executed inside a 'show' call, this will force a
-    #! HTTP 302 to occur to instruct the browser to forward to
-    #! the request URL.
-    [
-        "HTTP/1.1 302 Document Moved\nLocation: " % %
-        "\nContent-Length: 0\nContent-Type: text/plain\n\n" %
-    ] "" make write exit-continuation get continue ;
-
-: forward-to-id ( id -- )
-    #! When executed inside a 'show' call, this will force a
-    #! HTTP 302 to occur to instruct the browser to forward to
-    #! the request URL.
-    >r "request" get r> id>url append forward-to-url ;
-
-SYMBOL: current-show
-
-: store-current-show ( -- )
-  #! Store the current continuation in the variable 'current-show'
-  #! so it can be returned to later by href callbacks. Note that it
-  #! recalls itself when the continuation is called to ensure that
-  #! it resets its value back to the most recent show call.
-  [  ( 0 -- )
-      [ ( 0 1 -- )
-          current-show set ( 0 -- )
-          continue
-      ] callcc1
-      nip
-      restore-request
-      call
-      store-current-show
-  ] callcc0 restore-request ;
-
-: redirect-to-here ( -- )
-    #! Force a redirect to the client browser so that the browser
-    #! goes to the current point in the code. This forces an URL
-    #! change on the browser so that refreshing that URL will
-    #! immediately run from this code point. This prevents the
-    #! "this request will issue a POST" warning from the browser
-    #! and prevents re-running the previous POST logic. This is
-    #! known as the 'post-refresh-get' pattern.
-    post-refresh-get? get [
-        [
-            >callable t register-callback forward-to-url
-        ] callcc0  restore-request
-    ] [
-        t post-refresh-get? set
-    ] if ;
-
-: (show) ( quot -- hashtable )
-    #! See comments for show. The difference is the
-    #! quotation MUST set the content-type using 'serving-html'
-    #! or similar.
-    store-current-show redirect-to-here
-    [
-        >callable t register-callback swap with-scope
-        exit-continuation get  continue
-    ] callcc0 drop restore-request "response" get ;
-
-: show ( quot -- namespace )
-    #! Call the quotation with the URL associated with the current
-    #! continuation. All output from the quotation goes to the client
-    #! browser. When the URL is later referenced then
-    #! computation will resume from this 'show' call with a hashtable on
-    #! the stack containing any query or post parameters.
-    #! 'quot' has stack effect ( url -- )
-    #! NOTE: On return from 'show' the stack is exactly the same as
-    #! initial entry with 'quot' popped off and the hashtable pushed on. Even
-    #! if the quotation consumes items on the stack.
-    [ serving-html ] swap append (show) ;
-
-: (show-final) ( quot -- namespace )
-    #! See comments for show-final. The difference is the
-    #! quotation MUST set the content-type using 'serving-html'
-    #! or similar.
-    store-current-show redirect-to-here
-    with-scope exit-continuation get continue ;
-
-: show-final ( quot -- namespace )
-    #! Similar to 'show', except the quotation does not receive the URL
-    #! to resume computation following 'show-final'. No continuation is
-    #! stored for this resumption. As a result, 'show-final' is for use
-    #! when a page is to be displayed with no further action to occur. Its
-    #! use is an optimisation to save having to generate and save a continuation
-    #! in that special case.
-    #! 'quot' has stack effect ( -- ).
-    [ serving-html ] swap compose (show-final) ;
-
-#! Name of variable for holding initial continuation id that starts
-#! the responder.
-SYMBOL: root-callback
-
-: cont-get/post-responder ( id-or-f -- )
-    #! httpd responder that handles the root continuation request.
-    #! The requests for actual continuation are processed by the
-    #! 'callback-responder'.
-    [
-        [ f post-refresh-get? set <request> request set root-callback get call ] with-scope
-        exit-continuation get continue
-    ] with-exit-continuation  drop ;
-
-: quot-url ( quot -- url )
-    current-show get [ continue-with ] 2curry t register-callback ;
-
-: quot-href ( text quot -- )
-    #! Write to standard output an HTML HREF where the href,
-    #! when referenced, will call the quotation and then return
-    #! back to the most recent 'show' call (via the callback-cc).
-    #! The text of the link will be the 'text' argument on the
-    #! stack.
-    <a quot-url =href a> write </a> ;
-
-: install-cont-responder ( name quot -- )
-    #! Install a cont-responder with the given name
-    #! that will initially run the given quotation.
-    #!
-    #! Convert the quotation so it is run within a session namespace
-    #! and that namespace is initialized first.
-    [
-        [ cont-get/post-responder ] "get" set
-        [ cont-get/post-responder ] "post" set
-        swap "responder" set
-        root-callback set
-    ] make-responder ;
-
-: show-message-page ( message -- )
-    #! Display the message in an HTML page with an OK button.
-    [
-        "Press OK to Continue" [
-            swap paragraph
-            <a =href a> "OK" write </a>
-        ] simple-page
-    ] show 2drop ;
diff --git a/extra/webapps/continuation/examples/authors.txt b/extra/webapps/continuation/examples/authors.txt
deleted file mode 100755 (executable)
index 44b06f9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Chris Double
diff --git a/extra/webapps/continuation/examples/examples.factor b/extra/webapps/continuation/examples/examples.factor
deleted file mode 100644 (file)
index 2899562..0000000
+++ /dev/null
@@ -1,115 +0,0 @@
-! Copyright (C) 2004 Chris Double.
-! 
-! Redistribution and use in source and binary forms, with or without
-! modification, are permitted provided that the following conditions are met:
-! 
-! 1. Redistributions of source code must retain the above copyright notice,
-!    this list of conditions and the following disclaimer.
-! 
-! 2. Redistributions in binary form must reproduce the above copyright notice,
-!    this list of conditions and the following disclaimer in the documentation
-!    and/or other materials provided with the distribution.
-! 
-! THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-! INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-! FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-! DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-! OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-! WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-!
-! Simple test applications
-USING: hashtables html kernel io html html.elements strings math
-assocs quotations webapps.continuation namespaces prettyprint
-sequences ;
-
-IN: webapps.continuation.examples
-
-: display-page ( title -- ) 
-  #! Display a page with some text to test the cont-responder.
-  #! The page has a link to the 'next' continuation.
-  [ 
-    <h1> over write </h1>
-    swap [ 
-      <a =href a> "Next" write </a>
-    ] simple-html-document 
-  ] show 2drop ;
-
-: display-get-name-page ( -- name )
-  #! Display a page prompting for input of a name and return that name.
-  [ 
-    "Enter your name" [
-      <h1> swap write </h1>
-      <form "post" =method =action form> 
-        "Name: " write
-        <input "text" =type "name" =name "20" =size input/>
-        <input "submit" =type "Ok" =value input/>
-      </form>
-    ] simple-html-document
-  ] show "name" swap at ;
-
-: test-cont-responder ( -- )
-  #! Test the cont-responder responder by displaying a few pages in a row.
-  "Page one" display-page 
-  "Hello " display-get-name-page append display-page
-  "Page three" display-page ;
-
-: test-cont-responder2 ( -- )
-  #! Test the cont-responder responder by displaying a few pages in a loop.
-  [ "one" "two" "three" "four" ] [ display-page ]  each 
-  "Done!" display-page  ;
-
-: test-cont-responder3 ( -- )
-  #! Test the quot-href word by displaying a menu of the current
-  #! test words. Note that we use show-final as we don't link to a 'next' page.
-  [ 
-    "Menu" [ 
-      <h1> "Menu" write </h1>
-      <ol> 
-        <li> "Test responder1" [ test-cont-responder ] quot-href </li>
-        <li> "Test responder2" [ test-cont-responder2 ] quot-href </li>
-      </ol>
-    ] simple-html-document 
-  ] show-final ;
-
-: counter-example ( count -- )
-  #! Display a counter which can be incremented or decremented
-  #! using anchors.
-  #!
-  #! Don't need the original alist
-  [ 
-    #! And we don't need the 'url' argument
-    drop         
-    "Counter: " over unparse append [ 
-      dup <h2> unparse write </h2>
-      "++" over 1quotation [ f ] swap append [ 1 + counter-example ] append quot-href
-      "--" over 1quotation [ f ] swap append [ 1 - counter-example ] append quot-href
-      drop
-    ] simple-html-document 
-  ] show drop ;
-
-: counter-example2 ( -- )
-  #! Display a counter which can be incremented or decremented
-  #! using anchors.
-  #!
-  0 "counter" set
-  [ 
-    #! We don't need the 'url' argument
-    drop   
-    "Counter: " "counter" get unparse append [ 
-      <h2> "counter" get unparse write </h2>
-      "++" [ "counter" get 1 + "counter" set ] quot-href
-      "--" [ "counter" get 1 - "counter" set ] quot-href
-    ] simple-html-document 
-  ] show 
-  drop ;
-
-! Install the examples
-"counter1" [ drop 0 counter-example ] install-cont-responder
-"counter2" [ drop counter-example2 ] install-cont-responder
-"test1" [ test-cont-responder ] install-cont-responder
-"test2" [ drop test-cont-responder2 ] install-cont-responder
-"test3" [ drop test-cont-responder3 ] install-cont-responder
diff --git a/extra/webapps/fjsc/authors.txt b/extra/webapps/fjsc/authors.txt
deleted file mode 100644 (file)
index 44b06f9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Chris Double
diff --git a/extra/webapps/fjsc/fjsc.factor b/extra/webapps/fjsc/fjsc.factor
deleted file mode 100755 (executable)
index cf01bf6..0000000
+++ /dev/null
@@ -1,70 +0,0 @@
-! Copyright (C) 2006 Chris Double. All Rights Reserved.
-! See http://factorcode.org/license.txt for BSD license.
-!
-USING: kernel furnace fjsc  peg namespaces
-       lazy-lists io io.files furnace.validator sequences
-       http.client http.server http.server.responders
-       webapps.file html ;
-IN: webapps.fjsc
-
-: compile ( code -- )
-  #! Compile the factor code as a string, outputting the http
-  #! response containing the javascript.
-  serving-text
-  'expression' parse parse-result-ast fjsc-compile
-  write flush ;
-
-! The 'compile' action results in an URL that looks like
-! 'responder/fjsc/compile'. It takes one query or post
-! parameter called 'code'. It calls the 'compile' word
-! passing the parameter to it on the stack.
-\ compile {
-  { "code" v-required }
-} define-action
-
-: compile-url ( url -- )
-  #! Compile the factor code at the given url, return the javascript.
-  dup "http:" head? [ "Unable to access remote sites." throw ] when
-  "http://" "host" header-param rot 3append http-get compile "();" write flush ;
-
-\ compile-url {
-  { "url" v-required }
-} define-action
-
-: render-page* ( model body-template head-template -- )
-  [
-      [ render-component ] [ f rot render-component ] html-document 
-  ] serve-html ;
-
-: repl ( -- )
-  #! The main 'repl' page.
-  f "repl" "head" render-page* ;
-
-! An action called 'repl'
-\ repl { } define-action
-
-: fjsc-web-app ( -- )
-  ! Create the web app, providing access
-  ! under '/responder/fjsc' which calls the
-  ! 'repl' action.
-  "fjsc" "repl" "extra/webapps/fjsc" web-app
-
-  ! An URL to the javascript resource files used by
-  ! the 'fjsc' responder.
-  "fjsc-resources" [
-   [
-     "extra/fjsc/resources/" resource-path doc-root set
-     file-responder
-   ] with-scope
-  ] add-simple-responder
-
-  ! An URL to the resource files used by
-  ! 'termlib'.
-  "fjsc-repl-resources" [
-   [
-     "extra/webapps/fjsc/resources/" resource-path doc-root set
-     file-responder
-   ] with-scope
-  ] add-simple-responder ;
-
-MAIN: fjsc-web-app
diff --git a/extra/webapps/fjsc/head.furnace b/extra/webapps/fjsc/head.furnace
deleted file mode 100644 (file)
index 97a3645..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<title>Factor to Javascript REPL</title>\r
-<link rel="stylesheet" type="text/css" href="/responder/fjsc-repl-resources/termlib/term_styles.css"/>\r
-<script type="text/javascript" src="/responder/fjsc-repl-resources/termlib/termlib.js"></script>\r
-<script type="text/javascript" src="/responder/fjsc-resources/jquery.js"></script>\r
-<script type="text/javascript" src="/responder/fjsc-resources/bootstrap.js"></script>\r
-<script type="text/javascript" src="/responder/fjsc-repl-resources/repl.js"></script>\r
-<script type="text/javascript" src="/responder/fjsc/compile-url?url=/responder/fjsc-resources/bootstrap.factor"></script>\r
diff --git a/extra/webapps/fjsc/repl.furnace b/extra/webapps/fjsc/repl.furnace
deleted file mode 100644 (file)
index c67e9d4..0000000
+++ /dev/null
@@ -1,43 +0,0 @@
-<table border="0">
-<tr><td valign="top">
-<div id="repl" style="position:relative;"></div>
-<p>More information on the Factor to Javascript compiler can be found at these blog posts:
-<ul>
-<li><a href="http://www.bluishcoder.co.nz/2006/12/compiling-factor-to-javascript.html">Factor to Javascript Compiler</a></li>
-<li><a href="http://www.bluishcoder.co.nz/2006/12/factor-to-javascript-compiler-updates.html">Factor to Javascript Compiler Updates</a></li>
-<li><a href="http://www.bluishcoder.co.nz/2006/12/continuations-added-to-fjsc.html">Continuations added to fjsc</a></li>
-<li><a href="http://www.bluishcoder.co.nz/2006/12/cross-domain-json-with-fjsc.html">Cross Domain JSON with fjsc</a></li>
-<li><a href="http://www.bluishcoder.co.nz/2007/02/factor-to-javascript-compiler-makeover.html">Factor to Javascript Compiler Makeover</a></li>
-</ul>
-</p>
-<p>The terminal emulation code for the Factor REPL is provided by the awesome <a href="http://www.masswerk.at/termlib/index.html">termlib</a> library by Norbert Landsteiner. Documentation for termlib is <a href="/responder/fjsc-repl-resources/termlib/">available here</a>. Please note the license of 'termlib':</p>
-<blockquote>This JavaScript-library is free for private and academic use. Please include a readable copyright statement and a backlink to <http://www.masswerk.at> in the web page. The library should always be accompanied by the "readme.txt" and the sample HTML-documents.
-
-The term "private use" includes any personal or non-commercial use, which is not related to commercial activites, but excludes intranet, extranet and/or public net applications that are related to any kind of commercial or profit oriented activity.
-
-For commercial use see <a href="http://www.masswerk.at">http://www.masswerk.at</a> for contact information.</blockquote>
-</td>
-<td valign="top">
-<p><b>Stack</b></p>
-<div id="stack">
-</div>
-<p><b>Playground</b></p>
-<div id="playground">
-</div>
-<h3>Compiled Code</h3>
-<textarea id="compiled" cols="40" rows="10">
-</textarea>
-<p>Some useful words:
-<dl>
-<dt>vocabs ( -- seq )</dt>
-<dd>Return a sequence of available vocabularies</dd>
-<dt>words ( string -- seq )</dt>
-<dd>Return a sequence of words in the given vocabulary</dd>
-<dt>all-words ( -- seq )</dt>
-<dd>Return a sequence of all words</dd>
-</dl>
-</p>
-<p>The contents of <a href="/responder/fjsc-resources/bootstrap.factor">bootstrap.factor</a> have been loaded on startup.</p>
-</td>
-</tr>
-</table>
diff --git a/extra/webapps/fjsc/resources/repl.js b/extra/webapps/fjsc/resources/repl.js
deleted file mode 100644 (file)
index 3bc8bdc..0000000
+++ /dev/null
@@ -1,99 +0,0 @@
-/* Copyright (C) 2007 Chris Double. All Rights Reserved.\r
-   See http://factorcode.org/license.txt for BSD license. */\r
-\r
-var fjsc_repl = false;\r
-\r
-function fjsc_repl_handler() {\r
-  var my_term = this;\r
-  this.newLine();\r
-  if(this.lineBuffer != '') {\r
-    factor.server_eval(\r
-      this.lineBuffer, \r
-      function(text, result) { \r
-        document.getElementById("compiled").value = result;\r
-        display_datastack();        \r
-      }, \r
-      function() { my_term.prompt(); });\r
-  }\r
-  else\r
-    my_term.prompt();\r
-}\r
-\r
-function fjsc_init_handler() {\r
-  this.write(\r
-    [\r
-      TermGlobals.center('********************************************************'),\r
-      TermGlobals.center('*                                                      *'),\r
-      TermGlobals.center('*       Factor to Javascript Compiler Example          *'),\r
-      TermGlobals.center('*                                                      *'),\r
-      TermGlobals.center('********************************************************')\r
-    ]);\r
-  \r
-  this.prompt();\r
-}\r
-\r
-function startup() {\r
-  var conf = {\r
-    x: 0,\r
-    y: 0,\r
-    cols: 64,\r
-    rows: 18,\r
-    termDiv: "repl",\r
-    crsrBlinkMode: true,\r
-    ps: "scratchpad ",\r
-    initHandler: fjsc_init_handler,\r
-    handler: fjsc_repl_handler\r
-  };\r
-  fjsc_repl = new Terminal(conf);\r
-  fjsc_repl.open();\r
-}\r
-\r
-function display_datastack() {\r
-   var html=[];\r
-   html.push("<table border='1'>")\r
-   for(var i = 0; i < factor.cont.data_stack.length; ++i) {\r
-      html.push("<tr><td>")\r
-      html.push(factor.cont.data_stack[i])\r
-      html.push("</td></tr>")\r
-   }\r
-   html.push("</table>")\r
-   document.getElementById('stack').innerHTML=html.join("");\r
-}\r
-\r
-jQuery(function() {\r
-  startup();\r
-  display_datastack();\r
-});\r
-\r
-factor.add_word("kernel", ".s", "primitive", function(next) {   \r
-  var stack = factor.cont.data_stack;\r
-  var term = fjsc_repl;\r
-  for(var i=0; i<stack.length; ++i) {\r
-    term.type(""+stack[i]);\r
-    term.newLine();\r
-  }\r
-  factor.call_next(next);\r
-});\r
-\r
-factor.add_word("io", "print", "primitive", function(next) {   \r
-  var stack = factor.cont.data_stack;\r
-  var term = fjsc_repl;\r
-  term.type(""+stack.pop());\r
-  term.newLine();\r
-  factor.call_next(next);\r
-});\r
-\r
-factor.add_word("io", "write", "primitive", function(next) {   \r
-  var stack = factor.cont.data_stack;\r
-  var term = fjsc_repl;\r
-  term.type(""+stack.pop());\r
-  factor.call_next(next);\r
-});\r
-\r
-factor.add_word("io", ".", "primitive", function(next) {   \r
-  var stack = factor.cont.data_stack;\r
-  var term = fjsc_repl;\r
-  term.type(""+stack.pop());\r
-  term.newLine();\r
-  factor.call_next(next);\r
-});\r
diff --git a/extra/webapps/fjsc/resources/termlib/faq.html b/extra/webapps/fjsc/resources/termlib/faq.html
deleted file mode 100644 (file)
index 5adb516..0000000
+++ /dev/null
@@ -1,356 +0,0 @@
-<HTML>\r
-<HEAD>\r
-       <TITLE>mass:werk termlib faq</TITLE>\r
-\r
-<STYLE TYPE="text/css">\r
-body,p,a,td {\r
-       font-family: courier,fixed,swiss,sans-serif;\r
-       font-size: 12px;\r
-       color: #cccccc;\r
-}\r
-.lh13 {\r
-       line-height: 13px;\r
-}\r
-.lh15 {\r
-       line-height: 15px;\r
-}\r
-pre {\r
-       font-family: courier,fixed,swiss,sans-serif;\r
-       color: #ccffaa;\r
-       font-size: 12px;\r
-       line-height: 15px;\r
-}\r
-.prop {\r
-       font-family: courier,fixed,swiss,sans-serif;\r
-       color: #bbee99;\r
-       font-size: 12px;\r
-       line-height: 15px;\r
-}\r
-h1 {\r
-       font-family: courier,fixed,swiss,sans-serif;\r
-       font-size: 16px;\r
-       color: #cccccc;\r
-}\r
-b.quest {\r
-       font-family: courier,fixed,swiss,sans-serif;\r
-       font-size: 14px;\r
-       font-weight: bold;\r
-       color: #bbee99;\r
-}\r
-a,a:link,a:visited {\r
-       text-decoration: none;\r
-       color: #77dd11;\r
-}\r
-a:hover {\r
-       text-decoration: underline;\r
-       color: #77dd11;\r
-}\r
-a:active {\r
-       text-decoration: underline;\r
-       color: #dddddd;\r
-}\r
-\r
-@media print {\r
-       body { background-color: #ffffff; }\r
-       body,p,a,td {\r
-               font-family: courier,fixed,swiss,sans-serif;\r
-               font-size: 12px;\r
-               color: #000000;\r
-       }\r
-       .lh13 {\r
-               line-height: 13px;\r
-       }\r
-       .lh15 {\r
-               line-height: 15px;\r
-       }\r
-       pre,.prop {\r
-               font-family: courier,fixed,swiss,sans-serif;\r
-               font-size: 12px;\r
-               color: #000000;\r
-               line-height: 15px;\r
-       }\r
-       h1 {\r
-               font-family: courier,fixed,swiss,sans-serif;\r
-               font-size: 16px;\r
-               color: #000000;\r
-       }\r
-       b.quest {\r
-               font-family: courier,fixed,swiss,sans-serif;\r
-               font-size: 14px;\r
-               font-weight: bold;\r
-               color: #000000;\r
-       }\r
-       a,a:link,a:visited {\r
-               text-decoration: none;\r
-               color: #000000;\r
-       }\r
-       a:hover {\r
-               text-decoration: underline;\r
-               color: #000000;\r
-       }\r
-       a:active {\r
-               text-decoration: underline;\r
-               color: #000000;\r
-       }\r
-}\r
-</STYLE>\r
-</HEAD>\r
-\r
-\r
-<BODY BGCOLOR="#222222" LINK="#77dd11" TEXT="#cccccc" ALINK="#dddddd" VLINK="#77dd11"\r
-TOPMARGIN="0" BOTTOMMARGIN="0" LEFTMARGIN="0" RIGHTMARGIN="0" MARGINHEIGHT="0" MARGINWIDTH="0"><A NAME="top"></A>\r
-\r
-<TABLE BORDER="0" CELLSPACING="20" CELLPADDING="0" ALIGN="center">\r
-<TR>\r
-       <TD NOWRAP><A HREF="index.html">termlib.js home</A></TD>\r
-       <TD>|</TD>\r
-       <TD NOWRAP><A HREF="multiterm_test.html">multiple terminal test</A></TD>\r
-       <TD>|</TD>\r
-       <TD NOWRAP><A HREF="parser_sample.html">sample parser</A></TD>\r
-       <TD>|</TD>\r
-       <TD NOWRAP>faq</TD>\r
-       <TD>|</TD>\r
-       <TD NOWRAP><A HREF="readme.txt" TITLE="readme.txt (text/plain)">documentation</A></TD>\r
-</TR>\r
-</TABLE>\r
-\r
-<TABLE BORDER="0" CELLSPACING="20" CELLPADDING="0" WIDTH="700" ALIGN="center">\r
-       <TR><TD>\r
-               <H1>frequently asked questions</H1>\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13">\r
-&nbsp;<BR>\r
-       <UL>\r
-       <LI CLASS="lh15"><A HREF="#chrome">Can I add chrome to the terminal? (e.g. a window header, a close box)</A></LI>\r
-       <LI CLASS="lh15"><A HREF="#embed">How can I embed a terminal relative to my HTML layout?</A></LI>\r
-       <LI CLASS="lh15"><A HREF="#syntax">I pasted your sample code and just got an error. - ???</A></LI>\r
-       <LI CLASS="lh15"><A HREF="#keyboard">I can't get any input, but I don't get any erros too.</A></LI>\r
-       <LI CLASS="lh15"><A HREF="#keylock">How can I temporary disable the keyboard handlers?</A></LI>\r
-       <LI CLASS="lh15"><A HREF="#linesranges">How can I set the cusor to the start / the end of the command line?</A></LI>\r
-       <LI CLASS="lh15"><A HREF="#historyunique">How can I limit the command history to unique entries only?</A></LI>\r
-       <LI CLASS="lh15"><A HREF="#rebuild">How can I change my color theme on the fly?</A></LI>\r
-       <LI CLASS="lh15"><A HREF="#connect">How can I connect to a server?</A></LI>\r
-       </UL>\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13"><A NAME="chrome"></A>\r
-&nbsp;<BR>\r
-<B CLASS="quest">Can I add chrome to the terminal? (e.g. a window header, a close box)</B><BR><BR>\r
-\r
-Not by the means of the Terminal object's interface (since there are way too many things that you may possibly want to add).<BR>\r
-The Terminal object allows you to specify the background color, the frame color, the frame's width and the font class used. If you want to add more chrome, you must align this in a separate division element.<BR><BR>\r
-\r
-To calculate the dimensions of the terminal use this formula:<BR><BR>\r
-\r
-width:&nbsp; 2 * frameWidth + conf.cols * &lt;width of &nbsp;&gt; + 2 * 2px padding (left and right)<BR>\r
-height: 2 * frameWidth + conf.rows * conf.rowHeight + 2 * 2px padding (top and bottom).<BR><BR>\r
-\r
-Or you could get the empirical values for width and height by calling a terminal's `<SPAN CLASS="prop">getDimensions()</SPAN>' method, once the terminal is open. (see documentation in &quot;readme.txt&quot;).<BR><BR>\r
-\r
-Finnally, you could obviously embed the terminal's division element in your custom chrome layout (see below). [This will not be compatible to Netscape 4.]<BR><BR>\r
-\r
-p.e.:<PRE>\r
-  &lt;div id=&quot;myTerminal1&quot; style=&quot;position:absolute; top:100px; left:100px;&quot;&gt;\r
-     &lt;table class=&quot;termChrome&quot;&gt;\r
-       &lt;tbody&gt;\r
-        &lt;tr&gt;\r
-           &lt;td class=&quot;termTitle&quot;&gt;terminal 1&lt;/td&gt;\r
-        &lt;/tr&gt;\r
-        &lt;tr&gt;\r
-           &lt;td class=&quot;termBody&quot;&gt;&lt;div id=&quot;termDiv1&quot; style=&quot;position:relative&quot;&gt;&lt;/div&gt;&lt;/td&gt;\r
-        &lt;/tr&gt;\r
-       &lt;/tbody&gt;\r
-     &lt;/table&gt;\r
-   &lt;/div&gt;\r
-\r
-   // get a terminal for this\r
-\r
-   var term1 = new Terminal(\r
-                 {\r
-                   x: 0,\r
-                   y: 0,\r
-                   id: 1,\r
-                   termDiv: &quot;termDiv1&quot;,\r
-                   handler: myTermHandler\r
-                 }\r
-              );\r
-   term1.open();\r
-   \r
-   // and this is how to move the chrome and the embedded terminal\r
-\r
-   TermGlobals.setElementXY( &quot;myTerminal1&quot;, 200, 80 );\r
-</PRE>\r
-To keep track of the instance for any widgets use the terminal's `id' property. (You must set this in the configuration object to a unique value for this purpose.)<BR><BR>\r
-\r
-For a demonstration see the <A HREF="chrome_sample.html">Chrome Sample Page</A>.\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13"><A NAME="embed"></A>\r
-&nbsp;<BR>\r
-<B CLASS="quest">How can I embed a terminal relative to my HTML layout?</B><BR><BR>\r
-\r
-Define your devision element with attribute &quot;position&quot; set to &quot;relative&quot; and place this inside your layout. Call &quot;new Terminal()&quot; with config-values { x: 0, y: 0 } to leave it at its relative origin.\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13"><A NAME="syntax"></A>\r
-&nbsp;<BR>\r
-<B CLASS="quest">I pasted your sample code and just got an error. - ???</B><BR><BR>\r
-\r
-The short examples are kept arbitrarily simple to show the syntax.<BR>\r
-Make sure that your divison element(s) is/are rendered by the browser before `Terminal.open()' is called.<BR><BR>\r
-\r
-Does not work:\r
-<PRE>  &lt;head&gt;\r
-  &lt;script&gt;\r
-    var term = new Terminal();\r
-    term.open();\r
-  &lt;/script&gt;\r
-  &lt;/head&gt;\r
-</PRE>\r
-Does work:\r
-<PRE>  &lt;head&gt;\r
-  &lt;script&gt;\r
-    var term;\r
-    \r
-    function termOpen() {\r
-       // to be called from outside after compile time\r
-       term = new Terminal();\r
-       term.open();\r
-    }\r
-  &lt;/script&gt;\r
-  &lt;/head&gt;\r
-</PRE>\r
-c.f. &quot;readme.txt&quot;<BR>\r
-(Opening a terminal by clicking a link implies also that the page has currently focus.)<BR><BR>\r
-With v.1.01 and higher this doesn't cause an error any more.<BR>`Terminal.prototype.open()' now returns a value for success.\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13"><A NAME="keyboard"></A>\r
-&nbsp;<BR>\r
-<B CLASS="quest">I can't get any input, but I don't get any erros too.</B><BR><BR>\r
-\r
-The Terminal object's functionality relies on the browsers ability to generate and handle keyboard events.<BR>\r
-Sadly some browsers lack a full implementation of the event model. (e.g. Konquerer [khtml] and early versions of Apple Safari, which is a descendant of khtml.)\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13"><A NAME="keylock"></A>\r
-&nbsp;<BR>\r
-<B CLASS="quest">How can I temporary disable the keyboard handlers?</B><BR>\r
-<SPAN CLASS="prop">(The terminal is blocking my HTML form fields, etc.)</SPAN><BR><BR>\r
-\r
-With version 1.03 there's a global property `<SPAN CLASS="prop">TermGlobals.keylock</SPAN>'. Set this to `true' to disable the keyboard handlers without altering any other state. Reset it to `false' to continue with your terminal session(s).\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13"><A NAME="linesranges"></A>\r
-&nbsp;<BR>\r
-<B CLASS="quest">How can I set the cusor to the start / the end of the command line?</B><BR><BR>\r
-\r
-In case you need to implement a shortcut (like ^A of some UN*X-shells) to jump to the beginning or the end of the current input line, there are two private instance methods you could utilize:<BR><BR>\r
-`<SPAN CLASS="prop">_getLineEnd(&lt;row&gt;, &lt;col&gt;)</SPAN>' returns an array [&lt;row&gt;, &lt;col&gt;] with the position of the last character in the logical input line with ASCII value &gt;= 32 (0x20).<BR><BR>\r
-`<SPAN CLASS="prop">_getLineStart(&lt;row&gt;, &lt;col&gt;)</SPAN>' returns an array [&lt;row&gt;, &lt;col&gt;] with the position of the first character in the logical input line with ASCII value &gt;= 32 (0x20).<BR><BR>\r
-Both take a row and a column of a cursor position as arguments.<BR><BR>\r
-\r
-p.e.:\r
-<PRE>\r
-  // jump to the start of the input line\r
-\r
-  myCtrlHandler() {\r
-     // catch ^A and jump to start of the line\r
-     if (this.inputChar == 1) {\r
-        var firstChar = this._getLineStart(this.r, this.c);\r
-        this.cursorSet(firstChar[0], firstChar[1]);\r
-     }\r
-  }</PRE>\r
-(Keep in mind that this is not exactly a good example, since some browser actually don't issue a keyboard event for \r
-&quot;^A&quot;. And other browsers, which do catch such codes, are not very reliable in that.)\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13"><A NAME="historyunique"></A>\r
-&nbsp;<BR>\r
-<B CLASS="quest">How can I limit the command history to unique entries only?</B><BR>\r
-       <SPAN CLASS="prop">(My application effords commands to be commonly repeated.)</SPAN><BR><BR>\r
-\r
-With version 1.05 there is a new configuration and control flag `<SPAN CLASS="prop">historyUnique</SPAN>'. All you need is setting this to `true' in your terminal's configuration object.\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13"><A NAME="rebuild"></A>\r
-&nbsp;<BR>\r
-<B CLASS="quest">How can I change my color theme on the fly?</B><BR><BR>\r
-\r
-With version 1.07 there is a new method `<SPAN CLASS="prop">Terminal.rebuild()</SPAN>'.<BR>\r
-This method updates the GUI to current config settings while preserving all other state.<BR><BR>\r
-p.e.:\r
-<PRE>\r
-   // change color settings on the fly\r
-   // here: set bgColor to white and font style to class &quot;termWhite&quot;\r
-   // method rebuild() updates the GUI without side effects\r
-   // assume var term holds a referene to a Terminal object already active\r
-\r
-   term.conf.bgColor = '#ffffff';\r
-   term.conf.fontClass = 'termWhite';\r
-   term.rebuild();</PRE>\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13"><A NAME="connect"></A>\r
-&nbsp;<BR>\r
-<B CLASS="quest">How can I connect to a server?</B><BR><BR>\r
-\r
-The Terminal object only provides an interface to handle console input and output.<BR>\r
-External connections have to be handled outside the Terminal object. You could use the XMLHttpRequest-Object (and use a communication model like AJAX or JSON) or connect via a frame or iframe element to a foreign host.<BR><BR>\r
-Handling connections is considered to be out of the realm of the &quot;termlib.js&quot; library.<BR>\r
-The code you need is in fact quite simple:\r
-<PRE>\r
-  function connectToHost(url) {\r
-     if (window.XMLHttpRequest) {\r
-        request = new XMLHttpRequest();\r
-     }\r
-     else if (window.ActiveXObject) {\r
-         request = new ActiveXObject('Microsoft.XMLHTTP');\r
-     }\r
-     if (request) {\r
-         request.onreadystatechange = requestChangeHandler;\r
-         request.open('GET', url);\r
-         request.send('');\r
-     }\r
-     else {\r
-        // XMLHttpRequest not implemented\r
-     }\r
-  }\r
-  \r
-  function requestChangeHandler() {\r
-     if (request.readyState == 4) {\r
-        // readyState 4: complete; now test for server's response status\r
-        if (request.status == 200) {\r
-           // response in request.responseText or request.responseXML if XML-code\r
-           // if it's JS-code we could get this by eval(request.responseText)\r
-           // by this we could import whole functions to be used via the terminal\r
-        }\r
-        else {\r
-           // connection error\r
-           // status code and message in request.status and request.statusText\r
-        }\r
-     }\r
-  }\r
-</PRE>\r
-You should use this only together with a timer (window.setTimeout()) to handle connection timeouts.<BR>\r
-Additionally you would need some syntax to authenticate and tell the server what you want.<BR>\r
-For this purpose you could use the following methods of the XMLHttpRequest object:<BR><BR>\r
-\r
-       <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="3">\r
-       <TR VALIGN="top"><TD NOWRAP CLASS="prop">setRequestHeader(&quot;<I>headerLabel</I>&quot;, &quot;<I>value</I>&quot;)</TD><TD>set a HTTP header to be sent to the server</TD></TR>\r
-       <TR VALIGN="top"><TD NOWRAP CLASS="prop">getResponseHeader(&quot;<I>headerLabel</I>&quot;)</TD><TD>get a HTTP header sent from the server</TD></TR>\r
-       <TR VALIGN="top"><TD NOWRAP CLASS="prop">open(<I>method</I>, &quot;<I>url</I>&quot; [, <I>asyncFlag</I> [,<BR>&nbsp; &quot;<I>userid</I>&quot; [, &quot;<I>password</I>&quot;]]])</TD><TD>assign the destination properties to the request.<BR>be aware that userid and password are not encrypted!</TD></TR>\r
-       <TR VALIGN="top"><TD NOWRAP CLASS="prop">send(<I>content</I>)</TD><TD>transmit a message body (post-string or DOM object)</TD></TR>\r
-       <TR VALIGN="top"><TD NOWRAP CLASS="prop">abort()</TD><TD>use this to stop a pending connection</TD></TR>\r
-       </TABLE>\r
-\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13">\r
-       &nbsp;<BR>\r
-       Norbert Landsteiner - August 2005<BR>\r
-       <A HREF="http://www.masswerk.at/" TARGET="_blank">http://www.masswerk.at</A>\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13">\r
-       &nbsp;<BR>\r
-               <A HREF="#top">&gt; top of page</A>\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13">\r
-       &nbsp;\r
-       </TD></TR>\r
-</TABLE>\r
-\r
-<DIV ID="termDiv" STYLE="position:absolute; top:20px; left:100px;"></DIV>\r
-\r
-</BODY>\r
-</HTML>
\ No newline at end of file
diff --git a/extra/webapps/fjsc/resources/termlib/index.html b/extra/webapps/fjsc/resources/termlib/index.html
deleted file mode 100644 (file)
index 1770b2c..0000000
+++ /dev/null
@@ -1,207 +0,0 @@
-<HTML>\r
-<HEAD>\r
-       <TITLE>mass:werk termlib</TITLE>\r
-\r
-<STYLE TYPE="text/css">\r
-body,p,a,td {\r
-       font-family: courier,fixed,swiss,sans-serif;\r
-       font-size: 12px;\r
-       color: #cccccc;\r
-}\r
-.lh13 {\r
-       line-height: 13px;\r
-}\r
-.lh15 {\r
-       line-height: 15px;\r
-}\r
-pre {\r
-       font-family: courier,fixed,swiss,sans-serif;\r
-       font-size: 12px;\r
-       color: #ccffaa;\r
-       line-height: 15px;\r
-}\r
-.prop {\r
-       font-family: courier,fixed,swiss,sans-serif;\r
-       color: #bbee99;\r
-       font-size: 12px;\r
-       line-height: 15px;\r
-}\r
-h1 {\r
-       font-family: courier,fixed,swiss,sans-serif;\r
-       font-size: 16px;\r
-       color: #cccccc;\r
-}\r
-a,a:link,a:visited {\r
-       text-decoration: none;\r
-       color: #77dd11;\r
-}\r
-a:hover {\r
-       text-decoration: underline;\r
-       color: #77dd11;\r
-}\r
-a:active {\r
-       text-decoration: underline;\r
-       color: #dddddd;\r
-}\r
-\r
-@media print {\r
-       body { background-color: #ffffff; }\r
-       body,p,a,td {\r
-               font-family: courier,fixed,swiss,sans-serif;\r
-               font-size: 12px;\r
-               color: #000000;\r
-       }\r
-       .lh13 {\r
-               line-height: 13px;\r
-       }\r
-       .lh15 {\r
-               line-height: 15px;\r
-       }\r
-       pre,.prop {\r
-               font-family: courier,fixed,swiss,sans-serif;\r
-               font-size: 12px;\r
-               color: #000000;\r
-               line-height: 15px;\r
-       }\r
-       h1 {\r
-               font-family: courier,fixed,swiss,sans-serif;\r
-               font-size: 16px;\r
-               color: #000000;\r
-       }\r
-       a,a:link,a:visited {\r
-               text-decoration: none;\r
-               color: #000000;\r
-       }\r
-       a:hover {\r
-               text-decoration: underline;\r
-               color: #000000;\r
-       }\r
-       a:active {\r
-               text-decoration: underline;\r
-               color: #000000;\r
-       }\r
-}\r
-</STYLE>\r
-</HEAD>\r
-\r
-\r
-<BODY BGCOLOR="#222222" LINK="#77dd11" TEXT="#cccccc" ALINK="#dddddd" VLINK="#77dd11"\r
-TOPMARGIN="0" BOTTOMMARGIN="0" LEFTMARGIN="0" RIGHTMARGIN="0" MARGINHEIGHT="0" MARGINWIDTH="0"><A NAME="top"></A>\r
-\r
-<TABLE BORDER="0" CELLSPACING="20" CELLPADDING="0" ALIGN="center">\r
-<TR>\r
-       <TD NOWRAP>termlib.js home</TD>\r
-       <TD>|</TD>\r
-       <TD NOWRAP><A HREF="multiterm_test.html">multiple terminal test</A></TD>\r
-       <TD>|</TD>\r
-       <TD NOWRAP><A HREF="parser_sample.html">sample parser</A></TD>\r
-       <TD>|</TD>\r
-       <TD NOWRAP><A HREF="faq.html">faq</A></TD>\r
-       <TD>|</TD>\r
-       <TD NOWRAP><A HREF="readme.txt" TITLE="readme.txt (text/plain)">documentation</A></TD>\r
-</TR>\r
-</TABLE>\r
-\r
-<TABLE BORDER="0" CELLSPACING="20" CELLPADDING="0" WIDTH="700" ALIGN="center">\r
-       <TR><TD>\r
-               <H1>mass:werk termlib.js</H1>\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13">\r
-               The JavaScript library &quot;termlib.js&quot; provides a `Terminal' object, which\r
-               facillitates a simple and object oriented approach to generate and control a\r
-               terminal-like interface for web services.<BR><BR>\r
-               \r
-               "termlib.js" features direct keyboard input and powerful output methods\r
-               for multiple and simultanious instances of the `Terminal' object.<BR><BR>\r
-               \r
-               The library was written with the aim of simple usage and a maximum of compatibility\r
-               with minimal foot print in the global namespace.<BR><BR><BR>\r
-               \r
-               \r
-               A short example:<BR>\r
-  <PRE>\r
-  var term = new Terminal( {handler: termHandler} );\r
-  term.open();\r
-\r
-  function termHandler() {\r
-     this.newLine();\r
-     var line = this.lineBuffer;\r
-     if (line != &quot;&quot;) {\r
-        this.write(&quot;You typed: &quot;+line);\r
-     }\r
-     this.prompt();\r
-  }\r
-  </PRE>\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13">\r
-       <B>License</B><BR><BR>\r
-\r
-       This JavaScript-library is <U>free for private and academic use</U>.\r
-       Please include a readable copyright statement and a backlink to &lt;http://www.masswerk.at&gt; in the\r
-       web page. The library should always be accompanied by the &quot;readme.txt&quot; and the sample HTML-documents.<BR><BR>\r
-\r
-       The term &quot;private use&quot; includes any personal or non-commercial use, which is not related\r
-       to commercial activites, but excludes intranet, extranet and/or public net applications\r
-       that are related to any kind of commercial or profit oriented activity.<BR><BR>\r
-\r
-       For commercial use see &lt;<A HREF="http://www.masswerk.at/" TARGET="_blank">http://www.masswerk.at</A>&gt; for contact information.\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13">\r
-       <B>Distribution</B><BR><BR>\r
-\r
-       This JavaScript-library may be distributed freely as long it is distributed together with the &quot;readme.txt&quot; and the sample HTML-documents and this document.<BR><BR>\r
-\r
-       Any changes to the library should be commented and be documented in the readme-file.<BR>\r
-       Any changes must be reflected in the `Terminal.version' string as &quot;Version.Subversion&nbsp;(compatibility)&quot;.\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13">\r
-       <B>Disclaimer</B><BR><BR>\r
-\r
-       This software is distributed AS IS and in the hope that it will be useful, but WITHOUT ANY\r
-       WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
-       PURPOSE. The entire risk as to the quality and performance of the product is borne by the\r
-       user. No use of the product is authorized hereunder except under this disclaimer.\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13">\r
-       <B>History</B><BR><BR>\r
-\r
-       This library evolved from the terminal script &quot;TermApp&quot; ((c) N. Landsteiner 2003) and is in its\r
-       current form a down scaled spinn-off of the &quot;JS/UIX&quot; project. (JS/UIX is not a free&nbsp;software by now.)\r
-       c.f.: &lt;<A HREF="http://www.masswerk.at/jsuix/" TARGET="_blank">http://www.masswerk.at/jsuix</A>&gt;<BR><BR>\r
-\r
-       For version history: see the <A HREF="readme.txt">readme.txt</A>.\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13">\r
-       &nbsp;<BR>\r
-       <B>Download</B><BR><BR>\r
-       Be sure to have read the license information and the disclamer and that you are willing to respect copyrights.<BR><BR>\r
-\r
-       <SPAN CLASS="prop">Download:</SPAN> <A HREF="termlib.zip">termlib.zip</A> (~ 40 KB, incl. docs)<BR><BR>\r
-       Current version is &quot;1.07 (original)&quot;.<BR>\r
-       The files are now provided with line breaks  in format &lt;CRLF&gt;.<BR>\r
-       &nbsp;\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13">\r
-       <B>Author</B><BR><BR>\r
-       &copy; Norbert Landsteiner 2003-2005<BR>\r
-       mass:werk &#150; media environments<BR>\r
-       <A HREF="http://www.masswerk.at/" TARGET="_blank">http://www.masswerk.at</A>\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13">\r
-       &nbsp;<BR>\r
-       Author's note:<BR>\r
-       Please do not contact me on questions of simple usage. There is an extensive documentation (readme.txt) including plenty of sample code that should provide all information you need.\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13">\r
-       &nbsp;<BR>\r
-               <A HREF="#top">&gt; top of page</A>\r
-       </TD></TR>\r
-       <TR><TD CLASS="lh13">\r
-       &nbsp;\r
-       </TD></TR>\r
-</TABLE>\r
-\r
-<DIV ID="termDiv" STYLE="position:absolute; top:20px; left:100px;"></DIV>\r
-\r
-</BODY>\r
-</HTML>
\ No newline at end of file
diff --git a/extra/webapps/fjsc/resources/termlib/multiterm_test.html b/extra/webapps/fjsc/resources/termlib/multiterm_test.html
deleted file mode 100644 (file)
index 0a4e1ec..0000000
+++ /dev/null
@@ -1,188 +0,0 @@
-<HTML>\r
-<HEAD>\r
-       <TITLE>termlib Multiple Terminal Test</TITLE>\r
-       <SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript" SRC="termlib.js"></SCRIPT>\r
-\r
-<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript">\r
-<!--\r
-\r
-/*\r
-  multiple terminal test for termlib.js\r
-\r
-  (c) Norbert Landsteiner 2003-2005\r
-  mass:werk - media environments\r
-  <http://www.masswerk.at>\r
-\r
-*/\r
-\r
-var term=new Array();\r
-\r
-var helpPage=[\r
-       '%CS%+r Terminal Help %-r%n',\r
-       '  This is just a tiny test for multiple terminals.',\r
-       '  use one of the following commands:',\r
-       '     clear .... clear the terminal',\r
-       '     exit ..... close the terminal (or <ESC>)',\r
-       '     id ....... show terminal\'s id',\r
-       '     switch ... switch to other terminal',\r
-       '     help ..... show this help page',\r
-       '  other input will be echoed to the terminal.',\r
-       ' '\r
-];\r
-\r
-function termOpen(n) {\r
-       if (!term[n]) {\r
-               var y=(n==1)? 70: 280;\r
-               term[n]=new Terminal(\r
-                       {\r
-                               x: 220,\r
-                               y: y,\r
-                               rows: 12,\r
-                               greeting: '%+r +++ Terminal #'+n+' ready. +++ %-r%nType "help" for help.%n',\r
-                               id: n,\r
-                               termDiv: 'termDiv'+n,\r
-                               crsrBlinkMode: true,\r
-                               handler: termHandler,\r
-                               exitHandler: termExitHandler\r
-                       }\r
-               );\r
-               if (term[n]) term[n].open();\r
-       }\r
-       else if (term[n].closed) {\r
-               term[n].open();\r
-       }\r
-       else {\r
-               term[n].focus();\r
-       }\r
-}\r
-\r
-function termHandler() {\r
-       // called on <CR> or <ENTER>\r
-       this.newLine();\r
-       var cmd=this.lineBuffer;\r
-       if (cmd!='') {\r
-               if (cmd=='switch') {\r
-                       var other=(this.id==1)? 2:1;\r
-                       termOpen(other);\r
-               }\r
-               else if (cmd=='clear') {\r
-                       this.clear();\r
-               }\r
-               else if (cmd=='exit') {\r
-                       this.close();\r
-               }\r
-               else if (cmd=='help') {\r
-                       this.write(helpPage);\r
-               }\r
-               else if (cmd=='id') {\r
-                       this.write('terminal id: '+this.id);\r
-               }\r
-               else {\r
-                       this.type('You typed: '+cmd);\r
-                       this.newLine();\r
-               }\r
-       }\r
-       this.prompt();\r
-}\r
-\r
-function termExitHandler() {\r
-       // optional handler called on exit\r
-       // activate other terminal if open\r
-       var other=(this.id==1)? 2:1;\r
-       if ((term[other]) && (term[other].closed==false)) term[other].focus();\r
-}\r
-\r
-//-->\r
-</SCRIPT>\r
-\r
-<STYLE TYPE="text/css">\r
-body,p,a,td {\r
-       font-family: courier,fixed,swiss,sans-serif;\r
-       font-size: 12px;\r
-       color: #cccccc;\r
-}\r
-.lh15 {\r
-       line-height: 15px;\r
-}\r
-.term {\r
-       font-family: courier,fixed,swiss,sans-serif;\r
-       font-size: 12px;\r
-       color: #33d011;\r
-       background: none;\r
-}\r
-.termReverse {\r
-       color: #111111;\r
-       background: #33d011;\r
-}\r
-a,a:link,a:visited {\r
-       text-decoration: none;\r
-       color: #77dd11;\r
-}\r
-a:hover {\r
-       text-decoration: underline;\r
-       color: #77dd11;\r
-}\r
-a:active {\r
-       text-decoration: underline;\r
-       color: #dddddd;\r
-}\r
-\r
-a.termopen,a.termopen:link,a.termopen:visited {\r
-       text-decoration: none;\r
-       color: #77dd11;\r
-       background: none;\r
-}\r
-a.termopen:hover {\r
-       text-decoration: none;\r
-       color: #222222;\r
-       background: #77dd11;\r
-}\r
-a.termopen:active {\r
-       text-decoration: none;\r
-       color: #222222;\r
-       background: #dddddd;\r
-}\r
-\r
-</STYLE>\r
-</HEAD>\r
-\r
-\r
-<BODY BGCOLOR="#222222" LINK="#77dd11" TEXT="#cccccc" ALINK="#dddddd" VLINK="#77dd11"\r
-TOPMARGIN="0" BOTTOMMARGIN="0" LEFTMARGIN="0" RIGHTMARGIN="0" MARGINHEIGHT="0" MARGINWIDTH="0">\r
-\r
-<TABLE BORDER="0" CELLSPACING="20" CELLPADDING="0" ALIGN="center">\r
-<TR>\r
-       <TD NOWRAP><A HREF="index.html">termlib.js home</A></TD>\r
-       <TD>|</TD>\r
-       <TD NOWRAP>multiple terminal test</TD>\r
-       <TD>|</TD>\r
-       <TD NOWRAP><A HREF="parser_sample.html">sample parser</A></TD>\r
-       <TD>|</TD>\r
-       <TD NOWRAP><A HREF="faq.html">faq</A></TD>\r
-       <TD>|</TD>\r
-       <TD NOWRAP><A HREF="readme.txt" TITLE="readme.txt (text/plain)">documentation</A></TD>\r
-</TR>\r
-</TABLE>\r
-\r
-<TABLE BORDER="0" CELLSPACING="20" CELLPADDING="0">\r
-       <TR><TD NOWRAP>\r
-               Multiple Terminal Test<BR>&nbsp;\r
-       </TD></TR>\r
-       <TR><TD NOWRAP>\r
-               <A HREF="javascript:termOpen(1)" onfocus="if(this.blur)this.blur();" onmouseover="window.status='terminal 1'; return true" onmouseout="window.status=''; return true" CLASS="termopen">&gt; open terminal 1 &nbsp;</A>\r
-       </TD></TR>\r
-       <TR><TD NOWRAP>\r
-               <A HREF="javascript:termOpen(2)" onfocus="if(this.blur)this.blur();" onmouseover="window.status='terminal 2'; return true" onmouseout="window.status=''; return true" CLASS="termopen">&gt; open terminal 2 &nbsp;</A>\r
-       </TD></TR>\r
-       <TR><TD NOWRAP CLASS="lh15">\r
-               &nbsp;<BR>\r
-               (c) mass:werk,<BR>N. Landsteiner 2003-2005<BR>\r
-               <A HREF="http://www.masswerk.at/" TARGET="_blank">http://www.masswerk.at</A>\r
-       </TD></TR>\r
-</TABLE>\r
-\r
-<DIV ID="termDiv1" STYLE="position:absolute; top:20px; left:100px;"></DIV>\r
-<DIV ID="termDiv2" STYLE="position:absolute; top:20px; left:100px;"></DIV>\r
-\r
-</BODY>\r
-</HTML>
\ No newline at end of file
diff --git a/extra/webapps/fjsc/resources/termlib/parser_sample.html b/extra/webapps/fjsc/resources/termlib/parser_sample.html
deleted file mode 100644 (file)
index b332af1..0000000
+++ /dev/null
@@ -1,293 +0,0 @@
-<HTML>\r
-<HEAD>\r
-       <TITLE>termlib Sample Parser</TITLE>\r
-       <SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript" SRC="termlib.js"></SCRIPT>\r
-       <SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript" SRC="termlib_parser.js"></SCRIPT>\r
-\r
-<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript">\r
-<!--\r
-\r
-/*\r
-  test sample for termlib.js and termlib_parser.js\r
-\r
-  (c) Norbert Landsteiner 2005\r
-  mass:werk - media environments\r
-  <http://www.masswerk.at>\r
-\r
-*/\r
-\r
-var term;\r
-\r
-var helpPage=[\r
-       '%CS%+r Terminal Help %-r%n',\r
-       '  This is just a sample to demonstrate command line parsing.',\r
-       ' ',\r
-       '  Use one of the following commands:',\r
-       '     clear [-a] .......... clear the terminal',\r
-       '                           option "a" also removes the status line',\r
-       '     number -n<value> .... return value of option "n" (test for options)',\r
-       '     repeat -n<value> .... repeats the first argument n times (another test)',\r
-       '     login <username> .... sample login (test for raw mode)',\r
-       '     exit ................ close the terminal (same as <ESC>)',\r
-       '     help ................ show this help page',\r
-       ' ',\r
-       '  other input will be echoed to the terminal as a list of parsed arguments',\r
-       '  in the format <argument index> <quoting level> "<parsed value>".',\r
-       ' '\r
-];\r
-\r
-function termOpen() {\r
-       if (!term) {\r
-               term=new Terminal(\r
-                       {\r
-                               x: 220,\r
-                               y: 70,\r
-                               termDiv: 'termDiv',\r
-                               ps: '[guest]$',\r
-                               initHandler: termInitHandler,\r
-                               handler: commandHandler\r
-                       }\r
-               );\r
-               if (term) term.open();\r
-       }\r
-       else if (term.closed) {\r
-               term.open();\r
-       }\r
-       else {\r
-               term.focus();\r
-       }\r
-}\r
-\r
-function termInitHandler() {\r
-       // output a start up screen\r
-       this.write(\r
-               [\r
-                       TermGlobals.center('####################################################', 80),\r
-                       TermGlobals.center('#                                                  #', 80),\r
-                       TermGlobals.center('#           termlib.js - Sample Parser             #', 80),\r
-                       TermGlobals.center('#  Input is echoed as a list of parsed arguments.  #', 80),\r
-                       TermGlobals.center('#                                                  #', 80),\r
-                       TermGlobals.center('#  Type "help" for commands.                       #', 80),\r
-                       TermGlobals.center('#                                                  #', 80),\r
-                       TermGlobals.center('#  (c) N. Landsteiner 2005;  www.masswerk.at       #', 80),\r
-                       TermGlobals.center('#                                                  #', 80),\r
-                       TermGlobals.center('####################################################', 80),\r
-                       '%n'\r
-               ]\r
-       );\r
-       // set a double status line\r
-       this.statusLine('', 8,2); // just a line of strike\r
-       this.statusLine(' +++ This is just a test sample for command parsing. Type "help" for help. +++');\r
-       this.maxLines -= 2;\r
-       // and leave with prompt\r
-       this.prompt();\r
-}\r
-\r
-function commandHandler() {\r
-       this.newLine();\r
-       // check for raw mode first (should not be parsed)\r
-       if (this.rawMode) {\r
-               if (this.env.getPassword) {\r
-                       // sample password handler (lineBuffer == stored username ?)\r
-                       if (this.lineBuffer == this.env.username) {\r
-                               this.user = this.env.username;\r
-                               this.ps = '['+this.user+']>';\r
-                       }\r
-                       else {\r
-                               this.type('Sorry.');\r
-                       }\r
-                       this.env.username = '';\r
-                       this.env.getPassword = false;\r
-               }\r
-               // leave in normal mode\r
-               this.rawMode = false;\r
-               this.prompt();\r
-               return;\r
-       }\r
-       // normal command parsing\r
-       // just call the termlib_parser with a reference of the calling Terminal instance\r
-       // parsed arguments will be imported in this.argv,\r
-       // quoting levels per argument in this.argQL (quoting character or empty)\r
-       // cursor for arguments is this.argc (used by parserGetopt)\r
-       // => see 'termlib_parse.js' for configuration and details\r
-       parseLine(this);\r
-       if (this.argv.length == 0) {\r
-               // no commmand line input\r
-       }\r
-       else if (this.argQL[0]) {\r
-           // first argument quoted -> error\r
-               this.write("Syntax error: first argument quoted.");\r
-       }\r
-       else {\r
-               var cmd = this.argv[this.argc++];\r
-               /*\r
-                 process commands now\r
-                 1st argument: this.argv[this.argc]\r
-               */\r
-               if (cmd == 'help') {\r
-                       this.write(helpPage);\r
-               }\r
-               else if (cmd == 'clear') {\r
-                       // get options\r
-                       var opts = parserGetopt(this, 'aA');\r
-                       if (opts.a) {\r
-                               // discard status line on opt "a" or "A"\r
-                               this.maxLines = this.conf.rows;\r
-                       }\r
-                       this.clear();\r
-               }\r
-               else if (cmd == 'number') {\r
-                       // test for value options\r
-                       var opts = parserGetopt(this, 'n');\r
-                       if (opts.illegals.length) this.type('illegal option. usage: number -n<value>')\r
-                       else if ((opts.n) && (opts.n.value != -1)) this.type('option value: '+opts.n.value)\r
-                       else this.type('usage: number -n<value>');\r
-               }\r
-               else if (cmd == 'repeat') {\r
-                       // another test for value options\r
-                       var opts = parserGetopt(this, 'n');\r
-                       if (opts.illegals.length) this.type('illegal option. usage: repeat -n<value> <string>')\r
-                       else if ((opts.n) && (opts.n.value != -1)) {\r
-                               // first normal argument is again this.argv[this.argc]\r
-                               var s = this.argv[this.argc];\r
-                               if (typeof s != 'undefined') {\r
-                                       // repeat this string n times\r
-                                       var a = [];\r
-                                       for (var i=0; i<opts.n.value; i++) a[a.length] = s;\r
-                                       this.type(a.join(' '));\r
-                               }\r
-                       }\r
-                       else this.type('usage: repeat -n<value> <string>');\r
-               }\r
-               else if (cmd == 'login') {\r
-                       // sample login (test for raw mode)\r
-                       if ((this.argc == this.argv.length) || (this.argv[this.argc] == '')) {\r
-                               this.type('usage: login <username>');\r
-                       }\r
-                       else {\r
-                               this.env.getPassword = true;\r
-                               this.env.username = this.argv[this.argc];\r
-                               this.write('%+iSample login: repeat username as password.%-i%n');\r
-                               this.type('password: ');\r
-                               // exit in raw mode (blind input)\r
-                               this.rawMode = true;\r
-                               this.lock = false;\r
-                               return;\r
-                       }\r
-               }\r
-               else if (cmd == 'exit') {\r
-                       this.close();\r
-                       return;\r
-               }\r
-               else {\r
-                       // for test purpose just output argv as list\r
-                       // assemble a string of style-escaped lines and output it in more-mode\r
-                       s=' INDEX  QL  ARGUMENT%n';\r
-                       for (var i=0; i<this.argv.length; i++) {\r
-                               s += TermGlobals.stringReplace('%', '%%',\r
-                                               TermGlobals.fillLeft(i, 6) +\r
-                                               TermGlobals.fillLeft((this.argQL[i])? this.argQL[i]:'-', 4) +\r
-                                               '  "' + this.argv[i] + '"'\r
-                                       ) + '%n';\r
-                       }\r
-                       this.write(s, 1);\r
-                       return;\r
-               }\r
-       }\r
-       this.prompt();\r
-}\r
-\r
-\r
-//-->\r
-</SCRIPT>\r
-\r
-<STYLE TYPE="text/css">\r
-body,p,a,td {\r
-       font-family: courier,fixed,swiss,sans-serif;\r
-       font-size: 12px;\r
-       color: #cccccc;\r
-}\r
-.lh15 {\r
-       line-height: 15px;\r
-}\r
-.term {\r
-       font-family: courier,fixed,swiss,sans-serif;\r
-       font-size: 12px;\r
-       color: #33d011;\r
-       background: none;\r
-}\r
-.termReverse {\r
-       color: #111111;\r
-       background: #33d011;\r
-}\r
-a,a:link,a:visited {\r
-       text-decoration: none;\r
-       color: #77dd11;\r
-}\r
-a:hover {\r
-       text-decoration: underline;\r
-       color: #77dd11;\r
-}\r
-a:active {\r
-       text-decoration: underline;\r
-       color: #dddddd;\r
-}\r
-\r
-a.termopen,a.termopen:link,a.termopen:visited {\r
-       text-decoration: none;\r
-       color: #77dd11;\r
-       background: none;\r
-}\r
-a.termopen:hover {\r
-       text-decoration: none;\r
-       color: #222222;\r
-       background: #77dd11;\r
-}\r
-a.termopen:active {\r
-       text-decoration: none;\r
-       color: #222222;\r
-       background: #dddddd;\r
-}\r
-\r
-</STYLE>\r
-</HEAD>\r
-\r
-\r
-<BODY BGCOLOR="#222222" LINK="#77dd11" TEXT="#cccccc" ALINK="#dddddd" VLINK="#77dd11"\r
-TOPMARGIN="0" BOTTOMMARGIN="0" LEFTMARGIN="0" RIGHTMARGIN="0" MARGINHEIGHT="0" MARGINWIDTH="0">\r
-\r
-<TABLE BORDER="0" CELLSPACING="20" CELLPADDING="0" ALIGN="center">\r
-<TR>\r
-       <TD NOWRAP><A HREF="index.html">termlib.js home</A></TD>\r
-       <TD>|</TD>\r
-       <TD NOWRAP><A HREF="multiterm_test.html">multiple terminal test</A></TD>\r
-       <TD>|</TD>\r
-       <TD NOWRAP>sample parser</TD>\r
-       <TD>|</TD>\r
-       <TD NOWRAP><A HREF="faq.html">faq</A></TD>\r
-       <TD>|</TD>\r
-       <TD NOWRAP><A HREF="readme.txt" TITLE="readme.txt (text/plain)">documentation</A></TD>\r
-</TR>\r
-</TABLE>\r
-\r
-<TABLE BORDER="0" CELLSPACING="20" CELLPADDING="0">\r
-       <TR><TD NOWRAP>\r
-               Sample Parser Test<BR>&nbsp;\r
-       </TD></TR>\r
-       <TR><TD NOWRAP>\r
-               <A HREF="javascript:termOpen()" onfocus="if(this.blur)this.blur();" onmouseover="window.status='terminal 1'; return true" onmouseout="window.status=''; return true" CLASS="termopen">&gt; open terminal &nbsp;</A>\r
-       </TD></TR>\r
-       <TR><TD NOWRAP>\r
-               &nbsp;\r
-       </TD></TR>\r
-       <TR><TD NOWRAP CLASS="lh15">\r
-               &nbsp;<BR>\r
-               (c) mass:werk,<BR>N. Landsteiner 2003-2005<BR>\r
-               <A HREF="http://www.masswerk.at/" TARGET="_blank">http://www.masswerk.at</A>\r
-       </TD></TR>\r
-</TABLE>\r
-\r
-<DIV ID="termDiv" STYLE="position:absolute;"></DIV>\r
-\r
-</BODY>\r
-</HTML>
\ No newline at end of file
diff --git a/extra/webapps/fjsc/resources/termlib/readme.txt b/extra/webapps/fjsc/resources/termlib/readme.txt
deleted file mode 100644 (file)
index 8a92b9c..0000000
+++ /dev/null
@@ -1,1400 +0,0 @@
-****  mass:werk termlib.js - JS-WebTerminal Object v1.07  ****\r
-\r
-  (c) Norbert Landsteiner 2003-2005\r
-  mass:werk - media environments\r
-  <http://www.masswerk.at>\r
-\r
-\r
-\r
-\r
-Contents:\r
-\r
-   1  About\r
-   2  Creating a new Terminal Instance\r
-      2.1 Configuration Values\r
-   3  Using the Terminal\r
-      3.1  The Default Handler\r
-      3.2  Input Modes\r
-           3.2.1  Normal Line Input (Command Line Mode)\r
-                  3.2.1.2 Special Keys (ctrlHandler)\r
-           3.2.2  Raw Mode\r
-           3.2.3  Character Mode\r
-      3.3  Other Handlers\r
-           3.3.1  initHandler\r
-           3.3.2  exitHandler\r
-      3.4  Flags for Behaviour Control\r
-   4  Output Methods\r
-           4.1 Terminal.type()\r
-           4.2 Terminal.write()\r
-           4.3 Terminal.typeAt()\r
-           4.4 Terminal.setChar()\r
-           4.5 Terminal.newLine()\r
-           4.6 Terminal.clear()\r
-           4.7 Terminal.statusLine()\r
-           4.8 Terminal.printRowFromString()\r
-           4.9 Terminal.redraw()\r
-   5  Cursor Methods and Editing\r
-           5.1 Terminal.cursorOn()\r
-           5.2 Terminal.cursorOff()\r
-           5.3 Terminal.cursorSet()\r
-           5.4 Terminal.cursorLeft()\r
-           5.5 Terminal.cursorRight()\r
-           5.6 Terminal.backspace()\r
-           5.7 Terminal.fwdDelete()\r
-           5.8 Terminal.isPrintable()\r
-   6  Other Methods of the Terminal Object\r
-           6.1 Terminal.prompt()\r
-           6.2 Terminal.reset()\r
-           6.3 Terminal.open()\r
-           6.4 Terminal.close()\r
-           6.5 Terminal.focus()\r
-           6.6 Terminal.moveTo()\r
-           6.7 Terminal.resizeTo()\r
-           6.8 Terminal.getDimensions()\r
-           6.9 Terminal.rebuild()\r
-   7  Global Static Methods (TermGlobals)\r
-           7.1 TermGlobals.setFocus()\r
-           7.2 TermGlobals.keylock (Global Locking Flag)\r
-           7.3 TermGlobalsText Methods\r
-               7.3.1 TermGlobals.normalize()\r
-               7.3.2 TermGlobals.fillLeft()\r
-               7.3.3 TermGlobals.center()\r
-               7.3.4 TermGlobals.stringReplace()\r
-   8  Localization\r
-   9  Cross Browser Functions\r
-  10  Architecture, Internals\r
-      10.1  Global Entities\r
-      10.2  I/O Architecture\r
-      10.3  Compatibility\r
-  11  History\r
-  12  Example for a Command Line Parser\r
-  13  License\r
-  14  Disclaimer\r
-  15  References\r
-\r
-\r
-\r
-\r
-1  About\r
-\r
-The Terminal library "termlib.js" provides an object oriented constructor and control\r
-methods for a terminal-like DHTML interface.\r
-\r
-"termlib.js" features direct keyboard input and powerful output methods for multiple\r
-instances of the `Terminal' object (including focus control).\r
-\r
-The library was written with the aim of simple usage and a maximum of compatibility with\r
-minimal foot print in the global namespace.\r
-\r
-\r
-A simple example:\r
-\r
-  // creating a terminal and using it\r
-\r
-  var term = new Terminal( {handler: termHandler} );\r
-  term.open();\r
-\r
-  function termHandler() {\r
-    var line = this.lineBuffer;\r
-    this.newLine();\r
-    if (line == "help") {\r
-      this.write(helpPage)\r
-    }\r
-    else if (line == "exit") {\r
-      this.close();\r
-      return;\r
-    }\r
-    else if (line != "") {\r
-      this.write("You typed: "+line);\r
-    }\r
-    this.prompt();\r
-  }\r
-\r
-  var helpPage = [\r
-    "This is the monstrous help page for my groovy terminal.",\r
-    "Commands available:",\r
-    "   help ... print this monstrous help page",\r
-    "   exit ... leave this groovy terminal",\r
-    " ",\r
-    "Have fun!"\r
-  ];\r
-\r
-\r
-You should provide CSS font definitions for the classes ".term" (normal video) and\r
-".termReverse" (reverse video) in a monospaced font.\r
-A sample stylesheet "term_styles.css" comes with this library.\r
-\r
-See the sample application "multiterm_test.html" for a demo of multiple terminals.\r
-\r
-v.1.01: If you configure to use another font class (see 2.1 Configuration Values),\r
-        you must provide a subclass ".termReverse" for reversed video.\r
-\r
-        p.e.: .myFontClass .termReverse {\r
-                /* your definitions for reverse video here */\r
-              }\r
-        \r
-        With the addition of `conf.fontClass' you can now create multiple\r
-        instances with independend appearences.\r
-\r
-\r
-\r
-\r
-2   Creating a new Terminal Instance\r
-\r
-Use the `new' constructor to create a new instance of the Terminal object. You will want\r
-to supply a configuration object as an argument to the constructor. If the `new'\r
-constructor is called without an object as its first argument, default values are used.\r
-\r
-p.e.:\r
-\r
-  // creating a new instance of Terminal\r
-\r
-  var conf= {\r
-    x: 100,\r
-    y: 100,\r
-    cols: 80,\r
-    rows: 24\r
-  }\r
-\r
-  var term = new Term(conf);\r
-  term.open();\r
-\r
-`Terminal.open()' initializes the terminal and makes it visible to the user.\r
-This is handled in by separate method to allow the re-initilization of instances\r
-previously closed.\r
-\r
-NOTE:\r
-The division element (or NS-layer) that holds the terminal must be present when calling\r
-`Terminal.open()'. So you must not call this method from the header of a HTML-document at\r
-compile time.\r
-\r
-\r
-\r
-2.1 Configuration Values\r
-\r
-Set any of these values in your configuration object to override:\r
-\r
-  \r
-  LABEL                     DEFAULT VALUE    COMMENT\r
-  \r
-  x                                   100    terminal's position x in px\r
-  y                                   100    terminal's position y in px\r
-  divDiv                        'termDiv'    id of terminals CSS division\r
-  bgColor                       '#181818'    background color (HTML hex value)\r
-  frameColor                    '#555555'    frame color (HTML hex value)\r
-  frameWidth                            1    frame border width in px\r
-  fontClass                        'term'    class name of CSS font definition to use\r
-  cols                                 80    number of cols per row\r
-  rows                                 24    number of rows\r
-  rowHeight                            15    a row's line-height in px\r
-  blinkDelay                          500    delay for cursor blinking in milliseconds\r
-  crsrBlinkMode                     false    true for blinking cursor\r
-  crsrBlockMode                      true    true for block-cursor else underscore\r
-  DELisBS                           false    handle <DEL> as <BACKSPACE>\r
-  printTab                           true    handle <TAB> as printable (prints as space)\r
-  printEuro                          true    handle unicode 0x20AC (Euro sign) as printable\r
-  catchCtrlH                         true    handle ^H as <BACKSPACE>\r
-  closeOnESC                         true    close terminal on <ESC>\r
-  historyUnique                     false    prevent consecutive and identical entries in history\r
-  id                                    0    terminal id\r
-  ps                                  '>'    prompt string\r
-  greeting      '%+r Terminal ready. %-r'    string for greeting if no initHandler is used\r
-  handler              termDefaultHandler    reference to handler for command interpretation\r
-  ctrlHandler                        null    reference to handler called on uncatched special keys\r
-  initHandler                        null    reference to handler called at end of init()\r
-  exitHandler                        null    reference to handler called on close()\r
-\r
-\r
-At least you will want to specify `handler' to implement your own command parser.\r
-\r
-Note: While `id' is not used by the Termninal object, it provides an easy way to identify\r
-multiple terminals by the use of "this.id". (e.g.: "if (this.id == 1) startupterm = true;")\r
-\r
-p.e.:\r
-\r
-  // creating two individual Terminal instances\r
-\r
-  var term1 = new Terminal(\r
-    {\r
-      id: 1,\r
-      x: 200,\r
-      y: 10,\r
-      cols: 80,\r
-      rows: 12,\r
-      greeting: "*** This is Terminal 1 ***",\r
-      handler: myTerminalHandler\r
-    }\r
-  );\r
-  term1.open();\r
-\r
-  var term2 = new Terminal(\r
-    {\r
-      id: 2,\r
-      x, 200,\r
-      y: 220,\r
-      cols: 80\r
-      rows: 12,\r
-      greeting: "*** This is Terminal 2 ***",\r
-      handler: myTerminalHandler\r
-    }\r
-  );\r
-  term2.open();\r
-\r
-\r
-\r
-\r
-3   Using the Terminal\r
-\r
-There are 4 different handlers that are called by a Terminal instance to process input and\r
-some flags to control the input mode and behaviour.\r
-\r
-\r
-\r
-3.1 The Default Handler (a simlple example for input handling)\r
-\r
-If no handlers are defined in the configuration object, a default handler is called to\r
-handle a line of user input. The default command line handler `termDefaultHandler' just\r
-closes the command line with a new line and echos the input back to the user:\r
-\r
-  function termDefaultHandler() {\r
-    this.newLine();\r
-    if (this.lineBuffer != '') {\r
-      this.type('You typed: '+this.lineBuffer);\r
-      this.newLine();\r
-    }\r
-    this.prompt();\r
-  }\r
-\r
-First you may note that the instance is refered to as `this'. So you need not worry about\r
-which Terminal instance is calling your handler. As the handler is entered, the terminal\r
-is locked for user input and the cursor is off. The current input is available as a string\r
-value in `this.lineBuffer'.\r
-\r
-The method `type(<text>)' just does what it says and types a string at the current cursor\r
-position to the terminal screen.\r
-\r
-`newLine()' moves the cursor to a new line.\r
-\r
-The method `prompt()' adds a new line if the cursor isn't at the start of a line, outputs\r
-the prompt string (as specified in the configuration), activates the cursor, and unlocks\r
-the terminal for further input. While you're doing normal command line processing, always\r
-call `prompt()' when leaving your handler.\r
-\r
-In fact this is all you need to create your own terminal application. Please see at least\r
-the method `write()' for a more powerful output method.\r
-\r
-Below we will refer to all methods of the Terminal object as `Terminal.<method>()'.\r
-You can call them as `this.<method>()' in a handler or as methods of your named instance\r
-in other context (e.g.: "myTerminal.close()").\r
-\r
-[In technical terms these methods are methods of the Terminal's prototype object, while\r
-the properties are properties of a Termninal instance. Since this doesn't make any\r
-difference to your script, we'll refer to both as `Terminal.<method-or-property>'.]\r
-\r
-\r
-\r
-3.2 Input Modes\r
-\r
-3.2.1 Normal Line Input (Command Line Mode)\r
-\r
-By default the terminal is in normal input mode. Any printable characters in the range of\r
-ASCII 0x20 - 0xff are echoed to the terminal and may be edited with the use of the cursor\r
-keys and the <BACKSPACE> key.\r
-The cursor keys UP and DOWN let the user browse in the command line history (the list of\r
-all commands issued previously in this Terminal instance).\r
-\r
-If the user presses <CR> or <ENTER>, the line is read from the terminal buffer, converted\r
-to a string, and placed in `Terminal.lineBuffer' (-> `this.lineBuffer') for further use.\r
-The terminal is then locked for further input and the specified handler\r
-(`Terminal.handler') is called.\r
-\r
-\r
-3.2.1.2 Special Keys (ctrlHandler)\r
-\r
-If a special character (ASCII<0x20) or an according combination of <CTRL> and a key is\r
-pressed, which is not caught for editing or "enter", and a handler for `ctrlHandler' is\r
-specified, this handler is called.\r
-The ASCII value of the special character is available in `Terminal.inputChar'. Please note\r
-that the terminal is neither locked, nor is the cursor off - all further actions have to\r
-be controlled by `ctrlHandler'. (The tracking of <CTRL>-<key> combinations as "^C" usually\r
-works but cannot be taken for granted.)\r
-\r
-A named reference of the special control values in POSIX form (as well as the values of\r
-the cursor keys [LEFT, RIGHT, UP, DOWN]) is available in the `termKey' object.\r
-\r
-p.e.:\r
-\r
-  // a simple ctrlHandler\r
-\r
-  function myCtrlHandler() {\r
-    if (this.inputChar == termKey.ETX) {\r
-      // exit on ^C (^C == ASCII 0x03 == <ETX>)\r
-      this.close();\r
-    }\r
-  }\r
-\r
-If no `ctrlHandler' is specified, control keys are ignored (default).\r
-\r
-\r
-3.2.2 Raw Mode\r
-\r
-If the flag `Terminal.rawMode' is set to a value evaluating to `true', no special keys are\r
-tracked but <CR> and <ENTER> (and <ESC>, if the flag `Terminal.closeOnESC' is set).\r
-The input is NOT echoed to the terminal. All printable key values [0x20-0xff] are\r
-transformed to characters and added to `Terminal.lineBuffer' sequentially. The command\r
-line input is NOT added to the history.\r
-\r
-This mode is especially suitable for password input.\r
-\r
-p.e.:\r
-\r
-  // using raw mode for password input\r
-\r
-  function myTermHandler() {\r
-    this.newLine();\r
-    // we stored a flag in Terminal.env to track the status\r
-    if (this.env.getpassword) {\r
-      // leave raw mode\r
-      this.rawMode = false;\r
-      if (passwords[this.env.user] == this.lineBuffer) {\r
-        // matched\r
-        this.type('Welcome '+this.env.user);\r
-        this.env.loggedin = true;\r
-      }\r
-      else {\r
-        this.type('Sorry.');\r
-      }\r
-      this.env.getpassword = false;\r
-    }\r
-    else {\r
-      // simple parsing\r
-      var args = this.lineBuffer.split(' ');\r
-      var cmd = args[0];\r
-      if (cmd == 'login') {\r
-        var user = args[1];\r
-        if (!user) {\r
-          this.type('usage: login <username>');\r
-        }\r
-        else {\r
-          this.env.user = user;\r
-          this.env.getpassword = true;\r
-          this.type('password? ');\r
-          // enter raw mode\r
-          this.rawMode = true;\r
-          // leave without prompt so we must unlock first\r
-          this.lock = false;\r
-          return;\r
-        }\r
-      }\r
-      /*\r
-        other actions ...\r
-      */\r
-    }\r
-    this.prompt();\r
-  }\r
-\r
-In this example a handler is set up to process the command "login <username>" and ask for\r
-a password for the given user name in raw mode. Note the use of the object `Terminal.env'\r
-which is just an empty object set up at the creation of the Terminal instance. Its only\r
-purpose is to provide an individual namespace for private data to be stored by a Terminal\r
-instance.\r
-\r
-NOTE: The flag `Terminal.lock' is used to control the keyboard locking. If we would not\r
-set this to `false' before leaving in raw mode, we would be caught in dead-lock, since no\r
-input could be entered and our handler wouldn't be called again. - A dreadful end of our\r
-terminal session.\r
-\r
-NOTE: Raw mode utilizes the property `Terminal.lastLine' to collect the input string.\r
-This is normally emty, when a handler is called. This is not the case if your script left\r
-the input process on a call of ctrlHandler. You should clear `Terminal.lastLine' in such\r
-a case, if you're going to enter raw mode immediatly after this.\r
-\r
-\r
-3.2.3 Character Mode\r
-\r
-If the flag `Terminal.charMode' is set to a value evaluating to `true', the terminal is in\r
-character mode. In this mode the numeric ASCII value of the next key typed is stored in\r
-`Terminal.inputChar'. The input is NOT echoed to the terminal. NO locking or cursor\r
-control is performed and left to the handler.\r
-You can use this mode to implement your editor or a console game.\r
-`Terminal.charMode' takes precedence over `Terminal.rawMode'.\r
-\r
-p.e.: \r
-\r
-  // using char mode\r
-\r
-  function myTermHandler() {\r
-    // this is the normal handler\r
-    this.newLine();\r
-    // simple parsing\r
-    var args = this.lineBuffer.split(' ');\r
-    var cmd = args[0];\r
-    if (cmd == 'edit') {\r
-      // init the editor\r
-      myEditor(this);\r
-      // redirect the handler to editor\r
-      this.handler = myEditor;\r
-      // leave in char mode\r
-      this.charMode = true;\r
-      // show cursor\r
-      this.cursorOn();\r
-      // don't forget unlocking\r
-      this.lock = false;\r
-      return;\r
-    }\r
-    /*\r
-      other actions ...\r
-    */\r
-    this.prompt();\r
-  }\r
-\r
-  function myEditor(initterm) {\r
-    // our dummy editor (featuring modal behaviour)\r
-    if (initterm) {\r
-      // perform initialization tasks\r
-      initterm.clear();\r
-      initterm.write('this is a simple test editor; leave with <ESC> then "q"%n%n');\r
-      initterm.env.mode = '';\r
-      // store a reference of the calling handler\r
-      initterm.env.handler = initterm.handler;\r
-      return;\r
-    }\r
-    // called as handler -> lock first\r
-    this.lock=true;\r
-    // hide cursor\r
-    this.cursorOff();\r
-    var key = this.inputChar;\r
-    if (this.env.mode == 'ctrl') {\r
-      // control mode\r
-      if (key == 113) {\r
-        // "q" => quit\r
-        // leave charMode and reset the handler to normal\r
-        this.charMode = false;\r
-        this.handler = this.env.handler;\r
-        // clear the screen\r
-        this.clear();\r
-        // prompt and return\r
-        this.prompt();\r
-        return;\r
-      }\r
-      else {\r
-        // leave control mode\r
-        this.env.mode = '';\r
-      }\r
-    }\r
-    else {\r
-      // edit mode\r
-      if (key == termKey.ESC) {\r
-        // enter control mode\r
-        // we'd better indicate this in a status line ...\r
-        this.env.mode = 'ctrl';\r
-      }\r
-      else if (key == termKey.LEFT) {\r
-        // cursor left\r
-      }\r
-      else if (key == termKey.RIGHT) {\r
-        // cursor right\r
-      }\r
-      if (key == termKey.UP) {\r
-        // cursor up\r
-      }\r
-      else if (key == termKey.DOWN) {\r
-        // cursor down\r
-      }\r
-      else if (key == termKey.CR) {\r
-        // cr or enter\r
-      }\r
-      else if (key == termKey.BS) {\r
-        // backspace\r
-      }\r
-      else if (key == termKey.DEL) {\r
-        // fwd delete\r
-        // conf.DELisBS is not evaluated in charMode!\r
-      }\r
-      else if (this.isPrintable(key)) {\r
-        // printable char - just type it\r
-        var ch = String.fromCharCode(key);\r
-        this.type(ch);\r
-      }\r
-    }\r
-    // leave unlocked with cursor\r
-    this.lock = false;\r
-    this.cursorOn();\r
-  }\r
-\r
-\r
-Note the redirecting of the input handler to replace the command line handler by the\r
-editor. The method `Terminal.clear()' clears the terminal.\r
-`Terminal.cursorOn()' and `Terminal.cursorOff()' are used to show and hide the cursor.\r
-\r
-\r
-\r
-3.3 Other Handlers\r
-\r
-There are two more handlers that can be specified in the configuration object:\r
-\r
-\r
-3.3.1 initHandler\r
-\r
-`initHandler' is called at the end of the initialization triggered by `Terminal.open()'.\r
-The default action - if no `initHandler' is specified - is:\r
-\r
-  // default initilization\r
-\r
-  this.write(this.conf.greeting);\r
-  this.newLine();\r
-  this.prompt();\r
-\r
-Use `initHandler' to perform your own start up tasks (e.g. show a start up screen). Keep\r
-in mind that you should unlock the terminal and possibly show a cursor to give the\r
-impression of a usable terminal.\r
-\r
-\r
-3.3.2  exitHandler\r
-\r
-`exitHandler' is called by `Terminal.close()' just before hiding the terminal. You can use\r
-this handler to implement any tasks to be performed on exit. Note that this handler is\r
-called even if the terminal is closed on <ESC> outside of your inputHandlers control.\r
-\r
-See the file "multiterm_test.html" for an example.\r
-\r
-\r
-\r
-3.4   Overview: Flags for Behaviour Control\r
-\r
-These falgs are accessible as `Terminal.<flag>' at runtime. If not stated else, the\r
-initial value may be specified in the configuration object.\r
-The configuration object and its properties are accessible at runtime via `Terminal.conf'.\r
-\r
-\r
-  NAME                      DEFAULT VALUE    MEANING\r
-\r
-  blink_delay                         500    delay for cursor blinking in milliseconds.\r
-\r
-  crsrBlinkMode                     false    true for blinking cursor.\r
-                                             if false, cursor is static.\r
-  \r
-  crsrBlockMode                      true    true for block-cursor else underscore.\r
-\r
-  DELisBS                           false    handle <DEL> as <BACKSPACE>.\r
-\r
-  printTab                           true    handle <TAB> as printable (prints as space)\r
-                                             if false <TAB> is handled as a control character\r
-\r
-  printEuro                          true    handle the euro sign as valid input char.\r
-                                             if false char 0x20AC is printed, but not accepted\r
-                                             in the command line\r
-\r
-  catchCtrlH                         true    handle ^H as <BACKSPACE>.\r
-                                             if false, ^H must be tracked by a custom\r
-                                             ctrlHandler.\r
-\r
-  closeOnESC                         true    close terminal on <ESC>.\r
-                                             if true, <ESC> is not available for ctrHandler.\r
-\r
-\r
-  historyUnique                     false    unique history entries.\r
-                                             if true, entries that are identical to the last\r
-                                             entry in the user history will not be added.\r
-\r
-  charMode                          false    terminal in character mode (tracks next key-code).\r
-                                             (runtime only)\r
\r
-  rawMode                           false    terminal in raw mode (no echo, no editing).\r
-                                             (runtime only)\r
-\r
-\r
-Not exactly a flag but useful:\r
-\r
-  ps                                  '>'    prompt string.\r
-\r
-\r
-\r
-\r
-4  Output Methods\r
-\r
-Please note that any output to the terminal implies an advance of the cursor. This means,\r
-that if your output reaches the last column of your terminal, the cursor is advanced and\r
-a new line is opened automatically. This procedure may include scrolling to make room for\r
-the new line. While this is not of much interest for most purposes, please note that, if\r
-you output a string of length 80 to a 80-columns-terminal, and a new line, and another\r
-string, this will result in an empty line between the two strings.\r
-\r
-\r
-4.1  Terminal.type( <text> [,<stylevector>] )\r
-\r
-Types the string <text> at the current cursor position to the terminal. Long lines are\r
-broken where the last column of the terminal is reached and continued in the next line.\r
-`Terminal.write()' does not support any kind of arbitrary line breaks. (This is just a\r
-basic output routine. See `Terminal.write()' for a more powerful output method.)\r
-\r
-A bitvector may be supplied as an optional second argument to represent a style or a\r
-combination of styles. The meanings of the bits set are interpreted as follows:\r
-\r
-<stylevector>:\r
-\r
-   1 ... reverse    (2 power 0)\r
-   2 ... underline  (2 power 1)\r
-   4 ... italics    (2 power 2)\r
-   8 ... strike     (2 power 3)\r
-\r
-So "Terminal.type( 'text', 5 )" types "text" in italics and reverse video.\r
-\r
-Note:\r
-There is no bold, for most monospaced fonts (including Courier) tend to render wider in\r
-bold. Since this would bring the terminal's layout out of balance, we just can't use bold\r
-as a style. - Sorry.\r
-\r
-The HTML-representation of this styles are defined in "TermGlobals.termStyleOpen" and\r
-"TermGlobals.termStyleClose".\r
-\r
-\r
-4.2  Terminal.write( <text> [,<usemore>] )\r
-\r
-Writes a text with markup to the terminal. If an optional second argument evaluates to\r
-true, a UN*X-style utility like `more' is used to page the text. The text may be supplied\r
-as a single string (with newline character "\n") or as an array of lines. Any other input\r
-is transformed to a string value before output.\r
-\r
-4.2.1 Mark-up:\r
-\r
-`Terminal.write()' employs a simple mark-up with the following syntax:\r
-\r
-<markup>: %([+|-]<style>|n|CS|%)\r
-   \r
-   where "+" and '-' are used to switch on and off a style, where\r
-   \r
-   <style>:\r
-   \r
-      "i" ... italics\r
-      "r" ... reverse\r
-      "s" ... strike\r
-      "u" ... underline\r
-      \r
-      "p" ... reset to plain ("%+p" == "%-p")\r
-    \r
-   styles may be combined and may overlap. (e.g. "This is %+rREVERSE%-r, %+uUNDER%+iSCORE%-u%-i.")\r
-   \r
-   "%n"  represents a new line (in fact "\n" is translated to "%n" before processing)\r
-   \r
-   "%CS" clears the terminal screen\r
-   \r
-   "%%"  represents the percent character ('%')\r
-\r
-\r
-4.2.2 Buffering:\r
-\r
-`Terminal.write()' writes via buffered output to the terminal. This means that the\r
-provided text is rendered to a buffer first and then only the visible parts are transfered\r
-to the terminal display buffers. This avoids scrolling delays for long output.\r
-\r
-4.2.3 UseMore Mode:\r
-\r
-The buffering of `Terminal.write()' allows for pagewise output, which may be specified by\r
-a second boolean argument. If <usemore> evaluates to `true' and the output exceeds the\r
-range of empty rows on the terminal screen, `Terminal.write()' performs like the UN*X\r
-utility `more'. The next page may be accessed by hitting <SPACE> while <q> terminates\r
-paging and returns with the prompt (-> `Terminal.prompt()').\r
-\r
-To use this facillity make sure to return immediatly after calling `Terminal.write()' in\r
-order to allow the more-routine to track the user input.\r
-The terminal is set to "charMode == false" afterwards.\r
-\r
-p.e.:\r
-\r
-  // using Terminal.write as a pager\r
-\r
-  function myTermHandler() {\r
-    this.newLine();\r
-    var args = this.lineBuffer.split(' ');\r
-    var cmd = args[0];\r
-    if (cmd == 'more') {\r
-      var page = args[1];\r
-      if (myPages[page]) {\r
-        // Terminal.write as a pager\r
-        this.write(myPages[page], true);\r
-        return;\r
-      }\r
-      else {\r
-        // Terminal.write for simple output\r
-        this.write('no such page.');\r
-      }\r
-    }\r
-    /*\r
-      other actions ...\r
-    */\r
-    this.prompt();\r
-  }\r
-\r
-\r
-4.3  Terminal.typeAt( <r>, <c>, <text> [,<stylevector>] )\r
-\r
-Output the string <text> at row <r>, col <c>.\r
-For <stylevector> see `Terminal.type()'.\r
-`Terminal.typeAt()' does not move the cursor.\r
-\r
-\r
-4.4  Terminal.setChar( <charcode>, <r>, <c> [,<stylevector>] )\r
-\r
-Output a single character represented by the ASCII value of <charcode> at row <r>, col <c>.\r
-For <stylevector> see `Terminal.type()'.\r
-\r
-\r
-4.5  Terminal.newLine()\r
-\r
-Moves the cursor to the first column of the next line and performs scrolling, if needed.\r
-\r
-\r
-4.6  Terminal.clear()\r
-\r
-Clears the terminal screen. (Returns with cursor off.)\r
-\r
-\r
-4.7  Terminal.statusLine( <text> [,<stylevector> [,<lineoffset>]] )\r
-\r
-All output acts on a logical screen with the origin at row 0 / col 0. While the origin is\r
-fixed, the logical width and height of the terminal are defined by `Terminal.maxCols' and\r
-`Terminal.maxLines'. These are set to the configuration dimensions at initilization and by\r
-`Terminal.reset()', but may be altered at any moment. Please note that there are no bounds\r
-checked, so make sure that `Terminal.maxCols' and `Terminal.maxLines' are less or equal\r
-to the configuration dimensions.\r
-\r
-You may want to decrement `Terminal.maxLines' to keep space for a reserved status line.\r
-`Terminal.statusLine( <text>, <style> )' offers a simple way to type a text to the last\r
-line of the screen as defined by the configuration dimensions.\r
-\r
-  // using statusLine()\r
-\r
-  function myHandler() {\r
-    // ...\r
-    // reserve last line\r
-    this.maxLines = term.conf.rows-1;\r
-    // print to status line in reverse video\r
-    this.statusLine("Status: <none>", 1);\r
-    // ...\r
-  }\r
-\r
-For multiple status lines the optional argument <lineoffset> specifies the addressed row,\r
-where 1 is the line closest to the bottom, 2 the second line from the bottom and so on.\r
-(default: 1)\r
-\r
-\r
-4.8  Terminal.printRowFromString( <r> , <text> [,<stylevector>] )\r
-\r
-Outputs the string <text> to row <r> in the style of an optional <stylevector>.\r
-If the string's length exceeds the length of the row  (up to `Terminal.conf.cols'), extra\r
-characteres are ignored, else any extra space is filled with character code 0 (prints as\r
-<SPACE>).\r
-The valid range for <row> is: 0 >= <row> < `Terminal.maxLines'.\r
-`Terminal.printRowFromString()' does not set the cursor.\r
-\r
-You could, for example, use this method to output a line of a text editor's buffer.\r
-\r
-p.e.:\r
-\r
-  // page refresh function of a text editor\r
-\r
-  function myEditorRefresh(termref, topline) {\r
-    // termref: reference to Terminal instance\r
-    // topline: index of first line to print\r
-    // lines of text are stored in termref.env.lines\r
-    for (var r=0; r<termref.maxLines; r++) {\r
-      var i = topline + r;\r
-      if (i < termref.env.lines.length) {\r
-        // output stored line\r
-        termref.printRowFromString(r, termref.env.lines[i]);\r
-      }\r
-      else {\r
-        // output <tilde> for empty line\r
-        termref.printRowFromString(r, '~');\r
-      }\r
-    }\r
-    // set cursor to origin\r
-    termref.r = termref.c = 0; // same as termref.cursorSet(0, 0);\r
-  }\r
-\r
-\r
-4.9  Terminal.redraw( <row> )\r
-\r
-Basic function to redraw a terminal row <row> according to screen buffer values.\r
-For hackers only. (e.g.: for a console game, hack screen buffers first and redraw all\r
-changed rows at once.)\r
-\r
-\r
-\r
-\r
-5  Cursor Methods and Editing\r
-\r
-\r
-5.1  Terminal.cursorOn()\r
-\r
-Show the cursor.\r
-\r
-\r
-5.2  Terminal.cursorOff()\r
-\r
-Hide the cursor.\r
-\r
-\r
-5.3  Terminal.cursorSet( <r>, <c> )\r
-\r
-Set the cursor position to row <r> column <c>.\r
-`Terminal.cursorSet()' preserves the cursor's active state (on/off).\r
-\r
-\r
-5.4  Terminal.cursorLeft()\r
-\r
-Move the cursor left. (Movement is restricted to the logical input line.)\r
-`Terminal.cursorLeft()' preserves the cursor's active state (on/off).\r
-\r
-\r
-5.5  Terminal.cursorRight()\r
-\r
-Move the cursor right. (Movement is restricted to the logical input line.)\r
-`Terminal.cursorRight()' preserves the cursor's active state (on/off).\r
-\r
-\r
-5.6  Terminal.backspace()\r
-\r
-Delete the character left from the cursor, if the cursor is not in first position of the\r
-logical input line.\r
-`Terminal.backspace()' preserves the cursor's active state (on/off).\r
-\r
-\r
-5.7  Terminal.fwdDelete()\r
-\r
-Delete the character under the cursor.\r
-`Terminal.fwdDelete()' preserves the cursor's active state (on/off).\r
-\r
-\r
-5.8  Terminal.isPrintable( <key code> [,<unicode page 1 only>] )\r
-\r
-Returns `true' if the character represented by <key code> is printable with the current\r
-settings. An optional second argument <unicode page 1 only> limits the range of valid\r
-values to 255 with the exception of the Euro sign, if the flag `Terminal.printEuro' is set.\r
-(This second flag is used for input methods but not for output methods. So you may only\r
-enter portable characters, but you may print others to the terminals screen.)\r
-\r
-\r
-\r
-\r
-6  Other Methods of the Terminal Object\r
-\r
-6.1  Terminal.prompt()\r
-\r
-Performes the following actions:\r
-\r
-  * advance the cursor to a new line, if the cursor is not at 1st column\r
-  * type the prompt string (as specified in the configuaration object)\r
-  * show the cursor\r
-  * unlock the terminal\r
-\r
-(The value of the prompt string can be accessed and changed in `Terminal.ps'.)\r
-\r
-\r
-6.2  Terminal.reset()\r
-\r
-Resets the terminal to sane values and clears the terminal screen.\r
-\r
-\r
-6.3  Terminal.open()\r
-\r
-Opens the terminal. If this is a fresh instance, the HTML code for the terminal is\r
-generated. On re-entry the terminal's visibility is set to `true'. Initialization tasks\r
-are performed and the optional initHandler called. If no initHandler is specified in the\r
-configuration object, the greeting (configuration or default value) is shown and the user\r
-is prompted for input.\r
-\r
-v.1.01: `Terminal.open()' now checks for the existence of the DHTML element as defined in\r
-        `Terminal.conf.termDiv' and returns success.\r
-\r
-\r
-6.4  Terminal.close()\r
-\r
-Closes the terminal and hides its visibility. An optional exitHandler (specified in the\r
-configuration object) is called, and finally the flag `Terminal.closed' is set to true. So\r
-you can check for existing terminal instances as you would check for a `window' object\r
-created by `window.open()'.\r
-\r
-p.e.:\r
-\r
-  // check for a terminals state\r
-  // let array "term" hold references to terminals\r
-\r
-  if (term[n]) {\r
-    if (term[n].closed) {\r
-      // terminal exists and is closed\r
-      // re-enter via "term[n].open()"\r
-    }\r
-    else {\r
-      // terminal exists and is currently open\r
-    }\r
-  }\r
-  else {\r
-    // no such terminal\r
-    // create it via "term[n] = new Terminal()"\r
-  }\r
-\r
-\r
-6.5  Terminal.focus()\r
-\r
-Set the keyboard focus to this instance of Terminal. (As `window.focus()'.)\r
-\r
-\r
-6.6  Terminal.moveTo( <x>, <y> )\r
-\r
-Move the terminal to position <x>/<y> in px.\r
-(As `window.moveTo()', but inside the HTML page.)\r
-\r
-\r
-6.7  Terminal.resizeTo( <x>, <y> )\r
-\r
-Resize the terminal to dimensions <x> cols and <y> rows.\r
-<x> must be at least 4, <y> at least 2.\r
-`Terminal.resizeTo()' resets `Terminal.conf.rows', `Terminal.conf.cols',\r
-`Terminal.maxLines', and `Terminal.maxCols' to <y> and <x>, but leaves the instance' state\r
-else unchanged. Clears the terminal's screen and returns success.\r
-\r
-(A bit like `window.resizeTo()', but with rows and cols instead of px.)\r
-\r
-\r
-6.8  Terminal.getDimensions()\r
-\r
-Returns an object with properties "width" and "height" with numeric values for the\r
-terminal's outer dimensions in px. Values are zero (0) if the element is not present or\r
-if the method fails otherwise.\r
-\r
-\r
-6.9  Terminal.rebuild()\r
-\r
-Rebuilds the Terminal object's GUI preserving its state and content.\r
-Use this to change the color theme on the fly.\r
-\r
-p.e.:\r
-\r
-   // change color settings on the fly\r
-   // here: set bgColor to white and font style to "termWhite"\r
-   // method rebuild() updates the GUI without side effects\r
-\r
-   term.conf.bgColor = '#ffffff';\r
-   term.conf.fontClass = 'termWhite';\r
-   term.rebuild();\r
-\r
-\r
-\r
-\r
-7   Global Static Methods (TermGlobals)\r
-\r
-\r
-7.1  TermGlobals.setFocus( <termref> )\r
-\r
-Sets the keyboard focus to the instance referenced by <termref>.\r
-The focus is controlled by `TermGlobals.activeTerm' which may be accessed directly.\r
-See also: `Terminal.focus()'\r
-\r
-\r
-7.2  TermGlobals.keylock (Global Locking Flag)\r
-\r
-The global flag `TermGlobals.keylock' allows temporary keyboard locking without any\r
-other change of state. Use this to free the keyboard for any other resources.\r
-(added in v.1.03)\r
-\r
-\r
-7.3  TermGlobals Text Methods\r
-\r
-There is a small set of methods for common terminal related string tasks:\r
-\r
-\r
-7.3.1  TermGlobals.normalize( <n>, <fieldlength> )\r
-\r
-Converts a number to a string, which is filled at its left with zeros ("0") to the total\r
-length of <filedlength>. (e.g.: "TermGlobals.normalize(1, 2)" => "01")\r
-\r
-\r
-7.3.2  TermGlobals.fillLeft( <value>, <fieldlength> )\r
-\r
-Converts a value to a string and fills it to the left with blanks to <fieldlength>.\r
-\r
-\r
-7.3.3  TermGlobals.center( <text>, <length> )\r
-\r
-Adds blanks at the left of the string <text> until the text would be centered at a line\r
-of length <length>. (No blanks are added to the the right.)\r
-\r
-\r
-7.3.4  TermGlobals.stringReplace( <string1>, <string2>, <text> )\r
-\r
-Replaces all occurences of the string <string1> in <text> with <string2>.\r
-This is just a tiny work around for browsers with no support of RegExp.\r
-\r
-\r
-\r
-\r
-8   Localization\r
-\r
-The strings and key-codes used by the more utility of `Terminal.write()' are the only\r
-properties of "termlib.js" that may need localization. These properties are defined in\r
-`TermGlobals'. You may override them as needed:\r
-\r
-PROPERTY                                      STANDARD VALUE                 COMMENT\r
-\r
-TermGlobals.lcMorePrompt1                                    ' -- MORE -- '  1st string\r
-TermGlobals.lcMorePromtp1Style                                            1  reverse\r
-TermGlobals.lcMorePrompt2       ' (Type: space to continue, \'q\' to quit)'  appended string\r
-TermGlobals.lcMorePrompt2Style                                            0  plain\r
-TermGlobals.lcMoreKeyAbort                                              113  (key-code: q)\r
-TermGlobals.lcMoreKeyContinue                                            32  (key-code <SPACE>)\r
-\r
-\r
-As "TermGlobals.lcMorePrompt2" is appended to "TermGlobals.lcMorePrompt1" make sure that\r
-the length of the combined strings does not exceed `Terminal.conf.cols'.\r
-\r
-\r
-\r
-\r
-9   Cross Browser Functions\r
-\r
-For DHTML rendering some methods - as needed by the Terminal library - are provided.\r
-These may also be accessed for other purposes.\r
-\r
-\r
-9.1  TermGlobals.writeElement( <element id>, <text> [,<NS4 parent document>] )\r
-\r
-Writes <text> to the DHTML element with id/name <element id>. \r
-<NS4 parent document> is used for NS4 only and specifies an optional reference to a parent\r
-document (default `window.document').\r
-\r
-9.2  TermGlobals.setElementXY( <element id>, <x>, <y> )\r
-\r
-Sets the DHTML element with id/name <element id> to position <x>/<y>.\r
-For NS4 works only with children of the top document (window.document).\r
-\r
-\r
-9.3  TermGlobals.setVisible( <element id>, <value> )\r
-\r
-If <value> evaluates to `true' show DHTML element with id/name <element id> else hide it.\r
-For NS4 works only with children of the top document (window.document).\r
-\r
-\r
-9.4  Custom Fixes for Missing String Methods\r
-\r
-Although `String.fromCharCode' and `String.prototype.charCodeAt' are defined by ECMA-262-2\r
-specifications, a few number of browsers lack them in their JavaScript implementation. At\r
-compile time custom methods are installed to fix this. Please note that they work only\r
-with ASCII characters and values in the range of [0x20-0xff].\r
-\r
-\r
-9.5  TermGlobals.setDisplay( <element id>, <value> )\r
-\r
-Sets the style.display property of the element with id/name <element id> to the given\r
-<value>. (added with v. 1.06)\r
-\r
-\r
-\r
-\r
-10   Architecture, Internals\r
-\r
-10.1  Global Entities\r
-\r
-The library is designed to leave only a small foot print in the namespace while providing\r
-suitable usability:\r
-\r
-  Globals defined in this library:\r
-\r
-    Terminal           (Terminal object, `new' constructor and prototype methods)\r
-    TerminalDefaults   (default configuration, static object)\r
-    termDefaultHandler (default command line handler, static function)\r
-    TermGlobals        (common vars and code for all instances, static object and methods)\r
-    termKey            (named mappings for special keys, static object)\r
-    termDomKeyRef      (special key mapping for DOM key constants, static object)\r
-\r
-\r
-  Globals defined for fixing String methods, if missing\r
-  (String.fromCharCode, String.prototype.charCodeAt):\r
-\r
-    termString_keyref, termString_keycoderef, termString_makeKeyref\r
-\r
-  \r
-  Required CSS classes for font definitions: ".term", ".termReverse".\r
-\r
-\r
-\r
-10.2  I/O Architecture\r
-\r
-The Terminal object renders keyboard input from keyCodes to a line buffer and/or to a\r
-special keyCode buffer. In normal input mode printable input is echoed to the screen\r
-buffers. Special characters like <LEFT>, <RIGHT>, <BACKSPACE> are processed for command\r
-line editing by the internal key-handler `TermGlobals.keyHandler' and act directly on the\r
-screen buffers. On <CR> or <ENTER> the start and end positions of the current line are\r
-evaluated (terminated by ASCII 0x01 at the beginning which separates the prompt from the\r
-user input, and any value less than ASCII 0x20 (<SPACE>) at the right end). Then the\r
-character representation for the buffer values in this range are evaluated and\r
-concatenated to a string stored in `Terminal.lineBuffer'. As this involves some\r
-ASCII-to-String-transformations, the range of valid printable input characters is limited\r
-to the first page of unicode characters (0x0020-0x00ff).\r
-\r
-There are two screen buffers for output, one for character codes (ASCII values) and one\r
-for style codes. Style codes represent combination of styles as a bitvector (see\r
-`Terminal.type' for bit values.) The method `Terminal.redraw(<row>)' finally renders the\r
-buffers values to a string of HTML code, which is written to the HTML entity holding the\r
-according terminal row. The character buffer is a 2 dimensional array\r
-`Terminal.charBuf[<row>][<col>]' with ranges for <row> from 0 to less than\r
-`Terminal.conf.rows' and for <col> from 0 to less than `Terminal.conf.cols'. The style\r
-buffer is a 2 dimensional array `Terminal.styleBuf[<row>][<col>]' with according ranges.\r
-\r
-So every single character is represented by a ASCII code in `Terminal.charBuf' and a\r
-style-vector in `Terminal.styleBuf'. The range of printable character codes is unlimitted\r
-but should be kept to the first page of unicode characters (0x0020-0x00ff) for\r
-compatibility purpose. (c.f. 8.4)\r
-\r
-Keyboard input is first handled on the `KEYDOWN' event by the handler `TermGlobals.keyFix'\r
-to remap the keyCodes of cursor keys to consistent values. (To make them distinctable from\r
-any other possibly printable values, the values of POSIX <IS4> to <IS1> where chosen.)\r
-The mapping of the cursor keys is stored in the properties LEFT, RIGHT, UP, and DOWN of\r
-the global static object `termKey'.\r
-\r
-The main keyboard handler `TermGlobals.keyHandler' (invoked on `KEYPRESS' or by\r
-`TermGlobals.keyFix') does some final mapping first. Then the input is evaluated as\r
-controlled by the flags `Terminal.rawMode' and `Terminal.charMode' with precedence of the\r
-latter. In dependancy of the mode defined and the handlers currently defined, the input\r
-either is ignored, or is internally processed for command line editing, or one of the\r
-handlers is called.\r
-\r
-In the case of the simultanous presecence of two instances of Terminal, the keyboard focus\r
-is controlled via a reference stored in `TermGlobals.activeTerm'. This reference is also\r
-used to evaluate the `this'-context of the key handlers which are methods of the static\r
-Object `TermGlobals'.\r
-\r
-A terminal's screen consists of a HTML-table element residing in the HTML/CSS division\r
-spcified in `Terminal.conf.termDiv'. Any output is handled on a per row bases. The\r
-individual rows are either nested sub-divisions of the main divisions (used for NS4 or\r
-browsers not compatible to the "Gecko" engine) or the indiviual table data elements (<TD>)\r
-of the terminal's inner table (used for browsers employing the "Gecko" engine).\r
-(This implementation was chosen for rendering speed and in order to minimize any screen\r
-flicker.) Any output or change of state in a raw results in the inner HTML contents of a\r
-row's HTML element to be rewritten. Please note that as a result of this a blinking cursor\r
-may cause a flicker in the line containing the cursor's position while displayed by a\r
-browser, which employs the "Gecko" engine.\r
-\r
-\r
-\r
-10.3  Compatibility\r
-\r
-Standard web browsers with a JavaScript implementation compliant to ECMA-262 2nd edition\r
-[ECMA262-2] and support for the anonymous array and object constructs and the anonymous\r
-function construct in the form of "myfunc = function(x) {}" (c.f. ECMA-262 3rd edion\r
-[ECMA262-3] for details). This comprises almost all current browsers but Konquerer (khtml)\r
-and versions of Apple Safari for Mac OS 10.0-10.28 (Safari < 1.1) which lack support for\r
-keyboard events.\r
-\r
-To provide a maximum of compatibilty the extend of language keywords used was kept to a\r
-minimum and does not exceed the lexical conventions of ECMA-262-2. Especially there is no\r
-use of the `switch' statement or the `RegExp' method of the global object. Also the use of\r
-advanced Array methods like `push', `shift', `splice' was avoided.\r
-\r
-\r
-\r
-\r
-11   History\r
-\r
-This library evolved from the terminal script "TermApp" ((c) N. Landsteiner 2003) and is\r
-in its current form a down scaled spinn-off of the "JS/UIX" project [JS/UIX] (evolution\r
-"JS/UIX v0.5"). c.f.: <http://www.masswerk.at/jsuix>\r
-\r
-v 1.01: added Terminal.prototype.resizeTo(x,y)\r
-        added Terminal.conf.fontClass (=> configureable class name)\r
-        Terminal.prototype.open() now checks for element conf.termDiv in advance\r
-          and returns success.\r
-\r
-v 1.02: added support for <TAB> and Euro sign\r
-          Terminal.conf.printTab\r
-          Terminal.conf.printEuro\r
-        and method Terminal.prototype.isPrintable(keycode)\r
-        added support for getopt to sample parser ("parser_sample.html")\r
-\r
-\r
-v 1.03: added global keyboard locking (TermGlobals.keylock)\r
-        modified Terminal.prototype.redraw for speed (use of locals)\r
-\r
-\r
-v 1.04: modified the key handler to fix a bug with MSIE5/Mac\r
-        fixed a bug in TermGlobals.setVisible with older MSIE-alike browsers without\r
-        DOM support.\r
-        moved the script of the sample parser to an individual document\r
-        => "termlib_parser.js" (HTML document is "parser_sample.html" as before)\r
-\r
-v 1.05: added config flag historyUnique.\r
-\r
-v 1.06: fixed CTRl+ALT (Windows alt gr) isn't CTRL any more\r
-        -> better support for international keyboards with MSIE/Win.\r
-        fixed double backspace bug for Safari;\r
-        added TermGlobals.setDisplay for setting style.display props\r
-        termlib.js now outputs lower case html (xhtml compatibility)\r
-        (date: 12'2006)\r
-\r
-v 1.07: added method Terminal.rebuild() to rebuild the GUI with new color settings.\r
-        (date: 01'2007)\r
-\r
-\r
-\r
-\r
-12  Example for a Command Line Parser\r
-\r
-  // parser example, splits command line to args with quoting and escape\r
-  // for use as `Terminal.handler'\r
-  \r
-  function commandHandler() {\r
-    this.newLine();\r
-    var argv = [''];     // arguments vector\r
-    var argQL = [''];    // quoting level\r
-    var argc = 0;        // arguments cursor\r
-    var escape = false ; // escape flag\r
-    for (var i=0; i<this.lineBuffer.length; i++) {\r
-      var ch= this.lineBuffer.charAt(i);\r
-      if (escape) {\r
-        argv[argc] += ch;\r
-        escape = false;\r
-      }\r
-      else if ((ch == '"') || (ch == "'") || (ch == "`")) {\r
-        if (argQL[argc]) {\r
-          if (argQL[argc] == ch) {\r
-            argc ++;\r
-            argv[argc] = argQL[argc] = '';\r
-          }\r
-          else {\r
-            argv[argc] += ch;\r
-          }\r
-        }\r
-        else {\r
-          if (argv[argc] != '') {\r
-            argc ++;\r
-            argv[argc] = '';\r
-            argQL[argc] = ch;\r
-          }\r
-          else {\r
-            argQL[argc] = ch;\r
-          }\r
-        }\r
-      }\r
-      else if ((ch == ' ') || (ch == '\t')) {\r
-        if (argQL[argc]) {\r
-          argv[argc] += ch;\r
-        }\r
-        else if (argv[argc] != '') {\r
-          argc++;\r
-          argv[argc] = argQL[argc] = '';\r
-        }\r
-      }\r
-      else if (ch == '\\') {\r
-        escape = true;\r
-      }\r
-      else {\r
-        argv[argc] += ch;\r
-      }\r
-    }\r
-    if ((argv[argc] == '') && (!argQL[argc])) {\r
-      argv.length--;\r
-      argQL.length--;\r
-    }\r
-    if (argv.length == 0) {\r
-      // no commmand line input\r
-    }\r
-    else if (argQL[0]) {\r
-      // first argument quoted -> error\r
-      this.write("Error: first argument quoted by "+argQL[0]);\r
-    }\r
-    else {\r
-      argc = 0;\r
-      var cmd = argv[argc++];\r
-      /*\r
-        parse commands\r
-        1st argument is argv[argc]\r
-        arguments' quoting levels in argQL[argc] are of (<empty> | ' | " | `)\r
-      */\r
-      if (cmd == 'help') {\r
-        this.write(helpPage);\r
-      }\r
-      else if (cmd == 'clear') {\r
-        this.clear();\r
-      }\r
-      else if (cmd == 'exit') {\r
-        this.close();\r
-        return;\r
-      }\r
-      else {\r
-        // for test purpose just output argv as list\r
-        // assemple a string of style-escaped lines and output it in more-mode\r
-        s='   ARG  QL  VALUE%n';\r
-        for (var i=0; i<argv.length; i++) {\r
-          s += TermGlobals.stringReplace('%', '%%',\r
-                 TermGlobals.fillLeft(i, 6) +\r
-                 TermGlobals.fillLeft((argQL[i])? argQL[i]:'-', 4) +\r
-                 '  "' + argv[i] + '"'\r
-            ) + '%n';\r
-        }\r
-        this.write(s, 1);\r
-        return;\r
-      }\r
-    }\r
-    this.prompt();\r
-  }\r
-\r
-\r
-The file "parser_sample.html" features a stand-alone parser ("termlib_parser.js") very\r
-much like this. You are free to use it according to the termlib-license (see sect. 13).\r
-It provides configurable values for quotes and esape characters and imports the parsed\r
-argument list into a Terminal instance's namespace. ("parser_sample.html" and\r
-"termlib_parser.js" should accompany this file.)\r
-\r
-\r
-\r
-\r
-13   License\r
-\r
-This JavaScript-library is free for private and academic use.\r
-Please include a readable copyright statement and a backlink to <http://www.masswerk.at>\r
-in the web page. The library should always be accompanied by the 'readme.txt' and the\r
-sample HTML-documents.\r
-\r
-The term "private use" includes any personal or non-commercial use, which is not related\r
-to commercial activites, but excludes intranet, extranet and/or public net applications\r
-that are related to any kind of commercial or profit oriented activity.\r
-\r
-For commercial use see <http://www.masswerk.at> for contact information.\r
-\r
-Any changes to the library should be commented and be documented in the readme-file.\r
-Any changes must be reflected in the `Terminal.version' string as\r
-"Version.Subversion (compatibility)".\r
-\r
-\r
-\r
-\r
-14   Disclaimer\r
-\r
-This software is distributed AS IS and in the hope that it will be useful, but WITHOUT ANY\r
-WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
-PURPOSE. The entire risk as to the quality and performance of the product is borne by the\r
-user. No use of the product is authorized hereunder except under this disclaimer.\r
-\r
-\r
-\r
-\r
-15   References\r
-\r
-[ECMA262-2] "ECMAScript Language Specification" Standard ECMA-262 2nd Edition\r
-            August 1998 (ISO/IEC 16262 - April 1998)\r
-\r
-[ECMA262-3] "ECMAScript Language Specification" Standard ECMA-262 3rd Edition Final\r
-            24 March 2000\r
-\r
-[JS/UIX]     JS/UIX - JavaScript Uniplexed Interface eXtension\r
-             <http://www.masswerk.at/jsuix>\r
-\r
-\r
-\r
-\r
-\r
-Norbert Landsteiner / Vienna, August 2005\r
-mass:werk - media environments\r
-<http://www.masswerk.at>\r
-See web site for contact information.\r
diff --git a/extra/webapps/fjsc/resources/termlib/term_styles.css b/extra/webapps/fjsc/resources/termlib/term_styles.css
deleted file mode 100644 (file)
index 4971709..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-.term {\r
-       font-family: courier,fixed,swiss,sans-serif;\r
-       font-size: 12px;\r
-       color: #33d011;\r
-       background: none;\r
-}\r
-\r
-.termReverse {\r
-       color: #111111;\r
-       background: #33d011;\r
-}\r
diff --git a/extra/webapps/fjsc/resources/termlib/termlib.js b/extra/webapps/fjsc/resources/termlib/termlib.js
deleted file mode 100644 (file)
index 195e11f..0000000
+++ /dev/null
@@ -1,1633 +0,0 @@
-/*\r
-  termlib.js - JS-WebTerminal Object v1.07\r
-\r
-  (c) Norbert Landsteiner 2003-2005\r
-  mass:werk - media environments\r
-  <http://www.masswerk.at>\r
-\r
-  Creates [multiple] Terminal instances.\r
-\r
-  Synopsis:\r
-\r
-  myTerminal = new Terminal(<config object>);\r
-  myTerminal.open();\r
-\r
-  <config object> overrides any values of object `TerminalDefaults'.\r
-  individual values of `id' must be supplied for multiple terminals.\r
-  `handler' specifies a function to be called for input handling.\r
-  (see `Terminal.prototype.termDefaultHandler()' and documentation.)\r
-\r
-  globals defined in this library:\r
-       Terminal           (Terminal object)\r
-    TerminalDefaults   (default configuration)\r
-    termDefaultHandler (default command line handler)\r
-    TermGlobals        (common vars and code for all instances)\r
-    termKey            (named mappings for special keys)\r
-    termDomKeyRef      (special key mapping for DOM constants)\r
-\r
-  globals defined for fixing String methods, if missing\r
-  (String.fromCharCode, String.prototype.charCodeAt):\r
-    termString_keyref, termString_keycoderef, termString_makeKeyref\r
-\r
-  required CSS classes for font definitions: ".term", ".termReverse".\r
-\r
-  Compatibilty:\r
-  Standard web browsers with a JavaScript implementation compliant to\r
-  ECMA-262 2nd edition and support for the anonymous array and object\r
-  constructs and the anonymous function construct in the form of\r
-  "myfunc=function(x) {}" (c.f. ECMA-262 3rd edion for details).\r
-  This comprises almost all current browsers but Konquerer (khtml) and\r
-  versions of Apple Safari for Mac OS 10.0-10.28 (Safari 1.0) which\r
-  lack support for keyboard events.\r
-\r
-  License:\r
-  This JavaScript-library is free for private and academic use.\r
-  Please include a readable copyright statement and a backlink to\r
-  <http://www.masswerk.at> in the web page.\r
-  The library should always be accompanied by the 'readme.txt' and the\r
-  sample HTML-documents.\r
-  \r
-  The term "private use" includes any personal or non-commercial use, which\r
-  is not related to commercial activites, but excludes intranet, extranet\r
-  and/or public net applications that are related to any kind of commercial\r
-  or profit oriented activity.\r
-\r
-  For commercial use see <http://www.masswerk.at> for contact information.\r
-  \r
-  Any changes should be commented and must be reflected in `Terminal.version'\r
-  in the format: "Version.Subversion (compatibility)".\r
-\r
-  Disclaimer:\r
-  This software is distributed AS IS and in the hope that it will be useful,\r
-  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
-  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. The entire risk as to\r
-  the quality and performance of the product is borne by the user. No use of\r
-  the product is authorized hereunder except under this disclaimer.\r
-\r
-  ### The sections above must not be removed. ###\r
-  \r
-  version 1.01: added Terminal.prototype.resizeTo(x,y)\r
-                added Terminal.conf.fontClass (=> configureable class name)\r
-                Terminal.prototype.open() now checks for element conf.termDiv\r
-                in advance and returns success.\r
-\r
-  version 1.02: added support for <TAB> and Euro sign\r
-                (Terminal.conf.printTab, Terminal.conf.printEuro)\r
-                and a method to evaluate printable chars:\r
-                Terminal.prototype.isPrintable(keycode)\r
-\r
-  version 1.03: added global keyboard locking (TermGlobals.keylock)\r
-                modified Terminal.prototype.redraw for speed (use of locals)\r
-\r
-  version 1.04: modified the key handler to fix a bug with MSIE5/Mac\r
-                fixed a bug in TermGlobals.setVisible with older MSIE-alike\r
-                browsers without DOM support.\r
-\r
-  version 1.05: added config flag historyUnique.\r
\r
-  version 1.06: fixed CTRl+ALT (Windows alt gr) isn't CTRL any more\r
-                fixed double backspace bug for Safari;\r
-                added TermGlobals.setDisplay for setting style.display props\r
-                termlib.js now outputs lower case html (xhtml compatibility)\r
-\r
-  version 1.07: added method rebuild() to rebuild with new color settings.\r
-\r
-*/\r
-\r
-var TerminalDefaults = {\r
-       // dimensions\r
-       cols:80,\r
-       rows:24,\r
-       // appearance\r
-       x:100,\r
-       y:100,\r
-       termDiv:'termDiv',\r
-       bgColor:'#181818',\r
-       frameColor:'#555555',\r
-       frameWidth:1,\r
-       rowHeight:15,\r
-       blinkDelay:500,\r
-       // css class\r
-       fontClass:'term',\r
-       // initial cursor mode\r
-       crsrBlinkMode:false,\r
-       crsrBlockMode:true,\r
-       // key mapping\r
-       DELisBS:false,\r
-       printTab:true,\r
-       printEuro:true,\r
-       catchCtrlH:true,\r
-       closeOnESC:true,\r
-       // prevent consecutive history doublets\r
-       historyUnique:false,\r
-       // optional id\r
-       id:0,\r
-       // strings\r
-       ps:'>',\r
-       greeting:'%+r Terminal ready. %-r',\r
-       // handlers\r
-       handler:termDefaultHandler,\r
-       ctrlHandler:null,\r
-       initHandler:null,\r
-       exitHandler:null\r
-}\r
-\r
-var Terminal = function(conf) {\r
-       if (typeof conf != 'object') conf=new Object();\r
-       else {\r
-               for (var i in TerminalDefaults) {\r
-                       if (typeof conf[i] == 'undefined') conf[i]=TerminalDefaults[i];\r
-               }\r
-       }\r
-       this.conf=conf;\r
-       this.version='1.07 (original)';\r
-       this.isSafari= (navigator.userAgent.indexOf('Safari')>=0)? true:false;\r
-       this.setInitValues();\r
-}\r
-\r
-Terminal.prototype.setInitValues=function() {\r
-       this.id=this.conf.id;\r
-       this.maxLines=this.conf.rows;\r
-       this.maxCols=this.conf.cols;\r
-       this.termDiv=this.conf.termDiv;\r
-       this.crsrBlinkMode=this.conf.crsrBlinkMode;\r
-       this.crsrBlockMode=this.conf.crsrBlockMode;\r
-       this.blinkDelay=this.conf.blinkDelay;\r
-       this.DELisBS=this.conf.DELisBS;\r
-       this.printTab=this.conf.printTab;\r
-       this.printEuro=this.conf.printEuro;\r
-       this.catchCtrlH=this.conf.catchCtrlH;\r
-       this.closeOnESC=this.conf.closeOnESC;\r
-       this.historyUnique=this.conf.historyUnique;\r
-       this.ps=this.conf.ps;\r
-       this.closed=false;\r
-       this.r;\r
-       this.c;\r
-       this.charBuf=new Array();\r
-       this.styleBuf=new Array();\r
-       this.scrollBuf=null;\r
-       this.blinkBuffer=0;\r
-       this.blinkTimer;\r
-       this.cursoractive=false;\r
-       this.lock=true;\r
-       this.insert=false;\r
-       this.charMode=false;\r
-       this.rawMode=false;\r
-       this.lineBuffer='';\r
-       this.inputChar=0;\r
-       this.lastLine='';\r
-       this.guiCounter=0;\r
-       this.history=new Array();\r
-       this.histPtr=0;\r
-       this.env=new Object();\r
-       this.ns4ParentDoc=null;\r
-       this.handler=this.conf.handler;\r
-       this.ctrlHandler=this.conf.ctrlHandler;\r
-       this.initHandler=this.conf.initHandler;\r
-       this.exitHandler=this.conf.exitHandler;\r
-}\r
-\r
-function termDefaultHandler() {\r
-       this.newLine();\r
-       if (this.lineBuffer != '') {\r
-               this.type('You typed: '+this.lineBuffer);\r
-               this.newLine();\r
-       }\r
-       this.prompt();\r
-}\r
-\r
-Terminal.prototype.open=function() {\r
-       if (this.termDivReady()) {\r
-               if (!this.closed) this._makeTerm();\r
-               this.init();\r
-               return true;\r
-       }\r
-       else return false;\r
-}\r
-\r
-Terminal.prototype.close=function() {\r
-       this.lock=true;\r
-       this.cursorOff();\r
-       if (this.exitHandler) this.exitHandler();\r
-       TermGlobals.setVisible(this.termDiv,0);\r
-       this.closed=true;\r
-}\r
-\r
-Terminal.prototype.init=function() {\r
-       // wait for gui\r
-       if (this.guiReady()) {\r
-               this.guiCounter=0;\r
-               // clean up at re-entry\r
-               if (this.closed) {\r
-                       this.setInitValues();\r
-               }\r
-               this.clear();\r
-               TermGlobals.setVisible(this.termDiv,1);\r
-               TermGlobals.enableKeyboard(this);\r
-               if (this.initHandler) {\r
-                       this.initHandler();\r
-               }\r
-               else {\r
-                       this.write(this.conf.greeting);\r
-                       this.newLine();\r
-                       this.prompt();\r
-               }\r
-       }\r
-       else {\r
-               this.guiCounter++;\r
-               if (this.guiCounter>18000) {\r
-                       if (confirm('Terminal:\nYour browser hasn\'t responded for more than 2 minutes.\nRetry?')) this.guiCounter=0\r
-                       else return;\r
-               };\r
-               TermGlobals.termToInitialze=this;\r
-               window.setTimeout('TermGlobals.termToInitialze.init()',200);\r
-       }\r
-}\r
-\r
-Terminal.prototype.getRowArray=function(l,v) {\r
-       var a=new Array();\r
-       for (var i=0; i<l; i++) a[i]=v;\r
-       return a;\r
-}\r
-\r
-Terminal.prototype.type=function(text,style) {\r
-       for (var i=0; i<text.length; i++) {\r
-               var ch=text.charCodeAt(i);\r
-               if (!this.isPrintable(ch)) ch=94;\r
-               this.charBuf[this.r][this.c]=ch;\r
-               this.styleBuf[this.r][this.c]=(style)? style:0;\r
-               var last_r=this.r;\r
-               this._incCol();\r
-               if (this.r!=last_r) this.redraw(last_r);\r
-       }\r
-       this.redraw(this.r)\r
-}\r
-\r
-Terminal.prototype.write=function(text,usemore) {\r
-       // write to scroll buffer with markup\r
-       // new line = '%n' prepare any strings or arrys first\r
-       if (typeof text != 'object') {\r
-               if (typeof text!='string') text=''+text;\r
-               if (text.indexOf('\n')>=0) {\r
-                       var ta=text.split('\n');\r
-                       text=ta.join('%n');\r
-               }\r
-       }\r
-       else {\r
-               if (text.join) text=text.join('%n')\r
-               else text=''+text;\r
-       }\r
-       this._sbInit(usemore);\r
-       var chunks=text.split('%');\r
-       var esc=(text.charAt(0)!='%');\r
-       var style=0;\r
-       for (var i=0; i<chunks.length; i++) {\r
-               if (esc) {\r
-                       if (chunks[i].length>0) this._sbType(chunks[i],style)\r
-                       else if (i>0) this._sbType('%', style);\r
-                       esc=false;\r
-               }\r
-               else {\r
-                       var func=chunks[i].charAt(0);\r
-                       if ((chunks[i].length==0) && (i>0)) {\r
-                               this._sbType("%",style);\r
-                               esc=true;\r
-                       }\r
-                       else if (func=='n') {\r
-                               this._sbNewLine();\r
-                               if (chunks[i].length>1) this._sbType(chunks[i].substring(1),style);\r
-                       }\r
-                       else if (func=='+') {\r
-                               var opt=chunks[i].charAt(1);\r
-                               opt=opt.toLowerCase();\r
-                               if (opt=='p') style=0\r
-                               else if (opt=='r') style|=1\r
-                               else if (opt=='u') style|=2\r
-                               else if (opt=='i') style|=4\r
-                               else if (opt=='s') style|=8;\r
-                               if (chunks[i].length>2) this._sbType(chunks[i].substring(2),style);\r
-                       }\r
-                       else if (func=='-') {\r
-                               var opt=chunks[i].charAt(1);\r
-                               opt=opt.toLowerCase();\r
-                               if (opt=='p') style|=0\r
-                               else if (opt=='r') style&=~1\r
-                               else if (opt=='u') style&=~2\r
-                               else if (opt=='i') style&=~4\r
-                               else if (opt=='s') style&=~8;\r
-                               if (chunks[i].length>2) this._sbType(chunks[i].substring(2),style);\r
-                       }\r
-                       else if ((chunks[i].length>1) && (chunks[i].charAt(0)=='C') && (chunks[i].charAt(1)=='S')) {\r
-                               this.clear();\r
-                               this._sbInit();\r
-                               if (chunks[i].length>2) this._sbType(chunks[i].substring(2),style);\r
-                       }\r
-                       else {\r
-                               if (chunks[i].length>0) this._sbType(chunks[i],style);\r
-                       }\r
-               }\r
-       }\r
-       this._sbOut();\r
-}\r
-\r
-Terminal.prototype._sbType=function(text,style) {\r
-       // type to scroll buffer\r
-       var sb=this.scrollBuf;\r
-       for (var i=0; i<text.length; i++) {\r
-               var ch=text.charCodeAt(i);\r
-               if (!this.isPrintable(ch)) ch=94;\r
-               sb.lines[sb.r][sb.c]=ch;\r
-               sb.styles[sb.r][sb.c]=(style)? style:0;\r
-               sb.c++;\r
-               if (sb.c>=this.maxCols) this._sbNewLine();\r
-       }\r
-}\r
-\r
-Terminal.prototype._sbNewLine=function() {\r
-       var sb=this.scrollBuf;\r
-       sb.r++;\r
-       sb.c=0;\r
-       sb.lines[sb.r]=this.getRowArray(this.conf.cols,0);\r
-       sb.styles[sb.r]=this.getRowArray(this.conf.cols,0);\r
-}\r
-\r
-\r
-Terminal.prototype._sbInit=function(usemore) {\r
-       var sb=this.scrollBuf=new Object();\r
-       var sbl=sb.lines=new Array();\r
-       var sbs=sb.styles=new Array();\r
-       sb.more=usemore;\r
-       sb.line=0;\r
-       sb.status=0;\r
-       sb.r=0;\r
-       sb.c=this.c;\r
-       sbl[0]=this.getRowArray(this.conf.cols,0);\r
-       sbs[0]=this.getRowArray(this.conf.cols,0);\r
-       for (var i=0; i<this.c; i++) {\r
-               sbl[0][i]=this.charBuf[this.r][i];\r
-               sbs[0][i]=this.styleBuf[this.r][i];\r
-       }\r
-}\r
-\r
-Terminal.prototype._sbOut=function() {\r
-       var sb=this.scrollBuf;\r
-       var sbl=sb.lines;\r
-       var sbs=sb.styles;\r
-       var tcb=this.charBuf;\r
-       var tsb=this.styleBuf;\r
-       var ml=this.maxLines;\r
-       var buflen=sbl.length;\r
-       if (sb.more) {\r
-               if (sb.status) {\r
-                       if (this.inputChar==TermGlobals.lcMoreKeyAbort) {\r
-                               this.r=ml-1;\r
-                               this.c=0;\r
-                               tcb[this.r]=this.getRowArray(this.maxLines,0);\r
-                               tsb[this.r]=this.getRowArray(this.maxLines,0);\r
-                               this.redraw(this.r);\r
-                               this.handler=sb.handler;\r
-                               this.charMode=false;\r
-                               this.inputChar=0;\r
-                               this.scrollBuf=null;\r
-                               this.prompt();\r
-                               return;\r
-                       }\r
-                       else if (this.inputChar==TermGlobals.lcMoreKeyContinue) {\r
-                               this.clear();\r
-                       }\r
-                       else {\r
-                               return;\r
-                       }\r
-               }\r
-               else {\r
-                       if (this.r>=ml-1) this.clear();\r
-               }\r
-       }\r
-       if (this.r+buflen-sb.line<=ml) {\r
-               for (var i=sb.line; i<buflen; i++) {\r
-                       var r=this.r+i-sb.line;\r
-                       tcb[r]=sbl[i];\r
-                       tsb[r]=sbs[i];\r
-                       this.redraw(r);\r
-               }\r
-               this.r+=sb.r-sb.line;\r
-               this.c=sb.c;\r
-               if (sb.more) {\r
-                       if (sb.status) this.handler=sb.handler;\r
-                       this.charMode=false;\r
-                       this.inputChar=0;\r
-                       this.scrollBuf=null;\r
-                       this.prompt();\r
-                       return;\r
-               }\r
-       }\r
-       else if (sb.more) {\r
-               ml--;\r
-               if (sb.status==0) {\r
-                       sb.handler=this.handler;\r
-                       this.handler=this._sbOut;\r
-                       this.charMode=true;\r
-                       sb.status=1;\r
-               }\r
-               if (this.r) {\r
-                       var ofs=ml-this.r;\r
-                       for (var i=sb.line; i<ofs; i++) {\r
-                               var r=this.r+i-sb.line;\r
-                               tcb[r]=sbl[i];\r
-                               tsb[r]=sbs[i];\r
-                               this.redraw(r);\r
-                       }\r
-               }\r
-               else {\r
-                       var ofs=sb.line+ml;\r
-                       for (var i=sb.line; i<ofs; i++) {\r
-                               var r=this.r+i-sb.line;\r
-                               tcb[r]=sbl[i];\r
-                               tsb[r]=sbs[i];\r
-                               this.redraw(r);\r
-                       }\r
-               }\r
-               sb.line=ofs;\r
-               this.r=ml;\r
-               this.c=0;\r
-               this.type(TermGlobals.lcMorePrompt1, TermGlobals.lcMorePromtp1Style);\r
-               this.type(TermGlobals.lcMorePrompt2, TermGlobals.lcMorePrompt2Style);\r
-               this.lock=false;\r
-               return;\r
-       }\r
-       else if (buflen>=ml) {\r
-               var ofs=buflen-ml;\r
-               for (var i=0; i<ml; i++) {\r
-                       var r=ofs+i;\r
-                       tcb[i]=sbl[r];\r
-                       tsb[i]=sbs[r];\r
-                       this.redraw(i);\r
-               }\r
-               this.r=ml-1;\r
-               this.c=sb.c;\r
-       }\r
-       else {\r
-               var dr=ml-buflen;\r
-               var ofs=this.r-dr;\r
-               for (var i=0; i<dr; i++) {\r
-                       var r=ofs+i;\r
-                       for (var c=0; c<this.maxCols; c++) {\r
-                               tcb[i][c]=tcb[r][c];\r
-                               tsb[i][c]=tsb[r][c];\r
-                       }\r
-                       this.redraw(i);\r
-               }\r
-               for (var i=0; i<buflen; i++) {\r
-                       var r=dr+i;\r
-                       tcb[r]=sbl[i];\r
-                       tsb[r]=sbs[i];\r
-                       this.redraw(r);\r
-               }\r
-               this.r=ml-1;\r
-               this.c=sb.c;\r
-       }\r
-       this.scrollBuf=null;\r
-}\r
-\r
-// basic console output\r
-\r
-Terminal.prototype.typeAt=function(r,c,text,style) {\r
-       var tr1=this.r;\r
-       var tc1=this.c;\r
-       this.cursorSet(r,c);\r
-       for (var i=0; i<text.length; i++) {\r
-               var ch=text.charCodeAt(i);\r
-               if (!this.isPrintable(ch)) ch=94;\r
-               this.charBuf[this.r][this.c]=ch;\r
-               this.styleBuf[this.r][this.c]=(style)? style:0;\r
-               var last_r=this.r;\r
-               this._incCol();\r
-               if (this.r!=last_r) this.redraw(last_r);\r
-       }\r
-       this.redraw(this.r);\r
-       this.r=tr1;\r
-       this.c=tc1;\r
-}\r
-\r
-Terminal.prototype.statusLine = function(text,style,offset) {\r
-       var ch,r;\r
-       style=((style) && (!isNaN(style)))? parseInt(style)&15:0;\r
-       if ((offset) && (offset>0)) r=this.conf.rows-offset\r
-       else r=this.conf.rows-1;\r
-       for (var i=0; i<this.conf.cols; i++) {\r
-               if (i<text.length) {\r
-                       ch=text.charCodeAt(i);\r
-                       if (!this.isPrintable(ch)) ch = 94;\r
-               }\r
-               else ch=0;\r
-               this.charBuf[r][i]=ch;\r
-               this.styleBuf[r][i]=style;\r
-       }\r
-       this.redraw(r);\r
-}\r
-\r
-Terminal.prototype.printRowFromString = function(r,text,style) {\r
-       var ch;\r
-       style=((style) && (!isNaN(style)))? parseInt(style)&15:0;\r
-       if ((r>=0) && (r<this.maxLines)) {\r
-               if (typeof text != 'string') text=''+text;\r
-               for (var i=0; i<this.conf.cols; i++) {\r
-                       if (i<text.length) {\r
-                               ch=text.charCodeAt(i);\r
-                               if (!this.isPrintable(ch)) ch = 94;\r
-                       }\r
-                       else ch=0;\r
-                       this.charBuf[r][i]=ch;\r
-                       this.styleBuf[r][i]=style;\r
-               }\r
-               this.redraw(r);\r
-       }\r
-}\r
-\r
-Terminal.prototype.setChar=function(ch,r,c,style) {\r
-       this.charBuf[r][c]=ch;\r
-       this.styleBuf[this.r][this.c]=(style)? style:0;\r
-       this.redraw(r);\r
-}\r
-\r
-Terminal.prototype._charOut=function(ch, style) {\r
-       this.charBuf[this.r][this.c]=ch;\r
-       this.styleBuf[this.r][this.c]=(style)? style:0;\r
-       this.redraw(this.r);\r
-       this._incCol();\r
-}\r
-\r
-Terminal.prototype._incCol=function() {\r
-       this.c++;\r
-       if (this.c>=this.maxCols) {\r
-               this.c=0;\r
-               this._incRow();\r
-       }\r
-}\r
-\r
-Terminal.prototype._incRow=function() {\r
-       this.r++;\r
-       if (this.r>=this.maxLines) {\r
-               this._scrollLines(0,this.maxLines);\r
-               this.r=this.maxLines-1;\r
-       }\r
-}\r
-\r
-Terminal.prototype._scrollLines=function(start, end) {\r
-       window.status='Scrolling lines ...';\r
-       start++;\r
-       for (var ri=start; ri<end; ri++) {\r
-               var rt=ri-1;\r
-               this.charBuf[rt]=this.charBuf[ri];\r
-               this.styleBuf[rt]=this.styleBuf[ri];\r
-       }\r
-       // clear last line\r
-       var rt=end-1;\r
-       this.charBuf[rt]=this.getRowArray(this.conf.cols,0);\r
-       this.styleBuf[rt]=this.getRowArray(this.conf.cols,0);\r
-       this.redraw(rt);\r
-       for (var r=end-1; r>=start; r--) this.redraw(r-1);\r
-       window.status='';\r
-}\r
-\r
-Terminal.prototype.newLine=function() {\r
-       this.c=0;\r
-       this._incRow();\r
-}\r
-\r
-Terminal.prototype.clear=function() {\r
-       window.status='Clearing display ...';\r
-       this.cursorOff();\r
-       this.insert=false;\r
-       for (var ri=0; ri<this.maxLines; ri++) {\r
-               this.charBuf[ri]=this.getRowArray(this.conf.cols,0);\r
-               this.styleBuf[ri]=this.getRowArray(this.conf.cols,0);\r
-               this.redraw(ri);\r
-       }\r
-       this.r=0;\r
-       this.c=0;\r
-       window.status='';\r
-}\r
-\r
-Terminal.prototype.reset=function() {\r
-       if (this.lock) return;\r
-       this.lock=true;\r
-       this.rawMode=false;\r
-       this.charMode=false;\r
-       this.maxLines=this.conf.rows;\r
-       this.maxCols=this.conf.cols;\r
-       this.lastLine='';\r
-       this.lineBuffer='';\r
-       this.inputChar=0;\r
-       this.clear();\r
-}\r
-\r
-Terminal.prototype.cursorSet=function(r,c) {\r
-       var crsron=this.cursoractive;\r
-       if (crsron) this.cursorOff();\r
-       this.r=r%this.maxLines;\r
-       this.c=c%this.maxCols;\r
-       this._cursorReset(crsron);\r
-}\r
-\r
-Terminal.prototype._cursorReset=function(crsron) {\r
-       if (crsron) this.cursorOn()\r
-       else {\r
-               this.blinkBuffer=this.styleBuf[this.r][this.c];\r
-       }\r
-}\r
-\r
-Terminal.prototype.cursorOn=function() {\r
-       if (this.blinkTimer) clearTimeout(this.blinkTimer);\r
-       this.blinkBuffer=this.styleBuf[this.r][this.c];\r
-       this._cursorBlink();\r
-       this.cursoractive=true;\r
-}\r
-\r
-Terminal.prototype.cursorOff=function() {\r
-       if (this.blinkTimer) clearTimeout(this.blinkTimer);\r
-       if (this.cursoractive) {\r
-               this.styleBuf[this.r][this.c]=this.blinkBuffer;\r
-               this.redraw(this.r);\r
-               this.cursoractive=false;\r
-       }\r
-}\r
-\r
-Terminal.prototype._cursorBlink=function() {\r
-       if (this.blinkTimer) clearTimeout(this.blinkTimer);\r
-       if (this == TermGlobals.activeTerm) {\r
-               if (this.crsrBlockMode) {\r
-                       this.styleBuf[this.r][this.c]=(this.styleBuf[this.r][this.c]&1)?\r
-                               this.styleBuf[this.r][this.c]&254:this.styleBuf[this.r][this.c]|1;\r
-               }\r
-               else {\r
-                       this.styleBuf[this.r][this.c]=(this.styleBuf[this.r][this.c]&2)?\r
-                               this.styleBuf[this.r][this.c]&253:this.styleBuf[this.r][this.c]|2;\r
-               }\r
-               this.redraw(this.r);\r
-       }\r
-       if (this.crsrBlinkMode) this.blinkTimer=setTimeout('TermGlobals.activeTerm._cursorBlink()', this.blinkDelay);\r
-}\r
-\r
-Terminal.prototype.cursorLeft=function() {\r
-       var crsron=this.cursoractive;\r
-       if (crsron) this.cursorOff();\r
-       var r=this.r;\r
-       var c=this.c;\r
-       if (c>0) c--\r
-       else if (r>0) {\r
-               c=this.maxCols-1;\r
-               r--;\r
-       }\r
-       if (this.isPrintable(this.charBuf[r][c])) {\r
-               this.r=r;\r
-               this.c=c;\r
-       }\r
-       this.insert=true;\r
-       this._cursorReset(crsron);\r
-}\r
-\r
-Terminal.prototype.cursorRight=function() {\r
-       var crsron=this.cursoractive;\r
-       if (crsron) this.cursorOff();\r
-       var r=this.r;\r
-       var c=this.c;\r
-       if (c<this.maxCols-1) c++\r
-       else if (r<this.maxLines-1) {\r
-               c=0;\r
-               r++;\r
-       }\r
-       if (!this.isPrintable(this.charBuf[r][c])) {\r
-               this.insert=false;\r
-       }\r
-       if (this.isPrintable(this.charBuf[this.r][this.c])) {\r
-               this.r=r;\r
-               this.c=c;\r
-       }\r
-       this._cursorReset(crsron);\r
-}\r
-\r
-Terminal.prototype.backspace=function() {\r
-       var crsron=this.cursoractive;\r
-       if (crsron) this.cursorOff();\r
-       var r=this.r;\r
-       var c=this.c;\r
-       if (c>0) c--\r
-       else if (r>0) {\r
-               c=this.maxCols-1;\r
-               r--;\r
-       };\r
-       if (this.isPrintable(this.charBuf[r][c])) {\r
-               this._scrollLeft(r, c);\r
-               this.r=r;\r
-               this.c=c;\r
-       };      \r
-       this._cursorReset(crsron);\r
-}\r
-\r
-Terminal.prototype.fwdDelete=function() {\r
-       var crsron=this.cursoractive;\r
-       if (crsron) this.cursorOff();\r
-       if (this.isPrintable(this.charBuf[this.r][this.c])) {\r
-               this._scrollLeft(this.r,this.c);\r
-               if (!this.isPrintable(this.charBuf[this.r][this.c])) this.insert=false;\r
-       }\r
-       this._cursorReset(crsron);\r
-}\r
-\r
-Terminal.prototype.prompt=function() {\r
-       this.lock=true;\r
-       if (this.c>0) this.newLine();\r
-       this.type(this.ps);\r
-       this._charOut(1);\r
-       this.lock=false;\r
-       this.cursorOn();\r
-}\r
-\r
-Terminal.prototype._scrollLeft=function(r,c) {\r
-       var rows=new Array();\r
-       rows[0]=r;\r
-       while (this.isPrintable(this.charBuf[r][c])) {\r
-               var ri=r;\r
-               var ci=c+1;\r
-               if (ci==this.maxCols) {\r
-                       if (ri<this.maxLines-1) {\r
-                               ci=0;\r
-                               ri++;\r
-                               rows[rows.length]=ri;\r
-                       }\r
-                       else {\r
-                               break;\r
-                       }\r
-               }\r
-               this.charBuf[r][c]=this.charBuf[ri][ci];\r
-               this.styleBuf[r][c]=this.styleBuf[ri][ci];\r
-               c=ci;\r
-               r=ri;\r
-       }\r
-       if (this.charBuf[r][c]!=0) this.charBuf[r][c]=0;\r
-       for (var i=0; i<rows.length; i++) this.redraw(rows[i]);\r
-}\r
-\r
-Terminal.prototype._scrollRight=function(r,c) {\r
-       var rows=new Array();\r
-       var end=this._getLineEnd(r,c);\r
-       var ri=end[0];\r
-       var ci=end[1];\r
-       if ((ci==this.maxCols-1) && (ri==this.maxLines-1)) {\r
-               if (r==0) return;\r
-               this._scrollLines(0,this.maxLines);\r
-               this.r--;\r
-               r--;\r
-               ri--;\r
-       }\r
-       rows[r]=1;\r
-       while (this.isPrintable(this.charBuf[ri][ci])) {\r
-               var rt=ri;\r
-               var ct=ci+1;\r
-               if (ct==this.maxCols) {\r
-                       ct=0;\r
-                       rt++;\r
-                       rows[rt]=1;\r
-               }\r
-               this.charBuf[rt][ct]=this.charBuf[ri][ci];\r
-               this.styleBuf[rt][ct]=this.styleBuf[ri][ci];\r
-               if ((ri==r) && (ci==c)) break;\r
-               ci--;\r
-               if (ci<0) {\r
-                       ci=this.maxCols-1;\r
-                       ri--;\r
-                       rows[ri]=1;\r
-               }\r
-       }\r
-       for (var i=r; i<this.maxLines; i++) {\r
-               if (rows[i]) this.redraw(i);\r
-       }\r
-}\r
-\r
-Terminal.prototype._getLineEnd=function(r,c) {\r
-       if (!this.isPrintable(this.charBuf[r][c])) {\r
-               c--;\r
-               if (c<0) {\r
-                       if (r>0) {\r
-                               r--;\r
-                               c=this.maxCols-1;\r
-                       }\r
-                       else {\r
-                               c=0;\r
-                       }\r
-               }\r
-       }\r
-       if (this.isPrintable(this.charBuf[r][c])) {\r
-               while (true) {\r
-                       var ri=r;\r
-                       var ci=c+1;\r
-                       if (ci==this.maxCols) {\r
-                               if (ri<this.maxLines-1) {\r
-                                       ri++;\r
-                                       ci=0;\r
-                               }\r
-                               else {\r
-                                       break;\r
-                               }\r
-                       }\r
-                       if (!this.isPrintable(this.charBuf[ri][ci])) break;\r
-                       c=ci;\r
-                       r=ri;\r
-               }\r
-       }\r
-       return [r,c];\r
-}\r
-\r
-Terminal.prototype._getLineStart=function(r,c) {\r
-       // not used by now, just in case anyone needs this ...\r
-       var ci, ri;\r
-       if (!this.isPrintable(this.charBuf[r][c])) {\r
-               ci=c-1;\r
-               ri=r;\r
-               if (ci<0) {\r
-                       if (ri==0) return [0,0];\r
-                       ci=this.maxCols-1;\r
-                       ri--;\r
-               }\r
-               if (!this.isPrintable(this.charBuf[ri][ci])) return [r,c]\r
-               else {\r
-                       r=ri;\r
-                       c=ci;\r
-               }\r
-       }\r
-       while (true) {\r
-               var ri=r;\r
-               var ci=c-1;\r
-               if (ci<0) {\r
-                       if (ri==0) break;\r
-                       ci=this.maxCols-1;\r
-                       ri--;\r
-               }\r
-               if (!this.isPrintable(this.charBuf[ri][ci])) break;;\r
-               r=ri;\r
-               c=ci;\r
-       }\r
-       return [r,c];\r
-}\r
-\r
-Terminal.prototype._getLine=function() {\r
-       var end=this._getLineEnd(this.r,this.c);\r
-       var r=end[0];\r
-       var c=end[1];\r
-       var line=new Array();\r
-       while (this.isPrintable(this.charBuf[r][c])) {\r
-               line[line.length]=String.fromCharCode(this.charBuf[r][c]);\r
-               if (c>0) c--\r
-               else if (r>0) {\r
-                       c=this.maxCols-1;\r
-                       r--;\r
-               }\r
-               else break;\r
-       }\r
-       line.reverse();\r
-       return line.join('');\r
-}\r
-\r
-Terminal.prototype._clearLine=function() {\r
-       var end=this._getLineEnd(this.r,this.c);\r
-       var r=end[0];\r
-       var c=end[1];\r
-       var line='';\r
-       while (this.isPrintable(this.charBuf[r][c])) {\r
-               this.charBuf[r][c]=0;\r
-               if (c>0) {\r
-                       c--;\r
-               }\r
-               else if (r>0) {\r
-                       this.redraw(r);\r
-                       c=this.maxCols-1;\r
-                       r--;\r
-               }\r
-               else break;\r
-       }\r
-       if (r!=end[0]) this.redraw(r);\r
-       c++;\r
-       this.cursorSet(r,c);\r
-       this.insert=false;\r
-}\r
-\r
-Terminal.prototype.isPrintable=function(ch, unicodePage1only) {\r
-       if ((unicodePage1only) && (ch>255)) {\r
-               return ((ch==termKey.EURO) && (this.printEuro))? true:false;\r
-       }\r
-       return (\r
-               ((ch>=32) && (ch!=termKey.DEL)) ||\r
-               ((this.printTab) && (ch==termKey.TAB))\r
-       );\r
-}\r
-\r
-// keyboard focus\r
-\r
-Terminal.prototype.focus=function() {\r
-       TermGlobals.activeTerm=this;\r
-}\r
-\r
-// global store and functions\r
-\r
-var TermGlobals={\r
-       termToInitialze:null,\r
-       activeTerm:null,\r
-       kbdEnabled:false,\r
-       keylock:false,\r
-       lcMorePrompt1: ' -- MORE -- ',\r
-       lcMorePromtp1Style: 1,\r
-       lcMorePrompt2: ' (Type: space to continue, \'q\' to quit)',\r
-       lcMorePrompt2Style: 0,\r
-       lcMoreKeyAbort: 113,\r
-       lcMoreKeyContinue: 32\r
-};\r
-\r
-// keybard focus\r
-\r
-TermGlobals.setFocus=function(termref) {\r
-       TermGlobals.activeTerm=termref;\r
-}\r
-\r
-// text related\r
-\r
-TermGlobals.normalize=function(n,m) {\r
-       var s=''+n;\r
-       while (s.length<m) s='0'+s;\r
-       return s;\r
-}\r
-\r
-TermGlobals.fillLeft=function(t,n) {\r
-       if (typeof t != 'string') t=''+t;\r
-       while (t.length<n) t=' '+t;\r
-       return t;\r
-}\r
-\r
-TermGlobals.center=function(t,l) {\r
-       var s='';\r
-       for (var i=t.length; i<l; i+=2) s+=' ';\r
-       return s+t;\r
-}\r
-\r
-TermGlobals.stringReplace=function(s1,s2,t) {\r
-       var l1=s1.length;\r
-       var l2=s2.length;\r
-       var ofs=t.indexOf(s1);\r
-       while (ofs>=0) {\r
-               t=t.substring(0,ofs)+s2+t.substring(ofs+l1);\r
-               ofs=t.indexOf(s1,ofs+l2);\r
-       }\r
-       return t;\r
-}\r
-\r
-// keyboard\r
-\r
-var termKey= {\r
-       // special key codes\r
-       'NUL': 0x00,\r
-       'SOH': 0x01,\r
-       'STX': 0x02,\r
-       'ETX': 0x03,\r
-       'EOT': 0x04,\r
-       'ENQ': 0x05,\r
-       'ACK': 0x06,\r
-       'BEL': 0x07,\r
-       'BS': 0x08,\r
-       'HT': 0x09,\r
-       'TAB': 0x09,\r
-       'LF': 0x0A,\r
-       'VT': 0x0B,\r
-       'FF': 0x0C,\r
-       'CR': 0x0D,\r
-       'SO': 0x0E,\r
-       'SI': 0x0F,\r
-       'DLE': 0x10,\r
-       'DC1': 0x11,\r
-       'DC2': 0x12,\r
-       'DC3': 0x13,\r
-       'DC4': 0x14,\r
-       'NAK': 0x15,\r
-       'SYN': 0x16,\r
-       'ETB': 0x17,\r
-       'CAN': 0x18,\r
-       'EM': 0x19,\r
-       'SUB': 0x1A,\r
-       'ESC': 0x1B,\r
-       'IS4': 0x1C,\r
-       'IS3': 0x1D,\r
-       'IS2': 0x1E,\r
-       'IS1': 0x1F,\r
-       'DEL': 0x7F,\r
-       // other specials\r
-       'EURO': 0x20AC,\r
-       // cursor mapping\r
-       'LEFT': 0x1C,\r
-       'RIGHT': 0x1D,\r
-       'UP': 0x1E,\r
-       'DOWN': 0x1F\r
-};\r
-\r
-var termDomKeyRef = {\r
-       DOM_VK_LEFT: termKey.LEFT,\r
-       DOM_VK_RIGHT: termKey.RIGHT,\r
-       DOM_VK_UP: termKey.UP,\r
-       DOM_VK_DOWN: termKey.DOWN,\r
-       DOM_VK_BACK_SPACE: termKey.BS,\r
-       DOM_VK_RETURN: termKey.CR,\r
-       DOM_VK_ENTER: termKey.CR,\r
-       DOM_VK_ESCAPE: termKey.ESC,\r
-       DOM_VK_DELETE: termKey.DEL,\r
-       DOM_VK_TAB: termKey.TAB\r
-};\r
-\r
-TermGlobals.enableKeyboard=function(term) {\r
-       if (!this.kbdEnabled) {\r
-               if (document.addEventListener) document.addEventListener("keypress", this.keyHandler, true)\r
-               else {\r
-                       if ((self.Event) && (self.Event.KEYPRESS)) document.captureEvents(Event.KEYPRESS);\r
-                       document.onkeypress = this.keyHandler;\r
-               }\r
-               window.document.onkeydown=this.keyFix;\r
-               this.kbdEnabled=true;\r
-       }\r
-       this.activeTerm=term;\r
-}\r
-\r
-TermGlobals.keyFix=function(e) {\r
-       var term=TermGlobals.activeTerm;\r
-       if ((TermGlobals.keylock) || (term.lock)) return true;\r
-       if (window.event) {\r
-               var ch=window.event.keyCode;\r
-               if  (!e) e=window.event;\r
-               if (e.DOM_VK_UP) {\r
-                       for (var i in termDomKeyRef) {\r
-                               if ((e[i]) && (ch == e[i])) {\r
-                                       this.keyHandler({which:termDomKeyRef[i],_remapped:true});\r
-                                       if (e.preventDefault) e.preventDefault();\r
-                                       if (e.stopPropagation) e.stopPropagation();\r
-                                       e.cancleBubble=true;\r
-                                       return false;\r
-                               }\r
-                       }\r
-                       e.cancleBubble=false;\r
-                       return true;\r
-               }\r
-               else {\r
-                       // no DOM support\r
-                       if ((ch==8) && (!term.isSafari)) TermGlobals.keyHandler({which:termKey.BS,_remapped:true})\r
-                       else if (ch==9) TermGlobals.keyHandler({which:termKey.TAB,_remapped:true})\r
-                       else if (ch==37) TermGlobals.keyHandler({which:termKey.LEFT,_remapped:true})\r
-                       else if (ch==39) TermGlobals.keyHandler({which:termKey.RIGHT,_remapped:true})\r
-                       else if (ch==38) TermGlobals.keyHandler({which:termKey.UP,_remapped:true})\r
-                       else if (ch==40) TermGlobals.keyHandler({which:termKey.DOWN,_remapped:true})\r
-                       else if (ch==127) TermGlobals.keyHandler({which:termKey.DEL,_remapped:true})\r
-                       else if ((ch>=57373) && (ch<=57376)) {\r
-                               if (ch==57373) TermGlobals.keyHandler({which:termKey.UP,_remapped:true})\r
-                               else if (ch==57374) TermGlobals.keyHandler({which:termKey.DOWN,_remapped:true})\r
-                               else if (ch==57375) TermGlobals.keyHandler({which:termKey.LEFT,_remapped:true})\r
-                               else if (ch==57376) TermGlobals.keyHandler({which:termKey.RIGHT,_remapped:true});\r
-                       }\r
-                       else {\r
-                               e.cancleBubble=false;\r
-                               return true;\r
-                       }\r
-                       if (e.preventDefault) e.preventDefault();\r
-                       if (e.stopPropagation) e.stopPropagation();\r
-                       e.cancleBubble=true;\r
-                       return false;\r
-               }\r
-       }\r
-}\r
-\r
-TermGlobals.keyHandler=function(e) {\r
-       var term=TermGlobals.activeTerm;\r
-       if ((TermGlobals.keylock) || (term.lock)) return true;\r
-       if ((window.event) && (window.event.preventDefault)) window.event.preventDefault()\r
-       else if ((e) && (e.preventDefault)) e.preventDefault();\r
-       if ((window.event) && (window.event.stopPropagation)) window.event.stopPropagation()\r
-       else if ((e) && (e.stopPropagation)) e.stopPropagation();\r
-       var ch;\r
-       var ctrl=false;\r
-       var shft=false;\r
-       var remapped=false;\r
-       if (e) {\r
-               ch=e.which;\r
-               ctrl=(((e.ctrlKey) && (e.altKey)) || (e.modifiers==2));\r
-               shft=((e.shiftKey) || (e.modifiers==4));\r
-               if (e._remapped) {\r
-                       remapped=true;\r
-                       if (window.event) {\r
-                               //ctrl=((ctrl) || (window.event.ctrlKey));\r
-                               ctrl=((ctrl) || ((window.event.ctrlKey) && (!window.event.altKey)));\r
-                               shft=((shft) || (window.event.shiftKey));\r
-                       }\r
-               }\r
-       }\r
-       else if (window.event) {\r
-               ch=window.event.keyCode;\r
-               //ctrl=(window.event.ctrlKey);\r
-               ctrl=((window.event.ctrlKey) && (!window.event.altKey)); // allow alt gr == ctrl alts\r
-               shft=(window.event.shiftKey);\r
-       }\r
-       else {\r
-               return true;\r
-       }\r
-       if ((ch=='') && (remapped==false)) {\r
-               // map specials\r
-               if (e==null) e=window.event;\r
-               if ((e.charCode==0) && (e.keyCode)) {\r
-                       if (e.DOM_VK_UP) {\r
-                               for (var i in termDomKeyRef) {\r
-                                       if ((e[i]) && (e.keyCode == e[i])) {\r
-                                               ch=termDomKeyRef[i];\r
-                                               break;\r
-                                       }\r
-                               }\r
-                       }\r
-                       else {\r
-                               // NS4\r
-                               if (e.keyCode==28) ch=termKey.LEFT\r
-                               else if (e.keyCode==29) ch=termKey.RIGHT\r
-                               else if (e.keyCode==30) ch=termKey.UP\r
-                               else if (e.keyCode==31) ch=termKey.DOWN\r
-                               // Mozilla alike but no DOM support\r
-                               else if (e.keyCode==37) ch=termKey.LEFT\r
-                               else if (e.keyCode==39) ch=termKey.RIGHT\r
-                               else if (e.keyCode==38) ch=termKey.UP\r
-                               else if (e.keyCode==40) ch=termKey.DOWN\r
-                               // just to have the TAB mapping here too\r
-                               else if (e.keyCode==9) ch=termKey.TAB;\r
-                       }\r
-               }\r
-       }\r
-       // key actions\r
-       if (term.charMode) {\r
-               term.insert=false;\r
-               term.inputChar=ch;\r
-               term.lineBuffer='';\r
-               term.handler();\r
-               if ((ch<=32) && (window.event)) window.event.cancleBubble=true;\r
-               return false;\r
-       }\r
-       if (!ctrl) {\r
-               // special keys\r
-               if (ch==termKey.CR) {\r
-                       term.lock=true;\r
-                       term.cursorOff();\r
-                       term.insert=false;\r
-                       if (term.rawMode) {\r
-                               term.lineBuffer=term.lastLine;\r
-                       }\r
-                       else {\r
-                               term.lineBuffer=term._getLine();\r
-                               if (\r
-                                   (term.lineBuffer!='') && ((!term.historyUnique) ||\r
-                                   (term.history.length==0) ||\r
-                                   (term.lineBuffer!=term.history[term.history.length-1]))\r
-                                  ) {\r
-                                       term.history[term.history.length]=term.lineBuffer;\r
-                               }\r
-                               term.histPtr=term.history.length;\r
-                       }\r
-                       term.lastLine='';\r
-                       term.inputChar=0;\r
-                       term.handler();\r
-                       if (window.event) window.event.cancleBubble=true;\r
-                       return false;\r
-               }\r
-               else if (ch==termKey.ESC) {\r
-                       if (term.conf.closeOnESC) term.close();\r
-                       if (window.event) window.event.cancleBubble=true;\r
-                       return false;\r
-               }\r
-               if ((ch<32) && (term.rawMode)) {\r
-                       if (window.event) window.event.cancleBubble=true;\r
-                       return false;\r
-               }\r
-               else {\r
-                       if (ch==termKey.LEFT) {\r
-                               term.cursorLeft();\r
-                               if (window.event) window.event.cancleBubble=true;\r
-                               return false;\r
-                       }\r
-                       else if (ch==termKey.RIGHT) {\r
-                               term.cursorRight();\r
-                               if (window.event) window.event.cancleBubble=true;\r
-                               return false;\r
-                       }\r
-                       else if (ch==termKey.UP) {\r
-                               term.cursorOff();\r
-                               if (term.histPtr==term.history.length) term.lastLine=term._getLine();\r
-                               term._clearLine();\r
-                               if ((term.history.length) && (term.histPtr>=0)) {\r
-                                       if (term.histPtr>0) term.histPtr--;\r
-                                       term.type(term.history[term.histPtr]);\r
-                               }\r
-                               else if (term.lastLine) term.type(term.lastLine);\r
-                               term.cursorOn();\r
-                               if (window.event) window.event.cancleBubble=true;\r
-                               return false;\r
-                       }\r
-                       else if (ch==termKey.DOWN) {\r
-                               term.cursorOff();\r
-                               if (term.histPtr==term.history.length) term.lastLine=term._getLine();\r
-                               term._clearLine();\r
-                               if ((term.history.length) && (term.histPtr<=term.history.length)) {\r
-                                       if (term.histPtr<term.history.length) term.histPtr++;\r
-                                       if (term.histPtr<term.history.length) term.type(term.history[term.histPtr])\r
-                                       else if (term.lastLine) term.type(term.lastLine);\r
-                               }\r
-                               else if (term.lastLine) term.type(term.lastLine);\r
-                               term.cursorOn();\r
-                               if (window.event) window.event.cancleBubble=true;\r
-                               return false;\r
-                       }\r
-                       else if (ch==termKey.BS) {\r
-                               term.backspace();\r
-                               if (window.event) window.event.cancleBubble=true;\r
-                               return false;\r
-                       }\r
-                       else if (ch==termKey.DEL) {\r
-                               if (term.DELisBS) term.backspace()\r
-                               else term.fwdDelete();\r
-                               if (window.event) window.event.cancleBubble=true;\r
-                               return false;\r
-                       }\r
-               }\r
-       }\r
-       if (term.rawMode) {\r
-               if (term.isPrintable(ch)) {\r
-                       term.lastLine+=String.fromCharCode(ch);\r
-               }\r
-               if ((ch==32) && (window.event)) window.event.cancleBubble=true\r
-               else if ((window.opera) && (window.event)) window.event.cancleBubble=true;\r
-               return false;\r
-       }\r
-       else {\r
-               if ((term.conf.catchCtrlH) && ((ch==termKey.BS) || ((ctrl) && (ch==72)))) {\r
-                       // catch ^H\r
-                       term.backspace();\r
-                       if (window.event) window.event.cancleBubble=true;\r
-                       return false;\r
-               }\r
-               else if ((term.ctrlHandler) && ((ch<32) || ((ctrl) && (term.isPrintable(ch,true))))) {\r
-                       if (((ch>=65) && (ch<=96)) || (ch==63)) {\r
-                               // remap canonical\r
-                               if (ch==63) ch=31\r
-                               else ch-=64;\r
-                       }\r
-                       term.inputChar=ch;\r
-                       term.ctrlHandler();\r
-                       if (window.event) window.event.cancleBubble=true;\r
-                       return false;\r
-               }\r
-               else if ((ctrl) || (!term.isPrintable(ch,true))) {\r
-                       if (window.event) window.event.cancleBubble=true;\r
-                       return false;\r
-               }\r
-               else if (term.isPrintable(ch,true)) {\r
-                       if (term.blinkTimer) clearTimeout(term.blinkTimer);\r
-                       if (term.insert) {\r
-                               term.cursorOff();\r
-                               term._scrollRight(term.r,term.c);\r
-                       }\r
-                       term._charOut(ch);\r
-                       term.cursorOn();\r
-                       if ((ch==32) && (window.event)) window.event.cancleBubble=true\r
-                       else if ((window.opera) && (window.event)) window.event.cancleBubble=true;\r
-                       return false;\r
-               }\r
-       }\r
-       return true;\r
-}\r
-\r
-// term gui\r
-\r
-TermGlobals.hasSubDivs=false;\r
-TermGlobals.hasLayers=false;\r
-TermGlobals.termStringStart='';\r
-TermGlobals.termStringEnd='';\r
-\r
-TermGlobals.termSpecials=new Array();\r
-TermGlobals.termSpecials[0]='&nbsp;';\r
-TermGlobals.termSpecials[1]='&nbsp;';\r
-TermGlobals.termSpecials[9]='&nbsp;';\r
-TermGlobals.termSpecials[32]='&nbsp;';\r
-TermGlobals.termSpecials[34]='&quot;';\r
-TermGlobals.termSpecials[38]='&amp;';\r
-TermGlobals.termSpecials[60]='&lt;';\r
-TermGlobals.termSpecials[62]='&gt;';\r
-TermGlobals.termSpecials[127]='&loz;';\r
-TermGlobals.termSpecials[0x20AC]='&euro;';\r
-\r
-TermGlobals.termStyles=new Array(1,2,4,8);\r
-TermGlobals.termStyleOpen=new Array();\r
-TermGlobals.termStyleClose=new Array();\r
-TermGlobals.termStyleOpen[1]='<span class="termReverse">';\r
-TermGlobals.termStyleClose[1]='<\/span>';\r
-TermGlobals.termStyleOpen[2]='<u>';\r
-TermGlobals.termStyleClose[2]='<\/u>';\r
-TermGlobals.termStyleOpen[4]='<i>';\r
-TermGlobals.termStyleClose[4]='<\/i>';\r
-TermGlobals.termStyleOpen[8]='<strike>';\r
-TermGlobals.termStyleClose[8]='<\/strike>';\r
-\r
-Terminal.prototype._makeTerm=function(rebuild) {\r
-       window.status='Building terminal ...';\r
-       TermGlobals.hasLayers=(document.layers)? true:false;\r
-       TermGlobals.hasSubDivs=(navigator.userAgent.indexOf('Gecko')<0);\r
-       var divPrefix=this.termDiv+'_r';\r
-       var s='';\r
-       s+='<table border="0" cellspacing="0" cellpadding="'+this.conf.frameWidth+'">\n';\r
-       s+='<tr><td bgcolor="'+this.conf.frameColor+'"><table border="0" cellspacing="0" cellpadding="2"><tr><td  bgcolor="'+this.conf.bgColor+'"><table border="0" cellspacing="0" cellpadding="0">\n';\r
-       var rstr='';\r
-       for (var c=0; c<this.conf.cols; c++) rstr+='&nbsp;';\r
-       for (var r=0; r<this.conf.rows; r++) {\r
-               var termid=((TermGlobals.hasLayers) || (TermGlobals.hasSubDivs))? '' : ' id="'+divPrefix+r+'"';\r
-               s+='<tr><td nowrap height="'+this.conf.rowHeight+'"'+termid+' class="'+this.conf.fontClass+'">'+rstr+'<\/td><\/tr>\n';\r
-       }\r
-       s+='<\/table><\/td><\/tr>\n';\r
-       s+='<\/table><\/td><\/tr>\n';\r
-       s+='<\/table>\n';\r
-       var termOffset=2+this.conf.frameWidth;\r
-       if (TermGlobals.hasLayers) {\r
-               for (var r=0; r<this.conf.rows; r++) {\r
-                       s+='<layer name="'+divPrefix+r+'" top="'+(termOffset+r*this.conf.rowHeight)+'" left="'+termOffset+'" class="'+this.conf.fontClass+'"><\/layer>\n';\r
-               }\r
-               this.ns4ParentDoc=document.layers[this.termDiv].document;\r
-               TermGlobals.termStringStart='<table border="0" cellspacing="0" cellpadding="0"><tr><td nowrap height="'+this.conf.rowHeight+'" class="'+this.conf.fontClass+'">';\r
-               TermGlobals.termStringEnd='<\/td><\/tr><\/table>';\r
-       }\r
-       else if (TermGlobals.hasSubDivs) {\r
-               for (var r=0; r<this.conf.rows; r++) {\r
-                       s+='<div id="'+divPrefix+r+'" style="position:absolute; top:'+(termOffset+r*this.conf.rowHeight)+'px; left: '+termOffset+'px;" class="'+this.conf.fontClass+'"><\/div>\n';\r
-               }\r
-               TermGlobals.termStringStart='<table border="0" cellspacing="0" cellpadding="0"><tr><td nowrap height="'+this.conf.rowHeight+'" class="'+this.conf.fontClass+'">';\r
-               TermGlobals.termStringEnd='<\/td><\/tr><\/table>';\r
-       }\r
-       TermGlobals.writeElement(this.termDiv,s);\r
-       if (!rebuild) {\r
-               TermGlobals.setElementXY(this.termDiv,this.conf.x,this.conf.y);\r
-               TermGlobals.setVisible(this.termDiv,1);\r
-       }\r
-       window.status='';\r
-}\r
-\r
-Terminal.prototype.rebuild=function() {\r
-       // check for bounds and array lengths\r
-       var rl=this.conf.rows;\r
-       var cl=this.conf.cols;\r
-       for (var r=0; r<rl; r++) {\r
-               var cbr=this.charBuf[r];\r
-               if (!cbr) {\r
-                       this.charBuf[r]=this.getRowArray(cl,0);\r
-                       this.styleBuf[r]=this.getRowArray(cl,0);\r
-               }\r
-               else if (cbr.length<cl) {\r
-                       for (var c=cbr.length; c<cl; c++) {\r
-                               this.charBuf[r][c]=0;\r
-                               this.styleBuf[r][c]=0;\r
-                       }\r
-               }\r
-       }\r
-       var resetcrsr=false;\r
-       if (this.r>=rl) {\r
-               r=rl-1;\r
-               resetcrsr=true;\r
-       }\r
-       if (this.c>=cl) {\r
-               c=cl-1;\r
-               resetcrsr=true;\r
-       }\r
-       if ((resetcrsr) && (this.cursoractive)) this.cursorOn();\r
-       // and actually rebuild\r
-       this._makeTerm(true);\r
-       for (var r=0; r<rl; r++) {\r
-               this.redraw(r);\r
-       }\r
-}\r
-\r
-Terminal.prototype.moveTo=function(x,y) {\r
-       TermGlobals.setElementXY(this.termDiv,x,y);\r
-}\r
-\r
-Terminal.prototype.resizeTo=function(x,y) {\r
-       if (this.termDivReady()) {\r
-               x=parseInt(x,10);\r
-               y=parseInt(y,10);\r
-               if ((isNaN(x)) || (isNaN(y)) || (x<4) || (y<2)) return false;\r
-               this.maxCols=this.conf.cols=x;\r
-               this.maxLines=this.conf.rows=y;\r
-               this._makeTerm();\r
-               this.clear();\r
-               return true;\r
-       }\r
-       else return false;\r
-}\r
-\r
-Terminal.prototype.redraw=function(r) {\r
-       var s=TermGlobals.termStringStart;\r
-       var curStyle=0;\r
-       var tstls=TermGlobals.termStyles;\r
-       var tscls=TermGlobals.termStyleClose;\r
-       var tsopn=TermGlobals.termStyleOpen;\r
-       var tspcl=TermGlobals.termSpecials;\r
-       var t_cb=this.charBuf;\r
-       var t_sb=this.styleBuf;\r
-       for (var i=0; i<this.conf.cols; i++) {\r
-               var c=t_cb[r][i];\r
-               var cs=t_sb[r][i];\r
-               if (cs!=curStyle) {\r
-                       if (curStyle) {\r
-                               for (var k=tstls.length-1; k>=0; k--) {\r
-                                       var st=tstls[k];\r
-                                       if (curStyle&st) s+=tscls[st];\r
-                               }\r
-                       }\r
-                       curStyle=cs;\r
-                       for (var k=0; k<tstls.length; k++) {\r
-                               var st=tstls[k];\r
-                               if (curStyle&st) s+=tsopn[st];\r
-                       }\r
-               }\r
-               s+= (tspcl[c])? tspcl[c] : String.fromCharCode(c);\r
-       }\r
-       if (curStyle>0) {\r
-               for (var k=tstls.length-1; k>=0; k--) {\r
-                       var st=tstls[k];\r
-                       if (curStyle&st) s+=tscls[st];\r
-               }\r
-       }\r
-       s+=TermGlobals.termStringEnd;\r
-       TermGlobals.writeElement(this.termDiv+'_r'+r,s,this.ns4ParentDoc);\r
-}\r
-\r
-Terminal.prototype.guiReady=function() {\r
-       ready=true;\r
-       if (TermGlobals.guiElementsReady(this.termDiv, self.document)) {\r
-               for (var r=0; r<this.conf.rows; r++) {\r
-                       if (TermGlobals.guiElementsReady(this.termDiv+'_r'+r,this.ns4ParentDoc)==false) {\r
-                               ready=false;\r
-                               break;\r
-                       }\r
-               }\r
-       }\r
-       else ready=false;\r
-       return ready;\r
-}\r
-\r
-Terminal.prototype.termDivReady=function() {\r
-       if (document.layers) {\r
-               return (document.layers[this.termDiv])? true:false;\r
-       }\r
-       else if (document.getElementById) {\r
-               return (document.getElementById(this.termDiv))? true:false;\r
-       }\r
-       else if (document.all) {\r
-               return (document.all[this.termDiv])? true:false;\r
-       }\r
-       else {\r
-               return false;\r
-       }\r
-}\r
-\r
-Terminal.prototype.getDimensions=function() {\r
-       var w=0;\r
-       var h=0;\r
-       var d=this.termDiv;\r
-       if (document.layers) {\r
-               if (document.layers[d]) {\r
-                       w=document.layers[d].clip.right;\r
-                       h=document.layers[d].clip.bottom;\r
-               }\r
-       }\r
-       else if (document.getElementById) {\r
-               var obj=document.getElementById(d);\r
-               if ((obj) && (obj.firstChild)) {\r
-                       w=parseInt(obj.firstChild.offsetWidth,10);\r
-                       h=parseInt(obj.firstChild.offsetHeight,10);\r
-        }\r
-               else if ((obj) && (obj.children) && (obj.children[0])) {\r
-                       w=parseInt(obj.children[0].offsetWidth,10);\r
-                       h=parseInt(obj.children[0].offsetHeight,10);\r
-        }\r
-       }\r
-       else if (document.all) {\r
-               var obj=document.all[d];\r
-               if ((obj) && (obj.children) && (obj.children[0])) {\r
-                       w=parseInt(obj.children[0].offsetWidth,10);\r
-                       h=parseInt(obj.children[0].offsetHeight,10);\r
-        }\r
-       }\r
-       return { width: w, height: h };\r
-}\r
-\r
-// basic dynamics\r
-\r
-TermGlobals.writeElement=function(e,t,d) {\r
-       if (document.layers) {\r
-               var doc=(d)? d : self.document;\r
-               doc.layers[e].document.open();\r
-               doc.layers[e].document.write(t);\r
-               doc.layers[e].document.close();\r
-       }\r
-       else if (document.getElementById) {\r
-               var obj=document.getElementById(e);\r
-               obj.innerHTML=t;\r
-       }\r
-       else if (document.all) {\r
-               document.all[e].innerHTML=t;\r
-       }\r
-}\r
-\r
-TermGlobals.setElementXY=function(d,x,y) {\r
-       if (document.layers) {\r
-               document.layers[d].moveTo(x,y);\r
-       }\r
-       else if (document.getElementById) {\r
-               var obj=document.getElementById(d);\r
-               obj.style.left=x+'px';\r
-               obj.style.top=y+'px';\r
-       }\r
-       else if (document.all) {\r
-               document.all[d].style.left=x+'px';\r
-               document.all[d].style.top=y+'px';\r
-       }\r
-}\r
-\r
-TermGlobals.setVisible=function(d,v) {\r
-       if (document.layers) {\r
-               document.layers[d].visibility= (v)? 'show':'hide';\r
-       }\r
-       else if (document.getElementById) {\r
-               var obj=document.getElementById(d);\r
-               obj.style.visibility= (v)? 'visible':'hidden';\r
-       }\r
-       else if (document.all) {\r
-               document.all[d].style.visibility= (v)? 'visible':'hidden';\r
-       }\r
-}\r
-\r
-TermGlobals.setDisplay=function(d,v) {\r
-       if (document.getElementById) {\r
-               var obj=document.getElementById(d);\r
-               obj.style.display=v;\r
-       }\r
-       else if (document.all) {\r
-               document.all[d].style.display=v;\r
-       }\r
-}\r
-\r
-TermGlobals.guiElementsReady=function(e,d) {\r
-       if (document.layers) {\r
-               var doc=(d)? d : self.document;\r
-               return ((doc) && (doc.layers[e]))? true:false;\r
-       }\r
-       else if (document.getElementById) {\r
-               return (document.getElementById(e))? true:false;\r
-       }\r
-       else if (document.all) {\r
-               return (document.all[e])? true:false;\r
-       }\r
-       else return false;\r
-}\r
-\r
-\r
-// constructor mods (ie4 fix)\r
-\r
-var termString_keyref;\r
-var termString_keycoderef;\r
-\r
-function termString_makeKeyref() {\r
-       termString_keyref= new Array();\r
-       termString_keycoderef= new Array();\r
-       var hex= new Array('A','B','C','D','E','F');\r
-       for (var i=0; i<=15; i++) {\r
-               var high=(i<10)? i:hex[i-10];\r
-               for (var k=0; k<=15; k++) {\r
-                       var low=(k<10)? k:hex[k-10];\r
-                       var cc=i*16+k;\r
-                       if (cc>=32) {\r
-                               var cs=unescape("%"+high+low);\r
-                               termString_keyref[cc]=cs;\r
-                               termString_keycoderef[cs]=cc;\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
-if (!String.fromCharCode) {\r
-       termString_makeKeyref();\r
-       String.fromCharCode=function(cc) {\r
-               return (cc!=null)? termString_keyref[cc] : '';\r
-       };\r
-}\r
-if (!String.prototype.charCodeAt) {\r
-       if (!termString_keycoderef) termString_makeKeyref();\r
-       String.prototype.charCodeAt=function(n) {\r
-               cs=this.charAt(n);\r
-               return (termString_keycoderef[cs])? termString_keycoderef[cs] : 0;\r
-       };\r
-}\r
-\r
-// eof
\ No newline at end of file
diff --git a/extra/webapps/fjsc/resources/termlib/termlib_parser.js b/extra/webapps/fjsc/resources/termlib/termlib_parser.js
deleted file mode 100644 (file)
index 27c0c5f..0000000
+++ /dev/null
@@ -1,199 +0,0 @@
-/*\r
-  termlib_parser.js  v.1.0\r
-  command line parser for termlib.js\r
-  (c) Norbert Landsteiner 2005\r
-  mass:werk - media environments\r
-  <http://www.masswerk.at>\r
-\r
-  you are free to use this parser under the "termlib.js" license.\r
-\r
-  usage:  call "parseLine(this)" from your Terminal handler\r
-          parsed args in this.argv\r
-          quoting levels per arg in this.argQL (value: quote char)\r
-          this.argc: pointer to this.argv and this.argQL (used by parserGetopt)\r
-          call parseretopt(this, "<options>") from your handler to get opts\r
-          (returns an object with properties for every option flag. any float\r
-          values are stored in Object.<flag>.value; illegal opts in array\r
-          Object.illegals)\r
-\r
-  configuration: you may want to overide the follow objects (or add properties):\r
-          parserWhiteSpace: chars to be parsed as whitespace\r
-          parserQuoteChars: chars to be parsed as quotes\r
-          parserSingleEscapes: chars to escape a quote or escape expression\r
-          parserOptionChars: chars that start an option\r
-          parserEscapeExpressions: chars that start escape expressions\r
-*/\r
-\r
-// chars to be parsed as white space\r
-var parserWhiteSpace = {\r
-       ' ': true,\r
-       '\t': true\r
-}\r
-\r
-// chars to be parsed as quotes\r
-var parserQuoteChars = {\r
-       '"': true,\r
-       "'": true,\r
-       '`': true\r
-};\r
-\r
-// chars to be parsed as escape char\r
-var parserSingleEscapes = {\r
-       '\\': true\r
-};\r
-\r
-// chars that mark the start of an option-expression\r
-// for use with parserGetopt\r
-var parserOptionChars = {\r
-       '-': true\r
-}\r
-\r
-// chars that start escape expressions (value = handler)\r
-// plugin handlers for ascii escapes or variable substitution\r
-var parserEscapeExpressions = {\r
-       '%': parserHexExpression\r
-}\r
-\r
-function parserHexExpression(termref, pointer, echar, quotelevel) {\r
-       /* example for parserEscapeExpressions\r
-          params:\r
-            termref: ref to Terminal instance\r
-            pointer: position in termref.lineBuffer (echar)\r
-            echar:   escape character found\r
-            quotelevel: current quoting level (quote char or empty)\r
-          char under pointer will be ignored\r
-          the return value is added to the current argument\r
-       */\r
-       // convert hex values to chars (e.g. %20 => <SPACE>)\r
-       if (termref.lineBuffer.length > pointer+2) {\r
-               // get next 2 chars\r
-               var hi = termref.lineBuffer.charAt(pointer+1);\r
-               var lo = termref.lineBuffer.charAt(pointer+2);\r
-               lo = lo.toUpperCase();\r
-               hi = hi.toUpperCase();\r
-               // check for valid hex digits\r
-               if ((((hi>='0') && (hi<='9')) || ((hi>='A') && ((hi<='F')))) &&\r
-                   (((lo>='0') && (lo<='9')) || ((lo>='A') && ((lo<='F'))))) {\r
-                       // next 2 chars are valid hex, so strip them from lineBuffer\r
-                       parserEscExprStrip(termref, pointer+1, pointer+3);\r
-                       // and return the char\r
-                       return String.fromCharCode(parseInt(hi+lo, 16));\r
-               }\r
-       }\r
-       // if not handled return the escape character (=> no conversion)\r
-       return echar;\r
-}\r
-\r
-function parserEscExprStrip(termref, from, to) {\r
-       // strip characters from termref.lineBuffer (for use with escape expressions)\r
-       termref.lineBuffer =\r
-               termref.lineBuffer.substring(0, from) +\r
-               termref.lineBuffer.substring(to);\r
-}\r
-\r
-function parserGetopt(termref, optsstring) {\r
-    // scans argv form current position of argc for opts\r
-    // arguments in argv must not be quoted\r
-       // returns an object with a property for every option flag found\r
-       // option values (absolute floats) are stored in Object.<opt>.value (default -1)\r
-       // the property "illegals" contains an array of  all flags found but not in optstring\r
-       // argc is set to first argument that is not an option\r
-       var opts = { 'illegals':[] };\r
-       while ((termref.argc < termref.argv.length) && (termref.argQL[termref.argc]==''))  {\r
-               var a = termref.argv[termref.argc];\r
-               if ((a.length>0) && (parserOptionChars[a.charAt(0)])) {\r
-                       var i = 1;\r
-                       while (i<a.length) {\r
-                               var c=a.charAt(i);\r
-                               var v = '';\r
-                               while (i<a.length-1) {\r
-                                       var nc=a.charAt(i+1);\r
-                                       if ((nc=='.') || ((nc>='0') && (nc<='9'))) {\r
-                                               v += nc;\r
-                                               i++;\r
-                                       }\r
-                                       else break;\r
-                               }\r
-                               if (optsstring.indexOf(c)>=0) {\r
-                                       opts[c] = (v == '')? {value:-1} : (isNaN(v))? {value:0} : {value:parseFloat(v)};\r
-                               }\r
-                               else {\r
-                                       opts.illegals[opts.illegals.length]=c;\r
-                               }\r
-                               i++;\r
-                       }\r
-                       termref.argc++;\r
-               }\r
-               else break;\r
-       }\r
-       return opts;\r
-}\r
-\r
-function parseLine(termref) {\r
-       // stand-alone parser, takes a Terminal instance as argument\r
-       // parses the command line and stores results as instance properties\r
-       //   argv:  list of parsed arguments\r
-       //   argQL: argument's quoting level (<empty> or quote character)\r
-       //   argc:  cursur for argv, set initinally to zero (0)\r
-       // open quote strings are not an error but automatically closed.\r
-       var argv = [''];     // arguments vector\r
-       var argQL = [''];    // quoting level\r
-       var argc = 0;        // arguments cursor\r
-       var escape = false ; // escape flag\r
-       for (var i=0; i<termref.lineBuffer.length; i++) {\r
-               var ch= termref.lineBuffer.charAt(i);\r
-               if (escape) {\r
-                       argv[argc] += ch;\r
-                       escape = false;\r
-               }\r
-               else if (parserEscapeExpressions[ch]) {\r
-                       var v = parserEscapeExpressions[ch](termref, i, ch, argQL[argc]);\r
-                       if (typeof v != 'undefined') argv[argc] += v;\r
-               }\r
-               else if (parserQuoteChars[ch]) {\r
-                       if (argQL[argc]) {\r
-                               if (argQL[argc] == ch) {\r
-                                       argc ++;\r
-                                       argv[argc] = argQL[argc] = '';\r
-                               }\r
-                               else {\r
-                                       argv[argc] += ch;\r
-                               }\r
-                       }\r
-                       else {\r
-                               if (argv[argc] != '') {\r
-                                       argc ++;\r
-                                       argv[argc] = '';\r
-                                       argQL[argc] = ch;\r
-                               }\r
-                               else {\r
-                                       argQL[argc] = ch;\r
-                               }\r
-                       }\r
-               }\r
-               else if (parserWhiteSpace[ch]) {\r
-                       if (argQL[argc]) {\r
-                               argv[argc] += ch;\r
-                       }\r
-                       else if (argv[argc] != '') {\r
-                               argc++;\r
-                               argv[argc] = argQL[argc] = '';\r
-                       }\r
-               }\r
-               else if (parserSingleEscapes[ch]) {\r
-                       escape = true;\r
-               }\r
-               else {\r
-                       argv[argc] += ch;\r
-               }\r
-       }\r
-       if ((argv[argc] == '') && (!argQL[argc])) {\r
-               argv.length--;\r
-               argQL.length--;\r
-       }\r
-       termref.argv = argv;\r
-       termref.argQL = argQL;\r
-       termref.argc = 0;\r
-}\r
-\r
-// eof
\ No newline at end of file
diff --git a/extra/webapps/fjsc/summary.txt b/extra/webapps/fjsc/summary.txt
deleted file mode 100644 (file)
index 74e8bbb..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Web interface for Factor to Javascript compiler
diff --git a/extra/webapps/fjsc/tags.txt b/extra/webapps/fjsc/tags.txt
deleted file mode 100644 (file)
index 1b93c9e..0000000
+++ /dev/null
@@ -1 +0,0 @@
-webapp
diff --git a/extra/webapps/help/authors.txt b/extra/webapps/help/authors.txt
deleted file mode 100755 (executable)
index 1901f27..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Slava Pestov
diff --git a/extra/webapps/help/help.factor b/extra/webapps/help/help.factor
deleted file mode 100644 (file)
index 28d7360..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-! Copyright (C) 2005, 2007 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: kernel furnace furnace.validator http.server.responders
-       help help.topics html splitting sequences words strings 
-       quotations macros vocabs tools.browser combinators
-       arrays io.files ;
-IN: webapps.help 
-
-! : string>topic ( string -- topic )
-    ! " " split dup length 1 = [ first ] when ;
-
-: show-help ( topic -- )
-    serving-html
-    dup article-title [
-        [ help ] with-html-stream
-    ] simple-html-document ;
-
-\ show-help {
-    { "topic" }
-} define-action
-\ show-help { { "topic" "handbook" } } default-values
-
-M: link browser-link-href
-    link-name
-    dup word? over f eq? or [
-        browser-link-href
-    ] [
-        dup array? [ " " join ] when
-        [ show-help ] curry quot-link
-    ] if ;
-
-: show-word ( word vocab -- )
-    lookup show-help ;
-
-\ show-word {
-    { "word" }
-    { "vocab" }
-} define-action
-\ show-word { { "word" "call" } { "vocab" "kernel" } } default-values
-
-M: f browser-link-href
-    drop \ f browser-link-href ;
-
-M: word browser-link-href
-    dup word-name swap word-vocabulary
-    [ show-word ] 2curry quot-link ;
-
-: show-vocab ( vocab -- )
-    f >vocab-link show-help ;
-
-\ show-vocab {
-    { "vocab" }
-} define-action
-
-\ show-vocab { { "vocab" "kernel" } } default-values
-
-M: vocab-spec browser-link-href
-    vocab-name [ show-vocab ] curry quot-link ;
-
-: show-vocabs-tagged ( tag -- )
-    <vocab-tag> show-help ;
-
-\ show-vocabs-tagged {
-    { "tag" }
-} define-action
-
-M: vocab-tag browser-link-href
-    vocab-tag-name [ show-vocabs-tagged ] curry quot-link ;
-
-: show-vocabs-by ( author -- )
-    <vocab-author> show-help ;
-
-\ show-vocabs-by {
-    { "author" }
-} define-action
-
-M: vocab-author browser-link-href
-    vocab-author-name [ show-vocabs-by ] curry quot-link ;
-
-"help" "show-help" "extra/webapps/help" web-app
-
-! Hard-coding for factorcode.org
-PREDICATE: pathname resource-pathname
-    pathname-string "resource:" head? ;
-
-M: resource-pathname browser-link-href
-    pathname-string
-    "resource:" ?head drop
-    "/responder/source/" swap append ;
diff --git a/extra/webapps/numbers/authors.txt b/extra/webapps/numbers/authors.txt
deleted file mode 100755 (executable)
index 44b06f9..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Chris Double
diff --git a/extra/webapps/numbers/numbers.factor b/extra/webapps/numbers/numbers.factor
deleted file mode 100644 (file)
index 59247e9..0000000
+++ /dev/null
@@ -1,95 +0,0 @@
-! cont-number-guess
-!
-! Copyright (C) 2004 Chris Double.
-! 
-! Redistribution and use in source and binary forms, with or without
-! modification, are permitted provided that the following conditions are met:
-! 
-! 1. Redistributions of source code must retain the above copyright notice,
-!    this list of conditions and the following disclaimer.
-! 
-! 2. Redistributions in binary form must reproduce the above copyright notice,
-!    this list of conditions and the following disclaimer in the documentation
-!    and/or other materials provided with the distribution.
-! 
-! THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
-! INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
-! FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
-! DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
-! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
-! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
-! OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
-! WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
-! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
-! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-!
-! This example modifies the console based 'numbers-game' example
-! in a very minimal way to demonstrate conversion of a console
-! program to a web based application.
-!
-! All that was required was changing the input and output functions
-! to use HTML. The remaining code was untouched. 
-!
-! The result is not that pretty but it shows the basic idea.
-USING: kernel math parser html html.elements io namespaces
-math.parser random webapps.continuation ;
-
-IN: webapps.numbers
-
-: web-print ( str -- )
-  #! Display the string in a web page.
-  [
-    swap dup
-    <html>
-      <head> <title> write </title> </head>
-      <body>
-        <p> write </p>
-        <p> <a =href a> "Press to continue" write </a> </p>
-      </body>
-    </html>
-  ] show 2drop ;
-
-: read-number ( -- )
-  [
-    <html>
-      <head> <title> "Enter a number" write </title> </head>
-      <body>
-        <form =action "post" =method form>
-          <p> 
-            "Enter a number:" write
-            <input "text" =type "num" =name "20" =size input/>
-            <input "submit" =type "Press to continue" =value input/>
-          </p>
-        </form>
-      </body>
-    </html>
-  ] show [ "num" get ] bind string>number ;
-
-: guess-banner
-  "I'm thinking of a number between 0 and 100." web-print ;
-: guess-prompt  ;
-: too-high "Too high" web-print ;
-: too-low "Too low" web-print ;
-: correct "Correct - you win!" web-print ;
-: inexact-guess ( actual guess -- )
-     < [ too-high ] [ too-low ] if ;
-
-: judge-guess ( actual guess -- ? )
-    2dup = [
-        2drop correct f
-    ] [
-        inexact-guess t
-    ] if ;
-
-: number-to-guess ( -- n ) 100 random ;
-
-: numbers-game-loop ( actual -- )
-    dup guess-prompt read-number judge-guess [
-        numbers-game-loop
-    ] [
-        drop
-    ] if ;
-
-: numbers-game number-to-guess numbers-game-loop ;
-
-"numbers-game" [ numbers-game ] install-cont-responder
diff --git a/extra/webapps/pastebin/annotate-paste.furnace b/extra/webapps/pastebin/annotate-paste.furnace
deleted file mode 100755 (executable)
index 14a424f..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-<% USING: io math math.parser namespaces furnace ; %>
-
-<h1>Annotate</h1>
-
-<form method="POST" action="/responder/pastebin/annotate-paste">
-
-<table>
-
-<tr>
-<th align="right">Summary:</th>
-<td><input type="TEXT" name="summary" value="<% "summary" render %>" /></td>
-<td align="left" class="error"><% "summary" "*Required" render-error %></td>
-</tr>
-
-<tr>
-<th align="right">Your name:</th>
-<td><input type="TEXT" name="author" value="<% "author" render  %>" /></td>
-<td class="error"><% "author" "*Required" render-error %></td>
-</tr>
-
-<tr>
-<th align="right">File type:</th>
-<td><% "modes" render-template %></td>
-</tr>
-
-<!--
-<tr>
-<th align="right">Channel:</th>
-<td><input type="TEXT" name="channel" value="#concatenative" /></td>
-</tr>
--->
-
-<tr>
-<td></td>
-<td colspan="2" class="error" align="left"><% "contents" "*Required" render-error %></td>
-</tr>
-
-<tr>
-<th align="right" valign="top">Content:</th>
-<td colspan="2"><textarea rows="24" cols="60" name="contents"><% "contents" render %></textarea></td>
-</tr>
-</table>
-
-<input type="hidden" name="n" value="<% "n" get number>string write %>" />
-<input type="hidden" name="furnace-form-submitted" value="annotate-paste"/>
-<input type="SUBMIT" value="Annotate" />
-</form>
diff --git a/extra/webapps/pastebin/annotation.furnace b/extra/webapps/pastebin/annotation.furnace
deleted file mode 100755 (executable)
index e59db32..0000000
+++ /dev/null
@@ -1,11 +0,0 @@
-<% USING: namespaces io furnace calendar ; %>
-
-<h2>Annotation: <% "summary" get write %></h2>
-
-<table>
-<tr><th align="right">Annotation by:</th><td><% "author" get write %></td></tr>
-<tr><th align="right">File type:</th><td><% "mode" get write %></td></tr>
-<tr><th align="right">Created:</th><td><% "date" get timestamp>string write %></td></tr>
-</table>
-
-<% "syntax" render-template %>
diff --git a/extra/webapps/pastebin/authors.txt b/extra/webapps/pastebin/authors.txt
deleted file mode 100755 (executable)
index 1901f27..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Slava Pestov
diff --git a/extra/webapps/pastebin/footer.furnace b/extra/webapps/pastebin/footer.furnace
deleted file mode 100644 (file)
index 15b9011..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-</body>
-
-</html>
diff --git a/extra/webapps/pastebin/header.furnace b/extra/webapps/pastebin/header.furnace
deleted file mode 100644 (file)
index 2c8e79a..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-<% USING: namespaces io furnace sequences xmode.code2html webapps.pastebin ; %>
-
-<!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">
-<head>
-       <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
-
-       <title><% "title" get write %></title>
-       <link rel="stylesheet" href="style.css" type="text/css" media="screen" title="no title" charset="utf-8" />
-       <% default-stylesheet %>
-    <link rel="alternate" type="application/atom+xml" title="Pastebin - Atom" href="feed.xml" />
-</head>
-
-<body id="index">
-
-    <div class="navbar">
-        <% [ paste-list ] "Paste list" render-link %> |
-        <% [ new-paste ] "New paste" render-link %> |
-        <% [ feed.xml ] "Syndicate" render-link %>
-    </div>
-    <h1 class="pastebin-title"><% "title" get write %></h1>
diff --git a/extra/webapps/pastebin/modes.furnace b/extra/webapps/pastebin/modes.furnace
deleted file mode 100644 (file)
index 18bbec1..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-<% USING: furnace xmode.catalog sequences kernel html.elements assocs io sorting continuations ; %>
-
-<select name="mode">
-    <% modes keys natural-sort [
-        <option dup "mode" session-var = [ "true" =selected ] when option> write </option>
-    ] each %>
-</select>
diff --git a/extra/webapps/pastebin/new-paste.furnace b/extra/webapps/pastebin/new-paste.furnace
deleted file mode 100755 (executable)
index b21e197..0000000
+++ /dev/null
@@ -1,51 +0,0 @@
-<% USING: continuations furnace namespaces ; %>
-
-<%
-    "New paste" "title" set
-    "header" render-template
-%>
-
-<form method="POST" action="/responder/pastebin/submit-paste">
-
-<table>
-
-<tr>
-<th align="right">Summary:</th>
-<td><input type="TEXT" name="summary" value="<% "summary" render %>" /></td>
-<td align="left" class="error"><% "summary" "*Required" render-error %></td>
-</tr>
-
-<tr>
-<th align="right">Your name:</th>
-<td><input type="TEXT" name="author" value="<% "author" render  %>" /></td>
-<td class="error"><% "author" "*Required" render-error %></td>
-</tr>
-
-<tr>
-<th align="right">File type:</th>
-<td><% "modes" render-template %></td>
-</tr>
-
-<!--
-<tr>
-<th align="right">Channel:</th>
-<td><input type="TEXT" name="channel" value="#concatenative" /></td>
-</tr>
--->
-
-<tr>
-<td></td>
-<td colspan="2" class="error" align="left"><% "contents" "*Required" render-error %></td>
-</tr>
-
-<tr>
-<th align="right" valign="top">Content:</th>
-<td colspan="2"><textarea rows="24" cols="60" name="contents"><% "contents" render %></textarea></td>
-</tr>
-</table>
-
-<input type="hidden" name="furnace-form-submitted" value="new-paste"/>
-<input type="SUBMIT" value="Submit paste" />
-</form>
-
-<% "footer" render-template %>
diff --git a/extra/webapps/pastebin/paste-list.furnace b/extra/webapps/pastebin/paste-list.furnace
deleted file mode 100644 (file)
index 51813ec..0000000
+++ /dev/null
@@ -1,33 +0,0 @@
-<% USING: namespaces furnace sequences ; %>
-
-<%
-    "Pastebin" "title" set
-    "header" render-template
-%>
-
-<table width="100%" cellspacing="10">
-    <tr>
-        <td valign="top">
-            <table width="100%">
-                <tr align="left" class="pastebin-headings">
-                    <th width="50%">Summary:</th>
-                    <th width="100">Paste by:</th>
-                    <th width="200">Date:</th>
-                </tr>
-                <% "pastes" get <reversed> [ "paste-summary" render-component ] each %>
-            </table>
-        </td>
-        <td valign="top" width="25%">
-            <div class="infobox">
-                <p>This pastebin is written in <a href="http://factorcode.org/">Factor</a>. It is inspired by <a href="http://paste.lisp.org">lisppaste</a>.
-                </p>
-                <p>It can be used for collaborative development over IRC. You can post code for review, and annotate other people's code. Syntax highlighting for over a hundred file types is supported.
-                </p>
-                <p>
-                <% "webapps.pastebin" browse-webapp-source %></p>
-            </div>
-        </td>
-    </tr>
-</table>
-
-<% "footer" render-template %>
diff --git a/extra/webapps/pastebin/paste-summary.furnace b/extra/webapps/pastebin/paste-summary.furnace
deleted file mode 100644 (file)
index dc25fe1..0000000
+++ /dev/null
@@ -1,12 +0,0 @@
-<% USING: continuations namespaces io kernel math math.parser
-furnace webapps.pastebin calendar sequences ; %>
-
-<tr>
-    <td>
-        <a href="<% model get paste-link write %>">
-        <% "summary" get write %>
-        </a>
-    </td>
-    <td><% "author" get write %></td>
-    <td><% "date" get timestamp>string write %></td>
-</tr>
diff --git a/extra/webapps/pastebin/pastebin.factor b/extra/webapps/pastebin/pastebin.factor
deleted file mode 100755 (executable)
index 36a7279..0000000
+++ /dev/null
@@ -1,119 +0,0 @@
-USING: calendar furnace furnace.validator io.files kernel
-namespaces sequences http.server.responders html math.parser rss
-xml.writer xmode.code2html math calendar.format ;
-IN: webapps.pastebin
-
-TUPLE: pastebin pastes ;
-
-: <pastebin> ( -- pastebin )
-    V{ } clone pastebin construct-boa ;
-
-<pastebin> pastebin set-global
-
-TUPLE: paste
-summary author channel mode contents date
-annotations n ;
-
-: <paste> ( summary author channel mode contents -- paste )
-    f V{ } clone f paste construct-boa ;
-
-TUPLE: annotation summary author mode contents ;
-
-C: <annotation> annotation
-
-: get-paste ( n -- paste )
-    pastebin get pastebin-pastes nth ;
-
-: show-paste ( n -- )
-    serving-html
-    get-paste
-    [ "show-paste" render-component ] with-html-stream ;
-
-\ show-paste { { "n" v-number } } define-action
-
-: new-paste ( -- )
-    serving-html
-    [ "new-paste" render-template ] with-html-stream ;
-
-\ new-paste { } define-action
-
-: paste-list ( -- )
-    serving-html
-    [
-        [ show-paste ] "show-paste-quot" set
-        [ new-paste ] "new-paste-quot" set
-        pastebin get "paste-list" render-component
-    ] with-html-stream ;
-
-\ paste-list { } define-action
-
-: paste-link ( paste -- link )
-    paste-n number>string [ show-paste ] curry quot-link ;
-
-: safe-head ( seq n -- seq' )
-    over length min head ;
-
-: paste-feed ( -- entries )
-    pastebin get pastebin-pastes <reversed> 20 safe-head [
-        {
-            paste-summary
-            paste-link
-            paste-date
-        } get-slots timestamp>rfc3339 f swap <entry>
-    ] map ;
-
-: feed.xml ( -- )
-    "text/xml" serving-content
-    "pastebin"
-    "http://pastebin.factorcode.org"
-    paste-feed <feed> feed>xml write-xml ;
-
-\ feed.xml { } define-action
-
-: add-paste ( paste pastebin -- )
-    >r now over set-paste-date r>
-    pastebin-pastes 2dup length swap set-paste-n push ;
-
-: submit-paste ( summary author channel mode contents -- )
-    <paste> [ pastebin get add-paste ] keep
-    paste-link permanent-redirect ;
-
-\ new-paste
-\ submit-paste {
-    { "summary" v-required }
-    { "author" v-required }
-    { "channel" }
-    { "mode" v-required }
-    { "contents" v-required }
-} define-form
-
-\ new-paste {
-    { "channel" "#concatenative" }
-    { "mode" "factor" }
-} default-values
-
-: annotate-paste ( n summary author mode contents -- )
-    <annotation> swap get-paste
-    [ paste-annotations push ] keep
-    paste-link permanent-redirect ;
-
-[ "n" show-paste ]
-\ annotate-paste {
-    { "n" v-required v-number }
-    { "summary" v-required }
-    { "author" v-required }
-    { "mode" v-required }
-    { "contents" v-required }
-} define-form
-
-\ show-paste {
-    { "mode" "factor" }
-} default-values
-
-: style.css ( -- )
-    "text/css" serving-content
-    "style.css" send-resource ;
-
-\ style.css { } define-action
-
-"pastebin" "paste-list" "extra/webapps/pastebin" web-app
diff --git a/extra/webapps/pastebin/show-paste.furnace b/extra/webapps/pastebin/show-paste.furnace
deleted file mode 100755 (executable)
index 30129ed..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-<% USING: namespaces io furnace sequences xmode.code2html calendar ; %>
-
-<%
-    "Paste: " "summary" get append "title" set
-    "header" render-template
-%>
-
-<table>
-<tr><th>Paste by:</th><td><% "author" get write %></td></tr>
-<!-- <tr><th>Channel:</th><td><% "channel" get write %></td></tr> -->
-<tr><th>Created:</th><td><% "date" get timestamp>string write %></td></tr>
-<tr><th>File type:</th><td><% "mode" get write %></td></tr>
-</table>
-
-<% "syntax" render-template %>
-
-<% "annotations" get [ "annotation" render-component ] each %>
-
-<% model get "annotate-paste" render-component %>
-
-<% "footer" render-template %>
diff --git a/extra/webapps/pastebin/style.css b/extra/webapps/pastebin/style.css
deleted file mode 100644 (file)
index 4a469f9..0000000
+++ /dev/null
@@ -1,41 +0,0 @@
-body {
-       font:75%/1.6em "Lucida Grande", "Lucida Sans Unicode", verdana, geneva, sans-serif;
-       color:#888;
-}
-
-h1.pastebin-title {
-       font-size:300%;
-}
-
-a {
-       color:#222;
-       border-bottom:1px dotted #ccc;
-       text-decoration:none;
-}
-
-a:hover {
-       border-bottom:1px solid #ccc;
-}
-
-pre.code {
-       border:1px dashed #ccc;
-       background-color:#f5f5f5;
-       padding:5px;
-       font-size:150%;
-       color:#000000;
-}
-
-.navbar {
-       background-color:#eeeeee;
-       padding:5px;
-       border:1px solid #ccc;
-}
-
-.infobox {
-       border: 1px solid #C1DAD7;
-       padding: 10px;
-}
-
-.error {
-       color: red;
-}
diff --git a/extra/webapps/pastebin/syntax.furnace b/extra/webapps/pastebin/syntax.furnace
deleted file mode 100755 (executable)
index 17b64b9..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-<% USING: xmode.code2html splitting namespaces ; %>
-
-<pre class="code"><% "contents" get string-lines "mode" get htmlize-lines %></pre>
diff --git a/extra/webapps/planet/authors.txt b/extra/webapps/planet/authors.txt
deleted file mode 100755 (executable)
index 1901f27..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Slava Pestov
diff --git a/extra/webapps/planet/planet.factor b/extra/webapps/planet/planet.factor
deleted file mode 100755 (executable)
index 9a5f8ee..0000000
+++ /dev/null
@@ -1,129 +0,0 @@
-USING: sequences rss arrays concurrency.combinators kernel
-sorting html.elements io assocs namespaces math threads vocabs
-html furnace http.server.templating calendar math.parser
-splitting continuations debugger system http.server.responders
-xml.writer prettyprint logging calendar.format ;
-IN: webapps.planet
-
-: print-posting-summary ( posting -- )
-    <p "news" =class p>
-        <b> dup entry-title write </b> <br/>
-        <a entry-link =href "more" =class a>
-            "Read More..." write
-        </a>
-    </p> ;
-
-: print-posting-summaries ( postings -- )
-    [ print-posting-summary ] each ;
-
-: print-blogroll ( blogroll -- )
-    <ul "description" =class ul>
-        [
-            <li> <a dup third =href a> first write </a> </li>
-        ] each
-    </ul> ;
-
-: format-date ( date -- string )
-    rfc3339>timestamp timestamp>string ;
-
-: print-posting ( posting -- )
-    <h2 "posting-title" =class h2>
-        <a dup entry-link =href a>
-            dup entry-title write-html
-        </a>
-    </h2>
-    <p "posting-body" =class p>
-        dup entry-description write-html
-    </p>
-    <p "posting-date" =class p>
-        entry-pub-date format-date write
-    </p> ;
-
-: print-postings ( postings -- )
-    [ print-posting ] each ;
-
-SYMBOL: default-blogroll
-SYMBOL: cached-postings
-
-: safe-head ( seq n -- seq' )
-    over length min head ;
-
-: mini-planet-factor ( -- )
-    cached-postings get 4 safe-head print-posting-summaries ;
-
-: planet-factor ( -- )
-    serving-html [ "planet" render-template ] with-html-stream ;
-
-\ planet-factor { } define-action
-
-: planet-feed ( -- feed )
-    "[ planet-factor ]"
-    "http://planet.factorcode.org"
-    cached-postings get 30 safe-head <feed> ;
-
-: feed.xml ( -- )
-    "text/xml" serving-content
-    planet-feed feed>xml write-xml ;
-
-\ feed.xml { } define-action
-
-: style.css ( -- )
-    "text/css" serving-content
-    "style.css" send-resource ;
-
-\ style.css { } define-action
-
-SYMBOL: last-update
-
-: <posting> ( author entry -- entry' )
-    clone
-    [ ": " swap entry-title 3append ] keep
-    [ set-entry-title ] keep ;
-
-: fetch-feed ( url -- feed )
-    download-feed feed-entries ;
-
-\ fetch-feed DEBUG add-error-logging
-
-: fetch-blogroll ( blogroll -- entries )
-    dup 0 <column> swap 1 <column>
-    [ fetch-feed ] parallel-map
-    [ [ <posting> ] with map ] 2map concat ;
-
-: sort-entries ( entries -- entries' )
-    [ [ entry-pub-date ] compare ] sort <reversed> ;
-
-: update-cached-postings ( -- )
-    default-blogroll get
-    fetch-blogroll sort-entries
-    cached-postings set-global ;
-
-: update-thread ( -- )
-    millis last-update set-global
-    [ update-cached-postings ] "RSS feed update slave" spawn drop
-    10 60 * 1000 * sleep
-    update-thread ;
-
-: start-update-thread ( -- )
-    [
-        "webapps.planet" [
-            update-thread
-        ] with-logging
-    ] "RSS feed update master" spawn drop ;
-
-"planet" "planet-factor" "extra/webapps/planet" web-app
-
-{
-    { "Berlin Brown" "http://factorlang-fornovices.blogspot.com/feeds/posts/default" "http://factorlang-fornovices.blogspot.com" }
-    { "Chris Double" "http://www.blogger.com/feeds/18561009/posts/full/-/factor" "http://www.bluishcoder.co.nz/" }
-    { "Elie Chaftari" "http://fun-factor.blogspot.com/feeds/posts/default" "http://fun-factor.blogspot.com/" }
-    { "Doug Coleman" "http://code-factor.blogspot.com/feeds/posts/default" "http://code-factor.blogspot.com/" }
-    { "Daniel Ehrenberg" "http://useless-factor.blogspot.com/feeds/posts/default" "http://useless-factor.blogspot.com/" }
-    { "Gavin Harrison" "http://gmh33.blogspot.com/feeds/posts/default" "http://gmh33.blogspot.com/" }
-    { "Kio M. Smallwood"
-    "http://sekenre.wordpress.com/feed/atom/"
-    "http://sekenre.wordpress.com/" }
-    { "Phil Dawes" "http://www.phildawes.net/blog/category/factor/feed/atom" "http://www.phildawes.net/blog/" }
-    { "Samuel Tardieu" "http://www.rfc1149.net/blog/tag/factor/feed/atom/" "http://www.rfc1149.net/blog/tag/factor/" }
-    { "Slava Pestov" "http://factor-language.blogspot.com/atom.xml" "http://factor-language.blogspot.com/" }
-} default-blogroll set-global
diff --git a/extra/webapps/planet/planet.furnace b/extra/webapps/planet/planet.furnace
deleted file mode 100644 (file)
index 4c6676c..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-<% USING: namespaces html.elements webapps.planet sequences
-furnace ; %>
-
-<!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">
-<head>
-       <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
-
-       <title>planet-factor</title>
-       <link rel="stylesheet" href="style.css" type="text/css" media="screen" title="no title" charset="utf-8" />
-    <link rel="alternate" type="application/atom+xml" title="Planet Factor - Atom" href="feed.xml" />
-</head>
-
-<body id="index">
-    <h1 class="planet-title">[ planet-factor ]</h1>
-    <table width="100%" cellpadding="10">
-        <tr>
-            <td> <% cached-postings get 20 safe-head print-postings %> </td>
-            <td valign="top" width="25%" class="infobox">
-                <p>
-                    <b>planet-factor</b> is an Atom/RSS aggregator that collects the
-                    contents of <a href="http://factorcode.org/">Factor</a>-related blogs. It is inspired by
-                    <a href="http://planet.lisp.org">Planet Lisp</a>.
-                </p>
-                <p>
-                    <img src="http://planet.lisp.org/feed-icon-14x14.png" />
-                    <a href="feed.xml"> Syndicate </a>
-                </p>
-                <p>
-                    This webapp is written in <a href="http://factorcode.org/">Factor</a>.<br/>
-                    <% "webapps.planet" browse-webapp-source %>
-                </p>
-                <h2 class="blogroll-title">Blogroll</h2>
-                <% default-blogroll get print-blogroll %>
-                <p>
-                    If you want your weblog added to the blogroll, <a href="http://factorcode.org/gethelp.fhtml">just ask</a>.
-                </p>
-            </td>
-        </tr>
-    </table>
-</body>
-
-</html>
diff --git a/extra/webapps/planet/style.css b/extra/webapps/planet/style.css
deleted file mode 100644 (file)
index 7a66d8d..0000000
+++ /dev/null
@@ -1,45 +0,0 @@
-body {
-       font:75%/1.6em "Lucida Grande", "Lucida Sans Unicode", verdana, geneva, sans-serif;
-       color:#888;
-}
-
-h1.planet-title {
-       font-size:300%;
-}
-
-a {
-       color:#222;
-       border-bottom:1px dotted #ccc;
-       text-decoration:none;
-}
-
-a:hover {
-       border-bottom:1px solid #ccc;
-}
-
-.posting-title {
-       background-color:#f5f5f5;
-}
-
-pre, code {
-       color:#000000;
-       font-size:120%;
-}
-
-.infobox {
-       border-left: 1px solid #C1DAD7;
-}
-
-.posting-date {
-       text-align: right;
-       font-size:90%;
-}
-
-a.more {
-       display:block;
-       padding:0 0 5px 0;
-       color:#333;
-       text-decoration:none;
-       text-align:right;
-       border:none;
-}
index dc846a1b0413ba891cf90f1b15f35d9da07c5796..5492b34a54193e2dce108119b6f82df99be509a1 100755 (executable)
@@ -1,6 +1,8 @@
-USING: calendar calendar.windows kernel tools.test ;\r
-\r
-[ t ] [ windows-1601 [ timestamp>FILETIME FILETIME>timestamp ] keep = ] unit-test\r
-[ t ] [ windows-time [ windows-time>FILETIME FILETIME>windows-time ] keep = ] unit-test\r
-[ t ] [ windows-1601 400 years time+ [ timestamp>FILETIME FILETIME>timestamp ] keep = ] unit-test\r
-\r
+USING: calendar calendar.windows kernel tools.test
+windows.time ;
+IN: windows.time.tests
+
+[ t ] [ windows-1601 [ timestamp>FILETIME FILETIME>timestamp ] keep = ] unit-test
+[ t ] [ windows-time [ windows-time>FILETIME FILETIME>windows-time ] keep = ] unit-test
+[ t ] [ windows-1601 400 years time+ [ timestamp>FILETIME FILETIME>timestamp ] keep = ] unit-test
+
diff --git a/misc/macos-release.sh b/misc/macos-release.sh
deleted file mode 100644 (file)
index 3a080e0..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-source misc/version.sh
-
-TARGET=$1
-
-if [ "$1" = "x86" ]; then
-       CPU="x86.32"
-       TARGET=macosx-x86-32
-else
-       CPU="macosx-ppc"
-       TARGET=macosx-ppc
-fi
-
-BOOT_IMAGE=boot.$CPU.image
-wget http://factorcode.org/images/$VERSION/$BOOT_IMAGE
-
-make $TARGET
-Factor.app/Contents/MacOS/factor -i=$BOOT_IMAGE -no-user-init
-
-DISK_IMAGE_DIR=Factor-$VERSION
-DISK_IMAGE=Factor-$VERSION-$TARGET.dmg
-
-rm -f $DISK_IMAGE
-rm -rf $DISK_IMAGE_DIR
-mkdir $DISK_IMAGE_DIR
-mkdir -p $DISK_IMAGE_DIR/Factor/
-cp -R Factor.app $DISK_IMAGE_DIR/Factor/Factor.app
-chmod +x cp_dir
-cp factor.image license.txt README.txt $DISK_IMAGE_DIR/Factor/
-find core extra fonts misc unmaintained -type f \
-       -exec ./cp_dir {} $DISK_IMAGE_DIR/Factor/{} \;
-hdiutil create -srcfolder "$DISK_IMAGE_DIR" -fs HFS+ \
-       -volname "$DISK_IMAGE_DIR" "$DISK_IMAGE"
-
-ssh linode mkdir -p w/downloads/$VERSION/
-scp $DISK_IMAGE linode:w/downloads/$VERSION/
diff --git a/misc/source-release.sh b/misc/source-release.sh
deleted file mode 100755 (executable)
index 6b1bb2d..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-source misc/version.sh
-rm -rf .git .gitignore
-cd ..
-tar cfz Factor-$VERSION.tar.gz factor/
-
-ssh linode mkdir -p w/downloads/$VERSION/
-scp Factor-$VERSION.tar.gz linode:w/downloads/$VERSION/
diff --git a/misc/windows-release.sh b/misc/windows-release.sh
deleted file mode 100755 (executable)
index 7c3941a..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-source misc/version.sh
-
-CPU=$1
-
-if [ "$CPU" = "x86" ]; then
-    FLAGS="-no-sse2"
-fi
-
-make windows-nt-x86-32
-
-wget http://factorcode.org/dlls/freetype6.dll
-wget http://factorcode.org/dlls/zlib1.dll
-wget http://factorcode.org/images/$VERSION/boot.x86.32.image
-
-CMD="./factor-nt -i=boot.x86.32.image -no-user-init $FLAGS"
-echo $CMD
-$CMD
-rm -rf .git/ .gitignore
-rm -rf Factor.app/
-rm -rf vm/
-rm -f Makefile
-rm -f cp_dir
-rm -f boot.*.image
-
-FILE=Factor-$VERSION-win32-$CPU.zip
-
-cd ..
-zip -r $FILE Factor/
-
-ssh linode mkdir -p w/downloads/$VERSION/
-scp $FILE linode:w/downloads/$VERSION/
index e89bb0064500baaa28ad04fc2dbde221805e632f..5f82b21069ef3784be7f008c0b7f07428b81c069 100644 (file)
@@ -7,7 +7,7 @@ sequences io.sniffer.backend ;
 QUALIFIED: unix
 IN: io.sniffer.bsd
 
-M: unix-io destruct-handle ( obj -- ) unix:close drop ;
+M: unix-io destruct-handle ( obj -- ) unix:close ;
 
 C-UNION: ifreq_props "sockaddr-in" "short" "int" "caddr_t" ;
 C-STRUCT: ifreq { { "char" 16 } "name" } { "ifreq_props" "props" } ;
diff --git a/unmaintained/webapps/fjsc/authors.txt b/unmaintained/webapps/fjsc/authors.txt
new file mode 100644 (file)
index 0000000..44b06f9
--- /dev/null
@@ -0,0 +1 @@
+Chris Double
diff --git a/unmaintained/webapps/fjsc/fjsc.factor b/unmaintained/webapps/fjsc/fjsc.factor
new file mode 100755 (executable)
index 0000000..cf01bf6
--- /dev/null
@@ -0,0 +1,70 @@
+! Copyright (C) 2006 Chris Double. All Rights Reserved.
+! See http://factorcode.org/license.txt for BSD license.
+!
+USING: kernel furnace fjsc  peg namespaces
+       lazy-lists io io.files furnace.validator sequences
+       http.client http.server http.server.responders
+       webapps.file html ;
+IN: webapps.fjsc
+
+: compile ( code -- )
+  #! Compile the factor code as a string, outputting the http
+  #! response containing the javascript.
+  serving-text
+  'expression' parse parse-result-ast fjsc-compile
+  write flush ;
+
+! The 'compile' action results in an URL that looks like
+! 'responder/fjsc/compile'. It takes one query or post
+! parameter called 'code'. It calls the 'compile' word
+! passing the parameter to it on the stack.
+\ compile {
+  { "code" v-required }
+} define-action
+
+: compile-url ( url -- )
+  #! Compile the factor code at the given url, return the javascript.
+  dup "http:" head? [ "Unable to access remote sites." throw ] when
+  "http://" "host" header-param rot 3append http-get compile "();" write flush ;
+
+\ compile-url {
+  { "url" v-required }
+} define-action
+
+: render-page* ( model body-template head-template -- )
+  [
+      [ render-component ] [ f rot render-component ] html-document 
+  ] serve-html ;
+
+: repl ( -- )
+  #! The main 'repl' page.
+  f "repl" "head" render-page* ;
+
+! An action called 'repl'
+\ repl { } define-action
+
+: fjsc-web-app ( -- )
+  ! Create the web app, providing access
+  ! under '/responder/fjsc' which calls the
+  ! 'repl' action.
+  "fjsc" "repl" "extra/webapps/fjsc" web-app
+
+  ! An URL to the javascript resource files used by
+  ! the 'fjsc' responder.
+  "fjsc-resources" [
+   [
+     "extra/fjsc/resources/" resource-path doc-root set
+     file-responder
+   ] with-scope
+  ] add-simple-responder
+
+  ! An URL to the resource files used by
+  ! 'termlib'.
+  "fjsc-repl-resources" [
+   [
+     "extra/webapps/fjsc/resources/" resource-path doc-root set
+     file-responder
+   ] with-scope
+  ] add-simple-responder ;
+
+MAIN: fjsc-web-app
diff --git a/unmaintained/webapps/fjsc/head.furnace b/unmaintained/webapps/fjsc/head.furnace
new file mode 100644 (file)
index 0000000..97a3645
--- /dev/null
@@ -0,0 +1,7 @@
+<title>Factor to Javascript REPL</title>\r
+<link rel="stylesheet" type="text/css" href="/responder/fjsc-repl-resources/termlib/term_styles.css"/>\r
+<script type="text/javascript" src="/responder/fjsc-repl-resources/termlib/termlib.js"></script>\r
+<script type="text/javascript" src="/responder/fjsc-resources/jquery.js"></script>\r
+<script type="text/javascript" src="/responder/fjsc-resources/bootstrap.js"></script>\r
+<script type="text/javascript" src="/responder/fjsc-repl-resources/repl.js"></script>\r
+<script type="text/javascript" src="/responder/fjsc/compile-url?url=/responder/fjsc-resources/bootstrap.factor"></script>\r
diff --git a/unmaintained/webapps/fjsc/repl.furnace b/unmaintained/webapps/fjsc/repl.furnace
new file mode 100644 (file)
index 0000000..c67e9d4
--- /dev/null
@@ -0,0 +1,43 @@
+<table border="0">
+<tr><td valign="top">
+<div id="repl" style="position:relative;"></div>
+<p>More information on the Factor to Javascript compiler can be found at these blog posts:
+<ul>
+<li><a href="http://www.bluishcoder.co.nz/2006/12/compiling-factor-to-javascript.html">Factor to Javascript Compiler</a></li>
+<li><a href="http://www.bluishcoder.co.nz/2006/12/factor-to-javascript-compiler-updates.html">Factor to Javascript Compiler Updates</a></li>
+<li><a href="http://www.bluishcoder.co.nz/2006/12/continuations-added-to-fjsc.html">Continuations added to fjsc</a></li>
+<li><a href="http://www.bluishcoder.co.nz/2006/12/cross-domain-json-with-fjsc.html">Cross Domain JSON with fjsc</a></li>
+<li><a href="http://www.bluishcoder.co.nz/2007/02/factor-to-javascript-compiler-makeover.html">Factor to Javascript Compiler Makeover</a></li>
+</ul>
+</p>
+<p>The terminal emulation code for the Factor REPL is provided by the awesome <a href="http://www.masswerk.at/termlib/index.html">termlib</a> library by Norbert Landsteiner. Documentation for termlib is <a href="/responder/fjsc-repl-resources/termlib/">available here</a>. Please note the license of 'termlib':</p>
+<blockquote>This JavaScript-library is free for private and academic use. Please include a readable copyright statement and a backlink to <http://www.masswerk.at> in the web page. The library should always be accompanied by the "readme.txt" and the sample HTML-documents.
+
+The term "private use" includes any personal or non-commercial use, which is not related to commercial activites, but excludes intranet, extranet and/or public net applications that are related to any kind of commercial or profit oriented activity.
+
+For commercial use see <a href="http://www.masswerk.at">http://www.masswerk.at</a> for contact information.</blockquote>
+</td>
+<td valign="top">
+<p><b>Stack</b></p>
+<div id="stack">
+</div>
+<p><b>Playground</b></p>
+<div id="playground">
+</div>
+<h3>Compiled Code</h3>
+<textarea id="compiled" cols="40" rows="10">
+</textarea>
+<p>Some useful words:
+<dl>
+<dt>vocabs ( -- seq )</dt>
+<dd>Return a sequence of available vocabularies</dd>
+<dt>words ( string -- seq )</dt>
+<dd>Return a sequence of words in the given vocabulary</dd>
+<dt>all-words ( -- seq )</dt>
+<dd>Return a sequence of all words</dd>
+</dl>
+</p>
+<p>The contents of <a href="/responder/fjsc-resources/bootstrap.factor">bootstrap.factor</a> have been loaded on startup.</p>
+</td>
+</tr>
+</table>
diff --git a/unmaintained/webapps/fjsc/resources/repl.js b/unmaintained/webapps/fjsc/resources/repl.js
new file mode 100644 (file)
index 0000000..3bc8bdc
--- /dev/null
@@ -0,0 +1,99 @@
+/* Copyright (C) 2007 Chris Double. All Rights Reserved.\r
+   See http://factorcode.org/license.txt for BSD license. */\r
+\r
+var fjsc_repl = false;\r
+\r
+function fjsc_repl_handler() {\r
+  var my_term = this;\r
+  this.newLine();\r
+  if(this.lineBuffer != '') {\r
+    factor.server_eval(\r
+      this.lineBuffer, \r
+      function(text, result) { \r
+        document.getElementById("compiled").value = result;\r
+        display_datastack();        \r
+      }, \r
+      function() { my_term.prompt(); });\r
+  }\r
+  else\r
+    my_term.prompt();\r
+}\r
+\r
+function fjsc_init_handler() {\r
+  this.write(\r
+    [\r
+      TermGlobals.center('********************************************************'),\r
+      TermGlobals.center('*                                                      *'),\r
+      TermGlobals.center('*       Factor to Javascript Compiler Example          *'),\r
+      TermGlobals.center('*                                                      *'),\r
+      TermGlobals.center('********************************************************')\r
+    ]);\r
+  \r
+  this.prompt();\r
+}\r
+\r
+function startup() {\r
+  var conf = {\r
+    x: 0,\r
+    y: 0,\r
+    cols: 64,\r
+    rows: 18,\r
+    termDiv: "repl",\r
+    crsrBlinkMode: true,\r
+    ps: "scratchpad ",\r
+    initHandler: fjsc_init_handler,\r
+    handler: fjsc_repl_handler\r
+  };\r
+  fjsc_repl = new Terminal(conf);\r
+  fjsc_repl.open();\r
+}\r
+\r
+function display_datastack() {\r
+   var html=[];\r
+   html.push("<table border='1'>")\r
+   for(var i = 0; i < factor.cont.data_stack.length; ++i) {\r
+      html.push("<tr><td>")\r
+      html.push(factor.cont.data_stack[i])\r
+      html.push("</td></tr>")\r
+   }\r
+   html.push("</table>")\r
+   document.getElementById('stack').innerHTML=html.join("");\r
+}\r
+\r
+jQuery(function() {\r
+  startup();\r
+  display_datastack();\r
+});\r
+\r
+factor.add_word("kernel", ".s", "primitive", function(next) {   \r
+  var stack = factor.cont.data_stack;\r
+  var term = fjsc_repl;\r
+  for(var i=0; i<stack.length; ++i) {\r
+    term.type(""+stack[i]);\r
+    term.newLine();\r
+  }\r
+  factor.call_next(next);\r
+});\r
+\r
+factor.add_word("io", "print", "primitive", function(next) {   \r
+  var stack = factor.cont.data_stack;\r
+  var term = fjsc_repl;\r
+  term.type(""+stack.pop());\r
+  term.newLine();\r
+  factor.call_next(next);\r
+});\r
+\r
+factor.add_word("io", "write", "primitive", function(next) {   \r
+  var stack = factor.cont.data_stack;\r
+  var term = fjsc_repl;\r
+  term.type(""+stack.pop());\r
+  factor.call_next(next);\r
+});\r
+\r
+factor.add_word("io", ".", "primitive", function(next) {   \r
+  var stack = factor.cont.data_stack;\r
+  var term = fjsc_repl;\r
+  term.type(""+stack.pop());\r
+  term.newLine();\r
+  factor.call_next(next);\r
+});\r
diff --git a/unmaintained/webapps/fjsc/resources/termlib/faq.html b/unmaintained/webapps/fjsc/resources/termlib/faq.html
new file mode 100644 (file)
index 0000000..5adb516
--- /dev/null
@@ -0,0 +1,356 @@
+<HTML>\r
+<HEAD>\r
+       <TITLE>mass:werk termlib faq</TITLE>\r
+\r
+<STYLE TYPE="text/css">\r
+body,p,a,td {\r
+       font-family: courier,fixed,swiss,sans-serif;\r
+       font-size: 12px;\r
+       color: #cccccc;\r
+}\r
+.lh13 {\r
+       line-height: 13px;\r
+}\r
+.lh15 {\r
+       line-height: 15px;\r
+}\r
+pre {\r
+       font-family: courier,fixed,swiss,sans-serif;\r
+       color: #ccffaa;\r
+       font-size: 12px;\r
+       line-height: 15px;\r
+}\r
+.prop {\r
+       font-family: courier,fixed,swiss,sans-serif;\r
+       color: #bbee99;\r
+       font-size: 12px;\r
+       line-height: 15px;\r
+}\r
+h1 {\r
+       font-family: courier,fixed,swiss,sans-serif;\r
+       font-size: 16px;\r
+       color: #cccccc;\r
+}\r
+b.quest {\r
+       font-family: courier,fixed,swiss,sans-serif;\r
+       font-size: 14px;\r
+       font-weight: bold;\r
+       color: #bbee99;\r
+}\r
+a,a:link,a:visited {\r
+       text-decoration: none;\r
+       color: #77dd11;\r
+}\r
+a:hover {\r
+       text-decoration: underline;\r
+       color: #77dd11;\r
+}\r
+a:active {\r
+       text-decoration: underline;\r
+       color: #dddddd;\r
+}\r
+\r
+@media print {\r
+       body { background-color: #ffffff; }\r
+       body,p,a,td {\r
+               font-family: courier,fixed,swiss,sans-serif;\r
+               font-size: 12px;\r
+               color: #000000;\r
+       }\r
+       .lh13 {\r
+               line-height: 13px;\r
+       }\r
+       .lh15 {\r
+               line-height: 15px;\r
+       }\r
+       pre,.prop {\r
+               font-family: courier,fixed,swiss,sans-serif;\r
+               font-size: 12px;\r
+               color: #000000;\r
+               line-height: 15px;\r
+       }\r
+       h1 {\r
+               font-family: courier,fixed,swiss,sans-serif;\r
+               font-size: 16px;\r
+               color: #000000;\r
+       }\r
+       b.quest {\r
+               font-family: courier,fixed,swiss,sans-serif;\r
+               font-size: 14px;\r
+               font-weight: bold;\r
+               color: #000000;\r
+       }\r
+       a,a:link,a:visited {\r
+               text-decoration: none;\r
+               color: #000000;\r
+       }\r
+       a:hover {\r
+               text-decoration: underline;\r
+               color: #000000;\r
+       }\r
+       a:active {\r
+               text-decoration: underline;\r
+               color: #000000;\r
+       }\r
+}\r
+</STYLE>\r
+</HEAD>\r
+\r
+\r
+<BODY BGCOLOR="#222222" LINK="#77dd11" TEXT="#cccccc" ALINK="#dddddd" VLINK="#77dd11"\r
+TOPMARGIN="0" BOTTOMMARGIN="0" LEFTMARGIN="0" RIGHTMARGIN="0" MARGINHEIGHT="0" MARGINWIDTH="0"><A NAME="top"></A>\r
+\r
+<TABLE BORDER="0" CELLSPACING="20" CELLPADDING="0" ALIGN="center">\r
+<TR>\r
+       <TD NOWRAP><A HREF="index.html">termlib.js home</A></TD>\r
+       <TD>|</TD>\r
+       <TD NOWRAP><A HREF="multiterm_test.html">multiple terminal test</A></TD>\r
+       <TD>|</TD>\r
+       <TD NOWRAP><A HREF="parser_sample.html">sample parser</A></TD>\r
+       <TD>|</TD>\r
+       <TD NOWRAP>faq</TD>\r
+       <TD>|</TD>\r
+       <TD NOWRAP><A HREF="readme.txt" TITLE="readme.txt (text/plain)">documentation</A></TD>\r
+</TR>\r
+</TABLE>\r
+\r
+<TABLE BORDER="0" CELLSPACING="20" CELLPADDING="0" WIDTH="700" ALIGN="center">\r
+       <TR><TD>\r
+               <H1>frequently asked questions</H1>\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13">\r
+&nbsp;<BR>\r
+       <UL>\r
+       <LI CLASS="lh15"><A HREF="#chrome">Can I add chrome to the terminal? (e.g. a window header, a close box)</A></LI>\r
+       <LI CLASS="lh15"><A HREF="#embed">How can I embed a terminal relative to my HTML layout?</A></LI>\r
+       <LI CLASS="lh15"><A HREF="#syntax">I pasted your sample code and just got an error. - ???</A></LI>\r
+       <LI CLASS="lh15"><A HREF="#keyboard">I can't get any input, but I don't get any erros too.</A></LI>\r
+       <LI CLASS="lh15"><A HREF="#keylock">How can I temporary disable the keyboard handlers?</A></LI>\r
+       <LI CLASS="lh15"><A HREF="#linesranges">How can I set the cusor to the start / the end of the command line?</A></LI>\r
+       <LI CLASS="lh15"><A HREF="#historyunique">How can I limit the command history to unique entries only?</A></LI>\r
+       <LI CLASS="lh15"><A HREF="#rebuild">How can I change my color theme on the fly?</A></LI>\r
+       <LI CLASS="lh15"><A HREF="#connect">How can I connect to a server?</A></LI>\r
+       </UL>\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13"><A NAME="chrome"></A>\r
+&nbsp;<BR>\r
+<B CLASS="quest">Can I add chrome to the terminal? (e.g. a window header, a close box)</B><BR><BR>\r
+\r
+Not by the means of the Terminal object's interface (since there are way too many things that you may possibly want to add).<BR>\r
+The Terminal object allows you to specify the background color, the frame color, the frame's width and the font class used. If you want to add more chrome, you must align this in a separate division element.<BR><BR>\r
+\r
+To calculate the dimensions of the terminal use this formula:<BR><BR>\r
+\r
+width:&nbsp; 2 * frameWidth + conf.cols * &lt;width of &nbsp;&gt; + 2 * 2px padding (left and right)<BR>\r
+height: 2 * frameWidth + conf.rows * conf.rowHeight + 2 * 2px padding (top and bottom).<BR><BR>\r
+\r
+Or you could get the empirical values for width and height by calling a terminal's `<SPAN CLASS="prop">getDimensions()</SPAN>' method, once the terminal is open. (see documentation in &quot;readme.txt&quot;).<BR><BR>\r
+\r
+Finnally, you could obviously embed the terminal's division element in your custom chrome layout (see below). [This will not be compatible to Netscape 4.]<BR><BR>\r
+\r
+p.e.:<PRE>\r
+  &lt;div id=&quot;myTerminal1&quot; style=&quot;position:absolute; top:100px; left:100px;&quot;&gt;\r
+     &lt;table class=&quot;termChrome&quot;&gt;\r
+       &lt;tbody&gt;\r
+        &lt;tr&gt;\r
+           &lt;td class=&quot;termTitle&quot;&gt;terminal 1&lt;/td&gt;\r
+        &lt;/tr&gt;\r
+        &lt;tr&gt;\r
+           &lt;td class=&quot;termBody&quot;&gt;&lt;div id=&quot;termDiv1&quot; style=&quot;position:relative&quot;&gt;&lt;/div&gt;&lt;/td&gt;\r
+        &lt;/tr&gt;\r
+       &lt;/tbody&gt;\r
+     &lt;/table&gt;\r
+   &lt;/div&gt;\r
+\r
+   // get a terminal for this\r
+\r
+   var term1 = new Terminal(\r
+                 {\r
+                   x: 0,\r
+                   y: 0,\r
+                   id: 1,\r
+                   termDiv: &quot;termDiv1&quot;,\r
+                   handler: myTermHandler\r
+                 }\r
+              );\r
+   term1.open();\r
+   \r
+   // and this is how to move the chrome and the embedded terminal\r
+\r
+   TermGlobals.setElementXY( &quot;myTerminal1&quot;, 200, 80 );\r
+</PRE>\r
+To keep track of the instance for any widgets use the terminal's `id' property. (You must set this in the configuration object to a unique value for this purpose.)<BR><BR>\r
+\r
+For a demonstration see the <A HREF="chrome_sample.html">Chrome Sample Page</A>.\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13"><A NAME="embed"></A>\r
+&nbsp;<BR>\r
+<B CLASS="quest">How can I embed a terminal relative to my HTML layout?</B><BR><BR>\r
+\r
+Define your devision element with attribute &quot;position&quot; set to &quot;relative&quot; and place this inside your layout. Call &quot;new Terminal()&quot; with config-values { x: 0, y: 0 } to leave it at its relative origin.\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13"><A NAME="syntax"></A>\r
+&nbsp;<BR>\r
+<B CLASS="quest">I pasted your sample code and just got an error. - ???</B><BR><BR>\r
+\r
+The short examples are kept arbitrarily simple to show the syntax.<BR>\r
+Make sure that your divison element(s) is/are rendered by the browser before `Terminal.open()' is called.<BR><BR>\r
+\r
+Does not work:\r
+<PRE>  &lt;head&gt;\r
+  &lt;script&gt;\r
+    var term = new Terminal();\r
+    term.open();\r
+  &lt;/script&gt;\r
+  &lt;/head&gt;\r
+</PRE>\r
+Does work:\r
+<PRE>  &lt;head&gt;\r
+  &lt;script&gt;\r
+    var term;\r
+    \r
+    function termOpen() {\r
+       // to be called from outside after compile time\r
+       term = new Terminal();\r
+       term.open();\r
+    }\r
+  &lt;/script&gt;\r
+  &lt;/head&gt;\r
+</PRE>\r
+c.f. &quot;readme.txt&quot;<BR>\r
+(Opening a terminal by clicking a link implies also that the page has currently focus.)<BR><BR>\r
+With v.1.01 and higher this doesn't cause an error any more.<BR>`Terminal.prototype.open()' now returns a value for success.\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13"><A NAME="keyboard"></A>\r
+&nbsp;<BR>\r
+<B CLASS="quest">I can't get any input, but I don't get any erros too.</B><BR><BR>\r
+\r
+The Terminal object's functionality relies on the browsers ability to generate and handle keyboard events.<BR>\r
+Sadly some browsers lack a full implementation of the event model. (e.g. Konquerer [khtml] and early versions of Apple Safari, which is a descendant of khtml.)\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13"><A NAME="keylock"></A>\r
+&nbsp;<BR>\r
+<B CLASS="quest">How can I temporary disable the keyboard handlers?</B><BR>\r
+<SPAN CLASS="prop">(The terminal is blocking my HTML form fields, etc.)</SPAN><BR><BR>\r
+\r
+With version 1.03 there's a global property `<SPAN CLASS="prop">TermGlobals.keylock</SPAN>'. Set this to `true' to disable the keyboard handlers without altering any other state. Reset it to `false' to continue with your terminal session(s).\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13"><A NAME="linesranges"></A>\r
+&nbsp;<BR>\r
+<B CLASS="quest">How can I set the cusor to the start / the end of the command line?</B><BR><BR>\r
+\r
+In case you need to implement a shortcut (like ^A of some UN*X-shells) to jump to the beginning or the end of the current input line, there are two private instance methods you could utilize:<BR><BR>\r
+`<SPAN CLASS="prop">_getLineEnd(&lt;row&gt;, &lt;col&gt;)</SPAN>' returns an array [&lt;row&gt;, &lt;col&gt;] with the position of the last character in the logical input line with ASCII value &gt;= 32 (0x20).<BR><BR>\r
+`<SPAN CLASS="prop">_getLineStart(&lt;row&gt;, &lt;col&gt;)</SPAN>' returns an array [&lt;row&gt;, &lt;col&gt;] with the position of the first character in the logical input line with ASCII value &gt;= 32 (0x20).<BR><BR>\r
+Both take a row and a column of a cursor position as arguments.<BR><BR>\r
+\r
+p.e.:\r
+<PRE>\r
+  // jump to the start of the input line\r
+\r
+  myCtrlHandler() {\r
+     // catch ^A and jump to start of the line\r
+     if (this.inputChar == 1) {\r
+        var firstChar = this._getLineStart(this.r, this.c);\r
+        this.cursorSet(firstChar[0], firstChar[1]);\r
+     }\r
+  }</PRE>\r
+(Keep in mind that this is not exactly a good example, since some browser actually don't issue a keyboard event for \r
+&quot;^A&quot;. And other browsers, which do catch such codes, are not very reliable in that.)\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13"><A NAME="historyunique"></A>\r
+&nbsp;<BR>\r
+<B CLASS="quest">How can I limit the command history to unique entries only?</B><BR>\r
+       <SPAN CLASS="prop">(My application effords commands to be commonly repeated.)</SPAN><BR><BR>\r
+\r
+With version 1.05 there is a new configuration and control flag `<SPAN CLASS="prop">historyUnique</SPAN>'. All you need is setting this to `true' in your terminal's configuration object.\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13"><A NAME="rebuild"></A>\r
+&nbsp;<BR>\r
+<B CLASS="quest">How can I change my color theme on the fly?</B><BR><BR>\r
+\r
+With version 1.07 there is a new method `<SPAN CLASS="prop">Terminal.rebuild()</SPAN>'.<BR>\r
+This method updates the GUI to current config settings while preserving all other state.<BR><BR>\r
+p.e.:\r
+<PRE>\r
+   // change color settings on the fly\r
+   // here: set bgColor to white and font style to class &quot;termWhite&quot;\r
+   // method rebuild() updates the GUI without side effects\r
+   // assume var term holds a referene to a Terminal object already active\r
+\r
+   term.conf.bgColor = '#ffffff';\r
+   term.conf.fontClass = 'termWhite';\r
+   term.rebuild();</PRE>\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13"><A NAME="connect"></A>\r
+&nbsp;<BR>\r
+<B CLASS="quest">How can I connect to a server?</B><BR><BR>\r
+\r
+The Terminal object only provides an interface to handle console input and output.<BR>\r
+External connections have to be handled outside the Terminal object. You could use the XMLHttpRequest-Object (and use a communication model like AJAX or JSON) or connect via a frame or iframe element to a foreign host.<BR><BR>\r
+Handling connections is considered to be out of the realm of the &quot;termlib.js&quot; library.<BR>\r
+The code you need is in fact quite simple:\r
+<PRE>\r
+  function connectToHost(url) {\r
+     if (window.XMLHttpRequest) {\r
+        request = new XMLHttpRequest();\r
+     }\r
+     else if (window.ActiveXObject) {\r
+         request = new ActiveXObject('Microsoft.XMLHTTP');\r
+     }\r
+     if (request) {\r
+         request.onreadystatechange = requestChangeHandler;\r
+         request.open('GET', url);\r
+         request.send('');\r
+     }\r
+     else {\r
+        // XMLHttpRequest not implemented\r
+     }\r
+  }\r
+  \r
+  function requestChangeHandler() {\r
+     if (request.readyState == 4) {\r
+        // readyState 4: complete; now test for server's response status\r
+        if (request.status == 200) {\r
+           // response in request.responseText or request.responseXML if XML-code\r
+           // if it's JS-code we could get this by eval(request.responseText)\r
+           // by this we could import whole functions to be used via the terminal\r
+        }\r
+        else {\r
+           // connection error\r
+           // status code and message in request.status and request.statusText\r
+        }\r
+     }\r
+  }\r
+</PRE>\r
+You should use this only together with a timer (window.setTimeout()) to handle connection timeouts.<BR>\r
+Additionally you would need some syntax to authenticate and tell the server what you want.<BR>\r
+For this purpose you could use the following methods of the XMLHttpRequest object:<BR><BR>\r
+\r
+       <TABLE BORDER="0" CELLSPACING="0" CELLPADDING="3">\r
+       <TR VALIGN="top"><TD NOWRAP CLASS="prop">setRequestHeader(&quot;<I>headerLabel</I>&quot;, &quot;<I>value</I>&quot;)</TD><TD>set a HTTP header to be sent to the server</TD></TR>\r
+       <TR VALIGN="top"><TD NOWRAP CLASS="prop">getResponseHeader(&quot;<I>headerLabel</I>&quot;)</TD><TD>get a HTTP header sent from the server</TD></TR>\r
+       <TR VALIGN="top"><TD NOWRAP CLASS="prop">open(<I>method</I>, &quot;<I>url</I>&quot; [, <I>asyncFlag</I> [,<BR>&nbsp; &quot;<I>userid</I>&quot; [, &quot;<I>password</I>&quot;]]])</TD><TD>assign the destination properties to the request.<BR>be aware that userid and password are not encrypted!</TD></TR>\r
+       <TR VALIGN="top"><TD NOWRAP CLASS="prop">send(<I>content</I>)</TD><TD>transmit a message body (post-string or DOM object)</TD></TR>\r
+       <TR VALIGN="top"><TD NOWRAP CLASS="prop">abort()</TD><TD>use this to stop a pending connection</TD></TR>\r
+       </TABLE>\r
+\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13">\r
+       &nbsp;<BR>\r
+       Norbert Landsteiner - August 2005<BR>\r
+       <A HREF="http://www.masswerk.at/" TARGET="_blank">http://www.masswerk.at</A>\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13">\r
+       &nbsp;<BR>\r
+               <A HREF="#top">&gt; top of page</A>\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13">\r
+       &nbsp;\r
+       </TD></TR>\r
+</TABLE>\r
+\r
+<DIV ID="termDiv" STYLE="position:absolute; top:20px; left:100px;"></DIV>\r
+\r
+</BODY>\r
+</HTML>
\ No newline at end of file
diff --git a/unmaintained/webapps/fjsc/resources/termlib/index.html b/unmaintained/webapps/fjsc/resources/termlib/index.html
new file mode 100644 (file)
index 0000000..1770b2c
--- /dev/null
@@ -0,0 +1,207 @@
+<HTML>\r
+<HEAD>\r
+       <TITLE>mass:werk termlib</TITLE>\r
+\r
+<STYLE TYPE="text/css">\r
+body,p,a,td {\r
+       font-family: courier,fixed,swiss,sans-serif;\r
+       font-size: 12px;\r
+       color: #cccccc;\r
+}\r
+.lh13 {\r
+       line-height: 13px;\r
+}\r
+.lh15 {\r
+       line-height: 15px;\r
+}\r
+pre {\r
+       font-family: courier,fixed,swiss,sans-serif;\r
+       font-size: 12px;\r
+       color: #ccffaa;\r
+       line-height: 15px;\r
+}\r
+.prop {\r
+       font-family: courier,fixed,swiss,sans-serif;\r
+       color: #bbee99;\r
+       font-size: 12px;\r
+       line-height: 15px;\r
+}\r
+h1 {\r
+       font-family: courier,fixed,swiss,sans-serif;\r
+       font-size: 16px;\r
+       color: #cccccc;\r
+}\r
+a,a:link,a:visited {\r
+       text-decoration: none;\r
+       color: #77dd11;\r
+}\r
+a:hover {\r
+       text-decoration: underline;\r
+       color: #77dd11;\r
+}\r
+a:active {\r
+       text-decoration: underline;\r
+       color: #dddddd;\r
+}\r
+\r
+@media print {\r
+       body { background-color: #ffffff; }\r
+       body,p,a,td {\r
+               font-family: courier,fixed,swiss,sans-serif;\r
+               font-size: 12px;\r
+               color: #000000;\r
+       }\r
+       .lh13 {\r
+               line-height: 13px;\r
+       }\r
+       .lh15 {\r
+               line-height: 15px;\r
+       }\r
+       pre,.prop {\r
+               font-family: courier,fixed,swiss,sans-serif;\r
+               font-size: 12px;\r
+               color: #000000;\r
+               line-height: 15px;\r
+       }\r
+       h1 {\r
+               font-family: courier,fixed,swiss,sans-serif;\r
+               font-size: 16px;\r
+               color: #000000;\r
+       }\r
+       a,a:link,a:visited {\r
+               text-decoration: none;\r
+               color: #000000;\r
+       }\r
+       a:hover {\r
+               text-decoration: underline;\r
+               color: #000000;\r
+       }\r
+       a:active {\r
+               text-decoration: underline;\r
+               color: #000000;\r
+       }\r
+}\r
+</STYLE>\r
+</HEAD>\r
+\r
+\r
+<BODY BGCOLOR="#222222" LINK="#77dd11" TEXT="#cccccc" ALINK="#dddddd" VLINK="#77dd11"\r
+TOPMARGIN="0" BOTTOMMARGIN="0" LEFTMARGIN="0" RIGHTMARGIN="0" MARGINHEIGHT="0" MARGINWIDTH="0"><A NAME="top"></A>\r
+\r
+<TABLE BORDER="0" CELLSPACING="20" CELLPADDING="0" ALIGN="center">\r
+<TR>\r
+       <TD NOWRAP>termlib.js home</TD>\r
+       <TD>|</TD>\r
+       <TD NOWRAP><A HREF="multiterm_test.html">multiple terminal test</A></TD>\r
+       <TD>|</TD>\r
+       <TD NOWRAP><A HREF="parser_sample.html">sample parser</A></TD>\r
+       <TD>|</TD>\r
+       <TD NOWRAP><A HREF="faq.html">faq</A></TD>\r
+       <TD>|</TD>\r
+       <TD NOWRAP><A HREF="readme.txt" TITLE="readme.txt (text/plain)">documentation</A></TD>\r
+</TR>\r
+</TABLE>\r
+\r
+<TABLE BORDER="0" CELLSPACING="20" CELLPADDING="0" WIDTH="700" ALIGN="center">\r
+       <TR><TD>\r
+               <H1>mass:werk termlib.js</H1>\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13">\r
+               The JavaScript library &quot;termlib.js&quot; provides a `Terminal' object, which\r
+               facillitates a simple and object oriented approach to generate and control a\r
+               terminal-like interface for web services.<BR><BR>\r
+               \r
+               "termlib.js" features direct keyboard input and powerful output methods\r
+               for multiple and simultanious instances of the `Terminal' object.<BR><BR>\r
+               \r
+               The library was written with the aim of simple usage and a maximum of compatibility\r
+               with minimal foot print in the global namespace.<BR><BR><BR>\r
+               \r
+               \r
+               A short example:<BR>\r
+  <PRE>\r
+  var term = new Terminal( {handler: termHandler} );\r
+  term.open();\r
+\r
+  function termHandler() {\r
+     this.newLine();\r
+     var line = this.lineBuffer;\r
+     if (line != &quot;&quot;) {\r
+        this.write(&quot;You typed: &quot;+line);\r
+     }\r
+     this.prompt();\r
+  }\r
+  </PRE>\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13">\r
+       <B>License</B><BR><BR>\r
+\r
+       This JavaScript-library is <U>free for private and academic use</U>.\r
+       Please include a readable copyright statement and a backlink to &lt;http://www.masswerk.at&gt; in the\r
+       web page. The library should always be accompanied by the &quot;readme.txt&quot; and the sample HTML-documents.<BR><BR>\r
+\r
+       The term &quot;private use&quot; includes any personal or non-commercial use, which is not related\r
+       to commercial activites, but excludes intranet, extranet and/or public net applications\r
+       that are related to any kind of commercial or profit oriented activity.<BR><BR>\r
+\r
+       For commercial use see &lt;<A HREF="http://www.masswerk.at/" TARGET="_blank">http://www.masswerk.at</A>&gt; for contact information.\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13">\r
+       <B>Distribution</B><BR><BR>\r
+\r
+       This JavaScript-library may be distributed freely as long it is distributed together with the &quot;readme.txt&quot; and the sample HTML-documents and this document.<BR><BR>\r
+\r
+       Any changes to the library should be commented and be documented in the readme-file.<BR>\r
+       Any changes must be reflected in the `Terminal.version' string as &quot;Version.Subversion&nbsp;(compatibility)&quot;.\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13">\r
+       <B>Disclaimer</B><BR><BR>\r
+\r
+       This software is distributed AS IS and in the hope that it will be useful, but WITHOUT ANY\r
+       WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+       PURPOSE. The entire risk as to the quality and performance of the product is borne by the\r
+       user. No use of the product is authorized hereunder except under this disclaimer.\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13">\r
+       <B>History</B><BR><BR>\r
+\r
+       This library evolved from the terminal script &quot;TermApp&quot; ((c) N. Landsteiner 2003) and is in its\r
+       current form a down scaled spinn-off of the &quot;JS/UIX&quot; project. (JS/UIX is not a free&nbsp;software by now.)\r
+       c.f.: &lt;<A HREF="http://www.masswerk.at/jsuix/" TARGET="_blank">http://www.masswerk.at/jsuix</A>&gt;<BR><BR>\r
+\r
+       For version history: see the <A HREF="readme.txt">readme.txt</A>.\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13">\r
+       &nbsp;<BR>\r
+       <B>Download</B><BR><BR>\r
+       Be sure to have read the license information and the disclamer and that you are willing to respect copyrights.<BR><BR>\r
+\r
+       <SPAN CLASS="prop">Download:</SPAN> <A HREF="termlib.zip">termlib.zip</A> (~ 40 KB, incl. docs)<BR><BR>\r
+       Current version is &quot;1.07 (original)&quot;.<BR>\r
+       The files are now provided with line breaks  in format &lt;CRLF&gt;.<BR>\r
+       &nbsp;\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13">\r
+       <B>Author</B><BR><BR>\r
+       &copy; Norbert Landsteiner 2003-2005<BR>\r
+       mass:werk &#150; media environments<BR>\r
+       <A HREF="http://www.masswerk.at/" TARGET="_blank">http://www.masswerk.at</A>\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13">\r
+       &nbsp;<BR>\r
+       Author's note:<BR>\r
+       Please do not contact me on questions of simple usage. There is an extensive documentation (readme.txt) including plenty of sample code that should provide all information you need.\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13">\r
+       &nbsp;<BR>\r
+               <A HREF="#top">&gt; top of page</A>\r
+       </TD></TR>\r
+       <TR><TD CLASS="lh13">\r
+       &nbsp;\r
+       </TD></TR>\r
+</TABLE>\r
+\r
+<DIV ID="termDiv" STYLE="position:absolute; top:20px; left:100px;"></DIV>\r
+\r
+</BODY>\r
+</HTML>
\ No newline at end of file
diff --git a/unmaintained/webapps/fjsc/resources/termlib/multiterm_test.html b/unmaintained/webapps/fjsc/resources/termlib/multiterm_test.html
new file mode 100644 (file)
index 0000000..0a4e1ec
--- /dev/null
@@ -0,0 +1,188 @@
+<HTML>\r
+<HEAD>\r
+       <TITLE>termlib Multiple Terminal Test</TITLE>\r
+       <SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript" SRC="termlib.js"></SCRIPT>\r
+\r
+<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript">\r
+<!--\r
+\r
+/*\r
+  multiple terminal test for termlib.js\r
+\r
+  (c) Norbert Landsteiner 2003-2005\r
+  mass:werk - media environments\r
+  <http://www.masswerk.at>\r
+\r
+*/\r
+\r
+var term=new Array();\r
+\r
+var helpPage=[\r
+       '%CS%+r Terminal Help %-r%n',\r
+       '  This is just a tiny test for multiple terminals.',\r
+       '  use one of the following commands:',\r
+       '     clear .... clear the terminal',\r
+       '     exit ..... close the terminal (or <ESC>)',\r
+       '     id ....... show terminal\'s id',\r
+       '     switch ... switch to other terminal',\r
+       '     help ..... show this help page',\r
+       '  other input will be echoed to the terminal.',\r
+       ' '\r
+];\r
+\r
+function termOpen(n) {\r
+       if (!term[n]) {\r
+               var y=(n==1)? 70: 280;\r
+               term[n]=new Terminal(\r
+                       {\r
+                               x: 220,\r
+                               y: y,\r
+                               rows: 12,\r
+                               greeting: '%+r +++ Terminal #'+n+' ready. +++ %-r%nType "help" for help.%n',\r
+                               id: n,\r
+                               termDiv: 'termDiv'+n,\r
+                               crsrBlinkMode: true,\r
+                               handler: termHandler,\r
+                               exitHandler: termExitHandler\r
+                       }\r
+               );\r
+               if (term[n]) term[n].open();\r
+       }\r
+       else if (term[n].closed) {\r
+               term[n].open();\r
+       }\r
+       else {\r
+               term[n].focus();\r
+       }\r
+}\r
+\r
+function termHandler() {\r
+       // called on <CR> or <ENTER>\r
+       this.newLine();\r
+       var cmd=this.lineBuffer;\r
+       if (cmd!='') {\r
+               if (cmd=='switch') {\r
+                       var other=(this.id==1)? 2:1;\r
+                       termOpen(other);\r
+               }\r
+               else if (cmd=='clear') {\r
+                       this.clear();\r
+               }\r
+               else if (cmd=='exit') {\r
+                       this.close();\r
+               }\r
+               else if (cmd=='help') {\r
+                       this.write(helpPage);\r
+               }\r
+               else if (cmd=='id') {\r
+                       this.write('terminal id: '+this.id);\r
+               }\r
+               else {\r
+                       this.type('You typed: '+cmd);\r
+                       this.newLine();\r
+               }\r
+       }\r
+       this.prompt();\r
+}\r
+\r
+function termExitHandler() {\r
+       // optional handler called on exit\r
+       // activate other terminal if open\r
+       var other=(this.id==1)? 2:1;\r
+       if ((term[other]) && (term[other].closed==false)) term[other].focus();\r
+}\r
+\r
+//-->\r
+</SCRIPT>\r
+\r
+<STYLE TYPE="text/css">\r
+body,p,a,td {\r
+       font-family: courier,fixed,swiss,sans-serif;\r
+       font-size: 12px;\r
+       color: #cccccc;\r
+}\r
+.lh15 {\r
+       line-height: 15px;\r
+}\r
+.term {\r
+       font-family: courier,fixed,swiss,sans-serif;\r
+       font-size: 12px;\r
+       color: #33d011;\r
+       background: none;\r
+}\r
+.termReverse {\r
+       color: #111111;\r
+       background: #33d011;\r
+}\r
+a,a:link,a:visited {\r
+       text-decoration: none;\r
+       color: #77dd11;\r
+}\r
+a:hover {\r
+       text-decoration: underline;\r
+       color: #77dd11;\r
+}\r
+a:active {\r
+       text-decoration: underline;\r
+       color: #dddddd;\r
+}\r
+\r
+a.termopen,a.termopen:link,a.termopen:visited {\r
+       text-decoration: none;\r
+       color: #77dd11;\r
+       background: none;\r
+}\r
+a.termopen:hover {\r
+       text-decoration: none;\r
+       color: #222222;\r
+       background: #77dd11;\r
+}\r
+a.termopen:active {\r
+       text-decoration: none;\r
+       color: #222222;\r
+       background: #dddddd;\r
+}\r
+\r
+</STYLE>\r
+</HEAD>\r
+\r
+\r
+<BODY BGCOLOR="#222222" LINK="#77dd11" TEXT="#cccccc" ALINK="#dddddd" VLINK="#77dd11"\r
+TOPMARGIN="0" BOTTOMMARGIN="0" LEFTMARGIN="0" RIGHTMARGIN="0" MARGINHEIGHT="0" MARGINWIDTH="0">\r
+\r
+<TABLE BORDER="0" CELLSPACING="20" CELLPADDING="0" ALIGN="center">\r
+<TR>\r
+       <TD NOWRAP><A HREF="index.html">termlib.js home</A></TD>\r
+       <TD>|</TD>\r
+       <TD NOWRAP>multiple terminal test</TD>\r
+       <TD>|</TD>\r
+       <TD NOWRAP><A HREF="parser_sample.html">sample parser</A></TD>\r
+       <TD>|</TD>\r
+       <TD NOWRAP><A HREF="faq.html">faq</A></TD>\r
+       <TD>|</TD>\r
+       <TD NOWRAP><A HREF="readme.txt" TITLE="readme.txt (text/plain)">documentation</A></TD>\r
+</TR>\r
+</TABLE>\r
+\r
+<TABLE BORDER="0" CELLSPACING="20" CELLPADDING="0">\r
+       <TR><TD NOWRAP>\r
+               Multiple Terminal Test<BR>&nbsp;\r
+       </TD></TR>\r
+       <TR><TD NOWRAP>\r
+               <A HREF="javascript:termOpen(1)" onfocus="if(this.blur)this.blur();" onmouseover="window.status='terminal 1'; return true" onmouseout="window.status=''; return true" CLASS="termopen">&gt; open terminal 1 &nbsp;</A>\r
+       </TD></TR>\r
+       <TR><TD NOWRAP>\r
+               <A HREF="javascript:termOpen(2)" onfocus="if(this.blur)this.blur();" onmouseover="window.status='terminal 2'; return true" onmouseout="window.status=''; return true" CLASS="termopen">&gt; open terminal 2 &nbsp;</A>\r
+       </TD></TR>\r
+       <TR><TD NOWRAP CLASS="lh15">\r
+               &nbsp;<BR>\r
+               (c) mass:werk,<BR>N. Landsteiner 2003-2005<BR>\r
+               <A HREF="http://www.masswerk.at/" TARGET="_blank">http://www.masswerk.at</A>\r
+       </TD></TR>\r
+</TABLE>\r
+\r
+<DIV ID="termDiv1" STYLE="position:absolute; top:20px; left:100px;"></DIV>\r
+<DIV ID="termDiv2" STYLE="position:absolute; top:20px; left:100px;"></DIV>\r
+\r
+</BODY>\r
+</HTML>
\ No newline at end of file
diff --git a/unmaintained/webapps/fjsc/resources/termlib/parser_sample.html b/unmaintained/webapps/fjsc/resources/termlib/parser_sample.html
new file mode 100644 (file)
index 0000000..b332af1
--- /dev/null
@@ -0,0 +1,293 @@
+<HTML>\r
+<HEAD>\r
+       <TITLE>termlib Sample Parser</TITLE>\r
+       <SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript" SRC="termlib.js"></SCRIPT>\r
+       <SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript" SRC="termlib_parser.js"></SCRIPT>\r
+\r
+<SCRIPT LANGUAGE="JavaScript" TYPE="text/javascript">\r
+<!--\r
+\r
+/*\r
+  test sample for termlib.js and termlib_parser.js\r
+\r
+  (c) Norbert Landsteiner 2005\r
+  mass:werk - media environments\r
+  <http://www.masswerk.at>\r
+\r
+*/\r
+\r
+var term;\r
+\r
+var helpPage=[\r
+       '%CS%+r Terminal Help %-r%n',\r
+       '  This is just a sample to demonstrate command line parsing.',\r
+       ' ',\r
+       '  Use one of the following commands:',\r
+       '     clear [-a] .......... clear the terminal',\r
+       '                           option "a" also removes the status line',\r
+       '     number -n<value> .... return value of option "n" (test for options)',\r
+       '     repeat -n<value> .... repeats the first argument n times (another test)',\r
+       '     login <username> .... sample login (test for raw mode)',\r
+       '     exit ................ close the terminal (same as <ESC>)',\r
+       '     help ................ show this help page',\r
+       ' ',\r
+       '  other input will be echoed to the terminal as a list of parsed arguments',\r
+       '  in the format <argument index> <quoting level> "<parsed value>".',\r
+       ' '\r
+];\r
+\r
+function termOpen() {\r
+       if (!term) {\r
+               term=new Terminal(\r
+                       {\r
+                               x: 220,\r
+                               y: 70,\r
+                               termDiv: 'termDiv',\r
+                               ps: '[guest]$',\r
+                               initHandler: termInitHandler,\r
+                               handler: commandHandler\r
+                       }\r
+               );\r
+               if (term) term.open();\r
+       }\r
+       else if (term.closed) {\r
+               term.open();\r
+       }\r
+       else {\r
+               term.focus();\r
+       }\r
+}\r
+\r
+function termInitHandler() {\r
+       // output a start up screen\r
+       this.write(\r
+               [\r
+                       TermGlobals.center('####################################################', 80),\r
+                       TermGlobals.center('#                                                  #', 80),\r
+                       TermGlobals.center('#           termlib.js - Sample Parser             #', 80),\r
+                       TermGlobals.center('#  Input is echoed as a list of parsed arguments.  #', 80),\r
+                       TermGlobals.center('#                                                  #', 80),\r
+                       TermGlobals.center('#  Type "help" for commands.                       #', 80),\r
+                       TermGlobals.center('#                                                  #', 80),\r
+                       TermGlobals.center('#  (c) N. Landsteiner 2005;  www.masswerk.at       #', 80),\r
+                       TermGlobals.center('#                                                  #', 80),\r
+                       TermGlobals.center('####################################################', 80),\r
+                       '%n'\r
+               ]\r
+       );\r
+       // set a double status line\r
+       this.statusLine('', 8,2); // just a line of strike\r
+       this.statusLine(' +++ This is just a test sample for command parsing. Type "help" for help. +++');\r
+       this.maxLines -= 2;\r
+       // and leave with prompt\r
+       this.prompt();\r
+}\r
+\r
+function commandHandler() {\r
+       this.newLine();\r
+       // check for raw mode first (should not be parsed)\r
+       if (this.rawMode) {\r
+               if (this.env.getPassword) {\r
+                       // sample password handler (lineBuffer == stored username ?)\r
+                       if (this.lineBuffer == this.env.username) {\r
+                               this.user = this.env.username;\r
+                               this.ps = '['+this.user+']>';\r
+                       }\r
+                       else {\r
+                               this.type('Sorry.');\r
+                       }\r
+                       this.env.username = '';\r
+                       this.env.getPassword = false;\r
+               }\r
+               // leave in normal mode\r
+               this.rawMode = false;\r
+               this.prompt();\r
+               return;\r
+       }\r
+       // normal command parsing\r
+       // just call the termlib_parser with a reference of the calling Terminal instance\r
+       // parsed arguments will be imported in this.argv,\r
+       // quoting levels per argument in this.argQL (quoting character or empty)\r
+       // cursor for arguments is this.argc (used by parserGetopt)\r
+       // => see 'termlib_parse.js' for configuration and details\r
+       parseLine(this);\r
+       if (this.argv.length == 0) {\r
+               // no commmand line input\r
+       }\r
+       else if (this.argQL[0]) {\r
+           // first argument quoted -> error\r
+               this.write("Syntax error: first argument quoted.");\r
+       }\r
+       else {\r
+               var cmd = this.argv[this.argc++];\r
+               /*\r
+                 process commands now\r
+                 1st argument: this.argv[this.argc]\r
+               */\r
+               if (cmd == 'help') {\r
+                       this.write(helpPage);\r
+               }\r
+               else if (cmd == 'clear') {\r
+                       // get options\r
+                       var opts = parserGetopt(this, 'aA');\r
+                       if (opts.a) {\r
+                               // discard status line on opt "a" or "A"\r
+                               this.maxLines = this.conf.rows;\r
+                       }\r
+                       this.clear();\r
+               }\r
+               else if (cmd == 'number') {\r
+                       // test for value options\r
+                       var opts = parserGetopt(this, 'n');\r
+                       if (opts.illegals.length) this.type('illegal option. usage: number -n<value>')\r
+                       else if ((opts.n) && (opts.n.value != -1)) this.type('option value: '+opts.n.value)\r
+                       else this.type('usage: number -n<value>');\r
+               }\r
+               else if (cmd == 'repeat') {\r
+                       // another test for value options\r
+                       var opts = parserGetopt(this, 'n');\r
+                       if (opts.illegals.length) this.type('illegal option. usage: repeat -n<value> <string>')\r
+                       else if ((opts.n) && (opts.n.value != -1)) {\r
+                               // first normal argument is again this.argv[this.argc]\r
+                               var s = this.argv[this.argc];\r
+                               if (typeof s != 'undefined') {\r
+                                       // repeat this string n times\r
+                                       var a = [];\r
+                                       for (var i=0; i<opts.n.value; i++) a[a.length] = s;\r
+                                       this.type(a.join(' '));\r
+                               }\r
+                       }\r
+                       else this.type('usage: repeat -n<value> <string>');\r
+               }\r
+               else if (cmd == 'login') {\r
+                       // sample login (test for raw mode)\r
+                       if ((this.argc == this.argv.length) || (this.argv[this.argc] == '')) {\r
+                               this.type('usage: login <username>');\r
+                       }\r
+                       else {\r
+                               this.env.getPassword = true;\r
+                               this.env.username = this.argv[this.argc];\r
+                               this.write('%+iSample login: repeat username as password.%-i%n');\r
+                               this.type('password: ');\r
+                               // exit in raw mode (blind input)\r
+                               this.rawMode = true;\r
+                               this.lock = false;\r
+                               return;\r
+                       }\r
+               }\r
+               else if (cmd == 'exit') {\r
+                       this.close();\r
+                       return;\r
+               }\r
+               else {\r
+                       // for test purpose just output argv as list\r
+                       // assemble a string of style-escaped lines and output it in more-mode\r
+                       s=' INDEX  QL  ARGUMENT%n';\r
+                       for (var i=0; i<this.argv.length; i++) {\r
+                               s += TermGlobals.stringReplace('%', '%%',\r
+                                               TermGlobals.fillLeft(i, 6) +\r
+                                               TermGlobals.fillLeft((this.argQL[i])? this.argQL[i]:'-', 4) +\r
+                                               '  "' + this.argv[i] + '"'\r
+                                       ) + '%n';\r
+                       }\r
+                       this.write(s, 1);\r
+                       return;\r
+               }\r
+       }\r
+       this.prompt();\r
+}\r
+\r
+\r
+//-->\r
+</SCRIPT>\r
+\r
+<STYLE TYPE="text/css">\r
+body,p,a,td {\r
+       font-family: courier,fixed,swiss,sans-serif;\r
+       font-size: 12px;\r
+       color: #cccccc;\r
+}\r
+.lh15 {\r
+       line-height: 15px;\r
+}\r
+.term {\r
+       font-family: courier,fixed,swiss,sans-serif;\r
+       font-size: 12px;\r
+       color: #33d011;\r
+       background: none;\r
+}\r
+.termReverse {\r
+       color: #111111;\r
+       background: #33d011;\r
+}\r
+a,a:link,a:visited {\r
+       text-decoration: none;\r
+       color: #77dd11;\r
+}\r
+a:hover {\r
+       text-decoration: underline;\r
+       color: #77dd11;\r
+}\r
+a:active {\r
+       text-decoration: underline;\r
+       color: #dddddd;\r
+}\r
+\r
+a.termopen,a.termopen:link,a.termopen:visited {\r
+       text-decoration: none;\r
+       color: #77dd11;\r
+       background: none;\r
+}\r
+a.termopen:hover {\r
+       text-decoration: none;\r
+       color: #222222;\r
+       background: #77dd11;\r
+}\r
+a.termopen:active {\r
+       text-decoration: none;\r
+       color: #222222;\r
+       background: #dddddd;\r
+}\r
+\r
+</STYLE>\r
+</HEAD>\r
+\r
+\r
+<BODY BGCOLOR="#222222" LINK="#77dd11" TEXT="#cccccc" ALINK="#dddddd" VLINK="#77dd11"\r
+TOPMARGIN="0" BOTTOMMARGIN="0" LEFTMARGIN="0" RIGHTMARGIN="0" MARGINHEIGHT="0" MARGINWIDTH="0">\r
+\r
+<TABLE BORDER="0" CELLSPACING="20" CELLPADDING="0" ALIGN="center">\r
+<TR>\r
+       <TD NOWRAP><A HREF="index.html">termlib.js home</A></TD>\r
+       <TD>|</TD>\r
+       <TD NOWRAP><A HREF="multiterm_test.html">multiple terminal test</A></TD>\r
+       <TD>|</TD>\r
+       <TD NOWRAP>sample parser</TD>\r
+       <TD>|</TD>\r
+       <TD NOWRAP><A HREF="faq.html">faq</A></TD>\r
+       <TD>|</TD>\r
+       <TD NOWRAP><A HREF="readme.txt" TITLE="readme.txt (text/plain)">documentation</A></TD>\r
+</TR>\r
+</TABLE>\r
+\r
+<TABLE BORDER="0" CELLSPACING="20" CELLPADDING="0">\r
+       <TR><TD NOWRAP>\r
+               Sample Parser Test<BR>&nbsp;\r
+       </TD></TR>\r
+       <TR><TD NOWRAP>\r
+               <A HREF="javascript:termOpen()" onfocus="if(this.blur)this.blur();" onmouseover="window.status='terminal 1'; return true" onmouseout="window.status=''; return true" CLASS="termopen">&gt; open terminal &nbsp;</A>\r
+       </TD></TR>\r
+       <TR><TD NOWRAP>\r
+               &nbsp;\r
+       </TD></TR>\r
+       <TR><TD NOWRAP CLASS="lh15">\r
+               &nbsp;<BR>\r
+               (c) mass:werk,<BR>N. Landsteiner 2003-2005<BR>\r
+               <A HREF="http://www.masswerk.at/" TARGET="_blank">http://www.masswerk.at</A>\r
+       </TD></TR>\r
+</TABLE>\r
+\r
+<DIV ID="termDiv" STYLE="position:absolute;"></DIV>\r
+\r
+</BODY>\r
+</HTML>
\ No newline at end of file
diff --git a/unmaintained/webapps/fjsc/resources/termlib/readme.txt b/unmaintained/webapps/fjsc/resources/termlib/readme.txt
new file mode 100644 (file)
index 0000000..8a92b9c
--- /dev/null
@@ -0,0 +1,1400 @@
+****  mass:werk termlib.js - JS-WebTerminal Object v1.07  ****\r
+\r
+  (c) Norbert Landsteiner 2003-2005\r
+  mass:werk - media environments\r
+  <http://www.masswerk.at>\r
+\r
+\r
+\r
+\r
+Contents:\r
+\r
+   1  About\r
+   2  Creating a new Terminal Instance\r
+      2.1 Configuration Values\r
+   3  Using the Terminal\r
+      3.1  The Default Handler\r
+      3.2  Input Modes\r
+           3.2.1  Normal Line Input (Command Line Mode)\r
+                  3.2.1.2 Special Keys (ctrlHandler)\r
+           3.2.2  Raw Mode\r
+           3.2.3  Character Mode\r
+      3.3  Other Handlers\r
+           3.3.1  initHandler\r
+           3.3.2  exitHandler\r
+      3.4  Flags for Behaviour Control\r
+   4  Output Methods\r
+           4.1 Terminal.type()\r
+           4.2 Terminal.write()\r
+           4.3 Terminal.typeAt()\r
+           4.4 Terminal.setChar()\r
+           4.5 Terminal.newLine()\r
+           4.6 Terminal.clear()\r
+           4.7 Terminal.statusLine()\r
+           4.8 Terminal.printRowFromString()\r
+           4.9 Terminal.redraw()\r
+   5  Cursor Methods and Editing\r
+           5.1 Terminal.cursorOn()\r
+           5.2 Terminal.cursorOff()\r
+           5.3 Terminal.cursorSet()\r
+           5.4 Terminal.cursorLeft()\r
+           5.5 Terminal.cursorRight()\r
+           5.6 Terminal.backspace()\r
+           5.7 Terminal.fwdDelete()\r
+           5.8 Terminal.isPrintable()\r
+   6  Other Methods of the Terminal Object\r
+           6.1 Terminal.prompt()\r
+           6.2 Terminal.reset()\r
+           6.3 Terminal.open()\r
+           6.4 Terminal.close()\r
+           6.5 Terminal.focus()\r
+           6.6 Terminal.moveTo()\r
+           6.7 Terminal.resizeTo()\r
+           6.8 Terminal.getDimensions()\r
+           6.9 Terminal.rebuild()\r
+   7  Global Static Methods (TermGlobals)\r
+           7.1 TermGlobals.setFocus()\r
+           7.2 TermGlobals.keylock (Global Locking Flag)\r
+           7.3 TermGlobalsText Methods\r
+               7.3.1 TermGlobals.normalize()\r
+               7.3.2 TermGlobals.fillLeft()\r
+               7.3.3 TermGlobals.center()\r
+               7.3.4 TermGlobals.stringReplace()\r
+   8  Localization\r
+   9  Cross Browser Functions\r
+  10  Architecture, Internals\r
+      10.1  Global Entities\r
+      10.2  I/O Architecture\r
+      10.3  Compatibility\r
+  11  History\r
+  12  Example for a Command Line Parser\r
+  13  License\r
+  14  Disclaimer\r
+  15  References\r
+\r
+\r
+\r
+\r
+1  About\r
+\r
+The Terminal library "termlib.js" provides an object oriented constructor and control\r
+methods for a terminal-like DHTML interface.\r
+\r
+"termlib.js" features direct keyboard input and powerful output methods for multiple\r
+instances of the `Terminal' object (including focus control).\r
+\r
+The library was written with the aim of simple usage and a maximum of compatibility with\r
+minimal foot print in the global namespace.\r
+\r
+\r
+A simple example:\r
+\r
+  // creating a terminal and using it\r
+\r
+  var term = new Terminal( {handler: termHandler} );\r
+  term.open();\r
+\r
+  function termHandler() {\r
+    var line = this.lineBuffer;\r
+    this.newLine();\r
+    if (line == "help") {\r
+      this.write(helpPage)\r
+    }\r
+    else if (line == "exit") {\r
+      this.close();\r
+      return;\r
+    }\r
+    else if (line != "") {\r
+      this.write("You typed: "+line);\r
+    }\r
+    this.prompt();\r
+  }\r
+\r
+  var helpPage = [\r
+    "This is the monstrous help page for my groovy terminal.",\r
+    "Commands available:",\r
+    "   help ... print this monstrous help page",\r
+    "   exit ... leave this groovy terminal",\r
+    " ",\r
+    "Have fun!"\r
+  ];\r
+\r
+\r
+You should provide CSS font definitions for the classes ".term" (normal video) and\r
+".termReverse" (reverse video) in a monospaced font.\r
+A sample stylesheet "term_styles.css" comes with this library.\r
+\r
+See the sample application "multiterm_test.html" for a demo of multiple terminals.\r
+\r
+v.1.01: If you configure to use another font class (see 2.1 Configuration Values),\r
+        you must provide a subclass ".termReverse" for reversed video.\r
+\r
+        p.e.: .myFontClass .termReverse {\r
+                /* your definitions for reverse video here */\r
+              }\r
+        \r
+        With the addition of `conf.fontClass' you can now create multiple\r
+        instances with independend appearences.\r
+\r
+\r
+\r
+\r
+2   Creating a new Terminal Instance\r
+\r
+Use the `new' constructor to create a new instance of the Terminal object. You will want\r
+to supply a configuration object as an argument to the constructor. If the `new'\r
+constructor is called without an object as its first argument, default values are used.\r
+\r
+p.e.:\r
+\r
+  // creating a new instance of Terminal\r
+\r
+  var conf= {\r
+    x: 100,\r
+    y: 100,\r
+    cols: 80,\r
+    rows: 24\r
+  }\r
+\r
+  var term = new Term(conf);\r
+  term.open();\r
+\r
+`Terminal.open()' initializes the terminal and makes it visible to the user.\r
+This is handled in by separate method to allow the re-initilization of instances\r
+previously closed.\r
+\r
+NOTE:\r
+The division element (or NS-layer) that holds the terminal must be present when calling\r
+`Terminal.open()'. So you must not call this method from the header of a HTML-document at\r
+compile time.\r
+\r
+\r
+\r
+2.1 Configuration Values\r
+\r
+Set any of these values in your configuration object to override:\r
+\r
+  \r
+  LABEL                     DEFAULT VALUE    COMMENT\r
+  \r
+  x                                   100    terminal's position x in px\r
+  y                                   100    terminal's position y in px\r
+  divDiv                        'termDiv'    id of terminals CSS division\r
+  bgColor                       '#181818'    background color (HTML hex value)\r
+  frameColor                    '#555555'    frame color (HTML hex value)\r
+  frameWidth                            1    frame border width in px\r
+  fontClass                        'term'    class name of CSS font definition to use\r
+  cols                                 80    number of cols per row\r
+  rows                                 24    number of rows\r
+  rowHeight                            15    a row's line-height in px\r
+  blinkDelay                          500    delay for cursor blinking in milliseconds\r
+  crsrBlinkMode                     false    true for blinking cursor\r
+  crsrBlockMode                      true    true for block-cursor else underscore\r
+  DELisBS                           false    handle <DEL> as <BACKSPACE>\r
+  printTab                           true    handle <TAB> as printable (prints as space)\r
+  printEuro                          true    handle unicode 0x20AC (Euro sign) as printable\r
+  catchCtrlH                         true    handle ^H as <BACKSPACE>\r
+  closeOnESC                         true    close terminal on <ESC>\r
+  historyUnique                     false    prevent consecutive and identical entries in history\r
+  id                                    0    terminal id\r
+  ps                                  '>'    prompt string\r
+  greeting      '%+r Terminal ready. %-r'    string for greeting if no initHandler is used\r
+  handler              termDefaultHandler    reference to handler for command interpretation\r
+  ctrlHandler                        null    reference to handler called on uncatched special keys\r
+  initHandler                        null    reference to handler called at end of init()\r
+  exitHandler                        null    reference to handler called on close()\r
+\r
+\r
+At least you will want to specify `handler' to implement your own command parser.\r
+\r
+Note: While `id' is not used by the Termninal object, it provides an easy way to identify\r
+multiple terminals by the use of "this.id". (e.g.: "if (this.id == 1) startupterm = true;")\r
+\r
+p.e.:\r
+\r
+  // creating two individual Terminal instances\r
+\r
+  var term1 = new Terminal(\r
+    {\r
+      id: 1,\r
+      x: 200,\r
+      y: 10,\r
+      cols: 80,\r
+      rows: 12,\r
+      greeting: "*** This is Terminal 1 ***",\r
+      handler: myTerminalHandler\r
+    }\r
+  );\r
+  term1.open();\r
+\r
+  var term2 = new Terminal(\r
+    {\r
+      id: 2,\r
+      x, 200,\r
+      y: 220,\r
+      cols: 80\r
+      rows: 12,\r
+      greeting: "*** This is Terminal 2 ***",\r
+      handler: myTerminalHandler\r
+    }\r
+  );\r
+  term2.open();\r
+\r
+\r
+\r
+\r
+3   Using the Terminal\r
+\r
+There are 4 different handlers that are called by a Terminal instance to process input and\r
+some flags to control the input mode and behaviour.\r
+\r
+\r
+\r
+3.1 The Default Handler (a simlple example for input handling)\r
+\r
+If no handlers are defined in the configuration object, a default handler is called to\r
+handle a line of user input. The default command line handler `termDefaultHandler' just\r
+closes the command line with a new line and echos the input back to the user:\r
+\r
+  function termDefaultHandler() {\r
+    this.newLine();\r
+    if (this.lineBuffer != '') {\r
+      this.type('You typed: '+this.lineBuffer);\r
+      this.newLine();\r
+    }\r
+    this.prompt();\r
+  }\r
+\r
+First you may note that the instance is refered to as `this'. So you need not worry about\r
+which Terminal instance is calling your handler. As the handler is entered, the terminal\r
+is locked for user input and the cursor is off. The current input is available as a string\r
+value in `this.lineBuffer'.\r
+\r
+The method `type(<text>)' just does what it says and types a string at the current cursor\r
+position to the terminal screen.\r
+\r
+`newLine()' moves the cursor to a new line.\r
+\r
+The method `prompt()' adds a new line if the cursor isn't at the start of a line, outputs\r
+the prompt string (as specified in the configuration), activates the cursor, and unlocks\r
+the terminal for further input. While you're doing normal command line processing, always\r
+call `prompt()' when leaving your handler.\r
+\r
+In fact this is all you need to create your own terminal application. Please see at least\r
+the method `write()' for a more powerful output method.\r
+\r
+Below we will refer to all methods of the Terminal object as `Terminal.<method>()'.\r
+You can call them as `this.<method>()' in a handler or as methods of your named instance\r
+in other context (e.g.: "myTerminal.close()").\r
+\r
+[In technical terms these methods are methods of the Terminal's prototype object, while\r
+the properties are properties of a Termninal instance. Since this doesn't make any\r
+difference to your script, we'll refer to both as `Terminal.<method-or-property>'.]\r
+\r
+\r
+\r
+3.2 Input Modes\r
+\r
+3.2.1 Normal Line Input (Command Line Mode)\r
+\r
+By default the terminal is in normal input mode. Any printable characters in the range of\r
+ASCII 0x20 - 0xff are echoed to the terminal and may be edited with the use of the cursor\r
+keys and the <BACKSPACE> key.\r
+The cursor keys UP and DOWN let the user browse in the command line history (the list of\r
+all commands issued previously in this Terminal instance).\r
+\r
+If the user presses <CR> or <ENTER>, the line is read from the terminal buffer, converted\r
+to a string, and placed in `Terminal.lineBuffer' (-> `this.lineBuffer') for further use.\r
+The terminal is then locked for further input and the specified handler\r
+(`Terminal.handler') is called.\r
+\r
+\r
+3.2.1.2 Special Keys (ctrlHandler)\r
+\r
+If a special character (ASCII<0x20) or an according combination of <CTRL> and a key is\r
+pressed, which is not caught for editing or "enter", and a handler for `ctrlHandler' is\r
+specified, this handler is called.\r
+The ASCII value of the special character is available in `Terminal.inputChar'. Please note\r
+that the terminal is neither locked, nor is the cursor off - all further actions have to\r
+be controlled by `ctrlHandler'. (The tracking of <CTRL>-<key> combinations as "^C" usually\r
+works but cannot be taken for granted.)\r
+\r
+A named reference of the special control values in POSIX form (as well as the values of\r
+the cursor keys [LEFT, RIGHT, UP, DOWN]) is available in the `termKey' object.\r
+\r
+p.e.:\r
+\r
+  // a simple ctrlHandler\r
+\r
+  function myCtrlHandler() {\r
+    if (this.inputChar == termKey.ETX) {\r
+      // exit on ^C (^C == ASCII 0x03 == <ETX>)\r
+      this.close();\r
+    }\r
+  }\r
+\r
+If no `ctrlHandler' is specified, control keys are ignored (default).\r
+\r
+\r
+3.2.2 Raw Mode\r
+\r
+If the flag `Terminal.rawMode' is set to a value evaluating to `true', no special keys are\r
+tracked but <CR> and <ENTER> (and <ESC>, if the flag `Terminal.closeOnESC' is set).\r
+The input is NOT echoed to the terminal. All printable key values [0x20-0xff] are\r
+transformed to characters and added to `Terminal.lineBuffer' sequentially. The command\r
+line input is NOT added to the history.\r
+\r
+This mode is especially suitable for password input.\r
+\r
+p.e.:\r
+\r
+  // using raw mode for password input\r
+\r
+  function myTermHandler() {\r
+    this.newLine();\r
+    // we stored a flag in Terminal.env to track the status\r
+    if (this.env.getpassword) {\r
+      // leave raw mode\r
+      this.rawMode = false;\r
+      if (passwords[this.env.user] == this.lineBuffer) {\r
+        // matched\r
+        this.type('Welcome '+this.env.user);\r
+        this.env.loggedin = true;\r
+      }\r
+      else {\r
+        this.type('Sorry.');\r
+      }\r
+      this.env.getpassword = false;\r
+    }\r
+    else {\r
+      // simple parsing\r
+      var args = this.lineBuffer.split(' ');\r
+      var cmd = args[0];\r
+      if (cmd == 'login') {\r
+        var user = args[1];\r
+        if (!user) {\r
+          this.type('usage: login <username>');\r
+        }\r
+        else {\r
+          this.env.user = user;\r
+          this.env.getpassword = true;\r
+          this.type('password? ');\r
+          // enter raw mode\r
+          this.rawMode = true;\r
+          // leave without prompt so we must unlock first\r
+          this.lock = false;\r
+          return;\r
+        }\r
+      }\r
+      /*\r
+        other actions ...\r
+      */\r
+    }\r
+    this.prompt();\r
+  }\r
+\r
+In this example a handler is set up to process the command "login <username>" and ask for\r
+a password for the given user name in raw mode. Note the use of the object `Terminal.env'\r
+which is just an empty object set up at the creation of the Terminal instance. Its only\r
+purpose is to provide an individual namespace for private data to be stored by a Terminal\r
+instance.\r
+\r
+NOTE: The flag `Terminal.lock' is used to control the keyboard locking. If we would not\r
+set this to `false' before leaving in raw mode, we would be caught in dead-lock, since no\r
+input could be entered and our handler wouldn't be called again. - A dreadful end of our\r
+terminal session.\r
+\r
+NOTE: Raw mode utilizes the property `Terminal.lastLine' to collect the input string.\r
+This is normally emty, when a handler is called. This is not the case if your script left\r
+the input process on a call of ctrlHandler. You should clear `Terminal.lastLine' in such\r
+a case, if you're going to enter raw mode immediatly after this.\r
+\r
+\r
+3.2.3 Character Mode\r
+\r
+If the flag `Terminal.charMode' is set to a value evaluating to `true', the terminal is in\r
+character mode. In this mode the numeric ASCII value of the next key typed is stored in\r
+`Terminal.inputChar'. The input is NOT echoed to the terminal. NO locking or cursor\r
+control is performed and left to the handler.\r
+You can use this mode to implement your editor or a console game.\r
+`Terminal.charMode' takes precedence over `Terminal.rawMode'.\r
+\r
+p.e.: \r
+\r
+  // using char mode\r
+\r
+  function myTermHandler() {\r
+    // this is the normal handler\r
+    this.newLine();\r
+    // simple parsing\r
+    var args = this.lineBuffer.split(' ');\r
+    var cmd = args[0];\r
+    if (cmd == 'edit') {\r
+      // init the editor\r
+      myEditor(this);\r
+      // redirect the handler to editor\r
+      this.handler = myEditor;\r
+      // leave in char mode\r
+      this.charMode = true;\r
+      // show cursor\r
+      this.cursorOn();\r
+      // don't forget unlocking\r
+      this.lock = false;\r
+      return;\r
+    }\r
+    /*\r
+      other actions ...\r
+    */\r
+    this.prompt();\r
+  }\r
+\r
+  function myEditor(initterm) {\r
+    // our dummy editor (featuring modal behaviour)\r
+    if (initterm) {\r
+      // perform initialization tasks\r
+      initterm.clear();\r
+      initterm.write('this is a simple test editor; leave with <ESC> then "q"%n%n');\r
+      initterm.env.mode = '';\r
+      // store a reference of the calling handler\r
+      initterm.env.handler = initterm.handler;\r
+      return;\r
+    }\r
+    // called as handler -> lock first\r
+    this.lock=true;\r
+    // hide cursor\r
+    this.cursorOff();\r
+    var key = this.inputChar;\r
+    if (this.env.mode == 'ctrl') {\r
+      // control mode\r
+      if (key == 113) {\r
+        // "q" => quit\r
+        // leave charMode and reset the handler to normal\r
+        this.charMode = false;\r
+        this.handler = this.env.handler;\r
+        // clear the screen\r
+        this.clear();\r
+        // prompt and return\r
+        this.prompt();\r
+        return;\r
+      }\r
+      else {\r
+        // leave control mode\r
+        this.env.mode = '';\r
+      }\r
+    }\r
+    else {\r
+      // edit mode\r
+      if (key == termKey.ESC) {\r
+        // enter control mode\r
+        // we'd better indicate this in a status line ...\r
+        this.env.mode = 'ctrl';\r
+      }\r
+      else if (key == termKey.LEFT) {\r
+        // cursor left\r
+      }\r
+      else if (key == termKey.RIGHT) {\r
+        // cursor right\r
+      }\r
+      if (key == termKey.UP) {\r
+        // cursor up\r
+      }\r
+      else if (key == termKey.DOWN) {\r
+        // cursor down\r
+      }\r
+      else if (key == termKey.CR) {\r
+        // cr or enter\r
+      }\r
+      else if (key == termKey.BS) {\r
+        // backspace\r
+      }\r
+      else if (key == termKey.DEL) {\r
+        // fwd delete\r
+        // conf.DELisBS is not evaluated in charMode!\r
+      }\r
+      else if (this.isPrintable(key)) {\r
+        // printable char - just type it\r
+        var ch = String.fromCharCode(key);\r
+        this.type(ch);\r
+      }\r
+    }\r
+    // leave unlocked with cursor\r
+    this.lock = false;\r
+    this.cursorOn();\r
+  }\r
+\r
+\r
+Note the redirecting of the input handler to replace the command line handler by the\r
+editor. The method `Terminal.clear()' clears the terminal.\r
+`Terminal.cursorOn()' and `Terminal.cursorOff()' are used to show and hide the cursor.\r
+\r
+\r
+\r
+3.3 Other Handlers\r
+\r
+There are two more handlers that can be specified in the configuration object:\r
+\r
+\r
+3.3.1 initHandler\r
+\r
+`initHandler' is called at the end of the initialization triggered by `Terminal.open()'.\r
+The default action - if no `initHandler' is specified - is:\r
+\r
+  // default initilization\r
+\r
+  this.write(this.conf.greeting);\r
+  this.newLine();\r
+  this.prompt();\r
+\r
+Use `initHandler' to perform your own start up tasks (e.g. show a start up screen). Keep\r
+in mind that you should unlock the terminal and possibly show a cursor to give the\r
+impression of a usable terminal.\r
+\r
+\r
+3.3.2  exitHandler\r
+\r
+`exitHandler' is called by `Terminal.close()' just before hiding the terminal. You can use\r
+this handler to implement any tasks to be performed on exit. Note that this handler is\r
+called even if the terminal is closed on <ESC> outside of your inputHandlers control.\r
+\r
+See the file "multiterm_test.html" for an example.\r
+\r
+\r
+\r
+3.4   Overview: Flags for Behaviour Control\r
+\r
+These falgs are accessible as `Terminal.<flag>' at runtime. If not stated else, the\r
+initial value may be specified in the configuration object.\r
+The configuration object and its properties are accessible at runtime via `Terminal.conf'.\r
+\r
+\r
+  NAME                      DEFAULT VALUE    MEANING\r
+\r
+  blink_delay                         500    delay for cursor blinking in milliseconds.\r
+\r
+  crsrBlinkMode                     false    true for blinking cursor.\r
+                                             if false, cursor is static.\r
+  \r
+  crsrBlockMode                      true    true for block-cursor else underscore.\r
+\r
+  DELisBS                           false    handle <DEL> as <BACKSPACE>.\r
+\r
+  printTab                           true    handle <TAB> as printable (prints as space)\r
+                                             if false <TAB> is handled as a control character\r
+\r
+  printEuro                          true    handle the euro sign as valid input char.\r
+                                             if false char 0x20AC is printed, but not accepted\r
+                                             in the command line\r
+\r
+  catchCtrlH                         true    handle ^H as <BACKSPACE>.\r
+                                             if false, ^H must be tracked by a custom\r
+                                             ctrlHandler.\r
+\r
+  closeOnESC                         true    close terminal on <ESC>.\r
+                                             if true, <ESC> is not available for ctrHandler.\r
+\r
+\r
+  historyUnique                     false    unique history entries.\r
+                                             if true, entries that are identical to the last\r
+                                             entry in the user history will not be added.\r
+\r
+  charMode                          false    terminal in character mode (tracks next key-code).\r
+                                             (runtime only)\r
\r
+  rawMode                           false    terminal in raw mode (no echo, no editing).\r
+                                             (runtime only)\r
+\r
+\r
+Not exactly a flag but useful:\r
+\r
+  ps                                  '>'    prompt string.\r
+\r
+\r
+\r
+\r
+4  Output Methods\r
+\r
+Please note that any output to the terminal implies an advance of the cursor. This means,\r
+that if your output reaches the last column of your terminal, the cursor is advanced and\r
+a new line is opened automatically. This procedure may include scrolling to make room for\r
+the new line. While this is not of much interest for most purposes, please note that, if\r
+you output a string of length 80 to a 80-columns-terminal, and a new line, and another\r
+string, this will result in an empty line between the two strings.\r
+\r
+\r
+4.1  Terminal.type( <text> [,<stylevector>] )\r
+\r
+Types the string <text> at the current cursor position to the terminal. Long lines are\r
+broken where the last column of the terminal is reached and continued in the next line.\r
+`Terminal.write()' does not support any kind of arbitrary line breaks. (This is just a\r
+basic output routine. See `Terminal.write()' for a more powerful output method.)\r
+\r
+A bitvector may be supplied as an optional second argument to represent a style or a\r
+combination of styles. The meanings of the bits set are interpreted as follows:\r
+\r
+<stylevector>:\r
+\r
+   1 ... reverse    (2 power 0)\r
+   2 ... underline  (2 power 1)\r
+   4 ... italics    (2 power 2)\r
+   8 ... strike     (2 power 3)\r
+\r
+So "Terminal.type( 'text', 5 )" types "text" in italics and reverse video.\r
+\r
+Note:\r
+There is no bold, for most monospaced fonts (including Courier) tend to render wider in\r
+bold. Since this would bring the terminal's layout out of balance, we just can't use bold\r
+as a style. - Sorry.\r
+\r
+The HTML-representation of this styles are defined in "TermGlobals.termStyleOpen" and\r
+"TermGlobals.termStyleClose".\r
+\r
+\r
+4.2  Terminal.write( <text> [,<usemore>] )\r
+\r
+Writes a text with markup to the terminal. If an optional second argument evaluates to\r
+true, a UN*X-style utility like `more' is used to page the text. The text may be supplied\r
+as a single string (with newline character "\n") or as an array of lines. Any other input\r
+is transformed to a string value before output.\r
+\r
+4.2.1 Mark-up:\r
+\r
+`Terminal.write()' employs a simple mark-up with the following syntax:\r
+\r
+<markup>: %([+|-]<style>|n|CS|%)\r
+   \r
+   where "+" and '-' are used to switch on and off a style, where\r
+   \r
+   <style>:\r
+   \r
+      "i" ... italics\r
+      "r" ... reverse\r
+      "s" ... strike\r
+      "u" ... underline\r
+      \r
+      "p" ... reset to plain ("%+p" == "%-p")\r
+    \r
+   styles may be combined and may overlap. (e.g. "This is %+rREVERSE%-r, %+uUNDER%+iSCORE%-u%-i.")\r
+   \r
+   "%n"  represents a new line (in fact "\n" is translated to "%n" before processing)\r
+   \r
+   "%CS" clears the terminal screen\r
+   \r
+   "%%"  represents the percent character ('%')\r
+\r
+\r
+4.2.2 Buffering:\r
+\r
+`Terminal.write()' writes via buffered output to the terminal. This means that the\r
+provided text is rendered to a buffer first and then only the visible parts are transfered\r
+to the terminal display buffers. This avoids scrolling delays for long output.\r
+\r
+4.2.3 UseMore Mode:\r
+\r
+The buffering of `Terminal.write()' allows for pagewise output, which may be specified by\r
+a second boolean argument. If <usemore> evaluates to `true' and the output exceeds the\r
+range of empty rows on the terminal screen, `Terminal.write()' performs like the UN*X\r
+utility `more'. The next page may be accessed by hitting <SPACE> while <q> terminates\r
+paging and returns with the prompt (-> `Terminal.prompt()').\r
+\r
+To use this facillity make sure to return immediatly after calling `Terminal.write()' in\r
+order to allow the more-routine to track the user input.\r
+The terminal is set to "charMode == false" afterwards.\r
+\r
+p.e.:\r
+\r
+  // using Terminal.write as a pager\r
+\r
+  function myTermHandler() {\r
+    this.newLine();\r
+    var args = this.lineBuffer.split(' ');\r
+    var cmd = args[0];\r
+    if (cmd == 'more') {\r
+      var page = args[1];\r
+      if (myPages[page]) {\r
+        // Terminal.write as a pager\r
+        this.write(myPages[page], true);\r
+        return;\r
+      }\r
+      else {\r
+        // Terminal.write for simple output\r
+        this.write('no such page.');\r
+      }\r
+    }\r
+    /*\r
+      other actions ...\r
+    */\r
+    this.prompt();\r
+  }\r
+\r
+\r
+4.3  Terminal.typeAt( <r>, <c>, <text> [,<stylevector>] )\r
+\r
+Output the string <text> at row <r>, col <c>.\r
+For <stylevector> see `Terminal.type()'.\r
+`Terminal.typeAt()' does not move the cursor.\r
+\r
+\r
+4.4  Terminal.setChar( <charcode>, <r>, <c> [,<stylevector>] )\r
+\r
+Output a single character represented by the ASCII value of <charcode> at row <r>, col <c>.\r
+For <stylevector> see `Terminal.type()'.\r
+\r
+\r
+4.5  Terminal.newLine()\r
+\r
+Moves the cursor to the first column of the next line and performs scrolling, if needed.\r
+\r
+\r
+4.6  Terminal.clear()\r
+\r
+Clears the terminal screen. (Returns with cursor off.)\r
+\r
+\r
+4.7  Terminal.statusLine( <text> [,<stylevector> [,<lineoffset>]] )\r
+\r
+All output acts on a logical screen with the origin at row 0 / col 0. While the origin is\r
+fixed, the logical width and height of the terminal are defined by `Terminal.maxCols' and\r
+`Terminal.maxLines'. These are set to the configuration dimensions at initilization and by\r
+`Terminal.reset()', but may be altered at any moment. Please note that there are no bounds\r
+checked, so make sure that `Terminal.maxCols' and `Terminal.maxLines' are less or equal\r
+to the configuration dimensions.\r
+\r
+You may want to decrement `Terminal.maxLines' to keep space for a reserved status line.\r
+`Terminal.statusLine( <text>, <style> )' offers a simple way to type a text to the last\r
+line of the screen as defined by the configuration dimensions.\r
+\r
+  // using statusLine()\r
+\r
+  function myHandler() {\r
+    // ...\r
+    // reserve last line\r
+    this.maxLines = term.conf.rows-1;\r
+    // print to status line in reverse video\r
+    this.statusLine("Status: <none>", 1);\r
+    // ...\r
+  }\r
+\r
+For multiple status lines the optional argument <lineoffset> specifies the addressed row,\r
+where 1 is the line closest to the bottom, 2 the second line from the bottom and so on.\r
+(default: 1)\r
+\r
+\r
+4.8  Terminal.printRowFromString( <r> , <text> [,<stylevector>] )\r
+\r
+Outputs the string <text> to row <r> in the style of an optional <stylevector>.\r
+If the string's length exceeds the length of the row  (up to `Terminal.conf.cols'), extra\r
+characteres are ignored, else any extra space is filled with character code 0 (prints as\r
+<SPACE>).\r
+The valid range for <row> is: 0 >= <row> < `Terminal.maxLines'.\r
+`Terminal.printRowFromString()' does not set the cursor.\r
+\r
+You could, for example, use this method to output a line of a text editor's buffer.\r
+\r
+p.e.:\r
+\r
+  // page refresh function of a text editor\r
+\r
+  function myEditorRefresh(termref, topline) {\r
+    // termref: reference to Terminal instance\r
+    // topline: index of first line to print\r
+    // lines of text are stored in termref.env.lines\r
+    for (var r=0; r<termref.maxLines; r++) {\r
+      var i = topline + r;\r
+      if (i < termref.env.lines.length) {\r
+        // output stored line\r
+        termref.printRowFromString(r, termref.env.lines[i]);\r
+      }\r
+      else {\r
+        // output <tilde> for empty line\r
+        termref.printRowFromString(r, '~');\r
+      }\r
+    }\r
+    // set cursor to origin\r
+    termref.r = termref.c = 0; // same as termref.cursorSet(0, 0);\r
+  }\r
+\r
+\r
+4.9  Terminal.redraw( <row> )\r
+\r
+Basic function to redraw a terminal row <row> according to screen buffer values.\r
+For hackers only. (e.g.: for a console game, hack screen buffers first and redraw all\r
+changed rows at once.)\r
+\r
+\r
+\r
+\r
+5  Cursor Methods and Editing\r
+\r
+\r
+5.1  Terminal.cursorOn()\r
+\r
+Show the cursor.\r
+\r
+\r
+5.2  Terminal.cursorOff()\r
+\r
+Hide the cursor.\r
+\r
+\r
+5.3  Terminal.cursorSet( <r>, <c> )\r
+\r
+Set the cursor position to row <r> column <c>.\r
+`Terminal.cursorSet()' preserves the cursor's active state (on/off).\r
+\r
+\r
+5.4  Terminal.cursorLeft()\r
+\r
+Move the cursor left. (Movement is restricted to the logical input line.)\r
+`Terminal.cursorLeft()' preserves the cursor's active state (on/off).\r
+\r
+\r
+5.5  Terminal.cursorRight()\r
+\r
+Move the cursor right. (Movement is restricted to the logical input line.)\r
+`Terminal.cursorRight()' preserves the cursor's active state (on/off).\r
+\r
+\r
+5.6  Terminal.backspace()\r
+\r
+Delete the character left from the cursor, if the cursor is not in first position of the\r
+logical input line.\r
+`Terminal.backspace()' preserves the cursor's active state (on/off).\r
+\r
+\r
+5.7  Terminal.fwdDelete()\r
+\r
+Delete the character under the cursor.\r
+`Terminal.fwdDelete()' preserves the cursor's active state (on/off).\r
+\r
+\r
+5.8  Terminal.isPrintable( <key code> [,<unicode page 1 only>] )\r
+\r
+Returns `true' if the character represented by <key code> is printable with the current\r
+settings. An optional second argument <unicode page 1 only> limits the range of valid\r
+values to 255 with the exception of the Euro sign, if the flag `Terminal.printEuro' is set.\r
+(This second flag is used for input methods but not for output methods. So you may only\r
+enter portable characters, but you may print others to the terminals screen.)\r
+\r
+\r
+\r
+\r
+6  Other Methods of the Terminal Object\r
+\r
+6.1  Terminal.prompt()\r
+\r
+Performes the following actions:\r
+\r
+  * advance the cursor to a new line, if the cursor is not at 1st column\r
+  * type the prompt string (as specified in the configuaration object)\r
+  * show the cursor\r
+  * unlock the terminal\r
+\r
+(The value of the prompt string can be accessed and changed in `Terminal.ps'.)\r
+\r
+\r
+6.2  Terminal.reset()\r
+\r
+Resets the terminal to sane values and clears the terminal screen.\r
+\r
+\r
+6.3  Terminal.open()\r
+\r
+Opens the terminal. If this is a fresh instance, the HTML code for the terminal is\r
+generated. On re-entry the terminal's visibility is set to `true'. Initialization tasks\r
+are performed and the optional initHandler called. If no initHandler is specified in the\r
+configuration object, the greeting (configuration or default value) is shown and the user\r
+is prompted for input.\r
+\r
+v.1.01: `Terminal.open()' now checks for the existence of the DHTML element as defined in\r
+        `Terminal.conf.termDiv' and returns success.\r
+\r
+\r
+6.4  Terminal.close()\r
+\r
+Closes the terminal and hides its visibility. An optional exitHandler (specified in the\r
+configuration object) is called, and finally the flag `Terminal.closed' is set to true. So\r
+you can check for existing terminal instances as you would check for a `window' object\r
+created by `window.open()'.\r
+\r
+p.e.:\r
+\r
+  // check for a terminals state\r
+  // let array "term" hold references to terminals\r
+\r
+  if (term[n]) {\r
+    if (term[n].closed) {\r
+      // terminal exists and is closed\r
+      // re-enter via "term[n].open()"\r
+    }\r
+    else {\r
+      // terminal exists and is currently open\r
+    }\r
+  }\r
+  else {\r
+    // no such terminal\r
+    // create it via "term[n] = new Terminal()"\r
+  }\r
+\r
+\r
+6.5  Terminal.focus()\r
+\r
+Set the keyboard focus to this instance of Terminal. (As `window.focus()'.)\r
+\r
+\r
+6.6  Terminal.moveTo( <x>, <y> )\r
+\r
+Move the terminal to position <x>/<y> in px.\r
+(As `window.moveTo()', but inside the HTML page.)\r
+\r
+\r
+6.7  Terminal.resizeTo( <x>, <y> )\r
+\r
+Resize the terminal to dimensions <x> cols and <y> rows.\r
+<x> must be at least 4, <y> at least 2.\r
+`Terminal.resizeTo()' resets `Terminal.conf.rows', `Terminal.conf.cols',\r
+`Terminal.maxLines', and `Terminal.maxCols' to <y> and <x>, but leaves the instance' state\r
+else unchanged. Clears the terminal's screen and returns success.\r
+\r
+(A bit like `window.resizeTo()', but with rows and cols instead of px.)\r
+\r
+\r
+6.8  Terminal.getDimensions()\r
+\r
+Returns an object with properties "width" and "height" with numeric values for the\r
+terminal's outer dimensions in px. Values are zero (0) if the element is not present or\r
+if the method fails otherwise.\r
+\r
+\r
+6.9  Terminal.rebuild()\r
+\r
+Rebuilds the Terminal object's GUI preserving its state and content.\r
+Use this to change the color theme on the fly.\r
+\r
+p.e.:\r
+\r
+   // change color settings on the fly\r
+   // here: set bgColor to white and font style to "termWhite"\r
+   // method rebuild() updates the GUI without side effects\r
+\r
+   term.conf.bgColor = '#ffffff';\r
+   term.conf.fontClass = 'termWhite';\r
+   term.rebuild();\r
+\r
+\r
+\r
+\r
+7   Global Static Methods (TermGlobals)\r
+\r
+\r
+7.1  TermGlobals.setFocus( <termref> )\r
+\r
+Sets the keyboard focus to the instance referenced by <termref>.\r
+The focus is controlled by `TermGlobals.activeTerm' which may be accessed directly.\r
+See also: `Terminal.focus()'\r
+\r
+\r
+7.2  TermGlobals.keylock (Global Locking Flag)\r
+\r
+The global flag `TermGlobals.keylock' allows temporary keyboard locking without any\r
+other change of state. Use this to free the keyboard for any other resources.\r
+(added in v.1.03)\r
+\r
+\r
+7.3  TermGlobals Text Methods\r
+\r
+There is a small set of methods for common terminal related string tasks:\r
+\r
+\r
+7.3.1  TermGlobals.normalize( <n>, <fieldlength> )\r
+\r
+Converts a number to a string, which is filled at its left with zeros ("0") to the total\r
+length of <filedlength>. (e.g.: "TermGlobals.normalize(1, 2)" => "01")\r
+\r
+\r
+7.3.2  TermGlobals.fillLeft( <value>, <fieldlength> )\r
+\r
+Converts a value to a string and fills it to the left with blanks to <fieldlength>.\r
+\r
+\r
+7.3.3  TermGlobals.center( <text>, <length> )\r
+\r
+Adds blanks at the left of the string <text> until the text would be centered at a line\r
+of length <length>. (No blanks are added to the the right.)\r
+\r
+\r
+7.3.4  TermGlobals.stringReplace( <string1>, <string2>, <text> )\r
+\r
+Replaces all occurences of the string <string1> in <text> with <string2>.\r
+This is just a tiny work around for browsers with no support of RegExp.\r
+\r
+\r
+\r
+\r
+8   Localization\r
+\r
+The strings and key-codes used by the more utility of `Terminal.write()' are the only\r
+properties of "termlib.js" that may need localization. These properties are defined in\r
+`TermGlobals'. You may override them as needed:\r
+\r
+PROPERTY                                      STANDARD VALUE                 COMMENT\r
+\r
+TermGlobals.lcMorePrompt1                                    ' -- MORE -- '  1st string\r
+TermGlobals.lcMorePromtp1Style                                            1  reverse\r
+TermGlobals.lcMorePrompt2       ' (Type: space to continue, \'q\' to quit)'  appended string\r
+TermGlobals.lcMorePrompt2Style                                            0  plain\r
+TermGlobals.lcMoreKeyAbort                                              113  (key-code: q)\r
+TermGlobals.lcMoreKeyContinue                                            32  (key-code <SPACE>)\r
+\r
+\r
+As "TermGlobals.lcMorePrompt2" is appended to "TermGlobals.lcMorePrompt1" make sure that\r
+the length of the combined strings does not exceed `Terminal.conf.cols'.\r
+\r
+\r
+\r
+\r
+9   Cross Browser Functions\r
+\r
+For DHTML rendering some methods - as needed by the Terminal library - are provided.\r
+These may also be accessed for other purposes.\r
+\r
+\r
+9.1  TermGlobals.writeElement( <element id>, <text> [,<NS4 parent document>] )\r
+\r
+Writes <text> to the DHTML element with id/name <element id>. \r
+<NS4 parent document> is used for NS4 only and specifies an optional reference to a parent\r
+document (default `window.document').\r
+\r
+9.2  TermGlobals.setElementXY( <element id>, <x>, <y> )\r
+\r
+Sets the DHTML element with id/name <element id> to position <x>/<y>.\r
+For NS4 works only with children of the top document (window.document).\r
+\r
+\r
+9.3  TermGlobals.setVisible( <element id>, <value> )\r
+\r
+If <value> evaluates to `true' show DHTML element with id/name <element id> else hide it.\r
+For NS4 works only with children of the top document (window.document).\r
+\r
+\r
+9.4  Custom Fixes for Missing String Methods\r
+\r
+Although `String.fromCharCode' and `String.prototype.charCodeAt' are defined by ECMA-262-2\r
+specifications, a few number of browsers lack them in their JavaScript implementation. At\r
+compile time custom methods are installed to fix this. Please note that they work only\r
+with ASCII characters and values in the range of [0x20-0xff].\r
+\r
+\r
+9.5  TermGlobals.setDisplay( <element id>, <value> )\r
+\r
+Sets the style.display property of the element with id/name <element id> to the given\r
+<value>. (added with v. 1.06)\r
+\r
+\r
+\r
+\r
+10   Architecture, Internals\r
+\r
+10.1  Global Entities\r
+\r
+The library is designed to leave only a small foot print in the namespace while providing\r
+suitable usability:\r
+\r
+  Globals defined in this library:\r
+\r
+    Terminal           (Terminal object, `new' constructor and prototype methods)\r
+    TerminalDefaults   (default configuration, static object)\r
+    termDefaultHandler (default command line handler, static function)\r
+    TermGlobals        (common vars and code for all instances, static object and methods)\r
+    termKey            (named mappings for special keys, static object)\r
+    termDomKeyRef      (special key mapping for DOM key constants, static object)\r
+\r
+\r
+  Globals defined for fixing String methods, if missing\r
+  (String.fromCharCode, String.prototype.charCodeAt):\r
+\r
+    termString_keyref, termString_keycoderef, termString_makeKeyref\r
+\r
+  \r
+  Required CSS classes for font definitions: ".term", ".termReverse".\r
+\r
+\r
+\r
+10.2  I/O Architecture\r
+\r
+The Terminal object renders keyboard input from keyCodes to a line buffer and/or to a\r
+special keyCode buffer. In normal input mode printable input is echoed to the screen\r
+buffers. Special characters like <LEFT>, <RIGHT>, <BACKSPACE> are processed for command\r
+line editing by the internal key-handler `TermGlobals.keyHandler' and act directly on the\r
+screen buffers. On <CR> or <ENTER> the start and end positions of the current line are\r
+evaluated (terminated by ASCII 0x01 at the beginning which separates the prompt from the\r
+user input, and any value less than ASCII 0x20 (<SPACE>) at the right end). Then the\r
+character representation for the buffer values in this range are evaluated and\r
+concatenated to a string stored in `Terminal.lineBuffer'. As this involves some\r
+ASCII-to-String-transformations, the range of valid printable input characters is limited\r
+to the first page of unicode characters (0x0020-0x00ff).\r
+\r
+There are two screen buffers for output, one for character codes (ASCII values) and one\r
+for style codes. Style codes represent combination of styles as a bitvector (see\r
+`Terminal.type' for bit values.) The method `Terminal.redraw(<row>)' finally renders the\r
+buffers values to a string of HTML code, which is written to the HTML entity holding the\r
+according terminal row. The character buffer is a 2 dimensional array\r
+`Terminal.charBuf[<row>][<col>]' with ranges for <row> from 0 to less than\r
+`Terminal.conf.rows' and for <col> from 0 to less than `Terminal.conf.cols'. The style\r
+buffer is a 2 dimensional array `Terminal.styleBuf[<row>][<col>]' with according ranges.\r
+\r
+So every single character is represented by a ASCII code in `Terminal.charBuf' and a\r
+style-vector in `Terminal.styleBuf'. The range of printable character codes is unlimitted\r
+but should be kept to the first page of unicode characters (0x0020-0x00ff) for\r
+compatibility purpose. (c.f. 8.4)\r
+\r
+Keyboard input is first handled on the `KEYDOWN' event by the handler `TermGlobals.keyFix'\r
+to remap the keyCodes of cursor keys to consistent values. (To make them distinctable from\r
+any other possibly printable values, the values of POSIX <IS4> to <IS1> where chosen.)\r
+The mapping of the cursor keys is stored in the properties LEFT, RIGHT, UP, and DOWN of\r
+the global static object `termKey'.\r
+\r
+The main keyboard handler `TermGlobals.keyHandler' (invoked on `KEYPRESS' or by\r
+`TermGlobals.keyFix') does some final mapping first. Then the input is evaluated as\r
+controlled by the flags `Terminal.rawMode' and `Terminal.charMode' with precedence of the\r
+latter. In dependancy of the mode defined and the handlers currently defined, the input\r
+either is ignored, or is internally processed for command line editing, or one of the\r
+handlers is called.\r
+\r
+In the case of the simultanous presecence of two instances of Terminal, the keyboard focus\r
+is controlled via a reference stored in `TermGlobals.activeTerm'. This reference is also\r
+used to evaluate the `this'-context of the key handlers which are methods of the static\r
+Object `TermGlobals'.\r
+\r
+A terminal's screen consists of a HTML-table element residing in the HTML/CSS division\r
+spcified in `Terminal.conf.termDiv'. Any output is handled on a per row bases. The\r
+individual rows are either nested sub-divisions of the main divisions (used for NS4 or\r
+browsers not compatible to the "Gecko" engine) or the indiviual table data elements (<TD>)\r
+of the terminal's inner table (used for browsers employing the "Gecko" engine).\r
+(This implementation was chosen for rendering speed and in order to minimize any screen\r
+flicker.) Any output or change of state in a raw results in the inner HTML contents of a\r
+row's HTML element to be rewritten. Please note that as a result of this a blinking cursor\r
+may cause a flicker in the line containing the cursor's position while displayed by a\r
+browser, which employs the "Gecko" engine.\r
+\r
+\r
+\r
+10.3  Compatibility\r
+\r
+Standard web browsers with a JavaScript implementation compliant to ECMA-262 2nd edition\r
+[ECMA262-2] and support for the anonymous array and object constructs and the anonymous\r
+function construct in the form of "myfunc = function(x) {}" (c.f. ECMA-262 3rd edion\r
+[ECMA262-3] for details). This comprises almost all current browsers but Konquerer (khtml)\r
+and versions of Apple Safari for Mac OS 10.0-10.28 (Safari < 1.1) which lack support for\r
+keyboard events.\r
+\r
+To provide a maximum of compatibilty the extend of language keywords used was kept to a\r
+minimum and does not exceed the lexical conventions of ECMA-262-2. Especially there is no\r
+use of the `switch' statement or the `RegExp' method of the global object. Also the use of\r
+advanced Array methods like `push', `shift', `splice' was avoided.\r
+\r
+\r
+\r
+\r
+11   History\r
+\r
+This library evolved from the terminal script "TermApp" ((c) N. Landsteiner 2003) and is\r
+in its current form a down scaled spinn-off of the "JS/UIX" project [JS/UIX] (evolution\r
+"JS/UIX v0.5"). c.f.: <http://www.masswerk.at/jsuix>\r
+\r
+v 1.01: added Terminal.prototype.resizeTo(x,y)\r
+        added Terminal.conf.fontClass (=> configureable class name)\r
+        Terminal.prototype.open() now checks for element conf.termDiv in advance\r
+          and returns success.\r
+\r
+v 1.02: added support for <TAB> and Euro sign\r
+          Terminal.conf.printTab\r
+          Terminal.conf.printEuro\r
+        and method Terminal.prototype.isPrintable(keycode)\r
+        added support for getopt to sample parser ("parser_sample.html")\r
+\r
+\r
+v 1.03: added global keyboard locking (TermGlobals.keylock)\r
+        modified Terminal.prototype.redraw for speed (use of locals)\r
+\r
+\r
+v 1.04: modified the key handler to fix a bug with MSIE5/Mac\r
+        fixed a bug in TermGlobals.setVisible with older MSIE-alike browsers without\r
+        DOM support.\r
+        moved the script of the sample parser to an individual document\r
+        => "termlib_parser.js" (HTML document is "parser_sample.html" as before)\r
+\r
+v 1.05: added config flag historyUnique.\r
+\r
+v 1.06: fixed CTRl+ALT (Windows alt gr) isn't CTRL any more\r
+        -> better support for international keyboards with MSIE/Win.\r
+        fixed double backspace bug for Safari;\r
+        added TermGlobals.setDisplay for setting style.display props\r
+        termlib.js now outputs lower case html (xhtml compatibility)\r
+        (date: 12'2006)\r
+\r
+v 1.07: added method Terminal.rebuild() to rebuild the GUI with new color settings.\r
+        (date: 01'2007)\r
+\r
+\r
+\r
+\r
+12  Example for a Command Line Parser\r
+\r
+  // parser example, splits command line to args with quoting and escape\r
+  // for use as `Terminal.handler'\r
+  \r
+  function commandHandler() {\r
+    this.newLine();\r
+    var argv = [''];     // arguments vector\r
+    var argQL = [''];    // quoting level\r
+    var argc = 0;        // arguments cursor\r
+    var escape = false ; // escape flag\r
+    for (var i=0; i<this.lineBuffer.length; i++) {\r
+      var ch= this.lineBuffer.charAt(i);\r
+      if (escape) {\r
+        argv[argc] += ch;\r
+        escape = false;\r
+      }\r
+      else if ((ch == '"') || (ch == "'") || (ch == "`")) {\r
+        if (argQL[argc]) {\r
+          if (argQL[argc] == ch) {\r
+            argc ++;\r
+            argv[argc] = argQL[argc] = '';\r
+          }\r
+          else {\r
+            argv[argc] += ch;\r
+          }\r
+        }\r
+        else {\r
+          if (argv[argc] != '') {\r
+            argc ++;\r
+            argv[argc] = '';\r
+            argQL[argc] = ch;\r
+          }\r
+          else {\r
+            argQL[argc] = ch;\r
+          }\r
+        }\r
+      }\r
+      else if ((ch == ' ') || (ch == '\t')) {\r
+        if (argQL[argc]) {\r
+          argv[argc] += ch;\r
+        }\r
+        else if (argv[argc] != '') {\r
+          argc++;\r
+          argv[argc] = argQL[argc] = '';\r
+        }\r
+      }\r
+      else if (ch == '\\') {\r
+        escape = true;\r
+      }\r
+      else {\r
+        argv[argc] += ch;\r
+      }\r
+    }\r
+    if ((argv[argc] == '') && (!argQL[argc])) {\r
+      argv.length--;\r
+      argQL.length--;\r
+    }\r
+    if (argv.length == 0) {\r
+      // no commmand line input\r
+    }\r
+    else if (argQL[0]) {\r
+      // first argument quoted -> error\r
+      this.write("Error: first argument quoted by "+argQL[0]);\r
+    }\r
+    else {\r
+      argc = 0;\r
+      var cmd = argv[argc++];\r
+      /*\r
+        parse commands\r
+        1st argument is argv[argc]\r
+        arguments' quoting levels in argQL[argc] are of (<empty> | ' | " | `)\r
+      */\r
+      if (cmd == 'help') {\r
+        this.write(helpPage);\r
+      }\r
+      else if (cmd == 'clear') {\r
+        this.clear();\r
+      }\r
+      else if (cmd == 'exit') {\r
+        this.close();\r
+        return;\r
+      }\r
+      else {\r
+        // for test purpose just output argv as list\r
+        // assemple a string of style-escaped lines and output it in more-mode\r
+        s='   ARG  QL  VALUE%n';\r
+        for (var i=0; i<argv.length; i++) {\r
+          s += TermGlobals.stringReplace('%', '%%',\r
+                 TermGlobals.fillLeft(i, 6) +\r
+                 TermGlobals.fillLeft((argQL[i])? argQL[i]:'-', 4) +\r
+                 '  "' + argv[i] + '"'\r
+            ) + '%n';\r
+        }\r
+        this.write(s, 1);\r
+        return;\r
+      }\r
+    }\r
+    this.prompt();\r
+  }\r
+\r
+\r
+The file "parser_sample.html" features a stand-alone parser ("termlib_parser.js") very\r
+much like this. You are free to use it according to the termlib-license (see sect. 13).\r
+It provides configurable values for quotes and esape characters and imports the parsed\r
+argument list into a Terminal instance's namespace. ("parser_sample.html" and\r
+"termlib_parser.js" should accompany this file.)\r
+\r
+\r
+\r
+\r
+13   License\r
+\r
+This JavaScript-library is free for private and academic use.\r
+Please include a readable copyright statement and a backlink to <http://www.masswerk.at>\r
+in the web page. The library should always be accompanied by the 'readme.txt' and the\r
+sample HTML-documents.\r
+\r
+The term "private use" includes any personal or non-commercial use, which is not related\r
+to commercial activites, but excludes intranet, extranet and/or public net applications\r
+that are related to any kind of commercial or profit oriented activity.\r
+\r
+For commercial use see <http://www.masswerk.at> for contact information.\r
+\r
+Any changes to the library should be commented and be documented in the readme-file.\r
+Any changes must be reflected in the `Terminal.version' string as\r
+"Version.Subversion (compatibility)".\r
+\r
+\r
+\r
+\r
+14   Disclaimer\r
+\r
+This software is distributed AS IS and in the hope that it will be useful, but WITHOUT ANY\r
+WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR\r
+PURPOSE. The entire risk as to the quality and performance of the product is borne by the\r
+user. No use of the product is authorized hereunder except under this disclaimer.\r
+\r
+\r
+\r
+\r
+15   References\r
+\r
+[ECMA262-2] "ECMAScript Language Specification" Standard ECMA-262 2nd Edition\r
+            August 1998 (ISO/IEC 16262 - April 1998)\r
+\r
+[ECMA262-3] "ECMAScript Language Specification" Standard ECMA-262 3rd Edition Final\r
+            24 March 2000\r
+\r
+[JS/UIX]     JS/UIX - JavaScript Uniplexed Interface eXtension\r
+             <http://www.masswerk.at/jsuix>\r
+\r
+\r
+\r
+\r
+\r
+Norbert Landsteiner / Vienna, August 2005\r
+mass:werk - media environments\r
+<http://www.masswerk.at>\r
+See web site for contact information.\r
diff --git a/unmaintained/webapps/fjsc/resources/termlib/term_styles.css b/unmaintained/webapps/fjsc/resources/termlib/term_styles.css
new file mode 100644 (file)
index 0000000..4971709
--- /dev/null
@@ -0,0 +1,11 @@
+.term {\r
+       font-family: courier,fixed,swiss,sans-serif;\r
+       font-size: 12px;\r
+       color: #33d011;\r
+       background: none;\r
+}\r
+\r
+.termReverse {\r
+       color: #111111;\r
+       background: #33d011;\r
+}\r
diff --git a/unmaintained/webapps/fjsc/resources/termlib/termlib.js b/unmaintained/webapps/fjsc/resources/termlib/termlib.js
new file mode 100644 (file)
index 0000000..195e11f
--- /dev/null
@@ -0,0 +1,1633 @@
+/*\r
+  termlib.js - JS-WebTerminal Object v1.07\r
+\r
+  (c) Norbert Landsteiner 2003-2005\r
+  mass:werk - media environments\r
+  <http://www.masswerk.at>\r
+\r
+  Creates [multiple] Terminal instances.\r
+\r
+  Synopsis:\r
+\r
+  myTerminal = new Terminal(<config object>);\r
+  myTerminal.open();\r
+\r
+  <config object> overrides any values of object `TerminalDefaults'.\r
+  individual values of `id' must be supplied for multiple terminals.\r
+  `handler' specifies a function to be called for input handling.\r
+  (see `Terminal.prototype.termDefaultHandler()' and documentation.)\r
+\r
+  globals defined in this library:\r
+       Terminal           (Terminal object)\r
+    TerminalDefaults   (default configuration)\r
+    termDefaultHandler (default command line handler)\r
+    TermGlobals        (common vars and code for all instances)\r
+    termKey            (named mappings for special keys)\r
+    termDomKeyRef      (special key mapping for DOM constants)\r
+\r
+  globals defined for fixing String methods, if missing\r
+  (String.fromCharCode, String.prototype.charCodeAt):\r
+    termString_keyref, termString_keycoderef, termString_makeKeyref\r
+\r
+  required CSS classes for font definitions: ".term", ".termReverse".\r
+\r
+  Compatibilty:\r
+  Standard web browsers with a JavaScript implementation compliant to\r
+  ECMA-262 2nd edition and support for the anonymous array and object\r
+  constructs and the anonymous function construct in the form of\r
+  "myfunc=function(x) {}" (c.f. ECMA-262 3rd edion for details).\r
+  This comprises almost all current browsers but Konquerer (khtml) and\r
+  versions of Apple Safari for Mac OS 10.0-10.28 (Safari 1.0) which\r
+  lack support for keyboard events.\r
+\r
+  License:\r
+  This JavaScript-library is free for private and academic use.\r
+  Please include a readable copyright statement and a backlink to\r
+  <http://www.masswerk.at> in the web page.\r
+  The library should always be accompanied by the 'readme.txt' and the\r
+  sample HTML-documents.\r
+  \r
+  The term "private use" includes any personal or non-commercial use, which\r
+  is not related to commercial activites, but excludes intranet, extranet\r
+  and/or public net applications that are related to any kind of commercial\r
+  or profit oriented activity.\r
+\r
+  For commercial use see <http://www.masswerk.at> for contact information.\r
+  \r
+  Any changes should be commented and must be reflected in `Terminal.version'\r
+  in the format: "Version.Subversion (compatibility)".\r
+\r
+  Disclaimer:\r
+  This software is distributed AS IS and in the hope that it will be useful,\r
+  but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. The entire risk as to\r
+  the quality and performance of the product is borne by the user. No use of\r
+  the product is authorized hereunder except under this disclaimer.\r
+\r
+  ### The sections above must not be removed. ###\r
+  \r
+  version 1.01: added Terminal.prototype.resizeTo(x,y)\r
+                added Terminal.conf.fontClass (=> configureable class name)\r
+                Terminal.prototype.open() now checks for element conf.termDiv\r
+                in advance and returns success.\r
+\r
+  version 1.02: added support for <TAB> and Euro sign\r
+                (Terminal.conf.printTab, Terminal.conf.printEuro)\r
+                and a method to evaluate printable chars:\r
+                Terminal.prototype.isPrintable(keycode)\r
+\r
+  version 1.03: added global keyboard locking (TermGlobals.keylock)\r
+                modified Terminal.prototype.redraw for speed (use of locals)\r
+\r
+  version 1.04: modified the key handler to fix a bug with MSIE5/Mac\r
+                fixed a bug in TermGlobals.setVisible with older MSIE-alike\r
+                browsers without DOM support.\r
+\r
+  version 1.05: added config flag historyUnique.\r
\r
+  version 1.06: fixed CTRl+ALT (Windows alt gr) isn't CTRL any more\r
+                fixed double backspace bug for Safari;\r
+                added TermGlobals.setDisplay for setting style.display props\r
+                termlib.js now outputs lower case html (xhtml compatibility)\r
+\r
+  version 1.07: added method rebuild() to rebuild with new color settings.\r
+\r
+*/\r
+\r
+var TerminalDefaults = {\r
+       // dimensions\r
+       cols:80,\r
+       rows:24,\r
+       // appearance\r
+       x:100,\r
+       y:100,\r
+       termDiv:'termDiv',\r
+       bgColor:'#181818',\r
+       frameColor:'#555555',\r
+       frameWidth:1,\r
+       rowHeight:15,\r
+       blinkDelay:500,\r
+       // css class\r
+       fontClass:'term',\r
+       // initial cursor mode\r
+       crsrBlinkMode:false,\r
+       crsrBlockMode:true,\r
+       // key mapping\r
+       DELisBS:false,\r
+       printTab:true,\r
+       printEuro:true,\r
+       catchCtrlH:true,\r
+       closeOnESC:true,\r
+       // prevent consecutive history doublets\r
+       historyUnique:false,\r
+       // optional id\r
+       id:0,\r
+       // strings\r
+       ps:'>',\r
+       greeting:'%+r Terminal ready. %-r',\r
+       // handlers\r
+       handler:termDefaultHandler,\r
+       ctrlHandler:null,\r
+       initHandler:null,\r
+       exitHandler:null\r
+}\r
+\r
+var Terminal = function(conf) {\r
+       if (typeof conf != 'object') conf=new Object();\r
+       else {\r
+               for (var i in TerminalDefaults) {\r
+                       if (typeof conf[i] == 'undefined') conf[i]=TerminalDefaults[i];\r
+               }\r
+       }\r
+       this.conf=conf;\r
+       this.version='1.07 (original)';\r
+       this.isSafari= (navigator.userAgent.indexOf('Safari')>=0)? true:false;\r
+       this.setInitValues();\r
+}\r
+\r
+Terminal.prototype.setInitValues=function() {\r
+       this.id=this.conf.id;\r
+       this.maxLines=this.conf.rows;\r
+       this.maxCols=this.conf.cols;\r
+       this.termDiv=this.conf.termDiv;\r
+       this.crsrBlinkMode=this.conf.crsrBlinkMode;\r
+       this.crsrBlockMode=this.conf.crsrBlockMode;\r
+       this.blinkDelay=this.conf.blinkDelay;\r
+       this.DELisBS=this.conf.DELisBS;\r
+       this.printTab=this.conf.printTab;\r
+       this.printEuro=this.conf.printEuro;\r
+       this.catchCtrlH=this.conf.catchCtrlH;\r
+       this.closeOnESC=this.conf.closeOnESC;\r
+       this.historyUnique=this.conf.historyUnique;\r
+       this.ps=this.conf.ps;\r
+       this.closed=false;\r
+       this.r;\r
+       this.c;\r
+       this.charBuf=new Array();\r
+       this.styleBuf=new Array();\r
+       this.scrollBuf=null;\r
+       this.blinkBuffer=0;\r
+       this.blinkTimer;\r
+       this.cursoractive=false;\r
+       this.lock=true;\r
+       this.insert=false;\r
+       this.charMode=false;\r
+       this.rawMode=false;\r
+       this.lineBuffer='';\r
+       this.inputChar=0;\r
+       this.lastLine='';\r
+       this.guiCounter=0;\r
+       this.history=new Array();\r
+       this.histPtr=0;\r
+       this.env=new Object();\r
+       this.ns4ParentDoc=null;\r
+       this.handler=this.conf.handler;\r
+       this.ctrlHandler=this.conf.ctrlHandler;\r
+       this.initHandler=this.conf.initHandler;\r
+       this.exitHandler=this.conf.exitHandler;\r
+}\r
+\r
+function termDefaultHandler() {\r
+       this.newLine();\r
+       if (this.lineBuffer != '') {\r
+               this.type('You typed: '+this.lineBuffer);\r
+               this.newLine();\r
+       }\r
+       this.prompt();\r
+}\r
+\r
+Terminal.prototype.open=function() {\r
+       if (this.termDivReady()) {\r
+               if (!this.closed) this._makeTerm();\r
+               this.init();\r
+               return true;\r
+       }\r
+       else return false;\r
+}\r
+\r
+Terminal.prototype.close=function() {\r
+       this.lock=true;\r
+       this.cursorOff();\r
+       if (this.exitHandler) this.exitHandler();\r
+       TermGlobals.setVisible(this.termDiv,0);\r
+       this.closed=true;\r
+}\r
+\r
+Terminal.prototype.init=function() {\r
+       // wait for gui\r
+       if (this.guiReady()) {\r
+               this.guiCounter=0;\r
+               // clean up at re-entry\r
+               if (this.closed) {\r
+                       this.setInitValues();\r
+               }\r
+               this.clear();\r
+               TermGlobals.setVisible(this.termDiv,1);\r
+               TermGlobals.enableKeyboard(this);\r
+               if (this.initHandler) {\r
+                       this.initHandler();\r
+               }\r
+               else {\r
+                       this.write(this.conf.greeting);\r
+                       this.newLine();\r
+                       this.prompt();\r
+               }\r
+       }\r
+       else {\r
+               this.guiCounter++;\r
+               if (this.guiCounter>18000) {\r
+                       if (confirm('Terminal:\nYour browser hasn\'t responded for more than 2 minutes.\nRetry?')) this.guiCounter=0\r
+                       else return;\r
+               };\r
+               TermGlobals.termToInitialze=this;\r
+               window.setTimeout('TermGlobals.termToInitialze.init()',200);\r
+       }\r
+}\r
+\r
+Terminal.prototype.getRowArray=function(l,v) {\r
+       var a=new Array();\r
+       for (var i=0; i<l; i++) a[i]=v;\r
+       return a;\r
+}\r
+\r
+Terminal.prototype.type=function(text,style) {\r
+       for (var i=0; i<text.length; i++) {\r
+               var ch=text.charCodeAt(i);\r
+               if (!this.isPrintable(ch)) ch=94;\r
+               this.charBuf[this.r][this.c]=ch;\r
+               this.styleBuf[this.r][this.c]=(style)? style:0;\r
+               var last_r=this.r;\r
+               this._incCol();\r
+               if (this.r!=last_r) this.redraw(last_r);\r
+       }\r
+       this.redraw(this.r)\r
+}\r
+\r
+Terminal.prototype.write=function(text,usemore) {\r
+       // write to scroll buffer with markup\r
+       // new line = '%n' prepare any strings or arrys first\r
+       if (typeof text != 'object') {\r
+               if (typeof text!='string') text=''+text;\r
+               if (text.indexOf('\n')>=0) {\r
+                       var ta=text.split('\n');\r
+                       text=ta.join('%n');\r
+               }\r
+       }\r
+       else {\r
+               if (text.join) text=text.join('%n')\r
+               else text=''+text;\r
+       }\r
+       this._sbInit(usemore);\r
+       var chunks=text.split('%');\r
+       var esc=(text.charAt(0)!='%');\r
+       var style=0;\r
+       for (var i=0; i<chunks.length; i++) {\r
+               if (esc) {\r
+                       if (chunks[i].length>0) this._sbType(chunks[i],style)\r
+                       else if (i>0) this._sbType('%', style);\r
+                       esc=false;\r
+               }\r
+               else {\r
+                       var func=chunks[i].charAt(0);\r
+                       if ((chunks[i].length==0) && (i>0)) {\r
+                               this._sbType("%",style);\r
+                               esc=true;\r
+                       }\r
+                       else if (func=='n') {\r
+                               this._sbNewLine();\r
+                               if (chunks[i].length>1) this._sbType(chunks[i].substring(1),style);\r
+                       }\r
+                       else if (func=='+') {\r
+                               var opt=chunks[i].charAt(1);\r
+                               opt=opt.toLowerCase();\r
+                               if (opt=='p') style=0\r
+                               else if (opt=='r') style|=1\r
+                               else if (opt=='u') style|=2\r
+                               else if (opt=='i') style|=4\r
+                               else if (opt=='s') style|=8;\r
+                               if (chunks[i].length>2) this._sbType(chunks[i].substring(2),style);\r
+                       }\r
+                       else if (func=='-') {\r
+                               var opt=chunks[i].charAt(1);\r
+                               opt=opt.toLowerCase();\r
+                               if (opt=='p') style|=0\r
+                               else if (opt=='r') style&=~1\r
+                               else if (opt=='u') style&=~2\r
+                               else if (opt=='i') style&=~4\r
+                               else if (opt=='s') style&=~8;\r
+                               if (chunks[i].length>2) this._sbType(chunks[i].substring(2),style);\r
+                       }\r
+                       else if ((chunks[i].length>1) && (chunks[i].charAt(0)=='C') && (chunks[i].charAt(1)=='S')) {\r
+                               this.clear();\r
+                               this._sbInit();\r
+                               if (chunks[i].length>2) this._sbType(chunks[i].substring(2),style);\r
+                       }\r
+                       else {\r
+                               if (chunks[i].length>0) this._sbType(chunks[i],style);\r
+                       }\r
+               }\r
+       }\r
+       this._sbOut();\r
+}\r
+\r
+Terminal.prototype._sbType=function(text,style) {\r
+       // type to scroll buffer\r
+       var sb=this.scrollBuf;\r
+       for (var i=0; i<text.length; i++) {\r
+               var ch=text.charCodeAt(i);\r
+               if (!this.isPrintable(ch)) ch=94;\r
+               sb.lines[sb.r][sb.c]=ch;\r
+               sb.styles[sb.r][sb.c]=(style)? style:0;\r
+               sb.c++;\r
+               if (sb.c>=this.maxCols) this._sbNewLine();\r
+       }\r
+}\r
+\r
+Terminal.prototype._sbNewLine=function() {\r
+       var sb=this.scrollBuf;\r
+       sb.r++;\r
+       sb.c=0;\r
+       sb.lines[sb.r]=this.getRowArray(this.conf.cols,0);\r
+       sb.styles[sb.r]=this.getRowArray(this.conf.cols,0);\r
+}\r
+\r
+\r
+Terminal.prototype._sbInit=function(usemore) {\r
+       var sb=this.scrollBuf=new Object();\r
+       var sbl=sb.lines=new Array();\r
+       var sbs=sb.styles=new Array();\r
+       sb.more=usemore;\r
+       sb.line=0;\r
+       sb.status=0;\r
+       sb.r=0;\r
+       sb.c=this.c;\r
+       sbl[0]=this.getRowArray(this.conf.cols,0);\r
+       sbs[0]=this.getRowArray(this.conf.cols,0);\r
+       for (var i=0; i<this.c; i++) {\r
+               sbl[0][i]=this.charBuf[this.r][i];\r
+               sbs[0][i]=this.styleBuf[this.r][i];\r
+       }\r
+}\r
+\r
+Terminal.prototype._sbOut=function() {\r
+       var sb=this.scrollBuf;\r
+       var sbl=sb.lines;\r
+       var sbs=sb.styles;\r
+       var tcb=this.charBuf;\r
+       var tsb=this.styleBuf;\r
+       var ml=this.maxLines;\r
+       var buflen=sbl.length;\r
+       if (sb.more) {\r
+               if (sb.status) {\r
+                       if (this.inputChar==TermGlobals.lcMoreKeyAbort) {\r
+                               this.r=ml-1;\r
+                               this.c=0;\r
+                               tcb[this.r]=this.getRowArray(this.maxLines,0);\r
+                               tsb[this.r]=this.getRowArray(this.maxLines,0);\r
+                               this.redraw(this.r);\r
+                               this.handler=sb.handler;\r
+                               this.charMode=false;\r
+                               this.inputChar=0;\r
+                               this.scrollBuf=null;\r
+                               this.prompt();\r
+                               return;\r
+                       }\r
+                       else if (this.inputChar==TermGlobals.lcMoreKeyContinue) {\r
+                               this.clear();\r
+                       }\r
+                       else {\r
+                               return;\r
+                       }\r
+               }\r
+               else {\r
+                       if (this.r>=ml-1) this.clear();\r
+               }\r
+       }\r
+       if (this.r+buflen-sb.line<=ml) {\r
+               for (var i=sb.line; i<buflen; i++) {\r
+                       var r=this.r+i-sb.line;\r
+                       tcb[r]=sbl[i];\r
+                       tsb[r]=sbs[i];\r
+                       this.redraw(r);\r
+               }\r
+               this.r+=sb.r-sb.line;\r
+               this.c=sb.c;\r
+               if (sb.more) {\r
+                       if (sb.status) this.handler=sb.handler;\r
+                       this.charMode=false;\r
+                       this.inputChar=0;\r
+                       this.scrollBuf=null;\r
+                       this.prompt();\r
+                       return;\r
+               }\r
+       }\r
+       else if (sb.more) {\r
+               ml--;\r
+               if (sb.status==0) {\r
+                       sb.handler=this.handler;\r
+                       this.handler=this._sbOut;\r
+                       this.charMode=true;\r
+                       sb.status=1;\r
+               }\r
+               if (this.r) {\r
+                       var ofs=ml-this.r;\r
+                       for (var i=sb.line; i<ofs; i++) {\r
+                               var r=this.r+i-sb.line;\r
+                               tcb[r]=sbl[i];\r
+                               tsb[r]=sbs[i];\r
+                               this.redraw(r);\r
+                       }\r
+               }\r
+               else {\r
+                       var ofs=sb.line+ml;\r
+                       for (var i=sb.line; i<ofs; i++) {\r
+                               var r=this.r+i-sb.line;\r
+                               tcb[r]=sbl[i];\r
+                               tsb[r]=sbs[i];\r
+                               this.redraw(r);\r
+                       }\r
+               }\r
+               sb.line=ofs;\r
+               this.r=ml;\r
+               this.c=0;\r
+               this.type(TermGlobals.lcMorePrompt1, TermGlobals.lcMorePromtp1Style);\r
+               this.type(TermGlobals.lcMorePrompt2, TermGlobals.lcMorePrompt2Style);\r
+               this.lock=false;\r
+               return;\r
+       }\r
+       else if (buflen>=ml) {\r
+               var ofs=buflen-ml;\r
+               for (var i=0; i<ml; i++) {\r
+                       var r=ofs+i;\r
+                       tcb[i]=sbl[r];\r
+                       tsb[i]=sbs[r];\r
+                       this.redraw(i);\r
+               }\r
+               this.r=ml-1;\r
+               this.c=sb.c;\r
+       }\r
+       else {\r
+               var dr=ml-buflen;\r
+               var ofs=this.r-dr;\r
+               for (var i=0; i<dr; i++) {\r
+                       var r=ofs+i;\r
+                       for (var c=0; c<this.maxCols; c++) {\r
+                               tcb[i][c]=tcb[r][c];\r
+                               tsb[i][c]=tsb[r][c];\r
+                       }\r
+                       this.redraw(i);\r
+               }\r
+               for (var i=0; i<buflen; i++) {\r
+                       var r=dr+i;\r
+                       tcb[r]=sbl[i];\r
+                       tsb[r]=sbs[i];\r
+                       this.redraw(r);\r
+               }\r
+               this.r=ml-1;\r
+               this.c=sb.c;\r
+       }\r
+       this.scrollBuf=null;\r
+}\r
+\r
+// basic console output\r
+\r
+Terminal.prototype.typeAt=function(r,c,text,style) {\r
+       var tr1=this.r;\r
+       var tc1=this.c;\r
+       this.cursorSet(r,c);\r
+       for (var i=0; i<text.length; i++) {\r
+               var ch=text.charCodeAt(i);\r
+               if (!this.isPrintable(ch)) ch=94;\r
+               this.charBuf[this.r][this.c]=ch;\r
+               this.styleBuf[this.r][this.c]=(style)? style:0;\r
+               var last_r=this.r;\r
+               this._incCol();\r
+               if (this.r!=last_r) this.redraw(last_r);\r
+       }\r
+       this.redraw(this.r);\r
+       this.r=tr1;\r
+       this.c=tc1;\r
+}\r
+\r
+Terminal.prototype.statusLine = function(text,style,offset) {\r
+       var ch,r;\r
+       style=((style) && (!isNaN(style)))? parseInt(style)&15:0;\r
+       if ((offset) && (offset>0)) r=this.conf.rows-offset\r
+       else r=this.conf.rows-1;\r
+       for (var i=0; i<this.conf.cols; i++) {\r
+               if (i<text.length) {\r
+                       ch=text.charCodeAt(i);\r
+                       if (!this.isPrintable(ch)) ch = 94;\r
+               }\r
+               else ch=0;\r
+               this.charBuf[r][i]=ch;\r
+               this.styleBuf[r][i]=style;\r
+       }\r
+       this.redraw(r);\r
+}\r
+\r
+Terminal.prototype.printRowFromString = function(r,text,style) {\r
+       var ch;\r
+       style=((style) && (!isNaN(style)))? parseInt(style)&15:0;\r
+       if ((r>=0) && (r<this.maxLines)) {\r
+               if (typeof text != 'string') text=''+text;\r
+               for (var i=0; i<this.conf.cols; i++) {\r
+                       if (i<text.length) {\r
+                               ch=text.charCodeAt(i);\r
+                               if (!this.isPrintable(ch)) ch = 94;\r
+                       }\r
+                       else ch=0;\r
+                       this.charBuf[r][i]=ch;\r
+                       this.styleBuf[r][i]=style;\r
+               }\r
+               this.redraw(r);\r
+       }\r
+}\r
+\r
+Terminal.prototype.setChar=function(ch,r,c,style) {\r
+       this.charBuf[r][c]=ch;\r
+       this.styleBuf[this.r][this.c]=(style)? style:0;\r
+       this.redraw(r);\r
+}\r
+\r
+Terminal.prototype._charOut=function(ch, style) {\r
+       this.charBuf[this.r][this.c]=ch;\r
+       this.styleBuf[this.r][this.c]=(style)? style:0;\r
+       this.redraw(this.r);\r
+       this._incCol();\r
+}\r
+\r
+Terminal.prototype._incCol=function() {\r
+       this.c++;\r
+       if (this.c>=this.maxCols) {\r
+               this.c=0;\r
+               this._incRow();\r
+       }\r
+}\r
+\r
+Terminal.prototype._incRow=function() {\r
+       this.r++;\r
+       if (this.r>=this.maxLines) {\r
+               this._scrollLines(0,this.maxLines);\r
+               this.r=this.maxLines-1;\r
+       }\r
+}\r
+\r
+Terminal.prototype._scrollLines=function(start, end) {\r
+       window.status='Scrolling lines ...';\r
+       start++;\r
+       for (var ri=start; ri<end; ri++) {\r
+               var rt=ri-1;\r
+               this.charBuf[rt]=this.charBuf[ri];\r
+               this.styleBuf[rt]=this.styleBuf[ri];\r
+       }\r
+       // clear last line\r
+       var rt=end-1;\r
+       this.charBuf[rt]=this.getRowArray(this.conf.cols,0);\r
+       this.styleBuf[rt]=this.getRowArray(this.conf.cols,0);\r
+       this.redraw(rt);\r
+       for (var r=end-1; r>=start; r--) this.redraw(r-1);\r
+       window.status='';\r
+}\r
+\r
+Terminal.prototype.newLine=function() {\r
+       this.c=0;\r
+       this._incRow();\r
+}\r
+\r
+Terminal.prototype.clear=function() {\r
+       window.status='Clearing display ...';\r
+       this.cursorOff();\r
+       this.insert=false;\r
+       for (var ri=0; ri<this.maxLines; ri++) {\r
+               this.charBuf[ri]=this.getRowArray(this.conf.cols,0);\r
+               this.styleBuf[ri]=this.getRowArray(this.conf.cols,0);\r
+               this.redraw(ri);\r
+       }\r
+       this.r=0;\r
+       this.c=0;\r
+       window.status='';\r
+}\r
+\r
+Terminal.prototype.reset=function() {\r
+       if (this.lock) return;\r
+       this.lock=true;\r
+       this.rawMode=false;\r
+       this.charMode=false;\r
+       this.maxLines=this.conf.rows;\r
+       this.maxCols=this.conf.cols;\r
+       this.lastLine='';\r
+       this.lineBuffer='';\r
+       this.inputChar=0;\r
+       this.clear();\r
+}\r
+\r
+Terminal.prototype.cursorSet=function(r,c) {\r
+       var crsron=this.cursoractive;\r
+       if (crsron) this.cursorOff();\r
+       this.r=r%this.maxLines;\r
+       this.c=c%this.maxCols;\r
+       this._cursorReset(crsron);\r
+}\r
+\r
+Terminal.prototype._cursorReset=function(crsron) {\r
+       if (crsron) this.cursorOn()\r
+       else {\r
+               this.blinkBuffer=this.styleBuf[this.r][this.c];\r
+       }\r
+}\r
+\r
+Terminal.prototype.cursorOn=function() {\r
+       if (this.blinkTimer) clearTimeout(this.blinkTimer);\r
+       this.blinkBuffer=this.styleBuf[this.r][this.c];\r
+       this._cursorBlink();\r
+       this.cursoractive=true;\r
+}\r
+\r
+Terminal.prototype.cursorOff=function() {\r
+       if (this.blinkTimer) clearTimeout(this.blinkTimer);\r
+       if (this.cursoractive) {\r
+               this.styleBuf[this.r][this.c]=this.blinkBuffer;\r
+               this.redraw(this.r);\r
+               this.cursoractive=false;\r
+       }\r
+}\r
+\r
+Terminal.prototype._cursorBlink=function() {\r
+       if (this.blinkTimer) clearTimeout(this.blinkTimer);\r
+       if (this == TermGlobals.activeTerm) {\r
+               if (this.crsrBlockMode) {\r
+                       this.styleBuf[this.r][this.c]=(this.styleBuf[this.r][this.c]&1)?\r
+                               this.styleBuf[this.r][this.c]&254:this.styleBuf[this.r][this.c]|1;\r
+               }\r
+               else {\r
+                       this.styleBuf[this.r][this.c]=(this.styleBuf[this.r][this.c]&2)?\r
+                               this.styleBuf[this.r][this.c]&253:this.styleBuf[this.r][this.c]|2;\r
+               }\r
+               this.redraw(this.r);\r
+       }\r
+       if (this.crsrBlinkMode) this.blinkTimer=setTimeout('TermGlobals.activeTerm._cursorBlink()', this.blinkDelay);\r
+}\r
+\r
+Terminal.prototype.cursorLeft=function() {\r
+       var crsron=this.cursoractive;\r
+       if (crsron) this.cursorOff();\r
+       var r=this.r;\r
+       var c=this.c;\r
+       if (c>0) c--\r
+       else if (r>0) {\r
+               c=this.maxCols-1;\r
+               r--;\r
+       }\r
+       if (this.isPrintable(this.charBuf[r][c])) {\r
+               this.r=r;\r
+               this.c=c;\r
+       }\r
+       this.insert=true;\r
+       this._cursorReset(crsron);\r
+}\r
+\r
+Terminal.prototype.cursorRight=function() {\r
+       var crsron=this.cursoractive;\r
+       if (crsron) this.cursorOff();\r
+       var r=this.r;\r
+       var c=this.c;\r
+       if (c<this.maxCols-1) c++\r
+       else if (r<this.maxLines-1) {\r
+               c=0;\r
+               r++;\r
+       }\r
+       if (!this.isPrintable(this.charBuf[r][c])) {\r
+               this.insert=false;\r
+       }\r
+       if (this.isPrintable(this.charBuf[this.r][this.c])) {\r
+               this.r=r;\r
+               this.c=c;\r
+       }\r
+       this._cursorReset(crsron);\r
+}\r
+\r
+Terminal.prototype.backspace=function() {\r
+       var crsron=this.cursoractive;\r
+       if (crsron) this.cursorOff();\r
+       var r=this.r;\r
+       var c=this.c;\r
+       if (c>0) c--\r
+       else if (r>0) {\r
+               c=this.maxCols-1;\r
+               r--;\r
+       };\r
+       if (this.isPrintable(this.charBuf[r][c])) {\r
+               this._scrollLeft(r, c);\r
+               this.r=r;\r
+               this.c=c;\r
+       };      \r
+       this._cursorReset(crsron);\r
+}\r
+\r
+Terminal.prototype.fwdDelete=function() {\r
+       var crsron=this.cursoractive;\r
+       if (crsron) this.cursorOff();\r
+       if (this.isPrintable(this.charBuf[this.r][this.c])) {\r
+               this._scrollLeft(this.r,this.c);\r
+               if (!this.isPrintable(this.charBuf[this.r][this.c])) this.insert=false;\r
+       }\r
+       this._cursorReset(crsron);\r
+}\r
+\r
+Terminal.prototype.prompt=function() {\r
+       this.lock=true;\r
+       if (this.c>0) this.newLine();\r
+       this.type(this.ps);\r
+       this._charOut(1);\r
+       this.lock=false;\r
+       this.cursorOn();\r
+}\r
+\r
+Terminal.prototype._scrollLeft=function(r,c) {\r
+       var rows=new Array();\r
+       rows[0]=r;\r
+       while (this.isPrintable(this.charBuf[r][c])) {\r
+               var ri=r;\r
+               var ci=c+1;\r
+               if (ci==this.maxCols) {\r
+                       if (ri<this.maxLines-1) {\r
+                               ci=0;\r
+                               ri++;\r
+                               rows[rows.length]=ri;\r
+                       }\r
+                       else {\r
+                               break;\r
+                       }\r
+               }\r
+               this.charBuf[r][c]=this.charBuf[ri][ci];\r
+               this.styleBuf[r][c]=this.styleBuf[ri][ci];\r
+               c=ci;\r
+               r=ri;\r
+       }\r
+       if (this.charBuf[r][c]!=0) this.charBuf[r][c]=0;\r
+       for (var i=0; i<rows.length; i++) this.redraw(rows[i]);\r
+}\r
+\r
+Terminal.prototype._scrollRight=function(r,c) {\r
+       var rows=new Array();\r
+       var end=this._getLineEnd(r,c);\r
+       var ri=end[0];\r
+       var ci=end[1];\r
+       if ((ci==this.maxCols-1) && (ri==this.maxLines-1)) {\r
+               if (r==0) return;\r
+               this._scrollLines(0,this.maxLines);\r
+               this.r--;\r
+               r--;\r
+               ri--;\r
+       }\r
+       rows[r]=1;\r
+       while (this.isPrintable(this.charBuf[ri][ci])) {\r
+               var rt=ri;\r
+               var ct=ci+1;\r
+               if (ct==this.maxCols) {\r
+                       ct=0;\r
+                       rt++;\r
+                       rows[rt]=1;\r
+               }\r
+               this.charBuf[rt][ct]=this.charBuf[ri][ci];\r
+               this.styleBuf[rt][ct]=this.styleBuf[ri][ci];\r
+               if ((ri==r) && (ci==c)) break;\r
+               ci--;\r
+               if (ci<0) {\r
+                       ci=this.maxCols-1;\r
+                       ri--;\r
+                       rows[ri]=1;\r
+               }\r
+       }\r
+       for (var i=r; i<this.maxLines; i++) {\r
+               if (rows[i]) this.redraw(i);\r
+       }\r
+}\r
+\r
+Terminal.prototype._getLineEnd=function(r,c) {\r
+       if (!this.isPrintable(this.charBuf[r][c])) {\r
+               c--;\r
+               if (c<0) {\r
+                       if (r>0) {\r
+                               r--;\r
+                               c=this.maxCols-1;\r
+                       }\r
+                       else {\r
+                               c=0;\r
+                       }\r
+               }\r
+       }\r
+       if (this.isPrintable(this.charBuf[r][c])) {\r
+               while (true) {\r
+                       var ri=r;\r
+                       var ci=c+1;\r
+                       if (ci==this.maxCols) {\r
+                               if (ri<this.maxLines-1) {\r
+                                       ri++;\r
+                                       ci=0;\r
+                               }\r
+                               else {\r
+                                       break;\r
+                               }\r
+                       }\r
+                       if (!this.isPrintable(this.charBuf[ri][ci])) break;\r
+                       c=ci;\r
+                       r=ri;\r
+               }\r
+       }\r
+       return [r,c];\r
+}\r
+\r
+Terminal.prototype._getLineStart=function(r,c) {\r
+       // not used by now, just in case anyone needs this ...\r
+       var ci, ri;\r
+       if (!this.isPrintable(this.charBuf[r][c])) {\r
+               ci=c-1;\r
+               ri=r;\r
+               if (ci<0) {\r
+                       if (ri==0) return [0,0];\r
+                       ci=this.maxCols-1;\r
+                       ri--;\r
+               }\r
+               if (!this.isPrintable(this.charBuf[ri][ci])) return [r,c]\r
+               else {\r
+                       r=ri;\r
+                       c=ci;\r
+               }\r
+       }\r
+       while (true) {\r
+               var ri=r;\r
+               var ci=c-1;\r
+               if (ci<0) {\r
+                       if (ri==0) break;\r
+                       ci=this.maxCols-1;\r
+                       ri--;\r
+               }\r
+               if (!this.isPrintable(this.charBuf[ri][ci])) break;;\r
+               r=ri;\r
+               c=ci;\r
+       }\r
+       return [r,c];\r
+}\r
+\r
+Terminal.prototype._getLine=function() {\r
+       var end=this._getLineEnd(this.r,this.c);\r
+       var r=end[0];\r
+       var c=end[1];\r
+       var line=new Array();\r
+       while (this.isPrintable(this.charBuf[r][c])) {\r
+               line[line.length]=String.fromCharCode(this.charBuf[r][c]);\r
+               if (c>0) c--\r
+               else if (r>0) {\r
+                       c=this.maxCols-1;\r
+                       r--;\r
+               }\r
+               else break;\r
+       }\r
+       line.reverse();\r
+       return line.join('');\r
+}\r
+\r
+Terminal.prototype._clearLine=function() {\r
+       var end=this._getLineEnd(this.r,this.c);\r
+       var r=end[0];\r
+       var c=end[1];\r
+       var line='';\r
+       while (this.isPrintable(this.charBuf[r][c])) {\r
+               this.charBuf[r][c]=0;\r
+               if (c>0) {\r
+                       c--;\r
+               }\r
+               else if (r>0) {\r
+                       this.redraw(r);\r
+                       c=this.maxCols-1;\r
+                       r--;\r
+               }\r
+               else break;\r
+       }\r
+       if (r!=end[0]) this.redraw(r);\r
+       c++;\r
+       this.cursorSet(r,c);\r
+       this.insert=false;\r
+}\r
+\r
+Terminal.prototype.isPrintable=function(ch, unicodePage1only) {\r
+       if ((unicodePage1only) && (ch>255)) {\r
+               return ((ch==termKey.EURO) && (this.printEuro))? true:false;\r
+       }\r
+       return (\r
+               ((ch>=32) && (ch!=termKey.DEL)) ||\r
+               ((this.printTab) && (ch==termKey.TAB))\r
+       );\r
+}\r
+\r
+// keyboard focus\r
+\r
+Terminal.prototype.focus=function() {\r
+       TermGlobals.activeTerm=this;\r
+}\r
+\r
+// global store and functions\r
+\r
+var TermGlobals={\r
+       termToInitialze:null,\r
+       activeTerm:null,\r
+       kbdEnabled:false,\r
+       keylock:false,\r
+       lcMorePrompt1: ' -- MORE -- ',\r
+       lcMorePromtp1Style: 1,\r
+       lcMorePrompt2: ' (Type: space to continue, \'q\' to quit)',\r
+       lcMorePrompt2Style: 0,\r
+       lcMoreKeyAbort: 113,\r
+       lcMoreKeyContinue: 32\r
+};\r
+\r
+// keybard focus\r
+\r
+TermGlobals.setFocus=function(termref) {\r
+       TermGlobals.activeTerm=termref;\r
+}\r
+\r
+// text related\r
+\r
+TermGlobals.normalize=function(n,m) {\r
+       var s=''+n;\r
+       while (s.length<m) s='0'+s;\r
+       return s;\r
+}\r
+\r
+TermGlobals.fillLeft=function(t,n) {\r
+       if (typeof t != 'string') t=''+t;\r
+       while (t.length<n) t=' '+t;\r
+       return t;\r
+}\r
+\r
+TermGlobals.center=function(t,l) {\r
+       var s='';\r
+       for (var i=t.length; i<l; i+=2) s+=' ';\r
+       return s+t;\r
+}\r
+\r
+TermGlobals.stringReplace=function(s1,s2,t) {\r
+       var l1=s1.length;\r
+       var l2=s2.length;\r
+       var ofs=t.indexOf(s1);\r
+       while (ofs>=0) {\r
+               t=t.substring(0,ofs)+s2+t.substring(ofs+l1);\r
+               ofs=t.indexOf(s1,ofs+l2);\r
+       }\r
+       return t;\r
+}\r
+\r
+// keyboard\r
+\r
+var termKey= {\r
+       // special key codes\r
+       'NUL': 0x00,\r
+       'SOH': 0x01,\r
+       'STX': 0x02,\r
+       'ETX': 0x03,\r
+       'EOT': 0x04,\r
+       'ENQ': 0x05,\r
+       'ACK': 0x06,\r
+       'BEL': 0x07,\r
+       'BS': 0x08,\r
+       'HT': 0x09,\r
+       'TAB': 0x09,\r
+       'LF': 0x0A,\r
+       'VT': 0x0B,\r
+       'FF': 0x0C,\r
+       'CR': 0x0D,\r
+       'SO': 0x0E,\r
+       'SI': 0x0F,\r
+       'DLE': 0x10,\r
+       'DC1': 0x11,\r
+       'DC2': 0x12,\r
+       'DC3': 0x13,\r
+       'DC4': 0x14,\r
+       'NAK': 0x15,\r
+       'SYN': 0x16,\r
+       'ETB': 0x17,\r
+       'CAN': 0x18,\r
+       'EM': 0x19,\r
+       'SUB': 0x1A,\r
+       'ESC': 0x1B,\r
+       'IS4': 0x1C,\r
+       'IS3': 0x1D,\r
+       'IS2': 0x1E,\r
+       'IS1': 0x1F,\r
+       'DEL': 0x7F,\r
+       // other specials\r
+       'EURO': 0x20AC,\r
+       // cursor mapping\r
+       'LEFT': 0x1C,\r
+       'RIGHT': 0x1D,\r
+       'UP': 0x1E,\r
+       'DOWN': 0x1F\r
+};\r
+\r
+var termDomKeyRef = {\r
+       DOM_VK_LEFT: termKey.LEFT,\r
+       DOM_VK_RIGHT: termKey.RIGHT,\r
+       DOM_VK_UP: termKey.UP,\r
+       DOM_VK_DOWN: termKey.DOWN,\r
+       DOM_VK_BACK_SPACE: termKey.BS,\r
+       DOM_VK_RETURN: termKey.CR,\r
+       DOM_VK_ENTER: termKey.CR,\r
+       DOM_VK_ESCAPE: termKey.ESC,\r
+       DOM_VK_DELETE: termKey.DEL,\r
+       DOM_VK_TAB: termKey.TAB\r
+};\r
+\r
+TermGlobals.enableKeyboard=function(term) {\r
+       if (!this.kbdEnabled) {\r
+               if (document.addEventListener) document.addEventListener("keypress", this.keyHandler, true)\r
+               else {\r
+                       if ((self.Event) && (self.Event.KEYPRESS)) document.captureEvents(Event.KEYPRESS);\r
+                       document.onkeypress = this.keyHandler;\r
+               }\r
+               window.document.onkeydown=this.keyFix;\r
+               this.kbdEnabled=true;\r
+       }\r
+       this.activeTerm=term;\r
+}\r
+\r
+TermGlobals.keyFix=function(e) {\r
+       var term=TermGlobals.activeTerm;\r
+       if ((TermGlobals.keylock) || (term.lock)) return true;\r
+       if (window.event) {\r
+               var ch=window.event.keyCode;\r
+               if  (!e) e=window.event;\r
+               if (e.DOM_VK_UP) {\r
+                       for (var i in termDomKeyRef) {\r
+                               if ((e[i]) && (ch == e[i])) {\r
+                                       this.keyHandler({which:termDomKeyRef[i],_remapped:true});\r
+                                       if (e.preventDefault) e.preventDefault();\r
+                                       if (e.stopPropagation) e.stopPropagation();\r
+                                       e.cancleBubble=true;\r
+                                       return false;\r
+                               }\r
+                       }\r
+                       e.cancleBubble=false;\r
+                       return true;\r
+               }\r
+               else {\r
+                       // no DOM support\r
+                       if ((ch==8) && (!term.isSafari)) TermGlobals.keyHandler({which:termKey.BS,_remapped:true})\r
+                       else if (ch==9) TermGlobals.keyHandler({which:termKey.TAB,_remapped:true})\r
+                       else if (ch==37) TermGlobals.keyHandler({which:termKey.LEFT,_remapped:true})\r
+                       else if (ch==39) TermGlobals.keyHandler({which:termKey.RIGHT,_remapped:true})\r
+                       else if (ch==38) TermGlobals.keyHandler({which:termKey.UP,_remapped:true})\r
+                       else if (ch==40) TermGlobals.keyHandler({which:termKey.DOWN,_remapped:true})\r
+                       else if (ch==127) TermGlobals.keyHandler({which:termKey.DEL,_remapped:true})\r
+                       else if ((ch>=57373) && (ch<=57376)) {\r
+                               if (ch==57373) TermGlobals.keyHandler({which:termKey.UP,_remapped:true})\r
+                               else if (ch==57374) TermGlobals.keyHandler({which:termKey.DOWN,_remapped:true})\r
+                               else if (ch==57375) TermGlobals.keyHandler({which:termKey.LEFT,_remapped:true})\r
+                               else if (ch==57376) TermGlobals.keyHandler({which:termKey.RIGHT,_remapped:true});\r
+                       }\r
+                       else {\r
+                               e.cancleBubble=false;\r
+                               return true;\r
+                       }\r
+                       if (e.preventDefault) e.preventDefault();\r
+                       if (e.stopPropagation) e.stopPropagation();\r
+                       e.cancleBubble=true;\r
+                       return false;\r
+               }\r
+       }\r
+}\r
+\r
+TermGlobals.keyHandler=function(e) {\r
+       var term=TermGlobals.activeTerm;\r
+       if ((TermGlobals.keylock) || (term.lock)) return true;\r
+       if ((window.event) && (window.event.preventDefault)) window.event.preventDefault()\r
+       else if ((e) && (e.preventDefault)) e.preventDefault();\r
+       if ((window.event) && (window.event.stopPropagation)) window.event.stopPropagation()\r
+       else if ((e) && (e.stopPropagation)) e.stopPropagation();\r
+       var ch;\r
+       var ctrl=false;\r
+       var shft=false;\r
+       var remapped=false;\r
+       if (e) {\r
+               ch=e.which;\r
+               ctrl=(((e.ctrlKey) && (e.altKey)) || (e.modifiers==2));\r
+               shft=((e.shiftKey) || (e.modifiers==4));\r
+               if (e._remapped) {\r
+                       remapped=true;\r
+                       if (window.event) {\r
+                               //ctrl=((ctrl) || (window.event.ctrlKey));\r
+                               ctrl=((ctrl) || ((window.event.ctrlKey) && (!window.event.altKey)));\r
+                               shft=((shft) || (window.event.shiftKey));\r
+                       }\r
+               }\r
+       }\r
+       else if (window.event) {\r
+               ch=window.event.keyCode;\r
+               //ctrl=(window.event.ctrlKey);\r
+               ctrl=((window.event.ctrlKey) && (!window.event.altKey)); // allow alt gr == ctrl alts\r
+               shft=(window.event.shiftKey);\r
+       }\r
+       else {\r
+               return true;\r
+       }\r
+       if ((ch=='') && (remapped==false)) {\r
+               // map specials\r
+               if (e==null) e=window.event;\r
+               if ((e.charCode==0) && (e.keyCode)) {\r
+                       if (e.DOM_VK_UP) {\r
+                               for (var i in termDomKeyRef) {\r
+                                       if ((e[i]) && (e.keyCode == e[i])) {\r
+                                               ch=termDomKeyRef[i];\r
+                                               break;\r
+                                       }\r
+                               }\r
+                       }\r
+                       else {\r
+                               // NS4\r
+                               if (e.keyCode==28) ch=termKey.LEFT\r
+                               else if (e.keyCode==29) ch=termKey.RIGHT\r
+                               else if (e.keyCode==30) ch=termKey.UP\r
+                               else if (e.keyCode==31) ch=termKey.DOWN\r
+                               // Mozilla alike but no DOM support\r
+                               else if (e.keyCode==37) ch=termKey.LEFT\r
+                               else if (e.keyCode==39) ch=termKey.RIGHT\r
+                               else if (e.keyCode==38) ch=termKey.UP\r
+                               else if (e.keyCode==40) ch=termKey.DOWN\r
+                               // just to have the TAB mapping here too\r
+                               else if (e.keyCode==9) ch=termKey.TAB;\r
+                       }\r
+               }\r
+       }\r
+       // key actions\r
+       if (term.charMode) {\r
+               term.insert=false;\r
+               term.inputChar=ch;\r
+               term.lineBuffer='';\r
+               term.handler();\r
+               if ((ch<=32) && (window.event)) window.event.cancleBubble=true;\r
+               return false;\r
+       }\r
+       if (!ctrl) {\r
+               // special keys\r
+               if (ch==termKey.CR) {\r
+                       term.lock=true;\r
+                       term.cursorOff();\r
+                       term.insert=false;\r
+                       if (term.rawMode) {\r
+                               term.lineBuffer=term.lastLine;\r
+                       }\r
+                       else {\r
+                               term.lineBuffer=term._getLine();\r
+                               if (\r
+                                   (term.lineBuffer!='') && ((!term.historyUnique) ||\r
+                                   (term.history.length==0) ||\r
+                                   (term.lineBuffer!=term.history[term.history.length-1]))\r
+                                  ) {\r
+                                       term.history[term.history.length]=term.lineBuffer;\r
+                               }\r
+                               term.histPtr=term.history.length;\r
+                       }\r
+                       term.lastLine='';\r
+                       term.inputChar=0;\r
+                       term.handler();\r
+                       if (window.event) window.event.cancleBubble=true;\r
+                       return false;\r
+               }\r
+               else if (ch==termKey.ESC) {\r
+                       if (term.conf.closeOnESC) term.close();\r
+                       if (window.event) window.event.cancleBubble=true;\r
+                       return false;\r
+               }\r
+               if ((ch<32) && (term.rawMode)) {\r
+                       if (window.event) window.event.cancleBubble=true;\r
+                       return false;\r
+               }\r
+               else {\r
+                       if (ch==termKey.LEFT) {\r
+                               term.cursorLeft();\r
+                               if (window.event) window.event.cancleBubble=true;\r
+                               return false;\r
+                       }\r
+                       else if (ch==termKey.RIGHT) {\r
+                               term.cursorRight();\r
+                               if (window.event) window.event.cancleBubble=true;\r
+                               return false;\r
+                       }\r
+                       else if (ch==termKey.UP) {\r
+                               term.cursorOff();\r
+                               if (term.histPtr==term.history.length) term.lastLine=term._getLine();\r
+                               term._clearLine();\r
+                               if ((term.history.length) && (term.histPtr>=0)) {\r
+                                       if (term.histPtr>0) term.histPtr--;\r
+                                       term.type(term.history[term.histPtr]);\r
+                               }\r
+                               else if (term.lastLine) term.type(term.lastLine);\r
+                               term.cursorOn();\r
+                               if (window.event) window.event.cancleBubble=true;\r
+                               return false;\r
+                       }\r
+                       else if (ch==termKey.DOWN) {\r
+                               term.cursorOff();\r
+                               if (term.histPtr==term.history.length) term.lastLine=term._getLine();\r
+                               term._clearLine();\r
+                               if ((term.history.length) && (term.histPtr<=term.history.length)) {\r
+                                       if (term.histPtr<term.history.length) term.histPtr++;\r
+                                       if (term.histPtr<term.history.length) term.type(term.history[term.histPtr])\r
+                                       else if (term.lastLine) term.type(term.lastLine);\r
+                               }\r
+                               else if (term.lastLine) term.type(term.lastLine);\r
+                               term.cursorOn();\r
+                               if (window.event) window.event.cancleBubble=true;\r
+                               return false;\r
+                       }\r
+                       else if (ch==termKey.BS) {\r
+                               term.backspace();\r
+                               if (window.event) window.event.cancleBubble=true;\r
+                               return false;\r
+                       }\r
+                       else if (ch==termKey.DEL) {\r
+                               if (term.DELisBS) term.backspace()\r
+                               else term.fwdDelete();\r
+                               if (window.event) window.event.cancleBubble=true;\r
+                               return false;\r
+                       }\r
+               }\r
+       }\r
+       if (term.rawMode) {\r
+               if (term.isPrintable(ch)) {\r
+                       term.lastLine+=String.fromCharCode(ch);\r
+               }\r
+               if ((ch==32) && (window.event)) window.event.cancleBubble=true\r
+               else if ((window.opera) && (window.event)) window.event.cancleBubble=true;\r
+               return false;\r
+       }\r
+       else {\r
+               if ((term.conf.catchCtrlH) && ((ch==termKey.BS) || ((ctrl) && (ch==72)))) {\r
+                       // catch ^H\r
+                       term.backspace();\r
+                       if (window.event) window.event.cancleBubble=true;\r
+                       return false;\r
+               }\r
+               else if ((term.ctrlHandler) && ((ch<32) || ((ctrl) && (term.isPrintable(ch,true))))) {\r
+                       if (((ch>=65) && (ch<=96)) || (ch==63)) {\r
+                               // remap canonical\r
+                               if (ch==63) ch=31\r
+                               else ch-=64;\r
+                       }\r
+                       term.inputChar=ch;\r
+                       term.ctrlHandler();\r
+                       if (window.event) window.event.cancleBubble=true;\r
+                       return false;\r
+               }\r
+               else if ((ctrl) || (!term.isPrintable(ch,true))) {\r
+                       if (window.event) window.event.cancleBubble=true;\r
+                       return false;\r
+               }\r
+               else if (term.isPrintable(ch,true)) {\r
+                       if (term.blinkTimer) clearTimeout(term.blinkTimer);\r
+                       if (term.insert) {\r
+                               term.cursorOff();\r
+                               term._scrollRight(term.r,term.c);\r
+                       }\r
+                       term._charOut(ch);\r
+                       term.cursorOn();\r
+                       if ((ch==32) && (window.event)) window.event.cancleBubble=true\r
+                       else if ((window.opera) && (window.event)) window.event.cancleBubble=true;\r
+                       return false;\r
+               }\r
+       }\r
+       return true;\r
+}\r
+\r
+// term gui\r
+\r
+TermGlobals.hasSubDivs=false;\r
+TermGlobals.hasLayers=false;\r
+TermGlobals.termStringStart='';\r
+TermGlobals.termStringEnd='';\r
+\r
+TermGlobals.termSpecials=new Array();\r
+TermGlobals.termSpecials[0]='&nbsp;';\r
+TermGlobals.termSpecials[1]='&nbsp;';\r
+TermGlobals.termSpecials[9]='&nbsp;';\r
+TermGlobals.termSpecials[32]='&nbsp;';\r
+TermGlobals.termSpecials[34]='&quot;';\r
+TermGlobals.termSpecials[38]='&amp;';\r
+TermGlobals.termSpecials[60]='&lt;';\r
+TermGlobals.termSpecials[62]='&gt;';\r
+TermGlobals.termSpecials[127]='&loz;';\r
+TermGlobals.termSpecials[0x20AC]='&euro;';\r
+\r
+TermGlobals.termStyles=new Array(1,2,4,8);\r
+TermGlobals.termStyleOpen=new Array();\r
+TermGlobals.termStyleClose=new Array();\r
+TermGlobals.termStyleOpen[1]='<span class="termReverse">';\r
+TermGlobals.termStyleClose[1]='<\/span>';\r
+TermGlobals.termStyleOpen[2]='<u>';\r
+TermGlobals.termStyleClose[2]='<\/u>';\r
+TermGlobals.termStyleOpen[4]='<i>';\r
+TermGlobals.termStyleClose[4]='<\/i>';\r
+TermGlobals.termStyleOpen[8]='<strike>';\r
+TermGlobals.termStyleClose[8]='<\/strike>';\r
+\r
+Terminal.prototype._makeTerm=function(rebuild) {\r
+       window.status='Building terminal ...';\r
+       TermGlobals.hasLayers=(document.layers)? true:false;\r
+       TermGlobals.hasSubDivs=(navigator.userAgent.indexOf('Gecko')<0);\r
+       var divPrefix=this.termDiv+'_r';\r
+       var s='';\r
+       s+='<table border="0" cellspacing="0" cellpadding="'+this.conf.frameWidth+'">\n';\r
+       s+='<tr><td bgcolor="'+this.conf.frameColor+'"><table border="0" cellspacing="0" cellpadding="2"><tr><td  bgcolor="'+this.conf.bgColor+'"><table border="0" cellspacing="0" cellpadding="0">\n';\r
+       var rstr='';\r
+       for (var c=0; c<this.conf.cols; c++) rstr+='&nbsp;';\r
+       for (var r=0; r<this.conf.rows; r++) {\r
+               var termid=((TermGlobals.hasLayers) || (TermGlobals.hasSubDivs))? '' : ' id="'+divPrefix+r+'"';\r
+               s+='<tr><td nowrap height="'+this.conf.rowHeight+'"'+termid+' class="'+this.conf.fontClass+'">'+rstr+'<\/td><\/tr>\n';\r
+       }\r
+       s+='<\/table><\/td><\/tr>\n';\r
+       s+='<\/table><\/td><\/tr>\n';\r
+       s+='<\/table>\n';\r
+       var termOffset=2+this.conf.frameWidth;\r
+       if (TermGlobals.hasLayers) {\r
+               for (var r=0; r<this.conf.rows; r++) {\r
+                       s+='<layer name="'+divPrefix+r+'" top="'+(termOffset+r*this.conf.rowHeight)+'" left="'+termOffset+'" class="'+this.conf.fontClass+'"><\/layer>\n';\r
+               }\r
+               this.ns4ParentDoc=document.layers[this.termDiv].document;\r
+               TermGlobals.termStringStart='<table border="0" cellspacing="0" cellpadding="0"><tr><td nowrap height="'+this.conf.rowHeight+'" class="'+this.conf.fontClass+'">';\r
+               TermGlobals.termStringEnd='<\/td><\/tr><\/table>';\r
+       }\r
+       else if (TermGlobals.hasSubDivs) {\r
+               for (var r=0; r<this.conf.rows; r++) {\r
+                       s+='<div id="'+divPrefix+r+'" style="position:absolute; top:'+(termOffset+r*this.conf.rowHeight)+'px; left: '+termOffset+'px;" class="'+this.conf.fontClass+'"><\/div>\n';\r
+               }\r
+               TermGlobals.termStringStart='<table border="0" cellspacing="0" cellpadding="0"><tr><td nowrap height="'+this.conf.rowHeight+'" class="'+this.conf.fontClass+'">';\r
+               TermGlobals.termStringEnd='<\/td><\/tr><\/table>';\r
+       }\r
+       TermGlobals.writeElement(this.termDiv,s);\r
+       if (!rebuild) {\r
+               TermGlobals.setElementXY(this.termDiv,this.conf.x,this.conf.y);\r
+               TermGlobals.setVisible(this.termDiv,1);\r
+       }\r
+       window.status='';\r
+}\r
+\r
+Terminal.prototype.rebuild=function() {\r
+       // check for bounds and array lengths\r
+       var rl=this.conf.rows;\r
+       var cl=this.conf.cols;\r
+       for (var r=0; r<rl; r++) {\r
+               var cbr=this.charBuf[r];\r
+               if (!cbr) {\r
+                       this.charBuf[r]=this.getRowArray(cl,0);\r
+                       this.styleBuf[r]=this.getRowArray(cl,0);\r
+               }\r
+               else if (cbr.length<cl) {\r
+                       for (var c=cbr.length; c<cl; c++) {\r
+                               this.charBuf[r][c]=0;\r
+                               this.styleBuf[r][c]=0;\r
+                       }\r
+               }\r
+       }\r
+       var resetcrsr=false;\r
+       if (this.r>=rl) {\r
+               r=rl-1;\r
+               resetcrsr=true;\r
+       }\r
+       if (this.c>=cl) {\r
+               c=cl-1;\r
+               resetcrsr=true;\r
+       }\r
+       if ((resetcrsr) && (this.cursoractive)) this.cursorOn();\r
+       // and actually rebuild\r
+       this._makeTerm(true);\r
+       for (var r=0; r<rl; r++) {\r
+               this.redraw(r);\r
+       }\r
+}\r
+\r
+Terminal.prototype.moveTo=function(x,y) {\r
+       TermGlobals.setElementXY(this.termDiv,x,y);\r
+}\r
+\r
+Terminal.prototype.resizeTo=function(x,y) {\r
+       if (this.termDivReady()) {\r
+               x=parseInt(x,10);\r
+               y=parseInt(y,10);\r
+               if ((isNaN(x)) || (isNaN(y)) || (x<4) || (y<2)) return false;\r
+               this.maxCols=this.conf.cols=x;\r
+               this.maxLines=this.conf.rows=y;\r
+               this._makeTerm();\r
+               this.clear();\r
+               return true;\r
+       }\r
+       else return false;\r
+}\r
+\r
+Terminal.prototype.redraw=function(r) {\r
+       var s=TermGlobals.termStringStart;\r
+       var curStyle=0;\r
+       var tstls=TermGlobals.termStyles;\r
+       var tscls=TermGlobals.termStyleClose;\r
+       var tsopn=TermGlobals.termStyleOpen;\r
+       var tspcl=TermGlobals.termSpecials;\r
+       var t_cb=this.charBuf;\r
+       var t_sb=this.styleBuf;\r
+       for (var i=0; i<this.conf.cols; i++) {\r
+               var c=t_cb[r][i];\r
+               var cs=t_sb[r][i];\r
+               if (cs!=curStyle) {\r
+                       if (curStyle) {\r
+                               for (var k=tstls.length-1; k>=0; k--) {\r
+                                       var st=tstls[k];\r
+                                       if (curStyle&st) s+=tscls[st];\r
+                               }\r
+                       }\r
+                       curStyle=cs;\r
+                       for (var k=0; k<tstls.length; k++) {\r
+                               var st=tstls[k];\r
+                               if (curStyle&st) s+=tsopn[st];\r
+                       }\r
+               }\r
+               s+= (tspcl[c])? tspcl[c] : String.fromCharCode(c);\r
+       }\r
+       if (curStyle>0) {\r
+               for (var k=tstls.length-1; k>=0; k--) {\r
+                       var st=tstls[k];\r
+                       if (curStyle&st) s+=tscls[st];\r
+               }\r
+       }\r
+       s+=TermGlobals.termStringEnd;\r
+       TermGlobals.writeElement(this.termDiv+'_r'+r,s,this.ns4ParentDoc);\r
+}\r
+\r
+Terminal.prototype.guiReady=function() {\r
+       ready=true;\r
+       if (TermGlobals.guiElementsReady(this.termDiv, self.document)) {\r
+               for (var r=0; r<this.conf.rows; r++) {\r
+                       if (TermGlobals.guiElementsReady(this.termDiv+'_r'+r,this.ns4ParentDoc)==false) {\r
+                               ready=false;\r
+                               break;\r
+                       }\r
+               }\r
+       }\r
+       else ready=false;\r
+       return ready;\r
+}\r
+\r
+Terminal.prototype.termDivReady=function() {\r
+       if (document.layers) {\r
+               return (document.layers[this.termDiv])? true:false;\r
+       }\r
+       else if (document.getElementById) {\r
+               return (document.getElementById(this.termDiv))? true:false;\r
+       }\r
+       else if (document.all) {\r
+               return (document.all[this.termDiv])? true:false;\r
+       }\r
+       else {\r
+               return false;\r
+       }\r
+}\r
+\r
+Terminal.prototype.getDimensions=function() {\r
+       var w=0;\r
+       var h=0;\r
+       var d=this.termDiv;\r
+       if (document.layers) {\r
+               if (document.layers[d]) {\r
+                       w=document.layers[d].clip.right;\r
+                       h=document.layers[d].clip.bottom;\r
+               }\r
+       }\r
+       else if (document.getElementById) {\r
+               var obj=document.getElementById(d);\r
+               if ((obj) && (obj.firstChild)) {\r
+                       w=parseInt(obj.firstChild.offsetWidth,10);\r
+                       h=parseInt(obj.firstChild.offsetHeight,10);\r
+        }\r
+               else if ((obj) && (obj.children) && (obj.children[0])) {\r
+                       w=parseInt(obj.children[0].offsetWidth,10);\r
+                       h=parseInt(obj.children[0].offsetHeight,10);\r
+        }\r
+       }\r
+       else if (document.all) {\r
+               var obj=document.all[d];\r
+               if ((obj) && (obj.children) && (obj.children[0])) {\r
+                       w=parseInt(obj.children[0].offsetWidth,10);\r
+                       h=parseInt(obj.children[0].offsetHeight,10);\r
+        }\r
+       }\r
+       return { width: w, height: h };\r
+}\r
+\r
+// basic dynamics\r
+\r
+TermGlobals.writeElement=function(e,t,d) {\r
+       if (document.layers) {\r
+               var doc=(d)? d : self.document;\r
+               doc.layers[e].document.open();\r
+               doc.layers[e].document.write(t);\r
+               doc.layers[e].document.close();\r
+       }\r
+       else if (document.getElementById) {\r
+               var obj=document.getElementById(e);\r
+               obj.innerHTML=t;\r
+       }\r
+       else if (document.all) {\r
+               document.all[e].innerHTML=t;\r
+       }\r
+}\r
+\r
+TermGlobals.setElementXY=function(d,x,y) {\r
+       if (document.layers) {\r
+               document.layers[d].moveTo(x,y);\r
+       }\r
+       else if (document.getElementById) {\r
+               var obj=document.getElementById(d);\r
+               obj.style.left=x+'px';\r
+               obj.style.top=y+'px';\r
+       }\r
+       else if (document.all) {\r
+               document.all[d].style.left=x+'px';\r
+               document.all[d].style.top=y+'px';\r
+       }\r
+}\r
+\r
+TermGlobals.setVisible=function(d,v) {\r
+       if (document.layers) {\r
+               document.layers[d].visibility= (v)? 'show':'hide';\r
+       }\r
+       else if (document.getElementById) {\r
+               var obj=document.getElementById(d);\r
+               obj.style.visibility= (v)? 'visible':'hidden';\r
+       }\r
+       else if (document.all) {\r
+               document.all[d].style.visibility= (v)? 'visible':'hidden';\r
+       }\r
+}\r
+\r
+TermGlobals.setDisplay=function(d,v) {\r
+       if (document.getElementById) {\r
+               var obj=document.getElementById(d);\r
+               obj.style.display=v;\r
+       }\r
+       else if (document.all) {\r
+               document.all[d].style.display=v;\r
+       }\r
+}\r
+\r
+TermGlobals.guiElementsReady=function(e,d) {\r
+       if (document.layers) {\r
+               var doc=(d)? d : self.document;\r
+               return ((doc) && (doc.layers[e]))? true:false;\r
+       }\r
+       else if (document.getElementById) {\r
+               return (document.getElementById(e))? true:false;\r
+       }\r
+       else if (document.all) {\r
+               return (document.all[e])? true:false;\r
+       }\r
+       else return false;\r
+}\r
+\r
+\r
+// constructor mods (ie4 fix)\r
+\r
+var termString_keyref;\r
+var termString_keycoderef;\r
+\r
+function termString_makeKeyref() {\r
+       termString_keyref= new Array();\r
+       termString_keycoderef= new Array();\r
+       var hex= new Array('A','B','C','D','E','F');\r
+       for (var i=0; i<=15; i++) {\r
+               var high=(i<10)? i:hex[i-10];\r
+               for (var k=0; k<=15; k++) {\r
+                       var low=(k<10)? k:hex[k-10];\r
+                       var cc=i*16+k;\r
+                       if (cc>=32) {\r
+                               var cs=unescape("%"+high+low);\r
+                               termString_keyref[cc]=cs;\r
+                               termString_keycoderef[cs]=cc;\r
+                       }\r
+               }\r
+       }\r
+}\r
+\r
+if (!String.fromCharCode) {\r
+       termString_makeKeyref();\r
+       String.fromCharCode=function(cc) {\r
+               return (cc!=null)? termString_keyref[cc] : '';\r
+       };\r
+}\r
+if (!String.prototype.charCodeAt) {\r
+       if (!termString_keycoderef) termString_makeKeyref();\r
+       String.prototype.charCodeAt=function(n) {\r
+               cs=this.charAt(n);\r
+               return (termString_keycoderef[cs])? termString_keycoderef[cs] : 0;\r
+       };\r
+}\r
+\r
+// eof
\ No newline at end of file
diff --git a/unmaintained/webapps/fjsc/resources/termlib/termlib_parser.js b/unmaintained/webapps/fjsc/resources/termlib/termlib_parser.js
new file mode 100644 (file)
index 0000000..27c0c5f
--- /dev/null
@@ -0,0 +1,199 @@
+/*\r
+  termlib_parser.js  v.1.0\r
+  command line parser for termlib.js\r
+  (c) Norbert Landsteiner 2005\r
+  mass:werk - media environments\r
+  <http://www.masswerk.at>\r
+\r
+  you are free to use this parser under the "termlib.js" license.\r
+\r
+  usage:  call "parseLine(this)" from your Terminal handler\r
+          parsed args in this.argv\r
+          quoting levels per arg in this.argQL (value: quote char)\r
+          this.argc: pointer to this.argv and this.argQL (used by parserGetopt)\r
+          call parseretopt(this, "<options>") from your handler to get opts\r
+          (returns an object with properties for every option flag. any float\r
+          values are stored in Object.<flag>.value; illegal opts in array\r
+          Object.illegals)\r
+\r
+  configuration: you may want to overide the follow objects (or add properties):\r
+          parserWhiteSpace: chars to be parsed as whitespace\r
+          parserQuoteChars: chars to be parsed as quotes\r
+          parserSingleEscapes: chars to escape a quote or escape expression\r
+          parserOptionChars: chars that start an option\r
+          parserEscapeExpressions: chars that start escape expressions\r
+*/\r
+\r
+// chars to be parsed as white space\r
+var parserWhiteSpace = {\r
+       ' ': true,\r
+       '\t': true\r
+}\r
+\r
+// chars to be parsed as quotes\r
+var parserQuoteChars = {\r
+       '"': true,\r
+       "'": true,\r
+       '`': true\r
+};\r
+\r
+// chars to be parsed as escape char\r
+var parserSingleEscapes = {\r
+       '\\': true\r
+};\r
+\r
+// chars that mark the start of an option-expression\r
+// for use with parserGetopt\r
+var parserOptionChars = {\r
+       '-': true\r
+}\r
+\r
+// chars that start escape expressions (value = handler)\r
+// plugin handlers for ascii escapes or variable substitution\r
+var parserEscapeExpressions = {\r
+       '%': parserHexExpression\r
+}\r
+\r
+function parserHexExpression(termref, pointer, echar, quotelevel) {\r
+       /* example for parserEscapeExpressions\r
+          params:\r
+            termref: ref to Terminal instance\r
+            pointer: position in termref.lineBuffer (echar)\r
+            echar:   escape character found\r
+            quotelevel: current quoting level (quote char or empty)\r
+          char under pointer will be ignored\r
+          the return value is added to the current argument\r
+       */\r
+       // convert hex values to chars (e.g. %20 => <SPACE>)\r
+       if (termref.lineBuffer.length > pointer+2) {\r
+               // get next 2 chars\r
+               var hi = termref.lineBuffer.charAt(pointer+1);\r
+               var lo = termref.lineBuffer.charAt(pointer+2);\r
+               lo = lo.toUpperCase();\r
+               hi = hi.toUpperCase();\r
+               // check for valid hex digits\r
+               if ((((hi>='0') && (hi<='9')) || ((hi>='A') && ((hi<='F')))) &&\r
+                   (((lo>='0') && (lo<='9')) || ((lo>='A') && ((lo<='F'))))) {\r
+                       // next 2 chars are valid hex, so strip them from lineBuffer\r
+                       parserEscExprStrip(termref, pointer+1, pointer+3);\r
+                       // and return the char\r
+                       return String.fromCharCode(parseInt(hi+lo, 16));\r
+               }\r
+       }\r
+       // if not handled return the escape character (=> no conversion)\r
+       return echar;\r
+}\r
+\r
+function parserEscExprStrip(termref, from, to) {\r
+       // strip characters from termref.lineBuffer (for use with escape expressions)\r
+       termref.lineBuffer =\r
+               termref.lineBuffer.substring(0, from) +\r
+               termref.lineBuffer.substring(to);\r
+}\r
+\r
+function parserGetopt(termref, optsstring) {\r
+    // scans argv form current position of argc for opts\r
+    // arguments in argv must not be quoted\r
+       // returns an object with a property for every option flag found\r
+       // option values (absolute floats) are stored in Object.<opt>.value (default -1)\r
+       // the property "illegals" contains an array of  all flags found but not in optstring\r
+       // argc is set to first argument that is not an option\r
+       var opts = { 'illegals':[] };\r
+       while ((termref.argc < termref.argv.length) && (termref.argQL[termref.argc]==''))  {\r
+               var a = termref.argv[termref.argc];\r
+               if ((a.length>0) && (parserOptionChars[a.charAt(0)])) {\r
+                       var i = 1;\r
+                       while (i<a.length) {\r
+                               var c=a.charAt(i);\r
+                               var v = '';\r
+                               while (i<a.length-1) {\r
+                                       var nc=a.charAt(i+1);\r
+                                       if ((nc=='.') || ((nc>='0') && (nc<='9'))) {\r
+                                               v += nc;\r
+                                               i++;\r
+                                       }\r
+                                       else break;\r
+                               }\r
+                               if (optsstring.indexOf(c)>=0) {\r
+                                       opts[c] = (v == '')? {value:-1} : (isNaN(v))? {value:0} : {value:parseFloat(v)};\r
+                               }\r
+                               else {\r
+                                       opts.illegals[opts.illegals.length]=c;\r
+                               }\r
+                               i++;\r
+                       }\r
+                       termref.argc++;\r
+               }\r
+               else break;\r
+       }\r
+       return opts;\r
+}\r
+\r
+function parseLine(termref) {\r
+       // stand-alone parser, takes a Terminal instance as argument\r
+       // parses the command line and stores results as instance properties\r
+       //   argv:  list of parsed arguments\r
+       //   argQL: argument's quoting level (<empty> or quote character)\r
+       //   argc:  cursur for argv, set initinally to zero (0)\r
+       // open quote strings are not an error but automatically closed.\r
+       var argv = [''];     // arguments vector\r
+       var argQL = [''];    // quoting level\r
+       var argc = 0;        // arguments cursor\r
+       var escape = false ; // escape flag\r
+       for (var i=0; i<termref.lineBuffer.length; i++) {\r
+               var ch= termref.lineBuffer.charAt(i);\r
+               if (escape) {\r
+                       argv[argc] += ch;\r
+                       escape = false;\r
+               }\r
+               else if (parserEscapeExpressions[ch]) {\r
+                       var v = parserEscapeExpressions[ch](termref, i, ch, argQL[argc]);\r
+                       if (typeof v != 'undefined') argv[argc] += v;\r
+               }\r
+               else if (parserQuoteChars[ch]) {\r
+                       if (argQL[argc]) {\r
+                               if (argQL[argc] == ch) {\r
+                                       argc ++;\r
+                                       argv[argc] = argQL[argc] = '';\r
+                               }\r
+                               else {\r
+                                       argv[argc] += ch;\r
+                               }\r
+                       }\r
+                       else {\r
+                               if (argv[argc] != '') {\r
+                                       argc ++;\r
+                                       argv[argc] = '';\r
+                                       argQL[argc] = ch;\r
+                               }\r
+                               else {\r
+                                       argQL[argc] = ch;\r
+                               }\r
+                       }\r
+               }\r
+               else if (parserWhiteSpace[ch]) {\r
+                       if (argQL[argc]) {\r
+                               argv[argc] += ch;\r
+                       }\r
+                       else if (argv[argc] != '') {\r
+                               argc++;\r
+                               argv[argc] = argQL[argc] = '';\r
+                       }\r
+               }\r
+               else if (parserSingleEscapes[ch]) {\r
+                       escape = true;\r
+               }\r
+               else {\r
+                       argv[argc] += ch;\r
+               }\r
+       }\r
+       if ((argv[argc] == '') && (!argQL[argc])) {\r
+               argv.length--;\r
+               argQL.length--;\r
+       }\r
+       termref.argv = argv;\r
+       termref.argQL = argQL;\r
+       termref.argc = 0;\r
+}\r
+\r
+// eof
\ No newline at end of file
diff --git a/unmaintained/webapps/fjsc/summary.txt b/unmaintained/webapps/fjsc/summary.txt
new file mode 100644 (file)
index 0000000..74e8bbb
--- /dev/null
@@ -0,0 +1 @@
+Web interface for Factor to Javascript compiler
diff --git a/unmaintained/webapps/fjsc/tags.txt b/unmaintained/webapps/fjsc/tags.txt
new file mode 100644 (file)
index 0000000..1b93c9e
--- /dev/null
@@ -0,0 +1 @@
+webapp
diff --git a/unmaintained/webapps/help/authors.txt b/unmaintained/webapps/help/authors.txt
new file mode 100755 (executable)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/unmaintained/webapps/help/help.factor b/unmaintained/webapps/help/help.factor
new file mode 100644 (file)
index 0000000..28d7360
--- /dev/null
@@ -0,0 +1,89 @@
+! Copyright (C) 2005, 2007 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel furnace furnace.validator http.server.responders
+       help help.topics html splitting sequences words strings 
+       quotations macros vocabs tools.browser combinators
+       arrays io.files ;
+IN: webapps.help 
+
+! : string>topic ( string -- topic )
+    ! " " split dup length 1 = [ first ] when ;
+
+: show-help ( topic -- )
+    serving-html
+    dup article-title [
+        [ help ] with-html-stream
+    ] simple-html-document ;
+
+\ show-help {
+    { "topic" }
+} define-action
+\ show-help { { "topic" "handbook" } } default-values
+
+M: link browser-link-href
+    link-name
+    dup word? over f eq? or [
+        browser-link-href
+    ] [
+        dup array? [ " " join ] when
+        [ show-help ] curry quot-link
+    ] if ;
+
+: show-word ( word vocab -- )
+    lookup show-help ;
+
+\ show-word {
+    { "word" }
+    { "vocab" }
+} define-action
+\ show-word { { "word" "call" } { "vocab" "kernel" } } default-values
+
+M: f browser-link-href
+    drop \ f browser-link-href ;
+
+M: word browser-link-href
+    dup word-name swap word-vocabulary
+    [ show-word ] 2curry quot-link ;
+
+: show-vocab ( vocab -- )
+    f >vocab-link show-help ;
+
+\ show-vocab {
+    { "vocab" }
+} define-action
+
+\ show-vocab { { "vocab" "kernel" } } default-values
+
+M: vocab-spec browser-link-href
+    vocab-name [ show-vocab ] curry quot-link ;
+
+: show-vocabs-tagged ( tag -- )
+    <vocab-tag> show-help ;
+
+\ show-vocabs-tagged {
+    { "tag" }
+} define-action
+
+M: vocab-tag browser-link-href
+    vocab-tag-name [ show-vocabs-tagged ] curry quot-link ;
+
+: show-vocabs-by ( author -- )
+    <vocab-author> show-help ;
+
+\ show-vocabs-by {
+    { "author" }
+} define-action
+
+M: vocab-author browser-link-href
+    vocab-author-name [ show-vocabs-by ] curry quot-link ;
+
+"help" "show-help" "extra/webapps/help" web-app
+
+! Hard-coding for factorcode.org
+PREDICATE: pathname resource-pathname
+    pathname-string "resource:" head? ;
+
+M: resource-pathname browser-link-href
+    pathname-string
+    "resource:" ?head drop
+    "/responder/source/" swap append ;
diff --git a/unmaintained/webapps/numbers/authors.txt b/unmaintained/webapps/numbers/authors.txt
new file mode 100755 (executable)
index 0000000..44b06f9
--- /dev/null
@@ -0,0 +1 @@
+Chris Double
diff --git a/unmaintained/webapps/numbers/numbers.factor b/unmaintained/webapps/numbers/numbers.factor
new file mode 100644 (file)
index 0000000..59247e9
--- /dev/null
@@ -0,0 +1,95 @@
+! cont-number-guess
+!
+! Copyright (C) 2004 Chris Double.
+! 
+! Redistribution and use in source and binary forms, with or without
+! modification, are permitted provided that the following conditions are met:
+! 
+! 1. Redistributions of source code must retain the above copyright notice,
+!    this list of conditions and the following disclaimer.
+! 
+! 2. Redistributions in binary form must reproduce the above copyright notice,
+!    this list of conditions and the following disclaimer in the documentation
+!    and/or other materials provided with the distribution.
+! 
+! THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+! INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+! FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+! DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+! OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+! WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+!
+! This example modifies the console based 'numbers-game' example
+! in a very minimal way to demonstrate conversion of a console
+! program to a web based application.
+!
+! All that was required was changing the input and output functions
+! to use HTML. The remaining code was untouched. 
+!
+! The result is not that pretty but it shows the basic idea.
+USING: kernel math parser html html.elements io namespaces
+math.parser random webapps.continuation ;
+
+IN: webapps.numbers
+
+: web-print ( str -- )
+  #! Display the string in a web page.
+  [
+    swap dup
+    <html>
+      <head> <title> write </title> </head>
+      <body>
+        <p> write </p>
+        <p> <a =href a> "Press to continue" write </a> </p>
+      </body>
+    </html>
+  ] show 2drop ;
+
+: read-number ( -- )
+  [
+    <html>
+      <head> <title> "Enter a number" write </title> </head>
+      <body>
+        <form =action "post" =method form>
+          <p> 
+            "Enter a number:" write
+            <input "text" =type "num" =name "20" =size input/>
+            <input "submit" =type "Press to continue" =value input/>
+          </p>
+        </form>
+      </body>
+    </html>
+  ] show [ "num" get ] bind string>number ;
+
+: guess-banner
+  "I'm thinking of a number between 0 and 100." web-print ;
+: guess-prompt  ;
+: too-high "Too high" web-print ;
+: too-low "Too low" web-print ;
+: correct "Correct - you win!" web-print ;
+: inexact-guess ( actual guess -- )
+     < [ too-high ] [ too-low ] if ;
+
+: judge-guess ( actual guess -- ? )
+    2dup = [
+        2drop correct f
+    ] [
+        inexact-guess t
+    ] if ;
+
+: number-to-guess ( -- n ) 100 random ;
+
+: numbers-game-loop ( actual -- )
+    dup guess-prompt read-number judge-guess [
+        numbers-game-loop
+    ] [
+        drop
+    ] if ;
+
+: numbers-game number-to-guess numbers-game-loop ;
+
+"numbers-game" [ numbers-game ] install-cont-responder
diff --git a/unmaintained/webapps/pastebin/annotate-paste.furnace b/unmaintained/webapps/pastebin/annotate-paste.furnace
new file mode 100755 (executable)
index 0000000..14a424f
--- /dev/null
@@ -0,0 +1,47 @@
+<% USING: io math math.parser namespaces furnace ; %>
+
+<h1>Annotate</h1>
+
+<form method="POST" action="/responder/pastebin/annotate-paste">
+
+<table>
+
+<tr>
+<th align="right">Summary:</th>
+<td><input type="TEXT" name="summary" value="<% "summary" render %>" /></td>
+<td align="left" class="error"><% "summary" "*Required" render-error %></td>
+</tr>
+
+<tr>
+<th align="right">Your name:</th>
+<td><input type="TEXT" name="author" value="<% "author" render  %>" /></td>
+<td class="error"><% "author" "*Required" render-error %></td>
+</tr>
+
+<tr>
+<th align="right">File type:</th>
+<td><% "modes" render-template %></td>
+</tr>
+
+<!--
+<tr>
+<th align="right">Channel:</th>
+<td><input type="TEXT" name="channel" value="#concatenative" /></td>
+</tr>
+-->
+
+<tr>
+<td></td>
+<td colspan="2" class="error" align="left"><% "contents" "*Required" render-error %></td>
+</tr>
+
+<tr>
+<th align="right" valign="top">Content:</th>
+<td colspan="2"><textarea rows="24" cols="60" name="contents"><% "contents" render %></textarea></td>
+</tr>
+</table>
+
+<input type="hidden" name="n" value="<% "n" get number>string write %>" />
+<input type="hidden" name="furnace-form-submitted" value="annotate-paste"/>
+<input type="SUBMIT" value="Annotate" />
+</form>
diff --git a/unmaintained/webapps/pastebin/annotation.furnace b/unmaintained/webapps/pastebin/annotation.furnace
new file mode 100755 (executable)
index 0000000..e59db32
--- /dev/null
@@ -0,0 +1,11 @@
+<% USING: namespaces io furnace calendar ; %>
+
+<h2>Annotation: <% "summary" get write %></h2>
+
+<table>
+<tr><th align="right">Annotation by:</th><td><% "author" get write %></td></tr>
+<tr><th align="right">File type:</th><td><% "mode" get write %></td></tr>
+<tr><th align="right">Created:</th><td><% "date" get timestamp>string write %></td></tr>
+</table>
+
+<% "syntax" render-template %>
diff --git a/unmaintained/webapps/pastebin/authors.txt b/unmaintained/webapps/pastebin/authors.txt
new file mode 100755 (executable)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/unmaintained/webapps/pastebin/footer.furnace b/unmaintained/webapps/pastebin/footer.furnace
new file mode 100644 (file)
index 0000000..15b9011
--- /dev/null
@@ -0,0 +1,3 @@
+</body>
+
+</html>
diff --git a/unmaintained/webapps/pastebin/header.furnace b/unmaintained/webapps/pastebin/header.furnace
new file mode 100644 (file)
index 0000000..2c8e79a
--- /dev/null
@@ -0,0 +1,23 @@
+<% USING: namespaces io furnace sequences xmode.code2html webapps.pastebin ; %>
+
+<!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">
+<head>
+       <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
+
+       <title><% "title" get write %></title>
+       <link rel="stylesheet" href="style.css" type="text/css" media="screen" title="no title" charset="utf-8" />
+       <% default-stylesheet %>
+    <link rel="alternate" type="application/atom+xml" title="Pastebin - Atom" href="feed.xml" />
+</head>
+
+<body id="index">
+
+    <div class="navbar">
+        <% [ paste-list ] "Paste list" render-link %> |
+        <% [ new-paste ] "New paste" render-link %> |
+        <% [ feed.xml ] "Syndicate" render-link %>
+    </div>
+    <h1 class="pastebin-title"><% "title" get write %></h1>
diff --git a/unmaintained/webapps/pastebin/modes.furnace b/unmaintained/webapps/pastebin/modes.furnace
new file mode 100644 (file)
index 0000000..18bbec1
--- /dev/null
@@ -0,0 +1,7 @@
+<% USING: furnace xmode.catalog sequences kernel html.elements assocs io sorting continuations ; %>
+
+<select name="mode">
+    <% modes keys natural-sort [
+        <option dup "mode" session-var = [ "true" =selected ] when option> write </option>
+    ] each %>
+</select>
diff --git a/unmaintained/webapps/pastebin/new-paste.furnace b/unmaintained/webapps/pastebin/new-paste.furnace
new file mode 100755 (executable)
index 0000000..b21e197
--- /dev/null
@@ -0,0 +1,51 @@
+<% USING: continuations furnace namespaces ; %>
+
+<%
+    "New paste" "title" set
+    "header" render-template
+%>
+
+<form method="POST" action="/responder/pastebin/submit-paste">
+
+<table>
+
+<tr>
+<th align="right">Summary:</th>
+<td><input type="TEXT" name="summary" value="<% "summary" render %>" /></td>
+<td align="left" class="error"><% "summary" "*Required" render-error %></td>
+</tr>
+
+<tr>
+<th align="right">Your name:</th>
+<td><input type="TEXT" name="author" value="<% "author" render  %>" /></td>
+<td class="error"><% "author" "*Required" render-error %></td>
+</tr>
+
+<tr>
+<th align="right">File type:</th>
+<td><% "modes" render-template %></td>
+</tr>
+
+<!--
+<tr>
+<th align="right">Channel:</th>
+<td><input type="TEXT" name="channel" value="#concatenative" /></td>
+</tr>
+-->
+
+<tr>
+<td></td>
+<td colspan="2" class="error" align="left"><% "contents" "*Required" render-error %></td>
+</tr>
+
+<tr>
+<th align="right" valign="top">Content:</th>
+<td colspan="2"><textarea rows="24" cols="60" name="contents"><% "contents" render %></textarea></td>
+</tr>
+</table>
+
+<input type="hidden" name="furnace-form-submitted" value="new-paste"/>
+<input type="SUBMIT" value="Submit paste" />
+</form>
+
+<% "footer" render-template %>
diff --git a/unmaintained/webapps/pastebin/paste-list.furnace b/unmaintained/webapps/pastebin/paste-list.furnace
new file mode 100644 (file)
index 0000000..51813ec
--- /dev/null
@@ -0,0 +1,33 @@
+<% USING: namespaces furnace sequences ; %>
+
+<%
+    "Pastebin" "title" set
+    "header" render-template
+%>
+
+<table width="100%" cellspacing="10">
+    <tr>
+        <td valign="top">
+            <table width="100%">
+                <tr align="left" class="pastebin-headings">
+                    <th width="50%">Summary:</th>
+                    <th width="100">Paste by:</th>
+                    <th width="200">Date:</th>
+                </tr>
+                <% "pastes" get <reversed> [ "paste-summary" render-component ] each %>
+            </table>
+        </td>
+        <td valign="top" width="25%">
+            <div class="infobox">
+                <p>This pastebin is written in <a href="http://factorcode.org/">Factor</a>. It is inspired by <a href="http://paste.lisp.org">lisppaste</a>.
+                </p>
+                <p>It can be used for collaborative development over IRC. You can post code for review, and annotate other people's code. Syntax highlighting for over a hundred file types is supported.
+                </p>
+                <p>
+                <% "webapps.pastebin" browse-webapp-source %></p>
+            </div>
+        </td>
+    </tr>
+</table>
+
+<% "footer" render-template %>
diff --git a/unmaintained/webapps/pastebin/paste-summary.furnace b/unmaintained/webapps/pastebin/paste-summary.furnace
new file mode 100644 (file)
index 0000000..dc25fe1
--- /dev/null
@@ -0,0 +1,12 @@
+<% USING: continuations namespaces io kernel math math.parser
+furnace webapps.pastebin calendar sequences ; %>
+
+<tr>
+    <td>
+        <a href="<% model get paste-link write %>">
+        <% "summary" get write %>
+        </a>
+    </td>
+    <td><% "author" get write %></td>
+    <td><% "date" get timestamp>string write %></td>
+</tr>
diff --git a/unmaintained/webapps/pastebin/pastebin.factor b/unmaintained/webapps/pastebin/pastebin.factor
new file mode 100755 (executable)
index 0000000..36a7279
--- /dev/null
@@ -0,0 +1,119 @@
+USING: calendar furnace furnace.validator io.files kernel
+namespaces sequences http.server.responders html math.parser rss
+xml.writer xmode.code2html math calendar.format ;
+IN: webapps.pastebin
+
+TUPLE: pastebin pastes ;
+
+: <pastebin> ( -- pastebin )
+    V{ } clone pastebin construct-boa ;
+
+<pastebin> pastebin set-global
+
+TUPLE: paste
+summary author channel mode contents date
+annotations n ;
+
+: <paste> ( summary author channel mode contents -- paste )
+    f V{ } clone f paste construct-boa ;
+
+TUPLE: annotation summary author mode contents ;
+
+C: <annotation> annotation
+
+: get-paste ( n -- paste )
+    pastebin get pastebin-pastes nth ;
+
+: show-paste ( n -- )
+    serving-html
+    get-paste
+    [ "show-paste" render-component ] with-html-stream ;
+
+\ show-paste { { "n" v-number } } define-action
+
+: new-paste ( -- )
+    serving-html
+    [ "new-paste" render-template ] with-html-stream ;
+
+\ new-paste { } define-action
+
+: paste-list ( -- )
+    serving-html
+    [
+        [ show-paste ] "show-paste-quot" set
+        [ new-paste ] "new-paste-quot" set
+        pastebin get "paste-list" render-component
+    ] with-html-stream ;
+
+\ paste-list { } define-action
+
+: paste-link ( paste -- link )
+    paste-n number>string [ show-paste ] curry quot-link ;
+
+: safe-head ( seq n -- seq' )
+    over length min head ;
+
+: paste-feed ( -- entries )
+    pastebin get pastebin-pastes <reversed> 20 safe-head [
+        {
+            paste-summary
+            paste-link
+            paste-date
+        } get-slots timestamp>rfc3339 f swap <entry>
+    ] map ;
+
+: feed.xml ( -- )
+    "text/xml" serving-content
+    "pastebin"
+    "http://pastebin.factorcode.org"
+    paste-feed <feed> feed>xml write-xml ;
+
+\ feed.xml { } define-action
+
+: add-paste ( paste pastebin -- )
+    >r now over set-paste-date r>
+    pastebin-pastes 2dup length swap set-paste-n push ;
+
+: submit-paste ( summary author channel mode contents -- )
+    <paste> [ pastebin get add-paste ] keep
+    paste-link permanent-redirect ;
+
+\ new-paste
+\ submit-paste {
+    { "summary" v-required }
+    { "author" v-required }
+    { "channel" }
+    { "mode" v-required }
+    { "contents" v-required }
+} define-form
+
+\ new-paste {
+    { "channel" "#concatenative" }
+    { "mode" "factor" }
+} default-values
+
+: annotate-paste ( n summary author mode contents -- )
+    <annotation> swap get-paste
+    [ paste-annotations push ] keep
+    paste-link permanent-redirect ;
+
+[ "n" show-paste ]
+\ annotate-paste {
+    { "n" v-required v-number }
+    { "summary" v-required }
+    { "author" v-required }
+    { "mode" v-required }
+    { "contents" v-required }
+} define-form
+
+\ show-paste {
+    { "mode" "factor" }
+} default-values
+
+: style.css ( -- )
+    "text/css" serving-content
+    "style.css" send-resource ;
+
+\ style.css { } define-action
+
+"pastebin" "paste-list" "extra/webapps/pastebin" web-app
diff --git a/unmaintained/webapps/pastebin/show-paste.furnace b/unmaintained/webapps/pastebin/show-paste.furnace
new file mode 100755 (executable)
index 0000000..30129ed
--- /dev/null
@@ -0,0 +1,21 @@
+<% USING: namespaces io furnace sequences xmode.code2html calendar ; %>
+
+<%
+    "Paste: " "summary" get append "title" set
+    "header" render-template
+%>
+
+<table>
+<tr><th>Paste by:</th><td><% "author" get write %></td></tr>
+<!-- <tr><th>Channel:</th><td><% "channel" get write %></td></tr> -->
+<tr><th>Created:</th><td><% "date" get timestamp>string write %></td></tr>
+<tr><th>File type:</th><td><% "mode" get write %></td></tr>
+</table>
+
+<% "syntax" render-template %>
+
+<% "annotations" get [ "annotation" render-component ] each %>
+
+<% model get "annotate-paste" render-component %>
+
+<% "footer" render-template %>
diff --git a/unmaintained/webapps/pastebin/style.css b/unmaintained/webapps/pastebin/style.css
new file mode 100644 (file)
index 0000000..4a469f9
--- /dev/null
@@ -0,0 +1,41 @@
+body {
+       font:75%/1.6em "Lucida Grande", "Lucida Sans Unicode", verdana, geneva, sans-serif;
+       color:#888;
+}
+
+h1.pastebin-title {
+       font-size:300%;
+}
+
+a {
+       color:#222;
+       border-bottom:1px dotted #ccc;
+       text-decoration:none;
+}
+
+a:hover {
+       border-bottom:1px solid #ccc;
+}
+
+pre.code {
+       border:1px dashed #ccc;
+       background-color:#f5f5f5;
+       padding:5px;
+       font-size:150%;
+       color:#000000;
+}
+
+.navbar {
+       background-color:#eeeeee;
+       padding:5px;
+       border:1px solid #ccc;
+}
+
+.infobox {
+       border: 1px solid #C1DAD7;
+       padding: 10px;
+}
+
+.error {
+       color: red;
+}
diff --git a/unmaintained/webapps/pastebin/syntax.furnace b/unmaintained/webapps/pastebin/syntax.furnace
new file mode 100755 (executable)
index 0000000..17b64b9
--- /dev/null
@@ -0,0 +1,3 @@
+<% USING: xmode.code2html splitting namespaces ; %>
+
+<pre class="code"><% "contents" get string-lines "mode" get htmlize-lines %></pre>
diff --git a/unmaintained/webapps/planet/authors.txt b/unmaintained/webapps/planet/authors.txt
new file mode 100755 (executable)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/unmaintained/webapps/planet/planet.factor b/unmaintained/webapps/planet/planet.factor
new file mode 100755 (executable)
index 0000000..9a5f8ee
--- /dev/null
@@ -0,0 +1,129 @@
+USING: sequences rss arrays concurrency.combinators kernel
+sorting html.elements io assocs namespaces math threads vocabs
+html furnace http.server.templating calendar math.parser
+splitting continuations debugger system http.server.responders
+xml.writer prettyprint logging calendar.format ;
+IN: webapps.planet
+
+: print-posting-summary ( posting -- )
+    <p "news" =class p>
+        <b> dup entry-title write </b> <br/>
+        <a entry-link =href "more" =class a>
+            "Read More..." write
+        </a>
+    </p> ;
+
+: print-posting-summaries ( postings -- )
+    [ print-posting-summary ] each ;
+
+: print-blogroll ( blogroll -- )
+    <ul "description" =class ul>
+        [
+            <li> <a dup third =href a> first write </a> </li>
+        ] each
+    </ul> ;
+
+: format-date ( date -- string )
+    rfc3339>timestamp timestamp>string ;
+
+: print-posting ( posting -- )
+    <h2 "posting-title" =class h2>
+        <a dup entry-link =href a>
+            dup entry-title write-html
+        </a>
+    </h2>
+    <p "posting-body" =class p>
+        dup entry-description write-html
+    </p>
+    <p "posting-date" =class p>
+        entry-pub-date format-date write
+    </p> ;
+
+: print-postings ( postings -- )
+    [ print-posting ] each ;
+
+SYMBOL: default-blogroll
+SYMBOL: cached-postings
+
+: safe-head ( seq n -- seq' )
+    over length min head ;
+
+: mini-planet-factor ( -- )
+    cached-postings get 4 safe-head print-posting-summaries ;
+
+: planet-factor ( -- )
+    serving-html [ "planet" render-template ] with-html-stream ;
+
+\ planet-factor { } define-action
+
+: planet-feed ( -- feed )
+    "[ planet-factor ]"
+    "http://planet.factorcode.org"
+    cached-postings get 30 safe-head <feed> ;
+
+: feed.xml ( -- )
+    "text/xml" serving-content
+    planet-feed feed>xml write-xml ;
+
+\ feed.xml { } define-action
+
+: style.css ( -- )
+    "text/css" serving-content
+    "style.css" send-resource ;
+
+\ style.css { } define-action
+
+SYMBOL: last-update
+
+: <posting> ( author entry -- entry' )
+    clone
+    [ ": " swap entry-title 3append ] keep
+    [ set-entry-title ] keep ;
+
+: fetch-feed ( url -- feed )
+    download-feed feed-entries ;
+
+\ fetch-feed DEBUG add-error-logging
+
+: fetch-blogroll ( blogroll -- entries )
+    dup 0 <column> swap 1 <column>
+    [ fetch-feed ] parallel-map
+    [ [ <posting> ] with map ] 2map concat ;
+
+: sort-entries ( entries -- entries' )
+    [ [ entry-pub-date ] compare ] sort <reversed> ;
+
+: update-cached-postings ( -- )
+    default-blogroll get
+    fetch-blogroll sort-entries
+    cached-postings set-global ;
+
+: update-thread ( -- )
+    millis last-update set-global
+    [ update-cached-postings ] "RSS feed update slave" spawn drop
+    10 60 * 1000 * sleep
+    update-thread ;
+
+: start-update-thread ( -- )
+    [
+        "webapps.planet" [
+            update-thread
+        ] with-logging
+    ] "RSS feed update master" spawn drop ;
+
+"planet" "planet-factor" "extra/webapps/planet" web-app
+
+{
+    { "Berlin Brown" "http://factorlang-fornovices.blogspot.com/feeds/posts/default" "http://factorlang-fornovices.blogspot.com" }
+    { "Chris Double" "http://www.blogger.com/feeds/18561009/posts/full/-/factor" "http://www.bluishcoder.co.nz/" }
+    { "Elie Chaftari" "http://fun-factor.blogspot.com/feeds/posts/default" "http://fun-factor.blogspot.com/" }
+    { "Doug Coleman" "http://code-factor.blogspot.com/feeds/posts/default" "http://code-factor.blogspot.com/" }
+    { "Daniel Ehrenberg" "http://useless-factor.blogspot.com/feeds/posts/default" "http://useless-factor.blogspot.com/" }
+    { "Gavin Harrison" "http://gmh33.blogspot.com/feeds/posts/default" "http://gmh33.blogspot.com/" }
+    { "Kio M. Smallwood"
+    "http://sekenre.wordpress.com/feed/atom/"
+    "http://sekenre.wordpress.com/" }
+    { "Phil Dawes" "http://www.phildawes.net/blog/category/factor/feed/atom" "http://www.phildawes.net/blog/" }
+    { "Samuel Tardieu" "http://www.rfc1149.net/blog/tag/factor/feed/atom/" "http://www.rfc1149.net/blog/tag/factor/" }
+    { "Slava Pestov" "http://factor-language.blogspot.com/atom.xml" "http://factor-language.blogspot.com/" }
+} default-blogroll set-global
diff --git a/unmaintained/webapps/planet/planet.furnace b/unmaintained/webapps/planet/planet.furnace
new file mode 100644 (file)
index 0000000..4c6676c
--- /dev/null
@@ -0,0 +1,45 @@
+<% USING: namespaces html.elements webapps.planet sequences
+furnace ; %>
+
+<!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">
+<head>
+       <meta http-equiv="Content-type" content="text/html; charset=utf-8" />
+
+       <title>planet-factor</title>
+       <link rel="stylesheet" href="style.css" type="text/css" media="screen" title="no title" charset="utf-8" />
+    <link rel="alternate" type="application/atom+xml" title="Planet Factor - Atom" href="feed.xml" />
+</head>
+
+<body id="index">
+    <h1 class="planet-title">[ planet-factor ]</h1>
+    <table width="100%" cellpadding="10">
+        <tr>
+            <td> <% cached-postings get 20 safe-head print-postings %> </td>
+            <td valign="top" width="25%" class="infobox">
+                <p>
+                    <b>planet-factor</b> is an Atom/RSS aggregator that collects the
+                    contents of <a href="http://factorcode.org/">Factor</a>-related blogs. It is inspired by
+                    <a href="http://planet.lisp.org">Planet Lisp</a>.
+                </p>
+                <p>
+                    <img src="http://planet.lisp.org/feed-icon-14x14.png" />
+                    <a href="feed.xml"> Syndicate </a>
+                </p>
+                <p>
+                    This webapp is written in <a href="http://factorcode.org/">Factor</a>.<br/>
+                    <% "webapps.planet" browse-webapp-source %>
+                </p>
+                <h2 class="blogroll-title">Blogroll</h2>
+                <% default-blogroll get print-blogroll %>
+                <p>
+                    If you want your weblog added to the blogroll, <a href="http://factorcode.org/gethelp.fhtml">just ask</a>.
+                </p>
+            </td>
+        </tr>
+    </table>
+</body>
+
+</html>
diff --git a/unmaintained/webapps/planet/style.css b/unmaintained/webapps/planet/style.css
new file mode 100644 (file)
index 0000000..7a66d8d
--- /dev/null
@@ -0,0 +1,45 @@
+body {
+       font:75%/1.6em "Lucida Grande", "Lucida Sans Unicode", verdana, geneva, sans-serif;
+       color:#888;
+}
+
+h1.planet-title {
+       font-size:300%;
+}
+
+a {
+       color:#222;
+       border-bottom:1px dotted #ccc;
+       text-decoration:none;
+}
+
+a:hover {
+       border-bottom:1px solid #ccc;
+}
+
+.posting-title {
+       background-color:#f5f5f5;
+}
+
+pre, code {
+       color:#000000;
+       font-size:120%;
+}
+
+.infobox {
+       border-left: 1px solid #C1DAD7;
+}
+
+.posting-date {
+       text-align: right;
+       font-size:90%;
+}
+
+a.more {
+       display:block;
+       padding:0 0 5px 0;
+       color:#333;
+       text-decoration:none;
+       text-align:right;
+       border:none;
+}
diff --git a/vm/io.c b/vm/io.c
index d3a29abe72eea20d232561803615dde8c2e4e312..faf681bbefe0498b5482cc158acc29ab920d3090 100755 (executable)
--- a/vm/io.c
+++ b/vm/io.c
@@ -102,21 +102,46 @@ DEFINE_PRIMITIVE(fread)
                }
                else
                {
-                       dpush(tag_object(memory_to_char_string(
-                               (char *)(buf + 1),c)));
+                       if(c != size)
+                       {
+                               REGISTER_UNTAGGED(buf);
+                               F_BYTE_ARRAY *new_buf = allot_byte_array(c);
+                               UNREGISTER_UNTAGGED(buf);
+                               memcpy(new_buf + 1, buf + 1,c);
+                               buf = new_buf;
+                       }
+                       dpush(tag_object(buf));
                        break;
                }
        }
 }
 
+DEFINE_PRIMITIVE(fputc)
+{
+       FILE *file = unbox_alien();
+       F_FIXNUM ch = to_fixnum(dpop());
+
+       for(;;)
+       {
+               if(fputc(ch,file) == EOF)
+               {
+                       io_error();
+
+                       /* Still here? EINTR */
+               }
+               else
+                       break;
+       }
+}
+
 DEFINE_PRIMITIVE(fwrite)
 {
-       FILEfile = unbox_alien();
-       F_STRING* text = untag_string(dpop());
-       F_FIXNUM length = untag_fixnum_fast(text->length);
-       char* string = to_char_string(text,false);
+       FILE *file = unbox_alien();
+       F_BYTE_ARRAY *text = untag_byte_array(dpop());
+       F_FIXNUM length = array_capacity(text);
+       char *string = (char *)(text + 1);
 
-       if(string_capacity(text) == 0)
+       if(length == 0)
                return;
 
        for(;;)
diff --git a/vm/io.h b/vm/io.h
index 39e7390c3e5bc200d26c23070919777d74472af0..a19da3887c5e9d5863008e037a14cfe1eebcbc96 100755 (executable)
--- a/vm/io.h
+++ b/vm/io.h
@@ -3,11 +3,12 @@ void io_error(void);
 int err_no(void);
 
 DECLARE_PRIMITIVE(fopen);
+DECLARE_PRIMITIVE(fgetc);
+DECLARE_PRIMITIVE(fread);
+DECLARE_PRIMITIVE(fputc);
 DECLARE_PRIMITIVE(fwrite);
 DECLARE_PRIMITIVE(fflush);
 DECLARE_PRIMITIVE(fclose);
-DECLARE_PRIMITIVE(fgetc);
-DECLARE_PRIMITIVE(fread);
 
 /* Platform specific primitives */
 DECLARE_PRIMITIVE(open_file);
index a84b29c2e2023c3a8d60df235037d5e4aeb83f15..37dceb0d378ad89591b8d890827b41f142505b46 100755 (executable)
@@ -117,6 +117,29 @@ DEFINE_PRIMITIVE(os_envs)
        dpush(result);
 }
 
+DEFINE_PRIMITIVE(set_os_envs)
+{
+       F_ARRAY *array = untag_array(dpop());
+       CELL size = array_capacity(array);
+
+       /* Memory leak */
+       char **env = calloc(size + 1,sizeof(CELL));
+
+       CELL i;
+       for(i = 0; i < size; i++)
+       {
+               F_STRING *string = untag_string(array_nth(array,i));
+               CELL length = to_fixnum(string->length);
+
+               char *chars = malloc(length + 1);
+               char_string_to_memory(string,chars);
+               chars[length] = '\0';
+               env[i] = chars;
+       }
+
+       environ = env;
+}
+
 F_SEGMENT *alloc_segment(CELL size)
 {
        int pagesize = getpagesize();
index e28debd44987b8ca26bbe2c19db9466cd2f338ac..f9b80ea32a1d7ac21be74b9ae8e367672e0f92ac 100755 (executable)
@@ -233,3 +233,8 @@ void sleep_millis(DWORD msec)
 {
        Sleep(msec);
 }
+
+DECLARE_PRIMITIVE(set_os_envs)
+{
+       not_implemented_error();
+}
index a5cdb4f1ef08057e5c7e92eb968b20a55b20626f..d1d956dca0bd3bdcce76355723e186cd8b5d46be 100755 (executable)
@@ -162,6 +162,7 @@ void *primitives[] = {
        primitive_fopen,
        primitive_fgetc,
        primitive_fread,
+       primitive_fputc,
        primitive_fwrite,
        primitive_fflush,
        primitive_fclose,
@@ -185,6 +186,7 @@ void *primitives[] = {
        primitive_set_innermost_stack_frame_quot,
        primitive_call_clear,
        primitive_os_envs,
+       primitive_set_os_envs,
        primitive_resize_byte_array,
        primitive_resize_bit_array,
        primitive_resize_float_array,
index f9b80570693428df0f21ae60891f25d16d628cf7..216a00b27de528101e5df8ccd0cc31ef3c1754ab 100755 (executable)
--- a/vm/run.h
+++ b/vm/run.h
@@ -249,6 +249,7 @@ DECLARE_PRIMITIVE(setenv);
 DECLARE_PRIMITIVE(exit);
 DECLARE_PRIMITIVE(os_env);
 DECLARE_PRIMITIVE(os_envs);
+DECLARE_PRIMITIVE(set_os_envs);
 DECLARE_PRIMITIVE(eq);
 DECLARE_PRIMITIVE(millis);
 DECLARE_PRIMITIVE(sleep);