Skip to content

Commit

Permalink
Handle coincident page marks better (#1277)
Browse files Browse the repository at this point in the history
The `ReplaceSelectionsWith` function handles keeping page marks
in approximately the same location when a Search/Replace
operation spans a page boundary (by maintaining the relative
proportion of text each side of the page boundary).

This did not cope correctly when there were two or more
page marks at the same location (i.e. blank pages). The page
marks could get reversed, so that 015 came before 014, for
example (although still both at the same location).

Avoiding changing the mark gravity (whether the mark goes
left or right of text inserted at the mark) fixes this for marks within
the S/R region. Temporarily setting "right" gravity for page marks
that immediately follow the S/R region keeps those page marks
correct.
  • Loading branch information
windymilla authored Nov 27, 2023
1 parent b877758 commit 26e3f25
Showing 1 changed file with 24 additions and 21 deletions.
45 changes: 24 additions & 21 deletions src/lib/Guiguts/TextUnicode.pm
Original file line number Diff line number Diff line change
Expand Up @@ -278,17 +278,19 @@ sub ReplaceSelectionsWith {
push( @lengths, $fmlen );
}

# Set gravity of page marker after string to "right" to keep it after string
# It doesn't matter if it's not immediately after - no harmful effect since restored later
my $end_mark = ""; # Assume there isn't one
# Find page markers immediately after string so we can set their gravity
# to "right" to keep them after string
my @endmarks = ();
$mark = $last;
while ( $mark = $w->markNext($mark) ) {
if ( $mark =~ m{Pg(\S+)} ) { # Only look at page markers
$end_mark = $mark;
$w->markGravity( $end_mark, 'right' );
last;
last if $w->compare( $mark, ">", $last );
push( @endmarks, $mark );
}
}
for $mark (@endmarks) {
$w->markGravity( $mark, 'right' );
}

if ( !@lengths ) { # No page markers, so simply insert new and delete old text
$w->insert( $last, $new_text );
Expand All @@ -312,28 +314,28 @@ sub ReplaceSelectionsWith {
last if $w->compare( $mark, '<', $first ); # Stop if before start of old string
next if ( $mark eq $prev ); # Skip if we find same position again

$w->markGravity( $prev, 'right' ) if ( $prev =~ m{Pg(\S+)} ); # Keep page marker to right of replaced string
$w->delete( $mark, $prev );
$w->insert(
$mark,
substr(
$new_text, $lengths[ $idx + 1 ], $lengths[$idx] - $lengths[ $idx + 1 ]
)
);
$w->markGravity( $prev, 'left' ) if ( $prev =~ m{Pg(\S+)} ); # Restore page marker behaviour
my $insstr =
substr( $new_text, $lengths[ $idx + 1 ], $lengths[$idx] - $lengths[ $idx + 1 ] );
my $inslen = length($insstr);
$w->markSet( 'mark_del_end', $prev );
$w->insert( $mark, $insstr );
$w->delete( "$mark + $inslen c", 'mark_del_end' );
$prev = $mark;
++$idx;
}

# delete final (first) chunk and insert remainder
$w->markGravity( $prev, 'right' ) if ( $prev =~ m{Pg(\S+)} ); # Keep page marker to right of replaced string
$w->delete( $first, $prev );
$w->insert( $first, substr( $new_text, 0, $lengths[$idx] ) );
$w->markGravity( $prev, 'left' ) if ( $prev =~ m{Pg(\S+)} ); # Restore page marker behaviour
my $insstr = substr( $new_text, 0, $lengths[$idx] );
my $inslen = length($insstr);
$w->markSet( 'mark_del_end', $prev );
$w->insert( $first, $insstr );
$w->delete( "$first + $inslen c", 'mark_del_end' );
}

# restore gravity for page mark after replaced text
$w->markGravity( $end_mark, 'left' ) if $end_mark;
# restore gravity for page marks after replaced text
for $mark (@endmarks) {
$w->markGravity( $mark, 'left' );
}
}

# set the insert cursor to the end of the last insertion mark
Expand All @@ -343,6 +345,7 @@ sub ReplaceSelectionsWith {
for ( my $i = 0 ; $i < $range_total ; $i++ ) {
$w->markUnset( 'mark_sel_' . $i );
}
$w->markUnset('mark_del_end');

$w->addGlobEnd;
}
Expand Down

0 comments on commit 26e3f25

Please sign in to comment.