dk / Prima

prima.eu.org
Other
108 stars 27 forks source link

Word and text wrap can cause Prima to hang #24

Closed run4flat closed 9 years ago

run4flat commented 9 years ago

Here is a simple demonstration. Run this script and move the cursor to the right end of the space after test, and Prima will hang.

use strict;
use warnings;
use Prima qw(Edit Application);

my $w = Prima::MainWindow->new;
my $edit = $w->insert(Edit =>
    wordWrap => 1,
    cursorWrap => 1,
    text => "a test \nb\n",
);
my $text_width = $edit->get_text_width('test ');
$edit->width($text_width - 1);

run Prima;

The program hangs on line 1645 of Edit.pm, because text_wrap does not produce a chunk map entry for the location after the space at the end of the line.

This can probably be fixed by making sure that the while loop on line 1645 does not go out of the current paragraph ($$cm[$i+2] does not change) with something like this:

    my $j = $$cm[ $i + 2];
    while ( $x > $$cm[ $i] + $$cm[ $i + 1] and $$cm[ $i + 2] == $j) {
        $i+= 3;
        $y++;
    }
    $y--, $i-= 3 if $$cm[ $i + 2] != $j;

While this removes the hang, it leads to a situation in which the cursor does not get painted.

dk commented 9 years ago

I believe this should fix the problem, but as you rightly observed, at the expense of the cursor not being shown if positioned on the trailing space, and after it. I agree that it is not optimal, but this is an easy fix; the fully correct solution should account for this specific case, because text_wrap eats trailing spaces, and either provide a fake extra line or make an automatic horizontal scroll .

run4flat commented 9 years ago

Yeah, I agree that this is good enough for preventing the infinite loop. However, the behavior can still be rather odd in ways. For example, change the text to "a test \nmore text\n". Then, the cursor is drawn in the next line because the loop incorrectly picks out the location on the next line. Keeping track of the current $j prevents that. Then it comes down to properly drawing the vertical cursor line in that edge case.

dk commented 9 years ago

Yes, thanks, I somehow missed $j problem! I guess this version would nail it