7903fd4773e40b20457945f2129371a2cdc866e1
[egate.git] / www / z39util.tcl
1 #
2 # $Id: z39util.tcl,v 1.25 1996/01/24 16:59:29 adam Exp $
3 #
4 proc saveState {} {
5     uplevel #0 {
6     set f [open "tcl.state.${sessionId}" w]
7     foreach var [info globals] {
8         if {$var == "f"} continue
9         if {$var == "sessionId"} continue
10         if {$var == "errorInfo"} continue
11         if {[catch {set names [array names $var]}]} {
12             eval "set v \$${var}"
13             puts $f "set ${var} \{$v\}"
14         } else {
15             foreach n $names {
16                 eval "set v \$${var}(\$n)"
17                 puts $f "set ${var}($n) \{$v\}"
18             }
19             catch {
20                 eval "set v \$${var}"
21                 puts $f "set ${var} \{$v\}"
22             }
23         }
24     }
25     close $f
26     }
27 }
28
29 proc search-response {zz} {
30     global sessionWait
31
32     set status [$zz responseStatus]
33     if {[lindex $status 0] == "NSD"} {
34         $zz nextResultSetPosition 0
35         set code [lindex $status 1]
36         set msg [lindex $status 2]
37         set addinfo [lindex $status 3]
38         displayError "Diagnostic message" \
39                 "$msg: $addinfo<br>\n(error code $code)"
40         set sessionWait -2
41     } else {
42         set sessionWait 1
43     }
44 }
45
46 proc scan-response {zz} {
47     global sessionWait
48
49     set status [$zz scanStatus]
50     if {$status == 6} {
51         displayError "Scan fail" ""
52         set sessionWait -2
53     } else {
54         set sessionWait 1
55     }
56 }
57
58 proc ok-response {} {
59     global sessionWait
60     set sessionWait 1
61 }
62
63 proc fail-response {} {
64     global sessionWait
65     set sessionWait -1
66 }
67
68 proc display-brief {zset no tno} {
69     global env
70     global setNo
71     global sessionId
72
73
74     html {<li>}
75     set type [$zset type $no]
76     if {$type == "SD"} {
77         set err [lindex [$zset diag $no] 1]
78         set add [lindex [$zset diag $no] 2]
79         if {$add != {}} {
80             set add " :${add}"
81         }
82         html "${no} Error ${err}${add} <br>\n"
83         return
84     }
85     if {$type != "DB"} {
86         return
87     }
88     set rtype [$zset recordType $no]
89     if {$rtype == "SUTRS"} {
90         html [join [$zset getSutrs $no]]
91         html "<br>\n"
92         return
93     } 
94     if {![catch {
95         set author [$zset getMarc $no field 100 * a]
96         set corp [$zset getMarc $no field 110 * a]
97         set meet [$zset getMarc $no field 111 * a]
98         set title [$zset getMarc $no field 245 * a]
99         if {[llength $author] == 0} {
100             set cover [$zset getMarc $no field 245 * {[bc]}]
101         } else {
102             set cover [$zset getMarc $no field 245 * b]
103         }
104         set location [$zset getMarc $no field 260 * a] 
105         set publisher [$zset getMarc $no field 260 * b]
106         set year [$zset getMarc $no field 260 * c]
107     } ] } {
108         set p 0
109         foreach a $author {
110             if {$p} {
111                 html ", "
112             }
113             html $a
114             set p 1
115         }
116         foreach a $corp {
117             if {$p} {
118                 html ", "
119             }
120             html $a
121             set p 1
122         }
123         foreach a $meet {
124             if {$p} {
125                 html ", "
126             }
127             html $a
128             set p 1
129         }
130         if {$p} {
131             html ": "
132         }
133         html { <a href="http:} $env(SCRIPT_NAME) /
134         html $sessionId {/showfull.egw/} $setNo + $tno + $no + full {">}
135         set nope 1
136         foreach v $title {
137             html $v
138             set nope 0
139         }
140         if {$nope} {
141             html {No title} 
142         }
143         html {</a> }
144         foreach v $cover {
145             html $v
146         }
147         if {0} {
148             html {<br>}
149             foreach v $location {
150                 html " $v"
151             }
152             foreach v $publisher {
153                 html " $v"
154             }
155             foreach v $year {
156                 html " $v"
157             }
158         }
159     }
160     html "<br>\n"
161 }
162
163 proc display-raw {zset no tno} {
164     set type [$zset type $no]
165     if {$type == "SD"} {
166         set err [lindex [$zset diag $no] 1]
167         set add [lindex [$zset diag $no] 2]
168         if {$add != {}} {
169             set add " :${add}"
170         }
171         html "<h3>${no}</h3>\n"
172         html "Error ${err}${add} <br>\n"
173         return
174     }
175     if {$type != "DB"} {
176         return
177     }
178     set rtype [$zset recordType $no]
179     if {$rtype == "SUTRS"} {
180         html [join [$zset getSutrs $no]] "<br>\n"
181         return
182     } 
183     if {[catch {set r [$zset getMarc $no line * * *]}]} {
184         html "Unknown record type: $rtype <br>\n"
185         return
186     }
187     foreach line $r {
188         set tag [lindex $line 0]
189         set indicator [lindex $line 1]
190         set fields [lindex $line 2]
191         set l [string length $indicator]
192         html "<tt>$tag "
193         if {$l > 0} {
194             for {set i 0} {$i < $l} {incr i} {
195                 if {[string index $indicator $i] == " "} {
196                     html "-"
197                 } else {
198                     html [string index $tag $i]
199                 }
200             }
201         }
202         html "</tt>"
203         foreach field $fields {
204             set id [lindex $field 0]
205             set data [lindex $field 1]
206             if {$id != ""} {
207                 html " <b>\$$id</b> "
208             }
209             html $data
210         }
211         html "<br>\n"
212     }
213 }
214
215 proc put-marc-contents {cc} {
216     set ref ""
217     if {[string first :// $cc] > 0} {
218         foreach urltype {gopher http ftp mailto} {
219             if {[string first ${urltype}:// $cc] == 0} {
220                 set ref $urltype
221                 break
222             }
223         }
224     } 
225     if {$ref != ""} {
226         html {<a href="}
227     }
228     html $cc
229     if {$ref != ""} {
230         html {">} $cc {</a>}
231     }
232 }
233
234 proc dl-marc-field {zset no tag id la lb sep} {
235     set n 0
236     set c [$zset getMarc $no field $tag * $id]
237     set len [llength $c]
238     if {$len == 0} {
239         return 0
240     }
241     if {$len > 1 && "x$lb" != "x"} {
242         html "<dt><b>$lb</b>\n<dd>"
243     } else {
244         html "<dt><b>$la</b>\n<dd>"
245     }
246     foreach cc $c {
247         if {$n > 0} {
248             html $sep
249         }
250         put-marc-contents $cc
251         incr n
252     }
253     return $n
254 }
255
256 proc dd-marc-field {zset no tag id start stop} {
257     set n 0
258     set c [$zset getMarc $no field $tag * $id]
259     set len [llength $c]
260     if {$len == 0} {
261         return 0
262     }
263     foreach cc $c {
264         html $start
265         put-marc-contents $cc
266         html $stop
267         incr n
268     }
269     return $n
270 }
271
272 proc dl-marc-field-rec {zset no tag lead start stop startid sep} {
273     set n 0
274     set lines [$zset getMarc $no line $tag * *]
275     foreach line $lines {
276         foreach field [lindex $line 2] {
277             if {$n == 0} {
278                 html "<dt><b>$lead</b>"
279                 html "\n<dd>"
280             }
281             set id [lindex $field 0]
282             if {$id == $startid} {
283                 if {$n > 0} {
284                     html $stop
285                 }
286                 html $start
287                 incr n
288                 html [lindex $field 1]
289             } else {
290                 html $sep
291                 html [lindex $field 1]
292             }
293         }
294     }
295     if {$n > 0} {
296         html $stop
297     }
298 }
299
300 proc display-full {zset no tno} {
301     set type [$zset type $no]
302     if {$type == "SD"} {
303         set err [lindex [$zset diag $no] 1]
304         set add [lindex [$zset diag $no] 2]
305         if {$add != {}} {
306             set add " :${add}"
307         }
308         html "Error ${err}${add} <br>\n"
309         return
310     }
311     if {$type != "DB"} {
312         return
313     }
314     set rtype [$zset recordType $no]
315     if {$rtype == "SUTRS"} {
316         html [join [$zset getSutrs $no]] "<br>\n"
317         return
318     } 
319     if {[catch {set r [$zset getMarc $no line * * *]}]} {
320         html "Unknown record type: $rtype <br>\n"
321         return
322     }
323     html "<dl>\n"
324     set n [dl-marc-field $zset $no 700 a "Author" "Authors" "<br>\n"]
325     if {$n == 0} {
326         set n [dl-marc-field $zset $no 100 a "Author" "Authors" "<br>\n"]
327     }
328     set n [dl-marc-field $zset $no 710 a "Corporate Name" {} ", "]
329     if {$n == 0} {
330         set n [dl-marc-field $zset $no 110 a "Corporate Name" {} ", "]
331     }
332     set n [dl-marc-field $zset $no 711 a "Meeting Name" {} ", "]
333     if {$n > 0} {
334         dd-marc-field $zset $no 711 {[bndc]} " " ""
335     } else {
336         set n [dl-marc-field $zset $no 111 a "Meeting Name" {} ", "]
337         if {$n > 0} {
338             dd-marc-field $zset $no 111 {[bndc]} " " " "
339         }
340     } 
341     set n [dl-marc-field $zset $no 245 {a} "Title" {} " "]
342     if {$n > 0} {
343         dd-marc-field $zset $no 245 b "<em>" "</em>"
344         dd-marc-field $zset $no 245 c " " ""
345     } else {
346         dl-marc-field $zset $no 245 {[ab]} "Title" {} " "
347     }
348     dl-marc-field $zset $no 520 a "Abstract" {} ", "
349     dl-marc-field $zset $no 072 * "Subject code" "Subject codes" ", "
350     dl-marc-field $zset $no 650 * "Subject" {} ", "
351     dl-marc-field $zset $no 260 * "Publisher" {} " "
352     dl-marc-field $zset $no 300 * "Physical Description" {} " "
353
354     dl-marc-field-rec $zset $no 500 "Notes" "" "<br>\n" "a" ", "
355
356     dl-marc-field-rec $zset $no 510 "References" "" "<br>\n" "a" ", "
357
358     dl-marc-field-rec $zset $no 511 "Participant note" "" "<br>\n" "a" ", "
359
360     dl-marc-field $zset $no 513 a "Report type" {} ", "
361     dl-marc-field $zset $no 513 b "Period covered" {} ", "
362     dl-marc-field-rec $zset $no 515 "Numbering notes" "" "<br>\n" "a" ", "
363     dl-marc-field-rec $zset $no 516 "Data notes" "" "<br>\n" "a" ", "
364     dl-marc-field-rec $zset $no 518 "Date/time notes" "" "<br>\n" "a" ", "
365
366     dl-marc-field $zset $no 350 a "Price" {} ", "
367     dl-marc-field $zset $no 362 a "Dates of publication" {} ", "
368     dl-marc-field $zset $no 850 a "Holdings" {} ", "
369
370     dl-marc-field-rec $zset $no 270 "Contact name" "" "<br>\n" p ", "
371     if {0} {
372         set n [dl-marc-field $zset $no 270 p "Contact name" {} ", "]
373         if {$n > 0} {
374             html "\n<dl>\n"
375             
376             if {0} {
377                 dl-marc-field $zset $no 270 a "Street" {} ", "
378                 dl-marc-field $zset $no 270 b "City" {} ", "
379                 dl-marc-field $zset $no 270 c "State" {} ", "
380                 dl-marc-field $zset $no 270 e "Zip code" {} ", "
381                 dl-marc-field $zset $no 270 d "Country" {} ", "
382                 dl-marc-field $zset $no 270 m "Network address" {} ", "
383                 dl-marc-field $zset $no 301 a "Service hours" {} ", "
384                 dl-marc-field $zset $no 270 k "Phone" {} ", "
385                 dl-marc-field $zset $no 270 l "Fax" {} ", "
386             } else {
387                 dl-marc-field $zset $no 270 {[abcedmakl]} "Address" {} "<br>\n"
388             }
389             
390             html "\n</dl>\n"
391         }
392     }
393     dl-marc-field $zset $no 010 a "LC control number" {} ", "
394     dl-marc-field $zset $no 010 b "NUCMC control number" {} ", "
395     dl-marc-field $zset $no 020 a "ISBN" {} ", "
396     dl-marc-field $zset $no 022 a "ISSN" {} ", "
397     set url [$zset getMarc $no field 856 * u]
398     set sp [$zset getMarc $no field 856 * 3]
399     if {"x$url" != "x"} {
400         html "<dt><b>URL</b>\n"
401         if {"x$sp" == "x"} {
402             set sp $url
403         }
404         html {<dd><a href="} $url {">} [join $sp] "</a>\n"
405     }
406     dl-marc-field $zset $no 037 {[abc]} "Acquisition" {} "<br>\n"
407     dl-marc-field $zset $no 037 {[f6]} "Form of issue" {} "<br>\n"
408     dl-marc-field $zset $no 537 * "Source of data" {} "<br>\n"
409     dl-marc-field $zset $no 538 * "System details" {} "<br>\n"
410     dl-marc-field $zset $no 787 {[rstw6]} "Related information" {} "<br>\n"
411     dl-marc-field $zset $no 001 * "Local control number" {} ", "
412     html "</dl>\n"
413 }
414
415
416 proc display-rec {from to dfunc tno} {
417     global setNo
418
419     if {$tno > 0} {
420         while {$from <= $to} { 
421             eval "$dfunc z39${tno}.${setNo} $from $tno"
422             incr from
423         }
424     } else {
425         while {$from <= $to} { 
426             eval "$dfunc z39.${setNo} $from 0"
427             incr from
428         }
429     }
430 }
431
432 proc build-scan {t i} {
433     global targets
434
435     set term [egw_form entry$i]
436     if {$term != ""} {
437         set field [join [egw_form menu$i]]
438         set attr {Title}
439         foreach x [lindex $targets($t) 2] {
440             if {[lindex $x 0] == $field} {
441                 set attr [lindex $x 1]
442             }
443         }
444         return [list $term $attr]
445     }
446     return ""
447 }
448
449 proc build-query {t ilines} {
450     global targets
451
452     set op {}
453     set q {}
454     for {set i 1} {$i <= $ilines} {incr i} {
455         set term [join [egw_form entry$i]]
456         if {[string length $term] > 0} {
457             set field [join [egw_form menu$i]]
458             foreach x [lindex $targets($t) 2] {
459                 if {[lindex $x 0] == $field} {
460                     set attr [lindex $x 1]
461                 }
462             }
463             switch $op {
464             And
465                 { set q "@and $q ${attr} \"${term}\"" }
466             Or
467                 { set q "@or $q ${attr} \"${term}\"" }
468             {And not}
469                 { set q "@not $q ${attr} \"${term}\"" }
470             {}
471                 { set q "${attr} \"${term}\"" }
472             }
473             set op [egw_form logic$i]
474         }
475     }
476     return $q
477 }
478
479 proc z39scan {setNo scanNo tno scanLines scanPos cache} {
480     global hist
481     global sessionWait
482     global targets
483
484     if {$tno > 0} {
485         set zz z39$tno
486         set host $hist($setNo,$tno,host)
487         set idAuth $hist($setNo,$tno,idAuthentication)
488         set database $hist($setNo,$tno,database)
489         set scanAttr $hist($setNo,$tno,scanAttr)
490         set scanTerm $hist($setNo,$tno,$scanNo,scanTerm)
491     } else {
492         set zz z39
493         set host $hist($setNo,host)
494         set idAuth $hist($setNo,idAuthentication)
495         set database $hist($setNo,database)
496         set scanAttr $hist($setNo,scanAttr)
497         set scanTerm $hist($setNo,$scanNo,scanTerm)
498     }
499     if {[catch [list $zz failback fail-response]]} {
500         ir $zz
501     }
502     if {[catch [list set oldHost [$zz connect]]]} {
503         set oldHost ""
504     }
505     set zs $zz.s$scanNo.$setNo
506     $zz callback ok-response
507     $zz failback fail-response
508     set thisHost [splitHostSpec $host]
509     if {$oldHost != $thisHost} {
510         catch [list $zz disconnect]
511
512         set sessionWait 0
513         if {[catch [list $zz connect $thisHost]]} {
514             displayError "Cannot connect to target" $thisHost
515             return 0
516         } elseif {$sessionWait == 0} {
517             if {[catch {egw_wait sessionWait 300}]} {
518                 $zz disconnect
519                 displayError "Cannot connect to target" $thisHost
520                 return 0
521             }
522             if {$sessionWait != 1} {
523                 displayError "Cannot connect to target" $thisHost
524                 return 0
525             }
526         }
527         $zz idAuthentication $idAuth
528         set sessionWait 0
529         if {[catch {$zz init}]} {
530             displayError "Cannot initialize target" $thisHost
531             $zz disconnect
532             return 0
533         }
534         if {[catch {egw_wait sessionWait 60}]} {
535             displayError "Cannot initialize target" $thisHost
536             $zz disconnect
537             return 0
538         }
539         if {$sessionWait != "1"} {
540             displayError "Cannot initialize target" $thisHost
541             $zz disconnect
542             return 0
543         }
544         if {![$zz initResult]} {
545             set u [$zz userInformationField]
546             $zz disconnect
547             displayError "Cannot initialize target $thisHost" $u
548             return 0
549         }
550     } else {
551         if {$cache && ![catch [list $zs numberOfTermsRequested 5]]} {
552             return 1
553         }
554     }
555     eval $zz databaseNames $database
556
557     ir-scan $zs $zz
558
559     $zs numberOfTermsRequested $scanLines
560     $zs preferredPositionInResponse $scanPos
561
562     $zz callback [list scan-response $zs]
563
564     set sessionWait 0
565     $zs scan "${scanAttr} ${scanTerm}"
566
567     if {[catch {egw_wait sessionWait 60}]} {
568         egw_log debug "timeout/cancel in scan"
569         displayError "Timeout in scan" {}
570         html "</body></html>\n"
571         $zz disconnect
572         return 0
573     }
574     if {$sessionWait == -1} {
575         displayError "Scan fail" "Connection closed"
576         html "</body></html>\n"
577         $zz disconnect
578     }
579     if {$sessionWait != 1} {
580         return 0
581     }
582     return 1
583 }
584
585 proc display-scan {setNo scanNo tno} {
586     global hist
587     global targets
588     global env
589     global sessionId
590
591     if {$tno > 0} {
592         set zz z39$tno
593     } else {
594         set zz z39
595     }
596     set zs $zz.s$scanNo.$setNo
597     set m [$zs numberOfEntriesReturned]
598         
599     if {$m > 0} {
600         set t [lindex [$zs scanLine 0] 1]
601         if {$tno > 0} {
602             set hist($setNo,$tno,[expr $scanNo - 1],scanTerm) $t
603         } else {
604             set hist($setNo,[expr $scanNo - 1],scanTerm) $t
605         }
606         set t [lindex [$zs scanLine [expr $m - 1]] 1]
607         if {$tno > 0} {
608             set hist($setNo,$tno,[expr $scanNo + 1],scanTerm) $t
609         } else {
610             set hist($setNo,[expr $scanNo + 1],scanTerm) $t
611         }
612     }
613     for {set i 0} {$i < $m} {incr i} {
614         regsub -all {\ } [lindex [$zs scanLine $i] 1] + tterm
615         html {<a href="http:} $env(SCRIPT_NAME)
616         html / $sessionId {/query.egw/} $hist($setNo,host) + $setNo +
617         html $hist($setNo,scan) +  $tterm {">}
618         html [lindex [$zs scanLine $i] 1]
619         html {</a>: <em>}
620         html [lindex [$zs scanLine $i] 2]
621         html "</em><br>\n"
622     }
623 }
624
625 proc z39search {setNo piggy tno elements} {
626     global hist
627     global sessionWait
628     global targets
629
630     if {$tno > 0} {
631         set zz z39$tno
632         set host $hist($setNo,$tno,host)
633         set idAuth $hist($setNo,$tno,idAuthentication)
634         set database $hist($setNo,$tno,database)
635         set query $hist($setNo,$tno,query)
636     } else {
637         set zz z39
638         set host $hist($setNo,host)
639         set idAuth $hist($setNo,idAuthentication)
640         set database $hist($setNo,database)
641         set query $hist($setNo,query)
642     }
643     if {[catch [list $zz failback fail-response]]} {
644         ir $zz
645     }
646     if {[catch [list set oldHost [$zz connect]]]} {
647         set oldHost ""
648     }
649     $zz callback ok-response
650     $zz failback fail-response
651     set thisHost [splitHostSpec $host]
652     if {$oldHost != $thisHost} {
653         catch [list $zz disconnect]
654
655         set sessionWait 0
656         if {[catch [list $zz connect $thisHost]]} {
657             displayError "Cannot connect to target" $thisHost
658             return 0
659         } elseif {$sessionWait == 0} {
660             if {[catch {egw_wait sessionWait 300}]} {
661                 $zz disconnect
662                 displayError "Cannot connect to target" $thisHost
663                 return 0
664             }
665             if {$sessionWait != 1} {
666                 displayError "Cannot connect to target" $thisHost
667                 return 0
668             }
669         }
670         $zz idAuthentication $idAuth
671         set sessionWait 0
672         if {[catch {$zz init}]} {
673             displayError "Cannot initialize target" $thisHost
674             $zz disconnect
675             return 0
676         }
677         if {[catch {egw_wait sessionWait 60}]} {
678             displayError "Cannot initialize target" $thisHost
679             $zz disconnect
680             return 0
681         }
682         if {$sessionWait != "1"} {
683             displayError "Cannot initialize target" $thisHost
684             $zz disconnect
685             return 0
686         }
687         if {![$zz initResult]} {
688             set u [$zz userInformationField]
689             $zz disconnect
690             displayError "Cannot initialize target $thisHost" $u
691             return 0
692         }
693     } else {
694         if {[info exists hist($setNo,hits)] && \
695                 ![catch [list $zz.$setNo smallSetUpperBound 0]]} {
696             return 1
697         }
698         
699     }
700     ir-set $zz.$setNo $zz
701     
702     if {![lindex $targets($host) 5]} {
703         set elements {}
704     }
705     $zz.$setNo smallSetElementSetNames $elements
706     $zz.$setNo mediumSetElementSetNames $elements
707     $zz.$setNo recordElements $elements
708
709     egw_log debug "database=$database"
710     eval $zz.$setNo databaseNames $database
711
712     $zz.$setNo preferredRecordSyntax USMARC
713
714     $zz callback [list search-response $zz.$setNo]
715     if {$piggy} {
716         $zz.$setNo largeSetLowerBound 999999
717         $zz.$setNo smallSetUpperBound 0
718         $zz.$setNo mediumSetPresentNumber $hist($setNo,maxPresent)
719     } else {
720         $zz.$setNo largeSetLowerBound 2
721         $zz.$setNo smallSetUpperBound 0
722         $zz.$setNo mediumSetPresentNumber 0
723     }
724     set sessionWait 0
725     egw_log debug "search: $query"
726     $zz.$setNo search $query
727
728     if {[catch {egw_wait sessionWait 600}]} {
729         egw_log debug "timeout/cancel in search"
730         displayError "Timeout in search" {}
731         html "</body></html>\n"
732         $zz disconnect
733         return 0
734     }
735         
736     if {$sessionWait == -1} {
737         displayError "Search fail" "Connection closed"
738         html "</body></html>\n"
739         $zz disconnect
740     }
741     if {$sessionWait != 1} {
742         return 0
743     }
744     set hist($setNo,hits) [$zz.$setNo resultCount]
745     return 1
746 }
747
748 proc init-m-response {i} {
749     global zstatus
750     global zleft
751
752     egw_log debug "init-m-response"
753
754     set zstatus($i) 1
755     incr zleft -1
756 }
757
758 proc connect-m-response {i} {
759     global zstatus
760     global zleft
761
762     egw_log debug "connect-m-response"
763     z39$i callback [list init-m-response $i]
764     if {[catch {z39$i init}]} {
765         set zstatus($i) -1
766         incr zleft -1
767     }
768 }
769
770 proc fail-m-response {i} {
771     global zstatus
772     global zleft
773     
774     egw_log debug "fail-m-response"
775     set zstatus($i) -1
776     incr zleft -1
777 }
778
779 proc search-m-response {setNo i} {
780     global zleft
781     global zstatus
782
783     incr zleft -1
784     set zstatus($i) 2
785 }
786
787 proc z39msearch {setNo piggy elements} {
788     global zleft
789     global zstatus
790     global hist
791     global targets
792
793     set not $hist($setNo,0,host)
794
795     for {set i 1} {$i <= $not} {incr i} {
796         set host $hist($setNo,$i,host)
797         if {[catch {z39 failback fail-response}]} {
798             ir z39$i
799         }
800         if {[catch {set oldHost [z39$i connect]}]} {
801             set oldHost ""
802         }
803         set thisHost [splitHostSpec $host]
804         if {$oldHost != $thisHost} {
805             catch {z39$i disconnect}
806         }
807         z39$i callback [list connect-m-response $i]
808         z39$i failback [list fail-m-response $i]
809     }
810     set zleft 0
811     for {set i 1} {$i <= $not} {incr i} {
812         set oldHost [z39$i connect]
813         set host $hist($setNo,$i,host)
814         set thisHost [splitHostSpec $host]
815         if {$oldHost == $thisHost} {
816             set zstatus($i) 1
817             continue
818         }
819         z39$i idAuthentication $hist($setNo,$i,idAuthentication)
820         html "Connecting to target " $thisHost " <br>\n"
821         set zstatus($i) -1
822         if {![catch {z39$i connect $thisHost}]} {
823             incr zleft
824         } 
825     }
826     while {$zleft > 0} {
827         egw_log debug "Waiting for init response"
828         if {[catch {egw_wait zleft 10}]} {
829             break
830         }
831     }
832     set zleft 0
833     for {set i 1} {$i <= $not} {incr i} {
834         html "host " [splitHostSpec $hist($setNo,$i,host)] ": "
835         if {$zstatus($i) >= 1} {
836             html "ok <br>\n"
837             ir-set z39$i.$setNo z39$i
838             set hist($setNo,$i,offset) 0
839             eval z39$i.$setNo databaseNames $hist($setNo,$i,database)
840
841             if {![lindex $targets($hist($setNo,$i,host)) 5]} {
842                 set thisElements {}
843             } else {
844                 set thisElements $elements
845             }
846             z39$i.$setNo smallSetElementSetNames $thisElements
847             z39$i.$setNo mediumSetElementSetNames $thisElements
848             z39$i.$setNo recordElements $thisElements
849
850             z39$i.$setNo preferredRecordSyntax USMARC
851             z39$i callback [list search-m-response $setNo $i]
852
853             if {$piggy} {
854                 z39$i.$setNo largeSetLowerBound 999999
855                 z39$i.$setNo smallSetUpperBound 0
856                 z39$i.$setNo mediumSetPresentNumber $hist($setNo,maxPresent)
857             } else {
858                 z39$i.$setNo largeSetLowerBound 2
859                 z39$i.$setNo smallSetUpperBound 0
860                 z39$i.$setNo mediumSetPresentNumber 0
861             }
862             set zstatus($i) 1
863             egw_log debug "search " $hist($setNo,$i,query)
864             z39$i.$setNo search $hist($setNo,$i,query)
865             incr zleft
866         } else {
867             html "fail <br>\n"
868         }
869     }
870     while {$zleft > 0} {
871         egw_log debug "Waiting for search response"
872         if {[catch {egw_wait zleft 30}]} {
873             break
874         }
875     }
876     for {set i 1} {$i <= $not} {incr i} {
877         if {$zstatus($i) != 2} continue
878         set status [z39$i.$setNo responseStatus]
879         if {[lindex $status 0] != "NSD"} {
880             set hist($setNo,$i,offset) [z39$i.$setNo numberOfRecordsReturned]
881         }
882     }
883 }
884
885 proc z39present {setNo tno setOffset setMax dfunc elements} {
886     global hist
887     global sessionWait
888     global targets
889
890     if {$tno > 0} {
891         set zz z39$tno
892         set host $hist($setNo,$tno,host)
893     } else {
894         set zz z39
895         set host $hist($setNo,host)
896     }
897
898     if {![lindex $targets($host) 5]} {
899         set elements {}
900     }
901
902     $zz.$setNo elementSetNames $elements
903     $zz.$setNo recordElements $elements
904     set toGet [expr 1 + $setMax - $setOffset]
905
906     $zz callback [list search-response $zz.$setNo]
907
908     while {$setMax > 0 && $toGet > 0} {
909         for {set got 0} {$got < $toGet} {incr got} {
910             if {[$zz.$setNo type [expr $setOffset + $got]] == ""} {
911                 break
912             }
913         }
914         if {$got < $toGet} {
915             set sessionWait 0
916             $zz.$setNo present $setOffset $toGet
917             if {[catch {egw_wait sessionWait 300}]} {
918                 egw_log debug "timeout/cancel in present"
919                 $zz disconnect
920                 break
921             }
922             if {$sessionWait == "0"} {
923                 $zz disconnect
924             }
925             if {$sessionWait != "1"} {
926                 break
927             }
928             set got [$zz.$setNo numberOfRecordsReturned]
929             if {$got <= 0} {
930                 break
931             }
932         }
933         display-rec $setOffset [expr $got + $setOffset - 1] $dfunc $tno
934         set setOffset [expr $got + $setOffset]
935         set toGet [expr 1 + $setMax - $setOffset]
936         egw_flush
937     }
938 }
939
940 proc z39history {} {
941     global nextSetNo
942     global hist
943     global env
944     global sessionId
945     global targets
946
947     if {![info exists nextSetNo]} {
948         return
949     }
950     html "<h2>History</h2><dl><br>\n"
951     for {set setNo 1} {$setNo < $nextSetNo} {incr setNo} {
952         if {$hist($setNo,scan) > 0} continue
953         set host $hist($setNo,host)
954         html {<dt> } [lindex $targets($host) 0]
955         if {[llength [lindex $targets($host) 1]] > 1} {
956             html ": "
957             foreach b $hist($setNo,database) {
958                 html " $b"
959             }
960         }
961         html {. }
962
963         if {[info exists hist($setNo,hits)]} {
964             html { <a href="http:} $env(SCRIPT_NAME)
965             html / $sessionId {/search.egw/} $setNo + 1
966             html + $hist($setNo,maxPresent)
967             html {">Result</a>: } $hist($setNo,hits) { hits.}
968         } else {
969             html {Search failed.}
970         }
971         html "<dd>\n"
972         html { <a href="http:} $env(SCRIPT_NAME)
973         html / $sessionId {/query.egw/} $host + $setNo 
974         html {">Query</a>: }
975         set op {}
976         for {set i 1} {$i <= 3} {incr i} {
977             if {[string length $hist($setNo,form,entry$i)] > 0} {
978                 html " <b>" [join $op " "] "</b> "
979                 html $hist($setNo,form,menu$i) "=" $hist($setNo,form,entry$i)
980                 set op $hist($setNo,form,logic$i)
981             }
982         }
983     }
984     html "</dl>\n"
985 }
986
987 proc displayError {msga msgb} {
988     html "<p><center>\n"
989     html {<img src="/egwgif/noway.gif" alt="Error">}
990     html "<h2>" $msga "</h2>\n"
991     if {$msgb != ""} {
992         html "<h3>" $msgb "</h3>\n"
993     }
994     html "</center><p>\n"
995 }
996
997 proc button-europagate {} {
998     global useIcons
999     if {$useIcons} {
1000         html {<img src="/egwgif/button-egw.gif" alt="Europagate" border=0></a>}
1001     } else {
1002         html {Europagate | }
1003     }
1004 }
1005
1006 proc button-define-target {more} {
1007     global useIcons
1008     global env
1009     global sessionId
1010
1011     html {<a href="http:} $env(SCRIPT_NAME)
1012     html / $sessionId {/tform.egw}
1013     if {$useIcons} {
1014         html {"><img src="/egwgif/button-define-target.gif" }
1015         html {alt="New Target" border=0></a>}
1016     } else {
1017         html {">New Target</a>}
1018         if {$more} {
1019             html " | \n"
1020         } else {
1021             html "\n"
1022         }
1023     }
1024 }
1025
1026 proc button-new-target {more} {
1027     global useIcons
1028     global env
1029     global sessionId
1030
1031     html {<a href="http:} $env(SCRIPT_NAME)
1032     html / $sessionId {/targets.egw}
1033     if {$useIcons} {
1034         html {"><img src="/egwgif/button-new-target.gif" }
1035         html {alt="New Target" border=0></a>}
1036     } else {
1037         html {">New Target</a>}
1038         if {$more} {
1039             html " | \n"
1040         } else {
1041             html "\n"
1042         }
1043     }
1044 }
1045
1046 proc button-view-history {more} {
1047     global useIcons
1048     global env
1049     global sessionId
1050     global nextSetNo
1051
1052     html {<a href="http:} $env(SCRIPT_NAME)
1053     html / $sessionId {/history.egw;}
1054     catch { html "/" $nextSetNo}
1055     if {$useIcons} {
1056         html {"><img src="/egwgif/button-view-history.gif" alt="View History" }
1057         html {border=0></a>}
1058     } else {
1059         html {">View History</a>}
1060         if {$more} {
1061             html " | \n"
1062         } else {
1063             html "\n"
1064         }
1065     }
1066 }
1067
1068 proc button-new-query {more setNo} {
1069     global useIcons
1070     global env
1071     global sessionId
1072     global hist
1073
1074     html {<a href="http:} $env(SCRIPT_NAME)
1075     html / $sessionId {/query.egw/} $hist($setNo,host) + $setNo {">}
1076     if {$useIcons} {
1077         html {<img src="/egwgif/button-new-query.gif" }
1078         html {alt="New Query" border=0></a>}
1079     } else {
1080         html {New Query</a>}
1081         if {$more} {
1082             html " | \n"
1083         } else {
1084             html "\n"
1085         }
1086     }
1087 }
1088
1089 proc button-scan-window {more setNo} {
1090     global useIcons
1091     global env
1092     global sessionId
1093     global hist
1094
1095     html {<a href="http:} $env(SCRIPT_NAME)
1096     html / $sessionId {/search.egw/} $setNo + {scan} {">}
1097     if {$useIcons} {
1098         html {<img src="/egwgif/button-scan-window.gif" }
1099         html {alt="Scan" border=0></a>}
1100     } else {
1101         html {Scan</a>}
1102         if {$more} {
1103             html " | \n"
1104         } else {
1105             html "\n"
1106         }
1107     }
1108 }
1109
1110 proc maintenance {} {
1111     html {<hr>This page is maintained by }
1112     html {<a href="mailto:pwh@dtv.dk"> Peter Wad Hansen </a>.}
1113     html {Last modified 24. january 1996. <br>}
1114     html {<em> This and the following pages are under construction and }
1115     html {will continue to be so until the end of January 1996.</em>}
1116 }
1117
1118 proc splitHostSpec {host} {
1119     set i [string last . $host]
1120     if {$i > 1} {
1121         incr i -1
1122         return [string range $host 0 $i]
1123     }
1124     return $host
1125 }
1126
1127 proc mergeHostSpec {host databases} {
1128     return ${host}.[join $databases -]
1129 }