Version 191 of Ask, and it shall be given # 10

Updated 2015-04-25 21:02:49 by pooryorick

How to post on this page

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

Started on: 2012 January 31st(Tuesday)

Ended on: 2013 March 17th (Sunday)

------> Next: See Ask, and it shall be given # 11

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.

Please do not put any further questions on this page

Use the next one instead. Thanks!


JBR 2012-03-13 How to create a new Tk widget (or canvas item) without being left behind by the advancement of time.

Lets just say that I was rather dependent on a particular Tk extension widget that is no longer supported. Its stuck at 8.4 and 32 bits on a certain platform. If I wanted to create a new graphic display widget, what graphics API should I use to avoid being left behind (again)?

Thanks, John

the issue is BLT/RBC on OS X.


MoF 2013-03-04 - Distinguish between local and network drives on Windows?

I wrote a wrapper for an old parallel computing software package called PVM. A problem is, that it apparently cannot handle network drives. So I want to check in advance, if a given path is a network drive or not. Is there a function in TCL to do this? I tried file system but that does not do it.

$pathWhat is it?[file system $path]PVM result
c:localnativeworks
d:\\server\foonative NTFScrashes

I have to mention that c: and d: are both NTFS drives, but file system only gives the NTFS parameter in the second case. Any idea?

Thank you very much in advance!

AMG: Parse the output of [exec net use].

MoF Thx for the hint! As I was to lazy to parse it, I now use ::twapi::get_client_shares instead, which works basically the same way.


BMA 2013-03-01 - prototype-based OO?

Do I take it that snit is prototype-based or is there a library that supports that kind of OO paradigm? I'm thinking of something along the lines of ECMAscript etc.


JBR 2013-02-24 - Reading a unicode 16 file?

I don't know anything about how to use unicode. I have a unicode 16 file that startes with a byte order mark and contains the data that I'm after in 16 bit chars. I see lots of NUL characters alternating with the data I want. On my OS X machine I read the file with Tcl and it interprets the file as a stream of 8 bit chars. When confronted with this issue in the past I've simply chopped off the byte order mark and deleted all the NULs.

Can I tell Tcl something so that it does the right thing?

   fconfigure $fp -encoding unicode

Answering myself, the above works but is there a list of supported encodings somewhere?

Thanks,

John

MG It depends which are installed on your system, which usually varies depending on where you obtained Tcl (ActiveTcl typically includes more than are provided in a TclKit, for instance). The encoding names command will list all the currently-available encodings.


MG 2013-02-21 - I'm experimenting with threads for the first time. My aim was to create a socket in a thread, to avoid hanging my app while domain lookups are taking place, then transfer the channel to the main thread to use. However, when I attempt to do so, the channel created is called 'stdin', and trying to transfer it to the main thread fails. Is this intended? Example:

package require Thread
set t [thread::create]
set s [thread::send $t "socket www.tcl.tk 80"]
# Error checking would happen here
thread::send $t "thread::transfer [thread::id] $s"

Doing it the other way - creating the socket in the main thread, then transferring it to another thread - works fine:

package require Thread
set t [thread::create]
set s [socket www.tcl.tk 80]
# Error checking would happen here
thread::transfer $t $s

Am I doing something wrong? Or is there a better approach to this?


JBR - 2013-02-21 strange fconfigure behavior?

set sock [socket 192.168.1.32 502]
fconfigure $sock -translation binary
puts [fconfigure $sock -translation]


set file [open xxx w]
fconfigure $file -translation binary
puts [fconfigure $file -translation]

The result for several versions (every one I tried) of tcl is :

lf lf
lf

Not what I expected... Is the translation really set to binary?

MG The manpage states that it's almost identical to -translation lf, except that -encoding binary -eofchar {} is also set, so I assume that -translation binary is just a convenience wrapper for -translation lf -encoding binary -eofchar {}, albeit a slightly confusing one.


MG Is there any way to find out all widgets which are drawn at a particular coordinate? winfo containing only returns one (the one with the higest stacking order, it seems). I'm fiddling with some (Tcl/Tk-only) drag and drop code, but the widget being used as the visual identifier for what's being dragged is always the result of winfo containing, so it's not simple to check what it's being dragged over. The only solution I can find so far involves recursively checking winfo children and a lot of geometry-math, which is obviously not optimal.

GWM I have tried this trick and it seems to work. For whatever is the response to 'winfo containing': call place forget <result>; then repeat winfo containing will include the next level window; place forget that too.

Here is test code:

toplevel .t -width 200 -height 200 -bg green
frame .t.f -width 150 -height 150 -bd 2 -relief raised
place .t.f -x 25 -y 25
frame .t.f.1 -width 120 -height 120 -bd 2 -relief raised
place .t.f.1 -x 35 -y 35
frame .t.f.1.2 -width 100 -height 120 -bd 2 -relief raised
place .t.f.1.2 -x 45 -y 45
tkwait visibility .t.f

proc wot {x y} {
    set tw "."
    set allw {}
    set nf 0
    while {$tw != ".t" && $nf<20} {
        set tw [list [winfo containing $x $y]]
        if {[winfo exists $tw]} {
            lappend allw $tw
            place forget $tw
        }
        incr nf
    }
    puts "Pile of windows is $allw"
    place .t.f -x 25 -y 25
    place .t.f.1 -x 35 -y 35
    place .t.f.1.2 -x 45 -y 45

    return $allw
}

(bin) 78 % wot 190 190

Pile of windows is .t.f.1.2 .t.f.1 .t.f .t

In my sample allw collects the windows; your exercise is to replace the windows in $allw to their original place - above is a hack to demo the method.


Scrolled Frames

MG It was great to see Tcl/Tk 8.6 finally get an official (non-beta) release, and there are some really great new features. I was kind of disappointed not to see properly scrollable frames and ttk::frames (and other related widgets) included, though - while I know there are various workarounds (like putting things on a canvas), they all have assorted issues associated with them, and being able to put something in a frame and scroll it really seems like a pretty basic requirement. Given the number of other scrollable widgets (which are considerably more complex), it seems to me ('me' being someone completely unqualified to have an opinion) that it should be pretty simple functionality to add in. Can anyone in the know say how likely we are to see them any time soon?

AMG: The KJN version of a scrolled frame works great for me.

MG Thanks for the link - that does seem to work pretty nicely (certainly better than the experience I've had using a canvas), and with a little tweaking for Tk 8.5 seems to work fine with ttk::frames, too. But even so, it's rather a lot of Tcl code to include in every app to get a pretty basic function, and still has at least one issue (in that everything needs to be packed in $widget.scrolled instead of $widget).


Problem with Strings in Expressions

We have an ordered list of Parts that we loop through and we use some string comparison for the Part Names like this if {$var1 > $var2 } {...} Problem is when we hit our Part names that are like 1E3457 and 1E3456. These strings are compared as if they are scientific notation. I see string operators for eq and nq, but not for greater than or less than. e.g.

if {"1E3457" > "1E3456" } {
puts "Greater than"
} elseif {"1E3457" < "1E3456"} {
puts "less than"
} elseif {"1E3457" eq "1E3456"} {
puts "string are equal with \"eq\" "
} elseif {"1E3457" == "1E3456"} {
puts "string are equal with \"==\" "
}

The results are: string are equal with "=="

Any ideas or workarounds? This is a different behavior than our recently upgrade tcl 8.3 environment, may have been introduced in 8.4 when the eq and ne were introduced.

Thanks!

MG string compare is the easiest way to do gt/lt/eq:

switch [string compare "1E3457" "1E3456"] {
   1 {puts "Greater than"}
   0 {puts "Equal"}
  -1 {puts "Less than"}
}

That should also be consistant across a great many versions of Tcl (from 8.3 to 8.6 at the very least, but I'd suspect much older Tcls, too).

KFB Missed that one entirely ... thanks!


MG Is there an easy way to tell whether the copy of Tcl currently running is 32- or 64-bit? I have some extensions which have a different version for each, and am trying to find an intelligent way to figure out which one to run. My first thought was to use $tcl_platform(machine), but I think that's just whether the underlying OS is 32/64 bit (no help for 32bit Tcl on 64bit Windows, for example), and the values are not easily predictable anyway.

AMG: $tcl_platform(wordSize) maybe?

MG In at least one test, tcl_platform(wordSize) was 4 on both a 32- and 64-bit Tcl. tcl_platform(pointerSize), however, was 4 on 32-bit and 8 on 64-bit, so right now I'm having it check to see if both are 4, and assume 64-bit if either isn't.


bz-mof I am using a line like

set status [catch {eval file delete [glob [file join $env(S_PATH) pv.*]]} result]

to clean up a temp directory before starting another software which does not start if there are files like this belonging to the current user (e.g. user1). Normally that works. Sometimes the deleting aborts with a message like "error deleting "C:/TEMP/pv.user15": permission denied". The behaviour I want to have is that it deletes all files it has permission to.

Is there a command to do this automatically or do I have to iterate across all files, check permission manually and try to delete each file seperately? Thanks!

adavis: You could try something like:-

foreach file [glob -nocomplain -directory $env(S_PATH) pv.*] {
   catch {file delete $file}
}

bz-mof Thank you very much, that was exactly what i was searching for. I now can check what happened to each file quite easyly also:

foreach file [glob -nocomplain -directory $env(S_PATH) pv.*] {
   set status [catch {file delete $file} result opts]
   if {$status == 1} {
      log "Failed deleting $file, result was $result"   
   } elseif {$status == 0} {
      log "Successfully deleted $file"
   } else {
      log "Obscure error deleting $file, result= $result, opts=$opts"
   }
}

MG I just updated to ActiveTcl 8.6.0. I'm also hoping to use the ActiveTcl basekits (instead of Tclkits) for building binaries of my apps (mainly as they're more complete, wrt encodings and timezone data).

However, I only have a Win32 box, and want to build binaries for Linux and MacOS, too. Using teacup, I can see that there are basekits for all platforms there, but I can't find any way to get teacup to download them, as its knows they're not compatible with my system. I tried using --force. I even tried getting the URL from teacup archive list to see if I could download it through my browser, but couldn't find any way to. Can anyone help? It kind've defeats the point of being able to build binaries for any platform from one machine if I have to install each OS in a vm just to download the basekits...

gkubu teacup search says "Business Edition Only --- License required"

MG That's only on a few platforms (Win32 64bit, AIX, and a couple of others). MacOS X and Linux (32 or 64bit) don't have that restriction.

gkubu Submitting all details seems to work, but I could not test if the file has been corrupted:

% teacup get  --output . base-tcl-thread 8.6.0.0.296557 linux-glibc2.3-x86_64

Retrieving application base-tcl-thread 8.6.0.0.296557 linux-glibc2.3-x86_64 ...@ http://teapot.activestate.com ... Ok

Output directory .
1 package found, copying retrieved file ...

Copying application-base-tcl-thread-8.6.0.0.296557-linux-glibc2.3-x86_64

MG Son of a.. I think I was using install, not get. Meh. Thanks very much for your help.


In 8.6b3 in aqua, why do Text widgets have <<Paste>> bound to "tk::TextScrollPages %W 1" instead of "tk_textPaste %W"? This breaks Paste completely on my Mac (running 10.6) unless I change the binding back. in text.tcl this is listed as a "Macintosh only binding" but I can't see the point to it.

lihtox - 2013-01-12

Oh wait, never mind. It looks like it was supposed to be Control-V, and someone went through and replaced all the Control-V's with <<Paste>>.

http://sourceforge.net/tracker/?func=detail&aid=3600251&group_id=12997&atid=112997

-lihtox


(2013-Jan-07) Is it time to start page eleven yet?


beware - 2013-1-3 Phone upgrade time. What are the tcl/tk options available for the latest batch of windows phones (windows mobile 7.5 I believe)? Are there binaries available?


pundlik - 2012-12-28 12:39:57

Hello, i have executed wish executable by creating Process in java. I have executed puts command then it doesn't show the output to wish console. I have taken input streamreader of the wish java process and printed the result then i am able to get the result of "puts" command

AMG: I'm not entirely clear on the relationship between your Java and "wish" (Tcl/Tk) processes. Just a complete guess, but maybe the problem is that you started your Java process from Tcl using a blocking [exec] command, in which case none of the Tcl code (including any [puts]'s) following the [exec] will be executed until the Java process quits.

EE [clock format 1357581395]: The questioner doesn't say what platform or OS is being used. It sounds like what's happening here is that a java program is launching wish, and wish's stdin/stdout are tied to I/O channels in Java instead of being redirected to a GUI console produced by the wish app.


exec'ing program that tries to interact with the user

Wurzelsepp 2012-12-25

When I run a tk script, it is usually with &, disconnected from stdin

Now I exec some program from it, and it is usually fine. However, if a program wants to ask an occasional question (here it was gpg "this key is not trusted, do you want to use it anyway") the question appears on the terminal that started the tk script, and I certainly cannot answer it there. Is there some way to deal with this situation?

AMG: See: a way to 'pipe' from an external process into a text widget

Wurzelsepp: Thanks, but no luck so far. The target program - gpg - does not seem to play by the rules but probably uses /dev/tty

Would tclgpg be of any use for you for that specific problem?

AMG: Wrap gpg using unbuffer, which is part of expect.

Wurzelsepp: looking through the C part of tclpgp, I found some pointers that might lead to a pure tcl commection to gpg.

Otherwise I might try to use the pty.tcl

MDI Extension for Tk on Windows

MG 2012-12-04 I've been working on a native MDI extension for Tk on Windows for the last couple of days. However, it's my first time extending Tk (and doing any graphical C programming) and I've gotten a little lost, and was hoping someone with more experience might be able to take a look and help me out.

I have it working up to a point: it successfully creates an MDI client window. I also have it creating a child window (currently with the fixed name ".foo.bar"). However, the child window doesn't appear until I make a call such as

  winfo id .foo.bar

and I have no idea why that is.

The child window also doesn't display anything - it never gets redrawn (always displays whatever was on screen in that position when it appeared) and Tk widgets packed into it don't appear.

I've had a lot of fun digging through the Tk source and docs, and the Windows SDK, figuring out how to get this far, but I'm really not sure how to solve so my current problems, so.. Any pointers would be very much appreciated. I've pastebin'd the code at http://pastebin.com/D5baDU1t - the Tcl code I've been using to run it is:

  load mdi.dll
  pack [mdi::mdiframe .foo] -expand 1 -fill both
  wm geometry . 500x500
  winfo id .foo.bar ;# created automatically when an mdiframe is made. Name is hardcoded.

doncolton 2012-12-02 (This is my first time posting on this wiki. I hope I am doing it right.) I am baffled by this regular expression problem. It looks like it should match but does not.

 set p "\( a \)"
 set a "( a )"
 puts [regexp $p $a] ;# answers 1
 set p "\( a \) \( b \)"
 set a "( a ) ( b )"
 puts [regexp $p $a] ;# answers 0
 set p {\( a \) \( b \)}
 set a "( a ) ( b )"
 puts [regexp $p $a] ;# answers 1

This really has me stumped.

MG In Tcl, "quoted" strings are evaluated, while {braced} strings aren't. That means your first regexp check is matching the regexp

  ( a )

which is the string 'space a space', in a capturing subpattern against the string

  ( a )

Because the regexp isn't anchored, it will match at any point in the string - and because the string contains 'space a space', it matches. Your second regexp is matching the regular expression

  ( a ) ( b )

which is 'space a space' in one subpattern, a space, then 'space b space' in another subpattern, against the string

  ( a ) ( b )

This time, it doesn't match - the string 'space a space space space b space' doesn't appear anywhere in '( a ) ( b )'.

In your final regexp, because the pattern is braced, evaluation doesn't occur, so you're getting the intended result: matching the regexp pattern

 \( a \) \( b \)

which is a literal '(', space a space, literal ')', space, literal '(', space b space, literal ')', against the string

  ( a ) ( b )

This time, with escaped parenthesis in the regular expression (which match literally, instead of being 'special' regexp characters to denote a subpattern), it matches.

doncolton Ah. If I had used "\\\(" instead of "\(" it would have worked. I did not expect the "" to eat the \. Thanks for an excellent response!


MG 2012-11-23 Is it possible to create peers with differently-configured tags? I have a text widget displaying a large amount of text, and a number of other text widgets which display limited/filtered parts of it. Rather than duplicate all the information, it would be great if I could peer them (so it's all using the same data internally, to avoid duplication/wasting memory) and then just configure the tags in the peers to elide certain parts of the data.

If not, is this something that would be possible/likely to change?


pdt 2012-11-10

I would like to find out if there are any items on a text widget's undo/redo stacks. I want to know because I want to disable undo/redo menu items I have in a menu. I've managed to set the state of all other menu items based on the state of my program, and it's just these two that I have outstanding.

I haven't managed to find a solution by searching the net. I did however come across this:

https://groups.google.com/forum/?fromgroups#!searchin/comp.lang.tcl/text$20undo$20stack$20depth/comp.lang.tcl/IPMF4OoVclw/4Lv_RnsY-awJ

which says that it's not possible to do, but that was seven years ago, so I'm hoping that a solution might now exist.

Thanks!

MG I believe that

   $textWidget edit modified

will tell you.

pdt Hmmm, I don't think it does, unless I missed something. I'm already using modified, it tells you the state of the text widget, whether or not it has been modified. Lets say you modify the text, modify state would go to true, then say you do an undo, modified state would go back to false, but then it's possible to do a redo, i.e. redo stack is not empty.

MG Ahh, I see what you mean. I don't believe there's any way to tell that from the script level, no.

pdt OK. As you can imagine it's not particularly important, just a nice to have. Thanks.

gkubu You can test it with

$textWidget edit undo

or

$textWdiget edit redo

and check for error. In case of success, this will change the text, of course, so you will have to reverse it. I'm not sure whether this will bring the stacks back to the state where you started from.


Why does 'file join f a b' produce f/a/b and 'file join f: a b' produce f:a/b NOT f:/a/b ? Note also that 'file join f; a b' and any other punctuation mark except : works as expected (eg f;/a/b). Obviously f: is used to define the drive letter in Windows and needs to be followed by a /.

Also note that 'join {f: a b} "/"' produces f:/a/b.

RLE (2012-11-09): Copied from the file join page:

Windows programmers may be surprised to find that file join "c:" "test" does not necessarily (or perhaps ever?) mean "create a root directory called test on the C drive. Instead, it means "create a directory called test on the C drive. Make it in the current working directory."
MG notes that file join doesn't make the directories, it just provides a path which you can pass to file mkdir. But the path which would refer to a root directory "test" would be file join "c:/" "test" - you need that / make it work right.

The issue is that to Windows, these strings mean very different things:

  • f:a/b
  • f:/a/b

The first (f:a/b) means access directory path a/b in the current working directory of drive f:. The second (f:/a/b) means access path a/b in the root directory of drive f:. I surmise that had file join always inserted a directory separator between f: and a, the result would be that you could never access a/b relative to the current working directory of f: via file join. By not inserting the separator, then the programmer has the choice of "path from root" or "path from current dir" depending upon whether they perform [file join f: a b ] (path from current working directory) or [file join f:/ a b ] (path from root dir).

The reason this distinction exists at all is because Windows has per drive letter current working directories. If you have five drive letters, you have five independent current working directory locations.


mhhall I am attempting to compile Tcl 8.5.11 from source to provide thread support. I've followed directions to enable thread support, but still find the thread test failing (skipping tests). Is there a list that provide things to verify thread support should be available? Are there a set of errors within the config.log file that would indicate that "enable-thread" can't be done?

Unfortunately, this customer requires that Tcl be compiled from source for usage (can't get a version from vendor OS). Repeated this at home using Tcl8.5.13, and still seem unable to get thread test to work properly. What follows is the "head config.log":

This file contains any messages produced by compilers while running configure, to aid debugging if configure makes a mistake.

It was created by tcl configure 8.5, which was generated by GNU Autoconf 2.59. Invocation command line was

  $ ./configure --enable-threads --enable-64bit --enable-shared --with-tzdata

What follows is results is output from "thread.tcl" test: mhhall@mhhall-work:~/tcl8.5.13/tests$ tclsh <thread.test : Total 28 Passed 0 Skipped 28 Failed 0 Number of tests skipped for each constraint:

        28      testthread

mhhall@mhhall-work:~/tcl8.5.13/tests$ Thread related elements out of configure process appear below:

checking for pthread_mutex_init in -lpthread... yes checking for pthread_attr_setstacksize... yes checking for pthread_attr_get_np... no checking for pthread_getattr_np... yes checking for pthread_getattr_np declaration... missing checking for building with threads... yes

Seeing same results with version that I compiled and version delivered with kubuntu

DISTRIB_ID=Ubuntu DISTRIB_RELEASE=12.04 DISTRIB_CODENAME=precise DISTRIB_DESCRIPTION="Ubuntu 12.04.1 LTS" NAME="Ubuntu" VERSION="12.04.1 LTS, Precise Pangolin" ID=ubuntu ID_LIKE=debian PRETTY_NAME="Ubuntu precise (12.04.1 LTS)" VERSION_ID="12.04"

Any help / pointers would be appreciated.


MG Does anyone know when the tk::mac stuff was added? It's obviously some revision of 8.6, but I can't find a TIP related to it, or any mention of it on the wiki.

Few questions about it, too, if anyone knows the answers:

  • Will the ::tk::mac namespace always exist when it's supported (or just always on Mac?), or will it never exist unless you create it manually and define the procs/set the variables documented?
  • Can "::tk::mac::iconBitmap -imageFile" use a file in a vfs as an icon?
  • Will setting ::tk::mac::useThemedToplevel affect existing toplevels, or only new ones? (ie, if running with wish, will "." get the appropriate background if I set the var?)
  • The page says that if "::tk::mac::Quit" is not defined, exit is called. Does that mean that if you have a command set for 'wm protocol . WM_DELETE_WINDOW foo' you'd need to alias ::tk::mac::Quit to it, to ensure it's always run in all instances when "." is destroyed? Or would the WM_DELETE_WINDOW handler still catch it, and aliasing ::tk::mac::Quit to it would cause it to run twice?

Thanks, and I hope that makes sense.


AMG: I know this is a C question rather than a Tcl question, but maybe someone might have some advice. How does one go about writing a Tcl command wrapper function for a C function that takes variadic arguments? For example, let's say I wanted to make the C sprintf() function available to Tcl script. It doesn't matter whether I'm using SWIG, critcl, or writing the wrapper by hand; the question still stands. How would I actually pass the arguments to the function being wrapped? Targeting vsprintf() instead doesn't seem to make things any easier: how is a va_list constructed, other than by having already been passed variadic arguments?

aspect: AFAIK there is still no portable way to create an argument list at runtime. The C-FAQ has a relevant answer with some non-portable "wacky ideas" linked which may work ... for GCC, see here .

AMG: The GCC functions only work for forwarding arguments that were on the call stack to begin with. They appear to be conceptually similar to va_list, except that the arguments are passed to a function expecting to receive a normal argument list instead of a va_list. It's clear the only way to do what I'm asking is with unportable assembly language, since the arguments to pass come from Tcl_Obj*'s instead of the call stack.


jbr 2012-09-04

I'd like to allocate a byte array that is initialized to 0 and not have to provide the "bytes" argument that Tcl_NewByteArrayObj(bytes, length) requires. Ideas?

Thanks.

AMG: Pass NULL as the bytes argument for Tcl_NewByteArrayObj, then do memset on the return value of Tcl_GetByteArrayFromObj to initialize it to zero.

It's not necessary to do Tcl_IsShared and Tcl_DuplicateObj on the new Tcl_Obj in this case because it will have zero initial reference count, but you will want to do Tcl_IncrRefCount on it to be sure it doesn't get randomly freed or appropriated upon reentering the Tcl engine.


gkubu 2012-09-01

Is it possible to control which variables are exported from a namespace in a similar way as commands? E.g. if I say

namespace eval ns {
 export variable var
} 

then I can access $var after namespace import, otherwise not (and not with $ns::var either)

MG To the best of my knowledge, variables can't be exported in that way. However, you could likely use upvar at the global level to achieve it:

(bin) 1 % namespace eval foo {variable bar; set bar baz}
baz
(bin) 2 % set bar
can't read "bar": no such variable
(bin) 3 % set foo::bar
baz
(bin) 4 % upvar #0 ::foo::bar ::bar
(bin) 5 % set bar
baz
(bin) 6 % set bar test
test
(bin) 7 % set foo::bar
test

gkubu Thanks, but I want it the other way round:

(bin) 1 % namespace eval foo {variable bar; set bar baz}
baz
(bin) 2 % set foo::bar
can't read "foo::bar": no such variable  ;# <- Variable should not be accessible
baz

gwm try set ::foo::bar ;# that works.

gkubu yes, that's the problem :-) I don't want it to work, so that the namespace variable is hidden. Sorry for my English, obviously it's not very clear what I want to achieve. The variable should only be accessible within the namespace, but across procedures within the namespace, so it's not local to a procedure, but local to the namespace. Maybe this is possible by nesting proc's and use of upvar, but this approach looks rather weird (to me).

MG As far as I know, that's not possible with namespace variables. It sounds like you're trying to implement classes with private variables; maybe TclOO would be better?

RLE (2012-09-03): You might be able to create what you want with creative use of a read trace on the variables you want "protected" from reading. But for basic namespaces, if you know the path to the variable, you can access the variable.


couldn't open socket: connection refused

ckm says, 2012-08-30

Hi All, I'm facing an error "couldn't open socket: connection refused" in AIX server 6.1. When this error comes nothing else works unless we restart the server. Can anyone suggest me how to solve this issue.

Thanks

AMG: You're not giving us enough information to help diagnose the issue. First off, when you say "restart the server", are you referring to the client application, server application, the server computer, or your AIX server 6.1 machine? For that matter, is the [socket] command trying to connect to something on the local machine or elsewhere on the local network or across the Internet? Have you tried doing this without Tcl? For example, use telnet or similar to directly connect to the server socket. Does this same problem occur when running on different operating systems?

We'd appreciate some minimal code samples demonstrating the problem, preferably in a way anyone can repeat.

Hi,

Port scanning in tcl - this web page has the problem mention by me. But I couldnt get the reason or the solution for the problem. and when we encounter this problem we restart the client application.

Thanks


tkinter canvas_update gets slow

Does anybody know if there is a way to add a pixel, or image to a canvas without reupdating the entire canvas? I have a program that puts a colored pixel on a canvas, loops around and adds another pixel next to the first etc...works fine for the first few hundred, then gets slower and slower. I delete (canvas.delete(ALL)) the canvas before I update so I'm not burning up memory stacking canvases on top of each other. If I do a few hundred pixels at each update, that speeds it up but still gets too slow. I really want to be able to do this one pixel at a time.

AMG: You may want to use photo images instead. You can put an image inside a label, a canvas, or in other widgets. Images can be modified via script. If you want more performance, you can write C code, e.g., using critcl, to put the pixels into the image. Here's the API: [L1 ].


Hello I have an issue with the lindex command.

The piece of code is like this, for example

set var1          [lindex $some_list 7]
set var2          [lindex $some_list 7]

In this case var2 always recieves an empty string....

Is this correct? I look in manuals and nothing says about this.

Thanks.

rgf 2012-08-14 The following work for me:

  set some_list [list 0 1 2 3 4 5 6 7 8 9]
  set var1 [lindex $some_list 7]
  7
  set var2 [lindex $some_list 7]
  7
  set var1 ;# to check value
  7
  set var2 ;# to check value
  7

or

  set some_list [list 0 1 2 3 4 5 6 7 8 9]
  set var1 [lindex $some_list 7] ; set var2 [lindex $some_list 7]
  7
  set var1 ;# to check value
  7
  set var2 ;# to check value
  7

Is 'some_list' being changed between your statements set var1 ... and set var2 ... ?

MG lindex doesn't edit the original list, so var1 and var2 should always be the same in your example. As rgf said, I suspect there must be something between those two set calls which is altering the original list. Can you share the exact piece of code?

Hi the piece of code is this with another names....

orabindexec $select_sp_database :field1 $field1

    set some_list ""

    orafetch $select_sp_database -datavariable some_list


    set var1                             [lindex $some_list 0]

    set var2                             [lindex $some_list 1]

    set var3                             [lindex $some_list 2]

    set var4                             [lindex $some_list 3]

    set var5                             [lindex $some_list 4]

    set var6                             [lindex $some_list 5]

    set var7                             [lindex $some_list 6]

    set var8                             [lindex $some_list 7]

    #set var9                            ""
    set var9                             [lindex $some_list 7]

    set var10                            [lindex $some_list 8]

    set var11                            [lindex $some_list 9]

In this way lindex returns inforation to var8 and an empty string in var9.

if I comment this line

set var8 lindex $some_list 7

lindex returns the same information to var9 have.

rgf I suspect the orabindexec ... command puts something different than expected into 'some_list'. You may want to check the length of 'some_list' and what exactly is stored in it when the problem is exhibited.


MG July 21 2012 - One more. I'm using a ttk::notebook and want to style the tabs differently. I've tried using ttk::style in various ways with no luck.

There seem to be 3 styles for tabs currently - normal, active and disabled. What I'd really like is a way to use the "disabled" style without actually setting -state disabled on the tab (I still want it to be usable, just look disabled), and also a way to create a new style to show when a tab is updated (preferably so that I can flash the tab to show activity in an eye-grabbing way). Any help would be greatly appreciated.

Update: I set the theme to "alt" and then managed to see some results, using:

  ttk::style map TNotebook.Tab -background [list selected red disabled yellow]

But it doesn't seem like that (or anything else) has any effect using the winnative theme. I vaguely recall being told once before that tweaks to that theme are basically impossible because it uses Windows standard colours/settings/etc and you can't override them; is that the case, or is there something I can do?


MG Is there any way to bind to a keypress when you have a decimal value for the key, but no keysym name? My keyboard has 'extended' buttons for Back/Forward/Stop/etc which I'd like to bind to, but using:

  bind . <KeyPress> {puts "%k / %K"}

to try and find out what they are gives me

  166 / ??
  167 / ??

etc. I can't find a way to bind to the decimal number. The keysyms manpage lists 166 as 'brokenbar', but the '%K' sub obviously doesn't match up with that on my system (WinXP), and binding specifically to <KeyPress-brokenbar> gets me nothing.

Any ideas? Is there anything I can do short of checking to see if '%k%K' eq '166??' ?


MG (Moved this here from encoding convertfrom) Have a bit of a strange problem, hopefully someone can help. This example script shows what I'm trying to do - it displays cp437-encoded text in a text widget:

text .t -font Term

pack .t

.t insert end format %c 152

.t insert end [encoding convertfrom cp437 [format %c 152]

The Term font being used is available at http://8bit.memoryleak.org/Flag/Term.ttf and is designed for displaying cp437-encoded text.

Character 152 in cp437 is a y-umlaut. However, the first insert displays a placeholder character (a solid down-arrow) instead. The second does display a y-umlaut, but it does so by mapping to character 255, which isn't available in the Term font (because it has no meaning in cp437), so Tcl uses a fallback font, and it looks totally wrong (Term is fixed-width and quite bold; the fallback font, Lucida Sans Unicode, doesn't match up at all).

I can use the Term font in other (non-Tcl) applications, for instance MS Word, and insert char 152, which gives a y-umlaut without any problem. I honestly have no idea what's causing this issue; can anyone shed any light?


MG Pretty sure I already know the answer, but just in case there's something I'm not aware of: Is there any way to 'fix' the position of a line of text in a text widget? I have one line which, no matter how the widget is scrolled, I always want to be displayed at the bottom. Right now my best thought is to just use a separate text widget, but that seems like rather a lot of overhead (in terms of memory use) to display a single line at the bottom, and it would be nice if it was still selectable with the other text.


MG I'm a Windows user, and I've been trying to talk a friend through running a Tcl app on a Linux system, but with limited success.

On 3 separate linux distros (Mint, Ubuntu and Gentoo) he's installed Tcl and Tk (8.5) through the system's package manager, but all three of them fail to load the 'starkit' package, and none of them includes teacup with the Tcl install. I had thought that the starkit package was a very basic inclusion with a Tcl install these days. My only thought was that it might have been shifted out from the basic install into Teapot, but none of the installs included a teacup exec either, which made that seem unlikely. Anyone have any ideas/suggestions/reasons I'm an idiot?

RLE (2011-07-11) Both Starkit and Teapot are not shipped with the basic Tcl and Tk sources, which is what is usually installed via most Linux package managers when one installs Tcl/Tk, although the true answer is: "it depends on how your distro packages things". You can find links in the first section of the Starkit page to locations where your friend can obtain a tclkit executable file, which will run a Starkit package.

Alternately, if the package you want him to run is available as a Tcl/Tk source bundle, and the distro package manager can install any prerequisites, then the source bundle could be used with what the package manager installs.

MG OK - I thought it was standard for the starkit package to be bundled with Tcl so that starkits could be run by any copy of Tcl. I've just tweaked things to make it optional instead when running from source. Thanks for your help.

RLE (2011-07-15) I think the ActiveState bundles include starkit support, but the Tcl/Tk source tarballs do not. Most Linux distros use the Tcl/Tk source tarballs to produce their packages, not the ActiveState bundles (likely due to licensing conflict issues).


beware Can someone provide me some example code to keep a GUI alive during the copying of a large (2Gb) file?

RLE (2012-07-04): Try searching the wiki for "keep gui alive" and you will find something.


I am desperately trying to figure out how to run the tk tests in the tk8.5.11 tests directory. Building tcl was trivial and it tests beautifully and then installed neatly into /usr/local. All is well there. The build of tk8.5.11 took a bit more time in order to ensure all the X11 headers were available. Once that was done a configure was easy and build seemed smooth. No worries.

However running the tk tests is a total fail. There is no documentation on this issue anywhere I can find. I tried to run tcltest all.tcl in the tk8.5.11/tests directory and saw this foo :

$ ../../tcl8.5.11/unix/tcltest all.tcl can't find package Tk

    while executing

"package require Tk "

    (file "all.tcl" line 14)

It seems as if one has to install Tk first before testing it ? That will never, ever, happen.

So what is the magic incantation to get the tk tests to run ?

tcl floating point math error on 5.8.8

When subtracting 1.01 from 1.0, I get something like -.0100000009. Does anyone know why, and how to not get this error? Thanks JLD

JM please state the line of code you are using to get this...
because I am getting this...(did you mean version 8.5?)

 % expr {1.0 - 1.01}
 -0.01

RLE (2012-07-03) See What Every Programmer Should Know About Floating-Point Arithmetic


How to pass data from C to Tcl dynamically using critcl library I wrote a very simple script in tcl/tk as a GUI for a C procedure that should be the core for speed computation. The C procedure is called "start_tx_c" and it is an while loop. When I call from tcl/tk it works and when the exit criteria is matched it gives me back the results. The problem is that I can't control the while loop from tcl/tk and furthermore this procedure can't give to the GUI partial computation results before exiting from the while loop. Here the complete source code. Can anybody help me?

#--------- start source code ---------------

lappend auto_path pwd package require critcl

global stop_type global stop_cond global nr_of_cycles_before_stop global start_time global stop_time

set start_time 0 set stop_time 0

set stop_type "manual_stop"

critcl::cproc start_tx_c {double x} double {

        double i = 0;

        while (i != x)
        {

                i++;

        } 


        return i;

}

proc error_msg {messaggio} {

        .frm.msg configure -text $messaggio

}

proc stop_tx {} {

        global stop_cond
        global stop_time
        global start_time

        set stop_cond 0
        set stop_time [clock microseconds]
        set elapsed_time [expr $stop_time - $start_time]

        .frm.but_start configure -state normal
        .frm.but_reset_result configure -state normal
        .frm.but_stop configure -state disabled
        .frm.but_reset_entry_fields configure -state normal
        .frm.but_reset_all configure -state normal

        .frm.text_Stop_Time delete "insert linestart" "insert lineend +1 char"
        .frm.text_Stop_Time insert insert $stop_time

        .frm.text_Elapsed_Time delete "insert linestart" "insert lineend +1 char"
        .frm.text_Elapsed_Time insert insert $elapsed_time


        enable_entry_fields

}

proc enable_entry_fields {} {

        .frm.entry_nr_of_cycles_before_stop configure -state normal

}

proc reset_result {} {

        .frm.text_Start_Time config -state normal
        .frm.text_Start_Time delete "insert linestart" "insert lineend +1 char"

        .frm.text_Stop_Time config -state normal
        .frm.text_Stop_Time delete "insert linestart" "insert lineend +1 char"

        .frm.text_Elapsed_Time config -state normal
        .frm.text_Elapsed_Time delete "insert linestart" "insert lineend +1 char"

        .frm.text_Counted_Cycles config -state normal
        .frm.text_Counted_Cycles delete "insert linestart" "insert lineend +1 char"

}

proc reset_entry_fields {} {

        .frm.entry_nr_of_cycles_before_stop delete 0 end

}

proc reset_all {} {

        reset_result
        reset_entry_fields

}

proc check_entry {} {

        global nr_of_cycles_before_stop
        global stop_type
        global start_time

        set entry_ok 1

        error_msg ""



        if {[string is double -strict  [.frm.entry_nr_of_cycles_before_stop get]] } {

                if { [.frm.entry_nr_of_cycles_before_stop get] >= 1} {

                        set entry_cycles_before_stop_ok 1

                } else {

                        error_msg "The value of - Stop After Cycles - must be greater or equal than 1"
                        set entry_cycles_before_stop_ok 0
                }

        } else {

                error_msg "The value of - Stop After Cycles - is not an integer value"
                set entry_cycles_before_stop_ok 0
        }




        if { $entry_cycles_before_stop_ok == 1 } {

                set nr_of_cycles_before_stop [.frm.entry_nr_of_cycles_before_stop get]
                set start_time [clock microseconds]
                .frm.but_stop configure -state normal
                .frm.but_start configure -state disabled
                .frm.but_reset_all configure -state disabled
                .frm.but_reset_entry_fields configure -state disabled
                .frm.but_reset_result configure -state disabled
                .frm.entry_nr_of_cycles_before_stop configure -state disabled
                .frm.text_Start_Time delete "insert linestart" "insert lineend +1 char"
                .frm.text_Stop_Time delete "insert linestart" "insert lineend +1 char"
                .frm.text_Elapsed_Time delete "insert linestart" "insert lineend +1 char"
                .frm.text_Counted_Cycles delete "insert linestart" "insert lineend +1 char"

                .frm.text_Start_Time insert insert $start_time

# start_tx $nr_of_cycles_before_stop

                set count [start_tx_c $nr_of_cycles_before_stop]

                .frm.text_Counted_Cycles insert insert $count

                stop_tx

         } else {


        }

}

#====================================================================== frame .frm -relief groove grid .frm -column 0 -row 0 #======================================================================

button .frm.but_reset_result -text " Reset Result " -state normal -command reset_result grid .frm.but_reset_result -column 3 -row 1 -padx 10 -pady 5

button .frm.but_reset_entry_fields -text " Reset Entry " -state normal -command reset_entry_fields grid .frm.but_reset_entry_fields -column 4 -row 1 -padx 10 -pady 5

button .frm.but_start -text "Start Transmitting" -command check_entry -borderwidth 2 grid .frm.but_start -column 1 -row 1 -padx 10 -pady 5

button .frm.but_stop -text "Stop Transmitting" -state disabled -command stop_tx grid .frm.but_stop -column 2 -row 1 -padx 10 -pady 5

button .frm.but_reset_all -text " Reset All " -state normal -command reset_all grid .frm.but_reset_all -column 5 -row 1 -padx 10 -pady 5

#================================================================== label .frm.lab_number_of_cycles -text "Numero di cicli da effettuiare" grid .frm.lab_number_of_cycles -column 0 -row 13 -padx 10 -pady 5 entry .frm.entry_nr_of_cycles_before_stop -width 27 grid .frm.entry_nr_of_cycles_before_stop -column 1 -row 13 -padx 10 -pady 5 #==================================================================

#================================================================== label .frm.lab_Start_Time -text "Inizio Cicli While (microsec)" text .frm.text_Start_Time -width 27 -height 1 -state normal grid .frm.lab_Start_Time -column 0 -row 14 -padx 10 -pady 5 grid .frm.text_Start_Time -column 1 -row 14 -padx 10 -pady 5 #=================================================================

#================================================================== label .frm.lab_Stop_Time -text "Fine Cicli While (microsec)" text .frm.text_Stop_Time -width 27 -height 1 -state normal grid .frm.lab_Stop_Time -column 0 -row 15 -padx 10 -pady 5 grid .frm.text_Stop_Time -column 1 -row 15 -padx 10 -pady 5 #=================================================================

#================================================================== label .frm.lab_Elapsed_Time -text "Elapsed Time (microsec)" text .frm.text_Elapsed_Time -width 27 -height 1 -state normal grid .frm.lab_Elapsed_Time -column 0 -row 16 -padx 10 -pady 5 grid .frm.text_Elapsed_Time -column 1 -row 16 -padx 10 -pady 5 #=================================================================

#================================================================== label .frm.lab_Counted_Cycles -text "Numero di cicli effettuati" text .frm.text_Counted_Cycles -width 27 -height 1 -state normal grid .frm.lab_Counted_Cycles -column 0 -row 17 -padx 10 -pady 5 grid .frm.text_Counted_Cycles -column 1 -row 17 -padx 10 -pady 5 #=================================================================

message .frm.msg -text "" -width 10000 -justify left -foreground red grid .frm.msg -column 0 -row 30 -columnspan 15

reset_all

#------- end source code -------------

EG: See Keep a GUI alive during a long calculation for an in deep discussion about this problem and their possible solutions.

**

Recursion Problem

!!!sabareesh -2012-06-10 Hi. I have a Tcl script that finds the shortest path between two points in the XY plane when the plane contains some invalid points which cannot be traversed. The problem is that I have used recursion and my sample space is very large consisting of a million points. So i run out of stack space. I have gone through the section on bifurcation but I find it difficult at this point to recode the thing again. How do I get around the problem? Is there a way to increase the stack size? Any help would be really appreciated. Note: I am not bound by RAM size. I have a work station with 32 GB Ram.

A good solution to excessive recursion is not to use recursion; in STL you would use a std::stack to store the values which remain to be used, and push more items onto the stack as needed. There is a very similar struct::stack (which I have not used in anger) in Tcl which should do the task. As a simple approach you would code something like this:

  package require struct::stack
  struct::stack mystac

  mystac push 1
  mystac push 2
  while {[mystac size]} {
    set a [mystac pop]
    puts "stack size after $a is [mystac size]"
   # here you perform some action on the item popped, which might result in more items being pushed onto the stack
  }

Basically the stack replaces your recursion by storing the values (held in the list of calling procedures in recursion) with a single 'array' (it is not an array of course). The thing in the stack can be a value or a variable or the name of a variable or the name of an OO class object or whatever. It is wise to restrict your stack to holding only one type of data (int, float, name, just one type of OO class) although Tcl will allow you to make a mixed stack.

Will this save memory? Massively - the overhead every time you call a proc is significant. You should ensure that the while loop terminates at some point - just as your recursion must terminate and not carry on pushing more calls for ever. You will also find an increase in speed of up to 10 times (or more) due to not adding to the stack of recursions which need to be stored to allow the code to return.


Perhaps the highest-profile Tcl bug report ever: [L2 ]

  • If Anybody Can Tell Me Why...
    …Tcl/Tk 8.5.5 installs and plays well with R on the MacMini running OS X 10.6.8, but barfs and hangs-- sending two of the four processor cores into active catatonia-- on the MacBookAir running OS 10.7.4, I would be very grateful…

If someone here can help him, we may have our conference keynote speaker for next year...


lihtox - 2012-06-02 10:05:00 I want to modify a text widget so that pressing Control-I automatically assigns or removes an italics tag, just as it does in Word etc. Doing this on my own proved very difficult: changing selected text is easy, but I want to be able to have text be italicized appropriately while I'm typing it: e.g. In my text box, I press Control-I, and everything I type afterwards is marked with the italics tag until I press Control-I again.


nataraja - 2012-05-10 05:53:54

How to zoomin and zoomout on a canvas and still don't lose the resolution of coordinates example if I scale with 0.8 6times and then scale with 1.25 6times ( 1/0.8) , there is possibility of losing the resolution if I do this multiple times !!

if I create a rect at 100 100 200 200 after these operations on a canvas the $c coords rect_id , may return 100.3 100.3 200.3 200.3

these values are not exact , hope you understand the problem

Regards Nataraja

EG You can implement a "zoom stack" to keep track of the actual item coordinates while you are scaling up, and then pop the coordinates back form the stack when you are scaling down. A simple demo:

package require Tk
proc zoomIn {c factor x y} {
    global zoomstack
    foreach item [$c find all] {
        lappend zoomstack($item) [$c coords $item]
        $c scale $item $x $y $factor $factor
    }
}
proc zoomOut {c} {
    global zoomstack
    foreach item [$c find all] {
        if {![info exists zoomstack($item)] || ![llength $zoomstack($item)]} {
            continue
        }
        $c coords $item [lindex $zoomstack($item) end]
        set zoomstack($item) [lrange $zoomstack($item) 0 end-1]
    }
}
pack [canvas .c]
.c create rectangle {10 10 100 150}
.c create rectangle {20 5 120 130}
.c create oval {30 40 70 90}
set factor 1.33
# left click zooms in, right click restores the previous zoom factor
bind .c <1> [list zoomIn .c $factor %x %y]
bind .c <3> [list zoomOut .c]

AMG: Nataraja, I assume you're using the [$canvas scale] command. Here's a little test that demonstrates your problem:

% package require Tk
8.6b2
% pack [canvas .c]
% .c create rectangle 100 100 200 200
% .c scale all 150 150 0.8 0.8
% .c scale all 150 150 0.8 0.8
% .c scale all 150 150 0.8 0.8
% .c scale all 150 150 0.8 0.8
% .c scale all 150 150 0.8 0.8
% .c scale all 150 150 0.8 0.8
% .c scale all 150 150 1.25 1.25
% .c scale all 150 150 1.25 1.25
% .c scale all 150 150 1.25 1.25
% .c scale all 150 150 1.25 1.25
% .c scale all 150 150 1.25 1.25
% .c scale all 150 150 1.25 1.25
% .c coords all
100.00000000000009 100.00000000000009 199.99999999999994 199.99999999999994

After twelve rescales, the width/height of the rectangle is only off by 0.00000000000014210855% and the absolute position is off by 0.00000000000008526513%. Your message says that the size comes out right but the position is shifted by 30%. That's quite a discrepancy in magnitude. Are we talking about different issues?

Let's put the canvas aside and just do straight math:

% set x 10
% for {set i 0} {$i < 6} {incr i} {set x [expr {$x * 0.8}]}
% set x
2.621440000000001
% expr {10 * 0.8 ** 6}
2.621440000000001
% for {set i 0} {$i < 6} {incr i} {set x [expr {$x * 1.25}]}
% set x
10.000000000000007
% expr {10 * 0.8 ** 6 * 1.25 ** 6}
10.000000000000004
% expr {2.62144 * 1.25 ** 6}
10.0

Here, I start with 10, scale it by 0.8 six times, and get a value around 2.6. I double-check the result by performing it a different way, using exponentiation. The two come out exactly equal. (Note, however, that neither is exactly right: the real answer should be 2.62144 with no extra digits. So there's the first floating point error. See: a real problem.) Next, I scale the value from before by 1.25 six times, resulting in a value around (but slightly above) 10. Look familiar? It's the same problem you're having, though without the canvas. That little bit of floating point error got magnified! Then I tried to get the value in a different way, using a pair of exponentiations. There's less error, but it's still there. Finally, I scaled the exact value (computed external to Tcl) and got exactly 10, no error.

By the way, if you're using an older version of Tcl that doesn't have **, replace it with pow.

If it really matters to you that canvas scaling be perfectly invertible with no cumulative floating point error, you will need to perform your scaling in a different way.

To be honest, I have never used the [$canvas scale] command before; I always wind up writing code that generates or repositions all the canvas objects according to dynamic scene and viewing data. This avoids cumulative error, though that's not the reason I go this route. I do it because I often use the canvas to graph data that is dynamically produced outside of the canvas, and I never need to read the coordinates back out of the canvas, since the data "lives" elsewhere. For me, the canvas is write-only except in the case of user interaction.

Here's an example:

% package require Tk
8.6b2
% pack [canvas .c]
% set item [.c create rectangle 0 0 0 0]
% set obj_coords {10 10 20 20}
% set obj_center {15 15}
% set view_center {150 150}
% proc repaint {} {
    global item obj_coords obj_center view_center view_zoom
    for {set i 0} {$i < [llength $obj_coords]} {} {
        for {set j 0} {$j < 2} {incr i; incr j} {
            lappend view_coords [expr {
                ([lindex $obj_coords $i] - [lindex $obj_center $j])
              * $view_zoom + [lindex $view_center $j]}]
        }
    }
    .c coords $item $view_coords
}
% foreach i {0 1 2 3 4 5 6 5 4 3 2 1 0} {
    set view_zoom [expr {10 * 0.8 ** $i}]
    repaint
    update
    after 100
}
% .c coords $item
100.0 100.0 200.0 200.0

Now there's no error at the end, since there's no place where error is allowed to accumulate.

This example doesn't really show a good way to do animation. For something nicer, search for "coroutines" on the page Keep a GUI alive during a long calculation.


Expr question

Z3 201205081340: Following can be seen in the expr's manual: expr {"0y" < "0x12"} returns 1, because it is done using string comparison after the second operand is converted to the string 18. But the command returns 0 in the Tcl interpreter. Is it a bug?

AMG: Looks like a bug in the documentation. "0y" should sort after "0x" or "0x12", so I expect a 0 return, which is in fact what Tcl gives me.

Z3: But "0x12" is a valid hexadecimal number (18). And "0y" < "18" is true, because "0" < "1" (string comparison). (In the manual, part "STRING OPERATIONS" we can see: "Because of Tcl's tendency to treat values as numbers whenever possible, except in the case of the eq and ne operators.". And I expect the same on the ground of the part "OPERANDS": "Where possible, operands are interpreted as integer values.")

AMG: String comparisons do not consider numerical value, so the comparison is between "0y" and "0x12", not "0y" and "18". Only if both operands could be converted to numbers would their numerical values be compared.

Z3: Thank you for the quick answers. And how could we achieve the modification of the manual?

AMG: Report it here: [L3 ]. Use the "Add new" link.


Prasath - 2012-04-20 07:03:53

Best Practice - Style Guide - Variable declaration

 Multiple variable declaration and aligning them

Please Suggest the best practice - Method 1 or Method 2 and explain why if possible:

Method #1:
set var1              $val1
set var2              $val2
set variablename1     $value1
set variablename2     $value2
Method #2:
set var1 $var1
set var2 $var2
set variablename1 $value1
set variablename2 $value2

AMG: There's no preference. Pick whichever one suits your mood.

#1 may look prettier, but it also takes more time to maintain, so I tend to use it when I have a lot of clearly tabular data that doesn't change (e.g. a collection of unit conversion constants). I'm more likely to use #2 when the data's nonuniform (e.g. variable names have very different lengths, some values are constants, others are the result of complicated substitutions) and/or I expect to be making lots of changes before I'm done.

There's a similar issue regarding comment placement. Putting comments on each line and keeping the comment columns lined up has the same drawbacks (takes more time to maintain, constraints length of variable names and complexity of substitutions as well as length of comment text), so also consider putting the comments on their own lines immediately before the initializations they describe. But if you do that, you add so much of a visual break that there's no perceptual value to vertically aligning the variable values.

Prasath: Thanks for your suggestion. I was using python a few months ago.

PEP8 - http://www.python.org/dev/peps/pep-0008/

Above documentation is one of the style guide for python scripts and it explains this clearly. I couldn't find a similar one for TCL apart from Ray Johnson's doc.

According to PEP8

More than one space around an assignment (or other) operator to align it with another.

Yes:
x = 1
y = 2
long_variable = 3

No:
x             = 1
y             = 2
long_variable = 3

So i thought Method #2 could be the better one. But python uses operators for assignment. As you said, it takes a bit more time for maintenance. Also people can tend to make mistakes by adding tab instead of spaces.

AMG: The Python recommendation illustrates my point about "variable names have very different lengths". If the variable names have similar (but not identical) length, a little extra space may go a long way to helping readability. I'm sure the author of that PEP wouldn't mind the following:

north = 1
east  = 2
south = 3
west  = 4

and might even find it preferable to:

north = 1
east = 2
south = 3
west = 4

which has a distracting visual pattern. However, a syntax highlighter may obviate some of the need for columnar alignment, since it uses colors or other font modes to help the reader quickly pick out the different syntactic elements. The trouble is, many traditional syntax highlighting concepts are fundamentally incompatible with the minimal Tcl grammar.

Here's some style discussion on the Wiki:


Prasath: Yes. I agree. Thanks for sharing the Style guide discussion. Its really helpful.


Beware 17th April 2012: I'm using Bryan Oakley's lovely combobox widget. When first created and given a list, nothing is selected. Hence curselection returns "". If I select something, it returns the index. But how do I tell it to clear the selection? .cb selection clear 0 end does nothing.


Martyn Smith - 2012-04-17 Does anyone have any TCL code or a library to handle multitouch input. I have a user who has a large (2 metre) screen with multitouch added to allow zooming. another (QT) application seems to handle multitouch zooming/scrolling on its 2D canvas. I was wondering if anyone had any ideas about this. The idea is to use it to zoom/scroll BLT graphs. I have code for that which works well using the middlemouse button.


EE - 2012-04-16 Is there a Tcl script or library for encoding/decoding QR Code images?

AMG: Not at present, as far as I know, but I see no reason why there can't be. Maybe somebody will pick up this task now that you have suggested it.

escargo - Is this a suitable candidate for Google Summer of Code?

AK IMHO yes. This could also be making a binding to a C-based QR code library.

Beware Might be worth a look . I haven't gone much further than downloading it, but it does include a dll for any cpu.


uniquename: Hopefully an easy question: I know that a strpack first unpacks itself on to a virtual drive. Does it use a fixed or a well-known location for this such as C:\temp?

SEH -- the starpack's virtual directory structure exists entirely in RAM and is not written or copied to the hard drive. The directory's location is stored in the variable starkit::topdir at startup. When accessing virtual files you should use this variable as the start of the filename path rather than trying to discover and use the name of the top directory directly.

RFox Just as an add on...all of that works (I think) via the Tcl virtual file system mechanism. What _may_ get copied to a temp directory is compiled extensions (DLL' s in windows, .so's in all Unixes except Mac where they are .dynlibs). Those get copied to the native filesystem because the dynamic loader functions of the underlying operating system need a file they can see.


jbr - I'd like to use the Tcl library thread functions to process data in parallel. The thread man pages say that Windows threads are not joinable. Does someone have a simple example of how to wait for several worker thread to finish in a portable way?

Thanks, John

RFox Use Tcl_ThreadQueuEvent to send an 'exit' event from the worker thread to the master...master spawns off the workers and enters the event loop.


MG April 4th 2012 - I have a doozy of a text widget bug here. It's taken me a long time, on and off, to narrow it down to a simple test case:

pack [text .t -wrap word -width 80] -expand 1 -fill y -side left -anchor nw
wm state . zoom
proc write {str} {
 .t insert end [clock seconds] timestamp $str "" \n
}
.t tag configure timestamp -elide 1
for {set i 0} {$i < 35} {incr i} {
write "This is a rather pointless string."
}
write [string repeat - 8192]
write "Another string"

Then try and scroll the text widget to the end, either using the mousewheel or Page Down. When it reaches the bottom, it then continues to "scroll", by jumping back up again and then going back down. It also tends to only display half of the "---" line, mixing other lines into the middle of it in the display.

I'm running Tcl/Tk 8.5.7 on Windows (XP, 7 and Vista) but have had reports of the issue on other OSes, too, and at least one other version of Tcl/Tk. The elided text is key - without that, the issue doesn't appear. Anyone have any thoughts? Can this be replicated in newer (8.6) Tks?

(Now that I've finally narrowed it down, I've tested moving the elided text to the end of the line, and that seems to avoid the issue, whatever it is.)


beware - I'm probably being stupid here.

clock scan "01/01/1900" -format %d/%M/%Y
# -> 1333234800
clock format 1333234800 -format %d/%M/%Y
# -> 01/00/2012
clock format 1333234800 -format %d/%M/%G
# -> 01/00/2012
clock scan "01/01/1900" -format %d/%M/%G
# -> 1333234800

How do I either make clock scan give me the correct number for 1st Jan 1900, or make clock format use the given number properly?

I'm using timebox to display/choose dates, and need to set its default.

RLE (2012-04-02) It appears you may have found a bug:

% clock format -2208970800
Mon Jan 01 00:00:00 EST 1900

From the clock manpage:

  • The clock scan command accepts times that are formatted as strings and converts them to counts of seconds from the epoch time of 1 January 1970, 00:00 UTC.

Second zero is 1 Jan 1970, 00:00 UTC, so scanning a date from 1900 should return a negative clock value. Given that it does not, you might think about filing a bug report. Note that I found the EST value above by trial and error. You can repeat your own trial and error to find whatever base value you want.

beware I was and was not being stupid... %M is minutes. I should have been using %m for month. This now returns a negative number. However it appears timebox isn't interpreting it right.

A few hours later - timebox uses string is digit instead of string is integer, so it rejects negative dates.

RLE (2012-04-03) Do you have the source for timebox? Just change it from string is digit to string is integer.


JBR - I'm trying to use tcom to interface to a vendor provided object to configure and read out image data from a custom detector. I can use the simple COM methods that take simple parameters but not the one which is intended to return a data array. I'm "allocating" the data as a bytearray with binary format and passing it by name to the tcom method. The buffer parameter is declared in COM as:

 {{in out} {SAFEARRAY(UI2) *} targetArray}

Here is my test code:

 set size 20000
 set pixl 10000

 set buffer [binary format A$size "\000"]
 puts [$com ReadScienceData $card $pixl buffer]

The result is:

 Failed - Buffer insufficient to store 10000

So it seems that I'm not successfully passing the buffer.

Thanks, John

JBR - I've looked in the tcom source and it seems that the Tcl bytearray is only passed to a SAFEARRAY of type UI1, otherwise some fancy list of lists conversion is attempted. Thats too bad.


JBR - If I call Tcl_EvalObjEx(interp, body, 0); how do I control the interpreter stack level where the body is evaluated?

  ie How can I "uplevel" in C code?

IE automation with tcom

contents moved to IE automation with tcom


photo put query

Beware With photo put, we can specify a list of colours (or a list of lists) to write the pixels of an image. But without checking each pixel first, is there a way to specify transparency in that list of lists so that we don't overwrite what's already there? I don't really mean transparency I guess, I mean can we add a list of lists of pixel colours where some of them aren't set?

AMG: Sounds like you want to merge one image with another. Try [photo copy]. The default -compositingrule is overlay, where the transparent pixels in the new image do not replace the opaque pixels in the old image.


The old binary format

Everett This sounds like an urban legend but I'll verify it by asking the old timers to enlighten me with some of their knowledge. I read recently that it was much faster to access data saved in a binary file than in a regular text file. Is this true? Why is it so? My second question is how to save a txt file in a binary format. Tx for the advice and info.

AMG: Normally speed isn't the driving concern when choosing file formats. It's more important to have a file format that's easy to access and maintain, for instance with configuration management systems. Use text when possible. However, there are many cases where text formats are cumbersome or would take too much space; examples include sound, images, and video. Additionally, due to the possibility for fixed-sized record structures, binary file formats may be easier to index for random access, which may be important for real-time applications. Use the [time] command to profile performance. I think you'll find in most cases that binary formats don't offer significant performance advantages.

To use a binary format, use the [binary format] and [binary scan] commands. [binary format] generates a binary string which can be written out to a file or network socket, and [binary scan] interprets a formatted binary string which came in from disk or the network. See the linked pages for examples on their use.

Your second question, "how to save a txt file in a binary format," suggests to me that you might actually be asking about the "b" or "BINARY" options to the [open] command, or the equivalent "-translation binary" option to the [fconfigure] or [chan configure] commands. You probably don't want those unless you really are working with a binary format, as described above. If you're dealing with text, don't turn on binary mode, or you might wind up with carriage returns or garbled encodings in your strings. Correctness is far more important than speed!


Binary file naming and and formatting

Benny I have a very similar question in fact, it is also related to binary files. Say I am working on a txt file opened on screen (It has a txt extension) and I'd like to make a copy of the contents of the file on screen but in a second file that would be a binary file. This is what I'd like. Say the name of the file is c://Benny's Docs 1//Ragtime.txt. I am reading it on my screen with my Tcl-tk editor. I want to be able to write a command that will do this:

  • a) It will take the name of the path of the command opened on screen. Say: c://Benny's Docs 1 or c://Benny's marks 1
  • b) It will put a 2 to replace the 1 at the end of the directory. Say: c://Benny's Docs 1 becomes c://Benny's Docs 2 and c://Benny's marks 1 becomes c://Benny's marks 2
  • c) It will save the contents of the file on the screen but into a binary file and the extension would be changed. Say: c://Benny's Docs 2//Ragtime.bin or c://Benny's marks 2//Ragtime.bin.

In other words I want the file to be called the same name as the file on screen but with a different extension (A bin extension instead of a txt extension) and I want the number of the directory to be changed from 1 to 2.

How do I proceed? Thanks!

AMG: The extension on a file is just a name, that's all it is. Changing the name doesn't change the file. If you want to alter the way the content of the file is formatted, you have to write code that does so.

To increment a trailing number at the end of a path component, you must first find the substring that is the number, then replace that substring with one plus that number. [regexp] can help you find the substring. Also, [file split] splits a path into components.

Not sure why you're doubling the slashes... perhaps you're thinking of backslashes, which often need to be doubled to inhibit their special quoting and substitution properties. Forward slashes work fine as-is.

Here's a bit of code that does some of what you ask:

set name "c://Benny's Docs 2//Ragtime.txt"
set lastdir [lindex [file split $name] end-1]
if {[regexp -indices {\d+$} $lastdir indices]} {
    set value [expr {[string range $lastdir {*}$indices] + 1}]
    set lastdir [string replace $lastdir {*}$indices $value]
    set path [lreplace [file split $name] end-1 end-1 $lastdir]
    file mkdir [file join [lrange $path 0 end-1]]
    set name [file rootname [file join $path]].bin
}

It replaces the "2" with a "3" and the ".txt" with ".bin", it makes the new directory, and it updates $name to contain the new filename with path. You still have to write code to open the file and put in whatever data you want, in whatever format you want.

RFox I'm kind of missing the point. Actually all files are binary. What makes a file text is the interpretation of the binary bits in the file as characters in some encoding (e.g. ASCII or UTF-8, or UTF-16 etc.). So if you want to copy a 'text' file to a 'binary' file just use whatever copy utility the operating system gave you.


breddy - 2012-02-01 10:19:32

i want complete tcl code to make r to implement a project on examination management system.. m.id is [email protected]

AMG: Your English is a little unclear to me. Are you asking about R? Or are you just asking about how to compile Tcl code? Tcl code gets compiled during execution, so there's no need to compile it ahead of time. Perhaps what you want is a way to package up a collection of Tcl code into a single executable binary. For that, see Starpack or Freewrap.


Tosner - 2012-02-13 14:09:01

Problem using FFTW within Tcl C procedure

I am having problems with FFTW library: my program, written in C, creates Tcl inperpreter and a new command (created using Tcl_CreateObjCommand) calling fftw_execute. I get segmentation fault as fftw_execute starts. Everything works, however, when I call fftw functions directly from the main C program. Everything also works when I run it through valgrind... Gratefull for any comments and suggestions.

AMG: What versions of Tcl and FFTW are you using? Also, please give us a backtrace. You can use gdb on the core file to see where things broke, then use the backtrace command to dump the call stack that existed at the fatal instant. You might need to recompile Tcl with --enable-symbols to get a useful backtrace.

Tosner: Sometimes it is enough to rise a question... Thanks for the hint with gdb. My problem originated on windows where I compiled FFTW myself using MinGW. Then I tested the same thing on linux and my program also crashed. So I put my question here as it looked to me as a general problem. But it turned out later that the crash was due to another (also obscure to me) reason. So I prepared another, much simpler program combining Tcl and FFTW and it worked nicely on linux. Going back on windows, I used precompiled FFTW library and that solved my problem!


Googie - 2012-03-14 After a lecture of GSoC Idea: Parser For expr Command I wonder if using square brackets expression inside of expr expression is optimal, because of Tcl parser used inside of expr expression. Should I use

set len [llength $arg]
return [expr {$len * 2}]

rather then

return [expr {[llength $arg] * 2}]

? After some tests with the time command I find second form much faster, but it conflicts with the lecture I mentioned above. Can anyone explain it? Is executing one more command and allocating new object that expensive in resources, that extracting llength out of expr is not worth it?

AMG: Script substitution within an [expr] expression is only a problem if you don't brace your expr-essions. One of the discussions on GSoC Idea: Parser For expr Command concerns removing $ prefixes from variables within expressions partly in order to avoid the requirement that expressions be braced, but that only solves part of the problem plus adds numerous conflicts, e.g. array indexing and difficulty accessing variable with weird names. With the current [expr], definitely brace your expressions, and don't worry about embedding script substitution. The Tcl parser will be called either way, so only factor out your substitution if it makes your code clearer in an important way or if you want to refer back to the result multiple times.