--- loncom/interface/lonprintout.pm 2006/05/30 12:46:09 1.439 +++ loncom/interface/lonprintout.pm 2007/01/15 11:53:50 1.495 @@ -1,7 +1,8 @@ +# # The LearningOnline Network # Printout # -# $Id: lonprintout.pm,v 1.439 2006/05/30 12:46:09 www Exp $ +# $Id: lonprintout.pm,v 1.495 2007/01/15 11:53:50 foxr Exp $ # # Copyright Michigan State University Board of Trustees # @@ -22,7 +23,6 @@ # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # /home/httpd/html/adm/gpl.txt -# # http://www.lon-capa.org/ # # @@ -38,14 +38,126 @@ use Apache::grades; use Apache::edit; use Apache::File(); use Apache::lonnavmaps; -use Apache::lonratedt; +use LONCAPA::map(); use POSIX qw(strftime); use Apache::lonlocal; use Carp; -use lib '/home/httpd/lib/perl/'; use LONCAPA; my %perm; +my %parmhash; +my $resources_printed; + +# +# printf_style_subst item format_string repl +# +# Does printf style substitution for a format string that +# can have %[n]item in it.. wherever, %[n]item occurs, +# rep is substituted in format_string. Note that +# [n] is an optional integer length. If provided, +# repl is truncated to at most [n] characters prior to +# substitution. +# +sub printf_style_subst { + my ($item, $format_string, $repl) = @_; + my $result = ""; + while ($format_string =~ /(%)(\d*)\Q$item\E/g ) { + my $fmt = $1; + my $size = $2; + my $subst = $repl; + if ($size ne "") { + $subst = substr($subst, 0, $size); + + # Here's a nice edge case.. supose the end of the + # substring is a \. In that case may have just + # chopped off a TeX escape... in that case, we append + # " " for the trailing character, and let the field + # spill over a bit (sigh). + # We don't just chop off the last character in order to deal + # with one last pathology, and that would be if substr had + # trimmed us to e.g. \\\ + + + if ($subst =~ /\\$/) { + $subst .= " "; + } + } + my $item_pos = pos($format_string); + $result .= substr($format_string, 0, $item_pos - length($size) -2) . $subst; + $format_string = substr($format_string, pos($format_string)); + } + + # Put the residual format string into the result: + + $result .= $format_string; + + return $result; +} + + +# Format a header according to a format. +# + +# Substitutions: +# %a - Assignment name. +# %c - Course name. +# %n - Student name. +# +sub format_page_header { + my ($width, $format, $assignment, $course, $student) = @_; + + $width = &recalcto_mm($width); # Get width in mm. + # Default format? + + if ($format eq '') { + # For the default format, we may need to truncate + # elements.. To do this we need to get the page width. + # we assume that each character is about 2mm in width. + # (correct for the header text size??). We ignore + # any formatting (e.g. boldfacing in this). + # + # - Allow the student/course to be one line. + # but only truncate the course. + # - Allow the assignment to be 2 lines (wrapped). + # + my $chars_per_line = $width/2; # Character/textline. + + + my $firstline = "$student $course"; + if (length($firstline) > $chars_per_line) { + my $lastchar = $chars_per_line - length($student) - 1; + if ($lastchar > 0) { + $course = substr($course, 0, $lastchar); + } else { # Nothing left of course: + $course = ''; + } + } + if (length($assignment) > $chars_per_line) { + $assignment = substr($assignment, 0, $chars_per_line); + } + + $format = "\\textbf{$student} $course \\hfill \\thepage \\\\ \\textit{$assignment}"; + + } else { + # An open question is how to handle long user formatted page headers... + # A possible future is to support e.g. %na so that the user can control + # the truncation of the elements that can appear in the header. + # + $format = &printf_style_subst("a", $format, $assignment); + $format = &printf_style_subst("c", $format, $course); + $format = &printf_style_subst("n", $format, $student); + + # If the user put %'s in the format string, they must be escaped + # to \% else LaTeX will think they are comments and terminate + # the line.. which is bad!!! + + + } + + + return $format; + +} # # Convert a numeric code to letters @@ -63,7 +175,7 @@ sub num_to_letters { sub letters_to_num { my ($letters) = @_; my @letters = split('', uc($letters)); - my %substitution; + my %substitution; my $digit = 0; foreach my $letter ('A'..'J') { $substitution{$letter} = $digit; @@ -378,7 +490,7 @@ sub character_chart { $result =~ s/&\#147;/\`\`/g; $result =~ s/&\#148;/\'\'/g; $result =~ s/&\#149;/\\ensuremath\{\\bullet\}/g; - $result =~ s/&\#150;/--/g; + $result =~ s/&(\#150|\#8211);/--/g; $result =~ s/&\#151;/---/g; $result =~ s/&\#152;/\\ensuremath\{\\sim\}/g; $result =~ s/&\#153;/\\texttrademark /g; @@ -585,6 +697,20 @@ sub character_chart { $result =~ s/&(clubs|\#9827);/\\ensuremath\{\\clubsuit\}/g; $result =~ s/&(hearts|\#9829);/\\ensuremath\{\\heartsuit\}/g; $result =~ s/&(diams|\#9830);/\\ensuremath\{\\diamondsuit\}/g; +# Chemically useful 'things' contributed by Hon Kie (bug 4652). + $result =~ s/&\#8636;/\\ensuremath\{\\leftharpoonup\}/g; + $result =~ s/&\#8637;/\\ensuremath\{\\leftharpoondown\}/g; + $result =~ s/&\#8640;/\\ensuremath\{\\rightharpoonup\}/g; + $result =~ s/&\#8641;/\\ensuremath\{\\rightharpoondown\}/g; + $result =~ s/&\#8652;/\\ensuremath\{\\rightleftharpoons\}/g; + $result =~ s/&\#8605;/\\ensuremath\{\\leadsto\}/g; + $result =~ s/&\#8617;/\\ensuremath\{\\hookleftarrow\}/g; + $result =~ s/&\#8618;/\\ensuremath\{\\hookrightarrow\}/g; + $result =~ s/&\#8614;/\\ensuremath\{\\mapsto\}/g; + $result =~ s/&\#8599;/\\ensuremath\{\\nearrow\}/g; + $result =~ s/&\#8600;/\\ensuremath\{\\searrow\}/g; + $result =~ s/&\#8601;/\\ensuremath\{\\swarrow\}/g; + $result =~ s/&\#8598;/\\ensuremath\{\\nwarrow\}/g; return $result; } @@ -593,12 +719,12 @@ sub character_chart { my %page_formats= ('letter' => { 'book' => { - '1' => [ '7.1 in','9.8 in', '-0.57 in','-0.57 in','0.7 cm'], - '2' => ['3.66 in','9.8 in', '-0.57 in','-0.57 in','0.7 cm'] + '1' => [ '7.1 in','9.8 in', '-0.57 in','-0.57 in','0.275 in'], + '2' => ['3.66 in','9.8 in', '-0.57 in','-0.57 in','0.275 in'] }, 'album' => { - '1' => [ '8.8 in', '6.8 in','-40 pt in', '-60 pt','1 cm'], - '2' => [ '4.4 in', '6.8 in','-0.5 in', '-1.5 in','3.5 in'] + '1' => [ '8.8 in', '6.8 in','-0.55 in', '-0.55 in','1.0 in'], + '2' => [ '4.8 in', '6.8 in','-0.5 in', '-1.0 in','3.5 in'] }, }, 'legal' => { @@ -653,12 +779,12 @@ my %page_formats= }, 'a4' => { 'book' => { - '1' => ['176 mm','272 mm','-40 pt in','-60 pt','-0.5 in'], - '2' => [ '91 mm','272 mm','-40 pt in','-60 pt','-0.5 in'] + '1' => ['17.6 cm','27.2 cm','-1.397 cm','-2.11 cm','-1.27 cm'], + '2' => [ '9.1 cm','27.2 cm','-1.397 c,','-2.11 cm','-1.27 cm'] }, 'album' => { - '1' => ['8.5 in','7.7 in','-40 pt in','-60 pt','0 in'], - '2' => ['3.9 in','7.7 in','-40 pt in','-60 pt','0 in'] + '1' => ['21.59 cm','19.558 cm','-1.27 cm','-2.11 cm','0 cm'], + '2' => ['9.91 cm','19.558 cm','-1.397 cm','-2.11 cm','0 cm'] }, }, 'a5' => { @@ -702,7 +828,7 @@ sub get_name { if (!defined($udom)) { $udom=$env{'user.domain'}; } my $plainname=&Apache::loncommon::plainname($uname,$udom); if ($plainname=~/^\s*$/) { $plainname=$uname.'@'.$udom; } - $plainname=&Apache::lonxml::latex_special_symbols($plainname,'header'); + $plainname=&Apache::lonxml::latex_special_symbols($plainname,'header'); return $plainname; } @@ -717,22 +843,28 @@ sub get_course { sub page_format_transformation { my ($papersize,$layout,$numberofcolumns,$choice,$text,$assignment,$tableofcontents,$indexlist,$selectionmade) = @_; my ($textwidth,$textheight,$oddoffset,$evenoffset,$topmargin); + if ($selectionmade eq '4') { $assignment='Problems from the Whole Course'; } else { $assignment=&Apache::lonxml::latex_special_symbols($assignment,'header'); } ($textwidth,$textheight,$oddoffset,$evenoffset,$topmargin) = &page_format($papersize,$layout,$numberofcolumns,$topmargin); + + my $name = &get_name(); my $courseidinfo = &get_course(); if (defined($courseidinfo)) { $courseidinfo=' - '.$courseidinfo } + my $header_text = $parmhash{'print_header_format'}; + $header_text = &format_page_header($textwidth, $header_text, $assignment, + $courseidinfo, $name); my $topmargintoinsert = ''; if ($topmargin ne '0') {$topmargintoinsert='\setlength{\topmargin}{'.$topmargin.'}';} my $fancypagestatement=''; if ($numberofcolumns eq '2') { - $fancypagestatement="\\fancyhead{}\\fancyhead[LO]{\\textbf{$name} $courseidinfo \\hfill \\thepage \\\\ \\textit{$assignment}}"; + $fancypagestatement="\\fancyhead{}\\fancyhead[LO]{$header_text}"; } else { - $fancypagestatement="\\rhead{}\\chead{}\\lhead{\\textbf{$name} $courseidinfo \\hfill \\thepage \\\\ \\textit{$assignment}}"; + $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\\begin{document}\\voffset=-0\.8 cm\\setcounter{page}{1}\n /; @@ -775,6 +907,8 @@ sub details_for_menu { if (!$postdata) { $postdata=$helper->{VARS}{'postdata'}; } my $name_of_resource = &Apache::lonnet::gettitle($postdata); my $symbolic = &Apache::lonnet::symbread($postdata); + return if ( $symbolic eq ''); + my ($map,$id,$resource)=&Apache::lonnet::decode_symb($symbolic); $map=&Apache::lonnet::clutter($map); my $name_of_sequence = &Apache::lonnet::gettitle($map); @@ -790,16 +924,21 @@ sub details_for_menu { return ($name_of_resource,$name_of_sequence,$name_of_map); } +sub copyright_line { + return '\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}\vspace*{-2 mm}\newline\noindent{\tiny Printed from LON-CAPA\copyright MSU{\hfill} Licensed under GNU General Public License } '; +} +my $end_of_student = "\n".'\special{ps:ENDOFSTUDENTSTAMP}'."\n"; sub latex_corrections { my ($number_of_columns,$result,$selectionmade,$answer_mode) = @_; # $result =~ s/\\includegraphics{/\\includegraphics\[width=\\minipagewidth\]{/g; - $result =~ s/\$number_of_columns/$number_of_columns/g; + my $copyright = ©right_line(); if ($selectionmade eq '1' || $answer_mode eq 'only') { - $result =~ s/(\\end{document})/\\strut\\vskip 0 mm\\noindent\\makebox\[\\textwidth\/$number_of_columns\]\[b\]{\\hrulefill}\\newline\\noindent\\tiny Printed from LON-CAPA\\copyright MSU{\\hfill} Licensed under GNU General Public License $1/; + $result =~ s/(\\end{document})/\\strut\\vskip 0 mm $copyright $end_of_student $1/; } else { - $result =~ s/(\\end{document})/\\strut\\vspace\*{-4 mm}\\newline\\noindent\\makebox\[\\textwidth\/$number_of_columns\]\[b\]{\\hrulefill}\\newline\\noindent\\tiny Printed from LON-CAPA\\copyright MSU{\\hfill} Licensed under GNU General Public License $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; #-- LaTeX corrections @@ -856,7 +995,7 @@ sub IndexCreation { sub print_latex_header { my $mode=shift; - my $output='\documentclass[letterpaper,twoside]{article}'; + my $output='\documentclass[letterpaper,twoside]{article}\raggedbottom'; if (($mode eq 'batchmode') || (!$perm{'pav'})) { $output.='\batchmode'; } @@ -1020,10 +1159,112 @@ sub get_page_breaks { return %page_breaks; } +# Output a sequence (recursively if neeed) +# from construction space. +# Parameters: +# url = URL of the sequence to print. +# helper - Reference to the helper hash. +# form - Copy of the format hash. +# LaTeXWidth +# Returns: +# Text to add to the printout. +# NOTE if the first element of the outermost sequence +# is itself a sequence, the outermost caller may need to +# prefix the latex with the page headers stuff. +# +sub print_construction_sequence { + my ($currentURL, $helper, %form, $LaTeXwidth) = @_; + my $result; + my $rndseed=time; + if ($helper->{'VARS'}->{'curseed'}) { + $rndseed=$helper->{'VARS'}->{'curseed'}; + } + my $errtext=&LONCAPA::map::mapread($currentURL); + # + # These make this all support recursing for subsequences. + # + my @order = @LONCAPA::map::order; + my @resources = @LONCAPA::map::resources; + for (my $member=0;$member<=$#order;$member++) { + $resources[$order[$member]]=~/^([^:]*):([^:]*):/; + my $urlp=$2; + if ($urlp=~/\.(problem|exam|quiz|assess|survey|form|library|xml|html|htm|xhtml|xhtm)$/) { + my $texversion=''; + if ($helper->{'VARS'}->{'ANSWER_TYPE'} ne 'only') { + $form{'problem_split'}=$parmhash{'problem_stream_switch'}; + $form{'suppress_tries'}=$parmhash{'suppress_tries'}; + $form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'}; + $form{'rndseed'}=$rndseed; + $resources_printed .=$urlp.':'; + $texversion=&Apache::lonnet::ssi($urlp,%form); + } + if((($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') || + ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) && + ($urlp=~/\.(problem|exam|quiz|assess|survey|form|library|page)$/)) { + # Don't permanently modify %$form... + my %answerform = %form; + $answerform{'grade_target'}='answer'; + $answerform{'answer_output_mode'}='tex'; + $answerform{'rndseed'}=$rndseed; + $answerform{'problem_split'}=$parmhash{'problem_stream_switch'}; + if ($urlp=~/\/res\//) {$env{'request.state'}='published';} + $resources_printed .= $urlp.':'; + my $answer=&Apache::lonnet::ssi($urlp,%answerform); + if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') { + $texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/; + } else { + # If necessary, encapsulate answer in minipage: + + $texversion=&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'}); + my $title = &Apache::lonnet::gettitle($helper->{'VARS'}->{'symb'}); + $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.'\end{document}'; + $body = &encapsulate_minipage($body); + $texversion.=$body; + } + } + $texversion = &latex_header_footer_remove($texversion); + + if ($helper->{'VARS'}->{'TABLE_INDEX'} eq 'yes') { + $texversion=&IndexCreation($texversion,$urlp); + } + if ($helper->{'VARS'}->{'CONSTR_RESOURSE_URL'} eq 'yes') { + $texversion=~s/(\\addcontentsline\{toc\}\{subsection\}\{[^\}]*\})/$1 URL: \\verb|$urlp| \\strut\\\\\\strut /; + } + $result.=$texversion; + + } elsif ($urlp=~/\.(sequence|page)$/) { + + # header: + + $result.='\strut\newline\noindent Sequence/page '.$urlp.'\strut\newline\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}\newline\noindent '; + + # IF sequence, recurse: + + if ($urlp =~ /\.sequence$/) { + my $sequence_url = $urlp; + my $domain = $env{'user.domain'}; # Constr. space only on local + my $user = $env{'user.name'}; + + $sequence_url =~ s/^\/res\/$domain/\/home/; + $sequence_url =~ s/^(\/home\/$user)/$1\/public_html/; +# $sequence_url =~ s|\/~([^\/]+)\/|\/home\/$1\/public_html\/|; + $result .= &print_construction_sequence($sequence_url, + $helper, %form, + $LaTeXwidth); + } + } + } + if ($helper->{VARS}->{'construction'} eq '1') {$result=~s/(\\begin{document})/$1 \\fbox\{RANDOM SEED IS $rndseed\} /;} + return $result; +} + sub output_data { my ($r,$helper,$rparmhash) = @_; my %parmhash = %$rparmhash; - my $resources_printed = ''; + $resources_printed = ''; my $js = < var editbrowser; @@ -1172,7 +1413,9 @@ ENDPART } else { $texversion=&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'}); if ($helper->{'VARS'}->{'construction'} ne '1') { - $texversion.='\vskip 0 mm \noindent\textbf{'.&Apache::lonnet::gettitle($helper->{'VARS'}->{'symb'}).'}\vskip 0 mm '; + my $title = &Apache::lonnet::gettitle($helper->{'VARS'}->{'symb'}); + $title = &Apache::lonxml::latex_special_symbols($title); + $texversion.='\vskip 0 mm \noindent\textbf{'.$title.'}\vskip 0 mm '; $texversion.=&path_to_problem($cleanURL,$LaTeXwidth); } else { $texversion.='\vskip 0 mm \noindent\textbf{Prints from construction space - there is no title.}\vskip 0 mm '; @@ -1197,70 +1440,15 @@ ENDPART } elsif ($cleanURL!~m|^/adm/| && $currentURL=~/\.sequence$/ && $helper->{'VARS'}->{'construction'} eq '1') { #printing content of sequence from the construction space - my $flag_latex_header_remove = 'NO'; - my $rndseed=time; - if ($helper->{'VARS'}->{'curseed'}) { - $rndseed=$helper->{'VARS'}->{'curseed'}; - } $currentURL=~s|\/~([^\/]+)\/|\/home\/$1\/public_html\/|; - my $errtext=&Apache::lonratedt::mapread($currentURL); - for (my $member=0;$member<=$#Apache::lonratedt::order;$member++) { - $Apache::lonratedt::resources[$Apache::lonratedt::order[$member]]=~/^([^:]*):([^:]*):/; - my $urlp=$2; - if ($urlp=~/\.(problem|exam|quiz|assess|survey|form|library|xml|html|htm|xhtml|xhtm)$/) { - my $texversion=''; - if ($helper->{'VARS'}->{'ANSWER_TYPE'} ne 'only') { - $form{'problem_split'}=$parmhash{'problem_stream_switch'}; - $form{'suppress_tries'}=$parmhash{'suppress_tries'}; - $form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'}; - $form{'rndseed'}=$rndseed; - $resources_printed .=$urlp.':'; - $texversion=&Apache::lonnet::ssi($urlp,%form); - } - if((($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') || - ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) && - ($urlp=~/\.(problem|exam|quiz|assess|survey|form|library|page)$/)) { - # Don't permanently modify %$form... - my %answerform = %form; - $answerform{'grade_target'}='answer'; - $answerform{'answer_output_mode'}='tex'; - $answerform{'rndseed'}=$rndseed; - $answerform{'problem_split'}=$parmhash{'problem_stream_switch'}; - if ($urlp=~/\/res\//) {$env{'request.state'}='published';} - $resources_printed .= $urlp.':'; - my $answer=&Apache::lonnet::ssi($urlp,%answerform); - if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') { - $texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/; - } else { - # If necessary, encapsulate answer in minipage: - - $texversion=&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'}); - my $body ='\vskip 0 mm \noindent\textbf{'.&Apache::lonnet::gettitle($helper->{'VARS'}->{'symb'}).'}\vskip 0 mm '; - $body.=&path_to_problem($urlp,$LaTeXwidth); - $body.='\vskip 1 mm '.$answer.'\end{document}'; - $body = &encapsulate_minipage($body); - $texversion.=$body; - } - } - if ($flag_latex_header_remove ne 'NO') { - $texversion = &latex_header_footer_remove($texversion); - } else { - $texversion =~ s/\\end{document}//; - } - if ($helper->{'VARS'}->{'TABLE_INDEX'} eq 'yes') { - $texversion=&IndexCreation($texversion,$urlp); - } - if ($helper->{'VARS'}->{'CONSTR_RESOURSE_URpL'} eq 'yes') { - $texversion=~s/(\\addcontentsline\{toc\}\{subsection\}\{[^\}]*\})/$1 URL: \\verb|$urlp| \\strut\\\\\\strut /; - } - $result.=$texversion; - $flag_latex_header_remove = 'YES'; - } elsif ($urlp=~/\.(sequence|page)$/) { - $result.='\strut\newline\noindent Sequence/page '.$urlp.'\strut\newline\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}\newline\noindent '; - } + $result .= &print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'}); + $result .= &print_construction_sequence($currentURL, $helper, %form, + $LaTeXwidth); + $result .= '\end{document}'; + if (!($result =~ /\\begin\{document\}/)) { + $result = &print_latex_header() . $result; } - if ($helper->{VARS}->{'construction'} eq '1') {$result=~s/(\\begin{document})/$1 \\fbox\{RANDOM SEED IS $rndseed\} /;} - $result .= '\end{document}'; + # End construction space sequence. } elsif ($cleanURL=~/\/(smppg|syllabus|aboutme|bulletinboard)$/) { $form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'}; if ($currentURL=~/\/syllabus$/) {$currentURL=~s/\/res//;} @@ -1348,7 +1536,9 @@ ENDPART } else { if ($urlp=~/\.(problem|exam|quiz|assess|survey|form|library)$/) { $texversion=&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'}); - my $body ='\vskip 0 mm \noindent\textbf{'.&Apache::lonnet::gettitle($master_seq[$i]).'}\vskip 0 mm '; + 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); @@ -1371,10 +1561,15 @@ ENDPART my $courseidinfo = &get_course(); if (defined($courseidinfo)) { $courseidinfo=' - '.$courseidinfo } $prevassignment=$assignment; + my $header_text = $parmhash{'print_header_format'}; + $header_text = &format_page_header($textwidth, $header_text, + $assignment, + $courseidinfo, + $name); if ($numberofcolumns eq '1') { - $result .='\newpage \noindent\parbox{\minipagewidth}{\noindent\\lhead{\\textit{\\textbf{'.$name.'}}'.$courseidinfo.' \\hfill \\thepage \\\\ \\textit{'.$assignment.'}}} \vskip 5 mm '; + $result .='\newpage \noindent\parbox{\minipagewidth}{\noindent\\lhead{'.$header_text.'}} \vskip 5 mm '; } else { - $result .='\newpage \noindent\parbox{\minipagewidth}{\noindent\\fancyhead[LO]{\\textit{\\textbf{'.$name.'}}'.$courseidinfo.' \\hfill \\thepage \\\\ \\textit{'.$assignment.'}}} \vskip 5 mm '; + $result .='\newpage \noindent\parbox{\minipagewidth}{\noindent\\fancyhead[LO]{'.$header_text.'}} \vskip 5 mm '; } } $result .= $texversion; @@ -1561,6 +1756,7 @@ ENDPART } my @master_seq=split /\|\|\|/, $helper->{'VARS'}->{'RESOURCES'}; my ($type) = split(/_/,$helper->{'VARS'}->{'PRINT_TYPE'}); + &adjust_number_to_print($helper); my $number_per_page=$helper->{'VARS'}->{'NUMBER_TO_PRINT'}; if ($number_per_page eq '0' || $number_per_page eq 'all') { $number_per_page=$num_todo; @@ -1666,20 +1862,12 @@ ENDPART $result = &page_format_transformation($papersize,$laystyle,$numberofcolumns,$helper->{'VARS'}->{'PRINT_TYPE'},$result,$helper->{VARS}->{'assignment'},$helper->{'VARS'}->{'TABLE_CONTENTS'},$helper->{'VARS'}->{'TABLE_INDEX'},$selectionmade); $result = &latex_corrections($number_of_columns,$result,$selectionmade, $helper->{'VARS'}->{'ANSWER_TYPE'}); - for (my $i=1;$i<=$#print_array;$i++) { - $print_array[$i] = - &latex_corrections($number_of_columns,$print_array[$i], - $selectionmade, - $helper->{'VARS'}->{'ANSWER_TYPE'}); - } - &Apache::lonnet::logthis("Resetting page e.g. height -> $helper->{'VARS'}->{'pagesize.height'}"); - &Apache::lonnet::logthis("Before: $result \n--------------------------\n"); - $result =~ s/\\textwidth\s*=\s*-?\d*\.?\d*\s*(cm|mm|in)/\\textwidth= $helper->{'VARS'}->{'pagesize.width'} $helper->{'VARS'}->{'pagesize.widthunit'} /; - $result =~ s/\\textheight\s*=?\s*-?\d*\.?\d*\s*(cm|mm|in)/\\textheight $helper->{'VARS'}->{'pagesize.height'} $helper->{'VARS'}->{'pagesize.heightunit'} /; - $result =~ s/\\evensidemargin\s*=\s*-?\d*\.?\d*\s*(cm|mm|in)/\\evensidemargin= $helper->{'VARS'}->{'pagesize.lmargin'} $helper->{'VARS'}->{'pagesize.lmarginunit'} /; - $result =~ s/\\oddsidemargin\s*=\s*-?\d*\.?\d*\s*(cm|mm|in)/\\oddsidemargin= $helper->{'VARS'}->{'pagesize.lmargin'} $helper->{'VARS'}->{'pagesize.lmarginunit'} /; - - &Apache::lonnet::logthis("After: $result \n----------------------------------\n"); + #if ($numberofcolumns == 1) { + $result =~ s/\\textwidth\s*=\s*-?\d*\.?\d*\s*(cm|mm|in)/\\textwidth= $helper->{'VARS'}->{'pagesize.width'} $helper->{'VARS'}->{'pagesize.widthunit'} /; + $result =~ s/\\textheight\s*=?\s*-?\d*\.?\d*\s*(cm|mm|in)/\\textheight $helper->{'VARS'}->{'pagesize.height'} $helper->{'VARS'}->{'pagesize.heightunit'} /; + $result =~ s/\\evensidemargin\s*=\s*-?\d*\.?\d*\s*(cm|mm|in)/\\evensidemargin= $helper->{'VARS'}->{'pagesize.lmargin'} $helper->{'VARS'}->{'pagesize.lmarginunit'} /; + $result =~ s/\\oddsidemargin\s*=\s*-?\d*\.?\d*\s*(cm|mm|in)/\\oddsidemargin= $helper->{'VARS'}->{'pagesize.lmargin'} $helper->{'VARS'}->{'pagesize.lmarginunit'} /; + #} #-- writing .tex file in prtspool my $temp_file; @@ -1700,9 +1888,15 @@ ENDPART if ($i==0) { $print_array[$i]=$result; } else { + $print_array[$i].='\end{document}'; + $print_array[$i] = + &latex_corrections($number_of_columns,$print_array[$i], + $selectionmade, + $helper->{'VARS'}->{'ANSWER_TYPE'}); + my $anobegin=index($print_array[$i],'\setcounter{page}',0); substr($print_array[$i],0,$anobegin)=''; - $print_array[$i]=$inc.$print_array[$i].'\end{document}'; + $print_array[$i]=$inc.$print_array[$i]; } my $temp_file; my $newfilename=$filename; @@ -1799,19 +1993,31 @@ sub print_resources { my $printed = ''; my ($username,$userdomain,$usersection) = split /:/,$person; my $fullname = &get_name($username,$userdomain); - my $namepostfix; + my $namepostfix = "\\\\"; # Both anon and not anon should get the same vspace. if ($person =~ 'anon') { - $namepostfix="\\\\Name: "; + $namepostfix .="Name: "; $fullname = "CODE - ".$moreenv->{'CODE'}; } + # Fullname may have special latex characters that need \ prefixing: + # + my $i = 0; #goes through all resources, checks if they are available for #current student, and produces output &Apache::lonxml::clear_problem_counter(); my %page_breaks = &get_page_breaks($helper); - my @format_array = split(/\|/,$helper->{'VARS'}->{'FORMAT'}); - my $columns_in_format = $format_array[1]; + my $columns_in_format = (split(/\|/,$helper->{'VARS'}->{'FORMAT'}))[1]; + # + # end each student with a + # Special that allows the post processor to even out the page + # counts later. Nasty problem this... it would be really + # nice to put the special in as a postscript comment + # e.g. \special{ps:\ENDOFSTUDENTSTAMP} unfortunately, + # The special gets passed the \ and dvips puts it in the output file + # so we will just rely on prntout.pl to strip ENDOFSTUDENTSTAMP from the + # postscript. Each ENDOFSTUDENTSTAMP will go on a line by itself. + # foreach my $curresline (@{$master_seq}) { if (defined $page_breaks{$curresline}) { @@ -1849,8 +2055,10 @@ sub print_resources { my $header =&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'}); - my $body ='\vskip 0 mm \noindent\textbf{'.&Apache::lonnet::gettitle($curresline).'}\vskip 0 mm '; - $body .=&path_to_problem($res_url,$LaTeXwidth); + 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); $rendered = $header.$body; @@ -1891,22 +2099,27 @@ sub print_resources { if (defined($courseidinfo)) { $courseidinfo=' - '.$courseidinfo } if ($usersection ne '') {$courseidinfo.=' - Sec. '.$usersection} my $currentassignment=&Apache::lonxml::latex_special_symbols($helper->{VARS}->{'assignment'},'header'); - if ($current_output=~/\\documentclass/) { - if ($columns_in_format == 1) { - $current_output =~ s/\\begin{document}/\\setlength{\\topmargin}{1cm} \\begin{document}\\noindent\\parbox{\\minipagewidth}{\\noindent\\lhead{\\textit{\\textbf{$fullname}}$courseidinfo \\hfill \\thepage \\\\ \\textit{$currentassignment}$namepostfix}}\\vskip 5 mm /; - } else { - $current_output =~ s/\\begin{document}/\\setlength{\\topmargin}{1cm} \\begin{document}\\noindent\\parbox{\\minipagewidth}{\\noindent\\fancyhead[LO]{\\textit{\\textbf{$fullname}}$courseidinfo \\hfill \\thepage \\\\ \\textit{$currentassignment}$namepostfix}}\\vskip 5 mm /; + my $header_line = + &format_page_header($LaTeXwidth, $parmhash{'print_header_format'}, + $currentassignment, $courseidinfo, $fullname); + my $header_start = ($columns_in_format == 1) ? '\lhead' + : '\fancyhead[LO]'; + $header_line = $header_start.'{'.$header_line.'}'; - } + if ($current_output=~/\\documentclass/) { + $current_output =~ s/\\begin{document}/\\setlength{\\topmargin}{1cm} \\begin{document}\\noindent\\parbox{\\minipagewidth}{\\noindent$header_line$namepostfix}\\vskip 5 mm /; } else { - my $blankpages = ''; - for (my $j=0;$j<$helper->{'VARS'}->{'EMPTY_PAGES'};$j++) {$blankpages.='\clearpage\strut\clearpage';} - if ($columns_in_format == 1) { - $current_output = '\strut\vspace*{-6 mm}\\newline\\noindent\\makebox[\\textwidth/$number_of_columns][b]{\\hrulefill}\vspace*{-2 mm}\\newline\\noindent{\\tiny Printed from LON-CAPA\\copyright MSU{\\hfill} Licensed under GNU General Public License }\\newpage '.$blankpages.'\setcounter{page}{1}\noindent\parbox{\minipagewidth}{\noindent\\lhead{\\textit{\\textbf{'.$fullname.'}}'.$courseidinfo.' \\hfill \\thepage \\\\ \\textit{'.$currentassignment.'}'.$namepostfix.'}} \vskip 5 mm '.$current_output; - } else { - $current_output = '\strut\vspace*{-6 mm}\\newline\\noindent\\makebox[\\textwidth/$number_of_columns][b]{\\hrulefill}\vspace*{-2 mm}\\newline\\noindent{\\tiny Printed from LON-CAPA\\copyright MSU{\\hfill} Licensed under GNU General Public License }\\newpage '.$blankpages.'\setcounter{page}{1}\noindent\parbox{\minipagewidth}{\noindent\\fancyhead[LO]{\\textit{\\textbf{'.$fullname.'}}'.$courseidinfo.' \\hfill \\thepage \\\\ \\textit{'.$currentassignment.'}'.$namepostfix.'}} \vskip 5 mm '.$current_output; - } + my $blankpages = + '\clearpage\strut\clearpage'x$helper->{'VARS'}->{'EMPTY_PAGES'}; + + $current_output = '\strut\vspace*{-6 mm}\\newline'. + ©right_line().' \newpage '.$blankpages.$end_of_student. + '\setcounter{page}{1}\noindent\parbox{\minipagewidth}{\noindent'. + $header_line.$namepostfix.'} \vskip 5 mm '.$current_output; } + # + # Close the student bracketing. + # return ($current_output,$fullname, $printed); } @@ -1925,7 +2138,7 @@ sub handler { } - my %parmhash=&Apache::lonnet::coursedescription($env{'request.course.id'}); + %parmhash=&Apache::lonnet::coursedescription($env{'request.course.id'}); @@ -1960,7 +2173,7 @@ sub init_perm { $perm{'pav'}=&Apache::lonnet::allowed('pav', $env{'request.course.id'}.'/'.$env{'request.course.sec'}); } - $perm{'pfo'}=&Apache::lonnet::allowed('pav',$env{'request.course.id'}); + $perm{'pfo'}=&Apache::lonnet::allowed('pfo',$env{'request.course.id'}); if (!$perm{'pfo'}) { $perm{'pfo'}=&Apache::lonnet::allowed('pfo', $env{'request.course.id'}.'/'.$env{'request.course.sec'}); @@ -2008,6 +2221,7 @@ sub printHelper { $helper->declareVar('FINISHPAGE'); $helper->declareVar('PRINT_TYPE'); $helper->declareVar("showallfoils"); + $helper->declareVar("STUDENTS"); # The page breaks can get loaded initially from the course environment: # But we only do this in the initial state so that they are allowed to change. @@ -2019,6 +2233,8 @@ sub printHelper { {'pagebreaks' => 'scalar', 'lastprinttype' => 'scalar'}); + # This will persistently load in the data we want from the + # very first screen. if($helper->{VARS}->{PRINT_TYPE} eq $env{'form.lastprinttype'}) { if (!defined ($env{"form.CURRENT_STATE"})) { @@ -2033,9 +2249,7 @@ sub printHelper { } - - # This will persistently load in the data we want from the - # very first screen. + # Detect whether we're coming from construction space if ($env{'form.postdata'}=~/^(?:http:\/\/[^\/]+\/|\/|)\~([^\/]+)\/(.*)$/) { $helper->{VARS}->{'filename'} = "~$1/$2"; @@ -2043,6 +2257,9 @@ sub printHelper { } else { if ($env{'form.postdata'}) { $helper->{VARS}->{'symb'} = &Apache::lonnet::symbread($env{'form.postdata'}); + if ( $helper->{VARS}->{'symb'} eq '') { + $helper->{VARS}->{'postdata'} = $env{'form.postdata'}; + } } if ($env{'form.symb'}) { $helper->{VARS}->{'symb'} = $env{'form.symb'}; @@ -2070,6 +2287,7 @@ sub printHelper { my $symb = $helper->{VARS}->{'symb'}; my ($map, $id, $url); my $subdir; + my $is_published=0; # True when printing from resource space. # Get the resource name from construction space if ($helper->{VARS}->{'construction'}) { @@ -2078,9 +2296,15 @@ sub printHelper { $subdir = substr($helper->{VARS}->{'filename'}, 0, rindex($helper->{VARS}->{'filename'}, '/') + 1); } else { - ($map, $id, $url) = &Apache::lonnet::decode_symb($symb); - $helper->{VARS}->{'postdata'} = - &Apache::lonenc::check_encrypt(&Apache::lonnet::clutter($url)); + if ($symb ne '') { + ($map, $id, $url) = &Apache::lonnet::decode_symb($symb); + $helper->{VARS}->{'postdata'} = + &Apache::lonenc::check_encrypt(&Apache::lonnet::clutter($url)); + } else { + $url = $helper->{VARS}->{'postdata'}; + $is_published=1; # From resource space. + } + $url = &Apache::lonnet::clutter($url); if (!$resourceTitle) { # if the resource doesn't have a title, use the filename my $postdata = $helper->{VARS}->{'postdata'}; @@ -2101,11 +2325,6 @@ sub printHelper { # "Delete everything after the last slash." $subdir =~ s|/[^/]+$||; - if (not $helper->{VARS}->{'construction'}) { - $subdir=$Apache::lonnet::perlvar{'lonDocRoot'}.'/res/'.$subdir; - } - # "Remove all duplicate slashes." - $subdir =~ s|/+|/|g; # What can be printed is a very dynamic decision based on # lots of factors. So we need to dynamically build this list. @@ -2122,7 +2341,7 @@ sub printHelper { my $paramHash; if ($resourceTitle) { - push @{$printChoices}, ["$resourceTitle (".&mt('what you just saw on the screen').")", 'current_document', 'PAGESIZE']; + push @{$printChoices}, ["$resourceTitle (".&mt('the resource you just saw on the screen').")", 'current_document', 'PAGESIZE']; } # Useful filter strings @@ -2137,40 +2356,44 @@ sub printHelper { $helper->declareVar('SEQUENCE'); + # If we're in a sequence... + my $start_new_option; + if ($perm{'pav'}) { + $start_new_option = + "