├── README ├── protocols ├── JdbcFirebirdQry.nrx ├── SrvSockTDB.nrx ├── mod-net-utils.r ├── prot-daytime.r ├── prot-demo.r ├── prot-dns.r ├── prot-email.reb ├── prot-fax.r ├── prot-ftp.r ├── prot-http.r ├── prot-http.r3 ├── prot-imap.r ├── prot-jdbcbridge.r ├── prot-oldsmtp.r ├── prot-pop3.reb ├── prot-send.r ├── prot-send.reb ├── prot-sl4a.r3 ├── prot-smtp.r ├── prot-smtp.reb ├── prot-spop3.reb ├── prot-synctcp.reb └── prot-time.r ├── r3-gui ├── developer │ ├── actors │ │ ├── actor-changes.mdp │ │ ├── actor-overriding.mdp │ │ ├── actors.mdp │ │ └── actors.txt │ ├── events │ │ ├── gui-event-flow.graphml │ │ └── gui-event-flow.png │ ├── faces │ │ └── faces.mdp │ ├── hierarchy │ │ ├── gui-hierarchy.graphml │ │ └── gui-hierarchy.png │ ├── layouts │ │ ├── graphics │ │ │ ├── gui-layouts-0.png │ │ │ ├── gui-layouts-0a.png │ │ │ ├── gui-layouts-0b.png │ │ │ ├── gui-layouts-1.png │ │ │ ├── gui-layouts-2-col.png │ │ │ ├── gui-layouts-2.png │ │ │ ├── gui-layouts-2g-col.png │ │ │ ├── gui-layouts-3-col.png │ │ │ ├── gui-layouts-4-col.png │ │ │ ├── gui-layouts-combo-1.png │ │ │ ├── gui-layouts-combo-2.png │ │ │ ├── gui-layouts-combo-3.png │ │ │ ├── gui-layouts-combo-4.png │ │ │ ├── gui-layouts-combo-5.png │ │ │ ├── gui-layouts-group-1.png │ │ │ ├── gui-layouts-group-1a.png │ │ │ ├── gui-layouts-show.png │ │ │ ├── gui-layouts-sizing-1.png │ │ │ ├── gui-layouts-sizing-2.png │ │ │ ├── gui-layouts-sizing-3.png │ │ │ ├── gui-layouts-vert.png │ │ │ ├── gui-layouts-visibility.png │ │ │ └── gui-opinion-form.png │ │ ├── layouts.mdp │ │ └── layouts.txt │ ├── resizing │ │ ├── boxmodel.gif │ │ ├── corrections.mdp │ │ ├── resizing-ll.mdp │ │ └── resizing.mdp │ └── styles │ │ └── styles.mdp ├── gui.r3 ├── license │ ├── rla.txt │ └── rlanotes.txt ├── specs │ ├── dialogs │ │ ├── dialog-system.mdp │ │ ├── dialog01.png │ │ ├── dialog02.png │ │ └── dialogs-prototype.mdp │ ├── other │ │ ├── attaching.mdp │ │ ├── gob-capture.mdp │ │ ├── r3-gui-snippets.mdp │ │ └── save-state.mdp │ ├── resizing │ │ ├── resizing-proposal.mdp │ │ ├── resizing-shortcuts.mdp │ │ ├── resizing.rmd │ │ └── shortcut-notes.mdp │ ├── styles │ │ ├── gen-style-docs.r3 │ │ ├── panels │ │ │ ├── graphics │ │ │ │ ├── gui-opinion-form.PNG │ │ │ │ ├── gui-panels-0.PNG │ │ │ │ ├── gui-panels-0a.PNG │ │ │ │ ├── gui-panels-0b.PNG │ │ │ │ ├── gui-panels-1.PNG │ │ │ │ ├── gui-panels-2-col.PNG │ │ │ │ ├── gui-panels-2.PNG │ │ │ │ ├── gui-panels-2g-col.PNG │ │ │ │ ├── gui-panels-3-col.PNG │ │ │ │ ├── gui-panels-4-col.PNG │ │ │ │ ├── gui-panels-combo-1.PNG │ │ │ │ ├── gui-panels-combo-2.PNG │ │ │ │ ├── gui-panels-combo-3.PNG │ │ │ │ ├── gui-panels-combo-4.PNG │ │ │ │ ├── gui-panels-combo-5.PNG │ │ │ │ ├── gui-panels-group-1.PNG │ │ │ │ ├── gui-panels-group-1a.PNG │ │ │ │ ├── gui-panels-show.png │ │ │ │ ├── gui-panels-sizing-1.PNG │ │ │ │ ├── gui-panels-sizing-2.PNG │ │ │ │ ├── gui-panels-sizing-3.PNG │ │ │ │ ├── gui-panels-vert.PNG │ │ │ │ └── gui-panels-visibility.png │ │ │ ├── gui-opinion-form.PNG │ │ │ ├── gui-panel-sizing-3.PNG │ │ │ ├── gui-panels-0.PNG │ │ │ ├── gui-panels-0a.PNG │ │ │ ├── gui-panels-0b.PNG │ │ │ ├── gui-panels-1.PNG │ │ │ ├── gui-panels-2-col.PNG │ │ │ ├── gui-panels-2.PNG │ │ │ ├── gui-panels-2g-col.PNG │ │ │ ├── gui-panels-3-col.PNG │ │ │ ├── gui-panels-4-col.PNG │ │ │ ├── gui-panels-combo-1.PNG │ │ │ ├── gui-panels-combo-2.PNG │ │ │ ├── gui-panels-combo-3.PNG │ │ │ ├── gui-panels-combo-4.PNG │ │ │ ├── gui-panels-combo-5.PNG │ │ │ ├── gui-panels-group-1.PNG │ │ │ ├── gui-panels-group-1a.PNG │ │ │ ├── gui-panels-show.png │ │ │ ├── gui-panels-sizing-1.PNG │ │ │ ├── gui-panels-sizing-2.PNG │ │ │ ├── gui-panels-sizing-3.PNG │ │ │ ├── gui-panels-vert.PNG │ │ │ ├── gui-panels-visibility.png │ │ │ ├── gui-panels.mdp │ │ │ └── gui-panels.txt │ │ ├── style-list.rmd │ │ ├── style-tree.rmd │ │ ├── tab-box │ │ │ └── tab-box.mdp │ │ └── text-table │ │ │ └── text-table.mdp │ └── validation │ │ ├── validation-proposal.mdp │ │ └── validation-prototype.mdp └── user │ ├── getting-started.html │ └── getting-started.mdp └── scripts ├── base32.reb ├── calcCRC16.reb ├── calcCRC8.reb ├── calendar-google-api.reb ├── change-log.reb ├── db2-test.reb ├── demo.r3 ├── dl-renc.reb ├── editor.reb ├── flick-price-scraper.reb ├── flick.reb ├── flick5.reb ├── gmtimesheet.reb ├── gui-server.reb ├── helpdocs.reb ├── index.reb ├── inspector.reb ├── install.reb ├── language.reb ├── login2so.reb ├── loginso.reb ├── loginxport.reb ├── mediawiki-scrape.r3 ├── microwebserver.reb ├── modflick.reb ├── odbc-test.reb ├── pubmed.reb ├── rebol-flick-api.reb ├── rebol-flick-forecast-api.reb ├── rebolbot.r3 ├── task-client.reb ├── test-send.reb ├── test-smtp.reb ├── test-storage.reb ├── unzip.reb ├── userstuff.reb └── web3works.r3 /README: -------------------------------------------------------------------------------- 1 | This is a public repository of the official Rebol3 open sources, and those contributed by individuals. 2 | 3 | If there are any licensing issues which mean that some files should not be here .. let me know. 4 | 5 | Graham Chiu ( compkarori and I'm on gmail ) 6 | -------------------------------------------------------------------------------- /protocols/JdbcFirebirdQry.nrx: -------------------------------------------------------------------------------- 1 | /* jdbc\JdbcFirebirdQry.nrx 2 | 3 | This NetRexx program demonstrate Firebird query using the JDBC API. 4 | Usage: Java JdbcFirebirdQry [] [] 5 | Modified from the JdbcQry example from the red book - Graham Chiu 2010/06/27 6 | 7 | */ 8 | 9 | import java.sql. 10 | 11 | parse arg url prefix -- process arguments 12 | if url = '' then 13 | url = 'jdbc:firebirdsql:localhost/3050:c:\\database\\employee.gdb' -- default db 14 | else do -- check for correct URL 15 | parse url p1 ':' p2 ':' rest 16 | if p1 \= 'jdbc' | p2 \= 'firebirdsql' | rest = '' then do 17 | say 'Usage: java JdbcQry [] []' 18 | exit 8 19 | end 20 | end 21 | 22 | if prefix \= '' then 23 | parse prefix userid password 24 | 25 | if userid = '' then 26 | userid = 'SYSDBA' 27 | if password = '' then 28 | password = 'masterke' 29 | 30 | say url 31 | say p1 32 | say p2 33 | say rest 34 | say 'Userid: 'userid 35 | say 'Password: 'password 36 | 37 | do -- loading Firebird support 38 | say 'Loading Firebird driver classes...' 39 | Class.forName('org.firebirdsql.jdbc.FBDriver').newInstance() 40 | catch e1 = Exception 41 | say 'The Firebird driver classes could not be found and loaded !' 42 | say 'Exception (' e1 ') caught : \n' e1.getMessage() 43 | exit 1 44 | end -- end : loading Firebird support 45 | 46 | do -- connecting to Firebird host 47 | say 'Connecting to:' url 48 | jdbcCon = Connection DriverManager.getConnection(url, userid, password) 49 | catch e2 = SQLException 50 | say 'SQLException(s) caught while connecting !' 51 | loop while (e2 \= null) 52 | say 'SQLState:' e2.getSQLState() 53 | say 'Message: ' e2.getMessage() 54 | say 'Vendor: ' e2.getErrorCode() 55 | say 56 | e2 = e2.getNextException() 57 | end 58 | exit 1 59 | end -- end : connecting to Firebird host 60 | 61 | do -- do the query 62 | say 'Creating query...' 63 | query = 'SELECT * from staff' 64 | stmt = Statement jdbcCon.createStatement() 65 | say 'Executing query:' 66 | loop i=0 to (query.length()-1)%75 67 | say ' ' query.substr(i*75+1,75) 68 | end 69 | rs = ResultSet stmt.executeQuery(query) 70 | say 'Results:' 71 | loop row=0 while rs.next() 72 | say rs.getString('staffname') rs.getString('pwd') 73 | end 74 | rs.close() -- close the ResultSet 75 | stmt.close() -- close the Statement 76 | jdbcCon.close() -- close the Connection 77 | say 'Retrieved' row 'staff' 78 | catch e3 = SQLException 79 | say 'SQLException(s) caught !' 80 | loop while (e3 \= null) 81 | say 'SQLState:' e3.getSQLState() 82 | say 'Message: ' e3.getMessage() 83 | say 'Vendor: ' e3.getErrorCode() 84 | say 85 | e3 = e3.getNextException() 86 | end 87 | end -- end: get staff members -------------------------------------------------------------------------------- /protocols/mod-net-utils.r: -------------------------------------------------------------------------------- 1 | REBOL [ ] 2 | 3 | 4 | net-utils: module [ 5 | Title: "Network Module" 6 | Name: net-utils 7 | Version: 0.0.2 8 | Type: module 9 | Date: 25-Jan-2001 10 | Author: "Graham Chiu" 11 | Rights: 'BSD 12 | Exports: [ 13 | alpha 14 | digit 15 | non-digit 16 | pasv-rule 17 | within? 18 | print-string? 19 | net-log 20 | as-utc 21 | to-ISO8601-date 22 | to-ISO8601-UTC 23 | hmac-sha1 24 | url-encode 25 | enclose-tag 26 | ] 27 | ] [ 28 | 29 | alpha: charset [#"a" - #"z" #"A" - #"Z"] 30 | digit: charset [#"0" - #"9"] 31 | non-digit: complement digit 32 | non-digits: [some non-digit] 33 | pasv-rule: [1 3 digit "," 1 3 digit "," 1 3 digit "," 1 3 digit "," opt ["-"] 1 3 digit "," opt ["-"] 1 3 digit] 34 | 35 | within?: func [low hi code] [ 36 | all [code >= low code <= hi] 37 | ] 38 | 39 | print-string: func [txt] [ 40 | print to-string txt 41 | ] 42 | 43 | net-log: func [txt 44 | /C 45 | /S 46 | ] [ 47 | if C [prin "C: "] 48 | if S [prin "S: "] 49 | print txt 50 | txt 51 | ] 52 | 53 | ;; url stuff 54 | url-encode: func [ 55 | "URL-encode a string" 56 | data "String to encode" 57 | /local new-data 58 | ] [ 59 | new-data: make string! "" 60 | normal-char: charset [ 61 | #"A" - #"Z" #"a" - #"z" 62 | #"@" #"." #"*" #"-" #"_" 63 | #"0" - #"9" 64 | ] 65 | if not string? data [return new-data] 66 | forall data [ 67 | append new-data either find normal-char first data [ 68 | first data 69 | ] [ 70 | rejoin ["%" to-string skip tail (to-hex to-integer first data) -2] 71 | ] 72 | ] 73 | new-data 74 | ] 75 | 76 | ;; email stuff 77 | 78 | email: make object! [ 79 | To: none 80 | CC: none 81 | BCC: none 82 | From: none 83 | Reply-To: none 84 | Date: none 85 | Subject: none 86 | Return-Path: none 87 | Organization: none 88 | Message-Id: none 89 | Comment: none 90 | X-REBOL: form rebol/version 91 | MIME-Version: none 92 | Content-Type: none 93 | Content: none 94 | ] 95 | 96 | export: func [ 97 | {Export an object to something that looks like a header} 98 | object [object!] "Object to export" 99 | /local words values result word 100 | ] [ 101 | words: next first object 102 | values: next second object 103 | result: make string! (20 * length? words) 104 | foreach word words [ 105 | if found? first values [ 106 | insert tail result reduce [word ": " first values newline] 107 | ] 108 | values: next values 109 | ] 110 | result 111 | ] 112 | 113 | ;; amazon stuff 114 | 115 | format-10: func [d [integer! decimal!] 116 | ] [ 117 | next form 100 + d 118 | ] 119 | 120 | as-utc: func [date] [ 121 | if all [date/zone 0:00 <> date/zone] [ 122 | date: date - date/zone 123 | ] 124 | date/zone: none 125 | if none? date/time [date/time: 0:0:0.000] 126 | date 127 | ] 128 | 129 | to-ISO8601-date: func [d [date!] 130 | ] [ 131 | rejoin [ 132 | d/year "-" 133 | format-10 d/month "-" 134 | format-10 d/day "T" 135 | format-10 d/time/1 ":" 136 | format-10 d/time/2 ":" 137 | format-10 round/to d/time/3 .1 "00Z" 138 | ] 139 | ] 140 | 141 | to-ISO8601-UTC: func [date [date!] 142 | ] [ 143 | to-ISO8601-date as-utc date 144 | ] 145 | 146 | today-http-date: func [ 147 | /local d 148 | ] [ 149 | d: now-gmt 150 | rejoin [ 151 | copy/part pick system/locale/days d/weekday 3 152 | ", " next form 100 + d/day " " 153 | copy/part pick system/locale/months d/month 3 154 | " " d/year " " 155 | next form 100:00 + d/time " +0000" 156 | ] 157 | ] 158 | hmac-sha1: func [val [binary!] key [string!]] [checksum/method/key val 'sha1 key] 159 | 160 | ;; XML 161 | 162 | ; enclose-tag 'action 'createdomain 163 | ; createdomain 164 | 165 | comment { 166 | enclose-tag: func [ tag name ][ 167 | either all [ string? name empty? name ][ 168 | append to-tag tag "/" 169 | ][ 170 | ajoin [ to-tag tag name to-tag join "/" first parse form tag " " ] 171 | ] 172 | ] 173 | } 174 | 175 | enclose-tag: func [ tag name ][ 176 | either all [ string? name empty? name ][ 177 | append to-tag tag "/" 178 | ][ 179 | if block? name [ name: ajoin name ] 180 | ajoin [ to-tag tag name to-tag join "/" first parse form tag " " ] 181 | ] 182 | ] 183 | 184 | ] -------------------------------------------------------------------------------- /protocols/prot-daytime.r: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | file: %prot-daytime.r 3 | author: "Graham" 4 | rights: 'BSD 5 | date: 8-Jan-2010 6 | ] 7 | 8 | make-scheme [ 9 | name: 'daytime 10 | title: "Daytime Protocol" 11 | spec: make system/standard/port-spec-net [port-id: 13 ] 12 | awake: func [event /local port] [ 13 | ; print ["=== Client event:" event/type] 14 | port: event/port 15 | switch event/type [ 16 | lookup [ 17 | ; print "DNS lookup" 18 | open port 19 | ] 20 | connect [ 21 | print "connected" 22 | read port 23 | ; print to-string port/data 24 | ] 25 | read [ 26 | ; print [" " to-string port/data] 27 | close port 28 | return true ; quits the awake 29 | ] 30 | wrote [read port] 31 | ] 32 | false 33 | ] 34 | actor: [ 35 | open: func [ 36 | port [port!] 37 | /local conn 38 | ] [ 39 | if port/state [return port] 40 | if none? port/spec/host [http-error "Missing host address"] 41 | port/state: context [ 42 | state: 'ready 43 | connection: 44 | error: none 45 | awake: :port/awake 46 | close?: yes 47 | ] 48 | port/state/connection: conn: make port! [ 49 | scheme: 'tcp 50 | host: port/spec/host 51 | port-id: port/spec/port-id 52 | ref: rejoin [tcp:// host ":" port-id] 53 | ] 54 | conn/awake: :awake 55 | open conn 56 | port 57 | ] 58 | open?: func [ 59 | port [port!] 60 | ][ 61 | all [ port/state ] 62 | ] 63 | 64 | close: func [ 65 | port [port!] 66 | ] [ 67 | if open? port [ 68 | close port/state/connection 69 | port/state/connection/awake: none 70 | port/state: none 71 | ] 72 | port 73 | ] 74 | 75 | read: func [ 76 | port [port!] 77 | /local conn 78 | ] [ 79 | either any-function? :port/awake [ 80 | ; unless open? port [cause-error 'Access 'not-open port/spec/ref] 81 | unless open? port [ 82 | wait open port 83 | ] 84 | port 85 | ] [ 86 | ; do something synchronous here 87 | ] 88 | ] 89 | ] 90 | ] -------------------------------------------------------------------------------- /protocols/prot-demo.r: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | System: "REBOL [R3] Language Interpreter and Run-time Environment" 3 | title: "R3 SL4A" 4 | file: %prot-demo.r 5 | author: ["Graham"] 6 | name: 'sl4a 7 | type: 'module 8 | version: 0.0.1 9 | Date: [26-Mar-2013] 10 | Purpose: "R3 send and receive from Scripting Layer 4 Android" 11 | ] 12 | 13 | make-sl4a-error: func [ 14 | message 15 | ] [ 16 | ; the 'do arms the error! 17 | do make error! [ 18 | type: 'Access 19 | id: 'Protocol 20 | arg1: message 21 | ] 22 | ] 23 | 24 | awake-handler: func [event /local tcp-port ] [ 25 | print ["=== Client event:" event/type] 26 | tcp-port: event/port 27 | switch/default event/type [ 28 | error [ 29 | print "error event received" 30 | tcp-port/spec/port-state: 'error 31 | true 32 | ] 33 | lookup [ 34 | open tcp-port 35 | false 36 | ] 37 | connect [ 38 | print "connected " 39 | write tcp-port tcp-port/locals 40 | tcp-port/spec/port-state: 'ready 41 | false 42 | ] 43 | read [ 44 | print ["^\read:" length? tcp-port/data] 45 | tcp-port/spec/JSON: copy to string! tcp-port/data 46 | clear tcp-port/data 47 | true 48 | ] 49 | wrote [ 50 | print "written, so read port" 51 | read tcp-port 52 | false 53 | ] 54 | close [ 55 | print "closed on us!" 56 | tcp-port/spec/port-state: none 57 | true 58 | ] 59 | ] [ true] 60 | ] 61 | 62 | sync-write: func [sl4a-port [port!] JSON-string 63 | /local tcp-port 64 | ] [ 65 | unless open? sl4a-port [ 66 | open sl4a-port 67 | ] 68 | tcp-port: sl4a-port/state/tcp-port 69 | tcp-port/awake: :awake-handler 70 | either tcp-port/spec/port-state = 'ready [ 71 | write tcp-port to binary! JSON-string 72 | ][ 73 | tcp-port/locals: copy JSON-string 74 | ] 75 | unless port? wait [tcp-port sl4a-port/spec/timeout] [ 76 | make-sl4a-error "SL4A timeout on tcp-port" 77 | ] 78 | ] 79 | 80 | sys/make-scheme [ 81 | name: 'sl4a 82 | title: "SL4A Protocol" 83 | spec: make system/standard/port-spec-net [port-id: 4321 timeout: 5] 84 | 85 | actor: [ 86 | open: func [ 87 | sl4a-port [port!] 88 | /local tcp-port 89 | ] [ 90 | if sl4a-port/state [return sl4a-port] 91 | if none? sl4a-port/spec/host [make-sl4a-error "Missing host address"] 92 | sl4a-port/state: context [ 93 | tcp-port: none 94 | ] 95 | sl4a-port/state/tcp-port: tcp-port: make port! [ 96 | scheme: 'tcp 97 | host: sl4a-port/spec/host 98 | port-id: sl4a-port/spec/port-id 99 | timeout: sl4a-port/spec/timeout 100 | ref: rejoin [tcp:// host ":" port-id] 101 | port-state: 'init 102 | json: none 103 | ] 104 | ; port/state/tcp-port now looks like this [ spec [object!] scheme [object!] actor awake state data locals ] 105 | tcp-port/awake: none 106 | open tcp-port 107 | sl4a-port 108 | ] 109 | open?: func [sl4a-port [port!]] [ 110 | sl4a-port/state 111 | ] 112 | write: func [sl4a-port [port!] data] [ 113 | if not open? sl4a-port [ 114 | open sl4a-port 115 | ] 116 | sync-write sl4a-port data 117 | sl4a-port/state/tcp-port/spec/JSON 118 | ] 119 | close: func [sl4a-port [port!]] [ 120 | close sl4a-port/state/tcp-port 121 | sl4a-port/state: none 122 | ] 123 | append: func [ sl4a-port data][ 124 | print [ "you appended " data ] 125 | ] 126 | ] 127 | ] -------------------------------------------------------------------------------- /protocols/prot-dns.r: -------------------------------------------------------------------------------- 1 | REBOL [ 2 | author: "Graham Chiu" 3 | date: 11-Jan-2010 4 | rights: 'BSD 5 | 6 | ] 7 | make-scheme [ 8 | name: 'dns2 9 | title: "DNS Protocol" 10 | spec: make system/standard/port-spec-net [port-id: 80] 11 | awake: funct [event ] [ true ] 12 | actor: [ 13 | read: func [ 14 | port [port!] 15 | /local conn 16 | ] [ 17 | if port/state [return port] 18 | if none? port/spec/host [ 19 | make error! [ 20 | type: 'Access 21 | id: 'Protocol 22 | arg1: "Missing host address" 23 | ] 24 | ] 25 | ; set the port state 26 | port/state: context [ 27 | state: 28 | connection: 29 | error: none 30 | awake: none ;:port/awake 31 | close?: no 32 | ] 33 | ; create the tcp port and set it to port/state/connection 34 | port/state/connection: conn: make port! [ 35 | scheme: 'tcp 36 | host: port/spec/host 37 | port-id: port/spec/port-id 38 | ref: rejoin [tcp:// host ":" port-id] 39 | ] 40 | conn/awake: :awake 41 | open conn 42 | wait [ conn 5 ] 43 | attempt [ get in query conn 'remote-ip ] 44 | ] 45 | ] 46 | ] -------------------------------------------------------------------------------- /protocols/prot-email.reb: -------------------------------------------------------------------------------- 1 | REBOL [ 2 | Title: "REBOL Protocols: Email Processing" 3 | Version: 2.7.6 4 | Rights: "Copyright REBOL Technologies 2008. All rights reserved." 5 | Home: http://www.rebol.com 6 | Date: 14-Mar-2008 7 | 8 | ; You are free to use, modify, and distribute this file as long as the 9 | ; above header, copyright, and this entire comment remains intact. 10 | ; This software is provided "as is" without warranties of any kind. 11 | ; In no event shall REBOL Technologies or source contributors be liable 12 | ; for any damages of any kind, even if advised of the possibility of such 13 | ; damage. See license for more information. 14 | 15 | ; Please help us to improve this software by contributing changes and 16 | ; fixes. See http://www.rebol.com/support.html for details. 17 | ] 18 | parse-header: func [ 19 | {Returns a header object with header fields and their values} 20 | parent [object! none!] "Default header object" 21 | data [any-string!] "String to parse" 22 | /multiple "Obsolete. Here for compatibility only." 23 | ][ 24 | clear invalid 25 | template: parent 26 | any [ 27 | parse data message 28 | net-error "Headers not correctly parsed" 29 | ] 30 | make either parent [parent] [object!] head-list 31 | ] 32 | 33 | mail-list-rules: make object! [ 34 | "Rough draft. Still needs some work." 35 | addr-list: 36 | addr: _ 37 | opt-cmt: ["(" thru ")" | _] 38 | mailbox: [ 39 | opt-cmt thru "<" copy addr to ">" | ; normal method 40 | ; thru "(" addr: to ")" | ; crazy old way 41 | copy addr [to "," | to ";" | to " " | to tab | to end] ; anything we got will do 42 | ] 43 | maillist: [ 44 | mailbox (append addr-list to-email addr) 45 | [[thru "," | thru ";"] maillist | none] 46 | ] 47 | parse-mail-list: func [data [string!] 48 | ][ 49 | addr-list: make block! 1 50 | parse data maillist 51 | addr-list 52 | ] 53 | ] 54 | 55 | parse-email-addrs: func [data [string! none!]] [ 56 | if none? data [return _] 57 | Mail-List-Rules/parse-mail-list data 58 | ] 59 | 60 | import-email: func [ 61 | "Constructs an email object from an email message." 62 | data [string!] "The email message" 63 | /multiple "Collect multiple fields in header" parent [object!] 64 | /local content frm 65 | ][ 66 | data: parse-header either multiple [parent][system/standard/email] content: data 67 | ; check for blocks - fixes RAMBO #3771 68 | frm: func [val /local res] [ 69 | either block? val [ 70 | either empty? val [ 71 | copy "" 72 | ] [ 73 | res: copy first val 74 | foreach addlst next val [ 75 | insert insert tail res ", " addlst 76 | ] 77 | res 78 | ] 79 | ] [ 80 | val 81 | ] 82 | ] 83 | data/date: parse-header-date either block? data/date [first data/date] [data/date] 84 | data/from: parse-email-addrs frm data/from 85 | data/to: parse-email-addrs frm data/to 86 | all [multiple data/cc: parse-email-addrs frm data/cc] 87 | all [multiple data/bcc: parse-email-addrs frm data/bcc] 88 | data/reply-to: parse-email-addrs frm data/reply-to 89 | data/content: any [data/content tail content] 90 | data 91 | ] 92 | -------------------------------------------------------------------------------- /protocols/prot-jdbcbridge.r: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | file: %prot-jdbcbridge.r 3 | author: "Graham Chiu" 4 | rights: 'LGPL 5 | date: [ 29-June-2010 3-July-2010 7-July-2010 ] 6 | version: 0.0.3 7 | changes: { 8 | metadata is returned immediately 9 | selects return the number of rows 10 | Data is only transferred on pick, or a copy 11 | eg. insert db {pick 5000} 12 | insert db {copy 100} ; this moves the cursor to the end of this query ready for another copy 13 | } 14 | notes: { 15 | sample session. 16 | 17 | db: open jdbcbridge://www.compkarori.co.nz:8020 18 | insert db [{select * from employee where full_name = (?)} "Guckenheimer, Mark"] 19 | >> print length? db 20 | 1 21 | result: pick db 1 22 | >> print length? db 23 | 0 24 | insert db [ 'tables ] 25 | insert db [ 'tables "MYTABLE" ] 26 | insert db [ 'columns "Employee" ] 27 | close db 28 | } 29 | ] 30 | 31 | digit: charset [ #"0" - #"9" ] 32 | digits: [ some digit ] 33 | space: charset [ #" " ] 34 | 35 | net-log: func [txt 36 | /C 37 | /S 38 | ] [ 39 | if C [prin "C: "] 40 | if S [prin "S: "] 41 | print txt 42 | txt 43 | ] 44 | 45 | crlfbin: to-binary crlf 46 | 47 | clear-data: func [ port ][ 48 | port/state/connection/spec/data: make binary! 0 49 | port/state/connection/data: none 50 | ] 51 | 52 | write-cmd: funct [client] [ 53 | either string? cmd: client/spec/cmd [ 54 | write client to-binary net-log/C join cmd crlf 55 | read client 56 | ] [ 57 | if block? cmd [ 58 | ; see if the first command is a word, eg: [ columns "TABLENAME" ] looking for metadata 59 | either any [word? cmd/1 lit-word? cmd/1] [ 60 | net-log "command is a word" 61 | write client to-binary net-log/C join form reduce cmd crlf 62 | ] [ 63 | ; replace the place holders 64 | foreach var reduce next cmd [ 65 | either any [string? var date? var word? var] [ 66 | replace cmd/1 "?" rejoin ["'" var "'"] 67 | ] [ 68 | replace cmd/1 "?" var 69 | ] 70 | ] 71 | write client to-binary net-log/C join cmd/1 crlf 72 | ] 73 | read client 74 | ] 75 | ] 76 | ] 77 | 78 | make-scheme [ 79 | name: 'jdbcbridge 80 | title: "JDBC Bridge Protocol" 81 | spec: make system/standard/port-spec-net [port-id: 8000] 82 | count: 0 83 | rows: 0 84 | awake: func [event /local client response state code result cmd] [ 85 | print ["=== Client event:" event/type] 86 | client: event/port 87 | switch event/type [ 88 | lookup [ 89 | net-log "DNS lookup" 90 | open client 91 | ] 92 | connect [ 93 | net-log "connected" 94 | ; send the command and let the read event copy the data back 95 | write-cmd client 96 | ] 97 | read [ 98 | net-log "read occurred" 99 | probe length? client/data 100 | comment { 101 | append client/spec/data client/data 102 | ; net-log/S to-string client/data 103 | either find/last client/data crlfbin [ 104 | client/spec/data: load enline to-string client/spec/data 105 | client/data: none ; make binary! 0 106 | net-log "received end of line marker" 107 | return true 108 | ][ 109 | read client 110 | ] 111 | } 112 | if client/spec/data = #{} [ 113 | ; grab the count 114 | probe to-string client/data 115 | charcount: rows: none 116 | if parse to-string client/data [ copy charcount digits space opt [ "rows" space copy rows digits ] to end ][ 117 | either rows [ 118 | client/spec/rows: to-integer rows 119 | ][ 120 | remove/part client/data 1 + length? charcount 121 | ] 122 | ] 123 | ; remove/part client/data 1 + length? charcount 124 | charcount: to-integer charcount 125 | ] 126 | if none? rows [ 127 | append client/spec/data client/data 128 | ] 129 | client/data: none 130 | probe length? client/spec/data 131 | if rows [ return true ] 132 | either charcount <= length? client/spec/data [ 133 | attempt [ 134 | client/spec/data: load enline to-string client/spec/data 135 | ] 136 | return true 137 | ][ read client ] 138 | ] 139 | wrote [ 140 | ; query sent, let's get the response 141 | read client 142 | ] 143 | close [ 144 | net-log "Server closed the Port" 145 | ; we should now have all the data, so it's now safe to load it 146 | client/spec/data: load enline to-string client/spec/data 147 | client/spec/close?: true 148 | return true 149 | ] 150 | ] 151 | false 152 | ] 153 | actor: [ 154 | open: func [ 155 | port [port!] 156 | /local conn 157 | ] [ 158 | if port/state [return port] 159 | if none? port/spec/host [http-error "Missing host address"] 160 | ; set the port state 161 | port/state: context [ 162 | state: 163 | connection: 164 | error: none 165 | awake: none ;:port/awake 166 | close?: no 167 | ] 168 | ; create the tcp port and set it to port/state/connection 169 | port/state/connection: conn: make port! [ 170 | scheme: 'tcp 171 | host: port/spec/host 172 | port-id: port/spec/port-id 173 | ref: rejoin [tcp:// host ":" port-id] 174 | cmd: none ; will hold the commands we send 175 | data: make binary! 0 176 | close?: no 177 | rows: none 178 | ] 179 | conn/awake: :awake 180 | open conn 181 | print "port opened ..." 182 | probe port/state/connection/spec/port-id 183 | probe port/state/connection/spec/host 184 | probe port/state/connection/spec/scheme 185 | ; return the newly created and open port 186 | port 187 | ] 188 | open?: func [ 189 | port [port!] 190 | ] [ 191 | all [port/state] 192 | ] 193 | 194 | close: func [ 195 | port [port!] 196 | ] [ 197 | if open? port [ 198 | insert port "QUIT" ; to-binary join "QUIT" crlf 199 | close port/state/connection 200 | port/state/connection/awake: none 201 | port/state: none 202 | ] 203 | port 204 | ] 205 | 206 | insert: func [ port [port!] data [string! block!]][ 207 | ; since the data is a molded rebol value we need too make sure it doesn't get corrupted 208 | clear-data port 209 | if port/state/connection/spec/close? [ 210 | ; need to re-open the port using the existing structures 211 | ; this doesn't seem to work 212 | open port/state/connection 213 | net-log "re-opened the port??" 214 | ] 215 | ; we might have opened the port but not yet waited on it 216 | either none? port/state/connection/spec/cmd [ 217 | ; no commands sent yet, so use the connect event to send 218 | port/state/connection/spec/cmd: copy data 219 | ; now wait on the port and use the connect event to send our query 220 | wait port/state/connection 221 | ][ 222 | port/state/connection/spec/cmd: copy data 223 | write-cmd port/state/connection 224 | ] 225 | wait port/state/connection 226 | ] 227 | 228 | length?: func [ port [port!] index [integer!]][ 229 | system/contexts/system/length? any [ port/state/connection/spec/data 0 ] 230 | ] 231 | 232 | pick: funct [ port [port!] index [integer!]][ 233 | either open? port [ 234 | either any [ index > length? port index <= 0 ][ 235 | none 236 | ][ 237 | data: pick port/state/connection/spec/data index 238 | remove skip port/state/connection/spec/data index - 1 239 | data 240 | ] 241 | ][ none ] 242 | ] 243 | 244 | copy: funct [ port [port!] ][ 245 | either open? port [ 246 | data: either source: port/state/connection/spec/data [ 247 | copy source 248 | ][ none ] 249 | clear-data port 250 | data 251 | ][ none ] 252 | ] 253 | ] 254 | ] 255 | -------------------------------------------------------------------------------- /protocols/prot-oldsmtp.r: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | file: %prot-smtp.r 3 | title: "Rebol 3 smtp" 4 | author: "Graham" 5 | date: [ 9-Jan-2010 20-Jan-2013 ] 6 | rights: 'BSD 7 | type: 'module 8 | name: 'smtp 9 | version: 0.0.2 10 | notes: { 11 | a working async version 12 | 13 | p: open smtp://mail.vendor.com 14 | read p ; and this should send your email as constructed below with basic authentication only supported 15 | 16 | } 17 | ] 18 | 19 | auth-methods: copy [] 20 | alpha: charset [#"a" - #"z" #"A" - #"Z"] 21 | ehlo-msg: "my-r3-developement-pc" 22 | net-log: func [txt 23 | /C 24 | /S 25 | ] [ 26 | if C [prin "C: "] 27 | if S [prin "S: "] 28 | print txt 29 | txt 30 | ] 31 | 32 | email: myemail@localisp.com 33 | recipient: myemail@gmail.com 34 | myname: "Joe Bloggs" 35 | 36 | message: rejoin [ {To: } recipient { 37 | From: } myname { <} email {> 38 | Date: Sat, 9 Jan 2010 14:51:07 +1300 39 | Subject: testing from r3 40 | X-REBOL: REBOL3 Alpha 41 | 42 | testing from r3 2}] 43 | 44 | sys/make-scheme [ 45 | name: 'smtp 46 | title: "SMTP Protocol" 47 | spec: make system/standard/port-spec-net [port-id: 25] 48 | awake: func [event /local client response state code test] [ 49 | print ["=== Client event:" event/type] 50 | client: event/port 51 | switch event/type [ 52 | lookup [ 53 | ; print "DNS lookup" 54 | open client 55 | ] 56 | connect [ 57 | net-log "connected" 58 | ; need to write to the client to trigger flow of data 59 | ; write client to-binary net-log/C rejoin ["EHLO " ehlo-msg CRLF] 60 | ; write client to-binary net-log/C rejoin [ "NOOP " crlf ] 61 | ; now ready for the next state 62 | client/spec/state: 'EHLO 63 | ; system/contexts/system/ 64 | read client 65 | ] 66 | read [ 67 | net-log/S response: enline to-string client/data 68 | code: copy/part response 3 69 | switch/default client/spec/state [ 70 | INIT [ 71 | if find/part response "220 " 4 [ 72 | ; wants me to send EHLO 73 | write client to-binary net-log/C rejoin ["EHLO " ehlo-msg CRLF] 74 | client/spec/state: 'AUTH 75 | ] 76 | ] 77 | EHLO [ 78 | if find/part response "220 " 4 [ 79 | ; wants me to send EHLO 80 | write client to-binary net-log/C rejoin ["EHLO " ehlo-msg CRLF] 81 | client/spec/state: 'AUTH 82 | ] 83 | ] 84 | AUTH [ 85 | if find/part response "220 " 4 [ 86 | ; wants me to send EHLO 87 | write client to-binary net-log/C rejoin ["EHLO " ehlo-msg CRLF] 88 | ] 89 | ; should get this massive string 90 | if code = "250" [ 91 | parse/all response [ 92 | some [ 93 | copy test to CRLF ( 94 | parse/all test [ 95 | "250" ["-" | " " (client/spec/state: first any [find auth-methods 'plain find auth-methods 'login find auth-methods 'cram])] 96 | ["AUTH" [" " | "="] 97 | [ 98 | "CRAM-MD5" (append auth-methods 'cram) | 99 | "PLAIN LOGIN" (append auth-methods 'plain) | 100 | "LOGIN" (append auth-methods 'login) | 101 | some alpha 102 | ] | 103 | some alpha 104 | ] 105 | thru CRLF 106 | ] 107 | ) crlf 108 | ] 109 | ] 110 | ] 111 | if client/spec/state != 'AUTH [ 112 | switch client/spec/state [ 113 | PLAIN [ 114 | ; not going to authenticate at present 115 | client/spec/state: 'FROM 116 | write client to-binary net-log/C rejoin ["MAIL FROM: <" email ">" CRLF] 117 | ] 118 | LOGIN [] 119 | CRAM [] 120 | ] 121 | ] 122 | ] 123 | FROM [ 124 | either code = "250" [ 125 | write client to-binary net-log/C rejoin ["RCPT TO: <" recipient ">" crlf] 126 | client/spec/state: 'TO 127 | ] [ 128 | net-log "rejected by server" 129 | return true 130 | ] 131 | ] 132 | TO [ 133 | either code = "250" [ 134 | client/spec/state: 'DATA 135 | write client to-binary net-log/C join "DATA" CRLF 136 | ] [ 137 | net-log "server rejects TO address" 138 | return true 139 | ] 140 | ] 141 | DATA [ 142 | either code = "354" [ 143 | replace/all message "^/." "^/.." 144 | write client to-binary net-log/C rejoin [ enline message crlf "." crlf ] 145 | client/spec/state: 'END 146 | ] [ 147 | net-log "Not allowing us to send ... quitting" 148 | 149 | ] 150 | ] 151 | END [ 152 | either code = "250" [ 153 | net-log "message successfully sent." 154 | client/spec/state: 'QUIT 155 | write client to-binary net-log/C join "QUIT" crlf 156 | return true 157 | ] [ 158 | net-log "some error occurred on sending." 159 | return true 160 | ] 161 | ] 162 | QUIT [ 163 | net-log "Should never get here" 164 | ] 165 | ] [net-log join "Unknown state " client/spec/state] 166 | ] 167 | wrote [read client] 168 | close [net-log "Port closed on me"] 169 | ] 170 | false 171 | ] 172 | actor: [ 173 | open: func [ 174 | port [port!] 175 | /local conn 176 | ] [ 177 | if port/state [return port] 178 | if none? port/spec/host [http-error "Missing host address"] 179 | ; set the port state 180 | port/state: context [ 181 | state: 182 | connection: 183 | error: none 184 | awake: none ;:port/awake 185 | close?: no 186 | ] 187 | ; create the tcp port and set it to port/state/connection 188 | port/state/connection: conn: make port! [ 189 | scheme: 'tcp 190 | host: port/spec/host 191 | port-id: port/spec/port-id 192 | state: 'INIT 193 | ref: rejoin [tcp:// host ":" port-id] 194 | ] 195 | conn/awake: :awake 196 | open conn 197 | print "port opened ..." 198 | ; return the newly created and open port 199 | port 200 | ] 201 | open?: func [ 202 | port [port!] 203 | ] [ 204 | all [port/state] 205 | ] 206 | 207 | close: func [ 208 | port [port!] 209 | ] [ 210 | if open? port [ 211 | close port/state/connection 212 | port/state/connection/awake: none 213 | port/state: none 214 | ] 215 | port 216 | ] 217 | 218 | read: func [ 219 | port [port!] 220 | /local conn 221 | ] [ 222 | either any-function? :port/awake [ 223 | ; unless open? port [cause-error 'Access 'not-open port/spec/ref] 224 | either not open? port [ 225 | print "opening & waiting on port" 226 | wait open port/state/connection 227 | ] [ 228 | print "waiting on port" 229 | wait port/state/connection 230 | ] 231 | port 232 | ] [ 233 | print "doing something sync" 234 | ; do something synchronous here 235 | ] 236 | ] 237 | ] 238 | ] -------------------------------------------------------------------------------- /protocols/prot-sl4a.r3: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | System: "REBOL [R3] Language Interpreter and Run-time Environment" 3 | title: "R3 SL4A" 4 | file: %prot-sl4a.r3 5 | author: ["Graham" ] 6 | name: 'sl4a 7 | type: 'module 8 | version: 0.0.2 9 | Date: [ 14-Mar-2013 16-Mar-2013 ] 10 | Purpose: "R3 send and receive from Scripting Layer 4 Android" 11 | Note: "" 12 | Description: { 13 | A synchronous protocol to send and receive messages from the SL4A server 14 | Needs JSON utils loaded first 15 | 16 | if not value? 'load-json [ 17 | do http://reb4.me/r3/altjson 18 | ] 19 | 20 | p: open sl4a://localhost 21 | result: write p [ makeToast "hello, world" ] 22 | >> ?? result 23 | result: make object! [ 24 | error: none 25 | id: 1 26 | result: none 27 | ] 28 | these are all valid blocks, order is not important 29 | [ makeToast "hello, world" ] 30 | [ 2 makeToast ["hello, world" ]] 31 | [ dialogCreateAlert [{"title", "message"}] 3] 32 | [ dialogShow ] 33 | [ [ dialogCreateAlert ["title" "message" ] 3] [ dialogShow 4]] 34 | } 35 | History: { 36 | 0.0.1 first version 37 | 0.0.2 use a dialected block as the parameter for 'write 38 | } 39 | ] 40 | 41 | make-sl4a-error: func [ 42 | message 43 | ][ 44 | do make error! [ 45 | type: 'Access 46 | id: 'Protocol 47 | arg1: message 48 | ] 49 | ] 50 | 51 | ; if params is absent, then it's an empty JSON array 52 | ; if params is a string!, then it's a single element in a JSON array 53 | ; if params is a block!, then it needs to be converted to a JSON array 54 | 55 | parse-request: funct/with [ data [block!] 56 | /local params method id template 57 | ][ 58 | params: method: id: none 59 | parse data [ 60 | some [ 61 | set params block! | 62 | set params string! | 63 | set method word! | 64 | set id integer! 65 | ] 66 | ] 67 | template: copy {{"method":"$method","params":$params,"id":$id}} 68 | id: either none? id [ ++ cnt ][ cnt: id id ] 69 | params: switch type?/word params [ 70 | string! [ mold append copy [] params ] 71 | block! [ to-json copy params ] 72 | none! [ mold [] ] 73 | ][ mold []] 74 | 75 | reword template reduce [ 76 | 'method method 77 | 'params params 78 | 'id id 79 | ] 80 | ][ cnt: 1 ] 81 | 82 | ; android-request: {{"params": ["Hello, Android!"], "id":1, "method": "makeToast"}} 83 | 84 | sl4a-awake: func [event /local port] [ 85 | print ["=== Client event:" event/type] 86 | port: event/port 87 | switch/default event/type [ 88 | error [ 89 | print "error event received" 90 | return true 91 | ] 92 | lookup [ 93 | print "DNS lookup for Android, so opening port" 94 | open port 95 | print "port opened" 96 | port/spec/state: 'ready 97 | ] 98 | connect [ 99 | print "connected " 100 | ] 101 | read [ 102 | print "reading port" 103 | ; print ["^\read:" length? port/data] 104 | port/spec/json: load-json to string! port/data 105 | return true 106 | ] 107 | wrote [ 108 | print "written, so read port" 109 | read port 110 | ] 111 | close [ 112 | print "closed on us!" 113 | return true 114 | ] 115 | ][ true ] 116 | false 117 | ] 118 | 119 | sync-write: func [ port [port!] body 120 | /local state 121 | ][ 122 | unless port/state [ open port port/state/close?: yes ] 123 | state: port/state 124 | state/connection/awake: :sl4a-awake 125 | lib/write port/state/connection to binary! join body newline 126 | unless port? wait [ state/connection port/spec/timeout ] [ make-sl4a-error "SL4A timeout" ] 127 | true 128 | ] 129 | 130 | sys/make-scheme [ 131 | name: 'sl4a 132 | title: "SL4A Protocol" 133 | spec: make system/standard/port-spec-net [port-id: 4321 timeout: 60 ] 134 | 135 | actor: [ 136 | 137 | open: func [ 138 | port [port!] 139 | /local conn 140 | ] [ 141 | if port/state [return port] 142 | if none? port/spec/host [make-sl4a-error "Missing host address"] 143 | port/state: context [ 144 | connection: 145 | error: none 146 | awake: none 147 | close?: no 148 | json: none 149 | ] 150 | port/state/connection: 151 | conn: make port! [ 152 | scheme: 'tcp 153 | host: port/spec/host 154 | port-id: port/spec/port-id 155 | timeout: port/spec/timeout 156 | ref: rejoin [tcp:// host ":" port-id] 157 | json: none 158 | state: 'init 159 | ] 160 | conn/awake: :sl4a-awake 161 | open conn 162 | port 163 | ] 164 | 165 | open?: func [port [port!]][ 166 | all [ port/state ] 167 | ] 168 | 169 | close: func [ port [port!]] [ 170 | if open? port [ close port/state/connection ] 171 | ] 172 | 173 | write: func [ 174 | port [port!] 175 | obj [block!] 176 | /local result 177 | ][ 178 | if port/state/connection/spec/state = 'init [ 179 | wait [ port 2 ] 180 | ] 181 | either all [ block? obj/1 block? obj/2 ][ 182 | result: copy [] 183 | foreach cmd obj [ 184 | sync-write port parse-request cmd 185 | append result port/state/connection/spec/json 186 | ] 187 | result 188 | ][ 189 | sync-write port parse-request obj 190 | port/state/connection/spec/json 191 | ] 192 | ] 193 | ] 194 | ] 195 | -------------------------------------------------------------------------------- /protocols/prot-time.r: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | System: "REBOL [R3] Language Interpreter and Run-time Environment" 3 | title: "R3 time scheme" 4 | file: %prot-time.r 5 | author: [ "Pavel" "Graham" ] 6 | module: 'time 7 | Date: [ 30-Dec-2010 16-Jan-2013 ] 8 | Purpose: "R3 read time from RFC868 time server" 9 | Note: "Based on Graham's example daytime scheme for R3" 10 | Description: { 11 | create Rebol3 time:// scheme, 12 | read time://time.server returns number of UTC seconds from 1-jan-1900, 13 | read/lines time://time.server returns well formated local time 14 | 15 | write time://time.nist.gov [ GMT | days | seconds | local | stamp ] 16 | } 17 | History: { 18 | 0.0.1 first version 19 | 0.0.2 added write options, removed lines option - Graham 20 | } 21 | ] 22 | 23 | sys/make-scheme [ 24 | name: 'time 25 | title: "Time Protocol" 26 | spec: make system/standard/port-spec-net [port-id: 37 timeout: 15 ] 27 | awake: func [event /local port] [ 28 | ;print ["=== Client event:" event/type] 29 | port: event/port 30 | switch event/type [ 31 | lookup [ 32 | ;print "DNS lookup" 33 | open port 34 | ] 35 | connect [ 36 | ;print "connected" 37 | read port 38 | ] 39 | read [ 40 | port/locals: to-integer port/data 41 | close port 42 | return true ; quits the awake 43 | ] 44 | wrote [read port] 45 | ] 46 | false 47 | ] 48 | 49 | 50 | actor: [ 51 | open: func [ 52 | port [port!] 53 | /local conn 54 | ] [ 55 | if port/state [return port] 56 | if none? port/spec/host [http-error "Missing host address"] 57 | port/state: context [ 58 | state: 'ready 59 | connection: 60 | error: none 61 | awake: :port/awake 62 | close?: yes 63 | ] 64 | port/state/connection: conn: make port! [ 65 | scheme: 'tcp 66 | host: port/spec/host 67 | port-id: port/spec/port-id 68 | ref: rejoin [tcp:// host ":" port-id] 69 | ] 70 | conn/awake: :awake 71 | open conn 72 | conn 73 | ] 74 | 75 | open?: func [port [port!]][ 76 | all [ port/state ] 77 | ] 78 | 79 | close: func [ port [port!]] [ 80 | if open? port [ close port ] 81 | ] 82 | 83 | write: func [ 84 | port [port!] 85 | options [block!] 86 | /local con stamp days seconds timeout date 87 | ][ 88 | timeout: port/spec/timeout 89 | con: open rejoin [tcp:// port/spec/host ":" port/spec/port-id] 90 | ; replace the default tcp awake handler with our own 91 | con/awake: :awake 92 | wait [ con timeout] 93 | if none? con/locals [ 94 | return none 95 | ] 96 | stamp: con/locals 97 | days: round/down stamp / 86400 98 | seconds: stamp // 86400 99 | date: to date! rejoin [1-Jan-1900 + days + to-time seconds + now/zone ] 100 | parse options [ 101 | [ 'GMT ( 102 | date: date - now/zone 103 | date/zone: 0 104 | ) ] | 105 | 'Local | 106 | 'Seconds ( date: seconds ) | 107 | 'Stamp ( date: stamp ) | 108 | 'Days ( date: days ) 109 | ] 110 | date 111 | ] 112 | 113 | read: func [ 114 | port [port!] 115 | /local con stamp days seconds timeout 116 | ] [ 117 | timeout: port/spec/timeout 118 | con: open rejoin [tcp:// port/spec/host ":" port/spec/port-id] 119 | ; replace the default tcp awake handler with our own 120 | con/awake: :awake 121 | wait [ con timeout] 122 | 123 | stamp: con/locals 124 | either none? stamp [ 125 | none 126 | ][ 127 | days: round/down stamp / 86400 128 | seconds: stamp // 86400 129 | rejoin [1-Jan-1900 + days + to-time seconds + now/zone ] 130 | ] 131 | ] 132 | ] 133 | ] 134 | -------------------------------------------------------------------------------- /r3-gui/developer/actors/actor-changes.mdp: -------------------------------------------------------------------------------- 1 | R3 GUI Actor/Reactor design changes 2 | 3 | Author: Richard Smolak 4 | Date: 20-Jan-2013 5 | 6 | =toc 7 | 8 | ===Introduction 9 | 10 | This document describes the changes related to the decision to simplify the current actor/reactor model. 11 | 12 | ===No more Reactors 13 | 14 | The Reactors have been completely removed from the system because we (the RMA team) agreed they make the usage of the framework confusing and not flexible enough. 15 | 16 | After the changes made to the R3GUI the programmer will need to deal only with Actors. 17 | 18 | ===Actor Overriding 19 | 20 | Here is an example how to override a style (default) actor of a face: 21 | 22 | view [ 23 | my-field: field on-key [ 24 | ;arg holds event object 25 | if arg/type = 'key [ 26 | print ["field" face/name "key:" mold arg/key] 27 | ] 28 | ] 29 | ] 30 | 31 | Running the above code you should see that the w:on-key actor has been overridden in the w:my-field face and the new code is executed instead. 32 | 33 | But now the typed characters aren't shown in the field. That's because the style w:on-key actor is not called anymore. 34 | 35 | Here is a modified code of the above example executing the style actor after the newly added code: 36 | 37 | view [ 38 | my-field: field on-key [ 39 | ;arg holds event object 40 | if arg/type = 'key [ 41 | print ["field" face/name "key:" mold arg/key] 42 | ] 43 | 44 | ;now call the FIELD style actor 45 | do-actor/style face 'on-key arg face/style 46 | ] 47 | ] 48 | 49 | This techinque is flexible enough so the programmer can call the style actor at any possible place in the new code that overrides the style actor. 50 | 51 | \note 52 | NOTES: 53 | 54 | 1. Should we introduce API function wrapper for calling the style actor in some easier way? 55 | 56 | 2. If yes, what syntax form and name should have such function wrapper? 57 | 58 | /note 59 | 60 | ===ON-ACTION actor 61 | 62 | Because the DO reactor doesn't exist in the system, the ON-ACTION actor has been added as 'system actor' for the default style terminal action. 63 | 64 | The ON-ACTION actor is useful if the style needs to call some default action from multiple places (actors) in the style definition. 65 | 66 | For example, the BUTTON style needs to call the default style action from the ON-KEY actor and also from the ON-CLICK actor, so it is better to call the ON-ACTION actor from the both code points to avoid the necessity to override multiple style actors. 67 | 68 | The ON-ACTION actor can be overridden in the layout block without the need to call the original style actor code. Here is an example: 69 | 70 | view [ 71 | button on-action [print "button pressed"] 72 | ] 73 | 74 | \note 75 | NOTES: 76 | 77 | Styles should not define the ON-ACTION actor. This way the layout programmer doesn't need to deal with any interferences. 78 | 79 | Do we need a better name for this actor? 80 | 81 | /note 82 | 83 | ===Face ATTACH mechanism 84 | 85 | The face attaching subsystem has been reworked. The ATTACH reactor doesn't exist. The ATTACH keyword has been added to the layout dialect to keep the current syntax. 86 | 87 | Summary of main changes in the subsystem: 88 | 89 | *the face/targets field contains faces that are attached FROM the face 90 | 91 | *the face/attached field contains faces that are attached TO the face 92 | 93 | *the ON-ATTACH actor is called in the target face during the time the target face is being attached from any source face. The ON-ATTACH actor is optional. 94 | 95 | for example: 96 | 97 | view [ 98 | t1: toggle "toggle 1" attach 't2 99 | t2: toggle "toggle 2" 100 | t3: toggle "toggle 3" attach 't1 101 | ] 102 | 103 | In the example above: 104 | 105 | :t1/targets - contains t2 106 | 107 | :t1/attached - contains t3 108 | 109 | :t2/attached - contains t1 110 | 111 | :t3/targets - contains t1 112 | 113 | *the attached actions are chained by default (if the default ON-ATTACHED actor is used). So if we use the example above: 114 | 115 | :pressing t1 - triggers t2 only 116 | 117 | :pressing t2 - no effect 118 | 119 | :pressing t3 - triggers t1 but since t1 is attached to t2, t2 is triggered as well 120 | 121 | *if any triggered face attaches back to the initial face in the chain, such a feedback attachment is skipped and ignored 122 | 123 | *the ON-ATTACHED actor is called in every face that is triggered in the attach reaction chain. 124 | 125 | If the ON-ATTACHED actor returns TRUE the reaction is chained. Otherwise the reaction is terminated in such face. 126 | 127 | The default ON-ATTACHED actor contains following code: 128 | 129 | on-attached: [ ;arg: dst-face no-show-flag 130 | apply :set-face [arg/1 get-face face arg/2] 131 | true 132 | ] 133 | 134 | Where the ARG is the source face that triggers the actual face. 135 | 136 | \note 137 | 138 | NOTES: 139 | 140 | 1. Are the face/targets, face/attached and other naming good enough or are there better names? 141 | 142 | 2. Any feedback to the chaining is appreciated. 143 | 144 | 3. 145 | 146 | /note 147 | 148 | ===API function changes 149 | 150 | Following table describes all API functions that have been changed, added or removed: 151 | 152 | \table 153 | Function name | 154 | state | 155 | Description || 156 | DO-FACE | 157 | changed | 158 | Function name has been reused for the changed behaviour. Now the function executes the standard action code sequence of a face. 159 | The sequence contains the code that tries to call all attached targets of the face and then the ON-ACTION terminal actor (see below) || 160 | DO-STYLE | 161 | renamed to DO-ACTOR | 162 | DO-ACTOR now tries to call the face (overriding) actor first. If the face actor is not defined it calls style actor. DO-ACTOR/STYLE calls only the specified style actor code. It can be used to mix different actor calls. || 163 | DO-TARGETS | 164 | added | 165 | This function calls DO-FACE function on all target faces (the faces that have been attached FROM the calling face). Use DO-TARGETS/CUSTOM to execute custom code instead of the DO-FACE call on every target face. || 166 | DO-ATTACHED | 167 | changed | 168 | This function calls DO-FACE function on all faces which are attached TO the calling face. Use DO-ATTACHED/CUSTOM to execute custom code before the DO-FACE call on every attached face. 169 | /table 170 | 171 | \note 172 | Should be any function name changed to better one? 173 | /note 174 | -------------------------------------------------------------------------------- /r3-gui/developer/actors/actor-overriding.mdp: -------------------------------------------------------------------------------- 1 | R3 GUI Actor overriding techniques 2 | 3 | Author: Richard Smolak 4 | Date: 20-Jan-2013 5 | 6 | =toc 7 | 8 | ===Introduction 9 | 10 | During the R3 GUI application developement there are situations where you may look for a way how to override the default functionality of an actor in a specific style. 11 | 12 | There are two possible techiques how to do it depending on your preferences. 13 | 14 | ===Overriding techniques 15 | 16 | We'll use a simple example to demonstrate both overriding techniques. Let's have the following layout: 17 | 18 | view [ 19 | field 20 | text-list [ 21 | "Robert" 22 | "Bolek" 23 | "Richard" 24 | "Ladislav" 25 | ] 26 | ] 27 | 28 | The code above shows a simple field and a list of names in a window. We want to use a matching filter on the names in the list every time the user types some character in the field. 29 | 30 | ---Overriding actor functionality using the STYLIZE function 31 | 32 | This techinque is useful in case you want to separate the newly added actor code from the layout dialect or if you plan to derive new styles based on the additional code. 33 | 34 | Here is a possible solution: 35 | 36 | stylize [ 37 | filter-field: field [ 38 | actors: [ 39 | on-key: [ 40 | ;execute the 'original' actor of FIELD style 41 | do-actor/style face 'on-key arg 'field 42 | 43 | ;apply the matching filter on my-list 44 | val: get-face face 45 | set-face/field my-list make map! either empty? val [ 46 | [1 [true]] 47 | ][ 48 | compose/deep [1 [find/match first value (val)]] 49 | ] 'filter 50 | ] 51 | ] 52 | ] 53 | ] 54 | 55 | view [ 56 | filter-field 57 | my-list: text-list [ 58 | "Robert" 59 | "Bolek" 60 | "Richard" 61 | "Ladislav" 62 | ] 63 | ] 64 | 65 | The example above works well but there is one issue. The w:my-list name is hardcoded into the definition of the new style ON-KEY actor which is not good, since it can work only in case the MY-LIST name is defined and refers to the list related to the filter field. 66 | 67 | We should refine the example to be reusable. For that purpose we can use the w:attach dialect keyword to achieve a more general and system-friendly functionality: 68 | 69 | stylize [ 70 | filter-field: field [ 71 | actors: [ 72 | on-init: [ 73 | ;execute the 'original' actor of FIELD style 74 | do-actor/style face 'on-init arg 'field 75 | ] 76 | on-key: [ 77 | ;execute the 'original' actor of FIELD style 78 | do-actor/style face 'on-key arg 'field 79 | 80 | ;apply the matching filter on the attached target face(s) 81 | foreach target select face 'targets [ 82 | if target/style = 'text-list [ 83 | val: get-face face 84 | set-face/field target make map! either empty? val [ 85 | [1 [true]] 86 | ][ 87 | compose/deep [1 [find/match first value (val)]] 88 | ] 'filter 89 | ] 90 | ] 91 | ] 92 | ] 93 | ] 94 | ] 95 | 96 | view [ 97 | filter-field attach 'my-list 98 | my-list: text-list [ 99 | "Robert" 100 | "Bolek" 101 | "Richard" 102 | "Ladislav" 103 | ] 104 | ] 105 | 106 | The above example works with any text-list face which is attached to a filter-field. Also, the filter-field can be used as a base for new styles. 107 | Notice the code used in f:stylize is also longer and more complex, because in fact we derived a new child style from the FIELD parent style. 108 | 109 | ---Inline overriding using the layout dialect 110 | 111 | Sometimes you don't want to create a new derived style. This can be handy in the following conditions: 112 | 113 | *you intend to use the changed behaviour just once, and 114 | *don't want to use the changed actor behaviour as a base for new styles 115 | 116 | Here is a possible solution: 117 | 118 | 119 | match-filter: func [ 120 | list [object!] 121 | value [string!] 122 | ][ 123 | ;apply the matching filter on my-list 124 | set-face/field list make map! either empty? value [ 125 | [1 [true]] 126 | ][ 127 | compose/deep [1 [find/match first value (value)]] 128 | ] 'filter 129 | ] 130 | 131 | view [ 132 | field on-key [ 133 | ;execute the 'original' actor of the field 134 | do-actor/style face 'on-key arg 'field 135 | ;call the filtering function 136 | match-filter my-list get-face face 137 | ] 138 | my-list: text-list [ 139 | "Robert" 140 | "Bolek" 141 | "Richard" 142 | "Ladislav" 143 | ] 144 | ] 145 | 146 | In the above code the ON-KEY word in the layout dialect means you want to override the on-key actor of the FIELD style, i.e., instead of the original actor, the given code will be evaluated. 147 | 148 | You can override any other existing actor using the same approach. The actor name is then followed by a block which is used instead of the original ON-KEY actor block defined in the FIELD style. 149 | 150 | In this case we don't mind whether the inline block contains any application specific code. 151 | 152 | Same as with the original style actor, you are free to put any code into the inline actor block. 153 | 154 | For example, you can call the original actor before or after your application-dependent code. Or even don't call the original style actor at all or chain multiple actor calls and so on. It all depends on your needs. 155 | -------------------------------------------------------------------------------- /r3-gui/developer/events/gui-event-flow.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/events/gui-event-flow.png -------------------------------------------------------------------------------- /r3-gui/developer/hierarchy/gui-hierarchy.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/hierarchy/gui-hierarchy.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-0.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-0a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-0a.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-0b.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-0b.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-1.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-2-col.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-2-col.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-2.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-2g-col.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-2g-col.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-3-col.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-3-col.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-4-col.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-4-col.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-combo-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-combo-1.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-combo-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-combo-2.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-combo-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-combo-3.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-combo-4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-combo-4.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-combo-5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-combo-5.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-group-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-group-1.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-group-1a.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-group-1a.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-show.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-show.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-sizing-1.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-sizing-1.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-sizing-2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-sizing-2.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-sizing-3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-sizing-3.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-vert.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-vert.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-layouts-visibility.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-layouts-visibility.png -------------------------------------------------------------------------------- /r3-gui/developer/layouts/graphics/gui-opinion-form.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/layouts/graphics/gui-opinion-form.png -------------------------------------------------------------------------------- /r3-gui/developer/resizing/boxmodel.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/developer/resizing/boxmodel.gif -------------------------------------------------------------------------------- /r3-gui/developer/resizing/corrections.mdp: -------------------------------------------------------------------------------- 1 | An update of the current state of R3-GUI resizing, proposing some changes. 2 | 3 | Author: Ladislav Mecir 4 | 5 | ===Resizing 6 | 7 | The resizing algorithm resizes graphic objects knowing their INIT-SIZE, MIN-SIZE and MAX-SIZE. This part hasn't changed for quite some time now. 8 | 9 | ===Autosizing 10 | 11 | For panels like vpanels, hpanels, vgroups, and hgroups it is possible to calculate their INIT-SIZE, MIN-SIZE and MAX-SIZE dimensions using the known dimensions of their contents. The same holds for the dimensions of panel columns and rows. 12 | 13 | This autosizing worked for quite some time as well, automatically calculating the needed INIT-SIZE, MIN-SIZE and MAX-SIZE of panels, their columns, and rows. 14 | 15 | ---Autosizing versus manual sizing 16 | 17 | Unfortunately, we were warned by Bolek, that sometimes it was preferable to allow the user to set the panel dimensions directly (or, at least, choose the algorithm used to calculate the panel dimensions, which may be different in some cases) e.g. by manually moving a divider between panel columns, or using other methods. 18 | 19 | ---Allowing manual sizing, instead of autosizing, the current state 20 | 21 | Therefore, we defined some variables like RESIZE = OFF (used to set the panel MIN-SIZE and MAX-SIZE to the same pair as INIT-SIZE in such a case, suppressing the panel's "ability" to resize, since such panels will not change their dimension), AUTO-SIZE = OFF (used to suppress autozing, i.e. to keep the values that were manually set). 22 | 23 | The trouble is, that these variables have been proven insufficient by Bolek this week, showing examples, which don't behave expectedly, and don't allow a simple remedy. 24 | 25 | There already were some iterations of the autosizing algorithm, reacting to Bolek's requests we found necessary to honor. 26 | 27 | ---Autosizing - proposed changes 28 | 29 | Taking into account the number of iterations of the autosizing changes, the insufficiency of the current state, and the fact, that there is no guarantee a similar "evolutionary change" would be definitely sufficient, I propose a completely different, and hopefully much more flexible alternative as follows: 30 | 31 | *all "autosized dimensions" will always be calculated, but using so-called "hint variables" (already implemented in case of panel columns, where Cyphre wanted three different algorithms and their combinations to be used for column size calculation), to explain, why it will work, notice, that one of the possible algorithms used shall be the 'keep algorithm meaning, that the current value(s) are kept, instead of being truly recalculated 32 | *the user, instead of setting the INIT-SIZE, MIN-SIZE and MAX-SIZE attributes, that will be "always calculated" for panels, their rows and columns, shall, in case of hpanels, vpanels, hgroups, vgroups, and in case of their rows/columns always use the "hint variables", which will allow him to either specify the algorithm used to calculate the corresponding size attribute, or even specify the value to use "directly" to copy to the size attribute from the hint variable 33 | 34 | +++Advantages 35 | 36 | This proposal will allow using and specifying of any number of different autosizing algorithms, as well as direct setting of all size attributes the user wishes to set directly, so, this is a "future proof" approach. 37 | 38 | +++Disadvantages 39 | 40 | Since the flexibility is so high, in some cases, the user might find out he is able to set more attributes than he even cares to know. Nevertheless, due to our experiences with requests to allow manual settings of "unexpected attributes", this looks like the only proper way to go. 41 | 42 | ===Resizing quirks found recently 43 | 44 | Originally, the INIT-SIZE of any object was assumed to be in the range between the object's MIN-SIZE and MAX-SIZE. Due to the requirements/results of manual resizing, it occurred to be necessary to relax the relation, allowing the INIT-SIZE to be smaller than MIN-SIZE, or greater than MAX-SIZE, where appropriate. This may especially occur during manual resizing (divider moving), where the INIT-SIZE is recalculated for an object, which may already be resized (minified or magnified several times). In such case, the recalculated INIT-SIZE cannot be guaranteed to stay between the object's MIN-SIZE and MAX-SIZE values. 45 | 46 | ---Proposed resizing change 47 | 48 | It appears to be necessary to relax the relation between MIN-SIZE, MAX-SIZE and INIT-SIZE, thus, using a slightly different algorithm not relying on INIT-SIZE being in the specified range. 49 | 50 | The last research shows, that the algorithm will stay very similar, although a bit more complicated. The memory consumption will remain the same, the speed is expected to be a bit smaller, but not in a substantial way. 51 | 52 | The end. -------------------------------------------------------------------------------- /r3-gui/license/rla.txt: -------------------------------------------------------------------------------- 1 | REBOL License Agreement (RLA) 2 | 3 | DRAFT Jan 2010 4 | This document is still in the review and revision stage. 5 | 6 | PRELIMNARY 7 | 8 | This is the current license agreement for REBOL 3. The intention is to clarify how you can use, publish, and distribute REBOL 3. 9 | 10 | It's quite possible, likely in fact, that a better license agreement may be found (perhaps even one from the www.opensource.org, if we can find one that works for us.) 11 | 12 | Therefore, we reserve the right to modify this agreement in the future. However, we will keep all prior versions archived, so if you desire, you can refer to a specific version within your code as the license that you used. 13 | 14 | Purpose 15 | 16 | The purpose of this agreement is to provide open source software modules (SOURCE) for the mutual benefit of the REBOL community (RC), its users (MEMBERS), and REBOL Technologies (RT), and to define the terms and conditions for the use and distribution of this software. 17 | 18 | The SOURCE is combined with the REBOL Library (LIBRARY) to construct the REBOL Language program (EXECUTABLE). The term SOFTWARE herein refers to the SOURCE, LIBRARY, and EXECUTABLE separately or in combination. 19 | 20 | The SOURCE along with additional source can be combined with the REBOL Library (LIBRARY) to construct an application program (APPLICATION). 21 | 22 | We would like to encourage developers to contribute to the SOURCE and to help test and debug the EXECUTABLE, and to create and publish high quality APPLICATION programs. 23 | 24 | The term USE herein means to use, copy, modify, extend, compile, develop, build, publish, distribute, bundle, and sell. 25 | 26 | Specific Terms 27 | 28 | 1. The copyrights, ownership rights, and all other proprietary rights (national and international) of the SOURCE, LIBRARY, and EXECUTABLE belong to RT. 29 | 2. RT is the official archive, publisher, and distributor of the SOURCE, LIBRARY, and EXECUTABLE. 30 | 3. MEMBERS and RT can USE the SOURCE and EXECUTABLE free-of-charge for commercial, non-commercial, and educational APPLICATIONS. 31 | 4. MEMBERS can include the LIBRARY as a linker-resolved component of their their APPLICATIONS free-of-charge, except as specifically excluded within the terms of this license. 32 | 5. All titles, copyright and license notices, file names, credits, and disclaimers must remain as-is without modification within the SOFTWARE. 33 | 6. All SOURCE modifications contributed by MEMBERS are free contributions for the benefit of the RC and RT. MEMBERS transfer all rights, including all international copyrights and proprietary rights, to RT under the same terms of this agreement. 34 | 7. This agreement does not require the contribution or publication of modifications. Both MEMBERS and RT are free to develop, use, publish, distribute, and sell proprietary APPLICATIONS for their own benefit, and the SOURCE and EXECUTABLE of such can be kept private. 35 | 8. RT holds the exclusive worldwide rights to publish, distribute, sell, or otherwise license the SOFTWARE as a computer language system or product, and MEMBERS may not do so without a separate license agreement. 36 | 9. To USE the SOFTWARE as one of the primary components of any hardware device is not included in this agreement and requires a separate licensing agreement from RT. 37 | Warranty and Liability 38 | 39 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. 40 | 41 | IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 42 | 43 | Other 44 | 45 | This agreement is governed by the laws of California and the USA. 46 | 47 | If any provision of this license is invalid or unenforceable under applicable law, it shall not affect the validity or enforceability of the remainder of the terms. -------------------------------------------------------------------------------- /r3-gui/license/rlanotes.txt: -------------------------------------------------------------------------------- 1 | Brian Hawley's RLA notes 2 | 3 | There were some problems in 6, when combined with 8 and 9. 8 and 9 also violate the "open source" definition, and thus the trademark. 4 | 5 | "MEMBERS transfer all rights, including all international copyrights and proprietary rights, to RT under the same terms of this agreement." needs to be more of a license than a transferral, explicitly not taking rights away from the original authors. And 8 and 9 need to refer to the LIBRARY and EXECUTABLE but not the SOURCE. 6 | 7 | 8 and 9 could be left as-is if the definition of SOFTWARE above had the word SOURCE removed from it. 8 | 9 | Note that if 6 is changed to a contribution license, 1 needs to be changed to match. 10 | -------------------------------------------------------------------------------- /r3-gui/specs/dialogs/dialog01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/dialogs/dialog01.png -------------------------------------------------------------------------------- /r3-gui/specs/dialogs/dialog02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/dialogs/dialog02.png -------------------------------------------------------------------------------- /r3-gui/specs/other/attaching.mdp: -------------------------------------------------------------------------------- 1 | Face attaching 2 | 3 | Boleslav Brezovsky 4 | 5 | ===Introduction 6 | 7 | In R3GUI it's possible to attach one face to another. Attached face can control some aspects of target face 8 | 9 | ===Usage - styles 10 | 11 | ---Attached face 12 | 13 | Attaching is initialised in *ON-INIT* actor of the attached face. ON-INIT contains typically this lines: 14 | 15 | on-init: [ 16 | if target: find-face-actor/reverse face 'on-validate [ 17 | append-face-act face reduce ['validate target] 18 | do-style target 'on-attach face 19 | ] 20 | ] 21 | 22 | (example from INDICATOR style) 23 | 24 | Explanation: 25 | 26 | * FIND-FACE-ACTOR/REVERSE will go back thru collection of faces to find nearest face that has ON-VALIDATE actor. 27 | 28 | * When the face is found, new reactor is added to attached face, VALIDATOR in this case, with target face as parameter. 29 | 30 | * The target face is then notified that new face is attaching, that's done by calling the ON-ATTACH actor. 31 | 32 | Right now, attached face has established its binding to the target face, but we also need to do some maintenance in the target face. That's what we got *ON-ATTACH* actor for. 33 | 34 | ---Target face 35 | 36 | +++ON-ATTACH 37 | 38 | *ON-ATTACH* actor of the target face is called right from the *ON-INIT* actor of the attached face. Typical *ON-ATTACH* actor looks like this: 39 | 40 | on-attach: [ ; arg: scroller 41 | extend-face face 'attached arg 42 | ] 43 | 44 | (example from HGROUP style) 45 | 46 | This actor adds attached face to ATTACHED "facet" of target face (it's not facet as it is directly in FACE). It also sets default value for the ATTACHED face but that should probably depend on the attached face type. 47 | 48 | +++ON-ATTACHED 49 | 50 | Sometimes, we need to notify attached faces that they should do their work. For example in text style, when you press a key, if there's scroller, it's size may have changed, the validity of text in style may have changed and has to be checked again, etc. This is done using ON-ATTACHED actor that should be called from inside target face's actors (there's no single point where to do this - not every change requires running attached reactors, so it's on style designer to decide when to do this). 51 | 52 | on-attached: [ 53 | if faces: select face 'attached [ 54 | foreach f faces [ 55 | do-face f 56 | ] 57 | ] 58 | ] 59 | 60 | *ON-ATTACHED* check if there are some attached faces and when yes, it runs their reactors. 61 | 62 | However the truth is, that not all required informations can be obtained using automated methods. For example different scrolling method must be used for TEXT styles and PANEL styles. That's the reason why attached face calls actors in target face to do required job. But calling that particular actor requires that attached face has already right value set. 63 | 64 | So the problem here is, that we must set this value manually in the on-attached actor as currently there's now known method how to make this abstract. If some universal method can be found, this stuff can be moved out without impact on styles compatibility as the interface will stay same. 65 | 66 | Example ON-ATTACHED actor: 67 | 68 | 69 | 70 | 71 | ---Notes 72 | 73 | 74 | 75 | ===Usage - layout -------------------------------------------------------------------------------- /r3-gui/specs/other/gob-capture.mdp: -------------------------------------------------------------------------------- 1 | R3 GUI GOB Capture 2 | 3 | Author: Henrik Mikael Kristensen 4 | Type: Specification Document 5 | Date: 31-Jan-2011 6 | 7 | ===Premise 8 | 9 | For documentation purposes, it's necessary to have the R3 GUI create screenshots of the GUI to be saved in PNG format. This is also something that can be useful in the case of sending bug reports. 10 | 11 | The idea is that screenshots in documentation and bug reports should be as automated a process as possible, so goals are: 12 | 13 | # Avoid having to use 3rd party screenshot applications. 14 | 15 | # Store screenshots internally as image! for later processing. 16 | 17 | # Save files in PNG format using media savers or whatever is available. 18 | 19 | ===Some Technical Details 20 | 21 | # Avoid having the need to have the GUI element being captured being visible. 22 | 23 | # Allow capture of any GOB or tree of GOBs in any REBOL 3 window. 24 | 25 | # Allow also capturing separate screen GOBs, such as popups over windows that exist in a separate window at their correct positions relative to each other. 26 | 27 | ===Later possibilities 28 | 29 | These are for extended options. I don't expect that this is something we want directly inside the R3 GUI. 30 | 31 | # When capturing a whole window, create a fake window frame around it 32 | 33 | # Annotation of images with speech bubbles, arrows, frames, circles, etc. as an extension of the screenshot. 34 | -------------------------------------------------------------------------------- /r3-gui/specs/other/r3-gui-snippets.mdp: -------------------------------------------------------------------------------- 1 | R3 GUI Tipps & Tricks 2 | Author: Robert M. Münch 3 | Type: User Documentation 4 | Date: 09-Feb-2011 5 | 6 | =toc 7 | 8 | ===Introduction 9 | This document is a collection of how-tos, tipps & tricks, snippets that helps to get started with R3-GUI. As soon as the concepts and descriptions here get to big, the information is seperated into its own document. 10 | 11 | ===Actors & Re-Actors 12 | view [button "test" on-key [do [print mold value]]] 13 | 14 | ===Triggers 15 | You can use custom triggers in R3-GUI. Example of custom trigger: 16 | 17 | view [ 18 | when [my-trigger] do [print "my trigger has been called"] 19 | button "run my trigger" do [ 20 | if win: window-face? face [ 21 | do-triggers win 'my-trigger 22 | ] 23 | ] 24 | ] 25 | 26 | ===Showing layouts 27 | 28 | ---How to do a layout but don't show 29 | Couple of posibilities: 30 | #use VIEW/NO-WAIT and later than DO-EVENTS 31 | #use WHEN with triggers like: 32 | view [ 33 | button 34 | ... 35 | when [enter] do [print "layout has been created"] 36 | ] 37 | #use MAKE-FACE like: 38 | lay: [button ...] 39 | layout: make-face 'window reduce/no-set [content: lay] 40 | view layout 41 | 42 | -------------------------------------------------------------------------------- /r3-gui/specs/other/save-state.mdp: -------------------------------------------------------------------------------- 1 | Save state 2 | 3 | Boleslav Brezovsky 4 | 5 | ===Introduction 6 | 7 | Each style must be able to save and load its state. Faces have to sets of proprieties. One controls visual appearance and second controls functionality(?). 8 | 9 | The visual appearance is controlled mostly by values in FACETS and usually can be set directly. 10 | 11 | Functional proprieties are typically in STATE and shouldn't be set directly. 12 | 13 | However, the boundary here is blurred and depends on each's taste. There cannot be definitive distincion between each group but we can define each group for each style. 14 | 15 | ---Implementation 16 | 17 | It is expected that each save should be able to store all relevant informations using GET-FACE/STATE and be able to reconstruct itself using SET-FACE/STATE. As relevant are considered informations like TEXT-BODY in text styles, caret settings, but not font settings. 18 | 19 | ===Notes 20 | 21 | ---FACETS vs. STATE 22 | 23 | Values in FACETS control visual appearance mostly. However it's true that values in layout - specified in OPTIONS - are collected into FACETS during initialisation phase (ON-MAKE, ON-INIT). Because the style should exhibit uniform behaviour, it's not desirable to process values collected during layout phase differently from user input that may come later from GUI or API, so ON-INIT should make only basic initialisation of style and values should be processed by standard ON-SET. 24 | 25 | This however introduces some problems. Some things are not known during ON-INIT, like size. These values are calculated later, during ON-RESIZE and some code that may be expected to be in ON-SET must be moved to ON-RESIZE. On the other hand, this code is needed to be run not only in resize but also when new values are set with ON-SET, which creates interesting loop of requirements. 26 | 27 | There it's good idea to move part of this code into new actor, for example ON-UPDATE-FACE (because ON-UPDATE is taken already - on-update runs before on-resize and cannot be used in our case.) *** check if really true 28 | 29 | so we have this three situations (on-update is ignored here): 30 | 31 | +++DATA from LAYOUT (not sure about on-make) 32 | 33 | 1. ON-INIT does basic initialisation 34 | 35 | 2. ON-INIT calls ON-SET (or SET-FACE) to set starting value 36 | 37 | 3. ON-SET uses value (but not everything can be done here, size is not set etc.) 38 | 39 | 4. ON-SET finished and returns, 40 | 41 | 5. ON-INIT finished and returns, 42 | 43 | 6. ON-UPDATE is called and 44 | 45 | 7. ON-RESIZE is called by ON-UPDATE and 46 | 47 | 8. ON-UPDATE-TABLE is called by ON-RESIZE. 48 | 49 | 9. All actors ends and the code continues. 50 | 51 | 52 | What's important here is that ON-SET somehow cannot call ON-UPDATE-TABLE... 53 | 54 | What abput ON-DRAW??? -------------------------------------------------------------------------------- /r3-gui/specs/resizing/resizing-shortcuts.mdp: -------------------------------------------------------------------------------- 1 | High level management of MIN-SIZE, MAX-SIZE and INIT-SIZE 2 | 3 | Author: Henrik Mikael Kristense 4 | Type: Specification Document 5 | Date: 17-mar-2011 6 | 7 | =todos 8 | 9 | =toc 10 | 11 | ===Introduction 12 | 13 | The creator of styles are faced with three pairs: MIN-SIZE, MAX-SIZE and INIT-SIZE, each sizes that may need to be defined for a style to work as intended. 14 | 15 | A noted side effect is that many small faces contain an identical value in one direction, usually vertically, for all three values. This reveals certain usage patterns that can be shortened into specific actions. 16 | 17 | Example of using explicit sizes to create a face that does not resize at all vertically: 18 | 19 | bar: box [ 20 | about: "Simple horizontal divider bar." 21 | facets: [ 22 | init-size: 1x2 23 | min-size: 1x2 24 | max-size: -1x2 25 | ] 26 | ] 27 | 28 | A derivative that tries not to destruct size information from the parent: 29 | 30 | box: [ 31 | about: "Simple box" 32 | facets: [ 33 | init-size: 100x100 34 | max-size: guie/max-coord 35 | ] 36 | ] 37 | 38 | bar: box [ 39 | about: "Simple horizontal divider bar." 40 | facets: [ 41 | init-size: 1x2 42 | min-size/y: init-size/y 43 | max-size/y: init-size/y 44 | ] 45 | ] 46 | 47 | This can be simplified. 48 | 49 | ===FLEX 50 | 51 | The idea of FLEX requires two values passed, one for each direction, so here, three methods are presented, one with pairs, one with words and one with blocks. 52 | 53 | --- Pair Notation 54 | 55 | FLEX takes a pair and performs one of two operations of MIN-SIZE and MAX-SIZE: 56 | 57 | # If the value is *-1*, the direction will not resize at all. This happens by setting the MIN-SIZE and MAX-SIZE identical to INIT-SIZE for that direction. 58 | 59 | # If the value is *0*, the direction will not be touched and the existing INIT-SIZE, MIN-SIZE and MAX-SIZE values will not be altered. 60 | 61 | # If the value is *1*, the direction will infinitely resize, by setting the MAX-SIZE to GUIE/MAX-COORD for that direction. 62 | 63 | Example, for a box that flexes infinitely and a derived bar that flexes horizontally only: 64 | 65 | box: [ 66 | about: "Simple box" 67 | facets: [ 68 | init-size: 100x100 69 | flex: 1x1 70 | ] 71 | ] 72 | 73 | A derived bar that flexes horizontally only: 74 | 75 | bar: box [ 76 | about: "Simple horizontal divider bar." 77 | facets: [ 78 | init-size: 1x2 79 | flex: 1x-1 80 | ] 81 | ] 82 | 83 | Layout examples removes the need to know anything about sizes in order to produce the desired effect and are easier to read: 84 | 85 | view [box options [max-size: as-pair guie/max-coord 2]] ; the number 2 is necessary knowledge. MAX-COORD is necessary knowledge. 86 | 87 | view [box options [max-size/x: guie/max-coord/x]] ; this is not possible, currently 88 | 89 | view [box options [flex: 0x-1]] ; no previously stated sizing numbers are necessary to know 90 | 91 | --- Word Notation 92 | 93 | Using word notation may be easier to read, but may in this form be too easy to produce illegal char combinations. 94 | 95 | \table header 96 | 97 | Word|X resize|Y resize|Action|| 98 | none!|None|None|Set MIN-SIZE and MAX-SIZE to INIT-SIZE.|| 99 | 'x|Infinite|None|Set MAX-SIZE/X to GUIE/MAX-COORD/X and set MIN-SIZE/Y and MAX-SIZE/Y to INIT-SIZE/Y.|| 100 | 'y|None|Infinite|Set MAX-SIZE/Y to GUIE/MAX-COORD/Y and set MIN-SIZE/X and MAX-SIZE/X to INIT-SIZE/X.|| 101 | 'xy|Infinite|Infinite|Set MAX-SIZE to GUIE/MAX-COORD.|| 102 | 'h|Restricted|None|Set MIN-SIZE/Y and MAX-SIZE/Y to INIT-SIZE/Y. MIN-SIZE/X, MAX-SIZE/X and INIT-SIZE/X are untouched.|| 103 | 'v|None|Restricted|Set MIN-SIZE/X and MAX-SIZE/X to INIT-SIZE/X. MIN-SIZE/Y, MAX-SIZE/Y and INIT-SIZE/Y are untouched.|| 104 | 'hv|Restricted|Restricted|MIN-SIZE, MAX-SIZE and INIT-SIZE are untouched.|| 105 | 'hy|Restricted|Infinite|Set MAX-SIZE/Y to GUIE/MAX-COORD/Y and everything else untouched.|| 106 | 'xv|Infinite|Restricted|Set MAX-SIZE/X to GUIE/MAX-COORD/X and everything else untouched. 107 | /table 108 | 109 | Example, for a box that flexes infinitely: 110 | 111 | box: [ 112 | about: "Simple box" 113 | facets: [ 114 | init-size: 100x100 115 | flex: 'xy 116 | ] 117 | ] 118 | 119 | A box that flexes horizontally and is restricted vertically. 120 | 121 | box: [ 122 | about: "Simple box" 123 | facets: [ 124 | init-size: 100x100 125 | min-size/y: 50 126 | max-size/y: 200 127 | flex: 'xv 128 | ] 129 | ] 130 | 131 | A derived bar that flexes horizontally only: 132 | 133 | bar: box [ 134 | about: "Simple horizontal divider bar." 135 | facets: [ 136 | init-size: 1x2 137 | flex: 'x 138 | ] 139 | ] 140 | 141 | Layout example: 142 | 143 | view [box options [flex: 'x]] 144 | 145 | --- Block notation 146 | 147 | This performs one action per word and stores words in a block. Combinations are easier to figure out. 148 | 149 | The default here is important: 150 | 151 | By default, the value could be none! or an empty block, so it would provide no resizing in any direction. Then you would open up resizing, by providing words: 152 | 153 | \table header 154 | 155 | Value|Directional Resize|Action|| 156 | none!|None|Set MIN-SIZE and MAX-SIZE to INIT-SIZE.|| 157 | empty block!|None|Set MIN-SIZE and MAX-SIZE to INIT-SIZE.|| 158 | 'x|Infinite X|Set MAX-SIZE/X to GUIE/MAX-COORD/X.|| 159 | 'y|Infinite Y|Set MAX-SIZE/Y to GUIE/MAX-COORD/Y.|| 160 | 'h|Restricted X|Set MIN-SIZE/Y and MAX-SIZE/Y to INIT-SIZE/Y.|| 161 | 'v|Restricted Y|Set MIN-SIZE/X and MAX-SIZE/X to INIT-SIZE/X. 162 | /table 163 | 164 | This will be easier to derive new values from or to investigate, but might be slower to process and eats more memory? 165 | 166 | Example, for a box that flexes infinitely: 167 | 168 | box: [ 169 | about: "Simple box" 170 | facets: [ 171 | init-size: 100x100 172 | flex: [x y] 173 | ] 174 | ] 175 | 176 | A box that flexes horizontally and is restricted vertically. 177 | 178 | box: [ 179 | about: "Simple box" 180 | facets: [ 181 | init-size: 100x100 182 | min-size/y: 50 183 | max-size/y: 200 184 | flex: [x v] 185 | ] 186 | ] 187 | 188 | A derived bar that flexes horizontally only: 189 | 190 | bar: box [ 191 | about: "Simple horizontal divider bar." 192 | facets: [ 193 | init-size: 1x2 194 | flex: [x] 195 | ] 196 | ] 197 | 198 | Words that conflict would be overwritten. This case results in an infinitely flexing box: 199 | 200 | box: [ 201 | about: "Simple box" 202 | facets: [ 203 | init-size: 100x100 204 | min-size/y: 50 205 | max-size/y: 200 206 | flex: [h x v y] 207 | ] 208 | ] 209 | 210 | Layout example: 211 | 212 | view [box options [flex: [x]]] 213 | 214 | ===HINT 215 | 216 | =todo Please fill out any specs regarding HINT management here, if needed. 217 | -------------------------------------------------------------------------------- /r3-gui/specs/resizing/resizing.rmd: -------------------------------------------------------------------------------- 1 | Tab-box 2 | 3 | Author: Boleslav Brezovsky 4 | Date: 9-6-2010 5 | 6 | ===Introduction 7 | 8 | This documents covers resizing/initialisation flow in current R3/GUI. 9 | 10 | PM - %panel-make.r3 11 | PS - %panel-sizing.r3 12 | PL - %panel-layout.r3 13 | 14 | ===Simple layout 15 | 16 | simple layout is used for testing: 17 | 18 | view [button "hello world"] 19 | 20 | ---Flow 21 | 22 | +++Initialisation 23 | 24 | PM/make-panel... 25 | PM/init-panel... 26 | PS/make-panel-grid 27 | PS/collect-sizes... 28 | end 29 | PS/total-spacing? 30 | PS/resize-panel... 31 | PL/layout-panel... 32 | end 33 | end 34 | end 35 | end 36 | 37 | +++Resize 38 | 39 | Once everything is initialised and we resize the window, we got this chain of operations: 40 | 41 | PS/resize-panel... 42 | PL/layout-panel... 43 | end 44 | end 45 | 46 | ===Complex layout 47 | 48 | This is more complex layout using two groups: 49 | 50 | view [ 51 | panel [button "Hello world" field] 52 | group 2 [text-area scroller scroller] 53 | ] 54 | 55 | ---Flow 56 | 57 | +++Initialisation 58 | 59 | PM/make-panel... 60 | PM/init-panel... 61 | PS/make-panel-grid 62 | PM/make-panel2... 63 | PM/init-panel... 64 | PS/make-panel-grid 65 | PS/collect-sizes... 66 | end 67 | PS/total-spacing? 68 | PS/resize-panel... 69 | PL/layout-panel... 70 | end 71 | end 72 | end 73 | end 74 | PM/make-panel2... 75 | PM/init-panel... 76 | PS/make-panel-grid 77 | PS/collect-sizes... 78 | end 79 | PS/total-spacing? 80 | PS/resize-panel... 81 | PL/layout-panel... 82 | end 83 | end 84 | end 85 | end 86 | PS/collect-sizes... 87 | end 88 | PS/total-spacing? 89 | PS/resize-panel... 90 | PL/layout-panel... 91 | PS/resize-panel... 92 | PL/layout-panel... 93 | end 94 | end 95 | PS/resize-panel... 96 | PL/layout-panel... 97 | end 98 | end 99 | end 100 | end 101 | end 102 | end 103 | 104 | +++Resize 105 | 106 | PS/resize-panel... 107 | PL/layout-panel... 108 | PS/resize-panel... 109 | PL/layout-panel... 110 | end 111 | end 112 | PS/resize-panel... 113 | PL/layout-panel... 114 | end 115 | end 116 | end 117 | end -------------------------------------------------------------------------------- /r3-gui/specs/resizing/shortcut-notes.mdp: -------------------------------------------------------------------------------- 1 | Notes to the %resizing-shortcuts.mdp document 2 | 3 | Author: Ladislav Mecir, Richard Smolak 4 | Date: 18-Mar-2011/8:06:42+1:00 5 | 6 | ===Introduction 7 | 8 | Henrik had a nice idea to "throw in" three examples for comparison purposes. Let' see them: 9 | 10 | ---Simple horizontal divider bar 11 | 12 | bar: box [ 13 | about: "Simple horizontal divider bar." 14 | facets: [ 15 | init-size: 1x2 16 | min-size: 1x2 17 | max-size: -1x2 18 | ] 19 | ] 20 | 21 | The code is incorrect. In our opinion, the correct code was meant to be: 22 | 23 | bar: box [ 24 | about: "Simple horizontal divider bar." 25 | facets: [ 26 | init-size: 1x2 27 | min-size: 1x2 28 | max-size: as-pair 1 guie/max-coord 29 | ] 30 | ] 31 | 32 | ---Simple box 33 | 34 | Henrik wrote: "A derivative that tries not to destruct size information from the parent:" 35 | 36 | We do not understand what is meant by "tries not to destruct...". 37 | 38 | box: [ 39 | about: "Simple box" 40 | facets: [ 41 | init-size: 100x100 42 | max-size: guie/max-coord 43 | ] 44 | ] 45 | 46 | The code is incorrect. In our opinion, the correct code was meant to be: 47 | 48 | box: [ 49 | about: "Simple box" 50 | facets: [ 51 | init-size: 100x100 52 | ] 53 | ] 54 | 55 | ---Button 56 | 57 | Button in R3-GUI has the following dimensions: 58 | 59 | init-size: 130x24 60 | min-size: 24x24 61 | max-size: 260x24 62 | 63 | ---Panels 64 | 65 | In the case of panels the INIT-SIZE, MIN-SIZE and MAX-SIZE are calculated after every content change. Thus, to allow the user to influence these, the Hint dialect was designed. As opposed to the above Flex dialect, the Hint dialect is usable to influence every of the above panel dimensions in an unrestricted way, which was found to be necessary. 66 | 67 | ---Text and other styles with calculated dimensions 68 | 69 | In case of the text style, the INIT-SIZE, MIN-SIZE and MAX-SIZE dimensions are calculated after every content change. Thus, a way how to influence the result of the calculation is needed as well for the text style and similar styles. The Hint dialect is suitable for this allowing the user to adjust any available dimension. 70 | 71 | ===Flex 72 | 73 | ---Pair notation 74 | 75 | This notation uses some arbitrary numbers, that are not readable without documentation. 76 | 77 | In our opinion, the users are likely to make errors in them, since the meaning is not obvious. Moreover, such errors are hard to detect, due to the non-obvious meaning. 78 | 79 | +++Simple box 80 | 81 | box: [ 82 | about: "Simple box" 83 | facets: [ 84 | init-size: 100x100 85 | flex: 1x1 86 | ] 87 | ] 88 | 89 | Comparing this example to the code in the "Introduction" section we prefer the one in there, since it is: 90 | 91 | *shorter 92 | *simpler 93 | 94 | +++Simple horizontal divider bar. 95 | 96 | bar: box [ 97 | about: "Simple horizontal divider bar." 98 | facets: [ 99 | init-size: 1x2 100 | flex: 1x-1 101 | ] 102 | ] 103 | 104 | When compared to the example in the "Introduction" section it spares one line, i.e. it is shorter, but much more cryptic at the same time. 105 | 106 | +++Button 107 | 108 | The current button style cannot be defined using the Flex dialect. 109 | 110 | +++Panels 111 | 112 | While the Hint dialect has been found necessary (see the reasons above), the introduction of an incompatible Flex dialect does not help to simplify the situation of the user, which is forced to learn a new dialect even when: 113 | 114 | * the Flex dialect does not allow him to set all the properties demonstrated in the r3-gui/tests/panels/ examples 115 | * the Flex dialect does not make the code more readable 116 | 117 | +++Text and other styles with calculated dimensions 118 | 119 | The same objections as for panels apply. 120 | 121 | +++Layout examples 122 | 123 | ...Box example 124 | 125 | In the code example: 126 | 127 | view [box options [max-size: as-pair guie/max-coord 2]] 128 | ; the number 2 is necessary knowledge. MAX-COORD is necessary knowledge. 129 | 130 | , the comment is misleading. For the box style defined above the example can be: 131 | 132 | view [box] 133 | 134 | No Flex dialect can make this code simpler or shorter. 135 | 136 | ...Second box example 137 | 138 | In the example 139 | 140 | view [box options [max-size/x: guie/max-coord/x]] 141 | ; this is not possible, currently 142 | 143 | The comment is correct. This does not work, because the REDUCE/SET function is used to process the options. 144 | 145 | However, this code works: 146 | 147 | view [box options [max-size: guie/max-pair]] 148 | 149 | Compared to the Flex example it is roughly of the same length, and it looks less cryptic, since: 150 | 151 | *it does not use arbitrary numbering 152 | *it does not require the knowledge of a new dialect 153 | 154 | ---Word notation 155 | 156 | Henrik stated: "... word notation may be easier to read, but may in this form be too easy to produce illegal char combinations." 157 | 158 | We do agree with this objection and consider it serious. 159 | 160 | We don't like the word notation. Why X, Y should mean 'unlimited' and W,H 'restricted'... We don't think such a dialect would make the life of a style or layout writer easier. 161 | 162 | ===Other problems of the proposal 163 | 164 | We are worried, that this additional layer will unnecessarily slow down the system, because if Flex is defined in the face style, the init/min/max settings would need to be recalculated on every resize although currently this recalc is not really neccessary. Such a recalculation would in fact be disastrous for the performance of the resizing algorithm for (h/v)panel as well as the resizing algorithm for (h/v)group. 165 | 166 | ===Summary 167 | 168 | The most serious problems of the proposed Flex dialect are, that it is incompatible with: 169 | 170 | *the way how the dimensions of panels and groups are calculated 171 | *the way how the dimensions of buttons are currently specified 172 | *the way how the dimensions of text and other styles with calculated dimensions will be specified 173 | 174 | Takíng all the above disadvantages and the comparisons of the examples into account we do not recommend to use the dialect. -------------------------------------------------------------------------------- /r3-gui/specs/styles/gen-style-docs.r3: -------------------------------------------------------------------------------- 1 | REBOL [ 2 | Title: "REBOL 3 GUI - Style Tree" 3 | Author: ["Didier Cadieu" "Henrik Mikael Kristensen"] 4 | ] 5 | 6 | ; Find some way to run this regularly and automatically. 7 | 8 | ; use our GUI version 9 | do %../../original-vid34-patches/gui-load.r3 10 | 11 | styles: words-of guie/styles 12 | 13 | out: "" 14 | 15 | emit: func [o] [append out reform o append out newline] 16 | 17 | emit ["VID3.4 Style List" newline] 18 | emit ["Generated on" now "using REBOL 3 version" system/version newline] 19 | 20 | foreach st styles [ 21 | 22 | emit ["===" guie/styles/:st/name newline] 23 | emit ["Parent:" guie/styles/:st/parent newline] 24 | emit ["Description:" guie/styles/:st/about newline] 25 | emit ["Options:" mold words-of guie/styles/:st/options newline] 26 | 27 | ] 28 | 29 | write %style-list.rmd to-binary out 30 | if exists? %../../../r3-alpha [ 31 | write %../../../r3-alpha/files/Users/Henrik/style-list.rmd to-binary out 32 | ] 33 | 34 | tree: [] ; hold a pairs of : style, block of style's childs 35 | 36 | ; fill the block of style, childs 37 | foreach s styles [ 38 | p: guie/styles/:s/parent 39 | if not find tree p [repend tree [p copy []]] 40 | append tree/:p s 41 | ] 42 | 43 | ; simple stack of pair values 44 | pile: [] 45 | push: func [level value] [append pile level append pile value] ;probe pile] 46 | pop: func [] [take/part/last pile 2] 47 | 48 | ; now build a block of : title level, style 49 | level: 0 50 | style: none 51 | 52 | clear out 53 | 54 | emit "VID3.4 Style Tree" 55 | emit "" 56 | emit ["Generated on" now "using REBOL 3 version" system/version newline] 57 | 58 | forever [ 59 | b: tree/:style 60 | if block? b [ 61 | foreach style reverse b [push (level + 1) style] 62 | ] 63 | set [level style] pop 64 | if none? level [break] 65 | emit [array/initial level " " style] 66 | ] 67 | 68 | write %style-tree.rmd to-binary out 69 | if exists? %../../../r3-alpha [ 70 | write %../../../r3-alpha/files/Users/Henrik/style-tree.rmd to-binary out 71 | ] -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-opinion-form.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-opinion-form.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-0.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-0.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-0a.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-0a.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-0b.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-0b.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-1.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-2-col.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-2-col.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-2.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-2g-col.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-2g-col.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-3-col.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-3-col.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-4-col.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-4-col.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-combo-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-combo-1.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-combo-2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-combo-2.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-combo-3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-combo-3.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-combo-4.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-combo-4.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-combo-5.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-combo-5.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-group-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-group-1.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-group-1a.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-group-1a.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-show.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-show.png -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-sizing-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-sizing-1.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-sizing-2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-sizing-2.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-sizing-3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-sizing-3.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-vert.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-vert.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/graphics/gui-panels-visibility.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/graphics/gui-panels-visibility.png -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-opinion-form.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-opinion-form.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panel-sizing-3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panel-sizing-3.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-0.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-0.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-0a.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-0a.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-0b.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-0b.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-1.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-2-col.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-2-col.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-2.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-2g-col.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-2g-col.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-3-col.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-3-col.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-4-col.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-4-col.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-combo-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-combo-1.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-combo-2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-combo-2.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-combo-3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-combo-3.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-combo-4.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-combo-4.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-combo-5.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-combo-5.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-group-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-group-1.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-group-1a.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-group-1a.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-show.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-show.png -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-sizing-1.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-sizing-1.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-sizing-2.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-sizing-2.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-sizing-3.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-sizing-3.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-vert.PNG: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-vert.PNG -------------------------------------------------------------------------------- /r3-gui/specs/styles/panels/gui-panels-visibility.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/gchiu/Rebol3/bbe3a801fe49225b750b7d69a90b8d752cd707ba/r3-gui/specs/styles/panels/gui-panels-visibility.png -------------------------------------------------------------------------------- /r3-gui/specs/styles/style-list.rmd: -------------------------------------------------------------------------------- 1 | VID3.4 Style List 2 | 3 | Generated on 17-Feb-2010/22:53:52+1:00 using REBOL 3 version 2.100.97.3.1 4 | 5 | === window 6 | 7 | Parent: none 8 | 9 | Description: A special style used by system for window panels. 10 | 11 | Options: [] 12 | 13 | === face 14 | 15 | Parent: none 16 | 17 | Description: A special style used passing pre-built faces. 18 | 19 | Options: [content size] 20 | 21 | === when 22 | 23 | Parent: none 24 | 25 | Description: A special style for defining panel triggers. 26 | 27 | Options: [triggers] 28 | 29 | === data 30 | 31 | Parent: when 32 | 33 | Description: A special style for storing data. 34 | 35 | Options: [block] 36 | 37 | === embed 38 | 39 | Parent: data 40 | 41 | Description: A special style for including data values in SUBMIT. 42 | 43 | Options: [block] 44 | 45 | === plane 46 | 47 | Parent: none 48 | 49 | Description: A lean sub-panel used as a scroll frame. No internal resizing. 50 | 51 | Options: [size panel] 52 | 53 | === group 54 | 55 | Parent: none 56 | 57 | Description: For spaced groups. No background or borders. Default horizontal. 58 | 59 | Options: [content columns size] 60 | 61 | === tight 62 | 63 | Parent: group 64 | 65 | Description: Tightly spaced and packed group. No background or borders. Horizontal default. 66 | 67 | Options: [content columns size] 68 | 69 | === panel 70 | 71 | Parent: group 72 | 73 | Description: For grouping faces with a background and borders. 74 | 75 | Options: [content columns size area-color] 76 | 77 | === backdrop 78 | 79 | Parent: panel 80 | 81 | Description: For grouping faces with a background and borders. 82 | 83 | Options: [content columns size area-color] 84 | 85 | === pad 86 | 87 | Parent: none 88 | 89 | Description: Padding for blank spaces. 90 | 91 | Options: [size] 92 | 93 | === clicker 94 | 95 | Parent: none 96 | 97 | Description: Single-action button without text. Basis of other styles. 98 | 99 | Options: [size area-color] 100 | 101 | === button 102 | 103 | Parent: clicker 104 | 105 | Description: Single action button with text. 106 | 107 | Options: [text-body area-color size wide] 108 | 109 | === toggle 110 | 111 | Parent: button 112 | 113 | Description: Dual action button with text and LED indicator. 114 | 115 | Options: [text-body area-color orig-state size wide] 116 | 117 | === check 118 | 119 | Parent: toggle 120 | 121 | Description: Dual action button with text and LED indicator. 122 | 123 | Options: [text-body area-color orig-state size wide] 124 | 125 | === radio 126 | 127 | Parent: check 128 | 129 | Description: Dual action button with text and LED indicator. 130 | 131 | Options: [text-body area-color orig-state size wide] 132 | 133 | === arrow-button 134 | 135 | Parent: clicker 136 | 137 | Description: Single action button with arrow (but no text). 138 | 139 | Options: [size area-color angle] 140 | 141 | === box 142 | 143 | Parent: none 144 | 145 | Description: Simple rectangular box. 146 | 147 | Options: [size area-color] 148 | 149 | === bar 150 | 151 | Parent: box 152 | 153 | Description: Simple horizontal divider bar. 154 | 155 | Options: [size area-color] 156 | 157 | === div 158 | 159 | Parent: bar 160 | 161 | Description: Simple vertical divider bar. 162 | 163 | Options: [size area-color] 164 | 165 | === progress 166 | 167 | Parent: none 168 | 169 | Description: Progress bar. 170 | 171 | Options: [bar-color size] 172 | 173 | === slider 174 | 175 | Parent: none 176 | 177 | Description: Slide-bar for numeric input (0% - 100%) 178 | 179 | Options: [size knob-color] 180 | 181 | === scroller 182 | 183 | Parent: none 184 | 185 | Description: Scroll bar with end arrows. 186 | 187 | Options: [size] 188 | 189 | === text 190 | 191 | Parent: none 192 | 193 | Description: Simple text without background. 194 | 195 | Options: [text-body text-color size] 196 | 197 | === title 198 | 199 | Parent: text 200 | 201 | Description: Title text style without background. 202 | 203 | Options: [text-body text-color size] 204 | 205 | === head-bar 206 | 207 | Parent: text 208 | 209 | Description: Boxed text bar for headings. 210 | 211 | Options: [text-body area-color size] 212 | 213 | === label 214 | 215 | Parent: text 216 | 217 | Description: Label text without background. 218 | 219 | Options: [text-body text-color size] 220 | 221 | === text-area 222 | 223 | Parent: none 224 | 225 | Description: General text input area, editable, scrollable, without background. 226 | 227 | Options: [size text-edit] 228 | 229 | === text-box 230 | 231 | Parent: text-area 232 | 233 | Description: Text area with background box. 234 | 235 | Options: [size text-edit area-color] 236 | 237 | === field 238 | 239 | Parent: text-box 240 | 241 | Description: Single line text input, editable, with background box. 242 | 243 | Options: [size text-edit area-color] 244 | 245 | === area 246 | 247 | Parent: tight 248 | 249 | Description: Multi-line text input, editable, scrollable, with background and scrollbars. 250 | 251 | Options: [text-edit area-color size] 252 | 253 | === code-area 254 | 255 | Parent: area 256 | 257 | Description: Multi-line code input, editable, scrollable, with background and scrollbars. 258 | 259 | Options: [text-edit area-color size] 260 | 261 | === info 262 | 263 | Parent: text-area 264 | 265 | Description: Text information fields, non-editable. 266 | 267 | Options: [size text-edit] 268 | 269 | === info-area 270 | 271 | Parent: tight 272 | 273 | Description: Multi-line text info, non-editable, scrollable, scrollbars. 274 | 275 | Options: [text-edit area-color size] 276 | 277 | === doc 278 | 279 | Parent: text-area 280 | 281 | Description: A tiny document markup method for embedded docs, notes, messages. 282 | 283 | Options: [text-edit] 284 | 285 | === sensor 286 | 287 | Parent: none 288 | 289 | Description: Has no graphics, but can be clicked. 290 | 291 | Options: [size] 292 | 293 | === drawing 294 | 295 | Parent: sensor 296 | 297 | Description: Simple scalar vector draw block. Can be clicked. 298 | 299 | Options: [drawing size] 300 | 301 | === image 302 | 303 | Parent: sensor 304 | 305 | Description: Simple image with optional border. Can be clicked. 306 | 307 | Options: [src size edge-size] 308 | 309 | === icon 310 | 311 | Parent: image 312 | 313 | Description: Icon image with optional text below. 314 | 315 | Options: [src size edge-size] 316 | 317 | === text-list-box 318 | 319 | Parent: box 320 | 321 | Description: List of selectable text lines (no scrollbar). 322 | 323 | Options: [contents area-color] 324 | 325 | === text-list 326 | 327 | Parent: tight 328 | 329 | Description: List of selectable text lines with scrollbar. 330 | 331 | Options: [list-data] 332 | 333 | -------------------------------------------------------------------------------- /r3-gui/specs/styles/style-tree.rmd: -------------------------------------------------------------------------------- 1 | VID3.4 Style Tree 2 | 3 | Generated on 17-Feb-2010/22:53:52+1:00 using REBOL 3 version 2.100.97.3.1 4 | 5 | window 6 | face 7 | when 8 | data 9 | embed 10 | plane 11 | group 12 | tight 13 | area 14 | code-area 15 | info-area 16 | text-list 17 | panel 18 | backdrop 19 | pad 20 | clicker 21 | button 22 | toggle 23 | check 24 | radio 25 | arrow-button 26 | box 27 | bar 28 | div 29 | text-list-box 30 | progress 31 | slider 32 | scroller 33 | text 34 | title 35 | head-bar 36 | label 37 | text-area 38 | text-box 39 | field 40 | info 41 | doc 42 | sensor 43 | drawing 44 | image 45 | icon 46 | -------------------------------------------------------------------------------- /r3-gui/specs/styles/tab-box/tab-box.mdp: -------------------------------------------------------------------------------- 1 | R3 GUI / TAB-BOX 2 | Author: Boleslav Březovský 3 | Type: User Documentation 4 | Date: 25-Feb-2011 5 | 6 | =toc 7 | 8 | TAB-BOX provides tabbed interface similar to that found in web browsers. 9 | 10 | Each tab gets its unique id (stored as face's name) so it's possible to have tabs with same name. All GUI elements in tab can be addressed even if tab is not visible (if tab was initialized before). 11 | 12 | ===Dialect specification 13 | 14 | TAB-BOX tab-specs [block!] 15 | 16 | tab-specs: some [ 17 | tab-name [string!] 18 | tab-layout [block!] 19 | ] 20 | 21 | ---tab-name [string!] 22 | 23 | Tab name that will be displayed in the tab bar. 24 | 25 | ---tab-layout [block!] 26 | 27 | Layout code to be displayed in tab. TODO: Panel type for layout can be specified (hpanel, vgroup...) 28 | 29 | ===Style access 30 | 31 | ---Get values 32 | 33 | +++VALUE 34 | 35 | *word!* 36 | 37 | Return active tab. 38 | 39 | ---Set values 40 | 41 | +++VALUE 42 | 43 | *word!* - tab ID 44 | 45 | Set active tab. 46 | 47 | +++DATA 48 | 49 | *block!* - dialect tab-specs 50 | 51 | Data of tabs. See dialect specification for details. 52 | 53 | +++TAB 54 | 55 | *block!* - [tab-name opt tab-id tab-layout] 56 | 57 | Add new tab or change current if existing ID is specified. -------------------------------------------------------------------------------- /r3-gui/specs/validation/validation-proposal.mdp: -------------------------------------------------------------------------------- 1 | Validation Proposal 2 | 3 | Author: Henrik Mikael Kristensen 4 | Date: 25-May-2010 5 | 6 | ===Rationale 7 | 8 | The R3-GUI needs a way to validate forms. Form validation is trivial and time consuming work to implement, so it will be nice to have as a standard feature in the R3-GUI. 9 | 10 | ===Ideas 11 | 12 | ---VALIDATE-FACE 13 | 14 | # validation occurs through a single function: VALIDATE-FACE and is recursive, can be done on window level or face level. 15 | 16 | # validation of single faces with an INPUT tag 17 | 18 | # validation of panels of faces with INPUT tags 19 | 20 | ---Validation indication 21 | 22 | # validation indicator icon that would have to reside to the right of the face that needs to be validated. this is a bit informal to do it like that, but the setup is common and would be flexible enough to use both on single faces and entire panels. 23 | 24 | # validation indicator is not obligatory to attach to a face 25 | 26 | # method for triggering validation for a single face. not sure a reactor is useful. result of validation is logic! where true is 'valid 27 | 28 | ---Validation states 29 | 30 | # indicator states: 'not-required, 'required, 'valid, 'invalid 31 | 32 | # 'required means that when validation fails, this is a fatal error 33 | 34 | # 'not-required means that when validation fails, this is not a fatal error 35 | 36 | # keyword for indication of 'required field in layout 37 | 38 | # turn off validation on disabled faces 39 | 40 | ---Validation modes 41 | 42 | :init - sets all valid-indicators to initial state: 'valid, 'required or 'not-required, would be appropriate for reopened filled forms and cleared new forms 43 | 44 | :preliminary - performs validation, but doesn't show result - useful for when validation is required dyring typing in form 45 | 46 | :submission - validate and show all results and auto-focus first invalid field - useful on final validation when wanting to submit 47 | 48 | # state transition on init: valid -> valid, invalid -> required, not-required -> not-required, required -> required 49 | 50 | # state transition on validate: not-required -> valid, required -> valid or invalid, valid -> valid, invalid -> invalid 51 | 52 | ---When to validate 53 | 54 | # initial validation on window open. this would work both for new forms and already filled forms as indicated by the state transition above. 55 | 56 | # submission validation on window submission-close, when clicking a submit button 57 | 58 | # clear validation result on window cancel-close, when clicking a cancel button 59 | 60 | # sum of validation for entire form returns logic! 61 | 62 | # need a VALIDATION word in each face that needs validation. it holds the state words: 'not-required, 'required, 'valid, 'invalid or NONE, if the face is not to be validated at all. 63 | 64 | # function to collect a list of faces that are invalid by traversing the GUI for the VALIDATION word. name is TBD. 65 | 66 | # buttons that perform validation, such as a window submit button. 67 | 68 | ===Source examples 69 | 70 | This would validate the field, when clicking the button: 71 | 72 | view [ 73 | f: field validate [not empty? get-face face] valid-indicator 74 | button "Validate" do [validate-face f] 75 | ] 76 | 77 | ===Notes 78 | 79 | If this is done right, the only code the user needs to write is the code to validate the field, and otherwise place indicators and a submit button. The GUI handles the rest. 80 | 81 | I wouldn't want to provide standard validation code through keywords. The issue is that this splits the implementation in a need for custom validation and one that follows standard keywords and that's too messy. 82 | 83 | It's possible that we need to rework it to fit better with the philosophy of how to attach meta-information to a layout stated in the db-reactors.r3 file. 84 | 85 | I know this validation scheme is possible, because I've already implemented around 75% of it in the VID Extension Kit. -------------------------------------------------------------------------------- /r3-gui/user/getting-started.mdp: -------------------------------------------------------------------------------- 1 | R3-GUI Getting Started 2 | Author: Robert M. Münch, Saphirion AG 3 | Date: 20-Jan-2013/12:27:11+1:00 4 | Version: $Id$ 5 | 6 | =toc 7 | 8 | \note 9 | The docs are work in progress. 10 | /note 11 | ===Introduction 12 | R3-GUI is a framework for building GUI applications with Rebol 3. 13 | 14 | R3-GUI is inspired by the Rebol 2 GUI framework named VID in terms of ease of use and using a dialect to specify your GUI layout and functionality. 15 | 16 | R3-GUI is designed for real-world applications and can be used for code ranging from simple tests up to big commercial applications. 17 | 18 | --- Where does R3-GUI fit with respect to the other GUI libs? 19 | R3-GUI is built on but not backward compatible (anymore) with the old R3-GUI version designed by Carl Sassenrath for Rebol 3 in the past. We continued the development of R3-GUI and extended, optimized and changed it in many ways. This was necessary because the R3-GUI was unfinished when we started to work on it and due to the limitations we hit. We also had to make design decisions allowing us to create enterprise applications with R3-GUI. 20 | 21 | --- Available Documentation 22 | Different aspects of R3-GUI are documented. Some high level stuff but also some very low level stuff. The documentation is still in an early stage. We are working on it. 23 | 24 | We provide some older documentation as well. This documentation is based on the state of R3-GUI framework before we started to maintain it and still gives some hindsight. Nevertheless, the outdated examples etc. won't work with the latest version. 25 | 26 | We are going to clean-up this situation over time. 27 | 28 | --- Getting Ready 29 | R3-GUI is not part of the R3 interpreter. The R3 interpreter just contains the underlying things like the graphics engine and basic graphic building blocks. 30 | 31 | To use R3-GUI you first have to load it. This can be done by downloading R3-GUI to your local directory. Another option is to use Saphirion's latest release and have it downloaded from our web-site. To do this use: 32 | 33 | load-gui 34 | 35 | Saphirion's R3 version has the URL to the R3-GUI source code hard-coded into it, so you don't have to care. 36 | 37 | \note 38 | At the moment you can load only one R3-GUI version. We are going to add more fine grained options so that you can load the latest, stable, or a specific version using the load-gui command. 39 | /note 40 | 41 | === Minimal Example 42 | The following example creates a window that displays a text and has a button widget to close the window. 43 | 44 | view [ 45 | text "Example window." 46 | button "Close" on-action [close-window face] 47 | ] 48 | 49 | Let's walk through the different parts of the code. 50 | 51 | view 52 | 53 | The VIEW function displays a window with a content that is specified by a so called layout block. The layout block contents are written in R3-GUI language. In the layout block you specify how the GUI should be built and how it should act. 54 | 55 | Hence, the layout block is a classical Rebol dialect. In this case it is an optimized domain specific language to describe GUIs. 56 | 57 | The next two lines already use two widgets (~faces~ in Rebol world) having some predefined types called ~styles~ in the Rebol world. These are provided and implemented by the R3-GUI code you loaded. 58 | 59 | text 60 | button on-action 61 | 62 | The TEXT widget obviously shows the text given by the string. And the BUTTON widget looks like a button. So far pretty easy. 63 | 64 | The interesting part is how we define an action. Something that should be executed when the user, e.g., clicks on the button widget. This is done by specifying an ON-ACTION attribute of the button widget. For many widget types (styles) R3-GUI knows when the on-action code shall be executed. This was defined by the designer who implemented the widget type. Depending on the widget type ON-ACTION can be executed on different user actions. For the button this happens when the user "presses" the button. For a more complex widget this might be something different. 65 | 66 | Let's take a look at the action definition. 67 | 68 | on-action [close-window face] 69 | 70 | The CLOSE-WINDOW function is quite easy to understand. It is the function which closes the window containing the given FACE. When the application window is closed, the program terminates. 71 | 72 | But what's this FACE word? Where does it come from? The 'on-action' word is actually a name of an R3-GUI ~actor~. By the current convention, R3-GUI actors are implemented as functions and their arguments are fixed and standardized. Actor arguments are: 73 | 74 | \table 75 | face | 76 | The face upon which the actor acts. || 77 | arg | 78 | A single value or block of multiple values. 79 | /table 80 | 81 | When the actor is called, argument values are passed to the actor body block. Local variables can be defined using set-words (the same way as when using FUNCT). 82 | 83 | Thus, R3-GUI uses our button object, looks up the ON-ACTION actor and executes the found code as a function call. And, as for normal functions, the ON-ACTION actor is called with some arguments. In our case the FACE argument refers to our button widget. And since you can access function arguments in the function code, you can of course use the FACE word to access the button object. 84 | 85 | These are the words you can use for many widgets. 86 | 87 | --- Summary 88 | You see that it's quite easy to do GUIs with R3-GUI. You need to know a couple of concepts and that's it. Here is a list of things to remember: 89 | #Use VIEW to transform the R3-GUI dialect into some internal form and display it. 90 | #The code that should be executed because of an action of the user can be specified as an ON-ACTION action-block. This is a *major* difference to older R3-GUI implementations where a different notation was used. 91 | #You can access implicit words inside the action-block. One word is FACE which refers to the widget for which the action is executed, the other is ARG referring to the argument (or argument block) passed to the actor. 92 | 93 | === How do things fit together? 94 | Since R3-GUI is a bit different than normal GUI libraries you might know from the C, Java, etc. world, let's see how things fit together. 95 | 96 | You already learned that the Rebol widget types are called styles. These are definitions specifying default values for most attributes of a widget. Something like a class. 97 | 98 | Using defined styles you create specific widgets (faces). The FACE is the actual concrete widget on the screen. You can change all values of its attributes. A FACE object offers a lot of information you can inspect. 99 | 100 | A group of faces is managed through a ~layout~. Layouts are collections of faces used for specific parts of a user interface. You specify the layout by using special layout words in the layout-block of the VIEW function. 101 | 102 | R3-GUI system has been designed to make layouts very easy to create, debug, and maintain. One of the main goals was for simple GUI definitions to be able to create a wide range of simple, predictable layouts, but also to allow more sophisticated and elaborate results to be produced using the same set of basic rules. 103 | 104 | Layouts provide a way to: 105 | 106 | #Group a number of faces together 107 | #Arrange faces into a desired layout 108 | #Display a 2D layer, with background or other effects 109 | #Update, resize and reposition faces when events occur 110 | 111 | === What to read next? 112 | To get a good understanding, we suggest that you read things in the following order: 113 | 114 | #FACES to understand the basic building blocks and how they look. 115 | #LAYOUTS to understand how you can build GUIs consisting of many widgets and how these are managed. 116 | #ACTORS bring life to your GUI. This is where all the interaction comes from. 117 | #STYLES to understand how new widget types can be defined. 118 | 119 | END OF DOCUMENT 120 | -------------------------------------------------------------------------------- /scripts/base32.reb: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | file: %base32.reb 3 | date: 17-Sep-2015 4 | author: "Graham Chiu" 5 | version: 0.0.3 6 | notes: { 7 | encodes string to base32 or base32hex 8 | padding to 5 characters is not required in this method 9 | 10 | >> to-base32/decode/hex to-base32/hex "yessir" 11 | == "yessir" 12 | } 13 | ] 14 | 15 | to-base32: function [ st [string!] 16 | /hex {output base32hex} 17 | /decode {returns decoded base32/hex string} 18 | ][ 19 | accepted: either hex 20 | ["0123456789abcdefghijklmnopqrstuv"]; base32hex 21 | ["abcdefghijklmnopqrstuvwxyz234567"]; base32 22 | base2: [16 8 4 2 1] 23 | ajoin either not decode [ 24 | ; turn st, to be encoded, into a "binary" string 25 | b2: enbase/base st 2 26 | ; convert each block of 5 into a char from the accepted list 27 | collect [ 28 | while [not empty? b2][ 29 | five: take/part b2 5 30 | ; convert this "binary" into decimal, and look at blocks of 5 eg. "01111" 31 | offset: 0 32 | for i 1 5 1 [ 33 | if #"1" = take five [ 34 | offset: offset + base2/:i 35 | ] 36 | ] 37 | keep pick accepted offset + 1 38 | ] 39 | ] 40 | ][ 41 | ; find each character in the string, and form a 5 bit binary representation 42 | str: copy st ; so as not to affect the original 43 | result: ajoin collect [ 44 | while [not empty? st][ 45 | keep ajoin collect [ 46 | index: -1 + index? find accepted form take st 47 | for i 1 5 1 [ 48 | keep either positive? index AND base2/:i ["1"]["0"] 49 | ] 50 | ] 51 | ] 52 | ] 53 | ; we now have a very long string of "binary". We need to take it in blocks of 8 and convert back to characters 54 | collect [ 55 | while [not empty? result][ 56 | attempt [ 57 | keep to-char debase/base take/part result 8 2 58 | ] 59 | ] 60 | ] 61 | ] 62 | ] 63 | -------------------------------------------------------------------------------- /scripts/calcCRC16.reb: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | file: %calcCRC16.reb 3 | notes: {based on https://blog.naver.com/pinggusoft/221258891786 4 | >> rebol/build 5 | == 12-May-2018/22:24:10 6 | >> rebol/commit 7 | == "04895e5cae2541c54f2a39030d50e6bb63e36e02" 8 | } 9 | date: 13-May-2018 10 | name: "Graham" 11 | ] 12 | 13 | INIT_SEED16: to-integer/unsigned #{3692} 14 | 15 | TBL_CRC16: [ 16 | 0 4489 8978 12955 17956 22445 25910 29887 35912 40385 44890 48851 51820 56293 59774 63735 17 | 4225 264 13203 8730 22181 18220 30135 25662 40137 36160 49115 44626 56045 52068 63999 59510 18 | 8450 12427 528 5017 26406 30383 17460 21949 44362 48323 36440 40913 60270 64231 51324 55797 19 | 12675 8202 4753 792 30631 26158 21685 17724 48587 44098 40665 36688 64495 60006 55549 51572 20 | 16900 21389 24854 28831 1056 5545 10034 14011 52812 57285 60766 64727 34920 39393 43898 47859 21 | 21125 17164 29079 24606 5281 1320 14259 9786 57037 53060 64991 60502 39145 35168 48123 43634 22 | 25350 29327 16404 20893 9506 13483 1584 6073 61262 65223 52316 56789 43370 47331 35448 39921 23 | 29575 25102 20629 16668 13731 9258 5809 1848 65487 60998 56541 52564 47595 43106 39673 35696 24 | 33800 38273 42778 46739 49708 54181 57662 61623 2112 6601 11090 15067 20068 24557 28022 31999 25 | 38025 34048 47003 42514 53933 49956 61887 57398 6337 2376 15315 10842 24293 20332 32247 27774 26 | 42250 46211 34328 38801 58158 62119 49212 53685 10562 14539 2640 7129 28518 32495 19572 24061 27 | 46475 41986 38553 34576 62383 57894 53437 49460 14787 10314 6865 2904 32743 28270 23797 19836 28 | 50700 55173 58654 62615 32808 37281 41786 45747 19012 23501 26966 30943 3168 7657 12146 16123 29 | 54925 50948 62879 58390 37033 33056 46011 41522 23237 19276 31191 26718 7393 3432 16371 11898 30 | 59150 63111 50204 54677 41258 45219 33336 37809 27462 31439 18516 23005 11618 15595 3696 8185 31 | 63375 58886 54429 50452 45483 40994 37561 33584 31687 27214 22741 18780 15843 11370 7921 3960 32 | ] 33 | 34 | calcCRC16: function [ 35 | {calculates a crc16} 36 | buf [binary!] 37 | /little {returns as little endian} 38 | ][ 39 | action: either little [:reverse][:nihil] 40 | seed: INIT_SEED16 41 | ; seed = TBL_CRC16[(seed ^ buf[i++]) & 0xff] ^ (seed >> 8); 42 | forall buf [ 43 | index: 255 and+ (seed xor+ buf/1) 44 | ; C uses offset of 0, and Rebol uses 1 45 | seed: (shift seed -8) xor+ TBL_CRC16/(index + 1) 46 | ] 47 | return action trim to binary! seed 48 | ] 49 | 50 | ; uncomment to run tests 51 | ;print ["should be #{c216}" calcCRC16/little #{cc58007c685400e401}] 52 | ;print ["should be #{a5bd}" calcCRC16/little copy/part #{ccb0007f6050000000000420000108113a29da01a5bd} 20] 53 | -------------------------------------------------------------------------------- /scripts/calcCRC8.reb: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | file: %crc8.reb 3 | notes: {based on https://blog.naver.com/pinggusoft/221258891786 4 | >> rebol/build 5 | == 12-May-2018/22:24:10 6 | >> rebol/commit 7 | == "04895e5cae2541c54f2a39030d50e6bb63e36e02" 8 | } 9 | date: 13-May-2018 10 | author: "Graham" 11 | ] 12 | 13 | INIT_SEED8: to-integer/unsigned #{77} 14 | 15 | crc8-table: [ 16 | 0 94 188 226 97 63 221 131 194 156 126 32 163 253 31 65 17 | 157 195 33 127 252 162 64 30 95 1 227 189 62 96 130 220 18 | 35 125 159 193 66 28 254 160 225 191 93 3 128 222 60 98 19 | 190 224 2 92 223 129 99 61 124 34 192 158 29 67 161 255 20 | 70 24 250 164 39 121 155 197 132 218 56 102 229 187 89 7 21 | 219 133 103 57 186 228 6 88 25 71 165 251 120 38 196 154 22 | 101 59 217 135 4 90 184 230 167 249 27 69 198 152 122 36 23 | 248 166 68 26 153 199 37 123 58 100 134 216 91 5 231 185 24 | 140 210 48 110 237 179 81 15 78 16 242 172 47 113 147 205 25 | 17 79 173 243 112 46 204 146 211 141 111 49 178 236 14 80 26 | 175 241 19 77 206 144 114 44 109 51 209 143 12 82 176 238 27 | 50 108 142 208 83 13 239 177 240 174 76 18 145 207 45 115 28 | 202 148 118 40 171 245 23 73 8 86 180 234 105 55 213 139 29 | 87 9 235 181 54 104 138 212 149 203 41 119 244 170 72 22 30 | 233 183 85 11 136 214 52 106 43 117 151 201 74 20 246 168 31 | 116 42 200 150 21 75 169 247 182 232 10 84 215 137 107 53 32 | ] 33 | 34 | calcCRC8: function [ 35 | buf [binary!] 36 | ][ 37 | seed: INIT_SEED8 38 | ; seed = TBL_CRC8[(seed ^ buf[i++]) & 0xff]; 39 | forall buf [ 40 | index: ((buf/1 xor+ seed) and+ 255) 41 | seed: crc8-table/(index + 1) 42 | ] 43 | trim to binary! (255 and+ seed) 44 | ] 45 | 46 | ; test 47 | ; calcCRC8 #{CC5800} ; should return #{7C} 48 | -------------------------------------------------------------------------------- /scripts/calendar-google-api.reb: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | file: %calendar-google-api.reb 3 | title: "Access Google APIs" 4 | author: "Graham Chiu" 5 | date: 16-Sep-2015 6 | version: 0.0.5 7 | notes: { 8 | This script just uses the calendar api. Others are similar. 9 | 10 | 1. You need to be an authenticated user of the calendar. See https://developers.google.com/google-apps/calendar/auth 11 | 2. From the developers console https://console.developers.google.com/ you need to create a project 12 | 3. Once you have a project, click on "Apis and Auth/APIs" 13 | 4. Choose the Calendar API and click on the blue button "Enable Api" 14 | 5. Click on "Apis and Auth/Credentials", and then the blue button "Add Credentials" 15 | 6. Select OAuth 2.0 Client ID 16 | 7. Application type, choose other from the radio buttons 17 | 8. Give your client a name 18 | 9. You will now see your client name, Client ID and on the far right a down arrow to download the credentials. The credentials are a JSON file. 19 | 10. Load-json on this file to give yourself the installed object, and replace mine with yours in the settings object. 20 | 11. This file never changes so you can embed it in your script 21 | 12. You now build a query with scope set to the calendar. Use your own gmail account for the login_hint 22 | 13. Send the system web browser to the authentication server 23 | 14. You may have to login to your google account. If already logged in you'll be asked if it's okay to allow your project access to your calendar 24 | 15. Copy the generated access token and paste it into the view field that this script brings up ( or just copy it and change the value of settings/token with it ). We don't need to keep it as it's just used once to get our long lasting refresh token 25 | 16. We now form our query to exchange our access token for the refresh token. Bizzarely the redirect_uri parameter must not be URL encoded so we add it after we have formed the query 26 | 17. We now post to the token-server to get our refresh_token 27 | 18. Shows a cURL script to get the same data, helpful if you get 400 errors 28 | 19. The JSON object successfully returned 29 | 20. We're going to immediately refresh the access token returned 30 | 21. Call the token server using our refresh_token to get a new access_token 31 | 22. Demo add appointment 32 | 33 | NB: steps 1-19 are one time only. If you keep trying to get refesh tokens, you'll end up with invalid_token errors ( seen in the cURL script) 34 | } 35 | ] 36 | 37 | ; steps #1 - #11 are in the notes above 38 | token-server: https://www.googleapis.com/oauth2/v3/token 39 | calendar-api: https://www.googleapis.com/calendar/v3/calendars/primary/ 40 | 41 | u: self 42 | 43 | settings: make object! [ 44 | installed: make object! [ 45 | client_id: {see-step-10-above} 46 | auth_uri: "https://accounts.google.com/o/oauth2/auth" 47 | token_uri: "https://accounts.google.com/o/oauth2/token" 48 | auth_provider_x509_cert_url: "https://www.googleapis.com/oauth2/v1/certs" 49 | client_secret: "see-step-10-above" 50 | redirect_uris: [ 51 | "urn:ietf:wg:oauth:2.0:oob" 52 | "http://localhost" 53 | ] 54 | ] 55 | token: "" 56 | gmail: youraccount@gmail.com 57 | ] 58 | 59 | authentication-server: to url! append settings/installed/auth_uri "?" 60 | 61 | resources: [ 62 | %prot-http.reb https://raw.githubusercontent.com/gchiu/Rebol3/master/protocols/prot-http.r3 63 | %combine.reb https://raw.githubusercontent.com/hostilefork/rebol-proposals/master/combine.reb 64 | %altjson.reb http://reb4.me/r3/altjson 65 | %altwebform.reb http://reb4.me/r3/altwebform 66 | %r3-gui.reb http://www.atronixengineering.com/r3/r3-gui.r3 67 | ] 68 | 69 | ; one time download files we need 70 | foreach [script location] resources [ 71 | unless exists? script [write script read location] 72 | do script 73 | ] 74 | 75 | ; Step #12 76 | 77 | query: to-webform compose [ 78 | response_type: "code" 79 | client_id: (settings/installed/client_id) 80 | redirect_uri: (settings/installed/redirect_uris/1) 81 | scope: https://www.googleapis.com/auth/calendar 82 | state: "any" 83 | login_hint: (settings/gmail) 84 | include_granted_scopes: "true" 85 | access_type: "offline" 86 | approval_prompt: "force" 87 | ] 88 | 89 | ; Step #13 90 | browse join authentication-server query 91 | 92 | ; Step #15 93 | view [ 94 | vgroup [ 95 | label "Enter Google Authorisation Code: " f: field "" 96 | button "Accept" on-action [ 97 | u/settings/token: copy get-face f 98 | unview/all 99 | ] 100 | ] 101 | ] 102 | 103 | probe settings/token 104 | 105 | ; Step #16 106 | query: to-webform compose [ 107 | code: (settings/token) 108 | client_id: (settings/installed/client_id) 109 | client_secret: (settings/installed/client_secret) 110 | scope: "" 111 | grant_type: "authorization_code" 112 | ] 113 | 114 | ; some odd bug where it won't accept url-encoded redirect_uri 115 | append query join "&redirect_uri=" settings/installed/redirect_uris/1 116 | 117 | ; Step #17 118 | response: write token-server compose/deep [ 119 | POST 120 | [ 121 | Content-Type: "application/x-www-form-urlencoded" 122 | ] 123 | (query) 124 | ] 125 | 126 | ; Step #18 127 | ; script: reform ["curl -d" rejoin [ {"} query {"}] token-server] 128 | ; write %curl/script.cmd script 129 | 130 | resp: load-json to string! response 131 | 132 | ; Step #19 133 | comment { 134 | The object returned by exchanging the first token to get the refresh token looks like this: 135 | 136 | resp: make object! [ 137 | access_token: {ya29.7wHFAnZYm9QxSv2tmQnvlIe_Gj87v95O5OcOUnMNa94v6HpYLjTXDmodn3kpN7bLN_ct} 138 | token_type: "Bearer" 139 | expires_in: 859189296 140 | refresh_token: {1/long string of characters. Do not lose this one!} 141 | ] 142 | 143 | } 144 | 145 | ; Step #20 146 | query: to-webform compose [ 147 | client_id: (settings/installed/client_id) 148 | client_secret: (settings/installed/client_secret) 149 | refresh_token: (resp/refresh_token) 150 | grant_type: "refresh_token" 151 | ] 152 | 153 | ; Step 21 154 | jtoken: load-json to string! write token-server compose/deep [ 155 | POST 156 | [ 157 | Content-Type: "application/x-www-form-urlencoded" 158 | ] 159 | (query) 160 | ] 161 | 162 | comment { 163 | We get a JSON object back looking like this which expires in 60 mins 164 | 165 | make object! [ 166 | access_token: {ya29.7wGh6amVn5nEWZCZytOUYSioJYel9ZaTWSwTbwGjWGqg0-OS8sDPcZCAk4mmgd_WeySn42w} 167 | token_type: "Bearer" 168 | expires_in: 3600 169 | ] 170 | } 171 | 172 | ; change the expires_in to an actual datetime so we can check it later on, and see if we have to get another one 173 | jtoken/expires_in: now + to time! jtoken/expires_in 174 | 175 | Add-Calendar-Entry: function [{Add a basic entry to primary calendar} 176 | start-datetime [date!] end-datetime [date!] description [string!] 177 | ][ 178 | start-datetime/zone: end-datetime/zone: now/zone 179 | api: join calendar-api "events" 180 | payload: copy/deep [start: [dateTime: :start-datetime] end: [dateTime: :end-datetime] summary: :description] 181 | response: write api compose/deep [ 182 | POST 183 | [ 184 | content-type: "application/json; charset=UTF-8" 185 | Authorization: (join "Bearer " jtoken/access_token) 186 | ] 187 | (to-json payload) 188 | ] 189 | ] 190 | 191 | ; Step #22 192 | example: load-json to string! add-calendar-entry 16-09-2015/16:00 16-09-2015/17:00 "Call Hostilefork" 193 | -------------------------------------------------------------------------------- /scripts/change-log.reb: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | file: %change-log.reb 3 | notes: {Creates a change log on discourse site for the commits} 4 | ] 5 | 6 | system/options/dump-size: 1000 7 | 8 | import 9 | import 10 | 11 | s3files: http://metaeducation.s3.amazonaws.com 12 | commits: https://api.github.com/repos/metaeducation/ren-c/commits 13 | 14 | ; get all the unique commit values still available for download 15 | dom: load-xml/dom to string! read s3files 16 | result: dom/get 17 | 18 | comment { 19 | value: => [ 20 | "travis-builds/0.4.40/r3-fbe5237-debug-cpp" 21 | "2017-05-13T15:54:38.000Z" 22 | {"97b151cc9bda7c325828d499efb15332"} 23 | "4085984" 24 | "STANDARD" 25 | ] 26 | } 27 | 28 | files: copy [] 29 | 30 | for-each [key value] result/position [ 31 | r: copy value 32 | if parse value [ 33 | path! set keyvalue string! 34 | path! set datestring string! 35 | to end 36 | ][ 37 | if parse keyvalue ["travis-builds/" copy os: to "/" "/" copy filename to end][ 38 | if parse filename ["r3-" [copy hash: to "-" to end | copy hash: to end]][ 39 | append files hash 40 | repend/only files [os filename] 41 | ] 42 | ] 43 | ] 44 | ] 45 | 46 | if empty? files [quit] 47 | 48 | ; now read the commits 49 | json: reverse load-json to-string read commits ;=> block 50 | 51 | for-each committed json [ ; map! 52 | if something? hash: select committed 'sha [ 53 | ; we have a block of shortened hashes 54 | print newline 55 | print/only "Date: " probe select select select committed 'commit 'author 'date 56 | print/only "Author: " probe select select select committed 'commit 'author 'name 57 | print/only "Message: " probe select select committed 'commit 'message 58 | dump hash 59 | print "^/Binaries available?" 60 | 61 | for-each [h block] files [ 62 | if find hash h [ 63 | probe block 64 | ] 65 | ] 66 | ] 67 | ] 68 | -------------------------------------------------------------------------------- /scripts/dl-renc.reb: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | file: %DL-renc.reb 3 | date: 6-May-2017 4 | author: "Graham" 5 | purpose: {allow download of a specific build from S3} 6 | version: 0.1.2 7 | notes: {24-July-2017 update to use new ++ syntax 8 | 27-July-2017 clear blocks before downloading list to stop duplicates, and fixes for ++ which now returns the value after ++ 9 | } 10 | ] 11 | 12 | trap/with [c: 1 c: ++ 1][fail "This needs a later version of rebol3. Use `upgrade`"] 13 | 14 | oses: copy [] 15 | builds: copy [] 16 | dates: copy [] 17 | files: copy [] ; os - date -name 18 | 19 | contents-rule: [ 20 | thru thru copy key: to thru copy date: to thru 21 | ( 22 | if parse key [thru "travis-builds/" copy os: to "/" "/" copy filename: to end][ 23 | if parse filename [thru "r3-" [copy build: to "-" | copy build: to ".exe" | copy build: to end] to end][ 24 | append oses os 25 | take/last date 26 | replace date "T" "/" 27 | append dates load date 28 | append builds build 29 | repend files [os filename date] 30 | ] 31 | ] 32 | ) 33 | ] 34 | 35 | DL-renc: func [][ 36 | for-each block [oses builds dates files][clear get block] 37 | xml: to string! read http://metaeducation.s3.amazonaws.com 38 | parse xml [some contents-rule] 39 | dates: sort unique dates 40 | oses: sort unique oses 41 | builds: sort unique builds 42 | files: sort/skip files 3 43 | os-specific: copy [] 44 | 45 | default-os: find/tail find/tail form rebol/version "." "." 46 | count: 0 47 | print ["Available OSes: "] 48 | for-each os oses [print unspaced[count: ++ 1 ": " os]] 49 | print newline 50 | forever [ 51 | response: ask join-of default-os " Y/n/q " 52 | if response = "q" [halt] 53 | either any [empty? response find "Y yes" response][ 54 | break 55 | ; accepted default OS 56 | ][ 57 | forever [ 58 | response: ask "enter OS by number: " 59 | if response = "q" [halt] 60 | if all [ 61 | attempt [response: to integer! response] 62 | response > 0 63 | response <= count 64 | ][ 65 | default-os: pick oses response 66 | break 67 | ] 68 | ] 69 | break 70 | ] 71 | ] 72 | for-each [os filename date] files [ 73 | if os = default-os [ 74 | repend os-specific [date filename] 75 | ] 76 | ] 77 | count: 0 78 | os-specific: sort/skip os-specific 2 79 | for-each [date filename] os-specific [ 80 | print [count: ++ 1 date filename] 81 | ] 82 | forever [ 83 | response: ask ajoin ["What filename by number? (" count "q)"] 84 | if response = "q" [halt] 85 | if empty? response [response: count] 86 | if not blank? attempt [response: to integer! response][ 87 | if all [ 88 | response > 0 89 | response <= count 90 | ][ 91 | break 92 | ] 93 | ] 94 | ] 95 | file: pick os-specific response * 2 96 | print ["Downloading ... " file] 97 | write to file! file read rejoin [http://metaeducation.s3.amazonaws.com/travis-builds/ default-os "/" file] () 98 | print "Done." 99 | ] 100 | 101 | print "use dl-renc to get build by date" 102 | -------------------------------------------------------------------------------- /scripts/gmtimesheet.reb: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | date: 7-April-2019 3 | notes: { 4 | Docx templating test using JS and Rebol 5 | 6 | Ask a few questions, then generate a JS function which we push to the DOM. 7 | This should convert the template docx to be filled with our data which you download 8 | 9 | source: https://docxtemplater.com/ 10 | docs: https://docxtemplater.readthedocs.io/en/latest/generate.html 11 | 12 | } 13 | ] 14 | 15 | for-each site [ 16 | https://cdnjs.cloudflare.com/ajax/libs/docxtemplater/3.9.1/docxtemplater.js 17 | https://cdnjs.cloudflare.com/ajax/libs/jszip/2.6.1/jszip.js 18 | https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.js 19 | https://cdnjs.cloudflare.com/ajax/libs/jszip-utils/0.0.2/jszip-utils.js 20 | ][ 21 | js-do site 22 | ] 23 | 24 | ; places the JSZipUtils function named as loadFile in the DOM. 25 | js-do {window.loadFile = function(url,callback){ 26 | JSZipUtils.getBinaryContent(url,callback); 27 | }; 28 | } 29 | 30 | definput: function [ description def][ 31 | prin unspaced [Description " (" def "): "] 32 | temp: input 33 | if empty? temp [temp: def] 34 | return temp 35 | ] 36 | 37 | ;; get the week ending. Calculate a default for this week 38 | week_ending: 39 | if now/weekday = 1 [ 40 | now 41 | ] else [ 42 | now + 8 - now/weekday 43 | ] 44 | week_ending: week_ending/date 45 | 46 | cycle [ 47 | prin unspaced ["Week Ending (" week_ending "): "] 48 | endofweek: input 49 | if empty? endofweek [break] 50 | attempt [ 51 | endofweek: to date! endofweek 52 | week_ending: endofweek 53 | break 54 | ] 55 | ] 56 | 57 | ; get days worked {MTWHF} 58 | daysworked: definput "Which days were worked?" "MTWHF" 59 | 60 | if empty? daysworked [halt] 61 | 62 | if find daysworked "M" [ 63 | s2: "08:00" e2: "17:00" 64 | ] else [ 65 | s2: "" e2: "" 66 | ] 67 | 68 | if find daysworked "T" [ 69 | s3: "08:00" e3: "17:00" 70 | ] else [ 71 | s3: "" e3: "" 72 | ] 73 | 74 | if find daysworked "W" [ 75 | s4: "08:00" e4: "17:00" 76 | ] else [ 77 | s4: "" e4: "" 78 | ] 79 | 80 | if find daysworked "H" [ 81 | s5: "08:00" e5: "17:00" 82 | ] else [ 83 | s5: "" e5: "" 84 | ] 85 | 86 | if find daysworked "F" [ 87 | s6: "08:00" e6: "17:00" 88 | ] else [ 89 | s6: "" e6: "" 90 | ] 91 | 92 | if find daysworked "S" [ 93 | s7: "08:00" e7: "17:00" 94 | ] else [ 95 | s7: "" e7: "" 96 | ] 97 | 98 | if find daysworked "U" [ 99 | s1: "08:00" e1: "17:00" 100 | ] else [ 101 | s1: "" e1: "" 102 | ] 103 | 104 | data: {window.generate = function() { 105 | loadFile("https://metaeducation.s3.amazonaws.com/invoices/GM_timesheet_NZ-form-31.docx",function(error,content){ 106 | if (error) { throw error }; 107 | var zip = new JSZip(content); 108 | var doc=new window.docxtemplater().loadZip(zip) 109 | doc.setData({ 110 | Week_ending: '$week_ending', 111 | Hospital: '$hospital', 112 | Position: '$position', 113 | Name: '$name', 114 | 115 | S1: '$s1', 116 | E1: '$e1', 117 | S2: '$s2', 118 | E2: '$e2', 119 | S3: '$s3', 120 | E3: '$e3', 121 | S4: '$s4', 122 | E4: '$e4', 123 | S5: '$s5', 124 | E5: '$e5', 125 | S6: '$s6', 126 | E6: '$e6', 127 | S7: '$s7', 128 | E7: '$e7', 129 | }); 130 | try { 131 | // render the document (replace all occurences of {first_name} by John, {last_name} by Doe, ...) 132 | doc.render() 133 | } 134 | catch (error) { 135 | var e = { 136 | message: error.message, 137 | name: error.name, 138 | stack: error.stack, 139 | properties: error.properties, 140 | } 141 | console.log(JSON.stringify({error: e})); 142 | // The error thrown here contains additional information when logged with JSON.stringify (it contains a property object). 143 | throw error; 144 | } 145 | var out=doc.getZip().generate({ 146 | type:"blob", 147 | mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", 148 | }) //Output the document using Data-URI 149 | saveAs(out,"$week_ending.docx") 150 | }) 151 | }; 152 | generate() 153 | } 154 | 155 | name: "Graham Chiu" 156 | position: "Rheumatologist" 157 | hospital: "Tauranga Hospital" 158 | 159 | template: reduce [ 160 | 'week_ending week_ending 161 | 'name name 162 | 'hospital hospital 163 | 'position position 164 | 's1 s1 165 | 'e1 e1 166 | 's2 s2 167 | 'e2 e2 168 | 's3 s3 169 | 'e3 e3 170 | 's4 s4 171 | 'e4 e4 172 | 's5 s5 173 | 'e5 e5 174 | 's6 s6 175 | 'e6 e6 176 | 's7 s7 177 | 'e7 e7 178 | ] 179 | 180 | ; probe template 181 | 182 | data: reword data template 183 | ; probe data 184 | 185 | js-do data 186 | -------------------------------------------------------------------------------- /scripts/gui-server.reb: -------------------------------------------------------------------------------- 1 | REBOL [ 2 | title: "GUI http server" 3 | author: "Graham Chiu" 4 | date: 12-July-2014 5 | file: %gui-server.reb 6 | notes: { 7 | http server was based on abolka's code 8 | 9 | Once the GUI comes up, click on the buttons and run the client %task-client.reb 10 | 11 | } 12 | ] 13 | 14 | load-gui 15 | 16 | digit: charset [ #"0" - #"9"] 17 | 18 | code-map: make map! [200 "OK" 400 "Forbidden" 404 "Not Found"] 19 | mime-map: make map! ["html" "text/html" "jpg" "image/jpeg" "r" "text/plain"] 20 | error-template: { 21 | $code $text

$text

22 |

Requested URI: $uri


shttpd.r on 23 | REBOL 3 $r3 24 | } 25 | 26 | error-response: func [code uri /local values] [ 27 | values: [code (code) text (code-map/:code) uri (uri) r3 (system/version)] 28 | reduce [code "text/html" reword error-template compose values] 29 | ] 30 | 31 | send-response: func [port res /local code text type body] [ 32 | set [code type body] res 33 | write port ajoin ["HTTP/1.0 " code " " code-map/:code crlf] 34 | write port ajoin ["Content-type: " type crlf crlf] 35 | write port body 36 | ] 37 | 38 | handle-request: func [config req /local uri type file data t] [ 39 | print ["Request is: " to string! req] 40 | default 'type "text/plain" 41 | default 'data "Notok" 42 | 43 | req: to string! req 44 | case [ 45 | parse req [ 46 | "get" space ["/" space 47 | | 48 | copy uri to space] to end 49 | ][ 50 | ; get case is okay 51 | ] 52 | 53 | parse req [ 54 | "post" space [ "/" space 55 | | 56 | copy uri to " " (?? 0) thru "Content-length: " (?? "cl") copy length some digit (?? 1) thru "^/^/" copy payload to end ( 57 | ; get the task-id 58 | parse uri [ "/answer-task/" copy task-id to end] 59 | uri: copy "/answer-task" 60 | print [ "Content-length: " length] 61 | print [ "Read: " length? payload] 62 | ) 63 | ] 64 | ] 65 | true [ ; unrecognised verb 66 | print "failed parse of request, unrecognized verb?" 67 | ; need to return some type of error here 68 | ] 69 | ] 70 | 71 | ?? uri 72 | case [ 73 | uri = "/request-task" [ 74 | print "requested a task" 75 | if 0 < length? queue [ 76 | print "checking for tasks to be done" 77 | forall queue [ 78 | if all [ none? queue/1/start none? queue/1/end][ 79 | ; found a task that needs doing 80 | print "Got a task" 81 | queue/1/start: now/precise 82 | data: mold/all queue/1 83 | ?? data 84 | break 85 | ] 86 | ] 87 | ] 88 | ] 89 | 90 | uri = "/answer-task" [ 91 | print "got an answer" 92 | task-id: to integer! task-id 93 | ?? task-id 94 | data: copy "Notok" 95 | forall queue [ 96 | t: queue/1 97 | if t/id = task-id [ 98 | t/end: now/precise 99 | t/callback payload 100 | data: copy "OK" 101 | remove queue 102 | break 103 | ] 104 | ] 105 | ] 106 | 107 | true [data: copy "Notok"] 108 | ] 109 | reduce [200 type data] 110 | ] 111 | 112 | awake-client: func [event /local port res] [ 113 | port: event/port 114 | print [ "event: " event/type ] 115 | switch event/type [ 116 | read [ 117 | either find port/data to-binary join crlf crlf [ 118 | res: handle-request port/locals/config port/data 119 | send-response port res 120 | ] [ 121 | read port 122 | ] 123 | ] 124 | wrote [close port] 125 | close [close port] 126 | ] 127 | ] 128 | 129 | awake-server: func [event /local client] [ 130 | if event/type = 'accept [ 131 | client: first event/port 132 | client/awake: :awake-client 133 | read client 134 | ] 135 | ] 136 | 137 | serve: func [web-port web-root /local listen-port] [ 138 | listen-port: open join tcp://: web-port 139 | listen-port/locals: construct compose/deep [config: [root: (web-root)]] 140 | listen-port/awake: :awake-server 141 | wait listen-port 142 | ] 143 | 144 | task: make object! [ 145 | id: none 146 | callback: none 147 | created: none 148 | start: none 149 | end: none 150 | cancelled: false 151 | cmd: none 152 | ] 153 | 154 | Queue: copy [] 155 | task-counter: 0 156 | 157 | view/no-wait [ 158 | vgroup [ 159 | hgroup [ 160 | vgroup [ 161 | area1: area 162 | button "Task 1" on-action [ 163 | t: make task [ 164 | id: ++ task-counter 165 | callback: func [data][set-face area1 data show-now area1] 166 | created: now/precise 167 | cmd: [read http://www.rebol.com] 168 | ] 169 | append queue t 170 | set-face area1 "" 171 | set-face tstatus "added task 1" 172 | set-face tcount length? queue 173 | ] 174 | ] 175 | vgroup [ 176 | area2: area 177 | button "Task 2" on-action [ 178 | t: make task [ 179 | id: ++ task-counter 180 | callback: func [data][set-face area2 data show-now area2] 181 | created: now/precise 182 | cmd: [read http://rheum.mooo.com/2014/06/08/a-cure-for-diabetes/] 183 | ] 184 | append queue t 185 | set-face area2 "" 186 | set-face tstatus "added task 2" 187 | set-face tcount length? queue 188 | ] 189 | ] 190 | ] 191 | hgroup [ 192 | vgroup [ 193 | area3: area 194 | button "Task 3" on-action [ 195 | t: make task [ 196 | id: ++ task-counter 197 | callback: func [data][set-face area3 data show-now area3] 198 | created: now/precise 199 | cmd: [read http://www.rebol.net] 200 | ] 201 | append queue t 202 | set-face area3 "" 203 | set-face tstatus "added task 3" 204 | set-face tcount length? queue 205 | ] 206 | ] 207 | vgroup [ 208 | area4: area 209 | button "Task 4" on-action [ 210 | t: make task [ 211 | id: ++ task-counter 212 | callback: func [data][set-face area4 data show-now area4] 213 | created: now/precise 214 | cmd: [read http://www.rebolsource.net] 215 | ] 216 | append queue t 217 | set-face area4 "" 218 | set-face tstatus "added task 4" 219 | set-face tcount length? queue 220 | ] 221 | ] 222 | ] 223 | ] 224 | hgroup [ 225 | button "Halt" red on-action [unview/all halt] 226 | tstatus: field 227 | tcount: field 228 | ] 229 | ] 230 | 231 | print "waiting on port 8080" 232 | serve 8080 system/options/path -------------------------------------------------------------------------------- /scripts/index.reb: -------------------------------------------------------------------------------- 1 | Rebol [] 2 | 3 | links: make object! [ 4 | nzpower: 5 | chess: 6 | ] 7 | 8 | print "Link object is named links" 9 | 10 | probe links 11 | -------------------------------------------------------------------------------- /scripts/inspector.reb: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | title: "Rebol3 Inspector Gadget" 3 | file: %inspector.reb 4 | date: [28-Apr-2014 19-Sep-2015] 5 | author: "Graham Chiu" 6 | version: 0.0.3 7 | purpose: {browse an object/map/block} 8 | notes: {inspired by Carl's word browser} 9 | ] 10 | 11 | resources: [ 12 | %altjson.reb http://reb4.me/r3/altjson 13 | %r3-gui.reb http://www.atronixengineering.com/r3/r3-gui.r3 14 | ] 15 | 16 | ; one time download files we need 17 | foreach [script location] resources [ 18 | unless exists? script [write script read location] 19 | do script 20 | ] 21 | 22 | collection?: function [o][ 23 | either r: find ['object! 'block! 'map!] type?/word :o [r/1][none] 24 | ] 25 | 26 | comment { not working ... 27 | U: self 28 | cnt: 0 29 | length-of: closure [{return the max depth of o} 30 | o [object! block! map!] 31 | ][ 32 | depth: 0 33 | words: either block? o [ 34 | o 35 | ] [ 36 | words-of o 37 | ] 38 | if block? words [ 39 | ++ u/cnt 40 | foreach word words [ 41 | if collection? w: get word [ 42 | length-of w 43 | ] 44 | ] 45 | ] 46 | depth 47 | ] 48 | } 49 | 50 | get-selected: funct [text-list][ 51 | v: get-face/field text-list 'text 52 | while [block? v][v: v/1] 53 | v 54 | ] 55 | 56 | clear-lists: func [faces [block!] 57 | ][ 58 | foreach f faces [ 59 | set-face/field f copy [] 'data 60 | ] 61 | ] 62 | 63 | inspect: function [iface][ 64 | text-lists: copy [] 65 | 66 | expand: function [face 67 | ][ 68 | clear-lists next find text-lists face 69 | p: copy [iface] 70 | foreach tl text-lists [ 71 | append p get-selected tl 72 | if tl = face [ 73 | ntl: select text-lists face 74 | break 75 | ] 76 | ] 77 | section: get to path! p 78 | either r: collection? :section [ 79 | if ntl [ 80 | set-face/field ntl either block? section [section][words-of section] 'data 81 | ] 82 | set-face tb mold r 83 | ][ 84 | set-face tb 85 | either string? type?/word :section [ 86 | section 87 | ][ 88 | mold :section 89 | ] 90 | ] 91 | ] 92 | 93 | lay: layout [ 94 | hgroup [ 95 | t1: text-list (words-of iface) on-action [expand face] 96 | t2: text-list on-action [expand face] 97 | t3: text-list on-action [expand face] 98 | t4: text-list on-action [expand face] 99 | t5: text-list on-action [expand face] 100 | t6: text-list on-action [expand face] 101 | t7: text-list on-action [expand face] 102 | tb: area "(value)" 103 | ] 104 | ] 105 | foreach tl [t1 t2 t3 t4 t5 t6 t7][ 106 | append text-lists get tl 107 | ] 108 | 109 | view/modal lay 110 | ] 111 | 112 | u: self 113 | j: load-json https://www.googleapis.com/discovery/v1/apis/calendar/v3/rest 114 | 115 | lay: layout compose [ 116 | vgroup [ 117 | a: area (mold j) 118 | hgroup [ 119 | button "inspect" on-click [inspect u/j] 120 | button "close" on-action [unview/all] 121 | ] 122 | ] 123 | ] 124 | 125 | go: function [][ 126 | view/options lay [offset: 100x100] 127 | ] 128 | 129 | p: make port! http://www.rebol.com 130 | inspect p 131 | 132 | -------------------------------------------------------------------------------- /scripts/install.reb: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | title: "Ren garden pre-installer" 3 | author: "Graham" 4 | date: 30-Sep-2015 5 | version: 0.0.7 6 | purpose: "Downloads files to compile ren-c and ren garden" 7 | notes: {needs a version of ren-c that has Graham's prot-http.reb 8 | NB: this script downloads an unzip.exe until we have native unzip working again 9 | } 10 | ] 11 | 12 | root: %/c/r4/ 13 | 14 | unless exists? %r3-gc.exe [ 15 | print "Downloading r3-gc.exe" 16 | write %r3-gc.exe read http://www.compkarori.com/r3/r3.exe 17 | print "Run this script using gc.cmd with admin privs" 18 | write %gc.cmd "r3-gc install.reb" 19 | quit/now 20 | ] 21 | 22 | if not value? 'for-each [ 23 | do make error! "Needs r3-gc.exe. Run gc.cmd from your windows shell with admin priviledges" 24 | ] 25 | 26 | download-file: function [ target [file!] source [url!]][ 27 | if exists? target [exit] 28 | if error? set/any 'err try [ 29 | write target read source 30 | source: none 31 | ][ 32 | either find err/arg1 "Redirect to other host - requires custom handling" [ 33 | source: to url! err/arg3 34 | ][fail err] 35 | ] 36 | if source [ 37 | write target read source 38 | ] 39 | ] 40 | 41 | descend-path: function [{returns a path where p holds types decimal! string! or file!} 42 | start [file!] p [block!] 43 | ][ 44 | for-each el p [ 45 | for-each file read start [ 46 | switch type? el [ 47 | decimal! [ 48 | append start file 49 | break 50 | ] 51 | string! [ 52 | if find file el [ 53 | append start file 54 | break 55 | ] 56 | ] 57 | file! [ 58 | if file = el [ 59 | append start file 60 | break 61 | ] 62 | ] 63 | ] 64 | ] 65 | ] 66 | start 67 | ] 68 | 69 | ; waiting for a working unzip 70 | ; download-file %unzip.reb https://raw.githubusercontent.com/gchiu/Rebol3/master/scripts/unzip.reb 71 | ; do %unzip.reb 72 | 73 | if not exists? root [ 74 | print ["making" root ] 75 | make-dir root 76 | ] 77 | 78 | print ["changing to" root ] 79 | change-dir root 80 | 81 | sources: [ 82 | %master.zip https://github.com/metaeducation/ren-c/archive/master.zip 83 | %develop.zip https://github.com/metaeducation/ren-cpp/archive/develop.zip 84 | ] 85 | 86 | download-file %unzip.exe http://stahlworks.com/dev/unzip.exe 87 | 88 | for-each [target source] sources [ 89 | download-file target source 90 | print ["Unzipping" target] 91 | call/wait join "unzip " target 92 | ; unzip %./ target 93 | ] 94 | 95 | if error? set/any 'err try [rename %ren-c-master %rebol ][probe err] 96 | if error? set/any 'err try [rename %ren-cpp-develop %ren-cpp][probe err] 97 | 98 | binaries: [ 99 | %rebol/make/r3-make.exe http://www.rebolsource.net/downloads/win32-x86/r3-g25033f8.exe 100 | %cmake.exe https://cmake.org/files/v3.3/cmake-3.3.2-win32-x86.exe 101 | %qt.exe http://download.qt.io/official_releases/online_installers/qt-unified-windows-x86-online.exe 102 | ] 103 | 104 | for-each [target source] binaries [ 105 | print ["downloading" source "as" target] 106 | download-file target source 107 | ] 108 | 109 | print "Finished downloads, starting installers" 110 | 111 | for-each installer [ %cmake.exe %qt.exe ][ 112 | call/wait form installer 113 | ] 114 | 115 | print "Make sure that mingw32-make is in your path when using the Qt 5.5 for Desktop console that is needed to run the compilers." 116 | print "You can not use the command shell or powershell." 117 | print "If Qt console path does not show something similar to this" 118 | print "C:\Qt\5.5\mingw492_32\bin;C:\Qt\Tools\mingw492_32\bin; " 119 | print "then you'll need to add it manually using the provided addpath.cmd file." 120 | print "" 121 | 122 | script: copy "set path=%path%;" 123 | 124 | p: descend-path %/c/ [ %qt/ %tools/ "mingw" %bin/ ] 125 | if exists? join p %mingw32-make.exe [ 126 | append append script to-local-file p ";" 127 | ] 128 | p: descend-path %/c/ [ %qt/ 5.5 "ming" %bin/ ] 129 | append append script to-local-file p ";" 130 | 131 | print ["writing out path script addpath.cmd" script] 132 | write %addpath.cmd script 133 | 134 | print "finished." -------------------------------------------------------------------------------- /scripts/login2so.reb: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | file: %login2so.reb 3 | date: 26-April-2014 4 | author: "Graham Chiu" 5 | purpose: { 6 | login to stackoverflow using your stackexchange credentials 7 | returns the usr cookie and fkey 8 | confirmed as working using the sochat client 9 | } 10 | ] 11 | 12 | sx-email: stackexchange-email@somewhere.com ; email! 13 | sx-password: "-- password ---" ; string! 14 | chat-page: http://chat.stackoverflow.com/rooms/291/rebol-and-red ; url! 15 | 16 | ; load modified http protocol to return the info object on failed http redirect 17 | print "loading modified prot-http.r3" 18 | do https://raw.githubusercontent.com/gchiu/Rebol3/master/protocols/prot-http.r3 19 | print "loading altwebform.r" 20 | do http://reb4.me/r3/altwebform.r 21 | 22 | login2so: func [email [email!] password [string!] chat-page [url!] 23 | /local fkey root loginpage cookiejar result err 24 | ][ 25 | fkey: none 26 | root: https://stackoverflow.com 27 | ; grab the first fkey from the login page 28 | print "reading login page" 29 | loginpage: to string! read https://stackoverflow.com/users/login 30 | 31 | either parse loginpage [thru "se-login-form" thru {action="} copy action to {"} thru "fkey" thru {value="} copy fkey to {"} thru {"submit-button"} thru {value="} copy login to {"} to end][ 32 | postdata: to-webform reduce ['fkey fkey 'email email 'password password 'submit-button login] 33 | if error? err: try [ 34 | result: to-string write join root action postdata 35 | ][ 36 | cookiejar: reform err/arg2/headers/set-cookie 37 | parse cookiejar [ to "usr=" copy cookiejar to ";" ] 38 | result: write chat-page compose/deep [GET [cookie: (cookiejar)]] 39 | result: reverse decode 'markup result 40 | ; now grab the new fkey for the chat pages 41 | foreach tag result [ 42 | if tag? tag [ 43 | if parse tag [thru "fkey" thru "hidden" thru "value" thru {"} copy fkey to {"} to end][ 44 | fkey: to string! fkey 45 | break 46 | ] 47 | ] 48 | ] 49 | ] 50 | return make object! compose [fkey: (fkey) cookie: (cookiejar)] 51 | 52 | ][ 53 | return make object! [fkey: none cookie: none] 54 | ] 55 | ] 56 | 57 | ; example 58 | 59 | print "reading ..." 60 | result: login2so sx-email sx-password chat-page 61 | 62 | ?? result 63 | write clipboard:// mold result 64 | halt -------------------------------------------------------------------------------- /scripts/loginso.reb: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | file: %loginso.reb 3 | author: "Graham Chiu" 4 | date: 21-April-2014 5 | version: 0.0.4 6 | notes: { 7 | 1. Click on the "Fetch" button which grabs the web page and displays it in the area face. 8 | 2. Cick on the "Count Forms" button which parses the page to see how many web forms are embedded. 9 | 3. For Stackoverflow, click on "Form 2" button 10 | 4. Click on "Extract Form Data" to extract the field names and data for that form 11 | 5. Click on the empty cells and edit them using the keyboard "e" 12 | 6. Click on the "Submit Form" button to get the cookies and Fkey for Stackoverflow 13 | 14 | parse rule will crash at times 15 | } 16 | history: { 17 | 20-Apr-2014 allow editing of text table to enter form data ( click on the field, and enter "e" from keyboard to edit a field ) 18 | } 19 | ] 20 | 21 | do https://raw.githubusercontent.com/gchiu/Rebol3/master/protocols/prot-http.r3 22 | 23 | if not value? 'url-decode [ 24 | if not exists? %altwebform.r3 [ 25 | write %altwebform.r3 read http://reb4.me/r3/altwebform.r 26 | ] 27 | do %altwebform.r3 28 | ] 29 | 30 | if not value? 'to-text [ 31 | if not exists? %r3-gui.r3 [ 32 | write %r3-gui.r3 read http://development.saphirion.com/resources/r3-gui.r3 33 | ] 34 | do %r3-gui.r3 35 | ] 36 | 37 | forms: copy [] 38 | 39 | 40 | ;remove quotes 41 | remove-quotes: func [txt [string!]][ 42 | remove head remove back tail txt 43 | ] 44 | 45 | ; returns a bunch of pairs from a form 46 | parse-form: funct [txt][ 47 | data: copy [] 48 | alpha: complement charset space 49 | ; get the form action and method 50 | parse txt [ 51 | (tmp: copy []) 52 | thru "action" any space "=" any space copy action some alpha ( 53 | remove-quotes action 54 | append tmp join get-face sitefld action 55 | ) 56 | thru "method" any space "=" thru {"} copy method to {"} ( 57 | append tmp method 58 | append/only data tmp 59 | ) 60 | ] 61 | ; now get the input name vaue pairs 62 | html: decode 'markup to-binary txt 63 | foreach tagged html [ 64 | trim/head/tail tagged 65 | parse form tagged [ 66 | "<" any space "input" thru "name" thru "=" thru {"} copy name to {"} 67 | (repend/only data copy [name ""] value: none) 68 | thru "value" any space "=" thru {"} copy value to {"} to end 69 | (if string? value [ 70 | append remove back tail last data value 71 | ] 72 | ) 73 | ] 74 | ] 75 | data 76 | ] 77 | 78 | view [ 79 | vgroup [ 80 | hgroup [ 81 | label "Site:" sitefld: field "https://stackoverflow.com/users/login" 82 | ] 83 | button "Fetch" on-action [ 84 | if error? try [ 85 | set 'forms copy [] 86 | page: read to-url get-face sitefld 87 | set-face htmldata to-string page 88 | ][ 89 | alert "Page read error" 90 | ] 91 | ] 92 | ] 93 | vgroup [ 94 | label "Page Data" 95 | htmldata: area 96 | ] 97 | hgroup [ 98 | button "Count forms" on-action [ 99 | set 'forms copy [] 100 | if not empty? page: get-face htmldata [ 101 | cnt: 0 102 | alert either parse page [ 103 | some [ 104 | to "" 107 | append forms tmp 108 | ) 109 | ] to end 110 | ][ 111 | reform ["Found " cnt "forms"] 112 | ]["No forms found"] 113 | 114 | ] 115 | ] 116 | button "Form 1" on-action [ 117 | view/modal compose [ 118 | area (pick forms 1) 119 | button "Extract Form Data" on-action [ 120 | if forms/1 [ 121 | data: parse-form pick forms 1 122 | close-window face 123 | view/modal compose/deep [ 124 | text-table 200x200 ["Name" #1 250 "Value" #2 200] [(data)] 125 | ] 126 | ] 127 | ] 128 | ] 129 | ] 130 | 131 | button "Form 2" on-action [ 132 | view/modal compose [ 133 | area (pick forms 2) 134 | button "Extract Form Data" on-action [ 135 | if forms/2 [ 136 | formdata: parse-form pick forms 2 137 | 138 | close-window face 139 | view/modal compose/deep [ 140 | t: text-table 200x200 ["Name" #1 250 "Value" #2 200] [(formdata)] 141 | vgroup [ 142 | button "Submit Form" on-action [ 143 | postdata: copy [] 144 | foreach f next get-face/field t 'data [ 145 | repend postdata [to-word f/1 f/2] 146 | ] 147 | postdata: to-webform postdata 148 | if error? err: try [ 149 | ; submit the form with the entered data 150 | page: write to-url get-face sitefld postdata 151 | print to-string page 152 | ][ 153 | info: err/arg2 154 | ; print ["Redirecting to: " info/headers/location] 155 | cookies: info/headers/set-cookie 156 | cookiejar: copy "" 157 | foreach cookie cookies [ 158 | append cookiejar join cookie ";" 159 | ] 160 | page: to string! write http://chat.stackoverflow.com/rooms/291/rebol-and-red compose/deep [ 161 | GET [Cookie: (cookiejar)] 162 | ] 163 | comment { ; this doesn't work inside the script but works fine outside 164 | page: find/last page "fkey" 165 | 166 | either parse page [thru {fkey"} any space thru "type" thru {value="} copy fkey to {"} to end][ 167 | 168 | ][fkey: copy ""] 169 | } 170 | ;; work round for the parse rule failing inside here 171 | page: find/last page "fkey" 172 | page: find/tail page {value="} 173 | fkey: copy/part page find page {"} 174 | view/modal reduce [ 175 | 'vgroup [ 176 | 'label "Cookies" 177 | 'area cookiejar 178 | 'hgroup [ 179 | 'label "Fkey" fkeyfld: 'field fkey 180 | ] 181 | ] 182 | ] 183 | ] 184 | ] 185 | ] 186 | ] 187 | ] 188 | ] 189 | ] 190 | ] 191 | 192 | button "Form 3" on-action [ 193 | view/modal compose [ 194 | area (pick forms 3) 195 | button "Extract Form Data" on-action [ 196 | if forms/3 [ 197 | data: parse-form pick forms 3 198 | close-window face 199 | view/modal compose/deep [ 200 | text-table 200x200 ["Name" #1 250 "Value" #2 200] [(data)] 201 | ] 202 | ] 203 | ] 204 | ] 205 | ] 206 | 207 | button "Form 4" on-action [ 208 | view/modal compose [ 209 | area (pick forms 4) 210 | button "Extract Form Data" on-action [ 211 | if forms/4 [ 212 | data: parse-form pick forms 4 213 | close-window face 214 | view/modal compose/deep [ 215 | text-table 200x200 ["Name" #1 250 "Value" #2 200] [(data)] 216 | ] 217 | ] 218 | ] 219 | ] 220 | ] 221 | button "Form 5" on-action [ 222 | view/modal compose [ 223 | area (pick forms 5) 224 | button "Extract Form Data" on-action [ 225 | if forms/5 [ 226 | data: parse-form pick forms 5 227 | close-window face 228 | view/modal compose/deep [ 229 | text-table 200x200 ["Name" #1 250 "Value" #2 200] [(data)] 230 | ] 231 | ] 232 | ] 233 | ] 234 | ] 235 | ] 236 | ] 237 | 238 | -------------------------------------------------------------------------------- /scripts/loginxport.reb: -------------------------------------------------------------------------------- 1 | #!/usr/local/bin/rebol3 -cs 2 | Rebol [ 3 | title: "WxC broadband usage" 4 | file: %loginxport.reb 5 | author: "gchiu" 6 | rights: 'bsd 7 | date: 12-July-2014 8 | notes: {needs rebol3 with https. prints WxC's data usage page to the browser} 9 | version: 0.0.2 10 | ] 11 | 12 | ;; need to make these your own 13 | user: "yourWxCusername" 14 | password: "yourWxCportalpassword" 15 | 16 | loginpage: https://www.xport.co.nz 17 | 18 | ; we're going to fake the google analytics, may not even be neccesary 19 | fixed-cookie: ajoin [ 20 | space 21 | {usage_units=mb;} space 22 | ;; google analytic cookies 23 | {__utma=183813615.1685615688.1403992183.1405076746.1405109092.41;} space 24 | {__utmc=183813615;} space 25 | {__utmz=183813615.1403992183.1.1.utmcsr=(direct)|utmccn=(direct)|utmcmd=(none)} 26 | ] 27 | 28 | ; grab my custom http protocol 29 | do https://raw.githubusercontent.com/gchiu/Rebol3/master/protocols/prot-http.r3 30 | 31 | ; returns a bunch of pairs from a form 32 | parse-form: funct [txt][ 33 | data: copy [] 34 | quot: charset [ #"^"" #"'"] 35 | alpha: complement union quot charset space 36 | ; get the form action and method 37 | tmp: copy [] 38 | parse txt [ 39 | thru "action" any space "=" any space any quot copy action some alpha ( 40 | append tmp join loginpage action 41 | ;?? tmp 42 | ;print tmp/1 43 | ) 44 | ] 45 | parse txt [ 46 | thru "method" any space "=" thru {"} copy method to {"} ( 47 | append tmp method 48 | append/only data tmp 49 | ) 50 | ] 51 | ; now get the input name vaue pairs 52 | html: decode 'markup to-binary txt 53 | foreach tagged html [ 54 | parse tagged [ 55 | any space "input" thru "name" thru "=" any space quot copy name some alpha 56 | ( 57 | repend/only data copy [name ""] value: none 58 | ) 59 | thru "value" any space "=" any space quot copy value some alpha to end 60 | (if tag? value [ 61 | append remove back tail last data value 62 | ] 63 | ) 64 | ] 65 | ] 66 | ; ?? data 67 | data 68 | ] 69 | 70 | ; using my debug mode to grab the headers, and cookies 71 | loginobject: write loginpage [ headers GET /] 72 | 73 | login: to string! loginobject/data 74 | cookies: collect [ 75 | foreach crumb loginobject/spec/debug/headers/set-cookie [ 76 | keep append first parse crumb none ";" 77 | ] 78 | ] 79 | 80 | login-cookie: rejoin [ cookies fixed-cookie ] 81 | 82 | ; ?? login-cookie 83 | 84 | ; grab the form 85 | 86 | if parse login [ thru " to end ][ 87 | ; print "got the form" 88 | replace/all form1: to string! form1 {'} {"} 89 | pairs: parse-form form1 90 | ; build the submit string 91 | target: first take pairs 92 | payload: copy "" 93 | foreach pair pairs [ 94 | case [ 95 | pair/1 = [ append payload ajoin [ "username=" user "&"]] 96 | pair/1 = [ append payload ajoin [ "password=" password "&"]] 97 | pair/1 = [] 98 | true [ append payload rejoin [to string! pair/1 "=" to string! pair/2 "&"]] 99 | ] 100 | ] 101 | ;take/last payload 102 | append payload "next=" 103 | ;?? payload 104 | ;?? target 105 | 106 | if error? err: try [ 107 | result: to string! write target compose/deep [ 108 | POST 109 | [ 110 | Accept: "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8" 111 | Origin: https://www.xport.co.nz 112 | Referer: https://www.xport.co.nz/ 113 | Accept-Encoding: "gzip,deflate,sdch" 114 | Accept-Language: "en-GB,en-US;q=0.8,en;q=0.6" 115 | Content-Type: "application/x-www-form-urlencoded; charset=utf-8" 116 | cookie: (login-cookie) 117 | ] 118 | (payload) 119 | ] 120 | ][ 121 | ; we should now have the new sessionid, and redirect page 122 | redirect: to url! err/arg2/headers/location 123 | parse err/arg2/headers/set-cookie [ to "sessionid" copy sessionid thru ";"] 124 | ] 125 | ] 126 | 127 | ;?? redirect 128 | ;?? sessionid 129 | ;?? cookies 130 | 131 | forall cookies [ 132 | if "sessionid" = copy/part cookies/1 9 [ 133 | remove cookies 134 | ; print "removed old sessionid" 135 | break 136 | ] 137 | ] 138 | 139 | append cookies sessionid 140 | 141 | ;?? cookies 142 | 143 | session-cookie: reform [ cookies fixed-cookie ] 144 | 145 | ; we want broadband usage 146 | broadband-data: to string! write rejoin [ redirect "/services/internet/broadband/" user "/" ] compose/deep [ GET [ cookie: (session-cookie) "/" ]] 147 | 148 | ; turn all relative urls into absolute 149 | foreach [original final] [ 150 | {src="/} {src="https://www.xport.co.nz/} 151 | {href="/} {href="https://www.xport.co.nz/} 152 | ][ 153 | replace/all broadband-data original final 154 | ] 155 | 156 | prin ["Content-type: text/html" crlf crlf] 157 | print broadband-data 158 | 159 | ; for local testing, uncomment these next two lines 160 | ; write %broadband.html broadband-data 161 | ; browse %broadband.html 162 | -------------------------------------------------------------------------------- /scripts/mediawiki-scrape.r3: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | title: "Mediawiki Port" 3 | Author: "Graham Chiu" 4 | Date: 3-June-2013 5 | File: %mediwiki-scrape.r3 6 | Purpose: {Grab all the main content off the rebol.net pages, and using pandoc convert to asciidoc} 7 | Version: 0.0.1 8 | ] 9 | 10 | gui: none 11 | ;; comment out this next line if no gui 12 | load-gui gui: true 13 | 14 | save-dir: %rebol.net/ 15 | if not exists? save-dir [make-dir save-dir] 16 | bad-links: copy [] 17 | error-log: %error.log 18 | write error-log "" 19 | 20 | log-error: func [txt] [ 21 | write/append error-log join txt newline 22 | ] 23 | 24 | ; use this to pause the gui 25 | pause: false 26 | 27 | site-url: http://www.rebol.net/wiki/ 28 | all-pages-url: http://www.rebol.net/wiki/Special:Allpages 29 | export-url: http://www.rebol.net/wiki/Special:Export/ 30 | 31 | print ["reading " all-pages-url] 32 | ; read the all pages page, and break into elements so that we can extract the links 33 | tags: decode 'markup read all-pages-url 34 | 35 | urls: copy [] 36 | foreach element tags [ 37 | if tag! = type? element [ 38 | if parse form element [{} to end] [ 39 | if all [ 40 | name 41 | page 42 | ; remove special pages 43 | not parse name ["Special:" to end] 44 | not parse page ["a href=" to end] 45 | not parse page ["Docbase:" to end] 46 | ] [ 47 | repend/only urls [name page] 48 | ] 49 | ] 50 | ] 51 | ] 52 | 53 | if gui [ 54 | view compose/only [ 55 | vpanel [ 56 | text-table ["Link Name" #1 250 "URL" #2 250] (urls) options [init-hint: 500x500] 57 | hpanel [ 58 | button "Carry On" green on-action [close-window face] 59 | button "Stop" red on-action [close-window face halt] 60 | ] 61 | ] 62 | ] 63 | ] 64 | 65 | process-site: func [urls gui [logic!] prog [object! none!] name [object! none!] output [object! none!] 66 | /local cnt len percent wikifile asciifile script page 67 | ] [ 68 | len: length? urls 69 | cnt: 0 70 | foreach link urls [ 71 | wait .1 72 | percent: ++ cnt / len 73 | if pause [break] 74 | ; read the export link and parse out the text including html entity formatted data 75 | if error? set/any 'err try [ 76 | either gui [ 77 | set-face prog percent 78 | set-face name link/2 79 | ] [ 80 | print rejoin ["completed " percent "%"] 81 | ] 82 | page: to string! read newlink: join export-url link/1 83 | if parse page [thru copy content to to end] [ 84 | if gui [set-face output content] 85 | write wikifile: rejoin [save-dir link/2 %.wiki] content 86 | ; now convert to asciidoc 87 | asciifile: append head clear find/last copy wikifile %.wiki %.txt 88 | script: rejoin [{pandoc -f mediawiki -t asciidoc -s "} wikifile {" -o "} asciifile {"}] 89 | if zero? call/wait script [ 90 | ; now remove extraneous internal edit links 91 | page: read asciifile 92 | replace/all page "[[]]" "" 93 | write asciifile page 94 | ] 95 | ] 96 | ] [ 97 | log-error rejoin ["Error with page link: " link/1 " named " link/2] 98 | log-error mold err 99 | ] 100 | ] 101 | ] 102 | 103 | 104 | either gui [ 105 | view [ 106 | vpanel [ 107 | hpanel 2 [ 108 | label "Progress: " prog: progress 109 | label "Page name: " name: field 110 | label "Content: " contents: area 111 | ] 112 | hpanel [ 113 | button "Start" green on-action [ 114 | process-site urls true prog name contents 115 | ] 116 | button "Cancel" gold on-action [ 117 | set 'pause true 118 | ] 119 | button "Quit" red on-action [unview/all halt] 120 | ] 121 | ] 122 | ] 123 | ] [ 124 | process-site false none none none 125 | ] 126 | -------------------------------------------------------------------------------- /scripts/microwebserver.reb: -------------------------------------------------------------------------------- 1 | REBOL [ 2 | title: "A tiny static HTTP server" 3 | author: 'abolka 4 | date: 2009-11-04 5 | notes: {ported from r3alpha to ren-c 30/1/2020 Graham Chiu - still buggy} 6 | ] 7 | 8 | crlf: #{0D0A} 9 | crlf2bin: join crlf crlf 10 | 11 | code-map: make map! [200 "OK" 400 "Forbidden" 404 "Not Found"] 12 | 13 | mime-map: make map! [ 14 | "html" "text/html" "htm" "text/html" "css" "text/css" "js" "application/javascript" 15 | "gif" "image/gif" "jpg" "image/jpeg" "png" "image/png" 16 | "r" "text/plain" "r3" "text/plain" "reb" "text/plain" 17 | "ico" "image/x-icon" 18 | ] 19 | 20 | error-template: trim/auto copy { 21 | $code $text

$text

22 |

Requested URI: $uri


shttpd.r on 23 |
REBOL 3 $r3 24 | } 25 | 26 | error-response: func [code uri values] [ 27 | values: [code (code) text (code-map/:code) uri (uri) r3 (system/version)] 28 | reduce [code "text/html" reword error-template compose values] 29 | ] 30 | 31 | start-response: func [port res code text type body] [ 32 | set [code type body] res 33 | write port unspaced ["HTTP/1.0" space code space code-map/:code crlf] 34 | write port unspaced ["Content-type:" space type crlf] 35 | write port unspaced ["Content-length:" space length-of body crlf] 36 | write port crlf 37 | ;; Manual chunking is only necessary because of several bugs in R3's 38 | ;; networking stack (mainly cc#2098 & cc#2160; in some constellations also 39 | ;; cc#2103). Once those are fixed, we should directly use R3's internal 40 | ;; chunking instead: `write port body`. 41 | port/locals: copy body 42 | ] 43 | 44 | send-chunk: func [port] [ 45 | ;; Trying to send data >32'000 bytes at once will trigger R3's internal 46 | ;; chunking (which is buggy, see above). So we cannot use chunks >32'000 47 | ;; for our manual chunking. 48 | if not empty? port/locals [write port take/part port/locals 32'000] 49 | ] 50 | 51 | handle-request: func [config req uri type file data ext] [ 52 | parse to-text req ["get " ["/ " | copy uri to " "]] 53 | uri: default [%index.html] 54 | parse uri [some [thru "."] copy ext to end (type: :mime-map/:ext)] 55 | type: default ["application/octet-stream"] 56 | if not exists? file: config/root/:uri [return error-response 404 uri] 57 | if error? entrap [data: read file] [return error-response 400 uri] 58 | reduce [200 type data] 59 | ] 60 | 61 | awake-client: func [event port res] [ 62 | port: event/port 63 | switch event/type [ 64 | 'read [ 65 | either find port/data crlf2bin [ 66 | res: handle-request port/locals/config port/data 67 | start-response port res 68 | ] [ 69 | read port 70 | ] 71 | ] 72 | 'wrote [ 73 | either empty? port/locals [ 74 | close port 75 | ][ 76 | send-chunk port 77 | ] 78 | ] 79 | 'close [close port print "event port closed"] 80 | ] 81 | ] 82 | 83 | awake-server: func [event client] [ 84 | if event/type = 'accept [ 85 | client: take event/port 86 | client/awake: :awake-client 87 | read client 88 | ] 89 | ] 90 | 91 | serve: func [web-port web-root listen-port] [ 92 | listen-port: open join tcp://: web-port 93 | listen-port/locals: make object! compose/deep [config: [root: (web-root)]] 94 | listen-port/awake: :awake-server 95 | print spaced ["serving on port" web-port "..."] 96 | wait listen-port 97 | ] 98 | 99 | ; example, uncomment everything below here 100 | ;web-port: 8081 101 | ;serve web-port system/options/path 102 | test: does [serve 8081 system/options/path] 103 | -------------------------------------------------------------------------------- /scripts/modflick.reb: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | Title: "Flick API Utilities" 3 | Author: "Graham Chiu" 4 | Date: 15-Jul-2017 5 | Home: https://forum.rebol.info/t/flickelectric-utilities/207 6 | File: %modflick.reb 7 | Version: 0.1.0 8 | Purpose: "Implement Flick API" 9 | Type: module 10 | Name: modflick 11 | Exports: [ 12 | Get-flick-map ; object! => map! 13 | Get-current-price ; flick-map [map!] => price [map!] 14 | price-from ; price [map!] => decimal! 15 | price-type-from ; price [map!] => string! 16 | price-starts-at ; price [map!] => date! 17 | price-ends-at ; price [map!] => date! 18 | ] 19 | History: [ 20 | 16-July-2017 "first pass at moving code to a module" 21 | ] 22 | Example: [ 23 | https://github.com/gchiu/Rebol3/blob/master/scripts/rebol-flick-api.reb 24 | ] 25 | ] 26 | 27 | webform: import 28 | to-webform: :webform/to-webform 29 | 30 | import 31 | 32 | ; API endpoints 33 | get-jwt: https://api.flick.energy/identity/oauth/token 34 | get-price: https://api.flick.energy/customer/mobile_provider/price 35 | 36 | jsdate2reboldate: function [ 37 | {convert JS zulu date to rebol local date value} 38 | jsdate [string!] 39 | ][ 40 | replace jsdate "T" "/" 41 | replace jsdate "Z" "" 42 | d: now/zone + load jsdate 43 | d/zone: now/zone 44 | d 45 | ] 46 | 47 | blank-flick-map: make map! compose [ 48 | access_token _ 49 | expires_in (now - 1) 50 | id_token _ 51 | token_type "bearer" 52 | ] 53 | 54 | flick-map: either exists? %flick-map.reb [ 55 | load %flick-map.reb 56 | ][ 57 | blank-flick-map 58 | ] 59 | ; probe flick-map 60 | 61 | Get-flick-map: function [ 62 | {returns a map! of flick credentials when passed an object containing password etc} 63 | form-vars [object!] 64 | ][ 65 | fm: flick-map ; load saved map if it exists 66 | either fm/expires_in < now [ 67 | if error? err: trap [ 68 | result: load-json to string! write get-jwt compose [POST (to-webform form-vars)] 69 | result/expires_in: now + to time! result/expires_in 70 | save/all %flick-map.reb result 71 | ][ 72 | print "Error obtaining map" 73 | probe err 74 | return blank-flick-map 75 | ] 76 | result 77 | ][ 78 | fm 79 | ] 80 | ] 81 | 82 | Get-current-price: function [ 83 | {reads price data which is returned as a JSON string} 84 | flick-map [map!] 85 | ][ 86 | write get-price compose [ 87 | GET [Authorization: (join-of "Bearer " flick-map/id_token)] 88 | ] 89 | ] 90 | 91 | price-from: function [ 92 | {shortcut to return value from map, returns decimal value} 93 | price [map!] 94 | ][ 95 | to decimal! price/needle/price 96 | ] 97 | 98 | price-type-from: function [ 99 | {shortcut to return the price type as string} 100 | price [map!] 101 | ][ 102 | spaced [price/needle/charge_methods/2 "per" price/needle/per] 103 | ] 104 | 105 | price-starts-at: function [ 106 | {shortcut to return the start time of price} 107 | price [map!] 108 | ][ 109 | jsdate2reboldate price/needle/start_at 110 | ] 111 | 112 | price-ends-at: function [ 113 | {shortcut to return the end time of price} 114 | price [map!] 115 | ][ 116 | jsdate2reboldate price/needle/end_at 117 | ] 118 | 119 | comment { 120 | ; sample JSON map! returned by get-current-price after turned into a Rebol map! 121 | 122 | make map! [ 123 | kind "mobile_provider_price" 124 | customer_state "active" 125 | needle make map! [ 126 | price "21.004" 127 | status "urn:flick:market:price:forecast" 128 | unit_code "cents" 129 | per "kwh" 130 | start_at "2017-07-15T23:30:00Z" 131 | end_at "2017-07-15T23:59:59Z" 132 | now "2017-07-15T23:30:45.580Z" 133 | type "rated" 134 | charge_methods [ 135 | "kwh" 136 | "spot_price" 137 | ] 138 | components [ 139 | make map! [ 140 | charge_method "kwh" 141 | value "0.113" 142 | ] 143 | make map! [ 144 | charge_method "kwh" 145 | value "1.5" 146 | ] 147 | make map! [ 148 | charge_method "kwh" 149 | value "7.25" 150 | ] 151 | make map! [ 152 | charge_method "spot_price" 153 | value "12.141" 154 | ] 155 | ] 156 | ] 157 | ] 158 | } 159 | -------------------------------------------------------------------------------- /scripts/odbc-test.reb: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | Title: "ODBC Test Script for Firebird 3.0" 3 | Description: { 4 | This script does some basic table creation, assuming you have 5 | configured an ODBC connection with the DSN "Rebol" that has a "test" 6 | database inside it. Then it queries to make sure it can get the 7 | data back out. 8 | } 9 | version: 0.0.4 10 | date: 2-June-2017 11 | notes: {add a format-sql function, avoid using reserved names for tables, don't drop tables so we can examine in another DB browser} 12 | ] 13 | 14 | system/options/dump-size: 1000 15 | failures: copy [] 16 | success: copy [] 17 | 18 | tables: [ 19 | bit "BOOLEAN" [#[TRUE] #[FALSE] #[TRUE]] 20 | 21 | ; tinyint_s "SMALLINT" [-128 -10 0 10 127] 22 | ; tinyint_u "SMALLINT UNSIGNED" [0 10 20 30 255] 23 | smallint_s "SMALLINT" [-32768 -10 0 10 32767] 24 | ; smallint_u "SMALLINT UNSIGNED" [0 10 20 30 65535] 25 | integer_s "INT" [-2147483648 -10 0 10 2147483647] 26 | ; integer_u "INT UNSIGNED" [0 10 20 30 4294967295] 27 | bigint_s "BIGINT" [-9223372036854775808 -10 0 10 9223372036854775807] 28 | ; 29 | ; Note: though BIGINT unsigned storage in ODBC can store the full range of 30 | ; unsigned 64-bit values, Rebol's INTEGER! is always signed. Hence it 31 | ; is limited to the signed range. 32 | ; 33 | ; bigint_u "BIGINT UNSIGNED" [0 10 20 30 9223372036854775807] 34 | 35 | ; real "DOUBLE" [-3.4 -1.2 0.0 5.6 7.8] 36 | double "DOUBLE PRECISION" [-3.4 -1.2 0.0 5.6 7.8] 37 | float "FLOAT(20)" [-3.4 -1.2 0.0 5.6 7.8] 38 | numeric "NUMERIC(18,2)" [-3.4 -1.2 0.0 5.6 7.8] 39 | decimal "DECIMAL(3,2)" [-3.4 -1.2 0.0 5.6 7.8] 40 | 41 | date "TIMESTAMP" [12-Dec-2012 21-Apr-1975] 42 | time "TIME" [10:00 11:01:12 12:13:14.1 12:13:14.12 03:04:00.123] 43 | timestamp "TIMESTAMP" [30-May-2017/14:23:08 12-Dec-2012] 44 | 45 | char "CHAR(3)" [{abc} {def} {ghi}] 46 | varchar "VARCHAR(10)" ["" "abc" "defgh" "jklmnopqrs"] 47 | 48 | nchar "NCHAR(3)" ["abc" "ταБ" "ghi"] 49 | nvarchar "VARCHAR(10)" ["" "abc" "ταБЬℓσ" "٩(●̮̮̃•̃)۶"] 50 | 51 | binary "CHAR(3)" [#{000000} #{010203} #{FFFFFF}] 52 | varbinary "CHAR(10)" [#{} #{010203} #{DECAFBADCAFE}] 53 | blob "BLOB(10)" [#{} #{010203} #{DECAFBADCAFE}] 54 | ] 55 | 56 | connection: open odbc://Rebol 57 | statement: first connection 58 | 59 | debug: func [x][print/eval x x] 60 | 61 | format-sql: function [ 62 | {replace all ? in sql-data/1 [string!] with values from sql-data/2 [block!]} 63 | sql-data [block!] 64 | ][ 65 | sql-string: copy sql-data/1 66 | values: sql-data/2 67 | for-each value values [ 68 | case [ 69 | number? :value [ 70 | replacement: value 71 | ] 72 | word? :value [ 73 | replacement: value 74 | ] 75 | any [time? :value string? :value ][ 76 | replacement: ajoin [{'} value {'}] 77 | ] 78 | date? :value [ 79 | ; convert to GMT 80 | attempt [value: value - value/zone | value/zone: 0:00] 81 | replace value: form value "/" space 82 | replacement: ajoin [{'} value {'}] 83 | ] 84 | binary? :value [ 85 | replacement: form value 86 | replace replacement "{" {'} 87 | replace replacement "}" {'} 88 | replace replacement "#" {x} 89 | ] 90 | logic? :value [ 91 | replacement: either :value ["TRUE"]["FALSE"] 92 | ] 93 | true [ 94 | print/eval ["oops, missed one " type-of value] 95 | fail "switch does not match type-of" 96 | ] 97 | ] 98 | replace sql-string "?" replacement 99 | ] 100 | sql-string 101 | ] 102 | 103 | clear failures 104 | clear success 105 | for-each [name sqltype content] tables [ 106 | ; 107 | ; Drop table if it exists 108 | ; comment { 109 | trap [ 110 | print ["dropping table" uppercase join-of "REB" form name] 111 | insert statement 112 | debug unspaced [ 113 | {DROP TABLE "} uppercase join-of "REB" form name {"} 114 | ] 115 | ] 116 | ;} 117 | 118 | ; Create table, each one of which has a single field "value" as the 119 | ; primary key, of the named type. 120 | ; id integer generated by default as identity primary key 121 | ; 122 | 123 | dump [name sqltype content] 124 | 125 | insert statement 126 | debug unspaced [ 127 | {CREATE TABLE "} 128 | join-of "REB" uppercase form name 129 | {" (} 130 | {ID integer generated by default as identity primary key, } 131 | {"SQLVALUE"} 132 | space sqltype space 133 | {NOT NULL} 134 | {)} 135 | ] 136 | 137 | ; insert statement {commit;} 138 | 139 | ; Insert the values. As a side effect, here we wind up testing the 140 | ; parameter code for each type. 141 | ; 142 | for-each value content [ 143 | ; insert statement 144 | s: format-sql 145 | reduce compose/deep [ 146 | unspaced [ 147 | {INSERT INTO "} 148 | join-of "REB" uppercase form name 149 | {" ("SQLVALUE") VALUES (?)} 150 | ] [(value)] 151 | ] 152 | dump s 153 | insert statement s 154 | 155 | ] 156 | 157 | ; insert statement "commit;" 158 | 159 | ; Query the rows and make sure the values that come back are the same 160 | ; 161 | insert statement 162 | debug unspaced [ 163 | {SELECT "SQLVALUE" FROM "} join-of "REB" uppercase form name {"} 164 | ] 165 | rows: copy statement 166 | actual: copy [] 167 | for-each row rows [ 168 | ; assert [1 = length-of row] 169 | append actual first row 170 | ] 171 | 172 | print mold actual 173 | print mold content 174 | 175 | print either (sort copy actual) = (sort copy content) [ 176 | append success sqltype 177 | "QUERY MATCHED ORIGINAL DATA" 178 | ][ 179 | append failures sqltype 180 | "QUERY DID NOT MATCH ORIGINAL DATA" 181 | ] 182 | 183 | print-newline 184 | ] 185 | 186 | insert statement "commit" 187 | close statement 188 | close connection 189 | 190 | unless empty? failures [ 191 | print "Failed on: " 192 | dump failures 193 | ] 194 | unless empty? success [ 195 | print "Success on:" 196 | dump success 197 | ] 198 | -------------------------------------------------------------------------------- /scripts/rebol-flick-api.reb: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | title: "Flick Spot Price" 3 | file: %rebol-flick-api.reb 4 | author: "Graham" 5 | date: 14-July-2017 6 | version: 0.1.3 7 | notes: {api documentation obtained from https://github.com/madleech/FlickElectricApi 8 | HELP at https://forum.rebol.info/t/flickelectric-utilities/207 9 | 10 | 1. Download a rebol interpreter from here http://metaeducation.s3.amazonaws.com/index.html 11 | 2. Rename it to r3 (or r3.exe if using windows ) 12 | 3. On linux - chmod +x ./r3 13 | 4. Download this script, use the raw view https://raw.githubusercontent.com/gchiu/Rebol3/master/scripts/rebol-flick-api.reb 14 | 5. Use an editor to change the last 4 values in this header 15 | 6. From a shell, run the script like this c:\users\path\to\download\r3 rebol-flick-api.reb 16 | 17 | } 18 | ; user details which do change! 19 | username: the-email-you-use-with-flick-goes-here@somewhere.com 20 | password: "your-password-goes-here" 21 | waitmins: 10 ; maybe 30 is better 22 | save2Db?: #[false] ; #[true] 23 | ] 24 | 25 | import 26 | 27 | save2Db?: system/script/header/save2Db? 28 | waitperiod: system/script/header/waitmins 29 | 30 | form-vars: make object! [ 31 | ; API vars - cient_id and secret are the OAUTH credentials for the Android client, and don't change 32 | grant_type: "password" 33 | client_id: "le37iwi3qctbduh39fvnpevt1m2uuvz" 34 | client_secret: "ignwy9ztnst3azswww66y9vd9zt6qnt" 35 | username: system/script/header/username 36 | password: system/script/header/password 37 | ] 38 | 39 | flick-map: make object! [expires_in: now - 1] 40 | 41 | display-current-price: does [ 42 | forever [ 43 | if flick-map/expires_in < now [ 44 | print "Loading id_token" 45 | flick-map: Get-flick-map form-vars 46 | ] 47 | if flick-map/expires_in > now [ 48 | ; current id_token still valid 49 | if error? err: trap [ ; trap the network read 50 | price: load-json to string! Get-current-price flick-map 51 | time-at: price-at-now price 52 | time-until: price-ends-at price 53 | print/only spaced ["At" 54 | time-at/time 55 | price-from price "cents" 56 | price-type-from price 57 | "valid until" 58 | time-until/time 59 | "in about" 60 | round divide to-integer difference time-until now 60 "mins" 61 | ] 62 | ; and if you want to save the data to an influxDb, here's sample code, wrapping it in an attempt in case the Db server isn't on 63 | if save2Db? [ 64 | print "trying to save db data" 65 | if error? err: trap [ 66 | write http://127.0.0.1:8086/write?db=FlickUsage compose [POST (join-of "spotRate,location=home spotNow=" price-from price)] 67 | ][ 68 | print "*** Unable to save to DB" 69 | probe err 70 | ] 71 | ] 72 | ][ 73 | ; can't get price 74 | print "*** Unable to fetch pricing data" 75 | probe err 76 | ] 77 | ] 78 | print spaced ["; sleeping for" waitperiod "mins"] 79 | ; process/sleep 60 * waitperiod ; not using this as can't break out using Control-C 80 | wait/only 60 * waitperiod 81 | ] 82 | ] 83 | 84 | display-current-price 85 | -------------------------------------------------------------------------------- /scripts/rebol-flick-forecast-api.reb: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | file: %rebol-flick-forecast-api.reb 3 | author: "Graham" 4 | date: 14-July-2017 5 | notes: {api documentation obtained from https://github.com/madleech/FlickElectricApi 6 | Also see https://github.com/gchiu/Rebol3/wiki/Flick-API-and-Rebol 7 | 8 | 1. Download a rebol interpreter from here http://metaeducation.s3.amazonaws.com/index.html 9 | 2. Rename it to r3 (or r3.exe if using windows ) 10 | 3. On linux - chmod +x ./r3 11 | 4. Download this script, use the raw view https://raw.githubusercontent.com/gchiu/Rebol3/master/scripts/rebol-flick-forecast-api.reb 12 | 5. Use an editor to change the last 3 values in this header 13 | 6. From a shell, run the script like this c:\users\path\to\download\r3 rebol-flick-api.reb 14 | } 15 | ; NB: user details which do change! 16 | username: the-email-you-use-with-flick-goes-here@somewhere.com 17 | password: "your-password-goes-here" 18 | supply_node: "your-supply-node" ; Karori is "1791ac20-df64-4235-8d06-562cc24d22e6" 19 | ] 20 | 21 | net-trace off 22 | 23 | import 24 | import 25 | 26 | infeasible: "Can not compute!" ; see https://news.flickelectric.co.nz/2017/05/18/forecast-to-final-prices/ 27 | infeasible-price: 50'000 28 | 29 | ; API endpoints 30 | get-jwt: https://api.flick.energy/identity/oauth/token 31 | ; old api 32 | ; get-price: https://api.flick.energy/customer/mobile_provider/price 33 | ; current api 34 | get-price: rejoin [https://api.flick.energy//rating/forecast_prices?supply_node=/network/nz/supply_nodes/ system/script/header/supply_node "&number_of_periods_ahead=1"] 35 | 36 | form-vars: make object! [ 37 | ; API vars - cient_id and secret are the OAUTH credentials for the Android client, and don't change 38 | grant_type: "password" 39 | client_id: "le37iwi3qctbduh39fvnpevt1m2uuvz" 40 | client_secret: "ignwy9ztnst3azswww66y9vd9zt6qnt" 41 | username: system/script/header/username 42 | password: system/script/header/password 43 | ] 44 | 45 | jsdate2reboldate: function [ 46 | {convert JS zulu date to rebol local date value} 47 | jsdate [string!] 48 | ][ 49 | replace jsdate "T" "/" 50 | replace jsdate "Z" "" 51 | d: now/zone + load jsdate 52 | d/zone: now/zone 53 | d 54 | ] 55 | 56 | blank-flick-map: make map! compose [ 57 | access_token _ 58 | expires_in (now - 1) 59 | id_token _ 60 | token_type "bearer" 61 | ] 62 | 63 | flick-map: either exists? %flick-map.reb [ 64 | load %flick-map.reb 65 | ][ 66 | blank-flick-map 67 | ] 68 | 69 | ; probe flick-map 70 | 71 | Get-flick-map: func [ /local result err][ 72 | if error? err: trap [ 73 | result: load-json to string! write get-jwt compose [POST (to-webform form-vars)] 74 | result/expires_in: now + to time! result/expires_in 75 | save/all %flick-map.reb result 76 | ][ 77 | print "Error obtaining map" 78 | probe err 79 | return blank-flick-map 80 | ] 81 | result 82 | ] 83 | 84 | ; net-trace on 85 | 86 | display-current-price: does [ 87 | print spaced ["Using electricity supply node of" system/script/header/supply_node] 88 | forever [ 89 | next-time: now + 0:10:00 ; default of 10 mins if can't get the flick credentials 90 | if flick-map/expires_in < now [ 91 | print "Fetching id_token" 92 | flick-map: Get-flick-map 93 | ] 94 | if flick-map/expires_in > now [ 95 | ; id_token still valid 96 | if error? err: trap [ 97 | price: load-json to string! write get-price compose [ 98 | GET [Authorization: (join-of "Bearer " flick-map/id_token)] 99 | ] 100 | if (current-price: price/prices/1/price/value) = infeasible-price [current-price: infeasible] 101 | if (next-price: price/prices/2/price/value) = infeasible-price [next-price: infeasible] 102 | print spaced ["Current price at" jsdate2reboldate price/prices/1/start_at current-price price/prices/1/price/unit_code "per" price/prices/1/price/per] 103 | print spaced ["Next price at" next-time: jsdate2reboldate price/prices/2/start_at next-price price/prices/2/price/unit_code "per" price/prices/2/price/per] 104 | ][ 105 | ; can't get price 106 | probe err 107 | ] 108 | ] 109 | ; next-time is when the price changes, so let's wait until then 110 | print spaced ["... sleeping for about" round divide to-integer (difference next-time now) 60 "mins"] 111 | wait/only difference next-time now ;60 * waitperiod 112 | ] 113 | ] 114 | 115 | display-current-price 116 | -------------------------------------------------------------------------------- /scripts/task-client.reb: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | title: "Task Client" 3 | file: task-client.reb 4 | Author: "Graham Chiu" 5 | Date: 12-July-2014 6 | Notes: {run the gui-server first and then run mulitple clients} 7 | ] 8 | 9 | ; read the task server to see if task available. 10 | task-server: http://127.0.0.1:8080/ 11 | 12 | request-task: join task-server "request-task" 13 | answer-task: join task-server "answer-task" 14 | 15 | forever [ 16 | print "Fetching request" 17 | r: to string! read request-task 18 | either any [ r = "notok" none? r ][ 19 | ; no task, so wait 20 | print "no tasks available" 21 | wait 2 22 | ][ 23 | either object? task: load r [ 24 | print [ "Doing command " task/cmd] 25 | result: do task/cmd 26 | id: task/id 27 | response: write rejoin [ answer-task "/" id ] result 28 | wait 2 29 | print "Sent results" 30 | ][ 31 | probe type? task 32 | probe task 33 | wait 2 34 | ] 35 | ] 36 | ] -------------------------------------------------------------------------------- /scripts/test-send.reb: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | file: %test-send.reb 3 | notes: {testing prot-send} 4 | date: 6-May-2017 5 | author: "Graham" 6 | contact: http://chat.stackoverflow.com/rooms/291/rebol 7 | ] 8 | 9 | import %prot-smtp.reb 10 | do %prot-send.reb 11 | 12 | comment { ; set-net is now included in ren-c 13 | set-net: procedure [bl [block!] 14 | ][ 15 | if (length-of bl) <> 6 [fail "Needs all 6 parameters for set-net"] 16 | set words-of system/user/identity bl 17 | ] 18 | } 19 | 20 | set-net data: [me@gmail.com "smtp.gmail.com:465" "pop.gmail.com:995" "me@gmail.com" "gmail-application-password" "ihug.net"] 21 | 22 | probe system/user/identity 23 | 24 | net-trace on 25 | 26 | send me@gmail.com "testing from gmail" 27 | -------------------------------------------------------------------------------- /scripts/test-smtp.reb: -------------------------------------------------------------------------------- 1 | Rebol [ 2 | file: %test-smtp.reb 3 | notes: {needs a build newer than 5-May-2017} 4 | ] 5 | 6 | system/user/identity/fqdn: "ihug.co.nz" ; this needs to be done before importing the protocol, preferably in user.r 7 | import %prot-smtp.reb ; or import 8 | 9 | to-itime: func [ 10 | {Returns a standard internet time string (two digits for each segment)} 11 | time [time! number!] 12 | ][ 13 | time: make time! time 14 | rejoin [ 15 | next form 100 + time/hour ":" 16 | next form 100 + time/minute ":" 17 | next form 100 + round/down time/second 18 | ] 19 | ] 20 | 21 | date2edate: func [ date ][ 22 | unspaced [ 23 | copy/part pick system/locale/days date/3 3 24 | ", " 25 | date/3 space 26 | copy/part pick system/locale/months date/2 3 space 27 | date/1 space 28 | to-itime date/4 space 29 | either date/5 >= 0:00 ["+"]["-"] 30 | date/5 31 | ] 32 | ] 33 | 34 | ; construct a valid email message 35 | message: ajoin [{To: } me@gmail.com { 36 | From: } "Graham Chiu" { <} drme@clear.net.nz {> 37 | Date: } date2edate now { 38 | Subject: testing from renc 39 | X-REBOL: Ren-C } rebol/commit { 40 | 41 | where's my kibble?}] 42 | 43 | net-trace on 44 | 45 | write smtp://me@gmail.com:gmail-application-password@smtp.gmail.com:465 compose [ 46 | from: me@gmail.com 47 | to: drme@clear.net.nz 48 | message: (message) 49 | ] 50 | -------------------------------------------------------------------------------- /scripts/test-storage.reb: -------------------------------------------------------------------------------- 1 | Rebol [] 2 | 3 | do https://gist.githubusercontent.com/rgchris/8621b68fd54cf6750d8e4668c8c97004/raw/9884edfcd13a18ebd915d109c7a63064e74fbb51/storage-scheme.reb 4 | 5 | print "create the port p" 6 | p: make port! [scheme: 'storage host: "Foo"] 7 | 8 | print "put data into the storage port which is in persistent storage on your drive" 9 | insert p "test" 10 | 11 | print "now retrieve the data" 12 | copy p 13 | 14 | -------------------------------------------------------------------------------- /scripts/userstuff.reb: -------------------------------------------------------------------------------- 1 | Rebol [] 2 | 3 | repo: lowercase ask "github/gitlab?" 4 | user: ask "Userid?" 5 | project: ask "Your project?" 6 | 7 | if any [ empty? repo empty? user empty? project][quit] 8 | 9 | file: _ 10 | 11 | case [ 12 | repo = "github" [file: to url! unspaced [https://github.com/ user "/" project "/blob/master/index.reb"]] 13 | repo = "gitlab" [file: to url! unspaced [https://gitlab.com/ user "/" project "/-/blob/master/index.reb"]] 14 | true [print "repo not found" quit] 15 | ] 16 | 17 | print ["Your userfile (file) is at: " file] 18 | 19 | -------------------------------------------------------------------------------- /scripts/web3works.r3: -------------------------------------------------------------------------------- 1 | REBOL [Title: "First Web 3.0 Script"] 2 | 3 | load-gui 4 | 5 | msg: compose [ 6 | "This program was downloaded from the Internet! " 7 | "It is " bold "leaner, meaner, and a whole lot cleaner." drop 8 | newline newline 9 | "Its size is: " (form size? %web3works.r3) " bytes." 10 | newline newline 11 | "Click source to view source code." 12 | ] 13 | 14 | view [ 15 | title "Web 3.0 works!" 16 | text-area msg 17 | vgroup [ 18 | button "Source" on-action [ 19 | view compose [code-area (to string! read %web3works.r3)] 20 | ] 21 | button "Close" on-action [ close-window face ] 22 | ] 23 | ] --------------------------------------------------------------------------------