Diagnostic error message displayed with tkerror.
[ir-tcl-moved-to-github.git] / client.tcl
1 #
2 # $Log: client.tcl,v $
3 # Revision 1.11  1995-03-21 10:39:06  adam
4 # Diagnostic error message displayed with tkerror.
5 #
6 # Revision 1.10  1995/03/20  15:24:06  adam
7 # Diagnostic records saved on searchResponse.
8 #
9 # Revision 1.9  1995/03/17  18:26:16  adam
10 # Non-blocking i/o used now. Database names popup as cascade items.
11 #
12 # Revision 1.8  1995/03/17  15:45:00  adam
13 # Improved target/database setup.
14 #
15 # Revision 1.7  1995/03/16  17:54:03  adam
16 # Minor changes really.
17 #
18 # Revision 1.6  1995/03/15  19:10:20  adam
19 # Database setup in protocol-setup (rather target setup).
20 #
21 # Revision 1.5  1995/03/15  13:59:23  adam
22 # Minor changes.
23 #
24 # Revision 1.4  1995/03/14  17:32:29  adam
25 # Presentation of full Marc record in popup window.
26 #
27 # Revision 1.3  1995/03/12  19:31:52  adam
28 # Pattern matching implemented when retrieving MARC records. More
29 # diagnostic functions.
30 #
31 # Revision 1.2  1995/03/10  18:00:15  adam
32 # Actual presentation in line-by-line format. RPN query support.
33 #
34 # Revision 1.1  1995/03/09  16:15:07  adam
35 # First presentRequest attempts. Hot-target list.
36 #
37 #
38 set hotTargets {}
39 set hotInfo {}
40 set busy 0
41
42 set profile(Default) {{} {} {210} {} 16384 8192 tcpip {}}
43 set hostid Default
44 set settingsChanged 0
45 set setNo 0
46
47 wm minsize . 360 200
48
49 if {[file readable "~/.tk-c"]} {
50     source "~/.tk-c"
51 }
52
53 proc top-down-window {w} {
54     frame $w.top -relief raised -border 1
55     frame $w.bot -relief raised -border 1
56     
57     pack  $w.top $w.bot -side top -fill both -expand yes
58 }
59
60 proc top-down-ok-cancel {w ok-action g} {
61     frame $w.bot.left -relief sunken -border 1
62     pack $w.bot.left -side left -expand yes -padx 5 -pady 5
63     button $w.bot.left.ok -width 6 -text {Ok} \
64             -command ${ok-action}
65     pack $w.bot.left.ok -expand yes -padx 3 -pady 3
66     button $w.bot.cancel -width 6 -text {Cancel} \
67             -command "destroy $w"
68     pack $w.bot.cancel -side left -expand yes    
69
70     if {$g} {
71         # Grab ...
72         grab $w
73         tkwait window $w
74     }
75 }
76
77 proc show-target {target} {
78     .bot.target configure -text "$target"
79 }
80
81 proc show-busy {v1 v2} {
82     global busy
83     if {$busy != 0} {
84         .bot.status configure -fg $v1
85         after 200 [list show-busy $v2 $v1]
86     }
87 }
88         
89 proc show-status {status b} {
90     global busy
91     global statusbg
92     .bot.status configure -text "$status"
93     .bot.status configure -fg black
94     if {$b != 0} {
95         if {$busy == 0} {
96             set busy $b   
97             show-busy red blue
98         }
99         #        . config -cursor {watch black white}
100     } else {
101         #        . config -cursor {top_left_arrow black white}
102         puts "Normal"
103     }
104     set busy $b
105 }
106
107 proc show-message {msg} {
108     .bot.message configure -text "$msg"
109 }
110
111 proc insertWithTags {w text args} {
112     set start [$w index insert]
113     $w insert insert $text
114     foreach tag [$w tag names $start] {
115         $w tag remove $tag $start insert
116     }
117     foreach i $args {
118         $w tag add $i $start insert
119     }
120 }
121
122 proc show-full-marc {no} {
123     global setNo
124
125     set w .full-marc
126
127     if {[winfo exists $w]} {
128         $w.top.record delete 0.0 end
129         set new 0
130     } else {
131
132         toplevel $w
133
134         wm minsize $w 200 200
135         
136         frame $w.top -relief raised -border 1
137         frame $w.bot -relief raised -border 1
138
139         #        pack  $w.top $w.bot -side top -fill both -expand yes
140         pack  $w.top -side top -fill both -expand yes
141         pack  $w.bot -fill both
142
143         text $w.top.record -width 60 -height 10 -wrap word \
144                 -yscrollcommand [list $w.top.s set]
145         scrollbar $w.top.s -command [list $w.top.record yview]
146
147         set new 1
148     }
149     incr no
150     
151     set r [z39.$setNo recordMarc $no line * * *]
152
153     $w.top.record tag configure marc-tag -foreground blue
154     $w.top.record tag configure marc-data -foreground black
155     $w.top.record tag configure marc-id -foreground red
156
157     foreach line $r {
158         set tag [lindex $line 0]
159         set indicator [lindex $line 1]
160         set fields [lindex $line 2]
161
162         if {$indicator != ""} {
163             insertWithTags $w.top.record "$tag $indicator" marc-tag
164         } else {
165             insertWithTags $w.top.record "$tag    " marc-tag
166         }
167         foreach field $fields {
168             set id [lindex $field 0]
169             set data [lindex $field 1]
170             if {$id != ""} {
171                 insertWithTags $w.top.record " $id " marc-id
172             }
173             set start [$w.top.record index insert]
174             insertWithTags $w.top.record $data {}
175         }
176         $w.top.record insert end "\n"
177     }
178     if {$new} {
179         bind $w <Return> {destroy .full-marc}
180         
181         pack $w.top.s -side right -fill y
182         pack $w.top.record -expand yes -fill both
183         
184         frame $w.bot.left -relief sunken -border 1
185         pack $w.bot.left -side left -expand yes -padx 5 -pady 5
186         button $w.bot.left.close -width 6 -text {Close} \
187                 -command {destroy .full-marc}
188         pack $w.bot.left.close -expand yes -padx 3 -pady 3
189         button $w.bot.edit -width 6 -text {Edit} \
190                 -command {destroy .full-marc}
191         pack $w.bot.edit -side left -expand yes
192     }
193 }
194
195 proc update-target-hotlist {target} {
196     global hotTargets
197
198     set len [llength $hotTargets]
199     if {$len > 0} {
200         .top.target.m delete 5 [expr 5+[llength $hotTargets]]
201     }
202     set indx [lsearch $hotTargets $target]
203     if {$indx >= 0} {
204         set hotTargets [lreplace $hotTargets $indx $indx]
205     }
206     set hotTargets [linsert $hotTargets 0 $target]
207     set-target-hotlist    
208
209
210 proc set-target-hotlist {} {
211     global hotTargets
212     
213     set i 1
214     foreach target $hotTargets {
215         .top.target.m add command -label "$i $target" -command \
216                 "menu-open-target $target {}"
217         incr i
218         if {$i > 8} {
219              break
220         }
221     }
222 }
223
224 proc menu-open-target {target base} {
225     open-target $target $base
226     update-target-hotlist $target
227 }
228
229 proc define-target-action {} {
230     global profile
231
232     set target [.target-define.top.target.entry get]
233     if {$target == ""} {
234         return
235     }
236     update-target-hotlist $target
237     foreach n [array names profile] {
238         if {$n == $target} {
239             protocol-setup $n
240             return
241         }
242     }
243     set profile($target) $profile(Default)
244     protocol-setup $target
245     destroy .target-define
246 }
247
248 proc open-target {target base} {
249     global profile
250
251     .top.target.m disable 0
252     .top.target.m enable 1
253     z39 disconnect
254     z39 comstack [lindex $profile($target) 6]
255     # z39 idAuthentication [lindex $profile($target) 3]
256     z39 maximumRecordSize [lindex $profile($target) 4]
257     z39 preferredMessageSize [lindex $profile($target) 5]
258     puts -nonewline "maximumRecordSize="
259     puts [z39 maximumRecordSize]
260     puts -nonewline "preferredMessageSize="
261     puts [z39 preferredMessageSize]
262     if {$base == ""} {
263         z39 databaseNames [lindex [lindex $profile($target) 7] 0]
264     } else {
265         z39 databaseNames $base
266     }
267     show-target $target
268     z39 connect  [lindex $profile($target) 1]:[lindex $profile($target) 2]
269     init-request
270 }
271
272 proc load-set-action {} {
273     global setNo
274
275     incr setNo
276     ir-set z39.$setNo
277
278     set fname [.load-set.top.filename.entry get]
279     destroy .load-set
280     if {$fname != ""} {
281         init-title-lines
282
283         show-status {Loading} 1
284         z39.$setNo loadFile $fname
285
286         set no [z39.$setNo numberOfRecordsReturned]
287         add-title-lines $setNo $no 1
288     }
289     show-status {Ready} 0
290 }
291
292 proc load-set {} {
293     set w .load-set
294
295     toplevel $w
296
297     place-force $w .
298
299     top-down-window $w
300
301     frame $w.top.filename
302     
303     pack $w.top.filename -side top -anchor e -pady 2
304     
305     entry-fields $w.top {filename} \
306             {{Filename:}} \
307             {load-set-action} {destroy .load-set}
308     
309     top-down-ok-cancel $w {load-set-action} 1
310 }
311
312 proc init-request {} {
313     global setNo
314     
315     z39 callback {init-response}
316     z39 init
317     show-status {Initializing} 1
318     set setNo 0
319 }
320
321 proc init-response {} {
322     show-status {Ready} 0
323     pack .mid.searchlabel .mid.searchentry -side left
324     bind .mid.searchentry <Return> search-request
325     focus .mid.searchentry
326 }
327
328 proc search-request {} {
329     global setNo
330
331     incr setNo
332     ir-set z39.$setNo
333
334     z39 callback {search-response}
335     z39.$setNo search [.mid.searchentry get]
336     show-status {Search} 1
337 }
338
339 proc search-response {} {
340     global setNo
341     global setOffset
342     global setMax
343
344     init-title-lines
345     show-status {Ready} 0
346     show-message "[z39.$setNo resultCount] hits"
347     set setMax [z39.$setNo resultCount]
348     puts $setMax
349     if {$setMax == 0} {
350         set status [z39.$setNo responseStatus]
351         if {[lindex $status 0] == "NSD"} {
352             set code [lindex $status 1]
353             set msg [lindex $status 2]
354             set addinfo [lindex $status 3]
355             tkerror "NSD$code: $msg: $addinfo"
356         }
357         return
358     }
359     if {$setMax > 10} {
360         set setMax 10
361     }
362     z39 callback {present-response}
363     set setOffset 1
364     z39.$setNo present 1 $setMax
365     show-status {Retrieve} 1
366 }
367
368 proc init-title-lines {} {
369     .data.list delete 0 end
370 }
371
372 proc add-title-lines {setno no offset} {
373     for {set i 0} {$i < $no} {incr i} {
374         set o [expr $i + $offset]
375         set title [lindex [z39.$setno recordMarc $o field 245 * a] 0]
376         set year  [lindex [z39.$setno recordMarc $o field 260 * c] 0]
377         set nostr [format "%3d" $o]
378         .data.list insert end "$nostr $title - $year"
379     }
380 }
381
382 proc present-response {} {
383     global setNo
384     global setOffset
385     global setMax
386
387     puts "In present-response"
388     set no [z39.$setNo numberOfRecordsReturned]
389     puts "Returned $no records, setOffset $setOffset"
390     add-title-lines $setNo $no $setOffset
391     set setOffset [expr $setOffset + $no]
392     set status [z39.$setNo responseStatus]
393     if {[lindex $status 0] == "NSD"} {
394         show-status {Ready} 0
395         set code [lindex $status 1]
396         set msg [lindex $status 2]
397         set addinfo [lindex $status 3]
398         tkerror "NSD$code: $msg: $addinfo"
399         return
400     }
401     if {$no > 0 && $setOffset <= $setMax} {
402         z39.$setNo present $setOffset [expr $setMax - $setOffset + 1]
403     } else {
404         show-status {Finished} 0
405     }
406 }
407
408 proc left-cursor {w} {
409     set i [$w index insert]
410     if {$i > 0} {
411         incr i -1
412         $w icursor $i
413     }
414 }
415
416 proc right-cursor {w} {
417     set i [$w index insert]
418     incr i
419     $w icursor $i
420 }
421
422 proc bind-fields {list returnAction escapeAction} {
423     set max [expr [llength $list]-1]
424     for {set i 0} {$i < $max} {incr i} {
425         bind [lindex $list $i] <Return> $returnAction
426         bind [lindex $list $i] <Escape> $escapeAction
427         bind [lindex $list $i] <Tab> [list focus [lindex $list [expr $i+1]]]
428         bind [lindex $list $i] <Left> [list left-cursor [lindex $list $i]]
429         bind [lindex $list $i] <Right> [list right-cursor [lindex $list $i]]
430     }
431     bind [lindex $list $i] <Return> $returnAction
432     bind [lindex $list $i] <Escape> $escapeAction
433     bind [lindex $list $i] <Tab>    [list focus [lindex $list 0]]
434     bind [lindex $list $i] <Left> [list left-cursor [lindex $list $i]]
435     bind [lindex $list $i] <Right> [list right-cursor [lindex $list $i]]
436     focus [lindex $list 0]
437 }
438
439 proc entry-fields {parent list tlist returnAction escapeAction} {
440     set alist {}
441     set i 0
442     foreach field $list {
443         set label ${parent}.${field}.label
444         set entry ${parent}.${field}.entry
445         label $label -text [lindex $tlist $i] -anchor e
446         entry $entry -width 32 -relief sunken
447         pack $label -side left
448         pack $entry -side right
449         lappend alist $entry
450         incr i
451     }
452     bind-fields $alist $returnAction $escapeAction
453 }
454
455 proc define-target-dialog {} {
456     set w .target-define
457
458     toplevel $w
459
460     place-force $w .
461
462     top-down-window $w
463
464     frame $w.top.target
465
466     pack $w.top.target \
467             -side top -anchor e -pady 2 
468
469     entry-fields $w.top {target} \
470             {{Target:}} \
471             {define-target-action} {destroy .target-define}
472     
473     top-down-ok-cancel $w {define-target-action} 1
474 }
475
476 proc close-target {} {
477     pack forget .mid.searchlabel .mid.searchentry
478     z39 disconnect
479     show-target {None}
480     show-status {Not connected} 0
481     show-message {}
482     .top.target.m disable 1
483     .top.target.m enable 0
484 }
485
486 proc protocol-setup-action {target} {
487     global profile
488     global csRadioType
489     global settingsChanged
490
491     set w .setup-${target}.top
492
493     #set w .protocol-setup.top
494     
495     set b {}
496     set settingsChanged 1
497     set len [$w.databases.list size]
498     for {set i 0} {$i < $len} {incr i} {
499         lappend b [$w.databases.list get $i]
500     }
501     set profile($target) [list [$w.description.entry get] \
502             [$w.host.entry get] \
503             [$w.port.entry get] \
504             [$w.idAuthentication.entry get] \
505             [$w.maximumRecordSize.entry get] \
506             [$w.preferredMessageSize.entry get] \
507             $csRadioType \
508             $b]
509
510     cascade-target-list
511     puts $profile($target)
512     destroy .setup-${target}
513 }
514
515
516 proc place-force {window parent} {
517     set g [wm geometry $parent]
518
519     set p1 [string first + $g]
520     set p2 [string last + $g]
521
522     set x [expr 40+[string range $g [expr $p1 +1] [expr $p2 -1]]]
523     set y [expr 60+[string range $g [expr $p2 +1] end]]
524     wm geometry $window +${x}+${y}
525 }
526
527
528 proc add-database-action {target} {
529     set w .setup-${target}
530     
531     ${w}.top.databases.list insert end \
532             [.database-select.top.database.entry get]
533     destroy .database-select
534 }
535
536 proc add-database {target} {
537     set w .database-select
538
539     set oldFocus [focus]
540     toplevel $w
541
542     place-force $w .setup-${target}
543
544     top-down-window $w
545
546     frame $w.top.database
547
548     pack $w.top.database -side top -anchor e -pady 2
549     
550     entry-fields $w.top {database} \
551             {{Database to add:}} \
552             [list add-database-action $target] {destroy .database-select}
553
554     top-down-ok-cancel $w [list add-database-action $target] 1
555     focus $oldFocus
556 }
557
558 proc delete-database {target} {
559     set w .setup-${target}
560     
561     foreach i [lsort -decreasing \
562             [$w.top.databases.list curselection]] {
563         $w.top.databases.list delete $i
564     }
565 }
566
567 proc protocol-setup {target} {
568     set w .setup-$target
569
570     global profile
571     global csRadioType
572
573     toplevel $w
574
575     wm title $w "Setup $target"
576     place-force $w .
577
578     top-down-window $w
579     
580     if {$target == ""} {
581         set target Default
582     }
583     puts target
584     puts $profile($target)
585
586     frame $w.top.host
587     frame $w.top.port
588     frame $w.top.description
589     frame $w.top.idAuthentication
590     frame $w.top.maximumRecordSize
591     frame $w.top.preferredMessageSize
592     frame $w.top.cs-type -relief ridge -border 2
593     frame $w.top.query -relief ridge -border 2
594     frame $w.top.databases -relief ridge -border 2
595
596     # Maximum/preferred/idAuth ...
597     pack $w.top.description $w.top.host $w.top.port \
598             $w.top.idAuthentication $w.top.maximumRecordSize \
599             $w.top.preferredMessageSize -side top -anchor e -pady 2
600     #-anchor e
601     
602     entry-fields $w.top {description host port idAuthentication \
603             maximumRecordSize preferredMessageSize} \
604             {{Description:} {Host:} {Port:} {Id Authentification:} \
605             {Maximum Record Size:} {Preferred Message Size:}} \
606             [list protocol-setup-action $target] [list destroy $w]
607     
608     $w.top.description.entry insert 0 [lindex $profile($target) 0]
609     $w.top.host.entry insert 0 [lindex $profile($target) 1]
610     $w.top.port.entry insert 0 [lindex $profile($target) 2]
611     $w.top.idAuthentication.entry insert 0 [lindex $profile($target) 3]
612     $w.top.maximumRecordSize.entry insert 0 [lindex $profile($target) 4]
613     $w.top.preferredMessageSize.entry insert 0 [lindex $profile($target) 5]
614
615     # Databases ....
616     pack $w.top.databases -side left -pady 6 -padx 6 -expand yes -fill x
617
618     label $w.top.databases.label -text "Databases"
619     button $w.top.databases.add -text "Add" \
620             -command "add-database $target"
621     button $w.top.databases.delete -text "Delete" \
622             -command "delete-database $target"
623     listbox $w.top.databases.list -geometry 20x6 \
624             -yscrollcommand "$w.top.databases.scroll set"
625     scrollbar $w.top.databases.scroll -orient vertical -border 1
626     pack $w.top.databases.label -side top -fill x \
627             -padx 2 -pady 2
628     pack $w.top.databases.add $w.top.databases.delete -side top -fill x \
629             -padx 2 -pady 2
630     pack $w.top.databases.list -side left -fill both -expand yes \
631             -padx 2 -pady 2
632     pack $w.top.databases.scroll -side right -fill y \
633             -padx 2 -pady 2
634     $w.top.databases.scroll config -command "$w.top.databases.list yview"
635
636     foreach b [lindex $profile($target) 7] {
637         $w.top.databases.list insert end $b
638     }
639     
640     # Transport ...
641     set csRadioType [lindex $profile($target) 6]
642
643     pack $w.top.cs-type -pady 6 -padx 6 -side top
644     
645     label $w.top.cs-type.label -text "Transport" 
646     radiobutton $w.top.cs-type.tcpip -text "TCP/IP" \
647             -command {puts tcp/ip} -variable csRadioType -value tcpip
648     radiobutton $w.top.cs-type.mosi -text "MOSI" \
649             -command {puts mosi} -variable csRadioType -value mosi
650     
651     pack $w.top.cs-type.label $w.top.cs-type.tcpip $w.top.cs-type.mosi \
652             -padx 4 -side top -fill x
653
654     # Query ...
655     pack $w.top.query -pady 6 -padx 6 -side top
656
657     label $w.top.query.label -text "Query support" -anchor e
658     checkbutton $w.top.query.c1 -text "CCL query"   
659     checkbutton $w.top.query.c2 -text "RPN query"
660     checkbutton $w.top.query.c3 -text "Result sets"
661
662     pack $w.top.query.label -side top 
663     pack $w.top.query.c1 $w.top.query.c2 $w.top.query.c3 \
664             -padx 4 -side top -fill x
665
666     foreach sub [winfo children $w.top] {
667         puts $sub
668         bind $sub <Control-a> "add-database $target"
669     }
670     top-down-ok-cancel $w [list protocol-setup-action $target] 0
671 }
672
673 proc database-select-action {} {
674     set w .database-select.top
675     set b {}
676     foreach indx [$w.databases.list curselection] {
677         lappend b [$w.databases.list get $indx]
678     }
679     if {$b != ""} {
680         z39 databaseNames $b
681     }
682     destroy .database-select
683 }
684
685 proc database-select {} {
686     set w .database-select
687     global profile
688     global hostid
689
690     toplevel $w
691
692     place-force $w .
693
694     top-down-window $w
695
696     if {$hostid == ""} {
697         set hostid Default
698     }
699
700     frame $w.top.databases -relief ridge -border 2
701
702     pack $w.top.databases -side left -pady 6 -padx 6 -expand yes -fill x
703
704     label $w.top.databases.label -text "List"
705     listbox $w.top.databases.list -geometry 20x6 \
706             -yscrollcommand "$w.top.databases.scroll set"
707     scrollbar $w.top.databases.scroll -orient vertical -border 1
708     pack $w.top.databases.label -side top -fill x \
709             -padx 2 -pady 2
710     pack $w.top.databases.list -side left -fill both -expand yes \
711             -padx 2 -pady 2
712     pack $w.top.databases.scroll -side right -fill y \
713             -padx 2 -pady 2
714     $w.top.databases.scroll config -command "$w.top.databases.list yview"
715
716     foreach b [lindex $profile($hostid) 7] {
717         $w.top.databases.list insert end $b
718     }
719     top-down-ok-cancel $w {database-select-action} 1
720 }
721
722 proc cascade-target-list {} {
723     global profile
724     
725     foreach sub [winfo children .top.target.m.clist] {
726         puts "deleting $sub"
727         destroy $sub
728     }
729     .top.target.m.clist delete 0 last
730     foreach n [array names profile] {
731         if {$n != "Default"} {
732             set nl [string tolower $n]
733             if {[llength [lindex $profile($n) 7]] > 1} {
734                 .top.target.m.clist add cascade -label $n \
735                         -menu .top.target.m.clist.$nl
736                 menu .top.target.m.clist.$nl
737                 foreach b [lindex $profile($n) 7] {
738                     .top.target.m.clist.$nl add command -label $b \
739                             -command "menu-open-target $n $b"
740                 }
741             } else {
742                 .top.target.m.clist add command -label $n \
743                         -command "menu-open-target $n {}"
744             }
745         }
746     }
747     .top.target.m.slist delete 0 last
748     foreach n [array names profile] {
749         if {$n != "Default"} {
750             .top.target.m.slist add command -label $n \
751                     -command "protocol-setup $n"
752         }
753     }
754 }
755
756 proc save-settings {} {
757     global hotTargets 
758     global profile
759     global settingsChanged
760
761     set f [open "~/.tk-c" w]
762     puts $f "# Setup file"
763     puts $f "set hotTargets \{ $hotTargets \}"
764
765     foreach n [array names profile] {
766         puts -nonewline $f "set profile($n) \{"
767         puts -nonewline $f $profile($n)
768         puts $f "\}"
769     }
770     close $f
771     set settingsChanged 0
772 }
773
774 proc alert {ask} {
775     set w .alert
776
777     global alertAnswer
778
779     toplevel $w
780     place-force $w .
781     top-down-window $w
782
783     message $w.top.message -text $ask
784
785     pack $w.top.message -side left -pady 6 -padx 20 -expand yes -fill x
786   
787     set alertAnswer 0
788     top-down-ok-cancel $w {alert-action} 1
789     return $alertAnswer
790 }
791
792 proc alert-action {} {
793     global alertAnswer
794     set alertAnswer 1
795     destroy .alert
796 }
797
798 proc exit-action {} {
799     global settingsChanged
800
801     if {$settingsChanged} {
802         set a [alert "you havent saved your settings. Do you wish to save?"]
803         if {$a} {
804             save-settings
805         }
806     }
807     destroy .
808 }
809
810 frame .top  -border 1 -relief raised
811 frame .mid  -border 1 -relief raised
812 frame .data -border 1 -relief raised
813 frame .bot  -border 1 -relief raised
814 pack .top .mid -side top -fill x
815 pack .data      -side top -fill both -expand yes
816 pack .bot      -fill x
817
818 menubutton .top.file -text "File" -menu .top.file.m
819 menu .top.file.m
820 .top.file.m add command -label "Save settings" -command {save-settings}
821 .top.file.m add command -label "Load Set" -command {load-set}
822 .top.file.m add separator
823 .top.file.m add command -label "Exit" -command {exit-action}
824
825 menubutton .top.target -text "Target" -menu .top.target.m
826 menu .top.target.m
827 .top.target.m add cascade -label "Connect" -menu .top.target.m.clist
828 .top.target.m add command -label "Disconnect" -command {close-target}
829 #.top.target.m add command -label "Initialize" -command {init-request}
830 .top.target.m add cascade -label "Setup" -menu .top.target.m.slist
831 .top.target.m add command -label "Setup new" -command {define-target-dialog}
832 .top.target.m add separator
833 set-target-hotlist
834
835 .top.target.m disable 1
836
837 menu .top.target.m.clist
838 menu .top.target.m.slist
839 cascade-target-list
840
841 menubutton .top.database -text "Database" -menu .top.database.m
842 menu .top.database.m
843 .top.database.m add command -label "Select ..." -command {database-select}
844 .top.database.m add command -label "Add ..." -command {puts "Add"}
845
846 menubutton .top.help -text "Help" -menu .top.help.m
847 menu .top.help.m
848
849 .top.help.m add command -label "Help on help" -command {puts "Help on help"}
850 .top.help.m add command -label "About" -command {puts "About"}
851
852 pack .top.file .top.target .top.database -side left
853 pack .top.help -side right
854
855 label .mid.searchlabel -text {Search:}
856 entry .mid.searchentry -width 40 -relief sunken
857
858 bind .mid.searchentry <Left> {left-cursor .mid.searchentry}
859 bind .mid.searchentry <Right> {right-cursor .mid.searchentry}
860
861 listbox .data.list -yscrollcommand {.data.scroll set}
862 scrollbar .data.scroll -orient vertical -border 1
863 pack .data.list -side left -fill both -expand yes
864 pack .data.scroll -side right -fill y
865 .data.scroll config -command {.data.list yview}
866
867 message .bot.target -text "None" -aspect 1000 -relief sunken -border 1
868 label .bot.status -text "Not connected" -width 12 -relief \
869     sunken -anchor w -border 1
870 label .bot.message -text "" -width 20 -relief \
871     sunken -anchor w -border 1
872 pack .bot.target .bot.status .bot.message -anchor nw -side left -padx 2 -pady 2
873
874 bind .data.list <Double-Button-1> {set indx [.data.list nearest %y]
875 show-full-marc $indx}
876
877 ir z39