snit_tcl83_utils.tcl

Go to the documentation of this file.
00001 /* --------------------------------------------------------------------------*/
00002 /*  TITLE:*/
00003 /*  snit_tcl83_utils.tcl*/
00004 /* */
00005 /*  AUTHOR:*/
00006 /*  Kenneth Green, 28 Aug 2004*/
00007 /* */
00008 /*  DESCRIPTION:*/
00009 /*        Utilities to support the back-port of snit from Tcl 8.4 to 8.3*/
00010 /* */
00011 /* --------------------------------------------------------------------------*/
00012 /*  Copyright*/
00013 /* */
00014 /*  Copyright (c) 2005 Kenneth Green*/
00015 /*  Modified by Andreas Kupries.*/
00016 /*  All rights reserved. This code is licensed as described in license.txt.*/
00017 /* --------------------------------------------------------------------------*/
00018 /*  This code is freely distributable, but is provided as-is with*/
00019 /*  no warranty expressed or implied.*/
00020 /* --------------------------------------------------------------------------*/
00021 /*  Acknowledgements*/
00022 /*    The changes described in this file are made to the awesome 'snit'*/
00023 /*    library as provided by William H. Duquette under the terms*/
00024 /*    defined in the associated 'license.txt'.*/
00025 /* -----------------------------------------------------------------------*/
00026 
00027 /* -----------------------------------------------------------------------*/
00028 /*  Namespace*/
00029 
00030 namespace ::snit83 {}
00031 
00032 /* -----------------------------------------------------------------------*/
00033 /*  Some Snit83 variables*/
00034 
00035 namespace ::snit83 {
00036     variable  cmdTraceTable
00037     array  cmdTraceTable =  {}
00038 
00039     namespace private {}
00040 }
00041 
00042 
00043 /* -----------------------------------------------------------------------*/
00044 /*  Initialisation*/
00045 
00046 /* */
00047 /*  Override Tcl functions so we can mimic some behaviours. This is*/
00048 /*  conditional on not having been done already. Otherwise loading snit*/
00049 /*  twice will fail the second time.*/
00050 /* */
00051 
00052 if [info exists tk_version] {
00053     if {
00054     ![llength [info ret s destroy]] ||
00055     ![regexp snit83 [info body destroy]]
00056     } (
00057     type rename , type destroy __, type destroy__
00058     )
00059 }
00060 if {
00061     ![llength [info procs namespace]] ||
00062     ![regexp snit83 [info body namespace]]
00063 } {
00064     rename namespace __namespace__
00065     rename rename    __rename__ ;# must be last one renamed!
00066 }
00067 
00068 #-----------------------------------------------------------------------
00069 # Global namespace functions
00070 
00071 
00072 # destroy -
00073 #
00074 # Perform delete tracing and then invoke the actual Tk destroy command
00075 
00076 if [info exists tk_version] {
00077     proc destroy { w } {
00078     variable ::snit83::cmdTraceTable
00079 
00080      index =  "delete,$w"
00081     if [info exists cmdTraceTable($index)] {
00082          cmd =  $cmdTraceTable($index)
00083         ::un cmdTraceTable = ($index) ;/*  prevent recursive tracing*/
00084         if [catch {eval $cmd $oldName \"$newName\" delete} err] { ; /*  "*/
00085         error $err
00086         }
00087     }
00088 
00089     return [__destroy__ $w]
00090     }
00091 }
00092 
00093 /*  namespace -*/
00094 /* */
00095 /*  Add limited support for 'namespace exists'. Must be a fully*/
00096 /*  qualified namespace name (pattern match support not provided).*/
00097 
00098 ret  namespace ( type cmd , type args ) {
00099     if {[string equal $cmd "exists"]} {
00100         set ptn [lindex $args 0]
00101         return [::snit83::private::NamespaceIsDescendantOf :: $ptn]
00102     } elseif {[string equal $cmd "delete"]} {
00103         if [namespace exists [lindex $args 0]] {
00104             return [uplevel 1 [subst {__namespace__ $cmd $args}]]
00105         }
00106     } else {
00107         return [uplevel 1 [subst {__namespace__ $cmd $args}]]
00108     }
00109 }
00110 
00111 /*  rename -*/
00112 /* */
00113 /*  Perform rename tracing and then invoke the actual Tcl rename command*/
00114 
00115 ret  rename ( type oldName , type newName ) {
00116     variable ::snit83::cmdTraceTable
00117 
00118     # Get caller's namespace since rename must be performed
00119     # in the context of the caller's namespace
00120     set callerNs "::"
00121     set callerLevel [expr {[info level] - 1}]
00122     if { $callerLevel > 0 } {
00123         set callerInfo [info level $callerLevel]
00124         set procName   [lindex $callerInfo 0]
00125         set callerNs   [namespace qualifiers $procName]
00126     }
00127 
00128     #puts "rename: callerNs: $callerNs"
00129     #puts "rename: '$oldName' -> '$newName'"
00130     #puts "rename: rcds - [join [array names cmdTraceTable] "\nrename: rcds - "]"
00131 
00132     set result [namespace eval $callerNs [concat __rename__ [list $oldName $newName]]]
00133 
00134     set index1 "rename,$oldName"
00135     set index2 "rename,::$oldName"
00136 
00137     foreach index [list $index1 $index2] {
00138         if [info exists cmdTraceTable($index)] {
00139             set cmd $cmdTraceTable($index)
00140 
00141         #puts "rename: '$cmd' { $oldName -> $newName }"
00142 
00143             ::unset cmdTraceTable($index) ;# prevent recursive tracing
00144             if {![string equal $newName ""]} {
00145                 # Create a new trace record under the new name
00146                 set cmdTraceTable(rename,$newName) $cmd
00147             }
00148             if [catch {eval $cmd $oldName \"$newName\" rename} err] {
00149                 error $err
00150             }
00151             break
00152         }
00153     }
00154 
00155     return $result
00156 }
00157 
00158 
00159 /* -----------------------------------------------------------------------*/
00160 /*  Private functions*/
00161 
00162 ret  ::snit83::private::NamespaceIsDescendantOf ( type parent , type child ) {
00163     set result 0
00164 
00165     foreach ns [__namespace__ children $parent] {
00166         if [string match $ns $child] {
00167             set result 1
00168             break;
00169         } else {
00170             if [set result [NamespaceIsDescendantOf $ns $child]] {
00171                 break
00172             }
00173         }
00174     }
00175     return $result
00176 }
00177 
00178 
00179 /* -----------------------------------------------------------------------*/
00180 /*  Utility functions*/
00181 
00182 ret  ::snit83::traceAddCommand (type name , type ops , type command) {
00183     variable cmdTraceTable
00184 
00185     #puts "::snit83::traceAddCommand n/$name/ o/$ops/ c/$command/"
00186     #puts "XX [join [array names cmdTraceTable] "\nXX "]"
00187 
00188     foreach op $ops {
00189         set index "$op,$name"
00190     #puts "::snit83::traceAddCommand: index = $index cmd = $command"
00191 
00192         set cmdTraceTable($index) $command
00193     }
00194 }
00195 
00196 ret  ::snit83::traceRemoveCommand (type name , type ops , type command) {
00197     variable cmdTraceTable
00198 
00199     #puts "::snit83::traceRemoveCommand n/$name/ o/$ops/ c/$command/"
00200     #puts "YY [join [array names cmdTraceTable] "\nYY "]"
00201 
00202     foreach op $ops {
00203         set index "$op,$name"
00204     #puts "::snit83::traceRemoveCommand: index = $index cmd = $command"
00205 
00206     catch { ::unset cmdTraceTable($index) }
00207     }
00208 }
00209 
00210 /*  Add support for 'unset -nocomplain'*/
00211 ret  ::snit83::unset ( type args ) {
00212 
00213     #puts "::snit83::unset - args: '$args'"
00214 
00215     set noComplain 0
00216     if {[string equal [lindex $args 0] "-nocomplain"]} {
00217         set noComplain 1
00218         set args [lrange $args 1 end]
00219     }
00220     if {[string equal [lindex $args 0] "--"]} {
00221         set args [lrange $args 1 end]
00222     }
00223 
00224     if [catch {
00225     uplevel 1 [linsert $args 0 ::unset]
00226     } err] {
00227         if { !$noComplain } {
00228             error $err
00229         }
00230     }
00231 }
00232 

Generated on 21 Sep 2010 for Gui by  doxygen 1.6.1