Ask, and it shall be given # 11

How to post on this page

Please do not edit this part, it is meant as a guide!

This page runs the risk of being deleted and corrupted. Please be very careful when editing it. If you inadvertently delete it, immediately revert your edit using the History link on the left side of this page. Do NOT attempt to restore it by copying and pasting the text from a previous revision, or all page formatting will be lost!

Please put new questions at the TOP of the page, below this section, so that as the page grows longer, new questions are seen first.

Also please put a section header on top of every question and put two stars in the beginning of the title and two stars in the end. This will make your question's section easily editable.

Once you have received a satisfactory answer, please cut your question and answer directly on an appropriate page of the wiki. If you cannot find an existing page, create a new one.

You might also simply want to put a hyperlink leading to a page of the wiki where your question is included like Didier has done on February 5th 2011. This will save you the trouble of cutting your question to an existing page afterwards.

Put your question below. Thanks!

Aloha! I'm running Ubuntu 14 (Xfce) on a Chromebook-11 (Celeron processor) and am trying to use "snack," version 2.2. But I get error messages like "Unable to open mixer /dev/mixer" and "can't access /dev/sound/dsp." Could anyone help with this? Thanks!


trcel 2015-01-14 Tcl_DecrRefCount on lists

I am wondering about the use of Tcl_DecrRefCount in a Tcl extension. Here, I pass binary data from C to Tcl.

    // my_handler arg
    Tcl_Obj* cmd = Tcl_ObjPrintf("my_handler");
    // bytes from C program.
    Tcl_Obj* arg = Tcl_NewByteArrayObj(bytes, len);
    Tcl_ListObjAppendElement(NULL, cmd, arg);
    int rc = Tcl_EvalObjEx(interp, cmd, TCL_EVAL_GLOBAL | TCL_EVAL_DIRECT);
    // QUESTION: do I need to add
    // Tcl_DecrRefCount(arg);
    // Or does Tcl_DecrRefCount(cmd) already cover it?

Background image of ttk::treeview

ekd123 2014-12-28 - I'm writing a small program whose main window is basically a ttk::treeview. To prettify it, I want to show an image on it. I searched the Internet and read the doc, but had no luck. Is it possible to do this? If so, how? Thanks!

nurdglaw What are you trying to achieve? Does the -image option - available on the heading and insert widget commands - not do it for you?

ekd123 No. I want a background image for the whole widget, not just for a column.

bll 2015-1-1 Doesn't look promising. ttk::style configure Treeview -image $img seems to replace the text with the image rather than having it as a separate layer. ttk::style does not appear to support -background {} (for no background). This was supported by the non-ttk frame widget so I tried that.

ekd123 hmm what a pity. Perhaps I'd look into the source sometime. Thank you anyway. :-)

bll 2015-7-6 This is possible using the wm attributes . -transparentcolor option on windows and a second toplevel window containing the image. The treeview's background color doesn't turn transparent, though the fieldbackground color does.

ekd123 2015-8-29 Bram Lanam provided some code. It worked. Thanks Bram!

 package require Tk

 set tbg #abcdef ; # some color that will not be used...
 . configure -background $tbg
 wm attributes . -transparentcolor $tbg
 ttk::style configure TV.Treeview -background $tbg -fieldbackground $tbg
 ttk::treeview .tv -style TV.Treeview -show tree
 .tv insert {} end -text {line 1}
 .tv insert {} end -text {line 2}
 pack .tv -in . -fill both -expand true

 toplevel .bgimg
 .bgimg configure -background white

 proc dobg { } {
   wm geometry .bgimg [wm geometry .]
   lower .bgimg .

 bind . <Configure> dobg

 proc generate_data {} {
    set data [list]
    for {set x 0} {$x < 200} {incr x} {
       set row [list]
       for {set y 0} {$y < 200} {incr y} {
          lappend row [format "#%02x%02x%02x" [random_byte] [random_byte] [random_byte]]
       lappend data $row
    return $data

 proc random_byte {} {
    return [expr {int(rand() * 256)}]

 set image [image create photo] 
 $image put [generate_data]

 label .bgimg.l -image $image
 pack .bgimg.l -in .bgimg 

How to extract binary data from a database and return it from a web server

nurdglaw 2014-12-24 - Merry Christmas to all our readers.

I'm doing some work with a Tcl-based web server and am really stuck with trying to return some binary data (e.g. Word documents, or .zip files) that's stored in a database and should cause the client's browser to display a "Save As..." dialog. (I'm a Firefox user, and the dialog that FF should display gives the user a choice of "Open with..." or "Save As..." that's good, IE11 and Chrome do something similar but I'm unsure of the gory details of those two and ignorant of the details of other browsers, so I'll just refer to it as a "Save As..." dialog.)

The existing implimentation uses a Tcl script run as cgi and works fine, but I need to reimpliment the whole page to add some new features and am stuck on the file download part. I believe I have two distinct problems but maybe it's just one.

Problem 1: Although I believe I'm outputting exactly the same headers as the cgi script, none of the browsers I've tested on (Firefox, IE11 and Chrome) displays the dialog at all. Actually, I can see that I'm receiving the same headers, PLUS "Pragma: no-cache" and a couple of others which seem to be added "for free" by the server and that I was pretty confident would make no difference.

Problem 2: If I push the variable into which I deposit the data extracted from the db through string length, it returns, say 330000. The cgi script sends a message to the browser with a header of "Content-Length: 330000". The new implimentation gets exactly the same number of characters from the database but its Content-Length header has a value of around 480000. I've looked at the first kilobyte or so of data, and that returned by the cgi script has a number of ff bytes in it. The corresponding data returned by the new implimentation appears to be c3 bf. I know enough about encoding to know that I know nothing useful about it, which may be why this smells to me of an encoding problem. I hope that someone who understands encoding might be able to look at this and say "Aha, you're using a so-and-so encoding, but you should be using such-and-such" and that someone might be able to tell me how to achieve this. I'm mystified about how to achieve it anyway because I've looked at the configuration of stdout using fconfigure and as far as I can see, the channel is set up the same way both in my script and the existing cgi one.

I'm further mystified because I'd expect problem 2 to deliver corrupt data to the browser, which it would then offer to save for me and I wouldn't know it was corrupt until I tried to use it, but the browser isn't even offering to save it for me (problem 1).

I stopped banging my head against these problems about eight hours ago when I left work for the holidays so I'm a little hazy about the details - such as what the additional headers are that I'm returning, the exact lengths of data extracted from the db and returned by my script, and what exactly ff is being transformed into. If they would help, please say so and I'll add the details when I get back to work in January.

In the meantime, Happy Holidays, and thanks in advance.

Duoas 2014-11-28

I'm playing with Snack, and I can't figure out how to start a sound and then at any arbitrary point cause it to fade out. When I endeavor to pause and then play with a fade-out filter, it fails. I've also tried loading the sound data into memory with -load instead of -file, but it has no effect. Can someone help me?

Edit. Well, asked too soon, I guess. I should have 'stop'ped it instead of 'pause'ed it. example:

    set fadeout_time_in_ms 1500
    set filter [snack::filter fade out exponential $fadeout_time_in_ms]

    # (start sound playing and wait a bit)

    lassign [$sound info] length rate ;# length in samples, rate in samples per second
    set now [now] ;# returns seconds with millisecond resolution, as in, 1.500
    set start [expr {round( ($now - $music_start) * $rate )}]
    set stop  [expr {round( $start + $fadeout_time_in_ms / 1000.0 * $rate )}]
    $sound stop
    $sound play -start $start -end $stop -filter $filter

Duoas 2014-10-09

Is it possible to set a -minsize on the panes of a ttk::panedwindow? 2014-11-28 - Apparently not.

gold 2014-11-06

I was writing a wiki page for removing blank elements in list, but some routines with if statements are busted. Left draft and program at bottom of my user page gold, Console program for list of Unicode cards, values, multiple N1 decks. will post suggestion gems on future wiki page.

Menu - assign positions to menubuttons

HJG 2014-09-09 - A menu at the top of a window normally grows from the left, ie. "File","Edit","Options","Help" all appear next to each other.

Now I want to place them at separate positions, e.g. "File" and "Edit" as usual at the left, "Options" at the center, and "Help" positioned at the far right. How can this be done ?

It looks like separators are just barely visible here, and I also don't want to use dummy-menubuttons filled with spaces...

The tk-demos have examples for "Menus and cascades" and "Menu-buttons", but these are using grid and frame for the layout.

RLE (2014-09-08): If you are installing the menu using the -menu option to a toplevel window, then the answer is you can't.

To do what you want you'll have to build your own menu bar out of menu buttons and sub-menus and place/pack/grid it at the top of your window.

HJG Too bad, but thanks! I think I'll use the dummy-menuitem as a workaround after all, e.g.

 .m add command  -label "   "  -state disabled

RLE (2014-09-11): That would work as well, but unless you also bind to <Configure> on the window and adjust your spacing appropriately, it will not automatically adjust the positioning in light of window width changes.

griding in your own menu buttons at the top of your window would allow grid to automatically adjust the positioning of the buttons when the overall window width changes. All you have to do is tell grid which columns should expand/shrink, and how the menu buttons should be positioned within their grid cell.

Duoas You could do all that, but really, Don't do that!

People expect their programs to behave according to their platform standard. Windows users will find a left-aligned menu. Mac users will find a menu bar across the top of the screen. Etc. In all cases, the menu will look pretty and match the user's WM and themes. When you do an end run around the OS defaults and your user's preferences, your application goes from being slick and easy to use to clunky-looking and confusing and unfriendly to the user's wishes. Hobbits may put their doorknobs in the center of their doors, but the rest of us expect them to be in a specific place and to operate in a specific way. Likewise, your users will expect your application to look and behave according to their operating environment. Don't mess with that! Programs that behave differently than people expect -- programs that make people feel like they have lost control over their environment -- they get tossed pretty quickly.

TclOO - variables declared in a superclass

(2014-07-23) in TclOO, are variables declared in a superclass automatically imported in the methods of descendant class? I would expect so, but that is not the case:

    oo::class create A {
        variable v
        constructor arg {set v $arg}
        method get {} {return $v}

    oo::class create B {
        superclass A
        # this v is not related to the instance 'variable' of class A.
        method set arg {set v $arg}
        # using 'my variable' to link to the instance variable.
        method reallyset arg {my variable v; set v $arg}

    B create bb 1
    puts "initially v: <[bb get]>"
    puts "trying to set v to 99...: [bb set 99]"
    puts "alas v: <[bb get]>"
    puts "really setting v to 99: [bb reallyset 99]"
    puts "new v: <[bb get]>"
    puts ""

Is there some documentation I missed or misunderstood that explains this, or do I have to force the 'import' with 'my variable'?

After some more reading, I suspect it has something to do with slots, but I don't understand that part. Can you point me to an actual example?

APN If you do not want to use my variable in the method, you need to declare the variable in the subclass as well.

    oo::class create B {
        superclass A
        variable v
        blah blah

Both declaration refer to the same variable v in the object's namespace.

ttk::combobox - dropdown list

How to dynamically alter the contens of the dropdown list of a ttk::combobox? There is no $w configure -values "xyz" possible. Altering $w.popdown.f.l works, but it has no effect it seems. MHo Meanwhile, I answered the question by myself... configure -values indeed is possible....

Why does the wiki not accept UTF-8 characters?

It says "Encoding error" when I try to save a page with UTF-8 characters.

e.g. DISAPPOINTED FACE Unicode: U+1F61E (U+D83D U+DE1E), UTF-8: F0 9F 98 9E

AMG: Reported here: [L1 ]

In tcloo its an error to call next from a mixin if the class has no constructor?

How does a mixin know if next needs to be called? This seems like a case where do nothing quietly might logically apply.

Example that fails because the mixins must know about the constructor existence of other things mixed into the class. What if the mixins are mixed in a different order? Or a third mixin should like to be added to one class but not another?

 oo::class create mixin2 {
    constructor args {
 oo::class create mixin1 {
    constructor args {

 oo::class create class0 {
    mixin mixin1
    mixin mixin2

    constructor { args } {}

 class0 create inst

APN I think I'd asked this question before but don't remember getting an answer or resolution. This issue does not arise for just mixins but inheritance as well when inheriting from multiple classes. What I land up doing in my own classes is to always have a constructor that does nothing and always have mixin classes call next. This does not take care of all cases, multiple inheritance for example, but works for my relatively simple needs.

At some point in 8.6 development the nextto command was added to deal with this situation by allowing you to control the order in which methods in the method chain are invoked. Not thought about it enough to know if it is a complete solution to the issue, but I've found it useful, for example when mixin constructors differ in their arguments.

You can also use self next to check if there is another method in the chain or not, before calling next.

Note as an aside that in your example, the second mixin statement overwrites the first mixin statement so the class actually has only one mixin. To have both classes mixed in, either use a single mixin statement or use the -append option for the second mixin statement. However, that is not relevant here.

In tcloo can I create a new "slot" type class variable?

discussion moved to The methods that don't say "my"!

Multiple instances access to options.

RJH 6th June '14: How should I configure an application so that it takes its GUI options from the xrdb database even when multiple instances are running?

In all tests I have managed so far the first instance of the application gets the correct options. The subsequent instances do not - presumably because of the #2, #3 etc baing appended to thier appname. I have tried resetting the appname but to no avail.

Am I missing something obvious?

Many thanks, R.

Non-fatal warnings

AMG: What are some good ways to collect and present non-fatal warnings in scripting languages, Tcl in particular? [error] is nice and easy, but it has the sometimes-undesirable side effect of jumping up to the (perhaps distantly) enclosing [catch] or [try]. I tend to use [puts stderr], but this doesn't work so well when the code is a package being embedded in an application that may wish to present warnings differently, e.g. in Tk.

Perhaps I'm answering my own question, but here's what I just did. In my package foo, I made a command called ::foo::warn which just prints its argument to stderr. I also put a comment above it inviting the user of the package to override it between loading and using the package.

find a text in a line and replace the next line

Note: For those who don't follow comp.lang.tcl, this same individual has been asking the same question there over the course of the last couple weeks. He/She has been extremely resistant to actually learning anything and instead simply keeps asking for the answer to be handed to them on a silver platter. There was one member who continued trying to help but finally gave up in frustration because of the person's unwillingness to learn even the slightest bit of knowledge about "how to program a computer". One conclusion has been that this individual is a beginning student attempting to cheat on his/her homework by getting Usenet (and now the wiki) to do their homework problems for them.

tclamateur: I want to find a text in a line and replace the contents of the next line with a new string. I tried regsub, but it is only matching the first line. I don't know how to go to the next line. eg:

line 5> this is line 5.

line 6> apple


line 5> this is line 5.

line 6> banana


AMG: [regsub] has the -all option to replace every occurrence, not just the first.

proc replace {match replacement text} {
    # Backslash-quote special characters in match and replacement so they will
    # be interpreted as literal strings.
    regsub -all {[][*+?{}()<>|.^$]} $match {\\&} match
    regsub -all {[\\&]} $replacement {\\&} replacement

    # Perform the replacement.
    regsub -all ($match\\n)\[^\\n\]* $text \\1$replacement

replace "this is line 5." banana {
this is line 5.
this is line 5.
another apple
this is not line 5.
yet more apples

This gives the following result:

this is line 5.
this is line 5.
this is not line 5.
yet more apples

MG offers:

proc replace2 {args} {

if { [llength $args] < 3} {
     return -code error "wrong # arguments: replace2 ?-all? ?-regexp|-glob|-exact? \$find \$replace \$text"
set find [lindex $args end-2]
set replace [lindex $args end-1]
set text [lindex $args end]
set args [lrange $args 0 end-3
set matchtype -exact
set all ""
foreach x $args {
if {$x eq "" } {
   } elseif { $x eq "-all" } {
     set all [list "-all"]
   } elseif { $x in [list -regexp -glob -exact] } {
     set matchtype $x
   } else {
     return -code error "unknown option '$x'"
set text [split $text \n]
set matches [lsearch {*}$all $matchtype $text $find]
if { [llength $matches] && [lindex $matches 0] != -1 } {
     foreach x $matches {
        incr x
        set text [lreplace $text $x $x $replace]
return [join $text "\n"]


# Example:
replace2 -all -exact "this is line 5." banana {
this is line 5.
this is line 5.
another apple
this is not line 5.
yet more apples

tclamateur: Thanks for the input. In my case I'll have only two inputs. The input "match" and the input "replacement". What to give as input for "text"?

AMG: Whatever text you want the substitution to be performed on. For instance, if you're working on a file, you'd supply the contents of that file. Then write the return value back out to the file, and you're done.

Tcl GUI in Java environment

BillF 2014-04-16 - I have a need to port some existing Tcl/Tk scripts to a system without Tk or an X-windows equivalent installed. All the GUI displays on the target system have been implemented by the vendor in Java. I see on this wiki that Jacl/Swank are available and they appear to provide a solution to my problem. However, I cannot find any examples of how to port existing Tcl/Tk source to execute under Jacl/Swank. If someone can provide the details of how to do this, I would be very appreciative. Something as simple as porting the "Hello World" example found on this wiki would be immensely helpful. Thanks.

Tags for non-canvas items

HJG 2013-03-31 - I just noticed that non-canvas items like buttons, labels etc. cannot have tags. I think it would be useful to be able to organize / configure groups of widgets with tags, like it can be done on a canvas. Is there a reason they don't have tags, is there already an easy way to re-configure a group of widgets, or should I create an 'idea-page' for that ?

RLE (2014-04-01): One page describing your idea: Widget tags

User presses Window minimize

pdt Hi, I'm trying to determine when a user clicks on a window's minimize button. I've tried binding to <Unmap>, but I haven't got that to work because switching between virtual screens unmaps the window as well as pressing the minimze button.

Any suggestions?


RLE (2014-02-02): What is the windows wm state value between the two possibilities? If wm state differs then you might be able to detect minimization by binding to <Unmap> and looking at wm state.

pdt For both cases wm state returns iconic, so it doesn't look like I can use that.

HE (2014-02-03): The minimize button doesn't belong to the context of Tcl or Wish. It belongs to the Windows Manager (WM). It tells the WM, that the user request to minimize (iconify) the program window. This means, the program window shouldn't be displayed in the moment but kept existing (kept managed by the WM). The same occurs when you switch to another screen, or when 'wm iconify .' is used. Therefore, I would expect, that there is no way to get the information from the WM that the minimze button is pressed.

pdt You _may_ be right. Howvever, it's interesting that Java Swing's WindowListener for example has the ability to trap a minimize event on a window. After searching I came across someone listening for minimize and then creating a tray icon.

All that I want to do however is that when a minimize event occurs on a window, another window in my application that might be open will be minimized as well.

HE (2014-02-04): Sorry, if that wasn't what you are looking for. But, I guess that windowIconified of the WindowListener does the same as the <Unmap> event in tcl.

For my curiosity, do you have an existing example that the WindowListener distinguish between iconify (unmap, minimize) because of pressing the minimize button and iconify because of switching to another virtual screen?

pdt (2014-02-05): No I don't have an existing example, but I'm kind of curious myself now. I don't have much time this week, but I'll see if I can investigate WindowListener at the weekend, see what it does, and post back here.

pdt (2014-02-07): The following Java code shows that Swing's windowIconified only responds to a user pressing the minimize button, and doesn't respond to changing to a virtual screen.

import javax.swing.*;
import java.awt.event.*;
public class Test {
    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
    private static void show() {
        JFrame frame = new JFrame("Hello");
        frame.addWindowListener(new WindowAdapter() {
            public void windowIconified(WindowEvent e) {
        JLabel label = new JLabel("Hello.................................");

MG I'm not aware of a way to trap it (I had thought wm protocol may be able to, since you can catch WM_DELETE_WINDOW, but having looked through the spec I can't see anything related to minimizing that might help). However, if you want one toplevel to minimize/restore with another, wm transient may be what you're looking for?

pdt (2014-02-05): Yes, tried wm transient. From the man page, it says that the WM may decorate the window differently, and that's not what I want. With Gnome3, the WM doesn't put a maximize button on the window, which is something I don't really want to live without. There were also other issues with wm transient, but that's the main one. What I've done for now is just left my application the way it was, i.e. minimize one window doesn't minimize all. I've decided I can live with that. It's not perfect, but sometimes perfect is too hard to achieve.

KPV How about wm group? I'm believe that command was designed for what you want but I wouldn't be surprised if not all WM implement it.

pdt No, wm group doesn't work, at least for the WM I'm using.

XNO (2014-02-03)

how do I know I am in the event loop, that is, a vwait is pending? It doesn't seem possible in Tcl, and I can't find the right function in the C API.

AM What would be the purpose of knowing that? You want to know which variable is being waited on? You could do that by redefining vwait:

rename vwait _vwait
proc vwait {var} {
    set ::VariableBeingWaitedOn $var
    _vwait $var

Note, however, that any code that runs during a vwait is started by an event - initiated by [after] for instance or via Tk or other event sources.

XNO why? If the event loop is already running, I don't need to start it. And if there is none, I need to. Since vwait 'stacks up', a clean exit becomes tricky if I have to care about that stack.

Exotic file names with exec

RJH 31 Jan 2014: What is the correct/official/proper way of handling exotic file names in a list for 'exec'? By exotic, I am particularly concerned at present with whitespace.

If I may give an example:

  set files [list file1 file2 file3]

  # These would work fine
  exec ls -l {*}$files
  exec mv {*}$files /directory
  # etc.

  # ... but, the Unix/Linux filesystems have long supported a wide variety of characters - including space, tab etc.

  set files [list file1 file2 "another file"]

  exec ls -l {*}$files
  # produces: ls: cannot access {another file}...

  # exec performs fine when passed the proper argument, these are both fine:
  exec ls -l "¬her file"
  exec ls -l {another file}

The {*} expansion naturally encloses the third element with braces {} instead of quotes "" in accordance with TCLs dodecalogue (4). But this causes problems for exec.

So; how should this be handled?

Many thanks, R.

Duoas I cannot reproduce your problem. What OS and version of tclsh are you using?

RJH: Odd. I tested on a Unix machine at work. I don't have access to that over the weekend, but testing on my linux machine at home I agree that it works as expected. Ignore this one. Something must be amiss, I'll check further next week.

Thanks again, R.

RJH: I must apologise. I was in a hurry and misread the output from some old code. Ignore this one.

uplevel/return confusion

Answered here .

Scrolling Viewport/Items Efficiency

Answered here .

Strange things happen - or not seeing the forest for the trees:

Wurzelsepp: I have a script that used to run on older versions, but fails on 8.5. Now I have reduced it to the bare minimum, here:

 proc cequal {a b} {
        return [string equal $a $b]

 proc getresponse {s {aid {}}} {
        while {[gets $s line] >= 0} {
                puts stderr =$line
                if [regexp {^([A-Za-z].*?): (.*)$} $line all key val] {
                        puts stderr "found key $key"
                        set data($key) $val
                } elseif [cequal $line ""] {
                        if [info exists data(Response)] {
                                puts stderr "block complete"
                                return $data(Response)
                        catch {unset data}
                } elseif [regexp Follows $data(Response)] {
                        set data(Response) $line

 proc get1response {s {aid {}}} {
        while {[gets $s line] >= 0} {
                puts stderr =$line
                if [regexp {^([A-Za-z].*?): (.*)$} $line all key val] {
                        puts stderr "found key $key"
                        set data($key) $val
                } elseif [cequal $line ""] {
                        if [info exists data(Response)] {
                                puts stderr "block complete"
                                return $data(Response)
                        catch {unset data}

The only difference between the two seems to be a correctly formatted elseif clause. When I run the snippet in wish, I get

 source /tmp/x.tcl
 % getresponse stdin
 Response: Success
 =Response: Success
 can't read "data(Response)": no such variable
 (type CTL-D here)
 % get1response stdin
 Response: Success
 =Response: Success
 found key Response
 (type CTL-D here)

what could I try to get it working

AMG: Here's your answer: [L2 ]. You need to put braces around your expression arguments to [if], or else they're all evaluated every time, before the [if] is even executed. This means the first pass through the [if] requires the $data(Response) variable to already exist, no matter which branch is executed.

Wurzelsepp: Thanks a lot - it is working: so if I understand you right, on 8.3 (where the script was developed) the one set of braces in

 while {[gets stdin line] >= 0} {if [something] {code}}

was sufficient to evaluate the [something] at the right time, and now it is

 while {[gets stdin line] >= 0} {if {[something]} {code}}

AMG: This is not an incompatibility between versions of Tcl. Tcl has always had these substitution rules: [L3 ]. (Argument expansion is a fairly recent addition, but it's not used in your code.)

Your impression that this is a new quirk of Tcl 8.4 and beyond is due to coincidence. I'm sure this is the first time you used elseif or else expressions which depend on the side effects of previous expressions or invocations of the [if]. If you never do that, the order of evaluation doesn't matter. But in this case, it certainly does, so we're going to take a hard look at it.

Consider the sequence of events in the following code:

proc cequal {a b} {string equal $a $b}
while {[gets stdin line] >= 0} {
    if [regexp {^([A-Za-z].*?): (.*)$} $line _ key val] {
        set data($key) $val
    } elseif [cequal $line ""] {
        if [info exists data(Response)] {
        unset -nocomplain data
    } elseif [regexp Follows $data(Response)] {
        set data(Response) $line

Here's precisely what's going on. (I'll leave out details like type shimmering and bytecode compilation since they have no impact on correctness, only performance.) There are only two commands at the top level, though invocation of those commands recursively involves invoking other commands. The commands are [proc] and [while]

First, [proc] receives three arguments, which it uses as the name, argument list, and script body of the proc it creates.

  1. "cequal"
  2. "a b"
  3. "string equal $a $b"

Second, [while] receives two arguments. It evaluates the first argument as an [expr]-type expression before each iteration of the loop, and (if true) it evaluates the second argument as a Tcl script.

  1. "[gets stdin line] >= 0"
  2. Everything between (but not including) the braces

The body of the [while] loop consists of exactly one command: [if]. [if] receives eight arguments:

  1. The result of the [regexp {^([A-Za-z].*?): (.*)$} $line _ key val] substitution
  2. "set data($key) $val"
  3. "elseif"
  4. The result of the [cequal] substitution
  5. "if [info exists" (etc.)
  6. "elseif"
  7. The result of the [regexp Follows $data(Response)] substitution
  8. "set data(Response) $line"

It's crucial to note that the above strings are computed before [if] is called, therefore before any of its script arguments are called. Consequently, $data(Response) must already exist before the first iteration of the loop! That's your problem.

After changing your [if] to brace all its arguments, it receives:

  1. "[regexp {^([A-Za-z].*?): (.*)$} $line _ key val]"
  2. "set data($key) $val"
  3. "elseif"
  4. "[cequal]"
  5. "if [info exists" (etc.)
  6. "elseif"
  7. "[regexp Follows $data(Response)]"
  8. "set data(Response) $line"

It might not look like much of a difference, but it's huge. The crucial distinction is that none of its arguments are derived from substitutions. They are all literal strings. They don't need to be computed, so there's no way their computation can have any side effects such as crashing your program if a variable doesn't exist.

Now that [if] is allowed to proceed, it evaluates its first argument (see above list) as an [expr]-type expression. Now the [regexp ...] substitution occurs, with the possible side effect of creating the $_, $key, and $val variables. If the result of the substitution is true (nonzero), set data($key) $val is executed. But if not, the fourth argument is evaluated as an [expr]. And so forth.

What matters to you is that only when the first and fourth expression arguments evaluate to false (zero) does [if] even try to take the value of $data(Response), in the course of preparing the arguments to [regexp].

This may seem like excessive detail, but you really ought to review this example carefully if you want to understand how Tcl actually works so as to avoid future surprises. Strictly speaking, Tcl concerns itself only with basic text processing such as substitution, concatenation, and splitting words and lines. All program logic is implemented in commands such as [proc], [while], and [if]. There are no keywords or special cases. You have to understand your program as Tcl sees it (e.g., in terms of substitutions and word separation) separately from how your commands ([while], [if], etc.) see it.

Wurzelsepp: well, many thanks for the detailed explanation - I have a pile of code that will eventually need to move onto a current tcl, and these are good pointers where to look at (before trying to run it and hoping :) The big question, though: why did it work in the first place? When I found it not working, I first suspected the data source, so I created the test script and typed the expected input. Now I have an 8.3 system on one side, and an 8.5 on the other, and they behave differently. According to your explanation it should have never worked even on the old system (because "data" is initially empty) BTW: this is part of an Asterisk interface - it lets you enter a phone number in a tk entry and dial it

AMG: If this behavior really does differ between 8.3 and 8.5, then it's a bug in 8.3 and you should report it [L4 ]. Be sure to clearly indicate the versions involved! Also feel free to reference this page using this unambiguous URL: .

List Connected USB devices on Win (XP/7/8)?

I'm hoping someone has come up at some point with a tcl script on windows to see connected USB devices. Not just dump the USB registry entries, but show what's actually connected, preferably with "friendly names". Googled (and checked here) but nothing.

I'm assuming TWAPI is needed. And so far, looks like I need to access: Win32_USBControllerDevice

Really not making any progress yet, and before I devote even more time, thought I'd ask if anyone has such a thing tucked away somewhere.

BTW, this link shows it implemented nicely with a vb script:



APN A TWAPI version of above link is at TWAPI and USB.

RJH 17/1/14: TWAPI may be useful - but it is not essential. If it is not convenient to install TWAPI you can get all sorts of information through powershell on any recent version of Windows.


set a [exec powershell -Command "get-wmiobject win32_bios"]


set a [exec powershell -Command "(get-wmiobject win32_bios).SerialNumber"]

In your case, start with

set a [exec powershell -Command "get-wmiobject Win32_USBControllerDevice"]

from there you have two choices:

  1. Write simple powershell (e.g: the line above) and write complex TCL to parse the result for the information that you need.
  2. Write complex powershell which will return to TCL only the sanitised/formatted information that you need.

(of course - you are much better off with the secret option 3 - find the correct powershell online somewhere and use that...)

RJH 17/1/14.

MHo 2014/10/1: On my systems, exec powershell won't work. Don't know why. Open |powershell does not work, either. No process is created, regardless of using tclkit 32bit or 64 bit. Just found the answer by myself: using the gui version of tclkit isn't possible here - powershell needs a console, it seems (regardless of specifying -NonInteractive). This is because the tclgui has no real console attached. TWAPI's allocate_console and free_console are helpfull here....but again, TWAPI is required...

Accessing the help pages without changing the default directory

BMA (2013-10-26) My question is here: Signing a JWT header for Google OAuth2

Tcl/Tk 8.5/8.6 Installation Question

pvasudev, October 22, 2013 11:27 AM

Hi. I hope that I am editing this page in the right way by pressing the "Add Comment" button.

Either way, I have an installation question to ask. I installed Tcl/Tk version 8.6 from source, but Ubuntu doesn't seem to realize that I did that. When I was trying to install the python-tk package, it told me that it would automatically install Tcl/Tk8.5. I accepted, and installed Tcl/Tk8.5. So, here is my question.

1) Is there a way to remove the Tcl/Tk8.6 from source that I installed? I can't seem to find a "make uninstall" or anything like that. 2) By installing Tcl/Tk8.5 from a sudo apt-get install command on Ubuntu, did I wreck the Tcl/Tk8.6 install? 3) Perhaps a silly question, but if I didn't install Tcl/Tk8.6 from source and simply went "sudo apt-get install" to install tcl/tk8.5 would it be fully functional and properly working?

The reason I'm doing this is I want to install VTK, and VTK6.0 worked, but I need to make a VTK5.10 installation, and when installing VTK5.10 installation, it's giving some errors relating to Tcl/Tk so I have a feeling that I messed up the Tcl/Tk installation. I am new to all of this stuff, so any help would be greatly appreciated!


RJH 1st Oct. 2013 - returning non-contiguous elements from a list

what is the proper/recommended/standard way of returning non-contiguous elements from a list? I have been reading man pages around lindex/lrange etc. and searching the wiki but found nothing.

For clarification, I am talking about something along the lines of:

litems {a b c d e f g} 1 3 6 5
a c f e

This seems like such a basic use-case (and I could probably hack some inefficient version myself) but surely I am not the first to stumble across it?

Thanks, R.

000 3rd Oct 2013

Straightforward solution would be

proc litems {data args} {
    set r [list]
    foreach i $args {lappend r [lindex $data $i]}
    return $r

Relatively fast, ~4 mcs. Note that list item index in TCL starts from 0, not 1, so return value of your example would be "b d g f" If you insist on 1-based indexing for your data, then proc would be

proc litems-1 {data args} {
    set r [list]
    foreach i $args {lappend r [lindex $data $i-1]}
    return $r

RJH: Thanks. That is exactly the solution which I had already coded as a stop-gap. I just assumed that such an obvious case had been coded into the core language at the C level. Silly me. This works perfectly for my, undemanding, use-case (a handful of items needed from a list of no more than 20), I just worried that it would be slow for larger lists.

Thanks again, R.

RS 2013-10-04: well, lindex, lappend as well as foreach are all coded in C. Tcl is just used to glue the calls to these together... ^)

000 4th Oct 2013: Of course, if you absolutely want one command approach, you can go for

lmap i {1 3 6 5} {lindex {a b c d e f g} $i}

Needs 8.6, obviously, but option is always there ;P ...But it seems to actually be slower than straightforward solution XD...

RJH: Ah... The lmap seems somehow 'more elegant' (perhaps because it is vaguely 'lispy'), but I am quite happy to stay with the long-winded version. Many thanks again for the help.

DRB 2013-09-19 - list of installed image file format handlers for photo

I see no way to request the list of installed image file format handlers for photo. Have been Googling for days. Is there a way to do this within Tk? I am trying to remove platform dependencies from a script developed on Windows. Testing with various Tcl/Tk on Mac OS/X Mountain Lion. I fell back to PPM for images because that seems to be universal, but would prefer the compression of PNG or JPEG if it is available in the bundle/starpack/whatever. Sorry I'm an idiot.

MG I'm not aware of one, unfortunately, but it would be a nice addition. One thing you can do is check the version of Tk. All versions back to at least 8.3 (and probably a lot further) have GIF support. 8.6 adds PNG support in the core. Beyond that, it's dependant on external packages, the most common being Img and its component parts (img::jpeg, img::pcx, etc).

gold 24aug2013

i am working on Heat Engine Combustion and Calculator Demo Example. gold closed out 27May2014

MG - build a Tcl extension on Windows

I'm trying to build a Tcl extension on Windows using Microsoft Visual Studio Express 2012 Desktop. However, when I try the build I get a link error:

  Error        1        error LNK2019: unresolved external symbol _Tcl_InitStubs referenced in function _Mytest_Init

I have USE_TCL_STUBS defined and am linking against tclstub86.lib; the build log ends with

         Unused libraries:
           C:\Program Files (x86)\Windows Kits\8.0\lib\win8\um\x86\user32.lib
           C:\Program Files (x86)\Windows Kits\8.0\lib\win8\um\x86\gdi32.lib
           C:\Program Files (x86)\Windows Kits\8.0\lib\win8\um\x86\winspool.lib
           C:\Program Files (x86)\Windows Kits\8.0\lib\win8\um\x86\comdlg32.lib
           C:\Program Files (x86)\Windows Kits\8.0\lib\win8\um\x86\advapi32.lib
           C:\Program Files (x86)\Windows Kits\8.0\lib\win8\um\x86\shell32.lib
           C:\Program Files (x86)\Windows Kits\8.0\lib\win8\um\x86\ole32.lib
           C:\Program Files (x86)\Windows Kits\8.0\lib\win8\um\x86\oleaut32.lib
           C:\Program Files (x86)\Windows Kits\8.0\lib\win8\um\x86\uuid.lib
           C:\Program Files (x86)\Windows Kits\8.0\lib\win8\um\x86\odbc32.lib
           C:\Program Files (x86)\Windows Kits\8.0\lib\win8\um\x86\odbccp32.lib
           C:\Program Files (x86)\Microsoft Visual Studio 11.0\VC\lib\OLDNAMES.lib

     1>mytest.obj : error LNK2019: unresolved external symbol _Tcl_InitStubs referenced in function _Mytest_Init
     1>mytest.obj : error LNK2019: unresolved external symbol _Tk_InitStubs referenced in function _Mytest_Init
     1>E:\MSVC-Tests\Mytest\Debug\Mytest.dll : fatal error LNK1120: 2 unresolved externals
     1>Done Building Project "E:\MSVC-Tests\Mytest\Mytest\Mytest.vcxproj" (Build target(s)) -- FAILED.

I am completely stumped; I've been fiddling with various options and Googling for an hour to no avail. Any help would be greatly appreciated. My .c file is:

#include "mytest.h"

int Mytest_Init (Tcl_Interp *interp ) {

        if (Tcl_InitStubs(interp, TCL_VERSION, 0) == NULL) {
                return TCL_ERROR;

        if (Tk_InitStubs(interp, TK_VERSION, 0) == NULL) {
                return TCL_ERROR;

        return TCL_OK;

And mytest.h:

#ifndef _MYTEST
#define _MYTEST

#include <windows.h>

#include <tcl.h>
#include <tk.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <tkPlatDecls.h>


#if defined(_MSC_VER)
#   define EXPORT(a,b) __declspec(dllexport) a b
#   define DllEntryPoint DllMain
#   if defined(__BORLANDC__)
#       define EXPORT(a,b) a _export b
#   else
#       define EXPORT(a,b) a b
#   endif

#define DLL_BUILD
#define BUILD_Mytest_Init

#if defined(BUILD_Mytest_Init) || 1

#ifdef __cplusplus
extern "C"

EXTERN int Mytest_Init _ANSI_ARGS_((Tcl_Interp *interp));


#endif /* _MYTEST */

MG Update - I have somewhat solved the problem (huzzah!). The error message was bloody useless. The problem was that it was trying to build it as an x86 DLL and my tclstub86.lib was x64. Unfortunately, I don't seem to be able to build it as x64 due to a MS lib (dllmain.lib) being x86, so I took the easy way out and downloaded the x86 Alist file1 file2 ctiveTcl. Linking against that tclstub86.lib works like a charm. I'll just have to bug a friend to build the 64bit version for me later, I guess.


>>> On m¬y profile page, I have lines [ Drake... and Stonehenge ..} that won't link. Is it the font that my notebook delivers? Thanks

gold - hotted button

Can a hotted button or hotted link to Formatting Rules or a (this wiki) style guide be placed either (1)on the left icon window bar or (2)at the bottom of the changes page or (3)near the editor application window. A hotted icon to the rules on the left bar would be nice. thankx

RLE (2013-07-12): What, exactly, is a _"hotted"_ button or a _"hotted"_ link?

If you are actually referring to a link to the style guide, you can achieve a similar purpose by simply bookmarking the formatting rules page URL in your local browser. Not the same as having a link in the quick links section (where everyone sees it) but bookmarking it would give you fast access to return to the formatting page yourself.

Absolute beginner

See: The Hello World program as implemented in Tcl/Tk

Where is the "Contributed scripts in the public Expect archive"?

jrw32982 2013/06/04 - The link on is broken (points into

aspect: The man page links from work, but the example code is hidden away in the repository at ... they are also packaged in some distributions: for example, on Debian installing "expect-dev" gets you copies in /usr/bin/expect_*

jrw32982 2013/06/05: Thanks. I can see the example/ directory in the expect source that I have (expect5.45.tar.gz). Is the example/ directory equivalent to the "public Expect archive"? I guess I was expecting more and different examples than that.

22nd May 2013 - Processing Windows 7 Archive Files

I thought I'd write a quick application to allow me to compact my Windows 7 Archive files. To that end I used vfs::zip package. I then attempted to create a list of all the files in a particular zip file for example -

   package require vfs::zip
   set archfile "Backup Set 2013-05-10 190005/Backup Files 2013-05-19 190012/Backup files"
   set mnt_file [vfs::zip::Mount $archfile]
   set ZipDirs [glob -directory *]

and then using some crude code of I go down the tree structure

   set penitrate true
   set sublevel 0
   set ZipSubDir$sublevel $ZipDirs
   while { $penitrate } {
        foreach ZipSubDir [set ZipSubDir$sublevel] {
                if { [file isdirectory $ZipSubDir] } {
                        incr sublevel
                        set ZipSubDir$sublevel [glob -directory $ZipSubDir *]
                } else {
                        set penitrate false
                        set sublevel 0

This works well until I reach the actual files when I get the message

no files matched glob pattern "*"

yet if I inspect the zip file with say 7z then this does display the files

Is there something clever/silly about windows 7 archive zip files which the zip package does not understand? or am I doing something rather stupid - besides using windows :)

I'm using TCL 8.6

cheers Ian Mac

aspect That error message indicates that glob is looking at an empty directory - you probably want to use the "-nocomplain" option?

14th May 2013 - returning a value from a procedure

When returning a value from a procedure; what is the difference between ending the procedure with

  return $a


  set a

They appear to do the same thing.

I ask because almost every other language that I know returns values from procedures using a statement called 'return' and the tcl language evidently contains a statement called 'return' and yet I often see 'set' being used to return the value instead... Are there important reasons for using one rather than the other? Are there subtle differences that I have overlooked?

Many thanks, RJH.

MG The return command can be used to explicitly return a value at any point, as well as being able to return error codes, etc. However, if there is no return call present, the proc returns the result of the last command it ran. So, when you want to return the value of a variable, 'return $foo' and 'set foo' are basically equivilent. The former is clearer as to the intent, though, so is generally preferable. (I believe that some people started using 'set foo' instead before because, at one point, the set command was byte-compiled but return was not. As far as I know, though, that hasn't been the case since some time in 8.4)

RJH I'm grateful for the clarification. The fact that they are equivalent (in this use-case) was a conclusion which I had already reached - but it's nice to have that confirmed by someone more experienced. The difference in efficiency re: byte-code compilation is interesting and I couldn't resist a quick test:

  % proc p1 {} {
  set a 1
  set a
  % proc p2 {} {
  set a 1
  return $a

  % time p1 10000000
  0.7192274 microseconds per iteration

  % time p2 10000000
  0.7277182 microseconds per iteration

  % time p1 1000
  2.052 microseconds per iteration

  % time p2 1000
  2.04 microseconds per iteration

Which agrees with your inference that any performance differences are minimal. Thanks again.

Cannot Build Extensions - 10th May 2013

I appear to be unable to build C extensions. This is my attempt at xop:

  $ ./configure
  checking for gcc... cc
  checking for C compiler default output file name... a.out
  checking whether the C compiler works... yes
  checking whether we are cross compiling... no
  checking for suffix of executables...
  checking for suffix of object files... o
  checking whether we are using the GNU C compiler... yes
  checking whether cc accepts -g... yes
  checking for cc option to accept ANSI C... none needed
  checking for a BSD-compatible install... /usr/bin/ginstall -c
  checking whether make sets $(MAKE)... yes
  checking for ranlib... ranlib
  checking build system type... i686-pc-linux-gnu
  checking host system type... i686-pc-linux-gnu
  checking for Tcl public headers... /usr/include
  checking for Tcl configuration... configure: WARNING: Can't find Tcl configuration definitions

  $ locate

  $ ./configure --with-tcl /usr/lib
  configure: WARNING: you should use --build, --host, --target
  configure: WARNING: invalid host type: /usr/lib
  checking for /usr/lib-gcc... cc
  checking for C compiler default output file name... a.out
  checking whether the C compiler works... yes
  checking whether we are cross compiling... no
  checking for suffix of executables...
  checking for suffix of object files... o
  checking whether we are using the GNU C compiler... yes
  checking whether cc accepts -g... yes
  checking for cc option to accept ANSI C... none needed
  checking for a BSD-compatible install... /usr/bin/ginstall -c
  checking whether make sets $(MAKE)... yes
  checking for /usr/lib-ranlib... no
  checking for ranlib... ranlib
  checking build system type... Invalid configuration `/usr/lib': machine `/usr/lib' not recognized
  configure: error: /bin/sh ./config.sub /usr/lib failed

Is this a common problem? Does anyone else notice similar? I have a standard installation of slackware-14, which reports:

  root@two:~# slackpkg search tcl

  Looking for tcl in package list. Please wait... DONE

  The list below shows all packages with name matching "tcl".

  [ installed ] - expect-
  [ installed ] - hfsutils-3.2.6-i486-4
  [ installed ] - tcl-8.5.11-i486-1
  [ installed ] - tclx-8.4-i486-3
  [ installed ] - tix-8.4.3-i486-2
  [ installed ] - tk-8.5.11-i486-1

  You can search specific files using "slackpkg file-search file".

I am aware that slackware are slow in releasing an official 8.6 package, but surely 8.5.11 should be compatible with the configure included with xop?

Any help would be appreciated.

Many Thanks, Richard.

RLE (2013-04-10): Try this way: --with-tcl=/usr/lib/

Configure options need the '=' to work right.

RJH - Thanks. I stumbled across that myself 5 minutes before coming back to edit this page...

Window Manager? - 5th May 2013

I am very new to tcl/tk and am having trouble finding information on a particular subject. TIP No. 47 details changes needed to allow an X11 window manager to be implemented in core tk. I can also see tantalising possibilities in such things as binding MapRequest events. However there the trail runs dry. Searching this wiki; I have found the whim and tkwm projects, but these both appear to rely on external extensions written in C. I also note that whim appears to have been abandoned for several years.

So to the questions:

  • Has there been any progress on writing X11 window managers in native/core tk, with no extensions?
  • How are core facilities like bind MapRequest intended to be used, if the other facilities which would be neccessary for a WM are not available in the core tk distribution?

Many thanks, Richard.

gm - 2013/04/13 - tkpath

I'm trying to install tkpath tkpath on Windows XP/tcl8.6 is installed and works. The instructions say 'download from cvs and install'. I downloaded from cvs, I put it in /tcl and it is not accessible. The demos don't work. The code doesn't work. How did other users install it? When I know I will update the instructions to be useful.

lm - 2013/03/28 - tclXML

I'm trying to install tclXML but only the pure Tcl parts. The doc says then to run ./configure and then make install. Unfortunately, configre is looking for xslt-config file. So, should I install xslt in order to have the pure tcl tclXML ? (and the same thing may happen for libxml2 ?). Could it be possible to have a --without-xslt and --without-libxml2 flag in configure ? Thanks !

What to do with an extra Tcl_Obj

jbr - 2013-03-24

I'm writing a C extension to Tcl and have allocated an object with Tcl_NewObj() for the return value. Logic later in the routine may detect an error I need to free this guy. There is no Tcl_FreeObj(), do I just call Tcl_DecrRefCount(objPtr)? The man page is not very verbose on this subject.



MG That is the impression I get, from reading the manpage, too, yes. A new Tcl_Obj from Tcl_NewObj() has a reference count of 0. Calling Tcl_DecrRefCount() will then set it to -1, which will cause the Tcl_Obj to be freed instantly.

MouseWheel xy bug ?

ABU 17 Mar 2013

I noticed this strange behaviour on Mac (on Win it's OK):

Let's take this simple case

  canvas .c -bg yellow
  pack .c -expand true -fill both -pady 50 -padx 50
  focus .c  ;# this is necessary on Windows ..
  bind .c <Button-1>   { puts "B1 on %W  %x %y" }
  bind .c <MouseWheel> { puts "MW on %W  %x %y" }

I'm working with ActiveTcl 8.5.13

  • On Windows

Acting on B1 and on MouseWheel, you get the same coords (GOOD)

  • On MacOs

Printed coords are different ! In particular if you click near the top-left corner you'll get something very close to (0,0) (good), but if you act on mousewheel you'll get something close to (50,50) !!

  • On Unix

? to be tested ..

I'm still investigating; even with previous TclTk versions results don't change.

Can you do some tests with TclTk 8.6 on different platforms ?


beware I haven't tested,but could the mousewheelbe doing some scrolling on the canvas? try drawing a few items first.

ABU Yes, I tried with two demos included in zoom-canvas; The first demo works ok just because canvas is packed at the (0,0) of the toplevel. The second demo does not work (On Mac) because the canvas is not packed at the (0,0) of the toplevel.

Note that on Windows everythink is OK; on Mac the 2nd demo goes wrong. (I don't know on Linux ... )

The simple code I pasted above is the simplest case able to highlight this wrong behaviour.

ABU 2-apr-2013 -- Opened a BUG at [L5 ]