Version 31 of Ask, and it shall be given # 13

Updated 2020-02-25 17:21:11 by Busirane

How to post on this page

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



This page runs the risk of being deleted and corrupted. Please be very careful when editing it. If you inadvertently delete it, immediately revert your edit using the History link on the left side of this page.

Do NOT attempt to restore it by copying and pasting the text from a previous revision, or all page formatting will be lost!

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

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

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

You might also simply want to put a hyperlink leading to a page of the wiki where your question is included. This will save you the trouble of cutting your question to an existing page afterwards.

Put your question below. Thanks!

Questions


Continue script eval at point after error?

JJS 2020-Feb-02 I'm using a safe interp to parse config files; they're user-prepared so they can't be trusted. They consist of commands, some of which may be bad in the sense that they throw errors. I'd like to ignore the bad commands, but continue evaluating any following good commands. I tried variations of this, both in the master and the slave interp, but couldn't get what I want:

try {$interp eval $script} on error {res opt} { ;# or try $script ...
    return -code continue -level 0 ;# tried all combos of -code ok/continue and -level 0/1
}

Nothing I tried would continue with the eval. My bgerror handler never fired. I finally used a variation of the Verbose Evaluation code at eval. It works pretty well, but fails for scripts like {good; bad; good} with multiple commands on one line. Is there a way to ignore errors in a script *and* continue evaluating it?

P.S. I've taken to "Ask, and it shall be given" because I no longer have work access to chat or c.l.t.


90 second delay deleting file on unix

JJS 2019-Nov-12 Background: I have a Starpack that invokes itself for self-test purposes. On Windows the mounted VFS only shadows the application binary from Tcl's point of view, not in the actual underlying filesystem, so [exec [info nameofexecutable]] or even [exec [file dirname $argv0]] works. Interestingly, the same approach also works in a Red Hat VM under Oracle VirtualBox on a Windows host with file sharing enabled. But in Ubuntu under Windows Subsystem for Linux (WSL) the mounted VFS actually shadows the application binary, so I adapted the clonerun technique to temporarily unmount the VFS so I can make a copy that I can then execute:

proc clone {del args} {
    set testcopy testcopy.exe ;# works for windows or unix
    # Unmount the VFS so the app is exposed in the native filesystem.
    # Adapted from <http://wiki.tcl.tk/14945>.
    set me [info nameofexecutable]
    set info [vfs::filesystem info $me]
    vfs::filesystem unmount $me; puts "unmounted"
    catch {file copy -force $me $testcopy; puts "copied"}
    vfs::filesystem mount $me $info; puts "remounted"
    if {[file exists $testcopy] && [file executable $testcopy]} {
        puts "running"; exec $testcopy {*}$args
        if {$del} {puts "deleting"; time {file delete -force $testcopy}}
    }
}

That code unmounts the VFS, copies the binary, remounts the VFS, invokes the copy with optional arguments, waits for it to complete, then optionally deletes it. If I run a clone without deleting it, then as soon as the prompt returns I can delete it right away; the delete command was staged on the clipboard so it could be entered very quickly:

(tst) 7 % clone 0 final
unmounted
copied
remounted
running
(tst) 8 % puts "deleting"; time {file delete -force testcopy.exe}
deleting
1097152 microseconds per iteration

As you can see, it took about 1 second to delete the copy, only 1 or 2 seconds after it completed. But if I run a clone and delete it within the clone call, then it takes 88 seconds or so to delete:

(tst) 9 % clone 1 final
unmounted
copied
remounted
running
deleting
88498207 microseconds per iteration

There are a lot of moving parts here: Starpack, VFS, Windows vs. Linux, and TkCon, to name a few, but I can't put my finger on any of them. I've tried things like [update] or [update idletasks] before the delete; delaying it with [after idle], etc., but nothing works reliably. While debugging this problem and trying various fixes, I sometimes get into a situation where deleting the copy from within [clone] goes fast, but I can never tell what triggers it, and it doesn't last through restarting the debugging environment! I especially don't understand why returning to the prompt allows the delete to proceed immediately, but nothing else does. What could be going on here?


MacOS tk send question

Wurzelsepp 2019-Oct-14

I have Activestate tcl installed on a Mac. I tried to use the "rmt" remote commander, but the only app it shows is just itself.

Is there anything special that tcl/tk apps need to be visible


Odd tcom problem

robertlipman 2019-Jul-11 I have a program that I wrap with Tcl Dev Kit. Two Windows versions of the program are created, one with Tk that has a user interface and the other with Tcl that is run from a command prompt. tcom is used to create an object with

set objIFCsvr [::tcom::ref createobject IFCsvr.R300] 

When the object is created, some startup text is generated by IFCsvr.R300 that is displayed in the command prompt window version. I'd like to capture that text in a variable so that it can be processed or suppressed. In the GUI version, I don't know where that startup text from IFCsvr.R300 goes. Again, I'd like to capture it in a variable and process it.

How do I do that?


Windows auto_execok search path irregularity

Duoas 2019-Jul-05 I just had to debug a surprising behavior by auto_execok on Windows: apparently it injects the following paths (if available) to the head of the search path:

  • [info nameof]
  • .
  • %WINDIR%/system32
  • %WINDIR%/system
  • %WINDIR%

This is not correct! Especially injecting the interpreter’s directory before the current working directory in the search path! According to Windows documentation , the correct search path is [pwd] + %PATH%. All those Windows directory additions are also unnecessary; they should normally be in the user's PATH; if they are not it is either a conscious user choice or a user error; being Windows does not justify jumping the path to prefer a Windows program over a user program. This is especially irksome to anyone who (rightly) presumes to control his environment by controlling the PATH!

How long has this been an issue? Can it be corrected? Would something break if the core were corrected? (As it is, I have to code an alternate auto_execok so that my application does not violate the Principle of Least Surprise for my users.)

The offending code is somewhere around lines 670-680 in tcl8.6.7/library/init.tcl, and could be corrected by replacing that section with just

    set path ".;"

It is not unreasonable to find multiple copies of a same-named executable in the path. The path exists to control which one of those executables is loaded when asked, given ambiguity.


open a command pipeline

Wurzelsepp These examples work:

  set f [open "| ls existing_file" r]
  set f [open "| ls missing_file" r]

However, when I try

  set f [open "| ls &" r]

I just find out that there is no "&" file... So, how could I open a slow command in the background? I cannot use exec here. Thanks

EMJ 01 Jun 2019 : Neither exec nor open (with pipeline) use any external shell to process the command, Tcl does that itself. So exec checks for an & as the last element of the command, but open does not because it does not need to - the pipeline is run asynchronously anyway, in one or more separate processes - you can get the process id(s) with the pid command. You might want to look at How to run external script from Tk and make it throw output to the console? - if not using Tk you'll need vwait to get your own event loop if you go with using fileevent. There's also async.

Wurzelsepp Hi, many thanks for the prompt response. The open (or rather its associated close) seems to wait...

  set f [open "|tclsh" w]
  puts $f "exec sleep 100; puts done"
  close $f; ## waits until sleep is over

(EMJ As the close man page says,

If channelId is a blocking channel for a command pipeline then close waits for the child processes to complete.

so you would have to make it non-blocking.)

I tried something I found on the exec manual page, near "reflected channels", using chan pipe (EMJ - exec Wiki page presumably, the exec manual page doesn't mention reflected channels). This seems to do what I want

  lassign [chan pipe] rdc wrc
  exec tclsh <@ $rdc &
  puts $wrc "exec sleep 100; puts done"
  close $wrc; ## returns at once

BTW, this is meant to be called from wish, and I assume that Linux, Win and Mac systems will run a tclsh that matches the active wish - EMJ Under normal circumstances, yes.


flowchart_text_extraction

gold26Dec2018. Can someone point some refs or post some freeware TCL code on <flowchart_text_extraction> or automated outline of nodes and procs from TCL program, for loading flowchart nodes/outline into the TKpaint.tcl or wheelDiagram.tcl uniquename? An alternate method would be loading a <flowchart_text_extraction> from TCL program into spreadsheet charting tool (OpenOffice.odp? for VU-graphs). I have been using the TKpaint.tcl (freeware) for about ten years for displays and vu-graphs on this TCL-WIKI. TKpaint.tcl has the advantage of saving VU-graph in postscript, readable TCL format, and restarting from a saved chart in TCL format. Possibly, the <flowchart text extraction> could be readable as a saved chart in TKpaint.tcl. I have made 1st test chart from the ASED.tcl editor, 2nd homebrew freehand chart, and both are pretty close to where I would like to start. In opinion, my current wiki pages of guis etc would be more understandable with a flowchart. Thanks.


gold 4Jan2019. Follow-on code to <flowchart_text_extraction>

    # wish to grab title of proc and entries of proc into a list(S) < proc geoseries> and <argumemts aa bb cc >to
    # code into flowchart diagram. but not good on regexp topic. Can one break on the braces?
    # need to get rid of braces in print out
set item { proc geoseries1 {aa bb cc} { if {$bb <= -1||$bb >= 1} { return 0} ;return [ expr $aa / ( 1 - $bb ) ]};  } 
    regexp {proc((.??.*)\})(.*)}  $matched matched2 sub1 sub2 sub3
    puts $matched        
    puts $sub1          
    puts $sub2          
    puts $sub3   
    proc geoseries1 {aa bb cc}
 geoseries1 {aa bb cc}
 geoseries1 {aa bb cc
# need to get rid of braces in print out

old wiki content

gold 1dec2018. Is the link for the old wiki content https://oldwiki.tcl-lang.org , still active? If not, what date was it closed? I am clumsy on the browser, but i can not find the old content link. thank you.

Unwanted border around ttk::label

Duoas 2018-10-22 Hello again. I can't figure out how to get rid of a border around a ttk::label. Steps to reproduce:

set image [image create photo]
$image put green -to 0 0 20 20
ttk::label .i -compound image -image $image -background red
place .i -x 10 -y 10

Is there any way to get rid of that red?

Duoas 2018-10-22 19:54Z Heh, always after asking questions you figure out an answer... Gotta configure the layout to get rid of it.

ttk::style layout TMyImageLabel {Label.label -sticky nswe}
.i configure -style TMyImageLabel

All better. :O)

Intercept/Observe command-line -geometry

Duoas 2018-10-16 Hey there. Is there any way to intercept/observe the processing of -geometry arguments at the command line when wish (tclkit) starts, not involving binary extensions or hacking the core?

I would like to permit multiple -geometry options to manage multiple windows (order/matching windows does not matter — they appear as clones). I can query the last supplied geometry with $::geometry, of course. I’ve tried both traces and pkgIndex.tcl trickery, but the Initialize() function in ~/generic/tkWindow.c appears to get called before any kind of user code gets a chance. Is this correct? Am I out of luck here?

If it makes any difference I am packaging in a starkit.

bll 2018-10-16 I think you will have to have the user put the -geometry arguments on the command line after a -- argument and process them yourself. There's no way to have wish do unusual things with its command line arguments.

Duoas 2018-10-22 I have always thought that wish’s gobbling of command-line arguments without any hook for application intervention to be unusual. Only now that I am looking at this again (after many years) do I remember that I had, in fact, looked at this before. And no, there is no escape, so bll’s commentary is correct. The only options are:

  • modify Tk sources and recompile
  • start the application using a loader, which massages the command-line arguments into something Tk won’t gobble.

Alas.

<<Selection>> event for entry

Hi, has anyone written a script to add selection events like those for text widget to a one-line entry? (Or should I simply create a 1-line text instead?)

Hex String to Double

beware Hi all, I'm trying to decode some files. One of the values I need is stored as a double in hex. Example - "3fb999999999999a" -> "0.1". The double conversion here gets the correct result: https://gregstoll.dyndns.org/~gregstoll/floattohex/ currently my code just has the hex stored as a string (as in "set hexstr 3fb999999999999a"). How do I replicate the conversion done on that site?

Martyn Smith The TCL command is binary, you need to convert the hexadecimal string to a binary string with binary format then extract the big endian double from the binary string as follows

  binary scan [binary format H* $hexstr] Q floatValue

The Q is the format code for forced big endian double.

Google Photos

Has anyone written a tcl library that interfaces with Google Photos to allow one to download a "table of contents" of URLs to images and the albums to which they belong?

Image Scaling

MiR 2018-06-28:

On topic image scaling...

I was wondering, if Tk would in the future implement at least a robust image scaling alogrithm like in TkImageTools from (reference see Shrinking an image)? It's just to avoid having to deploy an externel dynamic library just to have an image resized...

AMG I did this just yesterday, but I'm probably not allowed to share the code though. I used libsamplerate [L1 ] to do it. The interface works like this:

[imgscale sourcePhoto targetPhoto ?method?]

sourcePhoto and targetPhoto can be one-, three-, or five-element lists:

photoName
operate on full extents of photo
photoName width height
explicit width and height, top left defaults to (0,0)
photoName left top width height
explicit width, height, and top left coordinates

targetPhoto will be expanded (if possible) to accommodate the explicit width and height. Otherwise, the width and height are clipped to the photos' actual width and height. It is an error for left or top to be negative, or for width or height to be non-positive.

method can be sinc, linear, or point, corresponding to libsamplerate's SRC_SINC_FASTEST, SRC_LINEAR, and SRC_ZERO_ORDER_HOLD modes, respectively. (The other two SINC modes are significantly slower and actually look comparatively poor on images.) The default is linear.

Implementation guidelines:

  • Use the Simple API [L2 ] which consists of only the src_simple() function. The more complicated APIs offer no benefit in this application because the image data is all available in advance.
  • Work on one channel (R, G, B, A) at a time. This requires less temporary space and offers better performance due to improved locality of reference and ability to use more optimized single-channel code within libsamplerate.
  • Step 1: Loop over each row of input R, G, B, or A bytes.
  • Step 1a: Convert the input row into a linear buffer of floats.
  • Step 1b: Rescale the width and store into an intermediate float buffer large enough to hold the whole channel.
  • Step 2: Transpose the intermediate buffer so that each column is contiguous in memory.
  • Step 3: Loop over each column of intermediate floats.
  • Step 3a: Rescale the height and store into a linear buffer of floats.
  • Step 3b: Convert the scaled column back into pixel bytes, storing into a pixel buffer large enough for the whole image.
  • Step 4: Use Tk_PhotoPutBlock() to write the pixel buffer to the target photo.

Regarding step 4: The pixel buffer will be divided into separate planes, each of which is transposed. This means the Tk_PhotoImageBlock will have to be arranged as follows:

pitch = 1
pixelSize = height
offset[n] = n * height * width

One other tip. I statically linked libsamplerate into my extension. Another possibility is to incorporate a subset of the source code, removing the unused SINC modes, to avoid their large coefficient tables. (BSD 2-clause license, by the way.)

Duoas 2018-10-19 Actually, was just working on a small binary extension to do the same thing, photo-resample.kit. Permits scaling using nearest neighbor, linear, cubic, box, and hqx algorithms, plus mirror and rotate, plus a few other resampling goodies like sharpen, gaussian blur, colorizing, desaturating, inverting an image, splitting and combining channels and alpha channel manipulations, and origin tracking, all with a very simple interface.

filker0 2019-01-04 Is Duoas's photo-resample.kit available for download? I'm kind of out of touch, and maybe it's a well known location.