--- loncom/interface/lonprintout.pm	2014/02/08 23:49:12	1.639
+++ loncom/interface/lonprintout.pm	2022/06/11 15:50:09	1.680
@@ -1,7 +1,7 @@
 # The LearningOnline Network
 # Printout
 #
-# $Id: lonprintout.pm,v 1.639 2014/02/08 23:49:12 raeburn Exp $
+# $Id: lonprintout.pm,v 1.680 2022/06/11 15:50:09 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -143,12 +143,13 @@ sub printable_sequence {
 # Parameters:
 #    helper - the helper which already contains info about the current folder we can
 #             purloin.
-#    url    - Top url of the sequence
+#    map    - the map for which incomplete problems are to be printed
+#    nocurrloc - True if printout called from icon/link in Tools in /adm/navmaps
 # Return:
 #     XML that can be parsed by the helper to drive the state machine.
 #
 sub create_incomplete_folder_selstud_helper {
-    my ($helper, $map)  = @_;
+    my ($helper, $map, $nocurrloc)  = @_;
 
 
     my $symbFilter = '$res->shown_symb()';
@@ -157,7 +158,7 @@ sub create_incomplete_folder_selstud_hel
 
     my $resource_chooser = &generate_resource_chooser('CHOOSE_INCOMPLETE_PEOPLE_SEQ',
 						      'Select problem(s) to print',
-						      'multichoice="1" toponly="1" addstatus="1" closeallpages="1"',
+						      'multichoice="1" toponly="1" addstatus="1" closeallpages="1" modallink="1" nocurrloc="'.$nocurrloc.'"',
 						      'RESOURCES',
 						      'CHOOSE_STUDENTS_INCOMPLETE',
 						      $map,
@@ -206,7 +207,7 @@ sub create_incomplete_course_helper {
     
     my $resource_chooser = &generate_resource_chooser('INCOMPLETE_PROBLEMS_COURSE_RESOURCES',
 						      'Select problem(s) to print',
-						      'multichoice = "1" suppressEmptySequences="0" addstatus="1" closeallpagtes="1"',
+						      'multichoice = "1" suppressEmptySequences="0" addstatus="1" closeallpagtes="1" modallink="1"',
 						      'RESOURCES',
 						      'INCOMPLETE_PROBLEMS_COURSE_STUDENTS',
 						      '',
@@ -235,6 +236,7 @@ sub create_incomplete_course_helper {
 # Parameters:
 #   $helper - helper we are generating states for.
 #   $map    - The map for which the student wants incomplete problems.
+#   $nocurrloc - True if printout called from icon/link in Tools in /adm/navmaps
 # Returns:
 #   XML that defines the helper states being created.
 #
@@ -242,7 +244,7 @@ sub create_incomplete_course_helper {
 #   CHOOSE_INCOMPLETE_SEQ  - Resource selector.
 #
 sub create_incomplete_folder_helper {
-    my ($helper, $map) = @_;
+    my ($helper, $map, $nocurrloc) = @_;
 
     my $filter    = '$res->is_problem()';
     $filter      .= ' && $res->resprintable() ';
@@ -252,7 +254,7 @@ sub create_incomplete_folder_helper {
 
     my $resource_chooser = &generate_resource_chooser('CHOOSE_INCOMPLETE_SEQ',
 						      'Select problem(s) to print',
-						      'multichoice="1", toponly ="1", addstatus="1", closeallpages="1"',
+						      'multichoice="1", toponly ="1", addstatus="1", closeallpages="1" modallink="1" nocurrloc="'.$nocurrloc.'"',
 						      'RESOURCES',
 						      'PAGESIZE',
 						      $map,
@@ -306,7 +308,8 @@ CHOOSE_STUDENTS
 #     this_state    - State name of the chooser.
 #     prompt_text   - Text to use to prompt user.
 #     resource_options - Resource tag options e.g.
-#                        "multichoice='1', toponly='1', addstatus='1'"
+#                        "multichoice='1', toponly='1', addstatus='1',
+#                         modallink='1'" 
 #                     that control the selection and appearance of the
 #                     resource selector.
 #     variable      - Name of the variable to hold the choice
@@ -443,6 +446,134 @@ CHOOSE_ANON1
    return $result;
 }
 
+sub generate_common_choosers {
+    my ($r,$helper,$map,$url,$isProblem,$symbFilter,$start_new_option) = @_;
+
+    my $randomly_ordered_warning =
+        &get_randomly_ordered_warning($helper, $map);
+
+    # code for a few states used for printout launched from both 
+    # /adm/navmpas and from a resource by a privileged user:
+    #   - To allow resources to be selected for printing.
+    #   - To determine pagination between assignments.
+    #   - To determine how many assignments should be bundled into a single PDF.
+
+    my $resource_selector= &generate_resource_chooser('SELECT_PROBLEMS',
+                                                      'Select resources to print',
+                                                      'multichoice="1" addstatus="1" closeallpages="1" modallink="1" suppressNavmap="1"',
+                                                      'RESOURCES',
+                                                      'PRINT_FORMATTING',
+                                                      $map,
+                                                      $isProblem, '', $symbFilter,
+                                                      $start_new_option);
+    $resource_selector .=  &generate_format_selector($helper,
+                                                     'How should results be printed?',
+                                                     'PRINT_FORMATTING').
+                           &generate_resource_chooser('CHOOSE_STUDENTS_PAGE',
+                                                      'Select Problem(s) to print',
+                                                      "multichoice='1' addstatus='1' closeallpages ='1' modallink='1'",
+                                                      'RESOURCES',
+                                                      'PRINT_FORMATTING',
+                                                      $url,
+                                                      $isProblem, '',  $symbFilter,
+                                                      $start_new_option);
+
+# Generate student choosers.
+
+    &Apache::lonxml::xmlparse($r, 'helper',
+                              &generate_student_chooser('CHOOSE_TGT_STUDENTS_PAGE',
+                                                        'student_sort',
+                                                        'STUDENTS',
+                                                        'CHOOSE_STUDENTS_PAGE'));
+    &Apache::lonxml::xmlparse($r, 'helper',
+                              &generate_student_chooser('CHOOSE_STUDENTS',
+                                                        'student_sort',
+                                                        'STUDENTS',
+                                                        'SELECT_PROBLEMS'));
+    &Apache::lonxml::xmlparse($r, 'helper', $resource_selector);
+
+    my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+    my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+    my @names=&Apache::lonnet::getkeys('CODEs',$cdom,$cnum);
+    my $namechoice='<choice></choice>';
+    foreach my $name (sort {uc($a) cmp uc($b)} @names) {
+        if ($name =~ /^error: 2 /) { next; }
+        if ($name =~ /^type\0/) { next; }
+        $namechoice.='<choice computer="'.$name.'">'.$name.'</choice>';
+    }
+
+    my %code_values;
+    my %codes_to_print;
+    foreach my $key (@names) {
+        %code_values = &Apache::grades::get_codes($key, $cdom, $cnum);
+        foreach my $key (keys(%code_values)) {
+            $codes_to_print{$key} = 1;
+        }
+    }
+
+    my $code_selection;
+    foreach my $code (sort {uc($a) cmp uc($b)} (keys(%codes_to_print))) {
+        my $choice  = $code;
+        if ($code =~ /^[A-Z]+$/) { # Alpha code
+            $choice = &letters_to_num($code);
+        }
+        push(@{$helper->{DATA}{ALL_CODE_CHOICES}},[$code,$choice]);
+    }
+    if (%codes_to_print) {
+        $code_selection .='
+        <message><b>Choose single CODE from list:</b></message>
+        <message></td><td></message>
+            <dropdown variable="CODE_SELECTED_FROM_LIST" multichoice="0" allowempty="0">
+              <choice></choice>
+              <exec>
+                 push(@{$state->{CHOICES}},@{$helper->{DATA}{ALL_CODE_CHOICES}});
+              </exec>
+            </dropdown>
+        <message></td></tr><tr><td></message>
+        '.$/;
+    }
+
+    my @lines = &Apache::lonnet::get_scantronformat_file();
+    my $codechoice='';
+    foreach my $line (@lines) {
+        next if (($line =~ /^\#/) || ($line eq ''));
+        my ($name,$description,$code_type,$code_length)=
+            (split(/:/,$line))[0,1,2,4];
+        if ($code_length > 0 &&
+            $code_type =~/^(letter|number|-1)/) {
+            $codechoice.='<choice computer="'.$name.'">'.$description.'</choice>';
+        }
+    }
+    if ($codechoice eq '') {
+        $codechoice='<choice computer="default">Default</choice>';
+    }
+    my $anon1 = &generate_code_selector($helper,
+                                        'CHOOSE_ANON1',
+                                        'SELECT_PROBLEMS',
+                                        $codechoice,
+                                        $code_selection,
+                                        $namechoice) . $resource_selector;
+
+    &Apache::lonxml::xmlparse($r, 'helper',$anon1);
+
+    my $anon_page = &generate_code_selector($helper,
+                                            'CHOOSE_ANON1_PAGE',
+                                            'SELECT_PROBLEMS_PAGE',
+                                            $codechoice,
+                                            $code_selection,
+                                            $namechoice) .
+                    &generate_resource_chooser('SELECT_PROBLEMS_PAGE',
+                                               'Select Problem(s) to print',
+                                               "multichoice='1' addstatus='1' closeallpages ='1' modallink='1'",
+                                               'RESOURCES',
+                                               'PRINT_FORMATTING',
+                                               $url,
+                                               $isProblem, '',  $symbFilter,
+                                               $start_new_option);
+    &Apache::lonxml::xmlparse($r, 'helper', $anon_page);
+    return ($randomly_ordered_warning,$codechoice,$code_selection,$namechoice);
+}
+
 #  Returns the XML for choosing how assignments are to be formatted 
 #  that text must still be parsed by the helper xml parser.
 # Parameters: 3 (required)
@@ -457,7 +588,9 @@ sub generate_format_selector {
     my $secpdfoption;
     unless (($helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_for_anon')     ||
             ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_for_anon_page') ||
-            ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'resources_for_anon')  ) {
+            ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'resources_for_anon') ||
+            ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'select_sequences_problems_for_anon') ||
+            ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'select_sequences_resources_for_anon')) {
         $secpdfoption =  '<choice computer="sections">Each PDF contains exactly one section</choice>';
     }
     return <<RESOURCE_SELECTOR;
@@ -700,12 +833,12 @@ sub incomplete {
     }
 }
 #
-#  When printing for students, the resoures and order of the
+#  When printing for students, the resources and order of the
 #  resources may need to be altered if there are folders with
 #  random selectiopn or random ordering (or both) enabled.
 #  This sub computes the set of resources to print for a student
 #  modified both by random ordering and selection and filtered
-#  to only those that are in the original set selcted to be printed.
+#  to only those that are in the original set selected to be printed.
 #
 # Parameters:
 #   $map - The URL of the folder being printed.
@@ -716,6 +849,9 @@ sub incomplete {
 #   $who   - Student/domain for whome the sequence will be generated.
 #   $code  - CODE being printed when printing Problems/Resources
 #            from folder for CODEd assignments
+#   $nohidemap - If true, parameter in map for hiddenresource will be
+#                ignored.  The user calling the routine should have
+#                both the pav and vgr privileges if this is set to true).
 #
 # Implicit inputs:
 #   $
@@ -737,7 +873,7 @@ sub master_seq_to_person_seq {
     my @output_seq;
 
     my $unhidden;
-    if ($perm{'pav'} && $perm{'vgr'} && $nohidemap) {
+    if ($nohidemap) {
         $unhidden = &Apache::lonnet::clutter($map);
     }
     
@@ -842,9 +978,10 @@ sub set_font_size {
 
     if ($font_size ne '') {
 
-	$text =~ s/\\begin{document}/\\begin{document}{\\$font_size/;
+	$text =~ s/\\begin\{document}/\\begin{document}{\\$font_size/;
+        $text =~ s/\\end\{document}/}\\end{document}/;
+
     }
-    $text =~ s/\\end{document}/}\\end{document}/;
     return $text;
 
 
@@ -886,7 +1023,7 @@ sub include_pdf {
     my $londocroot = $Apache::lonnet::perlvar{'lonDocRoot'};
     $file =~ s{(.*)/res/}{$londocroot/res/};
 
-    open(FILE,">>$Apache::lonnet::perlvar{'lonPrtDir'}/$env{'user.name'}_$env{'user.domain'}_printout.dat");
+    open(FILE,">>","$Apache::lonnet::perlvar{'lonPrtDir'}/$env{'user.name'}_$env{'user.domain'}_printout.dat");
     print FILE ("$file\n");
     close (FILE);
 
@@ -921,13 +1058,13 @@ sub include_pdf {
 sub collect_languages {
     my $doc = shift;
     my %languages;
-    while ($doc =~ /\\selectlanguage{(\w+)}/mg) {
+    while ($doc =~ /\\selectlanguage\{(\w+)}/mg) {
 	$languages{$1} = 1;	# allows us to request each language exactly once.
     }
     my @lang_list = (keys(%languages)); # List of unique languages
     if (scalar @lang_list) {
 	my $babel_header = '\usepackage[' . join(',', @lang_list) .']{babel}'. "\n";
-	$doc =~ s/\\begin{document}/$babel_header\\begin{document}/;
+	$doc =~ s/\\begin\{document}/$babel_header\\begin{document}/;
     }
     return $doc;
 }
@@ -1229,8 +1366,9 @@ sub is_valid_alpha_code {
 sub is_code_valid {
     my ($code_value, $code_option) = @_;
     my ($code_type, $code_length) = ('letter', 6);	# defaults.
-    my @lines = &Apache::grades::get_scantronformat_file();
+    my @lines = &Apache::lonnet::get_scantronformat_file();
     foreach my $line (@lines) {
+        next if (($line =~ /^\#/) || ($line eq ''));
 	my ($name, $type, $length) = (split(/:/, $line))[0,2,4];
 	if($name eq $code_option) {
 	    $code_length = $length;
@@ -1324,8 +1462,8 @@ sub compare_names {
 
 sub latex_header_footer_remove {
     my $text = shift;
-    $text =~ s/\\end{document}//;
-    $text =~ s/\\documentclass([^&]*)\\begin{document}//;
+    $text =~ s/\\end\{document}//;
+    $text =~ s/\\documentclass([^&]*)\\begin\{document}//;
     return $text;
 }
 #
@@ -1334,8 +1472,8 @@ sub latex_header_footer_remove {
 #  necessity is determined by the problem_split param.
 #
 sub encapsulate_minipage {
-    my ($text) = @_;
-    if (!($env{'form.problem.split'} =~ /yes/i)) {
+    my ($text,$problem_split) = @_;
+    if (!($problem_split =~ /yes/i)) {
 	$text = '\begin{minipage}{\textwidth}'.$text.'\end{minipage}';
     }
     return $text;
@@ -1875,12 +2013,12 @@ sub page_format_transformation {
 	$fancypagestatement="\\rhead{}\\chead{}\\lhead{$header_text}";
     }
     if ($layout eq 'album') {
-	    $text =~ s/\\begin{document}/\\setlength{\\oddsidemargin}{$oddoffset}\\setlength{\\evensidemargin}{$evenoffset}$topmargintoinsert\n\\setlength{\\textwidth}{$textwidth}\\setlength{\\textheight}{$textheight}\\setlength{\\textfloatsep}{8pt plus 2\.0pt minus 4\.0pt}\n\\newlength{\\minipagewidth}\\setlength{\\minipagewidth}{\\textwidth\/\$number_of_columns-0\.2cm}\\usepackage{fancyhdr}\\addtolength{\\headheight}{\\baselineskip}\n\\pagestyle{fancy}$fancypagestatement\\usepackage{booktabs}\\begin{document}\\voffset=-0\.8 cm\\setcounter{page}{1}\n /;
+	    $text =~ s/\\begin\{document}/\\setlength{\\oddsidemargin}{$oddoffset}\\setlength{\\evensidemargin}{$evenoffset}$topmargintoinsert\n\\setlength{\\textwidth}{$textwidth}\\setlength{\\textheight}{$textheight}\\setlength{\\textfloatsep}{8pt plus 2\.0pt minus 4\.0pt}\n\\newlength{\\minipagewidth}\\setlength{\\minipagewidth}{\\textwidth\/\$number_of_columns-0\.2cm}\\usepackage{fancyhdr}\\addtolength{\\headheight}{\\baselineskip}\n\\pagestyle{fancy}$fancypagestatement\\usepackage{booktabs}\\begin{document}\\voffset=-0\.8 cm\\setcounter{page}{1}\n /;
     } elsif ($layout eq 'book') {
 	if ($choice ne 'All class print') { 
-	    $text =~ s/\\begin{document}/\\textheight $textheight\\oddsidemargin = $evenoffset\\evensidemargin = $evenoffset $topmargintoinsert\n\\textwidth= $textwidth\\newlength{\\minipagewidth}\\setlength{\\minipagewidth}{\\textwidth\/\$number_of_columns-0\.2cm}\n\\renewcommand{\\ref}{\\keephidden\}\\usepackage{fancyhdr}\\addtolength{\\headheight}{\\baselineskip}\\pagestyle{fancy}$fancypagestatement\\usepackage{booktabs}\\begin{document}\n\\voffset=-0\.8 cm\\setcounter{page}{1}\n/;
+	    $text =~ s/\\begin\{document}/\\textheight $textheight\\oddsidemargin = $evenoffset\\evensidemargin = $evenoffset $topmargintoinsert\n\\textwidth= $textwidth\\newlength{\\minipagewidth}\\setlength{\\minipagewidth}{\\textwidth\/\$number_of_columns-0\.2cm}\n\\renewcommand{\\ref}{\\keephidden\}\\usepackage{fancyhdr}\\addtolength{\\headheight}{\\baselineskip}\\pagestyle{fancy}$fancypagestatement\\usepackage{booktabs}\\begin{document}\n\\voffset=-0\.8 cm\\setcounter{page}{1}\n/;
 	} else {
-	    $text =~ s/\\pagestyle{fancy}\\rhead{}\\chead{}\s*\\begin{document}/\\textheight = $textheight\\oddsidemargin = $evenoffset\n\\evensidemargin = $evenoffset $topmargintoinsert\\textwidth= $textwidth\\newlength{\\minipagewidth}\n\\setlength{\\minipagewidth}{\\textwidth\/\$number_of_columns-0\.2cm}\\renewcommand{\\ref}{\\keephidden\}\\pagestyle{fancy}\\rhead{}\\chead{}\\usepackage{booktabs}\\begin{document}\\voffset=-0\.8cm\n\\setcounter{page}{1}  \\vskip 5 mm\n /;
+	    $text =~ s/\\pagestyle\{fancy}\\rhead\{}\\chead\{}\s*\\begin\{document}/\\textheight = $textheight\\oddsidemargin = $evenoffset\n\\evensidemargin = $evenoffset $topmargintoinsert\\textwidth= $textwidth\\newlength{\\minipagewidth}\n\\setlength{\\minipagewidth}{\\textwidth\/\$number_of_columns-0\.2cm}\\renewcommand{\\ref}{\\keephidden\}\\pagestyle{fancy}\\rhead{}\\chead{}\\usepackage{booktabs}\\begin{document}\\voffset=-0\.8cm\n\\setcounter{page}{1}  \\vskip 5 mm\n /;
 	}
 	if ($papersize eq 'a4') {
 	    my $papersize_text;
@@ -1889,13 +2027,13 @@ sub page_format_transformation {
 	    } else {
 		$papersize_text = '\special{papersize=210mm,297mm}';
 	    }
-	    $text =~ s/(\\begin{document})/$1$papersize_text/;
+	    $text =~ s/(\\begin\{document})/$1$papersize_text/;
 	}
     }
     if ($tableofcontents eq 'yes') {$text=~s/(\\setcounter\{page\}\{1\})/$1 \\tableofcontents\\newpage /;}
     if ($indexlist eq 'yes') {
-	$text=~s/(\\begin{document})/\\makeindex $1/;
-	$text=~s/(\\end{document})/\\strut\\\\\\strut\\printindex $1/;
+	$text=~s/(\\begin\{document})/\\makeindex $1/;
+	$text=~s/(\\end\{document})/\\strut\\\\\\strut\\printindex $1/;
     }
     return $text;
 }
@@ -1904,12 +2042,12 @@ sub page_format_transformation {
 sub page_cleanup {
     my $result = shift;	
  
-    $result =~ m/\\end{document}(\d*)$/;
+    $result =~ m/\\end\{document}(\d*)$/;
     my $number_of_columns = $1;
     my $insert = '{';
     for (my $id=1;$id<=$number_of_columns;$id++) { $insert .='l'; }
     $insert .= '}';
-    $result =~ s/(\\begin{longtable})INSERTTHEHEADOFLONGTABLE\\endfirsthead\\endhead/$1$insert/g;
+    $result =~ s/(\\begin\{longtable})INSERTTHEHEADOFLONGTABLE\\endfirsthead\\endhead/$1$insert/g;
     $result =~ s/&\s*REMOVETHEHEADOFLONGTABLE\\\\/\\\\/g;
     return $result,$number_of_columns;
 }
@@ -1945,16 +2083,16 @@ my $end_of_student = "\n".'\special{ps:E
 
 sub latex_corrections {
     my ($number_of_columns,$result,$selectionmade,$answer_mode) = @_;
-#    $result =~ s/\\includegraphics{/\\includegraphics\[width=\\minipagewidth\]{/g;
+#    $result =~ s/\\includegraphics\{/\\includegraphics\[width=\\minipagewidth\]{/g;
     my $copyright = &copyright_line();
     if ($selectionmade eq '1' || $answer_mode eq 'only') {
-	$result =~ s/(\\end{document})/\\strut\\vskip 0 mm $copyright $end_of_student $1/;
+	$result =~ s/(\\end\{document})/\\strut\\vskip 0 mm $copyright $end_of_student $1/;
     } else {
-	$result =~ s/(\\end{document})/\\strut\\vspace\*{-4 mm}\\newline $copyright $end_of_student $1/;
+	$result =~ s/(\\end\{document})/\\strut\\vspace\*{-4 mm}\\newline $copyright $end_of_student $1/;
     }
     $result =~ s/\$number_of_columns/$number_of_columns/g;
-    $result =~ s/(\\end{longtable}\s*)(\\strut\\newline\\noindent\\makebox\[\\textwidth\/$number_of_columns\]\[b\]{\\hrulefill})/$2$1/g;
-    $result =~ s/(\\end{longtable}\s*)\\strut\\newline/$1/g;
+    $result =~ s/(\\end\{longtable}\s*)(\\strut\\newline\\noindent\\makebox\[\\textwidth\/$number_of_columns\]\[b\]\{\\hrulefill})/$2$1/g;
+    $result =~ s/(\\end\{longtable}\s*)\\strut\\newline/$1/g;
 #-- LaTeX corrections     
     my $first_comment = index($result,'<!--',0);
     while ($first_comment != -1) {
@@ -1973,8 +2111,8 @@ sub latex_corrections {
     if ($result =~ m/&(\w+|#\d+);/) {
 	$result = &character_chart($result);
     }
-    $result =~ s/(\\end{tabular})\s*\\vskip 0 mm/$1/g;
-    $result =~ s/(\\begin{enumerate})\s*\\noindent/$1/g;
+    $result =~ s/(\\end\{tabular})\s*\\vskip 0 mm/$1/g;
+    $result =~ s/(\\begin\{enumerate})\s*\\noindent/$1/g;
     return $result;
 }
 
@@ -2067,16 +2205,28 @@ sub get_textwidth {
 
 sub unsupported {
     my ($currentURL,$mode,$symb)=@_;
+    my $cleanURL=&Apache::lonenc::check_decrypt($currentURL);
+    my $shown = $currentURL;
+    if (($cleanURL ne $currentURL) || ($symb =~ m{/^enc/})) {
+        $shown = &mt('URL not shown (encrypted)');
+    }
     if ($mode ne '') {$mode='\\'.$mode}
-    my $result.= &print_latex_header($mode);
-    if ($currentURL=~m|^(/adm/wrapper/)?ext/|) {
-	$currentURL=~s|^(/adm/wrapper/)?ext/|http://|;
-        $currentURL=~s|^http://https://|https://|;
-	my $title=&Apache::lonnet::gettitle($symb);
-	$title = &Apache::lonxml::latex_special_symbols($title);
-	$result.=' \strut \\\\ '.$title.' \strut \\\\ '.$currentURL.' ';
+    my $result = &print_latex_header($mode);
+    if ($cleanURL=~m|^(/adm/wrapper)?/ext/|) {
+        $cleanURL=~s|^(/adm/wrapper)?/ext/|http://|;
+        $cleanURL=~s|^http://https://|https://|;
+        if ($shown eq $currentURL) {
+            $shown = &Apache::lonxml::latex_special_symbols($cleanURL);
+        }
+        my $title=&Apache::lonnet::gettitle($symb);
+        $title = &Apache::lonxml::latex_special_symbols($title);
+        $result.=' \strut \\\\ \textit{'.$title.'} \strut \\\\ '.$shown.' ';
     } else {
-	$result.=$currentURL;
+        if ($shown eq $currentURL) {
+	    $result.=&Apache::lonxml::latex_special_symbols($currentURL);
+        } else {
+            $result.=$shown;
+        }
     }
     $result.= '\vskip 0.5mm\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill} \end{document}';
     return $result;
@@ -2114,19 +2264,12 @@ sub print_page_in_course {
 								      $numberofcolumns);
     my $LaTeXwidth=&recalcto_mm($textwidth); 
 
-
     if ($mode ne '') {$mode='\\'.$mode}
     my $result   =    &print_latex_header($mode);
-    if ($currentURL=~m|^(/adm/wrapper/)?ext/|) {
-	$currentURL=~s|^(/adm/wrapper/)?ext/|http://|;
-	my $title=&Apache::lonnet::gettitle($symb);
-	$title = &Apache::lonxml::latex_special_symbols($title);
-    } else {
-        my $esc_currentURL= $currentURL;
-        $esc_currentURL =~ s/_/\\_/g;
-	$result.=$esc_currentURL;
-    }
-    $result .= '\\\\';
+
+    my $title=&Apache::lonnet::gettitle($currentURL);
+    $title = &Apache::lonxml::latex_special_symbols($title);
+    $result .= '\noindent\textit{'.$title.'}\\\\';
 
     if ($helper->{'VARS'}->{'style_file'}=~/\w/) {
 	&Apache::lonnet::appenv({'construct.style' =>
@@ -2142,7 +2285,7 @@ sub print_page_in_course {
 
     foreach my $resource (@page_resources) {
 	my $resource_src   = $resource->src(); # Essentially the URL of the resource.
-	$result           .= $resource->title() . '\\\\';
+        my $current_url = $resource->link();
 
 	# Recurse if a .page:
 
@@ -2152,11 +2295,10 @@ sub print_page_in_course {
 	    $result           .= &print_page_in_course($helper, $rparmhash, 
 						       $resource_src, \@page_resources);
         } elsif ($resource->ext()) {
-            $result .= &unsupported($currentURL,$mode,$symb);
-	}
-	# these resources go through the XML transformer:
-
-	elsif ($resource_src =~ /\.(problem|exam|quiz|assess|survey|form|library|xml|html|htm|xhtml|xhtm)$/)  {
+            $result.=&latex_header_footer_remove(&unsupported($current_url,$mode,$resource->symb));
+	} elsif ($resource_src =~ /\.(problem|exam|quiz|assess|survey|form|library|xml|html|htm|xhtml|xhtm)$/)  {
+            # these resources go through the XML transformer:
+            $result .= &Apache::lonxml::latex_special_symbols($resource->title()) . '\\\\';
 
 	    my $urlp = &Apache::lonnet::clutter($resource_src);
 
@@ -2212,7 +2354,7 @@ sub print_page_in_course {
 		my $answer=&ssi_with_retries($urlp,$ssi_retry_count, %answerform);
 
 		if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') {
-		    $texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
+		    $texversion=~s/(\\keephidden\{ENDOFPROBLEM})/$answer$1/;
 		} else {
 		    $texversion= &print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'});
 		    if ($helper->{'VARS'}->{'construction'} ne '1') {
@@ -2238,7 +2380,7 @@ sub print_page_in_course {
 
 	    if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
 		my $annotation .= &annotate($currentURL);
-		$texversion =~ s/(\\keephidden{ENDOFPROBLEM})/$annotation$1/;
+		$texversion =~ s/(\\keephidden\{ENDOFPROBLEM})/$annotation$1/;
 	    }
 	    
 	    if ($helper->{'VARS'}->{'TABLE_INDEX'} eq 'yes') {
@@ -2530,7 +2672,7 @@ sub print_construction_sequence {
 		$resources_printed .= $urlp.':';
 		my $answer=&ssi_with_retries($urlp, $ssi_retry_count, %answerform);
 		if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') {
-		    $texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
+		    $texversion=~s/(\\keephidden\{ENDOFPROBLEM})/$answer$1/;
 		} else {
 		    # If necessary, encapsulate answer in minipage:
 		    
@@ -2540,7 +2682,7 @@ sub print_construction_sequence {
 		    my $body ='\vskip 0 mm \noindent\textbf{'.$title.'}\vskip 0 mm ';
 		    $body.=&path_to_problem($urlp,$LaTeXwidth);
 		    $body.='\vskip 1 mm '.$answer.'\end{document}';
-		    $body = &encapsulate_minipage($body);
+		    $body = &encapsulate_minipage($body,$answerform{'problem_split'});
 		    $texversion.=$body;
 		}
 	    }
@@ -2583,7 +2725,7 @@ sub print_construction_sequence {
 	    $result .= $texversion;
 	}
     }
-    if ($helper->{VARS}->{'construction'} eq '1') {$result=~s/(\\begin{document})/$1 \\fbox\{RANDOM SEED IS $rndseed\} /;}
+    if ($helper->{VARS}->{'construction'} eq '1') {$result=~s/(\\begin\{document})/$1 \\fbox\{RANDOM SEED IS $rndseed\} /;}
     return $result;
 }
 
@@ -2740,7 +2882,7 @@ ENDPART
 	    $cleanURL=$currentURL;
 	}
 	$selectionmade = 1;
-      
+
 	if ($cleanURL!~m|^/adm/|
 	    && $cleanURL=~/\.(problem|exam|quiz|assess|survey|form|library|xml|html|htm|xhtml|xhtm)$/) {
 	    my $rndseed=time;
@@ -2793,7 +2935,7 @@ ENDPART
 		
 
 		if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') {
-		    $texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
+		    $texversion=~s/(\\keephidden\{ENDOFPROBLEM})/$answer$1/;
 		} else {
 		    $texversion=&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'});
 		    if ($helper->{'VARS'}->{'construction'} ne '1') {
@@ -2820,7 +2962,7 @@ ENDPART
 
 	    if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
 		my $annotation .= &annotate($currentURL);
-		$texversion =~ s/(\\keephidden{ENDOFPROBLEM})/$annotation$1/;
+		$texversion =~ s/(\\keephidden\{ENDOFPROBLEM})/$annotation$1/;
 	    }
 
 
@@ -2844,14 +2986,15 @@ ENDPART
 		$result = &print_latex_header() . $result;
 	    }
 	    # End construction space sequence.
-	} elsif ($cleanURL=~/\/(smppg|syllabus|aboutme|bulletinboard)$/) { 
+	} elsif ($cleanURL=~/\/(smppg|syllabus|aboutme|bulletinboard|ext\.tool)$/) { 
 		$form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'};
 		if ($currentURL=~/\/syllabus$/) {$currentURL=~s/\/res//;}
+                if ($currentURL=~/\/ext\.tool$/) {$currentURL=~s/^\/adm\/wrapper//;}
 		$resources_printed .= $currentURL.':';
 		my $texversion = &ssi_with_retries($currentURL, $ssi_retry_count, %form);
 		if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
 		    my $annotation = &annotate($currentURL);
-		    $texversion    =~ s/(\\end{document})/$annotation$1/;
+		    $texversion    =~ s/(\\end\{document})/$annotation$1/;
 		}
 		$result .= $texversion;
 	} elsif ($cleanURL =~/\.tex$/) {
@@ -2862,7 +3005,7 @@ ENDPART
 	    $result = &fetch_raw_resource($currentURL);
 	    if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
 		my $annotation = &annotate($currentURL);
-		$result =~ s/(\\end{document})/$annotation$1/;
+		$result =~ s/(\\end\{document})/$annotation$1/;
 	    }
 
 	    $do_postprocessing = 0; # Don't massage the result.
@@ -2928,12 +3071,10 @@ ENDPART
 
 	&Apache::lonxml::clear_problem_counter();
 
-	my $pbreakresources = keys %page_breaks;
 	for (my $i=0;$i<=$#master_seq;$i++) {
 
 	    &Apache::lonenc::reset_enc();
 
-
 	    # Note due to document structure, not allowed to put \newpage
 	    # prior to the first resource
 
@@ -2954,6 +3095,7 @@ ENDPART
 	    my $texversion='';
 	    if ($urlp!~m|^/adm/|
 		&& $urlp=~/\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)$/) {
+                my $extension = $1;
 		$resources_printed .= $urlp.':';
 		&Apache::lonxml::remember_problem_counter();
 		if ($flag_latex_header_remove eq 'NO') {
@@ -2962,7 +3104,7 @@ ENDPART
                             (($i==0) &&
                              (($urlp=~/\.page$/) ||
                               ($print_type eq 'map_problems_in_page') ||
-                              ($print_type eq 'map_resources_in_page')))) {
+                              (($print_type eq 'map_resources_in_page') && ($extension !~ /^x?html?$/))))) {
                         $flag_latex_header_remove = 'YES';
                     }
 		}
@@ -2970,7 +3112,7 @@ ENDPART
 		if ($urlp=~/\.page$/) {
 		    ($texversion,my $number_of_columns_page) = &page_cleanup($texversion);
 		    if ($number_of_columns_page > $number_of_columns) {$number_of_columns=$number_of_columns_page;} 
-		    $texversion =~ s/\\end{document}\d*/\\end{document}/;
+		    $texversion =~ s/\\end\{document}\d*/\\end{document}/;
 		    $flag_page_in_sequence = 'YES';
 		}
 
@@ -2985,27 +3127,27 @@ ENDPART
 		    &Apache::lonxml::restore_problem_counter();
 		    my $answer=&ssi_with_retries($urlp, $ssi_retry_count, %answerform);
                     if ($urlp =~ /\.page$/) {
-                        $answer =~ s/\\end{document}(\d*)$//;
+                        $answer =~ s/\\end\{document}(\d*)$//;
                     }
 		    if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') {
                         if ($urlp =~ /\.page$/) {
-                            my @probs = split(/\\keephidden{ENDOFPROBLEM}/,$texversion);
+                            my @probs = split(/\\keephidden\{ENDOFPROBLEM}/,$texversion);
                             my $lastprob = pop(@probs);
                             $texversion = join('\keephidden{ENDOFPROBLEM}',@probs).
                             $answer.'\keephidden{ENDOFPROBLEM}'.$lastprob;
                         } else {
-                            $texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
+                            $texversion=~s/(\\keephidden\{ENDOFPROBLEM})/$answer$1/;
                         }
 		    } else {
 			if ($urlp=~/$LONCAPA::assess_page_re/) {
 			    $texversion=&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'});
-#			    $texversion =~ s/\\begin{document}//; # FIXME
+#			    $texversion =~ s/\\begin\{document}//; # FIXME
 			    my $title = &Apache::lonnet::gettitle($master_seq[$i]);
 			    $title = &Apache::lonxml::latex_special_symbols($title);
 			    my $body ='\vskip 0 mm \noindent\textbf{'.$title.'}\vskip 0 mm ';
 			    $body   .= &path_to_problem ($urlp,$LaTeXwidth);
 			    $body   .='\vskip 1 mm '.$answer;
-			    $body    = &encapsulate_minipage($body);
+			    $body    = &encapsulate_minipage($body,$answerform{'problem_split'});
 			    $texversion .= $body;
 			} else {
 			    $texversion='';
@@ -3015,13 +3157,13 @@ ENDPART
 		}
 		if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
 		    my $annotation .= &annotate($urlp);
-		    $texversion =~ s/(\\keephidden{ENDOFPROBLEM})/$annotation$1/;
+		    $texversion =~ s/(\\keephidden\{ENDOFPROBLEM})/$annotation$1/;
 		}
 
 		if ($flag_latex_header_remove ne 'NO') {
 		    $texversion = &latex_header_footer_remove($texversion);
 		} else {
-		    $texversion =~ s/\\end{document}//;
+		    $texversion =~ s/\\end\{document}//;
 		}
 		if ($helper->{'VARS'}->{'TABLE_INDEX'} eq 'yes') {
 		    $texversion=&IndexCreation($texversion,$urlp);
@@ -3043,20 +3185,21 @@ ENDPART
 		}
 		$result .= $texversion;
 		$flag_latex_header_remove = 'YES';   
-	    } elsif ($urlp=~/\/(smppg|syllabus|aboutme|bulletinboard)$/) { 
+	    } elsif ($urlp=~/\/(smppg|syllabus|aboutme|bulletinboard|ext\.tool)$/) { 
 		$form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'};
 		if ($urlp=~/\/syllabus$/) {$urlp=~s/\/res//;}
+                if ($urlp=~/\/ext\.tool$/) {$urlp=~s/^\/adm\/wrapper//;}
 		$resources_printed .= $urlp.':';
 		my $texversion = &ssi_with_retries($urlp, $ssi_retry_count, %form);
 		if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
 		    my $annotation = &annotate($urlp);
-		    $texversion =~ s/(\\end{document)/$annotation$1/;
+		    $texversion =~ s/(\\end\{document)/$annotation$1/;
 		}
 
 		if ($flag_latex_header_remove ne 'NO') {
 		    $texversion = &latex_header_footer_remove($texversion);
 		} else {	
-		    $texversion =~ s/\\end{document}/\\vskip 0\.5mm\\noindent\\makebox\[\\textwidth\/\$number_of_columns\]\[b\]\{\\hrulefill\}/;
+		    $texversion =~ s/\\end\{document}/\\vskip 0\.5mm\\noindent\\makebox\[\\textwidth\/\$number_of_columns\]\[b\]\{\\hrulefill\}/;
 		}
 		$result .= $texversion;
 		$flag_latex_header_remove = 'YES'; 
@@ -3087,7 +3230,7 @@ ENDPART
 		if ($flag_latex_header_remove ne 'NO') {
 		    $texversion = &latex_header_footer_remove($texversion);
 		} else {
-		    $texversion =~ s/\\end{document}//;
+		    $texversion =~ s/\\end\{document}//;
 		}
 		$result .= $texversion;
 		$flag_latex_header_remove = 'YES';   
@@ -3098,7 +3241,7 @@ ENDPART
 	}
 	&Apache::lonxml::clear_problem_counter();
 	if ($flag_page_in_sequence eq 'YES') {
-	    $result =~ s/\\usepackage{calc}/\\usepackage{calc}\\usepackage{longtable}/;
+	    $result =~ s/\\usepackage\{calc}/\\usepackage{calc}\\usepackage{longtable}/;
 	}	
 	$result .= '\end{document}';
      } elsif (($print_type eq 'problems_for_students')           ||
@@ -3106,7 +3249,9 @@ ENDPART
 	      ($print_type eq 'all_problems_students')           ||
 	      ($print_type eq 'resources_for_students')          ||
 	      ($print_type eq 'incomplete_problems_selpeople_course') ||
-	      ($print_type eq 'map_incomplete_problems_people_seq')){
+	      ($print_type eq 'map_incomplete_problems_people_seq') ||
+              ($print_type eq 'select_sequences_problems_for_students') ||
+              ($print_type eq 'select_sequences_resources_for_students')) {
 
 
      #-- prints assignments for whole class or for selected students  
@@ -3115,10 +3260,12 @@ ENDPART
 	     ($print_type eq 'problems_for_students_from_page') ||
 	     ($print_type eq 'all_problems_students')           ||
 	     ($print_type eq 'incomplete_problems_selpeople_course') ||
-	     ($print_type eq 'map_incomplete_problems_people_seq')) {
+	     ($print_type eq 'map_incomplete_problems_people_seq') ||
+             ($print_type eq 'select_sequences_problems_for_students')) {
 	     $selectionmade=5;
 	     $type='problems';
-	 } elsif ($print_type eq 'resources_for_students') {
+	 } elsif (($print_type eq 'resources_for_students') ||
+                  ($print_type eq 'select_sequences_resources_for_students')) {
 	     $selectionmade=8;
 	     $type='resources';
 	 }
@@ -3179,6 +3326,10 @@ ENDPART
 	 my $student_counter=-1;
 	 my $i = 0;
 	 my $last_section = (split(/:/,$students[0]))[2];
+         my $nohidemap;
+         if ($perm{'pav'} && $perm{'vgr'}) {
+             $nohidemap = 1;
+         }
 	 foreach my $person (@students) {
              my $duefile="/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout.due";
 	     if (-e $duefile) {
@@ -3196,7 +3347,7 @@ ENDPART
 		 $i=int($student_counter/$helper->{'VARS'}{'NUMBER_TO_PRINT'});
 	     }
 	     my $actual_seq = master_seq_to_person_seq($map, \@master_seq,
-                                                       $person, undef, 1);
+                                                       $person, undef, $nohidemap);
 	     my ($output,$fullname, $printed)=&print_resources($r,$helper,
 						     $person,$type,
 						     \%moreenv,  $actual_seq,
@@ -3214,7 +3365,9 @@ ENDPART
 	 $result .= $print_array[0].'  \end{document}';
      } elsif (($print_type eq 'problems_for_anon')      ||
 	      ($print_type eq 'problems_for_anon_page') ||
-	      ($print_type eq 'resources_for_anon')  ) { 
+	      ($print_type eq 'resources_for_anon')     ||
+              ($print_type eq 'select_sequences_problems_for_anon') ||
+              ($print_type eq 'select_sequences_resources_for_anon')) {
 	 my $cdom =$env{'course.'.$env{'request.course.id'}.'.domain'};
 	 my $cnum =$env{'course.'.$env{'request.course.id'}.'.num'};
 	 my $num_todo=$helper->{'VARS'}->{'NUMBER_TO_PRINT_TOTAL'};
@@ -3223,10 +3376,10 @@ ENDPART
 	 my $single_code = $helper->{'VARS'}->{'SINGLE_CODE'};
 	 my $selected_code = $helper->{'VARS'}->{'CODE_SELECTED_FROM_LIST'};
 	 my $code_option=$helper->{'VARS'}->{'CODE_OPTION'};
-         my @lines = &Apache::grades::get_scantronformat_file();
+         my @lines = &Apache::lonnet::get_scantronformat_file();
 	 my ($code_type,$code_length,$bubbles_per_row)=('letter',6,10);
 	 foreach my $line (@lines) {
-             chomp($line);
+             next if (($line =~ /^\#/) || ($line eq ''));
 	     my ($name,$type,$length,$bubbles_per_item) = 
                  (split(/:/,$line))[0,2,4,17];
 	     if ($name eq $code_option) {
@@ -3238,18 +3391,10 @@ ENDPART
                  }
 	     }
 	 }
-         my ($randomorder,$randompick,$map);
+         my $map;
          if ($helper->{VARS}{'symb'}) {
              ($map, my $id, my $resource) =
                  &Apache::lonnet::decode_symb($helper->{VARS}{'symb'});
-             my $navmap = Apache::lonnavmaps::navmap->new();
-             if (defined($navmap)) {
-                 if ($map) {
-                     my $mapres = $navmap->getResourceByUrl($map);
-                     $randomorder = $mapres->randomorder();
-                     $randompick = $mapres->randompick();
-                 }
-             }
          }
 	 my %moreenv = ('textwidth' => &get_textwidth($helper,$LaTeXwidth));
 	 $moreenv{'problem_split'}    = $parmhash{'problem_stream_switch'};
@@ -3284,6 +3429,8 @@ ENDPART
 		 $moreenv{'CODE'}=&get_CODE(\%allcodes,$i,$seed,$code_length,
 					    $code_type);
 	     }
+             $code_name =~ s/^\s+//;
+             $code_name =~ s/\s+$//;
 	     if ($code_name) {
 		 &Apache::lonnet::put('CODEs',
 				      {
@@ -3305,6 +3452,10 @@ ENDPART
 	 my $flag_latex_header_remove = 'NO'; 
 	 my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,$num_todo);
 	 my $count=0;
+         my $nohidemap;
+         if ($perm{'pav'} && $perm{'vgr'}) {
+             $nohidemap = 1;
+         }
 	 foreach my $code (sort(@allcodes)) {
 	     my $file_num=int($count/$number_per_page);
 	     if ($code_type eq 'number') { 
@@ -3312,14 +3463,11 @@ ENDPART
 	     } else {
 		 $moreenv{'CODE'}=&num_to_letters($code);
 	     }
-             my $actual_seq = \@master_seq;
-             if ($randomorder || $randompick) {
-                 $env{'form.CODE'} = $moreenv{'CODE'};
-                 $actual_seq = master_seq_to_person_seq($map, \@master_seq,
-                                                        undef,
-                                                        $moreenv{'CODE'}, 1);
-                 delete($env{'form.CODE'});
-             }
+             $env{'form.CODE'} = $moreenv{'CODE'};
+             my $actual_seq = master_seq_to_person_seq($map, \@master_seq,
+                                                       undef,
+                                                       $moreenv{'CODE'}, $nohidemap);
+             delete($env{'form.CODE'});
 	     my ($output,$fullname, $printed)=
 		 &print_resources($r,$helper,'anonymous',$type,\%moreenv,
 				  $actual_seq,$flag_latex_header_remove,
@@ -3334,7 +3482,7 @@ ENDPART
 	 }
 	 &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
 	 $result .= $print_array[0].'  \end{document}';
-     } elsif ($print_type eq 'problems_from_directory') {      
+     } elsif ($print_type eq 'problems_from_directory') {
     #prints selected problems from the subdirectory 
 	$selectionmade = 6;
         my @list_of_files=split /\|\|\|/, $helper->{'VARS'}->{'FILES'};
@@ -3367,7 +3515,7 @@ ENDPART
 		    $resources_printed .= $urlp.':';
 		    my $answer=&ssi_with_retries($urlp, $ssi_retry_count, %answerform);
 		    if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') {
-			$texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
+			$texversion=~s/(\\keephidden\{ENDOFPROBLEM})/$answer$1/;
 		    } else {
 			$texversion=&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'});
 			if ($helper->{'VARS'}->{'construction'} ne '1') {
@@ -3384,11 +3532,11 @@ ENDPART
                 #this chunk is responsible for printing the path to problem
 
 		my $newurlp=&path_to_problem($urlp,$LaTeXwidth);
-		$texversion =~ s/(\\begin{minipage}{\\textwidth})/$1 $newurlp/;
+		$texversion =~ s/(\\begin\{minipage}\{\\textwidth})/$1 $newurlp/;
 		if ($flag_latex_header_remove ne 'NO') {
 		    $texversion = &latex_header_footer_remove($texversion);
 		} else {
-		    $texversion =~ s/\\end{document}//;
+		    $texversion =~ s/\\end\{document}//;
 		}
 		if ($helper->{'VARS'}->{'TABLE_INDEX'} eq 'yes') {
 		    $texversion=&IndexCreation($texversion,$urlp);
@@ -3426,13 +3574,51 @@ ENDPART
 	#}
     }
 
-    # Set URLback if this is a construction space print so we can provide
-    # a link to the resource being edited.
-    #
+    # Set URLback so we can provide a link back to the resource and to change options.
+    # (Since the browser back button does not currently work with https,
+    # the back link is useful even when there is an easy-to-miss LON-CAPA back button.)
 
     my $URLback=''; #link to original document
     if ($helper->{'VARS'}->{'construction'} eq '1') {
 	$URLback=$helper->{'VARS'}->{'filename'};
+    } elsif ($helper->{VARS}{'symb'}) {
+        my ($map, $id, $url) = &Apache::lonnet::decode_symb($helper->{VARS}{'symb'});
+        my $cdom =$env{'course.'.$env{'request.course.id'}.'.domain'};
+        my $cnum =$env{'course.'.$env{'request.course.id'}.'.num'};
+        my ($anchor,$usehttp,$plainurl);
+        $url = &Apache::lonnet::clutter($url);
+        $plainurl = $url;
+        if (($ENV{'SERVER_PORT'} == 443) && ($env{'request.course.id'}) &&
+            (($url =~ m{^\Q/public/$cdom/$cnum/syllabus\E($|\?)}) ||
+             ($url =~ m{^\Q/adm/wrapper/ext/\E(?!https:)}))) {
+            unless ((&Apache::lonnet::uses_sts()) || (&Apache::lonnet::waf_allssl())) {
+                $usehttp = 1;
+            }
+        }
+        if ($env{'request.enc'}) {
+            $url = &Apache::lonenc::encrypted($url); 
+        }
+        if ($url ne '') {
+            my $symb = $helper->{VARS}{'symb'};
+            if ($url =~ m{^\Q/adm/wrapper/ext/\E}) {
+                my $link = $url;
+                ($link,$anchor) = ($url =~ /^([^\#]+)(?:|(\#[^\#]+))$/);
+                if ($anchor) {
+                    ($symb) = ($helper->{VARS}{'symb'} =~ /^([^\#]+)/);
+                }
+                $url = $link;
+            }
+            $URLback = $url;
+            if ($usehttp) {
+                $URLback .= (($URLback =~ /\?/) ? '&amp;':'?').'usehttp=1';
+            }
+            unless ($plainurl =~ /\.page$/) {
+                $URLback .= (($URLback =~ /\?/) ? '&amp;':'?').'symb='.&escape($symb.$anchor);
+            }
+        }
+    } elsif (($helper->{VARS}->{'postdata'} eq '/adm/navmaps') &&
+             ($env{'request.course.id'})) {
+        $URLback=$helper->{VARS}->{'postdata'};
     }
     #
     # Final adjustment of the font size:
@@ -3516,7 +3702,7 @@ ENDPART
 				'cgi.'.$identifier.'.role' => $perm{'pav'},
 				'cgi.'.$identifier.'.numberoffiles' => $#print_array,
 				'cgi.'.$identifier.'.studentnames' => $student_names,
-				'cgi.'.$identifier.'.backref' => $URLback,});
+				'cgi.'.$identifier.'.backref' => &escape($URLback),});
     &Apache::lonnet::appenv({"cgi.$identifier.user"    => $env{'user.name'},
 				"cgi.$identifier.domain"  => $env{'user.domain'},
 				"cgi.$identifier.courseid" => $cnum, 
@@ -3612,10 +3798,10 @@ sub print_resources {
     #
 
     my $syllabus_first = 0;
-    my $assessment_first = 0;
     my $current_assignment = "";
     my $assignment;
     my $courseidinfo = &get_course();
+    my $possprint = scalar(@{$master_seq});
 
     foreach my $curresline (@{$master_seq})  {
 	if (defined $page_breaks{$curresline}) {
@@ -3634,9 +3820,6 @@ sub print_resources {
 	    if ($print_incomplete && !&incomplete($username, $userdomain, $res_url)) {
 		next;
 	    }
-            if ((!$actually_printed) && ($curresline =~ m/$LONCAPA::assess_re/)) {
-                $assessment_first = 1;
-            }
 	    $actually_printed++; # we're going to print one.
 
 	    if (&Apache::lonnet::allowed('bre',$res_url)) {
@@ -3656,7 +3839,7 @@ sub print_resources {
                         if ($remove_latex_header eq 'YES') {
                             $rendered = &latex_header_footer_remove($rendered);
                         } else {
-                            $rendered =~ s/\\end{document}\d*//;
+                            $rendered =~ s/\\end\{document}\d*//;
                         }
                     }
 		    if(($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') ||
@@ -3673,36 +3856,36 @@ sub print_resources {
 			my $ansrendered = &Apache::loncommon::get_student_answers($curresline,$username,$userdomain,$env{'request.course.id'},%answerenv);
 
 			if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') {
-			    $rendered=~s/(\\keephidden{ENDOFPROBLEM})/$ansrendered$1/;
+			    $rendered=~s/(\\keephidden\{ENDOFPROBLEM})/$ansrendered$1/;
 			} else {
 
 			    
 			    my $header =&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'});
                             unless ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only') {
-                                $header =~ s/\\begin{document}//;     #<<<<<
+                                $header =~ s/\\begin\{document}//;     #<<<<<
                             }
 			    my $title = &Apache::lonnet::gettitle($curresline);
 			    $title = &Apache::lonxml::latex_special_symbols($title);
 			    my $body   ='\vskip 0 mm \noindent\textbf{'.$title.'}\vskip 0 mm ';
 			    $body     .=&path_to_problem($res_url,$LaTeXwidth);
 			    $body     .='\vskip 1 mm '.$ansrendered;
-			    $body     = &encapsulate_minipage($body);
+			    $body     = &encapsulate_minipage($body,$answerenv{'problem_split'});
 			    $rendered = $header.$body;
 			}
 		    }
 		    if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
 			my $url = &Apache::lonnet::clutter($res_url);
 			my $annotation = &annotate($url);
-			$rendered =~  s/(\\keephidden{ENDOFPROBLEM})/$annotation$1/;
+			$rendered =~  s/(\\keephidden\{ENDOFPROBLEM})/$annotation$1/;
 		    }
 		    my $junk;
 		    if ($remove_latex_header eq 'YES') {
 			$rendered = &latex_header_footer_remove($rendered);
 		    } else {
-			$rendered =~ s/\\end{document}//;
+			$rendered =~ s/\\end\{document}//;
 		    }
 		    $current_output .= $rendered;		    
-		} elsif ($res_url=~/\/(smppg|syllabus|aboutme|bulletinboard)$/) {
+		} elsif ($res_url=~/\/(smppg|syllabus|aboutme|bulletinboard|ext\.tool)$/) {
 		    if ($i == 1) {
 			$syllabus_first = 1;
 		    }
@@ -3711,12 +3894,12 @@ sub print_resources {
 		    if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
 			my $url = &Apache::lonnet::clutter($res_url);
 			my $annotation = &annotate($url);
-			$annotation    =~ s/(\\end{document})/$annotation$1/;
+			$annotation    =~ s/(\\end\{document})/$annotation$1/;
 		    }
 		    if ($remove_latex_header eq 'YES') {
 			$rendered = &latex_header_footer_remove($rendered);
 		    } else {
-			$rendered =~ s/\\end{document}//;
+			$rendered =~ s/\\end\{document}//;
 		    }
 		    $current_output .= $rendered.'\vskip 0.5mm\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}\strut \vskip 0 mm \strut ';
 		} elsif($res_url = ~/\.pdf$/) {
@@ -3731,7 +3914,7 @@ sub print_resources {
 		    if ($remove_latex_header ne 'NO') {
 			$rendered = &latex_header_footer_remove($rendered);
 		    } else {
-			$rendered =~ s/\\end{document}//;
+			$rendered =~ s/\\end\{document}//;
 		    }
 		    $current_output .= $rendered;
 		}
@@ -3760,7 +3943,24 @@ sub print_resources {
     #
 
     if ($actually_printed == 0) {
-	$current_output  = &encapsulate_minipage("\\vskip -10mm \nNo incomplete resources\n \\vskip 100 mm { }\n");
+        my $message = &mt('No resources to print');
+        if (!$possprint) {
+            if ($perm{'pav'} || $perm{'pfo'}) {
+                $message = &mt('There are no unhidden resources to print.')."\n\n".
+                           &mt('The most likely reason is one of the following: ')."\n".
+                           '\begin{itemize}'."\n".
+                           '\item '.&mt("The 'Resource hidden from students' parameter is set for the folder being printed.")."\n".
+                           '\item '.&mt("'Hidden' is checked in the Course Editor individually for each resource in the folder being printed.")."\n".
+                           '\end{itemize}'."\n\n".
+                           &mt("Note: to print a bubblesheet exam which you want to hide from students, ".
+                               "use the Course Editor to check the 'Hidden' checkbox for the exam folder itself.")."\n";
+            }
+        } elsif ($print_incomplete) {
+            $message = &mt('No incomplete resources');
+        }
+        if ($message) { 
+	    $current_output  = &encapsulate_minipage("\\vskip -10mm \n$message\n \\vskip 100 mm { }\n",$moreenv->{'problem_split'});
+        }
 	if ($remove_latex_header eq "NO") {
 	    $current_output = &print_latex_header() . $current_output;
 	} else {
@@ -3771,18 +3971,14 @@ sub print_resources {
     if ($syllabus_first) {
         $current_output =~ s/\\\\ Last updated:/Last updated:/
     }
-    my $newheader;
-    unless ($assessment_first) {
-	my $currentassignment=&Apache::lonxml::latex_special_symbols($helper->{VARS}->{'assignment'},'header');
-	my $header_line =
-	    &format_page_header($LaTeXwidth, $parmhash{'print_header_format'},
-				$currentassignment, $courseidinfo, $fullname, $usersection);
-	my $header_start = ($columns_in_format == 1) ? '\lhead'
-	    : '\fancyhead[LO]';
-	$newheader = $header_start.'{'.$header_line.'}';
-    }
+    my $currentassignment=&Apache::lonxml::latex_special_symbols($helper->{VARS}->{'assignment'},'header');
+    my $header_line =
+    &format_page_header($LaTeXwidth, $parmhash{'print_header_format'},
+                        $currentassignment, $courseidinfo, $fullname, $usersection);
+    my $header_start = ($columns_in_format == 1) ? '\lhead' : '\fancyhead[LO]';
+    my $newheader = $header_start.'{'.$header_line.'}';
     if ($current_output=~/\\documentclass/) {
-	$current_output =~ s/\\begin{document}/\\setlength{\\topmargin}{1cm} \\begin{document}\\noindent\\parbox{\\minipagewidth}{\\noindent$newheader$namepostfix}\\vskip 5 mm /;
+	$current_output =~ s/\\begin\{document}/\\setlength{\\topmargin}{1cm} \\begin{document}\\noindent\\parbox{\\minipagewidth}{\\noindent$newheader$namepostfix}\\vskip 5 mm /;
 
     } else {
 	my $blankpages = 
@@ -3825,8 +4021,9 @@ sub handler {
     if ($env{'request.course.id'}) {
         my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
         my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+        my $clientip = &Apache::lonnet::get_requestor_ip($r);
         my ($blocked,$blocktext) = 
-            &Apache::loncommon::blocking_status('printout',$cnum,$cdom);
+            &Apache::loncommon::blocking_status('printout',$clientip,$cnum,$cdom);
         if ($blocked) {
             my $checkrole = "cm./$cdom/$cnum";
             if ($env{'request.course.sec'} ne '') {
@@ -4004,7 +4201,9 @@ sub printHelper {
         $helper->{VARS}->{'construction'} = 1;
     } else {
         if ($env{'form.postdata'}) {
-            $helper->{VARS}->{'symb'} = &Apache::lonnet::symbread($env{'form.postdata'});
+            unless ($env{'form.postdata'} eq '/adm/navmaps') {
+                $helper->{VARS}->{'symb'} = &Apache::lonnet::symbread($env{'form.postdata'});
+            }
 	    if ( $helper->{VARS}->{'symb'} eq '') {
 		$helper->{VARS}->{'postdata'} = $env{'form.postdata'};
 	    }
@@ -4022,12 +4221,40 @@ sub printHelper {
         $helper->{VARS}->{'symb'} = $env{'form.symb'};
     }
     if ($env{'form.url'}) {
-        $helper->{VARS}->{'symb'} = &Apache::lonnet::symbread($helper->{VARS}->{'postdata'});
-
+        unless ($env{'form.url'} eq '/adm/navmaps') {
+            $helper->{VARS}->{'symb'} = &Apache::lonnet::symbread($helper->{VARS}->{'postdata'});
+        }
+    }
+    if ($helper->{VARS}->{'symb'} ne '') {
+        $helper->{VARS}->{'symb'}=
+	    &Apache::lonenc::check_encrypt($helper->{VARS}->{'symb'});
+    }
+    my ($resourceTitle,$sequenceTitle,$mapTitle,$cdom,$cnum);
+    if ($helper->{VARS}->{'postdata'} eq '/adm/navmaps') {
+        $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+        $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+        if ($env{'course.'.$env{'request.course.id'}.'.url'} eq
+            "uploaded/$cdom/$cnum/default.sequence") {
+            my $navmap = Apache::lonnavmaps::navmap->new();
+            if (ref($navmap)) {
+                my @toplevelres = $navmap->retrieveResources('',sub { !(($_[0]->is_map()) || ($_[0]->src =~ /^\/adm\/navmaps/)) },0,0);
+                if (@toplevelres) {
+                    my @printable;
+                    if ($perm{'pav'} || $perm{'pfo'}) {
+                        @printable = @toplevelres;
+                    } else {
+                        @printable = $navmap->retrieveResources(undef,sub { $_[0]->resprintable() },0,1);
+                    }
+                    if (@printable) {
+                        $sequenceTitle = 'Main Content';
+                        $mapTitle = $sequenceTitle;
+                    }
+                }
+            }
+        }
+    } else {
+        ($resourceTitle,$sequenceTitle,$mapTitle) = &details_for_menu($helper);
     }
-    $helper->{VARS}->{'symb'}=
-	&Apache::lonenc::check_encrypt($helper->{VARS}->{'symb'});
-    my ($resourceTitle,$sequenceTitle,$mapTitle) = &details_for_menu($helper);
     if ($sequenceTitle ne '') {$helper->{VARS}->{'assignment'}=$sequenceTitle;}
 
     
@@ -4037,6 +4264,7 @@ sub printHelper {
     my $subdir;
     my $is_published=0;		# True when printing from resource space.
     my $res_printable = 1;	# By default the current resource is printable.    
+    my $res_error;
     my $userCanPrint = ($perm{'pav'} || $perm{'pfo'});
     my $res_printstartdate;
     my $res_printenddate;
@@ -4058,13 +4286,36 @@ sub printHelper {
 	    ($map, $id, $url) = &Apache::lonnet::decode_symb($symb);
 	    $helper->{VARS}->{'postdata'} = 
 		&Apache::lonenc::check_encrypt(&Apache::lonnet::clutter($url));
-	    my $navmap = Apache::lonnavmaps::navmap->new();
-	    my $res   = $navmap->getBySymb($symb);
-	    $res_printable  = $res->resprintable() || $userCanPrint; #printability in course context
-	    ($res_printstartdate, $res_printenddate) = 	&get_print_dates($res);
-	    ($course_open, $course_close) = &course_print_dates($res);
-	    ($map_open, $map_close)       = &map_print_dates($res);
-
+        } elsif (($helper->{VARS}->{'postdata'} eq '/adm/navmaps') &&
+                ($env{'request.course.id'} ne '')) {
+            if ($env{'course.'.$env{'request.course.id'}.'.url'} eq
+                "uploaded/$cdom/$cnum/default.sequence") {
+                $map = $env{'course.'.$env{'request.course.id'}.'.url'};
+                $url = $helper->{VARS}->{'postdata'};
+            }
+        }
+        if (($symb ne '') || ($map ne '')) {
+            if (!$userCanPrint) {
+	        my $navmap = Apache::lonnavmaps::navmap->new();
+                if (ref($navmap)) {
+                    my $res;
+                    if ($symb ne '') {
+	                $res = $navmap->getBySymb($symb);
+                    } elsif ($map ne '') {
+                        $res = $navmap->getResourceByUrl($map);
+                    }
+                    if (ref($res)) {
+	                $res_printable = $res->resprintable(); #printability in course context
+	                ($res_printstartdate, $res_printenddate) = &get_print_dates($res);
+	                ($course_open, $course_close) = &course_print_dates($res);
+	                ($map_open, $map_close) = &map_print_dates($res);
+                    } else {
+                        $res_error = 1; 
+                    }
+                } else {
+                    $res_error = 1;
+                }
+            }
 	} else {
 	    # Resource space.
 
@@ -4076,7 +4327,11 @@ sub printHelper {
             my $postdata = $helper->{VARS}->{'postdata'};
             $resourceTitle = substr($postdata, rindex($postdata, '/') + 1);
         }
-        $subdir = &Apache::lonnet::filelocation("", $url);
+        if (($url eq '/adm/navmaps') && ($map eq $env{'course.'.$env{'request.course.id'}.'.url'})) {
+            $res_printable=0;
+        } else {
+            $subdir = &Apache::lonnet::filelocation("", $url);
+        }
 
 
     }
@@ -4180,7 +4435,7 @@ sub printHelper {
 		}
         my $helperFragment = &generate_resource_chooser('CHOOSE_PROBLEMS_PAGE',
 							'Select Problem(s) to print',
-							"multichoice='1' toponly='1' addstatus='1' closeallpages='1'",
+							"multichoice='1' toponly='1' addstatus='1' closeallpages='1' modallink='1'",
 							'RESOURCES',
 							'PAGESIZE',
 							$url,
@@ -4190,14 +4445,14 @@ sub printHelper {
 
       $helperFragment .= &generate_resource_chooser('CHOOSE_RESOURCES_PAGE',
 						    'Select Resource(s) to print',
-						    'multichoice="1" toponly="1" addstatus="1" closeallpages="1"',
+						    'multichoice="1" toponly="1" addstatus="1" closeallpages="1" modallink="1" suppressNavmap="1"',
 						    'RESOURCES',
 						    'PAGESIZE',
 						    $url,
 						    $isNotMap, '', $symbFilter,
 						    $start_new_option);
 
-						    
+
 
 
 
@@ -4215,20 +4470,25 @@ sub printHelper {
 	# the exact form of this depends on whether or not we are privileged or a mere
 	# plebe of s student:
 
+        my $optionText    = '';
 	my $printSelector = 'map_incomplete_problems_seq';
 	my $nextState     = 'CHOOSE_INCOMPLETE_SEQ';
 	my $textSuffix    = '';
+        my $nocurrloc = '';
+        if ($helper->{VARS}->{'postdata'} eq '/adm/navmaps') {
+            $nocurrloc = 1;
+        }
 
 	if ($userCanPrint)  {
 	    $printSelector = 'map_incomplete_problems_people_seq';
 	    $nextState     = 'CHOOSE_INCOMPLETE_PEOPLE_SEQ';
 	    $textSuffix    = ' for selected students';
 	    my $helperStates =
-		&create_incomplete_folder_selstud_helper($helper, $map); 
+		&create_incomplete_folder_selstud_helper($helper, $map, $nocurrloc); 
 	    &Apache::lonxml::xmlparse($r, 'helper', $helperStates);
 	} else {
 	    if (&printable($map_open, $map_close)) {
-		my $helperStates = &create_incomplete_folder_helper($helper, $map); # Create needed states for student.
+		my $helperStates = &create_incomplete_folder_helper($helper, $map, $nocurrloc); # Create needed states for student.
 		&Apache::lonxml::xmlparse($r, 'helper', $helperStates);
 	    } else {
 		# TODO: Figure out how to break the news...this folder is not printable.
@@ -4236,26 +4496,41 @@ sub printHelper {
 	}
 
 	if ($userCanPrint || &printable($map_open, $map_close)) {
+            if ($helper->{VARS}->{'postdata'} eq '/adm/navmaps') {
+                $optionText = &mt('Selected [_1]Incomplete Problems[_2] [_3]not in a folder[_4]' . $textSuffix,
+                                  '<b>','</b>','<i>','</i>');
+            } else {
+                $optionText = &mt('Selected  [_1]Incomplete Problems[_2] from folder [_3]' . $textSuffix,
+                                  '<b>','</b>','<b><i>'.$sequenceTitle.'</b></i>');
+            }
 	    push(@{$printChoices},
-		 [&mt('Selected  [_1]Incomplete Problems[_2] from folder [_3]' . $textSuffix,
-		      '<b>', '</b>',
-		      '<b><i>'. $sequenceTitle . '</b></i>'),
+		 [$optionText,
 		  $printSelector,
 		  $nextState]);
 	}
         # Allow problems from sequence
 	if ($userCanPrint || &printable($map_open, $map_close)) {
+            if ($helper->{VARS}->{'postdata'} eq '/adm/navmaps') {
+                $optionText = &mt('Selected [_1]Problems[_2] [_3]not in a folder[_4]','<b>','</b>','<i>','</i>');
+            } else {
+                $optionText = &mt('Selected [_1]Problems[_2] from folder [_3]','<b>','</b>','<b><i>'.$sequenceTitle.'</i></b>');
+            }
 	    push @{$printChoices}, 
-	    [&mt('Selected [_1]Problems[_2] from folder [_3]','<b>','</b>','<b><i>'.$sequenceTitle.'</i></b>'), 
+	    [$optionText, 
 	     'map_problems', 
 	     'CHOOSE_PROBLEMS'];
 	    # Allow all resources from sequence
-	    push @{$printChoices}, [&mt('Selected [_1]Resources[_2] from folder [_3]','<b>','</b>','<b><i>'.$sequenceTitle.'</i></b>'), 
+            if ($helper->{VARS}->{'postdata'} eq '/adm/navmaps') {
+                $optionText = &mt('Selected [_1]Resources[_2] [_3]not in a folder[_4]','<b>','</b>','<i>','</i>');
+            } else {
+                $optionText = &mt('Selected [_1]Resources[_2] from folder [_3]','<b>','</b>','<b><i>'.$sequenceTitle.'</i></b>');
+            }
+	    push @{$printChoices}, [$optionText, 
 				    'map_problems_pages', 
 				    'CHOOSE_PROBLEMS_HTML'];
 	    my $helperFragment = &generate_resource_chooser('CHOOSE_PROBLEMS',
 							    'Select Problem(s) to print',
-							    'multichoice="1" toponly="1" addstatus="1" closeallpages="1"',
+							    'multichoice="1" toponly="1" addstatus="1" closeallpages="1" modallink="1" nocurrloc="'.$nocurrloc.'"',
 							    'RESOURCES',
 							    'PAGESIZE',
 							    $map,
@@ -4264,7 +4539,7 @@ sub printHelper {
 							    $start_new_option);
 	    $helperFragment .= &generate_resource_chooser('CHOOSE_PROBLEMS_HTML',
 							  'Select Resource(s) to print',
-							  'multichoice="1" toponly="1" addstatus="1" closeallpages="1"',
+							  'multichoice="1" toponly="1" addstatus="1" closeallpages="1" modallink="1" nocurrloc="'.$nocurrloc.'" suppressNavmap="1"',
 							  'RESOURCES',
 							  'PAGESIZE',
 							  $map,
@@ -4282,7 +4557,7 @@ sub printHelper {
 	my $post_data = $helper->{VARS}->{'postdata'};
     
     if ($perm{'pfo'} &&  !$is_published  &&
-        ($post_data=~/\/res\// || $post_data =~/\/(syllabus|smppg|aboutme|bulletinboard)$/)) { 
+        ($post_data=~/\/res\// || $post_data =~/\/(syllabus|smppg|aboutme|bulletinboard)$/)) {
 
 	# BZ 5209 - incomplete problems from entire course:
 
@@ -4312,7 +4587,7 @@ ALL_PROBLEMS
          &Apache::lonxml::xmlparse($r, 'helper', 
 				   &generate_resource_chooser('ALL_PROBLEMS',
 							      'Select Problem(s) to print',
-							      'multichoice="1" suppressEmptySequences="0" addstatus="1" closeallpages="1"',
+							      'multichoice="1" suppressEmptySequences="0" addstatus="1" closeallpages="1" modallink="1"',
 							      'RESOURCES',
 							      'PAGESIZE',
 							      '',
@@ -4321,7 +4596,7 @@ ALL_PROBLEMS
 							      $start_new_option) .
 				   &generate_resource_chooser('ALL_RESOURCES',
 							      'Select Resource(s) to print',
-							      " toponly='0' multichoice='1' suppressEmptySequences='0' addstatus='1' closeallpages='1'",
+							      'toponly="0" multichoice="1" suppressEmptySequences="0" addstatus="1" closeallpages="1" modallink="1" suppressNavmap="1"',
 							      'RESOURCES',
 							      'PAGESIZE',
 							      '',
@@ -4329,7 +4604,7 @@ ALL_PROBLEMS
 							      $start_new_option) .
 				   &generate_resource_chooser('ALL_PROBLEMS_STUDENTS',
 							      'Select Problem(s) to print',
-							      'toponly="0" multichoice="1" suppressEmptySequences="0" addstatus="1" closeallpages="1"',
+							      'toponly="0" multichoice="1" suppressEmptySequences="0" addstatus="1" closeallpages="1" modallink="1"',
 							      'RESOURCES',
 							      'STUDENTS1',
 							      '',
@@ -4359,138 +4634,8 @@ ALL_PROBLEMS
 				    'problems_for_anon', 'CHOOSE_ANON1'];
 	}
 
-	my $randomly_ordered_warning = 
-            &get_randomly_ordered_warning($helper, $map);
-
-	# resource_selector will hold a few states that:
-	#   - Allow resources to be selected for printing.
-	#   - Determine pagination between assignments.
-	#   - Determine how many assignments should be bundled into a single PDF.
-        # TODO:
-	#    Probably good to do things like separate this up into several vars, each
-	#    with one state, and use REGEXPs at inclusion time to set state names
-	#    and next states for better mix and match capability
-	#
-	my $resource_selector= &generate_resource_chooser('SELECT_PROBLEMS',
-							  'Select resources to print',
-							  'multichoice="1" addstatus="1" closeallpages="1"',
-							  'RESOURCES', 
-							  'PRINT_FORMATTING',
-							  $map,
-							  $isProblem, '', $symbFilter,
-							  $start_new_option);
-	$resource_selector .=  &generate_format_selector($helper,
-                                                         'How should results be printed?',
-                                                         'PRINT_FORMATTING').
-                               &generate_resource_chooser('CHOOSE_STUDENTS_PAGE',
-							'Select Problem(s) to print',
-							"multichoice='1' addstatus='1' closeallpages ='1'",
-							'RESOURCES',
-							'PRINT_FORMATTING',
-							$url,
-							$isProblem, '',  $symbFilter,
-							$start_new_option);
-
-
-# Generate student choosers.
-
-
-
-        &Apache::lonxml::xmlparse($r, 'helper',
-				  &generate_student_chooser('CHOOSE_TGT_STUDENTS_PAGE',
-							    'student_sort',
-							    'STUDENTS',
-							    'CHOOSE_STUDENTS_PAGE'));
-	&Apache::lonxml::xmlparse($r, 'helper', 
-				  &generate_student_chooser('CHOOSE_STUDENTS',
-							    'student_sort',
-							    'STUDENTS',
-							    'SELECT_PROBLEMS'));
-	&Apache::lonxml::xmlparse($r, 'helper', $resource_selector);
-
-	my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
-	my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
-        my @names=&Apache::lonnet::getkeys('CODEs',$cdom,$cnum);
-	my $namechoice='<choice></choice>';
-	foreach my $name (sort {uc($a) cmp uc($b)} @names) {
-	    if ($name =~ /^error: 2 /) { next; }
-	    if ($name =~ /^type\0/) { next; }
-	    $namechoice.='<choice computer="'.$name.'">'.$name.'</choice>';
-	}
-
-
-	my %code_values;
-	my %codes_to_print;
-	foreach my $key (@names) {
-	    %code_values = &Apache::grades::get_codes($key, $cdom, $cnum);
-	    foreach my $key (keys(%code_values)) {
-		$codes_to_print{$key} = 1;
-	    }
-	}
-
-	my $code_selection;
-	foreach my $code (sort {uc($a) cmp uc($b)} (keys(%codes_to_print))) {
-	    my $choice  = $code;
-	    if ($code =~ /^[A-Z]+$/) { # Alpha code
-		$choice = &letters_to_num($code);
-	    }
-	    push(@{$helper->{DATA}{ALL_CODE_CHOICES}},[$code,$choice]);
-	}
-	if (%codes_to_print) {
-	    $code_selection .='   
-	    <message><b>Choose single CODE from list:</b></message>
-		<message></td><td></message>
-		<dropdown variable="CODE_SELECTED_FROM_LIST" multichoice="0" allowempty="0">
-                  <choice></choice>
-                  <exec>
-                     push(@{$state->{CHOICES}},@{$helper->{DATA}{ALL_CODE_CHOICES}});
-                  </exec>
-		</dropdown>
-	    <message></td></tr><tr><td></message>
-            '.$/;
-
-	}
-
-        my @lines = &Apache::grades::get_scantronformat_file();
-	my $codechoice='';
-	foreach my $line (@lines) {
-            next if (($line =~ /^\#/) || ($line eq ''));
-	    my ($name,$description,$code_type,$code_length)=
-		(split(/:/,$line))[0,1,2,4];
-	    if ($code_length > 0 && 
-		$code_type =~/^(letter|number|-1)/) {
-		$codechoice.='<choice computer="'.$name.'">'.$description.'</choice>';
-	    }
-	}
-	if ($codechoice eq '') {
-	    $codechoice='<choice computer="default">Default</choice>';
-	}
-	my $anon1 = &generate_code_selector($helper, 
-					    'CHOOSE_ANON1',
-					    'SELECT_PROBLEMS',
-					    $codechoice,
-					    $code_selection,
-					    $namechoice) . $resource_selector;
-					    
-					    
-        &Apache::lonxml::xmlparse($r, 'helper',$anon1);
-
-	my $anon_page = &generate_code_selector($helper,
-						'CHOOSE_ANON1_PAGE',
-						'SELECT_PROBLEMS_PAGE',
-						$codechoice,
-						$code_selection,
-						$namechoice) .
-			&generate_resource_chooser('SELECT_PROBLEMS_PAGE',
-						   'Select Problem(s) to print',
-						   "multichoice='1' addstatus='1' closeallpages ='1'",
-						   'RESOURCES',
-						   'PRINT_FORMATTING',
-						   $url,
-						   $isProblem, '',  $symbFilter,
-						   $start_new_option);
-	&Apache::lonxml::xmlparse($r, 'helper', $anon_page);
-
+        my ($randomly_ordered_warning,$codechoice,$code_selection,$namechoice) =
+            &generate_common_choosers($r,$helper,$map,$url,$isProblem,$symbFilter,$start_new_option);
 
 	if ($helper->{VARS}->{'assignment'}) {
 
@@ -4499,15 +4644,24 @@ ALL_PROBLEMS
 	    push @{$printChoices}, [&mt('Selected [_1]Resources[_2] from folder [_3] for [_4]selected people[_5]','<b>','</b>','<b><i>'.$sequenceTitle.'</i></b>','<b>','</b>'), 'resources_for_students', 'CHOOSE_STUDENTS1'];
 	    push @{$printChoices}, [&mt('Selected [_1]Resources[_2] from folder [_3] for [_4]CODEd assignments[_5]','<b>','</b>','<b><i>'.$sequenceTitle.'</i></b>','<b>','</b>'), 'resources_for_anon', 'CHOOSE_ANON2'];
 	}
-	    
 
-	$resource_selector=<<RESOURCE_SELECTOR;
+        # resource_selector will hold a few states that:
+        #   - Allow resources to be selected for printing.
+        #   - Determine pagination between assignments.
+        #   - Determine how many assignments should be bundled into a single PDF.
+        # TODO:
+        #    Probably good to do things like separate this up into several vars, each
+        #    with one state, and use REGEXPs at inclusion time to set state names
+        #    and next states for better mix and match capability
+        #
+
+	my $resource_selector=<<RESOURCE_SELECTOR;
     <state name="SELECT_RESOURCES" title="Select Resources">
     $randomly_ordered_warning
     <nextstate>PRINT_FORMATTING</nextstate>
     <message><br /><big><i><b>Select resources for the assignment</b></i></big><br /></message>
     <resource variable="RESOURCES" multichoice="1" addstatus="1" 
-              closeallpages="1">
+              closeallpages="1" modallink="1">
       <filterfunc>return $isNotMap;</filterfunc>
       <mapurl>$map</mapurl>
       <valuefunc>return $symbFilter;</valuefunc>
@@ -4598,6 +4752,7 @@ CHOOSE_ANON2
 
     # FIXME: That RE should come from a library somewhere.
     if (($perm{'pav'} 
+        && ($subdir ne '') 
 	&& $subdir ne $Apache::lonnet::perlvar{'lonDocRoot'}.'/res/'
 	&& (defined($helper->{'VARS'}->{'construction'})
 	    ||
@@ -4631,14 +4786,118 @@ CHOOSE_FROM_SUBDIR
 
     # Allow the user to select any sequence in the course, feed it to
     # another resource selector for that sequence
-    if (!$helper->{VARS}->{'construction'} && !$is_published) {
-	push @$printChoices, [&mtn("Selected <b>Resources</b> from <b>selected folder</b> in course"),
-			      'select_sequences', 'CHOOSE_SEQUENCE'];
-	my $escapedSequenceName = $helper->{VARS}->{'SEQUENCE'};
-	#Escape apostrophes and backslashes for Perl
-	$escapedSequenceName =~ s/\\/\\\\/g;
-	$escapedSequenceName =~ s/'/\\'/g;
-	&Apache::lonxml::xmlparse($r, 'helper', <<CHOOSE_FROM_ANY_SEQUENCE);
+    if ((!$helper->{VARS}->{'construction'}) &&
+        (!$is_published || (($subdir eq '') && ($url eq '/adm/navmaps')))) {
+        push @$printChoices, [&mtn("Selected <b>Resources</b> from <b>selected folder</b> in course"),
+                              'select_sequences', 'CHOOSE_SEQUENCE'];
+        my $escapedSequenceName;
+        if ($helper->{VARS}->{'SEQUENCE'} ne '') {
+            $escapedSequenceName = $helper->{VARS}->{'SEQUENCE'};
+        } elsif (($subdir eq '') && ($url eq '/adm/navmaps')) {
+            my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+            my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+            if ($env{'course.'.$env{'request.course.id'}.'.url'} eq
+                "uploaded/$cdom/$cnum/default.sequence") {
+                $escapedSequenceName = $env{'course.'.$env{'request.course.id'}.'.url'};
+            }
+        }
+        #Escape apostrophes and backslashes for Perl
+        $escapedSequenceName =~ s/\\/\\\\/g;
+        $escapedSequenceName =~ s/'/\\'/g;
+        if (($subdir eq '') && ($url eq '/adm/navmaps')) {
+            if ($perm{'pfo'}) {
+                push(@{$printChoices},
+                    [&mt('Selected [_1]Problems[_2] from [_3]selected folder[_4] in course for [_5]selected people[_6]',
+                         '<b>','</b>','<b>','</b>','<b>','</b>'),
+                         'select_sequences_problems_for_students','CHOOSE_SEQUENCE_STUDENTS'],
+                    [&mt('Selected [_1]Problems[_2] from [_3]selected folder[_4] in course  for [_5]CODEd assignments[_6]',
+                         '<b>','</b>','<b>','</b>','<b>','</b>'),
+                         'select_sequences_problems_for_anon','CHOOSE_SEQUENCE_ANON1'],
+                    [&mt('Selected [_1]Resources[_2] from [_3]selected folder[_4] in course for [_5]selected people[_6]',
+                         '<b>','</b>','<b>','</b>','<b>','</b>'),
+                         'select_sequences_resources_for_students','CHOOSE_SEQUENCE_STUDENTS1'],
+                    [&mt('Selected [_1]Resources[_2] from [_3]selected folder[_4] in course for [_5]CODEd assignments[_6]',
+                         '<b>','</b>','<b>','</b>','<b>','</b>'),
+                         'select_sequences_resources_for_anon','CHOOSE_SEQUENCE_ANON2'],
+                    [&mt('Selected [_1]Resources[_2] from [_3]selected folder[_4] in course',
+                         '<b>','</b>','<b>','</b>'),
+                         'select_sequences','CHOOSE_SEQUENCE']);
+                if ($escapedSequenceName) {
+                    &generate_common_choosers($r,$helper,$escapedSequenceName,$escapedSequenceName,$isProblem,$symbFilter,$start_new_option);
+                }
+            } else {
+                push(@{$printChoices},
+                [&mt('Selected [_1]Resources[_2] from [_3]selected folder[_4] in course',
+                     '<b>','</b>','<b>','</b>'),
+                     'select_sequences','CHOOSE_SEQUENCE']);
+            }
+        }
+        if (($subdir eq '') && ($url eq '/adm/navmaps') && ($perm{'pfo'})) {
+           &Apache::lonxml::xmlparse($r, 'helper', <<CHOOSE_FROM_ANY_SEQUENCE);
+  <state name="CHOOSE_SEQUENCE" title="Select Sequence To Print From">
+    <message>Select the sequence to print resources from:</message>
+    <resource variable="SEQUENCE">
+      <nextstate>CHOOSE_FROM_ANY_SEQUENCE</nextstate>
+      <filterfunc>return &Apache::lonprintout::printable_sequence(\$res);</filterfunc>
+      <valuefunc>return $urlValue;</valuefunc>
+      <choicefunc>return \$res->hasResource(\$res,sub { return !\$_[0]->is_sequence() },0,0);
+        </choicefunc>
+      </resource>
+    </state>
+  <state name="CHOOSE_SEQUENCE_STUDENTS" title="Select Sequence To Print From">
+    <message>Select the sequence to print resources from:</message>
+    <resource variable="SEQUENCE">
+      <nextstate>CHOOSE_STUDENTS</nextstate>
+      <filterfunc>return &Apache::lonprintout::printable_sequence(\$res);</filterfunc>
+      <valuefunc>return $urlValue;</valuefunc>
+      <choicefunc>return \$res->hasResource(\$res,sub { return !\$_[0]->is_sequence() },0,0);
+        </choicefunc>
+      </resource>
+    </state>
+  <state name="CHOOSE_SEQUENCE_ANON1" title="Select Sequence To Print From">
+    <message>Select the sequence to print resources from:</message>
+    <resource variable="SEQUENCE">
+      <nextstate>CHOOSE_ANON1</nextstate>
+      <filterfunc>return &Apache::lonprintout::printable_sequence(\$res);</filterfunc>
+      <valuefunc>return $urlValue;</valuefunc>
+      <choicefunc>return \$res->hasResource(\$res,sub { return !\$_[0]->is_sequence() },0,0);
+        </choicefunc>
+      </resource>
+    </state>
+  <state name="CHOOSE_SEQUENCE_STUDENTS1" title="Select Sequence To Print From">
+    <message>Select the sequence to print resources from:</message>
+    <resource variable="SEQUENCE">
+      <nextstate>CHOOSE_STUDENTS</nextstate>
+      <filterfunc>return &Apache::lonprintout::printable_sequence(\$res);</filterfunc>
+      <valuefunc>return $urlValue;</valuefunc>
+      <choicefunc>return \$res->hasResource(\$res,sub { return !\$_[0]->is_sequence() },0,0);
+        </choicefunc>
+      </resource>
+    </state>
+  <state name="CHOOSE_SEQUENCE_ANON2" title="Select Sequence To Print From">
+    <message>Select the sequence to print resources from:</message>
+    <resource variable="SEQUENCE">
+      <nextstate>CHOOSE_ANON1</nextstate>
+      <filterfunc>return &Apache::lonprintout::printable_sequence(\$res);</filterfunc>
+      <valuefunc>return $urlValue;</valuefunc>
+      <choicefunc>return \$res->hasResource(\$res,sub { return !\$_[0]->is_sequence() },0,0);
+        </choicefunc>
+      </resource>
+    </state>
+  <state name="CHOOSE_FROM_ANY_SEQUENCE" title="Select Resources To Print">
+    <message>(mark desired resources then click "next" button) <br /></message>
+    <resource variable="RESOURCES" multichoice="1" toponly='1' addstatus="1"
+              closeallpages="1" modallink="1">
+      <nextstate>PAGESIZE</nextstate>
+      <filterfunc>return $isNotMap</filterfunc>
+      <mapurl evaluate='1'>return '$escapedSequenceName';</mapurl>
+      <valuefunc>return $symbFilter;</valuefunc>
+      $start_new_option
+      </resource>
+    </state>
+CHOOSE_FROM_ANY_SEQUENCE
+        } else {
+	    &Apache::lonxml::xmlparse($r, 'helper', <<CHOOSE_FROM_ANY_SEQUENCE);
   <state name="CHOOSE_SEQUENCE" title="Select Sequence To Print From">
     <message>Select the sequence to print resources from:</message>
     <resource variable="SEQUENCE">
@@ -4652,7 +4911,7 @@ CHOOSE_FROM_SUBDIR
   <state name="CHOOSE_FROM_ANY_SEQUENCE" title="Select Resources To Print">
     <message>(mark desired resources then click "next" button) <br /></message>
     <resource variable="RESOURCES" multichoice="1" toponly='1' addstatus="1"
-              closeallpages="1">
+              closeallpages="1" modallink="1">
       <nextstate>PAGESIZE</nextstate>
       <filterfunc>return $isNotMap</filterfunc>
       <mapurl evaluate='1'>return '$escapedSequenceName';</mapurl>
@@ -4661,28 +4920,47 @@ CHOOSE_FROM_SUBDIR
       </resource>
     </state>
 CHOOSE_FROM_ANY_SEQUENCE
-}
+        }
+    }
+    my $numchoices = 0;
+    if (ref($printChoices) eq 'ARRAY') {
+        $numchoices = @{$printChoices};
+    }
+    # Early out if nothing to print
+    if (!$numchoices) {
+        $r->print(&Apache::loncommon::start_page('Printing Helper').
+                  '<h2>'.&mt('Unable to determine print context').'</h2>'.
+                  '<p>'.&mt('Please display a resource, and then click the "Print" button/icon').'</p>');
+        my $prtspool=$r->dir_config('lonPrtDir');
+        my $footer = &recently_generated($prtspool);
+        $r->print($footer.&Apache::loncommon::end_page());
+        return OK;
+    }
 
     # Generate the first state, to select which resources get printed.
     Apache::lonhelper::state->new("START", "Select Printing Options:");
     if (!$res_printable) {
-        my $now = time;
-        my $shownprintstart = &Apache::lonlocal::locallocaltime($res_printstartdate);
-        my $shownprintend = &Apache::lonlocal::locallocaltime($res_printenddate);
         my $noprintmsg;
-        if (($res_printenddate) && ($res_printenddate < $now)) {
+        if ($res_error) {
+            $noprintmsg = &mt('Print availability for current resource could not be determined');
+        } else {
+            my $now = time;
+            my $shownprintstart = &Apache::lonlocal::locallocaltime($res_printstartdate);
+            my $shownprintend = &Apache::lonlocal::locallocaltime($res_printenddate);
+            if (($res_printenddate) && ($res_printenddate < $now)) {
                 $noprintmsg = &mt('Printing for current resource no longer available (ended: [_1])',
                                   $shownprintend);
-        } else {
-            if (($res_printstartdate) && ($res_printstartdate > $now)) {
-                if (($res_printenddate) && ($res_printenddate > $now) && ($res_printenddate > $res_printstartdate)) {
-                    $noprintmsg = &mt('Printing for current resource is only possible between [_1] and [_2]',
-                                  $shownprintstart,$shownprintend);
-                } elsif (!$res_printenddate) {
-                    $noprintmsg = &mt('Printing for current resource will only be possible starting [_1]',
-                                      $shownprintstart);
-                } else {
-                    $noprintmsg = &mt('Printing for current resource is unavailable');
+            } else {
+                if (($res_printstartdate) && ($res_printstartdate > $now)) {
+                    if (($res_printenddate) && ($res_printenddate > $now) && ($res_printenddate > $res_printstartdate)) {
+                        $noprintmsg = &mt('Printing for current resource is only possible between [_1] and [_2]',
+                                          $shownprintstart,$shownprintend);
+                    } elsif (!$res_printenddate) {
+                        $noprintmsg = &mt('Printing for current resource will only be possible starting [_1]',
+                                          $shownprintstart);
+                    } else {
+                        $noprintmsg = &mt('Printing for current resource is unavailable');
+                    }
                 }
             }
         }
@@ -4738,7 +5016,7 @@ CHOOSE_FROM_ANY_SEQUENCE
             my $xmlfrag = << "FONT_SELECTION";
 
           
-            <dropdown variable='fontsize' multichoice='0', allowempty='0'>
+            <dropdown variable='fontsize' multichoice='0' allowempty='0'>
             <defaultvalue>
 		  return 'normalsize';
             </defaultvalue>
@@ -5034,9 +5312,9 @@ sub render {
     my $PaperType=&mt('Paper type');
     my $landscape=&mt('Landscape');
     my $portrait=&mt('Portrait');
-    my $pdfFormLabel=&mt('PDF-Formfields');
-    my $with=&mt('with Formfields');
-    my $without=&mt('without Formfields');
+    my $pdfFormLabel=&mt('PDF Form Fields');
+    my $with=&mt('with Form Fields');
+    my $without=&mt('without Form Fields');
     
 
     $result.='<h3>'.&mt('Layout Options').'</h3>'