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

Hi Monks,
I have problem with Findnext, and also with Find function from Text widget.
These functions works well if I use them from the right-click menu, but I can't use them with my function. It found only the first hit.
#!/usr/bin/perl -- use strict; use warnings; use Tk; my $mw = MainWindow->new; my $filename; # Create necessary widgets my $f = $mw->Frame->pack( -side => 'top', -fill => 'x' ); $f->Entry( -textvariable => \$filename )->pack( -side => 'left', -anchor => 'w', -fill => 'x', -expand => 1 ); $f->Button( -text => "Exit", -command => sub { exit; } ) ->pack( -side => 'right' ); $f->Button(-text => "Find", -command => \&find) -> pack(-side => 'right'); my $t = $mw->Scrolled("Text")->pack( -side => 'bottom', -fill => 'both', -expand => 1, ); $t->insert( end => join "\n", 1 .. 10 ); $t->insert( 'end', "\nthe_the_the the\n"); $t->insert( 'end', "\nthe_the_the the\n"); MainLoop; sub find(){ #$t->FindNext(-forward, -exact,-nocase); my $result = $t->FindNext(-forwards, -exact, -nocase, "the"); print $result; }

Replies are listed 'Best First'.
Re: Why Findnext does not works?
by keszler (Priest) on Nov 15, 2009 at 00:42 UTC
    In your find function:
    my $result = $t->FindNext(-forwards, -exact, -nocase, "the"); # /^\
    You have the argument '-forwards'. The possible options are documented as '-forward' and '-reverse'.

    Note that Tk/Text.pm actually uses the following code:

    eval { if ($direction eq '-forward') { $w->markSet('insert', 'sel.last'); $w->markSet('current', 'sel.last'); } else { $w->markSet('insert', 'sel.first'); $w->markSet('current', 'sel.first'); } };
    So effectively anything not '-forward' is treated as '-reverse'.

    Update - I should have looked further.

    After the bit of code I copied above, FindNext calls the Text's search method with $direction as the first parameter. The search method is documented as using '-forwards' or '-backwards'. The C source at tkText.c agrees: the TextSearchCmd function does not mention '-reverse'.

    The relevant C is:

    arg = argv[i]; ... length = strlen(arg); ... c = arg[1]; if ((c == 'b') && (strncmp(argv[i], "-backwards", length) == 0)) { backwards = 1; ... } else if ((c == 'f') && (strncmp(argv[i], "-forwards", length) == 0)) + { backwards = 0;
    Because of the use of strncmp with 'length', either '-forward' or '-forwards' will work correctly in the call to search.

    Final answer: in FindNext use '-forward', '-backward', or '-backwards'. Do not use '-reverse' as documented, or '-forwards' like search.

    When using search, '-forward', '-forwards', '-backward', or '-backwards' are all acceptable.


    Update2: bug report forwarded to slaven@rezic.de. Tk::Text bug report

    Update 2010-02-02: Patches in the Perl/Tk subversion repo as r13796.