Skip Menu |

This queue is for tickets about the Tk CPAN distribution.

Report information
The Basics
Id: 39343
Status: resolved
Priority: 0/
Queue: Tk

People
Owner: Nobody in particular
Requestors: thundergnat [...] gmail.com
Cc:
AdminCc:

Bug Information
Severity: Normal
Broken in:
  • 804.027
  • 804.027_500
  • 804.027_501
  • 804.027_502
  • 804.028
Fixed in: (no value)



Subject: Skips lines when arrowing down in a window not exactly sized to a text line
If you resize a Text widget (or a derivation) so that the bottom of the window is NOT exactly at the bottom of a line of text, and then try to move the cursor down past the bottom of the text displayed in the window using the arrow key, the cursor advances two lines instead of one. It doesn't seem to matter whether the text widget is scrolled or not and is independent of the font & font size. OS independent. In 804.028 Tk::Text version 4.026 sub UpDownLine. Line 1205 reads: ($ly + $lh) > ( $w->height - 2*$w->cget(-bd) - 2*$w->cget(-highlightthickness) ) ) #Check if last line y position plus line height is greater than visible #window height (window height - decorations and borders) But it really should be checking if it is greater than the visible height minus any fraction of a line. Modifying the line to read: ($ly + $lh) > ( $w->height - 2*$w->cget(-bd) - 2*$w->cget(-highlightthickness) - $lh + 1) ) fixes the problem without any repercussions that I can see. Patch file attached. Here is a short script with a locally modified UpDownLine to demonstrate. Run the script. Put the cursor at the bottom of the file, then arrow down. The unmodified Text advances 2 lines at a time. ************************************************************* #!/usr/bin/perl {####################################################################### package FixedText; use base qw(Tk::Text); Construct Tk::Widget 'FixedText'; sub UpDownLine { my ($w,$n) = @_; $w->see('insert'); my $i = $w->index('insert'); my ($line,$char) = split(/\./,$i); my $testX; #used to check the "new" position my $testY; #used to check the "new" position (my $bx, my $by, my $bw, my $bh) = $w->bbox($i); (my $lx, my $ly, my $lw, my $lh) = $w->dlineinfo($i); if ( ($n == -1) and ($by <= $bh) ) { #On first display line.. so scroll up and recalculate.. $w->yview('scroll', -1, 'units'); unless (($w->yview)[0]) { #first line of entire text - keep same position. return $i; } ($bx, $by, $bw, $bh) = $w->bbox($i); ($lx, $ly, $lw, $lh) = $w->dlineinfo($i); } elsif ( ($n == 1) and ($ly + $lh) > ( $w->height - 2*$w->cget(-bd) - 2*$w->cget(-highlightthickness) - $lh + 1) ) { #On last display line.. so scroll down and recalculate.. $w->yview('scroll', 1, 'units'); ($bx, $by, $bw, $bh) = $w->bbox($i); ($lx, $ly, $lw, $lh) = $w->dlineinfo($i); } # Calculate the vertical position of the next display line my $Yoffset = 0; $Yoffset = $by - $ly + 1 if ($n== -1); $Yoffset = $ly + $lh + 1 - $by if ($n == 1); $Yoffset*=$n; $testY = $by + $Yoffset; # Save the original 'x' position of the insert cursor if: # 1. This is the first time through -- or -- # 2. The insert cursor position has changed from the previous # time the up or down key was pressed -- or -- # 3. The cursor has reached the beginning or end of the widget. { no warnings 'uninitialized'; if (not defined $w->{'origx'} or ($w->{'lastindex'} != $i) ) { $w->{'origx'} = $bx; } } # Try to keep the same column if possible $testX = $w->{'origx'}; # Get the coordinates of the possible new position my $testindex = $w->index('@'.$testX.','.$testY ); $w->see($testindex); my ($nx,$ny,$nw,$nh) = $w->bbox($testindex); # Which side of the character should we position the cursor - # mainly for a proportional font if ($testX > $nx+$nw/2) { $testX = $nx+$nw+1; } my $newindex = $w->index('@'.$testX.','.$testY ); if ( $w->compare($newindex,'==','end - 1 char') and ($ny == $ly ) ) { # Then we are trying to the 'end' of the text from # the same display line - don't do that return $i; } $w->{'lastindex'} = $newindex; $w->see($newindex); return $newindex; } 1; }############################################################################### use strict; use warnings; use Tk; my $w1 = MainWindow->new; my $t1 = $w1->Text->pack( -expand =>1, -fill => 'both' ); $w1->title('Original UpDownLine'); $t1->insert('end',"$_\n") for (1..100); my $w2 = MainWindow->new; my $t2 = $w2->FixedText->pack( -expand =>1, -fill => 'both' ); $w2->title('Modified UpDownLine'); $t2->insert('end',"$_\n") for (1..100); $w1->update; my $geometry = $w1->geometry; my ($width,$height,$x,$y) = split/[x+]/,$geometry; $height += 8; $width /= 2; $geometry = $width.'x'.$height."+$x+$y"; $w1->geometry($geometry); $x += $width+10; $geometry = $width.'x'.$height."+$x+$y"; $w2->geometry($geometry); MainLoop;
Subject: textdiff
Download textdiff
application/octet-stream 494b

Message body not shown because it is not plain text.

Thanks, applied to the svn repo at https://svn.perl.org/modules/Tk/trunk, change 11809. Regards, Slaven