Add support for external html docs
[maxima.git] / interfaces / xmaxima / Tkmaxima / Browser.tcl
blob48b950e9604afc2fdee3b827f971d1e148f7a500
1 ############################################################
2 # Browser.tcl #
3 # Copyright (C) 1998 William F. Schelter #
4 # For distribution under GNU public License. See COPYING. #
5 # #
6 # Modified by Jaime E. Villate #
7 # Time-stamp: "2024-03-26 12:57:21 villate" #
8 ############################################################
10 proc peekLastCommand {win} {
11 global maxima_priv
12 if { [info exists maxima_priv(lastcom,$win)] } {
13 return $maxima_priv(lastcom,$win)
17 proc pushCommand { win command arglist } {
18 global maxima_priv
19 set maxima_priv(lastcom,$win) [list $command $arglist]
22 #-----------------------------------------------------------------
24 # tkTextInsert -- we add some things to the default tkTextInsert
25 # so that tags present before or after the insert, which are sticky
26 # are added to the inserted string. As usual, ones on both sides
27 # are added.
29 # Results:
31 # Side Effects:
33 #----------------------------------------------------------------
35 proc tkTextInsert { w s } {
36 global maxima_priv
37 set after [$w tag names insert]
38 set before [$w tag names "insert-1char"]
39 set both [intersect $after $before]
40 # puts "after=$after"
41 # puts "before=$before"
43 foreach v [concat $after $before] {
44 if { [regexp -- $maxima_priv(sticky) $v] } {
45 lappend both $v
49 if { [info exists maxima_priv($w,inputTag) ] } {
50 lappend both $maxima_priv($w,inputTag)
53 if {($s == "") || ([$w cget -state] == "disabled")} {
54 return
56 catch {
57 if {[$w compare sel.first <= insert]
58 && [$w compare sel.last >= insert]} {
59 $w delete sel.first sel.last
62 $w insert insert $s $both
63 $w see insert
66 proc getRange { win a b } {
67 if { [$win compare $a < $b ] } {
68 return "$a $b"
69 } else {
70 return "$b $a"
74 #-----------------------------------------------------------------
76 # tagRanges -- find ranges on WINDOW for TAG from FROMINDEX below TOINDEX
78 # Results: a list of ranges start1 stop1 start2 stop2 ..
79 # which are contained in [fromindex,toindex] such that TAG is on from
80 # start1 to stop1 etc.
82 # Side Effects:
84 #----------------------------------------------------------------
86 proc tagRanges { win tag begin end } {
87 if { [$win compare $begin <= 1.0 ] && \
88 [$win compare $end >= end ] } {
89 return [$win tag ranges $tag ]
90 } else {
91 set answer ""
92 set begin [$win index $begin]
93 set end [$win index $end]
94 if { [lsearch [$win tag names $begin] $tag ]>=0 } {
95 set prev [$win tag prevrange $tag $begin+1chars]
96 set to [lindex $prev 1]
97 if { [$win compare $to > $end ] } {
98 set to $end
100 append answer "$begin $to "
101 set begin $to
103 #puts "<$begin $end>"
104 while { [$win compare $begin < $end ] } {
105 set next [$win tag nextrange $tag $begin]
106 #puts "next=$next"
107 if { "$next" == "" } { return $answer }
108 if { [$win compare [lindex $next 1] <= $end]} {
109 append answer "$next "
110 set begin [lindex $next 1]
111 } elseif {[$win compare [lindex $next 0] < $end ]} {
112 append answer "[lindex $next 0] $end"
113 return $answer
114 } else {
115 return $answer
118 return $answer
122 #-----------------------------------------------------------------
124 # quoteBraces -- given a STRING such that
125 # puts $file "set new [quoteBraces $string]"
126 # when re read by eval would make value of NEW identical to STRING
128 # Results: a string
130 # Side Effects:
132 #----------------------------------------------------------------
134 proc quoteBraces {string } {
135 regsub -all {[{}]} $string {\\&} val
136 return [list $val]
139 proc thisRange { win tag index } {
140 set prev [$win tag prevrange $tag $index]
141 if { "$prev" != "" && [$win compare [lindex $prev 1] >= $index] } {
142 return $prev
144 set next [$win tag nextrange $tag $index]
145 if { "$next" != "" && [$win compare [lindex $next 0] <= $index] } {
146 return $next
148 return ""
151 #-----------------------------------------------------------------
153 # insertRichText -- insert rich text in TEXTWINDOW at INDEX according
154 # to commands and data in LIST. The latter must be of the form
155 # command1 arg1 ..argn command2 arg1 ..argn2 ..
156 # for example if `Tins' takes two args
157 # and the commands must be in
158 # since the rich text might come from a selection or some or an untrusted
159 # file we want to be careful not to do any bad evals.
160 # Results: none
162 # Side Effects: the rich text commands are invoked to do insertions
163 # on the window.
165 #----------------------------------------------------------------
167 proc insertRichText {win index list } {
168 global maxima_priv
169 set maxima_priv(currentwin) $win
170 set maxima_priv(point) $index
171 foreach v $maxima_priv(richTextCommands) {
172 set maxima_priv($v,richTextCommand) [llength [info args $v]]
174 set i 0
175 set ll [llength $list]
176 while { $i < $ll } {
177 set com [lindex $list $i]
178 incr i
179 if { [catch { set n $maxima_priv($com,richTextCommand)} ] } {
180 return -code error -errorinfo [concat [mc "illegal command in rich text:"] "$com"]
182 set form [concat $com [lrange $list $i [expr {$i +$n -1}]]]
183 if { [catch {eval $form } ] } {
184 return -code error -errorinfo [concat [mc "unable to evaluate command:"] "`$form'"] }
186 incr i $n
189 proc Tins { tags text } {
190 global maxima_priv
191 # foreach v $args { append text $v }
192 $maxima_priv(currentwin) insert $maxima_priv(point) $text $tags
195 proc TinsSlashEnd { tags text } {
196 global maxima_priv
197 # foreach v $args { append text $v }
198 $maxima_priv(currentwin) insert $maxima_priv(point) "$text\\" $tags
201 proc underTop {top win} {
202 if { "$top" == "." } {
203 return $win
204 } else {
205 return $top$win
209 proc deleteAllTraces {var} {
210 foreach v [uplevel "#0" trace vinfo $var] {
211 uplevel "#0" trace vdelete $var [lindex $v 0] [list [lindex $v 1]]
215 # now unused
216 proc resetHistory { win list args } {
217 set action [lindex $args 1]
218 if { [catch {
219 if { "$action" == "history" } {
220 $list delete 0 end
221 if { [winfo exists $list] } {
222 foreach v [oget $win history] {
223 $list insert end [oget $v location]
227 $list selection clear 0 end
228 $list selection set [oget $win historyIndex]
229 after 200 raise [winfo parent $list]
231 } ] } {
232 deleteAllTraces [oloc $win history]
233 deleteAllTraces [oloc $win historyIndex]
237 proc startDragPlacedWindow { win x y } {
238 oset $win placeinfo [list $x $y [place info $win]]
241 proc dragPlacedWindow { win w1 x y } {
242 global me recursive
243 makeLocal $win placeinfo
244 catch { after cancel [oget $win after]}
245 set me [oget $win placeinfo]
246 #puts "have=[oget $win placeinfo]"
247 desetq "px py pinfo" [oget $win placeinfo]
248 set dx [expr {$x - $px}]
249 set dy [expr {$y - $py}]
250 set nx [expr {$dx + [assoc -x $pinfo]}]
251 set ny [expr {$dy + [assoc -y $pinfo]}]
252 set new "-x $nx -y $ny"
253 eval place $win $new
254 oset $win placeinfo [list $x $y $new]
257 # now unused
258 proc OpenMathMoveHistory { win n } {
259 makeLocal $win history historyIndex
260 incr historyIndex $n
261 if { $historyIndex >= [llength $history] } {
262 set historyIndex [expr {[llength $history] -1}]
264 if { $historyIndex < 0 } { set historyIndex 0}
265 if { "[lindex $history $historyIndex]" != ""} {
266 OpenMathGetWindow $win [lindex $history $historyIndex]
267 oset $win historyIndex $historyIndex
271 proc toLocalFilename { url } {
272 set type [assoc type $url]
273 switch -- $type {
274 http {
275 return [assoc filename $url]
277 file {
278 return [file join / [assoc dirname $url] [assoc filename $url] ]
281 default "unknown type: $type"
285 proc OpenMathGetWindow { commandPanel win } {
286 if { "[winfo parent [oget $commandPanel textwin]]" != "$win" } {
287 catch { pack forget [winfo parent [oget $commandPanel textwin]] }
288 pack $win -expand 1 -fill both
289 # pack $win
290 oset $commandPanel textwin $win.text
291 oset $commandPanel location [oget $win location]
292 set tem [toLocalFilename [decodeURL [oget $win location]]]
293 oset $commandPanel savefilename [file root $tem].txt
297 proc getw { s } {
298 eval pack forget [winfo children . ] ; pack $s
301 proc try1 { file } {
302 global ccc
303 eval pack forget [winfo children . ]
304 mkOpenMath [set w .t[incr ccc]]
305 uplevel "#0" source $file
308 proc filesplit { x } {
309 set l [split $x /]
310 set n [llength $l ]
311 set dir [lrange $l 0 [expr {$n - 2}]]
312 set file [lindex $l [expr {$n - 1}]]
313 return [list [join $dir /] $file]
316 proc decodeURL { name } {
317 set server ""
318 if { [regexp {([^#]*)#(.*)$} $name junk name anchor] } {
319 lappend answer anchor $anchor
320 # puts "answer=$answer"
322 if { [regexp {^([a-z]+)[(]?([0-9]*)[)]?:/(.+)$} $name all type port path ] } {
323 lappend answer type $type
324 } else {
325 set path $name ; set type ""
328 set path [removeDotDot $path]
329 #puts "path=$path"
330 desetq "dirname filename" [filesplit $path]
331 #puts "dirname=$dirname,path=$path,filename=$filename"
332 set po [assoc $type {http 80 nmtp 4443} ]
333 if { "$po" != "" } {
334 if { "$port" == "" } {set port $po }
336 if { [regexp {^/([^/:]*)(:([0-9]+))?(.*)$} $dirname all server \
337 jun po dirname] } {
338 # puts "hi ther,server=$server"
339 if { "$po" != ""} {set port $po}
340 if { "$dirname" == "" } {set dirname / }
341 } elseif { "$server" == "" } {
342 set server $filename
343 set dirname /
344 set filename {}
346 lappend answer port $port server $server
348 lappend answer dirname $dirname filename $filename
349 return $answer
352 proc removeDotDot { path } {
353 while { [regsub {/[^/]+/[.][.](/|$)} $path "\\1" path] } {list}
354 return $path
357 proc appendSeparate { var before item separator } {
358 if { "$item" != "" } {
359 uplevel 1 append $var $before $item $separator
363 proc dirnamePlusFilename { lis } {
364 return [string trimright [assoc dirname $lis ""] /]/[assoc filename $lis ""]
366 proc encodeURL { lis } {
367 set type [assoc type $lis ""]
368 switch -- $type {
369 nmtp {
370 if { [ set port [assoc port $lis 4443]] != 4443 } {
371 append type "($port)"
373 appendSeparate ans "" $type ://[assoc server $lis ""]
374 append ans [dirnamePlusFilename $lis]
375 appendSeparate ans "#" [assoc anchor $lis ""] ""
377 http {
378 if { [ set port [assoc port $lis 80]] != 80 } {
379 append type "($port)"
381 appendSeparate ans "" $type ://[assoc server $lis ""]
382 append ans [dirnamePlusFilename $lis]
383 #appendSeparate ans "" [assoc dirname $lis ""]
384 #appendSeparate ans "/" [assoc filename $lis ""] ""
385 appendSeparate ans "#" [assoc anchor $lis ""] ""
387 file {
388 appendSeparate ans "" $type :/
389 append ans [dirnamePlusFilename $lis]
390 # appendSeparate ans "" [assoc dirname $lis ""] "/"
391 # appendSeparate ans "" [assoc filename $lis ""] ""
392 appendSeparate ans "#" [assoc anchor $lis ""] ""
394 default "error unsupported url type: $type"
396 return $ans
399 proc resolveURL { name current {post ""} } {
400 set decode [decodeURL $name]
401 #puts "name=$name,current=$current"
402 set ans ""
403 set relative 0
404 if { "[assoc type $decode {} ]" == "" } {set relative 1}
405 if { $relative == 0 } {
406 set ans $decode
407 } else {
408 foreach {x y } $current {
409 switch -- $x {
410 dirname {
411 set ndir [assoc dirname $decode ""]
412 set cdir [assoc dirname $current ""]
413 if { [string match /* $ndir] } {
414 set new $ndir
415 } elseif { "$ndir" != "" } {
416 if { "$cdir" != "" } {
417 set new [string trimright $cdir /]/$ndir
418 } else {
419 set new $ndir
421 } else {
422 set new $cdir
424 lappend ans dirname [removeDotDot $new]
426 filename {
427 if { "[assoc filename $decode]" == "" && "[assoc anchor $decode]" != "" } {
428 lappend ans $x $y
431 post {
432 list
434 default {
435 lappend ans $x [assoc $x $decode $y]
439 foreach { key val } $decode {
440 if { "[assoc $key $ans --none--]" == "--none--" } {
441 lappend ans $key $val
445 if { "$post" != "" } {
446 set ans [putassoc post $ans $post]
448 return $ans
451 proc getURLrequest { path server port types {post ""} {meth ""} } {
452 global maxima_priv
454 if { "$meth" != "" } {
455 set method $meth
456 } else {
457 set method GET
458 if { "$post" != "" } {set method POST}
460 #puts "getURLrequest $path $server $port [list $types]"
461 foreach {v handler} $maxima_priv(urlHandlers) {
462 lappend types $v,
464 set ans "$method $path HTTP/1.0\nConnection: Keep-Alive\nUser-agent: netmath\nHost: $server:$port\nAccept: $types\n"
465 if { "$post" != "" } {
466 # append ans "Content-length: [string length $post]\n\n$post"
467 append ans "Content-type: application/x-www-form-urlencoded\nContent-length: [string length $post]\n\n$post"
469 return $ans
472 proc canonicalizeContentType { type } {
473 regexp -nocase {([---a-zA-Z]+)/([---a-zA-Z]+)} $type type
474 return [string tolower $type]
477 proc getURL { resolved type {mimeheader ""} {post ""} } {
478 global maxima_priv
479 set res $resolved
480 set ans ""
481 set method ""
482 if { "$mimeheader" != ""} {
483 uplevel 1 set $mimeheader \[list\]
485 uplevel 1 set $type "unknown"
486 #puts "getting $resolved,post=<$post>"
487 switch [assoc type $res] {
488 http {
489 #mike FIXME: replace with http get
490 # puts $res
491 # puts "socket [assoc server $res] [assoc port $res 80]"
492 if { [info exists maxima_priv(proxy,http) ] } {
493 set sock [eval socket $maxima_priv(proxy,http)]
494 # puts "opening proxy request socket $maxima_priv(proxy,http)"
495 } else {
496 set server [assoc server $res]
497 set port [assoc port $res 80]
498 #mike FIXME - use async sockets and dns
499 if {[catch {socket $server $port} sock]} {
500 global errorInfo
501 tk_messageBox -title Error -icon error -message \
502 [mc "Error connecting to %s on %s\n%s" \
503 $server $port $sock]
504 return
507 fconfigure $sock -blocking 0
508 ##DO NOT DELETE THE FOLLOWING !!!!!puts!!!!!!!!
509 #puts request=[getURLrequest [dirnamePlusFilename $res] [assoc server $res] [assoc port $res] image/gif $post]
510 # set path [dirnamePlusFilename $res]
511 set path [encodeURL $res]
512 set server [assoc server $res]
513 set port [assoc port $res]
514 puts $sock [getURLrequest $path $server $port image/gif $post]
515 if { "$post" == "" } {
516 oset $sock cachename "http://$server:$port$path"
517 } else {
518 oset $sock cachename ""
520 flush $sock
521 if { [readAllData $sock -tovar maxima_priv(url_result) \
522 -translation binary -mimeheader maxima_priv(mimeheader) \
523 -timeout 120000 -chunksize 2024] > 0 } {
525 #puts "length=[string length $maxima_priv(url_result)]"
526 # flush stdout
527 set contentType [canonicalizeContentType [assoc content-type $maxima_priv(mimeheader) text/plain]]
528 uplevel 1 set $type [list $contentType]
529 if { "$mimeheader" != "" } {
530 uplevel 1 set $mimeheader \[ uplevel "#0" set maxima_priv(mimeheader) \]
532 set ans $maxima_priv(url_result)
533 unset maxima_priv(url_result)
534 return $ans
535 } else {
536 return "had error"
539 file {
540 set name [toLocalFilename $res]
541 set fi [open $name r]
542 set answer [read $fi]
543 if { [regexp -nocase {[.]html?$} $name ] || [regexp -nocase "^(\[ \n\t\r\])*<html>" $answer] } {
544 set contentType text/html
545 } elseif { [regexp {[.]gif([^/]*)$} $name ] } {
546 set contentType image/gif
547 } elseif { [regexp {[.]png([^/]*)$} $name ] } {
548 set contentType image/png
549 } elseif { [regexp {[.]jpe?g([^/]*)$} $name ] } {
550 set contentType image/jpeg
551 } else {
552 set contentType text/plain
554 uplevel 1 set $type $contentType
556 close $fi
557 return $answer
559 default {
560 #mike dirpath?
561 error [concat [mc "not supported"] "[lindex $res 0]"]
566 proc getImage { resolved width height} {
567 global maxima_priv
568 set res $resolved
569 #puts [list getImage [list $resolved] $width $height]
570 set ans ""
571 catch {
572 if { "" != "[image type $maxima_priv(image,$res,$width,$height)]" } {
573 set ans $maxima_priv(image,$res,$width,$height)
576 if { "$ans" != "" } { return $ans }
578 set image [image create photo -width $width -height $height]
579 after 10 backgroundGetImage $image [list $resolved] $width $height
580 set maxima_priv(image,$res,$width,$height) $image
581 return $image
584 proc backgroundGetImage { image res width height } {
585 global maxima_priv
586 #puts [list backgroundGetImage $image $res $width $height ]
587 if { [catch { backgroundGetImage1 $image $res $width $height } err ] } {
588 set im ::img::brokenimage
589 $image config -width [image width $im] -height [image height $im]
590 $image copy $im
594 proc backgroundGetImage1 { image res width height } {
595 #puts "resolved=$res"
596 global maxima_priv
597 #puts [list backgroundGetImage $image $res $width $height]
598 switch [assoc type $res] {
599 http {
600 set server [assoc server $res]
601 set port [assoc port $res 80]
602 if { [info exists maxima_priv(proxy,http) ] } {
603 set s [eval socket $maxima_priv(proxy,http)]
604 # puts "opening proxy request socket $maxima_priv(proxy,http)"
605 } else {
606 set s [socket [assoc server $res] [assoc port $res 80]]
608 fconfigure $s -blocking 0
609 ##DO NOT DELETE THE FOLLOWING !!!!!puts!!!!!!!!
610 puts $s [getURLrequest [encodeURL $res] \
611 $server $port {image/gif image/png image/jpeg image/x-bitmap}]
612 flush $s
615 if { [regexp -nocase $maxima_priv(imgregexp) [assoc filename $res] mm extension] } {
616 fconfigure $s -translation binary
617 set tmp xxtmp[incr maxima_priv(imagecounter)].$extension
619 if { [info exists maxima_priv(inbrowser)] || [catch {set out [open $tmp w] } ] } {
620 # if have binary..
621 if { "[info command binary]" != "binary" } {
622 error [mc "need version of tk with 'binary' command for images"]}
623 #puts "hi binary" ; flush stdout
624 if { [readAllData $s -tovar \
625 maxima_priv($s,url_result) -mimeheader \
626 maxima_priv($s,mimeheader)
627 ] > 0 && [string match *$extension [assoc content-type $maxima_priv($s,mimeheader)]] } {
628 set ans $image
629 $image configure -data [tobase64 $maxima_priv($s,url_result)]
631 unset maxima_priv($s,mimeheader)
632 unset maxima_priv($s,url_result)
634 } else {
635 error [mc "could not get image"]
637 } else {
638 fconfigure $out -translation binary -blocking 0
639 if { [readAllData $s -tochannel $out \
640 -translation binary \
641 -mimeheader \
642 maxima_priv($s,mimeheader) -timeout 15000 -chunksize 2024 ] > 0 } {
643 set ans $image
644 $image config -file \
645 $tmp
646 unset maxima_priv($s,mimeheader)
648 # all the below just to try to remove the file..
649 # depending on versions and in environments..
653 file {
654 $image config -file [toLocalFilename $res]
655 set ans $image
656 # puts "$image config -file [toLocalFilename $res]"
657 #set ans [image create photo -file [toLocalFilename $res]]
661 default { error [mc "unknown type of image"] }
663 ## if we opened an out channel try hard to remove the tmp file.
664 if { [info exists out] &&
665 [catch { file delete $tmp } ] && [catch { rm $tmp }]
666 && [catch { exec rm $tmp }] } {
667 puts [concat [mc "cant remove tmp file"] "$tmp"]
669 if { "$ans" == "" } {
670 error [concat [mc "Unable to open an image for"] "[encodeURL $res]"]
675 #-----------------------------------------------------------------
677 # readData -- read data from S, storing the result
678 # in maxima_priv($s,url_result). It times out after TIMEOUT without any data coming.
679 # it can be aborted by setting set maxima_priv($s,done) -1
682 # Results: -1 on failure and 1 on success.
684 # Side Effects: it initially empties maxima_priv($s,url_result) and then
685 # adds data to it as read. maxima_priv($s,done) is initialized to 0
687 #----------------------------------------------------------------
689 proc readData { s { timeout 10000 }} {
690 global maxima_priv
692 after $timeout "set maxima_priv($s,done) -1"
693 fconfigure $s -blocking 0
694 set maxima_priv($s,done) 0
695 set maxima_priv($s,url_result) ""
697 #mike FIXME: this is a wrong use of after cancel
698 fileevent $s readable \
699 "after cancel {set maxima_priv($s,done) -1} ; after $timeout {set maxima_priv($s,done) -1} ; set da \[read $s 8000] ; append maxima_priv($s,url_result) \$da; if { \[string length \$da] < 8000 && \[eof $s] } {after cancel {set maxima_priv($s,done) -1} ; set maxima_priv($s,done) 1; fileevent $s readable {} ; }"
700 myVwait maxima_priv($s,done)
701 catch { close $s }
702 #mike FIXME: this is a wrong use of after cancel
703 after cancel "set maxima_priv($s,done) -1"
704 return $maxima_priv($s,done)
707 proc doRead { sock } {
708 global maxima_priv
710 #puts reading; flush stdout;
711 set tem [read $sock]
712 append maxima_priv(url_result) $tem
713 # puts read:<$tem>
714 # flush stdout
715 if { [eof $sock] } {
716 set maxima_priv(done) 1
717 close $sock
721 proc tempName { name extension } {
722 set count [pid]
723 while { [file exists $name[incr count].$extension] } { list }
724 return $name$count.$extension
727 proc ws_outputToTemp { string file ext encoding } {
728 upvar 1 $string result
729 set tmp [tempName $file $ext ]
730 set open $tmp
731 if { [lsearch {x-gzip x-compress} $encoding] >= 0 } {
732 # FIXME: Unix only
733 lappend dogzip |gzip -dc > $open ; set open $dogzip
735 set fi [open $open w]
736 fconfigure $fi -translation binary
737 puts -nonewline $fi $result
738 flush $fi
739 close $fi
740 return $tmp
743 proc OpenMathOpenUrl { name args} {
744 global maxima_priv
745 if {![winfo exists .browser]} {createBrowser .browser}
747 # Removes any white spaces at the end of the Url given
748 set name [string trimright $name]
750 maxStatus [concat [mc "Opening"] "$name"]
752 #puts "OpenMathOpenUrl $name $args "
753 set history "" ; set historyIndex -1 ; set currentUrl ""
754 set prevwindow ""
755 set commandPanel [assoc -commandpanel $args ]
756 if { "$commandPanel" == "" } {
757 linkLocal . omPanel
758 if { [info exists omPanel] } {
759 set commandPanel $omPanel
762 set toplevel [assoc -toplevel $args ""]
763 if { "$toplevel" == "" } {set toplevel ".browser"}
764 if { "$toplevel" == "." } {set toplevel ""}
765 set reload [assoc -reload $args 0]
766 set post [assoc -post $args ""]
767 #puts "post=$post"
768 if { [winfo exists $commandPanel ] } {
769 makeLocal $commandPanel history historyIndex textwin
770 # set toplevel [winfo paren $commandPanel]
771 # if { "$toplevel" == "." } {set toplevel ""}
772 # eval pack forget [winfo parent $textwin ]
773 set prevwin [winfo parent $textwin]
774 set currentUrl [oget $textwin currentUrl]
775 catch { set currentUrl [decodeURL [oget $textwin baseurl]] }
777 if { $reload == 0} {
779 set new [resolveURL $name $currentUrl $post]
780 if { [set anchor [assoc anchor $new]] != "" } {
781 set new [delassoc anchor $new]
783 set ii -1
784 foreach v $history {
785 incr ii
786 if { "[delassoc post $new]" == "[delassoc post [oget $v.text currentUrl]]" } {
787 # puts "new=$new\nold=[oget $v.text currentUrl]"
789 if { "$new" == "[delassoc anchor [oget $v.text currentUrl]]" } {
790 OpenMathMoveHistory $commandPanel [expr {$ii - $historyIndex }]
791 if { "$anchor" != "" } {
792 update
793 catch { $v.text yview anchor:$anchor }
796 # OpenMathGetWindow $commandPanel $v
797 # pushHistory $commandPanel $v
798 return
801 } else {
802 # reload=1
803 list
806 set count 5
807 while { [incr count -1] > 0 } {
808 set new [resolveURL $name $currentUrl $post]
809 set result [getURL $new contentType mimeheader $post]
810 if { [set tem [assoc location $mimeheader]] == "" } {
811 break
813 set name $tem
815 #puts "contentType defined:[info exists contentType]"
816 set handler [assoc $contentType $maxima_priv(urlHandlers)]
817 if { "$handler" != "netmath" && "$handler" != "" } {
818 set tmp [ws_outputToTemp result netmath ps "[assoc content-encoding $mimeheader]"]
819 # to do fix this for windows #####
820 exec sh -c "[format $handler $tmp] ; rm -f $tmp" &
821 return
823 #puts contentType=$contentType
824 #puts "got [string length $result] bytes"
825 #puts ", result= [string range $result 0 70] .."
827 if { [catch { set baseprogram [oget $textwin baseprogram] }] } {
828 set baseprogram [decodeURL [getBaseprogram]]
830 # puts "using $baseprogram"
831 if { $reload } { forgetCurrent $commandPanel }
833 #puts "maxima_priv(counter)=$maxima_priv(counter)"
834 set win [mkOpenMath [set w $toplevel.t[incr maxima_priv(counter)]] ]
836 #puts "maxima_priv(counter)=$maxima_priv(counter)"
837 makeLocal $w commandPanel
838 #puts "resolveURL $name $currentUrl"
839 if { [set anchor [assoc anchor $new]] != "" } {
840 set new [delassoc anchor $new]
842 if { "[assoc filename $new]" == "" } {
843 set new [putassoc filename $new index.html]
845 # puts "...> $new"
846 oset $w.text currentUrl $new
847 oset $commandPanel location [encodeURL $new]
848 oset $commandPanel textwin $win
849 oset $w location [encodeURL $new]
850 # puts "new=$new"
851 oset $commandPanel savefilename [file root [toLocalFilename $new]].txt
852 set tem [assoc filename $new ""]
853 #puts $contentType
854 if { "$contentType" != "text/html" } {
855 if { [string match "image/*" $contentType] } {
856 set im [image create photo -data $result]
857 $win image create 0.0 -image $im
858 set err 0
859 } else {
860 set err [catch { $win insert 0.0 $result } ]
862 } elseif { 1 } {
863 xHMinit_win $win
864 xHMset_state $win url [encodeURL $new]
865 oset $win baseprogram $baseprogram
866 # puts win=$win,lengres=[string length $result]
867 set errmsg1 ""
868 set err 0
869 global debugParse
870 if { $debugParse } {
871 xHMparse_html $result "xHMrender $win"
872 set err 0
873 } else {
874 set err [catch {
875 xHMparse_html $result "xHMrender $win"
876 } errmsg1 ]
878 catch {
879 if { "$anchor" != "" } {
880 update
881 $win yview anchor:$anchor
884 # foreach v {Tresult Teval} { $win tag raise $v}
885 } else {
886 ###Never get here.. must change to make be the rich text case..
887 # drop comment lines
888 regsub -all "(^|\n)#\[^\n\]*\n" $result \n result ;
889 #puts input=$result
891 # note netscape would just truncate the history
892 # at historyIndex, and start to grow it there,
893 # losing the record of all files you have visited after..
894 # maybe we should do this.
895 #puts "history=$history"
896 set err [catch { insertRichText $win insert $result }]
898 if { $err == 0 } {
899 pushHistory $commandPanel $w
901 if { $err } {
902 global errorInfo
903 #puts "======begin======"
904 #puts $result
905 #puts "======end========"
906 puts "$errmsg1"
907 error [concat [mc "unable to evaluate"] "[encodeURL $new]\n$errmsg1\n$errorInfo"]
911 proc pushHistory { commandPanel win } {
912 global [oarray $commandPanel]
913 makeLocal $commandPanel history historyIndex
915 if { [llength $history] == 0 } {
916 oset $commandPanel historyIndex -1
918 if { "[lindex $history $historyIndex ]" != "$win" } {
919 oset $commandPanel history [linsert $history [incr [oloc $commandPanel historyIndex]] $win]
923 #-----------------------------------------------------------------
925 # omScrollPage -- scroll the page by N pages, keeping the insert
926 # cursor visible.
928 # Results: none
930 # Side Effects: page scrolls
932 #----------------------------------------------------------------
934 proc omScrollPage { win n } {
935 tkTextScrollPages $win $n
936 set bbox [$win bbox insert]
937 if { "" == "$bbox" } {
938 if { $n > 0 } {
939 $win mark set insert @0,0
940 } else {$win mark set insert @0,[$win cget -height]}
944 proc addTagSameRange { win oldtag newtag index } {
945 if { [lsearch [$win tag names $index] $oldtag ] >= 0 } {
946 set this [$win tag prevrange $oldtag $index+1char]
947 if { "$this" != "" && [$win compare $index < [lindex $this 1]] } {
948 $win tag remove $newtag 0.0 end
949 $win tag add $newtag [lindex $this 0] [lindex $this 1]
950 $win tag raise $newtag
955 proc getBaseprogram { } {
956 global maxima_default
957 return [lindex $maxima_default(defaultservers) 0]
960 #mike FIXME: This is an abomination
961 proc fileBaseprogram { textwin parent x y } {
962 set e $textwin.e
963 catch { destroy $e }
964 set x [expr {[winfo rootx $parent] + $x +30 - [winfo rootx $textwin]} ]
965 set x 30
966 set y [expr {[winfo rooty $parent] + $y - [winfo rooty $textwin]} ]
967 global xHMpriv
968 set xHMpriv(baseprogram) [encodeURL [oget $textwin baseprogram]]
969 entry $e -width 40 -textvariable xHMpriv(baseprogram)
970 place $e -in $textwin -x $x -y $y
971 raise $e
972 set com "destroy $e ; oset $textwin baseprogram \[decodeURL \$xHMpriv(baseprogram)] "
973 bind $e <Leave> $com
974 bind $e <Return> $com
977 proc fontDialog { top } {
978 global maxima_default
980 set font [xHMmapFont font:propor:normal:r:3]
981 if {[winfo exists $top]} {catch { destroy $top }}
983 toplevel $top
984 wm iconify $top
986 set win $top.text
987 text $win -font [list [font config $font -family] [font config $font -size]] -height 20
988 wm deiconify $top
990 foreach fam {propor fixed} {
991 set lis ""
992 set i 0
993 while { $i <= 8 } {
994 lappend lis [expr {$i - 3}]
995 incr i
997 if { "$fam" == "fixed" } { set fixed 1 } else {
998 set fixed 0
1000 mkLabelListBoxChooser $win.size$fam "list $lis" maxima_default($fam,adjust)
1001 mkLabelListBoxChooser $win.family$fam "getFontFamilies $fixed " maxima_default($fam)
1002 set fo [xHMmapFont "font:$fam:normal:r:3"]
1003 catch { set maxima_default($fam) [assoc -family [font actual $fo]]}
1005 $win insert insert [mc "Font Settings\nThe proportional font is "]
1006 $win window create insert -window $win.familypropor
1007 $win insert insert [mc "with a size adjustment of "]
1008 $win window create insert -window $win.sizepropor
1009 $win insert insert [mc "\nThe fixed font is "]
1010 $win window create insert -window $win.familyfixed
1011 $win insert insert [mc "with a size adjustment of "]
1012 $win window create insert -window $win.sizefixed
1013 $win insert insert "\n"
1014 $win insert insert [mc "Default nmtp servers "]
1015 global _servers
1016 set _servers $maxima_default(defaultservers)
1017 entry $win.entry -textvariable _servers -width 40
1018 $win window create insert -window $win.entry
1019 $win insert insert "\n\n"
1020 global maxima_priv
1021 $win insert insert [mc "http Proxy host and port:"]
1022 entry $win.entryproxy -width 40
1023 catch { $win.entryproxy insert 0 $maxima_priv(proxy,http) }
1024 $win window create insert -window $win.entryproxy
1025 $win insert insert [mc "\nIf you are behind a firewall enter the name of your http proxy host and port,\n eg: `some.server.example.org 3128', otherwise leave this blank"]
1027 set men [tk_optionMenu $win.plottype maxima_default(plotwindow) embedded separate multiple ]
1028 $win insert insert [mc "\nShould plot windows be "]
1029 $win window create insert -window $win.plottype
1030 $win insert insert "?"
1031 $win insert insert "\n\n\n"
1032 $win insert insert [mc " Apply and Quit "] "bye raised"
1033 $win insert insert " "
1034 $win insert insert [mc " Apply "] "click raised"
1035 $win insert insert " "
1036 $win insert insert [mc " Cancel "] "cancel raised"
1037 proc _FontDialogApply { win } {
1038 global maxima_default _servers maxima_priv
1039 set maxima_default(defaultservers) $_servers
1040 catch {xHMresetFonts .}
1041 if { [llength [$win.entryproxy get]] == 2 } {
1042 set maxima_priv(proxy,http) [$win.entryproxy get]
1045 $win tag bind click <1> "_FontDialogApply $win"
1046 $win tag bind bye <1> "_FontDialogApply $win ; destroy $top"
1047 $win tag bind cancel <1> "destroy $top"
1048 $win tag configure raised -relief raised -borderwidth 2
1049 $win insert insert " "
1050 $win insert insert [mc " Save Preferences "] "save raised"
1051 $win tag bind save <1> "_FontDialogApply $win ; savePreferences"
1052 pack $win
1053 # place $win -in [oget [omPanel .] textwin] -x 10 -y 10
1056 proc savePreferences {} {
1057 global maxima_default maxima_priv
1058 makeLocal {.maxima.text} inputs
1060 # Save current console size in maxima_default
1061 set console [lindex [array get maxima_priv cConsoleText] end]
1062 set maxima_default(iConsoleWidth) [textWindowWidth $console]
1063 set maxima_default(iConsoleHeight) [textWindowHeight $console]
1065 catch {
1066 if {[winfo exists .browser]} {
1067 set maxima_default(browser) 1
1068 } else {
1069 set maxima_default(browser) 0}
1070 set fi [open "$maxima_priv(home)/.xmaximarc" w]
1071 puts $fi "array set maxima_default {"
1072 foreach {k v} [array get maxima_default *] {
1073 lappend all [list $k $v]
1075 set all [lsort $all]
1076 foreach v $all { puts $fi $v }
1077 puts $fi "}"
1079 #mike FIXME: make this a _default
1080 if { [info exists maxima_priv(proxy,http)] && \
1081 [llength $maxima_priv(proxy,http)] == 2 } {
1082 puts $fi [list array set maxima_priv [array get maxima_priv proxy,http]
1085 close $fi
1087 catch {
1088 set hf [open "$maxima_priv(home)/.xmaxima_history" w]
1089 puts $hf "oset {.maxima.text} inputs {"
1090 foreach v [lrange $inputs end-99 end] { puts $hf "{$v}" }
1091 puts $hf "}"
1092 close $hf
1096 #-----------------------------------------------------------------
1098 # mkLabelListBoxChooser -- creates a button called WIN with textvariable
1099 # $TEXTVAR. When clicked on the WIN, brings down
1100 # a list of items, and clicking on one of them selects that item. and
1101 # resets $TEXTVAR
1103 # Results: none
1105 # Side Effects: the TEXTVAR value is changed, and so consequently the label.
1107 #----------------------------------------------------------------
1109 proc mkLabelListBoxChooser { win items textvar} {
1110 button $win -textvariable $textvar -command "listBoxChoose $win [list $items] $textvar"
1113 proc listBoxChoose { win items textvar } {
1114 global maxima_default
1116 set whei [winfo height $win]
1117 set items [eval $items]
1118 set hei [llength $items]
1119 set fr ${win}frame
1120 frame ${win}frame
1121 set list $fr.list
1122 set scroll $fr.scroll
1123 scrollbar $scroll -command "$list yview"
1124 listbox $list -yscroll "$scroll set" -setgrid 1 -height 8
1125 pack $scroll -side right -fill y
1126 pack $list -side left -expand 1 -fill both
1127 set wid 0
1128 foreach v $items {
1129 set xx [string length $v] ;
1130 set wid [expr {($xx > $wid ? $xx : $wid)}]
1132 eval [concat $list insert 0 $items]
1133 catch { $list selection set [lsearch $items [set $textvar]] }
1134 bind $list <1> "set $textvar \[$list get \[$list nearest %y\]\]; destroy $fr"
1135 place $fr -in $win -x 0 -y 0 -anchor n
1138 proc quoteForRegexp { s } {
1139 regsub -all {[\]\[$+()\\.?*]} $s {\\\0} ans
1140 return $ans