Navigateur web intégré et piloté dans une application R2 View ou R3 GUI ?
deglingo24-Dec-2010/18:08:56+1:00
A votre avis, serait-il possible d'embarquer un navigateur web dans une application R2 View ou plus tard R3 GUI ? (en quelque sorte l'inverse du plugin IE/Firefox pour Rebol)

+ Eclipse RCP le fait par exemple avec son composant SWT Browser :
(http://wiki.eclipse.org/index.php/RCP_Browser_Example )
+ Eclipse RCP n'a pas redéveloppé un browser, il pilote le moteur d'1 des navigateurs installés sur le poste : IE piloté par OLE sur Windows, Mozilla (je crois) sur Linux, etc...
+ Il est capable de détecter des évènements venant du moteur du navigateur. Exemple : il détecte les changements de page grâce à un "LocationListener".

Pensez-vous que cela soit possible avec Rebol, et notamment le dernier point (récupérer des évènements du navigateur) ?
Est-ce que la librairie COMLib pourrait gérer cela, ou les extensions en R3 (avec le mécanisme de callbacks) ?

Merci si vous avez des infos là-dessus. Et, joyeux noël à tous.
shadwolf26-Dec-2010/9:04:20+1:00
un navigateur web dans R3/GUI j'ai évoqué le sujet on m'a dit d'aller me faire foutre ca te semble assez clair?


sur un plan complètement pratique il y a 2 façon de faire avec R3:

1) soit en passant par une librairie qui gère déjà le HTML comme webkit ou cairo suivant le niveau d'intégration qu'on veut. Evidement il faut aussi définir quel sera le niveau d'inter action voulu. Est ce qu'on veut du coté rebol une boite

2) soit en créant un moteur de rendu graphique en utilisant Draw/AGG. Comme le HTML a une vocation purement read only ca ne devrait pas être bien compliqué.

Personnellement je sais comment faire ce genre de widget modifier mais je n'ai pas envi de passer mon temps libre sur le sujet pour que d'autre aillent vendre dans mon dos mes idées.
shadwolf26-Dec-2010/9:09:59+1:00
Enfin notre guru a tous Carl prefererait que MakeDoc soit ulisé plutot que HTML, pour ce qui est de la documentation.
c'est pourquoi on entend parler depuis quelques années d'une widget de rendu MakeDoc.
deglingo27-Dec-2010/13:20:57+1:00
Merci pour la réponse.

En fait, mon objectif serait de ne pas redévelopper la roue, en l'occurence un navigateur web, de l'encapsuler dans une application graphique Rebol, et du coup de bénéficier de toutes ses capacités (javascript, html, et autres), sans avoir à developper un moteur de rendu graphique HTML, un interpréteur Javascript, sans avoir non plus à passer par une librairie gérant le HTML .

La librairie Java SWT permet de faire cela parce qu'elle attaque directement les composants bas niveau installés sur le système d'exploitation sur lequel elle tourne (les fenêtres ont directement le look & feel du système).
C'est pour cela qu'elle peut afficher le rendu graphique d'un navigateur web existant (IE, Firefox, etc...) et de ses plugins à l'intérieur d'une fenêtre SWT.
Didec27-Dec-2010/15:02:20+1:00
Maxim a réussi à encapsuler OpenGL alors je pense que via le host kit cela doit être possible.

Mais là, j'y connais rien. Jocko à déjà fait pas mal de choses sympa, il a peut-être un avis sur la question ?
nve27-Dec-2010/18:05:11+1:00
Sous Windows, avec Delphi on pouvait à l'époque récupérer le composant IE et interagir avec directement depuis Delphi.

shadwolf: je trouves cela dommage car un composant HTML permet énormément de choses.
Il y a 2 type d'application : soit effectivement le moteur de rendu HTML pour VID...
Mais surtout la partie exécution en silence pour faire du Mash-up.
Parce qu'avec REBOL en tant que moteur de mash-up, cela aurait été vraiment terrible...
jocko1-Jan-2011/11:14:21+1:00
Sous R3, je pense que celà ne pose pas trop de problèmes d'intégrer un composant webbrowser dans une fenêtre rebol, via une extension. Il doit falloir pour celà récupérer le handle de la fenêtre rebol dans lequel on veut afficher ce composant. Ceci dit, je ne vois pas un gros intérêt à cette fonction, compte tenu que le navigateur est une application de base sur tous les systèmes.
shadwolf1-Jan-2011/11:24:33+1:00
nve dessiné du texte ave l'agg de rebol 2 c'est une vraie galère. des viewer makedoc et makedoc pro ont été réalisé il y a quelques années en se servant d'une technique rudimentaire de clonage et de composition de face sur le wiki j'avais écris un article sur le sujet il me semble.

Tu peux partir de là et essayer de faire ton navigateur...
L'ennorme problème c'est que le web c'est plus uniquement du HTML il y a aussi des technologies annexes comme les CSS, Flash, la video l'audio le javascript etc... Et là ca complique les choses.
shadwolf1-Jan-2011/11:25:09+1:00
nve dessiné du texte ave l'agg de rebol 2 c'est une vraie galère. des viewer makedoc et makedoc pro ont été réalisé il y a quelques années en se servant d'une technique rudimentaire de clonage et de composition de face sur le wiki j'avais écris un article sur le sujet il me semble.

Tu peux partir de là et essayer de faire ton navigateur...
L'ennorme problème c'est que le web c'est plus uniquement du HTML il y a aussi des technologies annexes comme les CSS, Flash, la video l'audio le javascript etc... Et là ca complique les choses.
nve1-Jan-2011/17:45:36+1:00
En fait, un composant viewer HTML n'a pas d'intérêt selon moi. Par contre, un composant HTML permettant de simuler l'exécution pourrait être très intéressant pour faire du mash-up et le coupler avec Cheyenne par exemple.
Effectivement, il y a le pb du Flash, mais comptons sur 2 petites startup de la Sillicon Valley pour booster HTML 5.
Restera la partie Javascript. La solution passe-t-elle par un appel de module externe navigateur Web ? Comme on faisait en quelque sorte en Delphi pour le viewer HTML IE intégré dans l'application...
ldci2-Jan-2011/15:33:10+1:00
Bonjour
En recherchant dans mes archives, j'ai retrouvé sonar1.r qui avait été écrit en 2003 par errru@arcor.de
Ca fonctionne à minima et peut servir de base à quelque chose de plus élaboré

Amicalement




#! /usr/bin/rebol
REBOL [
Title: "SONAR1 web browser"
Date: 3-Nov-2003
Version: 0.0.5
File: %sonar1.r

Author: "errru"
Rights: "GNU GPL"
Email: errru@arcor.de

Needs: [view 1.2.8]

Purpose: {A small graphical web browser.}

Note: {
SONAR1 is a light-weight experimental web browser.

Web pages are presented in a simplified layout, happily
ignoring most of the HTML these pages usually consist of.
For now, that is. Because this project worked out so well,
there might actually come a more accurately rendering
future version, SONAR2. Which will take some time.

Tip: Besides URLs, you can also enter any valid REBOL
expression in the address field, e.g:

- alert "hi, there" ; display an alert box
- alert form system/stats ; display allocated memory
- alert reform links ; display all links
- recycle ; recycle memory
- read %file ; read address line from a file
- save %file cache ; save cache to a file
- clear cache ; clear the cache (see below)
- repend cache load %file ; load the cache again
- foreach l links [ .. ] ; ...you get the idea!

Special words accepted in expressions:
'links points to a block of all links on page
'cache points to the in-memory cache
'history points to the history
'content points to the layout of the current page
'about views this text

Still incomplete in this version of SONAR1:
- improve asynchronous downloading
- further testing and debugging
- display text files in <pre> ... </pre> format
- HTML forms
- cookies

<a href="mailto:errru@arcor.de">
Drop me an email</a>if you have questions or suggestions!
}

History: [
0.0.1 [31-Aug-2003 "first version of SONAR1"]
0.0.3 [03-Sep-2003 "a myriad of things"]
0.0.4 [18-Sep-2003 "detecting redirects, restructured html/process"]
0.0.5 [3-Nov-2003 "alive? always set to true" "goto uses correct suffix" "over feel for links"]
]
]

if system/version < second system/script/header/needs [
alert reform ["This script needs" system/script/header/needs "to run"]
quit
]

SONAR1: context [

options: context [
default-address: "about"
favorites: copy [http://www.rebol.com]
images: true
image-minsize: 23x23
indent: 20
margin: 80x12
min-width: 300
max-width: 800
cache-limit: 200
user-agent: copy system/schemes/HTTP/user-agent
view-size: 600x340
window-offset: 20x20
]

current-address: http://
content: none
history: make block! 100
cache: make block! 100
STOP: false

window: none
options-window: none
f-view: none
f-address: none
f-scroller: none
f-go: none
f-fav: none
f-add: none
f-status: none
f-textwidth: none
f-choose-fav: none

whitespace: charset " ^-^/"
alpha-num: charset [#"a" - #"z" #"A" - #"Z" #"0" - #"9"]

keymap: [
#"^M" [if same? system/view/focal-face f-address [evaluate-address]]
up [scroll-by -1]
down [scroll-by 1]
page-up [scroll-by/page -1]
page-down [scroll-by/page 1]
f1 [skip-history -1]
f2 [skip-history 1]
f3 [STOP: true]
f4 [edit-options]
]

signatures: [
image! [
#{474946383761} ;; GIF87a
#{474946383961} ;; GIF89a
#{FFD8FF} ;; JFIF
#{89504E470D0A1A0A} ;; PNG
#{4D42} ;; Microsoft DIB
]
]

extensions: [
image! [ ;; used to guess if it's an image
%.gif %.jpeg %.jpg %.png %.bmp
]
]

char-entities: [
"amp" #"&"
"quot" #"^""
"lt" #"<"
"gt" #">"
"nbsp" #" "
]

;; assuming ISO 8859-1 (latin 1) charset on client computer
use [c] [
c: #"^(A1)"
foreach n [
"iexcl" "cent" "pound" "curren" "yen" "brvbar"
"sect" "uml" "copy" "ordf" "laquo" "not"
"shy" "reg" "macr" "deg" "plusmn" "sup2"
"sup3" "acute" "micro" "para" "middot" "cedil"
"sup1" "ordm" "raquo" "frac14" "frac12" "frac34"
"iquest" "Agrave" "Aacute" "Acirc" "Atilde" "Auml"
"Aring" "AElig" "Ccedil" "Egrave" "Eacute" "Ecirc"
"Euml" "Igrave" "Iacute" "Icirc" "Iuml" "ETH"
"Ntilde" "Ograve" "Oacute" "Ocirc" "Otilde" "Ouml"
"times" "Oslash" "Ugrave" "Uacute" "Ucirc" "Uuml"
"Yacute" "THORN" "szlig" "agrave" "aacute" "acirc"
"atilde" "auml" "aring" "aelig" "ccedil" "egrave"
"eacute" "ecirc" "euml" "igrave" "iacute" "icirc"
"iuml" "eth" "ntilde" "ograve" "oacute" "ocirc"
"otilde" "ouml" "divide" "oslash" "ugrave" "uacute"
"ucirc" "uuml" "yacute" "thorn" "yuml"
][
repend char-entities [n c]
c: c + 1
]
]

;; see http://home.arcor.de/roland.hadinger/rebol/includes/2.demos/guard.r
guard: func [
{Evaluates a block only at the first recursion level, otherwise ignores it.}
[catch]
block [block! none!] "block to guard"
/status 'blocked? [word!] "get blocked status"
/local guard-blocks result
][
guard-blocks: [#[none]]
if status [set blocked? true]
if foreach b guard-blocks [
if same? block b [break/return none]
true
][
if status [set blocked? false]
insert/only guard-blocks block
set/any 'result do block
remove guard-blocks
get/any 'result
]
]

init: does [


set-options/reload

window: layout window-layout
layout-size: window/size

view-page "" 0x0 ;; creates empty pane
      center-face window
;view/new/options/offset window [resize] options/window-offset
view/new/options window [resize]
window/feel: make window/feel [
detect: func [face event] [
switch event/type [
scroll-line [scroll-by event/offset/y]
scroll-page [scroll-by/page event/offset/y]
resize [resize-window return true]
key [switch event/key keymap]
offset [options/window-offset: event/offset]
]
event
]
]

alive?: true

do-events
]

link-feel: make svv/vid-styles/BUTTON/feel [
engage: func [face action event] [
switch action [
time [
if not face/state [face/blinker: not face/blinker]
]
down [
face/state: on
show-address face/user-data/2
]
alt-down [
face/state: on
show-address face/user-data/2
]
up [
show-address none
if face/state [want face/user-data/2]
face/state: off
]
alt-up [
show-address none
if face/state [save-resource face/user-data/1]
face/state: off
]
over [
face/state: on
]
away [
face/state: off
]
]
cue face action
show face
]
over: func [face action event] [
if all [face/font face/font/colors] [
either action [
face/font/color: pick face/font/colors 2
show-address face/user-data/2
][
face/font/color: pick face/font/colors 1
show-address none
]
show face
face/font/color: first face/font/colors
]
]
]

window-styles: stylize [
btn-bright: btn 50x24 bold 255.172.0
btn-normal: btn 100x24 bold 255.255.255
status: text 0.0.0 229.227.218 no-wrap
fld-adr: field 100x23 101.98.95 101.98.95 font [
color: 255.255.255
] bold edge [
size: 0x0
] para [
origin: 6x2
]
]

view-styles: stylize [
hypertext: text
para [origin: 2x4 margin: 2x6]
font [space: 0x4 style: none]
boldtext: text
para [origin: 2x4 margin: 2x6]
font [space: 0x4 style: 'bold]
pretext: code no-wrap as-is
para [origin: 2x2 margin: 2x4]
font [space: 0x4 style: none]
hyperlink: button 248.248.248
edge [size: 1x1 color: 224.224.224]
font [colors: [0.0.0 255.224.0] shadow: none style: none]
effect []
with [feel: link-feel]
hyperlink-image: button 255.255.255
edge [size: 2x2 color: 0.0.0]
font [colors: [0.0.0 255.224.0] shadow: none]
effect []
with [feel: link-feel]
static-image: button 255.255.255
edge [size: 0x0 color: 0.0.0]
font [colors: [0.0.0 255.224.0] shadow: none]
effect []
with [feel: link-feel]
hrule: box 100x1 0.0.0
bullet: box 8x8 0.0.0 effect [oval 255.255.255]
]

layout [
f-choose-fav: choice 150x20 75.73.71 156.151.147 left
font [colors: [255.255.255 255.255.255] size: 11 shadow: 0x0 style: 'bold]
edge [size: 0x0 color: 0.0.0]
para [origin: 10x2]
]

layout [
styles view-styles
f-textwidth: hyperlink 1000 ""
]

;; main window
window-layout: [
styles window-styles
backcolor 0.0.0
origin 0 space 8x8
across pad 8x8
btn-normal "< back" [skip-history -1]
btn-normal "next >" [skip-history 1]
btn-normal "stop" [STOP: true]
btn-normal "options" [edit-options]
return pad 8x2
f-address: fld-adr (copy options/default-address) (options/view-size * 1x0 + -178x22)
pad 4x-2
f-go: btn-bright "go" [evaluate-address]
f-fav: btn-bright "fav" [choose-favorite]
f-add: btn-bright "+/-" [alter-favorite]
return space 0
f-view: box options/view-size 255.255.255
f-scroller: slider options/view-size * 0x1 + 20x0 0.0.0 255.255.255 edge [
size: 1x1
][
scroll-view
]
return
f-status: status options/view-size * 1x0 + 20x18 ""
sensor 0x0 rate 5 [guard [wait 0]]
]

layout-size: 0x0

resize-window: has [
delta
][
window/size: max window/size 540x200
delta: window/size - layout-size
layout-size: window/size

f-address/size/x: f-address/size/x + delta/x
f-go/offset/x: f-go/offset/x + delta/x
f-fav/offset/x: f-fav/offset/x + delta/x
f-add/offset/x: f-add/offset/x + delta/x
f-view/size: f-view/size + delta
f-scroller/size/y: f-scroller/size/y + delta/y
f-scroller/offset/x: f-scroller/offset/x + delta/x
f-status/offset/y: f-status/offset/y + delta/y
f-status/size/x: f-status/size/x + delta/x
options/view-size: f-view/size

show window
scroll-by 0
]

;; opens options-window
edit-options: has [f1 f2 f3 f4 f5 f6 f7 f8 f9] [

if all [options-window viewed? options-window] [return]
options-window: layout [
style text2 text 150 right 255.255.255 bold
style field2 field 200 edge [size: 1x1 color: 0.0.0]
style button2 btn 60 0.0.0 font [colors: [255.255.255 255.255.255]] bold
style check2 check edge [size: 2x2 color: 0.0.0]
backcolor 101.98.95
space 4x4
across
text2 "default address" f1: field2 (copy options/default-address) return
text2 "show images" f2: check2 (options/images) return
text2 "minimum image size" f3: field2 (mold options/image-minsize) return
text2 "indent width" f4: field2 (mold options/indent) return
text2 "margin" f5: field2 (mold options/margin) return
text2 "minimum width" f6: field2 (mold options/min-width) return
text2 "maximum width" f7: field2 (mold options/max-width) return
text2 "cache limit" f8: field2 (mold options/cache-limit) return
text2 "user agent string" f9: field2 (copy options/user-agent) return
pad 230x20
button2 "OK" [
options/default-address: copy f1/text
options/images: f2/data
options/image-minsize: any [attempt [to-pair f3/text] options/image-minsize]
options/indent: any [attempt [to-pair f4/text] options/indent]
options/margin: any [attempt [to-pair f5/text] options/margin]
options/min-width: any [attempt [to-integer f6/text] options/min-width]
options/max-width: any [attempt [to-integer f7/text] options/max-width]
options/cache-limit: any [attempt [to-integer f8/text] options/cache-limit]
options/user-agent: copy f9/text
save-options
set-options
unview
]
button2 "cancel" [unview]
]
view/new center-face/with options-window window
]

set-options: func [/reload] [
if reload [
attempt [
options: make options bind to-block read %sonar1-options.r 'system
]
]
if not empty? options/user-agent [
system/schemes/HTTP/user-agent: copy options/user-agent
]
]

save-options: does [
attempt [
save %sonar1-options.r third options
]
]

scroll-view: does [
if all [f-view content] [
content/offset/y: to-integer f-scroller/data * content/size/y * -1
]
guard [
wait 0
show f-view
]
]

scroll-by: func [n /page] [
f-scroller/data: min max 0.0 f-scroller/data + (
n * (either page [f-view/size/y] [20]) / max 1 content/size/y
) 1.0
show f-scroller
scroll-view
]

decode-entities: func [
text [string!]
/local result e c n
][
result: copy ""
parse/all text [
any [
end break
| #"&" opt [
"#x" copy e to #";" skip (
c: attempt [
all [
n: debase/base e 16
1 = length? n
to-char first n
]
]
)
| #"#" copy e to #";" skip (
c: attempt [
all [
n: to-integer e
1 <= n
255 >= n
to-char n
]
]
)
| copy e to #";" skip (
c: select/case char-entities e
)
] (
if c [append result c c: none]
)
| copy e [to #"&" | to end] (
if e [append result e]
)
]
]
result
]

evaluate-address: has [result] [
either error? set/any 'result try [
do bind load/all f-address/text in context [
history: SONAR1/history
cache: head SONAR1/cache
links: head SONAR1/html/links
content: head SONAR1/html/content
about: get in SONAR1 'view-about-info
] 'self
][
result: disarm result
alert reform bind (get result/id) (in result 'id)
][
if all [
not unset? get/any 'result
any [
file? result
url? result
email? result
none? result
]
][
want result
]
]
]

choose-favorite: has [list f] [
list: copy []
f-choose-fav/size/x: f-address/size/x + 178
foreach f options/favorites [
append list either string? f [f] [mold/only f]
]
choose/style/window/offset list func [face btn] [
f-address/text: copy face/text
f-address/line-list: none
] f-choose-fav window f-address/offset + (f-address/size * 0x1)
]

alter-favorite: has [value f] [
if all [
value: attempt [load f-address/text]
value <> 'none
not all [series? value empty? value]
][
either found? f: find/only options/favorites value [
if confirm reform ["Really remove" mold f/1 "from favorites?"] [
remove f
]
][
append/only options/favorites value
]
]
]

want: func [
address [file! url! email! none!]
/local new
][
either email! = type? address [
emailer/to address
][
if new: absolute-address address [
if all [not empty? head history f-view/pane] [
change back history f-view/pane/1/offset
]
history: tail repend clear history [copy new 0x0]
]
goto new 0x0
]
]

goto: func [
address [file! url! none!]
offset [pair!]
/local resource suffix
][
guard [
suffix: suffix? any [address ""]
resource: get-resource address any [
all [
find extensions/image! suffix
image!
]
string!
]
f-address/text: mold current-address: first resource
f-address/line-list: none

view-page second resource offset
f-status/text: either any [
none? first resource
not none? second resource
][
""
][
reform [address "not found"]
]
show window
]
]

view-about-info: does [
view-page rejoin ["<h1>About SONAR1</h1><hr><pre>" system/script/header/note "</pre>"] 0x0
show window
]

show-address: func [
address
][
f-status/text: form any [address ""]
show f-status
]

view-page: func [
data [string! image! none!]
offset [pair!]
][
content: copy [
styles view-styles
backcolor 255.255.255
space 2x2
origin (options/margin)
]
append content any [
switch type? data reduce [
string! [
html/process data min options/max-width options/view-size/x - 20
]
image! [
compose [image (data)]
]
]
copy []
]
f-view/pane: reduce [content: layout content]
f-status/text: none
f-status/line-list: none
f-view/pane/1/offset: offset
f-scroller/data: f-view/pane/1/offset/y / f-view/pane/1/size/y * -1
]

save-resource: func [
address [any-string!]
/local file data
][
if any [file? address url? address] [
if file: request-file/file/save/only second split-path address [
if data: second get-resource address binary! [
write/binary file data
f-status/text: join form file " saved."
show f-status
]
]
]
]

skip-history: func [value /local new offset] [
history: skip history value * 2
goto history/-2 any [history/-1 0x0] false
]

strip-address: func [address [any-string!]] [
copy/part address any [find address #"#" tail address]
]

absolute-address: func [
address [any-string! none!]
/local new dec host p
][
if any [none? address empty? address] [return none]
if file? address [return clean-path address]
if email? address [return address]

new: copy http://
if p: find/match address new [
address: either (index? find/last address #"/") > (index? find back p #"/") [
copy address
][
join address #"/"
]
return attempt [to-url address]
]
if file? current-address [
return none
]
dec: decode-url current-address
if not dec/host [
return none
]
repend new [dec/host #"/"]
host: copy new
if all [dec/path #"/" <> address/1] [
repend new [dec/path]
]
until [
not any [
if all [
find/match address "../"
p: find/last/any new "/?"
(index? p) > length? host
][
remove/part address 3
new: copy/part new next p
true
]
if find/match address "./" [
remove/part address 2
true
]
]
]
append new either #"/" = address/1 [next address] [address]
new
]

init-progress: func [
address
][
f-status/text: reform ["reading" address " "]
show f-status
progress: 0
]

show-progress: func [
total bytes
/local p
][
p: to-integer (log-2 max 1 bytes) * 2
if 500 > length? f-status/text [
f-status/text: head insert/dup tail copy any [
f-status/text ""
] #"|" max 0 p - progress
]
progress: p
guard [
show f-status
wait 0
]
]

read-net-url: func [
url [url!]
/local port buffer data size ready?
][
init-progress url
if port: attempt[open/direct url] [
change clear url port/url
buffer: make binary! size: to-integer any [
port/locals/headers/content-length
8000
]
set-modes port/sub-port [
lines: false
binary: true
no-wait: true
]
while [
all [
not STOP
data: wait [30 port/sub-port] ready?: true
data: copy port/sub-port
]
][
append buffer data
show-progress size length? buffer
ready?: false
]
close port
]
if ready? [buffer]
]

get-resource: func [
address [url! file! none!]
type [datatype!]
/local redirect raw data pos
][
if not address [return [#[none] #[none]]]

;; find the resource in cache
all [
url? address
pos: find/skip head cache reduce [address binary!] 3
error? raw: pick pos 3
]
all [
url? address
pos: find/skip head cache reduce [address type] 3
error? data: pick pos 3
]

;; otherwise download the resource
redirect: copy address
if not found? pos [
STOP: false
data: attempt [
all [
raw: any [
raw
all [
file? redirect
read/binary redirect
]
all [
url? redirect
read-net-url redirect
]
]
data: switch/default type reduce [
binary! [
raw
]
image! [
foreach sig signatures/image! [
if find/match raw sig [
image: load raw
break/return any [
all [block? image not empty? image image? image/1 image/1]
all [image? image image]
]
]
]
]
][
to type raw
]
]
]
;; insert resource into cache, even none! values
if (length? cache) > (options/cache-limit * 3) [
remove/part head cache 3
]
repend cache [redirect type data]
]
reduce [redirect data]
]

;; gets an attribute value from a tag string
get-attribute: func [
tag [tag!]
name [string!]
/local value
][
parse/all tag [
thru name (value: true) any whitespace #"=" any whitespace [
{"} copy value to {"} |
{'} copy value to {'} |
copy value [
to { } | to {^/} | to {^-} | to {/} | to {>}
]
]
]
value
]

;; gets a reference from a tag string
get-ref: func [
tag [tag!]
name [string!]
/local ref f
][
if ref: get-attribute tag name [
either f: find/match ref "mailto:" [
attempt [to-email f]
][
absolute-address ref
]
]
]

html: context [

content: make block! 100
links: make block! 100
flowtext: none
element: none
ref: none
a-ref: none
a-text: none
a-img: none
box: none
width: none
style: none
visible: true

;; generates VID code for a horizontal ruler element
insert-hr: does [
if all [visible not box] [
append content compose [
pad 0x12
hrule (1x0 * (max options/min-width width - (2 * options/margin/x)) + 0x1)
pad 0x12
]
box: true
]
]

;; generates VID code for a link button
insert-link: func [href [url! email!] text [string!] /local text2] [
if all [visible href not empty? href] [
text2: trim/lines decode-entities text
if any [not string? text2 empty? text2] [
text2: "(link)"
]
f-textwidth/text: text2
append content compose/deep/only [
hyperlink (copy text2
) (6x6 + size-text f-textwidth
) user-data (copy/deep reduce [href href]
)
]
append links copy href
box: false
]
]

;; generates VID code for a link image
insert-link-image: func [href [url! email!] src [url!] /local image] [
if all [visible not empty? href not empty? src] [
either options/images [
if image: second get-resource src image! [
append content compose/deep/only [
hyperlink-image (image
) (image/size + 4x4
) user-data (copy/deep reduce [src href]
)
]
append links copy href
box: false
]
][
insert-link href "(image)"
]
]
]

;; generates VID code for an image
insert-image: func [src [url!] /local image] [
if all [visible options/images not empty? src] [
if image: second get-resource src image! [
if image/size = max image/size options/image-minsize [
append content compose/deep/only [
static-image (image
) (image/size + 2x2
) user-data (copy/deep reduce [src src]
)
]
box: false
]
]
]
]

;; generates VID code for text
insert-text: does [
if all [visible 1 < length? flowtext] [
append content compose switch/default style [
bold [
[
boldtext (copy flowtext
) (max options/min-width width - (2 * options/margin/x)
)
]
]
item [
[
pad 0x6 bullet pad 20x-22
hypertext (copy flowtext
) (max options/min-width width - (2 * options/margin/x)
)
pad -20x-6
]
]
pre [
[
pretext (copy flowtext
) (max options/min-width width - (2 * options/margin/x)
)
]
]
][
[
hypertext (copy flowtext
) (max options/min-width width - (2 * options/margin/x)
)
]
]
box: false
]
clear flowtext
]

;; generates VID code for indentation
insert-indent: func [
value [integer!]
/local box2
][
box2: box
insert-text
if options/indent <> 0 [
append content compose [
indent (options/indent * value)
]
]
width: width - (options/indent * value)
box: box2
]

;; tags ==> actions
tag-actions: [
opening [<a> <frame> <p> <br> <hr> <img> <table> <tr> <td> <ul> <ol> <dl>
<dt> <dd> <li> <h1> <h2> <h3> <h4> <h5> <pre> <form> <script> <object> <style>] [
insert-text
]
opening [<form> <script> <object> <style>] [
visible: false
]
opening [<b>] [
if all [empty? flowtext style = none] [style: 'bold]
]
opening [<title> <h1> <h2> <h3> <h4> <h5> <dt>] [
style: 'bold
]
opening [<pre>] [
style: 'pre
]
opening [<li> <dd>] [
style: 'item
]
opening [<hr> <table> <tr>] [
insert-hr
]
opening [<table> <ul> <ol> <dl>] [
insert-indent 1
]
opening [<a>] [
a-ref: get-ref element "href"
a-img: none
clear a-text
]
opening [<frame>] [
if a-ref: get-ref element "src" [
insert-link a-ref "(frame)"
a-ref: none
]
]
opening [<img>] [
either a-ref [
a-img: get-ref element "src"
][
if ref: get-ref element "src" [
insert-image ref
]
]
]
closing [<a>] [
if a-ref [
either a-img [
insert-link-image a-ref a-img
][
insert-link a-ref a-text
]
a-ref: none
]
]
closing [<table> <ul> <ol> <dl>] [
insert-indent -1
if style = 'item [style: none]
]
closing [<hr> <table> <tr>] [
insert-hr
]
closing [<title> <h1> <h2> <h3> <h4> <h5> <pre> <li> <dt> <dd>] [
insert-text
style: none
]
closing [<b>] [
if style = 'bold [style: none]
]
closing [<form> <script> <object> <style>] [
clear flowtext
visible: true
]
]

;; generate a VID layout block from HTML
process: func [
html [string!]
new-width [integer!]
/local tags element tag text sub opening? closing? e
][
content: clear head content
links: clear head links
flowtext: copy ""
a-text: copy ""
a-img: a-ref: style: none
STOP: false
width: new-width

tags: load/markup html
foreach element tags [
self/element: element
if all [
tag? element
none? find/match element <!-->
parse/all element [
(e: none)
opt "/" copy e some alpha-num to end
]
][
e: to-tag lowercase e
opening?: #"/" <> first element
closing?: any [#"/" = first element #"/" = last element]
foreach [type tags code] tag-actions [
if any [
all [opening? type = 'opening]
all [closing? type = 'closing]
][
if find tags e [do code]
]
]
]
if string? element [
either all [style = 'pre none? a-ref] [
text: decode-entities element
append flowtext text
][
if not empty? text: trim/lines decode-entities element [
either a-ref [
repend a-text [" " text]
][
repend flowtext [" " text]
]
trim/lines flowtext
]
]
]
]
insert-text
content
]
]
]

SONAR1/init
deglingo3-Jan-2011/19:58:08+1:00
Une merveilleuse année à tous, pleine de bonnes nouvelles du côté Rebol.
Je ne suis qu'un piètre utilisateur de Rebol, mais sincèrement bravo à toutes les initiatives de Nicolas. Cela donne envie de continuer à s'accrocher à Rebol.

Et, merci pour toutes ces informations sur ce post.
Pas mal du tout ce mini-browser en Rebol. Par-contre, cela ne correspond pas tout à fait à mon idée initiale, j'aurai dû être plus précis dès le début, c'est ma faute, désolé !

En fait, je travaille en Java/J2EE en entreprise. Et, j'essaie souvent de voir si ce que l'on fait serait transposable en Rebol.
Nous avons :
+ un catalogue d'articles unique sous la forme d'une 1ère application web (HTML, Javascript, Ajax, CSS, flash, etc...) accessible depuis différents canaux de vente
+ une application de vente pour des internautes (2ème application web) / 1er canal de vente
+ une application de vente sous la forme d'un client "riche" Eclipse RCP utilisée dans des magasins, pilotant d'autres applications installées sur chaque poste / 2ème canal de vente

Les 2 applications de ventes (web et Eclipse RCP) doivent pouvoir afficher l'unique catalogue d'articles web.
Sur chaque fiche article du catalogue web, on trouve un bouton "Ajouter au panier" :
+ sur l'appli. web de vente, cela déclenche l'ajout dans le panier "web"
+ sur le client Eclipse RCP, le catalogue web est affiché à l'intérieur d'une fenêtre Eclipse dans le navigateur intégré (un peu comme dans la copie d'écran dans mon 1er post). Comme je l'ai expliqué, le navigateur n'a pas été redéveloppé, et ce n'était pas notre but.
C'est le navigateur installé sur le poste (IE6, IE7, Firefox, etc...) qui est utilisé et piloté.
Grâce à un "LocationListener" dans Eclipse, on peut capturer des URLs factices du type "vente://ajout_panier?codeArticle=12345", et déclencher l'ajout au panier dans l'application Eclipse RCP à partir d'actions dans le catalogue web.
(c'est cette application Eclipse RCP dont j'essaie de voir la transposition en Rebol / R2 View / R3GUI)

Le catalogue web est donc mutualisé entre plusieurs canaux/applications de vente. Dans chacune des applis de vente, on bénéficie de tout le rendu d'un des navigateurs du marché et de ses plugins.
C'est donc une question d'intégration d'applications au sein d'une entreprise, un cas d'école mais bien réel.

@Jocko
Selon toi, ce que je décris serait possible en utilisant une extension R3 ? On pourrait récupérer des évènements du navigateur dans Rebol ? grâce au mécanisme de Callbacks ?

@Didec
C'est OpenGL qui est intégré dans R3GUI, ce n'est plus AGG ? ou les deux ?

Merci.
Didec10-Jan-2011/10:08:49+1:00
AGG est toujours intégré dans le Rebol3 de base de RT.

Maxim a expérimenté l'intégration d'OpenGL en plus d'AGG via les extensions en C de R3. Il peut donc avoir un rendu OpenGL dans un gob! R3.
Je pense que pour l'affichage d'un objet "navigateur" dans une fenêtre R3 (donc dans un gob!) cela doit être possible par une technique similaire.
Pour ce qui est des événements, là, je ne sais pas.
deglingo10-Jan-2011/19:38:24+1:00
Merci beaucoup pour l'info.

Je serai intéressé pour en savoir un peu plus sur le sujet.

En fait, il faudrait arriver :
+ à ouvrir un objet navigateur (IE, Firefox, etc...) en ayant son rendu graphique dans un gob! R3
+ (sous Windows) et, en même temps, à piloter ce navigateur via un lien OLE

Par-contre, pour récupérer les évènements du navigateur, je ne sais pas si l'on peut utiliser le lien OLE.
Sinon, il n'y a pas une notion d'évènements au niveau des extensions R3 ?
trigram10-Jan-2011/23:33:06+1:00
Le mieu serait d'avoir un update pour Firefox multi-OS du plugin REBOL, non ?
deglingo10-Jan-2011/23:57:44+1:00
En fait, comme j'expliquais dans mon 1er post sur ce sujet, mon besoin est en quelque sorte l'inverse du plugin Rebol.

Je voudrais savoir comment l'on pourrait utiliser tout le potentiel d'un des navigateurs du marché (HTML, Javascript, CSS, Flash, Ajax, etc...), mais en affichant son rendu graphique dans une fenêtre Rebol. Comme le suggère Didec, il faudrait sans doute descendre au niveau gob!.
Eclipse RCP le fait par exemple très bien avec son composant SWT Browser utilisable sur tous les OS.
Je souhaiterai pouvoir également réagir dans le code Rebol sur les évènements venant du navigateur (exemple d'évènements sur IE : http://msdn.microsoft.com/en-us/library/aa752084(v=vs.85).aspx ).
J'ai expliqué plus haut le besoin derrière tout ça. C'est un cas que je rencontre dans mon boulot : l'intégration d'1 nouvelle application web dans un client riche Eclipse RCP existant. J'essayai de voir si l'on pouvait faire la même chose dans un client graphique Rebol.
trigram11-Jan-2011/0:32:29+1:00
A mon avis c'est pas gagné.
Je peux juste répéter qu'en Delphi tu pouvais importer IE et l'utiliser comme un composant standard Delphi.
Comme faire en Rebol ???
Gob! c'est du Rebol3 il me semble...
Si un moteur de rendu HTML digne de ce nom existait en REBOL se serait un sacré pied de nez aux browsers actuels avec leur dizaine voir centaine de Mo...
Ou alors, il faudrait faire le JRebol dont a parlé ou un MRebol ou encore REBOL.NET et pouvoir utiliser les librairies graphiques standard Java, Mono ou . NET
Je m'enlise...
R2 : non, sauf à repartir de Sonar et de le faire évoluer et d'accepter un truc un peu beaucoup moins jolie... après il faudra traiter le code Javascript... Il y a bien un début de tentative de Janko... Voir autre topic sur VID Web...
R3 : a priori possible grâce aux Gob!

Nico
deglingo11-Jan-2011/21:42:25+1:00
Non, je sais bien qu'un moteur de rendu HTML/Javascript/CSS/Flash digne d'un navigateur du marché n'existe pas en Rebol.
Justement, mon but serait de ne pas re-développer la roue, mais d'en piloter un existant en Rebol (IE, Firefox, etc...), comme le fait SWT/Eclipse RCP :

+ http://www.eclipse.org/articles/Article-SWT-browser-widget/browser.html
+ http://www.vogella.de/blog/2009/12/21/javascript-swt/
+ http://www.itaware.eu/2007/07/15/interaction-between-web-and-desktop-application/

Oui, le gob! est un type R3 (Graphical Object). Il faudrait voir si cela est possible dans ce type d'objet graphique bas niveau.

J'ai l'impression peut-être complètement fausse (vous me direz), qu'en Rebol, on veut souvent re-développer des choses existantes de A à Z, comme refaire un moteur de rendu HTML/CSS/Javascript/Flash. C'est sans doute très intéressant comme projet surtout avec un "méta-langage" comme Rebol.
Mais, pourquoi ne pas penser INTEGRATION avec des outils/technos existantes dans certains cas ?
deglingo11-Jan-2011/21:59:51+1:00
L'adoption massive d'un langage passe, entre autres, par sa capacité à intégrer ou à s'interconnecter avec des technos existantes.
Avec Rebol, on a l'impression que c'est vrai.
Le langage intègre tous les protocoles réseau de base. On peut même en développer de nouveaux. On peut se connecter à des bases de données MySQL, Oracle, etc...

Mais, est-ce si vrai que cela ?
rebolfrance12-Jan-2011/1:04:34+1:00
A mon avis, je peux rajouter un nouveau sujet à traiter : le Mashup.
Il faudrait voir si avec le module d'appel aux DLLs on arriverait à faire quelque chose pour sous-traiter le travail d'évaluation du Javascript par exemple...

REBOL aurait eu une carte à jouer sur ce terrain du Mashup parce que c'est du parsing de page, de l'intégration entre différentes applis... Aujourd'hui, pour faire du Mashup, on a en plus besoin d'un moteur/interpréteur Javascript. Si on souhaite faire quelque chose sur le sujet.

Nico
shadwolf13-Jan-2011/12:38:27+1:00
c'est d'autant plus compliqué que rebol cherche a redéfinir l'informatique de nos jours plus qu'à s'interfacer avec.

Quel interet d'avoir un module webkit dans rebol ? au final c'est pas ce qui assurera que vous pourrez etendre rebolesquement votre code existant sans avoir a y toucher.

Peut on faire une traduction de webkit en rebol ? Oui se serait un travail collossal qui necessiterait un travail a plein temps.

Tout cet immense travail a t'il un intéret je veux dire en quoi un navigateur rebolesque aurait une utilité ? Si le but final est de shinté les interfaces ajax pour les étendre et les rendre plus sympatiques avec du code rebol
on transformerait notre solution web based et donc relativement passe partout en une solution inter dépendante de rebol. en l'etat actuel de rebol est ce souhaitable ?
trigram13-Jan-2011/18:47:43+1:00
Pas besoin de la partie rendu graphique.
Juste la partie qui prend en compte les aspects javascript.

La question est plutôt : peut-on faire un appel à un module externe et récupérer le résultat en REBOL ? inter-agir avec Webkit ?

Login required to Post.


Powered by RebelBB and REBOL 2.7.8.4.2