6860b16fe7369223907d0491cc285add3190a698
[egate.git] / www / z39util.tcl
1 #
2 # $Id: z39util.tcl,v 1.26 1996/01/26 15:50:11 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} {
786     global zleft
787     global zstatus
788
789     incr zleft -1
790     set zstatus($i) 2
791 }
792
793 proc z39msearch {setNo piggy elements} {
794     global zleft
795     global zstatus
796     global hist
797     global targets
798
799     set not $hist($setNo,0,host)
800
801     for {set i 1} {$i <= $not} {incr i} {
802         set host $hist($setNo,$i,host)
803         if {[catch {z39 failback fail-response}]} {
804             ir z39$i
805         }
806         if {[catch {set oldHost [z39$i connect]}]} {
807             set oldHost ""
808         }
809         set thisHost [splitHostSpec $host]
810         if {$oldHost != $thisHost} {
811             catch {z39$i disconnect}
812         }
813         z39$i callback [list connect-m-response $i]
814         z39$i failback [list fail-m-response $i]
815     }
816     set zleft 0
817     for {set i 1} {$i <= $not} {incr i} {
818         set oldHost [z39$i connect]
819         set host $hist($setNo,$i,host)
820         set thisHost [splitHostSpec $host]
821         if {$oldHost == $thisHost} {
822             set zstatus($i) 1
823             continue
824         }
825         z39$i idAuthentication $hist($setNo,$i,idAuthentication)
826         html "Connecting to target " $thisHost " <br>\n"
827         set zstatus($i) -1
828         if {![catch {z39$i connect $thisHost}]} {
829             incr zleft
830         } 
831     }
832     while {$zleft > 0} {
833         egw_log debug "Waiting for init response"
834         if {[catch {egw_wait zleft 10}]} {
835             break
836         }
837     }
838     set zleft 0
839     for {set i 1} {$i <= $not} {incr i} {
840         html "host " [splitHostSpec $hist($setNo,$i,host)] ": "
841         if {$zstatus($i) >= 1} {
842             html "ok <br>\n"
843             ir-set z39$i.$setNo z39$i
844             set hist($setNo,$i,offset) 0
845             eval z39$i.$setNo databaseNames $hist($setNo,$i,database)
846
847             if {![lindex $targets($hist($setNo,$i,host)) 5]} {
848                 set thisElements {}
849             } else {
850                 set thisElements $elements
851             }
852             z39$i.$setNo smallSetElementSetNames $thisElements
853             z39$i.$setNo mediumSetElementSetNames $thisElements
854             z39$i.$setNo recordElements $thisElements
855
856             z39$i.$setNo preferredRecordSyntax USMARC
857             z39$i callback [list search-m-response $setNo $i]
858
859             if {$piggy} {
860                 z39$i.$setNo largeSetLowerBound 999999
861                 z39$i.$setNo smallSetUpperBound 0
862                 z39$i.$setNo mediumSetPresentNumber $hist($setNo,maxPresent)
863             } else {
864                 z39$i.$setNo largeSetLowerBound 2
865                 z39$i.$setNo smallSetUpperBound 0
866                 z39$i.$setNo mediumSetPresentNumber 0
867             }
868             set zstatus($i) 1
869             egw_log debug "search " $hist($setNo,$i,query)
870             z39$i.$setNo search $hist($setNo,$i,query)
871             incr zleft
872         } else {
873             html "fail <br>\n"
874         }
875     }
876     while {$zleft > 0} {
877         egw_log debug "Waiting for search response"
878         if {[catch {egw_wait zleft 30}]} {
879             break
880         }
881     }
882     for {set i 1} {$i <= $not} {incr i} {
883         if {$zstatus($i) != 2} continue
884         set status [z39$i.$setNo responseStatus]
885         if {[lindex $status 0] != "NSD"} {
886             set hist($setNo,$i,offset) [z39$i.$setNo numberOfRecordsReturned]
887         }
888     }
889 }
890
891 proc z39present {setNo tno setOffset setMax dfunc elements} {
892     global hist
893     global sessionWait
894     global targets
895
896     if {$tno > 0} {
897         set zz z39$tno
898         set host $hist($setNo,$tno,host)
899     } else {
900         set zz z39
901         set host $hist($setNo,host)
902     }
903
904     if {![lindex $targets($host) 5]} {
905         set elements {}
906     }
907
908     $zz.$setNo elementSetNames $elements
909     $zz.$setNo recordElements $elements
910     set toGet [expr 1 + $setMax - $setOffset]
911
912     $zz callback [list search-response $zz.$setNo]
913
914     while {$setMax > 0 && $toGet > 0} {
915         for {set got 0} {$got < $toGet} {incr got} {
916             if {[$zz.$setNo type [expr $setOffset + $got]] == ""} {
917                 break
918             }
919         }
920         if {$got < $toGet} {
921             set sessionWait 0
922             $zz.$setNo present $setOffset $toGet
923             if {[catch {egw_wait sessionWait 300}]} {
924                 egw_log debug "timeout/cancel in present"
925                 $zz disconnect
926                 break
927             }
928             if {$sessionWait == "0"} {
929                 $zz disconnect
930             }
931             if {$sessionWait != "1"} {
932                 break
933             }
934             set got [$zz.$setNo numberOfRecordsReturned]
935             if {$got <= 0} {
936                 break
937             }
938         }
939         display-rec $setOffset [expr $got + $setOffset - 1] $dfunc $tno
940         set setOffset [expr $got + $setOffset]
941         set toGet [expr 1 + $setMax - $setOffset]
942         egw_flush
943     }
944 }
945
946 proc z39history {} {
947     global nextSetNo
948     global hist
949     global env
950     global sessionId
951     global targets
952
953     if {![info exists nextSetNo]} {
954         return
955     }
956     html "<h2>History</h2><dl><br>\n"
957     for {set setNo 1} {$setNo < $nextSetNo} {incr setNo} {
958         if {$hist($setNo,scan) > 0} continue
959         set host $hist($setNo,host)
960         html {<dt> } [lindex $targets($host) 0]
961         if {[llength [lindex $targets($host) 1]] > 1} {
962             html ": "
963             foreach b $hist($setNo,database) {
964                 html " $b"
965             }
966         }
967         html {. }
968
969         if {[info exists hist($setNo,hits)]} {
970             html { <a href="http:} $env(SCRIPT_NAME)
971             html / $sessionId {/search.egw/} $setNo + 1
972             html + $hist($setNo,maxPresent)
973             html {">Result</a>: } $hist($setNo,hits) { hits.}
974         } else {
975             html {Search failed.}
976         }
977         html "<dd>\n"
978         html { <a href="http:} $env(SCRIPT_NAME)
979         html / $sessionId {/query.egw/} $host + $setNo 
980         html {">Query</a>: }
981         set op {}
982         for {set i 1} {$i <= 3} {incr i} {
983             if {[string length $hist($setNo,form,entry$i)] > 0} {
984                 html " <b>" [join $op " "] "</b> "
985                 html [join $hist($setNo,form,menu$i)] "=" 
986                 html $hist($setNo,form,entry$i)
987                 set op $hist($setNo,form,logic$i)
988             }
989         }
990     }
991     html "</dl>\n"
992 }
993
994 proc displayError {msga msgb} {
995     html "<p><center>\n"
996     html {<img src="/egwgif/noway.gif" alt="Error">}
997     html "<h2>" $msga "</h2>\n"
998     if {$msgb != ""} {
999         html "<h3>" $msgb "</h3>\n"
1000     }
1001     html "</center><p>\n"
1002 }
1003
1004 proc button-europagate {} {
1005     global useIcons
1006     if {$useIcons} {
1007         html {<img src="/egwgif/button-egw.gif" alt="Europagate" border=0></a>}
1008     } else {
1009         html {Europagate | }
1010     }
1011 }
1012
1013 proc button-define-target {more} {
1014     global useIcons
1015     global env
1016     global sessionId
1017
1018     html {<a href="http:} $env(SCRIPT_NAME)
1019     html / $sessionId {/tform.egw}
1020     if {$useIcons} {
1021         html {"><img src="/egwgif/button-define-target.gif" }
1022         html {alt="Define Target" border=0></a>}
1023     } else {
1024         html {">Define Target</a>}
1025         if {$more} {
1026             html " | \n"
1027         } else {
1028             html "\n"
1029         }
1030     }
1031 }
1032
1033 proc button-new-target {more} {
1034     global useIcons
1035     global env
1036     global sessionId
1037     global mMode
1038
1039     html {<a href="http:} $env(SCRIPT_NAME)
1040     html / $sessionId 
1041     if {$mMode} {
1042         html {/mtargets.egw}
1043     } else {
1044         html {/targets.egw}
1045     }
1046     if {$useIcons} {
1047         html {"><img src="/egwgif/button-new-target.gif" }
1048         html {alt="New Target" border=0></a>}
1049     } else {
1050         html {">New Target</a>}
1051         if {$more} {
1052             html " | \n"
1053         } else {
1054             html "\n"
1055         }
1056     }
1057 }
1058
1059 proc button-view-history {more} {
1060     global useIcons
1061     global env
1062     global sessionId
1063     global nextSetNo
1064
1065     html {<a href="http:} $env(SCRIPT_NAME)
1066     html / $sessionId {/history.egw;}
1067     catch { html "/" $nextSetNo}
1068     if {$useIcons} {
1069         html {"><img src="/egwgif/button-view-history.gif" alt="View History" }
1070         html {border=0></a>}
1071     } else {
1072         html {">View History</a>}
1073         if {$more} {
1074             html " | \n"
1075         } else {
1076             html "\n"
1077         }
1078     }
1079 }
1080
1081 proc button-new-query {more setNo} {
1082     global useIcons
1083     global env
1084     global sessionId
1085     global hist
1086     global mMode
1087
1088     html {<a href="http:} $env(SCRIPT_NAME)
1089     html / $sessionId 
1090     if {$mMode} {
1091         html {/mquery.egw/} $setNo
1092     } else {
1093         html {/query.egw/} $hist($setNo,host) + $setNo
1094     }
1095     html {">}
1096     if {$useIcons} {
1097         html {<img src="/egwgif/button-new-query.gif" }
1098         html {alt="New Query" border=0></a>}
1099     } else {
1100         html {New Query</a>}
1101         if {$more} {
1102             html " | \n"
1103         } else {
1104             html "\n"
1105         }
1106     }
1107 }
1108
1109 proc button-scan-window {more setNo} {
1110     global useIcons
1111     global env
1112     global sessionId
1113     global hist
1114
1115     html {<a href="http:} $env(SCRIPT_NAME)
1116     html / $sessionId {/search.egw/} $setNo + {scan} {">}
1117     if {$useIcons} {
1118         html {<img src="/egwgif/button-scan-window.gif" }
1119         html {alt="Scan" border=0></a>}
1120     } else {
1121         html {Scan</a>}
1122         if {$more} {
1123             html " | \n"
1124         } else {
1125             html "\n"
1126         }
1127     }
1128 }
1129
1130 proc maintenance {} {
1131     html {<hr>This page is maintained by }
1132     html {<a href="mailto:pwh@dtv.dk"> Peter Wad Hansen </a>.}
1133     html {Last modified 26. january 1996. <br>}
1134     html {<em> This and the following pages are under construction and }
1135     html {will continue to be so until the end of January 1996.</em>}
1136 }
1137
1138 proc splitHostSpec {host} {
1139     set i [string last . $host]
1140     if {$i > 1} {
1141         incr i -1
1142         return [string range $host 0 $i]
1143     }
1144     return $host
1145 }
1146
1147 proc mergeHostSpec {host databases} {
1148     return ${host}.[join $databases -]
1149 }