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