REBOL [
Title: "WPT viewer"
Purpose: "Live Waypoints"
Date: 2006-07-08
Version: 0.1.2
Author: "Piotr Gapinski"
Email: {news [at] rowery! olsztyn.pl}
File: %wpt.r
Url: http://www.rowery.olsztyn.pl/wspolpraca/rebol/rss/
Copyright: "Olsztynska Strona Rowerowa http://www.rowery.olsztyn.pl"
License: "GNU General Public License (Version II)"
Library: [
level: 'intermediate
platform: 'all
type: [tool]
domain: [web]
tested-under: [
view 1.3.1 on [Linux]
view 1.3.2 on [Linux WinXP]
]
support: none
license: 'GPL
]
]
if system/version < 1.3.1 [to error! "WPT viewer requires Rebol/View 1.3.1 or greater"]
if error? err: try [
ctx-wpts: context [
wpts: copy []
sort-waypoints: func [
"sortuje waypointy po nazwie - narastajaco"
a [block!]
b [block!]] [
(form a/name) < (form b/name)
]
set 'wpts-gen-html func [
"zapis waypointow do html"
file [string! file!] "nazwa pliku pod ktora zostana zapisane dane"
/local ] [
lines: copy {}
num: 0
foreach wpt self/wpts [
attempt [
num: minimum (num + 1) 1000
name: join "wpt" num
url: make-url wpt/latitude wpt/longitude wpt/name
dat: reform [
name {::} {} wpt/name CRLF]
append lines dat
]
]
insert lines reform [
CRLF
CRLF
"Live Waypoints" CRLF
CRLF
CRLF
CRLF
CRLF
CRLF
"Waypointy" (form second split-path file)
CRLF
CRLF
]
append lines reform [
CRLF
"plik html wygenerowany:" now CRLF
CRLF
CRLF
]
write/direct (to-file file) lines
]
not-valid-altitude: -777 ; znacznik braku wysokosci dla OZI-explorer
to-meters: func [feet [number!]] [either (feet = not-valid-altitude) [feet] [feet / 3.28083931316019]]
to-feet: func [meters [number!]] [either (meters = not-valid-altitude) [meters] [meters * 3.28083931316019]]
wpts-load-ozi: func [
"wczytuje waypointy w formacie OZI-WPT"
file "nazwa pliku do wczytania"
/local dat wpt] [
if not dat: attempt [read/lines to-file file] [return none]
dat: skip dat 4
foreach line dat [
attempt [
wpt: parse/all line ","
repend/only wpts [
'name trim form wpt/11 ;; wpt/2
'latitude to-decimal trim form wpt/3
'longitude to-decimal trim form wpt/4
'altitude (to-meters to-decimal trim form wpt/15)
'description wpt/2
]
]
]
sort/compare wpts :sort-waypoints
;; zablokuj zapis do formatu OZI (grozi nadpisaniem pliku WPT)
disable gui-ozi-button
wpts
]
set 'wpts-gen-ozi func [
"zapis waypointow do pliku WPT w formacie OZI"
file [string! file!] "nazwa pliku pod ktora beda zapisane dane"
/local lines num name latitude longitude altitude description datetime dat] [
lines: copy {}
num: 0
foreach wpt self/wpts [
attempt [
num: minimum (num + 1) 1000
name: join "wpt" num
latitude: wpt/latitude
longitude: wpt/longitude
altitude: either empty? form wpt/altitude [not-valid-altitude] [to-feet wpt/altitude]
description: trim/lines replace (copy/part reform [wpt/name] 40) "," " "
dat: rejoin [
num "," ; Number - this is the location in the array (max 1000), must be unique
name "," ; Name - the waypoint name, use the correct length name to suit the GPS type
latitude "," ; Latitude - decimal degrees
longitude "," ; Longitude - decimal degrees
"," ; Date - if blank a preset date will be used
"70," ; Symbol - 0 to number of symbols in GPS
"1," ; Status - always set to 1
"6," ; Map Display Format
"0," ; Foreground Color (RGB value)
"13158342," ; Background Color (RGB value)
description "," ; Description (max 40), no commas
"2," ; Pointer Direction
"0," ; Garmin Display Format
"0," ; Proximity Distance - 0 is off any other number is valid
altitude "," ; Altitude - in feet (-777 if not valid)
"8.25," ; Font Size - in points
"0," ; Font Style - 0 is normal, 1 is bold
"17" CRLF ; Symbol Size - 17 is normal size
]
append lines dat
]
]
insert lines join {OziExplorer Waypoint File Version 1.1} [CRLF "WGS 84" CRLF "Reserved 2" CRLF "garmin" CRLF]
write/direct (to-file file) lines
]
wpts-load-grm: func [
"wczytuje waypointy w formacie garmin-protocol"
file "nazwa pliku do wczytania"
/local line dat wpt] [
if not dat: attempt [read/lines to-file file] [return none]
foreach line dat [
attempt [
wpt: load line
repend/only wpts [
; jezeli w 4ej kolumnie nie ma liczby to traktuj ja jako opis waypointa
'name wpt/1
'latitude to-decimal trim form wpt/2
'longitude to-decimal trim form wpt/3
'altitude (any [attempt [to-decimal trim form wpt/4] ""])
'description (either not attempt [to-decimal wpt/4] [attempt [wpt/4]] [attempt [wpt/5]])
]
]
]
sort/compare wpts :sort-waypoints
wpts
]
set 'wpts-load func [file [string! file!]] [
f: any [
; decyzja w jakim formacie sa dane
select [".wpt" 'wpts-load-ozi ".txt" 'wpts-load-grm] form suffix? to-file file
'wpts-load-grm
]
do f file
]
set 'wpts-list has [list] [
; zwraca liste nazw waypointow
list: copy []
foreach wpt wpts [append list wpt/name]
return list
]
]
ctx-charset: context [
standards: [
; tabela standardow zamiany 18 polskich znakow (duze/male)
win-pl [165 198 202 163 209 211 140 143 175 185 230 234 179 241 243 156 159 191] ;; "windows-1250"
iso-pl [161 198 202 163 209 211 166 172 175 177 230 234 179 241 243 182 188 191] ;; "iso-8859-2"
ami-pl [194 202 203 206 207 211 212 218 219 226 234 235 238 239 243 244 250 251] ;; "Amiga PL"
ascii [065 067 069 076 078 079 083 090 090 097 099 101 108 110 111 115 122 122] ;; "ASCII"
]
set 'to-ascii func [
"Zmienia standard polskich znaków na ascii; Zwraca string! po konwersji"
str [string!] "tekst do konwersji"
/from data "wymus standard wejsciowy"
/local std] [
std: either all [value? 'from from] [select standards data] [select standards (either linux? ['iso-pl] ['win-pl])]
iconv str std (standards/ascii)
]
iconv: func [
"Konwertuje polskie znaki w tekscie; Zwraca string! po konwersji"
str [string!] "tekst do konwersji"
inp [block!] "tablica konwersji (wejsciowa)"
out [block!] "tablica konwersji (wyjsciowa)"
/local i c here] [
if same? inp out [return str]
parse/all str [
any [
here: skip (
if 127 < c: first here [
any [
none? i: attempt [index? find inp to-integer c]
change here to-char out/:i
]
]
) :here
skip
]
]
head here
]
]
ctx-display: context [
def-offset: 4x1 ; odleglosc XY od gornej ramki do pierwszego elementu listy newsow
def-list-separator: off
def-list-desc: on
pos-offset: def-offset
browse-url: none
list-box: none
list-pane: none
last-rss-num: 0
; funkcje przesuwajace liste newsow (scroll-list) oraz scrollera (scroller-value)
; przesuniecie slidera powoduje aktualizacje pozycji listy newsow
scroll-list: func [value [number!]] [
list-box/offset/y: negate value * (list-box/size/y - gui-news-list/size/y)
show list-box
]
scroller-value: func [distance [number!]] [
delta-y: gui-news-slider/data + (distance * 20 / pos-offset/y)
if delta-y < 0 [delta-y: 0]
if delta-y > 1 [delta-y: 1]
scroll-list gui-news-slider/data: delta-y
show gui-news-slider
]
clear-display: does [
; inicjalizuje zmienne gui; funkcja musi byc wywolana przed dostepem do list-pane i list-box
; odswiezenie gui nastepuje w funkcji display-wpts
pos-offset: def-offset
list-box: make-face/size 'box as-pair gui-news-list/size/x 1
gui-news-list/pane: list-box
list-pane: list-box/pane: copy []
]
display-error: func [
"Wyswietla informacje o bledzie; Odswiezenie gui nastepuje w funkcji display-wpts"
text [string!] "naglowek bledu"
desc [string! none!] "opis bledu"] [
clear-display
;hide [gui-html-button gui-ozi-button]
disable [gui-html-button gui-ozi-button]
append-wpt reduce ['name text 'description desc]
]
set 'disable func [
"Ukrywa obiekt lub block! obiektów GUI. W odroznieniu od HIDE dziala takze przy zamknietym okienku programu"
face [object! block!]] [
foreach obj (to-block face) [
hide obj
obj/show?: false
]
]
set 'display-wpts func [
"Wyswietla waypointy z okreslonego pliku; Zwraca wartosc logic!"
file [string! file!] "nazwa pliku z waypointami"
/local wpt wpts error] [
wpts: wpts-load file
either not empty? wpts [
clear-display
foreach wpt wpts [append-wpt wpt]
error: empty? list-pane
][
; dane nie zostaly zaladowane
error: true
]
gui-info/text: to-ascii form second (split-path file)
if error [display-error {Error reading wpt-list!} {please check file format!}]
; przesun scroller w polozenie wyjsciowe i przelicz pozycje suwaka
gui-news-slider/data: 0
gui-news-slider/redrag (gui-news-list/size/y / list-box/size/y)
show [
gui-info
gui-news-slider
gui-news-list
]
recycle
return not none? wpts
]
set 'make-url func [lat lon desc] [rejoin [http://mapa.szukacz.pl/?n= lat "&e=" lon "&z=2&t=" desc]]
make-header: func [
"Tworzy naglowek wiadomosci wykorzystujac VID button; Zwraca object! VID BUTTON"
hdr-text [string! none!] hdr-url [url! string! none!] hdr-size [pair!] hdr-offset [pair!]] [
make get-style 'button [
size: hdr-size
offset: hdr-offset
text: trim/lines/head/tail hdr-text
edge: make edge [size: 0x0]
font: make font [align: 'left size: 13]
user-data: either none? hdr-url [none] [copy hdr-url]
action: make function! [] [if not none? user-data [browse/only user-data]]
]
]
make-line: func [
"Tworzy linie oddzielajaca naglowek wiadomosci od jej tresci; Zwraca object! VID BOX"
line-size [pair!] line-offset [pair!]] [
make get-style 'box [
size: line-size ; minimalna wysokosc 'box wynosi 3pix
offset: line-offset
edge: make edge [color: coal size: 1x1]
]
]
make-description: func [
"Tworzy opis wiadomosci wykorzystujac VID txt; Zwraca object! VID TXT"
desc-text [string! none!] desc-size [pair!] desc-offset [pair!]] [
make get-style 'txt [
size: desc-size
offset: desc-offset
text: trim/lines/head/tail desc-text
font: make font [align: 'left color: black]
]
]
append-wpt: func [
"Dodaje pozycje do listy wyswietlanych waypointow (list-box); Nie zwraca wartosci"
wpt [block!] "waypoint"
/local link desc btn btn-size wh] [
text: to-ascii form wpt/name
link: attempt [either all [wpt/latitude wpt/longitude] [make-url wpt/latitude wpt/longitude wpt/name] [none]]
desc: reform [
any [attempt [wpt/description] ""]
any [attempt [wpt/latitude] ""]
any [attempt [wpt/longitude] ""]
any [attempt [wpt/altitude] ""]
]
btn-size: as-pair (gui-news-list/size/x - pos-offset/x - 8) (16)
jobs: [
; [check this] [do that]
[true] [make-header text link btn-size pos-offset]
[def-list-separator] [make-line (as-pair btn-size/x 3) pos-offset]
[all [def-list-desc desc]] [make-description desc btn-size pos-offset]
]
foreach [check job] jobs [
if do check [
btn: do job
; jezeli tekst nie miesci sie w jednej linijce to zmien wysokosc przycisku (Y)
if not zero? (wh: size-text btn) [btn/size/y: wh/y + 4]
append list-pane btn
list-box/size/y: list-box/size/y + btn/size/y
pos-offset: as-pair (pos-offset/x) (pos-offset/y + btn/size/y)
]
]
; dodaj odstep miedzy poszczegolnymi newsami
list-box/size/y: list-box/size/y + 4
pos-offset/y: pos-offset/y + 4
]
add-suffix: func [file [string! file!] suffix [string! file!] /local index] [
index: any [
attempt [index? find/last file #"."]
length? file
]
to-file join copy/part file index [alter form suffix "."]
]
set 'look-and-feel stylize [
info-btn: info 320 middle edge [size: 0x0] font [style: 'bold size: 14 align: 'left]
about-btn: btn-help [browse http://www.rowery.olsztyn.pl]
news-list: box 336x280 edge [size: 1x1 color: black]
news-slider: scroller 16x280 edge [size: 1x1 color: black] [scroll-list value]
save-html-btn: btn "save as HTML" #"h" [wpts-gen-html (add-suffix gui-info/text %.html)]
save-ozi-btn: btn "save as OZI/WPT" #"w" [wpts-gen-ozi (add-suffix gui-info/text %.wpt)]
]
insert-event-func [
switch event/type [
scroll-line [scroller-value event/offset/y] ; obsluga kolka w myszce (przesuwanie listy newsow)
key [ ; obslga klawiszy kursora
switch event/key [
up [scroller-value -3]
down [scroller-value 3]
]
]
]
event
]
]
linux?: equal? fourth system/version 4
if all [linux? (get-env "KDEDIR")] [
attempt [unprotect 'browse]
browse: func [value [any-string!] /only] [call reform ["konqueror" rejoin [{"} value {"}]]]
]
img: load 64#{
/9j/4AAQSkZJRgABAQIAAAAAAAD/2wBDAAoHBwgHBgoICAgLCgoLDhgQDg0NDh0V
FhEYIx8lJCIfIiEmKzcvJik0KSEiMEExNDk7Pj4+JS5ESUM8SDc9Pjv/2wBDAQoL
Cw4NDhwQEBw7KCIoOzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7
Ozs7Ozs7Ozs7Ozs7Ozv/wAARCAGQAfQDASIAAhEBAxEB/8QAHwAAAQUBAQEBAQEA
AAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIh
MUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6
Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZ
mqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx
8vP09fb3+Pn6/8QAHwEAAwEBAQEBAQEBAQAAAAAAAAECAwQFBgcICQoL/8QAtREA
AgECBAQDBAcFBAQAAQJ3AAECAxEEBSExBhJBUQdhcRMiMoEIFEKRobHBCSMzUvAV
YnLRChYkNOEl8RcYGRomJygpKjU2Nzg5OkNERUZHSElKU1RVVldYWVpjZGVmZ2hp
anN0dXZ3eHl6goOEhYaHiImKkpOUlZaXmJmaoqOkpaanqKmqsrO0tba3uLm6wsPE
xcbHyMnK0tPU1dbX2Nna4uPk5ebn6Onq8vP09fb3+Pn6/9oADAMBAAIRAxEAPwDt
aKKKACiiigAooooAKKKKACiiigAooooAKKKKACiiigAooooAKKKKAEoyKCQoyTxV
SWVpG2jOKAFml3HavSprWxL4aQcelSWdnjEkg57Cr+MUAIqqi4AwKXpS9KoXl55f
yIeaAFvb0Rgoh+astiWbcxyTQSWOT1NJQAUtFFACVYtLczyDI+UdahVdzADvW1aQ
CGEDuaAJlUKoA6CloooAKKKKACiiigAoopCwHU0AZuqdQKz60ryI3MgEfOKbHph6
uaAM7BNSJbyueENa8dnCn8OanACjAGKAMuPTWJy5xVuOyhjHTJqzjij8KAGhQvQA
UtFFACUUtJQAlFFBoAQ0UGigCvdQCWM4HNZDqUYqeCK36z763/jUfWgDPooooAKK
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
oAKKKSgAoooNACUUUUAf/9k=
}
main-window: center-face layout [
backdrop img effect [tile-view]
key (escape) [unview quit]
styles look-and-feel
origin 2x2 space 2x2 across
gui-info: info-btn return
gui-news-list: news-list
gui-news-slider: news-slider return
gui-html-button: save-html-btn
gui-ozi-button: save-ozi-btn pad 140 about-btn
]
file: remove-each name read %. [
;not found? [".wpt" ".grm"] lowercase form suffix? name]
all [
not found? find (lowercase form name) "wpt.txt"
not found? find (lowercase form name) ".wpt"
]
]
if 1 <> length? file [append file request-file/title "Load wpts..." "Load"]
if last file [
display-wpts last file
view/title main-window "Live Waypoints"
]
][
alert rejoin [{We apologize, an unexpected error occurred (} get in disarm err 'id { error)}]
]
;halt
quit