Wrote comments.
[ir-tcl-moved-to-github.git] / client.tcl
index 548b075..e5280bc 100644 (file)
@@ -4,7 +4,23 @@
 # Sebastian Hammer, Adam Dickmeiss
 #
 # $Log: client.tcl,v $
-# Revision 1.81  1995-10-19 10:34:43  adam
+# Revision 1.86  1996-01-22 09:29:01  adam
+# Wrote comments.
+#
+# Revision 1.85  1996/01/19  16:22:36  adam
+# New method: apduDump - returns information about last incoming APDU.
+#
+# Revision 1.84  1996/01/11  13:12:10  adam
+# Bug fix.
+#
+# Revision 1.83  1995/11/28  17:26:36  adam
+# Removed Carriage return from ir-tcl.c!
+# Removed misc. debug logs.
+#
+# Revision 1.82  1995/11/02  08:47:56  adam
+# Text widgets are flat now.
+#
+# Revision 1.81  1995/10/19  10:34:43  adam
 # More configurable client.
 #
 # Revision 1.80  1995/10/18  17:20:32  adam
 #
 #
 
+# Procedure tk4 is defined - returns 0 if tk 3.6 - returns 1 otherwise
 if {$tk_version == "3.6"} {
     proc tk4 {} {
         return 0
@@ -293,6 +310,19 @@ if {$tk_version == "3.6"} {
     }
 }
 
+# The following two procedures deals with menu entries. The interface
+# changed from Tk 3.6 to 4.X
+
+# Procedure configure-enable-e {w n}
+#  w   is a menu
+#  n   menu entry number (0 is first entry)
+# Enables menu entry
+
+# Procedure configure-disable-e {w n}
+#  w   is a menu
+#  n   menu entry number (0 is first entry)
+# Disables menu entry
+
 if {[tk4]} {
     proc configure-enable-e {w n} {
         incr n
@@ -313,6 +343,8 @@ if {[tk4]} {
     set noFocus {}
 }
 
+# Set monoFlag to 1 if screen is known not to support colors; otherwise
+#  set monoFlag to 0
 if {![tk4]} {
     if {[tk colormodel .] == "color"} {
         set monoFlag 0
@@ -323,10 +355,18 @@ if {![tk4]} {
     set monoFlag 0
 }
 
+# Define libdir to the IrTcl configuration directory.
+# In the line below LIBDIR will be modified during 'make install'.
 set libdir LIBDIR
+
+# If the bitmaps sub directory is present with a bitmap we assume 
+# the client is run from the source directory in which case we
+# set libdir the current directory.
 if {[file readable bitmaps/book2]} {
     set libdir .
 }
+
+# Make a final check to see if libdir was set ok.
 if {! [file readable ${libdir}/bitmaps/book2]} {
     puts "Cannot locate system files in ${libdir}. You must either run this"
     puts "program from the source directory root of ir-tcl or you must assure"
@@ -334,6 +374,7 @@ if {! [file readable ${libdir}/bitmaps/book2]} {
     exit 1
 }
 
+# Initialize a lot of globals.
 set hotTargets {}
 set hotInfo {}
 set busy 0
@@ -351,6 +392,7 @@ set textWrap word
 set recordSyntax None
 set elementSetNames None
 set delayRequest {}
+set debugMode 0
 
 set queryTypes {Simple}
 set queryButtons { { {I 0} {I 1} {I 2} } }
@@ -361,6 +403,9 @@ wm minsize . 0 0
 set setOffset 0
 set setMax 0
 
+# Procedure tkerror {err}
+#   err   error message
+# Override the Tk error handler function.
 proc tkerror err {
     set w .tkerrorw
 
@@ -381,6 +426,7 @@ proc tkerror err {
     bottom-buttons $w [list {Close} [list destroy $w]] 1
 }
 
+# Read the global configuration file.
 if {[file readable "clientrc.tcl"]} {
     source "clientrc.tcl"
 } else {
@@ -389,30 +435,40 @@ if {[file readable "clientrc.tcl"]} {
     }
 }
 
+# Read the user configuration file.
 if {[file readable "~/.clientrc.tcl"]} {
     source "~/.clientrc.tcl"
 }
 
+# These globals describe the current query type. They are set to the
+# first query type.
 set queryButtonsFind [lindex $queryButtons 0]
 set queryInfoFind [lindex $queryInfo 0]
 
+# Procedure read-formats
+# Read all Tcl source files in the subdirectory 'formats'.
+# The name of each source will correspond to a display format.
 proc read-formats {} {
     global displayFormats
     global libdir
-    if {[catch {set formats [glob -nocomplain ${libdir}/formats/*.tcl]}]} {
-        set formats ./formats/raw.tcl
-    }
+
+    set oldDir [pwd]
+    cd ${libdir}/formats
+    set formats [glob {*.[tT][cC][lL]}]
     foreach f $formats {
        if {[file readable $f]} {
             source $f
             set l [string length $f]
-            set f [string range $f [string length "${libdir}/formats/"] \
-                    [expr $l - 5]]
+            set f [string tolower [string range $f 0 [expr $l - 5]]]
             lappend displayFormats $f
         }
     }
+    cd $oldDir
 }
 
+# Procedure set-wrap {m}
+#  m    boolean wrap mode
+# Handler to enable/disable text wrap in the main record window
 proc set-wrap {m} {
     global textWrap
 
@@ -420,10 +476,61 @@ proc set-wrap {m} {
     .data.record configure -wrap $m
 }
 
+# Procedure dputs {m}
+#  m    string to be printed
+# puts utility for debugging.
 proc dputs {m} {
-    puts $m
+    global debugMode
+    if {$debugMode} {
+        puts $m
+    }
 }
 
+# Procedure apduDump {}
+# Logs BER dump of last APDU in window if debugMode is true.
+proc apduDump {} {
+    global debugMode
+
+    set w .apdu
+
+    if {$debugMode == 0} return
+    set x [z39 apduInfo]
+
+    set offset [lindex $x 1]
+    set length [lindex $x 0]
+
+    if {![winfo exists $w]} {
+        catch {destroy $w}
+        toplevelG $w
+
+        wm title $w "APDU information" 
+        
+        wm minsize $w 0 0
+        
+        top-down-window $w
+        
+        text $w.top.t -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
+        pack $w.top.t -expand yes -fill both
+
+        bottom-buttons $w [list {Close} [list destroy $w]] 0
+    }
+    $w.top.t insert end "Length: ${length}\n"
+    if {$offset != -1} {
+        $w.top.t insert end "Offset: ${offset}\n"
+    }
+    $w.top.t insert end [lindex $x 2]
+    $w.top.t insert end "---------------------------------\n"
+
+}
+
+# Procedure set-display-format {f}
+#  f    display format
+# Reformats main record window to use display format given by f
 proc set-display-format {f} {
     global displayFormat
     global setNo
@@ -440,6 +547,8 @@ proc set-display-format {f} {
     add-title-lines -1 10000 1
 }
 
+# Procedure initBindings
+# Disables various default bindings for Text and Listbox widgets.
 proc initBindings {} {
     set w Text
     bind $w <1> {}
@@ -465,6 +574,10 @@ proc initBindings {} {
     set w Entry
 }
 
+# Procedure post-menu {wbutton wmenu}
+#   wbutton    button widget
+#   wmenu      menu widget
+# Post menu near button. Note: not used.
 proc post-menu {wbutton wmenu} {
     $wmenu activate none
     focus $wmenu
@@ -473,10 +586,22 @@ proc post-menu {wbutton wmenu} {
 
 }
 
+# Procedure destroyGW {w}
+#   w     top level widget
+# Saves geometry of widget w in windowGeometry array. This
+# Procedure is used to save current geometry of a window before
+# it is destroyed.
+# See also topLevelG.
 proc destroyGW {w} {
     global windowGeometry
     set windowGeometry($w) [wm geometry $w]
 }    
+
+# Procedure topLevelG
+#   w     top level widget
+# Makes a new top level widget named w; sets geometry of window if it 
+# exists in windowGeometry array. The destroyGW procedure is set 
+# to be called when the Destroy event occurs.
 proc toplevelG {w} {
     global windowGeometry
 
@@ -490,7 +615,9 @@ proc toplevelG {w} {
     bind $w <Destroy> [list destroyGW $w]
 }
 
-
+# Procedure top-down-window {w}
+#  w    window (possibly top level)
+# Makes two frames inside w called top and bot.
 proc top-down-window {w} {
     frame $w.top -relief raised -border 1
     frame $w.bot -relief raised -border 1
@@ -499,6 +626,14 @@ proc top-down-window {w} {
     pack  $w.bot -fill both
 }
 
+# Procedure top-down-ok-cancel {w ok-action g}
+#  w          top level widget with $w.bot-frame
+#  ok-action  ok script
+#  g          grab flag
+# Makes two buttons in the bot frame called Ok and Cancel. The
+# ok-action is executed if Ok is pressed. If Cancel is activated
+# The window is destroyed. If g is true a grab is performed on the
+# window and the procedure waits until the window is destroyed.
 proc top-down-ok-cancel {w ok-action g} {
     frame $w.bot.left -relief sunken -border 1
     pack $w.bot.left -side left -expand yes -ipadx 2 -ipady 2 -padx 1 -pady 1
@@ -515,6 +650,15 @@ proc top-down-ok-cancel {w ok-action g} {
     }
 }
 
+# Procedure bottom-buttons {w buttonList g}
+#  w          top level widget with $w.bot-frame
+#  buttonList button specifications
+#  g          grab flag
+# Makes a list of buttons in the $w.bot frame. The buttonList is a list 
+# of button specifications. Each button specification consists of two
+# items; the first item is button label name; the second item is a script
+# of be executed when that button is executed. A grab is performed if g 
+# is true and it waits for the window to be destroyed.
 proc bottom-buttons {w buttonList g} {
     set i 0
     set l [llength $buttonList]
@@ -539,6 +683,12 @@ proc bottom-buttons {w buttonList g} {
     }
 }
 
+# Procedure cancel-operation
+# This handler is invoked when the user wishes to cancel an operation.
+# If the system is currently busy a "Cancel" will be displayed in the
+# status area and the cancelFlag is set to true indicating that future
+# responses from the target should be ignored. The system is no longer
+# when this procedure exists.
 proc cancel-operation {} {
     global cancelFlag
     global busy
@@ -551,6 +701,10 @@ proc cancel-operation {} {
     }
 }
 
+# Procedure show-target {target base}
+#  target     name of target
+#  base       name of database
+# Displays target name and database name in the target status area.
 proc show-target {target base} {
     global profile
 
@@ -565,6 +719,12 @@ proc show-target {target base} {
     }
 }
 
+# Procedure show-logo {v1}
+#  v1    integer level
+# This procedure maintains the book logo in the bottom of the screen.
+# It is invoked only once during initialization of windows, etc., and
+# by itself. The global 'busy' variable determines whether the logo is
+# moving or not.
 proc show-logo {v1} {
     global busy
     global libdir
@@ -587,7 +747,14 @@ proc show-logo {v1} {
         }
     }
 }
-        
+
+# Procedure show-status {status b sb}
+#  status     status message string
+#  b          busy indicator
+#  sb         search busy indicator
+# Display status information according to 'status' and sets the global
+# busy flag 'busy' to b if b is non-empty. If sb is non-empty it indicates
+# whether service buttons should be enabled or disabled.
 proc show-status {status b sb} {
     global busy
     global scanEnable
@@ -637,10 +804,19 @@ proc show-status {status b sb} {
     }
 }
 
+# Procedure show-message {msg}
+#  msg    message string
+# Sets message the bottom of the screen to msg.
 proc show-message {msg} {
     .bot.a.message configure -text "$msg"
 }
 
+# Procedure insertWithTags {w text args}
+#  w      text widget
+#  text   string to be inserted
+#  args   list of tags
+# Inserts text at the insertion point in widget w. The text is tagged 
+# with the tags in args.
 proc insertWithTags {w text args} {
     set start [$w index insert]
     $w insert insert $text
@@ -652,6 +828,8 @@ proc insertWithTags {w text args} {
     }
 }
 
+# Procedure popup-license
+# Displays LICENSE information.
 proc popup-license {} {
     global libdir
     set w .popup-licence
@@ -663,7 +841,7 @@ proc popup-license {} {
 
     top-down-window $w
 
-    text $w.top.t -width 80 -height 10 -wrap word \
+    text $w.top.t -width 80 -height 10 -wrap word -relief flat -borderwidth 0 \
         -yscrollcommand [list $w.top.s set]
     scrollbar $w.top.s -command [list $w.top.t yview]
     
@@ -681,6 +859,9 @@ proc popup-license {} {
     bottom-buttons $w [list {Close} [list destroy $w]] 1
 }
 
+# Procedure about-target
+# Displays various information about the current target, such
+# as implementation-name, implementation-id, etc.
 proc about-target {} {
     set w .about-target-w
     global hostid
@@ -715,6 +896,9 @@ proc about-target {} {
     bottom-buttons $w [list {Close} [list destroy $w]] 1
 }
 
+# Procedure about-origin-logo {n}
+#   n    integer level
+# Displays book logo in the .about-origin-w widget
 proc about-origin-logo {n} {
     global libdir
     set w .about-origin-w
@@ -729,6 +913,8 @@ proc about-origin-logo {n} {
     after 140 [list about-origin-logo $n]
 }
 
+# Procedure about-origin
+# Display various information about origin (this client).
 proc about-origin {} {
     set w .about-origin-w
     global libdir
@@ -770,6 +956,13 @@ proc about-origin {} {
                             {License} [list popup-license]] 0
 }
 
+# Procedure popup-marc {sno no b df}
+#  sno     result set number
+#  no      record position number
+#  b       popup window number
+#  df      display format
+# Displays record in set $sno at position $no in window .full-marc$b.
+# The global variable $popupMarcdf holds the current format method.
 proc popup-marc {sno no b df} {
     global displayFormats
     global popupMarcdf
@@ -796,7 +989,7 @@ 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 \
+        text $w.top.record -width 60 -height 5 -wrap word -relief flat -borderwidth 0 \
                 -yscrollcommand [list $w.top.s set]
         scrollbar $w.top.s -command [list $w.top.record yview]
 
@@ -871,6 +1064,12 @@ proc popup-marc {sno no b df} {
     $ffunc $sno $no $w.top.record 0
 }
 
+# Procedure update-target-hotlist {target base}
+#  target     current target name
+#  base       current database name
+# Updates the global $hotTargets so that $target and $base are
+# moved to the front, i.e. they become the number 1 target/base.
+# The target menu is updated by a call to set-target-hotlist.
 proc update-target-hotlist {target base} {
     global hotTargets
 
@@ -887,6 +1086,10 @@ proc update-target-hotlist {target base} {
     set-target-hotlist $olen
 } 
 
+# Procedure delete-target-hotlist {target}
+#  target    target to be deleted
+# Updates the global $hotTargets so that $target is removed.
+# The target menu is updated by a call to set-target-hotlist.
 proc delete-target-hotlist {target} {
     global hotTargets
 
@@ -901,6 +1104,10 @@ proc delete-target-hotlist {target} {
     set-target-hotlist $olen
 }
 
+# Procedure set-target-hotlist {olen}
+#  olen     number of hot target entries to be deleted from menu
+# Updates the target menu with the targets with the first 8 entries
+# in the $hotTargets global.
 proc set-target-hotlist {olen} {
     global hotTargets
    
@@ -929,12 +1136,21 @@ proc set-target-hotlist {olen} {
     }
 }
 
+# Procedure reopen-target {target base}
+#  target    target to be opened
+#  base      base to be used
+# Closes connection with current target and opens a new connection
+# with $target and database $base.
 proc reopen-target {target base} {
     close-target
     open-target $target $base
     update-target-hotlist $target $base
 }
 
+# Procedure define-target-action
+# Prepares the setup of a new target. The name of the target
+# is read from the dialog .target-define dialog and the target
+# definition window is displayed by a call to protocol-setup.
 proc define-target-action {} {
     global profile
     
@@ -959,19 +1175,37 @@ proc define-target-action {} {
     destroy .target-define
 }
 
+# Procedure fail-response {target}
+#  target   current target
+# Error handler (IrTcl failback) that takes care of serious protocol
+# errors, connection lost, etc.
 proc fail-response {target} {
+    global debugMode
+
     set c [lindex [z39 failInfo] 0]
     set m [lindex [z39 failInfo] 1]
+    if {$c == 4 || $c == 5} {
+        set debugMode 1        
+        apduDump
+    }
     close-target
     tkerror "$m ($c)"
 }
 
+# Procedure connect-response {target base}
+#  target   current target
+#  base     current database
+# IrTcl connect response handler.
 proc connect-response {target base} {
     dputs "connect-response"
     show-target $target $base
     init-request
 }
 
+# Procedure open-target {target base}
+#  target   target to be opened
+#  base     database to be used
+# Opens a new connection with $target/$base.
 proc open-target {target base} {
     global profile
     global hostid
@@ -1033,6 +1267,8 @@ proc open-target {target base} {
     configure-enable-e .top.target.m 2
 }
 
+# Procedure close-target
+# Shuts down the connection with current target.
 proc close-target {} {
     global hostid
     global cancelFlag
@@ -1121,6 +1357,7 @@ proc init-response {} {
     global scanEnable
 
     dputs {init-reponse}
+    apduDump
     if {$cancelFlag} {
         close-target
         return
@@ -1322,6 +1559,7 @@ proc scan-response {attr start toget} {
 
     set w .scan-window
     dputs "In scan-response"
+    apduDump
     set m [z39.scan numberOfEntriesReturned]
     dputs $m
     dputs attr=$attr
@@ -1492,7 +1730,7 @@ proc search-response {} {
     global delayRequest
     global presentChunk
 
-
+    apduDump
     dputs "In search-response"
     if {$cancelFlag} {
         dputs "Handling cancel"
@@ -1652,6 +1890,7 @@ proc present-response {} {
     global presentChunk
 
     dputs "In present-response"
+    apduDump
     set no [z39.$setNo numberOfRecordsReturned]
     dputs "Returned $no records, setOffset $setOffset"
     add-title-lines $setNo $no $setOffset
@@ -2264,7 +2503,7 @@ proc save-geometry {} {
         return
     } 
     if {$hostid != "Default"} {
-        puts $f "set hostid $hostid"
+        puts $f "set hostid \{$hostid\}"
         set b [z39 databaseNames]
         puts $f "set hostbase $b"
     }
@@ -3202,6 +3441,7 @@ menu .top.options.m
 .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
 
 menu .top.options.m.query
 .top.options.m.query add cascade -label "Select" \
@@ -3290,7 +3530,7 @@ 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 \
+text .data.record -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]} {
@@ -3351,7 +3591,7 @@ if {[catch {ir z39}]} {
     ir z39
     puts "ok"
 }
-z39 logLevel all
+#z39 logLevel all
 
 if {$hostid != "Default"} {
     catch {open-target $hostid $hostbase}