Bug fix in client.tcl: didn't save options on clientrc.tcl.
[ir-tcl-moved-to-github.git] / client.tcl
1 #
2 # $Log: client.tcl,v $
3 # Revision 1.24  1995-05-31 08:36:24  adam
4 # Bug fix in client.tcl: didn't save options on clientrc.tcl.
5 # New method: referenceId. More work on scan.
6 #
7 # Revision 1.23  1995/05/29  10:33:41  adam
8 # README and rename of startup script.
9 #
10 # Revision 1.22  1995/05/26  11:44:09  adam
11 # Bugs fixed. More work on MARC utilities and queries. Test
12 # client is up-to-date again.
13 #
14 # Revision 1.21  1995/05/11  15:34:46  adam
15 # Scan request changed a bit. This version works with RLG.
16 #
17 # Revision 1.20  1995/04/21  16:31:57  adam
18 # New radiobutton: protocol (z39v2/SR).
19 #
20 # Revision 1.19  1995/04/18  16:11:50  adam
21 # First version of graphical Scan. Some work on query-by-form.
22 #
23 # Revision 1.18  1995/04/10  10:50:22  adam
24 # Result-set name defaults to suffix of ir-set name.
25 # Started working on scan. Not finished at this point.
26 #
27 # Revision 1.17  1995/03/31  09:34:57  adam
28 # Search-button disabled when there is no connection.
29 #
30 # Revision 1.16  1995/03/31  08:56:36  adam
31 # New button "Search".
32 #
33 # Revision 1.15  1995/03/28  12:45:22  adam
34 # New ir method failback: called on disconnect/protocol error.
35 # New ir set/get method: protocol: SR / Z3950.
36 # Simple popup and disconnect when failback is invoked.
37 #
38 # Revision 1.14  1995/03/22  16:07:55  adam
39 # Minor changes.
40 #
41 # Revision 1.13  1995/03/21  17:27:26  adam
42 # Short-hand keys in setup.
43 #
44 # Revision 1.12  1995/03/21  13:41:03  adam
45 # Comstack cs_create not used too often. Non-blocking connect.
46 #
47 # Revision 1.11  1995/03/21  10:39:06  adam
48 # Diagnostic error message displayed with tkerror.
49 #
50 # Revision 1.10  1995/03/20  15:24:06  adam
51 # Diagnostic records saved on searchResponse.
52 #
53 # Revision 1.9  1995/03/17  18:26:16  adam
54 # Non-blocking i/o used now. Database names popup as cascade items.
55 #
56 # Revision 1.8  1995/03/17  15:45:00  adam
57 # Improved target/database setup.
58 #
59 # Revision 1.7  1995/03/16  17:54:03  adam
60 # Minor changes really.
61 #
62 # Revision 1.6  1995/03/15  19:10:20  adam
63 # Database setup in protocol-setup (rather target setup).
64 #
65 # Revision 1.5  1995/03/15  13:59:23  adam
66 # Minor changes.
67 #
68 # Revision 1.4  1995/03/14  17:32:29  adam
69 # Presentation of full Marc record in popup window.
70 #
71 # Revision 1.3  1995/03/12  19:31:52  adam
72 # Pattern matching implemented when retrieving MARC records. More
73 # diagnostic functions.
74 #
75 # Revision 1.2  1995/03/10  18:00:15  adam
76 # Actual presentation in line-by-line format. RPN query support.
77 #
78 # Revision 1.1  1995/03/09  16:15:07  adam
79 # First presentRequest attempts. Hot-target list.
80 #
81 #
82 set hotTargets {}
83 set hotInfo {}
84 set busy 0
85
86 set profile(Default) {{} {} {210} {} 16384 8192 tcpip {} 1 {} {} z39v2}
87 set hostid Default
88 set settingsChanged 0
89 set setNo 0
90
91 set queryTypes {Simple}
92 set queryButtons { { {I 0} {I 1} {I 2} } }
93 set queryInfo { { {Title {1=4}} {Author {1=1}} \
94         {Subject {1=21}} {Any {1=1016}} } }
95
96 wm minsize . 350 250
97
98 if {[file readable "clientrc.tcl"]} {
99     source "clientrc.tcl"
100 }
101
102 set queryButtonsFind [lindex $queryButtons 0]
103 set queryInfoFind [lindex $queryInfo 0]
104
105 proc top-down-window {w} {
106     frame $w.top -relief raised -border 1
107     frame $w.bot -relief raised -border 1
108     
109     pack  $w.top -side top -fill both -expand yes
110     pack  $w.bot -fill both
111 }
112
113 proc top-down-ok-cancel {w ok-action g} {
114     frame $w.bot.left -relief sunken -border 1
115     pack $w.bot.left -side left -expand yes -padx 5 -pady 5
116     button $w.bot.left.ok -width 6 -text {Ok} \
117             -command ${ok-action}
118     pack $w.bot.left.ok -expand yes -padx 3 -pady 3
119     button $w.bot.cancel -width 6 -text {Cancel} \
120             -command "destroy $w"
121     pack $w.bot.cancel -side left -expand yes    
122
123     if {$g} {
124         # Grab ...
125         grab $w
126         tkwait window $w
127     }
128 }
129
130 proc top-down-ok-cancelx {w buttonList g} {
131     set i 0
132     set l [llength $buttonList]
133
134     frame $w.bot.$i -relief sunken -border 1
135     pack $w.bot.$i -side left -expand yes -padx 5 -pady 5
136     button $w.bot.$i.ok -text [lindex $buttonList $i] \
137             -command [lindex $buttonList [expr $i+1]]
138     pack $w.bot.$i.ok -expand yes -padx 3 -pady 3 -side left
139
140     incr i 2
141     while {$i < $l} {
142         button $w.bot.$i -text [lindex $buttonList $i] \
143                 -command [lindex $buttonList [expr $i+1]]
144         pack $w.bot.$i -expand yes -padx 3 -pady 3 -side left
145         incr i 2
146     }
147     button $w.bot.cancel -width 6 -text {Cancel} \
148             -command "destroy $w"
149     pack $w.bot.cancel -side left -expand yes    
150     
151     if {$g} {
152         # Grab ...
153         grab $w
154         tkwait window $w
155     }
156 }
157
158 proc show-target {target} {
159     .bot.target configure -text "$target"
160 }
161
162 proc show-busy {v1 v2} {
163     global busy
164     if {$busy != 0} {
165         .bot.status configure -fg $v1
166         after 200 [list show-busy $v2 $v1]
167     }
168 }
169         
170 proc show-status {status b} {
171     global busy
172     global statusbg
173     .bot.status configure -text "$status"
174     .bot.status configure -fg black
175     if {$b != 0} {
176         if {$busy == 0} {
177             set busy $b   
178             show-busy red blue
179         }
180         #        . config -cursor {watch black white}
181     } else {
182         #        . config -cursor {top_left_arrow black white}
183         puts "Normal"
184     }
185     set busy $b
186 }
187
188 proc show-message {msg} {
189     .bot.message configure -text "$msg"
190 }
191
192 proc insertWithTags {w text args} {
193     set start [$w index insert]
194     $w insert insert $text
195     foreach tag [$w tag names $start] {
196         $w tag remove $tag $start insert
197     }
198     foreach i $args {
199         $w tag add $i $start insert
200     }
201 }
202
203 proc show-full-marc {no} {
204     global setNo
205
206     set w .full-marc
207
208     if {[winfo exists $w]} {
209         $w.top.record delete 0.0 end
210         set new 0
211     } else {
212
213         toplevel $w
214
215         wm minsize $w 200 200
216         
217         frame $w.top -relief raised -border 1
218         frame $w.bot -relief raised -border 1
219
220         pack  $w.top -side top -fill both -expand yes
221         pack  $w.bot -fill both
222
223         text $w.top.record -width 60 -height 12 -wrap word \
224                 -yscrollcommand [list $w.top.s set]
225         scrollbar $w.top.s -command [list $w.top.record yview]
226
227         set new 1
228     }
229     incr no
230     
231     set r [z39.$setNo getMarc $no list * * *]
232
233     $w.top.record tag configure marc-tag -foreground blue
234     $w.top.record tag configure marc-data -foreground black
235     $w.top.record tag configure marc-id -foreground red
236
237     foreach line $r {
238         set tag [lindex $line 0]
239         set indicator [lindex $line 1]
240         set fields [lindex $line 2]
241
242         if {$indicator != ""} {
243             insertWithTags $w.top.record "$tag $indicator" marc-tag
244         } else {
245             insertWithTags $w.top.record "$tag    " marc-tag
246         }
247         foreach field $fields {
248             set id [lindex $field 0]
249             set data [lindex $field 1]
250             if {$id != ""} {
251                 insertWithTags $w.top.record " $id " marc-id
252             }
253             set start [$w.top.record index insert]
254             insertWithTags $w.top.record $data {}
255         }
256         $w.top.record insert end "\n"
257     }
258     if {$new} {
259         bind $w <Return> {destroy .full-marc}
260         
261         pack $w.top.s -side right -fill y
262         pack $w.top.record -expand yes -fill both
263         
264         frame $w.bot.left -relief sunken -border 1
265         pack $w.bot.left -side left -expand yes -padx 5 -pady 5
266         button $w.bot.left.close -width 6 -text {Close} \
267                 -command {destroy .full-marc}
268         pack $w.bot.left.close -expand yes -padx 3 -pady 3
269         button $w.bot.edit -width 6 -text {Edit} \
270                 -command {destroy .full-marc}
271         pack $w.bot.edit -side left -expand yes
272     }
273 }
274
275 proc update-target-hotlist {target} {
276     global hotTargets
277
278     set len [llength $hotTargets]
279     if {$len > 0} {
280         .top.target.m delete 5 [expr 5+[llength $hotTargets]]
281     }
282     set indx [lsearch $hotTargets $target]
283     if {$indx >= 0} {
284         set hotTargets [lreplace $hotTargets $indx $indx]
285     }
286     set hotTargets [linsert $hotTargets 0 $target]
287     set-target-hotlist    
288
289
290 proc set-target-hotlist {} {
291     global hotTargets
292     
293     set i 1
294     foreach target $hotTargets {
295         .top.target.m add command -label "$i $target" -command \
296                 "reopen-target $target {}"
297         incr i
298         if {$i > 8} {
299              break
300         }
301     }
302 }
303
304 proc reopen-target {target base} {
305     close-target
306     open-target $target $base
307     update-target-hotlist $target
308 }
309
310 proc define-target-action {} {
311     global profile
312
313     set target [.target-define.top.target.entry get]
314     if {$target == ""} {
315         return
316     }
317     update-target-hotlist $target
318     foreach n [array names profile] {
319         if {$n == $target} {
320             protocol-setup $n
321             return
322         }
323     }
324     set profile($target) $profile(Default)
325     protocol-setup $target
326     destroy .target-define
327 }
328
329 proc fail-response {target} {
330     close-target
331     tkerror "Target connection closed or protocol error"
332 }
333
334 proc connect-response {target} {
335     puts "connect-response"
336     show-target $target
337     init-request
338 }
339
340 proc open-target {target base} {
341     global profile
342     global hostid
343
344     z39 disconnect
345     z39 comstack [lindex $profile($target) 6]
346     z39 idAuthentication [lindex $profile($target) 3]
347     z39 maximumRecordSize [lindex $profile($target) 4]
348     z39 preferredMessageSize [lindex $profile($target) 5]
349     puts -nonewline "maximumRecordSize="
350     puts [z39 maximumRecordSize]
351     puts -nonewline "preferredMessageSize="
352     puts [z39 preferredMessageSize]
353     if {$base == ""} {
354         z39 databaseNames [lindex [lindex $profile($target) 7] 0]
355     } else {
356         z39 databaseNames $base
357     }
358     z39 failback [list fail-response $target]
359     z39 callback [list connect-response $target]
360     z39 connect [lindex $profile($target) 1]:[lindex $profile($target) 2]
361     show-status {Connecting} 1
362     set hostid $target
363     .top.target.m disable 0
364     .top.target.m enable 1
365 }
366
367 proc close-target {} {
368     global hostid
369
370     set hostid Default
371     z39 disconnect
372     show-target {None}
373     show-status {Not connected} 0
374     show-message {}
375     .top.target.m disable 1
376     .top.target.m enable 0
377     .top.search configure -state disabled
378     .mid.search configure -state disabled
379     .mid.scan configure -state disabled
380 }
381
382 proc load-set-action {} {
383     global setNo
384
385     incr setNo
386     ir-set z39.$setNo z39
387
388     set fname [.load-set.top.filename.entry get]
389     destroy .load-set
390     if {$fname != ""} {
391         init-title-lines
392
393         show-status {Loading} 1
394         z39.$setNo loadFile $fname
395
396         set no [z39.$setNo numberOfRecordsReturned]
397         add-title-lines $setNo $no 1
398     }
399     show-status {Ready} 0
400 }
401
402 proc load-set {} {
403     set w .load-set
404
405     set oldFocus [focus]
406     toplevel $w
407
408     place-force $w .
409
410     top-down-window $w
411
412     frame $w.top.filename
413     
414     pack $w.top.filename -side top -anchor e -pady 2
415     
416     entry-fields $w.top {filename} \
417             {{Filename:}} \
418             {load-set-action} {destroy .load-set}
419     
420     top-down-ok-cancel $w {load-set-action} 1
421     focus $oldFocus
422 }
423
424 proc init-request {} {
425     global setNo
426     
427     z39 callback {init-response}
428     z39 init
429     show-status {Initializing} 1
430 }
431
432 proc init-response {} {
433     show-status {Ready} 0
434     .top.search configure -state normal
435     .mid.search configure -state normal
436     .mid.scan configure -state normal
437     if {![z39 initResult]} {
438         set u [z39 userInformationField]
439         close-target
440         tkerror "Connection rejected by target: $u"
441     }
442 }
443
444 proc search-request {} {
445     global setNo
446     global profile
447     global hostid
448
449     set target $hostid
450
451     set query [index-query]
452     if {$query==""} {
453         return
454     }
455     incr setNo
456     ir-set z39.$setNo z39
457
458     if {[lindex $profile($target) 10] == 1} {
459         z39.$setNo setName $setNo
460         puts "setName=${setNo}"
461     } else {
462         z39.$setNo setName Default
463         puts "setName=Default"
464     }
465     if {[lindex $profile($target) 8] == 1} {
466         z39.$setNo queryType rpn
467     }
468     if {[lindex $profile($target) 9] == 1} {
469         z39.$setNo queryType ccl
470     }
471     z39 callback {search-response}
472     z39.$setNo search $query
473     show-status {Search} 1
474 }
475
476 proc scan-request {} {
477     set w .scan-window
478
479     global profile
480     global hostid
481
482     set target $hostid
483
484     ir-scan z39.scan z39
485
486     z39 callback {scan-response}
487     if {![winfo exists $w]} {
488         toplevel $w
489         
490         wm title $w "Scan"
491         
492         wm minsize $w 200 200
493
494         top-down-window $w
495         
496         listbox $w.top.list -yscrollcommand [list $w.top.scroll set] \
497                 -font fixed -geometry 50x14
498         scrollbar $w.top.scroll -orient vertical -border 1
499         pack $w.top.list -side left -fill both -expand yes
500         pack $w.top.scroll -side right -fill y
501         $w.top.scroll config -command [list $w.top.list yview]
502
503         top-down-ok-cancelx $w [list {Close} [list destroy $w]] 0 
504     }
505     z39.scan numberOfTermsRequested 100
506     z39.scan scan "@attr 1=4 0"
507     
508     show-status {Scan} 1
509 }
510
511 proc scan-response {} {
512     set w .scan-window
513     set m [z39.scan numberOfEntriesReturned]
514     puts $m
515     for {set i 0} {$i < $m} {incr i} {
516         set term [lindex [z39.scan scanLine $i] 1]
517         set nostr [format "%7d" [lindex [z39.scan scanLine $i] 2]]
518
519         $w.top.list insert end "$nostr $term"
520     }
521     show-status {Ready} 0
522 }
523
524 proc search-response {} {
525     global setNo
526     global setOffset
527     global setMax
528
529     init-title-lines
530     show-status {Ready} 0
531     show-message "[z39.$setNo resultCount] hits"
532     set setMax [z39.$setNo resultCount]
533     puts $setMax
534     if {$setMax == 0} {
535         set status [z39.$setNo responseStatus]
536         if {[lindex $status 0] == "NSD"} {
537             set code [lindex $status 1]
538             set msg [lindex $status 2]
539             set addinfo [lindex $status 3]
540             tkerror "NSD$code: $msg: $addinfo"
541         }
542         return
543     }
544     if {$setMax > 4} {
545         set setMax 4
546     }
547     z39 callback {present-response}
548     set setOffset 1
549     z39.$setNo present $setOffset $setMax
550     show-status {Retrieve} 1
551 }
552
553 proc present-more {number} {
554     global setNo
555     global setOffset
556     global setMax
557
558     puts "present-more"
559     if {$setNo == 0} {
560         return
561     }
562     set max [z39.$setNo resultCount]
563     if {$max <= $setMax} {
564         return
565     }
566     puts "max=$max"
567     puts "setOffset=$setOffset"
568     if {$number == ""} {
569         set setMax $max
570     } else {
571         incr setMax $number
572     }
573     z39 callback {present-response}
574     z39.$setNo present $setOffset [expr $setMax - $setOffset + 1]
575     show-status {Retrieve} 1
576 }
577
578 proc init-title-lines {} {
579     .data.list delete 0 end
580 }
581
582 proc add-title-lines {setno no offset} {
583     for {set i 0} {$i < $no} {incr i} {
584         set o [expr $i + $offset]
585         set title [lindex [z39.$setno getMarc $o field 245 * a] 0]
586         set year  [lindex [z39.$setno getMarc $o field 260 * c] 0]
587         set nostr [format "%5d" $o]
588         .data.list insert end "$nostr $title - $year"
589     }
590 }
591
592 proc present-response {} {
593     global setNo
594     global setOffset
595     global setMax
596
597     puts "In present-response"
598     set no [z39.$setNo numberOfRecordsReturned]
599     puts "Returned $no records, setOffset $setOffset"
600     add-title-lines $setNo $no $setOffset
601     set setOffset [expr $setOffset + $no]
602     set status [z39.$setNo responseStatus]
603     if {[lindex $status 0] == "NSD"} {
604         show-status {Ready} 0
605         set code [lindex $status 1]
606         set msg [lindex $status 2]
607         set addinfo [lindex $status 3]
608         tkerror "NSD$code: $msg: $addinfo"
609         return
610     }
611     if {$no > 0 && $setOffset <= $setMax} {
612         z39.$setNo present $setOffset [expr $setMax - $setOffset + 1]
613     } else {
614         show-status {Finished} 0
615     }
616 }
617
618 proc left-cursor {w} {
619     set i [$w index insert]
620     if {$i > 0} {
621         incr i -1
622         $w icursor $i
623     }
624 }
625
626 proc right-cursor {w} {
627     set i [$w index insert]
628     incr i
629     $w icursor $i
630 }
631
632 proc bind-fields {list returnAction escapeAction} {
633     set max [expr [llength $list]-1]
634     for {set i 0} {$i < $max} {incr i} {
635         bind [lindex $list $i] <Return> $returnAction
636         bind [lindex $list $i] <Escape> $escapeAction
637         bind [lindex $list $i] <Tab> [list focus [lindex $list [expr $i+1]]]
638         bind [lindex $list $i] <Left> [list left-cursor [lindex $list $i]]
639         bind [lindex $list $i] <Right> [list right-cursor [lindex $list $i]]
640     }
641     bind [lindex $list $i] <Return> $returnAction
642     bind [lindex $list $i] <Escape> $escapeAction
643     bind [lindex $list $i] <Tab>    [list focus [lindex $list 0]]
644     bind [lindex $list $i] <Left> [list left-cursor [lindex $list $i]]
645     bind [lindex $list $i] <Right> [list right-cursor [lindex $list $i]]
646     focus [lindex $list 0]
647 }
648
649 proc entry-fields {parent list tlist returnAction escapeAction} {
650     set alist {}
651     set i 0
652     foreach field $list {
653         set label ${parent}.${field}.label
654         set entry ${parent}.${field}.entry
655         label $label -text [lindex $tlist $i] -anchor e
656         entry $entry -width 32 -relief sunken
657         pack $label -side left
658         pack $entry -side right
659         lappend alist $entry
660         incr i
661     }
662     bind-fields $alist $returnAction $escapeAction
663 }
664
665 proc define-target-dialog {} {
666     set w .target-define
667
668     toplevel $w
669     place-force $w .
670     top-down-window $w
671     frame $w.top.target
672     pack $w.top.target \
673             -side top -anchor e -pady 2 
674     entry-fields $w.top {target} \
675             {{Target:}} \
676             {define-target-action} {destroy .target-define}
677     top-down-ok-cancel $w {define-target-action} 1
678 }
679
680 proc protocol-setup-action {target} {
681     global profile
682     global csRadioType
683     global protocolRadioType
684     global settingsChanged
685     global RPNCheck
686     global CCLCheck
687     global ResultSetCheck
688
689     set w .setup-${target}.top
690
691     #set w .protocol-setup.top
692     
693     set b {}
694     set settingsChanged 1
695     set len [$w.databases.list size]
696     for {set i 0} {$i < $len} {incr i} {
697         lappend b [$w.databases.list get $i]
698     }
699     set profile($target) [list [$w.description.entry get] \
700             [$w.host.entry get] \
701             [$w.port.entry get] \
702             [$w.idAuthentication.entry get] \
703             [$w.maximumRecordSize.entry get] \
704             [$w.preferredMessageSize.entry get] \
705             $csRadioType \
706             $b \
707             $RPNCheck \
708             $CCLCheck \
709             $ResultSetCheck \
710             $protocolRadioType ]
711
712     cascade-target-list
713     puts $profile($target)
714     destroy .setup-${target}
715 }
716
717 proc place-force {window parent} {
718     set g [wm geometry $parent]
719
720     set p1 [string first + $g]
721     set p2 [string last + $g]
722
723     set x [expr 40+[string range $g [expr $p1 +1] [expr $p2 -1]]]
724     set y [expr 60+[string range $g [expr $p2 +1] end]]
725     wm geometry $window +${x}+${y}
726 }
727
728 proc add-database-action {target} {
729     set w .setup-${target}
730     
731     ${w}.top.databases.list insert end \
732             [.database-select.top.database.entry get]
733     destroy .database-select
734 }
735
736 proc add-database {target} {
737     set w .database-select
738
739     set oldFocus [focus]
740     toplevel $w
741
742     place-force $w .setup-${target}
743
744     top-down-window $w
745
746     frame $w.top.database
747
748     pack $w.top.database -side top -anchor e -pady 2
749     
750     entry-fields $w.top {database} \
751             {{Database to add:}} \
752             [list add-database-action $target] {destroy .database-select}
753
754     top-down-ok-cancel $w [list add-database-action $target] 1
755     focus $oldFocus
756 }
757
758 proc delete-database {target} {
759     set w .setup-${target}
760     
761     foreach i [lsort -decreasing \
762             [$w.top.databases.list curselection]] {
763         $w.top.databases.list delete $i
764     }
765 }
766
767 proc protocol-setup {target} {
768     set w .setup-$target
769
770     global profile
771     global csRadioType
772     global protocolRadioType
773     global RPNCheck
774     global CCLCheck
775     global ResultSetCheck
776
777     toplevel $w
778
779     wm title $w "Setup $target"
780     place-force $w .
781
782     top-down-window $w
783     
784     if {$target == ""} {
785         set target Default
786     }
787     puts target
788     puts $profile($target)
789
790     frame $w.top.host
791     frame $w.top.port
792     frame $w.top.description
793     frame $w.top.idAuthentication
794     frame $w.top.maximumRecordSize
795     frame $w.top.preferredMessageSize
796     frame $w.top.cs-type -relief ridge -border 2
797     frame $w.top.protocol -relief ridge -border 2
798     frame $w.top.query -relief ridge -border 2
799     frame $w.top.databases -relief ridge -border 2
800
801     # Maximum/preferred/idAuth ...
802     pack $w.top.description $w.top.host $w.top.port \
803             $w.top.idAuthentication $w.top.maximumRecordSize \
804             $w.top.preferredMessageSize -side top -anchor e -pady 2
805     
806     entry-fields $w.top {description host port idAuthentication \
807             maximumRecordSize preferredMessageSize} \
808             {{Description:} {Host:} {Port:} {Id Authentication:} \
809             {Maximum Record Size:} {Preferred Message Size:}} \
810             [list protocol-setup-action $target] [list destroy $w]
811     
812     foreach sub {description host port idAuthentication \
813             maximumRecordSize preferredMessageSize} {
814         puts $sub
815         bind $w.top.$sub.entry <Control-a> "add-database $target"
816         bind $w.top.$sub.entry <Control-d> "delete-database $target"
817     }
818     $w.top.description.entry insert 0 [lindex $profile($target) 0]
819     $w.top.host.entry insert 0 [lindex $profile($target) 1]
820     $w.top.port.entry insert 0 [lindex $profile($target) 2]
821     $w.top.idAuthentication.entry insert 0 [lindex $profile($target) 3]
822     $w.top.maximumRecordSize.entry insert 0 [lindex $profile($target) 4]
823     $w.top.preferredMessageSize.entry insert 0 [lindex $profile($target) 5]
824     set csRadioType [lindex $profile($target) 6]
825     set RPNCheck [lindex $profile($target) 8]
826     set CCLCheck [lindex $profile($target) 9]
827     set ResultSetCheck [lindex $profile($target) 10]
828     set protocolRadioType [lindex $profile($target) 11]
829     if {$protocolRadioType == ""} {
830         set protocolRadioType z39v2
831     }
832
833     # Databases ....
834     pack $w.top.databases -side left -pady 6 -padx 6 -expand yes -fill both
835
836     label $w.top.databases.label -text "Databases"
837     button $w.top.databases.add -text "Add" \
838             -command "add-database $target"
839     button $w.top.databases.delete -text "Delete" \
840             -command "delete-database $target"
841     listbox $w.top.databases.list -geometry 20x6 \
842             -yscrollcommand "$w.top.databases.scroll set"
843     scrollbar $w.top.databases.scroll -orient vertical -border 1
844     pack $w.top.databases.label -side top -fill x \
845             -padx 2 -pady 2
846     pack $w.top.databases.add $w.top.databases.delete -side top -fill x \
847             -padx 2 -pady 2
848     pack $w.top.databases.list -side left -fill both -expand yes \
849             -padx 2 -pady 2
850     pack $w.top.databases.scroll -side right -fill y \
851             -padx 2 -pady 2
852     $w.top.databases.scroll config -command "$w.top.databases.list yview"
853
854     foreach b [lindex $profile($target) 7] {
855         $w.top.databases.list insert end $b
856     }
857
858     # Transport ...
859     pack $w.top.cs-type -pady 6 -padx 6 -side top -fill x
860     
861     label $w.top.cs-type.label -text "Transport" 
862     radiobutton $w.top.cs-type.tcpip -text "TCP/IP" -anchor w \
863             -command {puts tcp/ip} -variable csRadioType -value tcpip
864     radiobutton $w.top.cs-type.mosi -text "MOSI" -anchor w\
865             -command {puts mosi} -variable csRadioType -value mosi
866     
867     pack $w.top.cs-type.label $w.top.cs-type.tcpip $w.top.cs-type.mosi \
868             -padx 4 -side top -fill x
869
870     # Protocol ...
871     pack $w.top.protocol -pady 6 -padx 6 -side top -fill x
872     
873     label $w.top.protocol.label -text "Protocol" 
874     radiobutton $w.top.protocol.z39v2 -text "Z39.50" -anchor w \
875             -command {puts z39v2} -variable protocolRadioType -value z39v2
876     radiobutton $w.top.protocol.sr -text "SR" -anchor w \
877             -command {puts sr} -variable protocolRadioType -value sr
878     
879     pack $w.top.protocol.label $w.top.protocol.z39v2 $w.top.protocol.sr \
880             -padx 4 -side top -fill x
881
882     # Query ...
883     pack $w.top.query -pady 6 -padx 6 -side top -fill x
884
885     label $w.top.query.label -text "Query support"
886     checkbutton $w.top.query.c1 -text "RPN query" -anchor w -variable RPNCheck
887     checkbutton $w.top.query.c2 -text "CCL query" -anchor w -variable CCLCheck
888     checkbutton $w.top.query.c3 -text "Result sets" -anchor w -variable ResultSetCheck
889
890     pack $w.top.query.label -side top 
891     pack $w.top.query.c1 $w.top.query.c2 $w.top.query.c3 \
892             -padx 4 -side top -fill x
893
894     # Ok-cancel
895     top-down-ok-cancel $w [list protocol-setup-action $target] 0
896 }
897
898 proc database-select-action {} {
899     set w .database-select.top
900     set b {}
901     foreach indx [$w.databases.list curselection] {
902         lappend b [$w.databases.list get $indx]
903     }
904     if {$b != ""} {
905         z39 databaseNames $b
906     }
907     destroy .database-select
908 }
909
910 proc database-select {} {
911     set w .database-select
912     global profile
913     global hostid
914
915     toplevel $w
916
917     place-force $w .
918
919     top-down-window $w
920
921     frame $w.top.databases -relief ridge -border 2
922
923     pack $w.top.databases -side left -pady 6 -padx 6 -expand yes -fill x
924
925     label $w.top.databases.label -text "List"
926     listbox $w.top.databases.list -geometry 20x6 \
927             -yscrollcommand "$w.top.databases.scroll set"
928     scrollbar $w.top.databases.scroll -orient vertical -border 1
929     pack $w.top.databases.label -side top -fill x \
930             -padx 2 -pady 2
931     pack $w.top.databases.list -side left -fill both -expand yes \
932             -padx 2 -pady 2
933     pack $w.top.databases.scroll -side right -fill y \
934             -padx 2 -pady 2
935     $w.top.databases.scroll config -command "$w.top.databases.list yview"
936
937     foreach b [lindex $profile($hostid) 7] {
938         $w.top.databases.list insert end $b
939     }
940     top-down-ok-cancel $w {database-select-action} 1
941 }
942
943 proc cascade-target-list {} {
944     global profile
945     
946     foreach sub [winfo children .top.target.m.clist] {
947         puts "deleting $sub"
948         destroy $sub
949     }
950     .top.target.m.clist delete 0 last
951     foreach n [array names profile] {
952         if {$n != "Default"} {
953             set nl [string tolower $n]
954             if {[llength [lindex $profile($n) 7]] > 1} {
955                 .top.target.m.clist add cascade -label $n \
956                         -menu .top.target.m.clist.$nl
957                 menu .top.target.m.clist.$nl
958                 foreach b [lindex $profile($n) 7] {
959                     .top.target.m.clist.$nl add command -label $b \
960                             -command "reopen-target $n $b"
961                 }
962             } else {
963                 .top.target.m.clist add command -label $n \
964                         -command "reopen-target $n {}"
965             }
966         }
967     }
968     .top.target.m.slist delete 0 last
969     foreach n [array names profile] {
970         if {$n != "Default"} {
971             .top.target.m.slist add command -label $n \
972                     -command "protocol-setup $n"
973         }
974     }
975 }
976
977 proc cascade-query-list {} {
978     global queryTypes
979
980     set i 0
981     .top.query.m.slist delete 0 last
982     foreach n $queryTypes {
983         .top.query.m.slist add command -label $n \
984                 -command [list query-setup $i]
985         incr i
986     }
987
988     set i 0
989     .top.query.m.clist delete 0 last
990     foreach n $queryTypes {
991         .top.query.m.clist add command -label $n \
992                 -command [list query-select $i]
993         incr i
994     }
995 }
996
997 proc save-settings {} {
998     global hotTargets 
999     global profile
1000     global settingsChanged
1001     global queryTypes
1002     global queryButtons
1003     global queryInfo
1004
1005     set f [open "clientrc.tcl" w]
1006     puts $f "# Setup file"
1007     puts $f "set hotTargets \{ $hotTargets \}"
1008
1009     foreach n [array names profile] {
1010         puts -nonewline $f "set profile($n) \{"
1011         puts -nonewline $f $profile($n)
1012         puts $f "\}"
1013     }
1014     puts -nonewline $f "set queryTypes \{" 
1015     puts -nonewline $f $queryTypes
1016     puts $f "\}"
1017     
1018     puts -nonewline $f "set queryButtons \{" 
1019     puts -nonewline $f $queryButtons
1020     puts $f "\}"
1021     
1022     puts -nonewline $f "set queryInfo \{"
1023     puts -nonewline $f $queryInfo
1024     puts $f "\}"
1025     
1026     close $f
1027     set settingsChanged 0
1028 }
1029
1030 proc alert {ask} {
1031     set w .alert
1032
1033     global alertAnswer
1034
1035     toplevel $w
1036     place-force $w .
1037     top-down-window $w
1038
1039     message $w.top.message -text $ask
1040
1041     pack $w.top.message -side left -pady 6 -padx 20 -expand yes -fill x
1042   
1043     set alertAnswer 0
1044     top-down-ok-cancel $w {alert-action} 1
1045     return $alertAnswer
1046 }
1047
1048 proc alert-action {} {
1049     global alertAnswer
1050     set alertAnswer 1
1051     destroy .alert
1052 }
1053
1054 proc exit-action {} {
1055     global settingsChanged
1056
1057     if {$settingsChanged} {
1058         set a [alert "you havent saved your settings. Do you wish to save?"]
1059         if {$a} {
1060             save-settings
1061         }
1062     }
1063     destroy .
1064 }
1065
1066 proc listbuttonaction {w name h user i} {
1067     $w configure -text [lindex $name 0]
1068     $h [lindex $name 1] $user $i
1069 }
1070     
1071 proc listbuttonx {button no names handle user} {
1072     if {[winfo exists $button]} {
1073         $button configure -text [lindex [lindex $names $no] 0]
1074         ${button}.m delete 0 last
1075     } else {
1076         menubutton $button -text [lindex [lindex $names $no] 0] \
1077                 -width 10 -menu ${button}.m -relief raised -border 1
1078         menu ${button}.m
1079     }
1080     set i 0
1081     foreach name $names {
1082         ${button}.m add command -label [lindex $name 0] \
1083                 -command [list listbuttonaction ${button} $name \
1084                 $handle $user $i]
1085         incr i
1086     }
1087 }
1088
1089 proc listbutton {button no names} {
1090     menubutton $button -text [lindex $names $no] -width 10 -menu ${button}.m \
1091             -relief raised -border 1
1092     menu ${button}.m
1093     foreach name $names {
1094         ${button}.m add command -label $name \
1095                 -command [list ${button} configure -text $name]
1096     }
1097 }
1098
1099 proc query-add-index-action {queryNo} {
1100     set w .setup-query-$queryNo
1101
1102     global queryInfoTmp
1103     global queryButtonsTmp
1104
1105     lappend queryInfoTmp [list [.query-add-index.top.index.entry get] {}]
1106
1107     destroy .query-add-index
1108     #destroy $w.top.lines
1109     #frame $w.top.lines -relief ridge -border 2
1110     index-lines $w.top.lines 0 $queryButtonsTmp $queryInfoTmp activate-e-index
1111     #pack $w.top.lines -side left -pady 6 -padx 6 -fill y
1112 }
1113
1114 proc query-add-line {queryNo} {
1115     set w .setup-query-$queryNo
1116
1117     global queryInfoTmp
1118     global queryButtonsTmp
1119
1120     lappend queryButtonsTmp {I 0}
1121
1122     #destroy $w.top.lines
1123     #frame $w.top.lines -relief ridge -border 2
1124     index-lines $w.top.lines 0 $queryButtonsTmp $queryInfoTmp activate-e-index
1125     #pack $w.top.lines -side left -pady 6 -padx 6 -fill y
1126 }
1127
1128 proc query-del-line {queryNo} {
1129     set w .setup-query-$queryNo
1130
1131     global queryInfoTmp
1132     global queryButtonsTmp
1133
1134     set l [llength $queryButtonsTmp]
1135     if {$l <= 0} {
1136         return
1137     }
1138     incr l -1
1139     set queryButtonsTmp [lreplace $queryButtonsTmp $l $l]
1140     index-lines $w.top.lines 0 $queryButtonsTmp $queryInfoTmp activate-e-index
1141 }
1142
1143 proc query-add-index {queryNo} {
1144     set w .query-add-index
1145
1146     toplevel $w
1147     place-force $w .setup-query-$queryNo
1148     top-down-window $w
1149     frame $w.top.index
1150     pack $w.top.index \
1151             -side top -anchor e -pady 2 
1152     entry-fields $w.top {index} \
1153             {{Index Name:}} \
1154             [list query-add-index-action $queryNo] {destroy .query-add-index}
1155     top-down-ok-cancel $w [list query-add-index-action $queryNo] 1
1156 }
1157
1158 proc query-setup-action {queryNo} {
1159     global queryButtons
1160     global queryInfo
1161     global queryButtonsTmp
1162     global queryInfoTmp
1163     global queryButtonsFind
1164     global queryInfoFind
1165
1166     set queryInfo [lreplace $queryInfo $queryNo $queryNo \
1167             $queryInfoTmp]
1168     set queryButtons [lreplace $queryButtons $queryNo $queryNo \
1169             $queryButtonsTmp]
1170     set queryInfoFind $queryInfoTmp
1171     set queryButtonsFind $queryButtonsTmp
1172
1173     puts $queryInfo
1174     puts $queryButtons
1175     destroy .setup-query-$queryNo
1176
1177     index-lines .lines 1 $queryButtonsFind $queryInfoFind activate-index
1178 }
1179
1180 proc activate-e-index {value no i} {
1181     global queryButtonsTmp
1182     
1183     puts $queryButtonsTmp
1184     set queryButtonsTmp [lreplace $queryButtonsTmp $no $no [list I $i]]
1185     puts $queryButtonsTmp
1186     puts "value $value"
1187     puts "no $no"
1188     puts "i $i"
1189 }
1190
1191 proc activate-index {value no i} {
1192     global queryButtonsFind
1193
1194     set queryButtonsFind [lreplace $queryButtonsFind $no $no [list I $i]]
1195
1196     puts "queryButtonsFind $queryButtonsFind"
1197     puts "value $value"
1198     puts "no $no"
1199     puts "i $i"
1200 }
1201
1202 proc query-setup {queryNo} {
1203     set w .setup-query-$queryNo
1204     global queryTypes
1205     set queryTypes {Simple}
1206     global queryButtons
1207     global queryInfo
1208     global queryButtonsTmp
1209     global queryInfoTmp
1210
1211     set queryName [lindex $queryTypes $queryNo]
1212     set queryInfoTmp [lindex $queryInfo $queryNo]
1213     set queryButtonsTmp [lindex $queryButtons $queryNo]
1214
1215     #set queryButtons { {I 0 I 1 I 2} }
1216     #set queryInfo { { {Title ti} {Author au} {Subject sh} } }
1217
1218     toplevel $w
1219
1220     wm title $w "Query setup $queryName"
1221     place-force $w .
1222
1223     top-down-window $w
1224
1225     frame $w.top.lines -relief ridge -border 2
1226     frame $w.top.use -relief ridge -border 2
1227     frame $w.top.relation -relief ridge -border 2
1228     frame $w.top.position -relief ridge -border 2
1229     frame $w.top.structure -relief ridge -border 2
1230     frame $w.top.truncation -relief ridge -border 2
1231     frame $w.top.completeness -relief ridge -border 2
1232
1233     # Index Lines
1234
1235     index-lines $w.top.lines 0 $queryButtonsTmp $queryInfoTmp activate-e-index
1236
1237     pack $w.top.lines -side left -pady 6 -padx 6 -fill y
1238
1239     # Use Attributes
1240     pack $w.top.use -side left -pady 6 -padx 6 -fill y
1241
1242     label $w.top.use.label -text "Use"
1243     listbox $w.top.use.list -geometry 20x10 \
1244             -yscrollcommand "$w.top.use.scroll set"
1245     scrollbar $w.top.use.scroll -orient vertical -border 1
1246     pack $w.top.use.label -side top -fill x \
1247             -padx 2 -pady 2
1248     pack $w.top.use.list -side left -fill both -expand yes \
1249             -padx 2 -pady 2
1250     pack $w.top.use.scroll -side right -fill y \
1251             -padx 2 -pady 2
1252     $w.top.use.scroll config -command "$w.top.use.list yview"
1253
1254     foreach u {{Personal name} {Corporate name}} {
1255         $w.top.use.list insert end $u
1256     }
1257     # Relation Attributes
1258     pack $w.top.relation -pady 6 -padx 6 -side top
1259
1260     label $w.top.relation.label -text "Relation" -width 18
1261     
1262     listbutton $w.top.relation.b 0\
1263             {{None} {Less than} {Greater than or equal} \
1264             {Equal} {Greater than or equal} {Greater than} {Not equal} \
1265             {Phonetic} \
1266             {Stem} {Relevance} {AlwaysMatches}}
1267     
1268     pack $w.top.relation.label $w.top.relation.b -fill x 
1269
1270     # Position Attributes
1271     pack $w.top.position -pady 6 -padx 6 -side top
1272
1273     label $w.top.position.label -text "Position" -width 18
1274
1275     listbutton $w.top.position.b 0 {{None} {First in field} {First in subfield}
1276     {Any position in field}}
1277     
1278     pack $w.top.position.label $w.top.position.b -fill x
1279
1280     # Structure Attributes
1281
1282     pack $w.top.structure -pady 6 -padx 6 -side top
1283     
1284     label $w.top.structure.label -text "Structure" -width 18
1285
1286     listbutton $w.top.structure.b 0 {{None} {Phrase} {Word} {Key} {Year}
1287     {Date (norm)} {Word list} {Date (un-norm)} {Name (norm)} {Date (un-norm)}
1288     {Structure} {urx} {free-form} {doc-text} {local-number} {string}
1289     {numeric string}}
1290
1291     pack $w.top.structure.label $w.top.structure.b -fill x
1292
1293     # Truncation Attributes
1294
1295     pack $w.top.truncation -pady 6 -padx 6 -side top
1296     
1297     label $w.top.truncation.label -text "Truncation" -width 18
1298
1299     listbutton $w.top.truncation.b 0 {{Auto} {Right} {Left} {Left and right} \
1300             {No truncation} {Process #} {Re-1} {Re-2}}
1301     pack $w.top.truncation.label $w.top.truncation.b -fill x
1302
1303     # Completeness Attributes
1304
1305     pack $w.top.completeness -pady 6 -padx 6 -side top
1306     
1307     label $w.top.completeness.label -text "Truncation" -width 18
1308
1309     listbutton $w.top.completeness.b 0 {{None} {Incomplete subfield} \
1310             {Complete subfield} {Complete field}}
1311     pack $w.top.completeness.label $w.top.completeness.b -fill x
1312
1313     # Ok-cancel
1314     top-down-ok-cancelx $w [list \
1315             {Ok} [list query-setup-action $queryNo] \
1316             {Add index} [list query-add-index $queryNo] \
1317             {Add line} [list query-add-line $queryNo] \
1318             {Delete line} [list query-del-line $queryNo]] 0
1319 }
1320
1321 proc index-clear {} {
1322     global queryButtonsFind
1323
1324     set i 0
1325     foreach b $queryButtonsFind {
1326         .lines.$i.e delete 0 end
1327         incr i
1328     }
1329 }
1330     
1331 proc index-query {} {
1332     global queryButtonsFind
1333     global queryInfoFind
1334
1335     set i 0
1336     set qs {}
1337
1338     foreach b $queryButtonsFind {
1339         set term [string trim [.lines.$i.e get]]
1340         if {$term != ""} {
1341             set attr [lindex [lindex $queryInfoFind [lindex $b 1]] 1]
1342
1343             set term "\{${term}\}"
1344             foreach a $attr {
1345                 set term "@attr $a ${term}"
1346             }
1347             if {$qs != ""} {
1348                 set qs "@and ${qs} ${term}"
1349             } else {
1350                 set qs $term
1351             }
1352         }
1353         incr i
1354     }
1355     puts "qs=  $qs"
1356     return $qs
1357 }
1358
1359 proc index-lines {w realOp buttonInfo queryInfo handle} {
1360     set i 0
1361     foreach b $buttonInfo {
1362         if {! [winfo exists $w.$i]} {
1363             frame $w.$i -background white -border 1
1364         }
1365         listbuttonx $w.$i.l [lindex $b 1] $queryInfo $handle $i
1366
1367         if {$realOp} {
1368             if {! [winfo exists $w.$i.e]} {
1369                 entry $w.$i.e -width 32 -relief sunken -border 1
1370                 bind $w.$i.e <FocusIn> [list $w.$i configure \
1371                         -background red]
1372                 bind $w.$i.e <FocusOut> [list $w.$i configure \
1373                         -background white]
1374                 pack $w.$i.l -side left
1375                 pack $w.$i.e -side left -fill x -expand yes
1376                 pack $w.$i -side top -fill x -padx 2 -pady 2
1377                 bind $w.$i.e <Left> [list left-cursor $w.$i.e]
1378                 bind $w.$i.e <Right> [list right-cursor $w.$i.e]
1379                 bind $w.$i.e <Return> search-request
1380             }
1381         } else {
1382             pack $w.$i.l -side left
1383             pack $w.$i -side top -fill x -padx 2 -pady 2
1384         }
1385         incr i
1386     }
1387     set j $i
1388     while {[winfo exists $w.$j]} {
1389         destroy $w.$j
1390         incr j
1391     }
1392     if {! $realOp} {
1393         return
1394     }
1395     set j 0
1396     incr i -1
1397     while {$j < $i} {
1398         set k [expr $j+1]
1399         bind $w.$j.e <Tab> "focus $w.$k.e"
1400         set j $k
1401     }
1402     if {$i >= 0} {
1403         bind $w.$i.e <Tab> "focus $w.0.e"
1404         focus $w.0.e
1405     }
1406 }
1407
1408 proc search-fields {w buttondefs} {
1409     set i 0
1410     foreach buttondef $buttondefs {
1411         frame $w.$i -background white
1412         
1413         listbutton $w.$i.l 0 $buttondef
1414         entry $w.$i.e -width 32 -relief sunken
1415         
1416         pack $w.$i.l -side left
1417         pack $w.$i.e -side left -fill x -expand yes
1418
1419         pack $w.$i -side top -fill x -padx 2 -pady 2
1420
1421         bind $w.$i.e <Left> [list left-cursor $w.$i.e]
1422         bind $w.$i.e <Right> [list right-cursor $w.$i.e]
1423
1424         incr i
1425     }
1426     set j 0
1427     incr i -1
1428     while {$j < $i} {
1429         set k [expr $j+1]
1430         bind $w.$j.e <Tab> "focus $w.$k.e \n
1431         $w.$k configure -background red \n
1432         $w.$j configure -background white"
1433         set j $k
1434     }
1435     bind $w.$i.e <Tab> "focus $w.0.e \n
1436         $w.0 configure -background red \n
1437         $w.$i configure -background white"
1438     focus $w.0.e
1439     $w.0 configure -background red
1440 }
1441
1442 frame .top  -border 1 -relief raised
1443 frame .lines  -border 1 -relief raised
1444 frame .mid  -border 1 -relief raised
1445 frame .data -border 1 -relief raised
1446 frame .bot  -border 1 -relief raised
1447 pack .top .lines .mid -side top -fill x
1448 pack .data -side top -fill both -expand yes
1449 pack .bot -fill x
1450
1451 menubutton .top.file -text "File" -underline 0 -menu .top.file.m
1452 menu .top.file.m
1453 .top.file.m add command -label "Save settings" -command {save-settings}
1454 .top.file.m add command -label "Load Set" -command {load-set}
1455 .top.file.m add separator
1456 .top.file.m add command -label "Exit" -command {exit-action}
1457
1458 menubutton .top.target -text "Target" -underline 0 -menu .top.target.m
1459 menu .top.target.m
1460 .top.target.m add cascade -label "Connect" -menu .top.target.m.clist
1461 .top.target.m add command -label "Disconnect" -command {close-target}
1462 #.top.target.m add command -label "Initialize" -command {init-request}
1463 .top.target.m add cascade -label "Setup" -menu .top.target.m.slist
1464 .top.target.m add command -label "Setup new" -command {define-target-dialog}
1465 .top.target.m add separator
1466 set-target-hotlist
1467
1468 .top.target.m disable 1
1469
1470 menu .top.target.m.clist
1471 menu .top.target.m.slist
1472 cascade-target-list
1473
1474 menubutton .top.search -text "Search" -underline 0 -menu .top.search.m
1475 menu .top.search.m
1476 .top.search.m add command -label "Database" -command {database-select}
1477 .top.search.m add cascade -label "Query type" -menu .top.search.m.querytype
1478 menu .top.search.m.querytype
1479 .top.search.m.querytype add radiobutton -label "RPN"
1480 .top.search.m.querytype add radiobutton -label "CCL"
1481 .top.search.m add cascade -label "Present" -menu .top.search.m.present
1482 menu .top.search.m.present
1483 .top.search.m.present add command -label "More" -command [list present-more 10]
1484 .top.search.m.present add command -label "All" -command [list present-more {}]
1485 .top.search configure -state disabled
1486
1487 menubutton .top.query -text "Query" -underline 0 -menu .top.query.m
1488 menu .top.query.m
1489 .top.query.m add cascade -label "Choose" -menu .top.query.m.clist
1490 .top.query.m add command -label "Define" -command {new-query-dialog}
1491 .top.query.m add cascade -label "Edit" -menu .top.query.m.slist
1492 menu .top.query.m.clist
1493 menu .top.query.m.slist
1494 cascade-query-list
1495
1496 menubutton .top.help -text "Help" -menu .top.help.m
1497 menu .top.help.m
1498
1499 .top.help.m add command -label "Help on help" -command {puts "Help on help"}
1500 .top.help.m add command -label "About" -command {puts "About"}
1501
1502 pack .top.file .top.target .top.query .top.search -side left
1503 pack .top.help -side right
1504
1505 index-lines .lines 1 $queryButtonsFind [lindex $queryInfo 0] activate-index
1506
1507 button .mid.search -width 6 -text {Search} -command search-request \
1508         -state disabled
1509 button .mid.scan -width 6 -text {Scan} -command scan-request \
1510         -state disabled
1511 button .mid.clear -width 6 -text {Clear} -command index-clear
1512 pack .mid.search .mid.scan .mid.clear -side left -padx 5 -pady 3
1513
1514 listbox .data.list -yscrollcommand {.data.scroll set} -font fixed
1515 scrollbar .data.scroll -orient vertical -border 1
1516 pack .data.list -side left -fill both -expand yes
1517 pack .data.scroll -side right -fill y
1518 .data.scroll config -command {.data.list yview}
1519
1520 message .bot.target -text "None" -aspect 1000 -relief sunken -border 1
1521 label .bot.status -text "Not connected" -width 12 -relief \
1522         sunken -anchor w -border 1
1523 label .bot.set -textvariable setNo -width 5 -relief \
1524         sunken -anchor w -border 1
1525 label .bot.message -text "" -width 14 -relief \
1526         sunken -anchor w -border 1
1527 pack .bot.target .bot.status .bot.set .bot.message -anchor nw \
1528         -side left -padx 2 -pady 2
1529
1530 bind .data.list <Double-Button-1> {set indx [.data.list nearest %y]
1531 show-full-marc $indx}
1532
1533 ir z39