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

1.389     foxr        1: # The LearningOnline Network
1.1       www         2: # Printout
                      3: #
1.518   ! foxr        4: # $Id: lonprintout.pm,v 1.517 2008/03/10 08:54:19 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: 
1.518   ! foxr     2487: 
        !          2488:    
        !          2489: 
        !          2490: 
1.363     foxr     2491:     #  The page breaks can get loaded initially from the course environment:
1.394     foxr     2492:     # But we only do this in the initial state so that they are allowed to change.
                   2493:     #
1.366     foxr     2494: 
1.416     foxr     2495:     # $helper->{VARS}->{FINISHPAGE} = '';
1.363     foxr     2496:     
                   2497:     &Apache::loncommon::restore_course_settings('print',
1.366     foxr     2498: 						{'pagebreaks'  => 'scalar',
                   2499: 					         'lastprinttype' => 'scalar'});
                   2500:     
1.483     foxr     2501:     # This will persistently load in the data we want from the
                   2502:     # very first screen.
1.394     foxr     2503:     
                   2504:     if($helper->{VARS}->{PRINT_TYPE} eq $env{'form.lastprinttype'}) {
                   2505: 	if (!defined ($env{"form.CURRENT_STATE"})) {
                   2506: 	    
                   2507: 	    $helper->{VARS}->{FINISHPAGE} = $env{'form.pagebreaks'};
                   2508: 	} else {
                   2509: 	    my $state = $env{"form.CURRENT_STATE"};
                   2510: 	    if ($state eq "START") {
                   2511: 		$helper->{VARS}->{FINISHPAGE} = $env{'form.pagebreaks'};
                   2512: 	    }
                   2513: 	}
                   2514: 	
1.366     foxr     2515:     }
1.481     albertel 2516: 
1.483     foxr     2517: 
1.156     bowersj2 2518:     # Detect whether we're coming from construction space
1.373     albertel 2519:     if ($env{'form.postdata'}=~/^(?:http:\/\/[^\/]+\/|\/|)\~([^\/]+)\/(.*)$/) {
1.235     bowersj2 2520:         $helper->{VARS}->{'filename'} = "~$1/$2";
1.156     bowersj2 2521:         $helper->{VARS}->{'construction'} = 1;
1.481     albertel 2522:     } else {
1.373     albertel 2523:         if ($env{'form.postdata'}) {
                   2524:             $helper->{VARS}->{'symb'} = &Apache::lonnet::symbread($env{'form.postdata'});
1.482     albertel 2525: 	    if ( $helper->{VARS}->{'symb'} eq '') {
                   2526: 		$helper->{VARS}->{'postdata'} = $env{'form.postdata'};
                   2527: 	    }
1.156     bowersj2 2528:         }
1.373     albertel 2529:         if ($env{'form.symb'}) {
                   2530:             $helper->{VARS}->{'symb'} = $env{'form.symb'};
1.156     bowersj2 2531:         }
1.373     albertel 2532:         if ($env{'form.url'}) {
1.156     bowersj2 2533:             $helper->{VARS}->{'symb'} = &Apache::lonnet::symbread($helper->{VARS}->{'postdata'});
                   2534:         }
1.416     foxr     2535: 
1.157     bowersj2 2536:     }
1.481     albertel 2537: 
1.373     albertel 2538:     if ($env{'form.symb'}) {
                   2539:         $helper->{VARS}->{'symb'} = $env{'form.symb'};
1.146     bowersj2 2540:     }
1.373     albertel 2541:     if ($env{'form.url'}) {
1.140     sakharuk 2542:         $helper->{VARS}->{'symb'} = &Apache::lonnet::symbread($helper->{VARS}->{'postdata'});
1.153     sakharuk 2543: 
1.140     sakharuk 2544:     }
1.343     albertel 2545:     $helper->{VARS}->{'symb'}=
                   2546: 	&Apache::lonenc::check_encrypt($helper->{VARS}->{'symb'});
1.335     albertel 2547:     my ($resourceTitle,$sequenceTitle,$mapTitle) = &details_for_menu($helper);
1.178     sakharuk 2548:     if ($sequenceTitle ne '') {$helper->{VARS}->{'assignment'}=$sequenceTitle;}
1.481     albertel 2549: 
1.156     bowersj2 2550:     
1.146     bowersj2 2551:     # Extract map
                   2552:     my $symb = $helper->{VARS}->{'symb'};
1.156     bowersj2 2553:     my ($map, $id, $url);
                   2554:     my $subdir;
1.483     foxr     2555:     my $is_published=0;		# True when printing from resource space.
1.156     bowersj2 2556: 
                   2557:     # Get the resource name from construction space
                   2558:     if ($helper->{VARS}->{'construction'}) {
                   2559:         $resourceTitle = substr($helper->{VARS}->{'filename'}, 
                   2560:                                 rindex($helper->{VARS}->{'filename'}, '/')+1);
                   2561:         $subdir = substr($helper->{VARS}->{'filename'},
                   2562:                          0, rindex($helper->{VARS}->{'filename'}, '/') + 1);
1.481     albertel 2563:     } else {
1.482     albertel 2564: 	if ($symb ne '') {
                   2565: 	    ($map, $id, $url) = &Apache::lonnet::decode_symb($symb);
                   2566: 	    $helper->{VARS}->{'postdata'} = 
                   2567: 		&Apache::lonenc::check_encrypt(&Apache::lonnet::clutter($url));
                   2568: 	} else {
                   2569: 	    $url = $helper->{VARS}->{'postdata'};
1.483     foxr     2570: 	    $is_published=1;	# From resource space.
1.482     albertel 2571: 	}
                   2572: 	$url = &Apache::lonnet::clutter($url);
1.481     albertel 2573: 
1.156     bowersj2 2574:         if (!$resourceTitle) { # if the resource doesn't have a title, use the filename
1.238     bowersj2 2575:             my $postdata = $helper->{VARS}->{'postdata'};
                   2576:             $resourceTitle = substr($postdata, rindex($postdata, '/') + 1);
1.156     bowersj2 2577:         }
                   2578:         $subdir = &Apache::lonnet::filelocation("", $url);
1.128     bowersj2 2579:     }
1.373     albertel 2580:     if (!$helper->{VARS}->{'curseed'} && $env{'form.curseed'}) {
                   2581: 	$helper->{VARS}->{'curseed'}=$env{'form.curseed'};
1.230     albertel 2582:     }
1.373     albertel 2583:     if (!$helper->{VARS}->{'probstatus'} && $env{'form.problemtype'}) {
1.512     foxr     2584: 	$helper->{VARS}->{'probstatus'}=$env{'form.problemstatus'};
1.290     sakharuk 2585:     }
1.115     bowersj2 2586: 
1.192     bowersj2 2587:     my $userCanSeeHidden = Apache::lonnavmaps::advancedUser();
                   2588: 
1.481     albertel 2589:     Apache::lonhelper::registerHelperTags();
1.119     bowersj2 2590: 
1.131     bowersj2 2591:     # "Delete everything after the last slash."
1.119     bowersj2 2592:     $subdir =~ s|/[^/]+$||;
                   2593: 
1.131     bowersj2 2594:     # What can be printed is a very dynamic decision based on
                   2595:     # lots of factors. So we need to dynamically build this list.
                   2596:     # To prevent security leaks, states are only added to the wizard
                   2597:     # if they can be reached, which ensures manipulating the form input
                   2598:     # won't allow anyone to reach states they shouldn't have permission
                   2599:     # to reach.
                   2600: 
                   2601:     # printChoices is tracking the kind of printing the user can
                   2602:     # do, and will be used in a choices construction later.
                   2603:     # In the meantime we will be adding states and elements to
                   2604:     # the helper by hand.
                   2605:     my $printChoices = [];
                   2606:     my $paramHash;
1.130     sakharuk 2607: 
1.240     albertel 2608:     if ($resourceTitle) {
1.458     www      2609:         push @{$printChoices}, ["<b><i>$resourceTitle</i></b> (".&mt('the resource you just saw on the screen').")", 'current_document', 'PAGESIZE'];
1.156     bowersj2 2610:     }
                   2611: 
1.238     bowersj2 2612:     # Useful filter strings
1.287     albertel 2613:     my $isProblem = '($res->is_problem()||$res->contains_problem) ';
1.238     bowersj2 2614:     $isProblem .= ' && !$res->randomout()' if !$userCanSeeHidden;
1.287     albertel 2615:     my $isProblemOrMap = '$res->is_problem() || $res->contains_problem() || $res->is_sequence()';
                   2616:     my $isNotMap = '!$res->is_sequence()';
1.238     bowersj2 2617:     $isNotMap .= ' && !$res->randomout()' if !$userCanSeeHidden;
                   2618:     my $isMap = '$res->is_map()';
1.342     albertel 2619:     my $symbFilter = '$res->shown_symb()';
                   2620:     my $urlValue = '$res->link()';
1.238     bowersj2 2621: 
                   2622:     $helper->declareVar('SEQUENCE');
                   2623: 
1.465     albertel 2624:     # If we're in a sequence...
1.416     foxr     2625: 
1.465     albertel 2626:     my $start_new_option;
                   2627:     if ($perm{'pav'}) {
                   2628: 	$start_new_option = 
                   2629: 	    "<option text='".&mt('Start new page<br />before selected').
                   2630: 	    "' variable='FINISHPAGE' />";
                   2631:     }
1.238     bowersj2 2632: 
1.483     foxr     2633:     if (($helper->{'VARS'}->{'construction'} ne '1' ) &&
1.350     foxr     2634: 
1.243     bowersj2 2635: 	$helper->{VARS}->{'postdata'} &&
                   2636: 	$helper->{VARS}->{'assignment'}) {
1.131     bowersj2 2637:         # Allow problems from sequence
1.458     www      2638:         push @{$printChoices}, [&mt('Selected <b>Problems</b> in folder <b><i>[_1]</i></b>',$sequenceTitle), 'map_problems', 'CHOOSE_PROBLEMS'];
1.131     bowersj2 2639:         # Allow all resources from sequence
1.458     www      2640:         push @{$printChoices}, [&mt('Selected <b>Resources</b> in folder <b><i>[_1]</i></b>',$sequenceTitle), 'map_problems_pages', 'CHOOSE_PROBLEMS_HTML'];
1.465     albertel 2641: 
1.131     bowersj2 2642:         my $helperFragment = <<HELPERFRAGMENT;
1.155     sakharuk 2643:   <state name="CHOOSE_PROBLEMS" title="Select Problem(s) to print">
1.435     foxr     2644:     <resource variable="RESOURCES" multichoice="1" toponly='1' addstatus="1"
1.287     albertel 2645:               closeallpages="1">
1.144     bowersj2 2646:       <nextstate>PAGESIZE</nextstate>
1.435     foxr     2647:       <filterfunc>return $isProblem;</filterfunc>
1.131     bowersj2 2648:       <mapurl>$map</mapurl>
1.238     bowersj2 2649:       <valuefunc>return $symbFilter;</valuefunc>
1.465     albertel 2650:       $start_new_option
1.131     bowersj2 2651:       </resource>
                   2652:     </state>
                   2653: 
1.155     sakharuk 2654:   <state name="CHOOSE_PROBLEMS_HTML" title="Select Resource(s) to print">
1.435     foxr     2655:     <resource variable="RESOURCES" multichoice="1" toponly='1' addstatus="1"
1.287     albertel 2656:               closeallpages="1">
1.144     bowersj2 2657:       <nextstate>PAGESIZE</nextstate>
1.435     foxr     2658:       <filterfunc>return $isNotMap;</filterfunc>
1.131     bowersj2 2659:       <mapurl>$map</mapurl>
1.238     bowersj2 2660:       <valuefunc>return $symbFilter;</valuefunc>
1.465     albertel 2661:       $start_new_option
1.131     bowersj2 2662:       </resource>
                   2663:     </state>
                   2664: HELPERFRAGMENT
1.121     bowersj2 2665: 
1.326     sakharuk 2666: 	&Apache::lonxml::xmlparse($r, 'helper', $helperFragment);
1.121     bowersj2 2667:     }
                   2668: 
1.397     albertel 2669:     # If the user has pfo (print for otheres) allow them to print all 
1.354     foxr     2670:     # problems and resources  in the entier course, optionally for selected students
1.483     foxr     2671:     if ($perm{'pfo'} &&  !$is_published  &&
1.481     albertel 2672:         ($helper->{VARS}->{'postdata'}=~/\/res\// || $helper->{VARS}->{'postdata'}=~/\/(syllabus|smppg|aboutme|bulletinboard)$/)) { 
                   2673: 
1.509     albertel 2674:         push @{$printChoices}, [&mtn('Selected <b>Problems</b> from <b>entire course</b>'), 'all_problems', 'ALL_PROBLEMS'];
                   2675: 	push @{$printChoices}, [&mtn('Selected <b>Resources</b> from <b>entire course</b>'), 'all_resources', 'ALL_RESOURCES'];
1.284     albertel 2676:          &Apache::lonxml::xmlparse($r, 'helper', <<ALL_PROBLEMS);
1.155     sakharuk 2677:   <state name="ALL_PROBLEMS" title="Select Problem(s) to print">
1.287     albertel 2678:     <resource variable="RESOURCES" toponly='0' multichoice="1"
                   2679: 	suppressEmptySequences='0' addstatus="1" closeallpages="1">
1.144     bowersj2 2680:       <nextstate>PAGESIZE</nextstate>
1.192     bowersj2 2681:       <filterfunc>return $isProblemOrMap;</filterfunc>
1.287     albertel 2682:       <choicefunc>return $isNotMap;</choicefunc>
1.238     bowersj2 2683:       <valuefunc>return $symbFilter;</valuefunc>
1.465     albertel 2684:       $start_new_option
1.284     albertel 2685:     </resource>
                   2686:   </state>
1.354     foxr     2687:   <state name="ALL_RESOURCES" title="Select Resource(s) to print">
                   2688:     <resource variable="RESOURCES" toponly='0' multichoice='1'
                   2689:               suppressEmptySequences='0' addstatus='1' closeallpages='1'>
                   2690:       <nextstate>PAGESIZE</nextstate>
                   2691:       <filterfunc>return $isNotMap; </filterfunc>
                   2692:       <valuefunc>return $symbFilter;</valuefunc>
1.465     albertel 2693:       $start_new_option
1.354     foxr     2694:     </resource>
                   2695:   </state>
1.284     albertel 2696: ALL_PROBLEMS
1.132     bowersj2 2697: 
1.284     albertel 2698: 	if ($helper->{VARS}->{'assignment'}) {
1.483     foxr     2699: 	    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      2700: 	    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 2701: 	}
1.424     foxr     2702: 
1.507     albertel 2703: 	my $randomly_ordered_warning = 
                   2704: 	    &get_randomly_ordered_warning($helper,$map);
                   2705: 
1.424     foxr     2706: 	# resource_selector will hold a few states that:
                   2707: 	#   - Allow resources to be selected for printing.
                   2708: 	#   - Determine pagination between assignments.
                   2709: 	#   - Determine how many assignments should be bundled into a single PDF.
                   2710:         # TODO:
                   2711: 	#    Probably good to do things like separate this up into several vars, each
                   2712: 	#    with one state, and use REGEXPs at inclusion time to set state names
                   2713: 	#    and next states for better mix and match capability
                   2714: 	#
1.284     albertel 2715: 	my $resource_selector=<<RESOURCE_SELECTOR;
1.424     foxr     2716:     <state name="SELECT_PROBLEMS" title="Select resources to print">
1.507     albertel 2717:     $randomly_ordered_warning
                   2718: 
1.424     foxr     2719:    <nextstate>PRINT_FORMATTING</nextstate> 
1.284     albertel 2720:    <message><br /><big><i><b>Select resources for the assignment</b></i></big><br /></message>
1.287     albertel 2721:     <resource variable="RESOURCES" multichoice="1" addstatus="1" 
                   2722:               closeallpages="1">
1.254     sakharuk 2723:       <filterfunc>return $isProblem;</filterfunc>
1.148     bowersj2 2724:       <mapurl>$map</mapurl>
1.254     sakharuk 2725:       <valuefunc>return $symbFilter;</valuefunc>
1.465     albertel 2726:       $start_new_option
1.147     bowersj2 2727:       </resource>
1.424     foxr     2728:     </state>
                   2729:     <state name="PRINT_FORMATTING" title="How should results be printed?">
1.155     sakharuk 2730:     <message><br /><big><i><b>How should the results be printed?</b></i></big><br /></message>
1.149     bowersj2 2731:     <choices variable="EMPTY_PAGES">
1.204     sakharuk 2732:       <choice computer='0'>Start each student\'s assignment on a new page/column (add a pagefeed after each assignment)</choice>
                   2733:       <choice computer='1'>Add one empty page/column after each student\'s assignment</choice>
                   2734:       <choice computer='2'>Add two empty pages/column after each student\'s assignment</choice>
                   2735:       <choice computer='3'>Add three empty pages/column after each student\'s assignment</choice>
1.284     albertel 2736:     </choices>
1.424     foxr     2737:     <nextstate>PAGESIZE</nextstate>
1.429     foxr     2738:     <message><hr width='33%' /><b>How do you want assignments split into PDF files? </b></message>
                   2739:     <choices variable="SPLIT_PDFS">
                   2740:        <choice computer="all">All assignments in a single PDF file</choice>
                   2741:        <choice computer="sections">Each PDF contains exactly one section</choice>
                   2742:        <choice computer="oneper">Each PDF contains exactly one assignment</choice>
1.449     albertel 2743:        <choice computer="usenumber" relatedvalue="NUMBER_TO_PRINT">
                   2744:             Specify the number of assignments per PDF:</choice>
1.429     foxr     2745:     </choices>
1.424     foxr     2746:     </state>
1.284     albertel 2747: RESOURCE_SELECTOR
                   2748: 
                   2749:         &Apache::lonxml::xmlparse($r, 'helper', <<CHOOSE_STUDENTS);
                   2750:   <state name="CHOOSE_STUDENTS" title="Select Students and Resources">
1.485     albertel 2751:       <message><b>Select sorting order of printout</b> </message>
1.340     foxr     2752:     <choices variable='student_sort'>
                   2753:       <choice computer='0'>Sort by section then student</choice>
                   2754:       <choice computer='1'>Sort by students across sections.</choice>
                   2755:     </choices>
1.437     foxr     2756:       <message><br /><hr /><br /> </message>
1.425     foxr     2757:       <student multichoice='1' variable="STUDENTS" nextstate="SELECT_PROBLEMS" coursepersonnel="1"/>
1.424     foxr     2758:   </state>
1.284     albertel 2759:     $resource_selector
1.131     bowersj2 2760: CHOOSE_STUDENTS
1.292     albertel 2761: 
1.373     albertel 2762: 	my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                   2763: 	my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
1.292     albertel 2764:         my @names=&Apache::lonnet::getkeys('CODEs',$cdom,$cnum);
                   2765: 	my $namechoice='<choice></choice>';
1.337     albertel 2766: 	foreach my $name (sort {uc($a) cmp uc($b)} @names) {
1.294     albertel 2767: 	    if ($name =~ /^error: 2 /) { next; }
1.381     albertel 2768: 	    if ($name =~ /^type\0/) { next; }
1.292     albertel 2769: 	    $namechoice.='<choice computer="'.$name.'">'.$name.'</choice>';
                   2770: 	}
1.389     foxr     2771: 
                   2772: 
                   2773: 	my %code_values;
1.405     albertel 2774: 	my %codes_to_print;
1.411     albertel 2775: 	foreach my $key (@names) {
1.389     foxr     2776: 	    %code_values = &Apache::grades::get_codes($key, $cdom, $cnum);
1.405     albertel 2777: 	    foreach my $key (keys(%code_values)) {
                   2778: 		$codes_to_print{$key} = 1;
1.388     foxr     2779: 	    }
                   2780: 	}
1.389     foxr     2781: 
1.452     albertel 2782: 	my $code_selection;
1.405     albertel 2783: 	foreach my $code (sort {uc($a) cmp uc($b)} (keys(%codes_to_print))) {
1.389     foxr     2784: 	    my $choice  = $code;
                   2785: 	    if ($code =~ /^[A-Z]+$/) { # Alpha code
                   2786: 		$choice = &letters_to_num($code);
                   2787: 	    }
1.432     albertel 2788: 	    push(@{$helper->{DATA}{ALL_CODE_CHOICES}},[$code,$choice]);
1.388     foxr     2789: 	}
1.436     albertel 2790: 	if (%codes_to_print) {
                   2791: 	    $code_selection .='   
1.472     albertel 2792: 	    <message><b>Choose single CODE from list:</b></message>
1.448     albertel 2793: 		<message></td><td></message>
1.452     albertel 2794: 		<dropdown variable="CODE_SELECTED_FROM_LIST" multichoice="0" allowempty="0">
                   2795:                   <choice></choice>
1.448     albertel 2796:                   <exec>
                   2797:                      push(@{$state->{CHOICES}},@{$helper->{DATA}{ALL_CODE_CHOICES}});
                   2798:                   </exec>
1.452     albertel 2799: 		</dropdown>
1.468     foxr     2800: 	    <message></td></tr><tr><td></message>
1.436     albertel 2801:             '.$/;
1.448     albertel 2802: 
1.436     albertel 2803: 	}
1.432     albertel 2804: 
                   2805: 	
1.381     albertel 2806: 	open(FH,$Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab');
                   2807: 	my $codechoice='';
                   2808: 	foreach my $line (<FH>) {
                   2809: 	    my ($name,$description,$code_type,$code_length)=
                   2810: 		(split(/:/,$line))[0,1,2,4];
                   2811: 	    if ($code_length > 0 && 
                   2812: 		$code_type =~/^(letter|number|-1)/) {
                   2813: 		$codechoice.='<choice computer="'.$name.'">'.$description.'</choice>';
                   2814: 	    }
                   2815: 	}
                   2816: 	if ($codechoice eq '') {
                   2817: 	    $codechoice='<choice computer="default">Default</choice>';
                   2818: 	}
1.284     albertel 2819:         &Apache::lonxml::xmlparse($r, 'helper', <<CHOOSE_ANON1);
1.468     foxr     2820:   <state name="CHOOSE_ANON1" title="Specify CODEd Assignments">
1.424     foxr     2821:     <nextstate>SELECT_PROBLEMS</nextstate>
1.468     foxr     2822:     <message><h4>Fill out one of the forms below</h4></message>
                   2823:     <message><br /><hr /> <br /></message>
                   2824:     <message><h3>Generate new CODEd Assignments</h3></message>
                   2825:     <message><table><tr><td><b>Number of CODEd assignments to print:</b></td><td></message>
1.362     albertel 2826:     <string variable="NUMBER_TO_PRINT_TOTAL" maxlength="5" size="5">
                   2827:        <validator>
                   2828: 	if (((\$helper->{'VARS'}{'NUMBER_TO_PRINT_TOTAL'}+0) < 1) &&
1.382     foxr     2829: 	    !\$helper->{'VARS'}{'REUSE_OLD_CODES'}                &&
1.388     foxr     2830:             !\$helper->{'VARS'}{'SINGLE_CODE'}                    &&
                   2831: 	    !\$helper->{'VARS'}{'CODE_SELECTED_FROM_LIST'}) {
1.362     albertel 2832: 	    return "You need to specify the number of assignments to print";
                   2833: 	}
                   2834: 	return undef;
                   2835:        </validator>
                   2836:     </string>
                   2837:     <message></td></tr><tr><td></message>
1.501     albertel 2838:     <message><b>Names to save the CODEs under for later:</b></message>
1.412     albertel 2839:     <message></td><td></message>
                   2840:     <string variable="ANON_CODE_STORAGE_NAME" maxlength="50" size="20" />
                   2841:     <message></td></tr><tr><td></message>
                   2842:     <message><b>Bubble sheet type:</b></message>
                   2843:     <message></td><td></message>
                   2844:     <dropdown variable="CODE_OPTION" multichoice="0" allowempty="0">
                   2845:     $codechoice
                   2846:     </dropdown>
1.468     foxr     2847:     <message></td></tr><tr><td colspan="2"></td></tr><tr><td></message>
                   2848:     <message></td></tr><tr><td></table></message>
1.472     albertel 2849:     <message><br /><hr /><h3>Print a Specific CODE </h3><br /><table></message>
1.468     foxr     2850:     <message><tr><td><b>Enter a CODE to print:</b></td><td></message>
1.412     albertel 2851:     <string variable="SINGLE_CODE" size="10">
1.382     foxr     2852:         <validator>
                   2853: 	   if(!\$helper->{'VARS'}{'NUMBER_TO_PRINT_TOTAL'}           &&
1.388     foxr     2854: 	      !\$helper->{'VARS'}{'REUSE_OLD_CODES'}                 &&
                   2855: 	      !\$helper->{'VARS'}{'CODE_SELECTED_FROM_LIST'}) {
1.382     foxr     2856: 	      return &Apache::lonprintout::is_code_valid(\$helper->{'VARS'}{'SINGLE_CODE'},
                   2857: 						      \$helper->{'VARS'}{'CODE_OPTION'});
                   2858: 	   } else {
                   2859: 	       return undef;	# Other forces control us.
                   2860: 	   }
                   2861:         </validator>
                   2862:     </string>
1.472     albertel 2863:     <message></td></tr><tr><td></message>
1.432     albertel 2864:         $code_selection
1.468     foxr     2865:     <message></td></tr></table></message>
1.472     albertel 2866:     <message><hr /><h3>Reprint a Set of Saved CODEs</h3><table><tr><td></message>
1.468     foxr     2867:     <message><b>Select saved CODEs:</b></message>
1.381     albertel 2868:     <message></td><td></message>
1.292     albertel 2869:     <dropdown variable="REUSE_OLD_CODES">
                   2870:         $namechoice
                   2871:     </dropdown>
1.412     albertel 2872:     <message></td></tr></table></message>
1.284     albertel 2873:   </state>
1.424     foxr     2874:   $resource_selector
1.284     albertel 2875: CHOOSE_ANON1
1.254     sakharuk 2876: 
1.272     sakharuk 2877: 
1.254     sakharuk 2878: 	if ($helper->{VARS}->{'assignment'}) {
1.483     foxr     2879: 	    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 2880: 	    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 2881: 	}
1.284     albertel 2882: 	    
                   2883: 
                   2884: 	$resource_selector=<<RESOURCE_SELECTOR;
1.424     foxr     2885:     <state name="SELECT_RESOURCES" title="Select Resources">
1.507     albertel 2886:     $randomly_ordered_warning
                   2887: 
1.424     foxr     2888:     <nextstate>PRINT_FORMATTING</nextstate>
1.254     sakharuk 2889:     <message><br /><big><i><b>Select resources for the assignment</b></i></big><br /></message>
1.287     albertel 2890:     <resource variable="RESOURCES" multichoice="1" addstatus="1" 
                   2891:               closeallpages="1">
1.254     sakharuk 2892:       <filterfunc>return $isNotMap;</filterfunc>
                   2893:       <mapurl>$map</mapurl>
                   2894:       <valuefunc>return $symbFilter;</valuefunc>
1.465     albertel 2895:       $start_new_option
1.254     sakharuk 2896:       </resource>
1.424     foxr     2897:     </state>
                   2898:     <state name="PRINT_FORMATTING" title="Format of the print job">
                   2899:     <nextstate>NUMBER_PER_PDF</nextstate>
1.254     sakharuk 2900:     <message><br /><big><i><b>How should the results be printed?</b></i></big><br /></message>
                   2901:     <choices variable="EMPTY_PAGES">
                   2902:       <choice computer='0'>Start each student\'s assignment on a new page/column (add a pagefeed after each assignment)</choice>
                   2903:       <choice computer='1'>Add one empty page/column after each student\'s assignment</choice>
                   2904:       <choice computer='2'>Add two empty pages/column after each student\'s assignment</choice>
                   2905:       <choice computer='3'>Add three empty pages/column after each student\'s assignment</choice>
1.284     albertel 2906:     </choices>
1.424     foxr     2907:     <nextstate>PAGESIZE</nextstate>
1.429     foxr     2908:     <message><hr width='33%' /><b>How do you want assignments split into PDF files? </b></message>
                   2909:     <choices variable="SPLIT_PDFS">
                   2910:        <choice computer="all">All assignments in a single PDF file</choice>
                   2911:        <choice computer="sections">Each PDF contains exactly one section</choice>
                   2912:        <choice computer="oneper">Each PDF contains exactly one assignment</choice>
1.449     albertel 2913:        <choice computer="usenumber" relatedvalue="NUMBER_TO_PRINT">
                   2914:            Specify the number of assignments per PDF:</choice>
1.429     foxr     2915:     </choices>
1.424     foxr     2916:     </state>
1.284     albertel 2917: RESOURCE_SELECTOR
                   2918: 
                   2919: 	&Apache::lonxml::xmlparse($r, 'helper', <<CHOOSE_STUDENTS1);
                   2920:   <state name="CHOOSE_STUDENTS1" title="Select Students and Resources">
1.340     foxr     2921:     <choices variable='student_sort'>
                   2922:       <choice computer='0'>Sort by section then student</choice>
                   2923:       <choice computer='1'>Sort by students across sections.</choice>
                   2924:     </choices>
1.437     foxr     2925:     <message><br /><hr /><br /></message>
1.426     foxr     2926:     <student multichoice='1' variable="STUDENTS" nextstate="SELECT_RESOURCES" coursepersonnel="1" />
1.340     foxr     2927: 
1.424     foxr     2928:     </state>
1.284     albertel 2929:     $resource_selector
1.254     sakharuk 2930: CHOOSE_STUDENTS1
                   2931: 
1.284     albertel 2932: 	&Apache::lonxml::xmlparse($r, 'helper', <<CHOOSE_ANON2);
1.472     albertel 2933:   <state name="CHOOSE_ANON2" title="Select CODEd Assignments">
1.424     foxr     2934:     <nextstate>SELECT_RESOURCES</nextstate>
1.472     albertel 2935:     <message><h4>Fill out one of the forms below</h4></message>
                   2936:     <message><br /><hr /> <br /></message>
                   2937:     <message><h3>Generate new CODEd Assignments</h3></message>
                   2938:     <message><table><tr><td><b>Number of CODEd assignments to print:</b></td><td></message>
1.362     albertel 2939:     <string variable="NUMBER_TO_PRINT_TOTAL" maxlength="5" size="5">
                   2940:        <validator>
                   2941: 	if (((\$helper->{'VARS'}{'NUMBER_TO_PRINT_TOTAL'}+0) < 1) &&
1.386     foxr     2942: 	    !\$helper->{'VARS'}{'REUSE_OLD_CODES'}                &&
1.388     foxr     2943: 	    !\$helper->{'VARS'}{'SINGLE_CODE'}                   &&
                   2944: 	    !\$helper->{'VARS'}{'CODE_SELECTED_FROM_LIST'}) {
1.362     albertel 2945: 	    return "You need to specify the number of assignments to print";
                   2946: 	}
                   2947: 	return undef;
                   2948:        </validator>
                   2949:     </string>
                   2950:     <message></td></tr><tr><td></message>
1.501     albertel 2951:     <message><b>Names to save the CODEs under for later:</b></message>
1.412     albertel 2952:     <message></td><td></message>
                   2953:     <string variable="ANON_CODE_STORAGE_NAME" maxlength="50" size="20" />
                   2954:     <message></td></tr><tr><td></message>
                   2955:     <message><b>Bubble sheet type:</b></message>
                   2956:     <message></td><td></message>
                   2957:     <dropdown variable="CODE_OPTION" multichoice="0" allowempty="0">
                   2958:     $codechoice
                   2959:     </dropdown>
1.472     albertel 2960:     <message></td></tr><tr><td></table></message>
                   2961:     <message><br /><hr /><h3>Print a Specific CODE </h3><br /><table></message>
                   2962:     <message><tr><td><b>Enter a CODE to print:</b></td><td></message>
1.412     albertel 2963:     <string variable="SINGLE_CODE" size="10">
1.386     foxr     2964:         <validator>
                   2965: 	   if(!\$helper->{'VARS'}{'NUMBER_TO_PRINT_TOTAL'}           &&
1.388     foxr     2966: 	      !\$helper->{'VARS'}{'REUSE_OLD_CODES'}                 &&
                   2967: 	      !\$helper->{'VARS'}{'CODE_SELECTED_FROM_LIST'}) {
1.386     foxr     2968: 	      return &Apache::lonprintout::is_code_valid(\$helper->{'VARS'}{'SINGLE_CODE'},
                   2969: 						      \$helper->{'VARS'}{'CODE_OPTION'});
                   2970: 	   } else {
                   2971: 	       return undef;	# Other forces control us.
                   2972: 	   }
                   2973:         </validator>
                   2974:     </string>
1.472     albertel 2975:     <message></td></tr><tr><td></message>
1.432     albertel 2976:         $code_selection
1.472     albertel 2977:     <message></td></tr></table></message>
                   2978:     <message><hr /><h3>Reprint a Set of Saved CODEs</h3><table><tr><td></message>
                   2979:     <message><b>Select saved CODEs:</b></message>
1.381     albertel 2980:     <message></td><td></message>
1.294     albertel 2981:     <dropdown variable="REUSE_OLD_CODES">
                   2982:         $namechoice
                   2983:     </dropdown>
1.412     albertel 2984:     <message></td></tr></table></message>
1.424     foxr     2985:   </state>
1.284     albertel 2986:     $resource_selector
                   2987: CHOOSE_ANON2
1.481     albertel 2988:     }
                   2989: 
1.121     bowersj2 2990:     # FIXME: That RE should come from a library somewhere.
1.483     foxr     2991:     if (($perm{'pav'} 
1.482     albertel 2992: 	&& $subdir ne $Apache::lonnet::perlvar{'lonDocRoot'}.'/res/'
                   2993: 	&& (defined($helper->{'VARS'}->{'construction'})
                   2994: 	    ||
                   2995: 	    (&Apache::lonnet::allowed('bre',$subdir) eq 'F'
                   2996: 	     && 
                   2997: 	     $helper->{VARS}->{'postdata'}=~/\.(problem|exam|quiz|assess|survey|form|library|page|xml|html|htm|xhtml|xhtm)/)
1.483     foxr     2998: 	    )) 
                   2999: 	&& $helper->{VARS}->{'assignment'} eq ""
1.482     albertel 3000: 	) {
1.238     bowersj2 3001: 
1.482     albertel 3002: 	my $pretty_dir = &Apache::lonnet::hreflocation($subdir);
                   3003:         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 3004:         my $xmlfrag = <<CHOOSE_FROM_SUBDIR;
1.482     albertel 3005:   <state name="CHOOSE_FROM_SUBDIR" title="Select File(s) from <b><small>$pretty_dir</small></b> to print">
1.458     www      3006: 
1.138     bowersj2 3007:     <files variable="FILES" multichoice='1'>
1.144     bowersj2 3008:       <nextstate>PAGESIZE</nextstate>
1.138     bowersj2 3009:       <filechoice>return '$subdir';</filechoice>
1.139     bowersj2 3010: CHOOSE_FROM_SUBDIR
                   3011:         
1.238     bowersj2 3012:         # this is broken up because I really want interpolation above,
                   3013:         # and I really DON'T want it below
1.139     bowersj2 3014:         $xmlfrag .= <<'CHOOSE_FROM_SUBDIR';
1.225     bowersj2 3015:       <filefilter>return Apache::lonhelper::files::not_old_version($filename) &&
                   3016: 	  $filename =~ m/\.(problem|exam|quiz|assess|survey|form|library)$/;
1.131     bowersj2 3017:       </filefilter>
1.138     bowersj2 3018:       </files>
1.131     bowersj2 3019:     </state>
                   3020: CHOOSE_FROM_SUBDIR
1.139     bowersj2 3021:         &Apache::lonxml::xmlparse($r, 'helper', $xmlfrag);
1.131     bowersj2 3022:     }
1.238     bowersj2 3023: 
                   3024:     # Allow the user to select any sequence in the course, feed it to
                   3025:     # another resource selector for that sequence
1.483     foxr     3026:     if (!$helper->{VARS}->{'construction'} && !$is_published) {
1.509     albertel 3027: 	push @$printChoices, [&mtn("Selected <b>Resources</b> from <b>selected folder</b> in course"),
1.249     sakharuk 3028: 			      'select_sequences', 'CHOOSE_SEQUENCE'];
1.244     bowersj2 3029: 	my $escapedSequenceName = $helper->{VARS}->{'SEQUENCE'};
                   3030: 	#Escape apostrophes and backslashes for Perl
                   3031: 	$escapedSequenceName =~ s/\\/\\\\/g;
                   3032: 	$escapedSequenceName =~ s/'/\\'/g;
1.239     bowersj2 3033: 	&Apache::lonxml::xmlparse($r, 'helper', <<CHOOSE_FROM_ANY_SEQUENCE);
1.238     bowersj2 3034:   <state name="CHOOSE_SEQUENCE" title="Select Sequence To Print From">
                   3035:     <message>Select the sequence to print resources from:</message>
                   3036:     <resource variable="SEQUENCE">
                   3037:       <nextstate>CHOOSE_FROM_ANY_SEQUENCE</nextstate>
                   3038:       <filterfunc>return \$res->is_sequence;</filterfunc>
                   3039:       <valuefunc>return $urlValue;</valuefunc>
1.447     foxr     3040:       <choicefunc>return \$res->hasResource(\$res,sub { return !\$_[0]->is_sequence() },0,0);
1.391     foxr     3041: 	</choicefunc>
1.238     bowersj2 3042:       </resource>
                   3043:     </state>
                   3044:   <state name="CHOOSE_FROM_ANY_SEQUENCE" title="Select Resources To Print">
                   3045:     <message>(mark desired resources then click "next" button) <br /></message>
1.435     foxr     3046:     <resource variable="RESOURCES" multichoice="1" toponly='1' addstatus="1"
1.287     albertel 3047:               closeallpages="1">
1.238     bowersj2 3048:       <nextstate>PAGESIZE</nextstate>
1.466     albertel 3049:       <filterfunc>return $isNotMap</filterfunc>
1.244     bowersj2 3050:       <mapurl evaluate='1'>return '$escapedSequenceName';</mapurl>
1.238     bowersj2 3051:       <valuefunc>return $symbFilter;</valuefunc>
1.465     albertel 3052:       $start_new_option
1.238     bowersj2 3053:       </resource>
                   3054:     </state>
                   3055: CHOOSE_FROM_ANY_SEQUENCE
1.239     bowersj2 3056: }
1.481     albertel 3057: 
1.131     bowersj2 3058:     # Generate the first state, to select which resources get printed.
1.223     bowersj2 3059:     Apache::lonhelper::state->new("START", "Select Printing Options:");
1.131     bowersj2 3060:     $paramHash = Apache::lonhelper::getParamHash();
1.155     sakharuk 3061:     $paramHash->{MESSAGE_TEXT} = "";
1.131     bowersj2 3062:     Apache::lonhelper::message->new();
                   3063:     $paramHash = Apache::lonhelper::getParamHash();
                   3064:     $paramHash->{'variable'} = 'PRINT_TYPE';
                   3065:     $paramHash->{CHOICES} = $printChoices;
                   3066:     Apache::lonhelper::choices->new();
1.161     bowersj2 3067: 
1.223     bowersj2 3068:     my $startedTable = 0; # have we started an HTML table yet? (need
                   3069:                           # to close it later)
                   3070: 
1.397     albertel 3071:     if (($perm{'pav'} and &Apache::lonnet::allowed('vgr',$env{'request.course.id'})) or 
1.170     sakharuk 3072: 	($helper->{VARS}->{'construction'} eq '1')) {
1.497     www      3073: 	addMessage("<hr width='33%' /><table><tr><td align='right'>".
                   3074:                    '<label for="ANSWER_TYPE_forminput">'.
                   3075:                    &mt('Print').
                   3076:                    "</label>: </td><td>");
1.161     bowersj2 3077:         $paramHash = Apache::lonhelper::getParamHash();
1.162     sakharuk 3078: 	$paramHash->{'variable'} = 'ANSWER_TYPE';   
                   3079: 	$helper->declareVar('ANSWER_TYPE');         
1.161     bowersj2 3080:         $paramHash->{CHOICES} = [
1.242     sakharuk 3081:                                    ['Without Answers', 'yes'],
                   3082:                                    ['With Answers', 'no'],
1.368     albertel 3083:                                    ['Only Answers', 'only']
1.289     sakharuk 3084:                                 ];
1.210     sakharuk 3085:         Apache::lonhelper::dropdown->new();
1.223     bowersj2 3086: 	addMessage("</td></tr>");
                   3087: 	$startedTable = 1;
1.161     bowersj2 3088:     }
1.209     sakharuk 3089: 
1.397     albertel 3090:     if ($perm{'pav'}) {
1.223     bowersj2 3091: 	if (!$startedTable) {
1.497     www      3092: 	    addMessage("<hr width='33%' /><table><tr><td align='right'>".
                   3093:                        '<label for="LATEX_TYPE_forminput">'.
                   3094:                        &mt('LaTeX mode').
                   3095:                        "</label>: </td><td>");
1.223     bowersj2 3096: 	    $startedTable = 1;
                   3097: 	} else {
1.497     www      3098: 	    addMessage("<tr><td align='right'>".
                   3099:                        '<label for="LATEX_TYPE_forminput">'.
                   3100:                         &mt('LaTeX mode').
                   3101:                        "</label>: </td><td>");
1.223     bowersj2 3102: 	}
1.203     sakharuk 3103:         $paramHash = Apache::lonhelper::getParamHash();
                   3104: 	$paramHash->{'variable'} = 'LATEX_TYPE';   
                   3105: 	$helper->declareVar('LATEX_TYPE');  
                   3106: 	if ($helper->{VARS}->{'construction'} eq '1') {       
                   3107: 	    $paramHash->{CHOICES} = [
1.223     bowersj2 3108: 				     ['standard LaTeX mode', 'standard'], 
                   3109: 				     ['LaTeX batchmode', 'batchmode'], ];
1.203     sakharuk 3110: 	} else {
                   3111: 	    $paramHash->{CHOICES} = [
1.223     bowersj2 3112: 				     ['LaTeX batchmode', 'batchmode'],
                   3113: 				     ['standard LaTeX mode', 'standard'] ];
1.203     sakharuk 3114: 	}
1.210     sakharuk 3115:         Apache::lonhelper::dropdown->new();
1.218     sakharuk 3116:  
1.497     www      3117: 	addMessage("</td></tr><tr><td align='right'>".
1.506     albertel 3118:                    '<label for="TABLE_CONTENTS_forminput">'.
1.497     www      3119:                    &mt('Print Table of Contents').
                   3120:                    "</label>: </td><td>");
1.209     sakharuk 3121:         $paramHash = Apache::lonhelper::getParamHash();
                   3122: 	$paramHash->{'variable'} = 'TABLE_CONTENTS';   
                   3123: 	$helper->declareVar('TABLE_CONTENTS');         
                   3124:         $paramHash->{CHOICES} = [
1.223     bowersj2 3125:                                    ['No', 'no'],
                   3126:                                    ['Yes', 'yes'] ];
1.210     sakharuk 3127:         Apache::lonhelper::dropdown->new();
1.223     bowersj2 3128: 	addMessage("</td></tr>");
1.214     sakharuk 3129:         
1.220     sakharuk 3130: 	if (not $helper->{VARS}->{'construction'}) {
1.497     www      3131: 	    addMessage("<tr><td align='right'>".
                   3132:                        '<label for="TABLE_INDEX_forminput">'.
                   3133:                        &mt('Print Index').
                   3134:                        "</label>: </td><td>");
1.220     sakharuk 3135: 	    $paramHash = Apache::lonhelper::getParamHash();
                   3136: 	    $paramHash->{'variable'} = 'TABLE_INDEX';   
                   3137: 	    $helper->declareVar('TABLE_INDEX');         
                   3138: 	    $paramHash->{CHOICES} = [
1.223     bowersj2 3139: 				     ['No', 'no'],
                   3140: 				     ['Yes', 'yes'] ];
1.220     sakharuk 3141: 	    Apache::lonhelper::dropdown->new();
1.223     bowersj2 3142: 	    addMessage("</td></tr>");
1.497     www      3143: 	    addMessage("<tr><td align='right'>".
                   3144:                        '<label for="PRINT_DISCUSSIONS_forminput">'.
                   3145:                        &mt('Print Discussions').
                   3146:                        "</label>: </td><td>");
1.309     sakharuk 3147: 	    $paramHash = Apache::lonhelper::getParamHash();
                   3148: 	    $paramHash->{'variable'} = 'PRINT_DISCUSSIONS';   
                   3149: 	    $helper->declareVar('PRINT_DISCUSSIONS');         
                   3150: 	    $paramHash->{CHOICES} = [
                   3151: 				     ['No', 'no'],
                   3152: 				     ['Yes', 'yes'] ];
                   3153: 	    Apache::lonhelper::dropdown->new();
                   3154: 	    addMessage("</td></tr>");
1.372     foxr     3155: 
1.511     foxr     3156: 	    # Prompt for printing annotations too.
                   3157: 		
                   3158: 	    addMessage("<tr><td align='right'>".
                   3159: 		       '<label for="PRINT_ANNOTATIONS_forminput">'.
                   3160: 		       &mt('Print Annotations').
                   3161: 		       "</label>:</td><td>");
                   3162: 	    $paramHash = Apache::lonhelper::getParamHash();
                   3163: 	    $paramHash->{'variable'} = "PRINT_ANNOTATIONS";
                   3164: 	    $helper->declareVar("PRINT_ANNOTATIONS");
                   3165: 	    $paramHash->{CHOICES} = [
                   3166: 				     ['No', 'no'],
                   3167: 				     ['Yes', 'yes']];
                   3168: 	    Apache::lonhelper::dropdown->new();
                   3169: 	    addMessage("</td></tr>");
                   3170: 
1.397     albertel 3171: 	    addMessage("<tr><td align = 'right'>  </td><td>");
                   3172: 	    $paramHash = Apache::lonhelper::getParamHash();
                   3173: 	    $paramHash->{'multichoice'} = "true";
                   3174: 	    $paramHash->{'allowempty'}  = "true";
                   3175: 	    $paramHash->{'variable'}   = "showallfoils";
                   3176: 	    $paramHash->{'CHOICES'} = [ ["Show all foils", "1"] ];
                   3177: 	    Apache::lonhelper::choices->new();
                   3178: 	    addMessage("</td></tr>");
1.220     sakharuk 3179: 	}
1.219     sakharuk 3180: 
1.230     albertel 3181: 	if ($helper->{'VARS'}->{'construction'}) { 
1.505     albertel 3182: 	    my $stylevalue='$Apache::lonnet::env{"construct.style"}';
1.497     www      3183:             my $randseedtext=&mt("Use random seed");
                   3184:             my $stylefiletext=&mt("Use style file");
1.506     albertel 3185:             my $selectfiletext=&mt("Select style file");
1.497     www      3186: 
1.265     sakharuk 3187: 	    my $xmlfrag .= <<"RNDSEED";
1.497     www      3188: 	    <message><tr><td align='right'>
                   3189:             <label for="curseed_forminput">$randseedtext</label>:
                   3190:             </td><td></message>
1.230     albertel 3191: 	    <string variable="curseed" size="15" maxlength="15">
                   3192: 		<defaultvalue>
                   3193: 	            return $helper->{VARS}->{'curseed'};
                   3194: 	        </defaultvalue>
1.262     sakharuk 3195: 	    </string>
1.497     www      3196: 	     <message></td></tr><tr><td align="right">
1.503     albertel 3197:              <label for="style_file">$stylefiletext</label>:
1.497     www      3198:              </td><td></message>
1.504     albertel 3199:              <string variable="style_file" size="40">
                   3200: 		<defaultvalue>
1.505     albertel 3201: 	            return $stylevalue;
1.504     albertel 3202: 	        </defaultvalue>
1.506     albertel 3203:              </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     3204: 	     <choices allowempty="1" multichoice="true" variable="showallfoils">
1.506     albertel 3205:                 <choice computer="1">Show all foils</choice>
1.371     foxr     3206:              </choices>
1.378     albertel 3207: 	     <message></td></tr></message>
1.230     albertel 3208: RNDSEED
                   3209:             &Apache::lonxml::xmlparse($r, 'helper', $xmlfrag);
1.512     foxr     3210: 
                   3211: 
                   3212: 	    addMessage("<tr><td>Problem Type:</td><td>");
                   3213: 	    #
                   3214: 	    # Initial value from construction space:
                   3215: 	    #
                   3216: 	    if (!$helper->{VARS}->{'probstatus'} && $env{'form.problemtype'}) {
                   3217: 		$helper->{VARS}->{'probstatus'} = $env{'form.problemtype'};	# initial value
                   3218: 	    }
1.518   ! foxr     3219: 	    $xmlfrag = << "PROBTYPE";
        !          3220: 		<dropdown variable="probstatus" multichoice="0" allowempty="0">
        !          3221: 		   <defaultvalue>
        !          3222: 		      return "$helper->{VARS}->{'probstatus'}";
        !          3223:                    </defaultvalue>
        !          3224: 		   <choice computer="problem">Homework Problem</choice>
        !          3225: 		   <choice computer="exam">Exam Problem</choice>
        !          3226: 		   <choice computer="survey">Survey question</choice>
        !          3227: 		</dropdown>
        !          3228: PROBTYPE
        !          3229:             &Apache::lonxml::xmlparse($r, 'helper', $xmlfrag);
        !          3230: 	    
1.512     foxr     3231: 	    addMessage("</td></tr>"); 
                   3232: 
1.372     foxr     3233: 	} 
1.223     bowersj2 3234:     }
1.264     sakharuk 3235: 
                   3236: 
                   3237: 
1.218     sakharuk 3238: 
1.223     bowersj2 3239:     if ($startedTable) {
                   3240: 	addMessage("</table>");
1.215     sakharuk 3241:     }
1.161     bowersj2 3242: 
1.131     bowersj2 3243:     Apache::lonprintout::page_format_state->new("FORMAT");
                   3244: 
1.144     bowersj2 3245:     # Generate the PAGESIZE state which will offer the user the margin
                   3246:     # choices if they select one column
                   3247:     Apache::lonhelper::state->new("PAGESIZE", "Set Margins");
                   3248:     Apache::lonprintout::page_size_state->new('pagesize', 'FORMAT', 'FINAL');
                   3249: 
                   3250: 
1.131     bowersj2 3251:     $helper->process();
                   3252: 
1.416     foxr     3253: 
1.131     bowersj2 3254:     # MANUAL BAILOUT CONDITION:
                   3255:     # If we're in the "final" state, bailout and return to handler
                   3256:     if ($helper->{STATE} eq 'FINAL') {
                   3257:         return $helper;
                   3258:     }    
1.130     sakharuk 3259: 
1.131     bowersj2 3260:     $r->print($helper->display());
1.395     www      3261:     if ($helper->{STATE} eq 'START') {
                   3262: 	&recently_generated($r);
                   3263:     }
1.333     albertel 3264:     &Apache::lonhelper::unregisterHelperTags();
1.115     bowersj2 3265: 
                   3266:     return OK;
                   3267: }
                   3268: 
1.1       www      3269: 
                   3270: 1;
1.119     bowersj2 3271: 
                   3272: package Apache::lonprintout::page_format_state;
                   3273: 
                   3274: =pod
                   3275: 
1.131     bowersj2 3276: =head1 Helper element: page_format_state
                   3277: 
                   3278: See lonhelper.pm documentation for discussion of the helper framework.
1.119     bowersj2 3279: 
1.131     bowersj2 3280: Apache::lonprintout::page_format_state is an element that gives the 
                   3281: user an opportunity to select the page layout they wish to print 
                   3282: with: Number of columns, portrait/landscape, and paper size. If you 
                   3283: want to change the paper size choices, change the @paperSize array 
                   3284: contents in this package.
1.119     bowersj2 3285: 
1.131     bowersj2 3286: page_format_state is always directly invoked in lonprintout.pm, so there
                   3287: is no tag interface. You actually pass parameters to the constructor.
1.119     bowersj2 3288: 
                   3289: =over 4
                   3290: 
1.131     bowersj2 3291: =item * B<new>(varName): varName is where the print information will be stored in the format FIXME.
1.119     bowersj2 3292: 
                   3293: =back
                   3294: 
                   3295: =cut
                   3296: 
1.131     bowersj2 3297: use Apache::lonhelper;
1.119     bowersj2 3298: 
                   3299: no strict;
1.131     bowersj2 3300: @ISA = ("Apache::lonhelper::element");
1.119     bowersj2 3301: use strict;
1.266     sakharuk 3302: use Apache::lonlocal;
1.373     albertel 3303: use Apache::lonnet;
1.119     bowersj2 3304: 
                   3305: my $maxColumns = 2;
1.376     albertel 3306: # it'd be nice if these all worked
                   3307: #my @paperSize = ("letter [8 1/2x11 in]", "legal [8 1/2x14 in]", 
                   3308: #                 "tabloid (ledger) [11x17 in]", "executive [7 1/2x10 in]",
                   3309: #                 "a2 [420x594 mm]", "a3 [297x420 mm]", "a4 [210x297 mm]", 
                   3310: #                 "a5 [148x210 mm]", "a6 [105x148 mm]" );
1.326     sakharuk 3311: my @paperSize = ("letter [8 1/2x11 in]", "legal [8 1/2x14 in]", 
1.376     albertel 3312: 		 "a4 [210x297 mm]");
1.119     bowersj2 3313: 
                   3314: # Tentative format: Orientation (L = Landscape, P = portrait) | Colnum |
                   3315: #                   Paper type
                   3316: 
                   3317: sub new { 
1.131     bowersj2 3318:     my $self = Apache::lonhelper::element->new();
1.119     bowersj2 3319: 
1.135     bowersj2 3320:     shift;
                   3321: 
1.131     bowersj2 3322:     $self->{'variable'} = shift;
1.134     bowersj2 3323:     my $helper = Apache::lonhelper::getHelper();
1.135     bowersj2 3324:     $helper->declareVar($self->{'variable'});
1.131     bowersj2 3325:     bless($self);
1.119     bowersj2 3326:     return $self;
                   3327: }
                   3328: 
                   3329: sub render {
                   3330:     my $self = shift;
1.131     bowersj2 3331:     my $helper = Apache::lonhelper::getHelper();
1.119     bowersj2 3332:     my $result = '';
1.131     bowersj2 3333:     my $var = $self->{'variable'};
1.266     sakharuk 3334:     my $PageLayout=&mt('Page layout');
                   3335:     my $NumberOfColumns=&mt('Number of columns');
                   3336:     my $PaperType=&mt('Paper type');
1.506     albertel 3337:     my $landscape=&mt('Landscape');
                   3338:     my $portrait=&mt('Portrait');
1.119     bowersj2 3339:     $result .= <<STATEHTML;
                   3340: 
1.223     bowersj2 3341: <hr width="33%" />
1.119     bowersj2 3342: <table cellpadding="3">
                   3343:   <tr>
1.266     sakharuk 3344:     <td align="center"><b>$PageLayout</b></td>
                   3345:     <td align="center"><b>$NumberOfColumns</b></td>
                   3346:     <td align="center"><b>$PaperType</b></td>
1.119     bowersj2 3347:   </tr>
                   3348:   <tr>
                   3349:     <td>
1.506     albertel 3350:       <label><input type="radio" name="${var}.layout" value="L" /> $landscape </label><br />
                   3351:       <label><input type="radio" name="${var}.layout" value="P" checked='1'  /> $portrait </label>
1.119     bowersj2 3352:     </td>
1.155     sakharuk 3353:     <td align="center">
1.119     bowersj2 3354:       <select name="${var}.cols">
                   3355: STATEHTML
                   3356: 
                   3357:     my $i;
                   3358:     for ($i = 1; $i <= $maxColumns; $i++) {
1.144     bowersj2 3359:         if ($i == 2) {
1.119     bowersj2 3360:             $result .= "<option value='$i' selected>$i</option>\n";
                   3361:         } else {
                   3362:             $result .= "<option value='$i'>$i</option>\n";
                   3363:         }
                   3364:     }
                   3365: 
                   3366:     $result .= "</select></td><td>\n";
                   3367:     $result .= "<select name='${var}.paper'>\n";
                   3368: 
1.373     albertel 3369:     my %parmhash=&Apache::lonnet::coursedescription($env{'request.course.id'});
1.398     albertel 3370:     my $DefaultPaperSize=lc($parmhash{'default_paper_size'});
                   3371:     $DefaultPaperSize=~s/\s//g;
1.304     sakharuk 3372:     if ($DefaultPaperSize eq '') {$DefaultPaperSize='letter';}
1.119     bowersj2 3373:     $i = 0;
                   3374:     foreach (@paperSize) {
1.326     sakharuk 3375: 	$_=~/(\w+)/;
                   3376: 	my $papersize=$1;
1.304     sakharuk 3377:         if ($paperSize[$i]=~/$DefaultPaperSize/) {
1.326     sakharuk 3378:             $result .= "<option selected value='$papersize'>" . $paperSize[$i] . "</option>\n";
1.119     bowersj2 3379:         } else {
1.326     sakharuk 3380:             $result .= "<option value='$papersize'>" . $paperSize[$i] . "</option>\n";
1.119     bowersj2 3381:         }
                   3382:         $i++;
                   3383:     }
                   3384:     $result .= "</select></td></tr></table>";
                   3385:     return $result;
1.135     bowersj2 3386: }
                   3387: 
                   3388: sub postprocess {
                   3389:     my $self = shift;
                   3390: 
                   3391:     my $var = $self->{'variable'};
1.136     bowersj2 3392:     my $helper = Apache::lonhelper->getHelper();
1.135     bowersj2 3393:     $helper->{VARS}->{$var} = 
1.373     albertel 3394:         $env{"form.$var.layout"} . '|' . $env{"form.$var.cols"} . '|' .
                   3395:         $env{"form.$var.paper"};
1.135     bowersj2 3396:     return 1;
1.119     bowersj2 3397: }
                   3398: 
                   3399: 1;
1.144     bowersj2 3400: 
                   3401: package Apache::lonprintout::page_size_state;
                   3402: 
                   3403: =pod
                   3404: 
                   3405: =head1 Helper element: page_size_state
                   3406: 
                   3407: See lonhelper.pm documentation for discussion of the helper framework.
                   3408: 
                   3409: Apache::lonprintout::page_size_state is an element that gives the 
                   3410: user the opportunity to further refine the page settings if they
                   3411: select a single-column page.
                   3412: 
                   3413: page_size_state is always directly invoked in lonprintout.pm, so there
                   3414: is no tag interface. You actually pass parameters to the constructor.
                   3415: 
                   3416: =over 4
                   3417: 
                   3418: =item * B<new>(varName): varName is where the print information will be stored in the format FIXME.
                   3419: 
                   3420: =back
                   3421: 
                   3422: =cut
                   3423: 
                   3424: use Apache::lonhelper;
1.373     albertel 3425: use Apache::lonnet;
1.144     bowersj2 3426: no strict;
                   3427: @ISA = ("Apache::lonhelper::element");
                   3428: use strict;
                   3429: 
                   3430: 
                   3431: 
                   3432: sub new { 
                   3433:     my $self = Apache::lonhelper::element->new();
                   3434: 
                   3435:     shift; # disturbs me (probably prevents subclassing) but works (drops
                   3436:            # package descriptor)... - Jeremy
                   3437: 
                   3438:     $self->{'variable'} = shift;
                   3439:     my $helper = Apache::lonhelper::getHelper();
                   3440:     $helper->declareVar($self->{'variable'});
                   3441: 
                   3442:     # The variable name of the format element, so we can look into 
                   3443:     # $helper->{VARS} to figure out whether the columns are one or two
                   3444:     $self->{'formatvar'} = shift;
                   3445: 
1.463     foxr     3446: 
1.144     bowersj2 3447:     $self->{NEXTSTATE} = shift;
                   3448:     bless($self);
1.467     foxr     3449: 
1.144     bowersj2 3450:     return $self;
                   3451: }
                   3452: 
                   3453: sub render {
                   3454:     my $self = shift;
                   3455:     my $helper = Apache::lonhelper::getHelper();
                   3456:     my $result = '';
                   3457:     my $var = $self->{'variable'};
                   3458: 
1.467     foxr     3459: 
                   3460: 
1.144     bowersj2 3461:     if (defined $self->{ERROR_MSG}) {
1.464     albertel 3462:         $result .= '<br /><span class="LC_error">' . $self->{ERROR_MSG} . '</span><br />';
1.144     bowersj2 3463:     }
                   3464: 
1.438     foxr     3465:     my $format = $helper->{VARS}->{$self->{'formatvar'}};
1.463     foxr     3466: 
                   3467:     # Use format to get sensible defaults for the margins:
                   3468: 
                   3469: 
                   3470:     my ($laystyle, $cols, $papersize) = split(/\|/, $format);
                   3471:     ($papersize)                      = split(/ /, $papersize);
                   3472: 
                   3473: 
                   3474:     if ($laystyle eq 'L') {
                   3475: 	$laystyle = 'album';
                   3476:     } else {
                   3477: 	$laystyle = 'book';
                   3478:     }
                   3479: 
                   3480: 
1.464     albertel 3481:     my %size;
                   3482:     ($size{'width_and_units'},
                   3483:      $size{'height_and_units'},
                   3484:      $size{'margin_and_units'})=
                   3485: 	 &Apache::lonprintout::page_format($papersize, $laystyle, $cols);
1.463     foxr     3486:     
1.464     albertel 3487:     foreach my $dimension ('width','height','margin') {
                   3488: 	($size{$dimension},$size{$dimension.'_unit'}) =
                   3489: 	    split(/ +/, $size{$dimension.'_and_units'},2);
                   3490:        	
                   3491: 	foreach my $unit ('cm','in') {
                   3492: 	    $size{$dimension.'_options'} .= '<option ';
                   3493: 	    if ($size{$dimension.'_unit'} eq $unit) {
                   3494: 		$size{$dimension.'_options'} .= 'selected="selected" ';
                   3495: 	    }
                   3496: 	    $size{$dimension.'_options'} .= '>'.$unit.'</option>';
                   3497: 	}
1.438     foxr     3498:     }
                   3499: 
1.470     foxr     3500:     # Adjust margin for LaTeX margin: .. requires units == cm or in.
                   3501: 
                   3502:     if ($size{'margin_unit'} eq 'in') {
                   3503: 	$size{'margin'} += 1;
                   3504:     }  else {
                   3505: 	$size{'margin'} += 2.54;
                   3506:     }
1.506     albertel 3507:     my %text = ('format' => 'How should each column be formatted?',
                   3508: 		'width'  => 'Width:',
                   3509: 		'height' => 'Height:',
                   3510: 		'margin' => 'Left Margin:',);
                   3511:     %text = &Apache::lonlocal::texthash(%text);
                   3512: 
1.144     bowersj2 3513:     $result .= <<ELEMENTHTML;
                   3514: 
1.506     albertel 3515: <p>$text{'format'}</p>
1.144     bowersj2 3516: 
                   3517: <table cellpadding='3'>
                   3518:   <tr>
1.506     albertel 3519:     <td align='right'><b>$text{'width'}</b></td>
1.464     albertel 3520:     <td align='left'><input type='text' name='$var.width' value="$size{'width'}" size='4' /></td>
1.144     bowersj2 3521:     <td align='left'>
                   3522:       <select name='$var.widthunit'>
1.464     albertel 3523:       $size{'width_options'}
1.144     bowersj2 3524:       </select>
                   3525:     </td>
                   3526:   </tr>
                   3527:   <tr>
1.506     albertel 3528:     <td align='right'><b>$text{'height'}</b></td>
1.464     albertel 3529:     <td align='left'><input type='text' name="$var.height" value="$size{'height'}" size='4' /></td>
1.144     bowersj2 3530:     <td align='left'>
                   3531:       <select name='$var.heightunit'>
1.464     albertel 3532:       $size{'height_options'}
1.144     bowersj2 3533:       </select>
                   3534:     </td>
                   3535:   </tr>
                   3536:   <tr>
1.506     albertel 3537:     <td align='right'><b>$text{'margin'}</b></td>
1.464     albertel 3538:     <td align='left'><input type='text' name='$var.lmargin' value="$size{'margin'}" size='4' /></td>
1.144     bowersj2 3539:     <td align='left'>
1.186     bowersj2 3540:       <select name='$var.lmarginunit'>
1.464     albertel 3541:       $size{'margin_options'}
1.144     bowersj2 3542:       </select>
                   3543:     </td>
                   3544:   </tr>
                   3545: </table>
                   3546: 
1.464     albertel 3547: <!--<p>Hint: Some instructors like to leave scratch space for the student by
                   3548: making the width much smaller than the width of the page.</p>-->
1.144     bowersj2 3549: 
                   3550: ELEMENTHTML
                   3551: 
                   3552:     return $result;
                   3553: }
                   3554: 
1.470     foxr     3555: 
1.144     bowersj2 3556: sub preprocess {
                   3557:     my $self = shift;
                   3558:     my $helper = Apache::lonhelper::getHelper();
                   3559: 
                   3560:     my $format = $helper->{VARS}->{$self->{'formatvar'}};
1.467     foxr     3561: 
                   3562:     #  If the user does not have 'pav' privilege, set default widths and
                   3563:     #  on to the next state right away.
                   3564:     #
                   3565:     if (!$perm{'pav'}) {
                   3566: 	my $var = $self->{'variable'};
                   3567: 	my $format = $helper->{VARS}->{$self->{'formatvar'}};
                   3568: 	
                   3569: 	my ($laystyle, $cols, $papersize) = split(/\|/, $format);
                   3570: 	($papersize)                      = split(/ /, $papersize);
                   3571: 	
                   3572: 	
                   3573: 	if ($laystyle eq 'L') {
                   3574: 	    $laystyle = 'album';
                   3575: 	} else {
                   3576: 	    $laystyle = 'book';
                   3577: 	}
                   3578: 	#  Figure out some good defaults for the print out and set them:
                   3579: 	
                   3580: 	my %size;
                   3581: 	($size{'width'},
                   3582: 	 $size{'height'},
                   3583: 	 $size{'lmargin'})=
                   3584: 	     &Apache::lonprintout::page_format($papersize, $laystyle, $cols);
                   3585: 	
                   3586: 	foreach my $dim ('width', 'height', 'lmargin') {
                   3587: 	    my ($value, $units) = split(/ /, $size{$dim});
1.470     foxr     3588: 	    	    
1.467     foxr     3589: 	    $helper->{VARS}->{"$var.".$dim}      = $value;
                   3590: 	    $helper->{VARS}->{"$var.".$dim.'unit'} = $units;
                   3591: 	    
                   3592: 	}
                   3593: 	
                   3594: 
                   3595: 	# Transition to the next state
                   3596: 
                   3597: 	$helper->changeState($self->{NEXTSTATE});
                   3598:     }
1.144     bowersj2 3599:    
                   3600:     return 1;
                   3601: }
                   3602: 
                   3603: sub postprocess {
                   3604:     my $self = shift;
                   3605: 
                   3606:     my $var = $self->{'variable'};
                   3607:     my $helper = Apache::lonhelper->getHelper();
1.373     albertel 3608:     my $width = $helper->{VARS}->{$var .'.width'} = $env{"form.${var}.width"}; 
                   3609:     my $height = $helper->{VARS}->{$var .'.height'} = $env{"form.${var}.height"}; 
                   3610:     my $lmargin = $helper->{VARS}->{$var .'.lmargin'} = $env{"form.${var}.lmargin"}; 
                   3611:     $helper->{VARS}->{$var .'.widthunit'} = $env{"form.${var}.widthunit"}; 
                   3612:     $helper->{VARS}->{$var .'.heightunit'} = $env{"form.${var}.heightunit"}; 
                   3613:     $helper->{VARS}->{$var .'.lmarginunit'} = $env{"form.${var}.lmarginunit"}; 
1.144     bowersj2 3614: 
                   3615:     my $error = '';
                   3616: 
                   3617:     # /^-?[0-9]+(\.[0-9]*)?$/ -> optional minus, at least on digit, followed 
                   3618:     # by an optional period, followed by digits, ending the string
                   3619: 
1.464     albertel 3620:     if ($width !~  /^-?[0-9]*(\.[0-9]*)?$/) {
1.144     bowersj2 3621:         $error .= "Invalid width; please type only a number.<br />\n";
                   3622:     }
1.464     albertel 3623:     if ($height !~  /^-?[0-9]*(\.[0-9]*)?$/) {
1.144     bowersj2 3624:         $error .= "Invalid height; please type only a number.<br />\n";
                   3625:     }
1.464     albertel 3626:     if ($lmargin !~  /^-?[0-9]*(\.[0-9]*)?$/) {
1.144     bowersj2 3627:         $error .= "Invalid left margin; please type only a number.<br />\n";
1.470     foxr     3628:     } else {
                   3629: 	# Adjust for LaTeX 1.0 inch margin:
                   3630: 
                   3631: 	if ($env{"form.${var}.lmarginunit"} eq "in") {
                   3632: 	    $helper->{VARS}->{$var.'.lmargin'} = $lmargin - 1;
                   3633: 	} else {
                   3634: 	    $helper->{VARS}->{$var.'.lmargin'} = $lmargin - 2.54;
                   3635: 	}
1.144     bowersj2 3636:     }
                   3637: 
                   3638:     if (!$error) {
                   3639:         Apache::lonhelper::getHelper()->changeState($self->{NEXTSTATE});
                   3640:         return 1;
                   3641:     } else {
                   3642:         $self->{ERROR_MSG} = $error;
                   3643:         return 0;
                   3644:     }
                   3645: }
                   3646: 
                   3647: 
1.119     bowersj2 3648: 
1.1       www      3649: __END__
1.6       sakharuk 3650: 

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