Annotation of loncom/interface/lonprintout.pm, revision 1.522

1.389     foxr        1: # The LearningOnline Network
1.1       www         2: # Printout
                      3: #
1.522   ! raeburn     4: # $Id: lonprintout.pm,v 1.521 2008/03/17 09:53:36 foxr Exp $
1.11      albertel    5: #
                      6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
                     14: #
                     15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     23: #
                     24: # /home/httpd/html/adm/gpl.txt
                     25: # http://www.lon-capa.org/
                     26: #
1.3       sakharuk   27: #
1.1       www        28: package Apache::lonprintout;
                     29: 
                     30: use strict;
1.10      albertel   31: use Apache::Constants qw(:common :http);
1.2       sakharuk   32: use Apache::lonxml;
                     33: use Apache::lonnet;
1.54      sakharuk   34: use Apache::loncommon;
1.13      sakharuk   35: use Apache::inputtags;
1.54      sakharuk   36: use Apache::grades;
1.13      sakharuk   37: use Apache::edit;
1.5       sakharuk   38: use Apache::File();
1.68      sakharuk   39: use Apache::lonnavmaps;
1.511     foxr       40: use Apache::admannotations;
1.521     foxr       41: use Apache::lonenc;
1.515     foxr       42: use HTTP::Response;
1.511     foxr       43: 
1.491     albertel   44: use LONCAPA::map();
1.34      sakharuk   45: use POSIX qw(strftime);
1.255     www        46: use Apache::lonlocal;
1.429     foxr       47: use Carp;
1.439     www        48: use LONCAPA;
1.60      sakharuk   49: 
1.397     albertel   50: my %perm;
1.454     foxr       51: my %parmhash;
1.459     foxr       52: my $resources_printed;
1.454     foxr       53: 
1.515     foxr       54: # Global variables that describe errors in ssi calls detected  by ssi_with_retries.
                     55: #
                     56: 
                     57: my $ssi_error;			# True if there was an ssi error.
                     58: my $ssi_last_error_resource;	# The resource URI that could not be fetched.
                     59: my $ssi_last_error;		# The error text from the server. (e.g. 500 Server timed out).
                     60: 
                     61: #
                     62: #  Our ssi max retry count.
                     63: #
                     64: 
                     65: my $ssi_retry_count = 5;	# Some arbitrary value.
                     66: 
                     67: 
                     68: 
1.498     foxr       69: # Fetch the contents of a resource, uninterpreted.
                     70: # This is used here to fetch a latex file to be included
                     71: # verbatim into the printout<
                     72: # NOTE: Ask Guy if there is a lonnet function similar to this?
                     73: #
                     74: # Parameters:
                     75: #   URL of the file
                     76: #
                     77: sub fetch_raw_resource {
                     78:     my ($url) = @_;
                     79: 
                     80:     my $filename  = &Apache::lonnet::filelocation("", $url);
1.500     foxr       81:     my $contents  = &Apache::lonnet::getfile($filename);
1.498     foxr       82: 
1.500     foxr       83:     if ($contents == -1) {
                     84: 	return "File open failed for $filename";      # This will bomb the print.
1.498     foxr       85:     }
1.500     foxr       86:     return $contents;
1.498     foxr       87: 
                     88:     
                     89: }
                     90: 
1.511     foxr       91: #  Fetch the annotations associated with a URL and 
                     92: #  put a centered 'annotations:' title.
                     93: #  This is all suppressed if the annotations are empty.
                     94: #
                     95: sub annotate {
                     96:     my ($symb) = @_;
                     97: 
                     98:     my $annotation_text = &Apache::admannotations::get_annotation($symb, 1);
                     99: 
                    100: 
                    101:     my $result = "";
                    102: 
                    103:     if (length($annotation_text) > 0) {
                    104: 	$result .= '\\hspace*{\\fill} \\\\[\\baselineskip] \textbf{Annotations:} \\\\ ';
                    105: 	$result .= "\n";
                    106: 	$result .= &Apache::lonxml::latex_special_symbols($annotation_text,"");	# Escape latex.
                    107: 	$result .= "\n\n";
                    108:     }
                    109:     return $result;
                    110: }
                    111: 
1.515     foxr      112: 
                    113: #
                    114: #   ssi_with_retries - Does the server side include of a resource.
                    115: #                      if the ssi call returns an error we'll retry it up to
                    116: #                      the number of times requested by the caller.
                    117: #                      If we still have a proble, no text is appended to the
                    118: #                      output and we set some global variables.
                    119: #                      to indicate to the caller an SSI error occured.  
                    120: #                      All of this is supposed to deal with the issues described
                    121: #                      in LonCAPA BZ 5631 see:
                    122: #                      http://bugs.lon-capa.org/show_bug.cgi?id=5631
                    123: #                      by informing the user that this happened.
                    124: #
                    125: # Parameters:
                    126: #   resource   - The resource to include.  This is passed directly, without
                    127: #                interpretation to lonnet::ssi.
                    128: #   form       - The form hash parameters that guide the interpretation of the resource
                    129: #                
                    130: #   retries    - Number of retries allowed before giving up completely.
                    131: # Returns:
                    132: #   On success, returns the rendered resource identified by the resource parameter.
                    133: # Side Effects:
                    134: #   The following global variables can be set:
                    135: #    ssi_error                - If an unrecoverable error occured this becomes true.
                    136: #                               It is up to the caller to initialize this to false
                    137: #                               if desired.
                    138: #    ssi_last_error_resource  - If an unrecoverable error occured, this is the value
                    139: #                               of the resource that could not be rendered by the ssi
                    140: #                               call.
                    141: #    ssi_last_error           - The error string fetched from the ssi response
                    142: #                               in the event of an error.
                    143: #
                    144: sub ssi_with_retries {
                    145:     my ($resource, $retries, %form) = @_;
                    146: 
                    147: 
1.516     foxr      148:     my ($content, $response) = &Apache::loncommon::ssi_with_retries($resource, $retries, %form);
                    149:     if (!$response->is_success) {
1.515     foxr      150: 	$ssi_error               = 1;
                    151: 	$ssi_last_error_resource = $resource;
1.516     foxr      152: 	$ssi_last_error          = $response->code . " " . $response->message;
1.519     foxr      153: 	
                    154: 	&Apache::lonnet::logthis("Error in SSI resource: $resource Error: $ssi_last_error");
1.515     foxr      155:     }
1.516     foxr      156: 
                    157:     return $content;
                    158: 
1.515     foxr      159: }
                    160: 
1.486     foxr      161: #
                    162: #   printf_style_subst  item format_string repl
                    163: #  
                    164: # Does printf style substitution for a format string that
                    165: # can have %[n]item in it.. wherever, %[n]item occurs,
                    166: # rep is substituted in format_string.  Note that
                    167: # [n] is an optional integer length.  If provided,
                    168: # repl is truncated to at most [n] characters prior to 
                    169: # substitution.
                    170: #
                    171: sub printf_style_subst {
                    172:     my ($item, $format_string, $repl) = @_;
1.490     foxr      173:     my $result = "";
                    174:     while ($format_string =~ /(%)(\d*)\Q$item\E/g ) {
1.488     albertel  175: 	my $fmt = $1;
                    176: 	my $size = $2;
1.486     foxr      177: 	my $subst = $repl;
                    178: 	if ($size ne "") {
                    179: 	    $subst = substr($subst, 0, $size);
1.490     foxr      180: 	    
                    181: 	    #  Here's a nice edge case.. supose the end of the
                    182: 	    #  substring is a \.  In that case may have  just
                    183: 	    #  chopped off a TeX escape... in that case, we append
                    184: 	    #   " " for the trailing character, and let the field 
                    185: 	    #  spill over a bit (sigh).
                    186: 	    #  We don't just chop off the last character in order to deal
                    187: 	    #  with one last pathology, and that would be if substr had
                    188: 	    #  trimmed us to e.g. \\\  
                    189: 
                    190: 
                    191: 	    if ($subst =~ /\\$/) {
                    192: 		$subst .= " ";
                    193: 	    }
1.486     foxr      194: 	}
1.490     foxr      195: 	my $item_pos = pos($format_string);
                    196: 	$result .= substr($format_string, 0, $item_pos - length($size) -2) . $subst;
                    197:         $format_string = substr($format_string, pos($format_string));
1.486     foxr      198:     }
1.490     foxr      199: 
                    200:     # Put the residual format string into the result:
                    201: 
                    202:     $result .= $format_string;
                    203: 
                    204:     return $result;
1.486     foxr      205: }
                    206: 
1.454     foxr      207: 
                    208: # Format a header according to a format.  
                    209: # 
                    210: 
                    211: # Substitutions:
                    212: #     %a    - Assignment name.
                    213: #     %c    - Course name.
                    214: #     %n    - Student name.
                    215: #
                    216: sub format_page_header {
1.486     foxr      217:     my ($width, $format, $assignment, $course, $student) = @_;
1.454     foxr      218:     
1.486     foxr      219:     $width = &recalcto_mm($width); # Get width in mm.
1.454     foxr      220:     #  Default format?
                    221: 
                    222:     if ($format eq '') {
1.486     foxr      223: 	# For the default format, we may need to truncate
                    224: 	# elements..  To do this we need to get the page width.
                    225: 	# we assume that each character is about 2mm in width.
                    226: 	# (correct for the header text size??).  We ignore
                    227: 	# any formatting (e.g. boldfacing in this).
                    228: 	# 
                    229: 	# - Allow the student/course to be one line.
                    230: 	#   but only truncate the course.
                    231: 	# - Allow the assignment to be 2 lines (wrapped).
                    232: 	#
                    233: 	my $chars_per_line = $width/2; # Character/textline.
                    234: 
                    235: 
                    236: 	my $firstline = "$student $course";
                    237: 	if (length($firstline) > $chars_per_line) {
                    238: 	    my $lastchar = $chars_per_line - length($student) - 1;
                    239: 	    if ($lastchar > 0) {
                    240: 		$course = substr($course, 0, $lastchar);
                    241: 	    } else {		# Nothing left of course:
                    242: 		$course = '';
                    243: 	    }
                    244: 	}
                    245: 	if (length($assignment) > $chars_per_line) {
                    246: 	    $assignment = substr($assignment, 0, $chars_per_line);
                    247: 	}
                    248: 	
1.454     foxr      249: 	$format =  "\\textbf{$student} $course \\hfill \\thepage \\\\ \\textit{$assignment}";
                    250: 	
                    251:     } else {
1.486     foxr      252: 	# An open question is how to handle long user formatted page headers...
                    253: 	# A possible future is to support e.g. %na so that the user can control
                    254: 	# the truncation of the elements that can appear in the header.
                    255: 	#
                    256: 	$format =  &printf_style_subst("a", $format, $assignment);
                    257: 	$format =  &printf_style_subst("c", $format, $course);
                    258: 	$format =  &printf_style_subst("n", $format, $student);
1.489     foxr      259: 
                    260: 	# If the user put %'s in the format string, they  must be escaped
                    261: 	# to \% else LaTeX will think they are comments and terminate
                    262: 	# the line.. which is bad!!!
                    263: 
1.490     foxr      264: 
1.454     foxr      265:     }
                    266:     
                    267: 
                    268:     return $format;
                    269:     
                    270: }
1.397     albertel  271: 
1.385     foxr      272: #
                    273: #   Convert a numeric code to letters
                    274: #
                    275: sub num_to_letters {
                    276:     my ($num) = @_;
                    277:     my @nums= split('',$num);
                    278:     my @num_to_let=('A'..'Z');
                    279:     my $word;
                    280:     foreach my $digit (@nums) { $word.=$num_to_let[$digit]; }
                    281:     return $word;
                    282: }
                    283: #   Convert a letter code to numeric.
                    284: #
                    285: sub letters_to_num {
                    286:     my ($letters) = @_;
                    287:     my @letters = split('', uc($letters));
1.490     foxr      288:    my %substitution;
1.385     foxr      289:     my $digit = 0;
                    290:     foreach my $letter ('A'..'J') {
                    291: 	$substitution{$letter} = $digit;
                    292: 	$digit++;
                    293:     }
                    294:     #  The substitution is done as below to preserve leading
                    295:     #  zeroes which are needed to keep the code size exact
                    296:     #
                    297:     my $result ="";
                    298:     foreach my $letter (@letters) {
                    299: 	$result.=$substitution{$letter};
                    300:     }
                    301:     return $result;
                    302: }
                    303: 
1.383     foxr      304: #  Determine if a code is a valid numeric code.  Valid
                    305: #  numeric codes must be comprised entirely of digits and
1.384     albertel  306: #  have a correct number of digits.
1.383     foxr      307: #
                    308: #  Parameters:
                    309: #     value      - proposed code value.
1.384     albertel  310: #     num_digits - Number of digits required.
1.383     foxr      311: #
                    312: sub is_valid_numeric_code {
1.384     albertel  313:     my ($value, $num_digits) = @_;
1.383     foxr      314:     #   Remove leading/trailing whitespace;
1.387     foxr      315:     $value =~ s/^\s*//g;
                    316:     $value =~ s/\s*$//g;
1.383     foxr      317:     
                    318:     #  All digits?
1.387     foxr      319:     if ($value !~ /^[0-9]+$/) {
1.383     foxr      320: 	return "Numeric code $value has invalid characters - must only be digits";
                    321:     }
1.384     albertel  322:     if (length($value) != $num_digits) {
                    323: 	return "Numeric code $value incorrect number of digits (correct = $num_digits)";
                    324:     }
1.385     foxr      325:     return undef;
1.383     foxr      326: }
                    327: #   Determines if a code is a valid alhpa code.  Alpha codes
                    328: #   are ciphers that map  [A-J,a-j] -> 0..9 0..9.
1.384     albertel  329: #   They also have a correct digit count.
1.383     foxr      330: # Parameters:
                    331: #     value          - Proposed code value.
1.384     albertel  332: #     num_letters    - correct number of letters.
1.383     foxr      333: # Note:
                    334: #    leading and trailing whitespace are ignored.
                    335: #
                    336: sub is_valid_alpha_code {
1.384     albertel  337:     my ($value, $num_letters) = @_;
1.383     foxr      338:     
                    339:      # strip leading and trailing spaces.
                    340: 
                    341:     $value =~ s/^\s*//g;
                    342:     $value =~ s/\s*$//g;
                    343: 
                    344:     #  All alphas in the right range?
1.384     albertel  345:     if ($value !~ /^[A-J,a-j]+$/) {
1.383     foxr      346: 	return "Invalid letter code $value must only contain A-J";
                    347:     }
1.384     albertel  348:     if (length($value) != $num_letters) {
                    349: 	return "Letter code $value has incorrect number of letters (correct = $num_letters)";
                    350:     }
1.385     foxr      351:     return undef;
1.383     foxr      352: }
                    353: 
1.382     foxr      354: #   Determine if a code entered by the user in a helper is valid.
                    355: #   valid depends on the code type and the type of code selected.
                    356: #   The type of code selected can either be numeric or 
                    357: #   Alphabetic.  If alphabetic, the code, in fact is a simple
                    358: #   substitution cipher for the actual numeric code: 0->A, 1->B ...
                    359: #   We'll be nice and be case insensitive for alpha codes.
                    360: # Parameters:
                    361: #    code_value    - the value of the code the user typed in.
                    362: #    code_option   - The code type selected from the set in the scantron format
                    363: #                    table.
                    364: # Returns:
                    365: #    undef         - The code is valid.
                    366: #    other         - An error message indicating what's wrong.
                    367: #
                    368: sub is_code_valid {
                    369:     my ($code_value, $code_option) = @_;
1.383     foxr      370:     my ($code_type, $code_length) = ('letter', 6);	# defaults.
                    371:     open(FG, $Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab');
                    372:     foreach my $line (<FG>) {
                    373: 	my ($name, $type, $length) = (split(/:/, $line))[0,2,4];
                    374: 	if($name eq $code_option) {
                    375: 	    $code_length = $length;
                    376: 	    if($type eq 'number') {
                    377: 		$code_type = 'number';
                    378: 	    }
                    379: 	}
                    380:     }
                    381:     my $valid;
                    382:     if ($code_type eq 'number') {
1.385     foxr      383: 	return &is_valid_numeric_code($code_value, $code_length);
1.383     foxr      384:     } else {
1.385     foxr      385: 	return &is_valid_alpha_code($code_value, $code_length);
1.383     foxr      386:     }
1.382     foxr      387: 
                    388: }
                    389: 
1.341     foxr      390: #   Compare two students by name.  The students are in the form
                    391: #   returned by the helper:
                    392: #      user:domain:section:last,   first:status
                    393: #   This is a helper function for the perl sort built-in  therefore:
                    394: # Implicit Inputs:
                    395: #    $a     - The first element to compare (global)
                    396: #    $b     - The second element to compare (global)
                    397: # Returns:
                    398: #   -1   - $a < $b
                    399: #    0   - $a == $b
                    400: #   +1   - $a > $b
                    401: #   Note that the initial comparison is done on the last names with the
                    402: #   first names only used to break the tie.
                    403: #
                    404: #
                    405: sub compare_names {
                    406:     #  First split the names up into the primary fields.
                    407: 
                    408:     my ($u1, $d1, $s1, $n1, $stat1) = split(/:/, $a);
                    409:     my ($u2, $d2, $s2, $n2, $stat2) = split(/:/, $b);
                    410: 
                    411:     # Now split the last name and first name of each n:
                    412:     #
                    413: 
                    414:     my ($l1,$f1) = split(/,/, $n1);
                    415:     my ($l2,$f2) = split(/,/, $n2);
                    416: 
                    417:     # We don't bother to remove the leading/trailing whitespace from the
                    418:     # firstname, unless the last names compare identical.
                    419: 
                    420:     if($l1 lt $l2) {
                    421: 	return -1;
                    422:     }
                    423:     if($l1 gt $l2) {
                    424: 	return  1;
                    425:     }
                    426: 
                    427:     # Break the tie on the first name, but there are leading (possibly trailing
                    428:     # whitespaces to get rid of first 
                    429:     #
                    430:     $f1 =~ s/^\s+//;		# Remove leading...
                    431:     $f1 =~ s/\s+$//;		# Trailing spaces from first 1...
                    432:     
                    433:     $f2 =~ s/^\s+//;
                    434:     $f2 =~ s/\s+$//;		# And the same for first 2...
                    435: 
                    436:     if($f1 lt $f2) {
                    437: 	return -1;
                    438:     }
                    439:     if($f1 gt $f2) {
                    440: 	return 1;
                    441:     }
                    442:     
                    443:     #  Must be the same name.
                    444: 
                    445:     return 0;
                    446: }
                    447: 
1.71      sakharuk  448: sub latex_header_footer_remove {
                    449:     my $text = shift;
                    450:     $text =~ s/\\end{document}//;
                    451:     $text =~ s/\\documentclass([^&]*)\\begin{document}//;
                    452:     return $text;
                    453: }
1.423     foxr      454: #
                    455: #  If necessary, encapsulate text inside 
                    456: #  a minipage env.
                    457: #  necessity is determined by the problem_split param.
                    458: #
                    459: sub encapsulate_minipage {
                    460:     my ($text) = @_;
1.427     albertel  461:     if (!($env{'form.problem.split'} =~ /yes/i)) {
1.423     foxr      462: 	$text = '\begin{minipage}{\textwidth}'.$text.'\end{minipage}';
                    463:     }
                    464:     return $text;
                    465: }
1.429     foxr      466: #
                    467: #  The NUMBER_TO_PRINT and SPLIT_PDFS
                    468: #  variables interact, this sub looks at these two parameters
                    469: #  and comes up with a final value for NUMBER_TO_PRINT which can be:
                    470: #     all     - if SPLIT_PDFS eq 'all'.
                    471: #     1       - if SPLIT_PDFS eq 'oneper'
                    472: #     section - if SPLIT_PDFS eq 'sections'
                    473: #     <unchanged> - if SPLIT_PDFS eq 'usenumber'
                    474: #
                    475: sub adjust_number_to_print {
                    476:     my $helper = shift;
1.71      sakharuk  477: 
1.429     foxr      478:     my $split_pdf = $helper->{'VARS'}->{'SPLIT_PDFS'};
                    479:     
                    480:     if ($split_pdf eq 'all') {
                    481: 	$helper->{'VARS'}->{'NUMBER_TO_PRINT'} = 'all';
                    482:     } elsif ($split_pdf eq 'oneper') {
                    483: 	$helper->{'VARS'}->{'NUMBER_TO_PRINT'} = 1;
                    484:     } elsif ($split_pdf eq 'sections') {
                    485: 	$helper->{'VARS'}->{'NUMBER_TO_PRINT'} = 'section';
                    486:     } elsif ($split_pdf eq 'usenumber') {
                    487: 	#  Unmodified.
                    488:     } else {
                    489: 	# Error!!!!
                    490: 
                    491: 	croak "bad SPLIT_PDFS: $split_pdf in lonprintout::adjust_number_to_print";
                    492:     }
                    493: }
1.71      sakharuk  494: 
1.37      sakharuk  495: sub character_chart {
                    496:     my $result = shift;	
1.116     sakharuk  497:     $result =~ s/&\#0?0?(7|9);//g;
                    498:     $result =~ s/&\#0?(10|13);//g;
                    499:     $result =~ s/&\#0?32;/ /g;
                    500:     $result =~ s/&\#0?33;/!/g;
                    501:     $result =~ s/&(\#0?34|quot);/\"/g;
                    502:     $result =~ s/&\#0?35;/\\\#/g;
                    503:     $result =~ s/&\#0?36;/\\\$/g;
                    504:     $result =~ s/&\#0?37;/\\%/g; 
                    505:     $result =~ s/&(\#0?38|amp);/\\&/g; 
                    506:     $result =~ s/&\#(0?39|146);/\'/g;
                    507:     $result =~ s/&\#0?40;/(/g;
                    508:     $result =~ s/&\#0?41;/)/g;
                    509:     $result =~ s/&\#0?42;/\*/g;
                    510:     $result =~ s/&\#0?43;/\+/g;
                    511:     $result =~ s/&\#(0?44|130);/,/g;
                    512:     $result =~ s/&\#0?45;/-/g;
                    513:     $result =~ s/&\#0?46;/\./g;
                    514:     $result =~ s/&\#0?47;/\//g;
                    515:     $result =~ s/&\#0?48;/0/g;
                    516:     $result =~ s/&\#0?49;/1/g;
                    517:     $result =~ s/&\#0?50;/2/g;
                    518:     $result =~ s/&\#0?51;/3/g;
                    519:     $result =~ s/&\#0?52;/4/g;
                    520:     $result =~ s/&\#0?53;/5/g;
                    521:     $result =~ s/&\#0?54;/6/g;
                    522:     $result =~ s/&\#0?55;/7/g;
                    523:     $result =~ s/&\#0?56;/8/g;
                    524:     $result =~ s/&\#0?57;/9/g;
1.269     albertel  525:     $result =~ s/&\#0?58;/:/g;
1.116     sakharuk  526:     $result =~ s/&\#0?59;/;/g;
                    527:     $result =~ s/&(\#0?60|lt|\#139);/\$<\$/g;
1.281     sakharuk  528:     $result =~ s/&\#0?61;/\\ensuremath\{=\}/g;
                    529:     $result =~ s/&(\#0?62|gt|\#155);/\\ensuremath\{>\}/g;
1.116     sakharuk  530:     $result =~ s/&\#0?63;/\?/g;
                    531:     $result =~ s/&\#0?65;/A/g;
                    532:     $result =~ s/&\#0?66;/B/g;
                    533:     $result =~ s/&\#0?67;/C/g;
                    534:     $result =~ s/&\#0?68;/D/g;
                    535:     $result =~ s/&\#0?69;/E/g;
                    536:     $result =~ s/&\#0?70;/F/g;
                    537:     $result =~ s/&\#0?71;/G/g;
                    538:     $result =~ s/&\#0?72;/H/g;
                    539:     $result =~ s/&\#0?73;/I/g;
                    540:     $result =~ s/&\#0?74;/J/g;
                    541:     $result =~ s/&\#0?75;/K/g;
                    542:     $result =~ s/&\#0?76;/L/g;
                    543:     $result =~ s/&\#0?77;/M/g;
                    544:     $result =~ s/&\#0?78;/N/g;
                    545:     $result =~ s/&\#0?79;/O/g;
                    546:     $result =~ s/&\#0?80;/P/g;
                    547:     $result =~ s/&\#0?81;/Q/g;
                    548:     $result =~ s/&\#0?82;/R/g;
                    549:     $result =~ s/&\#0?83;/S/g;
                    550:     $result =~ s/&\#0?84;/T/g;
                    551:     $result =~ s/&\#0?85;/U/g;
                    552:     $result =~ s/&\#0?86;/V/g;
                    553:     $result =~ s/&\#0?87;/W/g;
                    554:     $result =~ s/&\#0?88;/X/g;
                    555:     $result =~ s/&\#0?89;/Y/g;
                    556:     $result =~ s/&\#0?90;/Z/g;
                    557:     $result =~ s/&\#0?91;/[/g;
1.281     sakharuk  558:     $result =~ s/&\#0?92;/\\ensuremath\{\\setminus\}/g;
1.116     sakharuk  559:     $result =~ s/&\#0?93;/]/g;
1.281     sakharuk  560:     $result =~ s/&\#(0?94|136);/\\ensuremath\{\\wedge\}/g;
1.116     sakharuk  561:     $result =~ s/&\#(0?95|138|154);/\\underline{\\makebox[2mm]{\\strut}}/g;
                    562:     $result =~ s/&\#(0?96|145);/\`/g;
                    563:     $result =~ s/&\#0?97;/a/g;
                    564:     $result =~ s/&\#0?98;/b/g;
                    565:     $result =~ s/&\#0?99;/c/g;
                    566:     $result =~ s/&\#100;/d/g;
                    567:     $result =~ s/&\#101;/e/g;
                    568:     $result =~ s/&\#102;/f/g;
                    569:     $result =~ s/&\#103;/g/g;
                    570:     $result =~ s/&\#104;/h/g;
                    571:     $result =~ s/&\#105;/i/g;
                    572:     $result =~ s/&\#106;/j/g;
                    573:     $result =~ s/&\#107;/k/g;
                    574:     $result =~ s/&\#108;/l/g;
                    575:     $result =~ s/&\#109;/m/g;
                    576:     $result =~ s/&\#110;/n/g;
                    577:     $result =~ s/&\#111;/o/g;
                    578:     $result =~ s/&\#112;/p/g;
                    579:     $result =~ s/&\#113;/q/g;
                    580:     $result =~ s/&\#114;/r/g;
                    581:     $result =~ s/&\#115;/s/g;
                    582:     $result =~ s/&\#116;/t/g;
                    583:     $result =~ s/&\#117;/u/g;
                    584:     $result =~ s/&\#118;/v/g;
                    585:     $result =~ s/&\#119;/w/g;
                    586:     $result =~ s/&\#120;/x/g;
                    587:     $result =~ s/&\#121;/y/g;
                    588:     $result =~ s/&\#122;/z/g;
                    589:     $result =~ s/&\#123;/\\{/g;
                    590:     $result =~ s/&\#124;/\|/g;
                    591:     $result =~ s/&\#125;/\\}/g;
                    592:     $result =~ s/&\#126;/\~/g;
                    593:     $result =~ s/&\#131;/\\textflorin /g;
                    594:     $result =~ s/&\#132;/\"/g;
1.281     sakharuk  595:     $result =~ s/&\#133;/\\ensuremath\{\\ldots\}/g;
                    596:     $result =~ s/&\#134;/\\ensuremath\{\\dagger\}/g;
                    597:     $result =~ s/&\#135;/\\ensuremath\{\\ddagger\}/g;
1.116     sakharuk  598:     $result =~ s/&\#137;/\\textperthousand /g;
                    599:     $result =~ s/&\#140;/{\\OE}/g;
                    600:     $result =~ s/&\#147;/\`\`/g;
                    601:     $result =~ s/&\#148;/\'\'/g;
1.281     sakharuk  602:     $result =~ s/&\#149;/\\ensuremath\{\\bullet\}/g;
1.494     albertel  603:     $result =~ s/&(\#150|\#8211);/--/g;
1.116     sakharuk  604:     $result =~ s/&\#151;/---/g;
1.281     sakharuk  605:     $result =~ s/&\#152;/\\ensuremath\{\\sim\}/g;
1.116     sakharuk  606:     $result =~ s/&\#153;/\\texttrademark /g;
                    607:     $result =~ s/&\#156;/\\oe/g;
                    608:     $result =~ s/&\#159;/\\\"Y/g;
1.283     albertel  609:     $result =~ s/&(\#160|nbsp);/~/g;
1.116     sakharuk  610:     $result =~ s/&(\#161|iexcl);/!\`/g;
                    611:     $result =~ s/&(\#162|cent);/\\textcent /g;
                    612:     $result =~ s/&(\#163|pound);/\\pounds /g; 
                    613:     $result =~ s/&(\#164|curren);/\\textcurrency /g;
                    614:     $result =~ s/&(\#165|yen);/\\textyen /g;
                    615:     $result =~ s/&(\#166|brvbar);/\\textbrokenbar /g;
                    616:     $result =~ s/&(\#167|sect);/\\textsection /g;
                    617:     $result =~ s/&(\#168|uml);/\\texthighdieresis /g;
                    618:     $result =~ s/&(\#169|copy);/\\copyright /g;
                    619:     $result =~ s/&(\#170|ordf);/\\textordfeminine /g;
1.281     sakharuk  620:     $result =~ s/&(\#172|not);/\\ensuremath\{\\neg\}/g;
1.116     sakharuk  621:     $result =~ s/&(\#173|shy);/ - /g;
                    622:     $result =~ s/&(\#174|reg);/\\textregistered /g;
1.281     sakharuk  623:     $result =~ s/&(\#175|macr);/\\ensuremath\{^{-}\}/g;
                    624:     $result =~ s/&(\#176|deg);/\\ensuremath\{^{\\circ}\}/g;
                    625:     $result =~ s/&(\#177|plusmn);/\\ensuremath\{\\pm\}/g;
                    626:     $result =~ s/&(\#178|sup2);/\\ensuremath\{^2\}/g;
                    627:     $result =~ s/&(\#179|sup3);/\\ensuremath\{^3\}/g;
1.116     sakharuk  628:     $result =~ s/&(\#180|acute);/\\textacute /g;
1.281     sakharuk  629:     $result =~ s/&(\#181|micro);/\\ensuremath\{\\mu\}/g;
1.116     sakharuk  630:     $result =~ s/&(\#182|para);/\\P/g;
1.281     sakharuk  631:     $result =~ s/&(\#183|middot);/\\ensuremath\{\\cdot\}/g;
1.116     sakharuk  632:     $result =~ s/&(\#184|cedil);/\\c{\\strut}/g;
1.281     sakharuk  633:     $result =~ s/&(\#185|sup1);/\\ensuremath\{^1\}/g;
1.116     sakharuk  634:     $result =~ s/&(\#186|ordm);/\\textordmasculine /g;
                    635:     $result =~ s/&(\#188|frac14);/\\textonequarter /g;
                    636:     $result =~ s/&(\#189|frac12);/\\textonehalf /g;
                    637:     $result =~ s/&(\#190|frac34);/\\textthreequarters /g;
                    638:     $result =~ s/&(\#191|iquest);/?\`/g;   
                    639:     $result =~ s/&(\#192|Agrave);/\\\`{A}/g;  
                    640:     $result =~ s/&(\#193|Aacute);/\\\'{A}/g; 
                    641:     $result =~ s/&(\#194|Acirc);/\\^{A}/g;
                    642:     $result =~ s/&(\#195|Atilde);/\\~{A}/g;
                    643:     $result =~ s/&(\#196|Auml);/\\\"{A}/g; 
                    644:     $result =~ s/&(\#197|Aring);/{\\AA}/g;
                    645:     $result =~ s/&(\#198|AElig);/{\\AE}/g;
                    646:     $result =~ s/&(\#199|Ccedil);/\\c{c}/g;
                    647:     $result =~ s/&(\#200|Egrave);/\\\`{E}/g;  
                    648:     $result =~ s/&(\#201|Eacute);/\\\'{E}/g;    
                    649:     $result =~ s/&(\#202|Ecirc);/\\^{E}/g;
                    650:     $result =~ s/&(\#203|Euml);/\\\"{E}/g;
                    651:     $result =~ s/&(\#204|Igrave);/\\\`{I}/g;
                    652:     $result =~ s/&(\#205|Iacute);/\\\'{I}/g;    
                    653:     $result =~ s/&(\#206|Icirc);/\\^{I}/g;
                    654:     $result =~ s/&(\#207|Iuml);/\\\"{I}/g;    
                    655:     $result =~ s/&(\#209|Ntilde);/\\~{N}/g;
                    656:     $result =~ s/&(\#210|Ograve);/\\\`{O}/g;
                    657:     $result =~ s/&(\#211|Oacute);/\\\'{O}/g;
                    658:     $result =~ s/&(\#212|Ocirc);/\\^{O}/g;
                    659:     $result =~ s/&(\#213|Otilde);/\\~{O}/g;
                    660:     $result =~ s/&(\#214|Ouml);/\\\"{O}/g;    
1.281     sakharuk  661:     $result =~ s/&(\#215|times);/\\ensuremath\{\\times\}/g;
1.116     sakharuk  662:     $result =~ s/&(\#216|Oslash);/{\\O}/g;
                    663:     $result =~ s/&(\#217|Ugrave);/\\\`{U}/g;    
                    664:     $result =~ s/&(\#218|Uacute);/\\\'{U}/g;
                    665:     $result =~ s/&(\#219|Ucirc);/\\^{U}/g;
                    666:     $result =~ s/&(\#220|Uuml);/\\\"{U}/g;
                    667:     $result =~ s/&(\#221|Yacute);/\\\'{Y}/g;
1.329     sakharuk  668:     $result =~ s/&(\#223|szlig);/{\\ss}/g;
1.116     sakharuk  669:     $result =~ s/&(\#224|agrave);/\\\`{a}/g;
                    670:     $result =~ s/&(\#225|aacute);/\\\'{a}/g;
                    671:     $result =~ s/&(\#226|acirc);/\\^{a}/g;
                    672:     $result =~ s/&(\#227|atilde);/\\~{a}/g;
                    673:     $result =~ s/&(\#228|auml);/\\\"{a}/g;
                    674:     $result =~ s/&(\#229|aring);/{\\aa}/g;
                    675:     $result =~ s/&(\#230|aelig);/{\\ae}/g;
                    676:     $result =~ s/&(\#231|ccedil);/\\c{c}/g;
                    677:     $result =~ s/&(\#232|egrave);/\\\`{e}/g;
                    678:     $result =~ s/&(\#233|eacute);/\\\'{e}/g;
                    679:     $result =~ s/&(\#234|ecirc);/\\^{e}/g;
                    680:     $result =~ s/&(\#235|euml);/\\\"{e}/g;
                    681:     $result =~ s/&(\#236|igrave);/\\\`{i}/g;
                    682:     $result =~ s/&(\#237|iacute);/\\\'{i}/g;
                    683:     $result =~ s/&(\#238|icirc);/\\^{i}/g;
                    684:     $result =~ s/&(\#239|iuml);/\\\"{i}/g;
1.281     sakharuk  685:     $result =~ s/&(\#240|eth);/\\ensuremath\{\\partial\}/g;
1.116     sakharuk  686:     $result =~ s/&(\#241|ntilde);/\\~{n}/g;
                    687:     $result =~ s/&(\#242|ograve);/\\\`{o}/g;
                    688:     $result =~ s/&(\#243|oacute);/\\\'{o}/g;
                    689:     $result =~ s/&(\#244|ocirc);/\\^{o}/g;
                    690:     $result =~ s/&(\#245|otilde);/\\~{o}/g;
                    691:     $result =~ s/&(\#246|ouml);/\\\"{o}/g;
1.281     sakharuk  692:     $result =~ s/&(\#247|divide);/\\ensuremath\{\\div\}/g;
1.116     sakharuk  693:     $result =~ s/&(\#248|oslash);/{\\o}/g;
                    694:     $result =~ s/&(\#249|ugrave);/\\\`{u}/g; 
                    695:     $result =~ s/&(\#250|uacute);/\\\'{u}/g;
                    696:     $result =~ s/&(\#251|ucirc);/\\^{u}/g;
                    697:     $result =~ s/&(\#252|uuml);/\\\"{u}/g;
                    698:     $result =~ s/&(\#253|yacute);/\\\'{y}/g;
                    699:     $result =~ s/&(\#255|yuml);/\\\"{y}/g;
1.399     albertel  700:     $result =~ s/&\#295;/\\ensuremath\{\\hbar\}/g;
1.281     sakharuk  701:     $result =~ s/&\#952;/\\ensuremath\{\\theta\}/g;
1.117     sakharuk  702: #Greek Alphabet
1.281     sakharuk  703:     $result =~ s/&(alpha|\#945);/\\ensuremath\{\\alpha\}/g;
                    704:     $result =~ s/&(beta|\#946);/\\ensuremath\{\\beta\}/g;
                    705:     $result =~ s/&(gamma|\#947);/\\ensuremath\{\\gamma\}/g;
                    706:     $result =~ s/&(delta|\#948);/\\ensuremath\{\\delta\}/g;
                    707:     $result =~ s/&(epsilon|\#949);/\\ensuremath\{\\epsilon\}/g;
                    708:     $result =~ s/&(zeta|\#950);/\\ensuremath\{\\zeta\}/g;
                    709:     $result =~ s/&(eta|\#951);/\\ensuremath\{\\eta\}/g;
                    710:     $result =~ s/&(theta|\#952);/\\ensuremath\{\\theta\}/g;
                    711:     $result =~ s/&(iota|\#953);/\\ensuremath\{\\iota\}/g;
                    712:     $result =~ s/&(kappa|\#954);/\\ensuremath\{\\kappa\}/g;
                    713:     $result =~ s/&(lambda|\#955);/\\ensuremath\{\\lambda\}/g;
                    714:     $result =~ s/&(mu|\#956);/\\ensuremath\{\\mu\}/g;
                    715:     $result =~ s/&(nu|\#957);/\\ensuremath\{\\nu\}/g;
                    716:     $result =~ s/&(xi|\#958);/\\ensuremath\{\\xi\}/g;
1.199     sakharuk  717:     $result =~ s/&(omicron|\#959);/o/g;
1.281     sakharuk  718:     $result =~ s/&(pi|\#960);/\\ensuremath\{\\pi\}/g;
                    719:     $result =~ s/&(rho|\#961);/\\ensuremath\{\\rho\}/g;
                    720:     $result =~ s/&(sigma|\#963);/\\ensuremath\{\\sigma\}/g;
                    721:     $result =~ s/&(tau|\#964);/\\ensuremath\{\\tau\}/g;
                    722:     $result =~ s/&(upsilon|\#965);/\\ensuremath\{\\upsilon\}/g;
                    723:     $result =~ s/&(phi|\#966);/\\ensuremath\{\\phi\}/g;
                    724:     $result =~ s/&(chi|\#967);/\\ensuremath\{\\chi\}/g;
                    725:     $result =~ s/&(psi|\#968);/\\ensuremath\{\\psi\}/g;
                    726:     $result =~ s/&(omega|\#969);/\\ensuremath\{\\omega\}/g;
                    727:     $result =~ s/&(thetasym|\#977);/\\ensuremath\{\\vartheta\}/g;
                    728:     $result =~ s/&(piv|\#982);/\\ensuremath\{\\varpi\}/g;
1.199     sakharuk  729:     $result =~ s/&(Alpha|\#913);/A/g;
                    730:     $result =~ s/&(Beta|\#914);/B/g;
1.281     sakharuk  731:     $result =~ s/&(Gamma|\#915);/\\ensuremath\{\\Gamma\}/g;
                    732:     $result =~ s/&(Delta|\#916);/\\ensuremath\{\\Delta\}/g;
1.199     sakharuk  733:     $result =~ s/&(Epsilon|\#917);/E/g;
                    734:     $result =~ s/&(Zeta|\#918);/Z/g;
                    735:     $result =~ s/&(Eta|\#919);/H/g;
1.281     sakharuk  736:     $result =~ s/&(Theta|\#920);/\\ensuremath\{\\Theta\}/g;
1.199     sakharuk  737:     $result =~ s/&(Iota|\#921);/I/g;
                    738:     $result =~ s/&(Kappa|\#922);/K/g;
1.281     sakharuk  739:     $result =~ s/&(Lambda|\#923);/\\ensuremath\{\\Lambda\}/g;
1.199     sakharuk  740:     $result =~ s/&(Mu|\#924);/M/g;
                    741:     $result =~ s/&(Nu|\#925);/N/g;
1.281     sakharuk  742:     $result =~ s/&(Xi|\#926);/\\ensuremath\{\\Xi\}/g;
1.199     sakharuk  743:     $result =~ s/&(Omicron|\#927);/O/g;
1.281     sakharuk  744:     $result =~ s/&(Pi|\#928);/\\ensuremath\{\\Pi\}/g;
1.199     sakharuk  745:     $result =~ s/&(Rho|\#929);/P/g;
1.281     sakharuk  746:     $result =~ s/&(Sigma|\#931);/\\ensuremath\{\\Sigma\}/g;
1.199     sakharuk  747:     $result =~ s/&(Tau|\#932);/T/g;
1.281     sakharuk  748:     $result =~ s/&(Upsilon|\#933);/\\ensuremath\{\\Upsilon\}/g;
                    749:     $result =~ s/&(Phi|\#934);/\\ensuremath\{\\Phi\}/g;
1.199     sakharuk  750:     $result =~ s/&(Chi|\#935);/X/g;
1.281     sakharuk  751:     $result =~ s/&(Psi|\#936);/\\ensuremath\{\\Psi\}/g;
                    752:     $result =~ s/&(Omega|\#937);/\\ensuremath\{\\Omega\}/g;
1.199     sakharuk  753: #Arrows (extended HTML 4.01)
1.281     sakharuk  754:     $result =~ s/&(larr|\#8592);/\\ensuremath\{\\leftarrow\}/g;
                    755:     $result =~ s/&(uarr|\#8593);/\\ensuremath\{\\uparrow\}/g;
                    756:     $result =~ s/&(rarr|\#8594);/\\ensuremath\{\\rightarrow\}/g;
                    757:     $result =~ s/&(darr|\#8595);/\\ensuremath\{\\downarrow\}/g;
                    758:     $result =~ s/&(harr|\#8596);/\\ensuremath\{\\leftrightarrow\}/g;
                    759:     $result =~ s/&(lArr|\#8656);/\\ensuremath\{\\Leftarrow\}/g;
                    760:     $result =~ s/&(uArr|\#8657);/\\ensuremath\{\\Uparrow\}/g;
                    761:     $result =~ s/&(rArr|\#8658);/\\ensuremath\{\\Rightarrow\}/g;
                    762:     $result =~ s/&(dArr|\#8659);/\\ensuremath\{\\Downarrow\}/g;
                    763:     $result =~ s/&(hArr|\#8660);/\\ensuremath\{\\Leftrightarrow\}/g;
1.199     sakharuk  764: #Mathematical Operators (extended HTML 4.01)
1.281     sakharuk  765:     $result =~ s/&(forall|\#8704);/\\ensuremath\{\\forall\}/g;
                    766:     $result =~ s/&(part|\#8706);/\\ensuremath\{\\partial\}/g;
                    767:     $result =~ s/&(exist|\#8707);/\\ensuremath\{\\exists\}/g;
                    768:     $result =~ s/&(empty|\#8709);/\\ensuremath\{\\emptyset\}/g;
                    769:     $result =~ s/&(nabla|\#8711);/\\ensuremath\{\\nabla\}/g;
                    770:     $result =~ s/&(isin|\#8712);/\\ensuremath\{\\in\}/g;
                    771:     $result =~ s/&(notin|\#8713);/\\ensuremath\{\\notin\}/g;
                    772:     $result =~ s/&(ni|\#8715);/\\ensuremath\{\\ni\}/g;
                    773:     $result =~ s/&(prod|\#8719);/\\ensuremath\{\\prod\}/g;
                    774:     $result =~ s/&(sum|\#8721);/\\ensuremath\{\\sum\}/g;
                    775:     $result =~ s/&(minus|\#8722);/\\ensuremath\{-\}/g;
1.390     albertel  776:     $result =~ s/–/\\ensuremath\{-\}/g;
1.281     sakharuk  777:     $result =~ s/&(lowast|\#8727);/\\ensuremath\{*\}/g;
                    778:     $result =~ s/&(radic|\#8730);/\\ensuremath\{\\surd\}/g;
                    779:     $result =~ s/&(prop|\#8733);/\\ensuremath\{\\propto\}/g;
                    780:     $result =~ s/&(infin|\#8734);/\\ensuremath\{\\infty\}/g;
                    781:     $result =~ s/&(ang|\#8736);/\\ensuremath\{\\angle\}/g;
                    782:     $result =~ s/&(and|\#8743);/\\ensuremath\{\\wedge\}/g;
                    783:     $result =~ s/&(or|\#8744);/\\ensuremath\{\\vee\}/g;
                    784:     $result =~ s/&(cap|\#8745);/\\ensuremath\{\\cap\}/g;
                    785:     $result =~ s/&(cup|\#8746);/\\ensuremath\{\\cup\}/g;
                    786:     $result =~ s/&(int|\#8747);/\\ensuremath\{\\int\}/g;
                    787:     $result =~ s/&(sim|\#8764);/\\ensuremath\{\\sim\}/g;
                    788:     $result =~ s/&(cong|\#8773);/\\ensuremath\{\\cong\}/g;
                    789:     $result =~ s/&(asymp|\#8776);/\\ensuremath\{\\approx\}/g;
                    790:     $result =~ s/&(ne|\#8800);/\\ensuremath\{\\not=\}/g;
                    791:     $result =~ s/&(equiv|\#8801);/\\ensuremath\{\\equiv\}/g;
                    792:     $result =~ s/&(le|\#8804);/\\ensuremath\{\\leq\}/g;
                    793:     $result =~ s/&(ge|\#8805);/\\ensuremath\{\\geq\}/g;
                    794:     $result =~ s/&(sub|\#8834);/\\ensuremath\{\\subset\}/g;
                    795:     $result =~ s/&(sup|\#8835);/\\ensuremath\{\\supset\}/g;
                    796:     $result =~ s/&(nsub|\#8836);/\\ensuremath\{\\not\\subset\}/g;
                    797:     $result =~ s/&(sube|\#8838);/\\ensuremath\{\\subseteq\}/g;
                    798:     $result =~ s/&(supe|\#8839);/\\ensuremath\{\\supseteq\}/g;
                    799:     $result =~ s/&(oplus|\#8853);/\\ensuremath\{\\oplus\}/g;
                    800:     $result =~ s/&(otimes|\#8855);/\\ensuremath\{\\otimes\}/g;
                    801:     $result =~ s/&(perp|\#8869);/\\ensuremath\{\\perp\}/g;
                    802:     $result =~ s/&(sdot|\#8901);/\\ensuremath\{\\cdot\}/g;
1.199     sakharuk  803: #Geometric Shapes (extended HTML 4.01)
1.281     sakharuk  804:     $result =~ s/&(loz|\#9674);/\\ensuremath\{\\Diamond\}/g;
1.199     sakharuk  805: #Miscellaneous Symbols (extended HTML 4.01)
1.281     sakharuk  806:     $result =~ s/&(spades|\#9824);/\\ensuremath\{\\spadesuit\}/g;
                    807:     $result =~ s/&(clubs|\#9827);/\\ensuremath\{\\clubsuit\}/g;
                    808:     $result =~ s/&(hearts|\#9829);/\\ensuremath\{\\heartsuit\}/g;
                    809:     $result =~ s/&(diams|\#9830);/\\ensuremath\{\\diamondsuit\}/g;
1.495     foxr      810: #   Chemically useful 'things' contributed by Hon Kie (bug 4652).
1.515     foxr      811: 
1.495     foxr      812:     $result =~ s/&\#8636;/\\ensuremath\{\\leftharpoonup\}/g;
                    813:     $result =~ s/&\#8637;/\\ensuremath\{\\leftharpoondown\}/g;
                    814:     $result =~ s/&\#8640;/\\ensuremath\{\\rightharpoonup\}/g;
                    815:     $result =~ s/&\#8641;/\\ensuremath\{\\rightharpoondown\}/g;
                    816:     $result =~ s/&\#8652;/\\ensuremath\{\\rightleftharpoons\}/g;
                    817:     $result =~ s/&\#8605;/\\ensuremath\{\\leadsto\}/g;
                    818:     $result =~ s/&\#8617;/\\ensuremath\{\\hookleftarrow\}/g;
                    819:     $result =~ s/&\#8618;/\\ensuremath\{\\hookrightarrow\}/g;
                    820:     $result =~ s/&\#8614;/\\ensuremath\{\\mapsto\}/g;
                    821:     $result =~ s/&\#8599;/\\ensuremath\{\\nearrow\}/g;
                    822:     $result =~ s/&\#8600;/\\ensuremath\{\\searrow\}/g;
                    823:     $result =~ s/&\#8601;/\\ensuremath\{\\swarrow\}/g;
                    824:     $result =~ s/&\#8598;/\\ensuremath\{\\nwarrow\}/g;
1.513     foxr      825: 
                    826:     # Left/right quotations:
                    827: 
                    828:     $result =~ s/&(ldquo|#8220);/\`\`/g;
                    829:     $result =~ s/&(rdquo|#8221);/\'\'/g;
                    830: 
                    831: 
1.37      sakharuk  832:     return $result;
                    833: }
1.41      sakharuk  834: 
                    835: 
1.327     albertel  836:                   #width, height, oddsidemargin, evensidemargin, topmargin
                    837: my %page_formats=
                    838:     ('letter' => {
                    839: 	 'book' => {
1.493     foxr      840: 	     '1' => [ '7.1 in','9.8 in', '-0.57 in','-0.57 in','0.275 in'],
                    841: 	     '2' => ['3.66 in','9.8 in', '-0.57 in','-0.57 in','0.275 in']
1.327     albertel  842: 	 },
                    843: 	 'album' => {
1.496     foxr      844: 	     '1' => [ '8.8 in', '6.8 in','-0.55 in',  '-0.55 in','0.394 in'],
1.484     albertel  845: 	     '2' => [ '4.8 in', '6.8 in','-0.5 in', '-1.0 in','3.5 in']
1.327     albertel  846: 	 },
                    847:      },
                    848:      'legal' => {
                    849: 	 'book' => {
                    850: 	     '1' => ['7.1 in','13 in',,'-0.57 in','-0.57 in','-0.5 in'],
1.514     foxr      851: 	     '2' => ['3.66 in','13 in','-0.57 in','-0.57 in','-0.5 in']
1.327     albertel  852: 	 },
                    853: 	 'album' => {
1.376     albertel  854: 	     '1' => ['12 in','7.1 in',,'-0.57 in','-0.57 in','-0.5 in'],
                    855:              '2' => ['6.0 in','7.1 in','-1 in','-1 in','5 in']
1.327     albertel  856:           },
                    857:      },
                    858:      'tabloid' => {
                    859: 	 'book' => {
                    860: 	     '1' => ['9.8 in','16 in','-0.57 in','-0.57 in','-0.5 in'],
                    861: 	     '2' => ['4.9 in','16 in','-0.57 in','-0.57 in','-0.5 in']
                    862: 	 },
                    863: 	 'album' => {
1.376     albertel  864: 	     '1' => ['16 in','9.8 in','-0.57 in','-0.57 in','-0.5 in'],
                    865: 	     '2' => ['16 in','4.9 in','-0.57 in','-0.57 in','-0.5 in']
1.327     albertel  866:           },
                    867:      },
                    868:      'executive' => {
                    869: 	 'book' => {
                    870: 	     '1' => ['6.8 in','9 in','-0.57 in','-0.57 in','1.2 in'],
                    871: 	     '2' => ['3.1 in','9 in','-0.57 in','-0.57 in','1.2 in']
                    872: 	 },
                    873: 	 'album' => {
                    874: 	     '1' => [],
                    875: 	     '2' => []
                    876:           },
                    877:      },
                    878:      'a2' => {
                    879: 	 'book' => {
                    880: 	     '1' => [],
                    881: 	     '2' => []
                    882: 	 },
                    883: 	 'album' => {
                    884: 	     '1' => [],
                    885: 	     '2' => []
                    886:           },
                    887:      },
                    888:      'a3' => {
                    889: 	 'book' => {
                    890: 	     '1' => [],
                    891: 	     '2' => []
                    892: 	 },
                    893: 	 'album' => {
                    894: 	     '1' => [],
                    895: 	     '2' => []
                    896:           },
                    897:      },
                    898:      'a4' => {
                    899: 	 'book' => {
1.493     foxr      900: 	     '1' => ['17.6 cm','27.2 cm','-1.397 cm','-2.11 cm','-1.27 cm'],
1.496     foxr      901: 	     '2' => [ '9.1 cm','27.2 cm','-1.397 cm','-2.11 cm','-1.27 cm']
1.327     albertel  902: 	 },
                    903: 	 'album' => {
1.496     foxr      904: 	     '1' => ['21.59 cm','19.558 cm','-1.397cm','-2.11 cm','0 cm'],
1.493     foxr      905: 	     '2' => ['9.91 cm','19.558 cm','-1.397 cm','-2.11 cm','0 cm']
1.327     albertel  906: 	 },
                    907:      },
                    908:      'a5' => {
                    909: 	 'book' => {
                    910: 	     '1' => [],
                    911: 	     '2' => []
                    912: 	 },
                    913: 	 'album' => {
                    914: 	     '1' => [],
                    915: 	     '2' => []
                    916:           },
                    917:      },
                    918:      'a6' => {
                    919: 	 'book' => {
                    920: 	     '1' => [],
                    921: 	     '2' => []
                    922: 	 },
                    923: 	 'album' => {
                    924: 	     '1' => [],
                    925: 	     '2' => []
                    926:           },
                    927:      },
                    928:      );
                    929: 
1.177     sakharuk  930: sub page_format {
1.140     sakharuk  931: #
1.326     sakharuk  932: #Supported paper format: "Letter [8 1/2x11 in]",      "Legal [8 1/2x14 in]",
                    933: #                        "Ledger/Tabloid [11x17 in]", "Executive [7 1/2x10 in]",
                    934: #                        "A2 [420x594 mm]",           "A3 [297x420 mm]",
                    935: #                        "A4 [210x297 mm]",           "A5 [148x210 mm]",
                    936: #                        "A6 [105x148 mm]"
1.140     sakharuk  937: # 
                    938:     my ($papersize,$layout,$numberofcolumns) = @_; 
1.327     albertel  939:     return @{$page_formats{$papersize}->{$layout}->{$numberofcolumns}};
1.140     sakharuk  940: }
1.76      sakharuk  941: 
                    942: 
1.126     albertel  943: sub get_name {
                    944:     my ($uname,$udom)=@_;
1.373     albertel  945:     if (!defined($uname)) { $uname=$env{'user.name'}; }
                    946:     if (!defined($udom)) { $udom=$env{'user.domain'}; }
1.126     albertel  947:     my $plainname=&Apache::loncommon::plainname($uname,$udom);
1.213     albertel  948:     if ($plainname=~/^\s*$/) { $plainname=$uname.'@'.$udom; }
1.453     foxr      949:    $plainname=&Apache::lonxml::latex_special_symbols($plainname,'header');
1.213     albertel  950:     return $plainname;
1.126     albertel  951: }
                    952: 
1.213     albertel  953: sub get_course {
                    954:     my $courseidinfo;
1.373     albertel  955:     if (defined($env{'request.course.id'})) {
1.439     www       956: 	$courseidinfo = &Apache::lonxml::latex_special_symbols(&unescape($env{'course.'.$env{'request.course.id'}.'.description'}),'header');
1.213     albertel  957:     }
                    958:     return $courseidinfo;
                    959: }
1.177     sakharuk  960: 
1.76      sakharuk  961: sub page_format_transformation {
1.312     sakharuk  962:     my ($papersize,$layout,$numberofcolumns,$choice,$text,$assignment,$tableofcontents,$indexlist,$selectionmade) = @_; 
1.202     sakharuk  963:     my ($textwidth,$textheight,$oddoffset,$evenoffset,$topmargin);
1.454     foxr      964: 
1.312     sakharuk  965:     if ($selectionmade eq '4') {
1.502     foxr      966: 	if ($choice eq 'all_problems') {
                    967: 	    $assignment='Problems from the Whole Course';
                    968: 	} else {
                    969: 	    $assignment='Resources from the Whole Course';
                    970: 	}
1.312     sakharuk  971:     } else {
                    972: 	$assignment=&Apache::lonxml::latex_special_symbols($assignment,'header');
                    973:     }
1.261     sakharuk  974:     ($textwidth,$textheight,$oddoffset,$evenoffset,$topmargin) = &page_format($papersize,$layout,$numberofcolumns,$topmargin);
1.454     foxr      975: 
                    976: 
1.126     albertel  977:     my $name = &get_name();
1.213     albertel  978:     my $courseidinfo = &get_course();
                    979:     if (defined($courseidinfo)) { $courseidinfo=' - '.$courseidinfo }
1.455     albertel  980:     my $header_text  = $parmhash{'print_header_format'};
1.486     foxr      981:     $header_text     = &format_page_header($textwidth, $header_text, $assignment,
1.455     albertel  982: 					   $courseidinfo, $name);
1.319     sakharuk  983:     my $topmargintoinsert = '';
                    984:     if ($topmargin ne '0') {$topmargintoinsert='\setlength{\topmargin}{'.$topmargin.'}';}
1.325     sakharuk  985:     my $fancypagestatement='';
                    986:     if ($numberofcolumns eq '2') {
1.455     albertel  987: 	$fancypagestatement="\\fancyhead{}\\fancyhead[LO]{$header_text}";
1.325     sakharuk  988:     } else {
1.455     albertel  989: 	$fancypagestatement="\\rhead{}\\chead{}\\lhead{$header_text}";
1.325     sakharuk  990:     }
1.140     sakharuk  991:     if ($layout eq 'album') {
1.340     foxr      992: 	    $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 /;
1.140     sakharuk  993:     } elsif ($layout eq 'book') {
                    994: 	if ($choice ne 'All class print') { 
1.340     foxr      995: 	    $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\\begin{document}\n\\voffset=-0\.8 cm\\setcounter{page}{1}\n/;
1.140     sakharuk  996: 	} else {
1.340     foxr      997: 	    $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{}\\begin{document}\\voffset=-0\.8cm\n\\setcounter{page}{1}  \\vskip 5 mm\n /;
1.319     sakharuk  998: 	}
1.326     sakharuk  999: 	if ($papersize eq 'a4') {
1.319     sakharuk 1000: 	    $text =~ s/(\\begin{document})/$1\\special{papersize=210mm,297mm}/;
1.140     sakharuk 1001: 	}
                   1002:     }
1.214     sakharuk 1003:     if ($tableofcontents eq 'yes') {$text=~s/(\\setcounter\{page\}\{1\})/$1 \\tableofcontents\\newpage /;}
                   1004:     if ($indexlist eq 'yes') {
                   1005: 	$text=~s/(\\begin{document})/\\makeindex $1/;
                   1006: 	$text=~s/(\\end{document})/\\strut\\\\\\strut\\printindex $1/;
                   1007:     }
1.140     sakharuk 1008:     return $text;
                   1009: }
                   1010: 
                   1011: 
1.33      sakharuk 1012: sub page_cleanup {
                   1013:     my $result = shift;	
1.65      sakharuk 1014:  
                   1015:     $result =~ m/\\end{document}(\d*)$/;
1.34      sakharuk 1016:     my $number_of_columns = $1;
1.33      sakharuk 1017:     my $insert = '{';
1.34      sakharuk 1018:     for (my $id=1;$id<=$number_of_columns;$id++) { $insert .='l'; }
1.33      sakharuk 1019:     $insert .= '}';
1.65      sakharuk 1020:     $result =~ s/(\\begin{longtable})INSERTTHEHEADOFLONGTABLE\\endfirsthead\\endhead/$1$insert/g;
1.34      sakharuk 1021:     $result =~ s/&\s*REMOVETHEHEADOFLONGTABLE\\\\/\\\\/g;
                   1022:     return $result,$number_of_columns;
1.7       sakharuk 1023: }
1.5       sakharuk 1024: 
1.3       sakharuk 1025: 
1.60      sakharuk 1026: sub details_for_menu {
1.335     albertel 1027:     my ($helper)=@_;
1.373     albertel 1028:     my $postdata=$env{'form.postdata'};
1.335     albertel 1029:     if (!$postdata) { $postdata=$helper->{VARS}{'postdata'}; }
                   1030:     my $name_of_resource = &Apache::lonnet::gettitle($postdata);
                   1031:     my $symbolic = &Apache::lonnet::symbread($postdata);
1.482     albertel 1032:     return if ( $symbolic eq '');
                   1033: 
1.233     www      1034:     my ($map,$id,$resource)=&Apache::lonnet::decode_symb($symbolic);
1.123     albertel 1035:     $map=&Apache::lonnet::clutter($map);
1.269     albertel 1036:     my $name_of_sequence = &Apache::lonnet::gettitle($map);
1.63      albertel 1037:     if ($name_of_sequence =~ /^\s*$/) {
1.123     albertel 1038: 	$map =~ m|([^/]+)$|;
                   1039: 	$name_of_sequence = $1;
1.63      albertel 1040:     }
1.373     albertel 1041:     my $name_of_map = &Apache::lonnet::gettitle($env{'request.course.uri'});
1.63      albertel 1042:     if ($name_of_map =~ /^\s*$/) {
1.373     albertel 1043: 	$env{'request.course.uri'} =~ m|([^/]+)$|;
1.123     albertel 1044: 	$name_of_map = $1;
                   1045:     }
1.335     albertel 1046:     return ($name_of_resource,$name_of_sequence,$name_of_map);
1.76      sakharuk 1047: }
                   1048: 
1.476     albertel 1049: sub copyright_line {
                   1050:     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 } ';
                   1051: }
                   1052: my $end_of_student = "\n".'\special{ps:ENDOFSTUDENTSTAMP}'."\n";
1.76      sakharuk 1053: 
                   1054: sub latex_corrections {
1.408     albertel 1055:     my ($number_of_columns,$result,$selectionmade,$answer_mode) = @_;
1.185     sakharuk 1056: #    $result =~ s/\\includegraphics{/\\includegraphics\[width=\\minipagewidth\]{/g;
1.476     albertel 1057:     my $copyright = &copyright_line();
1.408     albertel 1058:     if ($selectionmade eq '1' || $answer_mode eq 'only') {
1.476     albertel 1059: 	$result =~ s/(\\end{document})/\\strut\\vskip 0 mm $copyright $end_of_student $1/;
1.408     albertel 1060:     } else {
1.476     albertel 1061: 	$result =~ s/(\\end{document})/\\strut\\vspace\*{-4 mm}\\newline $copyright $end_of_student $1/;
1.316     sakharuk 1062:     }
1.476     albertel 1063:     $result =~ s/\$number_of_columns/$number_of_columns/g;
1.91      sakharuk 1064:     $result =~ s/(\\end{longtable}\s*)(\\strut\\newline\\noindent\\makebox\[\\textwidth\/$number_of_columns\]\[b\]{\\hrulefill})/$2$1/g;
                   1065:     $result =~ s/(\\end{longtable}\s*)\\strut\\newline/$1/g;
1.76      sakharuk 1066: #-- LaTeX corrections     
                   1067:     my $first_comment = index($result,'<!--',0);
                   1068:     while ($first_comment != -1) {
                   1069: 	my $end_comment = index($result,'-->',$first_comment);
                   1070: 	substr($result,$first_comment,$end_comment-$first_comment+3) = '';
                   1071: 	$first_comment = index($result,'<!--',$first_comment);
                   1072:     }
                   1073:     $result =~ s/^\s+$//gm; #remove empty lines
1.377     albertel 1074:     #removes more than one empty space
                   1075:     $result =~ s|(\s\s+)|($1=~/[\n\r]/)?"\n":" "|ge;
1.76      sakharuk 1076:     $result =~ s/\\\\\s*\\vskip/\\vskip/gm;
                   1077:     $result =~ s/\\\\\s*\\noindent\s*(\\\\)+/\\\\\\noindent /g;
                   1078:     $result =~ s/{\\par }\s*\\\\/\\\\/gm;
1.313     sakharuk 1079:     $result =~ s/\\\\\s+\[/ \[/g;
1.76      sakharuk 1080:     #conversion of html characters to LaTeX equivalents
                   1081:     if ($result =~ m/&(\w+|#\d+);/) {
                   1082: 	$result = &character_chart($result);
                   1083:     }
                   1084:     $result =~ s/(\\end{tabular})\s*\\vskip 0 mm/$1/g;
                   1085:     $result =~ s/(\\begin{enumerate})\s*\\noindent/$1/g;
                   1086:     return $result;
1.60      sakharuk 1087: }
                   1088: 
1.3       sakharuk 1089: 
1.214     sakharuk 1090: sub index_table {
                   1091:     my $currentURL = shift;
                   1092:     my $insex_string='';
                   1093:     $currentURL=~s/\.([^\/+])$/\.$1\.meta/;
                   1094:     $insex_string=&Apache::lonnet::metadata($currentURL,'keywords');
                   1095:     return $insex_string;
                   1096: }
                   1097: 
                   1098: 
1.215     sakharuk 1099: sub IndexCreation {
                   1100:     my ($texversion,$currentURL)=@_;
                   1101:     my @key_words=split(/,/,&index_table($currentURL));
                   1102:     my $chunk='';
                   1103:     my $st=index $texversion,'\addcontentsline{toc}{subsection}{';
                   1104:     if ($st>0) {
                   1105: 	for (my $i=0;$i<3;$i++) {$st=(index $texversion,'}',$st+1);}
                   1106: 	$chunk=substr($texversion,0,$st+1);
                   1107: 	substr($texversion,0,$st+1)=' ';
                   1108:     }
                   1109:     foreach my $key_word (@key_words) {
                   1110: 	if ($key_word=~/\S+/) {
                   1111: 	    $texversion=~s/\b($key_word)\b/$1 \\index{$key_word} /i;
                   1112: 	}
                   1113:     }			
                   1114:     if ($st>0) {substr($texversion,0,1)=$chunk;}
                   1115:     return $texversion;
                   1116: }
                   1117: 
1.242     sakharuk 1118: sub print_latex_header {
                   1119:     my $mode=shift;
1.473     albertel 1120:     my $output='\documentclass[letterpaper,twoside]{article}\raggedbottom';
1.397     albertel 1121:     if (($mode eq 'batchmode') || (!$perm{'pav'})) {
1.242     sakharuk 1122: 	$output.='\batchmode';
                   1123:     }
1.340     foxr     1124:     $output.='\newcommand{\keephidden}[1]{}\renewcommand{\deg}{$^{\circ}$}'."\n".
1.410     foxr     1125:    	    '\usepackage{multirow}'."\n".
1.340     foxr     1126: 	     '\usepackage{longtable}\usepackage{textcomp}\usepackage{makeidx}'."\n".
1.344     foxr     1127: 	     '\usepackage[dvips]{graphicx}\usepackage{epsfig}'."\n".
1.393     foxr     1128: 	     '\usepackage{wrapfig}'.
1.344     foxr     1129: 	     '\usepackage{picins}\usepackage{calc}'."\n".
1.517     foxr     1130: 	     '\usepackage[utf8]{inputenc}'."\n".
1.340     foxr     1131: 	     '\newenvironment{choicelist}{\begin{list}{}{\setlength{\rightmargin}{0in}'."\n".
                   1132: 	     '\setlength{\leftmargin}{0.13in}\setlength{\topsep}{0.05in}'."\n".
                   1133: 	     '\setlength{\itemsep}{0.022in}\setlength{\parsep}{0in}'."\n".
                   1134: 	     '\setlength{\belowdisplayskip}{0.04in}\setlength{\abovedisplayskip}{0.05in}'."\n".
                   1135: 	     '\setlength{\abovedisplayshortskip}{-0.04in}'."\n".
                   1136: 	     '\setlength{\belowdisplayshortskip}{0.04in}}}{\end{list}}'."\n".
                   1137: 	     '\renewenvironment{theindex}{\begin{list}{}{{\vskip 1mm \noindent \large'."\n".
                   1138: 	     '\textbf{Index}} \newline \setlength{\rightmargin}{0in}'."\n".
                   1139: 	     '\setlength{\leftmargin}{0.13in}\setlength{\topsep}{0.01in}'."\n".
                   1140: 	     '\setlength{\itemsep}{0.1in}\setlength{\parsep}{-0.02in}'."\n".
                   1141: 	     '\setlength{\belowdisplayskip}{0.01in}\setlength{\abovedisplayskip}{0.01in}'."\n".
                   1142: 	     '\setlength{\abovedisplayshortskip}{-0.04in}'."\n".
                   1143: 	     '\setlength{\belowdisplayshortskip}{0.01in}}}{\end{list}}\begin{document}'."\n";
1.242     sakharuk 1144:     return $output;	     
                   1145: }
                   1146: 
                   1147: sub path_to_problem {
1.328     albertel 1148:     my ($urlp,$colwidth)=@_;
1.404     albertel 1149:     $urlp=&Apache::lonnet::clutter($urlp);
                   1150: 
1.242     sakharuk 1151:     my $newurlp = '';
1.328     albertel 1152:     $colwidth=~s/\s*mm\s*$//;
                   1153: #characters average about 2 mm in width
1.360     albertel 1154:     if (length($urlp)*2 > $colwidth) {
1.404     albertel 1155: 	my @elements = split('/',$urlp);
1.328     albertel 1156: 	my $curlength=0;
                   1157: 	foreach my $element (@elements) {
1.404     albertel 1158: 	    if ($element eq '') { next; }
1.328     albertel 1159: 	    if ($curlength+(length($element)*2) > $colwidth) {
1.404     albertel 1160: 		$newurlp .=  '|\vskip -1 mm \verb|';
                   1161: 		$curlength=length($element)*2;
1.328     albertel 1162: 	    } else {
                   1163: 		$curlength+=length($element)*2;
1.242     sakharuk 1164: 	    }
1.328     albertel 1165: 	    $newurlp.='/'.$element;
1.242     sakharuk 1166: 	}
1.253     sakharuk 1167:     } else {
                   1168: 	$newurlp=$urlp;
1.242     sakharuk 1169:     }
                   1170:     return '{\small\noindent\verb|'.$newurlp.'|\vskip 0 mm}';
                   1171: }
1.215     sakharuk 1172: 
1.275     sakharuk 1173: sub recalcto_mm {
                   1174:     my $textwidth=shift;
                   1175:     my $LaTeXwidth;
1.339     albertel 1176:     if ($textwidth=~/(-?\d+\.?\d*)\s*cm/) {
1.275     sakharuk 1177: 	$LaTeXwidth = $1*10;
1.339     albertel 1178:     } elsif ($textwidth=~/(-?\d+\.?\d*)\s*mm/) {
1.275     sakharuk 1179: 	$LaTeXwidth = $1;
1.339     albertel 1180:     } elsif ($textwidth=~/(-?\d+\.?\d*)\s*in/) {
1.275     sakharuk 1181: 	$LaTeXwidth = $1*25.4;
                   1182:     }
                   1183:     $LaTeXwidth.=' mm';
                   1184:     return $LaTeXwidth;
                   1185: }
                   1186: 
1.285     albertel 1187: sub get_textwidth {
                   1188:     my ($helper,$LaTeXwidth)=@_;
1.286     albertel 1189:     my $textwidth=$LaTeXwidth;
1.285     albertel 1190:     if ($helper->{'VARS'}->{'pagesize.width'}=~/\d+/ &&
                   1191: 	$helper->{'VARS'}->{'pagesize.widthunit'}=~/\w+/) {
1.286     albertel 1192: 	$textwidth=&recalcto_mm($helper->{'VARS'}->{'pagesize.width'}.' '.
                   1193: 				$helper->{'VARS'}->{'pagesize.widthunit'});
1.285     albertel 1194:     }
1.286     albertel 1195:     return $textwidth;
1.285     albertel 1196: }
                   1197: 
1.296     sakharuk 1198: 
                   1199: sub unsupported {
1.414     albertel 1200:     my ($currentURL,$mode,$symb)=@_;
1.307     sakharuk 1201:     if ($mode ne '') {$mode='\\'.$mode}
1.308     sakharuk 1202:     my $result.= &print_latex_header($mode);
1.414     albertel 1203:     if ($currentURL=~m|^(/adm/wrapper/)?ext/|) {
                   1204: 	$currentURL=~s|^(/adm/wrapper/)?ext/|http://|;
                   1205: 	my $title=&Apache::lonnet::gettitle($symb);
                   1206: 	$title = &Apache::lonxml::latex_special_symbols($title);
                   1207: 	$result.=' \strut \\\\ '.$title.' \strut \\\\ '.$currentURL.' ';
1.296     sakharuk 1208:     } else {
                   1209: 	$result.=$currentURL;
                   1210:     }
1.419     albertel 1211:     $result.= '\vskip 0.5mm\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill} \end{document}';
1.296     sakharuk 1212:     return $result;
                   1213: }
                   1214: 
                   1215: 
1.363     foxr     1216: #
1.395     www      1217: # List of recently generated print files
                   1218: #
                   1219: sub recently_generated {
                   1220:     my $r=shift;
                   1221:     my $prtspool=$r->dir_config('lonPrtDir');
1.400     albertel 1222:     my $zip_result;
                   1223:     my $pdf_result;
1.395     www      1224:     opendir(DIR,$prtspool);
1.400     albertel 1225: 
                   1226:     my @files = 
                   1227: 	grep(/^$env{'user.name'}_$env{'user.domain'}_printout_(\d+)_.*\.(pdf|zip)$/,readdir(DIR));
1.395     www      1228:     closedir(DIR);
1.400     albertel 1229: 
                   1230:     @files = sort {
                   1231: 	my ($actime) = (stat($prtspool.'/'.$a))[10];
                   1232: 	my ($bctime) = (stat($prtspool.'/'.$b))[10];
                   1233: 	return $bctime <=> $actime;
                   1234:     } (@files);
                   1235: 
                   1236:     foreach my $filename (@files) {
                   1237: 	my ($ext) = ($filename =~ m/(pdf|zip)$/);
                   1238: 	my ($cdev,$cino,$cmode,$cnlink,
                   1239: 	    $cuid,$cgid,$crdev,$csize,
                   1240: 	    $catime,$cmtime,$cctime,
                   1241: 	    $cblksize,$cblocks)=stat($prtspool.'/'.$filename);
                   1242: 	my $result="<a href='/prtspool/$filename'>".
                   1243: 	    &mt('Generated [_1] ([_2] bytes)',
                   1244: 		&Apache::lonlocal::locallocaltime($cctime),$csize).
                   1245: 		'</a><br />';
                   1246: 	if ($ext eq 'pdf') { $pdf_result .= $result; }
                   1247: 	if ($ext eq 'zip') { $zip_result .= $result; }
                   1248:     }
                   1249:     if ($zip_result) {
                   1250: 	$r->print('<h4>'.&mt('Recently generated printout zip files')."</h4>\n"
                   1251: 		  .$zip_result);
                   1252:     }
                   1253:     if ($pdf_result) {
                   1254: 	$r->print('<h4>'.&mt('Recently generated printouts')."</h4>\n"
                   1255: 		  .$pdf_result);
1.396     albertel 1256:     }
1.395     www      1257: }
                   1258: 
                   1259: #
1.363     foxr     1260: #   Retrieve the hash of page breaks.
                   1261: #
                   1262: #  Inputs:
                   1263: #    helper   - reference to helper object.
                   1264: #  Outputs
                   1265: #    A reference to a page break hash.
                   1266: #
                   1267: #
1.418     foxr     1268: #use Data::Dumper;
                   1269: #sub dump_helper_vars {
                   1270: #    my ($helper) = @_;
                   1271: #    my $helpervars = Dumper($helper->{'VARS'});
                   1272: #    &Apache::lonnet::logthis("Dump of helper vars:\n $helpervars");
                   1273: #}
1.363     foxr     1274: 
1.481     albertel 1275: sub get_page_breaks  {
                   1276:     my ($helper) = @_;
                   1277:     my %page_breaks;
                   1278: 
                   1279:     foreach my $break (split /\|\|\|/, $helper->{'VARS'}->{'FINISHPAGE'}) {
                   1280: 	$page_breaks{$break} = 1;
                   1281:     }
                   1282:     return %page_breaks;
                   1283: }
1.363     foxr     1284: 
1.459     foxr     1285: #  Output a sequence (recursively if neeed)
                   1286: #  from construction space.
                   1287: # Parameters:
                   1288: #    url     = URL of the sequence to print.
                   1289: #    helper  - Reference to the helper hash.
                   1290: #    form    - Copy of the format hash.
                   1291: #    LaTeXWidth
                   1292: # Returns:
                   1293: #   Text to add to the printout.
                   1294: #   NOTE if the first element of the outermost sequence
                   1295: #   is itself a sequence, the outermost caller may need to
                   1296: #   prefix the latex with the page headers stuff.
                   1297: #
                   1298: sub print_construction_sequence {
                   1299:     my ($currentURL, $helper, %form, $LaTeXwidth) = @_;
                   1300:     my $result;
                   1301:     my $rndseed=time;
                   1302:     if ($helper->{'VARS'}->{'curseed'}) {
                   1303: 	$rndseed=$helper->{'VARS'}->{'curseed'};
                   1304:     }
1.491     albertel 1305:     my $errtext=&LONCAPA::map::mapread($currentURL);
1.459     foxr     1306:     # 
                   1307:     #  These make this all support recursing for subsequences.
                   1308:     #
1.491     albertel 1309:     my @order    = @LONCAPA::map::order;
                   1310:     my @resources = @LONCAPA::map::resources; 
1.459     foxr     1311:     for (my $member=0;$member<=$#order;$member++) {
                   1312: 	$resources[$order[$member]]=~/^([^:]*):([^:]*):/;
                   1313: 	my $urlp=$2;
                   1314: 	if ($urlp=~/\.(problem|exam|quiz|assess|survey|form|library|xml|html|htm|xhtml|xhtm)$/) {
                   1315: 	    my $texversion='';
                   1316: 	    if ($helper->{'VARS'}->{'ANSWER_TYPE'} ne 'only') {
                   1317: 		$form{'problem_split'}=$parmhash{'problem_stream_switch'};
                   1318: 		$form{'suppress_tries'}=$parmhash{'suppress_tries'};
                   1319: 		$form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'};
                   1320: 		$form{'rndseed'}=$rndseed;
                   1321: 		$resources_printed .=$urlp.':';
1.515     foxr     1322: 		$texversion=&ssi_with_retries($urlp, $ssi_retry_count, %form);
1.459     foxr     1323: 	    }
                   1324: 	    if((($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') ||
                   1325: 		($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) && 
                   1326: 	       ($urlp=~/\.(problem|exam|quiz|assess|survey|form|library|page)$/)) {
                   1327: 		#  Don't permanently modify %$form...
                   1328: 		my %answerform = %form;
                   1329: 		$answerform{'grade_target'}='answer';
                   1330: 		$answerform{'answer_output_mode'}='tex';
                   1331: 		$answerform{'rndseed'}=$rndseed;
                   1332: 		$answerform{'problem_split'}=$parmhash{'problem_stream_switch'};
1.481     albertel 1333: 		if ($urlp=~/\/res\//) {$env{'request.state'}='published';}
1.459     foxr     1334: 		$resources_printed .= $urlp.':';
1.515     foxr     1335: 		my $answer=&ssi_with_retries($urlp, $ssi_retry_count, %answerform);
1.459     foxr     1336: 		if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') {
                   1337: 		    $texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
                   1338: 		} else {
                   1339: 		    # If necessary, encapsulate answer in minipage:
                   1340: 		    
                   1341: 		    $texversion=&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'});
1.477     albertel 1342: 		    my $title = &Apache::lonnet::gettitle($helper->{'VARS'}->{'symb'});
                   1343: 		    $title = &Apache::lonxml::latex_special_symbols($title);
                   1344: 		    my $body ='\vskip 0 mm \noindent\textbf{'.$title.'}\vskip 0 mm ';
1.459     foxr     1345: 		    $body.=&path_to_problem($urlp,$LaTeXwidth);
                   1346: 		    $body.='\vskip 1 mm '.$answer.'\end{document}';
                   1347: 		    $body = &encapsulate_minipage($body);
                   1348: 		    $texversion.=$body;
                   1349: 		}
                   1350: 	    }
                   1351: 	    $texversion = &latex_header_footer_remove($texversion);
                   1352: 
                   1353: 	    if ($helper->{'VARS'}->{'TABLE_INDEX'} eq 'yes') {
                   1354: 		$texversion=&IndexCreation($texversion,$urlp);
                   1355: 	    }
                   1356: 	    if ($helper->{'VARS'}->{'CONSTR_RESOURSE_URL'} eq 'yes') {
                   1357: 		$texversion=~s/(\\addcontentsline\{toc\}\{subsection\}\{[^\}]*\})/$1 URL: \\verb|$urlp| \\strut\\\\\\strut /;
                   1358: 	    }
                   1359: 	    $result.=$texversion;
                   1360: 
                   1361: 	} elsif ($urlp=~/\.(sequence|page)$/) {
                   1362: 	    
                   1363: 	    # header:
                   1364: 
                   1365: 	    $result.='\strut\newline\noindent Sequence/page '.$urlp.'\strut\newline\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}\newline\noindent ';
                   1366: 
                   1367: 	    # IF sequence, recurse:
                   1368: 	    
                   1369: 	    if ($urlp =~ /\.sequence$/) {
                   1370: 		my $sequence_url = $urlp;
                   1371: 		my $domain       = $env{'user.domain'};	# Constr. space only on local
                   1372: 		my $user         = $env{'user.name'};
                   1373: 
                   1374: 		$sequence_url    =~ s/^\/res\/$domain/\/home/;
                   1375: 		$sequence_url    =~ s/^(\/home\/$user)/$1\/public_html/;
                   1376: #		$sequence_url    =~ s|\/~([^\/]+)\/|\/home\/$1\/public_html\/|;
                   1377: 		$result .= &print_construction_sequence($sequence_url, 
                   1378: 							$helper, %form, 
                   1379: 							$LaTeXwidth);
                   1380: 	    }
                   1381: 	}  
                   1382:     }
                   1383:     if ($helper->{VARS}->{'construction'} eq '1') {$result=~s/(\\begin{document})/$1 \\fbox\{RANDOM SEED IS $rndseed\} /;}
                   1384:     return $result;
                   1385: }
                   1386: 
1.177     sakharuk 1387: sub output_data {
1.184     sakharuk 1388:     my ($r,$helper,$rparmhash) = @_;
                   1389:     my %parmhash = %$rparmhash;
1.515     foxr     1390:     $ssi_error = 0;		# This will be set nonzero by failing ssi's.
1.459     foxr     1391:     $resources_printed = '';
1.499     foxr     1392:     my $do_postprocessing = 1;
1.433     albertel 1393:     my $js = <<ENDPART;
                   1394: <script type="text/javascript">
1.264     sakharuk 1395:     var editbrowser;
                   1396:     function openbrowser(formname,elementname,only,omit) {
                   1397:         var url = '/res/?';
                   1398:         if (editbrowser == null) {
                   1399:             url += 'launch=1&';
                   1400:         }
                   1401:         url += 'catalogmode=interactive&';
                   1402:         url += 'mode=parmset&';
                   1403:         url += 'form=' + formname + '&';
                   1404:         if (only != null) {
                   1405:             url += 'only=' + only + '&';
                   1406:         } 
                   1407:         if (omit != null) {
                   1408:             url += 'omit=' + omit + '&';
                   1409:         }
                   1410:         url += 'element=' + elementname + '';
                   1411:         var title = 'Browser';
                   1412:         var options = 'scrollbars=1,resizable=1,menubar=0';
                   1413:         options += ',width=700,height=600';
                   1414:         editbrowser = open(url,title,options,'1');
                   1415:         editbrowser.focus();
                   1416:     }
                   1417: </script>
1.140     sakharuk 1418: ENDPART
                   1419: 
1.512     foxr     1420: 
                   1421: 
1.433     albertel 1422:     my $start_page  = &Apache::loncommon::start_page('Preparing Printout',$js);
                   1423:     my $msg = &mt('Please stand by while processing your print request, this may take some time ...');
1.363     foxr     1424: 
1.433     albertel 1425:     $r->print($start_page."\n<p>\n$msg\n</p>\n");
1.372     foxr     1426: 
1.363     foxr     1427:     # fetch the pagebreaks and store them in the course environment
                   1428:     # The page breaks will be pulled into the hash %page_breaks which is
                   1429:     # indexed by symb and contains 1's for each break.
                   1430: 
1.373     albertel 1431:     $env{'form.pagebreaks'}  = $helper->{'VARS'}->{'FINISHPAGE'};
                   1432:     $env{'form.lastprinttype'} = $helper->{'VARS'}->{'PRINT_TYPE'}; 
1.363     foxr     1433:     &Apache::loncommon::store_course_settings('print',
1.366     foxr     1434: 					      {'pagebreaks'    => 'scalar',
                   1435: 					       'lastprinttype' => 'scalar'});
1.363     foxr     1436: 
1.364     albertel 1437:     my %page_breaks  = &get_page_breaks($helper);
1.363     foxr     1438: 
1.140     sakharuk 1439:     my $format_from_helper = $helper->{'VARS'}->{'FORMAT'};
                   1440:     my ($result,$selectionmade) = ('','');
                   1441:     my $number_of_columns = 1; #used only for pages to determine the width of the cell
                   1442:     my @temporary_array=split /\|/,$format_from_helper;
                   1443:     my ($laystyle,$numberofcolumns,$papersize)=@temporary_array;
                   1444:     if ($laystyle eq 'L') {
                   1445: 	$laystyle='album';
                   1446:     } else {
                   1447: 	$laystyle='book';
                   1448:     }
1.177     sakharuk 1449:     my ($textwidth,$textheight,$oddoffset,$evenoffset) = &page_format($papersize,$laystyle,$numberofcolumns);
1.373     albertel 1450:     my $assignment =  $env{'form.assignment'};
1.275     sakharuk 1451:     my $LaTeXwidth=&recalcto_mm($textwidth); 
1.272     sakharuk 1452:     my @print_array=();
1.274     sakharuk 1453:     my @student_names=();
1.360     albertel 1454: 
1.512     foxr     1455:      
1.360     albertel 1456:     #  Common settings for the %form has:
                   1457:     # In some cases these settings get overriddent by specific cases, but the
                   1458:     # settings are common enough to make it worthwhile factoring them out
                   1459:     # here.
                   1460:     #
                   1461:     my %form;
                   1462:     $form{'grade_target'} = 'tex';
                   1463:     $form{'textwidth'}    = &get_textwidth($helper, $LaTeXwidth);
1.372     foxr     1464: 
                   1465:     # If form.showallfoils is set, then request all foils be shown:
                   1466:     # privilege will be enforced both by not allowing the 
                   1467:     # check box selecting this option to be presnt unless it's ok,
                   1468:     # and by lonresponse's priv. check.
                   1469:     # The if is here because lonresponse.pm only cares that
                   1470:     # showallfoils is defined, not what the value is.
                   1471: 
                   1472:     if ($helper->{'VARS'}->{'showallfoils'} eq "1") { 
                   1473: 	$form{'showallfoils'} = $helper->{'VARS'}->{'showallfoils'};
                   1474:     }
1.504     albertel 1475:     
                   1476:     if ($helper->{'VARS'}->{'style_file'}=~/\w/) {
1.520     raeburn  1477: 	&Apache::lonnet::appenv({'construct.style' =>
                   1478: 				$helper->{'VARS'}->{'style_file'}});
1.504     albertel 1479:     } elsif ($env{'construct.style'}) {
                   1480: 	&Apache::lonnet::delenv('construct\\.style');
                   1481:     }
                   1482: 
1.372     foxr     1483: 
1.140     sakharuk 1484:     if ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'current_document') {
1.143     sakharuk 1485:       #-- single document - problem, page, html, xml, ...
1.343     albertel 1486: 	my ($currentURL,$cleanURL);
1.375     foxr     1487: 
1.162     sakharuk 1488: 	if ($helper->{'VARS'}->{'construction'} ne '1') {
1.185     sakharuk 1489:             #prints published resource
1.153     sakharuk 1490: 	    $currentURL=$helper->{'VARS'}->{'postdata'};
1.343     albertel 1491: 	    $cleanURL=&Apache::lonenc::check_decrypt($currentURL);
1.143     sakharuk 1492: 	} else {
1.512     foxr     1493: 
1.185     sakharuk 1494:             #prints resource from the construction space
1.240     albertel 1495: 	    $currentURL='/'.$helper->{'VARS'}->{'filename'};
1.206     sakharuk 1496: 	    if ($currentURL=~/([^?]+)/) {$currentURL=$1;}
1.343     albertel 1497: 	    $cleanURL=$currentURL;
1.143     sakharuk 1498: 	}
1.140     sakharuk 1499: 	$selectionmade = 1;
1.413     albertel 1500: 	if ($cleanURL!~m|^/adm/|
                   1501: 	    && $cleanURL=~/\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)$/) {
1.169     albertel 1502: 	    my $rndseed=time;
1.242     sakharuk 1503: 	    my $texversion='';
                   1504: 	    if ($helper->{'VARS'}->{'ANSWER_TYPE'} ne 'only') {
                   1505: 		my %moreenv;
1.343     albertel 1506: 		$moreenv{'request.filename'}=$cleanURL;
1.290     sakharuk 1507:                 if ($helper->{'VARS'}->{'probstatus'} eq 'exam') {$form{'problemtype'}='exam';}
1.242     sakharuk 1508: 		$form{'problem_split'}=$parmhash{'problem_stream_switch'};
1.310     sakharuk 1509: 		$form{'suppress_tries'}=$parmhash{'suppress_tries'};
1.242     sakharuk 1510: 		$form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'};
1.309     sakharuk 1511: 		$form{'print_discussions'}=$helper->{'VARS'}->{'PRINT_DISCUSSIONS'};
1.511     foxr     1512: 		$form{'print_annotations'}=$helper->{'VARS'}->{'PRINT_ANNOTATIONS'};
                   1513: 		if (($helper->{'VARS'}->{'PRINT_DISCUSSIONS'} eq 'yes') ||
                   1514: 		    ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes')) {
                   1515: 		    $form{'problem_split'}='yes';
                   1516: 		}
1.242     sakharuk 1517: 		if ($helper->{'VARS'}->{'curseed'}) {
                   1518: 		    $rndseed=$helper->{'VARS'}->{'curseed'};
                   1519: 		}
                   1520: 		$form{'rndseed'}=$rndseed;
1.520     raeburn  1521: 		&Apache::lonnet::appenv(\%moreenv);
1.428     albertel 1522: 
                   1523: 		&Apache::lonxml::clear_problem_counter();
                   1524: 
1.375     foxr     1525: 		$resources_printed .= $currentURL.':';
1.515     foxr     1526: 		$texversion.=&ssi_with_retries($currentURL,$ssi_retry_count, %form);
1.428     albertel 1527: 
1.511     foxr     1528: 		#  Add annotations if required:
                   1529: 	    
1.428     albertel 1530: 		&Apache::lonxml::clear_problem_counter();
                   1531: 
1.242     sakharuk 1532: 		&Apache::lonnet::delenv('request.filename');
1.230     albertel 1533: 	    }
1.423     foxr     1534: 	    # current document with answers.. no need to encap in minipage
                   1535: 	    #  since there's only one answer.
                   1536: 
1.242     sakharuk 1537: 	    if(($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') ||
                   1538: 	       ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) {
1.353     foxr     1539: 		$form{'problem_split'}=$parmhash{'problem_stream_switch'};
1.166     albertel 1540: 		$form{'grade_target'}='answer';
1.167     albertel 1541: 		$form{'answer_output_mode'}='tex';
1.169     albertel 1542: 		$form{'rndseed'}=$rndseed;
1.401     albertel 1543:                 if ($helper->{'VARS'}->{'probstatus'} eq 'exam') {
                   1544: 		    $form{'problemtype'}='exam';
                   1545: 		}
1.375     foxr     1546: 		$resources_printed .= $currentURL.':';
1.515     foxr     1547: 		my $answer=&ssi_with_retries($currentURL,$ssi_retry_count, %form);
1.511     foxr     1548: 		
                   1549: 
1.242     sakharuk 1550: 		if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') {
                   1551: 		    $texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
                   1552: 		} else {
                   1553: 		    $texversion=&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'});
1.245     sakharuk 1554: 		    if ($helper->{'VARS'}->{'construction'} ne '1') {
1.477     albertel 1555: 			my $title = &Apache::lonnet::gettitle($helper->{'VARS'}->{'symb'});
                   1556: 			$title = &Apache::lonxml::latex_special_symbols($title);
                   1557: 			$texversion.='\vskip 0 mm \noindent\textbf{'.$title.'}\vskip 0 mm ';
1.343     albertel 1558: 			$texversion.=&path_to_problem($cleanURL,$LaTeXwidth);
1.245     sakharuk 1559: 		    } else {
                   1560: 			$texversion.='\vskip 0 mm \noindent\textbf{Prints from construction space - there is no title.}\vskip 0 mm ';
1.343     albertel 1561: 			my $URLpath=$cleanURL;
1.245     sakharuk 1562: 			$URLpath=~s/~([^\/]+)/public_html\/$1\/$1/;
1.504     albertel 1563: 			$texversion.=&path_to_problem($URLpath,$LaTeXwidth);
1.245     sakharuk 1564: 		    }
1.242     sakharuk 1565: 		    $texversion.='\vskip 1 mm '.$answer.'\end{document}';
                   1566: 		}
1.511     foxr     1567: 
                   1568: 
                   1569: 		
                   1570: 
                   1571: 	    }
                   1572: 	    # Print annotations.
                   1573: 
                   1574: 
                   1575: 	    if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
                   1576: 		my $annotation .= &annotate($currentURL);
                   1577: 		$texversion =~ s/(\\keephidden{ENDOFPROBLEM})/$annotation$1/;
1.163     sakharuk 1578: 	    }
1.511     foxr     1579: 
                   1580: 
1.214     sakharuk 1581: 	    if ($helper->{'VARS'}->{'TABLE_INDEX'} eq 'yes') {
1.215     sakharuk 1582: 		$texversion=&IndexCreation($texversion,$currentURL);
1.214     sakharuk 1583: 	    }
1.219     sakharuk 1584: 	    if ($helper->{'VARS'}->{'CONSTR_RESOURSE_URL'} eq 'yes') {
                   1585: 		$texversion=~s/(\\addcontentsline\{toc\}\{subsection\}\{[^\}]*\})/$1 URL: \\verb|$currentURL| \\strut\\\\\\strut /;
                   1586: 
                   1587: 	    }
1.162     sakharuk 1588: 	    $result .= $texversion;
                   1589: 	    if ($currentURL=~m/\.page\s*$/) {
                   1590: 		($result,$number_of_columns) = &page_cleanup($result);
                   1591: 	    }
1.413     albertel 1592:         } elsif ($cleanURL!~m|^/adm/|
                   1593: 		 && $currentURL=~/\.sequence$/ && $helper->{'VARS'}->{'construction'} eq '1') {
1.227     sakharuk 1594:             #printing content of sequence from the construction space	
                   1595: 	    $currentURL=~s|\/~([^\/]+)\/|\/home\/$1\/public_html\/|;
1.459     foxr     1596: 	    $result .= &print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'});
                   1597: 	    $result .= &print_construction_sequence($currentURL, $helper, %form,
                   1598: 						    $LaTeXwidth);
                   1599: 	    $result .= '\end{document}';  
                   1600: 	    if (!($result =~ /\\begin\{document\}/)) {
                   1601: 		$result = &print_latex_header() . $result;
1.227     sakharuk 1602: 	    }
1.459     foxr     1603: 	    # End construction space sequence.
1.456     raeburn  1604: 	} elsif ($cleanURL=~/\/(smppg|syllabus|aboutme|bulletinboard)$/) { 
1.258     sakharuk 1605: 		$form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'};
1.298     sakharuk 1606: 		if ($currentURL=~/\/syllabus$/) {$currentURL=~s/\/res//;}
1.375     foxr     1607: 		$resources_printed .= $currentURL.':';
1.515     foxr     1608: 		my $texversion=&ssi_with_retries($currentURL, $ssi_retry_count, %form);
1.511     foxr     1609: 		if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
                   1610: 		    my $annotation = &annotate($currentURL);
                   1611: 		    $texversion    =~ s/(\\end{document})/$annotation$1/;
                   1612: 		}
1.258     sakharuk 1613: 		$result .= $texversion;
1.498     foxr     1614: 	} elsif ($cleanURL =~/.tex$/) {
                   1615: 	    # For this sort of print of a single LaTeX file,
                   1616: 	    # We can just print the LaTeX file as it is uninterpreted in any way:
                   1617: 	    #
                   1618: 
                   1619: 	    $result = &fetch_raw_resource($currentURL);
1.511     foxr     1620: 	    if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
                   1621: 		my $annotation = &annotate($currentURL);
                   1622: 		$result =~ s/(\\end{document})/$annotation$1/;
                   1623: 	    }
                   1624: 
1.499     foxr     1625: 	    $do_postprocessing = 0; # Don't massage the result.
1.498     foxr     1626: 
1.162     sakharuk 1627: 	} else {
1.414     albertel 1628: 	    $result.=&unsupported($currentURL,$helper->{'VARS'}->{'LATEX_TYPE'},
                   1629: 				  $helper->{'VARS'}->{'symb'});
1.162     sakharuk 1630: 	}
1.354     foxr     1631:     } elsif (($helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_problems')       or
1.142     sakharuk 1632:              ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_problems_pages') or
1.354     foxr     1633:              ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'all_problems')       or
                   1634: 	     ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'all_resources')      or # BUGBUG
1.252     sakharuk 1635: 	     ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'select_sequences')) { 
1.511     foxr     1636: 
                   1637: 
1.141     sakharuk 1638:         #-- produce an output string
1.296     sakharuk 1639: 	if ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_problems') {
                   1640: 	    $selectionmade = 2;
                   1641: 	} elsif ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'map_problems_pages') {
                   1642: 	    $selectionmade = 3;
                   1643: 	} elsif ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'all_problems') {
                   1644: 	    $selectionmade = 4;
1.354     foxr     1645: 	} elsif ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'all_resources') {  #BUGBUG
                   1646: 	    $selectionmade = 4;
1.296     sakharuk 1647: 	} elsif ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'select_sequences') {
                   1648: 	    $selectionmade = 7;
                   1649: 	}
1.193     sakharuk 1650: 	$form{'problem_split'}=$parmhash{'problem_stream_switch'};
1.310     sakharuk 1651: 	$form{'suppress_tries'}=$parmhash{'suppress_tries'};
1.203     sakharuk 1652: 	$form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'};
1.309     sakharuk 1653: 	$form{'print_discussions'}=$helper->{'VARS'}->{'PRINT_DISCUSSIONS'};
1.511     foxr     1654: 	$form{'print_annotations'} = $helper->{'VARS'}->{'PRINT_ANNOTATIONS'};
                   1655: 	if (($helper->{'VARS'}->{'PRINT_DISCUSSIONS'} eq 'yes')   ||
                   1656: 	    ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') ) {
                   1657: 	    $form{'problem_split'}='yes';
                   1658: 	}
1.141     sakharuk 1659: 	my $flag_latex_header_remove = 'NO';
                   1660: 	my $flag_page_in_sequence = 'NO';
                   1661: 	my @master_seq=split /\|\|\|/, $helper->{'VARS'}->{'RESOURCES'};
1.193     sakharuk 1662: 	my $prevassignment='';
1.428     albertel 1663: 
                   1664: 	&Apache::lonxml::clear_problem_counter();
                   1665: 
1.416     foxr     1666: 	my $pbreakresources = keys %page_breaks;
1.141     sakharuk 1667: 	for (my $i=0;$i<=$#master_seq;$i++) {
1.350     foxr     1668: 
1.521     foxr     1669: 	    &Apache::lonenc::reset_enc();
                   1670: 
                   1671: 
1.350     foxr     1672: 	    # Note due to document structure, not allowed to put \newpage
                   1673: 	    # prior to the first resource
                   1674: 
1.351     foxr     1675: 	    if (defined $page_breaks{$master_seq[$i]}) {
1.350     foxr     1676: 		if($i != 0) {
                   1677: 		    $result.="\\newpage\n";
                   1678: 		}
                   1679: 	    }
1.521     foxr     1680: 	    my ($sequence,$middle_thingy,$urlp)=&Apache::lonnet::decode_symb($master_seq[$i]);
1.237     albertel 1681: 	    $urlp=&Apache::lonnet::clutter($urlp);
1.166     albertel 1682: 	    $form{'symb'}=$master_seq[$i];
1.407     albertel 1683: 
1.521     foxr     1684: 
1.407     albertel 1685: 	    my $assignment=&Apache::lonxml::latex_special_symbols(&Apache::lonnet::gettitle($sequence),'header'); #title of the assignment which contains this problem
1.521     foxr     1686: 
1.267     sakharuk 1687: 	    if ($selectionmade==7) {$helper->{VARS}->{'assignment'}=$assignment;}
1.247     sakharuk 1688: 	    if ($i==0) {$prevassignment=$assignment;}
1.297     sakharuk 1689: 	    my $texversion='';
1.413     albertel 1690: 	    if ($urlp!~m|^/adm/|
                   1691: 		&& $urlp=~/\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)$/) {
1.375     foxr     1692: 		$resources_printed .= $urlp.':';
1.428     albertel 1693: 		&Apache::lonxml::remember_problem_counter();
1.515     foxr     1694: 		$texversion.=&ssi_with_retries($urlp, $ssi_retry_count, %form);
1.296     sakharuk 1695: 		if ($urlp=~/\.page$/) {
                   1696: 		    ($texversion,my $number_of_columns_page) = &page_cleanup($texversion);
                   1697: 		    if ($number_of_columns_page > $number_of_columns) {$number_of_columns=$number_of_columns_page;} 
                   1698: 		    $texversion =~ s/\\end{document}\d*/\\end{document}/;
                   1699: 		    $flag_page_in_sequence = 'YES';
                   1700: 		} 
1.428     albertel 1701: 
1.296     sakharuk 1702: 		if(($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') ||
                   1703: 		   ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) {
1.380     foxr     1704: 		    #  Don't permanently pervert the %form hash
                   1705: 		    my %answerform = %form;
                   1706: 		    $answerform{'grade_target'}='answer';
                   1707: 		    $answerform{'answer_output_mode'}='tex';
1.375     foxr     1708: 		    $resources_printed .= $urlp.':';
1.428     albertel 1709: 
                   1710: 		    &Apache::lonxml::restore_problem_counter();
1.515     foxr     1711: 		    my $answer=&ssi_with_retries($urlp, $ssi_retry_count, %answerform);
1.428     albertel 1712: 
1.296     sakharuk 1713: 		    if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') {
                   1714: 			$texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
1.249     sakharuk 1715: 		    } else {
1.307     sakharuk 1716: 			if ($urlp=~/\.(problem|exam|quiz|assess|survey|form|library)$/) {
1.296     sakharuk 1717: 			    $texversion=&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'});
1.477     albertel 1718: 			    my $title = &Apache::lonnet::gettitle($master_seq[$i]);
                   1719: 			    $title = &Apache::lonxml::latex_special_symbols($title);
                   1720: 			    my $body ='\vskip 0 mm \noindent\textbf{'.$title.'}\vskip 0 mm ';
1.423     foxr     1721: 			    $body   .= &path_to_problem ($urlp,$LaTeXwidth);
                   1722: 			    $body   .='\vskip 1 mm '.$answer;
                   1723: 			    $body    = &encapsulate_minipage($body);
                   1724: 			    $texversion .= $body;
1.296     sakharuk 1725: 			} else {
                   1726: 			    $texversion='';
                   1727: 			}
1.249     sakharuk 1728: 		    }
1.511     foxr     1729: 
1.246     sakharuk 1730: 		}
1.511     foxr     1731: 		if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
                   1732: 		    my $annotation .= &annotate($urlp);
                   1733: 		    $texversion =~ s/(\\keephidden{ENDOFPROBLEM})/$annotation$1/;
                   1734: 		}
                   1735: 
1.296     sakharuk 1736: 		if ($flag_latex_header_remove ne 'NO') {
                   1737: 		    $texversion = &latex_header_footer_remove($texversion);
                   1738: 		} else {
                   1739: 		    $texversion =~ s/\\end{document}//;
                   1740: 		}
                   1741: 		if ($helper->{'VARS'}->{'TABLE_INDEX'} eq 'yes') {
                   1742: 		    $texversion=&IndexCreation($texversion,$urlp);
                   1743: 		}
                   1744: 		if (($selectionmade == 4) and ($assignment ne $prevassignment)) {
                   1745: 		    my $name = &get_name();
                   1746: 		    my $courseidinfo = &get_course();
                   1747: 		    if (defined($courseidinfo)) { $courseidinfo=' - '.$courseidinfo }
                   1748: 		    $prevassignment=$assignment;
1.455     albertel 1749: 		    my $header_text = $parmhash{'print_header_format'};
1.486     foxr     1750: 		    $header_text    = &format_page_header($textwidth, $header_text,
1.455     albertel 1751: 							  $assignment, 
                   1752: 							  $courseidinfo, 
                   1753: 							  $name);
1.417     foxr     1754: 		    if ($numberofcolumns eq '1') {
1.455     albertel 1755: 			$result .='\newpage \noindent\parbox{\minipagewidth}{\noindent\\lhead{'.$header_text.'}} \vskip 5 mm ';
1.416     foxr     1756: 		    } else {
1.455     albertel 1757: 			$result .='\newpage \noindent\parbox{\minipagewidth}{\noindent\\fancyhead[LO]{'.$header_text.'}} \vskip 5 mm ';
1.416     foxr     1758: 		    }			
1.296     sakharuk 1759: 		}
                   1760: 		$result .= $texversion;
                   1761: 		$flag_latex_header_remove = 'YES';   
1.456     raeburn  1762: 	    } elsif ($urlp=~/\/(smppg|syllabus|aboutme|bulletinboard)$/) { 
1.301     sakharuk 1763: 		$form{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'};
                   1764: 		if ($urlp=~/\/syllabus$/) {$urlp=~s/\/res//;}
1.375     foxr     1765: 		$resources_printed .= $urlp.':';
1.515     foxr     1766: 		my $texversion=&ssi_with_retries($urlp, $ssi_retry_count, %form);
1.511     foxr     1767: 		if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
                   1768: 		    my $annotation = &annotate($urlp);
                   1769: 		    $texversion =~ s/(\\end{document)/$annotation$1/;
                   1770: 		}
                   1771: 
1.301     sakharuk 1772: 		if ($flag_latex_header_remove ne 'NO') {
                   1773: 		    $texversion = &latex_header_footer_remove($texversion);
                   1774: 		} else {
                   1775: 		    $texversion =~ s/\\end{document}/\\vskip 0\.5mm\\noindent\\makebox\[\\textwidth\/\$number_of_columns\]\[b\]\{\\hrulefill\}/;
                   1776: 		}
                   1777: 		$result .= $texversion;
                   1778: 		$flag_latex_header_remove = 'YES'; 
1.141     sakharuk 1779: 	    } else {
1.414     albertel 1780: 		$texversion=&unsupported($urlp,$helper->{'VARS'}->{'LATEX_TYPE'},
                   1781: 					 $master_seq[$i]);
1.297     sakharuk 1782: 		if ($flag_latex_header_remove ne 'NO') {
                   1783: 		    $texversion = &latex_header_footer_remove($texversion);
                   1784: 		} else {
                   1785: 		    $texversion =~ s/\\end{document}//;
                   1786: 		}
                   1787: 		$result .= $texversion;
                   1788: 		$flag_latex_header_remove = 'YES';   
1.296     sakharuk 1789: 	    }	    
1.331     albertel 1790: 	    if (&Apache::loncommon::connection_aborted($r)) { last; }
1.141     sakharuk 1791: 	}
1.428     albertel 1792: 	&Apache::lonxml::clear_problem_counter();
1.344     foxr     1793: 	if ($flag_page_in_sequence eq 'YES') {
                   1794: 	    $result =~ s/\\usepackage{calc}/\\usepackage{calc}\\usepackage{longtable}/;
                   1795: 	}	
1.141     sakharuk 1796: 	$result .= '\end{document}';
1.284     albertel 1797:      } elsif (($helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_for_students') ||
                   1798: 	      ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'resources_for_students')){
1.353     foxr     1799: 
                   1800: 
1.150     sakharuk 1801:      #-- prints assignments for whole class or for selected students  
1.284     albertel 1802: 	 my $type;
1.254     sakharuk 1803: 	 if ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_for_students') {
                   1804: 	     $selectionmade=5;
1.284     albertel 1805: 	     $type='problems';
1.254     sakharuk 1806: 	 } elsif ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'resources_for_students') {
                   1807: 	     $selectionmade=8;
1.284     albertel 1808: 	     $type='resources';
1.254     sakharuk 1809: 	 }
1.150     sakharuk 1810: 	 my @students=split /\|\|\|/, $helper->{'VARS'}->{'STUDENTS'};
1.341     foxr     1811: 	 #   The normal sort order is by section then by students within the
                   1812: 	 #   section. If the helper var student_sort is 1, then the user has elected
                   1813: 	 #   to override this and output the students by name.
                   1814: 	 #    Each element of the students array is of the form:
                   1815: 	 #       username:domain:section:last, first:status
                   1816: 	 #    
1.429     foxr     1817: 	 #  Note that student sort is not compatible with printing 
                   1818: 	 #  1 section per pdf...so that setting overrides.
1.341     foxr     1819: 	 #   
1.429     foxr     1820: 	 if (($helper->{'VARS'}->{'student_sort'}    eq 1)  && 
                   1821: 	     ($helper->{'VARS'}->{'SPLIT_PDFS'} ne "sections")) {
1.341     foxr     1822: 	     @students = sort compare_names  @students;
                   1823: 	 }
1.429     foxr     1824: 	 &adjust_number_to_print($helper);
                   1825: 
1.278     albertel 1826:          if ($helper->{'VARS'}->{'NUMBER_TO_PRINT'} eq '0' ||
                   1827: 	     $helper->{'VARS'}->{'NUMBER_TO_PRINT'} eq 'all' ) {
                   1828: 	     $helper->{'VARS'}->{'NUMBER_TO_PRINT'}=$#students+1;
                   1829: 	 }
1.429     foxr     1830: 	 # If we are splitting on section boundaries, we need 
                   1831: 	 # to remember that in split_on_sections and 
                   1832: 	 # print all of the students in the list.
                   1833: 	 #
                   1834: 	 my $split_on_sections = 0;
                   1835: 	 if ($helper->{'VARS'}->{'NUMBER_TO_PRINT'} eq 'section') {
                   1836: 	     $split_on_sections = 1;
                   1837: 	     $helper->{'VARS'}->{'NUMBER_TO_PRINT'} = $#students+1;
                   1838: 	 }
1.150     sakharuk 1839: 	 my @master_seq=split /\|\|\|/, $helper->{'VARS'}->{'RESOURCES'};
1.350     foxr     1840: 
1.150     sakharuk 1841: 	 #loop over students
                   1842: 	 my $flag_latex_header_remove = 'NO'; 
                   1843: 	 my %moreenv;
1.330     sakharuk 1844:          $moreenv{'instructor_comments'}='hide';
1.285     albertel 1845: 	 $moreenv{'textwidth'}=&get_textwidth($helper,$LaTeXwidth);
1.309     sakharuk 1846: 	 $moreenv{'print_discussions'}=$helper->{'VARS'}->{'PRINT_DISCUSSIONS'};
1.511     foxr     1847: 	 $moreenv{'print_annotations'} = $helper->{'VARS'}->{'PRINT_ANNOTATIONS'};
1.353     foxr     1848: 	 $moreenv{'problem_split'}    = $parmhash{'problem_stream_switch'};
1.369     foxr     1849: 	 $moreenv{'suppress_tries'}   = $parmhash{'suppress_tries'};
1.511     foxr     1850: 	 if (($helper->{'VARS'}->{'PRINT_DISCUSSIONS'} eq 'yes')  ||
                   1851: 	     ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes')) {
                   1852: 	     $moreenv{'problem_split'}='yes';
                   1853: 	 }
1.318     albertel 1854: 	 my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,'Print Status','Class Print Status',$#students+1,'inline','75');
1.272     sakharuk 1855: 	 my $student_counter=-1;
1.429     foxr     1856: 	 my $i = 0;
1.430     albertel 1857: 	 my $last_section = (split(/:/,$students[0]))[2];
1.150     sakharuk 1858: 	 foreach my $person (@students) {
1.350     foxr     1859: 
1.373     albertel 1860:              my $duefile="/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout.due";
1.311     sakharuk 1861: 	     if (-e $duefile) {
                   1862: 		 my $temp_file = Apache::File->new('>>'.$duefile);
                   1863: 		 print $temp_file "1969\n";
                   1864: 	     }
1.272     sakharuk 1865: 	     $student_counter++;
1.429     foxr     1866: 	     if ($split_on_sections) {
1.430     albertel 1867: 		 my $this_section = (split(/:/,$person))[2];
1.429     foxr     1868: 		 if ($this_section ne $last_section) {
                   1869: 		     $i++;
                   1870: 		     $last_section = $this_section;
                   1871: 		 }
                   1872: 	     } else {
                   1873: 		 $i=int($student_counter/$helper->{'VARS'}{'NUMBER_TO_PRINT'});
                   1874: 	     }
1.375     foxr     1875: 	     my ($output,$fullname, $printed)=&print_resources($r,$helper,
1.353     foxr     1876: 						     $person,$type,
                   1877: 						     \%moreenv,\@master_seq,
1.360     albertel 1878: 						     $flag_latex_header_remove,
1.422     albertel 1879: 						     $LaTeXwidth);
1.375     foxr     1880: 	     $resources_printed .= ":";
1.284     albertel 1881: 	     $print_array[$i].=$output;
                   1882: 	     $student_names[$i].=$person.':'.$fullname.'_END_';
                   1883: 	     &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,&mt('last student').' '.$fullname);
                   1884: 	     $flag_latex_header_remove = 'YES';
1.331     albertel 1885: 	     if (&Apache::loncommon::connection_aborted($r)) { last; }
1.284     albertel 1886: 	 }
                   1887: 	 &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
                   1888: 	 $result .= $print_array[0].'  \end{document}';
                   1889:      } elsif (($helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_for_anon')     ||
                   1890: 	      ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'resources_for_anon')  ) { 
1.373     albertel 1891: 	 my $cdom =$env{'course.'.$env{'request.course.id'}.'.domain'};
                   1892: 	 my $cnum =$env{'course.'.$env{'request.course.id'}.'.num'};
1.288     albertel 1893: 	 my $num_todo=$helper->{'VARS'}->{'NUMBER_TO_PRINT_TOTAL'};
                   1894: 	 my $code_name=$helper->{'VARS'}->{'ANON_CODE_STORAGE_NAME'};
1.292     albertel 1895: 	 my $old_name=$helper->{'VARS'}->{'REUSE_OLD_CODES'};
1.385     foxr     1896: 	 my $single_code = $helper->{'VARS'}->{'SINGLE_CODE'};
1.388     foxr     1897: 	 my $selected_code = $helper->{'VARS'}->{'CODE_SELECTED_FROM_LIST'};
                   1898: 
1.381     albertel 1899: 	 my $code_option=$helper->{'VARS'}->{'CODE_OPTION'};
                   1900: 	 open(FH,$Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab');
                   1901: 	 my ($code_type,$code_length)=('letter',6);
                   1902: 	 foreach my $line (<FH>) {
                   1903: 	     my ($name,$type,$length) = (split(/:/,$line))[0,2,4];
                   1904: 	     if ($name eq $code_option) {
                   1905: 		 $code_length=$length;
                   1906: 		 if ($type eq 'number') { $code_type = 'number'; }
                   1907: 	     }
                   1908: 	 }
1.288     albertel 1909: 	 my %moreenv = ('textwidth' => &get_textwidth($helper,$LaTeXwidth));
1.353     foxr     1910: 	 $moreenv{'problem_split'}    = $parmhash{'problem_stream_switch'};
1.420     albertel 1911:          $moreenv{'instructor_comments'}='hide';
1.288     albertel 1912: 	 my $seed=time+($$<<16)+($$);
1.292     albertel 1913: 	 my @allcodes;
                   1914: 	 if ($old_name) {
1.381     albertel 1915: 	     my %result=&Apache::lonnet::get('CODEs',
                   1916: 					     [$old_name,"type\0$old_name"],
                   1917: 					     $cdom,$cnum);
                   1918: 	     $code_type=$result{"type\0$old_name"};
1.292     albertel 1919: 	     @allcodes=split(',',$result{$old_name});
1.336     albertel 1920: 	     $num_todo=scalar(@allcodes);
1.389     foxr     1921: 	 } elsif ($selected_code) { # Selection value is always numeric.
1.388     foxr     1922: 	     $num_todo = 1;
                   1923: 	     @allcodes = ($selected_code);
1.385     foxr     1924: 	 } elsif ($single_code) {
                   1925: 
1.387     foxr     1926: 	     $num_todo    = 1;	# Unconditionally one code to do.
1.385     foxr     1927: 	     # If an alpha code have to convert to numbers so it can be
                   1928: 	     # converted back to letters again :-)
                   1929: 	     #
                   1930: 	     if ($code_type ne 'number') {
                   1931: 		 $single_code = &letters_to_num($single_code);
                   1932: 	     }
                   1933: 	     @allcodes = ($single_code);
1.292     albertel 1934: 	 } else {
                   1935: 	     my %allcodes;
1.299     albertel 1936: 	     srand($seed);
1.292     albertel 1937: 	     for (my $i=0;$i<$num_todo;$i++) {
1.381     albertel 1938: 		 $moreenv{'CODE'}=&get_CODE(\%allcodes,$i,$seed,$code_length,
                   1939: 					    $code_type);
1.292     albertel 1940: 	     }
                   1941: 	     if ($code_name) {
                   1942: 		 &Apache::lonnet::put('CODEs',
1.381     albertel 1943: 				      {
                   1944: 					$code_name =>join(',',keys(%allcodes)),
                   1945: 					"type\0$code_name" => $code_type
                   1946: 				      },
1.292     albertel 1947: 				      $cdom,$cnum);
                   1948: 	     }
                   1949: 	     @allcodes=keys(%allcodes);
                   1950: 	 }
1.336     albertel 1951: 	 my @master_seq=split /\|\|\|/, $helper->{'VARS'}->{'RESOURCES'};
                   1952: 	 my ($type) = split(/_/,$helper->{'VARS'}->{'PRINT_TYPE'});
1.452     albertel 1953: 	 &adjust_number_to_print($helper);
1.336     albertel 1954: 	 my $number_per_page=$helper->{'VARS'}->{'NUMBER_TO_PRINT'};
                   1955: 	 if ($number_per_page eq '0' || $number_per_page eq 'all') {
                   1956: 	     $number_per_page=$num_todo;
                   1957: 	 }
                   1958: 	 my $flag_latex_header_remove = 'NO'; 
                   1959: 	 my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin($r,'Print Status','Class Print Status',$num_todo,'inline','75');
1.295     albertel 1960: 	 my $count=0;
1.292     albertel 1961: 	 foreach my $code (sort(@allcodes)) {
1.295     albertel 1962: 	     my $file_num=int($count/$number_per_page);
1.381     albertel 1963: 	     if ($code_type eq 'number') { 
                   1964: 		 $moreenv{'CODE'}=$code;
                   1965: 	     } else {
                   1966: 		 $moreenv{'CODE'}=&num_to_letters($code);
                   1967: 	     }
1.375     foxr     1968: 	     my ($output,$fullname, $printed)=
1.288     albertel 1969: 		 &print_resources($r,$helper,'anonymous',$type,\%moreenv,
1.360     albertel 1970: 				  \@master_seq,$flag_latex_header_remove,
                   1971: 				  $LaTeXwidth);
1.375     foxr     1972: 	     $resources_printed .= ":";
1.295     albertel 1973: 	     $print_array[$file_num].=$output;
1.288     albertel 1974: 	     &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,
                   1975: 				       &mt('last assignment').' '.$fullname);
                   1976: 	     $flag_latex_header_remove = 'YES';
1.295     albertel 1977: 	     $count++;
1.331     albertel 1978: 	     if (&Apache::loncommon::connection_aborted($r)) { last; }
1.288     albertel 1979: 	 }
                   1980: 	 &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
                   1981: 	 $result .= $print_array[0].'  \end{document}';
                   1982:      } elsif ($helper->{'VARS'}->{'PRINT_TYPE'} eq 'problems_from_directory') {      
1.151     sakharuk 1983:     #prints selected problems from the subdirectory 
                   1984: 	$selectionmade = 6;
                   1985:         my @list_of_files=split /\|\|\|/, $helper->{'VARS'}->{'FILES'};
1.154     sakharuk 1986: 	@list_of_files=sort @list_of_files;
1.175     sakharuk 1987: 	my $flag_latex_header_remove = 'NO'; 
                   1988: 	my $rndseed=time;
1.230     albertel 1989: 	if ($helper->{'VARS'}->{'curseed'}) {
                   1990: 	    $rndseed=$helper->{'VARS'}->{'curseed'};
                   1991: 	}
1.151     sakharuk 1992: 	for (my $i=0;$i<=$#list_of_files;$i++) {
1.521     foxr     1993: 
                   1994: 	    &Apache::lonenc::reset_enc();
                   1995: 
1.152     sakharuk 1996: 	    my $urlp = $list_of_files[$i];
1.253     sakharuk 1997: 	    $urlp=~s|//|/|;
1.152     sakharuk 1998: 	    if ($urlp=~/\//) {
1.353     foxr     1999: 		$form{'problem_split'}=$parmhash{'problem_stream_switch'};
1.175     sakharuk 2000: 		$form{'rndseed'}=$rndseed;
1.152     sakharuk 2001: 		if ($urlp =~ m|/home/([^/]+)/public_html|) {
                   2002: 		    $urlp =~ s|/home/([^/]*)/public_html|/~$1|;
                   2003: 		} else {
1.302     sakharuk 2004: 		    $urlp =~ s|^$Apache::lonnet::perlvar{'lonDocRoot'}||;
1.152     sakharuk 2005: 		}
1.375     foxr     2006: 		$resources_printed .= $urlp.':';
1.515     foxr     2007: 		my $texversion=&ssi_with_retries($urlp, $ssi_retry_count, %form);
1.251     sakharuk 2008: 		if(($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') ||
1.253     sakharuk 2009: 		   ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) {
1.380     foxr     2010: 		    #  Don't permanently pervert %form:
                   2011: 		    my %answerform = %form;
                   2012: 		    $answerform{'grade_target'}='answer';
                   2013: 		    $answerform{'answer_output_mode'}='tex';
                   2014: 		    $answerform{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'};
                   2015: 		    $answerform{'rndseed'}=$rndseed;
1.375     foxr     2016: 		    $resources_printed .= $urlp.':';
1.515     foxr     2017: 		    my $answer=&ssi_with_retries($urlp, $ssi_retry_count, %answerform);
1.251     sakharuk 2018: 		    if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') {
                   2019: 			$texversion=~s/(\\keephidden{ENDOFPROBLEM})/$answer$1/;
                   2020: 		    } else {
1.253     sakharuk 2021: 			$texversion=&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'});
                   2022: 			if ($helper->{'VARS'}->{'construction'} ne '1') {
                   2023: 			    $texversion.='\vskip 0 mm \noindent ';
                   2024: 			    $texversion.=&path_to_problem ($urlp,$LaTeXwidth);
                   2025: 			} else {
                   2026: 			    $texversion.='\vskip 0 mm \noindent\textbf{Prints from construction space - there is no title.}\vskip 0 mm ';
                   2027: 			    my $URLpath=$urlp;
                   2028: 			    $URLpath=~s/~([^\/]+)/public_html\/$1\/$1/;
                   2029: 			    $texversion.=&path_to_problem ($URLpath,$LaTeXwidth);
                   2030: 			}
                   2031: 			$texversion.='\vskip 1 mm '.$answer.'\end{document}';
1.251     sakharuk 2032: 		    }
1.174     sakharuk 2033: 		}
1.515     foxr     2034:                 #this chunk is responsible for printing the path to problem
                   2035: 
1.253     sakharuk 2036: 		my $newurlp=$urlp;
                   2037: 		if ($newurlp=~/~/) {$newurlp=~s|\/~([^\/]+)\/|\/home\/$1\/public_html\/|;}
                   2038: 		$newurlp=&path_to_problem($newurlp,$LaTeXwidth);
1.242     sakharuk 2039: 		$texversion =~ s/(\\begin{minipage}{\\textwidth})/$1 $newurlp/;
1.152     sakharuk 2040: 		if ($flag_latex_header_remove ne 'NO') {
                   2041: 		    $texversion = &latex_header_footer_remove($texversion);
                   2042: 		} else {
                   2043: 		    $texversion =~ s/\\end{document}//;
1.216     sakharuk 2044: 		}
                   2045: 		if ($helper->{'VARS'}->{'TABLE_INDEX'} eq 'yes') {
                   2046: 		    $texversion=&IndexCreation($texversion,$urlp);
1.152     sakharuk 2047: 		}
1.219     sakharuk 2048: 		if ($helper->{'VARS'}->{'CONSTR_RESOURSE_URL'} eq 'yes') {
                   2049: 		    $texversion=~s/(\\addcontentsline\{toc\}\{subsection\}\{[^\}]*\})/$1 URL: \\verb|$urlp| \\strut\\\\\\strut /;
                   2050: 		    
                   2051: 		}
1.152     sakharuk 2052: 		$result .= $texversion;
                   2053: 	    }
                   2054: 	    $flag_latex_header_remove = 'YES';  
1.151     sakharuk 2055: 	}
1.175     sakharuk 2056: 	if ($helper->{VARS}->{'construction'} eq '1') {$result=~s/(\\typeout)/ RANDOM SEED IS $rndseed $1/;}
1.152     sakharuk 2057: 	$result .= '\end{document}';      	
1.140     sakharuk 2058:     }
                   2059: #-------------------------------------------------------- corrections for the different page formats
1.499     foxr     2060: 
                   2061:     # Only post process if that has not been turned off e.g. by a raw latex resource.
                   2062: 
                   2063:     if ($do_postprocessing) {
                   2064: 	$result = &page_format_transformation($papersize,$laystyle,$numberofcolumns,$helper->{'VARS'}->{'PRINT_TYPE'},$result,$helper->{VARS}->{'assignment'},$helper->{'VARS'}->{'TABLE_CONTENTS'},$helper->{'VARS'}->{'TABLE_INDEX'},$selectionmade);
                   2065: 	$result = &latex_corrections($number_of_columns,$result,$selectionmade,
                   2066: 				     $helper->{'VARS'}->{'ANSWER_TYPE'});
                   2067: 	#if ($numberofcolumns == 1) {
1.451     albertel 2068: 	$result =~ s/\\textwidth\s*=\s*-?\d*\.?\d*\s*(cm|mm|in)/\\textwidth= $helper->{'VARS'}->{'pagesize.width'} $helper->{'VARS'}->{'pagesize.widthunit'} /;
                   2069: 	$result =~ s/\\textheight\s*=?\s*-?\d*\.?\d*\s*(cm|mm|in)/\\textheight $helper->{'VARS'}->{'pagesize.height'} $helper->{'VARS'}->{'pagesize.heightunit'} /;
                   2070: 	$result =~ s/\\evensidemargin\s*=\s*-?\d*\.?\d*\s*(cm|mm|in)/\\evensidemargin= $helper->{'VARS'}->{'pagesize.lmargin'} $helper->{'VARS'}->{'pagesize.lmarginunit'} /;
                   2071: 	$result =~ s/\\oddsidemargin\s*=\s*-?\d*\.?\d*\s*(cm|mm|in)/\\oddsidemargin= $helper->{'VARS'}->{'pagesize.lmargin'} $helper->{'VARS'}->{'pagesize.lmarginunit'} /;
1.499     foxr     2072: 	#}
                   2073:     }
1.367     foxr     2074: 
1.515     foxr     2075:     # Set URLback if this is a construction space print so we can provide
                   2076:     # a link to the resource being edited.
                   2077:     #
1.274     sakharuk 2078: 
1.276     sakharuk 2079:     my $URLback=''; #link to original document
1.510     albertel 2080:     if ($helper->{'VARS'}->{'construction'} eq '1') {
1.276     sakharuk 2081: 	#prints resource from the construction space
                   2082: 	$URLback='/'.$helper->{'VARS'}->{'filename'};
1.279     albertel 2083: 	if ($URLback=~/([^?]+)/) {
                   2084: 	    $URLback=$1;
                   2085: 	    $URLback=~s|^/~|/priv/|;
                   2086: 	}
1.276     sakharuk 2087:     }
1.375     foxr     2088: 
1.515     foxr     2089: 
                   2090:     # If there's been an unrecoverable SSI error, report it to the user
                   2091:     # otherwise, we can write the tex file.
                   2092:     #
                   2093: 
                   2094:     if ($ssi_error) {
1.522   ! raeburn  2095: 
        !          2096:         my $helpurl = &Apache::loncommon::top_nav_help('Helpdesk');
1.515     foxr     2097: 	my $end_page = &Apache::loncommon::end_page();
1.522   ! raeburn  2098: 	$r->print('
1.515     foxr     2099: <br />
1.522   ! raeburn  2100: <h2>'.&mt('An unrecoverable error occured:').'</h2>
1.515     foxr     2101: <p>
1.522   ! raeburn  2102:   '.&mt('One of the resources ([_1]) you chose to print could not be rendered due to an unrecoverable error when communicating with a server:',$ssi_last_error_resource).' 
1.515     foxr     2103: <br />
1.522   ! raeburn  2104: '.$ssi_last_error.'
1.515     foxr     2105: </p>
1.522   ! raeburn  2106: <p>'.
        !          2107: &mt('It is recommended that you try printing again later, as this error may mean the server was just temporarily unavailable, or is down for maintenance.').'<br />'.
        !          2108: &mt('If the error persists, please contact the [_1] for assistance.',$helpurl).
        !          2109: '</p><p>'.
        !          2110: &mt('We apologize for the inconvenience.').
        !          2111: '</p>'.
        !          2112: $end_page);
1.515     foxr     2113:     } else {
                   2114: 
                   2115: #-- writing .tex file in prtspool 
                   2116: 	my $temp_file;
                   2117: 	my $identifier = &Apache::loncommon::get_cgi_id();
                   2118: 	my $filename = "/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout_$identifier.tex";
                   2119: 	if (!($#print_array>0)) { 
                   2120: 	    unless ($temp_file = Apache::File->new('>'.$filename)) {
                   2121: 		$r->log_error("Couldn't open $filename for output $!");
                   2122: 		return SERVER_ERROR; 
                   2123: 	    }
                   2124: 	    print $temp_file $result;
                   2125: 	    my $begin=index($result,'\begin{document}',0);
                   2126: 	    my $inc=substr($result,0,$begin+16);
                   2127: 	} else {
                   2128: 	    my $begin=index($result,'\begin{document}',0);
                   2129: 	    my $inc=substr($result,0,$begin+16);
                   2130: 	    for (my $i=0;$i<=$#print_array;$i++) {
                   2131: 		if ($i==0) {
                   2132: 		    $print_array[$i]=$result;
                   2133: 		} else {
                   2134: 		    $print_array[$i].='\end{document}';
                   2135: 		    $print_array[$i] = 
                   2136: 			&latex_corrections($number_of_columns,$print_array[$i],
                   2137: 					   $selectionmade, 
                   2138: 					   $helper->{'VARS'}->{'ANSWER_TYPE'});
                   2139: 		    
                   2140: 		    my $anobegin=index($print_array[$i],'\setcounter{page}',0);
                   2141: 		    substr($print_array[$i],0,$anobegin)='';
                   2142: 		    $print_array[$i]=$inc.$print_array[$i];
                   2143: 		}
                   2144: 		my $temp_file;
                   2145: 		my $newfilename=$filename;
                   2146: 		my $num=$i+1;
                   2147: 		$newfilename =~s/\.tex$//; 
                   2148: 		$newfilename=sprintf("%s_%03d.tex",$newfilename, $num);
                   2149: 		unless ($temp_file = Apache::File->new('>'.$newfilename)) {
                   2150: 		    $r->log_error("Couldn't open $newfilename for output $!");
                   2151: 		    return SERVER_ERROR; 
                   2152: 		}
                   2153: 		print $temp_file $print_array[$i];
                   2154: 	    }
                   2155: 	    
                   2156: 	}
                   2157: 	my $student_names='';
                   2158: 	if ($#print_array>0) {
                   2159: 	    for (my $i=0;$i<=$#print_array;$i++) {
                   2160: 		$student_names.=$student_names[$i].'_ENDPERSON_';
                   2161: 	    }
                   2162: 	} else {
                   2163: 	    if ($#student_names>-1) {
                   2164: 		$student_names=$student_names[0].'_ENDPERSON_';
                   2165: 	    } else {
                   2166: 		my $fullname = &get_name($env{'user.name'},$env{'user.domain'});
                   2167: 		$student_names=join(':',$env{'user.name'},$env{'user.domain'},
                   2168: 				    $env{'request.course.sec'},$fullname).
                   2169: 					'_ENDPERSON_'.'_END_';
                   2170: 	    }
                   2171: 	}
                   2172: 	
                   2173: 	# logic for now is too complex to trace if this has been defined
                   2174: 	#  yet.
                   2175: 	my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
                   2176: 	my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
1.520     raeburn  2177: 	&Apache::lonnet::appenv({'cgi.'.$identifier.'.file'   => $filename,
1.515     foxr     2178: 				'cgi.'.$identifier.'.layout'  => $laystyle,
                   2179: 				'cgi.'.$identifier.'.numcol'  => $numberofcolumns,
                   2180: 				'cgi.'.$identifier.'.paper'  => $papersize,
                   2181: 				'cgi.'.$identifier.'.selection' => $selectionmade,
                   2182: 				'cgi.'.$identifier.'.tableofcontents' => $helper->{'VARS'}->{'TABLE_CONTENTS'},
                   2183: 				'cgi.'.$identifier.'.tableofindex' => $helper->{'VARS'}->{'TABLE_INDEX'},
                   2184: 				'cgi.'.$identifier.'.role' => $perm{'pav'},
                   2185: 				'cgi.'.$identifier.'.numberoffiles' => $#print_array,
                   2186: 				'cgi.'.$identifier.'.studentnames' => $student_names,
1.520     raeburn  2187: 				'cgi.'.$identifier.'.backref' => $URLback,});
                   2188: 	&Apache::lonnet::appenv({"cgi.$identifier.user"    => $env{'user.name'},
1.515     foxr     2189: 				"cgi.$identifier.domain"  => $env{'user.domain'},
                   2190: 				"cgi.$identifier.courseid" => $cnum, 
                   2191: 				"cgi.$identifier.coursedom" => $cdom, 
1.520     raeburn  2192: 				"cgi.$identifier.resources" => $resources_printed});
1.515     foxr     2193: 	
                   2194: 	my $end_page = &Apache::loncommon::end_page();
                   2195: 	$r->print(<<FINALEND);
1.317     albertel 2196: <br />
1.288     albertel 2197: <meta http-equiv="Refresh" content="0; url=/cgi-bin/printout.pl?$identifier" />
1.317     albertel 2198: <a href="/cgi-bin/printout.pl?$identifier">Continue</a>
1.431     albertel 2199: $end_page
1.140     sakharuk 2200: FINALEND
1.515     foxr     2201:   }                                       # endif ssi errors.
1.140     sakharuk 2202: }
                   2203: 
1.288     albertel 2204: 
                   2205: sub get_CODE {
1.381     albertel 2206:     my ($all_codes,$num,$seed,$size,$type)=@_;
1.288     albertel 2207:     my $max='1'.'0'x$size;
                   2208:     my $newcode;
                   2209:     while(1) {
1.392     albertel 2210: 	$newcode=sprintf("%0".$size."d",int(rand($max)));
1.288     albertel 2211: 	if (!exists($$all_codes{$newcode})) {
                   2212: 	    $$all_codes{$newcode}=1;
1.381     albertel 2213: 	    if ($type eq 'number' ) {
                   2214: 		return $newcode;
                   2215: 	    } else {
                   2216: 		return &num_to_letters($newcode);
                   2217: 	    }
1.288     albertel 2218: 	}
                   2219:     }
                   2220: }
1.140     sakharuk 2221: 
1.284     albertel 2222: sub print_resources {
1.360     albertel 2223:     my ($r,$helper,$person,$type,$moreenv,$master_seq,$remove_latex_header,
1.422     albertel 2224: 	$LaTeXwidth)=@_;
1.284     albertel 2225:     my $current_output = ''; 
1.375     foxr     2226:     my $printed = '';
1.284     albertel 2227:     my ($username,$userdomain,$usersection) = split /:/,$person;
                   2228:     my $fullname = &get_name($username,$userdomain);
1.492     foxr     2229:     my $namepostfix = "\\\\";	# Both anon and not anon should get the same vspace.
1.288     albertel 2230:     if ($person =~ 'anon') {
1.492     foxr     2231: 	$namepostfix .="Name: ";
1.288     albertel 2232: 	$fullname = "CODE - ".$moreenv->{'CODE'};
                   2233:     }
1.444     foxr     2234:     #  Fullname may have special latex characters that need \ prefixing:
                   2235:     #
                   2236: 
1.350     foxr     2237:     my $i           = 0;
1.284     albertel 2238:     #goes through all resources, checks if they are available for 
                   2239:     #current student, and produces output   
1.428     albertel 2240: 
                   2241:     &Apache::lonxml::clear_problem_counter();
1.364     albertel 2242:     my %page_breaks  = &get_page_breaks($helper);
1.476     albertel 2243:     my $columns_in_format = (split(/\|/,$helper->{'VARS'}->{'FORMAT'}))[1];
1.440     foxr     2244:     #
1.441     foxr     2245:     #   end each student with a 
1.440     foxr     2246:     #   Special that allows the post processor to even out the page
                   2247:     #   counts later.  Nasty problem this... it would be really
                   2248:     #   nice to put the special in as a postscript comment
1.441     foxr     2249:     #   e.g. \special{ps:\ENDOFSTUDENTSTAMP}  unfortunately,
1.440     foxr     2250:     #   The special gets passed the \ and dvips puts it in the output file
1.441     foxr     2251:     #   so we will just rely on prntout.pl to strip  ENDOFSTUDENTSTAMP from the
                   2252:     #   postscript.  Each ENDOFSTUDENTSTAMP will go on a line by itself.
1.440     foxr     2253:     #
1.363     foxr     2254: 
1.511     foxr     2255: 
1.284     albertel 2256:     foreach my $curresline (@{$master_seq})  {
1.351     foxr     2257: 	if (defined $page_breaks{$curresline}) {
1.350     foxr     2258: 	    if($i != 0) {
                   2259: 		$current_output.= "\\newpage\n";
                   2260: 	    }
                   2261: 	}
                   2262: 	$i++;
1.511     foxr     2263: 
1.284     albertel 2264: 	if ( !($type eq 'problems' && 
                   2265: 	       ($curresline!~ m/\.(problem|exam|quiz|assess|survey|form|library)$/)) ) {
                   2266: 	    my ($map,$id,$res_url) = &Apache::lonnet::decode_symb($curresline);
                   2267: 	    if (&Apache::lonnet::allowed('bre',$res_url)) {
1.414     albertel 2268: 		if ($res_url!~m|^ext/|
1.413     albertel 2269: 		    && $res_url=~/\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)$/) {
1.375     foxr     2270: 		    $printed .= $curresline.':';
1.428     albertel 2271: 
                   2272: 		    &Apache::lonxml::remember_problem_counter();    
                   2273: 
1.373     albertel 2274: 		    my $rendered = &Apache::loncommon::get_student_view($curresline,$username,$userdomain,$env{'request.course.id'},'tex',$moreenv);
1.428     albertel 2275: 
1.305     sakharuk 2276: 		    if(($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') ||
                   2277: 		       ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'only')) {
1.380     foxr     2278: 			#   Use a copy of the hash so we don't pervert it on future loop passes.
                   2279: 			my %answerenv = %{$moreenv};
                   2280: 			$answerenv{'answer_output_mode'}='tex';
                   2281: 			$answerenv{'latex_type'}=$helper->{'VARS'}->{'LATEX_TYPE'};
1.428     albertel 2282: 			
                   2283: 			&Apache::lonxml::restore_problem_counter();
                   2284: 
1.380     foxr     2285: 			my $ansrendered = &Apache::loncommon::get_student_answers($curresline,$username,$userdomain,$env{'request.course.id'},%answerenv);
1.428     albertel 2286: 
1.305     sakharuk 2287: 			if ($helper->{'VARS'}->{'ANSWER_TYPE'} eq 'no') {
                   2288: 			    $rendered=~s/(\\keephidden{ENDOFPROBLEM})/$ansrendered$1/;
                   2289: 			} else {
1.423     foxr     2290: 
                   2291: 			    
                   2292: 			    my $header =&print_latex_header($helper->{'VARS'}->{'LATEX_TYPE'});
1.477     albertel 2293: 			    my $title = &Apache::lonnet::gettitle($curresline);
                   2294: 			    $title = &Apache::lonxml::latex_special_symbols($title);
                   2295: 			    my $body   ='\vskip 0 mm \noindent\textbf{'.$title.'}\vskip 0 mm ';
                   2296: 			    $body     .=&path_to_problem($res_url,$LaTeXwidth);
1.423     foxr     2297: 			    $body     .='\vskip 1 mm '.$ansrendered;
                   2298: 			    $body     = &encapsulate_minipage($body);
                   2299: 			    $rendered = $header.$body;
1.305     sakharuk 2300: 			}
                   2301: 		    }
1.511     foxr     2302: 
                   2303: 		    if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
                   2304: 			my $url = &Apache::lonnet::clutter($res_url);
                   2305: 			my $annotation = &annotate($url);
                   2306: 			$rendered =~  s/(\\keephidden{ENDOFPROBLEM})/$annotation$1/;
                   2307: 		    }
1.305     sakharuk 2308: 		    if ($remove_latex_header eq 'YES') {
                   2309: 			$rendered = &latex_header_footer_remove($rendered);
                   2310: 		    } else {
                   2311: 			$rendered =~ s/\\end{document}//;
                   2312: 		    }
                   2313: 		    $current_output .= $rendered;		    
1.456     raeburn  2314: 		} elsif ($res_url=~/\/(smppg|syllabus|aboutme|bulletinboard)$/) {
1.375     foxr     2315: 		    $printed .= $curresline.':';
1.373     albertel 2316: 		    my $rendered = &Apache::loncommon::get_student_view($curresline,$username,$userdomain,$env{'request.course.id'},'tex',$moreenv);
1.511     foxr     2317: 		    if ($helper->{'VARS'}->{'PRINT_ANNOTATIONS'} eq 'yes') {
                   2318: 			my $url = &Apache::lonnet::clutter($res_url);
                   2319: 			my $annotation = &annotate($url);
                   2320: 			$annotation    =~ s/(\\end{document})/$annotation$1/;
                   2321: 		    }
1.305     sakharuk 2322: 		    if ($remove_latex_header eq 'YES') {
                   2323: 			$rendered = &latex_header_footer_remove($rendered);
1.284     albertel 2324: 		    } else {
1.305     sakharuk 2325: 			$rendered =~ s/\\end{document}//;
1.284     albertel 2326: 		    }
1.421     foxr     2327: 		    $current_output .= $rendered.'\vskip 0.5mm\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}\strut \vskip 0 mm \strut ';
                   2328: 
1.284     albertel 2329: 		} else {
1.414     albertel 2330: 		    my $rendered = &unsupported($res_url,$helper->{'VARS'}->{'LATEX_TYPE'},$curresline);
1.305     sakharuk 2331: 		    if ($remove_latex_header ne 'NO') {
                   2332: 			$rendered = &latex_header_footer_remove($rendered);
                   2333: 		    } else {
                   2334: 			$rendered =~ s/\\end{document}//;
                   2335: 		    }
                   2336: 		    $current_output .= $rendered;
1.284     albertel 2337: 		}
                   2338: 	    }
                   2339: 	    $remove_latex_header = 'YES';
                   2340: 	}
1.331     albertel 2341: 	if (&Apache::loncommon::connection_aborted($r)) { last; }
1.284     albertel 2342:     }
                   2343:     my $courseidinfo = &get_course();
                   2344:     if (defined($courseidinfo)) { $courseidinfo=' - '.$courseidinfo }
                   2345:     if ($usersection ne '') {$courseidinfo.=' - Sec. '.$usersection}
                   2346:     my $currentassignment=&Apache::lonxml::latex_special_symbols($helper->{VARS}->{'assignment'},'header');
1.476     albertel 2347:     my $header_line =
1.486     foxr     2348: 	&format_page_header($LaTeXwidth, $parmhash{'print_header_format'},
1.476     albertel 2349: 			    $currentassignment, $courseidinfo, $fullname);
                   2350:     my $header_start = ($columns_in_format == 1) ? '\lhead'
                   2351: 	                                         : '\fancyhead[LO]';
                   2352:     $header_line = $header_start.'{'.$header_line.'}';
                   2353: 
1.284     albertel 2354:     if ($current_output=~/\\documentclass/) {
1.476     albertel 2355: 	$current_output =~ s/\\begin{document}/\\setlength{\\topmargin}{1cm} \\begin{document}\\noindent\\parbox{\\minipagewidth}{\\noindent$header_line$namepostfix}\\vskip 5 mm /;
1.284     albertel 2356:     } else {
1.476     albertel 2357: 	my $blankpages = 
                   2358: 	    '\clearpage\strut\clearpage'x$helper->{'VARS'}->{'EMPTY_PAGES'};
                   2359: 	    
                   2360: 	$current_output = '\strut\vspace*{-6 mm}\\newline'.
                   2361: 	    &copyright_line().' \newpage '.$blankpages.$end_of_student.
                   2362: 	    '\setcounter{page}{1}\noindent\parbox{\minipagewidth}{\noindent'.
                   2363: 	    $header_line.$namepostfix.'} \vskip 5 mm '.$current_output;
1.284     albertel 2364:     }
1.440     foxr     2365:     #
                   2366:     #  Close the student bracketing.
                   2367:     #
1.375     foxr     2368:     return ($current_output,$fullname, $printed);
1.284     albertel 2369: 
                   2370: }
1.140     sakharuk 2371: 
1.3       sakharuk 2372: sub handler {
                   2373: 
                   2374:     my $r = shift;
1.397     albertel 2375:     
                   2376:     &init_perm();
1.114     bowersj2 2377: 
1.416     foxr     2378: 
1.67      www      2379: 
1.397     albertel 2380:     my $helper = printHelper($r);
                   2381:     if (!ref($helper)) {
                   2382: 	return $helper;
1.60      sakharuk 2383:     }
1.177     sakharuk 2384:    
1.184     sakharuk 2385: 
1.454     foxr     2386:     %parmhash=&Apache::lonnet::coursedescription($env{'request.course.id'});
1.353     foxr     2387:  
1.416     foxr     2388: 
1.350     foxr     2389: 
                   2390: 
1.367     foxr     2391:     #  If a figure conversion queue file exists for this user.domain
                   2392:     # we delete it since it can only be bad (if it were good, printout.pl
                   2393:     # would have deleted it the last time around.
                   2394: 
1.373     albertel 2395:     my $conversion_queuefile = "/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout.dat";
1.367     foxr     2396:     if(-e $conversion_queuefile) {
                   2397: 	unlink $conversion_queuefile;
                   2398:     }
1.515     foxr     2399:     
                   2400: 
1.184     sakharuk 2401:     &output_data($r,$helper,\%parmhash);
1.2       sakharuk 2402:     return OK;
1.60      sakharuk 2403: } 
1.2       sakharuk 2404: 
1.131     bowersj2 2405: use Apache::lonhelper;
1.130     sakharuk 2406: 
1.223     bowersj2 2407: sub addMessage {
                   2408:     my $text = shift;
                   2409:     my $paramHash = Apache::lonhelper::getParamHash();
                   2410:     $paramHash->{MESSAGE_TEXT} = $text;
                   2411:     Apache::lonhelper::message->new();
                   2412: }
                   2413: 
1.416     foxr     2414: 
1.238     bowersj2 2415: 
1.397     albertel 2416: sub init_perm {
                   2417:     undef(%perm);
                   2418:     $perm{'pav'}=&Apache::lonnet::allowed('pav',$env{'request.course.id'});
                   2419:     if (!$perm{'pav'}) {
                   2420: 	$perm{'pav'}=&Apache::lonnet::allowed('pav',
                   2421: 		  $env{'request.course.id'}.'/'.$env{'request.course.sec'});
                   2422:     }
1.465     albertel 2423:     $perm{'pfo'}=&Apache::lonnet::allowed('pfo',$env{'request.course.id'});
1.397     albertel 2424:     if (!$perm{'pfo'}) {
                   2425: 	$perm{'pfo'}=&Apache::lonnet::allowed('pfo',
                   2426: 		  $env{'request.course.id'}.'/'.$env{'request.course.sec'});
                   2427:     }
                   2428: }
                   2429: 
1.507     albertel 2430: sub get_randomly_ordered_warning {
                   2431:     my ($helper,$map) = @_;
                   2432: 
                   2433:     my $message;
                   2434: 
                   2435:     my $postdata = $env{'form.postdata'} || $helper->{VARS}{'postdata'};
                   2436:     my $navmap = Apache::lonnavmaps::navmap->new();
                   2437:     my $res = $navmap->getResourceByUrl($map);
                   2438:     if ($res) {
                   2439: 	my $func = 
                   2440: 	    sub { return ($_[0]->is_map() && $_[0]->randomorder); };
                   2441: 	my @matches = $navmap->retrieveResources($res, $func,1,1,1);
                   2442: 	if (@matches) {
1.508     albertel 2443: 	    $message = "Some of the items below are in folders set to be randomly ordered. However, when printing the contents of these folders, they will be printed in the original order for all students, not the randomized order.";
1.507     albertel 2444: 	}
                   2445:     }
                   2446:     if ($message) {
                   2447: 	return '<message type="warning">'.$message.'</message>';
                   2448:     }
                   2449:     return;
                   2450: }
                   2451: 
1.131     bowersj2 2452: sub printHelper {
1.115     bowersj2 2453:     my $r = shift;
                   2454: 
                   2455:     if ($r->header_only) {
1.373     albertel 2456:         if ($env{'browser.mathml'}) {
1.241     www      2457:             &Apache::loncommon::content_type($r,'text/xml');
1.131     bowersj2 2458:         } else {
1.241     www      2459:             &Apache::loncommon::content_type($r,'text/html');
1.131     bowersj2 2460:         }
                   2461:         $r->send_http_header;
                   2462:         return OK;
1.115     bowersj2 2463:     }
                   2464: 
1.131     bowersj2 2465:     # Send header, nocache
1.373     albertel 2466:     if ($env{'browser.mathml'}) {
1.241     www      2467:         &Apache::loncommon::content_type($r,'text/xml');
1.115     bowersj2 2468:     } else {
1.241     www      2469:         &Apache::loncommon::content_type($r,'text/html');
1.115     bowersj2 2470:     }
                   2471:     &Apache::loncommon::no_cache($r);
                   2472:     $r->send_http_header;
                   2473:     $r->rflush();
                   2474: 
1.131     bowersj2 2475:     # Unfortunately, this helper is so complicated we have to
                   2476:     # write it by hand
                   2477: 
                   2478:     Apache::loncommon::get_unprocessed_cgi($ENV{QUERY_STRING});
                   2479:     
1.176     bowersj2 2480:     my $helper = Apache::lonhelper::helper->new("Printing Helper");
1.146     bowersj2 2481:     $helper->declareVar('symb');
1.156     bowersj2 2482:     $helper->declareVar('postdata');    
1.290     sakharuk 2483:     $helper->declareVar('curseed'); 
                   2484:     $helper->declareVar('probstatus');   
1.156     bowersj2 2485:     $helper->declareVar('filename');
                   2486:     $helper->declareVar('construction');
1.178     sakharuk 2487:     $helper->declareVar('assignment');
1.262     sakharuk 2488:     $helper->declareVar('style_file');
1.340     foxr     2489:     $helper->declareVar('student_sort');
1.363     foxr     2490:     $helper->declareVar('FINISHPAGE');
1.366     foxr     2491:     $helper->declareVar('PRINT_TYPE');
1.372     foxr     2492:     $helper->declareVar("showallfoils");
1.483     foxr     2493:     $helper->declareVar("STUDENTS");
1.363     foxr     2494: 
1.518     foxr     2495: 
                   2496:    
                   2497: 
                   2498: 
1.363     foxr     2499:     #  The page breaks can get loaded initially from the course environment:
1.394     foxr     2500:     # But we only do this in the initial state so that they are allowed to change.
                   2501:     #
1.366     foxr     2502: 
1.416     foxr     2503:     # $helper->{VARS}->{FINISHPAGE} = '';
1.363     foxr     2504:     
                   2505:     &Apache::loncommon::restore_course_settings('print',
1.366     foxr     2506: 						{'pagebreaks'  => 'scalar',
                   2507: 					         'lastprinttype' => 'scalar'});
                   2508:     
1.483     foxr     2509:     # This will persistently load in the data we want from the
                   2510:     # very first screen.
1.394     foxr     2511:     
                   2512:     if($helper->{VARS}->{PRINT_TYPE} eq $env{'form.lastprinttype'}) {
                   2513: 	if (!defined ($env{"form.CURRENT_STATE"})) {
                   2514: 	    
                   2515: 	    $helper->{VARS}->{FINISHPAGE} = $env{'form.pagebreaks'};
                   2516: 	} else {
                   2517: 	    my $state = $env{"form.CURRENT_STATE"};
                   2518: 	    if ($state eq "START") {
                   2519: 		$helper->{VARS}->{FINISHPAGE} = $env{'form.pagebreaks'};
                   2520: 	    }
                   2521: 	}
                   2522: 	
1.366     foxr     2523:     }
1.481     albertel 2524: 
1.483     foxr     2525: 
1.156     bowersj2 2526:     # Detect whether we're coming from construction space
1.373     albertel 2527:     if ($env{'form.postdata'}=~/^(?:http:\/\/[^\/]+\/|\/|)\~([^\/]+)\/(.*)$/) {
1.235     bowersj2 2528:         $helper->{VARS}->{'filename'} = "~$1/$2";
1.156     bowersj2 2529:         $helper->{VARS}->{'construction'} = 1;
1.481     albertel 2530:     } else {
1.373     albertel 2531:         if ($env{'form.postdata'}) {
                   2532:             $helper->{VARS}->{'symb'} = &Apache::lonnet::symbread($env{'form.postdata'});
1.482     albertel 2533: 	    if ( $helper->{VARS}->{'symb'} eq '') {
                   2534: 		$helper->{VARS}->{'postdata'} = $env{'form.postdata'};
                   2535: 	    }
1.156     bowersj2 2536:         }
1.373     albertel 2537:         if ($env{'form.symb'}) {
                   2538:             $helper->{VARS}->{'symb'} = $env{'form.symb'};
1.156     bowersj2 2539:         }
1.373     albertel 2540:         if ($env{'form.url'}) {
1.156     bowersj2 2541:             $helper->{VARS}->{'symb'} = &Apache::lonnet::symbread($helper->{VARS}->{'postdata'});
                   2542:         }
1.416     foxr     2543: 
1.157     bowersj2 2544:     }
1.481     albertel 2545: 
1.373     albertel 2546:     if ($env{'form.symb'}) {
                   2547:         $helper->{VARS}->{'symb'} = $env{'form.symb'};
1.146     bowersj2 2548:     }
1.373     albertel 2549:     if ($env{'form.url'}) {
1.140     sakharuk 2550:         $helper->{VARS}->{'symb'} = &Apache::lonnet::symbread($helper->{VARS}->{'postdata'});
1.153     sakharuk 2551: 
1.140     sakharuk 2552:     }
1.343     albertel 2553:     $helper->{VARS}->{'symb'}=
                   2554: 	&Apache::lonenc::check_encrypt($helper->{VARS}->{'symb'});
1.335     albertel 2555:     my ($resourceTitle,$sequenceTitle,$mapTitle) = &details_for_menu($helper);
1.178     sakharuk 2556:     if ($sequenceTitle ne '') {$helper->{VARS}->{'assignment'}=$sequenceTitle;}
1.481     albertel 2557: 
1.156     bowersj2 2558:     
1.146     bowersj2 2559:     # Extract map
                   2560:     my $symb = $helper->{VARS}->{'symb'};
1.156     bowersj2 2561:     my ($map, $id, $url);
                   2562:     my $subdir;
1.483     foxr     2563:     my $is_published=0;		# True when printing from resource space.
1.156     bowersj2 2564: 
                   2565:     # Get the resource name from construction space
                   2566:     if ($helper->{VARS}->{'construction'}) {
                   2567:         $resourceTitle = substr($helper->{VARS}->{'filename'}, 
                   2568:                                 rindex($helper->{VARS}->{'filename'}, '/')+1);
                   2569:         $subdir = substr($helper->{VARS}->{'filename'},
                   2570:                          0, rindex($helper->{VARS}->{'filename'}, '/') + 1);
1.481     albertel 2571:     } else {
1.482     albertel 2572: 	if ($symb ne '') {
                   2573: 	    ($map, $id, $url) = &Apache::lonnet::decode_symb($symb);
                   2574: 	    $helper->{VARS}->{'postdata'} = 
                   2575: 		&Apache::lonenc::check_encrypt(&Apache::lonnet::clutter($url));
                   2576: 	} else {
                   2577: 	    $url = $helper->{VARS}->{'postdata'};
1.483     foxr     2578: 	    $is_published=1;	# From resource space.
1.482     albertel 2579: 	}
                   2580: 	$url = &Apache::lonnet::clutter($url);
1.481     albertel 2581: 
1.156     bowersj2 2582:         if (!$resourceTitle) { # if the resource doesn't have a title, use the filename
1.238     bowersj2 2583:             my $postdata = $helper->{VARS}->{'postdata'};
                   2584:             $resourceTitle = substr($postdata, rindex($postdata, '/') + 1);
1.156     bowersj2 2585:         }
                   2586:         $subdir = &Apache::lonnet::filelocation("", $url);
1.128     bowersj2 2587:     }
1.373     albertel 2588:     if (!$helper->{VARS}->{'curseed'} && $env{'form.curseed'}) {
                   2589: 	$helper->{VARS}->{'curseed'}=$env{'form.curseed'};
1.230     albertel 2590:     }
1.373     albertel 2591:     if (!$helper->{VARS}->{'probstatus'} && $env{'form.problemtype'}) {
1.512     foxr     2592: 	$helper->{VARS}->{'probstatus'}=$env{'form.problemstatus'};
1.290     sakharuk 2593:     }
1.115     bowersj2 2594: 
1.192     bowersj2 2595:     my $userCanSeeHidden = Apache::lonnavmaps::advancedUser();
                   2596: 
1.481     albertel 2597:     Apache::lonhelper::registerHelperTags();
1.119     bowersj2 2598: 
1.131     bowersj2 2599:     # "Delete everything after the last slash."
1.119     bowersj2 2600:     $subdir =~ s|/[^/]+$||;
                   2601: 
1.131     bowersj2 2602:     # What can be printed is a very dynamic decision based on
                   2603:     # lots of factors. So we need to dynamically build this list.
                   2604:     # To prevent security leaks, states are only added to the wizard
                   2605:     # if they can be reached, which ensures manipulating the form input
                   2606:     # won't allow anyone to reach states they shouldn't have permission
                   2607:     # to reach.
                   2608: 
                   2609:     # printChoices is tracking the kind of printing the user can
                   2610:     # do, and will be used in a choices construction later.
                   2611:     # In the meantime we will be adding states and elements to
                   2612:     # the helper by hand.
                   2613:     my $printChoices = [];
                   2614:     my $paramHash;
1.130     sakharuk 2615: 
1.240     albertel 2616:     if ($resourceTitle) {
1.458     www      2617:         push @{$printChoices}, ["<b><i>$resourceTitle</i></b> (".&mt('the resource you just saw on the screen').")", 'current_document', 'PAGESIZE'];
1.156     bowersj2 2618:     }
                   2619: 
1.238     bowersj2 2620:     # Useful filter strings
1.287     albertel 2621:     my $isProblem = '($res->is_problem()||$res->contains_problem) ';
1.238     bowersj2 2622:     $isProblem .= ' && !$res->randomout()' if !$userCanSeeHidden;
1.287     albertel 2623:     my $isProblemOrMap = '$res->is_problem() || $res->contains_problem() || $res->is_sequence()';
                   2624:     my $isNotMap = '!$res->is_sequence()';
1.238     bowersj2 2625:     $isNotMap .= ' && !$res->randomout()' if !$userCanSeeHidden;
                   2626:     my $isMap = '$res->is_map()';
1.342     albertel 2627:     my $symbFilter = '$res->shown_symb()';
                   2628:     my $urlValue = '$res->link()';
1.238     bowersj2 2629: 
                   2630:     $helper->declareVar('SEQUENCE');
                   2631: 
1.465     albertel 2632:     # If we're in a sequence...
1.416     foxr     2633: 
1.465     albertel 2634:     my $start_new_option;
                   2635:     if ($perm{'pav'}) {
                   2636: 	$start_new_option = 
                   2637: 	    "<option text='".&mt('Start new page<br />before selected').
                   2638: 	    "' variable='FINISHPAGE' />";
                   2639:     }
1.238     bowersj2 2640: 
1.483     foxr     2641:     if (($helper->{'VARS'}->{'construction'} ne '1' ) &&
1.350     foxr     2642: 
1.243     bowersj2 2643: 	$helper->{VARS}->{'postdata'} &&
                   2644: 	$helper->{VARS}->{'assignment'}) {
1.131     bowersj2 2645:         # Allow problems from sequence
1.458     www      2646:         push @{$printChoices}, [&mt('Selected <b>Problems</b> in folder <b><i>[_1]</i></b>',$sequenceTitle), 'map_problems', 'CHOOSE_PROBLEMS'];
1.131     bowersj2 2647:         # Allow all resources from sequence
1.458     www      2648:         push @{$printChoices}, [&mt('Selected <b>Resources</b> in folder <b><i>[_1]</i></b>',$sequenceTitle), 'map_problems_pages', 'CHOOSE_PROBLEMS_HTML'];
1.465     albertel 2649: 
1.131     bowersj2 2650:         my $helperFragment = <<HELPERFRAGMENT;
1.155     sakharuk 2651:   <state name="CHOOSE_PROBLEMS" title="Select Problem(s) to print">
1.435     foxr     2652:     <resource variable="RESOURCES" multichoice="1" toponly='1' addstatus="1"
1.287     albertel 2653:               closeallpages="1">
1.144     bowersj2 2654:       <nextstate>PAGESIZE</nextstate>
1.435     foxr     2655:       <filterfunc>return $isProblem;</filterfunc>
1.131     bowersj2 2656:       <mapurl>$map</mapurl>
1.238     bowersj2 2657:       <valuefunc>return $symbFilter;</valuefunc>
1.465     albertel 2658:       $start_new_option
1.131     bowersj2 2659:       </resource>
                   2660:     </state>
                   2661: 
1.155     sakharuk 2662:   <state name="CHOOSE_PROBLEMS_HTML" title="Select Resource(s) to print">
1.435     foxr     2663:     <resource variable="RESOURCES" multichoice="1" toponly='1' addstatus="1"
1.287     albertel 2664:               closeallpages="1">
1.144     bowersj2 2665:       <nextstate>PAGESIZE</nextstate>
1.435     foxr     2666:       <filterfunc>return $isNotMap;</filterfunc>
1.131     bowersj2 2667:       <mapurl>$map</mapurl>
1.238     bowersj2 2668:       <valuefunc>return $symbFilter;</valuefunc>
1.465     albertel 2669:       $start_new_option
1.131     bowersj2 2670:       </resource>
                   2671:     </state>
                   2672: HELPERFRAGMENT
1.121     bowersj2 2673: 
1.326     sakharuk 2674: 	&Apache::lonxml::xmlparse($r, 'helper', $helperFragment);
1.121     bowersj2 2675:     }
                   2676: 
1.397     albertel 2677:     # If the user has pfo (print for otheres) allow them to print all 
1.354     foxr     2678:     # problems and resources  in the entier course, optionally for selected students
1.483     foxr     2679:     if ($perm{'pfo'} &&  !$is_published  &&
1.481     albertel 2680:         ($helper->{VARS}->{'postdata'}=~/\/res\// || $helper->{VARS}->{'postdata'}=~/\/(syllabus|smppg|aboutme|bulletinboard)$/)) { 
                   2681: 
1.509     albertel 2682:         push @{$printChoices}, [&mtn('Selected <b>Problems</b> from <b>entire course</b>'), 'all_problems', 'ALL_PROBLEMS'];
                   2683: 	push @{$printChoices}, [&mtn('Selected <b>Resources</b> from <b>entire course</b>'), 'all_resources', 'ALL_RESOURCES'];
1.284     albertel 2684:          &Apache::lonxml::xmlparse($r, 'helper', <<ALL_PROBLEMS);
1.155     sakharuk 2685:   <state name="ALL_PROBLEMS" title="Select Problem(s) to print">
1.287     albertel 2686:     <resource variable="RESOURCES" toponly='0' multichoice="1"
                   2687: 	suppressEmptySequences='0' addstatus="1" closeallpages="1">
1.144     bowersj2 2688:       <nextstate>PAGESIZE</nextstate>
1.192     bowersj2 2689:       <filterfunc>return $isProblemOrMap;</filterfunc>
1.287     albertel 2690:       <choicefunc>return $isNotMap;</choicefunc>
1.238     bowersj2 2691:       <valuefunc>return $symbFilter;</valuefunc>
1.465     albertel 2692:       $start_new_option
1.284     albertel 2693:     </resource>
                   2694:   </state>
1.354     foxr     2695:   <state name="ALL_RESOURCES" title="Select Resource(s) to print">
                   2696:     <resource variable="RESOURCES" toponly='0' multichoice='1'
                   2697:               suppressEmptySequences='0' addstatus='1' closeallpages='1'>
                   2698:       <nextstate>PAGESIZE</nextstate>
                   2699:       <filterfunc>return $isNotMap; </filterfunc>
                   2700:       <valuefunc>return $symbFilter;</valuefunc>
1.465     albertel 2701:       $start_new_option
1.354     foxr     2702:     </resource>
                   2703:   </state>
1.284     albertel 2704: ALL_PROBLEMS
1.132     bowersj2 2705: 
1.284     albertel 2706: 	if ($helper->{VARS}->{'assignment'}) {
1.483     foxr     2707: 	    push @{$printChoices}, [&mt("Selected <b>Problems</b> from folder <b><i>[_1]</i></b> for <b>selected people</b>",$sequenceTitle), 'problems_for_students', 'CHOOSE_STUDENTS'];
1.474     www      2708: 	    push @{$printChoices}, [&mt("Selected <b>Problems</b> from folder <b><i>[_1]</i></b> for <b>CODEd assignments</b>",$sequenceTitle), 'problems_for_anon', 'CHOOSE_ANON1'];
1.284     albertel 2709: 	}
1.424     foxr     2710: 
1.507     albertel 2711: 	my $randomly_ordered_warning = 
                   2712: 	    &get_randomly_ordered_warning($helper,$map);
                   2713: 
1.424     foxr     2714: 	# resource_selector will hold a few states that:
                   2715: 	#   - Allow resources to be selected for printing.
                   2716: 	#   - Determine pagination between assignments.
                   2717: 	#   - Determine how many assignments should be bundled into a single PDF.
                   2718:         # TODO:
                   2719: 	#    Probably good to do things like separate this up into several vars, each
                   2720: 	#    with one state, and use REGEXPs at inclusion time to set state names
                   2721: 	#    and next states for better mix and match capability
                   2722: 	#
1.284     albertel 2723: 	my $resource_selector=<<RESOURCE_SELECTOR;
1.424     foxr     2724:     <state name="SELECT_PROBLEMS" title="Select resources to print">
1.507     albertel 2725:     $randomly_ordered_warning
                   2726: 
1.424     foxr     2727:    <nextstate>PRINT_FORMATTING</nextstate> 
1.284     albertel 2728:    <message><br /><big><i><b>Select resources for the assignment</b></i></big><br /></message>
1.287     albertel 2729:     <resource variable="RESOURCES" multichoice="1" addstatus="1" 
                   2730:               closeallpages="1">
1.254     sakharuk 2731:       <filterfunc>return $isProblem;</filterfunc>
1.148     bowersj2 2732:       <mapurl>$map</mapurl>
1.254     sakharuk 2733:       <valuefunc>return $symbFilter;</valuefunc>
1.465     albertel 2734:       $start_new_option
1.147     bowersj2 2735:       </resource>
1.424     foxr     2736:     </state>
                   2737:     <state name="PRINT_FORMATTING" title="How should results be printed?">
1.155     sakharuk 2738:     <message><br /><big><i><b>How should the results be printed?</b></i></big><br /></message>
1.149     bowersj2 2739:     <choices variable="EMPTY_PAGES">
1.204     sakharuk 2740:       <choice computer='0'>Start each student\'s assignment on a new page/column (add a pagefeed after each assignment)</choice>
                   2741:       <choice computer='1'>Add one empty page/column after each student\'s assignment</choice>
                   2742:       <choice computer='2'>Add two empty pages/column after each student\'s assignment</choice>
                   2743:       <choice computer='3'>Add three empty pages/column after each student\'s assignment</choice>
1.284     albertel 2744:     </choices>
1.424     foxr     2745:     <nextstate>PAGESIZE</nextstate>
1.429     foxr     2746:     <message><hr width='33%' /><b>How do you want assignments split into PDF files? </b></message>
                   2747:     <choices variable="SPLIT_PDFS">
                   2748:        <choice computer="all">All assignments in a single PDF file</choice>
                   2749:        <choice computer="sections">Each PDF contains exactly one section</choice>
                   2750:        <choice computer="oneper">Each PDF contains exactly one assignment</choice>
1.449     albertel 2751:        <choice computer="usenumber" relatedvalue="NUMBER_TO_PRINT">
                   2752:             Specify the number of assignments per PDF:</choice>
1.429     foxr     2753:     </choices>
1.424     foxr     2754:     </state>
1.284     albertel 2755: RESOURCE_SELECTOR
                   2756: 
                   2757:         &Apache::lonxml::xmlparse($r, 'helper', <<CHOOSE_STUDENTS);
                   2758:   <state name="CHOOSE_STUDENTS" title="Select Students and Resources">
1.485     albertel 2759:       <message><b>Select sorting order of printout</b> </message>
1.340     foxr     2760:     <choices variable='student_sort'>
                   2761:       <choice computer='0'>Sort by section then student</choice>
                   2762:       <choice computer='1'>Sort by students across sections.</choice>
                   2763:     </choices>
1.437     foxr     2764:       <message><br /><hr /><br /> </message>
1.425     foxr     2765:       <student multichoice='1' variable="STUDENTS" nextstate="SELECT_PROBLEMS" coursepersonnel="1"/>
1.424     foxr     2766:   </state>
1.284     albertel 2767:     $resource_selector
1.131     bowersj2 2768: CHOOSE_STUDENTS
1.292     albertel 2769: 
1.373     albertel 2770: 	my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   2771: 	my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.292     albertel 2772:         my @names=&Apache::lonnet::getkeys('CODEs',$cdom,$cnum);
                   2773: 	my $namechoice='<choice></choice>';
1.337     albertel 2774: 	foreach my $name (sort {uc($a) cmp uc($b)} @names) {
1.294     albertel 2775: 	    if ($name =~ /^error: 2 /) { next; }
1.381     albertel 2776: 	    if ($name =~ /^type\0/) { next; }
1.292     albertel 2777: 	    $namechoice.='<choice computer="'.$name.'">'.$name.'</choice>';
                   2778: 	}
1.389     foxr     2779: 
                   2780: 
                   2781: 	my %code_values;
1.405     albertel 2782: 	my %codes_to_print;
1.411     albertel 2783: 	foreach my $key (@names) {
1.389     foxr     2784: 	    %code_values = &Apache::grades::get_codes($key, $cdom, $cnum);
1.405     albertel 2785: 	    foreach my $key (keys(%code_values)) {
                   2786: 		$codes_to_print{$key} = 1;
1.388     foxr     2787: 	    }
                   2788: 	}
1.389     foxr     2789: 
1.452     albertel 2790: 	my $code_selection;
1.405     albertel 2791: 	foreach my $code (sort {uc($a) cmp uc($b)} (keys(%codes_to_print))) {
1.389     foxr     2792: 	    my $choice  = $code;
                   2793: 	    if ($code =~ /^[A-Z]+$/) { # Alpha code
                   2794: 		$choice = &letters_to_num($code);
                   2795: 	    }
1.432     albertel 2796: 	    push(@{$helper->{DATA}{ALL_CODE_CHOICES}},[$code,$choice]);
1.388     foxr     2797: 	}
1.436     albertel 2798: 	if (%codes_to_print) {
                   2799: 	    $code_selection .='   
1.472     albertel 2800: 	    <message><b>Choose single CODE from list:</b></message>
1.448     albertel 2801: 		<message></td><td></message>
1.452     albertel 2802: 		<dropdown variable="CODE_SELECTED_FROM_LIST" multichoice="0" allowempty="0">
                   2803:                   <choice></choice>
1.448     albertel 2804:                   <exec>
                   2805:                      push(@{$state->{CHOICES}},@{$helper->{DATA}{ALL_CODE_CHOICES}});
                   2806:                   </exec>
1.452     albertel 2807: 		</dropdown>
1.468     foxr     2808: 	    <message></td></tr><tr><td></message>
1.436     albertel 2809:             '.$/;
1.448     albertel 2810: 
1.436     albertel 2811: 	}
1.432     albertel 2812: 
                   2813: 	
1.381     albertel 2814: 	open(FH,$Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab');
                   2815: 	my $codechoice='';
                   2816: 	foreach my $line (<FH>) {
                   2817: 	    my ($name,$description,$code_type,$code_length)=
                   2818: 		(split(/:/,$line))[0,1,2,4];
                   2819: 	    if ($code_length > 0 && 
                   2820: 		$code_type =~/^(letter|number|-1)/) {
                   2821: 		$codechoice.='<choice computer="'.$name.'">'.$description.'</choice>';
                   2822: 	    }
                   2823: 	}
                   2824: 	if ($codechoice eq '') {
                   2825: 	    $codechoice='<choice computer="default">Default</choice>';
                   2826: 	}
1.284     albertel 2827:         &Apache::lonxml::xmlparse($r, 'helper', <<CHOOSE_ANON1);
1.468     foxr     2828:   <state name="CHOOSE_ANON1" title="Specify CODEd Assignments">
1.424     foxr     2829:     <nextstate>SELECT_PROBLEMS</nextstate>
1.468     foxr     2830:     <message><h4>Fill out one of the forms below</h4></message>
                   2831:     <message><br /><hr /> <br /></message>
                   2832:     <message><h3>Generate new CODEd Assignments</h3></message>
                   2833:     <message><table><tr><td><b>Number of CODEd assignments to print:</b></td><td></message>
1.362     albertel 2834:     <string variable="NUMBER_TO_PRINT_TOTAL" maxlength="5" size="5">
                   2835:        <validator>
                   2836: 	if (((\$helper->{'VARS'}{'NUMBER_TO_PRINT_TOTAL'}+0) < 1) &&
1.382     foxr     2837: 	    !\$helper->{'VARS'}{'REUSE_OLD_CODES'}                &&
1.388     foxr     2838:             !\$helper->{'VARS'}{'SINGLE_CODE'}                    &&
                   2839: 	    !\$helper->{'VARS'}{'CODE_SELECTED_FROM_LIST'}) {
1.362     albertel 2840: 	    return "You need to specify the number of assignments to print";
                   2841: 	}
                   2842: 	return undef;
                   2843:        </validator>
                   2844:     </string>
                   2845:     <message></td></tr><tr><td></message>
1.501     albertel 2846:     <message><b>Names to save the CODEs under for later:</b></message>
1.412     albertel 2847:     <message></td><td></message>
                   2848:     <string variable="ANON_CODE_STORAGE_NAME" maxlength="50" size="20" />
                   2849:     <message></td></tr><tr><td></message>
                   2850:     <message><b>Bubble sheet type:</b></message>
                   2851:     <message></td><td></message>
                   2852:     <dropdown variable="CODE_OPTION" multichoice="0" allowempty="0">
                   2853:     $codechoice
                   2854:     </dropdown>
1.468     foxr     2855:     <message></td></tr><tr><td colspan="2"></td></tr><tr><td></message>
                   2856:     <message></td></tr><tr><td></table></message>
1.472     albertel 2857:     <message><br /><hr /><h3>Print a Specific CODE </h3><br /><table></message>
1.468     foxr     2858:     <message><tr><td><b>Enter a CODE to print:</b></td><td></message>
1.412     albertel 2859:     <string variable="SINGLE_CODE" size="10">
1.382     foxr     2860:         <validator>
                   2861: 	   if(!\$helper->{'VARS'}{'NUMBER_TO_PRINT_TOTAL'}           &&
1.388     foxr     2862: 	      !\$helper->{'VARS'}{'REUSE_OLD_CODES'}                 &&
                   2863: 	      !\$helper->{'VARS'}{'CODE_SELECTED_FROM_LIST'}) {
1.382     foxr     2864: 	      return &Apache::lonprintout::is_code_valid(\$helper->{'VARS'}{'SINGLE_CODE'},
                   2865: 						      \$helper->{'VARS'}{'CODE_OPTION'});
                   2866: 	   } else {
                   2867: 	       return undef;	# Other forces control us.
                   2868: 	   }
                   2869:         </validator>
                   2870:     </string>
1.472     albertel 2871:     <message></td></tr><tr><td></message>
1.432     albertel 2872:         $code_selection
1.468     foxr     2873:     <message></td></tr></table></message>
1.472     albertel 2874:     <message><hr /><h3>Reprint a Set of Saved CODEs</h3><table><tr><td></message>
1.468     foxr     2875:     <message><b>Select saved CODEs:</b></message>
1.381     albertel 2876:     <message></td><td></message>
1.292     albertel 2877:     <dropdown variable="REUSE_OLD_CODES">
                   2878:         $namechoice
                   2879:     </dropdown>
1.412     albertel 2880:     <message></td></tr></table></message>
1.284     albertel 2881:   </state>
1.424     foxr     2882:   $resource_selector
1.284     albertel 2883: CHOOSE_ANON1
1.254     sakharuk 2884: 
1.272     sakharuk 2885: 
1.254     sakharuk 2886: 	if ($helper->{VARS}->{'assignment'}) {
1.483     foxr     2887: 	    push @{$printChoices}, [&mt("Selected <b>Resources</b> from folder <b><i>[_1]</i></b> for <b>selected people</b>",$sequenceTitle), 'resources_for_students', 'CHOOSE_STUDENTS1'];
1.472     albertel 2888: 	    push @{$printChoices}, [&mt("Selected <b>Resources</b> from folder <b><i>[_1]</i></b> for <b>CODEd assignments</b>",$sequenceTitle), 'resources_for_anon', 'CHOOSE_ANON2'];
1.254     sakharuk 2889: 	}
1.284     albertel 2890: 	    
                   2891: 
                   2892: 	$resource_selector=<<RESOURCE_SELECTOR;
1.424     foxr     2893:     <state name="SELECT_RESOURCES" title="Select Resources">
1.507     albertel 2894:     $randomly_ordered_warning
                   2895: 
1.424     foxr     2896:     <nextstate>PRINT_FORMATTING</nextstate>
1.254     sakharuk 2897:     <message><br /><big><i><b>Select resources for the assignment</b></i></big><br /></message>
1.287     albertel 2898:     <resource variable="RESOURCES" multichoice="1" addstatus="1" 
                   2899:               closeallpages="1">
1.254     sakharuk 2900:       <filterfunc>return $isNotMap;</filterfunc>
                   2901:       <mapurl>$map</mapurl>
                   2902:       <valuefunc>return $symbFilter;</valuefunc>
1.465     albertel 2903:       $start_new_option
1.254     sakharuk 2904:       </resource>
1.424     foxr     2905:     </state>
                   2906:     <state name="PRINT_FORMATTING" title="Format of the print job">
                   2907:     <nextstate>NUMBER_PER_PDF</nextstate>
1.254     sakharuk 2908:     <message><br /><big><i><b>How should the results be printed?</b></i></big><br /></message>
                   2909:     <choices variable="EMPTY_PAGES">
                   2910:       <choice computer='0'>Start each student\'s assignment on a new page/column (add a pagefeed after each assignment)</choice>
                   2911:       <choice computer='1'>Add one empty page/column after each student\'s assignment</choice>
                   2912:       <choice computer='2'>Add two empty pages/column after each student\'s assignment</choice>
                   2913:       <choice computer='3'>Add three empty pages/column after each student\'s assignment</choice>
1.284     albertel 2914:     </choices>
1.424     foxr     2915:     <nextstate>PAGESIZE</nextstate>
1.429     foxr     2916:     <message><hr width='33%' /><b>How do you want assignments split into PDF files? </b></message>
                   2917:     <choices variable="SPLIT_PDFS">
                   2918:        <choice computer="all">All assignments in a single PDF file</choice>
                   2919:        <choice computer="sections">Each PDF contains exactly one section</choice>
                   2920:        <choice computer="oneper">Each PDF contains exactly one assignment</choice>
1.449     albertel 2921:        <choice computer="usenumber" relatedvalue="NUMBER_TO_PRINT">
                   2922:            Specify the number of assignments per PDF:</choice>
1.429     foxr     2923:     </choices>
1.424     foxr     2924:     </state>
1.284     albertel 2925: RESOURCE_SELECTOR
                   2926: 
                   2927: 	&Apache::lonxml::xmlparse($r, 'helper', <<CHOOSE_STUDENTS1);
                   2928:   <state name="CHOOSE_STUDENTS1" title="Select Students and Resources">
1.340     foxr     2929:     <choices variable='student_sort'>
                   2930:       <choice computer='0'>Sort by section then student</choice>
                   2931:       <choice computer='1'>Sort by students across sections.</choice>
                   2932:     </choices>
1.437     foxr     2933:     <message><br /><hr /><br /></message>
1.426     foxr     2934:     <student multichoice='1' variable="STUDENTS" nextstate="SELECT_RESOURCES" coursepersonnel="1" />
1.340     foxr     2935: 
1.424     foxr     2936:     </state>
1.284     albertel 2937:     $resource_selector
1.254     sakharuk 2938: CHOOSE_STUDENTS1
                   2939: 
1.284     albertel 2940: 	&Apache::lonxml::xmlparse($r, 'helper', <<CHOOSE_ANON2);
1.472     albertel 2941:   <state name="CHOOSE_ANON2" title="Select CODEd Assignments">
1.424     foxr     2942:     <nextstate>SELECT_RESOURCES</nextstate>
1.472     albertel 2943:     <message><h4>Fill out one of the forms below</h4></message>
                   2944:     <message><br /><hr /> <br /></message>
                   2945:     <message><h3>Generate new CODEd Assignments</h3></message>
                   2946:     <message><table><tr><td><b>Number of CODEd assignments to print:</b></td><td></message>
1.362     albertel 2947:     <string variable="NUMBER_TO_PRINT_TOTAL" maxlength="5" size="5">
                   2948:        <validator>
                   2949: 	if (((\$helper->{'VARS'}{'NUMBER_TO_PRINT_TOTAL'}+0) < 1) &&
1.386     foxr     2950: 	    !\$helper->{'VARS'}{'REUSE_OLD_CODES'}                &&
1.388     foxr     2951: 	    !\$helper->{'VARS'}{'SINGLE_CODE'}                   &&
                   2952: 	    !\$helper->{'VARS'}{'CODE_SELECTED_FROM_LIST'}) {
1.362     albertel 2953: 	    return "You need to specify the number of assignments to print";
                   2954: 	}
                   2955: 	return undef;
                   2956:        </validator>
                   2957:     </string>
                   2958:     <message></td></tr><tr><td></message>
1.501     albertel 2959:     <message><b>Names to save the CODEs under for later:</b></message>
1.412     albertel 2960:     <message></td><td></message>
                   2961:     <string variable="ANON_CODE_STORAGE_NAME" maxlength="50" size="20" />
                   2962:     <message></td></tr><tr><td></message>
                   2963:     <message><b>Bubble sheet type:</b></message>
                   2964:     <message></td><td></message>
                   2965:     <dropdown variable="CODE_OPTION" multichoice="0" allowempty="0">
                   2966:     $codechoice
                   2967:     </dropdown>
1.472     albertel 2968:     <message></td></tr><tr><td></table></message>
                   2969:     <message><br /><hr /><h3>Print a Specific CODE </h3><br /><table></message>
                   2970:     <message><tr><td><b>Enter a CODE to print:</b></td><td></message>
1.412     albertel 2971:     <string variable="SINGLE_CODE" size="10">
1.386     foxr     2972:         <validator>
                   2973: 	   if(!\$helper->{'VARS'}{'NUMBER_TO_PRINT_TOTAL'}           &&
1.388     foxr     2974: 	      !\$helper->{'VARS'}{'REUSE_OLD_CODES'}                 &&
                   2975: 	      !\$helper->{'VARS'}{'CODE_SELECTED_FROM_LIST'}) {
1.386     foxr     2976: 	      return &Apache::lonprintout::is_code_valid(\$helper->{'VARS'}{'SINGLE_CODE'},
                   2977: 						      \$helper->{'VARS'}{'CODE_OPTION'});
                   2978: 	   } else {
                   2979: 	       return undef;	# Other forces control us.
                   2980: 	   }
                   2981:         </validator>
                   2982:     </string>
1.472     albertel 2983:     <message></td></tr><tr><td></message>
1.432     albertel 2984:         $code_selection
1.472     albertel 2985:     <message></td></tr></table></message>
                   2986:     <message><hr /><h3>Reprint a Set of Saved CODEs</h3><table><tr><td></message>
                   2987:     <message><b>Select saved CODEs:</b></message>
1.381     albertel 2988:     <message></td><td></message>
1.294     albertel 2989:     <dropdown variable="REUSE_OLD_CODES">
                   2990:         $namechoice
                   2991:     </dropdown>
1.412     albertel 2992:     <message></td></tr></table></message>
1.424     foxr     2993:   </state>
1.284     albertel 2994:     $resource_selector
                   2995: CHOOSE_ANON2
1.481     albertel 2996:     }
                   2997: 
1.121     bowersj2 2998:     # FIXME: That RE should come from a library somewhere.
1.483     foxr     2999:     if (($perm{'pav'} 
1.482     albertel 3000: 	&& $subdir ne $Apache::lonnet::perlvar{'lonDocRoot'}.'/res/'
                   3001: 	&& (defined($helper->{'VARS'}->{'construction'})
                   3002: 	    ||
                   3003: 	    (&Apache::lonnet::allowed('bre',$subdir) eq 'F'
                   3004: 	     && 
                   3005: 	     $helper->{VARS}->{'postdata'}=~/\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)/)
1.483     foxr     3006: 	    )) 
                   3007: 	&& $helper->{VARS}->{'assignment'} eq ""
1.482     albertel 3008: 	) {
1.238     bowersj2 3009: 
1.482     albertel 3010: 	my $pretty_dir = &Apache::lonnet::hreflocation($subdir);
                   3011:         push @{$printChoices}, [&mt("Selected <b>Problems</b> from current subdirectory <b><i>[_1]</i></b>",$pretty_dir), 'problems_from_directory', 'CHOOSE_FROM_SUBDIR'];
1.139     bowersj2 3012:         my $xmlfrag = <<CHOOSE_FROM_SUBDIR;
1.482     albertel 3013:   <state name="CHOOSE_FROM_SUBDIR" title="Select File(s) from <b><small>$pretty_dir</small></b> to print">
1.458     www      3014: 
1.138     bowersj2 3015:     <files variable="FILES" multichoice='1'>
1.144     bowersj2 3016:       <nextstate>PAGESIZE</nextstate>
1.138     bowersj2 3017:       <filechoice>return '$subdir';</filechoice>
1.139     bowersj2 3018: CHOOSE_FROM_SUBDIR
                   3019:         
1.238     bowersj2 3020:         # this is broken up because I really want interpolation above,
                   3021:         # and I really DON'T want it below
1.139     bowersj2 3022:         $xmlfrag .= <<'CHOOSE_FROM_SUBDIR';
1.225     bowersj2 3023:       <filefilter>return Apache::lonhelper::files::not_old_version($filename) &&
                   3024: 	  $filename =~ m/\.(problem|exam|quiz|assess|survey|form|library)$/;
1.131     bowersj2 3025:       </filefilter>
1.138     bowersj2 3026:       </files>
1.131     bowersj2 3027:     </state>
                   3028: CHOOSE_FROM_SUBDIR
1.139     bowersj2 3029:         &Apache::lonxml::xmlparse($r, 'helper', $xmlfrag);
1.131     bowersj2 3030:     }
1.238     bowersj2 3031: 
                   3032:     # Allow the user to select any sequence in the course, feed it to
                   3033:     # another resource selector for that sequence
1.483     foxr     3034:     if (!$helper->{VARS}->{'construction'} && !$is_published) {
1.509     albertel 3035: 	push @$printChoices, [&mtn("Selected <b>Resources</b> from <b>selected folder</b> in course"),
1.249     sakharuk 3036: 			      'select_sequences', 'CHOOSE_SEQUENCE'];
1.244     bowersj2 3037: 	my $escapedSequenceName = $helper->{VARS}->{'SEQUENCE'};
                   3038: 	#Escape apostrophes and backslashes for Perl
                   3039: 	$escapedSequenceName =~ s/\\/\\\\/g;
                   3040: 	$escapedSequenceName =~ s/'/\\'/g;
1.239     bowersj2 3041: 	&Apache::lonxml::xmlparse($r, 'helper', <<CHOOSE_FROM_ANY_SEQUENCE);
1.238     bowersj2 3042:   <state name="CHOOSE_SEQUENCE" title="Select Sequence To Print From">
                   3043:     <message>Select the sequence to print resources from:</message>
                   3044:     <resource variable="SEQUENCE">
                   3045:       <nextstate>CHOOSE_FROM_ANY_SEQUENCE</nextstate>
                   3046:       <filterfunc>return \$res->is_sequence;</filterfunc>
                   3047:       <valuefunc>return $urlValue;</valuefunc>
1.447     foxr     3048:       <choicefunc>return \$res->hasResource(\$res,sub { return !\$_[0]->is_sequence() },0,0);
1.391     foxr     3049: 	</choicefunc>
1.238     bowersj2 3050:       </resource>
                   3051:     </state>
                   3052:   <state name="CHOOSE_FROM_ANY_SEQUENCE" title="Select Resources To Print">
                   3053:     <message>(mark desired resources then click "next" button) <br /></message>
1.435     foxr     3054:     <resource variable="RESOURCES" multichoice="1" toponly='1' addstatus="1"
1.287     albertel 3055:               closeallpages="1">
1.238     bowersj2 3056:       <nextstate>PAGESIZE</nextstate>
1.466     albertel 3057:       <filterfunc>return $isNotMap</filterfunc>
1.244     bowersj2 3058:       <mapurl evaluate='1'>return '$escapedSequenceName';</mapurl>
1.238     bowersj2 3059:       <valuefunc>return $symbFilter;</valuefunc>
1.465     albertel 3060:       $start_new_option
1.238     bowersj2 3061:       </resource>
                   3062:     </state>
                   3063: CHOOSE_FROM_ANY_SEQUENCE
1.239     bowersj2 3064: }
1.481     albertel 3065: 
1.131     bowersj2 3066:     # Generate the first state, to select which resources get printed.
1.223     bowersj2 3067:     Apache::lonhelper::state->new("START", "Select Printing Options:");
1.131     bowersj2 3068:     $paramHash = Apache::lonhelper::getParamHash();
1.155     sakharuk 3069:     $paramHash->{MESSAGE_TEXT} = "";
1.131     bowersj2 3070:     Apache::lonhelper::message->new();
                   3071:     $paramHash = Apache::lonhelper::getParamHash();
                   3072:     $paramHash->{'variable'} = 'PRINT_TYPE';
                   3073:     $paramHash->{CHOICES} = $printChoices;
                   3074:     Apache::lonhelper::choices->new();
1.161     bowersj2 3075: 
1.223     bowersj2 3076:     my $startedTable = 0; # have we started an HTML table yet? (need
                   3077:                           # to close it later)
                   3078: 
1.397     albertel 3079:     if (($perm{'pav'} and &Apache::lonnet::allowed('vgr',$env{'request.course.id'})) or 
1.170     sakharuk 3080: 	($helper->{VARS}->{'construction'} eq '1')) {
1.497     www      3081: 	addMessage("<hr width='33%' /><table><tr><td align='right'>".
                   3082:                    '<label for="ANSWER_TYPE_forminput">'.
                   3083:                    &mt('Print').
                   3084:                    "</label>: </td><td>");
1.161     bowersj2 3085:         $paramHash = Apache::lonhelper::getParamHash();
1.162     sakharuk 3086: 	$paramHash->{'variable'} = 'ANSWER_TYPE';   
                   3087: 	$helper->declareVar('ANSWER_TYPE');         
1.161     bowersj2 3088:         $paramHash->{CHOICES} = [
1.242     sakharuk 3089:                                    ['Without Answers', 'yes'],
                   3090:                                    ['With Answers', 'no'],
1.368     albertel 3091:                                    ['Only Answers', 'only']
1.289     sakharuk 3092:                                 ];
1.210     sakharuk 3093:         Apache::lonhelper::dropdown->new();
1.223     bowersj2 3094: 	addMessage("</td></tr>");
                   3095: 	$startedTable = 1;
1.161     bowersj2 3096:     }
1.209     sakharuk 3097: 
1.397     albertel 3098:     if ($perm{'pav'}) {
1.223     bowersj2 3099: 	if (!$startedTable) {
1.497     www      3100: 	    addMessage("<hr width='33%' /><table><tr><td align='right'>".
                   3101:                        '<label for="LATEX_TYPE_forminput">'.
                   3102:                        &mt('LaTeX mode').
                   3103:                        "</label>: </td><td>");
1.223     bowersj2 3104: 	    $startedTable = 1;
                   3105: 	} else {
1.497     www      3106: 	    addMessage("<tr><td align='right'>".
                   3107:                        '<label for="LATEX_TYPE_forminput">'.
                   3108:                         &mt('LaTeX mode').
                   3109:                        "</label>: </td><td>");
1.223     bowersj2 3110: 	}
1.203     sakharuk 3111:         $paramHash = Apache::lonhelper::getParamHash();
                   3112: 	$paramHash->{'variable'} = 'LATEX_TYPE';   
                   3113: 	$helper->declareVar('LATEX_TYPE');  
                   3114: 	if ($helper->{VARS}->{'construction'} eq '1') {       
                   3115: 	    $paramHash->{CHOICES} = [
1.223     bowersj2 3116: 				     ['standard LaTeX mode', 'standard'], 
                   3117: 				     ['LaTeX batchmode', 'batchmode'], ];
1.203     sakharuk 3118: 	} else {
                   3119: 	    $paramHash->{CHOICES} = [
1.223     bowersj2 3120: 				     ['LaTeX batchmode', 'batchmode'],
                   3121: 				     ['standard LaTeX mode', 'standard'] ];
1.203     sakharuk 3122: 	}
1.210     sakharuk 3123:         Apache::lonhelper::dropdown->new();
1.218     sakharuk 3124:  
1.497     www      3125: 	addMessage("</td></tr><tr><td align='right'>".
1.506     albertel 3126:                    '<label for="TABLE_CONTENTS_forminput">'.
1.497     www      3127:                    &mt('Print Table of Contents').
                   3128:                    "</label>: </td><td>");
1.209     sakharuk 3129:         $paramHash = Apache::lonhelper::getParamHash();
                   3130: 	$paramHash->{'variable'} = 'TABLE_CONTENTS';   
                   3131: 	$helper->declareVar('TABLE_CONTENTS');         
                   3132:         $paramHash->{CHOICES} = [
1.223     bowersj2 3133:                                    ['No', 'no'],
                   3134:                                    ['Yes', 'yes'] ];
1.210     sakharuk 3135:         Apache::lonhelper::dropdown->new();
1.223     bowersj2 3136: 	addMessage("</td></tr>");
1.214     sakharuk 3137:         
1.220     sakharuk 3138: 	if (not $helper->{VARS}->{'construction'}) {
1.497     www      3139: 	    addMessage("<tr><td align='right'>".
                   3140:                        '<label for="TABLE_INDEX_forminput">'.
                   3141:                        &mt('Print Index').
                   3142:                        "</label>: </td><td>");
1.220     sakharuk 3143: 	    $paramHash = Apache::lonhelper::getParamHash();
                   3144: 	    $paramHash->{'variable'} = 'TABLE_INDEX';   
                   3145: 	    $helper->declareVar('TABLE_INDEX');         
                   3146: 	    $paramHash->{CHOICES} = [
1.223     bowersj2 3147: 				     ['No', 'no'],
                   3148: 				     ['Yes', 'yes'] ];
1.220     sakharuk 3149: 	    Apache::lonhelper::dropdown->new();
1.223     bowersj2 3150: 	    addMessage("</td></tr>");
1.497     www      3151: 	    addMessage("<tr><td align='right'>".
                   3152:                        '<label for="PRINT_DISCUSSIONS_forminput">'.
                   3153:                        &mt('Print Discussions').
                   3154:                        "</label>: </td><td>");
1.309     sakharuk 3155: 	    $paramHash = Apache::lonhelper::getParamHash();
                   3156: 	    $paramHash->{'variable'} = 'PRINT_DISCUSSIONS';   
                   3157: 	    $helper->declareVar('PRINT_DISCUSSIONS');         
                   3158: 	    $paramHash->{CHOICES} = [
                   3159: 				     ['No', 'no'],
                   3160: 				     ['Yes', 'yes'] ];
                   3161: 	    Apache::lonhelper::dropdown->new();
                   3162: 	    addMessage("</td></tr>");
1.372     foxr     3163: 
1.511     foxr     3164: 	    # Prompt for printing annotations too.
                   3165: 		
                   3166: 	    addMessage("<tr><td align='right'>".
                   3167: 		       '<label for="PRINT_ANNOTATIONS_forminput">'.
                   3168: 		       &mt('Print Annotations').
                   3169: 		       "</label>:</td><td>");
                   3170: 	    $paramHash = Apache::lonhelper::getParamHash();
                   3171: 	    $paramHash->{'variable'} = "PRINT_ANNOTATIONS";
                   3172: 	    $helper->declareVar("PRINT_ANNOTATIONS");
                   3173: 	    $paramHash->{CHOICES} = [
                   3174: 				     ['No', 'no'],
                   3175: 				     ['Yes', 'yes']];
                   3176: 	    Apache::lonhelper::dropdown->new();
                   3177: 	    addMessage("</td></tr>");
                   3178: 
1.397     albertel 3179: 	    addMessage("<tr><td align = 'right'>  </td><td>");
                   3180: 	    $paramHash = Apache::lonhelper::getParamHash();
                   3181: 	    $paramHash->{'multichoice'} = "true";
                   3182: 	    $paramHash->{'allowempty'}  = "true";
                   3183: 	    $paramHash->{'variable'}   = "showallfoils";
                   3184: 	    $paramHash->{'CHOICES'} = [ ["Show all foils", "1"] ];
                   3185: 	    Apache::lonhelper::choices->new();
                   3186: 	    addMessage("</td></tr>");
1.220     sakharuk 3187: 	}
1.219     sakharuk 3188: 
1.230     albertel 3189: 	if ($helper->{'VARS'}->{'construction'}) { 
1.505     albertel 3190: 	    my $stylevalue='$Apache::lonnet::env{"construct.style"}';
1.497     www      3191:             my $randseedtext=&mt("Use random seed");
                   3192:             my $stylefiletext=&mt("Use style file");
1.506     albertel 3193:             my $selectfiletext=&mt("Select style file");
1.497     www      3194: 
1.265     sakharuk 3195: 	    my $xmlfrag .= <<"RNDSEED";
1.497     www      3196: 	    <message><tr><td align='right'>
                   3197:             <label for="curseed_forminput">$randseedtext</label>:
                   3198:             </td><td></message>
1.230     albertel 3199: 	    <string variable="curseed" size="15" maxlength="15">
                   3200: 		<defaultvalue>
                   3201: 	            return $helper->{VARS}->{'curseed'};
                   3202: 	        </defaultvalue>
1.262     sakharuk 3203: 	    </string>
1.497     www      3204: 	     <message></td></tr><tr><td align="right">
1.503     albertel 3205:              <label for="style_file">$stylefiletext</label>:
1.497     www      3206:              </td><td></message>
1.504     albertel 3207:              <string variable="style_file" size="40">
                   3208: 		<defaultvalue>
1.505     albertel 3209: 	            return $stylevalue;
1.504     albertel 3210: 	        </defaultvalue>
1.506     albertel 3211:              </string><message>&nbsp; <a href="javascript:openbrowser('helpform','style_file_forminput','sty')">$selectfiletext</a> </td></tr><tr><td></td><td align="left"></message>
1.371     foxr     3212: 	     <choices allowempty="1" multichoice="true" variable="showallfoils">
1.506     albertel 3213:                 <choice computer="1">Show all foils</choice>
1.371     foxr     3214:              </choices>
1.378     albertel 3215: 	     <message></td></tr></message>
1.230     albertel 3216: RNDSEED
                   3217:             &Apache::lonxml::xmlparse($r, 'helper', $xmlfrag);
1.512     foxr     3218: 
                   3219: 
                   3220: 	    addMessage("<tr><td>Problem Type:</td><td>");
                   3221: 	    #
                   3222: 	    # Initial value from construction space:
                   3223: 	    #
                   3224: 	    if (!$helper->{VARS}->{'probstatus'} && $env{'form.problemtype'}) {
                   3225: 		$helper->{VARS}->{'probstatus'} = $env{'form.problemtype'};	# initial value
                   3226: 	    }
1.518     foxr     3227: 	    $xmlfrag = << "PROBTYPE";
                   3228: 		<dropdown variable="probstatus" multichoice="0" allowempty="0">
                   3229: 		   <defaultvalue>
                   3230: 		      return "$helper->{VARS}->{'probstatus'}";
                   3231:                    </defaultvalue>
                   3232: 		   <choice computer="problem">Homework Problem</choice>
                   3233: 		   <choice computer="exam">Exam Problem</choice>
                   3234: 		   <choice computer="survey">Survey question</choice>
                   3235: 		</dropdown>
                   3236: PROBTYPE
                   3237:             &Apache::lonxml::xmlparse($r, 'helper', $xmlfrag);
                   3238: 	    
1.512     foxr     3239: 	    addMessage("</td></tr>"); 
                   3240: 
1.372     foxr     3241: 	} 
1.223     bowersj2 3242:     }
1.264     sakharuk 3243: 
                   3244: 
                   3245: 
1.218     sakharuk 3246: 
1.223     bowersj2 3247:     if ($startedTable) {
                   3248: 	addMessage("</table>");
1.215     sakharuk 3249:     }
1.161     bowersj2 3250: 
1.131     bowersj2 3251:     Apache::lonprintout::page_format_state->new("FORMAT");
                   3252: 
1.144     bowersj2 3253:     # Generate the PAGESIZE state which will offer the user the margin
                   3254:     # choices if they select one column
                   3255:     Apache::lonhelper::state->new("PAGESIZE", "Set Margins");
                   3256:     Apache::lonprintout::page_size_state->new('pagesize', 'FORMAT', 'FINAL');
                   3257: 
                   3258: 
1.131     bowersj2 3259:     $helper->process();
                   3260: 
1.416     foxr     3261: 
1.131     bowersj2 3262:     # MANUAL BAILOUT CONDITION:
                   3263:     # If we're in the "final" state, bailout and return to handler
                   3264:     if ($helper->{STATE} eq 'FINAL') {
                   3265:         return $helper;
                   3266:     }    
1.130     sakharuk 3267: 
1.131     bowersj2 3268:     $r->print($helper->display());
1.395     www      3269:     if ($helper->{STATE} eq 'START') {
                   3270: 	&recently_generated($r);
                   3271:     }
1.333     albertel 3272:     &Apache::lonhelper::unregisterHelperTags();
1.115     bowersj2 3273: 
                   3274:     return OK;
                   3275: }
                   3276: 
1.1       www      3277: 
                   3278: 1;
1.119     bowersj2 3279: 
                   3280: package Apache::lonprintout::page_format_state;
                   3281: 
                   3282: =pod
                   3283: 
1.131     bowersj2 3284: =head1 Helper element: page_format_state
                   3285: 
                   3286: See lonhelper.pm documentation for discussion of the helper framework.
1.119     bowersj2 3287: 
1.131     bowersj2 3288: Apache::lonprintout::page_format_state is an element that gives the 
                   3289: user an opportunity to select the page layout they wish to print 
                   3290: with: Number of columns, portrait/landscape, and paper size. If you 
                   3291: want to change the paper size choices, change the @paperSize array 
                   3292: contents in this package.
1.119     bowersj2 3293: 
1.131     bowersj2 3294: page_format_state is always directly invoked in lonprintout.pm, so there
                   3295: is no tag interface. You actually pass parameters to the constructor.
1.119     bowersj2 3296: 
                   3297: =over 4
                   3298: 
1.131     bowersj2 3299: =item * B<new>(varName): varName is where the print information will be stored in the format FIXME.
1.119     bowersj2 3300: 
                   3301: =back
                   3302: 
                   3303: =cut
                   3304: 
1.131     bowersj2 3305: use Apache::lonhelper;
1.119     bowersj2 3306: 
                   3307: no strict;
1.131     bowersj2 3308: @ISA = ("Apache::lonhelper::element");
1.119     bowersj2 3309: use strict;
1.266     sakharuk 3310: use Apache::lonlocal;
1.373     albertel 3311: use Apache::lonnet;
1.119     bowersj2 3312: 
                   3313: my $maxColumns = 2;
1.376     albertel 3314: # it'd be nice if these all worked
                   3315: #my @paperSize = ("letter [8 1/2x11 in]", "legal [8 1/2x14 in]", 
                   3316: #                 "tabloid (ledger) [11x17 in]", "executive [7 1/2x10 in]",
                   3317: #                 "a2 [420x594 mm]", "a3 [297x420 mm]", "a4 [210x297 mm]", 
                   3318: #                 "a5 [148x210 mm]", "a6 [105x148 mm]" );
1.326     sakharuk 3319: my @paperSize = ("letter [8 1/2x11 in]", "legal [8 1/2x14 in]", 
1.376     albertel 3320: 		 "a4 [210x297 mm]");
1.119     bowersj2 3321: 
                   3322: # Tentative format: Orientation (L = Landscape, P = portrait) | Colnum |
                   3323: #                   Paper type
                   3324: 
                   3325: sub new { 
1.131     bowersj2 3326:     my $self = Apache::lonhelper::element->new();
1.119     bowersj2 3327: 
1.135     bowersj2 3328:     shift;
                   3329: 
1.131     bowersj2 3330:     $self->{'variable'} = shift;
1.134     bowersj2 3331:     my $helper = Apache::lonhelper::getHelper();
1.135     bowersj2 3332:     $helper->declareVar($self->{'variable'});
1.131     bowersj2 3333:     bless($self);
1.119     bowersj2 3334:     return $self;
                   3335: }
                   3336: 
                   3337: sub render {
                   3338:     my $self = shift;
1.131     bowersj2 3339:     my $helper = Apache::lonhelper::getHelper();
1.119     bowersj2 3340:     my $result = '';
1.131     bowersj2 3341:     my $var = $self->{'variable'};
1.266     sakharuk 3342:     my $PageLayout=&mt('Page layout');
                   3343:     my $NumberOfColumns=&mt('Number of columns');
                   3344:     my $PaperType=&mt('Paper type');
1.506     albertel 3345:     my $landscape=&mt('Landscape');
                   3346:     my $portrait=&mt('Portrait');
1.119     bowersj2 3347:     $result .= <<STATEHTML;
                   3348: 
1.223     bowersj2 3349: <hr width="33%" />
1.119     bowersj2 3350: <table cellpadding="3">
                   3351:   <tr>
1.266     sakharuk 3352:     <td align="center"><b>$PageLayout</b></td>
                   3353:     <td align="center"><b>$NumberOfColumns</b></td>
                   3354:     <td align="center"><b>$PaperType</b></td>
1.119     bowersj2 3355:   </tr>
                   3356:   <tr>
                   3357:     <td>
1.506     albertel 3358:       <label><input type="radio" name="${var}.layout" value="L" /> $landscape </label><br />
                   3359:       <label><input type="radio" name="${var}.layout" value="P" checked='1'  /> $portrait </label>
1.119     bowersj2 3360:     </td>
1.155     sakharuk 3361:     <td align="center">
1.119     bowersj2 3362:       <select name="${var}.cols">
                   3363: STATEHTML
                   3364: 
                   3365:     my $i;
                   3366:     for ($i = 1; $i <= $maxColumns; $i++) {
1.144     bowersj2 3367:         if ($i == 2) {
1.119     bowersj2 3368:             $result .= "<option value='$i' selected>$i</option>\n";
                   3369:         } else {
                   3370:             $result .= "<option value='$i'>$i</option>\n";
                   3371:         }
                   3372:     }
                   3373: 
                   3374:     $result .= "</select></td><td>\n";
                   3375:     $result .= "<select name='${var}.paper'>\n";
                   3376: 
1.373     albertel 3377:     my %parmhash=&Apache::lonnet::coursedescription($env{'request.course.id'});
1.398     albertel 3378:     my $DefaultPaperSize=lc($parmhash{'default_paper_size'});
                   3379:     $DefaultPaperSize=~s/\s//g;
1.304     sakharuk 3380:     if ($DefaultPaperSize eq '') {$DefaultPaperSize='letter';}
1.119     bowersj2 3381:     $i = 0;
                   3382:     foreach (@paperSize) {
1.326     sakharuk 3383: 	$_=~/(\w+)/;
                   3384: 	my $papersize=$1;
1.304     sakharuk 3385:         if ($paperSize[$i]=~/$DefaultPaperSize/) {
1.326     sakharuk 3386:             $result .= "<option selected value='$papersize'>" . $paperSize[$i] . "</option>\n";
1.119     bowersj2 3387:         } else {
1.326     sakharuk 3388:             $result .= "<option value='$papersize'>" . $paperSize[$i] . "</option>\n";
1.119     bowersj2 3389:         }
                   3390:         $i++;
                   3391:     }
                   3392:     $result .= "</select></td></tr></table>";
                   3393:     return $result;
1.135     bowersj2 3394: }
                   3395: 
                   3396: sub postprocess {
                   3397:     my $self = shift;
                   3398: 
                   3399:     my $var = $self->{'variable'};
1.136     bowersj2 3400:     my $helper = Apache::lonhelper->getHelper();
1.135     bowersj2 3401:     $helper->{VARS}->{$var} = 
1.373     albertel 3402:         $env{"form.$var.layout"} . '|' . $env{"form.$var.cols"} . '|' .
                   3403:         $env{"form.$var.paper"};
1.135     bowersj2 3404:     return 1;
1.119     bowersj2 3405: }
                   3406: 
                   3407: 1;
1.144     bowersj2 3408: 
                   3409: package Apache::lonprintout::page_size_state;
                   3410: 
                   3411: =pod
                   3412: 
                   3413: =head1 Helper element: page_size_state
                   3414: 
                   3415: See lonhelper.pm documentation for discussion of the helper framework.
                   3416: 
                   3417: Apache::lonprintout::page_size_state is an element that gives the 
                   3418: user the opportunity to further refine the page settings if they
                   3419: select a single-column page.
                   3420: 
                   3421: page_size_state is always directly invoked in lonprintout.pm, so there
                   3422: is no tag interface. You actually pass parameters to the constructor.
                   3423: 
                   3424: =over 4
                   3425: 
                   3426: =item * B<new>(varName): varName is where the print information will be stored in the format FIXME.
                   3427: 
                   3428: =back
                   3429: 
                   3430: =cut
                   3431: 
                   3432: use Apache::lonhelper;
1.373     albertel 3433: use Apache::lonnet;
1.144     bowersj2 3434: no strict;
                   3435: @ISA = ("Apache::lonhelper::element");
                   3436: use strict;
                   3437: 
                   3438: 
                   3439: 
                   3440: sub new { 
                   3441:     my $self = Apache::lonhelper::element->new();
                   3442: 
                   3443:     shift; # disturbs me (probably prevents subclassing) but works (drops
                   3444:            # package descriptor)... - Jeremy
                   3445: 
                   3446:     $self->{'variable'} = shift;
                   3447:     my $helper = Apache::lonhelper::getHelper();
                   3448:     $helper->declareVar($self->{'variable'});
                   3449: 
                   3450:     # The variable name of the format element, so we can look into 
                   3451:     # $helper->{VARS} to figure out whether the columns are one or two
                   3452:     $self->{'formatvar'} = shift;
                   3453: 
1.463     foxr     3454: 
1.144     bowersj2 3455:     $self->{NEXTSTATE} = shift;
                   3456:     bless($self);
1.467     foxr     3457: 
1.144     bowersj2 3458:     return $self;
                   3459: }
                   3460: 
                   3461: sub render {
                   3462:     my $self = shift;
                   3463:     my $helper = Apache::lonhelper::getHelper();
                   3464:     my $result = '';
                   3465:     my $var = $self->{'variable'};
                   3466: 
1.467     foxr     3467: 
                   3468: 
1.144     bowersj2 3469:     if (defined $self->{ERROR_MSG}) {
1.464     albertel 3470:         $result .= '<br /><span class="LC_error">' . $self->{ERROR_MSG} . '</span><br />';
1.144     bowersj2 3471:     }
                   3472: 
1.438     foxr     3473:     my $format = $helper->{VARS}->{$self->{'formatvar'}};
1.463     foxr     3474: 
                   3475:     # Use format to get sensible defaults for the margins:
                   3476: 
                   3477: 
                   3478:     my ($laystyle, $cols, $papersize) = split(/\|/, $format);
                   3479:     ($papersize)                      = split(/ /, $papersize);
                   3480: 
                   3481: 
                   3482:     if ($laystyle eq 'L') {
                   3483: 	$laystyle = 'album';
                   3484:     } else {
                   3485: 	$laystyle = 'book';
                   3486:     }
                   3487: 
                   3488: 
1.464     albertel 3489:     my %size;
                   3490:     ($size{'width_and_units'},
                   3491:      $size{'height_and_units'},
                   3492:      $size{'margin_and_units'})=
                   3493: 	 &Apache::lonprintout::page_format($papersize, $laystyle, $cols);
1.463     foxr     3494:     
1.464     albertel 3495:     foreach my $dimension ('width','height','margin') {
                   3496: 	($size{$dimension},$size{$dimension.'_unit'}) =
                   3497: 	    split(/ +/, $size{$dimension.'_and_units'},2);
                   3498:        	
                   3499: 	foreach my $unit ('cm','in') {
                   3500: 	    $size{$dimension.'_options'} .= '<option ';
                   3501: 	    if ($size{$dimension.'_unit'} eq $unit) {
                   3502: 		$size{$dimension.'_options'} .= 'selected="selected" ';
                   3503: 	    }
                   3504: 	    $size{$dimension.'_options'} .= '>'.$unit.'</option>';
                   3505: 	}
1.438     foxr     3506:     }
                   3507: 
1.470     foxr     3508:     # Adjust margin for LaTeX margin: .. requires units == cm or in.
                   3509: 
                   3510:     if ($size{'margin_unit'} eq 'in') {
                   3511: 	$size{'margin'} += 1;
                   3512:     }  else {
                   3513: 	$size{'margin'} += 2.54;
                   3514:     }
1.506     albertel 3515:     my %text = ('format' => 'How should each column be formatted?',
                   3516: 		'width'  => 'Width:',
                   3517: 		'height' => 'Height:',
                   3518: 		'margin' => 'Left Margin:',);
                   3519:     %text = &Apache::lonlocal::texthash(%text);
                   3520: 
1.144     bowersj2 3521:     $result .= <<ELEMENTHTML;
                   3522: 
1.506     albertel 3523: <p>$text{'format'}</p>
1.144     bowersj2 3524: 
                   3525: <table cellpadding='3'>
                   3526:   <tr>
1.506     albertel 3527:     <td align='right'><b>$text{'width'}</b></td>
1.464     albertel 3528:     <td align='left'><input type='text' name='$var.width' value="$size{'width'}" size='4' /></td>
1.144     bowersj2 3529:     <td align='left'>
                   3530:       <select name='$var.widthunit'>
1.464     albertel 3531:       $size{'width_options'}
1.144     bowersj2 3532:       </select>
                   3533:     </td>
                   3534:   </tr>
                   3535:   <tr>
1.506     albertel 3536:     <td align='right'><b>$text{'height'}</b></td>
1.464     albertel 3537:     <td align='left'><input type='text' name="$var.height" value="$size{'height'}" size='4' /></td>
1.144     bowersj2 3538:     <td align='left'>
                   3539:       <select name='$var.heightunit'>
1.464     albertel 3540:       $size{'height_options'}
1.144     bowersj2 3541:       </select>
                   3542:     </td>
                   3543:   </tr>
                   3544:   <tr>
1.506     albertel 3545:     <td align='right'><b>$text{'margin'}</b></td>
1.464     albertel 3546:     <td align='left'><input type='text' name='$var.lmargin' value="$size{'margin'}" size='4' /></td>
1.144     bowersj2 3547:     <td align='left'>
1.186     bowersj2 3548:       <select name='$var.lmarginunit'>
1.464     albertel 3549:       $size{'margin_options'}
1.144     bowersj2 3550:       </select>
                   3551:     </td>
                   3552:   </tr>
                   3553: </table>
                   3554: 
1.464     albertel 3555: <!--<p>Hint: Some instructors like to leave scratch space for the student by
                   3556: making the width much smaller than the width of the page.</p>-->
1.144     bowersj2 3557: 
                   3558: ELEMENTHTML
                   3559: 
                   3560:     return $result;
                   3561: }
                   3562: 
1.470     foxr     3563: 
1.144     bowersj2 3564: sub preprocess {
                   3565:     my $self = shift;
                   3566:     my $helper = Apache::lonhelper::getHelper();
                   3567: 
                   3568:     my $format = $helper->{VARS}->{$self->{'formatvar'}};
1.467     foxr     3569: 
                   3570:     #  If the user does not have 'pav' privilege, set default widths and
                   3571:     #  on to the next state right away.
                   3572:     #
                   3573:     if (!$perm{'pav'}) {
                   3574: 	my $var = $self->{'variable'};
                   3575: 	my $format = $helper->{VARS}->{$self->{'formatvar'}};
                   3576: 	
                   3577: 	my ($laystyle, $cols, $papersize) = split(/\|/, $format);
                   3578: 	($papersize)                      = split(/ /, $papersize);
                   3579: 	
                   3580: 	
                   3581: 	if ($laystyle eq 'L') {
                   3582: 	    $laystyle = 'album';
                   3583: 	} else {
                   3584: 	    $laystyle = 'book';
                   3585: 	}
                   3586: 	#  Figure out some good defaults for the print out and set them:
                   3587: 	
                   3588: 	my %size;
                   3589: 	($size{'width'},
                   3590: 	 $size{'height'},
                   3591: 	 $size{'lmargin'})=
                   3592: 	     &Apache::lonprintout::page_format($papersize, $laystyle, $cols);
                   3593: 	
                   3594: 	foreach my $dim ('width', 'height', 'lmargin') {
                   3595: 	    my ($value, $units) = split(/ /, $size{$dim});
1.470     foxr     3596: 	    	    
1.467     foxr     3597: 	    $helper->{VARS}->{"$var.".$dim}      = $value;
                   3598: 	    $helper->{VARS}->{"$var.".$dim.'unit'} = $units;
                   3599: 	    
                   3600: 	}
                   3601: 	
                   3602: 
                   3603: 	# Transition to the next state
                   3604: 
                   3605: 	$helper->changeState($self->{NEXTSTATE});
                   3606:     }
1.144     bowersj2 3607:    
                   3608:     return 1;
                   3609: }
                   3610: 
                   3611: sub postprocess {
                   3612:     my $self = shift;
                   3613: 
                   3614:     my $var = $self->{'variable'};
                   3615:     my $helper = Apache::lonhelper->getHelper();
1.373     albertel 3616:     my $width = $helper->{VARS}->{$var .'.width'} = $env{"form.${var}.width"}; 
                   3617:     my $height = $helper->{VARS}->{$var .'.height'} = $env{"form.${var}.height"}; 
                   3618:     my $lmargin = $helper->{VARS}->{$var .'.lmargin'} = $env{"form.${var}.lmargin"}; 
                   3619:     $helper->{VARS}->{$var .'.widthunit'} = $env{"form.${var}.widthunit"}; 
                   3620:     $helper->{VARS}->{$var .'.heightunit'} = $env{"form.${var}.heightunit"}; 
                   3621:     $helper->{VARS}->{$var .'.lmarginunit'} = $env{"form.${var}.lmarginunit"}; 
1.144     bowersj2 3622: 
                   3623:     my $error = '';
                   3624: 
                   3625:     # /^-?[0-9]+(\.[0-9]*)?$/ -> optional minus, at least on digit, followed 
                   3626:     # by an optional period, followed by digits, ending the string
                   3627: 
1.464     albertel 3628:     if ($width !~  /^-?[0-9]*(\.[0-9]*)?$/) {
1.144     bowersj2 3629:         $error .= "Invalid width; please type only a number.<br />\n";
                   3630:     }
1.464     albertel 3631:     if ($height !~  /^-?[0-9]*(\.[0-9]*)?$/) {
1.144     bowersj2 3632:         $error .= "Invalid height; please type only a number.<br />\n";
                   3633:     }
1.464     albertel 3634:     if ($lmargin !~  /^-?[0-9]*(\.[0-9]*)?$/) {
1.144     bowersj2 3635:         $error .= "Invalid left margin; please type only a number.<br />\n";
1.470     foxr     3636:     } else {
                   3637: 	# Adjust for LaTeX 1.0 inch margin:
                   3638: 
                   3639: 	if ($env{"form.${var}.lmarginunit"} eq "in") {
                   3640: 	    $helper->{VARS}->{$var.'.lmargin'} = $lmargin - 1;
                   3641: 	} else {
                   3642: 	    $helper->{VARS}->{$var.'.lmargin'} = $lmargin - 2.54;
                   3643: 	}
1.144     bowersj2 3644:     }
                   3645: 
                   3646:     if (!$error) {
                   3647:         Apache::lonhelper::getHelper()->changeState($self->{NEXTSTATE});
                   3648:         return 1;
                   3649:     } else {
                   3650:         $self->{ERROR_MSG} = $error;
                   3651:         return 0;
                   3652:     }
                   3653: }
                   3654: 
                   3655: 
1.119     bowersj2 3656: 
1.1       www      3657: __END__
1.6       sakharuk 3658: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>