From bec03ff2517f92c97b6ef3a4943d1d43f33fa8c0 Mon Sep 17 00:00:00 2001 From: peteyboy Date: Fri, 12 Jun 2026 21:27:39 +0000 Subject: [PATCH] Fix paging bug where if you go to a page and scroll down further than a previous (shorter) page can get to, the document is scrolled to bottom and looks empty. Used AI to figure this out after some back and forth, the 'ypos' function was not obvious. Ideally I would add a feature that actually tracks the scroll position with the history, so you would go back to the line/page where you came from, preserving previous scrolling. The load (page,1) code in here doesn't reall do that as intended in light of the bugfix discovery. Also improved the goto_link and goto_page dialog/feature so they handle bogus links and bogus URLs better. --- script/connex.pl | 114 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 80 insertions(+), 34 deletions(-) diff --git a/script/connex.pl b/script/connex.pl index 7c4d123..d69f2b1 100755 --- a/script/connex.pl +++ b/script/connex.pl @@ -1,9 +1,9 @@ #!/usr/bin/perl -w # connex.pl Nightfall Express (nex://) browser # By Pete Dussin, peteyboy@sdf.org 3/2024 +# updated 6/2026 # This program uses telnet instead of nc to make nex requests, because I couldn't get the Perl nc module to work right. -#TODO: Fill out help Dialog, mention vi navigatio and search #TODO: Fill out About Dialog #TODO: Make status dialog actually useful #TODO: bookmarks, maybe a quick mark-and-hold toggle to jump between two pages? @@ -18,6 +18,7 @@ use Curses::UI; use Net::Telnet; use URI::Split qw(uri_split uri_join); use URI (); +use Scalar::Util 'looks_like_number'; use Term::ReadKey; #for fatpacker? @@ -62,7 +63,7 @@ if (defined $full_url){ die "Need a $SCHEME_NEX url, or start without supplying URL argument.\n"; } $full_url= $uri->as_string; - $HOME_URL = $full_url; #TODO make sure you want to do this, mostly go home and other defaults will go here instead o nightfall.city + $HOME_URL = $full_url; #TODO make sure you want to do this, mostly go home and other defaults will go here instead of nightfall.city }else{ $full_url = $HOME_URL; } @@ -84,19 +85,19 @@ my $connect = new Net::Telnet (Timeout => 10, my @menu = ( { -label => 'File', -submenu => [ - { -label => 'Choose Link >', -value => \&goto_link_dialog }, - { -label => 'Back ^B/<', -value => \&goto_back }, - { -label => 'Go to Link ^G', -value => \&navigate_link_dialog }, - { -label => 'Go Home ^M', -value => \&goto_home }, - { -label => 'Page Links ^P', -value => \&page_links_dialog }, - { -label => 'History ^Y', -value => \&history_status_dialog }, - { -label => 'Exit ^Q', -value => \&exit_dialog } + { -label => 'Choose Link >', -value => \&goto_link_dialog }, + { -label => 'Back ^B/<', -value => \&goto_back }, + { -label => 'Go to Link ^G', -value => \&navigate_link_dialog }, + { -label => 'Go Home ^M', -value => \&goto_home }, + { -label => 'Page Links ^P', -value => \&page_links_dialog }, + { -label => 'Browser History ^Y', -value => \&history_status_dialog }, + { -label => 'Exit ^Q', -value => \&exit_dialog } ] }, { -label => 'Help', -submenu => [ - { -label => 'Help ^H', -value => \&help_dialog }, - { -label => 'About ', -value => \&about_dialog }, + { -label => 'Help ^H', -value => \&help_dialog }, + { -label => 'About ', -value => \&about_dialog }, ] }, @@ -108,7 +109,7 @@ my @menu = ( sub exit_dialog() { my $return = $cui->dialog( - -title => "Quit Connex?", + -title => "Quit Connex", -message => "Are you sure?", -buttons => ['yes', 'no'], @@ -132,6 +133,9 @@ sub links_dialog() sub unsupported_dialog { my $scheme = shift; + if (!defined $scheme){ + $scheme="unknown"; + } my $return = $cui->dialog( -message => "$scheme protocol not supported.", -title => "Bad Navigation", @@ -159,16 +163,19 @@ sub goto_link_dialog() ); #if not canceled, or too big or too small, goto link if($return){ - my $linkcount = scalar @page_links; - if($return <= $linkcount && $return >0){ - update_status($S_REQUESTING); - goto_link($return); - }else{ - #$browser->focus(); - my $return1 = $cui->status("there is no link # " . $return); + if(looks_like_number($return)){ + my $linkcount = scalar @page_links; + if($return <= $linkcount && $return >0){ + update_status($S_REQUESTING); + goto_link($return); + }else{ + my $return1 = $cui->status("there is no link # " . $return); + } + }else{ #they are using it to navigate to a different site or for some other reason entered text + my $return2 = $cui->status("You did not enter a link #. To Go to a different site, use 'Go' menu or type ctl-g"); } - #do nothing on cancel } + #do nothing on cancel } @@ -182,7 +189,7 @@ sub goto_back() #if($fetched) { $full_url =$fetched; update_status($S_REQUESTING); - load($full_url,0); #don't move back to top + load($full_url,1); #move back to top history_status_dialog(); #} @@ -198,7 +205,7 @@ sub goto_home() $full_url=$HOME_URL; } update_status($S_REQUESTING); - load($full_url,0); #don't move back to top + load($full_url,1); #move back to top history_status_dialog(); } @@ -211,7 +218,7 @@ sub goto_link{ #my $element=$linknum -1; #offset for array element #if ($element <= $#page_links){ #such a perlism, this is highest INDEX of array - if ($linknum <= $linkcount){ #such a perlism, this is highest INDEX of array + if ($linknum <= $linkcount){ navigate($page_links[$linknum-1]); #offset from count to index }else{ #my $browser = $win1->getobj("browser"); @@ -231,6 +238,15 @@ sub navigate{ } +sub browser_scroll_reset +{ + my $browser = $win1->getobj("browser"); + $browser->{-ypos} = 0; + #$browser->{-viewPos} =0; none of this works + $browser->draw(); + $browser->focus(); +} + sub update_status_bar { my $status = shift; @@ -291,12 +307,16 @@ sub history_status_dialog sub page_links_dialog { + my $browser = $win1->getobj("browser"); + $browser->focus(); + #my $link_list = join("\n", @page_links); if(@page_links){ - my $browser = $win1->getobj("browser"); - $browser->focus(); - #my $link_list = join("\n", @page_links); my $link_list = page_links_list(); my $return = $cui->status("links on this page:\n$link_list"); + #}elsif (!is_path_index($browser->title())){ #if not an index, actually is this even important to the user? + # my $return = $cui->status("Not an index page."); + }else{ #there are no links in this index (should be rare, and index with no links?) + my $return = $cui->status("No links on this page."); } } @@ -330,12 +350,27 @@ sub help_dialog my $browser = $win1->getobj("browser"); $browser->focus(); my $message = <<'END_MESSAGE'; -Navigation: -Press '>' key to select a '[>#]link by # +Browsing: +Press '>' key to select a '[>#] link by # Press '<' key to go back to previous page +Press 'ctl-Y' to see viewed page history +Press 'ctl-P' to see list of links on current page -Program Features: +Scrolling: +Arrow keys to scroll document +Press 'PageDown' to scroll down by page +Press 'PageUp' to scroll up by page + +Search: +'less' type search function supported: +Press '/' to start a forward search (type search term, hit ) + search for the next occurance using the 'n' key or the previous + occurance using the 'N' key. +Press '?' to start a reverse search (type search term, hit ) + +More Program Features: Press ctl-x for menu + END_MESSAGE my $return = $cui->dialog( @@ -397,6 +432,7 @@ $statusbar = $win1->add("status", "TextViewer", #key bindings, should match menu items $cui->set_binding(sub {$menu->focus()}, "\cX"); +$cui->set_binding( \&help_dialog , "\cH"); $cui->set_binding( \&exit_dialog , "\cQ"); $cui->set_binding( \&navigate_link_dialog , "\cG"); $cui->set_binding( \&goto_back , "\cB"); @@ -405,7 +441,6 @@ $cui->set_binding( \&goto_link_dialog , ">"); $cui->set_binding( \&goto_home , "\cM"); $cui->set_binding( \&page_links_dialog , "\cP"); $cui->set_binding( \&history_status_dialog , "\cY"); -$cui->set_binding( \&help_dialog , "\cH"); $cui->set_binding(sub { my $cui = shift; $cui->layout; @@ -516,7 +551,20 @@ sub load #TODO:handle non-existent request? Die is not pretty to do here die unless $connect->eof(); $connect->close(); + my $widget= $texteditor; + # check if we want to scroll to top + if ($top eq 1){ + #For widget programmers: To control the scrollbar, the widget data -vscrolllen (the total length of the content of the widget) and -vscrollpos (the current position in the document) should be set. + # If Curses::UI::Widget::draw is called, the scrollbar will be drawn. + #browser_scroll_reset(); + #my $browser = $win1->getobj("browser"); + $widget->{-ypos} = 0; + #$browser->{-viewPos} =0; none of this works + #$browser->draw(); + #$browser->focus(); + + } #loop through nex response and load into text editor. Identify, mark and store link lines for index pages my $page_contents =""; #this is the page contents to be dumped into the browser widget @@ -532,11 +580,9 @@ sub load } $page_contents= $page_contents . $currentline; } - $widget->text($page_contents); + $widget->text($page_contents); $widget->draw(); - if ($top){ - $widget->pos(0); - } + if ($page_contents eq ''){ update_status($S_NORESPONSE); }else{ -- 2.39.5