Changeset 986 for trunk/tkcon
- Timestamp:
- Apr 21, 2010 2:42:21 PM (14 years ago)
- Location:
- trunk/tkcon
- Files:
-
- 1 added
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/tkcon/tkcon.tcl
r931 r986 11 11 ## 12 12 ## Thanks to the following (among many) for early bug reports & code ideas: 13 ## Steven Wahl <steven@indra.com>, Jan Nijtmans <nijtmans@nici.kun.nl> 14 ## Crimmins <markcrim@umich.edu>, Wart <wart@ugcs.caltech.edu> 13 ## Steven Wahl, Jan Nijtmans, Mark Crimmins, Wart 15 14 ## 16 ## Copyright 1995-2001 Jeffrey Hobbs15 ## Copyright (c) 1995-2004 Jeffrey Hobbs, jeff(a)hobbs(.)org 17 16 ## Initiated: Thu Aug 17 15:36:47 PDT 1995 18 ##19 ## jeff.hobbs@acm.org, jeff@hobbs.org20 17 ## 21 18 ## source standard_disclaimer.tcl … … 25 22 # Proxy support for retrieving the current version of Tkcon. 26 23 # 27 # Mon Jun 25 12:19:56 2001 - Pat Thoyts <Pat.Thoyts@bigfoot.com>24 # Mon Jun 25 12:19:56 2001 - Pat Thoyts 28 25 # 29 26 # In your tkcon.cfg or .tkconrc file put your proxy details into the … … 45 42 return -code error "tkcon requires at least Tcl/Tk8" 46 43 } else { 47 package require -exact Tk $tcl_version 48 } 49 50 catch {package require bogus-package-name} 44 # package require -exact Tk $tcl_version; # exact causes a problem with Tk 8.5+ 45 package require Tk $tcl_version 46 } 47 48 # We need to load some package to get what's available, and we 49 # choose ctext because we'll use it if its available in the editor 50 catch {package require ctext} 51 51 foreach pkg [info loaded {}] { 52 52 set file [lindex $pkg 0] … … 75 75 # 76 76 namespace eval ::tkcon { 77 # when modifying this line, make sure that the auto-upgrade check 78 # for version still works. 79 variable VERSION "2.4" 77 80 # The OPT variable is an array containing most of the optional 78 81 # info to configure. COLOR has the color data. … … 83 86 variable PRIV 84 87 set PRIV(WWW) [info exists embed_args] 88 89 variable EXPECT 0 85 90 } 86 91 … … 90 95 # Outputs: errors found in tkcon's resource file 91 96 ## 92 proc ::tkcon::Init {} { 97 proc ::tkcon::Init {args} { 98 variable VERSION 93 99 variable OPT 94 100 variable COLOR 95 101 variable PRIV 96 global tcl_platform env argc argv tcl_interactive errorInfo 97 98 if {![info exists argv]} { 99 set argv {} 100 set argc 0 101 } 102 global tcl_platform env tcl_interactive errorInfo 102 103 103 104 set tcl_interactive 1 104 105 if {[info exists PRIV(name)]} { 106 set title $PRIV(name) 107 } else { 108 MainInit 109 # some main initialization occurs later in this proc, 110 # to go after the UI init 111 set MainInit 1 112 set title Main 113 } 105 set argc [llength $args] 114 106 115 107 ## … … 135 127 } 136 128 129 # expandorder could also include 'Xotcl' (before Procname) 137 130 foreach {key default} { 138 131 autoload {} … … 140 133 blinkrange 1 141 134 buffer 512 135 maxlinelen 0 142 136 calcmode 0 143 137 cols 80 144 138 debugPrompt {(level \#$level) debug [history nextid] > } 145 139 dead {} 140 edit edit 146 141 expandorder {Pathname Variable Procname} 147 142 font {} … … 152 147 lightcmd 1 153 148 maineval {} 154 maxmenu 1 5149 maxmenu 18 155 150 nontcl 0 156 151 prompt1 {ignore this, it's set below} … … 159 154 showmenu 1 160 155 showmultiple 1 161 showstatusbar 0156 showstatusbar 1 162 157 slaveeval {} 163 158 slaveexit close … … 165 160 gc-delay 60000 166 161 gets {congets} 162 overrideexit 1 167 163 usehistory 1 168 164 … … 190 186 find,reg 0 191 187 errorInfo {} 188 protocol exit 192 189 showOnStartup 1 193 slavealias { edit more less tkcon }194 190 slaveprocs { 195 191 alias clear dir dump echo idebug lremove 196 192 tkcon_puts tkcon_gets observe observe_var unalias which what 197 193 } 198 version 2.3199 RCS {RCS: @(#) $Id: tkcon.tcl,v 1.52 2002/01/24 19:50:36 hobbs Exp $}200 HEADURL {http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/tkcon/tkcon/tkcon.tcl?rev=HEAD} 194 RCS {RCS: @(#) $Id: tkcon.tcl,v 1.89 2005/09/12 19:07:17 hobbs Exp $} 195 HEADURL {http://cvs.sourceforge.net/viewcvs.py/*checkout*/tkcon/tkcon/tkcon.tcl?rev=HEAD} 196 201 197 docs "http://tkcon.sourceforge.net/" 202 email {jeff @hobbs.org}198 email {jeff(a)hobbs(.)org} 203 199 root . 200 uid 0 201 tabs {} 204 202 } { 205 203 if {![info exists PRIV($key)]} { set PRIV($key) $default } 204 } 205 foreach {key default} { 206 slavealias { $OPT(edit) more less tkcon } 207 } { 208 if {![info exists PRIV($key)]} { set PRIV($key) [subst $default] } 209 } 210 set PRIV(version) $VERSION 211 212 option add *Menu.tearOff 0 213 option add *takeFocus 0 214 215 if {[info exists PRIV(name)]} { 216 set title $PRIV(name) 217 } else { 218 MainInit 219 # some main initialization occurs later in this proc, 220 # to go after the UI init 221 set MainInit 1 222 set title Main 206 223 } 207 224 … … 254 271 } 255 272 if {[info exists env($envHome)]} { 273 set home $env($envHome) 274 if {[file pathtype $home] == "volumerelative"} { 275 # Convert 'C:' to 'C:/' if necessary, innocuous otherwise 276 append home / 277 } 256 278 if {![info exists PRIV(rcfile)]} { 257 set PRIV(rcfile) [file join $ env($envHome)$rcfile]279 set PRIV(rcfile) [file join $home $rcfile] 258 280 } 259 281 if {![info exists PRIV(histfile)]} { 260 set PRIV(histfile) [file join $ env($envHome)$histfile]282 set PRIV(histfile) [file join $home $histfile] 261 283 } 262 284 } … … 264 286 ## Handle command line arguments before sourcing resource file to 265 287 ## find if resource file is being specified (let other args pass). 266 if {[set i [lsearch -exact $arg v-rcfile]] != -1} {267 set PRIV(rcfile) [lindex $arg v[incr i]]288 if {[set i [lsearch -exact $args -rcfile]] != -1} { 289 set PRIV(rcfile) [lindex $args [incr i]] 268 290 } 269 291 … … 274 296 if {[info exists env(TK_CON_LIBRARY)]} { 275 297 lappend ::auto_path $env(TK_CON_LIBRARY) 276 } else {298 } elseif {$OPT(library) != ""} { 277 299 lappend ::auto_path $OPT(library) 278 300 } … … 293 315 set truth {^(1|yes|true|on)$} 294 316 for {set i 0} {$i < $argc} {incr i} { 295 set arg [lindex $arg v$i]317 set arg [lindex $args $i] 296 318 if {[string match {-*} $arg]} { 297 set val [lindex $arg v[incr i]]319 set val [lindex $args [incr i]] 298 320 ## Handle arg based options 299 321 switch -glob -- $arg { 300 -- - -argv 322 -- - -argv - -args { 301 323 set argv [concat -- [lrange $argv $i end]] 302 324 set argc [llength $argv] … … 322 344 323 345 ## Create slave executable 324 if { [string compare {} $OPT(exec)]} {346 if {"" != $OPT(exec)} { 325 347 uplevel \#0 ::tkcon::InitSlave $OPT(exec) $slaveargs 326 348 } else { 327 349 set argc [llength $slaveargs] 328 set arg v$slaveargs350 set args $slaveargs 329 351 uplevel \#0 $slaveargs 330 352 } … … 333 355 Attach $PRIV(appname) $PRIV(apptype) 334 356 InitUI $title 357 if {"" != $OPT(exec)} { 358 # override exit to DeleteTab now that tab has been created 359 $OPT(exec) alias exit ::tkcon::DeleteTab $PRIV(curtab) $OPT(exec) 360 } 335 361 336 362 ## swap puts and gets with the tkcon versions to make sure all … … 407 433 StateCheckpoint $PRIV(name) slave 408 434 435 puts "buffer line limit:\ 436 [expr {$OPT(buffer)?$OPT(buffer):{unlimited}}] \ 437 max line length:\ 438 [expr {$OPT(maxlinelen)?$OPT(maxlinelen):{unlimited}}]" 439 409 440 Prompt "$title console display active (Tcl$::tcl_patchLevel / Tk$::tk_patchLevel)\n" 410 441 } … … 420 451 variable COLOR 421 452 variable PRIV 422 global argv0 tcl_interactive tcl_library env auto_path 453 global argv0 tcl_interactive tcl_library env auto_path tk_library 423 454 424 455 if {[string match {} $slave]} { … … 431 462 $slave alias open SafeOpen $slave 432 463 $slave alias file file 433 interp eval $slave [dump var -nocomplain tcl_library auto_path env] 464 interp eval $slave \ 465 [list set auto_path [lremove $auto_path $tk_library]] 466 interp eval $slave [dump var -nocomplain tcl_library env] 434 467 interp eval $slave { catch {source [file join $tcl_library init.tcl]} } 435 468 interp eval $slave { catch unknown } 436 469 } 470 # This will likely be overridden to call DeleteTab where possible 437 471 $slave alias exit exit 438 472 interp eval $slave { … … 451 485 if {[info exists argv0]} {interp eval $slave [list set argv0 $argv0]} 452 486 interp eval $slave set tcl_interactive $tcl_interactive \; \ 453 set auto_path [list $auto_path] \; \487 set auto_path [list [lremove $auto_path $tk_library]] \; \ 454 488 set argc [llength $args] \; \ 455 489 set argv [list $args] \; { … … 499 533 } 500 534 interp { 501 set thistkcon [ tkappname]535 set thistkcon [::send::appname] 502 536 foreach cmd $PRIV(slavealias) { 503 EvalAttached "proc $cmd args { send [list $thistkcon] $cmd \$args }"537 EvalAttached "proc $cmd args { ::send::send [list $thistkcon] $cmd \$args }" 504 538 } 505 539 } … … 542 576 if {!$PRIV(WWW)} { 543 577 wm withdraw $root 544 wm protocol $root WM_DELETE_WINDOW exit578 wm protocol $root WM_DELETE_WINDOW $PRIV(protocol) 545 579 } 546 580 set PRIV(base) $w 547 581 548 ## Text Console 549 set PRIV(console) [set con $w.text] 550 text $con -wrap char -yscrollcommand [list $w.sy set] \ 551 -foreground $COLOR(stdin) \ 552 -insertbackground $COLOR(cursor) 582 catch {font create tkconfixed -family Courier -size -12} 583 catch {font create tkconfixedbold -family Courier -size -12 -weight bold} 584 585 set PRIV(statusbar) [set sbar [frame $w.fstatus]] 586 set PRIV(tabframe) [frame $sbar.tabs] 587 set PRIV(X) [button $sbar.deltab -text "X" -command ::tkcon::DeleteTab \ 588 -activeforeground red -fg red -font tkconfixedbold \ 589 -highlightthickness 0 -padx 2 -pady 0 -bd 1 \ 590 -state disabled -relief flat] 591 catch {$PRIV(X) configure -overrelief raised} 592 label $sbar.cursor -relief sunken -bd 1 -anchor e -width 6 \ 593 -textvariable ::tkcon::PRIV(StatusCursor) 594 set padx [expr {![info exists ::tcl_platform(os)] 595 || ![string match "Windows CE" $::tcl_platform(os)]}] 596 grid $PRIV(X) $PRIV(tabframe) $sbar.cursor -sticky news -padx $padx 597 grid configure $PRIV(tabframe) -sticky nsw 598 grid configure $PRIV(X) -pady 0 -padx 0 599 grid columnconfigure $sbar 1 -weight 1 600 grid rowconfigure $sbar 0 -weight 1 601 grid rowconfigure $PRIV(tabframe) 0 -weight 1 602 if {$::tcl_version >= 8.4 && [tk windowingsystem] == "aqua"} { 603 # resize control space 604 grid columnconfigure $sbar [lindex [grid size $sbar] 0] -minsize 16 605 } 606 607 ## Create console tab 608 set con [InitTab $w] 609 set PRIV(curtab) $con 610 611 # Only apply this for the first console 612 $con configure -setgrid 1 -width $OPT(cols) -height $OPT(rows) 613 bind $PRIV(root) <Configure> { 614 if {"%W" == $::tkcon::PRIV(root)} { 615 scan [wm geometry [winfo toplevel %W]] "%%dx%%d" \ 616 ::tkcon::OPT(cols) ::tkcon::OPT(rows) 617 if {[info exists ::tkcon::EXP(spawn_id)]} { 618 catch {stty rows $::tkcon::OPT(rows) columns \ 619 $::tkcon::OPT(cols) < $::tkcon::EXP(slave,name)} 620 } 621 } 622 } 623 624 # scrollbar 625 set sy [scrollbar $w.sy -takefocus 0 -bd 1 -command [list $con yview]] 626 if {!$PRIV(WWW) && [string match "Windows CE" $::tcl_platform(os)]} { 627 $w.sy configure -width 10 628 } 629 630 $con configure -yscrollcommand [list $sy set] 631 set PRIV(console) $con 632 set PRIV(scrolly) $sy 633 634 ## Menus 635 ## catch against use in plugin 636 if {[catch {menu $w.mbar} PRIV(menubar)]} { 637 set PRIV(menubar) [frame $w.mbar -relief raised -bd 1] 638 } 639 640 InitMenus $PRIV(menubar) $title 641 Bindings 642 643 if {$OPT(showmenu)} { 644 $root configure -menu $PRIV(menubar) 645 } 646 647 grid $con -row 1 -column 1 -sticky news 648 grid $sy -row 1 -column [expr {$OPT(scrollypos)=="left"?0:2}] -sticky ns 649 grid $sbar -row 2 -column 0 -columnspan 3 -sticky ew 650 651 grid columnconfigure $root 1 -weight 1 652 grid rowconfigure $root 1 -weight 1 653 654 if {!$OPT(showstatusbar)} { 655 grid remove $sbar 656 } 657 658 if {!$PRIV(WWW)} { 659 wm title $root "tkcon $PRIV(version) $title" 660 if {$PRIV(showOnStartup)} { wm deiconify $root } 661 } 662 if {$PRIV(showOnStartup)} { focus -force $PRIV(console) } 663 if {$OPT(gc-delay)} { 664 after $OPT(gc-delay) ::tkcon::GarbageCollect 665 } 666 } 667 668 proc ::tkcon::InitTab {w} { 669 variable OPT 670 variable PRIV 671 variable COLOR 672 variable ATTACH 673 674 # text console 675 set con $w.tab[incr PRIV(uid)] 676 text $con -wrap char -foreground $COLOR(stdin) \ 677 -insertbackground $COLOR(cursor) 553 678 $con mark set output 1.0 554 679 $con mark set limit 1.0 … … 560 685 ## Set user-requested font, if any 561 686 $con configure -font $OPT(font) 562 } else {687 } elseif {[string compare unix $::tcl_platform(platform)]} { 563 688 ## otherwise make sure the font is monospace 564 689 set font [$con cget -font] 565 690 if {![font metrics $font -fixed]} { 566 font create tkconfixed -family Courier -size 12567 691 $con configure -font tkconfixed 568 692 } 693 } else { 694 $con configure -font tkconfixed 569 695 } 570 696 set OPT(font) [$con cget -font] 697 bindtags $con [list $con TkConsole TkConsolePost $PRIV(root) all] 698 699 # scrollbar 571 700 if {!$PRIV(WWW)} { 572 $con configure -setgrid 1 -width $OPT(cols) -height $OPT(rows) 573 } 574 bindtags $con [list $con TkConsole TkConsolePost $root all] 575 ## Menus 576 ## catch against use in plugin 577 if {[catch {menu $w.mbar} PRIV(menubar)]} { 578 set PRIV(menubar) [frame $w.mbar -relief raised -bd 1] 579 } 580 ## Scrollbar 581 set PRIV(scrolly) [scrollbar $w.sy -takefocus 0 -bd 1 \ 582 -command [list $con yview]] 583 584 InitMenus $PRIV(menubar) $title 585 Bindings 586 587 if {$OPT(showmenu)} { 588 $root configure -menu $PRIV(menubar) 589 } 590 pack $w.sy -side $OPT(scrollypos) -fill y 591 pack $con -fill both -expand 1 592 593 set PRIV(statusbar) [set sbar [frame $w.sbar]] 594 label $sbar.attach -relief sunken -bd 1 -anchor w \ 595 -textvariable ::tkcon::PRIV(StatusAttach) 596 label $sbar.mode -relief sunken -bd 1 -anchor w \ 597 -textvariable ::tkcon::PRIV(StatusMode) 598 label $sbar.cursor -relief sunken -bd 1 -anchor w -width 6 \ 599 -textvariable ::tkcon::PRIV(StatusCursor) 600 grid $sbar.attach $sbar.mode $sbar.cursor -sticky news -padx 1 601 grid columnconfigure $sbar 0 -weight 1 602 grid columnconfigure $sbar 1 -weight 1 603 grid columnconfigure $sbar 2 -weight 0 604 605 if {$OPT(showstatusbar)} { 606 pack $sbar -side bottom -fill x -before $::tkcon::PRIV(scrolly) 607 } 701 if {[string match "Windows CE" $::tcl_platform(os)]} { 702 font configure tkconfixed -family Tahoma -size 8 703 $con configure -font tkconfixed -bd 0 -padx 0 -pady 0 704 set cw [font measure tkconfixed "0"] 705 set ch [font metrics tkconfixed -linespace] 706 set sw [winfo screenwidth $con] 707 set sh [winfo screenheight $con] 708 # We need the magic hard offsets until I find a way to 709 # correctly assume size 710 if {$cw*($OPT(cols)+2) > $sw} { 711 set OPT(cols) [expr {($sw / $cw) - 2}] 712 } 713 if {$ch*($OPT(rows)+3) > $sh} { 714 set OPT(rows) [expr {($sh / $ch) - 3}] 715 } 716 # Place it so that the titlebar underlaps the CE titlebar 717 wm geometry $PRIV(root) +0+0 718 } 719 } 720 $con configure -height $OPT(rows) -width $OPT(cols) 608 721 609 722 foreach col {prompt stdout stderr stdin proc} { … … 615 728 $con tag configure find -background $COLOR(blink) 616 729 617 if {!$PRIV(WWW)} { 618 wm title $root "tkcon $PRIV(version) $title" 619 bind $con <Configure> { 620 scan [wm geometry [winfo toplevel %W]] "%%dx%%d" \ 621 ::tkcon::OPT(cols) ::tkcon::OPT(rows) 622 } 623 if {$PRIV(showOnStartup)} { wm deiconify $root } 624 } 625 if {$PRIV(showOnStartup)} { focus -force $PRIV(console) } 626 if {$OPT(gc-delay)} { 627 after $OPT(gc-delay) ::tkcon::GarbageCollect 628 } 730 set ATTACH($con) [Attach] 731 set rb [radiobutton $PRIV(tabframe).cb[winfo name $con] \ 732 -textvariable ::tkcon::ATTACH($con) \ 733 -selectcolor white -relief sunken \ 734 -indicatoron 0 -padx 0 -pady 0 -bd 1 \ 735 -variable ::tkcon::PRIV(curtab) -value $con \ 736 -command [list ::tkcon::GotoTab $con]] 737 if {$::tcl_version >= 8.4} { 738 $rb configure -offrelief flat -overrelief raised 739 } 740 grid $rb -row 0 -column [lindex [grid size $PRIV(tabframe)] 0] -sticky ns 741 grid $con -row 1 -column 1 -sticky news 742 743 lappend PRIV(tabs) $con 744 return $con 745 } 746 747 proc ::tkcon::GotoTab {con} { 748 variable PRIV 749 variable ATTACH 750 751 set numtabs [llength $PRIV(tabs)] 752 #if {$numtabs == 1} { return } 753 754 if {[regexp {^[0-9]+$} $con]} { 755 set curtab [lsearch -exact $PRIV(tabs) $PRIV(console)] 756 set nexttab [expr {$curtab + $con}] 757 if {$nexttab >= $numtabs} { 758 set nexttab 0 759 } elseif {$nexttab < 0} { 760 set nexttab "end" 761 } 762 set con [lindex $PRIV(tabs) $nexttab] 763 } elseif {$con == $PRIV(console)} { 764 return 765 } 766 767 # adjust console 768 if {[winfo exists $PRIV(console)]} { 769 lower $PRIV(console) 770 $PRIV(console) configure -yscrollcommand {} 771 set ATTACH($PRIV(console)) [Attach] 772 } 773 set PRIV(console) $con 774 $con configure -yscrollcommand [list $PRIV(scrolly) set] 775 $PRIV(scrolly) configure -command [list $con yview] 776 777 # adjust attach 778 eval [linsert $ATTACH($con) 0 Attach] 779 780 set PRIV(curtab) $con 781 782 raise $con 783 784 if {[$con compare 1.0 == end-1c]} { 785 Prompt 786 } 787 788 # set StatusCursor 789 set PRIV(StatusCursor) [$con index insert] 790 791 focus -force $con 792 } 793 794 proc ::tkcon::NewTab {{con {}}} { 795 variable PRIV 796 variable ATTACH 797 798 set con [InitTab $PRIV(base)] 799 set slave [interp create Slave[GetSlaveNum]] 800 InitSlave $slave 801 $slave alias exit ::tkcon::DeleteTab $con $slave 802 set ATTACH($con) [list $slave slave] 803 $PRIV(X) configure -state normal 804 MenuConfigure Console "Delete Tab" -state normal 805 GotoTab $con 806 } 807 808 # The extra code arg is for the alias of exit to this function 809 proc ::tkcon::DeleteTab {{con {}} {slave {}} {code 0}} { 810 variable PRIV 811 812 set numtabs [llength $PRIV(tabs)] 813 if {$numtabs <= 2} { 814 $PRIV(X) configure -state disabled 815 MenuConfigure Console "Delete Tab" -state disabled 816 } 817 if {$numtabs == 1} { 818 # in the master, it should do the right thing 819 # currently the first master still exists - need rearch to fix 820 exit 821 # we might end up here, depending on how exit is rerouted 822 return 823 } 824 825 if {$con == ""} { 826 set con $PRIV(console) 827 } 828 catch {unset ATTACH($con)} 829 set curtab [lsearch -exact $PRIV(tabs) $con] 830 set PRIV(tabs) [lreplace $PRIV(tabs) $curtab $curtab] 831 832 set numtabs [llength $PRIV(tabs)] 833 set nexttab $curtab 834 if {$nexttab >= $numtabs} { 835 set nexttab end 836 } 837 set nexttab [lindex $PRIV(tabs) $nexttab] 838 839 GotoTab $nexttab 840 841 if {$slave != "" && $slave != $::tkcon::OPT(exec)} { 842 interp delete $slave 843 } 844 destroy $PRIV(tabframe).cb[winfo name $con] 845 destroy $con 629 846 } 630 847 … … 635 852 variable PRIV 636 853 637 set w $PRIV(console) 638 ## Remove error tags that no longer span anything 639 ## Make sure the tag pattern matches the unique tag prefix 640 foreach tag [$w tag names] { 641 if {[string match _tag* $tag] && ![llength [$w tag ranges $tag]]} { 642 $w tag delete $tag 854 foreach w $PRIV(tabs) { 855 if {[winfo exists $w]} { 856 ## Remove error tags that no longer span anything 857 ## Make sure the tag pattern matches the unique tag prefix 858 foreach tag [$w tag names] { 859 if {[string match _tag* $tag] 860 && ![llength [$w tag ranges $tag]]} { 861 $w tag delete $tag 862 } 863 } 643 864 } 644 865 } … … 666 887 EvalCmd $w $last 667 888 } 668 $w see insert 889 if {[winfo exists $w]} { 890 $w see insert 891 } 669 892 } 670 893 … … 686 909 set ev [EvalSlave history nextid] 687 910 incr ev -1 911 ## FIX: calcmode doesn't work with requesting history events 688 912 if {[string match !! $cmd]} { 689 913 set code [catch {EvalSlave history event $ev} cmd] … … 703 927 } 704 928 } elseif {$OPT(calcmode) && ![catch {expr $cmd} err]} { 705 EvalSlave history add$cmd929 AddSlaveHistory $cmd 706 930 set cmd $err 707 931 set code -1 … … 736 960 } 737 961 } 738 EvalSlave history add $cmd 962 if {![winfo exists $w]} { 963 # early abort - must be a deleted tab 964 return 965 } 966 AddSlaveHistory $cmd 967 catch {EvalAttached [list set _ $res]} 968 set maxlen $OPT(maxlinelen) 969 set trailer "" 970 if {($maxlen > 0) && ([string length $res] > $maxlen)} { 971 # If we exceed maximum desired output line length, truncate 972 # the result and add "...+${num}b" in error coloring 973 set trailer ...+[expr {[string length $res]-$maxlen}]b 974 set res [string range $res 0 $maxlen] 975 } 739 976 if {$code} { 740 977 if {$OPT(hoterrors)} { 741 978 set tag [UniqueTag $w] 742 $w insert output $res [list stderr $tag] \n stderr979 $w insert output $res [list stderr $tag] \n$trailer stderr 743 980 $w tag bind $tag <Enter> \ 744 981 [list $w tag configure $tag -under 1] … … 747 984 $w tag bind $tag <ButtonRelease-1> \ 748 985 "if {!\[info exists tkPriv(mouseMoved)\] || !\$tkPriv(mouseMoved)} \ 749 {[list edit-attach [Attach] -type error -- $PRIV(errorInfo)]}"986 {[list $OPT(edit) -attach [Attach] -type error -- $PRIV(errorInfo)]}" 750 987 } else { 751 $w insert output $res\n stderr988 $w insert output $res\n$trailer stderr 752 989 } 753 990 } elseif {[string compare {} $res]} { 754 $w insert output $res \n stdout991 $w insert output $res stdout $trailer stderr \n stdout 755 992 } 756 993 } … … 778 1015 return [Slave $app $args] 779 1016 } else { 780 return [uplevel 1 send [list $app] $args] 1017 return [uplevel 1 ::send::send [list $app] $args] 1018 } 1019 } 1020 1021 ## ::tkcon::AddSlaveHistory - 1022 ## Command is added to history only if different from previous command. 1023 ## This also doesn't cause the history id to be incremented, although the 1024 ## command will be evaluated. 1025 # ARGS: cmd - command to add 1026 ## 1027 proc ::tkcon::AddSlaveHistory cmd { 1028 set ev [EvalSlave history nextid] 1029 incr ev -1 1030 set code [catch {EvalSlave history event $ev} lastCmd] 1031 if {$code || [string compare $cmd $lastCmd]} { 1032 EvalSlave history add $cmd 781 1033 } 782 1034 } … … 793 1045 794 1046 if {$PRIV(deadapp)} { 795 if {[lsearch -exact [ winfointerps] $PRIV(app)]<0} {1047 if {[lsearch -exact [::send::interps] $PRIV(app)]<0} { 796 1048 return 797 1049 } else { … … 801 1053 } 802 1054 } 803 set code [catch { send -displayof $PRIV(displayWin) $PRIV(app) $cmd} result]804 if {$code && [lsearch -exact [ winfointerps] $PRIV(app)]<0} {1055 set code [catch {::send::send -displayof $PRIV(displayWin) $PRIV(app) $cmd} result] 1056 if {$code && [lsearch -exact [::send::interps] $PRIV(app)]<0} { 805 1057 ## Interpreter disappeared 806 1058 if {[string compare leave $OPT(dead)] && \ 807 1059 ([string match ignore $OPT(dead)] || \ 808 [tk_dialog $PRIV(base).dead "Dead Attachment" \ 809 "\"$PRIV(app)\" appears to have died.\ 810 \nReturn to primary slave interpreter?" questhead 0 OK No])} { 1060 [tk_messageBox -title "Dead Attachment" -type yesno \ 1061 -icon info -message \ 1062 "\"$PRIV(app)\" appears to have died.\ 1063 \nReturn to primary slave interpreter?"]=="no")} { 811 1064 set PRIV(appname) "DEAD:$PRIV(appname)" 812 1065 set PRIV(deadapp) 1 … … 854 1107 ## Interpreter died or disappeared 855 1108 puts "$code eof [eof $PRIV(app)]" 856 EvalSocketClosed 1109 EvalSocketClosed $PRIV(app) 857 1110 } 858 1111 return -code $code $result … … 865 1118 # Returns: the result of the command 866 1119 ## 867 proc ::tkcon::EvalSocketEvent { } {1120 proc ::tkcon::EvalSocketEvent {sock} { 868 1121 variable PRIV 869 1122 870 if {[gets $ PRIV(app)line] == -1} {871 if {[eof $ PRIV(app)]} {872 EvalSocketClosed 1123 if {[gets $sock line] == -1} { 1124 if {[eof $sock]} { 1125 EvalSocketClosed $sock 873 1126 } 874 1127 return … … 882 1135 # Returns: the result of the command 883 1136 ## 884 proc ::tkcon::EvalSocketClosed { } {1137 proc ::tkcon::EvalSocketClosed {sock} { 885 1138 variable OPT 886 1139 variable PRIV 887 1140 888 catch {close $PRIV(app)} 1141 catch {close $sock} 1142 if {![string match $sock $PRIV(app)]} { 1143 # If we are not still attached to that socket, just return. 1144 # Might be nice to tell the user the socket closed ... 1145 return 1146 } 889 1147 if {[string compare leave $OPT(dead)] && \ 890 1148 ([string match ignore $OPT(dead)] || \ 891 [tk_dialog $PRIV(base).dead "Dead Attachment" \ 892 "\"$PRIV(app)\" appears to have died.\ 893 \nReturn to primary slave interpreter?" questhead 0 OK No])} { 1149 [tk_messageBox -title "Dead Attachment" -type yesno \ 1150 -icon question \ 1151 -message "\"$PRIV(app)\" appears to have died.\ 1152 \nReturn to primary slave interpreter?"] == "no")} { 894 1153 set PRIV(appname) "DEAD:$PRIV(appname)" 895 1154 set PRIV(deadapp) 1 … … 1014 1273 ## 1015 1274 proc ::tkcon::ConstrainBuffer {w size} { 1016 if { [$w index end] > $size} {1275 if {$size && ([$w index end] > $size)} { 1017 1276 $w delete 1.0 [expr {int([$w index end])-$size}].0 1018 1277 } … … 1028 1287 1029 1288 set w $PRIV(console) 1289 if {![winfo exists $w]} { return } 1030 1290 if {[string compare {} $pre]} { $w insert end $pre stdout } 1031 1291 set i [$w index end-1c] … … 1052 1312 $w see end 1053 1313 } 1314 proc ::tkcon::RePrompt {{pre {}} {post {}} {prompt {}}} { 1315 # same as prompt, but does nothing for those actions where we 1316 # only wanted to refresh the prompt on attach change when the 1317 # statusbar is showing (which carries that info instead) 1318 variable OPT 1319 if {!$OPT(showstatusbar)} { 1320 Prompt $pre $post $prompt 1321 } 1322 } 1054 1323 1055 1324 ## ::tkcon::About - gives about info for tkcon … … 1061 1330 1062 1331 set w $PRIV(base).about 1063 if {[winfo exists $w]} { 1064 wm deiconify $w 1065 } else { 1332 if {![winfo exists $w]} { 1066 1333 global tk_patchLevel tcl_patchLevel tcl_version 1067 1334 toplevel $w 1335 wm withdraw $w 1336 wm transient $w $PRIV(root) 1337 wm group $w $PRIV(root) 1068 1338 wm title $w "About tkcon v$PRIV(version)" 1069 1339 button $w.b -text Dismiss -command [list wm withdraw $w] … … 1079 1349 regexp {,v ([0-9\./: ]*)} $PRIV(RCS) -> RCS 1080 1350 $w.text insert 1.0 "About tkcon v$PRIV(version)" title \ 1081 "\n\nCopyright 1995-200 1Jeffrey Hobbs, $PRIV(email)\1351 "\n\nCopyright 1995-2002 Jeffrey Hobbs, $PRIV(email)\ 1082 1352 \nRelease Info: v$PRIV(version), CVS v$RCS\ 1083 1353 \nDocumentation available at:\n$PRIV(docs)\ 1084 1354 \nUsing: Tcl v$tcl_patchLevel / Tk v$tk_patchLevel" center 1085 1355 $w.text config -state disabled 1086 } 1356 bind $w <Escape> [list destroy $w] 1357 } 1358 wm deiconify $w 1087 1359 } 1088 1360 … … 1096 1368 global tcl_platform 1097 1369 1098 if {[catch {menu $w.pop -tearoff 0}]} {1370 if {[catch {menu $w.pop}]} { 1099 1371 label $w.label -text "Menus not available in plugin mode" 1100 pack $w.label1372 grid $w.label -sticky ew 1101 1373 return 1102 1374 } 1103 menu $w.context - tearoff 0 -disabledforeground $COLOR(disabled)1375 menu $w.context -disabledforeground $COLOR(disabled) 1104 1376 set PRIV(context) $w.context 1105 1377 set PRIV(popup) $w.pop … … 1108 1380 $w add cascade -label $m -underline 0 -menu $w.$l 1109 1381 return $w.$l 1382 } 1383 proc MenuConfigure {m l args} { 1384 variable PRIV 1385 eval [list $PRIV(menubar).[string tolower $m] entryconfigure $l] $args 1386 eval [list $PRIV(popup).[string tolower $m] entryconfigure $l] $args 1110 1387 } 1111 1388 … … 1128 1405 ## 1129 1406 set s $m.save 1130 menu $s -disabledforeground $COLOR(disabled) -tearoff 01407 menu $s -disabledforeground $COLOR(disabled) 1131 1408 $s add command -label "All" -underline 0 \ 1132 1409 -command {::tkcon::Save {} all} … … 1148 1425 $m add command -label "New Console" -underline 0 -accel Ctrl-N \ 1149 1426 -command ::tkcon::New 1427 $m add command -label "New Tab" -underline 4 -accel Ctrl-T \ 1428 -command ::tkcon::NewTab 1429 $m add command -label "Delete Tab" -underline 0 \ 1430 -command ::tkcon::DeleteTab -state disabled 1150 1431 $m add command -label "Close Console" -underline 0 -accel Ctrl-w \ 1151 1432 -command ::tkcon::Destroy … … 1158 1439 } 1159 1440 $m add separator 1160 $m add cascade -label "Attach To ..." 1441 $m add cascade -label "Attach To ..." -underline 0 -menu $m.attach 1161 1442 1162 1443 ## Attach Console Menu 1163 1444 ## 1164 1445 set sub [menu $m.attach -disabledforeground $COLOR(disabled)] 1165 $sub add cascade -label "Interpreter" -underline 0 -menu $sub.apps 1166 $sub add cascade -label "Namespace" -underline 1 -menu $sub.name 1167 $sub add cascade -label "Socket" -underline 1 -menu $sub.sock \ 1168 -state [expr {([info tclversion] < 8.3)?"disabled":"normal"}] 1446 $sub add cascade -label "Interpreter" -underline 0 -menu $sub.apps 1447 $sub add cascade -label "Namespace" -underline 0 -menu $sub.name 1169 1448 1170 1449 ## Attach Console Menu … … 1175 1454 ## Attach Namespace Menu 1176 1455 ## 1177 menu $sub.name -disabledforeground $COLOR(disabled) -tearoff 0\1456 menu $sub.name -disabledforeground $COLOR(disabled) \ 1178 1457 -postcommand [list ::tkcon::NamespaceMenu $sub.name] 1179 1458 1180 1459 if {$::tcl_version >= 8.3} { 1460 ## Attach Socket Menu 1461 ## 1181 1462 # This uses [file channels] to create the menu, so we only 1182 1463 # want it for newer versions of Tcl. 1183 1184 ## Attach Socket Menu 1464 $sub add cascade -label "Socket" -underline 0 -menu $sub.sock 1465 menu $sub.sock -disabledforeground $COLOR(disabled) \ 1466 -postcommand [list ::tkcon::SocketMenu $sub.sock] 1467 } 1468 1469 if {![string compare "unix" $tcl_platform(platform)]} { 1470 ## Attach Display Menu 1185 1471 ## 1186 menu $sub.sock -disabledforeground $COLOR(disabled) -tearoff 0 \ 1187 -postcommand [list ::tkcon::SocketMenu $sub.sock] 1188 } 1189 1190 ## Attach Display Menu 1191 ## 1192 if {![string compare "unix" $tcl_platform(platform)]} { 1193 $sub add cascade -label "Display" -und 1 -menu $sub.disp 1472 $sub add cascade -label "Display" -underline 0 -menu $sub.disp 1194 1473 menu $sub.disp -disabledforeground $COLOR(disabled) \ 1195 -tearoff 0 \1196 1474 -postcommand [list ::tkcon::DisplayMenu $sub.disp] 1197 1475 } … … 1230 1508 -underline 0 -variable ::tkcon::OPT(subhistory) 1231 1509 $m add check -label "Hot Errors" \ 1232 -underline 0-variable ::tkcon::OPT(hoterrors)1510 -underline 4 -variable ::tkcon::OPT(hoterrors) 1233 1511 $m add check -label "Non-Tcl Attachments" \ 1234 1512 -underline 0 -variable ::tkcon::OPT(nontcl) … … 1242 1520 {$::tkcon::OPT(showmenu) ? $::tkcon::PRIV(menubar) : {}}]} 1243 1521 $m add check -label "Show Statusbar" \ 1244 -underline 5 -variable ::tkcon::OPT(showstatusbar) \ 1245 -command { 1246 if {$::tkcon::OPT(showstatusbar)} { 1247 pack $::tkcon::PRIV(statusbar) -side bottom -fill x \ 1248 -before $::tkcon::PRIV(scrolly) 1249 } else { pack forget $::tkcon::PRIV(statusbar) } 1250 } 1522 -underline 5 -variable ::tkcon::OPT(showstatusbar) \ 1523 -command { 1524 if {$::tkcon::OPT(showstatusbar)} { 1525 grid $::tkcon::PRIV(statusbar) 1526 } else { grid remove $::tkcon::PRIV(statusbar) } 1527 } 1251 1528 $m add cascade -label "Scrollbar" -underline 2 -menu $m.scroll 1252 1529 1253 1530 ## Scrollbar Menu 1254 1531 ## 1255 set m [menu $m.scroll -tearoff 0]1532 set m [menu $m.scroll] 1256 1533 $m add radio -label "Left" -value left \ 1257 1534 -variable ::tkcon::OPT(scrollypos) \ 1258 -command { pack config $::tkcon::PRIV(scrolly) -side left}1535 -command { grid configure $::tkcon::PRIV(scrolly) -column 0 } 1259 1536 $m add radio -label "Right" -value right \ 1260 1537 -variable ::tkcon::OPT(scrollypos) \ 1261 -command { pack config $::tkcon::PRIV(scrolly) -side right}1538 -command { grid configure $::tkcon::PRIV(scrolly) -column 2 } 1262 1539 } 1263 1540 … … 1276 1553 $m add command -label "Retrieve Latest Version" -underline 0 \ 1277 1554 -command ::tkcon::Retrieve 1555 if {![catch {package require ActiveTcl} ver]} { 1556 set cmd "" 1557 if {$tcl_platform(platform) == "windows"} { 1558 package require registry 1559 set ver [join [lrange [split $ver .] 0 3] .] 1560 set key {HKEY_LOCAL_MACHINE\SOFTWARE\ActiveState\ActiveTcl} 1561 if {![catch {registry get "$key\\$ver\\Help" ""} help] 1562 && [file exists $help]} { 1563 set cmd [list exec $::env(COMSPEC) /c start $help] 1564 } 1565 } elseif {$tcl_platform(os) == "Darwin"} { 1566 set ver ActiveTcl-[join [lrange [split $ver .] 0 1] .] 1567 set rsc "/Library/Frameworks/Tcl.framework/Resources" 1568 set help "$rsc/English.lproj/$ver/index.html" 1569 if {[file exists $help]} { 1570 set cmd [list exec open $help] 1571 } 1572 } elseif {$tcl_platform(platform) == "unix"} { 1573 set help [file dirname [info nameofexe]] 1574 append help /../html/index.html 1575 if {[file exists $help]} { 1576 set cmd [list puts "Start $help"] 1577 } 1578 } 1579 if {$cmd != ""} { 1580 $m add separator 1581 $m add command -label "ActiveTcl Help" -underline 10 \ 1582 -command $cmd 1583 } 1584 } 1278 1585 } 1279 1586 } … … 1332 1639 ## 1333 1640 $w add separator 1334 $w add cascade -label Packages -underline 0 -menu $w.pkg 1335 set m $w.pkg 1336 if {![winfo exists $m]} { 1337 menu $m -tearoff no -disabledforeground $COLOR(disabled) \ 1338 -postcommand [list ::tkcon::PkgMenu $m $app $type] 1339 } 1641 $w add command -label "Manage Packages" -underline 0 \ 1642 -command [list ::tkcon::InterpPkgs $app $type] 1340 1643 1341 1644 ## State Checkpoint/Revert … … 1359 1662 ## with a list of all the applications that currently exist. 1360 1663 ## 1361 proc ::tkcon::PkgMenu {m app type} { 1664 proc ::tkcon::InterpPkgs {app type} { 1665 variable PRIV 1666 1667 set t $PRIV(base).interppkgs 1668 if {![winfo exists $t]} { 1669 toplevel $t 1670 wm withdraw $t 1671 wm title $t "$app Packages" 1672 wm transient $t $PRIV(root) 1673 wm group $t $PRIV(root) 1674 bind $t <Escape> [list destroy $t] 1675 1676 label $t.ll -text "Loadable:" -anchor w 1677 label $t.lr -text "Loaded:" -anchor w 1678 listbox $t.loadable -bg white -bd 1 -font tkconfixed \ 1679 -yscrollcommand [list $t.llsy set] -selectmode extended 1680 listbox $t.loaded -bg white -bd 1 -font tkconfixed \ 1681 -yscrollcommand [list $t.lrsy set] 1682 scrollbar $t.llsy -bd 1 -command [list $t.loadable yview] 1683 scrollbar $t.lrsy -bd 1 -command [list $t.loaded yview] 1684 button $t.load -bd 1 -text ">>" \ 1685 -command [list ::tkcon::InterpPkgLoad $app $type $t.loadable] 1686 if {$::tcl_version >= 8.4} { 1687 $t.load configure -relief flat -overrelief raised 1688 } 1689 1690 set f [frame $t.btns] 1691 button $f.refresh -width 8 -text "Refresh" -command [info level 0] 1692 button $f.dismiss -width 8 -text "Dismiss" -command [list destroy $t] 1693 grid $f.refresh $f.dismiss -padx 4 -pady 3 -sticky ew 1694 1695 grid $t.ll x x $t.lr x -sticky ew 1696 grid $t.loadable $t.llsy $t.load $t.loaded $t.lrsy -sticky news 1697 grid $t.btns -sticky e -columnspan 5 1698 grid columnconfigure $t {0 3} -weight 1 1699 grid rowconfigure $t 1 -weight 1 1700 grid configure $t.load -sticky "" 1701 1702 bind $t.loadable <Double-1> "[list $t.load invoke]; break" 1703 } 1704 $t.loaded delete 0 end 1705 $t.loadable delete 0 end 1706 1362 1707 # just in case stuff has been added to the auto_path 1363 1708 # we have to make sure that the errorInfo doesn't get screwed up … … 1368 1713 unset __tkcon_error 1369 1714 } 1370 $m delete 0 end1715 # get all packages loaded into current interp 1371 1716 foreach pkg [EvalAttached [list info loaded {}]] { 1372 set loaded([lindex $pkg 1]) [package provide $pkg] 1373 } 1717 set pkg [lindex $pkg 1] 1718 set loaded($pkg) [package provide $pkg] 1719 } 1720 # get all package names currently visible 1374 1721 foreach pkg [lremove [EvalAttached {package names}] Tcl] { 1375 1722 set version [EvalAttached [list package provide $pkg]] … … 1377 1724 set loaded($pkg) $version 1378 1725 } elseif {![info exists loaded($pkg)]} { 1379 set loadable($pkg) [list package require $pkg] 1380 } 1381 } 1726 set loadable($pkg) package 1727 } 1728 } 1729 # get packages that are loaded in any interp 1382 1730 foreach pkg [EvalAttached {info loaded}] { 1383 1731 set pkg [lindex $pkg 1] 1384 1732 if {![info exists loaded($pkg)] && ![info exists loadable($pkg)]} { 1385 set loadable($pkg) [list load {} $pkg] 1386 } 1387 } 1388 set npkg 0 1733 set loadable($pkg) load 1734 } 1735 } 1389 1736 foreach pkg [lsort -dictionary [array names loadable]] { 1390 1737 foreach v [EvalAttached [list package version $pkg]] { 1391 set brkcol [expr {([incr npkg]%16)==0}] 1392 $m add command -label "Load $pkg ($v)" -command \ 1393 "::tkcon::EvalOther [list $app] $type $loadable($pkg) $v" \ 1394 -columnbreak $brkcol 1395 } 1396 } 1397 if {[info exists loaded] && [info exists loadable]} { 1398 $m add separator 1738 $t.loadable insert end [list $pkg $v "($loadable($pkg))"] 1739 } 1399 1740 } 1400 1741 foreach pkg [lsort -dictionary [array names loaded]] { 1401 $m add command -label "${pkg}$loaded($pkg) Loaded" -state disabled 1402 } 1742 $t.loaded insert end [list $pkg $loaded($pkg)] 1743 } 1744 1745 wm deiconify $t 1746 raise $t 1747 } 1748 1749 proc ::tkcon::InterpPkgLoad {app type lb} { 1750 # load the lb entry items into the interp 1751 foreach sel [$lb curselection] { 1752 foreach {pkg ver method} [$lb get $sel] { break } 1753 if {$method == "(package)"} { 1754 set code [catch {::tkcon::EvalOther $app $type \ 1755 package require $pkg $ver} msg] 1756 } elseif {$method == "(load)"} { 1757 set code [catch {::tkcon::EvalOther $app $type load {} $pkg} msg] 1758 } else { 1759 set code 1 1760 set msg "Incorrect entry in Loadable selection" 1761 } 1762 if {$code} { 1763 tk_messageBox -icon error -title "Error requiring $pkg" -type ok \ 1764 -message "Error requiring $pkg $ver:\n$msg\n$::errorInfo" 1765 } 1766 } 1767 # refresh package list 1768 InterpPkgs $app $type 1403 1769 } 1404 1770 … … 1414 1780 1415 1781 $m delete 0 end 1416 set cmd {::tkcon:: Prompt \n [::tkcon::CmdGet $::tkcon::PRIV(console)]}1782 set cmd {::tkcon::RePrompt \n [::tkcon::CmdGet $::tkcon::PRIV(console)]} 1417 1783 $m add radio -label {None (use local slave) } -accel Ctrl-1 \ 1418 1784 -variable ::tkcon::PRIV(app) \ … … 1421 1787 $m add separator 1422 1788 $m add command -label "Foreign Tk Interpreters" -state disabled 1423 foreach i [lsort [lremove [ winfointerps] [array names tknames]]] {1789 foreach i [lsort [lremove [::send::interps] [array names tknames]]] { 1424 1790 $m add radio -label $i -variable ::tkcon::PRIV(app) -value $i \ 1425 1791 -command "::tkcon::Attach [list $i] interp; $cmd" … … 1457 1823 proc ::tkcon::DisplayMenu m { 1458 1824 $m delete 0 end 1459 set cmd {::tkcon:: Prompt \n [::tkcon::CmdGet $::tkcon::PRIV(console)]}1825 set cmd {::tkcon::RePrompt \n [::tkcon::CmdGet $::tkcon::PRIV(console)]} 1460 1826 1461 1827 $m add command -label "New Display" -command ::tkcon::NewDisplay … … 1476 1842 proc ::tkcon::SocketMenu m { 1477 1843 $m delete 0 end 1478 set cmd {::tkcon:: Prompt \n [::tkcon::CmdGet $::tkcon::PRIV(console)]}1844 set cmd {::tkcon::RePrompt \n [::tkcon::CmdGet $::tkcon::PRIV(console)]} 1479 1845 1480 1846 $m add command -label "Create Connection" \ … … 1500 1866 1501 1867 ## Same command as for ::tkcon::AttachMenu items 1502 set cmd {::tkcon:: Prompt \n [::tkcon::CmdGet $::tkcon::PRIV(console)]}1868 set cmd {::tkcon::RePrompt \n [::tkcon::CmdGet $::tkcon::PRIV(console)]} 1503 1869 1504 1870 set names [lsort [Namespaces ::]] … … 1557 1923 ## Catch in case the namespace disappeared on us 1558 1924 catch { ::tkcon::AttachNamespace [%W get [%W nearest %y]] } 1559 ::tkcon:: Prompt "\n" [::tkcon::CmdGet $::tkcon::PRIV(console)]1925 ::tkcon::RePrompt "\n" [::tkcon::CmdGet $::tkcon::PRIV(console)] 1560 1926 destroy [winfo toplevel %W] 1561 1927 } … … 1685 2051 # appropriate interpreter 1686 2052 ## 1687 proc ::tkcon::Attach {{name <NONE>} {type slave} } {2053 proc ::tkcon::Attach {{name <NONE>} {type slave} {ns {}}} { 1688 2054 variable PRIV 1689 2055 variable OPT 2056 variable ATTACH 1690 2057 1691 2058 if {[llength [info level 0]] == 1} { 1692 2059 # no args were specified, return the attach info instead 1693 if {[string match {} $PRIV(appname)]} { 1694 return [list [concat $PRIV(name) $OPT(exec)] $PRIV(apptype)] 1695 } else { 1696 return [list $PRIV(appname) $PRIV(apptype)] 1697 } 2060 return [AttachId] 1698 2061 } 1699 2062 set path [concat $PRIV(name) $OPT(exec)] … … 1732 2095 set name [concat $path $name] 1733 2096 set type slave 1734 } elseif {[lsearch -exact [ winfointerps] $name] > -1} {2097 } elseif {[lsearch -exact [::send::interps] $name] > -1} { 1735 2098 if {[EvalSlave info exists tk_library] \ 1736 2099 && [string match $name [EvalSlave tk appname]]} { … … 1761 2124 # ARGS: args - the command and args to evaluate 1762 2125 ## 2126 set PRIV(namesp) :: 2127 set namespOK 0 1763 2128 switch -glob -- $type { 1764 2129 slave { … … 1774 2139 ::tkcon::Slave $::tkcon::PRIV(app) 1775 2140 } 2141 set namespOK 1 1776 2142 } 1777 2143 sock* { … … 1781 2147 # into the interpreter 1782 2148 fconfigure $name -buffering line -blocking 0 1783 fileevent $name readable ::tkcon::EvalSocketEvent2149 fileevent $name readable [list ::tkcon::EvalSocketEvent $name] 1784 2150 } 1785 2151 dpy:* - … … 1787 2153 if {$OPT(nontcl)} { 1788 2154 interp alias {} ::tkcon::EvalAttached {} ::tkcon::EvalSlave 1789 set PRIV(namesp) ::1790 2155 } else { 1791 2156 interp alias {} ::tkcon::EvalAttached {} ::tkcon::EvalSend 2157 set namespOK 1 1792 2158 } 1793 2159 } … … 1797 2163 } 1798 2164 } 1799 if {[string match slave $type] || \ 1800 (!$OPT(nontcl) && [regexp {^(interp|dpy)} $type])} { 1801 set PRIV(namesp) :: 1802 } 1803 set PRIV(StatusAttach) "$PRIV(app) ($PRIV(apptype))" 1804 return 2165 if {![string match {} $ns] && $namespOK} { 2166 AttachNamespace $ns 2167 } 2168 return [AttachId] 2169 } 2170 2171 proc ::tkcon::AttachId {} { 2172 # return Attach info in a form that Attach accepts again 2173 variable PRIV 2174 2175 if {[string match {} $PRIV(appname)]} { 2176 variable OPT 2177 set appname [concat $PRIV(name) $OPT(exec)] 2178 } else { 2179 set appname $PRIV(appname) 2180 } 2181 set id [list $appname $PRIV(apptype)] 2182 # only display ns info if it isn't "::" as that is what is also 2183 # used to indicate no eval in namespace 2184 if {![string match :: $PRIV(namesp)]} { lappend id $PRIV(namesp) } 2185 if {[info exists PRIV(console)]} { 2186 variable ATTACH 2187 set ATTACH($PRIV(console)) $id 2188 } 2189 return $id 1805 2190 } 1806 2191 … … 1836 2221 } 1837 2222 set PRIV(namesp) $name 1838 set PRIV(StatusAttach) "$PRIV(app) $PRIV(namesp) ($PRIV(apptype))"2223 return [AttachId] 1839 2224 } 1840 2225 … … 1852 2237 wm title $t "tkcon Create Socket" 1853 2238 label $t.lhost -text "Host: " 1854 entry $t.host -width 202239 entry $t.host -width 16 -takefocus 1 1855 2240 label $t.lport -text "Port: " 1856 entry $t.port -width 4 1857 button $t.ok -text "OK" -command {set ::tkcon::PRIV(grab) 1} 2241 entry $t.port -width 4 -takefocus 1 2242 button $t.ok -text "OK" -command {set ::tkcon::PRIV(grab) 1} -width 4 \ 2243 -takefocus 1 1858 2244 bind $t.host <Return> [list focus $t.port] 1859 2245 bind $t.port <Return> [list focus $t.ok] 1860 2246 bind $t.ok <Return> [list $t.ok invoke] 1861 grid $t.lhost $t.host $t.lport $t.port -sticky ew1862 grid $t.ok - - - -sticky ew2247 grid $t.lhost $t.host $t.lport $t.port $t.ok -sticky ew 2248 grid configure $t.ok -padx 4 -pady 2 1863 2249 grid columnconfig $t 1 -weight 1 1864 2250 grid rowconfigure $t 1 -weight 1 1865 2251 wm transient $t $PRIV(root) 2252 wm group $t $PRIV(root) 1866 2253 wm geometry $t +[expr {([winfo screenwidth $t]-[winfo \ 1867 2254 reqwidth $t]) / 2}]+[expr {([winfo \ 1868 2255 screenheight $t]-[winfo reqheight $t]) / 2}] 2256 bind $t <Escape> [list destroy $t] 1869 2257 } 1870 2258 #$t.host delete 0 end … … 1964 2352 proc ::tkcon::MainInit {} { 1965 2353 variable PRIV 2354 variable OPT 1966 2355 1967 2356 if {![info exists PRIV(slaves)]} { … … 1992 2381 lappend PRIV(slaves) $tmp 1993 2382 load {} Tk $tmp 2383 # If we have tbcload, then that should be autoloaded into slaves. 2384 set idx [lsearch [info loaded] "* Tbcload"] 2385 if {$idx != -1} { catch {load {} Tbcload $tmp} } 1994 2386 lappend PRIV(interps) [$tmp eval [list tk appname \ 1995 2387 "[tk appname] $tmp"]] 1996 if {[info exist argv0]} {$tmp eval [list set argv0 $argv0]}1997 $tmp eval set argc $argc1998 $tmp eval [list set argv $argv]2388 if {[info exists argv0]} {$tmp eval [list set argv0 $argv0]} 2389 if {[info exists argc]} {$tmp eval [list set argc $argc]} 2390 if {[info exists argv]} {$tmp eval [list set argv $argv]} 1999 2391 $tmp eval [list namespace eval ::tkcon {}] 2000 2392 $tmp eval [list set ::tkcon::PRIV(name) $tmp] … … 2003 2395 $tmp alias ::tkcon::Destroy ::tkcon::Destroy $tmp 2004 2396 $tmp alias ::tkcon::New ::tkcon::New 2397 $tmp alias ::tkcon::GetSlaveNum ::tkcon::GetSlaveNum 2005 2398 $tmp alias ::tkcon::Main ::tkcon::InterpEval Main 2006 2399 $tmp alias ::tkcon::Slave ::tkcon::InterpEval … … 2027 2420 2028 2421 ## Slave interpreter exit request 2029 if {[string match exit $OPT(slaveexit)]} { 2030 ## Only exit if it specifically is stated to do so 2422 if {[string match exit $OPT(slaveexit)] 2423 || [llength $PRIV(interps)] == 1} { 2424 ## Only exit if it specifically is stated to do so, or this 2425 ## is the last interp 2031 2426 uplevel 1 exit $args 2032 } 2033 ## Otherwise we will delete the slave interp and associated data 2034 set name [InterpEval $slave] 2035 set PRIV(interps) [lremove $PRIV(interps) [list $name]] 2036 set PRIV(slaves) [lremove $PRIV(slaves) [list $slave]] 2037 interp delete $slave 2038 StateCleanup $slave 2039 return 2427 } else { 2428 ## Otherwise we will delete the slave interp and associated data 2429 Destroy $slave 2430 } 2040 2431 } 2041 2432 … … 2048 2439 variable PRIV 2049 2440 2050 if {[string match {} $slave]} { 2441 # Just close on the last one 2442 if {[llength $PRIV(interps)] == 1} { exit } 2443 if {"" == $slave} { 2051 2444 ## Main interpreter close request 2052 if {[tk_dialog $PRIV(base).destroyme {Quit tkcon?} \ 2053 {Closing the Main console will quit tkcon} \ 2054 warning 0 "Don't Quit" "Quit tkcon"]} exit 2445 if {[tk_messageBox -parent $PRIV(root) -title "Quit tkcon?" \ 2446 -message "Close all windows and exit tkcon?" \ 2447 -icon question -type yesno] == "yes"} { exit } 2448 return 2449 } elseif {$slave == $::tkcon::OPT(exec)} { 2450 set name [tk appname] 2451 set slave "Main" 2055 2452 } else { 2056 2453 ## Slave interpreter close request 2057 2454 set name [InterpEval $slave] 2058 set PRIV(interps) [lremove $PRIV(interps) [list $name]]2059 set PRIV(slaves) [lremove $PRIV(slaves) [list $slave]]2060 2455 interp delete $slave 2061 2456 } 2457 set PRIV(interps) [lremove $PRIV(interps) [list $name]] 2458 set PRIV(slaves) [lremove $PRIV(slaves) [list $slave]] 2062 2459 StateCleanup $slave 2063 return 2064 } 2065 2066 ## We want to do a couple things before exiting... 2067 if {[catch {rename ::exit ::tkcon::FinalExit} err]} { 2068 puts stderr "tkcon might panic:\n$err" 2069 } 2070 proc ::exit args { 2071 if {$::tkcon::OPT(usehistory)} { 2072 if {[catch {open $::tkcon::PRIV(histfile) w} fid]} { 2073 puts stderr "unable to save history file:\n$fid" 2074 # pause a moment, because we are about to die finally... 2075 after 1000 2076 } else { 2077 set max [::tkcon::EvalSlave history nextid] 2078 set id [expr {$max - $::tkcon::OPT(history)}] 2079 if {$id < 1} { set id 1 } 2080 ## FIX: This puts history in backwards!! 2081 while {($id < $max) && \ 2082 ![catch {::tkcon::EvalSlave history event $id} cmd]} { 2083 if {[string compare {} $cmd]} { 2084 puts $fid "::tkcon::EvalSlave history add [list $cmd]" 2460 } 2461 2462 if {$OPT(overrideexit)} { 2463 ## We want to do a couple things before exiting... 2464 if {[catch {rename ::exit ::tkcon::FinalExit} err]} { 2465 puts stderr "tkcon might panic:\n$err" 2466 } 2467 proc ::exit args { 2468 if {$::tkcon::OPT(usehistory)} { 2469 if {[catch {open $::tkcon::PRIV(histfile) w} fid]} { 2470 puts stderr "unable to save history file:\n$fid" 2471 # pause a moment, because we are about to die finally... 2472 after 1000 2473 } else { 2474 set max [::tkcon::EvalSlave history nextid] 2475 set id [expr {$max - $::tkcon::OPT(history)}] 2476 if {$id < 1} { set id 1 } 2477 ## FIX: This puts history in backwards!! 2478 while {($id < $max) && ![catch \ 2479 {::tkcon::EvalSlave history event $id} cmd]} { 2480 if {[string compare {} $cmd]} { 2481 puts $fid "::tkcon::EvalSlave\ 2482 history add [list $cmd]" 2483 } 2484 incr id 2085 2485 } 2086 incrid2486 close $fid 2087 2487 } 2088 close $fid 2089 } 2090 } 2091 uplevel 1 ::tkcon::FinalExit $args 2488 } 2489 uplevel 1 ::tkcon::FinalExit $args 2490 } 2092 2491 } 2093 2492 … … 2099 2498 variable PRIV 2100 2499 2101 if {[string match {} $slave]} { 2500 if {[llength [info level 0]] == 1} { 2501 # no args given 2102 2502 return $PRIV(slaves) 2103 2503 } elseif {[string match {[Mm]ain} $slave]} { … … 2107 2507 return [interp eval $slave uplevel \#0 $args] 2108 2508 } else { 2109 return [interp eval $slave tk appname] 2509 # beware safe interps with Tk 2510 if {[interp eval $slave {llength [info commands tk]}]} { 2511 if {[catch {interp eval $slave tk appname} name]} { 2512 return "safetk" 2513 } 2514 return $name 2515 } 2110 2516 } 2111 2517 } 2112 2518 2113 2519 proc ::tkcon::Interps {{ls {}} {interp {}}} { 2114 if {[string match {} $interp]} { lappend ls {} [tk appname] } 2520 if {[string match {} $interp]} { 2521 lappend ls {} [tk appname] 2522 } 2115 2523 foreach i [interp slaves $interp] { 2116 2524 if {[string compare {} $interp]} { set i "$interp $i" } 2117 2525 if {[string compare {} [interp eval $i package provide Tk]]} { 2118 lappend ls $i [interp eval $i tk appname] 2526 # beware safe interps with Tk 2527 if {[catch {interp eval $i tk appname} name]} { 2528 set name {} 2529 } 2530 lappend ls $i $name 2119 2531 } else { 2120 2532 lappend ls $i {} … … 2178 2590 error "No other Tk interpreters on $disp" 2179 2591 } 2180 send -displayof $dt [lindex $interps 0] [list info tclversion]2592 ::send::send -displayof $dt [lindex $interps 0] [list info tclversion] 2181 2593 } err]} { 2182 2594 global env … … 2439 2851 } 2440 2852 2441 ## ::tkcon:: ErrorHighlight - magic errorhighlighting2853 ## ::tkcon::Highlight - magic highlighting 2442 2854 ## beware: voodoo included 2443 2855 # ARGS: 2444 2856 ## 2445 proc ::tkcon:: ErrorHighlight w{2857 proc ::tkcon::Highlight {w type} { 2446 2858 variable COLOR 2859 variable OPT 2860 2861 switch -exact $type { 2862 "error" { HighlightError $w } 2863 "tcl" - "test" { 2864 if {[winfo class $w] != "Ctext"} { return } 2865 2866 foreach {app type} [tkcon attach] {break} 2867 set cmds [::tkcon::EvalOther $app $type info commands] 2868 2869 set classes [list \ 2870 [list comment ClassForRegexp "^\\s*#\[^\n\]*" $COLOR(stderr)] \ 2871 [list var ClassWithOnlyCharStart "\$" $COLOR(stdout)] \ 2872 [list syntax ClassForSpecialChars "\[\]{}\"" $COLOR(prompt)] \ 2873 [list command Class $cmds $COLOR(proc)] \ 2874 ] 2875 2876 # Remove all highlight classes from a widget 2877 ctext::clearHighlightClasses $w 2878 foreach class $classes { 2879 foreach {cname ctype cptn ccol} $class break 2880 ctext::addHighlight$ctype $w $cname $ccol $cptn 2881 } 2882 $w highlight 1.0 end 2883 } 2884 } 2885 } 2886 2887 ## ::tkcon::HighlightError - magic error highlighting 2888 ## beware: voodoo included 2889 # ARGS: 2890 ## 2891 proc ::tkcon::HighlightError w { 2892 variable COLOR 2893 variable OPT 2447 2894 2448 2895 ## do voodoo here … … 2476 2923 $w tag bind $tag <Leave> [list $w tag configure $tag -under 0] 2477 2924 $w tag bind $tag <ButtonRelease-1> "if {!\$tkPriv(mouseMoved)} \ 2478 {[list edit-attach $app -type proc -find $what -- $cmd]}"2925 {[list $OPT(edit) -attach $app -type proc -find $what -- $cmd]}" 2479 2926 } 2480 2927 set info [string range $info $c1 end] … … 2505 2952 $w tag bind $tag <Leave> [list $w tag configure $tag -under 0] 2506 2953 $w tag bind $tag <ButtonRelease-1> "if {!\$tkPriv(mouseMoved)} \ 2507 {[list edit -attach $app -type proc -- $cmd]}" 2508 } 2954 {[list $OPT(edit) -attach $app -type proc -- $cmd]}" 2955 } 2956 } 2957 } 2958 2959 proc ::tkcon::ExpectInit {{termcap 1} {terminfo 1}} { 2960 global env 2961 2962 if {$termcap} { 2963 set env(TERM) "tt" 2964 set env(TERMCAP) {tt: 2965 :ks=\E[KS: 2966 :ke=\E[KE: 2967 :cm=\E[%d;%dH: 2968 :up=\E[A: 2969 :nd=\E[C: 2970 :cl=\E[H\E[J: 2971 :do=^J: 2972 :so=\E[7m: 2973 :se=\E[m: 2974 :k1=\EOP: 2975 :k2=\EOQ: 2976 :k3=\EOR: 2977 :k4=\EOS: 2978 :k5=\EOT: 2979 :k6=\EOU: 2980 :k7=\EOV: 2981 :k8=\EOW: 2982 :k9=\EOX: 2983 } 2984 } 2985 2986 if {$terminfo} { 2987 set env(TERM) "tkterm" 2988 if {![info exists env(TEMP)]} { set env(TEMP) /tmp } 2989 set env(TERMINFO) $env(TEMP) 2990 2991 set ttsrc [file join $env(TEMP) tt.src] 2992 set file [open $ttsrc w] 2993 puts $file {tkterm|Don Libes' tk text widget terminal emulator, 2994 smkx=\E[KS, 2995 rmkx=\E[KE, 2996 cup=\E[%p1%d;%p2%dH, 2997 cuu1=\E[A, 2998 cuf1=\E[C, 2999 clear=\E[H\E[J, 3000 ind=\n, 3001 cr=\r, 3002 smso=\E[7m, 3003 rmso=\E[m, 3004 kf1=\EOP, 3005 kf2=\EOQ, 3006 kf3=\EOR, 3007 kf4=\EOS, 3008 kf5=\EOT, 3009 kf6=\EOU, 3010 kf7=\EOV, 3011 kf8=\EOW, 3012 kf9=\EOX, 3013 } 3014 close $file 3015 3016 if {[catch {exec tic $ttsrc} msg]} { 3017 return -code error \ 3018 "tic failed, you may not have terminfo support:\n$msg" 3019 } 3020 3021 file delete $ttsrc 3022 } 3023 } 3024 3025 # term_exit is called if the spawned process exits 3026 proc ::tkcon::term_exit {w} { 3027 variable EXP 3028 catch {exp_close -i $EXP(spawn_id)} 3029 set EXP(forever) 1 3030 unset EXP 3031 } 3032 3033 # term_chars_changed is called after every change to the displayed chars 3034 # You can use if you want matches to occur in the background (a la bind) 3035 # If you want to test synchronously, then just do so - you don't need to 3036 # redefine this procedure. 3037 proc ::tkcon::term_chars_changed {w args} { 3038 } 3039 3040 # term_cursor_changed is called after the cursor is moved 3041 proc ::tkcon::term_cursor_changed {w args} { 3042 } 3043 3044 proc ::tkcon::term_update_cursor {w args} { 3045 variable OPT 3046 variable EXP 3047 3048 $w mark set insert $EXP(row).$EXP(col) 3049 $w see insert 3050 term_cursor_changed $w 3051 } 3052 3053 proc ::tkcon::term_clear {w args} { 3054 $w delete 1.0 end 3055 term_init $w 3056 } 3057 3058 proc ::tkcon::term_init {w args} { 3059 variable OPT 3060 variable EXP 3061 3062 # initialize it with blanks to make insertions later more easily 3063 set blankline [string repeat " " $OPT(cols)]\n 3064 for {set i 1} {$i <= $OPT(rows)} {incr i} { 3065 $w insert $i.0 $blankline 3066 } 3067 3068 set EXP(row) 1 3069 set EXP(col) 0 3070 3071 $w mark set insert $EXP(row).$EXP(col) 3072 } 3073 3074 proc ::tkcon::term_down {w args} { 3075 variable OPT 3076 variable EXP 3077 3078 if {$EXP(row) < $OPT(rows)} { 3079 incr EXP(row) 3080 } else { 3081 # already at last line of term, so scroll screen up 3082 $w delete 1.0 2.0 3083 3084 # recreate line at end 3085 $w insert end [string repeat " " $OPT(cols)]\n 3086 } 3087 } 3088 3089 proc ::tkcon::term_insert {w s} { 3090 variable OPT 3091 variable EXP 3092 3093 set chars_rem_to_write [string length $s] 3094 set space_rem_on_line [expr {$OPT(cols) - $EXP(col)}] 3095 3096 set tag_action [expr {$EXP(standout) ? "add" : "remove"}] 3097 3098 ################## 3099 # write first line 3100 ################## 3101 3102 if {$chars_rem_to_write > $space_rem_on_line} { 3103 set chars_to_write $space_rem_on_line 3104 set newline 1 3105 } else { 3106 set chars_to_write $chars_rem_to_write 3107 set newline 0 3108 } 3109 3110 $w delete $EXP(row).$EXP(col) \ 3111 $EXP(row).[expr {$EXP(col) + $chars_to_write}] 3112 $w insert $EXP(row).$EXP(col) \ 3113 [string range $s 0 [expr {$space_rem_on_line-1}]] 3114 3115 $w tag $tag_action standout $EXP(row).$EXP(col) \ 3116 $EXP(row).[expr {$EXP(col) + $chars_to_write}] 3117 3118 # discard first line already written 3119 incr chars_rem_to_write -$chars_to_write 3120 set s [string range $s $chars_to_write end] 3121 3122 # update EXP(col) 3123 incr EXP(col) $chars_to_write 3124 # update EXP(row) 3125 if {$newline} { term_down $w } 3126 3127 ################## 3128 # write full lines 3129 ################## 3130 while {$chars_rem_to_write >= $OPT(cols)} { 3131 $w delete $EXP(row).0 $EXP(row).end 3132 $w insert $EXP(row).0 [string range $s 0 [expr {$OPT(cols)-1}]] 3133 $w tag $tag_action standout $EXP(row).0 $EXP(row).end 3134 3135 # discard line from buffer 3136 set s [string range $s $OPT(cols) end] 3137 incr chars_rem_to_write -$OPT(cols) 3138 3139 set EXP(col) 0 3140 term_down $w 3141 } 3142 3143 ################# 3144 # write last line 3145 ################# 3146 3147 if {$chars_rem_to_write} { 3148 $w delete $EXP(row).0 $EXP(row).$chars_rem_to_write 3149 $w insert $EXP(row).0 $s 3150 $w tag $tag_action standout $EXP(row).0 $EXP(row).$chars_rem_to_write 3151 set EXP(col) $chars_rem_to_write 3152 } 3153 3154 term_chars_changed $w 3155 } 3156 3157 proc ::tkcon::Expect {cmd} { 3158 variable OPT 3159 variable PRIV 3160 variable EXP 3161 3162 set EXP(standout) 0 3163 set EXP(row) 0 3164 set EXP(col) 0 3165 3166 set env(LINES) $OPT(rows) 3167 set env(COLUMNS) $OPT(cols) 3168 3169 ExpectInit 3170 log_user 0 3171 set ::stty_init "-tabs" 3172 uplevel \#0 [linsert $cmd 0 spawn] 3173 set EXP(spawn_id) $::spawn_id 3174 if {[info exists ::spawn_out(slave,name)]} { 3175 set EXP(slave,name) $::spawn_out(slave,name) 3176 catch {stty rows $OPT(rows) columns $OPT(cols) < $::spawn_out(slave,name)} 3177 } 3178 if {[string index $cmd end] == "&"} { 3179 set cmd expect_background 3180 } else { 3181 set cmd expect 3182 } 3183 bind $PRIV(console) <Meta-KeyPress> { 3184 if {"%A" != ""} { 3185 exp_send -i $::tkcon::EXP(spawn_id) "\033%A" 3186 break 3187 } 3188 } 3189 bind $PRIV(console) <KeyPress> { 3190 exp_send -i $::tkcon::EXP(spawn_id) -- %A 3191 break 3192 } 3193 bind $PRIV(console) <Control-space> {exp_send -null} 3194 set code [catch { 3195 term_init $PRIV(console) 3196 while {[info exists EXP(spawn_id)]} { 3197 $cmd { 3198 -i $::tkcon::EXP(spawn_id) 3199 -re "^\[^\x01-\x1f\]+" { 3200 # Text 3201 ::tkcon::term_insert $::tkcon::PRIV(console) \ 3202 $expect_out(0,string) 3203 ::tkcon::term_update_cursor $::tkcon::PRIV(console) 3204 } "^\r" { 3205 # (cr,) Go to beginning of line 3206 update idle 3207 set ::tkcon::EXP(col) 0 3208 ::tkcon::term_update_cursor $::tkcon::PRIV(console) 3209 } "^\n" { 3210 # (ind,do) Move cursor down one line 3211 if {$::tcl_platform(platform) eq "windows"} { 3212 # Windows seems to get the LF without the CR 3213 update idle 3214 set ::tkcon::EXP(col) 0 3215 } 3216 ::tkcon::term_down $::tkcon::PRIV(console) 3217 ::tkcon::term_update_cursor $::tkcon::PRIV(console) 3218 } "^\b" { 3219 # Backspace nondestructively 3220 incr ::tkcon::EXP(col) -1 3221 ::tkcon::term_update_cursor $::tkcon::PRIV(console) 3222 } "^\a" { 3223 bell 3224 } "^\t" { 3225 # Tab, shouldn't happen 3226 send_error "got a tab!?" 3227 } eof { 3228 ::tkcon::term_exit $::tkcon::PRIV(console) 3229 } "^\x1b\\\[A" { 3230 # Cursor Up (cuu1,up) 3231 incr ::tkcon::EXP(row) -1 3232 ::tkcon::term_update_cursor $::tkcon::PRIV(console) 3233 } "^\x1b\\\[B" { 3234 # Cursor Down 3235 incr ::tkcon::EXP(row) 3236 ::tkcon::term_update_cursor $::tkcon::PRIV(console) 3237 } "^\x1b\\\[C" { 3238 # Cursor Right (cuf1,nd) 3239 incr ::tkcon::EXP(col) 3240 ::tkcon::term_update_cursor $::tkcon::PRIV(console) 3241 } "^\x1b\\\[D" { 3242 # Cursor Left 3243 incr ::tkcon::EXP(col) 3244 ::tkcon::term_update_cursor $::tkcon::PRIV(console) 3245 } "^\x1b\\\[H" { 3246 # Cursor Home 3247 } -re "^\x1b\\\[(\[0-9\]*);(\[0-9\]*)H" { 3248 # (cup,cm) Move to row y col x 3249 set ::tkcon::EXP(row) [expr {$expect_out(1,string)+1}] 3250 set ::tkcon::EXP(col) $expect_out(2,string) 3251 ::tkcon::term_update_cursor $::tkcon::PRIV(console) 3252 } "^\x1b\\\[H\x1b\\\[J" { 3253 # (clear,cl) Clear screen 3254 ::tkcon::term_clear $::tkcon::PRIV(console) 3255 ::tkcon::term_update_cursor $::tkcon::PRIV(console) 3256 } "^\x1b\\\[7m" { 3257 # (smso,so) Begin standout mode 3258 set ::tkcon::EXP(standout) 1 3259 } "^\x1b\\\[m" { 3260 # (rmso,se) End standout mode 3261 set ::tkcon::EXP(standout) 0 3262 } "^\x1b\\\[KS" { 3263 # (smkx,ks) start keyboard-transmit mode 3264 # terminfo invokes these when going in/out of graphics mode 3265 # In graphics mode, we should have no scrollbars 3266 #graphicsSet 1 3267 } "^\x1b\\\[KE" { 3268 # (rmkx,ke) end keyboard-transmit mode 3269 # Out of graphics mode, we should have scrollbars 3270 #graphicsSet 0 3271 } 3272 } 3273 } 3274 #vwait ::tkcon::EXP(forever) 3275 } err] 3276 bind $PRIV(console) <Meta-KeyPress> {} 3277 bind $PRIV(console) <KeyPress> {} 3278 bind $PRIV(console) <Control-space> {} 3279 catch {unset EXP} 3280 if {$code} { 3281 return -code $code -errorinfo $::errorInfo $err 2509 3282 } 2510 3283 } … … 2516 3289 ## 2517 3290 proc tkcon {cmd args} { 3291 variable ::tkcon::PRIV 3292 variable ::tkcon::OPT 2518 3293 global errorInfo 2519 3294 … … 2523 3298 if {[llength $args]} { 2524 3299 if {[regexp {^[1-9][0-9]*$} $args]} { 2525 set ::tkcon::OPT(buffer) $args3300 set OPT(buffer) $args 2526 3301 # catch in case the console doesn't exist yet 2527 catch {::tkcon::ConstrainBuffer $ ::tkcon::PRIV(console) \2528 $ ::tkcon::OPT(buffer)}3302 catch {::tkcon::ConstrainBuffer $PRIV(console) \ 3303 $OPT(buffer)} 2529 3304 } else { 2530 3305 return -code error "buffer must be a valid integer" 2531 3306 } 2532 3307 } 2533 return $::tkcon::OPT(buffer) 3308 return $OPT(buffer) 3309 } 3310 linelen* { 3311 ## 'linelength' Sets/Query the maximum line length 3312 if {[llength $args]} { 3313 if {[regexp {^-?[0-9]+$} $args]} { 3314 set OPT(maxlinelen) $args 3315 } else { 3316 return -code error "buffer must be a valid integer" 3317 } 3318 } 3319 return $OPT(maxlinelen) 2534 3320 } 2535 3321 bg* { … … 2544 3330 cons* { 2545 3331 ## 'console' - passes the args to the text widget of the console. 2546 set result [uplevel 1 $ ::tkcon::PRIV(console) $args]2547 ::tkcon::ConstrainBuffer $ ::tkcon::PRIV(console) \2548 $ ::tkcon::OPT(buffer)3332 set result [uplevel 1 $PRIV(console) $args] 3333 ::tkcon::ConstrainBuffer $PRIV(console) \ 3334 $OPT(buffer) 2549 3335 return $result 2550 3336 } … … 2559 3345 set old [bind TkConsole <<TkCon_Eval>>] 2560 3346 bind TkConsole <<TkCon_Eval>> { set ::tkcon::PRIV(wait) 0 } 2561 set w $ ::tkcon::PRIV(console)3347 set w $PRIV(console) 2562 3348 # Make sure to move the limit to get the right data 2563 3349 $w mark set insert end … … 2570 3356 return $line 2571 3357 } 3358 exp* { 3359 ::tkcon::Expect [lindex $args 0] 3360 } 2572 3361 getc* { 2573 3362 ## 'getcommand' a replacement for [gets stdin] … … 2579 3368 set old [bind TkConsole <<TkCon_Eval>>] 2580 3369 bind TkConsole <<TkCon_Eval>> { set ::tkcon::PRIV(wait) 0 } 2581 set w $ ::tkcon::PRIV(console)3370 set w $PRIV(console) 2582 3371 # Make sure to move the limit to get the right data 2583 3372 $w mark set insert end … … 2602 3391 return -code error "wrong # args: should be \"tkcon gets\"" 2603 3392 } 2604 set t $ ::tkcon::PRIV(base).gets3393 set t $PRIV(base).gets 2605 3394 if {![winfo exists $t]} { 2606 3395 toplevel $t … … 2623 3412 grid columnconfig $t 0 -weight 1 2624 3413 grid rowconfig $t 1 -weight 1 2625 wm transient $t $ ::tkcon::PRIV(root)3414 wm transient $t $PRIV(root) 2626 3415 wm geometry $t +[expr {([winfo screenwidth $t]-[winfo \ 2627 3416 reqwidth $t]) / 2}]+[expr {([winfo \ … … 2648 3437 } 2649 3438 } else { 2650 set info $ ::tkcon::PRIV(errorInfo)3439 set info $PRIV(errorInfo) 2651 3440 } 2652 3441 if {[string match {} $info]} { set info "errorInfo empty" } 2653 3442 ## If args is empty, the -attach switch just ignores it 2654 edit-attach $args -type error -- $info3443 $OPT(edit) -attach $args -type error -- $info 2655 3444 } 2656 3445 fi* { 2657 3446 ## 'find' string 2658 ::tkcon::Find $ ::tkcon::PRIV(console) $args3447 ::tkcon::Find $PRIV(console) $args 2659 3448 } 2660 3449 fo* { 2661 3450 ## 'font' ?fontname? - gets/sets the font of the console 2662 3451 if {[llength $args]} { 2663 if {[info exists ::tkcon::PRIV(console)] && \2664 [winfo exists $ ::tkcon::PRIV(console)]} {2665 $ ::tkcon::PRIV(console) config -font $args2666 set ::tkcon::OPT(font) [$::tkcon::PRIV(console) cget -font]3452 if {[info exists PRIV(console)] && \ 3453 [winfo exists $PRIV(console)]} { 3454 $PRIV(console) config -font $args 3455 set OPT(font) [$PRIV(console) cget -font] 2667 3456 } else { 2668 set ::tkcon::OPT(font) $args3457 set OPT(font) $args 2669 3458 } 2670 3459 } 2671 return $ ::tkcon::OPT(font)3460 return $OPT(font) 2672 3461 } 2673 3462 hid* - with* { 2674 3463 ## 'hide' 'withdraw' - hides the console. 2675 wm withdraw $::tkcon::PRIV(root) 3464 if {[info exists PRIV(root)] && [winfo exists $PRIV(root)]} { 3465 wm withdraw $PRIV(root) 3466 } 2676 3467 } 2677 3468 his* { … … 2685 3476 ico* { 2686 3477 ## 'iconify' - iconifies the console with 'iconify'. 2687 wm iconify $::tkcon::PRIV(root) 3478 if {[info exists PRIV(root)] && [winfo exists $PRIV(root)]} { 3479 wm iconify $PRIV(root) 3480 } 2688 3481 } 2689 3482 mas* - eval { … … 2735 3528 sh* - dei* { 2736 3529 ## 'show|deiconify' - deiconifies the console. 2737 wm deiconify $::tkcon::PRIV(root) 2738 raise $::tkcon::PRIV(root) 2739 focus -force $::tkcon::PRIV(console) 3530 if {![info exists PRIV(root)]} { 3531 set PRIV(showOnStartup) 0 3532 set PRIV(root) .tkcon 3533 set OPT(exec) "" 3534 } 3535 if {![winfo exists $PRIV(root)]} { 3536 ::tkcon::Init 3537 } 3538 wm deiconify $PRIV(root) 3539 raise $PRIV(root) 3540 focus -force $PRIV(console) 2740 3541 } 2741 3542 ti* { 2742 3543 ## 'title' ?title? - gets/sets the console's title 2743 3544 if {[llength $args]} { 2744 return [wm title $ ::tkcon::PRIV(root) [join $args]]3545 return [wm title $PRIV(root) [join $args]] 2745 3546 } else { 2746 return [wm title $ ::tkcon::PRIV(root)]3547 return [wm title $PRIV(root)] 2747 3548 } 2748 3549 } … … 2754 3555 set slaveVar [lindex $args 1] 2755 3556 if {[info exists $masterVar]} { 2756 interp eval $ ::tkcon::OPT(exec) \3557 interp eval $OPT(exec) \ 2757 3558 [list set $slaveVar [set $masterVar]] 2758 3559 } else { 2759 catch {interp eval $ ::tkcon::OPT(exec) [list unset $slaveVar]}2760 } 2761 interp eval $ ::tkcon::OPT(exec) \3560 catch {interp eval $OPT(exec) [list unset $slaveVar]} 3561 } 3562 interp eval $OPT(exec) \ 2762 3563 [list trace variable $slaveVar rwu \ 2763 [list tkcon set $masterVar $ ::tkcon::OPT(exec)]]3564 [list tkcon set $masterVar $OPT(exec)]] 2764 3565 return 2765 3566 } 2766 3567 v* { 2767 return $ ::tkcon::PRIV(version)3568 return $PRIV(version) 2768 3569 } 2769 3570 default { … … 2917 3718 toplevel $w 2918 3719 wm withdraw $w 2919 if {[string length $word] > 12} {2920 wm title $w " tkcon Edit: [string range $word 0 9]..."3720 if {[string length $word] > 20} { 3721 wm title $w "[string range $word 0 16]... - tkcon Edit" 2921 3722 } else { 2922 wm title $w "tkcon Edit: $word" 2923 } 2924 2925 text $w.text -wrap none \ 3723 wm title $w "$word - tkcon Edit" 3724 } 3725 3726 if {[package provide ctext] != ""} { 3727 set txt [ctext $w.text] 3728 } else { 3729 set txt [text $w.text] 3730 } 3731 $w.text configure -wrap none \ 2926 3732 -xscrollcommand [list $w.sx set] \ 2927 3733 -yscrollcommand [list $w.sy set] \ … … 2930 3736 -insertbackground $::tkcon::COLOR(cursor) \ 2931 3737 -font $::tkcon::OPT(font) 3738 catch {$w.text configure -undo 1} 2932 3739 scrollbar $w.sx -orient h -takefocus 0 -bd 1 \ 2933 3740 -command [list $w.text xview] … … 2990 3797 $w.text insert 1.0 \ 2991 3798 [::tkcon::EvalOther $app $type dump proc [list $word]] 3799 after idle [::tkcon::Highlight $w.text tcl] 2992 3800 } 2993 3801 var* { 2994 3802 $w.text insert 1.0 \ 2995 3803 [::tkcon::EvalOther $app $type dump var [list $word]] 3804 after idle [::tkcon::Highlight $w.text tcl] 2996 3805 } 2997 3806 file { … … 3005 3814 } 3006 3815 ]] 3816 after idle [::tkcon::Highlight $w.text \ 3817 [string trimleft [file extension $word] .]] 3007 3818 } 3008 3819 error* { 3009 3820 $w.text insert 1.0 [join $args \n] 3010 ::tkcon::ErrorHighlight $w.text3821 after idle [::tkcon::Highlight $w.text error] 3011 3822 } 3012 3823 default { … … 3027 3838 # ARGS: any number of strings to output to stdout 3028 3839 ## 3029 proc echo args { puts [concat $args] }3840 proc echo args { puts stdout [concat $args] } 3030 3841 3031 3842 ## clear - clears the buffer of the console (not the history though) … … 3156 3967 foreach var [lsort $vars] { 3157 3968 if {[uplevel 1 [list info locals $var]] == ""} { 3158 # use the proper scope of the var, but 3159 # namespace which won't id locals correctly3160 set var[uplevel 1 \3969 # use the proper scope of the var, but namespace which 3970 # won't id locals or some upvar'ed vars correctly 3971 set new [uplevel 1 \ 3161 3972 [list namespace which -variable $var]] 3973 if {$new != ""} { 3974 set var $new 3975 } 3162 3976 } 3163 3977 upvar 1 $var v … … 3166 3980 append res "array set [list $var] \{\n" 3167 3981 if {[array size v]} { 3168 foreach i [lsort [array names v $fltr]] { 3982 foreach i \ 3983 [lsort -dictionary [array names v $fltr]] { 3169 3984 upvar 0 v\($i\) __a 3170 3985 if {[array exists __a]} { … … 3179 3994 ## empty array 3180 3995 append res " empty array\n" 3181 append nst "unset [list $var](empty)\n" 3996 if {$var == ""} { 3997 append nst "unset (empty)\n" 3998 } else { 3999 append nst "unset [list $var](empty)\n" 4000 } 3182 4001 } 3183 4002 append res "\}\n$nst" … … 3560 4379 set max 4 3561 4380 regexp {^[0-9]+} $args max 4381 # handle the observe'ing of 'proc' 4382 set proccmd "proc" 4383 if {[string match "proc" $name]} { set proccmd $old } 3562 4384 ## idebug trace could be used here 3563 proc$name args "4385 $proccmd $name args " 3564 4386 for {set i \[info level\]; set max \[expr \[info level\]-$max\]} { 3565 4387 \$i>=\$max && !\[catch {uplevel \#\$i info level 0} info\] … … 3599 4421 } 3600 4422 if {![llength $args]} { set args observe_var } 4423 foreach c [uplevel 1 [list trace vinfo $name]] { 4424 # don't double up on the traces 4425 if {[list $type $args] == $c} { return } 4426 } 3601 4427 uplevel 1 [list trace $opt $name $type $args] 3602 4428 } … … 3741 4567 } 3742 4568 set sep [string trim [file join . .] .] 3743 if {![llength $args]} { set args .}4569 if {![llength $args]} { set args [list [pwd]] } 3744 4570 if {$::tcl_version >= 8.3} { 3745 4571 # Newer glob args allow safer dir processing. The user may still … … 3777 4603 if {$s(long)} { 3778 4604 set old [clock scan {1 year ago}] 3779 set fmt "%s%9 d %s %s\n"4605 set fmt "%s%9ld %s %s\n" 3780 4606 foreach o $out { 3781 4607 set d [lindex $o 0] … … 3967 4793 3968 4794 set cmd [lindex $args 0] 3969 if {[regexp "^namespace\[ \t\n\]+inscope" $cmd] && [llength $cmd] == 4} { 4795 if {[regexp "^:*namespace\[ \t\n\]+inscope" $cmd] \ 4796 && [llength $cmd] == 4} { 3970 4797 set arglist [lrange $args 1 end] 3971 4798 set ret [catch {uplevel 1 $cmd $arglist} result] … … 4029 4856 set errorCode $savedErrorCode 4030 4857 set errorInfo $savedErrorInfo 4031 return [uplevel 1 exec $new [lrange $args 1 end]] 4858 if {[info exists ::tkcon::EXPECT] && $::tkcon::EXPECT && [package provide Expect] != ""} { 4859 return [tkcon expect [concat $new [lrange $args 1 end]]] 4860 } else { 4861 return [uplevel 1 exec $new [lrange $args 1 end]] 4862 } 4032 4863 #return [uplevel exec >&@stdout <@stdin $new [lrange $args 1 end]] 4033 4864 } … … 4063 4894 canvas checkbutton clipboard destroy \ 4064 4895 entry event focus font frame grab grid image \ 4065 label l istbox lower menu menubutton message \4066 option pack p lace radiobutton raise \4896 label labelframe listbox lower menu menubutton message \ 4897 option pack panedwindow place radiobutton raise \ 4067 4898 scale scrollbar selection send spinbox \ 4068 4899 text tk tkwait toplevel winfo wm … … 4112 4943 4113 4944 ## Get all Text bindings into TkConsole 4114 foreach ev [bind Text] { bind TkConsole $ev [bind Text $ev] } 4945 foreach ev [bind Text] { bind TkConsole $ev [bind Text $ev] } 4115 4946 ## We really didn't want the newline insertion 4116 4947 bind TkConsole <Control-Key-o> {} … … 4120 4951 <<TkCon_Exit>> <Control-q> 4121 4952 <<TkCon_New>> <Control-N> 4953 <<TkCon_NewTab>> <Control-T> 4954 <<TkCon_NextTab>> <Control-Key-Tab> 4955 <<TkCon_PrevTab>> <Control-Shift-Key-Tab> 4122 4956 <<TkCon_Close>> <Control-w> 4123 4957 <<TkCon_About>> <Control-A> … … 4159 4993 bind $PRIV(root) <<TkCon_Exit>> exit 4160 4994 bind $PRIV(root) <<TkCon_New>> { ::tkcon::New } 4995 bind $PRIV(root) <<TkCon_NewTab>> { ::tkcon::NewTab } 4996 bind $PRIV(root) <<TkCon_NextTab>> { ::tkcon::GotoTab 1 ; break } 4997 bind $PRIV(root) <<TkCon_PrevTab>> { ::tkcon::GotoTab -1 ; break } 4161 4998 bind $PRIV(root) <<TkCon_Close>> { ::tkcon::Destroy } 4162 4999 bind $PRIV(root) <<TkCon_About>> { ::tkcon::About } … … 4165 5002 bind $PRIV(root) <<TkCon_Slave>> { 4166 5003 ::tkcon::Attach {} 4167 ::tkcon:: Prompt "\n" [::tkcon::CmdGet $::tkcon::PRIV(console)]5004 ::tkcon::RePrompt "\n" [::tkcon::CmdGet $::tkcon::PRIV(console)] 4168 5005 } 4169 5006 bind $PRIV(root) <<TkCon_Master>> { … … 4173 5010 ::tkcon::Attach Main 4174 5011 } 4175 ::tkcon:: Prompt "\n" [::tkcon::CmdGet $::tkcon::PRIV(console)]5012 ::tkcon::RePrompt "\n" [::tkcon::CmdGet $::tkcon::PRIV(console)] 4176 5013 } 4177 5014 bind $PRIV(root) <<TkCon_Main>> { 4178 5015 ::tkcon::Attach Main 4179 ::tkcon:: Prompt "\n" [::tkcon::CmdGet $::tkcon::PRIV(console)]5016 ::tkcon::RePrompt "\n" [::tkcon::CmdGet $::tkcon::PRIV(console)] 4180 5017 } 4181 5018 bind $PRIV(root) <<TkCon_Popup>> { … … 4457 5294 4458 5295 bind TkConsolePost <KeyPress> { 4459 if {$::tkcon::OPT(lightcmd) && [string compare {} %A]} { 4460 ::tkcon::TagProc %W 4461 } 4462 set ::tkcon::PRIV(StatusCursor) [%W index insert] 5296 if {[winfo exists "%W"]} { 5297 if {$::tkcon::OPT(lightcmd) && [string compare {} %A]} { 5298 ::tkcon::TagProc %W 5299 } 5300 set ::tkcon::PRIV(StatusCursor) [%W index insert] 5301 } 4463 5302 } 4464 5303 … … 4477 5316 proc ::tkcon::PopupMenu {X Y} { 4478 5317 variable PRIV 5318 variable OPT 4479 5319 4480 5320 set w $PRIV(console) … … 4534 5374 if {[lsearch $type proc] != -1} { 4535 5375 $PRIV(context) add command -label "View Procedure" \ 4536 -command [list edit-attach $app -type proc -- $word]5376 -command [list $OPT(edit) -attach $app -type proc -- $word] 4537 5377 } 4538 5378 if {[lsearch $type var] != -1} { 4539 5379 $PRIV(context) add command -label "View Variable" \ 4540 -command [list edit-attach $app -type var -- $word]5380 -command [list $OPT(edit) -attach $app -type var -- $word] 4541 5381 } 4542 5382 if {[lsearch $type file] != -1} { 4543 5383 $PRIV(context) add command -label "View File" \ 4544 -command [list edit-attach $app -type file -- $word]5384 -command [list $OPT(edit) -attach $app -type file -- $word] 4545 5385 } 4546 5386 tk_popup $PRIV(context) $X $Y … … 4663 5503 return 4664 5504 } 5505 variable EXP 5506 if {[info exists EXP(spawn_id)]} { 5507 exp_send -i $EXP(spawn_id) -- $s 5508 return 5509 } 4665 5510 if {[$w comp insert < limit]} { 4666 5511 $w mark set insert end … … 4799 5644 } 4800 5645 5646 ## ::tkcon::ExpandXotcl - expand an xotcl method name based on $str 5647 # ARGS: str - partial proc name to expand 5648 # Calls: ::tkcon::ExpandBestMatch 5649 # Returns: list containing longest unique match followed by all the 5650 # possible further matches 5651 ## 5652 proc ::tkcon::ExpandXotcl str { 5653 # in a first step, get the cmd to check, if we should handle subcommands 5654 set cmd [::tkcon::CmdGet $::tkcon::PRIV(console)] 5655 # Only do the xotcl magic if there are two cmds and xotcl is loaded 5656 if {[llength $cmd] != 2 5657 || ![EvalAttached [list info exists ::xotcl::version]]} { 5658 return 5659 } 5660 set obj [lindex $cmd 0] 5661 set sub [lindex $cmd 1] 5662 set match [EvalAttached [list $obj info methods $sub*]] 5663 if {[llength $match] > 1} { 5664 regsub -all {([^\\]) } [ExpandBestMatch $match $str] {\1\\ } str 5665 set match [linsert $match 0 $str] 5666 } else { 5667 regsub -all {([^\\]) } $match {\1\\ } match 5668 } 5669 return $match 5670 } 5671 4801 5672 ## ::tkcon::ExpandVariable - expand a tcl variable name based on $str 4802 5673 # ARGS: str - partial tcl var name to expand … … 4813 5684 foreach var $match {lappend vars $ary\($var\)} 4814 5685 return $vars 4815 } else {set match $ary\($match\)} 5686 } elseif {[llength $match] == 1} { 5687 set match $ary\($match\) 5688 } 4816 5689 ## Space transformation avoided for array names. 4817 5690 } else { … … 4890 5763 # - Other (e.g. bind, bindtag, image), which need their own function. 4891 5764 # 4892 ## These functions courtesy Jan Nijtmans (nijtmans@nici.kun.nl)5765 ## These functions courtesy Jan Nijtmans 4893 5766 ## 4894 if { [string compare [info command tk] tk]} {5767 if {![llength [info commands tk]]} { 4895 5768 proc tk {option args} { 4896 5769 if {![string match app* $option]} { … … 4901 5774 } 4902 5775 4903 if { [string compare [info command toplevel] toplevel]} {5776 if {![llength [info command toplevel]]} { 4904 5777 proc toplevel {name args} { 4905 eval frame $name $args4906 pack $name5778 eval [linsert $args 0 frame $name] 5779 grid $name -sticky news 4907 5780 } 4908 5781 } … … 4946 5819 $i alias . ::tkcon::SafeWindow $i {} 4947 5820 foreach var {tk_version tk_patchLevel tk_library auto_path} { 4948 $i eval set $var [list[set $var]]5821 $i eval [list set $var [set $var]] 4949 5822 } 4950 5823 $i eval { … … 5184 6057 if {[string compare $file ""]} { 5185 6058 package require http 2 6059 set headers {} 6060 if {[info exists PRIV(proxy)]} { 6061 ::http::config -proxyfilter [namespace origin RetrieveFilter] 6062 if {[lindex $PRIV(proxy) 1] != {}} { 6063 set headers [RetrieveAuthentication] 6064 } 6065 } 6066 set token [::http::geturl $PRIV(HEADURL) \ 6067 -headers $headers -timeout 30000] 5186 6068 set token [::http::geturl $PRIV(HEADURL) -timeout 30000] 5187 6069 ::http::wait $token 5188 6070 set code [catch { 5189 if {[::http::status $token] == "ok"} { 6071 set ncode [::http::ncode $token] 6072 if {$ncode != 200} { 6073 return "expected http return code 200, received $ncode" 6074 } 6075 set status [::http::status $token] 6076 if {$status == "ok"} { 6077 set data [::http::data $token] 6078 regexp {Id: tkcon.tcl,v (\d+\.\d+)} $data -> rcsVersion 6079 regexp {VERSION\s+"(\d+\.\d+[^\"]*)"} $data -> tkconVersion 6080 if {(![info exists rcsVersion] || ![info exists tkconVersion]) 6081 && [tk_messageBox -type yesno -icon warning \ 6082 -parent $PRIV(root) \ 6083 -title "Invalid tkcon source code" \ 6084 -message "Source code retrieved does not appear\ 6085 to be correct.\nContinue with save to \"$file\"?"] \ 6086 == "no"} { 6087 return "invalid tkcon source code retrieved" 6088 } 5190 6089 set fid [open $file w] 5191 6090 # We don't want newline mode to change 5192 6091 fconfigure $fid -translation binary 5193 set data [::http::data $token]5194 6092 puts -nonewline $fid $data 5195 6093 close $fid 5196 regexp {Id: tkcon.tcl,v (\d+\.\d+)} $data -> rcsVersion5197 re gexp {version\s+(\d+\.\d[^\n]*)} $data -> tkconVersion6094 } else { 6095 return "expected http status ok, received $status" 5198 6096 } 5199 6097 } err] 5200 6098 ::http::cleanup $token 5201 if {$code} { 6099 if {$code == 2} { 6100 tk_messageBox -type ok -icon info -parent $PRIV(root) \ 6101 -title "Failed to retrieve source" \ 6102 -message "Failed to retrieve latest tkcon source:\n$err" 6103 } elseif {$code} { 5202 6104 return -code error $err 5203 } elseif {[tk_messageBox -type yesno -icon info -parent $PRIV(root) \ 5204 -title "Retrieved tkcon v$tkconVersion, RCS $rcsVersion" \ 5205 -message "Successfully retrieved tkcon v$tkconVersion,\ 5206 RCS $rcsVersion. Shall I resource (not restart) this\ 5207 version now?"] == "yes"} { 5208 set PRIV(SCRIPT) $file 5209 set PRIV(version) $tkconVersion.$rcsVersion 5210 ::tkcon::Resource 6105 } else { 6106 if {![info exists rcsVersion]} { set rcsVersion "UNKNOWN" } 6107 if {![info exists tkconVersion]} { set tkconVersion "UNKNOWN" } 6108 if {[tk_messageBox -type yesno -icon info -parent $PRIV(root) \ 6109 -title "Retrieved tkcon v$tkconVersion, RCS $rcsVersion" \ 6110 -message "Successfully retrieved tkcon v$tkconVersion,\ 6111 RCS $rcsVersion. Shall I resource (not restart) this\ 6112 version now?"] == "yes"} { 6113 set PRIV(SCRIPT) $file 6114 set PRIV(version) $tkconVersion.$rcsVersion 6115 ::tkcon::Resource 6116 } 6117 } 6118 } 6119 } 6120 6121 ## 'send' package that handles multiple communication variants 6122 ## 6123 # Try using Tk send first, then look for a winsend interp, 6124 # then try dde and finally have a go at comm 6125 namespace eval ::send {} 6126 proc ::send::send {args} { 6127 set winfoInterpCmd [list ::winfo interps] 6128 array set opts [list displayof {} async 0] 6129 while {[string match -* [lindex $args 0]]} { 6130 switch -exact -- [lindex $args 0] { 6131 -displayof { 6132 set opts(displayof) [Pop args 1] 6133 lappend winfoInterpCmd -displayof $opts(displayof) 6134 } 6135 -async { set opts(async) 1 } 6136 -- { Pop args ; break } 6137 default { 6138 return -code error "bad option \"[lindex $args 0]\":\ 6139 should be -displayof, -async or --" 6140 } 6141 } 6142 Pop args 6143 } 6144 set app [Pop args] 6145 6146 if {[llength [info commands ::winfo]] 6147 && [lsearch -exact [eval $winfoInterpCmd] $app] > -1} { 6148 set cmd [list ::send] 6149 if {$opts(async) == 1} {lappend cmd -async} 6150 if {$opts(displayof) != {}} {lappend cmd -displayof $opts(displayof)} 6151 lappend cmd $app 6152 eval $cmd $args 6153 } elseif {[llength [info commands ::winsend]] 6154 && [lsearch -exact [::winsend interps] $app] > -1} { 6155 eval [list ::winsend send $app] $args 6156 } elseif {[llength [info commands ::dde]] 6157 && [lsearch -exact [dde services TclEval {}] \ 6158 [list TclEval $app]] > -1} { 6159 eval [list ::dde eval $app] $args 6160 } elseif {[package provide comm] != {} 6161 && [regexp {^[0-9]+$} [lindex $app 0]]} { 6162 #if {$opts(displayof) != {} && [llength $app] == 1} { 6163 # lappend app $opts(displayof) 6164 #} 6165 eval [list ::comm::comm send $app] $args 6166 } else { 6167 return -code error "bad interp: \"$app\" could not be found" 6168 } 6169 } 6170 6171 proc ::send::interps {args} { 6172 set winfoInterpCmd [list ::winfo interps] 6173 array set opts [list displayof {}] 6174 while {[string match -* [lindex $args 0]]} { 6175 switch -exact -- [lindex $args 0] { 6176 -displayof { 6177 set opts(displayof) [Pop args 1] 6178 lappend winfoInterpCmd -displayof $opts(displayof) 6179 } 6180 -- { Pop args ; break } 6181 default { 6182 return -code error "bad option \"[lindex $args 0]\":\ 6183 should be -displayof or --" 6184 } 6185 } 6186 Pop args 6187 } 6188 6189 set interps {} 6190 if {[llength [info commands ::winfo]]} { 6191 set interps [concat $interps [eval $winfoInterpCmd]] 6192 } 6193 if {[llength [info commands ::winsend]]} { 6194 set interps [concat $interps [::winsend interps]] 6195 } 6196 if {[llength [info commands ::dde]]} { 6197 set servers {} 6198 foreach server [::dde services TclEval {}] { 6199 lappend servers [lindex $server 1] 6200 } 6201 set interps [concat $interps $servers] 6202 } 6203 if {[package provide comm] != {}} { 6204 set interps [concat $interps [::comm::comm interps]] 6205 } 6206 return $interps 6207 } 6208 6209 proc ::send::appname {args} { 6210 set appname {} 6211 if {[llength [info commands ::tk]]} { 6212 set appname [eval ::tk appname $args] 6213 } 6214 if {[llength [info commands ::winsend]]} { 6215 set appname [concat $appname [eval ::winsend appname $args]] 6216 } 6217 if {[llength [info commands ::dde]]} { 6218 set appname [concat $appname [eval ::dde servername $args]] 6219 } 6220 # comm? can set port num and local/global interface. 6221 return [lsort -unique $appname] 6222 } 6223 6224 proc ::send::Pop {varname {nth 0}} { 6225 upvar $varname args 6226 set r [lindex $args $nth] 6227 set args [lreplace $args $nth $nth] 6228 return $r 6229 } 6230 ## 6231 ## end 'send' pacakge 6232 6233 ## special case 'tk appname' in Tcl plugin 6234 if {$::tkcon::PRIV(WWW)} { 6235 rename tk ::tkcon::_tk 6236 proc tk {cmd args} { 6237 if {$cmd == "appname"} { 6238 return "tkcon/WWW" 6239 } else { 6240 return [uplevel 1 ::tkcon::_tk [list $cmd] $args] 5211 6241 } 5212 6242 } … … 5216 6246 ## Meant primarily for my development of this program. It follows 5217 6247 ## links until the ultimate source is found. 5218 ## 5219 set ::tkcon::PRIV(SCRIPT) [info script] 5220 if {!$::tkcon::PRIV(WWW) && [string compare $::tkcon::PRIV(SCRIPT) {}]} { 5221 # we use a catch here because some wrap apps choke on 'file type' 5222 # because TclpLstat wasn't wrappable until 8.4. 5223 catch { 5224 while {[string match link [file type $::tkcon::PRIV(SCRIPT)]]} { 5225 set link [file readlink $::tkcon::PRIV(SCRIPT)] 5226 if {[string match relative [file pathtype $link]]} { 5227 set ::tkcon::PRIV(SCRIPT) \ 5228 [file join [file dirname $::tkcon::PRIV(SCRIPT)] $link] 5229 } else { 5230 set ::tkcon::PRIV(SCRIPT) $link 5231 } 5232 } 5233 catch {unset link} 5234 if {[string match relative [file pathtype $::tkcon::PRIV(SCRIPT)]]} { 5235 set ::tkcon::PRIV(SCRIPT) [file join [pwd] $::tkcon::PRIV(SCRIPT)] 5236 } 5237 } 5238 } 5239 6248 ## 5240 6249 proc ::tkcon::Resource {} { 5241 6250 uplevel \#0 { … … 5246 6255 } 5247 6256 5248 ## Initialize only if we haven't yet 6257 ## Initialize only if we haven't yet, and do other stuff that prepares to 6258 ## run. It only actually inits (and runs) tkcon if it is the main script. 5249 6259 ## 5250 if {![info exists ::tkcon::PRIV(root)] || \ 5251 ![winfo exists $::tkcon::PRIV(root)]} { 5252 ::tkcon::Init 5253 } 6260 proc ::tkcon::AtSource {} { 6261 variable PRIV 6262 6263 # the info script assumes we always call this while being sourced 6264 set PRIV(SCRIPT) [info script] 6265 if {!$PRIV(WWW) && [string length $PRIV(SCRIPT)]} { 6266 if {[info tclversion] >= 8.4} { 6267 set PRIV(SCRIPT) [file normalize $PRIV(SCRIPT)] 6268 } else { 6269 # we use a catch here because some wrap apps choke on 'file type' 6270 # because TclpLstat wasn't wrappable until 8.4. 6271 catch { 6272 while {[string match link [file type $PRIV(SCRIPT)]]} { 6273 set link [file readlink $PRIV(SCRIPT)] 6274 if {[string match relative [file pathtype $link]]} { 6275 set PRIV(SCRIPT) \ 6276 [file join [file dirname $PRIV(SCRIPT)] $link] 6277 } else { 6278 set PRIV(SCRIPT) $link 6279 } 6280 } 6281 catch {unset link} 6282 if {[string match relative [file pathtype $PRIV(SCRIPT)]]} { 6283 set PRIV(SCRIPT) [file join [pwd] $PRIV(SCRIPT)] 6284 } 6285 } 6286 } 6287 } 6288 # normalize argv0 if it was tkcon to ensure that we'll be able 6289 # to load slaves correctly. 6290 if {[info exists ::argv0] && [info script] == $::argv0} { 6291 set ::argv0 $PRIV(SCRIPT) 6292 } 6293 6294 if {(![info exists PRIV(root)] || ![winfo exists $PRIV(root)]) \ 6295 && (![info exists ::argv0] || $PRIV(SCRIPT) == $::argv0)} { 6296 global argv 6297 if {[info exists argv]} { 6298 eval ::tkcon::Init $argv 6299 } else { 6300 ::tkcon::Init 6301 } 6302 } 6303 } 6304 tkcon::AtSource 6305 6306 package provide tkcon $::tkcon::VERSION
Note: See TracChangeset
for help on using the changeset viewer.