# This H_load module contains routines that deal with loading files of # various sorts. The "doc*" routines deal with reading the primary document # that is being displayed. There are also a number of "*IMG" routines that # deal with images. global idlist agentid Btags docFil docPid docRdrN Imgdly N Src redirect global waitchr waitchrs waitchrn waitstyle global loadchars loadspeed loadstart loadtime Source H_wait set loadchars 0; # Chars in document. set loadspeed 0; # Chars/second. set loadtime 0; # Seconds for most recent load. set loadstart [clock seconds] set agentid {Mozilla/5.1 [en] (compatible; I; Linux 6.1)} set Imgdly 0 ;# Image delay, for debugging. set N(IMG) 0 ;# Image counter. set N(OBJ) 0 ;# Current object index. set Src {} ;# Current HTML input source line. set docFil {} ;# File handle for current document. set docPid {} ;# Process id for current w3cat command. set docRdrN 0 set redirect 0 set Sep { }; # Line separator for incoming source. # Here is a list of known HTTP_USER_AGENT strings: set idlist { {Mozilla/4.05 [en] (X11; I; SunOS 5.7 sun4u)} {Mozilla/4.5 [en] (WinNT; I)} {Mozilla/4.0 (compatible; MSIE 4.0; Windows NT)} {Lynx/2.6 libwww-FM/2.14} } # Balanced tags that need to be closed: set Btags {A B BIG BL BLOCKQUOTE BODY CENTER DIV DL EM FORM FONT H1 H2 H3 H4 H5 H6 HEAD HTML I OL PRE SCRIPT SELECT STRONG TABLE TD TH TR TCL TITLE UL comment except} # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # Reader for incoming documents. This routine reads from the w3cat process # # that is reading a document from a remote web server. We get the data a line # # at a time, including the HTML HEAD lines. Header lines are passed to # # hdrLine for processing; document lines are passed to HTML for processing. # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # proc docRdr {w f} { global C V me errmsg folder imageBufsiz imagePipe in \ docFil docLines docRdrN docPid \ loadchars loadspeed loadstart loadtime waitstyle Sep incr docRdrN set id "$me/docRdr" if {$V>2} {puts "$id: File \"$f\" docFil=\"$docFil\" in(HDR)=$in(HDR) in(H)=$in(H) in(IMAGE)=$in(IMAGE)"} if [eof $f] {docDone $w $f; return} if {$V>2} {puts "$id: File \"$f\" has activity ..."} if {$f != $docFil} { if {$V>2} {puts "$id: File \"$f\" is not current docFil=\"$docFil\""} set oldpid [pid $f] Msg "Kill old doc reader process $oldpid ..." if [catch {close $f} e] {Msg "docRdr: close $f gave $e"} else {Msg "Closed $f"} if [catch {eval exec kill -TERM $oldpid} x] {Msg $x} return } # if {$V>2} {puts "$id: File \"$f\" is docFil"} # if {$in(IMAGE) && ($f == $docFil || $f == $imagePipe)} { # if {$V>2} {puts "$id: Ignore fileevent for $f because docFil=$docFil imagePipe=$imagePipe."} # return # } if {$V>2} {puts "$id: Read from \"$f\" ..."} if {[gets $f line] < 0} { if {$V>2} {Msg "$id: gets failed."} docDone $w $f return } if {$V>7} {puts "$id: line=\"$line\""} if {$waitstyle>0} {Tick} if {$in(HDR)} { if {$V>5} {puts "$id: Header line \"$line\""} Msg {Reading headers ...} hdrLine $line if {$V>6} {puts "$id: Header line \"$line\" done."} Msg "Loading headers ..." return } if {$V>4} {puts "$id: .src.t insert end \"$line\\n\""} .src.t insert end $line\n incr docLines incr loadchars [string length "$line\n"] set loadtime [Max 1 [expr {[clock seconds] - $loadstart}]] set loadspeed [expr {$loadchars / $loadtime}] docLine $w $line; # $Sep if {$V>6} {puts "$id: Text line \"$line\" done."} Msg "Loading ($loadchars / $loadtime = $loadspeed c/s)" update idletasks } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # Here we clear out the text widget prior to loading it with new # data. Various global initializations happen here, too. We get a # window w as an arg, but as present it has never been tested for any # non-null value. proc docInit {w} { global V me B Btags Herr LC Mtab N wantNL Obj SP Sep curD curW Tf2c \ WinH WinW bd form in input link ll lm1 lm2 mark opt scripts space \ Foto Fott Fotw FotW i2U U2i \ loadchars loadspeed loadstart loadtime basefont Ftag TxtLen if {$V>1} {set id "$me/docInit"} if {$V>4} {puts "$id: curD=\"$curD\" (start)"} $curD delete 1.0 end set Herr {} set LC {} set wantNL($curD) 1 HSP $curD {} # foreach t {Fott Fotw FotW i2U U2i} { # if {$V>4} {puts "$id: Destroy $t"} # global $t # if [info exists $t] {unset $t} # } # foreach x [array names Foto] { # if {$V>4} {puts "$id: Destroy $Foto($x)"} # image delete $Foto($x) # } foreach t {PicMinw PicMaxw TxtLen TxtMin TxtMaxw TxtMaxW TxtMinw TxtMinW} { if {$V>4} {puts "$id: Destroy $t"} global $t if [info exists $t] {unset $t} set ${t}($curD) 0 } set Tf2c($curD) {} foreach x [winfo children $curD] { destroy $x if [info exists WinW($curD)] {unset WinW($curD)} if [info exists WinH($curD)] {unset WinH($curD)} } if {$opt(_)} {set space {_}} else {set space { }} set Mtab Mtab0 foreach x [array names N] {set N($x) 0} set form 0 set input 0 set link 0 set ll 0 set lm1 0 set lm2 0 set loadchars 0 set loadspeed 0 set loadtime 0 set loadstart [clock seconds] set mark 0 set scripts 0 set SP(TITLE) {} set TxtLen(TITLE 0 foreach x [array names in] {set in($x) 0} foreach x $Btags {set in($x) 0} foreach x [array names N] {set N($x) 0} if [set in(H) $opt(H)] {set Sep { }} else {set Sep "\n"} set basefont $opt(BASEFONT) if {$V>4} {puts "$id: Set fonts for curD=\"$curD\" to ($basefont v s r)"} SetFont $curD 0 $basefont v r m if {$V>4} {puts "$id: config $curD -font F$Ftag"} $curD config -font F$Ftag } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # This is called when we abandon a document. This can be because we hit EOF, # # or we give up, or we get a redirect, or whatever. We close the file, turn # # off the spinning line, kill any reader subprocess, and so on. # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # proc docDone {w f} { global V me docFil docPid Herr set id "$me/docDone" if {$V>1} {puts "$id: File \"$f\" window \"$w\""} if [eof $f] {if {$V>1} {puts "$id: EOF on $f."} } else {if {$V>1} {puts "$id: Error on $f."} } if [catch {close $f} e] { Msg "close $f gave $e" } else { Msg "Closed $f" } if 0 { if {[set pid [pid $f]] != {}} { if [catch {eval exec kill -TERM $docPid} x] { if {$V>1} {Msg "$id: Kill failed for process $pid for file $f ($x)"} Msg $x } else { if {$V>1} {Msg "$id: Killed process $pid for file $f"} } } } set docFil {} WaitDone + if {$Herr == {}} {Msg "Done."} else {Msg $Herr} # if {$V>1} {puts "$id: Resize the $w window."} # ResizeText $w } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # We've found that there's a problem with a cached file. We send a # # message to the H_cache process telling it the reason (x). It should # # respond by either deleting or refreshing the file. # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # proc BadCache {w f U x} { global V me myname global B V IB R me curD Foto Foth FotH Fott Fotw FotW i2f U2f set id "$me/BadCache" if {$V>1} {puts "$id: win \"$w\" file $f URL \"$U\" err \"$x\""} if [catch {send H_cache Bad \"$myname\" \"$f\" \"$U\" \"$x\"} p] { Msg $p if {$V>1} {puts "$id: {send H_cache Bad ...} request got \"$p\""} if {$V>1} {puts "$id: Can't send to H_cache; try to start it."} if [catch {exec H_cache &}] { if {$V>1} {Msg "Can't start H_cache."} return } if {$V>1} {Msg "Started H_cache."} after 1000 if [catch {send H_cache Bad \"$myname\" \"$f\" \"$x\" \"$U\"} p] { if {$V>1} {Msg "Still can't send to H_cache; give up."} return } } if [info exists Foto($U)] {destroy Foto($U)} if [info exists Foth($U)] {destroy Foth($U)} if [info exists FotH($U)] {destroy FotH($U)} if [info exists Fott($U)] {destroy Fott($U)} if [info exists Fotw($U)] {destroy Fotw($U)} if [info exists FotW($U)] {destroy FotW($U)} if [info exists U2f($U)] {destroy U2f($U)} if [info exists i2f($i)] {destroy i2f($i)} } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # This is called to load a picture from Foto(f) into the nth image in window # # w. It must only be called after the picture has been successfully loaded. # # Note one special kludge here: The array Fotw(URL) is used to remember which # # images we successfully loaded into Foto(URL). We do this because tcl tells # # us that Foto(X) exists for every X, even when the load failed. Also, if the # # file contains indecipherable data, the load will appear to "succeed", but # # when we try to use it in a label, we get an error. The catch command # # handles this, and turns off Fotw(URL) so we don't try to use it again. # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # proc FotoIMG {w n U} { global B V IB R me in i2f link opt curD TxtLen TxtMinw TxtMinW \ Foto Foth FotH Fott Fotw FotW PicMinw PicMaxw set id "$me/FotoIMG" if {$V>4} {puts "$id: w=\"$w\" n=\"$n\" U=\"$U\""} set img "$w.img$n.img" if {$V>2} {puts "$id: Load Foto($U) into $img ..."} if ![info exists Fotw($U)] { if {$V>1} {puts "$id: ### Foto($U) hasn't been loaded yet ###"} return 0 } if ![info exists PicMinw($w)] {set PicMinw($w) 0} if ![info exists PicMaxw($w)] {set PicMaxw($w) 0} if ![info exists Fotw($U)] { Msg "$id: ### Fotw($U) not defined###" return } if [winfo exists $img] { if {$V>4} {puts "$id: $img exists; load {$U}"} $img config -image Foto($U) if {$V>4} {puts "$id: $img loaded."} # ImgSize $curD $n $U # set bd [lindex [$img config -bd] end] # set TxtMinw($w) [Max $TxtMinw($w) $Fotw($U)] # set TxtMinW($w) [Max $TxtMinW($w) [expr {$Fotw($U) + (2 * $bd)}]] } else { if {$V>2} {puts "$id: Create img $img for {$U}"} if [catch {eval label $img -image Foto($U) $IB} xx] { Msg $xx if [info exists FotW($U)] {unset FotW($U)} if [info exists Fotw($U)] {unset Fotw($U)} if [info exists FotH($U)] {unset FotH($U)} if [info exists Foth($U)] {unset Foth($U)} return 0 } else { if {$V>5} {puts "$id: pack $img into $w.img$n"} pack $img -in $w.img$n -side top ImgSize $curD $n $U set PicMinw($w) [Max $PicMinw($w) $Fotw($U)] incr PicMaxw($w) $Fotw($U) if {$V>2} {puts "$id: $w PicMinw=$PicMinw($w) PicMaxw=$PicMaxw($w)."} } } update idletasks if {$V>4} {puts "$id: $img contains {$U}"} if {!$opt(ALT) && [winfo exists $w.img$n.alt]} { if {$V>2} {puts "$id: destroy $w.img$n.alt"} destroy $w.img$n.alt } else { if ![info exists ALT($n)] {set ALT($n) {}} incr TxtLen($curD) [string length $ALT($n)] if {$V>2} {puts "$id: $curD TxtLen=$TxtLen($curD) chars (ALT($n))."} } update idletasks if {$V>4} {puts "$id: $img should be visible now."} if {$in(A)} { if {$V>4} {puts "$id: $img is inside link \"$link\"."} ButtonBindings $w $img $link } if {$V>4} {puts "$id: done."} } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # Strip all the spaces out of a string. # proc nosp x { regsub -all {[ ]} $x {} v return $v } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # Here we talk to the H_cache server, sending it a URL and hoping to get # # back a local file path. If the URL isn't cached, H_cache will get it and # # later send us a message announding its arrival. # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # proc GetCache {w i U} { global V me myname U2i U2f i2U i2w useH_cache set id "$me/GetCache" set p {} if ![info exists i2w($i)] { if {$V>0} {puts "$id: ### Image $i not in i2w ###"} return } if {$V>1} {puts "$id: win \"$w\" image $i URL \"$U\" img $i2w($i)"} if [file exists $U] { set p "$U" if {$V>2} {puts "$id: URL \"$U\" is in file \"$p\""} } elseif [info exists U2f($U)] { set p $U2f($U) if {$V>2} {puts "$id: URL \"$U\" is in path \"$p\""} } elseif {$useH_cache} { if {$V>2} {puts "$id: First time for \"$U\""} lappend U2i($U) $i if {$V>4} {puts "$id: $U is for images {$U2i($U)}"} set i2U($i) "$U" if {$V>2} {puts "$id: Item $i is \"$U\""} if [catch {send H_cache Find \"$myname\" \"$U\" "GotCache $i"} p] { Msg "$p" if [regexp -nocase {insecure} $p] { set useH_cache 0 if {$V>0} {puts "$id: H_cache disabled."} if {$V>0} {puts "$id: $p"} return } if {$V>1} {puts "$id: {send H_cache Find ...} request got \"$p\""} if {$V>2} {puts "$id: Can't send to H_cache; try to start it."} if [catch {exec H_cache &}] { if {$V>1} {puts "$id: Can't start H_cache."} CheckCache $w $i "$U" return } if {$V>2} {puts "$id: Started H_cache."} after 1000 if [catch {send H_cache Find \"$myname\" \"$U\" "GotCache $i"} p] { if {$V>1} {puts "$id: Still can't send to H_cache; give up."} if {$V>2} {puts "$id: {send H_cache Find ...} request got \"$p\""} CheckCache $w $i "$U" return } } } else { Msg "H_cache disabled; can't get image." } if {$p != {}} { if {$V>1} {puts "$id: URL \"$U\" is in cache; p=\"$p\""} set U2f($U) "$p" LoadImgFile "$w" "$i" "$p" } else { if {$V>1} {puts "$id: URL \"$U\" can't be found."} } } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # The H_cache server will send us calls of this function when a URL has been # cached. By then, there may be a lot more references to the URL. We load the # image into a Foto() image widget, and call LoadImgFile to do the rest of # the processing. # proc GotCache {i p u} { global V B R me myname isRmt i2U i2w U2i U2f set id "$me/GotCache" if {$V>2} {puts "$id: i=\"$i\" p=\"$p\" u=\"$u\""} set U "$i2U($i)" if ![info exists i2w($i)] { if {$V>0} {puts "$id: ### Image $i not in i2w ###"} return } set w $i2w($i) if {$V>2} {puts "$id: i=\"$i\" U=\"$U\" w=\"$w\"."} if {$u != $U} { if {$V>1} {puts "$id: Image $i wanted \"$U\" got \"$u\""} if [catch {send H_cache Find \"$myname\" $U "GotCache $i"} p] { if {$V>2} {puts "$id: H_cache didn't reply for \"$U\""} if {$V>2} {puts "$id: Returned p=\"$p\""} return } } if {$V>2} {puts "$id: Got \"$p\" for \"$U\""} set U2f($U) "$p" LoadImgFile $w "$i" "$p" } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # For a loaded image, we measure its sizes and put them into some global # # arrays for later use. Is this a waste of time? # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # proc ImgSize {w i U} { global B V me Foto Foth FotH Fott Fotw FotW PicMinw PicMaxw set id "$me/ImgSize" if {$V>2} {puts "$id: w=\"$w\" i=$i U=\"$U\""} set iw [set Fotw($U) [image width Foto($U)]] set ih [set Foth($U) [image height Foto($U)]] set iW [set FotW($U) [expr {$iw + (2 * $B)}]] set iH [set FotH($U) [expr {$ih + (2 * $B)}]] if {$V>2} {puts "$id: $Fott($U) Foto($U) iw=$iw iW=$iW ih=$ih iH=$iH."} if ![info exists PicMinw($w)] {set PicMinw($w) 0} if ![info exists PicMaxw($w)] {set PicMaxw($w) 0} } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # Load an image file into image n from local file p. The image may be needed # # for several widgets, listed in U2i(). We look thru the image list U2I for # # the URL, and load the image into all of them. # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # proc LoadImgFile {w n p} { global B V me Foto Fott Fotw FotW in i2U i2U i2w opt link \ curD TxtMinw TxtMaxw TxtMinW TxtMaxW U2i set id "$me/LoadImgFile" if {$V>2} {puts "$id: w=\"$w\" n=$n p=\"$p\""} if ![info exists i2w($n)] {if {$V>0} {puts "$id: ### i2w($n) unknown ###"; return}} set f "$i2w($n)"; # Image frame. set U "$i2U($n)"; # Image URL. if {$V>2} {puts "$id: n=$n p=\"$p\" f=\"$f\" U=\"$U\""} if {$p == {}} {if {$V>1} {puts "$id: Called with n=$n p=\"$p\""}; return 0} if ![file readable $p] {Msg "$id: \"$p\" is not readable."; return 0} if [regexp -nocase {\.xbm$} $p] {set type bitmap} else {set type photo} if [catch {image create $type Foto($U) -file $p} x] { if {$V>0} {puts "$id: #### Can't load $p ($x) ####"} BadCache $w "$p" "$U" "$x" return } if {$V>2} {puts "$id: Image $n type $type Foto($U) \"$p\""} set Fott($U) $type ImgSize $curD $n $U # if ![info exists TxtMinw($curD)] {set TxtMinw($curD) 0} # if ![info exists TxtMaxw($curD)] {set TxtMaxw($curD) 0} # if ![info exists TxtMinW($curD)] {set TxtMinW($curD) 0} # if ![info exists TxtMaxW($curD)] {set TxtMaxW($curD) 0} # if {$TxtMinw($curD) < $Fotw($U)} {set TxtMinw($curD) $Fotw($U)} # if {$TxtMinW($curD) < $FotW($U)} {set TxtMinW($curD) $FotW($U)} # incr TxtMaxw($curD) $Fotw($U) # incr TxtMaxW($curD) $Fotw($U) # if {$V>4} {puts "$id: TxtMinw($curD)=$TxtMinw($curD) TxtMaxw($curD)=$TxtMaxw($curD)."} # if {$V>4} {puts "$id: TxtMinW($curD)=$TxtMinW($curD) TxtMaxW($curD)=$TxtMaxW($curD)."} set U $i2U($n) foreach i $U2i($U) { if {$V>2} {puts "$id: Image $i is {$U}"} set f $i2w($i) FotoIMG $curD $i $i2U($n) } } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # Here we load an image from a local file into memory. We load the image into # # Foto(URL), and set Fotox(URL) true to indicate that we have it. Fotox is a # # kludge to handle the problem that tcl pretends that all images "exist" even # # if the image create operation failed. # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # proc GetImgFile {n p} { set id "$me/GetImgFile" } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # proc GetURL {txt url meth} { global C V LC wantNL URLt me agentid folder getcmd docFil docPid in opt docLines set id "$me/GetURL" if {$V>2} {puts "$id: $txt url=\"$url\" meth={$meth}"} if {$V>3} {puts "$id: #############################################################"} set URLt($txt) [nosp $url] if {$V>2} {puts "$id: URLt($txt)=\"$URLt($txt)\""} set I {} regsub -all {[ ]} $URLt($txt) {} URLt($txt) if {$meth == {POST}} {set P w3post} else {set P w3cat} if {$agentid != {}} {set I "\"+I$agentid\" "} Msg "Get URL \"$URLt($txt)\" via {$P} ..." set getcmd "| $P +THR $I$URLt($txt) |& cat" if [catch {open $getcmd {RDWR NONBLOCK}} f] { Msg "Can't run \"$getcmd\" ($f)" return } Msg {Connecting ...} set in(H) $opt(H); # Are we assuming HTML? set in(HDR) 1; # We're reading headers. set LC {}; # No last char in current document. set wantNL($txt) 1; # We are at the start of a new line. if {$V>1} {puts "$id: Started in(HDR)=$in(HDR) in(H)=$in(H) f=\"$f\" getcmd=\"$getcmd\""} set docFil $f set docPid [pid $f] set docLines 0 WaitDone - Waiting fileevent $f readable "docRdr {$txt} {$f}" } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # Handle one header line. We only get these from web servers; for local # # files, this will never be called. # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # proc hdrLine {l} { global V me docFil Herr imageViewer imagePid imagePipe in loadstart loadspeed \ opt doctype Sep subtype URLt redirect curD curW set id "$me/hdrLine" if {$V>4} {puts "$id: \"$l\""} if {$V>4} {puts "$id: .hdr.t insert end \"$l\\n\""} .hdr.t insert end $l\n if {$V>4} {puts "$id: \"$l\" inserted."} if {$l == {}} { if {$V>4} {puts "$id: Null line ends headers."} set in(HDR) 0 if {$V>4} {puts "$id: Check doctype=\"$doctype\" imagePipe=\"$imagePipe\""} if {$doctype == {image} && $imagePipe != {}} { if {$V>4} {puts "$id: Image file."} set in(IMAGE) 1 fconfigure $imagePipe -blocking 0 -buffering none -translation binary fconfigure $docFil -blocking 0 -buffering none -translation binary if {$V>2} {puts "$id: Start \"fcopy $docFil $imagePipe -command imageDone\""} fcopy $docFil $imagePipe -command imageDone } else { if {$V>4} {puts "$id: Text file."} } } else { if {$V>4} {puts "$id: Header \"$l\""} if [regexp {^(HTTP/[0-9.]+)[ ]+([4-9][0-9]+)[ ]+(.*)} $l {} v e m] { Msg [set Herr "$v ERROR $e $m"] } elseif [regexp {^Content-Type: *(.*)/(.*)} $l {} t s] { if {$V>4} {puts "$id: Content-Type: t=\"$t\" s=\"$s\""} set doctype [string tolower $t] set subtype [string tolower $s] set in(H) $opt(H) if {$V>2} {puts "$id: doctype=\"$doctype\" subtype=\"$subtype\""} switch $doctype { text { switch $subtype { html {set in(H) 1; set Sep " "} plain {set in(H) 0; set Sep "\n"} } } image { Msg "Document is image/$subtype" set in(H) 0 Htxt "Starting $imageViewer to view $URLt($curD) ...\n" if [catch {open "| $imageViewer" w} f] { Msg "Can't run \"$imageViewer\" ($f)" if {$V>0} {puts "$id: Can't run \"$imageViewer\" ($f)"} return } set imagePipe $f set imagePid [pid $f] if {$V>2} {puts "$id: IMAGE/$subtype $imagePipe=\"$imageViewer\""} } default { if [set in(H) $opt(H)] {set Sep { }} else {set Sep "\n"} } } if {$V>2} {puts "$id: Content-Type: $doctype/$subtype set in(H)=$in(H).."} } elseif [regexp {^} $l {} t s] { Msg $t } elseif [regexp {^Location: *(.*)} $l {} t s] { Msg "Redirected to \"$t\"" Stop set redirect 1 LoadFile "$curW" "" "$t" GET set redirect 0 } else { if {$V>4} {puts "$id: Header \"$l\" ignored."} } if {$V>4} {puts "$id: Header \"$l\" done."} } if {$V>4} {puts "$id: Done."} } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # proc LoadMsg args { global V loadspeed loadstart if {$args == {}} { Msg "Loading document ($loadspeed c/s)" } else { Msg "[concat $args] ($loadspeed c/s)" } } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # Check to see if an image file is in the cache, and if so, we load it # # immediately into frame i. If not, we call GetCache to start a new # # background process to load the image. # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # proc CheckCache {w i u} { global V B R me curD isRmt Foto Fott Fotw FotW i2f i2U i2w U2i U2f set id "$me/CheckCache" if {$V>5} {puts "$id: $w image $i url \"$u\""} if ![info exists i2w($i)] { if {$V>0} {puts "$id: ### Image $i not in i2w ###"} return } set i2U($i) [set U [url2URL "$u"]] if {$V>4} {puts "$id: win \"$w\" image $i URL \"$i2U($i)\" img $i2w($i)"} if ![info exists U2f($U)] { if {$V>4} {puts "$id: $U hasn't been loaded."} GetCache $w $i $U return } if {$V>4} {puts "$id: $U has been loaded."} set f "$U2f($U)" if {$V>4} {puts "$id: url $U is in file \"$f\" for images {$U2i($U)}"} if [regexp -nocase {\.xbm$} $f] {set Fott($U) bitmap} else {set Fott($U) photo} if [catch {image create $Fott($U) Foto($U) -file $f} x] { if {$V>0} {puts "$id: ### Can't load image from \"$f\" ($x)"} BadCache $w $f $U $x GetCache $w $i $U return } if ![info exists Fotw($U)] {ImgSize $curD $i $U} if {$V>4} {puts "$id: New $Fott($U) Foto($U) (Fotw=$Fotw($U)) (FotW=$FotW($U))"} set U2f($U) "$f" set i2f($i) "$f" FotoIMG "$curD" "$i" "$U" } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # This is called when we have a new URL to add to the Hist list and stack. proc NewURL {name} { global V me Hist stk stkN if {[lsearch $Hist $name] < 0} { if {$V>1} {puts "NewURL: Hist doesn't contain \"$name\""} set Hist [linsert $Hist 0 $name] if {$V>4} {puts "NewURL: Hist={$Hist}"} } if {$stkN > 0} { set x [lindex $stk $stkN] if {$x == $name} { if {$V>1} {puts "NewURL: \"$name\" is stack $stkN \"$x\""} } else { if {$V>1} {puts "NewURL: \"$name\" differs from stack $stkN \"$x\""} incr stkN -1 set stk [lreplace $stk $stkN $stkN $name] if {$V>1} {puts "NewURL: Replaced stack $stkN with \"$name\""} } } else { if {[lindex $stk 0] != $name} { set stk [linsert $stk 0 $name] if {$V>1} {puts "NewURL: Inserted \"$name\" at top of stack"} } } } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # This is called when we finish copying in an image file. This is only used # # when the main "document file" is actually a graphic image file. For images # # embedded within HTML documents, we now rely on H_cache to fetch the file, # # and tell us what its cache name is. # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # proc imageDone {args} { global V me docFil imagePipe in if {$V>2} {puts "$me/imageDone: docFil={$docFil} imagePipe={$imagePipe} args={$args}"} if {$docFil != {}} { if {$V>5} {puts "$me/imageDone: Close docFil={$docFil} ..."} close $docFil if {$V>6} {puts "$me/imageDone: Closed docFil={$docFil}"} } if {$imagePipe != {}} { if {$V>5} {puts "$me/imageDone: Close imagePipe={$imagePipe} ..."} close $imagePipe if {$V>6} {puts "$me/imageDone: Closed imagePipe={$imagePipe}"} } set in(IMAGE) 0 WaitDone + Msg Done } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # Here's the main routine for loading a document into the .src window, and # # loading the processed version into a document window. For remote files, we # # fire up a w3cat process to fetch the file and feed us the data, which we # # read line at a time and parcel out to other functions for further # # processing. The meth arg is the method to use, GET or POST. # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # proc LoadFile {xxx trgt name meth} { global V me curD curW Doc URLt PROT HOST DIR docFil docPid Hist isRmt N opt in \ txtlvl ll waitstyle redirect set id "$me/LoadFile" if {$V>2} {puts "$id: \"$xxx\" trgt=\"$trgt\" name=\"$name\" meth=\"$meth\""} wm title . $name # if {$xxx == {}} { # set curW $xxx # set curD $xxx.f.d # } elseif [regexp {(.*)\.f\.d$} $xxx {} curW] { # set curD $xxx # } else { # set curW $xxx # set curD $xxx.f.d # } set curD $Doc set curW {} set U [set URLt($curD) $name] if {$V>2} {puts "$id: URLt($curD)=\"$URLt($curD)\""} set isRmt 0 set Imgdly 0 set txtlvl 0 # set N(TABLE) 0 NtagInit if {$V>4} {puts "$id: \"$name\" URL=\"$U\""} if {$V>4} {puts "$id: name=\"$name\""} if {$V>4} {puts "$id: Hist={$Hist}"} if {$meth == {GET}} {NewURL $name} if [regexp {^#(.*)$} $name {} mark] { ToMark $curD $mark return } if {$docFil != {}} { if {$V>1} {puts "$id: Stop load from \"$docFil\" pid $docPid."} Msg "Stop current load f=\"$docFil\" p=$docPid ..." Stop } if {$trgt != {}} { if [info exists target($trgt)] { if {[set x $target($trgt)] != {}} { set curW $x if {$V>2} {puts "$id: Target \"$trgt\" is window \"$curW\""} } else { set n [incr N(TARGET)] set curW [set target($trgt) .w$n] if {$V>2} {puts "$id: Target \"$trgt\" is new window \"$curW\""} } set curD $curW.f.d if {$V>2} {puts "$id: curD set to \"$curD\""} } } if {$V>2} {puts "$id: Window curW is \"$curW\" text curD is \"$curD\""} docInit $curW if [winfo exists .src.t] {.src.t delete 1.0 end} if !$redirect { .hdr.t delete 1.0 end } if [file exists $name] { if {$V>4} {puts "$id: name=\"$name\" is a local file."} if [file isdirectory $name] { if {$V>4} {puts "$id: name=\"$name\" is a local directory."} set DIR [set d [Dir "$name/"]] if {$DIR == {./}} {set DIR [pwd]/} GetURL $curD $d $meth return } if [catch {open $name r} h] {Msg $h; return} if [regexp {^(/)([^/]*)$} $name {} d f] { if {$V>4} {puts "$id: Absolute directory \"$d\" + file \"$f\""} set DIR $d if {$V>4} {puts "$id: DIR=\"$DIR\" file=\"$f\" (ABS1)"} } elseif [regexp {^(/.*/)(.*$)} $name {} d f] { if {$V>4} {puts "$id: Absolute directory \"$d\" + file \"$f\""} set DIR [Dir $d] if {$V>4} {puts "$id: DIR=\"$DIR\" file=\"$f\" (ABS2)"} } elseif [regexp {^(.*/)(.*$)} $name {} d f] { if {$V>4} {puts "$id: Relative directory \"$d\" + file \"$f\""} set DIR [Dir $d] if {$V>4} {puts "$id: DIR=\"$DIR\" file=\"$f\" (REL)"} } else { if {$V>4} {puts "$id: Simple file \"$name\""} } while {[gets $h line] >= 0} { if {$V>4} {puts "$id: line=\"$line\""} if {$waitstyle>0} {Tick} if {$V>4} {puts "$me/hdrLine: .src.t insert end \"$line\\n\""} .src.t insert end $line\n docLine $curD $line update idletasks } if {$V>4} {puts "$id: EOF"} docDone $curD $h return } if [regexp {^([A-Za-z]+)://([-A-Za-z0-9_.:]*)/(.*)$} $name {} PROT HOST path] { if {$V>4} {puts "$id: name=\"$name\" is a full URL."} if {$V>4} {puts "$id: PROT=\"$PROT\" HOST=\"$HOST\" path=\"$path\""} if {$V>4} {puts "$id: name=\"$name\" looks like a remote file."} if [regexp {^(.*)/(.*)$} $path {} d f] { if {$V>4} {puts "$id: d=\"$d\""} set DIR /$d/ } GetURL $curD $name $meth return } if {$PROT != {} && $HOST != {}} { if {$V>4} {puts "$id: PROT=\"$PROT\" HOST=\"$HOST\" name=\"$name\" relative file."} if [regexp {^(/.*)/(.*$)} $name {} d f] { if {$V>4} {puts "$id: Absolute directory \"$d\" + file \"$f\""} set url "$PROT://$HOST$name" if {$V>4} {puts "$id: url=\"$url\""} } elseif [regexp {^(.*)/(.*$)} $name {} d f] { if {$V>4} {puts "$id: Relative directory \"$d\" + file \"$f\""} set url "$PROT://$HOST$DIR$name" if {$V>4} {puts "$id: url=\"$url\""} } else { if {$V>4} {puts "$id: Simple file \"$name\""} set url "$PROT://$HOST$DIR$name" if {$V>4} {puts "$id: url=\"$url\""} } GetURL $curD $url $meth return } Msg "Can't handle \"$name\"" } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # The Load button merely fetches a new copy of the current document and loads # # it into the $w and .src windows. # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # proc Load {w} { global URLt curD docFil if {$docFil != {}} {Stop} LoadFile "$w" "" $URLt($curD) GET } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # Stop a load operation. It turns out that just closing the pipe has no # # effect on w3cat, which is probably hung on a connect() call. But a TERM # # signal seems to get its attention. # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # proc Stop {} { global docFil docPid waitchr Msg {Stop the transfer ...} if {$docFil == {}} { Msg {No transfer in progress} return } if {$docPid != {}} { if [catch {eval exec kill -TERM $docPid} x] { Msg $x } else { Msg "TERMed doc process $docPid." set docPid {} } } if [catch {close $docFil} x] { Msg $x } else { Msg "Closed doc file \"$docFil\"." set docFil {} } WaitDone * } # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # # We have encountered a new IMG tag. It is common for the same image to # # appear several times in a document, and so we try to keep track of images # # and only load each one once. We first create a frame to hold the image, and # # fill it with the ALT text if one exists. Then we try to load the image. If # # it's a local file, we can read it directly. If it's a remote file, we talk # # to a H_cache process to fetch it for us asynchronously. # # - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - # proc tagIMG {w t a} { global B V FB IB R curD TxtLen me ALT bd Foto in link Ltag N i2w i2U U2i Obj opt set id "$me/tagIMG" DoSP set ni [incr N(IMG)]; # Number of images in this doc. set no [incr N(OBJ)]; # Number of objects in this doc. set f "$curD.img$ni"; # Frame for image. if {$V>1} {puts "$id: Image $ni Frame $f is <$t $a> ..."} if [winfo exists $f] {destroy $f} eval frame $f $FB if {$V>4} {puts "$id: Frame $f created."} set ALT($ni) {___} set Obj($no) {---} eval label $f.alt -textvariable ALT($ni) $IB incr TxtLen($curD) [string length $ALT($ni)] if {$V>2} {puts "$id: $curD TxtLen=$TxtLen($curD) chars (ALT($ni)."} pack $f.alt -in $f -side bottom set i2w($ni) $f if {$V>4} {puts "$id: $curD window create insert -window \"$f\""} $curD window create insert -window $f if {[regexp -nocase {ALT="([^"]*)"} $a {} alt] || [regexp -nocase {ALT=([^ ]*)} $a {} alt]} { if {$V>1} {puts "$id: ALT=\"$alt\" attribute"} set Obj($no) [set ALT($ni) [Hdecode $alt]] bind $f "ObjEnter $f.alt $no %X %Y {$alt}" bind $f "ObjLeave $f.alt $no %X %Y" if {$V>1} {puts "$id: $f.alt filled with \"$alt\""} if {$in(A)} {ButtonBindings $curD $f.alt $link} } if [regexp -nocase {SRC="([^"]+)"} $a {} src] { if {$V>4} {puts "$id: SRC=\"$src\" attribute"} if {$opt(IMG)} { if {$V>4} {puts "$id: src=\"$src\""} set SRC [url2URL $src] if {$V>4} {puts "$id: src=\"$src\""; puts "$id: SRC=\"$SRC\""} if [info exists Fotw($SRC)] { if {$V>4} {puts "$id: Foto($SRC) has been loaded already."} FotoIMG $curD $ni $SRC } elseif [file readable $SRC] { if {$V>4} {puts "$id: Foto($SRC) is local file."} set i2U($ni) $SRC set U2i($SRC) $ni if {$V>4} {puts "$id: i2U($ni)=\"$i2U($ni)\" U2i($SRC)=$U2i($SRC)"} LoadImgFile $curD $ni $SRC } else { if {$V>4} {puts "$id: Foto($SRC) must be loaded."} CheckCache $curD $ni $SRC } } else { if {$V>3} {puts "$id: Not showing images."} } } if {$Ltag == {Llink}} { if {$V>4} {puts "$id: We are inside Link $link."} $f configure -bd $bd(LNK) -relief ridge if {$in(A)} {ButtonBindings $curD $f $link} } HSP $curD {} }