Takamoto has asked for the wisdom of the Perl Monks concerning the following question:

Dear Monks

May I assue that Tk chooseDirectory is faulty with Unicode paths on Windows?

My assumption is based on the following observation: on the same Windows 10 (Perl 5.26.1) machine the following scripts returns different paths. With getOpenFile and getSaveFile, the paths - even with unicode characters (chinese and so on) - are okay. I can use them to do things (open file, save it, etc.). The path returned by chooseDirectory is unusable (????). I read quite a lot about chooseDirectory and Unicode on this form, POD and so on. However, never found a working solution to get a usable path from chooseDirectory. Notice that my script has to work on potentially any Windows machine, irrespective of its way to encode paths. What do you think?

use Tk; use strict; use warnings; my $mw = MainWindow->new; my $menubar = $mw->Menu(-type => 'menubar'); $mw->configure(-menu => $menubar); my $mfile = $menubar->cascade(-label => '~File', -tearoff => 0); $mfile->command(-label => '~Open', -accelerator => 'Control+o', -command => \&open_file); $mfile->command(-label => '~Save', -accelerator => 'Control+s', -command => \&save_file); $mfile->command(-label => '~Select Dir', -accelerator => 'Control+d', -command => \&select_dir); my $exit = $mw->Button(-text => 'Exit', -command => [$mw => 'destroy']); $mw->bind('<Control-o>', [\&open_file]); $mw->bind('<Control-s>', [\&save_file]); $mw->bind('<Control-d>', [\&select_dir]); $exit->pack; my $types = [ ['Perl files', '.pl'], ['All Files', '*'],]; MainLoop; sub open_file { my $open = $mw->getOpenFile(-filetypes => $types, -defaultextension => '.pl'); print qq{You chose to open "$open"\n} if $open; } sub save_file { my $save = $mw->getSaveFile(-filetypes => $types, -initialfile => 'test', -defaultextension => '.pl'); print qq{You chose to save as "$save"\n} if $save; } sub select_dir { my $DirSelected = $mw->chooseDirectory(-initialdir => "~", -title +=> 'Choose directory to save your backup'); print qq{You chose to save as "$DirSelected"\n} if $DirSelected; }

Update

I just moved to a Chinese machine with a Chinese username. Well, here even getOpenFile/getSaveFile fail. Windows fires an error message saying that the path does not exist (with ??? in place of the user's name).

Replies are listed 'Best First'.
Re: Tk unicode paths chooseDirectory vs getOpenFile and getSaveFile
by Lotus1 (Vicar) on Mar 04, 2019 at 14:26 UTC
     my $DirSelected = $mw->chooseDirectory(-initialdir => "~",

    Since you said you are using a Windows machine the first thing I would try is to replace "~" with a test folder such as "c:/temp". If that works then try $ENV{HOME}.

    Update: The documentation for Tk::chooseDirectory mentions encoding issues with this method:

    Perl does not have a concept of encoded filesystems yet. This means that operations on filenames like opendir and open still use byte semantics. Tk however uses character semantics internally, which means that you can get filenames with the UTF-8 flag set in functions like chooseDirectory, getOpenFile and similar. It's the user's responsibility to determine the encoding of the underlying filesystem and convert the result into bytes, e.g.

    use Encode; ... my $dir = $mw->chooseDirectory; $dir = encode("windows-1252", $dir); opendir DIR, $dir or die $!; ...

      Thank you. I had already read what you posted. However, this does not solve the problem.

      What I am trying to point to in my post is that of two Tk methods, one is broken chooseDirectory for reading unicode paths, the other getOpenFile/getSaveFile seems to have no problem with unicode paths, even if in the POD of getOpenFile/getSaveFile there is a link See "CAVEATS" in Tk::chooseDirectory. I'd really much like to have some insights in what it seems to me a strange situation.

Re: Tk unicode paths chooseDirectory vs getOpenFile and getSaveFile
by vr (Curate) on Mar 04, 2019 at 17:37 UTC

    I don't have a solution, nor can comment on your latest update, but can only confirm: for me, getOpenFile returns correct utf8 path in all tests.

    chooseDirectory, for "ã" dir, returns plain Latin "a" as trailing path component, with utf8::is_utf8 being false. While, for "у" -- Cyrillic, qq(\x{443}) -- it returns utf8, but "ó". Weird and broken.

      No solution with Tk yet, but I conducted a little investigation, Prima on Windows suffers the same (or worse) issues with Unicode in paths returned from standard file/directory selection dialogs. But IUP appears to perform correctly in my tests:

      use strict; use warnings; use feature 'say'; binmode STDOUT, 'utf8'; use IUP ':all'; my $dlg = IUP::FileDlg-> new( DIALOGTYPE => 'OPEN' ); # try 'DIR' for +folder selection my $app = IUP::Dialog-> new( TITLE => 'Test', MARGIN => '10x10', GAP = +> 10, child => IUP::Vbox-> new([ IUP::Button-> new( TITLE => 'Select', PADDING => '10x10', ACTI +ON => sub { $dlg-> Popup; if ( $dlg-> STATUS != -1 ) { say $dlg-> VALUE; } return IUP_DEFAULT }), ]), ); $app-> Show; IUP-> MainLoop;

      (Maybe consider this toolkit as replacement? :) Looks nice, and feature-rich and cross-platform, too.)

        Thank you for pointing me to IUP which I never heard of before. why it is never ever mentioned in connection to Perl and GUI?!? It looks very interesting! Unfortunately, in my case the (very big) application is based on Tk, and changing toolkit is not possible.

Re: Tk unicode paths chooseDirectory vs getOpenFile and getSaveFile
by Takamoto (Monk) on Mar 04, 2019 at 18:59 UTC

    To add a bit more on this chaos, your script works fine at least for getOpenFile/getSaveFile and Unicode paths on Windows 10 running ActivePerl 5.16 while it fires the error you mentioned on Strawberry Perl 5.28. I have the latest Tk installed. In my humble opinion, Tk is broken as far as communicating with the Windows system is concerned. Which is a shame, because Perl Unicode support is good!