Skip Menu | You are currently an anonymous guest. | Login | Return to Main | About rt.cpan.org
 

Please report any issues with rt.cpan.org to rt-cpan-admin@bestpractical.com.

X Report information
Id: 39343
Status: resolved
Left: 0 min
Priority: 0/0
Queue: Tk

Owner: Nobody
Requestors: thundergnat <thundergnat [...] gmail.com>
Cc:
AdminCc:

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




X History Display mode: Brief headersFull headers
#   Tue Sep 16 20:15:49 2008 thundergnat - Ticket created  
Subject: Skips lines when arrowing down in a window not exactly sized to a text line
[text/plain 4.3k]
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

[application/octet-stream 494b]
Message body not shown because it is too large or is not plain text.
#   Thu Sep 18 02:57:11 2008 SREZIC - Correspondence added  
[text/plain 109b]
Thanks, applied to the svn repo at
https://svn.perl.org/modules/Tk/trunk, change 11809.

Regards,
Slaven

#   Thu Sep 18 02:57:13 2008 RT_System - Status changed from 'new' to 'open'  
#   Thu Sep 18 02:57:14 2008 SREZIC - Status changed from 'open' to 'resolved'