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

Hi,

I have a GUI with a text window, in which I sometimes want to delete a chunk of text and insert different text in its place. I'm using something like this:
$text->delete($start_index,$end_index); $text->insert($start_index,$my_new_text);
(Both $start_index and $end_index always look like '###.0'.)

This works fine as long as $end_index is somewhere in the middle of the whole text. However, if $end_index is actually the same as 'end',
the new text isn't inserted after a newline, but rather at the end of the previous line.

Is there a way to prevent this? (Other than checking if I'm inserting text in the end, and then adding a newline myself...)

Here is a sample code that I wrote to demonstrate the problem:
use strict; use Tk; my $mw = MainWindow->new(); my $frame = $mw->Frame() ->pack(-side => "left", -expand => 1, -fill => 'both'); my $text = $frame->Scrolled('Text') ->pack(-expand => 1, -fill => 'both'); my $data; for (my $i = 1; $i < 20; $i++) { $data .= "abcdefghi $i \n"; } $text->insert('end',$data); my $but1 = $frame->Button(-text => "Replace in the middle", -command => [\&replace,$text,'3.0','7.0']) ->pack(-side => 'left'); my $but2 = $frame->Button(-text => "Replace in the end", -command => [\&replace,$text,'16.0','end']) ->pack(-side => 'left'); MainLoop(); sub replace { my ($text,$start_index,$end_index) = @_; my $old_data = $text->get($start_index,$end_index); $old_data =~ s/cdefg/12345/g; $text->delete($start_index,$end_index); $text->insert($start_index,$old_data); return; }
Thanks a lot!

Replies are listed 'Best First'.
Re: Indices and inserts in Tk::Text
by zentara (Cardinal) on Nov 27, 2008 at 16:43 UTC
    No, it's not a bug in Tk, but the way the Text widget works...it always adds a newline at the end of text, so you need to strip it when doing indices. A fix for your code is (and notice double quotes around end - 1c)
    my $but2 = $frame->Button(-text => "Replace in the end", -command => [\&replace,$text,'16.0', "end - 1c" ]) ->pack(-side => 'left');
    This shows the empty text problem more clearly:
    #!/usr/bin/perl use warnings; use strict; use Tk; my $mw = MainWindow->new; my $text = $mw->Text->pack; my $bFrame = $mw->Frame->pack(qw/-side bottom/); $bFrame->Button( -text => "Check Text", -command => sub { if ($text->index('end - 1c') == 1) { print "Text is empty\n"; } else { print "Text contains data\n"; } })->pack(qw/-side left/); $bFrame->Button( -text => "Clear Text", -command => sub { $text->delete("1.0", 'end'); })->pack(qw/-side left/); MainLoop;

    I'm not really a human, but I play one on earth Remember How Lucky You Are

      Lets call it an intentional bug then. Or at least it is a huge inconsistency. If you change the sub in anna_blacks program to:

      sub replace { my ($text,$start_index,$end_index) = @_; my $old_data = $text->get($start_index,$end_index); print "<$old_data>\n"; $old_data =~ s/cdefg/12345/g; $text->delete($start_index,$end_index); $text->insert($start_index,$old_data); my $old_data = $text->get('3.0',$end_index); print "<$old_data>\n"; return; }

      ... you can see that the insert started one char too early.

      It could be argued that you should not insert into lines that don't exist (i.e. after the delete of all lines starting from line 16 the location 16.0 doesn't really exist anymore). But then your 'end-1c' solution would be illegal as well, and it only works because the additional \n is confused with the \n of not-existant line 16.

      If TK inserts spurious characters it is its job to make sure that those characters don't get in the way of the programmer.

      PS: Why double quotes? They don't do anything different than a single quote here.

      UPDATE: changed 2 sentences
        Oh, you are right about the double quotes not making a difference.

        As far as it being a bug or not, that is left up to you, all I'm saying is that is the way it works. There are alot of complicated interactions in the predefined subs in the Tk::Text module, that break expected behavior when changing or overriding them. I'm sure that if you redine 'end', that somwhere it will break some other method. File a bug report if you want.


        I'm not really a human, but I play one on earth Remember How Lucky You Are
Re: Indices and inserts in Tk::Text
by jethro (Monsignor) on Nov 27, 2008 at 15:37 UTC
    Looks like a bug in tk. You might check if there is a newer version available and if not, alert the author. Then either patch or update your version or circumvent the bug.