Started work on Explain in client.
[ir-tcl-moved-to-github.git] / client.tcl
index ad22a84..9a3565f 100644 (file)
@@ -1,10 +1,42 @@
 # IR toolkit for tcl/tk
-# (c) Index Data 1995
+# (c) Index Data 1995-1996
 # See the file LICENSE for details.
 # Sebastian Hammer, Adam Dickmeiss
 #
 # $Log: client.tcl,v $
-# Revision 1.87  1996-01-22 17:13:34  adam
+# Revision 1.97  1996-09-13 10:54:22  adam
+# Started work on Explain in client.
+#
+# Revision 1.96  1996/08/09  15:30:18  adam
+# Procedure destroyGW modified to handle multiple calls - probably an
+# error introduced by tk4.1 patch level 1.
+#
+# Revision 1.95  1996/07/26  09:15:08  adam
+# IrTcl version 1.2 patch level 1.
+#
+# Revision 1.94  1996/07/25  15:55:34  adam
+# IrTcl version 1.2 release.
+#
+# Revision 1.93  1996/06/28  08:43:54  adam
+# Moved towards version 1.2.
+#
+# Revision 1.92  1996/03/29  16:04:30  adam
+# Work on GRS-1 presentation.
+#
+# Revision 1.91  1996/03/27  17:00:53  adam
+# Fix: main defined when using Tk3.6; it shouldn't be.
+#
+# Revision 1.90  1996/03/20  13:54:02  adam
+# The Tcl_File structure is only manipulated in the Tk-event interface
+# in tkinit.c.
+#
+# Revision 1.89  1996/03/05  09:16:04  adam
+# Sets tearoff to off on several menus.
+#
+# Revision 1.88  1996/01/23  15:24:09  adam
+# Wrore more comments.
+#
+# Revision 1.87  1996/01/22  17:13:34  adam
 # Wrote comments.
 #
 # Revision 1.86  1996/01/22  09:29:01  adam
@@ -346,6 +378,12 @@ if {[tk4]} {
     set noFocus {}
 }
 
+# Define dummy clock function if it is not there.
+if {[catch {clock seconds}]} {
+    proc clock {args} {
+        return {}
+    }
+}
 # Set monoFlag to 1 if screen is known not to support colors; otherwise
 #  set monoFlag to 0
 if {![tk4]} {
@@ -382,6 +420,43 @@ set hotTargets {}
 set hotInfo {}
 set busy 0
 
+# profile: associative array with target profiles.
+#indx exp description
+#
+#   0  T  Target description
+#   1     Host
+#   2     Port
+#   3     Authentication
+#   4     Maximum Record Size
+#   5     Preferred Messages Size
+#   6     Comstack
+#   7  D  Databases available
+#   8  T  Result Sets support
+#   9     RPN-Query support
+#  10     CCL-Query support
+#  11     Protocol (Z39/SR)
+#  12     Window Number
+#  13     LSLB  Large Set Lower Bound
+#  14     SSUB  Small Set Upper Bound
+#  15     MSPN  Medium Set Present Number
+#  16     Present Chunk - number of records to fetch in each present
+#  17     Time of first define
+#  18     Time of last init
+#  19     Time of last explain
+#  20  T  Name in TargetInfo
+#  21  T  Recent News
+#  22  T  Max Result Sets
+#  23  T  Max Result Size
+#  24  T  Max Terms
+#  25  D  List of database info records
+#  26  T  Multiple Databases
+#  27  T  Welcome message
+#
+#
+# Legend:
+#  T  TargetInfo explain
+#  D  DatabaseInfo explain
+
 set profile(Default) {{} {} {210} {} 50000 30000 tcpip {} 1 {} {} Z39 1 2 0 0 4}
 set hostid Default
 set settingsChanged 0
@@ -409,7 +484,7 @@ set setMax 0
 # Procedure tkerror {err}
 #   err   error message
 # Override the Tk error handler function.
-proc tkerror err {
+proc tkerrorx err {
     set w .tkerrorw
 
     if {[winfo exists $w]} {
@@ -429,12 +504,24 @@ proc tkerror err {
     bottom-buttons $w [list {Close} [list destroy $w]] 1
 }
 
+# Read tag set file (if present)
+if {[file readable "${libdir}/tagsets.tcl"]} {
+    source "${libdir}/tagsets.tcl"
+}
+
 # Read the global configuration file.
 if {[file readable "clientrc.tcl"]} {
     source "clientrc.tcl"
-} else {
-    if {[file readable "${libdir}/clientrc.tcl"]} {
-        source "${libdir}/clientrc.tcl"
+} elseif {[file readable "${libdir}/clientrc.tcl"]} {
+    source "${libdir}/clientrc.tcl"
+}
+
+# Make old definitions up-to-date.
+foreach n [array names profile] {
+    set l [llength $profile($n)]
+    while {$l < 29} {
+        lappend profile($n) {}
+        incr l
     }
 }
 
@@ -512,9 +599,8 @@ proc apduDump {} {
         
         top-down-window $w
         
-        text $w.top.t -width 60 -height 12 -wrap word -relief flat \
-                -borderwidth 0 \
-                -yscrollcommand [list $w.top.s set]
+        text $w.top.t -font fixed -width 60 -height 12 -wrap word \
+               -relief flat -borderwidth 0 -yscrollcommand [list $w.top.s set]
         scrollbar $w.top.s -command [list $w.top.t yview]
         
         pack $w.top.s -side right -fill y
@@ -553,23 +639,12 @@ proc set-display-format {f} {
 # Procedure initBindings
 # Disables various default bindings for Text and Listbox widgets.
 proc initBindings {} {
-    set w Text
-    bind $w <1> {}
-    bind $w <Double-1> {}
-    bind $w <Triple-1> {}
-    bind $w <B1-Motion> {}
-    bind $w <Shift-1> {}
-    bind $w <Shift-B1-Motion> {}
-    bind $w <2> {}
-    bind $w <B2-Motion> {}
-    bind $w <Any-KeyPress> {}
-    bind $w <Return> {}
-    bind $w <BackSpace> {}
-    bind $w <Delete> {}
-    bind $w <Control-h> {}
-    bind $w <Control-d> {}
-    bind $w <Control-v> {}
+    global TextBinding
 
+    foreach e [bind Text] {
+        set TextBinding($e) [bind Text $e]
+        bind Text $e {}
+    }
     set w Listbox
     bind $w <B1-Motion> {}
     bind $w <Shift-B1-Motion> {}
@@ -577,6 +652,16 @@ proc initBindings {} {
     set w Entry
 }
 
+# Procedure TextEditable 
+# Apply "standard" events to a text widget. It should be editable now.
+proc TextEditable {w} {
+    global TextBinding
+
+    foreach e [array names TextBinding] {
+        bind $w $e $TextBinding($e)
+    }
+}
+
 # Procedure post-menu {wbutton wmenu}
 #   wbutton    button widget
 #   wmenu      menu widget
@@ -597,7 +682,7 @@ proc post-menu {wbutton wmenu} {
 # See also topLevelG.
 proc destroyGW {w} {
     global windowGeometry
-    set windowGeometry($w) [wm geometry $w]
+    catch {set windowGeometry($w) [wm geometry $w]}
 }    
 
 # Procedure topLevelG
@@ -711,11 +796,11 @@ proc cancel-operation {} {
 proc show-target {target base} {
     global profile
 
-    if {$target == ""} {
+    if {![string length $target]} {
         .bot.a.target configure -text ""
         return
     }
-    if {$base == ""} {
+    if {![string length $base]} {
          .bot.a.target configure -text "$target"
     } else {
          .bot.a.target configure -text "$target - $base"
@@ -779,6 +864,8 @@ proc show-status {status b sb} {
         .mid.search configure -state normal
         if {$scanEnable} {
             .mid.scan configure -state normal
+        } else {
+            configure-disable-e .top.service.m 3
         }
         if {$setNo == 0} {
             configure-disable-e .top.service.m 1
@@ -845,7 +932,7 @@ proc popup-license {} {
     top-down-window $w
 
     text $w.top.t -width 80 -height 10 -wrap word -relief flat -borderwidth 0 \
-        -yscrollcommand [list $w.top.s set]
+        -font fixed -yscrollcommand [list $w.top.s set]
     scrollbar $w.top.s -command [list $w.top.t yview]
     
     pack $w.top.s -side right -fill y
@@ -992,8 +1079,8 @@ proc popup-marc {sno no b df} {
         pack  $w.top -side top -fill both -expand yes
         pack  $w.bot -fill both
 
-        text $w.top.record -width 60 -height 5 -wrap word -relief flat -borderwidth 0 \
-                -yscrollcommand [list $w.top.s set]
+        text $w.top.record -width 60 -height 5 -wrap word -relief flat \
+                -borderwidth 0 -font fixed -yscrollcommand [list $w.top.s set]
         scrollbar $w.top.s -command [list $w.top.record yview]
 
         global monoFlag
@@ -1125,7 +1212,7 @@ proc set-target-hotlist {olen} {
     foreach e $hotTargets {
         set target [lindex $e 0]
         set base [lindex $e 1]
-        if {$base == ""} {
+        if {![string length $base]} {
             .top.target.m add command -label "$i $target" -command \
                 [list reopen-target $target {}]
         } else {
@@ -1159,7 +1246,7 @@ proc define-target-action {} {
     global profile
     
     set target [.target-define.top.target.entry get]
-    if {$target == ""} {
+    if {![string length $target]} {
         return
     }
     foreach n [array names profile] {
@@ -1202,8 +1289,7 @@ proc fail-response {target} {
 # IrTcl connect response handler.
 proc connect-response {target base} {
     dputs "connect-response"
-    show-target $target $base
-    init-request
+    init-request $target $base
 }
 
 # Procedure open-target {target base}
@@ -1215,54 +1301,58 @@ proc open-target {target base} {
     global hostid
     global presentChunk
 
+    set desc [lindex $profile($target) 0]
+    if {[string length $desc]} {
+        .data.record insert end $desc
+    } else {
+        .data.record insert end $target
+    }
+    .data.record insert end "\n\n"
+
     z39 disconnect
     z39 comstack [lindex $profile($target) 6]
     z39 protocol [lindex $profile($target) 11]
-    z39 idAuthentication [lindex $profile($target) 3]
+    eval z39 idAuthentication [lindex $profile($target) 3]
     z39 maximumRecordSize [lindex $profile($target) 4]
     z39 preferredMessageSize [lindex $profile($target) 5]
-    dputs "maximumRecordSize="
-    dputs [z39 maximumRecordSize]
-    dputs "preferredMessageSize="
-    dputs [z39 preferredMessageSize]
+    dputs "maximumRecordSize=[z39 maximumRecordSize]"
+    dputs "preferredMessageSize=[z39 preferredMessageSize]"
     show-status Connecting 1 0
-    if {$base == ""} {
-        z39 databaseNames [lindex [lindex $profile($target) 7] 0]
-    } else {
-        z39 databaseNames $base
-    }
     set x [lindex $profile($target) 13]
-    if {$x == ""} {
+    if {![string length $x]} {
         set x 2
     }
     z39 largeSetLowerBound $x
-
+    
     set x [lindex $profile($target) 14]
-    if {$x == ""} {
+    if {![string length $x]} {
         set x 0
     }
     z39 smallSetUpperBound $x
-
+    
     set x [lindex $profile($target) 15]
-    if {$x == ""} {
+    if {![string length $x]} {
         set x 0
     }
     z39 mediumSetPresentNumber $x
 
     set presentChunk [lindex $profile($target) 16]
-    if {$presentChunk == ""} {
+    if {![string length $presentChunk]} {
         set presentChunk 4
     }
 
     z39 failback [list fail-response $target]
     z39 callback [list connect-response $target $base]
+    show-target $target $base
     update idletasks
     set err [catch {
         z39 connect [lindex $profile($target) 1]:[lindex $profile($target) 2]
         } errorMessage]
     if {$err} {
+        set hostid Default
         tkerror $errorMessage
         show-status "Not connected" 0 {}
+        show-target {} {}
         return
     }
     set hostid $target
@@ -1349,14 +1439,14 @@ proc load-set {} {
 # Procedure init-request
 # Sends an initialize request to the target. This procedure is called
 # when a connect has been established.
-proc init-request {} {
+proc init-request {target base} {
     global cancelFlag
 
     if {$cancelFlag} {
         close-target
         return
     }
-    z39 callback {init-response}
+    z39 callback [list init-response $target $base]
     show-status Initializing 1 {}
     set err [catch {z39 init} errorMessage]
     if {$err} {
@@ -1369,28 +1459,61 @@ proc init-request {} {
 # Handles and incoming init-response. The service buttons
 # are enabled. The global $scanEnable indicates whether the target
 # supports scan.
-proc init-response {} {
-    global cancelFlag
-    global scanEnable
+proc init-response {target base} {
+    global cancelFlag profile
+    global scanEnable settingsChanged
 
-    dputs {init-reponse}
+    dputs {init-response}
     apduDump
     if {$cancelFlag} {
         close-target
         return
     }
     if {![z39 initResult]} {
-        show-status Ready 0 1
         set u [z39 userInformationField]
         close-target
         tkerror "Connection rejected by target: $u"
     } else {
-        if {[lsearch [z39 options] scan] >= 0} {
-            set scanEnable 1
-        } else {
-            set scanEnable 0
-        }
-        show-status Ready 0 1
+        explain-check $target [list ready-response $base]
+    }
+}
+
+# Procedure explain-check 
+# Stub function to check explain. May be overwritten later.
+proc explain-check {target response} {
+    eval $response [list $target]
+}
+
+# Procedure ready-response
+# Called after a target has been initialized and, possibly, explained
+proc ready-response {base target} {
+    global profile settingsChanged scanEnable
+    
+    if {![string length $base]} {
+        set base [lindex [lindex $profile($target) 7] 0]
+    }
+    if {![string length $base]} {
+        set base Default
+    }
+    z39 databaseNames $base
+    set profile($target) [lreplace $profile($target) 18 18 [clock seconds]]
+    set settingsChanged 1
+    if {[lsearch [z39 options] scan] >= 0} {
+        set scanEnable 1
+    } else {
+        set scanEnable 0
+    }
+    cascade-dblist $target $base
+    show-target $target $base
+    show-message {}
+    show-status Ready 0 1
+
+    .data.record insert end [lindex $profile($target) 27]
+    .data.record insert end "\n"
+    set data [lindex $profile($target) 21]
+    if {[string length $data]} {
+        .data.record insert end "News:\n"
+        .data.record insert end "$data\n"
     }
 }
 
@@ -1412,8 +1535,8 @@ proc search-request {bflag} {
     global elementSetNames
 
     set target $hostid
-
-    if {[z39 connect] == ""} {
+    
+    if {![string length [z39 connect]]} {
         return
     }
     dputs "search-request"
@@ -1431,7 +1554,7 @@ proc search-request {bflag} {
     set delayRequest {} 
 
     set query [index-query]
-    if {$query==""} {
+    if {![string length $query]} {
         return
     }
     incr setNoLast
@@ -1453,12 +1576,12 @@ proc search-request {bflag} {
     }
     dputs Setting
     dputs $recordSyntax
-    if {$recordSyntax == "None" } {
+    if {![string compare $recordSyntax None]} {
         z39.$setNo preferredRecordSyntax {}
     } else {
         z39.$setNo preferredRecordSyntax $recordSyntax
     }
-    if {$elementSetNames == "None" } {
+    if {![string compare $elementSetNames None]} {
         z39.$setNo elementSetNames {}
         z39.$setNo smallSetElementSetNames {}
         z39.$setNo mediumSetElementSetNames {}
@@ -1579,7 +1702,7 @@ proc scan-term-h {attr} {
     z39.scan numberOfTermsRequested 5
     z39.scan preferredPositionInResponse 1
     dputs "${attr} \{${scanTerm}\}"
-    if {$scanTerm == ""} {
+    if {![string length $scanTerm]} {
         z39.scan scan "${attr} 0"
     } else {
         z39.scan scan "${attr} \{${scanTerm}\}"
@@ -1631,7 +1754,7 @@ proc scan-response {attr start toget} {
         z39.scan preferredPositionInResponse 1
         set scanTerm $nScanTerm
         dputs "${attr} \{${scanTerm}\}"
-        if {$scanTerm == ""} {
+        if {![string length $scanTerm]} {
             z39.scan scan "${attr} 0"
         } else {
             z39.scan scan "${attr} \{${scanTerm}\}"
@@ -1809,7 +1932,7 @@ proc search-response {} {
     set setMax [z39.$setNo resultCount]
     show-status Ready 0 1
     set status [z39.$setNo responseStatus]
-    if {[lindex $status 0] == "NSD"} {
+    if {![string compare [lindex $status 0] NSD]} {
         z39.$setNo nextResultSetPosition 0
         set code [lindex $status 1]
         set msg [lindex $status 2]
@@ -1825,7 +1948,7 @@ proc search-response {} {
     show-status Ready 0 1
     set l [format "%-4d %7d" $setNo $setMax]
     .top.rset.m add command -label $l \
-            -command [list add-title-lines $setNo 10000 1]
+            -command [list recall-set $setNo]
     if {$setMax > 20} {
         set setMax 20
     }
@@ -1885,7 +2008,7 @@ proc present-more {number} {
         show-status Ready 0 1
         return
     }
-    if {$number == ""} {
+    if {![string length $number]} {
         set setMax $max
     } else {
         incr setMax $number
@@ -1894,7 +2017,7 @@ proc present-more {number} {
         }
     }
     z39 callback {present-response}
-
+    
     set toGet [expr $setMax - $setOffset + 1]
     if {$toGet <= 0} {
         return
@@ -1912,6 +2035,12 @@ proc init-title-lines {} {
     .data.record delete 0.0 end
 }
 
+# Procedure recall-set {setno}
+#  setno    Set number to recall
+proc recall-set {setno} {
+    add-title-lines $setno 10000 1
+}
+
 # Procedure add-title-lines {setno no offset}
 #  setno    Set number
 #  no       Number of records
@@ -1941,7 +2070,7 @@ proc add-title-lines {setno no offset} {
     for {set i 0} {$i < $no} {incr i} {
         set o [expr $i + $offset]
         set type [z39.$setno type $o]
-        if {$type == ""} {
+        if {![string length $type]} {
             dputs "no more at $o"
             break
         }
@@ -1986,7 +2115,7 @@ proc present-response {} {
         return
     }
     set status [z39.$setNo responseStatus]
-    if {[lindex $status 0] == "NSD"} {
+    if {![string compare [lindex $status 0] NSD]} {
         show-status Ready 0 1
         set code [lindex $status 1]
         set msg [lindex $status 2]
@@ -2133,11 +2262,17 @@ proc protocol-setup-action {target w} {
         lappend dataBases [$w.top.databases.list get $i]
     }
     set wno [lindex $profile($target) 12]
+    set timedef [lindex $profile($target) 17]
+    if {![string length $timedef]} {
+        set timedef [clock seconds]
+    }
+
+    set idauth [$w.top.idAuthentication.entry get]
 
     set profile($target) [list [$w.top.description.entry get] \
             [$w.top.host.entry get] \
             [$w.top.port.entry get] \
-            [$w.top.idAuthentication.entry get] \
+            $idauth \
             $targetS($target,MRS) \
             $targetS($target,PMS) \
             $targetS($target,csType) \
@@ -2150,7 +2285,10 @@ proc protocol-setup-action {target w} {
             $targetS($target,LSLB) \
             $targetS($target,SSUB) \
             $targetS($target,MSPN) \
-            $targetS($target,presentChunk) ]
+            $targetS($target,presentChunk) \
+            $timedef \
+            {} \
+            {} ]
 
     cascade-target-list
     delete-target-hotlist $target
@@ -2213,6 +2351,7 @@ proc add-database {target wp} {
     focus $oldFocus
 }
 
+
 # Procedure delete-database {target w}
 #  target     target to be defined
 #  w          top level widget for the target definition
@@ -2256,7 +2395,7 @@ proc protocol-setup {target} {
 
     top-down-window $w
     
-    if {$target == ""} {
+    if {![string length $target]} {
         set target Default
     }
     dputs target
@@ -2266,6 +2405,7 @@ proc protocol-setup {target} {
     frame $w.top.host
     frame $w.top.port
     frame $w.top.idAuthentication
+
     frame $w.top.cs-type -relief ridge -border 2
     frame $w.top.protocol -relief ridge -border 2
     frame $w.top.query -relief ridge -border 2
@@ -2293,7 +2433,7 @@ proc protocol-setup {target} {
     set targetS($target,CCL) [lindex $profile($target) 9]
     set targetS($target,ResultSets) [lindex $profile($target) 10]
     set targetS($target,protocolType) [lindex $profile($target) 11]
-    if {$targetS($target,protocolType) == ""} {
+    if {![string length $targetS($target,protocolType)]} {
         set targetS($target,protocolType) Z39
     }
     set targetS($target,LSLB) [lindex $profile($target) 13]
@@ -2302,6 +2442,7 @@ proc protocol-setup {target} {
     set targetS($target,presentChunk) [lindex $profile($target) 16]
     set targetS($target,MRS) [lindex $profile($target) 4]
     set targetS($target,PMS) [lindex $profile($target) 5]
+
     # Databases ....
     pack $w.top.databases -side left -pady 2 -padx 2 -expand yes -fill both
 
@@ -2395,7 +2536,7 @@ proc advanced-setup {target b} {
     
     top-down-window $w
     
-    if {$target == ""} {
+    if {![string length $target]} {
         set target Default
     }
     dputs target
@@ -2502,6 +2643,25 @@ proc database-select {} {
     focus $oldFocus
 }
 
+# Procedure cascase-dblist-select
+proc cascade-dblist-select {target db} {
+    show-target $target $db
+    z39 databaseNames $db
+}
+
+# Procedure cascade-dblist 
+# Makes the Service/database list with proper databases for the target
+proc cascade-dblist {target base} {
+    global profile
+
+    set w .top.service.m.dblist
+    $w delete 0 200
+    foreach db [lindex $profile($target) 7] {
+        $w add command -label $db \
+                -command [list cascade-dblist-select $target $db]
+    }
+}
+
 # Procedure cascade-target-list
 # Makes all target/databases available in the Target|Connect
 # menu as well as all targets in the Target|Setup menu.
@@ -2723,9 +2883,11 @@ proc save-settings {} {
     puts $f "# Setup file"
 
     foreach n [array names profile] {
+
         puts -nonewline $f "set \{profile($n)\} \{"
         puts -nonewline $f $profile($n)
         puts $f "\}"
+        puts $f {}
     }
     puts -nonewline $f "set queryTypes \{" 
     puts -nonewline $f $queryTypes
@@ -2778,16 +2940,12 @@ proc alert-action {} {
 }
 
 # Procedure exit-action
-# This procedure is called if the user tries to exit without saving the
-# system settings.
+# This procedure is called if the user exists the application
 proc exit-action {} {
     global settingsChanged
 
     if {$settingsChanged} {
-        set a [alert "you haven't saved your settings. Do you wish to save?"]
-        if {$a} {
-            save-settings
-        }
+        save-settings
     }
     save-geometry
     exit 0
@@ -2823,6 +2981,9 @@ proc listbuttonx {button no names handle user} {
         menubutton $button -text [lindex [lindex $names $no] 0] \
                 -width 10 -menu ${button}.m -relief raised -border 1
         menu ${button}.m
+        if {[tk4]} {
+            ${button}.m configure -tearoff off
+       }
     }
     set i 0
     foreach name $names {
@@ -2843,6 +3004,9 @@ proc listbutton {button no names} {
     menubutton $button -text [lindex $names $no] -width 10 -menu ${button}.m \
             -relief raised -border 1
     menu ${button}.m
+    if {[tk4]} {
+        ${button}.m configure -tearoff off
+    }
     foreach name $names {
         ${button}.m add command -label $name \
                 -command [list ${button} configure -text $name]
@@ -2889,6 +3053,9 @@ proc listbuttonv {button var names} {
     menubutton $button -text $n -menu ${button}.m \
             -relief raised -border 1
     menu ${button}.m
+    if {[tk4]} {
+        ${button}.m configure -tearoff off
+    }
     for {set i 0} {$i < $l} {incr i 2} {
         ${button}.m add command -label [lindex $names $i] \
                 -command [list listbuttonv-action $button $var $names $i]
@@ -2997,6 +3164,12 @@ proc query-setup-action {queryNo} {
     index-lines .lines 1 $queryButtonsFind $queryInfoFind activate-index
 }
 
+# Procedure activate-e-index {value no i}
+#   value   menu name
+#   no      query index number
+#   i       menu index (integer)
+# Procedure called when listbutton is activated in the query type edit
+# window. The global $queryButtonsTmp is updated in this operation.
 proc activate-e-index {value no i} {
     global queryButtonsTmp
     global queryIndexTmp
@@ -3006,6 +3179,12 @@ proc activate-e-index {value no i} {
     set queryIndexTmp $i
 }
 
+# Procedure activate-index {value no i}
+#   value   menu name
+#   no      query index number
+#   i       menu index (integer)
+# Procedure called when listbutton is activated in the main query 
+# window. The global $queryButtonsFind is updated in this operation.
 proc activate-index {value no i} {
     global queryButtonsFind
 
@@ -3014,6 +3193,12 @@ proc activate-index {value no i} {
     dputs "queryButtonsFind $queryButtonsFind"
 }
 
+# Procedure update-attr
+# This procedure creates listbuttons for all bib-1 attributes except
+# the use-attribute in the .index-setup window.
+# The globals $relationTmpValue, $positionTmpValue, $structureTmpValue,
+# $truncationTmpValue and $completenessTmpValue are maintainted by the
+# listbuttons.
 proc update-attr {} {
     set w .index-setup
     listbuttonv $w.top.relation.b relationTmpValue\
@@ -3034,6 +3219,12 @@ proc update-attr {} {
             {Incomplete subfield} 1 {Complete subfield} 2 {Complete field} 3}
 }
 
+# Procedure use-attr {init}
+#  init      init flag
+# This procedure creates a listbox with several Bib-1 use attributes.
+# If $init is 1 the listbox is created with the attributes. If $init
+# is 0 the current selection of the listbox is read and the global
+# $useTmpValue is set to the current use-value.
 proc use-attr {init} {
     set attr {
         {None}                           0
@@ -3171,6 +3362,12 @@ proc use-attr {init} {
     }
 }
 
+# Procedure index-setup-action {oldAttr queryNo indexNo}
+#  oldAttr     original attributes (?)
+#  queryNo     query number
+#  indexNo     index number
+# Commits setup of a query index. The mapping from the index to 
+# the Bib-1 attributes are handled by this function.
 proc index-setup-action {oldAttr queryNo indexNo} {
     set attr [lindex $oldAttr 0]
 
@@ -3210,6 +3407,12 @@ proc index-setup-action {oldAttr queryNo indexNo} {
     destroy .index-setup
 }
 
+# Procedure index-setup {attr queryNo indexNo}
+#  attr        original attributes
+#  queryNo     query number
+#  indexNo     index number
+# Makes a window with settings of a given query index which the user
+# may inspect/modify.
 proc index-setup {attr queryNo indexNo} {
     set w .index-setup
 
@@ -3332,12 +3535,16 @@ proc index-setup {attr queryNo indexNo} {
 
 }
 
+# Procedure query-edit-index {queryNo}
+#  queryNo     query number
+# Determines if a selection of an index is active. If one is selected
+# the index-setup dialog is started.
 proc query-edit-index {queryNo} {
     global queryInfoTmp
     set w .query-setup
 
     set i [lindex [$w.top.index.list curselection] 0]
-    if {$i == ""} {
+    if {![string length $i]} {
         return
     }
     set attr [lindex $queryInfoTmp $i]
@@ -3345,13 +3552,17 @@ proc query-edit-index {queryNo} {
     index-setup $attr $queryNo $i
 }
 
+# Procedure query-delete-index {queryNo}
+#  queryNo     query number
+# Determines if a selection of an index is active. If one is selected
+# the index is deleted.
 proc query-delete-index {queryNo} {
     global queryInfoTmp
     global queryButtonsTmp
     set w .query-setup
 
     set i [lindex [$w.top.index.list curselection] 0]
-    if {$i == ""} {
+    if {![string length $i]} {
         return
     }
     set queryInfoTmp [lreplace $queryInfoTmp $i $i]
@@ -3359,6 +3570,9 @@ proc query-delete-index {queryNo} {
     $w.top.index.list delete $i
 }
     
+# Procedure query-setup {queryNo}
+#  queryNo     query number
+# Makes a dialog in which a query type an be customized.
 proc query-setup {queryNo} {
     set w .query-setup
 
@@ -3431,6 +3645,8 @@ proc query-setup {queryNo} {
             Cancel [list destroy $w]] 0
 }
 
+# Procedure index-clear
+# Handler that clears the search entry fields.
 proc index-clear {} {
     global queryButtonsFind
 
@@ -3440,7 +3656,18 @@ proc index-clear {} {
         incr i
     }
 }
-    
+
+# Procedure index-query
+# The purpose of this function is to read the user's query and convert
+# it to the prefix query that IrTcl/YAZ uses to represent an RPN query.
+# Each entry in a search fields takes the form
+#    [relOp][?]term[?]
+#  Here, relOp is an optional relational operator and one of:
+#      >  < >= <=  <>
+#    which sets the Bib-1 relation to greater-than, less-than, etc.
+#  The ? (question-mark) is also optional. A (?) on left-side indicates
+#    left truncation; (?) on right-side indicates right-truncation; (?)
+#    on both sides indicates both-left-and-right truncation.
 proc index-query {} {
     global queryButtonsFind
     global queryInfoFind
@@ -3517,6 +3744,12 @@ proc index-query {} {
     return $qs
 }
 
+# Procedure index-focus-in {w i}
+#  w    index frame
+#  i    index number
+# This procedure handles <FocusIn> events. A red border is drawed
+# around the active search entry field when tk3.6 is used (tk4.X
+# makes a black focus border itself).
 proc index-focus-in {w i} {
     global curIndexEntry
 
@@ -3526,6 +3759,14 @@ proc index-focus-in {w i} {
     set curIndexEntry $i
 }
 
+# Procedure index-lines {w readOp buttonInfo queryInfo handle}
+#  w          search fields entry frame
+#  realOp     if true, search-request bindings are bound to the entries.
+#  buttonInfo query type button information
+#  queryInfo  query type field information
+#  handle     handler called a when a 'listbutton' changes its value
+# Makes one or more search areas - with listbuttons on the left
+# and entries on the right. 
 proc index-lines {w realOp buttonInfo queryInfo handle} {
     set i 0
     foreach b $buttonInfo {
@@ -3584,6 +3825,12 @@ proc index-lines {w realOp buttonInfo queryInfo handle} {
     }
 }
 
+# Procedure search-fields {w buttondefs}
+#  w           search fields entry frame
+#  buttondefs  button definitions
+# Makes search entry fields and listbuttons. 
+# Note: This procedure is not used elsewhere. The index-lines
+#       procedure is used instead.
 proc search-fields {w buttondefs} {
     set i 0
     foreach buttondef $buttondefs {
@@ -3618,15 +3865,18 @@ proc search-fields {w buttondefs} {
     $w.0 configure -background red
 }
 
-if {[info exists windowGeometry(.)]} {
-    set g $windowGeometry(.)
-    if {$g != ""} {
-        wm geometry . $g
-    }
-}    
+# Init: The geometry information for the main window is set - either
+# to a default value or to the value in windowGeometry(.)
+if {[catch {set g $windowGeometry(.)}]} {
+    wm geometry . 420x340
+} else {
+    wm geometry . $g
+}
 
+# Init: Presentation formats are read.
 read-formats
 
+# Init: The main window is defined.
 frame .top  -border 1 -relief raised
 frame .lines  -border 1 -relief raised
 frame .mid  -border 1 -relief raised
@@ -3636,19 +3886,21 @@ pack .top .lines .mid -side top -fill x
 pack .data -side top -fill both -expand yes
 pack .bot -fill x
 
-menubutton .top.file -text "File" -menu .top.file.m
+# Init: Definition of File menu.
+menubutton .top.file -text File -menu .top.file.m
 menu .top.file.m
-.top.file.m add command -label "Save settings" -command {save-settings}
+.top.file.m add command -label {Save settings} -command {save-settings}
 .top.file.m add separator
-.top.file.m add command -label "Exit" -command {exit-action}
+.top.file.m add command -label Exit -command {exit-action}
 
-menubutton .top.target -text "Target" -menu .top.target.m
+# Init: Definition of Target menu.
+menubutton .top.target -text Target -menu .top.target.m
 menu .top.target.m
-.top.target.m add cascade -label "Connect" -menu .top.target.m.clist
-.top.target.m add command -label "Disconnect" -command {close-target}
-.top.target.m add command -label "About" -command {about-target}
-.top.target.m add cascade -label "Setup" -menu .top.target.m.slist
-.top.target.m add command -label "Setup new" -command {define-target-dialog}
+.top.target.m add cascade -label Connect -menu .top.target.m.clist
+.top.target.m add command -label Disconnect -command {close-target}
+.top.target.m add command -label About -command {about-target}
+.top.target.m add cascade -label Setup -menu .top.target.m.slist
+.top.target.m add command -label {Setup new} -command {define-target-dialog}
 .top.target.m add separator
 set-target-hotlist 0
 
@@ -3659,42 +3911,47 @@ menu .top.target.m.clist
 menu .top.target.m.slist
 cascade-target-list
 
-menubutton .top.service -text "Service" -menu .top.service.m
+# Init: Definition of Service menu.
+menubutton .top.service -text Service -menu .top.service.m
 menu .top.service.m
-.top.service.m add command -label "Database" -command {database-select}
-.top.service.m add cascade -label "Present" -menu .top.service.m.present
+.top.service.m add cascade -label Database -menu .top.service.m.dblist
+.top.service.m add cascade -label Present -menu .top.service.m.present
 menu .top.service.m.present
-.top.service.m.present add command -label "10 More" \
+.top.service.m.present add command -label {10 More} \
         -command [list present-more 10]
-.top.service.m.present add command -label "All" \
+.top.service.m.present add command -label All \
         -command [list present-more {}]
-.top.service.m add command -label "Search" -command {search-request 0}
-.top.service.m add command -label "Scan" -command {scan-request}
+.top.service.m add command -label Search -command {search-request 0}
+.top.service.m add command -label Scan -command {scan-request}
 
 .top.service configure -state disabled
 
-menubutton .top.rset -text "Set" -menu .top.rset.m
+menu .top.service.m.dblist
+
+menubutton .top.rset -text Set -menu .top.rset.m
 menu .top.rset.m
-.top.rset.m add command -label "Load" -command {load-set}
+.top.rset.m add command -label Load -command {load-set}
 .top.rset.m add separator
 
-menubutton .top.options -text "Options" -menu .top.options.m
+# Init: Definition of the Options menu.
+menubutton .top.options -text Options -menu .top.options.m
 menu .top.options.m
-.top.options.m add cascade -label "Query" -menu .top.options.m.query
-.top.options.m add cascade -label "Format" -menu .top.options.m.formats
-.top.options.m add cascade -label "Wrap" -menu .top.options.m.wrap
-.top.options.m add cascade -label "Syntax" -menu .top.options.m.syntax
-.top.options.m add cascade -label "Elements" -menu .top.options.m.elements
-.top.options.m add radiobutton -label "Debug" -variable debugMode -value 1
-
+.top.options.m add cascade -label Query -menu .top.options.m.query
+.top.options.m add cascade -label Format -menu .top.options.m.formats
+.top.options.m add cascade -label Wrap -menu .top.options.m.wrap
+.top.options.m add cascade -label Syntax -menu .top.options.m.syntax
+.top.options.m add cascade -label Elements -menu .top.options.m.elements
+.top.options.m add radiobutton -label Debug -variable debugMode -value 1
+
+# Init: Definition of the Options|Query menu.
 menu .top.options.m.query
-.top.options.m.query add cascade -label "Select" \
+.top.options.m.query add cascade -label Select \
         -menu .top.options.m.query.clist
-.top.options.m.query add cascade -label "Edit" \
+.top.options.m.query add cascade -label Edit \
         -menu .top.options.m.query.slist
-.top.options.m.query add command -label "New" \
+.top.options.m.query add command -label New \
         -command {query-new}
-.top.options.m.query add cascade -label "Delete" \
+.top.options.m.query add cascade -label Delete \
         -menu .top.options.m.query.dlist
 
 menu .top.options.m.query.slist
@@ -3702,6 +3959,7 @@ menu .top.options.m.query.clist
 menu .top.options.m.query.dlist
 cascade-query-list
 
+# Init: Definition of the Options|Formats menu.
 menu .top.options.m.formats
 set i 0
 foreach f $displayFormats {
@@ -3710,47 +3968,51 @@ foreach f $displayFormats {
     incr i
 }
 
+# Init: Definition of the Options|Wrap menu.
 menu .top.options.m.wrap
-.top.options.m.wrap add radiobutton -label "Character" \
+.top.options.m.wrap add radiobutton -label Character \
         -value char -variable textWrap -command {set-wrap char}
-.top.options.m.wrap add radiobutton -label "Word" \
+.top.options.m.wrap add radiobutton -label Word \
         -value word -variable textWrap -command {set-wrap word}
-.top.options.m.wrap add radiobutton -label "None" \
+.top.options.m.wrap add radiobutton -label None \
         -value none -variable textWrap -command {set-wrap none}
 
+# Init: Definition of the Options|Syntax menu.
 menu .top.options.m.syntax
-.top.options.m.syntax add radiobutton -label "None" \
+.top.options.m.syntax add radiobutton -label None \
         -value None -variable recordSyntax
 .top.options.m.syntax add separator
-.top.options.m.syntax add radiobutton -label "USMARC" \
+.top.options.m.syntax add radiobutton -label USMARC \
         -value USMARC -variable recordSyntax
-.top.options.m.syntax add radiobutton -label "UNIMARC" \
+.top.options.m.syntax add radiobutton -label UNIMARC \
         -value UNIMARC -variable recordSyntax
-.top.options.m.syntax add radiobutton -label "UKMARC" \
+.top.options.m.syntax add radiobutton -label UKMARC \
         -value UKMARC -variable recordSyntax
-.top.options.m.syntax add radiobutton -label "DANMARC" \
+.top.options.m.syntax add radiobutton -label DANMARC \
         -value DANMARC -variable recordSyntax
-.top.options.m.syntax add radiobutton -label "FINMARC" \
+.top.options.m.syntax add radiobutton -label FINMARC \
         -value FINMARC -variable recordSyntax
-.top.options.m.syntax add radiobutton -label "NORMARC" \
+.top.options.m.syntax add radiobutton -label NORMARC \
         -value NORMARC -variable recordSyntax
-.top.options.m.syntax add radiobutton -label "PICAMARC" \
+.top.options.m.syntax add radiobutton -label PICAMARC \
         -value PICAMARC -variable recordSyntax
 .top.options.m.syntax add separator
-.top.options.m.syntax add radiobutton -label "SUTRS" \
+.top.options.m.syntax add radiobutton -label SUTRS \
         -value SUTRS -variable recordSyntax
 .top.options.m.syntax add separator
-.top.options.m.syntax add radiobutton -label "GRS1" \
+.top.options.m.syntax add radiobutton -label GRS1 \
         -value GRS1 -variable recordSyntax
 
+# Init: Definition of the Options|Elements menu.
 menu .top.options.m.elements
-.top.options.m.elements add radiobutton -label "Unspecified" \
+.top.options.m.elements add radiobutton -label Unspecified \
         -value None -variable elementSetNames
-.top.options.m.elements add radiobutton -label "Full" \
+.top.options.m.elements add radiobutton -label Full \
         -value F -variable elementSetNames
-.top.options.m.elements add radiobutton -label "Brief" \
+.top.options.m.elements add radiobutton -label Brief \
         -value B -variable elementSetNames
 
+# Init: Definition of Help menu.
 menubutton .top.help -text "Help" -menu .top.help.m
 menu .top.help.m
 
@@ -3758,9 +4020,11 @@ menu .top.help.m
         -command {tkerror "Help on help not available. Sorry"}
 .top.help.m add command -label "About" -command {about-origin}
 
+# Init: Pack menu bar items.
 pack .top.file .top.target .top.service .top.rset .top.options -side left
 pack .top.help -side right
 
+# Init: Define query area.
 index-lines .lines 1 $queryButtonsFind [lindex $queryInfo 0] activate-index
 
 button .mid.search -text Search -command {search-request 0} \
@@ -3774,17 +4038,21 @@ button .mid.clear -text Clear -command index-clear
 pack .mid.search .mid.scan .mid.present .mid.clear -side left \
         -fill y -pady 1
 
-text .data.record -height 2 -width 20 -wrap none -borderwidth 0 -relief flat \
-        -yscrollcommand [list .data.scroll set] -wrap $textWrap
+# Init: Define record area in main window.
+text .data.record -font fixed -height 2 -width 20 -wrap none -borderwidth 0 \
+        -relief flat -yscrollcommand [list .data.scroll set] -wrap $textWrap
 scrollbar .data.scroll -command [list .data.record yview]
 if {[tk4]} {
     .data.record configure -takefocus 0
     .data.scroll configure -takefocus 0
 }
+
 pack .data.scroll -side right -fill y
 pack .data.record -expand yes -fill both
 initBindings
 
+# Init: Define standards tags. These are used in the display
+# format procedures.
 if {! $monoFlag} {
     .data.record tag configure marc-tag -foreground blue
     .data.record tag configure marc-id -foreground red
@@ -3807,10 +4075,12 @@ if {! $monoFlag} {
         -font -Adobe-Times-Medium-I-Normal-*-140-* \
         -foreground black
 
+# Init: Define logo.
 button .bot.logo -bitmap @${libdir}/bitmaps/book1 -command cancel-operation
 if {[tk4]} {
     .bot.logo configure -takefocus 0
 }
+# Init: Define status information fields at the bottom.
 frame .bot.a
 pack .bot.a -side left -fill x
 pack .bot.logo -side right -padx 2 -pady 2 -ipadx 1
@@ -3828,6 +4098,8 @@ pack .bot.a.target -side top -anchor nw -padx 2 -pady 2
 pack .bot.a.status .bot.a.set .bot.a.message \
         -side left -padx 2 -pady 2 -ipadx 1 -ipady 1
 
+# Init: Determine if the IrTcl extension is already there. If
+#  not, then dynamically load the IrTcl extension.
 if {[catch {ir z39}]} {
     set e [info sharedlibextension]
     puts -nonewline "Loading irtcl$e ..."
@@ -3835,11 +4107,24 @@ if {[catch {ir z39}]} {
     ir z39
     puts "ok"
 }
-#z39 logLevel all {} mylog
 
-if {$hostid != "Default"} {
+if {[file exists ${libdir}/explain.tcl]} {
+    source ${libdir}/explain.tcl
+}
+
+if {[file exists ${libdir}/setup.tcl]} {
+    source ${libdir}/setup.tcl
+}
+
+# Init: Uncomment this line if you wan't to enable logging.
+#z39 logLevel all
+
+# Init: If hostid is a valid target, a new connection will be established
+# immediately.
+if {[string compare $hostid Default]} {
     catch {open-target $hostid $hostbase}
 }
 
+# Init: Enable the logo.
 show-logo 1