Version 758 of Ask, and it shall be given # 2

Updated 2007-05-06 09:22:14 by colin

If you have a question, please post it on the latest version of Ask, and it shall be given.: Ask, and it shall be given # 6.


Welcome to Ask, and it shall be given # 2

  • Starting on: 4 December 2004
  • Ending on: 17 April 2005

A few pointers

When asking your question, please put the date along with your name.

Once your question has been answered, please cut it to the appropriate page on the Wiki so that all questions will be regrouped by subject-matter. If you cannot find a page, please create a new one.

If a question has been on this page for a long time and it has not been given an appropriate or a complete answer, please cut it to Unanswered Ask Questions.

Thanks!


MK I am using a button which when invoked adds image inside itself with text . The size of the button increases. How can I fix this size ??

Peter Newman 17 April 2005: Paved Widgets allows you to tile an image behind the text of an otherwise standard Tk button (so the button size is fixed by the text size). Maybe Tile has something similar. Otherwise, make your own button with eg a canvas or label - and add <Enter>, <Leave> and <ButtonPress-1> etc, bindings, to give it the button-like behaviour you want. And possibly enclosed in a frame, to provide the 3D border (and avoid the canvas feature/bug that it's border intrudes on the content).

MG You can also set an initial size for the button with something like this:

  set myImage [image create photo -file foobar.gif]
  set blank [image create photo]
  button .b -image $blank -text "Click me" -height [image height $myImage] \
            -width [image width $myImage] -compound center -command [list .b config -image $myImage]

When clicked, the image should appear behind the text, but the button won't resize. Or at least that's the plan.


LV In debugging, I often need to figure out from where a proc was called. Certainly I could go through all the procs in a program and add code that output something. But that is time consuming and adds a lot of output that I'd rather not have to dig through. When there's an error, I see sort of a stack trace; is this info something that I can programatically invoke?

Lars H: Yes, at least partially. Using info level you can determine what procedure calls were made. You probably cannot get the "... at line XX of ..." parts though, as that information is added to the stack trace when returning with an error. Another option could be to use a trace that, rather than just dumping everything in a list or to a file, pushes and pops data onto and off its own emulation of the call stack. Then you could inspect that in the places you find interesting.

RS: See also "stack trace" in the Bag of algorithms.


LV on comp.lang.tcl , Ethan Blanton and William Poser, in the thread titled "combining diacritics fail to combine in Tk", report that attempts to display text containing Unicode non-spacing diacritics and text are failing. Instead of being displayed as a single character, they are displaying as multiples. Anyone know how to deal with that?


SH I am using Iwidgets::combobox. I have inserted items in the list using the "insert" command. Now my combobox entries present in list changes. Now I will have to remove entries and then insert new entries. Is there any way such that I can associate entries with a variable. When the variable gets updated , values in the combobox list also gets updated ??? In case of listbox widget there is a option -listvariable, but for Iwidgets::combobox there is no such option.. Is there any better way of doing this which can enable me not to interact with the widget but with the variable ???

MG I'm not familiar with the Iwidgets::combobox, but if there is no "native" way to do it, you could set up a trace on your variable, and fire a proc to update the combobox whenever the var changes.


MK How can I capture Key events or mouse events for testing my application. Suppose I have a entry widget , and on pressing Return a procedure is invoked. How can I perform this operation without manually pressing return ??? Similarly for mouse events , how can I move mouse , press mouse buttons etc (not doing anything manually) ??

Peter Newman 14 April 2005: There's the event generate command. Also it's -warp option allows you to move the mouse. If you're on Windows (95+), there's c:/Windows/recorder.exe, which "...is an application that you can use to create macros. Macros are useful if you perform a series of keystrokes or mouse actions frequently. By using Recorder, you can record your keystrokes and mouse actions, and then play them back later by just pressing a key.". And there are may similar propgrams on the Net. See also Techniques for 'driving' Windows applications.


MK How can I make a Tk widget button very small size less than 1 ??

 button .a -width 1

Now I cannot reduce the size of this button. - RS: See the Bag of Tk algorithms, scroll down to "Minimal buttons". The idea is to create a tiny photo of 1 pixel size, and put that as content of the button.

Peter Newman Another approach is to just use a frame - and bind <1> to the button handler. That's essentially all a button is anyway - with a few extras like switching the relief to sunken when the mouse button is pressed, etc.


MG April 7th 2005 - This isn't a problem, just something I'm curious about. If I fire up a wish console (Tcl/Tk 8.4.9 on Win XP), and type in

  info body parray

it gives me the error "parray" isn't a procedure. If I then do a parray then (just with no args works fine), and then repeat the info body parray, it shows up fine. Is it that "parray" is loading through "unknown", or something like that? RS: info body seems not to try to autoload procedures - only unknown does that. The error message comes for anything not known:

 % info body notaproc
 "notaproc" isn't a procedure

Vince: you can use [auto_load parray] if you want to force the procedure to exist. (This command will return 1 if it succeeded in finding the given proc).


MH 06 April 2005 Hi, I have been usin jacl for a while now and I've got a new requirement and I cant for the life of me, no matter how many web sites I've checked, figure out how to run a ksh shell script from within a jacl script and be able to see the output and enter input to/from the shell script. For example: content of mel.jacl could be:

    exec /tmp/mel.sh a b c

content of /tmp/mel.sh could be:

    /usr/bin/ksh
    echo "$1 $2 $3"
    echo "Enter Name: \c"
    read user_name

The exec works but there is not output to the screen.

What do I need to do?

RS: The stdout of the execed command is its return value. Try just

    puts [exec /tmp/mel.sh a b c]

MH yes that works but the shell script needs to be interactive, it displays some stuff to the screen, asks for input and then does some processing. RS: Hm, then try (untested):

 exec /tmp/mel.sh a b c <@stdin >@stdout

MH Nope, no output to screen, doesnt complete script, assume its hanging. LV Okay, what platform are you on? Because on windows, there are peculiar requirements for setting up to get to stdin, stdout, and stderr .

Can you try something like

 exec ksh -i /tmp/mel.sh a b c 

MHplatform=sun solaris - no still hangs

LV I am not certain what might be going on then. Have you tried writing the Jacl mailing list?

RJ If you have Expect, spawn the command, then interact:

   #!/usr/local/bin/expect --
   spawn -noecho /tmp/mel.sh a b c
   interact

MK Is there any good tool which can help to determine code coverage and memory consumption in Tcl application. ??

LV I don't know about tool, but in tcllib there is a module called profiler, and there's some kind of memory debugging compile time option in tcl. TclX has profile and profrep. memory leak finding with memory trace memory introspection measuring memory usage

Anyone else have some Wiki or other URL references on this topic?


MK We can save canvas information to a file in Postscript Format. Is there any way to read this file and show the information in the canvas ??? RS: In a way yes, but it requires the Img extension and Ghostscript installed. Then you can render Postscript into a photo image, which can of course be put on a canvas. See Postscript for details.


ABU 2005/03/31

? Listbox: Is there an event raised when a listbox has no selected items ?

Here is a simple scenario:

I have a listbox and a button The button should be enabled when a selected element exists, and it should be disabled when no element is selected.

In order to enable the button, I can intercept the <<ListboxSelect>> event, but, I cannot find a similar event for the other case (when the listbox has no element selected).

Can anybody suggest me a tecnique for catching this 'event', so that I can properly enable/disable the button ?

Peter Newman 31 March 2005: As I read the listbox manpage, <<ListBoxSelect>> is generated when the selection changes. So all you have to do is bind to <<ListBoxSelect>> - and then check if something is selected now or not. Also, the treectrl and tablelist (and the BWidget ListBox too, I think,) handle selection changes differently than the standard listbox (and every one different from the other). And I'm pretty certain, that with the treectrl at least (especially the latest (Feb 2005, I think,) version), you can do what you want.

ABU Sorry, but it doesn not work ! <<ListboxSelect>> is generated when a new element is selected, but when the listbox looses its selection (or maybe its last element is deleted), no event is generated. Below you can find a simple scenario I used for testing .... I cannot find a way to *disable* the button ...

 proc mylistbox {w} {
  listbox $w.lb1
  pack $w.lb1

  $w.lb1 insert 0 aa bb cc dd

  button $w.b1 -text "apply on selected element" -state disabled
  pack $w.b1

  bind $w.lb1 <<ListboxSelect>> [list $w.b1 configure -state normal]
 }

 toplevel .wa
 toplevel .wb

 mylistbox .wa
 mylistbox .wb

To be honest I am interested with the Tablelist widget, but I think that listbox could be a simpler starting point.

Peter Newman 31 March 2005: Strange about the listbox; the manpage clearly states when the selection changes. My main app. is focused around one main single column listbox. But to get it to work right, I've had to experiment with the standard listbox, the BWidget Listbox, tablelist and treectrl. They're all implemented, and you can menu select between them. But the treectrl is far and away the most powerful. Check out it's <Selection> event:-

 <Selection>
        Generated whenever the selection changes. This event gives information about how the selection changed. 
        %c   Same as the selection count widget command 
        %D   List of newly-deselected item ids 
        %S   List of newly-selected item id

Clearly, that will do what you want. (I use the <Selection> event in my own code. And it fires for both selections and de-selections.) It basically blows the others away in every other respect too. I agree that the standard Tk listbox should be the simplest to use. But the fact is it's so gutless, that this is only true for very simple applications. treectrl is a nightmare to learn though. So if that selection thing is all you're concerned about, I'd check out the BWidget ListBox and tablelist first.

Just checked it out in my app. And treectrl is to be the only one that fires on both selection and de-selection. But in my test, I can't get the listbox to fire even on selection. Something's not right. Monitoring selection and de-selection is important to my app. - and I'm sure they all do it. I think we're both missing something.

ABU As far as I read from your notes, Treectrl seems to deal the de-selection perfectly; unfortunatelly, treectrl is not a pure-tcl widget, so I cannot investigate further ... About your listbox bindings experiment, check if you wrote <<ListboxSelect>> or <<ListBoxSelect>> (wrong). As I said before, I'm interested with Tablelist, and since it is built upon listbox widget, I though it was simpler to investigate.

Peter Newman I re-wrote your test code to try and figure this out...

 pack [listbox .myListbox]
 button .b1 -text addElement    -command addElement
 button .b2 -text deleteElement -command deleteElement
 button .b3 -text selectFirst   -command selectFirst
 button .b4 -text selectAll     -command selectAll
 button .b5 -text selectNone    -command selectNone
 pack .b1 .b2  .b3  .b4  .b5 -side left
 set elementNumber 1
 proc addElement { } {
        global elementNumber
        .myListbox insert end Element#${elementNumber}
        incr elementNumber
        }
 proc deleteElement { } {
        .myListbox delete 0
        }
 proc selectFirst { } {
        .myListbox selection set 0
        }
 proc selectAll { } {
        .myListbox selection set 0 end
        }
 proc selectNone { } {
        .myListbox selection clear 0 end
        }
 pack [button .myButton                                 \
        -text           "apply on selected element"     \
        -state          disabled                        \
        -command        bell                            \
        ]
 bind .myListbox <<ListboxSelect>> ListboxSelectHandler
 proc ListboxSelectHandler  { } {
    set listOfCurrentlySelectedElements [.myListbox curselection]
    set elementCount [llength $listOfCurrentlySelectedElements]
    puts "${elementCount} Currently Selected Elements: ${listOfCurrentlySelectedElements}"
    if { $elementCount == 0 } {
        puts {Disabling the button...}
        .myButton configure -state disabled
    } else {
        puts {Enabling the button...}
        .myButton configure -state normal
           }
    }

Running the above shows that - contrary to what the manpage says - <<ListboxSelect>> DOESN'T fire in response to selection changes at all (neither selections nor de-selections trigger it). But it does fire in response to a LEFT MOUSE CLICK??? This makes no sense to me at all. Has the listbox always behaved this way? Or is it a bug introduced with recent versions of Tcl? Might pay to check the listbox bindings. Possibly, by fiddling with them, you can get it to behave the way it should.

ABU Peter, I've repeated your experiment on my PC (WinXP, Tcl 8.4.3) and I can confirm that the <<ListboxSelect>> behavior is not what we expected.

I don't know if it is a new bug; I'm not aware of a "good" app providing the behavior I wanted ...

Now I'm investigating with Tablelist internal code; it seems to me that it handles correctly the case when the widget loose the selection (I've found a proc named tablelist::lostSelection), but I'm not sure of all the required preconditions and side-effects ...

NOTE: I must correct my myself: Tablelist does not use listbox internally; it uses a text-widget.

It seems to me that Tablelist is using some sophisticated (?) tecniques with the 'selection' command. Unfortunatelly this is quite obscure to me now . I'll keep you informed on future results.

Any help is appreciated.

Peter Newman Aha, it becomes clearer! It seems that <<ListboxSelect>> ISN'T generated in response to selection changes made by the PROGRAM - only in response to selection changes made by the USER. Then it fires for both selections and de-selections, as you want it to.

The user can select and de-select things:-

  • In -selectmode multiple - by clicking the left mouse button, and;
  • In -selectmode extended - by holding down Ctrl whilst clicking the left mouse button.

The following updated code demonstrates this...

 global selectMode ; set selectMode browse
 pack [listbox .myListbox -selectmode $selectMode]
 pack [frame .row1]
 radiobutton .row1.sm1 -text browse   -variable selectMode -value browse   \
        -command {.myListbox configure -selectmode $selectMode}
 radiobutton .row1.sm2 -text multiple -variable selectMode -value multiple \
        -command {.myListbox configure -selectmode $selectMode}
 radiobutton .row1.sm3 -text extended -variable selectMode -value extended \
        -command {.myListbox configure -selectmode $selectMode}
 pack .row1.sm1 .row1.sm2 .row1.sm3 -side left
 pack [frame .row2]
 button .row2.b1 -text addElement    -command addElement
 button .row2.b2 -text deleteElement -command deleteElement
 button .row2.b3 -text selectFirst   -command selectFirst
 button .row2.b4 -text selectAll     -command selectAll
 button .row2.b5 -text selectNone    -command selectNone
 pack .row2.b1 .row2.b2 .row2.b3 .row2.b4 .row2.b5 -side left
 set elementNumber 1
 proc addElement { } {
        global elementNumber
        .myListbox insert end Element#${elementNumber}
        incr elementNumber
        }
 proc deleteElement { } { .myListbox delete 0 }
 proc selectFirst   { } { .myListbox selection set 0 }
 proc selectAll     { } { .myListbox selection set 0 end }
 proc selectNone    { } { .myListbox selection clear 0 end }
 pack [button .myButton                                 \
        -text           "apply on selected element"     \
        -state          disabled                        \
        -command        bell                            \
        ]
 bind .myListbox <<ListboxSelect>> ListboxSelectHandler
 proc ListboxSelectHandler  { } {
    set listOfCurrentlySelectedElements [.myListbox curselection]
    set elementCount [llength $listOfCurrentlySelectedElements]
    puts "${elementCount} Currently Selected Elements: ${listOfCurrentlySelectedElements}"
    if { $elementCount == 0 } {
        puts {Disabling the button...}
        .myButton configure -state disabled
    } else {
        puts {Enabling the button...}
        .myButton configure -state normal
           }
    }

So all you have to do is update the button's state manually, when selecting, de-selecting, inserting and deleting listbox items from the program. And provide a <<ListboxSelect>> handler to deal with changes made by the user.

ABU 4-apr-2005 Sorry, but catching <<ListboxSelect>> is not enough ...

Here is a simple way to test ...

  • Add an entry-widget to the last example:

entry .e ; pack .e

  • add some rows to the listbox, then select a row ..
  • click within the entry-widget ..
  • write some text and SELECT IT
  • now you can see that the selected row within the listbox has disappeared, but no <<ListboxSelect>> has been generated !

I developed a more general solution (hint: the "selection own" command) ; currently it is under testing. I hope to be able to publish it before tomorrow.

ABU 5-apr-2005

You can find my solution at: How to totally handle listbox selection.

Feel free to add suggestions.


NickM 2005/03/28 I need to call a simple TCL (8.4.9) script from within a Windows XP DLL environment (no tclsh or console init). The script will make use of some custom TCL command extentions. Tip#66 starts to talk about the all the system initialization that occurs before you can make the first call to something like Tcl_FindExecutable("bla"); Is there a single simple initialization call I can make like to tclWinInit.c, that takes care of this initialization, except outside of a console environment? Interestingly, I have been able to make some progress creating an interp using a dynamic TCL build with USE_TLC_STUBS not set. With a static build, you can't call Tcl_bla out of the chute because the stubs table needs to be inited. There's got to be some secret sauce. Thanks.


MK I want to show progress bar of a process. Which widget to use and how to use such that the bar automatically updates itself according to the time taken by a process. (Time taken by a process may differ at different time). The progress bar should also be destroyed at the time a process ends.

Peter Newman 29 March 2005: 1) Just search for progress on this Wiki, and you'll get a whole heap of progress bars. 2) I assume that you mean that you want to launch an external process with (say) exec - and have the launching process display a progress bar that indicates (say) the percent completed of whatever it is that the launched process is doing. The general problem with this is; How does the launching process know how much the launched process has done?. If this is correct, the solution will depend on what the launching and launched processes are - and what possibilities the launching process has for monitoring the launched process? It would help if you tell us what the launching and launched processes are. - RS Hint: a quick search URL is http://mini.net/tcl/2?progress - just add your search term after the "2?" part.


Erik Purins 2005/03/23

I need to just install part of tcllib, but tcllib's installer.tcl wants to install and make docs for them all. Can this be changed to treat the args to installer.tcl (after the options) as a list of packages to install? Is there already a mechanism for this that I missed?

So instead of 'tclsh installer.tcl -dry-run' and an install of all the scripts and docs, I can 'tclsh installer.tcl -dry-run cmdline' and just install 1 or more of them.


tk newbie 2005/03/19

When i run a tcl-tk script xterm window opens along with my widget. How to avoid this....

Peter Newman 21 March 2005: If you run the script with tclsh, that won't happen. But if you run the script with wish, it will - because wish automatically opens an (empty) toplevel window called . when it starts.

Normally, a Tk script will fill the toplevel with widgets, so this is no problem. But you can get rid of the toplevel with either:-

 wm iconify .   # Hides the window, though it still appears on the taskbar.
 --OR--
 wm withdraw .  # Hides it totally.

Use wm deiconify . to restore the window. The above behaviour is what is seen on Windows; it might be a little different on Linux. Hope that helps.


Meir March 18, 2005 As a newbie to Apache and Tcl I'd appreciate if this simple question can be answered for me.

I run a local WIN2K box. Got tcl 8.4 loaded and working. Loaded Apache 2.0. It runs on startup. (I nixed IIS) My browser is Firefox. I note that it has the tcl plugin.

Question: How do I get Apache to run a script? Just putting the URL to point to the script seems NOT to work; It seems Tcl isn't interpreting the script commands.

Thank you - I hope I asked my question correctly. It seems to be an imposing way to ask a question, editing and all.

LV Sorry, I can't imagine a much easier way to ask a question than to type it in a window. However, check the Apache and Rivet pages here on this site for more help. Also, check out tkchat for information about IRC chatrooms (or the chatroom on this site) where you can ask people questions in real-time.

ECS 2005-03-18 -- I am not sure if I understood correctly, but I think you want to download a TCL script to be executed by TCL plugin in Firefox. Two things: you need to configure apache to return tcl scripts as 'application/x-tcl'. And have Firefox configured to associate this MIME type with the plug-in.

Another interpretation is that you want a CGI written in TCL.

Sorry if I misunderstood your question.

Meir March 20, 2005 I want to develop web programs using Tcl on my local WIN2K box; By repeatedly testing them with my local browser.

I know my Firefox browser has a plugin enabling the Tcl extension.

Now Apache seems to be my main obstacle for progress. Seems I need to know a whole lot about how to configure it.

May I make this request of you just so I can get going? Can you just spell out for me how I can run a file residing in D:\myServer ; How do I actually tell Apache that this is my "virtual directory"? That is, in what section of httpd.conf do I say what. Do I need to say, AddType application/x-tcl .TCL or do I need an Action/Application statement too?

If I can just get the browser to run a simple (albeit sloppy) Tcl file, such as puts "Content-Type: text/html" puts "<Title>Current Time</Title>" puts "The time is <b>[clock format [clock seconds]</b>"

I'd be grateful to hear from you. Thanks so much.

Peter Newman 21 March 2005: I could well be wrong, but AFAIK there is NO Tcl plugin for Firefox under Windows. Under Linux, and as far as I can tell from the Web, it seems to be possible. But under Windows??? (This doesn't mean to say you couldn't compile it, and get it to run under Windows. But I can't find any such package on the Web.)

Are you absolutely sure you have a working version of that package. And if so, where did you get if from? (I ask that question because I've been unable to find a precompiled copy of the Tcl plugin, that works in the LATEST browsers, under Windows.) Meir I wish you'd've responded to my heartfelt request, Peter. In answer to your question; The 1st Google search for "tcl plugin windows" yields result #1: http://www.demailly.com/tcl/plugin/download.html It's called nptcl30.dll and resides in C:\Documents and Settings\Administrator\Application Data\Mozilla\Plugins

Could someone please refer to my previous request and help me out.

Peter Newman 22 March 2005: I know nothing of Apache, so I can't help you there. But you don't need Apache to test the plugin. There are pages on the Web that use the plugin, eg; [L1 ] - so going there will let you know whether or not the plug-in's installed properly (or whether it's Apache that's the problem).

I've installed the version you pointed me too, but FROM MEMORY: 1) It's for VERY old browsers, eg; Netscape BEFORE Mozilla and IE 3/4/5 (not sure which one(s)). (In other words, it's for browsers that you'd be lucky if even 1% of Web users still have - so running a site that uses it is virtually pointless). And: 2) I found it either (very) flaky - or it just wouldn't install and run on the latest browsers. A few months ago I tried installing it on Win98SE and/or XP - under Firefox and/or IE6. But oh dear!!!

In other words, it's a great idea, but it's dead; Tcl PlugIn, RIP.

But check out the site above, and any others you can find. That at least will tell whether or not and how well the plug-in works.

If you find that the plugin works OK, but you're still having problems with Apache, then you might want to consider switching to TclHttpd as your Web Server - at least until you get the plugin running properly. I'm sure you'll find a LOT more Tcl'ers with experience of that who can help you, than with Apache.

TclHttpd is also MUCH easier to use than Apache. It works practically straight out of the box - though you do need the external documentation to help you get started. I've tried installing Apache twice. It installs OK. But getting it to do stuff is just too complicated. If you're running a Web Server maybe. But on a desktop, it's just not worth the time & effort. I've got a copy of TclHttpd installed on this desktop, so maybe can help you with TclHttpd, if you're still having problems.

Meir Thanks Peter. I'll give TclHttpd a try.


KB 14-03-05. TCLCurl seems to be written for POST docs, I need to simply listen to a given TCP port and respond with a HTTP 200 OK when documents received. Docs will be pushed at me instead of pulling them. Is TCLCurl a good lib for this? Is there something else that would provide better performance for this?

Peter Newman 15 March 2005: http is the standard Tcl package for HTTP. It's simpler than TclCurl - though it doesn't support all the bells and whistles that TclCurl does. I'd try http first.


MK Consider an example : bind $topLevel <Return> {puts "toplevel window"} bind $toplevel.button <Return> {puts "button inside a toplevel window"}

if focus is on the button, then both the scripts get executed. I want that only the script associated with the button should be executed. How will this be done ???

aricb:

 bind $toplevel.button <Return> {puts "button inside a toplevel window"; break}

MK Thanks


rdt asks how would you implement a text widget with some "fixed uneditable" parts and some parts that are editable? Like a Form to be filled out?

rdt How about creating a text widget, placing entry boxes for each editable part, then seting the text widget read-only?

Peter Newman 13 March 2005: Your suggested solution sounds OK to me. But check out Wcb; it has solutions for this too.

DKF: Works very well. Remember to add bindings for <Up>, <Down> and <Return> too.

rdt Yeah, but with my idea, how do you get a multiline entry widget? Looks like a combination of read-only and normal text widgets!

aricb: Is gridplus an option for you, or is that totally not what you're looking for?

Peter Newman 13 March 2005: For multi-line entry widgets, see LabelText -A Multi Line Entry Widget and Multiline expanding entry widget. I also wrote one which I think is probably better than both of those, because it also fixes the Tab and Shift+Tab keys so that they work exactly like they do for the entry' and other widgets (move you from field to field in a data entry form). The text widget uses Tab and Shift+Tab for 8-space text editor/word processor tabbing. Though if you check out the bindings on the text widget manpage, you'll see that it's not too difficult to restore the entry' widget like behaviour. Though I found I also needed Wcb, to do the job properly. See Multi-Line Text Entry Widget - With Entry Widget Like Field To Field Tabbing.

MG You could also overload the text widget's standard bindings for all the keys which edit to check to see if the text you're editing is locked (like add a disabled tag around it). Then, for insertion, check to see if the characters either side of the insertion cursor have the tag, and for deletion/modification, check to see if any of the characters in the selection range (or the single character next to the insertion cursor, for deletion) has the tag. That might be more difficult than the suggestions above, though - especially since the bindings change over different versions of Tk...


Is it possible to recursively walk a keyed list. If so, any algorithm?

Peter Newman 9 March 2005: Yes it's possible. Can you give an example of the keyed list you want to walk - and explain what you mean by walking it.


MRS 2005-03-03

It is safe to do a

 source [file join .. somefile.tcl]

or is better always to do

 source [file join [file dirname [info script]] .. somefile.tcl]

???

MG It depends on where you're doing it. ".." is relative to the current directory - so, if you use cd, it'll work differently. Running a Tcl script in wish from ActiveTcl 8.4.9.0, I find that (after the app has started), [info script] returns nothing, but [pwd] (without changing directory manually first) is the dir my script is in, as is [file dirname $argv0].

So, basically, it depends on when and where you're using it, and whether somefile.tcl is relative to your current working directory, or to the directory your original script was in at the time it was run.


MRS 2005-03-03

What are the effects of a

 package require

???

My question is because, as I understand, The difference between a package require and a source is that with source one needs to inform the path where to find the script and with package require Tcl will look in the library dirs.

If there is only this difference, why I see in many scripts both lines like this:

 source somepackage.tcl
 package require somepackage

???

MG The main difference is that [package require $package] is intended for loading libraries of code - commonly used functions which are shared among a lot of applications. The code for these, whether it's pure-Tcl or compiled extensions, is stored in a place which is not relevant to any particular program (but is relevant to Tcl itself), so that any program using Tcl can access it, without knowing where it's stored (or can check if it's available, even), with a simple [package require $packageName].

source, on the other hand, is more useful (when used inside a program) for loading code used only by / packaged with that particular program. Then you can, for instance,

  source [file join . lib moduleX.tcl]

to load a particular piece of code that your program needs to use, without making it "publically" available to other apps. (Of course, they could always source [file join $pathToLibFolder moduleX.tcl], but they'd have to know exactly where to find it.)

Hope that helps a little :)


And is this concept of widgets also established for other languages or is it just a concept available only in TCL? - RS: Just see widget. This term was introduced in X - in the MS Windows world they call it "form".

LV Robert, if a language supports GUI development, then they will have some kind of terminology for those entities which can be combined together to create an application. Many languages use the term widgets for that class of objects.


I am using iwidget::scrolledframe. Inside it I am adding a frame which contains a canvas. Now on adding a frame , I want that vertical scrollbar should automatically move to show me that frame. This frame can be added anywhere in the scrolledframe. So every time I add a frame , I want that it should be visible. Is it possible ??

Help me out.

Thanks Manish Khanna [email protected]

MG Can you show us the code you have so far, for creating the scrolledframe and for creating and packing a frame inside it? That'd be helpful...

MK The code looks like this :

    set topLevel [toplevel .timingpage]
    wm protocol $topLevel WM_DELETE_WINDOW
    wm title $topLevel "Timing"
    wm resizable $topLevel no no

    iwidgets::labeledframe $Timing.cd  -labeltext "Clock Domains" -labelpos nw
    set clockdomains [$Timing.cd childsite]
    grid $Timing.cd -row 1 -column 0 -ipadx 5 -ipady 5 -sticky nsew
    set ClkDomain(ScrolledFrame) [iwidgets::scrolledframe $clockdomains.sf -vscrollmode dynamic \
                                                             -hscrollmode dynamic \
                                                             -width 500 \
                                                             -height 200 \
                                                             -highlightcolor black \
                                                             -highlightthickness 1]
    pack $ClkDomain(ScrolledFrame) -expand yes -fill both
    set ClkDomain(sfchildsite) [$clockdomains.sf childsite]
    .
    .
    .
    AddDomain 

# This proc is called by a button in GUI which adds a frame containing a canvas inside a scrolledframe . The frame can be placed in different order inside scrolledframe depending on variable "i" used. I want that scrollbar should move accordingly such that this frame which i have currently added becomes completely visible.

#I have written down the idea how am I using it .

proc AddDomain {} {

   set Domainframe [frame $ClkDomain(sfchildsite).domain$i -bd 1 \
                                        -height 80 \
                                        -width 200 \
                                        -takefocus 0 ]
   grid $Domainframe -row $i -column 0 -sticky nw

   set Clock(canvas) [canvas $Domainframe.clock -width 500 \
                                                      -height 50 \
                                                      -bg black  \
                                                      -takefocus 0 \
                                                      -cursor hand2]
   grid $Clock(canvas)

}

MG has looked over your code and the manpages for the scrollframe/grid, and is afraid he isn't sure quite how to do it...

Peter Newman 23 February 2005: Looks to me like you'd be struggling with the iwidgets ScrolledFrame. But with the BWidget ScrollableFrame, it looks to me like a piece of cake. Check out the see command.

In my experience, putting multiple widgets inside a single Scrollbar Manager widget leads to VERY sluggish performance. Could you not use just the one canvas - and divide it into imaginary rows. I'm sure that would scroll much faster - and you can use xview to show the content you've just added.

MK thanks for your advice . I have solved the problem. I have done event <Map> binding on the frame which I am adding. The procedure called will calculate fraction where the frame lies in scrolledFrame and I have adjusted the view usin yview command.


I have got two query : 1) How to allow expansion of a toplevel window in only one direction (either x or y) ?? 2) When a mousecursor is inside canvas , Scrolling occurs inside the canvas using scroll button. How can we stop this scrolling??

Manish [email protected]

MG To answer your first question, try wm resizable

  wm resizable . 1 0;# only resize along x
  wm resizable . 0 1;# only resize along y

MK This does not solves the problem . wm resizable is useful when you are compressing a toplevel. But in case of expansion it allows expansion in both direction .

Peter Newman 23 February 2005: If you look at the bind manpage, you'll see that Tk, under Windows, supports the MouseWheel event. On the assumption that the scroll button you mention is a Windows Mouse Wheel, then presumably either canvas, and/or one of the iwidgets you're using, is supporting the MouseWheel event. And you'll have to use either bind and/or bindtags to disable it. MK Thanks for the advice . I think it will solve the problem


I have query regarding Drag and Drop between Tk and motif based application. Drop is supported from Motif Application to Tk, but is Drag supported from Tk to motif based application ? If Yes , then how ?? Qt allows drag and drop to motif both ways. Both Qt and Tk are based on XDnd protocol. But drag from Tk to motif is not working. Please find out how it will work.

Awaiting for your Response Mukundan [email protected]


ANSWERED QUESTIONS (thanks to all!)

I use iwidget::combobox in my code and insert a list of elements to it. I don't have this list anywhere except in the combobox now. Now from somewhere I get a variable which can have one of these values. I want the combobox to show this value. What is the way to do it? Is there a method which can return me a list of all the items? Or, is there a method which takes the value of this variable and makes the combobox show it?

 Any help would be great!!

Thanks, Saumitra ([email protected])

MG Try something like this...

  # create a combobox to start, and populate the list
  pack [::iwidgets::combobox .cb]
  .cb insert list end Jan Feb Mar Apr May Jun Jul Aug Sept Oct Nov Dec

  # and now check for a value...
  set search "Aug"
  set which -1
  for {set i 0} {$i < [$widget size]} {incr i} {
       if { [.cb get $i] == $search } {
            set which $i
            break;
          }
      }
  if { $which == "-1" } {
       # Not there, so add it
       .cb insert list end $search
       incr i
       puts "Value added at position $i"
     } else {
       # was found in list
       puts "Value already present at position $i"
     }

SG Thanks MG. Your suggestion works. I was expecting it to be having a direct method to get the index of an item? Thanks anyways!!

MG No problem. The combobox does has an index method, but when I fiddled briefly earlier this morning I couldn't get it to work as expected - I think it's for the entry part of the widget, rather than the list part. Whether there is a way to do it 'properly' or not, I'm not sure.


2005/02/18 skm I am trying to kluge a pkgIndex.tcl file to source some files that will eventually go into a real package. Right now I have a pkgIndex.tcl kluge in place, but it's too simpleminded for my taste. It sources another index file I created which assumes the directory location. I'd rather use $dir. I tried forming a fooScript variable containing a foreach command that looped over filenames with source [file join $dir $filename]. For some reason, $dir is not recognized. Why does it get recognized outside of the foreach loop? I tried some other experiments, and invoking it as ::dir does not work, nor does setting a temporary foodir variable to it and trying to access $foodir or $::foodir work.

LV Can you provide us example code showing your problem? It's always easier to help debug problems that way.

skm small example. Create c:/home/pkg. Touch t1.tcl, t2.tcl, t3.tcl. Put package provide pkgtest 0.0.1 in t1.tcl. Create pkgIndex.tcl:

 set ifneededScript [list foreach fname [list t1.tcl t2.tcl t3.tcl]\
                        [list source [file join $dir $fname]]]
 package ifneeded pkgtest 0.0.1 $ifneededScript

Launch shell.

 % lappend auto_path [file join c:/ home]
 C:/Tcl/lib/tcl8.4 C:/Tcl/lib C:/Tcl/lib/tcllib1.6 C:/Tcl/lib/tklib0.2 c:/home
 % package require pkgtest
 error reading package index file c:/home/pkg/pkgIndex.tcl: can't read "fname": no such variable
 can't find package pkgtest
 % 

This is one of the variations I played with. Btw, I know that I'm polluting the global namespace here. In the actual code the variables are all namespace variables.

Peter Newman 19 February 2005: Looks like quoting hell to me. Wouldn't the file join $dir $fname be executed when set ifneededScript xxx is interpreted (rather than when the resulting script is eval'd, as I think you intend). Escaping (putting a backslash before,) the opening square bracket that precedes file might fix things (though I haven't tested it).

skm The reason I did quoting hell was that I wanted fname to undergo a round of substitution. It would not if I used {}, unless I'm mistaken (which isn't rare). Looks like you are right about fixing quoting hell; and I'll report back if I don't successfully figure it out.

MG It might be easier if you just added a "package.tcl" file, which sourced all those files. Something like: pkgIndex.tcl:

  package ifneeded pkgtest 0.0.1 [list source [file join $dir package.tcl]]

package.tcl:

  foreach x [glob -dir . t*.tcl] {
           source $x
          }
  package provide pkgtest 0.0.1

skm MG, the reason I did not want to follow that approach is that [glob] is going to return files from the current directory, not the directory containing the package.

MG My apologies, you're quite right. You need to use -dir [file dirname [info script]]] instead of -dir . to get the right directory.


MG - Jan 31st 2005 - Does anyone know if it's possible, with the standard Tcl socket code, to implement RFC 1091 [L2 ] ? I'm hoping to have a Telnet-type application in Tcl/Tk identify itself, but have absolutely no idea how it might be possible...

RA2 Stuart! This one is for you!

Mike MG has been so kind and helpful to all that is really super-sad that his question goes unanswered... :-(

Peter Newman 19 February 2005: I had a look at RFC 1091 when MG first raised the question. And couldn't see any problem with doing that with socket; looks like standard ASCII I/O to me. But I kept my trap shut because I rarely use socket - and never Telnet - and I couldn't understand why MG was even asking the question. Thought I'd leave it to someone who could see the potential problem(s) that MG presumably sees.

RA2 Hi Peter! Nice to see you again! :-) Well, I say "see you", sort of... :-) So how would you do it using standard ASCII I/O?

MG 18 Feb 2005 (apparantly a time-zone or two behind Peter Newman:) - Chances are that it's just me being clueless, and doing something really stupid. The RFC docs have always confused the hell out of me anyway, and on top of that I don't really know a whole lot about the Telnet protocols (and get lost even more reading those to figure it out:). I have some code that I tried shortly after I posted the question, integrated into Potato MUSH (MUD) Client (which is where I'm trying to do this). The problem is that the program hangs after receiving a few lines of data (trying to connect to telnet://mush.elendor.net:1892). Here's the code I have...

 # socket already opened in async mode, and checked to be properly connected
 fconfigure $id -buffering line -blocking 1 -translation binary
  set startString [read $id 3]
  if { $startString == [format "%c%c%c" 255 253 34] } {
       puts $id [format "%c%c%c" 255 252 34]
     }
  fconfigure $id -blocking 0

And then it sets up a fileevent to read the data and output it in a text widget. It's probably trying to vastly oversimplify it. If anyone can tell me a little more specifically what I'm doing wrong, though, I'd appreciate it.

Peter Newman 19 February 2005: I could be wrong, but I suspect that your fconfigure also needs:-

 -encoding binary
 -eofchar {}

See Help! My Tcl application just hung!.

MG Thanks Peter, I'll give that a try.


(18 Feb. 2005)

Today's question is a little more evolved than the previous days: does TCL consider a file being modified when it has been given a title even if there are no contents in that file?

If the answer is yes, then consequently if I ask the program to execute a script if a file has been modified, it will execute the script if the file:

  • is unnamed and has contents.
  • is named and has no contents

In fact since we are talking of an unnamed file, technically this is not a file but merely some text in the edit area....

So this is my code (I converted MG's very useful check_exit code)

  proc ask_to_save_file {} {
   if {![::main_ht modified]} {
      return
   }
  set ans [tk_messageBox -type yesno -icon question -message "The file has not been saved; do you want to save it? "]   
  if { $ans != "no" } {
         save
   }
  }

But unfortunately I am served with an error message. What did I do wrong this time? :-)

LV I don't understand the question. Files don't have titles, as far as Tcl is concerned. I don't know what that ::main_ht does.

MG On the assumption that by "file" you mean a text widget, the command for checking whether it's been modified is

  $textWidget edit modified

According to the text widget's helpfiles for 8.4.9.0, inserting or deleting text, along with undoing/redoing changes will alter the "modified" value. What code were you using to change titles? Assuming it's something like wm title $textWidgetsToplevel "New Title" then it won't affect the text widget's modiifed state.

Robert Abitbol On this one, I really didn't express myself clearly and I apologize.

What I meant is this: when a user enters the editor, he starts typing in text. The text is unsaved until he/she saves it; obviously.

Now what I'm trying to do is to put warnings here and there on the program to warn the user that the text has not been saved and that he/she should save before it going to the next function. I put a warning at "New" (when the user wants to create a new file), at open file, exit, etc. The warning simply tells the user that the text he/she has typed in is not saved.

This is what the code above was supposed to do... I thought ::main_ht modified meant that the edit area had been modified. But apparently it doesn't mean that... :-(

My complex question about the title was this (put in simpler terms): if the user has saved a file with no character (in other words empty), does the program consider that it has been edited since some characters have been put on the title or is it considered a non-edited file since there are no characters in it (even though there is a title).

If you don't understand this last part, please let me know I'll reformulate it differently...

MG Robert, again assuming your editing area is a text widget, I think you want something like this:

  pack [text .t]
  set doc(saved) 0
  set doc(path) {}

  proc save {{as 0}} {
    global doc

    # call as [save 1] for "Save As...", and [save] for a normal save

    if { !$doc(saved) || $as } {
         set path [tk_getSaveFile]
         if { $path == "" } {
              return;# user cancelled
            }
         set doc(path) $path
      }
    set fid [open $doc(path) w+]
    puts $fid [.t get 1.0 end]
    close $fid
    .t edit modified 0
  };# save 

  proc ask_to_save_file {} {
    global doc

    if { [.t edit modified] } {
         set ans [tk_messageBox -message "You have unsaved changes. Save now?" \
                                -type yesno]
         if { $ans == "yes" } {
              save
            }
       }
  };# ask_to_save_file

Robert Abitbol Thanks again Mike! You certainly have a bright future in front of you! This we have in common, despite our difference of age.

I don't want to sound totally stupid (partially is enough!) but how do I know if my editing area is a text widget? :-)

This is what I have now for the save.

proc save {} {

 if {![$::main_ht edit modified] || "" eq $::data_dir || "" eq $::current_node} return
 write \
  [set fd [open [file join $::data_dir $::current_node].txt w]] \
  [$::main_ht get 1.0 end-1c]
 close $fd
 $::main_ht edit modified 0}

#END proc save

And I have a separate module for Save as.

I guess I'd have to modify this save module so that it remains in line with the rest of the code... But how! That's the question!

The important thing I understand is to find a way for the program to know that there has been a character added to the edit area.

MG Well, if the widget you type into is created with the text command, it's a text widget :) From your code, it looks like you have the widget's name stored in $::main_ht - try going to the console and entering 'winfo class $::main_ht', and see if it says Text. But judging from the fact you have $widget edit modified in your code, it looks highly likely it is a text widget - it's the only standard Tk widget that has a subcommand like that, I believe.

Your save command there looks OK (presumably write there is an alias of puts?). (Although just returning silently from your save if data_dir isn't set could cause people a lot of aggro, if they don't realise their file isn't being saved; might be better to show a message box, or ask for a directory with tk_chooseDirectory.) One thing to watch, though, is the removal of the trailing new-line from the text widget (you use end-1char, to strip it); there's a discussion about why that could be bad on the text page.

RA2 Well the first programmer wrote all that. I am perfectly incapable of doing it at that stage.

So, if I keep my "save" procedure the way it is and I use your "ask to save" procedure and I put those three things on the top of the script: pack [text .t] set doc(saved) 0, set doc(path) {}, would it work? Or do I need to modify the "save" procedure?

MG Well, that was a basic but "fully working" example, not really something to be integrated into yours. You don't need those two doc variables, since you have that sorted already, though ::data_dir. You should be able to keep your save proc as it is, and then use something like this to ask if you should save.

  proc ask_to_save_file {} {

    if { [$::main_ht edit modified] } {
         set ans [tk_messageBox -message "You have unsaved changes. Save now?" \
                                -type yesno]
         if { $ans == "yes" } {
              save
            }
       }
  };# ask_to_save_file

Robert Abitbol Great! It works great! Thanks again, Mike!

Now what do I do to ask a second condition for putting this warning sign on: the second condition would be at the condition that there is no file loaded (hence no file name appearing on the path)... That happens when the program starts. The user types in some text and there is no file name since he/she hasn't saved yet.

Thanks again!


SEH -- 1/27/05 -- Is there a way to call the pure Tk tk_chooseDirectory from tkfbox.tcl explicitly on Windows in a manner equivalent to [::tk::dialog::file:: open] for tk_getOpenFile?

MG 18 Feb 2005 - It looks like (in ActiveTcl 8.4.9.0 at least) it's in choosedir.tcl, not tkfbox.tcl, from the same directory ($rootpath/lib/tk8.4). Try [::tk::dialog::file::chooseDir::]


2005/02/10 skm I'd like a WinXP analog to Quicksilver in OSX. It could probably be done in Tcl. Has anyone done this already? Don't want to re-invent the wheel.

Robert Abitbol Hi skm! I have googled the words Win Xp + Quicksilver and this is the URL: http://www.google.com/search?hl=en&ie=ISO-8859-1&q=Windows+XP+Quicksilver

Quicksilver apparently exists in Windows XP (check the first hit; Softpedia). Now is this Win XP version analog to Quicksilver in OSX? That remains to be seen...

skm Hi RA, nope that's not the same thing. I did some preliminary searching before asking the question. Quicksilver is akin to a keyboard app launcher (but also integrates bookmarks, del.icio.us, files, &c., in addition to being scriptable). I'd like to be able to use something similar on my winXP machine. I searched tucows.com and found some keyboard launchers (hotkeys for example) but the performance wasn't up to the performance of Quicksilver. It struck me that a tcl app could do this (and be cross-platform), so I wanted to see if it was already out there.

Robert Abitbol Ah! So you're looking for a keyboard app launcher for Win Xp that would do as good a job as Quicksilver on OSX. So let's google: tcl keyboard app launcher. And if there are no hits, it means it has not been done and you can program it in TCL/TK and strike gold. :-)

So let me try Google with the following keywords: TCL keyboard app launcher.

---> Nada for this query: http://www.google.com/search?hl=en&ie=ISO-8859-1&q=tcl+keyboard+app+launcher

---> We're much luckier with this one: http://www.google.com/search?hl=en&lr=&ie=ISO-8859-1&q=tcl+app+launcher&btnG=Search

And of course we still ask Wikit users if they can recommend a good keyboard app launcher for Win Xp (something as good as Quicksilver for OSX).

Actually the best would be to get in contact with the Quicksilver/OSX gang and ask them if they have done the equivalent for WinXP. If the answer is "no" I am sure they can recommend a product since it is their field of expertise...


Moritz: Which online blogs, news sites or other web resources do you read? I just read Slashdot and every week I read the BOFH column in The Register. Sometimes i also read kuro5hin.


ANSWERED QUESTIONS (a million thanks to all those who take the time and make the effort to answer questions; please move these answered questions on the appropriate page on WikiT)

MSW(2004-02-17) has found the right logfiles and thus no more questions for today.

Robert Abitbol (18 Feb. 2005) I am happy we have another satisfied customer! :-)


MSW(2004-02-17) a proc returns the value of the last statement as its value. Is there a way to access the value of the last statement in a way similar to what proc's doing? (hehe, yeah I know about [], I'm just curious).. like:

 set a 1
 puts [whatever]
 => 1

RS Not in regular Tcl, as fare as I know. tkcon keeps the last result in a global variable named _ or {}, depending on version.

 % set b 2
 2
 % set ""
 2

MG Feb 17 2005 - One way to do this would be with something like..

  proc * {args} {
    upvar 1 lastResult myvar
    set myvar [uplevel 1 $args]
  }

And then prefix any commands you might want the return value from with a *

  Prompt> * tk_messageBox -type yesno -message "Press a button"
  yes
  Prompt> set lastResult
  yes

That would mean adding the * before all the commands you wanted traced, though, which isn't ideal.


To be moved to Message Box

(16 Fev. 2005) Robert Abitbol A quick question: how to put a return in a message box so that the text appears on the next line? What symbol should be used? Thanks!

MSW: what's wrong with "\n" ?

 tk_messageBox -message "Banzai!"
 tk_messageBox -message "\nBanzai!"
 tk_messageBox -message [join [split " Banzai!" {}] "\n"]

Robert Abitbol Nothing wrong with n. All for it. :-) This will give me the return carriage I longed for! Thanks very much, MSW!

MSW says: that sounded so obvious, sorry I forgot we all once started.. Check [L3 ] for the other \<char>'s :)

Robert Abitbol Well on this one I plead guilty for I should have known, since they are the same characters used in C and I used them so often on the code for my translator! Along with the printf...


Question to be moved to Cursors and to Date and Time Issues when answered.

11 Feb. 2005.. I have a time/date stamp on my app. It puts the date/time at the place where the cursor is located. What code should I add so that once the date has been put in, the cursor would place itself after the last character of the time + a space. More precisely here (at the X):

 Friday February 10 2005, 8h 38 am '''X''' 

Thanks!

MG 11th Feb 2005 - What is it you're using? Assuming it's Tk's text widget, then just use $widgetName insert insert "$timestamp " - for me, on Tcl/Tk 8.4.9, that puts the text just before the insertion cursor, which seems to be what you want? Same thing happens with the entry widget.

Thanks Mike! I'll try like you suggest.


I have Tcl 8.4.6 and TkImg 1.3. I get a "can't find package Img" error. I've loaded my libraries. I know it's something simple, but you have any advice?

Peter Newman 10 February 2005: It's probably the Tcl variable(s) (check the docs/sources to find out which they are,) that hold the pathspecs of the directories that Tcl searches to find Img. For some reason, in your system, the pathspec of the directory your Img is in, isn't in those Tcl variables. You'll have to add it (to the appropriate variable).


rdt 2005/02/03 I have question. I'm creating a tcl/tk app running on a Linux distro with tcl/tk 8.4. The app includes a 'package require Tk'. When I start it with tclsh, I can't tab from field to field. The error given is 'invalid command name "tk_focusNext"'. Works ok with wish. Am I not loading some needed library for focus to work?

Peter Newman 4 February 2005: I've got Activestate Tcl 8.4 for Windows. And it has a directory called /Tcl/lib/tk8.4, which has a whole load of *.tcl files - including one called focus.tcl, where tk_focusNext is defined. So presumably your Linux distro is missing either; focus.tcl, or; all the files in /Tcl/lib/tk8.4. Or perhaps it's the directories that Tcl searches to find focus.tcl that aren't wired up correctly. Since it works OK with wish, it's presumably the directory searching that's the problem. Hope that helps.

rdt Cool. You got it right. Thats it. Thanks.


SZ - Feb 02 2005 - A question along the lines Pipes vs Expect. Right now I'm experimenting with sending commands to ghci -- GHC Interactive, interpreter of Haskell programming language, -- and it sends command results into standard output and error information into standard error. Use of [open "|ghci"] allows me to catch only standard output and error information is lost. One solution is to wait for ghci termination abd get it rhtough "set errorInfo [close $h]", but it won't be right on time. Another is to open Ghci with standard error redirection through [open "|ghci 2>streamhandle"], monitoring file change and reading from last position, but it is somewhat cumbersome. Does more complete and less complex solution exist?

Peter Newman 2 February 2005: What about exec? I've never used it - but I understand it makes this sort of thing quite trivial.

Lars H, 3 Feb 2005: The effect of exec would be to wait for ghci to terminate, whereas the point here rather seems to be to interact with it; hence one must rather use open. One trick often used by Alphatk is to open a pipe whose first element is the program you want and whose second element is cat; this allows you to recollect standard output and error into one channel. I think another possibility might be to use bgexec.


2005, Jan 20 WJR - How can I calculate the log base 2 of a number? Thanks!

aricb: You have two options, which both operate on the same principle.

The options:

 [expr {log($num) / log(2)}]
 [expr {log10($num) / log10(2)}]

The principle:

Given bases b1 and b2 and number n, log base b2 of n = (log base b1 of n) / (log base b1 of b2).


2005, Jan 13 GPS -- problem with line objects on a canvas

I have written a program in which i draw a lines between pairs of points. Now each line, when right-clicked, throws up another window whihc allows me to set the properties of the line. (i am using this GUI to simulate a flow between two nodes, hence the properties will include type of flow, packet size etc..) Every line, therefore has to have a unique set of properties. Unfortunately, I can not bind my click to the particular line. I can only set the properties of the last created line. How do i rectify this?

Any ideas? Thanks.

George Peter Staplin: Hi, someone asked me today if you are me. I use the nick GPS in the Tcl'ers Chat and some pages on this Wiki (my initials). Maybe a different nick would ease confusion.

I wonder how you're binding lines. Each [$canvas create line ...] call returns a unique id that you can bind events to. Read the canvas documentation, because I suspect you're missing something about how it works.

MG 13 Jan 2005 - You could use something like this (where showPropertiesSub is the name of the proc you use to edit the points)...

  bind $canvas <ButtonPress-3> {showProperties %W %x %y}
  proc showProperties {w x y} {
    set tag [$w find overlapping [incr x -2] [incr y -2] [incr x 4] [incr y 4]]
    if { [llength $tag] == "0" } {
         return;
       }
    showPropertiesSub [lindex $tag 0] $w
  }

Your showPropertiesSub procedure would then take twoargument, the id of the line on the canvas you're editing; to make changes and the name of the canvas widget itself. To make changes then, just have (in showPropertiesSub):

  $w itemconfigure $item -option value -option value

2005/1/5 Undo Stack Question

I have a question about accessing the undo/redo stack in a text widget. I am trying to determine what, if anything is in the stack in either direction, but I don't want to actually modify it. Is there any way to do this?

MG Jan 13th 2005 - That's not something that's currently possible at present (Tcl 8.4.9), but it is something that would have uses, IMHO. Could well be worth writing a TIP for it, though, I would imagine (naively, with no knowledge of C programming or the Tcl core:) that it wouldn't be a huge change to implement.


2004/12/22 sheila Are there any pages in the wiki on configuration management, project management, formal reviews, build process, etc etc etc? I'm not sure which search strings to use, so I'd like a cheat sheet. Otherwise, I'll start one. I've found that just the right amount of structure in all of this, for a large project, contributes to productivity and stability; but when using tcl (or I suppose any scripting language) the process can get unweildy since the rate of change in tcl scripts is higher (at least, in my experience) than the rate of change in c code. So, I've been wondering how other people manage these things.

For example, for a project with a c code base, any changes whatsoever can undergo peer review without a big head ache, assuming you have the right process to speed things up, but for a tcl code base, does this hold? I've found it to be a big headache before. But, perhaps that was due to the stability of the code base compared to the stability of the other code base.

Is there a wiki page where people have discussed this?

2004/12/30 sheila UPDATE: I'm moving my question to Boost Build since that is where I'm discussing how to get tcl to work with bjam. Since that is part and parcel of my work on a build process in general, I figure it is as good a place as any for a home for my question. :)


2004.12.18 DK Howdy all. I want to create a 'dynamic' widget of sorts. I'd like to be able to enter a number into an entry widget, press a button, and it creates i) a label, ii) an entry, and iii) a menubutton (i'm using grid), all for the number of lines previously entered. My problem is that if I choose to create 2 of these sets (enter '2' and press the button), but later decide to only have 1 (enter '1' and press the button), the only way the make the second line disappear is to deselect/reselect the window with mouse clicks. I've tried using 'update idletasks', but that does not work. Anyone have any ideas?

2004.12.18 DK (edit 1) I think I fixed this problem by surrounding much of the 'grid' code with a pack (I also added a 'labelframe' to the mix). Next question (I'm going to look up as this waits for a response, but I figured I'd get it out while I'm typing). Is it possible to dynamically resize the root window? If I choose to create say 10 sets of columns, but then enter 2 at a later point, the root window is still the same size as it was with 10 sets, but the labelframe and encompassing code shrinks to the proper size. Thanks!

2004.12.19 DK Although I'm not sure it's the most efficient, I found a solution. Grab the size of the outermost frame, then resize the window

  set wsize [grid box .window.frame]
  wm geometry .window [lindex $wsize 2]x[lindex $wsize 3]

20041130 sheila I want to call an ImageMagick commandline function called convert. There is also a tcl command called convert. arg. How do I get this to work?

Working example from the dos prompt

 C:\home>convert -flip test.bmp test.bmp
 C:\home>

Wish prompt

 % set cmd [list convert -flip test.bmp test.bmp]
 convert -flip test.bmp test.bmp

Trying exec

 % exec $cmd
 couldn't execute "convert -flip test.bmp test.bmp": no such file or directory

Trying a pipe

 % set pid [open |$cmd]
 file120ea40
 % close $pid
 Invalid Parameter - test.bmp

Output from regular convert, for comparison

 % convert -flip test.bmp test.bmp
 Invalid Parameter - test.bmp

aricb exec wants a separate argument for each argument that will be passed to the spawned process. No guarantees, but try:

 exec convert -flip test.bmp test.bmp

sheila When I try that, I get the "Invalid Parameter - test.bmp" result.

MG Checking [auto_execok convert] on Win XP SP2, it shows "c:\windows\system32\convert.exe". I just ran "convert -flip test.bmp test.bmp" from a Win Command Prompt (not a tclsh prompt) and it showed the same error you mentioned, so it's not actually Tcl, it's the convert.exe throwing that error. Is that the file you're trying to run? If not, try giving an exact path to convert.exe. If it is the file you want, try giving exact paths for the test.bmp file - it might be that it's trying to find test.bmp relative to the wrong directory.

sheila It works when I provide the full path to the ImageMagick convert. I didn't realize convert is also a Win command. Pathing must be different between my wish shell and cmd.exe.

Peter Newman 1 December 2004: When properly installed, Image Magick requires the path to your Image Magick binary directory (where convert' etc live) in your PATH. That's why you can type convert whatever' from the DOS prompt, and Image Magick's convert runs - no matter what directory you're in. From recollection, the Image Magick install program is buggy, and doesn't update the PATH environment variable properly. You have to do that yourself (generally by appending ;"D:\Path\to\Image Magick" to your PATH in AUTOEXEC.BAT - and then re-booting). Type SET <Enter>' from the DOS prompt to see if your PATH is set correctly. exec' knows about PATH - so once you've done that, it should work. But you'll still have the conflict with the other `convert' if that too is in your PATH - or anywhere else Windows looks for files.


Ro 2004-11-25

glob gets all files in a directory but it takes time if there is over 1000 files in a given dir. I would like to get one file at a time, so that I may call update to keep the gui alive. Is there an analog to FindFirstFile, FindNextFile and FindClose from the Win32 API? Otherwise I will write a little extension to wrap that functionality up, or use ffidl to call those functions directly. Thanks y'all.

Peter Newman 26 November 2004: There is if you use 'fnmatch' or 'glob' from C. (See the `GNU C Library Refrence Manual' for example.) But Tcl's glob (IMHO) isn't particularly well-written or Windows friendly. Something that supports all the C glob's functionality - and/or direct access to the Windows API functions - would definitely be useful.

Ro Thanks for the answer Peter, but I'm not sure if glob from C is the right answer, after reading the C manpage for it. I think readdir(3)[L4 ] is closer to the functionality that I want. Too bad it's not supported in Windows, otherwise there prolly would have been an implementation for it that covered unix and windows. On the bottom of that readdir(3) manpage I referenced is some sample code that shows reading a directory by using a handle to an opened one and looping until you have null for the next dir. I just hate firing up my C compiler, I've been spoiled by scripting. Ah well, so much functionality I need these days is not supported I may just have to really bone up on my C skillz.

Peter Newman 26 November 2004: Yeah you're right. opendir/readdir's the way to go. They work on Windows too (with gcc), as far as I know. Perl supports them (and Tcl should too). I assume that on Windows they're just wrappers around FindFirst/Next.

LV Note that tclx provides a Tcl interface to readdir - and I believe there is a version of it for Windows as well as Unix. Alas, the readdir returns a list of all the files - so that doesn't do what you were wanting. Sorry.


RHS 02Nov2004


Threaded Startkit Question

snichols Anyone know how to configure starkits to find packages within a Tcl Thread? I am trying the package require command frp, within a Tcl thread in a starkit and it can not find my package. Thanks in advance.

snichols With a little bit of troubleshooting and expermintation I was able to figure out how to include a Tcl package within a Tcl thread running in a starkit. Here's how:

Beginning of main thread:

 # The code below goes in the main thread only, 
 # at the very beginning of the script
 package require starkit
 starkit::startup
 package require cmdline
 package require Thread

 tsv::set argv0 ID $argv0
 tsv::set argc ID $argc
 tsv::set argv ID $argv

Beginning of child thread Tcl script:

 # This code goes in the child thread. 
 # For my application I am running tDom in the child thread, 
 # but other Tcl packages can be used to

 # Load the required packages
 set ::argv0 [tsv::get argv0 ID]
 set ::argc [tsv::get argc ID]
 set ::argv [tsv::get argv ID]

 package require starkit
 starkit::startup
 package require tdom

Ok, so now I am able to include Tcl packages running in a thread in a starkit, but I am not able to source in Tcl scripts in a starkit. For example:

 source [file join $starkit::topdir mysript.tcl]

The myscript is at the same level in the starkit as the main.tcl script, but it does not find it. To work around this for now I have put all my Tcl scripts in the same main.tcl file.


4Dec04 SRIV If I define a widget in a tcl OO system, why do I have to use the "method" keyword instead of proc? Can't it "do the right thing" and know that I'm defining a method and make it behave as such, without having to use a redundant keyword? The proc would be private to the widget/object, unless explicitly exported, as in namespaces.

2004-12-04 MSW: I suppose the "method" (or "instproc" or whatever) keyword is needed for the distinction of instance vs. class methods/state [ which makes sense ].

CMcC: most OO systems distinguish between proc and method, probably because (a) their authors have had to jump through hoops to make method work, and you should appreciate the effort, (b) it feels like a big step to redefine proc. In any case, method is a well known term in OO, so of course a tcl OO system will use it - it's just nomenclature.

LV Of course, an additional reason is that many OO extension writers name their commands in a manner that reflects terminology from another arena - c++, java, smalltalk, whatever. Most OO systems treat the Objects as having state and policy. The state consists of the variables that are private to this object. The policy are the functions the object performs - in Tcl, those are procs. Defining these OO functions using a method command instead of a proc command helps distinguish the code that is going to be specific to the object from code that is going to be used by Tcl in some other manner.


Category Ask - Category Discussion - Category Development