]> gitweb.factorcode.org Git - factor.git/commitdiff
Merge branch 'master' of git://factorcode.org/git/factor
authorslava <slava@slava-laptop.(none)>
Sat, 13 Dec 2008 06:09:42 +0000 (00:09 -0600)
committerslava <slava@slava-laptop.(none)>
Sat, 13 Dec 2008 06:09:42 +0000 (00:09 -0600)
137 files changed:
basis/alien/c-types/c-types-tests.factor
basis/alien/syntax/syntax-docs.factor
basis/alien/syntax/syntax.factor
basis/bootstrap/stage2.factor
basis/cocoa/application/application-docs.factor
basis/cocoa/application/application.factor
basis/cocoa/cocoa.factor
basis/cocoa/dialogs/dialogs.factor
basis/cocoa/nibs/nibs.factor
basis/cocoa/pasteboard/pasteboard.factor
basis/cocoa/plists/plists.factor
basis/cocoa/views/views.factor
basis/compiler/tests/alien.factor
basis/core-foundation/arrays/arrays-docs.factor [new file with mode: 0644]
basis/core-foundation/arrays/arrays.factor [new file with mode: 0644]
basis/core-foundation/arrays/tags.txt [new file with mode: 0644]
basis/core-foundation/bundles/bundles-docs.factor [new file with mode: 0644]
basis/core-foundation/bundles/bundles.factor [new file with mode: 0644]
basis/core-foundation/bundles/tags.txt [new file with mode: 0644]
basis/core-foundation/core-foundation-docs.factor
basis/core-foundation/core-foundation-tests.factor [deleted file]
basis/core-foundation/core-foundation.factor
basis/core-foundation/data/data.factor [new file with mode: 0644]
basis/core-foundation/data/tags.txt [new file with mode: 0644]
basis/core-foundation/file-descriptors/file-descriptors.factor [new file with mode: 0644]
basis/core-foundation/file-descriptors/tags.txt [new file with mode: 0644]
basis/core-foundation/fsevents/fsevents.factor
basis/core-foundation/run-loop/run-loop.factor
basis/core-foundation/run-loop/thread/authors.txt [deleted file]
basis/core-foundation/run-loop/thread/summary.txt [deleted file]
basis/core-foundation/run-loop/thread/tags.txt [deleted file]
basis/core-foundation/run-loop/thread/thread.factor [deleted file]
basis/core-foundation/strings/strings-docs.factor [new file with mode: 0644]
basis/core-foundation/strings/strings-tests.factor [new file with mode: 0644]
basis/core-foundation/strings/strings.factor [new file with mode: 0644]
basis/core-foundation/strings/tags.txt [new file with mode: 0644]
basis/core-foundation/timers/tags.txt [new file with mode: 0644]
basis/core-foundation/timers/timers.factor [new file with mode: 0644]
basis/core-foundation/urls/tags.txt [new file with mode: 0644]
basis/core-foundation/urls/urls-docs.factor [new file with mode: 0644]
basis/core-foundation/urls/urls.factor [new file with mode: 0644]
basis/cpu/x86/32/bootstrap.factor
basis/cpu/x86/64/unix/bootstrap.factor
basis/cpu/x86/64/winnt/bootstrap.factor
basis/cpu/x86/bootstrap.factor
basis/environment/unix/unix.factor
basis/http/client/client.factor
basis/io/launcher/launcher-docs.factor
basis/io/launcher/launcher.factor
basis/io/thread/thread.factor
basis/io/unix/backend/backend.factor
basis/io/unix/bsd/bsd.factor
basis/io/unix/epoll/epoll.factor
basis/io/unix/files/freebsd/freebsd.factor
basis/io/unix/files/linux/linux.factor
basis/io/unix/files/netbsd/netbsd.factor
basis/io/unix/files/openbsd/openbsd.factor
basis/io/unix/kqueue/kqueue.factor
basis/io/unix/launcher/launcher-tests.factor
basis/io/unix/launcher/launcher.factor
basis/io/unix/linux/linux.factor
basis/io/unix/linux/monitors/monitors.factor
basis/io/unix/macosx/macosx.factor
basis/io/unix/multiplexers/epoll/authors.txt [new file with mode: 0755]
basis/io/unix/multiplexers/epoll/epoll.factor [new file with mode: 0644]
basis/io/unix/multiplexers/epoll/tags.txt [new file with mode: 0644]
basis/io/unix/multiplexers/kqueue/authors.txt [new file with mode: 0755]
basis/io/unix/multiplexers/kqueue/kqueue.factor [new file with mode: 0644]
basis/io/unix/multiplexers/kqueue/tags.txt [new file with mode: 0644]
basis/io/unix/multiplexers/multiplexers.factor [new file with mode: 0644]
basis/io/unix/multiplexers/run-loop/run-loop.factor [new file with mode: 0644]
basis/io/unix/multiplexers/run-loop/tags.txt [new file with mode: 0644]
basis/io/unix/multiplexers/select/authors.txt [new file with mode: 0755]
basis/io/unix/multiplexers/select/select.factor [new file with mode: 0644]
basis/io/unix/multiplexers/select/tags.txt [new file with mode: 0644]
basis/io/unix/select/select.factor
basis/stack-checker/alien/alien.factor
basis/tools/deploy/deploy-tests.factor
basis/tools/deploy/test/3/deploy.factor
basis/tools/deploy/test/9/9.factor [new file with mode: 0644]
basis/tools/deploy/test/9/deploy.factor [new file with mode: 0644]
basis/tools/disassembler/disassembler-docs.factor
basis/tools/disassembler/disassembler.factor
basis/tools/disassembler/gdb/gdb.factor [new file with mode: 0644]
basis/tools/disassembler/gdb/tags.txt [new file with mode: 0644]
basis/tools/disassembler/udis/tags.txt [new file with mode: 0644]
basis/tools/disassembler/udis/udis.factor [new file with mode: 0644]
basis/tools/files/files.factor
basis/ui/backend/backend.factor [changed mode: 0644->0755]
basis/ui/cocoa/cocoa.factor [changed mode: 0644->0755]
basis/ui/cocoa/tools/tools.factor
basis/ui/cocoa/views/views.factor
basis/ui/event-loop/event-loop.factor [new file with mode: 0644]
basis/ui/gadgets/worlds/worlds-docs.factor
basis/ui/gadgets/worlds/worlds.factor
basis/ui/gestures/gestures-docs.factor
basis/ui/gestures/gestures.factor
basis/ui/ui-docs.factor
basis/ui/ui.factor
basis/ui/windows/windows.factor
basis/ui/x11/x11.factor
basis/unix/process/process.factor
basis/windows/gdi32/gdi32.factor [changed mode: 0644->0755]
basis/windows/opengl32/opengl32.factor [changed mode: 0644->0755]
basis/windows/types/types.factor [changed mode: 0644->0755]
basis/x11/glx/glx.factor
basis/x11/windows/windows.factor
basis/x11/xlib/xlib.factor
core/alien/alien.factor
core/byte-arrays/byte-arrays-tests.factor
core/io/backend/backend.factor
core/memory/memory-tests.factor
core/sequences/sequences.factor
extra/benchmark/benchmark.factor
extra/flatland/flatland.factor
extra/fuel/fuel.factor
extra/graphics/bitmap/bitmap.factor
extra/iokit/iokit.factor
extra/key-caps/key-caps.factor
extra/literals/literals-tests.factor [new file with mode: 0644]
extra/literals/literals.factor [new file with mode: 0644]
extra/pong/pong.factor
extra/ui/offscreen/authors.txt [new file with mode: 0644]
extra/ui/offscreen/offscreen-docs.factor [new file with mode: 0644]
extra/ui/offscreen/offscreen.factor [new file with mode: 0755]
extra/ui/offscreen/summary.txt [new file with mode: 0644]
extra/ui/offscreen/tags.txt [new file with mode: 0644]
misc/fuel/README
misc/fuel/fuel-base.el
misc/fuel/fuel-connection.el [new file with mode: 0644]
misc/fuel/fuel-debug.el
misc/fuel/fuel-eval.el
misc/fuel/fuel-font-lock.el
misc/fuel/fuel-help.el
misc/fuel/fuel-listener.el
misc/fuel/fuel-mode.el
vm/Config.macosx

index f57d102452ca132031787331aef8201729158683..31542b2699eb94224500aa3c5fe181e47d4f9fa0 100644 (file)
@@ -8,7 +8,7 @@ sequences system libc alien.strings io.encodings.utf8 ;
 
 [ { "blah" 123 } ] [ { "blah" xyz } expand-constants ] unit-test
 
-: foo ( -- n ) "fdafd" f dlsym [ 123 ] unless* ;
+: foo ( -- n ) &: fdafd [ 123 ] unless* ;
 
 [ 123 ] [ foo ] unit-test
 
index 586bb974028978b2e78e663c9b6061f21d49d0bf..a3215cd8c6ae737c739fd18208565f819aab6e04 100644 (file)
@@ -77,6 +77,11 @@ HELP: C-ENUM:
     { $code "C-ENUM: red green blue ;" ": red 0 ;  : green 1 ;  : blue 2 ;" }
 } ;
 
+HELP: &:
+{ $syntax "&: symbol" }
+{ $values { "symbol" "A C library symbol name" } }
+{ $description "Pushes the address of a symbol named " { $snippet "symbol" } " from the current library, set with " { $link POSTPONE: LIBRARY: } "." } ;
+
 HELP: typedef
 { $values { "old" "a string" } { "new" "a string" } }
 { $description "Alises the C type " { $snippet "old" } " under the name " { $snippet "new" } "." }
index b0ba10a316176e501699e8487a993e168d50f482..15d82884f9c82e6fa18bd4e3511a94471efe1f35 100644 (file)
@@ -3,7 +3,8 @@
 USING: accessors arrays alien alien.c-types alien.structs
 alien.arrays alien.strings kernel math namespaces parser
 sequences words quotations math.parser splitting grouping
-effects assocs combinators lexer strings.parser alien.parser ;
+effects assocs combinators lexer strings.parser alien.parser 
+fry ;
 IN: alien.syntax
 
 : DLL" lexer get skip-blank parse-string dlopen parsed ; parsing
@@ -33,3 +34,7 @@ IN: alien.syntax
     dup length
     [ [ create-in ] dip 1quotation define ] 2each ;
     parsing
+
+: &:
+    scan "c-library" get
+    '[ _ _ load-library dlsym ] over push-all ; parsing
index fb7292b989caaa7508711711a014c8d935dc27f7..45a6c354a69cad0069a3af12e88013a147b37f2a 100644 (file)
@@ -102,6 +102,8 @@ SYMBOL: bootstrap-time
     ] if
 ] [
     drop
-    load-help? off
-    "resource:basis/bootstrap/bootstrap-error.factor" run-file
+    [
+        load-help? off
+        "resource:basis/bootstrap/bootstrap-error.factor" run-file
+    ] with-scope
 ] recover
index 791613e876ee7747bdae4902555adab3c2385f85..e12b6eb2765e78e0fa0b306937a36b2885cdb83e 100644 (file)
@@ -1,5 +1,5 @@
 USING: debugger quotations help.markup help.syntax strings alien
-core-foundation ;
+core-foundation core-foundation.strings core-foundation.arrays ;
 IN: cocoa.application
 
 HELP: <NSString>
index e2c853ea77ed19d0c7fbd48f62f65a497a9c97ab..a52aaedce27d226623a7e51bbb813b7caa1fef93 100644 (file)
@@ -1,9 +1,10 @@
 ! Copyright (C) 2006, 2008 Slava Pestov
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien alien.syntax io kernel namespaces core-foundation
-core-foundation.run-loop cocoa.messages cocoa cocoa.classes
-cocoa.runtime sequences threads init summary kernel.private
-assocs ;
+core-foundation.run-loop core-foundation.arrays
+core-foundation.data core-foundation.strings cocoa.messages
+cocoa cocoa.classes cocoa.runtime sequences threads init summary
+kernel.private assocs ;
 IN: cocoa.application
 
 : <NSString> ( str -- alien ) <CFString> -> autorelease ;
index ab86796236108bd5251620060c753e751dabaff5..44252a3b19fd35aa1b6e7314fb91573ff25a62d6 100644 (file)
@@ -2,8 +2,8 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: compiler io kernel cocoa.runtime cocoa.subclassing
 cocoa.messages cocoa.types sequences words vocabs parser
-core-foundation namespaces assocs hashtables compiler.units
-lexer init ;
+core-foundation.bundles namespaces assocs hashtables
+compiler.units lexer init ;
 IN: cocoa
 
 : (remember-send) ( selector variable -- )
index 2b01c5d751215eced96995d3e87779e27f7c4930..13f6f0b7d61f2f2ad24948f7e0ad4b98957456cc 100644 (file)
@@ -1,7 +1,8 @@
 ! Copyright (C) 2006, 2008 Slava Pestov
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel cocoa cocoa.messages cocoa.classes
-cocoa.application sequences splitting core-foundation ;
+cocoa.application sequences splitting core-foundation
+core-foundation.strings ;
 IN: cocoa.dialogs
 
 : <NSOpenPanel> ( -- panel )
index 31dac2531b532d161f86922c4f883764f7280109..a39cc794d0f09d2f41f2468d563975f2a54c8896 100644 (file)
@@ -1,5 +1,8 @@
-USING: cocoa.application cocoa.messages cocoa.classes cocoa.runtime 
-kernel cocoa core-foundation alien.c-types ;
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: cocoa.application cocoa.messages cocoa.classes
+cocoa.runtime kernel cocoa alien.c-types core-foundation
+core-foundation.arrays ;
 IN: cocoa.nibs
 
 : load-nib ( name -- )
index b530ccbc3760620e0e1abb1a70d1f35efbe58c3b..888f5452e2d619c5e9097a7b37243a48159cf11e 100644 (file)
@@ -1,8 +1,8 @@
 ! Copyright (C) 2006, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien.accessors arrays kernel cocoa.messages
-cocoa.classes cocoa.application cocoa core-foundation sequences
-;
+cocoa.classes cocoa.application sequences cocoa core-foundation
+core-foundation.strings core-foundation.arrays ;
 IN: cocoa.pasteboard
 
 : NSStringPboardType "NSStringPboardType" ;
index bb73b8fac31b4901d24bc08785796a2d71a2a7eb..cf68f9864ae059ec7c4d46c63e040a21198e0ab7 100644 (file)
@@ -3,7 +3,7 @@
 USING: strings arrays hashtables assocs sequences
 cocoa.messages cocoa.classes cocoa.application cocoa kernel
 namespaces io.backend math cocoa.enumeration byte-arrays
-combinators alien.c-types core-foundation ;
+combinators alien.c-types core-foundation core-foundation.data ;
 IN: cocoa.plists
 
 GENERIC: >plist ( value -- plist )
index be67f03184e12347b8596f897c6c3c8ce16b1663..03cafd0a0a895bd414a1ce9d57459d6946ca6440 100644 (file)
@@ -55,10 +55,9 @@ PRIVATE>
 : with-multisample ( quot -- )
     t +multisample+ pick with-variable ; inline
 
-: <PixelFormat> ( -- pixelfmt )
-    NSOpenGLPixelFormat -> alloc [
-        NSOpenGLPFAWindow ,
-        NSOpenGLPFADoubleBuffer ,
+: <PixelFormat> ( attributes -- pixelfmt )
+    NSOpenGLPixelFormat -> alloc swap [
+        %
         NSOpenGLPFADepthSize , 16 ,
         +software-renderer+ get [
             NSOpenGLPFARendererID , kCGLRendererGenericFloatID ,
@@ -74,7 +73,8 @@ PRIVATE>
     -> autorelease ;
 
 : <GLView> ( class dim -- view )
-    [ -> alloc 0 0 ] dip first2 <NSRect> <PixelFormat>
+    [ -> alloc 0 0 ] dip first2 <NSRect>
+    NSOpenGLPFAWindow NSOpenGLPFADoubleBuffer 2array <PixelFormat>
     -> initWithFrame:pixelFormat:
     dup 1 -> setPostsBoundsChangedNotifications:
     dup 1 -> setPostsFrameChangedNotifications: ;
index 230a7bf54213379bd5fcc0ccd66c31c05c4ed049..1b21e40bace1c762d5dd211f8ccebc53a6719f3d 100644 (file)
@@ -83,14 +83,14 @@ FUNCTION: tiny ffi_test_17 int x ;
 
 { 1 1 } [ indirect-test-1 ] must-infer-as
 
-[ 3 ] [ "ffi_test_1" f dlsym indirect-test-1 ] unit-test
+[ 3 ] [ &: ffi_test_1 indirect-test-1 ] unit-test
 
 : indirect-test-1' ( ptr -- )
     "int" { } "cdecl" alien-indirect drop ;
 
 { 1 0 } [ indirect-test-1' ] must-infer-as
 
-[ ] [ "ffi_test_1" f dlsym indirect-test-1' ] unit-test
+[ ] [ &: ffi_test_1 indirect-test-1' ] unit-test
 
 [ -1 indirect-test-1 ] must-fail
 
@@ -100,7 +100,7 @@ FUNCTION: tiny ffi_test_17 int x ;
 { 3 1 } [ indirect-test-2 ] must-infer-as
 
 [ 5 ]
-[ 2 3 "ffi_test_2" f dlsym indirect-test-2 ]
+[ 2 3 &: ffi_test_2 indirect-test-2 ]
 unit-test
 
 : indirect-test-3 ( a b c d ptr -- result )
diff --git a/basis/core-foundation/arrays/arrays-docs.factor b/basis/core-foundation/arrays/arrays-docs.factor
new file mode 100644 (file)
index 0000000..36d14a8
--- /dev/null
@@ -0,0 +1,11 @@
+USING: help.syntax help.markup arrays alien ;
+IN: core-foundation.arrays
+
+HELP: CF>array
+{ $values { "alien" "a " { $snippet "CFArray" } } { "array" "an array of " { $link alien } " instances" } }
+{ $description "Creates a Factor array from a Core Foundation array." } ;
+
+HELP: <CFArray>
+{ $values { "seq" "a sequence of " { $link alien } " instances" } { "alien" "a " { $snippet "CFArray" } } }
+{ $description "Creates a Core Foundation array from a Factor array." } ;
+
diff --git a/basis/core-foundation/arrays/arrays.factor b/basis/core-foundation/arrays/arrays.factor
new file mode 100644 (file)
index 0000000..3708059
--- /dev/null
@@ -0,0 +1,22 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: alien.syntax kernel sequences ;
+IN: core-foundation.arrays
+
+TYPEDEF: void* CFArrayRef
+
+FUNCTION: CFArrayRef CFArrayCreateMutable ( CFAllocatorRef allocator, CFIndex capacity, void* callbacks ) ;
+
+FUNCTION: void* CFArrayGetValueAtIndex ( CFArrayRef array, CFIndex idx ) ;
+
+FUNCTION: void CFArraySetValueAtIndex ( CFArrayRef array, CFIndex index, void* value ) ;
+
+FUNCTION: CFIndex CFArrayGetCount ( CFArrayRef array ) ;
+
+: CF>array ( alien -- array )
+    dup CFArrayGetCount [ CFArrayGetValueAtIndex ] with map ;
+
+: <CFArray> ( seq -- alien )
+    [ f swap length f CFArrayCreateMutable ] keep
+    [ length ] keep
+    [ [ dupd ] dip CFArraySetValueAtIndex ] 2each ;
diff --git a/basis/core-foundation/arrays/tags.txt b/basis/core-foundation/arrays/tags.txt
new file mode 100644 (file)
index 0000000..2320bdd
--- /dev/null
@@ -0,0 +1,2 @@
+unportable
+bindings
diff --git a/basis/core-foundation/bundles/bundles-docs.factor b/basis/core-foundation/bundles/bundles-docs.factor
new file mode 100644 (file)
index 0000000..baa1b4d
--- /dev/null
@@ -0,0 +1,11 @@
+USING: help.syntax help.markup ;
+IN: core-foundation.bundles
+
+HELP: <CFBundle>
+{ $values { "string" "a pathname string" } { "bundle" "a " { $snippet "CFBundle" } } }
+{ $description "Creates a new " { $snippet "CFBundle" } "." } ;
+
+HELP: load-framework
+{ $values { "name" "a pathname string" } }
+{ $description "Loads a Core Foundation framework." } ;
+
diff --git a/basis/core-foundation/bundles/bundles.factor b/basis/core-foundation/bundles/bundles.factor
new file mode 100644 (file)
index 0000000..790f176
--- /dev/null
@@ -0,0 +1,23 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: alien.syntax kernel sequences core-foundation
+core-foundation.urls ;
+IN: core-foundation.bundles
+
+TYPEDEF: void* CFBundleRef
+
+FUNCTION: CFBundleRef CFBundleCreate ( CFAllocatorRef allocator, CFURLRef bundleURL ) ;
+
+FUNCTION: Boolean CFBundleLoadExecutable ( CFBundleRef bundle ) ;
+
+: <CFBundle> ( string -- bundle )
+    t <CFFileSystemURL> [
+        f swap CFBundleCreate
+    ] keep CFRelease ;
+
+: load-framework ( name -- )
+    dup <CFBundle> [
+        CFBundleLoadExecutable drop
+    ] [
+        "Cannot load bundle named " prepend throw
+    ] ?if ;
diff --git a/basis/core-foundation/bundles/tags.txt b/basis/core-foundation/bundles/tags.txt
new file mode 100644 (file)
index 0000000..2320bdd
--- /dev/null
@@ -0,0 +1,2 @@
+unportable
+bindings
index d577c523cff2afc01cd139ae6fa7df9b15cecb67..c1783cb92bd0012976c3f790a34e5bc1eec0cb6c 100644 (file)
@@ -1,42 +1,6 @@
 USING: alien strings arrays help.markup help.syntax destructors ;
 IN: core-foundation
 
-HELP: CF>array
-{ $values { "alien" "a " { $snippet "CFArray" } } { "array" "an array of " { $link alien } " instances" } }
-{ $description "Creates a Factor array from a Core Foundation array." } ;
-
-HELP: <CFArray>
-{ $values { "seq" "a sequence of " { $link alien } " instances" } { "alien" "a " { $snippet "CFArray" } } }
-{ $description "Creates a Core Foundation array from a Factor array." } ;
-
-HELP: <CFString>
-{ $values { "string" string } { "alien" "a " { $snippet "CFString" } } }
-{ $description "Creates a Core Foundation string from a Factor string." } ;
-
-HELP: CF>string
-{ $values { "alien" "a " { $snippet "CFString" } } { "string" string } }
-{ $description "Creates a Factor string from a Core Foundation string." } ;
-
-HELP: CF>string-array
-{ $values { "alien" "a " { $snippet "CFArray" } " of " { $snippet "CFString" } " instances" } { "seq" string } }
-{ $description "Creates an array of Factor strings from a " { $snippet "CFArray" } " of " { $snippet "CFString" } "s." } ;
-
-HELP: <CFFileSystemURL>
-{ $values { "string" "a pathname string" } { "dir?" "a boolean indicating if the pathname is a directory" } { "url" "a " { $snippet "CFURL" } } }
-{ $description "Creates a new " { $snippet "CFURL" } " pointing to the given local pathname." } ;
-
-HELP: <CFURL>
-{ $values { "string" "a URL string" } { "url" "a " { $snippet "CFURL" } } }
-{ $description "Creates a new " { $snippet "CFURL" } "." } ;
-
-HELP: <CFBundle>
-{ $values { "string" "a pathname string" } { "bundle" "a " { $snippet "CFBundle" } } }
-{ $description "Creates a new " { $snippet "CFBundle" } "." } ;
-
-HELP: load-framework
-{ $values { "name" "a pathname string" } }
-{ $description "Loads a Core Foundation framework." } ;
-
 HELP: &CFRelease
 { $values { "alien" "Pointer to a Core Foundation object" } }
 { $description "Marks the given Core Foundation object for unconditional release via " { $link CFRelease } " at the end of the enclosing " { $link with-destructors } " scope." } ;
@@ -46,24 +10,3 @@ HELP: |CFRelease
 { $description "Marks the given Core Foundation object for release via " { $link CFRelease } " in the event of an error at the end of the enclosing " { $link with-destructors } " scope." } ;
 
 { CFRelease |CFRelease &CFRelease } related-words
-
-ARTICLE: "core-foundation" "Core foundation utilities"
-"The " { $vocab-link "core-foundation" } " vocabulary defines bindings for some frequently-used Core Foundation functions. It also provides some utility words."
-$nl
-"Strings:"
-{ $subsection <CFString> }
-{ $subsection CF>string }
-"Arrays:"
-{ $subsection <CFArray> }
-{ $subsection CF>array }
-{ $subsection CF>string-array }
-"URLs:"
-{ $subsection <CFFileSystemURL> }
-{ $subsection <CFURL> }
-"Frameworks:"
-{ $subsection load-framework }
-"Memory management:"
-{ $subsection &CFRelease }
-{ $subsection |CFRelease } ;
-
-ABOUT: "core-foundation"
diff --git a/basis/core-foundation/core-foundation-tests.factor b/basis/core-foundation/core-foundation-tests.factor
deleted file mode 100644 (file)
index c1d6788..0000000
+++ /dev/null
@@ -1,9 +0,0 @@
-! Copyright (C) 2008 Slava Pestov.
-! See http://factorcode.org/license.txt for BSD license.
-USING: core-foundation tools.test kernel ;
-IN: core-foundation
-
-[ ] [ "Hello" <CFString> CFRelease ] unit-test
-[ "Hello" ] [ "Hello" <CFString> [ CF>string ] [ CFRelease ] bi ] unit-test
-[ "Hello\u003456" ] [ "Hello\u003456" <CFString> [ CF>string ] [ CFRelease ] bi ] unit-test
-[ "Hello\u013456" ] [ "Hello\u013456" <CFString> [ CF>string ] [ CFRelease ] bi ] unit-test
index 48d7b7e4832b5243bdf580ce59965eff78bf6d21..51173aff211019b4c5009c3085930bf7b97f10c5 100644 (file)
@@ -1,23 +1,13 @@
 ! Copyright (C) 2006, 2008 Slava Pestov
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien alien.c-types alien.strings alien.syntax kernel
-math sequences io.encodings.utf8 destructors accessors
-combinators byte-arrays ;
+USING: alien.syntax destructors accessors kernel calendar ;
 IN: core-foundation
 
-TYPEDEF: void* CFAllocatorRef
-TYPEDEF: void* CFArrayRef
-TYPEDEF: void* CFDataRef
-TYPEDEF: void* CFDictionaryRef
-TYPEDEF: void* CFMutableDictionaryRef
-TYPEDEF: void* CFNumberRef
-TYPEDEF: void* CFBundleRef
-TYPEDEF: void* CFSetRef
-TYPEDEF: void* CFStringRef
-TYPEDEF: void* CFURLRef
-TYPEDEF: void* CFUUIDRef
 TYPEDEF: void* CFTypeRef
-TYPEDEF: void* CFFileDescriptorRef
+
+TYPEDEF: void* CFAllocatorRef
+: kCFAllocatorDefault f ; inline
+
 TYPEDEF: bool Boolean
 TYPEDEF: long CFIndex
 TYPEDEF: int SInt32
@@ -26,186 +16,10 @@ TYPEDEF: ulong CFTypeID
 TYPEDEF: UInt32 CFOptionFlags
 TYPEDEF: double CFTimeInterval
 TYPEDEF: double CFAbsoluteTime
-TYPEDEF: int CFFileDescriptorNativeDescriptor
-TYPEDEF: void* CFFileDescriptorCallBack
-
-TYPEDEF: int CFNumberType
-: kCFNumberSInt8Type 1 ; inline
-: kCFNumberSInt16Type 2 ; inline
-: kCFNumberSInt32Type 3 ; inline
-: kCFNumberSInt64Type 4 ; inline
-: kCFNumberFloat32Type 5 ; inline
-: kCFNumberFloat64Type 6 ; inline
-: kCFNumberCharType 7 ; inline
-: kCFNumberShortType 8 ; inline
-: kCFNumberIntType 9 ; inline
-: kCFNumberLongType 10 ; inline
-: kCFNumberLongLongType 11 ; inline
-: kCFNumberFloatType 12 ; inline
-: kCFNumberDoubleType 13 ; inline
-: kCFNumberCFIndexType 14 ; inline
-: kCFNumberNSIntegerType 15 ; inline
-: kCFNumberCGFloatType 16 ; inline
-: kCFNumberMaxType 16 ; inline
-
-TYPEDEF: int CFPropertyListMutabilityOptions
-: kCFPropertyListImmutable                  0 ; inline
-: kCFPropertyListMutableContainers          1 ; inline
-: kCFPropertyListMutableContainersAndLeaves 2 ; inline
-
-FUNCTION: CFArrayRef CFArrayCreateMutable ( CFAllocatorRef allocator, CFIndex capacity, void* callbacks ) ;
-
-FUNCTION: void* CFArrayGetValueAtIndex ( CFArrayRef array, CFIndex idx ) ;
-
-FUNCTION: void CFArraySetValueAtIndex ( CFArrayRef array, CFIndex index, void* value ) ;
-
-FUNCTION: CFIndex CFArrayGetCount ( CFArrayRef array ) ;
-
-: kCFURLPOSIXPathStyle 0 ; inline
-: kCFAllocatorDefault f ; inline
-
-FUNCTION: CFURLRef CFURLCreateWithFileSystemPath ( CFAllocatorRef allocator, CFStringRef filePath, int pathStyle, Boolean isDirectory ) ;
-
-FUNCTION: CFURLRef CFURLCreateWithString ( CFAllocatorRef allocator, CFStringRef string, CFURLRef base ) ;
-
-FUNCTION: CFURLRef CFURLCopyFileSystemPath ( CFURLRef url, int pathStyle ) ;
-
-TYPEDEF: int CFStringEncoding
-: kCFStringEncodingMacRoman HEX: 0 ;
-: kCFStringEncodingWindowsLatin1 HEX: 0500 ;
-: kCFStringEncodingISOLatin1 HEX: 0201 ;
-: kCFStringEncodingNextStepLatin HEX: 0B01 ;
-: kCFStringEncodingASCII HEX: 0600 ;
-: kCFStringEncodingUnicode HEX: 0100 ;
-: kCFStringEncodingUTF8 HEX: 08000100 ;
-: kCFStringEncodingNonLossyASCII HEX: 0BFF ;
-: kCFStringEncodingUTF16 HEX: 0100 ;
-: kCFStringEncodingUTF16BE HEX: 10000100 ;
-: kCFStringEncodingUTF16LE HEX: 14000100 ;
-: kCFStringEncodingUTF32 HEX: 0c000100 ;
-: kCFStringEncodingUTF32BE HEX: 18000100 ;
-: kCFStringEncodingUTF32LE HEX: 1c000100 ;
-
-FUNCTION: CFStringRef CFStringCreateFromExternalRepresentation (
-   CFAllocatorRef alloc,
-   CFDataRef data,
-   CFStringEncoding encoding
-) ;
-
-FUNCTION: CFStringRef CFStringCreateWithBytes (
-   CFAllocatorRef alloc,
-   UInt8* bytes,
-   CFIndex numBytes,
-   CFStringEncoding encoding,
-   Boolean isExternalRepresentation
-) ;
-
-FUNCTION: CFIndex CFStringGetLength ( CFStringRef theString ) ;
-
-FUNCTION: void CFStringGetCharacters ( void* theString, CFIndex start, CFIndex length, void* buffer ) ;
-
-FUNCTION: Boolean CFStringGetCString (
-   CFStringRef theString,
-   char* buffer,
-   CFIndex bufferSize,
-   CFStringEncoding encoding
-) ;
-
-FUNCTION: CFStringRef CFStringCreateWithCString (
-   CFAllocatorRef alloc,
-   char* cStr,
-   CFStringEncoding encoding
-) ;
-
-FUNCTION: CFNumberRef CFNumberCreate ( CFAllocatorRef allocator, CFNumberType theType, void* valuePtr ) ;
-
-FUNCTION: CFDataRef CFDataCreate ( CFAllocatorRef allocator, uchar* bytes, CFIndex length ) ;
-
-FUNCTION: CFBundleRef CFBundleCreate ( CFAllocatorRef allocator, CFURLRef bundleURL ) ;
-
-FUNCTION: Boolean CFBundleLoadExecutable ( CFBundleRef bundle ) ;
 
 FUNCTION: CFTypeRef CFRetain ( CFTypeRef cf ) ;
-FUNCTION: void CFRelease ( CFTypeRef cf ) ;
-
-FUNCTION: CFTypeID CFGetTypeID ( CFTypeRef cf ) ;
-
-: CF>array ( alien -- array )
-    dup CFArrayGetCount [ CFArrayGetValueAtIndex ] with map ;
-
-: <CFArray> ( seq -- alien )
-    [ f swap length f CFArrayCreateMutable ] keep
-    [ length ] keep
-    [ [ dupd ] dip CFArraySetValueAtIndex ] 2each ;
-
-: <CFString> ( string -- alien )
-    f swap utf8 string>alien kCFStringEncodingUTF8 CFStringCreateWithCString
-    [ "CFStringCreateWithCString failed" throw ] unless* ;
-
-: CF>string ( alien -- string )
-    dup CFStringGetLength 4 * 1 + <byte-array> [
-        dup length
-        kCFStringEncodingUTF8
-        CFStringGetCString
-        [ "CFStringGetCString failed" throw ] unless
-    ] keep utf8 alien>string ;
-
-: CF>string-array ( alien -- seq )
-    CF>array [ CF>string ] map ;
-
-: <CFStringArray> ( seq -- alien )
-    [ <CFString> ] map [ <CFArray> ] [ [ CFRelease ] each ] bi ;
-
-: <CFFileSystemURL> ( string dir? -- url )
-    [ <CFString> f over kCFURLPOSIXPathStyle ] dip
-    CFURLCreateWithFileSystemPath swap CFRelease ;
-
-: <CFURL> ( string -- url )
-    <CFString>
-    [ f swap f CFURLCreateWithString ] keep
-    CFRelease ;
 
-: <CFBundle> ( string -- bundle )
-    t <CFFileSystemURL> [
-        f swap CFBundleCreate
-    ] keep CFRelease ;
-
-GENERIC: <CFNumber> ( number -- alien )
-
-M: integer <CFNumber>
-    [ f kCFNumberLongLongType ] dip <longlong> CFNumberCreate ;
-
-M: float <CFNumber>
-    [ f kCFNumberDoubleType ] dip <double> CFNumberCreate ;
-
-M: t <CFNumber>
-    drop f kCFNumberIntType 1 <int> CFNumberCreate ;
-
-M: f <CFNumber>
-    drop f kCFNumberIntType 0 <int> CFNumberCreate ;
-
-: <CFData> ( byte-array -- alien )
-    [ f ] dip dup length CFDataCreate ;
-
-FUNCTION: CFFileDescriptorRef CFFileDescriptorCreate (
-    CFAllocatorRef allocator,
-    CFFileDescriptorNativeDescriptor fd,
-    Boolean closeOnInvalidate,
-    CFFileDescriptorCallBack callout, 
-    CFFileDescriptorContext* context
-) ;
-
-FUNCTION: void CFFileDescriptorEnableCallBacks (
-    CFFileDescriptorRef f,
-    CFOptionFlags callBackTypes
-) ;
-
-: load-framework ( name -- )
-    dup <CFBundle> [
-        CFBundleLoadExecutable drop
-    ] [
-        "Cannot load bundle named " prepend throw
-    ] ?if ;
+FUNCTION: void CFRelease ( CFTypeRef cf ) ;
 
 TUPLE: CFRelease-destructor alien disposed ;
 
@@ -216,3 +30,10 @@ M: CFRelease-destructor dispose* alien>> CFRelease ;
 
 : |CFRelease ( alien -- alien )
     dup f CFRelease-destructor boa |dispose drop ; inline
+
+: >CFTimeInterval ( duration -- interval )
+    duration>seconds ; inline
+
+: >CFAbsoluteTime ( timestamp -- time )
+    T{ timestamp { year 2001 } { month 1 } { day 1 } } time-
+    duration>seconds ; inline
diff --git a/basis/core-foundation/data/data.factor b/basis/core-foundation/data/data.factor
new file mode 100644 (file)
index 0000000..043fb90
--- /dev/null
@@ -0,0 +1,58 @@
+! Copyright (C) 2008 Joe Groff.
+! See http://factorcode.org/license.txt for BSD license.
+USING: alien.syntax alien.c-types sequences kernel math ;
+IN: core-foundation.data
+
+TYPEDEF: void* CFDataRef
+TYPEDEF: void* CFDictionaryRef
+TYPEDEF: void* CFMutableDictionaryRef
+TYPEDEF: void* CFNumberRef
+TYPEDEF: void* CFSetRef
+TYPEDEF: void* CFUUIDRef
+
+TYPEDEF: int CFNumberType
+: kCFNumberSInt8Type 1 ; inline
+: kCFNumberSInt16Type 2 ; inline
+: kCFNumberSInt32Type 3 ; inline
+: kCFNumberSInt64Type 4 ; inline
+: kCFNumberFloat32Type 5 ; inline
+: kCFNumberFloat64Type 6 ; inline
+: kCFNumberCharType 7 ; inline
+: kCFNumberShortType 8 ; inline
+: kCFNumberIntType 9 ; inline
+: kCFNumberLongType 10 ; inline
+: kCFNumberLongLongType 11 ; inline
+: kCFNumberFloatType 12 ; inline
+: kCFNumberDoubleType 13 ; inline
+: kCFNumberCFIndexType 14 ; inline
+: kCFNumberNSIntegerType 15 ; inline
+: kCFNumberCGFloatType 16 ; inline
+: kCFNumberMaxType 16 ; inline
+
+TYPEDEF: int CFPropertyListMutabilityOptions
+: kCFPropertyListImmutable                  0 ; inline
+: kCFPropertyListMutableContainers          1 ; inline
+: kCFPropertyListMutableContainersAndLeaves 2 ; inline
+
+FUNCTION: CFNumberRef CFNumberCreate ( CFAllocatorRef allocator, CFNumberType theType, void* valuePtr ) ;
+
+FUNCTION: CFDataRef CFDataCreate ( CFAllocatorRef allocator, uchar* bytes, CFIndex length ) ;
+
+FUNCTION: CFTypeID CFGetTypeID ( CFTypeRef cf ) ;
+
+GENERIC: <CFNumber> ( number -- alien )
+
+M: integer <CFNumber>
+    [ f kCFNumberLongLongType ] dip <longlong> CFNumberCreate ;
+
+M: float <CFNumber>
+    [ f kCFNumberDoubleType ] dip <double> CFNumberCreate ;
+
+M: t <CFNumber>
+    drop f kCFNumberIntType 1 <int> CFNumberCreate ;
+
+M: f <CFNumber>
+    drop f kCFNumberIntType 0 <int> CFNumberCreate ;
+
+: <CFData> ( byte-array -- alien )
+    [ f ] dip dup length CFDataCreate ;
diff --git a/basis/core-foundation/data/tags.txt b/basis/core-foundation/data/tags.txt
new file mode 100644 (file)
index 0000000..2320bdd
--- /dev/null
@@ -0,0 +1,2 @@
+unportable
+bindings
diff --git a/basis/core-foundation/file-descriptors/file-descriptors.factor b/basis/core-foundation/file-descriptors/file-descriptors.factor
new file mode 100644 (file)
index 0000000..29c4219
--- /dev/null
@@ -0,0 +1,32 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: alien.syntax kernel math.bitwise core-foundation ;
+IN: core-foundation.file-descriptors
+
+TYPEDEF: void* CFFileDescriptorRef
+TYPEDEF: int CFFileDescriptorNativeDescriptor
+TYPEDEF: void* CFFileDescriptorCallBack
+
+FUNCTION: CFFileDescriptorRef CFFileDescriptorCreate (
+    CFAllocatorRef allocator,
+    CFFileDescriptorNativeDescriptor fd,
+    Boolean closeOnInvalidate,
+    CFFileDescriptorCallBack callout, 
+    CFFileDescriptorContext* context
+) ;
+
+: kCFFileDescriptorReadCallBack 1 ; inline
+: kCFFileDescriptorWriteCallBack 2 ; inline
+   
+FUNCTION: void CFFileDescriptorEnableCallBacks (
+    CFFileDescriptorRef f,
+    CFOptionFlags callBackTypes
+) ;
+
+: enable-all-callbacks ( fd -- )
+    { kCFFileDescriptorReadCallBack kCFFileDescriptorWriteCallBack } flags
+    CFFileDescriptorEnableCallBacks ;
+
+: <CFFileDescriptor> ( fd callback -- handle )
+    [ f swap ] [ t swap ] bi* f CFFileDescriptorCreate
+    [ "CFFileDescriptorCreate failed" throw ] unless* ;
diff --git a/basis/core-foundation/file-descriptors/tags.txt b/basis/core-foundation/file-descriptors/tags.txt
new file mode 100644 (file)
index 0000000..2320bdd
--- /dev/null
@@ -0,0 +1,2 @@
+unportable
+bindings
index d4d5e88512e25c72c0e2c4d464a80c2b342d358f..7ed040b45538c05e7aee75270ce6db51b7439019 100644 (file)
@@ -2,11 +2,10 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien alien.c-types alien.strings alien.syntax kernel
 math sequences namespaces make assocs init accessors
-continuations combinators core-foundation
-core-foundation.run-loop core-foundation.run-loop.thread
-io.encodings.utf8 destructors locals arrays
-specialized-arrays.direct.alien specialized-arrays.direct.int
-specialized-arrays.direct.longlong ;
+continuations combinators io.encodings.utf8 destructors locals
+arrays specialized-arrays.direct.alien
+specialized-arrays.direct.int specialized-arrays.direct.longlong
+core-foundation core-foundation.run-loop core-foundation.strings ;
 IN: core-foundation.fsevents
 
 : kFSEventStreamCreateFlagUseCFTypes 2 ; inline
@@ -118,7 +117,7 @@ FUNCTION: CFStringRef FSEventStreamCopyDescription ( FSEventStreamRef streamRef
     FSEventStreamCreate ;
 
 : kCFRunLoopCommonModes ( -- string )
-    "kCFRunLoopCommonModes" f dlsym *void* ;
+    &: kCFRunLoopCommonModes *void* ;
 
 : schedule-event-stream ( event-stream -- )
     CFRunLoopGetMain
index 39f4101301352e85226bfe93037672459bf6ebf4..5f2ff7bd53261cc703faee350195799bba92bcfe 100644 (file)
@@ -1,6 +1,9 @@
 ! Copyright (C) 2008 Slava Pestov
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien alien.syntax core-foundation kernel namespaces ;
+USING: accessors alien alien.syntax kernel math namespaces
+sequences destructors combinators threads heaps deques calendar
+core-foundation core-foundation.strings
+core-foundation.file-descriptors core-foundation.timers ;
 IN: core-foundation.run-loop
 
 : kCFRunLoopRunFinished 1 ; inline
@@ -32,6 +35,24 @@ FUNCTION: void CFRunLoopAddSource (
    CFStringRef mode
 ) ;
 
+FUNCTION: void CFRunLoopRemoveSource (
+   CFRunLoopRef rl,
+   CFRunLoopSourceRef source,
+   CFStringRef mode
+) ;
+
+FUNCTION: void CFRunLoopAddTimer (
+   CFRunLoopRef rl,
+   CFRunLoopTimerRef timer,
+   CFStringRef mode
+) ;
+
+FUNCTION: void CFRunLoopRemoveTimer (
+   CFRunLoopRef rl,
+   CFRunLoopTimerRef timer,
+   CFStringRef mode
+) ;
+
 : CFRunLoopDefaultMode ( -- alien )
     #! Ugly, but we don't have static NSStrings
     \ CFRunLoopDefaultMode get-global dup expired? [
@@ -39,3 +60,80 @@ FUNCTION: void CFRunLoopAddSource (
         "kCFRunLoopDefaultMode" <CFString>
         dup \ CFRunLoopDefaultMode set-global
     ] when ;
+
+TUPLE: run-loop fds sources timers ;
+
+: <run-loop> ( -- run-loop )
+    V{ } clone V{ } clone V{ } clone \ run-loop boa ;
+
+SYMBOL: expiry-check
+
+: run-loop ( -- run-loop )
+    \ run-loop get-global not expiry-check get expired? or
+    [
+        31337 <alien> expiry-check set-global
+        <run-loop> dup \ run-loop set-global
+    ] [ \ run-loop get-global ] if ;
+
+: add-source-to-run-loop ( source -- )
+    [ run-loop sources>> push ]
+    [
+        CFRunLoopGetMain
+        swap CFRunLoopDefaultMode
+        CFRunLoopAddSource
+    ] bi ;
+
+: create-fd-source ( CFFileDescriptor -- source )
+    f swap 0 CFFileDescriptorCreateRunLoopSource ;
+
+: add-fd-to-run-loop ( fd callback -- )
+    [
+        <CFFileDescriptor> |CFRelease
+        [ run-loop fds>> push ]
+        [ create-fd-source |CFRelease add-source-to-run-loop ]
+        bi
+    ] with-destructors ;
+
+: add-timer-to-run-loop ( timer -- )
+    [ run-loop timers>> push ]
+    [
+        CFRunLoopGetMain
+        swap CFRunLoopDefaultMode
+        CFRunLoopAddTimer
+    ] bi ;
+
+<PRIVATE
+
+: ((reset-timer)) ( timer counter timestamp -- )
+    nip >CFAbsoluteTime CFRunLoopTimerSetNextFireDate ;
+
+: (reset-timer) ( timer counter -- )
+    yield {
+        { [ dup 0 = ] [ now ((reset-timer)) ] }
+        { [ run-queue deque-empty? not ] [ 1- (reset-timer) ] }
+        { [ sleep-queue heap-empty? ] [ 5 minutes hence ((reset-timer)) ] }
+        [ sleep-queue heap-peek nip micros>timestamp ((reset-timer)) ]
+    } cond ;
+
+: reset-timer ( timer -- )
+    10 (reset-timer) ;
+
+PRIVATE>
+
+: reset-run-loop ( -- )
+    run-loop
+    [ timers>> [ reset-timer ] each ]
+    [ fds>> [ enable-all-callbacks ] each ] bi ;
+
+: timer-callback ( -- callback )
+    "void" { "CFRunLoopTimerRef" "void*" } "cdecl"
+    [ 2drop reset-run-loop yield ] alien-callback ;
+
+: init-thread-timer ( -- )
+    timer-callback <CFTimer> add-timer-to-run-loop ;
+
+: run-one-iteration ( us -- handled? )
+    reset-run-loop
+    CFRunLoopDefaultMode
+    swap [ microseconds ] [ 5 minutes ] if* >CFTimeInterval
+    t CFRunLoopRunInMode kCFRunLoopRunHandledSource = ;
diff --git a/basis/core-foundation/run-loop/thread/authors.txt b/basis/core-foundation/run-loop/thread/authors.txt
deleted file mode 100644 (file)
index 1901f27..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Slava Pestov
diff --git a/basis/core-foundation/run-loop/thread/summary.txt b/basis/core-foundation/run-loop/thread/summary.txt
deleted file mode 100644 (file)
index e5818b3..0000000
+++ /dev/null
@@ -1 +0,0 @@
-Vocabulary with init hook for running CoreFoundation event loop
diff --git a/basis/core-foundation/run-loop/thread/tags.txt b/basis/core-foundation/run-loop/thread/tags.txt
deleted file mode 100644 (file)
index 6bf6830..0000000
+++ /dev/null
@@ -1 +0,0 @@
-unportable
diff --git a/basis/core-foundation/run-loop/thread/thread.factor b/basis/core-foundation/run-loop/thread/thread.factor
deleted file mode 100644 (file)
index aeeff31..0000000
+++ /dev/null
@@ -1,16 +0,0 @@
-! Copyright (C) 2008 Slava Pestov
-! See http://factorcode.org/license.txt for BSD license.
-USING: calendar core-foundation.run-loop init kernel threads ;
-IN: core-foundation.run-loop.thread
-
-! Load this vocabulary if you need a run loop running.
-
-: run-loop-thread ( -- )
-    CFRunLoopDefaultMode 0 f CFRunLoopRunInMode
-    kCFRunLoopRunHandledSource = [ 1 seconds sleep ] unless
-    run-loop-thread ;
-
-: start-run-loop-thread ( -- )
-    [ run-loop-thread t ] "CFRunLoop dispatcher" spawn-server drop ;
-
-[ start-run-loop-thread ] "core-foundation.run-loop.thread" add-init-hook
diff --git a/basis/core-foundation/strings/strings-docs.factor b/basis/core-foundation/strings/strings-docs.factor
new file mode 100644 (file)
index 0000000..4c12fb5
--- /dev/null
@@ -0,0 +1,14 @@
+USING: help.syntax help.markup strings ;
+IN: core-foundation.strings
+
+HELP: <CFString>
+{ $values { "string" string } { "alien" "a " { $snippet "CFString" } } }
+{ $description "Creates a Core Foundation string from a Factor string." } ;
+
+HELP: CF>string
+{ $values { "alien" "a " { $snippet "CFString" } } { "string" string } }
+{ $description "Creates a Factor string from a Core Foundation string." } ;
+
+HELP: CF>string-array
+{ $values { "alien" "a " { $snippet "CFArray" } " of " { $snippet "CFString" } " instances" } { "seq" string } }
+{ $description "Creates an array of Factor strings from a " { $snippet "CFArray" } " of " { $snippet "CFString" } "s." } ;
diff --git a/basis/core-foundation/strings/strings-tests.factor b/basis/core-foundation/strings/strings-tests.factor
new file mode 100644 (file)
index 0000000..39d5ee6
--- /dev/null
@@ -0,0 +1,9 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: core-foundation.strings core-foundation tools.test kernel ;
+IN: core-foundation
+
+[ ] [ "Hello" <CFString> CFRelease ] unit-test
+[ "Hello" ] [ "Hello" <CFString> [ CF>string ] [ CFRelease ] bi ] unit-test
+[ "Hello\u003456" ] [ "Hello\u003456" <CFString> [ CF>string ] [ CFRelease ] bi ] unit-test
+[ "Hello\u013456" ] [ "Hello\u013456" <CFString> [ CF>string ] [ CFRelease ] bi ] unit-test
diff --git a/basis/core-foundation/strings/strings.factor b/basis/core-foundation/strings/strings.factor
new file mode 100644 (file)
index 0000000..2e6180c
--- /dev/null
@@ -0,0 +1,66 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: alien.syntax alien.strings kernel sequences byte-arrays
+io.encodings.utf8 math core-foundation core-foundation.arrays ;
+IN: core-foundation.strings
+
+TYPEDEF: void* CFStringRef
+
+TYPEDEF: int CFStringEncoding
+: kCFStringEncodingMacRoman HEX: 0 ;
+: kCFStringEncodingWindowsLatin1 HEX: 0500 ;
+: kCFStringEncodingISOLatin1 HEX: 0201 ;
+: kCFStringEncodingNextStepLatin HEX: 0B01 ;
+: kCFStringEncodingASCII HEX: 0600 ;
+: kCFStringEncodingUnicode HEX: 0100 ;
+: kCFStringEncodingUTF8 HEX: 08000100 ;
+: kCFStringEncodingNonLossyASCII HEX: 0BFF ;
+: kCFStringEncodingUTF16 HEX: 0100 ;
+: kCFStringEncodingUTF16BE HEX: 10000100 ;
+: kCFStringEncodingUTF16LE HEX: 14000100 ;
+: kCFStringEncodingUTF32 HEX: 0c000100 ;
+: kCFStringEncodingUTF32BE HEX: 18000100 ;
+: kCFStringEncodingUTF32LE HEX: 1c000100 ;
+
+FUNCTION: CFStringRef CFStringCreateWithBytes (
+   CFAllocatorRef alloc,
+   UInt8* bytes,
+   CFIndex numBytes,
+   CFStringEncoding encoding,
+   Boolean isExternalRepresentation
+) ;
+
+FUNCTION: CFIndex CFStringGetLength ( CFStringRef theString ) ;
+
+FUNCTION: void CFStringGetCharacters ( void* theString, CFIndex start, CFIndex length, void* buffer ) ;
+
+FUNCTION: Boolean CFStringGetCString (
+   CFStringRef theString,
+   char* buffer,
+   CFIndex bufferSize,
+   CFStringEncoding encoding
+) ;
+
+FUNCTION: CFStringRef CFStringCreateWithCString (
+   CFAllocatorRef alloc,
+   char* cStr,
+   CFStringEncoding encoding
+) ;
+
+: <CFString> ( string -- alien )
+    f swap utf8 string>alien kCFStringEncodingUTF8 CFStringCreateWithCString
+    [ "CFStringCreateWithCString failed" throw ] unless* ;
+
+: CF>string ( alien -- string )
+    dup CFStringGetLength 4 * 1 + <byte-array> [
+        dup length
+        kCFStringEncodingUTF8
+        CFStringGetCString
+        [ "CFStringGetCString failed" throw ] unless
+    ] keep utf8 alien>string ;
+
+: CF>string-array ( alien -- seq )
+    CF>array [ CF>string ] map ;
+
+: <CFStringArray> ( seq -- alien )
+    [ <CFString> ] map [ <CFArray> ] [ [ CFRelease ] each ] bi ;
diff --git a/basis/core-foundation/strings/tags.txt b/basis/core-foundation/strings/tags.txt
new file mode 100644 (file)
index 0000000..2320bdd
--- /dev/null
@@ -0,0 +1,2 @@
+unportable
+bindings
diff --git a/basis/core-foundation/timers/tags.txt b/basis/core-foundation/timers/tags.txt
new file mode 100644 (file)
index 0000000..2320bdd
--- /dev/null
@@ -0,0 +1,2 @@
+unportable
+bindings
diff --git a/basis/core-foundation/timers/timers.factor b/basis/core-foundation/timers/timers.factor
new file mode 100644 (file)
index 0000000..0acd92c
--- /dev/null
@@ -0,0 +1,34 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: alien.syntax system math kernel core-foundation calendar ;
+IN: core-foundation.timers
+
+TYPEDEF: void* CFRunLoopTimerRef
+TYPEDEF: void* CFRunLoopTimerCallBack
+TYPEDEF: void* CFRunLoopTimerContext
+
+FUNCTION: CFRunLoopTimerRef CFRunLoopTimerCreate (
+   CFAllocatorRef allocator,
+   CFAbsoluteTime fireDate,
+   CFTimeInterval interval,
+   CFOptionFlags flags,
+   CFIndex order,
+   CFRunLoopTimerCallBack callout,
+   CFRunLoopTimerContext* context
+) ;
+
+: <CFTimer> ( callback -- timer )
+    [ f now >CFAbsoluteTime 60 0 0 ] dip f CFRunLoopTimerCreate ;
+
+FUNCTION: void CFRunLoopTimerInvalidate (
+   CFRunLoopTimerRef timer
+) ;
+
+FUNCTION: Boolean CFRunLoopTimerIsValid (
+   CFRunLoopTimerRef timer
+) ;
+
+FUNCTION: void CFRunLoopTimerSetNextFireDate (
+   CFRunLoopTimerRef timer,
+   CFAbsoluteTime fireDate
+) ;
diff --git a/basis/core-foundation/urls/tags.txt b/basis/core-foundation/urls/tags.txt
new file mode 100644 (file)
index 0000000..2320bdd
--- /dev/null
@@ -0,0 +1,2 @@
+unportable
+bindings
diff --git a/basis/core-foundation/urls/urls-docs.factor b/basis/core-foundation/urls/urls-docs.factor
new file mode 100644 (file)
index 0000000..d017e70
--- /dev/null
@@ -0,0 +1,10 @@
+USING: help.syntax help.markup ;
+IN: core-foundation.urls
+
+HELP: <CFFileSystemURL>
+{ $values { "string" "a pathname string" } { "dir?" "a boolean indicating if the pathname is a directory" } { "url" "a " { $snippet "CFURL" } } }
+{ $description "Creates a new " { $snippet "CFURL" } " pointing to the given local pathname." } ;
+
+HELP: <CFURL>
+{ $values { "string" "a URL string" } { "url" "a " { $snippet "CFURL" } } }
+{ $description "Creates a new " { $snippet "CFURL" } "." } ;
diff --git a/basis/core-foundation/urls/urls.factor b/basis/core-foundation/urls/urls.factor
new file mode 100644 (file)
index 0000000..9f9d3a6
--- /dev/null
@@ -0,0 +1,24 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: alien.syntax kernel core-foundation.strings
+core-foundation ;
+IN: core-foundation.urls
+
+: kCFURLPOSIXPathStyle 0 ; inline
+
+TYPEDEF: void* CFURLRef
+
+FUNCTION: CFURLRef CFURLCreateWithFileSystemPath ( CFAllocatorRef allocator, CFStringRef filePath, int pathStyle, Boolean isDirectory ) ;
+
+FUNCTION: CFURLRef CFURLCreateWithString ( CFAllocatorRef allocator, CFStringRef string, CFURLRef base ) ;
+
+FUNCTION: CFURLRef CFURLCopyFileSystemPath ( CFURLRef url, int pathStyle ) ;
+
+: <CFFileSystemURL> ( string dir? -- url )
+    [ <CFString> f over kCFURLPOSIXPathStyle ] dip
+    CFURLCreateWithFileSystemPath swap CFRelease ;
+
+: <CFURL> ( string -- url )
+    <CFString>
+    [ f swap f CFURLCreateWithString ] keep
+    CFRelease ;
index 698c3a17668f0e815555593530e6790cbb0fc2a1..f29dec128ca8e82463dbfe2d04d5fbf0a68a47b3 100644 (file)
@@ -10,6 +10,7 @@ IN: bootstrap.x86
 : shift-arg ( -- reg ) ECX ;
 : div-arg ( -- reg ) EAX ;
 : mod-arg ( -- reg ) EDX ;
+: arg ( -- reg ) EAX ;
 : temp0 ( -- reg ) EAX ;
 : temp1 ( -- reg ) EDX ;
 : temp2 ( -- reg ) ECX ;
index a21c4534d25e153ee03382a784ac824f5b3d7fb3..20a953b6d509969fd0cf424fc3dc1832d501aac7 100644 (file)
@@ -5,6 +5,7 @@ cpu.x86.assembler layouts vocabs parser ;
 IN: bootstrap.x86
 
 : stack-frame-size ( -- n ) 4 bootstrap-cells ;
+: arg ( -- reg ) RDI ;
 
 << "resource:basis/cpu/x86/64/bootstrap.factor" parse-file parsed >>
 call
index 709f138463c6bbb1aa5cf008853520171e78ba00..3accca400f84f97108e5648be2ea30d6b41fa8f2 100644 (file)
@@ -5,6 +5,7 @@ cpu.x86.assembler layouts vocabs parser ;
 IN: bootstrap.x86
 
 : stack-frame-size ( -- n ) 8 bootstrap-cells ;
+: arg ( -- reg ) RCX ;
 
 << "resource:basis/cpu/x86/64/bootstrap.factor" parse-file parsed >>
 call
index 3451da78e1dda774e1f52ad894382d17d4396158..42fcfaa6a2421f0d851c884a701ea24485059b80 100644 (file)
@@ -162,11 +162,11 @@ big-endian off
 ! Quotations and words
 [
     ! load from stack
-    temp0 ds-reg [] MOV
+    arg ds-reg [] MOV
     ! pop stack
     ds-reg bootstrap-cell SUB
     ! call quotation
-    temp0 quot-xt-offset [+] JMP
+    arg quot-xt-offset [+] JMP
 ] f f f \ (call) define-sub-primitive
 
 [
index c2dddc25ab8cea4444c18293680c85bd964aa232..7da19ee47b5f4b954ca1097d48df41539c0b6aee 100644 (file)
@@ -2,12 +2,13 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien alien.c-types alien.strings alien.syntax kernel
 layouts sequences system unix environment io.encodings.utf8
-unix.utilities vocabs.loader combinators alien.accessors ;
+unix.utilities vocabs.loader combinators alien.accessors
+alien.syntax ;
 IN: environment.unix
 
 HOOK: environ os ( -- void* )
 
-M: unix environ ( -- void* ) "environ" f dlsym ;
+M: unix environ ( -- void* ) &: environ ;
 
 M: unix os-env ( key -- value ) getenv ;
 
index 119fa23567ce0b1e590d6bb62819b953d6c54d51..108ae5ecc4c28bbbea3f2441288f8ff48fc09088 100644 (file)
@@ -7,6 +7,7 @@ math.order hashtables byte-arrays destructors
 io.encodings
 io.encodings.string
 io.encodings.ascii
+io.encodings.utf8
 io.encodings.8-bit
 io.encodings.binary
 io.streams.duplex
@@ -40,11 +41,11 @@ GENERIC: >post-data ( object -- post-data )
 
 M: post-data >post-data ;
 
-M: string >post-data "application/octet-stream" <post-data> ;
+M: string >post-data utf8 encode "application/octet-stream" <post-data> ;
 
 M: byte-array >post-data "application/octet-stream" <post-data> ;
 
-M: assoc >post-data assoc>query "application/x-www-form-urlencoded" <post-data> ;
+M: assoc >post-data assoc>query ascii encode "application/x-www-form-urlencoded" <post-data> ;
 
 M: f >post-data ;
 
@@ -52,12 +53,13 @@ M: f >post-data ;
     [ >post-data ] change-post-data ;
 
 : write-post-data ( request -- request )
-    dup method>> "POST" = [ dup post-data>> raw>> write ] when ; 
+    dup method>> [ "POST" = ] [ "PUT" = ] bi or [ dup post-data>> raw>> write ] when ; 
 
 : write-request ( request -- )
     unparse-post-data
     write-request-line
     write-request-header
+    binary encode-output
     write-post-data
     flush
     drop ;
@@ -153,7 +155,7 @@ SYMBOL: redirects
 
 PRIVATE>
 
-: success? ( code -- ? ) 200 = ;
+: success? ( code -- ? ) 200 299 between? ;
 
 ERROR: download-failed response ;
 
index 45bbec20e345cd0cd9d70a4da7c26edfd56e1752..358521473540ce253234015f96c15a63ed1f62a9 100644 (file)
@@ -143,8 +143,9 @@ HELP: <process-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." } ;
 
 HELP: wait-for-process
-{ $values { "process" process } { "status" integer } }
-{ $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." } ;
+{ $values { "process" process } { "status" object } }
+{ $description "If the process is still running, waits for it to exit, otherwise outputs the status code immediately. Can be called multiple times on the same process." }
+{ $notes "The status code is operating system specific; it may be an integer, or another object (the latter is the case on Unix if the process was killed by a signal). However, one cross-platform behavior code can rely on is that a status code of 0 indicates success." } ;
 
 ARTICLE: "io.launcher.descriptors" "Launch descriptors"
 "Words which launch processes can take either a command line string, a sequence of command line arguments, or a " { $link process } "."
index 0ed10e63c3418330775c111090bcddce7293c596..7bafb95376876e7ef6987b6ca7a4ce95af40e21b 100644 (file)
@@ -157,7 +157,7 @@ M: process-failed error.
     process>> . ;
 
 : wait-for-success ( process -- )
-    dup wait-for-process dup zero?
+    dup wait-for-process dup 0 =
     [ 2drop ] [ process-failed ] if ;
 
 : try-process ( desc -- )
index fe86ba9e3dbe996a0c065c3cbc7f5c3d39283c36..7589d4918ec29fff8fe0231269b201b9d8a48713 100644 (file)
@@ -1,14 +1,20 @@
 ! Copyright (C) 2008 Slava Pestov.\r
 ! See http://factorcode.org/license.txt for BSD license.\r
+USING: threads io.backend namespaces init math kernel ;\r
 IN: io.thread\r
-USING: threads io.backend namespaces init math ;\r
+\r
+! The Cocoa UI backend stops the I/O thread and takes over\r
+! completely.\r
+SYMBOL: io-thread-running?\r
 \r
 : io-thread ( -- )\r
     sleep-time io-multiplex yield ;\r
 \r
 : start-io-thread ( -- )\r
-    [ io-thread t ]\r
-    "I/O wait" spawn-server\r
-    \ io-thread set-global ;\r
+    [ [ io-thread-running? get-global ] [ io-thread ] [ ] while ]\r
+    "I/O wait" spawn drop ;\r
 \r
-[ start-io-thread ] "io.thread" add-init-hook\r
+[\r
+    t io-thread-running? set-global\r
+    start-io-thread\r
+] "io.thread" add-init-hook\r
index 1666d60c83fee70f2678fc02e37efe6f9b0d7e60..41bd03a58bb34b57a031b7f72f3fa91560483252 100644 (file)
@@ -1,11 +1,11 @@
 ! Copyright (C) 2004, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: alien alien.c-types generic assocs kernel kernel.private
-math io.ports sequences strings sbufs threads unix
-vectors io.buffers io.backend io.encodings math.parser
+USING: alien alien.c-types alien.syntax generic assocs kernel
+kernel.private math io.ports sequences strings sbufs threads
+unix vectors io.buffers io.backend io.encodings math.parser
 continuations system libc qualified namespaces make io.timeouts
 io.encodings.utf8 destructors accessors summary combinators
-locals unix.time fry ;
+locals unix.time fry io.unix.multiplexers ;
 QUALIFIED: io
 IN: io.unix.backend
 
@@ -37,38 +37,6 @@ M: fd dispose
 
 M: fd handle-fd dup check-disposed fd>> ;
 
-! I/O multiplexers
-TUPLE: mx fd reads writes ;
-
-: new-mx ( class -- obj )
-    new
-        H{ } clone >>reads
-        H{ } clone >>writes ; inline
-
-GENERIC: add-input-callback ( thread fd mx -- )
-
-M: mx add-input-callback reads>> push-at ;
-
-GENERIC: add-output-callback ( thread fd mx -- )
-
-M: mx add-output-callback writes>> push-at ;
-
-GENERIC: remove-input-callbacks ( fd mx -- callbacks )
-
-M: mx remove-input-callbacks reads>> delete-at* drop ;
-
-GENERIC: remove-output-callbacks ( fd mx -- callbacks )
-
-M: mx remove-output-callbacks writes>> delete-at* drop ;
-
-GENERIC: wait-for-events ( ms mx -- )
-
-: input-available ( fd mx -- )
-    reads>> delete-at* drop [ resume ] each ;
-
-: output-available ( fd mx -- )
-    writes>> delete-at* drop [ resume ] each ;
-
 M: fd cancel-operation ( fd -- )
     dup disposed>> [ drop ] [
         fd>>
@@ -184,11 +152,11 @@ M: stdin dispose*
 M: stdin refill
     [ buffer>> ] [ dup wait-for-stdin ] bi* refill-stdin f ;
 
-: control-write-fd ( -- fd ) "control_write" f dlsym *uint ;
+: control-write-fd ( -- fd ) &: control_write *uint ;
 
-: size-read-fd ( -- fd ) "size_read" f dlsym *uint ;
+: size-read-fd ( -- fd ) &: size_read *uint ;
 
-: data-read-fd ( -- fd ) "stdin_read" f dlsym *uint ;
+: data-read-fd ( -- fd ) &: stdin_read *uint ;
 
 : <stdin> ( -- stdin )
     stdin new
@@ -207,10 +175,10 @@ TUPLE: mx-port < port mx ;
 : <mx-port> ( mx -- port )
     dup fd>> mx-port <port> swap >>mx ;
 
-: multiplexer-error ( n -- )
-    0 < [
+: multiplexer-error ( n -- )
+    dup 0 < [
         err_no [ EAGAIN = ] [ EINTR = ] bi or
-        [ (io-error) ] unless
+        [ drop 0 ] [ (io-error) ] if
     ] when ;
 
 : ?flag ( n mask symbol -- n )
index 50b4b610da1fc0177edd5f1c0986693c9fe34306..83f063d713d0e9e9dd5cc2ca536540b30c0c23fa 100644 (file)
@@ -1,16 +1,12 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-IN: io.unix.bsd
 USING: namespaces system kernel accessors assocs continuations
-unix io.backend io.unix.backend io.unix.select ;
+unix io.backend io.unix.backend io.unix.multiplexers
+io.unix.multiplexers.kqueue ;
+IN: io.unix.bsd
 
 M: bsd init-io ( -- )
-    <select-mx> mx set-global ;
-!     <kqueue-mx> kqueue-mx set-global
-!     kqueue-mx get-global <mx-port> <mx-task>
-!     dup io-task-fd
-!     [ mx get-global reads>> set-at ]
-!     [ mx get-global writes>> set-at ] 2bi ;
+    <kqueue-mx> mx set-global ;
 
 ! M: bsd (monitor) ( path recursive? mailbox -- )
 !     swap [ "Recursive kqueue monitors not supported" throw ] when
index e8d33787f38b295f27d5fe90f6ff5550c7ac89a8..93d0b4aa99235d4b3f219828f036c9b978b0152d 100644 (file)
@@ -49,7 +49,7 @@ M: epoll-mx remove-output-callbacks ( fd mx -- seq )
 
 : wait-event ( mx us -- n )
     [ [ fd>> ] [ events>> ] bi [ underlying>> ] [ length ] bi ] [ 1000 /i ] bi*
-    epoll_wait dup multiplexer-error ;
+    epoll_wait multiplexer-error ;
 
 : handle-event ( event mx -- )
     [ epoll-event-fd ] dip
index 3786a82b55a248d21f3a821da938e0df0f9261b5..eaf217af6263ee9d51de195938bd342e2f4598f0 100644 (file)
@@ -3,7 +3,8 @@
 USING: accessors alien.c-types alien.syntax combinators
 io.backend io.files io.unix.files kernel math system unix
 unix.statfs.freebsd unix.statvfs.freebsd unix.getfsstat.freebsd
-sequences grouping alien.strings io.encodings.utf8 ;
+sequences grouping alien.strings io.encodings.utf8
+specialized-arrays.direct.uint arrays ;
 IN: io.unix.files.freebsd
 
 TUPLE: freebsd-file-system-info < unix-file-system-info
@@ -32,7 +33,7 @@ M: freebsd statfs>file-system-info ( file-system-info statvfs -- file-system-inf
         [ statfs-f_asyncreads >>asyncreads ]
         [ statfs-f_namemax >>name-max ]
         [ statfs-f_owner >>owner ]
-        [ statfs-f_fsid >>id ]
+        [ statfs-f_fsid 2 <direct-uint-array> >array >>id ]
         [ statfs-f_fstypename utf8 alien>string >>type ]
         [ statfs-f_mntfromname utf8 alien>string >>device-name ]
         [ statfs-f_mntonname utf8 alien>string >>mount-point ]
index 3e4e1c043a0e1589ee786558c306895132c44ffd..c30855c3ee850c3a4315d6b67a27ebd05e320022 100644 (file)
@@ -3,7 +3,8 @@
 USING: accessors alien.c-types alien.syntax combinators csv
 io.backend io.encodings.utf8 io.files io.streams.string
 io.unix.files kernel math.order namespaces sequences sorting
-system unix unix.statfs.linux unix.statvfs.linux ;
+system unix unix.statfs.linux unix.statvfs.linux
+specialized-arrays.direct.uint arrays ;
 IN: io.unix.files.linux
 
 TUPLE: linux-file-system-info < unix-file-system-info
@@ -23,7 +24,7 @@ M: linux statfs>file-system-info ( struct -- statfs )
         [ statfs64-f_bavail >>blocks-available ]
         [ statfs64-f_files >>files ]
         [ statfs64-f_ffree >>files-free ]
-        [ statfs64-f_fsid >>id ]
+        [ statfs64-f_fsid 2 <direct-uint-array> >array >>id ]
         [ statfs64-f_namelen >>namelen ]
         [ statfs64-f_frsize >>preferred-block-size ]
         ! [ statfs64-f_spare >>spare ]
index 23717b41a467a819ada468fccfc389774ec9da50..82ac3dc70d385e2acfefa6fe3c8812e979fe8392 100644 (file)
@@ -3,8 +3,8 @@
 USING: alien.syntax kernel unix.stat math unix
 combinators system io.backend accessors alien.c-types
 io.encodings.utf8 alien.strings unix.types io.unix.files
-io.files unix.statvfs.netbsd unix.getfsstat.netbsd
-grouping sequences io.encodings.utf8 ;
+io.files unix.statvfs.netbsd unix.getfsstat.netbsd arrays
+grouping sequences io.encodings.utf8 specialized-arrays.direct.uint ;
 IN: io.unix.files.netbsd
 
 TUPLE: netbsd-file-system-info < unix-file-system-info
@@ -35,7 +35,7 @@ M: netbsd statvfs>file-system-info ( file-system-info statvfs -- file-system-inf
         [ statvfs-f_syncwrites >>sync-writes ]
         [ statvfs-f_asyncreads >>async-reads ]
         [ statvfs-f_asyncwrites >>async-writes ]
-        [ statvfs-f_fsidx >>idx ]
+        [ statvfs-f_fsidx 2 <direct-uint-array> >array >>idx ]
         [ statvfs-f_fsid >>id ]
         [ statvfs-f_namemax >>name-max ]
         [ statvfs-f_owner >>owner ]
index 8c8f7c154b2bf79d7a286a7bbf156cd1805b29dc..e5e18b29ea93a470754e288fa0604bddd58dfff0 100644 (file)
@@ -3,7 +3,8 @@
 USING: accessors alien.c-types alien.strings alien.syntax
 combinators io.backend io.files io.unix.files kernel math
 sequences system unix unix.getfsstat.openbsd grouping
-unix.statfs.openbsd unix.statvfs.openbsd unix.types ;
+unix.statfs.openbsd unix.statvfs.openbsd unix.types
+specialized-arrays.direct.uint arrays ;
 IN: io.unix.files.openbsd
 
 TUPLE: freebsd-file-system-info < unix-file-system-info
@@ -30,7 +31,7 @@ M: openbsd statfs>file-system-info ( file-system-info statfs -- file-system-info
         [ statfs-f_syncreads >>sync-reads ]
         [ statfs-f_asyncwrites >>async-writes ]
         [ statfs-f_asyncreads >>async-reads ]
-        [ statfs-f_fsid >>id ]
+        [ statfs-f_fsid 2 <direct-uint-array> >array >>id ]
         [ statfs-f_namemax >>name-max ]
         [ statfs-f_owner >>owner ]
         ! [ statfs-f_spare >>spare ]
index b4e2b7af6fb017be664c9285806415d5561cfd4a..be99d1757264d4d881fb9f9d797a3d12cd0e0b20 100644 (file)
@@ -58,8 +58,7 @@ M: kqueue-mx remove-output-callbacks ( fd mx -- seq )
     [
         [ fd>> f 0 ]
         [ events>> [ underlying>> ] [ length ] bi ] bi
-    ] dip kevent
-    dup multiplexer-error ;
+    ] dip kevent multiplexer-error ;
 
 : handle-kevent ( mx kevent -- )
     [ kevent-ident swap ] [ kevent-filter ] bi {
index 33988c273bc871d124de968898b92b5f515b9821..68ca821ed43a43d20902e68bd2f29fac142e93d5 100644 (file)
@@ -2,7 +2,8 @@ IN: io.unix.launcher.tests
 USING: io.files tools.test io.launcher arrays io namespaces
 continuations math io.encodings.binary io.encodings.ascii
 accessors kernel sequences io.encodings.utf8 destructors
-io.streams.duplex ;
+io.streams.duplex locals concurrency.promises threads
+unix.process ;
 
 [ ] [
     [ "launcher-test-1" temp-file delete-file ] ignore-errors
@@ -121,3 +122,17 @@ io.streams.duplex ;
         input-stream get contents
     ] with-stream
 ] unit-test
+
+! Killed processes were exiting with code 0 on FreeBSD
+[ f ] [
+    [let | p [ <promise> ]
+           s [ <promise> ] |
+       [
+           "sleep 1000" run-detached
+           [ p fulfill ] [ wait-for-process s fulfill ] bi
+       ] in-thread
+
+       p ?promise handle>> 9 kill drop
+       s ?promise 0 =
+    ]
+] unit-test
index e80a372aefc475475cbbb7efed349be164437b4a..729c1545d83a1270b6c7b4bfe4cf82248ab49e4f 100644 (file)
@@ -92,14 +92,16 @@ M: unix kill-process* ( pid -- )
     processes get swap [ nip swap handle>> = ] curry
     assoc-find 2drop ;
 
+TUPLE: signal n ;
+
+: code>status ( code -- obj )
+    dup WIFEXITED [ WEXITSTATUS ] [ WTERMSIG signal boa ] if ;
+
 M: unix wait-for-processes ( -- ? )
     -1 0 <int> tuck WNOHANG waitpid
     dup 0 <= [
         2drop t
     ] [
-        find-process dup [
-            swap *int WEXITSTATUS notify-exit f
-        ] [
-            2drop f
-        ] if
+        find-process dup
+        [ swap *int code>status notify-exit f ] [ 2drop f ] if
     ] if ;
index be5b83f1b06e33e72762249fb09a873fafbb3d7a..fd24e0ac02c7a86ac67dbb26d97f402c91b21eae 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
-USING: kernel io.backend io.monitors io.unix.backend
-io.unix.epoll io.unix.linux.monitors system namespaces ;
+USING: kernel system namespaces io.backend io.unix.backend
+io.unix.multiplexers io.unix.multiplexers.epoll ;
 IN: io.unix.linux
 
 M: linux init-io ( -- )
index f27d48c6b0b3391254498e10329876f75ae59c66..3964a25a04bf86553ad9e9bbb66af2ce1c111144 100644 (file)
@@ -2,10 +2,10 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: kernel io.backend io.monitors io.monitors.recursive
 io.files io.buffers io.monitors io.ports io.timeouts
-io.unix.backend io.unix.select io.encodings.utf8
-unix.linux.inotify assocs namespaces make threads continuations
-init math math.bitwise sets alien alien.strings alien.c-types
-vocabs.loader accessors system hashtables destructors unix ;
+io.unix.backend io.encodings.utf8 unix.linux.inotify assocs
+namespaces make threads continuations init math math.bitwise
+sets alien alien.strings alien.c-types vocabs.loader accessors
+system hashtables destructors unix ;
 IN: io.unix.linux.monitors
 
 SYMBOL: watches
index ef52b676fb60d53070c9c0a80e034f53dc59cc83..75f42b7394770d39b1cb24657e7051492058106e 100644 (file)
@@ -1,10 +1,10 @@
 ! Copyright (C) 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
+USING: io.backend system namespaces io.unix.multiplexers
+io.unix.multiplexers.run-loop ;
 IN: io.unix.macosx
-USING: io.unix.backend io.unix.bsd io.unix.kqueue io.backend
-namespaces system ;
 
 M: macosx init-io ( -- )
-    <kqueue-mx> mx set-global ;
+    <run-loop-mx> mx set-global ;
 
 macosx set-io-backend
diff --git a/basis/io/unix/multiplexers/epoll/authors.txt b/basis/io/unix/multiplexers/epoll/authors.txt
new file mode 100755 (executable)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/basis/io/unix/multiplexers/epoll/epoll.factor b/basis/io/unix/multiplexers/epoll/epoll.factor
new file mode 100644 (file)
index 0000000..08e20d4
--- /dev/null
@@ -0,0 +1,66 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors alien.c-types kernel destructors bit-arrays
+sequences assocs struct-arrays math namespaces locals fry unix
+unix.linux.epoll unix.time io.ports io.unix.backend
+io.unix.multiplexers ;
+IN: io.unix.multiplexers.epoll
+
+TUPLE: epoll-mx < mx events ;
+
+: max-events ( -- n )
+    #! We read up to 256 events at a time. This is an arbitrary
+    #! constant...
+    256 ; inline
+
+: <epoll-mx> ( -- mx )
+    epoll-mx new-mx
+        max-events epoll_create dup io-error >>fd
+        max-events "epoll-event" <struct-array> >>events ;
+
+M: epoll-mx dispose fd>> close-file ;
+
+: make-event ( fd events -- event )
+    "epoll-event" <c-object>
+    [ set-epoll-event-events ] keep
+    [ set-epoll-event-fd ] keep ;
+
+:: do-epoll-ctl ( fd mx what events -- )
+    mx fd>> what fd fd events make-event epoll_ctl io-error ;
+
+: do-epoll-add ( fd mx events -- )
+    EPOLL_CTL_ADD swap EPOLLONESHOT bitor do-epoll-ctl ;
+
+: do-epoll-del ( fd mx events -- )
+    EPOLL_CTL_DEL swap do-epoll-ctl ;
+
+M: epoll-mx add-input-callback ( thread fd mx -- )
+    [ EPOLLIN do-epoll-add ] [ call-next-method ] 2bi ;
+
+M: epoll-mx add-output-callback ( thread fd mx -- )
+    [ EPOLLOUT do-epoll-add ] [ call-next-method ] 2bi ;
+
+M: epoll-mx remove-input-callbacks ( fd mx -- seq )
+    2dup reads>> key? [
+        [ call-next-method ] [ EPOLLIN do-epoll-del ] 2bi
+    ] [ 2drop f ] if ;
+
+M: epoll-mx remove-output-callbacks ( fd mx -- seq )
+    2dup writes>> key? [
+        [ EPOLLOUT do-epoll-del ] [ call-next-method ] 2bi
+    ] [ 2drop f ] if ;
+
+: wait-event ( mx us -- n )
+    [ [ fd>> ] [ events>> ] bi [ underlying>> ] [ length ] bi ] [ 1000 /i ] bi*
+    epoll_wait multiplexer-error ;
+
+: handle-event ( event mx -- )
+    [ epoll-event-fd ] dip
+    [ EPOLLIN EPOLLOUT bitor do-epoll-del ]
+    [ input-available ] [ output-available ] 2tri ;
+
+: handle-events ( mx n -- )
+    [ dup events>> ] dip head-slice swap '[ _ handle-event ] each ;
+
+M: epoll-mx wait-for-events ( us mx -- )
+    swap 60000000 or dupd wait-event handle-events ;
diff --git a/basis/io/unix/multiplexers/epoll/tags.txt b/basis/io/unix/multiplexers/epoll/tags.txt
new file mode 100644 (file)
index 0000000..6bf6830
--- /dev/null
@@ -0,0 +1 @@
+unportable
diff --git a/basis/io/unix/multiplexers/kqueue/authors.txt b/basis/io/unix/multiplexers/kqueue/authors.txt
new file mode 100755 (executable)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/basis/io/unix/multiplexers/kqueue/kqueue.factor b/basis/io/unix/multiplexers/kqueue/kqueue.factor
new file mode 100644 (file)
index 0000000..a66e86a
--- /dev/null
@@ -0,0 +1,76 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: accessors alien.c-types combinators destructors
+io.unix.backend kernel math.bitwise sequences struct-arrays unix
+unix.kqueue unix.time assocs io.unix.multiplexers ;
+IN: io.unix.multiplexers.kqueue
+
+TUPLE: kqueue-mx < mx events ;
+
+: max-events ( -- n )
+    #! We read up to 256 events at a time. This is an arbitrary
+    #! constant...
+    256 ; inline
+
+: <kqueue-mx> ( -- mx )
+    kqueue-mx new-mx
+        kqueue dup io-error >>fd
+        max-events "kevent" <struct-array> >>events ;
+
+M: kqueue-mx dispose fd>> close-file ;
+
+: make-kevent ( fd filter flags -- event )
+    "kevent" <c-object>
+    [ set-kevent-flags ] keep
+    [ set-kevent-filter ] keep
+    [ set-kevent-ident ] keep ;
+
+: register-kevent ( kevent mx -- )
+    fd>> swap 1 f 0 f kevent io-error ;
+
+M: kqueue-mx add-input-callback ( thread fd mx -- )
+    [ call-next-method ] [
+        [ EVFILT_READ { EV_ADD EV_ONESHOT } flags make-kevent ] dip
+        register-kevent
+    ] 2bi ;
+
+M: kqueue-mx add-output-callback ( thread fd mx -- )
+    [ call-next-method ] [
+        [ EVFILT_WRITE { EV_ADD EV_ONESHOT } flags make-kevent ] dip
+        register-kevent
+    ] 2bi ;
+
+M: kqueue-mx remove-input-callbacks ( fd mx -- seq )
+    2dup reads>> key? [
+        [ call-next-method ] [
+            [ EVFILT_READ EV_DELETE make-kevent ] dip
+            register-kevent
+        ] 2bi
+    ] [ 2drop f ] if ;
+
+M: kqueue-mx remove-output-callbacks ( fd mx -- seq )
+    2dup writes>> key? [
+        [
+            [ EVFILT_WRITE EV_DELETE make-kevent ] dip
+            register-kevent
+        ] [ call-next-method ] 2bi
+    ] [ 2drop f ] if ;
+
+: wait-kevent ( mx timespec -- n )
+    [
+        [ fd>> f 0 ]
+        [ events>> [ underlying>> ] [ length ] bi ] bi
+    ] dip kevent multiplexer-error ;
+
+: handle-kevent ( mx kevent -- )
+    [ kevent-ident swap ] [ kevent-filter ] bi {
+        { EVFILT_READ [ input-available ] }
+        { EVFILT_WRITE [ output-available ] }
+    } case ;
+
+: handle-kevents ( mx n -- )
+    [ dup events>> ] dip head-slice [ handle-kevent ] with each ;
+
+M: kqueue-mx wait-for-events ( us mx -- )
+    swap dup [ make-timespec ] when
+    dupd wait-kevent handle-kevents ;
diff --git a/basis/io/unix/multiplexers/kqueue/tags.txt b/basis/io/unix/multiplexers/kqueue/tags.txt
new file mode 100644 (file)
index 0000000..6bf6830
--- /dev/null
@@ -0,0 +1 @@
+unportable
diff --git a/basis/io/unix/multiplexers/multiplexers.factor b/basis/io/unix/multiplexers/multiplexers.factor
new file mode 100644 (file)
index 0000000..1c9fb13
--- /dev/null
@@ -0,0 +1,35 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel accessors assocs sequences threads ;
+IN: io.unix.multiplexers
+
+TUPLE: mx fd reads writes ;
+
+: new-mx ( class -- obj )
+    new
+        H{ } clone >>reads
+        H{ } clone >>writes ; inline
+
+GENERIC: add-input-callback ( thread fd mx -- )
+
+M: mx add-input-callback reads>> push-at ;
+
+GENERIC: add-output-callback ( thread fd mx -- )
+
+M: mx add-output-callback writes>> push-at ;
+
+GENERIC: remove-input-callbacks ( fd mx -- callbacks )
+
+M: mx remove-input-callbacks reads>> delete-at* drop ;
+
+GENERIC: remove-output-callbacks ( fd mx -- callbacks )
+
+M: mx remove-output-callbacks writes>> delete-at* drop ;
+
+GENERIC: wait-for-events ( ms mx -- )
+
+: input-available ( fd mx -- )
+    reads>> delete-at* drop [ resume ] each ;
+
+: output-available ( fd mx -- )
+    writes>> delete-at* drop [ resume ] each ;
diff --git a/basis/io/unix/multiplexers/run-loop/run-loop.factor b/basis/io/unix/multiplexers/run-loop/run-loop.factor
new file mode 100644 (file)
index 0000000..4b2486d
--- /dev/null
@@ -0,0 +1,33 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: kernel arrays namespaces math accessors alien locals
+destructors system threads io.unix.multiplexers
+io.unix.multiplexers.kqueue core-foundation
+core-foundation.run-loop ;
+IN: io.unix.multiplexers.run-loop
+
+TUPLE: run-loop-mx kqueue-mx ;
+
+: file-descriptor-callback ( -- callback )
+    "void" { "CFFileDescriptorRef" "CFOptionFlags" "void*" }
+    "cdecl" [
+        3drop
+        0 mx get kqueue-mx>> wait-for-events
+        reset-run-loop
+        yield
+    ] alien-callback ;
+
+: <run-loop-mx> ( -- mx )
+    [
+        <kqueue-mx> |dispose
+        dup fd>> file-descriptor-callback add-fd-to-run-loop
+        run-loop-mx boa
+    ] with-destructors ;
+
+M: run-loop-mx add-input-callback kqueue-mx>> add-input-callback ;
+M: run-loop-mx add-output-callback kqueue-mx>> add-output-callback ;
+M: run-loop-mx remove-input-callbacks kqueue-mx>> remove-input-callbacks ;
+M: run-loop-mx remove-output-callbacks kqueue-mx>> remove-output-callbacks ;
+
+M: run-loop-mx wait-for-events ( us mx -- )
+    swap run-one-iteration [ 0 swap wait-for-events ] [ drop ] if ;
diff --git a/basis/io/unix/multiplexers/run-loop/tags.txt b/basis/io/unix/multiplexers/run-loop/tags.txt
new file mode 100644 (file)
index 0000000..6bf6830
--- /dev/null
@@ -0,0 +1 @@
+unportable
diff --git a/basis/io/unix/multiplexers/select/authors.txt b/basis/io/unix/multiplexers/select/authors.txt
new file mode 100755 (executable)
index 0000000..1901f27
--- /dev/null
@@ -0,0 +1 @@
+Slava Pestov
diff --git a/basis/io/unix/multiplexers/select/select.factor b/basis/io/unix/multiplexers/select/select.factor
new file mode 100644 (file)
index 0000000..915daac
--- /dev/null
@@ -0,0 +1,56 @@
+! Copyright (C) 2004, 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: alien.c-types kernel bit-arrays sequences assocs unix
+math namespaces accessors math.order locals unix.time fry
+io.ports io.unix.backend io.unix.multiplexers ;
+IN: io.unix.multiplexers.select
+
+TUPLE: select-mx < mx read-fdset write-fdset ;
+
+! Factor's bit-arrays are an array of bytes, OS X expects
+! FD_SET to be an array of cells, so we have to account for
+! byte order differences on big endian platforms
+: munge ( i -- i' )
+    little-endian? [ BIN: 11000 bitxor ] unless ; inline
+
+: <select-mx> ( -- mx )
+    select-mx new-mx
+        FD_SETSIZE 8 * <bit-array> >>read-fdset
+        FD_SETSIZE 8 * <bit-array> >>write-fdset ;
+
+: clear-nth ( n seq -- ? )
+    [ nth ] [ [ f ] 2dip set-nth ] 2bi ;
+
+:: check-fd ( fd fdset mx quot -- )
+    fd munge fdset clear-nth [ fd mx quot call ] when ; inline
+
+: check-fdset ( fds fdset mx quot -- )
+    [ check-fd ] 3curry each ; inline
+
+: init-fdset ( fds fdset -- )
+    '[ t swap munge _ set-nth ] each ;
+
+: read-fdset/tasks ( mx -- seq fdset )
+    [ reads>> keys ] [ read-fdset>> ] bi ;
+
+: write-fdset/tasks ( mx -- seq fdset )
+    [ writes>> keys ] [ write-fdset>> ] bi ;
+
+: max-fd ( assoc -- n )
+    dup assoc-empty? [ drop 0 ] [ keys supremum ] if ;
+
+: num-fds ( mx -- n )
+    [ reads>> max-fd ] [ writes>> max-fd ] bi max 1+ ;
+
+: init-fdsets ( mx -- nfds read write except )
+    [ num-fds ]
+    [ read-fdset/tasks [ init-fdset ] [ underlying>> ] bi ]
+    [ write-fdset/tasks [ init-fdset ] [ underlying>> ] bi ] tri
+    f ;
+
+M:: select-mx wait-for-events ( us mx -- )
+    mx
+    [ init-fdsets us dup [ make-timeval ] when select multiplexer-error drop ]
+    [ [ read-fdset/tasks ] keep [ input-available ] check-fdset ]
+    [ [ write-fdset/tasks ] keep [ output-available ] check-fdset ]
+    tri ;
diff --git a/basis/io/unix/multiplexers/select/tags.txt b/basis/io/unix/multiplexers/select/tags.txt
new file mode 100644 (file)
index 0000000..6bf6830
--- /dev/null
@@ -0,0 +1 @@
+unportable
index 27231aee5a8adc56e303ae7ac4cba27d38c4e20f..a6b61001a63c059403dbb1f6f9b9b11c4c4d57c2 100644 (file)
@@ -50,7 +50,7 @@ TUPLE: select-mx < mx read-fdset write-fdset ;
 
 M:: select-mx wait-for-events ( us mx -- )
     mx
-    [ init-fdsets us dup [ make-timeval ] when select multiplexer-error ]
+    [ init-fdsets us dup [ make-timeval ] when select multiplexer-error drop ]
     [ [ read-fdset/tasks ] keep [ input-available ] check-fdset ]
     [ [ write-fdset/tasks ] keep [ output-available ] check-fdset ]
     tri ;
index a38e9ea784201229e8a1dab3e1a1427c482b9a13..f52632040d23725697604b0d8186b764fcb0bde0 100644 (file)
@@ -61,12 +61,6 @@ TUPLE: alien-callback-params < alien-node-params quot xt ;
     ! Quotation which coerces return value to required type
     return-prep-quot infer-quot-here ;
 
-! Callbacks are registered in a global hashtable. If you clear
-! this hashtable, they will all be blown away by code GC, beware
-SYMBOL: callbacks
-
-[ H{ } clone callbacks set-global ] "alien.compiler" add-init-hook
-
 : register-callback ( word -- ) callbacks get conjoin ;
 
 : callback-bottom ( params -- )
index 71dc746fb51e938d68495e8ca8a2366f67d770b3..a390ce56c4437f4b16a74da051fde20cc7c98502 100644 (file)
@@ -107,3 +107,8 @@ M: quit-responder call-responder*
     "tools.deploy.test.8" shake-and-bake\r
     run-temp-image\r
 ] unit-test\r
+\r
+[ ] [\r
+    "tools.deploy.test.9" shake-and-bake\r
+    run-temp-image\r
+] unit-test\r
index b38c5da6767da39b42ee3a944b2c5318c66cb63b..f3131237bfa4e7c739a0df95c9a1a4c9288e7f04 100644 (file)
@@ -1,14 +1,15 @@
 USING: tools.deploy.config ;
 H{
-    { deploy-threads? t }
-    { deploy-c-types? f }
+    { deploy-unicode? f }
+    { deploy-name "tools.deploy.test.3" }
     { deploy-ui? f }
-    { deploy-word-props? f }
+    { "stop-after-last-window?" t }
     { deploy-word-defs? f }
-    { deploy-math? t }
-    { deploy-io 3 }
-    { deploy-name "tools.deploy.test.3" }
-    { deploy-compiler? t }
     { deploy-reflection 1 }
-    { "stop-after-last-window?" t }
+    { deploy-compiler? t }
+    { deploy-threads? t }
+    { deploy-io 3 }
+    { deploy-math? t }
+    { deploy-word-props? f }
+    { deploy-c-types? f }
 }
diff --git a/basis/tools/deploy/test/9/9.factor b/basis/tools/deploy/test/9/9.factor
new file mode 100644 (file)
index 0000000..a1cbd5b
--- /dev/null
@@ -0,0 +1,10 @@
+USING: alien kernel math ;
+IN: tools.deploy.test.9
+
+: callback-test ( -- callback )
+    "int" { "int" } "cdecl" [ 1 + ] alien-callback ;
+
+: indirect-test ( -- )
+    10 callback-test "int" { "int" } "cdecl" alien-indirect 11 assert= ;
+
+MAIN: indirect-test
diff --git a/basis/tools/deploy/test/9/deploy.factor b/basis/tools/deploy/test/9/deploy.factor
new file mode 100644 (file)
index 0000000..91b1da5
--- /dev/null
@@ -0,0 +1,15 @@
+USING: tools.deploy.config ;
+H{
+    { deploy-unicode? f }
+    { deploy-name "tools.deploy.test.9" }
+    { deploy-ui? f }
+    { "stop-after-last-window?" t }
+    { deploy-word-defs? f }
+    { deploy-reflection 1 }
+    { deploy-compiler? t }
+    { deploy-threads? f }
+    { deploy-io 1 }
+    { deploy-math? t }
+    { deploy-word-props? f }
+    { deploy-c-types? f }
+}
index f03861a8ed76828d1bcc35c3cbe7b5f2ba253fec..7d193d0aac29ed03f9a65d3cfd10a214eb367c8b 100644 (file)
@@ -3,11 +3,11 @@ USING: help.markup help.syntax sequences.private ;
 \r
 HELP: disassemble\r
 { $values { "obj" "a word or a pair of addresses" } }\r
-{ $description "Disassembles either a compiled word definition or an arbitrary memory range (in the case " { $snippet "obj" } " is a pair of integers) by attaching " { $snippet "gdb" } " to the Factor VM and capturing the output." }\r
-{ $notes "In some cases the Factor compiler emits data inline with code, which can confuse " { $snippet "gdb" } ". This occurs in words which call " { $link dispatch } ", where the jump table addresses are compiled inline. Also on the ARM architecture, various pointers are often compiled inline, and the preceeding instruction jumps over the inline pinter." } ;\r
+{ $description "Disassembles either a compiled word definition or an arbitrary memory range (in the case " { $snippet "obj" } " is a pair of integers)." }\r
+{ $notes "In some cases the Factor compiler emits data inline with code, which can confuse the disassembler. This occurs in words which call " { $link dispatch } ", where the jump table addresses are compiled inline." } ;\r
 \r
 ARTICLE: "tools.disassembler" "Disassembling words"\r
-"The " { $vocab-link "tools.disassembler" } " vocabulary integrates Factor with the GNU debugger (" { $snippet "gdb" } ") for viewing the assembly code generated by the compiler. It can be used on both Unix and Windows as long as a working copy of " { $snippet "gdb" } " is installed and available in the " { $snippet "PATH" } "."\r
+"The " { $vocab-link "tools.disassembler" } " vocabulary provides support for disassembling compiled word definitions. It uses the " { $snippet "libudis86" } " library on x86-32 and x86-64, and " { $snippet "gdb" } " on PowerPC."\r
 { $subsection disassemble } ;\r
 \r
 ABOUT: "tools.disassembler"\r
index 76e1f0f1b86132ec2910258b3d7f577ae39d99ac..2a717c084fd038515ad36586f01bdc2d5eda46b6 100644 (file)
@@ -1,43 +1,24 @@
-! Copyright (C) 2008 Slava Pestov, Jorge Acereda Macia.
+! Copyright (C) 2008 Slava Pestov.
 ! 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 make
-qualified system math compiler.codegen.fixup
-io.encodings.ascii accessors generic tr ;
+USING: tr arrays sequences io words generic system combinators
+vocabs.loader kernel ;
 IN: tools.disassembler
 
-: in-file ( -- path ) "gdb-in.txt" temp-file ;
+GENERIC: disassemble ( obj -- )
 
-: out-file ( -- path ) "gdb-out.txt" temp-file ;
+SYMBOL: disassembler-backend
 
-GENERIC: make-disassemble-cmd ( obj -- )
+HOOK: disassemble* disassembler-backend ( from to -- lines )
 
-M: word make-disassemble-cmd
-    word-xt code-format - 2array make-disassemble-cmd ;
-
-M: pair make-disassemble-cmd
-    in-file ascii [
-        "attach " write
-        current-process-handle number>string print
-        "disassemble " write
-        [ number>string write bl ] each
-    ] with-file-writer ;
-
-M: method-spec make-disassemble-cmd
-    first2 method make-disassemble-cmd ;
+TR: tabs>spaces "\t" "\s" ;
 
-: gdb-binary ( -- string ) "gdb" ;
+M: pair disassemble first2 disassemble* [ tabs>spaces print ] each ;
 
-: run-gdb ( -- lines )
-    <process>
-        +closed+ >>stdin
-        out-file >>stdout
-        [ gdb-binary , "-x" , in-file , "-batch" , ] { } make >>command
-    try-process
-    out-file ascii file-lines ;
+M: word disassemble word-xt 2array disassemble ;
 
-TR: tabs>spaces "\t" "\s" ;
+M: method-spec disassemble first2 method disassemble ;
 
-: disassemble ( obj -- )
-    make-disassemble-cmd run-gdb
-    [ tabs>spaces ] map [ print ] each ;
+cpu x86? os unix? and
+"tools.disassembler.udis"
+"tools.disassembler.gdb" ?
+require
diff --git a/basis/tools/disassembler/gdb/gdb.factor b/basis/tools/disassembler/gdb/gdb.factor
new file mode 100644 (file)
index 0000000..65d0e2f
--- /dev/null
@@ -0,0 +1,36 @@
+! Copyright (C) 2008 Slava Pestov, Jorge Acereda Macia.
+! 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 make
+qualified system math io.encodings.ascii accessors
+tools.disassembler ;
+IN: tools.disassembler.gdb
+
+SINGLETON: gdb-disassembler
+
+: in-file ( -- path ) "gdb-in.txt" temp-file ;
+
+: out-file ( -- path ) "gdb-out.txt" temp-file ;
+
+: make-disassemble-cmd ( from to -- )
+    in-file ascii [
+        "attach " write
+        current-process-handle number>string print
+        "disassemble " write
+        [ number>string write bl ] bi@
+    ] with-file-writer ;
+
+: gdb-binary ( -- string ) "gdb" ;
+
+: run-gdb ( -- lines )
+    <process>
+        +closed+ >>stdin
+        out-file >>stdout
+        [ gdb-binary , "-x" , in-file , "-batch" , ] { } make >>command
+    try-process
+    out-file ascii file-lines ;
+
+M: gdb-disassembler disassemble*
+    make-disassemble-cmd run-gdb ;
+
+gdb-disassembler disassembler-backend set-global
diff --git a/basis/tools/disassembler/gdb/tags.txt b/basis/tools/disassembler/gdb/tags.txt
new file mode 100644 (file)
index 0000000..6bf6830
--- /dev/null
@@ -0,0 +1 @@
+unportable
diff --git a/basis/tools/disassembler/udis/tags.txt b/basis/tools/disassembler/udis/tags.txt
new file mode 100644 (file)
index 0000000..6bf6830
--- /dev/null
@@ -0,0 +1 @@
+unportable
diff --git a/basis/tools/disassembler/udis/udis.factor b/basis/tools/disassembler/udis/udis.factor
new file mode 100644 (file)
index 0000000..c5b5c80
--- /dev/null
@@ -0,0 +1,89 @@
+! Copyright (C) 2008 Slava Pestov, Jorge Acereda Macia.
+! See http://factorcode.org/license.txt for BSD license.
+USING: tools.disassembler namespaces combinators
+alien alien.syntax alien.c-types lexer parser kernel
+sequences layouts math math.parser system make fry arrays ;
+IN: tools.disassembler.udis
+
+<<
+"libudis86" {
+    { [ os macosx? ] [ "libudis86.0.dylib" ] }
+    { [ os unix? ] [ "libudis86.so.0" ] }
+    { [ os winnt? ] [ "libudis86.dll" ] }
+} cond "cdecl" add-library
+>>
+
+LIBRARY: libudis86
+
+TYPEDEF: char[592] ud
+
+FUNCTION: void ud_translate_intel ( ud* u ) ;
+FUNCTION: void ud_translate_att ( ud* u ) ;
+
+: UD_SYN_INTEL    &: ud_translate_intel ; inline
+: UD_SYN_ATT      &: ud_translate_att ; inline
+: UD_EOI          -1 ; inline
+: UD_INP_CACHE_SZ 32 ; inline
+: UD_VENDOR_AMD   0 ; inline
+: UD_VENDOR_INTEL 1 ; inline
+
+FUNCTION: void ud_init ( ud* u ) ;
+FUNCTION: void ud_set_mode ( ud* u, uint8_t mode ) ;
+FUNCTION: void ud_set_pc ( ud* u, ulonglong pc ) ;
+FUNCTION: void ud_set_input_buffer ( ud* u, uint8_t* offset, size_t size ) ;
+FUNCTION: void ud_set_vendor ( ud* u, uint vendor ) ;
+FUNCTION: void ud_set_syntax ( ud* u, void* syntax ) ;
+FUNCTION: void ud_input_skip ( ud* u, size_t size ) ;
+FUNCTION: int ud_input_end ( ud* u ) ;
+FUNCTION: uint ud_decode ( ud* u ) ;
+FUNCTION: uint ud_disassemble ( ud* u ) ;
+FUNCTION: char* ud_insn_asm ( ud* u ) ;
+FUNCTION: void* ud_insn_ptr ( ud* u ) ;
+FUNCTION: ulonglong ud_insn_off ( ud* u ) ;
+FUNCTION: char* ud_insn_hex ( ud* u ) ;
+FUNCTION: uint ud_insn_len ( ud* u ) ;
+FUNCTION: char* ud_lookup_mnemonic ( int c ) ;
+
+: <ud> ( -- ud )
+    "ud" <c-object>
+    dup ud_init
+    dup cell-bits ud_set_mode
+    dup UD_SYN_INTEL ud_set_syntax ;
+
+SINGLETON: udis-disassembler
+
+: buf/len ( from to -- buf len ) [ drop <alien> ] [ swap - ] 2bi ;
+
+: format-disassembly ( lines -- lines' )
+    dup [ second length ] map supremum
+    '[
+        [
+            [ first >hex cell 2 * CHAR: 0 pad-left % ": " % ]
+            [ second _ CHAR: \s pad-right % "  " % ]
+            [ third % ]
+            tri
+        ] "" make
+    ] map ;
+
+: (disassemble) ( ud -- lines )
+    [
+        dup '[
+            _ ud_disassemble 0 =
+            [ f ] [
+                _
+                [ ud_insn_off ]
+                [ ud_insn_hex ]
+                [ ud_insn_asm ]
+                tri 3array , t
+            ] if
+        ] loop
+    ] { } make ;
+
+M: udis-disassembler disassemble* ( from to -- buffer )
+    [ <ud> ] 2dip {
+        [ drop ud_set_pc ]
+        [ buf/len ud_set_input_buffer ]
+        [ 2drop (disassemble) format-disassembly ]
+    } 3cleave ;
+
+udis-disassembler disassembler-backend set-global
index b4295af2050b08ee28cfdc237f751b441f7084db..7968639d47ff510987d6e1d3e6429ded5ad08735 100755 (executable)
@@ -41,9 +41,9 @@ percent-used percent-free ;
 
 : file-system-spec ( file-system-info obj -- str )
     {
-        { device-name [ device-name>> ] }
-        { mount-point [ mount-point>> ] }
-        { type [ type>> ] }
+        { device-name [ device-name>> [ "" ] unless* ] }
+        { mount-point [ mount-point>> [ "" ] unless* ] }
+        { type [ type>> [ "" ] unless* ] }
         { available-space [ available-space>> [ 0 ] unless* ] }
         { free-space [ free-space>> [ 0 ] unless* ] }
         { used-space [ used-space>> [ 0 ] unless* ] }
old mode 100644 (file)
new mode 100755 (executable)
index 0840d07..eaa0953
@@ -5,8 +5,6 @@ IN: ui.backend
 
 SYMBOL: ui-backend
 
-HOOK: do-events ui-backend ( -- )
-
 HOOK: set-title ui-backend ( string world -- )
 
 HOOK: set-fullscreen* ui-backend ( ? world -- )
@@ -17,11 +15,17 @@ HOOK: (open-window) ui-backend ( world -- )
 
 HOOK: (close-window) ui-backend ( handle -- )
 
+HOOK: (open-offscreen-buffer) ui-backend ( world -- )
+
+HOOK: (close-offscreen-buffer) ui-backend ( handle -- )
+
 HOOK: raise-window* ui-backend ( world -- )
 
-HOOK: select-gl-context ui-backend ( handle -- )
+GENERIC: select-gl-context ( handle -- )
+
+GENERIC: flush-gl-context ( handle -- )
 
-HOOK: flush-gl-context ui-backend ( handle -- )
+HOOK: offscreen-pixels ui-backend ( world -- alien w h )
 
 HOOK: beep ui-backend ( -- )
 
old mode 100644 (file)
new mode 100755 (executable)
index b90f4d3..331c0a6
@@ -3,21 +3,22 @@
 USING: accessors math arrays assocs cocoa cocoa.application
 command-line kernel memory namespaces cocoa.messages
 cocoa.runtime cocoa.subclassing cocoa.pasteboard cocoa.types
-cocoa.windows cocoa.classes cocoa.application cocoa.nibs
-sequences system ui ui.backend ui.clipboards ui.gadgets
-ui.gadgets.worlds ui.cocoa.views core-foundation threads
-math.geometry.rect fry ;
+cocoa.windows cocoa.classes cocoa.nibs sequences system ui
+ui.backend ui.clipboards ui.gadgets ui.gadgets.worlds
+ui.cocoa.views core-foundation core-foundation.run-loop threads
+math.geometry.rect fry libc generalizations alien.c-types
+cocoa.views combinators io.thread ;
 IN: ui.cocoa
 
-TUPLE: handle view window ;
+TUPLE: handle ;
+TUPLE: window-handle < handle view window ;
+TUPLE: offscreen-handle < handle context buffer ;
 
-C: <handle> handle
+C: <window-handle> window-handle
+C: <offscreen-handle> offscreen-handle
 
 SINGLETON: cocoa-ui-backend
 
-M: cocoa-ui-backend do-events ( -- )
-    [ NSApp '[ _ do-event ] loop ui-wait ] with-autorelease-pool ;
-
 TUPLE: pasteboard handle ;
 
 C: <pasteboard> pasteboard
@@ -39,7 +40,8 @@ M: pasteboard set-clipboard-contents
 : gadget-window ( world -- )
     dup <FactorView>
     2dup swap world>NSRect <ViewWindow>
-    [ [ -> release ] [ install-window-delegate ] bi* ] [ <handle> ] 2bi
+    [ [ -> release ] [ install-window-delegate ] bi* ]
+    [ <window-handle> ] 2bi
     >>handle drop ;
 
 M: cocoa-ui-backend set-title ( string world -- )
@@ -88,11 +90,39 @@ M: cocoa-ui-backend raise-window* ( world -- )
         NSApp 1 -> activateIgnoringOtherApps:
     ] when* ;
 
-M: cocoa-ui-backend select-gl-context ( handle -- )
-    view>> -> openGLContext -> makeCurrentContext ;
+: pixel-size ( pixel-format -- size )
+    0 <int> [ NSOpenGLPFAColorSize 0 -> getValues:forAttribute:forVirtualScreen: ]
+    keep *int -3 shift ;
+
+: offscreen-buffer ( world pixel-format -- alien w h pitch )
+    [ dim>> first2 ] [ pixel-size ] bi*
+    { [ * * malloc ] [ 2drop ] [ drop nip ] [ nip * ] } 3cleave ;
+
+: gadget-offscreen-context ( world -- context buffer )
+    NSOpenGLPFAOffScreen 1array <PixelFormat>
+    [ nip NSOpenGLContext -> alloc swap f -> initWithFormat:shareContext: dup ]
+    [ offscreen-buffer ] 2bi
+    4 npick [ -> setOffScreen:width:height:rowbytes: ] dip ;
+
+M: cocoa-ui-backend (open-offscreen-buffer) ( world -- )
+    dup gadget-offscreen-context <offscreen-handle> >>handle drop ;
+
+M: cocoa-ui-backend (close-offscreen-buffer) ( handle -- )
+    [ context>> -> release ]
+    [ buffer>> free ] bi ;
+
+GENERIC: (gl-context) ( handle -- context )
+M: window-handle (gl-context) view>> -> openGLContext ;
+M: offscreen-handle (gl-context) context>> ;
+
+M: handle select-gl-context ( handle -- )
+    (gl-context) -> makeCurrentContext ;
+
+M: handle flush-gl-context ( handle -- )
+    (gl-context) -> flushBuffer ;
 
-M: cocoa-ui-backend flush-gl-context ( handle -- )
-    view>> -> openGLContext -> flushBuffer ;
+M: cocoa-ui-backend offscreen-pixels ( world -- alien w h )
+    [ handle>> buffer>> ] [ dim>> first2 neg ] bi ;
 
 M: cocoa-ui-backend beep ( -- )
     NSBeep ;
@@ -102,8 +132,8 @@ CLASS: {
     { +name+ "FactorApplicationDelegate" }
 }
 
-{ "applicationDidFinishLaunching:" "void" { "id" "SEL" "id" }
-    [ 3drop event-loop ]
+{  "applicationDidUpdate:" "void" { "id" "SEL" "id" }
+    [ 3drop reset-run-loop ]
 } ;
 
 : install-app-delegate ( -- )
@@ -121,6 +151,9 @@ M: cocoa-ui-backend ui
             init-clipboard
             cocoa-init-hook get call
             start-ui
+            f io-thread-running? set-global
+            init-thread-timer
+            reset-run-loop
             NSApp -> run
         ] ui-running
     ] with-cocoa ;
index ccaae0c1ab39629f498dc63ab166b82e9aeb79e9..a0755e9ec89da647a7566e457e01c9239dcfec20 100644 (file)
@@ -1,10 +1,10 @@
-! Copyright (C) 2006, 2007 Slava Pestov.
+! Copyright (C) 2006, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien.syntax cocoa cocoa.nibs cocoa.application
 cocoa.classes cocoa.dialogs cocoa.pasteboard cocoa.subclassing
-core-foundation help.topics kernel memory namespaces parser
-system ui ui.tools.browser ui.tools.listener ui.tools.workspace
-ui.cocoa eval locals ;
+core-foundation core-foundation.strings help.topics kernel
+memory namespaces parser system ui ui.tools.browser
+ui.tools.listener ui.tools.workspace ui.cocoa eval locals ;
 IN: ui.cocoa.tools
 
 : finder-run-files ( alien -- )
index 128fdceeb4f02065020c39f4f88741effc056470..3201779cc5026822e96a68f3a12a3d71654da0db 100644 (file)
@@ -4,7 +4,7 @@ USING: accessors alien alien.c-types arrays assocs cocoa kernel
 math cocoa.messages cocoa.subclassing cocoa.classes cocoa.views
 cocoa.application cocoa.pasteboard cocoa.types cocoa.windows
 sequences ui ui.gadgets ui.gadgets.worlds ui.gestures
-core-foundation threads combinators math.geometry.rect ;
+core-foundation.strings threads combinators math.geometry.rect ;
 IN: ui.cocoa.views
 
 : send-mouse-moved ( view event -- )
@@ -60,7 +60,7 @@ IN: ui.cocoa.views
     dup event-modifiers swap key-code ;
 
 : send-key-event ( view gesture -- )
-    swap window-focus propagate-gesture ;
+    swap window propagate-key-gesture ;
 
 : interpret-key-event ( view event -- )
     NSArray swap -> arrayWithObject: -> interpretKeyEvents: ;
@@ -266,30 +266,23 @@ CLASS: {
 { "writeSelectionToPasteboard:types:" "char" { "id" "SEL" "id" "id" }
     [
         CF>string-array NSStringPboardType swap member? [
-            >r drop window-focus gadget-selection dup [
-                r> set-pasteboard-string 1
-            ] [
-                r> 2drop 0
-            ] if
-        ] [
-            3drop 0
-        ] if
+            [ drop window-focus gadget-selection ] dip over
+            [ set-pasteboard-string 1 ] [ 2drop 0 ] if
+        ] [ 3drop 0 ] if
     ]
 }
 
 { "readSelectionFromPasteboard:" "char" { "id" "SEL" "id" }
     [
         pasteboard-string dup [
-            [ drop window-focus ] dip swap user-input 1
-        ] [
-            3drop 0
-        ] if
+            [ drop window ] dip swap user-input 1
+        ] [ 3drop 0 ] if
     ]
 }
 
 ! Text input
 { "insertText:" "void" { "id" "SEL" "id" }
-    [ nip CF>string swap window-focus user-input ]
+    [ nip CF>string swap window user-input ]
 }
 
 { "hasMarkedText" "char" { "id" "SEL" }
diff --git a/basis/ui/event-loop/event-loop.factor b/basis/ui/event-loop/event-loop.factor
new file mode 100644 (file)
index 0000000..fe6f4d7
--- /dev/null
@@ -0,0 +1,19 @@
+! Copyright (C) 2008 Slava Pestov.
+! See http://factorcode.org/license.txt for BSD license.
+USING: ui.backend kernel namespaces sequences deques calendar
+threads ;
+IN: ui.event-loop
+
+: event-loop? ( -- ? )
+    {
+        { [ stop-after-last-window? get not ] [ t ] }
+        { [ graft-queue deque-empty? not ] [ t ] }
+        { [ windows get-global empty? not ] [ t ] }
+        [ f ]
+    } cond ;
+
+HOOK: do-events ui-backend ( -- )
+
+: event-loop ( quot -- ) [ event-loop? ] [ do-events ] [ ] while ;
+
+: ui-wait ( -- ) 10 milliseconds sleep ;
index 35781fa5685606d99137c1cf8acc2aa19f7d38da..60e4e58ed5d7e9539e24019d887927ffb0f505b5 100644 (file)
@@ -2,6 +2,10 @@ USING: ui.gadgets ui.render ui.gestures ui.backend help.markup
 help.syntax models opengl strings ;
 IN: ui.gadgets.worlds
 
+HELP: user-input
+{ $values { "string" string } { "world" world } }
+{ $description "Calls " { $link user-input* } " on every parent of the world's currently-focused child." } ;
+
 HELP: origin
 { $var-description "Within the dynamic extent of " { $link draw-world } ", holds the co-ordinate system origin for the gadget currently being drawn." } ;
 
index 3b9b2fa1f374157b15ef922675539140d032d0ca..732a438203496df1400c2654eaed6eb487cff55b 100644 (file)
@@ -38,8 +38,8 @@ M: world request-focus-on ( child gadget -- )
     2dup eq?
     [ 2drop ] [ dup focused?>> (request-focus) ] if ;
 
-: <world> ( gadget title status -- world )
-    { 0 1 } world new-track
+: new-world ( gadget title status class -- world )
+    { 0 1 } swap new-track
         t >>root?
         t >>active?
         H{ } clone >>fonts
@@ -49,6 +49,9 @@ M: world request-focus-on ( child gadget -- )
         swap 1 track-add
     dup request-focus ;
 
+: <world> ( gadget title status -- world )
+    world new-world ;
+
 M: world layout*
     dup call-next-method
     dup glass>> [
index 602d3fd4255a25d7c032f24e3384b221d8106e07..f6495a14c3297f4dcc8c6ec5187dac8d7c084599 100644 (file)
@@ -1,5 +1,5 @@
-USING: ui.gadgets help.markup help.syntax hashtables
-strings kernel system ;
+USING: ui.gadgets ui.gadgets.worlds help.markup help.syntax
+hashtables strings kernel system ;
 IN: ui.gestures
 
 HELP: set-gestures
@@ -21,10 +21,6 @@ HELP: propagate-gesture
 { $values { "gesture" "a gesture" } { "gadget" gadget } }
 { $description "Calls " { $link handle-gesture } " on every parent of " { $snippet "gadget" } "." } ;
 
-HELP: user-input
-{ $values { "string" string } { "gadget" gadget } }
-{ $description "Calls " { $link user-input* } " on every parent of the gadget." } ;
-
 HELP: motion
 { $class-description "Mouse motion gesture." }
 { $examples { $code "T{ motion }" } } ;
index 5faaa93292ed4a4a5b5e294fa23b4610509e0ee6..123a7620d1f4b500b75d8217e8ed8209ca2922f7 100644 (file)
@@ -41,13 +41,25 @@ M: propagate-gesture send-queued-gesture
 : propagate-gesture ( gesture gadget -- )
     \ propagate-gesture queue-gesture ;
 
-TUPLE: user-input string gadget ;
+TUPLE: propagate-key-gesture gesture world ;
+
+: world-focus ( world -- gadget )
+    dup focus>> [ world-focus ] [ ] ?if ;
+
+M: propagate-key-gesture send-queued-gesture
+    [ gesture>> ] [ world>> world-focus ] bi
+    [ handle-gesture ] with each-parent drop ;
+
+: propagate-key-gesture ( gesture world -- )
+    \ propagate-key-gesture queue-gesture ;
+
+TUPLE: user-input string world ;
 
 M: user-input send-queued-gesture
-    [ string>> ] [ gadget>> ] bi
+    [ string>> ] [ world>> world-focus ] bi
     [ user-input* ] with each-parent drop ;
 
-: user-input ( string gadget -- )
+: user-input ( string world -- )
     '[ _ \ user-input queue-gesture ] unless-empty ;
 
 ! Gesture objects
@@ -261,9 +273,6 @@ SYMBOL: drag-timer
     scroll-direction set-global
     T{ mouse-scroll } hand-gadget get-global propagate-gesture ;
 
-: world-focus ( world -- gadget )
-    dup focus>> [ world-focus ] [ ] ?if ;
-
 : send-action ( world gesture -- )
     swap world-focus propagate-gesture ;
 
index 738d259cad5c0a3c15843887fab27eb3de9e7e2a..64a98fee0392bec439bb9b6b3207c3824fa0fd3f 100644 (file)
@@ -143,9 +143,7 @@ ARTICLE: "ui-backend-init" "UI initialization and the event loop"
 }
 "The above word must call the following:"
 { $subsection start-ui }
-"The " { $link ui } " word must not return until the event loop has stopped and the UI has been shut down."
-$nl
-"The event loop must not block, since otherwise other Factor threads and I/O will not run. Instead, it should poll for pending events, then call " { $link ui-wait } "." ;
+"The " { $link ui } " word must not return until the event loop has stopped and the UI has been shut down." ;
 
 ARTICLE: "ui-backend-windows" "UI backend window management"
 "The high-level " { $link open-window } " word eventually calls a low-level word which you must implement:"
index 88f0a353b94d76f7308968d7de2e1a7a77cc55b5..b6bc172c21c456f5c2f5cf720e7ea7569f08340a 100644 (file)
@@ -12,16 +12,6 @@ SYMBOL: windows
 
 SYMBOL: stop-after-last-window?
 
-: event-loop? ( -- ? )
-    {
-        { [ stop-after-last-window? get not ] [ t ] }
-        { [ graft-queue deque-empty? not ] [ t ] }
-        { [ windows get-global empty? not ] [ t ] }
-        [ f ]
-    } cond ;
-
-: event-loop ( -- ) [ event-loop? ] [ do-events ] [ ] while ;
-
 : window ( handle -- world ) windows get-global at ;
 
 : window-focus ( handle -- gadget ) window world-focus ;
@@ -60,23 +50,26 @@ SYMBOL: stop-after-last-window?
     focus-path f swap focus-gestures ;
 
 M: world graft*
-    dup (open-window)
-    dup title>> over set-title
-    request-focus ;
+    [ (open-window) ]
+    [ [ title>> ] keep set-title ]
+    [ request-focus ] tri ;
 
 : reset-world ( world -- )
     #! This is used when a window is being closed, but also
     #! when restoring saved worlds on image startup.
-    dup fonts>> clear-assoc
-    dup unfocus-world
-    f >>handle drop ;
+    [ fonts>> clear-assoc ]
+    [ unfocus-world ]
+    [ f >>handle drop ] tri ;
+
+: (ungraft-world) ( world -- )
+    [ free-fonts ]
+    [ hand-clicked close-global ]
+    [ hand-gadget close-global ] tri ;
 
 M: world ungraft*
-    dup free-fonts
-    dup hand-clicked close-global
-    dup hand-gadget close-global
-    dup handle>> (close-window)
-    reset-world ;
+    [ (ungraft-world) ]
+    [ handle>> (close-window) ]
+    [ reset-world ] tri ;
 
 : find-window ( quot -- world )
     windows get values
@@ -140,7 +133,7 @@ SYMBOL: ui-hook
     graft-queue [ notify ] slurp-deque ;
 
 : send-queued-gestures ( -- )
-    gesture-queue [ send-queued-gesture ] slurp-deque ;
+    gesture-queue [ send-queued-gesture notify-queued ] slurp-deque ;
 
 : update-ui ( -- )
     [
@@ -152,9 +145,6 @@ SYMBOL: ui-hook
         ] assert-depth
     ] [ ui-error ] recover ;
 
-: ui-wait ( -- )
-    10 milliseconds sleep ;
-
 SYMBOL: ui-thread
 
 : ui-running ( quot -- )
index 0510e21f17eca9ac4ecfd8224ecd02b9bdca407e..7f68bb5736b5e21b08a78d8a99f41a6c94f7da97 100755 (executable)
@@ -3,14 +3,14 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien alien.c-types alien.strings arrays assocs ui
 ui.gadgets ui.backend ui.clipboards ui.gadgets.worlds
-ui.gestures io kernel math math.vectors namespaces make
-sequences strings vectors words windows.kernel32 windows.gdi32
-windows.user32 windows.opengl32 windows.messages windows.types
-windows.nt windows threads libc combinators
+ui.gestures ui.event-loop io kernel math math.vectors namespaces
+make sequences strings vectors words windows.kernel32
+windows.gdi32 windows.user32 windows.opengl32 windows.messages
+windows.types windows.nt windows threads libc combinators fry
 combinators.short-circuit continuations command-line shuffle
 opengl ui.render ascii math.bitwise locals symbols accessors
-math.geometry.rect math.order ascii calendar
-io.encodings.utf16n ;
+math.geometry.rect math.order ascii calendar io.encodings.utf16n
+;
 IN: ui.windows
 
 SINGLETON: windows-ui-backend
@@ -70,9 +70,11 @@ M: pasteboard set-clipboard-contents drop copy ;
     <pasteboard> clipboard set-global
     <clipboard> selection set-global ;
 
-! world-handle is a <win>
-TUPLE: win hWnd hDC hRC world title ;
+TUPLE: win-base hDC hRC ;
+TUPLE: win < win-base hWnd world title ;
+TUPLE: win-offscreen < win-base hBitmap bits ;
 C: <win> win
+C: <win-offscreen> win-offscreen
 
 SYMBOLS: msg-obj class-name-ptr mouse-captured ;
 
@@ -181,7 +183,7 @@ SYMBOLS: msg-obj class-name-ptr mouse-captured ;
 
 : send-key-gesture ( sym action? quot hWnd -- )
     [ [ key-modifiers ] 3dip call ] dip
-    window-focus propagate-gesture ; inline
+    window propagate-key-gesture ; inline
 
 : send-key-down ( sym action? hWnd -- )
     [ [ <key-down> ] ] dip send-key-gesture ;
@@ -213,7 +215,7 @@ SYMBOLS: msg-obj class-name-ptr mouse-captured ;
         ctrl? alt? xor [
             wParam 1string
             [ f hWnd send-key-down ]
-            [ hWnd window-focus user-input ] bi
+            [ hWnd window user-input ] bi
         ] unless
     ] unless ;
 
@@ -479,8 +481,8 @@ M: windows-ui-backend do-events
     f class-name-ptr set-global
     f msg-obj set-global ;
 
-: setup-pixel-format ( hdc -- )
-    16 make-pfd [ ChoosePixelFormat dup win32-error=0/f ] 2keep
+: setup-pixel-format ( hdc flags -- )
+    32 make-pfd [ ChoosePixelFormat dup win32-error=0/f ] 2keep
     swapd SetPixelFormat win32-error=0/f ;
 
 : get-dc ( hWnd -- hDC ) GetDC dup win32-error=0/f ;
@@ -490,22 +492,73 @@ M: windows-ui-backend do-events
     [ wglMakeCurrent win32-error=0/f ] keep ;
 
 : setup-gl ( hwnd -- hDC hRC )
-    get-dc dup setup-pixel-format dup get-rc ;
+    get-dc dup windowed-pfd-dwFlags setup-pixel-format dup get-rc ;
 
 M: windows-ui-backend (open-window) ( world -- )
-    [ create-window dup setup-gl ] keep
+    [ create-window [ setup-gl ] keep ] keep
     [ f <win> ] keep
     [ swap hWnd>> register-window ] 2keep
     dupd (>>handle)
     hWnd>> show-window ;
 
-M: windows-ui-backend select-gl-context ( handle -- )
-    [ hDC>> ] keep hRC>> wglMakeCurrent win32-error=0/f ;
+M: win-base select-gl-context ( handle -- )
+    [ hDC>> ] keep hRC>> wglMakeCurrent win32-error=0/f
+    GdiFlush drop ;
 
-M: windows-ui-backend flush-gl-context ( handle -- )
+M: win-base flush-gl-context ( handle -- )
     hDC>> SwapBuffers win32-error=0/f ;
 
-! Move window to front
+: (bitmap-info) ( dim -- BITMAPINFO )
+    "BITMAPINFO" <c-object> [
+        BITMAPINFO-bmiHeader {
+            [ nip "BITMAPINFOHEADER" heap-size swap set-BITMAPINFOHEADER-biSize ]
+            [ [ first ] dip set-BITMAPINFOHEADER-biWidth ]
+            [ [ second ] dip set-BITMAPINFOHEADER-biHeight ]
+            [ nip 1 swap set-BITMAPINFOHEADER-biPlanes ]
+            [ nip 32 swap set-BITMAPINFOHEADER-biBitCount ]
+            [ nip BI_RGB swap set-BITMAPINFOHEADER-biCompression ]
+            [ [ first2 * 4 * ] dip set-BITMAPINFOHEADER-biSizeImage ]
+            [ nip 72 swap set-BITMAPINFOHEADER-biXPelsPerMeter ]
+            [ nip 72 swap set-BITMAPINFOHEADER-biYPelsPerMeter ]
+            [ nip 0 swap set-BITMAPINFOHEADER-biClrUsed ]
+            [ nip 0 swap set-BITMAPINFOHEADER-biClrImportant ]
+        } 2cleave
+    ] keep ;
+
+: make-offscreen-dc-and-bitmap ( dim -- hDC hBitmap bits )
+    f CreateCompatibleDC
+    dup rot (bitmap-info) DIB_RGB_COLORS f <void*>
+    [ f 0 CreateDIBSection ] keep *void*
+    [ 2dup SelectObject drop ] dip ;
+
+: setup-offscreen-gl ( dim -- hDC hRC hBitmap bits )
+    make-offscreen-dc-and-bitmap [
+        [ dup offscreen-pfd-dwFlags setup-pixel-format ]
+        [ get-rc ] bi
+    ] 2dip ;
+
+M: windows-ui-backend (open-offscreen-buffer) ( world -- )
+    dup dim>> setup-offscreen-gl <win-offscreen>
+    >>handle drop ;
+M: windows-ui-backend (close-offscreen-buffer) ( handle -- )
+    [ hDC>> DeleteDC drop ]
+    [ hBitmap>> DeleteObject drop ] bi ;
+
+! Windows 32-bit bitmaps don't actually use the alpha byte of
+! each pixel; it's left as zero
+
+: (make-opaque) ( byte-array -- byte-array' )
+    [ length 4 / ]
+    [ '[ 255 swap 4 * 3 + _ set-nth ] each ]
+    [ ] tri ;
+
+: (opaque-pixels) ( world -- pixels )
+    [ handle>> bits>> ] [ dim>> first2 * 4 * ] bi
+    memory>byte-array (make-opaque) ;
+
+M: windows-ui-backend offscreen-pixels ( world -- alien w h )
+    [ (opaque-pixels) ] [ dim>> first2 ] bi ;
+
 M: windows-ui-backend raise-window* ( world -- )
     handle>> [
         hWnd>> SetFocus drop
index a532a13b697055ca1ab31719a24612c1ff99f82f..9be3c2fd109416c92916af7c935689ffe6c8e55e 100755 (executable)
@@ -2,9 +2,9 @@
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors alien alien.c-types arrays ui ui.gadgets
 ui.gestures ui.backend ui.clipboards ui.gadgets.worlds ui.render
-assocs kernel math namespaces opengl sequences strings x11.xlib
-x11.events x11.xim x11.glx x11.clipboard x11.constants
-x11.windows io.encodings.string io.encodings.ascii
+ui.event-loop assocs kernel math namespaces opengl sequences
+strings x11.xlib x11.events x11.xim x11.glx x11.clipboard
+x11.constants x11.windows io.encodings.string io.encodings.ascii
 io.encodings.utf8 combinators command-line qualified
 math.vectors classes.tuple opengl.gl threads math.geometry.rect
 environment ascii ;
@@ -14,9 +14,12 @@ SINGLETON: x11-ui-backend
 
 : XA_NET_WM_NAME ( -- atom ) "_NET_WM_NAME" x-atom ;
 
-TUPLE: x11-handle window glx xic ;
+TUPLE: x11-handle-base glx ;
+TUPLE: x11-handle < x11-handle-base xic window ;
+TUPLE: x11-pixmap-handle < x11-handle-base pixmap glx-pixmap ;
 
 C: <x11-handle> x11-handle
+C: <x11-pixmap-handle> x11-pixmap-handle
 
 M: world expose-event nip relayout ;
 
@@ -83,8 +86,7 @@ M: world configure-event
 
 M: world key-down-event
     [ key-down-event>gesture ] keep
-    world-focus
-    [ propagate-gesture drop ]
+    [ propagate-key-gesture drop ]
     [ 2over valid-input? [ nip user-input ] [ 3drop ] if ]
     3bi ;
 
@@ -92,7 +94,7 @@ M: world key-down-event
     dup event-modifiers swap 0 XLookupKeysym key-code <key-up> ;
 
 M: world key-up-event
-    [ key-up-event>gesture ] dip world-focus propagate-gesture ;
+    [ key-up-event>gesture ] dip propagate-key-gesture ;
 
 : mouse-event>gesture ( event -- modifiers button loc )
     [ event-modifiers ]
@@ -138,7 +140,7 @@ M: world focus-out-event
 
 M: world selection-notify-event
     [ handle>> window>> selection-from-event ] keep
-    world-focus user-input ;
+    user-input ;
 
 : supported-type? ( atom -- ? )
     { "UTF8_STRING" "STRING" "TEXT" }
@@ -185,7 +187,7 @@ M: world client-event
 
 : gadget-window ( world -- )
     dup window-loc>> over rect-dim glx-window
-    over "Factor" create-xic <x11-handle>
+    over "Factor" create-xic rot <x11-handle>
     2dup window>> register-window
     >>handle drop ;
 
@@ -248,14 +250,33 @@ M: x11-ui-backend raise-window* ( world -- )
         dpy get swap window>> XRaiseWindow drop
     ] when* ;
 
-M: x11-ui-backend select-gl-context ( handle -- )
+M: x11-handle select-gl-context ( handle -- )
     dpy get swap
-    dup window>> swap glx>> glXMakeCurrent
+    [ window>> ] [ glx>> ] bi glXMakeCurrent
     [ "Failed to set current GLX context" throw ] unless ;
 
-M: x11-ui-backend flush-gl-context ( handle -- )
+M: x11-handle flush-gl-context ( handle -- )
     dpy get swap window>> glXSwapBuffers ;
 
+M: x11-pixmap-handle select-gl-context ( handle -- )
+    dpy get swap
+    [ glx-pixmap>> ] [ glx>> ] bi glXMakeCurrent
+    [ "Failed to set current GLX context" throw ] unless ;
+
+M: x11-pixmap-handle flush-gl-context ( handle -- )
+    drop ;
+
+M: x11-ui-backend (open-offscreen-buffer) ( world -- )
+    dup dim>> glx-pixmap <x11-pixmap-handle> >>handle drop ;
+M: x11-ui-backend (close-offscreen-buffer) ( handle -- )
+    dpy get swap
+    [ glx-pixmap>> glXDestroyGLXPixmap ]
+    [ pixmap>> XFreePixmap drop ]
+    [ glx>> glXDestroyContext ] 2tri ;
+
+M: x11-ui-backend offscreen-pixels ( world -- alien w h )
+    [ [ dim>> ] [ handle>> pixmap>> ] bi pixmap-bits ] [ dim>> first2 ] bi ;
+
 M: x11-ui-backend ui ( -- )
     [
         f [
index 175425f948f7298c34eec524a4ad7fa603300bd4..7d5f9eb330468ee079f6f8bd2da03921297643b6 100644 (file)
@@ -74,7 +74,7 @@ FUNCTION: int setpriority ( int which, int who, int prio ) ;
     HEX: 7f bitand ; inline
 
 : WIFEXITED ( status -- ? )
-    WTERMSIG zero? ; inline
+    WTERMSIG 0 = ; inline
 
 : WEXITSTATUS ( status -- value )
     HEX: ff00 bitand -8 shift ; inline
@@ -86,7 +86,7 @@ FUNCTION: int setpriority ( int which, int who, int prio ) ;
     HEX: 80 ; inline
 
 : WCOREDUMP ( status -- ? )
-    WCOREFLAG bitand zero? not ; inline
+    WCOREFLAG bitand 0 = not ; inline
 
 : WIFSTOPPED ( status -- ? )
     HEX: ff bitand HEX: 7f = ; inline
old mode 100644 (file)
new mode 100755 (executable)
index b9ba518..32e4f3c
@@ -26,6 +26,14 @@ IN: windows.gdi32
 : DC_BRUSH            18 ; inline
 : DC_PEN              19 ; inline
 
+: BI_RGB        0 ; inline
+: BI_RLE8       1 ; inline
+: BI_RLE4       2 ; inline
+: BI_BITFIELDS  3 ; inline
+
+: DIB_RGB_COLORS 0 ; inline
+: DIB_PAL_COLORS 1 ; inline
+
 LIBRARY: gdi32
 
 ! FUNCTION: AbortPath
@@ -75,13 +83,13 @@ FUNCTION: int ChoosePixelFormat ( HDC hDC, PFD* ppfd ) ;
 ! FUNCTION: CreateColorSpaceA
 ! FUNCTION: CreateColorSpaceW
 ! FUNCTION: CreateCompatibleBitmap
-! FUNCTION: CreateCompatibleDC
+FUNCTION: HDC CreateCompatibleDC ( HDC hdc ) ;
 ! FUNCTION: CreateDCA
 ! FUNCTION: CreateDCW
 ! FUNCTION: CreateDIBitmap
 ! FUNCTION: CreateDIBPatternBrush
 ! FUNCTION: CreateDIBPatternBrushPt
-! FUNCTION: CreateDIBSection
+FUNCTION: HBITMAP CreateDIBSection ( HDC hdc, BITMAPINFO* pbmi, UINT iUsage, void** ppvBits, HANDLE hSection, DWORD dwOffset ) ;
 ! FUNCTION: CreateDiscardableBitmap
 ! FUNCTION: CreateEllipticRgn
 ! FUNCTION: CreateEllipticRgnIndirect
@@ -169,7 +177,7 @@ FUNCTION: HRGN CreateRectRgn ( int x, int y, int w, int h ) ;
 ! FUNCTION: DdEntry8
 ! FUNCTION: DdEntry9
 ! FUNCTION: DeleteColorSpace
-! FUNCTION: DeleteDC
+FUNCTION: BOOL DeleteDC ( HDC hdc ) ;
 ! FUNCTION: DeleteEnhMetaFile
 ! FUNCTION: DeleteMetaFile
 FUNCTION: BOOL DeleteObject ( HGDIOBJ hObject ) ;
@@ -313,7 +321,7 @@ FUNCTION: BOOL DeleteObject ( HGDIOBJ hObject ) ;
 ! FUNCTION: GdiEntry8
 ! FUNCTION: GdiEntry9
 ! FUNCTION: GdiFixUpHandle
-! FUNCTION: GdiFlush
+FUNCTION: BOOL GdiFlush ( ) ;
 ! FUNCTION: GdiFullscreenControl
 ! FUNCTION: GdiGetBatchLimit
 ! FUNCTION: GdiGetCharDimensions
@@ -552,7 +560,7 @@ FUNCTION: HGDIOBJ GetStockObject ( int fnObject ) ;
 ! FUNCTION: SelectClipPath
 FUNCTION: int SelectClipRgn ( HDC hDC, HRGN hrgn ) ;
 ! FUNCTION: SelectFontLocal
-! FUNCTION: SelectObject
+FUNCTION: HGDIOBJ SelectObject ( HDC hdc, HGDIOBJ hgdiobj ) ;
 ! FUNCTION: SelectPalette
 ! FUNCTION: SetAbortProc
 ! FUNCTION: SetArcDirection
old mode 100644 (file)
new mode 100755 (executable)
index df09d93..63384e8
@@ -71,15 +71,17 @@ IN: windows.opengl32
 : WGL_SWAP_UNDERLAY14     HEX: 20000000 ; inline
 : WGL_SWAP_UNDERLAY15     HEX: 40000000 ; inline
 
-: pfd-dwFlags ( -- n )
+: windowed-pfd-dwFlags ( -- n )
     { PFD_DRAW_TO_WINDOW PFD_SUPPORT_OPENGL PFD_DOUBLEBUFFER } flags ;
+: offscreen-pfd-dwFlags ( -- n )
+    { PFD_DRAW_TO_BITMAP PFD_SUPPORT_OPENGL } flags ;
 
 ! TODO: compare to http://www.nullterminator.net/opengl32.html
-: make-pfd ( bits -- pfd )
+: make-pfd ( flags bits -- pfd )
     "PIXELFORMATDESCRIPTOR" <c-object>
     "PIXELFORMATDESCRIPTOR" heap-size over set-PIXELFORMATDESCRIPTOR-nSize
     1 over set-PIXELFORMATDESCRIPTOR-nVersion
-    pfd-dwFlags over set-PIXELFORMATDESCRIPTOR-dwFlags
+    rot over set-PIXELFORMATDESCRIPTOR-dwFlags
     PFD_TYPE_RGBA over set-PIXELFORMATDESCRIPTOR-iPixelType
     [ set-PIXELFORMATDESCRIPTOR-cColorBits ] keep
     16 over set-PIXELFORMATDESCRIPTOR-cDepthBits
old mode 100644 (file)
new mode 100755 (executable)
index 63ee662..8cc18d4
@@ -253,6 +253,29 @@ C-STRUCT: RECT
     ! { "BYTE[32]" "rgbReserved" }
 ! ;
 
+C-STRUCT: BITMAPINFOHEADER
+    { "DWORD"  "biSize" }
+    { "LONG"   "biWidth" }
+    { "LONG"   "biHeight" }
+    { "WORD"   "biPlanes" }
+    { "WORD"   "biBitCount" }
+    { "DWORD"  "biCompression" }
+    { "DWORD"  "biSizeImage" }
+    { "LONG"   "biXPelsPerMeter" }
+    { "LONG"   "biYPelsPerMeter" }
+    { "DWORD"  "biClrUsed" }
+    { "DWORD"  "biClrImportant" } ;
+
+C-STRUCT: RGBQUAD
+    { "BYTE" "rgbBlue" }
+    { "BYTE" "rgbGreen" }
+    { "BYTE" "rgbRed" }
+    { "BYTE" "rgbReserved" } ;
+
+C-STRUCT: BITMAPINFO
+    { "BITMAPINFOHEADER" "bmiHeader" }
+    { "RGBQUAD[1]" "bmiColors" } ;
+
 TYPEDEF: void* LPPAINTSTRUCT
 TYPEDEF: void* PAINTSTRUCT
 
index 1fab2832421094dc6f0951eb13be9f12aa1a567b..e0b786ce7d586792a74d53f890c160aa8e484cb0 100644 (file)
@@ -84,13 +84,13 @@ FUNCTION: void* glXGetProcAddress ( char* procname ) ;
 FUNCTION: void* glXGetProcAddressARB ( char* procname ) ;
 
 ! GLX Events
-! (also skipped for now. only has GLXPbufferClobberEvent, the rest is handled by xlib methinks
+! (also skipped for now. only has GLXPbufferClobberEvent, the rest is handled by xlib methinks)
 
-: choose-visual ( -- XVisualInfo* )
-    dpy get scr get
+: choose-visual ( flags -- XVisualInfo* )
+    [ dpy get scr get ] dip
     [
+        %
         GLX_RGBA ,
-        GLX_DOUBLEBUFFER ,
         GLX_DEPTH_SIZE , 16 ,
         0 ,
     ] int-array{ } make underlying>>
@@ -98,8 +98,8 @@ FUNCTION: void* glXGetProcAddressARB ( char* procname ) ;
     [ "Could not get a double-buffered GLX RGBA visual" throw ] unless* ;
 
 : create-glx ( XVisualInfo* -- GLXContext )
-    >r dpy get r> f 1 glXCreateContext
+    [ dpy get ] dip f 1 glXCreateContext
     [ "Failed to create GLX context" throw ] unless* ;
 
 : destroy-glx ( GLXContext -- )
-    dpy get swap glXDestroyContext ;
\ No newline at end of file
+    dpy get swap glXDestroyContext ;
index aed45655f6c08bd86e24ce7d73ddc2e6c19b4c6f..3c41a7858411f7118c782567501cec67fca1a3c5 100644 (file)
@@ -1,7 +1,8 @@
 ! Copyright (C) 2005, 2006 Eduardo Cavazos and Slava Pestov
 ! See http://factorcode.org/license.txt for BSD license.
 USING: alien alien.c-types hashtables kernel math math.vectors
-math.bitwise namespaces sequences x11.xlib x11.constants x11.glx ;
+math.bitwise namespaces sequences x11.xlib x11.constants x11.glx
+arrays fry ;
 IN: x11.windows
 
 : create-window-mask ( -- n )
@@ -50,11 +51,30 @@ IN: x11.windows
     dup r> auto-position ;
 
 : glx-window ( loc dim -- window glx )
-    choose-visual
+    GLX_DOUBLEBUFFER 1array choose-visual
     [ create-window ] keep
     [ create-glx ] keep
     XFree ;
 
+: create-pixmap ( dim visual -- pixmap )
+    [ [ { 0 0 } swap ] dip create-window ] [
+        drop [ dpy get ] 2dip first2 24 XCreatePixmap
+        [ "Failed to create offscreen pixmap" throw ] unless*
+    ] 2bi ;
+
+: (create-glx-pixmap) ( pixmap visual -- pixmap glx-pixmap )
+    [ drop ] [
+        [ dpy get ] 2dip swap glXCreateGLXPixmap
+        [ "Failed to create offscreen GLXPixmap" throw ] unless*
+    ] 2bi ;
+
+: create-glx-pixmap ( dim visual -- pixmap glx-pixmap )
+    [ create-pixmap ] [ (create-glx-pixmap) ] bi ;
+
+: glx-pixmap ( dim -- glx pixmap glx-pixmap )
+    { } choose-visual
+    [ nip create-glx ] [ create-glx-pixmap ] [ nip XFree ] 2tri ;
+
 : destroy-window ( win -- )
     dpy get swap XDestroyWindow drop ;
 
@@ -65,3 +85,7 @@ IN: x11.windows
 : map-window ( win -- ) dpy get swap XMapWindow drop ;
 
 : unmap-window ( win -- ) dpy get swap XUnmapWindow drop ;
+
+: pixmap-bits ( dim pixmap -- alien )
+    swap first2 '[ dpy get _ 0 0 _ _ AllPlanes ZPixmap XGetImage ] call
+    [ XImage-pixels ] [ XDestroyImage drop ] bi ;
index 58b4995c40fd528b7ad3852812ba6269aa17a4b0..1eee8307b1b7e70da8d03f81e3c02fec723bfc32 100644 (file)
@@ -277,6 +277,17 @@ FUNCTION: Window XGetSelectionOwner ( Display* display, Atom selection ) ;
 
 FUNCTION: int XConvertSelection ( Display* display, Atom selection, Atom target, Atom property, Window requestor, Time time ) ;
 
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+! 5 - Pixmap and Cursor Functions
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+! 5.1 - Creating and Freeing Pixmaps
+
+FUNCTION: Pixmap XCreatePixmap ( Display* display, Drawable d, uint width, uint height, uint depth ) ;
+FUNCTION: int XFreePixmap ( Display* display, Pixmap pixmap ) ;
+
+
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 ! 6 - Color Management Functions
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
@@ -434,6 +445,49 @@ FUNCTION: Status XDrawString (
         char* string,
         int length ) ;
 
+! 8.7 - Transferring Images between Client and Server
+
+: XYBitmap 0 ; inline
+: XYPixmap 1 ; inline
+: ZPixmap  2 ; inline
+: AllPlanes -1 ; inline
+
+C-STRUCT: XImage-funcs
+    { "void*" "create_image" }
+    { "void*" "destroy_image" }
+    { "void*" "get_pixel" }
+    { "void*" "put_pixel" }
+    { "void*" "sub_image" }
+    { "void*" "add_pixel" } ;
+
+C-STRUCT: XImage
+    { "int"          "width" }
+    { "int"          "height" }
+    { "int"          "xoffset" }
+    { "int"          "format" }
+    { "char*"        "data" }
+    { "int"          "byte_order" }
+    { "int"          "bitmap_unit" }
+    { "int"          "bitmap_bit_order" }
+    { "int"          "bitmap_pad" }
+    { "int"          "depth" }
+    { "int"          "bytes_per_line" }
+    { "int"          "bits_per_pixel" }
+    { "ulong"        "red_mask" }
+    { "ulong"        "green_mask" }
+    { "ulong"        "blue_mask" }
+    { "XPointer"     "obdata" }
+    { "XImage-funcs" "f" } ;
+
+FUNCTION: XImage* XGetImage ( Display* display, Drawable d, int x, int y, uint width, uint height, ulong plane_mask, int format ) ;
+FUNCTION: int XDestroyImage ( XImage *ximage ) ;
+
+: XImage-size ( ximage -- size )
+    [ XImage-height ] [ XImage-bytes_per_line ] bi * ;
+
+: XImage-pixels ( ximage -- byte-array )
+    [ XImage-data ] [ XImage-size ] bi memory>byte-array ;
+
 !
 ! 9 - Window and Session Manager Functions
 !
index 6a5dfe30dff2db2aa510a2cc260a8f08845fe930..c97e36e889cc323ed885ea2126a7e60518f23d5e 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2004, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: accessors assocs kernel math namespaces sequences system
-kernel.private byte-arrays arrays ;
+kernel.private byte-arrays arrays init ;
 IN: alien
 
 ! Some predicate classes used by the compiler for optimization
@@ -72,3 +72,9 @@ ERROR: alien-invoke-error library symbol ;
 
 : alien-invoke ( ... return library function parameters -- ... )
     2over alien-invoke-error ;
+
+! Callbacks are registered in a global hashtable. If you clear
+! this hashtable, they will all be blown away by code GC, beware.
+SYMBOL: callbacks
+
+[ H{ } clone callbacks set-global ] "alien" add-init-hook
index 07b82f6111268d41ea7bd0e137ad01069d2d7b07..edaea108a18d23d10d1a36d43741ff9dd04e68dc 100644 (file)
@@ -1,7 +1,10 @@
 IN: byte-arrays.tests\r
-USING: tools.test byte-arrays ;\r
+USING: tools.test byte-arrays sequences kernel ;\r
 \r
-[ B{ 1 2 3 0 0 0 } ] [ 6 B{ 1 2 3 } resize-byte-array ] unit-test\r
+[ 6 B{ 1 2 3 } ] [\r
+    6 B{ 1 2 3 } resize-byte-array\r
+    [ length ] [ 3 head ] bi\r
+] unit-test\r
 \r
 [ B{ 1 2 } ] [ 2 B{ 1 2 3 4 5 6 7 8 9 } resize-byte-array ] unit-test\r
 \r
index 5456f2251ca61cfe782f10393dd2236fe9cb2fa5..e2c6c3d4647709e3a96eb791ae2f304c214af8e4 100644 (file)
@@ -1,7 +1,7 @@
 ! Copyright (C) 2007, 2008 Slava Pestov.
 ! See http://factorcode.org/license.txt for BSD license.
 USING: init kernel system namespaces io io.encodings
-io.encodings.utf8 init assocs splitting ;
+io.encodings.utf8 init assocs splitting alien ;
 IN: io.backend
 
 SYMBOL: io-backend
@@ -32,5 +32,7 @@ M: object normalize-directory normalize-path ;
     io-backend set-global init-io init-stdio
     "io.files" init-hooks get at call ;
 
+! Note that we have 'alien' in our using list so that the alien
+! init hook runs before this one.
 [ init-io embedded? [ init-stdio ] unless ]
 "io.backend" add-init-hook
index 6794825897e540e9b8547d92ebfe55c17f4b961b..11a6a9d8a991a1247219bf8ebb20b64a9739c9c0 100644 (file)
@@ -6,9 +6,10 @@ IN: memory.tests
 ! LOL
 [ ] [
     vm
+    "-i=" image append
     "-generations=2"
     "-e=USING: memory io prettyprint system ; input-stream gc . 0 exit"
-    3array try-process
+    4array try-process
 ] unit-test
 
 [ [ ] instances ] must-infer
index 8c9eff94f514d2dfc1f52d3c915f478c0b74bd15..7bb509cb67072e8aabcdef8ea02cbe5537c0eac9 100644 (file)
@@ -343,7 +343,7 @@ PRIVATE>
     [ (each) ] dip collect ; inline
 
 : 2nth-unsafe ( n seq1 seq2 -- elt1 elt2 )
-    [ over ] dip nth-unsafe [ nth-unsafe ] dip ; inline
+    [ over ] dip [ nth-unsafe ] 2bi@ ; inline
 
 : (2each) ( seq1 seq2 quot -- n quot' )
     [ [ min-length ] 2keep ] dip
@@ -538,12 +538,12 @@ M: sequence <=>
 
 : sequence-hashcode-step ( oldhash newpart -- newhash )
     >fixnum swap [
-        dup -2 fixnum-shift-fast swap 5 fixnum-shift-fast
+        [ -2 fixnum-shift-fast ] [ 5 fixnum-shift-fast ] bi
         fixnum+fast fixnum+fast
     ] keep fixnum-bitxor ; inline
 
 : sequence-hashcode ( n seq -- x )
-    0 -rot [ hashcode* sequence-hashcode-step ] with each ; inline
+    [ 0 ] 2dip [ hashcode* sequence-hashcode-step ] with each ; inline
 
 M: reversed equal? over reversed? [ sequence= ] [ 2drop f ] if ;
 
@@ -845,9 +845,10 @@ PRIVATE>
 USE: arrays
 
 : array-length ( array -- len )
-    { array } declare length>> ;
+    { array } declare length>> ; inline
 
 : array-flip ( matrix -- newmatrix )
+    { array } declare
     [ dup first array-length [ array-length min ] reduce ] keep
     [ [ array-nth ] with { } map-as ] curry { } map-as ;
 
index a1e892229ad8a0f84e0b4a82fcb58bf4cf3c2738..9afd2118766d9bebf382683e8797e4d07feb945a 100755 (executable)
@@ -6,8 +6,10 @@ continuations debugger math ;
 IN: benchmark
 
 : run-benchmark ( vocab -- result )
-    [ [ require ] [ [ run ] benchmark ] bi ] curry
-    [ error. f ] recover ;
+    [ "=== " write vocab-name print flush ] [
+        [ [ require ] [ [ run ] benchmark ] bi ] curry
+        [ error. f ] recover
+    ] bi ;
 
 : run-benchmarks ( -- assoc )
     "benchmark" all-child-vocabs-seq
index c98c5a6c574f22ebd1a628b7a035af1c2ce71e3e..72d9e50a9d8d6bbb816fbc5613b67823e60dbc9f 100644 (file)
@@ -2,6 +2,7 @@
 USING: accessors arrays fry kernel math math.vectors sequences
        math.intervals
        multi-methods
+       combinators.short-circuit
        combinators.cleave.enhanced
        multi-method-syntax ;
 
@@ -218,3 +219,16 @@ USING: locals combinators ;
   cond
 
   2array ;
+
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+GENERIC: within? ( a b -- ? )
+
+METHOD: within? ( <pos> <rectangle> -- ? )
+  {
+    [ left   to-the-right-of? ]
+    [ right  to-the-left-of?  ]
+    [ bottom above?           ]
+    [ top    below?           ]
+  }
+  2&& ;
index d9db83b5e35df51e365e48683a87e4d33589d020..e2535ade30028148a7c6dab33cb708e91220563a 100644 (file)
@@ -151,7 +151,8 @@ M: source-file fuel-pprint path>> fuel-pprint ;
 : fuel-end-eval ( -- ) [ ] (fuel-end-eval) ; inline
 
 : fuel-get-edit-location ( defspec -- )
-    where [ first2 [ (normalize-path) ] dip 2array fuel-eval-set-result ] when* ;
+    where [ first2 [ (normalize-path) ] dip 2array fuel-eval-set-result ]
+    when* ;
 
 : fuel-run-file ( path -- ) run-file ; inline
 
index 4c35e3d7d0c56b36be47c4cd04caf499bb36a97f..9bb8db0f6d5302f791714577c1d780bc5a996971 100755 (executable)
@@ -4,24 +4,35 @@
 USING: alien arrays byte-arrays combinators summary io.backend
 graphics.viewer io io.binary io.files kernel libc math
 math.functions math.bitwise namespaces opengl opengl.gl
-prettyprint sequences strings ui ui.gadgets.panes
-io.encodings.binary accessors grouping ;
+prettyprint sequences strings ui ui.gadgets.panes fry
+io.encodings.binary accessors grouping macros alien.c-types ;
 IN: graphics.bitmap
 
-! Currently can only handle 24bit bitmaps.
+! Currently can only handle 24/32bit bitmaps.
 ! Handles row-reversed bitmaps (their height is negative)
 
 TUPLE: bitmap magic size reserved offset header-length width
     height planes bit-count compression size-image
     x-pels y-pels color-used color-important rgb-quads color-index array ;
 
+: (array-copy) ( bitmap array -- bitmap array' )
+    over size-image>> abs memory>byte-array ;
+
+MACRO: (nbits>bitmap) ( bits -- )
+    [ -3 shift ] keep '[
+        bitmap new
+            2over * _ * >>size-image
+            swap >>height
+            swap >>width
+            swap (array-copy) [ >>array ] [ >>color-index ] bi
+            _ >>bit-count
+    ] ;
+
 : bgr>bitmap ( array height width -- bitmap )
-    bitmap new
-        2over * 3 * >>size-image
-        swap >>height
-        swap >>width
-        swap [ >>array ] [ >>color-index ] bi
-        24 >>bit-count ;
+    24 (nbits>bitmap) ;
+
+: bgra>bitmap ( array height width -- bitmap )
+    32 (nbits>bitmap) ;
 
 : 8bit>array ( bitmap -- array )
     [ rgb-quads>> 4 <sliced-groups> [ 3 head-slice ] map ]
@@ -124,7 +135,7 @@ M: bitmap draw-image ( bitmap -- )
     [
         [ height>> abs ] keep
         bit-count>> {
-            ! { 32 [ GL_BGRA GL_UNSIGNED_INT_8_8_8_8 ] } ! broken
+            { 32 [ GL_BGRA GL_UNSIGNED_BYTE ] }
             { 24 [ GL_BGR GL_UNSIGNED_BYTE ] }
             { 8 [ GL_BGR GL_UNSIGNED_BYTE ] }
             { 4 [ GL_BGR GL_UNSIGNED_BYTE ] }
index 680723def903f61c37779395caa1deb2c616a42c..2317d21ed58ea97df481132c608e1c4654b33580 100755 (executable)
@@ -1,5 +1,6 @@
-USING: alien.syntax alien.c-types core-foundation system
-combinators kernel sequences debugger io accessors ;
+USING: alien.syntax alien.c-types core-foundation
+core-foundation.bundles system combinators kernel sequences
+debugger io accessors ;
 IN: iokit
 
 <<
index 0865b0ada2feb696db288220b96a755a365a1e97..05edb205d2e04c495b2998e2a3a1863e5487abfd 100755 (executable)
@@ -139,7 +139,7 @@ TUPLE: key-caps-gadget < gadget keys alarm ;
 : make-key-gadget ( scancode dim array -- )
     [ 
         swap [ 
-            " " [ ] <bevel-button>
+            " " [ drop ] <bevel-button>
             swap [ first >>loc ] [ second >>dim ] bi
         ] [ execute ] bi*
     ] dip set-nth ;
diff --git a/extra/literals/literals-tests.factor b/extra/literals/literals-tests.factor
new file mode 100644 (file)
index 0000000..b88a286
--- /dev/null
@@ -0,0 +1,12 @@
+USING: kernel literals tools.test ;
+IN: literals.tests
+
+<<
+: five 5 ;
+: seven-eleven 7 11 ;
+: six-six-six 6 6 6 ;
+>>
+
+[ { 5 } ] [ { $ five } ] unit-test
+[ { 7 11 } ] [ { $ seven-eleven } ] unit-test
+[ { 6 6 6 } ] [ { $ six-six-six } ] unit-test
diff --git a/extra/literals/literals.factor b/extra/literals/literals.factor
new file mode 100644 (file)
index 0000000..d46f492
--- /dev/null
@@ -0,0 +1,4 @@
+USING: continuations kernel parser words ;
+IN: literals
+
+: $ scan-word [ execute ] curry with-datastack ; parsing
index befb64a7a795ca4dfd3257026a09d15208305e9e..3f7626074a4cd87c935d1a4f6adc9ceffc3d7348 100644 (file)
@@ -15,6 +15,13 @@ USING: kernel accessors locals math math.intervals math.order
 
 IN: pong
 
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+! 
+! Inspired by this Ruby/Shoes version by why: http://gist.github.com/26431
+!
+! Which was based on this Nodebox version: http://billmill.org/pong.html
+! by Bill Mill.
+! 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
 : clamp-to-interval ( x interval -- x )
@@ -95,28 +102,37 @@ METHOD: draw ( <ball>   -- ) [ pos>>       ] [ diameter>> 2 / ] bi circle    ;
 USE: syntax ! Switch back to core 'TUPLE:' instead of the one provided
             ! by multi-methods
 
-TUPLE: <pong> < gadget draw closed ;
+TUPLE: <pong> < gadget paused field ball player computer ;
 
-M: <pong> pref-dim*    ( <pong> -- dim ) drop { 400 400 } ;
-M: <pong> draw-gadget* ( <pong> --     ) draw>> call      ;
-M: <pong> ungraft*     ( <pong> --     ) t >>closed drop  ;
+: pong ( -- gadget )
+  <pong> new-gadget
+  T{ <play-field> { pos {   0   0 } } { dim { 400 400 } } } clone >>field
+  T{ <ball>       { pos {  50  50 } } { vel {   3   4 } } } clone >>ball
+  T{ <paddle>     { pos { 200 396 } } { dim {  75   4 } } } clone >>player
+  T{ <computer>   { pos { 200   0 } } { dim {  75   4 } } } clone >>computer ;
 
+M: <pong> pref-dim* ( <pong> -- dim ) drop { 400 400 } ;
+M: <pong> ungraft*  ( <pong> --     ) t >>paused drop  ;
+    
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-: make-draw-closure ( -- closure )
+M:: <pong> draw-gadget* ( PONG -- )
 
-  ! Establish some bindings
+  PONG computer>> draw
+  PONG player>>   draw
+  PONG ball>>     draw ;
 
-  [let | PLAY-FIELD [ T{ <play-field> { pos {  0  0 } } { dim { 400 400 } } } ]
-         BALL       [ T{ <ball>       { pos { 50 50 } } { vel {   3   4 } } } ]
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-         PLAYER   [ T{ <paddle>   { pos { 200 396 } } { dim { 75 4 } } } ]
-         COMPUTER [ T{ <computer> { pos { 200   0 } } { dim { 75 4 } } } ] |
+:: iterate-system ( GADGET -- )
 
-    ! Define some internal words in terms of those bindings ...
+  [let | FIELD    [ GADGET field>>    ]
+         BALL     [ GADGET ball>>     ]
+         PLAYER   [ GADGET player>>   ]
+         COMPUTER [ GADGET computer>> ] |
 
     [wlet | align-player-with-mouse [ ( -- )
-              PLAYER PLAY-FIELD align-paddle-with-mouse ]
+              PLAYER FIELD align-paddle-with-mouse ]
 
             move-ball [ ( -- ) BALL 1 move-for ]
 
@@ -127,69 +143,52 @@ M: <pong> ungraft*     ( <pong> --     ) t >>closed drop  ;
               BALL COMPUTER { [ below? ] [ in-between-horizontally? ] } && ]
 
             bounce-off-wall? [ ( -- ? )
-              BALL PLAY-FIELD in-between-horizontally? not ] |
-
-      ! Note, we're returning a quotation.
-      ! The quotation closes over the bindings established by the 'let'.
-      ! Thus the name of the word 'make-draw-closure'.
-      ! This closure is intended to be placed in the 'draw' slot of a
-      ! <pong> gadget.
-      
+              BALL FIELD in-between-horizontally? not ]
+
+            stop-game [ ( -- ) t GADGET (>>paused) ] |
+
+      BALL FIELD in-bounds?
       [
 
-        BALL PLAY-FIELD in-bounds?
-          [
-            align-player-with-mouse
-              
-            move-ball
-  
-            ! computer reaction
-  
-            BALL COMPUTER to-the-left-of?  [ COMPUTER computer-move-left  ] when
-            BALL COMPUTER to-the-right-of? [ COMPUTER computer-move-right ] when
-
-            ! check if ball bounced off something
-              
-            player-blocked-ball?   [ BALL PLAYER   bounce-off-paddle  ] when
-            computer-blocked-ball? [ BALL COMPUTER bounce-off-paddle  ] when
-            bounce-off-wall?       [ BALL reverse-horizontal-velocity ] when
+        align-player-with-mouse
 
-            ! draw the objects
-              
-            COMPUTER draw
-            PLAYER   draw
-            BALL     draw
-  
-          ]
-        when
-
-      ] ] ] ( -- closure ) ; ! The trailing stack effect here is a workaround.
-                             ! The stack effects in the wlet expression throw
-                             ! off the effect for the whole word, so we reset
-                             ! it to the correct one here.
+        move-ball
 
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+        ! computer reaction
 
-:: pong-loop-step ( PONG -- ? )
-  PONG closed>>
-    [ f ]
-    [ PONG relayout-1 25 milliseconds sleep t ]
-  if ;
+        BALL COMPUTER to-the-left-of?  [ COMPUTER computer-move-left  ] when
+        BALL COMPUTER to-the-right-of? [ COMPUTER computer-move-right ] when
 
-:: start-pong-thread ( PONG -- ) [ [ PONG pong-loop-step ] loop ] in-thread ;
+        ! check if ball bounced off something
+              
+        player-blocked-ball?   [ BALL PLAYER   bounce-off-paddle  ] when
+        computer-blocked-ball? [ BALL COMPUTER bounce-off-paddle  ] when
+        bounce-off-wall?       [ BALL reverse-horizontal-velocity ] when
+      ]
+      [ stop-game ]
+      if
 
-! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+  ] ] ( gadget -- ) ;
 
-: play-pong ( -- )
+! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-  <pong> new-gadget
-    make-draw-closure >>draw
-  dup "PONG" open-window
-    
-  start-pong-thread ;
+:: start-pong-thread ( GADGET -- )
+  f GADGET (>>paused)
+  [
+    [
+      GADGET paused>>
+      [ f ]
+      [ GADGET iterate-system GADGET relayout-1 25 milliseconds sleep t ]
+      if
+    ]
+    loop
+  ]
+  in-thread ;
 
 ! !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
 
-: play-pong-main ( -- ) [ play-pong ] with-ui ;
+: pong-window ( -- ) pong [ "PONG" open-window ] [ start-pong-thread ] bi ;
+
+: pong-main ( -- ) [ pong-window ] with-ui ;
 
-MAIN: play-pong-main
\ No newline at end of file
+MAIN: pong-window
\ No newline at end of file
diff --git a/extra/ui/offscreen/authors.txt b/extra/ui/offscreen/authors.txt
new file mode 100644 (file)
index 0000000..f13c9c1
--- /dev/null
@@ -0,0 +1 @@
+Joe Groff
diff --git a/extra/ui/offscreen/offscreen-docs.factor b/extra/ui/offscreen/offscreen-docs.factor
new file mode 100644 (file)
index 0000000..5d80098
--- /dev/null
@@ -0,0 +1,63 @@
+! Copyright (C) 2008 Joe Groff.
+! See http://factorcode.org/license.txt for BSD license.
+USING: help.markup help.syntax kernel quotations ui.gadgets
+graphics.bitmap strings ui.gadgets.worlds ;
+IN: ui.offscreen
+
+HELP: <offscreen-world>
+{ $values
+     { "gadget" gadget } { "title" string } { "status" "a boolean" }
+     { "world" offscreen-world }
+}
+{ $description "Constructs an " { $link offscreen-world } " gadget with " { $snippet "gadget" } " as its only child. Generally you should use " { $link open-offscreen } " or " { $link do-offscreen } " instead of calling this word directly." } ;
+
+HELP: close-offscreen
+{ $values
+     { "world" offscreen-world }
+}
+{ $description "Releases the resources used by the rendering buffer for " { $snippet "world" } "." } ;
+
+HELP: do-offscreen
+{ $values
+     { "gadget" gadget } { "quot" quotation }
+}
+{ $description "Constructs an " { $link offscreen-world } " around " { $snippet "gadget" } " with " { $link open-offscreen } ", calls " { $snippet "quotation" } " with the world on the top of the stack, and cleans up the world with " { $link close-offscreen } " at the end of " { $snippet "quotation" } "." } ;
+
+HELP: gadget>bitmap
+{ $values
+     { "gadget" gadget }
+     { "bitmap" bitmap }
+}
+{ $description "Renders " { $snippet "gadget" } " to an " { $link offscreen-world } " and creates a " { $link bitmap } " from its contents." } ;
+
+HELP: offscreen-world
+{ $class-description "The class of " { $link world } " objects that render to an offscreen buffer." } ;
+
+HELP: offscreen-world>bitmap
+{ $values
+     { "world" offscreen-world }
+     { "bitmap" bitmap }
+}
+{ $description "Saves a copy of the contents of " { $snippet "world" } " to a " { $link bitmap } " object." } ;
+
+HELP: open-offscreen
+{ $values
+     { "gadget" gadget }
+     { "world" offscreen-world }
+}
+{ $description "Creates and sets up an " { $link offscreen-world } " with " { $snippet "gadget" } " as its only child." } ;
+
+{ offscreen-world open-offscreen close-offscreen do-offscreen } related-words
+
+ARTICLE: "ui.offscreen" "Offscreen UI rendering"
+"The " { $vocab-link "ui.offscreen" } " provides words for rendering gadgets to an offscreen buffer so that bitmaps can be made from their contents."
+{ $subsection offscreen-world }
+"Opening gadgets offscreen:"
+{ $subsection open-offscreen }
+{ $subsection close-offscreen }
+{ $subsection do-offscreen }
+"Creating bitmaps from offscreen buffers:"
+{ $subsection offscreen-world>bitmap }
+{ $subsection gadget>bitmap } ;
+
+ABOUT: "ui.offscreen"
diff --git a/extra/ui/offscreen/offscreen.factor b/extra/ui/offscreen/offscreen.factor
new file mode 100755 (executable)
index 0000000..89c1c7f
--- /dev/null
@@ -0,0 +1,36 @@
+! (c) 2008 Joe Groff, see license for details
+USING: accessors continuations graphics.bitmap kernel math
+sequences ui.gadgets ui.gadgets.worlds ui ui.backend
+destructors ;
+IN: ui.offscreen
+
+TUPLE: offscreen-world < world ;
+
+: <offscreen-world> ( gadget title status -- world )
+    offscreen-world new-world ;
+
+M: offscreen-world graft*
+    (open-offscreen-buffer) ;
+
+M: offscreen-world ungraft*
+    [ (ungraft-world) ]
+    [ handle>> (close-offscreen-buffer) ]
+    [ reset-world ] tri ;
+
+: open-offscreen ( gadget -- world )
+    "" f <offscreen-world>
+    [ open-world-window dup relayout-1 ] keep
+    notify-queued ;
+
+: close-offscreen ( world -- )
+    ungraft notify-queued ;
+
+: offscreen-world>bitmap ( world -- bitmap )
+    offscreen-pixels bgra>bitmap ;
+
+: do-offscreen ( gadget quot: ( offscreen-world -- ) -- )
+    [ open-offscreen ] dip
+    over [ slip ] [ close-offscreen ] [ ] cleanup ; inline
+
+: gadget>bitmap ( gadget -- bitmap )
+    [ offscreen-world>bitmap ] do-offscreen ;
diff --git a/extra/ui/offscreen/summary.txt b/extra/ui/offscreen/summary.txt
new file mode 100644 (file)
index 0000000..51ef124
--- /dev/null
@@ -0,0 +1 @@
+Offscreen world gadgets for rendering UI elements to bitmaps
diff --git a/extra/ui/offscreen/tags.txt b/extra/ui/offscreen/tags.txt
new file mode 100644 (file)
index 0000000..b796ebd
--- /dev/null
@@ -0,0 +1,3 @@
+unportable
+ui
+graphics
index 18f6fa1e94e271c3867ca7fab38183f5b6b8fa58..4dfb16da511679004088dbf36d11e03df06eeecd 100644 (file)
@@ -50,7 +50,7 @@ Quick key reference
 (Chords ending in a single letter <x> accept also C-<x> (e.g. C-cC-z is
 the same as C-cz)).
 
-* In factor files:
+* In factor source files:
 
  - C-cz : switch to listener
  - C-co : cycle between code, tests and docs factor files
@@ -70,6 +70,13 @@ the same as C-cz)).
 
  - g : go to error
  - <digit> : invoke nth restart
+ - w/e/l : invoke :warnings, :errors, :linkage
  - q : bury buffer
 
+* In the Help browser:
+
+ - RET : help for word at point
+ - f/b : next/previous page
+ - SPC/S-SPC : scroll up/down
+ - q: bury buffer
 
index a62d16cb32615d9caf9a46c8ac5e0ba445cd11e3..9ea17903804baec494ac151cebba68c3c6fed0be 100644 (file)
@@ -59,5 +59,7 @@
                                 " ")
                      len))
 
+(defsubst empty-string-p (str) (equal str ""))
+
 (provide 'fuel-base)
 ;;; fuel-base.el ends here
diff --git a/misc/fuel/fuel-connection.el b/misc/fuel/fuel-connection.el
new file mode 100644 (file)
index 0000000..1914245
--- /dev/null
@@ -0,0 +1,186 @@
+;;; fuel-connection.el -- asynchronous comms with the fuel listener
+
+;; Copyright (C) 2008 Jose Antonio Ortega Ruiz
+;; See http://factorcode.org/license.txt for BSD license.
+
+;; Author: Jose Antonio Ortega Ruiz <jao@gnu.org>
+;; Keywords: languages, fuel, factor
+;; Start date: Thu Dec 11, 2008 03:10
+
+;;; Comentary:
+
+;; Handling communications via a comint buffer running a factor
+;; listener.
+
+;;; Code:
+
+\f
+;;; Default connection:
+
+(make-variable-buffer-local
+ (defvar fuel-con--connection nil))
+
+(defun fuel-con--get-connection (buffer/proc)
+  (if (processp buffer/proc)
+      (fuel-con--get-connection (process-buffer buffer/proc))
+    (with-current-buffer buffer/proc
+      (or fuel-con--connection
+          (setq fuel-con--connection
+                (fuel-con--setup-connection buffer/proc))))))
+
+\f
+;;; Request and connection datatypes:
+
+(defun fuel-con--connection-queue-request (c r)
+  (let ((reqs (assoc :requests c)))
+    (setcdr reqs (append (cdr reqs) (list r)))))
+
+(defun fuel-con--make-request (str cont &optional sender-buffer)
+  (list :fuel-connection-request
+        (cons :id (random))
+        (cons :string str)
+        (cons :continuation cont)
+        (cons :buffer (or sender-buffer (current-buffer)))))
+
+(defsubst fuel-con--request-p (req)
+  (and (listp req) (eq (car req) :fuel-connection-request)))
+
+(defsubst fuel-con--request-id (req)
+  (cdr (assoc :id req)))
+
+(defsubst fuel-con--request-string (req)
+  (cdr (assoc :string req)))
+
+(defsubst fuel-con--request-continuation (req)
+  (cdr (assoc :continuation req)))
+
+(defsubst fuel-con--request-buffer (req)
+  (cdr (assoc :buffer req)))
+
+(defsubst fuel-con--request-deactivate (req)
+  (setcdr (assoc :continuation req) nil))
+
+(defsubst fuel-con--request-deactivated-p (req)
+  (null (cdr (assoc :continuation req))))
+
+(defsubst fuel-con--make-connection (buffer)
+  (list :fuel-connection
+        (list :requests)
+        (list :current)
+        (cons :completed (make-hash-table :weakness 'value))
+        (cons :buffer buffer)))
+
+(defsubst fuel-con--connection-p (c)
+  (and (listp c) (eq (car c) :fuel-connection)))
+
+(defsubst fuel-con--connection-requests (c)
+  (cdr (assoc :requests c)))
+
+(defsubst fuel-con--connection-current-request (c)
+  (cdr (assoc :current c)))
+
+(defun fuel-con--connection-clean-current-request (c)
+  (let* ((cell (assoc :current c))
+         (req (cdr cell)))
+    (when req
+      (puthash (fuel-con--request-id req) req (cdr (assoc :completed c)))
+      (setcdr cell nil))))
+
+(defsubst fuel-con--connection-completed-p (c id)
+  (gethash id (cdr (assoc :completed c))))
+
+(defsubst fuel-con--connection-buffer (c)
+  (cdr (assoc :buffer c)))
+
+(defun fuel-con--connection-pop-request (c)
+  (let ((reqs (assoc :requests c))
+        (current (assoc :current c)))
+    (setcdr current (prog1 (cadr reqs) (setcdr reqs (cddr reqs))))
+    (if (and current (fuel-con--request-deactivated-p current))
+        (fuel-con--connection-pop-request c)
+      current)))
+
+\f
+;;; Connection setup:
+
+(defun fuel-con--setup-connection (buffer)
+  (set-buffer buffer)
+  (let ((conn (fuel-con--make-connection buffer)))
+    (fuel-con--setup-comint)
+    (setq fuel-con--connection conn)))
+
+(defun fuel-con--setup-comint ()
+  (add-hook 'comint-redirect-filter-functions
+            'fuel-con--comint-redirect-filter t t))
+
+\f
+;;; Requests handling:
+
+(defun fuel-con--process-next (con)
+  (when (not (fuel-con--connection-current-request con))
+    (let* ((buffer (fuel-con--connection-buffer con))
+           (req (fuel-con--connection-pop-request con))
+           (str (and req (fuel-con--request-string req))))
+      (when (and buffer req str)
+        (set-buffer buffer)
+        (comint-redirect-send-command str
+                                      (get-buffer-create "*factor messages*")
+                                      nil
+                                      t)))))
+
+(defun fuel-con--comint-redirect-filter (str)
+  (if (not fuel-con--connection)
+      (format "\nERROR: No connection in buffer (%s)\n" str)
+    (let ((req (fuel-con--connection-current-request fuel-con--connection)))
+      (if (not req) (format "\nERROR: No current request (%s)\n" str)
+        (let ((cont (fuel-con--request-continuation req))
+              (id (fuel-con--request-id req))
+              (rstr (fuel-con--request-string req))
+              (buffer (fuel-con--request-buffer req)))
+          (prog1
+              (if (not cont)
+                  (format "\nWARNING: Droping result for request %s:%S (%s)\n"
+                          id rstr str)
+                (condition-case cerr
+                    (with-current-buffer (or buffer (current-buffer))
+                      (funcall cont str)
+                      (format "\nINFO: %s:%S processed\nINFO: %s\n" id rstr str))
+                  (error (format "\nERROR: continuation failed %s:%S \nERROR: %s\n"
+                                 id rstr cerr))))
+            (fuel-con--connection-clean-current-request fuel-con--connection)))))))
+
+\f
+;;; Message sending interface:
+
+(defun fuel-con--send-string (buffer/proc str cont &optional sender-buffer)
+  (save-current-buffer
+    (let ((con (fuel-con--get-connection buffer/proc)))
+      (unless con
+        (error "FUEL: couldn't find connection"))
+      (let ((req (fuel-con--make-request str cont sender-buffer)))
+        (fuel-con--connection-queue-request con req)
+        (fuel-con--process-next con)
+        req))))
+
+(defvar fuel-connection-timeout 30000
+  "Time limit, in msecs, blocking on synchronous evaluation requests")
+
+(defun fuel-con--send-string/wait (buffer/proc str cont &optional timeout sbuf)
+  (save-current-buffer
+    (let* ((con (fuel-con--get-connection buffer/proc))
+         (req (fuel-con--send-string buffer/proc str cont sbuf))
+         (id (and req (fuel-con--request-id req)))
+         (time (or timeout fuel-connection-timeout))
+         (step 2))
+      (when id
+        (while (and (> time 0)
+                    (not (fuel-con--connection-completed-p con id)))
+          (sleep-for 0 step)
+          (setq time (- time step)))
+        (or (> time 0)
+            (fuel-con--request-deactivate req)
+            nil)))))
+
+\f
+(provide 'fuel-connection)
+;;; fuel-connection.el ends here
index b3aad7f3dcc1597d967aef5578d75abce6198046..ad9f47ceb1a62fba34bdab6d907fdf0ea06c215f 100644 (file)
              (buffer (if file (find-file-noselect file) (current-buffer))))
         (with-current-buffer buffer
           (fuel-debug--display-retort
-           (fuel-eval--eval-string/context (format ":%s" n))
+           (fuel-eval--send/wait (fuel-eval--cmd/string (format ":%s" n)))
            (format "Restart %s (%s) successful" n (nth (1- n) rs))))))))
 
 (defun fuel-debug-show--compiler-info (info)
       (error "%s information not available" info))
     (message "Retrieving %s info ..." info)
     (unless (fuel-debug--display-retort
-             (fuel-eval--eval-string info) "" (fuel-debug--buffer-file))
+             (fuel-eval--send/wait (fuel-eval--cmd/string info))
+             "" (fuel-debug--buffer-file))
       (error "Sorry, no %s info available" info))))
 
 \f
index 62001cc48c2785f6228a196275a2f4c8e7bd96d7..02bcb54d66f09c169fd4b1b6b8474a783a37ac75 100644 (file)
@@ -1,4 +1,4 @@
-;;; fuel-eval.el --- utilities for communication with fuel-listener
+;;; fuel-eval.el --- evaluating Factor expressions
 
 ;; Copyright (C) 2008  Jose Antonio Ortega Ruiz
 ;; See http://factorcode.org/license.txt for BSD license.
@@ -9,46 +9,16 @@
 
 ;;; Commentary:
 
-;; Protocols for handling communications via a comint buffer running a
-;; factor listener.
+;; Protocols for sending evaluations to the Factor listener.
 
 ;;; Code:
 
 (require 'fuel-base)
 (require 'fuel-syntax)
+(require 'fuel-connection)
 
 \f
-;;; Syncronous string sending:
-
-(defvar fuel-eval-log-max-length 16000)
-
-(defvar fuel-eval--default-proc-function nil)
-(defsubst fuel-eval--default-proc ()
-  (and fuel-eval--default-proc-function
-       (funcall fuel-eval--default-proc-function)))
-
-(defvar fuel-eval--proc nil)
-(defvar fuel-eval--log t)
-
-(defun fuel-eval--send-string (str)
-  (let ((proc (or fuel-eval--proc (fuel-eval--default-proc))))
-    (when proc
-      (with-current-buffer (get-buffer-create "*factor messages*")
-        (goto-char (point-max))
-        (when (and (> fuel-eval-log-max-length 0)
-                   (> (point) fuel-eval-log-max-length))
-          (erase-buffer))
-        (when fuel-eval--log (insert "\n>> " (fuel--shorten-str str 256)))
-        (newline)
-        (let ((beg (point)))
-          (comint-redirect-send-command-to-process str (current-buffer) proc nil t)
-          (with-current-buffer (process-buffer proc)
-            (while (not comint-redirect-completed) (sleep-for 0 1)))
-          (goto-char beg)
-          (current-buffer))))))
-
-\f
-;;; Evaluation protocol
+;;; Retort and retort-error datatypes:
 
 (defsubst fuel-eval--retort-make (err result &optional output)
   (list err result output))
 (defsubst fuel-eval--retort-p (ret) (listp ret))
 
 (defsubst fuel-eval--make-parse-error-retort (str)
-  (fuel-eval--retort-make 'parse-retort-error nil str))
+  (fuel-eval--retort-make (cons 'fuel-parse-retort-error str) nil))
 
-(defun fuel-eval--parse-retort (buffer)
+(defun fuel-eval--parse-retort (str)
   (save-current-buffer
-    (set-buffer buffer)
     (condition-case nil
-        (read (current-buffer))
-      (error (fuel-eval--make-parse-error-retort
-              (buffer-substring-no-properties (point) (point-max)))))))
-
-(defsubst fuel-eval--send/retort (str)
-  (fuel-eval--parse-retort (fuel-eval--send-string str)))
-
-(defsubst fuel-eval--eval-begin ()
-  (fuel-eval--send/retort "fuel-begin-eval"))
-
-(defsubst fuel-eval--eval-end ()
-  (fuel-eval--send/retort "fuel-begin-eval"))
-
-(defsubst fuel-eval--factor-array (strs)
-  (format "V{ %S }" (mapconcat 'identity strs " ")))
-
-(defsubst fuel-eval--eval-strings (strs &optional no-restart)
-  (let ((str (format "fuel-eval-%s %s fuel-eval"
-                     (if no-restart "non-restartable" "restartable")
-                     (fuel-eval--factor-array strs))))
-    (fuel-eval--send/retort str)))
-
-(defsubst fuel-eval--eval-string (str &optional no-restart)
-  (fuel-eval--eval-strings (list str) no-restart))
-
-(defun fuel-eval--eval-strings/context (strs &optional no-restart)
-  (let ((usings (fuel-syntax--usings-update)))
-    (fuel-eval--send/retort
-     (format "fuel-eval-%s %s %S %s fuel-eval-in-context"
-             (if no-restart "non-restartable" "restartable")
-             (fuel-eval--factor-array strs)
-             (or fuel-syntax--current-vocab "f")
-             (if usings (fuel-eval--factor-array usings) "f")))))
-
-(defsubst fuel-eval--eval-string/context (str &optional no-restart)
-  (fuel-eval--eval-strings/context (list str) no-restart))
-
-(defun fuel-eval--eval-region/context (begin end &optional no-restart)
-  (let ((lines (split-string (buffer-substring-no-properties begin end)
-                             "[\f\n\r\v]+" t)))
-    (when (> (length lines) 0)
-      (fuel-eval--eval-strings/context lines no-restart))))
-
-\f
-;;; Error parsing
+        (let ((ret (car (read-from-string str))))
+          (if (fuel-eval--retort-p ret) ret (error)))
+      (error (fuel-eval--make-parse-error-retort str)))))
 
 (defsubst fuel-eval--error-name (err) (car err))
 
 (defsubst fuel-eval--error-line-text (err)
   (nth 3 (fuel-eval--error-lexer-p err)))
 
+\f
+;;; String sending::
+
+(defvar fuel-eval-log-max-length 16000)
+
+(defvar fuel-eval--default-proc-function nil)
+(defsubst fuel-eval--default-proc ()
+  (and fuel-eval--default-proc-function
+       (funcall fuel-eval--default-proc-function)))
+
+(defvar fuel-eval--proc nil)
+
+(defvar fuel-eval--log t)
+
+(defvar fuel-eval--sync-retort nil)
+
+(defun fuel-eval--send/wait (str &optional timeout buffer)
+  (setq fuel-eval--sync-retort nil)
+  (fuel-con--send-string/wait (or fuel-eval--proc (fuel-eval--default-proc))
+                              str
+                              '(lambda (s)
+                                 (setq fuel-eval--sync-retort
+                                       (fuel-eval--parse-retort s)))
+                              timeout
+                              buffer)
+  fuel-eval--sync-retort)
+
+(defun fuel-eval--send (str cont &optional buffer)
+  (fuel-con--send-string (or fuel-eval--proc (fuel-eval--default-proc))
+                         str
+                         `(lambda (s) (,cont (fuel-eval--parse-retort s)))
+                         buffer))
+
+\f
+;;; Evaluation protocol
+
+(defsubst fuel-eval--factor-array (strs)
+  (format "V{ %S }" (mapconcat 'identity strs " ")))
+
+(defun fuel-eval--cmd/lines (strs &optional no-rs in usings)
+  (unless (and in usings) (fuel-syntax--usings-update))
+  (let* ((in (cond ((not in) (or fuel-syntax--current-vocab "f"))
+                   ((eq in t) "fuel-scratchpad")
+                   (in in)))
+         (usings (cond ((not usings) fuel-syntax--usings)
+                       ((eq usings t) nil)
+                       (usings usings))))
+    (format "fuel-eval-%srestartable %s %S %s fuel-eval-in-context"
+            (if no-rs "non-" "")
+            (fuel-eval--factor-array strs)
+            in
+            (fuel-eval--factor-array usings))))
+
+(defsubst fuel-eval--cmd/string (str &optional no-rs in usings)
+  (fuel-eval--cmd/lines (list str) no-rs in usings))
+
+(defun fuel-eval--cmd/region (begin end &optional no-rs in usings)
+  (let ((lines (split-string (buffer-substring-no-properties begin end)
+                             "[\f\n\r\v]+" t)))
+    (when (> (length lines) 0)
+      (fuel-eval--cmd/lines lines no-rs in usings))))
+
+
 \f
 (provide 'fuel-eval)
 ;;; fuel-eval.el ends here
index 4c710635ba56d4b8b4f33f3fc7fef84eab9c312d..ba2a499b4bee3e9c772925d9a6d6004b06e184f2 100644 (file)
@@ -57,7 +57,7 @@
     (,fuel-syntax--type-definition-regex 2 'factor-font-lock-type-name)
     (,fuel-syntax--method-definition-regex (1 'factor-font-lock-type-name)
                                            (2 'factor-font-lock-word))
-    (,fuel-syntax--parent-type-regex 1 'factor-font-lock-type)
+    (,fuel-syntax--parent-type-regex 1 'factor-font-lock-type-name)
     (,fuel-syntax--constructor-regex . 'factor-font-lock-constructor)
     (,fuel-syntax--setter-regex . 'factor-font-lock-setter-word)
     (,fuel-syntax--symbol-definition-regex 2 'factor-font-lock-symbol)
index 1db9b25d69787b9c30c8db57292f96ec8dfefde5..227778934a889800cdda1befb6d6a763bd993b7c 100644 (file)
   :type 'hook
   :group 'fuel-help)
 
+(defcustom fuel-help-history-cache-size 50
+  "Maximum number of pages to keep in the help browser cache."
+  :type 'integer
+  :group 'fuel-help)
+
 (defface fuel-help-font-lock-headlines '((t (:bold t :weight bold)))
   "Face for headlines in help buffers."
   :group 'fuel-help
   (let ((word (or word (fuel-syntax-symbol-at-point)))
         (fuel-eval--log t))
     (when word
-      (let ((ret (fuel-eval--eval-string/context
-                  (format "\\ %s synopsis fuel-eval-set-result" word)
-                  t)))
-        (when (not (fuel-eval--retort-error ret))
+      (let* ((str (format "\\ %s synopsis fuel-eval-set-result" word))
+             (cmd (fuel-eval--cmd/string str t t))
+             (ret (fuel-eval--send/wait cmd 20)))
+        (when (and ret (not (fuel-eval--retort-error ret)))
           (if fuel-help-minibuffer-font-lock
               (fuel-help--font-lock-str (fuel-eval--retort-result ret))
             (fuel-eval--retort-result ret)))))))
@@ -101,92 +106,83 @@ displayed in the minibuffer."
   (message "Fuel Autodoc %s" (if fuel-autodoc-mode "enabled" "disabled")))
 
 \f
-;;;; Factor help mode:
-
-(defvar fuel-help-mode-map (make-sparse-keymap)
-  "Keymap for Factor help mode.")
-
-(define-key fuel-help-mode-map [(return)] 'fuel-help)
-
-(defconst fuel-help--headlines
-  (regexp-opt '("Class description"
-                "Definition"
-                "Examples"
-                "Generic word contract"
-                "Inputs and outputs"
-                "Methods"
-                "Notes"
-                "Parent topics:"
-                "See also"
-                "Syntax"
-                "Vocabulary"
-                "Warning"
-                "Word description")
-              t))
+;;; Help browser history:
 
-(defconst fuel-help--headlines-regexp (format "^%s" fuel-help--headlines))
+(defvar fuel-help--history
+  (list nil
+        (make-ring fuel-help-history-cache-size)
+        (make-ring fuel-help-history-cache-size)))
 
-(defconst fuel-help--font-lock-keywords
-  `(,@fuel-font-lock--font-lock-keywords
-    (,fuel-help--headlines-regexp . 'fuel-help-font-lock-headlines)))
+(defvar fuel-help--history-idx 0)
 
-(defun fuel-help-mode ()
-  "Major mode for displaying Factor documentation.
-\\{fuel-help-mode-map}"
-  (interactive)
-  (kill-all-local-variables)
-  (use-local-map fuel-help-mode-map)
-  (setq mode-name "Factor Help")
-  (setq major-mode 'fuel-help-mode)
+(defun fuel-help--history-push (term)
+  (when (car fuel-help--history)
+    (ring-insert (nth 1 fuel-help--history) (car fuel-help--history)))
+  (setcar fuel-help--history term))
 
-  (fuel-font-lock--font-lock-setup fuel-help--font-lock-keywords t)
+(defun fuel-help--history-next ()
+  (when (not (ring-empty-p (nth 2 fuel-help--history)))
+    (when (car fuel-help--history)
+      (ring-insert (nth 1 fuel-help--history) (car fuel-help--history)))
+    (setcar fuel-help--history (ring-remove (nth 2 fuel-help--history) 0))))
 
-  (set (make-local-variable 'view-no-disable-on-exit) t)
-  (view-mode)
-  (setq view-exit-action
-        (lambda (buffer)
-          ;; Use `with-current-buffer' to make sure that `bury-buffer'
-          ;; also removes BUFFER from the selected window.
-          (with-current-buffer buffer
-            (bury-buffer))))
+(defun fuel-help--history-previous ()
+  (when (not (ring-empty-p (nth 1 fuel-help--history)))
+    (when (car fuel-help--history)
+      (ring-insert (nth 2 fuel-help--history) (car fuel-help--history)))
+    (setcar fuel-help--history (ring-remove (nth 1 fuel-help--history) 0))))
 
-  (setq fuel-autodoc-mode-string "")
-  (fuel-autodoc-mode)
-  (run-mode-hooks 'fuel-help-mode-hook))
+\f
+;;; Fuel help buffer and internals:
 
 (defun fuel-help--help-buffer ()
   (with-current-buffer (get-buffer-create "*fuel-help*")
     (fuel-help-mode)
     (current-buffer)))
 
-(defvar fuel-help--history nil)
+(defvar fuel-help--prompt-history nil)
 
-(defun fuel-help--show-help (&optional see)
-  (let* ((def (fuel-syntax-symbol-at-point))
+(defun fuel-help--show-help (&optional see word)
+  (let* ((def (or word (fuel-syntax-symbol-at-point)))
          (prompt (format "See%s help on%s: " (if see " short" "")
                          (if def (format " (%s)" def) "")))
          (ask (or (not (memq major-mode '(factor-mode fuel-help-mode)))
                   (not def)
                   fuel-help-always-ask))
-         (def (if ask (read-string prompt nil 'fuel-help--history def) def))
-         (cmd (format "\\ %s %s" def (if see "see" "help")))
-         (fuel-eval--log nil)
-         (ret (fuel-eval--eval-string/context cmd t))
-         (out (fuel-eval--retort-output ret)))
+         (def (if ask (read-string prompt nil 'fuel-help--prompt-history def)
+                def))
+         (cmd (format "\\ %s %s" def (if see "see" "help"))))
+    (message "Looking up '%s' ..." def)
+    (fuel-eval--send (fuel-eval--cmd/string cmd t t)
+                     `(lambda (r) (fuel-help--show-help-cont ,def r)))))
+
+(defun fuel-help--show-help-cont (def ret)
+  (let ((out (fuel-eval--retort-output ret)))
     (if (or (fuel-eval--retort-error ret) (empty-string-p out))
         (message "No help for '%s'" def)
-      (let ((hb (fuel-help--help-buffer))
-            (inhibit-read-only t)
-            (font-lock-verbose nil))
-        (set-buffer hb)
-        (erase-buffer)
-        (insert out)
-        (set-buffer-modified-p nil)
-        (pop-to-buffer hb)
-        (goto-char (point-min))))))
+      (fuel-help--insert-contents def out))))
+
+(defun fuel-help--insert-contents (def str &optional nopush)
+  (let ((hb (fuel-help--help-buffer))
+        (inhibit-read-only t)
+        (font-lock-verbose nil))
+    (set-buffer hb)
+    (erase-buffer)
+    (insert str)
+    (goto-char (point-min))
+    (when (re-search-forward (format "^%s" def) nil t)
+      (beginning-of-line)
+      (kill-region (point-min) (point))
+      (next-line)
+      (open-line 1))
+    (set-buffer-modified-p nil)
+    (unless nopush (fuel-help--history-push (cons def str)))
+    (pop-to-buffer hb)
+    (goto-char (point-min))
+    (message "%s" def)))
 
 \f
-;;; Interface: see/help commands
+;;; Interactive help commands:
 
 (defun fuel-help-short (&optional arg)
   "See a help summary of symbol at point.
@@ -204,6 +200,79 @@ buffer."
   (interactive)
   (fuel-help--show-help))
 
+(defun fuel-help-next ()
+  "Go to next page in help browser."
+  (interactive)
+  (let ((item (fuel-help--history-next))
+        (fuel-help-always-ask nil))
+    (unless item
+      (error "No next page"))
+    (fuel-help--insert-contents (car item) (cdr item) t)))
+
+(defun fuel-help-previous ()
+  "Go to next page in help browser."
+  (interactive)
+  (let ((item (fuel-help--history-previous))
+        (fuel-help-always-ask nil))
+    (unless item
+      (error "No previous page"))
+    (fuel-help--insert-contents (car item) (cdr item) t)))
+
+\f
+;;;; Factor help mode:
+
+(defvar fuel-help-mode-map
+  (let ((map (make-sparse-keymap)))
+    (define-key map "\C-m" 'fuel-help)
+    (define-key map "q" 'bury-buffer)
+    (define-key map "b" 'fuel-help-previous)
+    (define-key map "f" 'fuel-help-next)
+    (define-key map (kbd "SPC")  'scroll-up)
+    (define-key map (kbd "S-SPC") 'scroll-down)
+    map))
+
+(defconst fuel-help--headlines
+  (regexp-opt '("Class description"
+                "Definition"
+                "Errors"
+                "Examples"
+                "Generic word contract"
+                "Inputs and outputs"
+                "Methods"
+                "Notes"
+                "Parent topics:"
+                "See also"
+                "Syntax"
+                "Variable description"
+                "Variable value"
+                "Vocabulary"
+                "Warning"
+                "Word description")
+              t))
+
+(defconst fuel-help--headlines-regexp (format "^%s" fuel-help--headlines))
+
+(defconst fuel-help--font-lock-keywords
+  `(,@fuel-font-lock--font-lock-keywords
+    (,fuel-help--headlines-regexp . 'fuel-help-font-lock-headlines)))
+
+(defun fuel-help-mode ()
+  "Major mode for browsing Factor documentation.
+\\{fuel-help-mode-map}"
+  (interactive)
+  (kill-all-local-variables)
+  (use-local-map fuel-help-mode-map)
+  (setq mode-name "Factor Help")
+  (setq major-mode 'fuel-help-mode)
+
+  (fuel-font-lock--font-lock-setup fuel-help--font-lock-keywords t)
+
+  (setq fuel-autodoc-mode-string "")
+  (fuel-autodoc-mode)
+
+  (run-mode-hooks 'fuel-help-mode-hook)
+  (toggle-read-only 1))
+
 \f
 (provide 'fuel-help)
 ;;; fuel-help.el ends here
index 9fa330993c2015a6201b70ed18558014480ff5f5..c72f66b21c17d9c2888cae7533d7c46e826d98c6 100644 (file)
@@ -66,7 +66,7 @@ buffer."
       (comint-exec fuel-listener-buffer "factor"
                    factor nil `("-run=fuel" ,(format "-i=%s" image)))
       (fuel-listener--wait-for-prompt 20)
-      (fuel-eval--send-string "USE: fuel")
+      (fuel-eval--send/wait "USE: fuel")
       (message "FUEL listener up and running!"))))
 
 (defun fuel-listener--process (&optional start)
@@ -83,18 +83,18 @@ buffer."
 ;;; Prompt chasing
 
 (defun fuel-listener--wait-for-prompt (&optional timeout)
-    (let ((proc (get-buffer-process fuel-listener-buffer))
-          (seen))
-      (with-current-buffer fuel-listener-buffer
-        (while (progn (goto-char comint-last-input-end)
-                      (not (or seen
-                               (setq seen
-                                     (re-search-forward comint-prompt-regexp nil t))
-                               (not (accept-process-output proc timeout))))))
-        (goto-char (point-max)))
-      (unless seen
+  (let ((proc (get-buffer-process fuel-listener-buffer)))
+    (with-current-buffer fuel-listener-buffer
+      (goto-char (or comint-last-input-end (point-min)))
+      (let ((seen (re-search-forward comint-prompt-regexp nil t)))
+        (while (and (not seen)
+                    (accept-process-output proc (or timeout 10) nil t))
+          (sleep-for 0 1)
+          (goto-char comint-last-input-end)
+          (setq seen (re-search-forward comint-prompt-regexp nil t)))
         (pop-to-buffer fuel-listener-buffer)
-        (error "No prompt found!"))))
+        (goto-char (point-max))
+        (unless seen (error "No prompt found!"))))))
 
 \f
 ;;; Interface: starting fuel listener
@@ -124,6 +124,8 @@ buffer."
   (set (make-local-variable 'comint-prompt-read-only) t)
   (setq fuel-listener--compilation-begin nil))
 
+(define-key fuel-listener-mode-map "\C-cz" 'run-factor)
+(define-key fuel-listener-mode-map "\C-c\C-z" 'run-factor)
 (define-key fuel-listener-mode-map "\C-ch" 'fuel-help)
 (define-key fuel-listener-mode-map "\M-." 'fuel-edit-word-at-point)
 (define-key fuel-listener-mode-map "\C-ck" 'fuel-run-file)
index ea1d4b93ed0c196ddcebd387eaff22f6f4c89d81..feaea1548e2f44463694c6d3fb321c52bde13944 100644 (file)
@@ -45,16 +45,20 @@ With prefix argument, ask for the file to run."
   (let* ((file (or (and arg (read-file-name "File: " nil (buffer-file-name) t))
                    (buffer-file-name)))
          (file (expand-file-name file))
-         (buffer (find-file-noselect file))
-         (cmd (format "%S fuel-run-file" file)))
+         (buffer (find-file-noselect file)))
     (when buffer
       (with-current-buffer buffer
         (message "Compiling %s ..." file)
-        (let ((r (fuel-debug--display-retort (fuel-eval--eval-string/context cmd)
-                                             (format "%s successfully compiled" file)
-                                             nil
-                                             file)))
-          (if r (message "Compiling %s ... OK!" file) (message "")))))))
+        (fuel-eval--send (fuel-eval--cmd/string (format "%S fuel-run-file" file))
+                         `(lambda (r) (fuel--run-file-cont r ,file)))))))
+
+(defun fuel--run-file-cont (ret file)
+  (if (fuel-debug--display-retort ret
+                                  (format "%s successfully compiled" file)
+                                  nil
+                                  file)
+      (message "Compiling %s ... OK!" file)
+    (message "")))
 
 (defun fuel-eval-region (begin end &optional arg)
   "Sends region to Fuel's listener for evaluation.
@@ -62,7 +66,7 @@ Unless called with a prefix, switchs to the compilation results
 buffer in case of errors."
   (interactive "r\nP")
   (fuel-debug--display-retort
-   (fuel-eval--eval-region/context begin end)
+   (fuel-eval--send/wait (fuel-eval--cmd/region begin end) 10000)
    (format "%s%s"
            (if fuel-syntax--current-vocab
                (format "IN: %s " fuel-syntax--current-vocab)
@@ -105,8 +109,9 @@ With prefix, asks for the word to edit."
                                         (if word (format " (%s)" word) ""))
                                 word)
                  word)))
-    (let* ((ret (fuel-eval--eval-string/context
+    (let* ((str (fuel-eval--cmd/string
                  (format "\\ %s fuel-get-edit-location" word)))
+           (ret (fuel-eval--send/wait str))
            (err (fuel-eval--retort-error ret))
            (loc (fuel-eval--retort-result ret)))
       (when (or err (not loc) (not (listp loc)) (not (stringp (car loc))))
index 54078cfe8d7436f113c4c3794b2ee527476559bd..e5aac32b54535ef41642f6ccb57afba9a4ab5bf9 100644 (file)
@@ -6,7 +6,7 @@ PLAF_DLL_OBJS += vm/os-macosx.o vm/mach_signal.o
 DLL_EXTENSION = .dylib
 
 ifdef X11
-       LIBS = -lm -framework Foundation $(X11_UI_LIBS) -Wl,-dylib_file,/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib:/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib
+       LIBS = -lm -framework Cocoa $(X11_UI_LIBS) -Wl,-dylib_file,/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib:/System/Library/Frameworks/OpenGL.framework/Versions/A/Libraries/libGL.dylib
 else
     LIBS = -lm -framework Cocoa -framework AppKit
 endif