[LON-CAPA-cvs] cvs: loncom /interface lonsearchcat.pm

matthew lon-capa-cvs@mail.lon-capa.org
Mon, 29 Jul 2002 21:53:57 -0000


This is a MIME encoded message

--matthew1027979637
Content-Type: text/plain

matthew		Mon Jul 29 17:53:57 2002 EDT

  Modified files:              
    /loncom/interface	lonsearchcat.pm 
  Log:
  This code should NOT be considered stable.
  However, it seems to work occasionally.
  Frames are now used to contact two httpd daemons.  Results are shown in
  pages of 20.  
  &handler was mostly rewritten.  Hopefully the logic is clearer.
  Some function names were changed to reflect that they now output html 
  directly via $r. 
  Data persistence is a problem.  Rewrites were done of the previous 'persistent'
  functions.  Two new functions were added as well.  This still needs work.
  &create_results_table is a new function to create the mysql tables.
  &write_status is depricated and will be removed once major debugging stops.
  Many changes.  Much wailing and gnashing of teeth.
  
  
--matthew1027979637
Content-Type: text/plain
Content-Disposition: attachment; filename="matthew-20020729175357.txt"

Index: loncom/interface/lonsearchcat.pm
diff -u loncom/interface/lonsearchcat.pm:1.145 loncom/interface/lonsearchcat.pm:1.146
--- loncom/interface/lonsearchcat.pm:1.145	Sun Jul 28 16:02:14 2002
+++ loncom/interface/lonsearchcat.pm	Mon Jul 29 17:53:57 2002
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # Search Catalog
 #
-# $Id: lonsearchcat.pm,v 1.145 2002/07/28 20:02:14 matthew Exp $
+# $Id: lonsearchcat.pm,v 1.146 2002/07/29 21:53:57 matthew Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -141,7 +141,6 @@
              "Summary View"           => \&summary_view,
              "Fielded Format"         => \&fielded_format_view,
              "XML/SGML"               => \&xml_sgml_view );
-my $persistent_db_file;
 my %persistent_db;
 my $hidden_fields;
 ######################################################################
@@ -172,8 +171,6 @@
 sub handler {
     my $r = shift;
     #
-    untie %groupsearch_db if (tied(%groupsearch_db));
-    #
     my $closebutton;  # button that closes the search window 
                       # This button is different for the RAT compared to
                       # normal invocation.
@@ -185,8 +182,18 @@
     ## Pick up form fields passed in the links.
     ##
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
-             ['catalogmode','launch','acts','mode','form','element',
-              'reqinterface','persistent_db_id','table']);
+             ['catalogmode','launch','acts','mode','form','element','pause',
+              'phase','persistent_db_id','table','start','show']);
+    ##
+    ## The following is a trick - we wait a few seconds if asked to so
+    ##     the daemon running the search can get ahead of the daemon
+    ##     printing the results.  We only need (theoretically) to do
+    ##     this once, so the pause indicator is deleted
+    ##
+    if (exists($ENV{'form.pause'})) {
+        sleep(5);
+        delete($ENV{'form.pause'});
+    }
     ##
     ## Initialize global variables
     ##
@@ -195,29 +202,21 @@
             "\_".&Apache::lonnet::escape($ENV{'user.name'})."_searchcat.db";
     #
     # set the name of the persistent database
-    # $ENV{'form.persistent_db_id'} can only have digits in it.
+    #          $ENV{'form.persistent_db_id'} can only have digits in it.
     if (! exists($ENV{'form.persistent_db_id'}) ||
             $ENV{'form.persistent_db_id'} =~ /\D/ ) {
         $ENV{'form.persistent_db_id'} = time;
     }
-    $persistent_db_file = "/home/httpd/perl/tmp/".
+    my $persistent_db_file = "/home/httpd/perl/tmp/".
         &Apache::lonnet::escape($domain).
             '_'.&Apache::lonnet::escape($ENV{'user.name'}).
                 '_'.$ENV{'form.persistent_db_id'}.'_persistent_search.db';
-    #
-    # Read in the database.  It should (hopefully) not be catastrophic to
-    #    fail in this exercise. 
-    if (-e $persistent_db_file) {
-        # Read in the previous values, if we can.
-	if (tie(%persistent_db,'GDBM_File',$persistent_db_file,
-                &GDBM_READER,0640)) {
-            &reconstruct_persistent_form_data($r);
-            untie (%persistent_db);
-	}
-    }
+    ##
+    &get_persistent_form_data($r,$persistent_db_file);
     ##
     ## Clear out old values from groupsearch database
     ##
+    untie %groupsearch_db if (tied(%groupsearch_db));
     if ($ENV{'form.launch'} eq '1') {
 	if (tie(%groupsearch_db,'GDBM_File',$diropendb,&GDBM_WRCREAT,0640)) {
 	    &start_fresh_session();
@@ -233,6 +232,7 @@
     ##
     $hidden_fields = '<input type="hidden" name="persistent_db_id" value="'.
         $ENV{'form.persistent_db_id'}.'" />';
+    ##
     if ($ENV{'form.catalogmode'} eq 'interactive') {
         $closebutton="<input type='button' name='close' value='CLOSE' ".
 	    "onClick='self.close()'>"."\n";
@@ -244,69 +244,78 @@
 <input type='button' name='import' value='IMPORT'
 onClick='javascript:select_group()'>
 END
+    } else {
+        $closebutton = '';
+        $importbutton = '';
     }
     ##
-    ##  Do a search, if needed.
+    ## Sanity checks on form elements
     ##
-    my $searchtype;
-    $searchtype = 'Basic'    if ($ENV{'form.basicsubmit'}    eq 'SEARCH');
-    $searchtype = 'Advanced' if ($ENV{'form.advancedsubmit'} eq 'SEARCH');
-    if ($searchtype) {
-        ##
-        ## make query information persistent to allow for subsequent revision
-        ##
-        tie(%persistent_db,'GDBM_File',$persistent_db_file,&GDBM_WRCREAT,0640);
-        &make_persistent(\%ENV);
-        untie(%persistent_db);
+    if (!defined($ENV{'form.viewselect'})) {
+        $ENV{'form.viewselect'} ="Detailed Citation View";
+    }
+    $ENV{'form.phase'} = 'displaybasic' if (! exists($ENV{'form.phase'}));
+    ##
+    ## Switch on the phase
+    ##
+    if ($ENV{'form.phase'} eq 'disp_basic') {
+        &print_basic_search_form($r,$closebutton);
+    } elsif ($ENV{'form.phase'} eq 'disp_adv') {
+        &print_advanced_search_form($r,$closebutton);
+    } elsif ($ENV{'form.phase'} eq 'results') {
+        &display_results($r,$importbutton,$closebutton);
+    } elsif($ENV{'form.phase'} eq 'run_search') {
+        my ($query,$customquery,$customshow,$libraries,$pretty_string) =
+            &get_persistent_data($persistent_db_file,
+                 ['query','customquery','customshow',
+                  'libraries','pretty_string']);
+        &write_status($r,"query         = $query");
+        &write_status($r,"customquery   = $customquery");
+        &write_status($r,"customshow    = $customshow");
+        &write_status($r,"libraries     = $libraries");
+        &write_status($r,"pretty_string = $pretty_string");
+        &run_search($r,$query,$customquery,$customshow,
+                    $libraries,$pretty_string);
+    } elsif(($ENV{'form.phase'} eq 'basic_search') ||
+            ($ENV{'form.phase'} eq 'adv_search')) {
+        # Set up table
+        if (! defined(&create_results_table())) {
+            # Unable to make table to store results in.  
+            # Definately abort search.
+        }
+        if (! &make_form_data_persistent($r,$persistent_db_file)) {
+            # Unable to store persistent data.
+            # Probably should bail out.
+        }
         #
         # We are running a search
         my ($query,$customquery,$customshow,$libraries) = 
             (undef,undef,undef,undef);
         my $pretty_string;
-        if ($searchtype eq 'Basic') {
+        if ($ENV{'form.phase'} eq 'basic_search') {
             ($query,$pretty_string) = &parse_basic_search($r,$closebutton);
-        } elsif ($ENV{'form.advancedsubmit'} eq 'SEARCH') {
+        } else {                      # Advanced search
             ($query,$customquery,$customshow,$libraries,$pretty_string) 
                 = &parse_advanced_search($r,$closebutton);
             return OK if (! defined($query));
         }
-        # Output some information to the user.
-        $r->print(&search_results_header($searchtype,$pretty_string));
-        $r->print("Sending search request to LON-CAPA servers.<br />\n");
-        $r->rflush();
-        &run_search($r,$query,$customquery,$customshow,$libraries);
+        &write_status($r,"query         = $query");
+        &write_status($r,"customquery   = $customquery");
+        &write_status($r,"customshow    = $customshow");
+        &write_status($r,"libraries     = $libraries");
+        &write_status($r,"pretty_string = $pretty_string");
+        &make_persistent($r,
+                         { query => $query,
+                           customquery => $customquery,
+                           customshow => $customshow,
+                           libraries => $libraries,
+                           pretty_string => $pretty_string },
+                         $persistent_db_file);
         ##
-        ## Display the results
+        ## Print out the frames interface
         ##
-        &display_results($r,$searchtype,$importbutton,$closebutton);
-        $r->rflush();
-    } else {
-        #
-        # Set the default view if it is not already set.
-        if (!defined($ENV{'form.viewselect'})) {
-            $ENV{'form.viewselect'} ="Detailed Citation View";
-        }
-        # 
-        # remove the requested interface from the environment.
-        my $interface;
-        if ($ENV{'form.reqinterface'}) {
-            $interface = lc($ENV{'form.reqinterface'});
-        } else {
-            $interface = 'basic';
-        }
-        ##
-        ## Determine course of action
-        ##
-        if ($interface eq 'display') {
-            # &display_results($closebutton));
-        } elsif ($interface eq 'advanced') {
-            $r->print(&advanced_search_form($closebutton));
-        } elsif ($interface eq 'basic') { 
-            # Output normal search interface
-            $r->print(&basic_search_form($closebutton));
-        }
+        &print_frames_interface($r);
     }
-    untie (%persistent_db);
     return OK;
 } 
 
@@ -315,7 +324,7 @@
 
 =pod 
 
-=item &basic_search_form() 
+=item &print_basic_search_form() 
 
 Returns a scalar which holds html for the basic search form.
 
@@ -324,8 +333,8 @@
 ######################################################################
 ######################################################################
 
-sub basic_search_form{
-    my ($closebutton) = @_;
+sub print_basic_search_form{
+    my ($r,$closebutton) = @_;
     my $scrout=<<"ENDDOCUMENT";
 <html>
 <head>
@@ -342,6 +351,7 @@
 <img align='right' src='/adm/lonIcons/lonlogos.gif' />
 <h1>Search Catalog</h1>
 <form method="post" action="/adm/searchcat">
+<input type="hidden" name="phase" value="basic_search" />
 $hidden_fields
 <h3>Basic Search</h3>
 <p>
@@ -358,7 +368,7 @@
 #    $scrout.='<font color="#800000">Search historic archives</font>';
     my $checkbox = &simplecheckbox('related',$ENV{'form.related'});
     $scrout.=<<END;
-</td><td><a href="/adm/searchcat?reqinterface=advanced">Advanced Search</a></td></tr>
+</td><td><a href="/adm/searchcat?phase=disp_adv">Advanced Search</a></td></tr>
 <tr><td>$checkbox use related words</td><td></td></tr>
 </table>
 </p>
@@ -377,7 +387,8 @@
 </body>
 </html>
 ENDDOCUMENT
-    return $scrout;
+    $r->print($scrout);
+    return;
 }
 ######################################################################
 ######################################################################
@@ -393,8 +404,8 @@
 ######################################################################
 ######################################################################
 
-sub advanced_search_form{
-    my ($closebutton) = @_;
+sub print_advanced_search_form{
+    my ($r,$closebutton) = @_;
     my $advanced_buttons = <<"END";
 <p>
 <input type="submit" name="advancedsubmit" value='SEARCH' />
@@ -427,6 +438,7 @@
 <form method="post" action="/adm/searchcat">
 $advanced_buttons
 $hidden_fields
+<input type="hidden" name="phase" value="adv_search" />
 <table>
 <tr><td><font color="#800000" face="helvetica"><b>VIEW:</b></font></td>
 <td>
@@ -568,7 +580,8 @@
 </body>
 </html>
 ENDDOCUMENT
-    return $scrout;
+    $r->print($scrout);
+    return;
 }
 
 ######################################################################
@@ -576,40 +589,102 @@
 
 =pod 
 
-=item &reconstruct_persistent_form_data
+=item &get_persistent_form_data
 
-This function is the reverse of &make_persistent();
+Inputs: filename of database
+
+Outputs: returns undef on database errors.
+
+This function is the reverse of &make_persistent() for form data.
 Retrieve persistent data from %persistent_db.  Retrieved items will have their
-values unescaped.  If the item contains commas (before unescaping), the
-returned value will be an array pointer.  Items will be returned in the
-environment in $ENV{"form.$name"}.
+values unescaped.  If a form value already exists in $ENV, it will not be
+overwritten.  Form values that are array references may have values appended
+to them.
 
 =cut
 
 ######################################################################
 ######################################################################
-sub reconstruct_persistent_form_data {
-    foreach my $name (keys %persistent_db) {
-        # &Apache::lonnet::logthis("Reconstructing $name = $persistent_db{$name}");
-        my @Values = split(',',$persistent_db{$name});
-        my @value = map { &Apache::lonnet::unescape($_) } @Values;
-        $name = 'form.'.$name;
+sub get_persistent_form_data {
+    my $r = shift;
+    my $filename = shift;
+    return undef if (! -e $filename);
+    return undef if (! tie(%persistent_db,'GDBM_File',$filename,
+                           &GDBM_READER,0640));
+    #
+    # These make sure we do not get array references printed out as 'values'.
+    my %arrays_allowed = ('form.category'=>1,'form.domains'=>1);
+    #
+    # Loop through the keys, looking for 'form.'
+    foreach my $name (keys(%persistent_db)) {
+        next if ($name !~ /^form./);
+        my @values = map { 
+            &Apache::lonnet::unescape($_);
+        } split(',',$persistent_db{$name});
+        next if (@values <1);
         if (exists($ENV{$name})) {
-            if (ref($ENV{$name})) {
-                # Assume it is an array reference
-                $ENV{$name} = [@{$ENV{$name}},@value];
-            } else {
-                $ENV{$name} = [$ENV{$name},@value];
-            }
+            if (ref($ENV{$name}) eq 'ARRAY') {
+                # If it is an array, tack @values on the end of it.
+                $ENV{$name} = [@$ENV{$name},@values];
+            } elsif (! ref($ENV{$name}) && $arrays_allowed{$name}) {
+                # if arrays are allowed, turn it into one and add @values
+                $ENV{$name} = [$ENV{$name},@values];
+            } # otherwise, assume the value in $ENV{$name} is better than ours.
         } else {
-            if (@value > 1) {
-                $ENV{$name} = [@value];
+            if ($arrays_allowed{$name}) {
+                $ENV{$name} = [@values];
             } else {
-                $ENV{$name} = $value[0];
+                $ENV{$name} = $values[0] if ($values[0]);
             }
         }
+        &write_status($r,"Reconstructed $name = $ENV{$name}");
     }
-    return;
+    untie (%persistent_db);
+    return 1;
+}
+######################################################################
+######################################################################
+
+=pod 
+
+=item &get_persistent_data
+
+Inputs: filename of database, ref to array of values to recover.
+
+Outputs: array of values.  Returns undef on error.
+
+This function is the reverse of &make_persistent();
+Retrieve persistent data from %persistent_db.  Retrieved items will have their
+values unescaped.  If the item contains commas (before unescaping), the
+returned value will be an array pointer. 
+
+=cut
+
+######################################################################
+######################################################################
+sub get_persistent_data {
+    my $filename = shift;
+    my @Vars = @{shift()};
+    my @Values;   # Return array
+    return undef if (! -e $filename);
+    return undef if (! tie(%persistent_db,'GDBM_File',$filename,
+                           &GDBM_READER,0640));
+    foreach my $name (@Vars) {
+        if (! exists($persistent_db{$name})) {
+            push @Values, undef;
+            next;
+        }
+        my @values = map { 
+            &Apache::lonnet::unescape($_);
+        } split(',',$persistent_db{$name});
+        if (@values == 1) {
+            push @Values,$values[0];
+        } else {
+            push @Values,\@values;
+        }
+    }
+    untie (%persistent_db);
+    return @Values;
 }
 
 ######################################################################
@@ -619,7 +694,9 @@
 
 =item &make_persistent() 
 
-Store (environment) variables away to the %persistent_db.  
+Inputs: Hash of values to save, filename of persistent database.
+
+Store variables away to the %persistent_db.
 Values will be escaped.  Values that are array pointers will have their
 elements escaped and concatenated in a comma seperated string.  
 
@@ -628,16 +705,50 @@
 ######################################################################
 ######################################################################
 sub make_persistent {
+    my $r = shift;
     my %save = %{shift()};
-    foreach my $name (keys %save) {
-        next if ($name !~ /^form\./ || $name =~ /submit/);
+    my $filename = shift;
+    return undef if (! tie(%persistent_db,'GDBM_File',
+                           $filename,&GDBM_WRCREAT,0640));
+    foreach my $name (keys(%save)) {
+        next if (! exists($save{$name}));
+        next if (! defined($save{$name}) || $save{$name} eq '');
         my @values = (ref($save{$name}) ? @{$save{$name}} : ($save{$name}));
         # We handle array references, but not recursively.
         my $store = join(',', map { &Apache::lonnet::escape($_); } @values );
-        $name=~s/^form\.//;
         $persistent_db{$name} = $store;
+        &write_status($r,"Stored $name = $store");
     }
-    return '';
+    untie(%persistent_db);
+    return 1;
+}
+
+######################################################################
+######################################################################
+
+=pod 
+
+=item &make_form_data_persistent() 
+
+Inputs: filename of persistent database.
+
+Store most form variables away to the %persistent_db.
+Values will be escaped.  Values that are array pointers will have their
+elements escaped and concatenated in a comma seperated string.  
+
+=cut
+
+######################################################################
+######################################################################
+sub make_form_data_persistent {
+    my $r = shift;
+    my $filename = shift;
+    my %save;
+    foreach (keys(%ENV)) {
+        next if (! /^form/ || /submit/);
+        $save{$_} = $ENV{$_};
+    }
+    return &make_persistent($r,\%save,$filename);
 }
 
 ######################################################################
@@ -1459,6 +1570,35 @@
 
 =pod
 
+=item &create_results_table()
+
+Creates the table of search results by calling lonmysql.  Stores the
+table id in $ENV{'form.table'}
+
+Inputs: none.
+
+Returns: the identifier of the table on success, undef on error.
+
+=cut
+
+######################################################################
+######################################################################
+sub create_results_table {
+    my $table = &Apache::lonmysql::create_table
+        ( { columns => \%Datatypes,
+            column_order => \@DataOrder,
+        } );
+    if (defined($table)) {
+        $ENV{'form.table'} = $table;
+        return $table;
+    } 
+    return undef; # Error...
+}
+######################################################################
+######################################################################
+
+=pod
+
 =item &write_status()
 
 =cut
@@ -1467,8 +1607,10 @@
 ######################################################################
 sub write_status {
     my ($r,$string) = @_;
-    $r->print("<pre>".$string."</pre>\n");
-    $r->rflush();
+    $string =~ s/(\')/\$1/g;
+    $string =~ s/\n//sg;
+#    $r->print("<script>alert('$string');</script>\n");
+#    $r->rflush();
     return;
 }
 
@@ -1484,13 +1626,19 @@
 ######################################################################
 ######################################################################
 sub run_search {
-    my ($r,$query,$customquery,$customshow,$serverlist) = @_;
+    my ($r,$query,$customquery,$customshow,$serverlist,$pretty_string) = @_;
     #
     # Timing variables
     #
     my $starttime = time;
     my $max_time  = 120;  # seconds for the search to complete
     #
+    # Print run_search header
+    #
+    $r->print("<html><head><title>Search Status</title></head><body>");
+    $r->print("Search: ".$pretty_string."<br />\n");
+    $r->rflush();
+    #
     # Determine the servers we need to contact.
     #
     my @Servers_to_contact;
@@ -1500,13 +1648,7 @@
         @Servers_to_contact = sort(keys(%Apache::lonnet::libserv));
     }
     my %Server_status;
-    #
-    # Create Table
-    #
-    my $table = &Apache::lonmysql::create_table
-        ( { columns => \%Datatypes,
-            column_order => \@DataOrder,
-        } );
+    my $table =$ENV{'form.table'};
     if (! defined($table)) {
         # What do I do now?  Print out an error page.
         &Apache::lonnet::logthis("lonmysql attempted to create a table ".
@@ -1518,12 +1660,8 @@
         return;
     }
     ##
-    ## form.table needs to be stored in the persistent database...
-    ## 
-    $ENV{'form.table'}=$table;
-    #
-    # Prepare for the big loop.
-    #
+    ## Prepare for the big loop.
+    ##
     my $hitcountsum;
     my $server; 
     my $status;
@@ -1537,8 +1675,7 @@
                                                       $customshow,[$server]);
             ($server) = keys(%$reply);
             $Server_status{$server} = $reply->{$server};
-            # &write_status($r,"Contacted:$server:reply:".
-            #                   $Server_status{$server});
+            # $r->print("Contacted:$server:reply:$Server_status{$server}");
             if ($max_time - (time - $starttime) < 20) {
                 # If there are less than 20 seconds to go in the search,
                 # give the newly contacted servers 20 more seconds to 
@@ -1551,14 +1688,14 @@
         while (my ($server,$status) = each(%Server_status)) {
             if ($status eq 'con_lost') {
                 delete ($Server_status{$server});
-                # &write_status($r,"server $server is not responding.");
+                # $r->print("server $server is not responding.");
                 next;
             }
             $status=~/^([\.\w]+)$/; 
        	    my $datafile=$r->dir_config('lonDaemons').'/tmp/'.$1;
             if (-e $datafile && ! -e "$datafile.end") {
                 # Let the user know we are receiving data from the server
-                # &write_status($r,"$server:Receiving file");
+                # $r->print("$server:Receiving file");
                 next;
             }
             if (-e "$datafile.end") {
@@ -1571,7 +1708,7 @@
                     # Error opening file...
                     # Tell the user and exit...?
                     # Should I give up on opening it?
-                    &write_status("Unable to open search results file for ".
+                    $r->print("Unable to open search results file for ".
                                   "server $server.  Omitting from search");
                     next;
                 }
@@ -1587,16 +1724,16 @@
                     # Store the result in the mysql database
                     my $result = &Apache::lonmysql::store_row($table,\%Fields);
                     if (! defined($result)) {
-                        &write_status($r,&Apache::lonmysql::get_error());
+                        $r->print(&Apache::lonmysql::get_error());
                     }
-                    # &write_status($r,&Apache::lonmysql::get_debug());
+                    # $r->print(&Apache::lonmysql::get_debug());
                     $hitcountsum ++;
                 } # End of foreach (@results)
                 $fh->close();
                 # $server is only deleted if the results file has been 
                 # found and (successfully) opened.  This may be a bad idea.
                 delete($Server_status{$server});
-                #&write_status($r,"Received $new_count more results from ".
+                # $r->print("Received $new_count more results from ".
                 #              $server.".");
             }
         }
@@ -1607,12 +1744,13 @@
     #
     # We have run out of time or run out of servers to talk to and
     # results to get.  
-    &write_status($r,"Search completed.");
+    $r->print("<h1>Search completed.</h1>");
     if ($hitcountsum) {
-        &write_status($r,$hitcountsum." successful matches to your query.");
+        $r->print($hitcountsum." successful matches to your query.<br />");
     } else {
-        &write_status($r,"There were no successful matches to your query.");
+        $r->print("There were no successful matches to your query.<br />");
     }
+    $r->print("</body></html>");
     return;
 }
 
@@ -1620,13 +1758,13 @@
 ######################################################################
 =pod
 
-=item &display_buttons
+=item &prev_next_buttons
 
 =cut
 
 ######################################################################
 ######################################################################
-sub display_buttons {
+sub prev_next_buttons {
     my ($current_min,$show,$total,$parms) = @_;
     return '' if ($show eq 'all'); # No links if you get them all at once.
     my $links;
@@ -1636,21 +1774,27 @@
     $prev_min = 0 if $prev_min < 0;
     if ($prev_min < $current_min) {
         $links .= qq{
-<a href="/adm/searchcat?$parms&startwith=$prev_min&show=$show">prev</a>
+<a href="/adm/searchcat?$parms&start=$prev_min&show=$show">prev</a>
 };    
+    } else {
+        $links .= 'prev';
     }
     ##
     ## Pages.... Someday.
     ##
-
+    $links .= qq{ &nbsp;
+<a href="/adm/searchcat?$parms&start=$current_min&$show=$show">reload</a>
+};
     ##
     ## Next
     my $next_min = $current_min + $show;
-    my $next_min = $current_min if ($next_min > $total);
+    $next_min = $current_min if ($next_min > $total);
     if ($next_min != $current_min) {
-        $links .= qq{
-<a href="/adm/searchcat?$parms&startwith=$next_min&show=$show">next</a>
+        $links .= qq{ &nbsp;
+<a href="/adm/searchcat?$parms&start=$next_min&show=$show">next</a>
 };    
+    } else {
+        $links .= '&nbsp;next';
     }
     return $links;
 }
@@ -1667,6 +1811,7 @@
 ######################################################################
 sub display_results {
     my ($r,$mode,$importbutton,$closebutton) = @_;
+    $r->print(&search_results_header());
     ##
     ## Set viewing function
     ##
@@ -1679,34 +1824,25 @@
     ##
     ## Get the catalog controls setup
     ##
-    my $action = "/adm/searchcat";
-    if ($mode eq 'Basic') { 
-        $action .= "?reqinterface=basic";
-    } elsif ($mode eq 'Advanced') {
-        $action .= "?reqinterface=advanced";
+    my $action = "/adm/searchcat?phase=results";
+    ##
+    ##
+    ##
+    if ($ENV{'form.catalogmode'} eq 'groupsearch') {
+        if (! tie(%groupsearch_db,'GDBM_File',$diropendb,
+                  &GDBM_WRCREAT,0640)) {
+            $r->print('Unable to tie hash to db file</body></html>');
+            $r->rflush();
+            return;
+        } 
     }
-    $r->print(<<CATALOGCONTROLS);
-<form name='results' method="post" action="$action">
-$hidden_fields
-<input type='hidden' name='acts' value='' />
-<input type='button' value='Revise search request'
-onClick='this.form.submit();' />
-$importbutton
-$closebutton
-<hr />
-CATALOGCONTROLS
-    if (! tie(%groupsearch_db,'GDBM_File',$diropendb,&GDBM_WRCREAT,0640)) {
-        $r->print('Unable to tie hash to db file</body></html>');
-        $r->rflush();
-        return;
-    } 
     ##
     ## Prepare the table for querying
     ##
     my $table = $ENV{'form.table'};
     my $connection_result = &Apache::lonmysql::connect_to_db();
     if (!defined($connection_result)) {
-        &write_status($r,&Apache::lonmysql::get_error());
+        $r->print(&Apache::lonmysql::get_error());
     }
     my $table_check = &Apache::lonmysql::check_table($table);
     if (! defined($table_check)) {
@@ -1740,19 +1876,29 @@
     ##
     ## Determine how many results we need to get
     ##
-    $ENV{'form.startwith'} = 0      if (! exists($ENV{'form.startwith'}));
+    $ENV{'form.show'} = 20;
+    $ENV{'form.start'} = 0      if (! exists($ENV{'form.start'}));
     $ENV{'form.show'}      = 'all'  if (! exists($ENV{'form.show'}));
-    my $min = $ENV{'form.startwith'};
+    my $min = $ENV{'form.start'};
     my $max;
     if ($ENV{'form.show'} eq 'all') {
         $max = $total_results ;
     } else {
         $max = $min + $ENV{'form.show'};
+        $max = $total_results if ($max > $total_results);
     }
     ##
     ## Output links (if necessary) for 'prev' and 'next' pages.
     ##
-    
+    $r->print("<center>Results $min to $max out of $total_results</center>\n");
+    $r->print
+        ('<br /><center>'.
+         &prev_next_buttons($min,$ENV{'form.show'},$total_results,
+                            "table=".$ENV{'form.table'}.
+                            "&phase=results".
+                            "&persistent_db_id=".$ENV{'form.persistent_db_id'})
+         ."</center><br />\n"
+         );
     ##
     ## Get results from MySQL table
     ##
@@ -2024,21 +2170,8 @@
 ######################################################################
 ######################################################################
 sub search_results_header {
-    my ($mode,$pretty_query) = @_;
-    $mode = lc($mode);
-    my $title;
-    if ($mode eq 'advanced') {
-        $title = "Advanced Search Results";
-    } elsif ($mode eq 'basic') {
-        $title = "Basic Search Results";
-    }
     my $result = '';
     # output beginning of search page
-    $result.=<<BEGINNING;
-<html>
-<head>
-<title>$title</title>
-BEGINNING
     # conditional output of script functions dependent on the mode in
     # which the search was invoked
     if ($ENV{'form.catalogmode'} eq 'interactive'){
@@ -2105,35 +2238,50 @@
     }
 </script>
 SCRIPT
-    $result.=<<SCRIPT;
-<script type="text/javascript">
-    function displayinfo(val) {
-	popwin.document.forms.popremain.sdetails.value=val;
-    }
-    function openhelp(val) {
-	openhelpwin=open('/adm/help/searchcat.html','helpscreen',
-	     'scrollbars=1,width=400,height=300');
-	openhelpwin.focus();
-    }
-    function abortsearch(val) {
-	popwin.close();
-    }
-</script>
-SCRIPT
     $result.=<<END;
 </head>
-<body bgcolor="#ffffff">
-<img align=right src=/adm/lonIcons/lonlogos.gif>
-<h1>$title</h1>
 END
-    if ($pretty_query) {
-        $result .= "<p>Search query: $pretty_query</p>";
-    }
     return $result;
 }
 
 ######################################################################
 ######################################################################
+sub search_status_header {
+    return <<ENDSTATUS;
+<html><head><title>Search Status</title></head>
+<body>
+<h3>Search Status</h3>
+Sending search request to LON-CAPA servers.<br />
+ENDSTATUS
+}
+
+######################################################################
+######################################################################
+sub print_frames_interface {
+    my $r = shift;
+    my $basic_link = "/adm/searchcat?"."&table=".$ENV{'form.table'}.
+        "&persistent_db_id=".$ENV{'form.persistent_db_id'};
+    my $run_search_link = $basic_link."&phase=run_search";
+    my $results_link = $basic_link."&phase=results".
+        "&pause=10"."&start=0"."&show=20";
+    my $result = <<"ENDFRAMES";
+<html>
+<head>
+<title>LON-CAPA Digital Library Search Results</title>
+</head>
+<frameset rows="150,*">
+    <frame name="statusframe"  src="$run_search_link">
+    <frame name="resultsframe" src="$results_link">
+</frameset>
+</html>
+ENDFRAMES
+
+    $r->print($result);
+    return;
+}
+
+######################################################################
+######################################################################
 
 =pod 
 
@@ -2184,7 +2332,6 @@
 =item &summary_view() 
 
 =cut
-
 ######################################################################
 ######################################################################
 sub summary_view {
@@ -2332,8 +2479,8 @@
 <h1>Search Catalog</h1>
 <form method="post" action="/adm/searchcat">
 $hidden_fields
-<input type='button' value='Revise search request'
-onClick='this.form.submit();' />
+<a href="/adm/searchcat?persistent_db_id=$ENV{'form.persistent_db_id'}"
+>Revise search request</a>&nbsp;
 $closebutton
 <hr />
 <h3>Helpful Message</h3>

--matthew1027979637--