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

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

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