Misc. improvements.
[egate.git] / www / z39util.tcl
1 #
2 # $Id: z39util.tcl,v 1.31 1996/02/20 16:07:39 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     } dispError ] } {
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                 set nope 0
144                 html [string range $v 0 38] "..."
145             } elseif {[string length $v] > 0} {
146                 set nope 0
147                 html $v
148             } else {
149                 html "No Title"
150             }
151         }
152         html {</a> }
153     } else {
154         html { <a href="http:} $env(SCRIPT_NAME) /
155         html $sessionId {/showfull.egw/} $setNo + $tno + $no + full {">}
156         html {No Title}
157         html {</a> }
158         html "Error: " $dispError "\n"
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="} [join $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     egw_log debug "scan: ${scanAttr} ${scanTerm}"
565     set sessionWait 0
566     $zs scan "${scanAttr} ${scanTerm}"
567
568     if {[catch {egw_wait sessionWait 60}]} {
569         egw_log debug "timeout/cancel in scan"
570         displayError "Timeout in scan" {}
571         html "</body></html>\n"
572         $zz disconnect
573         return 0
574     }
575     if {$sessionWait == -1} {
576         displayError "Scan fail" "Connection closed"
577         html "</body></html>\n"
578         $zz disconnect
579     }
580     if {$sessionWait != 1} {
581         return 0
582     }
583     return 1
584 }
585
586 proc display-scan {setNo scanNo tno} {
587     global hist
588     global targets
589     global env
590     global sessionId
591
592     if {$tno > 0} {
593         set zz z39$tno
594     } else {
595         set zz z39
596     }
597     set zs $zz.s$scanNo.$setNo
598     set m [$zs numberOfEntriesReturned]
599         
600     if {$m > 0} {
601         set t [lindex [$zs scanLine 0] 1]
602         if {$tno > 0} {
603             set hist($setNo,$tno,[expr $scanNo - 1],scanTerm) $t
604         } else {
605             set hist($setNo,[expr $scanNo - 1],scanTerm) $t
606         }
607         set t [lindex [$zs scanLine [expr $m - 1]] 1]
608         if {$tno > 0} {
609             set hist($setNo,$tno,[expr $scanNo + 1],scanTerm) $t
610         } else {
611             set hist($setNo,[expr $scanNo + 1],scanTerm) $t
612         }
613     }
614     html {<table width=500 border=0><tr>}
615     html {<td align=left><b>Scan term</b>}
616     html {<td align=right><b>Hits</b>}
617     html {<tr>} \n
618
619     for {set i 0} {$i < $m} {incr i} {
620         html {<td align=left>}
621         if {0} {
622             regsub -all {\ } [lindex [$zs scanLine $i] 1] + tterm
623             html {<a href="http:} $env(SCRIPT_NAME)
624             html / $sessionId {/query.egw/} $hist($setNo,host) + $setNo +
625             html $hist($setNo,scan) +  $tterm {">}
626         } else {
627             regsub -all {\ } [lindex [$zs scanLine $i] 1] + tterm
628             html {<a href="http:} $env(SCRIPT_NAME)
629             html / $sessionId {/search.egw/} $setNo +
630             html hyper + $tterm {">}
631         }
632         html [lindex [$zs scanLine $i] 1]
633         html {</a>} 
634         html {<td align=right>}
635         html [lindex [$zs scanLine $i] 2]
636         html {<tr>} \n
637     }
638     html {</table} \n
639 }
640
641 proc z39search {setNo piggy tno elements} {
642     global hist
643     global sessionWait
644     global targets
645
646     if {$tno > 0} {
647         set zz z39$tno
648         set host $hist($setNo,$tno,host)
649         set idAuth $hist($setNo,$tno,idAuthentication)
650         set database $hist($setNo,$tno,database)
651         set query $hist($setNo,$tno,query)
652     } else {
653         set zz z39
654         set host $hist($setNo,host)
655         set idAuth $hist($setNo,idAuthentication)
656         set database $hist($setNo,database)
657         set query $hist($setNo,query)
658     }
659     if {[catch [list $zz failback fail-response]]} {
660         ir $zz
661     }
662     if {[catch [list set oldHost [$zz connect]]]} {
663         set oldHost ""
664     }
665     $zz callback ok-response
666     $zz failback fail-response
667     set thisHost [splitHostSpec $host]
668     if {$oldHost != $thisHost} {
669         catch [list $zz disconnect]
670
671         set sessionWait 0
672         if {[catch [list $zz connect $thisHost]]} {
673             displayError "Cannot connect to target" $thisHost
674             return 0
675         } elseif {$sessionWait == 0} {
676             if {[catch {egw_wait sessionWait 300}]} {
677                 $zz disconnect
678                 displayError "Cannot connect to target" $thisHost
679                 return 0
680             }
681             if {$sessionWait != 1} {
682                 displayError "Cannot connect to target" $thisHost
683                 return 0
684             }
685         }
686         $zz idAuthentication $idAuth
687         set sessionWait 0
688         if {[catch {$zz init}]} {
689             displayError "Cannot initialize target" $thisHost
690             $zz disconnect
691             return 0
692         }
693         if {[catch {egw_wait sessionWait 60}]} {
694             displayError "Cannot initialize target" $thisHost
695             $zz disconnect
696             return 0
697         }
698         if {$sessionWait != "1"} {
699             displayError "Cannot initialize target" $thisHost
700             $zz disconnect
701             return 0
702         }
703         if {![$zz initResult]} {
704             set u [$zz userInformationField]
705             $zz disconnect
706             displayError "Cannot initialize target $thisHost" $u
707             return 0
708         }
709     } else {
710         if {[info exists hist($setNo,hits)] && \
711                 ![catch [list $zz.$setNo smallSetUpperBound 0]]} {
712             return 1
713         }
714         
715     }
716     ir-set $zz.$setNo $zz
717     
718     if {![lindex $targets($host) 5]} {
719         set elements {}
720     }
721     $zz.$setNo smallSetElementSetNames $elements
722     $zz.$setNo mediumSetElementSetNames $elements
723     $zz.$setNo recordElements $elements
724
725     egw_log debug "database=$database"
726     eval $zz.$setNo databaseNames $database
727
728     $zz.$setNo preferredRecordSyntax USMARC
729
730     $zz callback [list search-response $zz.$setNo]
731     if {$piggy} {
732         $zz.$setNo largeSetLowerBound 999999
733         $zz.$setNo smallSetUpperBound 0
734         $zz.$setNo mediumSetPresentNumber $hist($setNo,maxPresent)
735     } else {
736         $zz.$setNo largeSetLowerBound 2
737         $zz.$setNo smallSetUpperBound 0
738         $zz.$setNo mediumSetPresentNumber 0
739     }
740     set sessionWait 0
741     egw_log debug "search: $query"
742     $zz.$setNo search $query
743
744     if {[catch {egw_wait sessionWait 60}]} {
745         egw_log debug "timeout/cancel in search"
746         displayError "Timeout in search" {}
747         html "</body></html>\n"
748         $zz disconnect
749         return 0
750     }
751         
752     if {$sessionWait == -1} {
753         displayError "Search fail" "Connection closed"
754         html "</body></html>\n"
755         $zz disconnect
756     }
757     if {$sessionWait != 1} {
758         return 0
759     }
760     set hist($setNo,hits) [$zz.$setNo resultCount]
761     return 1
762 }
763
764 proc init-m-response {i} {
765     global zstatus
766     global zleft
767
768     egw_log debug "init-m-response"
769
770     incr zleft -1
771     if {![z39$i initResult]} {
772         set zstatus($i) -1
773         z39$i disconnect
774         return
775     }
776     set zstatus($i) 1
777 }
778
779 proc connect-m-response {i} {
780     global zstatus
781     global zleft
782
783     egw_log debug "connect-m-response"
784     z39$i callback [list init-m-response $i]
785     if {[catch {z39$i init}]} {
786         set zstatus($i) -1
787         incr zleft -1
788     }
789 }
790
791 proc fail-m-response {i} {
792     global zstatus
793     global zleft
794     
795     egw_log debug "fail-m-response"
796     set zstatus($i) -1
797     incr zleft -1
798 }
799
800 proc search-m-response {setNo i start number} {
801     global zleft
802     global zstatus
803     global hist
804
805     egw_log debug "search-m-response"
806     set status [z39$i.$setNo responseStatus]
807     egw_log debug "search-m-response1"
808     if {[lindex $status 0] != "DBOSD"} {
809         egw_log debug "search-m-response2"
810         incr zleft -1
811         set zstatus($i) 2
812         return
813     }
814     set nor [z39$i.$setNo numberOfRecordsReturned]
815     egw_log debug "search-m-response3"
816     set hist($setNo,$i,offset) [expr $start + $nor -1]
817     if {[expr $nor + $start] > [z39$i.$setNo resultCount]} {
818         egw_log debug "search-m-response4"
819         incr zleft -1
820         set zstatus($i) 2
821         return
822     }
823     egw_log debug "search-m-response5"
824     if {$nor >= $number} {
825         egw_log debug "search-m-response6 nor=$nor number=$number"
826         incr zleft -1
827         set zstatus($i) 2
828         return
829     }
830     egw_log debug "search-m-response7"
831     set start [expr $start + $nor]
832     set number [expr $number - $nor]
833     if {[expr $start + $number - 1] > [z39$i.$setNo resultCount]} {
834         set number [expr [z39$i.$setNo resultCount] - $start + 1]
835     }
836     z39$i callback [list search-m-response $setNo $i $start $number]
837     egw_log debug "mpresent start=$number number=$number"
838     z39$i.$setNo present $start $number
839 }
840
841 proc z39msearch {setNo elements start number cache} {
842     global zleft
843     global zstatus
844     global hist
845     global targets
846     global debug
847
848     set not $hist($setNo,0,host)
849
850     egw_log debug "z39msearch start=$start number=$number elements=$elements"
851     for {set i 1} {$i <= $not} {incr i} {
852         set host $hist($setNo,$i,host)
853         if {[catch [list z39$i failback fail-m-response $i]]} {
854             ir z39$i
855         }
856         set oldHost [z39$i connect]
857         set thisHost [splitHostSpec $host]
858         if {$oldHost != $thisHost} {
859             catch {z39$i disconnect}
860         }
861         z39$i callback [list connect-m-response $i]
862         z39$i failback [list fail-m-response $i]
863     }
864     set zleft 0
865     for {set i 1} {$i <= $not} {incr i} {
866         set oldHost [z39$i connect]
867         set host $hist($setNo,$i,host)
868         set thisHost [splitHostSpec $host]
869         if {$oldHost == $thisHost} {
870             continue
871         }
872         egw_log debug "old=$oldHost this=$thisHost"
873         z39$i idAuthentication $hist($setNo,$i,idAuthentication)
874         html "Connecting to target " $thisHost " <br>\n"
875         set zstatus($i) -1
876         if {![catch {z39$i connect $thisHost}]} {
877             incr zleft
878         } 
879     }
880     while {$zleft > 0} {
881         egw_log debug "Waiting for init response"
882         if {[catch {egw_wait zleft 20}]} {
883             break
884         }
885     }
886     set zleft 0
887     for {set i 1} {$i <= $not} {incr i} {
888         if {$debug} {
889             html "host " [splitHostSpec $hist($setNo,$i,host)] ": "
890         }
891         egw_log debug "i=$i zstatus=$zstatus($i)"
892         if {$zstatus($i) < 1} {
893             if {$debug} {
894                 html "fail<br>\n"
895             }
896             continue
897         }
898         if {[catch [list z39$i.$setNo preferredRecordSyntax USMARC]]} {
899             if {$debug} {
900                 html "ok<br>\n"
901             }
902             ir-set z39$i.$setNo z39$i
903             set hist($setNo,$i,offset) 0
904             eval z39$i.$setNo databaseNames $hist($setNo,$i,database)
905
906             if {![lindex $targets($hist($setNo,$i,host)) 5]} {
907                 set thisElements {}
908             } else {
909                 set thisElements $elements
910             }
911             z39$i.$setNo smallSetElementSetNames $thisElements
912             z39$i.$setNo mediumSetElementSetNames $thisElements
913             z39$i.$setNo elementSetNames $thisElements
914             z39$i.$setNo recordElements $thisElements
915
916             z39$i.$setNo preferredRecordSyntax USMARC
917             z39$i callback [list search-m-response $setNo $i $start $number]
918
919             if {$start == 1} {
920                 z39$i.$setNo largeSetLowerBound 999999
921                 z39$i.$setNo smallSetUpperBound 0
922                 z39$i.$setNo mediumSetPresentNumber $number
923             } else {
924                 z39$i.$setNo largeSetLowerBound 2
925                 z39$i.$setNo smallSetUpperBound 0
926                 z39$i.$setNo mediumSetPresentNumber 0
927             }
928             set zstatus($i) 1
929             incr zleft
930             egw_log debug "setNo=$setNo msearch " $hist($setNo,$i,query)
931             z39$i.$setNo search $hist($setNo,$i,query)
932         } elseif {[z39$i.$setNo resultCount] >= $start} {
933             if {[expr $start + $number - 1] > [z39$i.$setNo resultCount]} {
934                 set tnumber [expr [z39$i.$setNo resultCount] - $start + 1]
935             } else {
936                 set tnumber $number
937             }
938             if {![lindex $targets($hist($setNo,$i,host)) 5]} {
939                 set thisElements {}
940             } else {
941                 set thisElements $elements
942             }
943             z39$i.$setNo smallSetElementSetNames $thisElements
944             z39$i.$setNo mediumSetElementSetNames $thisElements
945             z39$i.$setNo elementSetNames $thisElements
946             z39$i.$setNo recordElements $thisElements
947
948             for {set n 0} {$n < $tnumber} {incr n} {
949                 if {[z39$i.$setNo recordType [expr $start + $n]] == ""} {
950                     if {$n > 0} {
951                         egw_log debug "failed on $n"
952                     }
953                     if {$debug} {
954                         html "no record at #" [expr $start + $n]
955                         html " el=-" $thisElements "-"
956                     }
957                     break
958                 }
959             }
960             if {$n == $tnumber} {
961                 if {$debug} {
962                     html "cached<br>\n"
963                 }
964                 continue
965             }
966             
967             html "present<br>\n"
968             z39$i.$setNo preferredRecordSyntax USMARC
969             z39$i callback [list search-m-response $setNo $i $start $tnumber]
970             incr zleft
971             egw_log debug "mpresent start=$start number=$tnumber"
972             z39$i.$setNo present $start $tnumber
973         } else {
974             if {$debug} {
975                 html "ok<br>\n"
976             }
977         }
978     }
979     while {$zleft > 0} {
980         egw_log debug "Waiting for search/present response"
981         if {[catch {egw_wait zleft 60}]} {
982             break
983         }
984     }
985     for {set i 1} {$i <= $not} {incr i} {
986         if {$zstatus($i) != 2} continue
987         set status [z39$i.$setNo responseStatus]
988         if {0 && [lindex $status 0] != "NSD"} {
989             set hist($setNo,$i,offset) [z39$i.$setNo numberOfRecordsReturned]
990         }
991     }
992 }
993
994 proc z39present {setNo tno setOffset setMax dfunc elements} {
995     global hist
996     global sessionWait
997     global targets
998
999     if {$tno > 0} {
1000         set zz z39$tno
1001         set host $hist($setNo,$tno,host)
1002     } else {
1003         set zz z39
1004         set host $hist($setNo,host)
1005     }
1006
1007     if {![lindex $targets($host) 5]} {
1008         set elements {}
1009     }
1010
1011     $zz.$setNo elementSetNames $elements
1012     $zz.$setNo recordElements $elements
1013     set toGet [expr 1 + $setMax - $setOffset]
1014
1015     $zz callback [list search-response $zz.$setNo]
1016
1017     while {$setMax > 0 && $toGet > 0} {
1018         for {set got 0} {$got < $toGet} {incr got} {
1019             if {[$zz.$setNo recordType [expr $setOffset + $got]] == ""} {
1020                 break
1021             }
1022         }
1023         if {$got < $toGet} {
1024             set sessionWait 0
1025             $zz.$setNo present $setOffset $toGet
1026             if {[catch {egw_wait sessionWait 300}]} {
1027                 egw_log debug "timeout/cancel in present"
1028                 $zz disconnect
1029                 break
1030             }
1031             if {$sessionWait == "0"} {
1032                 $zz disconnect
1033             }
1034             if {$sessionWait != "1"} {
1035                 break
1036             }
1037             set got [$zz.$setNo numberOfRecordsReturned]
1038             if {$got <= 0} {
1039                 break
1040             }
1041         }
1042         display-rec $setOffset [expr $got + $setOffset - 1] $dfunc $tno
1043         set setOffset [expr $got + $setOffset]
1044         set toGet [expr 1 + $setMax - $setOffset]
1045         egw_flush
1046     }
1047 }
1048
1049 proc z39history {} {
1050     global nextSetNo
1051     global hist
1052     global env
1053     global sessionId
1054     global targets
1055     global html3
1056
1057     if {![info exists nextSetNo]} {
1058         return
1059     }
1060     html "<h2>History</h2><br>\n"
1061     if {$html3} {
1062         html {<table width=500 border=1><tr>}
1063         html {<td align=center><b>Target</b>}
1064         html {<td align=center><b>Database</b>}
1065         html {<td align=center><b>Hits</b>}
1066         html {<td align=center><b>Query</b>}
1067         html {<tr>} "\n"
1068     } else {
1069         html {<dl>} "\n"
1070     }
1071     for {set setNo 1} {$setNo < $nextSetNo} {incr setNo} {
1072         if {$hist($setNo,scan) > 0} continue
1073         set host $hist($setNo,host)
1074         if {$html3} {
1075             html {<td align=left>}
1076         } else {
1077             html {<dt> }
1078         }
1079         html [lindex $targets($host) 0]
1080         if {$html3} {
1081             html {<td align=left>} [join $hist($setNo,database)]
1082         } else {
1083             if {[llength [lindex $targets($host) 1]] > 1} {
1084                 html ": "
1085                 foreach b $hist($setNo,database) {
1086                     html " $b"
1087                 }
1088             }
1089             html {. }
1090         }
1091         if {$html3} {
1092             html {<td align=right>}
1093         }
1094         if {[info exists hist($setNo,hits)]} {
1095             html { <a href="http:} $env(SCRIPT_NAME)
1096             html / $sessionId {/search.egw/} $setNo + 1
1097             html + $hist($setNo,maxPresent)
1098             if {1} {
1099                 html {">} $hist($setNo,hits) {</a>}
1100             } else {
1101                 html {">Result</a>: } $hist($setNo,hits) { hits.}
1102             }
1103         } else {
1104             if {$html3} {
1105                 html {Failed}
1106             } else {
1107                 html {Search failed.}
1108             }
1109         }
1110         if {$html3} {
1111             html {<td align=left>}
1112         } else {
1113             html "<dd>\n"
1114         }
1115         html { <a href="http:} $env(SCRIPT_NAME)
1116         html / $sessionId {/query.egw/} $host + $setNo
1117         if {$html3} {
1118             html {">}
1119         } else {
1120             html {">Query</a>: }
1121         }
1122         set op {}
1123         for {set i 1} {$i <= 3} {incr i} {
1124             if {[string length $hist($setNo,form,entry$i)] > 0} {
1125                 html " <b>" [join $op " "] "</b> "
1126                 html [join $hist($setNo,form,menu$i)] "=" 
1127                 html $hist($setNo,form,entry$i)
1128                 set op $hist($setNo,form,logic$i)
1129             }
1130         }
1131         if {$html3} {
1132             html {</a><tr>} "\n"
1133         }
1134     }
1135     if {$html3} {
1136         html {</table><p>}
1137     } else {
1138         html {</dl>}
1139     }
1140     html "\n"
1141 }
1142
1143 proc displayError {msga msgb} {
1144     html "<p><center>\n"
1145     html {<img src="/egwgif/noway.gif" alt="Error">}
1146     html "<h2>" $msga "</h2>\n"
1147     if {$msgb != ""} {
1148         html "<h3>" $msgb "</h3>\n"
1149     }
1150     html "</center><p>\n"
1151 }
1152
1153 proc button-europagate {} {
1154     global useIcons
1155     html {<a href="http://europagate.dtv.dk/">}
1156     if {$useIcons} {
1157         html {<img src="/egwgif/button-egw.gif" alt="Europagate" border=0></a>}
1158     } else {
1159         html {Europagate</a> | }
1160     }
1161 }
1162
1163 proc button-define-target {more} {
1164     global useIcons
1165     global env
1166     global sessionId
1167
1168     html {<a href="http:} $env(SCRIPT_NAME)
1169     html / $sessionId {/tform.egw}
1170     if {$useIcons} {
1171         html {"><img src="/egwgif/button-define-target.gif" }
1172         html {alt="Define Target" border=0></a>}
1173     } else {
1174         html {">Define Target</a>}
1175         if {$more} {
1176             html " | \n"
1177         } else {
1178             html "\n"
1179         }
1180     }
1181 }
1182
1183 proc button-new-target {more} {
1184     global useIcons
1185     global env
1186     global sessionId
1187     global mMode
1188
1189     html {<a href="http:} $env(SCRIPT_NAME)
1190     html / $sessionId 
1191     if {$mMode} {
1192         html {/mtargets.egw}
1193     } else {
1194         html {/targets.egw}
1195     }
1196     if {$useIcons} {
1197         html {"><img src="/egwgif/button-new-target.gif" }
1198         html {alt="New Target" border=0></a>}
1199     } else {
1200         html {">New Target</a>}
1201         if {$more} {
1202             html " | \n"
1203         } else {
1204             html "\n"
1205         }
1206     }
1207 }
1208
1209 proc button-view-history {more} {
1210     global useIcons
1211     global env
1212     global sessionId
1213     global nextSetNo
1214
1215     html {<a href="http:} $env(SCRIPT_NAME)
1216     html / $sessionId {/history.egw;}
1217     catch { html "/" $nextSetNo}
1218     if {$useIcons} {
1219         html {"><img src="/egwgif/button-view-history.gif" alt="View History" }
1220         html {border=0></a>}
1221     } else {
1222         html {">View History</a>}
1223         if {$more} {
1224             html " | \n"
1225         } else {
1226             html "\n"
1227         }
1228     }
1229 }
1230
1231 proc button-new-query {more setNo} {
1232     global useIcons
1233     global env
1234     global sessionId
1235     global hist
1236     global mMode
1237
1238     html {<a href="http:} $env(SCRIPT_NAME)
1239     html / $sessionId 
1240     if {$mMode} {
1241         html {/mquery.egw/} $setNo
1242     } else {
1243         html {/query.egw/} $hist($setNo,host) + $setNo
1244     }
1245     html {">}
1246     if {$useIcons} {
1247         html {<img src="/egwgif/button-new-query.gif" }
1248         html {alt="New Query" border=0></a>}
1249     } else {
1250         html {New Query</a>}
1251         if {$more} {
1252             html " | \n"
1253         } else {
1254             html "\n"
1255         }
1256     }
1257 }
1258
1259 proc button-scan-window {more setNo} {
1260     global useIcons
1261     global env
1262     global sessionId
1263     global hist
1264
1265     html {<a href="http:} $env(SCRIPT_NAME)
1266     html / $sessionId {/search.egw/} $setNo + {scan} {">}
1267     if {$useIcons} {
1268         html {<img src="/egwgif/button-scan-window.gif" }
1269         html {alt="Scan" border=0></a>}
1270     } else {
1271         html {Scan</a>}
1272         if {$more} {
1273             html " | \n"
1274         } else {
1275             html "\n"
1276         }
1277     }
1278 }
1279
1280 proc maintenance {} {
1281     html {<hr>This page is maintained by }
1282     html {<a href="mailto:pwh@dtv.dk"> Peter Wad Hansen </a>.}
1283     html {Last modified 29. january 1996. <br>}
1284     html {<em> This and the following pages are under construction and }
1285     html {will continue to be so until the end of January 1996.</em>}
1286 }
1287
1288 proc splitHostSpec {host} {
1289     set i [string last . $host]
1290     if {$i > 1} {
1291         incr i -1
1292         return [string range $host 0 $i]
1293     }
1294     return $host
1295 }
1296
1297 proc mergeHostSpec {host databases} {
1298     return ${host}.[join $databases -]
1299 }