Attempt to inform user if session has really terminated.
[egate.git] / www / z39util.tcl
index 51d3e18..36a28a1 100644 (file)
@@ -1,5 +1,5 @@
 #
-# $Id: z39util.tcl,v 1.22 1996/01/23 14:22:03 adam Exp $
+# $Id: z39util.tcl,v 1.41 1996/03/14 11:50:51 adam Exp $
 #
 proc saveState {} {
     uplevel #0 {
@@ -65,12 +65,10 @@ proc fail-response {} {
     set sessionWait -1
 }
 
-proc display-brief {zset no tno} {
+proc display-medium {zset no setNo targetNo} {
     global env
-    global setNo
     global sessionId
 
-
     html {<li>}
     set type [$zset type $no]
     if {$type == "SD"} {
@@ -86,11 +84,29 @@ proc display-brief {zset no tno} {
         return
     }
     set rtype [$zset recordType $no]
-    if {$rtype == "SUTRS"} {
-        html [join [$zset getSutrs $no]]
-        html "<br>\n"
-        return
-    } 
+    switch $rtype {
+        SUTRS {
+            html { <a href="http:} $env(SCRIPT_NAME) / $sessionId
+            html {/showfull.egw/} $setNo + $targetNo + $no + full {">}
+            html [join [$zset getSutrs $no]]
+            html "</a><br>\n"
+            return
+        }
+        WAIS {
+            html { <a href="http:} $env(SCRIPT_NAME) / $sessionId
+            html {/showfull.egw/} $setNo + $targetNo + $no + full {">}
+            html [join [$zset getWAIS $no headline]]
+            html {</a>}
+            html "<br>\n"
+            html {Score: } [$zset getWAIS $no score]
+            set lines [$zset getWAIS $no lines]
+            if {$lines > 0} {
+                html {, } $lines { lines}
+            }
+            html "<br>\n"
+            return
+        }
+    }
     if {![catch {
         set author [$zset getMarc $no field 100 * a]
         set corp [$zset getMarc $no field 110 * a]
@@ -104,7 +120,10 @@ proc display-brief {zset no tno} {
        set location [$zset getMarc $no field 260 * a] 
        set publisher [$zset getMarc $no field 260 * b]
         set year [$zset getMarc $no field 260 * c]
-    } ] } {
+        set score [$zset getMarc $no field 999 * r]
+    } dispError ] } {
+        html { <a href="http:} $env(SCRIPT_NAME) /
+        html $sessionId {/showfull.egw/} $setNo + $targetNo + $no + full {">}
         set p 0
         foreach a $author {
             if {$p} {
@@ -130,37 +149,37 @@ proc display-brief {zset no tno} {
         if {$p} {
             html ": "
         }
-       html {<em>}
        set nope 1
         foreach v $title {
             html $v
             set nope 0
         }
-        if {$nope} {
-            html {No title} 
-        }
-        html {</em> }
-       foreach v $cover {
-           html $v
-       }
-        html {<br>}
-       foreach v $location {
-           html " $v"
-        }
-       foreach v $publisher {
-           html " $v"
+        set v [join $cover ""]
+        if {[string length $v] > 0} {
+            set nope 0
+            html $v
+        } elseif {$nope} {
+            html "No Title"
         }
-       foreach v $year {
-           html " $v"
+        html {</a> }
+        if {[scan $score %d nscore]} {
+            html "; Score " $nscore
         }
-        html { -- <a href="http:} $env(SCRIPT_NAME) /
-        html $sessionId {/showfull.egw/} $setNo + $tno + $no + full {">}
-       html "<em>view full</em></a>"
+    } else {
+        html { <a href="http:} $env(SCRIPT_NAME) /
+        html $sessionId {/showfull.egw/} $setNo + $targetNo + $no + full {">}
+        html {No Title}
+        html {</a> }
+        html "Error: " $dispError "\n"
     }
     html "<br>\n"
 }
 
-proc display-raw {zset no tno} {
+proc display-brief {zset no setNo targetNo} {
+    global env
+    global sessionId
+
+    html {<li>}
     set type [$zset type $no]
     if {$type == "SD"} {
         set err [lindex [$zset diag $no] 1]
@@ -168,18 +187,134 @@ proc display-raw {zset no tno} {
         if {$add != {}} {
             set add " :${add}"
         }
-        html "<h3>${no}</h3>\n"
-        html "Error ${err}${add} <br>\n"
+        html "${no} Error ${err}${add} <br>\n"
         return
     }
     if {$type != "DB"} {
         return
     }
     set rtype [$zset recordType $no]
-    if {$rtype == "SUTRS"} {
-        html [join [$zset getSutrs $no]] "<br>\n"
-        return
-    } 
+    switch $rtype {
+        SUTRS {
+            html { <a href="http:} $env(SCRIPT_NAME) / $sessionId
+            html {/showfull.egw/} $setNo + $targetNo + $no + full {">}
+            html [string range [join [$zset getSutrs $no]] 0 70]
+            html "</a><br>\n"
+            return
+        }
+        WAIS {
+            html { <a href="http:} $env(SCRIPT_NAME) / $sessionId
+            html {/showfull.egw/} $setNo + $targetNo + $no + full {">}
+            html [string range [join [$zset getWAIS $no headline]] 0 70]
+            
+            html {</a>}
+            set score [$zset getWAIS $no score]
+            html { Score } $score
+            html "<br>\n"
+            return
+        }
+    }
+    if {![catch {
+        set author [$zset getMarc $no field 100 * a]
+        set corp [$zset getMarc $no field 110 * a]
+        set meet [$zset getMarc $no field 111 * a]
+        set title [$zset getMarc $no field 245 * a]
+       if {[llength $author] == 0} {
+            set cover [$zset getMarc $no field 245 * {[bc]}]
+       } else {
+            set cover [$zset getMarc $no field 245 * b]
+       }
+       set location [$zset getMarc $no field 260 * a] 
+       set publisher [$zset getMarc $no field 260 * b]
+        set year [$zset getMarc $no field 260 * c]
+    } dispError ] } {
+        html { <a href="http:} $env(SCRIPT_NAME) /
+        html $sessionId {/showfull.egw/} $setNo + $targetNo + $no + full {">}
+        set p 0
+        foreach a $author {
+            if {$p} {
+                html ", "
+            }
+            html $a
+            set p 1
+        }
+        foreach a $corp {
+            if {$p} {
+                html ", "
+            }
+            html $a
+            set p 1
+        }
+        foreach a $meet {
+            if {$p} {
+                html ", "
+            }
+            html $a
+            set p 1
+        }
+        if {$p} {
+            html ": "
+        }
+        html {<it>}
+       set nope 1
+        foreach v $title {
+            html $v
+            set nope 0
+        }
+        html {</it>}
+        if {$nope} {
+            set v [join $cover ""]
+            if {[string length $v] > 40} {
+                set nope 0
+                html [string range $v 0 38] "..."
+            } elseif {[string length $v] > 0} {
+                set nope 0
+                html $v
+            } else {
+                html "No Title"
+            }
+       }
+        html {</a> }
+    } else {
+        html { <a href="http:} $env(SCRIPT_NAME) /
+        html $sessionId {/showfull.egw/} $setNo + $targetNo + $no + full {">}
+        html {No Title}
+        html {</a> }
+        html "Error: " $dispError "\n"
+    }
+    html "<br>\n"
+}
+
+proc display-raw {zset no setNo targetNo} {
+    set type [$zset type $no]
+    switch $type {
+        SD {
+            set err [lindex [$zset diag $no] 1]
+            set add [lindex [$zset diag $no] 2]
+            if {$add != {}} {
+                set add " :${add}"
+            }
+            html "<h3>${no}</h3>\n"
+            html "Error ${err}${add} <br>\n"
+            return
+        }
+        DB {
+        }
+        default {
+            return
+        }
+    }
+    set rtype [$zset recordType $no]
+    switch $rtype {
+        SUTRS {
+            html "<xmp>\n" [join [$zset getSutrs $no]] "\n</xmp>\n"
+            return
+        } 
+        WAIS {
+            html "<xmp>\n" [join [$zset getWAIS $no text]] "\n</xmp>\n"
+            return
+        }
+    }
     if {[catch {set r [$zset getMarc $no line * * *]}]} {
         html "Unknown record type: $rtype <br>\n"
         return
@@ -208,7 +343,7 @@ proc display-raw {zset no tno} {
             }
             html $data
         }
-        htmlr {<br>}
+        html "<br>\n"
     }
 }
 
@@ -297,29 +432,11 @@ proc dl-marc-field-rec {zset no tag lead start stop startid sep} {
     }
 }
 
-proc display-full {zset no tno} {
-    set type [$zset type $no]
-    if {$type == "SD"} {
-        set err [lindex [$zset diag $no] 1]
-        set add [lindex [$zset diag $no] 2]
-        if {$add != {}} {
-            set add " :${add}"
-        }
-        html "Error ${err}${add} <br>\n"
-        return
-    }
-    if {$type != "DB"} {
-        return
-    }
-    set rtype [$zset recordType $no]
-    if {$rtype == "SUTRS"} {
-        html [join [$zset getSutrs $no]] "<br>\n"
-        return
-    } 
-    if {[catch {set r [$zset getMarc $no line * * *]}]} {
-        html "Unknown record type: $rtype <br>\n"
-        return
-    }
+proc display-full-marc {zset no setNo targetNo} {
+    global env
+    global hist
+    global sessionId
+
     html "<dl>\n"
     set n [dl-marc-field $zset $no 700 a "Author" "Authors" "<br>\n"]
     if {$n == 0} {
@@ -401,40 +518,176 @@ proc display-full {zset no tno} {
         if {"x$sp" == "x"} {
             set sp $url
         }
-        html {<dd><a href="} $url {">} [join $sp] "</a>\n"
+        html {<dd><a href="} [join $url] {">} [join $sp] "</a>\n"
     }
     dl-marc-field $zset $no 037 {[abc]} "Acquisition" {} "<br>\n"
     dl-marc-field $zset $no 037 {[f6]} "Form of issue" {} "<br>\n"
     dl-marc-field $zset $no 537 * "Source of data" {} "<br>\n"
     dl-marc-field $zset $no 538 * "System details" {} "<br>\n"
     dl-marc-field $zset $no 787 {[rstw6]} "Related information" {} "<br>\n"
+    dl-marc-field $zset $no 999 r "Score" {} ", "
     dl-marc-field $zset $no 001 * "Local control number" {} ", "
     html "</dl>\n"
 }
 
+proc display-full-wais {zset no setNo targetNo} {
+    global env
+    global hist
+    global sessionId
 
-proc display-rec {from to dfunc tno} {
-    global setNo
-
-    if {$tno > 0} {
-        while {$from <= $to} { 
-            eval "$dfunc z39${tno}.${setNo} $from $tno"
-            incr from
+    set i 0    
+    set element junk
+    htmlToken l [join [$zset getWAIS $no text]] {
+        if {[string compare [string index $l 0] {<}]} {
+            if {[info exist data($element)]} {
+                set data($element) $data($element)$l
+            } else {
+                set data($element) $l
+            }
+            continue
         }
+        switch -- $l {
+            <ti> {
+                set element title 
+            }
+            <dm> {
+                set element dateOfLastModification
+            }
+            <ci> {
+                set element controlIdentifier
+            }
+            <lc> {
+                set element lastChecked
+            }
+            <by> {
+                set element bytes
+            }
+            <avli> {
+                set element linkage
+            }
+            <cr> {
+                incr i
+            }
+            <li> {
+                set element "$i,linkage"
+            }
+            <cp> {
+                set element "$i,title"
+            }
+            <ip> {
+                set element ip
+            }
+            default {
+                set element junk
+            }
+        }
+    }
+    if {![info exists data(title)] || ![info exists data(linkage)]} {
+        set nwi 0
+    } else {
+        set nwi 1
+    }
+    html "<dl>\n"
+    html {<dt><b>Title</b>}
+    if {$nwi} {
+        html {<dd><a href="} $data(linkage) {">} $data(title) "</a>"
+        html {<dt><b>URL</b>}
+        html {<dd>} $data(linkage) "<br>\n"
     } else {
-        while {$from <= $to} { 
-            eval "$dfunc z39.${setNo} $from 0"
-            incr from
+        html {<dd>} [join [$zset getWAIS $no headline]]
+    }
+    html {<dt><b>Score</b><dd>} [$zset getWAIS $no score]
+    set lines [$zset getWAIS $no lines]
+    if {$lines > 0} {
+        html {<dt><b>Lines</b><dd>} $lines "<br>\n"
+    }
+    if {!$nwi} {
+        html "</dl><pre>\n" [join [$zset getWAIS $no text]] "\n</pre>\n"
+        return
+    }
+    if {[info exists data(bytes)]} {
+        html {<dt><b>Bytes</b><dd>} $data(bytes)
+    }
+    if {[info exists data(dateOfLastModification)]} {
+        html {<dt><b>Last modified</b><dd>} $data(dateOfLastModification)
+    }
+    if {[info exists data(lastChecked)]} {
+        html {<dt><b>Last checked</b><dd>} $data(lastChecked) "<br>\n"
+    }
+    if {[info exists data(ip)]} {
+        html {<dt><b>Initial text</b><dd>} $data(ip) "<br>\n"
+    }
+    if {0} {
+        html {<a href="} $env(SCRIPT_NAME) / $sessionId {/sameas.egw/}
+        html $setNo + $targetNo + 1 + $hist($setNo,maxPresent) +
+        html [egw_enc [$zset getWAIS $no documentID]] {">}
+        html {Similar WAIS record</a><br>}
+    }
+    if {[info exists data($i,linkage)]} {
+        html "<dt><b>References</b>\n"
+    }
+    for {set i 1} {[info exists data($i,linkage)]} {incr i} {
+        html {<dd><a href="} $data($i,linkage) {">}
+        if {[info exists data($i,title)]} {
+            html $data($i,title)
+        } else {
+            html Untitled
+        }
+        html "</a><br>\n"
+    }
+    html "</dl>\n"
+}
+
+proc display-full {zset no setNo targetNo} {
+    set type [$zset type $no]
+    switch $type {
+        SD {
+            set err [lindex [$zset diag $no] 1]
+            set add [lindex [$zset diag $no] 2]
+            if {$add != {}} {
+                set add " :${add}"
+            }
+            html "Error ${err}${add} <br>\n"
+            return
+        }
+        DB {
+        }
+        default {
+            return
+        }
+    }
+    set rtype [$zset recordType $no]
+    switch $rtype {
+        SUTRS {
+            html "<pre>" [join [$zset getSutrs $no]] "</pre><br>\n"
+            return
         }
+        WAIS {
+            display-full-wais $zset $no $setNo $targetNo
+            return
+        }
+    }
+    if {[catch {set r [$zset getMarc $no line * * *]}]} {
+        html "Unknown record type: $rtype <br>\n"
+        return
+    }
+    display-full-marc $zset $no $setNo $targetNo
+}
+
+
+proc display-rec {from to dfunc setNo targetNo} {
+    while {$from <= $to} { 
+        eval "$dfunc z39${targetNo}.${setNo} $from $setNo $targetNo"
+        incr from
     }
 }
 
 proc build-scan {t i} {
     global targets
 
-    set term [wform entry$i]
+    set term [egw_form entry$i]
     if {$term != ""} {
-        set field [join [wform menu$i]]
+        set field [join [egw_form menu$i]]
         set attr {Title}
         foreach x [lindex $targets($t) 2] {
             if {[lindex $x 0] == $field} {
@@ -452,25 +705,39 @@ proc build-query {t ilines} {
     set op {}
     set q {}
     for {set i 1} {$i <= $ilines} {incr i} {
-        set term [join [wform entry$i]]
-        if {[string length $term] > 0} {
-            set field [join [wform menu$i]]
+        set term [join [egw_form entry$i]]
+        if {[string length $term] == 0} continue
+        if {![string compare [lindex $targets($t) 1] WAIS]} {
+            if {[string length $q] == 0} {
+                set q $term
+            } else {
+                set q "$term $q"
+            }
+            set op [egw_form logic$i]
+            continue
+        } else {
+            set field [join [egw_form menu$i]]
+            catch {unset attr}
             foreach x [lindex $targets($t) 2] {
-                if {[lindex $x 0] == $field} {
+                if {![string compare [lindex $x 0] $field]} {
                     set attr [lindex $x 1]
                 }
             }
+            if {![info exists attr]} {
+                egw_log debug "attr failed for $t"
+                set attr [lindex [lindex [lindex $targets($t) 2] 0] 1]
+            }
             switch $op {
-            And
-                { set q "@and $q ${attr} ${term}" }
-            Or
-                { set q "@or $q ${attr} ${term}" }
-            {And not}
-                { set q "@not $q ${attr} ${term}" }
-            {}
-                { set q "${attr} ${term}" }
+                And
+                { set q "@and $q ${attr} \"${term}\"" }
+                Or
+                { set q "@or $q ${attr} \"${term}\"" }
+                {And not}
+                { set q "@not $q ${attr} \"${term}\"" }
+                {}
+                { set q "${attr} \"${term}\"" }
             }
-            set op [wform logic$i]
+            set op [egw_form logic$i]
         }
     }
     return $q
@@ -481,69 +748,60 @@ proc z39scan {setNo scanNo tno scanLines scanPos cache} {
     global sessionWait
     global targets
 
-    if {$tno > 0} {
-        set zz z39$tno
-        set host $hist($setNo,$tno,host)
-        set idAuth $hist($setNo,$tno,idAuthentication)
-        set database $hist($setNo,$tno,database)
-        set scanAttr $hist($setNo,$tno,scanAttr)
-        set scanTerm $hist($setNo,$tno,$scanNo,scanTerm)
-    } else {
-        set zz z39
-        set host $hist($setNo,host)
-        set idAuth $hist($setNo,idAuthentication)
-        set database $hist($setNo,database)
-        set scanAttr $hist($setNo,scanAttr)
-        set scanTerm $hist($setNo,$scanNo,scanTerm)
-    }
-    if {[catch [list $zz failback fail-response]]} {
-        ir $zz
-    }
+    set zz z39$tno
+    set host $hist($setNo,$tno,host)
+    set idAuth $hist($setNo,$tno,idAuthentication)
+    set database $hist($setNo,$tno,database)
+    set scanAttr $hist($setNo,scanAttr)
+    set scanTerm $hist($setNo,$scanNo,scanTerm)
+
+    mkAssoc $zz $host
     if {[catch [list set oldHost [$zz connect]]]} {
         set oldHost ""
     }
     set zs $zz.s$scanNo.$setNo
     $zz callback ok-response
     $zz failback fail-response
-    if {$oldHost != $host} {
+    set thisHost [splitHostSpec $host]
+    if {[string compare $oldHost $thisHost]} {
         catch [list $zz disconnect]
 
         set sessionWait 0
-        if {[catch [list $zz connect $host]]} {
-            displayError "Cannot connect to target" $host
+        if {[catch [list $zz connect $thisHost]]} {
+            displayError "Cannot connect to target" $thisHost
             return 0
         } elseif {$sessionWait == 0} {
-            if {[catch {zwait sessionWait 300}]} {
+            if {[catch {egw_wait sessionWait 300}]} {
                $zz disconnect
-                displayError "Cannot connect to target" $host
+                displayError "Cannot connect to target" $thisHost
                 return 0
             }
             if {$sessionWait != 1} {
-                displayError "Cannot connect to target" $host
+                displayError "Cannot connect to target" $thisHost
                 return 0
             }
         }
         $zz idAuthentication $idAuth
         set sessionWait 0
         if {[catch {$zz init}]} {
-            displayError "Cannot initialize target" $host
+            displayError "Cannot initialize target" $thisHost
            $zz disconnect
             return 0
         }
-        if {[catch {zwait sessionWait 60}]} {
-            displayError "Cannot initialize target" $host
+        if {[catch {egw_wait sessionWait 60}]} {
+            displayError "Cannot initialize target" $thisHost
            $zz disconnect
             return 0
         }
         if {$sessionWait != "1"} {
-            displayError "Cannot initialize target" $host
+            displayError "Cannot initialize target" $thisHost
            $zz disconnect
             return 0
         }
         if {![$zz initResult]} {
             set u [$zz userInformationField]
             $zz disconnect
-            displayError "Cannot initialize target $host" $u
+            displayError "Cannot initialize target $thisHost" $u
             return 0
         }
     } else {
@@ -560,11 +818,12 @@ proc z39scan {setNo scanNo tno scanLines scanPos cache} {
 
     $zz callback [list scan-response $zs]
 
+    egw_log debug "scan: ${scanAttr} ${scanTerm}"
     set sessionWait 0
     $zs scan "${scanAttr} ${scanTerm}"
 
-    if {[catch {zwait sessionWait 60}]} {
-        wlog debug "timeout/cancel in scan"
+    if {[catch {egw_wait sessionWait 60}]} {
+        egw_log debug "timeout/cancel in scan"
         displayError "Timeout in scan" {}
         html "</body></html>\n"
         $zz disconnect
@@ -586,12 +845,9 @@ proc display-scan {setNo scanNo tno} {
     global targets
     global env
     global sessionId
+    global scriptQuery
 
-    if {$tno > 0} {
-        set zz z39$tno
-    } else {
-        set zz z39
-    }
+    set zz z39$tno
     set zs $zz.s$scanNo.$setNo
     set m [$zs numberOfEntriesReturned]
         
@@ -609,16 +865,31 @@ proc display-scan {setNo scanNo tno} {
             set hist($setNo,[expr $scanNo + 1],scanTerm) $t
         }
     }
+    html {<table width=500 border=0><tr>}
+    html {<td align=left><b>Scan term</b>}
+    html {<td align=right><b>Hits</b>}
+    html {<tr>} \n
+
     for {set i 0} {$i < $m} {incr i} {
-        regsub -all {\ } [lindex [$zs scanLine $i] 1] + tterm
-        html {<a href="http:} $env(SCRIPT_NAME)
-        html / $sessionId {/query.egw/} $hist($setNo,host) + $setNo +
-        html $hist($setNo,scan) +  $tterm {">}
+        html {<td align=left>}
+        if {0} {
+            regsub -all {\ } [lindex [$zs scanLine $i] 1] + tterm
+            html {<a href="http:} $env(SCRIPT_NAME)
+            html / $sessionId / $scriptQuery {;/} $setNo + $hist($setNo,host) +
+            html $hist($setNo,scan) +  $tterm {">}
+        } else {
+            regsub -all {\ } [lindex [$zs scanLine $i] 1] + tterm
+            html {<a href="http:} $env(SCRIPT_NAME)
+            html / $sessionId {/search.egw/} $setNo + $tno +
+            html hyper + $tterm {">}
+        }
         html [lindex [$zs scanLine $i] 1]
-        html {</a>: <em>}
+        html {</a>} 
+        html {<td align=right>}
         html [lindex [$zs scanLine $i] 2]
-        html "</em><br>\n"
+        html {<tr>} \n
     }
+    html {</table} \n
 }
 
 proc z39search {setNo piggy tno elements} {
@@ -626,77 +897,74 @@ proc z39search {setNo piggy tno elements} {
     global sessionWait
     global targets
 
-    if {$tno > 0} {
-        set zz z39$tno
-        set host $hist($setNo,$tno,host)
-        set idAuth $hist($setNo,$tno,idAuthentication)
-        set database $hist($setNo,$tno,database)
-        set query $hist($setNo,$tno,query)
-    } else {
-        set zz z39
-        set host $hist($setNo,host)
-        set idAuth $hist($setNo,idAuthentication)
-        set database $hist($setNo,database)
-        set query $hist($setNo,query)
-    }
-    if {[catch [list $zz failback fail-response]]} {
-        ir $zz
-    }
+    set zz z39$tno
+    set host $hist($setNo,$tno,host)
+    set idAuth $hist($setNo,$tno,idAuthentication)
+    set database $hist($setNo,$tno,database)
+    set query $hist($setNo,$tno,query)
+    catch {set docId $hist($setNo,$tno,queryId)}
+
+    mkAssoc $zz $host
     if {[catch [list set oldHost [$zz connect]]]} {
         set oldHost ""
     }
     $zz callback ok-response
     $zz failback fail-response
-    if {$oldHost != $host} {
+    set thisHost [splitHostSpec $host]
+    if {[string compare $oldHost $thisHost]} {
         catch [list $zz disconnect]
 
         set sessionWait 0
-        if {[catch [list $zz connect $host]]} {
-            displayError "Cannot connect to target" $host
+        if {[catch [list $zz connect $thisHost]]} {
+            displayError "Cannot connect to target" $thisHost
             return 0
         } elseif {$sessionWait == 0} {
-            if {[catch {zwait sessionWait 300}]} {
+            if {[catch {egw_wait sessionWait 300}]} {
                $zz disconnect
-                displayError "Cannot connect to target" $host
+                displayError "Cannot connect to target" $thisHost
                 return 0
             }
             if {$sessionWait != 1} {
-                displayError "Cannot connect to target" $host
+                displayError "Cannot connect to target" $thisHost
                 return 0
             }
         }
         $zz idAuthentication $idAuth
         set sessionWait 0
         if {[catch {$zz init}]} {
-            displayError "Cannot initialize target" $host
+            displayError "Cannot initialize target" $thisHost
            $zz disconnect
             return 0
         }
-        if {[catch {zwait sessionWait 60}]} {
-            displayError "Cannot initialize target" $host
+        if {$sessionWait == 0 && [catch {egw_wait sessionWait 60}]} {
+            displayError "Cannot initialize target" $thisHost
            $zz disconnect
             return 0
         }
         if {$sessionWait != "1"} {
-            displayError "Cannot initialize target" $host
+            displayError "Cannot initialize target" $thisHost
            $zz disconnect
             return 0
         }
         if {![$zz initResult]} {
             set u [$zz userInformationField]
             $zz disconnect
-            displayError "Cannot initialize target $host" $u
+            displayError "Cannot initialize target $thisHost" $u
             return 0
         }
-    } else {
-        if {[info exists hist($setNo,hits)] && \
-                ![catch [list $zz.$setNo smallSetUpperBound 0]]} {
+    } elseif {![catch  [list $zz.$setNo smallSetUpperBound 0]]} {
+        if {[info exists hist($setNo,$tno,hits)]} {
             return 1
         }
-        
     }
-    ir-set $zz.$setNo $zz
     
+    if {![string compare [lindex $targets($host) 1] WAIS]} {
+        wais-set $zz.$setNo $zz
+    } else {
+        ir-set $zz.$setNo $zz
+        $zz.$setNo preferredRecordSyntax [lindex $targets($host) 1]
+        egw_log debug "set syntax to [lindex $targets($host) 1]"
+    }
     if {![lindex $targets($host) 5]} {
         set elements {}
     }
@@ -704,11 +972,9 @@ proc z39search {setNo piggy tno elements} {
     $zz.$setNo mediumSetElementSetNames $elements
     $zz.$setNo recordElements $elements
 
-    wlog debug "database=$database"
+    egw_log debug "database=$database"
     eval $zz.$setNo databaseNames $database
 
-    $zz.$setNo preferredRecordSyntax USMARC
-
     $zz callback [list search-response $zz.$setNo]
     if {$piggy} {
         $zz.$setNo largeSetLowerBound 999999
@@ -720,10 +986,16 @@ proc z39search {setNo piggy tno elements} {
         $zz.$setNo mediumSetPresentNumber 0
     }
     set sessionWait 0
-    $zz.$setNo search $query
+    egw_log debug "search: $query"
 
-    if {[catch {zwait sessionWait 600}]} {
-        wlog debug "timeout/cancel in search"
+    if {[info exists docId]} {
+        $zz.$setNo search $query $docId
+    } else {
+        $zz.$setNo search $query
+    }
+
+    if {!$sessionWait && [catch {egw_wait sessionWait 60}]} {
+        egw_log debug "timeout/cancel in search"
         displayError "Timeout in search" {}
         html "</body></html>\n"
         $zz disconnect
@@ -738,7 +1010,7 @@ proc z39search {setNo piggy tno elements} {
     if {$sessionWait != 1} {
        return 0
     }
-    set hist($setNo,hits) [$zz.$setNo resultCount]
+    set hist($setNo,$tno,hits) [$zz.$setNo resultCount]
     return 1
 }
 
@@ -746,17 +1018,22 @@ proc init-m-response {i} {
     global zstatus
     global zleft
 
-    wlog debug "init-m-response"
+    egw_log debug "init-m-response"
 
-    set zstatus($i) 1
     incr zleft -1
+    if {![z39$i initResult]} {
+        set zstatus($i) -1
+        z39$i disconnect
+        return
+    }
+    set zstatus($i) 1
 }
 
 proc connect-m-response {i} {
     global zstatus
     global zleft
 
-    wlog debug "connect-m-response"
+    egw_log debug "connect-m-response"
     z39$i callback [list init-m-response $i]
     if {[catch {z39$i init}]} {
         set zstatus($i) -1
@@ -768,36 +1045,72 @@ proc fail-m-response {i} {
     global zstatus
     global zleft
     
-    wlog debug "fail-m-response"
+    egw_log debug "fail-m-response"
     set zstatus($i) -1
     incr zleft -1
 }
 
-proc search-m-response {setNo i} {
+proc search-m-response {setNo i start number} {
     global zleft
     global zstatus
+    global hist
 
-    incr zleft -1
-    set zstatus($i) 2
+    egw_log debug "search-m-response"
+    set status [z39$i.$setNo responseStatus]
+    egw_log debug "search-m-response1"
+    if {[lindex $status 0] == "OK"} {
+        set nor 0
+    } elseif {[lindex $status 0] == "DBOSD"} {
+        set nor [z39$i.$setNo numberOfRecordsReturned]
+    } else {
+        egw_log debug "search-m-response2"
+        incr zleft -1
+        set zstatus($i) 2
+        return
+    }
+    set hist($setNo,$i,hits) [z39$i.$setNo resultCount]
+    egw_log debug "search-m-response3"
+    set hist($setNo,$i,offset) [expr $start + $nor -1]
+    if {[expr $nor + $start] > [z39$i.$setNo resultCount]} {
+        egw_log debug "search-m-response4"
+        incr zleft -1
+        set zstatus($i) 2
+        return
+    }
+    egw_log debug "search-m-response5"
+    if {$nor >= $number} {
+        egw_log debug "search-m-response6 nor=$nor number=$number"
+        incr zleft -1
+        set zstatus($i) 2
+        return
+    }
+    egw_log debug "search-m-response7"
+    set start [expr $start + $nor]
+    set number [expr $number - $nor]
+    if {[expr $start + $number - 1] > [z39$i.$setNo resultCount]} {
+        set number [expr [z39$i.$setNo resultCount] - $start + 1]
+    }
+    z39$i callback [list search-m-response $setNo $i $start $number]
+    egw_log debug "mpresent start=$number number=$number"
+    z39$i.$setNo present $start $number
 }
 
-proc z39msearch {setNo piggy elements} {
+proc z39msearch {setNo elements start number cache} {
     global zleft
     global zstatus
     global hist
     global targets
+    global debug
 
     set not $hist($setNo,0,host)
 
+    egw_log debug "z39msearch start=$start number=$number elements=$elements"
     for {set i 1} {$i <= $not} {incr i} {
         set host $hist($setNo,$i,host)
-        if {[catch {z39 failback fail-response}]} {
-            ir z39$i
-        }
-        if {[catch {set oldHost [z39$i connect]}]} {
-            set oldHost ""
-        }
-        if {$oldHost != $host} {
+        mkAssoc z39$i $host
+        set oldHost [z39$i connect]
+        set thisHost [splitHostSpec $host]
+        if {[string compare $oldHost $thisHost]} {
             catch {z39$i disconnect}
         }
         z39$i callback [list connect-m-response $i]
@@ -807,29 +1120,49 @@ proc z39msearch {setNo piggy elements} {
     for {set i 1} {$i <= $not} {incr i} {
         set oldHost [z39$i connect]
         set host $hist($setNo,$i,host)
-        if {$oldHost == $host} {
-            set zstatus($i) 1
+        set thisHost [splitHostSpec $host]
+        if {![string compare $oldHost $thisHost]} {
             continue
         }
+        egw_log debug "old=$oldHost this=$thisHost"
         z39$i idAuthentication $hist($setNo,$i,idAuthentication)
-        html "Connecting to target " $host " <br>\n"
+        html "Connecting to target " $thisHost " <br>\n"
         set zstatus($i) -1
-        if {![catch {z39$i connect $host}]} {
+        if {![catch {z39$i connect $thisHost}]} {
             incr zleft
         } 
     }
     while {$zleft > 0} {
-        wlog debug "Waiting for init response"
-        if {[catch {zwait zleft 10}]} {
+        egw_log debug "Waiting for init response"
+        if {[catch {egw_wait zleft 20}]} {
             break
         }
     }
     set zleft 0
     for {set i 1} {$i <= $not} {incr i} {
-        html "host " $hist($setNo,$i,host) ": "
-        if {$zstatus($i) >= 1} {
-            html "ok <br>\n"
-            ir-set z39$i.$setNo z39$i
+        set host $hist($setNo,$i,host)
+        if {$debug} {
+            html "host " [splitHostSpec $host] ": "
+        }
+        egw_log debug "i=$i zstatus=$zstatus($i)"
+        if {$zstatus($i) < 1} {
+            if {$debug} {
+                html "fail<br>\n"
+            }
+            continue
+        }
+        if {[catch [list z39$i.$setNo preferredRecordSyntax]]} {
+            if {$debug} {
+                html "ok<br>\n"
+            }
+
+            if {![string compare [lindex $targets($host) 1] WAIS]} {
+                wais-set z39$i.$setNo z39$i
+            } else {
+                ir-set z39$i.$setNo z39$i
+                z39$i.$setNo preferredRecordSyntax [lindex $targets($host) 1]
+                egw_log debug "set syntax to [lindex $targets($host) 1]"
+            }
             set hist($setNo,$i,offset) 0
             eval z39$i.$setNo databaseNames $hist($setNo,$i,database)
 
@@ -840,38 +1173,84 @@ proc z39msearch {setNo piggy elements} {
             }
             z39$i.$setNo smallSetElementSetNames $thisElements
             z39$i.$setNo mediumSetElementSetNames $thisElements
+            z39$i.$setNo elementSetNames $thisElements
             z39$i.$setNo recordElements $thisElements
 
-            z39$i.$setNo preferredRecordSyntax USMARC
-            z39$i callback [list search-m-response $setNo $i]
+            z39$i callback [list search-m-response $setNo $i $start $number]
 
-            if {$piggy} {
+            if {$start == 1} {
                 z39$i.$setNo largeSetLowerBound 999999
                 z39$i.$setNo smallSetUpperBound 0
-                z39$i.$setNo mediumSetPresentNumber $hist($setNo,maxPresent)
+                z39$i.$setNo mediumSetPresentNumber $number
             } else {
                 z39$i.$setNo largeSetLowerBound 2
                 z39$i.$setNo smallSetUpperBound 0
                 z39$i.$setNo mediumSetPresentNumber 0
             }
             set zstatus($i) 1
-            wlog debug "search " $hist($setNo,$i,query)
-            z39$i.$setNo search $hist($setNo,$i,query)
             incr zleft
+            egw_log debug "msearch host=" $hist($setNo,$i,host)
+            egw_log debug "setNo=$setNo query=" $hist($setNo,$i,query) "="
+            if {[catch {z39$i.$setNo search $hist($setNo,$i,query)}]} {
+                set zstatus($i) -1
+                incr zleft -1
+            }
+        } elseif {[z39$i.$setNo resultCount] >= $start} {
+            if {[expr $start + $number - 1] > [z39$i.$setNo resultCount]} {
+                set tnumber [expr [z39$i.$setNo resultCount] - $start + 1]
+            } else {
+                set tnumber $number
+            }
+            if {![lindex $targets($hist($setNo,$i,host)) 5]} {
+                set thisElements {}
+            } else {
+                set thisElements $elements
+            }
+            z39$i.$setNo smallSetElementSetNames $thisElements
+            z39$i.$setNo mediumSetElementSetNames $thisElements
+            z39$i.$setNo elementSetNames $thisElements
+            z39$i.$setNo recordElements $thisElements
+
+            for {set n 0} {$n < $tnumber} {incr n} {
+                if {[z39$i.$setNo recordType [expr $start + $n]] == ""} {
+                    if {$n > 0} {
+                        egw_log debug "failed on $n"
+                    }
+                    if {$debug} {
+                        html "no record at #" [expr $start + $n]
+                        html " el=-" $thisElements "-"
+                    }
+                    break
+                }
+            }
+            if {$n == $tnumber} {
+                if {$debug} {
+                    html "cached<br>\n"
+                }
+                continue
+            }
+            
+            html "present<br>\n"
+            z39$i callback [list search-m-response $setNo $i $start $tnumber]
+            incr zleft
+            egw_log debug "mpresent start=$start number=$tnumber"
+            z39$i.$setNo present $start $tnumber
         } else {
-            html "fail <br>\n"
+            if {$debug} {
+                html "ok<br>\n"
+            }
         }
     }
     while {$zleft > 0} {
-        wlog debug "Waiting for search response"
-        if {[catch {zwait zleft 30}]} {
+        egw_log debug "Waiting for search/present response"
+        if {[catch {egw_wait zleft 60}]} {
             break
         }
     }
     for {set i 1} {$i <= $not} {incr i} {
         if {$zstatus($i) != 2} continue
         set status [z39$i.$setNo responseStatus]
-        if {[lindex $status 0] != "NSD"} {
+        if {0 && [lindex $status 0] != "NSD"} {
             set hist($setNo,$i,offset) [z39$i.$setNo numberOfRecordsReturned]
         }
     }
@@ -882,13 +1261,8 @@ proc z39present {setNo tno setOffset setMax dfunc elements} {
     global sessionWait
     global targets
 
-    if {$tno > 0} {
-        set zz z39$tno
-        set host $hist($setNo,$tno,host)
-    } else {
-        set zz z39
-        set host $hist($setNo,host)
-    }
+    set zz z39$tno
+    set host $hist($setNo,$tno,host)
 
     if {![lindex $targets($host) 5]} {
         set elements {}
@@ -902,15 +1276,15 @@ proc z39present {setNo tno setOffset setMax dfunc elements} {
 
     while {$setMax > 0 && $toGet > 0} {
         for {set got 0} {$got < $toGet} {incr got} {
-            if {[$zz.$setNo type [expr $setOffset + $got]] == ""} {
+            if {[$zz.$setNo recordType [expr $setOffset + $got]] == ""} {
                 break
             }
         }
         if {$got < $toGet} {
             set sessionWait 0
             $zz.$setNo present $setOffset $toGet
-            if {[catch {zwait sessionWait 300}]} {
-                wlog debug "timeout/cancel in present"
+            if {[catch {egw_wait sessionWait 300}]} {
+                egw_log debug "timeout/cancel in present"
                $zz disconnect
                 break
            }
@@ -925,105 +1299,412 @@ proc z39present {setNo tno setOffset setMax dfunc elements} {
                 break
             }
         }
-        display-rec $setOffset [expr $got + $setOffset - 1] $dfunc $tno
+        display-rec $setOffset [expr $got + $setOffset - 1] $dfunc $setNo $tno
         set setOffset [expr $got + $setOffset]
         set toGet [expr 1 + $setMax - $setOffset]
-        wflush
+        egw_flush
     }
 }
 
+proc buttons-result-set-s {setNo targetNo setMax startPos after} {
+    global sessionId
+    global useIcons
+    global env
+    global hist
+
+    set zz z39$targetNo
+    html "<p>\n"
+    button-main
+    if {$setMax > 0 && $setMax < [$zz.$setNo resultCount]} {
+        if {!$useIcons} {
+            html "\n | "
+        }
+        html {<a href="http:} $env(SCRIPT_NAME)
+        html / $sessionId {/search.egw/} $setNo + $targetNo + 
+        html [expr $setMax + 1] + [expr $setMax + $hist($setNo,maxPresent)]
+        if {$useIcons} {
+            html {"><img src="/egwgif/button-next-records.gif" }
+            html {alt="Next Records" border=0></a>}
+        } else {
+            html {">Next Records</a>}
+        }
+    }
+    if {$setMax > 0 && $startPos != "" && $startPos != "1"} {
+        if {!$useIcons} {
+            html "\n | "
+        }
+        html {<a href="http:} $env(SCRIPT_NAME)
+        html / $sessionId {/search.egw/} $setNo + $targetNo
+        html + [expr $startPos - $hist($setNo,maxPresent)]
+        html + [expr $startPos - 1]
+        if {$useIcons} {
+            html {"><img src="/egwgif/button-previous-records.gif" }
+           html {alt="Previous Records" border=0></a>}
+        } else {
+            html {">Previous Records</a>} 
+        }
+    }
+    if {$targetNo > 0} {
+        button-result-set $setNo $targetNo
+    }
+    button-new-query $setNo
+    button-new-target
+    button-view-history
+
+    html "<p>\n"
+}
+
+proc score-sort {l r} {
+    return [expr [lindex $r 0] - [lindex $l 0]]
+}
+
+proc display-result-set-m-score {setNo} {
+    global hist
+    global useIcons
+    global zstatus
+    global targets
+
+    set not $hist($setNo,0,host)
+    for {set i 1} {$i <= $not} {incr i} {
+        if {$zstatus($i) != 2} continue
+        set status [z39$i.$setNo responseStatus]
+        if {[lindex $status 0] != "DBOSD"} continue        
+        set nor $hist($setNo,$i,offset)
+        for {set j 1} {$j <= $nor} {incr j} {
+            if {![string compare [z39$i.$setNo recordType $j] WAIS]} {
+                set score [z39$i.$setNo getWAIS $j score]
+            } elseif {![string compare [z39$i.$setNo recordType $j] USmarc]} {
+                set score [z39$i.$setNo getMarc $j field 999 * r]
+                if {[scan $score %d score] != 1} {
+                    set score 10
+                }
+            } else {
+                set score 10
+            }
+            if {$score > 0} {
+                lappend scoreArray [list $score $i $j]
+            }
+        }
+    }
+    if {![info exists scoreArray]} {
+        html "<br><h3>Search produced no result</h3><br>\n"
+    } else {
+        html "<ul>\n"
+        set scoreSorted [lsort -command score-sort $scoreArray]
+        foreach r $scoreSorted {
+            set i [lindex $r 1]
+            set j [lindex $r 2]
+            display-$hist($setNo,format) z39$i.$setNo $j $setNo $i
+        }
+        html "<br></ul>\n"
+    }
+    for {set i 1} {$i <= $not} {incr i} {
+        if {$zstatus($i) != 2} continue
+        set status [z39$i.$setNo responseStatus]
+        if {[lindex $status 0] == "NSD"} {
+            z39$i.$setNo nextResultSetPosition 0
+            set code [lindex $status 1]
+            set msg [lindex $status 2]
+            set addinfo [lindex $status 3]
+            html {<dt>} [lindex $targets($hist($setNo,$i,host)) 0] 
+            html "<dd>Error: $msg: $addinfo (code $code)<br>\n"
+        }
+    }
+    html "\n<br>"
+}
+
+proc display-result-set-m-server {setNo} {
+    global hist
+    global useIcons
+    global zstatus
+    global targets
+    global env
+    global sessionId
+
+    set not $hist($setNo,0,host)
+    html "<dl>\n"
+    for {set i 1} {$i <= $not} {incr i} {
+        if {$zstatus($i) != 2} continue
+        set status [z39$i.$setNo responseStatus]
+        if {[lindex $status 0] == "NSD"} {
+            html "<dt><h3>" [lindex $targets($hist($setNo,$i,host)) 0] ": "
+            z39$i.$setNo nextResultSetPosition 0
+            set code [lindex $status 1]
+            set msg [lindex $status 2]
+            set addinfo [lindex $status 3]
+            html "Error</h3>\n<dd>NSD$code: $msg: $addinfo"
+        } else {
+            html {<dt><a href="http:} $env(SCRIPT_NAME)
+            html / $sessionId {/search.egw/} $setNo + $i + 1
+            html + $hist($setNo,maxPresent) {">}
+            html "<h3>" [lindex $targets($hist($setNo,$i,host)) 0] "</a>: "
+            set r [z39$i.$setNo resultCount]
+            html "$r hits</h3>\n<dd>\n"
+            
+            if {$hist($setNo,$i,offset) > $hist($setNo,maxPresent)} {
+                set nor $hist($setNo,maxPresent)
+            } else {
+                set nor $hist($setNo,$i,offset)
+            }
+            display-rec 1 $nor display-$hist($setNo,format) $setNo $i
+        }
+        html "\n"
+    }
+    html "</dl>\n"
+}
+
+proc display-result-set-m {setNo} {
+    global hist
+    global useIcons
+    global zstatus
+    global targets
+
+    egw_log debug "sort=$hist($setNo,sort)"
+    switch $hist($setNo,sort) {
+        score {
+            display-result-set-m-score $setNo
+        }
+        default {
+            display-result-set-m-server $setNo
+        }
+    }
+}
+
+proc display-result-set-s {setNo targetNo startPos endPos} {
+    global hist
+    global useIcons
+
+    set zz z39$targetNo
+    set host $hist($setNo,$targetNo,host)
+    set idAuth $hist($setNo,$targetNo,idAuthentication)
+    set database $hist($setNo,$targetNo,database)
+    set query $hist($setNo,$targetNo,query)
+
+    set useIcons 1
+
+    if {$startPos == ""} {
+        if {[z39search $setNo 1 $targetNo B] != "1"} {
+            return
+        }
+        set r [$zz.$setNo resultCount]
+
+        set setMax [$zz.$setNo resultCount]
+        if {$setMax > $hist($setNo,maxPresent)} {
+            set setMax $hist($setNo,maxPresent)
+        }
+        buttons-result-set-s $setNo $targetNo $setMax $startPos 0
+
+        set setOffset [$zz.$setNo numberOfRecordsReturned]
+        if {$setMax > 0} {
+            html {<h3> Records 1-} $setMax " out of $r</h3>\n"
+        } else {
+            html "<h3> No hits</h3>\n"
+        }
+        egw_flush
+        html "<ul>\n"
+        display-rec 1 $setMax display-brief $setNo $targetNo
+        incr setOffset
+
+    } else {
+        if {[z39search $setNo 0 $targetNo B] != "1"} {
+            return 
+        }
+        set r [$zz.$setNo resultCount]
+        set setOffset $startPos
+        set setMax [$zz.$setNo resultCount]
+        if {$setMax > $endPos} {
+            set setMax $endPos
+        }
+        buttons-result-set-s $setNo $targetNo $setMax $startPos 0
+        if {$setMax > 0} {
+            html {<h3> Records } $startPos {-} $setMax " out of $r</h3>\n"
+        } else {
+            html "<h3> No hits</h3>\n"
+        }
+        egw_flush
+        html "<ul>\n"
+    }
+    if {$setMax > 0} {
+        z39present $setNo $targetNo $setOffset $setMax display-brief B
+    }
+    html "</ul>\n"
+    set useIcons 0
+    buttons-result-set-s $setNo $targetNo $setMax $startPos 1
+}
+
 proc z39history {} {
     global nextSetNo
     global hist
     global env
     global sessionId
     global targets
+    global html3
+    global scriptQuery
 
     if {![info exists nextSetNo]} {
         return
     }
-    html "<h2>History</h2><dl><br>\n"
+    html "<h2>History</h2><br>\n"
+    if {$html3} {
+        html {<table width=500 border=1><tr>}
+        html {<td align=center><b>Target</b>}
+        html {<td align=center><b>Database</b>}
+        html {<td align=center><b>Hits</b>}
+        html {<td align=center><b>Query</b>}
+        html {<tr>} "\n"
+    } else {
+        html {<dl>} "\n"
+    }
     for {set setNo 1} {$setNo < $nextSetNo} {incr setNo} {
-        if {$hist($setNo,scan) > 0} continue
-        set host $hist($setNo,host)
-        html {<dt> } [lindex $targets($host) 0]
-        if {[llength [lindex $targets($host) 1]] > 1} {
-            html ": "
-            foreach b $hist($setNo,database) {
-                html " $b"
-            }
+        if {[info exists hist($setNo,scan)]} {
+            if {$hist($setNo,scan) > 0} continue
         }
-        html {. }
-
-        if {[info exists hist($setNo,hits)]} {
-            html { <a href="http:} $env(SCRIPT_NAME)
-            html / $sessionId {/search.egw/} $setNo + 1
-            html + $hist($setNo,maxPresent)
-            html {">Result</a>: } $hist($setNo,hits) { hits.}
+        if {[info exists hist($setNo,1,host)]} {
+            set start 1
+            set end $hist($setNo,0,host)
         } else {
-            html {Search failed.}
+            set start 0
+            set end 0
         }
-        html "<dd>\n"
-        html { <a href="http:} $env(SCRIPT_NAME)
-        html / $sessionId {/query.egw/} $host + $setNo 
-        html {">Query</a>: }
-        set op {}
-        for {set i 1} {$i <= 3} {incr i} {
-            if {[string length $hist($setNo,form,entry$i)] > 0} {
-                html " <b>" [join $op " "] "</b> "
-                html $hist($setNo,form,menu$i) "=" $hist($setNo,form,entry$i)
-                set op $hist($setNo,form,logic$i)
+        for {set i $start} {$i <= $end} {incr i} {
+            if {$html3} {
+                html {<td align=left>}
+            } else {
+                html {<dt> }
+            }
+            set host $hist($setNo,$i,host)
+            html [lindex $targets($host) 0]
+            if {$html3} {
+                html {<td align=left>} [join $hist($setNo,$i,database)]
+            } else {
+                if {[llength [lindex $targets($host) 1]] > 1} {
+                    html ": "
+                    foreach b $hist($setNo,$i,database) {
+                        html " $b"
+                    }
+                }
+                html {. }
+            }
+            if {$html3} {
+                html {<td align=right>}
+            }
+            if {[info exists hist($setNo,$i,hits)]} {
+                html { <a href="http:} $env(SCRIPT_NAME)
+                html / $sessionId {/search.egw/} $setNo + $i + 1
+                html + $hist($setNo,maxPresent)
+                html {">} $hist($setNo,$i,hits) {</a>}
+            } else {
+                if {$html3} {
+                    html {Failed}
+                } else {
+                    html {Search failed.}
+                }
+            }
+            if {$html3} {
+                html {<td align=left>}
+            } else {
+                html "<dd>\n"
+            }
+            html { <a href="http:} $env(SCRIPT_NAME)
+            html / $sessionId / $scriptQuery {;/} $setNo + $host
+            if {$html3} {
+                html {">}
+            } else {
+                html {">Query</a>: }
+            }
+            set op {}
+            for {set j 1} {$j <= 3} {incr j} {
+                if {[string length $hist($setNo,form,entry$j)] > 0} {
+                    html " <b>" [join $op " "] "</b> "
+                set pre [join $hist($setNo,form,menu$j)]
+                    if {[string length $pre] > 0} {
+                        html $pre "="
+                    }
+                    html $hist($setNo,form,entry$j)
+                    set op $hist($setNo,form,logic$j)
+                }
+            }
+            if {$html3} {
+                html {</a><tr>} "\n"
             }
         }
     }
-    html "</dl>\n"
+    if {$html3} {
+        html {</table><p>}
+    } else {
+        html {</dl>}
+    }
+    html "\n"
 }
 
 proc displayError {msga msgb} {
     html "<p><center>\n"
     html {<img src="/egwgif/noway.gif" alt="Error">}
     html "<h2>" $msga "</h2>\n"
-    if {$msgb != ""} {
+    if {[string length $msgb] > 0} {
         html "<h3>" $msgb "</h3>\n"
     }
     html "</center><p>\n"
 }
 
-proc button-europagate {} {
+proc button-main {} {
     global useIcons
+    html {<a href="http://europagate.dtv.dk/">}
     if {$useIcons} {
         html {<img src="/egwgif/button-egw.gif" alt="Europagate" border=0></a>}
     } else {
-        html {Europagate | }
+        html {Europagate</a>}
+    }
+}
+
+proc button-define-target {} {
+    global useIcons
+    global env
+    global sessionId
+
+    if {!$useIcons} {
+        html "\n | "
+    }
+    html {<a href="http:} $env(SCRIPT_NAME)
+    html / $sessionId {/tform.egw}
+    if {$useIcons} {
+        html {"><img src="/egwgif/button-define-target.gif" }
+       html {alt="Define Target" border=0></a>}
+    } else {
+        html {">Define Target</a>}
     }
 }
 
-proc button-new-target {more} {
+proc button-new-target {} {
     global useIcons
     global env
     global sessionId
+    global scriptTarget
 
+    if {[string length $scriptTarget] == 0} return
+
+    if {!$useIcons} {
+        html "\n | "
+    }
     html {<a href="http:} $env(SCRIPT_NAME)
-    html / $sessionId {/targets.egw}
+    html / $sessionId / $scriptTarget
     if {$useIcons} {
         html {"><img src="/egwgif/button-new-target.gif" }
        html {alt="New Target" border=0></a>}
     } else {
         html {">New Target</a>}
-        if {$more} {
-            html " | \n"
-        } else {
-            html "\n"
-        }
     }
 }
 
-proc button-view-history {more} {
+proc button-view-history {} {
     global useIcons
     global env
     global sessionId
     global nextSetNo
 
+    if {!$useIcons} {
+        html "\n | "
+    }
     html {<a href="http:} $env(SCRIPT_NAME)
     html / $sessionId {/history.egw;}
     catch { html "/" $nextSetNo}
@@ -1032,60 +1713,181 @@ proc button-view-history {more} {
         html {border=0></a>}
     } else {
         html {">View History</a>}
-        if {$more} {
-            html " | \n"
-        } else {
-            html "\n"
-        }
     }
 }
 
-proc button-new-query {more setNo} {
+proc button-new-query {setNo} {
     global useIcons
     global env
     global sessionId
     global hist
+    global scriptQuery
 
+    if {!$useIcons} {
+        html "\n | "
+    }
     html {<a href="http:} $env(SCRIPT_NAME)
-    html / $sessionId {/query.egw/} $hist($setNo,host) + $setNo {">}
+    html / $sessionId / $scriptQuery {;/} $setNo + $hist($setNo,0,host) {">}
+
     if {$useIcons} {
         html {<img src="/egwgif/button-new-query.gif" }
        html {alt="New Query" border=0></a>}
     } else {
         html {New Query</a>}
-        if {$more} {
-            html " | \n"
-        } else {
-            html "\n"
-        }
     }
 }
 
-proc button-scan-window {more setNo} {
+proc button-result-set {setNo tno} {
+    global useIcons
+    global env
+    global sessionId
+    global hist
+
+    if {!$useIcons} {
+        html "\n | "
+    }
+    html {<a href="http:} $env(SCRIPT_NAME) / $sessionId 
+    if {$tno > 0} {
+        html {/msearch.egw/} $setNo
+    } else {
+        html {/search.egw/} $setNo + $tno
+    }
+    html + 1 + $hist($setNo,maxPresent)
+    if {$useIcons} {
+        html {"><img src="/egwgif/button-result-set.gif" }
+       html {alt="Result Set" border=0></a>}
+    } else {
+        html {">Result Set</a>}
+    }
+}
+
+proc button-scan-window {setNo} {
     global useIcons
     global env
     global sessionId
     global hist
 
+    if {!$useIcons} {
+        html "\n | "
+    }
+    set targetNo 0
     html {<a href="http:} $env(SCRIPT_NAME)
-    html / $sessionId {/search.egw/} $setNo + {scan} {">}
+    html / $sessionId {/search.egw/} $setNo + $targetNo + {scan} {">}
     if {$useIcons} {
         html {<img src="/egwgif/button-scan-window.gif" }
        html {alt="Scan" border=0></a>}
     } else {
         html {Scan</a>}
-        if {$more} {
-            html " | \n"
-        } else {
-            html "\n"
-        }
     }
 }
 
 proc maintenance {} {
     html {<hr>This page is maintained by }
     html {<a href="mailto:pwh@dtv.dk"> Peter Wad Hansen </a>.}
-    html {Last modified 9. january 1996. <br>}
+    html {Last modified 29. january 1996. <br>}
     html {<em> This and the following pages are under construction and }
     html {will continue to be so until the end of January 1996.</em>}
 }
+
+proc splitHostSpec {host} {
+    set i [string first / $host]
+    if {$i > 1} {
+        incr i -1
+        return [string range $host 0 $i]
+    }
+    return $host
+}
+
+proc splitDatabaseSpec {host} {
+    set i [string first / $host]
+    if {$i > 1} {
+        incr i
+        regsub -all -- - [string range $host $i end] { } res
+        return $res
+    }
+    regsub -all -- - $host {} res
+    return $res
+}
+
+proc mergeHostSpec {host databases} {
+    return ${host}/[join $databases -]
+}
+
+proc mkAssoc {assoc host} {
+    global targets
+
+    if {[catch {$assoc failback fail-response}]} {
+        if {![string compare [lindex $targets($host) 1] WAIS]} {
+            wais $assoc
+        } else {
+            ir $assoc
+        }
+    } else {
+        if {![string compare [lindex $targets($host) 1] WAIS]} {
+            if {[$assoc comstack] == "wais"} return
+            wais $assoc
+        } else {
+            if {[$assoc comstack] == "tcpip"} return
+            ir $assoc
+        }
+    }
+}
+
+proc serverList {headlineProc targetProc} {
+    global targets
+    global groupsDescription
+   
+    proc targetsCmp {l r} {
+        global targets
+        return [string compare [string tolower [lindex $targets($l) 0]] \
+                               [string tolower [lindex $targets($r) 0]]]
+    }
+    proc groupCmp {l r} {
+        global groupsOrder
+        if {[catch {set lo $groupsOrder($l)}]} {
+            set lo 10
+        }
+        if {[catch {set ro $groupsOrder($r)}]} {
+            set ro 10
+        }
+        return [expr $lo - $ro]
+    }
+    
+    foreach tt [array names targets] {
+        lappend groupsTmp([lindex $targets($tt) 6]) $tt
+    }
+    set gts [lsort -command groupCmp [array names groupsTmp]]
+    foreach gt $gts {
+        if {[info exists groupsDescription($gt)]} {
+            eval $headlineProc [list $groupsDescription($gt)]
+        } else {
+            eval $headlineProc $gt
+        }
+        set tn [lsort -command targetsCmp $groupsTmp($gt)]
+        foreach t $tn {
+            eval $targetProc $t
+        }
+    }
+
+    rename targetsCmp {}
+}
+
+proc session-lost {} {
+    global useIcons
+
+    html {<head><title>WWW/Z39.50 Gateway: Session Expired</title></head>}
+    html \n {<body>}
+    set useIcons 1
+    button-main
+    html {<h1>Session Expired</h1>}
+    html {Your session has expired. Please reload the gateways' }
+    html {front page.<br><br>} \n
+    set useIcons 0
+    button-main
+    html {</body></html>}
+}
+
+if {[info exists utilExtension]} {
+    source $utilExtension
+}
+